linux/drivers/scsi/bfa/bfad_attr.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2005-2010 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
  25/*
  26 * FC transport template entry, get SCSI target port ID.
  27 */
  28static void
  29bfad_im_get_starget_port_id(struct scsi_target *starget)
  30{
  31        struct Scsi_Host *shost;
  32        struct bfad_im_port_s *im_port;
  33        struct bfad_s         *bfad;
  34        struct bfad_itnim_s   *itnim = NULL;
  35        u32        fc_id = -1;
  36        unsigned long   flags;
  37
  38        shost = dev_to_shost(starget->dev.parent);
  39        im_port = (struct bfad_im_port_s *) shost->hostdata[0];
  40        bfad = im_port->bfad;
  41        spin_lock_irqsave(&bfad->bfad_lock, flags);
  42
  43        itnim = bfad_get_itnim(im_port, starget->id);
  44        if (itnim)
  45                fc_id = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim);
  46
  47        fc_starget_port_id(starget) = fc_id;
  48        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
  49}
  50
  51/*
  52 * FC transport template entry, get SCSI target nwwn.
  53 */
  54static void
  55bfad_im_get_starget_node_name(struct scsi_target *starget)
  56{
  57        struct Scsi_Host *shost;
  58        struct bfad_im_port_s *im_port;
  59        struct bfad_s         *bfad;
  60        struct bfad_itnim_s   *itnim = NULL;
  61        u64             node_name = 0;
  62        unsigned long   flags;
  63
  64        shost = dev_to_shost(starget->dev.parent);
  65        im_port = (struct bfad_im_port_s *) shost->hostdata[0];
  66        bfad = im_port->bfad;
  67        spin_lock_irqsave(&bfad->bfad_lock, flags);
  68
  69        itnim = bfad_get_itnim(im_port, starget->id);
  70        if (itnim)
  71                node_name = bfa_fcs_itnim_get_nwwn(&itnim->fcs_itnim);
  72
  73        fc_starget_node_name(starget) = cpu_to_be64(node_name);
  74        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
  75}
  76
  77/*
  78 * FC transport template entry, get SCSI target pwwn.
  79 */
  80static void
  81bfad_im_get_starget_port_name(struct scsi_target *starget)
  82{
  83        struct Scsi_Host *shost;
  84        struct bfad_im_port_s *im_port;
  85        struct bfad_s         *bfad;
  86        struct bfad_itnim_s   *itnim = NULL;
  87        u64             port_name = 0;
  88        unsigned long   flags;
  89
  90        shost = dev_to_shost(starget->dev.parent);
  91        im_port = (struct bfad_im_port_s *) shost->hostdata[0];
  92        bfad = im_port->bfad;
  93        spin_lock_irqsave(&bfad->bfad_lock, flags);
  94
  95        itnim = bfad_get_itnim(im_port, starget->id);
  96        if (itnim)
  97                port_name = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim);
  98
  99        fc_starget_port_name(starget) = cpu_to_be64(port_name);
 100        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 101}
 102
 103/*
 104 * FC transport template entry, get SCSI host port ID.
 105 */
 106static void
 107bfad_im_get_host_port_id(struct Scsi_Host *shost)
 108{
 109        struct bfad_im_port_s *im_port =
 110                        (struct bfad_im_port_s *) shost->hostdata[0];
 111        struct bfad_port_s    *port = im_port->port;
 112
 113        fc_host_port_id(shost) =
 114                        bfa_hton3b(bfa_fcs_lport_get_fcid(port->fcs_port));
 115}
 116
 117/*
 118 * FC transport template entry, get SCSI host port type.
 119 */
 120static void
 121bfad_im_get_host_port_type(struct Scsi_Host *shost)
 122{
 123        struct bfad_im_port_s *im_port =
 124                        (struct bfad_im_port_s *) shost->hostdata[0];
 125        struct bfad_s         *bfad = im_port->bfad;
 126        struct bfa_lport_attr_s port_attr;
 127
 128        bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
 129
 130        switch (port_attr.port_type) {
 131        case BFA_PORT_TYPE_NPORT:
 132                fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
 133                break;
 134        case BFA_PORT_TYPE_NLPORT:
 135                fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
 136                break;
 137        case BFA_PORT_TYPE_P2P:
 138                fc_host_port_type(shost) = FC_PORTTYPE_PTP;
 139                break;
 140        case BFA_PORT_TYPE_LPORT:
 141                fc_host_port_type(shost) = FC_PORTTYPE_LPORT;
 142                break;
 143        default:
 144                fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
 145                break;
 146        }
 147}
 148
 149/*
 150 * FC transport template entry, get SCSI host port state.
 151 */
 152static void
 153bfad_im_get_host_port_state(struct Scsi_Host *shost)
 154{
 155        struct bfad_im_port_s *im_port =
 156                        (struct bfad_im_port_s *) shost->hostdata[0];
 157        struct bfad_s         *bfad = im_port->bfad;
 158        struct bfa_port_attr_s attr;
 159
 160        bfa_fcport_get_attr(&bfad->bfa, &attr);
 161
 162        switch (attr.port_state) {
 163        case BFA_PORT_ST_LINKDOWN:
 164                fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
 165                break;
 166        case BFA_PORT_ST_LINKUP:
 167                fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
 168                break;
 169        case BFA_PORT_ST_DISABLED:
 170        case BFA_PORT_ST_STOPPED:
 171        case BFA_PORT_ST_IOCDOWN:
 172        case BFA_PORT_ST_IOCDIS:
 173                fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
 174                break;
 175        case BFA_PORT_ST_UNINIT:
 176        case BFA_PORT_ST_ENABLING_QWAIT:
 177        case BFA_PORT_ST_ENABLING:
 178        case BFA_PORT_ST_DISABLING_QWAIT:
 179        case BFA_PORT_ST_DISABLING:
 180        default:
 181                fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
 182                break;
 183        }
 184}
 185
 186/*
 187 * FC transport template entry, get SCSI host active fc4s.
 188 */
 189static void
 190bfad_im_get_host_active_fc4s(struct Scsi_Host *shost)
 191{
 192        struct bfad_im_port_s *im_port =
 193                        (struct bfad_im_port_s *) shost->hostdata[0];
 194        struct bfad_port_s    *port = im_port->port;
 195
 196        memset(fc_host_active_fc4s(shost), 0,
 197               sizeof(fc_host_active_fc4s(shost)));
 198
 199        if (port->supported_fc4s & BFA_LPORT_ROLE_FCP_IM)
 200                fc_host_active_fc4s(shost)[2] = 1;
 201
 202        fc_host_active_fc4s(shost)[7] = 1;
 203}
 204
 205/*
 206 * FC transport template entry, get SCSI host link speed.
 207 */
 208static void
 209bfad_im_get_host_speed(struct Scsi_Host *shost)
 210{
 211        struct bfad_im_port_s *im_port =
 212                        (struct bfad_im_port_s *) shost->hostdata[0];
 213        struct bfad_s         *bfad = im_port->bfad;
 214        struct bfa_port_attr_s attr;
 215
 216        bfa_fcport_get_attr(&bfad->bfa, &attr);
 217        switch (attr.speed) {
 218        case BFA_PORT_SPEED_10GBPS:
 219                fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
 220                break;
 221        case BFA_PORT_SPEED_8GBPS:
 222                fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
 223                break;
 224        case BFA_PORT_SPEED_4GBPS:
 225                fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
 226                break;
 227        case BFA_PORT_SPEED_2GBPS:
 228                fc_host_speed(shost) = FC_PORTSPEED_2GBIT;
 229                break;
 230        case BFA_PORT_SPEED_1GBPS:
 231                fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
 232                break;
 233        default:
 234                fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
 235                break;
 236        }
 237}
 238
 239/*
 240 * FC transport template entry, get SCSI host port type.
 241 */
 242static void
 243bfad_im_get_host_fabric_name(struct Scsi_Host *shost)
 244{
 245        struct bfad_im_port_s *im_port =
 246                        (struct bfad_im_port_s *) shost->hostdata[0];
 247        struct bfad_port_s    *port = im_port->port;
 248        wwn_t           fabric_nwwn = 0;
 249
 250        fabric_nwwn = bfa_fcs_lport_get_fabric_name(port->fcs_port);
 251
 252        fc_host_fabric_name(shost) = cpu_to_be64(fabric_nwwn);
 253
 254}
 255
 256/*
 257 * FC transport template entry, get BFAD statistics.
 258 */
 259static struct fc_host_statistics *
 260bfad_im_get_stats(struct Scsi_Host *shost)
 261{
 262        struct bfad_im_port_s *im_port =
 263                        (struct bfad_im_port_s *) shost->hostdata[0];
 264        struct bfad_s         *bfad = im_port->bfad;
 265        struct bfad_hal_comp fcomp;
 266        union bfa_port_stats_u *fcstats;
 267        struct fc_host_statistics *hstats;
 268        bfa_status_t    rc;
 269        unsigned long   flags;
 270
 271        fcstats = kzalloc(sizeof(union bfa_port_stats_u), GFP_KERNEL);
 272        if (fcstats == NULL)
 273                return NULL;
 274
 275        hstats = &bfad->link_stats;
 276        init_completion(&fcomp.comp);
 277        spin_lock_irqsave(&bfad->bfad_lock, flags);
 278        memset(hstats, 0, sizeof(struct fc_host_statistics));
 279        rc = bfa_port_get_stats(BFA_FCPORT(&bfad->bfa),
 280                                fcstats, bfad_hcb_comp, &fcomp);
 281        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 282        if (rc != BFA_STATUS_OK)
 283                return NULL;
 284
 285        wait_for_completion(&fcomp.comp);
 286
 287        /* Fill the fc_host_statistics structure */
 288        hstats->seconds_since_last_reset = fcstats->fc.secs_reset;
 289        hstats->tx_frames = fcstats->fc.tx_frames;
 290        hstats->tx_words  = fcstats->fc.tx_words;
 291        hstats->rx_frames = fcstats->fc.rx_frames;
 292        hstats->rx_words  = fcstats->fc.rx_words;
 293        hstats->lip_count = fcstats->fc.lip_count;
 294        hstats->nos_count = fcstats->fc.nos_count;
 295        hstats->error_frames = fcstats->fc.error_frames;
 296        hstats->dumped_frames = fcstats->fc.dropped_frames;
 297        hstats->link_failure_count = fcstats->fc.link_failures;
 298        hstats->loss_of_sync_count = fcstats->fc.loss_of_syncs;
 299        hstats->loss_of_signal_count = fcstats->fc.loss_of_signals;
 300        hstats->prim_seq_protocol_err_count = fcstats->fc.primseq_errs;
 301        hstats->invalid_crc_count = fcstats->fc.invalid_crcs;
 302
 303        kfree(fcstats);
 304        return hstats;
 305}
 306
 307/*
 308 * FC transport template entry, reset BFAD statistics.
 309 */
 310static void
 311bfad_im_reset_stats(struct Scsi_Host *shost)
 312{
 313        struct bfad_im_port_s *im_port =
 314                        (struct bfad_im_port_s *) shost->hostdata[0];
 315        struct bfad_s         *bfad = im_port->bfad;
 316        struct bfad_hal_comp fcomp;
 317        unsigned long   flags;
 318        bfa_status_t    rc;
 319
 320        init_completion(&fcomp.comp);
 321        spin_lock_irqsave(&bfad->bfad_lock, flags);
 322        rc = bfa_port_clear_stats(BFA_FCPORT(&bfad->bfa), bfad_hcb_comp,
 323                                        &fcomp);
 324        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 325
 326        if (rc != BFA_STATUS_OK)
 327                return;
 328
 329        wait_for_completion(&fcomp.comp);
 330
 331        return;
 332}
 333
 334/*
 335 * FC transport template entry, get rport loss timeout.
 336 */
 337static void
 338bfad_im_get_rport_loss_tmo(struct fc_rport *rport)
 339{
 340        struct bfad_itnim_data_s *itnim_data = rport->dd_data;
 341        struct bfad_itnim_s   *itnim = itnim_data->itnim;
 342        struct bfad_s         *bfad = itnim->im->bfad;
 343        unsigned long   flags;
 344
 345        spin_lock_irqsave(&bfad->bfad_lock, flags);
 346        rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa);
 347        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 348}
 349
 350/*
 351 * FC transport template entry, set rport loss timeout.
 352 */
 353static void
 354bfad_im_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)
 355{
 356        struct bfad_itnim_data_s *itnim_data = rport->dd_data;
 357        struct bfad_itnim_s   *itnim = itnim_data->itnim;
 358        struct bfad_s         *bfad = itnim->im->bfad;
 359        unsigned long   flags;
 360
 361        if (timeout > 0) {
 362                spin_lock_irqsave(&bfad->bfad_lock, flags);
 363                bfa_fcpim_path_tov_set(&bfad->bfa, timeout);
 364                rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa);
 365                spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 366        }
 367
 368}
 369
 370static int
 371bfad_im_vport_create(struct fc_vport *fc_vport, bool disable)
 372{
 373        char *vname = fc_vport->symbolic_name;
 374        struct Scsi_Host *shost = fc_vport->shost;
 375        struct bfad_im_port_s *im_port =
 376                (struct bfad_im_port_s *) shost->hostdata[0];
 377        struct bfad_s *bfad = im_port->bfad;
 378        struct bfa_lport_cfg_s port_cfg;
 379        struct bfad_vport_s *vp;
 380        int status = 0, rc;
 381        unsigned long flags;
 382
 383        memset(&port_cfg, 0, sizeof(port_cfg));
 384        u64_to_wwn(fc_vport->node_name, (u8 *)&port_cfg.nwwn);
 385        u64_to_wwn(fc_vport->port_name, (u8 *)&port_cfg.pwwn);
 386        if (strlen(vname) > 0)
 387                strcpy((char *)&port_cfg.sym_name, vname);
 388        port_cfg.roles = BFA_LPORT_ROLE_FCP_IM;
 389
 390        spin_lock_irqsave(&bfad->bfad_lock, flags);
 391        list_for_each_entry(vp, &bfad->pbc_vport_list, list_entry) {
 392                if (port_cfg.pwwn ==
 393                                vp->fcs_vport.lport.port_cfg.pwwn) {
 394                        port_cfg.preboot_vp =
 395                                vp->fcs_vport.lport.port_cfg.preboot_vp;
 396                        break;
 397                }
 398        }
 399        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 400
 401        rc = bfad_vport_create(bfad, 0, &port_cfg, &fc_vport->dev);
 402        if (rc == BFA_STATUS_OK) {
 403                struct bfad_vport_s *vport;
 404                struct bfa_fcs_vport_s *fcs_vport;
 405                struct Scsi_Host *vshost;
 406
 407                spin_lock_irqsave(&bfad->bfad_lock, flags);
 408                fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0,
 409                                        port_cfg.pwwn);
 410                spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 411                if (fcs_vport == NULL)
 412                        return VPCERR_BAD_WWN;
 413
 414                fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE);
 415                if (disable) {
 416                        spin_lock_irqsave(&bfad->bfad_lock, flags);
 417                        bfa_fcs_vport_stop(fcs_vport);
 418                        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 419                        fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
 420                }
 421
 422                vport = fcs_vport->vport_drv;
 423                vshost = vport->drv_port.im_port->shost;
 424                fc_host_node_name(vshost) = wwn_to_u64((u8 *)&port_cfg.nwwn);
 425                fc_host_port_name(vshost) = wwn_to_u64((u8 *)&port_cfg.pwwn);
 426                fc_vport->dd_data = vport;
 427                vport->drv_port.im_port->fc_vport = fc_vport;
 428        } else if (rc == BFA_STATUS_INVALID_WWN)
 429                return VPCERR_BAD_WWN;
 430        else if (rc == BFA_STATUS_VPORT_EXISTS)
 431                return VPCERR_BAD_WWN;
 432        else if (rc == BFA_STATUS_VPORT_MAX)
 433                return VPCERR_NO_FABRIC_SUPP;
 434        else if (rc == BFA_STATUS_VPORT_WWN_BP)
 435                return VPCERR_BAD_WWN;
 436        else
 437                return FC_VPORT_FAILED;
 438
 439        return status;
 440}
 441
 442static int
 443bfad_im_vport_delete(struct fc_vport *fc_vport)
 444{
 445        struct bfad_vport_s *vport = (struct bfad_vport_s *)fc_vport->dd_data;
 446        struct bfad_im_port_s *im_port =
 447                        (struct bfad_im_port_s *) vport->drv_port.im_port;
 448        struct bfad_s *bfad = im_port->bfad;
 449        struct bfad_port_s *port;
 450        struct bfa_fcs_vport_s *fcs_vport;
 451        struct Scsi_Host *vshost;
 452        wwn_t   pwwn;
 453        int rc;
 454        unsigned long flags;
 455        struct completion fcomp;
 456
 457        if (im_port->flags & BFAD_PORT_DELETE)
 458                goto free_scsi_host;
 459
 460        port = im_port->port;
 461
 462        vshost = vport->drv_port.im_port->shost;
 463        u64_to_wwn(fc_host_port_name(vshost), (u8 *)&pwwn);
 464
 465        spin_lock_irqsave(&bfad->bfad_lock, flags);
 466        fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn);
 467        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 468
 469        if (fcs_vport == NULL)
 470                return VPCERR_BAD_WWN;
 471
 472        vport->drv_port.flags |= BFAD_PORT_DELETE;
 473
 474        vport->comp_del = &fcomp;
 475        init_completion(vport->comp_del);
 476
 477        spin_lock_irqsave(&bfad->bfad_lock, flags);
 478        rc = bfa_fcs_vport_delete(&vport->fcs_vport);
 479        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 480
 481        if (rc == BFA_STATUS_PBC) {
 482                vport->drv_port.flags &= ~BFAD_PORT_DELETE;
 483                vport->comp_del = NULL;
 484                return -1;
 485        }
 486
 487        wait_for_completion(vport->comp_del);
 488
 489free_scsi_host:
 490        bfad_scsi_host_free(bfad, im_port);
 491
 492        kfree(vport);
 493
 494        return 0;
 495}
 496
 497static int
 498bfad_im_vport_disable(struct fc_vport *fc_vport, bool disable)
 499{
 500        struct bfad_vport_s *vport;
 501        struct bfad_s *bfad;
 502        struct bfa_fcs_vport_s *fcs_vport;
 503        struct Scsi_Host *vshost;
 504        wwn_t   pwwn;
 505        unsigned long flags;
 506
 507        vport = (struct bfad_vport_s *)fc_vport->dd_data;
 508        bfad = vport->drv_port.bfad;
 509        vshost = vport->drv_port.im_port->shost;
 510        u64_to_wwn(fc_host_port_name(vshost), (u8 *)&pwwn);
 511
 512        spin_lock_irqsave(&bfad->bfad_lock, flags);
 513        fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn);
 514        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 515
 516        if (fcs_vport == NULL)
 517                return VPCERR_BAD_WWN;
 518
 519        if (disable) {
 520                bfa_fcs_vport_stop(fcs_vport);
 521                fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
 522        } else {
 523                bfa_fcs_vport_start(fcs_vport);
 524                fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE);
 525        }
 526
 527        return 0;
 528}
 529
 530struct fc_function_template bfad_im_fc_function_template = {
 531
 532        /* Target dynamic attributes */
 533        .get_starget_port_id = bfad_im_get_starget_port_id,
 534        .show_starget_port_id = 1,
 535        .get_starget_node_name = bfad_im_get_starget_node_name,
 536        .show_starget_node_name = 1,
 537        .get_starget_port_name = bfad_im_get_starget_port_name,
 538        .show_starget_port_name = 1,
 539
 540        /* Host dynamic attribute */
 541        .get_host_port_id = bfad_im_get_host_port_id,
 542        .show_host_port_id = 1,
 543
 544        /* Host fixed attributes */
 545        .show_host_node_name = 1,
 546        .show_host_port_name = 1,
 547        .show_host_supported_classes = 1,
 548        .show_host_supported_fc4s = 1,
 549        .show_host_supported_speeds = 1,
 550        .show_host_maxframe_size = 1,
 551
 552        /* More host dynamic attributes */
 553        .show_host_port_type = 1,
 554        .get_host_port_type = bfad_im_get_host_port_type,
 555        .show_host_port_state = 1,
 556        .get_host_port_state = bfad_im_get_host_port_state,
 557        .show_host_active_fc4s = 1,
 558        .get_host_active_fc4s = bfad_im_get_host_active_fc4s,
 559        .show_host_speed = 1,
 560        .get_host_speed = bfad_im_get_host_speed,
 561        .show_host_fabric_name = 1,
 562        .get_host_fabric_name = bfad_im_get_host_fabric_name,
 563
 564        .show_host_symbolic_name = 1,
 565
 566        /* Statistics */
 567        .get_fc_host_stats = bfad_im_get_stats,
 568        .reset_fc_host_stats = bfad_im_reset_stats,
 569
 570        /* Allocation length for host specific data */
 571        .dd_fcrport_size = sizeof(struct bfad_itnim_data_s *),
 572
 573        /* Remote port fixed attributes */
 574        .show_rport_maxframe_size = 1,
 575        .show_rport_supported_classes = 1,
 576        .show_rport_dev_loss_tmo = 1,
 577        .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo,
 578        .set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo,
 579
 580        .vport_create = bfad_im_vport_create,
 581        .vport_delete = bfad_im_vport_delete,
 582        .vport_disable = bfad_im_vport_disable,
 583};
 584
 585struct fc_function_template bfad_im_vport_fc_function_template = {
 586
 587        /* Target dynamic attributes */
 588        .get_starget_port_id = bfad_im_get_starget_port_id,
 589        .show_starget_port_id = 1,
 590        .get_starget_node_name = bfad_im_get_starget_node_name,
 591        .show_starget_node_name = 1,
 592        .get_starget_port_name = bfad_im_get_starget_port_name,
 593        .show_starget_port_name = 1,
 594
 595        /* Host dynamic attribute */
 596        .get_host_port_id = bfad_im_get_host_port_id,
 597        .show_host_port_id = 1,
 598
 599        /* Host fixed attributes */
 600        .show_host_node_name = 1,
 601        .show_host_port_name = 1,
 602        .show_host_supported_classes = 1,
 603        .show_host_supported_fc4s = 1,
 604        .show_host_supported_speeds = 1,
 605        .show_host_maxframe_size = 1,
 606
 607        /* More host dynamic attributes */
 608        .show_host_port_type = 1,
 609        .get_host_port_type = bfad_im_get_host_port_type,
 610        .show_host_port_state = 1,
 611        .get_host_port_state = bfad_im_get_host_port_state,
 612        .show_host_active_fc4s = 1,
 613        .get_host_active_fc4s = bfad_im_get_host_active_fc4s,
 614        .show_host_speed = 1,
 615        .get_host_speed = bfad_im_get_host_speed,
 616        .show_host_fabric_name = 1,
 617        .get_host_fabric_name = bfad_im_get_host_fabric_name,
 618
 619        .show_host_symbolic_name = 1,
 620
 621        /* Statistics */
 622        .get_fc_host_stats = bfad_im_get_stats,
 623        .reset_fc_host_stats = bfad_im_reset_stats,
 624
 625        /* Allocation length for host specific data */
 626        .dd_fcrport_size = sizeof(struct bfad_itnim_data_s *),
 627
 628        /* Remote port fixed attributes */
 629        .show_rport_maxframe_size = 1,
 630        .show_rport_supported_classes = 1,
 631        .show_rport_dev_loss_tmo = 1,
 632        .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo,
 633        .set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo,
 634};
 635
 636/*
 637 *  Scsi_Host_attrs SCSI host attributes
 638 */
 639static ssize_t
 640bfad_im_serial_num_show(struct device *dev, struct device_attribute *attr,
 641                         char *buf)
 642{
 643        struct Scsi_Host *shost = class_to_shost(dev);
 644        struct bfad_im_port_s *im_port =
 645                        (struct bfad_im_port_s *) shost->hostdata[0];
 646        struct bfad_s *bfad = im_port->bfad;
 647        char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
 648
 649        bfa_get_adapter_serial_num(&bfad->bfa, serial_num);
 650        return snprintf(buf, PAGE_SIZE, "%s\n", serial_num);
 651}
 652
 653static ssize_t
 654bfad_im_model_show(struct device *dev, struct device_attribute *attr,
 655                        char *buf)
 656{
 657        struct Scsi_Host *shost = class_to_shost(dev);
 658        struct bfad_im_port_s *im_port =
 659                        (struct bfad_im_port_s *) shost->hostdata[0];
 660        struct bfad_s *bfad = im_port->bfad;
 661        char model[BFA_ADAPTER_MODEL_NAME_LEN];
 662
 663        bfa_get_adapter_model(&bfad->bfa, model);
 664        return snprintf(buf, PAGE_SIZE, "%s\n", model);
 665}
 666
 667static ssize_t
 668bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
 669                                 char *buf)
 670{
 671        struct Scsi_Host *shost = class_to_shost(dev);
 672        struct bfad_im_port_s *im_port =
 673                        (struct bfad_im_port_s *) shost->hostdata[0];
 674        struct bfad_s *bfad = im_port->bfad;
 675        char model[BFA_ADAPTER_MODEL_NAME_LEN];
 676        char model_descr[BFA_ADAPTER_MODEL_DESCR_LEN];
 677
 678        bfa_get_adapter_model(&bfad->bfa, model);
 679        if (!strcmp(model, "Brocade-425"))
 680                snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
 681                        "Brocade 4Gbps PCIe dual port FC HBA");
 682        else if (!strcmp(model, "Brocade-825"))
 683                snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
 684                        "Brocade 8Gbps PCIe dual port FC HBA");
 685        else if (!strcmp(model, "Brocade-42B"))
 686                snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
 687                        "HP 4Gbps PCIe dual port FC HBA");
 688        else if (!strcmp(model, "Brocade-82B"))
 689                snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
 690                        "HP 8Gbps PCIe dual port FC HBA");
 691        else if (!strcmp(model, "Brocade-1010"))
 692                snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
 693                        "Brocade 10Gbps single port CNA");
 694        else if (!strcmp(model, "Brocade-1020"))
 695                snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
 696                        "Brocade 10Gbps dual port CNA");
 697        else if (!strcmp(model, "Brocade-1007"))
 698                snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
 699                        "Brocade 10Gbps CNA");
 700        else if (!strcmp(model, "Brocade-415"))
 701                snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
 702                        "Brocade 4Gbps PCIe single port FC HBA");
 703        else if (!strcmp(model, "Brocade-815"))
 704                snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
 705                        "Brocade 8Gbps PCIe single port FC HBA");
 706        else if (!strcmp(model, "Brocade-41B"))
 707                snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
 708                        "HP 4Gbps PCIe single port FC HBA");
 709        else if (!strcmp(model, "Brocade-81B"))
 710                snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
 711                        "HP 8Gbps PCIe single port FC HBA");
 712        else if (!strcmp(model, "Brocade-804"))
 713                snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
 714                        "HP Bladesystem C-class 8Gbps FC HBA");
 715        else if (!strcmp(model, "Brocade-902"))
 716                snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
 717                        "Brocade 10Gbps CNA");
 718        else
 719                snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
 720                        "Invalid Model");
 721
 722        return snprintf(buf, PAGE_SIZE, "%s\n", model_descr);
 723}
 724
 725static ssize_t
 726bfad_im_node_name_show(struct device *dev, struct device_attribute *attr,
 727                                 char *buf)
 728{
 729        struct Scsi_Host *shost = class_to_shost(dev);
 730        struct bfad_im_port_s *im_port =
 731                        (struct bfad_im_port_s *) shost->hostdata[0];
 732        struct bfad_port_s    *port = im_port->port;
 733        u64        nwwn;
 734
 735        nwwn = bfa_fcs_lport_get_nwwn(port->fcs_port);
 736        return snprintf(buf, PAGE_SIZE, "0x%llx\n", cpu_to_be64(nwwn));
 737}
 738
 739static ssize_t
 740bfad_im_symbolic_name_show(struct device *dev, struct device_attribute *attr,
 741                                 char *buf)
 742{
 743        struct Scsi_Host *shost = class_to_shost(dev);
 744        struct bfad_im_port_s *im_port =
 745                        (struct bfad_im_port_s *) shost->hostdata[0];
 746        struct bfad_s *bfad = im_port->bfad;
 747        struct bfa_lport_attr_s port_attr;
 748        char symname[BFA_SYMNAME_MAXLEN];
 749
 750        bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
 751        strncpy(symname, port_attr.port_cfg.sym_name.symname,
 752                        BFA_SYMNAME_MAXLEN);
 753        return snprintf(buf, PAGE_SIZE, "%s\n", symname);
 754}
 755
 756static ssize_t
 757bfad_im_hw_version_show(struct device *dev, struct device_attribute *attr,
 758                                char *buf)
 759{
 760        struct Scsi_Host *shost = class_to_shost(dev);
 761        struct bfad_im_port_s *im_port =
 762                        (struct bfad_im_port_s *) shost->hostdata[0];
 763        struct bfad_s *bfad = im_port->bfad;
 764        char hw_ver[BFA_VERSION_LEN];
 765
 766        bfa_get_pci_chip_rev(&bfad->bfa, hw_ver);
 767        return snprintf(buf, PAGE_SIZE, "%s\n", hw_ver);
 768}
 769
 770static ssize_t
 771bfad_im_drv_version_show(struct device *dev, struct device_attribute *attr,
 772                                char *buf)
 773{
 774        return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_VERSION);
 775}
 776
 777static ssize_t
 778bfad_im_optionrom_version_show(struct device *dev,
 779                         struct device_attribute *attr, char *buf)
 780{
 781        struct Scsi_Host *shost = class_to_shost(dev);
 782        struct bfad_im_port_s *im_port =
 783                        (struct bfad_im_port_s *) shost->hostdata[0];
 784        struct bfad_s *bfad = im_port->bfad;
 785        char optrom_ver[BFA_VERSION_LEN];
 786
 787        bfa_get_adapter_optrom_ver(&bfad->bfa, optrom_ver);
 788        return snprintf(buf, PAGE_SIZE, "%s\n", optrom_ver);
 789}
 790
 791static ssize_t
 792bfad_im_fw_version_show(struct device *dev, struct device_attribute *attr,
 793                                 char *buf)
 794{
 795        struct Scsi_Host *shost = class_to_shost(dev);
 796        struct bfad_im_port_s *im_port =
 797                        (struct bfad_im_port_s *) shost->hostdata[0];
 798        struct bfad_s *bfad = im_port->bfad;
 799        char fw_ver[BFA_VERSION_LEN];
 800
 801        bfa_get_adapter_fw_ver(&bfad->bfa, fw_ver);
 802        return snprintf(buf, PAGE_SIZE, "%s\n", fw_ver);
 803}
 804
 805static ssize_t
 806bfad_im_num_of_ports_show(struct device *dev, struct device_attribute *attr,
 807                                char *buf)
 808{
 809        struct Scsi_Host *shost = class_to_shost(dev);
 810        struct bfad_im_port_s *im_port =
 811                        (struct bfad_im_port_s *) shost->hostdata[0];
 812        struct bfad_s *bfad = im_port->bfad;
 813
 814        return snprintf(buf, PAGE_SIZE, "%d\n",
 815                        bfa_get_nports(&bfad->bfa));
 816}
 817
 818static ssize_t
 819bfad_im_drv_name_show(struct device *dev, struct device_attribute *attr,
 820                                char *buf)
 821{
 822        return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_NAME);
 823}
 824
 825static ssize_t
 826bfad_im_num_of_discovered_ports_show(struct device *dev,
 827                        struct device_attribute *attr, char *buf)
 828{
 829        struct Scsi_Host *shost = class_to_shost(dev);
 830        struct bfad_im_port_s *im_port =
 831                        (struct bfad_im_port_s *) shost->hostdata[0];
 832        struct bfad_port_s    *port = im_port->port;
 833        struct bfad_s         *bfad = im_port->bfad;
 834        int        nrports = 2048;
 835        wwn_t          *rports = NULL;
 836        unsigned long   flags;
 837
 838        rports = kzalloc(sizeof(wwn_t) * nrports , GFP_ATOMIC);
 839        if (rports == NULL)
 840                return snprintf(buf, PAGE_SIZE, "Failed\n");
 841
 842        spin_lock_irqsave(&bfad->bfad_lock, flags);
 843        bfa_fcs_lport_get_rports(port->fcs_port, rports, &nrports);
 844        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 845        kfree(rports);
 846
 847        return snprintf(buf, PAGE_SIZE, "%d\n", nrports);
 848}
 849
 850static          DEVICE_ATTR(serial_number, S_IRUGO,
 851                                bfad_im_serial_num_show, NULL);
 852static          DEVICE_ATTR(model, S_IRUGO, bfad_im_model_show, NULL);
 853static          DEVICE_ATTR(model_description, S_IRUGO,
 854                                bfad_im_model_desc_show, NULL);
 855static          DEVICE_ATTR(node_name, S_IRUGO, bfad_im_node_name_show, NULL);
 856static          DEVICE_ATTR(symbolic_name, S_IRUGO,
 857                                bfad_im_symbolic_name_show, NULL);
 858static          DEVICE_ATTR(hardware_version, S_IRUGO,
 859                                bfad_im_hw_version_show, NULL);
 860static          DEVICE_ATTR(driver_version, S_IRUGO,
 861                                bfad_im_drv_version_show, NULL);
 862static          DEVICE_ATTR(option_rom_version, S_IRUGO,
 863                                bfad_im_optionrom_version_show, NULL);
 864static          DEVICE_ATTR(firmware_version, S_IRUGO,
 865                                bfad_im_fw_version_show, NULL);
 866static          DEVICE_ATTR(number_of_ports, S_IRUGO,
 867                                bfad_im_num_of_ports_show, NULL);
 868static          DEVICE_ATTR(driver_name, S_IRUGO, bfad_im_drv_name_show, NULL);
 869static          DEVICE_ATTR(number_of_discovered_ports, S_IRUGO,
 870                                bfad_im_num_of_discovered_ports_show, NULL);
 871
 872struct device_attribute *bfad_im_host_attrs[] = {
 873        &dev_attr_serial_number,
 874        &dev_attr_model,
 875        &dev_attr_model_description,
 876        &dev_attr_node_name,
 877        &dev_attr_symbolic_name,
 878        &dev_attr_hardware_version,
 879        &dev_attr_driver_version,
 880        &dev_attr_option_rom_version,
 881        &dev_attr_firmware_version,
 882        &dev_attr_number_of_ports,
 883        &dev_attr_driver_name,
 884        &dev_attr_number_of_discovered_ports,
 885        NULL,
 886};
 887
 888struct device_attribute *bfad_im_vport_attrs[] = {
 889        &dev_attr_serial_number,
 890        &dev_attr_model,
 891        &dev_attr_model_description,
 892        &dev_attr_node_name,
 893        &dev_attr_symbolic_name,
 894        &dev_attr_hardware_version,
 895        &dev_attr_driver_version,
 896        &dev_attr_option_rom_version,
 897        &dev_attr_firmware_version,
 898        &dev_attr_number_of_ports,
 899        &dev_attr_driver_name,
 900        &dev_attr_number_of_discovered_ports,
 901        NULL,
 902};
 903
 904
 905