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