csio_attr.c (21349B)
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 47static void 48csio_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 */ 58void 59csio_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; 97update_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 */ 120void 121csio_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 */ 140void 141csio_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 */ 181void 182csio_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 */ 209static void 210csio_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 */ 225static void 226csio_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 */ 244static void 245csio_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 */ 269static void 270csio_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_CAP32_SPEED_1G: 278 fc_host_speed(shost) = FC_PORTSPEED_1GBIT; 279 break; 280 case FW_PORT_CAP32_SPEED_10G: 281 fc_host_speed(shost) = FC_PORTSPEED_10GBIT; 282 break; 283 case FW_PORT_CAP32_SPEED_25G: 284 fc_host_speed(shost) = FC_PORTSPEED_25GBIT; 285 break; 286 case FW_PORT_CAP32_SPEED_40G: 287 fc_host_speed(shost) = FC_PORTSPEED_40GBIT; 288 break; 289 case FW_PORT_CAP32_SPEED_50G: 290 fc_host_speed(shost) = FC_PORTSPEED_50GBIT; 291 break; 292 case FW_PORT_CAP32_SPEED_100G: 293 fc_host_speed(shost) = FC_PORTSPEED_100GBIT; 294 break; 295 default: 296 fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; 297 break; 298 } 299 spin_unlock_irq(&hw->lock); 300} 301 302/* 303 * csio_get_host_fabric_name - Return fabric name 304 * @shost: scsi host. 305 * 306 */ 307static void 308csio_get_host_fabric_name(struct Scsi_Host *shost) 309{ 310 struct csio_lnode *ln = shost_priv(shost); 311 struct csio_rnode *rn = NULL; 312 struct csio_hw *hw = csio_lnode_to_hw(ln); 313 314 spin_lock_irq(&hw->lock); 315 rn = csio_rnode_lookup_portid(ln, FC_FID_FLOGI); 316 if (rn) 317 fc_host_fabric_name(shost) = wwn_to_u64(csio_rn_wwnn(rn)); 318 else 319 fc_host_fabric_name(shost) = 0; 320 spin_unlock_irq(&hw->lock); 321} 322 323/* 324 * csio_get_host_speed - Return FC transport statistics. 325 * @ln: Lnode. 326 * 327 */ 328static struct fc_host_statistics * 329csio_get_stats(struct Scsi_Host *shost) 330{ 331 struct csio_lnode *ln = shost_priv(shost); 332 struct csio_hw *hw = csio_lnode_to_hw(ln); 333 struct fc_host_statistics *fhs = &ln->fch_stats; 334 struct fw_fcoe_port_stats fcoe_port_stats; 335 uint64_t seconds; 336 337 memset(&fcoe_port_stats, 0, sizeof(struct fw_fcoe_port_stats)); 338 csio_get_phy_port_stats(hw, ln->portid, &fcoe_port_stats); 339 340 fhs->tx_frames += (be64_to_cpu(fcoe_port_stats.tx_bcast_frames) + 341 be64_to_cpu(fcoe_port_stats.tx_mcast_frames) + 342 be64_to_cpu(fcoe_port_stats.tx_ucast_frames) + 343 be64_to_cpu(fcoe_port_stats.tx_offload_frames)); 344 fhs->tx_words += (be64_to_cpu(fcoe_port_stats.tx_bcast_bytes) + 345 be64_to_cpu(fcoe_port_stats.tx_mcast_bytes) + 346 be64_to_cpu(fcoe_port_stats.tx_ucast_bytes) + 347 be64_to_cpu(fcoe_port_stats.tx_offload_bytes)) / 348 CSIO_WORD_TO_BYTE; 349 fhs->rx_frames += (be64_to_cpu(fcoe_port_stats.rx_bcast_frames) + 350 be64_to_cpu(fcoe_port_stats.rx_mcast_frames) + 351 be64_to_cpu(fcoe_port_stats.rx_ucast_frames)); 352 fhs->rx_words += (be64_to_cpu(fcoe_port_stats.rx_bcast_bytes) + 353 be64_to_cpu(fcoe_port_stats.rx_mcast_bytes) + 354 be64_to_cpu(fcoe_port_stats.rx_ucast_bytes)) / 355 CSIO_WORD_TO_BYTE; 356 fhs->error_frames += be64_to_cpu(fcoe_port_stats.rx_err_frames); 357 fhs->fcp_input_requests += ln->stats.n_input_requests; 358 fhs->fcp_output_requests += ln->stats.n_output_requests; 359 fhs->fcp_control_requests += ln->stats.n_control_requests; 360 fhs->fcp_input_megabytes += ln->stats.n_input_bytes >> 20; 361 fhs->fcp_output_megabytes += ln->stats.n_output_bytes >> 20; 362 fhs->link_failure_count = ln->stats.n_link_down; 363 /* Reset stats for the device */ 364 seconds = jiffies_to_msecs(jiffies) - hw->stats.n_reset_start; 365 do_div(seconds, 1000); 366 fhs->seconds_since_last_reset = seconds; 367 368 return fhs; 369} 370 371/* 372 * csio_set_rport_loss_tmo - Set the rport dev loss timeout 373 * @rport: fc rport. 374 * @timeout: new value for dev loss tmo. 375 * 376 * If timeout is non zero set the dev_loss_tmo to timeout, else set 377 * dev_loss_tmo to one. 378 */ 379static void 380csio_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) 381{ 382 if (timeout) 383 rport->dev_loss_tmo = timeout; 384 else 385 rport->dev_loss_tmo = 1; 386} 387 388static void 389csio_vport_set_state(struct csio_lnode *ln) 390{ 391 struct fc_vport *fc_vport = ln->fc_vport; 392 struct csio_lnode *pln = ln->pln; 393 char state[16]; 394 395 /* Set fc vport state based on phyiscal lnode */ 396 csio_lnode_state_to_str(pln, state); 397 if (strcmp(state, "READY")) { 398 fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN); 399 return; 400 } 401 402 if (!(pln->flags & CSIO_LNF_NPIVSUPP)) { 403 fc_vport_set_state(fc_vport, FC_VPORT_NO_FABRIC_SUPP); 404 return; 405 } 406 407 /* Set fc vport state based on virtual lnode */ 408 csio_lnode_state_to_str(ln, state); 409 if (strcmp(state, "READY")) { 410 fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN); 411 return; 412 } 413 fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE); 414} 415 416static int 417csio_fcoe_alloc_vnp(struct csio_hw *hw, struct csio_lnode *ln) 418{ 419 struct csio_lnode *pln; 420 struct csio_mb *mbp; 421 struct fw_fcoe_vnp_cmd *rsp; 422 int ret = 0; 423 int retry = 0; 424 425 /* Issue VNP cmd to alloc vport */ 426 /* Allocate Mbox request */ 427 spin_lock_irq(&hw->lock); 428 mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC); 429 if (!mbp) { 430 CSIO_INC_STATS(hw, n_err_nomem); 431 ret = -ENOMEM; 432 goto out; 433 } 434 435 pln = ln->pln; 436 ln->fcf_flowid = pln->fcf_flowid; 437 ln->portid = pln->portid; 438 439 csio_fcoe_vnp_alloc_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO, 440 pln->fcf_flowid, pln->vnp_flowid, 0, 441 csio_ln_wwnn(ln), csio_ln_wwpn(ln), NULL); 442 443 for (retry = 0; retry < 3; retry++) { 444 /* FW is expected to complete vnp cmd in immediate mode 445 * without much delay. 446 * Otherwise, there will be increase in IO latency since HW 447 * lock is held till completion of vnp mbox cmd. 448 */ 449 ret = csio_mb_issue(hw, mbp); 450 if (ret != -EBUSY) 451 break; 452 453 /* Retry if mbox returns busy */ 454 spin_unlock_irq(&hw->lock); 455 msleep(2000); 456 spin_lock_irq(&hw->lock); 457 } 458 459 if (ret) { 460 csio_ln_err(ln, "Failed to issue mbox FCoE VNP command\n"); 461 goto out_free; 462 } 463 464 /* Process Mbox response of VNP command */ 465 rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb); 466 if (FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)) != FW_SUCCESS) { 467 csio_ln_err(ln, "FCOE VNP ALLOC cmd returned 0x%x!\n", 468 FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16))); 469 ret = -EINVAL; 470 goto out_free; 471 } 472 473 ln->vnp_flowid = FW_FCOE_VNP_CMD_VNPI_GET( 474 ntohl(rsp->gen_wwn_to_vnpi)); 475 memcpy(csio_ln_wwnn(ln), rsp->vnport_wwnn, 8); 476 memcpy(csio_ln_wwpn(ln), rsp->vnport_wwpn, 8); 477 478 csio_ln_dbg(ln, "FCOE VNPI: 0x%x\n", ln->vnp_flowid); 479 csio_ln_dbg(ln, "\tWWNN: %x%x%x%x%x%x%x%x\n", 480 ln->ln_sparm.wwnn[0], ln->ln_sparm.wwnn[1], 481 ln->ln_sparm.wwnn[2], ln->ln_sparm.wwnn[3], 482 ln->ln_sparm.wwnn[4], ln->ln_sparm.wwnn[5], 483 ln->ln_sparm.wwnn[6], ln->ln_sparm.wwnn[7]); 484 csio_ln_dbg(ln, "\tWWPN: %x%x%x%x%x%x%x%x\n", 485 ln->ln_sparm.wwpn[0], ln->ln_sparm.wwpn[1], 486 ln->ln_sparm.wwpn[2], ln->ln_sparm.wwpn[3], 487 ln->ln_sparm.wwpn[4], ln->ln_sparm.wwpn[5], 488 ln->ln_sparm.wwpn[6], ln->ln_sparm.wwpn[7]); 489 490out_free: 491 mempool_free(mbp, hw->mb_mempool); 492out: 493 spin_unlock_irq(&hw->lock); 494 return ret; 495} 496 497static int 498csio_fcoe_free_vnp(struct csio_hw *hw, struct csio_lnode *ln) 499{ 500 struct csio_mb *mbp; 501 struct fw_fcoe_vnp_cmd *rsp; 502 int ret = 0; 503 int retry = 0; 504 505 /* Issue VNP cmd to free vport */ 506 /* Allocate Mbox request */ 507 508 spin_lock_irq(&hw->lock); 509 mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC); 510 if (!mbp) { 511 CSIO_INC_STATS(hw, n_err_nomem); 512 ret = -ENOMEM; 513 goto out; 514 } 515 516 csio_fcoe_vnp_free_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO, 517 ln->fcf_flowid, ln->vnp_flowid, 518 NULL); 519 520 for (retry = 0; retry < 3; retry++) { 521 ret = csio_mb_issue(hw, mbp); 522 if (ret != -EBUSY) 523 break; 524 525 /* Retry if mbox returns busy */ 526 spin_unlock_irq(&hw->lock); 527 msleep(2000); 528 spin_lock_irq(&hw->lock); 529 } 530 531 if (ret) { 532 csio_ln_err(ln, "Failed to issue mbox FCoE VNP command\n"); 533 goto out_free; 534 } 535 536 /* Process Mbox response of VNP command */ 537 rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb); 538 if (FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)) != FW_SUCCESS) { 539 csio_ln_err(ln, "FCOE VNP FREE cmd returned 0x%x!\n", 540 FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16))); 541 ret = -EINVAL; 542 } 543 544out_free: 545 mempool_free(mbp, hw->mb_mempool); 546out: 547 spin_unlock_irq(&hw->lock); 548 return ret; 549} 550 551static int 552csio_vport_create(struct fc_vport *fc_vport, bool disable) 553{ 554 struct Scsi_Host *shost = fc_vport->shost; 555 struct csio_lnode *pln = shost_priv(shost); 556 struct csio_lnode *ln = NULL; 557 struct csio_hw *hw = csio_lnode_to_hw(pln); 558 uint8_t wwn[8]; 559 int ret = -1; 560 561 ln = csio_shost_init(hw, &fc_vport->dev, false, pln); 562 if (!ln) 563 goto error; 564 565 if (fc_vport->node_name != 0) { 566 u64_to_wwn(fc_vport->node_name, wwn); 567 568 if (!CSIO_VALID_WWN(wwn)) { 569 csio_ln_err(ln, 570 "vport create failed. Invalid wwnn\n"); 571 goto error; 572 } 573 memcpy(csio_ln_wwnn(ln), wwn, 8); 574 } 575 576 if (fc_vport->port_name != 0) { 577 u64_to_wwn(fc_vport->port_name, wwn); 578 579 if (!CSIO_VALID_WWN(wwn)) { 580 csio_ln_err(ln, 581 "vport create failed. Invalid wwpn\n"); 582 goto error; 583 } 584 585 if (csio_lnode_lookup_by_wwpn(hw, wwn)) { 586 csio_ln_err(ln, 587 "vport create failed. wwpn already exists\n"); 588 goto error; 589 } 590 memcpy(csio_ln_wwpn(ln), wwn, 8); 591 } 592 593 fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING); 594 ln->fc_vport = fc_vport; 595 596 if (csio_fcoe_alloc_vnp(hw, ln)) 597 goto error; 598 599 *(struct csio_lnode **)fc_vport->dd_data = ln; 600 if (!fc_vport->node_name) 601 fc_vport->node_name = wwn_to_u64(csio_ln_wwnn(ln)); 602 if (!fc_vport->port_name) 603 fc_vport->port_name = wwn_to_u64(csio_ln_wwpn(ln)); 604 csio_fchost_attr_init(ln); 605 return 0; 606error: 607 if (ln) 608 csio_shost_exit(ln); 609 610 return ret; 611} 612 613static int 614csio_vport_delete(struct fc_vport *fc_vport) 615{ 616 struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data; 617 struct Scsi_Host *shost = csio_ln_to_shost(ln); 618 struct csio_hw *hw = csio_lnode_to_hw(ln); 619 int rmv; 620 621 spin_lock_irq(&hw->lock); 622 rmv = csio_is_hw_removing(hw); 623 spin_unlock_irq(&hw->lock); 624 625 if (rmv) { 626 csio_shost_exit(ln); 627 return 0; 628 } 629 630 /* Quiesce ios and send remove event to lnode */ 631 scsi_block_requests(shost); 632 spin_lock_irq(&hw->lock); 633 csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln); 634 csio_lnode_close(ln); 635 spin_unlock_irq(&hw->lock); 636 scsi_unblock_requests(shost); 637 638 /* Free vnp */ 639 if (fc_vport->vport_state != FC_VPORT_DISABLED) 640 csio_fcoe_free_vnp(hw, ln); 641 642 csio_shost_exit(ln); 643 return 0; 644} 645 646static int 647csio_vport_disable(struct fc_vport *fc_vport, bool disable) 648{ 649 struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data; 650 struct Scsi_Host *shost = csio_ln_to_shost(ln); 651 struct csio_hw *hw = csio_lnode_to_hw(ln); 652 653 /* disable vport */ 654 if (disable) { 655 /* Quiesce ios and send stop event to lnode */ 656 scsi_block_requests(shost); 657 spin_lock_irq(&hw->lock); 658 csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln); 659 csio_lnode_stop(ln); 660 spin_unlock_irq(&hw->lock); 661 scsi_unblock_requests(shost); 662 663 /* Free vnp */ 664 csio_fcoe_free_vnp(hw, ln); 665 fc_vport_set_state(fc_vport, FC_VPORT_DISABLED); 666 csio_ln_err(ln, "vport disabled\n"); 667 return 0; 668 } else { 669 /* enable vport */ 670 fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING); 671 if (csio_fcoe_alloc_vnp(hw, ln)) { 672 csio_ln_err(ln, "vport enabled failed.\n"); 673 return -1; 674 } 675 csio_ln_err(ln, "vport enabled\n"); 676 return 0; 677 } 678} 679 680static void 681csio_dev_loss_tmo_callbk(struct fc_rport *rport) 682{ 683 struct csio_rnode *rn; 684 struct csio_hw *hw; 685 struct csio_lnode *ln; 686 687 rn = *((struct csio_rnode **)rport->dd_data); 688 ln = csio_rnode_to_lnode(rn); 689 hw = csio_lnode_to_hw(ln); 690 691 spin_lock_irq(&hw->lock); 692 693 /* return if driver is being removed or same rnode comes back online */ 694 if (csio_is_hw_removing(hw) || csio_is_rnode_ready(rn)) 695 goto out; 696 697 csio_ln_dbg(ln, "devloss timeout on rnode:%p portid:x%x flowid:x%x\n", 698 rn, rn->nport_id, csio_rn_flowid(rn)); 699 700 CSIO_INC_STATS(ln, n_dev_loss_tmo); 701 702 /* 703 * enqueue devloss event to event worker thread to serialize all 704 * rnode events. 705 */ 706 if (csio_enqueue_evt(hw, CSIO_EVT_DEV_LOSS, &rn, sizeof(rn))) { 707 CSIO_INC_STATS(hw, n_evt_drop); 708 goto out; 709 } 710 711 if (!(hw->flags & CSIO_HWF_FWEVT_PENDING)) { 712 hw->flags |= CSIO_HWF_FWEVT_PENDING; 713 spin_unlock_irq(&hw->lock); 714 schedule_work(&hw->evtq_work); 715 return; 716 } 717 718out: 719 spin_unlock_irq(&hw->lock); 720} 721 722/* FC transport functions template - Physical port */ 723struct fc_function_template csio_fc_transport_funcs = { 724 .show_host_node_name = 1, 725 .show_host_port_name = 1, 726 .show_host_supported_classes = 1, 727 .show_host_supported_fc4s = 1, 728 .show_host_maxframe_size = 1, 729 730 .get_host_port_id = csio_get_host_port_id, 731 .show_host_port_id = 1, 732 733 .get_host_port_type = csio_get_host_port_type, 734 .show_host_port_type = 1, 735 736 .get_host_port_state = csio_get_host_port_state, 737 .show_host_port_state = 1, 738 739 .show_host_active_fc4s = 1, 740 .get_host_speed = csio_get_host_speed, 741 .show_host_speed = 1, 742 .get_host_fabric_name = csio_get_host_fabric_name, 743 .show_host_fabric_name = 1, 744 745 .get_fc_host_stats = csio_get_stats, 746 747 .dd_fcrport_size = sizeof(struct csio_rnode *), 748 .show_rport_maxframe_size = 1, 749 .show_rport_supported_classes = 1, 750 751 .set_rport_dev_loss_tmo = csio_set_rport_loss_tmo, 752 .show_rport_dev_loss_tmo = 1, 753 754 .show_starget_port_id = 1, 755 .show_starget_node_name = 1, 756 .show_starget_port_name = 1, 757 758 .dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk, 759 .dd_fcvport_size = sizeof(struct csio_lnode *), 760 761 .vport_create = csio_vport_create, 762 .vport_disable = csio_vport_disable, 763 .vport_delete = csio_vport_delete, 764}; 765 766/* FC transport functions template - Virtual port */ 767struct fc_function_template csio_fc_transport_vport_funcs = { 768 .show_host_node_name = 1, 769 .show_host_port_name = 1, 770 .show_host_supported_classes = 1, 771 .show_host_supported_fc4s = 1, 772 .show_host_maxframe_size = 1, 773 774 .get_host_port_id = csio_get_host_port_id, 775 .show_host_port_id = 1, 776 777 .get_host_port_type = csio_get_host_port_type, 778 .show_host_port_type = 1, 779 780 .get_host_port_state = csio_get_host_port_state, 781 .show_host_port_state = 1, 782 .show_host_active_fc4s = 1, 783 784 .get_host_speed = csio_get_host_speed, 785 .show_host_speed = 1, 786 787 .get_host_fabric_name = csio_get_host_fabric_name, 788 .show_host_fabric_name = 1, 789 790 .get_fc_host_stats = csio_get_stats, 791 792 .dd_fcrport_size = sizeof(struct csio_rnode *), 793 .show_rport_maxframe_size = 1, 794 .show_rport_supported_classes = 1, 795 796 .set_rport_dev_loss_tmo = csio_set_rport_loss_tmo, 797 .show_rport_dev_loss_tmo = 1, 798 799 .show_starget_port_id = 1, 800 .show_starget_node_name = 1, 801 .show_starget_port_name = 1, 802 803 .dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk, 804 805};