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