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); | |
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 | ||
f8ceafde | 1094 | static void |
7725ccfd JH |
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 | ||
f8ceafde | 1148 | static void |
7725ccfd JH |
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 | } |