linux/drivers/scsi/csiostor/csio_attr.c
<<
>>
Prefs
   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};
 806