blob: cfc0b09465ec9392bad42bd506cc7b4044c40c97 [file] [log] [blame]
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001/*
2 * Copyright (c) 2005-2010 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
Maggie Zhangf16a1752010-12-09 19:12:32 -080018#include "bfad_drv.h"
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070019#include "bfa_plog.h"
20#include "bfa_cs.h"
21#include "bfa_modules.h"
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070022
23BFA_TRC_FILE(HAL, FCXP);
24BFA_MODULE(fcxp);
25BFA_MODULE(sgpg);
26BFA_MODULE(lps);
27BFA_MODULE(fcport);
28BFA_MODULE(rport);
29BFA_MODULE(uf);
30
Jing Huang5fbe25c2010-10-18 17:17:23 -070031/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070032 * LPS related definitions
33 */
34#define BFA_LPS_MIN_LPORTS (1)
35#define BFA_LPS_MAX_LPORTS (256)
36
37/*
38 * Maximum Vports supported per physical port or vf.
39 */
40#define BFA_LPS_MAX_VPORTS_SUPP_CB 255
41#define BFA_LPS_MAX_VPORTS_SUPP_CT 190
42
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070043
Jing Huang5fbe25c2010-10-18 17:17:23 -070044/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070045 * FC PORT related definitions
46 */
47/*
48 * The port is considered disabled if corresponding physical port or IOC are
49 * disabled explicitly
50 */
51#define BFA_PORT_IS_DISABLED(bfa) \
52 ((bfa_fcport_is_disabled(bfa) == BFA_TRUE) || \
53 (bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE))
54
Jing Huang5fbe25c2010-10-18 17:17:23 -070055/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070056 * BFA port state machine events
57 */
58enum bfa_fcport_sm_event {
59 BFA_FCPORT_SM_START = 1, /* start port state machine */
60 BFA_FCPORT_SM_STOP = 2, /* stop port state machine */
61 BFA_FCPORT_SM_ENABLE = 3, /* enable port */
62 BFA_FCPORT_SM_DISABLE = 4, /* disable port state machine */
63 BFA_FCPORT_SM_FWRSP = 5, /* firmware enable/disable rsp */
64 BFA_FCPORT_SM_LINKUP = 6, /* firmware linkup event */
65 BFA_FCPORT_SM_LINKDOWN = 7, /* firmware linkup down */
66 BFA_FCPORT_SM_QRESUME = 8, /* CQ space available */
67 BFA_FCPORT_SM_HWFAIL = 9, /* IOC h/w failure */
68};
69
Jing Huang5fbe25c2010-10-18 17:17:23 -070070/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070071 * BFA port link notification state machine events
72 */
73
74enum bfa_fcport_ln_sm_event {
75 BFA_FCPORT_LN_SM_LINKUP = 1, /* linkup event */
76 BFA_FCPORT_LN_SM_LINKDOWN = 2, /* linkdown event */
77 BFA_FCPORT_LN_SM_NOTIFICATION = 3 /* done notification */
78};
79
Jing Huang5fbe25c2010-10-18 17:17:23 -070080/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070081 * RPORT related definitions
82 */
83#define bfa_rport_offline_cb(__rp) do { \
84 if ((__rp)->bfa->fcs) \
85 bfa_cb_rport_offline((__rp)->rport_drv); \
86 else { \
87 bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe, \
88 __bfa_cb_rport_offline, (__rp)); \
89 } \
90} while (0)
91
92#define bfa_rport_online_cb(__rp) do { \
93 if ((__rp)->bfa->fcs) \
94 bfa_cb_rport_online((__rp)->rport_drv); \
95 else { \
96 bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe, \
97 __bfa_cb_rport_online, (__rp)); \
98 } \
99} while (0)
100
Jing Huang5fbe25c2010-10-18 17:17:23 -0700101/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700102 * forward declarations FCXP related functions
103 */
104static void __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete);
105static void hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
106 struct bfi_fcxp_send_rsp_s *fcxp_rsp);
107static void hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen,
108 struct bfa_fcxp_s *fcxp, struct fchs_s *fchs);
109static void bfa_fcxp_qresume(void *cbarg);
110static void bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,
111 struct bfi_fcxp_send_req_s *send_req);
112
Jing Huang5fbe25c2010-10-18 17:17:23 -0700113/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700114 * forward declarations for LPS functions
115 */
116static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
117 u32 *dm_len);
118static void bfa_lps_attach(struct bfa_s *bfa, void *bfad,
119 struct bfa_iocfc_cfg_s *cfg,
120 struct bfa_meminfo_s *meminfo,
121 struct bfa_pcidev_s *pcidev);
122static void bfa_lps_detach(struct bfa_s *bfa);
123static void bfa_lps_start(struct bfa_s *bfa);
124static void bfa_lps_stop(struct bfa_s *bfa);
125static void bfa_lps_iocdisable(struct bfa_s *bfa);
126static void bfa_lps_login_rsp(struct bfa_s *bfa,
127 struct bfi_lps_login_rsp_s *rsp);
Krishna Gudipati3fd45982011-06-24 20:24:08 -0700128static void bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700129static void bfa_lps_logout_rsp(struct bfa_s *bfa,
130 struct bfi_lps_logout_rsp_s *rsp);
131static void bfa_lps_reqq_resume(void *lps_arg);
132static void bfa_lps_free(struct bfa_lps_s *lps);
133static void bfa_lps_send_login(struct bfa_lps_s *lps);
134static void bfa_lps_send_logout(struct bfa_lps_s *lps);
Krishna Gudipatib7044952010-12-13 16:17:42 -0800135static void bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700136static void bfa_lps_login_comp(struct bfa_lps_s *lps);
137static void bfa_lps_logout_comp(struct bfa_lps_s *lps);
138static void bfa_lps_cvl_event(struct bfa_lps_s *lps);
139
Jing Huang5fbe25c2010-10-18 17:17:23 -0700140/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700141 * forward declaration for LPS state machine
142 */
143static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event);
144static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);
145static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event
146 event);
147static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);
Krishna Gudipatib7044952010-12-13 16:17:42 -0800148static void bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps,
149 enum bfa_lps_event event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700150static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);
151static void bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event
152 event);
153
Jing Huang5fbe25c2010-10-18 17:17:23 -0700154/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700155 * forward declaration for FC Port functions
156 */
157static bfa_boolean_t bfa_fcport_send_enable(struct bfa_fcport_s *fcport);
158static bfa_boolean_t bfa_fcport_send_disable(struct bfa_fcport_s *fcport);
159static void bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport);
160static void bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport);
161static void bfa_fcport_set_wwns(struct bfa_fcport_s *fcport);
162static void __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete);
163static void bfa_fcport_scn(struct bfa_fcport_s *fcport,
164 enum bfa_port_linkstate event, bfa_boolean_t trunk);
165static void bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln,
166 enum bfa_port_linkstate event);
167static void __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete);
168static void bfa_fcport_stats_get_timeout(void *cbarg);
169static void bfa_fcport_stats_clr_timeout(void *cbarg);
170static void bfa_trunk_iocdisable(struct bfa_s *bfa);
171
Jing Huang5fbe25c2010-10-18 17:17:23 -0700172/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700173 * forward declaration for FC PORT state machine
174 */
175static void bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
176 enum bfa_fcport_sm_event event);
177static void bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
178 enum bfa_fcport_sm_event event);
179static void bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
180 enum bfa_fcport_sm_event event);
181static void bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
182 enum bfa_fcport_sm_event event);
183static void bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
184 enum bfa_fcport_sm_event event);
185static void bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
186 enum bfa_fcport_sm_event event);
187static void bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
188 enum bfa_fcport_sm_event event);
189static void bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
190 enum bfa_fcport_sm_event event);
191static void bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
192 enum bfa_fcport_sm_event event);
193static void bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
194 enum bfa_fcport_sm_event event);
195static void bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
196 enum bfa_fcport_sm_event event);
197static void bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
198 enum bfa_fcport_sm_event event);
199
200static void bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
201 enum bfa_fcport_ln_sm_event event);
202static void bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
203 enum bfa_fcport_ln_sm_event event);
204static void bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
205 enum bfa_fcport_ln_sm_event event);
206static void bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
207 enum bfa_fcport_ln_sm_event event);
208static void bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
209 enum bfa_fcport_ln_sm_event event);
210static void bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
211 enum bfa_fcport_ln_sm_event event);
212static void bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
213 enum bfa_fcport_ln_sm_event event);
214
215static struct bfa_sm_table_s hal_port_sm_table[] = {
216 {BFA_SM(bfa_fcport_sm_uninit), BFA_PORT_ST_UNINIT},
217 {BFA_SM(bfa_fcport_sm_enabling_qwait), BFA_PORT_ST_ENABLING_QWAIT},
218 {BFA_SM(bfa_fcport_sm_enabling), BFA_PORT_ST_ENABLING},
219 {BFA_SM(bfa_fcport_sm_linkdown), BFA_PORT_ST_LINKDOWN},
220 {BFA_SM(bfa_fcport_sm_linkup), BFA_PORT_ST_LINKUP},
221 {BFA_SM(bfa_fcport_sm_disabling_qwait), BFA_PORT_ST_DISABLING_QWAIT},
222 {BFA_SM(bfa_fcport_sm_toggling_qwait), BFA_PORT_ST_TOGGLING_QWAIT},
223 {BFA_SM(bfa_fcport_sm_disabling), BFA_PORT_ST_DISABLING},
224 {BFA_SM(bfa_fcport_sm_disabled), BFA_PORT_ST_DISABLED},
225 {BFA_SM(bfa_fcport_sm_stopped), BFA_PORT_ST_STOPPED},
226 {BFA_SM(bfa_fcport_sm_iocdown), BFA_PORT_ST_IOCDOWN},
227 {BFA_SM(bfa_fcport_sm_iocfail), BFA_PORT_ST_IOCDOWN},
228};
229
230
Jing Huang5fbe25c2010-10-18 17:17:23 -0700231/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700232 * forward declaration for RPORT related functions
233 */
234static struct bfa_rport_s *bfa_rport_alloc(struct bfa_rport_mod_s *rp_mod);
235static void bfa_rport_free(struct bfa_rport_s *rport);
236static bfa_boolean_t bfa_rport_send_fwcreate(struct bfa_rport_s *rp);
237static bfa_boolean_t bfa_rport_send_fwdelete(struct bfa_rport_s *rp);
238static bfa_boolean_t bfa_rport_send_fwspeed(struct bfa_rport_s *rp);
239static void __bfa_cb_rport_online(void *cbarg,
240 bfa_boolean_t complete);
241static void __bfa_cb_rport_offline(void *cbarg,
242 bfa_boolean_t complete);
243
Jing Huang5fbe25c2010-10-18 17:17:23 -0700244/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700245 * forward declaration for RPORT state machine
246 */
247static void bfa_rport_sm_uninit(struct bfa_rport_s *rp,
248 enum bfa_rport_event event);
249static void bfa_rport_sm_created(struct bfa_rport_s *rp,
250 enum bfa_rport_event event);
251static void bfa_rport_sm_fwcreate(struct bfa_rport_s *rp,
252 enum bfa_rport_event event);
253static void bfa_rport_sm_online(struct bfa_rport_s *rp,
254 enum bfa_rport_event event);
255static void bfa_rport_sm_fwdelete(struct bfa_rport_s *rp,
256 enum bfa_rport_event event);
257static void bfa_rport_sm_offline(struct bfa_rport_s *rp,
258 enum bfa_rport_event event);
259static void bfa_rport_sm_deleting(struct bfa_rport_s *rp,
260 enum bfa_rport_event event);
261static void bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
262 enum bfa_rport_event event);
263static void bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
264 enum bfa_rport_event event);
265static void bfa_rport_sm_iocdisable(struct bfa_rport_s *rp,
266 enum bfa_rport_event event);
267static void bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp,
268 enum bfa_rport_event event);
269static void bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp,
270 enum bfa_rport_event event);
271static void bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp,
272 enum bfa_rport_event event);
273
Jing Huang5fbe25c2010-10-18 17:17:23 -0700274/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700275 * PLOG related definitions
276 */
277static int
278plkd_validate_logrec(struct bfa_plog_rec_s *pl_rec)
279{
280 if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&
281 (pl_rec->log_type != BFA_PL_LOG_TYPE_STRING))
282 return 1;
283
284 if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&
285 (pl_rec->log_num_ints > BFA_PL_INT_LOG_SZ))
286 return 1;
287
288 return 0;
289}
290
Maggie Zhangf16a1752010-12-09 19:12:32 -0800291static u64
292bfa_get_log_time(void)
293{
294 u64 system_time = 0;
295 struct timeval tv;
296 do_gettimeofday(&tv);
297
298 /* We are interested in seconds only. */
299 system_time = tv.tv_sec;
300 return system_time;
301}
302
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700303static void
304bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)
305{
306 u16 tail;
307 struct bfa_plog_rec_s *pl_recp;
308
309 if (plog->plog_enabled == 0)
310 return;
311
312 if (plkd_validate_logrec(pl_rec)) {
Jing Huangd4b671c2010-12-26 21:46:35 -0800313 WARN_ON(1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700314 return;
315 }
316
317 tail = plog->tail;
318
319 pl_recp = &(plog->plog_recs[tail]);
320
Jing Huang6a18b162010-10-18 17:08:54 -0700321 memcpy(pl_recp, pl_rec, sizeof(struct bfa_plog_rec_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700322
Maggie Zhangf16a1752010-12-09 19:12:32 -0800323 pl_recp->tv = bfa_get_log_time();
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700324 BFA_PL_LOG_REC_INCR(plog->tail);
325
326 if (plog->head == plog->tail)
327 BFA_PL_LOG_REC_INCR(plog->head);
328}
329
330void
331bfa_plog_init(struct bfa_plog_s *plog)
332{
Jing Huang6a18b162010-10-18 17:08:54 -0700333 memset((char *)plog, 0, sizeof(struct bfa_plog_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700334
Jing Huang6a18b162010-10-18 17:08:54 -0700335 memcpy(plog->plog_sig, BFA_PL_SIG_STR, BFA_PL_SIG_LEN);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700336 plog->head = plog->tail = 0;
337 plog->plog_enabled = 1;
338}
339
340void
341bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
342 enum bfa_plog_eid event,
343 u16 misc, char *log_str)
344{
345 struct bfa_plog_rec_s lp;
346
347 if (plog->plog_enabled) {
Jing Huang6a18b162010-10-18 17:08:54 -0700348 memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700349 lp.mid = mid;
350 lp.eid = event;
351 lp.log_type = BFA_PL_LOG_TYPE_STRING;
352 lp.misc = misc;
353 strncpy(lp.log_entry.string_log, log_str,
354 BFA_PL_STRING_LOG_SZ - 1);
355 lp.log_entry.string_log[BFA_PL_STRING_LOG_SZ - 1] = '\0';
356 bfa_plog_add(plog, &lp);
357 }
358}
359
360void
361bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
362 enum bfa_plog_eid event,
363 u16 misc, u32 *intarr, u32 num_ints)
364{
365 struct bfa_plog_rec_s lp;
366 u32 i;
367
368 if (num_ints > BFA_PL_INT_LOG_SZ)
369 num_ints = BFA_PL_INT_LOG_SZ;
370
371 if (plog->plog_enabled) {
Jing Huang6a18b162010-10-18 17:08:54 -0700372 memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700373 lp.mid = mid;
374 lp.eid = event;
375 lp.log_type = BFA_PL_LOG_TYPE_INT;
376 lp.misc = misc;
377
378 for (i = 0; i < num_ints; i++)
Jing Huang6a18b162010-10-18 17:08:54 -0700379 lp.log_entry.int_log[i] = intarr[i];
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700380
381 lp.log_num_ints = (u8) num_ints;
382
383 bfa_plog_add(plog, &lp);
384 }
385}
386
387void
388bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
389 enum bfa_plog_eid event,
390 u16 misc, struct fchs_s *fchdr)
391{
392 struct bfa_plog_rec_s lp;
393 u32 *tmp_int = (u32 *) fchdr;
394 u32 ints[BFA_PL_INT_LOG_SZ];
395
396 if (plog->plog_enabled) {
Jing Huang6a18b162010-10-18 17:08:54 -0700397 memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700398
399 ints[0] = tmp_int[0];
400 ints[1] = tmp_int[1];
401 ints[2] = tmp_int[4];
402
403 bfa_plog_intarr(plog, mid, event, misc, ints, 3);
404 }
405}
406
407void
408bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
409 enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr,
410 u32 pld_w0)
411{
412 struct bfa_plog_rec_s lp;
413 u32 *tmp_int = (u32 *) fchdr;
414 u32 ints[BFA_PL_INT_LOG_SZ];
415
416 if (plog->plog_enabled) {
Jing Huang6a18b162010-10-18 17:08:54 -0700417 memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700418
419 ints[0] = tmp_int[0];
420 ints[1] = tmp_int[1];
421 ints[2] = tmp_int[4];
422 ints[3] = pld_w0;
423
424 bfa_plog_intarr(plog, mid, event, misc, ints, 4);
425 }
426}
427
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700428
Jing Huang5fbe25c2010-10-18 17:17:23 -0700429/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700430 * fcxp_pvt BFA FCXP private functions
431 */
432
433static void
434claim_fcxp_req_rsp_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
435{
436 u8 *dm_kva = NULL;
437 u64 dm_pa;
438 u32 buf_pool_sz;
439
440 dm_kva = bfa_meminfo_dma_virt(mi);
441 dm_pa = bfa_meminfo_dma_phys(mi);
442
443 buf_pool_sz = mod->req_pld_sz * mod->num_fcxps;
444
445 /*
446 * Initialize the fcxp req payload list
447 */
448 mod->req_pld_list_kva = dm_kva;
449 mod->req_pld_list_pa = dm_pa;
450 dm_kva += buf_pool_sz;
451 dm_pa += buf_pool_sz;
Jing Huang6a18b162010-10-18 17:08:54 -0700452 memset(mod->req_pld_list_kva, 0, buf_pool_sz);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700453
454 /*
455 * Initialize the fcxp rsp payload list
456 */
457 buf_pool_sz = mod->rsp_pld_sz * mod->num_fcxps;
458 mod->rsp_pld_list_kva = dm_kva;
459 mod->rsp_pld_list_pa = dm_pa;
460 dm_kva += buf_pool_sz;
461 dm_pa += buf_pool_sz;
Jing Huang6a18b162010-10-18 17:08:54 -0700462 memset(mod->rsp_pld_list_kva, 0, buf_pool_sz);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700463
464 bfa_meminfo_dma_virt(mi) = dm_kva;
465 bfa_meminfo_dma_phys(mi) = dm_pa;
466}
467
468static void
469claim_fcxps_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
470{
471 u16 i;
472 struct bfa_fcxp_s *fcxp;
473
474 fcxp = (struct bfa_fcxp_s *) bfa_meminfo_kva(mi);
Jing Huang6a18b162010-10-18 17:08:54 -0700475 memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700476
477 INIT_LIST_HEAD(&mod->fcxp_free_q);
478 INIT_LIST_HEAD(&mod->fcxp_active_q);
Krishna Gudipati3fd45982011-06-24 20:24:08 -0700479 INIT_LIST_HEAD(&mod->fcxp_unused_q);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700480
481 mod->fcxp_list = fcxp;
482
483 for (i = 0; i < mod->num_fcxps; i++) {
484 fcxp->fcxp_mod = mod;
485 fcxp->fcxp_tag = i;
486
487 list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
488 bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
489 fcxp->reqq_waiting = BFA_FALSE;
490
491 fcxp = fcxp + 1;
492 }
493
494 bfa_meminfo_kva(mi) = (void *)fcxp;
495}
496
497static void
498bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
499 u32 *dm_len)
500{
501 u16 num_fcxp_reqs = cfg->fwcfg.num_fcxp_reqs;
502
503 if (num_fcxp_reqs == 0)
504 return;
505
506 /*
507 * Account for req/rsp payload
508 */
509 *dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
510 if (cfg->drvcfg.min_cfg)
511 *dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
512 else
513 *dm_len += BFA_FCXP_MAX_LBUF_SZ * num_fcxp_reqs;
514
515 /*
516 * Account for fcxp structs
517 */
518 *ndm_len += sizeof(struct bfa_fcxp_s) * num_fcxp_reqs;
519}
520
521static void
522bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
523 struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
524{
525 struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
526
Jing Huang6a18b162010-10-18 17:08:54 -0700527 memset(mod, 0, sizeof(struct bfa_fcxp_mod_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700528 mod->bfa = bfa;
529 mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;
530
Jing Huang5fbe25c2010-10-18 17:17:23 -0700531 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700532 * Initialize FCXP request and response payload sizes.
533 */
534 mod->req_pld_sz = mod->rsp_pld_sz = BFA_FCXP_MAX_IBUF_SZ;
535 if (!cfg->drvcfg.min_cfg)
536 mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
537
538 INIT_LIST_HEAD(&mod->wait_q);
539
540 claim_fcxp_req_rsp_mem(mod, meminfo);
541 claim_fcxps_mem(mod, meminfo);
542}
543
544static void
545bfa_fcxp_detach(struct bfa_s *bfa)
546{
547}
548
549static void
550bfa_fcxp_start(struct bfa_s *bfa)
551{
552}
553
554static void
555bfa_fcxp_stop(struct bfa_s *bfa)
556{
557}
558
559static void
560bfa_fcxp_iocdisable(struct bfa_s *bfa)
561{
562 struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
563 struct bfa_fcxp_s *fcxp;
564 struct list_head *qe, *qen;
565
Krishna Gudipati3fd45982011-06-24 20:24:08 -0700566 /* Enqueue unused fcxp resources to free_q */
567 list_splice_tail_init(&mod->fcxp_unused_q, &mod->fcxp_free_q);
568
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700569 list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
570 fcxp = (struct bfa_fcxp_s *) qe;
571 if (fcxp->caller == NULL) {
572 fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
573 BFA_STATUS_IOC_FAILURE, 0, 0, NULL);
574 bfa_fcxp_free(fcxp);
575 } else {
576 fcxp->rsp_status = BFA_STATUS_IOC_FAILURE;
577 bfa_cb_queue(bfa, &fcxp->hcb_qe,
578 __bfa_fcxp_send_cbfn, fcxp);
579 }
580 }
581}
582
583static struct bfa_fcxp_s *
584bfa_fcxp_get(struct bfa_fcxp_mod_s *fm)
585{
586 struct bfa_fcxp_s *fcxp;
587
588 bfa_q_deq(&fm->fcxp_free_q, &fcxp);
589
590 if (fcxp)
591 list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
592
593 return fcxp;
594}
595
596static void
597bfa_fcxp_init_reqrsp(struct bfa_fcxp_s *fcxp,
598 struct bfa_s *bfa,
599 u8 *use_ibuf,
600 u32 *nr_sgles,
601 bfa_fcxp_get_sgaddr_t *r_sga_cbfn,
602 bfa_fcxp_get_sglen_t *r_sglen_cbfn,
603 struct list_head *r_sgpg_q,
604 int n_sgles,
605 bfa_fcxp_get_sgaddr_t sga_cbfn,
606 bfa_fcxp_get_sglen_t sglen_cbfn)
607{
608
Jing Huangd4b671c2010-12-26 21:46:35 -0800609 WARN_ON(bfa == NULL);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700610
611 bfa_trc(bfa, fcxp->fcxp_tag);
612
613 if (n_sgles == 0) {
614 *use_ibuf = 1;
615 } else {
Jing Huangd4b671c2010-12-26 21:46:35 -0800616 WARN_ON(*sga_cbfn == NULL);
617 WARN_ON(*sglen_cbfn == NULL);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700618
619 *use_ibuf = 0;
620 *r_sga_cbfn = sga_cbfn;
621 *r_sglen_cbfn = sglen_cbfn;
622
623 *nr_sgles = n_sgles;
624
625 /*
626 * alloc required sgpgs
627 */
628 if (n_sgles > BFI_SGE_INLINE)
Jing Huangd4b671c2010-12-26 21:46:35 -0800629 WARN_ON(1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700630 }
631
632}
633
634static void
635bfa_fcxp_init(struct bfa_fcxp_s *fcxp,
636 void *caller, struct bfa_s *bfa, int nreq_sgles,
637 int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
638 bfa_fcxp_get_sglen_t req_sglen_cbfn,
639 bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
640 bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
641{
642
Jing Huangd4b671c2010-12-26 21:46:35 -0800643 WARN_ON(bfa == NULL);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700644
645 bfa_trc(bfa, fcxp->fcxp_tag);
646
647 fcxp->caller = caller;
648
649 bfa_fcxp_init_reqrsp(fcxp, bfa,
650 &fcxp->use_ireqbuf, &fcxp->nreq_sgles, &fcxp->req_sga_cbfn,
651 &fcxp->req_sglen_cbfn, &fcxp->req_sgpg_q,
652 nreq_sgles, req_sga_cbfn, req_sglen_cbfn);
653
654 bfa_fcxp_init_reqrsp(fcxp, bfa,
655 &fcxp->use_irspbuf, &fcxp->nrsp_sgles, &fcxp->rsp_sga_cbfn,
656 &fcxp->rsp_sglen_cbfn, &fcxp->rsp_sgpg_q,
657 nrsp_sgles, rsp_sga_cbfn, rsp_sglen_cbfn);
658
659}
660
661static void
662bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
663{
664 struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
665 struct bfa_fcxp_wqe_s *wqe;
666
667 bfa_q_deq(&mod->wait_q, &wqe);
668 if (wqe) {
669 bfa_trc(mod->bfa, fcxp->fcxp_tag);
670
671 bfa_fcxp_init(fcxp, wqe->caller, wqe->bfa, wqe->nreq_sgles,
672 wqe->nrsp_sgles, wqe->req_sga_cbfn,
673 wqe->req_sglen_cbfn, wqe->rsp_sga_cbfn,
674 wqe->rsp_sglen_cbfn);
675
676 wqe->alloc_cbfn(wqe->alloc_cbarg, fcxp);
677 return;
678 }
679
Jing Huangd4b671c2010-12-26 21:46:35 -0800680 WARN_ON(!bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700681 list_del(&fcxp->qe);
682 list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
683}
684
685static void
686bfa_fcxp_null_comp(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
687 bfa_status_t req_status, u32 rsp_len,
688 u32 resid_len, struct fchs_s *rsp_fchs)
689{
690 /* discarded fcxp completion */
691}
692
693static void
694__bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete)
695{
696 struct bfa_fcxp_s *fcxp = cbarg;
697
698 if (complete) {
699 fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
700 fcxp->rsp_status, fcxp->rsp_len,
701 fcxp->residue_len, &fcxp->rsp_fchs);
702 } else {
703 bfa_fcxp_free(fcxp);
704 }
705}
706
707static void
708hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
709{
710 struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
711 struct bfa_fcxp_s *fcxp;
Jing Huangba816ea2010-10-18 17:10:50 -0700712 u16 fcxp_tag = be16_to_cpu(fcxp_rsp->fcxp_tag);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700713
714 bfa_trc(bfa, fcxp_tag);
715
Jing Huangba816ea2010-10-18 17:10:50 -0700716 fcxp_rsp->rsp_len = be32_to_cpu(fcxp_rsp->rsp_len);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700717
Jing Huang5fbe25c2010-10-18 17:17:23 -0700718 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700719 * @todo f/w should not set residue to non-0 when everything
720 * is received.
721 */
722 if (fcxp_rsp->req_status == BFA_STATUS_OK)
723 fcxp_rsp->residue_len = 0;
724 else
Jing Huangba816ea2010-10-18 17:10:50 -0700725 fcxp_rsp->residue_len = be32_to_cpu(fcxp_rsp->residue_len);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700726
727 fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);
728
Jing Huangd4b671c2010-12-26 21:46:35 -0800729 WARN_ON(fcxp->send_cbfn == NULL);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700730
731 hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);
732
733 if (fcxp->send_cbfn != NULL) {
734 bfa_trc(mod->bfa, (NULL == fcxp->caller));
735 if (fcxp->caller == NULL) {
736 fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
737 fcxp_rsp->req_status, fcxp_rsp->rsp_len,
738 fcxp_rsp->residue_len, &fcxp_rsp->fchs);
739 /*
740 * fcxp automatically freed on return from the callback
741 */
742 bfa_fcxp_free(fcxp);
743 } else {
744 fcxp->rsp_status = fcxp_rsp->req_status;
745 fcxp->rsp_len = fcxp_rsp->rsp_len;
746 fcxp->residue_len = fcxp_rsp->residue_len;
747 fcxp->rsp_fchs = fcxp_rsp->fchs;
748
749 bfa_cb_queue(bfa, &fcxp->hcb_qe,
750 __bfa_fcxp_send_cbfn, fcxp);
751 }
752 } else {
753 bfa_trc(bfa, (NULL == fcxp->send_cbfn));
754 }
755}
756
757static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700758hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,
759 struct fchs_s *fchs)
760{
761 /*
762 * TODO: TX ox_id
763 */
764 if (reqlen > 0) {
765 if (fcxp->use_ireqbuf) {
766 u32 pld_w0 =
767 *((u32 *) BFA_FCXP_REQ_PLD(fcxp));
768
769 bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
770 BFA_PL_EID_TX,
771 reqlen + sizeof(struct fchs_s), fchs,
772 pld_w0);
773 } else {
774 bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
775 BFA_PL_EID_TX,
776 reqlen + sizeof(struct fchs_s),
777 fchs);
778 }
779 } else {
780 bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_TX,
781 reqlen + sizeof(struct fchs_s), fchs);
782 }
783}
784
785static void
786hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
787 struct bfi_fcxp_send_rsp_s *fcxp_rsp)
788{
789 if (fcxp_rsp->rsp_len > 0) {
790 if (fcxp->use_irspbuf) {
791 u32 pld_w0 =
792 *((u32 *) BFA_FCXP_RSP_PLD(fcxp));
793
794 bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
795 BFA_PL_EID_RX,
796 (u16) fcxp_rsp->rsp_len,
797 &fcxp_rsp->fchs, pld_w0);
798 } else {
799 bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
800 BFA_PL_EID_RX,
801 (u16) fcxp_rsp->rsp_len,
802 &fcxp_rsp->fchs);
803 }
804 } else {
805 bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_RX,
806 (u16) fcxp_rsp->rsp_len, &fcxp_rsp->fchs);
807 }
808}
809
Jing Huang5fbe25c2010-10-18 17:17:23 -0700810/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700811 * Handler to resume sending fcxp when space in available in cpe queue.
812 */
813static void
814bfa_fcxp_qresume(void *cbarg)
815{
816 struct bfa_fcxp_s *fcxp = cbarg;
817 struct bfa_s *bfa = fcxp->fcxp_mod->bfa;
818 struct bfi_fcxp_send_req_s *send_req;
819
820 fcxp->reqq_waiting = BFA_FALSE;
821 send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
822 bfa_fcxp_queue(fcxp, send_req);
823}
824
Jing Huang5fbe25c2010-10-18 17:17:23 -0700825/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700826 * Queue fcxp send request to foimrware.
827 */
828static void
829bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
830{
831 struct bfa_s *bfa = fcxp->fcxp_mod->bfa;
832 struct bfa_fcxp_req_info_s *reqi = &fcxp->req_info;
833 struct bfa_fcxp_rsp_info_s *rspi = &fcxp->rsp_info;
834 struct bfa_rport_s *rport = reqi->bfa_rport;
835
836 bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,
Krishna Gudipati3fd45982011-06-24 20:24:08 -0700837 bfa_fn_lpu(bfa));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700838
Jing Huangba816ea2010-10-18 17:10:50 -0700839 send_req->fcxp_tag = cpu_to_be16(fcxp->fcxp_tag);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700840 if (rport) {
841 send_req->rport_fw_hndl = rport->fw_handle;
Jing Huangba816ea2010-10-18 17:10:50 -0700842 send_req->max_frmsz = cpu_to_be16(rport->rport_info.max_frmsz);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700843 if (send_req->max_frmsz == 0)
Jing Huangba816ea2010-10-18 17:10:50 -0700844 send_req->max_frmsz = cpu_to_be16(FC_MAX_PDUSZ);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700845 } else {
846 send_req->rport_fw_hndl = 0;
Jing Huangba816ea2010-10-18 17:10:50 -0700847 send_req->max_frmsz = cpu_to_be16(FC_MAX_PDUSZ);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700848 }
849
Jing Huangba816ea2010-10-18 17:10:50 -0700850 send_req->vf_id = cpu_to_be16(reqi->vf_id);
Krishna Gudipati3fd45982011-06-24 20:24:08 -0700851 send_req->lp_fwtag = bfa_lps_get_fwtag(bfa, reqi->lp_tag);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700852 send_req->class = reqi->class;
853 send_req->rsp_timeout = rspi->rsp_timeout;
854 send_req->cts = reqi->cts;
855 send_req->fchs = reqi->fchs;
856
Jing Huangba816ea2010-10-18 17:10:50 -0700857 send_req->req_len = cpu_to_be32(reqi->req_tot_len);
858 send_req->rsp_maxlen = cpu_to_be32(rspi->rsp_maxlen);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700859
860 /*
861 * setup req sgles
862 */
863 if (fcxp->use_ireqbuf == 1) {
Krishna Gudipati85ce9282011-06-13 15:39:36 -0700864 bfa_alen_set(&send_req->req_alen, reqi->req_tot_len,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700865 BFA_FCXP_REQ_PLD_PA(fcxp));
866 } else {
867 if (fcxp->nreq_sgles > 0) {
Jing Huangd4b671c2010-12-26 21:46:35 -0800868 WARN_ON(fcxp->nreq_sgles != 1);
Krishna Gudipati85ce9282011-06-13 15:39:36 -0700869 bfa_alen_set(&send_req->req_alen, reqi->req_tot_len,
870 fcxp->req_sga_cbfn(fcxp->caller, 0));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700871 } else {
Jing Huangd4b671c2010-12-26 21:46:35 -0800872 WARN_ON(reqi->req_tot_len != 0);
Krishna Gudipati85ce9282011-06-13 15:39:36 -0700873 bfa_alen_set(&send_req->rsp_alen, 0, 0);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700874 }
875 }
876
877 /*
878 * setup rsp sgles
879 */
880 if (fcxp->use_irspbuf == 1) {
Jing Huangd4b671c2010-12-26 21:46:35 -0800881 WARN_ON(rspi->rsp_maxlen > BFA_FCXP_MAX_LBUF_SZ);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700882
Krishna Gudipati85ce9282011-06-13 15:39:36 -0700883 bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700884 BFA_FCXP_RSP_PLD_PA(fcxp));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700885 } else {
886 if (fcxp->nrsp_sgles > 0) {
Jing Huangd4b671c2010-12-26 21:46:35 -0800887 WARN_ON(fcxp->nrsp_sgles != 1);
Krishna Gudipati85ce9282011-06-13 15:39:36 -0700888 bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen,
889 fcxp->rsp_sga_cbfn(fcxp->caller, 0));
890
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700891 } else {
Jing Huangd4b671c2010-12-26 21:46:35 -0800892 WARN_ON(rspi->rsp_maxlen != 0);
Krishna Gudipati85ce9282011-06-13 15:39:36 -0700893 bfa_alen_set(&send_req->rsp_alen, 0, 0);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700894 }
895 }
896
897 hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);
898
Krishna Gudipati3fd45982011-06-24 20:24:08 -0700899 bfa_reqq_produce(bfa, BFA_REQQ_FCXP, send_req->mh);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700900
901 bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));
902 bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));
903}
904
Jing Huang5fbe25c2010-10-18 17:17:23 -0700905/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700906 * Allocate an FCXP instance to send a response or to send a request
907 * that has a response. Request/response buffers are allocated by caller.
908 *
909 * @param[in] bfa BFA bfa instance
910 * @param[in] nreq_sgles Number of SG elements required for request
911 * buffer. 0, if fcxp internal buffers are used.
912 * Use bfa_fcxp_get_reqbuf() to get the
913 * internal req buffer.
914 * @param[in] req_sgles SG elements describing request buffer. Will be
915 * copied in by BFA and hence can be freed on
916 * return from this function.
917 * @param[in] get_req_sga function ptr to be called to get a request SG
918 * Address (given the sge index).
919 * @param[in] get_req_sglen function ptr to be called to get a request SG
920 * len (given the sge index).
921 * @param[in] get_rsp_sga function ptr to be called to get a response SG
922 * Address (given the sge index).
923 * @param[in] get_rsp_sglen function ptr to be called to get a response SG
924 * len (given the sge index).
925 *
926 * @return FCXP instance. NULL on failure.
927 */
928struct bfa_fcxp_s *
929bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
930 int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
931 bfa_fcxp_get_sglen_t req_sglen_cbfn,
932 bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
933 bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
934{
935 struct bfa_fcxp_s *fcxp = NULL;
936
Jing Huangd4b671c2010-12-26 21:46:35 -0800937 WARN_ON(bfa == NULL);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700938
939 fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa));
940 if (fcxp == NULL)
941 return NULL;
942
943 bfa_trc(bfa, fcxp->fcxp_tag);
944
945 bfa_fcxp_init(fcxp, caller, bfa, nreq_sgles, nrsp_sgles, req_sga_cbfn,
946 req_sglen_cbfn, rsp_sga_cbfn, rsp_sglen_cbfn);
947
948 return fcxp;
949}
950
Jing Huang5fbe25c2010-10-18 17:17:23 -0700951/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700952 * Get the internal request buffer pointer
953 *
954 * @param[in] fcxp BFA fcxp pointer
955 *
956 * @return pointer to the internal request buffer
957 */
958void *
959bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
960{
961 struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
962 void *reqbuf;
963
Jing Huangd4b671c2010-12-26 21:46:35 -0800964 WARN_ON(fcxp->use_ireqbuf != 1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700965 reqbuf = ((u8 *)mod->req_pld_list_kva) +
966 fcxp->fcxp_tag * mod->req_pld_sz;
967 return reqbuf;
968}
969
970u32
971bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp)
972{
973 struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
974
975 return mod->req_pld_sz;
976}
977
Jing Huang5fbe25c2010-10-18 17:17:23 -0700978/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700979 * Get the internal response buffer pointer
980 *
981 * @param[in] fcxp BFA fcxp pointer
982 *
983 * @return pointer to the internal request buffer
984 */
985void *
986bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
987{
988 struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
989 void *rspbuf;
990
Jing Huangd4b671c2010-12-26 21:46:35 -0800991 WARN_ON(fcxp->use_irspbuf != 1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700992
993 rspbuf = ((u8 *)mod->rsp_pld_list_kva) +
994 fcxp->fcxp_tag * mod->rsp_pld_sz;
995 return rspbuf;
996}
997
Jing Huang5fbe25c2010-10-18 17:17:23 -0700998/*
Maggie Zhangda99dcc2010-12-09 19:13:20 -0800999 * Free the BFA FCXP
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001000 *
1001 * @param[in] fcxp BFA fcxp pointer
1002 *
1003 * @return void
1004 */
1005void
1006bfa_fcxp_free(struct bfa_fcxp_s *fcxp)
1007{
1008 struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
1009
Jing Huangd4b671c2010-12-26 21:46:35 -08001010 WARN_ON(fcxp == NULL);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001011 bfa_trc(mod->bfa, fcxp->fcxp_tag);
1012 bfa_fcxp_put(fcxp);
1013}
1014
Jing Huang5fbe25c2010-10-18 17:17:23 -07001015/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001016 * Send a FCXP request
1017 *
1018 * @param[in] fcxp BFA fcxp pointer
1019 * @param[in] rport BFA rport pointer. Could be left NULL for WKA rports
1020 * @param[in] vf_id virtual Fabric ID
1021 * @param[in] lp_tag lport tag
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001022 * @param[in] cts use Continuous sequence
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001023 * @param[in] cos fc Class of Service
1024 * @param[in] reqlen request length, does not include FCHS length
1025 * @param[in] fchs fc Header Pointer. The header content will be copied
1026 * in by BFA.
1027 *
1028 * @param[in] cbfn call back function to be called on receiving
1029 * the response
1030 * @param[in] cbarg arg for cbfn
1031 * @param[in] rsp_timeout
1032 * response timeout
1033 *
1034 * @return bfa_status_t
1035 */
1036void
1037bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
1038 u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos,
1039 u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn,
1040 void *cbarg, u32 rsp_maxlen, u8 rsp_timeout)
1041{
1042 struct bfa_s *bfa = fcxp->fcxp_mod->bfa;
1043 struct bfa_fcxp_req_info_s *reqi = &fcxp->req_info;
1044 struct bfa_fcxp_rsp_info_s *rspi = &fcxp->rsp_info;
1045 struct bfi_fcxp_send_req_s *send_req;
1046
1047 bfa_trc(bfa, fcxp->fcxp_tag);
1048
Jing Huang5fbe25c2010-10-18 17:17:23 -07001049 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001050 * setup request/response info
1051 */
1052 reqi->bfa_rport = rport;
1053 reqi->vf_id = vf_id;
1054 reqi->lp_tag = lp_tag;
1055 reqi->class = cos;
1056 rspi->rsp_timeout = rsp_timeout;
1057 reqi->cts = cts;
1058 reqi->fchs = *fchs;
1059 reqi->req_tot_len = reqlen;
1060 rspi->rsp_maxlen = rsp_maxlen;
1061 fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp;
1062 fcxp->send_cbarg = cbarg;
1063
Jing Huang5fbe25c2010-10-18 17:17:23 -07001064 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001065 * If no room in CPE queue, wait for space in request queue
1066 */
1067 send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
1068 if (!send_req) {
1069 bfa_trc(bfa, fcxp->fcxp_tag);
1070 fcxp->reqq_waiting = BFA_TRUE;
1071 bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe);
1072 return;
1073 }
1074
1075 bfa_fcxp_queue(fcxp, send_req);
1076}
1077
Jing Huang5fbe25c2010-10-18 17:17:23 -07001078/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001079 * Abort a BFA FCXP
1080 *
1081 * @param[in] fcxp BFA fcxp pointer
1082 *
1083 * @return void
1084 */
1085bfa_status_t
1086bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
1087{
1088 bfa_trc(fcxp->fcxp_mod->bfa, fcxp->fcxp_tag);
Jing Huangd4b671c2010-12-26 21:46:35 -08001089 WARN_ON(1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001090 return BFA_STATUS_OK;
1091}
1092
1093void
1094bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
1095 bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg,
1096 void *caller, int nreq_sgles,
1097 int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
1098 bfa_fcxp_get_sglen_t req_sglen_cbfn,
1099 bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
1100 bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
1101{
1102 struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1103
Jing Huangd4b671c2010-12-26 21:46:35 -08001104 WARN_ON(!list_empty(&mod->fcxp_free_q));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001105
1106 wqe->alloc_cbfn = alloc_cbfn;
1107 wqe->alloc_cbarg = alloc_cbarg;
1108 wqe->caller = caller;
1109 wqe->bfa = bfa;
1110 wqe->nreq_sgles = nreq_sgles;
1111 wqe->nrsp_sgles = nrsp_sgles;
1112 wqe->req_sga_cbfn = req_sga_cbfn;
1113 wqe->req_sglen_cbfn = req_sglen_cbfn;
1114 wqe->rsp_sga_cbfn = rsp_sga_cbfn;
1115 wqe->rsp_sglen_cbfn = rsp_sglen_cbfn;
1116
1117 list_add_tail(&wqe->qe, &mod->wait_q);
1118}
1119
1120void
1121bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
1122{
1123 struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1124
Jing Huangd4b671c2010-12-26 21:46:35 -08001125 WARN_ON(!bfa_q_is_on_q(&mod->wait_q, wqe));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001126 list_del(&wqe->qe);
1127}
1128
1129void
1130bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)
1131{
Jing Huang5fbe25c2010-10-18 17:17:23 -07001132 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001133 * If waiting for room in request queue, cancel reqq wait
1134 * and free fcxp.
1135 */
1136 if (fcxp->reqq_waiting) {
1137 fcxp->reqq_waiting = BFA_FALSE;
1138 bfa_reqq_wcancel(&fcxp->reqq_wqe);
1139 bfa_fcxp_free(fcxp);
1140 return;
1141 }
1142
1143 fcxp->send_cbfn = bfa_fcxp_null_comp;
1144}
1145
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001146void
1147bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
1148{
1149 switch (msg->mhdr.msg_id) {
1150 case BFI_FCXP_I2H_SEND_RSP:
1151 hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg);
1152 break;
1153
1154 default:
1155 bfa_trc(bfa, msg->mhdr.msg_id);
Jing Huangd4b671c2010-12-26 21:46:35 -08001156 WARN_ON(1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001157 }
1158}
1159
1160u32
1161bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
1162{
1163 struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1164
1165 return mod->rsp_pld_sz;
1166}
1167
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001168void
1169bfa_fcxp_res_recfg(struct bfa_s *bfa, u16 num_fcxp_fw)
1170{
1171 struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1172 struct list_head *qe;
1173 int i;
1174
1175 for (i = 0; i < (mod->num_fcxps - num_fcxp_fw); i++) {
1176 bfa_q_deq_tail(&mod->fcxp_free_q, &qe);
1177 list_add_tail(qe, &mod->fcxp_unused_q);
1178 }
1179}
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001180
Jing Huang5fbe25c2010-10-18 17:17:23 -07001181/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001182 * BFA LPS state machine functions
1183 */
1184
Jing Huang5fbe25c2010-10-18 17:17:23 -07001185/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001186 * Init state -- no login
1187 */
1188static void
1189bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
1190{
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001191 bfa_trc(lps->bfa, lps->bfa_tag);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001192 bfa_trc(lps->bfa, event);
1193
1194 switch (event) {
1195 case BFA_LPS_SM_LOGIN:
1196 if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1197 bfa_sm_set_state(lps, bfa_lps_sm_loginwait);
1198 bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1199 } else {
1200 bfa_sm_set_state(lps, bfa_lps_sm_login);
1201 bfa_lps_send_login(lps);
1202 }
1203
1204 if (lps->fdisc)
1205 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1206 BFA_PL_EID_LOGIN, 0, "FDISC Request");
1207 else
1208 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1209 BFA_PL_EID_LOGIN, 0, "FLOGI Request");
1210 break;
1211
1212 case BFA_LPS_SM_LOGOUT:
1213 bfa_lps_logout_comp(lps);
1214 break;
1215
1216 case BFA_LPS_SM_DELETE:
1217 bfa_lps_free(lps);
1218 break;
1219
1220 case BFA_LPS_SM_RX_CVL:
1221 case BFA_LPS_SM_OFFLINE:
1222 break;
1223
1224 case BFA_LPS_SM_FWRSP:
1225 /*
1226 * Could happen when fabric detects loopback and discards
1227 * the lps request. Fw will eventually sent out the timeout
1228 * Just ignore
1229 */
1230 break;
1231
1232 default:
1233 bfa_sm_fault(lps->bfa, event);
1234 }
1235}
1236
Jing Huang5fbe25c2010-10-18 17:17:23 -07001237/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001238 * login is in progress -- awaiting response from firmware
1239 */
1240static void
1241bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
1242{
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001243 bfa_trc(lps->bfa, lps->bfa_tag);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001244 bfa_trc(lps->bfa, event);
1245
1246 switch (event) {
1247 case BFA_LPS_SM_FWRSP:
1248 if (lps->status == BFA_STATUS_OK) {
1249 bfa_sm_set_state(lps, bfa_lps_sm_online);
1250 if (lps->fdisc)
1251 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1252 BFA_PL_EID_LOGIN, 0, "FDISC Accept");
1253 else
1254 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1255 BFA_PL_EID_LOGIN, 0, "FLOGI Accept");
Krishna Gudipatib7044952010-12-13 16:17:42 -08001256 /* If N2N, send the assigned PID to FW */
1257 bfa_trc(lps->bfa, lps->fport);
1258 bfa_trc(lps->bfa, lps->lp_pid);
1259
1260 if (!lps->fport && lps->lp_pid)
1261 bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001262 } else {
1263 bfa_sm_set_state(lps, bfa_lps_sm_init);
1264 if (lps->fdisc)
1265 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1266 BFA_PL_EID_LOGIN, 0,
1267 "FDISC Fail (RJT or timeout)");
1268 else
1269 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1270 BFA_PL_EID_LOGIN, 0,
1271 "FLOGI Fail (RJT or timeout)");
1272 }
1273 bfa_lps_login_comp(lps);
1274 break;
1275
1276 case BFA_LPS_SM_OFFLINE:
Krishna Gudipatibe540a92011-06-13 15:53:04 -07001277 case BFA_LPS_SM_DELETE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001278 bfa_sm_set_state(lps, bfa_lps_sm_init);
1279 break;
1280
Krishna Gudipatib7044952010-12-13 16:17:42 -08001281 case BFA_LPS_SM_SET_N2N_PID:
1282 bfa_trc(lps->bfa, lps->fport);
1283 bfa_trc(lps->bfa, lps->lp_pid);
1284 break;
1285
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001286 default:
1287 bfa_sm_fault(lps->bfa, event);
1288 }
1289}
1290
Jing Huang5fbe25c2010-10-18 17:17:23 -07001291/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001292 * login pending - awaiting space in request queue
1293 */
1294static void
1295bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1296{
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001297 bfa_trc(lps->bfa, lps->bfa_tag);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001298 bfa_trc(lps->bfa, event);
1299
1300 switch (event) {
1301 case BFA_LPS_SM_RESUME:
1302 bfa_sm_set_state(lps, bfa_lps_sm_login);
1303 break;
1304
1305 case BFA_LPS_SM_OFFLINE:
Krishna Gudipatibe540a92011-06-13 15:53:04 -07001306 case BFA_LPS_SM_DELETE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001307 bfa_sm_set_state(lps, bfa_lps_sm_init);
1308 bfa_reqq_wcancel(&lps->wqe);
1309 break;
1310
1311 case BFA_LPS_SM_RX_CVL:
1312 /*
1313 * Login was not even sent out; so when getting out
1314 * of this state, it will appear like a login retry
1315 * after Clear virtual link
1316 */
1317 break;
1318
1319 default:
1320 bfa_sm_fault(lps->bfa, event);
1321 }
1322}
1323
Jing Huang5fbe25c2010-10-18 17:17:23 -07001324/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001325 * login complete
1326 */
1327static void
1328bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
1329{
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001330 bfa_trc(lps->bfa, lps->bfa_tag);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001331 bfa_trc(lps->bfa, event);
1332
1333 switch (event) {
1334 case BFA_LPS_SM_LOGOUT:
1335 if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1336 bfa_sm_set_state(lps, bfa_lps_sm_logowait);
1337 bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1338 } else {
1339 bfa_sm_set_state(lps, bfa_lps_sm_logout);
1340 bfa_lps_send_logout(lps);
1341 }
1342 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1343 BFA_PL_EID_LOGO, 0, "Logout");
1344 break;
1345
1346 case BFA_LPS_SM_RX_CVL:
1347 bfa_sm_set_state(lps, bfa_lps_sm_init);
1348
1349 /* Let the vport module know about this event */
1350 bfa_lps_cvl_event(lps);
1351 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1352 BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
1353 break;
1354
Krishna Gudipatib7044952010-12-13 16:17:42 -08001355 case BFA_LPS_SM_SET_N2N_PID:
1356 if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1357 bfa_sm_set_state(lps, bfa_lps_sm_online_n2n_pid_wait);
1358 bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1359 } else
1360 bfa_lps_send_set_n2n_pid(lps);
1361 break;
1362
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001363 case BFA_LPS_SM_OFFLINE:
1364 case BFA_LPS_SM_DELETE:
1365 bfa_sm_set_state(lps, bfa_lps_sm_init);
1366 break;
1367
1368 default:
1369 bfa_sm_fault(lps->bfa, event);
1370 }
1371}
1372
Jing Huang8f4bfad2010-12-26 21:50:10 -08001373/*
Krishna Gudipatib7044952010-12-13 16:17:42 -08001374 * login complete
1375 */
1376static void
1377bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1378{
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001379 bfa_trc(lps->bfa, lps->bfa_tag);
Krishna Gudipatib7044952010-12-13 16:17:42 -08001380 bfa_trc(lps->bfa, event);
1381
1382 switch (event) {
1383 case BFA_LPS_SM_RESUME:
1384 bfa_sm_set_state(lps, bfa_lps_sm_online);
1385 bfa_lps_send_set_n2n_pid(lps);
1386 break;
1387
1388 case BFA_LPS_SM_LOGOUT:
1389 bfa_sm_set_state(lps, bfa_lps_sm_logowait);
1390 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1391 BFA_PL_EID_LOGO, 0, "Logout");
1392 break;
1393
1394 case BFA_LPS_SM_RX_CVL:
1395 bfa_sm_set_state(lps, bfa_lps_sm_init);
1396 bfa_reqq_wcancel(&lps->wqe);
1397
1398 /* Let the vport module know about this event */
1399 bfa_lps_cvl_event(lps);
1400 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1401 BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
1402 break;
1403
1404 case BFA_LPS_SM_OFFLINE:
1405 case BFA_LPS_SM_DELETE:
1406 bfa_sm_set_state(lps, bfa_lps_sm_init);
1407 bfa_reqq_wcancel(&lps->wqe);
1408 break;
1409
1410 default:
1411 bfa_sm_fault(lps->bfa, event);
1412 }
1413}
1414
Jing Huang5fbe25c2010-10-18 17:17:23 -07001415/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001416 * logout in progress - awaiting firmware response
1417 */
1418static void
1419bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
1420{
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001421 bfa_trc(lps->bfa, lps->bfa_tag);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001422 bfa_trc(lps->bfa, event);
1423
1424 switch (event) {
1425 case BFA_LPS_SM_FWRSP:
1426 bfa_sm_set_state(lps, bfa_lps_sm_init);
1427 bfa_lps_logout_comp(lps);
1428 break;
1429
1430 case BFA_LPS_SM_OFFLINE:
Krishna Gudipatibe540a92011-06-13 15:53:04 -07001431 case BFA_LPS_SM_DELETE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001432 bfa_sm_set_state(lps, bfa_lps_sm_init);
1433 break;
1434
1435 default:
1436 bfa_sm_fault(lps->bfa, event);
1437 }
1438}
1439
Jing Huang5fbe25c2010-10-18 17:17:23 -07001440/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001441 * logout pending -- awaiting space in request queue
1442 */
1443static void
1444bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1445{
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001446 bfa_trc(lps->bfa, lps->bfa_tag);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001447 bfa_trc(lps->bfa, event);
1448
1449 switch (event) {
1450 case BFA_LPS_SM_RESUME:
1451 bfa_sm_set_state(lps, bfa_lps_sm_logout);
1452 bfa_lps_send_logout(lps);
1453 break;
1454
1455 case BFA_LPS_SM_OFFLINE:
Krishna Gudipatibe540a92011-06-13 15:53:04 -07001456 case BFA_LPS_SM_DELETE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001457 bfa_sm_set_state(lps, bfa_lps_sm_init);
1458 bfa_reqq_wcancel(&lps->wqe);
1459 break;
1460
1461 default:
1462 bfa_sm_fault(lps->bfa, event);
1463 }
1464}
1465
1466
1467
Jing Huang5fbe25c2010-10-18 17:17:23 -07001468/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001469 * lps_pvt BFA LPS private functions
1470 */
1471
Jing Huang5fbe25c2010-10-18 17:17:23 -07001472/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001473 * return memory requirement
1474 */
1475static void
1476bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
1477 u32 *dm_len)
1478{
1479 if (cfg->drvcfg.min_cfg)
1480 *ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS;
1481 else
1482 *ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS;
1483}
1484
Jing Huang5fbe25c2010-10-18 17:17:23 -07001485/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001486 * bfa module attach at initialization time
1487 */
1488static void
1489bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
1490 struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
1491{
1492 struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
1493 struct bfa_lps_s *lps;
1494 int i;
1495
Jing Huang6a18b162010-10-18 17:08:54 -07001496 memset(mod, 0, sizeof(struct bfa_lps_mod_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001497 mod->num_lps = BFA_LPS_MAX_LPORTS;
1498 if (cfg->drvcfg.min_cfg)
1499 mod->num_lps = BFA_LPS_MIN_LPORTS;
1500 else
1501 mod->num_lps = BFA_LPS_MAX_LPORTS;
1502 mod->lps_arr = lps = (struct bfa_lps_s *) bfa_meminfo_kva(meminfo);
1503
1504 bfa_meminfo_kva(meminfo) += mod->num_lps * sizeof(struct bfa_lps_s);
1505
1506 INIT_LIST_HEAD(&mod->lps_free_q);
1507 INIT_LIST_HEAD(&mod->lps_active_q);
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001508 INIT_LIST_HEAD(&mod->lps_login_q);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001509
1510 for (i = 0; i < mod->num_lps; i++, lps++) {
1511 lps->bfa = bfa;
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001512 lps->bfa_tag = (u8) i;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001513 lps->reqq = BFA_REQQ_LPS;
1514 bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);
1515 list_add_tail(&lps->qe, &mod->lps_free_q);
1516 }
1517}
1518
1519static void
1520bfa_lps_detach(struct bfa_s *bfa)
1521{
1522}
1523
1524static void
1525bfa_lps_start(struct bfa_s *bfa)
1526{
1527}
1528
1529static void
1530bfa_lps_stop(struct bfa_s *bfa)
1531{
1532}
1533
Jing Huang5fbe25c2010-10-18 17:17:23 -07001534/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001535 * IOC in disabled state -- consider all lps offline
1536 */
1537static void
1538bfa_lps_iocdisable(struct bfa_s *bfa)
1539{
1540 struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
1541 struct bfa_lps_s *lps;
1542 struct list_head *qe, *qen;
1543
1544 list_for_each_safe(qe, qen, &mod->lps_active_q) {
1545 lps = (struct bfa_lps_s *) qe;
1546 bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
1547 }
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001548 list_for_each_safe(qe, qen, &mod->lps_login_q) {
1549 lps = (struct bfa_lps_s *) qe;
1550 bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
1551 }
1552 list_splice_tail_init(&mod->lps_login_q, &mod->lps_active_q);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001553}
1554
Jing Huang5fbe25c2010-10-18 17:17:23 -07001555/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001556 * Firmware login response
1557 */
1558static void
1559bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
1560{
1561 struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
1562 struct bfa_lps_s *lps;
1563
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001564 WARN_ON(rsp->bfa_tag >= mod->num_lps);
1565 lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001566
1567 lps->status = rsp->status;
1568 switch (rsp->status) {
1569 case BFA_STATUS_OK:
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001570 lps->fw_tag = rsp->fw_tag;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001571 lps->fport = rsp->f_port;
Krishna Gudipatib7044952010-12-13 16:17:42 -08001572 if (lps->fport)
1573 lps->lp_pid = rsp->lp_pid;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001574 lps->npiv_en = rsp->npiv_en;
Jing Huangba816ea2010-10-18 17:10:50 -07001575 lps->pr_bbcred = be16_to_cpu(rsp->bb_credit);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001576 lps->pr_pwwn = rsp->port_name;
1577 lps->pr_nwwn = rsp->node_name;
1578 lps->auth_req = rsp->auth_req;
1579 lps->lp_mac = rsp->lp_mac;
1580 lps->brcd_switch = rsp->brcd_switch;
1581 lps->fcf_mac = rsp->fcf_mac;
Krishna Gudipatibe540a92011-06-13 15:53:04 -07001582 lps->pr_bbscn = rsp->bb_scn;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001583
1584 break;
1585
1586 case BFA_STATUS_FABRIC_RJT:
1587 lps->lsrjt_rsn = rsp->lsrjt_rsn;
1588 lps->lsrjt_expl = rsp->lsrjt_expl;
1589
1590 break;
1591
1592 case BFA_STATUS_EPROTOCOL:
1593 lps->ext_status = rsp->ext_status;
1594
1595 break;
1596
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001597 case BFA_STATUS_VPORT_MAX:
1598 if (!rsp->ext_status)
1599 bfa_lps_no_res(lps, rsp->ext_status);
1600 break;
1601
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001602 default:
1603 /* Nothing to do with other status */
1604 break;
1605 }
1606
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001607 list_del(&lps->qe);
1608 list_add_tail(&lps->qe, &mod->lps_active_q);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001609 bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1610}
1611
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001612static void
1613bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count)
1614{
1615 struct bfa_s *bfa = first_lps->bfa;
1616 struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
1617 struct list_head *qe, *qe_next;
1618 struct bfa_lps_s *lps;
1619
1620 bfa_trc(bfa, count);
1621
1622 qe = bfa_q_next(first_lps);
1623
1624 while (count && qe) {
1625 qe_next = bfa_q_next(qe);
1626 lps = (struct bfa_lps_s *)qe;
1627 bfa_trc(bfa, lps->bfa_tag);
1628 lps->status = first_lps->status;
1629 list_del(&lps->qe);
1630 list_add_tail(&lps->qe, &mod->lps_active_q);
1631 bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1632 qe = qe_next;
1633 count--;
1634 }
1635}
1636
Jing Huang5fbe25c2010-10-18 17:17:23 -07001637/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001638 * Firmware logout response
1639 */
1640static void
1641bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
1642{
1643 struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
1644 struct bfa_lps_s *lps;
1645
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001646 WARN_ON(rsp->bfa_tag >= mod->num_lps);
1647 lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001648
1649 bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1650}
1651
Jing Huang5fbe25c2010-10-18 17:17:23 -07001652/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001653 * Firmware received a Clear virtual link request (for FCoE)
1654 */
1655static void
1656bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)
1657{
1658 struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
1659 struct bfa_lps_s *lps;
1660
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001661 lps = BFA_LPS_FROM_TAG(mod, cvl->bfa_tag);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001662
1663 bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);
1664}
1665
Jing Huang5fbe25c2010-10-18 17:17:23 -07001666/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001667 * Space is available in request queue, resume queueing request to firmware.
1668 */
1669static void
1670bfa_lps_reqq_resume(void *lps_arg)
1671{
1672 struct bfa_lps_s *lps = lps_arg;
1673
1674 bfa_sm_send_event(lps, BFA_LPS_SM_RESUME);
1675}
1676
Jing Huang5fbe25c2010-10-18 17:17:23 -07001677/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001678 * lps is freed -- triggered by vport delete
1679 */
1680static void
1681bfa_lps_free(struct bfa_lps_s *lps)
1682{
1683 struct bfa_lps_mod_s *mod = BFA_LPS_MOD(lps->bfa);
1684
1685 lps->lp_pid = 0;
1686 list_del(&lps->qe);
1687 list_add_tail(&lps->qe, &mod->lps_free_q);
1688}
1689
Jing Huang5fbe25c2010-10-18 17:17:23 -07001690/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001691 * send login request to firmware
1692 */
1693static void
1694bfa_lps_send_login(struct bfa_lps_s *lps)
1695{
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001696 struct bfa_lps_mod_s *mod = BFA_LPS_MOD(lps->bfa);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001697 struct bfi_lps_login_req_s *m;
1698
1699 m = bfa_reqq_next(lps->bfa, lps->reqq);
Jing Huangd4b671c2010-12-26 21:46:35 -08001700 WARN_ON(!m);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001701
1702 bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001703 bfa_fn_lpu(lps->bfa));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001704
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001705 m->bfa_tag = lps->bfa_tag;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001706 m->alpa = lps->alpa;
Jing Huangba816ea2010-10-18 17:10:50 -07001707 m->pdu_size = cpu_to_be16(lps->pdusz);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001708 m->pwwn = lps->pwwn;
1709 m->nwwn = lps->nwwn;
1710 m->fdisc = lps->fdisc;
1711 m->auth_en = lps->auth_en;
Krishna Gudipatibe540a92011-06-13 15:53:04 -07001712 m->bb_scn = lps->bb_scn;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001713
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001714 bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
1715 list_del(&lps->qe);
1716 list_add_tail(&lps->qe, &mod->lps_login_q);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001717}
1718
Jing Huang5fbe25c2010-10-18 17:17:23 -07001719/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001720 * send logout request to firmware
1721 */
1722static void
1723bfa_lps_send_logout(struct bfa_lps_s *lps)
1724{
1725 struct bfi_lps_logout_req_s *m;
1726
1727 m = bfa_reqq_next(lps->bfa, lps->reqq);
Jing Huangd4b671c2010-12-26 21:46:35 -08001728 WARN_ON(!m);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001729
1730 bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001731 bfa_fn_lpu(lps->bfa));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001732
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001733 m->fw_tag = lps->fw_tag;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001734 m->port_name = lps->pwwn;
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001735 bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001736}
1737
Jing Huang8f4bfad2010-12-26 21:50:10 -08001738/*
Krishna Gudipatib7044952010-12-13 16:17:42 -08001739 * send n2n pid set request to firmware
1740 */
1741static void
1742bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps)
1743{
1744 struct bfi_lps_n2n_pid_req_s *m;
1745
1746 m = bfa_reqq_next(lps->bfa, lps->reqq);
Jing Huangd4b671c2010-12-26 21:46:35 -08001747 WARN_ON(!m);
Krishna Gudipatib7044952010-12-13 16:17:42 -08001748
1749 bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_N2N_PID_REQ,
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001750 bfa_fn_lpu(lps->bfa));
Krishna Gudipatib7044952010-12-13 16:17:42 -08001751
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001752 m->fw_tag = lps->fw_tag;
Krishna Gudipatib7044952010-12-13 16:17:42 -08001753 m->lp_pid = lps->lp_pid;
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001754 bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
Krishna Gudipatib7044952010-12-13 16:17:42 -08001755}
1756
Jing Huang5fbe25c2010-10-18 17:17:23 -07001757/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001758 * Indirect login completion handler for non-fcs
1759 */
1760static void
1761bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete)
1762{
1763 struct bfa_lps_s *lps = arg;
1764
1765 if (!complete)
1766 return;
1767
1768 if (lps->fdisc)
1769 bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
1770 else
1771 bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
1772}
1773
Jing Huang5fbe25c2010-10-18 17:17:23 -07001774/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001775 * Login completion handler -- direct call for fcs, queue for others
1776 */
1777static void
1778bfa_lps_login_comp(struct bfa_lps_s *lps)
1779{
1780 if (!lps->bfa->fcs) {
1781 bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_login_comp_cb,
1782 lps);
1783 return;
1784 }
1785
1786 if (lps->fdisc)
1787 bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
1788 else
1789 bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
1790}
1791
Jing Huang5fbe25c2010-10-18 17:17:23 -07001792/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001793 * Indirect logout completion handler for non-fcs
1794 */
1795static void
1796bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)
1797{
1798 struct bfa_lps_s *lps = arg;
1799
1800 if (!complete)
1801 return;
1802
1803 if (lps->fdisc)
1804 bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
1805}
1806
Jing Huang5fbe25c2010-10-18 17:17:23 -07001807/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001808 * Logout completion handler -- direct call for fcs, queue for others
1809 */
1810static void
1811bfa_lps_logout_comp(struct bfa_lps_s *lps)
1812{
1813 if (!lps->bfa->fcs) {
1814 bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_logout_comp_cb,
1815 lps);
1816 return;
1817 }
1818 if (lps->fdisc)
1819 bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
1820}
1821
Jing Huang5fbe25c2010-10-18 17:17:23 -07001822/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001823 * Clear virtual link completion handler for non-fcs
1824 */
1825static void
1826bfa_lps_cvl_event_cb(void *arg, bfa_boolean_t complete)
1827{
1828 struct bfa_lps_s *lps = arg;
1829
1830 if (!complete)
1831 return;
1832
1833 /* Clear virtual link to base port will result in link down */
1834 if (lps->fdisc)
1835 bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
1836}
1837
Jing Huang5fbe25c2010-10-18 17:17:23 -07001838/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001839 * Received Clear virtual link event --direct call for fcs,
1840 * queue for others
1841 */
1842static void
1843bfa_lps_cvl_event(struct bfa_lps_s *lps)
1844{
1845 if (!lps->bfa->fcs) {
1846 bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_cvl_event_cb,
1847 lps);
1848 return;
1849 }
1850
1851 /* Clear virtual link to base port will result in link down */
1852 if (lps->fdisc)
1853 bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
1854}
1855
1856
1857
Jing Huang5fbe25c2010-10-18 17:17:23 -07001858/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001859 * lps_public BFA LPS public functions
1860 */
1861
1862u32
1863bfa_lps_get_max_vport(struct bfa_s *bfa)
1864{
1865 if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT)
1866 return BFA_LPS_MAX_VPORTS_SUPP_CT;
1867 else
1868 return BFA_LPS_MAX_VPORTS_SUPP_CB;
1869}
1870
Jing Huang5fbe25c2010-10-18 17:17:23 -07001871/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001872 * Allocate a lport srvice tag.
1873 */
1874struct bfa_lps_s *
1875bfa_lps_alloc(struct bfa_s *bfa)
1876{
1877 struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
1878 struct bfa_lps_s *lps = NULL;
1879
1880 bfa_q_deq(&mod->lps_free_q, &lps);
1881
1882 if (lps == NULL)
1883 return NULL;
1884
1885 list_add_tail(&lps->qe, &mod->lps_active_q);
1886
1887 bfa_sm_set_state(lps, bfa_lps_sm_init);
1888 return lps;
1889}
1890
Jing Huang5fbe25c2010-10-18 17:17:23 -07001891/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001892 * Free lport service tag. This can be called anytime after an alloc.
1893 * No need to wait for any pending login/logout completions.
1894 */
1895void
1896bfa_lps_delete(struct bfa_lps_s *lps)
1897{
1898 bfa_sm_send_event(lps, BFA_LPS_SM_DELETE);
1899}
1900
Jing Huang5fbe25c2010-10-18 17:17:23 -07001901/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001902 * Initiate a lport login.
1903 */
1904void
1905bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
Krishna Gudipatibe540a92011-06-13 15:53:04 -07001906 wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en, uint8_t bb_scn)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001907{
1908 lps->uarg = uarg;
1909 lps->alpa = alpa;
1910 lps->pdusz = pdusz;
1911 lps->pwwn = pwwn;
1912 lps->nwwn = nwwn;
1913 lps->fdisc = BFA_FALSE;
1914 lps->auth_en = auth_en;
Krishna Gudipatibe540a92011-06-13 15:53:04 -07001915 lps->bb_scn = bb_scn;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001916 bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
1917}
1918
Jing Huang5fbe25c2010-10-18 17:17:23 -07001919/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001920 * Initiate a lport fdisc login.
1921 */
1922void
1923bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
1924 wwn_t nwwn)
1925{
1926 lps->uarg = uarg;
1927 lps->alpa = 0;
1928 lps->pdusz = pdusz;
1929 lps->pwwn = pwwn;
1930 lps->nwwn = nwwn;
1931 lps->fdisc = BFA_TRUE;
1932 lps->auth_en = BFA_FALSE;
1933 bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
1934}
1935
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001936
Jing Huang5fbe25c2010-10-18 17:17:23 -07001937/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001938 * Initiate a lport FDSIC logout.
1939 */
1940void
1941bfa_lps_fdisclogo(struct bfa_lps_s *lps)
1942{
1943 bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
1944}
1945
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001946u8
1947bfa_lps_get_fwtag(struct bfa_s *bfa, u8 lp_tag)
1948{
1949 struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
1950
1951 return BFA_LPS_FROM_TAG(mod, lp_tag)->fw_tag;
1952}
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001953
Jing Huang5fbe25c2010-10-18 17:17:23 -07001954/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001955 * Return lport services tag given the pid
1956 */
1957u8
1958bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
1959{
1960 struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
1961 struct bfa_lps_s *lps;
1962 int i;
1963
1964 for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
1965 if (lps->lp_pid == pid)
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001966 return lps->bfa_tag;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001967 }
1968
1969 /* Return base port tag anyway */
1970 return 0;
1971}
1972
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001973
Jing Huang5fbe25c2010-10-18 17:17:23 -07001974/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001975 * return port id assigned to the base lport
1976 */
1977u32
1978bfa_lps_get_base_pid(struct bfa_s *bfa)
1979{
1980 struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
1981
1982 return BFA_LPS_FROM_TAG(mod, 0)->lp_pid;
1983}
1984
Jing Huang8f4bfad2010-12-26 21:50:10 -08001985/*
Krishna Gudipatib7044952010-12-13 16:17:42 -08001986 * Set PID in case of n2n (which is assigned during PLOGI)
1987 */
1988void
1989bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, uint32_t n2n_pid)
1990{
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001991 bfa_trc(lps->bfa, lps->bfa_tag);
Krishna Gudipatib7044952010-12-13 16:17:42 -08001992 bfa_trc(lps->bfa, n2n_pid);
1993
1994 lps->lp_pid = n2n_pid;
1995 bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
1996}
1997
Jing Huang5fbe25c2010-10-18 17:17:23 -07001998/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001999 * LPS firmware message class handler.
2000 */
2001void
2002bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
2003{
2004 union bfi_lps_i2h_msg_u msg;
2005
2006 bfa_trc(bfa, m->mhdr.msg_id);
2007 msg.msg = m;
2008
2009 switch (m->mhdr.msg_id) {
Krishna Gudipati43ffdf42011-06-13 15:46:21 -07002010 case BFI_LPS_I2H_LOGIN_RSP:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002011 bfa_lps_login_rsp(bfa, msg.login_rsp);
2012 break;
2013
Krishna Gudipati43ffdf42011-06-13 15:46:21 -07002014 case BFI_LPS_I2H_LOGOUT_RSP:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002015 bfa_lps_logout_rsp(bfa, msg.logout_rsp);
2016 break;
2017
Krishna Gudipati43ffdf42011-06-13 15:46:21 -07002018 case BFI_LPS_I2H_CVL_EVENT:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002019 bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
2020 break;
2021
2022 default:
2023 bfa_trc(bfa, m->mhdr.msg_id);
Jing Huangd4b671c2010-12-26 21:46:35 -08002024 WARN_ON(1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002025 }
2026}
2027
Jing Huang5fbe25c2010-10-18 17:17:23 -07002028/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002029 * FC PORT state machine functions
2030 */
2031static void
2032bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
2033 enum bfa_fcport_sm_event event)
2034{
2035 bfa_trc(fcport->bfa, event);
2036
2037 switch (event) {
2038 case BFA_FCPORT_SM_START:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002039 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002040 * Start event after IOC is configured and BFA is started.
2041 */
Krishna Gudipatif3a060c2010-12-13 16:16:50 -08002042 fcport->use_flash_cfg = BFA_TRUE;
2043
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002044 if (bfa_fcport_send_enable(fcport)) {
2045 bfa_trc(fcport->bfa, BFA_TRUE);
2046 bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2047 } else {
2048 bfa_trc(fcport->bfa, BFA_FALSE);
2049 bfa_sm_set_state(fcport,
2050 bfa_fcport_sm_enabling_qwait);
2051 }
2052 break;
2053
2054 case BFA_FCPORT_SM_ENABLE:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002055 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002056 * Port is persistently configured to be in enabled state. Do
2057 * not change state. Port enabling is done when START event is
2058 * received.
2059 */
2060 break;
2061
2062 case BFA_FCPORT_SM_DISABLE:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002063 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002064 * If a port is persistently configured to be disabled, the
2065 * first event will a port disable request.
2066 */
2067 bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2068 break;
2069
2070 case BFA_FCPORT_SM_HWFAIL:
2071 bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2072 break;
2073
2074 default:
2075 bfa_sm_fault(fcport->bfa, event);
2076 }
2077}
2078
2079static void
2080bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
2081 enum bfa_fcport_sm_event event)
2082{
2083 char pwwn_buf[BFA_STRING_32];
2084 struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2085 bfa_trc(fcport->bfa, event);
2086
2087 switch (event) {
2088 case BFA_FCPORT_SM_QRESUME:
2089 bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2090 bfa_fcport_send_enable(fcport);
2091 break;
2092
2093 case BFA_FCPORT_SM_STOP:
2094 bfa_reqq_wcancel(&fcport->reqq_wait);
2095 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2096 break;
2097
2098 case BFA_FCPORT_SM_ENABLE:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002099 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002100 * Already enable is in progress.
2101 */
2102 break;
2103
2104 case BFA_FCPORT_SM_DISABLE:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002105 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002106 * Just send disable request to firmware when room becomes
2107 * available in request queue.
2108 */
2109 bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2110 bfa_reqq_wcancel(&fcport->reqq_wait);
2111 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2112 BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2113 wwn2str(pwwn_buf, fcport->pwwn);
Jing Huang88166242010-12-09 17:11:53 -08002114 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002115 "Base port disabled: WWN = %s\n", pwwn_buf);
2116 break;
2117
2118 case BFA_FCPORT_SM_LINKUP:
2119 case BFA_FCPORT_SM_LINKDOWN:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002120 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002121 * Possible to get link events when doing back-to-back
2122 * enable/disables.
2123 */
2124 break;
2125
2126 case BFA_FCPORT_SM_HWFAIL:
2127 bfa_reqq_wcancel(&fcport->reqq_wait);
2128 bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2129 break;
2130
2131 default:
2132 bfa_sm_fault(fcport->bfa, event);
2133 }
2134}
2135
2136static void
2137bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
2138 enum bfa_fcport_sm_event event)
2139{
2140 char pwwn_buf[BFA_STRING_32];
2141 struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2142 bfa_trc(fcport->bfa, event);
2143
2144 switch (event) {
2145 case BFA_FCPORT_SM_FWRSP:
2146 case BFA_FCPORT_SM_LINKDOWN:
2147 bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
2148 break;
2149
2150 case BFA_FCPORT_SM_LINKUP:
2151 bfa_fcport_update_linkinfo(fcport);
2152 bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
2153
Jing Huangd4b671c2010-12-26 21:46:35 -08002154 WARN_ON(!fcport->event_cbfn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002155 bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
2156 break;
2157
2158 case BFA_FCPORT_SM_ENABLE:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002159 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002160 * Already being enabled.
2161 */
2162 break;
2163
2164 case BFA_FCPORT_SM_DISABLE:
2165 if (bfa_fcport_send_disable(fcport))
2166 bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2167 else
2168 bfa_sm_set_state(fcport,
2169 bfa_fcport_sm_disabling_qwait);
2170
2171 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2172 BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2173 wwn2str(pwwn_buf, fcport->pwwn);
Jing Huang88166242010-12-09 17:11:53 -08002174 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002175 "Base port disabled: WWN = %s\n", pwwn_buf);
2176 break;
2177
2178 case BFA_FCPORT_SM_STOP:
2179 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2180 break;
2181
2182 case BFA_FCPORT_SM_HWFAIL:
2183 bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2184 break;
2185
2186 default:
2187 bfa_sm_fault(fcport->bfa, event);
2188 }
2189}
2190
2191static void
2192bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
2193 enum bfa_fcport_sm_event event)
2194{
2195 struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
2196 char pwwn_buf[BFA_STRING_32];
2197 struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2198
2199 bfa_trc(fcport->bfa, event);
2200
2201 switch (event) {
2202 case BFA_FCPORT_SM_LINKUP:
2203 bfa_fcport_update_linkinfo(fcport);
2204 bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
Jing Huangd4b671c2010-12-26 21:46:35 -08002205 WARN_ON(!fcport->event_cbfn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002206 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2207 BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");
2208 if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
2209
2210 bfa_trc(fcport->bfa,
2211 pevent->link_state.vc_fcf.fcf.fipenabled);
2212 bfa_trc(fcport->bfa,
2213 pevent->link_state.vc_fcf.fcf.fipfailed);
2214
2215 if (pevent->link_state.vc_fcf.fcf.fipfailed)
2216 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2217 BFA_PL_EID_FIP_FCF_DISC, 0,
2218 "FIP FCF Discovery Failed");
2219 else
2220 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2221 BFA_PL_EID_FIP_FCF_DISC, 0,
2222 "FIP FCF Discovered");
2223 }
2224
2225 bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
2226 wwn2str(pwwn_buf, fcport->pwwn);
Jing Huang88166242010-12-09 17:11:53 -08002227 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002228 "Base port online: WWN = %s\n", pwwn_buf);
2229 break;
2230
2231 case BFA_FCPORT_SM_LINKDOWN:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002232 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002233 * Possible to get link down event.
2234 */
2235 break;
2236
2237 case BFA_FCPORT_SM_ENABLE:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002238 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002239 * Already enabled.
2240 */
2241 break;
2242
2243 case BFA_FCPORT_SM_DISABLE:
2244 if (bfa_fcport_send_disable(fcport))
2245 bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2246 else
2247 bfa_sm_set_state(fcport,
2248 bfa_fcport_sm_disabling_qwait);
2249
2250 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2251 BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2252 wwn2str(pwwn_buf, fcport->pwwn);
Jing Huang88166242010-12-09 17:11:53 -08002253 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002254 "Base port disabled: WWN = %s\n", pwwn_buf);
2255 break;
2256
2257 case BFA_FCPORT_SM_STOP:
2258 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2259 break;
2260
2261 case BFA_FCPORT_SM_HWFAIL:
2262 bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2263 break;
2264
2265 default:
2266 bfa_sm_fault(fcport->bfa, event);
2267 }
2268}
2269
2270static void
2271bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
2272 enum bfa_fcport_sm_event event)
2273{
2274 char pwwn_buf[BFA_STRING_32];
2275 struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2276
2277 bfa_trc(fcport->bfa, event);
2278
2279 switch (event) {
2280 case BFA_FCPORT_SM_ENABLE:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002281 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002282 * Already enabled.
2283 */
2284 break;
2285
2286 case BFA_FCPORT_SM_DISABLE:
2287 if (bfa_fcport_send_disable(fcport))
2288 bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2289 else
2290 bfa_sm_set_state(fcport,
2291 bfa_fcport_sm_disabling_qwait);
2292
2293 bfa_fcport_reset_linkinfo(fcport);
2294 bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2295 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2296 BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2297 wwn2str(pwwn_buf, fcport->pwwn);
Jing Huang88166242010-12-09 17:11:53 -08002298 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002299 "Base port offline: WWN = %s\n", pwwn_buf);
Jing Huang88166242010-12-09 17:11:53 -08002300 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002301 "Base port disabled: WWN = %s\n", pwwn_buf);
2302 break;
2303
2304 case BFA_FCPORT_SM_LINKDOWN:
2305 bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
2306 bfa_fcport_reset_linkinfo(fcport);
2307 bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2308 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2309 BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
2310 wwn2str(pwwn_buf, fcport->pwwn);
2311 if (BFA_PORT_IS_DISABLED(fcport->bfa))
Jing Huang88166242010-12-09 17:11:53 -08002312 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002313 "Base port offline: WWN = %s\n", pwwn_buf);
2314 else
Jing Huang88166242010-12-09 17:11:53 -08002315 BFA_LOG(KERN_ERR, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002316 "Base port (WWN = %s) "
2317 "lost fabric connectivity\n", pwwn_buf);
2318 break;
2319
2320 case BFA_FCPORT_SM_STOP:
2321 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2322 bfa_fcport_reset_linkinfo(fcport);
2323 wwn2str(pwwn_buf, fcport->pwwn);
2324 if (BFA_PORT_IS_DISABLED(fcport->bfa))
Jing Huang88166242010-12-09 17:11:53 -08002325 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002326 "Base port offline: WWN = %s\n", pwwn_buf);
2327 else
Jing Huang88166242010-12-09 17:11:53 -08002328 BFA_LOG(KERN_ERR, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002329 "Base port (WWN = %s) "
2330 "lost fabric connectivity\n", pwwn_buf);
2331 break;
2332
2333 case BFA_FCPORT_SM_HWFAIL:
2334 bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2335 bfa_fcport_reset_linkinfo(fcport);
2336 bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2337 wwn2str(pwwn_buf, fcport->pwwn);
2338 if (BFA_PORT_IS_DISABLED(fcport->bfa))
Jing Huang88166242010-12-09 17:11:53 -08002339 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002340 "Base port offline: WWN = %s\n", pwwn_buf);
2341 else
Jing Huang88166242010-12-09 17:11:53 -08002342 BFA_LOG(KERN_ERR, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002343 "Base port (WWN = %s) "
2344 "lost fabric connectivity\n", pwwn_buf);
2345 break;
2346
2347 default:
2348 bfa_sm_fault(fcport->bfa, event);
2349 }
2350}
2351
2352static void
2353bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
2354 enum bfa_fcport_sm_event event)
2355{
2356 bfa_trc(fcport->bfa, event);
2357
2358 switch (event) {
2359 case BFA_FCPORT_SM_QRESUME:
2360 bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2361 bfa_fcport_send_disable(fcport);
2362 break;
2363
2364 case BFA_FCPORT_SM_STOP:
2365 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2366 bfa_reqq_wcancel(&fcport->reqq_wait);
2367 break;
2368
2369 case BFA_FCPORT_SM_ENABLE:
2370 bfa_sm_set_state(fcport, bfa_fcport_sm_toggling_qwait);
2371 break;
2372
2373 case BFA_FCPORT_SM_DISABLE:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002374 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002375 * Already being disabled.
2376 */
2377 break;
2378
2379 case BFA_FCPORT_SM_LINKUP:
2380 case BFA_FCPORT_SM_LINKDOWN:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002381 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002382 * Possible to get link events when doing back-to-back
2383 * enable/disables.
2384 */
2385 break;
2386
2387 case BFA_FCPORT_SM_HWFAIL:
2388 bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2389 bfa_reqq_wcancel(&fcport->reqq_wait);
2390 break;
2391
2392 default:
2393 bfa_sm_fault(fcport->bfa, event);
2394 }
2395}
2396
2397static void
2398bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
2399 enum bfa_fcport_sm_event event)
2400{
2401 bfa_trc(fcport->bfa, event);
2402
2403 switch (event) {
2404 case BFA_FCPORT_SM_QRESUME:
2405 bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2406 bfa_fcport_send_disable(fcport);
2407 if (bfa_fcport_send_enable(fcport))
2408 bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2409 else
2410 bfa_sm_set_state(fcport,
2411 bfa_fcport_sm_enabling_qwait);
2412 break;
2413
2414 case BFA_FCPORT_SM_STOP:
2415 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2416 bfa_reqq_wcancel(&fcport->reqq_wait);
2417 break;
2418
2419 case BFA_FCPORT_SM_ENABLE:
2420 break;
2421
2422 case BFA_FCPORT_SM_DISABLE:
2423 bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
2424 break;
2425
2426 case BFA_FCPORT_SM_LINKUP:
2427 case BFA_FCPORT_SM_LINKDOWN:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002428 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002429 * Possible to get link events when doing back-to-back
2430 * enable/disables.
2431 */
2432 break;
2433
2434 case BFA_FCPORT_SM_HWFAIL:
2435 bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2436 bfa_reqq_wcancel(&fcport->reqq_wait);
2437 break;
2438
2439 default:
2440 bfa_sm_fault(fcport->bfa, event);
2441 }
2442}
2443
2444static void
2445bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
2446 enum bfa_fcport_sm_event event)
2447{
2448 char pwwn_buf[BFA_STRING_32];
2449 struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2450 bfa_trc(fcport->bfa, event);
2451
2452 switch (event) {
2453 case BFA_FCPORT_SM_FWRSP:
2454 bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2455 break;
2456
2457 case BFA_FCPORT_SM_DISABLE:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002458 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002459 * Already being disabled.
2460 */
2461 break;
2462
2463 case BFA_FCPORT_SM_ENABLE:
2464 if (bfa_fcport_send_enable(fcport))
2465 bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2466 else
2467 bfa_sm_set_state(fcport,
2468 bfa_fcport_sm_enabling_qwait);
2469
2470 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2471 BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
2472 wwn2str(pwwn_buf, fcport->pwwn);
Jing Huang88166242010-12-09 17:11:53 -08002473 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002474 "Base port enabled: WWN = %s\n", pwwn_buf);
2475 break;
2476
2477 case BFA_FCPORT_SM_STOP:
2478 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2479 break;
2480
2481 case BFA_FCPORT_SM_LINKUP:
2482 case BFA_FCPORT_SM_LINKDOWN:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002483 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002484 * Possible to get link events when doing back-to-back
2485 * enable/disables.
2486 */
2487 break;
2488
2489 case BFA_FCPORT_SM_HWFAIL:
2490 bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2491 break;
2492
2493 default:
2494 bfa_sm_fault(fcport->bfa, event);
2495 }
2496}
2497
2498static void
2499bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
2500 enum bfa_fcport_sm_event event)
2501{
2502 char pwwn_buf[BFA_STRING_32];
2503 struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2504 bfa_trc(fcport->bfa, event);
2505
2506 switch (event) {
2507 case BFA_FCPORT_SM_START:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002508 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002509 * Ignore start event for a port that is disabled.
2510 */
2511 break;
2512
2513 case BFA_FCPORT_SM_STOP:
2514 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2515 break;
2516
2517 case BFA_FCPORT_SM_ENABLE:
2518 if (bfa_fcport_send_enable(fcport))
2519 bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2520 else
2521 bfa_sm_set_state(fcport,
2522 bfa_fcport_sm_enabling_qwait);
2523
2524 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2525 BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
2526 wwn2str(pwwn_buf, fcport->pwwn);
Jing Huang88166242010-12-09 17:11:53 -08002527 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002528 "Base port enabled: WWN = %s\n", pwwn_buf);
2529 break;
2530
2531 case BFA_FCPORT_SM_DISABLE:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002532 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002533 * Already disabled.
2534 */
2535 break;
2536
2537 case BFA_FCPORT_SM_HWFAIL:
2538 bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2539 break;
2540
2541 default:
2542 bfa_sm_fault(fcport->bfa, event);
2543 }
2544}
2545
2546static void
2547bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
2548 enum bfa_fcport_sm_event event)
2549{
2550 bfa_trc(fcport->bfa, event);
2551
2552 switch (event) {
2553 case BFA_FCPORT_SM_START:
2554 if (bfa_fcport_send_enable(fcport))
2555 bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2556 else
2557 bfa_sm_set_state(fcport,
2558 bfa_fcport_sm_enabling_qwait);
2559 break;
2560
2561 default:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002562 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002563 * Ignore all other events.
2564 */
2565 ;
2566 }
2567}
2568
Jing Huang5fbe25c2010-10-18 17:17:23 -07002569/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002570 * Port is enabled. IOC is down/failed.
2571 */
2572static void
2573bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
2574 enum bfa_fcport_sm_event event)
2575{
2576 bfa_trc(fcport->bfa, event);
2577
2578 switch (event) {
2579 case BFA_FCPORT_SM_START:
2580 if (bfa_fcport_send_enable(fcport))
2581 bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2582 else
2583 bfa_sm_set_state(fcport,
2584 bfa_fcport_sm_enabling_qwait);
2585 break;
2586
2587 default:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002588 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002589 * Ignore all events.
2590 */
2591 ;
2592 }
2593}
2594
Jing Huang5fbe25c2010-10-18 17:17:23 -07002595/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002596 * Port is disabled. IOC is down/failed.
2597 */
2598static void
2599bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
2600 enum bfa_fcport_sm_event event)
2601{
2602 bfa_trc(fcport->bfa, event);
2603
2604 switch (event) {
2605 case BFA_FCPORT_SM_START:
2606 bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2607 break;
2608
2609 case BFA_FCPORT_SM_ENABLE:
2610 bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2611 break;
2612
2613 default:
Jing Huang5fbe25c2010-10-18 17:17:23 -07002614 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002615 * Ignore all events.
2616 */
2617 ;
2618 }
2619}
2620
Jing Huang5fbe25c2010-10-18 17:17:23 -07002621/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002622 * Link state is down
2623 */
2624static void
2625bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
2626 enum bfa_fcport_ln_sm_event event)
2627{
2628 bfa_trc(ln->fcport->bfa, event);
2629
2630 switch (event) {
2631 case BFA_FCPORT_LN_SM_LINKUP:
2632 bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
2633 bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
2634 break;
2635
2636 default:
2637 bfa_sm_fault(ln->fcport->bfa, event);
2638 }
2639}
2640
Jing Huang5fbe25c2010-10-18 17:17:23 -07002641/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002642 * Link state is waiting for down notification
2643 */
2644static void
2645bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
2646 enum bfa_fcport_ln_sm_event event)
2647{
2648 bfa_trc(ln->fcport->bfa, event);
2649
2650 switch (event) {
2651 case BFA_FCPORT_LN_SM_LINKUP:
2652 bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
2653 break;
2654
2655 case BFA_FCPORT_LN_SM_NOTIFICATION:
2656 bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
2657 break;
2658
2659 default:
2660 bfa_sm_fault(ln->fcport->bfa, event);
2661 }
2662}
2663
Jing Huang5fbe25c2010-10-18 17:17:23 -07002664/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002665 * Link state is waiting for down notification and there is a pending up
2666 */
2667static void
2668bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
2669 enum bfa_fcport_ln_sm_event event)
2670{
2671 bfa_trc(ln->fcport->bfa, event);
2672
2673 switch (event) {
2674 case BFA_FCPORT_LN_SM_LINKDOWN:
2675 bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2676 break;
2677
2678 case BFA_FCPORT_LN_SM_NOTIFICATION:
2679 bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
2680 bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
2681 break;
2682
2683 default:
2684 bfa_sm_fault(ln->fcport->bfa, event);
2685 }
2686}
2687
Jing Huang5fbe25c2010-10-18 17:17:23 -07002688/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002689 * Link state is up
2690 */
2691static void
2692bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
2693 enum bfa_fcport_ln_sm_event event)
2694{
2695 bfa_trc(ln->fcport->bfa, event);
2696
2697 switch (event) {
2698 case BFA_FCPORT_LN_SM_LINKDOWN:
2699 bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2700 bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2701 break;
2702
2703 default:
2704 bfa_sm_fault(ln->fcport->bfa, event);
2705 }
2706}
2707
Jing Huang5fbe25c2010-10-18 17:17:23 -07002708/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002709 * Link state is waiting for up notification
2710 */
2711static void
2712bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
2713 enum bfa_fcport_ln_sm_event event)
2714{
2715 bfa_trc(ln->fcport->bfa, event);
2716
2717 switch (event) {
2718 case BFA_FCPORT_LN_SM_LINKDOWN:
2719 bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
2720 break;
2721
2722 case BFA_FCPORT_LN_SM_NOTIFICATION:
2723 bfa_sm_set_state(ln, bfa_fcport_ln_sm_up);
2724 break;
2725
2726 default:
2727 bfa_sm_fault(ln->fcport->bfa, event);
2728 }
2729}
2730
Jing Huang5fbe25c2010-10-18 17:17:23 -07002731/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002732 * Link state is waiting for up notification and there is a pending down
2733 */
2734static void
2735bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
2736 enum bfa_fcport_ln_sm_event event)
2737{
2738 bfa_trc(ln->fcport->bfa, event);
2739
2740 switch (event) {
2741 case BFA_FCPORT_LN_SM_LINKUP:
2742 bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_up_nf);
2743 break;
2744
2745 case BFA_FCPORT_LN_SM_NOTIFICATION:
2746 bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2747 bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2748 break;
2749
2750 default:
2751 bfa_sm_fault(ln->fcport->bfa, event);
2752 }
2753}
2754
Jing Huang5fbe25c2010-10-18 17:17:23 -07002755/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002756 * Link state is waiting for up notification and there are pending down and up
2757 */
2758static void
2759bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
2760 enum bfa_fcport_ln_sm_event event)
2761{
2762 bfa_trc(ln->fcport->bfa, event);
2763
2764 switch (event) {
2765 case BFA_FCPORT_LN_SM_LINKDOWN:
2766 bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
2767 break;
2768
2769 case BFA_FCPORT_LN_SM_NOTIFICATION:
2770 bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
2771 bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2772 break;
2773
2774 default:
2775 bfa_sm_fault(ln->fcport->bfa, event);
2776 }
2777}
2778
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002779static void
2780__bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete)
2781{
2782 struct bfa_fcport_ln_s *ln = cbarg;
2783
2784 if (complete)
2785 ln->fcport->event_cbfn(ln->fcport->event_cbarg, ln->ln_event);
2786 else
2787 bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
2788}
2789
Jing Huang5fbe25c2010-10-18 17:17:23 -07002790/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002791 * Send SCN notification to upper layers.
2792 * trunk - false if caller is fcport to ignore fcport event in trunked mode
2793 */
2794static void
2795bfa_fcport_scn(struct bfa_fcport_s *fcport, enum bfa_port_linkstate event,
2796 bfa_boolean_t trunk)
2797{
2798 if (fcport->cfg.trunked && !trunk)
2799 return;
2800
2801 switch (event) {
2802 case BFA_PORT_LINKUP:
2803 bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKUP);
2804 break;
2805 case BFA_PORT_LINKDOWN:
2806 bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKDOWN);
2807 break;
2808 default:
Jing Huangd4b671c2010-12-26 21:46:35 -08002809 WARN_ON(1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002810 }
2811}
2812
2813static void
2814bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln, enum bfa_port_linkstate event)
2815{
2816 struct bfa_fcport_s *fcport = ln->fcport;
2817
2818 if (fcport->bfa->fcs) {
2819 fcport->event_cbfn(fcport->event_cbarg, event);
2820 bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
2821 } else {
2822 ln->ln_event = event;
2823 bfa_cb_queue(fcport->bfa, &ln->ln_qe,
2824 __bfa_cb_fcport_event, ln);
2825 }
2826}
2827
2828#define FCPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_fcport_stats_u), \
2829 BFA_CACHELINE_SZ))
2830
2831static void
2832bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
2833 u32 *dm_len)
2834{
2835 *dm_len += FCPORT_STATS_DMA_SZ;
2836}
2837
2838static void
2839bfa_fcport_qresume(void *cbarg)
2840{
2841 struct bfa_fcport_s *fcport = cbarg;
2842
2843 bfa_sm_send_event(fcport, BFA_FCPORT_SM_QRESUME);
2844}
2845
2846static void
2847bfa_fcport_mem_claim(struct bfa_fcport_s *fcport, struct bfa_meminfo_s *meminfo)
2848{
2849 u8 *dm_kva;
2850 u64 dm_pa;
2851
2852 dm_kva = bfa_meminfo_dma_virt(meminfo);
2853 dm_pa = bfa_meminfo_dma_phys(meminfo);
2854
2855 fcport->stats_kva = dm_kva;
2856 fcport->stats_pa = dm_pa;
2857 fcport->stats = (union bfa_fcport_stats_u *) dm_kva;
2858
2859 dm_kva += FCPORT_STATS_DMA_SZ;
2860 dm_pa += FCPORT_STATS_DMA_SZ;
2861
2862 bfa_meminfo_dma_virt(meminfo) = dm_kva;
2863 bfa_meminfo_dma_phys(meminfo) = dm_pa;
2864}
2865
Jing Huang5fbe25c2010-10-18 17:17:23 -07002866/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002867 * Memory initialization.
2868 */
2869static void
2870bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
2871 struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
2872{
2873 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
2874 struct bfa_port_cfg_s *port_cfg = &fcport->cfg;
2875 struct bfa_fcport_ln_s *ln = &fcport->ln;
Maggie Zhangf16a1752010-12-09 19:12:32 -08002876 struct timeval tv;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002877
Jing Huang6a18b162010-10-18 17:08:54 -07002878 memset(fcport, 0, sizeof(struct bfa_fcport_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002879 fcport->bfa = bfa;
2880 ln->fcport = fcport;
2881
2882 bfa_fcport_mem_claim(fcport, meminfo);
2883
2884 bfa_sm_set_state(fcport, bfa_fcport_sm_uninit);
2885 bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
2886
Jing Huang5fbe25c2010-10-18 17:17:23 -07002887 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002888 * initialize time stamp for stats reset
2889 */
Maggie Zhangf16a1752010-12-09 19:12:32 -08002890 do_gettimeofday(&tv);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002891 fcport->stats_reset_time = tv.tv_sec;
2892
Jing Huang5fbe25c2010-10-18 17:17:23 -07002893 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002894 * initialize and set default configuration
2895 */
2896 port_cfg->topology = BFA_PORT_TOPOLOGY_P2P;
2897 port_cfg->speed = BFA_PORT_SPEED_AUTO;
2898 port_cfg->trunked = BFA_FALSE;
2899 port_cfg->maxfrsize = 0;
2900
2901 port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS;
2902
2903 bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);
2904}
2905
2906static void
2907bfa_fcport_detach(struct bfa_s *bfa)
2908{
2909}
2910
Jing Huang5fbe25c2010-10-18 17:17:23 -07002911/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002912 * Called when IOC is ready.
2913 */
2914static void
2915bfa_fcport_start(struct bfa_s *bfa)
2916{
2917 bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_START);
2918}
2919
Jing Huang5fbe25c2010-10-18 17:17:23 -07002920/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002921 * Called before IOC is stopped.
2922 */
2923static void
2924bfa_fcport_stop(struct bfa_s *bfa)
2925{
2926 bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_STOP);
2927 bfa_trunk_iocdisable(bfa);
2928}
2929
Jing Huang5fbe25c2010-10-18 17:17:23 -07002930/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002931 * Called when IOC failure is detected.
2932 */
2933static void
2934bfa_fcport_iocdisable(struct bfa_s *bfa)
2935{
2936 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
2937
2938 bfa_sm_send_event(fcport, BFA_FCPORT_SM_HWFAIL);
2939 bfa_trunk_iocdisable(bfa);
2940}
2941
2942static void
2943bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
2944{
2945 struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
2946 struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
2947
2948 fcport->speed = pevent->link_state.speed;
2949 fcport->topology = pevent->link_state.topology;
2950
2951 if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP)
2952 fcport->myalpa = 0;
2953
2954 /* QoS Details */
Jing Huang6a18b162010-10-18 17:08:54 -07002955 fcport->qos_attr = pevent->link_state.qos_attr;
2956 fcport->qos_vc_attr = pevent->link_state.vc_fcf.qos_vc_attr;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002957
Jing Huang5fbe25c2010-10-18 17:17:23 -07002958 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002959 * update trunk state if applicable
2960 */
2961 if (!fcport->cfg.trunked)
2962 trunk->attr.state = BFA_TRUNK_DISABLED;
2963
2964 /* update FCoE specific */
Jing Huangba816ea2010-10-18 17:10:50 -07002965 fcport->fcoe_vlan = be16_to_cpu(pevent->link_state.vc_fcf.fcf.vlan);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002966
2967 bfa_trc(fcport->bfa, fcport->speed);
2968 bfa_trc(fcport->bfa, fcport->topology);
2969}
2970
2971static void
2972bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)
2973{
2974 fcport->speed = BFA_PORT_SPEED_UNKNOWN;
2975 fcport->topology = BFA_PORT_TOPOLOGY_NONE;
Krishna Gudipatibe540a92011-06-13 15:53:04 -07002976 fcport->bbsc_op_state = BFA_FALSE;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002977}
2978
Jing Huang5fbe25c2010-10-18 17:17:23 -07002979/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002980 * Send port enable message to firmware.
2981 */
2982static bfa_boolean_t
2983bfa_fcport_send_enable(struct bfa_fcport_s *fcport)
2984{
2985 struct bfi_fcport_enable_req_s *m;
2986
Jing Huang5fbe25c2010-10-18 17:17:23 -07002987 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002988 * Increment message tag before queue check, so that responses to old
2989 * requests are discarded.
2990 */
2991 fcport->msgtag++;
2992
Jing Huang5fbe25c2010-10-18 17:17:23 -07002993 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002994 * check for room in queue to send request now
2995 */
2996 m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
2997 if (!m) {
2998 bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
2999 &fcport->reqq_wait);
3000 return BFA_FALSE;
3001 }
3002
3003 bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_ENABLE_REQ,
Krishna Gudipati3fd45982011-06-24 20:24:08 -07003004 bfa_fn_lpu(fcport->bfa));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003005 m->nwwn = fcport->nwwn;
3006 m->pwwn = fcport->pwwn;
3007 m->port_cfg = fcport->cfg;
3008 m->msgtag = fcport->msgtag;
Jing Huangba816ea2010-10-18 17:10:50 -07003009 m->port_cfg.maxfrsize = cpu_to_be16(fcport->cfg.maxfrsize);
Krishna Gudipatif3a060c2010-12-13 16:16:50 -08003010 m->use_flash_cfg = fcport->use_flash_cfg;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003011 bfa_dma_be_addr_set(m->stats_dma_addr, fcport->stats_pa);
3012 bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_lo);
3013 bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_hi);
3014
Jing Huang5fbe25c2010-10-18 17:17:23 -07003015 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003016 * queue I/O message to firmware
3017 */
Krishna Gudipati3fd45982011-06-24 20:24:08 -07003018 bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003019 return BFA_TRUE;
3020}
3021
Jing Huang5fbe25c2010-10-18 17:17:23 -07003022/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003023 * Send port disable message to firmware.
3024 */
3025static bfa_boolean_t
3026bfa_fcport_send_disable(struct bfa_fcport_s *fcport)
3027{
3028 struct bfi_fcport_req_s *m;
3029
Jing Huang5fbe25c2010-10-18 17:17:23 -07003030 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003031 * Increment message tag before queue check, so that responses to old
3032 * requests are discarded.
3033 */
3034 fcport->msgtag++;
3035
Jing Huang5fbe25c2010-10-18 17:17:23 -07003036 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003037 * check for room in queue to send request now
3038 */
3039 m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3040 if (!m) {
3041 bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3042 &fcport->reqq_wait);
3043 return BFA_FALSE;
3044 }
3045
3046 bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_DISABLE_REQ,
Krishna Gudipati3fd45982011-06-24 20:24:08 -07003047 bfa_fn_lpu(fcport->bfa));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003048 m->msgtag = fcport->msgtag;
3049
Jing Huang5fbe25c2010-10-18 17:17:23 -07003050 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003051 * queue I/O message to firmware
3052 */
Krishna Gudipati3fd45982011-06-24 20:24:08 -07003053 bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003054
3055 return BFA_TRUE;
3056}
3057
3058static void
3059bfa_fcport_set_wwns(struct bfa_fcport_s *fcport)
3060{
Maggie Zhangf7f73812010-12-09 19:08:43 -08003061 fcport->pwwn = fcport->bfa->ioc.attr->pwwn;
3062 fcport->nwwn = fcport->bfa->ioc.attr->nwwn;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003063
3064 bfa_trc(fcport->bfa, fcport->pwwn);
3065 bfa_trc(fcport->bfa, fcport->nwwn);
3066}
3067
3068static void
3069bfa_fcport_send_txcredit(void *port_cbarg)
3070{
3071
3072 struct bfa_fcport_s *fcport = port_cbarg;
3073 struct bfi_fcport_set_svc_params_req_s *m;
3074
Jing Huang5fbe25c2010-10-18 17:17:23 -07003075 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003076 * check for room in queue to send request now
3077 */
3078 m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3079 if (!m) {
3080 bfa_trc(fcport->bfa, fcport->cfg.tx_bbcredit);
3081 return;
3082 }
3083
3084 bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ,
Krishna Gudipati3fd45982011-06-24 20:24:08 -07003085 bfa_fn_lpu(fcport->bfa));
Jing Huangba816ea2010-10-18 17:10:50 -07003086 m->tx_bbcredit = cpu_to_be16((u16)fcport->cfg.tx_bbcredit);
Krishna Gudipatibe540a92011-06-13 15:53:04 -07003087 m->bb_scn = fcport->cfg.bb_scn;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003088
Jing Huang5fbe25c2010-10-18 17:17:23 -07003089 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003090 * queue I/O message to firmware
3091 */
Krishna Gudipati3fd45982011-06-24 20:24:08 -07003092 bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003093}
3094
3095static void
3096bfa_fcport_qos_stats_swap(struct bfa_qos_stats_s *d,
3097 struct bfa_qos_stats_s *s)
3098{
3099 u32 *dip = (u32 *) d;
Maggie50444a32010-11-29 18:26:32 -08003100 __be32 *sip = (__be32 *) s;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003101 int i;
3102
3103 /* Now swap the 32 bit fields */
3104 for (i = 0; i < (sizeof(struct bfa_qos_stats_s)/sizeof(u32)); ++i)
Jing Huangba816ea2010-10-18 17:10:50 -07003105 dip[i] = be32_to_cpu(sip[i]);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003106}
3107
3108static void
3109bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,
3110 struct bfa_fcoe_stats_s *s)
3111{
3112 u32 *dip = (u32 *) d;
Maggie50444a32010-11-29 18:26:32 -08003113 __be32 *sip = (__be32 *) s;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003114 int i;
3115
3116 for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32));
3117 i = i + 2) {
Maggie Zhangf16a1752010-12-09 19:12:32 -08003118#ifdef __BIG_ENDIAN
Jing Huangba816ea2010-10-18 17:10:50 -07003119 dip[i] = be32_to_cpu(sip[i]);
3120 dip[i + 1] = be32_to_cpu(sip[i + 1]);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003121#else
Jing Huangba816ea2010-10-18 17:10:50 -07003122 dip[i] = be32_to_cpu(sip[i + 1]);
3123 dip[i + 1] = be32_to_cpu(sip[i]);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003124#endif
3125 }
3126}
3127
3128static void
3129__bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)
3130{
3131 struct bfa_fcport_s *fcport = cbarg;
3132
3133 if (complete) {
3134 if (fcport->stats_status == BFA_STATUS_OK) {
Maggie Zhangf16a1752010-12-09 19:12:32 -08003135 struct timeval tv;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003136
3137 /* Swap FC QoS or FCoE stats */
3138 if (bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
3139 bfa_fcport_qos_stats_swap(
3140 &fcport->stats_ret->fcqos,
3141 &fcport->stats->fcqos);
3142 } else {
3143 bfa_fcport_fcoe_stats_swap(
3144 &fcport->stats_ret->fcoe,
3145 &fcport->stats->fcoe);
3146
Maggie Zhangf16a1752010-12-09 19:12:32 -08003147 do_gettimeofday(&tv);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003148 fcport->stats_ret->fcoe.secs_reset =
3149 tv.tv_sec - fcport->stats_reset_time;
3150 }
3151 }
3152 fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
3153 } else {
3154 fcport->stats_busy = BFA_FALSE;
3155 fcport->stats_status = BFA_STATUS_OK;
3156 }
3157}
3158
3159static void
3160bfa_fcport_stats_get_timeout(void *cbarg)
3161{
3162 struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3163
3164 bfa_trc(fcport->bfa, fcport->stats_qfull);
3165
3166 if (fcport->stats_qfull) {
3167 bfa_reqq_wcancel(&fcport->stats_reqq_wait);
3168 fcport->stats_qfull = BFA_FALSE;
3169 }
3170
3171 fcport->stats_status = BFA_STATUS_ETIMER;
3172 bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, __bfa_cb_fcport_stats_get,
3173 fcport);
3174}
3175
3176static void
3177bfa_fcport_send_stats_get(void *cbarg)
3178{
3179 struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3180 struct bfi_fcport_req_s *msg;
3181
3182 msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3183
3184 if (!msg) {
3185 fcport->stats_qfull = BFA_TRUE;
3186 bfa_reqq_winit(&fcport->stats_reqq_wait,
3187 bfa_fcport_send_stats_get, fcport);
3188 bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3189 &fcport->stats_reqq_wait);
3190 return;
3191 }
3192 fcport->stats_qfull = BFA_FALSE;
3193
Jing Huang6a18b162010-10-18 17:08:54 -07003194 memset(msg, 0, sizeof(struct bfi_fcport_req_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003195 bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_GET_REQ,
Krishna Gudipati3fd45982011-06-24 20:24:08 -07003196 bfa_fn_lpu(fcport->bfa));
3197 bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003198}
3199
3200static void
3201__bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
3202{
3203 struct bfa_fcport_s *fcport = cbarg;
3204
3205 if (complete) {
Maggie Zhangf16a1752010-12-09 19:12:32 -08003206 struct timeval tv;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003207
Jing Huang5fbe25c2010-10-18 17:17:23 -07003208 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003209 * re-initialize time stamp for stats reset
3210 */
Maggie Zhangf16a1752010-12-09 19:12:32 -08003211 do_gettimeofday(&tv);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003212 fcport->stats_reset_time = tv.tv_sec;
3213
3214 fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
3215 } else {
3216 fcport->stats_busy = BFA_FALSE;
3217 fcport->stats_status = BFA_STATUS_OK;
3218 }
3219}
3220
3221static void
3222bfa_fcport_stats_clr_timeout(void *cbarg)
3223{
3224 struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3225
3226 bfa_trc(fcport->bfa, fcport->stats_qfull);
3227
3228 if (fcport->stats_qfull) {
3229 bfa_reqq_wcancel(&fcport->stats_reqq_wait);
3230 fcport->stats_qfull = BFA_FALSE;
3231 }
3232
3233 fcport->stats_status = BFA_STATUS_ETIMER;
3234 bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
3235 __bfa_cb_fcport_stats_clr, fcport);
3236}
3237
3238static void
3239bfa_fcport_send_stats_clear(void *cbarg)
3240{
3241 struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3242 struct bfi_fcport_req_s *msg;
3243
3244 msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3245
3246 if (!msg) {
3247 fcport->stats_qfull = BFA_TRUE;
3248 bfa_reqq_winit(&fcport->stats_reqq_wait,
3249 bfa_fcport_send_stats_clear, fcport);
3250 bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3251 &fcport->stats_reqq_wait);
3252 return;
3253 }
3254 fcport->stats_qfull = BFA_FALSE;
3255
Jing Huang6a18b162010-10-18 17:08:54 -07003256 memset(msg, 0, sizeof(struct bfi_fcport_req_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003257 bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_CLEAR_REQ,
Krishna Gudipati3fd45982011-06-24 20:24:08 -07003258 bfa_fn_lpu(fcport->bfa));
3259 bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003260}
3261
Jing Huang5fbe25c2010-10-18 17:17:23 -07003262/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003263 * Handle trunk SCN event from firmware.
3264 */
3265static void
3266bfa_trunk_scn(struct bfa_fcport_s *fcport, struct bfi_fcport_trunk_scn_s *scn)
3267{
3268 struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
3269 struct bfi_fcport_trunk_link_s *tlink;
3270 struct bfa_trunk_link_attr_s *lattr;
3271 enum bfa_trunk_state state_prev;
3272 int i;
3273 int link_bm = 0;
3274
3275 bfa_trc(fcport->bfa, fcport->cfg.trunked);
Jing Huangd4b671c2010-12-26 21:46:35 -08003276 WARN_ON(scn->trunk_state != BFA_TRUNK_ONLINE &&
3277 scn->trunk_state != BFA_TRUNK_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003278
3279 bfa_trc(fcport->bfa, trunk->attr.state);
3280 bfa_trc(fcport->bfa, scn->trunk_state);
3281 bfa_trc(fcport->bfa, scn->trunk_speed);
3282
Jing Huang5fbe25c2010-10-18 17:17:23 -07003283 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003284 * Save off new state for trunk attribute query
3285 */
3286 state_prev = trunk->attr.state;
3287 if (fcport->cfg.trunked && (trunk->attr.state != BFA_TRUNK_DISABLED))
3288 trunk->attr.state = scn->trunk_state;
3289 trunk->attr.speed = scn->trunk_speed;
3290 for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
3291 lattr = &trunk->attr.link_attr[i];
3292 tlink = &scn->tlink[i];
3293
3294 lattr->link_state = tlink->state;
3295 lattr->trunk_wwn = tlink->trunk_wwn;
3296 lattr->fctl = tlink->fctl;
3297 lattr->speed = tlink->speed;
Jing Huangba816ea2010-10-18 17:10:50 -07003298 lattr->deskew = be32_to_cpu(tlink->deskew);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003299
3300 if (tlink->state == BFA_TRUNK_LINK_STATE_UP) {
3301 fcport->speed = tlink->speed;
3302 fcport->topology = BFA_PORT_TOPOLOGY_P2P;
3303 link_bm |= 1 << i;
3304 }
3305
3306 bfa_trc(fcport->bfa, lattr->link_state);
3307 bfa_trc(fcport->bfa, lattr->trunk_wwn);
3308 bfa_trc(fcport->bfa, lattr->fctl);
3309 bfa_trc(fcport->bfa, lattr->speed);
3310 bfa_trc(fcport->bfa, lattr->deskew);
3311 }
3312
3313 switch (link_bm) {
3314 case 3:
3315 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3316 BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,1)");
3317 break;
3318 case 2:
3319 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3320 BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(-,1)");
3321 break;
3322 case 1:
3323 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3324 BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,-)");
3325 break;
3326 default:
3327 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3328 BFA_PL_EID_TRUNK_SCN, 0, "Trunk down");
3329 }
3330
Jing Huang5fbe25c2010-10-18 17:17:23 -07003331 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003332 * Notify upper layers if trunk state changed.
3333 */
3334 if ((state_prev != trunk->attr.state) ||
3335 (scn->trunk_state == BFA_TRUNK_OFFLINE)) {
3336 bfa_fcport_scn(fcport, (scn->trunk_state == BFA_TRUNK_ONLINE) ?
3337 BFA_PORT_LINKUP : BFA_PORT_LINKDOWN, BFA_TRUE);
3338 }
3339}
3340
3341static void
3342bfa_trunk_iocdisable(struct bfa_s *bfa)
3343{
3344 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3345 int i = 0;
3346
Jing Huang5fbe25c2010-10-18 17:17:23 -07003347 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003348 * In trunked mode, notify upper layers that link is down
3349 */
3350 if (fcport->cfg.trunked) {
3351 if (fcport->trunk.attr.state == BFA_TRUNK_ONLINE)
3352 bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_TRUE);
3353
3354 fcport->trunk.attr.state = BFA_TRUNK_OFFLINE;
3355 fcport->trunk.attr.speed = BFA_PORT_SPEED_UNKNOWN;
3356 for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
3357 fcport->trunk.attr.link_attr[i].trunk_wwn = 0;
3358 fcport->trunk.attr.link_attr[i].fctl =
3359 BFA_TRUNK_LINK_FCTL_NORMAL;
3360 fcport->trunk.attr.link_attr[i].link_state =
3361 BFA_TRUNK_LINK_STATE_DN_LINKDN;
3362 fcport->trunk.attr.link_attr[i].speed =
3363 BFA_PORT_SPEED_UNKNOWN;
3364 fcport->trunk.attr.link_attr[i].deskew = 0;
3365 }
3366 }
3367}
3368
Jing Huang5fbe25c2010-10-18 17:17:23 -07003369/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003370 * Called to initialize port attributes
3371 */
3372void
3373bfa_fcport_init(struct bfa_s *bfa)
3374{
3375 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3376
Jing Huang5fbe25c2010-10-18 17:17:23 -07003377 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003378 * Initialize port attributes from IOC hardware data.
3379 */
3380 bfa_fcport_set_wwns(fcport);
3381 if (fcport->cfg.maxfrsize == 0)
3382 fcport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc);
3383 fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
3384 fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
3385
Krishna Gudipati43ffdf42011-06-13 15:46:21 -07003386 if (bfa_fcport_is_pbcdisabled(bfa))
3387 bfa->modules.port.pbc_disabled = BFA_TRUE;
3388
Jing Huangd4b671c2010-12-26 21:46:35 -08003389 WARN_ON(!fcport->cfg.maxfrsize);
3390 WARN_ON(!fcport->cfg.rx_bbcredit);
3391 WARN_ON(!fcport->speed_sup);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003392}
3393
Jing Huang5fbe25c2010-10-18 17:17:23 -07003394/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003395 * Firmware message handler.
3396 */
3397void
3398bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
3399{
3400 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3401 union bfi_fcport_i2h_msg_u i2hmsg;
3402
3403 i2hmsg.msg = msg;
3404 fcport->event_arg.i2hmsg = i2hmsg;
3405
3406 bfa_trc(bfa, msg->mhdr.msg_id);
3407 bfa_trc(bfa, bfa_sm_to_state(hal_port_sm_table, fcport->sm));
3408
3409 switch (msg->mhdr.msg_id) {
3410 case BFI_FCPORT_I2H_ENABLE_RSP:
Krishna Gudipatif3a060c2010-12-13 16:16:50 -08003411 if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) {
3412
3413 if (fcport->use_flash_cfg) {
3414 fcport->cfg = i2hmsg.penable_rsp->port_cfg;
3415 fcport->cfg.maxfrsize =
3416 cpu_to_be16(fcport->cfg.maxfrsize);
3417 fcport->cfg.path_tov =
3418 cpu_to_be16(fcport->cfg.path_tov);
3419 fcport->cfg.q_depth =
3420 cpu_to_be16(fcport->cfg.q_depth);
3421
3422 if (fcport->cfg.trunked)
3423 fcport->trunk.attr.state =
3424 BFA_TRUNK_OFFLINE;
3425 else
3426 fcport->trunk.attr.state =
3427 BFA_TRUNK_DISABLED;
3428 fcport->use_flash_cfg = BFA_FALSE;
3429 }
3430
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003431 bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
Krishna Gudipatif3a060c2010-12-13 16:16:50 -08003432 }
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003433 break;
3434
3435 case BFI_FCPORT_I2H_DISABLE_RSP:
3436 if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)
3437 bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
3438 break;
3439
3440 case BFI_FCPORT_I2H_EVENT:
3441 if (i2hmsg.event->link_state.linkstate == BFA_PORT_LINKUP)
3442 bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP);
3443 else
3444 bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKDOWN);
3445 break;
3446
3447 case BFI_FCPORT_I2H_TRUNK_SCN:
3448 bfa_trunk_scn(fcport, i2hmsg.trunk_scn);
3449 break;
3450
3451 case BFI_FCPORT_I2H_STATS_GET_RSP:
3452 /*
3453 * check for timer pop before processing the rsp
3454 */
3455 if (fcport->stats_busy == BFA_FALSE ||
3456 fcport->stats_status == BFA_STATUS_ETIMER)
3457 break;
3458
3459 bfa_timer_stop(&fcport->timer);
3460 fcport->stats_status = i2hmsg.pstatsget_rsp->status;
3461 bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
3462 __bfa_cb_fcport_stats_get, fcport);
3463 break;
3464
3465 case BFI_FCPORT_I2H_STATS_CLEAR_RSP:
3466 /*
3467 * check for timer pop before processing the rsp
3468 */
3469 if (fcport->stats_busy == BFA_FALSE ||
3470 fcport->stats_status == BFA_STATUS_ETIMER)
3471 break;
3472
3473 bfa_timer_stop(&fcport->timer);
3474 fcport->stats_status = BFA_STATUS_OK;
3475 bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
3476 __bfa_cb_fcport_stats_clr, fcport);
3477 break;
3478
3479 case BFI_FCPORT_I2H_ENABLE_AEN:
3480 bfa_sm_send_event(fcport, BFA_FCPORT_SM_ENABLE);
3481 break;
3482
3483 case BFI_FCPORT_I2H_DISABLE_AEN:
3484 bfa_sm_send_event(fcport, BFA_FCPORT_SM_DISABLE);
3485 break;
3486
3487 default:
Jing Huangd4b671c2010-12-26 21:46:35 -08003488 WARN_ON(1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003489 break;
3490 }
3491}
3492
Jing Huang5fbe25c2010-10-18 17:17:23 -07003493/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003494 * Registered callback for port events.
3495 */
3496void
3497bfa_fcport_event_register(struct bfa_s *bfa,
3498 void (*cbfn) (void *cbarg,
3499 enum bfa_port_linkstate event),
3500 void *cbarg)
3501{
3502 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3503
3504 fcport->event_cbfn = cbfn;
3505 fcport->event_cbarg = cbarg;
3506}
3507
3508bfa_status_t
3509bfa_fcport_enable(struct bfa_s *bfa)
3510{
3511 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3512
Krishna Gudipati43ffdf42011-06-13 15:46:21 -07003513 if (bfa_fcport_is_pbcdisabled(bfa))
3514 return BFA_STATUS_PBC;
3515
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003516 if (bfa_ioc_is_disabled(&bfa->ioc))
3517 return BFA_STATUS_IOC_DISABLED;
3518
3519 if (fcport->diag_busy)
3520 return BFA_STATUS_DIAG_BUSY;
3521
3522 bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_ENABLE);
3523 return BFA_STATUS_OK;
3524}
3525
3526bfa_status_t
3527bfa_fcport_disable(struct bfa_s *bfa)
3528{
Krishna Gudipati43ffdf42011-06-13 15:46:21 -07003529 if (bfa_fcport_is_pbcdisabled(bfa))
3530 return BFA_STATUS_PBC;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003531
3532 if (bfa_ioc_is_disabled(&bfa->ioc))
3533 return BFA_STATUS_IOC_DISABLED;
3534
3535 bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DISABLE);
3536 return BFA_STATUS_OK;
3537}
3538
Krishna Gudipati43ffdf42011-06-13 15:46:21 -07003539/* If PBC is disabled on port, return error */
3540bfa_status_t
3541bfa_fcport_is_pbcdisabled(struct bfa_s *bfa)
3542{
3543 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3544 struct bfa_iocfc_s *iocfc = &bfa->iocfc;
3545 struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
3546
3547 if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) {
3548 bfa_trc(bfa, fcport->pwwn);
3549 return BFA_STATUS_PBC;
3550 }
3551 return BFA_STATUS_OK;
3552}
3553
Jing Huang5fbe25c2010-10-18 17:17:23 -07003554/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003555 * Configure port speed.
3556 */
3557bfa_status_t
3558bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
3559{
3560 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3561
3562 bfa_trc(bfa, speed);
3563
3564 if (fcport->cfg.trunked == BFA_TRUE)
3565 return BFA_STATUS_TRUNK_ENABLED;
3566 if ((speed != BFA_PORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {
3567 bfa_trc(bfa, fcport->speed_sup);
3568 return BFA_STATUS_UNSUPP_SPEED;
3569 }
3570
Krishna Gudipatia7141342011-06-24 20:23:19 -07003571 /* For Mezz card, port speed entered needs to be checked */
3572 if (bfa_mfg_is_mezz(fcport->bfa->ioc.attr->card_type)) {
3573 if (bfa_ioc_get_type(&fcport->bfa->ioc) == BFA_IOC_TYPE_FC) {
3574 /* For CT2, 1G is not supported */
3575 if ((speed == BFA_PORT_SPEED_1GBPS) &&
3576 (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)))
3577 return BFA_STATUS_UNSUPP_SPEED;
3578
3579 /* Already checked for Auto Speed and Max Speed supp */
3580 if (!(speed == BFA_PORT_SPEED_1GBPS ||
3581 speed == BFA_PORT_SPEED_2GBPS ||
3582 speed == BFA_PORT_SPEED_4GBPS ||
3583 speed == BFA_PORT_SPEED_8GBPS ||
3584 speed == BFA_PORT_SPEED_16GBPS ||
3585 speed == BFA_PORT_SPEED_AUTO))
3586 return BFA_STATUS_UNSUPP_SPEED;
3587 } else {
3588 if (speed != BFA_PORT_SPEED_10GBPS)
3589 return BFA_STATUS_UNSUPP_SPEED;
3590 }
3591 }
3592
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003593 fcport->cfg.speed = speed;
3594
3595 return BFA_STATUS_OK;
3596}
3597
Jing Huang5fbe25c2010-10-18 17:17:23 -07003598/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003599 * Get current speed.
3600 */
3601enum bfa_port_speed
3602bfa_fcport_get_speed(struct bfa_s *bfa)
3603{
3604 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3605
3606 return fcport->speed;
3607}
3608
Jing Huang5fbe25c2010-10-18 17:17:23 -07003609/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003610 * Configure port topology.
3611 */
3612bfa_status_t
3613bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)
3614{
3615 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3616
3617 bfa_trc(bfa, topology);
3618 bfa_trc(bfa, fcport->cfg.topology);
3619
3620 switch (topology) {
3621 case BFA_PORT_TOPOLOGY_P2P:
3622 case BFA_PORT_TOPOLOGY_LOOP:
3623 case BFA_PORT_TOPOLOGY_AUTO:
3624 break;
3625
3626 default:
3627 return BFA_STATUS_EINVAL;
3628 }
3629
3630 fcport->cfg.topology = topology;
3631 return BFA_STATUS_OK;
3632}
3633
Jing Huang5fbe25c2010-10-18 17:17:23 -07003634/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003635 * Get current topology.
3636 */
3637enum bfa_port_topology
3638bfa_fcport_get_topology(struct bfa_s *bfa)
3639{
3640 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3641
3642 return fcport->topology;
3643}
3644
3645bfa_status_t
3646bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
3647{
3648 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3649
3650 bfa_trc(bfa, alpa);
3651 bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
3652 bfa_trc(bfa, fcport->cfg.hardalpa);
3653
3654 fcport->cfg.cfg_hardalpa = BFA_TRUE;
3655 fcport->cfg.hardalpa = alpa;
3656
3657 return BFA_STATUS_OK;
3658}
3659
3660bfa_status_t
3661bfa_fcport_clr_hardalpa(struct bfa_s *bfa)
3662{
3663 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3664
3665 bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
3666 bfa_trc(bfa, fcport->cfg.hardalpa);
3667
3668 fcport->cfg.cfg_hardalpa = BFA_FALSE;
3669 return BFA_STATUS_OK;
3670}
3671
3672bfa_boolean_t
3673bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa)
3674{
3675 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3676
3677 *alpa = fcport->cfg.hardalpa;
3678 return fcport->cfg.cfg_hardalpa;
3679}
3680
3681u8
3682bfa_fcport_get_myalpa(struct bfa_s *bfa)
3683{
3684 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3685
3686 return fcport->myalpa;
3687}
3688
3689bfa_status_t
3690bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize)
3691{
3692 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3693
3694 bfa_trc(bfa, maxfrsize);
3695 bfa_trc(bfa, fcport->cfg.maxfrsize);
3696
3697 /* with in range */
3698 if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ))
3699 return BFA_STATUS_INVLD_DFSZ;
3700
3701 /* power of 2, if not the max frame size of 2112 */
3702 if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1)))
3703 return BFA_STATUS_INVLD_DFSZ;
3704
3705 fcport->cfg.maxfrsize = maxfrsize;
3706 return BFA_STATUS_OK;
3707}
3708
3709u16
3710bfa_fcport_get_maxfrsize(struct bfa_s *bfa)
3711{
3712 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3713
3714 return fcport->cfg.maxfrsize;
3715}
3716
3717u8
3718bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
3719{
3720 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3721
3722 return fcport->cfg.rx_bbcredit;
3723}
3724
3725void
Krishna Gudipatibe540a92011-06-13 15:53:04 -07003726bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit, u8 bb_scn)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003727{
3728 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3729
3730 fcport->cfg.tx_bbcredit = (u8)tx_bbcredit;
Krishna Gudipatibe540a92011-06-13 15:53:04 -07003731 fcport->cfg.bb_scn = bb_scn;
3732 if (bb_scn)
3733 fcport->bbsc_op_state = BFA_TRUE;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003734 bfa_fcport_send_txcredit(fcport);
3735}
3736
Jing Huang5fbe25c2010-10-18 17:17:23 -07003737/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003738 * Get port attributes.
3739 */
3740
3741wwn_t
3742bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node)
3743{
3744 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3745 if (node)
3746 return fcport->nwwn;
3747 else
3748 return fcport->pwwn;
3749}
3750
3751void
3752bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)
3753{
3754 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3755
Jing Huang6a18b162010-10-18 17:08:54 -07003756 memset(attr, 0, sizeof(struct bfa_port_attr_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003757
3758 attr->nwwn = fcport->nwwn;
3759 attr->pwwn = fcport->pwwn;
3760
Maggie Zhangf7f73812010-12-09 19:08:43 -08003761 attr->factorypwwn = bfa->ioc.attr->mfg_pwwn;
3762 attr->factorynwwn = bfa->ioc.attr->mfg_nwwn;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003763
Jing Huang6a18b162010-10-18 17:08:54 -07003764 memcpy(&attr->pport_cfg, &fcport->cfg,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003765 sizeof(struct bfa_port_cfg_s));
3766 /* speed attributes */
3767 attr->pport_cfg.speed = fcport->cfg.speed;
3768 attr->speed_supported = fcport->speed_sup;
3769 attr->speed = fcport->speed;
3770 attr->cos_supported = FC_CLASS_3;
3771
3772 /* topology attributes */
3773 attr->pport_cfg.topology = fcport->cfg.topology;
3774 attr->topology = fcport->topology;
3775 attr->pport_cfg.trunked = fcport->cfg.trunked;
3776
3777 /* beacon attributes */
3778 attr->beacon = fcport->beacon;
3779 attr->link_e2e_beacon = fcport->link_e2e_beacon;
Maggie Zhangf7f73812010-12-09 19:08:43 -08003780 attr->plog_enabled = (bfa_boolean_t)fcport->bfa->plog->plog_enabled;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003781 attr->io_profile = bfa_fcpim_get_io_profile(fcport->bfa);
3782
3783 attr->pport_cfg.path_tov = bfa_fcpim_path_tov_get(bfa);
3784 attr->pport_cfg.q_depth = bfa_fcpim_qdepth_get(bfa);
3785 attr->port_state = bfa_sm_to_state(hal_port_sm_table, fcport->sm);
Krishna Gudipatibe540a92011-06-13 15:53:04 -07003786 attr->bbsc_op_status = fcport->bbsc_op_state;
Krishna Gudipati43ffdf42011-06-13 15:46:21 -07003787
3788 /* PBC Disabled State */
3789 if (bfa_fcport_is_pbcdisabled(bfa))
3790 attr->port_state = BFA_PORT_ST_PREBOOT_DISABLED;
3791 else {
3792 if (bfa_ioc_is_disabled(&fcport->bfa->ioc))
3793 attr->port_state = BFA_PORT_ST_IOCDIS;
3794 else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc))
3795 attr->port_state = BFA_PORT_ST_FWMISMATCH;
Krishna Gudipatia7141342011-06-24 20:23:19 -07003796 else if (bfa_ioc_is_acq_addr(&fcport->bfa->ioc))
3797 attr->port_state = BFA_PORT_ST_ACQ_ADDR;
Krishna Gudipati43ffdf42011-06-13 15:46:21 -07003798 }
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003799
3800 /* FCoE vlan */
3801 attr->fcoe_vlan = fcport->fcoe_vlan;
3802}
3803
3804#define BFA_FCPORT_STATS_TOV 1000
3805
Jing Huang5fbe25c2010-10-18 17:17:23 -07003806/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003807 * Fetch port statistics (FCQoS or FCoE).
3808 */
3809bfa_status_t
3810bfa_fcport_get_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
3811 bfa_cb_port_t cbfn, void *cbarg)
3812{
3813 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3814
3815 if (fcport->stats_busy) {
3816 bfa_trc(bfa, fcport->stats_busy);
3817 return BFA_STATUS_DEVBUSY;
3818 }
3819
3820 fcport->stats_busy = BFA_TRUE;
3821 fcport->stats_ret = stats;
3822 fcport->stats_cbfn = cbfn;
3823 fcport->stats_cbarg = cbarg;
3824
3825 bfa_fcport_send_stats_get(fcport);
3826
3827 bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_get_timeout,
3828 fcport, BFA_FCPORT_STATS_TOV);
3829 return BFA_STATUS_OK;
3830}
3831
Jing Huang5fbe25c2010-10-18 17:17:23 -07003832/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003833 * Reset port statistics (FCQoS or FCoE).
3834 */
3835bfa_status_t
3836bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg)
3837{
3838 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3839
3840 if (fcport->stats_busy) {
3841 bfa_trc(bfa, fcport->stats_busy);
3842 return BFA_STATUS_DEVBUSY;
3843 }
3844
3845 fcport->stats_busy = BFA_TRUE;
3846 fcport->stats_cbfn = cbfn;
3847 fcport->stats_cbarg = cbarg;
3848
3849 bfa_fcport_send_stats_clear(fcport);
3850
3851 bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_clr_timeout,
3852 fcport, BFA_FCPORT_STATS_TOV);
3853 return BFA_STATUS_OK;
3854}
3855
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003856
Jing Huang5fbe25c2010-10-18 17:17:23 -07003857/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003858 * Fetch port attributes.
3859 */
3860bfa_boolean_t
3861bfa_fcport_is_disabled(struct bfa_s *bfa)
3862{
3863 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3864
3865 return bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
3866 BFA_PORT_ST_DISABLED;
3867
3868}
3869
3870bfa_boolean_t
3871bfa_fcport_is_ratelim(struct bfa_s *bfa)
3872{
3873 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3874
3875 return fcport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE;
3876
3877}
3878
Jing Huang5fbe25c2010-10-18 17:17:23 -07003879/*
Krishna Gudipatia7141342011-06-24 20:23:19 -07003880 * Enable/Disable FAA feature in port config
3881 */
3882void
3883bfa_fcport_cfg_faa(struct bfa_s *bfa, u8 state)
3884{
3885 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3886
3887 bfa_trc(bfa, state);
3888 fcport->cfg.faa_state = state;
3889}
3890
3891/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003892 * Get default minimum ratelim speed
3893 */
3894enum bfa_port_speed
3895bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)
3896{
3897 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3898
3899 bfa_trc(bfa, fcport->cfg.trl_def_speed);
3900 return fcport->cfg.trl_def_speed;
3901
3902}
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003903
3904bfa_boolean_t
3905bfa_fcport_is_linkup(struct bfa_s *bfa)
3906{
3907 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3908
3909 return (!fcport->cfg.trunked &&
3910 bfa_sm_cmp_state(fcport, bfa_fcport_sm_linkup)) ||
3911 (fcport->cfg.trunked &&
3912 fcport->trunk.attr.state == BFA_TRUNK_ONLINE);
3913}
3914
3915bfa_boolean_t
3916bfa_fcport_is_qos_enabled(struct bfa_s *bfa)
3917{
3918 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3919
3920 return fcport->cfg.qos_enabled;
3921}
3922
Krishna Gudipatibe540a92011-06-13 15:53:04 -07003923bfa_boolean_t
3924bfa_fcport_is_trunk_enabled(struct bfa_s *bfa)
3925{
3926 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3927
3928 return fcport->cfg.trunked;
3929}
3930
Jing Huang5fbe25c2010-10-18 17:17:23 -07003931/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003932 * Rport State machine functions
3933 */
Jing Huang5fbe25c2010-10-18 17:17:23 -07003934/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003935 * Beginning state, only online event expected.
3936 */
3937static void
3938bfa_rport_sm_uninit(struct bfa_rport_s *rp, enum bfa_rport_event event)
3939{
3940 bfa_trc(rp->bfa, rp->rport_tag);
3941 bfa_trc(rp->bfa, event);
3942
3943 switch (event) {
3944 case BFA_RPORT_SM_CREATE:
3945 bfa_stats(rp, sm_un_cr);
3946 bfa_sm_set_state(rp, bfa_rport_sm_created);
3947 break;
3948
3949 default:
3950 bfa_stats(rp, sm_un_unexp);
3951 bfa_sm_fault(rp->bfa, event);
3952 }
3953}
3954
3955static void
3956bfa_rport_sm_created(struct bfa_rport_s *rp, enum bfa_rport_event event)
3957{
3958 bfa_trc(rp->bfa, rp->rport_tag);
3959 bfa_trc(rp->bfa, event);
3960
3961 switch (event) {
3962 case BFA_RPORT_SM_ONLINE:
3963 bfa_stats(rp, sm_cr_on);
3964 if (bfa_rport_send_fwcreate(rp))
3965 bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
3966 else
3967 bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
3968 break;
3969
3970 case BFA_RPORT_SM_DELETE:
3971 bfa_stats(rp, sm_cr_del);
3972 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
3973 bfa_rport_free(rp);
3974 break;
3975
3976 case BFA_RPORT_SM_HWFAIL:
3977 bfa_stats(rp, sm_cr_hwf);
3978 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
3979 break;
3980
3981 default:
3982 bfa_stats(rp, sm_cr_unexp);
3983 bfa_sm_fault(rp->bfa, event);
3984 }
3985}
3986
Jing Huang5fbe25c2010-10-18 17:17:23 -07003987/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003988 * Waiting for rport create response from firmware.
3989 */
3990static void
3991bfa_rport_sm_fwcreate(struct bfa_rport_s *rp, enum bfa_rport_event event)
3992{
3993 bfa_trc(rp->bfa, rp->rport_tag);
3994 bfa_trc(rp->bfa, event);
3995
3996 switch (event) {
3997 case BFA_RPORT_SM_FWRSP:
3998 bfa_stats(rp, sm_fwc_rsp);
3999 bfa_sm_set_state(rp, bfa_rport_sm_online);
4000 bfa_rport_online_cb(rp);
4001 break;
4002
4003 case BFA_RPORT_SM_DELETE:
4004 bfa_stats(rp, sm_fwc_del);
4005 bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
4006 break;
4007
4008 case BFA_RPORT_SM_OFFLINE:
4009 bfa_stats(rp, sm_fwc_off);
4010 bfa_sm_set_state(rp, bfa_rport_sm_offline_pending);
4011 break;
4012
4013 case BFA_RPORT_SM_HWFAIL:
4014 bfa_stats(rp, sm_fwc_hwf);
4015 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4016 break;
4017
4018 default:
4019 bfa_stats(rp, sm_fwc_unexp);
4020 bfa_sm_fault(rp->bfa, event);
4021 }
4022}
4023
Jing Huang5fbe25c2010-10-18 17:17:23 -07004024/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004025 * Request queue is full, awaiting queue resume to send create request.
4026 */
4027static void
4028bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4029{
4030 bfa_trc(rp->bfa, rp->rport_tag);
4031 bfa_trc(rp->bfa, event);
4032
4033 switch (event) {
4034 case BFA_RPORT_SM_QRESUME:
4035 bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4036 bfa_rport_send_fwcreate(rp);
4037 break;
4038
4039 case BFA_RPORT_SM_DELETE:
4040 bfa_stats(rp, sm_fwc_del);
4041 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4042 bfa_reqq_wcancel(&rp->reqq_wait);
4043 bfa_rport_free(rp);
4044 break;
4045
4046 case BFA_RPORT_SM_OFFLINE:
4047 bfa_stats(rp, sm_fwc_off);
4048 bfa_sm_set_state(rp, bfa_rport_sm_offline);
4049 bfa_reqq_wcancel(&rp->reqq_wait);
4050 bfa_rport_offline_cb(rp);
4051 break;
4052
4053 case BFA_RPORT_SM_HWFAIL:
4054 bfa_stats(rp, sm_fwc_hwf);
4055 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4056 bfa_reqq_wcancel(&rp->reqq_wait);
4057 break;
4058
4059 default:
4060 bfa_stats(rp, sm_fwc_unexp);
4061 bfa_sm_fault(rp->bfa, event);
4062 }
4063}
4064
Jing Huang5fbe25c2010-10-18 17:17:23 -07004065/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004066 * Online state - normal parking state.
4067 */
4068static void
4069bfa_rport_sm_online(struct bfa_rport_s *rp, enum bfa_rport_event event)
4070{
4071 struct bfi_rport_qos_scn_s *qos_scn;
4072
4073 bfa_trc(rp->bfa, rp->rport_tag);
4074 bfa_trc(rp->bfa, event);
4075
4076 switch (event) {
4077 case BFA_RPORT_SM_OFFLINE:
4078 bfa_stats(rp, sm_on_off);
4079 if (bfa_rport_send_fwdelete(rp))
4080 bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4081 else
4082 bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
4083 break;
4084
4085 case BFA_RPORT_SM_DELETE:
4086 bfa_stats(rp, sm_on_del);
4087 if (bfa_rport_send_fwdelete(rp))
4088 bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4089 else
4090 bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4091 break;
4092
4093 case BFA_RPORT_SM_HWFAIL:
4094 bfa_stats(rp, sm_on_hwf);
4095 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4096 break;
4097
4098 case BFA_RPORT_SM_SET_SPEED:
4099 bfa_rport_send_fwspeed(rp);
4100 break;
4101
4102 case BFA_RPORT_SM_QOS_SCN:
4103 qos_scn = (struct bfi_rport_qos_scn_s *) rp->event_arg.fw_msg;
4104 rp->qos_attr = qos_scn->new_qos_attr;
4105 bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_flow_id);
4106 bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_flow_id);
4107 bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_priority);
4108 bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_priority);
4109
4110 qos_scn->old_qos_attr.qos_flow_id =
Jing Huangba816ea2010-10-18 17:10:50 -07004111 be32_to_cpu(qos_scn->old_qos_attr.qos_flow_id);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004112 qos_scn->new_qos_attr.qos_flow_id =
Jing Huangba816ea2010-10-18 17:10:50 -07004113 be32_to_cpu(qos_scn->new_qos_attr.qos_flow_id);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004114
4115 if (qos_scn->old_qos_attr.qos_flow_id !=
4116 qos_scn->new_qos_attr.qos_flow_id)
4117 bfa_cb_rport_qos_scn_flowid(rp->rport_drv,
4118 qos_scn->old_qos_attr,
4119 qos_scn->new_qos_attr);
4120 if (qos_scn->old_qos_attr.qos_priority !=
4121 qos_scn->new_qos_attr.qos_priority)
4122 bfa_cb_rport_qos_scn_prio(rp->rport_drv,
4123 qos_scn->old_qos_attr,
4124 qos_scn->new_qos_attr);
4125 break;
4126
4127 default:
4128 bfa_stats(rp, sm_on_unexp);
4129 bfa_sm_fault(rp->bfa, event);
4130 }
4131}
4132
Jing Huang5fbe25c2010-10-18 17:17:23 -07004133/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004134 * Firmware rport is being deleted - awaiting f/w response.
4135 */
4136static void
4137bfa_rport_sm_fwdelete(struct bfa_rport_s *rp, enum bfa_rport_event event)
4138{
4139 bfa_trc(rp->bfa, rp->rport_tag);
4140 bfa_trc(rp->bfa, event);
4141
4142 switch (event) {
4143 case BFA_RPORT_SM_FWRSP:
4144 bfa_stats(rp, sm_fwd_rsp);
4145 bfa_sm_set_state(rp, bfa_rport_sm_offline);
4146 bfa_rport_offline_cb(rp);
4147 break;
4148
4149 case BFA_RPORT_SM_DELETE:
4150 bfa_stats(rp, sm_fwd_del);
4151 bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4152 break;
4153
4154 case BFA_RPORT_SM_HWFAIL:
4155 bfa_stats(rp, sm_fwd_hwf);
4156 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4157 bfa_rport_offline_cb(rp);
4158 break;
4159
4160 default:
4161 bfa_stats(rp, sm_fwd_unexp);
4162 bfa_sm_fault(rp->bfa, event);
4163 }
4164}
4165
4166static void
4167bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4168{
4169 bfa_trc(rp->bfa, rp->rport_tag);
4170 bfa_trc(rp->bfa, event);
4171
4172 switch (event) {
4173 case BFA_RPORT_SM_QRESUME:
4174 bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4175 bfa_rport_send_fwdelete(rp);
4176 break;
4177
4178 case BFA_RPORT_SM_DELETE:
4179 bfa_stats(rp, sm_fwd_del);
4180 bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4181 break;
4182
4183 case BFA_RPORT_SM_HWFAIL:
4184 bfa_stats(rp, sm_fwd_hwf);
4185 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4186 bfa_reqq_wcancel(&rp->reqq_wait);
4187 bfa_rport_offline_cb(rp);
4188 break;
4189
4190 default:
4191 bfa_stats(rp, sm_fwd_unexp);
4192 bfa_sm_fault(rp->bfa, event);
4193 }
4194}
4195
Jing Huang5fbe25c2010-10-18 17:17:23 -07004196/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004197 * Offline state.
4198 */
4199static void
4200bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event)
4201{
4202 bfa_trc(rp->bfa, rp->rport_tag);
4203 bfa_trc(rp->bfa, event);
4204
4205 switch (event) {
4206 case BFA_RPORT_SM_DELETE:
4207 bfa_stats(rp, sm_off_del);
4208 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4209 bfa_rport_free(rp);
4210 break;
4211
4212 case BFA_RPORT_SM_ONLINE:
4213 bfa_stats(rp, sm_off_on);
4214 if (bfa_rport_send_fwcreate(rp))
4215 bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4216 else
4217 bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4218 break;
4219
4220 case BFA_RPORT_SM_HWFAIL:
4221 bfa_stats(rp, sm_off_hwf);
4222 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4223 break;
4224
4225 default:
4226 bfa_stats(rp, sm_off_unexp);
4227 bfa_sm_fault(rp->bfa, event);
4228 }
4229}
4230
Jing Huang5fbe25c2010-10-18 17:17:23 -07004231/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004232 * Rport is deleted, waiting for firmware response to delete.
4233 */
4234static void
4235bfa_rport_sm_deleting(struct bfa_rport_s *rp, enum bfa_rport_event event)
4236{
4237 bfa_trc(rp->bfa, rp->rport_tag);
4238 bfa_trc(rp->bfa, event);
4239
4240 switch (event) {
4241 case BFA_RPORT_SM_FWRSP:
4242 bfa_stats(rp, sm_del_fwrsp);
4243 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4244 bfa_rport_free(rp);
4245 break;
4246
4247 case BFA_RPORT_SM_HWFAIL:
4248 bfa_stats(rp, sm_del_hwf);
4249 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4250 bfa_rport_free(rp);
4251 break;
4252
4253 default:
4254 bfa_sm_fault(rp->bfa, event);
4255 }
4256}
4257
4258static void
4259bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4260{
4261 bfa_trc(rp->bfa, rp->rport_tag);
4262 bfa_trc(rp->bfa, event);
4263
4264 switch (event) {
4265 case BFA_RPORT_SM_QRESUME:
4266 bfa_stats(rp, sm_del_fwrsp);
4267 bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4268 bfa_rport_send_fwdelete(rp);
4269 break;
4270
4271 case BFA_RPORT_SM_HWFAIL:
4272 bfa_stats(rp, sm_del_hwf);
4273 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4274 bfa_reqq_wcancel(&rp->reqq_wait);
4275 bfa_rport_free(rp);
4276 break;
4277
4278 default:
4279 bfa_sm_fault(rp->bfa, event);
4280 }
4281}
4282
Jing Huang5fbe25c2010-10-18 17:17:23 -07004283/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004284 * Waiting for rport create response from firmware. A delete is pending.
4285 */
4286static void
4287bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
4288 enum bfa_rport_event event)
4289{
4290 bfa_trc(rp->bfa, rp->rport_tag);
4291 bfa_trc(rp->bfa, event);
4292
4293 switch (event) {
4294 case BFA_RPORT_SM_FWRSP:
4295 bfa_stats(rp, sm_delp_fwrsp);
4296 if (bfa_rport_send_fwdelete(rp))
4297 bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4298 else
4299 bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4300 break;
4301
4302 case BFA_RPORT_SM_HWFAIL:
4303 bfa_stats(rp, sm_delp_hwf);
4304 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4305 bfa_rport_free(rp);
4306 break;
4307
4308 default:
4309 bfa_stats(rp, sm_delp_unexp);
4310 bfa_sm_fault(rp->bfa, event);
4311 }
4312}
4313
Jing Huang5fbe25c2010-10-18 17:17:23 -07004314/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004315 * Waiting for rport create response from firmware. Rport offline is pending.
4316 */
4317static void
4318bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
4319 enum bfa_rport_event event)
4320{
4321 bfa_trc(rp->bfa, rp->rport_tag);
4322 bfa_trc(rp->bfa, event);
4323
4324 switch (event) {
4325 case BFA_RPORT_SM_FWRSP:
4326 bfa_stats(rp, sm_offp_fwrsp);
4327 if (bfa_rport_send_fwdelete(rp))
4328 bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4329 else
4330 bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
4331 break;
4332
4333 case BFA_RPORT_SM_DELETE:
4334 bfa_stats(rp, sm_offp_del);
4335 bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
4336 break;
4337
4338 case BFA_RPORT_SM_HWFAIL:
4339 bfa_stats(rp, sm_offp_hwf);
4340 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4341 break;
4342
4343 default:
4344 bfa_stats(rp, sm_offp_unexp);
4345 bfa_sm_fault(rp->bfa, event);
4346 }
4347}
4348
Jing Huang5fbe25c2010-10-18 17:17:23 -07004349/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004350 * IOC h/w failed.
4351 */
4352static void
4353bfa_rport_sm_iocdisable(struct bfa_rport_s *rp, enum bfa_rport_event event)
4354{
4355 bfa_trc(rp->bfa, rp->rport_tag);
4356 bfa_trc(rp->bfa, event);
4357
4358 switch (event) {
4359 case BFA_RPORT_SM_OFFLINE:
4360 bfa_stats(rp, sm_iocd_off);
4361 bfa_rport_offline_cb(rp);
4362 break;
4363
4364 case BFA_RPORT_SM_DELETE:
4365 bfa_stats(rp, sm_iocd_del);
4366 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4367 bfa_rport_free(rp);
4368 break;
4369
4370 case BFA_RPORT_SM_ONLINE:
4371 bfa_stats(rp, sm_iocd_on);
4372 if (bfa_rport_send_fwcreate(rp))
4373 bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4374 else
4375 bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4376 break;
4377
4378 case BFA_RPORT_SM_HWFAIL:
4379 break;
4380
4381 default:
4382 bfa_stats(rp, sm_iocd_unexp);
4383 bfa_sm_fault(rp->bfa, event);
4384 }
4385}
4386
4387
4388
Jing Huang5fbe25c2010-10-18 17:17:23 -07004389/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004390 * bfa_rport_private BFA rport private functions
4391 */
4392
4393static void
4394__bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete)
4395{
4396 struct bfa_rport_s *rp = cbarg;
4397
4398 if (complete)
4399 bfa_cb_rport_online(rp->rport_drv);
4400}
4401
4402static void
4403__bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete)
4404{
4405 struct bfa_rport_s *rp = cbarg;
4406
4407 if (complete)
4408 bfa_cb_rport_offline(rp->rport_drv);
4409}
4410
4411static void
4412bfa_rport_qresume(void *cbarg)
4413{
4414 struct bfa_rport_s *rp = cbarg;
4415
4416 bfa_sm_send_event(rp, BFA_RPORT_SM_QRESUME);
4417}
4418
4419static void
4420bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
4421 u32 *dm_len)
4422{
4423 if (cfg->fwcfg.num_rports < BFA_RPORT_MIN)
4424 cfg->fwcfg.num_rports = BFA_RPORT_MIN;
4425
4426 *km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s);
4427}
4428
4429static void
4430bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
4431 struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
4432{
4433 struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
4434 struct bfa_rport_s *rp;
4435 u16 i;
4436
4437 INIT_LIST_HEAD(&mod->rp_free_q);
4438 INIT_LIST_HEAD(&mod->rp_active_q);
Krishna Gudipati3fd45982011-06-24 20:24:08 -07004439 INIT_LIST_HEAD(&mod->rp_unused_q);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004440
4441 rp = (struct bfa_rport_s *) bfa_meminfo_kva(meminfo);
4442 mod->rps_list = rp;
4443 mod->num_rports = cfg->fwcfg.num_rports;
4444
Jing Huangd4b671c2010-12-26 21:46:35 -08004445 WARN_ON(!mod->num_rports ||
4446 (mod->num_rports & (mod->num_rports - 1)));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004447
4448 for (i = 0; i < mod->num_rports; i++, rp++) {
Jing Huang6a18b162010-10-18 17:08:54 -07004449 memset(rp, 0, sizeof(struct bfa_rport_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004450 rp->bfa = bfa;
4451 rp->rport_tag = i;
4452 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4453
Jing Huang5fbe25c2010-10-18 17:17:23 -07004454 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004455 * - is unused
4456 */
4457 if (i)
4458 list_add_tail(&rp->qe, &mod->rp_free_q);
4459
4460 bfa_reqq_winit(&rp->reqq_wait, bfa_rport_qresume, rp);
4461 }
4462
Jing Huang5fbe25c2010-10-18 17:17:23 -07004463 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004464 * consume memory
4465 */
4466 bfa_meminfo_kva(meminfo) = (u8 *) rp;
4467}
4468
4469static void
4470bfa_rport_detach(struct bfa_s *bfa)
4471{
4472}
4473
4474static void
4475bfa_rport_start(struct bfa_s *bfa)
4476{
4477}
4478
4479static void
4480bfa_rport_stop(struct bfa_s *bfa)
4481{
4482}
4483
4484static void
4485bfa_rport_iocdisable(struct bfa_s *bfa)
4486{
4487 struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
4488 struct bfa_rport_s *rport;
4489 struct list_head *qe, *qen;
4490
Krishna Gudipati3fd45982011-06-24 20:24:08 -07004491 /* Enqueue unused rport resources to free_q */
4492 list_splice_tail_init(&mod->rp_unused_q, &mod->rp_free_q);
4493
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004494 list_for_each_safe(qe, qen, &mod->rp_active_q) {
4495 rport = (struct bfa_rport_s *) qe;
4496 bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL);
4497 }
4498}
4499
4500static struct bfa_rport_s *
4501bfa_rport_alloc(struct bfa_rport_mod_s *mod)
4502{
4503 struct bfa_rport_s *rport;
4504
4505 bfa_q_deq(&mod->rp_free_q, &rport);
4506 if (rport)
4507 list_add_tail(&rport->qe, &mod->rp_active_q);
4508
4509 return rport;
4510}
4511
4512static void
4513bfa_rport_free(struct bfa_rport_s *rport)
4514{
4515 struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa);
4516
Jing Huangd4b671c2010-12-26 21:46:35 -08004517 WARN_ON(!bfa_q_is_on_q(&mod->rp_active_q, rport));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004518 list_del(&rport->qe);
4519 list_add_tail(&rport->qe, &mod->rp_free_q);
4520}
4521
4522static bfa_boolean_t
4523bfa_rport_send_fwcreate(struct bfa_rport_s *rp)
4524{
4525 struct bfi_rport_create_req_s *m;
4526
Jing Huang5fbe25c2010-10-18 17:17:23 -07004527 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004528 * check for room in queue to send request now
4529 */
4530 m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4531 if (!m) {
4532 bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
4533 return BFA_FALSE;
4534 }
4535
4536 bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ,
Krishna Gudipati3fd45982011-06-24 20:24:08 -07004537 bfa_fn_lpu(rp->bfa));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004538 m->bfa_handle = rp->rport_tag;
Jing Huangba816ea2010-10-18 17:10:50 -07004539 m->max_frmsz = cpu_to_be16(rp->rport_info.max_frmsz);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004540 m->pid = rp->rport_info.pid;
Krishna Gudipati3fd45982011-06-24 20:24:08 -07004541 m->lp_fwtag = bfa_lps_get_fwtag(rp->bfa, (u8)rp->rport_info.lp_tag);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004542 m->local_pid = rp->rport_info.local_pid;
4543 m->fc_class = rp->rport_info.fc_class;
4544 m->vf_en = rp->rport_info.vf_en;
4545 m->vf_id = rp->rport_info.vf_id;
4546 m->cisc = rp->rport_info.cisc;
4547
Jing Huang5fbe25c2010-10-18 17:17:23 -07004548 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004549 * queue I/O message to firmware
4550 */
Krishna Gudipati3fd45982011-06-24 20:24:08 -07004551 bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004552 return BFA_TRUE;
4553}
4554
4555static bfa_boolean_t
4556bfa_rport_send_fwdelete(struct bfa_rport_s *rp)
4557{
4558 struct bfi_rport_delete_req_s *m;
4559
Jing Huang5fbe25c2010-10-18 17:17:23 -07004560 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004561 * check for room in queue to send request now
4562 */
4563 m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4564 if (!m) {
4565 bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
4566 return BFA_FALSE;
4567 }
4568
4569 bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ,
Krishna Gudipati3fd45982011-06-24 20:24:08 -07004570 bfa_fn_lpu(rp->bfa));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004571 m->fw_handle = rp->fw_handle;
4572
Jing Huang5fbe25c2010-10-18 17:17:23 -07004573 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004574 * queue I/O message to firmware
4575 */
Krishna Gudipati3fd45982011-06-24 20:24:08 -07004576 bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004577 return BFA_TRUE;
4578}
4579
4580static bfa_boolean_t
4581bfa_rport_send_fwspeed(struct bfa_rport_s *rp)
4582{
4583 struct bfa_rport_speed_req_s *m;
4584
Jing Huang5fbe25c2010-10-18 17:17:23 -07004585 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004586 * check for room in queue to send request now
4587 */
4588 m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4589 if (!m) {
4590 bfa_trc(rp->bfa, rp->rport_info.speed);
4591 return BFA_FALSE;
4592 }
4593
4594 bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ,
Krishna Gudipati3fd45982011-06-24 20:24:08 -07004595 bfa_fn_lpu(rp->bfa));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004596 m->fw_handle = rp->fw_handle;
4597 m->speed = (u8)rp->rport_info.speed;
4598
Jing Huang5fbe25c2010-10-18 17:17:23 -07004599 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004600 * queue I/O message to firmware
4601 */
Krishna Gudipati3fd45982011-06-24 20:24:08 -07004602 bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004603 return BFA_TRUE;
4604}
4605
4606
4607
Jing Huang5fbe25c2010-10-18 17:17:23 -07004608/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004609 * bfa_rport_public
4610 */
4611
Jing Huang5fbe25c2010-10-18 17:17:23 -07004612/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004613 * Rport interrupt processing.
4614 */
4615void
4616bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
4617{
4618 union bfi_rport_i2h_msg_u msg;
4619 struct bfa_rport_s *rp;
4620
4621 bfa_trc(bfa, m->mhdr.msg_id);
4622
4623 msg.msg = m;
4624
4625 switch (m->mhdr.msg_id) {
4626 case BFI_RPORT_I2H_CREATE_RSP:
4627 rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);
4628 rp->fw_handle = msg.create_rsp->fw_handle;
4629 rp->qos_attr = msg.create_rsp->qos_attr;
Jing Huangd4b671c2010-12-26 21:46:35 -08004630 WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004631 bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
4632 break;
4633
4634 case BFI_RPORT_I2H_DELETE_RSP:
4635 rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle);
Jing Huangd4b671c2010-12-26 21:46:35 -08004636 WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004637 bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
4638 break;
4639
4640 case BFI_RPORT_I2H_QOS_SCN:
4641 rp = BFA_RPORT_FROM_TAG(bfa, msg.qos_scn_evt->bfa_handle);
4642 rp->event_arg.fw_msg = msg.qos_scn_evt;
4643 bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);
4644 break;
4645
4646 default:
4647 bfa_trc(bfa, m->mhdr.msg_id);
Jing Huangd4b671c2010-12-26 21:46:35 -08004648 WARN_ON(1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004649 }
4650}
4651
Krishna Gudipati3fd45982011-06-24 20:24:08 -07004652void
4653bfa_rport_res_recfg(struct bfa_s *bfa, u16 num_rport_fw)
4654{
4655 struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
4656 struct list_head *qe;
4657 int i;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004658
Krishna Gudipati3fd45982011-06-24 20:24:08 -07004659 for (i = 0; i < (mod->num_rports - num_rport_fw); i++) {
4660 bfa_q_deq_tail(&mod->rp_free_q, &qe);
4661 list_add_tail(qe, &mod->rp_unused_q);
4662 }
4663}
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004664
Jing Huang5fbe25c2010-10-18 17:17:23 -07004665/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004666 * bfa_rport_api
4667 */
4668
4669struct bfa_rport_s *
4670bfa_rport_create(struct bfa_s *bfa, void *rport_drv)
4671{
4672 struct bfa_rport_s *rp;
4673
4674 rp = bfa_rport_alloc(BFA_RPORT_MOD(bfa));
4675
4676 if (rp == NULL)
4677 return NULL;
4678
4679 rp->bfa = bfa;
4680 rp->rport_drv = rport_drv;
Maggie Zhangf7f73812010-12-09 19:08:43 -08004681 memset(&rp->stats, 0, sizeof(rp->stats));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004682
Jing Huangd4b671c2010-12-26 21:46:35 -08004683 WARN_ON(!bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004684 bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);
4685
4686 return rp;
4687}
4688
4689void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004690bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)
4691{
Jing Huangd4b671c2010-12-26 21:46:35 -08004692 WARN_ON(rport_info->max_frmsz == 0);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004693
Jing Huang5fbe25c2010-10-18 17:17:23 -07004694 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004695 * Some JBODs are seen to be not setting PDU size correctly in PLOGI
4696 * responses. Default to minimum size.
4697 */
4698 if (rport_info->max_frmsz == 0) {
4699 bfa_trc(rport->bfa, rport->rport_tag);
4700 rport_info->max_frmsz = FC_MIN_PDUSZ;
4701 }
4702
Jing Huang6a18b162010-10-18 17:08:54 -07004703 rport->rport_info = *rport_info;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004704 bfa_sm_send_event(rport, BFA_RPORT_SM_ONLINE);
4705}
4706
4707void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004708bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed)
4709{
Jing Huangd4b671c2010-12-26 21:46:35 -08004710 WARN_ON(speed == 0);
4711 WARN_ON(speed == BFA_PORT_SPEED_AUTO);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004712
4713 rport->rport_info.speed = speed;
4714 bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
4715}
4716
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004717
Jing Huang5fbe25c2010-10-18 17:17:23 -07004718/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004719 * SGPG related functions
4720 */
4721
Jing Huang5fbe25c2010-10-18 17:17:23 -07004722/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004723 * Compute and return memory needed by FCP(im) module.
4724 */
4725static void
4726bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
4727 u32 *dm_len)
4728{
4729 if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)
4730 cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
4731
4732 *km_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfa_sgpg_s);
4733 *dm_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfi_sgpg_s);
4734}
4735
4736
4737static void
4738bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
4739 struct bfa_meminfo_s *minfo, struct bfa_pcidev_s *pcidev)
4740{
4741 struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
4742 int i;
4743 struct bfa_sgpg_s *hsgpg;
4744 struct bfi_sgpg_s *sgpg;
4745 u64 align_len;
4746
4747 union {
4748 u64 pa;
4749 union bfi_addr_u addr;
4750 } sgpg_pa, sgpg_pa_tmp;
4751
4752 INIT_LIST_HEAD(&mod->sgpg_q);
4753 INIT_LIST_HEAD(&mod->sgpg_wait_q);
4754
4755 bfa_trc(bfa, cfg->drvcfg.num_sgpgs);
4756
4757 mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
4758 mod->sgpg_arr_pa = bfa_meminfo_dma_phys(minfo);
4759 align_len = (BFA_SGPG_ROUNDUP(mod->sgpg_arr_pa) - mod->sgpg_arr_pa);
4760 mod->sgpg_arr_pa += align_len;
4761 mod->hsgpg_arr = (struct bfa_sgpg_s *) (bfa_meminfo_kva(minfo) +
4762 align_len);
4763 mod->sgpg_arr = (struct bfi_sgpg_s *) (bfa_meminfo_dma_virt(minfo) +
4764 align_len);
4765
4766 hsgpg = mod->hsgpg_arr;
4767 sgpg = mod->sgpg_arr;
4768 sgpg_pa.pa = mod->sgpg_arr_pa;
4769 mod->free_sgpgs = mod->num_sgpgs;
4770
Jing Huangd4b671c2010-12-26 21:46:35 -08004771 WARN_ON(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004772
4773 for (i = 0; i < mod->num_sgpgs; i++) {
Jing Huang6a18b162010-10-18 17:08:54 -07004774 memset(hsgpg, 0, sizeof(*hsgpg));
4775 memset(sgpg, 0, sizeof(*sgpg));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004776
4777 hsgpg->sgpg = sgpg;
4778 sgpg_pa_tmp.pa = bfa_sgaddr_le(sgpg_pa.pa);
4779 hsgpg->sgpg_pa = sgpg_pa_tmp.addr;
4780 list_add_tail(&hsgpg->qe, &mod->sgpg_q);
4781
4782 hsgpg++;
4783 sgpg++;
4784 sgpg_pa.pa += sizeof(struct bfi_sgpg_s);
4785 }
4786
4787 bfa_meminfo_kva(minfo) = (u8 *) hsgpg;
4788 bfa_meminfo_dma_virt(minfo) = (u8 *) sgpg;
4789 bfa_meminfo_dma_phys(minfo) = sgpg_pa.pa;
4790}
4791
4792static void
4793bfa_sgpg_detach(struct bfa_s *bfa)
4794{
4795}
4796
4797static void
4798bfa_sgpg_start(struct bfa_s *bfa)
4799{
4800}
4801
4802static void
4803bfa_sgpg_stop(struct bfa_s *bfa)
4804{
4805}
4806
4807static void
4808bfa_sgpg_iocdisable(struct bfa_s *bfa)
4809{
4810}
4811
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004812bfa_status_t
4813bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
4814{
4815 struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
4816 struct bfa_sgpg_s *hsgpg;
4817 int i;
4818
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004819 if (mod->free_sgpgs < nsgpgs)
4820 return BFA_STATUS_ENOMEM;
4821
4822 for (i = 0; i < nsgpgs; i++) {
4823 bfa_q_deq(&mod->sgpg_q, &hsgpg);
Jing Huangd4b671c2010-12-26 21:46:35 -08004824 WARN_ON(!hsgpg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004825 list_add_tail(&hsgpg->qe, sgpg_q);
4826 }
4827
4828 mod->free_sgpgs -= nsgpgs;
4829 return BFA_STATUS_OK;
4830}
4831
4832void
4833bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)
4834{
4835 struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
4836 struct bfa_sgpg_wqe_s *wqe;
4837
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004838 mod->free_sgpgs += nsgpg;
Jing Huangd4b671c2010-12-26 21:46:35 -08004839 WARN_ON(mod->free_sgpgs > mod->num_sgpgs);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004840
4841 list_splice_tail_init(sgpg_q, &mod->sgpg_q);
4842
4843 if (list_empty(&mod->sgpg_wait_q))
4844 return;
4845
Jing Huang5fbe25c2010-10-18 17:17:23 -07004846 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004847 * satisfy as many waiting requests as possible
4848 */
4849 do {
4850 wqe = bfa_q_first(&mod->sgpg_wait_q);
4851 if (mod->free_sgpgs < wqe->nsgpg)
4852 nsgpg = mod->free_sgpgs;
4853 else
4854 nsgpg = wqe->nsgpg;
4855 bfa_sgpg_malloc(bfa, &wqe->sgpg_q, nsgpg);
4856 wqe->nsgpg -= nsgpg;
4857 if (wqe->nsgpg == 0) {
4858 list_del(&wqe->qe);
4859 wqe->cbfn(wqe->cbarg);
4860 }
4861 } while (mod->free_sgpgs && !list_empty(&mod->sgpg_wait_q));
4862}
4863
4864void
4865bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)
4866{
4867 struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
4868
Jing Huangd4b671c2010-12-26 21:46:35 -08004869 WARN_ON(nsgpg <= 0);
4870 WARN_ON(nsgpg <= mod->free_sgpgs);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004871
4872 wqe->nsgpg_total = wqe->nsgpg = nsgpg;
4873
Jing Huang5fbe25c2010-10-18 17:17:23 -07004874 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004875 * allocate any left to this one first
4876 */
4877 if (mod->free_sgpgs) {
Jing Huang5fbe25c2010-10-18 17:17:23 -07004878 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004879 * no one else is waiting for SGPG
4880 */
Jing Huangd4b671c2010-12-26 21:46:35 -08004881 WARN_ON(!list_empty(&mod->sgpg_wait_q));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004882 list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);
4883 wqe->nsgpg -= mod->free_sgpgs;
4884 mod->free_sgpgs = 0;
4885 }
4886
4887 list_add_tail(&wqe->qe, &mod->sgpg_wait_q);
4888}
4889
4890void
4891bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)
4892{
4893 struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
4894
Jing Huangd4b671c2010-12-26 21:46:35 -08004895 WARN_ON(!bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004896 list_del(&wqe->qe);
4897
4898 if (wqe->nsgpg_total != wqe->nsgpg)
4899 bfa_sgpg_mfree(bfa, &wqe->sgpg_q,
4900 wqe->nsgpg_total - wqe->nsgpg);
4901}
4902
4903void
4904bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, void (*cbfn) (void *cbarg),
4905 void *cbarg)
4906{
4907 INIT_LIST_HEAD(&wqe->sgpg_q);
4908 wqe->cbfn = cbfn;
4909 wqe->cbarg = cbarg;
4910}
4911
Jing Huang5fbe25c2010-10-18 17:17:23 -07004912/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004913 * UF related functions
4914 */
4915/*
4916 *****************************************************************************
4917 * Internal functions
4918 *****************************************************************************
4919 */
4920static void
4921__bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)
4922{
4923 struct bfa_uf_s *uf = cbarg;
4924 struct bfa_uf_mod_s *ufm = BFA_UF_MOD(uf->bfa);
4925
4926 if (complete)
4927 ufm->ufrecv(ufm->cbarg, uf);
4928}
4929
4930static void
4931claim_uf_pbs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
4932{
4933 u32 uf_pb_tot_sz;
4934
4935 ufm->uf_pbs_kva = (struct bfa_uf_buf_s *) bfa_meminfo_dma_virt(mi);
4936 ufm->uf_pbs_pa = bfa_meminfo_dma_phys(mi);
4937 uf_pb_tot_sz = BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * ufm->num_ufs),
4938 BFA_DMA_ALIGN_SZ);
4939
4940 bfa_meminfo_dma_virt(mi) += uf_pb_tot_sz;
4941 bfa_meminfo_dma_phys(mi) += uf_pb_tot_sz;
4942
Jing Huang6a18b162010-10-18 17:08:54 -07004943 memset((void *)ufm->uf_pbs_kva, 0, uf_pb_tot_sz);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004944}
4945
4946static void
4947claim_uf_post_msgs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
4948{
4949 struct bfi_uf_buf_post_s *uf_bp_msg;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004950 u16 i;
4951 u16 buf_len;
4952
4953 ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_meminfo_kva(mi);
4954 uf_bp_msg = ufm->uf_buf_posts;
4955
4956 for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;
4957 i++, uf_bp_msg++) {
Jing Huang6a18b162010-10-18 17:08:54 -07004958 memset(uf_bp_msg, 0, sizeof(struct bfi_uf_buf_post_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004959
4960 uf_bp_msg->buf_tag = i;
4961 buf_len = sizeof(struct bfa_uf_buf_s);
Jing Huangba816ea2010-10-18 17:10:50 -07004962 uf_bp_msg->buf_len = cpu_to_be16(buf_len);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004963 bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST,
Krishna Gudipati3fd45982011-06-24 20:24:08 -07004964 bfa_fn_lpu(ufm->bfa));
Krishna Gudipati85ce9282011-06-13 15:39:36 -07004965 bfa_alen_set(&uf_bp_msg->alen, buf_len, ufm_pbs_pa(ufm, i));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004966 }
4967
Jing Huang5fbe25c2010-10-18 17:17:23 -07004968 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004969 * advance pointer beyond consumed memory
4970 */
4971 bfa_meminfo_kva(mi) = (u8 *) uf_bp_msg;
4972}
4973
4974static void
4975claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
4976{
4977 u16 i;
4978 struct bfa_uf_s *uf;
4979
4980 /*
4981 * Claim block of memory for UF list
4982 */
4983 ufm->uf_list = (struct bfa_uf_s *) bfa_meminfo_kva(mi);
4984
4985 /*
4986 * Initialize UFs and queue it in UF free queue
4987 */
4988 for (i = 0, uf = ufm->uf_list; i < ufm->num_ufs; i++, uf++) {
Jing Huang6a18b162010-10-18 17:08:54 -07004989 memset(uf, 0, sizeof(struct bfa_uf_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004990 uf->bfa = ufm->bfa;
4991 uf->uf_tag = i;
4992 uf->pb_len = sizeof(struct bfa_uf_buf_s);
4993 uf->buf_kva = (void *)&ufm->uf_pbs_kva[i];
4994 uf->buf_pa = ufm_pbs_pa(ufm, i);
4995 list_add_tail(&uf->qe, &ufm->uf_free_q);
4996 }
4997
Jing Huang5fbe25c2010-10-18 17:17:23 -07004998 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004999 * advance memory pointer
5000 */
5001 bfa_meminfo_kva(mi) = (u8 *) uf;
5002}
5003
5004static void
5005uf_mem_claim(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
5006{
5007 claim_uf_pbs(ufm, mi);
5008 claim_ufs(ufm, mi);
5009 claim_uf_post_msgs(ufm, mi);
5010}
5011
5012static void
5013bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
5014{
5015 u32 num_ufs = cfg->fwcfg.num_uf_bufs;
5016
5017 /*
5018 * dma-able memory for UF posted bufs
5019 */
5020 *dm_len += BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * num_ufs),
5021 BFA_DMA_ALIGN_SZ);
5022
5023 /*
5024 * kernel Virtual memory for UFs and UF buf post msg copies
5025 */
5026 *ndm_len += sizeof(struct bfa_uf_s) * num_ufs;
5027 *ndm_len += sizeof(struct bfi_uf_buf_post_s) * num_ufs;
5028}
5029
5030static void
5031bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
5032 struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
5033{
5034 struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5035
Jing Huang6a18b162010-10-18 17:08:54 -07005036 memset(ufm, 0, sizeof(struct bfa_uf_mod_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005037 ufm->bfa = bfa;
5038 ufm->num_ufs = cfg->fwcfg.num_uf_bufs;
5039 INIT_LIST_HEAD(&ufm->uf_free_q);
5040 INIT_LIST_HEAD(&ufm->uf_posted_q);
Krishna Gudipati3fd45982011-06-24 20:24:08 -07005041 INIT_LIST_HEAD(&ufm->uf_unused_q);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005042
5043 uf_mem_claim(ufm, meminfo);
5044}
5045
5046static void
5047bfa_uf_detach(struct bfa_s *bfa)
5048{
5049}
5050
5051static struct bfa_uf_s *
5052bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
5053{
5054 struct bfa_uf_s *uf;
5055
5056 bfa_q_deq(&uf_mod->uf_free_q, &uf);
5057 return uf;
5058}
5059
5060static void
5061bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf)
5062{
5063 list_add_tail(&uf->qe, &uf_mod->uf_free_q);
5064}
5065
5066static bfa_status_t
5067bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
5068{
5069 struct bfi_uf_buf_post_s *uf_post_msg;
5070
5071 uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP);
5072 if (!uf_post_msg)
5073 return BFA_STATUS_FAILED;
5074
Jing Huang6a18b162010-10-18 17:08:54 -07005075 memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005076 sizeof(struct bfi_uf_buf_post_s));
Krishna Gudipati3fd45982011-06-24 20:24:08 -07005077 bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP, uf_post_msg->mh);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005078
5079 bfa_trc(ufm->bfa, uf->uf_tag);
5080
5081 list_add_tail(&uf->qe, &ufm->uf_posted_q);
5082 return BFA_STATUS_OK;
5083}
5084
5085static void
5086bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod)
5087{
5088 struct bfa_uf_s *uf;
5089
5090 while ((uf = bfa_uf_get(uf_mod)) != NULL) {
5091 if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK)
5092 break;
5093 }
5094}
5095
5096static void
5097uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
5098{
5099 struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5100 u16 uf_tag = m->buf_tag;
5101 struct bfa_uf_buf_s *uf_buf = &ufm->uf_pbs_kva[uf_tag];
5102 struct bfa_uf_s *uf = &ufm->uf_list[uf_tag];
5103 u8 *buf = &uf_buf->d[0];
5104 struct fchs_s *fchs;
5105
Jing Huangba816ea2010-10-18 17:10:50 -07005106 m->frm_len = be16_to_cpu(m->frm_len);
5107 m->xfr_len = be16_to_cpu(m->xfr_len);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005108
5109 fchs = (struct fchs_s *)uf_buf;
5110
5111 list_del(&uf->qe); /* dequeue from posted queue */
5112
5113 uf->data_ptr = buf;
5114 uf->data_len = m->xfr_len;
5115
Jing Huangd4b671c2010-12-26 21:46:35 -08005116 WARN_ON(uf->data_len < sizeof(struct fchs_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005117
5118 if (uf->data_len == sizeof(struct fchs_s)) {
5119 bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,
5120 uf->data_len, (struct fchs_s *)buf);
5121 } else {
5122 u32 pld_w0 = *((u32 *) (buf + sizeof(struct fchs_s)));
5123 bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_UF,
5124 BFA_PL_EID_RX, uf->data_len,
5125 (struct fchs_s *)buf, pld_w0);
5126 }
5127
5128 if (bfa->fcs)
5129 __bfa_cb_uf_recv(uf, BFA_TRUE);
5130 else
5131 bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);
5132}
5133
5134static void
5135bfa_uf_stop(struct bfa_s *bfa)
5136{
5137}
5138
5139static void
5140bfa_uf_iocdisable(struct bfa_s *bfa)
5141{
5142 struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5143 struct bfa_uf_s *uf;
5144 struct list_head *qe, *qen;
5145
Krishna Gudipati3fd45982011-06-24 20:24:08 -07005146 /* Enqueue unused uf resources to free_q */
5147 list_splice_tail_init(&ufm->uf_unused_q, &ufm->uf_free_q);
5148
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005149 list_for_each_safe(qe, qen, &ufm->uf_posted_q) {
5150 uf = (struct bfa_uf_s *) qe;
5151 list_del(&uf->qe);
5152 bfa_uf_put(ufm, uf);
5153 }
5154}
5155
5156static void
5157bfa_uf_start(struct bfa_s *bfa)
5158{
5159 bfa_uf_post_all(BFA_UF_MOD(bfa));
5160}
5161
Jing Huang5fbe25c2010-10-18 17:17:23 -07005162/*
Lucas De Marchi25985ed2011-03-30 22:57:33 -03005163 * Register handler for all unsolicted receive frames.
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005164 *
5165 * @param[in] bfa BFA instance
5166 * @param[in] ufrecv receive handler function
5167 * @param[in] cbarg receive handler arg
5168 */
5169void
5170bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg)
5171{
5172 struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5173
5174 ufm->ufrecv = ufrecv;
5175 ufm->cbarg = cbarg;
5176}
5177
Jing Huang5fbe25c2010-10-18 17:17:23 -07005178/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005179 * Free an unsolicited frame back to BFA.
5180 *
5181 * @param[in] uf unsolicited frame to be freed
5182 *
5183 * @return None
5184 */
5185void
5186bfa_uf_free(struct bfa_uf_s *uf)
5187{
5188 bfa_uf_put(BFA_UF_MOD(uf->bfa), uf);
5189 bfa_uf_post_all(BFA_UF_MOD(uf->bfa));
5190}
5191
5192
5193
Jing Huang5fbe25c2010-10-18 17:17:23 -07005194/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005195 * uf_pub BFA uf module public functions
5196 */
5197void
5198bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
5199{
5200 bfa_trc(bfa, msg->mhdr.msg_id);
5201
5202 switch (msg->mhdr.msg_id) {
5203 case BFI_UF_I2H_FRM_RCVD:
5204 uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg);
5205 break;
5206
5207 default:
5208 bfa_trc(bfa, msg->mhdr.msg_id);
Jing Huangd4b671c2010-12-26 21:46:35 -08005209 WARN_ON(1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005210 }
5211}
5212
Krishna Gudipati3fd45982011-06-24 20:24:08 -07005213void
5214bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw)
5215{
5216 struct bfa_uf_mod_s *mod = BFA_UF_MOD(bfa);
5217 struct list_head *qe;
5218 int i;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005219
Krishna Gudipati3fd45982011-06-24 20:24:08 -07005220 for (i = 0; i < (mod->num_ufs - num_uf_fw); i++) {
5221 bfa_q_deq_tail(&mod->uf_free_q, &qe);
5222 list_add_tail(qe, &mod->uf_unused_q);
5223 }
5224}