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 | #include <defs/bfa_defs_cee.h> | |
19 | #include <cs/bfa_trc.h> | |
20 | #include <cs/bfa_log.h> | |
21 | #include <cs/bfa_debug.h> | |
22 | #include <cee/bfa_cee.h> | |
23 | #include <bfi/bfi_cee.h> | |
24 | #include <bfi/bfi.h> | |
25 | #include <bfa_ioc.h> | |
26 | #include <cna/bfa_cna_trcmod.h> | |
27 | ||
28 | BFA_TRC_FILE(CNA, CEE); | |
29 | ||
30 | #define bfa_ioc_portid(__ioc) ((__ioc)->port_id) | |
31 | #define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc) | |
32 | ||
33 | static void bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg); | |
34 | static void bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s | |
35 | *dcbcx_stats); | |
36 | static void bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s | |
37 | *lldp_stats); | |
38 | static void bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats); | |
39 | static void bfa_cee_format_cee_cfg(void *buffer); | |
40 | static void bfa_cee_format_cee_stats(void *buffer); | |
41 | ||
42 | static void | |
43 | bfa_cee_format_cee_stats(void *buffer) | |
44 | { | |
45 | struct bfa_cee_stats_s *cee_stats = buffer; | |
46 | bfa_cee_format_dcbcx_stats(&cee_stats->dcbx_stats); | |
47 | bfa_cee_format_lldp_stats(&cee_stats->lldp_stats); | |
48 | bfa_cee_format_cfg_stats(&cee_stats->cfg_stats); | |
49 | } | |
50 | ||
51 | static void | |
52 | bfa_cee_format_cee_cfg(void *buffer) | |
53 | { | |
54 | struct bfa_cee_attr_s *cee_cfg = buffer; | |
55 | bfa_cee_format_lldp_cfg(&cee_cfg->lldp_remote); | |
56 | } | |
57 | ||
58 | static void | |
59 | bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s *dcbcx_stats) | |
60 | { | |
61 | dcbcx_stats->subtlvs_unrecognized = | |
62 | bfa_os_ntohl(dcbcx_stats->subtlvs_unrecognized); | |
63 | dcbcx_stats->negotiation_failed = | |
64 | bfa_os_ntohl(dcbcx_stats->negotiation_failed); | |
65 | dcbcx_stats->remote_cfg_changed = | |
66 | bfa_os_ntohl(dcbcx_stats->remote_cfg_changed); | |
67 | dcbcx_stats->tlvs_received = bfa_os_ntohl(dcbcx_stats->tlvs_received); | |
68 | dcbcx_stats->tlvs_invalid = bfa_os_ntohl(dcbcx_stats->tlvs_invalid); | |
69 | dcbcx_stats->seqno = bfa_os_ntohl(dcbcx_stats->seqno); | |
70 | dcbcx_stats->ackno = bfa_os_ntohl(dcbcx_stats->ackno); | |
71 | dcbcx_stats->recvd_seqno = bfa_os_ntohl(dcbcx_stats->recvd_seqno); | |
72 | dcbcx_stats->recvd_ackno = bfa_os_ntohl(dcbcx_stats->recvd_ackno); | |
73 | } | |
74 | ||
75 | static void | |
76 | bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s *lldp_stats) | |
77 | { | |
78 | lldp_stats->frames_transmitted = | |
79 | bfa_os_ntohl(lldp_stats->frames_transmitted); | |
80 | lldp_stats->frames_aged_out = bfa_os_ntohl(lldp_stats->frames_aged_out); | |
81 | lldp_stats->frames_discarded = | |
82 | bfa_os_ntohl(lldp_stats->frames_discarded); | |
83 | lldp_stats->frames_in_error = bfa_os_ntohl(lldp_stats->frames_in_error); | |
84 | lldp_stats->frames_rcvd = bfa_os_ntohl(lldp_stats->frames_rcvd); | |
85 | lldp_stats->tlvs_discarded = bfa_os_ntohl(lldp_stats->tlvs_discarded); | |
86 | lldp_stats->tlvs_unrecognized = | |
87 | bfa_os_ntohl(lldp_stats->tlvs_unrecognized); | |
88 | } | |
89 | ||
90 | static void | |
91 | bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats) | |
92 | { | |
93 | cfg_stats->cee_status_down = bfa_os_ntohl(cfg_stats->cee_status_down); | |
94 | cfg_stats->cee_status_up = bfa_os_ntohl(cfg_stats->cee_status_up); | |
95 | cfg_stats->cee_hw_cfg_changed = | |
96 | bfa_os_ntohl(cfg_stats->cee_hw_cfg_changed); | |
97 | cfg_stats->recvd_invalid_cfg = | |
98 | bfa_os_ntohl(cfg_stats->recvd_invalid_cfg); | |
99 | } | |
100 | ||
101 | static void | |
102 | bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg) | |
103 | { | |
104 | lldp_cfg->time_to_interval = bfa_os_ntohs(lldp_cfg->time_to_interval); | |
105 | lldp_cfg->enabled_system_cap = | |
106 | bfa_os_ntohs(lldp_cfg->enabled_system_cap); | |
107 | } | |
108 | ||
109 | /** | |
110 | * bfa_cee_attr_meminfo() | |
111 | * | |
112 | * | |
113 | * @param[in] void | |
114 | * | |
115 | * @return Size of DMA region | |
116 | */ | |
117 | static u32 | |
118 | bfa_cee_attr_meminfo(void) | |
119 | { | |
120 | return BFA_ROUNDUP(sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ); | |
121 | } | |
122 | ||
123 | /** | |
124 | * bfa_cee_stats_meminfo() | |
125 | * | |
126 | * | |
127 | * @param[in] void | |
128 | * | |
129 | * @return Size of DMA region | |
130 | */ | |
131 | static u32 | |
132 | bfa_cee_stats_meminfo(void) | |
133 | { | |
134 | return BFA_ROUNDUP(sizeof(struct bfa_cee_stats_s), BFA_DMA_ALIGN_SZ); | |
135 | } | |
136 | ||
137 | /** | |
138 | * bfa_cee_get_attr_isr() | |
139 | * | |
140 | * | |
141 | * @param[in] cee - Pointer to the CEE module | |
142 | * status - Return status from the f/w | |
143 | * | |
144 | * @return void | |
145 | */ | |
146 | static void | |
147 | bfa_cee_get_attr_isr(struct bfa_cee_s *cee, bfa_status_t status) | |
148 | { | |
149 | cee->get_attr_status = status; | |
150 | bfa_trc(cee, 0); | |
151 | if (status == BFA_STATUS_OK) { | |
152 | bfa_trc(cee, 0); | |
153 | /* | |
154 | * The requested data has been copied to the DMA area, *process | |
155 | * it. | |
156 | */ | |
157 | memcpy(cee->attr, cee->attr_dma.kva, | |
158 | sizeof(struct bfa_cee_attr_s)); | |
159 | bfa_cee_format_cee_cfg(cee->attr); | |
160 | } | |
161 | cee->get_attr_pending = BFA_FALSE; | |
162 | if (cee->cbfn.get_attr_cbfn) { | |
163 | bfa_trc(cee, 0); | |
164 | cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status); | |
165 | } | |
166 | bfa_trc(cee, 0); | |
167 | } | |
168 | ||
169 | /** | |
170 | * bfa_cee_get_attr_isr() | |
171 | * | |
172 | * | |
173 | * @param[in] cee - Pointer to the CEE module | |
174 | * status - Return status from the f/w | |
175 | * | |
176 | * @return void | |
177 | */ | |
178 | static void | |
179 | bfa_cee_get_stats_isr(struct bfa_cee_s *cee, bfa_status_t status) | |
180 | { | |
181 | cee->get_stats_status = status; | |
182 | bfa_trc(cee, 0); | |
183 | if (status == BFA_STATUS_OK) { | |
184 | bfa_trc(cee, 0); | |
185 | /* | |
186 | * The requested data has been copied to the DMA area, process | |
187 | * it. | |
188 | */ | |
189 | memcpy(cee->stats, cee->stats_dma.kva, | |
190 | sizeof(struct bfa_cee_stats_s)); | |
191 | bfa_cee_format_cee_stats(cee->stats); | |
192 | } | |
193 | cee->get_stats_pending = BFA_FALSE; | |
194 | bfa_trc(cee, 0); | |
195 | if (cee->cbfn.get_stats_cbfn) { | |
196 | bfa_trc(cee, 0); | |
197 | cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status); | |
198 | } | |
199 | bfa_trc(cee, 0); | |
200 | } | |
201 | ||
202 | /** | |
203 | * bfa_cee_get_attr_isr() | |
204 | * | |
205 | * | |
206 | * @param[in] cee - Pointer to the CEE module | |
207 | * status - Return status from the f/w | |
208 | * | |
209 | * @return void | |
210 | */ | |
211 | static void | |
212 | bfa_cee_reset_stats_isr(struct bfa_cee_s *cee, bfa_status_t status) | |
213 | { | |
214 | cee->reset_stats_status = status; | |
215 | cee->reset_stats_pending = BFA_FALSE; | |
216 | if (cee->cbfn.reset_stats_cbfn) | |
217 | cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status); | |
218 | } | |
219 | ||
220 | /** | |
221 | * bfa_cee_meminfo() | |
222 | * | |
223 | * | |
224 | * @param[in] void | |
225 | * | |
226 | * @return Size of DMA region | |
227 | */ | |
228 | u32 | |
229 | bfa_cee_meminfo(void) | |
230 | { | |
f8ceafde | 231 | return bfa_cee_attr_meminfo() + bfa_cee_stats_meminfo(); |
7725ccfd JH |
232 | } |
233 | ||
234 | /** | |
235 | * bfa_cee_mem_claim() | |
236 | * | |
237 | * | |
238 | * @param[in] cee CEE module pointer | |
239 | * dma_kva Kernel Virtual Address of CEE DMA Memory | |
240 | * dma_pa Physical Address of CEE DMA Memory | |
241 | * | |
242 | * @return void | |
243 | */ | |
244 | void | |
245 | bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva, u64 dma_pa) | |
246 | { | |
247 | cee->attr_dma.kva = dma_kva; | |
248 | cee->attr_dma.pa = dma_pa; | |
249 | cee->stats_dma.kva = dma_kva + bfa_cee_attr_meminfo(); | |
250 | cee->stats_dma.pa = dma_pa + bfa_cee_attr_meminfo(); | |
251 | cee->attr = (struct bfa_cee_attr_s *)dma_kva; | |
252 | cee->stats = | |
253 | (struct bfa_cee_stats_s *)(dma_kva + bfa_cee_attr_meminfo()); | |
254 | } | |
255 | ||
256 | /** | |
257 | * bfa_cee_get_attr() | |
258 | * | |
259 | * Send the request to the f/w to fetch CEE attributes. | |
260 | * | |
261 | * @param[in] Pointer to the CEE module data structure. | |
262 | * | |
263 | * @return Status | |
264 | */ | |
265 | ||
266 | bfa_status_t | |
267 | bfa_cee_get_attr(struct bfa_cee_s *cee, struct bfa_cee_attr_s *attr, | |
268 | bfa_cee_get_attr_cbfn_t cbfn, void *cbarg) | |
269 | { | |
270 | struct bfi_cee_get_req_s *cmd; | |
271 | ||
272 | bfa_assert((cee != NULL) && (cee->ioc != NULL)); | |
273 | bfa_trc(cee, 0); | |
274 | if (!bfa_ioc_is_operational(cee->ioc)) { | |
275 | bfa_trc(cee, 0); | |
276 | return BFA_STATUS_IOC_FAILURE; | |
277 | } | |
278 | if (cee->get_attr_pending == BFA_TRUE) { | |
279 | bfa_trc(cee, 0); | |
280 | return BFA_STATUS_DEVBUSY; | |
281 | } | |
282 | cee->get_attr_pending = BFA_TRUE; | |
283 | cmd = (struct bfi_cee_get_req_s *)cee->get_cfg_mb.msg; | |
284 | cee->attr = attr; | |
285 | cee->cbfn.get_attr_cbfn = cbfn; | |
286 | cee->cbfn.get_attr_cbarg = cbarg; | |
287 | bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ, | |
288 | bfa_ioc_portid(cee->ioc)); | |
289 | bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa); | |
290 | bfa_ioc_mbox_queue(cee->ioc, &cee->get_cfg_mb); | |
291 | bfa_trc(cee, 0); | |
292 | ||
293 | return BFA_STATUS_OK; | |
294 | } | |
295 | ||
296 | /** | |
297 | * bfa_cee_get_stats() | |
298 | * | |
299 | * Send the request to the f/w to fetch CEE statistics. | |
300 | * | |
301 | * @param[in] Pointer to the CEE module data structure. | |
302 | * | |
303 | * @return Status | |
304 | */ | |
305 | ||
306 | bfa_status_t | |
307 | bfa_cee_get_stats(struct bfa_cee_s *cee, struct bfa_cee_stats_s *stats, | |
308 | bfa_cee_get_stats_cbfn_t cbfn, void *cbarg) | |
309 | { | |
310 | struct bfi_cee_get_req_s *cmd; | |
311 | ||
312 | bfa_assert((cee != NULL) && (cee->ioc != NULL)); | |
313 | ||
314 | if (!bfa_ioc_is_operational(cee->ioc)) { | |
315 | bfa_trc(cee, 0); | |
316 | return BFA_STATUS_IOC_FAILURE; | |
317 | } | |
318 | if (cee->get_stats_pending == BFA_TRUE) { | |
319 | bfa_trc(cee, 0); | |
320 | return BFA_STATUS_DEVBUSY; | |
321 | } | |
322 | cee->get_stats_pending = BFA_TRUE; | |
323 | cmd = (struct bfi_cee_get_req_s *)cee->get_stats_mb.msg; | |
324 | cee->stats = stats; | |
325 | cee->cbfn.get_stats_cbfn = cbfn; | |
326 | cee->cbfn.get_stats_cbarg = cbarg; | |
327 | bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_STATS_REQ, | |
328 | bfa_ioc_portid(cee->ioc)); | |
329 | bfa_dma_be_addr_set(cmd->dma_addr, cee->stats_dma.pa); | |
330 | bfa_ioc_mbox_queue(cee->ioc, &cee->get_stats_mb); | |
331 | bfa_trc(cee, 0); | |
332 | ||
333 | return BFA_STATUS_OK; | |
334 | } | |
335 | ||
336 | /** | |
337 | * bfa_cee_reset_stats() | |
338 | * | |
339 | * | |
340 | * @param[in] Pointer to the CEE module data structure. | |
341 | * | |
342 | * @return Status | |
343 | */ | |
344 | ||
345 | bfa_status_t | |
346 | bfa_cee_reset_stats(struct bfa_cee_s *cee, bfa_cee_reset_stats_cbfn_t cbfn, | |
347 | void *cbarg) | |
348 | { | |
349 | struct bfi_cee_reset_stats_s *cmd; | |
350 | ||
351 | bfa_assert((cee != NULL) && (cee->ioc != NULL)); | |
352 | if (!bfa_ioc_is_operational(cee->ioc)) { | |
353 | bfa_trc(cee, 0); | |
354 | return BFA_STATUS_IOC_FAILURE; | |
355 | } | |
356 | if (cee->reset_stats_pending == BFA_TRUE) { | |
357 | bfa_trc(cee, 0); | |
358 | return BFA_STATUS_DEVBUSY; | |
359 | } | |
360 | cee->reset_stats_pending = BFA_TRUE; | |
361 | cmd = (struct bfi_cee_reset_stats_s *)cee->reset_stats_mb.msg; | |
362 | cee->cbfn.reset_stats_cbfn = cbfn; | |
363 | cee->cbfn.reset_stats_cbarg = cbarg; | |
364 | bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_RESET_STATS, | |
365 | bfa_ioc_portid(cee->ioc)); | |
366 | bfa_ioc_mbox_queue(cee->ioc, &cee->reset_stats_mb); | |
367 | bfa_trc(cee, 0); | |
368 | return BFA_STATUS_OK; | |
369 | } | |
370 | ||
371 | /** | |
372 | * bfa_cee_isrs() | |
373 | * | |
374 | * | |
375 | * @param[in] Pointer to the CEE module data structure. | |
376 | * | |
377 | * @return void | |
378 | */ | |
379 | ||
380 | void | |
381 | bfa_cee_isr(void *cbarg, struct bfi_mbmsg_s *m) | |
382 | { | |
383 | union bfi_cee_i2h_msg_u *msg; | |
384 | struct bfi_cee_get_rsp_s *get_rsp; | |
385 | struct bfa_cee_s *cee = (struct bfa_cee_s *)cbarg; | |
386 | msg = (union bfi_cee_i2h_msg_u *)m; | |
387 | get_rsp = (struct bfi_cee_get_rsp_s *)m; | |
388 | bfa_trc(cee, msg->mh.msg_id); | |
389 | switch (msg->mh.msg_id) { | |
390 | case BFI_CEE_I2H_GET_CFG_RSP: | |
391 | bfa_trc(cee, get_rsp->cmd_status); | |
392 | bfa_cee_get_attr_isr(cee, get_rsp->cmd_status); | |
393 | break; | |
394 | case BFI_CEE_I2H_GET_STATS_RSP: | |
395 | bfa_cee_get_stats_isr(cee, get_rsp->cmd_status); | |
396 | break; | |
397 | case BFI_CEE_I2H_RESET_STATS_RSP: | |
398 | bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status); | |
399 | break; | |
400 | default: | |
401 | bfa_assert(0); | |
402 | } | |
403 | } | |
404 | ||
405 | /** | |
406 | * bfa_cee_hbfail() | |
407 | * | |
408 | * | |
409 | * @param[in] Pointer to the CEE module data structure. | |
410 | * | |
411 | * @return void | |
412 | */ | |
413 | ||
414 | void | |
415 | bfa_cee_hbfail(void *arg) | |
416 | { | |
417 | struct bfa_cee_s *cee; | |
418 | cee = (struct bfa_cee_s *)arg; | |
419 | ||
420 | if (cee->get_attr_pending == BFA_TRUE) { | |
421 | cee->get_attr_status = BFA_STATUS_FAILED; | |
422 | cee->get_attr_pending = BFA_FALSE; | |
423 | if (cee->cbfn.get_attr_cbfn) { | |
424 | cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, | |
425 | BFA_STATUS_FAILED); | |
426 | } | |
427 | } | |
428 | if (cee->get_stats_pending == BFA_TRUE) { | |
429 | cee->get_stats_status = BFA_STATUS_FAILED; | |
430 | cee->get_stats_pending = BFA_FALSE; | |
431 | if (cee->cbfn.get_stats_cbfn) { | |
432 | cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, | |
433 | BFA_STATUS_FAILED); | |
434 | } | |
435 | } | |
436 | if (cee->reset_stats_pending == BFA_TRUE) { | |
437 | cee->reset_stats_status = BFA_STATUS_FAILED; | |
438 | cee->reset_stats_pending = BFA_FALSE; | |
439 | if (cee->cbfn.reset_stats_cbfn) { | |
440 | cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, | |
441 | BFA_STATUS_FAILED); | |
442 | } | |
443 | } | |
444 | } | |
445 | ||
446 | /** | |
447 | * bfa_cee_attach() | |
448 | * | |
449 | * | |
450 | * @param[in] cee - Pointer to the CEE module data structure | |
451 | * ioc - Pointer to the ioc module data structure | |
452 | * dev - Pointer to the device driver module data structure | |
453 | * The device driver specific mbox ISR functions have | |
454 | * this pointer as one of the parameters. | |
455 | * trcmod - | |
456 | * logmod - | |
457 | * | |
458 | * @return void | |
459 | */ | |
460 | void | |
461 | bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc, void *dev, | |
462 | struct bfa_trc_mod_s *trcmod, struct bfa_log_mod_s *logmod) | |
463 | { | |
464 | bfa_assert(cee != NULL); | |
465 | cee->dev = dev; | |
466 | cee->trcmod = trcmod; | |
467 | cee->logmod = logmod; | |
468 | cee->ioc = ioc; | |
469 | ||
470 | bfa_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee); | |
471 | bfa_ioc_hbfail_init(&cee->hbfail, bfa_cee_hbfail, cee); | |
472 | bfa_ioc_hbfail_register(cee->ioc, &cee->hbfail); | |
473 | bfa_trc(cee, 0); | |
474 | } | |
475 | ||
476 | /** | |
477 | * bfa_cee_detach() | |
478 | * | |
479 | * | |
480 | * @param[in] cee - Pointer to the CEE module data structure | |
481 | * | |
482 | * @return void | |
483 | */ | |
484 | void | |
485 | bfa_cee_detach(struct bfa_cee_s *cee) | |
486 | { | |
487 | /* | |
488 | * For now, just check if there is some ioctl pending and mark that as | |
489 | * failed? | |
490 | */ | |
491 | /* bfa_cee_hbfail(cee); */ | |
492 | } |