1 /* 2 * This file is part of the Chelsio FCoE driver for Linux. 3 * 4 * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved. 5 * 6 * This software is available to you under a choice of one of two 7 * licenses. You may choose to be licensed under the terms of the GNU 8 * General Public License (GPL) Version 2, available from the file 9 * COPYING in the main directory of this source tree, or the 10 * OpenIB.org BSD license below: 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * - Redistributions of source code must retain the above 17 * copyright notice, this list of conditions and the following 18 * disclaimer. 19 * 20 * - Redistributions in binary form must reproduce the above 21 * copyright notice, this list of conditions and the following 22 * disclaimer in the documentation and/or other materials 23 * provided with the distribution. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 * SOFTWARE. 33 */ 34 35 #include <linux/kernel.h> 36 #include <linux/string.h> 37 #include <linux/delay.h> 38 #include <linux/module.h> 39 #include <linux/init.h> 40 #include <linux/pci.h> 41 #include <linux/mm.h> 42 #include <linux/jiffies.h> 43 #include <scsi/fc/fc_fs.h> 44 45 #include "csio_init.h" 46 47 static void 48 csio_vport_set_state(struct csio_lnode *ln); 49 50 /* 51 * csio_reg_rnode - Register a remote port with FC transport. 52 * @rn: Rnode representing remote port. 53 * 54 * Call fc_remote_port_add() to register this remote port with FC transport. 55 * If remote port is Initiator OR Target OR both, change the role appropriately. 56 * 57 */ 58 void 59 csio_reg_rnode(struct csio_rnode *rn) 60 { 61 struct csio_lnode *ln = csio_rnode_to_lnode(rn); 62 struct Scsi_Host *shost = csio_ln_to_shost(ln); 63 struct fc_rport_identifiers ids; 64 struct fc_rport *rport; 65 struct csio_service_parms *sp; 66 67 ids.node_name = wwn_to_u64(csio_rn_wwnn(rn)); 68 ids.port_name = wwn_to_u64(csio_rn_wwpn(rn)); 69 ids.port_id = rn->nport_id; 70 ids.roles = FC_RPORT_ROLE_UNKNOWN; 71 72 if (rn->role & CSIO_RNFR_INITIATOR || rn->role & CSIO_RNFR_TARGET) { 73 rport = rn->rport; 74 CSIO_ASSERT(rport != NULL); 75 goto update_role; 76 } 77 78 rn->rport = fc_remote_port_add(shost, 0, &ids); 79 if (!rn->rport) { 80 csio_ln_err(ln, "Failed to register rport = 0x%x.\n", 81 rn->nport_id); 82 return; 83 } 84 85 ln->num_reg_rnodes++; 86 rport = rn->rport; 87 spin_lock_irq(shost->host_lock); 88 *((struct csio_rnode **)rport->dd_data) = rn; 89 spin_unlock_irq(shost->host_lock); 90 91 sp = &rn->rn_sparm; 92 rport->maxframe_size = ntohs(sp->csp.sp_bb_data); 93 if (ntohs(sp->clsp[2].cp_class) & FC_CPC_VALID) 94 rport->supported_classes = FC_COS_CLASS3; 95 else 96 rport->supported_classes = FC_COS_UNSPECIFIED; 97 update_role: 98 if (rn->role & CSIO_RNFR_INITIATOR) 99 ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; 100 if (rn->role & CSIO_RNFR_TARGET) 101 ids.roles |= FC_RPORT_ROLE_FCP_TARGET; 102 103 if (ids.roles != FC_RPORT_ROLE_UNKNOWN) 104 fc_remote_port_rolechg(rport, ids.roles); 105 106 rn->scsi_id = rport->scsi_target_id; 107 108 csio_ln_dbg(ln, "Remote port x%x role 0x%x registered\n", 109 rn->nport_id, ids.roles); 110 } 111 112 /* 113 * csio_unreg_rnode - Unregister a remote port with FC transport. 114 * @rn: Rnode representing remote port. 115 * 116 * Call fc_remote_port_delete() to unregister this remote port with FC 117 * transport. 118 * 119 */ 120 void 121 csio_unreg_rnode(struct csio_rnode *rn) 122 { 123 struct csio_lnode *ln = csio_rnode_to_lnode(rn); 124 struct fc_rport *rport = rn->rport; 125 126 rn->role &= ~(CSIO_RNFR_INITIATOR | CSIO_RNFR_TARGET); 127 fc_remote_port_delete(rport); 128 ln->num_reg_rnodes--; 129 130 csio_ln_dbg(ln, "Remote port x%x un-registered\n", rn->nport_id); 131 } 132 133 /* 134 * csio_lnode_async_event - Async events from local port. 135 * @ln: lnode representing local port. 136 * 137 * Async events from local node that FC transport/SCSI ML 138 * should be made aware of (Eg: RSCN). 139 */ 140 void 141 csio_lnode_async_event(struct csio_lnode *ln, enum csio_ln_fc_evt fc_evt) 142 { 143 switch (fc_evt) { 144 case CSIO_LN_FC_RSCN: 145 /* Get payload of rscn from ln */ 146 /* For each RSCN entry */ 147 /* 148 * fc_host_post_event(shost, 149 * fc_get_event_number(), 150 * FCH_EVT_RSCN, 151 * rscn_entry); 152 */ 153 break; 154 case CSIO_LN_FC_LINKUP: 155 /* send fc_host_post_event */ 156 /* set vport state */ 157 if (csio_is_npiv_ln(ln)) 158 csio_vport_set_state(ln); 159 160 break; 161 case CSIO_LN_FC_LINKDOWN: 162 /* send fc_host_post_event */ 163 /* set vport state */ 164 if (csio_is_npiv_ln(ln)) 165 csio_vport_set_state(ln); 166 167 break; 168 case CSIO_LN_FC_ATTRIB_UPDATE: 169 csio_fchost_attr_init(ln); 170 break; 171 default: 172 break; 173 } 174 } 175 176 /* 177 * csio_fchost_attr_init - Initialize FC transport attributes 178 * @ln: Lnode. 179 * 180 */ 181 void 182 csio_fchost_attr_init(struct csio_lnode *ln) 183 { 184 struct Scsi_Host *shost = csio_ln_to_shost(ln); 185 186 fc_host_node_name(shost) = wwn_to_u64(csio_ln_wwnn(ln)); 187 fc_host_port_name(shost) = wwn_to_u64(csio_ln_wwpn(ln)); 188 189 fc_host_supported_classes(shost) = FC_COS_CLASS3; 190 fc_host_max_npiv_vports(shost) = 191 (csio_lnode_to_hw(ln))->fres_info.max_vnps; 192 fc_host_supported_speeds(shost) = FC_PORTSPEED_10GBIT | 193 FC_PORTSPEED_1GBIT; 194 195 fc_host_maxframe_size(shost) = ntohs(ln->ln_sparm.csp.sp_bb_data); 196 memset(fc_host_supported_fc4s(shost), 0, 197 sizeof(fc_host_supported_fc4s(shost))); 198 fc_host_supported_fc4s(shost)[7] = 1; 199 200 memset(fc_host_active_fc4s(shost), 0, 201 sizeof(fc_host_active_fc4s(shost))); 202 fc_host_active_fc4s(shost)[7] = 1; 203 } 204 205 /* 206 * csio_get_host_port_id - sysfs entries for nport_id is 207 * populated/cached from this function 208 */ 209 static void 210 csio_get_host_port_id(struct Scsi_Host *shost) 211 { 212 struct csio_lnode *ln = shost_priv(shost); 213 struct csio_hw *hw = csio_lnode_to_hw(ln); 214 215 spin_lock_irq(&hw->lock); 216 fc_host_port_id(shost) = ln->nport_id; 217 spin_unlock_irq(&hw->lock); 218 } 219 220 /* 221 * csio_get_port_type - Return FC local port type. 222 * @shost: scsi host. 223 * 224 */ 225 static void 226 csio_get_host_port_type(struct Scsi_Host *shost) 227 { 228 struct csio_lnode *ln = shost_priv(shost); 229 struct csio_hw *hw = csio_lnode_to_hw(ln); 230 231 spin_lock_irq(&hw->lock); 232 if (csio_is_npiv_ln(ln)) 233 fc_host_port_type(shost) = FC_PORTTYPE_NPIV; 234 else 235 fc_host_port_type(shost) = FC_PORTTYPE_NPORT; 236 spin_unlock_irq(&hw->lock); 237 } 238 239 /* 240 * csio_get_port_state - Return FC local port state. 241 * @shost: scsi host. 242 * 243 */ 244 static void 245 csio_get_host_port_state(struct Scsi_Host *shost) 246 { 247 struct csio_lnode *ln = shost_priv(shost); 248 struct csio_hw *hw = csio_lnode_to_hw(ln); 249 char state[16]; 250 251 spin_lock_irq(&hw->lock); 252 253 csio_lnode_state_to_str(ln, state); 254 if (!strcmp(state, "READY")) 255 fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; 256 else if (!strcmp(state, "OFFLINE")) 257 fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN; 258 else 259 fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN; 260 261 spin_unlock_irq(&hw->lock); 262 } 263 264 /* 265 * csio_get_host_speed - Return link speed to FC transport. 266 * @shost: scsi host. 267 * 268 */ 269 static void 270 csio_get_host_speed(struct Scsi_Host *shost) 271 { 272 struct csio_lnode *ln = shost_priv(shost); 273 struct csio_hw *hw = csio_lnode_to_hw(ln); 274 275 spin_lock_irq(&hw->lock); 276 switch (hw->pport[ln->portid].link_speed) { 277 case FW_PORT_CAP_SPEED_1G: 278 fc_host_speed(shost) = FC_PORTSPEED_1GBIT; 279 break; 280 case FW_PORT_CAP_SPEED_10G: 281 fc_host_speed(shost) = FC_PORTSPEED_10GBIT; 282 break; 283 default: 284 fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; 285 break; 286 } 287 spin_unlock_irq(&hw->lock); 288 } 289 290 /* 291 * csio_get_host_fabric_name - Return fabric name 292 * @shost: scsi host. 293 * 294 */ 295 static void 296 csio_get_host_fabric_name(struct Scsi_Host *shost) 297 { 298 struct csio_lnode *ln = shost_priv(shost); 299 struct csio_rnode *rn = NULL; 300 struct csio_hw *hw = csio_lnode_to_hw(ln); 301 302 spin_lock_irq(&hw->lock); 303 rn = csio_rnode_lookup_portid(ln, FC_FID_FLOGI); 304 if (rn) 305 fc_host_fabric_name(shost) = wwn_to_u64(csio_rn_wwnn(rn)); 306 else 307 fc_host_fabric_name(shost) = 0; 308 spin_unlock_irq(&hw->lock); 309 } 310 311 /* 312 * csio_get_host_speed - Return FC transport statistics. 313 * @ln: Lnode. 314 * 315 */ 316 static struct fc_host_statistics * 317 csio_get_stats(struct Scsi_Host *shost) 318 { 319 struct csio_lnode *ln = shost_priv(shost); 320 struct csio_hw *hw = csio_lnode_to_hw(ln); 321 struct fc_host_statistics *fhs = &ln->fch_stats; 322 struct fw_fcoe_port_stats fcoe_port_stats; 323 uint64_t seconds; 324 325 memset(&fcoe_port_stats, 0, sizeof(struct fw_fcoe_port_stats)); 326 csio_get_phy_port_stats(hw, ln->portid, &fcoe_port_stats); 327 328 fhs->tx_frames += (be64_to_cpu(fcoe_port_stats.tx_bcast_frames) + 329 be64_to_cpu(fcoe_port_stats.tx_mcast_frames) + 330 be64_to_cpu(fcoe_port_stats.tx_ucast_frames) + 331 be64_to_cpu(fcoe_port_stats.tx_offload_frames)); 332 fhs->tx_words += (be64_to_cpu(fcoe_port_stats.tx_bcast_bytes) + 333 be64_to_cpu(fcoe_port_stats.tx_mcast_bytes) + 334 be64_to_cpu(fcoe_port_stats.tx_ucast_bytes) + 335 be64_to_cpu(fcoe_port_stats.tx_offload_bytes)) / 336 CSIO_WORD_TO_BYTE; 337 fhs->rx_frames += (be64_to_cpu(fcoe_port_stats.rx_bcast_frames) + 338 be64_to_cpu(fcoe_port_stats.rx_mcast_frames) + 339 be64_to_cpu(fcoe_port_stats.rx_ucast_frames)); 340 fhs->rx_words += (be64_to_cpu(fcoe_port_stats.rx_bcast_bytes) + 341 be64_to_cpu(fcoe_port_stats.rx_mcast_bytes) + 342 be64_to_cpu(fcoe_port_stats.rx_ucast_bytes)) / 343 CSIO_WORD_TO_BYTE; 344 fhs->error_frames += be64_to_cpu(fcoe_port_stats.rx_err_frames); 345 fhs->fcp_input_requests += ln->stats.n_input_requests; 346 fhs->fcp_output_requests += ln->stats.n_output_requests; 347 fhs->fcp_control_requests += ln->stats.n_control_requests; 348 fhs->fcp_input_megabytes += ln->stats.n_input_bytes >> 20; 349 fhs->fcp_output_megabytes += ln->stats.n_output_bytes >> 20; 350 fhs->link_failure_count = ln->stats.n_link_down; 351 /* Reset stats for the device */ 352 seconds = jiffies_to_msecs(jiffies) - hw->stats.n_reset_start; 353 do_div(seconds, 1000); 354 fhs->seconds_since_last_reset = seconds; 355 356 return fhs; 357 } 358 359 /* 360 * csio_set_rport_loss_tmo - Set the rport dev loss timeout 361 * @rport: fc rport. 362 * @timeout: new value for dev loss tmo. 363 * 364 * If timeout is non zero set the dev_loss_tmo to timeout, else set 365 * dev_loss_tmo to one. 366 */ 367 static void 368 csio_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) 369 { 370 if (timeout) 371 rport->dev_loss_tmo = timeout; 372 else 373 rport->dev_loss_tmo = 1; 374 } 375 376 static void 377 csio_vport_set_state(struct csio_lnode *ln) 378 { 379 struct fc_vport *fc_vport = ln->fc_vport; 380 struct csio_lnode *pln = ln->pln; 381 char state[16]; 382 383 /* Set fc vport state based on phyiscal lnode */ 384 csio_lnode_state_to_str(pln, state); 385 if (strcmp(state, "READY")) { 386 fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN); 387 return; 388 } 389 390 if (!(pln->flags & CSIO_LNF_NPIVSUPP)) { 391 fc_vport_set_state(fc_vport, FC_VPORT_NO_FABRIC_SUPP); 392 return; 393 } 394 395 /* Set fc vport state based on virtual lnode */ 396 csio_lnode_state_to_str(ln, state); 397 if (strcmp(state, "READY")) { 398 fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN); 399 return; 400 } 401 fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE); 402 } 403 404 static int 405 csio_fcoe_alloc_vnp(struct csio_hw *hw, struct csio_lnode *ln) 406 { 407 struct csio_lnode *pln; 408 struct csio_mb *mbp; 409 struct fw_fcoe_vnp_cmd *rsp; 410 int ret = 0; 411 int retry = 0; 412 413 /* Issue VNP cmd to alloc vport */ 414 /* Allocate Mbox request */ 415 spin_lock_irq(&hw->lock); 416 mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC); 417 if (!mbp) { 418 CSIO_INC_STATS(hw, n_err_nomem); 419 ret = -ENOMEM; 420 goto out; 421 } 422 423 pln = ln->pln; 424 ln->fcf_flowid = pln->fcf_flowid; 425 ln->portid = pln->portid; 426 427 csio_fcoe_vnp_alloc_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO, 428 pln->fcf_flowid, pln->vnp_flowid, 0, 429 csio_ln_wwnn(ln), csio_ln_wwpn(ln), NULL); 430 431 for (retry = 0; retry < 3; retry++) { 432 /* FW is expected to complete vnp cmd in immediate mode 433 * without much delay. 434 * Otherwise, there will be increase in IO latency since HW 435 * lock is held till completion of vnp mbox cmd. 436 */ 437 ret = csio_mb_issue(hw, mbp); 438 if (ret != -EBUSY) 439 break; 440 441 /* Retry if mbox returns busy */ 442 spin_unlock_irq(&hw->lock); 443 msleep(2000); 444 spin_lock_irq(&hw->lock); 445 } 446 447 if (ret) { 448 csio_ln_err(ln, "Failed to issue mbox FCoE VNP command\n"); 449 goto out_free; 450 } 451 452 /* Process Mbox response of VNP command */ 453 rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb); 454 if (FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)) != FW_SUCCESS) { 455 csio_ln_err(ln, "FCOE VNP ALLOC cmd returned 0x%x!\n", 456 FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16))); 457 ret = -EINVAL; 458 goto out_free; 459 } 460 461 ln->vnp_flowid = FW_FCOE_VNP_CMD_VNPI_GET( 462 ntohl(rsp->gen_wwn_to_vnpi)); 463 memcpy(csio_ln_wwnn(ln), rsp->vnport_wwnn, 8); 464 memcpy(csio_ln_wwpn(ln), rsp->vnport_wwpn, 8); 465 466 csio_ln_dbg(ln, "FCOE VNPI: 0x%x\n", ln->vnp_flowid); 467 csio_ln_dbg(ln, "\tWWNN: %x%x%x%x%x%x%x%x\n", 468 ln->ln_sparm.wwnn[0], ln->ln_sparm.wwnn[1], 469 ln->ln_sparm.wwnn[2], ln->ln_sparm.wwnn[3], 470 ln->ln_sparm.wwnn[4], ln->ln_sparm.wwnn[5], 471 ln->ln_sparm.wwnn[6], ln->ln_sparm.wwnn[7]); 472 csio_ln_dbg(ln, "\tWWPN: %x%x%x%x%x%x%x%x\n", 473 ln->ln_sparm.wwpn[0], ln->ln_sparm.wwpn[1], 474 ln->ln_sparm.wwpn[2], ln->ln_sparm.wwpn[3], 475 ln->ln_sparm.wwpn[4], ln->ln_sparm.wwpn[5], 476 ln->ln_sparm.wwpn[6], ln->ln_sparm.wwpn[7]); 477 478 out_free: 479 mempool_free(mbp, hw->mb_mempool); 480 out: 481 spin_unlock_irq(&hw->lock); 482 return ret; 483 } 484 485 static int 486 csio_fcoe_free_vnp(struct csio_hw *hw, struct csio_lnode *ln) 487 { 488 struct csio_lnode *pln; 489 struct csio_mb *mbp; 490 struct fw_fcoe_vnp_cmd *rsp; 491 int ret = 0; 492 int retry = 0; 493 494 /* Issue VNP cmd to free vport */ 495 /* Allocate Mbox request */ 496 497 spin_lock_irq(&hw->lock); 498 mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC); 499 if (!mbp) { 500 CSIO_INC_STATS(hw, n_err_nomem); 501 ret = -ENOMEM; 502 goto out; 503 } 504 505 pln = ln->pln; 506 507 csio_fcoe_vnp_free_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO, 508 ln->fcf_flowid, ln->vnp_flowid, 509 NULL); 510 511 for (retry = 0; retry < 3; retry++) { 512 ret = csio_mb_issue(hw, mbp); 513 if (ret != -EBUSY) 514 break; 515 516 /* Retry if mbox returns busy */ 517 spin_unlock_irq(&hw->lock); 518 msleep(2000); 519 spin_lock_irq(&hw->lock); 520 } 521 522 if (ret) { 523 csio_ln_err(ln, "Failed to issue mbox FCoE VNP command\n"); 524 goto out_free; 525 } 526 527 /* Process Mbox response of VNP command */ 528 rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb); 529 if (FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)) != FW_SUCCESS) { 530 csio_ln_err(ln, "FCOE VNP FREE cmd returned 0x%x!\n", 531 FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16))); 532 ret = -EINVAL; 533 } 534 535 out_free: 536 mempool_free(mbp, hw->mb_mempool); 537 out: 538 spin_unlock_irq(&hw->lock); 539 return ret; 540 } 541 542 static int 543 csio_vport_create(struct fc_vport *fc_vport, bool disable) 544 { 545 struct Scsi_Host *shost = fc_vport->shost; 546 struct csio_lnode *pln = shost_priv(shost); 547 struct csio_lnode *ln = NULL; 548 struct csio_hw *hw = csio_lnode_to_hw(pln); 549 uint8_t wwn[8]; 550 int ret = -1; 551 552 ln = csio_shost_init(hw, &fc_vport->dev, false, pln); 553 if (!ln) 554 goto error; 555 556 if (fc_vport->node_name != 0) { 557 u64_to_wwn(fc_vport->node_name, wwn); 558 559 if (!CSIO_VALID_WWN(wwn)) { 560 csio_ln_err(ln, 561 "vport create failed. Invalid wwnn\n"); 562 goto error; 563 } 564 memcpy(csio_ln_wwnn(ln), wwn, 8); 565 } 566 567 if (fc_vport->port_name != 0) { 568 u64_to_wwn(fc_vport->port_name, wwn); 569 570 if (!CSIO_VALID_WWN(wwn)) { 571 csio_ln_err(ln, 572 "vport create failed. Invalid wwpn\n"); 573 goto error; 574 } 575 576 if (csio_lnode_lookup_by_wwpn(hw, wwn)) { 577 csio_ln_err(ln, 578 "vport create failed. wwpn already exists\n"); 579 goto error; 580 } 581 memcpy(csio_ln_wwpn(ln), wwn, 8); 582 } 583 584 fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING); 585 586 if (csio_fcoe_alloc_vnp(hw, ln)) 587 goto error; 588 589 *(struct csio_lnode **)fc_vport->dd_data = ln; 590 ln->fc_vport = fc_vport; 591 if (!fc_vport->node_name) 592 fc_vport->node_name = wwn_to_u64(csio_ln_wwnn(ln)); 593 if (!fc_vport->port_name) 594 fc_vport->port_name = wwn_to_u64(csio_ln_wwpn(ln)); 595 csio_fchost_attr_init(ln); 596 return 0; 597 error: 598 if (ln) 599 csio_shost_exit(ln); 600 601 return ret; 602 } 603 604 static int 605 csio_vport_delete(struct fc_vport *fc_vport) 606 { 607 struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data; 608 struct Scsi_Host *shost = csio_ln_to_shost(ln); 609 struct csio_hw *hw = csio_lnode_to_hw(ln); 610 int rmv; 611 612 spin_lock_irq(&hw->lock); 613 rmv = csio_is_hw_removing(hw); 614 spin_unlock_irq(&hw->lock); 615 616 if (rmv) { 617 csio_shost_exit(ln); 618 return 0; 619 } 620 621 /* Quiesce ios and send remove event to lnode */ 622 scsi_block_requests(shost); 623 spin_lock_irq(&hw->lock); 624 csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln); 625 csio_lnode_close(ln); 626 spin_unlock_irq(&hw->lock); 627 scsi_unblock_requests(shost); 628 629 /* Free vnp */ 630 if (fc_vport->vport_state != FC_VPORT_DISABLED) 631 csio_fcoe_free_vnp(hw, ln); 632 633 csio_shost_exit(ln); 634 return 0; 635 } 636 637 static int 638 csio_vport_disable(struct fc_vport *fc_vport, bool disable) 639 { 640 struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data; 641 struct Scsi_Host *shost = csio_ln_to_shost(ln); 642 struct csio_hw *hw = csio_lnode_to_hw(ln); 643 644 /* disable vport */ 645 if (disable) { 646 /* Quiesce ios and send stop event to lnode */ 647 scsi_block_requests(shost); 648 spin_lock_irq(&hw->lock); 649 csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln); 650 csio_lnode_stop(ln); 651 spin_unlock_irq(&hw->lock); 652 scsi_unblock_requests(shost); 653 654 /* Free vnp */ 655 csio_fcoe_free_vnp(hw, ln); 656 fc_vport_set_state(fc_vport, FC_VPORT_DISABLED); 657 csio_ln_err(ln, "vport disabled\n"); 658 return 0; 659 } else { 660 /* enable vport */ 661 fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING); 662 if (csio_fcoe_alloc_vnp(hw, ln)) { 663 csio_ln_err(ln, "vport enabled failed.\n"); 664 return -1; 665 } 666 csio_ln_err(ln, "vport enabled\n"); 667 return 0; 668 } 669 } 670 671 static void 672 csio_dev_loss_tmo_callbk(struct fc_rport *rport) 673 { 674 struct csio_rnode *rn; 675 struct csio_hw *hw; 676 struct csio_lnode *ln; 677 678 rn = *((struct csio_rnode **)rport->dd_data); 679 ln = csio_rnode_to_lnode(rn); 680 hw = csio_lnode_to_hw(ln); 681 682 spin_lock_irq(&hw->lock); 683 684 /* return if driver is being removed or same rnode comes back online */ 685 if (csio_is_hw_removing(hw) || csio_is_rnode_ready(rn)) 686 goto out; 687 688 csio_ln_dbg(ln, "devloss timeout on rnode:%p portid:x%x flowid:x%x\n", 689 rn, rn->nport_id, csio_rn_flowid(rn)); 690 691 CSIO_INC_STATS(ln, n_dev_loss_tmo); 692 693 /* 694 * enqueue devloss event to event worker thread to serialize all 695 * rnode events. 696 */ 697 if (csio_enqueue_evt(hw, CSIO_EVT_DEV_LOSS, &rn, sizeof(rn))) { 698 CSIO_INC_STATS(hw, n_evt_drop); 699 goto out; 700 } 701 702 if (!(hw->flags & CSIO_HWF_FWEVT_PENDING)) { 703 hw->flags |= CSIO_HWF_FWEVT_PENDING; 704 spin_unlock_irq(&hw->lock); 705 schedule_work(&hw->evtq_work); 706 return; 707 } 708 709 out: 710 spin_unlock_irq(&hw->lock); 711 } 712 713 /* FC transport functions template - Physical port */ 714 struct fc_function_template csio_fc_transport_funcs = { 715 .show_host_node_name = 1, 716 .show_host_port_name = 1, 717 .show_host_supported_classes = 1, 718 .show_host_supported_fc4s = 1, 719 .show_host_maxframe_size = 1, 720 721 .get_host_port_id = csio_get_host_port_id, 722 .show_host_port_id = 1, 723 724 .get_host_port_type = csio_get_host_port_type, 725 .show_host_port_type = 1, 726 727 .get_host_port_state = csio_get_host_port_state, 728 .show_host_port_state = 1, 729 730 .show_host_active_fc4s = 1, 731 .get_host_speed = csio_get_host_speed, 732 .show_host_speed = 1, 733 .get_host_fabric_name = csio_get_host_fabric_name, 734 .show_host_fabric_name = 1, 735 736 .get_fc_host_stats = csio_get_stats, 737 738 .dd_fcrport_size = sizeof(struct csio_rnode *), 739 .show_rport_maxframe_size = 1, 740 .show_rport_supported_classes = 1, 741 742 .set_rport_dev_loss_tmo = csio_set_rport_loss_tmo, 743 .show_rport_dev_loss_tmo = 1, 744 745 .show_starget_port_id = 1, 746 .show_starget_node_name = 1, 747 .show_starget_port_name = 1, 748 749 .dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk, 750 .dd_fcvport_size = sizeof(struct csio_lnode *), 751 752 .vport_create = csio_vport_create, 753 .vport_disable = csio_vport_disable, 754 .vport_delete = csio_vport_delete, 755 }; 756 757 /* FC transport functions template - Virtual port */ 758 struct fc_function_template csio_fc_transport_vport_funcs = { 759 .show_host_node_name = 1, 760 .show_host_port_name = 1, 761 .show_host_supported_classes = 1, 762 .show_host_supported_fc4s = 1, 763 .show_host_maxframe_size = 1, 764 765 .get_host_port_id = csio_get_host_port_id, 766 .show_host_port_id = 1, 767 768 .get_host_port_type = csio_get_host_port_type, 769 .show_host_port_type = 1, 770 771 .get_host_port_state = csio_get_host_port_state, 772 .show_host_port_state = 1, 773 .show_host_active_fc4s = 1, 774 775 .get_host_speed = csio_get_host_speed, 776 .show_host_speed = 1, 777 778 .get_host_fabric_name = csio_get_host_fabric_name, 779 .show_host_fabric_name = 1, 780 781 .get_fc_host_stats = csio_get_stats, 782 783 .dd_fcrport_size = sizeof(struct csio_rnode *), 784 .show_rport_maxframe_size = 1, 785 .show_rport_supported_classes = 1, 786 787 .set_rport_dev_loss_tmo = csio_set_rport_loss_tmo, 788 .show_rport_dev_loss_tmo = 1, 789 790 .show_starget_port_id = 1, 791 .show_starget_node_name = 1, 792 .show_starget_port_name = 1, 793 794 .dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk, 795 796 }; 797