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