GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / scsi / bfa / rport_ftrs.c
blobf2a9361ce9a4335ba97e710014f933030855c16f
1 /*
2 * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
3 * All rights reserved
4 * www.brocade.com
6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
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
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.
18 /**
19 * rport_ftrs.c Remote port features (RPF) implementation.
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"
31 BFA_TRC_FILE(FCS, RPORT_FTRS);
33 #define BFA_FCS_RPF_RETRIES (3)
34 #define BFA_FCS_RPF_RETRY_TIMEOUT (1000) /* 1 sec (In millisecs) */
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);
45 /**
46 * fcs_rport_ftrs_sm FCS rport state machine events
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,
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);
72 static void
73 bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
75 struct bfa_fcs_rport_s *rport = rpf->rport;
76 struct bfa_fcs_fabric_s *fabric = &rport->fcs->fabric;
78 bfa_trc(rport->fcs, rport->pwwn);
79 bfa_trc(rport->fcs, rport->pid);
80 bfa_trc(rport->fcs, event);
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);
93 break;
95 case RPFSM_EVENT_RPORT_OFFLINE:
96 break;
98 default:
99 bfa_sm_fault(rport->fcs, event);
103 static void
104 bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
106 struct bfa_fcs_rport_s *rport = rpf->rport;
108 bfa_trc(rport->fcs, event);
110 switch (event) {
111 case RPFSM_EVENT_FCXP_SENT:
112 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc);
113 break;
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;
121 default:
122 bfa_sm_fault(rport->fcs, event);
126 static void
127 bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
129 struct bfa_fcs_rport_s *rport = rpf->rport;
131 bfa_trc(rport->fcs, rport->pid);
132 bfa_trc(rport->fcs, event);
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;
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;
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);
159 break;
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;
167 default:
168 bfa_sm_fault(rport->fcs, event);
172 static void
173 bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
175 struct bfa_fcs_rport_s *rport = rpf->rport;
177 bfa_trc(rport->fcs, rport->pid);
178 bfa_trc(rport->fcs, event);
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;
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;
193 default:
194 bfa_sm_fault(rport->fcs, event);
198 static void
199 bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
201 struct bfa_fcs_rport_s *rport = rpf->rport;
203 bfa_trc(rport->fcs, rport->pwwn);
204 bfa_trc(rport->fcs, rport->pid);
205 bfa_trc(rport->fcs, event);
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;
213 default:
214 bfa_sm_fault(rport->fcs, event);
218 static void
219 bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
221 struct bfa_fcs_rport_s *rport = rpf->rport;
223 bfa_trc(rport->fcs, rport->pwwn);
224 bfa_trc(rport->fcs, rport->pid);
225 bfa_trc(rport->fcs, event);
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;
233 case RPFSM_EVENT_RPORT_OFFLINE:
234 break;
236 default:
237 bfa_sm_fault(rport->fcs, event);
241 * Called when Rport is created.
243 void bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport)
245 struct bfa_fcs_rpf_s *rpf = &rport->rpf;
247 bfa_trc(rport->fcs, rport->pid);
248 rpf->rport = rport;
250 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_uninit);
254 * Called when Rport becomes online
256 void bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport)
258 bfa_trc(rport->fcs, rport->pid);
260 if (__fcs_min_cfg(rport->port->fcs))
261 return;
263 if (bfa_fcs_fabric_is_switched(rport->port->fabric))
264 bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_ONLINE);
268 * Called when Rport becomes offline
270 void bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport)
272 bfa_trc(rport->fcs, rport->pid);
274 if (__fcs_min_cfg(rport->port->fcs))
275 return;
277 rport->rpf.rpsc_speed = 0;
278 bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_OFFLINE);
281 static void
282 bfa_fcs_rpf_timeout(void *arg)
284 struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) arg;
285 struct bfa_fcs_rport_s *rport = rpf->rport;
287 bfa_trc(rport->fcs, rport->pid);
288 bfa_sm_send_event(rpf, RPFSM_EVENT_TIMEOUT);
291 static void
292 bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced)
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;
301 bfa_trc(rport->fcs, rport->pwwn);
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;
309 rpf->fcxp = fcxp;
311 len = fc_rpsc2_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
312 bfa_fcs_port_get_fcid(port), &rport->pid, 1);
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);
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)
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;
333 bfa_trc(rport->fcs, req_status);
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;
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);
359 if (rpsc2_acc->port_info[0].speed == 0) {
360 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
361 return;
364 rpf->rpsc_speed = fc_rpsc_operspeed_to_bfa_speed(
365 bfa_os_ntohs(rpsc2_acc->port_info[0].speed));
367 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_COMP);
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);