1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35#include <linux/string.h>
36#include <scsi/scsi_device.h>
37#include <scsi/scsi_transport_fc.h>
38#include <scsi/fc/fc_els.h>
39#include <scsi/fc/fc_fs.h>
40
41#include "csio_hw.h"
42#include "csio_lnode.h"
43#include "csio_rnode.h"
44
45static int csio_rnode_init(struct csio_rnode *, struct csio_lnode *);
46static void csio_rnode_exit(struct csio_rnode *);
47
48
49static void csio_rns_uninit(struct csio_rnode *, enum csio_rn_ev);
50static void csio_rns_ready(struct csio_rnode *, enum csio_rn_ev);
51static void csio_rns_offline(struct csio_rnode *, enum csio_rn_ev);
52static void csio_rns_disappeared(struct csio_rnode *, enum csio_rn_ev);
53
54
55static enum csio_rn_ev fwevt_to_rnevt[] = {
56 CSIO_RNFE_NONE,
57 CSIO_RNFE_LOGGED_IN,
58 CSIO_RNFE_NONE,
59 CSIO_RNFE_PLOGI_RECV,
60 CSIO_RNFE_LOGO_RECV,
61 CSIO_RNFE_PRLI_DONE,
62 CSIO_RNFE_NONE,
63 CSIO_RNFE_PRLI_RECV,
64 CSIO_RNFE_PRLO_RECV,
65 CSIO_RNFE_NONE,
66 CSIO_RNFE_LOGO_RECV,
67 CSIO_RNFE_NONE,
68 CSIO_RNFE_LOGGED_IN,
69 CSIO_RNFE_NONE,
70 CSIO_RNFE_LOGGED_IN,
71 CSIO_RNFE_NONE,
72 CSIO_RNFE_NONE,
73 CSIO_RNFE_NONE,
74 CSIO_RNFE_NONE,
75 CSIO_RNFE_NONE,
76 CSIO_RNFE_NONE,
77 CSIO_RNFE_NONE,
78 CSIO_RNFE_NAME_MISSING,
79 CSIO_RNFE_NONE,
80 CSIO_RNFE_NONE,
81 CSIO_RNFE_NONE,
82 CSIO_RNFE_LOGO_RECV,
83};
84
85#define CSIO_FWE_TO_RNFE(_evt) ((_evt > PROTO_ERR_IMPL_LOGO) ? \
86 CSIO_RNFE_NONE : \
87 fwevt_to_rnevt[_evt])
88int
89csio_is_rnode_ready(struct csio_rnode *rn)
90{
91 return csio_match_state(rn, csio_rns_ready);
92}
93
94static int
95csio_is_rnode_uninit(struct csio_rnode *rn)
96{
97 return csio_match_state(rn, csio_rns_uninit);
98}
99
100static int
101csio_is_rnode_wka(uint8_t rport_type)
102{
103 if ((rport_type == FLOGI_VFPORT) ||
104 (rport_type == FDISC_VFPORT) ||
105 (rport_type == NS_VNPORT) ||
106 (rport_type == FDMI_VNPORT))
107 return 1;
108
109 return 0;
110}
111
112
113
114
115
116
117
118
119
120static struct csio_rnode *
121csio_rn_lookup(struct csio_lnode *ln, uint32_t flowid)
122{
123 struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
124 struct list_head *tmp;
125 struct csio_rnode *rn;
126
127 list_for_each(tmp, &rnhead->sm.sm_list) {
128 rn = (struct csio_rnode *) tmp;
129 if (rn->flowid == flowid)
130 return rn;
131 }
132
133 return NULL;
134}
135
136
137
138
139
140
141
142
143
144static struct csio_rnode *
145csio_rn_lookup_wwpn(struct csio_lnode *ln, uint8_t *wwpn)
146{
147 struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
148 struct list_head *tmp;
149 struct csio_rnode *rn;
150
151 list_for_each(tmp, &rnhead->sm.sm_list) {
152 rn = (struct csio_rnode *) tmp;
153 if (!memcmp(csio_rn_wwpn(rn), wwpn, 8))
154 return rn;
155 }
156
157 return NULL;
158}
159
160
161
162
163
164
165
166
167
168struct csio_rnode *
169csio_rnode_lookup_portid(struct csio_lnode *ln, uint32_t portid)
170{
171 struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
172 struct list_head *tmp;
173 struct csio_rnode *rn;
174
175 list_for_each(tmp, &rnhead->sm.sm_list) {
176 rn = (struct csio_rnode *) tmp;
177 if (rn->nport_id == portid)
178 return rn;
179 }
180
181 return NULL;
182}
183
184static int
185csio_rn_dup_flowid(struct csio_lnode *ln, uint32_t rdev_flowid,
186 uint32_t *vnp_flowid)
187{
188 struct csio_rnode *rnhead;
189 struct list_head *tmp, *tmp1;
190 struct csio_rnode *rn;
191 struct csio_lnode *ln_tmp;
192 struct csio_hw *hw = csio_lnode_to_hw(ln);
193
194 list_for_each(tmp1, &hw->sln_head) {
195 ln_tmp = (struct csio_lnode *) tmp1;
196 if (ln_tmp == ln)
197 continue;
198
199 rnhead = (struct csio_rnode *)&ln_tmp->rnhead;
200 list_for_each(tmp, &rnhead->sm.sm_list) {
201
202 rn = (struct csio_rnode *) tmp;
203 if (csio_is_rnode_ready(rn)) {
204 if (rn->flowid == rdev_flowid) {
205 *vnp_flowid = csio_ln_flowid(ln_tmp);
206 return 1;
207 }
208 }
209 }
210 }
211
212 return 0;
213}
214
215static struct csio_rnode *
216csio_alloc_rnode(struct csio_lnode *ln)
217{
218 struct csio_hw *hw = csio_lnode_to_hw(ln);
219
220 struct csio_rnode *rn = mempool_alloc(hw->rnode_mempool, GFP_ATOMIC);
221 if (!rn)
222 goto err;
223
224 memset(rn, 0, sizeof(struct csio_rnode));
225 if (csio_rnode_init(rn, ln))
226 goto err_free;
227
228 CSIO_INC_STATS(ln, n_rnode_alloc);
229
230 return rn;
231
232err_free:
233 mempool_free(rn, hw->rnode_mempool);
234err:
235 CSIO_INC_STATS(ln, n_rnode_nomem);
236 return NULL;
237}
238
239static void
240csio_free_rnode(struct csio_rnode *rn)
241{
242 struct csio_hw *hw = csio_lnode_to_hw(csio_rnode_to_lnode(rn));
243
244 csio_rnode_exit(rn);
245 CSIO_INC_STATS(rn->lnp, n_rnode_free);
246 mempool_free(rn, hw->rnode_mempool);
247}
248
249
250
251
252
253
254
255
256
257static struct csio_rnode *
258csio_get_rnode(struct csio_lnode *ln, uint32_t flowid)
259{
260 struct csio_rnode *rn;
261
262 rn = csio_rn_lookup(ln, flowid);
263 if (!rn) {
264 rn = csio_alloc_rnode(ln);
265 if (!rn)
266 return NULL;
267
268 rn->flowid = flowid;
269 }
270
271 return rn;
272}
273
274
275
276
277
278
279
280
281
282void
283csio_put_rnode(struct csio_lnode *ln, struct csio_rnode *rn)
284{
285 CSIO_DB_ASSERT(csio_is_rnode_uninit(rn) != 0);
286 csio_free_rnode(rn);
287}
288
289
290
291
292
293
294
295
296
297
298
299struct csio_rnode *
300csio_confirm_rnode(struct csio_lnode *ln, uint32_t rdev_flowid,
301 struct fcoe_rdev_entry *rdevp)
302{
303 uint8_t rport_type;
304 struct csio_rnode *rn, *match_rn;
305 uint32_t vnp_flowid = 0;
306 __be32 *port_id;
307
308 port_id = (__be32 *)&rdevp->r_id[0];
309 rport_type =
310 FW_RDEV_WR_RPORT_TYPE_GET(rdevp->rd_xfer_rdy_to_rport_type);
311
312
313 if (rport_type == FAB_CTLR_VNPORT) {
314 csio_ln_dbg(ln,
315 "Unhandled rport_type:%d recv in rdev evt "
316 "ssni:x%x\n", rport_type, rdev_flowid);
317 return NULL;
318 }
319
320
321 rn = csio_rn_lookup(ln, rdev_flowid);
322 if (!rn) {
323
324
325 if (csio_rn_dup_flowid(ln, rdev_flowid, &vnp_flowid)) {
326 csio_ln_warn(ln,
327 "ssni:%x already active on vnpi:%x",
328 rdev_flowid, vnp_flowid);
329 return NULL;
330 }
331
332
333 rn = csio_rn_lookup_wwpn(ln, rdevp->wwpn);
334 if (!rn)
335 goto alloc_rnode;
336
337 } else {
338
339 if (csio_is_rnode_wka(rport_type)) {
340 match_rn = csio_rnode_lookup_portid(ln,
341 ((ntohl(*port_id) >> 8) & CSIO_DID_MASK));
342 if (match_rn == NULL) {
343 csio_rn_flowid(rn) = CSIO_INVALID_IDX;
344 goto alloc_rnode;
345 }
346
347
348
349
350
351
352 if (!memcmp(csio_rn_wwpn(match_rn), rdevp->wwpn, 8)) {
353 if (rn == match_rn)
354 goto found_rnode;
355 csio_ln_dbg(ln,
356 "nport_id:x%x and wwpn:%llx"
357 " match for ssni:x%x\n",
358 rn->nport_id,
359 wwn_to_u64(rdevp->wwpn),
360 rdev_flowid);
361 if (csio_is_rnode_ready(rn)) {
362 csio_ln_warn(ln,
363 "rnode is already"
364 "active ssni:x%x\n",
365 rdev_flowid);
366 CSIO_ASSERT(0);
367 }
368 csio_rn_flowid(rn) = CSIO_INVALID_IDX;
369 rn = match_rn;
370
371
372 goto found_rnode;
373 }
374 csio_rn_flowid(rn) = CSIO_INVALID_IDX;
375 goto alloc_rnode;
376 }
377
378
379 if (!memcmp(csio_rn_wwpn(rn), rdevp->wwpn, 8))
380 goto found_rnode;
381
382
383 match_rn = csio_rn_lookup_wwpn(ln, rdevp->wwpn);
384 if (match_rn != NULL) {
385 csio_ln_dbg(ln,
386 "ssni:x%x changed for rport name(wwpn):%llx "
387 "did:x%x\n", rdev_flowid,
388 wwn_to_u64(rdevp->wwpn),
389 match_rn->nport_id);
390 csio_rn_flowid(rn) = CSIO_INVALID_IDX;
391 rn = match_rn;
392 } else {
393 csio_ln_dbg(ln,
394 "rnode wwpn mismatch found ssni:x%x "
395 "name(wwpn):%llx\n",
396 rdev_flowid,
397 wwn_to_u64(csio_rn_wwpn(rn)));
398 if (csio_is_rnode_ready(rn)) {
399 csio_ln_warn(ln,
400 "rnode is already active "
401 "wwpn:%llx ssni:x%x\n",
402 wwn_to_u64(csio_rn_wwpn(rn)),
403 rdev_flowid);
404 CSIO_ASSERT(0);
405 }
406 csio_rn_flowid(rn) = CSIO_INVALID_IDX;
407 goto alloc_rnode;
408 }
409 }
410
411found_rnode:
412 csio_ln_dbg(ln, "found rnode:%p ssni:x%x name(wwpn):%llx\n",
413 rn, rdev_flowid, wwn_to_u64(rdevp->wwpn));
414
415
416 csio_rn_flowid(rn) = rdev_flowid;
417
418
419 rn->rdev_entry = rdevp;
420 CSIO_INC_STATS(ln, n_rnode_match);
421 return rn;
422
423alloc_rnode:
424 rn = csio_get_rnode(ln, rdev_flowid);
425 if (!rn)
426 return NULL;
427
428 csio_ln_dbg(ln, "alloc rnode:%p ssni:x%x name(wwpn):%llx\n",
429 rn, rdev_flowid, wwn_to_u64(rdevp->wwpn));
430
431
432 rn->rdev_entry = rdevp;
433 return rn;
434}
435
436
437
438
439
440
441
442
443static int
444csio_rn_verify_rparams(struct csio_lnode *ln, struct csio_rnode *rn,
445 struct fcoe_rdev_entry *rdevp)
446{
447 uint8_t null[8];
448 uint8_t rport_type;
449 uint8_t fc_class;
450 __be32 *did;
451
452 did = (__be32 *) &rdevp->r_id[0];
453 rport_type =
454 FW_RDEV_WR_RPORT_TYPE_GET(rdevp->rd_xfer_rdy_to_rport_type);
455 switch (rport_type) {
456 case FLOGI_VFPORT:
457 rn->role = CSIO_RNFR_FABRIC;
458 if (((ntohl(*did) >> 8) & CSIO_DID_MASK) != FC_FID_FLOGI) {
459 csio_ln_err(ln, "ssni:x%x invalid fabric portid\n",
460 csio_rn_flowid(rn));
461 return -EINVAL;
462 }
463
464 if (FW_RDEV_WR_NPIV_GET(rdevp->vft_to_qos))
465 ln->flags |= CSIO_LNF_NPIVSUPP;
466
467 break;
468
469 case NS_VNPORT:
470 rn->role = CSIO_RNFR_NS;
471 if (((ntohl(*did) >> 8) & CSIO_DID_MASK) != FC_FID_DIR_SERV) {
472 csio_ln_err(ln, "ssni:x%x invalid fabric portid\n",
473 csio_rn_flowid(rn));
474 return -EINVAL;
475 }
476 break;
477
478 case REG_FC4_VNPORT:
479 case REG_VNPORT:
480 rn->role = CSIO_RNFR_NPORT;
481 if (rdevp->event_cause == PRLI_ACC_RCVD ||
482 rdevp->event_cause == PRLI_RCVD) {
483 if (FW_RDEV_WR_TASK_RETRY_ID_GET(
484 rdevp->enh_disc_to_tgt))
485 rn->fcp_flags |= FCP_SPPF_OVLY_ALLOW;
486
487 if (FW_RDEV_WR_RETRY_GET(rdevp->enh_disc_to_tgt))
488 rn->fcp_flags |= FCP_SPPF_RETRY;
489
490 if (FW_RDEV_WR_CONF_CMPL_GET(rdevp->enh_disc_to_tgt))
491 rn->fcp_flags |= FCP_SPPF_CONF_COMPL;
492
493 if (FW_RDEV_WR_TGT_GET(rdevp->enh_disc_to_tgt))
494 rn->role |= CSIO_RNFR_TARGET;
495
496 if (FW_RDEV_WR_INI_GET(rdevp->enh_disc_to_tgt))
497 rn->role |= CSIO_RNFR_INITIATOR;
498 }
499
500 break;
501
502 case FDMI_VNPORT:
503 case FAB_CTLR_VNPORT:
504 rn->role = 0;
505 break;
506
507 default:
508 csio_ln_err(ln, "ssni:x%x invalid rport type recv x%x\n",
509 csio_rn_flowid(rn), rport_type);
510 return -EINVAL;
511 }
512
513
514 if (rport_type == REG_VNPORT || rport_type == NS_VNPORT) {
515 memset(null, 0, 8);
516 if (!memcmp(rdevp->wwnn, null, 8)) {
517 csio_ln_err(ln,
518 "ssni:x%x invalid wwnn received from"
519 " rport did:x%x\n",
520 csio_rn_flowid(rn),
521 (ntohl(*did) & CSIO_DID_MASK));
522 return -EINVAL;
523 }
524
525 if (!memcmp(rdevp->wwpn, null, 8)) {
526 csio_ln_err(ln,
527 "ssni:x%x invalid wwpn received from"
528 " rport did:x%x\n",
529 csio_rn_flowid(rn),
530 (ntohl(*did) & CSIO_DID_MASK));
531 return -EINVAL;
532 }
533
534 }
535
536
537 rn->nport_id = (ntohl(*did) >> 8) & CSIO_DID_MASK;
538 memcpy(csio_rn_wwnn(rn), rdevp->wwnn, 8);
539 memcpy(csio_rn_wwpn(rn), rdevp->wwpn, 8);
540 rn->rn_sparm.csp.sp_bb_data = rdevp->rcv_fr_sz;
541 fc_class = FW_RDEV_WR_CLASS_GET(rdevp->vft_to_qos);
542 rn->rn_sparm.clsp[fc_class - 1].cp_class = htons(FC_CPC_VALID);
543
544 return 0;
545}
546
547static void
548__csio_reg_rnode(struct csio_rnode *rn)
549{
550 struct csio_lnode *ln = csio_rnode_to_lnode(rn);
551 struct csio_hw *hw = csio_lnode_to_hw(ln);
552
553 spin_unlock_irq(&hw->lock);
554 csio_reg_rnode(rn);
555 spin_lock_irq(&hw->lock);
556
557 if (rn->role & CSIO_RNFR_TARGET)
558 ln->n_scsi_tgts++;
559
560 if (rn->nport_id == FC_FID_MGMT_SERV)
561 csio_ln_fdmi_start(ln, (void *) rn);
562}
563
564static void
565__csio_unreg_rnode(struct csio_rnode *rn)
566{
567 struct csio_lnode *ln = csio_rnode_to_lnode(rn);
568 struct csio_hw *hw = csio_lnode_to_hw(ln);
569 LIST_HEAD(tmp_q);
570 int cmpl = 0;
571
572 if (!list_empty(&rn->host_cmpl_q)) {
573 csio_dbg(hw, "Returning completion queue I/Os\n");
574 list_splice_tail_init(&rn->host_cmpl_q, &tmp_q);
575 cmpl = 1;
576 }
577
578 if (rn->role & CSIO_RNFR_TARGET) {
579 ln->n_scsi_tgts--;
580 ln->last_scan_ntgts--;
581 }
582
583 spin_unlock_irq(&hw->lock);
584 csio_unreg_rnode(rn);
585 spin_lock_irq(&hw->lock);
586
587
588 if (cmpl)
589 csio_scsi_cleanup_io_q(csio_hw_to_scsim(hw), &tmp_q);
590
591}
592
593
594
595
596
597
598
599
600
601
602
603static void
604csio_rns_uninit(struct csio_rnode *rn, enum csio_rn_ev evt)
605{
606 struct csio_lnode *ln = csio_rnode_to_lnode(rn);
607 int ret = 0;
608
609 CSIO_INC_STATS(rn, n_evt_sm[evt]);
610
611 switch (evt) {
612 case CSIO_RNFE_LOGGED_IN:
613 case CSIO_RNFE_PLOGI_RECV:
614 ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
615 if (!ret) {
616 csio_set_state(&rn->sm, csio_rns_ready);
617 __csio_reg_rnode(rn);
618 } else {
619 CSIO_INC_STATS(rn, n_err_inval);
620 }
621 break;
622 case CSIO_RNFE_LOGO_RECV:
623 csio_ln_dbg(ln,
624 "ssni:x%x Ignoring event %d recv "
625 "in rn state[uninit]\n", csio_rn_flowid(rn), evt);
626 CSIO_INC_STATS(rn, n_evt_drop);
627 break;
628 default:
629 csio_ln_dbg(ln,
630 "ssni:x%x unexp event %d recv "
631 "in rn state[uninit]\n", csio_rn_flowid(rn), evt);
632 CSIO_INC_STATS(rn, n_evt_unexp);
633 break;
634 }
635}
636
637
638
639
640
641
642
643static void
644csio_rns_ready(struct csio_rnode *rn, enum csio_rn_ev evt)
645{
646 struct csio_lnode *ln = csio_rnode_to_lnode(rn);
647 int ret = 0;
648
649 CSIO_INC_STATS(rn, n_evt_sm[evt]);
650
651 switch (evt) {
652 case CSIO_RNFE_LOGGED_IN:
653 case CSIO_RNFE_PLOGI_RECV:
654 csio_ln_dbg(ln,
655 "ssni:x%x Ignoring event %d recv from did:x%x "
656 "in rn state[ready]\n", csio_rn_flowid(rn), evt,
657 rn->nport_id);
658 CSIO_INC_STATS(rn, n_evt_drop);
659 break;
660
661 case CSIO_RNFE_PRLI_DONE:
662 case CSIO_RNFE_PRLI_RECV:
663 ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
664 if (!ret)
665 __csio_reg_rnode(rn);
666 else
667 CSIO_INC_STATS(rn, n_err_inval);
668
669 break;
670 case CSIO_RNFE_DOWN:
671 csio_set_state(&rn->sm, csio_rns_offline);
672 __csio_unreg_rnode(rn);
673
674
675
676
677 break;
678
679 case CSIO_RNFE_LOGO_RECV:
680 csio_set_state(&rn->sm, csio_rns_offline);
681
682 __csio_unreg_rnode(rn);
683
684
685
686
687 break;
688
689 case CSIO_RNFE_CLOSE:
690
691
692
693
694
695
696
697 csio_set_state(&rn->sm, csio_rns_uninit);
698 __csio_unreg_rnode(rn);
699 break;
700
701 case CSIO_RNFE_NAME_MISSING:
702 csio_set_state(&rn->sm, csio_rns_disappeared);
703 __csio_unreg_rnode(rn);
704
705
706
707
708
709
710 break;
711
712 default:
713 csio_ln_dbg(ln,
714 "ssni:x%x unexp event %d recv from did:x%x "
715 "in rn state[uninit]\n", csio_rn_flowid(rn), evt,
716 rn->nport_id);
717 CSIO_INC_STATS(rn, n_evt_unexp);
718 break;
719 }
720}
721
722
723
724
725
726
727
728static void
729csio_rns_offline(struct csio_rnode *rn, enum csio_rn_ev evt)
730{
731 struct csio_lnode *ln = csio_rnode_to_lnode(rn);
732 int ret = 0;
733
734 CSIO_INC_STATS(rn, n_evt_sm[evt]);
735
736 switch (evt) {
737 case CSIO_RNFE_LOGGED_IN:
738 case CSIO_RNFE_PLOGI_RECV:
739 ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
740 if (!ret) {
741 csio_set_state(&rn->sm, csio_rns_ready);
742 __csio_reg_rnode(rn);
743 } else {
744 CSIO_INC_STATS(rn, n_err_inval);
745 csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
746 }
747 break;
748
749 case CSIO_RNFE_DOWN:
750 csio_ln_dbg(ln,
751 "ssni:x%x Ignoring event %d recv from did:x%x "
752 "in rn state[offline]\n", csio_rn_flowid(rn), evt,
753 rn->nport_id);
754 CSIO_INC_STATS(rn, n_evt_drop);
755 break;
756
757 case CSIO_RNFE_CLOSE:
758
759
760
761
762
763
764 csio_set_state(&rn->sm, csio_rns_uninit);
765 break;
766
767 case CSIO_RNFE_NAME_MISSING:
768 csio_set_state(&rn->sm, csio_rns_disappeared);
769 break;
770
771 default:
772 csio_ln_dbg(ln,
773 "ssni:x%x unexp event %d recv from did:x%x "
774 "in rn state[offline]\n", csio_rn_flowid(rn), evt,
775 rn->nport_id);
776 CSIO_INC_STATS(rn, n_evt_unexp);
777 break;
778 }
779}
780
781
782
783
784
785
786
787static void
788csio_rns_disappeared(struct csio_rnode *rn, enum csio_rn_ev evt)
789{
790 struct csio_lnode *ln = csio_rnode_to_lnode(rn);
791 int ret = 0;
792
793 CSIO_INC_STATS(rn, n_evt_sm[evt]);
794
795 switch (evt) {
796 case CSIO_RNFE_LOGGED_IN:
797 case CSIO_RNFE_PLOGI_RECV:
798 ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
799 if (!ret) {
800 csio_set_state(&rn->sm, csio_rns_ready);
801 __csio_reg_rnode(rn);
802 } else {
803 CSIO_INC_STATS(rn, n_err_inval);
804 csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
805 }
806 break;
807
808 case CSIO_RNFE_CLOSE:
809
810
811
812
813
814
815 csio_set_state(&rn->sm, csio_rns_uninit);
816 break;
817
818 case CSIO_RNFE_DOWN:
819 case CSIO_RNFE_NAME_MISSING:
820 csio_ln_dbg(ln,
821 "ssni:x%x Ignoring event %d recv from did x%x"
822 "in rn state[disappeared]\n", csio_rn_flowid(rn),
823 evt, rn->nport_id);
824 break;
825
826 default:
827 csio_ln_dbg(ln,
828 "ssni:x%x unexp event %d recv from did x%x"
829 "in rn state[disappeared]\n", csio_rn_flowid(rn),
830 evt, rn->nport_id);
831 CSIO_INC_STATS(rn, n_evt_unexp);
832 break;
833 }
834}
835
836
837
838
839
840
841
842
843
844
845
846void
847csio_rnode_devloss_handler(struct csio_rnode *rn)
848{
849 struct csio_lnode *ln = csio_rnode_to_lnode(rn);
850
851
852 if (csio_is_rnode_ready(rn))
853 return;
854
855 csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
856
857
858 if (csio_is_rnode_uninit(rn))
859 csio_put_rnode(ln, rn);
860}
861
862
863
864
865
866
867void
868csio_rnode_fwevt_handler(struct csio_rnode *rn, uint8_t fwevt)
869{
870 struct csio_lnode *ln = csio_rnode_to_lnode(rn);
871 enum csio_rn_ev evt;
872
873 evt = CSIO_FWE_TO_RNFE(fwevt);
874 if (!evt) {
875 csio_ln_err(ln, "ssni:x%x Unhandled FW Rdev event: %d\n",
876 csio_rn_flowid(rn), fwevt);
877 CSIO_INC_STATS(rn, n_evt_unexp);
878 return;
879 }
880 CSIO_INC_STATS(rn, n_evt_fw[fwevt]);
881
882
883 rn->prev_evt = rn->cur_evt;
884 rn->cur_evt = fwevt;
885
886
887 csio_post_event(&rn->sm, evt);
888
889
890 if (csio_is_rnode_uninit(rn))
891 csio_put_rnode(ln, rn);
892}
893
894
895
896
897
898
899
900
901
902static int
903csio_rnode_init(struct csio_rnode *rn, struct csio_lnode *ln)
904{
905 csio_rnode_to_lnode(rn) = ln;
906 csio_init_state(&rn->sm, csio_rns_uninit);
907 INIT_LIST_HEAD(&rn->host_cmpl_q);
908 csio_rn_flowid(rn) = CSIO_INVALID_IDX;
909
910
911 list_add_tail(&rn->sm.sm_list, &ln->rnhead);
912
913 return 0;
914}
915
916static void
917csio_rnode_exit(struct csio_rnode *rn)
918{
919 list_del_init(&rn->sm.sm_list);
920 CSIO_DB_ASSERT(list_empty(&rn->host_cmpl_q));
921}
922