Commit | Line | Data |
---|---|---|
7725ccfd | 1 | /* |
889d0d42 AG |
2 | * Copyright (c) 2005-2014 Brocade Communications Systems, Inc. |
3 | * Copyright (c) 2014- QLogic Corporation. | |
7725ccfd | 4 | * All rights reserved |
889d0d42 | 5 | * www.qlogic.com |
7725ccfd | 6 | * |
31e1d569 | 7 | * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter. |
7725ccfd JH |
8 | * |
9 | * This program is free software; you can redistribute it and/or modify it | |
10 | * under the terms of the GNU General Public License (GPL) Version 2 as | |
11 | * published by the Free Software Foundation | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, but | |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * General Public License for more details. | |
17 | */ | |
18 | ||
f16a1750 | 19 | #include "bfad_drv.h" |
7826f304 | 20 | #include "bfad_im.h" |
a36c61f9 KG |
21 | #include "bfa_fcs.h" |
22 | #include "bfa_fcbuild.h" | |
23 | #include "bfa_fc.h" | |
7725ccfd JH |
24 | |
25 | BFA_TRC_FILE(FCS, PORT); | |
26 | ||
bc0e2c2a KG |
27 | /* |
28 | * ALPA to LIXA bitmap mapping | |
29 | * | |
30 | * ALPA 0x00 (Word 0, Bit 30) is invalid for N_Ports. Also Word 0 Bit 31 | |
31 | * is for L_bit (login required) and is filled as ALPA 0x00 here. | |
32 | */ | |
33 | static const u8 loop_alpa_map[] = { | |
34 | 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x0F, 0x10, /* Word 0 Bits 31..24 */ | |
35 | 0x17, 0x18, 0x1B, 0x1D, 0x1E, 0x1F, 0x23, 0x25, /* Word 0 Bits 23..16 */ | |
36 | 0x26, 0x27, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, /* Word 0 Bits 15..08 */ | |
37 | 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x39, 0x3A, /* Word 0 Bits 07..00 */ | |
38 | ||
39 | 0x3C, 0x43, 0x45, 0x46, 0x47, 0x49, 0x4A, 0x4B, /* Word 1 Bits 31..24 */ | |
40 | 0x4C, 0x4D, 0x4E, 0x51, 0x52, 0x53, 0x54, 0x55, /* Word 1 Bits 23..16 */ | |
41 | 0x56, 0x59, 0x5A, 0x5C, 0x63, 0x65, 0x66, 0x67, /* Word 1 Bits 15..08 */ | |
42 | 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x71, 0x72, /* Word 1 Bits 07..00 */ | |
43 | ||
44 | 0x73, 0x74, 0x75, 0x76, 0x79, 0x7A, 0x7C, 0x80, /* Word 2 Bits 31..24 */ | |
45 | 0x81, 0x82, 0x84, 0x88, 0x8F, 0x90, 0x97, 0x98, /* Word 2 Bits 23..16 */ | |
46 | 0x9B, 0x9D, 0x9E, 0x9F, 0xA3, 0xA5, 0xA6, 0xA7, /* Word 2 Bits 15..08 */ | |
47 | 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xB1, 0xB2, /* Word 2 Bits 07..00 */ | |
48 | ||
49 | 0xB3, 0xB4, 0xB5, 0xB6, 0xB9, 0xBA, 0xBC, 0xC3, /* Word 3 Bits 31..24 */ | |
50 | 0xC5, 0xC6, 0xC7, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, /* Word 3 Bits 23..16 */ | |
51 | 0xCE, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD9, /* Word 3 Bits 15..08 */ | |
52 | 0xDA, 0xDC, 0xE0, 0xE1, 0xE2, 0xE4, 0xE8, 0xEF, /* Word 3 Bits 07..00 */ | |
53 | }; | |
54 | ||
a36c61f9 KG |
55 | static void bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, |
56 | struct fchs_s *rx_fchs, u8 reason_code, | |
57 | u8 reason_code_expl); | |
58 | static void bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port, | |
59 | struct fchs_s *rx_fchs, struct fc_logi_s *plogi); | |
60 | static void bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port); | |
61 | static void bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port); | |
62 | static void bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port); | |
63 | static void bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port); | |
64 | static void bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port); | |
65 | static void bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port); | |
66 | static void bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, | |
7725ccfd JH |
67 | struct fchs_s *rx_fchs, |
68 | struct fc_echo_s *echo, u16 len); | |
a36c61f9 | 69 | static void bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, |
7725ccfd JH |
70 | struct fchs_s *rx_fchs, |
71 | struct fc_rnid_cmd_s *rnid, u16 len); | |
a36c61f9 | 72 | static void bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port, |
7725ccfd JH |
73 | struct fc_rnid_general_topology_data_s *gen_topo_data); |
74 | ||
a36c61f9 KG |
75 | static void bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port); |
76 | static void bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port); | |
77 | static void bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port); | |
78 | ||
79 | static void bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port); | |
80 | static void bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port); | |
81 | static void bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port); | |
82 | ||
bc0e2c2a KG |
83 | static void bfa_fcs_lport_loop_init(struct bfa_fcs_lport_s *port); |
84 | static void bfa_fcs_lport_loop_online(struct bfa_fcs_lport_s *port); | |
85 | static void bfa_fcs_lport_loop_offline(struct bfa_fcs_lport_s *port); | |
86 | ||
7725ccfd | 87 | static struct { |
a36c61f9 KG |
88 | void (*init) (struct bfa_fcs_lport_s *port); |
89 | void (*online) (struct bfa_fcs_lport_s *port); | |
90 | void (*offline) (struct bfa_fcs_lport_s *port); | |
7725ccfd JH |
91 | } __port_action[] = { |
92 | { | |
a36c61f9 KG |
93 | bfa_fcs_lport_unknown_init, bfa_fcs_lport_unknown_online, |
94 | bfa_fcs_lport_unknown_offline}, { | |
95 | bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online, | |
96 | bfa_fcs_lport_fab_offline}, { | |
97 | bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online, | |
bc0e2c2a KG |
98 | bfa_fcs_lport_n2n_offline}, { |
99 | bfa_fcs_lport_loop_init, bfa_fcs_lport_loop_online, | |
100 | bfa_fcs_lport_loop_offline}, | |
a36c61f9 | 101 | }; |
7725ccfd | 102 | |
5fbe25c7 | 103 | /* |
7725ccfd JH |
104 | * fcs_port_sm FCS logical port state machine |
105 | */ | |
106 | ||
a36c61f9 | 107 | enum bfa_fcs_lport_event { |
7725ccfd JH |
108 | BFA_FCS_PORT_SM_CREATE = 1, |
109 | BFA_FCS_PORT_SM_ONLINE = 2, | |
110 | BFA_FCS_PORT_SM_OFFLINE = 3, | |
111 | BFA_FCS_PORT_SM_DELETE = 4, | |
112 | BFA_FCS_PORT_SM_DELRPORT = 5, | |
dd5aaf45 | 113 | BFA_FCS_PORT_SM_STOP = 6, |
7725ccfd JH |
114 | }; |
115 | ||
a36c61f9 KG |
116 | static void bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port, |
117 | enum bfa_fcs_lport_event event); | |
118 | static void bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port, | |
119 | enum bfa_fcs_lport_event event); | |
120 | static void bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s *port, | |
121 | enum bfa_fcs_lport_event event); | |
122 | static void bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port, | |
123 | enum bfa_fcs_lport_event event); | |
124 | static void bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port, | |
125 | enum bfa_fcs_lport_event event); | |
dd5aaf45 KG |
126 | static void bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port, |
127 | enum bfa_fcs_lport_event event); | |
7725ccfd JH |
128 | |
129 | static void | |
a36c61f9 KG |
130 | bfa_fcs_lport_sm_uninit( |
131 | struct bfa_fcs_lport_s *port, | |
132 | enum bfa_fcs_lport_event event) | |
7725ccfd JH |
133 | { |
134 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
135 | bfa_trc(port->fcs, event); | |
136 | ||
137 | switch (event) { | |
138 | case BFA_FCS_PORT_SM_CREATE: | |
a36c61f9 | 139 | bfa_sm_set_state(port, bfa_fcs_lport_sm_init); |
7725ccfd JH |
140 | break; |
141 | ||
142 | default: | |
e641de37 | 143 | bfa_sm_fault(port->fcs, event); |
7725ccfd JH |
144 | } |
145 | } | |
146 | ||
147 | static void | |
a36c61f9 KG |
148 | bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port, |
149 | enum bfa_fcs_lport_event event) | |
7725ccfd JH |
150 | { |
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_ONLINE: | |
a36c61f9 KG |
156 | bfa_sm_set_state(port, bfa_fcs_lport_sm_online); |
157 | bfa_fcs_lport_online_actions(port); | |
7725ccfd JH |
158 | break; |
159 | ||
160 | case BFA_FCS_PORT_SM_DELETE: | |
a36c61f9 KG |
161 | bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit); |
162 | bfa_fcs_lport_deleted(port); | |
7725ccfd JH |
163 | break; |
164 | ||
dd5aaf45 KG |
165 | case BFA_FCS_PORT_SM_STOP: |
166 | /* If vport - send completion call back */ | |
167 | if (port->vport) | |
168 | bfa_fcs_vport_stop_comp(port->vport); | |
881c1b3c KG |
169 | else |
170 | bfa_wc_down(&(port->fabric->stop_wc)); | |
dd5aaf45 KG |
171 | break; |
172 | ||
3e98cc01 JH |
173 | case BFA_FCS_PORT_SM_OFFLINE: |
174 | break; | |
175 | ||
7725ccfd | 176 | default: |
e641de37 | 177 | bfa_sm_fault(port->fcs, event); |
7725ccfd JH |
178 | } |
179 | } | |
180 | ||
181 | static void | |
a36c61f9 KG |
182 | bfa_fcs_lport_sm_online( |
183 | struct bfa_fcs_lport_s *port, | |
184 | enum bfa_fcs_lport_event event) | |
7725ccfd JH |
185 | { |
186 | struct bfa_fcs_rport_s *rport; | |
a36c61f9 | 187 | struct list_head *qe, *qen; |
7725ccfd JH |
188 | |
189 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
190 | bfa_trc(port->fcs, event); | |
191 | ||
192 | switch (event) { | |
193 | case BFA_FCS_PORT_SM_OFFLINE: | |
a36c61f9 KG |
194 | bfa_sm_set_state(port, bfa_fcs_lport_sm_offline); |
195 | bfa_fcs_lport_offline_actions(port); | |
7725ccfd JH |
196 | break; |
197 | ||
dd5aaf45 KG |
198 | case BFA_FCS_PORT_SM_STOP: |
199 | __port_action[port->fabric->fab_type].offline(port); | |
200 | ||
201 | if (port->num_rports == 0) { | |
202 | bfa_sm_set_state(port, bfa_fcs_lport_sm_init); | |
203 | /* If vport - send completion call back */ | |
204 | if (port->vport) | |
205 | bfa_fcs_vport_stop_comp(port->vport); | |
881c1b3c KG |
206 | else |
207 | bfa_wc_down(&(port->fabric->stop_wc)); | |
dd5aaf45 KG |
208 | } else { |
209 | bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping); | |
210 | list_for_each_safe(qe, qen, &port->rport_q) { | |
211 | rport = (struct bfa_fcs_rport_s *) qe; | |
212 | bfa_sm_send_event(rport, RPSM_EVENT_DELETE); | |
213 | } | |
214 | } | |
215 | break; | |
216 | ||
7725ccfd JH |
217 | case BFA_FCS_PORT_SM_DELETE: |
218 | ||
219 | __port_action[port->fabric->fab_type].offline(port); | |
220 | ||
221 | if (port->num_rports == 0) { | |
a36c61f9 KG |
222 | bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit); |
223 | bfa_fcs_lport_deleted(port); | |
7725ccfd | 224 | } else { |
a36c61f9 | 225 | bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting); |
7725ccfd | 226 | list_for_each_safe(qe, qen, &port->rport_q) { |
a36c61f9 | 227 | rport = (struct bfa_fcs_rport_s *) qe; |
f7f73812 | 228 | bfa_sm_send_event(rport, RPSM_EVENT_DELETE); |
7725ccfd JH |
229 | } |
230 | } | |
231 | break; | |
232 | ||
233 | case BFA_FCS_PORT_SM_DELRPORT: | |
234 | break; | |
235 | ||
236 | default: | |
e641de37 | 237 | bfa_sm_fault(port->fcs, event); |
7725ccfd JH |
238 | } |
239 | } | |
240 | ||
241 | static void | |
a36c61f9 KG |
242 | bfa_fcs_lport_sm_offline( |
243 | struct bfa_fcs_lport_s *port, | |
244 | enum bfa_fcs_lport_event event) | |
7725ccfd JH |
245 | { |
246 | struct bfa_fcs_rport_s *rport; | |
a36c61f9 | 247 | struct list_head *qe, *qen; |
7725ccfd JH |
248 | |
249 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
250 | bfa_trc(port->fcs, event); | |
251 | ||
252 | switch (event) { | |
253 | case BFA_FCS_PORT_SM_ONLINE: | |
a36c61f9 KG |
254 | bfa_sm_set_state(port, bfa_fcs_lport_sm_online); |
255 | bfa_fcs_lport_online_actions(port); | |
7725ccfd JH |
256 | break; |
257 | ||
dd5aaf45 KG |
258 | case BFA_FCS_PORT_SM_STOP: |
259 | if (port->num_rports == 0) { | |
260 | bfa_sm_set_state(port, bfa_fcs_lport_sm_init); | |
261 | /* If vport - send completion call back */ | |
262 | if (port->vport) | |
263 | bfa_fcs_vport_stop_comp(port->vport); | |
881c1b3c KG |
264 | else |
265 | bfa_wc_down(&(port->fabric->stop_wc)); | |
dd5aaf45 KG |
266 | } else { |
267 | bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping); | |
268 | list_for_each_safe(qe, qen, &port->rport_q) { | |
269 | rport = (struct bfa_fcs_rport_s *) qe; | |
270 | bfa_sm_send_event(rport, RPSM_EVENT_DELETE); | |
271 | } | |
272 | } | |
273 | break; | |
274 | ||
7725ccfd JH |
275 | case BFA_FCS_PORT_SM_DELETE: |
276 | if (port->num_rports == 0) { | |
a36c61f9 KG |
277 | bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit); |
278 | bfa_fcs_lport_deleted(port); | |
7725ccfd | 279 | } else { |
a36c61f9 | 280 | bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting); |
7725ccfd | 281 | list_for_each_safe(qe, qen, &port->rport_q) { |
a36c61f9 | 282 | rport = (struct bfa_fcs_rport_s *) qe; |
f7f73812 | 283 | bfa_sm_send_event(rport, RPSM_EVENT_DELETE); |
7725ccfd JH |
284 | } |
285 | } | |
286 | break; | |
287 | ||
288 | case BFA_FCS_PORT_SM_DELRPORT: | |
289 | case BFA_FCS_PORT_SM_OFFLINE: | |
290 | break; | |
291 | ||
292 | default: | |
e641de37 | 293 | bfa_sm_fault(port->fcs, event); |
7725ccfd JH |
294 | } |
295 | } | |
296 | ||
dd5aaf45 KG |
297 | static void |
298 | bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port, | |
299 | enum bfa_fcs_lport_event event) | |
300 | { | |
301 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
302 | bfa_trc(port->fcs, event); | |
303 | ||
304 | switch (event) { | |
305 | case BFA_FCS_PORT_SM_DELRPORT: | |
306 | if (port->num_rports == 0) { | |
307 | bfa_sm_set_state(port, bfa_fcs_lport_sm_init); | |
308 | /* If vport - send completion call back */ | |
309 | if (port->vport) | |
310 | bfa_fcs_vport_stop_comp(port->vport); | |
881c1b3c KG |
311 | else |
312 | bfa_wc_down(&(port->fabric->stop_wc)); | |
dd5aaf45 KG |
313 | } |
314 | break; | |
315 | ||
316 | default: | |
317 | bfa_sm_fault(port->fcs, event); | |
318 | } | |
319 | } | |
320 | ||
7725ccfd | 321 | static void |
a36c61f9 KG |
322 | bfa_fcs_lport_sm_deleting( |
323 | struct bfa_fcs_lport_s *port, | |
324 | enum bfa_fcs_lport_event event) | |
7725ccfd JH |
325 | { |
326 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
327 | bfa_trc(port->fcs, event); | |
328 | ||
329 | switch (event) { | |
330 | case BFA_FCS_PORT_SM_DELRPORT: | |
331 | if (port->num_rports == 0) { | |
a36c61f9 KG |
332 | bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit); |
333 | bfa_fcs_lport_deleted(port); | |
7725ccfd JH |
334 | } |
335 | break; | |
336 | ||
337 | default: | |
e641de37 | 338 | bfa_sm_fault(port->fcs, event); |
7725ccfd JH |
339 | } |
340 | } | |
341 | ||
5fbe25c7 | 342 | /* |
7725ccfd JH |
343 | * fcs_port_pvt |
344 | */ | |
345 | ||
7826f304 KG |
346 | /* |
347 | * Send AEN notification | |
348 | */ | |
349 | static void | |
350 | bfa_fcs_lport_aen_post(struct bfa_fcs_lport_s *port, | |
351 | enum bfa_lport_aen_event event) | |
352 | { | |
353 | struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad; | |
354 | struct bfa_aen_entry_s *aen_entry; | |
355 | ||
356 | bfad_get_aen_entry(bfad, aen_entry); | |
357 | if (!aen_entry) | |
358 | return; | |
359 | ||
360 | aen_entry->aen_data.lport.vf_id = port->fabric->vf_id; | |
361 | aen_entry->aen_data.lport.roles = port->port_cfg.roles; | |
362 | aen_entry->aen_data.lport.ppwwn = bfa_fcs_lport_get_pwwn( | |
363 | bfa_fcs_get_base_port(port->fcs)); | |
364 | aen_entry->aen_data.lport.lpwwn = bfa_fcs_lport_get_pwwn(port); | |
365 | ||
366 | /* Send the AEN notification */ | |
367 | bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq, | |
368 | BFA_AEN_CAT_LPORT, event); | |
369 | } | |
370 | ||
7725ccfd JH |
371 | /* |
372 | * Send a LS reject | |
373 | */ | |
374 | static void | |
a36c61f9 | 375 | bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs, |
7725ccfd JH |
376 | u8 reason_code, u8 reason_code_expl) |
377 | { | |
a36c61f9 | 378 | struct fchs_s fchs; |
7725ccfd JH |
379 | struct bfa_fcxp_s *fcxp; |
380 | struct bfa_rport_s *bfa_rport = NULL; | |
a36c61f9 | 381 | int len; |
7725ccfd | 382 | |
a36c61f9 | 383 | bfa_trc(port->fcs, rx_fchs->d_id); |
7725ccfd JH |
384 | bfa_trc(port->fcs, rx_fchs->s_id); |
385 | ||
c3f1b123 | 386 | fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE); |
7725ccfd JH |
387 | if (!fcxp) |
388 | return; | |
389 | ||
a36c61f9 KG |
390 | len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), |
391 | rx_fchs->s_id, bfa_fcs_lport_get_fcid(port), | |
392 | rx_fchs->ox_id, reason_code, reason_code_expl); | |
7725ccfd JH |
393 | |
394 | bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, | |
a36c61f9 KG |
395 | BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, |
396 | FC_MAX_PDUSZ, 0); | |
7725ccfd JH |
397 | } |
398 | ||
d7be54cc KG |
399 | /* |
400 | * Send a FCCT Reject | |
401 | */ | |
402 | static void | |
403 | bfa_fcs_lport_send_fcgs_rjt(struct bfa_fcs_lport_s *port, | |
404 | struct fchs_s *rx_fchs, u8 reason_code, u8 reason_code_expl) | |
405 | { | |
406 | struct fchs_s fchs; | |
407 | struct bfa_fcxp_s *fcxp; | |
408 | struct bfa_rport_s *bfa_rport = NULL; | |
409 | int len; | |
410 | struct ct_hdr_s *rx_cthdr = (struct ct_hdr_s *)(rx_fchs + 1); | |
411 | struct ct_hdr_s *ct_hdr; | |
412 | ||
413 | bfa_trc(port->fcs, rx_fchs->d_id); | |
414 | bfa_trc(port->fcs, rx_fchs->s_id); | |
415 | ||
c3f1b123 | 416 | fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE); |
d7be54cc KG |
417 | if (!fcxp) |
418 | return; | |
419 | ||
420 | ct_hdr = bfa_fcxp_get_reqbuf(fcxp); | |
421 | ct_hdr->gs_type = rx_cthdr->gs_type; | |
422 | ct_hdr->gs_sub_type = rx_cthdr->gs_sub_type; | |
423 | ||
424 | len = fc_gs_rjt_build(&fchs, ct_hdr, rx_fchs->s_id, | |
425 | bfa_fcs_lport_get_fcid(port), | |
426 | rx_fchs->ox_id, reason_code, reason_code_expl); | |
427 | ||
428 | bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, | |
429 | BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, | |
430 | FC_MAX_PDUSZ, 0); | |
431 | } | |
432 | ||
5fbe25c7 | 433 | /* |
7725ccfd JH |
434 | * Process incoming plogi from a remote port. |
435 | */ | |
436 | static void | |
a36c61f9 KG |
437 | bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port, |
438 | struct fchs_s *rx_fchs, struct fc_logi_s *plogi) | |
7725ccfd JH |
439 | { |
440 | struct bfa_fcs_rport_s *rport; | |
441 | ||
442 | bfa_trc(port->fcs, rx_fchs->d_id); | |
443 | bfa_trc(port->fcs, rx_fchs->s_id); | |
444 | ||
445 | /* | |
446 | * If min cfg mode is enabled, drop any incoming PLOGIs | |
447 | */ | |
448 | if (__fcs_min_cfg(port->fcs)) { | |
449 | bfa_trc(port->fcs, rx_fchs->s_id); | |
450 | return; | |
451 | } | |
452 | ||
453 | if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) { | |
454 | bfa_trc(port->fcs, rx_fchs->s_id); | |
455 | /* | |
456 | * send a LS reject | |
457 | */ | |
a36c61f9 KG |
458 | bfa_fcs_lport_send_ls_rjt(port, rx_fchs, |
459 | FC_LS_RJT_RSN_PROTOCOL_ERROR, | |
460 | FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS); | |
7725ccfd JH |
461 | return; |
462 | } | |
463 | ||
5fbe25c7 | 464 | /* |
a36c61f9 | 465 | * Direct Attach P2P mode : verify address assigned by the r-port. |
7725ccfd | 466 | */ |
a36c61f9 KG |
467 | if ((!bfa_fcs_fabric_is_switched(port->fabric)) && |
468 | (memcmp((void *)&bfa_fcs_lport_get_pwwn(port), | |
469 | (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) { | |
7725ccfd | 470 | if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) { |
a36c61f9 KG |
471 | /* Address assigned to us cannot be a WKA */ |
472 | bfa_fcs_lport_send_ls_rjt(port, rx_fchs, | |
7725ccfd JH |
473 | FC_LS_RJT_RSN_PROTOCOL_ERROR, |
474 | FC_LS_RJT_EXP_INVALID_NPORT_ID); | |
475 | return; | |
476 | } | |
a36c61f9 | 477 | port->pid = rx_fchs->d_id; |
b704495c | 478 | bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id); |
7725ccfd JH |
479 | } |
480 | ||
5fbe25c7 | 481 | /* |
7725ccfd JH |
482 | * First, check if we know the device by pwwn. |
483 | */ | |
a36c61f9 | 484 | rport = bfa_fcs_lport_get_rport_by_pwwn(port, plogi->port_name); |
7725ccfd | 485 | if (rport) { |
5fbe25c7 | 486 | /* |
a36c61f9 KG |
487 | * Direct Attach P2P mode : handle address assigned by r-port. |
488 | */ | |
489 | if ((!bfa_fcs_fabric_is_switched(port->fabric)) && | |
490 | (memcmp((void *)&bfa_fcs_lport_get_pwwn(port), | |
491 | (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) { | |
492 | port->pid = rx_fchs->d_id; | |
b704495c | 493 | bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id); |
7725ccfd JH |
494 | rport->pid = rx_fchs->s_id; |
495 | } | |
496 | bfa_fcs_rport_plogi(rport, rx_fchs, plogi); | |
497 | return; | |
498 | } | |
499 | ||
5fbe25c7 | 500 | /* |
7725ccfd JH |
501 | * Next, lookup rport by PID. |
502 | */ | |
a36c61f9 | 503 | rport = bfa_fcs_lport_get_rport_by_pid(port, rx_fchs->s_id); |
7725ccfd | 504 | if (!rport) { |
5fbe25c7 | 505 | /* |
7725ccfd JH |
506 | * Inbound PLOGI from a new device. |
507 | */ | |
508 | bfa_fcs_rport_plogi_create(port, rx_fchs, plogi); | |
509 | return; | |
510 | } | |
511 | ||
5fbe25c7 | 512 | /* |
7725ccfd JH |
513 | * Rport is known only by PID. |
514 | */ | |
515 | if (rport->pwwn) { | |
5fbe25c7 | 516 | /* |
7725ccfd JH |
517 | * This is a different device with the same pid. Old device |
518 | * disappeared. Send implicit LOGO to old device. | |
519 | */ | |
d4b671c5 | 520 | WARN_ON(rport->pwwn == plogi->port_name); |
f7f73812 | 521 | bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP); |
7725ccfd | 522 | |
5fbe25c7 | 523 | /* |
7725ccfd JH |
524 | * Inbound PLOGI from a new device (with old PID). |
525 | */ | |
526 | bfa_fcs_rport_plogi_create(port, rx_fchs, plogi); | |
527 | return; | |
528 | } | |
529 | ||
5fbe25c7 | 530 | /* |
7725ccfd JH |
531 | * PLOGI crossing each other. |
532 | */ | |
d4b671c5 | 533 | WARN_ON(rport->pwwn != WWN_NULL); |
7725ccfd JH |
534 | bfa_fcs_rport_plogi(rport, rx_fchs, plogi); |
535 | } | |
536 | ||
537 | /* | |
538 | * Process incoming ECHO. | |
539 | * Since it does not require a login, it is processed here. | |
540 | */ | |
541 | static void | |
a36c61f9 KG |
542 | bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs, |
543 | struct fc_echo_s *echo, u16 rx_len) | |
7725ccfd | 544 | { |
a36c61f9 KG |
545 | struct fchs_s fchs; |
546 | struct bfa_fcxp_s *fcxp; | |
547 | struct bfa_rport_s *bfa_rport = NULL; | |
548 | int len, pyld_len; | |
7725ccfd JH |
549 | |
550 | bfa_trc(port->fcs, rx_fchs->s_id); | |
551 | bfa_trc(port->fcs, rx_fchs->d_id); | |
7725ccfd | 552 | |
c3f1b123 | 553 | fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE); |
7725ccfd JH |
554 | if (!fcxp) |
555 | return; | |
556 | ||
a36c61f9 KG |
557 | len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), |
558 | rx_fchs->s_id, bfa_fcs_lport_get_fcid(port), | |
559 | rx_fchs->ox_id); | |
7725ccfd JH |
560 | |
561 | /* | |
562 | * Copy the payload (if any) from the echo frame | |
563 | */ | |
564 | pyld_len = rx_len - sizeof(struct fchs_s); | |
a36c61f9 | 565 | bfa_trc(port->fcs, rx_len); |
7725ccfd JH |
566 | bfa_trc(port->fcs, pyld_len); |
567 | ||
568 | if (pyld_len > len) | |
569 | memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) + | |
a36c61f9 KG |
570 | sizeof(struct fc_echo_s), (echo + 1), |
571 | (pyld_len - sizeof(struct fc_echo_s))); | |
7725ccfd JH |
572 | |
573 | bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, | |
a36c61f9 KG |
574 | BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL, |
575 | FC_MAX_PDUSZ, 0); | |
7725ccfd JH |
576 | } |
577 | ||
578 | /* | |
579 | * Process incoming RNID. | |
580 | * Since it does not require a login, it is processed here. | |
581 | */ | |
582 | static void | |
a36c61f9 KG |
583 | bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs, |
584 | struct fc_rnid_cmd_s *rnid, u16 rx_len) | |
7725ccfd JH |
585 | { |
586 | struct fc_rnid_common_id_data_s common_id_data; | |
587 | struct fc_rnid_general_topology_data_s gen_topo_data; | |
a36c61f9 | 588 | struct fchs_s fchs; |
7725ccfd JH |
589 | struct bfa_fcxp_s *fcxp; |
590 | struct bfa_rport_s *bfa_rport = NULL; | |
a36c61f9 KG |
591 | u16 len; |
592 | u32 data_format; | |
7725ccfd JH |
593 | |
594 | bfa_trc(port->fcs, rx_fchs->s_id); | |
595 | bfa_trc(port->fcs, rx_fchs->d_id); | |
596 | bfa_trc(port->fcs, rx_len); | |
597 | ||
c3f1b123 | 598 | fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE); |
7725ccfd JH |
599 | if (!fcxp) |
600 | return; | |
601 | ||
602 | /* | |
603 | * Check Node Indentification Data Format | |
604 | * We only support General Topology Discovery Format. | |
605 | * For any other requested Data Formats, we return Common Node Id Data | |
606 | * only, as per FC-LS. | |
607 | */ | |
608 | bfa_trc(port->fcs, rnid->node_id_data_format); | |
609 | if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) { | |
610 | data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY; | |
611 | /* | |
612 | * Get General topology data for this port | |
613 | */ | |
614 | bfa_fs_port_get_gen_topo_data(port, &gen_topo_data); | |
615 | } else { | |
616 | data_format = RNID_NODEID_DATA_FORMAT_COMMON; | |
617 | } | |
618 | ||
619 | /* | |
620 | * Copy the Node Id Info | |
621 | */ | |
a36c61f9 KG |
622 | common_id_data.port_name = bfa_fcs_lport_get_pwwn(port); |
623 | common_id_data.node_name = bfa_fcs_lport_get_nwwn(port); | |
7725ccfd | 624 | |
a36c61f9 KG |
625 | len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), |
626 | rx_fchs->s_id, bfa_fcs_lport_get_fcid(port), | |
627 | rx_fchs->ox_id, data_format, &common_id_data, | |
628 | &gen_topo_data); | |
7725ccfd JH |
629 | |
630 | bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, | |
a36c61f9 KG |
631 | BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, |
632 | FC_MAX_PDUSZ, 0); | |
7725ccfd JH |
633 | } |
634 | ||
635 | /* | |
636 | * Fill out General Topolpgy Discovery Data for RNID ELS. | |
637 | */ | |
638 | static void | |
a36c61f9 | 639 | bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port, |
7725ccfd JH |
640 | struct fc_rnid_general_topology_data_s *gen_topo_data) |
641 | { | |
6a18b167 | 642 | memset(gen_topo_data, 0, |
7725ccfd JH |
643 | sizeof(struct fc_rnid_general_topology_data_s)); |
644 | ||
ba816ea8 | 645 | gen_topo_data->asso_type = cpu_to_be32(RNID_ASSOCIATED_TYPE_HOST); |
7725ccfd | 646 | gen_topo_data->phy_port_num = 0; /* @todo */ |
ba816ea8 | 647 | gen_topo_data->num_attached_nodes = cpu_to_be32(1); |
7725ccfd JH |
648 | } |
649 | ||
650 | static void | |
a36c61f9 | 651 | bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port) |
7725ccfd | 652 | { |
a36c61f9 KG |
653 | struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad; |
654 | char lpwwn_buf[BFA_STRING_32]; | |
655 | ||
7725ccfd JH |
656 | bfa_trc(port->fcs, port->fabric->oper_type); |
657 | ||
658 | __port_action[port->fabric->fab_type].init(port); | |
659 | __port_action[port->fabric->fab_type].online(port); | |
660 | ||
a36c61f9 | 661 | wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port)); |
a3f29ccc | 662 | BFA_LOG(KERN_WARNING, bfad, bfa_log_level, |
a36c61f9 KG |
663 | "Logical port online: WWN = %s Role = %s\n", |
664 | lpwwn_buf, "Initiator"); | |
7826f304 | 665 | bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_ONLINE); |
a36c61f9 KG |
666 | |
667 | bfad->bfad_flags |= BFAD_PORT_ONLINE; | |
7725ccfd JH |
668 | } |
669 | ||
670 | static void | |
a36c61f9 | 671 | bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port) |
7725ccfd | 672 | { |
a36c61f9 | 673 | struct list_head *qe, *qen; |
7725ccfd | 674 | struct bfa_fcs_rport_s *rport; |
a36c61f9 KG |
675 | struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad; |
676 | char lpwwn_buf[BFA_STRING_32]; | |
7725ccfd JH |
677 | |
678 | bfa_trc(port->fcs, port->fabric->oper_type); | |
679 | ||
680 | __port_action[port->fabric->fab_type].offline(port); | |
681 | ||
a36c61f9 | 682 | wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port)); |
f7f73812 | 683 | if (bfa_sm_cmp_state(port->fabric, |
7826f304 | 684 | bfa_fcs_fabric_sm_online) == BFA_TRUE) { |
a3f29ccc | 685 | BFA_LOG(KERN_WARNING, bfad, bfa_log_level, |
a36c61f9 KG |
686 | "Logical port lost fabric connectivity: WWN = %s Role = %s\n", |
687 | lpwwn_buf, "Initiator"); | |
7826f304 KG |
688 | bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_DISCONNECT); |
689 | } else { | |
a3f29ccc | 690 | BFA_LOG(KERN_WARNING, bfad, bfa_log_level, |
a36c61f9 KG |
691 | "Logical port taken offline: WWN = %s Role = %s\n", |
692 | lpwwn_buf, "Initiator"); | |
7826f304 KG |
693 | bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_OFFLINE); |
694 | } | |
7725ccfd JH |
695 | |
696 | list_for_each_safe(qe, qen, &port->rport_q) { | |
a36c61f9 | 697 | rport = (struct bfa_fcs_rport_s *) qe; |
f7f73812 | 698 | bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP); |
7725ccfd JH |
699 | } |
700 | } | |
701 | ||
702 | static void | |
a36c61f9 | 703 | bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port) |
7725ccfd | 704 | { |
d4b671c5 | 705 | WARN_ON(1); |
7725ccfd JH |
706 | } |
707 | ||
708 | static void | |
a36c61f9 | 709 | bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port) |
7725ccfd | 710 | { |
d4b671c5 | 711 | WARN_ON(1); |
7725ccfd JH |
712 | } |
713 | ||
714 | static void | |
a36c61f9 | 715 | bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port) |
7725ccfd | 716 | { |
d4b671c5 | 717 | WARN_ON(1); |
7725ccfd JH |
718 | } |
719 | ||
720 | static void | |
a36c61f9 | 721 | bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs) |
7725ccfd | 722 | { |
a36c61f9 KG |
723 | struct fchs_s fchs; |
724 | struct bfa_fcxp_s *fcxp; | |
725 | int len; | |
7725ccfd | 726 | |
a36c61f9 KG |
727 | bfa_trc(port->fcs, rx_fchs->d_id); |
728 | bfa_trc(port->fcs, rx_fchs->s_id); | |
729 | ||
c3f1b123 | 730 | fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE); |
a36c61f9 KG |
731 | if (!fcxp) |
732 | return; | |
733 | ||
734 | len = fc_ba_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | |
735 | rx_fchs->s_id, bfa_fcs_lport_get_fcid(port), | |
736 | rx_fchs->ox_id, 0); | |
737 | ||
738 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, | |
739 | BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, | |
740 | FC_MAX_PDUSZ, 0); | |
741 | } | |
742 | static void | |
743 | bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port) | |
744 | { | |
745 | struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad; | |
746 | char lpwwn_buf[BFA_STRING_32]; | |
747 | ||
748 | wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port)); | |
88166242 | 749 | BFA_LOG(KERN_INFO, bfad, bfa_log_level, |
a36c61f9 KG |
750 | "Logical port deleted: WWN = %s Role = %s\n", |
751 | lpwwn_buf, "Initiator"); | |
7826f304 | 752 | bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_DELETE); |
a36c61f9 KG |
753 | |
754 | /* Base port will be deleted by the OS driver */ | |
17c201b3 | 755 | if (port->vport) |
7725ccfd | 756 | bfa_fcs_vport_delete_comp(port->vport); |
17c201b3 | 757 | else |
f7f73812 | 758 | bfa_wc_down(&port->fabric->wc); |
7725ccfd JH |
759 | } |
760 | ||
761 | ||
5fbe25c7 | 762 | /* |
a36c61f9 | 763 | * Unsolicited frame receive handling. |
7725ccfd JH |
764 | */ |
765 | void | |
a36c61f9 KG |
766 | bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport, |
767 | struct fchs_s *fchs, u16 len) | |
7725ccfd | 768 | { |
a36c61f9 | 769 | u32 pid = fchs->s_id; |
7725ccfd | 770 | struct bfa_fcs_rport_s *rport = NULL; |
a36c61f9 | 771 | struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); |
7725ccfd JH |
772 | |
773 | bfa_stats(lport, uf_recvs); | |
15821f05 | 774 | bfa_trc(lport->fcs, fchs->type); |
7725ccfd | 775 | |
a36c61f9 | 776 | if (!bfa_fcs_lport_is_online(lport)) { |
9781851f VMG |
777 | /* |
778 | * In direct attach topology, it is possible to get a PLOGI | |
779 | * before the lport is online due to port feature | |
780 | * (QoS/Trunk/FEC/CR), so send a rjt | |
781 | */ | |
782 | if ((fchs->type == FC_TYPE_ELS) && | |
783 | (els_cmd->els_code == FC_ELS_PLOGI)) { | |
784 | bfa_fcs_lport_send_ls_rjt(lport, fchs, | |
785 | FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD, | |
786 | FC_LS_RJT_EXP_NO_ADDL_INFO); | |
787 | bfa_stats(lport, plogi_rcvd); | |
788 | } else | |
789 | bfa_stats(lport, uf_recv_drops); | |
790 | ||
7725ccfd JH |
791 | return; |
792 | } | |
793 | ||
5fbe25c7 | 794 | /* |
7725ccfd JH |
795 | * First, handle ELSs that donot require a login. |
796 | */ | |
797 | /* | |
798 | * Handle PLOGI first | |
799 | */ | |
800 | if ((fchs->type == FC_TYPE_ELS) && | |
801 | (els_cmd->els_code == FC_ELS_PLOGI)) { | |
a36c61f9 | 802 | bfa_fcs_lport_plogi(lport, fchs, (struct fc_logi_s *) els_cmd); |
7725ccfd JH |
803 | return; |
804 | } | |
805 | ||
806 | /* | |
807 | * Handle ECHO separately. | |
808 | */ | |
809 | if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) { | |
a36c61f9 KG |
810 | bfa_fcs_lport_echo(lport, fchs, |
811 | (struct fc_echo_s *)els_cmd, len); | |
7725ccfd JH |
812 | return; |
813 | } | |
814 | ||
815 | /* | |
816 | * Handle RNID separately. | |
817 | */ | |
818 | if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) { | |
a36c61f9 | 819 | bfa_fcs_lport_rnid(lport, fchs, |
7725ccfd JH |
820 | (struct fc_rnid_cmd_s *) els_cmd, len); |
821 | return; | |
822 | } | |
823 | ||
a36c61f9 KG |
824 | if (fchs->type == FC_TYPE_BLS) { |
825 | if ((fchs->routing == FC_RTG_BASIC_LINK) && | |
826 | (fchs->cat_info == FC_CAT_ABTS)) | |
827 | bfa_fcs_lport_abts_acc(lport, fchs); | |
828 | return; | |
829 | } | |
d7be54cc KG |
830 | |
831 | if (fchs->type == FC_TYPE_SERVICES) { | |
832 | /* | |
833 | * Unhandled FC-GS frames. Send a FC-CT Reject | |
834 | */ | |
835 | bfa_fcs_lport_send_fcgs_rjt(lport, fchs, CT_RSN_NOT_SUPP, | |
836 | CT_NS_EXP_NOADDITIONAL); | |
837 | return; | |
838 | } | |
839 | ||
5fbe25c7 | 840 | /* |
7725ccfd JH |
841 | * look for a matching remote port ID |
842 | */ | |
a36c61f9 | 843 | rport = bfa_fcs_lport_get_rport_by_pid(lport, pid); |
7725ccfd JH |
844 | if (rport) { |
845 | bfa_trc(rport->fcs, fchs->s_id); | |
846 | bfa_trc(rport->fcs, fchs->d_id); | |
847 | bfa_trc(rport->fcs, fchs->type); | |
848 | ||
849 | bfa_fcs_rport_uf_recv(rport, fchs, len); | |
850 | return; | |
851 | } | |
852 | ||
5fbe25c7 | 853 | /* |
7725ccfd JH |
854 | * Only handles ELS frames for now. |
855 | */ | |
856 | if (fchs->type != FC_TYPE_ELS) { | |
15821f05 KG |
857 | bfa_trc(lport->fcs, fchs->s_id); |
858 | bfa_trc(lport->fcs, fchs->d_id); | |
859 | /* ignore type FC_TYPE_FC_FSS */ | |
860 | if (fchs->type != FC_TYPE_FC_FSS) | |
861 | bfa_sm_fault(lport->fcs, fchs->type); | |
7725ccfd JH |
862 | return; |
863 | } | |
864 | ||
865 | bfa_trc(lport->fcs, els_cmd->els_code); | |
866 | if (els_cmd->els_code == FC_ELS_RSCN) { | |
a36c61f9 | 867 | bfa_fcs_lport_scn_process_rscn(lport, fchs, len); |
7725ccfd JH |
868 | return; |
869 | } | |
870 | ||
871 | if (els_cmd->els_code == FC_ELS_LOGO) { | |
5fbe25c7 | 872 | /* |
7725ccfd JH |
873 | * @todo Handle LOGO frames received. |
874 | */ | |
7725ccfd JH |
875 | return; |
876 | } | |
877 | ||
878 | if (els_cmd->els_code == FC_ELS_PRLI) { | |
5fbe25c7 | 879 | /* |
7725ccfd JH |
880 | * @todo Handle PRLI frames received. |
881 | */ | |
7725ccfd JH |
882 | return; |
883 | } | |
884 | ||
5fbe25c7 | 885 | /* |
7725ccfd JH |
886 | * Unhandled ELS frames. Send a LS_RJT. |
887 | */ | |
a36c61f9 | 888 | bfa_fcs_lport_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP, |
7725ccfd JH |
889 | FC_LS_RJT_EXP_NO_ADDL_INFO); |
890 | ||
891 | } | |
892 | ||
5fbe25c7 | 893 | /* |
7725ccfd JH |
894 | * PID based Lookup for a R-Port in the Port R-Port Queue |
895 | */ | |
896 | struct bfa_fcs_rport_s * | |
a36c61f9 | 897 | bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid) |
7725ccfd JH |
898 | { |
899 | struct bfa_fcs_rport_s *rport; | |
a36c61f9 | 900 | struct list_head *qe; |
7725ccfd JH |
901 | |
902 | list_for_each(qe, &port->rport_q) { | |
a36c61f9 | 903 | rport = (struct bfa_fcs_rport_s *) qe; |
7725ccfd JH |
904 | if (rport->pid == pid) |
905 | return rport; | |
906 | } | |
907 | ||
908 | bfa_trc(port->fcs, pid); | |
909 | return NULL; | |
910 | } | |
911 | ||
ee1a4a42 KG |
912 | /* |
913 | * OLD_PID based Lookup for a R-Port in the Port R-Port Queue | |
914 | */ | |
915 | struct bfa_fcs_rport_s * | |
916 | bfa_fcs_lport_get_rport_by_old_pid(struct bfa_fcs_lport_s *port, u32 pid) | |
917 | { | |
918 | struct bfa_fcs_rport_s *rport; | |
919 | struct list_head *qe; | |
920 | ||
921 | list_for_each(qe, &port->rport_q) { | |
922 | rport = (struct bfa_fcs_rport_s *) qe; | |
923 | if (rport->old_pid == pid) | |
924 | return rport; | |
925 | } | |
926 | ||
927 | bfa_trc(port->fcs, pid); | |
928 | return NULL; | |
929 | } | |
930 | ||
5fbe25c7 | 931 | /* |
7725ccfd JH |
932 | * PWWN based Lookup for a R-Port in the Port R-Port Queue |
933 | */ | |
934 | struct bfa_fcs_rport_s * | |
a36c61f9 | 935 | bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s *port, wwn_t pwwn) |
7725ccfd JH |
936 | { |
937 | struct bfa_fcs_rport_s *rport; | |
a36c61f9 | 938 | struct list_head *qe; |
7725ccfd JH |
939 | |
940 | list_for_each(qe, &port->rport_q) { | |
a36c61f9 | 941 | rport = (struct bfa_fcs_rport_s *) qe; |
7725ccfd JH |
942 | if (wwn_is_equal(rport->pwwn, pwwn)) |
943 | return rport; | |
944 | } | |
945 | ||
946 | bfa_trc(port->fcs, pwwn); | |
f8ceafde | 947 | return NULL; |
7725ccfd JH |
948 | } |
949 | ||
5fbe25c7 | 950 | /* |
7725ccfd JH |
951 | * NWWN based Lookup for a R-Port in the Port R-Port Queue |
952 | */ | |
953 | struct bfa_fcs_rport_s * | |
a36c61f9 | 954 | bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn) |
7725ccfd JH |
955 | { |
956 | struct bfa_fcs_rport_s *rport; | |
a36c61f9 | 957 | struct list_head *qe; |
7725ccfd JH |
958 | |
959 | list_for_each(qe, &port->rport_q) { | |
a36c61f9 | 960 | rport = (struct bfa_fcs_rport_s *) qe; |
7725ccfd JH |
961 | if (wwn_is_equal(rport->nwwn, nwwn)) |
962 | return rport; | |
963 | } | |
964 | ||
965 | bfa_trc(port->fcs, nwwn); | |
f8ceafde | 966 | return NULL; |
7725ccfd JH |
967 | } |
968 | ||
ee1a4a42 KG |
969 | /* |
970 | * PWWN & PID based Lookup for a R-Port in the Port R-Port Queue | |
971 | */ | |
972 | struct bfa_fcs_rport_s * | |
973 | bfa_fcs_lport_get_rport_by_qualifier(struct bfa_fcs_lport_s *port, | |
974 | wwn_t pwwn, u32 pid) | |
975 | { | |
976 | struct bfa_fcs_rport_s *rport; | |
977 | struct list_head *qe; | |
978 | ||
979 | list_for_each(qe, &port->rport_q) { | |
980 | rport = (struct bfa_fcs_rport_s *) qe; | |
981 | if (wwn_is_equal(rport->pwwn, pwwn) && rport->pid == pid) | |
982 | return rport; | |
983 | } | |
984 | ||
985 | bfa_trc(port->fcs, pwwn); | |
986 | return NULL; | |
987 | } | |
988 | ||
5fbe25c7 | 989 | /* |
7725ccfd JH |
990 | * Called by rport module when new rports are discovered. |
991 | */ | |
992 | void | |
a36c61f9 KG |
993 | bfa_fcs_lport_add_rport( |
994 | struct bfa_fcs_lport_s *port, | |
995 | struct bfa_fcs_rport_s *rport) | |
7725ccfd JH |
996 | { |
997 | list_add_tail(&rport->qe, &port->rport_q); | |
998 | port->num_rports++; | |
999 | } | |
1000 | ||
5fbe25c7 | 1001 | /* |
7725ccfd JH |
1002 | * Called by rport module to when rports are deleted. |
1003 | */ | |
1004 | void | |
a36c61f9 KG |
1005 | bfa_fcs_lport_del_rport( |
1006 | struct bfa_fcs_lport_s *port, | |
1007 | struct bfa_fcs_rport_s *rport) | |
7725ccfd | 1008 | { |
d4b671c5 | 1009 | WARN_ON(!bfa_q_is_on_q(&port->rport_q, rport)); |
7725ccfd JH |
1010 | list_del(&rport->qe); |
1011 | port->num_rports--; | |
1012 | ||
1013 | bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT); | |
1014 | } | |
1015 | ||
5fbe25c7 | 1016 | /* |
7725ccfd JH |
1017 | * Called by fabric for base port when fabric login is complete. |
1018 | * Called by vport for virtual ports when FDISC is complete. | |
1019 | */ | |
1020 | void | |
a36c61f9 | 1021 | bfa_fcs_lport_online(struct bfa_fcs_lport_s *port) |
7725ccfd JH |
1022 | { |
1023 | bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE); | |
1024 | } | |
1025 | ||
5fbe25c7 | 1026 | /* |
7725ccfd JH |
1027 | * Called by fabric for base port when fabric goes offline. |
1028 | * Called by vport for virtual ports when virtual port becomes offline. | |
1029 | */ | |
1030 | void | |
a36c61f9 | 1031 | bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port) |
7725ccfd JH |
1032 | { |
1033 | bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE); | |
1034 | } | |
1035 | ||
881c1b3c KG |
1036 | /* |
1037 | * Called by fabric for base port and by vport for virtual ports | |
1038 | * when target mode driver is unloaded. | |
1039 | */ | |
1040 | void | |
1041 | bfa_fcs_lport_stop(struct bfa_fcs_lport_s *port) | |
1042 | { | |
1043 | bfa_sm_send_event(port, BFA_FCS_PORT_SM_STOP); | |
1044 | } | |
1045 | ||
5fbe25c7 | 1046 | /* |
7725ccfd JH |
1047 | * Called by fabric to delete base lport and associated resources. |
1048 | * | |
1049 | * Called by vport to delete lport and associated resources. Should call | |
1050 | * bfa_fcs_vport_delete_comp() for vports on completion. | |
1051 | */ | |
1052 | void | |
a36c61f9 | 1053 | bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port) |
7725ccfd JH |
1054 | { |
1055 | bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE); | |
1056 | } | |
1057 | ||
5fbe25c7 | 1058 | /* |
7725ccfd JH |
1059 | * Return TRUE if port is online, else return FALSE |
1060 | */ | |
1061 | bfa_boolean_t | |
a36c61f9 | 1062 | bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port) |
7725ccfd | 1063 | { |
a36c61f9 | 1064 | return bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online); |
7725ccfd JH |
1065 | } |
1066 | ||
5fbe25c7 | 1067 | /* |
a36c61f9 | 1068 | * Attach time initialization of logical ports. |
7725ccfd JH |
1069 | */ |
1070 | void | |
a36c61f9 KG |
1071 | bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs, |
1072 | u16 vf_id, struct bfa_fcs_vport_s *vport) | |
7725ccfd JH |
1073 | { |
1074 | lport->fcs = fcs; | |
1075 | lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id); | |
7725ccfd | 1076 | lport->vport = vport; |
3fd45980 KG |
1077 | lport->lp_tag = (vport) ? vport->lps->bfa_tag : |
1078 | lport->fabric->lps->bfa_tag; | |
7725ccfd JH |
1079 | |
1080 | INIT_LIST_HEAD(&lport->rport_q); | |
1081 | lport->num_rports = 0; | |
e6714324 KG |
1082 | } |
1083 | ||
5fbe25c7 | 1084 | /* |
e6714324 KG |
1085 | * Logical port initialization of base or virtual port. |
1086 | * Called by fabric for base port or by vport for virtual ports. | |
1087 | */ | |
7725ccfd | 1088 | |
e6714324 | 1089 | void |
a36c61f9 KG |
1090 | bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport, |
1091 | struct bfa_lport_cfg_s *port_cfg) | |
e6714324 KG |
1092 | { |
1093 | struct bfa_fcs_vport_s *vport = lport->vport; | |
a36c61f9 KG |
1094 | struct bfad_s *bfad = (struct bfad_s *)lport->fcs->bfad; |
1095 | char lpwwn_buf[BFA_STRING_32]; | |
e6714324 | 1096 | |
6a18b167 | 1097 | lport->port_cfg = *port_cfg; |
e6714324 | 1098 | |
a36c61f9 KG |
1099 | lport->bfad_port = bfa_fcb_lport_new(lport->fcs->bfad, lport, |
1100 | lport->port_cfg.roles, | |
1101 | lport->fabric->vf_drv, | |
1102 | vport ? vport->vport_drv : NULL); | |
e6714324 | 1103 | |
a36c61f9 | 1104 | wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport)); |
88166242 | 1105 | BFA_LOG(KERN_INFO, bfad, bfa_log_level, |
a36c61f9 KG |
1106 | "New logical port created: WWN = %s Role = %s\n", |
1107 | lpwwn_buf, "Initiator"); | |
7826f304 | 1108 | bfa_fcs_lport_aen_post(lport, BFA_LPORT_AEN_NEW); |
7725ccfd | 1109 | |
a36c61f9 | 1110 | bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit); |
7725ccfd JH |
1111 | bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE); |
1112 | } | |
1113 | ||
22a08538 VMG |
1114 | void |
1115 | bfa_fcs_lport_set_symname(struct bfa_fcs_lport_s *port, | |
1116 | char *symname) | |
1117 | { | |
1118 | strcpy(port->port_cfg.sym_name.symname, symname); | |
1119 | ||
1120 | if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online)) | |
1121 | bfa_fcs_lport_ns_util_send_rspn_id( | |
1122 | BFA_FCS_GET_NS_FROM_PORT(port), NULL); | |
1123 | } | |
1124 | ||
5fbe25c7 | 1125 | /* |
7725ccfd JH |
1126 | * fcs_lport_api |
1127 | */ | |
1128 | ||
1129 | void | |
a36c61f9 KG |
1130 | bfa_fcs_lport_get_attr( |
1131 | struct bfa_fcs_lport_s *port, | |
1132 | struct bfa_lport_attr_s *port_attr) | |
7725ccfd | 1133 | { |
a36c61f9 | 1134 | if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online)) |
7725ccfd JH |
1135 | port_attr->pid = port->pid; |
1136 | else | |
1137 | port_attr->pid = 0; | |
1138 | ||
1139 | port_attr->port_cfg = port->port_cfg; | |
1140 | ||
1141 | if (port->fabric) { | |
f7f73812 | 1142 | port_attr->port_type = port->fabric->oper_type; |
da99dcc9 MZ |
1143 | port_attr->loopback = bfa_sm_cmp_state(port->fabric, |
1144 | bfa_fcs_fabric_sm_loopback); | |
f926a05f | 1145 | port_attr->authfail = |
f7f73812 MZ |
1146 | bfa_sm_cmp_state(port->fabric, |
1147 | bfa_fcs_fabric_sm_auth_failed); | |
a36c61f9 | 1148 | port_attr->fabric_name = bfa_fcs_lport_get_fabric_name(port); |
7725ccfd | 1149 | memcpy(port_attr->fabric_ip_addr, |
a36c61f9 KG |
1150 | bfa_fcs_lport_get_fabric_ipaddr(port), |
1151 | BFA_FCS_FABRIC_IPADDR_SZ); | |
7725ccfd | 1152 | |
86e32dab | 1153 | if (port->vport != NULL) { |
a36c61f9 | 1154 | port_attr->port_type = BFA_PORT_TYPE_VPORT; |
86e32dab | 1155 | port_attr->fpma_mac = |
f7f73812 | 1156 | port->vport->lps->lp_mac; |
a36c61f9 | 1157 | } else { |
86e32dab | 1158 | port_attr->fpma_mac = |
f7f73812 | 1159 | port->fabric->lps->lp_mac; |
a36c61f9 | 1160 | } |
7725ccfd | 1161 | } else { |
a36c61f9 KG |
1162 | port_attr->port_type = BFA_PORT_TYPE_UNKNOWN; |
1163 | port_attr->state = BFA_LPORT_UNINIT; | |
1164 | } | |
1165 | } | |
1166 | ||
5fbe25c7 | 1167 | /* |
a36c61f9 KG |
1168 | * bfa_fcs_lport_fab port fab functions |
1169 | */ | |
1170 | ||
5fbe25c7 | 1171 | /* |
a36c61f9 KG |
1172 | * Called by port to initialize fabric services of the base port. |
1173 | */ | |
1174 | static void | |
1175 | bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port) | |
1176 | { | |
1177 | bfa_fcs_lport_ns_init(port); | |
1178 | bfa_fcs_lport_scn_init(port); | |
1179 | bfa_fcs_lport_ms_init(port); | |
1180 | } | |
1181 | ||
5fbe25c7 | 1182 | /* |
a36c61f9 KG |
1183 | * Called by port to notify transition to online state. |
1184 | */ | |
1185 | static void | |
1186 | bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port) | |
1187 | { | |
1188 | bfa_fcs_lport_ns_online(port); | |
bc0e2c2a | 1189 | bfa_fcs_lport_fab_scn_online(port); |
a36c61f9 KG |
1190 | } |
1191 | ||
5fbe25c7 | 1192 | /* |
a36c61f9 KG |
1193 | * Called by port to notify transition to offline state. |
1194 | */ | |
1195 | static void | |
1196 | bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port) | |
1197 | { | |
1198 | bfa_fcs_lport_ns_offline(port); | |
1199 | bfa_fcs_lport_scn_offline(port); | |
1200 | bfa_fcs_lport_ms_offline(port); | |
1201 | } | |
1202 | ||
5fbe25c7 | 1203 | /* |
a36c61f9 KG |
1204 | * bfa_fcs_lport_n2n functions |
1205 | */ | |
1206 | ||
5fbe25c7 | 1207 | /* |
a36c61f9 KG |
1208 | * Called by fcs/port to initialize N2N topology. |
1209 | */ | |
1210 | static void | |
1211 | bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port) | |
1212 | { | |
1213 | } | |
1214 | ||
5fbe25c7 | 1215 | /* |
a36c61f9 KG |
1216 | * Called by fcs/port to notify transition to online state. |
1217 | */ | |
1218 | static void | |
1219 | bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port) | |
1220 | { | |
1221 | struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n; | |
1222 | struct bfa_lport_cfg_s *pcfg = &port->port_cfg; | |
1223 | struct bfa_fcs_rport_s *rport; | |
1224 | ||
1225 | bfa_trc(port->fcs, pcfg->pwwn); | |
1226 | ||
1227 | /* | |
1228 | * If our PWWN is > than that of the r-port, we have to initiate PLOGI | |
1229 | * and assign an Address. if not, we need to wait for its PLOGI. | |
1230 | * | |
1231 | * If our PWWN is < than that of the remote port, it will send a PLOGI | |
1232 | * with the PIDs assigned. The rport state machine take care of this | |
1233 | * incoming PLOGI. | |
1234 | */ | |
1235 | if (memcmp | |
1236 | ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn, | |
1237 | sizeof(wwn_t)) > 0) { | |
1238 | port->pid = N2N_LOCAL_PID; | |
b704495c | 1239 | bfa_lps_set_n2n_pid(port->fabric->lps, N2N_LOCAL_PID); |
5fbe25c7 | 1240 | /* |
a36c61f9 KG |
1241 | * First, check if we know the device by pwwn. |
1242 | */ | |
1243 | rport = bfa_fcs_lport_get_rport_by_pwwn(port, | |
1244 | n2n_port->rem_port_wwn); | |
1245 | if (rport) { | |
1246 | bfa_trc(port->fcs, rport->pid); | |
1247 | bfa_trc(port->fcs, rport->pwwn); | |
1248 | rport->pid = N2N_REMOTE_PID; | |
f7f73812 | 1249 | bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND); |
a36c61f9 KG |
1250 | return; |
1251 | } | |
1252 | ||
1253 | /* | |
1254 | * In n2n there can be only one rport. Delete the old one | |
1255 | * whose pid should be zero, because it is offline. | |
1256 | */ | |
1257 | if (port->num_rports > 0) { | |
1258 | rport = bfa_fcs_lport_get_rport_by_pid(port, 0); | |
d4b671c5 | 1259 | WARN_ON(rport == NULL); |
a36c61f9 KG |
1260 | if (rport) { |
1261 | bfa_trc(port->fcs, rport->pwwn); | |
f7f73812 | 1262 | bfa_sm_send_event(rport, RPSM_EVENT_DELETE); |
a36c61f9 KG |
1263 | } |
1264 | } | |
1265 | bfa_fcs_rport_create(port, N2N_REMOTE_PID); | |
1266 | } | |
1267 | } | |
1268 | ||
5fbe25c7 | 1269 | /* |
a36c61f9 KG |
1270 | * Called by fcs/port to notify transition to offline state. |
1271 | */ | |
1272 | static void | |
1273 | bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port) | |
1274 | { | |
1275 | struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n; | |
1276 | ||
1277 | bfa_trc(port->fcs, port->pid); | |
1278 | port->pid = 0; | |
1279 | n2n_port->rem_port_wwn = 0; | |
1280 | n2n_port->reply_oxid = 0; | |
1281 | } | |
1282 | ||
bc0e2c2a KG |
1283 | void |
1284 | bfa_fcport_get_loop_attr(struct bfa_fcs_lport_s *port) | |
1285 | { | |
1286 | int i = 0, j = 0, bit = 0, alpa_bit = 0; | |
1287 | u8 k = 0; | |
1288 | struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(port->fcs->bfa); | |
1289 | ||
1290 | port->port_topo.ploop.alpabm_valid = fcport->alpabm_valid; | |
1291 | port->pid = fcport->myalpa; | |
1292 | port->pid = bfa_hton3b(port->pid); | |
1293 | ||
1294 | for (i = 0; i < (FC_ALPA_MAX / 8); i++) { | |
1295 | for (j = 0, alpa_bit = 0; j < 8; j++, alpa_bit++) { | |
1296 | bfa_trc(port->fcs->bfa, fcport->alpabm.alpa_bm[i]); | |
1297 | bit = (fcport->alpabm.alpa_bm[i] & (1 << (7 - j))); | |
1298 | if (bit) { | |
1299 | port->port_topo.ploop.alpa_pos_map[k] = | |
1300 | loop_alpa_map[(i * 8) + alpa_bit]; | |
1301 | k++; | |
1302 | bfa_trc(port->fcs->bfa, k); | |
1303 | bfa_trc(port->fcs->bfa, | |
1304 | port->port_topo.ploop.alpa_pos_map[k]); | |
1305 | } | |
1306 | } | |
1307 | } | |
1308 | port->port_topo.ploop.num_alpa = k; | |
1309 | } | |
1310 | ||
1311 | /* | |
1312 | * Called by fcs/port to initialize Loop topology. | |
1313 | */ | |
1314 | static void | |
1315 | bfa_fcs_lport_loop_init(struct bfa_fcs_lport_s *port) | |
1316 | { | |
1317 | } | |
1318 | ||
1319 | /* | |
1320 | * Called by fcs/port to notify transition to online state. | |
1321 | */ | |
1322 | static void | |
1323 | bfa_fcs_lport_loop_online(struct bfa_fcs_lport_s *port) | |
1324 | { | |
1325 | u8 num_alpa = 0, alpabm_valid = 0; | |
1326 | struct bfa_fcs_rport_s *rport; | |
1327 | u8 *alpa_map = NULL; | |
1328 | int i = 0; | |
1329 | u32 pid; | |
1330 | ||
1331 | bfa_fcport_get_loop_attr(port); | |
1332 | ||
1333 | num_alpa = port->port_topo.ploop.num_alpa; | |
1334 | alpabm_valid = port->port_topo.ploop.alpabm_valid; | |
1335 | alpa_map = port->port_topo.ploop.alpa_pos_map; | |
1336 | ||
1337 | bfa_trc(port->fcs->bfa, port->pid); | |
1338 | bfa_trc(port->fcs->bfa, num_alpa); | |
1339 | if (alpabm_valid == 1) { | |
1340 | for (i = 0; i < num_alpa; i++) { | |
1341 | bfa_trc(port->fcs->bfa, alpa_map[i]); | |
1342 | if (alpa_map[i] != bfa_hton3b(port->pid)) { | |
1343 | pid = alpa_map[i]; | |
1344 | bfa_trc(port->fcs->bfa, pid); | |
1345 | rport = bfa_fcs_lport_get_rport_by_pid(port, | |
1346 | bfa_hton3b(pid)); | |
1347 | if (!rport) | |
1348 | rport = bfa_fcs_rport_create(port, | |
1349 | bfa_hton3b(pid)); | |
1350 | } | |
1351 | } | |
1352 | } else { | |
1353 | for (i = 0; i < MAX_ALPA_COUNT; i++) { | |
1354 | if (alpa_map[i] != port->pid) { | |
1355 | pid = loop_alpa_map[i]; | |
1356 | bfa_trc(port->fcs->bfa, pid); | |
1357 | rport = bfa_fcs_lport_get_rport_by_pid(port, | |
1358 | bfa_hton3b(pid)); | |
1359 | if (!rport) | |
1360 | rport = bfa_fcs_rport_create(port, | |
1361 | bfa_hton3b(pid)); | |
1362 | } | |
1363 | } | |
1364 | } | |
1365 | } | |
1366 | ||
1367 | /* | |
1368 | * Called by fcs/port to notify transition to offline state. | |
1369 | */ | |
1370 | static void | |
1371 | bfa_fcs_lport_loop_offline(struct bfa_fcs_lport_s *port) | |
1372 | { | |
1373 | } | |
1374 | ||
a36c61f9 KG |
1375 | #define BFA_FCS_FDMI_CMD_MAX_RETRIES 2 |
1376 | ||
1377 | /* | |
1378 | * forward declarations | |
1379 | */ | |
1380 | static void bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, | |
1381 | struct bfa_fcxp_s *fcxp_alloced); | |
1382 | static void bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, | |
1383 | struct bfa_fcxp_s *fcxp_alloced); | |
1384 | static void bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, | |
1385 | struct bfa_fcxp_s *fcxp_alloced); | |
1386 | static void bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, | |
1387 | struct bfa_fcxp_s *fcxp, | |
1388 | void *cbarg, | |
1389 | bfa_status_t req_status, | |
1390 | u32 rsp_len, | |
1391 | u32 resid_len, | |
1392 | struct fchs_s *rsp_fchs); | |
1393 | static void bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, | |
1394 | struct bfa_fcxp_s *fcxp, | |
1395 | void *cbarg, | |
1396 | bfa_status_t req_status, | |
1397 | u32 rsp_len, | |
1398 | u32 resid_len, | |
1399 | struct fchs_s *rsp_fchs); | |
1400 | static void bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, | |
1401 | struct bfa_fcxp_s *fcxp, | |
1402 | void *cbarg, | |
1403 | bfa_status_t req_status, | |
1404 | u32 rsp_len, | |
1405 | u32 resid_len, | |
1406 | struct fchs_s *rsp_fchs); | |
1407 | static void bfa_fcs_lport_fdmi_timeout(void *arg); | |
1408 | static u16 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1409 | u8 *pyld); | |
1410 | static u16 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1411 | u8 *pyld); | |
1412 | static u16 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1413 | u8 *pyld); | |
1414 | static u16 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s * | |
1415 | fdmi, u8 *pyld); | |
1416 | static void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1417 | struct bfa_fcs_fdmi_hba_attr_s *hba_attr); | |
1418 | static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1419 | struct bfa_fcs_fdmi_port_attr_s *port_attr); | |
d7be54cc KG |
1420 | u32 bfa_fcs_fdmi_convert_speed(enum bfa_port_speed pport_speed); |
1421 | ||
5fbe25c7 | 1422 | /* |
a36c61f9 KG |
1423 | * fcs_fdmi_sm FCS FDMI state machine |
1424 | */ | |
1425 | ||
5fbe25c7 | 1426 | /* |
a36c61f9 KG |
1427 | * FDMI State Machine events |
1428 | */ | |
1429 | enum port_fdmi_event { | |
1430 | FDMISM_EVENT_PORT_ONLINE = 1, | |
1431 | FDMISM_EVENT_PORT_OFFLINE = 2, | |
1432 | FDMISM_EVENT_RSP_OK = 4, | |
1433 | FDMISM_EVENT_RSP_ERROR = 5, | |
1434 | FDMISM_EVENT_TIMEOUT = 6, | |
1435 | FDMISM_EVENT_RHBA_SENT = 7, | |
1436 | FDMISM_EVENT_RPRT_SENT = 8, | |
1437 | FDMISM_EVENT_RPA_SENT = 9, | |
1438 | }; | |
1439 | ||
1440 | static void bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1441 | enum port_fdmi_event event); | |
1442 | static void bfa_fcs_lport_fdmi_sm_sending_rhba( | |
1443 | struct bfa_fcs_lport_fdmi_s *fdmi, | |
1444 | enum port_fdmi_event event); | |
1445 | static void bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1446 | enum port_fdmi_event event); | |
1447 | static void bfa_fcs_lport_fdmi_sm_rhba_retry( | |
1448 | struct bfa_fcs_lport_fdmi_s *fdmi, | |
1449 | enum port_fdmi_event event); | |
1450 | static void bfa_fcs_lport_fdmi_sm_sending_rprt( | |
1451 | struct bfa_fcs_lport_fdmi_s *fdmi, | |
1452 | enum port_fdmi_event event); | |
1453 | static void bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1454 | enum port_fdmi_event event); | |
1455 | static void bfa_fcs_lport_fdmi_sm_rprt_retry( | |
1456 | struct bfa_fcs_lport_fdmi_s *fdmi, | |
1457 | enum port_fdmi_event event); | |
1458 | static void bfa_fcs_lport_fdmi_sm_sending_rpa( | |
1459 | struct bfa_fcs_lport_fdmi_s *fdmi, | |
1460 | enum port_fdmi_event event); | |
1461 | static void bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1462 | enum port_fdmi_event event); | |
1463 | static void bfa_fcs_lport_fdmi_sm_rpa_retry( | |
1464 | struct bfa_fcs_lport_fdmi_s *fdmi, | |
1465 | enum port_fdmi_event event); | |
1466 | static void bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1467 | enum port_fdmi_event event); | |
1468 | static void bfa_fcs_lport_fdmi_sm_disabled( | |
1469 | struct bfa_fcs_lport_fdmi_s *fdmi, | |
1470 | enum port_fdmi_event event); | |
5fbe25c7 | 1471 | /* |
a36c61f9 KG |
1472 | * Start in offline state - awaiting MS to send start. |
1473 | */ | |
1474 | static void | |
1475 | bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1476 | enum port_fdmi_event event) | |
1477 | { | |
1478 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
1479 | ||
1480 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
1481 | bfa_trc(port->fcs, event); | |
1482 | ||
1483 | fdmi->retry_cnt = 0; | |
1484 | ||
1485 | switch (event) { | |
1486 | case FDMISM_EVENT_PORT_ONLINE: | |
1487 | if (port->vport) { | |
1488 | /* | |
1489 | * For Vports, register a new port. | |
1490 | */ | |
1491 | bfa_sm_set_state(fdmi, | |
1492 | bfa_fcs_lport_fdmi_sm_sending_rprt); | |
1493 | bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL); | |
1494 | } else { | |
1495 | /* | |
1496 | * For a base port, we should first register the HBA | |
25985edc | 1497 | * attribute. The HBA attribute also contains the base |
a36c61f9 KG |
1498 | * port registration. |
1499 | */ | |
1500 | bfa_sm_set_state(fdmi, | |
1501 | bfa_fcs_lport_fdmi_sm_sending_rhba); | |
1502 | bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL); | |
1503 | } | |
1504 | break; | |
1505 | ||
1506 | case FDMISM_EVENT_PORT_OFFLINE: | |
1507 | break; | |
1508 | ||
1509 | default: | |
1510 | bfa_sm_fault(port->fcs, event); | |
1511 | } | |
1512 | } | |
1513 | ||
1514 | static void | |
1515 | bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1516 | enum port_fdmi_event event) | |
1517 | { | |
1518 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
1519 | ||
1520 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
1521 | bfa_trc(port->fcs, event); | |
1522 | ||
1523 | switch (event) { | |
1524 | case FDMISM_EVENT_RHBA_SENT: | |
1525 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rhba); | |
1526 | break; | |
1527 | ||
1528 | case FDMISM_EVENT_PORT_OFFLINE: | |
1529 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); | |
1530 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port), | |
1531 | &fdmi->fcxp_wqe); | |
1532 | break; | |
1533 | ||
1534 | default: | |
1535 | bfa_sm_fault(port->fcs, event); | |
1536 | } | |
1537 | } | |
1538 | ||
1539 | static void | |
1540 | bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1541 | enum port_fdmi_event event) | |
1542 | { | |
1543 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
1544 | ||
1545 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
1546 | bfa_trc(port->fcs, event); | |
1547 | ||
1548 | switch (event) { | |
1549 | case FDMISM_EVENT_RSP_ERROR: | |
1550 | /* | |
1551 | * if max retries have not been reached, start timer for a | |
1552 | * delayed retry | |
1553 | */ | |
1554 | if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) { | |
1555 | bfa_sm_set_state(fdmi, | |
1556 | bfa_fcs_lport_fdmi_sm_rhba_retry); | |
1557 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port), | |
1558 | &fdmi->timer, | |
1559 | bfa_fcs_lport_fdmi_timeout, fdmi, | |
1560 | BFA_FCS_RETRY_TIMEOUT); | |
1561 | } else { | |
1562 | /* | |
1563 | * set state to offline | |
1564 | */ | |
1565 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); | |
1566 | } | |
1567 | break; | |
1568 | ||
1569 | case FDMISM_EVENT_RSP_OK: | |
1570 | /* | |
1571 | * Initiate Register Port Attributes | |
1572 | */ | |
1573 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa); | |
1574 | fdmi->retry_cnt = 0; | |
1575 | bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL); | |
1576 | break; | |
1577 | ||
1578 | case FDMISM_EVENT_PORT_OFFLINE: | |
1579 | bfa_fcxp_discard(fdmi->fcxp); | |
1580 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); | |
1581 | break; | |
1582 | ||
1583 | default: | |
1584 | bfa_sm_fault(port->fcs, event); | |
1585 | } | |
1586 | } | |
1587 | ||
1588 | static void | |
1589 | bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1590 | enum port_fdmi_event event) | |
1591 | { | |
1592 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
1593 | ||
1594 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
1595 | bfa_trc(port->fcs, event); | |
1596 | ||
1597 | switch (event) { | |
1598 | case FDMISM_EVENT_TIMEOUT: | |
1599 | /* | |
1600 | * Retry Timer Expired. Re-send | |
1601 | */ | |
1602 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rhba); | |
1603 | bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL); | |
1604 | break; | |
1605 | ||
1606 | case FDMISM_EVENT_PORT_OFFLINE: | |
1607 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); | |
1608 | bfa_timer_stop(&fdmi->timer); | |
1609 | break; | |
1610 | ||
1611 | default: | |
1612 | bfa_sm_fault(port->fcs, event); | |
1613 | } | |
1614 | } | |
1615 | ||
1616 | /* | |
1617 | * RPRT : Register Port | |
1618 | */ | |
1619 | static void | |
1620 | bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1621 | enum port_fdmi_event event) | |
1622 | { | |
1623 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
1624 | ||
1625 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
1626 | bfa_trc(port->fcs, event); | |
1627 | ||
1628 | switch (event) { | |
1629 | case FDMISM_EVENT_RPRT_SENT: | |
1630 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rprt); | |
1631 | break; | |
1632 | ||
1633 | case FDMISM_EVENT_PORT_OFFLINE: | |
1634 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); | |
1635 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port), | |
1636 | &fdmi->fcxp_wqe); | |
1637 | break; | |
1638 | ||
1639 | default: | |
1640 | bfa_sm_fault(port->fcs, event); | |
7725ccfd | 1641 | } |
a36c61f9 KG |
1642 | } |
1643 | ||
1644 | static void | |
1645 | bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1646 | enum port_fdmi_event event) | |
1647 | { | |
1648 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
1649 | ||
1650 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
1651 | bfa_trc(port->fcs, event); | |
1652 | ||
1653 | switch (event) { | |
1654 | case FDMISM_EVENT_RSP_ERROR: | |
1655 | /* | |
1656 | * if max retries have not been reached, start timer for a | |
1657 | * delayed retry | |
1658 | */ | |
1659 | if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) { | |
1660 | bfa_sm_set_state(fdmi, | |
1661 | bfa_fcs_lport_fdmi_sm_rprt_retry); | |
1662 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port), | |
1663 | &fdmi->timer, | |
1664 | bfa_fcs_lport_fdmi_timeout, fdmi, | |
1665 | BFA_FCS_RETRY_TIMEOUT); | |
7725ccfd | 1666 | |
a36c61f9 KG |
1667 | } else { |
1668 | /* | |
1669 | * set state to offline | |
1670 | */ | |
1671 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); | |
1672 | fdmi->retry_cnt = 0; | |
1673 | } | |
1674 | break; | |
1675 | ||
1676 | case FDMISM_EVENT_RSP_OK: | |
1677 | fdmi->retry_cnt = 0; | |
1678 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online); | |
1679 | break; | |
1680 | ||
1681 | case FDMISM_EVENT_PORT_OFFLINE: | |
1682 | bfa_fcxp_discard(fdmi->fcxp); | |
1683 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); | |
1684 | break; | |
1685 | ||
1686 | default: | |
1687 | bfa_sm_fault(port->fcs, event); | |
1688 | } | |
7725ccfd JH |
1689 | } |
1690 | ||
a36c61f9 KG |
1691 | static void |
1692 | bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1693 | enum port_fdmi_event event) | |
1694 | { | |
1695 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
7725ccfd | 1696 | |
a36c61f9 KG |
1697 | bfa_trc(port->fcs, port->port_cfg.pwwn); |
1698 | bfa_trc(port->fcs, event); | |
1699 | ||
1700 | switch (event) { | |
1701 | case FDMISM_EVENT_TIMEOUT: | |
1702 | /* | |
1703 | * Retry Timer Expired. Re-send | |
1704 | */ | |
1705 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rprt); | |
1706 | bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL); | |
1707 | break; | |
1708 | ||
1709 | case FDMISM_EVENT_PORT_OFFLINE: | |
1710 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); | |
1711 | bfa_timer_stop(&fdmi->timer); | |
1712 | break; | |
1713 | ||
1714 | default: | |
1715 | bfa_sm_fault(port->fcs, event); | |
1716 | } | |
1717 | } | |
1718 | ||
1719 | /* | |
1720 | * Register Port Attributes | |
1721 | */ | |
1722 | static void | |
1723 | bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1724 | enum port_fdmi_event event) | |
1725 | { | |
1726 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
1727 | ||
1728 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
1729 | bfa_trc(port->fcs, event); | |
1730 | ||
1731 | switch (event) { | |
1732 | case FDMISM_EVENT_RPA_SENT: | |
1733 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa); | |
1734 | break; | |
1735 | ||
1736 | case FDMISM_EVENT_PORT_OFFLINE: | |
1737 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); | |
1738 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port), | |
1739 | &fdmi->fcxp_wqe); | |
1740 | break; | |
1741 | ||
1742 | default: | |
1743 | bfa_sm_fault(port->fcs, event); | |
1744 | } | |
1745 | } | |
1746 | ||
1747 | static void | |
1748 | bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1749 | enum port_fdmi_event event) | |
1750 | { | |
1751 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
1752 | ||
1753 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
1754 | bfa_trc(port->fcs, event); | |
1755 | ||
1756 | switch (event) { | |
1757 | case FDMISM_EVENT_RSP_ERROR: | |
1758 | /* | |
1759 | * if max retries have not been reached, start timer for a | |
1760 | * delayed retry | |
1761 | */ | |
1762 | if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) { | |
1763 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa_retry); | |
1764 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port), | |
1765 | &fdmi->timer, | |
1766 | bfa_fcs_lport_fdmi_timeout, fdmi, | |
1767 | BFA_FCS_RETRY_TIMEOUT); | |
1768 | } else { | |
1769 | /* | |
1770 | * set state to offline | |
1771 | */ | |
1772 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); | |
1773 | fdmi->retry_cnt = 0; | |
1774 | } | |
1775 | break; | |
1776 | ||
1777 | case FDMISM_EVENT_RSP_OK: | |
1778 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online); | |
1779 | fdmi->retry_cnt = 0; | |
1780 | break; | |
1781 | ||
1782 | case FDMISM_EVENT_PORT_OFFLINE: | |
1783 | bfa_fcxp_discard(fdmi->fcxp); | |
1784 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); | |
1785 | break; | |
1786 | ||
1787 | default: | |
1788 | bfa_sm_fault(port->fcs, event); | |
1789 | } | |
1790 | } | |
1791 | ||
1792 | static void | |
1793 | bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1794 | enum port_fdmi_event event) | |
1795 | { | |
1796 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
1797 | ||
1798 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
1799 | bfa_trc(port->fcs, event); | |
1800 | ||
1801 | switch (event) { | |
1802 | case FDMISM_EVENT_TIMEOUT: | |
1803 | /* | |
1804 | * Retry Timer Expired. Re-send | |
1805 | */ | |
1806 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa); | |
1807 | bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL); | |
1808 | break; | |
1809 | ||
1810 | case FDMISM_EVENT_PORT_OFFLINE: | |
1811 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); | |
1812 | bfa_timer_stop(&fdmi->timer); | |
1813 | break; | |
1814 | ||
1815 | default: | |
1816 | bfa_sm_fault(port->fcs, event); | |
1817 | } | |
1818 | } | |
1819 | ||
1820 | static void | |
1821 | bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1822 | enum port_fdmi_event event) | |
1823 | { | |
1824 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
1825 | ||
1826 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
1827 | bfa_trc(port->fcs, event); | |
1828 | ||
1829 | switch (event) { | |
1830 | case FDMISM_EVENT_PORT_OFFLINE: | |
1831 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); | |
1832 | break; | |
1833 | ||
1834 | default: | |
1835 | bfa_sm_fault(port->fcs, event); | |
1836 | } | |
1837 | } | |
5fbe25c7 | 1838 | /* |
a36c61f9 KG |
1839 | * FDMI is disabled state. |
1840 | */ | |
1841 | static void | |
1842 | bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s *fdmi, | |
1843 | enum port_fdmi_event event) | |
1844 | { | |
1845 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
1846 | ||
1847 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
1848 | bfa_trc(port->fcs, event); | |
1849 | ||
1850 | /* No op State. It can only be enabled at Driver Init. */ | |
1851 | } | |
1852 | ||
5fbe25c7 | 1853 | /* |
a36c61f9 KG |
1854 | * RHBA : Register HBA Attributes. |
1855 | */ | |
1856 | static void | |
1857 | bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced) | |
1858 | { | |
1859 | struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg; | |
1860 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
1861 | struct fchs_s fchs; | |
1862 | int len, attr_len; | |
1863 | struct bfa_fcxp_s *fcxp; | |
1864 | u8 *pyld; | |
1865 | ||
1866 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
1867 | ||
c3f1b123 KG |
1868 | fcxp = fcxp_alloced ? fcxp_alloced : |
1869 | bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); | |
a36c61f9 KG |
1870 | if (!fcxp) { |
1871 | bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe, | |
c3f1b123 | 1872 | bfa_fcs_lport_fdmi_send_rhba, fdmi, BFA_TRUE); |
a36c61f9 KG |
1873 | return; |
1874 | } | |
1875 | fdmi->fcxp = fcxp; | |
1876 | ||
1877 | pyld = bfa_fcxp_get_reqbuf(fcxp); | |
6a18b167 | 1878 | memset(pyld, 0, FC_MAX_PDUSZ); |
a36c61f9 KG |
1879 | |
1880 | len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port), | |
1881 | FDMI_RHBA); | |
1882 | ||
1883 | attr_len = | |
1884 | bfa_fcs_lport_fdmi_build_rhba_pyld(fdmi, | |
1885 | (u8 *) ((struct ct_hdr_s *) pyld | |
1886 | + 1)); | |
1887 | ||
1888 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | |
1889 | FC_CLASS_3, (len + attr_len), &fchs, | |
1890 | bfa_fcs_lport_fdmi_rhba_response, (void *)fdmi, | |
1891 | FC_MAX_PDUSZ, FC_FCCT_TOV); | |
1892 | ||
1893 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT); | |
1894 | } | |
1895 | ||
1896 | static u16 | |
1897 | bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld) | |
1898 | { | |
1899 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
1900 | struct bfa_fcs_fdmi_hba_attr_s hba_attr; | |
1901 | struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr; | |
1902 | struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld; | |
1903 | struct fdmi_attr_s *attr; | |
1904 | u8 *curr_ptr; | |
1905 | u16 len, count; | |
50444a34 | 1906 | u16 templen; |
a36c61f9 KG |
1907 | |
1908 | /* | |
1909 | * get hba attributes | |
1910 | */ | |
1911 | bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr); | |
1912 | ||
1913 | rhba->hba_id = bfa_fcs_lport_get_pwwn(port); | |
ba816ea8 | 1914 | rhba->port_list.num_ports = cpu_to_be32(1); |
a36c61f9 KG |
1915 | rhba->port_list.port_entry = bfa_fcs_lport_get_pwwn(port); |
1916 | ||
1917 | len = sizeof(rhba->hba_id) + sizeof(rhba->port_list); | |
1918 | ||
1919 | count = 0; | |
1920 | len += sizeof(rhba->hba_attr_blk.attr_count); | |
1921 | ||
1922 | /* | |
1923 | * fill out the invididual entries of the HBA attrib Block | |
1924 | */ | |
1925 | curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr; | |
1926 | ||
1927 | /* | |
1928 | * Node Name | |
1929 | */ | |
1930 | attr = (struct fdmi_attr_s *) curr_ptr; | |
ba816ea8 | 1931 | attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODENAME); |
50444a34 M |
1932 | templen = sizeof(wwn_t); |
1933 | memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), templen); | |
1934 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
1935 | len += templen; | |
a36c61f9 | 1936 | count++; |
50444a34 M |
1937 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + |
1938 | sizeof(templen)); | |
a36c61f9 KG |
1939 | |
1940 | /* | |
1941 | * Manufacturer | |
1942 | */ | |
1943 | attr = (struct fdmi_attr_s *) curr_ptr; | |
ba816ea8 | 1944 | attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MANUFACTURER); |
50444a34 M |
1945 | templen = (u16) strlen(fcs_hba_attr->manufacturer); |
1946 | memcpy(attr->value, fcs_hba_attr->manufacturer, templen); | |
1947 | templen = fc_roundup(templen, sizeof(u32)); | |
1948 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
1949 | len += templen; | |
a36c61f9 | 1950 | count++; |
50444a34 M |
1951 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + |
1952 | sizeof(templen)); | |
a36c61f9 KG |
1953 | |
1954 | /* | |
1955 | * Serial Number | |
1956 | */ | |
1957 | attr = (struct fdmi_attr_s *) curr_ptr; | |
ba816ea8 | 1958 | attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_SERIALNUM); |
50444a34 M |
1959 | templen = (u16) strlen(fcs_hba_attr->serial_num); |
1960 | memcpy(attr->value, fcs_hba_attr->serial_num, templen); | |
1961 | templen = fc_roundup(templen, sizeof(u32)); | |
1962 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
1963 | len += templen; | |
a36c61f9 | 1964 | count++; |
50444a34 M |
1965 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + |
1966 | sizeof(templen)); | |
a36c61f9 KG |
1967 | |
1968 | /* | |
1969 | * Model | |
1970 | */ | |
1971 | attr = (struct fdmi_attr_s *) curr_ptr; | |
ba816ea8 | 1972 | attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL); |
50444a34 M |
1973 | templen = (u16) strlen(fcs_hba_attr->model); |
1974 | memcpy(attr->value, fcs_hba_attr->model, templen); | |
1975 | templen = fc_roundup(templen, sizeof(u32)); | |
1976 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
1977 | len += templen; | |
a36c61f9 | 1978 | count++; |
50444a34 M |
1979 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + |
1980 | sizeof(templen)); | |
a36c61f9 KG |
1981 | |
1982 | /* | |
1983 | * Model Desc | |
1984 | */ | |
1985 | attr = (struct fdmi_attr_s *) curr_ptr; | |
ba816ea8 | 1986 | attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL_DESC); |
50444a34 M |
1987 | templen = (u16) strlen(fcs_hba_attr->model_desc); |
1988 | memcpy(attr->value, fcs_hba_attr->model_desc, templen); | |
1989 | templen = fc_roundup(templen, sizeof(u32)); | |
1990 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
1991 | len += templen; | |
a36c61f9 | 1992 | count++; |
50444a34 M |
1993 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + |
1994 | sizeof(templen)); | |
a36c61f9 KG |
1995 | |
1996 | /* | |
1997 | * H/W Version | |
1998 | */ | |
1999 | if (fcs_hba_attr->hw_version[0] != '\0') { | |
2000 | attr = (struct fdmi_attr_s *) curr_ptr; | |
ba816ea8 | 2001 | attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_HW_VERSION); |
50444a34 M |
2002 | templen = (u16) strlen(fcs_hba_attr->hw_version); |
2003 | memcpy(attr->value, fcs_hba_attr->hw_version, templen); | |
2004 | templen = fc_roundup(templen, sizeof(u32)); | |
2005 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2006 | len += templen; | |
a36c61f9 | 2007 | count++; |
50444a34 M |
2008 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + |
2009 | sizeof(templen)); | |
a36c61f9 KG |
2010 | } |
2011 | ||
2012 | /* | |
2013 | * Driver Version | |
2014 | */ | |
2015 | attr = (struct fdmi_attr_s *) curr_ptr; | |
ba816ea8 | 2016 | attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_DRIVER_VERSION); |
50444a34 M |
2017 | templen = (u16) strlen(fcs_hba_attr->driver_version); |
2018 | memcpy(attr->value, fcs_hba_attr->driver_version, templen); | |
2019 | templen = fc_roundup(templen, sizeof(u32)); | |
2020 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
dd5aaf45 | 2021 | len += templen; |
a36c61f9 | 2022 | count++; |
50444a34 M |
2023 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + |
2024 | sizeof(templen)); | |
a36c61f9 KG |
2025 | |
2026 | /* | |
2027 | * Option Rom Version | |
2028 | */ | |
2029 | if (fcs_hba_attr->option_rom_ver[0] != '\0') { | |
2030 | attr = (struct fdmi_attr_s *) curr_ptr; | |
ba816ea8 | 2031 | attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_ROM_VERSION); |
50444a34 M |
2032 | templen = (u16) strlen(fcs_hba_attr->option_rom_ver); |
2033 | memcpy(attr->value, fcs_hba_attr->option_rom_ver, templen); | |
2034 | templen = fc_roundup(templen, sizeof(u32)); | |
2035 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2036 | len += templen; | |
a36c61f9 | 2037 | count++; |
50444a34 M |
2038 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + |
2039 | sizeof(templen)); | |
a36c61f9 KG |
2040 | } |
2041 | ||
a36c61f9 | 2042 | attr = (struct fdmi_attr_s *) curr_ptr; |
ba816ea8 | 2043 | attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION); |
b480a32e KG |
2044 | templen = (u16) strlen(fcs_hba_attr->fw_version); |
2045 | memcpy(attr->value, fcs_hba_attr->fw_version, templen); | |
50444a34 M |
2046 | templen = fc_roundup(templen, sizeof(u32)); |
2047 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2048 | len += templen; | |
a36c61f9 | 2049 | count++; |
50444a34 M |
2050 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + |
2051 | sizeof(templen)); | |
a36c61f9 KG |
2052 | |
2053 | /* | |
2054 | * OS Name | |
2055 | */ | |
2056 | if (fcs_hba_attr->os_name[0] != '\0') { | |
2057 | attr = (struct fdmi_attr_s *) curr_ptr; | |
ba816ea8 | 2058 | attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_OS_NAME); |
50444a34 M |
2059 | templen = (u16) strlen(fcs_hba_attr->os_name); |
2060 | memcpy(attr->value, fcs_hba_attr->os_name, templen); | |
2061 | templen = fc_roundup(templen, sizeof(u32)); | |
2062 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2063 | len += templen; | |
a36c61f9 | 2064 | count++; |
50444a34 M |
2065 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + |
2066 | sizeof(templen)); | |
a36c61f9 KG |
2067 | } |
2068 | ||
2069 | /* | |
2070 | * MAX_CT_PAYLOAD | |
2071 | */ | |
2072 | attr = (struct fdmi_attr_s *) curr_ptr; | |
ba816ea8 | 2073 | attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT); |
50444a34 M |
2074 | templen = sizeof(fcs_hba_attr->max_ct_pyld); |
2075 | memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen); | |
d7cbc304 VMG |
2076 | templen = fc_roundup(templen, sizeof(u32)); |
2077 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
50444a34 | 2078 | len += templen; |
a36c61f9 | 2079 | count++; |
50444a34 M |
2080 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + |
2081 | sizeof(templen)); | |
d7cbc304 VMG |
2082 | /* |
2083 | * Send extended attributes ( FOS 7.1 support ) | |
2084 | */ | |
2085 | if (fdmi->retry_cnt == 0) { | |
2086 | attr = (struct fdmi_attr_s *) curr_ptr; | |
2087 | attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODE_SYM_NAME); | |
2088 | templen = sizeof(fcs_hba_attr->node_sym_name); | |
2089 | memcpy(attr->value, &fcs_hba_attr->node_sym_name, templen); | |
2090 | templen = fc_roundup(templen, sizeof(u32)); | |
2091 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2092 | len += templen; | |
2093 | count++; | |
2094 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + | |
2095 | sizeof(templen)); | |
2096 | ||
2097 | attr = (struct fdmi_attr_s *) curr_ptr; | |
2098 | attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_VENDOR_ID); | |
2099 | templen = sizeof(fcs_hba_attr->vendor_info); | |
2100 | memcpy(attr->value, &fcs_hba_attr->vendor_info, templen); | |
2101 | templen = fc_roundup(templen, sizeof(u32)); | |
2102 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2103 | len += templen; | |
2104 | count++; | |
2105 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + | |
2106 | sizeof(templen)); | |
2107 | ||
2108 | attr = (struct fdmi_attr_s *) curr_ptr; | |
2109 | attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NUM_PORTS); | |
2110 | templen = sizeof(fcs_hba_attr->num_ports); | |
2111 | memcpy(attr->value, &fcs_hba_attr->num_ports, templen); | |
2112 | templen = fc_roundup(templen, sizeof(u32)); | |
2113 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2114 | len += templen; | |
2115 | count++; | |
2116 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + | |
2117 | sizeof(templen)); | |
2118 | ||
2119 | attr = (struct fdmi_attr_s *) curr_ptr; | |
2120 | attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FABRIC_NAME); | |
2121 | templen = sizeof(fcs_hba_attr->fabric_name); | |
2122 | memcpy(attr->value, &fcs_hba_attr->fabric_name, templen); | |
2123 | templen = fc_roundup(templen, sizeof(u32)); | |
2124 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2125 | len += templen; | |
2126 | count++; | |
2127 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + | |
2128 | sizeof(templen)); | |
2129 | ||
2130 | attr = (struct fdmi_attr_s *) curr_ptr; | |
2131 | attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_BIOS_VER); | |
2132 | templen = sizeof(fcs_hba_attr->bios_ver); | |
2133 | memcpy(attr->value, &fcs_hba_attr->bios_ver, templen); | |
2134 | templen = fc_roundup(attr->len, sizeof(u32)); | |
2135 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2136 | len += templen; | |
2137 | count++; | |
2138 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + | |
2139 | sizeof(templen)); | |
2140 | } | |
a36c61f9 KG |
2141 | |
2142 | /* | |
2143 | * Update size of payload | |
2144 | */ | |
5fbe25c7 | 2145 | len += ((sizeof(attr->type) + sizeof(attr->len)) * count); |
a36c61f9 | 2146 | |
ba816ea8 | 2147 | rhba->hba_attr_blk.attr_count = cpu_to_be32(count); |
a36c61f9 KG |
2148 | return len; |
2149 | } | |
2150 | ||
2151 | static void | |
2152 | bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | |
2153 | void *cbarg, bfa_status_t req_status, | |
2154 | u32 rsp_len, u32 resid_len, | |
2155 | struct fchs_s *rsp_fchs) | |
2156 | { | |
2157 | struct bfa_fcs_lport_fdmi_s *fdmi = | |
2158 | (struct bfa_fcs_lport_fdmi_s *) cbarg; | |
2159 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
2160 | struct ct_hdr_s *cthdr = NULL; | |
2161 | ||
2162 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
2163 | ||
2164 | /* | |
2165 | * Sanity Checks | |
2166 | */ | |
2167 | if (req_status != BFA_STATUS_OK) { | |
2168 | bfa_trc(port->fcs, req_status); | |
2169 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); | |
2170 | return; | |
2171 | } | |
2172 | ||
2173 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | |
ba816ea8 | 2174 | cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); |
a36c61f9 KG |
2175 | |
2176 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | |
2177 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK); | |
2178 | return; | |
2179 | } | |
2180 | ||
2181 | bfa_trc(port->fcs, cthdr->reason_code); | |
2182 | bfa_trc(port->fcs, cthdr->exp_code); | |
2183 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); | |
2184 | } | |
2185 | ||
5fbe25c7 | 2186 | /* |
a36c61f9 KG |
2187 | * RPRT : Register Port |
2188 | */ | |
2189 | static void | |
2190 | bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced) | |
2191 | { | |
2192 | struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg; | |
2193 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
2194 | struct fchs_s fchs; | |
2195 | u16 len, attr_len; | |
2196 | struct bfa_fcxp_s *fcxp; | |
2197 | u8 *pyld; | |
2198 | ||
2199 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
2200 | ||
c3f1b123 KG |
2201 | fcxp = fcxp_alloced ? fcxp_alloced : |
2202 | bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); | |
a36c61f9 KG |
2203 | if (!fcxp) { |
2204 | bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe, | |
c3f1b123 | 2205 | bfa_fcs_lport_fdmi_send_rprt, fdmi, BFA_TRUE); |
a36c61f9 KG |
2206 | return; |
2207 | } | |
2208 | fdmi->fcxp = fcxp; | |
2209 | ||
2210 | pyld = bfa_fcxp_get_reqbuf(fcxp); | |
6a18b167 | 2211 | memset(pyld, 0, FC_MAX_PDUSZ); |
a36c61f9 KG |
2212 | |
2213 | len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port), | |
2214 | FDMI_RPRT); | |
2215 | ||
2216 | attr_len = | |
2217 | bfa_fcs_lport_fdmi_build_rprt_pyld(fdmi, | |
2218 | (u8 *) ((struct ct_hdr_s *) pyld | |
2219 | + 1)); | |
2220 | ||
2221 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | |
2222 | FC_CLASS_3, len + attr_len, &fchs, | |
2223 | bfa_fcs_lport_fdmi_rprt_response, (void *)fdmi, | |
2224 | FC_MAX_PDUSZ, FC_FCCT_TOV); | |
2225 | ||
2226 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT); | |
2227 | } | |
2228 | ||
5fbe25c7 | 2229 | /* |
a36c61f9 KG |
2230 | * This routine builds Port Attribute Block that used in RPA, RPRT commands. |
2231 | */ | |
2232 | static u16 | |
2233 | bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi, | |
2234 | u8 *pyld) | |
2235 | { | |
2236 | struct bfa_fcs_fdmi_port_attr_s fcs_port_attr; | |
2237 | struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld; | |
2238 | struct fdmi_attr_s *attr; | |
2239 | u8 *curr_ptr; | |
2240 | u16 len; | |
2241 | u8 count = 0; | |
50444a34 | 2242 | u16 templen; |
a36c61f9 KG |
2243 | |
2244 | /* | |
2245 | * get port attributes | |
2246 | */ | |
2247 | bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr); | |
2248 | ||
2249 | len = sizeof(port_attrib->attr_count); | |
2250 | ||
2251 | /* | |
2252 | * fill out the invididual entries | |
2253 | */ | |
2254 | curr_ptr = (u8 *) &port_attrib->port_attr; | |
2255 | ||
2256 | /* | |
2257 | * FC4 Types | |
2258 | */ | |
2259 | attr = (struct fdmi_attr_s *) curr_ptr; | |
ba816ea8 | 2260 | attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FC4_TYPES); |
50444a34 M |
2261 | templen = sizeof(fcs_port_attr.supp_fc4_types); |
2262 | memcpy(attr->value, fcs_port_attr.supp_fc4_types, templen); | |
2263 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2264 | len += templen; | |
a36c61f9 KG |
2265 | ++count; |
2266 | attr->len = | |
50444a34 M |
2267 | cpu_to_be16(templen + sizeof(attr->type) + |
2268 | sizeof(templen)); | |
a36c61f9 KG |
2269 | |
2270 | /* | |
2271 | * Supported Speed | |
2272 | */ | |
2273 | attr = (struct fdmi_attr_s *) curr_ptr; | |
ba816ea8 | 2274 | attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_SPEED); |
50444a34 M |
2275 | templen = sizeof(fcs_port_attr.supp_speed); |
2276 | memcpy(attr->value, &fcs_port_attr.supp_speed, templen); | |
2277 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2278 | len += templen; | |
a36c61f9 KG |
2279 | ++count; |
2280 | attr->len = | |
50444a34 M |
2281 | cpu_to_be16(templen + sizeof(attr->type) + |
2282 | sizeof(templen)); | |
a36c61f9 KG |
2283 | |
2284 | /* | |
2285 | * current Port Speed | |
2286 | */ | |
2287 | attr = (struct fdmi_attr_s *) curr_ptr; | |
ba816ea8 | 2288 | attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SPEED); |
50444a34 M |
2289 | templen = sizeof(fcs_port_attr.curr_speed); |
2290 | memcpy(attr->value, &fcs_port_attr.curr_speed, templen); | |
2291 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2292 | len += templen; | |
a36c61f9 | 2293 | ++count; |
50444a34 M |
2294 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + |
2295 | sizeof(templen)); | |
a36c61f9 KG |
2296 | |
2297 | /* | |
2298 | * max frame size | |
2299 | */ | |
2300 | attr = (struct fdmi_attr_s *) curr_ptr; | |
ba816ea8 | 2301 | attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FRAME_SIZE); |
50444a34 M |
2302 | templen = sizeof(fcs_port_attr.max_frm_size); |
2303 | memcpy(attr->value, &fcs_port_attr.max_frm_size, templen); | |
2304 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2305 | len += templen; | |
a36c61f9 | 2306 | ++count; |
50444a34 M |
2307 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + |
2308 | sizeof(templen)); | |
a36c61f9 KG |
2309 | |
2310 | /* | |
2311 | * OS Device Name | |
2312 | */ | |
2313 | if (fcs_port_attr.os_device_name[0] != '\0') { | |
2314 | attr = (struct fdmi_attr_s *) curr_ptr; | |
ba816ea8 | 2315 | attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_DEV_NAME); |
50444a34 M |
2316 | templen = (u16) strlen(fcs_port_attr.os_device_name); |
2317 | memcpy(attr->value, fcs_port_attr.os_device_name, templen); | |
2318 | templen = fc_roundup(templen, sizeof(u32)); | |
2319 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2320 | len += templen; | |
a36c61f9 | 2321 | ++count; |
50444a34 M |
2322 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + |
2323 | sizeof(templen)); | |
a36c61f9 KG |
2324 | } |
2325 | /* | |
2326 | * Host Name | |
2327 | */ | |
2328 | if (fcs_port_attr.host_name[0] != '\0') { | |
2329 | attr = (struct fdmi_attr_s *) curr_ptr; | |
ba816ea8 | 2330 | attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_HOST_NAME); |
50444a34 M |
2331 | templen = (u16) strlen(fcs_port_attr.host_name); |
2332 | memcpy(attr->value, fcs_port_attr.host_name, templen); | |
2333 | templen = fc_roundup(templen, sizeof(u32)); | |
2334 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2335 | len += templen; | |
a36c61f9 | 2336 | ++count; |
50444a34 M |
2337 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + |
2338 | sizeof(templen)); | |
a36c61f9 KG |
2339 | } |
2340 | ||
d7cbc304 VMG |
2341 | if (fdmi->retry_cnt == 0) { |
2342 | attr = (struct fdmi_attr_s *) curr_ptr; | |
2343 | attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_NODE_NAME); | |
2344 | templen = sizeof(fcs_port_attr.node_name); | |
2345 | memcpy(attr->value, &fcs_port_attr.node_name, templen); | |
2346 | templen = fc_roundup(templen, sizeof(u32)); | |
2347 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2348 | len += templen; | |
2349 | ++count; | |
2350 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + | |
2351 | sizeof(templen)); | |
2352 | ||
2353 | attr = (struct fdmi_attr_s *) curr_ptr; | |
2354 | attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_NAME); | |
2355 | templen = sizeof(fcs_port_attr.port_name); | |
2356 | memcpy(attr->value, &fcs_port_attr.port_name, templen); | |
2357 | templen = fc_roundup(templen, sizeof(u32)); | |
2358 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + templen; | |
2359 | len += templen; | |
2360 | ++count; | |
2361 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + | |
2362 | sizeof(templen)); | |
2363 | ||
2364 | if (fcs_port_attr.port_sym_name.symname[0] != '\0') { | |
2365 | attr = (struct fdmi_attr_s *) curr_ptr; | |
2366 | attr->type = | |
2367 | cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SYM_NAME); | |
2368 | templen = sizeof(fcs_port_attr.port_sym_name); | |
2369 | memcpy(attr->value, | |
2370 | &fcs_port_attr.port_sym_name, templen); | |
2371 | templen = fc_roundup(templen, sizeof(u32)); | |
2372 | curr_ptr += sizeof(attr->type) + | |
2373 | sizeof(templen) + templen; | |
2374 | len += templen; | |
2375 | ++count; | |
2376 | attr->len = cpu_to_be16(templen + | |
2377 | sizeof(attr->type) + sizeof(templen)); | |
2378 | } | |
2379 | ||
2380 | attr = (struct fdmi_attr_s *) curr_ptr; | |
2381 | attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_TYPE); | |
2382 | templen = sizeof(fcs_port_attr.port_type); | |
2383 | memcpy(attr->value, &fcs_port_attr.port_type, templen); | |
2384 | templen = fc_roundup(templen, sizeof(u32)); | |
2385 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2386 | len += templen; | |
2387 | ++count; | |
2388 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + | |
2389 | sizeof(templen)); | |
2390 | ||
2391 | attr = (struct fdmi_attr_s *) curr_ptr; | |
2392 | attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_COS); | |
2393 | templen = sizeof(fcs_port_attr.scos); | |
2394 | memcpy(attr->value, &fcs_port_attr.scos, templen); | |
2395 | templen = fc_roundup(templen, sizeof(u32)); | |
2396 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2397 | len += templen; | |
2398 | ++count; | |
2399 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + | |
2400 | sizeof(templen)); | |
2401 | ||
2402 | attr = (struct fdmi_attr_s *) curr_ptr; | |
2403 | attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_FAB_NAME); | |
2404 | templen = sizeof(fcs_port_attr.port_fabric_name); | |
2405 | memcpy(attr->value, &fcs_port_attr.port_fabric_name, templen); | |
2406 | templen = fc_roundup(templen, sizeof(u32)); | |
2407 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2408 | len += templen; | |
2409 | ++count; | |
2410 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + | |
2411 | sizeof(templen)); | |
2412 | ||
2413 | attr = (struct fdmi_attr_s *) curr_ptr; | |
2414 | attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_FC4_TYPE); | |
2415 | templen = sizeof(fcs_port_attr.port_act_fc4_type); | |
2416 | memcpy(attr->value, fcs_port_attr.port_act_fc4_type, | |
2417 | templen); | |
2418 | templen = fc_roundup(templen, sizeof(u32)); | |
2419 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2420 | len += templen; | |
2421 | ++count; | |
2422 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + | |
2423 | sizeof(templen)); | |
2424 | ||
2425 | attr = (struct fdmi_attr_s *) curr_ptr; | |
2426 | attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_STATE); | |
2427 | templen = sizeof(fcs_port_attr.port_state); | |
2428 | memcpy(attr->value, &fcs_port_attr.port_state, templen); | |
2429 | templen = fc_roundup(templen, sizeof(u32)); | |
2430 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2431 | len += templen; | |
2432 | ++count; | |
2433 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + | |
2434 | sizeof(templen)); | |
2435 | ||
2436 | attr = (struct fdmi_attr_s *) curr_ptr; | |
2437 | attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_NUM_RPRT); | |
2438 | templen = sizeof(fcs_port_attr.num_ports); | |
2439 | memcpy(attr->value, &fcs_port_attr.num_ports, templen); | |
2440 | templen = fc_roundup(templen, sizeof(u32)); | |
2441 | curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; | |
2442 | len += templen; | |
2443 | ++count; | |
2444 | attr->len = cpu_to_be16(templen + sizeof(attr->type) + | |
2445 | sizeof(templen)); | |
2446 | } | |
2447 | ||
a36c61f9 KG |
2448 | /* |
2449 | * Update size of payload | |
2450 | */ | |
ba816ea8 | 2451 | port_attrib->attr_count = cpu_to_be32(count); |
5fbe25c7 | 2452 | len += ((sizeof(attr->type) + sizeof(attr->len)) * count); |
a36c61f9 KG |
2453 | return len; |
2454 | } | |
2455 | ||
2456 | static u16 | |
2457 | bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld) | |
2458 | { | |
2459 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
2460 | struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld; | |
2461 | u16 len; | |
2462 | ||
2463 | rprt->hba_id = bfa_fcs_lport_get_pwwn(bfa_fcs_get_base_port(port->fcs)); | |
2464 | rprt->port_name = bfa_fcs_lport_get_pwwn(port); | |
2465 | ||
2466 | len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi, | |
2467 | (u8 *) &rprt->port_attr_blk); | |
2468 | ||
2469 | len += sizeof(rprt->hba_id) + sizeof(rprt->port_name); | |
2470 | ||
2471 | return len; | |
2472 | } | |
2473 | ||
2474 | static void | |
2475 | bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | |
2476 | void *cbarg, bfa_status_t req_status, | |
2477 | u32 rsp_len, u32 resid_len, | |
2478 | struct fchs_s *rsp_fchs) | |
2479 | { | |
2480 | struct bfa_fcs_lport_fdmi_s *fdmi = | |
2481 | (struct bfa_fcs_lport_fdmi_s *) cbarg; | |
2482 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
2483 | struct ct_hdr_s *cthdr = NULL; | |
2484 | ||
2485 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
2486 | ||
2487 | /* | |
2488 | * Sanity Checks | |
2489 | */ | |
2490 | if (req_status != BFA_STATUS_OK) { | |
2491 | bfa_trc(port->fcs, req_status); | |
2492 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); | |
2493 | return; | |
2494 | } | |
2495 | ||
2496 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | |
ba816ea8 | 2497 | cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); |
a36c61f9 KG |
2498 | |
2499 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | |
2500 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK); | |
2501 | return; | |
2502 | } | |
2503 | ||
2504 | bfa_trc(port->fcs, cthdr->reason_code); | |
2505 | bfa_trc(port->fcs, cthdr->exp_code); | |
2506 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); | |
2507 | } | |
2508 | ||
5fbe25c7 | 2509 | /* |
a36c61f9 KG |
2510 | * RPA : Register Port Attributes. |
2511 | */ | |
2512 | static void | |
2513 | bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced) | |
2514 | { | |
2515 | struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg; | |
2516 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
2517 | struct fchs_s fchs; | |
2518 | u16 len, attr_len; | |
2519 | struct bfa_fcxp_s *fcxp; | |
2520 | u8 *pyld; | |
2521 | ||
2522 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
2523 | ||
c3f1b123 KG |
2524 | fcxp = fcxp_alloced ? fcxp_alloced : |
2525 | bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); | |
a36c61f9 KG |
2526 | if (!fcxp) { |
2527 | bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe, | |
c3f1b123 | 2528 | bfa_fcs_lport_fdmi_send_rpa, fdmi, BFA_TRUE); |
a36c61f9 KG |
2529 | return; |
2530 | } | |
2531 | fdmi->fcxp = fcxp; | |
2532 | ||
2533 | pyld = bfa_fcxp_get_reqbuf(fcxp); | |
6a18b167 | 2534 | memset(pyld, 0, FC_MAX_PDUSZ); |
a36c61f9 KG |
2535 | |
2536 | len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port), | |
2537 | FDMI_RPA); | |
2538 | ||
5fbe25c7 JH |
2539 | attr_len = bfa_fcs_lport_fdmi_build_rpa_pyld(fdmi, |
2540 | (u8 *) ((struct ct_hdr_s *) pyld + 1)); | |
a36c61f9 KG |
2541 | |
2542 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | |
2543 | FC_CLASS_3, len + attr_len, &fchs, | |
2544 | bfa_fcs_lport_fdmi_rpa_response, (void *)fdmi, | |
2545 | FC_MAX_PDUSZ, FC_FCCT_TOV); | |
2546 | ||
2547 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT); | |
2548 | } | |
2549 | ||
2550 | static u16 | |
2551 | bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld) | |
2552 | { | |
2553 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
2554 | struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld; | |
2555 | u16 len; | |
2556 | ||
2557 | rpa->port_name = bfa_fcs_lport_get_pwwn(port); | |
2558 | ||
2559 | len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi, | |
2560 | (u8 *) &rpa->port_attr_blk); | |
2561 | ||
2562 | len += sizeof(rpa->port_name); | |
2563 | ||
2564 | return len; | |
2565 | } | |
2566 | ||
2567 | static void | |
2568 | bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | |
2569 | void *cbarg, bfa_status_t req_status, u32 rsp_len, | |
2570 | u32 resid_len, struct fchs_s *rsp_fchs) | |
2571 | { | |
2572 | struct bfa_fcs_lport_fdmi_s *fdmi = | |
2573 | (struct bfa_fcs_lport_fdmi_s *) cbarg; | |
2574 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
2575 | struct ct_hdr_s *cthdr = NULL; | |
2576 | ||
2577 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
2578 | ||
2579 | /* | |
2580 | * Sanity Checks | |
2581 | */ | |
2582 | if (req_status != BFA_STATUS_OK) { | |
2583 | bfa_trc(port->fcs, req_status); | |
2584 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); | |
2585 | return; | |
2586 | } | |
2587 | ||
2588 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | |
ba816ea8 | 2589 | cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); |
a36c61f9 KG |
2590 | |
2591 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | |
2592 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK); | |
2593 | return; | |
2594 | } | |
2595 | ||
2596 | bfa_trc(port->fcs, cthdr->reason_code); | |
2597 | bfa_trc(port->fcs, cthdr->exp_code); | |
2598 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); | |
2599 | } | |
2600 | ||
2601 | static void | |
2602 | bfa_fcs_lport_fdmi_timeout(void *arg) | |
2603 | { | |
2604 | struct bfa_fcs_lport_fdmi_s *fdmi = (struct bfa_fcs_lport_fdmi_s *) arg; | |
2605 | ||
2606 | bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT); | |
2607 | } | |
2608 | ||
52f94b6f | 2609 | static void |
a36c61f9 KG |
2610 | bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi, |
2611 | struct bfa_fcs_fdmi_hba_attr_s *hba_attr) | |
2612 | { | |
2613 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
2614 | struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info; | |
b480a32e | 2615 | struct bfa_fcs_fdmi_port_attr_s fcs_port_attr; |
a36c61f9 | 2616 | |
6a18b167 | 2617 | memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s)); |
a36c61f9 KG |
2618 | |
2619 | bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc, | |
2620 | hba_attr->manufacturer); | |
2621 | bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc, | |
2622 | hba_attr->serial_num); | |
2623 | bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc, | |
2624 | hba_attr->model); | |
2625 | bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc, | |
2626 | hba_attr->model_desc); | |
2627 | bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc, | |
2628 | hba_attr->hw_version); | |
2629 | bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc, | |
2630 | hba_attr->option_rom_ver); | |
2631 | bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc, | |
2632 | hba_attr->fw_version); | |
2633 | ||
2634 | strncpy(hba_attr->driver_version, (char *)driver_info->version, | |
2635 | sizeof(hba_attr->driver_version)); | |
2636 | ||
2637 | strncpy(hba_attr->os_name, driver_info->host_os_name, | |
2638 | sizeof(hba_attr->os_name)); | |
2639 | ||
2640 | /* | |
2641 | * If there is a patch level, append it | |
2642 | * to the os name along with a separator | |
2643 | */ | |
2644 | if (driver_info->host_os_patch[0] != '\0') { | |
2645 | strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR, | |
2646 | sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); | |
2647 | strncat(hba_attr->os_name, driver_info->host_os_patch, | |
2648 | sizeof(driver_info->host_os_patch)); | |
2649 | } | |
2650 | ||
b480a32e KG |
2651 | /* Retrieve the max frame size from the port attr */ |
2652 | bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr); | |
2653 | hba_attr->max_ct_pyld = fcs_port_attr.max_frm_size; | |
d7cbc304 VMG |
2654 | |
2655 | strncpy(hba_attr->node_sym_name.symname, | |
2656 | port->port_cfg.node_sym_name.symname, BFA_SYMNAME_MAXLEN); | |
31e1d569 | 2657 | strcpy(hba_attr->vendor_info, "QLogic"); |
d7cbc304 VMG |
2658 | hba_attr->num_ports = |
2659 | cpu_to_be32(bfa_ioc_get_nports(&port->fcs->bfa->ioc)); | |
2660 | hba_attr->fabric_name = port->fabric->lps->pr_nwwn; | |
2661 | strncpy(hba_attr->bios_ver, hba_attr->option_rom_ver, BFA_VERSION_LEN); | |
2662 | ||
a36c61f9 KG |
2663 | } |
2664 | ||
52f94b6f | 2665 | static void |
a36c61f9 KG |
2666 | bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi, |
2667 | struct bfa_fcs_fdmi_port_attr_s *port_attr) | |
2668 | { | |
2669 | struct bfa_fcs_lport_s *port = fdmi->ms->port; | |
2670 | struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info; | |
2671 | struct bfa_port_attr_s pport_attr; | |
d7cbc304 | 2672 | struct bfa_lport_attr_s lport_attr; |
a36c61f9 | 2673 | |
6a18b167 | 2674 | memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s)); |
a36c61f9 KG |
2675 | |
2676 | /* | |
2677 | * get pport attributes from hal | |
2678 | */ | |
2679 | bfa_fcport_get_attr(port->fcs->bfa, &pport_attr); | |
2680 | ||
2681 | /* | |
2682 | * get FC4 type Bitmask | |
2683 | */ | |
2684 | fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types); | |
2685 | ||
2686 | /* | |
2687 | * Supported Speeds | |
2688 | */ | |
d7be54cc KG |
2689 | switch (pport_attr.speed_supported) { |
2690 | case BFA_PORT_SPEED_16GBPS: | |
2691 | port_attr->supp_speed = | |
2692 | cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_16G); | |
2693 | break; | |
2694 | ||
2695 | case BFA_PORT_SPEED_10GBPS: | |
2696 | port_attr->supp_speed = | |
2697 | cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_10G); | |
2698 | break; | |
2699 | ||
2700 | case BFA_PORT_SPEED_8GBPS: | |
2701 | port_attr->supp_speed = | |
2702 | cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_8G); | |
2703 | break; | |
2704 | ||
2705 | case BFA_PORT_SPEED_4GBPS: | |
2706 | port_attr->supp_speed = | |
2707 | cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_4G); | |
2708 | break; | |
2709 | ||
2710 | default: | |
2711 | bfa_sm_fault(port->fcs, pport_attr.speed_supported); | |
2712 | } | |
a36c61f9 KG |
2713 | |
2714 | /* | |
2715 | * Current Speed | |
2716 | */ | |
d7be54cc KG |
2717 | port_attr->curr_speed = cpu_to_be32( |
2718 | bfa_fcs_fdmi_convert_speed(pport_attr.speed)); | |
a36c61f9 KG |
2719 | |
2720 | /* | |
2721 | * Max PDU Size. | |
2722 | */ | |
b480a32e | 2723 | port_attr->max_frm_size = cpu_to_be32(pport_attr.pport_cfg.maxfrsize); |
a36c61f9 KG |
2724 | |
2725 | /* | |
2726 | * OS device Name | |
2727 | */ | |
2728 | strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name, | |
2729 | sizeof(port_attr->os_device_name)); | |
2730 | ||
2731 | /* | |
2732 | * Host name | |
2733 | */ | |
2734 | strncpy(port_attr->host_name, (char *)driver_info->host_machine_name, | |
2735 | sizeof(port_attr->host_name)); | |
2736 | ||
d7cbc304 VMG |
2737 | port_attr->node_name = bfa_fcs_lport_get_nwwn(port); |
2738 | port_attr->port_name = bfa_fcs_lport_get_pwwn(port); | |
2739 | ||
2740 | strncpy(port_attr->port_sym_name.symname, | |
2741 | (char *)&bfa_fcs_lport_get_psym_name(port), BFA_SYMNAME_MAXLEN); | |
2742 | bfa_fcs_lport_get_attr(port, &lport_attr); | |
2743 | port_attr->port_type = cpu_to_be32(lport_attr.port_type); | |
2744 | port_attr->scos = pport_attr.cos_supported; | |
2745 | port_attr->port_fabric_name = port->fabric->lps->pr_nwwn; | |
2746 | fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->port_act_fc4_type); | |
2747 | port_attr->port_state = cpu_to_be32(pport_attr.port_state); | |
2748 | port_attr->num_ports = cpu_to_be32(port->num_rports); | |
a36c61f9 KG |
2749 | } |
2750 | ||
d7be54cc KG |
2751 | /* |
2752 | * Convert BFA speed to FDMI format. | |
2753 | */ | |
2754 | u32 | |
2755 | bfa_fcs_fdmi_convert_speed(bfa_port_speed_t pport_speed) | |
2756 | { | |
2757 | u32 ret; | |
2758 | ||
2759 | switch (pport_speed) { | |
2760 | case BFA_PORT_SPEED_1GBPS: | |
2761 | case BFA_PORT_SPEED_2GBPS: | |
2762 | ret = pport_speed; | |
2763 | break; | |
2764 | ||
2765 | case BFA_PORT_SPEED_4GBPS: | |
2766 | ret = FDMI_TRANS_SPEED_4G; | |
2767 | break; | |
2768 | ||
2769 | case BFA_PORT_SPEED_8GBPS: | |
2770 | ret = FDMI_TRANS_SPEED_8G; | |
2771 | break; | |
2772 | ||
2773 | case BFA_PORT_SPEED_10GBPS: | |
2774 | ret = FDMI_TRANS_SPEED_10G; | |
2775 | break; | |
2776 | ||
2777 | case BFA_PORT_SPEED_16GBPS: | |
2778 | ret = FDMI_TRANS_SPEED_16G; | |
2779 | break; | |
2780 | ||
2781 | default: | |
2782 | ret = FDMI_TRANS_SPEED_UNKNOWN; | |
2783 | } | |
2784 | return ret; | |
2785 | } | |
a36c61f9 KG |
2786 | |
2787 | void | |
2788 | bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms) | |
2789 | { | |
2790 | struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi; | |
2791 | ||
2792 | fdmi->ms = ms; | |
2793 | if (ms->port->fcs->fdmi_enabled) | |
2794 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); | |
2795 | else | |
2796 | bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_disabled); | |
2797 | } | |
2798 | ||
2799 | void | |
2800 | bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms) | |
2801 | { | |
2802 | struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi; | |
2803 | ||
2804 | fdmi->ms = ms; | |
2805 | bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE); | |
2806 | } | |
2807 | ||
2808 | void | |
2809 | bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms) | |
2810 | { | |
2811 | struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi; | |
2812 | ||
2813 | fdmi->ms = ms; | |
2814 | bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE); | |
2815 | } | |
2816 | ||
2817 | #define BFA_FCS_MS_CMD_MAX_RETRIES 2 | |
2818 | ||
2819 | /* | |
2820 | * forward declarations | |
2821 | */ | |
2822 | static void bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, | |
2823 | struct bfa_fcxp_s *fcxp_alloced); | |
2824 | static void bfa_fcs_lport_ms_timeout(void *arg); | |
2825 | static void bfa_fcs_lport_ms_plogi_response(void *fcsarg, | |
2826 | struct bfa_fcxp_s *fcxp, | |
2827 | void *cbarg, | |
2828 | bfa_status_t req_status, | |
2829 | u32 rsp_len, | |
2830 | u32 resid_len, | |
2831 | struct fchs_s *rsp_fchs); | |
2832 | ||
2833 | static void bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, | |
2834 | struct bfa_fcxp_s *fcxp_alloced); | |
2835 | static void bfa_fcs_lport_ms_gmal_response(void *fcsarg, | |
2836 | struct bfa_fcxp_s *fcxp, | |
2837 | void *cbarg, | |
2838 | bfa_status_t req_status, | |
2839 | u32 rsp_len, | |
2840 | u32 resid_len, | |
2841 | struct fchs_s *rsp_fchs); | |
2842 | static void bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, | |
2843 | struct bfa_fcxp_s *fcxp_alloced); | |
2844 | static void bfa_fcs_lport_ms_gfn_response(void *fcsarg, | |
2845 | struct bfa_fcxp_s *fcxp, | |
2846 | void *cbarg, | |
2847 | bfa_status_t req_status, | |
2848 | u32 rsp_len, | |
2849 | u32 resid_len, | |
2850 | struct fchs_s *rsp_fchs); | |
5fbe25c7 | 2851 | /* |
a36c61f9 KG |
2852 | * fcs_ms_sm FCS MS state machine |
2853 | */ | |
2854 | ||
5fbe25c7 | 2855 | /* |
a36c61f9 KG |
2856 | * MS State Machine events |
2857 | */ | |
2858 | enum port_ms_event { | |
2859 | MSSM_EVENT_PORT_ONLINE = 1, | |
2860 | MSSM_EVENT_PORT_OFFLINE = 2, | |
2861 | MSSM_EVENT_RSP_OK = 3, | |
2862 | MSSM_EVENT_RSP_ERROR = 4, | |
2863 | MSSM_EVENT_TIMEOUT = 5, | |
2864 | MSSM_EVENT_FCXP_SENT = 6, | |
2865 | MSSM_EVENT_PORT_FABRIC_RSCN = 7 | |
2866 | }; | |
2867 | ||
2868 | static void bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms, | |
2869 | enum port_ms_event event); | |
2870 | static void bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms, | |
2871 | enum port_ms_event event); | |
2872 | static void bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms, | |
2873 | enum port_ms_event event); | |
2874 | static void bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms, | |
2875 | enum port_ms_event event); | |
2876 | static void bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms, | |
2877 | enum port_ms_event event); | |
2878 | static void bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms, | |
2879 | enum port_ms_event event); | |
2880 | static void bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms, | |
2881 | enum port_ms_event event); | |
2882 | static void bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms, | |
2883 | enum port_ms_event event); | |
2884 | static void bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms, | |
2885 | enum port_ms_event event); | |
2886 | static void bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms, | |
2887 | enum port_ms_event event); | |
2888 | static void bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms, | |
2889 | enum port_ms_event event); | |
5fbe25c7 | 2890 | /* |
a36c61f9 KG |
2891 | * Start in offline state - awaiting NS to send start. |
2892 | */ | |
2893 | static void | |
2894 | bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms, | |
2895 | enum port_ms_event event) | |
2896 | { | |
2897 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | |
2898 | bfa_trc(ms->port->fcs, event); | |
2899 | ||
2900 | switch (event) { | |
2901 | case MSSM_EVENT_PORT_ONLINE: | |
2902 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending); | |
2903 | bfa_fcs_lport_ms_send_plogi(ms, NULL); | |
2904 | break; | |
2905 | ||
2906 | case MSSM_EVENT_PORT_OFFLINE: | |
2907 | break; | |
2908 | ||
2909 | default: | |
2910 | bfa_sm_fault(ms->port->fcs, event); | |
2911 | } | |
2912 | } | |
2913 | ||
2914 | static void | |
2915 | bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms, | |
2916 | enum port_ms_event event) | |
2917 | { | |
2918 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | |
2919 | bfa_trc(ms->port->fcs, event); | |
2920 | ||
2921 | switch (event) { | |
2922 | case MSSM_EVENT_FCXP_SENT: | |
2923 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi); | |
2924 | break; | |
2925 | ||
2926 | case MSSM_EVENT_PORT_OFFLINE: | |
2927 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); | |
2928 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port), | |
2929 | &ms->fcxp_wqe); | |
2930 | break; | |
2931 | ||
2932 | default: | |
2933 | bfa_sm_fault(ms->port->fcs, event); | |
2934 | } | |
2935 | } | |
2936 | ||
2937 | static void | |
2938 | bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms, | |
2939 | enum port_ms_event event) | |
2940 | { | |
2941 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | |
2942 | bfa_trc(ms->port->fcs, event); | |
2943 | ||
2944 | switch (event) { | |
2945 | case MSSM_EVENT_RSP_ERROR: | |
2946 | /* | |
2947 | * Start timer for a delayed retry | |
2948 | */ | |
2949 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_retry); | |
2950 | ms->port->stats.ms_retries++; | |
2951 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), | |
2952 | &ms->timer, bfa_fcs_lport_ms_timeout, ms, | |
2953 | BFA_FCS_RETRY_TIMEOUT); | |
2954 | break; | |
2955 | ||
2956 | case MSSM_EVENT_RSP_OK: | |
2957 | /* | |
2958 | * since plogi is done, now invoke MS related sub-modules | |
2959 | */ | |
2960 | bfa_fcs_lport_fdmi_online(ms); | |
2961 | ||
5fbe25c7 | 2962 | /* |
a36c61f9 KG |
2963 | * if this is a Vport, go to online state. |
2964 | */ | |
2965 | if (ms->port->vport) { | |
2966 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online); | |
2967 | break; | |
2968 | } | |
2969 | ||
2970 | /* | |
2971 | * For a base port we need to get the | |
2972 | * switch's IP address. | |
2973 | */ | |
2974 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending); | |
2975 | bfa_fcs_lport_ms_send_gmal(ms, NULL); | |
2976 | break; | |
2977 | ||
2978 | case MSSM_EVENT_PORT_OFFLINE: | |
2979 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); | |
2980 | bfa_fcxp_discard(ms->fcxp); | |
2981 | break; | |
2982 | ||
2983 | default: | |
2984 | bfa_sm_fault(ms->port->fcs, event); | |
2985 | } | |
2986 | } | |
2987 | ||
2988 | static void | |
2989 | bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms, | |
2990 | enum port_ms_event event) | |
2991 | { | |
2992 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | |
2993 | bfa_trc(ms->port->fcs, event); | |
2994 | ||
2995 | switch (event) { | |
2996 | case MSSM_EVENT_TIMEOUT: | |
2997 | /* | |
2998 | * Retry Timer Expired. Re-send | |
2999 | */ | |
3000 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending); | |
3001 | bfa_fcs_lport_ms_send_plogi(ms, NULL); | |
3002 | break; | |
3003 | ||
3004 | case MSSM_EVENT_PORT_OFFLINE: | |
3005 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); | |
3006 | bfa_timer_stop(&ms->timer); | |
3007 | break; | |
3008 | ||
3009 | default: | |
3010 | bfa_sm_fault(ms->port->fcs, event); | |
3011 | } | |
3012 | } | |
3013 | ||
3014 | static void | |
3015 | bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms, | |
3016 | enum port_ms_event event) | |
3017 | { | |
3018 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | |
3019 | bfa_trc(ms->port->fcs, event); | |
3020 | ||
3021 | switch (event) { | |
3022 | case MSSM_EVENT_PORT_OFFLINE: | |
3023 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); | |
3024 | break; | |
3025 | ||
3026 | case MSSM_EVENT_PORT_FABRIC_RSCN: | |
3027 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending); | |
3028 | ms->retry_cnt = 0; | |
3029 | bfa_fcs_lport_ms_send_gfn(ms, NULL); | |
3030 | break; | |
3031 | ||
3032 | default: | |
3033 | bfa_sm_fault(ms->port->fcs, event); | |
3034 | } | |
3035 | } | |
3036 | ||
3037 | static void | |
3038 | bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms, | |
3039 | enum port_ms_event event) | |
3040 | { | |
3041 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | |
3042 | bfa_trc(ms->port->fcs, event); | |
3043 | ||
3044 | switch (event) { | |
3045 | case MSSM_EVENT_FCXP_SENT: | |
3046 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal); | |
3047 | break; | |
3048 | ||
3049 | case MSSM_EVENT_PORT_OFFLINE: | |
3050 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); | |
3051 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port), | |
3052 | &ms->fcxp_wqe); | |
3053 | break; | |
3054 | ||
3055 | default: | |
3056 | bfa_sm_fault(ms->port->fcs, event); | |
3057 | } | |
3058 | } | |
3059 | ||
3060 | static void | |
3061 | bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms, | |
3062 | enum port_ms_event event) | |
3063 | { | |
3064 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | |
3065 | bfa_trc(ms->port->fcs, event); | |
3066 | ||
3067 | switch (event) { | |
3068 | case MSSM_EVENT_RSP_ERROR: | |
3069 | /* | |
3070 | * Start timer for a delayed retry | |
3071 | */ | |
3072 | if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) { | |
3073 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_retry); | |
3074 | ms->port->stats.ms_retries++; | |
3075 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), | |
3076 | &ms->timer, bfa_fcs_lport_ms_timeout, ms, | |
3077 | BFA_FCS_RETRY_TIMEOUT); | |
3078 | } else { | |
3079 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending); | |
3080 | bfa_fcs_lport_ms_send_gfn(ms, NULL); | |
3081 | ms->retry_cnt = 0; | |
3082 | } | |
3083 | break; | |
3084 | ||
3085 | case MSSM_EVENT_RSP_OK: | |
3086 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending); | |
3087 | bfa_fcs_lport_ms_send_gfn(ms, NULL); | |
3088 | break; | |
3089 | ||
3090 | case MSSM_EVENT_PORT_OFFLINE: | |
3091 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); | |
3092 | bfa_fcxp_discard(ms->fcxp); | |
3093 | break; | |
3094 | ||
3095 | default: | |
3096 | bfa_sm_fault(ms->port->fcs, event); | |
3097 | } | |
3098 | } | |
3099 | ||
3100 | static void | |
3101 | bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms, | |
3102 | enum port_ms_event event) | |
3103 | { | |
3104 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | |
3105 | bfa_trc(ms->port->fcs, event); | |
3106 | ||
3107 | switch (event) { | |
3108 | case MSSM_EVENT_TIMEOUT: | |
3109 | /* | |
3110 | * Retry Timer Expired. Re-send | |
3111 | */ | |
3112 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending); | |
3113 | bfa_fcs_lport_ms_send_gmal(ms, NULL); | |
3114 | break; | |
3115 | ||
3116 | case MSSM_EVENT_PORT_OFFLINE: | |
3117 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); | |
3118 | bfa_timer_stop(&ms->timer); | |
3119 | break; | |
3120 | ||
3121 | default: | |
3122 | bfa_sm_fault(ms->port->fcs, event); | |
3123 | } | |
3124 | } | |
5fbe25c7 | 3125 | /* |
a36c61f9 KG |
3126 | * ms_pvt MS local functions |
3127 | */ | |
3128 | ||
3129 | static void | |
3130 | bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced) | |
3131 | { | |
3132 | struct bfa_fcs_lport_ms_s *ms = ms_cbarg; | |
3133 | bfa_fcs_lport_t *port = ms->port; | |
3134 | struct fchs_s fchs; | |
3135 | int len; | |
3136 | struct bfa_fcxp_s *fcxp; | |
3137 | ||
3138 | bfa_trc(port->fcs, port->pid); | |
3139 | ||
c3f1b123 KG |
3140 | fcxp = fcxp_alloced ? fcxp_alloced : |
3141 | bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); | |
a36c61f9 KG |
3142 | if (!fcxp) { |
3143 | bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe, | |
c3f1b123 | 3144 | bfa_fcs_lport_ms_send_gmal, ms, BFA_TRUE); |
a36c61f9 KG |
3145 | return; |
3146 | } | |
3147 | ms->fcxp = fcxp; | |
3148 | ||
3149 | len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | |
3150 | bfa_fcs_lport_get_fcid(port), | |
f7f73812 | 3151 | port->fabric->lps->pr_nwwn); |
a36c61f9 KG |
3152 | |
3153 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | |
3154 | FC_CLASS_3, len, &fchs, | |
3155 | bfa_fcs_lport_ms_gmal_response, (void *)ms, | |
3156 | FC_MAX_PDUSZ, FC_FCCT_TOV); | |
3157 | ||
3158 | bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT); | |
3159 | } | |
3160 | ||
3161 | static void | |
3162 | bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | |
3163 | void *cbarg, bfa_status_t req_status, | |
3164 | u32 rsp_len, u32 resid_len, | |
3165 | struct fchs_s *rsp_fchs) | |
3166 | { | |
3167 | struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg; | |
3168 | bfa_fcs_lport_t *port = ms->port; | |
3169 | struct ct_hdr_s *cthdr = NULL; | |
3170 | struct fcgs_gmal_resp_s *gmal_resp; | |
3171 | struct fcgs_gmal_entry_s *gmal_entry; | |
3172 | u32 num_entries; | |
3173 | u8 *rsp_str; | |
3174 | ||
3175 | bfa_trc(port->fcs, req_status); | |
3176 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
3177 | ||
3178 | /* | |
3179 | * Sanity Checks | |
3180 | */ | |
3181 | if (req_status != BFA_STATUS_OK) { | |
3182 | bfa_trc(port->fcs, req_status); | |
3183 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); | |
3184 | return; | |
3185 | } | |
3186 | ||
3187 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | |
ba816ea8 | 3188 | cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); |
a36c61f9 KG |
3189 | |
3190 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | |
3191 | gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1); | |
3192 | ||
ba816ea8 | 3193 | num_entries = be32_to_cpu(gmal_resp->ms_len); |
a36c61f9 KG |
3194 | if (num_entries == 0) { |
3195 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); | |
3196 | return; | |
3197 | } | |
3198 | /* | |
3199 | * The response could contain multiple Entries. | |
3200 | * Entries for SNMP interface, etc. | |
3201 | * We look for the entry with a telnet prefix. | |
3202 | * First "http://" entry refers to IP addr | |
3203 | */ | |
3204 | ||
3205 | gmal_entry = (struct fcgs_gmal_entry_s *)gmal_resp->ms_ma; | |
3206 | while (num_entries > 0) { | |
3207 | if (strncmp(gmal_entry->prefix, | |
3208 | CT_GMAL_RESP_PREFIX_HTTP, | |
3209 | sizeof(gmal_entry->prefix)) == 0) { | |
3210 | ||
3211 | /* | |
3212 | * if the IP address is terminating with a '/', | |
3213 | * remove it. | |
3214 | * Byte 0 consists of the length of the string. | |
3215 | */ | |
3216 | rsp_str = &(gmal_entry->prefix[0]); | |
3217 | if (rsp_str[gmal_entry->len-1] == '/') | |
3218 | rsp_str[gmal_entry->len-1] = 0; | |
3219 | ||
3220 | /* copy IP Address to fabric */ | |
3221 | strncpy(bfa_fcs_lport_get_fabric_ipaddr(port), | |
3222 | gmal_entry->ip_addr, | |
3223 | BFA_FCS_FABRIC_IPADDR_SZ); | |
3224 | break; | |
3225 | } else { | |
3226 | --num_entries; | |
3227 | ++gmal_entry; | |
3228 | } | |
3229 | } | |
3230 | ||
3231 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK); | |
3232 | return; | |
3233 | } | |
3234 | ||
3235 | bfa_trc(port->fcs, cthdr->reason_code); | |
3236 | bfa_trc(port->fcs, cthdr->exp_code); | |
3237 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); | |
3238 | } | |
3239 | ||
3240 | static void | |
3241 | bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms, | |
3242 | enum port_ms_event event) | |
3243 | { | |
3244 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | |
3245 | bfa_trc(ms->port->fcs, event); | |
3246 | ||
3247 | switch (event) { | |
3248 | case MSSM_EVENT_FCXP_SENT: | |
3249 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn); | |
3250 | break; | |
3251 | ||
3252 | case MSSM_EVENT_PORT_OFFLINE: | |
3253 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); | |
3254 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port), | |
3255 | &ms->fcxp_wqe); | |
3256 | break; | |
3257 | ||
3258 | default: | |
3259 | bfa_sm_fault(ms->port->fcs, event); | |
3260 | } | |
3261 | } | |
3262 | ||
3263 | static void | |
3264 | bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms, | |
3265 | enum port_ms_event event) | |
3266 | { | |
3267 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | |
3268 | bfa_trc(ms->port->fcs, event); | |
3269 | ||
3270 | switch (event) { | |
3271 | case MSSM_EVENT_RSP_ERROR: | |
3272 | /* | |
3273 | * Start timer for a delayed retry | |
3274 | */ | |
3275 | if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) { | |
3276 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_retry); | |
3277 | ms->port->stats.ms_retries++; | |
3278 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), | |
3279 | &ms->timer, bfa_fcs_lport_ms_timeout, ms, | |
3280 | BFA_FCS_RETRY_TIMEOUT); | |
3281 | } else { | |
3282 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online); | |
3283 | ms->retry_cnt = 0; | |
3284 | } | |
3285 | break; | |
3286 | ||
3287 | case MSSM_EVENT_RSP_OK: | |
3288 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online); | |
3289 | break; | |
3290 | ||
3291 | case MSSM_EVENT_PORT_OFFLINE: | |
3292 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); | |
3293 | bfa_fcxp_discard(ms->fcxp); | |
3294 | break; | |
3295 | ||
3296 | default: | |
3297 | bfa_sm_fault(ms->port->fcs, event); | |
3298 | } | |
3299 | } | |
3300 | ||
3301 | static void | |
3302 | bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms, | |
3303 | enum port_ms_event event) | |
3304 | { | |
3305 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | |
3306 | bfa_trc(ms->port->fcs, event); | |
3307 | ||
3308 | switch (event) { | |
3309 | case MSSM_EVENT_TIMEOUT: | |
3310 | /* | |
3311 | * Retry Timer Expired. Re-send | |
3312 | */ | |
3313 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending); | |
3314 | bfa_fcs_lport_ms_send_gfn(ms, NULL); | |
3315 | break; | |
3316 | ||
3317 | case MSSM_EVENT_PORT_OFFLINE: | |
3318 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); | |
3319 | bfa_timer_stop(&ms->timer); | |
3320 | break; | |
3321 | ||
3322 | default: | |
3323 | bfa_sm_fault(ms->port->fcs, event); | |
3324 | } | |
3325 | } | |
5fbe25c7 | 3326 | /* |
a36c61f9 KG |
3327 | * ms_pvt MS local functions |
3328 | */ | |
3329 | ||
3330 | static void | |
3331 | bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced) | |
3332 | { | |
3333 | struct bfa_fcs_lport_ms_s *ms = ms_cbarg; | |
3334 | bfa_fcs_lport_t *port = ms->port; | |
3335 | struct fchs_s fchs; | |
3336 | int len; | |
3337 | struct bfa_fcxp_s *fcxp; | |
3338 | ||
3339 | bfa_trc(port->fcs, port->pid); | |
3340 | ||
c3f1b123 KG |
3341 | fcxp = fcxp_alloced ? fcxp_alloced : |
3342 | bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); | |
a36c61f9 KG |
3343 | if (!fcxp) { |
3344 | bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe, | |
c3f1b123 | 3345 | bfa_fcs_lport_ms_send_gfn, ms, BFA_TRUE); |
a36c61f9 KG |
3346 | return; |
3347 | } | |
3348 | ms->fcxp = fcxp; | |
3349 | ||
3350 | len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | |
3351 | bfa_fcs_lport_get_fcid(port), | |
f7f73812 | 3352 | port->fabric->lps->pr_nwwn); |
a36c61f9 KG |
3353 | |
3354 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | |
3355 | FC_CLASS_3, len, &fchs, | |
3356 | bfa_fcs_lport_ms_gfn_response, (void *)ms, | |
3357 | FC_MAX_PDUSZ, FC_FCCT_TOV); | |
3358 | ||
3359 | bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT); | |
3360 | } | |
3361 | ||
3362 | static void | |
3363 | bfa_fcs_lport_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | |
3364 | void *cbarg, bfa_status_t req_status, u32 rsp_len, | |
3365 | u32 resid_len, struct fchs_s *rsp_fchs) | |
3366 | { | |
3367 | struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg; | |
3368 | bfa_fcs_lport_t *port = ms->port; | |
3369 | struct ct_hdr_s *cthdr = NULL; | |
3370 | wwn_t *gfn_resp; | |
3371 | ||
3372 | bfa_trc(port->fcs, req_status); | |
3373 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
3374 | ||
3375 | /* | |
3376 | * Sanity Checks | |
3377 | */ | |
3378 | if (req_status != BFA_STATUS_OK) { | |
3379 | bfa_trc(port->fcs, req_status); | |
3380 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); | |
3381 | return; | |
3382 | } | |
3383 | ||
3384 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | |
ba816ea8 | 3385 | cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); |
a36c61f9 KG |
3386 | |
3387 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | |
3388 | gfn_resp = (wwn_t *)(cthdr + 1); | |
3389 | /* check if it has actually changed */ | |
3390 | if ((memcmp((void *)&bfa_fcs_lport_get_fabric_name(port), | |
3391 | gfn_resp, sizeof(wwn_t)) != 0)) { | |
3392 | bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp); | |
3393 | } | |
3394 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK); | |
3395 | return; | |
3396 | } | |
3397 | ||
3398 | bfa_trc(port->fcs, cthdr->reason_code); | |
3399 | bfa_trc(port->fcs, cthdr->exp_code); | |
3400 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); | |
3401 | } | |
3402 | ||
5fbe25c7 | 3403 | /* |
a36c61f9 KG |
3404 | * ms_pvt MS local functions |
3405 | */ | |
3406 | ||
3407 | static void | |
3408 | bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced) | |
3409 | { | |
3410 | struct bfa_fcs_lport_ms_s *ms = ms_cbarg; | |
3411 | struct bfa_fcs_lport_s *port = ms->port; | |
3412 | struct fchs_s fchs; | |
3413 | int len; | |
3414 | struct bfa_fcxp_s *fcxp; | |
3415 | ||
3416 | bfa_trc(port->fcs, port->pid); | |
3417 | ||
c3f1b123 KG |
3418 | fcxp = fcxp_alloced ? fcxp_alloced : |
3419 | bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); | |
a36c61f9 KG |
3420 | if (!fcxp) { |
3421 | port->stats.ms_plogi_alloc_wait++; | |
3422 | bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe, | |
c3f1b123 | 3423 | bfa_fcs_lport_ms_send_plogi, ms, BFA_TRUE); |
a36c61f9 KG |
3424 | return; |
3425 | } | |
3426 | ms->fcxp = fcxp; | |
3427 | ||
3428 | len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | |
f16a1750 | 3429 | bfa_hton3b(FC_MGMT_SERVER), |
a36c61f9 KG |
3430 | bfa_fcs_lport_get_fcid(port), 0, |
3431 | port->port_cfg.pwwn, port->port_cfg.nwwn, | |
be540a99 KG |
3432 | bfa_fcport_get_maxfrsize(port->fcs->bfa), |
3433 | bfa_fcport_get_rx_bbcredit(port->fcs->bfa)); | |
a36c61f9 KG |
3434 | |
3435 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | |
3436 | FC_CLASS_3, len, &fchs, | |
3437 | bfa_fcs_lport_ms_plogi_response, (void *)ms, | |
3438 | FC_MAX_PDUSZ, FC_ELS_TOV); | |
3439 | ||
3440 | port->stats.ms_plogi_sent++; | |
3441 | bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT); | |
3442 | } | |
3443 | ||
3444 | static void | |
3445 | bfa_fcs_lport_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | |
3446 | void *cbarg, bfa_status_t req_status, | |
3447 | u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs) | |
3448 | { | |
3449 | struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg; | |
3450 | struct bfa_fcs_lport_s *port = ms->port; | |
3451 | struct fc_els_cmd_s *els_cmd; | |
3452 | struct fc_ls_rjt_s *ls_rjt; | |
3453 | ||
3454 | bfa_trc(port->fcs, req_status); | |
3455 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
3456 | ||
3457 | /* | |
3458 | * Sanity Checks | |
3459 | */ | |
3460 | if (req_status != BFA_STATUS_OK) { | |
3461 | port->stats.ms_plogi_rsp_err++; | |
3462 | bfa_trc(port->fcs, req_status); | |
3463 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); | |
3464 | return; | |
3465 | } | |
3466 | ||
3467 | els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp); | |
3468 | ||
3469 | switch (els_cmd->els_code) { | |
3470 | ||
3471 | case FC_ELS_ACC: | |
3472 | if (rsp_len < sizeof(struct fc_logi_s)) { | |
3473 | bfa_trc(port->fcs, rsp_len); | |
3474 | port->stats.ms_plogi_acc_err++; | |
3475 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); | |
3476 | break; | |
3477 | } | |
3478 | port->stats.ms_plogi_accepts++; | |
3479 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK); | |
3480 | break; | |
3481 | ||
3482 | case FC_ELS_LS_RJT: | |
3483 | ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp); | |
3484 | ||
3485 | bfa_trc(port->fcs, ls_rjt->reason_code); | |
3486 | bfa_trc(port->fcs, ls_rjt->reason_code_expl); | |
3487 | ||
3488 | port->stats.ms_rejects++; | |
3489 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); | |
3490 | break; | |
3491 | ||
3492 | default: | |
3493 | port->stats.ms_plogi_unknown_rsp++; | |
3494 | bfa_trc(port->fcs, els_cmd->els_code); | |
3495 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); | |
3496 | } | |
3497 | } | |
3498 | ||
3499 | static void | |
3500 | bfa_fcs_lport_ms_timeout(void *arg) | |
3501 | { | |
3502 | struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) arg; | |
3503 | ||
3504 | ms->port->stats.ms_timeouts++; | |
3505 | bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT); | |
3506 | } | |
3507 | ||
3508 | ||
3509 | void | |
3510 | bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port) | |
3511 | { | |
3512 | struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port); | |
3513 | ||
3514 | ms->port = port; | |
3515 | bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); | |
3516 | ||
3517 | /* | |
3518 | * Invoke init routines of sub modules. | |
3519 | */ | |
3520 | bfa_fcs_lport_fdmi_init(ms); | |
3521 | } | |
3522 | ||
3523 | void | |
3524 | bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port) | |
3525 | { | |
3526 | struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port); | |
3527 | ||
3528 | ms->port = port; | |
3529 | bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE); | |
3530 | bfa_fcs_lport_fdmi_offline(ms); | |
3531 | } | |
3532 | ||
3533 | void | |
3534 | bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port) | |
3535 | { | |
3536 | struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port); | |
3537 | ||
3538 | ms->port = port; | |
3539 | bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE); | |
3540 | } | |
3541 | void | |
3542 | bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port) | |
3543 | { | |
3544 | struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port); | |
3545 | ||
3546 | /* todo. Handle this only when in Online state */ | |
3547 | if (bfa_sm_cmp_state(ms, bfa_fcs_lport_ms_sm_online)) | |
3548 | bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN); | |
3549 | } | |
3550 | ||
5fbe25c7 | 3551 | /* |
a36c61f9 KG |
3552 | * @page ns_sm_info VPORT NS State Machine |
3553 | * | |
3554 | * @section ns_sm_interactions VPORT NS State Machine Interactions | |
3555 | * | |
3556 | * @section ns_sm VPORT NS State Machine | |
3557 | * img ns_sm.jpg | |
3558 | */ | |
3559 | ||
3560 | /* | |
3561 | * forward declarations | |
3562 | */ | |
3563 | static void bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, | |
3564 | struct bfa_fcxp_s *fcxp_alloced); | |
3565 | static void bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, | |
3566 | struct bfa_fcxp_s *fcxp_alloced); | |
3567 | static void bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, | |
3568 | struct bfa_fcxp_s *fcxp_alloced); | |
3569 | static void bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, | |
3570 | struct bfa_fcxp_s *fcxp_alloced); | |
3571 | static void bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, | |
3572 | struct bfa_fcxp_s *fcxp_alloced); | |
ce7242b8 KG |
3573 | static void bfa_fcs_lport_ns_send_rnn_id(void *ns_cbarg, |
3574 | struct bfa_fcxp_s *fcxp_alloced); | |
3575 | static void bfa_fcs_lport_ns_send_rsnn_nn(void *ns_cbarg, | |
3576 | struct bfa_fcxp_s *fcxp_alloced); | |
a36c61f9 KG |
3577 | static void bfa_fcs_lport_ns_timeout(void *arg); |
3578 | static void bfa_fcs_lport_ns_plogi_response(void *fcsarg, | |
3579 | struct bfa_fcxp_s *fcxp, | |
3580 | void *cbarg, | |
3581 | bfa_status_t req_status, | |
3582 | u32 rsp_len, | |
3583 | u32 resid_len, | |
3584 | struct fchs_s *rsp_fchs); | |
3585 | static void bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, | |
3586 | struct bfa_fcxp_s *fcxp, | |
3587 | void *cbarg, | |
3588 | bfa_status_t req_status, | |
3589 | u32 rsp_len, | |
3590 | u32 resid_len, | |
3591 | struct fchs_s *rsp_fchs); | |
3592 | static void bfa_fcs_lport_ns_rft_id_response(void *fcsarg, | |
3593 | struct bfa_fcxp_s *fcxp, | |
3594 | void *cbarg, | |
3595 | bfa_status_t req_status, | |
3596 | u32 rsp_len, | |
3597 | u32 resid_len, | |
3598 | struct fchs_s *rsp_fchs); | |
3599 | static void bfa_fcs_lport_ns_rff_id_response(void *fcsarg, | |
3600 | struct bfa_fcxp_s *fcxp, | |
3601 | void *cbarg, | |
3602 | bfa_status_t req_status, | |
3603 | u32 rsp_len, | |
3604 | u32 resid_len, | |
3605 | struct fchs_s *rsp_fchs); | |
3606 | static void bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, | |
3607 | struct bfa_fcxp_s *fcxp, | |
3608 | void *cbarg, | |
3609 | bfa_status_t req_status, | |
3610 | u32 rsp_len, | |
3611 | u32 resid_len, | |
3612 | struct fchs_s *rsp_fchs); | |
ce7242b8 KG |
3613 | static void bfa_fcs_lport_ns_rnn_id_response(void *fcsarg, |
3614 | struct bfa_fcxp_s *fcxp, | |
3615 | void *cbarg, | |
3616 | bfa_status_t req_status, | |
3617 | u32 rsp_len, | |
3618 | u32 resid_len, | |
3619 | struct fchs_s *rsp_fchs); | |
3620 | static void bfa_fcs_lport_ns_rsnn_nn_response(void *fcsarg, | |
3621 | struct bfa_fcxp_s *fcxp, | |
3622 | void *cbarg, | |
3623 | bfa_status_t req_status, | |
3624 | u32 rsp_len, | |
3625 | u32 resid_len, | |
3626 | struct fchs_s *rsp_fchs); | |
a36c61f9 KG |
3627 | static void bfa_fcs_lport_ns_process_gidft_pids( |
3628 | struct bfa_fcs_lport_s *port, | |
3629 | u32 *pid_buf, u32 n_pids); | |
3630 | ||
3631 | static void bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port); | |
5fbe25c7 | 3632 | /* |
a36c61f9 KG |
3633 | * fcs_ns_sm FCS nameserver interface state machine |
3634 | */ | |
3635 | ||
5fbe25c7 | 3636 | /* |
a36c61f9 KG |
3637 | * VPort NS State Machine events |
3638 | */ | |
3639 | enum vport_ns_event { | |
3640 | NSSM_EVENT_PORT_ONLINE = 1, | |
3641 | NSSM_EVENT_PORT_OFFLINE = 2, | |
3642 | NSSM_EVENT_PLOGI_SENT = 3, | |
3643 | NSSM_EVENT_RSP_OK = 4, | |
3644 | NSSM_EVENT_RSP_ERROR = 5, | |
3645 | NSSM_EVENT_TIMEOUT = 6, | |
3646 | NSSM_EVENT_NS_QUERY = 7, | |
3647 | NSSM_EVENT_RSPNID_SENT = 8, | |
3648 | NSSM_EVENT_RFTID_SENT = 9, | |
3649 | NSSM_EVENT_RFFID_SENT = 10, | |
3650 | NSSM_EVENT_GIDFT_SENT = 11, | |
ce7242b8 KG |
3651 | NSSM_EVENT_RNNID_SENT = 12, |
3652 | NSSM_EVENT_RSNN_NN_SENT = 13, | |
a36c61f9 KG |
3653 | }; |
3654 | ||
3655 | static void bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns, | |
3656 | enum vport_ns_event event); | |
3657 | static void bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns, | |
3658 | enum vport_ns_event event); | |
3659 | static void bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns, | |
3660 | enum vport_ns_event event); | |
3661 | static void bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns, | |
3662 | enum vport_ns_event event); | |
3663 | static void bfa_fcs_lport_ns_sm_sending_rspn_id( | |
3664 | struct bfa_fcs_lport_ns_s *ns, | |
3665 | enum vport_ns_event event); | |
3666 | static void bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns, | |
3667 | enum vport_ns_event event); | |
3668 | static void bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns, | |
3669 | enum vport_ns_event event); | |
3670 | static void bfa_fcs_lport_ns_sm_sending_rft_id( | |
3671 | struct bfa_fcs_lport_ns_s *ns, | |
3672 | enum vport_ns_event event); | |
3673 | static void bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns, | |
3674 | enum vport_ns_event event); | |
3675 | static void bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns, | |
3676 | enum vport_ns_event event); | |
3677 | static void bfa_fcs_lport_ns_sm_sending_rff_id( | |
3678 | struct bfa_fcs_lport_ns_s *ns, | |
3679 | enum vport_ns_event event); | |
3680 | static void bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns, | |
3681 | enum vport_ns_event event); | |
3682 | static void bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns, | |
3683 | enum vport_ns_event event); | |
3684 | static void bfa_fcs_lport_ns_sm_sending_gid_ft( | |
3685 | struct bfa_fcs_lport_ns_s *ns, | |
3686 | enum vport_ns_event event); | |
3687 | static void bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns, | |
3688 | enum vport_ns_event event); | |
3689 | static void bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns, | |
3690 | enum vport_ns_event event); | |
3691 | static void bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns, | |
3692 | enum vport_ns_event event); | |
ce7242b8 KG |
3693 | static void bfa_fcs_lport_ns_sm_sending_rnn_id( |
3694 | struct bfa_fcs_lport_ns_s *ns, | |
3695 | enum vport_ns_event event); | |
3696 | static void bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s *ns, | |
3697 | enum vport_ns_event event); | |
3698 | static void bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s *ns, | |
3699 | enum vport_ns_event event); | |
3700 | static void bfa_fcs_lport_ns_sm_sending_rsnn_nn( | |
3701 | struct bfa_fcs_lport_ns_s *ns, | |
3702 | enum vport_ns_event event); | |
3703 | static void bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s *ns, | |
3704 | enum vport_ns_event event); | |
3705 | static void bfa_fcs_lport_ns_sm_rsnn_nn_retry( | |
3706 | struct bfa_fcs_lport_ns_s *ns, | |
3707 | enum vport_ns_event event); | |
5fbe25c7 | 3708 | /* |
a36c61f9 KG |
3709 | * Start in offline state - awaiting linkup |
3710 | */ | |
3711 | static void | |
3712 | bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns, | |
3713 | enum vport_ns_event event) | |
3714 | { | |
3715 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
3716 | bfa_trc(ns->port->fcs, event); | |
3717 | ||
3718 | switch (event) { | |
3719 | case NSSM_EVENT_PORT_ONLINE: | |
3720 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending); | |
3721 | bfa_fcs_lport_ns_send_plogi(ns, NULL); | |
3722 | break; | |
3723 | ||
3724 | case NSSM_EVENT_PORT_OFFLINE: | |
3725 | break; | |
3726 | ||
3727 | default: | |
3728 | bfa_sm_fault(ns->port->fcs, event); | |
3729 | } | |
3730 | } | |
3731 | ||
3732 | static void | |
3733 | bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns, | |
3734 | enum vport_ns_event event) | |
3735 | { | |
3736 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
3737 | bfa_trc(ns->port->fcs, event); | |
3738 | ||
3739 | switch (event) { | |
3740 | case NSSM_EVENT_PLOGI_SENT: | |
3741 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi); | |
3742 | break; | |
3743 | ||
3744 | case NSSM_EVENT_PORT_OFFLINE: | |
3745 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
3746 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port), | |
3747 | &ns->fcxp_wqe); | |
3748 | break; | |
3749 | ||
3750 | default: | |
3751 | bfa_sm_fault(ns->port->fcs, event); | |
3752 | } | |
3753 | } | |
3754 | ||
3755 | static void | |
3756 | bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns, | |
3757 | enum vport_ns_event event) | |
3758 | { | |
3759 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
3760 | bfa_trc(ns->port->fcs, event); | |
3761 | ||
3762 | switch (event) { | |
3763 | case NSSM_EVENT_RSP_ERROR: | |
3764 | /* | |
3765 | * Start timer for a delayed retry | |
3766 | */ | |
3767 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_retry); | |
3768 | ns->port->stats.ns_retries++; | |
3769 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), | |
3770 | &ns->timer, bfa_fcs_lport_ns_timeout, ns, | |
3771 | BFA_FCS_RETRY_TIMEOUT); | |
3772 | break; | |
3773 | ||
3774 | case NSSM_EVENT_RSP_OK: | |
ce7242b8 KG |
3775 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rnn_id); |
3776 | ns->num_rnnid_retries = 0; | |
3777 | bfa_fcs_lport_ns_send_rnn_id(ns, NULL); | |
a36c61f9 KG |
3778 | break; |
3779 | ||
3780 | case NSSM_EVENT_PORT_OFFLINE: | |
3781 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
3782 | bfa_fcxp_discard(ns->fcxp); | |
3783 | break; | |
3784 | ||
3785 | default: | |
3786 | bfa_sm_fault(ns->port->fcs, event); | |
3787 | } | |
3788 | } | |
3789 | ||
3790 | static void | |
3791 | bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns, | |
3792 | enum vport_ns_event event) | |
3793 | { | |
3794 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
3795 | bfa_trc(ns->port->fcs, event); | |
3796 | ||
3797 | switch (event) { | |
3798 | case NSSM_EVENT_TIMEOUT: | |
3799 | /* | |
3800 | * Retry Timer Expired. Re-send | |
3801 | */ | |
3802 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending); | |
3803 | bfa_fcs_lport_ns_send_plogi(ns, NULL); | |
3804 | break; | |
3805 | ||
3806 | case NSSM_EVENT_PORT_OFFLINE: | |
3807 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
3808 | bfa_timer_stop(&ns->timer); | |
3809 | break; | |
3810 | ||
3811 | default: | |
3812 | bfa_sm_fault(ns->port->fcs, event); | |
3813 | } | |
3814 | } | |
3815 | ||
ce7242b8 KG |
3816 | static void |
3817 | bfa_fcs_lport_ns_sm_sending_rnn_id(struct bfa_fcs_lport_ns_s *ns, | |
3818 | enum vport_ns_event event) | |
3819 | { | |
3820 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
3821 | bfa_trc(ns->port->fcs, event); | |
3822 | ||
3823 | switch (event) { | |
3824 | case NSSM_EVENT_RNNID_SENT: | |
3825 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rnn_id); | |
3826 | break; | |
3827 | ||
3828 | case NSSM_EVENT_PORT_OFFLINE: | |
3829 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
3830 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port), | |
3831 | &ns->fcxp_wqe); | |
3832 | break; | |
3833 | default: | |
3834 | bfa_sm_fault(ns->port->fcs, event); | |
3835 | } | |
3836 | } | |
3837 | ||
3838 | static void | |
3839 | bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s *ns, | |
3840 | enum vport_ns_event event) | |
3841 | { | |
3842 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
3843 | bfa_trc(ns->port->fcs, event); | |
3844 | ||
3845 | switch (event) { | |
3846 | case NSSM_EVENT_RSP_OK: | |
3847 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rsnn_nn); | |
3848 | ns->num_rnnid_retries = 0; | |
3849 | ns->num_rsnn_nn_retries = 0; | |
3850 | bfa_fcs_lport_ns_send_rsnn_nn(ns, NULL); | |
3851 | break; | |
3852 | ||
3853 | case NSSM_EVENT_RSP_ERROR: | |
3854 | if (ns->num_rnnid_retries < BFA_FCS_MAX_NS_RETRIES) { | |
3855 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rnn_id_retry); | |
3856 | ns->port->stats.ns_retries++; | |
3857 | ns->num_rnnid_retries++; | |
3858 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), | |
3859 | &ns->timer, bfa_fcs_lport_ns_timeout, ns, | |
3860 | BFA_FCS_RETRY_TIMEOUT); | |
3861 | } else { | |
3862 | bfa_sm_set_state(ns, | |
3863 | bfa_fcs_lport_ns_sm_sending_rspn_id); | |
3864 | bfa_fcs_lport_ns_send_rspn_id(ns, NULL); | |
3865 | } | |
3866 | break; | |
3867 | ||
3868 | case NSSM_EVENT_PORT_OFFLINE: | |
3869 | bfa_fcxp_discard(ns->fcxp); | |
3870 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
3871 | break; | |
3872 | ||
3873 | default: | |
3874 | bfa_sm_fault(ns->port->fcs, event); | |
3875 | } | |
3876 | } | |
3877 | ||
3878 | static void | |
3879 | bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s *ns, | |
3880 | enum vport_ns_event event) | |
3881 | { | |
3882 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
3883 | bfa_trc(ns->port->fcs, event); | |
3884 | ||
3885 | switch (event) { | |
3886 | case NSSM_EVENT_TIMEOUT: | |
3887 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rnn_id); | |
3888 | bfa_fcs_lport_ns_send_rnn_id(ns, NULL); | |
3889 | break; | |
3890 | ||
3891 | case NSSM_EVENT_PORT_OFFLINE: | |
3892 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
3893 | bfa_timer_stop(&ns->timer); | |
3894 | break; | |
3895 | ||
3896 | default: | |
3897 | bfa_sm_fault(ns->port->fcs, event); | |
3898 | } | |
3899 | } | |
3900 | ||
3901 | static void | |
3902 | bfa_fcs_lport_ns_sm_sending_rsnn_nn(struct bfa_fcs_lport_ns_s *ns, | |
3903 | enum vport_ns_event event) | |
3904 | { | |
3905 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
3906 | bfa_trc(ns->port->fcs, event); | |
3907 | ||
3908 | switch (event) { | |
3909 | case NSSM_EVENT_RSNN_NN_SENT: | |
3910 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rsnn_nn); | |
3911 | break; | |
3912 | ||
3913 | case NSSM_EVENT_PORT_OFFLINE: | |
3914 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
3915 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port), | |
3916 | &ns->fcxp_wqe); | |
3917 | break; | |
3918 | ||
3919 | default: | |
3920 | bfa_sm_fault(ns->port->fcs, event); | |
3921 | } | |
3922 | } | |
3923 | ||
3924 | static void | |
3925 | bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s *ns, | |
3926 | enum vport_ns_event event) | |
3927 | { | |
3928 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
3929 | bfa_trc(ns->port->fcs, event); | |
3930 | ||
3931 | switch (event) { | |
3932 | case NSSM_EVENT_RSP_OK: | |
3933 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id); | |
3934 | ns->num_rsnn_nn_retries = 0; | |
3935 | bfa_fcs_lport_ns_send_rspn_id(ns, NULL); | |
3936 | break; | |
3937 | ||
3938 | case NSSM_EVENT_RSP_ERROR: | |
3939 | if (ns->num_rsnn_nn_retries < BFA_FCS_MAX_NS_RETRIES) { | |
3940 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rsnn_nn_retry); | |
3941 | ns->port->stats.ns_retries++; | |
3942 | ns->num_rsnn_nn_retries++; | |
3943 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), | |
3944 | &ns->timer, bfa_fcs_lport_ns_timeout, | |
3945 | ns, BFA_FCS_RETRY_TIMEOUT); | |
3946 | } else { | |
3947 | bfa_sm_set_state(ns, | |
3948 | bfa_fcs_lport_ns_sm_sending_rspn_id); | |
3949 | bfa_fcs_lport_ns_send_rspn_id(ns, NULL); | |
3950 | } | |
3951 | break; | |
3952 | ||
3953 | case NSSM_EVENT_PORT_OFFLINE: | |
3954 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
3955 | bfa_fcxp_discard(ns->fcxp); | |
3956 | break; | |
3957 | ||
3958 | default: | |
3959 | bfa_sm_fault(ns->port->fcs, event); | |
3960 | } | |
3961 | } | |
3962 | ||
3963 | static void | |
3964 | bfa_fcs_lport_ns_sm_rsnn_nn_retry(struct bfa_fcs_lport_ns_s *ns, | |
3965 | enum vport_ns_event event) | |
3966 | { | |
3967 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
3968 | bfa_trc(ns->port->fcs, event); | |
3969 | ||
3970 | switch (event) { | |
3971 | case NSSM_EVENT_TIMEOUT: | |
3972 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rsnn_nn); | |
3973 | bfa_fcs_lport_ns_send_rsnn_nn(ns, NULL); | |
3974 | break; | |
3975 | ||
3976 | case NSSM_EVENT_PORT_OFFLINE: | |
3977 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
3978 | bfa_timer_stop(&ns->timer); | |
3979 | break; | |
3980 | ||
3981 | default: | |
3982 | bfa_sm_fault(ns->port->fcs, event); | |
3983 | } | |
3984 | } | |
3985 | ||
a36c61f9 KG |
3986 | static void |
3987 | bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns, | |
3988 | enum vport_ns_event event) | |
3989 | { | |
3990 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
3991 | bfa_trc(ns->port->fcs, event); | |
3992 | ||
3993 | switch (event) { | |
3994 | case NSSM_EVENT_RSPNID_SENT: | |
3995 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id); | |
3996 | break; | |
3997 | ||
3998 | case NSSM_EVENT_PORT_OFFLINE: | |
3999 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
4000 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port), | |
4001 | &ns->fcxp_wqe); | |
4002 | break; | |
4003 | ||
4004 | default: | |
4005 | bfa_sm_fault(ns->port->fcs, event); | |
4006 | } | |
4007 | } | |
4008 | ||
4009 | static void | |
4010 | bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns, | |
4011 | enum vport_ns_event event) | |
4012 | { | |
4013 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
4014 | bfa_trc(ns->port->fcs, event); | |
4015 | ||
4016 | switch (event) { | |
4017 | case NSSM_EVENT_RSP_ERROR: | |
4018 | /* | |
4019 | * Start timer for a delayed retry | |
4020 | */ | |
4021 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry); | |
4022 | ns->port->stats.ns_retries++; | |
4023 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), | |
4024 | &ns->timer, bfa_fcs_lport_ns_timeout, ns, | |
4025 | BFA_FCS_RETRY_TIMEOUT); | |
4026 | break; | |
4027 | ||
4028 | case NSSM_EVENT_RSP_OK: | |
4029 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id); | |
4030 | bfa_fcs_lport_ns_send_rft_id(ns, NULL); | |
4031 | break; | |
4032 | ||
4033 | case NSSM_EVENT_PORT_OFFLINE: | |
4034 | bfa_fcxp_discard(ns->fcxp); | |
4035 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
4036 | break; | |
4037 | ||
4038 | default: | |
4039 | bfa_sm_fault(ns->port->fcs, event); | |
4040 | } | |
4041 | } | |
4042 | ||
4043 | static void | |
4044 | bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns, | |
4045 | enum vport_ns_event event) | |
4046 | { | |
4047 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
4048 | bfa_trc(ns->port->fcs, event); | |
4049 | ||
4050 | switch (event) { | |
4051 | case NSSM_EVENT_TIMEOUT: | |
4052 | /* | |
4053 | * Retry Timer Expired. Re-send | |
4054 | */ | |
4055 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id); | |
4056 | bfa_fcs_lport_ns_send_rspn_id(ns, NULL); | |
4057 | break; | |
4058 | ||
4059 | case NSSM_EVENT_PORT_OFFLINE: | |
4060 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
4061 | bfa_timer_stop(&ns->timer); | |
4062 | break; | |
4063 | ||
4064 | default: | |
4065 | bfa_sm_fault(ns->port->fcs, event); | |
4066 | } | |
4067 | } | |
4068 | ||
4069 | static void | |
4070 | bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s *ns, | |
4071 | enum vport_ns_event event) | |
4072 | { | |
4073 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
4074 | bfa_trc(ns->port->fcs, event); | |
4075 | ||
4076 | switch (event) { | |
4077 | case NSSM_EVENT_RFTID_SENT: | |
4078 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id); | |
4079 | break; | |
4080 | ||
4081 | case NSSM_EVENT_PORT_OFFLINE: | |
4082 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
4083 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port), | |
4084 | &ns->fcxp_wqe); | |
4085 | break; | |
4086 | ||
4087 | default: | |
4088 | bfa_sm_fault(ns->port->fcs, event); | |
4089 | } | |
4090 | } | |
4091 | ||
4092 | static void | |
4093 | bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns, | |
4094 | enum vport_ns_event event) | |
4095 | { | |
4096 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
4097 | bfa_trc(ns->port->fcs, event); | |
4098 | ||
4099 | switch (event) { | |
4100 | case NSSM_EVENT_RSP_OK: | |
4101 | /* Now move to register FC4 Features */ | |
4102 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id); | |
4103 | bfa_fcs_lport_ns_send_rff_id(ns, NULL); | |
4104 | break; | |
4105 | ||
4106 | case NSSM_EVENT_RSP_ERROR: | |
4107 | /* | |
4108 | * Start timer for a delayed retry | |
4109 | */ | |
4110 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id_retry); | |
4111 | ns->port->stats.ns_retries++; | |
4112 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), | |
4113 | &ns->timer, bfa_fcs_lport_ns_timeout, ns, | |
4114 | BFA_FCS_RETRY_TIMEOUT); | |
4115 | break; | |
4116 | ||
4117 | case NSSM_EVENT_PORT_OFFLINE: | |
4118 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
4119 | bfa_fcxp_discard(ns->fcxp); | |
4120 | break; | |
4121 | ||
4122 | default: | |
4123 | bfa_sm_fault(ns->port->fcs, event); | |
4124 | } | |
4125 | } | |
4126 | ||
4127 | static void | |
4128 | bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns, | |
4129 | enum vport_ns_event event) | |
4130 | { | |
4131 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
4132 | bfa_trc(ns->port->fcs, event); | |
4133 | ||
4134 | switch (event) { | |
4135 | case NSSM_EVENT_TIMEOUT: | |
4136 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id); | |
4137 | bfa_fcs_lport_ns_send_rft_id(ns, NULL); | |
4138 | break; | |
4139 | ||
4140 | case NSSM_EVENT_PORT_OFFLINE: | |
4141 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
4142 | bfa_timer_stop(&ns->timer); | |
4143 | break; | |
4144 | ||
4145 | default: | |
4146 | bfa_sm_fault(ns->port->fcs, event); | |
4147 | } | |
4148 | } | |
4149 | ||
4150 | static void | |
4151 | bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s *ns, | |
4152 | enum vport_ns_event event) | |
4153 | { | |
4154 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
4155 | bfa_trc(ns->port->fcs, event); | |
4156 | ||
4157 | switch (event) { | |
4158 | case NSSM_EVENT_RFFID_SENT: | |
4159 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id); | |
4160 | break; | |
4161 | ||
4162 | case NSSM_EVENT_PORT_OFFLINE: | |
4163 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
4164 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port), | |
4165 | &ns->fcxp_wqe); | |
4166 | break; | |
4167 | ||
4168 | default: | |
4169 | bfa_sm_fault(ns->port->fcs, event); | |
4170 | } | |
4171 | } | |
4172 | ||
4173 | static void | |
4174 | bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns, | |
4175 | enum vport_ns_event event) | |
4176 | { | |
4177 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
4178 | bfa_trc(ns->port->fcs, event); | |
4179 | ||
4180 | switch (event) { | |
4181 | case NSSM_EVENT_RSP_OK: | |
4182 | ||
4183 | /* | |
4184 | * If min cfg mode is enabled, we donot initiate rport | |
4185 | * discovery with the fabric. Instead, we will retrieve the | |
4186 | * boot targets from HAL/FW. | |
4187 | */ | |
4188 | if (__fcs_min_cfg(ns->port->fcs)) { | |
4189 | bfa_fcs_lport_ns_boot_target_disc(ns->port); | |
4190 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online); | |
4191 | return; | |
4192 | } | |
4193 | ||
4194 | /* | |
4195 | * If the port role is Initiator Mode issue NS query. | |
4196 | * If it is Target Mode, skip this and go to online. | |
4197 | */ | |
4198 | if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) { | |
4199 | bfa_sm_set_state(ns, | |
4200 | bfa_fcs_lport_ns_sm_sending_gid_ft); | |
4201 | bfa_fcs_lport_ns_send_gid_ft(ns, NULL); | |
4202 | } | |
4203 | /* | |
4204 | * kick off mgmt srvr state machine | |
4205 | */ | |
4206 | bfa_fcs_lport_ms_online(ns->port); | |
4207 | break; | |
4208 | ||
4209 | case NSSM_EVENT_RSP_ERROR: | |
4210 | /* | |
4211 | * Start timer for a delayed retry | |
4212 | */ | |
4213 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id_retry); | |
4214 | ns->port->stats.ns_retries++; | |
4215 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), | |
4216 | &ns->timer, bfa_fcs_lport_ns_timeout, ns, | |
4217 | BFA_FCS_RETRY_TIMEOUT); | |
4218 | break; | |
4219 | ||
4220 | case NSSM_EVENT_PORT_OFFLINE: | |
4221 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
4222 | bfa_fcxp_discard(ns->fcxp); | |
4223 | break; | |
4224 | ||
4225 | default: | |
4226 | bfa_sm_fault(ns->port->fcs, event); | |
4227 | } | |
4228 | } | |
4229 | ||
4230 | static void | |
4231 | bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns, | |
4232 | enum vport_ns_event event) | |
4233 | { | |
4234 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
4235 | bfa_trc(ns->port->fcs, event); | |
4236 | ||
4237 | switch (event) { | |
4238 | case NSSM_EVENT_TIMEOUT: | |
4239 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id); | |
4240 | bfa_fcs_lport_ns_send_rff_id(ns, NULL); | |
4241 | break; | |
4242 | ||
4243 | case NSSM_EVENT_PORT_OFFLINE: | |
4244 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
4245 | bfa_timer_stop(&ns->timer); | |
4246 | break; | |
4247 | ||
4248 | default: | |
4249 | bfa_sm_fault(ns->port->fcs, event); | |
4250 | } | |
4251 | } | |
4252 | static void | |
4253 | bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s *ns, | |
4254 | enum vport_ns_event event) | |
4255 | { | |
4256 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
4257 | bfa_trc(ns->port->fcs, event); | |
4258 | ||
4259 | switch (event) { | |
4260 | case NSSM_EVENT_GIDFT_SENT: | |
4261 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft); | |
4262 | break; | |
4263 | ||
4264 | case NSSM_EVENT_PORT_OFFLINE: | |
4265 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
4266 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port), | |
4267 | &ns->fcxp_wqe); | |
4268 | break; | |
4269 | ||
4270 | default: | |
4271 | bfa_sm_fault(ns->port->fcs, event); | |
4272 | } | |
4273 | } | |
4274 | ||
4275 | static void | |
4276 | bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns, | |
4277 | enum vport_ns_event event) | |
4278 | { | |
4279 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
4280 | bfa_trc(ns->port->fcs, event); | |
4281 | ||
4282 | switch (event) { | |
4283 | case NSSM_EVENT_RSP_OK: | |
4284 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online); | |
4285 | break; | |
4286 | ||
4287 | case NSSM_EVENT_RSP_ERROR: | |
4288 | /* | |
4289 | * TBD: for certain reject codes, we don't need to retry | |
4290 | */ | |
4291 | /* | |
4292 | * Start timer for a delayed retry | |
4293 | */ | |
4294 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft_retry); | |
4295 | ns->port->stats.ns_retries++; | |
4296 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), | |
4297 | &ns->timer, bfa_fcs_lport_ns_timeout, ns, | |
4298 | BFA_FCS_RETRY_TIMEOUT); | |
4299 | break; | |
4300 | ||
4301 | case NSSM_EVENT_PORT_OFFLINE: | |
4302 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
4303 | bfa_fcxp_discard(ns->fcxp); | |
4304 | break; | |
4305 | ||
4306 | case NSSM_EVENT_NS_QUERY: | |
4307 | break; | |
4308 | ||
4309 | default: | |
4310 | bfa_sm_fault(ns->port->fcs, event); | |
4311 | } | |
4312 | } | |
4313 | ||
4314 | static void | |
4315 | bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns, | |
4316 | enum vport_ns_event event) | |
4317 | { | |
4318 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
4319 | bfa_trc(ns->port->fcs, event); | |
4320 | ||
4321 | switch (event) { | |
4322 | case NSSM_EVENT_TIMEOUT: | |
4323 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_gid_ft); | |
4324 | bfa_fcs_lport_ns_send_gid_ft(ns, NULL); | |
4325 | break; | |
4326 | ||
4327 | case NSSM_EVENT_PORT_OFFLINE: | |
4328 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
4329 | bfa_timer_stop(&ns->timer); | |
4330 | break; | |
4331 | ||
4332 | default: | |
4333 | bfa_sm_fault(ns->port->fcs, event); | |
4334 | } | |
4335 | } | |
4336 | ||
4337 | static void | |
4338 | bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns, | |
4339 | enum vport_ns_event event) | |
4340 | { | |
4341 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | |
4342 | bfa_trc(ns->port->fcs, event); | |
4343 | ||
4344 | switch (event) { | |
4345 | case NSSM_EVENT_PORT_OFFLINE: | |
4346 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
4347 | break; | |
4348 | ||
4349 | case NSSM_EVENT_NS_QUERY: | |
4350 | /* | |
4351 | * If the port role is Initiator Mode issue NS query. | |
4352 | * If it is Target Mode, skip this and go to online. | |
4353 | */ | |
4354 | if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) { | |
4355 | bfa_sm_set_state(ns, | |
4356 | bfa_fcs_lport_ns_sm_sending_gid_ft); | |
4357 | bfa_fcs_lport_ns_send_gid_ft(ns, NULL); | |
4358 | }; | |
4359 | break; | |
4360 | ||
4361 | default: | |
4362 | bfa_sm_fault(ns->port->fcs, event); | |
4363 | } | |
4364 | } | |
4365 | ||
4366 | ||
4367 | ||
5fbe25c7 | 4368 | /* |
a36c61f9 KG |
4369 | * ns_pvt Nameserver local functions |
4370 | */ | |
4371 | ||
4372 | static void | |
4373 | bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) | |
4374 | { | |
4375 | struct bfa_fcs_lport_ns_s *ns = ns_cbarg; | |
4376 | struct bfa_fcs_lport_s *port = ns->port; | |
4377 | struct fchs_s fchs; | |
4378 | int len; | |
4379 | struct bfa_fcxp_s *fcxp; | |
4380 | ||
4381 | bfa_trc(port->fcs, port->pid); | |
4382 | ||
c3f1b123 KG |
4383 | fcxp = fcxp_alloced ? fcxp_alloced : |
4384 | bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); | |
a36c61f9 KG |
4385 | if (!fcxp) { |
4386 | port->stats.ns_plogi_alloc_wait++; | |
4387 | bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, | |
c3f1b123 | 4388 | bfa_fcs_lport_ns_send_plogi, ns, BFA_TRUE); |
a36c61f9 KG |
4389 | return; |
4390 | } | |
4391 | ns->fcxp = fcxp; | |
4392 | ||
4393 | len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | |
f16a1750 | 4394 | bfa_hton3b(FC_NAME_SERVER), |
a36c61f9 KG |
4395 | bfa_fcs_lport_get_fcid(port), 0, |
4396 | port->port_cfg.pwwn, port->port_cfg.nwwn, | |
be540a99 KG |
4397 | bfa_fcport_get_maxfrsize(port->fcs->bfa), |
4398 | bfa_fcport_get_rx_bbcredit(port->fcs->bfa)); | |
a36c61f9 KG |
4399 | |
4400 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | |
4401 | FC_CLASS_3, len, &fchs, | |
4402 | bfa_fcs_lport_ns_plogi_response, (void *)ns, | |
4403 | FC_MAX_PDUSZ, FC_ELS_TOV); | |
4404 | port->stats.ns_plogi_sent++; | |
4405 | ||
4406 | bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT); | |
4407 | } | |
4408 | ||
4409 | static void | |
4410 | bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | |
4411 | void *cbarg, bfa_status_t req_status, u32 rsp_len, | |
4412 | u32 resid_len, struct fchs_s *rsp_fchs) | |
4413 | { | |
4414 | struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg; | |
4415 | struct bfa_fcs_lport_s *port = ns->port; | |
4416 | /* struct fc_logi_s *plogi_resp; */ | |
4417 | struct fc_els_cmd_s *els_cmd; | |
4418 | struct fc_ls_rjt_s *ls_rjt; | |
4419 | ||
4420 | bfa_trc(port->fcs, req_status); | |
4421 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
4422 | ||
4423 | /* | |
4424 | * Sanity Checks | |
4425 | */ | |
4426 | if (req_status != BFA_STATUS_OK) { | |
4427 | bfa_trc(port->fcs, req_status); | |
4428 | port->stats.ns_plogi_rsp_err++; | |
4429 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | |
4430 | return; | |
4431 | } | |
4432 | ||
4433 | els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp); | |
4434 | ||
4435 | switch (els_cmd->els_code) { | |
4436 | ||
4437 | case FC_ELS_ACC: | |
4438 | if (rsp_len < sizeof(struct fc_logi_s)) { | |
4439 | bfa_trc(port->fcs, rsp_len); | |
4440 | port->stats.ns_plogi_acc_err++; | |
4441 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | |
4442 | break; | |
4443 | } | |
4444 | port->stats.ns_plogi_accepts++; | |
4445 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); | |
4446 | break; | |
4447 | ||
4448 | case FC_ELS_LS_RJT: | |
4449 | ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp); | |
4450 | ||
4451 | bfa_trc(port->fcs, ls_rjt->reason_code); | |
4452 | bfa_trc(port->fcs, ls_rjt->reason_code_expl); | |
4453 | ||
4454 | port->stats.ns_rejects++; | |
4455 | ||
4456 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | |
4457 | break; | |
4458 | ||
4459 | default: | |
4460 | port->stats.ns_plogi_unknown_rsp++; | |
4461 | bfa_trc(port->fcs, els_cmd->els_code); | |
4462 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | |
4463 | } | |
4464 | } | |
4465 | ||
ce7242b8 KG |
4466 | /* |
4467 | * Register node name for port_id | |
4468 | */ | |
4469 | static void | |
4470 | bfa_fcs_lport_ns_send_rnn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) | |
4471 | { | |
4472 | struct bfa_fcs_lport_ns_s *ns = ns_cbarg; | |
4473 | struct bfa_fcs_lport_s *port = ns->port; | |
4474 | struct fchs_s fchs; | |
4475 | int len; | |
4476 | struct bfa_fcxp_s *fcxp; | |
4477 | ||
4478 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
4479 | ||
4480 | fcxp = fcxp_alloced ? fcxp_alloced : | |
4481 | bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); | |
4482 | if (!fcxp) { | |
4483 | port->stats.ns_rnnid_alloc_wait++; | |
4484 | bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, | |
4485 | bfa_fcs_lport_ns_send_rnn_id, ns, BFA_TRUE); | |
4486 | return; | |
4487 | } | |
4488 | ||
4489 | ns->fcxp = fcxp; | |
4490 | ||
4491 | len = fc_rnnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | |
4492 | bfa_fcs_lport_get_fcid(port), | |
4493 | bfa_fcs_lport_get_fcid(port), | |
4494 | bfa_fcs_lport_get_nwwn(port)); | |
4495 | ||
4496 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | |
4497 | FC_CLASS_3, len, &fchs, | |
4498 | bfa_fcs_lport_ns_rnn_id_response, (void *)ns, | |
4499 | FC_MAX_PDUSZ, FC_FCCT_TOV); | |
4500 | ||
4501 | port->stats.ns_rnnid_sent++; | |
4502 | bfa_sm_send_event(ns, NSSM_EVENT_RNNID_SENT); | |
4503 | } | |
4504 | ||
4505 | static void | |
4506 | bfa_fcs_lport_ns_rnn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | |
4507 | void *cbarg, bfa_status_t req_status, | |
4508 | u32 rsp_len, u32 resid_len, | |
4509 | struct fchs_s *rsp_fchs) | |
4510 | ||
4511 | { | |
4512 | struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg; | |
4513 | struct bfa_fcs_lport_s *port = ns->port; | |
4514 | struct ct_hdr_s *cthdr = NULL; | |
4515 | ||
4516 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
4517 | ||
4518 | /* | |
4519 | * Sanity Checks | |
4520 | */ | |
4521 | if (req_status != BFA_STATUS_OK) { | |
4522 | bfa_trc(port->fcs, req_status); | |
4523 | port->stats.ns_rnnid_rsp_err++; | |
4524 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | |
4525 | return; | |
4526 | } | |
4527 | ||
4528 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | |
4529 | cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); | |
4530 | ||
4531 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | |
4532 | port->stats.ns_rnnid_accepts++; | |
4533 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); | |
4534 | return; | |
4535 | } | |
4536 | ||
4537 | port->stats.ns_rnnid_rejects++; | |
4538 | bfa_trc(port->fcs, cthdr->reason_code); | |
4539 | bfa_trc(port->fcs, cthdr->exp_code); | |
4540 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | |
4541 | } | |
4542 | ||
4543 | /* | |
4544 | * Register the symbolic node name for a given node name. | |
4545 | */ | |
4546 | static void | |
4547 | bfa_fcs_lport_ns_send_rsnn_nn(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) | |
4548 | { | |
4549 | struct bfa_fcs_lport_ns_s *ns = ns_cbarg; | |
4550 | struct bfa_fcs_lport_s *port = ns->port; | |
4551 | struct fchs_s fchs; | |
4552 | int len; | |
4553 | struct bfa_fcxp_s *fcxp; | |
4554 | u8 *nsymbl; | |
4555 | ||
4556 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
4557 | ||
4558 | fcxp = fcxp_alloced ? fcxp_alloced : | |
4559 | bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); | |
4560 | if (!fcxp) { | |
4561 | port->stats.ns_rsnn_nn_alloc_wait++; | |
4562 | bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, | |
4563 | bfa_fcs_lport_ns_send_rsnn_nn, ns, BFA_TRUE); | |
4564 | return; | |
4565 | } | |
4566 | ns->fcxp = fcxp; | |
4567 | ||
4568 | nsymbl = (u8 *) &(bfa_fcs_lport_get_nsym_name( | |
4569 | bfa_fcs_get_base_port(port->fcs))); | |
4570 | ||
4571 | len = fc_rsnn_nn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | |
4572 | bfa_fcs_lport_get_fcid(port), | |
4573 | bfa_fcs_lport_get_nwwn(port), nsymbl); | |
4574 | ||
4575 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | |
4576 | FC_CLASS_3, len, &fchs, | |
4577 | bfa_fcs_lport_ns_rsnn_nn_response, (void *)ns, | |
4578 | FC_MAX_PDUSZ, FC_FCCT_TOV); | |
4579 | ||
4580 | port->stats.ns_rsnn_nn_sent++; | |
4581 | ||
4582 | bfa_sm_send_event(ns, NSSM_EVENT_RSNN_NN_SENT); | |
4583 | } | |
4584 | ||
4585 | static void | |
4586 | bfa_fcs_lport_ns_rsnn_nn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | |
4587 | void *cbarg, bfa_status_t req_status, | |
4588 | u32 rsp_len, u32 resid_len, | |
4589 | struct fchs_s *rsp_fchs) | |
4590 | { | |
4591 | struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg; | |
4592 | struct bfa_fcs_lport_s *port = ns->port; | |
4593 | struct ct_hdr_s *cthdr = NULL; | |
4594 | ||
4595 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
4596 | ||
4597 | /* | |
4598 | * Sanity Checks | |
4599 | */ | |
4600 | if (req_status != BFA_STATUS_OK) { | |
4601 | bfa_trc(port->fcs, req_status); | |
4602 | port->stats.ns_rsnn_nn_rsp_err++; | |
4603 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | |
4604 | return; | |
4605 | } | |
4606 | ||
4607 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | |
4608 | cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); | |
4609 | ||
4610 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | |
4611 | port->stats.ns_rsnn_nn_accepts++; | |
4612 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); | |
4613 | return; | |
4614 | } | |
4615 | ||
4616 | port->stats.ns_rsnn_nn_rejects++; | |
4617 | bfa_trc(port->fcs, cthdr->reason_code); | |
4618 | bfa_trc(port->fcs, cthdr->exp_code); | |
4619 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | |
4620 | } | |
4621 | ||
5fbe25c7 | 4622 | /* |
a36c61f9 KG |
4623 | * Register the symbolic port name. |
4624 | */ | |
4625 | static void | |
4626 | bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) | |
4627 | { | |
4628 | struct bfa_fcs_lport_ns_s *ns = ns_cbarg; | |
4629 | struct bfa_fcs_lport_s *port = ns->port; | |
4630 | struct fchs_s fchs; | |
4631 | int len; | |
4632 | struct bfa_fcxp_s *fcxp; | |
4633 | u8 symbl[256]; | |
4634 | u8 *psymbl = &symbl[0]; | |
4635 | ||
6a18b167 | 4636 | memset(symbl, 0, sizeof(symbl)); |
a36c61f9 KG |
4637 | |
4638 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
4639 | ||
c3f1b123 KG |
4640 | fcxp = fcxp_alloced ? fcxp_alloced : |
4641 | bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); | |
a36c61f9 KG |
4642 | if (!fcxp) { |
4643 | port->stats.ns_rspnid_alloc_wait++; | |
4644 | bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, | |
c3f1b123 | 4645 | bfa_fcs_lport_ns_send_rspn_id, ns, BFA_TRUE); |
a36c61f9 KG |
4646 | return; |
4647 | } | |
4648 | ns->fcxp = fcxp; | |
4649 | ||
4650 | /* | |
4651 | * for V-Port, form a Port Symbolic Name | |
4652 | */ | |
4653 | if (port->vport) { | |
5fbe25c7 | 4654 | /* |
a36c61f9 KG |
4655 | * For Vports, we append the vport's port symbolic name |
4656 | * to that of the base port. | |
4657 | */ | |
4658 | ||
4659 | strncpy((char *)psymbl, | |
4660 | (char *) & | |
4661 | (bfa_fcs_lport_get_psym_name | |
4662 | (bfa_fcs_get_base_port(port->fcs))), | |
4663 | strlen((char *) & | |
4664 | bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port | |
4665 | (port->fcs)))); | |
4666 | ||
4667 | /* Ensure we have a null terminating string. */ | |
4668 | ((char *)psymbl)[strlen((char *) & | |
4669 | bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port | |
4670 | (port->fcs)))] = 0; | |
4671 | strncat((char *)psymbl, | |
4672 | (char *) &(bfa_fcs_lport_get_psym_name(port)), | |
4673 | strlen((char *) &bfa_fcs_lport_get_psym_name(port))); | |
4674 | } else { | |
4675 | psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port)); | |
4676 | } | |
4677 | ||
4678 | len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | |
4679 | bfa_fcs_lport_get_fcid(port), 0, psymbl); | |
4680 | ||
4681 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | |
4682 | FC_CLASS_3, len, &fchs, | |
4683 | bfa_fcs_lport_ns_rspn_id_response, (void *)ns, | |
4684 | FC_MAX_PDUSZ, FC_FCCT_TOV); | |
4685 | ||
4686 | port->stats.ns_rspnid_sent++; | |
4687 | ||
4688 | bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT); | |
4689 | } | |
4690 | ||
4691 | static void | |
4692 | bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | |
4693 | void *cbarg, bfa_status_t req_status, | |
4694 | u32 rsp_len, u32 resid_len, | |
4695 | struct fchs_s *rsp_fchs) | |
4696 | { | |
4697 | struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg; | |
4698 | struct bfa_fcs_lport_s *port = ns->port; | |
4699 | struct ct_hdr_s *cthdr = NULL; | |
4700 | ||
4701 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
4702 | ||
4703 | /* | |
4704 | * Sanity Checks | |
4705 | */ | |
4706 | if (req_status != BFA_STATUS_OK) { | |
4707 | bfa_trc(port->fcs, req_status); | |
4708 | port->stats.ns_rspnid_rsp_err++; | |
4709 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | |
4710 | return; | |
4711 | } | |
4712 | ||
4713 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | |
ba816ea8 | 4714 | cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); |
a36c61f9 KG |
4715 | |
4716 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | |
4717 | port->stats.ns_rspnid_accepts++; | |
4718 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); | |
4719 | return; | |
4720 | } | |
4721 | ||
4722 | port->stats.ns_rspnid_rejects++; | |
4723 | bfa_trc(port->fcs, cthdr->reason_code); | |
4724 | bfa_trc(port->fcs, cthdr->exp_code); | |
4725 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | |
4726 | } | |
4727 | ||
5fbe25c7 | 4728 | /* |
a36c61f9 KG |
4729 | * Register FC4-Types |
4730 | */ | |
4731 | static void | |
4732 | bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) | |
4733 | { | |
4734 | struct bfa_fcs_lport_ns_s *ns = ns_cbarg; | |
4735 | struct bfa_fcs_lport_s *port = ns->port; | |
4736 | struct fchs_s fchs; | |
4737 | int len; | |
4738 | struct bfa_fcxp_s *fcxp; | |
4739 | ||
4740 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
4741 | ||
c3f1b123 KG |
4742 | fcxp = fcxp_alloced ? fcxp_alloced : |
4743 | bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); | |
a36c61f9 KG |
4744 | if (!fcxp) { |
4745 | port->stats.ns_rftid_alloc_wait++; | |
4746 | bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, | |
c3f1b123 | 4747 | bfa_fcs_lport_ns_send_rft_id, ns, BFA_TRUE); |
a36c61f9 KG |
4748 | return; |
4749 | } | |
4750 | ns->fcxp = fcxp; | |
4751 | ||
4752 | len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | |
4753 | bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.roles); | |
4754 | ||
4755 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | |
4756 | FC_CLASS_3, len, &fchs, | |
4757 | bfa_fcs_lport_ns_rft_id_response, (void *)ns, | |
4758 | FC_MAX_PDUSZ, FC_FCCT_TOV); | |
4759 | ||
4760 | port->stats.ns_rftid_sent++; | |
4761 | bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT); | |
4762 | } | |
4763 | ||
4764 | static void | |
4765 | bfa_fcs_lport_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | |
4766 | void *cbarg, bfa_status_t req_status, | |
4767 | u32 rsp_len, u32 resid_len, | |
4768 | struct fchs_s *rsp_fchs) | |
4769 | { | |
4770 | struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg; | |
4771 | struct bfa_fcs_lport_s *port = ns->port; | |
4772 | struct ct_hdr_s *cthdr = NULL; | |
4773 | ||
4774 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
4775 | ||
4776 | /* | |
4777 | * Sanity Checks | |
4778 | */ | |
4779 | if (req_status != BFA_STATUS_OK) { | |
4780 | bfa_trc(port->fcs, req_status); | |
4781 | port->stats.ns_rftid_rsp_err++; | |
4782 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | |
4783 | return; | |
4784 | } | |
4785 | ||
4786 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | |
ba816ea8 | 4787 | cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); |
a36c61f9 KG |
4788 | |
4789 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | |
4790 | port->stats.ns_rftid_accepts++; | |
4791 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); | |
4792 | return; | |
4793 | } | |
4794 | ||
4795 | port->stats.ns_rftid_rejects++; | |
4796 | bfa_trc(port->fcs, cthdr->reason_code); | |
4797 | bfa_trc(port->fcs, cthdr->exp_code); | |
4798 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | |
4799 | } | |
4800 | ||
5fbe25c7 | 4801 | /* |
a36c61f9 KG |
4802 | * Register FC4-Features : Should be done after RFT_ID |
4803 | */ | |
4804 | static void | |
4805 | bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) | |
4806 | { | |
4807 | struct bfa_fcs_lport_ns_s *ns = ns_cbarg; | |
4808 | struct bfa_fcs_lport_s *port = ns->port; | |
4809 | struct fchs_s fchs; | |
4810 | int len; | |
4811 | struct bfa_fcxp_s *fcxp; | |
4812 | u8 fc4_ftrs = 0; | |
4813 | ||
4814 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
4815 | ||
c3f1b123 KG |
4816 | fcxp = fcxp_alloced ? fcxp_alloced : |
4817 | bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); | |
a36c61f9 KG |
4818 | if (!fcxp) { |
4819 | port->stats.ns_rffid_alloc_wait++; | |
4820 | bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, | |
c3f1b123 | 4821 | bfa_fcs_lport_ns_send_rff_id, ns, BFA_TRUE); |
a36c61f9 KG |
4822 | return; |
4823 | } | |
4824 | ns->fcxp = fcxp; | |
4825 | ||
4826 | if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) | |
4827 | fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR; | |
4828 | ||
4829 | len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | |
4830 | bfa_fcs_lport_get_fcid(port), 0, | |
4831 | FC_TYPE_FCP, fc4_ftrs); | |
4832 | ||
4833 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | |
4834 | FC_CLASS_3, len, &fchs, | |
4835 | bfa_fcs_lport_ns_rff_id_response, (void *)ns, | |
4836 | FC_MAX_PDUSZ, FC_FCCT_TOV); | |
4837 | ||
4838 | port->stats.ns_rffid_sent++; | |
4839 | bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT); | |
4840 | } | |
4841 | ||
4842 | static void | |
4843 | bfa_fcs_lport_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | |
4844 | void *cbarg, bfa_status_t req_status, | |
4845 | u32 rsp_len, u32 resid_len, | |
4846 | struct fchs_s *rsp_fchs) | |
4847 | { | |
4848 | struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg; | |
4849 | struct bfa_fcs_lport_s *port = ns->port; | |
4850 | struct ct_hdr_s *cthdr = NULL; | |
4851 | ||
4852 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
4853 | ||
4854 | /* | |
4855 | * Sanity Checks | |
4856 | */ | |
4857 | if (req_status != BFA_STATUS_OK) { | |
4858 | bfa_trc(port->fcs, req_status); | |
4859 | port->stats.ns_rffid_rsp_err++; | |
4860 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | |
4861 | return; | |
4862 | } | |
4863 | ||
4864 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | |
ba816ea8 | 4865 | cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); |
a36c61f9 KG |
4866 | |
4867 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | |
4868 | port->stats.ns_rffid_accepts++; | |
4869 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); | |
4870 | return; | |
4871 | } | |
4872 | ||
4873 | port->stats.ns_rffid_rejects++; | |
4874 | bfa_trc(port->fcs, cthdr->reason_code); | |
4875 | bfa_trc(port->fcs, cthdr->exp_code); | |
4876 | ||
4877 | if (cthdr->reason_code == CT_RSN_NOT_SUPP) { | |
4878 | /* if this command is not supported, we don't retry */ | |
4879 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); | |
4880 | } else | |
4881 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | |
4882 | } | |
5fbe25c7 | 4883 | /* |
a36c61f9 KG |
4884 | * Query Fabric for FC4-Types Devices. |
4885 | * | |
4886 | * TBD : Need to use a local (FCS private) response buffer, since the response | |
4887 | * can be larger than 2K. | |
4888 | */ | |
4889 | static void | |
4890 | bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) | |
4891 | { | |
4892 | struct bfa_fcs_lport_ns_s *ns = ns_cbarg; | |
4893 | struct bfa_fcs_lport_s *port = ns->port; | |
4894 | struct fchs_s fchs; | |
4895 | int len; | |
4896 | struct bfa_fcxp_s *fcxp; | |
4897 | ||
4898 | bfa_trc(port->fcs, port->pid); | |
4899 | ||
c3f1b123 KG |
4900 | fcxp = fcxp_alloced ? fcxp_alloced : |
4901 | bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); | |
a36c61f9 KG |
4902 | if (!fcxp) { |
4903 | port->stats.ns_gidft_alloc_wait++; | |
4904 | bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, | |
c3f1b123 | 4905 | bfa_fcs_lport_ns_send_gid_ft, ns, BFA_TRUE); |
a36c61f9 KG |
4906 | return; |
4907 | } | |
4908 | ns->fcxp = fcxp; | |
4909 | ||
4910 | /* | |
4911 | * This query is only initiated for FCP initiator mode. | |
4912 | */ | |
4913 | len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | |
4914 | ns->port->pid, FC_TYPE_FCP); | |
4915 | ||
4916 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | |
4917 | FC_CLASS_3, len, &fchs, | |
4918 | bfa_fcs_lport_ns_gid_ft_response, (void *)ns, | |
4919 | bfa_fcxp_get_maxrsp(port->fcs->bfa), FC_FCCT_TOV); | |
4920 | ||
4921 | port->stats.ns_gidft_sent++; | |
4922 | ||
4923 | bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT); | |
4924 | } | |
4925 | ||
4926 | static void | |
4927 | bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | |
4928 | void *cbarg, bfa_status_t req_status, | |
4929 | u32 rsp_len, u32 resid_len, | |
4930 | struct fchs_s *rsp_fchs) | |
4931 | { | |
4932 | struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg; | |
4933 | struct bfa_fcs_lport_s *port = ns->port; | |
4934 | struct ct_hdr_s *cthdr = NULL; | |
4935 | u32 n_pids; | |
4936 | ||
4937 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
4938 | ||
4939 | /* | |
4940 | * Sanity Checks | |
4941 | */ | |
4942 | if (req_status != BFA_STATUS_OK) { | |
4943 | bfa_trc(port->fcs, req_status); | |
4944 | port->stats.ns_gidft_rsp_err++; | |
4945 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | |
4946 | return; | |
4947 | } | |
4948 | ||
4949 | if (resid_len != 0) { | |
4950 | /* | |
4951 | * TBD : we will need to allocate a larger buffer & retry the | |
4952 | * command | |
4953 | */ | |
4954 | bfa_trc(port->fcs, rsp_len); | |
4955 | bfa_trc(port->fcs, resid_len); | |
4956 | return; | |
4957 | } | |
4958 | ||
4959 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | |
ba816ea8 | 4960 | cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); |
a36c61f9 KG |
4961 | |
4962 | switch (cthdr->cmd_rsp_code) { | |
4963 | ||
4964 | case CT_RSP_ACCEPT: | |
4965 | ||
4966 | port->stats.ns_gidft_accepts++; | |
4967 | n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32)); | |
4968 | bfa_trc(port->fcs, n_pids); | |
4969 | bfa_fcs_lport_ns_process_gidft_pids(port, | |
4970 | (u32 *) (cthdr + 1), | |
4971 | n_pids); | |
4972 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); | |
4973 | break; | |
4974 | ||
4975 | case CT_RSP_REJECT: | |
4976 | ||
4977 | /* | |
4978 | * Check the reason code & explanation. | |
4979 | * There may not have been any FC4 devices in the fabric | |
4980 | */ | |
4981 | port->stats.ns_gidft_rejects++; | |
4982 | bfa_trc(port->fcs, cthdr->reason_code); | |
4983 | bfa_trc(port->fcs, cthdr->exp_code); | |
4984 | ||
4985 | if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF) | |
4986 | && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) { | |
4987 | ||
4988 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); | |
4989 | } else { | |
4990 | /* | |
4991 | * for all other errors, retry | |
4992 | */ | |
4993 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | |
4994 | } | |
4995 | break; | |
4996 | ||
4997 | default: | |
4998 | port->stats.ns_gidft_unknown_rsp++; | |
4999 | bfa_trc(port->fcs, cthdr->cmd_rsp_code); | |
5000 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | |
5001 | } | |
5002 | } | |
5003 | ||
5fbe25c7 | 5004 | /* |
a36c61f9 KG |
5005 | * This routine will be called by bfa_timer on timer timeouts. |
5006 | * | |
5007 | * param[in] port - pointer to bfa_fcs_lport_t. | |
5008 | * | |
5009 | * return | |
5010 | * void | |
5011 | * | |
5012 | * Special Considerations: | |
5013 | * | |
5014 | * note | |
5015 | */ | |
5016 | static void | |
5017 | bfa_fcs_lport_ns_timeout(void *arg) | |
5018 | { | |
5019 | struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) arg; | |
5020 | ||
5021 | ns->port->stats.ns_timeouts++; | |
5022 | bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT); | |
5023 | } | |
5024 | ||
5025 | /* | |
5026 | * Process the PID list in GID_FT response | |
5027 | */ | |
5028 | static void | |
5029 | bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf, | |
5030 | u32 n_pids) | |
5031 | { | |
5032 | struct fcgs_gidft_resp_s *gidft_entry; | |
5033 | struct bfa_fcs_rport_s *rport; | |
5034 | u32 ii; | |
61ba4394 KG |
5035 | struct bfa_fcs_fabric_s *fabric = port->fabric; |
5036 | struct bfa_fcs_vport_s *vport; | |
5037 | struct list_head *qe; | |
5038 | u8 found = 0; | |
a36c61f9 KG |
5039 | |
5040 | for (ii = 0; ii < n_pids; ii++) { | |
5041 | gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii]; | |
5042 | ||
5043 | if (gidft_entry->pid == port->pid) | |
5044 | continue; | |
5045 | ||
61ba4394 KG |
5046 | /* |
5047 | * Ignore PID if it is of base port | |
5048 | * (Avoid vports discovering base port as remote port) | |
5049 | */ | |
5050 | if (gidft_entry->pid == fabric->bport.pid) | |
5051 | continue; | |
5052 | ||
5053 | /* | |
5054 | * Ignore PID if it is of vport created on the same base port | |
5055 | * (Avoid vport discovering every other vport created on the | |
5056 | * same port as remote port) | |
5057 | */ | |
5058 | list_for_each(qe, &fabric->vport_q) { | |
5059 | vport = (struct bfa_fcs_vport_s *) qe; | |
5060 | if (vport->lport.pid == gidft_entry->pid) | |
5061 | found = 1; | |
5062 | } | |
5063 | ||
5064 | if (found) { | |
5065 | found = 0; | |
5066 | continue; | |
5067 | } | |
5068 | ||
a36c61f9 KG |
5069 | /* |
5070 | * Check if this rport already exists | |
5071 | */ | |
5072 | rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid); | |
5073 | if (rport == NULL) { | |
5074 | /* | |
5075 | * this is a new device. create rport | |
5076 | */ | |
5077 | rport = bfa_fcs_rport_create(port, gidft_entry->pid); | |
5078 | } else { | |
5079 | /* | |
5080 | * this rport already exists | |
5081 | */ | |
5082 | bfa_fcs_rport_scn(rport); | |
5083 | } | |
5084 | ||
5085 | bfa_trc(port->fcs, gidft_entry->pid); | |
5086 | ||
5087 | /* | |
5088 | * if the last entry bit is set, bail out. | |
5089 | */ | |
5090 | if (gidft_entry->last) | |
5091 | return; | |
5092 | } | |
5093 | } | |
5094 | ||
5fbe25c7 | 5095 | /* |
a36c61f9 KG |
5096 | * fcs_ns_public FCS nameserver public interfaces |
5097 | */ | |
5098 | ||
5099 | /* | |
5100 | * Functions called by port/fab. | |
5101 | * These will send relevant Events to the ns state machine. | |
5102 | */ | |
5103 | void | |
5104 | bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *port) | |
5105 | { | |
5106 | struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port); | |
5107 | ||
5108 | ns->port = port; | |
5109 | bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); | |
5110 | } | |
5111 | ||
5112 | void | |
5113 | bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *port) | |
5114 | { | |
5115 | struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port); | |
5116 | ||
5117 | ns->port = port; | |
5118 | bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE); | |
5119 | } | |
5120 | ||
5121 | void | |
5122 | bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *port) | |
5123 | { | |
5124 | struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port); | |
5125 | ||
5126 | ns->port = port; | |
5127 | bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE); | |
5128 | } | |
5129 | ||
5130 | void | |
5131 | bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port) | |
5132 | { | |
5133 | struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port); | |
5134 | ||
5135 | bfa_trc(port->fcs, port->pid); | |
61ba4394 KG |
5136 | if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_online)) |
5137 | bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY); | |
a36c61f9 KG |
5138 | } |
5139 | ||
52f94b6f | 5140 | static void |
a36c61f9 KG |
5141 | bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port) |
5142 | { | |
5143 | ||
5144 | struct bfa_fcs_rport_s *rport; | |
5145 | u8 nwwns; | |
5146 | wwn_t wwns[BFA_PREBOOT_BOOTLUN_MAX]; | |
5147 | int ii; | |
5148 | ||
5149 | bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns); | |
5150 | ||
5151 | for (ii = 0 ; ii < nwwns; ++ii) { | |
5152 | rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]); | |
d4b671c5 | 5153 | WARN_ON(!rport); |
a36c61f9 KG |
5154 | } |
5155 | } | |
5156 | ||
ebfe8392 KG |
5157 | void |
5158 | bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced) | |
5159 | { | |
5160 | struct bfa_fcs_lport_ns_s *ns = cbarg; | |
5161 | struct bfa_fcs_lport_s *port = ns->port; | |
5162 | struct fchs_s fchs; | |
5163 | struct bfa_fcxp_s *fcxp; | |
5164 | u8 symbl[256]; | |
5165 | u8 *psymbl = &symbl[0]; | |
5166 | int len; | |
5167 | ||
ebfe8392 KG |
5168 | /* Avoid sending RSPN in the following states. */ |
5169 | if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_offline) || | |
5170 | bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_sending) || | |
5171 | bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi) || | |
5172 | bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_retry) || | |
5173 | bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry)) | |
5174 | return; | |
5175 | ||
5176 | memset(symbl, 0, sizeof(symbl)); | |
5177 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
5178 | ||
c3f1b123 KG |
5179 | fcxp = fcxp_alloced ? fcxp_alloced : |
5180 | bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE); | |
ebfe8392 KG |
5181 | if (!fcxp) { |
5182 | port->stats.ns_rspnid_alloc_wait++; | |
5183 | bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, | |
c3f1b123 | 5184 | bfa_fcs_lport_ns_util_send_rspn_id, ns, BFA_FALSE); |
ebfe8392 KG |
5185 | return; |
5186 | } | |
5187 | ||
5188 | ns->fcxp = fcxp; | |
5189 | ||
5190 | if (port->vport) { | |
5191 | /* | |
5192 | * For Vports, we append the vport's port symbolic name | |
5193 | * to that of the base port. | |
5194 | */ | |
5195 | strncpy((char *)psymbl, (char *)&(bfa_fcs_lport_get_psym_name | |
5196 | (bfa_fcs_get_base_port(port->fcs))), | |
5197 | strlen((char *)&bfa_fcs_lport_get_psym_name( | |
5198 | bfa_fcs_get_base_port(port->fcs)))); | |
5199 | ||
5200 | /* Ensure we have a null terminating string. */ | |
5201 | ((char *)psymbl)[strlen((char *)&bfa_fcs_lport_get_psym_name( | |
5202 | bfa_fcs_get_base_port(port->fcs)))] = 0; | |
5203 | ||
5204 | strncat((char *)psymbl, | |
5205 | (char *)&(bfa_fcs_lport_get_psym_name(port)), | |
5206 | strlen((char *)&bfa_fcs_lport_get_psym_name(port))); | |
5207 | } | |
5208 | ||
5209 | len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | |
5210 | bfa_fcs_lport_get_fcid(port), 0, psymbl); | |
5211 | ||
5212 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | |
5213 | FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0); | |
5214 | ||
5215 | port->stats.ns_rspnid_sent++; | |
5216 | } | |
5217 | ||
5fbe25c7 | 5218 | /* |
a36c61f9 KG |
5219 | * FCS SCN |
5220 | */ | |
5221 | ||
5222 | #define FC_QOS_RSCN_EVENT 0x0c | |
5223 | #define FC_FABRIC_NAME_RSCN_EVENT 0x0d | |
5224 | ||
5225 | /* | |
5226 | * forward declarations | |
5227 | */ | |
5228 | static void bfa_fcs_lport_scn_send_scr(void *scn_cbarg, | |
5229 | struct bfa_fcxp_s *fcxp_alloced); | |
5230 | static void bfa_fcs_lport_scn_scr_response(void *fcsarg, | |
5231 | struct bfa_fcxp_s *fcxp, | |
5232 | void *cbarg, | |
5233 | bfa_status_t req_status, | |
5234 | u32 rsp_len, | |
5235 | u32 resid_len, | |
5236 | struct fchs_s *rsp_fchs); | |
5237 | static void bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port, | |
5238 | struct fchs_s *rx_fchs); | |
5239 | static void bfa_fcs_lport_scn_timeout(void *arg); | |
5240 | ||
5fbe25c7 | 5241 | /* |
a36c61f9 KG |
5242 | * fcs_scm_sm FCS SCN state machine |
5243 | */ | |
5244 | ||
5fbe25c7 | 5245 | /* |
a36c61f9 KG |
5246 | * VPort SCN State Machine events |
5247 | */ | |
5248 | enum port_scn_event { | |
5249 | SCNSM_EVENT_PORT_ONLINE = 1, | |
5250 | SCNSM_EVENT_PORT_OFFLINE = 2, | |
5251 | SCNSM_EVENT_RSP_OK = 3, | |
5252 | SCNSM_EVENT_RSP_ERROR = 4, | |
5253 | SCNSM_EVENT_TIMEOUT = 5, | |
5254 | SCNSM_EVENT_SCR_SENT = 6, | |
5255 | }; | |
5256 | ||
5257 | static void bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn, | |
5258 | enum port_scn_event event); | |
5259 | static void bfa_fcs_lport_scn_sm_sending_scr( | |
5260 | struct bfa_fcs_lport_scn_s *scn, | |
5261 | enum port_scn_event event); | |
5262 | static void bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn, | |
5263 | enum port_scn_event event); | |
5264 | static void bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn, | |
5265 | enum port_scn_event event); | |
5266 | static void bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn, | |
5267 | enum port_scn_event event); | |
5268 | ||
5fbe25c7 | 5269 | /* |
a36c61f9 KG |
5270 | * Starting state - awaiting link up. |
5271 | */ | |
5272 | static void | |
5273 | bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn, | |
5274 | enum port_scn_event event) | |
5275 | { | |
5276 | switch (event) { | |
5277 | case SCNSM_EVENT_PORT_ONLINE: | |
5278 | bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr); | |
5279 | bfa_fcs_lport_scn_send_scr(scn, NULL); | |
5280 | break; | |
5281 | ||
5282 | case SCNSM_EVENT_PORT_OFFLINE: | |
5283 | break; | |
5284 | ||
5285 | default: | |
5286 | bfa_sm_fault(scn->port->fcs, event); | |
5287 | } | |
5288 | } | |
5289 | ||
5290 | static void | |
5291 | bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s *scn, | |
5292 | enum port_scn_event event) | |
5293 | { | |
5294 | switch (event) { | |
5295 | case SCNSM_EVENT_SCR_SENT: | |
5296 | bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr); | |
5297 | break; | |
5298 | ||
5299 | case SCNSM_EVENT_PORT_OFFLINE: | |
5300 | bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline); | |
5301 | bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe); | |
5302 | break; | |
5303 | ||
5304 | default: | |
5305 | bfa_sm_fault(scn->port->fcs, event); | |
5306 | } | |
5307 | } | |
5308 | ||
5309 | static void | |
5310 | bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn, | |
5311 | enum port_scn_event event) | |
5312 | { | |
5313 | struct bfa_fcs_lport_s *port = scn->port; | |
5314 | ||
5315 | switch (event) { | |
5316 | case SCNSM_EVENT_RSP_OK: | |
5317 | bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_online); | |
5318 | break; | |
5319 | ||
5320 | case SCNSM_EVENT_RSP_ERROR: | |
5321 | bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr_retry); | |
5322 | bfa_timer_start(port->fcs->bfa, &scn->timer, | |
5323 | bfa_fcs_lport_scn_timeout, scn, | |
5324 | BFA_FCS_RETRY_TIMEOUT); | |
5325 | break; | |
5326 | ||
5327 | case SCNSM_EVENT_PORT_OFFLINE: | |
5328 | bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline); | |
5329 | bfa_fcxp_discard(scn->fcxp); | |
5330 | break; | |
5331 | ||
5332 | default: | |
5333 | bfa_sm_fault(port->fcs, event); | |
5334 | } | |
5335 | } | |
5336 | ||
5337 | static void | |
5338 | bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn, | |
5339 | enum port_scn_event event) | |
5340 | { | |
5341 | switch (event) { | |
5342 | case SCNSM_EVENT_TIMEOUT: | |
5343 | bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr); | |
5344 | bfa_fcs_lport_scn_send_scr(scn, NULL); | |
5345 | break; | |
5346 | ||
5347 | case SCNSM_EVENT_PORT_OFFLINE: | |
5348 | bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline); | |
5349 | bfa_timer_stop(&scn->timer); | |
5350 | break; | |
5351 | ||
5352 | default: | |
5353 | bfa_sm_fault(scn->port->fcs, event); | |
5354 | } | |
5355 | } | |
5356 | ||
5357 | static void | |
5358 | bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn, | |
5359 | enum port_scn_event event) | |
5360 | { | |
5361 | switch (event) { | |
5362 | case SCNSM_EVENT_PORT_OFFLINE: | |
5363 | bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline); | |
5364 | break; | |
5365 | ||
5366 | default: | |
5367 | bfa_sm_fault(scn->port->fcs, event); | |
5368 | } | |
5369 | } | |
5370 | ||
5371 | ||
5372 | ||
5fbe25c7 | 5373 | /* |
a36c61f9 KG |
5374 | * fcs_scn_private FCS SCN private functions |
5375 | */ | |
5376 | ||
5fbe25c7 | 5377 | /* |
a36c61f9 KG |
5378 | * This routine will be called to send a SCR command. |
5379 | */ | |
5380 | static void | |
5381 | bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced) | |
5382 | { | |
5383 | struct bfa_fcs_lport_scn_s *scn = scn_cbarg; | |
5384 | struct bfa_fcs_lport_s *port = scn->port; | |
5385 | struct fchs_s fchs; | |
5386 | int len; | |
5387 | struct bfa_fcxp_s *fcxp; | |
5388 | ||
5389 | bfa_trc(port->fcs, port->pid); | |
5390 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
5391 | ||
c3f1b123 KG |
5392 | fcxp = fcxp_alloced ? fcxp_alloced : |
5393 | bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); | |
a36c61f9 KG |
5394 | if (!fcxp) { |
5395 | bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe, | |
c3f1b123 | 5396 | bfa_fcs_lport_scn_send_scr, scn, BFA_TRUE); |
a36c61f9 KG |
5397 | return; |
5398 | } | |
5399 | scn->fcxp = fcxp; | |
5400 | ||
5401 | /* Handle VU registrations for Base port only */ | |
5402 | if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) { | |
5403 | len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | |
f7f73812 MZ |
5404 | port->fabric->lps->brcd_switch, |
5405 | port->pid, 0); | |
a36c61f9 KG |
5406 | } else { |
5407 | len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | |
5408 | BFA_FALSE, | |
5409 | port->pid, 0); | |
5410 | } | |
5411 | ||
5412 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | |
5413 | FC_CLASS_3, len, &fchs, | |
5414 | bfa_fcs_lport_scn_scr_response, | |
5415 | (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV); | |
5416 | ||
5417 | bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT); | |
5418 | } | |
5419 | ||
5420 | static void | |
5421 | bfa_fcs_lport_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | |
5422 | void *cbarg, bfa_status_t req_status, u32 rsp_len, | |
5423 | u32 resid_len, struct fchs_s *rsp_fchs) | |
5424 | { | |
5425 | struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) cbarg; | |
5426 | struct bfa_fcs_lport_s *port = scn->port; | |
5427 | struct fc_els_cmd_s *els_cmd; | |
5428 | struct fc_ls_rjt_s *ls_rjt; | |
5429 | ||
5430 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
5431 | ||
5432 | /* | |
5433 | * Sanity Checks | |
5434 | */ | |
5435 | if (req_status != BFA_STATUS_OK) { | |
5436 | bfa_trc(port->fcs, req_status); | |
5437 | bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR); | |
5438 | return; | |
5439 | } | |
5440 | ||
5441 | els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp); | |
5442 | ||
5443 | switch (els_cmd->els_code) { | |
5444 | ||
5445 | case FC_ELS_ACC: | |
5446 | bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK); | |
5447 | break; | |
5448 | ||
5449 | case FC_ELS_LS_RJT: | |
5450 | ||
5451 | ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp); | |
5452 | ||
5453 | bfa_trc(port->fcs, ls_rjt->reason_code); | |
5454 | bfa_trc(port->fcs, ls_rjt->reason_code_expl); | |
5455 | ||
5456 | bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR); | |
5457 | break; | |
5458 | ||
5459 | default: | |
5460 | bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR); | |
5461 | } | |
5462 | } | |
5463 | ||
5464 | /* | |
5465 | * Send a LS Accept | |
5466 | */ | |
5467 | static void | |
5468 | bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port, | |
5469 | struct fchs_s *rx_fchs) | |
5470 | { | |
5471 | struct fchs_s fchs; | |
5472 | struct bfa_fcxp_s *fcxp; | |
5473 | struct bfa_rport_s *bfa_rport = NULL; | |
5474 | int len; | |
5475 | ||
5476 | bfa_trc(port->fcs, rx_fchs->s_id); | |
5477 | ||
c3f1b123 | 5478 | fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE); |
a36c61f9 KG |
5479 | if (!fcxp) |
5480 | return; | |
5481 | ||
5482 | len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | |
5483 | rx_fchs->s_id, bfa_fcs_lport_get_fcid(port), | |
5484 | rx_fchs->ox_id); | |
5485 | ||
5486 | bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, | |
5487 | BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, | |
5488 | FC_MAX_PDUSZ, 0); | |
5489 | } | |
5490 | ||
5fbe25c7 | 5491 | /* |
a36c61f9 KG |
5492 | * This routine will be called by bfa_timer on timer timeouts. |
5493 | * | |
5494 | * param[in] vport - pointer to bfa_fcs_lport_t. | |
5495 | * param[out] vport_status - pointer to return vport status in | |
5496 | * | |
5497 | * return | |
5498 | * void | |
5499 | * | |
5500 | * Special Considerations: | |
5501 | * | |
5502 | * note | |
5503 | */ | |
5504 | static void | |
5505 | bfa_fcs_lport_scn_timeout(void *arg) | |
5506 | { | |
5507 | struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) arg; | |
5508 | ||
5509 | bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT); | |
5510 | } | |
5511 | ||
5512 | ||
5513 | ||
5fbe25c7 | 5514 | /* |
a36c61f9 KG |
5515 | * fcs_scn_public FCS state change notification public interfaces |
5516 | */ | |
5517 | ||
5518 | /* | |
5519 | * Functions called by port/fab | |
5520 | */ | |
5521 | void | |
5522 | bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *port) | |
5523 | { | |
5524 | struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port); | |
5525 | ||
5526 | scn->port = port; | |
5527 | bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline); | |
5528 | } | |
5529 | ||
5530 | void | |
5531 | bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port) | |
5532 | { | |
5533 | struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port); | |
5534 | ||
5535 | scn->port = port; | |
5536 | bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE); | |
5537 | } | |
5538 | ||
5539 | void | |
bc0e2c2a | 5540 | bfa_fcs_lport_fab_scn_online(struct bfa_fcs_lport_s *port) |
a36c61f9 KG |
5541 | { |
5542 | struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port); | |
5543 | ||
5544 | scn->port = port; | |
5545 | bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE); | |
5546 | } | |
5547 | ||
5548 | static void | |
5549 | bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid) | |
5550 | { | |
5551 | struct bfa_fcs_rport_s *rport; | |
61ba4394 KG |
5552 | struct bfa_fcs_fabric_s *fabric = port->fabric; |
5553 | struct bfa_fcs_vport_s *vport; | |
5554 | struct list_head *qe; | |
a36c61f9 KG |
5555 | |
5556 | bfa_trc(port->fcs, rpid); | |
5557 | ||
61ba4394 KG |
5558 | /* |
5559 | * Ignore PID if it is of base port or of vports created on the | |
5560 | * same base port. It is to avoid vports discovering base port or | |
5561 | * other vports created on same base port as remote port | |
5562 | */ | |
5563 | if (rpid == fabric->bport.pid) | |
5564 | return; | |
5565 | ||
5566 | list_for_each(qe, &fabric->vport_q) { | |
5567 | vport = (struct bfa_fcs_vport_s *) qe; | |
5568 | if (vport->lport.pid == rpid) | |
5569 | return; | |
5570 | } | |
5fbe25c7 | 5571 | /* |
a36c61f9 KG |
5572 | * If this is an unknown device, then it just came online. |
5573 | * Otherwise let rport handle the RSCN event. | |
5574 | */ | |
5575 | rport = bfa_fcs_lport_get_rport_by_pid(port, rpid); | |
ee1a4a42 KG |
5576 | if (!rport) |
5577 | rport = bfa_fcs_lport_get_rport_by_old_pid(port, rpid); | |
5578 | ||
a36c61f9 KG |
5579 | if (rport == NULL) { |
5580 | /* | |
5581 | * If min cfg mode is enabled, we donot need to | |
5582 | * discover any new rports. | |
5583 | */ | |
5584 | if (!__fcs_min_cfg(port->fcs)) | |
5585 | rport = bfa_fcs_rport_create(port, rpid); | |
5586 | } else | |
5587 | bfa_fcs_rport_scn(rport); | |
5588 | } | |
5589 | ||
5fbe25c7 | 5590 | /* |
a36c61f9 KG |
5591 | * rscn format based PID comparison |
5592 | */ | |
5593 | #define __fc_pid_match(__c0, __c1, __fmt) \ | |
5594 | (((__fmt) == FC_RSCN_FORMAT_FABRIC) || \ | |
5595 | (((__fmt) == FC_RSCN_FORMAT_DOMAIN) && \ | |
5596 | ((__c0)[0] == (__c1)[0])) || \ | |
5597 | (((__fmt) == FC_RSCN_FORMAT_AREA) && \ | |
5598 | ((__c0)[0] == (__c1)[0]) && \ | |
5599 | ((__c0)[1] == (__c1)[1]))) | |
5600 | ||
5601 | static void | |
5602 | bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s *port, | |
5603 | enum fc_rscn_format format, | |
5604 | u32 rscn_pid) | |
5605 | { | |
5606 | struct bfa_fcs_rport_s *rport; | |
5607 | struct list_head *qe, *qe_next; | |
5608 | u8 *c0, *c1; | |
5609 | ||
5610 | bfa_trc(port->fcs, format); | |
5611 | bfa_trc(port->fcs, rscn_pid); | |
5612 | ||
5613 | c0 = (u8 *) &rscn_pid; | |
5614 | ||
5615 | list_for_each_safe(qe, qe_next, &port->rport_q) { | |
5616 | rport = (struct bfa_fcs_rport_s *) qe; | |
5617 | c1 = (u8 *) &rport->pid; | |
5618 | if (__fc_pid_match(c0, c1, format)) | |
5619 | bfa_fcs_rport_scn(rport); | |
5620 | } | |
5621 | } | |
5622 | ||
5623 | ||
5624 | void | |
5625 | bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port, | |
5626 | struct fchs_s *fchs, u32 len) | |
5627 | { | |
5628 | struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1); | |
5629 | int num_entries; | |
5630 | u32 rscn_pid; | |
5631 | bfa_boolean_t nsquery = BFA_FALSE, found; | |
5632 | int i = 0, j; | |
5633 | ||
5634 | num_entries = | |
ba816ea8 | 5635 | (be16_to_cpu(rscn->payldlen) - |
a36c61f9 KG |
5636 | sizeof(u32)) / sizeof(rscn->event[0]); |
5637 | ||
5638 | bfa_trc(port->fcs, num_entries); | |
5639 | ||
5640 | port->stats.num_rscn++; | |
5641 | ||
5642 | bfa_fcs_lport_scn_send_ls_acc(port, fchs); | |
5643 | ||
5644 | for (i = 0; i < num_entries; i++) { | |
5645 | rscn_pid = rscn->event[i].portid; | |
5646 | ||
5647 | bfa_trc(port->fcs, rscn->event[i].format); | |
5648 | bfa_trc(port->fcs, rscn_pid); | |
5649 | ||
5650 | /* check for duplicate entries in the list */ | |
5651 | found = BFA_FALSE; | |
5652 | for (j = 0; j < i; j++) { | |
5653 | if (rscn->event[j].portid == rscn_pid) { | |
5654 | found = BFA_TRUE; | |
5655 | break; | |
5656 | } | |
5657 | } | |
5658 | ||
5659 | /* if found in down the list, pid has been already processed */ | |
5660 | if (found) { | |
5661 | bfa_trc(port->fcs, rscn_pid); | |
5662 | continue; | |
5663 | } | |
5664 | ||
5665 | switch (rscn->event[i].format) { | |
5666 | case FC_RSCN_FORMAT_PORTID: | |
5667 | if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) { | |
5668 | /* | |
5669 | * Ignore this event. | |
5670 | * f/w would have processed it | |
5671 | */ | |
5672 | bfa_trc(port->fcs, rscn_pid); | |
5673 | } else { | |
5674 | port->stats.num_portid_rscn++; | |
5675 | bfa_fcs_lport_scn_portid_rscn(port, rscn_pid); | |
5676 | } | |
5677 | break; | |
5678 | ||
5679 | case FC_RSCN_FORMAT_FABRIC: | |
5680 | if (rscn->event[i].qualifier == | |
5681 | FC_FABRIC_NAME_RSCN_EVENT) { | |
5682 | bfa_fcs_lport_ms_fabric_rscn(port); | |
5683 | break; | |
5684 | } | |
5685 | /* !!!!!!!!! Fall Through !!!!!!!!!!!!! */ | |
5686 | ||
5687 | case FC_RSCN_FORMAT_AREA: | |
5688 | case FC_RSCN_FORMAT_DOMAIN: | |
5689 | nsquery = BFA_TRUE; | |
5690 | bfa_fcs_lport_scn_multiport_rscn(port, | |
5691 | rscn->event[i].format, | |
5692 | rscn_pid); | |
5693 | break; | |
5694 | ||
5695 | ||
5696 | default: | |
d4b671c5 | 5697 | WARN_ON(1); |
a36c61f9 KG |
5698 | nsquery = BFA_TRUE; |
5699 | } | |
5700 | } | |
5701 | ||
5fbe25c7 JH |
5702 | /* |
5703 | * If any of area, domain or fabric RSCN is received, do a fresh | |
5704 | * discovery to find new devices. | |
a36c61f9 KG |
5705 | */ |
5706 | if (nsquery) | |
5707 | bfa_fcs_lport_ns_query(port); | |
5708 | } | |
5709 | ||
5fbe25c7 | 5710 | /* |
a36c61f9 KG |
5711 | * BFA FCS port |
5712 | */ | |
5fbe25c7 | 5713 | /* |
a36c61f9 KG |
5714 | * fcs_port_api BFA FCS port API |
5715 | */ | |
5716 | struct bfa_fcs_lport_s * | |
5717 | bfa_fcs_get_base_port(struct bfa_fcs_s *fcs) | |
5718 | { | |
5719 | return &fcs->fabric.bport; | |
5720 | } | |
5721 | ||
5722 | wwn_t | |
5723 | bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index, | |
5724 | int nrports, bfa_boolean_t bwwn) | |
5725 | { | |
5726 | struct list_head *qh, *qe; | |
5727 | struct bfa_fcs_rport_s *rport = NULL; | |
5728 | int i; | |
5729 | struct bfa_fcs_s *fcs; | |
5730 | ||
5731 | if (port == NULL || nrports == 0) | |
5732 | return (wwn_t) 0; | |
5733 | ||
5734 | fcs = port->fcs; | |
5735 | bfa_trc(fcs, (u32) nrports); | |
5736 | ||
5737 | i = 0; | |
5738 | qh = &port->rport_q; | |
5739 | qe = bfa_q_first(qh); | |
5740 | ||
5741 | while ((qe != qh) && (i < nrports)) { | |
5742 | rport = (struct bfa_fcs_rport_s *) qe; | |
f16a1750 | 5743 | if (bfa_ntoh3b(rport->pid) > 0xFFF000) { |
a36c61f9 KG |
5744 | qe = bfa_q_next(qe); |
5745 | bfa_trc(fcs, (u32) rport->pwwn); | |
5746 | bfa_trc(fcs, rport->pid); | |
5747 | bfa_trc(fcs, i); | |
5748 | continue; | |
5749 | } | |
5750 | ||
5751 | if (bwwn) { | |
5752 | if (!memcmp(&wwn, &rport->pwwn, 8)) | |
5753 | break; | |
5754 | } else { | |
5755 | if (i == index) | |
5756 | break; | |
5757 | } | |
5758 | ||
5759 | i++; | |
5760 | qe = bfa_q_next(qe); | |
5761 | } | |
5762 | ||
5763 | bfa_trc(fcs, i); | |
5764 | if (rport) | |
5765 | return rport->pwwn; | |
5766 | else | |
5767 | return (wwn_t) 0; | |
5768 | } | |
5769 | ||
5770 | void | |
ee1a4a42 KG |
5771 | bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s *port, |
5772 | struct bfa_rport_qualifier_s rports[], int *nrports) | |
a36c61f9 KG |
5773 | { |
5774 | struct list_head *qh, *qe; | |
5775 | struct bfa_fcs_rport_s *rport = NULL; | |
5776 | int i; | |
5777 | struct bfa_fcs_s *fcs; | |
5778 | ||
ee1a4a42 | 5779 | if (port == NULL || rports == NULL || *nrports == 0) |
a36c61f9 KG |
5780 | return; |
5781 | ||
5782 | fcs = port->fcs; | |
5783 | bfa_trc(fcs, (u32) *nrports); | |
5784 | ||
5785 | i = 0; | |
5786 | qh = &port->rport_q; | |
5787 | qe = bfa_q_first(qh); | |
5788 | ||
5789 | while ((qe != qh) && (i < *nrports)) { | |
5790 | rport = (struct bfa_fcs_rport_s *) qe; | |
f16a1750 | 5791 | if (bfa_ntoh3b(rport->pid) > 0xFFF000) { |
a36c61f9 KG |
5792 | qe = bfa_q_next(qe); |
5793 | bfa_trc(fcs, (u32) rport->pwwn); | |
5794 | bfa_trc(fcs, rport->pid); | |
5795 | bfa_trc(fcs, i); | |
5796 | continue; | |
5797 | } | |
5798 | ||
ee1a4a42 KG |
5799 | if (!rport->pwwn && !rport->pid) { |
5800 | qe = bfa_q_next(qe); | |
5801 | continue; | |
5802 | } | |
5803 | ||
5804 | rports[i].pwwn = rport->pwwn; | |
5805 | rports[i].pid = rport->pid; | |
a36c61f9 KG |
5806 | |
5807 | i++; | |
5808 | qe = bfa_q_next(qe); | |
5809 | } | |
5810 | ||
5811 | bfa_trc(fcs, i); | |
5812 | *nrports = i; | |
5813 | } | |
5814 | ||
5815 | /* | |
5816 | * Iterate's through all the rport's in the given port to | |
5817 | * determine the maximum operating speed. | |
5818 | * | |
5819 | * !!!! To be used in TRL Functionality only !!!! | |
5820 | */ | |
5821 | bfa_port_speed_t | |
5822 | bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port) | |
5823 | { | |
5824 | struct list_head *qh, *qe; | |
5825 | struct bfa_fcs_rport_s *rport = NULL; | |
5826 | struct bfa_fcs_s *fcs; | |
5827 | bfa_port_speed_t max_speed = 0; | |
5828 | struct bfa_port_attr_s port_attr; | |
5829 | bfa_port_speed_t port_speed, rport_speed; | |
5f6ac2ce | 5830 | bfa_boolean_t trl_enabled; |
a36c61f9 KG |
5831 | |
5832 | if (port == NULL) | |
5833 | return 0; | |
5834 | ||
5835 | fcs = port->fcs; | |
5f6ac2ce | 5836 | trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa); |
a36c61f9 KG |
5837 | |
5838 | /* Get Physical port's current speed */ | |
5839 | bfa_fcport_get_attr(port->fcs->bfa, &port_attr); | |
5840 | port_speed = port_attr.speed; | |
5841 | bfa_trc(fcs, port_speed); | |
5842 | ||
5843 | qh = &port->rport_q; | |
5844 | qe = bfa_q_first(qh); | |
5845 | ||
5846 | while (qe != qh) { | |
5847 | rport = (struct bfa_fcs_rport_s *) qe; | |
f16a1750 | 5848 | if ((bfa_ntoh3b(rport->pid) > 0xFFF000) || |
d7be54cc KG |
5849 | (bfa_fcs_rport_get_state(rport) == BFA_RPORT_OFFLINE) || |
5850 | (rport->scsi_function != BFA_RPORT_TARGET)) { | |
a36c61f9 KG |
5851 | qe = bfa_q_next(qe); |
5852 | continue; | |
5853 | } | |
5854 | ||
5855 | rport_speed = rport->rpf.rpsc_speed; | |
5856 | if ((trl_enabled) && (rport_speed == | |
5857 | BFA_PORT_SPEED_UNKNOWN)) { | |
5858 | /* Use default ratelim speed setting */ | |
5859 | rport_speed = | |
5860 | bfa_fcport_get_ratelim_speed(port->fcs->bfa); | |
5861 | } | |
5862 | ||
d7be54cc | 5863 | if (rport_speed > max_speed) |
a36c61f9 | 5864 | max_speed = rport_speed; |
a36c61f9 KG |
5865 | |
5866 | qe = bfa_q_next(qe); | |
5867 | } | |
5868 | ||
d7be54cc KG |
5869 | if (max_speed > port_speed) |
5870 | max_speed = port_speed; | |
5871 | ||
a36c61f9 KG |
5872 | bfa_trc(fcs, max_speed); |
5873 | return max_speed; | |
5874 | } | |
5875 | ||
5876 | struct bfa_fcs_lport_s * | |
5877 | bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn) | |
5878 | { | |
5879 | struct bfa_fcs_vport_s *vport; | |
5880 | bfa_fcs_vf_t *vf; | |
5881 | ||
d4b671c5 | 5882 | WARN_ON(fcs == NULL); |
a36c61f9 KG |
5883 | |
5884 | vf = bfa_fcs_vf_lookup(fcs, vf_id); | |
5885 | if (vf == NULL) { | |
5886 | bfa_trc(fcs, vf_id); | |
5887 | return NULL; | |
5888 | } | |
5889 | ||
5890 | if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn)) | |
5891 | return &vf->bport; | |
5892 | ||
5893 | vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn); | |
5894 | if (vport) | |
5895 | return &vport->lport; | |
5896 | ||
5897 | return NULL; | |
5898 | } | |
5899 | ||
5900 | /* | |
5901 | * API corresponding to NPIV_VPORT_GETINFO. | |
5902 | */ | |
5903 | void | |
5904 | bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port, | |
5905 | struct bfa_lport_info_s *port_info) | |
5906 | { | |
5907 | ||
5908 | bfa_trc(port->fcs, port->fabric->fabric_name); | |
5909 | ||
5910 | if (port->vport == NULL) { | |
5911 | /* | |
5912 | * This is a Physical port | |
5913 | */ | |
5914 | port_info->port_type = BFA_LPORT_TYPE_PHYSICAL; | |
5915 | ||
5916 | /* | |
5917 | * @todo : need to fix the state & reason | |
5918 | */ | |
5919 | port_info->port_state = 0; | |
5920 | port_info->offline_reason = 0; | |
5921 | ||
5922 | port_info->port_wwn = bfa_fcs_lport_get_pwwn(port); | |
5923 | port_info->node_wwn = bfa_fcs_lport_get_nwwn(port); | |
5924 | ||
5925 | port_info->max_vports_supp = | |
5926 | bfa_lps_get_max_vport(port->fcs->bfa); | |
5927 | port_info->num_vports_inuse = | |
f7f73812 | 5928 | port->fabric->num_vports; |
a36c61f9 KG |
5929 | port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP; |
5930 | port_info->num_rports_inuse = port->num_rports; | |
5931 | } else { | |
5932 | /* | |
5933 | * This is a virtual port | |
5934 | */ | |
5935 | port_info->port_type = BFA_LPORT_TYPE_VIRTUAL; | |
5936 | ||
5937 | /* | |
5938 | * @todo : need to fix the state & reason | |
5939 | */ | |
5940 | port_info->port_state = 0; | |
5941 | port_info->offline_reason = 0; | |
5942 | ||
5943 | port_info->port_wwn = bfa_fcs_lport_get_pwwn(port); | |
5944 | port_info->node_wwn = bfa_fcs_lport_get_nwwn(port); | |
5945 | } | |
5946 | } | |
5947 | ||
5948 | void | |
5949 | bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port, | |
5950 | struct bfa_lport_stats_s *port_stats) | |
5951 | { | |
5952 | *port_stats = fcs_port->stats; | |
5953 | } | |
5954 | ||
5955 | void | |
5956 | bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port) | |
5957 | { | |
6a18b167 | 5958 | memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s)); |
a36c61f9 KG |
5959 | } |
5960 | ||
bc0e2c2a KG |
5961 | /* |
5962 | * Let new loop map create missing rports | |
5963 | */ | |
5964 | void | |
5965 | bfa_fcs_lport_lip_scn_online(struct bfa_fcs_lport_s *port) | |
5966 | { | |
5967 | bfa_fcs_lport_loop_online(port); | |
5968 | } | |
5969 | ||
5fbe25c7 | 5970 | /* |
a36c61f9 KG |
5971 | * FCS virtual port state machine |
5972 | */ | |
5973 | ||
5974 | #define __vport_fcs(__vp) ((__vp)->lport.fcs) | |
5975 | #define __vport_pwwn(__vp) ((__vp)->lport.port_cfg.pwwn) | |
5976 | #define __vport_nwwn(__vp) ((__vp)->lport.port_cfg.nwwn) | |
5977 | #define __vport_bfa(__vp) ((__vp)->lport.fcs->bfa) | |
5978 | #define __vport_fcid(__vp) ((__vp)->lport.pid) | |
5979 | #define __vport_fabric(__vp) ((__vp)->lport.fabric) | |
5980 | #define __vport_vfid(__vp) ((__vp)->lport.fabric->vf_id) | |
5981 | ||
5982 | #define BFA_FCS_VPORT_MAX_RETRIES 5 | |
5983 | /* | |
5984 | * Forward declarations | |
5985 | */ | |
5986 | static void bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport); | |
5987 | static void bfa_fcs_vport_timeout(void *vport_arg); | |
5988 | static void bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport); | |
5989 | static void bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport); | |
5990 | ||
5fbe25c7 | 5991 | /* |
a36c61f9 KG |
5992 | * fcs_vport_sm FCS virtual port state machine |
5993 | */ | |
5994 | ||
5fbe25c7 | 5995 | /* |
a36c61f9 KG |
5996 | * VPort State Machine events |
5997 | */ | |
5998 | enum bfa_fcs_vport_event { | |
5999 | BFA_FCS_VPORT_SM_CREATE = 1, /* vport create event */ | |
6000 | BFA_FCS_VPORT_SM_DELETE = 2, /* vport delete event */ | |
6001 | BFA_FCS_VPORT_SM_START = 3, /* vport start request */ | |
6002 | BFA_FCS_VPORT_SM_STOP = 4, /* stop: unsupported */ | |
6003 | BFA_FCS_VPORT_SM_ONLINE = 5, /* fabric online */ | |
6004 | BFA_FCS_VPORT_SM_OFFLINE = 6, /* fabric offline event */ | |
6005 | BFA_FCS_VPORT_SM_FRMSENT = 7, /* fdisc/logo sent events */ | |
6006 | BFA_FCS_VPORT_SM_RSP_OK = 8, /* good response */ | |
6007 | BFA_FCS_VPORT_SM_RSP_ERROR = 9, /* error/bad response */ | |
6008 | BFA_FCS_VPORT_SM_TIMEOUT = 10, /* delay timer event */ | |
6009 | BFA_FCS_VPORT_SM_DELCOMP = 11, /* lport delete completion */ | |
6010 | BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12, /* Dup wnn error*/ | |
6011 | BFA_FCS_VPORT_SM_RSP_FAILED = 13, /* non-retryable failure */ | |
dd5aaf45 | 6012 | BFA_FCS_VPORT_SM_STOPCOMP = 14, /* vport delete completion */ |
f2a0cc3f | 6013 | BFA_FCS_VPORT_SM_FABRIC_MAX = 15, /* max vports on fabric */ |
a36c61f9 KG |
6014 | }; |
6015 | ||
6016 | static void bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport, | |
6017 | enum bfa_fcs_vport_event event); | |
6018 | static void bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport, | |
6019 | enum bfa_fcs_vport_event event); | |
6020 | static void bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport, | |
6021 | enum bfa_fcs_vport_event event); | |
6022 | static void bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport, | |
6023 | enum bfa_fcs_vport_event event); | |
6024 | static void bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport, | |
6025 | enum bfa_fcs_vport_event event); | |
d7be54cc KG |
6026 | static void bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport, |
6027 | enum bfa_fcs_vport_event event); | |
a36c61f9 KG |
6028 | static void bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport, |
6029 | enum bfa_fcs_vport_event event); | |
6030 | static void bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport, | |
6031 | enum bfa_fcs_vport_event event); | |
6032 | static void bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport, | |
6033 | enum bfa_fcs_vport_event event); | |
6034 | static void bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport, | |
6035 | enum bfa_fcs_vport_event event); | |
6036 | static void bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport, | |
6037 | enum bfa_fcs_vport_event event); | |
dd5aaf45 KG |
6038 | static void bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport, |
6039 | enum bfa_fcs_vport_event event); | |
6040 | static void bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport, | |
6041 | enum bfa_fcs_vport_event event); | |
a36c61f9 KG |
6042 | |
6043 | static struct bfa_sm_table_s vport_sm_table[] = { | |
6044 | {BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT}, | |
6045 | {BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED}, | |
6046 | {BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE}, | |
6047 | {BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC}, | |
6048 | {BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY}, | |
d7be54cc | 6049 | {BFA_SM(bfa_fcs_vport_sm_fdisc_rsp_wait), BFA_FCS_VPORT_FDISC_RSP_WAIT}, |
a36c61f9 KG |
6050 | {BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE}, |
6051 | {BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING}, | |
6052 | {BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP}, | |
6053 | {BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO}, | |
6054 | {BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR} | |
6055 | }; | |
6056 | ||
5fbe25c7 | 6057 | /* |
a36c61f9 KG |
6058 | * Beginning state. |
6059 | */ | |
6060 | static void | |
6061 | bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport, | |
6062 | enum bfa_fcs_vport_event event) | |
6063 | { | |
6064 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | |
6065 | bfa_trc(__vport_fcs(vport), event); | |
6066 | ||
6067 | switch (event) { | |
6068 | case BFA_FCS_VPORT_SM_CREATE: | |
6069 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_created); | |
6070 | bfa_fcs_fabric_addvport(__vport_fabric(vport), vport); | |
6071 | break; | |
6072 | ||
6073 | default: | |
6074 | bfa_sm_fault(__vport_fcs(vport), event); | |
6075 | } | |
6076 | } | |
6077 | ||
5fbe25c7 | 6078 | /* |
a36c61f9 KG |
6079 | * Created state - a start event is required to start up the state machine. |
6080 | */ | |
6081 | static void | |
6082 | bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport, | |
6083 | enum bfa_fcs_vport_event event) | |
6084 | { | |
6085 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | |
6086 | bfa_trc(__vport_fcs(vport), event); | |
6087 | ||
6088 | switch (event) { | |
6089 | case BFA_FCS_VPORT_SM_START: | |
f7f73812 MZ |
6090 | if (bfa_sm_cmp_state(__vport_fabric(vport), |
6091 | bfa_fcs_fabric_sm_online) | |
a36c61f9 KG |
6092 | && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) { |
6093 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); | |
6094 | bfa_fcs_vport_do_fdisc(vport); | |
6095 | } else { | |
5fbe25c7 | 6096 | /* |
a36c61f9 KG |
6097 | * Fabric is offline or not NPIV capable, stay in |
6098 | * offline state. | |
6099 | */ | |
6100 | vport->vport_stats.fab_no_npiv++; | |
6101 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); | |
6102 | } | |
6103 | break; | |
6104 | ||
6105 | case BFA_FCS_VPORT_SM_DELETE: | |
6106 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); | |
6107 | bfa_fcs_lport_delete(&vport->lport); | |
6108 | break; | |
6109 | ||
6110 | case BFA_FCS_VPORT_SM_ONLINE: | |
6111 | case BFA_FCS_VPORT_SM_OFFLINE: | |
5fbe25c7 | 6112 | /* |
a36c61f9 KG |
6113 | * Ignore ONLINE/OFFLINE events from fabric |
6114 | * till vport is started. | |
6115 | */ | |
6116 | break; | |
6117 | ||
6118 | default: | |
6119 | bfa_sm_fault(__vport_fcs(vport), event); | |
6120 | } | |
6121 | } | |
6122 | ||
5fbe25c7 | 6123 | /* |
a36c61f9 KG |
6124 | * Offline state - awaiting ONLINE event from fabric SM. |
6125 | */ | |
6126 | static void | |
6127 | bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport, | |
6128 | enum bfa_fcs_vport_event event) | |
6129 | { | |
6130 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | |
6131 | bfa_trc(__vport_fcs(vport), event); | |
6132 | ||
6133 | switch (event) { | |
6134 | case BFA_FCS_VPORT_SM_DELETE: | |
6135 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); | |
6136 | bfa_fcs_lport_delete(&vport->lport); | |
6137 | break; | |
6138 | ||
6139 | case BFA_FCS_VPORT_SM_ONLINE: | |
6140 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); | |
6141 | vport->fdisc_retries = 0; | |
6142 | bfa_fcs_vport_do_fdisc(vport); | |
6143 | break; | |
6144 | ||
dd5aaf45 KG |
6145 | case BFA_FCS_VPORT_SM_STOP: |
6146 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); | |
6147 | bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP); | |
6148 | break; | |
6149 | ||
a36c61f9 KG |
6150 | case BFA_FCS_VPORT_SM_OFFLINE: |
6151 | /* | |
6152 | * This can happen if the vport couldn't be initialzied | |
6153 | * due the fact that the npiv was not enabled on the switch. | |
6154 | * In that case we will put the vport in offline state. | |
6155 | * However, the link can go down and cause the this event to | |
6156 | * be sent when we are already offline. Ignore it. | |
6157 | */ | |
6158 | break; | |
6159 | ||
6160 | default: | |
6161 | bfa_sm_fault(__vport_fcs(vport), event); | |
6162 | } | |
6163 | } | |
6164 | ||
6165 | ||
5fbe25c7 | 6166 | /* |
a36c61f9 KG |
6167 | * FDISC is sent and awaiting reply from fabric. |
6168 | */ | |
6169 | static void | |
6170 | bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport, | |
6171 | enum bfa_fcs_vport_event event) | |
6172 | { | |
6173 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | |
6174 | bfa_trc(__vport_fcs(vport), event); | |
6175 | ||
6176 | switch (event) { | |
6177 | case BFA_FCS_VPORT_SM_DELETE: | |
d7be54cc | 6178 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_rsp_wait); |
a36c61f9 KG |
6179 | break; |
6180 | ||
6181 | case BFA_FCS_VPORT_SM_OFFLINE: | |
6182 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); | |
f7f73812 | 6183 | bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE); |
a36c61f9 KG |
6184 | break; |
6185 | ||
6186 | case BFA_FCS_VPORT_SM_RSP_OK: | |
6187 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_online); | |
6188 | bfa_fcs_lport_online(&vport->lport); | |
6189 | break; | |
6190 | ||
6191 | case BFA_FCS_VPORT_SM_RSP_ERROR: | |
6192 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry); | |
6193 | bfa_timer_start(__vport_bfa(vport), &vport->timer, | |
6194 | bfa_fcs_vport_timeout, vport, | |
6195 | BFA_FCS_RETRY_TIMEOUT); | |
6196 | break; | |
6197 | ||
6198 | case BFA_FCS_VPORT_SM_RSP_FAILED: | |
f2a0cc3f | 6199 | case BFA_FCS_VPORT_SM_FABRIC_MAX: |
a36c61f9 KG |
6200 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); |
6201 | break; | |
6202 | ||
6203 | case BFA_FCS_VPORT_SM_RSP_DUP_WWN: | |
6204 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_error); | |
6205 | break; | |
6206 | ||
6207 | default: | |
6208 | bfa_sm_fault(__vport_fcs(vport), event); | |
6209 | } | |
6210 | } | |
6211 | ||
5fbe25c7 | 6212 | /* |
a36c61f9 KG |
6213 | * FDISC attempt failed - a timer is active to retry FDISC. |
6214 | */ | |
6215 | static void | |
6216 | bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport, | |
6217 | enum bfa_fcs_vport_event event) | |
6218 | { | |
6219 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | |
6220 | bfa_trc(__vport_fcs(vport), event); | |
6221 | ||
6222 | switch (event) { | |
6223 | case BFA_FCS_VPORT_SM_DELETE: | |
6224 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); | |
6225 | bfa_timer_stop(&vport->timer); | |
6226 | bfa_fcs_lport_delete(&vport->lport); | |
6227 | break; | |
6228 | ||
6229 | case BFA_FCS_VPORT_SM_OFFLINE: | |
6230 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); | |
6231 | bfa_timer_stop(&vport->timer); | |
6232 | break; | |
6233 | ||
6234 | case BFA_FCS_VPORT_SM_TIMEOUT: | |
6235 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); | |
6236 | vport->vport_stats.fdisc_retries++; | |
6237 | vport->fdisc_retries++; | |
6238 | bfa_fcs_vport_do_fdisc(vport); | |
6239 | break; | |
6240 | ||
6241 | default: | |
6242 | bfa_sm_fault(__vport_fcs(vport), event); | |
6243 | } | |
6244 | } | |
6245 | ||
d7be54cc KG |
6246 | /* |
6247 | * FDISC is in progress and we got a vport delete request - | |
6248 | * this is a wait state while we wait for fdisc response and | |
6249 | * we will transition to the appropriate state - on rsp status. | |
6250 | */ | |
6251 | static void | |
6252 | bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport, | |
6253 | enum bfa_fcs_vport_event event) | |
6254 | { | |
6255 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | |
6256 | bfa_trc(__vport_fcs(vport), event); | |
6257 | ||
6258 | switch (event) { | |
6259 | case BFA_FCS_VPORT_SM_RSP_OK: | |
6260 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting); | |
6261 | bfa_fcs_lport_delete(&vport->lport); | |
6262 | break; | |
6263 | ||
6264 | case BFA_FCS_VPORT_SM_DELETE: | |
6265 | break; | |
6266 | ||
6267 | case BFA_FCS_VPORT_SM_OFFLINE: | |
6268 | case BFA_FCS_VPORT_SM_RSP_ERROR: | |
6269 | case BFA_FCS_VPORT_SM_RSP_FAILED: | |
f2a0cc3f | 6270 | case BFA_FCS_VPORT_SM_FABRIC_MAX: |
d7be54cc KG |
6271 | case BFA_FCS_VPORT_SM_RSP_DUP_WWN: |
6272 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); | |
6273 | bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE); | |
6274 | bfa_fcs_lport_delete(&vport->lport); | |
6275 | break; | |
6276 | ||
6277 | default: | |
6278 | bfa_sm_fault(__vport_fcs(vport), event); | |
6279 | } | |
6280 | } | |
6281 | ||
5fbe25c7 | 6282 | /* |
a36c61f9 KG |
6283 | * Vport is online (FDISC is complete). |
6284 | */ | |
6285 | static void | |
6286 | bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport, | |
6287 | enum bfa_fcs_vport_event event) | |
6288 | { | |
6289 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | |
6290 | bfa_trc(__vport_fcs(vport), event); | |
6291 | ||
6292 | switch (event) { | |
6293 | case BFA_FCS_VPORT_SM_DELETE: | |
6294 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting); | |
6295 | bfa_fcs_lport_delete(&vport->lport); | |
6296 | break; | |
6297 | ||
dd5aaf45 KG |
6298 | case BFA_FCS_VPORT_SM_STOP: |
6299 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_stopping); | |
6300 | bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP); | |
6301 | break; | |
6302 | ||
a36c61f9 KG |
6303 | case BFA_FCS_VPORT_SM_OFFLINE: |
6304 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); | |
f7f73812 | 6305 | bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE); |
a36c61f9 KG |
6306 | bfa_fcs_lport_offline(&vport->lport); |
6307 | break; | |
6308 | ||
6309 | default: | |
6310 | bfa_sm_fault(__vport_fcs(vport), event); | |
6311 | } | |
6312 | } | |
6313 | ||
dd5aaf45 KG |
6314 | /* |
6315 | * Vport is being stopped - awaiting lport stop completion to send | |
6316 | * LOGO to fabric. | |
6317 | */ | |
6318 | static void | |
6319 | bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport, | |
6320 | enum bfa_fcs_vport_event event) | |
6321 | { | |
6322 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | |
6323 | bfa_trc(__vport_fcs(vport), event); | |
6324 | ||
6325 | switch (event) { | |
6326 | case BFA_FCS_VPORT_SM_STOPCOMP: | |
6327 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo_for_stop); | |
6328 | bfa_fcs_vport_do_logo(vport); | |
6329 | break; | |
6330 | ||
6331 | case BFA_FCS_VPORT_SM_OFFLINE: | |
6332 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); | |
6333 | break; | |
6334 | ||
6335 | default: | |
6336 | bfa_sm_fault(__vport_fcs(vport), event); | |
6337 | } | |
6338 | } | |
6339 | ||
5fbe25c7 | 6340 | /* |
a36c61f9 KG |
6341 | * Vport is being deleted - awaiting lport delete completion to send |
6342 | * LOGO to fabric. | |
6343 | */ | |
6344 | static void | |
6345 | bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport, | |
6346 | enum bfa_fcs_vport_event event) | |
6347 | { | |
6348 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | |
6349 | bfa_trc(__vport_fcs(vport), event); | |
6350 | ||
6351 | switch (event) { | |
6352 | case BFA_FCS_VPORT_SM_DELETE: | |
6353 | break; | |
6354 | ||
6355 | case BFA_FCS_VPORT_SM_DELCOMP: | |
6356 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo); | |
6357 | bfa_fcs_vport_do_logo(vport); | |
6358 | break; | |
6359 | ||
6360 | case BFA_FCS_VPORT_SM_OFFLINE: | |
6361 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); | |
6362 | break; | |
6363 | ||
6364 | default: | |
6365 | bfa_sm_fault(__vport_fcs(vport), event); | |
6366 | } | |
6367 | } | |
6368 | ||
5fbe25c7 | 6369 | /* |
a36c61f9 KG |
6370 | * Error State. |
6371 | * This state will be set when the Vport Creation fails due | |
6372 | * to errors like Dup WWN. In this state only operation allowed | |
6373 | * is a Vport Delete. | |
6374 | */ | |
6375 | static void | |
6376 | bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport, | |
6377 | enum bfa_fcs_vport_event event) | |
6378 | { | |
6379 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | |
6380 | bfa_trc(__vport_fcs(vport), event); | |
6381 | ||
6382 | switch (event) { | |
6383 | case BFA_FCS_VPORT_SM_DELETE: | |
6384 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); | |
6385 | bfa_fcs_lport_delete(&vport->lport); | |
6386 | break; | |
6387 | ||
6388 | default: | |
6389 | bfa_trc(__vport_fcs(vport), event); | |
6390 | } | |
6391 | } | |
6392 | ||
5fbe25c7 | 6393 | /* |
a36c61f9 KG |
6394 | * Lport cleanup is in progress since vport is being deleted. Fabric is |
6395 | * offline, so no LOGO is needed to complete vport deletion. | |
6396 | */ | |
6397 | static void | |
6398 | bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport, | |
6399 | enum bfa_fcs_vport_event event) | |
6400 | { | |
6401 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | |
6402 | bfa_trc(__vport_fcs(vport), event); | |
6403 | ||
6404 | switch (event) { | |
6405 | case BFA_FCS_VPORT_SM_DELCOMP: | |
6406 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); | |
6407 | bfa_fcs_vport_free(vport); | |
6408 | break; | |
6409 | ||
dd5aaf45 KG |
6410 | case BFA_FCS_VPORT_SM_STOPCOMP: |
6411 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_created); | |
6412 | break; | |
6413 | ||
a36c61f9 KG |
6414 | case BFA_FCS_VPORT_SM_DELETE: |
6415 | break; | |
6416 | ||
6417 | default: | |
6418 | bfa_sm_fault(__vport_fcs(vport), event); | |
6419 | } | |
6420 | } | |
6421 | ||
dd5aaf45 KG |
6422 | /* |
6423 | * LOGO is sent to fabric. Vport stop is in progress. Lport stop cleanup | |
6424 | * is done. | |
6425 | */ | |
6426 | static void | |
6427 | bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport, | |
6428 | enum bfa_fcs_vport_event event) | |
6429 | { | |
6430 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | |
6431 | bfa_trc(__vport_fcs(vport), event); | |
6432 | ||
6433 | switch (event) { | |
6434 | case BFA_FCS_VPORT_SM_OFFLINE: | |
6435 | bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE); | |
6436 | /* | |
6437 | * !!! fall through !!! | |
6438 | */ | |
6439 | ||
6440 | case BFA_FCS_VPORT_SM_RSP_OK: | |
6441 | case BFA_FCS_VPORT_SM_RSP_ERROR: | |
6442 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_created); | |
6443 | break; | |
6444 | ||
6445 | default: | |
6446 | bfa_sm_fault(__vport_fcs(vport), event); | |
6447 | } | |
6448 | } | |
6449 | ||
5fbe25c7 | 6450 | /* |
a36c61f9 KG |
6451 | * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup |
6452 | * is done. | |
6453 | */ | |
6454 | static void | |
6455 | bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport, | |
6456 | enum bfa_fcs_vport_event event) | |
6457 | { | |
6458 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | |
6459 | bfa_trc(__vport_fcs(vport), event); | |
6460 | ||
6461 | switch (event) { | |
6462 | case BFA_FCS_VPORT_SM_OFFLINE: | |
f7f73812 | 6463 | bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE); |
a36c61f9 KG |
6464 | /* |
6465 | * !!! fall through !!! | |
6466 | */ | |
6467 | ||
6468 | case BFA_FCS_VPORT_SM_RSP_OK: | |
6469 | case BFA_FCS_VPORT_SM_RSP_ERROR: | |
6470 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); | |
6471 | bfa_fcs_vport_free(vport); | |
6472 | break; | |
6473 | ||
6474 | case BFA_FCS_VPORT_SM_DELETE: | |
6475 | break; | |
6476 | ||
6477 | default: | |
6478 | bfa_sm_fault(__vport_fcs(vport), event); | |
6479 | } | |
6480 | } | |
6481 | ||
6482 | ||
6483 | ||
5fbe25c7 | 6484 | /* |
a36c61f9 KG |
6485 | * fcs_vport_private FCS virtual port private functions |
6486 | */ | |
7826f304 KG |
6487 | /* |
6488 | * Send AEN notification | |
6489 | */ | |
6490 | static void | |
6491 | bfa_fcs_vport_aen_post(struct bfa_fcs_lport_s *port, | |
6492 | enum bfa_lport_aen_event event) | |
6493 | { | |
6494 | struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad; | |
6495 | struct bfa_aen_entry_s *aen_entry; | |
6496 | ||
6497 | bfad_get_aen_entry(bfad, aen_entry); | |
6498 | if (!aen_entry) | |
6499 | return; | |
6500 | ||
6501 | aen_entry->aen_data.lport.vf_id = port->fabric->vf_id; | |
6502 | aen_entry->aen_data.lport.roles = port->port_cfg.roles; | |
6503 | aen_entry->aen_data.lport.ppwwn = bfa_fcs_lport_get_pwwn( | |
6504 | bfa_fcs_get_base_port(port->fcs)); | |
6505 | aen_entry->aen_data.lport.lpwwn = bfa_fcs_lport_get_pwwn(port); | |
6506 | ||
6507 | /* Send the AEN notification */ | |
6508 | bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq, | |
6509 | BFA_AEN_CAT_LPORT, event); | |
6510 | } | |
6511 | ||
5fbe25c7 | 6512 | /* |
a36c61f9 KG |
6513 | * This routine will be called to send a FDISC command. |
6514 | */ | |
6515 | static void | |
6516 | bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport) | |
6517 | { | |
6518 | bfa_lps_fdisc(vport->lps, vport, | |
6519 | bfa_fcport_get_maxfrsize(__vport_bfa(vport)), | |
6520 | __vport_pwwn(vport), __vport_nwwn(vport)); | |
6521 | vport->vport_stats.fdisc_sent++; | |
6522 | } | |
6523 | ||
6524 | static void | |
6525 | bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport) | |
6526 | { | |
f7f73812 MZ |
6527 | u8 lsrjt_rsn = vport->lps->lsrjt_rsn; |
6528 | u8 lsrjt_expl = vport->lps->lsrjt_expl; | |
a36c61f9 KG |
6529 | |
6530 | bfa_trc(__vport_fcs(vport), lsrjt_rsn); | |
6531 | bfa_trc(__vport_fcs(vport), lsrjt_expl); | |
6532 | ||
6533 | /* For certain reason codes, we don't want to retry. */ | |
f7f73812 | 6534 | switch (vport->lps->lsrjt_expl) { |
a36c61f9 KG |
6535 | case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */ |
6536 | case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */ | |
6537 | if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) | |
6538 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); | |
7826f304 KG |
6539 | else { |
6540 | bfa_fcs_vport_aen_post(&vport->lport, | |
6541 | BFA_LPORT_AEN_NPIV_DUP_WWN); | |
a36c61f9 | 6542 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN); |
7826f304 | 6543 | } |
a36c61f9 KG |
6544 | break; |
6545 | ||
6546 | case FC_LS_RJT_EXP_INSUFF_RES: | |
6547 | /* | |
6548 | * This means max logins per port/switch setting on the | |
6549 | * switch was exceeded. | |
6550 | */ | |
6551 | if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) | |
6552 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); | |
7826f304 KG |
6553 | else { |
6554 | bfa_fcs_vport_aen_post(&vport->lport, | |
6555 | BFA_LPORT_AEN_NPIV_FABRIC_MAX); | |
f2a0cc3f | 6556 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_FABRIC_MAX); |
7826f304 | 6557 | } |
a36c61f9 KG |
6558 | break; |
6559 | ||
6560 | default: | |
7826f304 KG |
6561 | if (vport->fdisc_retries == 0) |
6562 | bfa_fcs_vport_aen_post(&vport->lport, | |
6563 | BFA_LPORT_AEN_NPIV_UNKNOWN); | |
a36c61f9 KG |
6564 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); |
6565 | } | |
6566 | } | |
6567 | ||
5fbe25c7 | 6568 | /* |
a36c61f9 KG |
6569 | * Called to send a logout to the fabric. Used when a V-Port is |
6570 | * deleted/stopped. | |
6571 | */ | |
6572 | static void | |
6573 | bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport) | |
6574 | { | |
6575 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | |
6576 | ||
6577 | vport->vport_stats.logo_sent++; | |
6578 | bfa_lps_fdisclogo(vport->lps); | |
6579 | } | |
6580 | ||
6581 | ||
5fbe25c7 | 6582 | /* |
a36c61f9 KG |
6583 | * This routine will be called by bfa_timer on timer timeouts. |
6584 | * | |
6585 | * param[in] vport - pointer to bfa_fcs_vport_t. | |
6586 | * param[out] vport_status - pointer to return vport status in | |
6587 | * | |
6588 | * return | |
6589 | * void | |
6590 | * | |
6591 | * Special Considerations: | |
6592 | * | |
6593 | * note | |
6594 | */ | |
6595 | static void | |
6596 | bfa_fcs_vport_timeout(void *vport_arg) | |
6597 | { | |
6598 | struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *) vport_arg; | |
6599 | ||
6600 | vport->vport_stats.fdisc_timeouts++; | |
6601 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT); | |
6602 | } | |
6603 | ||
6604 | static void | |
6605 | bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport) | |
6606 | { | |
6607 | struct bfad_vport_s *vport_drv = | |
6608 | (struct bfad_vport_s *)vport->vport_drv; | |
6609 | ||
6610 | bfa_fcs_fabric_delvport(__vport_fabric(vport), vport); | |
17c201b3 | 6611 | bfa_lps_delete(vport->lps); |
a36c61f9 | 6612 | |
17c201b3 | 6613 | if (vport_drv->comp_del) { |
a36c61f9 | 6614 | complete(vport_drv->comp_del); |
17c201b3 KG |
6615 | return; |
6616 | } | |
a36c61f9 | 6617 | |
17c201b3 KG |
6618 | /* |
6619 | * We queue the vport delete work to the IM work_q from here. | |
6620 | * The memory for the bfad_vport_s is freed from the FC function | |
6621 | * template vport_delete entry point. | |
6622 | */ | |
529f9a76 | 6623 | bfad_im_port_delete(vport_drv->drv_port.bfad, &vport_drv->drv_port); |
a36c61f9 KG |
6624 | } |
6625 | ||
5fbe25c7 | 6626 | /* |
a36c61f9 KG |
6627 | * fcs_vport_public FCS virtual port public interfaces |
6628 | */ | |
6629 | ||
5fbe25c7 | 6630 | /* |
a36c61f9 KG |
6631 | * Online notification from fabric SM. |
6632 | */ | |
6633 | void | |
6634 | bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport) | |
6635 | { | |
6636 | vport->vport_stats.fab_online++; | |
d7be54cc KG |
6637 | if (bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) |
6638 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE); | |
6639 | else | |
6640 | vport->vport_stats.fab_no_npiv++; | |
a36c61f9 KG |
6641 | } |
6642 | ||
5fbe25c7 | 6643 | /* |
a36c61f9 KG |
6644 | * Offline notification from fabric SM. |
6645 | */ | |
6646 | void | |
6647 | bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport) | |
6648 | { | |
6649 | vport->vport_stats.fab_offline++; | |
6650 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE); | |
6651 | } | |
6652 | ||
5fbe25c7 | 6653 | /* |
a36c61f9 KG |
6654 | * Cleanup notification from fabric SM on link timer expiry. |
6655 | */ | |
6656 | void | |
6657 | bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport) | |
6658 | { | |
6659 | vport->vport_stats.fab_cleanup++; | |
6660 | } | |
881c1b3c KG |
6661 | |
6662 | /* | |
6663 | * Stop notification from fabric SM. To be invoked from within FCS. | |
6664 | */ | |
6665 | void | |
6666 | bfa_fcs_vport_fcs_stop(struct bfa_fcs_vport_s *vport) | |
6667 | { | |
6668 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP); | |
6669 | } | |
6670 | ||
5fbe25c7 | 6671 | /* |
a36c61f9 KG |
6672 | * delete notification from fabric SM. To be invoked from within FCS. |
6673 | */ | |
6674 | void | |
6675 | bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport) | |
6676 | { | |
6677 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE); | |
6678 | } | |
6679 | ||
dd5aaf45 KG |
6680 | /* |
6681 | * Stop completion callback from associated lport | |
6682 | */ | |
6683 | void | |
6684 | bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport) | |
6685 | { | |
6686 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOPCOMP); | |
6687 | } | |
6688 | ||
5fbe25c7 | 6689 | /* |
a36c61f9 KG |
6690 | * Delete completion callback from associated lport |
6691 | */ | |
6692 | void | |
6693 | bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport) | |
6694 | { | |
6695 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP); | |
6696 | } | |
6697 | ||
6698 | ||
6699 | ||
5fbe25c7 | 6700 | /* |
a36c61f9 KG |
6701 | * fcs_vport_api Virtual port API |
6702 | */ | |
6703 | ||
5fbe25c7 | 6704 | /* |
a36c61f9 KG |
6705 | * Use this function to instantiate a new FCS vport object. This |
6706 | * function will not trigger any HW initialization process (which will be | |
6707 | * done in vport_start() call) | |
6708 | * | |
6709 | * param[in] vport - pointer to bfa_fcs_vport_t. This space | |
6710 | * needs to be allocated by the driver. | |
6711 | * param[in] fcs - FCS instance | |
6712 | * param[in] vport_cfg - vport configuration | |
6713 | * param[in] vf_id - VF_ID if vport is created within a VF. | |
6714 | * FC_VF_ID_NULL to specify base fabric. | |
6715 | * param[in] vport_drv - Opaque handle back to the driver's vport | |
6716 | * structure | |
6717 | * | |
6718 | * retval BFA_STATUS_OK - on success. | |
6719 | * retval BFA_STATUS_FAILED - on failure. | |
6720 | */ | |
6721 | bfa_status_t | |
6722 | bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs, | |
6723 | u16 vf_id, struct bfa_lport_cfg_s *vport_cfg, | |
6724 | struct bfad_vport_s *vport_drv) | |
6725 | { | |
6726 | if (vport_cfg->pwwn == 0) | |
6727 | return BFA_STATUS_INVALID_WWN; | |
6728 | ||
6729 | if (bfa_fcs_lport_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn) | |
6730 | return BFA_STATUS_VPORT_WWN_BP; | |
6731 | ||
6732 | if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL) | |
6733 | return BFA_STATUS_VPORT_EXISTS; | |
6734 | ||
f7f73812 | 6735 | if (fcs->fabric.num_vports == |
a36c61f9 KG |
6736 | bfa_lps_get_max_vport(fcs->bfa)) |
6737 | return BFA_STATUS_VPORT_MAX; | |
6738 | ||
6739 | vport->lps = bfa_lps_alloc(fcs->bfa); | |
6740 | if (!vport->lps) | |
6741 | return BFA_STATUS_VPORT_MAX; | |
6742 | ||
6743 | vport->vport_drv = vport_drv; | |
6744 | vport_cfg->preboot_vp = BFA_FALSE; | |
6745 | ||
6746 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); | |
6747 | bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport); | |
6748 | bfa_fcs_lport_init(&vport->lport, vport_cfg); | |
6749 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE); | |
6750 | ||
6751 | return BFA_STATUS_OK; | |
6752 | } | |
6753 | ||
5fbe25c7 | 6754 | /* |
a36c61f9 KG |
6755 | * Use this function to instantiate a new FCS PBC vport object. This |
6756 | * function will not trigger any HW initialization process (which will be | |
6757 | * done in vport_start() call) | |
6758 | * | |
6759 | * param[in] vport - pointer to bfa_fcs_vport_t. This space | |
6760 | * needs to be allocated by the driver. | |
6761 | * param[in] fcs - FCS instance | |
6762 | * param[in] vport_cfg - vport configuration | |
6763 | * param[in] vf_id - VF_ID if vport is created within a VF. | |
6764 | * FC_VF_ID_NULL to specify base fabric. | |
6765 | * param[in] vport_drv - Opaque handle back to the driver's vport | |
6766 | * structure | |
6767 | * | |
6768 | * retval BFA_STATUS_OK - on success. | |
6769 | * retval BFA_STATUS_FAILED - on failure. | |
6770 | */ | |
6771 | bfa_status_t | |
6772 | bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs, | |
6773 | u16 vf_id, struct bfa_lport_cfg_s *vport_cfg, | |
6774 | struct bfad_vport_s *vport_drv) | |
6775 | { | |
6776 | bfa_status_t rc; | |
6777 | ||
6778 | rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv); | |
6779 | vport->lport.port_cfg.preboot_vp = BFA_TRUE; | |
6780 | ||
6781 | return rc; | |
6782 | } | |
6783 | ||
5fbe25c7 | 6784 | /* |
a36c61f9 KG |
6785 | * Use this function to findout if this is a pbc vport or not. |
6786 | * | |
6787 | * @param[in] vport - pointer to bfa_fcs_vport_t. | |
6788 | * | |
6789 | * @returns None | |
6790 | */ | |
6791 | bfa_boolean_t | |
6792 | bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport) | |
6793 | { | |
6794 | ||
6795 | if (vport && (vport->lport.port_cfg.preboot_vp == BFA_TRUE)) | |
6796 | return BFA_TRUE; | |
6797 | else | |
6798 | return BFA_FALSE; | |
6799 | ||
6800 | } | |
6801 | ||
5fbe25c7 | 6802 | /* |
a36c61f9 KG |
6803 | * Use this function initialize the vport. |
6804 | * | |
6805 | * @param[in] vport - pointer to bfa_fcs_vport_t. | |
6806 | * | |
6807 | * @returns None | |
6808 | */ | |
6809 | bfa_status_t | |
6810 | bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport) | |
6811 | { | |
6812 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START); | |
6813 | ||
6814 | return BFA_STATUS_OK; | |
6815 | } | |
6816 | ||
5fbe25c7 | 6817 | /* |
a36c61f9 KG |
6818 | * Use this function quiese the vport object. This function will return |
6819 | * immediately, when the vport is actually stopped, the | |
6820 | * bfa_drv_vport_stop_cb() will be called. | |
6821 | * | |
6822 | * param[in] vport - pointer to bfa_fcs_vport_t. | |
6823 | * | |
6824 | * return None | |
6825 | */ | |
6826 | bfa_status_t | |
6827 | bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport) | |
6828 | { | |
6829 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP); | |
6830 | ||
6831 | return BFA_STATUS_OK; | |
6832 | } | |
6833 | ||
5fbe25c7 | 6834 | /* |
a36c61f9 KG |
6835 | * Use this function to delete a vport object. Fabric object should |
6836 | * be stopped before this function call. | |
6837 | * | |
6838 | * !!!!!!! Donot invoke this from within FCS !!!!!!! | |
6839 | * | |
6840 | * param[in] vport - pointer to bfa_fcs_vport_t. | |
6841 | * | |
6842 | * return None | |
6843 | */ | |
6844 | bfa_status_t | |
6845 | bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport) | |
6846 | { | |
6847 | ||
6848 | if (vport->lport.port_cfg.preboot_vp) | |
6849 | return BFA_STATUS_PBC; | |
6850 | ||
6851 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE); | |
6852 | ||
6853 | return BFA_STATUS_OK; | |
6854 | } | |
6855 | ||
5fbe25c7 | 6856 | /* |
a36c61f9 KG |
6857 | * Use this function to get vport's current status info. |
6858 | * | |
6859 | * param[in] vport pointer to bfa_fcs_vport_t. | |
6860 | * param[out] attr pointer to return vport attributes | |
6861 | * | |
6862 | * return None | |
6863 | */ | |
6864 | void | |
6865 | bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport, | |
6866 | struct bfa_vport_attr_s *attr) | |
6867 | { | |
6868 | if (vport == NULL || attr == NULL) | |
6869 | return; | |
6870 | ||
6a18b167 | 6871 | memset(attr, 0, sizeof(struct bfa_vport_attr_s)); |
a36c61f9 KG |
6872 | |
6873 | bfa_fcs_lport_get_attr(&vport->lport, &attr->port_attr); | |
6874 | attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm); | |
6875 | } | |
6876 | ||
a36c61f9 | 6877 | |
5fbe25c7 | 6878 | /* |
a36c61f9 KG |
6879 | * Lookup a virtual port. Excludes base port from lookup. |
6880 | */ | |
6881 | struct bfa_fcs_vport_s * | |
6882 | bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn) | |
6883 | { | |
6884 | struct bfa_fcs_vport_s *vport; | |
6885 | struct bfa_fcs_fabric_s *fabric; | |
6886 | ||
6887 | bfa_trc(fcs, vf_id); | |
6888 | bfa_trc(fcs, vpwwn); | |
6889 | ||
6890 | fabric = bfa_fcs_vf_lookup(fcs, vf_id); | |
6891 | if (!fabric) { | |
6892 | bfa_trc(fcs, vf_id); | |
6893 | return NULL; | |
6894 | } | |
6895 | ||
6896 | vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn); | |
6897 | return vport; | |
6898 | } | |
6899 | ||
5fbe25c7 | 6900 | /* |
a36c61f9 KG |
6901 | * FDISC Response |
6902 | */ | |
6903 | void | |
6904 | bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status) | |
6905 | { | |
6906 | struct bfa_fcs_vport_s *vport = uarg; | |
6907 | ||
6908 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | |
6909 | bfa_trc(__vport_fcs(vport), status); | |
6910 | ||
6911 | switch (status) { | |
6912 | case BFA_STATUS_OK: | |
6913 | /* | |
b595076a | 6914 | * Initialize the V-Port fields |
a36c61f9 | 6915 | */ |
f7f73812 | 6916 | __vport_fcid(vport) = vport->lps->lp_pid; |
a36c61f9 KG |
6917 | vport->vport_stats.fdisc_accepts++; |
6918 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK); | |
6919 | break; | |
6920 | ||
6921 | case BFA_STATUS_INVALID_MAC: | |
6922 | /* Only for CNA */ | |
6923 | vport->vport_stats.fdisc_acc_bad++; | |
6924 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); | |
6925 | ||
6926 | break; | |
6927 | ||
6928 | case BFA_STATUS_EPROTOCOL: | |
f7f73812 | 6929 | switch (vport->lps->ext_status) { |
a36c61f9 KG |
6930 | case BFA_EPROTO_BAD_ACCEPT: |
6931 | vport->vport_stats.fdisc_acc_bad++; | |
6932 | break; | |
6933 | ||
6934 | case BFA_EPROTO_UNKNOWN_RSP: | |
6935 | vport->vport_stats.fdisc_unknown_rsp++; | |
6936 | break; | |
6937 | ||
6938 | default: | |
6939 | break; | |
6940 | } | |
6941 | ||
f2a0cc3f VMG |
6942 | if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) |
6943 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); | |
6944 | else | |
6945 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED); | |
6946 | ||
6947 | break; | |
6948 | ||
6949 | case BFA_STATUS_ETIMER: | |
6950 | vport->vport_stats.fdisc_timeouts++; | |
6951 | if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) | |
6952 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); | |
6953 | else | |
6954 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED); | |
a36c61f9 KG |
6955 | break; |
6956 | ||
6957 | case BFA_STATUS_FABRIC_RJT: | |
6958 | vport->vport_stats.fdisc_rejects++; | |
6959 | bfa_fcs_vport_fdisc_rejected(vport); | |
6960 | break; | |
6961 | ||
6962 | default: | |
6963 | vport->vport_stats.fdisc_rsp_err++; | |
6964 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); | |
6965 | } | |
6966 | } | |
6967 | ||
5fbe25c7 | 6968 | /* |
a36c61f9 KG |
6969 | * LOGO response |
6970 | */ | |
6971 | void | |
6972 | bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg) | |
6973 | { | |
6974 | struct bfa_fcs_vport_s *vport = uarg; | |
6975 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK); | |
6976 | } | |
6977 | ||
5fbe25c7 | 6978 | /* |
a36c61f9 KG |
6979 | * Received clear virtual link |
6980 | */ | |
6981 | void | |
6982 | bfa_cb_lps_cvl_event(void *bfad, void *uarg) | |
6983 | { | |
6984 | struct bfa_fcs_vport_s *vport = uarg; | |
6985 | ||
6986 | /* Send an Offline followed by an ONLINE */ | |
6987 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE); | |
6988 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE); | |
6989 | } |