xref: /openbmc/linux/drivers/scsi/bfa/bfa_port.c (revision 9dbbc3b9)
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 }
865