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