Commit | Line | Data |
---|---|---|
7725ccfd JH |
1 | /* |
2 | * Copyright (c) 2005-2009 Brocade Communications Systems, Inc. | |
3 | * All rights reserved | |
4 | * www.brocade.com | |
5 | * | |
6 | * Linux driver for Brocade Fibre Channel Host Bus Adapter. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify it | |
9 | * under the terms of the GNU General Public License (GPL) Version 2 as | |
10 | * published by the Free Software Foundation | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | */ | |
17 | ||
18 | /** | |
19 | * port_api.c BFA FCS port | |
20 | */ | |
21 | ||
22 | ||
23 | #include <bfa.h> | |
24 | #include <bfa_svc.h> | |
25 | #include "fcs_lport.h" | |
26 | #include "fcs_rport.h" | |
27 | #include "lport_priv.h" | |
28 | #include "fcs_trcmod.h" | |
29 | #include "fcs_fcxp.h" | |
30 | #include <fcs/bfa_fcs_fdmi.h> | |
31 | ||
32 | BFA_TRC_FILE(FCS, FDMI); | |
33 | ||
34 | #define BFA_FCS_FDMI_CMD_MAX_RETRIES 2 | |
35 | ||
36 | /* | |
37 | * forward declarations | |
38 | */ | |
39 | static void bfa_fcs_port_fdmi_send_rhba(void *fdmi_cbarg, | |
40 | struct bfa_fcxp_s *fcxp_alloced); | |
41 | static void bfa_fcs_port_fdmi_send_rprt(void *fdmi_cbarg, | |
42 | struct bfa_fcxp_s *fcxp_alloced); | |
43 | static void bfa_fcs_port_fdmi_send_rpa(void *fdmi_cbarg, | |
44 | struct bfa_fcxp_s *fcxp_alloced); | |
45 | static void bfa_fcs_port_fdmi_rhba_response(void *fcsarg, | |
46 | struct bfa_fcxp_s *fcxp, | |
47 | void *cbarg, | |
48 | bfa_status_t req_status, | |
49 | u32 rsp_len, | |
50 | u32 resid_len, | |
51 | struct fchs_s *rsp_fchs); | |
52 | static void bfa_fcs_port_fdmi_rprt_response(void *fcsarg, | |
53 | struct bfa_fcxp_s *fcxp, | |
54 | void *cbarg, | |
55 | bfa_status_t req_status, | |
56 | u32 rsp_len, | |
57 | u32 resid_len, | |
58 | struct fchs_s *rsp_fchs); | |
59 | static void bfa_fcs_port_fdmi_rpa_response(void *fcsarg, | |
60 | struct bfa_fcxp_s *fcxp, | |
61 | void *cbarg, | |
62 | bfa_status_t req_status, | |
63 | u32 rsp_len, | |
64 | u32 resid_len, | |
65 | struct fchs_s *rsp_fchs); | |
66 | static void bfa_fcs_port_fdmi_timeout(void *arg); | |
67 | static u16 bfa_fcs_port_fdmi_build_rhba_pyld( | |
68 | struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld); | |
69 | static u16 bfa_fcs_port_fdmi_build_rprt_pyld( | |
70 | struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld); | |
71 | static u16 bfa_fcs_port_fdmi_build_rpa_pyld( | |
72 | struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld); | |
73 | static u16 bfa_fcs_port_fdmi_build_portattr_block( | |
74 | struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld); | |
f8ceafde | 75 | static void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_port_fdmi_s *fdmi, |
7725ccfd | 76 | struct bfa_fcs_fdmi_hba_attr_s *hba_attr); |
f8ceafde | 77 | static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_port_fdmi_s *fdmi, |
7725ccfd JH |
78 | struct bfa_fcs_fdmi_port_attr_s *port_attr); |
79 | /** | |
80 | * fcs_fdmi_sm FCS FDMI state machine | |
81 | */ | |
82 | ||
83 | /** | |
84 | * FDMI State Machine events | |
85 | */ | |
86 | enum port_fdmi_event { | |
87 | FDMISM_EVENT_PORT_ONLINE = 1, | |
88 | FDMISM_EVENT_PORT_OFFLINE = 2, | |
89 | FDMISM_EVENT_RSP_OK = 4, | |
90 | FDMISM_EVENT_RSP_ERROR = 5, | |
91 | FDMISM_EVENT_TIMEOUT = 6, | |
92 | FDMISM_EVENT_RHBA_SENT = 7, | |
93 | FDMISM_EVENT_RPRT_SENT = 8, | |
94 | FDMISM_EVENT_RPA_SENT = 9, | |
95 | }; | |
96 | ||
97 | static void bfa_fcs_port_fdmi_sm_offline(struct bfa_fcs_port_fdmi_s *fdmi, | |
98 | enum port_fdmi_event event); | |
99 | static void bfa_fcs_port_fdmi_sm_sending_rhba(struct bfa_fcs_port_fdmi_s *fdmi, | |
100 | enum port_fdmi_event event); | |
101 | static void bfa_fcs_port_fdmi_sm_rhba(struct bfa_fcs_port_fdmi_s *fdmi, | |
102 | enum port_fdmi_event event); | |
103 | static void bfa_fcs_port_fdmi_sm_rhba_retry(struct bfa_fcs_port_fdmi_s *fdmi, | |
104 | enum port_fdmi_event event); | |
105 | static void bfa_fcs_port_fdmi_sm_sending_rprt(struct bfa_fcs_port_fdmi_s *fdmi, | |
106 | enum port_fdmi_event event); | |
107 | static void bfa_fcs_port_fdmi_sm_rprt(struct bfa_fcs_port_fdmi_s *fdmi, | |
108 | enum port_fdmi_event event); | |
109 | static void bfa_fcs_port_fdmi_sm_rprt_retry(struct bfa_fcs_port_fdmi_s *fdmi, | |
110 | enum port_fdmi_event event); | |
111 | static void bfa_fcs_port_fdmi_sm_sending_rpa(struct bfa_fcs_port_fdmi_s *fdmi, | |
112 | enum port_fdmi_event event); | |
113 | static void bfa_fcs_port_fdmi_sm_rpa(struct bfa_fcs_port_fdmi_s *fdmi, | |
114 | enum port_fdmi_event event); | |
115 | static void bfa_fcs_port_fdmi_sm_rpa_retry(struct bfa_fcs_port_fdmi_s *fdmi, | |
116 | enum port_fdmi_event event); | |
117 | static void bfa_fcs_port_fdmi_sm_online(struct bfa_fcs_port_fdmi_s *fdmi, | |
118 | enum port_fdmi_event event); | |
5b098082 KG |
119 | static void bfa_fcs_port_fdmi_sm_disabled(struct bfa_fcs_port_fdmi_s *fdmi, |
120 | enum port_fdmi_event event); | |
121 | ||
7725ccfd JH |
122 | /** |
123 | * Start in offline state - awaiting MS to send start. | |
124 | */ | |
125 | static void | |
126 | bfa_fcs_port_fdmi_sm_offline(struct bfa_fcs_port_fdmi_s *fdmi, | |
127 | enum port_fdmi_event event) | |
128 | { | |
129 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
130 | ||
131 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
132 | bfa_trc(port->fcs, event); | |
133 | ||
134 | fdmi->retry_cnt = 0; | |
135 | ||
136 | switch (event) { | |
137 | case FDMISM_EVENT_PORT_ONLINE: | |
138 | if (port->vport) { | |
139 | /* | |
140 | * For Vports, register a new port. | |
141 | */ | |
142 | bfa_sm_set_state(fdmi, | |
143 | bfa_fcs_port_fdmi_sm_sending_rprt); | |
144 | bfa_fcs_port_fdmi_send_rprt(fdmi, NULL); | |
145 | } else { | |
146 | /* | |
147 | * For a base port, we should first register the HBA | |
148 | * atribute. The HBA attribute also contains the base | |
149 | * port registration. | |
150 | */ | |
151 | bfa_sm_set_state(fdmi, | |
152 | bfa_fcs_port_fdmi_sm_sending_rhba); | |
153 | bfa_fcs_port_fdmi_send_rhba(fdmi, NULL); | |
154 | } | |
155 | break; | |
156 | ||
157 | case FDMISM_EVENT_PORT_OFFLINE: | |
158 | break; | |
159 | ||
160 | default: | |
e641de37 | 161 | bfa_sm_fault(port->fcs, event); |
7725ccfd JH |
162 | } |
163 | } | |
164 | ||
165 | static void | |
166 | bfa_fcs_port_fdmi_sm_sending_rhba(struct bfa_fcs_port_fdmi_s *fdmi, | |
167 | enum port_fdmi_event event) | |
168 | { | |
169 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
170 | ||
171 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
172 | bfa_trc(port->fcs, event); | |
173 | ||
174 | switch (event) { | |
175 | case FDMISM_EVENT_RHBA_SENT: | |
176 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rhba); | |
177 | break; | |
178 | ||
179 | case FDMISM_EVENT_PORT_OFFLINE: | |
180 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | |
181 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port), | |
182 | &fdmi->fcxp_wqe); | |
183 | break; | |
184 | ||
185 | default: | |
e641de37 | 186 | bfa_sm_fault(port->fcs, event); |
7725ccfd JH |
187 | } |
188 | } | |
189 | ||
190 | static void | |
191 | bfa_fcs_port_fdmi_sm_rhba(struct bfa_fcs_port_fdmi_s *fdmi, | |
192 | enum port_fdmi_event event) | |
193 | { | |
194 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
195 | ||
196 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
197 | bfa_trc(port->fcs, event); | |
198 | ||
199 | switch (event) { | |
200 | case FDMISM_EVENT_RSP_ERROR: | |
201 | /* | |
202 | * if max retries have not been reached, start timer for a | |
203 | * delayed retry | |
204 | */ | |
205 | if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) { | |
206 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rhba_retry); | |
207 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port), | |
208 | &fdmi->timer, bfa_fcs_port_fdmi_timeout, | |
209 | fdmi, BFA_FCS_RETRY_TIMEOUT); | |
210 | } else { | |
211 | /* | |
212 | * set state to offline | |
213 | */ | |
214 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | |
215 | } | |
216 | break; | |
217 | ||
218 | case FDMISM_EVENT_RSP_OK: | |
219 | /* | |
220 | * Initiate Register Port Attributes | |
221 | */ | |
222 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rpa); | |
223 | fdmi->retry_cnt = 0; | |
224 | bfa_fcs_port_fdmi_send_rpa(fdmi, NULL); | |
225 | break; | |
226 | ||
227 | case FDMISM_EVENT_PORT_OFFLINE: | |
228 | bfa_fcxp_discard(fdmi->fcxp); | |
229 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | |
230 | break; | |
231 | ||
232 | default: | |
e641de37 | 233 | bfa_sm_fault(port->fcs, event); |
7725ccfd JH |
234 | } |
235 | } | |
236 | ||
237 | static void | |
238 | bfa_fcs_port_fdmi_sm_rhba_retry(struct bfa_fcs_port_fdmi_s *fdmi, | |
239 | enum port_fdmi_event event) | |
240 | { | |
241 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
242 | ||
243 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
244 | bfa_trc(port->fcs, event); | |
245 | ||
246 | switch (event) { | |
247 | case FDMISM_EVENT_TIMEOUT: | |
248 | /* | |
249 | * Retry Timer Expired. Re-send | |
250 | */ | |
251 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rhba); | |
252 | bfa_fcs_port_fdmi_send_rhba(fdmi, NULL); | |
253 | break; | |
254 | ||
255 | case FDMISM_EVENT_PORT_OFFLINE: | |
256 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | |
257 | bfa_timer_stop(&fdmi->timer); | |
258 | break; | |
259 | ||
260 | default: | |
e641de37 | 261 | bfa_sm_fault(port->fcs, event); |
7725ccfd JH |
262 | } |
263 | } | |
264 | ||
265 | /* | |
266 | * RPRT : Register Port | |
267 | */ | |
268 | static void | |
269 | bfa_fcs_port_fdmi_sm_sending_rprt(struct bfa_fcs_port_fdmi_s *fdmi, | |
270 | enum port_fdmi_event event) | |
271 | { | |
272 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
273 | ||
274 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
275 | bfa_trc(port->fcs, event); | |
276 | ||
277 | switch (event) { | |
278 | case FDMISM_EVENT_RPRT_SENT: | |
279 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rprt); | |
280 | break; | |
281 | ||
282 | case FDMISM_EVENT_PORT_OFFLINE: | |
283 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | |
284 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port), | |
285 | &fdmi->fcxp_wqe); | |
286 | break; | |
287 | ||
288 | default: | |
e641de37 | 289 | bfa_sm_fault(port->fcs, event); |
7725ccfd JH |
290 | } |
291 | } | |
292 | ||
293 | static void | |
294 | bfa_fcs_port_fdmi_sm_rprt(struct bfa_fcs_port_fdmi_s *fdmi, | |
295 | enum port_fdmi_event event) | |
296 | { | |
297 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
298 | ||
299 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
300 | bfa_trc(port->fcs, event); | |
301 | ||
302 | switch (event) { | |
303 | case FDMISM_EVENT_RSP_ERROR: | |
304 | /* | |
305 | * if max retries have not been reached, start timer for a | |
306 | * delayed retry | |
307 | */ | |
308 | if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) { | |
309 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rprt_retry); | |
310 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port), | |
311 | &fdmi->timer, bfa_fcs_port_fdmi_timeout, | |
312 | fdmi, BFA_FCS_RETRY_TIMEOUT); | |
313 | ||
314 | } else { | |
315 | /* | |
316 | * set state to offline | |
317 | */ | |
318 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | |
319 | fdmi->retry_cnt = 0; | |
320 | } | |
321 | break; | |
322 | ||
323 | case FDMISM_EVENT_RSP_OK: | |
324 | fdmi->retry_cnt = 0; | |
325 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_online); | |
326 | break; | |
327 | ||
328 | case FDMISM_EVENT_PORT_OFFLINE: | |
329 | bfa_fcxp_discard(fdmi->fcxp); | |
330 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | |
331 | break; | |
332 | ||
333 | default: | |
e641de37 | 334 | bfa_sm_fault(port->fcs, event); |
7725ccfd JH |
335 | } |
336 | } | |
337 | ||
338 | static void | |
339 | bfa_fcs_port_fdmi_sm_rprt_retry(struct bfa_fcs_port_fdmi_s *fdmi, | |
340 | enum port_fdmi_event event) | |
341 | { | |
342 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
343 | ||
344 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
345 | bfa_trc(port->fcs, event); | |
346 | ||
347 | switch (event) { | |
348 | case FDMISM_EVENT_TIMEOUT: | |
349 | /* | |
350 | * Retry Timer Expired. Re-send | |
351 | */ | |
352 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rprt); | |
353 | bfa_fcs_port_fdmi_send_rprt(fdmi, NULL); | |
354 | break; | |
355 | ||
356 | case FDMISM_EVENT_PORT_OFFLINE: | |
357 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | |
358 | bfa_timer_stop(&fdmi->timer); | |
359 | break; | |
360 | ||
361 | default: | |
e641de37 | 362 | bfa_sm_fault(port->fcs, event); |
7725ccfd JH |
363 | } |
364 | } | |
365 | ||
366 | /* | |
367 | * Register Port Attributes | |
368 | */ | |
369 | static void | |
370 | bfa_fcs_port_fdmi_sm_sending_rpa(struct bfa_fcs_port_fdmi_s *fdmi, | |
371 | enum port_fdmi_event event) | |
372 | { | |
373 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
374 | ||
375 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
376 | bfa_trc(port->fcs, event); | |
377 | ||
378 | switch (event) { | |
379 | case FDMISM_EVENT_RPA_SENT: | |
380 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rpa); | |
381 | break; | |
382 | ||
383 | case FDMISM_EVENT_PORT_OFFLINE: | |
384 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | |
385 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port), | |
386 | &fdmi->fcxp_wqe); | |
387 | break; | |
388 | ||
389 | default: | |
e641de37 | 390 | bfa_sm_fault(port->fcs, event); |
7725ccfd JH |
391 | } |
392 | } | |
393 | ||
394 | static void | |
395 | bfa_fcs_port_fdmi_sm_rpa(struct bfa_fcs_port_fdmi_s *fdmi, | |
396 | enum port_fdmi_event event) | |
397 | { | |
398 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
399 | ||
400 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
401 | bfa_trc(port->fcs, event); | |
402 | ||
403 | switch (event) { | |
404 | case FDMISM_EVENT_RSP_ERROR: | |
405 | /* | |
406 | * if max retries have not been reached, start timer for a | |
407 | * delayed retry | |
408 | */ | |
409 | if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) { | |
410 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rpa_retry); | |
411 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port), | |
412 | &fdmi->timer, bfa_fcs_port_fdmi_timeout, | |
413 | fdmi, BFA_FCS_RETRY_TIMEOUT); | |
414 | } else { | |
415 | /* | |
416 | * set state to offline | |
417 | */ | |
418 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | |
419 | fdmi->retry_cnt = 0; | |
420 | } | |
421 | break; | |
422 | ||
423 | case FDMISM_EVENT_RSP_OK: | |
424 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_online); | |
425 | fdmi->retry_cnt = 0; | |
426 | break; | |
427 | ||
428 | case FDMISM_EVENT_PORT_OFFLINE: | |
429 | bfa_fcxp_discard(fdmi->fcxp); | |
430 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | |
431 | break; | |
432 | ||
433 | default: | |
e641de37 | 434 | bfa_sm_fault(port->fcs, event); |
7725ccfd JH |
435 | } |
436 | } | |
437 | ||
438 | static void | |
439 | bfa_fcs_port_fdmi_sm_rpa_retry(struct bfa_fcs_port_fdmi_s *fdmi, | |
440 | enum port_fdmi_event event) | |
441 | { | |
442 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
443 | ||
444 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
445 | bfa_trc(port->fcs, event); | |
446 | ||
447 | switch (event) { | |
448 | case FDMISM_EVENT_TIMEOUT: | |
449 | /* | |
450 | * Retry Timer Expired. Re-send | |
451 | */ | |
452 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rpa); | |
453 | bfa_fcs_port_fdmi_send_rpa(fdmi, NULL); | |
454 | break; | |
455 | ||
456 | case FDMISM_EVENT_PORT_OFFLINE: | |
457 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | |
458 | bfa_timer_stop(&fdmi->timer); | |
459 | break; | |
460 | ||
461 | default: | |
e641de37 | 462 | bfa_sm_fault(port->fcs, event); |
7725ccfd JH |
463 | } |
464 | } | |
465 | ||
466 | static void | |
467 | bfa_fcs_port_fdmi_sm_online(struct bfa_fcs_port_fdmi_s *fdmi, | |
468 | enum port_fdmi_event event) | |
469 | { | |
470 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
471 | ||
472 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
473 | bfa_trc(port->fcs, event); | |
474 | ||
475 | switch (event) { | |
476 | case FDMISM_EVENT_PORT_OFFLINE: | |
477 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | |
478 | break; | |
479 | ||
480 | default: | |
e641de37 | 481 | bfa_sm_fault(port->fcs, event); |
7725ccfd JH |
482 | } |
483 | } | |
484 | ||
5b098082 KG |
485 | /** |
486 | * FDMI is disabled state. | |
487 | */ | |
488 | static void | |
489 | bfa_fcs_port_fdmi_sm_disabled(struct bfa_fcs_port_fdmi_s *fdmi, | |
490 | enum port_fdmi_event event) | |
491 | { | |
492 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
493 | ||
494 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
495 | bfa_trc(port->fcs, event); | |
496 | ||
497 | /* No op State. It can only be enabled at Driver Init. */ | |
498 | } | |
7725ccfd JH |
499 | |
500 | /** | |
501 | * RHBA : Register HBA Attributes. | |
502 | */ | |
503 | static void | |
504 | bfa_fcs_port_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced) | |
505 | { | |
506 | struct bfa_fcs_port_fdmi_s *fdmi = fdmi_cbarg; | |
507 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
508 | struct fchs_s fchs; | |
509 | int len, attr_len; | |
510 | struct bfa_fcxp_s *fcxp; | |
511 | u8 *pyld; | |
512 | ||
513 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
514 | ||
515 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | |
516 | if (!fcxp) { | |
517 | bfa_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe, | |
518 | bfa_fcs_port_fdmi_send_rhba, fdmi); | |
519 | return; | |
520 | } | |
521 | fdmi->fcxp = fcxp; | |
522 | ||
523 | pyld = bfa_fcxp_get_reqbuf(fcxp); | |
524 | bfa_os_memset(pyld, 0, FC_MAX_PDUSZ); | |
525 | ||
526 | len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_port_get_fcid(port), | |
527 | FDMI_RHBA); | |
528 | ||
529 | attr_len = bfa_fcs_port_fdmi_build_rhba_pyld(fdmi, | |
530 | (u8 *) ((struct ct_hdr_s *) pyld + 1)); | |
531 | ||
532 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | |
533 | FC_CLASS_3, (len + attr_len), &fchs, | |
534 | bfa_fcs_port_fdmi_rhba_response, (void *)fdmi, | |
535 | FC_MAX_PDUSZ, FC_RA_TOV); | |
536 | ||
537 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT); | |
538 | } | |
539 | ||
540 | static u16 | |
541 | bfa_fcs_port_fdmi_build_rhba_pyld(struct bfa_fcs_port_fdmi_s *fdmi, | |
542 | u8 *pyld) | |
543 | { | |
544 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
545 | struct bfa_fcs_fdmi_hba_attr_s hba_attr; /* @todo */ | |
546 | struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr; /* @todo */ | |
547 | struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld; | |
548 | struct fdmi_attr_s *attr; | |
549 | u8 *curr_ptr; | |
550 | u16 len, count; | |
551 | ||
552 | /* | |
553 | * get hba attributes | |
554 | */ | |
555 | bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr); | |
556 | ||
557 | rhba->hba_id = bfa_fcs_port_get_pwwn(port); | |
558 | rhba->port_list.num_ports = bfa_os_htonl(1); | |
559 | rhba->port_list.port_entry = bfa_fcs_port_get_pwwn(port); | |
560 | ||
561 | len = sizeof(rhba->hba_id) + sizeof(rhba->port_list); | |
562 | ||
563 | count = 0; | |
564 | len += sizeof(rhba->hba_attr_blk.attr_count); | |
565 | ||
566 | /* | |
567 | * fill out the invididual entries of the HBA attrib Block | |
568 | */ | |
569 | curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr; | |
570 | ||
571 | /* | |
572 | * Node Name | |
573 | */ | |
574 | attr = (struct fdmi_attr_s *) curr_ptr; | |
575 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_NODENAME); | |
576 | attr->len = sizeof(wwn_t); | |
577 | memcpy(attr->value, &bfa_fcs_port_get_nwwn(port), attr->len); | |
578 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | |
579 | len += attr->len; | |
580 | count++; | |
581 | attr->len = | |
582 | bfa_os_htons(attr->len + sizeof(attr->type) + | |
583 | sizeof(attr->len)); | |
584 | ||
585 | /* | |
586 | * Manufacturer | |
587 | */ | |
588 | attr = (struct fdmi_attr_s *) curr_ptr; | |
589 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MANUFACTURER); | |
590 | attr->len = (u16) strlen(fcs_hba_attr->manufacturer); | |
591 | memcpy(attr->value, fcs_hba_attr->manufacturer, attr->len); | |
592 | /* variable fields need to be 4 byte aligned */ | |
593 | attr->len = fc_roundup(attr->len, sizeof(u32)); | |
594 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | |
595 | len += attr->len; | |
596 | count++; | |
597 | attr->len = | |
598 | bfa_os_htons(attr->len + sizeof(attr->type) + | |
599 | sizeof(attr->len)); | |
600 | ||
601 | /* | |
602 | * Serial Number | |
603 | */ | |
604 | attr = (struct fdmi_attr_s *) curr_ptr; | |
605 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_SERIALNUM); | |
606 | attr->len = (u16) strlen(fcs_hba_attr->serial_num); | |
607 | memcpy(attr->value, fcs_hba_attr->serial_num, attr->len); | |
608 | /* variable fields need to be 4 byte aligned */ | |
609 | attr->len = fc_roundup(attr->len, sizeof(u32)); | |
610 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | |
611 | len += attr->len; | |
612 | count++; | |
613 | attr->len = | |
614 | bfa_os_htons(attr->len + sizeof(attr->type) + | |
615 | sizeof(attr->len)); | |
616 | ||
617 | /* | |
618 | * Model | |
619 | */ | |
620 | attr = (struct fdmi_attr_s *) curr_ptr; | |
621 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL); | |
622 | attr->len = (u16) strlen(fcs_hba_attr->model); | |
623 | memcpy(attr->value, fcs_hba_attr->model, attr->len); | |
624 | /* variable fields need to be 4 byte aligned */ | |
625 | attr->len = fc_roundup(attr->len, sizeof(u32)); | |
626 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | |
627 | len += attr->len; | |
628 | count++; | |
629 | attr->len = | |
630 | bfa_os_htons(attr->len + sizeof(attr->type) + | |
631 | sizeof(attr->len)); | |
632 | ||
633 | /* | |
634 | * Model Desc | |
635 | */ | |
636 | attr = (struct fdmi_attr_s *) curr_ptr; | |
637 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL_DESC); | |
638 | attr->len = (u16) strlen(fcs_hba_attr->model_desc); | |
639 | memcpy(attr->value, fcs_hba_attr->model_desc, attr->len); | |
640 | /* variable fields need to be 4 byte aligned */ | |
641 | attr->len = fc_roundup(attr->len, sizeof(u32)); | |
642 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | |
643 | len += attr->len; | |
644 | count++; | |
645 | attr->len = | |
646 | bfa_os_htons(attr->len + sizeof(attr->type) + | |
647 | sizeof(attr->len)); | |
648 | ||
649 | /* | |
650 | * H/W Version | |
651 | */ | |
652 | if (fcs_hba_attr->hw_version[0] != '\0') { | |
653 | attr = (struct fdmi_attr_s *) curr_ptr; | |
654 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_HW_VERSION); | |
655 | attr->len = (u16) strlen(fcs_hba_attr->hw_version); | |
656 | memcpy(attr->value, fcs_hba_attr->hw_version, attr->len); | |
657 | /* variable fields need to be 4 byte aligned */ | |
658 | attr->len = fc_roundup(attr->len, sizeof(u32)); | |
659 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | |
660 | len += attr->len; | |
661 | count++; | |
662 | attr->len = | |
663 | bfa_os_htons(attr->len + sizeof(attr->type) + | |
664 | sizeof(attr->len)); | |
665 | } | |
666 | ||
667 | /* | |
668 | * Driver Version | |
669 | */ | |
670 | attr = (struct fdmi_attr_s *) curr_ptr; | |
671 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_DRIVER_VERSION); | |
672 | attr->len = (u16) strlen(fcs_hba_attr->driver_version); | |
673 | memcpy(attr->value, fcs_hba_attr->driver_version, attr->len); | |
674 | /* variable fields need to be 4 byte aligned */ | |
675 | attr->len = fc_roundup(attr->len, sizeof(u32)); | |
676 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | |
677 | len += attr->len;; | |
678 | count++; | |
679 | attr->len = | |
680 | bfa_os_htons(attr->len + sizeof(attr->type) + | |
681 | sizeof(attr->len)); | |
682 | ||
683 | /* | |
684 | * Option Rom Version | |
685 | */ | |
686 | if (fcs_hba_attr->option_rom_ver[0] != '\0') { | |
687 | attr = (struct fdmi_attr_s *) curr_ptr; | |
688 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_ROM_VERSION); | |
689 | attr->len = (u16) strlen(fcs_hba_attr->option_rom_ver); | |
690 | memcpy(attr->value, fcs_hba_attr->option_rom_ver, attr->len); | |
691 | /* variable fields need to be 4 byte aligned */ | |
692 | attr->len = fc_roundup(attr->len, sizeof(u32)); | |
693 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | |
694 | len += attr->len; | |
695 | count++; | |
696 | attr->len = | |
697 | bfa_os_htons(attr->len + sizeof(attr->type) + | |
698 | sizeof(attr->len)); | |
699 | } | |
700 | ||
701 | /* | |
702 | * f/w Version = driver version | |
703 | */ | |
704 | attr = (struct fdmi_attr_s *) curr_ptr; | |
705 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_FW_VERSION); | |
706 | attr->len = (u16) strlen(fcs_hba_attr->driver_version); | |
707 | memcpy(attr->value, fcs_hba_attr->driver_version, attr->len); | |
708 | /* variable fields need to be 4 byte aligned */ | |
709 | attr->len = fc_roundup(attr->len, sizeof(u32)); | |
710 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | |
711 | len += attr->len; | |
712 | count++; | |
713 | attr->len = | |
714 | bfa_os_htons(attr->len + sizeof(attr->type) + | |
715 | sizeof(attr->len)); | |
716 | ||
717 | /* | |
718 | * OS Name | |
719 | */ | |
720 | if (fcs_hba_attr->os_name[0] != '\0') { | |
721 | attr = (struct fdmi_attr_s *) curr_ptr; | |
722 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_OS_NAME); | |
723 | attr->len = (u16) strlen(fcs_hba_attr->os_name); | |
724 | memcpy(attr->value, fcs_hba_attr->os_name, attr->len); | |
725 | /* variable fields need to be 4 byte aligned */ | |
726 | attr->len = fc_roundup(attr->len, sizeof(u32)); | |
727 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | |
728 | len += attr->len; | |
729 | count++; | |
730 | attr->len = | |
731 | bfa_os_htons(attr->len + sizeof(attr->type) + | |
732 | sizeof(attr->len)); | |
733 | } | |
734 | ||
735 | /* | |
736 | * MAX_CT_PAYLOAD | |
737 | */ | |
738 | attr = (struct fdmi_attr_s *) curr_ptr; | |
739 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MAX_CT); | |
740 | attr->len = sizeof(fcs_hba_attr->max_ct_pyld); | |
741 | memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, attr->len); | |
742 | len += attr->len; | |
743 | count++; | |
744 | attr->len = | |
745 | bfa_os_htons(attr->len + sizeof(attr->type) + | |
746 | sizeof(attr->len)); | |
747 | ||
748 | /* | |
749 | * Update size of payload | |
750 | */ | |
751 | len += ((sizeof(attr->type) + sizeof(attr->len)) * count); | |
752 | ||
753 | rhba->hba_attr_blk.attr_count = bfa_os_htonl(count); | |
754 | return len; | |
755 | } | |
756 | ||
757 | static void | |
758 | bfa_fcs_port_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | |
759 | void *cbarg, bfa_status_t req_status, | |
760 | u32 rsp_len, u32 resid_len, | |
761 | struct fchs_s *rsp_fchs) | |
762 | { | |
763 | struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)cbarg; | |
764 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
765 | struct ct_hdr_s *cthdr = NULL; | |
766 | ||
767 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
768 | ||
769 | /* | |
770 | * Sanity Checks | |
771 | */ | |
772 | if (req_status != BFA_STATUS_OK) { | |
773 | bfa_trc(port->fcs, req_status); | |
774 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); | |
775 | return; | |
776 | } | |
777 | ||
778 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | |
779 | cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code); | |
780 | ||
781 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | |
782 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK); | |
783 | return; | |
784 | } | |
785 | ||
786 | bfa_trc(port->fcs, cthdr->reason_code); | |
787 | bfa_trc(port->fcs, cthdr->exp_code); | |
788 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); | |
789 | } | |
790 | ||
791 | /** | |
792 | * RPRT : Register Port | |
793 | */ | |
794 | static void | |
795 | bfa_fcs_port_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced) | |
796 | { | |
797 | struct bfa_fcs_port_fdmi_s *fdmi = fdmi_cbarg; | |
798 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
799 | struct fchs_s fchs; | |
800 | u16 len, attr_len; | |
801 | struct bfa_fcxp_s *fcxp; | |
802 | u8 *pyld; | |
803 | ||
804 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
805 | ||
806 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | |
807 | if (!fcxp) { | |
808 | bfa_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe, | |
809 | bfa_fcs_port_fdmi_send_rprt, fdmi); | |
810 | return; | |
811 | } | |
812 | fdmi->fcxp = fcxp; | |
813 | ||
814 | pyld = bfa_fcxp_get_reqbuf(fcxp); | |
815 | bfa_os_memset(pyld, 0, FC_MAX_PDUSZ); | |
816 | ||
817 | len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_port_get_fcid(port), | |
818 | FDMI_RPRT); | |
819 | ||
820 | attr_len = bfa_fcs_port_fdmi_build_rprt_pyld(fdmi, | |
821 | (u8 *) ((struct ct_hdr_s *) pyld + 1)); | |
822 | ||
823 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | |
824 | FC_CLASS_3, len + attr_len, &fchs, | |
825 | bfa_fcs_port_fdmi_rprt_response, (void *)fdmi, | |
826 | FC_MAX_PDUSZ, FC_RA_TOV); | |
827 | ||
828 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT); | |
829 | } | |
830 | ||
831 | /** | |
832 | * This routine builds Port Attribute Block that used in RPA, RPRT commands. | |
833 | */ | |
834 | static u16 | |
835 | bfa_fcs_port_fdmi_build_portattr_block(struct bfa_fcs_port_fdmi_s *fdmi, | |
836 | u8 *pyld) | |
837 | { | |
838 | struct bfa_fcs_fdmi_port_attr_s fcs_port_attr; | |
839 | struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld; | |
840 | struct fdmi_attr_s *attr; | |
841 | u8 *curr_ptr; | |
842 | u16 len; | |
843 | u8 count = 0; | |
844 | ||
845 | /* | |
846 | * get port attributes | |
847 | */ | |
848 | bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr); | |
849 | ||
850 | len = sizeof(port_attrib->attr_count); | |
851 | ||
852 | /* | |
853 | * fill out the invididual entries | |
854 | */ | |
855 | curr_ptr = (u8 *) &port_attrib->port_attr; | |
856 | ||
857 | /* | |
858 | * FC4 Types | |
859 | */ | |
860 | attr = (struct fdmi_attr_s *) curr_ptr; | |
861 | attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FC4_TYPES); | |
862 | attr->len = sizeof(fcs_port_attr.supp_fc4_types); | |
863 | memcpy(attr->value, fcs_port_attr.supp_fc4_types, attr->len); | |
864 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | |
865 | len += attr->len; | |
866 | ++count; | |
867 | attr->len = | |
868 | bfa_os_htons(attr->len + sizeof(attr->type) + | |
869 | sizeof(attr->len)); | |
870 | ||
871 | /* | |
872 | * Supported Speed | |
873 | */ | |
874 | attr = (struct fdmi_attr_s *) curr_ptr; | |
875 | attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_SUPP_SPEED); | |
876 | attr->len = sizeof(fcs_port_attr.supp_speed); | |
877 | memcpy(attr->value, &fcs_port_attr.supp_speed, attr->len); | |
878 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | |
879 | len += attr->len; | |
880 | ++count; | |
881 | attr->len = | |
882 | bfa_os_htons(attr->len + sizeof(attr->type) + | |
883 | sizeof(attr->len)); | |
884 | ||
885 | /* | |
886 | * current Port Speed | |
887 | */ | |
888 | attr = (struct fdmi_attr_s *) curr_ptr; | |
889 | attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_PORT_SPEED); | |
890 | attr->len = sizeof(fcs_port_attr.curr_speed); | |
891 | memcpy(attr->value, &fcs_port_attr.curr_speed, attr->len); | |
892 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | |
893 | len += attr->len; | |
894 | ++count; | |
895 | attr->len = | |
896 | bfa_os_htons(attr->len + sizeof(attr->type) + | |
897 | sizeof(attr->len)); | |
898 | ||
899 | /* | |
900 | * max frame size | |
901 | */ | |
902 | attr = (struct fdmi_attr_s *) curr_ptr; | |
903 | attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FRAME_SIZE); | |
904 | attr->len = sizeof(fcs_port_attr.max_frm_size); | |
905 | memcpy(attr->value, &fcs_port_attr.max_frm_size, attr->len); | |
906 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | |
907 | len += attr->len; | |
908 | ++count; | |
909 | attr->len = | |
910 | bfa_os_htons(attr->len + sizeof(attr->type) + | |
911 | sizeof(attr->len)); | |
912 | ||
913 | /* | |
914 | * OS Device Name | |
915 | */ | |
916 | if (fcs_port_attr.os_device_name[0] != '\0') { | |
917 | attr = (struct fdmi_attr_s *) curr_ptr; | |
918 | attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_DEV_NAME); | |
919 | attr->len = (u16) strlen(fcs_port_attr.os_device_name); | |
920 | memcpy(attr->value, fcs_port_attr.os_device_name, attr->len); | |
921 | /* variable fields need to be 4 byte aligned */ | |
922 | attr->len = fc_roundup(attr->len, sizeof(u32)); | |
923 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | |
924 | len += attr->len; | |
925 | ++count; | |
926 | attr->len = | |
927 | bfa_os_htons(attr->len + sizeof(attr->type) + | |
928 | sizeof(attr->len)); | |
929 | ||
930 | } | |
931 | /* | |
932 | * Host Name | |
933 | */ | |
934 | if (fcs_port_attr.host_name[0] != '\0') { | |
935 | attr = (struct fdmi_attr_s *) curr_ptr; | |
936 | attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_HOST_NAME); | |
937 | attr->len = (u16) strlen(fcs_port_attr.host_name); | |
938 | memcpy(attr->value, fcs_port_attr.host_name, attr->len); | |
939 | /* variable fields need to be 4 byte aligned */ | |
940 | attr->len = fc_roundup(attr->len, sizeof(u32)); | |
941 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | |
942 | len += attr->len; | |
943 | ++count; | |
944 | attr->len = | |
945 | bfa_os_htons(attr->len + sizeof(attr->type) + | |
946 | sizeof(attr->len)); | |
947 | ||
948 | } | |
949 | ||
950 | /* | |
951 | * Update size of payload | |
952 | */ | |
953 | port_attrib->attr_count = bfa_os_htonl(count); | |
954 | len += ((sizeof(attr->type) + sizeof(attr->len)) * count); | |
955 | return len; | |
956 | } | |
957 | ||
958 | static u16 | |
959 | bfa_fcs_port_fdmi_build_rprt_pyld(struct bfa_fcs_port_fdmi_s *fdmi, | |
960 | u8 *pyld) | |
961 | { | |
962 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
963 | struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld; | |
964 | u16 len; | |
965 | ||
966 | rprt->hba_id = bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs)); | |
967 | rprt->port_name = bfa_fcs_port_get_pwwn(port); | |
968 | ||
969 | len = bfa_fcs_port_fdmi_build_portattr_block(fdmi, | |
970 | (u8 *) &rprt->port_attr_blk); | |
971 | ||
972 | len += sizeof(rprt->hba_id) + sizeof(rprt->port_name); | |
973 | ||
974 | return len; | |
975 | } | |
976 | ||
977 | static void | |
978 | bfa_fcs_port_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | |
979 | void *cbarg, bfa_status_t req_status, | |
980 | u32 rsp_len, u32 resid_len, | |
981 | struct fchs_s *rsp_fchs) | |
982 | { | |
983 | struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)cbarg; | |
984 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
985 | struct ct_hdr_s *cthdr = NULL; | |
986 | ||
987 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
988 | ||
989 | /* | |
990 | * Sanity Checks | |
991 | */ | |
992 | if (req_status != BFA_STATUS_OK) { | |
993 | bfa_trc(port->fcs, req_status); | |
994 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); | |
995 | return; | |
996 | } | |
997 | ||
998 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | |
999 | cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code); | |
1000 | ||
1001 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | |
1002 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK); | |
1003 | return; | |
1004 | } | |
1005 | ||
1006 | bfa_trc(port->fcs, cthdr->reason_code); | |
1007 | bfa_trc(port->fcs, cthdr->exp_code); | |
1008 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); | |
1009 | } | |
1010 | ||
1011 | /** | |
1012 | * RPA : Register Port Attributes. | |
1013 | */ | |
1014 | static void | |
1015 | bfa_fcs_port_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced) | |
1016 | { | |
1017 | struct bfa_fcs_port_fdmi_s *fdmi = fdmi_cbarg; | |
1018 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
1019 | struct fchs_s fchs; | |
1020 | u16 len, attr_len; | |
1021 | struct bfa_fcxp_s *fcxp; | |
1022 | u8 *pyld; | |
1023 | ||
1024 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
1025 | ||
1026 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | |
1027 | if (!fcxp) { | |
1028 | bfa_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe, | |
1029 | bfa_fcs_port_fdmi_send_rpa, fdmi); | |
1030 | return; | |
1031 | } | |
1032 | fdmi->fcxp = fcxp; | |
1033 | ||
1034 | pyld = bfa_fcxp_get_reqbuf(fcxp); | |
1035 | bfa_os_memset(pyld, 0, FC_MAX_PDUSZ); | |
1036 | ||
1037 | len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_port_get_fcid(port), | |
1038 | FDMI_RPA); | |
1039 | ||
1040 | attr_len = bfa_fcs_port_fdmi_build_rpa_pyld(fdmi, | |
1041 | (u8 *) ((struct ct_hdr_s *) pyld + 1)); | |
1042 | ||
1043 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | |
1044 | FC_CLASS_3, len + attr_len, &fchs, | |
1045 | bfa_fcs_port_fdmi_rpa_response, (void *)fdmi, | |
1046 | FC_MAX_PDUSZ, FC_RA_TOV); | |
1047 | ||
1048 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT); | |
1049 | } | |
1050 | ||
1051 | static u16 | |
1052 | bfa_fcs_port_fdmi_build_rpa_pyld(struct bfa_fcs_port_fdmi_s *fdmi, | |
1053 | u8 *pyld) | |
1054 | { | |
1055 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
1056 | struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld; | |
1057 | u16 len; | |
1058 | ||
1059 | rpa->port_name = bfa_fcs_port_get_pwwn(port); | |
1060 | ||
1061 | len = bfa_fcs_port_fdmi_build_portattr_block(fdmi, | |
1062 | (u8 *) &rpa->port_attr_blk); | |
1063 | ||
1064 | len += sizeof(rpa->port_name); | |
1065 | ||
1066 | return len; | |
1067 | } | |
1068 | ||
1069 | static void | |
1070 | bfa_fcs_port_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | |
1071 | void *cbarg, bfa_status_t req_status, | |
1072 | u32 rsp_len, u32 resid_len, | |
1073 | struct fchs_s *rsp_fchs) | |
1074 | { | |
1075 | struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)cbarg; | |
1076 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
1077 | struct ct_hdr_s *cthdr = NULL; | |
1078 | ||
1079 | bfa_trc(port->fcs, port->port_cfg.pwwn); | |
1080 | ||
1081 | /* | |
1082 | * Sanity Checks | |
1083 | */ | |
1084 | if (req_status != BFA_STATUS_OK) { | |
1085 | bfa_trc(port->fcs, req_status); | |
1086 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); | |
1087 | return; | |
1088 | } | |
1089 | ||
1090 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | |
1091 | cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code); | |
1092 | ||
1093 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | |
1094 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK); | |
1095 | return; | |
1096 | } | |
1097 | ||
1098 | bfa_trc(port->fcs, cthdr->reason_code); | |
1099 | bfa_trc(port->fcs, cthdr->exp_code); | |
1100 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); | |
1101 | } | |
1102 | ||
1103 | static void | |
1104 | bfa_fcs_port_fdmi_timeout(void *arg) | |
1105 | { | |
1106 | struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)arg; | |
1107 | ||
1108 | bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT); | |
1109 | } | |
1110 | ||
f8ceafde | 1111 | static void |
7725ccfd JH |
1112 | bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_port_fdmi_s *fdmi, |
1113 | struct bfa_fcs_fdmi_hba_attr_s *hba_attr) | |
1114 | { | |
1115 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
1116 | struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info; | |
7725ccfd JH |
1117 | |
1118 | bfa_os_memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s)); | |
7725ccfd | 1119 | |
25e2934c KG |
1120 | bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc, |
1121 | hba_attr->manufacturer); | |
1122 | bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc, | |
1123 | hba_attr->serial_num); | |
1124 | bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc, hba_attr->model); | |
1125 | bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc, hba_attr->model_desc); | |
1126 | bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc, hba_attr->hw_version); | |
1127 | bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc, | |
1128 | hba_attr->option_rom_ver); | |
1129 | bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc, hba_attr->fw_version); | |
7725ccfd JH |
1130 | |
1131 | strncpy(hba_attr->driver_version, (char *)driver_info->version, | |
1132 | sizeof(hba_attr->driver_version)); | |
1133 | ||
7725ccfd JH |
1134 | strncpy(hba_attr->os_name, driver_info->host_os_name, |
1135 | sizeof(hba_attr->os_name)); | |
1136 | ||
1137 | /* | |
1138 | * If there is a patch level, append it to the os name along with a | |
1139 | * separator | |
1140 | */ | |
1141 | if (driver_info->host_os_patch[0] != '\0') { | |
1142 | strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR, | |
1143 | sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); | |
1144 | strncat(hba_attr->os_name, driver_info->host_os_patch, | |
1145 | sizeof(driver_info->host_os_patch)); | |
1146 | } | |
1147 | ||
1148 | hba_attr->max_ct_pyld = bfa_os_htonl(FC_MAX_PDUSZ); | |
1149 | ||
1150 | } | |
1151 | ||
f8ceafde | 1152 | static void |
7725ccfd JH |
1153 | bfa_fcs_fdmi_get_portattr(struct bfa_fcs_port_fdmi_s *fdmi, |
1154 | struct bfa_fcs_fdmi_port_attr_s *port_attr) | |
1155 | { | |
1156 | struct bfa_fcs_port_s *port = fdmi->ms->port; | |
1157 | struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info; | |
1158 | struct bfa_pport_attr_s pport_attr; | |
1159 | ||
1160 | bfa_os_memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s)); | |
1161 | ||
1162 | /* | |
1163 | * get pport attributes from hal | |
1164 | */ | |
1c8a4c37 | 1165 | bfa_fcport_get_attr(port->fcs->bfa, &pport_attr); |
7725ccfd JH |
1166 | |
1167 | /* | |
1168 | * get FC4 type Bitmask | |
1169 | */ | |
1170 | fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types); | |
1171 | ||
1172 | /* | |
1173 | * Supported Speeds | |
1174 | */ | |
1175 | port_attr->supp_speed = bfa_os_htonl(BFA_FCS_FDMI_SUPORTED_SPEEDS); | |
1176 | ||
1177 | /* | |
1178 | * Current Speed | |
1179 | */ | |
1180 | port_attr->curr_speed = bfa_os_htonl(pport_attr.speed); | |
1181 | ||
1182 | /* | |
1183 | * Max PDU Size. | |
1184 | */ | |
1185 | port_attr->max_frm_size = bfa_os_htonl(FC_MAX_PDUSZ); | |
1186 | ||
1187 | /* | |
1188 | * OS device Name | |
1189 | */ | |
1190 | strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name, | |
1191 | sizeof(port_attr->os_device_name)); | |
1192 | ||
1193 | /* | |
1194 | * Host name | |
1195 | */ | |
1196 | strncpy(port_attr->host_name, (char *)driver_info->host_machine_name, | |
1197 | sizeof(port_attr->host_name)); | |
1198 | ||
1199 | } | |
1200 | ||
1201 | ||
1202 | void | |
1203 | bfa_fcs_port_fdmi_init(struct bfa_fcs_port_ms_s *ms) | |
1204 | { | |
1205 | struct bfa_fcs_port_fdmi_s *fdmi = &ms->fdmi; | |
1206 | ||
1207 | fdmi->ms = ms; | |
5b098082 KG |
1208 | if (ms->port->fcs->fdmi_enabled) |
1209 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | |
1210 | else | |
1211 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_disabled); | |
7725ccfd JH |
1212 | } |
1213 | ||
1214 | void | |
1215 | bfa_fcs_port_fdmi_offline(struct bfa_fcs_port_ms_s *ms) | |
1216 | { | |
1217 | struct bfa_fcs_port_fdmi_s *fdmi = &ms->fdmi; | |
1218 | ||
1219 | fdmi->ms = ms; | |
1220 | bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE); | |
1221 | } | |
1222 | ||
1223 | void | |
1224 | bfa_fcs_port_fdmi_online(struct bfa_fcs_port_ms_s *ms) | |
1225 | { | |
1226 | struct bfa_fcs_port_fdmi_s *fdmi = &ms->fdmi; | |
1227 | ||
1228 | fdmi->ms = ms; | |
1229 | bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE); | |
1230 | } |