Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[pandora-kernel.git] / drivers / scsi / bfa / rport_ftrs.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  *  rport_ftrs.c Remote port features (RPF) implementation.
20  */
21
22 #include <bfa.h>
23 #include <bfa_svc.h>
24 #include "fcbuild.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
31 BFA_TRC_FILE(FCS, RPORT_FTRS);
32
33 #define BFA_FCS_RPF_RETRIES     (3)
34 #define BFA_FCS_RPF_RETRY_TIMEOUT  (1000) /* 1 sec (In millisecs) */
35
36 static void     bfa_fcs_rpf_send_rpsc2(void *rport_cbarg,
37                         struct bfa_fcxp_s *fcxp_alloced);
38 static void     bfa_fcs_rpf_rpsc2_response(void *fcsarg,
39                         struct bfa_fcxp_s *fcxp, void *cbarg,
40                         bfa_status_t req_status, u32 rsp_len,
41                         u32 resid_len,
42                         struct fchs_s *rsp_fchs);
43 static void     bfa_fcs_rpf_timeout(void *arg);
44
45 /**
46  *  fcs_rport_ftrs_sm FCS rport state machine events
47  */
48
49 enum rpf_event {
50         RPFSM_EVENT_RPORT_OFFLINE  = 1,     /*  Rport offline            */
51         RPFSM_EVENT_RPORT_ONLINE   = 2,     /*  Rport online            */
52         RPFSM_EVENT_FCXP_SENT      = 3,    /*  Frame from has been sent */
53         RPFSM_EVENT_TIMEOUT        = 4,    /*  Rport SM timeout event   */
54         RPFSM_EVENT_RPSC_COMP      = 5,
55         RPFSM_EVENT_RPSC_FAIL      = 6,
56         RPFSM_EVENT_RPSC_ERROR     = 7,
57 };
58
59 static void     bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf,
60                                         enum rpf_event event);
61 static void     bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf,
62                                                enum rpf_event event);
63 static void     bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf,
64                                                enum rpf_event event);
65 static void     bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf,
66                                                         enum rpf_event event);
67 static void     bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf,
68                                                         enum rpf_event event);
69 static void     bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf,
70                                                         enum rpf_event event);
71
72 static void
73 bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
74 {
75         struct bfa_fcs_rport_s *rport = rpf->rport;
76
77         bfa_trc(rport->fcs, rport->pwwn);
78         bfa_trc(rport->fcs, rport->pid);
79         bfa_trc(rport->fcs, event);
80
81         switch (event) {
82         case RPFSM_EVENT_RPORT_ONLINE :
83                 if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
84                         bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
85                         rpf->rpsc_retries = 0;
86                         bfa_fcs_rpf_send_rpsc2(rpf, NULL);
87                         break;
88                 };
89
90         case RPFSM_EVENT_RPORT_OFFLINE :
91                 break;
92
93         default:
94                 bfa_assert(0);
95         }
96 }
97
98 static void
99 bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
100 {
101         struct bfa_fcs_rport_s *rport = rpf->rport;
102
103         bfa_trc(rport->fcs, event);
104
105         switch (event) {
106         case RPFSM_EVENT_FCXP_SENT:
107                 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc);
108                 break;
109
110         case RPFSM_EVENT_RPORT_OFFLINE :
111                 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
112                 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rpf->fcxp_wqe);
113                 rpf->rpsc_retries = 0;
114                 break;
115
116         default:
117                 bfa_assert(0);
118         }
119 }
120
121 static void
122 bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
123 {
124         struct bfa_fcs_rport_s *rport = rpf->rport;
125
126         bfa_trc(rport->fcs, rport->pid);
127         bfa_trc(rport->fcs, event);
128
129         switch (event) {
130         case RPFSM_EVENT_RPSC_COMP:
131                 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
132                 /* Update speed info in f/w via BFA */
133                 if (rpf->rpsc_speed != BFA_PPORT_SPEED_UNKNOWN) {
134                         bfa_rport_speed(rport->bfa_rport, rpf->rpsc_speed);
135                 } else if (rpf->assigned_speed != BFA_PPORT_SPEED_UNKNOWN) {
136                         bfa_rport_speed(rport->bfa_rport, rpf->assigned_speed);
137                 }
138                 break;
139
140         case RPFSM_EVENT_RPSC_FAIL:
141                 /* RPSC not supported by rport */
142                 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
143                 break;
144
145         case RPFSM_EVENT_RPSC_ERROR:
146                 /* need to retry...delayed a bit. */
147                 if (rpf->rpsc_retries++ < BFA_FCS_RPF_RETRIES) {
148                         bfa_timer_start(rport->fcs->bfa, &rpf->timer,
149                                     bfa_fcs_rpf_timeout, rpf,
150                                     BFA_FCS_RPF_RETRY_TIMEOUT);
151                         bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_retry);
152                 } else {
153                         bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
154                 }
155                 break;
156
157         case RPFSM_EVENT_RPORT_OFFLINE :
158                 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
159                 bfa_fcxp_discard(rpf->fcxp);
160                 rpf->rpsc_retries = 0;
161                 break;
162
163         default:
164                 bfa_assert(0);
165         }
166 }
167
168 static void
169 bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
170 {
171         struct bfa_fcs_rport_s *rport = rpf->rport;
172
173         bfa_trc(rport->fcs, rport->pid);
174         bfa_trc(rport->fcs, event);
175
176         switch (event) {
177         case RPFSM_EVENT_TIMEOUT :
178                 /* re-send the RPSC */
179                 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
180                 bfa_fcs_rpf_send_rpsc2(rpf, NULL);
181                 break;
182
183         case RPFSM_EVENT_RPORT_OFFLINE :
184                 bfa_timer_stop(&rpf->timer);
185                 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
186                 rpf->rpsc_retries = 0;
187                 break;
188
189         default:
190                 bfa_assert(0);
191         }
192 }
193
194 static void
195 bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
196 {
197         struct bfa_fcs_rport_s *rport = rpf->rport;
198
199         bfa_trc(rport->fcs, rport->pwwn);
200         bfa_trc(rport->fcs, rport->pid);
201         bfa_trc(rport->fcs, event);
202
203         switch (event) {
204         case RPFSM_EVENT_RPORT_OFFLINE :
205                 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
206                 rpf->rpsc_retries = 0;
207                 break;
208
209         default:
210                 bfa_assert(0);
211         }
212 }
213
214 static void
215 bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
216 {
217         struct bfa_fcs_rport_s *rport = rpf->rport;
218
219         bfa_trc(rport->fcs, rport->pwwn);
220         bfa_trc(rport->fcs, rport->pid);
221         bfa_trc(rport->fcs, event);
222
223         switch (event) {
224         case RPFSM_EVENT_RPORT_ONLINE :
225                 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
226                 bfa_fcs_rpf_send_rpsc2(rpf, NULL);
227                 break;
228
229         case RPFSM_EVENT_RPORT_OFFLINE :
230                 break;
231
232         default:
233                 bfa_assert(0);
234         }
235 }
236 /**
237  * Called when Rport is created.
238  */
239 void  bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport)
240 {
241         struct bfa_fcs_rpf_s *rpf = &rport->rpf;
242
243         bfa_trc(rport->fcs, rport->pid);
244         rpf->rport = rport;
245
246         bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_uninit);
247 }
248
249 /**
250  * Called when Rport becomes online
251  */
252 void  bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport)
253 {
254         bfa_trc(rport->fcs, rport->pid);
255
256         if (__fcs_min_cfg(rport->port->fcs))
257                 return;
258
259         if (bfa_fcs_fabric_is_switched(rport->port->fabric))
260                 bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_ONLINE);
261 }
262
263 /**
264  * Called when Rport becomes offline
265  */
266 void  bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport)
267 {
268         bfa_trc(rport->fcs, rport->pid);
269
270         if (__fcs_min_cfg(rport->port->fcs))
271                 return;
272
273         bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_OFFLINE);
274 }
275
276 static void
277 bfa_fcs_rpf_timeout(void *arg)
278 {
279         struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) arg;
280         struct bfa_fcs_rport_s *rport = rpf->rport;
281
282         bfa_trc(rport->fcs, rport->pid);
283         bfa_sm_send_event(rpf, RPFSM_EVENT_TIMEOUT);
284 }
285
286 static void
287 bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced)
288 {
289         struct bfa_fcs_rpf_s *rpf       = (struct bfa_fcs_rpf_s *)rpf_cbarg;
290         struct bfa_fcs_rport_s *rport = rpf->rport;
291         struct bfa_fcs_port_s *port = rport->port;
292         struct fchs_s          fchs;
293         int             len;
294         struct bfa_fcxp_s *fcxp;
295
296         bfa_trc(rport->fcs, rport->pwwn);
297
298         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
299         if (!fcxp) {
300                 bfa_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe,
301                                         bfa_fcs_rpf_send_rpsc2, rpf);
302                 return;
303         }
304         rpf->fcxp = fcxp;
305
306         len = fc_rpsc2_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
307                             bfa_fcs_port_get_fcid(port), &rport->pid, 1);
308
309         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
310                           FC_CLASS_3, len, &fchs, bfa_fcs_rpf_rpsc2_response,
311                           rpf, FC_MAX_PDUSZ, FC_RA_TOV);
312         rport->stats.rpsc_sent++;
313         bfa_sm_send_event(rpf, RPFSM_EVENT_FCXP_SENT);
314
315 }
316
317 static void
318 bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
319                             bfa_status_t req_status, u32 rsp_len,
320                             u32 resid_len, struct fchs_s *rsp_fchs)
321 {
322         struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) cbarg;
323         struct bfa_fcs_rport_s *rport = rpf->rport;
324         struct fc_ls_rjt_s    *ls_rjt;
325         struct fc_rpsc2_acc_s  *rpsc2_acc;
326         u16        num_ents;
327
328         bfa_trc(rport->fcs, req_status);
329
330         if (req_status != BFA_STATUS_OK) {
331                 bfa_trc(rport->fcs, req_status);
332                 if (req_status == BFA_STATUS_ETIMER)
333                         rport->stats.rpsc_failed++;
334                 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
335                 return;
336         }
337
338         rpsc2_acc = (struct fc_rpsc2_acc_s *) BFA_FCXP_RSP_PLD(fcxp);
339         if (rpsc2_acc->els_cmd == FC_ELS_ACC) {
340                 rport->stats.rpsc_accs++;
341                 num_ents = bfa_os_ntohs(rpsc2_acc->num_pids);
342                 bfa_trc(rport->fcs, num_ents);
343                 if (num_ents > 0) {
344                         bfa_assert(rpsc2_acc->port_info[0].pid != rport->pid);
345                         bfa_trc(rport->fcs,
346                                 bfa_os_ntohs(rpsc2_acc->port_info[0].pid));
347                         bfa_trc(rport->fcs,
348                                 bfa_os_ntohs(rpsc2_acc->port_info[0].speed));
349                         bfa_trc(rport->fcs,
350                                 bfa_os_ntohs(rpsc2_acc->port_info[0].index));
351                         bfa_trc(rport->fcs,
352                                 rpsc2_acc->port_info[0].type);
353
354                         if (rpsc2_acc->port_info[0].speed == 0) {
355                                 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
356                                 return;
357                         }
358
359                         rpf->rpsc_speed = fc_rpsc_operspeed_to_bfa_speed(
360                                 bfa_os_ntohs(rpsc2_acc->port_info[0].speed));
361
362                         bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_COMP);
363                 }
364         } else {
365                 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
366                 bfa_trc(rport->fcs, ls_rjt->reason_code);
367                 bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
368                 rport->stats.rpsc_rejects++;
369                 if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP) {
370                         bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_FAIL);
371                 } else {
372                         bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
373                 }
374         }
375 }