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_lnode *pln;
 501        struct csio_mb  *mbp;
 502        struct fw_fcoe_vnp_cmd *rsp;
 503        int ret = 0;
 504        int retry = 0;
 505
 506        /* Issue VNP cmd to free vport */
 507        /* Allocate Mbox request */
 508
 509        spin_lock_irq(&hw->lock);
 510        mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
 511        if (!mbp) {
 512                CSIO_INC_STATS(hw, n_err_nomem);
 513                ret = -ENOMEM;
 514                goto out;
 515        }
 516
 517        pln = ln->pln;
 518
 519        csio_fcoe_vnp_free_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,
 520                                   ln->fcf_flowid, ln->vnp_flowid,
 521                                   NULL);
 522
 523        for (retry = 0; retry < 3; retry++) {
 524                ret = csio_mb_issue(hw, mbp);
 525                if (ret != -EBUSY)
 526                        break;
 527
 528                /* Retry if mbox returns busy */
 529                spin_unlock_irq(&hw->lock);
 530                msleep(2000);
 531                spin_lock_irq(&hw->lock);
 532        }
 533
 534        if (ret) {
 535                csio_ln_err(ln, "Failed to issue mbox FCoE VNP command\n");
 536                goto out_free;
 537        }
 538
 539        /* Process Mbox response of VNP command */
 540        rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb);
 541        if (FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)) != FW_SUCCESS) {
 542                csio_ln_err(ln, "FCOE VNP FREE cmd returned 0x%x!\n",
 543                            FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)));
 544                ret = -EINVAL;
 545        }
 546
 547out_free:
 548        mempool_free(mbp, hw->mb_mempool);
 549out:
 550        spin_unlock_irq(&hw->lock);
 551        return ret;
 552}
 553
 554static int
 555csio_vport_create(struct fc_vport *fc_vport, bool disable)
 556{
 557        struct Scsi_Host *shost = fc_vport->shost;
 558        struct csio_lnode *pln = shost_priv(shost);
 559        struct csio_lnode *ln = NULL;
 560        struct csio_hw *hw = csio_lnode_to_hw(pln);
 561        uint8_t wwn[8];
 562        int ret = -1;
 563
 564        ln = csio_shost_init(hw, &fc_vport->dev, false, pln);
 565        if (!ln)
 566                goto error;
 567
 568        if (fc_vport->node_name != 0) {
 569                u64_to_wwn(fc_vport->node_name, wwn);
 570
 571                if (!CSIO_VALID_WWN(wwn)) {
 572                        csio_ln_err(ln,
 573                                    "vport create failed. Invalid wwnn\n");
 574                        goto error;
 575                }
 576                memcpy(csio_ln_wwnn(ln), wwn, 8);
 577        }
 578
 579        if (fc_vport->port_name != 0) {
 580                u64_to_wwn(fc_vport->port_name, wwn);
 581
 582                if (!CSIO_VALID_WWN(wwn)) {
 583                        csio_ln_err(ln,
 584                                    "vport create failed. Invalid wwpn\n");
 585                        goto error;
 586                }
 587
 588                if (csio_lnode_lookup_by_wwpn(hw, wwn)) {
 589                        csio_ln_err(ln,
 590                            "vport create failed. wwpn already exists\n");
 591                        goto error;
 592                }
 593                memcpy(csio_ln_wwpn(ln), wwn, 8);
 594        }
 595
 596        fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);
 597
 598        if (csio_fcoe_alloc_vnp(hw, ln))
 599                goto error;
 600
 601        *(struct csio_lnode **)fc_vport->dd_data = ln;
 602        ln->fc_vport = fc_vport;
 603        if (!fc_vport->node_name)
 604                fc_vport->node_name = wwn_to_u64(csio_ln_wwnn(ln));
 605        if (!fc_vport->port_name)
 606                fc_vport->port_name = wwn_to_u64(csio_ln_wwpn(ln));
 607        csio_fchost_attr_init(ln);
 608        return 0;
 609error:
 610        if (ln)
 611                csio_shost_exit(ln);
 612
 613        return ret;
 614}
 615
 616static int
 617csio_vport_delete(struct fc_vport *fc_vport)
 618{
 619        struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data;
 620        struct Scsi_Host *shost = csio_ln_to_shost(ln);
 621        struct csio_hw *hw = csio_lnode_to_hw(ln);
 622        int rmv;
 623
 624        spin_lock_irq(&hw->lock);
 625        rmv = csio_is_hw_removing(hw);
 626        spin_unlock_irq(&hw->lock);
 627
 628        if (rmv) {
 629                csio_shost_exit(ln);
 630                return 0;
 631        }
 632
 633        /* Quiesce ios and send remove event to lnode */
 634        scsi_block_requests(shost);
 635        spin_lock_irq(&hw->lock);
 636        csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln);
 637        csio_lnode_close(ln);
 638        spin_unlock_irq(&hw->lock);
 639        scsi_unblock_requests(shost);
 640
 641        /* Free vnp */
 642        if (fc_vport->vport_state !=  FC_VPORT_DISABLED)
 643                csio_fcoe_free_vnp(hw, ln);
 644
 645        csio_shost_exit(ln);
 646        return 0;
 647}
 648
 649static int
 650csio_vport_disable(struct fc_vport *fc_vport, bool disable)
 651{
 652        struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data;
 653        struct Scsi_Host *shost = csio_ln_to_shost(ln);
 654        struct csio_hw *hw = csio_lnode_to_hw(ln);
 655
 656        /* disable vport */
 657        if (disable) {
 658                /* Quiesce ios and send stop event to lnode */
 659                scsi_block_requests(shost);
 660                spin_lock_irq(&hw->lock);
 661                csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln);
 662                csio_lnode_stop(ln);
 663                spin_unlock_irq(&hw->lock);
 664                scsi_unblock_requests(shost);
 665
 666                /* Free vnp */
 667                csio_fcoe_free_vnp(hw, ln);
 668                fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
 669                csio_ln_err(ln, "vport disabled\n");
 670                return 0;
 671        } else {
 672                /* enable vport */
 673                fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);
 674                if (csio_fcoe_alloc_vnp(hw, ln)) {
 675                        csio_ln_err(ln, "vport enabled failed.\n");
 676                        return -1;
 677                }
 678                csio_ln_err(ln, "vport enabled\n");
 679                return 0;
 680        }
 681}
 682
 683static void
 684csio_dev_loss_tmo_callbk(struct fc_rport *rport)
 685{
 686        struct csio_rnode *rn;
 687        struct csio_hw *hw;
 688        struct csio_lnode *ln;
 689
 690        rn = *((struct csio_rnode **)rport->dd_data);
 691        ln = csio_rnode_to_lnode(rn);
 692        hw = csio_lnode_to_hw(ln);
 693
 694        spin_lock_irq(&hw->lock);
 695
 696        /* return if driver is being removed or same rnode comes back online */
 697        if (csio_is_hw_removing(hw) || csio_is_rnode_ready(rn))
 698                goto out;
 699
 700        csio_ln_dbg(ln, "devloss timeout on rnode:%p portid:x%x flowid:x%x\n",
 701                    rn, rn->nport_id, csio_rn_flowid(rn));
 702
 703        CSIO_INC_STATS(ln, n_dev_loss_tmo);
 704
 705        /*
 706         * enqueue devloss event to event worker thread to serialize all
 707         * rnode events.
 708         */
 709        if (csio_enqueue_evt(hw, CSIO_EVT_DEV_LOSS, &rn, sizeof(rn))) {
 710                CSIO_INC_STATS(hw, n_evt_drop);
 711                goto out;
 712        }
 713
 714        if (!(hw->flags & CSIO_HWF_FWEVT_PENDING)) {
 715                hw->flags |= CSIO_HWF_FWEVT_PENDING;
 716                spin_unlock_irq(&hw->lock);
 717                schedule_work(&hw->evtq_work);
 718                return;
 719        }
 720
 721out:
 722        spin_unlock_irq(&hw->lock);
 723}
 724
 725/* FC transport functions template - Physical port */
 726struct fc_function_template csio_fc_transport_funcs = {
 727        .show_host_node_name = 1,
 728        .show_host_port_name = 1,
 729        .show_host_supported_classes = 1,
 730        .show_host_supported_fc4s = 1,
 731        .show_host_maxframe_size = 1,
 732
 733        .get_host_port_id = csio_get_host_port_id,
 734        .show_host_port_id = 1,
 735
 736        .get_host_port_type = csio_get_host_port_type,
 737        .show_host_port_type = 1,
 738
 739        .get_host_port_state = csio_get_host_port_state,
 740        .show_host_port_state = 1,
 741
 742        .show_host_active_fc4s = 1,
 743        .get_host_speed = csio_get_host_speed,
 744        .show_host_speed = 1,
 745        .get_host_fabric_name = csio_get_host_fabric_name,
 746        .show_host_fabric_name = 1,
 747
 748        .get_fc_host_stats = csio_get_stats,
 749
 750        .dd_fcrport_size = sizeof(struct csio_rnode *),
 751        .show_rport_maxframe_size = 1,
 752        .show_rport_supported_classes = 1,
 753
 754        .set_rport_dev_loss_tmo = csio_set_rport_loss_tmo,
 755        .show_rport_dev_loss_tmo = 1,
 756
 757        .show_starget_port_id = 1,
 758        .show_starget_node_name = 1,
 759        .show_starget_port_name = 1,
 760
 761        .dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk,
 762        .dd_fcvport_size = sizeof(struct csio_lnode *),
 763
 764        .vport_create = csio_vport_create,
 765        .vport_disable = csio_vport_disable,
 766        .vport_delete = csio_vport_delete,
 767};
 768
 769/* FC transport functions template - Virtual  port */
 770struct fc_function_template csio_fc_transport_vport_funcs = {
 771        .show_host_node_name = 1,
 772        .show_host_port_name = 1,
 773        .show_host_supported_classes = 1,
 774        .show_host_supported_fc4s = 1,
 775        .show_host_maxframe_size = 1,
 776
 777        .get_host_port_id = csio_get_host_port_id,
 778        .show_host_port_id = 1,
 779
 780        .get_host_port_type = csio_get_host_port_type,
 781        .show_host_port_type = 1,
 782
 783        .get_host_port_state = csio_get_host_port_state,
 784        .show_host_port_state = 1,
 785        .show_host_active_fc4s = 1,
 786
 787        .get_host_speed = csio_get_host_speed,
 788        .show_host_speed = 1,
 789
 790        .get_host_fabric_name = csio_get_host_fabric_name,
 791        .show_host_fabric_name = 1,
 792
 793        .get_fc_host_stats = csio_get_stats,
 794
 795        .dd_fcrport_size = sizeof(struct csio_rnode *),
 796        .show_rport_maxframe_size = 1,
 797        .show_rport_supported_classes = 1,
 798
 799        .set_rport_dev_loss_tmo = csio_set_rport_loss_tmo,
 800        .show_rport_dev_loss_tmo = 1,
 801
 802        .show_starget_port_id = 1,
 803        .show_starget_node_name = 1,
 804        .show_starget_port_name = 1,
 805
 806        .dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk,
 807
 808};
 809