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