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
bfa_port_stats_swap(struct bfa_port_s * port,union bfa_port_stats_u * stats)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
bfa_port_enable_isr(struct bfa_port_s * port,bfa_status_t status)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
bfa_port_disable_isr(struct bfa_port_s * port,bfa_status_t status)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
bfa_port_get_stats_isr(struct bfa_port_s * port,bfa_status_t status)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
bfa_port_clear_stats_isr(struct bfa_port_s * port,bfa_status_t status)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
bfa_port_isr(void * cbarg,struct bfi_mbmsg_s * m)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
bfa_port_meminfo(void)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
bfa_port_mem_claim(struct bfa_port_s * port,u8 * dma_kva,u64 dma_pa)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
bfa_port_enable(struct bfa_port_s * port,bfa_port_endis_cbfn_t cbfn,void * cbarg)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
bfa_port_disable(struct bfa_port_s * port,bfa_port_endis_cbfn_t cbfn,void * cbarg)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
bfa_port_get_stats(struct bfa_port_s * port,union bfa_port_stats_u * stats,bfa_port_stats_cbfn_t cbfn,void * cbarg)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
bfa_port_clear_stats(struct bfa_port_s * port,bfa_port_stats_cbfn_t cbfn,void * cbarg)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
bfa_port_notify(void * arg,enum bfa_ioc_event_e event)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
bfa_port_attach(struct bfa_port_s * port,struct bfa_ioc_s * ioc,void * dev,struct bfa_trc_mod_s * trcmod)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
bfa_port_set_dportenabled(struct bfa_port_s * port,bfa_boolean_t enabled)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
bfa_cee_get_attr_isr(struct bfa_cee_s * cee,bfa_status_t status)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
bfa_cee_get_stats_isr(struct bfa_cee_s * cee,bfa_status_t status)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
bfa_cee_reset_stats_isr(struct bfa_cee_s * cee,bfa_status_t status)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
bfa_cee_meminfo(void)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
bfa_cee_mem_claim(struct bfa_cee_s * cee,u8 * dma_kva,u64 dma_pa)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
bfa_cee_get_attr(struct bfa_cee_s * cee,struct bfa_cee_attr_s * attr,bfa_cee_get_attr_cbfn_t cbfn,void * cbarg)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
bfa_cee_get_stats(struct bfa_cee_s * cee,struct bfa_cee_stats_s * stats,bfa_cee_get_stats_cbfn_t cbfn,void * cbarg)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
bfa_cee_reset_stats(struct bfa_cee_s * cee,bfa_cee_reset_stats_cbfn_t cbfn,void * cbarg)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
bfa_cee_isr(void * cbarg,struct bfi_mbmsg_s * m)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
bfa_cee_notify(void * arg,enum bfa_ioc_event_e event)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
bfa_cee_attach(struct bfa_cee_s * cee,struct bfa_ioc_s * ioc,void * dev)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