1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
4 * Copyright (c) 2014- QLogic Corporation.
5 * All rights reserved
6 * www.qlogic.com
7 *
8 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
9 */
10
11#include "bfad_drv.h"
12#include "bfa_defs_svc.h"
13#include "bfa_port.h"
14#include "bfi.h"
15#include "bfa_ioc.h"
16
17
18BFA_TRC_FILE(CNA, PORT);
19
20static void
21bfa_port_stats_swap(struct bfa_port_s *port, union bfa_port_stats_u *stats)
22{
23 u32 *dip = (u32 *) stats;
24 __be32 t0, t1;
25 int i;
26
27 for (i = 0; i < sizeof(union bfa_port_stats_u)/sizeof(u32);
28 i += 2) {
29 t0 = dip[i];
30 t1 = dip[i + 1];
31#ifdef __BIG_ENDIAN
32 dip[i] = be32_to_cpu(t0);
33 dip[i + 1] = be32_to_cpu(t1);
34#else
35 dip[i] = be32_to_cpu(t1);
36 dip[i + 1] = be32_to_cpu(t0);
37#endif
38 }
39}
40
41/*
42 * bfa_port_enable_isr()
43 *
44 *
45 * @param[in] port - Pointer to the port module
46 * status - Return status from the f/w
47 *
48 * @return void
49 */
50static void
51bfa_port_enable_isr(struct bfa_port_s *port, bfa_status_t status)
52{
53 bfa_trc(port, status);
54 port->endis_pending = BFA_FALSE;
55 port->endis_cbfn(port->endis_cbarg, status);
56}
57
58/*
59 * bfa_port_disable_isr()
60 *
61 *
62 * @param[in] port - Pointer to the port module
63 * status - Return status from the f/w
64 *
65 * @return void
66 */
67static void
68bfa_port_disable_isr(struct bfa_port_s *port, bfa_status_t status)
69{
70 bfa_trc(port, status);
71 port->endis_pending = BFA_FALSE;
72 port->endis_cbfn(port->endis_cbarg, status);
73}
74
75/*
76 * bfa_port_get_stats_isr()
77 *
78 *
79 * @param[in] port - Pointer to the Port module
80 * status - Return status from the f/w
81 *
82 * @return void
83 */
84static void
85bfa_port_get_stats_isr(struct bfa_port_s *port, bfa_status_t status)
86{
87 port->stats_status = status;
88 port->stats_busy = BFA_FALSE;
89
90 if (status == BFA_STATUS_OK) {
91 memcpy(port->stats, port->stats_dma.kva,
92 sizeof(union bfa_port_stats_u));
93 bfa_port_stats_swap(port, stats: port->stats);
94
95 port->stats->fc.secs_reset = ktime_get_seconds() - port->stats_reset_time;
96 }
97
98 if (port->stats_cbfn) {
99 port->stats_cbfn(port->stats_cbarg, status);
100 port->stats_cbfn = NULL;
101 }
102}
103
104/*
105 * bfa_port_clear_stats_isr()
106 *
107 *
108 * @param[in] port - Pointer to the Port module
109 * status - Return status from the f/w
110 *
111 * @return void
112 */
113static void
114bfa_port_clear_stats_isr(struct bfa_port_s *port, bfa_status_t status)
115{
116 port->stats_status = status;
117 port->stats_busy = BFA_FALSE;
118
119 /*
120 * re-initialize time stamp for stats reset
121 */
122 port->stats_reset_time = ktime_get_seconds();
123
124 if (port->stats_cbfn) {
125 port->stats_cbfn(port->stats_cbarg, status);
126 port->stats_cbfn = NULL;
127 }
128}
129
130/*
131 * bfa_port_isr()
132 *
133 *
134 * @param[in] Pointer to the Port module data structure.
135 *
136 * @return void
137 */
138static void
139bfa_port_isr(void *cbarg, struct bfi_mbmsg_s *m)
140{
141 struct bfa_port_s *port = (struct bfa_port_s *) cbarg;
142 union bfi_port_i2h_msg_u *i2hmsg;
143
144 i2hmsg = (union bfi_port_i2h_msg_u *) m;
145 bfa_trc(port, m->mh.msg_id);
146
147 switch (m->mh.msg_id) {
148 case BFI_PORT_I2H_ENABLE_RSP:
149 if (port->endis_pending == BFA_FALSE)
150 break;
151 bfa_port_enable_isr(port, status: i2hmsg->enable_rsp.status);
152 break;
153
154 case BFI_PORT_I2H_DISABLE_RSP:
155 if (port->endis_pending == BFA_FALSE)
156 break;
157 bfa_port_disable_isr(port, status: i2hmsg->disable_rsp.status);
158 break;
159
160 case BFI_PORT_I2H_GET_STATS_RSP:
161 /* Stats busy flag is still set? (may be cmd timed out) */
162 if (port->stats_busy == BFA_FALSE)
163 break;
164 bfa_port_get_stats_isr(port, status: i2hmsg->getstats_rsp.status);
165 break;
166
167 case BFI_PORT_I2H_CLEAR_STATS_RSP:
168 if (port->stats_busy == BFA_FALSE)
169 break;
170 bfa_port_clear_stats_isr(port, status: i2hmsg->clearstats_rsp.status);
171 break;
172
173 default:
174 WARN_ON(1);
175 }
176}
177
178/*
179 * bfa_port_meminfo()
180 *
181 *
182 * @param[in] void
183 *
184 * @return Size of DMA region
185 */
186u32
187bfa_port_meminfo(void)
188{
189 return BFA_ROUNDUP(sizeof(union bfa_port_stats_u), BFA_DMA_ALIGN_SZ);
190}
191
192/*
193 * bfa_port_mem_claim()
194 *
195 *
196 * @param[in] port Port module pointer
197 * dma_kva Kernel Virtual Address of Port DMA Memory
198 * dma_pa Physical Address of Port DMA Memory
199 *
200 * @return void
201 */
202void
203bfa_port_mem_claim(struct bfa_port_s *port, u8 *dma_kva, u64 dma_pa)
204{
205 port->stats_dma.kva = dma_kva;
206 port->stats_dma.pa = dma_pa;
207}
208
209/*
210 * bfa_port_enable()
211 *
212 * Send the Port enable request to the f/w
213 *
214 * @param[in] Pointer to the Port module data structure.
215 *
216 * @return Status
217 */
218bfa_status_t
219bfa_port_enable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
220 void *cbarg)
221{
222 struct bfi_port_generic_req_s *m;
223
224 /* If port is PBC disabled, return error */
225 if (port->pbc_disabled) {
226 bfa_trc(port, BFA_STATUS_PBC);
227 return BFA_STATUS_PBC;
228 }
229
230 if (bfa_ioc_is_disabled(ioc: port->ioc)) {
231 bfa_trc(port, BFA_STATUS_IOC_DISABLED);
232 return BFA_STATUS_IOC_DISABLED;
233 }
234
235 if (!bfa_ioc_is_operational(ioc: port->ioc)) {
236 bfa_trc(port, BFA_STATUS_IOC_FAILURE);
237 return BFA_STATUS_IOC_FAILURE;
238 }
239
240 /* if port is d-port enabled, return error */
241 if (port->dport_enabled) {
242 bfa_trc(port, BFA_STATUS_DPORT_ERR);
243 return BFA_STATUS_DPORT_ERR;
244 }
245
246 if (port->endis_pending) {
247 bfa_trc(port, BFA_STATUS_DEVBUSY);
248 return BFA_STATUS_DEVBUSY;
249 }
250
251 m = (struct bfi_port_generic_req_s *) port->endis_mb.msg;
252
253 port->msgtag++;
254 port->endis_cbfn = cbfn;
255 port->endis_cbarg = cbarg;
256 port->endis_pending = BFA_TRUE;
257
258 bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_ENABLE_REQ,
259 bfa_ioc_portid(port->ioc));
260 bfa_ioc_mbox_queue(ioc: port->ioc, cmd: &port->endis_mb);
261
262 return BFA_STATUS_OK;
263}
264
265/*
266 * bfa_port_disable()
267 *
268 * Send the Port disable request to the f/w
269 *
270 * @param[in] Pointer to the Port module data structure.
271 *
272 * @return Status
273 */
274bfa_status_t
275bfa_port_disable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
276 void *cbarg)
277{
278 struct bfi_port_generic_req_s *m;
279
280 /* If port is PBC disabled, return error */
281 if (port->pbc_disabled) {
282 bfa_trc(port, BFA_STATUS_PBC);
283 return BFA_STATUS_PBC;
284 }
285
286 if (bfa_ioc_is_disabled(ioc: port->ioc)) {
287 bfa_trc(port, BFA_STATUS_IOC_DISABLED);
288 return BFA_STATUS_IOC_DISABLED;
289 }
290
291 if (!bfa_ioc_is_operational(ioc: port->ioc)) {
292 bfa_trc(port, BFA_STATUS_IOC_FAILURE);
293 return BFA_STATUS_IOC_FAILURE;
294 }
295
296 /* if port is d-port enabled, return error */
297 if (port->dport_enabled) {
298 bfa_trc(port, BFA_STATUS_DPORT_ERR);
299 return BFA_STATUS_DPORT_ERR;
300 }
301
302 if (port->endis_pending) {
303 bfa_trc(port, BFA_STATUS_DEVBUSY);
304 return BFA_STATUS_DEVBUSY;
305 }
306
307 m = (struct bfi_port_generic_req_s *) port->endis_mb.msg;
308
309 port->msgtag++;
310 port->endis_cbfn = cbfn;
311 port->endis_cbarg = cbarg;
312 port->endis_pending = BFA_TRUE;
313
314 bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_DISABLE_REQ,
315 bfa_ioc_portid(port->ioc));
316 bfa_ioc_mbox_queue(ioc: port->ioc, cmd: &port->endis_mb);
317
318 return BFA_STATUS_OK;
319}
320
321/*
322 * bfa_port_get_stats()
323 *
324 * Send the request to the f/w to fetch Port statistics.
325 *
326 * @param[in] Pointer to the Port module data structure.
327 *
328 * @return Status
329 */
330bfa_status_t
331bfa_port_get_stats(struct bfa_port_s *port, union bfa_port_stats_u *stats,
332 bfa_port_stats_cbfn_t cbfn, void *cbarg)
333{
334 struct bfi_port_get_stats_req_s *m;
335
336 if (!bfa_ioc_is_operational(ioc: port->ioc)) {
337 bfa_trc(port, BFA_STATUS_IOC_FAILURE);
338 return BFA_STATUS_IOC_FAILURE;
339 }
340
341 if (port->stats_busy) {
342 bfa_trc(port, BFA_STATUS_DEVBUSY);
343 return BFA_STATUS_DEVBUSY;
344 }
345
346 m = (struct bfi_port_get_stats_req_s *) port->stats_mb.msg;
347
348 port->stats = stats;
349 port->stats_cbfn = cbfn;
350 port->stats_cbarg = cbarg;
351 port->stats_busy = BFA_TRUE;
352 bfa_dma_be_addr_set(m->dma_addr, port->stats_dma.pa);
353
354 bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_GET_STATS_REQ,
355 bfa_ioc_portid(port->ioc));
356 bfa_ioc_mbox_queue(ioc: port->ioc, cmd: &port->stats_mb);
357
358 return BFA_STATUS_OK;
359}
360
361/*
362 * bfa_port_clear_stats()
363 *
364 *
365 * @param[in] Pointer to the Port module data structure.
366 *
367 * @return Status
368 */
369bfa_status_t
370bfa_port_clear_stats(struct bfa_port_s *port, bfa_port_stats_cbfn_t cbfn,
371 void *cbarg)
372{
373 struct bfi_port_generic_req_s *m;
374
375 if (!bfa_ioc_is_operational(ioc: port->ioc)) {
376 bfa_trc(port, BFA_STATUS_IOC_FAILURE);
377 return BFA_STATUS_IOC_FAILURE;
378 }
379
380 if (port->stats_busy) {
381 bfa_trc(port, BFA_STATUS_DEVBUSY);
382 return BFA_STATUS_DEVBUSY;
383 }
384
385 m = (struct bfi_port_generic_req_s *) port->stats_mb.msg;
386
387 port->stats_cbfn = cbfn;
388 port->stats_cbarg = cbarg;
389 port->stats_busy = BFA_TRUE;
390
391 bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_CLEAR_STATS_REQ,
392 bfa_ioc_portid(port->ioc));
393 bfa_ioc_mbox_queue(ioc: port->ioc, cmd: &port->stats_mb);
394
395 return BFA_STATUS_OK;
396}
397
398/*
399 * bfa_port_notify()
400 *
401 * Port module IOC event handler
402 *
403 * @param[in] Pointer to the Port module data structure.
404 * @param[in] IOC event structure
405 *
406 * @return void
407 */
408void
409bfa_port_notify(void *arg, enum bfa_ioc_event_e event)
410{
411 struct bfa_port_s *port = (struct bfa_port_s *) arg;
412
413 switch (event) {
414 case BFA_IOC_E_DISABLED:
415 case BFA_IOC_E_FAILED:
416 /* Fail any pending get_stats/clear_stats requests */
417 if (port->stats_busy) {
418 if (port->stats_cbfn)
419 port->stats_cbfn(port->stats_cbarg,
420 BFA_STATUS_FAILED);
421 port->stats_cbfn = NULL;
422 port->stats_busy = BFA_FALSE;
423 }
424
425 /* Clear any enable/disable is pending */
426 if (port->endis_pending) {
427 if (port->endis_cbfn)
428 port->endis_cbfn(port->endis_cbarg,
429 BFA_STATUS_FAILED);
430 port->endis_cbfn = NULL;
431 port->endis_pending = BFA_FALSE;
432 }
433
434 /* clear D-port mode */
435 if (port->dport_enabled)
436 bfa_port_set_dportenabled(port, enabled: BFA_FALSE);
437 break;
438 default:
439 break;
440 }
441}
442
443/*
444 * bfa_port_attach()
445 *
446 *
447 * @param[in] port - Pointer to the Port module data structure
448 * ioc - Pointer to the ioc module data structure
449 * dev - Pointer to the device driver module data structure
450 * The device driver specific mbox ISR functions have
451 * this pointer as one of the parameters.
452 * trcmod -
453 *
454 * @return void
455 */
456void
457bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
458 void *dev, struct bfa_trc_mod_s *trcmod)
459{
460 WARN_ON(!port);
461
462 port->dev = dev;
463 port->ioc = ioc;
464 port->trcmod = trcmod;
465
466 port->stats_busy = BFA_FALSE;
467 port->endis_pending = BFA_FALSE;
468 port->stats_cbfn = NULL;
469 port->endis_cbfn = NULL;
470 port->pbc_disabled = BFA_FALSE;
471 port->dport_enabled = BFA_FALSE;
472
473 bfa_ioc_mbox_regisr(ioc: port->ioc, mc: BFI_MC_PORT, cbfn: bfa_port_isr, cbarg: port);
474 bfa_q_qe_init(&port->ioc_notify);
475 bfa_ioc_notify_init(&port->ioc_notify, bfa_port_notify, port);
476 list_add_tail(new: &port->ioc_notify.qe, head: &port->ioc->notify_q);
477
478 /*
479 * initialize time stamp for stats reset
480 */
481 port->stats_reset_time = ktime_get_seconds();
482
483 bfa_trc(port, 0);
484}
485
486/*
487 * bfa_port_set_dportenabled();
488 *
489 * Port module- set pbc disabled flag
490 *
491 * @param[in] port - Pointer to the Port module data structure
492 *
493 * @return void
494 */
495void
496bfa_port_set_dportenabled(struct bfa_port_s *port, bfa_boolean_t enabled)
497{
498 port->dport_enabled = enabled;
499}
500
501/*
502 * CEE module specific definitions
503 */
504
505/*
506 * bfa_cee_get_attr_isr()
507 *
508 * @brief CEE ISR for get-attributes responses from f/w
509 *
510 * @param[in] cee - Pointer to the CEE module
511 * status - Return status from the f/w
512 *
513 * @return void
514 */
515static void
516bfa_cee_get_attr_isr(struct bfa_cee_s *cee, bfa_status_t status)
517{
518 struct bfa_cee_lldp_cfg_s *lldp_cfg = &cee->attr->lldp_remote;
519
520 cee->get_attr_status = status;
521 bfa_trc(cee, 0);
522 if (status == BFA_STATUS_OK) {
523 bfa_trc(cee, 0);
524 memcpy(cee->attr, cee->attr_dma.kva,
525 sizeof(struct bfa_cee_attr_s));
526 lldp_cfg->time_to_live = be16_to_cpu(lldp_cfg->time_to_live);
527 lldp_cfg->enabled_system_cap =
528 be16_to_cpu(lldp_cfg->enabled_system_cap);
529 }
530 cee->get_attr_pending = BFA_FALSE;
531 if (cee->cbfn.get_attr_cbfn) {
532 bfa_trc(cee, 0);
533 cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status);
534 }
535}
536
537/*
538 * bfa_cee_get_stats_isr()
539 *
540 * @brief CEE ISR for get-stats responses from f/w
541 *
542 * @param[in] cee - Pointer to the CEE module
543 * status - Return status from the f/w
544 *
545 * @return void
546 */
547static void
548bfa_cee_get_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
549{
550 u32 *buffer;
551 int i;
552
553 cee->get_stats_status = status;
554 bfa_trc(cee, 0);
555 if (status == BFA_STATUS_OK) {
556 bfa_trc(cee, 0);
557 memcpy(cee->stats, cee->stats_dma.kva,
558 sizeof(struct bfa_cee_stats_s));
559 /* swap the cee stats */
560 buffer = (u32 *)cee->stats;
561 for (i = 0; i < (sizeof(struct bfa_cee_stats_s) /
562 sizeof(u32)); i++)
563 buffer[i] = cpu_to_be32(buffer[i]);
564 }
565 cee->get_stats_pending = BFA_FALSE;
566 bfa_trc(cee, 0);
567 if (cee->cbfn.get_stats_cbfn) {
568 bfa_trc(cee, 0);
569 cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status);
570 }
571}
572
573/*
574 * bfa_cee_reset_stats_isr()
575 *
576 * @brief CEE ISR for reset-stats responses from f/w
577 *
578 * @param[in] cee - Pointer to the CEE module
579 * status - Return status from the f/w
580 *
581 * @return void
582 */
583static void
584bfa_cee_reset_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
585{
586 cee->reset_stats_status = status;
587 cee->reset_stats_pending = BFA_FALSE;
588 if (cee->cbfn.reset_stats_cbfn)
589 cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status);
590}
591
592/*
593 * bfa_cee_meminfo()
594 *
595 * @brief Returns the size of the DMA memory needed by CEE module
596 *
597 * @param[in] void
598 *
599 * @return Size of DMA region
600 */
601u32
602bfa_cee_meminfo(void)
603{
604 return BFA_ROUNDUP(sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ) +
605 BFA_ROUNDUP(sizeof(struct bfa_cee_stats_s), BFA_DMA_ALIGN_SZ);
606}
607
608/*
609 * bfa_cee_mem_claim()
610 *
611 * @brief Initialized CEE DMA Memory
612 *
613 * @param[in] cee CEE module pointer
614 * dma_kva Kernel Virtual Address of CEE DMA Memory
615 * dma_pa Physical Address of CEE DMA Memory
616 *
617 * @return void
618 */
619void
620bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva, u64 dma_pa)
621{
622 cee->attr_dma.kva = dma_kva;
623 cee->attr_dma.pa = dma_pa;
624 cee->stats_dma.kva = dma_kva + BFA_ROUNDUP(
625 sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ);
626 cee->stats_dma.pa = dma_pa + BFA_ROUNDUP(
627 sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ);
628 cee->attr = (struct bfa_cee_attr_s *) dma_kva;
629 cee->stats = (struct bfa_cee_stats_s *) (dma_kva + BFA_ROUNDUP(
630 sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ));
631}
632
633/*
634 * bfa_cee_get_attr()
635 *
636 * @brief
637 * Send the request to the f/w to fetch CEE attributes.
638 *
639 * @param[in] Pointer to the CEE module data structure.
640 *
641 * @return Status
642 */
643
644bfa_status_t
645bfa_cee_get_attr(struct bfa_cee_s *cee, struct bfa_cee_attr_s *attr,
646 bfa_cee_get_attr_cbfn_t cbfn, void *cbarg)
647{
648 struct bfi_cee_get_req_s *cmd;
649
650 WARN_ON((cee == NULL) || (cee->ioc == NULL));
651 bfa_trc(cee, 0);
652 if (!bfa_ioc_is_operational(ioc: cee->ioc)) {
653 bfa_trc(cee, 0);
654 return BFA_STATUS_IOC_FAILURE;
655 }
656 if (cee->get_attr_pending == BFA_TRUE) {
657 bfa_trc(cee, 0);
658 return BFA_STATUS_DEVBUSY;
659 }
660 cee->get_attr_pending = BFA_TRUE;
661 cmd = (struct bfi_cee_get_req_s *) cee->get_cfg_mb.msg;
662 cee->attr = attr;
663 cee->cbfn.get_attr_cbfn = cbfn;
664 cee->cbfn.get_attr_cbarg = cbarg;
665 bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ,
666 bfa_ioc_portid(cee->ioc));
667 bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa);
668 bfa_ioc_mbox_queue(ioc: cee->ioc, cmd: &cee->get_cfg_mb);
669
670 return BFA_STATUS_OK;
671}
672
673/*
674 * bfa_cee_get_stats()
675 *
676 * @brief
677 * Send the request to the f/w to fetch CEE statistics.
678 *
679 * @param[in] Pointer to the CEE module data structure.
680 *
681 * @return Status
682 */
683
684bfa_status_t
685bfa_cee_get_stats(struct bfa_cee_s *cee, struct bfa_cee_stats_s *stats,
686 bfa_cee_get_stats_cbfn_t cbfn, void *cbarg)
687{
688 struct bfi_cee_get_req_s *cmd;
689
690 WARN_ON((cee == NULL) || (cee->ioc == NULL));
691
692 if (!bfa_ioc_is_operational(ioc: cee->ioc)) {
693 bfa_trc(cee, 0);
694 return BFA_STATUS_IOC_FAILURE;
695 }
696 if (cee->get_stats_pending == BFA_TRUE) {
697 bfa_trc(cee, 0);
698 return BFA_STATUS_DEVBUSY;
699 }
700 cee->get_stats_pending = BFA_TRUE;
701 cmd = (struct bfi_cee_get_req_s *) cee->get_stats_mb.msg;
702 cee->stats = stats;
703 cee->cbfn.get_stats_cbfn = cbfn;
704 cee->cbfn.get_stats_cbarg = cbarg;
705 bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_STATS_REQ,
706 bfa_ioc_portid(cee->ioc));
707 bfa_dma_be_addr_set(cmd->dma_addr, cee->stats_dma.pa);
708 bfa_ioc_mbox_queue(ioc: cee->ioc, cmd: &cee->get_stats_mb);
709
710 return BFA_STATUS_OK;
711}
712
713/*
714 * bfa_cee_reset_stats()
715 *
716 * @brief Clears CEE Stats in the f/w.
717 *
718 * @param[in] Pointer to the CEE module data structure.
719 *
720 * @return Status
721 */
722
723bfa_status_t
724bfa_cee_reset_stats(struct bfa_cee_s *cee,
725 bfa_cee_reset_stats_cbfn_t cbfn, void *cbarg)
726{
727 struct bfi_cee_reset_stats_s *cmd;
728
729 WARN_ON((cee == NULL) || (cee->ioc == NULL));
730 if (!bfa_ioc_is_operational(ioc: cee->ioc)) {
731 bfa_trc(cee, 0);
732 return BFA_STATUS_IOC_FAILURE;
733 }
734 if (cee->reset_stats_pending == BFA_TRUE) {
735 bfa_trc(cee, 0);
736 return BFA_STATUS_DEVBUSY;
737 }
738 cee->reset_stats_pending = BFA_TRUE;
739 cmd = (struct bfi_cee_reset_stats_s *) cee->reset_stats_mb.msg;
740 cee->cbfn.reset_stats_cbfn = cbfn;
741 cee->cbfn.reset_stats_cbarg = cbarg;
742 bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_RESET_STATS,
743 bfa_ioc_portid(cee->ioc));
744 bfa_ioc_mbox_queue(ioc: cee->ioc, cmd: &cee->reset_stats_mb);
745
746 return BFA_STATUS_OK;
747}
748
749/*
750 * bfa_cee_isrs()
751 *
752 * @brief Handles Mail-box interrupts for CEE module.
753 *
754 * @param[in] Pointer to the CEE module data structure.
755 *
756 * @return void
757 */
758
759static void
760bfa_cee_isr(void *cbarg, struct bfi_mbmsg_s *m)
761{
762 union bfi_cee_i2h_msg_u *msg;
763 struct bfi_cee_get_rsp_s *get_rsp;
764 struct bfa_cee_s *cee = (struct bfa_cee_s *) cbarg;
765 msg = (union bfi_cee_i2h_msg_u *) m;
766 get_rsp = (struct bfi_cee_get_rsp_s *) m;
767 bfa_trc(cee, msg->mh.msg_id);
768 switch (msg->mh.msg_id) {
769 case BFI_CEE_I2H_GET_CFG_RSP:
770 bfa_trc(cee, get_rsp->cmd_status);
771 bfa_cee_get_attr_isr(cee, status: get_rsp->cmd_status);
772 break;
773 case BFI_CEE_I2H_GET_STATS_RSP:
774 bfa_cee_get_stats_isr(cee, status: get_rsp->cmd_status);
775 break;
776 case BFI_CEE_I2H_RESET_STATS_RSP:
777 bfa_cee_reset_stats_isr(cee, status: get_rsp->cmd_status);
778 break;
779 default:
780 WARN_ON(1);
781 }
782}
783
784/*
785 * bfa_cee_notify()
786 *
787 * @brief CEE module IOC event handler.
788 *
789 * @param[in] Pointer to the CEE module data structure.
790 * @param[in] IOC event type
791 *
792 * @return void
793 */
794
795static void
796bfa_cee_notify(void *arg, enum bfa_ioc_event_e event)
797{
798 struct bfa_cee_s *cee = (struct bfa_cee_s *) arg;
799
800 bfa_trc(cee, event);
801
802 switch (event) {
803 case BFA_IOC_E_DISABLED:
804 case BFA_IOC_E_FAILED:
805 if (cee->get_attr_pending == BFA_TRUE) {
806 cee->get_attr_status = BFA_STATUS_FAILED;
807 cee->get_attr_pending = BFA_FALSE;
808 if (cee->cbfn.get_attr_cbfn) {
809 cee->cbfn.get_attr_cbfn(
810 cee->cbfn.get_attr_cbarg,
811 BFA_STATUS_FAILED);
812 }
813 }
814 if (cee->get_stats_pending == BFA_TRUE) {
815 cee->get_stats_status = BFA_STATUS_FAILED;
816 cee->get_stats_pending = BFA_FALSE;
817 if (cee->cbfn.get_stats_cbfn) {
818 cee->cbfn.get_stats_cbfn(
819 cee->cbfn.get_stats_cbarg,
820 BFA_STATUS_FAILED);
821 }
822 }
823 if (cee->reset_stats_pending == BFA_TRUE) {
824 cee->reset_stats_status = BFA_STATUS_FAILED;
825 cee->reset_stats_pending = BFA_FALSE;
826 if (cee->cbfn.reset_stats_cbfn) {
827 cee->cbfn.reset_stats_cbfn(
828 cee->cbfn.reset_stats_cbarg,
829 BFA_STATUS_FAILED);
830 }
831 }
832 break;
833
834 default:
835 break;
836 }
837}
838
839/*
840 * bfa_cee_attach()
841 *
842 * @brief CEE module-attach API
843 *
844 * @param[in] cee - Pointer to the CEE module data structure
845 * ioc - Pointer to the ioc module data structure
846 * dev - Pointer to the device driver module data structure
847 * The device driver specific mbox ISR functions have
848 * this pointer as one of the parameters.
849 *
850 * @return void
851 */
852void
853bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc,
854 void *dev)
855{
856 WARN_ON(cee == NULL);
857 cee->dev = dev;
858 cee->ioc = ioc;
859
860 bfa_ioc_mbox_regisr(ioc: cee->ioc, mc: BFI_MC_CEE, cbfn: bfa_cee_isr, cbarg: cee);
861 bfa_q_qe_init(&cee->ioc_notify);
862 bfa_ioc_notify_init(&cee->ioc_notify, bfa_cee_notify, cee);
863 list_add_tail(new: &cee->ioc_notify.qe, head: &cee->ioc->notify_q);
864}
865

source code of linux/drivers/scsi/bfa/bfa_port.c