[SCSI] bfa: fix prli retry issues
[pandora-kernel.git] / drivers / scsi / bfa / fcpim.c
1 /*
2  * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
3  * All rights reserved
4  * www.brocade.com
5  *
6  * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License (GPL) Version 2 as
10  * published by the Free Software Foundation
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  */
17
18 /**
19  *  fcpim.c - FCP initiator mode i-t nexus state machine
20  */
21
22 #include <bfa.h>
23 #include <bfa_svc.h>
24 #include "fcs_fcpim.h"
25 #include "fcs_rport.h"
26 #include "fcs_lport.h"
27 #include "fcs_trcmod.h"
28 #include "fcs_fcxp.h"
29 #include "fcs.h"
30 #include <fcs/bfa_fcs_fcpim.h>
31 #include <fcb/bfa_fcb_fcpim.h>
32 #include <aen/bfa_aen_itnim.h>
33
34 BFA_TRC_FILE(FCS, FCPIM);
35
36 /*
37  * forward declarations
38  */
39 static void     bfa_fcs_itnim_timeout(void *arg);
40 static void     bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim);
41 static void     bfa_fcs_itnim_send_prli(void *itnim_cbarg,
42                                         struct bfa_fcxp_s *fcxp_alloced);
43 static void     bfa_fcs_itnim_prli_response(void *fcsarg,
44                                             struct bfa_fcxp_s *fcxp,
45                                             void *cbarg,
46                                             bfa_status_t req_status,
47                                             u32 rsp_len,
48                                             u32 resid_len,
49                                             struct fchs_s *rsp_fchs);
50 static void     bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
51                                        enum bfa_itnim_aen_event event);
52
53 /**
54  *  fcs_itnim_sm FCS itnim state machine events
55  */
56
57 enum bfa_fcs_itnim_event {
58         BFA_FCS_ITNIM_SM_ONLINE = 1,    /*  rport online event */
59         BFA_FCS_ITNIM_SM_OFFLINE = 2,   /*  rport offline */
60         BFA_FCS_ITNIM_SM_FRMSENT = 3,   /*  prli frame is sent */
61         BFA_FCS_ITNIM_SM_RSP_OK = 4,    /*  good response */
62         BFA_FCS_ITNIM_SM_RSP_ERROR = 5, /*  error response */
63         BFA_FCS_ITNIM_SM_TIMEOUT = 6,   /*  delay timeout */
64         BFA_FCS_ITNIM_SM_HCB_OFFLINE = 7,       /*  BFA online callback */
65         BFA_FCS_ITNIM_SM_HCB_ONLINE = 8,        /*  BFA offline callback */
66         BFA_FCS_ITNIM_SM_INITIATOR = 9, /*  rport is initiator */
67         BFA_FCS_ITNIM_SM_DELETE = 10,   /*  delete event from rport */
68         BFA_FCS_ITNIM_SM_PRLO = 11,     /*  delete event from rport */
69 };
70
71 static void     bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
72                                          enum bfa_fcs_itnim_event event);
73 static void     bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
74                                            enum bfa_fcs_itnim_event event);
75 static void     bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
76                                       enum bfa_fcs_itnim_event event);
77 static void     bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
78                                             enum bfa_fcs_itnim_event event);
79 static void     bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
80                                             enum bfa_fcs_itnim_event event);
81 static void     bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
82                                         enum bfa_fcs_itnim_event event);
83 static void     bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
84                                              enum bfa_fcs_itnim_event event);
85 static void     bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
86                                            enum bfa_fcs_itnim_event event);
87
88 static struct bfa_sm_table_s itnim_sm_table[] = {
89         {BFA_SM(bfa_fcs_itnim_sm_offline), BFA_ITNIM_OFFLINE},
90         {BFA_SM(bfa_fcs_itnim_sm_prli_send), BFA_ITNIM_PRLI_SEND},
91         {BFA_SM(bfa_fcs_itnim_sm_prli), BFA_ITNIM_PRLI_SENT},
92         {BFA_SM(bfa_fcs_itnim_sm_prli_retry), BFA_ITNIM_PRLI_RETRY},
93         {BFA_SM(bfa_fcs_itnim_sm_hcb_online), BFA_ITNIM_HCB_ONLINE},
94         {BFA_SM(bfa_fcs_itnim_sm_online), BFA_ITNIM_ONLINE},
95         {BFA_SM(bfa_fcs_itnim_sm_hcb_offline), BFA_ITNIM_HCB_OFFLINE},
96         {BFA_SM(bfa_fcs_itnim_sm_initiator), BFA_ITNIM_INITIATIOR},
97 };
98
99 /**
100  *  fcs_itnim_sm FCS itnim state machine
101  */
102
103 static void
104 bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
105                          enum bfa_fcs_itnim_event event)
106 {
107         bfa_trc(itnim->fcs, itnim->rport->pwwn);
108         bfa_trc(itnim->fcs, event);
109
110         switch (event) {
111         case BFA_FCS_ITNIM_SM_ONLINE:
112                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
113                 itnim->prli_retries = 0;
114                 bfa_fcs_itnim_send_prli(itnim, NULL);
115                 break;
116
117         case BFA_FCS_ITNIM_SM_OFFLINE:
118                 bfa_fcs_rport_itnim_ack(itnim->rport);
119                 break;
120
121         case BFA_FCS_ITNIM_SM_INITIATOR:
122                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
123                 break;
124
125         case BFA_FCS_ITNIM_SM_DELETE:
126                 bfa_fcs_itnim_free(itnim);
127                 break;
128
129         default:
130                 bfa_sm_fault(itnim->fcs, event);
131         }
132
133 }
134
135 static void
136 bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
137                            enum bfa_fcs_itnim_event event)
138 {
139         bfa_trc(itnim->fcs, itnim->rport->pwwn);
140         bfa_trc(itnim->fcs, event);
141
142         switch (event) {
143         case BFA_FCS_ITNIM_SM_FRMSENT:
144                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli);
145                 break;
146
147         case BFA_FCS_ITNIM_SM_INITIATOR:
148                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
149                 bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
150                 break;
151
152         case BFA_FCS_ITNIM_SM_OFFLINE:
153                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
154                 bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
155                 bfa_fcs_rport_itnim_ack(itnim->rport);
156                 break;
157
158         case BFA_FCS_ITNIM_SM_DELETE:
159                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
160                 bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
161                 bfa_fcs_itnim_free(itnim);
162                 break;
163
164         default:
165                 bfa_sm_fault(itnim->fcs, event);
166         }
167 }
168
169 static void
170 bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
171                       enum bfa_fcs_itnim_event event)
172 {
173         bfa_trc(itnim->fcs, itnim->rport->pwwn);
174         bfa_trc(itnim->fcs, event);
175
176         switch (event) {
177         case BFA_FCS_ITNIM_SM_RSP_OK:
178                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online);
179                 bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec);
180                 break;
181
182         case BFA_FCS_ITNIM_SM_RSP_ERROR:
183                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_retry);
184                 bfa_timer_start(itnim->fcs->bfa, &itnim->timer,
185                                 bfa_fcs_itnim_timeout, itnim,
186                                 BFA_FCS_RETRY_TIMEOUT);
187                 break;
188
189         case BFA_FCS_ITNIM_SM_OFFLINE:
190                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
191                 bfa_fcxp_discard(itnim->fcxp);
192                 bfa_fcs_rport_itnim_ack(itnim->rport);
193                 break;
194
195         case BFA_FCS_ITNIM_SM_INITIATOR:
196                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
197                 /*
198                  * dont discard fcxp. accept will reach same state
199                  */
200                 break;
201
202         case BFA_FCS_ITNIM_SM_DELETE:
203                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
204                 bfa_fcxp_discard(itnim->fcxp);
205                 bfa_fcs_itnim_free(itnim);
206                 break;
207
208         default:
209                 bfa_sm_fault(itnim->fcs, event);
210         }
211 }
212
213 static void
214 bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
215                             enum bfa_fcs_itnim_event event)
216 {
217         bfa_trc(itnim->fcs, itnim->rport->pwwn);
218         bfa_trc(itnim->fcs, event);
219
220         switch (event) {
221         case BFA_FCS_ITNIM_SM_TIMEOUT:
222                 if (itnim->prli_retries < BFA_FCS_RPORT_MAX_RETRIES) {
223                         itnim->prli_retries++;
224                         bfa_trc(itnim->fcs, itnim->prli_retries);
225                         bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
226                         bfa_fcs_itnim_send_prli(itnim, NULL);
227                 } else {
228                         /* invoke target offline */
229                         bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
230                         bfa_fcs_rport_logo_imp(itnim->rport);
231                 }
232                 break;
233
234         case BFA_FCS_ITNIM_SM_OFFLINE:
235                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
236                 bfa_timer_stop(&itnim->timer);
237                 bfa_fcs_rport_itnim_ack(itnim->rport);
238                 break;
239
240         case BFA_FCS_ITNIM_SM_INITIATOR:
241                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
242                 bfa_timer_stop(&itnim->timer);
243                 break;
244
245         case BFA_FCS_ITNIM_SM_DELETE:
246                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
247                 bfa_timer_stop(&itnim->timer);
248                 bfa_fcs_itnim_free(itnim);
249                 break;
250
251         default:
252                 bfa_sm_fault(itnim->fcs, event);
253         }
254 }
255
256 static void
257 bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
258                             enum bfa_fcs_itnim_event event)
259 {
260         bfa_trc(itnim->fcs, itnim->rport->pwwn);
261         bfa_trc(itnim->fcs, event);
262
263         switch (event) {
264         case BFA_FCS_ITNIM_SM_HCB_ONLINE:
265                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_online);
266                 bfa_fcb_itnim_online(itnim->itnim_drv);
267                 bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_ONLINE);
268                 break;
269
270         case BFA_FCS_ITNIM_SM_OFFLINE:
271                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
272                 bfa_itnim_offline(itnim->bfa_itnim);
273                 bfa_fcs_rport_itnim_ack(itnim->rport);
274                 break;
275
276         case BFA_FCS_ITNIM_SM_DELETE:
277                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
278                 bfa_fcs_itnim_free(itnim);
279                 break;
280
281         default:
282                 bfa_sm_fault(itnim->fcs, event);
283         }
284 }
285
286 static void
287 bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
288                         enum bfa_fcs_itnim_event event)
289 {
290         bfa_trc(itnim->fcs, itnim->rport->pwwn);
291         bfa_trc(itnim->fcs, event);
292
293         switch (event) {
294         case BFA_FCS_ITNIM_SM_OFFLINE:
295                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);
296                 bfa_fcb_itnim_offline(itnim->itnim_drv);
297                 bfa_itnim_offline(itnim->bfa_itnim);
298                 if (bfa_fcs_port_is_online(itnim->rport->port) == BFA_TRUE)
299                         bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_DISCONNECT);
300                 else
301                         bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_OFFLINE);
302                 break;
303
304         case BFA_FCS_ITNIM_SM_DELETE:
305                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
306                 bfa_fcs_itnim_free(itnim);
307                 break;
308
309         default:
310                 bfa_sm_fault(itnim->fcs, event);
311         }
312 }
313
314 static void
315 bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
316                              enum bfa_fcs_itnim_event event)
317 {
318         bfa_trc(itnim->fcs, itnim->rport->pwwn);
319         bfa_trc(itnim->fcs, event);
320
321         switch (event) {
322         case BFA_FCS_ITNIM_SM_HCB_OFFLINE:
323                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
324                 bfa_fcs_rport_itnim_ack(itnim->rport);
325                 break;
326
327         case BFA_FCS_ITNIM_SM_DELETE:
328                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
329                 bfa_fcs_itnim_free(itnim);
330                 break;
331
332         default:
333                 bfa_sm_fault(itnim->fcs, event);
334         }
335 }
336
337 /*
338  * This state is set when a discovered rport is also in intiator mode.
339  * This ITN is marked as no_op and is not active and will not be truned into
340  * online state.
341  */
342 static void
343 bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
344                            enum bfa_fcs_itnim_event event)
345 {
346         bfa_trc(itnim->fcs, itnim->rport->pwwn);
347         bfa_trc(itnim->fcs, event);
348
349         switch (event) {
350         case BFA_FCS_ITNIM_SM_OFFLINE:
351                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
352                 bfa_fcs_rport_itnim_ack(itnim->rport);
353                 break;
354
355         case BFA_FCS_ITNIM_SM_RSP_ERROR:
356         case BFA_FCS_ITNIM_SM_ONLINE:
357         case BFA_FCS_ITNIM_SM_INITIATOR:
358                 break;
359
360         case BFA_FCS_ITNIM_SM_DELETE:
361                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
362                 bfa_fcs_itnim_free(itnim);
363                 break;
364
365         default:
366                 bfa_sm_fault(itnim->fcs, event);
367         }
368 }
369
370
371
372 /**
373  *  itnim_private FCS ITNIM private interfaces
374  */
375
376 static void
377 bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
378                        enum bfa_itnim_aen_event event)
379 {
380         struct bfa_fcs_rport_s *rport = itnim->rport;
381         union bfa_aen_data_u aen_data;
382         struct bfa_log_mod_s *logmod = rport->fcs->logm;
383         wwn_t           lpwwn = bfa_fcs_port_get_pwwn(rport->port);
384         wwn_t           rpwwn = rport->pwwn;
385         char            lpwwn_ptr[BFA_STRING_32];
386         char            rpwwn_ptr[BFA_STRING_32];
387
388         /*
389          * Don't post events for well known addresses
390          */
391         if (BFA_FCS_PID_IS_WKA(rport->pid))
392                 return;
393
394         wwn2str(lpwwn_ptr, lpwwn);
395         wwn2str(rpwwn_ptr, rpwwn);
396
397         bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_ITNIM, event),
398                 rpwwn_ptr, lpwwn_ptr);
399
400         aen_data.itnim.vf_id = rport->port->fabric->vf_id;
401         aen_data.itnim.ppwwn =
402                 bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(itnim->fcs));
403         aen_data.itnim.lpwwn = lpwwn;
404         aen_data.itnim.rpwwn = rpwwn;
405 }
406
407 static void
408 bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced)
409 {
410         struct bfa_fcs_itnim_s *itnim = itnim_cbarg;
411         struct bfa_fcs_rport_s *rport = itnim->rport;
412         struct bfa_fcs_port_s *port = rport->port;
413         struct fchs_s          fchs;
414         struct bfa_fcxp_s *fcxp;
415         int             len;
416
417         bfa_trc(itnim->fcs, itnim->rport->pwwn);
418
419         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
420         if (!fcxp) {
421                 itnim->stats.fcxp_alloc_wait++;
422                 bfa_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe,
423                                     bfa_fcs_itnim_send_prli, itnim);
424                 return;
425         }
426         itnim->fcxp = fcxp;
427
428         len = fc_prli_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), itnim->rport->pid,
429                             bfa_fcs_port_get_fcid(port), 0);
430
431         bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id, port->lp_tag,
432                       BFA_FALSE, FC_CLASS_3, len, &fchs,
433                       bfa_fcs_itnim_prli_response, (void *)itnim, FC_MAX_PDUSZ,
434                       FC_ELS_TOV);
435
436         itnim->stats.prli_sent++;
437         bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_FRMSENT);
438 }
439
440 static void
441 bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
442                             bfa_status_t req_status, u32 rsp_len,
443                             u32 resid_len, struct fchs_s *rsp_fchs)
444 {
445         struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cbarg;
446         struct fc_els_cmd_s   *els_cmd;
447         struct fc_prli_s      *prli_resp;
448         struct fc_ls_rjt_s    *ls_rjt;
449         struct fc_prli_params_s *sparams;
450
451         bfa_trc(itnim->fcs, req_status);
452
453         /*
454          * Sanity Checks
455          */
456         if (req_status != BFA_STATUS_OK) {
457                 itnim->stats.prli_rsp_err++;
458                 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
459                 return;
460         }
461
462         els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
463
464         if (els_cmd->els_code == FC_ELS_ACC) {
465                 prli_resp = (struct fc_prli_s *) els_cmd;
466
467                 if (fc_prli_rsp_parse(prli_resp, rsp_len) != FC_PARSE_OK) {
468                         bfa_trc(itnim->fcs, rsp_len);
469                         /*
470                          * Check if this  r-port is also in Initiator mode.
471                          * If so, we need to set this ITN as a no-op.
472                          */
473                         if (prli_resp->parampage.servparams.initiator) {
474                                 bfa_trc(itnim->fcs, prli_resp->parampage.type);
475                                 itnim->rport->scsi_function =
476                                         BFA_RPORT_INITIATOR;
477                                 itnim->stats.prli_rsp_acc++;
478                                 bfa_sm_send_event(itnim,
479                                                   BFA_FCS_ITNIM_SM_INITIATOR);
480                                 return;
481                         }
482
483                         itnim->stats.prli_rsp_parse_err++;
484                         return;
485                 }
486                 itnim->rport->scsi_function = BFA_RPORT_TARGET;
487
488                 sparams = &prli_resp->parampage.servparams;
489                 itnim->seq_rec = sparams->retry;
490                 itnim->rec_support = sparams->rec_support;
491                 itnim->task_retry_id = sparams->task_retry_id;
492                 itnim->conf_comp = sparams->confirm;
493
494                 itnim->stats.prli_rsp_acc++;
495                 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_OK);
496         } else {
497                 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
498
499                 bfa_trc(itnim->fcs, ls_rjt->reason_code);
500                 bfa_trc(itnim->fcs, ls_rjt->reason_code_expl);
501
502                 itnim->stats.prli_rsp_rjt++;
503                 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
504         }
505 }
506
507 static void
508 bfa_fcs_itnim_timeout(void *arg)
509 {
510         struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)arg;
511
512         itnim->stats.timeout++;
513         bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_TIMEOUT);
514 }
515
516 static void
517 bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim)
518 {
519         bfa_itnim_delete(itnim->bfa_itnim);
520         bfa_fcb_itnim_free(itnim->fcs->bfad, itnim->itnim_drv);
521 }
522
523
524
525 /**
526  *  itnim_public FCS ITNIM public interfaces
527  */
528
529 /**
530  *      Called by rport when a new rport is created.
531  *
532  * @param[in] rport     -  remote port.
533  */
534 struct bfa_fcs_itnim_s *
535 bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)
536 {
537         struct bfa_fcs_port_s *port = rport->port;
538         struct bfa_fcs_itnim_s *itnim;
539         struct bfad_itnim_s *itnim_drv;
540         struct bfa_itnim_s *bfa_itnim;
541
542         /*
543          * call bfad to allocate the itnim
544          */
545         bfa_fcb_itnim_alloc(port->fcs->bfad, &itnim, &itnim_drv);
546         if (itnim == NULL) {
547                 bfa_trc(port->fcs, rport->pwwn);
548                 return NULL;
549         }
550
551         /*
552          * Initialize itnim
553          */
554         itnim->rport = rport;
555         itnim->fcs = rport->fcs;
556         itnim->itnim_drv = itnim_drv;
557
558         /*
559          * call BFA to create the itnim
560          */
561         bfa_itnim = bfa_itnim_create(port->fcs->bfa, rport->bfa_rport, itnim);
562
563         if (bfa_itnim == NULL) {
564                 bfa_trc(port->fcs, rport->pwwn);
565                 bfa_fcb_itnim_free(port->fcs->bfad, itnim_drv);
566                 bfa_assert(0);
567                 return NULL;
568         }
569
570         itnim->bfa_itnim = bfa_itnim;
571         itnim->seq_rec = BFA_FALSE;
572         itnim->rec_support = BFA_FALSE;
573         itnim->conf_comp = BFA_FALSE;
574         itnim->task_retry_id = BFA_FALSE;
575
576         /*
577          * Set State machine
578          */
579         bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
580
581         return itnim;
582 }
583
584 /**
585  *      Called by rport to delete  the instance of FCPIM.
586  *
587  * @param[in] rport     -  remote port.
588  */
589 void
590 bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim)
591 {
592         bfa_trc(itnim->fcs, itnim->rport->pid);
593         bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_DELETE);
594 }
595
596 /**
597  * Notification from rport that PLOGI is complete to initiate FC-4 session.
598  */
599 void
600 bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim)
601 {
602         itnim->stats.onlines++;
603
604         if (!BFA_FCS_PID_IS_WKA(itnim->rport->pid)) {
605                 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_ONLINE);
606         } else {
607                 /*
608                  * For well known addresses, we set the itnim to initiator
609                  * state
610                  */
611                 itnim->stats.initiator++;
612                 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
613         }
614 }
615
616 /**
617  * Called by rport to handle a remote device offline.
618  */
619 void
620 bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim)
621 {
622         itnim->stats.offlines++;
623         bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_OFFLINE);
624 }
625
626 /**
627  * Called by rport when remote port is known to be an initiator from
628  * PRLI received.
629  */
630 void
631 bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim)
632 {
633         bfa_trc(itnim->fcs, itnim->rport->pid);
634         itnim->stats.initiator++;
635         bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
636 }
637
638 /**
639  * Called by rport to check if the itnim is online.
640  */
641 bfa_status_t
642 bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim)
643 {
644         bfa_trc(itnim->fcs, itnim->rport->pid);
645         switch (bfa_sm_to_state(itnim_sm_table, itnim->sm)) {
646         case BFA_ITNIM_ONLINE:
647         case BFA_ITNIM_INITIATIOR:
648                 return BFA_STATUS_OK;
649
650         default:
651                 return BFA_STATUS_NO_FCPIM_NEXUS;
652
653         }
654 }
655
656 /**
657  * BFA completion callback for bfa_itnim_online().
658  */
659 void
660 bfa_cb_itnim_online(void *cbarg)
661 {
662         struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cbarg;
663
664         bfa_trc(itnim->fcs, itnim->rport->pwwn);
665         bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_ONLINE);
666 }
667
668 /**
669  * BFA completion callback for bfa_itnim_offline().
670  */
671 void
672 bfa_cb_itnim_offline(void *cb_arg)
673 {
674         struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
675
676         bfa_trc(itnim->fcs, itnim->rport->pwwn);
677         bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_OFFLINE);
678 }
679
680 /**
681  * Mark the beginning of PATH TOV handling. IO completion callbacks
682  * are still pending.
683  */
684 void
685 bfa_cb_itnim_tov_begin(void *cb_arg)
686 {
687         struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
688
689         bfa_trc(itnim->fcs, itnim->rport->pwwn);
690 }
691
692 /**
693  * Mark the end of PATH TOV handling. All pending IOs are already cleaned up.
694  */
695 void
696 bfa_cb_itnim_tov(void *cb_arg)
697 {
698         struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
699
700         bfa_trc(itnim->fcs, itnim->rport->pwwn);
701         bfa_fcb_itnim_tov(itnim->itnim_drv);
702 }
703
704 /**
705  *              BFA notification to FCS/driver for second level error recovery.
706  *
707  * Atleast one I/O request has timedout and target is unresponsive to
708  * repeated abort requests. Second level error recovery should be initiated
709  * by starting implicit logout and recovery procedures.
710  */
711 void
712 bfa_cb_itnim_sler(void *cb_arg)
713 {
714         struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
715
716         itnim->stats.sler++;
717         bfa_trc(itnim->fcs, itnim->rport->pwwn);
718         bfa_fcs_rport_logo_imp(itnim->rport);
719 }
720
721 struct bfa_fcs_itnim_s *
722 bfa_fcs_itnim_lookup(struct bfa_fcs_port_s *port, wwn_t rpwwn)
723 {
724         struct bfa_fcs_rport_s *rport;
725         rport = bfa_fcs_rport_lookup(port, rpwwn);
726
727         if (!rport)
728                 return NULL;
729
730         bfa_assert(rport->itnim != NULL);
731         return rport->itnim;
732 }
733
734 bfa_status_t
735 bfa_fcs_itnim_attr_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
736                        struct bfa_itnim_attr_s *attr)
737 {
738         struct bfa_fcs_itnim_s *itnim = NULL;
739
740         itnim = bfa_fcs_itnim_lookup(port, rpwwn);
741
742         if (itnim == NULL)
743                 return BFA_STATUS_NO_FCPIM_NEXUS;
744
745         attr->state = bfa_sm_to_state(itnim_sm_table, itnim->sm);
746         attr->retry = itnim->seq_rec;
747         attr->rec_support = itnim->rec_support;
748         attr->conf_comp = itnim->conf_comp;
749         attr->task_retry_id = itnim->task_retry_id;
750         bfa_os_memset(&attr->io_latency, 0, sizeof(struct bfa_itnim_latency_s));
751
752         return BFA_STATUS_OK;
753 }
754
755 bfa_status_t
756 bfa_fcs_itnim_stats_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
757                         struct bfa_itnim_stats_s *stats)
758 {
759         struct bfa_fcs_itnim_s *itnim = NULL;
760
761         bfa_assert(port != NULL);
762
763         itnim = bfa_fcs_itnim_lookup(port, rpwwn);
764
765         if (itnim == NULL)
766                 return BFA_STATUS_NO_FCPIM_NEXUS;
767
768         bfa_os_memcpy(stats, &itnim->stats, sizeof(struct bfa_itnim_stats_s));
769
770         return BFA_STATUS_OK;
771 }
772
773 bfa_status_t
774 bfa_fcs_itnim_stats_clear(struct bfa_fcs_port_s *port, wwn_t rpwwn)
775 {
776         struct bfa_fcs_itnim_s *itnim = NULL;
777
778         bfa_assert(port != NULL);
779
780         itnim = bfa_fcs_itnim_lookup(port, rpwwn);
781
782         if (itnim == NULL)
783                 return BFA_STATUS_NO_FCPIM_NEXUS;
784
785         bfa_os_memset(&itnim->stats, 0, sizeof(struct bfa_itnim_stats_s));
786         return BFA_STATUS_OK;
787 }
788
789 void
790 bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim, struct fchs_s *fchs,
791                       u16 len)
792 {
793         struct fc_els_cmd_s   *els_cmd;
794
795         bfa_trc(itnim->fcs, fchs->type);
796
797         if (fchs->type != FC_TYPE_ELS)
798                 return;
799
800         els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
801
802         bfa_trc(itnim->fcs, els_cmd->els_code);
803
804         switch (els_cmd->els_code) {
805         case FC_ELS_PRLO:
806                 /* bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_PRLO); */
807                 break;
808
809         default:
810                 bfa_assert(0);
811         }
812 }
813
814 void
815 bfa_fcs_itnim_pause(struct bfa_fcs_itnim_s *itnim)
816 {
817 }
818
819 void
820 bfa_fcs_itnim_resume(struct bfa_fcs_itnim_s *itnim)
821 {
822 }