0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
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
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
0055 static enum csio_rn_ev fwevt_to_rnevt[] = {
0056 CSIO_RNFE_NONE,
0057 CSIO_RNFE_LOGGED_IN,
0058 CSIO_RNFE_NONE,
0059 CSIO_RNFE_PLOGI_RECV,
0060 CSIO_RNFE_LOGO_RECV,
0061 CSIO_RNFE_PRLI_DONE,
0062 CSIO_RNFE_NONE,
0063 CSIO_RNFE_PRLI_RECV,
0064 CSIO_RNFE_PRLO_RECV,
0065 CSIO_RNFE_NONE,
0066 CSIO_RNFE_LOGO_RECV,
0067 CSIO_RNFE_NONE,
0068 CSIO_RNFE_LOGGED_IN,
0069 CSIO_RNFE_NONE,
0070 CSIO_RNFE_LOGGED_IN,
0071 CSIO_RNFE_NONE,
0072 CSIO_RNFE_NONE,
0073 CSIO_RNFE_NONE,
0074 CSIO_RNFE_NONE,
0075 CSIO_RNFE_NONE,
0076 CSIO_RNFE_NONE,
0077 CSIO_RNFE_NONE,
0078 CSIO_RNFE_NAME_MISSING,
0079 CSIO_RNFE_NONE,
0080 CSIO_RNFE_NONE,
0081 CSIO_RNFE_NONE,
0082 CSIO_RNFE_LOGO_RECV,
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
0114
0115
0116
0117
0118
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
0138
0139
0140
0141
0142
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
0162
0163
0164
0165
0166
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
0251
0252
0253
0254
0255
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
0276
0277
0278
0279
0280
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
0291
0292
0293
0294
0295
0296
0297
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
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
0321 rn = csio_rn_lookup(ln, rdev_flowid);
0322 if (!rn) {
0323
0324
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
0333 rn = csio_rn_lookup_wwpn(ln, rdevp->wwpn);
0334 if (!rn)
0335 goto alloc_rnode;
0336
0337 } else {
0338
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
0349
0350
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
0372 goto found_rnode;
0373 }
0374 csio_rn_flowid(rn) = CSIO_INVALID_IDX;
0375 goto alloc_rnode;
0376 }
0377
0378
0379 if (!memcmp(csio_rn_wwpn(rn), rdevp->wwpn, 8))
0380 goto found_rnode;
0381
0382
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
0416 csio_rn_flowid(rn) = rdev_flowid;
0417
0418
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
0432 rn->rdev_entry = rdevp;
0433 return rn;
0434 }
0435
0436
0437
0438
0439
0440
0441
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
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
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
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
0588 if (cmpl)
0589 csio_scsi_cleanup_io_q(csio_hw_to_scsim(hw), &tmp_q);
0590
0591 }
0592
0593
0594
0595
0596
0597
0598
0599
0600
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
0639
0640
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
0675
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
0685
0686
0687 break;
0688
0689 case CSIO_RNFE_CLOSE:
0690
0691
0692
0693
0694
0695
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
0707
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
0724
0725
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
0759
0760
0761
0762
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
0783
0784
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
0810
0811
0812
0813
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
0838
0839
0840
0841
0842
0843
0844
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
0852 if (csio_is_rnode_ready(rn))
0853 return;
0854
0855 csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
0856
0857
0858 if (csio_is_rnode_uninit(rn))
0859 csio_put_rnode(ln, rn);
0860 }
0861
0862
0863
0864
0865
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
0883 rn->prev_evt = rn->cur_evt;
0884 rn->cur_evt = fwevt;
0885
0886
0887 csio_post_event(&rn->sm, evt);
0888
0889
0890 if (csio_is_rnode_uninit(rn))
0891 csio_put_rnode(ln, rn);
0892 }
0893
0894
0895
0896
0897
0898
0899
0900
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
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 }