GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / scsi / bfa / bfa_port.c
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
18 BFA_TRC_FILE(CNA, PORT);
19
20 static void
21 bfa_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  */
50 static void
51 bfa_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  */
67 static void
68 bfa_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  */
84 static void
85 bfa_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, 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  */
113 static void
114 bfa_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  */
138 static void
139 bfa_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, 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, 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, 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, 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  */
186 u32
187 bfa_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  */
202 void
203 bfa_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  */
218 bfa_status_t
219 bfa_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(port->ioc)) {
231                 bfa_trc(port, BFA_STATUS_IOC_DISABLED);
232                 return BFA_STATUS_IOC_DISABLED;
233         }
234
235         if (!bfa_ioc_is_operational(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(port->ioc, &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  */
274 bfa_status_t
275 bfa_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(port->ioc)) {
287                 bfa_trc(port, BFA_STATUS_IOC_DISABLED);
288                 return BFA_STATUS_IOC_DISABLED;
289         }
290
291         if (!bfa_ioc_is_operational(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(port->ioc, &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  */
330 bfa_status_t
331 bfa_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(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(port->ioc, &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  */
369 bfa_status_t
370 bfa_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(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(port->ioc, &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  */
408 void
409 bfa_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, 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  */
456 void
457 bfa_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(port->ioc, BFI_MC_PORT, bfa_port_isr, 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(&port->ioc_notify.qe, &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  */
495 void
496 bfa_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  */
515 static void
516 bfa_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  */
547 static void
548 bfa_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  */
583 static void
584 bfa_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  */
601 u32
602 bfa_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  */
619 void
620 bfa_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
644 bfa_status_t
645 bfa_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(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(cee->ioc, &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
684 bfa_status_t
685 bfa_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(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(cee->ioc, &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
723 bfa_status_t
724 bfa_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(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(cee->ioc, &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
759 static void
760 bfa_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, get_rsp->cmd_status);
772                 break;
773         case BFI_CEE_I2H_GET_STATS_RSP:
774                 bfa_cee_get_stats_isr(cee, get_rsp->cmd_status);
775                 break;
776         case BFI_CEE_I2H_RESET_STATS_RSP:
777                 bfa_cee_reset_stats_isr(cee, 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
795 static void
796 bfa_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  */
852 void
853 bfa_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(cee->ioc, BFI_MC_CEE, bfa_cee_isr, 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(&cee->ioc_notify.qe, &cee->ioc->notify_q);
864 }