Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / scsi / csiostor / csio_rnode.c
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/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
45 static int csio_rnode_init(struct csio_rnode *, struct csio_lnode *);
46 static void csio_rnode_exit(struct csio_rnode *);
47
48 /* Static machine forward declarations */
49 static void csio_rns_uninit(struct csio_rnode *, enum csio_rn_ev);
50 static void csio_rns_ready(struct csio_rnode *, enum csio_rn_ev);
51 static void csio_rns_offline(struct csio_rnode *, enum csio_rn_ev);
52 static void csio_rns_disappeared(struct csio_rnode *, enum csio_rn_ev);
53
54 /* RNF event mapping */
55 static enum csio_rn_ev fwevt_to_rnevt[] = {
56         CSIO_RNFE_NONE,         /* None */
57         CSIO_RNFE_LOGGED_IN,    /* PLOGI_ACC_RCVD  */
58         CSIO_RNFE_NONE,         /* PLOGI_RJT_RCVD  */
59         CSIO_RNFE_PLOGI_RECV,   /* PLOGI_RCVD      */
60         CSIO_RNFE_LOGO_RECV,    /* PLOGO_RCVD      */
61         CSIO_RNFE_PRLI_DONE,    /* PRLI_ACC_RCVD   */
62         CSIO_RNFE_NONE,         /* PRLI_RJT_RCVD   */
63         CSIO_RNFE_PRLI_RECV,    /* PRLI_RCVD       */
64         CSIO_RNFE_PRLO_RECV,    /* PRLO_RCVD       */
65         CSIO_RNFE_NONE,         /* NPORT_ID_CHGD   */
66         CSIO_RNFE_LOGO_RECV,    /* FLOGO_RCVD      */
67         CSIO_RNFE_NONE,         /* CLR_VIRT_LNK_RCVD */
68         CSIO_RNFE_LOGGED_IN,    /* FLOGI_ACC_RCVD   */
69         CSIO_RNFE_NONE,         /* FLOGI_RJT_RCVD   */
70         CSIO_RNFE_LOGGED_IN,    /* FDISC_ACC_RCVD   */
71         CSIO_RNFE_NONE,         /* FDISC_RJT_RCVD   */
72         CSIO_RNFE_NONE,         /* FLOGI_TMO_MAX_RETRY */
73         CSIO_RNFE_NONE,         /* IMPL_LOGO_ADISC_ACC */
74         CSIO_RNFE_NONE,         /* IMPL_LOGO_ADISC_RJT */
75         CSIO_RNFE_NONE,         /* IMPL_LOGO_ADISC_CNFLT */
76         CSIO_RNFE_NONE,         /* PRLI_TMO             */
77         CSIO_RNFE_NONE,         /* ADISC_TMO            */
78         CSIO_RNFE_NAME_MISSING, /* RSCN_DEV_LOST  */
79         CSIO_RNFE_NONE,         /* SCR_ACC_RCVD */
80         CSIO_RNFE_NONE,         /* ADISC_RJT_RCVD */
81         CSIO_RNFE_NONE,         /* LOGO_SNT */
82         CSIO_RNFE_LOGO_RECV,    /* PROTO_ERR_IMPL_LOGO */
83 };
84
85 #define CSIO_FWE_TO_RNFE(_evt)  ((_evt > PROTO_ERR_IMPL_LOGO) ?         \
86                                                 CSIO_RNFE_NONE :        \
87                                                 fwevt_to_rnevt[_evt])
88 int
89 csio_is_rnode_ready(struct csio_rnode *rn)
90 {
91         return csio_match_state(rn, csio_rns_ready);
92 }
93
94 static int
95 csio_is_rnode_uninit(struct csio_rnode *rn)
96 {
97         return csio_match_state(rn, csio_rns_uninit);
98 }
99
100 static int
101 csio_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  * csio_rn_lookup - Finds the rnode with the given flowid
114  * @ln - lnode
115  * @flowid - flowid.
116  *
117  * Does the rnode lookup on the given lnode and flowid.If no matching entry
118  * found, NULL is returned.
119  */
120 static struct csio_rnode *
121 csio_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  * csio_rn_lookup_wwpn - Finds the rnode with the given wwpn
138  * @ln: lnode
139  * @wwpn: wwpn
140  *
141  * Does the rnode lookup on the given lnode and wwpn. If no matching entry
142  * found, NULL is returned.
143  */
144 static struct csio_rnode *
145 csio_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  * csio_rnode_lookup_portid - Finds the rnode with the given portid
162  * @ln:         lnode
163  * @portid:     port id
164  *
165  * Lookup the rnode list for a given portid. If no matching entry
166  * found, NULL is returned.
167  */
168 struct csio_rnode *
169 csio_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
184 static int
185 csio_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
215 static struct csio_rnode *
216 csio_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
232 err_free:
233         mempool_free(rn, hw->rnode_mempool);
234 err:
235         CSIO_INC_STATS(ln, n_rnode_nomem);
236         return NULL;
237 }
238
239 static void
240 csio_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  * csio_get_rnode - Gets rnode with the given flowid
251  * @ln - lnode
252  * @flowid - flow id.
253  *
254  * Does the rnode lookup on the given lnode and flowid. If no matching
255  * rnode found, then new rnode with given npid is allocated and returned.
256  */
257 static struct csio_rnode *
258 csio_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  * csio_put_rnode - Frees the given rnode
276  * @ln - lnode
277  * @flowid - flow id.
278  *
279  * Does the rnode lookup on the given lnode and flowid. If no matching
280  * rnode found, then new rnode with given npid is allocated and returned.
281  */
282 void
283 csio_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  * csio_confirm_rnode - confirms rnode based on wwpn.
291  * @ln: lnode
292  * @rdev_flowid: remote device flowid
293  * @rdevp: remote device params
294  * This routines searches other rnode in list having same wwpn of new rnode.
295  * If there is a match, then matched rnode is returned and otherwise new rnode
296  * is returned.
297  * returns rnode.
298  */
299 struct csio_rnode *
300 csio_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         /* Drop rdev event for cntrl port */
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         /* Lookup on flowid */
321         rn = csio_rn_lookup(ln, rdev_flowid);
322         if (!rn) {
323
324                 /* Drop events with duplicate flowid */
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                 /* Lookup on wwpn for NPORTs */
333                 rn = csio_rn_lookup_wwpn(ln, rdevp->wwpn);
334                 if (!rn)
335                         goto alloc_rnode;
336
337         } else {
338                 /* Lookup well-known ports with nport id */
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                          * Now compare the wwpn to confirm that
349                          * same port relogged in. If so update the matched rn.
350                          * Else, go ahead and alloc a new rnode.
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                                 /* Update rn */
372                                 goto found_rnode;
373                         }
374                         csio_rn_flowid(rn) = CSIO_INVALID_IDX;
375                         goto alloc_rnode;
376                 }
377
378                 /* wwpn match */
379                 if (!memcmp(csio_rn_wwpn(rn), rdevp->wwpn, 8))
380                         goto found_rnode;
381
382                 /* Search for rnode that have same wwpn */
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
411 found_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         /* Update flowid */
416         csio_rn_flowid(rn) = rdev_flowid;
417
418         /* update rdev entry */
419         rn->rdev_entry = rdevp;
420         CSIO_INC_STATS(ln, n_rnode_match);
421         return rn;
422
423 alloc_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         /* update rdev entry */
432         rn->rdev_entry = rdevp;
433         return rn;
434 }
435
436 /*
437  * csio_rn_verify_rparams - verify rparams.
438  * @ln: lnode
439  * @rn: rnode
440  * @rdevp: remote device params
441  * returns success if rparams are verified.
442  */
443 static int
444 csio_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                 /* NPIV support */
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         /* validate wwpn/wwnn for Name server/remote port */
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         /* Copy wwnn, wwpn and nport id */
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
547 static 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
564 static 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         /* Cleanup I/Os that were waiting for rnode to unregister */
588         if (cmpl)
589                 csio_scsi_cleanup_io_q(csio_hw_to_scsim(hw), &tmp_q);
590
591 }
592
593 /*****************************************************************************/
594 /* START: Rnode SM                                                           */
595 /*****************************************************************************/
596
597 /*
598  * csio_rns_uninit -
599  * @rn - rnode
600  * @evt - SM event.
601  *
602  */
603 static void
604 csio_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  * csio_rns_ready -
639  * @rn - rnode
640  * @evt - SM event.
641  *
642  */
643 static void
644 csio_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                 /* FW expected to internally aborted outstanding SCSI WRs
675                  * and return all SCSI WRs to host with status "ABORTED".
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                 /* FW expected to internally aborted outstanding SCSI WRs
685                  * and return all SCSI WRs to host with status "ABORTED".
686                  */
687                 break;
688
689         case CSIO_RNFE_CLOSE:
690                 /*
691                  * Each rnode receives CLOSE event when driver is removed or
692                  * device is reset
693                  * Note: All outstanding IOs on remote port need to returned
694                  * to uppper layer with appropriate error before sending
695                  * CLOSE event
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                  * FW expected to internally aborted outstanding SCSI WRs
707                  * and return all SCSI WRs to host with status "ABORTED".
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  * csio_rns_offline -
724  * @rn - rnode
725  * @evt - SM event.
726  *
727  */
728 static void
729 csio_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                 /* Each rnode receives CLOSE event when driver is removed or
759                  * device is reset
760                  * Note: All outstanding IOs on remote port need to returned
761                  * to uppper layer with appropriate error before sending
762                  * CLOSE event
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  * csio_rns_disappeared -
783  * @rn - rnode
784  * @evt - SM event.
785  *
786  */
787 static void
788 csio_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                 /* Each rnode receives CLOSE event when driver is removed or
810                  * device is reset.
811                  * Note: All outstanding IOs on remote port need to returned
812                  * to uppper layer with appropriate error before sending
813                  * CLOSE event
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 /* END: Rnode SM                                                             */
838 /*****************************************************************************/
839
840 /*
841  * csio_rnode_devloss_handler - Device loss event handler
842  * @rn: rnode
843  *
844  * Post event to close rnode SM and free rnode.
845  */
846 void
847 csio_rnode_devloss_handler(struct csio_rnode *rn)
848 {
849         struct csio_lnode *ln = csio_rnode_to_lnode(rn);
850
851         /* ignore if same rnode came back as online */
852         if (csio_is_rnode_ready(rn))
853                 return;
854
855         csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
856
857         /* Free rn if in uninit state */
858         if (csio_is_rnode_uninit(rn))
859                 csio_put_rnode(ln, rn);
860 }
861
862 /**
863  * csio_rnode_fwevt_handler - Event handler for firmware rnode events.
864  * @rn:         rnode
865  *
866  */
867 void
868 csio_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         /* Track previous & current events for debugging */
883         rn->prev_evt = rn->cur_evt;
884         rn->cur_evt = fwevt;
885
886         /* Post event to rnode SM */
887         csio_post_event(&rn->sm, evt);
888
889         /* Free rn if in uninit state */
890         if (csio_is_rnode_uninit(rn))
891                 csio_put_rnode(ln, rn);
892 }
893
894 /*
895  * csio_rnode_init - Initialize rnode.
896  * @rn: RNode
897  * @ln: Associated lnode
898  *
899  * Caller is responsible for holding the lock. The lock is required
900  * to be held for inserting the rnode in ln->rnhead list.
901  */
902 static int
903 csio_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         /* Add rnode to list of lnodes->rnhead */
911         list_add_tail(&rn->sm.sm_list, &ln->rnhead);
912
913         return 0;
914 }
915
916 static void
917 csio_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 }