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 */ 28 static void 29 bfad_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 */ 54 static void 55 bfad_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 */ 80 static void 81 bfad_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 */ 106 static void 107 bfad_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 */ 120 static void 121 bfad_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 */ 152 static void 153 bfad_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 */ 189 static void 190 bfad_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 */ 208 static void 209 bfad_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_16GBPS: 222 fc_host_speed(shost) = FC_PORTSPEED_16GBIT; 223 break; 224 case BFA_PORT_SPEED_8GBPS: 225 fc_host_speed(shost) = FC_PORTSPEED_8GBIT; 226 break; 227 case BFA_PORT_SPEED_4GBPS: 228 fc_host_speed(shost) = FC_PORTSPEED_4GBIT; 229 break; 230 case BFA_PORT_SPEED_2GBPS: 231 fc_host_speed(shost) = FC_PORTSPEED_2GBIT; 232 break; 233 case BFA_PORT_SPEED_1GBPS: 234 fc_host_speed(shost) = FC_PORTSPEED_1GBIT; 235 break; 236 default: 237 fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; 238 break; 239 } 240 } 241 242 /* 243 * FC transport template entry, get SCSI host port type. 244 */ 245 static void 246 bfad_im_get_host_fabric_name(struct Scsi_Host *shost) 247 { 248 struct bfad_im_port_s *im_port = 249 (struct bfad_im_port_s *) shost->hostdata[0]; 250 struct bfad_port_s *port = im_port->port; 251 wwn_t fabric_nwwn = 0; 252 253 fabric_nwwn = bfa_fcs_lport_get_fabric_name(port->fcs_port); 254 255 fc_host_fabric_name(shost) = cpu_to_be64(fabric_nwwn); 256 257 } 258 259 /* 260 * FC transport template entry, get BFAD statistics. 261 */ 262 static struct fc_host_statistics * 263 bfad_im_get_stats(struct Scsi_Host *shost) 264 { 265 struct bfad_im_port_s *im_port = 266 (struct bfad_im_port_s *) shost->hostdata[0]; 267 struct bfad_s *bfad = im_port->bfad; 268 struct bfad_hal_comp fcomp; 269 union bfa_port_stats_u *fcstats; 270 struct fc_host_statistics *hstats; 271 bfa_status_t rc; 272 unsigned long flags; 273 274 fcstats = kzalloc(sizeof(union bfa_port_stats_u), GFP_KERNEL); 275 if (fcstats == NULL) 276 return NULL; 277 278 hstats = &bfad->link_stats; 279 init_completion(&fcomp.comp); 280 spin_lock_irqsave(&bfad->bfad_lock, flags); 281 memset(hstats, 0, sizeof(struct fc_host_statistics)); 282 rc = bfa_port_get_stats(BFA_FCPORT(&bfad->bfa), 283 fcstats, bfad_hcb_comp, &fcomp); 284 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 285 if (rc != BFA_STATUS_OK) 286 return NULL; 287 288 wait_for_completion(&fcomp.comp); 289 290 /* Fill the fc_host_statistics structure */ 291 hstats->seconds_since_last_reset = fcstats->fc.secs_reset; 292 hstats->tx_frames = fcstats->fc.tx_frames; 293 hstats->tx_words = fcstats->fc.tx_words; 294 hstats->rx_frames = fcstats->fc.rx_frames; 295 hstats->rx_words = fcstats->fc.rx_words; 296 hstats->lip_count = fcstats->fc.lip_count; 297 hstats->nos_count = fcstats->fc.nos_count; 298 hstats->error_frames = fcstats->fc.error_frames; 299 hstats->dumped_frames = fcstats->fc.dropped_frames; 300 hstats->link_failure_count = fcstats->fc.link_failures; 301 hstats->loss_of_sync_count = fcstats->fc.loss_of_syncs; 302 hstats->loss_of_signal_count = fcstats->fc.loss_of_signals; 303 hstats->prim_seq_protocol_err_count = fcstats->fc.primseq_errs; 304 hstats->invalid_crc_count = fcstats->fc.invalid_crcs; 305 306 kfree(fcstats); 307 return hstats; 308 } 309 310 /* 311 * FC transport template entry, reset BFAD statistics. 312 */ 313 static void 314 bfad_im_reset_stats(struct Scsi_Host *shost) 315 { 316 struct bfad_im_port_s *im_port = 317 (struct bfad_im_port_s *) shost->hostdata[0]; 318 struct bfad_s *bfad = im_port->bfad; 319 struct bfad_hal_comp fcomp; 320 unsigned long flags; 321 bfa_status_t rc; 322 323 init_completion(&fcomp.comp); 324 spin_lock_irqsave(&bfad->bfad_lock, flags); 325 rc = bfa_port_clear_stats(BFA_FCPORT(&bfad->bfa), bfad_hcb_comp, 326 &fcomp); 327 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 328 329 if (rc != BFA_STATUS_OK) 330 return; 331 332 wait_for_completion(&fcomp.comp); 333 334 return; 335 } 336 337 /* 338 * FC transport template entry, get rport loss timeout. 339 */ 340 static void 341 bfad_im_get_rport_loss_tmo(struct fc_rport *rport) 342 { 343 struct bfad_itnim_data_s *itnim_data = rport->dd_data; 344 struct bfad_itnim_s *itnim = itnim_data->itnim; 345 struct bfad_s *bfad = itnim->im->bfad; 346 unsigned long flags; 347 348 spin_lock_irqsave(&bfad->bfad_lock, flags); 349 rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa); 350 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 351 } 352 353 /* 354 * FC transport template entry, set rport loss timeout. 355 */ 356 static void 357 bfad_im_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) 358 { 359 struct bfad_itnim_data_s *itnim_data = rport->dd_data; 360 struct bfad_itnim_s *itnim = itnim_data->itnim; 361 struct bfad_s *bfad = itnim->im->bfad; 362 unsigned long flags; 363 364 if (timeout > 0) { 365 spin_lock_irqsave(&bfad->bfad_lock, flags); 366 bfa_fcpim_path_tov_set(&bfad->bfa, timeout); 367 rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa); 368 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 369 } 370 371 } 372 373 static int 374 bfad_im_vport_create(struct fc_vport *fc_vport, bool disable) 375 { 376 char *vname = fc_vport->symbolic_name; 377 struct Scsi_Host *shost = fc_vport->shost; 378 struct bfad_im_port_s *im_port = 379 (struct bfad_im_port_s *) shost->hostdata[0]; 380 struct bfad_s *bfad = im_port->bfad; 381 struct bfa_lport_cfg_s port_cfg; 382 struct bfad_vport_s *vp; 383 int status = 0, rc; 384 unsigned long flags; 385 386 memset(&port_cfg, 0, sizeof(port_cfg)); 387 u64_to_wwn(fc_vport->node_name, (u8 *)&port_cfg.nwwn); 388 u64_to_wwn(fc_vport->port_name, (u8 *)&port_cfg.pwwn); 389 if (strlen(vname) > 0) 390 strcpy((char *)&port_cfg.sym_name, vname); 391 port_cfg.roles = BFA_LPORT_ROLE_FCP_IM; 392 393 spin_lock_irqsave(&bfad->bfad_lock, flags); 394 list_for_each_entry(vp, &bfad->pbc_vport_list, list_entry) { 395 if (port_cfg.pwwn == 396 vp->fcs_vport.lport.port_cfg.pwwn) { 397 port_cfg.preboot_vp = 398 vp->fcs_vport.lport.port_cfg.preboot_vp; 399 break; 400 } 401 } 402 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 403 404 rc = bfad_vport_create(bfad, 0, &port_cfg, &fc_vport->dev); 405 if (rc == BFA_STATUS_OK) { 406 struct bfad_vport_s *vport; 407 struct bfa_fcs_vport_s *fcs_vport; 408 struct Scsi_Host *vshost; 409 410 spin_lock_irqsave(&bfad->bfad_lock, flags); 411 fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, 412 port_cfg.pwwn); 413 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 414 if (fcs_vport == NULL) 415 return VPCERR_BAD_WWN; 416 417 fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE); 418 if (disable) { 419 spin_lock_irqsave(&bfad->bfad_lock, flags); 420 bfa_fcs_vport_stop(fcs_vport); 421 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 422 fc_vport_set_state(fc_vport, FC_VPORT_DISABLED); 423 } 424 425 vport = fcs_vport->vport_drv; 426 vshost = vport->drv_port.im_port->shost; 427 fc_host_node_name(vshost) = wwn_to_u64((u8 *)&port_cfg.nwwn); 428 fc_host_port_name(vshost) = wwn_to_u64((u8 *)&port_cfg.pwwn); 429 fc_host_supported_classes(vshost) = FC_COS_CLASS3; 430 431 memset(fc_host_supported_fc4s(vshost), 0, 432 sizeof(fc_host_supported_fc4s(vshost))); 433 434 /* For FCP type 0x08 */ 435 if (supported_fc4s & BFA_LPORT_ROLE_FCP_IM) 436 fc_host_supported_fc4s(vshost)[2] = 1; 437 438 /* For fibre channel services type 0x20 */ 439 fc_host_supported_fc4s(vshost)[7] = 1; 440 441 fc_host_supported_speeds(vshost) = 442 bfad_im_supported_speeds(&bfad->bfa); 443 fc_host_maxframe_size(vshost) = 444 bfa_fcport_get_maxfrsize(&bfad->bfa); 445 446 fc_vport->dd_data = vport; 447 vport->drv_port.im_port->fc_vport = fc_vport; 448 } else if (rc == BFA_STATUS_INVALID_WWN) 449 return VPCERR_BAD_WWN; 450 else if (rc == BFA_STATUS_VPORT_EXISTS) 451 return VPCERR_BAD_WWN; 452 else if (rc == BFA_STATUS_VPORT_MAX) 453 return VPCERR_NO_FABRIC_SUPP; 454 else if (rc == BFA_STATUS_VPORT_WWN_BP) 455 return VPCERR_BAD_WWN; 456 else 457 return FC_VPORT_FAILED; 458 459 return status; 460 } 461 462 int 463 bfad_im_issue_fc_host_lip(struct Scsi_Host *shost) 464 { 465 struct bfad_im_port_s *im_port = 466 (struct bfad_im_port_s *) shost->hostdata[0]; 467 struct bfad_s *bfad = im_port->bfad; 468 struct bfad_hal_comp fcomp; 469 unsigned long flags; 470 uint32_t status; 471 472 init_completion(&fcomp.comp); 473 spin_lock_irqsave(&bfad->bfad_lock, flags); 474 status = bfa_port_disable(&bfad->bfa.modules.port, 475 bfad_hcb_comp, &fcomp); 476 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 477 478 if (status != BFA_STATUS_OK) 479 return -EIO; 480 481 wait_for_completion(&fcomp.comp); 482 if (fcomp.status != BFA_STATUS_OK) 483 return -EIO; 484 485 spin_lock_irqsave(&bfad->bfad_lock, flags); 486 status = bfa_port_enable(&bfad->bfa.modules.port, 487 bfad_hcb_comp, &fcomp); 488 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 489 if (status != BFA_STATUS_OK) 490 return -EIO; 491 492 wait_for_completion(&fcomp.comp); 493 if (fcomp.status != BFA_STATUS_OK) 494 return -EIO; 495 496 return 0; 497 } 498 499 static int 500 bfad_im_vport_delete(struct fc_vport *fc_vport) 501 { 502 struct bfad_vport_s *vport = (struct bfad_vport_s *)fc_vport->dd_data; 503 struct bfad_im_port_s *im_port = 504 (struct bfad_im_port_s *) vport->drv_port.im_port; 505 struct bfad_s *bfad = im_port->bfad; 506 struct bfad_port_s *port; 507 struct bfa_fcs_vport_s *fcs_vport; 508 struct Scsi_Host *vshost; 509 wwn_t pwwn; 510 int rc; 511 unsigned long flags; 512 struct completion fcomp; 513 514 if (im_port->flags & BFAD_PORT_DELETE) { 515 bfad_scsi_host_free(bfad, im_port); 516 list_del(&vport->list_entry); 517 kfree(vport); 518 return 0; 519 } 520 521 port = im_port->port; 522 523 vshost = vport->drv_port.im_port->shost; 524 u64_to_wwn(fc_host_port_name(vshost), (u8 *)&pwwn); 525 526 spin_lock_irqsave(&bfad->bfad_lock, flags); 527 fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn); 528 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 529 530 if (fcs_vport == NULL) 531 return VPCERR_BAD_WWN; 532 533 vport->drv_port.flags |= BFAD_PORT_DELETE; 534 535 vport->comp_del = &fcomp; 536 init_completion(vport->comp_del); 537 538 spin_lock_irqsave(&bfad->bfad_lock, flags); 539 rc = bfa_fcs_vport_delete(&vport->fcs_vport); 540 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 541 542 if (rc == BFA_STATUS_PBC) { 543 vport->drv_port.flags &= ~BFAD_PORT_DELETE; 544 vport->comp_del = NULL; 545 return -1; 546 } 547 548 wait_for_completion(vport->comp_del); 549 550 bfad_scsi_host_free(bfad, im_port); 551 list_del(&vport->list_entry); 552 kfree(vport); 553 554 return 0; 555 } 556 557 static int 558 bfad_im_vport_disable(struct fc_vport *fc_vport, bool disable) 559 { 560 struct bfad_vport_s *vport; 561 struct bfad_s *bfad; 562 struct bfa_fcs_vport_s *fcs_vport; 563 struct Scsi_Host *vshost; 564 wwn_t pwwn; 565 unsigned long flags; 566 567 vport = (struct bfad_vport_s *)fc_vport->dd_data; 568 bfad = vport->drv_port.bfad; 569 vshost = vport->drv_port.im_port->shost; 570 u64_to_wwn(fc_host_port_name(vshost), (u8 *)&pwwn); 571 572 spin_lock_irqsave(&bfad->bfad_lock, flags); 573 fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn); 574 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 575 576 if (fcs_vport == NULL) 577 return VPCERR_BAD_WWN; 578 579 if (disable) { 580 bfa_fcs_vport_stop(fcs_vport); 581 fc_vport_set_state(fc_vport, FC_VPORT_DISABLED); 582 } else { 583 bfa_fcs_vport_start(fcs_vport); 584 fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE); 585 } 586 587 return 0; 588 } 589 590 void 591 bfad_im_vport_set_symbolic_name(struct fc_vport *fc_vport) 592 { 593 struct bfad_vport_s *vport = (struct bfad_vport_s *)fc_vport->dd_data; 594 struct bfad_im_port_s *im_port = 595 (struct bfad_im_port_s *)vport->drv_port.im_port; 596 struct bfad_s *bfad = im_port->bfad; 597 struct Scsi_Host *vshost = vport->drv_port.im_port->shost; 598 char *sym_name = fc_vport->symbolic_name; 599 struct bfa_fcs_vport_s *fcs_vport; 600 wwn_t pwwn; 601 unsigned long flags; 602 603 u64_to_wwn(fc_host_port_name(vshost), (u8 *)&pwwn); 604 605 spin_lock_irqsave(&bfad->bfad_lock, flags); 606 fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn); 607 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 608 609 if (fcs_vport == NULL) 610 return; 611 612 spin_lock_irqsave(&bfad->bfad_lock, flags); 613 if (strlen(sym_name) > 0) { 614 strcpy(fcs_vport->lport.port_cfg.sym_name.symname, sym_name); 615 bfa_fcs_lport_ns_util_send_rspn_id( 616 BFA_FCS_GET_NS_FROM_PORT((&fcs_vport->lport)), NULL); 617 } 618 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 619 } 620 621 struct fc_function_template bfad_im_fc_function_template = { 622 623 /* Target dynamic attributes */ 624 .get_starget_port_id = bfad_im_get_starget_port_id, 625 .show_starget_port_id = 1, 626 .get_starget_node_name = bfad_im_get_starget_node_name, 627 .show_starget_node_name = 1, 628 .get_starget_port_name = bfad_im_get_starget_port_name, 629 .show_starget_port_name = 1, 630 631 /* Host dynamic attribute */ 632 .get_host_port_id = bfad_im_get_host_port_id, 633 .show_host_port_id = 1, 634 635 /* Host fixed attributes */ 636 .show_host_node_name = 1, 637 .show_host_port_name = 1, 638 .show_host_supported_classes = 1, 639 .show_host_supported_fc4s = 1, 640 .show_host_supported_speeds = 1, 641 .show_host_maxframe_size = 1, 642 643 /* More host dynamic attributes */ 644 .show_host_port_type = 1, 645 .get_host_port_type = bfad_im_get_host_port_type, 646 .show_host_port_state = 1, 647 .get_host_port_state = bfad_im_get_host_port_state, 648 .show_host_active_fc4s = 1, 649 .get_host_active_fc4s = bfad_im_get_host_active_fc4s, 650 .show_host_speed = 1, 651 .get_host_speed = bfad_im_get_host_speed, 652 .show_host_fabric_name = 1, 653 .get_host_fabric_name = bfad_im_get_host_fabric_name, 654 655 .show_host_symbolic_name = 1, 656 657 /* Statistics */ 658 .get_fc_host_stats = bfad_im_get_stats, 659 .reset_fc_host_stats = bfad_im_reset_stats, 660 661 /* Allocation length for host specific data */ 662 .dd_fcrport_size = sizeof(struct bfad_itnim_data_s *), 663 664 /* Remote port fixed attributes */ 665 .show_rport_maxframe_size = 1, 666 .show_rport_supported_classes = 1, 667 .show_rport_dev_loss_tmo = 1, 668 .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo, 669 .set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo, 670 .issue_fc_host_lip = bfad_im_issue_fc_host_lip, 671 .vport_create = bfad_im_vport_create, 672 .vport_delete = bfad_im_vport_delete, 673 .vport_disable = bfad_im_vport_disable, 674 .set_vport_symbolic_name = bfad_im_vport_set_symbolic_name, 675 .bsg_request = bfad_im_bsg_request, 676 .bsg_timeout = bfad_im_bsg_timeout, 677 }; 678 679 struct fc_function_template bfad_im_vport_fc_function_template = { 680 681 /* Target dynamic attributes */ 682 .get_starget_port_id = bfad_im_get_starget_port_id, 683 .show_starget_port_id = 1, 684 .get_starget_node_name = bfad_im_get_starget_node_name, 685 .show_starget_node_name = 1, 686 .get_starget_port_name = bfad_im_get_starget_port_name, 687 .show_starget_port_name = 1, 688 689 /* Host dynamic attribute */ 690 .get_host_port_id = bfad_im_get_host_port_id, 691 .show_host_port_id = 1, 692 693 /* Host fixed attributes */ 694 .show_host_node_name = 1, 695 .show_host_port_name = 1, 696 .show_host_supported_classes = 1, 697 .show_host_supported_fc4s = 1, 698 .show_host_supported_speeds = 1, 699 .show_host_maxframe_size = 1, 700 701 /* More host dynamic attributes */ 702 .show_host_port_type = 1, 703 .get_host_port_type = bfad_im_get_host_port_type, 704 .show_host_port_state = 1, 705 .get_host_port_state = bfad_im_get_host_port_state, 706 .show_host_active_fc4s = 1, 707 .get_host_active_fc4s = bfad_im_get_host_active_fc4s, 708 .show_host_speed = 1, 709 .get_host_speed = bfad_im_get_host_speed, 710 .show_host_fabric_name = 1, 711 .get_host_fabric_name = bfad_im_get_host_fabric_name, 712 713 .show_host_symbolic_name = 1, 714 715 /* Statistics */ 716 .get_fc_host_stats = bfad_im_get_stats, 717 .reset_fc_host_stats = bfad_im_reset_stats, 718 719 /* Allocation length for host specific data */ 720 .dd_fcrport_size = sizeof(struct bfad_itnim_data_s *), 721 722 /* Remote port fixed attributes */ 723 .show_rport_maxframe_size = 1, 724 .show_rport_supported_classes = 1, 725 .show_rport_dev_loss_tmo = 1, 726 .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo, 727 .set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo, 728 }; 729 730 /* 731 * Scsi_Host_attrs SCSI host attributes 732 */ 733 static ssize_t 734 bfad_im_serial_num_show(struct device *dev, struct device_attribute *attr, 735 char *buf) 736 { 737 struct Scsi_Host *shost = class_to_shost(dev); 738 struct bfad_im_port_s *im_port = 739 (struct bfad_im_port_s *) shost->hostdata[0]; 740 struct bfad_s *bfad = im_port->bfad; 741 char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN]; 742 743 bfa_get_adapter_serial_num(&bfad->bfa, serial_num); 744 return snprintf(buf, PAGE_SIZE, "%s\n", serial_num); 745 } 746 747 static ssize_t 748 bfad_im_model_show(struct device *dev, struct device_attribute *attr, 749 char *buf) 750 { 751 struct Scsi_Host *shost = class_to_shost(dev); 752 struct bfad_im_port_s *im_port = 753 (struct bfad_im_port_s *) shost->hostdata[0]; 754 struct bfad_s *bfad = im_port->bfad; 755 char model[BFA_ADAPTER_MODEL_NAME_LEN]; 756 757 bfa_get_adapter_model(&bfad->bfa, model); 758 return snprintf(buf, PAGE_SIZE, "%s\n", model); 759 } 760 761 static ssize_t 762 bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr, 763 char *buf) 764 { 765 struct Scsi_Host *shost = class_to_shost(dev); 766 struct bfad_im_port_s *im_port = 767 (struct bfad_im_port_s *) shost->hostdata[0]; 768 struct bfad_s *bfad = im_port->bfad; 769 char model[BFA_ADAPTER_MODEL_NAME_LEN]; 770 char model_descr[BFA_ADAPTER_MODEL_DESCR_LEN]; 771 int nports = 0; 772 773 bfa_get_adapter_model(&bfad->bfa, model); 774 nports = bfa_get_nports(&bfad->bfa); 775 if (!strcmp(model, "Brocade-425")) 776 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 777 "Brocade 4Gbps PCIe dual port FC HBA"); 778 else if (!strcmp(model, "Brocade-825")) 779 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 780 "Brocade 8Gbps PCIe dual port FC HBA"); 781 else if (!strcmp(model, "Brocade-42B")) 782 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 783 "Brocade 4Gbps PCIe dual port FC HBA for HP"); 784 else if (!strcmp(model, "Brocade-82B")) 785 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 786 "Brocade 8Gbps PCIe dual port FC HBA for HP"); 787 else if (!strcmp(model, "Brocade-1010")) 788 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 789 "Brocade 10Gbps single port CNA"); 790 else if (!strcmp(model, "Brocade-1020")) 791 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 792 "Brocade 10Gbps dual port CNA"); 793 else if (!strcmp(model, "Brocade-1007")) 794 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 795 "Brocade 10Gbps CNA for IBM Blade Center"); 796 else if (!strcmp(model, "Brocade-415")) 797 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 798 "Brocade 4Gbps PCIe single port FC HBA"); 799 else if (!strcmp(model, "Brocade-815")) 800 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 801 "Brocade 8Gbps PCIe single port FC HBA"); 802 else if (!strcmp(model, "Brocade-41B")) 803 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 804 "Brocade 4Gbps PCIe single port FC HBA for HP"); 805 else if (!strcmp(model, "Brocade-81B")) 806 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 807 "Brocade 8Gbps PCIe single port FC HBA for HP"); 808 else if (!strcmp(model, "Brocade-804")) 809 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 810 "Brocade 8Gbps FC HBA for HP Bladesystem C-class"); 811 else if (!strcmp(model, "Brocade-1741")) 812 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 813 "Brocade 10Gbps CNA for Dell M-Series Blade Servers"); 814 else if (strstr(model, "Brocade-1860")) { 815 if (nports == 1 && bfa_ioc_is_cna(&bfad->bfa.ioc)) 816 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 817 "Brocade 10Gbps single port CNA"); 818 else if (nports == 1 && !bfa_ioc_is_cna(&bfad->bfa.ioc)) 819 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 820 "Brocade 16Gbps PCIe single port FC HBA"); 821 else if (nports == 2 && bfa_ioc_is_cna(&bfad->bfa.ioc)) 822 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 823 "Brocade 10Gbps dual port CNA"); 824 else if (nports == 2 && !bfa_ioc_is_cna(&bfad->bfa.ioc)) 825 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 826 "Brocade 16Gbps PCIe dual port FC HBA"); 827 } else if (!strcmp(model, "Brocade-1867")) { 828 if (nports == 1 && !bfa_ioc_is_cna(&bfad->bfa.ioc)) 829 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 830 "Brocade 16Gbps PCIe single port FC HBA for IBM"); 831 else if (nports == 2 && !bfa_ioc_is_cna(&bfad->bfa.ioc)) 832 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 833 "Brocade 16Gbps PCIe dual port FC HBA for IBM"); 834 } else 835 snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, 836 "Invalid Model"); 837 838 return snprintf(buf, PAGE_SIZE, "%s\n", model_descr); 839 } 840 841 static ssize_t 842 bfad_im_node_name_show(struct device *dev, struct device_attribute *attr, 843 char *buf) 844 { 845 struct Scsi_Host *shost = class_to_shost(dev); 846 struct bfad_im_port_s *im_port = 847 (struct bfad_im_port_s *) shost->hostdata[0]; 848 struct bfad_port_s *port = im_port->port; 849 u64 nwwn; 850 851 nwwn = bfa_fcs_lport_get_nwwn(port->fcs_port); 852 return snprintf(buf, PAGE_SIZE, "0x%llx\n", cpu_to_be64(nwwn)); 853 } 854 855 static ssize_t 856 bfad_im_symbolic_name_show(struct device *dev, struct device_attribute *attr, 857 char *buf) 858 { 859 struct Scsi_Host *shost = class_to_shost(dev); 860 struct bfad_im_port_s *im_port = 861 (struct bfad_im_port_s *) shost->hostdata[0]; 862 struct bfad_s *bfad = im_port->bfad; 863 struct bfa_lport_attr_s port_attr; 864 char symname[BFA_SYMNAME_MAXLEN]; 865 866 bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr); 867 strncpy(symname, port_attr.port_cfg.sym_name.symname, 868 BFA_SYMNAME_MAXLEN); 869 return snprintf(buf, PAGE_SIZE, "%s\n", symname); 870 } 871 872 static ssize_t 873 bfad_im_hw_version_show(struct device *dev, struct device_attribute *attr, 874 char *buf) 875 { 876 struct Scsi_Host *shost = class_to_shost(dev); 877 struct bfad_im_port_s *im_port = 878 (struct bfad_im_port_s *) shost->hostdata[0]; 879 struct bfad_s *bfad = im_port->bfad; 880 char hw_ver[BFA_VERSION_LEN]; 881 882 bfa_get_pci_chip_rev(&bfad->bfa, hw_ver); 883 return snprintf(buf, PAGE_SIZE, "%s\n", hw_ver); 884 } 885 886 static ssize_t 887 bfad_im_drv_version_show(struct device *dev, struct device_attribute *attr, 888 char *buf) 889 { 890 return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_VERSION); 891 } 892 893 static ssize_t 894 bfad_im_optionrom_version_show(struct device *dev, 895 struct device_attribute *attr, char *buf) 896 { 897 struct Scsi_Host *shost = class_to_shost(dev); 898 struct bfad_im_port_s *im_port = 899 (struct bfad_im_port_s *) shost->hostdata[0]; 900 struct bfad_s *bfad = im_port->bfad; 901 char optrom_ver[BFA_VERSION_LEN]; 902 903 bfa_get_adapter_optrom_ver(&bfad->bfa, optrom_ver); 904 return snprintf(buf, PAGE_SIZE, "%s\n", optrom_ver); 905 } 906 907 static ssize_t 908 bfad_im_fw_version_show(struct device *dev, struct device_attribute *attr, 909 char *buf) 910 { 911 struct Scsi_Host *shost = class_to_shost(dev); 912 struct bfad_im_port_s *im_port = 913 (struct bfad_im_port_s *) shost->hostdata[0]; 914 struct bfad_s *bfad = im_port->bfad; 915 char fw_ver[BFA_VERSION_LEN]; 916 917 bfa_get_adapter_fw_ver(&bfad->bfa, fw_ver); 918 return snprintf(buf, PAGE_SIZE, "%s\n", fw_ver); 919 } 920 921 static ssize_t 922 bfad_im_num_of_ports_show(struct device *dev, struct device_attribute *attr, 923 char *buf) 924 { 925 struct Scsi_Host *shost = class_to_shost(dev); 926 struct bfad_im_port_s *im_port = 927 (struct bfad_im_port_s *) shost->hostdata[0]; 928 struct bfad_s *bfad = im_port->bfad; 929 930 return snprintf(buf, PAGE_SIZE, "%d\n", 931 bfa_get_nports(&bfad->bfa)); 932 } 933 934 static ssize_t 935 bfad_im_drv_name_show(struct device *dev, struct device_attribute *attr, 936 char *buf) 937 { 938 return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_NAME); 939 } 940 941 static ssize_t 942 bfad_im_num_of_discovered_ports_show(struct device *dev, 943 struct device_attribute *attr, char *buf) 944 { 945 struct Scsi_Host *shost = class_to_shost(dev); 946 struct bfad_im_port_s *im_port = 947 (struct bfad_im_port_s *) shost->hostdata[0]; 948 struct bfad_port_s *port = im_port->port; 949 struct bfad_s *bfad = im_port->bfad; 950 int nrports = 2048; 951 struct bfa_rport_qualifier_s *rports = NULL; 952 unsigned long flags; 953 954 rports = kzalloc(sizeof(struct bfa_rport_qualifier_s) * nrports, 955 GFP_ATOMIC); 956 if (rports == NULL) 957 return snprintf(buf, PAGE_SIZE, "Failed\n"); 958 959 spin_lock_irqsave(&bfad->bfad_lock, flags); 960 bfa_fcs_lport_get_rport_quals(port->fcs_port, rports, &nrports); 961 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 962 kfree(rports); 963 964 return snprintf(buf, PAGE_SIZE, "%d\n", nrports); 965 } 966 967 static DEVICE_ATTR(serial_number, S_IRUGO, 968 bfad_im_serial_num_show, NULL); 969 static DEVICE_ATTR(model, S_IRUGO, bfad_im_model_show, NULL); 970 static DEVICE_ATTR(model_description, S_IRUGO, 971 bfad_im_model_desc_show, NULL); 972 static DEVICE_ATTR(node_name, S_IRUGO, bfad_im_node_name_show, NULL); 973 static DEVICE_ATTR(symbolic_name, S_IRUGO, 974 bfad_im_symbolic_name_show, NULL); 975 static DEVICE_ATTR(hardware_version, S_IRUGO, 976 bfad_im_hw_version_show, NULL); 977 static DEVICE_ATTR(driver_version, S_IRUGO, 978 bfad_im_drv_version_show, NULL); 979 static DEVICE_ATTR(option_rom_version, S_IRUGO, 980 bfad_im_optionrom_version_show, NULL); 981 static DEVICE_ATTR(firmware_version, S_IRUGO, 982 bfad_im_fw_version_show, NULL); 983 static DEVICE_ATTR(number_of_ports, S_IRUGO, 984 bfad_im_num_of_ports_show, NULL); 985 static DEVICE_ATTR(driver_name, S_IRUGO, bfad_im_drv_name_show, NULL); 986 static DEVICE_ATTR(number_of_discovered_ports, S_IRUGO, 987 bfad_im_num_of_discovered_ports_show, NULL); 988 989 struct device_attribute *bfad_im_host_attrs[] = { 990 &dev_attr_serial_number, 991 &dev_attr_model, 992 &dev_attr_model_description, 993 &dev_attr_node_name, 994 &dev_attr_symbolic_name, 995 &dev_attr_hardware_version, 996 &dev_attr_driver_version, 997 &dev_attr_option_rom_version, 998 &dev_attr_firmware_version, 999 &dev_attr_number_of_ports, 1000 &dev_attr_driver_name, 1001 &dev_attr_number_of_discovered_ports, 1002 NULL, 1003 }; 1004 1005 struct device_attribute *bfad_im_vport_attrs[] = { 1006 &dev_attr_serial_number, 1007 &dev_attr_model, 1008 &dev_attr_model_description, 1009 &dev_attr_node_name, 1010 &dev_attr_symbolic_name, 1011 &dev_attr_hardware_version, 1012 &dev_attr_driver_version, 1013 &dev_attr_option_rom_version, 1014 &dev_attr_firmware_version, 1015 &dev_attr_number_of_ports, 1016 &dev_attr_driver_name, 1017 &dev_attr_number_of_discovered_ports, 1018 NULL, 1019 }; 1020 1021 1022