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