blob: 479ccbe901b53cc8a9686878a7ae831036b3b183 [file] [log] [blame]
Jing Huang7725ccf2009-09-23 17:46:15 -07001/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002 * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
Jing Huang7725ccf2009-09-23 17:46:15 -07003 * 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_fcs.h"
20#include "bfa_fcbuild.h"
21#include "bfa_fc.h"
Jing Huang7725ccf2009-09-23 17:46:15 -070022
23BFA_TRC_FILE(FCS, PORT);
24
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070025static void bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port,
26 struct fchs_s *rx_fchs, u8 reason_code,
27 u8 reason_code_expl);
28static void bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
29 struct fchs_s *rx_fchs, struct fc_logi_s *plogi);
30static void bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port);
31static void bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port);
32static void bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port);
33static void bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port);
34static void bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port);
35static void bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port);
36static void bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port,
Jing Huang7725ccf2009-09-23 17:46:15 -070037 struct fchs_s *rx_fchs,
38 struct fc_echo_s *echo, u16 len);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070039static void bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port,
Jing Huang7725ccf2009-09-23 17:46:15 -070040 struct fchs_s *rx_fchs,
41 struct fc_rnid_cmd_s *rnid, u16 len);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070042static void bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
Jing Huang7725ccf2009-09-23 17:46:15 -070043 struct fc_rnid_general_topology_data_s *gen_topo_data);
44
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070045static void bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port);
46static void bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port);
47static void bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port);
48
49static void bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);
50static void bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);
51static void bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port);
52
Jing Huang7725ccf2009-09-23 17:46:15 -070053static struct {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070054 void (*init) (struct bfa_fcs_lport_s *port);
55 void (*online) (struct bfa_fcs_lport_s *port);
56 void (*offline) (struct bfa_fcs_lport_s *port);
Jing Huang7725ccf2009-09-23 17:46:15 -070057} __port_action[] = {
58 {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070059 bfa_fcs_lport_unknown_init, bfa_fcs_lport_unknown_online,
60 bfa_fcs_lport_unknown_offline}, {
61 bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online,
62 bfa_fcs_lport_fab_offline}, {
63 bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online,
64 bfa_fcs_lport_n2n_offline},
65 };
Jing Huang7725ccf2009-09-23 17:46:15 -070066
Jing Huang5fbe25c2010-10-18 17:17:23 -070067/*
Jing Huang7725ccf2009-09-23 17:46:15 -070068 * fcs_port_sm FCS logical port state machine
69 */
70
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070071enum bfa_fcs_lport_event {
Jing Huang7725ccf2009-09-23 17:46:15 -070072 BFA_FCS_PORT_SM_CREATE = 1,
73 BFA_FCS_PORT_SM_ONLINE = 2,
74 BFA_FCS_PORT_SM_OFFLINE = 3,
75 BFA_FCS_PORT_SM_DELETE = 4,
76 BFA_FCS_PORT_SM_DELRPORT = 5,
Krishna Gudipatidd5aaf42011-06-13 15:51:24 -070077 BFA_FCS_PORT_SM_STOP = 6,
Jing Huang7725ccf2009-09-23 17:46:15 -070078};
79
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070080static void bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port,
81 enum bfa_fcs_lport_event event);
82static void bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
83 enum bfa_fcs_lport_event event);
84static void bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s *port,
85 enum bfa_fcs_lport_event event);
86static void bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port,
87 enum bfa_fcs_lport_event event);
88static void bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,
89 enum bfa_fcs_lport_event event);
Krishna Gudipatidd5aaf42011-06-13 15:51:24 -070090static void bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
91 enum bfa_fcs_lport_event event);
Jing Huang7725ccf2009-09-23 17:46:15 -070092
93static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070094bfa_fcs_lport_sm_uninit(
95 struct bfa_fcs_lport_s *port,
96 enum bfa_fcs_lport_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -070097{
98 bfa_trc(port->fcs, port->port_cfg.pwwn);
99 bfa_trc(port->fcs, event);
100
101 switch (event) {
102 case BFA_FCS_PORT_SM_CREATE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700103 bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
Jing Huang7725ccf2009-09-23 17:46:15 -0700104 break;
105
106 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800107 bfa_sm_fault(port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700108 }
109}
110
111static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700112bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
113 enum bfa_fcs_lport_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -0700114{
115 bfa_trc(port->fcs, port->port_cfg.pwwn);
116 bfa_trc(port->fcs, event);
117
118 switch (event) {
119 case BFA_FCS_PORT_SM_ONLINE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700120 bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
121 bfa_fcs_lport_online_actions(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700122 break;
123
124 case BFA_FCS_PORT_SM_DELETE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700125 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
126 bfa_fcs_lport_deleted(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700127 break;
128
Krishna Gudipatidd5aaf42011-06-13 15:51:24 -0700129 case BFA_FCS_PORT_SM_STOP:
130 /* If vport - send completion call back */
131 if (port->vport)
132 bfa_fcs_vport_stop_comp(port->vport);
133 break;
134
Jing Huang3e98cc02010-07-08 19:52:46 -0700135 case BFA_FCS_PORT_SM_OFFLINE:
136 break;
137
Jing Huang7725ccf2009-09-23 17:46:15 -0700138 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800139 bfa_sm_fault(port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700140 }
141}
142
143static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700144bfa_fcs_lport_sm_online(
145 struct bfa_fcs_lport_s *port,
146 enum bfa_fcs_lport_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -0700147{
148 struct bfa_fcs_rport_s *rport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700149 struct list_head *qe, *qen;
Jing Huang7725ccf2009-09-23 17:46:15 -0700150
151 bfa_trc(port->fcs, port->port_cfg.pwwn);
152 bfa_trc(port->fcs, event);
153
154 switch (event) {
155 case BFA_FCS_PORT_SM_OFFLINE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700156 bfa_sm_set_state(port, bfa_fcs_lport_sm_offline);
157 bfa_fcs_lport_offline_actions(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700158 break;
159
Krishna Gudipatidd5aaf42011-06-13 15:51:24 -0700160 case BFA_FCS_PORT_SM_STOP:
161 __port_action[port->fabric->fab_type].offline(port);
162
163 if (port->num_rports == 0) {
164 bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
165 /* If vport - send completion call back */
166 if (port->vport)
167 bfa_fcs_vport_stop_comp(port->vport);
168 } else {
169 bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
170 list_for_each_safe(qe, qen, &port->rport_q) {
171 rport = (struct bfa_fcs_rport_s *) qe;
172 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
173 }
174 }
175 break;
176
Jing Huang7725ccf2009-09-23 17:46:15 -0700177 case BFA_FCS_PORT_SM_DELETE:
178
179 __port_action[port->fabric->fab_type].offline(port);
180
181 if (port->num_rports == 0) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700182 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
183 bfa_fcs_lport_deleted(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700184 } else {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700185 bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
Jing Huang7725ccf2009-09-23 17:46:15 -0700186 list_for_each_safe(qe, qen, &port->rport_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700187 rport = (struct bfa_fcs_rport_s *) qe;
Maggie Zhangf7f738122010-12-09 19:08:43 -0800188 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
Jing Huang7725ccf2009-09-23 17:46:15 -0700189 }
190 }
191 break;
192
193 case BFA_FCS_PORT_SM_DELRPORT:
194 break;
195
196 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800197 bfa_sm_fault(port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700198 }
199}
200
201static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700202bfa_fcs_lport_sm_offline(
203 struct bfa_fcs_lport_s *port,
204 enum bfa_fcs_lport_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -0700205{
206 struct bfa_fcs_rport_s *rport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700207 struct list_head *qe, *qen;
Jing Huang7725ccf2009-09-23 17:46:15 -0700208
209 bfa_trc(port->fcs, port->port_cfg.pwwn);
210 bfa_trc(port->fcs, event);
211
212 switch (event) {
213 case BFA_FCS_PORT_SM_ONLINE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700214 bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
215 bfa_fcs_lport_online_actions(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700216 break;
217
Krishna Gudipatidd5aaf42011-06-13 15:51:24 -0700218 case BFA_FCS_PORT_SM_STOP:
219 if (port->num_rports == 0) {
220 bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
221 /* If vport - send completion call back */
222 if (port->vport)
223 bfa_fcs_vport_stop_comp(port->vport);
224 } else {
225 bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
226 list_for_each_safe(qe, qen, &port->rport_q) {
227 rport = (struct bfa_fcs_rport_s *) qe;
228 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
229 }
230 }
231 break;
232
Jing Huang7725ccf2009-09-23 17:46:15 -0700233 case BFA_FCS_PORT_SM_DELETE:
234 if (port->num_rports == 0) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700235 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
236 bfa_fcs_lport_deleted(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700237 } else {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700238 bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
Jing Huang7725ccf2009-09-23 17:46:15 -0700239 list_for_each_safe(qe, qen, &port->rport_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700240 rport = (struct bfa_fcs_rport_s *) qe;
Maggie Zhangf7f738122010-12-09 19:08:43 -0800241 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
Jing Huang7725ccf2009-09-23 17:46:15 -0700242 }
243 }
244 break;
245
246 case BFA_FCS_PORT_SM_DELRPORT:
247 case BFA_FCS_PORT_SM_OFFLINE:
248 break;
249
250 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800251 bfa_sm_fault(port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700252 }
253}
254
255static void
Krishna Gudipatidd5aaf42011-06-13 15:51:24 -0700256bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
257 enum bfa_fcs_lport_event event)
258{
259 bfa_trc(port->fcs, port->port_cfg.pwwn);
260 bfa_trc(port->fcs, event);
261
262 switch (event) {
263 case BFA_FCS_PORT_SM_DELRPORT:
264 if (port->num_rports == 0) {
265 bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
266 /* If vport - send completion call back */
267 if (port->vport)
268 bfa_fcs_vport_stop_comp(port->vport);
269 }
270 break;
271
272 default:
273 bfa_sm_fault(port->fcs, event);
274 }
275}
276
277static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700278bfa_fcs_lport_sm_deleting(
279 struct bfa_fcs_lport_s *port,
280 enum bfa_fcs_lport_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -0700281{
282 bfa_trc(port->fcs, port->port_cfg.pwwn);
283 bfa_trc(port->fcs, event);
284
285 switch (event) {
286 case BFA_FCS_PORT_SM_DELRPORT:
287 if (port->num_rports == 0) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700288 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
289 bfa_fcs_lport_deleted(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700290 }
291 break;
292
293 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800294 bfa_sm_fault(port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700295 }
296}
297
Jing Huang5fbe25c2010-10-18 17:17:23 -0700298/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700299 * fcs_port_pvt
300 */
301
Jing Huang7725ccf2009-09-23 17:46:15 -0700302/*
303 * Send a LS reject
304 */
305static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700306bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
Jing Huang7725ccf2009-09-23 17:46:15 -0700307 u8 reason_code, u8 reason_code_expl)
308{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700309 struct fchs_s fchs;
Jing Huang7725ccf2009-09-23 17:46:15 -0700310 struct bfa_fcxp_s *fcxp;
311 struct bfa_rport_s *bfa_rport = NULL;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700312 int len;
Jing Huang7725ccf2009-09-23 17:46:15 -0700313
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700314 bfa_trc(port->fcs, rx_fchs->d_id);
Jing Huang7725ccf2009-09-23 17:46:15 -0700315 bfa_trc(port->fcs, rx_fchs->s_id);
316
317 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
318 if (!fcxp)
319 return;
320
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700321 len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
322 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
323 rx_fchs->ox_id, reason_code, reason_code_expl);
Jing Huang7725ccf2009-09-23 17:46:15 -0700324
325 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700326 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
327 FC_MAX_PDUSZ, 0);
Jing Huang7725ccf2009-09-23 17:46:15 -0700328}
329
Jing Huang5fbe25c2010-10-18 17:17:23 -0700330/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700331 * Process incoming plogi from a remote port.
332 */
333static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700334bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
335 struct fchs_s *rx_fchs, struct fc_logi_s *plogi)
Jing Huang7725ccf2009-09-23 17:46:15 -0700336{
337 struct bfa_fcs_rport_s *rport;
338
339 bfa_trc(port->fcs, rx_fchs->d_id);
340 bfa_trc(port->fcs, rx_fchs->s_id);
341
342 /*
343 * If min cfg mode is enabled, drop any incoming PLOGIs
344 */
345 if (__fcs_min_cfg(port->fcs)) {
346 bfa_trc(port->fcs, rx_fchs->s_id);
347 return;
348 }
349
350 if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) {
351 bfa_trc(port->fcs, rx_fchs->s_id);
352 /*
353 * send a LS reject
354 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700355 bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
356 FC_LS_RJT_RSN_PROTOCOL_ERROR,
357 FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
Jing Huang7725ccf2009-09-23 17:46:15 -0700358 return;
359 }
360
Jing Huang5fbe25c2010-10-18 17:17:23 -0700361 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700362 * Direct Attach P2P mode : verify address assigned by the r-port.
Jing Huang7725ccf2009-09-23 17:46:15 -0700363 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700364 if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
365 (memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
366 (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
Jing Huang7725ccf2009-09-23 17:46:15 -0700367 if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700368 /* Address assigned to us cannot be a WKA */
369 bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
Jing Huang7725ccf2009-09-23 17:46:15 -0700370 FC_LS_RJT_RSN_PROTOCOL_ERROR,
371 FC_LS_RJT_EXP_INVALID_NPORT_ID);
372 return;
373 }
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700374 port->pid = rx_fchs->d_id;
Krishna Gudipatib7044952010-12-13 16:17:42 -0800375 bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
Jing Huang7725ccf2009-09-23 17:46:15 -0700376 }
377
Jing Huang5fbe25c2010-10-18 17:17:23 -0700378 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700379 * First, check if we know the device by pwwn.
380 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700381 rport = bfa_fcs_lport_get_rport_by_pwwn(port, plogi->port_name);
Jing Huang7725ccf2009-09-23 17:46:15 -0700382 if (rport) {
Jing Huang5fbe25c2010-10-18 17:17:23 -0700383 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700384 * Direct Attach P2P mode : handle address assigned by r-port.
Jing Huang7725ccf2009-09-23 17:46:15 -0700385 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700386 if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
387 (memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
388 (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
389 port->pid = rx_fchs->d_id;
Krishna Gudipatib7044952010-12-13 16:17:42 -0800390 bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
Jing Huang7725ccf2009-09-23 17:46:15 -0700391 rport->pid = rx_fchs->s_id;
392 }
393 bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
394 return;
395 }
396
Jing Huang5fbe25c2010-10-18 17:17:23 -0700397 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700398 * Next, lookup rport by PID.
399 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700400 rport = bfa_fcs_lport_get_rport_by_pid(port, rx_fchs->s_id);
Jing Huang7725ccf2009-09-23 17:46:15 -0700401 if (!rport) {
Jing Huang5fbe25c2010-10-18 17:17:23 -0700402 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700403 * Inbound PLOGI from a new device.
404 */
405 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
406 return;
407 }
408
Jing Huang5fbe25c2010-10-18 17:17:23 -0700409 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700410 * Rport is known only by PID.
411 */
412 if (rport->pwwn) {
Jing Huang5fbe25c2010-10-18 17:17:23 -0700413 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700414 * This is a different device with the same pid. Old device
415 * disappeared. Send implicit LOGO to old device.
416 */
Jing Huangd4b671c2010-12-26 21:46:35 -0800417 WARN_ON(rport->pwwn == plogi->port_name);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800418 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
Jing Huang7725ccf2009-09-23 17:46:15 -0700419
Jing Huang5fbe25c2010-10-18 17:17:23 -0700420 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700421 * Inbound PLOGI from a new device (with old PID).
422 */
423 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
424 return;
425 }
426
Jing Huang5fbe25c2010-10-18 17:17:23 -0700427 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700428 * PLOGI crossing each other.
429 */
Jing Huangd4b671c2010-12-26 21:46:35 -0800430 WARN_ON(rport->pwwn != WWN_NULL);
Jing Huang7725ccf2009-09-23 17:46:15 -0700431 bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
432}
433
434/*
435 * Process incoming ECHO.
436 * Since it does not require a login, it is processed here.
437 */
438static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700439bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
440 struct fc_echo_s *echo, u16 rx_len)
Jing Huang7725ccf2009-09-23 17:46:15 -0700441{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700442 struct fchs_s fchs;
443 struct bfa_fcxp_s *fcxp;
444 struct bfa_rport_s *bfa_rport = NULL;
445 int len, pyld_len;
Jing Huang7725ccf2009-09-23 17:46:15 -0700446
447 bfa_trc(port->fcs, rx_fchs->s_id);
448 bfa_trc(port->fcs, rx_fchs->d_id);
Jing Huang7725ccf2009-09-23 17:46:15 -0700449
450 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
451 if (!fcxp)
452 return;
453
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700454 len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
455 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
456 rx_fchs->ox_id);
Jing Huang7725ccf2009-09-23 17:46:15 -0700457
458 /*
459 * Copy the payload (if any) from the echo frame
460 */
461 pyld_len = rx_len - sizeof(struct fchs_s);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700462 bfa_trc(port->fcs, rx_len);
Jing Huang7725ccf2009-09-23 17:46:15 -0700463 bfa_trc(port->fcs, pyld_len);
464
465 if (pyld_len > len)
466 memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) +
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700467 sizeof(struct fc_echo_s), (echo + 1),
468 (pyld_len - sizeof(struct fc_echo_s)));
Jing Huang7725ccf2009-09-23 17:46:15 -0700469
470 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700471 BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
472 FC_MAX_PDUSZ, 0);
Jing Huang7725ccf2009-09-23 17:46:15 -0700473}
474
475/*
476 * Process incoming RNID.
477 * Since it does not require a login, it is processed here.
478 */
479static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700480bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
481 struct fc_rnid_cmd_s *rnid, u16 rx_len)
Jing Huang7725ccf2009-09-23 17:46:15 -0700482{
483 struct fc_rnid_common_id_data_s common_id_data;
484 struct fc_rnid_general_topology_data_s gen_topo_data;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700485 struct fchs_s fchs;
Jing Huang7725ccf2009-09-23 17:46:15 -0700486 struct bfa_fcxp_s *fcxp;
487 struct bfa_rport_s *bfa_rport = NULL;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700488 u16 len;
489 u32 data_format;
Jing Huang7725ccf2009-09-23 17:46:15 -0700490
491 bfa_trc(port->fcs, rx_fchs->s_id);
492 bfa_trc(port->fcs, rx_fchs->d_id);
493 bfa_trc(port->fcs, rx_len);
494
495 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
496 if (!fcxp)
497 return;
498
499 /*
500 * Check Node Indentification Data Format
501 * We only support General Topology Discovery Format.
502 * For any other requested Data Formats, we return Common Node Id Data
503 * only, as per FC-LS.
504 */
505 bfa_trc(port->fcs, rnid->node_id_data_format);
506 if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
507 data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY;
508 /*
509 * Get General topology data for this port
510 */
511 bfa_fs_port_get_gen_topo_data(port, &gen_topo_data);
512 } else {
513 data_format = RNID_NODEID_DATA_FORMAT_COMMON;
514 }
515
516 /*
517 * Copy the Node Id Info
518 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700519 common_id_data.port_name = bfa_fcs_lport_get_pwwn(port);
520 common_id_data.node_name = bfa_fcs_lport_get_nwwn(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700521
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700522 len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
523 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
524 rx_fchs->ox_id, data_format, &common_id_data,
525 &gen_topo_data);
Jing Huang7725ccf2009-09-23 17:46:15 -0700526
527 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700528 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
529 FC_MAX_PDUSZ, 0);
Jing Huang7725ccf2009-09-23 17:46:15 -0700530}
531
532/*
533 * Fill out General Topolpgy Discovery Data for RNID ELS.
534 */
535static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700536bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
Jing Huang7725ccf2009-09-23 17:46:15 -0700537 struct fc_rnid_general_topology_data_s *gen_topo_data)
538{
Jing Huang6a18b162010-10-18 17:08:54 -0700539 memset(gen_topo_data, 0,
Jing Huang7725ccf2009-09-23 17:46:15 -0700540 sizeof(struct fc_rnid_general_topology_data_s));
541
Jing Huangba816ea2010-10-18 17:10:50 -0700542 gen_topo_data->asso_type = cpu_to_be32(RNID_ASSOCIATED_TYPE_HOST);
Jing Huang7725ccf2009-09-23 17:46:15 -0700543 gen_topo_data->phy_port_num = 0; /* @todo */
Jing Huangba816ea2010-10-18 17:10:50 -0700544 gen_topo_data->num_attached_nodes = cpu_to_be32(1);
Jing Huang7725ccf2009-09-23 17:46:15 -0700545}
546
547static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700548bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700549{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700550 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
551 char lpwwn_buf[BFA_STRING_32];
552
Jing Huang7725ccf2009-09-23 17:46:15 -0700553 bfa_trc(port->fcs, port->fabric->oper_type);
554
555 __port_action[port->fabric->fab_type].init(port);
556 __port_action[port->fabric->fab_type].online(port);
557
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700558 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
Jing Huang88166242010-12-09 17:11:53 -0800559 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700560 "Logical port online: WWN = %s Role = %s\n",
561 lpwwn_buf, "Initiator");
562
563 bfad->bfad_flags |= BFAD_PORT_ONLINE;
Jing Huang7725ccf2009-09-23 17:46:15 -0700564}
565
566static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700567bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700568{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700569 struct list_head *qe, *qen;
Jing Huang7725ccf2009-09-23 17:46:15 -0700570 struct bfa_fcs_rport_s *rport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700571 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
572 char lpwwn_buf[BFA_STRING_32];
Jing Huang7725ccf2009-09-23 17:46:15 -0700573
574 bfa_trc(port->fcs, port->fabric->oper_type);
575
576 __port_action[port->fabric->fab_type].offline(port);
577
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700578 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
Maggie Zhangf7f738122010-12-09 19:08:43 -0800579 if (bfa_sm_cmp_state(port->fabric,
580 bfa_fcs_fabric_sm_online) == BFA_TRUE)
Jing Huang88166242010-12-09 17:11:53 -0800581 BFA_LOG(KERN_ERR, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700582 "Logical port lost fabric connectivity: WWN = %s Role = %s\n",
583 lpwwn_buf, "Initiator");
Jing Huangf8ceafd2009-09-25 12:29:54 -0700584 else
Jing Huang88166242010-12-09 17:11:53 -0800585 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700586 "Logical port taken offline: WWN = %s Role = %s\n",
587 lpwwn_buf, "Initiator");
Jing Huang7725ccf2009-09-23 17:46:15 -0700588
589 list_for_each_safe(qe, qen, &port->rport_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700590 rport = (struct bfa_fcs_rport_s *) qe;
Maggie Zhangf7f738122010-12-09 19:08:43 -0800591 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
Jing Huang7725ccf2009-09-23 17:46:15 -0700592 }
593}
594
595static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700596bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700597{
Jing Huangd4b671c2010-12-26 21:46:35 -0800598 WARN_ON(1);
Jing Huang7725ccf2009-09-23 17:46:15 -0700599}
600
601static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700602bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700603{
Jing Huangd4b671c2010-12-26 21:46:35 -0800604 WARN_ON(1);
Jing Huang7725ccf2009-09-23 17:46:15 -0700605}
606
607static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700608bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700609{
Jing Huangd4b671c2010-12-26 21:46:35 -0800610 WARN_ON(1);
Jing Huang7725ccf2009-09-23 17:46:15 -0700611}
612
613static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700614bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs)
Jing Huang7725ccf2009-09-23 17:46:15 -0700615{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700616 struct fchs_s fchs;
617 struct bfa_fcxp_s *fcxp;
618 int len;
Jing Huang7725ccf2009-09-23 17:46:15 -0700619
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700620 bfa_trc(port->fcs, rx_fchs->d_id);
621 bfa_trc(port->fcs, rx_fchs->s_id);
622
623 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
624 if (!fcxp)
625 return;
626
627 len = fc_ba_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
628 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
629 rx_fchs->ox_id, 0);
630
631 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
632 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
633 FC_MAX_PDUSZ, 0);
634}
635static void
636bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
637{
638 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
639 char lpwwn_buf[BFA_STRING_32];
640
641 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
Jing Huang88166242010-12-09 17:11:53 -0800642 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700643 "Logical port deleted: WWN = %s Role = %s\n",
644 lpwwn_buf, "Initiator");
645
646 /* Base port will be deleted by the OS driver */
Jing Huang7725ccf2009-09-23 17:46:15 -0700647 if (port->vport) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700648 bfa_fcb_lport_delete(port->fcs->bfad, port->port_cfg.roles,
649 port->fabric->vf_drv,
650 port->vport ? port->vport->vport_drv : NULL);
Jing Huang7725ccf2009-09-23 17:46:15 -0700651 bfa_fcs_vport_delete_comp(port->vport);
652 } else {
Maggie Zhangf7f738122010-12-09 19:08:43 -0800653 bfa_wc_down(&port->fabric->wc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700654 }
655}
656
657
Jing Huang5fbe25c2010-10-18 17:17:23 -0700658/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700659 * Unsolicited frame receive handling.
Jing Huang7725ccf2009-09-23 17:46:15 -0700660 */
661void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700662bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
663 struct fchs_s *fchs, u16 len)
Jing Huang7725ccf2009-09-23 17:46:15 -0700664{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700665 u32 pid = fchs->s_id;
Jing Huang7725ccf2009-09-23 17:46:15 -0700666 struct bfa_fcs_rport_s *rport = NULL;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700667 struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
Jing Huang7725ccf2009-09-23 17:46:15 -0700668
669 bfa_stats(lport, uf_recvs);
Krishna Gudipati15821f02010-12-13 16:23:27 -0800670 bfa_trc(lport->fcs, fchs->type);
Jing Huang7725ccf2009-09-23 17:46:15 -0700671
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700672 if (!bfa_fcs_lport_is_online(lport)) {
Jing Huang7725ccf2009-09-23 17:46:15 -0700673 bfa_stats(lport, uf_recv_drops);
674 return;
675 }
676
Jing Huang5fbe25c2010-10-18 17:17:23 -0700677 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700678 * First, handle ELSs that donot require a login.
679 */
680 /*
681 * Handle PLOGI first
682 */
683 if ((fchs->type == FC_TYPE_ELS) &&
684 (els_cmd->els_code == FC_ELS_PLOGI)) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700685 bfa_fcs_lport_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -0700686 return;
687 }
688
689 /*
690 * Handle ECHO separately.
691 */
692 if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700693 bfa_fcs_lport_echo(lport, fchs,
694 (struct fc_echo_s *)els_cmd, len);
Jing Huang7725ccf2009-09-23 17:46:15 -0700695 return;
696 }
697
698 /*
699 * Handle RNID separately.
700 */
701 if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700702 bfa_fcs_lport_rnid(lport, fchs,
Jing Huang7725ccf2009-09-23 17:46:15 -0700703 (struct fc_rnid_cmd_s *) els_cmd, len);
704 return;
705 }
706
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700707 if (fchs->type == FC_TYPE_BLS) {
708 if ((fchs->routing == FC_RTG_BASIC_LINK) &&
709 (fchs->cat_info == FC_CAT_ABTS))
710 bfa_fcs_lport_abts_acc(lport, fchs);
711 return;
712 }
Jing Huang5fbe25c2010-10-18 17:17:23 -0700713 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700714 * look for a matching remote port ID
715 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700716 rport = bfa_fcs_lport_get_rport_by_pid(lport, pid);
Jing Huang7725ccf2009-09-23 17:46:15 -0700717 if (rport) {
718 bfa_trc(rport->fcs, fchs->s_id);
719 bfa_trc(rport->fcs, fchs->d_id);
720 bfa_trc(rport->fcs, fchs->type);
721
722 bfa_fcs_rport_uf_recv(rport, fchs, len);
723 return;
724 }
725
Jing Huang5fbe25c2010-10-18 17:17:23 -0700726 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700727 * Only handles ELS frames for now.
728 */
729 if (fchs->type != FC_TYPE_ELS) {
Krishna Gudipati15821f02010-12-13 16:23:27 -0800730 bfa_trc(lport->fcs, fchs->s_id);
731 bfa_trc(lport->fcs, fchs->d_id);
732 /* ignore type FC_TYPE_FC_FSS */
733 if (fchs->type != FC_TYPE_FC_FSS)
734 bfa_sm_fault(lport->fcs, fchs->type);
Jing Huang7725ccf2009-09-23 17:46:15 -0700735 return;
736 }
737
738 bfa_trc(lport->fcs, els_cmd->els_code);
739 if (els_cmd->els_code == FC_ELS_RSCN) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700740 bfa_fcs_lport_scn_process_rscn(lport, fchs, len);
Jing Huang7725ccf2009-09-23 17:46:15 -0700741 return;
742 }
743
744 if (els_cmd->els_code == FC_ELS_LOGO) {
Jing Huang5fbe25c2010-10-18 17:17:23 -0700745 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700746 * @todo Handle LOGO frames received.
747 */
Jing Huang7725ccf2009-09-23 17:46:15 -0700748 return;
749 }
750
751 if (els_cmd->els_code == FC_ELS_PRLI) {
Jing Huang5fbe25c2010-10-18 17:17:23 -0700752 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700753 * @todo Handle PRLI frames received.
754 */
Jing Huang7725ccf2009-09-23 17:46:15 -0700755 return;
756 }
757
Jing Huang5fbe25c2010-10-18 17:17:23 -0700758 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700759 * Unhandled ELS frames. Send a LS_RJT.
760 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700761 bfa_fcs_lport_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
Jing Huang7725ccf2009-09-23 17:46:15 -0700762 FC_LS_RJT_EXP_NO_ADDL_INFO);
763
764}
765
Jing Huang5fbe25c2010-10-18 17:17:23 -0700766/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700767 * PID based Lookup for a R-Port in the Port R-Port Queue
768 */
769struct bfa_fcs_rport_s *
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700770bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
Jing Huang7725ccf2009-09-23 17:46:15 -0700771{
772 struct bfa_fcs_rport_s *rport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700773 struct list_head *qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700774
775 list_for_each(qe, &port->rport_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700776 rport = (struct bfa_fcs_rport_s *) qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700777 if (rport->pid == pid)
778 return rport;
779 }
780
781 bfa_trc(port->fcs, pid);
782 return NULL;
783}
784
Jing Huang5fbe25c2010-10-18 17:17:23 -0700785/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700786 * PWWN based Lookup for a R-Port in the Port R-Port Queue
787 */
788struct bfa_fcs_rport_s *
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700789bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s *port, wwn_t pwwn)
Jing Huang7725ccf2009-09-23 17:46:15 -0700790{
791 struct bfa_fcs_rport_s *rport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700792 struct list_head *qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700793
794 list_for_each(qe, &port->rport_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700795 rport = (struct bfa_fcs_rport_s *) qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700796 if (wwn_is_equal(rport->pwwn, pwwn))
797 return rport;
798 }
799
800 bfa_trc(port->fcs, pwwn);
Jing Huangf8ceafd2009-09-25 12:29:54 -0700801 return NULL;
Jing Huang7725ccf2009-09-23 17:46:15 -0700802}
803
Jing Huang5fbe25c2010-10-18 17:17:23 -0700804/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700805 * NWWN based Lookup for a R-Port in the Port R-Port Queue
806 */
807struct bfa_fcs_rport_s *
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700808bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
Jing Huang7725ccf2009-09-23 17:46:15 -0700809{
810 struct bfa_fcs_rport_s *rport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700811 struct list_head *qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700812
813 list_for_each(qe, &port->rport_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700814 rport = (struct bfa_fcs_rport_s *) qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700815 if (wwn_is_equal(rport->nwwn, nwwn))
816 return rport;
817 }
818
819 bfa_trc(port->fcs, nwwn);
Jing Huangf8ceafd2009-09-25 12:29:54 -0700820 return NULL;
Jing Huang7725ccf2009-09-23 17:46:15 -0700821}
822
Jing Huang5fbe25c2010-10-18 17:17:23 -0700823/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700824 * Called by rport module when new rports are discovered.
825 */
826void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700827bfa_fcs_lport_add_rport(
828 struct bfa_fcs_lport_s *port,
829 struct bfa_fcs_rport_s *rport)
Jing Huang7725ccf2009-09-23 17:46:15 -0700830{
831 list_add_tail(&rport->qe, &port->rport_q);
832 port->num_rports++;
833}
834
Jing Huang5fbe25c2010-10-18 17:17:23 -0700835/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700836 * Called by rport module to when rports are deleted.
837 */
838void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700839bfa_fcs_lport_del_rport(
840 struct bfa_fcs_lport_s *port,
841 struct bfa_fcs_rport_s *rport)
Jing Huang7725ccf2009-09-23 17:46:15 -0700842{
Jing Huangd4b671c2010-12-26 21:46:35 -0800843 WARN_ON(!bfa_q_is_on_q(&port->rport_q, rport));
Jing Huang7725ccf2009-09-23 17:46:15 -0700844 list_del(&rport->qe);
845 port->num_rports--;
846
847 bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT);
848}
849
Jing Huang5fbe25c2010-10-18 17:17:23 -0700850/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700851 * Called by fabric for base port when fabric login is complete.
852 * Called by vport for virtual ports when FDISC is complete.
853 */
854void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700855bfa_fcs_lport_online(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700856{
857 bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE);
858}
859
Jing Huang5fbe25c2010-10-18 17:17:23 -0700860/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700861 * Called by fabric for base port when fabric goes offline.
862 * Called by vport for virtual ports when virtual port becomes offline.
863 */
864void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700865bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700866{
867 bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
868}
869
Jing Huang5fbe25c2010-10-18 17:17:23 -0700870/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700871 * Called by fabric to delete base lport and associated resources.
872 *
873 * Called by vport to delete lport and associated resources. Should call
874 * bfa_fcs_vport_delete_comp() for vports on completion.
875 */
876void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700877bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700878{
879 bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE);
880}
881
Jing Huang5fbe25c2010-10-18 17:17:23 -0700882/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700883 * Return TRUE if port is online, else return FALSE
884 */
885bfa_boolean_t
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700886bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port)
Jing Huang7725ccf2009-09-23 17:46:15 -0700887{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700888 return bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online);
Jing Huang7725ccf2009-09-23 17:46:15 -0700889}
890
Jing Huang5fbe25c2010-10-18 17:17:23 -0700891/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700892 * Attach time initialization of logical ports.
Jing Huang7725ccf2009-09-23 17:46:15 -0700893 */
894void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700895bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
896 u16 vf_id, struct bfa_fcs_vport_s *vport)
Jing Huang7725ccf2009-09-23 17:46:15 -0700897{
898 lport->fcs = fcs;
899 lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
Jing Huang7725ccf2009-09-23 17:46:15 -0700900 lport->vport = vport;
Maggie Zhangf7f738122010-12-09 19:08:43 -0800901 lport->lp_tag = (vport) ? vport->lps->lp_tag :
902 lport->fabric->lps->lp_tag;
Jing Huang7725ccf2009-09-23 17:46:15 -0700903
904 INIT_LIST_HEAD(&lport->rport_q);
905 lport->num_rports = 0;
Krishna Gudipatie6714322010-03-03 17:44:02 -0800906}
Jing Huang7725ccf2009-09-23 17:46:15 -0700907
Jing Huang5fbe25c2010-10-18 17:17:23 -0700908/*
Krishna Gudipatie6714322010-03-03 17:44:02 -0800909 * Logical port initialization of base or virtual port.
910 * Called by fabric for base port or by vport for virtual ports.
911 */
912
913void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700914bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
915 struct bfa_lport_cfg_s *port_cfg)
Krishna Gudipatie6714322010-03-03 17:44:02 -0800916{
917 struct bfa_fcs_vport_s *vport = lport->vport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700918 struct bfad_s *bfad = (struct bfad_s *)lport->fcs->bfad;
919 char lpwwn_buf[BFA_STRING_32];
Krishna Gudipatie6714322010-03-03 17:44:02 -0800920
Jing Huang6a18b162010-10-18 17:08:54 -0700921 lport->port_cfg = *port_cfg;
Krishna Gudipatie6714322010-03-03 17:44:02 -0800922
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700923 lport->bfad_port = bfa_fcb_lport_new(lport->fcs->bfad, lport,
924 lport->port_cfg.roles,
925 lport->fabric->vf_drv,
926 vport ? vport->vport_drv : NULL);
Krishna Gudipatie6714322010-03-03 17:44:02 -0800927
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700928 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport));
Jing Huang88166242010-12-09 17:11:53 -0800929 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700930 "New logical port created: WWN = %s Role = %s\n",
931 lpwwn_buf, "Initiator");
Jing Huang7725ccf2009-09-23 17:46:15 -0700932
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700933 bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit);
Jing Huang7725ccf2009-09-23 17:46:15 -0700934 bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
935}
936
Jing Huang5fbe25c2010-10-18 17:17:23 -0700937/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700938 * fcs_lport_api
939 */
940
941void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700942bfa_fcs_lport_get_attr(
943 struct bfa_fcs_lport_s *port,
944 struct bfa_lport_attr_s *port_attr)
Jing Huang7725ccf2009-09-23 17:46:15 -0700945{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700946 if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
Jing Huang7725ccf2009-09-23 17:46:15 -0700947 port_attr->pid = port->pid;
948 else
949 port_attr->pid = 0;
950
951 port_attr->port_cfg = port->port_cfg;
952
953 if (port->fabric) {
Maggie Zhangf7f738122010-12-09 19:08:43 -0800954 port_attr->port_type = port->fabric->oper_type;
Maggie Zhangda99dcc2010-12-09 19:13:20 -0800955 port_attr->loopback = bfa_sm_cmp_state(port->fabric,
956 bfa_fcs_fabric_sm_loopback);
Krishna Gudipatif926a052010-03-05 19:36:00 -0800957 port_attr->authfail =
Maggie Zhangf7f738122010-12-09 19:08:43 -0800958 bfa_sm_cmp_state(port->fabric,
959 bfa_fcs_fabric_sm_auth_failed);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700960 port_attr->fabric_name = bfa_fcs_lport_get_fabric_name(port);
Jing Huang7725ccf2009-09-23 17:46:15 -0700961 memcpy(port_attr->fabric_ip_addr,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700962 bfa_fcs_lport_get_fabric_ipaddr(port),
963 BFA_FCS_FABRIC_IPADDR_SZ);
Jing Huang7725ccf2009-09-23 17:46:15 -0700964
Krishna Gudipati86e32da2010-03-05 19:35:33 -0800965 if (port->vport != NULL) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700966 port_attr->port_type = BFA_PORT_TYPE_VPORT;
Krishna Gudipati86e32da2010-03-05 19:35:33 -0800967 port_attr->fpma_mac =
Maggie Zhangf7f738122010-12-09 19:08:43 -0800968 port->vport->lps->lp_mac;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700969 } else {
Krishna Gudipati86e32da2010-03-05 19:35:33 -0800970 port_attr->fpma_mac =
Maggie Zhangf7f738122010-12-09 19:08:43 -0800971 port->fabric->lps->lp_mac;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700972 }
Jing Huang7725ccf2009-09-23 17:46:15 -0700973 } else {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700974 port_attr->port_type = BFA_PORT_TYPE_UNKNOWN;
975 port_attr->state = BFA_LPORT_UNINIT;
Jing Huang7725ccf2009-09-23 17:46:15 -0700976 }
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700977}
978
Jing Huang5fbe25c2010-10-18 17:17:23 -0700979/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700980 * bfa_fcs_lport_fab port fab functions
981 */
982
Jing Huang5fbe25c2010-10-18 17:17:23 -0700983/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700984 * Called by port to initialize fabric services of the base port.
985 */
986static void
987bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port)
988{
989 bfa_fcs_lport_ns_init(port);
990 bfa_fcs_lport_scn_init(port);
991 bfa_fcs_lport_ms_init(port);
992}
993
Jing Huang5fbe25c2010-10-18 17:17:23 -0700994/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700995 * Called by port to notify transition to online state.
996 */
997static void
998bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
999{
1000 bfa_fcs_lport_ns_online(port);
1001 bfa_fcs_lport_scn_online(port);
1002}
1003
Jing Huang5fbe25c2010-10-18 17:17:23 -07001004/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001005 * Called by port to notify transition to offline state.
1006 */
1007static void
1008bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port)
1009{
1010 bfa_fcs_lport_ns_offline(port);
1011 bfa_fcs_lport_scn_offline(port);
1012 bfa_fcs_lport_ms_offline(port);
1013}
1014
Jing Huang5fbe25c2010-10-18 17:17:23 -07001015/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001016 * bfa_fcs_lport_n2n functions
1017 */
1018
Jing Huang5fbe25c2010-10-18 17:17:23 -07001019/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001020 * Called by fcs/port to initialize N2N topology.
1021 */
1022static void
1023bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port)
1024{
1025}
1026
Jing Huang5fbe25c2010-10-18 17:17:23 -07001027/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001028 * Called by fcs/port to notify transition to online state.
1029 */
1030static void
1031bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)
1032{
1033 struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
1034 struct bfa_lport_cfg_s *pcfg = &port->port_cfg;
1035 struct bfa_fcs_rport_s *rport;
1036
1037 bfa_trc(port->fcs, pcfg->pwwn);
1038
1039 /*
1040 * If our PWWN is > than that of the r-port, we have to initiate PLOGI
1041 * and assign an Address. if not, we need to wait for its PLOGI.
1042 *
1043 * If our PWWN is < than that of the remote port, it will send a PLOGI
1044 * with the PIDs assigned. The rport state machine take care of this
1045 * incoming PLOGI.
1046 */
1047 if (memcmp
1048 ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
1049 sizeof(wwn_t)) > 0) {
1050 port->pid = N2N_LOCAL_PID;
Krishna Gudipatib7044952010-12-13 16:17:42 -08001051 bfa_lps_set_n2n_pid(port->fabric->lps, N2N_LOCAL_PID);
Jing Huang5fbe25c2010-10-18 17:17:23 -07001052 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001053 * First, check if we know the device by pwwn.
1054 */
1055 rport = bfa_fcs_lport_get_rport_by_pwwn(port,
1056 n2n_port->rem_port_wwn);
1057 if (rport) {
1058 bfa_trc(port->fcs, rport->pid);
1059 bfa_trc(port->fcs, rport->pwwn);
1060 rport->pid = N2N_REMOTE_PID;
Maggie Zhangf7f738122010-12-09 19:08:43 -08001061 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001062 return;
1063 }
1064
1065 /*
1066 * In n2n there can be only one rport. Delete the old one
1067 * whose pid should be zero, because it is offline.
1068 */
1069 if (port->num_rports > 0) {
1070 rport = bfa_fcs_lport_get_rport_by_pid(port, 0);
Jing Huangd4b671c2010-12-26 21:46:35 -08001071 WARN_ON(rport == NULL);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001072 if (rport) {
1073 bfa_trc(port->fcs, rport->pwwn);
Maggie Zhangf7f738122010-12-09 19:08:43 -08001074 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001075 }
1076 }
1077 bfa_fcs_rport_create(port, N2N_REMOTE_PID);
1078 }
1079}
1080
Jing Huang5fbe25c2010-10-18 17:17:23 -07001081/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001082 * Called by fcs/port to notify transition to offline state.
1083 */
1084static void
1085bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)
1086{
1087 struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
1088
1089 bfa_trc(port->fcs, port->pid);
1090 port->pid = 0;
1091 n2n_port->rem_port_wwn = 0;
1092 n2n_port->reply_oxid = 0;
1093}
1094
1095#define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
1096
1097/*
1098 * forward declarations
1099 */
1100static void bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg,
1101 struct bfa_fcxp_s *fcxp_alloced);
1102static void bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg,
1103 struct bfa_fcxp_s *fcxp_alloced);
1104static void bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg,
1105 struct bfa_fcxp_s *fcxp_alloced);
1106static void bfa_fcs_lport_fdmi_rhba_response(void *fcsarg,
1107 struct bfa_fcxp_s *fcxp,
1108 void *cbarg,
1109 bfa_status_t req_status,
1110 u32 rsp_len,
1111 u32 resid_len,
1112 struct fchs_s *rsp_fchs);
1113static void bfa_fcs_lport_fdmi_rprt_response(void *fcsarg,
1114 struct bfa_fcxp_s *fcxp,
1115 void *cbarg,
1116 bfa_status_t req_status,
1117 u32 rsp_len,
1118 u32 resid_len,
1119 struct fchs_s *rsp_fchs);
1120static void bfa_fcs_lport_fdmi_rpa_response(void *fcsarg,
1121 struct bfa_fcxp_s *fcxp,
1122 void *cbarg,
1123 bfa_status_t req_status,
1124 u32 rsp_len,
1125 u32 resid_len,
1126 struct fchs_s *rsp_fchs);
1127static void bfa_fcs_lport_fdmi_timeout(void *arg);
1128static u16 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1129 u8 *pyld);
1130static u16 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1131 u8 *pyld);
1132static u16 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1133 u8 *pyld);
1134static u16 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *
1135 fdmi, u8 *pyld);
1136static void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1137 struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
1138static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1139 struct bfa_fcs_fdmi_port_attr_s *port_attr);
Jing Huang5fbe25c2010-10-18 17:17:23 -07001140/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001141 * fcs_fdmi_sm FCS FDMI state machine
1142 */
1143
Jing Huang5fbe25c2010-10-18 17:17:23 -07001144/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001145 * FDMI State Machine events
1146 */
1147enum port_fdmi_event {
1148 FDMISM_EVENT_PORT_ONLINE = 1,
1149 FDMISM_EVENT_PORT_OFFLINE = 2,
1150 FDMISM_EVENT_RSP_OK = 4,
1151 FDMISM_EVENT_RSP_ERROR = 5,
1152 FDMISM_EVENT_TIMEOUT = 6,
1153 FDMISM_EVENT_RHBA_SENT = 7,
1154 FDMISM_EVENT_RPRT_SENT = 8,
1155 FDMISM_EVENT_RPA_SENT = 9,
1156};
1157
1158static void bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1159 enum port_fdmi_event event);
1160static void bfa_fcs_lport_fdmi_sm_sending_rhba(
1161 struct bfa_fcs_lport_fdmi_s *fdmi,
1162 enum port_fdmi_event event);
1163static void bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1164 enum port_fdmi_event event);
1165static void bfa_fcs_lport_fdmi_sm_rhba_retry(
1166 struct bfa_fcs_lport_fdmi_s *fdmi,
1167 enum port_fdmi_event event);
1168static void bfa_fcs_lport_fdmi_sm_sending_rprt(
1169 struct bfa_fcs_lport_fdmi_s *fdmi,
1170 enum port_fdmi_event event);
1171static void bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1172 enum port_fdmi_event event);
1173static void bfa_fcs_lport_fdmi_sm_rprt_retry(
1174 struct bfa_fcs_lport_fdmi_s *fdmi,
1175 enum port_fdmi_event event);
1176static void bfa_fcs_lport_fdmi_sm_sending_rpa(
1177 struct bfa_fcs_lport_fdmi_s *fdmi,
1178 enum port_fdmi_event event);
1179static void bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1180 enum port_fdmi_event event);
1181static void bfa_fcs_lport_fdmi_sm_rpa_retry(
1182 struct bfa_fcs_lport_fdmi_s *fdmi,
1183 enum port_fdmi_event event);
1184static void bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1185 enum port_fdmi_event event);
1186static void bfa_fcs_lport_fdmi_sm_disabled(
1187 struct bfa_fcs_lport_fdmi_s *fdmi,
1188 enum port_fdmi_event event);
Jing Huang5fbe25c2010-10-18 17:17:23 -07001189/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001190 * Start in offline state - awaiting MS to send start.
1191 */
1192static void
1193bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1194 enum port_fdmi_event event)
1195{
1196 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1197
1198 bfa_trc(port->fcs, port->port_cfg.pwwn);
1199 bfa_trc(port->fcs, event);
1200
1201 fdmi->retry_cnt = 0;
1202
1203 switch (event) {
1204 case FDMISM_EVENT_PORT_ONLINE:
1205 if (port->vport) {
1206 /*
1207 * For Vports, register a new port.
1208 */
1209 bfa_sm_set_state(fdmi,
1210 bfa_fcs_lport_fdmi_sm_sending_rprt);
1211 bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1212 } else {
1213 /*
1214 * For a base port, we should first register the HBA
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001215 * attribute. The HBA attribute also contains the base
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001216 * port registration.
1217 */
1218 bfa_sm_set_state(fdmi,
1219 bfa_fcs_lport_fdmi_sm_sending_rhba);
1220 bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1221 }
1222 break;
1223
1224 case FDMISM_EVENT_PORT_OFFLINE:
1225 break;
1226
1227 default:
1228 bfa_sm_fault(port->fcs, event);
1229 }
1230}
1231
1232static void
1233bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1234 enum port_fdmi_event event)
1235{
1236 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1237
1238 bfa_trc(port->fcs, port->port_cfg.pwwn);
1239 bfa_trc(port->fcs, event);
1240
1241 switch (event) {
1242 case FDMISM_EVENT_RHBA_SENT:
1243 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rhba);
1244 break;
1245
1246 case FDMISM_EVENT_PORT_OFFLINE:
1247 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1248 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1249 &fdmi->fcxp_wqe);
1250 break;
1251
1252 default:
1253 bfa_sm_fault(port->fcs, event);
1254 }
1255}
1256
1257static void
1258bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1259 enum port_fdmi_event event)
1260{
1261 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1262
1263 bfa_trc(port->fcs, port->port_cfg.pwwn);
1264 bfa_trc(port->fcs, event);
1265
1266 switch (event) {
1267 case FDMISM_EVENT_RSP_ERROR:
1268 /*
1269 * if max retries have not been reached, start timer for a
1270 * delayed retry
1271 */
1272 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1273 bfa_sm_set_state(fdmi,
1274 bfa_fcs_lport_fdmi_sm_rhba_retry);
1275 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1276 &fdmi->timer,
1277 bfa_fcs_lport_fdmi_timeout, fdmi,
1278 BFA_FCS_RETRY_TIMEOUT);
1279 } else {
1280 /*
1281 * set state to offline
1282 */
1283 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1284 }
1285 break;
1286
1287 case FDMISM_EVENT_RSP_OK:
1288 /*
1289 * Initiate Register Port Attributes
1290 */
1291 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1292 fdmi->retry_cnt = 0;
1293 bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1294 break;
1295
1296 case FDMISM_EVENT_PORT_OFFLINE:
1297 bfa_fcxp_discard(fdmi->fcxp);
1298 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1299 break;
1300
1301 default:
1302 bfa_sm_fault(port->fcs, event);
1303 }
1304}
1305
1306static void
1307bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1308 enum port_fdmi_event event)
1309{
1310 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1311
1312 bfa_trc(port->fcs, port->port_cfg.pwwn);
1313 bfa_trc(port->fcs, event);
1314
1315 switch (event) {
1316 case FDMISM_EVENT_TIMEOUT:
1317 /*
1318 * Retry Timer Expired. Re-send
1319 */
1320 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rhba);
1321 bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1322 break;
1323
1324 case FDMISM_EVENT_PORT_OFFLINE:
1325 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1326 bfa_timer_stop(&fdmi->timer);
1327 break;
1328
1329 default:
1330 bfa_sm_fault(port->fcs, event);
1331 }
1332}
1333
1334/*
1335* RPRT : Register Port
1336 */
1337static void
1338bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1339 enum port_fdmi_event event)
1340{
1341 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1342
1343 bfa_trc(port->fcs, port->port_cfg.pwwn);
1344 bfa_trc(port->fcs, event);
1345
1346 switch (event) {
1347 case FDMISM_EVENT_RPRT_SENT:
1348 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rprt);
1349 break;
1350
1351 case FDMISM_EVENT_PORT_OFFLINE:
1352 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1353 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1354 &fdmi->fcxp_wqe);
1355 break;
1356
1357 default:
1358 bfa_sm_fault(port->fcs, event);
1359 }
1360}
1361
1362static void
1363bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1364 enum port_fdmi_event event)
1365{
1366 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1367
1368 bfa_trc(port->fcs, port->port_cfg.pwwn);
1369 bfa_trc(port->fcs, event);
1370
1371 switch (event) {
1372 case FDMISM_EVENT_RSP_ERROR:
1373 /*
1374 * if max retries have not been reached, start timer for a
1375 * delayed retry
1376 */
1377 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1378 bfa_sm_set_state(fdmi,
1379 bfa_fcs_lport_fdmi_sm_rprt_retry);
1380 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1381 &fdmi->timer,
1382 bfa_fcs_lport_fdmi_timeout, fdmi,
1383 BFA_FCS_RETRY_TIMEOUT);
1384
1385 } else {
1386 /*
1387 * set state to offline
1388 */
1389 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1390 fdmi->retry_cnt = 0;
1391 }
1392 break;
1393
1394 case FDMISM_EVENT_RSP_OK:
1395 fdmi->retry_cnt = 0;
1396 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1397 break;
1398
1399 case FDMISM_EVENT_PORT_OFFLINE:
1400 bfa_fcxp_discard(fdmi->fcxp);
1401 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1402 break;
1403
1404 default:
1405 bfa_sm_fault(port->fcs, event);
1406 }
1407}
1408
1409static void
1410bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1411 enum port_fdmi_event event)
1412{
1413 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1414
1415 bfa_trc(port->fcs, port->port_cfg.pwwn);
1416 bfa_trc(port->fcs, event);
1417
1418 switch (event) {
1419 case FDMISM_EVENT_TIMEOUT:
1420 /*
1421 * Retry Timer Expired. Re-send
1422 */
1423 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rprt);
1424 bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1425 break;
1426
1427 case FDMISM_EVENT_PORT_OFFLINE:
1428 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1429 bfa_timer_stop(&fdmi->timer);
1430 break;
1431
1432 default:
1433 bfa_sm_fault(port->fcs, event);
1434 }
1435}
1436
1437/*
1438 * Register Port Attributes
1439 */
1440static void
1441bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1442 enum port_fdmi_event event)
1443{
1444 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1445
1446 bfa_trc(port->fcs, port->port_cfg.pwwn);
1447 bfa_trc(port->fcs, event);
1448
1449 switch (event) {
1450 case FDMISM_EVENT_RPA_SENT:
1451 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa);
1452 break;
1453
1454 case FDMISM_EVENT_PORT_OFFLINE:
1455 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1456 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1457 &fdmi->fcxp_wqe);
1458 break;
1459
1460 default:
1461 bfa_sm_fault(port->fcs, event);
1462 }
1463}
1464
1465static void
1466bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1467 enum port_fdmi_event event)
1468{
1469 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1470
1471 bfa_trc(port->fcs, port->port_cfg.pwwn);
1472 bfa_trc(port->fcs, event);
1473
1474 switch (event) {
1475 case FDMISM_EVENT_RSP_ERROR:
1476 /*
1477 * if max retries have not been reached, start timer for a
1478 * delayed retry
1479 */
1480 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1481 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa_retry);
1482 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1483 &fdmi->timer,
1484 bfa_fcs_lport_fdmi_timeout, fdmi,
1485 BFA_FCS_RETRY_TIMEOUT);
1486 } else {
1487 /*
1488 * set state to offline
1489 */
1490 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1491 fdmi->retry_cnt = 0;
1492 }
1493 break;
1494
1495 case FDMISM_EVENT_RSP_OK:
1496 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1497 fdmi->retry_cnt = 0;
1498 break;
1499
1500 case FDMISM_EVENT_PORT_OFFLINE:
1501 bfa_fcxp_discard(fdmi->fcxp);
1502 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1503 break;
1504
1505 default:
1506 bfa_sm_fault(port->fcs, event);
1507 }
1508}
1509
1510static void
1511bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1512 enum port_fdmi_event event)
1513{
1514 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1515
1516 bfa_trc(port->fcs, port->port_cfg.pwwn);
1517 bfa_trc(port->fcs, event);
1518
1519 switch (event) {
1520 case FDMISM_EVENT_TIMEOUT:
1521 /*
1522 * Retry Timer Expired. Re-send
1523 */
1524 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1525 bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1526 break;
1527
1528 case FDMISM_EVENT_PORT_OFFLINE:
1529 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1530 bfa_timer_stop(&fdmi->timer);
1531 break;
1532
1533 default:
1534 bfa_sm_fault(port->fcs, event);
1535 }
1536}
1537
1538static void
1539bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1540 enum port_fdmi_event event)
1541{
1542 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1543
1544 bfa_trc(port->fcs, port->port_cfg.pwwn);
1545 bfa_trc(port->fcs, event);
1546
1547 switch (event) {
1548 case FDMISM_EVENT_PORT_OFFLINE:
1549 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1550 break;
1551
1552 default:
1553 bfa_sm_fault(port->fcs, event);
1554 }
1555}
Jing Huang5fbe25c2010-10-18 17:17:23 -07001556/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001557 * FDMI is disabled state.
1558 */
1559static void
1560bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s *fdmi,
1561 enum port_fdmi_event event)
1562{
1563 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1564
1565 bfa_trc(port->fcs, port->port_cfg.pwwn);
1566 bfa_trc(port->fcs, event);
1567
1568 /* No op State. It can only be enabled at Driver Init. */
1569}
1570
Jing Huang5fbe25c2010-10-18 17:17:23 -07001571/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001572* RHBA : Register HBA Attributes.
1573 */
1574static void
1575bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1576{
1577 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1578 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1579 struct fchs_s fchs;
1580 int len, attr_len;
1581 struct bfa_fcxp_s *fcxp;
1582 u8 *pyld;
1583
1584 bfa_trc(port->fcs, port->port_cfg.pwwn);
1585
1586 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1587 if (!fcxp) {
1588 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1589 bfa_fcs_lport_fdmi_send_rhba, fdmi);
1590 return;
1591 }
1592 fdmi->fcxp = fcxp;
1593
1594 pyld = bfa_fcxp_get_reqbuf(fcxp);
Jing Huang6a18b162010-10-18 17:08:54 -07001595 memset(pyld, 0, FC_MAX_PDUSZ);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001596
1597 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1598 FDMI_RHBA);
1599
1600 attr_len =
1601 bfa_fcs_lport_fdmi_build_rhba_pyld(fdmi,
1602 (u8 *) ((struct ct_hdr_s *) pyld
1603 + 1));
1604
1605 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1606 FC_CLASS_3, (len + attr_len), &fchs,
1607 bfa_fcs_lport_fdmi_rhba_response, (void *)fdmi,
1608 FC_MAX_PDUSZ, FC_FCCT_TOV);
1609
1610 bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
1611}
1612
1613static u16
1614bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
1615{
1616 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1617 struct bfa_fcs_fdmi_hba_attr_s hba_attr;
1618 struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr;
1619 struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld;
1620 struct fdmi_attr_s *attr;
1621 u8 *curr_ptr;
1622 u16 len, count;
Maggie50444a32010-11-29 18:26:32 -08001623 u16 templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001624
1625 /*
1626 * get hba attributes
1627 */
1628 bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
1629
1630 rhba->hba_id = bfa_fcs_lport_get_pwwn(port);
Jing Huangba816ea2010-10-18 17:10:50 -07001631 rhba->port_list.num_ports = cpu_to_be32(1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001632 rhba->port_list.port_entry = bfa_fcs_lport_get_pwwn(port);
1633
1634 len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
1635
1636 count = 0;
1637 len += sizeof(rhba->hba_attr_blk.attr_count);
1638
1639 /*
1640 * fill out the invididual entries of the HBA attrib Block
1641 */
1642 curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
1643
1644 /*
1645 * Node Name
1646 */
1647 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001648 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODENAME);
Maggie50444a32010-11-29 18:26:32 -08001649 templen = sizeof(wwn_t);
1650 memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), templen);
1651 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1652 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001653 count++;
Maggie50444a32010-11-29 18:26:32 -08001654 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1655 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001656
1657 /*
1658 * Manufacturer
1659 */
1660 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001661 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MANUFACTURER);
Maggie50444a32010-11-29 18:26:32 -08001662 templen = (u16) strlen(fcs_hba_attr->manufacturer);
1663 memcpy(attr->value, fcs_hba_attr->manufacturer, templen);
1664 templen = fc_roundup(templen, sizeof(u32));
1665 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1666 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001667 count++;
Maggie50444a32010-11-29 18:26:32 -08001668 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1669 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001670
1671 /*
1672 * Serial Number
1673 */
1674 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001675 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_SERIALNUM);
Maggie50444a32010-11-29 18:26:32 -08001676 templen = (u16) strlen(fcs_hba_attr->serial_num);
1677 memcpy(attr->value, fcs_hba_attr->serial_num, templen);
1678 templen = fc_roundup(templen, sizeof(u32));
1679 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1680 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001681 count++;
Maggie50444a32010-11-29 18:26:32 -08001682 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1683 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001684
1685 /*
1686 * Model
1687 */
1688 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001689 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL);
Maggie50444a32010-11-29 18:26:32 -08001690 templen = (u16) strlen(fcs_hba_attr->model);
1691 memcpy(attr->value, fcs_hba_attr->model, templen);
1692 templen = fc_roundup(templen, sizeof(u32));
1693 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1694 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001695 count++;
Maggie50444a32010-11-29 18:26:32 -08001696 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1697 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001698
1699 /*
1700 * Model Desc
1701 */
1702 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001703 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL_DESC);
Maggie50444a32010-11-29 18:26:32 -08001704 templen = (u16) strlen(fcs_hba_attr->model_desc);
1705 memcpy(attr->value, fcs_hba_attr->model_desc, templen);
1706 templen = fc_roundup(templen, sizeof(u32));
1707 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1708 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001709 count++;
Maggie50444a32010-11-29 18:26:32 -08001710 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1711 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001712
1713 /*
1714 * H/W Version
1715 */
1716 if (fcs_hba_attr->hw_version[0] != '\0') {
1717 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001718 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_HW_VERSION);
Maggie50444a32010-11-29 18:26:32 -08001719 templen = (u16) strlen(fcs_hba_attr->hw_version);
1720 memcpy(attr->value, fcs_hba_attr->hw_version, templen);
1721 templen = fc_roundup(templen, sizeof(u32));
1722 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1723 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001724 count++;
Maggie50444a32010-11-29 18:26:32 -08001725 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1726 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001727 }
1728
1729 /*
1730 * Driver Version
1731 */
1732 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001733 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_DRIVER_VERSION);
Maggie50444a32010-11-29 18:26:32 -08001734 templen = (u16) strlen(fcs_hba_attr->driver_version);
1735 memcpy(attr->value, fcs_hba_attr->driver_version, templen);
1736 templen = fc_roundup(templen, sizeof(u32));
1737 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
Krishna Gudipatidd5aaf42011-06-13 15:51:24 -07001738 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001739 count++;
Maggie50444a32010-11-29 18:26:32 -08001740 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1741 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001742
1743 /*
1744 * Option Rom Version
1745 */
1746 if (fcs_hba_attr->option_rom_ver[0] != '\0') {
1747 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001748 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_ROM_VERSION);
Maggie50444a32010-11-29 18:26:32 -08001749 templen = (u16) strlen(fcs_hba_attr->option_rom_ver);
1750 memcpy(attr->value, fcs_hba_attr->option_rom_ver, templen);
1751 templen = fc_roundup(templen, sizeof(u32));
1752 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1753 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001754 count++;
Maggie50444a32010-11-29 18:26:32 -08001755 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1756 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001757 }
1758
1759 /*
1760 * f/w Version = driver version
1761 */
1762 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001763 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION);
Maggie50444a32010-11-29 18:26:32 -08001764 templen = (u16) strlen(fcs_hba_attr->driver_version);
1765 memcpy(attr->value, fcs_hba_attr->driver_version, templen);
1766 templen = fc_roundup(templen, sizeof(u32));
1767 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1768 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001769 count++;
Maggie50444a32010-11-29 18:26:32 -08001770 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1771 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001772
1773 /*
1774 * OS Name
1775 */
1776 if (fcs_hba_attr->os_name[0] != '\0') {
1777 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001778 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_OS_NAME);
Maggie50444a32010-11-29 18:26:32 -08001779 templen = (u16) strlen(fcs_hba_attr->os_name);
1780 memcpy(attr->value, fcs_hba_attr->os_name, templen);
1781 templen = fc_roundup(templen, sizeof(u32));
1782 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1783 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001784 count++;
Maggie50444a32010-11-29 18:26:32 -08001785 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1786 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001787 }
1788
1789 /*
1790 * MAX_CT_PAYLOAD
1791 */
1792 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001793 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT);
Maggie50444a32010-11-29 18:26:32 -08001794 templen = sizeof(fcs_hba_attr->max_ct_pyld);
1795 memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen);
1796 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001797 count++;
Maggie50444a32010-11-29 18:26:32 -08001798 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1799 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001800
1801 /*
1802 * Update size of payload
1803 */
Jing Huang5fbe25c2010-10-18 17:17:23 -07001804 len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001805
Jing Huangba816ea2010-10-18 17:10:50 -07001806 rhba->hba_attr_blk.attr_count = cpu_to_be32(count);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001807 return len;
1808}
1809
1810static void
1811bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
1812 void *cbarg, bfa_status_t req_status,
1813 u32 rsp_len, u32 resid_len,
1814 struct fchs_s *rsp_fchs)
1815{
1816 struct bfa_fcs_lport_fdmi_s *fdmi =
1817 (struct bfa_fcs_lport_fdmi_s *) cbarg;
1818 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1819 struct ct_hdr_s *cthdr = NULL;
1820
1821 bfa_trc(port->fcs, port->port_cfg.pwwn);
1822
1823 /*
1824 * Sanity Checks
1825 */
1826 if (req_status != BFA_STATUS_OK) {
1827 bfa_trc(port->fcs, req_status);
1828 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1829 return;
1830 }
1831
1832 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07001833 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001834
1835 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1836 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
1837 return;
1838 }
1839
1840 bfa_trc(port->fcs, cthdr->reason_code);
1841 bfa_trc(port->fcs, cthdr->exp_code);
1842 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1843}
1844
Jing Huang5fbe25c2010-10-18 17:17:23 -07001845/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001846* RPRT : Register Port
1847 */
1848static void
1849bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1850{
1851 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1852 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1853 struct fchs_s fchs;
1854 u16 len, attr_len;
1855 struct bfa_fcxp_s *fcxp;
1856 u8 *pyld;
1857
1858 bfa_trc(port->fcs, port->port_cfg.pwwn);
1859
1860 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1861 if (!fcxp) {
1862 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1863 bfa_fcs_lport_fdmi_send_rprt, fdmi);
1864 return;
1865 }
1866 fdmi->fcxp = fcxp;
1867
1868 pyld = bfa_fcxp_get_reqbuf(fcxp);
Jing Huang6a18b162010-10-18 17:08:54 -07001869 memset(pyld, 0, FC_MAX_PDUSZ);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001870
1871 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1872 FDMI_RPRT);
1873
1874 attr_len =
1875 bfa_fcs_lport_fdmi_build_rprt_pyld(fdmi,
1876 (u8 *) ((struct ct_hdr_s *) pyld
1877 + 1));
1878
1879 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1880 FC_CLASS_3, len + attr_len, &fchs,
1881 bfa_fcs_lport_fdmi_rprt_response, (void *)fdmi,
1882 FC_MAX_PDUSZ, FC_FCCT_TOV);
1883
1884 bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
1885}
1886
Jing Huang5fbe25c2010-10-18 17:17:23 -07001887/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001888 * This routine builds Port Attribute Block that used in RPA, RPRT commands.
1889 */
1890static u16
1891bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
1892 u8 *pyld)
1893{
1894 struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
1895 struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
1896 struct fdmi_attr_s *attr;
1897 u8 *curr_ptr;
1898 u16 len;
1899 u8 count = 0;
Maggie50444a32010-11-29 18:26:32 -08001900 u16 templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001901
1902 /*
1903 * get port attributes
1904 */
1905 bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
1906
1907 len = sizeof(port_attrib->attr_count);
1908
1909 /*
1910 * fill out the invididual entries
1911 */
1912 curr_ptr = (u8 *) &port_attrib->port_attr;
1913
1914 /*
1915 * FC4 Types
1916 */
1917 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001918 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FC4_TYPES);
Maggie50444a32010-11-29 18:26:32 -08001919 templen = sizeof(fcs_port_attr.supp_fc4_types);
1920 memcpy(attr->value, fcs_port_attr.supp_fc4_types, templen);
1921 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1922 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001923 ++count;
1924 attr->len =
Maggie50444a32010-11-29 18:26:32 -08001925 cpu_to_be16(templen + sizeof(attr->type) +
1926 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001927
1928 /*
1929 * Supported Speed
1930 */
1931 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001932 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_SPEED);
Maggie50444a32010-11-29 18:26:32 -08001933 templen = sizeof(fcs_port_attr.supp_speed);
1934 memcpy(attr->value, &fcs_port_attr.supp_speed, templen);
1935 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1936 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001937 ++count;
1938 attr->len =
Maggie50444a32010-11-29 18:26:32 -08001939 cpu_to_be16(templen + sizeof(attr->type) +
1940 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001941
1942 /*
1943 * current Port Speed
1944 */
1945 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001946 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SPEED);
Maggie50444a32010-11-29 18:26:32 -08001947 templen = sizeof(fcs_port_attr.curr_speed);
1948 memcpy(attr->value, &fcs_port_attr.curr_speed, templen);
1949 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1950 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001951 ++count;
Maggie50444a32010-11-29 18:26:32 -08001952 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1953 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001954
1955 /*
1956 * max frame size
1957 */
1958 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001959 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FRAME_SIZE);
Maggie50444a32010-11-29 18:26:32 -08001960 templen = sizeof(fcs_port_attr.max_frm_size);
1961 memcpy(attr->value, &fcs_port_attr.max_frm_size, templen);
1962 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1963 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001964 ++count;
Maggie50444a32010-11-29 18:26:32 -08001965 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1966 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001967
1968 /*
1969 * OS Device Name
1970 */
1971 if (fcs_port_attr.os_device_name[0] != '\0') {
1972 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001973 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_DEV_NAME);
Maggie50444a32010-11-29 18:26:32 -08001974 templen = (u16) strlen(fcs_port_attr.os_device_name);
1975 memcpy(attr->value, fcs_port_attr.os_device_name, templen);
1976 templen = fc_roundup(templen, sizeof(u32));
1977 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1978 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001979 ++count;
Maggie50444a32010-11-29 18:26:32 -08001980 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1981 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001982 }
1983 /*
1984 * Host Name
1985 */
1986 if (fcs_port_attr.host_name[0] != '\0') {
1987 attr = (struct fdmi_attr_s *) curr_ptr;
Jing Huangba816ea2010-10-18 17:10:50 -07001988 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_HOST_NAME);
Maggie50444a32010-11-29 18:26:32 -08001989 templen = (u16) strlen(fcs_port_attr.host_name);
1990 memcpy(attr->value, fcs_port_attr.host_name, templen);
1991 templen = fc_roundup(templen, sizeof(u32));
1992 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1993 len += templen;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001994 ++count;
Maggie50444a32010-11-29 18:26:32 -08001995 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1996 sizeof(templen));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001997 }
1998
1999 /*
2000 * Update size of payload
2001 */
Jing Huangba816ea2010-10-18 17:10:50 -07002002 port_attrib->attr_count = cpu_to_be32(count);
Jing Huang5fbe25c2010-10-18 17:17:23 -07002003 len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002004 return len;
2005}
2006
2007static u16
2008bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2009{
2010 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2011 struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld;
2012 u16 len;
2013
2014 rprt->hba_id = bfa_fcs_lport_get_pwwn(bfa_fcs_get_base_port(port->fcs));
2015 rprt->port_name = bfa_fcs_lport_get_pwwn(port);
2016
2017 len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2018 (u8 *) &rprt->port_attr_blk);
2019
2020 len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
2021
2022 return len;
2023}
2024
2025static void
2026bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2027 void *cbarg, bfa_status_t req_status,
2028 u32 rsp_len, u32 resid_len,
2029 struct fchs_s *rsp_fchs)
2030{
2031 struct bfa_fcs_lport_fdmi_s *fdmi =
2032 (struct bfa_fcs_lport_fdmi_s *) cbarg;
2033 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2034 struct ct_hdr_s *cthdr = NULL;
2035
2036 bfa_trc(port->fcs, port->port_cfg.pwwn);
2037
2038 /*
2039 * Sanity Checks
2040 */
2041 if (req_status != BFA_STATUS_OK) {
2042 bfa_trc(port->fcs, req_status);
2043 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2044 return;
2045 }
2046
2047 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07002048 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002049
2050 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2051 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2052 return;
2053 }
2054
2055 bfa_trc(port->fcs, cthdr->reason_code);
2056 bfa_trc(port->fcs, cthdr->exp_code);
2057 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2058}
2059
Jing Huang5fbe25c2010-10-18 17:17:23 -07002060/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002061* RPA : Register Port Attributes.
2062 */
2063static void
2064bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2065{
2066 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
2067 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2068 struct fchs_s fchs;
2069 u16 len, attr_len;
2070 struct bfa_fcxp_s *fcxp;
2071 u8 *pyld;
2072
2073 bfa_trc(port->fcs, port->port_cfg.pwwn);
2074
2075 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2076 if (!fcxp) {
2077 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
2078 bfa_fcs_lport_fdmi_send_rpa, fdmi);
2079 return;
2080 }
2081 fdmi->fcxp = fcxp;
2082
2083 pyld = bfa_fcxp_get_reqbuf(fcxp);
Jing Huang6a18b162010-10-18 17:08:54 -07002084 memset(pyld, 0, FC_MAX_PDUSZ);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002085
2086 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
2087 FDMI_RPA);
2088
Jing Huang5fbe25c2010-10-18 17:17:23 -07002089 attr_len = bfa_fcs_lport_fdmi_build_rpa_pyld(fdmi,
2090 (u8 *) ((struct ct_hdr_s *) pyld + 1));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002091
2092 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2093 FC_CLASS_3, len + attr_len, &fchs,
2094 bfa_fcs_lport_fdmi_rpa_response, (void *)fdmi,
2095 FC_MAX_PDUSZ, FC_FCCT_TOV);
2096
2097 bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
2098}
2099
2100static u16
2101bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2102{
2103 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2104 struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld;
2105 u16 len;
2106
2107 rpa->port_name = bfa_fcs_lport_get_pwwn(port);
2108
2109 len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2110 (u8 *) &rpa->port_attr_blk);
2111
2112 len += sizeof(rpa->port_name);
2113
2114 return len;
2115}
2116
2117static void
2118bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2119 void *cbarg, bfa_status_t req_status, u32 rsp_len,
2120 u32 resid_len, struct fchs_s *rsp_fchs)
2121{
2122 struct bfa_fcs_lport_fdmi_s *fdmi =
2123 (struct bfa_fcs_lport_fdmi_s *) cbarg;
2124 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2125 struct ct_hdr_s *cthdr = NULL;
2126
2127 bfa_trc(port->fcs, port->port_cfg.pwwn);
2128
2129 /*
2130 * Sanity Checks
2131 */
2132 if (req_status != BFA_STATUS_OK) {
2133 bfa_trc(port->fcs, req_status);
2134 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2135 return;
2136 }
2137
2138 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07002139 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002140
2141 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2142 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2143 return;
2144 }
2145
2146 bfa_trc(port->fcs, cthdr->reason_code);
2147 bfa_trc(port->fcs, cthdr->exp_code);
2148 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2149}
2150
2151static void
2152bfa_fcs_lport_fdmi_timeout(void *arg)
2153{
2154 struct bfa_fcs_lport_fdmi_s *fdmi = (struct bfa_fcs_lport_fdmi_s *) arg;
2155
2156 bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
2157}
2158
Maggie52f94b62010-11-29 18:21:32 -08002159static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002160bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2161 struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
2162{
2163 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2164 struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
2165
Jing Huang6a18b162010-10-18 17:08:54 -07002166 memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002167
2168 bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc,
2169 hba_attr->manufacturer);
2170 bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc,
2171 hba_attr->serial_num);
2172 bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2173 hba_attr->model);
2174 bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2175 hba_attr->model_desc);
2176 bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc,
2177 hba_attr->hw_version);
2178 bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc,
2179 hba_attr->option_rom_ver);
2180 bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc,
2181 hba_attr->fw_version);
2182
2183 strncpy(hba_attr->driver_version, (char *)driver_info->version,
2184 sizeof(hba_attr->driver_version));
2185
2186 strncpy(hba_attr->os_name, driver_info->host_os_name,
2187 sizeof(hba_attr->os_name));
2188
2189 /*
2190 * If there is a patch level, append it
2191 * to the os name along with a separator
2192 */
2193 if (driver_info->host_os_patch[0] != '\0') {
2194 strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
2195 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
2196 strncat(hba_attr->os_name, driver_info->host_os_patch,
2197 sizeof(driver_info->host_os_patch));
2198 }
2199
Jing Huangba816ea2010-10-18 17:10:50 -07002200 hba_attr->max_ct_pyld = cpu_to_be32(FC_MAX_PDUSZ);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002201}
2202
Maggie52f94b62010-11-29 18:21:32 -08002203static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002204bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2205 struct bfa_fcs_fdmi_port_attr_s *port_attr)
2206{
2207 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2208 struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
2209 struct bfa_port_attr_s pport_attr;
2210
Jing Huang6a18b162010-10-18 17:08:54 -07002211 memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002212
2213 /*
2214 * get pport attributes from hal
2215 */
2216 bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
2217
2218 /*
2219 * get FC4 type Bitmask
2220 */
2221 fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
2222
2223 /*
2224 * Supported Speeds
2225 */
Jing Huangba816ea2010-10-18 17:10:50 -07002226 port_attr->supp_speed = cpu_to_be32(BFA_FCS_FDMI_SUPORTED_SPEEDS);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002227
2228 /*
2229 * Current Speed
2230 */
Jing Huangba816ea2010-10-18 17:10:50 -07002231 port_attr->curr_speed = cpu_to_be32(pport_attr.speed);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002232
2233 /*
2234 * Max PDU Size.
2235 */
Jing Huangba816ea2010-10-18 17:10:50 -07002236 port_attr->max_frm_size = cpu_to_be32(FC_MAX_PDUSZ);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002237
2238 /*
2239 * OS device Name
2240 */
2241 strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name,
2242 sizeof(port_attr->os_device_name));
2243
2244 /*
2245 * Host name
2246 */
2247 strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
2248 sizeof(port_attr->host_name));
Jing Huang7725ccf2009-09-23 17:46:15 -07002249
2250}
2251
2252
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002253void
2254bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
2255{
2256 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2257
2258 fdmi->ms = ms;
2259 if (ms->port->fcs->fdmi_enabled)
2260 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
2261 else
2262 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_disabled);
2263}
2264
2265void
2266bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms)
2267{
2268 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2269
2270 fdmi->ms = ms;
2271 bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
2272}
2273
2274void
2275bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms)
2276{
2277 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2278
2279 fdmi->ms = ms;
2280 bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
2281}
2282
2283#define BFA_FCS_MS_CMD_MAX_RETRIES 2
2284
2285/*
2286 * forward declarations
2287 */
2288static void bfa_fcs_lport_ms_send_plogi(void *ms_cbarg,
2289 struct bfa_fcxp_s *fcxp_alloced);
2290static void bfa_fcs_lport_ms_timeout(void *arg);
2291static void bfa_fcs_lport_ms_plogi_response(void *fcsarg,
2292 struct bfa_fcxp_s *fcxp,
2293 void *cbarg,
2294 bfa_status_t req_status,
2295 u32 rsp_len,
2296 u32 resid_len,
2297 struct fchs_s *rsp_fchs);
2298
2299static void bfa_fcs_lport_ms_send_gmal(void *ms_cbarg,
2300 struct bfa_fcxp_s *fcxp_alloced);
2301static void bfa_fcs_lport_ms_gmal_response(void *fcsarg,
2302 struct bfa_fcxp_s *fcxp,
2303 void *cbarg,
2304 bfa_status_t req_status,
2305 u32 rsp_len,
2306 u32 resid_len,
2307 struct fchs_s *rsp_fchs);
2308static void bfa_fcs_lport_ms_send_gfn(void *ms_cbarg,
2309 struct bfa_fcxp_s *fcxp_alloced);
2310static void bfa_fcs_lport_ms_gfn_response(void *fcsarg,
2311 struct bfa_fcxp_s *fcxp,
2312 void *cbarg,
2313 bfa_status_t req_status,
2314 u32 rsp_len,
2315 u32 resid_len,
2316 struct fchs_s *rsp_fchs);
Jing Huang5fbe25c2010-10-18 17:17:23 -07002317/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002318 * fcs_ms_sm FCS MS state machine
2319 */
2320
Jing Huang5fbe25c2010-10-18 17:17:23 -07002321/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002322 * MS State Machine events
2323 */
2324enum port_ms_event {
2325 MSSM_EVENT_PORT_ONLINE = 1,
2326 MSSM_EVENT_PORT_OFFLINE = 2,
2327 MSSM_EVENT_RSP_OK = 3,
2328 MSSM_EVENT_RSP_ERROR = 4,
2329 MSSM_EVENT_TIMEOUT = 5,
2330 MSSM_EVENT_FCXP_SENT = 6,
2331 MSSM_EVENT_PORT_FABRIC_RSCN = 7
2332};
2333
2334static void bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2335 enum port_ms_event event);
2336static void bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2337 enum port_ms_event event);
2338static void bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2339 enum port_ms_event event);
2340static void bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2341 enum port_ms_event event);
2342static void bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2343 enum port_ms_event event);
2344static void bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2345 enum port_ms_event event);
2346static void bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2347 enum port_ms_event event);
2348static void bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2349 enum port_ms_event event);
2350static void bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2351 enum port_ms_event event);
2352static void bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2353 enum port_ms_event event);
2354static void bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2355 enum port_ms_event event);
Jing Huang5fbe25c2010-10-18 17:17:23 -07002356/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002357 * Start in offline state - awaiting NS to send start.
2358 */
2359static void
2360bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2361 enum port_ms_event event)
2362{
2363 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2364 bfa_trc(ms->port->fcs, event);
2365
2366 switch (event) {
2367 case MSSM_EVENT_PORT_ONLINE:
2368 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2369 bfa_fcs_lport_ms_send_plogi(ms, NULL);
2370 break;
2371
2372 case MSSM_EVENT_PORT_OFFLINE:
2373 break;
2374
2375 default:
2376 bfa_sm_fault(ms->port->fcs, event);
2377 }
2378}
2379
2380static void
2381bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2382 enum port_ms_event event)
2383{
2384 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2385 bfa_trc(ms->port->fcs, event);
2386
2387 switch (event) {
2388 case MSSM_EVENT_FCXP_SENT:
2389 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi);
2390 break;
2391
2392 case MSSM_EVENT_PORT_OFFLINE:
2393 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2394 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2395 &ms->fcxp_wqe);
2396 break;
2397
2398 default:
2399 bfa_sm_fault(ms->port->fcs, event);
2400 }
2401}
2402
2403static void
2404bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2405 enum port_ms_event event)
2406{
2407 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2408 bfa_trc(ms->port->fcs, event);
2409
2410 switch (event) {
2411 case MSSM_EVENT_RSP_ERROR:
2412 /*
2413 * Start timer for a delayed retry
2414 */
2415 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_retry);
2416 ms->port->stats.ms_retries++;
2417 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2418 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2419 BFA_FCS_RETRY_TIMEOUT);
2420 break;
2421
2422 case MSSM_EVENT_RSP_OK:
2423 /*
2424 * since plogi is done, now invoke MS related sub-modules
2425 */
2426 bfa_fcs_lport_fdmi_online(ms);
2427
Jing Huang5fbe25c2010-10-18 17:17:23 -07002428 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002429 * if this is a Vport, go to online state.
2430 */
2431 if (ms->port->vport) {
2432 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2433 break;
2434 }
2435
2436 /*
2437 * For a base port we need to get the
2438 * switch's IP address.
2439 */
2440 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2441 bfa_fcs_lport_ms_send_gmal(ms, NULL);
2442 break;
2443
2444 case MSSM_EVENT_PORT_OFFLINE:
2445 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2446 bfa_fcxp_discard(ms->fcxp);
2447 break;
2448
2449 default:
2450 bfa_sm_fault(ms->port->fcs, event);
2451 }
2452}
2453
2454static void
2455bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2456 enum port_ms_event event)
2457{
2458 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2459 bfa_trc(ms->port->fcs, event);
2460
2461 switch (event) {
2462 case MSSM_EVENT_TIMEOUT:
2463 /*
2464 * Retry Timer Expired. Re-send
2465 */
2466 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2467 bfa_fcs_lport_ms_send_plogi(ms, NULL);
2468 break;
2469
2470 case MSSM_EVENT_PORT_OFFLINE:
2471 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2472 bfa_timer_stop(&ms->timer);
2473 break;
2474
2475 default:
2476 bfa_sm_fault(ms->port->fcs, event);
2477 }
2478}
2479
2480static void
2481bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2482 enum port_ms_event event)
2483{
2484 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2485 bfa_trc(ms->port->fcs, event);
2486
2487 switch (event) {
2488 case MSSM_EVENT_PORT_OFFLINE:
2489 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2490 break;
2491
2492 case MSSM_EVENT_PORT_FABRIC_RSCN:
2493 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2494 ms->retry_cnt = 0;
2495 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2496 break;
2497
2498 default:
2499 bfa_sm_fault(ms->port->fcs, event);
2500 }
2501}
2502
2503static void
2504bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2505 enum port_ms_event event)
2506{
2507 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2508 bfa_trc(ms->port->fcs, event);
2509
2510 switch (event) {
2511 case MSSM_EVENT_FCXP_SENT:
2512 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal);
2513 break;
2514
2515 case MSSM_EVENT_PORT_OFFLINE:
2516 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2517 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2518 &ms->fcxp_wqe);
2519 break;
2520
2521 default:
2522 bfa_sm_fault(ms->port->fcs, event);
2523 }
2524}
2525
2526static void
2527bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2528 enum port_ms_event event)
2529{
2530 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2531 bfa_trc(ms->port->fcs, event);
2532
2533 switch (event) {
2534 case MSSM_EVENT_RSP_ERROR:
2535 /*
2536 * Start timer for a delayed retry
2537 */
2538 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2539 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_retry);
2540 ms->port->stats.ms_retries++;
2541 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2542 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2543 BFA_FCS_RETRY_TIMEOUT);
2544 } else {
2545 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2546 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2547 ms->retry_cnt = 0;
2548 }
2549 break;
2550
2551 case MSSM_EVENT_RSP_OK:
2552 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2553 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2554 break;
2555
2556 case MSSM_EVENT_PORT_OFFLINE:
2557 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2558 bfa_fcxp_discard(ms->fcxp);
2559 break;
2560
2561 default:
2562 bfa_sm_fault(ms->port->fcs, event);
2563 }
2564}
2565
2566static void
2567bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2568 enum port_ms_event event)
2569{
2570 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2571 bfa_trc(ms->port->fcs, event);
2572
2573 switch (event) {
2574 case MSSM_EVENT_TIMEOUT:
2575 /*
2576 * Retry Timer Expired. Re-send
2577 */
2578 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2579 bfa_fcs_lport_ms_send_gmal(ms, NULL);
2580 break;
2581
2582 case MSSM_EVENT_PORT_OFFLINE:
2583 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2584 bfa_timer_stop(&ms->timer);
2585 break;
2586
2587 default:
2588 bfa_sm_fault(ms->port->fcs, event);
2589 }
2590}
Jing Huang5fbe25c2010-10-18 17:17:23 -07002591/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002592 * ms_pvt MS local functions
2593 */
2594
2595static void
2596bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2597{
2598 struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2599 bfa_fcs_lport_t *port = ms->port;
2600 struct fchs_s fchs;
2601 int len;
2602 struct bfa_fcxp_s *fcxp;
2603
2604 bfa_trc(port->fcs, port->pid);
2605
2606 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2607 if (!fcxp) {
2608 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2609 bfa_fcs_lport_ms_send_gmal, ms);
2610 return;
2611 }
2612 ms->fcxp = fcxp;
2613
2614 len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2615 bfa_fcs_lport_get_fcid(port),
Maggie Zhangf7f738122010-12-09 19:08:43 -08002616 port->fabric->lps->pr_nwwn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002617
2618 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2619 FC_CLASS_3, len, &fchs,
2620 bfa_fcs_lport_ms_gmal_response, (void *)ms,
2621 FC_MAX_PDUSZ, FC_FCCT_TOV);
2622
2623 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2624}
2625
2626static void
2627bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2628 void *cbarg, bfa_status_t req_status,
2629 u32 rsp_len, u32 resid_len,
2630 struct fchs_s *rsp_fchs)
2631{
2632 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2633 bfa_fcs_lport_t *port = ms->port;
2634 struct ct_hdr_s *cthdr = NULL;
2635 struct fcgs_gmal_resp_s *gmal_resp;
2636 struct fcgs_gmal_entry_s *gmal_entry;
2637 u32 num_entries;
2638 u8 *rsp_str;
2639
2640 bfa_trc(port->fcs, req_status);
2641 bfa_trc(port->fcs, port->port_cfg.pwwn);
2642
2643 /*
2644 * Sanity Checks
2645 */
2646 if (req_status != BFA_STATUS_OK) {
2647 bfa_trc(port->fcs, req_status);
2648 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2649 return;
2650 }
2651
2652 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07002653 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002654
2655 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2656 gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
2657
Jing Huangba816ea2010-10-18 17:10:50 -07002658 num_entries = be32_to_cpu(gmal_resp->ms_len);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002659 if (num_entries == 0) {
2660 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2661 return;
2662 }
2663 /*
2664 * The response could contain multiple Entries.
2665 * Entries for SNMP interface, etc.
2666 * We look for the entry with a telnet prefix.
2667 * First "http://" entry refers to IP addr
2668 */
2669
2670 gmal_entry = (struct fcgs_gmal_entry_s *)gmal_resp->ms_ma;
2671 while (num_entries > 0) {
2672 if (strncmp(gmal_entry->prefix,
2673 CT_GMAL_RESP_PREFIX_HTTP,
2674 sizeof(gmal_entry->prefix)) == 0) {
2675
2676 /*
2677 * if the IP address is terminating with a '/',
2678 * remove it.
2679 * Byte 0 consists of the length of the string.
2680 */
2681 rsp_str = &(gmal_entry->prefix[0]);
2682 if (rsp_str[gmal_entry->len-1] == '/')
2683 rsp_str[gmal_entry->len-1] = 0;
2684
2685 /* copy IP Address to fabric */
2686 strncpy(bfa_fcs_lport_get_fabric_ipaddr(port),
2687 gmal_entry->ip_addr,
2688 BFA_FCS_FABRIC_IPADDR_SZ);
2689 break;
2690 } else {
2691 --num_entries;
2692 ++gmal_entry;
2693 }
2694 }
2695
2696 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2697 return;
2698 }
2699
2700 bfa_trc(port->fcs, cthdr->reason_code);
2701 bfa_trc(port->fcs, cthdr->exp_code);
2702 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2703}
2704
2705static void
2706bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2707 enum port_ms_event event)
2708{
2709 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2710 bfa_trc(ms->port->fcs, event);
2711
2712 switch (event) {
2713 case MSSM_EVENT_FCXP_SENT:
2714 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn);
2715 break;
2716
2717 case MSSM_EVENT_PORT_OFFLINE:
2718 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2719 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2720 &ms->fcxp_wqe);
2721 break;
2722
2723 default:
2724 bfa_sm_fault(ms->port->fcs, event);
2725 }
2726}
2727
2728static void
2729bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2730 enum port_ms_event event)
2731{
2732 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2733 bfa_trc(ms->port->fcs, event);
2734
2735 switch (event) {
2736 case MSSM_EVENT_RSP_ERROR:
2737 /*
2738 * Start timer for a delayed retry
2739 */
2740 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2741 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_retry);
2742 ms->port->stats.ms_retries++;
2743 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2744 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2745 BFA_FCS_RETRY_TIMEOUT);
2746 } else {
2747 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2748 ms->retry_cnt = 0;
2749 }
2750 break;
2751
2752 case MSSM_EVENT_RSP_OK:
2753 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2754 break;
2755
2756 case MSSM_EVENT_PORT_OFFLINE:
2757 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2758 bfa_fcxp_discard(ms->fcxp);
2759 break;
2760
2761 default:
2762 bfa_sm_fault(ms->port->fcs, event);
2763 }
2764}
2765
2766static void
2767bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2768 enum port_ms_event event)
2769{
2770 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2771 bfa_trc(ms->port->fcs, event);
2772
2773 switch (event) {
2774 case MSSM_EVENT_TIMEOUT:
2775 /*
2776 * Retry Timer Expired. Re-send
2777 */
2778 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2779 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2780 break;
2781
2782 case MSSM_EVENT_PORT_OFFLINE:
2783 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2784 bfa_timer_stop(&ms->timer);
2785 break;
2786
2787 default:
2788 bfa_sm_fault(ms->port->fcs, event);
2789 }
2790}
Jing Huang5fbe25c2010-10-18 17:17:23 -07002791/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002792 * ms_pvt MS local functions
2793 */
2794
2795static void
2796bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2797{
2798 struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2799 bfa_fcs_lport_t *port = ms->port;
2800 struct fchs_s fchs;
2801 int len;
2802 struct bfa_fcxp_s *fcxp;
2803
2804 bfa_trc(port->fcs, port->pid);
2805
2806 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2807 if (!fcxp) {
2808 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2809 bfa_fcs_lport_ms_send_gfn, ms);
2810 return;
2811 }
2812 ms->fcxp = fcxp;
2813
2814 len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2815 bfa_fcs_lport_get_fcid(port),
Maggie Zhangf7f738122010-12-09 19:08:43 -08002816 port->fabric->lps->pr_nwwn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002817
2818 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2819 FC_CLASS_3, len, &fchs,
2820 bfa_fcs_lport_ms_gfn_response, (void *)ms,
2821 FC_MAX_PDUSZ, FC_FCCT_TOV);
2822
2823 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2824}
2825
2826static void
2827bfa_fcs_lport_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2828 void *cbarg, bfa_status_t req_status, u32 rsp_len,
2829 u32 resid_len, struct fchs_s *rsp_fchs)
2830{
2831 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2832 bfa_fcs_lport_t *port = ms->port;
2833 struct ct_hdr_s *cthdr = NULL;
2834 wwn_t *gfn_resp;
2835
2836 bfa_trc(port->fcs, req_status);
2837 bfa_trc(port->fcs, port->port_cfg.pwwn);
2838
2839 /*
2840 * Sanity Checks
2841 */
2842 if (req_status != BFA_STATUS_OK) {
2843 bfa_trc(port->fcs, req_status);
2844 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2845 return;
2846 }
2847
2848 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07002849 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002850
2851 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2852 gfn_resp = (wwn_t *)(cthdr + 1);
2853 /* check if it has actually changed */
2854 if ((memcmp((void *)&bfa_fcs_lport_get_fabric_name(port),
2855 gfn_resp, sizeof(wwn_t)) != 0)) {
2856 bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
2857 }
2858 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2859 return;
2860 }
2861
2862 bfa_trc(port->fcs, cthdr->reason_code);
2863 bfa_trc(port->fcs, cthdr->exp_code);
2864 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2865}
2866
Jing Huang5fbe25c2010-10-18 17:17:23 -07002867/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002868 * ms_pvt MS local functions
2869 */
2870
2871static void
2872bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2873{
2874 struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2875 struct bfa_fcs_lport_s *port = ms->port;
2876 struct fchs_s fchs;
2877 int len;
2878 struct bfa_fcxp_s *fcxp;
2879
2880 bfa_trc(port->fcs, port->pid);
2881
2882 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2883 if (!fcxp) {
2884 port->stats.ms_plogi_alloc_wait++;
2885 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2886 bfa_fcs_lport_ms_send_plogi, ms);
2887 return;
2888 }
2889 ms->fcxp = fcxp;
2890
2891 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
Maggie Zhangf16a1752010-12-09 19:12:32 -08002892 bfa_hton3b(FC_MGMT_SERVER),
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002893 bfa_fcs_lport_get_fcid(port), 0,
2894 port->port_cfg.pwwn, port->port_cfg.nwwn,
Krishna Gudipatibe540a92011-06-13 15:53:04 -07002895 bfa_fcport_get_maxfrsize(port->fcs->bfa),
2896 bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002897
2898 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2899 FC_CLASS_3, len, &fchs,
2900 bfa_fcs_lport_ms_plogi_response, (void *)ms,
2901 FC_MAX_PDUSZ, FC_ELS_TOV);
2902
2903 port->stats.ms_plogi_sent++;
2904 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2905}
2906
2907static void
2908bfa_fcs_lport_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2909 void *cbarg, bfa_status_t req_status,
2910 u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs)
2911{
2912 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2913 struct bfa_fcs_lport_s *port = ms->port;
2914 struct fc_els_cmd_s *els_cmd;
2915 struct fc_ls_rjt_s *ls_rjt;
2916
2917 bfa_trc(port->fcs, req_status);
2918 bfa_trc(port->fcs, port->port_cfg.pwwn);
2919
2920 /*
2921 * Sanity Checks
2922 */
2923 if (req_status != BFA_STATUS_OK) {
2924 port->stats.ms_plogi_rsp_err++;
2925 bfa_trc(port->fcs, req_status);
2926 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2927 return;
2928 }
2929
2930 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
2931
2932 switch (els_cmd->els_code) {
2933
2934 case FC_ELS_ACC:
2935 if (rsp_len < sizeof(struct fc_logi_s)) {
2936 bfa_trc(port->fcs, rsp_len);
2937 port->stats.ms_plogi_acc_err++;
2938 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2939 break;
2940 }
2941 port->stats.ms_plogi_accepts++;
2942 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2943 break;
2944
2945 case FC_ELS_LS_RJT:
2946 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
2947
2948 bfa_trc(port->fcs, ls_rjt->reason_code);
2949 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
2950
2951 port->stats.ms_rejects++;
2952 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2953 break;
2954
2955 default:
2956 port->stats.ms_plogi_unknown_rsp++;
2957 bfa_trc(port->fcs, els_cmd->els_code);
2958 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2959 }
2960}
2961
2962static void
2963bfa_fcs_lport_ms_timeout(void *arg)
2964{
2965 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) arg;
2966
2967 ms->port->stats.ms_timeouts++;
2968 bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
2969}
2970
2971
2972void
2973bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port)
2974{
2975 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2976
2977 ms->port = port;
2978 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2979
2980 /*
2981 * Invoke init routines of sub modules.
2982 */
2983 bfa_fcs_lport_fdmi_init(ms);
2984}
2985
2986void
2987bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port)
2988{
2989 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2990
2991 ms->port = port;
2992 bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
2993 bfa_fcs_lport_fdmi_offline(ms);
2994}
2995
2996void
2997bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port)
2998{
2999 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3000
3001 ms->port = port;
3002 bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
3003}
3004void
3005bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port)
3006{
3007 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3008
3009 /* todo. Handle this only when in Online state */
3010 if (bfa_sm_cmp_state(ms, bfa_fcs_lport_ms_sm_online))
3011 bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
3012}
3013
Jing Huang5fbe25c2010-10-18 17:17:23 -07003014/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003015 * @page ns_sm_info VPORT NS State Machine
3016 *
3017 * @section ns_sm_interactions VPORT NS State Machine Interactions
3018 *
3019 * @section ns_sm VPORT NS State Machine
3020 * img ns_sm.jpg
3021 */
3022
3023/*
3024 * forward declarations
3025 */
3026static void bfa_fcs_lport_ns_send_plogi(void *ns_cbarg,
3027 struct bfa_fcxp_s *fcxp_alloced);
3028static void bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg,
3029 struct bfa_fcxp_s *fcxp_alloced);
3030static void bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg,
3031 struct bfa_fcxp_s *fcxp_alloced);
3032static void bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
3033 struct bfa_fcxp_s *fcxp_alloced);
3034static void bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
3035 struct bfa_fcxp_s *fcxp_alloced);
3036static void bfa_fcs_lport_ns_timeout(void *arg);
3037static void bfa_fcs_lport_ns_plogi_response(void *fcsarg,
3038 struct bfa_fcxp_s *fcxp,
3039 void *cbarg,
3040 bfa_status_t req_status,
3041 u32 rsp_len,
3042 u32 resid_len,
3043 struct fchs_s *rsp_fchs);
3044static void bfa_fcs_lport_ns_rspn_id_response(void *fcsarg,
3045 struct bfa_fcxp_s *fcxp,
3046 void *cbarg,
3047 bfa_status_t req_status,
3048 u32 rsp_len,
3049 u32 resid_len,
3050 struct fchs_s *rsp_fchs);
3051static void bfa_fcs_lport_ns_rft_id_response(void *fcsarg,
3052 struct bfa_fcxp_s *fcxp,
3053 void *cbarg,
3054 bfa_status_t req_status,
3055 u32 rsp_len,
3056 u32 resid_len,
3057 struct fchs_s *rsp_fchs);
3058static void bfa_fcs_lport_ns_rff_id_response(void *fcsarg,
3059 struct bfa_fcxp_s *fcxp,
3060 void *cbarg,
3061 bfa_status_t req_status,
3062 u32 rsp_len,
3063 u32 resid_len,
3064 struct fchs_s *rsp_fchs);
3065static void bfa_fcs_lport_ns_gid_ft_response(void *fcsarg,
3066 struct bfa_fcxp_s *fcxp,
3067 void *cbarg,
3068 bfa_status_t req_status,
3069 u32 rsp_len,
3070 u32 resid_len,
3071 struct fchs_s *rsp_fchs);
3072static void bfa_fcs_lport_ns_process_gidft_pids(
3073 struct bfa_fcs_lport_s *port,
3074 u32 *pid_buf, u32 n_pids);
3075
3076static void bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port);
Jing Huang5fbe25c2010-10-18 17:17:23 -07003077/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003078 * fcs_ns_sm FCS nameserver interface state machine
3079 */
3080
Jing Huang5fbe25c2010-10-18 17:17:23 -07003081/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003082 * VPort NS State Machine events
3083 */
3084enum vport_ns_event {
3085 NSSM_EVENT_PORT_ONLINE = 1,
3086 NSSM_EVENT_PORT_OFFLINE = 2,
3087 NSSM_EVENT_PLOGI_SENT = 3,
3088 NSSM_EVENT_RSP_OK = 4,
3089 NSSM_EVENT_RSP_ERROR = 5,
3090 NSSM_EVENT_TIMEOUT = 6,
3091 NSSM_EVENT_NS_QUERY = 7,
3092 NSSM_EVENT_RSPNID_SENT = 8,
3093 NSSM_EVENT_RFTID_SENT = 9,
3094 NSSM_EVENT_RFFID_SENT = 10,
3095 NSSM_EVENT_GIDFT_SENT = 11,
3096};
3097
3098static void bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3099 enum vport_ns_event event);
3100static void bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3101 enum vport_ns_event event);
3102static void bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3103 enum vport_ns_event event);
3104static void bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3105 enum vport_ns_event event);
3106static void bfa_fcs_lport_ns_sm_sending_rspn_id(
3107 struct bfa_fcs_lport_ns_s *ns,
3108 enum vport_ns_event event);
3109static void bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3110 enum vport_ns_event event);
3111static void bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3112 enum vport_ns_event event);
3113static void bfa_fcs_lport_ns_sm_sending_rft_id(
3114 struct bfa_fcs_lport_ns_s *ns,
3115 enum vport_ns_event event);
3116static void bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3117 enum vport_ns_event event);
3118static void bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3119 enum vport_ns_event event);
3120static void bfa_fcs_lport_ns_sm_sending_rff_id(
3121 struct bfa_fcs_lport_ns_s *ns,
3122 enum vport_ns_event event);
3123static void bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3124 enum vport_ns_event event);
3125static void bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3126 enum vport_ns_event event);
3127static void bfa_fcs_lport_ns_sm_sending_gid_ft(
3128 struct bfa_fcs_lport_ns_s *ns,
3129 enum vport_ns_event event);
3130static void bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3131 enum vport_ns_event event);
3132static void bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3133 enum vport_ns_event event);
3134static void bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3135 enum vport_ns_event event);
Jing Huang5fbe25c2010-10-18 17:17:23 -07003136/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003137 * Start in offline state - awaiting linkup
3138 */
3139static void
3140bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3141 enum vport_ns_event event)
3142{
3143 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3144 bfa_trc(ns->port->fcs, event);
3145
3146 switch (event) {
3147 case NSSM_EVENT_PORT_ONLINE:
3148 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3149 bfa_fcs_lport_ns_send_plogi(ns, NULL);
3150 break;
3151
3152 case NSSM_EVENT_PORT_OFFLINE:
3153 break;
3154
3155 default:
3156 bfa_sm_fault(ns->port->fcs, event);
3157 }
3158}
3159
3160static void
3161bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3162 enum vport_ns_event event)
3163{
3164 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3165 bfa_trc(ns->port->fcs, event);
3166
3167 switch (event) {
3168 case NSSM_EVENT_PLOGI_SENT:
3169 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi);
3170 break;
3171
3172 case NSSM_EVENT_PORT_OFFLINE:
3173 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3174 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3175 &ns->fcxp_wqe);
3176 break;
3177
3178 default:
3179 bfa_sm_fault(ns->port->fcs, event);
3180 }
3181}
3182
3183static void
3184bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3185 enum vport_ns_event event)
3186{
3187 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3188 bfa_trc(ns->port->fcs, event);
3189
3190 switch (event) {
3191 case NSSM_EVENT_RSP_ERROR:
3192 /*
3193 * Start timer for a delayed retry
3194 */
3195 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_retry);
3196 ns->port->stats.ns_retries++;
3197 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3198 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3199 BFA_FCS_RETRY_TIMEOUT);
3200 break;
3201
3202 case NSSM_EVENT_RSP_OK:
3203 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3204 bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3205 break;
3206
3207 case NSSM_EVENT_PORT_OFFLINE:
3208 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3209 bfa_fcxp_discard(ns->fcxp);
3210 break;
3211
3212 default:
3213 bfa_sm_fault(ns->port->fcs, event);
3214 }
3215}
3216
3217static void
3218bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3219 enum vport_ns_event event)
3220{
3221 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3222 bfa_trc(ns->port->fcs, event);
3223
3224 switch (event) {
3225 case NSSM_EVENT_TIMEOUT:
3226 /*
3227 * Retry Timer Expired. Re-send
3228 */
3229 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3230 bfa_fcs_lport_ns_send_plogi(ns, NULL);
3231 break;
3232
3233 case NSSM_EVENT_PORT_OFFLINE:
3234 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3235 bfa_timer_stop(&ns->timer);
3236 break;
3237
3238 default:
3239 bfa_sm_fault(ns->port->fcs, event);
3240 }
3241}
3242
3243static void
3244bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3245 enum vport_ns_event event)
3246{
3247 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3248 bfa_trc(ns->port->fcs, event);
3249
3250 switch (event) {
3251 case NSSM_EVENT_RSPNID_SENT:
3252 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id);
3253 break;
3254
3255 case NSSM_EVENT_PORT_OFFLINE:
3256 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3257 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3258 &ns->fcxp_wqe);
3259 break;
3260
3261 default:
3262 bfa_sm_fault(ns->port->fcs, event);
3263 }
3264}
3265
3266static void
3267bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3268 enum vport_ns_event event)
3269{
3270 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3271 bfa_trc(ns->port->fcs, event);
3272
3273 switch (event) {
3274 case NSSM_EVENT_RSP_ERROR:
3275 /*
3276 * Start timer for a delayed retry
3277 */
3278 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry);
3279 ns->port->stats.ns_retries++;
3280 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3281 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3282 BFA_FCS_RETRY_TIMEOUT);
3283 break;
3284
3285 case NSSM_EVENT_RSP_OK:
3286 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
3287 bfa_fcs_lport_ns_send_rft_id(ns, NULL);
3288 break;
3289
3290 case NSSM_EVENT_PORT_OFFLINE:
3291 bfa_fcxp_discard(ns->fcxp);
3292 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3293 break;
3294
3295 default:
3296 bfa_sm_fault(ns->port->fcs, event);
3297 }
3298}
3299
3300static void
3301bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3302 enum vport_ns_event event)
3303{
3304 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3305 bfa_trc(ns->port->fcs, event);
3306
3307 switch (event) {
3308 case NSSM_EVENT_TIMEOUT:
3309 /*
3310 * Retry Timer Expired. Re-send
3311 */
3312 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3313 bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3314 break;
3315
3316 case NSSM_EVENT_PORT_OFFLINE:
3317 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3318 bfa_timer_stop(&ns->timer);
3319 break;
3320
3321 default:
3322 bfa_sm_fault(ns->port->fcs, event);
3323 }
3324}
3325
3326static void
3327bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s *ns,
3328 enum vport_ns_event event)
3329{
3330 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3331 bfa_trc(ns->port->fcs, event);
3332
3333 switch (event) {
3334 case NSSM_EVENT_RFTID_SENT:
3335 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id);
3336 break;
3337
3338 case NSSM_EVENT_PORT_OFFLINE:
3339 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3340 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3341 &ns->fcxp_wqe);
3342 break;
3343
3344 default:
3345 bfa_sm_fault(ns->port->fcs, event);
3346 }
3347}
3348
3349static void
3350bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3351 enum vport_ns_event event)
3352{
3353 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3354 bfa_trc(ns->port->fcs, event);
3355
3356 switch (event) {
3357 case NSSM_EVENT_RSP_OK:
3358 /* Now move to register FC4 Features */
3359 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
3360 bfa_fcs_lport_ns_send_rff_id(ns, NULL);
3361 break;
3362
3363 case NSSM_EVENT_RSP_ERROR:
3364 /*
3365 * Start timer for a delayed retry
3366 */
3367 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id_retry);
3368 ns->port->stats.ns_retries++;
3369 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3370 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3371 BFA_FCS_RETRY_TIMEOUT);
3372 break;
3373
3374 case NSSM_EVENT_PORT_OFFLINE:
3375 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3376 bfa_fcxp_discard(ns->fcxp);
3377 break;
3378
3379 default:
3380 bfa_sm_fault(ns->port->fcs, event);
3381 }
3382}
3383
3384static void
3385bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3386 enum vport_ns_event event)
3387{
3388 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3389 bfa_trc(ns->port->fcs, event);
3390
3391 switch (event) {
3392 case NSSM_EVENT_TIMEOUT:
3393 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
3394 bfa_fcs_lport_ns_send_rft_id(ns, NULL);
3395 break;
3396
3397 case NSSM_EVENT_PORT_OFFLINE:
3398 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3399 bfa_timer_stop(&ns->timer);
3400 break;
3401
3402 default:
3403 bfa_sm_fault(ns->port->fcs, event);
3404 }
3405}
3406
3407static void
3408bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s *ns,
3409 enum vport_ns_event event)
3410{
3411 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3412 bfa_trc(ns->port->fcs, event);
3413
3414 switch (event) {
3415 case NSSM_EVENT_RFFID_SENT:
3416 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id);
3417 break;
3418
3419 case NSSM_EVENT_PORT_OFFLINE:
3420 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3421 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3422 &ns->fcxp_wqe);
3423 break;
3424
3425 default:
3426 bfa_sm_fault(ns->port->fcs, event);
3427 }
3428}
3429
3430static void
3431bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3432 enum vport_ns_event event)
3433{
3434 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3435 bfa_trc(ns->port->fcs, event);
3436
3437 switch (event) {
3438 case NSSM_EVENT_RSP_OK:
3439
3440 /*
3441 * If min cfg mode is enabled, we donot initiate rport
3442 * discovery with the fabric. Instead, we will retrieve the
3443 * boot targets from HAL/FW.
3444 */
3445 if (__fcs_min_cfg(ns->port->fcs)) {
3446 bfa_fcs_lport_ns_boot_target_disc(ns->port);
3447 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
3448 return;
3449 }
3450
3451 /*
3452 * If the port role is Initiator Mode issue NS query.
3453 * If it is Target Mode, skip this and go to online.
3454 */
3455 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
3456 bfa_sm_set_state(ns,
3457 bfa_fcs_lport_ns_sm_sending_gid_ft);
3458 bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3459 }
3460 /*
3461 * kick off mgmt srvr state machine
3462 */
3463 bfa_fcs_lport_ms_online(ns->port);
3464 break;
3465
3466 case NSSM_EVENT_RSP_ERROR:
3467 /*
3468 * Start timer for a delayed retry
3469 */
3470 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id_retry);
3471 ns->port->stats.ns_retries++;
3472 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3473 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3474 BFA_FCS_RETRY_TIMEOUT);
3475 break;
3476
3477 case NSSM_EVENT_PORT_OFFLINE:
3478 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3479 bfa_fcxp_discard(ns->fcxp);
3480 break;
3481
3482 default:
3483 bfa_sm_fault(ns->port->fcs, event);
3484 }
3485}
3486
3487static void
3488bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3489 enum vport_ns_event event)
3490{
3491 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3492 bfa_trc(ns->port->fcs, event);
3493
3494 switch (event) {
3495 case NSSM_EVENT_TIMEOUT:
3496 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
3497 bfa_fcs_lport_ns_send_rff_id(ns, NULL);
3498 break;
3499
3500 case NSSM_EVENT_PORT_OFFLINE:
3501 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3502 bfa_timer_stop(&ns->timer);
3503 break;
3504
3505 default:
3506 bfa_sm_fault(ns->port->fcs, event);
3507 }
3508}
3509static void
3510bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3511 enum vport_ns_event event)
3512{
3513 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3514 bfa_trc(ns->port->fcs, event);
3515
3516 switch (event) {
3517 case NSSM_EVENT_GIDFT_SENT:
3518 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft);
3519 break;
3520
3521 case NSSM_EVENT_PORT_OFFLINE:
3522 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3523 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3524 &ns->fcxp_wqe);
3525 break;
3526
3527 default:
3528 bfa_sm_fault(ns->port->fcs, event);
3529 }
3530}
3531
3532static void
3533bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3534 enum vport_ns_event event)
3535{
3536 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3537 bfa_trc(ns->port->fcs, event);
3538
3539 switch (event) {
3540 case NSSM_EVENT_RSP_OK:
3541 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
3542 break;
3543
3544 case NSSM_EVENT_RSP_ERROR:
3545 /*
3546 * TBD: for certain reject codes, we don't need to retry
3547 */
3548 /*
3549 * Start timer for a delayed retry
3550 */
3551 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft_retry);
3552 ns->port->stats.ns_retries++;
3553 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3554 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3555 BFA_FCS_RETRY_TIMEOUT);
3556 break;
3557
3558 case NSSM_EVENT_PORT_OFFLINE:
3559 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3560 bfa_fcxp_discard(ns->fcxp);
3561 break;
3562
3563 case NSSM_EVENT_NS_QUERY:
3564 break;
3565
3566 default:
3567 bfa_sm_fault(ns->port->fcs, event);
3568 }
3569}
3570
3571static void
3572bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3573 enum vport_ns_event event)
3574{
3575 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3576 bfa_trc(ns->port->fcs, event);
3577
3578 switch (event) {
3579 case NSSM_EVENT_TIMEOUT:
3580 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_gid_ft);
3581 bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3582 break;
3583
3584 case NSSM_EVENT_PORT_OFFLINE:
3585 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3586 bfa_timer_stop(&ns->timer);
3587 break;
3588
3589 default:
3590 bfa_sm_fault(ns->port->fcs, event);
3591 }
3592}
3593
3594static void
3595bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3596 enum vport_ns_event event)
3597{
3598 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3599 bfa_trc(ns->port->fcs, event);
3600
3601 switch (event) {
3602 case NSSM_EVENT_PORT_OFFLINE:
3603 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3604 break;
3605
3606 case NSSM_EVENT_NS_QUERY:
3607 /*
3608 * If the port role is Initiator Mode issue NS query.
3609 * If it is Target Mode, skip this and go to online.
3610 */
3611 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
3612 bfa_sm_set_state(ns,
3613 bfa_fcs_lport_ns_sm_sending_gid_ft);
3614 bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3615 };
3616 break;
3617
3618 default:
3619 bfa_sm_fault(ns->port->fcs, event);
3620 }
3621}
3622
3623
3624
Jing Huang5fbe25c2010-10-18 17:17:23 -07003625/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003626 * ns_pvt Nameserver local functions
3627 */
3628
3629static void
3630bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3631{
3632 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3633 struct bfa_fcs_lport_s *port = ns->port;
3634 struct fchs_s fchs;
3635 int len;
3636 struct bfa_fcxp_s *fcxp;
3637
3638 bfa_trc(port->fcs, port->pid);
3639
Krishna Gudipatibe540a92011-06-13 15:53:04 -07003640 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003641 if (!fcxp) {
3642 port->stats.ns_plogi_alloc_wait++;
3643 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3644 bfa_fcs_lport_ns_send_plogi, ns);
3645 return;
3646 }
3647 ns->fcxp = fcxp;
3648
3649 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
Maggie Zhangf16a1752010-12-09 19:12:32 -08003650 bfa_hton3b(FC_NAME_SERVER),
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003651 bfa_fcs_lport_get_fcid(port), 0,
3652 port->port_cfg.pwwn, port->port_cfg.nwwn,
Krishna Gudipatibe540a92011-06-13 15:53:04 -07003653 bfa_fcport_get_maxfrsize(port->fcs->bfa),
3654 bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003655
3656 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3657 FC_CLASS_3, len, &fchs,
3658 bfa_fcs_lport_ns_plogi_response, (void *)ns,
3659 FC_MAX_PDUSZ, FC_ELS_TOV);
3660 port->stats.ns_plogi_sent++;
3661
3662 bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
3663}
3664
3665static void
3666bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3667 void *cbarg, bfa_status_t req_status, u32 rsp_len,
3668 u32 resid_len, struct fchs_s *rsp_fchs)
3669{
3670 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3671 struct bfa_fcs_lport_s *port = ns->port;
3672 /* struct fc_logi_s *plogi_resp; */
3673 struct fc_els_cmd_s *els_cmd;
3674 struct fc_ls_rjt_s *ls_rjt;
3675
3676 bfa_trc(port->fcs, req_status);
3677 bfa_trc(port->fcs, port->port_cfg.pwwn);
3678
3679 /*
3680 * Sanity Checks
3681 */
3682 if (req_status != BFA_STATUS_OK) {
3683 bfa_trc(port->fcs, req_status);
3684 port->stats.ns_plogi_rsp_err++;
3685 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3686 return;
3687 }
3688
3689 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
3690
3691 switch (els_cmd->els_code) {
3692
3693 case FC_ELS_ACC:
3694 if (rsp_len < sizeof(struct fc_logi_s)) {
3695 bfa_trc(port->fcs, rsp_len);
3696 port->stats.ns_plogi_acc_err++;
3697 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3698 break;
3699 }
3700 port->stats.ns_plogi_accepts++;
3701 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3702 break;
3703
3704 case FC_ELS_LS_RJT:
3705 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
3706
3707 bfa_trc(port->fcs, ls_rjt->reason_code);
3708 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
3709
3710 port->stats.ns_rejects++;
3711
3712 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3713 break;
3714
3715 default:
3716 port->stats.ns_plogi_unknown_rsp++;
3717 bfa_trc(port->fcs, els_cmd->els_code);
3718 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3719 }
3720}
3721
Jing Huang5fbe25c2010-10-18 17:17:23 -07003722/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003723 * Register the symbolic port name.
3724 */
3725static void
3726bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3727{
3728 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3729 struct bfa_fcs_lport_s *port = ns->port;
3730 struct fchs_s fchs;
3731 int len;
3732 struct bfa_fcxp_s *fcxp;
3733 u8 symbl[256];
3734 u8 *psymbl = &symbl[0];
3735
Jing Huang6a18b162010-10-18 17:08:54 -07003736 memset(symbl, 0, sizeof(symbl));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003737
3738 bfa_trc(port->fcs, port->port_cfg.pwwn);
3739
3740 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3741 if (!fcxp) {
3742 port->stats.ns_rspnid_alloc_wait++;
3743 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3744 bfa_fcs_lport_ns_send_rspn_id, ns);
3745 return;
3746 }
3747 ns->fcxp = fcxp;
3748
3749 /*
3750 * for V-Port, form a Port Symbolic Name
3751 */
3752 if (port->vport) {
Jing Huang5fbe25c2010-10-18 17:17:23 -07003753 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003754 * For Vports, we append the vport's port symbolic name
3755 * to that of the base port.
3756 */
3757
3758 strncpy((char *)psymbl,
3759 (char *) &
3760 (bfa_fcs_lport_get_psym_name
3761 (bfa_fcs_get_base_port(port->fcs))),
3762 strlen((char *) &
3763 bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
3764 (port->fcs))));
3765
3766 /* Ensure we have a null terminating string. */
3767 ((char *)psymbl)[strlen((char *) &
3768 bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
3769 (port->fcs)))] = 0;
3770 strncat((char *)psymbl,
3771 (char *) &(bfa_fcs_lport_get_psym_name(port)),
3772 strlen((char *) &bfa_fcs_lport_get_psym_name(port)));
3773 } else {
3774 psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port));
3775 }
3776
3777 len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3778 bfa_fcs_lport_get_fcid(port), 0, psymbl);
3779
3780 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3781 FC_CLASS_3, len, &fchs,
3782 bfa_fcs_lport_ns_rspn_id_response, (void *)ns,
3783 FC_MAX_PDUSZ, FC_FCCT_TOV);
3784
3785 port->stats.ns_rspnid_sent++;
3786
3787 bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
3788}
3789
3790static void
3791bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3792 void *cbarg, bfa_status_t req_status,
3793 u32 rsp_len, u32 resid_len,
3794 struct fchs_s *rsp_fchs)
3795{
3796 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3797 struct bfa_fcs_lport_s *port = ns->port;
3798 struct ct_hdr_s *cthdr = NULL;
3799
3800 bfa_trc(port->fcs, port->port_cfg.pwwn);
3801
3802 /*
3803 * Sanity Checks
3804 */
3805 if (req_status != BFA_STATUS_OK) {
3806 bfa_trc(port->fcs, req_status);
3807 port->stats.ns_rspnid_rsp_err++;
3808 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3809 return;
3810 }
3811
3812 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07003813 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003814
3815 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3816 port->stats.ns_rspnid_accepts++;
3817 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3818 return;
3819 }
3820
3821 port->stats.ns_rspnid_rejects++;
3822 bfa_trc(port->fcs, cthdr->reason_code);
3823 bfa_trc(port->fcs, cthdr->exp_code);
3824 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3825}
3826
Jing Huang5fbe25c2010-10-18 17:17:23 -07003827/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003828 * Register FC4-Types
3829 */
3830static void
3831bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3832{
3833 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3834 struct bfa_fcs_lport_s *port = ns->port;
3835 struct fchs_s fchs;
3836 int len;
3837 struct bfa_fcxp_s *fcxp;
3838
3839 bfa_trc(port->fcs, port->port_cfg.pwwn);
3840
3841 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3842 if (!fcxp) {
3843 port->stats.ns_rftid_alloc_wait++;
3844 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3845 bfa_fcs_lport_ns_send_rft_id, ns);
3846 return;
3847 }
3848 ns->fcxp = fcxp;
3849
3850 len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3851 bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.roles);
3852
3853 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3854 FC_CLASS_3, len, &fchs,
3855 bfa_fcs_lport_ns_rft_id_response, (void *)ns,
3856 FC_MAX_PDUSZ, FC_FCCT_TOV);
3857
3858 port->stats.ns_rftid_sent++;
3859 bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
3860}
3861
3862static void
3863bfa_fcs_lport_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3864 void *cbarg, bfa_status_t req_status,
3865 u32 rsp_len, u32 resid_len,
3866 struct fchs_s *rsp_fchs)
3867{
3868 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3869 struct bfa_fcs_lport_s *port = ns->port;
3870 struct ct_hdr_s *cthdr = NULL;
3871
3872 bfa_trc(port->fcs, port->port_cfg.pwwn);
3873
3874 /*
3875 * Sanity Checks
3876 */
3877 if (req_status != BFA_STATUS_OK) {
3878 bfa_trc(port->fcs, req_status);
3879 port->stats.ns_rftid_rsp_err++;
3880 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3881 return;
3882 }
3883
3884 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07003885 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003886
3887 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3888 port->stats.ns_rftid_accepts++;
3889 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3890 return;
3891 }
3892
3893 port->stats.ns_rftid_rejects++;
3894 bfa_trc(port->fcs, cthdr->reason_code);
3895 bfa_trc(port->fcs, cthdr->exp_code);
3896 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3897}
3898
Jing Huang5fbe25c2010-10-18 17:17:23 -07003899/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003900 * Register FC4-Features : Should be done after RFT_ID
3901 */
3902static void
3903bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3904{
3905 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3906 struct bfa_fcs_lport_s *port = ns->port;
3907 struct fchs_s fchs;
3908 int len;
3909 struct bfa_fcxp_s *fcxp;
3910 u8 fc4_ftrs = 0;
3911
3912 bfa_trc(port->fcs, port->port_cfg.pwwn);
3913
3914 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3915 if (!fcxp) {
3916 port->stats.ns_rffid_alloc_wait++;
3917 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3918 bfa_fcs_lport_ns_send_rff_id, ns);
3919 return;
3920 }
3921 ns->fcxp = fcxp;
3922
3923 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
3924 fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
3925
3926 len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3927 bfa_fcs_lport_get_fcid(port), 0,
3928 FC_TYPE_FCP, fc4_ftrs);
3929
3930 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3931 FC_CLASS_3, len, &fchs,
3932 bfa_fcs_lport_ns_rff_id_response, (void *)ns,
3933 FC_MAX_PDUSZ, FC_FCCT_TOV);
3934
3935 port->stats.ns_rffid_sent++;
3936 bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
3937}
3938
3939static void
3940bfa_fcs_lport_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3941 void *cbarg, bfa_status_t req_status,
3942 u32 rsp_len, u32 resid_len,
3943 struct fchs_s *rsp_fchs)
3944{
3945 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3946 struct bfa_fcs_lport_s *port = ns->port;
3947 struct ct_hdr_s *cthdr = NULL;
3948
3949 bfa_trc(port->fcs, port->port_cfg.pwwn);
3950
3951 /*
3952 * Sanity Checks
3953 */
3954 if (req_status != BFA_STATUS_OK) {
3955 bfa_trc(port->fcs, req_status);
3956 port->stats.ns_rffid_rsp_err++;
3957 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3958 return;
3959 }
3960
3961 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07003962 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003963
3964 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3965 port->stats.ns_rffid_accepts++;
3966 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3967 return;
3968 }
3969
3970 port->stats.ns_rffid_rejects++;
3971 bfa_trc(port->fcs, cthdr->reason_code);
3972 bfa_trc(port->fcs, cthdr->exp_code);
3973
3974 if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
3975 /* if this command is not supported, we don't retry */
3976 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3977 } else
3978 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3979}
Jing Huang5fbe25c2010-10-18 17:17:23 -07003980/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003981 * Query Fabric for FC4-Types Devices.
3982 *
3983* TBD : Need to use a local (FCS private) response buffer, since the response
3984 * can be larger than 2K.
3985 */
3986static void
3987bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3988{
3989 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3990 struct bfa_fcs_lport_s *port = ns->port;
3991 struct fchs_s fchs;
3992 int len;
3993 struct bfa_fcxp_s *fcxp;
3994
3995 bfa_trc(port->fcs, port->pid);
3996
3997 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3998 if (!fcxp) {
3999 port->stats.ns_gidft_alloc_wait++;
4000 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4001 bfa_fcs_lport_ns_send_gid_ft, ns);
4002 return;
4003 }
4004 ns->fcxp = fcxp;
4005
4006 /*
4007 * This query is only initiated for FCP initiator mode.
4008 */
4009 len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4010 ns->port->pid, FC_TYPE_FCP);
4011
4012 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4013 FC_CLASS_3, len, &fchs,
4014 bfa_fcs_lport_ns_gid_ft_response, (void *)ns,
4015 bfa_fcxp_get_maxrsp(port->fcs->bfa), FC_FCCT_TOV);
4016
4017 port->stats.ns_gidft_sent++;
4018
4019 bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
4020}
4021
4022static void
4023bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4024 void *cbarg, bfa_status_t req_status,
4025 u32 rsp_len, u32 resid_len,
4026 struct fchs_s *rsp_fchs)
4027{
4028 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4029 struct bfa_fcs_lport_s *port = ns->port;
4030 struct ct_hdr_s *cthdr = NULL;
4031 u32 n_pids;
4032
4033 bfa_trc(port->fcs, port->port_cfg.pwwn);
4034
4035 /*
4036 * Sanity Checks
4037 */
4038 if (req_status != BFA_STATUS_OK) {
4039 bfa_trc(port->fcs, req_status);
4040 port->stats.ns_gidft_rsp_err++;
4041 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4042 return;
4043 }
4044
4045 if (resid_len != 0) {
4046 /*
4047 * TBD : we will need to allocate a larger buffer & retry the
4048 * command
4049 */
4050 bfa_trc(port->fcs, rsp_len);
4051 bfa_trc(port->fcs, resid_len);
4052 return;
4053 }
4054
4055 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07004056 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004057
4058 switch (cthdr->cmd_rsp_code) {
4059
4060 case CT_RSP_ACCEPT:
4061
4062 port->stats.ns_gidft_accepts++;
4063 n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32));
4064 bfa_trc(port->fcs, n_pids);
4065 bfa_fcs_lport_ns_process_gidft_pids(port,
4066 (u32 *) (cthdr + 1),
4067 n_pids);
4068 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4069 break;
4070
4071 case CT_RSP_REJECT:
4072
4073 /*
4074 * Check the reason code & explanation.
4075 * There may not have been any FC4 devices in the fabric
4076 */
4077 port->stats.ns_gidft_rejects++;
4078 bfa_trc(port->fcs, cthdr->reason_code);
4079 bfa_trc(port->fcs, cthdr->exp_code);
4080
4081 if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
4082 && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
4083
4084 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4085 } else {
4086 /*
4087 * for all other errors, retry
4088 */
4089 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4090 }
4091 break;
4092
4093 default:
4094 port->stats.ns_gidft_unknown_rsp++;
4095 bfa_trc(port->fcs, cthdr->cmd_rsp_code);
4096 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4097 }
4098}
4099
Jing Huang5fbe25c2010-10-18 17:17:23 -07004100/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004101 * This routine will be called by bfa_timer on timer timeouts.
4102 *
4103 * param[in] port - pointer to bfa_fcs_lport_t.
4104 *
4105 * return
4106 * void
4107 *
4108 * Special Considerations:
4109 *
4110 * note
4111 */
4112static void
4113bfa_fcs_lport_ns_timeout(void *arg)
4114{
4115 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) arg;
4116
4117 ns->port->stats.ns_timeouts++;
4118 bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
4119}
4120
4121/*
4122 * Process the PID list in GID_FT response
4123 */
4124static void
4125bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
4126 u32 n_pids)
4127{
4128 struct fcgs_gidft_resp_s *gidft_entry;
4129 struct bfa_fcs_rport_s *rport;
4130 u32 ii;
4131
4132 for (ii = 0; ii < n_pids; ii++) {
4133 gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
4134
4135 if (gidft_entry->pid == port->pid)
4136 continue;
4137
4138 /*
4139 * Check if this rport already exists
4140 */
4141 rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid);
4142 if (rport == NULL) {
4143 /*
4144 * this is a new device. create rport
4145 */
4146 rport = bfa_fcs_rport_create(port, gidft_entry->pid);
4147 } else {
4148 /*
4149 * this rport already exists
4150 */
4151 bfa_fcs_rport_scn(rport);
4152 }
4153
4154 bfa_trc(port->fcs, gidft_entry->pid);
4155
4156 /*
4157 * if the last entry bit is set, bail out.
4158 */
4159 if (gidft_entry->last)
4160 return;
4161 }
4162}
4163
Jing Huang5fbe25c2010-10-18 17:17:23 -07004164/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004165 * fcs_ns_public FCS nameserver public interfaces
4166 */
4167
4168/*
4169 * Functions called by port/fab.
4170 * These will send relevant Events to the ns state machine.
4171 */
4172void
4173bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *port)
4174{
4175 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4176
4177 ns->port = port;
4178 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4179}
4180
4181void
4182bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *port)
4183{
4184 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4185
4186 ns->port = port;
4187 bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
4188}
4189
4190void
4191bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *port)
4192{
4193 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4194
4195 ns->port = port;
4196 bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
4197}
4198
4199void
4200bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
4201{
4202 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4203
4204 bfa_trc(port->fcs, port->pid);
4205 bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
4206}
4207
Maggie52f94b62010-11-29 18:21:32 -08004208static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004209bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
4210{
4211
4212 struct bfa_fcs_rport_s *rport;
4213 u8 nwwns;
4214 wwn_t wwns[BFA_PREBOOT_BOOTLUN_MAX];
4215 int ii;
4216
4217 bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns);
4218
4219 for (ii = 0 ; ii < nwwns; ++ii) {
4220 rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
Jing Huangd4b671c2010-12-26 21:46:35 -08004221 WARN_ON(!rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004222 }
4223}
4224
Jing Huang5fbe25c2010-10-18 17:17:23 -07004225/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004226 * FCS SCN
4227 */
4228
4229#define FC_QOS_RSCN_EVENT 0x0c
4230#define FC_FABRIC_NAME_RSCN_EVENT 0x0d
4231
4232/*
4233 * forward declarations
4234 */
4235static void bfa_fcs_lport_scn_send_scr(void *scn_cbarg,
4236 struct bfa_fcxp_s *fcxp_alloced);
4237static void bfa_fcs_lport_scn_scr_response(void *fcsarg,
4238 struct bfa_fcxp_s *fcxp,
4239 void *cbarg,
4240 bfa_status_t req_status,
4241 u32 rsp_len,
4242 u32 resid_len,
4243 struct fchs_s *rsp_fchs);
4244static void bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4245 struct fchs_s *rx_fchs);
4246static void bfa_fcs_lport_scn_timeout(void *arg);
4247
Jing Huang5fbe25c2010-10-18 17:17:23 -07004248/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004249 * fcs_scm_sm FCS SCN state machine
4250 */
4251
Jing Huang5fbe25c2010-10-18 17:17:23 -07004252/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004253 * VPort SCN State Machine events
4254 */
4255enum port_scn_event {
4256 SCNSM_EVENT_PORT_ONLINE = 1,
4257 SCNSM_EVENT_PORT_OFFLINE = 2,
4258 SCNSM_EVENT_RSP_OK = 3,
4259 SCNSM_EVENT_RSP_ERROR = 4,
4260 SCNSM_EVENT_TIMEOUT = 5,
4261 SCNSM_EVENT_SCR_SENT = 6,
4262};
4263
4264static void bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4265 enum port_scn_event event);
4266static void bfa_fcs_lport_scn_sm_sending_scr(
4267 struct bfa_fcs_lport_scn_s *scn,
4268 enum port_scn_event event);
4269static void bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4270 enum port_scn_event event);
4271static void bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
4272 enum port_scn_event event);
4273static void bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
4274 enum port_scn_event event);
4275
Jing Huang5fbe25c2010-10-18 17:17:23 -07004276/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004277 * Starting state - awaiting link up.
4278 */
4279static void
4280bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4281 enum port_scn_event event)
4282{
4283 switch (event) {
4284 case SCNSM_EVENT_PORT_ONLINE:
4285 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
4286 bfa_fcs_lport_scn_send_scr(scn, NULL);
4287 break;
4288
4289 case SCNSM_EVENT_PORT_OFFLINE:
4290 break;
4291
4292 default:
4293 bfa_sm_fault(scn->port->fcs, event);
4294 }
4295}
4296
4297static void
4298bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s *scn,
4299 enum port_scn_event event)
4300{
4301 switch (event) {
4302 case SCNSM_EVENT_SCR_SENT:
4303 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr);
4304 break;
4305
4306 case SCNSM_EVENT_PORT_OFFLINE:
4307 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4308 bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
4309 break;
4310
4311 default:
4312 bfa_sm_fault(scn->port->fcs, event);
4313 }
4314}
4315
4316static void
4317bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4318 enum port_scn_event event)
4319{
4320 struct bfa_fcs_lport_s *port = scn->port;
4321
4322 switch (event) {
4323 case SCNSM_EVENT_RSP_OK:
4324 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_online);
4325 break;
4326
4327 case SCNSM_EVENT_RSP_ERROR:
4328 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr_retry);
4329 bfa_timer_start(port->fcs->bfa, &scn->timer,
4330 bfa_fcs_lport_scn_timeout, scn,
4331 BFA_FCS_RETRY_TIMEOUT);
4332 break;
4333
4334 case SCNSM_EVENT_PORT_OFFLINE:
4335 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4336 bfa_fcxp_discard(scn->fcxp);
4337 break;
4338
4339 default:
4340 bfa_sm_fault(port->fcs, event);
4341 }
4342}
4343
4344static void
4345bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
4346 enum port_scn_event event)
4347{
4348 switch (event) {
4349 case SCNSM_EVENT_TIMEOUT:
4350 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
4351 bfa_fcs_lport_scn_send_scr(scn, NULL);
4352 break;
4353
4354 case SCNSM_EVENT_PORT_OFFLINE:
4355 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4356 bfa_timer_stop(&scn->timer);
4357 break;
4358
4359 default:
4360 bfa_sm_fault(scn->port->fcs, event);
4361 }
4362}
4363
4364static void
4365bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
4366 enum port_scn_event event)
4367{
4368 switch (event) {
4369 case SCNSM_EVENT_PORT_OFFLINE:
4370 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4371 break;
4372
4373 default:
4374 bfa_sm_fault(scn->port->fcs, event);
4375 }
4376}
4377
4378
4379
Jing Huang5fbe25c2010-10-18 17:17:23 -07004380/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004381 * fcs_scn_private FCS SCN private functions
4382 */
4383
Jing Huang5fbe25c2010-10-18 17:17:23 -07004384/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004385 * This routine will be called to send a SCR command.
4386 */
4387static void
4388bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4389{
4390 struct bfa_fcs_lport_scn_s *scn = scn_cbarg;
4391 struct bfa_fcs_lport_s *port = scn->port;
4392 struct fchs_s fchs;
4393 int len;
4394 struct bfa_fcxp_s *fcxp;
4395
4396 bfa_trc(port->fcs, port->pid);
4397 bfa_trc(port->fcs, port->port_cfg.pwwn);
4398
4399 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
4400 if (!fcxp) {
4401 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
4402 bfa_fcs_lport_scn_send_scr, scn);
4403 return;
4404 }
4405 scn->fcxp = fcxp;
4406
4407 /* Handle VU registrations for Base port only */
4408 if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
4409 len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
Maggie Zhangf7f738122010-12-09 19:08:43 -08004410 port->fabric->lps->brcd_switch,
4411 port->pid, 0);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004412 } else {
4413 len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4414 BFA_FALSE,
4415 port->pid, 0);
4416 }
4417
4418 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4419 FC_CLASS_3, len, &fchs,
4420 bfa_fcs_lport_scn_scr_response,
4421 (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV);
4422
4423 bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
4424}
4425
4426static void
4427bfa_fcs_lport_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4428 void *cbarg, bfa_status_t req_status, u32 rsp_len,
4429 u32 resid_len, struct fchs_s *rsp_fchs)
4430{
4431 struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) cbarg;
4432 struct bfa_fcs_lport_s *port = scn->port;
4433 struct fc_els_cmd_s *els_cmd;
4434 struct fc_ls_rjt_s *ls_rjt;
4435
4436 bfa_trc(port->fcs, port->port_cfg.pwwn);
4437
4438 /*
4439 * Sanity Checks
4440 */
4441 if (req_status != BFA_STATUS_OK) {
4442 bfa_trc(port->fcs, req_status);
4443 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4444 return;
4445 }
4446
4447 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
4448
4449 switch (els_cmd->els_code) {
4450
4451 case FC_ELS_ACC:
4452 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
4453 break;
4454
4455 case FC_ELS_LS_RJT:
4456
4457 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
4458
4459 bfa_trc(port->fcs, ls_rjt->reason_code);
4460 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
4461
4462 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4463 break;
4464
4465 default:
4466 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4467 }
4468}
4469
4470/*
4471 * Send a LS Accept
4472 */
4473static void
4474bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4475 struct fchs_s *rx_fchs)
4476{
4477 struct fchs_s fchs;
4478 struct bfa_fcxp_s *fcxp;
4479 struct bfa_rport_s *bfa_rport = NULL;
4480 int len;
4481
4482 bfa_trc(port->fcs, rx_fchs->s_id);
4483
4484 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
4485 if (!fcxp)
4486 return;
4487
4488 len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4489 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
4490 rx_fchs->ox_id);
4491
4492 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
4493 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
4494 FC_MAX_PDUSZ, 0);
4495}
4496
Jing Huang5fbe25c2010-10-18 17:17:23 -07004497/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004498 * This routine will be called by bfa_timer on timer timeouts.
4499 *
4500 * param[in] vport - pointer to bfa_fcs_lport_t.
4501 * param[out] vport_status - pointer to return vport status in
4502 *
4503 * return
4504 * void
4505 *
4506 * Special Considerations:
4507 *
4508 * note
4509 */
4510static void
4511bfa_fcs_lport_scn_timeout(void *arg)
4512{
4513 struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) arg;
4514
4515 bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
4516}
4517
4518
4519
Jing Huang5fbe25c2010-10-18 17:17:23 -07004520/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004521 * fcs_scn_public FCS state change notification public interfaces
4522 */
4523
4524/*
4525 * Functions called by port/fab
4526 */
4527void
4528bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *port)
4529{
4530 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4531
4532 scn->port = port;
4533 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4534}
4535
4536void
4537bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
4538{
4539 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4540
4541 scn->port = port;
4542 bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
4543}
4544
4545void
4546bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *port)
4547{
4548 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4549
4550 scn->port = port;
4551 bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
4552}
4553
4554static void
4555bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
4556{
4557 struct bfa_fcs_rport_s *rport;
4558
4559 bfa_trc(port->fcs, rpid);
4560
Jing Huang5fbe25c2010-10-18 17:17:23 -07004561 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004562 * If this is an unknown device, then it just came online.
4563 * Otherwise let rport handle the RSCN event.
4564 */
4565 rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
4566 if (rport == NULL) {
4567 /*
4568 * If min cfg mode is enabled, we donot need to
4569 * discover any new rports.
4570 */
4571 if (!__fcs_min_cfg(port->fcs))
4572 rport = bfa_fcs_rport_create(port, rpid);
4573 } else
4574 bfa_fcs_rport_scn(rport);
4575}
4576
Jing Huang5fbe25c2010-10-18 17:17:23 -07004577/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004578 * rscn format based PID comparison
4579 */
4580#define __fc_pid_match(__c0, __c1, __fmt) \
4581 (((__fmt) == FC_RSCN_FORMAT_FABRIC) || \
4582 (((__fmt) == FC_RSCN_FORMAT_DOMAIN) && \
4583 ((__c0)[0] == (__c1)[0])) || \
4584 (((__fmt) == FC_RSCN_FORMAT_AREA) && \
4585 ((__c0)[0] == (__c1)[0]) && \
4586 ((__c0)[1] == (__c1)[1])))
4587
4588static void
4589bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s *port,
4590 enum fc_rscn_format format,
4591 u32 rscn_pid)
4592{
4593 struct bfa_fcs_rport_s *rport;
4594 struct list_head *qe, *qe_next;
4595 u8 *c0, *c1;
4596
4597 bfa_trc(port->fcs, format);
4598 bfa_trc(port->fcs, rscn_pid);
4599
4600 c0 = (u8 *) &rscn_pid;
4601
4602 list_for_each_safe(qe, qe_next, &port->rport_q) {
4603 rport = (struct bfa_fcs_rport_s *) qe;
4604 c1 = (u8 *) &rport->pid;
4605 if (__fc_pid_match(c0, c1, format))
4606 bfa_fcs_rport_scn(rport);
4607 }
4608}
4609
4610
4611void
4612bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
4613 struct fchs_s *fchs, u32 len)
4614{
4615 struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
4616 int num_entries;
4617 u32 rscn_pid;
4618 bfa_boolean_t nsquery = BFA_FALSE, found;
4619 int i = 0, j;
4620
4621 num_entries =
Jing Huangba816ea2010-10-18 17:10:50 -07004622 (be16_to_cpu(rscn->payldlen) -
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004623 sizeof(u32)) / sizeof(rscn->event[0]);
4624
4625 bfa_trc(port->fcs, num_entries);
4626
4627 port->stats.num_rscn++;
4628
4629 bfa_fcs_lport_scn_send_ls_acc(port, fchs);
4630
4631 for (i = 0; i < num_entries; i++) {
4632 rscn_pid = rscn->event[i].portid;
4633
4634 bfa_trc(port->fcs, rscn->event[i].format);
4635 bfa_trc(port->fcs, rscn_pid);
4636
4637 /* check for duplicate entries in the list */
4638 found = BFA_FALSE;
4639 for (j = 0; j < i; j++) {
4640 if (rscn->event[j].portid == rscn_pid) {
4641 found = BFA_TRUE;
4642 break;
4643 }
4644 }
4645
4646 /* if found in down the list, pid has been already processed */
4647 if (found) {
4648 bfa_trc(port->fcs, rscn_pid);
4649 continue;
4650 }
4651
4652 switch (rscn->event[i].format) {
4653 case FC_RSCN_FORMAT_PORTID:
4654 if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
4655 /*
4656 * Ignore this event.
4657 * f/w would have processed it
4658 */
4659 bfa_trc(port->fcs, rscn_pid);
4660 } else {
4661 port->stats.num_portid_rscn++;
4662 bfa_fcs_lport_scn_portid_rscn(port, rscn_pid);
4663 }
4664 break;
4665
4666 case FC_RSCN_FORMAT_FABRIC:
4667 if (rscn->event[i].qualifier ==
4668 FC_FABRIC_NAME_RSCN_EVENT) {
4669 bfa_fcs_lport_ms_fabric_rscn(port);
4670 break;
4671 }
4672 /* !!!!!!!!! Fall Through !!!!!!!!!!!!! */
4673
4674 case FC_RSCN_FORMAT_AREA:
4675 case FC_RSCN_FORMAT_DOMAIN:
4676 nsquery = BFA_TRUE;
4677 bfa_fcs_lport_scn_multiport_rscn(port,
4678 rscn->event[i].format,
4679 rscn_pid);
4680 break;
4681
4682
4683 default:
Jing Huangd4b671c2010-12-26 21:46:35 -08004684 WARN_ON(1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004685 nsquery = BFA_TRUE;
4686 }
4687 }
4688
Jing Huang5fbe25c2010-10-18 17:17:23 -07004689 /*
4690 * If any of area, domain or fabric RSCN is received, do a fresh
4691 * discovery to find new devices.
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004692 */
4693 if (nsquery)
4694 bfa_fcs_lport_ns_query(port);
4695}
4696
Jing Huang5fbe25c2010-10-18 17:17:23 -07004697/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004698 * BFA FCS port
4699 */
Jing Huang5fbe25c2010-10-18 17:17:23 -07004700/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004701 * fcs_port_api BFA FCS port API
4702 */
4703struct bfa_fcs_lport_s *
4704bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
4705{
4706 return &fcs->fabric.bport;
4707}
4708
4709wwn_t
4710bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
4711 int nrports, bfa_boolean_t bwwn)
4712{
4713 struct list_head *qh, *qe;
4714 struct bfa_fcs_rport_s *rport = NULL;
4715 int i;
4716 struct bfa_fcs_s *fcs;
4717
4718 if (port == NULL || nrports == 0)
4719 return (wwn_t) 0;
4720
4721 fcs = port->fcs;
4722 bfa_trc(fcs, (u32) nrports);
4723
4724 i = 0;
4725 qh = &port->rport_q;
4726 qe = bfa_q_first(qh);
4727
4728 while ((qe != qh) && (i < nrports)) {
4729 rport = (struct bfa_fcs_rport_s *) qe;
Maggie Zhangf16a1752010-12-09 19:12:32 -08004730 if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004731 qe = bfa_q_next(qe);
4732 bfa_trc(fcs, (u32) rport->pwwn);
4733 bfa_trc(fcs, rport->pid);
4734 bfa_trc(fcs, i);
4735 continue;
4736 }
4737
4738 if (bwwn) {
4739 if (!memcmp(&wwn, &rport->pwwn, 8))
4740 break;
4741 } else {
4742 if (i == index)
4743 break;
4744 }
4745
4746 i++;
4747 qe = bfa_q_next(qe);
4748 }
4749
4750 bfa_trc(fcs, i);
4751 if (rport)
4752 return rport->pwwn;
4753 else
4754 return (wwn_t) 0;
4755}
4756
4757void
4758bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
4759 wwn_t rport_wwns[], int *nrports)
4760{
4761 struct list_head *qh, *qe;
4762 struct bfa_fcs_rport_s *rport = NULL;
4763 int i;
4764 struct bfa_fcs_s *fcs;
4765
4766 if (port == NULL || rport_wwns == NULL || *nrports == 0)
4767 return;
4768
4769 fcs = port->fcs;
4770 bfa_trc(fcs, (u32) *nrports);
4771
4772 i = 0;
4773 qh = &port->rport_q;
4774 qe = bfa_q_first(qh);
4775
4776 while ((qe != qh) && (i < *nrports)) {
4777 rport = (struct bfa_fcs_rport_s *) qe;
Maggie Zhangf16a1752010-12-09 19:12:32 -08004778 if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004779 qe = bfa_q_next(qe);
4780 bfa_trc(fcs, (u32) rport->pwwn);
4781 bfa_trc(fcs, rport->pid);
4782 bfa_trc(fcs, i);
4783 continue;
4784 }
4785
4786 rport_wwns[i] = rport->pwwn;
4787
4788 i++;
4789 qe = bfa_q_next(qe);
4790 }
4791
4792 bfa_trc(fcs, i);
4793 *nrports = i;
4794}
4795
4796/*
4797 * Iterate's through all the rport's in the given port to
4798 * determine the maximum operating speed.
4799 *
4800 * !!!! To be used in TRL Functionality only !!!!
4801 */
4802bfa_port_speed_t
4803bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
4804{
4805 struct list_head *qh, *qe;
4806 struct bfa_fcs_rport_s *rport = NULL;
4807 struct bfa_fcs_s *fcs;
4808 bfa_port_speed_t max_speed = 0;
4809 struct bfa_port_attr_s port_attr;
4810 bfa_port_speed_t port_speed, rport_speed;
4811 bfa_boolean_t trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
4812
4813
4814 if (port == NULL)
4815 return 0;
4816
4817 fcs = port->fcs;
4818
4819 /* Get Physical port's current speed */
4820 bfa_fcport_get_attr(port->fcs->bfa, &port_attr);
4821 port_speed = port_attr.speed;
4822 bfa_trc(fcs, port_speed);
4823
4824 qh = &port->rport_q;
4825 qe = bfa_q_first(qh);
4826
4827 while (qe != qh) {
4828 rport = (struct bfa_fcs_rport_s *) qe;
Maggie Zhangf16a1752010-12-09 19:12:32 -08004829 if ((bfa_ntoh3b(rport->pid) > 0xFFF000) ||
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004830 (bfa_fcs_rport_get_state(rport) ==
4831 BFA_RPORT_OFFLINE)) {
4832 qe = bfa_q_next(qe);
4833 continue;
4834 }
4835
4836 rport_speed = rport->rpf.rpsc_speed;
4837 if ((trl_enabled) && (rport_speed ==
4838 BFA_PORT_SPEED_UNKNOWN)) {
4839 /* Use default ratelim speed setting */
4840 rport_speed =
4841 bfa_fcport_get_ratelim_speed(port->fcs->bfa);
4842 }
4843
4844 if ((rport_speed == BFA_PORT_SPEED_8GBPS) ||
4845 (rport_speed > port_speed)) {
4846 max_speed = rport_speed;
4847 break;
4848 } else if (rport_speed > max_speed) {
4849 max_speed = rport_speed;
4850 }
4851
4852 qe = bfa_q_next(qe);
4853 }
4854
4855 bfa_trc(fcs, max_speed);
4856 return max_speed;
4857}
4858
4859struct bfa_fcs_lport_s *
4860bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
4861{
4862 struct bfa_fcs_vport_s *vport;
4863 bfa_fcs_vf_t *vf;
4864
Jing Huangd4b671c2010-12-26 21:46:35 -08004865 WARN_ON(fcs == NULL);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004866
4867 vf = bfa_fcs_vf_lookup(fcs, vf_id);
4868 if (vf == NULL) {
4869 bfa_trc(fcs, vf_id);
4870 return NULL;
4871 }
4872
4873 if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
4874 return &vf->bport;
4875
4876 vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
4877 if (vport)
4878 return &vport->lport;
4879
4880 return NULL;
4881}
4882
4883/*
4884 * API corresponding to NPIV_VPORT_GETINFO.
4885 */
4886void
4887bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
4888 struct bfa_lport_info_s *port_info)
4889{
4890
4891 bfa_trc(port->fcs, port->fabric->fabric_name);
4892
4893 if (port->vport == NULL) {
4894 /*
4895 * This is a Physical port
4896 */
4897 port_info->port_type = BFA_LPORT_TYPE_PHYSICAL;
4898
4899 /*
4900 * @todo : need to fix the state & reason
4901 */
4902 port_info->port_state = 0;
4903 port_info->offline_reason = 0;
4904
4905 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
4906 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
4907
4908 port_info->max_vports_supp =
4909 bfa_lps_get_max_vport(port->fcs->bfa);
4910 port_info->num_vports_inuse =
Maggie Zhangf7f738122010-12-09 19:08:43 -08004911 port->fabric->num_vports;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004912 port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
4913 port_info->num_rports_inuse = port->num_rports;
4914 } else {
4915 /*
4916 * This is a virtual port
4917 */
4918 port_info->port_type = BFA_LPORT_TYPE_VIRTUAL;
4919
4920 /*
4921 * @todo : need to fix the state & reason
4922 */
4923 port_info->port_state = 0;
4924 port_info->offline_reason = 0;
4925
4926 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
4927 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
4928 }
4929}
4930
4931void
4932bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
4933 struct bfa_lport_stats_s *port_stats)
4934{
4935 *port_stats = fcs_port->stats;
4936}
4937
4938void
4939bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
4940{
Jing Huang6a18b162010-10-18 17:08:54 -07004941 memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004942}
4943
Jing Huang5fbe25c2010-10-18 17:17:23 -07004944/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004945 * FCS virtual port state machine
4946 */
4947
4948#define __vport_fcs(__vp) ((__vp)->lport.fcs)
4949#define __vport_pwwn(__vp) ((__vp)->lport.port_cfg.pwwn)
4950#define __vport_nwwn(__vp) ((__vp)->lport.port_cfg.nwwn)
4951#define __vport_bfa(__vp) ((__vp)->lport.fcs->bfa)
4952#define __vport_fcid(__vp) ((__vp)->lport.pid)
4953#define __vport_fabric(__vp) ((__vp)->lport.fabric)
4954#define __vport_vfid(__vp) ((__vp)->lport.fabric->vf_id)
4955
4956#define BFA_FCS_VPORT_MAX_RETRIES 5
4957/*
4958 * Forward declarations
4959 */
4960static void bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
4961static void bfa_fcs_vport_timeout(void *vport_arg);
4962static void bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
4963static void bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
4964
Jing Huang5fbe25c2010-10-18 17:17:23 -07004965/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004966 * fcs_vport_sm FCS virtual port state machine
4967 */
4968
Jing Huang5fbe25c2010-10-18 17:17:23 -07004969/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004970 * VPort State Machine events
4971 */
4972enum bfa_fcs_vport_event {
4973 BFA_FCS_VPORT_SM_CREATE = 1, /* vport create event */
4974 BFA_FCS_VPORT_SM_DELETE = 2, /* vport delete event */
4975 BFA_FCS_VPORT_SM_START = 3, /* vport start request */
4976 BFA_FCS_VPORT_SM_STOP = 4, /* stop: unsupported */
4977 BFA_FCS_VPORT_SM_ONLINE = 5, /* fabric online */
4978 BFA_FCS_VPORT_SM_OFFLINE = 6, /* fabric offline event */
4979 BFA_FCS_VPORT_SM_FRMSENT = 7, /* fdisc/logo sent events */
4980 BFA_FCS_VPORT_SM_RSP_OK = 8, /* good response */
4981 BFA_FCS_VPORT_SM_RSP_ERROR = 9, /* error/bad response */
4982 BFA_FCS_VPORT_SM_TIMEOUT = 10, /* delay timer event */
4983 BFA_FCS_VPORT_SM_DELCOMP = 11, /* lport delete completion */
4984 BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12, /* Dup wnn error*/
4985 BFA_FCS_VPORT_SM_RSP_FAILED = 13, /* non-retryable failure */
Krishna Gudipatidd5aaf42011-06-13 15:51:24 -07004986 BFA_FCS_VPORT_SM_STOPCOMP = 14, /* vport delete completion */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07004987};
4988
4989static void bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
4990 enum bfa_fcs_vport_event event);
4991static void bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
4992 enum bfa_fcs_vport_event event);
4993static void bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
4994 enum bfa_fcs_vport_event event);
4995static void bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
4996 enum bfa_fcs_vport_event event);
4997static void bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
4998 enum bfa_fcs_vport_event event);
4999static void bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
5000 enum bfa_fcs_vport_event event);
5001static void bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
5002 enum bfa_fcs_vport_event event);
5003static void bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
5004 enum bfa_fcs_vport_event event);
5005static void bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
5006 enum bfa_fcs_vport_event event);
5007static void bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
5008 enum bfa_fcs_vport_event event);
Krishna Gudipatidd5aaf42011-06-13 15:51:24 -07005009static void bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
5010 enum bfa_fcs_vport_event event);
5011static void bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
5012 enum bfa_fcs_vport_event event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005013
5014static struct bfa_sm_table_s vport_sm_table[] = {
5015 {BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
5016 {BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED},
5017 {BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
5018 {BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
5019 {BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
5020 {BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
5021 {BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
5022 {BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
5023 {BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO},
5024 {BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR}
5025};
5026
Jing Huang5fbe25c2010-10-18 17:17:23 -07005027/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005028 * Beginning state.
5029 */
5030static void
5031bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
5032 enum bfa_fcs_vport_event event)
5033{
5034 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5035 bfa_trc(__vport_fcs(vport), event);
5036
5037 switch (event) {
5038 case BFA_FCS_VPORT_SM_CREATE:
5039 bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
5040 bfa_fcs_fabric_addvport(__vport_fabric(vport), vport);
5041 break;
5042
5043 default:
5044 bfa_sm_fault(__vport_fcs(vport), event);
5045 }
5046}
5047
Jing Huang5fbe25c2010-10-18 17:17:23 -07005048/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005049 * Created state - a start event is required to start up the state machine.
5050 */
5051static void
5052bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
5053 enum bfa_fcs_vport_event event)
5054{
5055 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5056 bfa_trc(__vport_fcs(vport), event);
5057
5058 switch (event) {
5059 case BFA_FCS_VPORT_SM_START:
Maggie Zhangf7f738122010-12-09 19:08:43 -08005060 if (bfa_sm_cmp_state(__vport_fabric(vport),
5061 bfa_fcs_fabric_sm_online)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005062 && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
5063 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5064 bfa_fcs_vport_do_fdisc(vport);
5065 } else {
Jing Huang5fbe25c2010-10-18 17:17:23 -07005066 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005067 * Fabric is offline or not NPIV capable, stay in
5068 * offline state.
5069 */
5070 vport->vport_stats.fab_no_npiv++;
5071 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5072 }
5073 break;
5074
5075 case BFA_FCS_VPORT_SM_DELETE:
5076 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5077 bfa_fcs_lport_delete(&vport->lport);
5078 break;
5079
5080 case BFA_FCS_VPORT_SM_ONLINE:
5081 case BFA_FCS_VPORT_SM_OFFLINE:
Jing Huang5fbe25c2010-10-18 17:17:23 -07005082 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005083 * Ignore ONLINE/OFFLINE events from fabric
5084 * till vport is started.
5085 */
5086 break;
5087
5088 default:
5089 bfa_sm_fault(__vport_fcs(vport), event);
5090 }
5091}
5092
Jing Huang5fbe25c2010-10-18 17:17:23 -07005093/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005094 * Offline state - awaiting ONLINE event from fabric SM.
5095 */
5096static void
5097bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
5098 enum bfa_fcs_vport_event event)
5099{
5100 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5101 bfa_trc(__vport_fcs(vport), event);
5102
5103 switch (event) {
5104 case BFA_FCS_VPORT_SM_DELETE:
5105 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5106 bfa_fcs_lport_delete(&vport->lport);
5107 break;
5108
5109 case BFA_FCS_VPORT_SM_ONLINE:
5110 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5111 vport->fdisc_retries = 0;
5112 bfa_fcs_vport_do_fdisc(vport);
5113 break;
5114
Krishna Gudipatidd5aaf42011-06-13 15:51:24 -07005115 case BFA_FCS_VPORT_SM_STOP:
5116 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5117 bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
5118 break;
5119
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005120 case BFA_FCS_VPORT_SM_OFFLINE:
5121 /*
5122 * This can happen if the vport couldn't be initialzied
5123 * due the fact that the npiv was not enabled on the switch.
5124 * In that case we will put the vport in offline state.
5125 * However, the link can go down and cause the this event to
5126 * be sent when we are already offline. Ignore it.
5127 */
5128 break;
5129
5130 default:
5131 bfa_sm_fault(__vport_fcs(vport), event);
5132 }
5133}
5134
5135
Jing Huang5fbe25c2010-10-18 17:17:23 -07005136/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005137 * FDISC is sent and awaiting reply from fabric.
5138 */
5139static void
5140bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
5141 enum bfa_fcs_vport_event event)
5142{
5143 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5144 bfa_trc(__vport_fcs(vport), event);
5145
5146 switch (event) {
5147 case BFA_FCS_VPORT_SM_DELETE:
5148 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
Maggie Zhangf7f738122010-12-09 19:08:43 -08005149 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005150 bfa_fcs_lport_delete(&vport->lport);
5151 break;
5152
5153 case BFA_FCS_VPORT_SM_OFFLINE:
5154 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
Maggie Zhangf7f738122010-12-09 19:08:43 -08005155 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005156 break;
5157
5158 case BFA_FCS_VPORT_SM_RSP_OK:
5159 bfa_sm_set_state(vport, bfa_fcs_vport_sm_online);
5160 bfa_fcs_lport_online(&vport->lport);
5161 break;
5162
5163 case BFA_FCS_VPORT_SM_RSP_ERROR:
5164 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry);
5165 bfa_timer_start(__vport_bfa(vport), &vport->timer,
5166 bfa_fcs_vport_timeout, vport,
5167 BFA_FCS_RETRY_TIMEOUT);
5168 break;
5169
5170 case BFA_FCS_VPORT_SM_RSP_FAILED:
5171 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5172 break;
5173
5174 case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
5175 bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
5176 break;
5177
5178 default:
5179 bfa_sm_fault(__vport_fcs(vport), event);
5180 }
5181}
5182
Jing Huang5fbe25c2010-10-18 17:17:23 -07005183/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005184 * FDISC attempt failed - a timer is active to retry FDISC.
5185 */
5186static void
5187bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
5188 enum bfa_fcs_vport_event event)
5189{
5190 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5191 bfa_trc(__vport_fcs(vport), event);
5192
5193 switch (event) {
5194 case BFA_FCS_VPORT_SM_DELETE:
5195 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5196 bfa_timer_stop(&vport->timer);
5197 bfa_fcs_lport_delete(&vport->lport);
5198 break;
5199
5200 case BFA_FCS_VPORT_SM_OFFLINE:
5201 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5202 bfa_timer_stop(&vport->timer);
5203 break;
5204
5205 case BFA_FCS_VPORT_SM_TIMEOUT:
5206 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5207 vport->vport_stats.fdisc_retries++;
5208 vport->fdisc_retries++;
5209 bfa_fcs_vport_do_fdisc(vport);
5210 break;
5211
5212 default:
5213 bfa_sm_fault(__vport_fcs(vport), event);
5214 }
5215}
5216
Jing Huang5fbe25c2010-10-18 17:17:23 -07005217/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005218 * Vport is online (FDISC is complete).
5219 */
5220static void
5221bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
5222 enum bfa_fcs_vport_event event)
5223{
5224 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5225 bfa_trc(__vport_fcs(vport), event);
5226
5227 switch (event) {
5228 case BFA_FCS_VPORT_SM_DELETE:
5229 bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
5230 bfa_fcs_lport_delete(&vport->lport);
5231 break;
5232
Krishna Gudipatidd5aaf42011-06-13 15:51:24 -07005233 case BFA_FCS_VPORT_SM_STOP:
5234 bfa_sm_set_state(vport, bfa_fcs_vport_sm_stopping);
5235 bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
5236 break;
5237
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005238 case BFA_FCS_VPORT_SM_OFFLINE:
5239 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
Maggie Zhangf7f738122010-12-09 19:08:43 -08005240 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005241 bfa_fcs_lport_offline(&vport->lport);
5242 break;
5243
5244 default:
5245 bfa_sm_fault(__vport_fcs(vport), event);
5246 }
5247}
5248
Jing Huang5fbe25c2010-10-18 17:17:23 -07005249/*
Krishna Gudipatidd5aaf42011-06-13 15:51:24 -07005250 * Vport is being stopped - awaiting lport stop completion to send
5251 * LOGO to fabric.
5252 */
5253static void
5254bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
5255 enum bfa_fcs_vport_event event)
5256{
5257 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5258 bfa_trc(__vport_fcs(vport), event);
5259
5260 switch (event) {
5261 case BFA_FCS_VPORT_SM_STOPCOMP:
5262 bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo_for_stop);
5263 bfa_fcs_vport_do_logo(vport);
5264 break;
5265
5266 case BFA_FCS_VPORT_SM_OFFLINE:
5267 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5268 break;
5269
5270 default:
5271 bfa_sm_fault(__vport_fcs(vport), event);
5272 }
5273}
5274
5275/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005276 * Vport is being deleted - awaiting lport delete completion to send
5277 * LOGO to fabric.
5278 */
5279static void
5280bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
5281 enum bfa_fcs_vport_event event)
5282{
5283 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5284 bfa_trc(__vport_fcs(vport), event);
5285
5286 switch (event) {
5287 case BFA_FCS_VPORT_SM_DELETE:
5288 break;
5289
5290 case BFA_FCS_VPORT_SM_DELCOMP:
5291 bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
5292 bfa_fcs_vport_do_logo(vport);
5293 break;
5294
5295 case BFA_FCS_VPORT_SM_OFFLINE:
5296 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5297 break;
5298
5299 default:
5300 bfa_sm_fault(__vport_fcs(vport), event);
5301 }
5302}
5303
Jing Huang5fbe25c2010-10-18 17:17:23 -07005304/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005305 * Error State.
5306 * This state will be set when the Vport Creation fails due
5307 * to errors like Dup WWN. In this state only operation allowed
5308 * is a Vport Delete.
5309 */
5310static void
5311bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
5312 enum bfa_fcs_vport_event event)
5313{
5314 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5315 bfa_trc(__vport_fcs(vport), event);
5316
5317 switch (event) {
5318 case BFA_FCS_VPORT_SM_DELETE:
5319 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5320 bfa_fcs_lport_delete(&vport->lport);
5321 break;
5322
5323 default:
5324 bfa_trc(__vport_fcs(vport), event);
5325 }
5326}
5327
Jing Huang5fbe25c2010-10-18 17:17:23 -07005328/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005329 * Lport cleanup is in progress since vport is being deleted. Fabric is
5330 * offline, so no LOGO is needed to complete vport deletion.
5331 */
5332static void
5333bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
5334 enum bfa_fcs_vport_event event)
5335{
5336 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5337 bfa_trc(__vport_fcs(vport), event);
5338
5339 switch (event) {
5340 case BFA_FCS_VPORT_SM_DELCOMP:
5341 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5342 bfa_fcs_vport_free(vport);
5343 break;
5344
Krishna Gudipatidd5aaf42011-06-13 15:51:24 -07005345 case BFA_FCS_VPORT_SM_STOPCOMP:
5346 bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
5347 break;
5348
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005349 case BFA_FCS_VPORT_SM_DELETE:
5350 break;
5351
5352 default:
5353 bfa_sm_fault(__vport_fcs(vport), event);
5354 }
5355}
5356
Jing Huang5fbe25c2010-10-18 17:17:23 -07005357/*
Krishna Gudipatidd5aaf42011-06-13 15:51:24 -07005358 * LOGO is sent to fabric. Vport stop is in progress. Lport stop cleanup
5359 * is done.
5360 */
5361static void
5362bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
5363 enum bfa_fcs_vport_event event)
5364{
5365 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5366 bfa_trc(__vport_fcs(vport), event);
5367
5368 switch (event) {
5369 case BFA_FCS_VPORT_SM_OFFLINE:
5370 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5371 /*
5372 * !!! fall through !!!
5373 */
5374
5375 case BFA_FCS_VPORT_SM_RSP_OK:
5376 case BFA_FCS_VPORT_SM_RSP_ERROR:
5377 bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
5378 break;
5379
5380 default:
5381 bfa_sm_fault(__vport_fcs(vport), event);
5382 }
5383}
5384
5385/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005386 * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
5387 * is done.
5388 */
5389static void
5390bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
5391 enum bfa_fcs_vport_event event)
5392{
5393 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5394 bfa_trc(__vport_fcs(vport), event);
5395
5396 switch (event) {
5397 case BFA_FCS_VPORT_SM_OFFLINE:
Maggie Zhangf7f738122010-12-09 19:08:43 -08005398 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005399 /*
5400 * !!! fall through !!!
5401 */
5402
5403 case BFA_FCS_VPORT_SM_RSP_OK:
5404 case BFA_FCS_VPORT_SM_RSP_ERROR:
5405 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5406 bfa_fcs_vport_free(vport);
5407 break;
5408
5409 case BFA_FCS_VPORT_SM_DELETE:
5410 break;
5411
5412 default:
5413 bfa_sm_fault(__vport_fcs(vport), event);
5414 }
5415}
5416
5417
5418
Jing Huang5fbe25c2010-10-18 17:17:23 -07005419/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005420 * fcs_vport_private FCS virtual port private functions
5421 */
Jing Huang5fbe25c2010-10-18 17:17:23 -07005422/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005423 * This routine will be called to send a FDISC command.
5424 */
5425static void
5426bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
5427{
5428 bfa_lps_fdisc(vport->lps, vport,
5429 bfa_fcport_get_maxfrsize(__vport_bfa(vport)),
5430 __vport_pwwn(vport), __vport_nwwn(vport));
5431 vport->vport_stats.fdisc_sent++;
5432}
5433
5434static void
5435bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
5436{
Maggie Zhangf7f738122010-12-09 19:08:43 -08005437 u8 lsrjt_rsn = vport->lps->lsrjt_rsn;
5438 u8 lsrjt_expl = vport->lps->lsrjt_expl;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005439
5440 bfa_trc(__vport_fcs(vport), lsrjt_rsn);
5441 bfa_trc(__vport_fcs(vport), lsrjt_expl);
5442
5443 /* For certain reason codes, we don't want to retry. */
Maggie Zhangf7f738122010-12-09 19:08:43 -08005444 switch (vport->lps->lsrjt_expl) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005445 case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */
5446 case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */
5447 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
5448 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5449 else
5450 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
5451 break;
5452
5453 case FC_LS_RJT_EXP_INSUFF_RES:
5454 /*
5455 * This means max logins per port/switch setting on the
5456 * switch was exceeded.
5457 */
5458 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
5459 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5460 else
5461 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
5462 break;
5463
5464 default:
5465 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5466 }
5467}
5468
Jing Huang5fbe25c2010-10-18 17:17:23 -07005469/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005470 * Called to send a logout to the fabric. Used when a V-Port is
5471 * deleted/stopped.
5472 */
5473static void
5474bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
5475{
5476 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5477
5478 vport->vport_stats.logo_sent++;
5479 bfa_lps_fdisclogo(vport->lps);
5480}
5481
5482
Jing Huang5fbe25c2010-10-18 17:17:23 -07005483/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005484 * This routine will be called by bfa_timer on timer timeouts.
5485 *
5486 * param[in] vport - pointer to bfa_fcs_vport_t.
5487 * param[out] vport_status - pointer to return vport status in
5488 *
5489 * return
5490 * void
5491 *
5492 * Special Considerations:
5493 *
5494 * note
5495 */
5496static void
5497bfa_fcs_vport_timeout(void *vport_arg)
5498{
5499 struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *) vport_arg;
5500
5501 vport->vport_stats.fdisc_timeouts++;
5502 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
5503}
5504
5505static void
5506bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
5507{
5508 struct bfad_vport_s *vport_drv =
5509 (struct bfad_vport_s *)vport->vport_drv;
5510
5511 bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
5512
5513 if (vport_drv->comp_del)
5514 complete(vport_drv->comp_del);
5515
5516 bfa_lps_delete(vport->lps);
5517}
5518
5519
5520
Jing Huang5fbe25c2010-10-18 17:17:23 -07005521/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005522 * fcs_vport_public FCS virtual port public interfaces
5523 */
5524
Jing Huang5fbe25c2010-10-18 17:17:23 -07005525/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005526 * Online notification from fabric SM.
5527 */
5528void
5529bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
5530{
5531 vport->vport_stats.fab_online++;
5532 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
5533}
5534
Jing Huang5fbe25c2010-10-18 17:17:23 -07005535/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005536 * Offline notification from fabric SM.
5537 */
5538void
5539bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
5540{
5541 vport->vport_stats.fab_offline++;
5542 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
5543}
5544
Jing Huang5fbe25c2010-10-18 17:17:23 -07005545/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005546 * Cleanup notification from fabric SM on link timer expiry.
5547 */
5548void
5549bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
5550{
5551 vport->vport_stats.fab_cleanup++;
5552}
Jing Huang5fbe25c2010-10-18 17:17:23 -07005553/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005554 * delete notification from fabric SM. To be invoked from within FCS.
5555 */
5556void
5557bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
5558{
5559 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
5560}
5561
Jing Huang5fbe25c2010-10-18 17:17:23 -07005562/*
Krishna Gudipatidd5aaf42011-06-13 15:51:24 -07005563 * Stop completion callback from associated lport
5564 */
5565void
5566bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport)
5567{
5568 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOPCOMP);
5569}
5570
5571/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005572 * Delete completion callback from associated lport
5573 */
5574void
5575bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
5576{
5577 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
5578}
5579
5580
5581
Jing Huang5fbe25c2010-10-18 17:17:23 -07005582/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005583 * fcs_vport_api Virtual port API
5584 */
5585
Jing Huang5fbe25c2010-10-18 17:17:23 -07005586/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005587 * Use this function to instantiate a new FCS vport object. This
5588 * function will not trigger any HW initialization process (which will be
5589 * done in vport_start() call)
5590 *
5591 * param[in] vport - pointer to bfa_fcs_vport_t. This space
5592 * needs to be allocated by the driver.
5593 * param[in] fcs - FCS instance
5594 * param[in] vport_cfg - vport configuration
5595 * param[in] vf_id - VF_ID if vport is created within a VF.
5596 * FC_VF_ID_NULL to specify base fabric.
5597 * param[in] vport_drv - Opaque handle back to the driver's vport
5598 * structure
5599 *
5600 * retval BFA_STATUS_OK - on success.
5601 * retval BFA_STATUS_FAILED - on failure.
5602 */
5603bfa_status_t
5604bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
5605 u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
5606 struct bfad_vport_s *vport_drv)
5607{
5608 if (vport_cfg->pwwn == 0)
5609 return BFA_STATUS_INVALID_WWN;
5610
5611 if (bfa_fcs_lport_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
5612 return BFA_STATUS_VPORT_WWN_BP;
5613
5614 if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
5615 return BFA_STATUS_VPORT_EXISTS;
5616
Maggie Zhangf7f738122010-12-09 19:08:43 -08005617 if (fcs->fabric.num_vports ==
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005618 bfa_lps_get_max_vport(fcs->bfa))
5619 return BFA_STATUS_VPORT_MAX;
5620
5621 vport->lps = bfa_lps_alloc(fcs->bfa);
5622 if (!vport->lps)
5623 return BFA_STATUS_VPORT_MAX;
5624
5625 vport->vport_drv = vport_drv;
5626 vport_cfg->preboot_vp = BFA_FALSE;
5627
5628 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5629 bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport);
5630 bfa_fcs_lport_init(&vport->lport, vport_cfg);
5631 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE);
5632
5633 return BFA_STATUS_OK;
5634}
5635
Jing Huang5fbe25c2010-10-18 17:17:23 -07005636/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005637 * Use this function to instantiate a new FCS PBC vport object. This
5638 * function will not trigger any HW initialization process (which will be
5639 * done in vport_start() call)
5640 *
5641 * param[in] vport - pointer to bfa_fcs_vport_t. This space
5642 * needs to be allocated by the driver.
5643 * param[in] fcs - FCS instance
5644 * param[in] vport_cfg - vport configuration
5645 * param[in] vf_id - VF_ID if vport is created within a VF.
5646 * FC_VF_ID_NULL to specify base fabric.
5647 * param[in] vport_drv - Opaque handle back to the driver's vport
5648 * structure
5649 *
5650 * retval BFA_STATUS_OK - on success.
5651 * retval BFA_STATUS_FAILED - on failure.
5652 */
5653bfa_status_t
5654bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
5655 u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
5656 struct bfad_vport_s *vport_drv)
5657{
5658 bfa_status_t rc;
5659
5660 rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv);
5661 vport->lport.port_cfg.preboot_vp = BFA_TRUE;
5662
5663 return rc;
5664}
5665
Jing Huang5fbe25c2010-10-18 17:17:23 -07005666/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005667 * Use this function to findout if this is a pbc vport or not.
5668 *
5669 * @param[in] vport - pointer to bfa_fcs_vport_t.
5670 *
5671 * @returns None
5672 */
5673bfa_boolean_t
5674bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport)
5675{
5676
5677 if (vport && (vport->lport.port_cfg.preboot_vp == BFA_TRUE))
5678 return BFA_TRUE;
5679 else
5680 return BFA_FALSE;
5681
5682}
5683
Jing Huang5fbe25c2010-10-18 17:17:23 -07005684/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005685 * Use this function initialize the vport.
5686 *
5687 * @param[in] vport - pointer to bfa_fcs_vport_t.
5688 *
5689 * @returns None
5690 */
5691bfa_status_t
5692bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
5693{
5694 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
5695
5696 return BFA_STATUS_OK;
5697}
5698
Jing Huang5fbe25c2010-10-18 17:17:23 -07005699/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005700 * Use this function quiese the vport object. This function will return
5701 * immediately, when the vport is actually stopped, the
5702 * bfa_drv_vport_stop_cb() will be called.
5703 *
5704 * param[in] vport - pointer to bfa_fcs_vport_t.
5705 *
5706 * return None
5707 */
5708bfa_status_t
5709bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
5710{
5711 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
5712
5713 return BFA_STATUS_OK;
5714}
5715
Jing Huang5fbe25c2010-10-18 17:17:23 -07005716/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005717 * Use this function to delete a vport object. Fabric object should
5718 * be stopped before this function call.
5719 *
5720 * !!!!!!! Donot invoke this from within FCS !!!!!!!
5721 *
5722 * param[in] vport - pointer to bfa_fcs_vport_t.
5723 *
5724 * return None
5725 */
5726bfa_status_t
5727bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
5728{
5729
5730 if (vport->lport.port_cfg.preboot_vp)
5731 return BFA_STATUS_PBC;
5732
5733 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
5734
5735 return BFA_STATUS_OK;
5736}
5737
Jing Huang5fbe25c2010-10-18 17:17:23 -07005738/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005739 * Use this function to get vport's current status info.
5740 *
5741 * param[in] vport pointer to bfa_fcs_vport_t.
5742 * param[out] attr pointer to return vport attributes
5743 *
5744 * return None
5745 */
5746void
5747bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
5748 struct bfa_vport_attr_s *attr)
5749{
5750 if (vport == NULL || attr == NULL)
5751 return;
5752
Jing Huang6a18b162010-10-18 17:08:54 -07005753 memset(attr, 0, sizeof(struct bfa_vport_attr_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005754
5755 bfa_fcs_lport_get_attr(&vport->lport, &attr->port_attr);
5756 attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
5757}
5758
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005759
Jing Huang5fbe25c2010-10-18 17:17:23 -07005760/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005761 * Lookup a virtual port. Excludes base port from lookup.
5762 */
5763struct bfa_fcs_vport_s *
5764bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
5765{
5766 struct bfa_fcs_vport_s *vport;
5767 struct bfa_fcs_fabric_s *fabric;
5768
5769 bfa_trc(fcs, vf_id);
5770 bfa_trc(fcs, vpwwn);
5771
5772 fabric = bfa_fcs_vf_lookup(fcs, vf_id);
5773 if (!fabric) {
5774 bfa_trc(fcs, vf_id);
5775 return NULL;
5776 }
5777
5778 vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
5779 return vport;
5780}
5781
Jing Huang5fbe25c2010-10-18 17:17:23 -07005782/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005783 * FDISC Response
5784 */
5785void
5786bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
5787{
5788 struct bfa_fcs_vport_s *vport = uarg;
5789
5790 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5791 bfa_trc(__vport_fcs(vport), status);
5792
5793 switch (status) {
5794 case BFA_STATUS_OK:
5795 /*
Uwe Kleine-Königb5950762010-11-01 15:38:34 -04005796 * Initialize the V-Port fields
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005797 */
Maggie Zhangf7f738122010-12-09 19:08:43 -08005798 __vport_fcid(vport) = vport->lps->lp_pid;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005799 vport->vport_stats.fdisc_accepts++;
5800 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
5801 break;
5802
5803 case BFA_STATUS_INVALID_MAC:
5804 /* Only for CNA */
5805 vport->vport_stats.fdisc_acc_bad++;
5806 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5807
5808 break;
5809
5810 case BFA_STATUS_EPROTOCOL:
Maggie Zhangf7f738122010-12-09 19:08:43 -08005811 switch (vport->lps->ext_status) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005812 case BFA_EPROTO_BAD_ACCEPT:
5813 vport->vport_stats.fdisc_acc_bad++;
5814 break;
5815
5816 case BFA_EPROTO_UNKNOWN_RSP:
5817 vport->vport_stats.fdisc_unknown_rsp++;
5818 break;
5819
5820 default:
5821 break;
5822 }
5823
5824 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5825 break;
5826
5827 case BFA_STATUS_FABRIC_RJT:
5828 vport->vport_stats.fdisc_rejects++;
5829 bfa_fcs_vport_fdisc_rejected(vport);
5830 break;
5831
5832 default:
5833 vport->vport_stats.fdisc_rsp_err++;
5834 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5835 }
5836}
5837
Jing Huang5fbe25c2010-10-18 17:17:23 -07005838/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005839 * LOGO response
5840 */
5841void
5842bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
5843{
5844 struct bfa_fcs_vport_s *vport = uarg;
5845 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
5846}
5847
Jing Huang5fbe25c2010-10-18 17:17:23 -07005848/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07005849 * Received clear virtual link
5850 */
5851void
5852bfa_cb_lps_cvl_event(void *bfad, void *uarg)
5853{
5854 struct bfa_fcs_vport_s *vport = uarg;
5855
5856 /* Send an Offline followed by an ONLINE */
5857 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
5858 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
5859}