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