linux/drivers/scsi/bfa/bfad_attr.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
   3 * All rights reserved
   4 * www.brocade.com
   5 *
   6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
   7 *
   8 * This program is free software; you can redistribute it and/or modify it
   9 * under the terms of the GNU General Public License (GPL) Version 2 as
  10 * published by the Free Software Foundation
  11 *
  12 * This program is distributed in the hope that it will be useful, but
  13 * WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * General Public License for more details.
  16 */
  17
  18/**
  19 *  bfa_attr.c Linux driver configuration interface module.
  20 */
  21
  22#include "bfad_drv.h"
  23#include "bfad_im.h"
  24#include "bfad_trcmod.h"
  25#include "bfad_attr.h"
  26
  27/**
  28 *  FC_transport_template FC transport template
  29 */
  30
  31/**
  32 * FC transport template entry, get SCSI target port ID.
  33 */
  34void
  35bfad_im_get_starget_port_id(struct scsi_target *starget)
  36{
  37        struct Scsi_Host *shost;
  38        struct bfad_im_port_s *im_port;
  39        struct bfad_s         *bfad;
  40        struct bfad_itnim_s   *itnim = NULL;
  41        u32        fc_id = -1;
  42        unsigned long   flags;
  43
  44        shost = bfad_os_starget_to_shost(starget);
  45        im_port = (struct bfad_im_port_s *) shost->hostdata[0];
  46        bfad = im_port->bfad;
  47        spin_lock_irqsave(&bfad->bfad_lock, flags);
  48
  49        itnim = bfad_os_get_itnim(im_port, starget->id);
  50        if (itnim)
  51                fc_id = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim);
  52
  53        fc_starget_port_id(starget) = fc_id;
  54        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
  55}
  56
  57/**
  58 * FC transport template entry, get SCSI target nwwn.
  59 */
  60void
  61bfad_im_get_starget_node_name(struct scsi_target *starget)
  62{
  63        struct Scsi_Host *shost;
  64        struct bfad_im_port_s *im_port;
  65        struct bfad_s         *bfad;
  66        struct bfad_itnim_s   *itnim = NULL;
  67        u64             node_name = 0;
  68        unsigned long   flags;
  69
  70        shost = bfad_os_starget_to_shost(starget);
  71        im_port = (struct bfad_im_port_s *) shost->hostdata[0];
  72        bfad = im_port->bfad;
  73        spin_lock_irqsave(&bfad->bfad_lock, flags);
  74
  75        itnim = bfad_os_get_itnim(im_port, starget->id);
  76        if (itnim)
  77                node_name = bfa_fcs_itnim_get_nwwn(&itnim->fcs_itnim);
  78
  79        fc_starget_node_name(starget) = bfa_os_htonll(node_name);
  80        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
  81}
  82
  83/**
  84 * FC transport template entry, get SCSI target pwwn.
  85 */
  86void
  87bfad_im_get_starget_port_name(struct scsi_target *starget)
  88{
  89        struct Scsi_Host *shost;
  90        struct bfad_im_port_s *im_port;
  91        struct bfad_s         *bfad;
  92        struct bfad_itnim_s   *itnim = NULL;
  93        u64             port_name = 0;
  94        unsigned long   flags;
  95
  96        shost = bfad_os_starget_to_shost(starget);
  97        im_port = (struct bfad_im_port_s *) shost->hostdata[0];
  98        bfad = im_port->bfad;
  99        spin_lock_irqsave(&bfad->bfad_lock, flags);
 100
 101        itnim = bfad_os_get_itnim(im_port, starget->id);
 102        if (itnim)
 103                port_name = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim);
 104
 105        fc_starget_port_name(starget) = bfa_os_htonll(port_name);
 106        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 107}
 108
 109/**
 110 * FC transport template entry, get SCSI host port ID.
 111 */
 112void
 113bfad_im_get_host_port_id(struct Scsi_Host *shost)
 114{
 115        struct bfad_im_port_s *im_port =
 116                        (struct bfad_im_port_s *) shost->hostdata[0];
 117        struct bfad_port_s    *port = im_port->port;
 118
 119        fc_host_port_id(shost) =
 120                        bfa_os_hton3b(bfa_fcs_port_get_fcid(port->fcs_port));
 121}
 122
 123
 124
 125
 126
 127struct Scsi_Host *
 128bfad_os_starget_to_shost(struct scsi_target *starget)
 129{
 130        return dev_to_shost(starget->dev.parent);
 131}
 132
 133/**
 134 * FC transport template entry, get SCSI host port type.
 135 */
 136static void
 137bfad_im_get_host_port_type(struct Scsi_Host *shost)
 138{
 139        struct bfad_im_port_s *im_port =
 140                        (struct bfad_im_port_s *) shost->hostdata[0];
 141        struct bfad_s         *bfad = im_port->bfad;
 142        struct bfa_pport_attr_s attr;
 143
 144        bfa_pport_get_attr(&bfad->bfa, &attr);
 145
 146        switch (attr.port_type) {
 147        case BFA_PPORT_TYPE_NPORT:
 148                fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
 149                break;
 150        case BFA_PPORT_TYPE_NLPORT:
 151                fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
 152                break;
 153        case BFA_PPORT_TYPE_P2P:
 154                fc_host_port_type(shost) = FC_PORTTYPE_PTP;
 155                break;
 156        case BFA_PPORT_TYPE_LPORT:
 157                fc_host_port_type(shost) = FC_PORTTYPE_LPORT;
 158                break;
 159        default:
 160                fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
 161                break;
 162        }
 163}
 164
 165/**
 166 * FC transport template entry, get SCSI host port state.
 167 */
 168static void
 169bfad_im_get_host_port_state(struct Scsi_Host *shost)
 170{
 171        struct bfad_im_port_s *im_port =
 172                        (struct bfad_im_port_s *) shost->hostdata[0];
 173        struct bfad_s         *bfad = im_port->bfad;
 174        struct bfa_pport_attr_s attr;
 175
 176        bfa_pport_get_attr(&bfad->bfa, &attr);
 177
 178        switch (attr.port_state) {
 179        case BFA_PPORT_ST_LINKDOWN:
 180                fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
 181                break;
 182        case BFA_PPORT_ST_LINKUP:
 183                fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
 184                break;
 185        case BFA_PPORT_ST_UNINIT:
 186        case BFA_PPORT_ST_ENABLING_QWAIT:
 187        case BFA_PPORT_ST_ENABLING:
 188        case BFA_PPORT_ST_DISABLING_QWAIT:
 189        case BFA_PPORT_ST_DISABLING:
 190        case BFA_PPORT_ST_DISABLED:
 191        case BFA_PPORT_ST_STOPPED:
 192        case BFA_PPORT_ST_IOCDOWN:
 193        default:
 194                fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
 195                break;
 196        }
 197}
 198
 199/**
 200 * FC transport template entry, get SCSI host active fc4s.
 201 */
 202static void
 203bfad_im_get_host_active_fc4s(struct Scsi_Host *shost)
 204{
 205        struct bfad_im_port_s *im_port =
 206                        (struct bfad_im_port_s *) shost->hostdata[0];
 207        struct bfad_port_s    *port = im_port->port;
 208
 209        memset(fc_host_active_fc4s(shost), 0,
 210               sizeof(fc_host_active_fc4s(shost)));
 211
 212        if (port->supported_fc4s &
 213                (BFA_PORT_ROLE_FCP_IM | BFA_PORT_ROLE_FCP_TM))
 214                fc_host_active_fc4s(shost)[2] = 1;
 215
 216        if (port->supported_fc4s & BFA_PORT_ROLE_FCP_IPFC)
 217                fc_host_active_fc4s(shost)[3] = 0x20;
 218
 219        fc_host_active_fc4s(shost)[7] = 1;
 220}
 221
 222/**
 223 * FC transport template entry, get SCSI host link speed.
 224 */
 225static void
 226bfad_im_get_host_speed(struct Scsi_Host *shost)
 227{
 228        struct bfad_im_port_s *im_port =
 229                        (struct bfad_im_port_s *) shost->hostdata[0];
 230        struct bfad_s         *bfad = im_port->bfad;
 231        struct bfa_pport_attr_s attr;
 232
 233        bfa_pport_get_attr(&bfad->bfa, &attr);
 234        switch (attr.speed) {
 235        case BFA_PPORT_SPEED_8GBPS:
 236                fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
 237                break;
 238        case BFA_PPORT_SPEED_4GBPS:
 239                fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
 240                break;
 241        case BFA_PPORT_SPEED_2GBPS:
 242                fc_host_speed(shost) = FC_PORTSPEED_2GBIT;
 243                break;
 244        case BFA_PPORT_SPEED_1GBPS:
 245                fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
 246                break;
 247        default:
 248                fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
 249                break;
 250        }
 251}
 252
 253/**
 254 * FC transport template entry, get SCSI host port type.
 255 */
 256static void
 257bfad_im_get_host_fabric_name(struct Scsi_Host *shost)
 258{
 259        struct bfad_im_port_s *im_port =
 260                        (struct bfad_im_port_s *) shost->hostdata[0];
 261        struct bfad_port_s    *port = im_port->port;
 262        wwn_t           fabric_nwwn = 0;
 263
 264        fabric_nwwn = bfa_fcs_port_get_fabric_name(port->fcs_port);
 265
 266        fc_host_fabric_name(shost) = bfa_os_htonll(fabric_nwwn);
 267
 268}
 269
 270/**
 271 * FC transport template entry, get BFAD statistics.
 272 */
 273static struct fc_host_statistics *
 274bfad_im_get_stats(struct Scsi_Host *shost)
 275{
 276        struct bfad_im_port_s *im_port =
 277                        (struct bfad_im_port_s *) shost->hostdata[0];
 278        struct bfad_s         *bfad = im_port->bfad;
 279        struct bfad_hal_comp fcomp;
 280        struct fc_host_statistics *hstats;
 281        bfa_status_t    rc;
 282        unsigned long   flags;
 283
 284        hstats = &bfad->link_stats;
 285        init_completion(&fcomp.comp);
 286        spin_lock_irqsave(&bfad->bfad_lock, flags);
 287        memset(hstats, 0, sizeof(struct fc_host_statistics));
 288        rc = bfa_pport_get_stats(&bfad->bfa,
 289                                     (union bfa_pport_stats_u *) hstats,
 290                                     bfad_hcb_comp, &fcomp);
 291        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 292        if (rc != BFA_STATUS_OK)
 293                return NULL;
 294
 295        wait_for_completion(&fcomp.comp);
 296
 297        return hstats;
 298}
 299
 300/**
 301 * FC transport template entry, reset BFAD statistics.
 302 */
 303static void
 304bfad_im_reset_stats(struct Scsi_Host *shost)
 305{
 306        struct bfad_im_port_s *im_port =
 307                        (struct bfad_im_port_s *) shost->hostdata[0];
 308        struct bfad_s         *bfad = im_port->bfad;
 309        struct bfad_hal_comp fcomp;
 310        unsigned long   flags;
 311        bfa_status_t    rc;
 312
 313        init_completion(&fcomp.comp);
 314        spin_lock_irqsave(&bfad->bfad_lock, flags);
 315        rc = bfa_pport_clear_stats(&bfad->bfa, bfad_hcb_comp, &fcomp);
 316        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 317
 318        if (rc != BFA_STATUS_OK)
 319                return;
 320
 321        wait_for_completion(&fcomp.comp);
 322
 323        return;
 324}
 325
 326/**
 327 * FC transport template entry, get rport loss timeout.
 328 */
 329static void
 330bfad_im_get_rport_loss_tmo(struct fc_rport *rport)
 331{
 332        struct bfad_itnim_data_s *itnim_data = rport->dd_data;
 333        struct bfad_itnim_s   *itnim = itnim_data->itnim;
 334        struct bfad_s         *bfad = itnim->im->bfad;
 335        unsigned long   flags;
 336
 337        spin_lock_irqsave(&bfad->bfad_lock, flags);
 338        rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa);
 339        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 340}
 341
 342/**
 343 * FC transport template entry, set rport loss timeout.
 344 */
 345static void
 346bfad_im_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)
 347{
 348        struct bfad_itnim_data_s *itnim_data = rport->dd_data;
 349        struct bfad_itnim_s   *itnim = itnim_data->itnim;
 350        struct bfad_s         *bfad = itnim->im->bfad;
 351        unsigned long   flags;
 352
 353        if (timeout > 0) {
 354                spin_lock_irqsave(&bfad->bfad_lock, flags);
 355                bfa_fcpim_path_tov_set(&bfad->bfa, timeout);
 356                rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa);
 357                spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 358        }
 359
 360}
 361
 362struct fc_function_template bfad_im_fc_function_template = {
 363
 364        /* Target dynamic attributes */
 365        .get_starget_port_id = bfad_im_get_starget_port_id,
 366        .show_starget_port_id = 1,
 367        .get_starget_node_name = bfad_im_get_starget_node_name,
 368        .show_starget_node_name = 1,
 369        .get_starget_port_name = bfad_im_get_starget_port_name,
 370        .show_starget_port_name = 1,
 371
 372        /* Host dynamic attribute */
 373        .get_host_port_id = bfad_im_get_host_port_id,
 374        .show_host_port_id = 1,
 375
 376        /* Host fixed attributes */
 377        .show_host_node_name = 1,
 378        .show_host_port_name = 1,
 379        .show_host_supported_classes = 1,
 380        .show_host_supported_fc4s = 1,
 381        .show_host_supported_speeds = 1,
 382        .show_host_maxframe_size = 1,
 383
 384        /* More host dynamic attributes */
 385        .show_host_port_type = 1,
 386        .get_host_port_type = bfad_im_get_host_port_type,
 387        .show_host_port_state = 1,
 388        .get_host_port_state = bfad_im_get_host_port_state,
 389        .show_host_active_fc4s = 1,
 390        .get_host_active_fc4s = bfad_im_get_host_active_fc4s,
 391        .show_host_speed = 1,
 392        .get_host_speed = bfad_im_get_host_speed,
 393        .show_host_fabric_name = 1,
 394        .get_host_fabric_name = bfad_im_get_host_fabric_name,
 395
 396        .show_host_symbolic_name = 1,
 397
 398        /* Statistics */
 399        .get_fc_host_stats = bfad_im_get_stats,
 400        .reset_fc_host_stats = bfad_im_reset_stats,
 401
 402        /* Allocation length for host specific data */
 403        .dd_fcrport_size = sizeof(struct bfad_itnim_data_s *),
 404
 405        /* Remote port fixed attributes */
 406        .show_rport_maxframe_size = 1,
 407        .show_rport_supported_classes = 1,
 408        .show_rport_dev_loss_tmo = 1,
 409        .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo,
 410        .set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo,
 411};
 412
 413/**
 414 *  Scsi_Host_attrs SCSI host attributes
 415 */
 416static ssize_t
 417bfad_im_serial_num_show(struct device *dev, struct device_attribute *attr,
 418                         char *buf)
 419{
 420        struct Scsi_Host *shost = class_to_shost(dev);
 421        struct bfad_im_port_s *im_port =
 422                        (struct bfad_im_port_s *) shost->hostdata[0];
 423        struct bfad_s         *bfad = im_port->bfad;
 424        struct bfa_ioc_attr_s  ioc_attr;
 425
 426        memset(&ioc_attr, 0, sizeof(ioc_attr));
 427        bfa_get_attr(&bfad->bfa, &ioc_attr);
 428        return snprintf(buf, PAGE_SIZE, "%s\n",
 429                        ioc_attr.adapter_attr.serial_num);
 430}
 431
 432static ssize_t
 433bfad_im_model_show(struct device *dev, struct device_attribute *attr,
 434                        char *buf)
 435{
 436        struct Scsi_Host *shost = class_to_shost(dev);
 437        struct bfad_im_port_s *im_port =
 438                        (struct bfad_im_port_s *) shost->hostdata[0];
 439        struct bfad_s         *bfad = im_port->bfad;
 440        struct bfa_ioc_attr_s  ioc_attr;
 441
 442        memset(&ioc_attr, 0, sizeof(ioc_attr));
 443        bfa_get_attr(&bfad->bfa, &ioc_attr);
 444        return snprintf(buf, PAGE_SIZE, "%s\n", ioc_attr.adapter_attr.model);
 445}
 446
 447static ssize_t
 448bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
 449                                 char *buf)
 450{
 451        struct Scsi_Host *shost = class_to_shost(dev);
 452        struct bfad_im_port_s *im_port =
 453                        (struct bfad_im_port_s *) shost->hostdata[0];
 454        struct bfad_s         *bfad = im_port->bfad;
 455        struct bfa_ioc_attr_s  ioc_attr;
 456
 457        memset(&ioc_attr, 0, sizeof(ioc_attr));
 458        bfa_get_attr(&bfad->bfa, &ioc_attr);
 459        return snprintf(buf, PAGE_SIZE, "%s\n",
 460                        ioc_attr.adapter_attr.model_descr);
 461}
 462
 463static ssize_t
 464bfad_im_node_name_show(struct device *dev, struct device_attribute *attr,
 465                                 char *buf)
 466{
 467        struct Scsi_Host *shost = class_to_shost(dev);
 468        struct bfad_im_port_s *im_port =
 469                        (struct bfad_im_port_s *) shost->hostdata[0];
 470        struct bfad_port_s    *port = im_port->port;
 471        u64        nwwn;
 472
 473        nwwn = bfa_fcs_port_get_nwwn(port->fcs_port);
 474        return snprintf(buf, PAGE_SIZE, "0x%llx\n", bfa_os_htonll(nwwn));
 475}
 476
 477static ssize_t
 478bfad_im_symbolic_name_show(struct device *dev, struct device_attribute *attr,
 479                                 char *buf)
 480{
 481        struct Scsi_Host *shost = class_to_shost(dev);
 482        struct bfad_im_port_s *im_port =
 483                        (struct bfad_im_port_s *) shost->hostdata[0];
 484        struct bfad_s         *bfad = im_port->bfad;
 485        struct bfa_ioc_attr_s  ioc_attr;
 486
 487        memset(&ioc_attr, 0, sizeof(ioc_attr));
 488        bfa_get_attr(&bfad->bfa, &ioc_attr);
 489
 490        return snprintf(buf, PAGE_SIZE, "Brocade %s FV%s DV%s\n",
 491                        ioc_attr.adapter_attr.model,
 492                        ioc_attr.adapter_attr.fw_ver, BFAD_DRIVER_VERSION);
 493}
 494
 495static ssize_t
 496bfad_im_hw_version_show(struct device *dev, struct device_attribute *attr,
 497                                char *buf)
 498{
 499        struct Scsi_Host *shost = class_to_shost(dev);
 500        struct bfad_im_port_s *im_port =
 501                        (struct bfad_im_port_s *) shost->hostdata[0];
 502        struct bfad_s         *bfad = im_port->bfad;
 503        struct bfa_ioc_attr_s  ioc_attr;
 504
 505        memset(&ioc_attr, 0, sizeof(ioc_attr));
 506        bfa_get_attr(&bfad->bfa, &ioc_attr);
 507        return snprintf(buf, PAGE_SIZE, "%s\n", ioc_attr.adapter_attr.hw_ver);
 508}
 509
 510static ssize_t
 511bfad_im_drv_version_show(struct device *dev, struct device_attribute *attr,
 512                                char *buf)
 513{
 514        return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_VERSION);
 515}
 516
 517static ssize_t
 518bfad_im_optionrom_version_show(struct device *dev,
 519                         struct device_attribute *attr, char *buf)
 520{
 521        struct Scsi_Host *shost = class_to_shost(dev);
 522        struct bfad_im_port_s *im_port =
 523                        (struct bfad_im_port_s *) shost->hostdata[0];
 524        struct bfad_s         *bfad = im_port->bfad;
 525        struct bfa_ioc_attr_s  ioc_attr;
 526
 527        memset(&ioc_attr, 0, sizeof(ioc_attr));
 528        bfa_get_attr(&bfad->bfa, &ioc_attr);
 529        return snprintf(buf, PAGE_SIZE, "%s\n",
 530                        ioc_attr.adapter_attr.optrom_ver);
 531}
 532
 533static ssize_t
 534bfad_im_fw_version_show(struct device *dev, struct device_attribute *attr,
 535                                 char *buf)
 536{
 537        struct Scsi_Host *shost = class_to_shost(dev);
 538        struct bfad_im_port_s *im_port =
 539                        (struct bfad_im_port_s *) shost->hostdata[0];
 540        struct bfad_s         *bfad = im_port->bfad;
 541        struct bfa_ioc_attr_s  ioc_attr;
 542
 543        memset(&ioc_attr, 0, sizeof(ioc_attr));
 544        bfa_get_attr(&bfad->bfa, &ioc_attr);
 545        return snprintf(buf, PAGE_SIZE, "%s\n", ioc_attr.adapter_attr.fw_ver);
 546}
 547
 548static ssize_t
 549bfad_im_num_of_ports_show(struct device *dev, struct device_attribute *attr,
 550                                char *buf)
 551{
 552        struct Scsi_Host *shost = class_to_shost(dev);
 553        struct bfad_im_port_s *im_port =
 554                        (struct bfad_im_port_s *) shost->hostdata[0];
 555        struct bfad_s         *bfad = im_port->bfad;
 556        struct bfa_ioc_attr_s  ioc_attr;
 557
 558        memset(&ioc_attr, 0, sizeof(ioc_attr));
 559        bfa_get_attr(&bfad->bfa, &ioc_attr);
 560        return snprintf(buf, PAGE_SIZE, "%d\n", ioc_attr.adapter_attr.nports);
 561}
 562
 563static ssize_t
 564bfad_im_drv_name_show(struct device *dev, struct device_attribute *attr,
 565                                char *buf)
 566{
 567        return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_NAME);
 568}
 569
 570static ssize_t
 571bfad_im_num_of_discovered_ports_show(struct device *dev,
 572                        struct device_attribute *attr, char *buf)
 573{
 574        struct Scsi_Host *shost = class_to_shost(dev);
 575        struct bfad_im_port_s *im_port =
 576                        (struct bfad_im_port_s *) shost->hostdata[0];
 577        struct bfad_port_s    *port = im_port->port;
 578        struct bfad_s         *bfad = im_port->bfad;
 579        int        nrports = 2048;
 580        wwn_t          *rports = NULL;
 581        unsigned long   flags;
 582
 583        rports = kzalloc(sizeof(wwn_t) * nrports , GFP_ATOMIC);
 584        if (rports == NULL)
 585                return -ENOMEM;
 586
 587        spin_lock_irqsave(&bfad->bfad_lock, flags);
 588        bfa_fcs_port_get_rports(port->fcs_port, rports, &nrports);
 589        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 590        kfree(rports);
 591
 592        return snprintf(buf, PAGE_SIZE, "%d\n", nrports);
 593}
 594
 595static          DEVICE_ATTR(serial_number, S_IRUGO,
 596                                bfad_im_serial_num_show, NULL);
 597static          DEVICE_ATTR(model, S_IRUGO, bfad_im_model_show, NULL);
 598static          DEVICE_ATTR(model_description, S_IRUGO,
 599                                bfad_im_model_desc_show, NULL);
 600static          DEVICE_ATTR(node_name, S_IRUGO, bfad_im_node_name_show, NULL);
 601static          DEVICE_ATTR(symbolic_name, S_IRUGO,
 602                                bfad_im_symbolic_name_show, NULL);
 603static          DEVICE_ATTR(hardware_version, S_IRUGO,
 604                                bfad_im_hw_version_show, NULL);
 605static          DEVICE_ATTR(driver_version, S_IRUGO,
 606                                bfad_im_drv_version_show, NULL);
 607static          DEVICE_ATTR(option_rom_version, S_IRUGO,
 608                                bfad_im_optionrom_version_show, NULL);
 609static          DEVICE_ATTR(firmware_version, S_IRUGO,
 610                                bfad_im_fw_version_show, NULL);
 611static          DEVICE_ATTR(number_of_ports, S_IRUGO,
 612                                bfad_im_num_of_ports_show, NULL);
 613static          DEVICE_ATTR(driver_name, S_IRUGO, bfad_im_drv_name_show, NULL);
 614static          DEVICE_ATTR(number_of_discovered_ports, S_IRUGO,
 615                                bfad_im_num_of_discovered_ports_show, NULL);
 616
 617struct device_attribute *bfad_im_host_attrs[] = {
 618        &dev_attr_serial_number,
 619        &dev_attr_model,
 620        &dev_attr_model_description,
 621        &dev_attr_node_name,
 622        &dev_attr_symbolic_name,
 623        &dev_attr_hardware_version,
 624        &dev_attr_driver_version,
 625        &dev_attr_option_rom_version,
 626        &dev_attr_firmware_version,
 627        &dev_attr_number_of_ports,
 628        &dev_attr_driver_name,
 629        &dev_attr_number_of_discovered_ports,
 630        NULL,
 631};
 632
 633struct device_attribute *bfad_im_vport_attrs[] = {
 634    &dev_attr_serial_number,
 635    &dev_attr_model,
 636    &dev_attr_model_description,
 637    &dev_attr_node_name,
 638    &dev_attr_symbolic_name,
 639    &dev_attr_hardware_version,
 640    &dev_attr_driver_version,
 641    &dev_attr_option_rom_version,
 642    &dev_attr_firmware_version,
 643    &dev_attr_number_of_ports,
 644    &dev_attr_driver_name,
 645    &dev_attr_number_of_discovered_ports,
 646    NULL,
 647};
 648
 649
 650