Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is part of the Chelsio FCoE driver for Linux.
0003  *
0004  * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
0005  *
0006  * This software is available to you under a choice of one of two
0007  * licenses.  You may choose to be licensed under the terms of the GNU
0008  * General Public License (GPL) Version 2, available from the file
0009  * COPYING in the main directory of this source tree, or the
0010  * OpenIB.org BSD license below:
0011  *
0012  *     Redistribution and use in source and binary forms, with or
0013  *     without modification, are permitted provided that the following
0014  *     conditions are met:
0015  *
0016  *      - Redistributions of source code must retain the above
0017  *        copyright notice, this list of conditions and the following
0018  *        disclaimer.
0019  *
0020  *      - Redistributions in binary form must reproduce the above
0021  *        copyright notice, this list of conditions and the following
0022  *        disclaimer in the documentation and/or other materials
0023  *        provided with the distribution.
0024  *
0025  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0026  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0027  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0028  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
0029  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
0030  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0031  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0032  * SOFTWARE.
0033  */
0034 
0035 #include <linux/string.h>
0036 #include <scsi/scsi_device.h>
0037 #include <scsi/scsi_transport_fc.h>
0038 #include <scsi/fc/fc_els.h>
0039 #include <scsi/fc/fc_fs.h>
0040 
0041 #include "csio_hw.h"
0042 #include "csio_lnode.h"
0043 #include "csio_rnode.h"
0044 
0045 static int csio_rnode_init(struct csio_rnode *, struct csio_lnode *);
0046 static void csio_rnode_exit(struct csio_rnode *);
0047 
0048 /* Static machine forward declarations */
0049 static void csio_rns_uninit(struct csio_rnode *, enum csio_rn_ev);
0050 static void csio_rns_ready(struct csio_rnode *, enum csio_rn_ev);
0051 static void csio_rns_offline(struct csio_rnode *, enum csio_rn_ev);
0052 static void csio_rns_disappeared(struct csio_rnode *, enum csio_rn_ev);
0053 
0054 /* RNF event mapping */
0055 static enum csio_rn_ev fwevt_to_rnevt[] = {
0056     CSIO_RNFE_NONE,     /* None */
0057     CSIO_RNFE_LOGGED_IN,    /* PLOGI_ACC_RCVD  */
0058     CSIO_RNFE_NONE,     /* PLOGI_RJT_RCVD  */
0059     CSIO_RNFE_PLOGI_RECV,   /* PLOGI_RCVD      */
0060     CSIO_RNFE_LOGO_RECV,    /* PLOGO_RCVD      */
0061     CSIO_RNFE_PRLI_DONE,    /* PRLI_ACC_RCVD   */
0062     CSIO_RNFE_NONE,     /* PRLI_RJT_RCVD   */
0063     CSIO_RNFE_PRLI_RECV,    /* PRLI_RCVD       */
0064     CSIO_RNFE_PRLO_RECV,    /* PRLO_RCVD       */
0065     CSIO_RNFE_NONE,     /* NPORT_ID_CHGD   */
0066     CSIO_RNFE_LOGO_RECV,    /* FLOGO_RCVD      */
0067     CSIO_RNFE_NONE,     /* CLR_VIRT_LNK_RCVD */
0068     CSIO_RNFE_LOGGED_IN,    /* FLOGI_ACC_RCVD   */
0069     CSIO_RNFE_NONE,     /* FLOGI_RJT_RCVD   */
0070     CSIO_RNFE_LOGGED_IN,    /* FDISC_ACC_RCVD   */
0071     CSIO_RNFE_NONE,     /* FDISC_RJT_RCVD   */
0072     CSIO_RNFE_NONE,     /* FLOGI_TMO_MAX_RETRY */
0073     CSIO_RNFE_NONE,     /* IMPL_LOGO_ADISC_ACC */
0074     CSIO_RNFE_NONE,     /* IMPL_LOGO_ADISC_RJT */
0075     CSIO_RNFE_NONE,     /* IMPL_LOGO_ADISC_CNFLT */
0076     CSIO_RNFE_NONE,     /* PRLI_TMO     */
0077     CSIO_RNFE_NONE,     /* ADISC_TMO        */
0078     CSIO_RNFE_NAME_MISSING, /* RSCN_DEV_LOST  */
0079     CSIO_RNFE_NONE,     /* SCR_ACC_RCVD */
0080     CSIO_RNFE_NONE,     /* ADISC_RJT_RCVD */
0081     CSIO_RNFE_NONE,     /* LOGO_SNT */
0082     CSIO_RNFE_LOGO_RECV,    /* PROTO_ERR_IMPL_LOGO */
0083 };
0084 
0085 #define CSIO_FWE_TO_RNFE(_evt)  ((_evt > PROTO_ERR_IMPL_LOGO) ?     \
0086                         CSIO_RNFE_NONE :    \
0087                         fwevt_to_rnevt[_evt])
0088 int
0089 csio_is_rnode_ready(struct csio_rnode *rn)
0090 {
0091     return csio_match_state(rn, csio_rns_ready);
0092 }
0093 
0094 static int
0095 csio_is_rnode_uninit(struct csio_rnode *rn)
0096 {
0097     return csio_match_state(rn, csio_rns_uninit);
0098 }
0099 
0100 static int
0101 csio_is_rnode_wka(uint8_t rport_type)
0102 {
0103     if ((rport_type == FLOGI_VFPORT) ||
0104         (rport_type == FDISC_VFPORT) ||
0105         (rport_type == NS_VNPORT) ||
0106         (rport_type == FDMI_VNPORT))
0107         return 1;
0108 
0109     return 0;
0110 }
0111 
0112 /*
0113  * csio_rn_lookup - Finds the rnode with the given flowid
0114  * @ln - lnode
0115  * @flowid - flowid.
0116  *
0117  * Does the rnode lookup on the given lnode and flowid.If no matching entry
0118  * found, NULL is returned.
0119  */
0120 static struct csio_rnode *
0121 csio_rn_lookup(struct csio_lnode *ln, uint32_t flowid)
0122 {
0123     struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
0124     struct list_head *tmp;
0125     struct csio_rnode *rn;
0126 
0127     list_for_each(tmp, &rnhead->sm.sm_list) {
0128         rn = (struct csio_rnode *) tmp;
0129         if (rn->flowid == flowid)
0130             return rn;
0131     }
0132 
0133     return NULL;
0134 }
0135 
0136 /*
0137  * csio_rn_lookup_wwpn - Finds the rnode with the given wwpn
0138  * @ln: lnode
0139  * @wwpn: wwpn
0140  *
0141  * Does the rnode lookup on the given lnode and wwpn. If no matching entry
0142  * found, NULL is returned.
0143  */
0144 static struct csio_rnode *
0145 csio_rn_lookup_wwpn(struct csio_lnode *ln, uint8_t *wwpn)
0146 {
0147     struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
0148     struct list_head *tmp;
0149     struct csio_rnode *rn;
0150 
0151     list_for_each(tmp, &rnhead->sm.sm_list) {
0152         rn = (struct csio_rnode *) tmp;
0153         if (!memcmp(csio_rn_wwpn(rn), wwpn, 8))
0154             return rn;
0155     }
0156 
0157     return NULL;
0158 }
0159 
0160 /**
0161  * csio_rnode_lookup_portid - Finds the rnode with the given portid
0162  * @ln:     lnode
0163  * @portid: port id
0164  *
0165  * Lookup the rnode list for a given portid. If no matching entry
0166  * found, NULL is returned.
0167  */
0168 struct csio_rnode *
0169 csio_rnode_lookup_portid(struct csio_lnode *ln, uint32_t portid)
0170 {
0171     struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
0172     struct list_head *tmp;
0173     struct csio_rnode *rn;
0174 
0175     list_for_each(tmp, &rnhead->sm.sm_list) {
0176         rn = (struct csio_rnode *) tmp;
0177         if (rn->nport_id == portid)
0178             return rn;
0179     }
0180 
0181     return NULL;
0182 }
0183 
0184 static int
0185 csio_rn_dup_flowid(struct csio_lnode *ln, uint32_t rdev_flowid,
0186             uint32_t *vnp_flowid)
0187 {
0188     struct csio_rnode *rnhead;
0189     struct list_head *tmp, *tmp1;
0190     struct csio_rnode *rn;
0191     struct csio_lnode *ln_tmp;
0192     struct csio_hw *hw = csio_lnode_to_hw(ln);
0193 
0194     list_for_each(tmp1, &hw->sln_head) {
0195         ln_tmp = (struct csio_lnode *) tmp1;
0196         if (ln_tmp == ln)
0197             continue;
0198 
0199         rnhead = (struct csio_rnode *)&ln_tmp->rnhead;
0200         list_for_each(tmp, &rnhead->sm.sm_list) {
0201 
0202             rn = (struct csio_rnode *) tmp;
0203             if (csio_is_rnode_ready(rn)) {
0204                 if (rn->flowid == rdev_flowid) {
0205                     *vnp_flowid = csio_ln_flowid(ln_tmp);
0206                     return 1;
0207                 }
0208             }
0209         }
0210     }
0211 
0212     return 0;
0213 }
0214 
0215 static struct csio_rnode *
0216 csio_alloc_rnode(struct csio_lnode *ln)
0217 {
0218     struct csio_hw *hw = csio_lnode_to_hw(ln);
0219 
0220     struct csio_rnode *rn = mempool_alloc(hw->rnode_mempool, GFP_ATOMIC);
0221     if (!rn)
0222         goto err;
0223 
0224     memset(rn, 0, sizeof(struct csio_rnode));
0225     if (csio_rnode_init(rn, ln))
0226         goto err_free;
0227 
0228     CSIO_INC_STATS(ln, n_rnode_alloc);
0229 
0230     return rn;
0231 
0232 err_free:
0233     mempool_free(rn, hw->rnode_mempool);
0234 err:
0235     CSIO_INC_STATS(ln, n_rnode_nomem);
0236     return NULL;
0237 }
0238 
0239 static void
0240 csio_free_rnode(struct csio_rnode *rn)
0241 {
0242     struct csio_hw *hw = csio_lnode_to_hw(csio_rnode_to_lnode(rn));
0243 
0244     csio_rnode_exit(rn);
0245     CSIO_INC_STATS(rn->lnp, n_rnode_free);
0246     mempool_free(rn, hw->rnode_mempool);
0247 }
0248 
0249 /*
0250  * csio_get_rnode - Gets rnode with the given flowid
0251  * @ln - lnode
0252  * @flowid - flow id.
0253  *
0254  * Does the rnode lookup on the given lnode and flowid. If no matching
0255  * rnode found, then new rnode with given npid is allocated and returned.
0256  */
0257 static struct csio_rnode *
0258 csio_get_rnode(struct csio_lnode *ln, uint32_t flowid)
0259 {
0260     struct csio_rnode *rn;
0261 
0262     rn = csio_rn_lookup(ln, flowid);
0263     if (!rn) {
0264         rn = csio_alloc_rnode(ln);
0265         if (!rn)
0266             return NULL;
0267 
0268         rn->flowid = flowid;
0269     }
0270 
0271     return rn;
0272 }
0273 
0274 /*
0275  * csio_put_rnode - Frees the given rnode
0276  * @ln - lnode
0277  * @flowid - flow id.
0278  *
0279  * Does the rnode lookup on the given lnode and flowid. If no matching
0280  * rnode found, then new rnode with given npid is allocated and returned.
0281  */
0282 void
0283 csio_put_rnode(struct csio_lnode *ln, struct csio_rnode *rn)
0284 {
0285     CSIO_DB_ASSERT(csio_is_rnode_uninit(rn) != 0);
0286     csio_free_rnode(rn);
0287 }
0288 
0289 /*
0290  * csio_confirm_rnode - confirms rnode based on wwpn.
0291  * @ln: lnode
0292  * @rdev_flowid: remote device flowid
0293  * @rdevp: remote device params
0294  * This routines searches other rnode in list having same wwpn of new rnode.
0295  * If there is a match, then matched rnode is returned and otherwise new rnode
0296  * is returned.
0297  * returns rnode.
0298  */
0299 struct csio_rnode *
0300 csio_confirm_rnode(struct csio_lnode *ln, uint32_t rdev_flowid,
0301            struct fcoe_rdev_entry *rdevp)
0302 {
0303     uint8_t rport_type;
0304     struct csio_rnode *rn, *match_rn;
0305     uint32_t vnp_flowid = 0;
0306     __be32 *port_id;
0307 
0308     port_id = (__be32 *)&rdevp->r_id[0];
0309     rport_type =
0310         FW_RDEV_WR_RPORT_TYPE_GET(rdevp->rd_xfer_rdy_to_rport_type);
0311 
0312     /* Drop rdev event for cntrl port */
0313     if (rport_type == FAB_CTLR_VNPORT) {
0314         csio_ln_dbg(ln,
0315                 "Unhandled rport_type:%d recv in rdev evt "
0316                 "ssni:x%x\n", rport_type, rdev_flowid);
0317         return NULL;
0318     }
0319 
0320     /* Lookup on flowid */
0321     rn = csio_rn_lookup(ln, rdev_flowid);
0322     if (!rn) {
0323 
0324         /* Drop events with duplicate flowid */
0325         if (csio_rn_dup_flowid(ln, rdev_flowid, &vnp_flowid)) {
0326             csio_ln_warn(ln,
0327                      "ssni:%x already active on vnpi:%x",
0328                      rdev_flowid, vnp_flowid);
0329             return NULL;
0330         }
0331 
0332         /* Lookup on wwpn for NPORTs */
0333         rn = csio_rn_lookup_wwpn(ln, rdevp->wwpn);
0334         if (!rn)
0335             goto alloc_rnode;
0336 
0337     } else {
0338         /* Lookup well-known ports with nport id */
0339         if (csio_is_rnode_wka(rport_type)) {
0340             match_rn = csio_rnode_lookup_portid(ln,
0341                       ((ntohl(*port_id) >> 8) & CSIO_DID_MASK));
0342             if (match_rn == NULL) {
0343                 csio_rn_flowid(rn) = CSIO_INVALID_IDX;
0344                 goto alloc_rnode;
0345             }
0346 
0347             /*
0348              * Now compare the wwpn to confirm that
0349              * same port relogged in. If so update the matched rn.
0350              * Else, go ahead and alloc a new rnode.
0351              */
0352             if (!memcmp(csio_rn_wwpn(match_rn), rdevp->wwpn, 8)) {
0353                 if (rn == match_rn)
0354                     goto found_rnode;
0355                 csio_ln_dbg(ln,
0356                         "nport_id:x%x and wwpn:%llx"
0357                         " match for ssni:x%x\n",
0358                         rn->nport_id,
0359                         wwn_to_u64(rdevp->wwpn),
0360                         rdev_flowid);
0361                 if (csio_is_rnode_ready(rn)) {
0362                     csio_ln_warn(ln,
0363                              "rnode is already"
0364                              "active ssni:x%x\n",
0365                              rdev_flowid);
0366                     CSIO_ASSERT(0);
0367                 }
0368                 csio_rn_flowid(rn) = CSIO_INVALID_IDX;
0369                 rn = match_rn;
0370 
0371                 /* Update rn */
0372                 goto found_rnode;
0373             }
0374             csio_rn_flowid(rn) = CSIO_INVALID_IDX;
0375             goto alloc_rnode;
0376         }
0377 
0378         /* wwpn match */
0379         if (!memcmp(csio_rn_wwpn(rn), rdevp->wwpn, 8))
0380             goto found_rnode;
0381 
0382         /* Search for rnode that have same wwpn */
0383         match_rn = csio_rn_lookup_wwpn(ln, rdevp->wwpn);
0384         if (match_rn != NULL) {
0385             csio_ln_dbg(ln,
0386                 "ssni:x%x changed for rport name(wwpn):%llx "
0387                 "did:x%x\n", rdev_flowid,
0388                 wwn_to_u64(rdevp->wwpn),
0389                 match_rn->nport_id);
0390             csio_rn_flowid(rn) = CSIO_INVALID_IDX;
0391             rn = match_rn;
0392         } else {
0393             csio_ln_dbg(ln,
0394                 "rnode wwpn mismatch found ssni:x%x "
0395                 "name(wwpn):%llx\n",
0396                 rdev_flowid,
0397                 wwn_to_u64(csio_rn_wwpn(rn)));
0398             if (csio_is_rnode_ready(rn)) {
0399                 csio_ln_warn(ln,
0400                          "rnode is already active "
0401                          "wwpn:%llx ssni:x%x\n",
0402                          wwn_to_u64(csio_rn_wwpn(rn)),
0403                          rdev_flowid);
0404                 CSIO_ASSERT(0);
0405             }
0406             csio_rn_flowid(rn) = CSIO_INVALID_IDX;
0407             goto alloc_rnode;
0408         }
0409     }
0410 
0411 found_rnode:
0412     csio_ln_dbg(ln, "found rnode:%p ssni:x%x name(wwpn):%llx\n",
0413         rn, rdev_flowid, wwn_to_u64(rdevp->wwpn));
0414 
0415     /* Update flowid */
0416     csio_rn_flowid(rn) = rdev_flowid;
0417 
0418     /* update rdev entry */
0419     rn->rdev_entry = rdevp;
0420     CSIO_INC_STATS(ln, n_rnode_match);
0421     return rn;
0422 
0423 alloc_rnode:
0424     rn = csio_get_rnode(ln, rdev_flowid);
0425     if (!rn)
0426         return NULL;
0427 
0428     csio_ln_dbg(ln, "alloc rnode:%p ssni:x%x name(wwpn):%llx\n",
0429         rn, rdev_flowid, wwn_to_u64(rdevp->wwpn));
0430 
0431     /* update rdev entry */
0432     rn->rdev_entry = rdevp;
0433     return rn;
0434 }
0435 
0436 /*
0437  * csio_rn_verify_rparams - verify rparams.
0438  * @ln: lnode
0439  * @rn: rnode
0440  * @rdevp: remote device params
0441  * returns success if rparams are verified.
0442  */
0443 static int
0444 csio_rn_verify_rparams(struct csio_lnode *ln, struct csio_rnode *rn,
0445             struct fcoe_rdev_entry *rdevp)
0446 {
0447     uint8_t null[8];
0448     uint8_t rport_type;
0449     uint8_t fc_class;
0450     __be32 *did;
0451 
0452     did = (__be32 *) &rdevp->r_id[0];
0453     rport_type =
0454         FW_RDEV_WR_RPORT_TYPE_GET(rdevp->rd_xfer_rdy_to_rport_type);
0455     switch (rport_type) {
0456     case FLOGI_VFPORT:
0457         rn->role = CSIO_RNFR_FABRIC;
0458         if (((ntohl(*did) >> 8) & CSIO_DID_MASK) != FC_FID_FLOGI) {
0459             csio_ln_err(ln, "ssni:x%x invalid fabric portid\n",
0460                 csio_rn_flowid(rn));
0461             return -EINVAL;
0462         }
0463         /* NPIV support */
0464         if (FW_RDEV_WR_NPIV_GET(rdevp->vft_to_qos))
0465             ln->flags |= CSIO_LNF_NPIVSUPP;
0466 
0467         break;
0468 
0469     case NS_VNPORT:
0470         rn->role = CSIO_RNFR_NS;
0471         if (((ntohl(*did) >> 8) & CSIO_DID_MASK) != FC_FID_DIR_SERV) {
0472             csio_ln_err(ln, "ssni:x%x invalid fabric portid\n",
0473                 csio_rn_flowid(rn));
0474             return -EINVAL;
0475         }
0476         break;
0477 
0478     case REG_FC4_VNPORT:
0479     case REG_VNPORT:
0480         rn->role = CSIO_RNFR_NPORT;
0481         if (rdevp->event_cause == PRLI_ACC_RCVD ||
0482             rdevp->event_cause == PRLI_RCVD) {
0483             if (FW_RDEV_WR_TASK_RETRY_ID_GET(
0484                             rdevp->enh_disc_to_tgt))
0485                 rn->fcp_flags |= FCP_SPPF_OVLY_ALLOW;
0486 
0487             if (FW_RDEV_WR_RETRY_GET(rdevp->enh_disc_to_tgt))
0488                 rn->fcp_flags |= FCP_SPPF_RETRY;
0489 
0490             if (FW_RDEV_WR_CONF_CMPL_GET(rdevp->enh_disc_to_tgt))
0491                 rn->fcp_flags |= FCP_SPPF_CONF_COMPL;
0492 
0493             if (FW_RDEV_WR_TGT_GET(rdevp->enh_disc_to_tgt))
0494                 rn->role |= CSIO_RNFR_TARGET;
0495 
0496             if (FW_RDEV_WR_INI_GET(rdevp->enh_disc_to_tgt))
0497                 rn->role |= CSIO_RNFR_INITIATOR;
0498         }
0499 
0500         break;
0501 
0502     case FDMI_VNPORT:
0503     case FAB_CTLR_VNPORT:
0504         rn->role = 0;
0505         break;
0506 
0507     default:
0508         csio_ln_err(ln, "ssni:x%x invalid rport type recv x%x\n",
0509             csio_rn_flowid(rn), rport_type);
0510         return -EINVAL;
0511     }
0512 
0513     /* validate wwpn/wwnn for Name server/remote port */
0514     if (rport_type == REG_VNPORT || rport_type == NS_VNPORT) {
0515         memset(null, 0, 8);
0516         if (!memcmp(rdevp->wwnn, null, 8)) {
0517             csio_ln_err(ln,
0518                     "ssni:x%x invalid wwnn received from"
0519                     " rport did:x%x\n",
0520                     csio_rn_flowid(rn),
0521                     (ntohl(*did) & CSIO_DID_MASK));
0522             return -EINVAL;
0523         }
0524 
0525         if (!memcmp(rdevp->wwpn, null, 8)) {
0526             csio_ln_err(ln,
0527                     "ssni:x%x invalid wwpn received from"
0528                     " rport did:x%x\n",
0529                     csio_rn_flowid(rn),
0530                     (ntohl(*did) & CSIO_DID_MASK));
0531             return -EINVAL;
0532         }
0533 
0534     }
0535 
0536     /* Copy wwnn, wwpn and nport id */
0537     rn->nport_id = (ntohl(*did) >> 8) & CSIO_DID_MASK;
0538     memcpy(csio_rn_wwnn(rn), rdevp->wwnn, 8);
0539     memcpy(csio_rn_wwpn(rn), rdevp->wwpn, 8);
0540     rn->rn_sparm.csp.sp_bb_data = rdevp->rcv_fr_sz;
0541     fc_class = FW_RDEV_WR_CLASS_GET(rdevp->vft_to_qos);
0542     rn->rn_sparm.clsp[fc_class - 1].cp_class = htons(FC_CPC_VALID);
0543 
0544     return 0;
0545 }
0546 
0547 static void
0548 __csio_reg_rnode(struct csio_rnode *rn)
0549 {
0550     struct csio_lnode *ln = csio_rnode_to_lnode(rn);
0551     struct csio_hw *hw = csio_lnode_to_hw(ln);
0552 
0553     spin_unlock_irq(&hw->lock);
0554     csio_reg_rnode(rn);
0555     spin_lock_irq(&hw->lock);
0556 
0557     if (rn->role & CSIO_RNFR_TARGET)
0558         ln->n_scsi_tgts++;
0559 
0560     if (rn->nport_id == FC_FID_MGMT_SERV)
0561         csio_ln_fdmi_start(ln, (void *) rn);
0562 }
0563 
0564 static void
0565 __csio_unreg_rnode(struct csio_rnode *rn)
0566 {
0567     struct csio_lnode *ln = csio_rnode_to_lnode(rn);
0568     struct csio_hw *hw = csio_lnode_to_hw(ln);
0569     LIST_HEAD(tmp_q);
0570     int cmpl = 0;
0571 
0572     if (!list_empty(&rn->host_cmpl_q)) {
0573         csio_dbg(hw, "Returning completion queue I/Os\n");
0574         list_splice_tail_init(&rn->host_cmpl_q, &tmp_q);
0575         cmpl = 1;
0576     }
0577 
0578     if (rn->role & CSIO_RNFR_TARGET) {
0579         ln->n_scsi_tgts--;
0580         ln->last_scan_ntgts--;
0581     }
0582 
0583     spin_unlock_irq(&hw->lock);
0584     csio_unreg_rnode(rn);
0585     spin_lock_irq(&hw->lock);
0586 
0587     /* Cleanup I/Os that were waiting for rnode to unregister */
0588     if (cmpl)
0589         csio_scsi_cleanup_io_q(csio_hw_to_scsim(hw), &tmp_q);
0590 
0591 }
0592 
0593 /*****************************************************************************/
0594 /* START: Rnode SM                                                           */
0595 /*****************************************************************************/
0596 
0597 /*
0598  * csio_rns_uninit -
0599  * @rn - rnode
0600  * @evt - SM event.
0601  *
0602  */
0603 static void
0604 csio_rns_uninit(struct csio_rnode *rn, enum csio_rn_ev evt)
0605 {
0606     struct csio_lnode *ln = csio_rnode_to_lnode(rn);
0607     int ret = 0;
0608 
0609     CSIO_INC_STATS(rn, n_evt_sm[evt]);
0610 
0611     switch (evt) {
0612     case CSIO_RNFE_LOGGED_IN:
0613     case CSIO_RNFE_PLOGI_RECV:
0614         ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
0615         if (!ret) {
0616             csio_set_state(&rn->sm, csio_rns_ready);
0617             __csio_reg_rnode(rn);
0618         } else {
0619             CSIO_INC_STATS(rn, n_err_inval);
0620         }
0621         break;
0622     case CSIO_RNFE_LOGO_RECV:
0623         csio_ln_dbg(ln,
0624                 "ssni:x%x Ignoring event %d recv "
0625                 "in rn state[uninit]\n", csio_rn_flowid(rn), evt);
0626         CSIO_INC_STATS(rn, n_evt_drop);
0627         break;
0628     default:
0629         csio_ln_dbg(ln,
0630                 "ssni:x%x unexp event %d recv "
0631                 "in rn state[uninit]\n", csio_rn_flowid(rn), evt);
0632         CSIO_INC_STATS(rn, n_evt_unexp);
0633         break;
0634     }
0635 }
0636 
0637 /*
0638  * csio_rns_ready -
0639  * @rn - rnode
0640  * @evt - SM event.
0641  *
0642  */
0643 static void
0644 csio_rns_ready(struct csio_rnode *rn, enum csio_rn_ev evt)
0645 {
0646     struct csio_lnode *ln = csio_rnode_to_lnode(rn);
0647     int ret = 0;
0648 
0649     CSIO_INC_STATS(rn, n_evt_sm[evt]);
0650 
0651     switch (evt) {
0652     case CSIO_RNFE_LOGGED_IN:
0653     case CSIO_RNFE_PLOGI_RECV:
0654         csio_ln_dbg(ln,
0655             "ssni:x%x Ignoring event %d recv from did:x%x "
0656             "in rn state[ready]\n", csio_rn_flowid(rn), evt,
0657             rn->nport_id);
0658         CSIO_INC_STATS(rn, n_evt_drop);
0659         break;
0660 
0661     case CSIO_RNFE_PRLI_DONE:
0662     case CSIO_RNFE_PRLI_RECV:
0663         ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
0664         if (!ret)
0665             __csio_reg_rnode(rn);
0666         else
0667             CSIO_INC_STATS(rn, n_err_inval);
0668 
0669         break;
0670     case CSIO_RNFE_DOWN:
0671         csio_set_state(&rn->sm, csio_rns_offline);
0672         __csio_unreg_rnode(rn);
0673 
0674         /* FW expected to internally aborted outstanding SCSI WRs
0675          * and return all SCSI WRs to host with status "ABORTED".
0676          */
0677         break;
0678 
0679     case CSIO_RNFE_LOGO_RECV:
0680         csio_set_state(&rn->sm, csio_rns_offline);
0681 
0682         __csio_unreg_rnode(rn);
0683 
0684         /* FW expected to internally aborted outstanding SCSI WRs
0685          * and return all SCSI WRs to host with status "ABORTED".
0686          */
0687         break;
0688 
0689     case CSIO_RNFE_CLOSE:
0690         /*
0691          * Each rnode receives CLOSE event when driver is removed or
0692          * device is reset
0693          * Note: All outstanding IOs on remote port need to returned
0694          * to uppper layer with appropriate error before sending
0695          * CLOSE event
0696          */
0697         csio_set_state(&rn->sm, csio_rns_uninit);
0698         __csio_unreg_rnode(rn);
0699         break;
0700 
0701     case CSIO_RNFE_NAME_MISSING:
0702         csio_set_state(&rn->sm, csio_rns_disappeared);
0703         __csio_unreg_rnode(rn);
0704 
0705         /*
0706          * FW expected to internally aborted outstanding SCSI WRs
0707          * and return all SCSI WRs to host with status "ABORTED".
0708          */
0709 
0710         break;
0711 
0712     default:
0713         csio_ln_dbg(ln,
0714             "ssni:x%x unexp event %d recv from did:x%x "
0715             "in rn state[uninit]\n", csio_rn_flowid(rn), evt,
0716             rn->nport_id);
0717         CSIO_INC_STATS(rn, n_evt_unexp);
0718         break;
0719     }
0720 }
0721 
0722 /*
0723  * csio_rns_offline -
0724  * @rn - rnode
0725  * @evt - SM event.
0726  *
0727  */
0728 static void
0729 csio_rns_offline(struct csio_rnode *rn, enum csio_rn_ev evt)
0730 {
0731     struct csio_lnode *ln = csio_rnode_to_lnode(rn);
0732     int ret = 0;
0733 
0734     CSIO_INC_STATS(rn, n_evt_sm[evt]);
0735 
0736     switch (evt) {
0737     case CSIO_RNFE_LOGGED_IN:
0738     case CSIO_RNFE_PLOGI_RECV:
0739         ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
0740         if (!ret) {
0741             csio_set_state(&rn->sm, csio_rns_ready);
0742             __csio_reg_rnode(rn);
0743         } else {
0744             CSIO_INC_STATS(rn, n_err_inval);
0745             csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
0746         }
0747         break;
0748 
0749     case CSIO_RNFE_DOWN:
0750         csio_ln_dbg(ln,
0751             "ssni:x%x Ignoring event %d recv from did:x%x "
0752             "in rn state[offline]\n", csio_rn_flowid(rn), evt,
0753             rn->nport_id);
0754         CSIO_INC_STATS(rn, n_evt_drop);
0755         break;
0756 
0757     case CSIO_RNFE_CLOSE:
0758         /* Each rnode receives CLOSE event when driver is removed or
0759          * device is reset
0760          * Note: All outstanding IOs on remote port need to returned
0761          * to uppper layer with appropriate error before sending
0762          * CLOSE event
0763          */
0764         csio_set_state(&rn->sm, csio_rns_uninit);
0765         break;
0766 
0767     case CSIO_RNFE_NAME_MISSING:
0768         csio_set_state(&rn->sm, csio_rns_disappeared);
0769         break;
0770 
0771     default:
0772         csio_ln_dbg(ln,
0773             "ssni:x%x unexp event %d recv from did:x%x "
0774             "in rn state[offline]\n", csio_rn_flowid(rn), evt,
0775             rn->nport_id);
0776         CSIO_INC_STATS(rn, n_evt_unexp);
0777         break;
0778     }
0779 }
0780 
0781 /*
0782  * csio_rns_disappeared -
0783  * @rn - rnode
0784  * @evt - SM event.
0785  *
0786  */
0787 static void
0788 csio_rns_disappeared(struct csio_rnode *rn, enum csio_rn_ev evt)
0789 {
0790     struct csio_lnode *ln = csio_rnode_to_lnode(rn);
0791     int ret = 0;
0792 
0793     CSIO_INC_STATS(rn, n_evt_sm[evt]);
0794 
0795     switch (evt) {
0796     case CSIO_RNFE_LOGGED_IN:
0797     case CSIO_RNFE_PLOGI_RECV:
0798         ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
0799         if (!ret) {
0800             csio_set_state(&rn->sm, csio_rns_ready);
0801             __csio_reg_rnode(rn);
0802         } else {
0803             CSIO_INC_STATS(rn, n_err_inval);
0804             csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
0805         }
0806         break;
0807 
0808     case CSIO_RNFE_CLOSE:
0809         /* Each rnode receives CLOSE event when driver is removed or
0810          * device is reset.
0811          * Note: All outstanding IOs on remote port need to returned
0812          * to uppper layer with appropriate error before sending
0813          * CLOSE event
0814          */
0815         csio_set_state(&rn->sm, csio_rns_uninit);
0816         break;
0817 
0818     case CSIO_RNFE_DOWN:
0819     case CSIO_RNFE_NAME_MISSING:
0820         csio_ln_dbg(ln,
0821             "ssni:x%x Ignoring event %d recv from did x%x"
0822             "in rn state[disappeared]\n", csio_rn_flowid(rn),
0823             evt, rn->nport_id);
0824         break;
0825 
0826     default:
0827         csio_ln_dbg(ln,
0828             "ssni:x%x unexp event %d recv from did x%x"
0829             "in rn state[disappeared]\n", csio_rn_flowid(rn),
0830             evt, rn->nport_id);
0831         CSIO_INC_STATS(rn, n_evt_unexp);
0832         break;
0833     }
0834 }
0835 
0836 /*****************************************************************************/
0837 /* END: Rnode SM                                                             */
0838 /*****************************************************************************/
0839 
0840 /*
0841  * csio_rnode_devloss_handler - Device loss event handler
0842  * @rn: rnode
0843  *
0844  * Post event to close rnode SM and free rnode.
0845  */
0846 void
0847 csio_rnode_devloss_handler(struct csio_rnode *rn)
0848 {
0849     struct csio_lnode *ln = csio_rnode_to_lnode(rn);
0850 
0851     /* ignore if same rnode came back as online */
0852     if (csio_is_rnode_ready(rn))
0853         return;
0854 
0855     csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
0856 
0857     /* Free rn if in uninit state */
0858     if (csio_is_rnode_uninit(rn))
0859         csio_put_rnode(ln, rn);
0860 }
0861 
0862 /**
0863  * csio_rnode_fwevt_handler - Event handler for firmware rnode events.
0864  * @rn:     rnode
0865  * @fwevt:  firmware event to handle
0866  */
0867 void
0868 csio_rnode_fwevt_handler(struct csio_rnode *rn, uint8_t fwevt)
0869 {
0870     struct csio_lnode *ln = csio_rnode_to_lnode(rn);
0871     enum csio_rn_ev evt;
0872 
0873     evt = CSIO_FWE_TO_RNFE(fwevt);
0874     if (!evt) {
0875         csio_ln_err(ln, "ssni:x%x Unhandled FW Rdev event: %d\n",
0876                 csio_rn_flowid(rn), fwevt);
0877         CSIO_INC_STATS(rn, n_evt_unexp);
0878         return;
0879     }
0880     CSIO_INC_STATS(rn, n_evt_fw[fwevt]);
0881 
0882     /* Track previous & current events for debugging */
0883     rn->prev_evt = rn->cur_evt;
0884     rn->cur_evt = fwevt;
0885 
0886     /* Post event to rnode SM */
0887     csio_post_event(&rn->sm, evt);
0888 
0889     /* Free rn if in uninit state */
0890     if (csio_is_rnode_uninit(rn))
0891         csio_put_rnode(ln, rn);
0892 }
0893 
0894 /*
0895  * csio_rnode_init - Initialize rnode.
0896  * @rn: RNode
0897  * @ln: Associated lnode
0898  *
0899  * Caller is responsible for holding the lock. The lock is required
0900  * to be held for inserting the rnode in ln->rnhead list.
0901  */
0902 static int
0903 csio_rnode_init(struct csio_rnode *rn, struct csio_lnode *ln)
0904 {
0905     csio_rnode_to_lnode(rn) = ln;
0906     csio_init_state(&rn->sm, csio_rns_uninit);
0907     INIT_LIST_HEAD(&rn->host_cmpl_q);
0908     csio_rn_flowid(rn) = CSIO_INVALID_IDX;
0909 
0910     /* Add rnode to list of lnodes->rnhead */
0911     list_add_tail(&rn->sm.sm_list, &ln->rnhead);
0912 
0913     return 0;
0914 }
0915 
0916 static void
0917 csio_rnode_exit(struct csio_rnode *rn)
0918 {
0919     list_del_init(&rn->sm.sm_list);
0920     CSIO_DB_ASSERT(list_empty(&rn->host_cmpl_q));
0921 }