Merge branch 'net-2.6' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[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_sm_fault(rport->fcs, event);
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_sm_fault(rport->fcs, event);
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                 break;
138
139         case RPFSM_EVENT_RPSC_FAIL:
140                 /* RPSC not supported by rport */
141                 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
142                 break;
143
144         case RPFSM_EVENT_RPSC_ERROR:
145                 /* need to retry...delayed a bit. */
146                 if (rpf->rpsc_retries++ < BFA_FCS_RPF_RETRIES) {
147                         bfa_timer_start(rport->fcs->bfa, &rpf->timer,
148                                     bfa_fcs_rpf_timeout, rpf,
149                                     BFA_FCS_RPF_RETRY_TIMEOUT);
150                         bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_retry);
151                 } else {
152                         bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
153                 }
154                 break;
155
156         case RPFSM_EVENT_RPORT_OFFLINE:
157                 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
158                 bfa_fcxp_discard(rpf->fcxp);
159                 rpf->rpsc_retries = 0;
160                 break;
161
162         default:
163                 bfa_sm_fault(rport->fcs, event);
164         }
165 }
166
167 static void
168 bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
169 {
170         struct bfa_fcs_rport_s *rport = rpf->rport;
171
172         bfa_trc(rport->fcs, rport->pid);
173         bfa_trc(rport->fcs, event);
174
175         switch (event) {
176         case RPFSM_EVENT_TIMEOUT:
177                 /* re-send the RPSC */
178                 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
179                 bfa_fcs_rpf_send_rpsc2(rpf, NULL);
180                 break;
181
182         case RPFSM_EVENT_RPORT_OFFLINE:
183                 bfa_timer_stop(&rpf->timer);
184                 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
185                 rpf->rpsc_retries = 0;
186                 break;
187
188         default:
189                 bfa_sm_fault(rport->fcs, event);
190         }
191 }
192
193 static void
194 bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
195 {
196         struct bfa_fcs_rport_s *rport = rpf->rport;
197
198         bfa_trc(rport->fcs, rport->pwwn);
199         bfa_trc(rport->fcs, rport->pid);
200         bfa_trc(rport->fcs, event);
201
202         switch (event) {
203         case RPFSM_EVENT_RPORT_OFFLINE:
204                 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
205                 rpf->rpsc_retries = 0;
206                 break;
207
208         default:
209                 bfa_sm_fault(rport->fcs, event);
210         }
211 }
212
213 static void
214 bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
215 {
216         struct bfa_fcs_rport_s *rport = rpf->rport;
217
218         bfa_trc(rport->fcs, rport->pwwn);
219         bfa_trc(rport->fcs, rport->pid);
220         bfa_trc(rport->fcs, event);
221
222         switch (event) {
223         case RPFSM_EVENT_RPORT_ONLINE:
224                 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
225                 bfa_fcs_rpf_send_rpsc2(rpf, NULL);
226                 break;
227
228         case RPFSM_EVENT_RPORT_OFFLINE:
229                 break;
230
231         default:
232                 bfa_sm_fault(rport->fcs, event);
233         }
234 }
235 /**
236  * Called when Rport is created.
237  */
238 void  bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport)
239 {
240         struct bfa_fcs_rpf_s *rpf = &rport->rpf;
241
242         bfa_trc(rport->fcs, rport->pid);
243         rpf->rport = rport;
244
245         bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_uninit);
246 }
247
248 /**
249  * Called when Rport becomes online
250  */
251 void  bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport)
252 {
253         bfa_trc(rport->fcs, rport->pid);
254
255         if (__fcs_min_cfg(rport->port->fcs))
256                 return;
257
258         if (bfa_fcs_fabric_is_switched(rport->port->fabric))
259                 bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_ONLINE);
260 }
261
262 /**
263  * Called when Rport becomes offline
264  */
265 void  bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport)
266 {
267         bfa_trc(rport->fcs, rport->pid);
268
269         if (__fcs_min_cfg(rport->port->fcs))
270                 return;
271
272         bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_OFFLINE);
273 }
274
275 static void
276 bfa_fcs_rpf_timeout(void *arg)
277 {
278         struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) arg;
279         struct bfa_fcs_rport_s *rport = rpf->rport;
280
281         bfa_trc(rport->fcs, rport->pid);
282         bfa_sm_send_event(rpf, RPFSM_EVENT_TIMEOUT);
283 }
284
285 static void
286 bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced)
287 {
288         struct bfa_fcs_rpf_s *rpf       = (struct bfa_fcs_rpf_s *)rpf_cbarg;
289         struct bfa_fcs_rport_s *rport = rpf->rport;
290         struct bfa_fcs_port_s *port = rport->port;
291         struct fchs_s          fchs;
292         int             len;
293         struct bfa_fcxp_s *fcxp;
294
295         bfa_trc(rport->fcs, rport->pwwn);
296
297         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
298         if (!fcxp) {
299                 bfa_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe,
300                                         bfa_fcs_rpf_send_rpsc2, rpf);
301                 return;
302         }
303         rpf->fcxp = fcxp;
304
305         len = fc_rpsc2_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
306                             bfa_fcs_port_get_fcid(port), &rport->pid, 1);
307
308         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
309                           FC_CLASS_3, len, &fchs, bfa_fcs_rpf_rpsc2_response,
310                           rpf, FC_MAX_PDUSZ, FC_RA_TOV);
311         rport->stats.rpsc_sent++;
312         bfa_sm_send_event(rpf, RPFSM_EVENT_FCXP_SENT);
313
314 }
315
316 static void
317 bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
318                             bfa_status_t req_status, u32 rsp_len,
319                             u32 resid_len, struct fchs_s *rsp_fchs)
320 {
321         struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) cbarg;
322         struct bfa_fcs_rport_s *rport = rpf->rport;
323         struct fc_ls_rjt_s    *ls_rjt;
324         struct fc_rpsc2_acc_s  *rpsc2_acc;
325         u16        num_ents;
326
327         bfa_trc(rport->fcs, req_status);
328
329         if (req_status != BFA_STATUS_OK) {
330                 bfa_trc(rport->fcs, req_status);
331                 if (req_status == BFA_STATUS_ETIMER)
332                         rport->stats.rpsc_failed++;
333                 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
334                 return;
335         }
336
337         rpsc2_acc = (struct fc_rpsc2_acc_s *) BFA_FCXP_RSP_PLD(fcxp);
338         if (rpsc2_acc->els_cmd == FC_ELS_ACC) {
339                 rport->stats.rpsc_accs++;
340                 num_ents = bfa_os_ntohs(rpsc2_acc->num_pids);
341                 bfa_trc(rport->fcs, num_ents);
342                 if (num_ents > 0) {
343                         bfa_assert(rpsc2_acc->port_info[0].pid != rport->pid);
344                         bfa_trc(rport->fcs,
345                                 bfa_os_ntohs(rpsc2_acc->port_info[0].pid));
346                         bfa_trc(rport->fcs,
347                                 bfa_os_ntohs(rpsc2_acc->port_info[0].speed));
348                         bfa_trc(rport->fcs,
349                                 bfa_os_ntohs(rpsc2_acc->port_info[0].index));
350                         bfa_trc(rport->fcs,
351                                 rpsc2_acc->port_info[0].type);
352
353                         if (rpsc2_acc->port_info[0].speed == 0) {
354                                 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
355                                 return;
356                         }
357
358                         rpf->rpsc_speed = fc_rpsc_operspeed_to_bfa_speed(
359                                 bfa_os_ntohs(rpsc2_acc->port_info[0].speed));
360
361                         bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_COMP);
362                 }
363         } else {
364                 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
365                 bfa_trc(rport->fcs, ls_rjt->reason_code);
366                 bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
367                 rport->stats.rpsc_rejects++;
368                 if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP)
369                         bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_FAIL);
370                 else
371                         bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
372         }
373 }