Merge tag 'stable/for-linus-3.8-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel...
[profile/ivi/kernel-adaptation-intel-automotive.git] / 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;
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 (csio_is_rnode_ready(rn)) {
354                                         csio_ln_warn(ln,
355                                                      "rnode is already"
356                                                      "active ssni:x%x\n",
357                                                      rdev_flowid);
358                                         CSIO_ASSERT(0);
359                                 }
360                                 csio_rn_flowid(rn) = CSIO_INVALID_IDX;
361                                 rn = match_rn;
362
363                                 /* Update rn */
364                                 goto found_rnode;
365                         }
366                         csio_rn_flowid(rn) = CSIO_INVALID_IDX;
367                         goto alloc_rnode;
368                 }
369
370                 /* wwpn match */
371                 if (!memcmp(csio_rn_wwpn(rn), rdevp->wwpn, 8))
372                         goto found_rnode;
373
374                 /* Search for rnode that have same wwpn */
375                 match_rn = csio_rn_lookup_wwpn(ln, rdevp->wwpn);
376                 if (match_rn != NULL) {
377                         csio_ln_dbg(ln,
378                                 "ssni:x%x changed for rport name(wwpn):%llx "
379                                 "did:x%x\n", rdev_flowid,
380                                 wwn_to_u64(rdevp->wwpn),
381                                 match_rn->nport_id);
382                         csio_rn_flowid(rn) = CSIO_INVALID_IDX;
383                         rn = match_rn;
384                 } else {
385                         csio_ln_dbg(ln,
386                                 "rnode wwpn mismatch found ssni:x%x "
387                                 "name(wwpn):%llx\n",
388                                 rdev_flowid,
389                                 wwn_to_u64(csio_rn_wwpn(rn)));
390                         if (csio_is_rnode_ready(rn)) {
391                                 csio_ln_warn(ln,
392                                              "rnode is already active "
393                                              "wwpn:%llx ssni:x%x\n",
394                                              wwn_to_u64(csio_rn_wwpn(rn)),
395                                              rdev_flowid);
396                                 CSIO_ASSERT(0);
397                         }
398                         csio_rn_flowid(rn) = CSIO_INVALID_IDX;
399                         goto alloc_rnode;
400                 }
401         }
402
403 found_rnode:
404         csio_ln_dbg(ln, "found rnode:%p ssni:x%x name(wwpn):%llx\n",
405                 rn, rdev_flowid, wwn_to_u64(rdevp->wwpn));
406
407         /* Update flowid */
408         csio_rn_flowid(rn) = rdev_flowid;
409
410         /* update rdev entry */
411         rn->rdev_entry = rdevp;
412         CSIO_INC_STATS(ln, n_rnode_match);
413         return rn;
414
415 alloc_rnode:
416         rn = csio_get_rnode(ln, rdev_flowid);
417         if (!rn)
418                 return NULL;
419
420         csio_ln_dbg(ln, "alloc rnode:%p ssni:x%x name(wwpn):%llx\n",
421                 rn, rdev_flowid, wwn_to_u64(rdevp->wwpn));
422
423         /* update rdev entry */
424         rn->rdev_entry = rdevp;
425         return rn;
426 }
427
428 /*
429  * csio_rn_verify_rparams - verify rparams.
430  * @ln: lnode
431  * @rn: rnode
432  * @rdevp: remote device params
433  * returns success if rparams are verified.
434  */
435 static int
436 csio_rn_verify_rparams(struct csio_lnode *ln, struct csio_rnode *rn,
437                         struct fcoe_rdev_entry *rdevp)
438 {
439         uint8_t null[8];
440         uint8_t rport_type;
441         uint8_t fc_class;
442         __be32 *did;
443
444         did = (__be32 *) &rdevp->r_id[0];
445         rport_type =
446                 FW_RDEV_WR_RPORT_TYPE_GET(rdevp->rd_xfer_rdy_to_rport_type);
447         switch (rport_type) {
448         case FLOGI_VFPORT:
449                 rn->role = CSIO_RNFR_FABRIC;
450                 if (((ntohl(*did) >> 8) & CSIO_DID_MASK) != FC_FID_FLOGI) {
451                         csio_ln_err(ln, "ssni:x%x invalid fabric portid\n",
452                                 csio_rn_flowid(rn));
453                         return -EINVAL;
454                 }
455                 /* NPIV support */
456                 if (FW_RDEV_WR_NPIV_GET(rdevp->vft_to_qos))
457                         ln->flags |= CSIO_LNF_NPIVSUPP;
458
459                 break;
460
461         case NS_VNPORT:
462                 rn->role = CSIO_RNFR_NS;
463                 if (((ntohl(*did) >> 8) & CSIO_DID_MASK) != FC_FID_DIR_SERV) {
464                         csio_ln_err(ln, "ssni:x%x invalid fabric portid\n",
465                                 csio_rn_flowid(rn));
466                         return -EINVAL;
467                 }
468                 break;
469
470         case REG_FC4_VNPORT:
471         case REG_VNPORT:
472                 rn->role = CSIO_RNFR_NPORT;
473                 if (rdevp->event_cause == PRLI_ACC_RCVD ||
474                         rdevp->event_cause == PRLI_RCVD) {
475                         if (FW_RDEV_WR_TASK_RETRY_ID_GET(
476                                                         rdevp->enh_disc_to_tgt))
477                                 rn->fcp_flags |= FCP_SPPF_OVLY_ALLOW;
478
479                         if (FW_RDEV_WR_RETRY_GET(rdevp->enh_disc_to_tgt))
480                                 rn->fcp_flags |= FCP_SPPF_RETRY;
481
482                         if (FW_RDEV_WR_CONF_CMPL_GET(rdevp->enh_disc_to_tgt))
483                                 rn->fcp_flags |= FCP_SPPF_CONF_COMPL;
484
485                         if (FW_RDEV_WR_TGT_GET(rdevp->enh_disc_to_tgt))
486                                 rn->role |= CSIO_RNFR_TARGET;
487
488                         if (FW_RDEV_WR_INI_GET(rdevp->enh_disc_to_tgt))
489                                 rn->role |= CSIO_RNFR_INITIATOR;
490                 }
491
492                 break;
493
494         case FDMI_VNPORT:
495         case FAB_CTLR_VNPORT:
496                 rn->role = 0;
497                 break;
498
499         default:
500                 csio_ln_err(ln, "ssni:x%x invalid rport type recv x%x\n",
501                         csio_rn_flowid(rn), rport_type);
502                 return -EINVAL;
503         }
504
505         /* validate wwpn/wwnn for Name server/remote port */
506         if (rport_type == REG_VNPORT || rport_type == NS_VNPORT) {
507                 memset(null, 0, 8);
508                 if (!memcmp(rdevp->wwnn, null, 8)) {
509                         csio_ln_err(ln,
510                                     "ssni:x%x invalid wwnn received from"
511                                     " rport did:x%x\n",
512                                     csio_rn_flowid(rn),
513                                     (ntohl(*did) & CSIO_DID_MASK));
514                         return -EINVAL;
515                 }
516
517                 if (!memcmp(rdevp->wwpn, null, 8)) {
518                         csio_ln_err(ln,
519                                     "ssni:x%x invalid wwpn received from"
520                                     " rport did:x%x\n",
521                                     csio_rn_flowid(rn),
522                                     (ntohl(*did) & CSIO_DID_MASK));
523                         return -EINVAL;
524                 }
525
526         }
527
528         /* Copy wwnn, wwpn and nport id */
529         rn->nport_id = (ntohl(*did) >> 8) & CSIO_DID_MASK;
530         memcpy(csio_rn_wwnn(rn), rdevp->wwnn, 8);
531         memcpy(csio_rn_wwpn(rn), rdevp->wwpn, 8);
532         rn->rn_sparm.csp.sp_bb_data = rdevp->rcv_fr_sz;
533         fc_class = FW_RDEV_WR_CLASS_GET(rdevp->vft_to_qos);
534         rn->rn_sparm.clsp[fc_class - 1].cp_class = htons(FC_CPC_VALID);
535
536         return 0;
537 }
538
539 static void
540 __csio_reg_rnode(struct csio_rnode *rn)
541 {
542         struct csio_lnode *ln = csio_rnode_to_lnode(rn);
543         struct csio_hw *hw = csio_lnode_to_hw(ln);
544
545         spin_unlock_irq(&hw->lock);
546         csio_reg_rnode(rn);
547         spin_lock_irq(&hw->lock);
548
549         if (rn->role & CSIO_RNFR_TARGET)
550                 ln->n_scsi_tgts++;
551
552         if (rn->nport_id == FC_FID_MGMT_SERV)
553                 csio_ln_fdmi_start(ln, (void *) rn);
554 }
555
556 static void
557 __csio_unreg_rnode(struct csio_rnode *rn)
558 {
559         struct csio_lnode *ln = csio_rnode_to_lnode(rn);
560         struct csio_hw *hw = csio_lnode_to_hw(ln);
561         LIST_HEAD(tmp_q);
562         int cmpl = 0;
563
564         if (!list_empty(&rn->host_cmpl_q)) {
565                 csio_dbg(hw, "Returning completion queue I/Os\n");
566                 list_splice_tail_init(&rn->host_cmpl_q, &tmp_q);
567                 cmpl = 1;
568         }
569
570         if (rn->role & CSIO_RNFR_TARGET) {
571                 ln->n_scsi_tgts--;
572                 ln->last_scan_ntgts--;
573         }
574
575         spin_unlock_irq(&hw->lock);
576         csio_unreg_rnode(rn);
577         spin_lock_irq(&hw->lock);
578
579         /* Cleanup I/Os that were waiting for rnode to unregister */
580         if (cmpl)
581                 csio_scsi_cleanup_io_q(csio_hw_to_scsim(hw), &tmp_q);
582
583 }
584
585 /*****************************************************************************/
586 /* START: Rnode SM                                                           */
587 /*****************************************************************************/
588
589 /*
590  * csio_rns_uninit -
591  * @rn - rnode
592  * @evt - SM event.
593  *
594  */
595 static void
596 csio_rns_uninit(struct csio_rnode *rn, enum csio_rn_ev evt)
597 {
598         struct csio_lnode *ln = csio_rnode_to_lnode(rn);
599         int ret = 0;
600
601         CSIO_INC_STATS(rn, n_evt_sm[evt]);
602
603         switch (evt) {
604         case CSIO_RNFE_LOGGED_IN:
605         case CSIO_RNFE_PLOGI_RECV:
606                 ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
607                 if (!ret) {
608                         csio_set_state(&rn->sm, csio_rns_ready);
609                         __csio_reg_rnode(rn);
610                 } else {
611                         CSIO_INC_STATS(rn, n_err_inval);
612                 }
613                 break;
614         case CSIO_RNFE_LOGO_RECV:
615                 csio_ln_dbg(ln,
616                             "ssni:x%x Ignoring event %d recv "
617                             "in rn state[uninit]\n", csio_rn_flowid(rn), evt);
618                 CSIO_INC_STATS(rn, n_evt_drop);
619                 break;
620         default:
621                 csio_ln_dbg(ln,
622                             "ssni:x%x unexp event %d recv "
623                             "in rn state[uninit]\n", csio_rn_flowid(rn), evt);
624                 CSIO_INC_STATS(rn, n_evt_unexp);
625                 break;
626         }
627 }
628
629 /*
630  * csio_rns_ready -
631  * @rn - rnode
632  * @evt - SM event.
633  *
634  */
635 static void
636 csio_rns_ready(struct csio_rnode *rn, enum csio_rn_ev evt)
637 {
638         struct csio_lnode *ln = csio_rnode_to_lnode(rn);
639         int ret = 0;
640
641         CSIO_INC_STATS(rn, n_evt_sm[evt]);
642
643         switch (evt) {
644         case CSIO_RNFE_LOGGED_IN:
645         case CSIO_RNFE_PLOGI_RECV:
646                 csio_ln_dbg(ln,
647                         "ssni:x%x Ignoring event %d recv from did:x%x "
648                         "in rn state[ready]\n", csio_rn_flowid(rn), evt,
649                         rn->nport_id);
650                 CSIO_INC_STATS(rn, n_evt_drop);
651                 break;
652
653         case CSIO_RNFE_PRLI_DONE:
654         case CSIO_RNFE_PRLI_RECV:
655                 ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
656                 if (!ret)
657                         __csio_reg_rnode(rn);
658                 else
659                         CSIO_INC_STATS(rn, n_err_inval);
660
661                 break;
662         case CSIO_RNFE_DOWN:
663                 csio_set_state(&rn->sm, csio_rns_offline);
664                 __csio_unreg_rnode(rn);
665
666                 /* FW expected to internally aborted outstanding SCSI WRs
667                  * and return all SCSI WRs to host with status "ABORTED".
668                  */
669                 break;
670
671         case CSIO_RNFE_LOGO_RECV:
672                 csio_set_state(&rn->sm, csio_rns_offline);
673
674                 __csio_unreg_rnode(rn);
675
676                 /* FW expected to internally aborted outstanding SCSI WRs
677                  * and return all SCSI WRs to host with status "ABORTED".
678                  */
679                 break;
680
681         case CSIO_RNFE_CLOSE:
682                 /*
683                  * Each rnode receives CLOSE event when driver is removed or
684                  * device is reset
685                  * Note: All outstanding IOs on remote port need to returned
686                  * to uppper layer with appropriate error before sending
687                  * CLOSE event
688                  */
689                 csio_set_state(&rn->sm, csio_rns_uninit);
690                 __csio_unreg_rnode(rn);
691                 break;
692
693         case CSIO_RNFE_NAME_MISSING:
694                 csio_set_state(&rn->sm, csio_rns_disappeared);
695                 __csio_unreg_rnode(rn);
696
697                 /*
698                  * FW expected to internally aborted outstanding SCSI WRs
699                  * and return all SCSI WRs to host with status "ABORTED".
700                  */
701
702                 break;
703
704         default:
705                 csio_ln_dbg(ln,
706                         "ssni:x%x unexp event %d recv from did:x%x "
707                         "in rn state[uninit]\n", csio_rn_flowid(rn), evt,
708                         rn->nport_id);
709                 CSIO_INC_STATS(rn, n_evt_unexp);
710                 break;
711         }
712 }
713
714 /*
715  * csio_rns_offline -
716  * @rn - rnode
717  * @evt - SM event.
718  *
719  */
720 static void
721 csio_rns_offline(struct csio_rnode *rn, enum csio_rn_ev evt)
722 {
723         struct csio_lnode *ln = csio_rnode_to_lnode(rn);
724         int ret = 0;
725
726         CSIO_INC_STATS(rn, n_evt_sm[evt]);
727
728         switch (evt) {
729         case CSIO_RNFE_LOGGED_IN:
730         case CSIO_RNFE_PLOGI_RECV:
731                 ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
732                 if (!ret) {
733                         csio_set_state(&rn->sm, csio_rns_ready);
734                         __csio_reg_rnode(rn);
735                 } else {
736                         CSIO_INC_STATS(rn, n_err_inval);
737                         csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
738                 }
739                 break;
740
741         case CSIO_RNFE_DOWN:
742                 csio_ln_dbg(ln,
743                         "ssni:x%x Ignoring event %d recv from did:x%x "
744                         "in rn state[offline]\n", csio_rn_flowid(rn), evt,
745                         rn->nport_id);
746                 CSIO_INC_STATS(rn, n_evt_drop);
747                 break;
748
749         case CSIO_RNFE_CLOSE:
750                 /* Each rnode receives CLOSE event when driver is removed or
751                  * device is reset
752                  * Note: All outstanding IOs on remote port need to returned
753                  * to uppper layer with appropriate error before sending
754                  * CLOSE event
755                  */
756                 csio_set_state(&rn->sm, csio_rns_uninit);
757                 break;
758
759         case CSIO_RNFE_NAME_MISSING:
760                 csio_set_state(&rn->sm, csio_rns_disappeared);
761                 break;
762
763         default:
764                 csio_ln_dbg(ln,
765                         "ssni:x%x unexp event %d recv from did:x%x "
766                         "in rn state[offline]\n", csio_rn_flowid(rn), evt,
767                         rn->nport_id);
768                 CSIO_INC_STATS(rn, n_evt_unexp);
769                 break;
770         }
771 }
772
773 /*
774  * csio_rns_disappeared -
775  * @rn - rnode
776  * @evt - SM event.
777  *
778  */
779 static void
780 csio_rns_disappeared(struct csio_rnode *rn, enum csio_rn_ev evt)
781 {
782         struct csio_lnode *ln = csio_rnode_to_lnode(rn);
783         int ret = 0;
784
785         CSIO_INC_STATS(rn, n_evt_sm[evt]);
786
787         switch (evt) {
788         case CSIO_RNFE_LOGGED_IN:
789         case CSIO_RNFE_PLOGI_RECV:
790                 ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
791                 if (!ret) {
792                         csio_set_state(&rn->sm, csio_rns_ready);
793                         __csio_reg_rnode(rn);
794                 } else {
795                         CSIO_INC_STATS(rn, n_err_inval);
796                         csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
797                 }
798                 break;
799
800         case CSIO_RNFE_CLOSE:
801                 /* Each rnode receives CLOSE event when driver is removed or
802                  * device is reset.
803                  * Note: All outstanding IOs on remote port need to returned
804                  * to uppper layer with appropriate error before sending
805                  * CLOSE event
806                  */
807                 csio_set_state(&rn->sm, csio_rns_uninit);
808                 break;
809
810         case CSIO_RNFE_DOWN:
811         case CSIO_RNFE_NAME_MISSING:
812                 csio_ln_dbg(ln,
813                         "ssni:x%x Ignoring event %d recv from did x%x"
814                         "in rn state[disappeared]\n", csio_rn_flowid(rn),
815                         evt, rn->nport_id);
816                 break;
817
818         default:
819                 csio_ln_dbg(ln,
820                         "ssni:x%x unexp event %d recv from did x%x"
821                         "in rn state[disappeared]\n", csio_rn_flowid(rn),
822                         evt, rn->nport_id);
823                 CSIO_INC_STATS(rn, n_evt_unexp);
824                 break;
825         }
826 }
827
828 /*****************************************************************************/
829 /* END: Rnode SM                                                             */
830 /*****************************************************************************/
831
832 /*
833  * csio_rnode_devloss_handler - Device loss event handler
834  * @rn: rnode
835  *
836  * Post event to close rnode SM and free rnode.
837  */
838 void
839 csio_rnode_devloss_handler(struct csio_rnode *rn)
840 {
841         struct csio_lnode *ln = csio_rnode_to_lnode(rn);
842
843         /* ignore if same rnode came back as online */
844         if (csio_is_rnode_ready(rn))
845                 return;
846
847         csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
848
849         /* Free rn if in uninit state */
850         if (csio_is_rnode_uninit(rn))
851                 csio_put_rnode(ln, rn);
852 }
853
854 /**
855  * csio_rnode_fwevt_handler - Event handler for firmware rnode events.
856  * @rn:         rnode
857  *
858  */
859 void
860 csio_rnode_fwevt_handler(struct csio_rnode *rn, uint8_t fwevt)
861 {
862         struct csio_lnode *ln = csio_rnode_to_lnode(rn);
863         enum csio_rn_ev evt;
864
865         evt = CSIO_FWE_TO_RNFE(fwevt);
866         if (!evt) {
867                 csio_ln_err(ln, "ssni:x%x Unhandled FW Rdev event: %d\n",
868                             csio_rn_flowid(rn), fwevt);
869                 CSIO_INC_STATS(rn, n_evt_unexp);
870                 return;
871         }
872         CSIO_INC_STATS(rn, n_evt_fw[fwevt]);
873
874         /* Track previous & current events for debugging */
875         rn->prev_evt = rn->cur_evt;
876         rn->cur_evt = fwevt;
877
878         /* Post event to rnode SM */
879         csio_post_event(&rn->sm, evt);
880
881         /* Free rn if in uninit state */
882         if (csio_is_rnode_uninit(rn))
883                 csio_put_rnode(ln, rn);
884 }
885
886 /*
887  * csio_rnode_init - Initialize rnode.
888  * @rn: RNode
889  * @ln: Associated lnode
890  *
891  * Caller is responsible for holding the lock. The lock is required
892  * to be held for inserting the rnode in ln->rnhead list.
893  */
894 static int
895 csio_rnode_init(struct csio_rnode *rn, struct csio_lnode *ln)
896 {
897         csio_rnode_to_lnode(rn) = ln;
898         csio_init_state(&rn->sm, csio_rns_uninit);
899         INIT_LIST_HEAD(&rn->host_cmpl_q);
900         csio_rn_flowid(rn) = CSIO_INVALID_IDX;
901
902         /* Add rnode to list of lnodes->rnhead */
903         list_add_tail(&rn->sm.sm_list, &ln->rnhead);
904
905         return 0;
906 }
907
908 static void
909 csio_rnode_exit(struct csio_rnode *rn)
910 {
911         list_del_init(&rn->sm.sm_list);
912         CSIO_DB_ASSERT(list_empty(&rn->host_cmpl_q));
913 }