root/drivers/scsi/csiostor/csio_attr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. csio_reg_rnode
  2. csio_unreg_rnode
  3. csio_lnode_async_event
  4. csio_fchost_attr_init
  5. csio_get_host_port_id
  6. csio_get_host_port_type
  7. csio_get_host_port_state
  8. csio_get_host_speed
  9. csio_get_host_fabric_name
  10. csio_get_stats
  11. csio_set_rport_loss_tmo
  12. csio_vport_set_state
  13. csio_fcoe_alloc_vnp
  14. csio_fcoe_free_vnp
  15. csio_vport_create
  16. csio_vport_delete
  17. csio_vport_disable
  18. csio_dev_loss_tmo_callbk

   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 
  47 static void
  48 csio_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  */
  58 void
  59 csio_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;
  97 update_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  */
 120 void
 121 csio_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  */
 140 void
 141 csio_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  */
 181 void
 182 csio_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  */
 209 static void
 210 csio_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  */
 225 static void
 226 csio_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  */
 244 static void
 245 csio_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  */
 269 static void
 270 csio_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  */
 307 static void
 308 csio_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  */
 328 static struct fc_host_statistics *
 329 csio_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  */
 379 static void
 380 csio_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 
 388 static void
 389 csio_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 
 416 static int
 417 csio_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 
 490 out_free:
 491         mempool_free(mbp, hw->mb_mempool);
 492 out:
 493         spin_unlock_irq(&hw->lock);
 494         return ret;
 495 }
 496 
 497 static int
 498 csio_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 
 544 out_free:
 545         mempool_free(mbp, hw->mb_mempool);
 546 out:
 547         spin_unlock_irq(&hw->lock);
 548         return ret;
 549 }
 550 
 551 static int
 552 csio_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;
 606 error:
 607         if (ln)
 608                 csio_shost_exit(ln);
 609 
 610         return ret;
 611 }
 612 
 613 static int
 614 csio_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 
 646 static int
 647 csio_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 
 680 static void
 681 csio_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 
 718 out:
 719         spin_unlock_irq(&hw->lock);
 720 }
 721 
 722 /* FC transport functions template - Physical port */
 723 struct 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 */
 767 struct 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 };

/* [<][>][^][v][top][bottom][index][help] */