1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Linux network driver for QLogic BR-series Converged Network Adapter.
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun /*
6*4882a593Smuzhiyun * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
7*4882a593Smuzhiyun * Copyright (c) 2014-2015 QLogic Corporation
8*4882a593Smuzhiyun * All rights reserved
9*4882a593Smuzhiyun * www.qlogic.com
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include "bfa_cee.h"
13*4882a593Smuzhiyun #include "bfi_cna.h"
14*4882a593Smuzhiyun #include "bfa_ioc.h"
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun static void bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg *lldp_cfg);
17*4882a593Smuzhiyun static void bfa_cee_format_cee_cfg(void *buffer);
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun static void
bfa_cee_format_cee_cfg(void * buffer)20*4882a593Smuzhiyun bfa_cee_format_cee_cfg(void *buffer)
21*4882a593Smuzhiyun {
22*4882a593Smuzhiyun struct bfa_cee_attr *cee_cfg = buffer;
23*4882a593Smuzhiyun bfa_cee_format_lldp_cfg(&cee_cfg->lldp_remote);
24*4882a593Smuzhiyun }
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun static void
bfa_cee_stats_swap(struct bfa_cee_stats * stats)27*4882a593Smuzhiyun bfa_cee_stats_swap(struct bfa_cee_stats *stats)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun u32 *buffer = (u32 *)stats;
30*4882a593Smuzhiyun int i;
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun for (i = 0; i < (sizeof(struct bfa_cee_stats) / sizeof(u32));
33*4882a593Smuzhiyun i++) {
34*4882a593Smuzhiyun buffer[i] = ntohl(buffer[i]);
35*4882a593Smuzhiyun }
36*4882a593Smuzhiyun }
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun static void
bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg * lldp_cfg)39*4882a593Smuzhiyun bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg *lldp_cfg)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun lldp_cfg->time_to_live =
42*4882a593Smuzhiyun ntohs(lldp_cfg->time_to_live);
43*4882a593Smuzhiyun lldp_cfg->enabled_system_cap =
44*4882a593Smuzhiyun ntohs(lldp_cfg->enabled_system_cap);
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun /**
48*4882a593Smuzhiyun * bfa_cee_attr_meminfo - Returns the size of the DMA memory needed by CEE attributes
49*4882a593Smuzhiyun */
50*4882a593Smuzhiyun static u32
bfa_cee_attr_meminfo(void)51*4882a593Smuzhiyun bfa_cee_attr_meminfo(void)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun return roundup(sizeof(struct bfa_cee_attr), BFA_DMA_ALIGN_SZ);
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun /**
56*4882a593Smuzhiyun * bfa_cee_stats_meminfo - Returns the size of the DMA memory needed by CEE stats
57*4882a593Smuzhiyun */
58*4882a593Smuzhiyun static u32
bfa_cee_stats_meminfo(void)59*4882a593Smuzhiyun bfa_cee_stats_meminfo(void)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun return roundup(sizeof(struct bfa_cee_stats), BFA_DMA_ALIGN_SZ);
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun /**
65*4882a593Smuzhiyun * bfa_cee_get_attr_isr - CEE ISR for get-attributes responses from f/w
66*4882a593Smuzhiyun *
67*4882a593Smuzhiyun * @cee: Pointer to the CEE module
68*4882a593Smuzhiyun * @status: Return status from the f/w
69*4882a593Smuzhiyun */
70*4882a593Smuzhiyun static void
bfa_cee_get_attr_isr(struct bfa_cee * cee,enum bfa_status status)71*4882a593Smuzhiyun bfa_cee_get_attr_isr(struct bfa_cee *cee, enum bfa_status status)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun cee->get_attr_status = status;
74*4882a593Smuzhiyun if (status == BFA_STATUS_OK) {
75*4882a593Smuzhiyun memcpy(cee->attr, cee->attr_dma.kva,
76*4882a593Smuzhiyun sizeof(struct bfa_cee_attr));
77*4882a593Smuzhiyun bfa_cee_format_cee_cfg(cee->attr);
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun cee->get_attr_pending = false;
80*4882a593Smuzhiyun if (cee->cbfn.get_attr_cbfn)
81*4882a593Smuzhiyun cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status);
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun /**
85*4882a593Smuzhiyun * bfa_cee_get_attr_isr - CEE ISR for get-stats responses from f/w
86*4882a593Smuzhiyun *
87*4882a593Smuzhiyun * @cee: Pointer to the CEE module
88*4882a593Smuzhiyun * @status: Return status from the f/w
89*4882a593Smuzhiyun */
90*4882a593Smuzhiyun static void
bfa_cee_get_stats_isr(struct bfa_cee * cee,enum bfa_status status)91*4882a593Smuzhiyun bfa_cee_get_stats_isr(struct bfa_cee *cee, enum bfa_status status)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun cee->get_stats_status = status;
94*4882a593Smuzhiyun if (status == BFA_STATUS_OK) {
95*4882a593Smuzhiyun memcpy(cee->stats, cee->stats_dma.kva,
96*4882a593Smuzhiyun sizeof(struct bfa_cee_stats));
97*4882a593Smuzhiyun bfa_cee_stats_swap(cee->stats);
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun cee->get_stats_pending = false;
100*4882a593Smuzhiyun if (cee->cbfn.get_stats_cbfn)
101*4882a593Smuzhiyun cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun /**
105*4882a593Smuzhiyun * bfa_cee_reset_stats_isr - CEE ISR for reset-stats responses from f/w
106*4882a593Smuzhiyun *
107*4882a593Smuzhiyun * @cee: Input Pointer to the CEE module
108*4882a593Smuzhiyun * @status: Return status from the f/w
109*4882a593Smuzhiyun */
110*4882a593Smuzhiyun static void
bfa_cee_reset_stats_isr(struct bfa_cee * cee,enum bfa_status status)111*4882a593Smuzhiyun bfa_cee_reset_stats_isr(struct bfa_cee *cee, enum bfa_status status)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun cee->reset_stats_status = status;
114*4882a593Smuzhiyun cee->reset_stats_pending = false;
115*4882a593Smuzhiyun if (cee->cbfn.reset_stats_cbfn)
116*4882a593Smuzhiyun cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status);
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun /**
119*4882a593Smuzhiyun * bfa_nw_cee_meminfo - Returns the size of the DMA memory needed by CEE module
120*4882a593Smuzhiyun */
121*4882a593Smuzhiyun u32
bfa_nw_cee_meminfo(void)122*4882a593Smuzhiyun bfa_nw_cee_meminfo(void)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun return bfa_cee_attr_meminfo() + bfa_cee_stats_meminfo();
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun /**
128*4882a593Smuzhiyun * bfa_nw_cee_mem_claim - Initialized CEE DMA Memory
129*4882a593Smuzhiyun *
130*4882a593Smuzhiyun * @cee: CEE module pointer
131*4882a593Smuzhiyun * @dma_kva: Kernel Virtual Address of CEE DMA Memory
132*4882a593Smuzhiyun * @dma_pa: Physical Address of CEE DMA Memory
133*4882a593Smuzhiyun */
134*4882a593Smuzhiyun void
bfa_nw_cee_mem_claim(struct bfa_cee * cee,u8 * dma_kva,u64 dma_pa)135*4882a593Smuzhiyun bfa_nw_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva, u64 dma_pa)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun cee->attr_dma.kva = dma_kva;
138*4882a593Smuzhiyun cee->attr_dma.pa = dma_pa;
139*4882a593Smuzhiyun cee->stats_dma.kva = dma_kva + bfa_cee_attr_meminfo();
140*4882a593Smuzhiyun cee->stats_dma.pa = dma_pa + bfa_cee_attr_meminfo();
141*4882a593Smuzhiyun cee->attr = (struct bfa_cee_attr *) dma_kva;
142*4882a593Smuzhiyun cee->stats = (struct bfa_cee_stats *)
143*4882a593Smuzhiyun (dma_kva + bfa_cee_attr_meminfo());
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun /**
147*4882a593Smuzhiyun * bfa_nw_cee_get_attr - Send the request to the f/w to fetch CEE attributes.
148*4882a593Smuzhiyun *
149*4882a593Smuzhiyun * @cee: Pointer to the CEE module data structure.
150*4882a593Smuzhiyun * @attr: attribute requested
151*4882a593Smuzhiyun * @cbfn: function pointer
152*4882a593Smuzhiyun * @cbarg: function pointer arguments
153*4882a593Smuzhiyun *
154*4882a593Smuzhiyun * Return: status
155*4882a593Smuzhiyun */
156*4882a593Smuzhiyun enum bfa_status
bfa_nw_cee_get_attr(struct bfa_cee * cee,struct bfa_cee_attr * attr,bfa_cee_get_attr_cbfn_t cbfn,void * cbarg)157*4882a593Smuzhiyun bfa_nw_cee_get_attr(struct bfa_cee *cee, struct bfa_cee_attr *attr,
158*4882a593Smuzhiyun bfa_cee_get_attr_cbfn_t cbfn, void *cbarg)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun struct bfi_cee_get_req *cmd;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun BUG_ON(!((cee != NULL) && (cee->ioc != NULL)));
163*4882a593Smuzhiyun if (!bfa_nw_ioc_is_operational(cee->ioc))
164*4882a593Smuzhiyun return BFA_STATUS_IOC_FAILURE;
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun if (cee->get_attr_pending)
167*4882a593Smuzhiyun return BFA_STATUS_DEVBUSY;
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun cee->get_attr_pending = true;
170*4882a593Smuzhiyun cmd = (struct bfi_cee_get_req *) cee->get_cfg_mb.msg;
171*4882a593Smuzhiyun cee->attr = attr;
172*4882a593Smuzhiyun cee->cbfn.get_attr_cbfn = cbfn;
173*4882a593Smuzhiyun cee->cbfn.get_attr_cbarg = cbarg;
174*4882a593Smuzhiyun bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ,
175*4882a593Smuzhiyun bfa_ioc_portid(cee->ioc));
176*4882a593Smuzhiyun bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa);
177*4882a593Smuzhiyun bfa_nw_ioc_mbox_queue(cee->ioc, &cee->get_cfg_mb, NULL, NULL);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun return BFA_STATUS_OK;
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun /**
183*4882a593Smuzhiyun * bfa_cee_isr - Handles Mail-box interrupts for CEE module.
184*4882a593Smuzhiyun * @cbarg: argument passed containing pointer to the CEE module data structure.
185*4882a593Smuzhiyun * @m: message pointer
186*4882a593Smuzhiyun */
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun static void
bfa_cee_isr(void * cbarg,struct bfi_mbmsg * m)189*4882a593Smuzhiyun bfa_cee_isr(void *cbarg, struct bfi_mbmsg *m)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun union bfi_cee_i2h_msg_u *msg;
192*4882a593Smuzhiyun struct bfi_cee_get_rsp *get_rsp;
193*4882a593Smuzhiyun struct bfa_cee *cee = (struct bfa_cee *) cbarg;
194*4882a593Smuzhiyun msg = (union bfi_cee_i2h_msg_u *) m;
195*4882a593Smuzhiyun get_rsp = (struct bfi_cee_get_rsp *) m;
196*4882a593Smuzhiyun switch (msg->mh.msg_id) {
197*4882a593Smuzhiyun case BFI_CEE_I2H_GET_CFG_RSP:
198*4882a593Smuzhiyun bfa_cee_get_attr_isr(cee, get_rsp->cmd_status);
199*4882a593Smuzhiyun break;
200*4882a593Smuzhiyun case BFI_CEE_I2H_GET_STATS_RSP:
201*4882a593Smuzhiyun bfa_cee_get_stats_isr(cee, get_rsp->cmd_status);
202*4882a593Smuzhiyun break;
203*4882a593Smuzhiyun case BFI_CEE_I2H_RESET_STATS_RSP:
204*4882a593Smuzhiyun bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status);
205*4882a593Smuzhiyun break;
206*4882a593Smuzhiyun default:
207*4882a593Smuzhiyun BUG_ON(1);
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun /**
212*4882a593Smuzhiyun * bfa_cee_notify - CEE module heart-beat failure handler.
213*4882a593Smuzhiyun *
214*4882a593Smuzhiyun * @arg: argument passed containing pointer to the CEE module data structure.
215*4882a593Smuzhiyun * @event: IOC event type
216*4882a593Smuzhiyun */
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun static void
bfa_cee_notify(void * arg,enum bfa_ioc_event event)219*4882a593Smuzhiyun bfa_cee_notify(void *arg, enum bfa_ioc_event event)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun struct bfa_cee *cee;
222*4882a593Smuzhiyun cee = (struct bfa_cee *) arg;
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun switch (event) {
225*4882a593Smuzhiyun case BFA_IOC_E_DISABLED:
226*4882a593Smuzhiyun case BFA_IOC_E_FAILED:
227*4882a593Smuzhiyun if (cee->get_attr_pending) {
228*4882a593Smuzhiyun cee->get_attr_status = BFA_STATUS_FAILED;
229*4882a593Smuzhiyun cee->get_attr_pending = false;
230*4882a593Smuzhiyun if (cee->cbfn.get_attr_cbfn) {
231*4882a593Smuzhiyun cee->cbfn.get_attr_cbfn(
232*4882a593Smuzhiyun cee->cbfn.get_attr_cbarg,
233*4882a593Smuzhiyun BFA_STATUS_FAILED);
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun if (cee->get_stats_pending) {
237*4882a593Smuzhiyun cee->get_stats_status = BFA_STATUS_FAILED;
238*4882a593Smuzhiyun cee->get_stats_pending = false;
239*4882a593Smuzhiyun if (cee->cbfn.get_stats_cbfn) {
240*4882a593Smuzhiyun cee->cbfn.get_stats_cbfn(
241*4882a593Smuzhiyun cee->cbfn.get_stats_cbarg,
242*4882a593Smuzhiyun BFA_STATUS_FAILED);
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun if (cee->reset_stats_pending) {
246*4882a593Smuzhiyun cee->reset_stats_status = BFA_STATUS_FAILED;
247*4882a593Smuzhiyun cee->reset_stats_pending = false;
248*4882a593Smuzhiyun if (cee->cbfn.reset_stats_cbfn) {
249*4882a593Smuzhiyun cee->cbfn.reset_stats_cbfn(
250*4882a593Smuzhiyun cee->cbfn.reset_stats_cbarg,
251*4882a593Smuzhiyun BFA_STATUS_FAILED);
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun break;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun default:
257*4882a593Smuzhiyun break;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun /**
262*4882a593Smuzhiyun * bfa_nw_cee_attach - CEE module-attach API
263*4882a593Smuzhiyun *
264*4882a593Smuzhiyun * @cee: Pointer to the CEE module data structure
265*4882a593Smuzhiyun * @ioc: Pointer to the ioc module data structure
266*4882a593Smuzhiyun * @dev: Pointer to the device driver module data structure.
267*4882a593Smuzhiyun * The device driver specific mbox ISR functions have
268*4882a593Smuzhiyun * this pointer as one of the parameters.
269*4882a593Smuzhiyun */
270*4882a593Smuzhiyun void
bfa_nw_cee_attach(struct bfa_cee * cee,struct bfa_ioc * ioc,void * dev)271*4882a593Smuzhiyun bfa_nw_cee_attach(struct bfa_cee *cee, struct bfa_ioc *ioc,
272*4882a593Smuzhiyun void *dev)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun BUG_ON(!(cee != NULL));
275*4882a593Smuzhiyun cee->dev = dev;
276*4882a593Smuzhiyun cee->ioc = ioc;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun bfa_nw_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee);
279*4882a593Smuzhiyun bfa_ioc_notify_init(&cee->ioc_notify, bfa_cee_notify, cee);
280*4882a593Smuzhiyun bfa_nw_ioc_notify_register(cee->ioc, &cee->ioc_notify);
281*4882a593Smuzhiyun }
282