806 lines · c
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 two7 * licenses. You may choose to be licensed under the terms of the GNU8 * General Public License (GPL) Version 2, available from the file9 * COPYING in the main directory of this source tree, or the10 * OpenIB.org BSD license below:11 *12 * Redistribution and use in source and binary forms, with or13 * without modification, are permitted provided that the following14 * conditions are met:15 *16 * - Redistributions of source code must retain the above17 * copyright notice, this list of conditions and the following18 * disclaimer.19 *20 * - Redistributions in binary form must reproduce the above21 * copyright notice, this list of conditions and the following22 * disclaimer in the documentation and/or other materials23 * 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 OF27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE32 * 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 void48csio_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 */58void59csio_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 else96 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 FC117 * transport.118 *119 */120void121csio_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 ML138 * should be made aware of (Eg: RSCN).139 */140void141csio_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 attributes178 * @ln: Lnode.179 *180 */181void182csio_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 is207 * populated/cached from this function208 */209static void210csio_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 void226csio_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 else235 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 void245csio_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 else259 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 void270csio_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 name304 * @shost: scsi host.305 *306 */307static void308csio_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 else319 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 timeout373 * @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 set377 * dev_loss_tmo to one.378 */379static void380csio_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)381{382 if (timeout)383 rport->dev_loss_tmo = timeout;384 else385 rport->dev_loss_tmo = 1;386}387 388static void389csio_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 int417csio_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 mode445 * without much delay.446 * Otherwise, there will be increase in IO latency since HW447 * 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 int498csio_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 int552csio_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 int614csio_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 int647csio_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 void681csio_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 all704 * 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};806