1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* Huawei HiNIC PCI Express Linux driver |
3 | * Copyright(c) 2017 Huawei Technologies Co., Ltd |
4 | */ |
5 | #include <linux/pci.h> |
6 | #include <linux/delay.h> |
7 | #include <linux/types.h> |
8 | #include <linux/completion.h> |
9 | #include <linux/semaphore.h> |
10 | #include <linux/spinlock.h> |
11 | #include <linux/workqueue.h> |
12 | |
13 | #include "hinic_hw_if.h" |
14 | #include "hinic_hw_mgmt.h" |
15 | #include "hinic_hw_csr.h" |
16 | #include "hinic_hw_dev.h" |
17 | #include "hinic_hw_mbox.h" |
18 | |
19 | #define HINIC_MBOX_INT_DST_FUNC_SHIFT 0 |
20 | #define HINIC_MBOX_INT_DST_AEQN_SHIFT 10 |
21 | #define HINIC_MBOX_INT_SRC_RESP_AEQN_SHIFT 12 |
22 | #define HINIC_MBOX_INT_STAT_DMA_SHIFT 14 |
23 | /* The size of data to be sended (unit of 4 bytes) */ |
24 | #define HINIC_MBOX_INT_TX_SIZE_SHIFT 20 |
25 | /* SO_RO(strong order, relax order) */ |
26 | #define HINIC_MBOX_INT_STAT_DMA_SO_RO_SHIFT 25 |
27 | #define HINIC_MBOX_INT_WB_EN_SHIFT 28 |
28 | |
29 | #define HINIC_MBOX_INT_DST_FUNC_MASK 0x3FF |
30 | #define HINIC_MBOX_INT_DST_AEQN_MASK 0x3 |
31 | #define HINIC_MBOX_INT_SRC_RESP_AEQN_MASK 0x3 |
32 | #define HINIC_MBOX_INT_STAT_DMA_MASK 0x3F |
33 | #define HINIC_MBOX_INT_TX_SIZE_MASK 0x1F |
34 | #define HINIC_MBOX_INT_STAT_DMA_SO_RO_MASK 0x3 |
35 | #define HINIC_MBOX_INT_WB_EN_MASK 0x1 |
36 | |
37 | #define HINIC_MBOX_INT_SET(val, field) \ |
38 | (((val) & HINIC_MBOX_INT_##field##_MASK) << \ |
39 | HINIC_MBOX_INT_##field##_SHIFT) |
40 | |
41 | enum hinic_mbox_tx_status { |
42 | TX_NOT_DONE = 1, |
43 | }; |
44 | |
45 | #define HINIC_MBOX_CTRL_TRIGGER_AEQE_SHIFT 0 |
46 | |
47 | /* specifies the issue request for the message data. |
48 | * 0 - Tx request is done; |
49 | * 1 - Tx request is in process. |
50 | */ |
51 | #define HINIC_MBOX_CTRL_TX_STATUS_SHIFT 1 |
52 | |
53 | #define HINIC_MBOX_CTRL_TRIGGER_AEQE_MASK 0x1 |
54 | #define HINIC_MBOX_CTRL_TX_STATUS_MASK 0x1 |
55 | |
56 | #define HINIC_MBOX_CTRL_SET(val, field) \ |
57 | (((val) & HINIC_MBOX_CTRL_##field##_MASK) << \ |
58 | HINIC_MBOX_CTRL_##field##_SHIFT) |
59 | |
60 | #define 0 |
61 | #define 11 |
62 | #define 16 |
63 | #define 22 |
64 | #define 24 |
65 | #define 30 |
66 | |
67 | /* specifies the mailbox message direction |
68 | * 0 - send |
69 | * 1 - receive |
70 | */ |
71 | #define 31 |
72 | #define 32 |
73 | #define 40 |
74 | #define 48 |
75 | #define 54 |
76 | |
77 | #define 0x7FF |
78 | #define 0x1F |
79 | #define 0x3F |
80 | #define 0x1 |
81 | #define 0x3F |
82 | #define 0x1 |
83 | #define 0x1 |
84 | #define 0xFF |
85 | #define 0xFF |
86 | #define 0x3F |
87 | #define 0x3FF |
88 | |
89 | #define (val, field) \ |
90 | (((val) >> HINIC_MBOX_HEADER_##field##_SHIFT) & \ |
91 | HINIC_MBOX_HEADER_##field##_MASK) |
92 | #define (val, field) \ |
93 | ((u64)((val) & HINIC_MBOX_HEADER_##field##_MASK) << \ |
94 | HINIC_MBOX_HEADER_##field##_SHIFT) |
95 | |
96 | #define MBOX_SEGLEN_MASK \ |
97 | HINIC_MBOX_HEADER_SET(HINIC_MBOX_HEADER_SEG_LEN_MASK, SEG_LEN) |
98 | |
99 | #define HINIC_MBOX_SEG_LEN 48 |
100 | #define HINIC_MBOX_COMP_TIME 8000U |
101 | #define MBOX_MSG_POLLING_TIMEOUT 8000 |
102 | |
103 | #define HINIC_MBOX_DATA_SIZE 2040 |
104 | |
105 | #define MBOX_MAX_BUF_SZ 2048UL |
106 | #define 8 |
107 | |
108 | #define MBOX_INFO_SZ 4 |
109 | |
110 | /* MBOX size is 64B, 8B for mbox_header, 4B reserved */ |
111 | #define MBOX_SEG_LEN 48 |
112 | #define MBOX_SEG_LEN_ALIGN 4 |
113 | #define MBOX_WB_STATUS_LEN 16UL |
114 | |
115 | /* mbox write back status is 16B, only first 4B is used */ |
116 | #define MBOX_WB_STATUS_ERRCODE_MASK 0xFFFF |
117 | #define MBOX_WB_STATUS_MASK 0xFF |
118 | #define MBOX_WB_ERROR_CODE_MASK 0xFF00 |
119 | #define MBOX_WB_STATUS_FINISHED_SUCCESS 0xFF |
120 | #define MBOX_WB_STATUS_NOT_FINISHED 0x00 |
121 | |
122 | #define MBOX_STATUS_FINISHED(wb) \ |
123 | (((wb) & MBOX_WB_STATUS_MASK) != MBOX_WB_STATUS_NOT_FINISHED) |
124 | #define MBOX_STATUS_SUCCESS(wb) \ |
125 | (((wb) & MBOX_WB_STATUS_MASK) == MBOX_WB_STATUS_FINISHED_SUCCESS) |
126 | #define MBOX_STATUS_ERRCODE(wb) \ |
127 | ((wb) & MBOX_WB_ERROR_CODE_MASK) |
128 | |
129 | #define SEQ_ID_START_VAL 0 |
130 | #define SEQ_ID_MAX_VAL 42 |
131 | |
132 | #define NO_DMA_ATTRIBUTE_VAL 0 |
133 | |
134 | #define HINIC_MBOX_RSP_AEQN 2 |
135 | #define HINIC_MBOX_RECV_AEQN 0 |
136 | |
137 | #define MBOX_MSG_NO_DATA_LEN 1 |
138 | |
139 | #define MBOX_BODY_FROM_HDR(header) ((u8 *)(header) + MBOX_HEADER_SZ) |
140 | #define MBOX_AREA(hwif) \ |
141 | ((hwif)->cfg_regs_bar + HINIC_FUNC_CSR_MAILBOX_DATA_OFF) |
142 | |
143 | #define IS_PF_OR_PPF_SRC(src_func_idx) ((src_func_idx) < HINIC_MAX_PF_FUNCS) |
144 | |
145 | #define MBOX_MSG_ID_MASK 0xFF |
146 | #define MBOX_MSG_ID(func_to_func) ((func_to_func)->send_msg_id) |
147 | #define MBOX_MSG_ID_INC(func_to_func_mbox) (MBOX_MSG_ID(func_to_func_mbox) = \ |
148 | (MBOX_MSG_ID(func_to_func_mbox) + 1) & MBOX_MSG_ID_MASK) |
149 | |
150 | #define FUNC_ID_OFF_SET_8B 8 |
151 | |
152 | /* max message counter wait to process for one function */ |
153 | #define HINIC_MAX_MSG_CNT_TO_PROCESS 10 |
154 | |
155 | #define HINIC_QUEUE_MIN_DEPTH 6 |
156 | #define HINIC_QUEUE_MAX_DEPTH 12 |
157 | #define HINIC_MAX_RX_BUFFER_SIZE 15 |
158 | |
159 | enum hinic_hwif_direction_type { |
160 | HINIC_HWIF_DIRECT_SEND = 0, |
161 | HINIC_HWIF_RESPONSE = 1, |
162 | }; |
163 | |
164 | enum mbox_send_mod { |
165 | MBOX_SEND_MSG_INT, |
166 | }; |
167 | |
168 | enum mbox_seg_type { |
169 | NOT_LAST_SEG, |
170 | LAST_SEG, |
171 | }; |
172 | |
173 | enum mbox_ordering_type { |
174 | STRONG_ORDER, |
175 | }; |
176 | |
177 | enum mbox_write_back_type { |
178 | WRITE_BACK = 1, |
179 | }; |
180 | |
181 | enum mbox_aeq_trig_type { |
182 | NOT_TRIGGER, |
183 | TRIGGER, |
184 | }; |
185 | |
186 | static bool check_func_id(struct hinic_hwdev *hwdev, u16 src_func_idx, |
187 | const void *buf_in, u16 in_size, u16 offset) |
188 | { |
189 | u16 func_idx; |
190 | |
191 | if (in_size < offset + sizeof(func_idx)) { |
192 | dev_warn(&hwdev->hwif->pdev->dev, |
193 | "Receive mailbox msg len: %d less than %d Bytes is invalid\n" , |
194 | in_size, offset); |
195 | return false; |
196 | } |
197 | |
198 | func_idx = *((u16 *)((u8 *)buf_in + offset)); |
199 | |
200 | if (src_func_idx != func_idx) { |
201 | dev_warn(&hwdev->hwif->pdev->dev, |
202 | "Receive mailbox function id: 0x%x not equal to msg function id: 0x%x\n" , |
203 | src_func_idx, func_idx); |
204 | return false; |
205 | } |
206 | |
207 | return true; |
208 | } |
209 | |
210 | bool hinic_mbox_check_func_id_8B(struct hinic_hwdev *hwdev, u16 func_idx, |
211 | void *buf_in, u16 in_size) |
212 | { |
213 | return check_func_id(hwdev, src_func_idx: func_idx, buf_in, in_size, |
214 | FUNC_ID_OFF_SET_8B); |
215 | } |
216 | |
217 | /** |
218 | * hinic_register_pf_mbox_cb - register mbox callback for pf |
219 | * @hwdev: the pointer to hw device |
220 | * @mod: specific mod that the callback will handle |
221 | * @callback: callback function |
222 | * Return: 0 - success, negative - failure |
223 | */ |
224 | int hinic_register_pf_mbox_cb(struct hinic_hwdev *hwdev, |
225 | enum hinic_mod_type mod, |
226 | hinic_pf_mbox_cb callback) |
227 | { |
228 | struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func; |
229 | |
230 | if (mod >= HINIC_MOD_MAX) |
231 | return -EFAULT; |
232 | |
233 | func_to_func->pf_mbox_cb[mod] = callback; |
234 | |
235 | set_bit(nr: HINIC_PF_MBOX_CB_REG, addr: &func_to_func->pf_mbox_cb_state[mod]); |
236 | |
237 | return 0; |
238 | } |
239 | |
240 | /** |
241 | * hinic_register_vf_mbox_cb - register mbox callback for vf |
242 | * @hwdev: the pointer to hw device |
243 | * @mod: specific mod that the callback will handle |
244 | * @callback: callback function |
245 | * Return: 0 - success, negative - failure |
246 | */ |
247 | int hinic_register_vf_mbox_cb(struct hinic_hwdev *hwdev, |
248 | enum hinic_mod_type mod, |
249 | hinic_vf_mbox_cb callback) |
250 | { |
251 | struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func; |
252 | |
253 | if (mod >= HINIC_MOD_MAX) |
254 | return -EFAULT; |
255 | |
256 | func_to_func->vf_mbox_cb[mod] = callback; |
257 | |
258 | set_bit(nr: HINIC_VF_MBOX_CB_REG, addr: &func_to_func->vf_mbox_cb_state[mod]); |
259 | |
260 | return 0; |
261 | } |
262 | |
263 | /** |
264 | * hinic_unregister_pf_mbox_cb - unregister the mbox callback for pf |
265 | * @hwdev: the pointer to hw device |
266 | * @mod: specific mod that the callback will handle |
267 | */ |
268 | void hinic_unregister_pf_mbox_cb(struct hinic_hwdev *hwdev, |
269 | enum hinic_mod_type mod) |
270 | { |
271 | struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func; |
272 | |
273 | clear_bit(nr: HINIC_PF_MBOX_CB_REG, addr: &func_to_func->pf_mbox_cb_state[mod]); |
274 | |
275 | while (test_bit(HINIC_PF_MBOX_CB_RUNNING, |
276 | &func_to_func->pf_mbox_cb_state[mod])) |
277 | usleep_range(min: 900, max: 1000); |
278 | |
279 | func_to_func->pf_mbox_cb[mod] = NULL; |
280 | } |
281 | |
282 | /** |
283 | * hinic_unregister_vf_mbox_cb - unregister the mbox callback for vf |
284 | * @hwdev: the pointer to hw device |
285 | * @mod: specific mod that the callback will handle |
286 | */ |
287 | void hinic_unregister_vf_mbox_cb(struct hinic_hwdev *hwdev, |
288 | enum hinic_mod_type mod) |
289 | { |
290 | struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func; |
291 | |
292 | clear_bit(nr: HINIC_VF_MBOX_CB_REG, addr: &func_to_func->vf_mbox_cb_state[mod]); |
293 | |
294 | while (test_bit(HINIC_VF_MBOX_CB_RUNNING, |
295 | &func_to_func->vf_mbox_cb_state[mod])) |
296 | usleep_range(min: 900, max: 1000); |
297 | |
298 | func_to_func->vf_mbox_cb[mod] = NULL; |
299 | } |
300 | |
301 | static int recv_vf_mbox_handler(struct hinic_mbox_func_to_func *func_to_func, |
302 | struct hinic_recv_mbox *recv_mbox, |
303 | void *buf_out, u16 *out_size) |
304 | { |
305 | hinic_vf_mbox_cb cb; |
306 | int ret = 0; |
307 | |
308 | if (recv_mbox->mod >= HINIC_MOD_MAX) { |
309 | dev_err(&func_to_func->hwif->pdev->dev, "Receive illegal mbox message, mod = %d\n" , |
310 | recv_mbox->mod); |
311 | return -EINVAL; |
312 | } |
313 | |
314 | set_bit(nr: HINIC_VF_MBOX_CB_RUNNING, |
315 | addr: &func_to_func->vf_mbox_cb_state[recv_mbox->mod]); |
316 | |
317 | cb = func_to_func->vf_mbox_cb[recv_mbox->mod]; |
318 | if (cb && test_bit(HINIC_VF_MBOX_CB_REG, |
319 | &func_to_func->vf_mbox_cb_state[recv_mbox->mod])) { |
320 | cb(func_to_func->hwdev, recv_mbox->cmd, recv_mbox->mbox, |
321 | recv_mbox->mbox_len, buf_out, out_size); |
322 | } else { |
323 | dev_err(&func_to_func->hwif->pdev->dev, "VF mbox cb is not registered\n" ); |
324 | ret = -EINVAL; |
325 | } |
326 | |
327 | clear_bit(nr: HINIC_VF_MBOX_CB_RUNNING, |
328 | addr: &func_to_func->vf_mbox_cb_state[recv_mbox->mod]); |
329 | |
330 | return ret; |
331 | } |
332 | |
333 | static int |
334 | recv_pf_from_vf_mbox_handler(struct hinic_mbox_func_to_func *func_to_func, |
335 | struct hinic_recv_mbox *recv_mbox, |
336 | u16 src_func_idx, void *buf_out, |
337 | u16 *out_size) |
338 | { |
339 | hinic_pf_mbox_cb cb; |
340 | u16 vf_id = 0; |
341 | int ret; |
342 | |
343 | if (recv_mbox->mod >= HINIC_MOD_MAX) { |
344 | dev_err(&func_to_func->hwif->pdev->dev, "Receive illegal mbox message, mod = %d\n" , |
345 | recv_mbox->mod); |
346 | return -EINVAL; |
347 | } |
348 | |
349 | set_bit(nr: HINIC_PF_MBOX_CB_RUNNING, |
350 | addr: &func_to_func->pf_mbox_cb_state[recv_mbox->mod]); |
351 | |
352 | cb = func_to_func->pf_mbox_cb[recv_mbox->mod]; |
353 | if (cb && test_bit(HINIC_PF_MBOX_CB_REG, |
354 | &func_to_func->pf_mbox_cb_state[recv_mbox->mod])) { |
355 | vf_id = src_func_idx - |
356 | hinic_glb_pf_vf_offset(hwif: func_to_func->hwif); |
357 | ret = cb(func_to_func->hwdev, vf_id, recv_mbox->cmd, |
358 | recv_mbox->mbox, recv_mbox->mbox_len, |
359 | buf_out, out_size); |
360 | } else { |
361 | dev_err(&func_to_func->hwif->pdev->dev, "PF mbox mod(0x%x) cb is not registered\n" , |
362 | recv_mbox->mod); |
363 | ret = -EINVAL; |
364 | } |
365 | |
366 | clear_bit(nr: HINIC_PF_MBOX_CB_RUNNING, |
367 | addr: &func_to_func->pf_mbox_cb_state[recv_mbox->mod]); |
368 | |
369 | return ret; |
370 | } |
371 | |
372 | static bool check_mbox_seq_id_and_seg_len(struct hinic_recv_mbox *recv_mbox, |
373 | u8 seq_id, u8 seg_len) |
374 | { |
375 | if (seq_id > SEQ_ID_MAX_VAL || seg_len > MBOX_SEG_LEN) |
376 | return false; |
377 | |
378 | if (seq_id == 0) { |
379 | recv_mbox->seq_id = seq_id; |
380 | } else { |
381 | if (seq_id != recv_mbox->seq_id + 1) |
382 | return false; |
383 | |
384 | recv_mbox->seq_id = seq_id; |
385 | } |
386 | |
387 | return true; |
388 | } |
389 | |
390 | static void resp_mbox_handler(struct hinic_mbox_func_to_func *func_to_func, |
391 | struct hinic_recv_mbox *recv_mbox) |
392 | { |
393 | spin_lock(lock: &func_to_func->mbox_lock); |
394 | if (recv_mbox->msg_info.msg_id == func_to_func->send_msg_id && |
395 | func_to_func->event_flag == EVENT_START) |
396 | complete(&recv_mbox->recv_done); |
397 | else |
398 | dev_err(&func_to_func->hwif->pdev->dev, |
399 | "Mbox response timeout, current send msg id(0x%x), recv msg id(0x%x), status(0x%x)\n" , |
400 | func_to_func->send_msg_id, recv_mbox->msg_info.msg_id, |
401 | recv_mbox->msg_info.status); |
402 | spin_unlock(lock: &func_to_func->mbox_lock); |
403 | } |
404 | |
405 | static void recv_func_mbox_handler(struct hinic_mbox_func_to_func *func_to_func, |
406 | struct hinic_recv_mbox *recv_mbox, |
407 | u16 src_func_idx); |
408 | |
409 | static void recv_func_mbox_work_handler(struct work_struct *work) |
410 | { |
411 | struct hinic_mbox_work *mbox_work = |
412 | container_of(work, struct hinic_mbox_work, work); |
413 | struct hinic_recv_mbox *recv_mbox; |
414 | |
415 | recv_func_mbox_handler(func_to_func: mbox_work->func_to_func, recv_mbox: mbox_work->recv_mbox, |
416 | src_func_idx: mbox_work->src_func_idx); |
417 | |
418 | recv_mbox = |
419 | &mbox_work->func_to_func->mbox_send[mbox_work->src_func_idx]; |
420 | |
421 | atomic_dec(v: &recv_mbox->msg_cnt); |
422 | |
423 | kfree(objp: mbox_work); |
424 | } |
425 | |
426 | static void recv_mbox_handler(struct hinic_mbox_func_to_func *func_to_func, |
427 | void *, struct hinic_recv_mbox *recv_mbox) |
428 | { |
429 | void *mbox_body = MBOX_BODY_FROM_HDR(header); |
430 | struct hinic_recv_mbox *rcv_mbox_temp = NULL; |
431 | u64 = *((u64 *)header); |
432 | struct hinic_mbox_work *mbox_work; |
433 | u8 seq_id, seg_len; |
434 | u16 src_func_idx; |
435 | int pos; |
436 | |
437 | seq_id = HINIC_MBOX_HEADER_GET(mbox_header, SEQID); |
438 | seg_len = HINIC_MBOX_HEADER_GET(mbox_header, SEG_LEN); |
439 | src_func_idx = HINIC_MBOX_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX); |
440 | |
441 | if (!check_mbox_seq_id_and_seg_len(recv_mbox, seq_id, seg_len)) { |
442 | dev_err(&func_to_func->hwif->pdev->dev, |
443 | "Mailbox sequence and segment check fail, src func id: 0x%x, front id: 0x%x, current id: 0x%x, seg len: 0x%x\n" , |
444 | src_func_idx, recv_mbox->seq_id, seq_id, seg_len); |
445 | recv_mbox->seq_id = SEQ_ID_MAX_VAL; |
446 | return; |
447 | } |
448 | |
449 | pos = seq_id * MBOX_SEG_LEN; |
450 | memcpy((u8 *)recv_mbox->mbox + pos, mbox_body, |
451 | HINIC_MBOX_HEADER_GET(mbox_header, SEG_LEN)); |
452 | |
453 | if (!HINIC_MBOX_HEADER_GET(mbox_header, LAST)) |
454 | return; |
455 | |
456 | recv_mbox->cmd = HINIC_MBOX_HEADER_GET(mbox_header, CMD); |
457 | recv_mbox->mod = HINIC_MBOX_HEADER_GET(mbox_header, MODULE); |
458 | recv_mbox->mbox_len = HINIC_MBOX_HEADER_GET(mbox_header, MSG_LEN); |
459 | recv_mbox->ack_type = HINIC_MBOX_HEADER_GET(mbox_header, NO_ACK); |
460 | recv_mbox->msg_info.msg_id = HINIC_MBOX_HEADER_GET(mbox_header, MSG_ID); |
461 | recv_mbox->msg_info.status = HINIC_MBOX_HEADER_GET(mbox_header, STATUS); |
462 | recv_mbox->seq_id = SEQ_ID_MAX_VAL; |
463 | |
464 | if (HINIC_MBOX_HEADER_GET(mbox_header, DIRECTION) == |
465 | HINIC_HWIF_RESPONSE) { |
466 | resp_mbox_handler(func_to_func, recv_mbox); |
467 | return; |
468 | } |
469 | |
470 | if (atomic_read(v: &recv_mbox->msg_cnt) > HINIC_MAX_MSG_CNT_TO_PROCESS) { |
471 | dev_warn(&func_to_func->hwif->pdev->dev, |
472 | "This function(%u) have %d message wait to process,can't add to work queue\n" , |
473 | src_func_idx, atomic_read(&recv_mbox->msg_cnt)); |
474 | return; |
475 | } |
476 | |
477 | rcv_mbox_temp = kmemdup(p: recv_mbox, size: sizeof(*rcv_mbox_temp), GFP_KERNEL); |
478 | if (!rcv_mbox_temp) |
479 | return; |
480 | |
481 | rcv_mbox_temp->mbox = kmemdup(p: recv_mbox->mbox, MBOX_MAX_BUF_SZ, |
482 | GFP_KERNEL); |
483 | if (!rcv_mbox_temp->mbox) |
484 | goto err_alloc_rcv_mbox_msg; |
485 | |
486 | rcv_mbox_temp->buf_out = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL); |
487 | if (!rcv_mbox_temp->buf_out) |
488 | goto err_alloc_rcv_mbox_buf; |
489 | |
490 | mbox_work = kzalloc(size: sizeof(*mbox_work), GFP_KERNEL); |
491 | if (!mbox_work) |
492 | goto err_alloc_mbox_work; |
493 | |
494 | mbox_work->func_to_func = func_to_func; |
495 | mbox_work->recv_mbox = rcv_mbox_temp; |
496 | mbox_work->src_func_idx = src_func_idx; |
497 | |
498 | atomic_inc(v: &recv_mbox->msg_cnt); |
499 | INIT_WORK(&mbox_work->work, recv_func_mbox_work_handler); |
500 | queue_work(wq: func_to_func->workq, work: &mbox_work->work); |
501 | |
502 | return; |
503 | |
504 | err_alloc_mbox_work: |
505 | kfree(objp: rcv_mbox_temp->buf_out); |
506 | |
507 | err_alloc_rcv_mbox_buf: |
508 | kfree(objp: rcv_mbox_temp->mbox); |
509 | |
510 | err_alloc_rcv_mbox_msg: |
511 | kfree(objp: rcv_mbox_temp); |
512 | } |
513 | |
514 | static int set_vf_mbox_random_id(struct hinic_hwdev *hwdev, u16 func_id) |
515 | { |
516 | struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func; |
517 | struct hinic_set_random_id rand_info = {0}; |
518 | u16 out_size = sizeof(rand_info); |
519 | struct hinic_pfhwdev *pfhwdev; |
520 | int ret; |
521 | |
522 | pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); |
523 | |
524 | rand_info.version = HINIC_CMD_VER_FUNC_ID; |
525 | rand_info.func_idx = func_id; |
526 | rand_info.vf_in_pf = func_id - hinic_glb_pf_vf_offset(hwif: hwdev->hwif); |
527 | rand_info.random_id = get_random_u32(); |
528 | |
529 | func_to_func->vf_mbx_rand_id[func_id] = rand_info.random_id; |
530 | |
531 | ret = hinic_msg_to_mgmt(pf_to_mgmt: &pfhwdev->pf_to_mgmt, mod: HINIC_MOD_COMM, |
532 | cmd: HINIC_MGMT_CMD_SET_VF_RANDOM_ID, |
533 | buf_in: &rand_info, in_size: sizeof(rand_info), |
534 | buf_out: &rand_info, out_size: &out_size, sync: HINIC_MGMT_MSG_SYNC); |
535 | if ((rand_info.status != HINIC_MGMT_CMD_UNSUPPORTED && |
536 | rand_info.status) || !out_size || ret) { |
537 | dev_err(&hwdev->hwif->pdev->dev, "Set VF random id failed, err: %d, status: 0x%x, out size: 0x%x\n" , |
538 | ret, rand_info.status, out_size); |
539 | return -EIO; |
540 | } |
541 | |
542 | if (rand_info.status == HINIC_MGMT_CMD_UNSUPPORTED) |
543 | return rand_info.status; |
544 | |
545 | func_to_func->vf_mbx_old_rand_id[func_id] = |
546 | func_to_func->vf_mbx_rand_id[func_id]; |
547 | |
548 | return 0; |
549 | } |
550 | |
551 | static void update_random_id_work_handler(struct work_struct *work) |
552 | { |
553 | struct hinic_mbox_work *mbox_work = |
554 | container_of(work, struct hinic_mbox_work, work); |
555 | struct hinic_mbox_func_to_func *func_to_func; |
556 | u16 src = mbox_work->src_func_idx; |
557 | |
558 | func_to_func = mbox_work->func_to_func; |
559 | |
560 | if (set_vf_mbox_random_id(hwdev: func_to_func->hwdev, func_id: src)) |
561 | dev_warn(&func_to_func->hwdev->hwif->pdev->dev, "Update VF id: 0x%x random id failed\n" , |
562 | mbox_work->src_func_idx); |
563 | |
564 | kfree(objp: mbox_work); |
565 | } |
566 | |
567 | static bool check_vf_mbox_random_id(struct hinic_mbox_func_to_func *func_to_func, |
568 | u8 *) |
569 | { |
570 | struct hinic_hwdev *hwdev = func_to_func->hwdev; |
571 | struct hinic_mbox_work *mbox_work = NULL; |
572 | u64 = *((u64 *)header); |
573 | u16 offset, src; |
574 | u32 random_id; |
575 | int vf_in_pf; |
576 | |
577 | src = HINIC_MBOX_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX); |
578 | |
579 | if (IS_PF_OR_PPF_SRC(src) || !func_to_func->support_vf_random) |
580 | return true; |
581 | |
582 | if (!HINIC_IS_PPF(hwdev->hwif)) { |
583 | offset = hinic_glb_pf_vf_offset(hwif: hwdev->hwif); |
584 | vf_in_pf = src - offset; |
585 | |
586 | if (vf_in_pf < 1 || vf_in_pf > hwdev->nic_cap.max_vf) { |
587 | dev_warn(&hwdev->hwif->pdev->dev, |
588 | "Receive vf id(0x%x) is invalid, vf id should be from 0x%x to 0x%x\n" , |
589 | src, offset + 1, |
590 | hwdev->nic_cap.max_vf + offset); |
591 | return false; |
592 | } |
593 | } |
594 | |
595 | random_id = be32_to_cpu(*(u32 *)(header + MBOX_SEG_LEN + |
596 | MBOX_HEADER_SZ)); |
597 | |
598 | if (random_id == func_to_func->vf_mbx_rand_id[src] || |
599 | random_id == func_to_func->vf_mbx_old_rand_id[src]) |
600 | return true; |
601 | |
602 | dev_warn(&hwdev->hwif->pdev->dev, |
603 | "The mailbox random id(0x%x) of func_id(0x%x) doesn't match with pf reservation(0x%x)\n" , |
604 | random_id, src, func_to_func->vf_mbx_rand_id[src]); |
605 | |
606 | mbox_work = kzalloc(size: sizeof(*mbox_work), GFP_KERNEL); |
607 | if (!mbox_work) |
608 | return false; |
609 | |
610 | mbox_work->func_to_func = func_to_func; |
611 | mbox_work->src_func_idx = src; |
612 | |
613 | INIT_WORK(&mbox_work->work, update_random_id_work_handler); |
614 | queue_work(wq: func_to_func->workq, work: &mbox_work->work); |
615 | |
616 | return false; |
617 | } |
618 | |
619 | static void hinic_mbox_func_aeqe_handler(void *handle, void *, u8 size) |
620 | { |
621 | struct hinic_mbox_func_to_func *func_to_func; |
622 | u64 = *((u64 *)header); |
623 | struct hinic_recv_mbox *recv_mbox; |
624 | u64 src, dir; |
625 | |
626 | func_to_func = ((struct hinic_hwdev *)handle)->func_to_func; |
627 | |
628 | dir = HINIC_MBOX_HEADER_GET(mbox_header, DIRECTION); |
629 | src = HINIC_MBOX_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX); |
630 | |
631 | if (src >= HINIC_MAX_FUNCTIONS) { |
632 | dev_err(&func_to_func->hwif->pdev->dev, |
633 | "Mailbox source function id:%u is invalid\n" , (u32)src); |
634 | return; |
635 | } |
636 | |
637 | if (!check_vf_mbox_random_id(func_to_func, header)) |
638 | return; |
639 | |
640 | recv_mbox = (dir == HINIC_HWIF_DIRECT_SEND) ? |
641 | &func_to_func->mbox_send[src] : |
642 | &func_to_func->mbox_resp[src]; |
643 | |
644 | recv_mbox_handler(func_to_func, header: (u64 *)header, recv_mbox); |
645 | } |
646 | |
647 | static void hinic_mbox_self_aeqe_handler(void *handle, void *, u8 size) |
648 | { |
649 | struct hinic_mbox_func_to_func *func_to_func; |
650 | struct hinic_send_mbox *send_mbox; |
651 | |
652 | func_to_func = ((struct hinic_hwdev *)handle)->func_to_func; |
653 | send_mbox = &func_to_func->send_mbox; |
654 | |
655 | complete(&send_mbox->send_done); |
656 | } |
657 | |
658 | static void clear_mbox_status(struct hinic_send_mbox *mbox) |
659 | { |
660 | *mbox->wb_status = 0; |
661 | |
662 | /* clear mailbox write back status */ |
663 | wmb(); |
664 | } |
665 | |
666 | static void (struct hinic_hwdev *hwdev, |
667 | struct hinic_send_mbox *mbox, u64 *) |
668 | { |
669 | u32 i, idx_max = MBOX_HEADER_SZ / sizeof(u32); |
670 | u32 *data = (u32 *)header; |
671 | |
672 | for (i = 0; i < idx_max; i++) |
673 | __raw_writel(val: *(data + i), addr: mbox->data + i * sizeof(u32)); |
674 | } |
675 | |
676 | static void mbox_copy_send_data(struct hinic_hwdev *hwdev, |
677 | struct hinic_send_mbox *mbox, void *seg, |
678 | u16 seg_len) |
679 | { |
680 | u8 mbox_max_buf[MBOX_SEG_LEN] = {0}; |
681 | u32 data_len, chk_sz = sizeof(u32); |
682 | u32 *data = seg; |
683 | u32 i, idx_max; |
684 | |
685 | /* The mbox message should be aligned in 4 bytes. */ |
686 | if (seg_len % chk_sz) { |
687 | memcpy(mbox_max_buf, seg, seg_len); |
688 | data = (u32 *)mbox_max_buf; |
689 | } |
690 | |
691 | data_len = seg_len; |
692 | idx_max = ALIGN(data_len, chk_sz) / chk_sz; |
693 | |
694 | for (i = 0; i < idx_max; i++) |
695 | __raw_writel(val: *(data + i), |
696 | addr: mbox->data + MBOX_HEADER_SZ + i * sizeof(u32)); |
697 | } |
698 | |
699 | static void write_mbox_msg_attr(struct hinic_mbox_func_to_func *func_to_func, |
700 | u16 dst_func, u16 dst_aeqn, u16 seg_len, |
701 | int poll) |
702 | { |
703 | u16 rsp_aeq = (dst_aeqn == 0) ? 0 : HINIC_MBOX_RSP_AEQN; |
704 | u32 mbox_int, mbox_ctrl; |
705 | |
706 | mbox_int = HINIC_MBOX_INT_SET(dst_func, DST_FUNC) | |
707 | HINIC_MBOX_INT_SET(dst_aeqn, DST_AEQN) | |
708 | HINIC_MBOX_INT_SET(rsp_aeq, SRC_RESP_AEQN) | |
709 | HINIC_MBOX_INT_SET(NO_DMA_ATTRIBUTE_VAL, STAT_DMA) | |
710 | HINIC_MBOX_INT_SET(ALIGN(MBOX_SEG_LEN + MBOX_HEADER_SZ + |
711 | MBOX_INFO_SZ, MBOX_SEG_LEN_ALIGN) >> 2, |
712 | TX_SIZE) | |
713 | HINIC_MBOX_INT_SET(STRONG_ORDER, STAT_DMA_SO_RO) | |
714 | HINIC_MBOX_INT_SET(WRITE_BACK, WB_EN); |
715 | |
716 | hinic_hwif_write_reg(hwif: func_to_func->hwif, |
717 | HINIC_FUNC_CSR_MAILBOX_INT_OFFSET_OFF, val: mbox_int); |
718 | |
719 | wmb(); /* writing the mbox int attributes */ |
720 | mbox_ctrl = HINIC_MBOX_CTRL_SET(TX_NOT_DONE, TX_STATUS); |
721 | |
722 | if (poll) |
723 | mbox_ctrl |= HINIC_MBOX_CTRL_SET(NOT_TRIGGER, TRIGGER_AEQE); |
724 | else |
725 | mbox_ctrl |= HINIC_MBOX_CTRL_SET(TRIGGER, TRIGGER_AEQE); |
726 | |
727 | hinic_hwif_write_reg(hwif: func_to_func->hwif, |
728 | HINIC_FUNC_CSR_MAILBOX_CONTROL_OFF, val: mbox_ctrl); |
729 | } |
730 | |
731 | static void dump_mox_reg(struct hinic_hwdev *hwdev) |
732 | { |
733 | u32 val; |
734 | |
735 | val = hinic_hwif_read_reg(hwif: hwdev->hwif, |
736 | HINIC_FUNC_CSR_MAILBOX_CONTROL_OFF); |
737 | dev_err(&hwdev->hwif->pdev->dev, "Mailbox control reg: 0x%x\n" , val); |
738 | |
739 | val = hinic_hwif_read_reg(hwif: hwdev->hwif, |
740 | HINIC_FUNC_CSR_MAILBOX_INT_OFFSET_OFF); |
741 | dev_err(&hwdev->hwif->pdev->dev, "Mailbox interrupt offset: 0x%x\n" , |
742 | val); |
743 | } |
744 | |
745 | static u16 get_mbox_status(struct hinic_send_mbox *mbox) |
746 | { |
747 | /* write back is 16B, but only use first 4B */ |
748 | u64 wb_val = be64_to_cpu(*mbox->wb_status); |
749 | |
750 | rmb(); /* verify reading before check */ |
751 | |
752 | return (u16)(wb_val & MBOX_WB_STATUS_ERRCODE_MASK); |
753 | } |
754 | |
755 | static int |
756 | wait_for_mbox_seg_completion(struct hinic_mbox_func_to_func *func_to_func, |
757 | int poll, u16 *wb_status) |
758 | { |
759 | struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox; |
760 | struct hinic_hwdev *hwdev = func_to_func->hwdev; |
761 | struct completion *done = &send_mbox->send_done; |
762 | u32 cnt = 0; |
763 | unsigned long jif; |
764 | |
765 | if (poll) { |
766 | while (cnt < MBOX_MSG_POLLING_TIMEOUT) { |
767 | *wb_status = get_mbox_status(mbox: send_mbox); |
768 | if (MBOX_STATUS_FINISHED(*wb_status)) |
769 | break; |
770 | |
771 | usleep_range(min: 900, max: 1000); |
772 | cnt++; |
773 | } |
774 | |
775 | if (cnt == MBOX_MSG_POLLING_TIMEOUT) { |
776 | dev_err(&hwdev->hwif->pdev->dev, "Send mailbox segment timeout, wb status: 0x%x\n" , |
777 | *wb_status); |
778 | dump_mox_reg(hwdev); |
779 | return -ETIMEDOUT; |
780 | } |
781 | } else { |
782 | jif = msecs_to_jiffies(HINIC_MBOX_COMP_TIME); |
783 | if (!wait_for_completion_timeout(x: done, timeout: jif)) { |
784 | dev_err(&hwdev->hwif->pdev->dev, "Send mailbox segment timeout\n" ); |
785 | dump_mox_reg(hwdev); |
786 | hinic_dump_aeq_info(hwdev); |
787 | return -ETIMEDOUT; |
788 | } |
789 | |
790 | *wb_status = get_mbox_status(mbox: send_mbox); |
791 | } |
792 | |
793 | return 0; |
794 | } |
795 | |
796 | static int send_mbox_seg(struct hinic_mbox_func_to_func *func_to_func, |
797 | u64 , u16 dst_func, void *seg, u16 seg_len, |
798 | int poll, void *msg_info) |
799 | { |
800 | struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox; |
801 | u16 seq_dir = HINIC_MBOX_HEADER_GET(header, DIRECTION); |
802 | struct hinic_hwdev *hwdev = func_to_func->hwdev; |
803 | struct completion *done = &send_mbox->send_done; |
804 | u8 num_aeqs = hwdev->hwif->attr.num_aeqs; |
805 | u16 dst_aeqn, wb_status = 0, errcode; |
806 | |
807 | if (num_aeqs >= 4) |
808 | dst_aeqn = (seq_dir == HINIC_HWIF_DIRECT_SEND) ? |
809 | HINIC_MBOX_RECV_AEQN : HINIC_MBOX_RSP_AEQN; |
810 | else |
811 | dst_aeqn = 0; |
812 | |
813 | if (!poll) |
814 | init_completion(x: done); |
815 | |
816 | clear_mbox_status(mbox: send_mbox); |
817 | |
818 | mbox_copy_header(hwdev, mbox: send_mbox, header: &header); |
819 | |
820 | mbox_copy_send_data(hwdev, mbox: send_mbox, seg, seg_len); |
821 | |
822 | write_mbox_msg_attr(func_to_func, dst_func, dst_aeqn, seg_len, poll); |
823 | |
824 | wmb(); /* writing the mbox msg attributes */ |
825 | |
826 | if (wait_for_mbox_seg_completion(func_to_func, poll, wb_status: &wb_status)) |
827 | return -ETIMEDOUT; |
828 | |
829 | if (!MBOX_STATUS_SUCCESS(wb_status)) { |
830 | dev_err(&hwdev->hwif->pdev->dev, "Send mailbox segment to function %d error, wb status: 0x%x\n" , |
831 | dst_func, wb_status); |
832 | errcode = MBOX_STATUS_ERRCODE(wb_status); |
833 | return errcode ? errcode : -EFAULT; |
834 | } |
835 | |
836 | return 0; |
837 | } |
838 | |
839 | static int send_mbox_to_func(struct hinic_mbox_func_to_func *func_to_func, |
840 | enum hinic_mod_type mod, u16 cmd, void *msg, |
841 | u16 msg_len, u16 dst_func, |
842 | enum hinic_hwif_direction_type direction, |
843 | enum hinic_mbox_ack_type ack_type, |
844 | struct mbox_msg_info *msg_info) |
845 | { |
846 | struct hinic_hwdev *hwdev = func_to_func->hwdev; |
847 | u16 seg_len = MBOX_SEG_LEN; |
848 | u8 *msg_seg = (u8 *)msg; |
849 | u16 left = msg_len; |
850 | u32 seq_id = 0; |
851 | u64 = 0; |
852 | int err = 0; |
853 | |
854 | down(sem: &func_to_func->msg_send_sem); |
855 | |
856 | header = HINIC_MBOX_HEADER_SET(msg_len, MSG_LEN) | |
857 | HINIC_MBOX_HEADER_SET(mod, MODULE) | |
858 | HINIC_MBOX_HEADER_SET(seg_len, SEG_LEN) | |
859 | HINIC_MBOX_HEADER_SET(ack_type, NO_ACK) | |
860 | HINIC_MBOX_HEADER_SET(SEQ_ID_START_VAL, SEQID) | |
861 | HINIC_MBOX_HEADER_SET(NOT_LAST_SEG, LAST) | |
862 | HINIC_MBOX_HEADER_SET(direction, DIRECTION) | |
863 | HINIC_MBOX_HEADER_SET(cmd, CMD) | |
864 | /* The vf's offset to it's associated pf */ |
865 | HINIC_MBOX_HEADER_SET(msg_info->msg_id, MSG_ID) | |
866 | HINIC_MBOX_HEADER_SET(msg_info->status, STATUS) | |
867 | HINIC_MBOX_HEADER_SET(hinic_global_func_id_hw(hwdev->hwif), |
868 | SRC_GLB_FUNC_IDX); |
869 | |
870 | while (!(HINIC_MBOX_HEADER_GET(header, LAST))) { |
871 | if (left <= HINIC_MBOX_SEG_LEN) { |
872 | header &= ~MBOX_SEGLEN_MASK; |
873 | header |= HINIC_MBOX_HEADER_SET(left, SEG_LEN); |
874 | header |= HINIC_MBOX_HEADER_SET(LAST_SEG, LAST); |
875 | |
876 | seg_len = left; |
877 | } |
878 | |
879 | err = send_mbox_seg(func_to_func, header, dst_func, seg: msg_seg, |
880 | seg_len, poll: MBOX_SEND_MSG_INT, msg_info); |
881 | if (err) { |
882 | dev_err(&hwdev->hwif->pdev->dev, "Failed to send mbox seg, seq_id=0x%llx\n" , |
883 | HINIC_MBOX_HEADER_GET(header, SEQID)); |
884 | goto err_send_mbox_seg; |
885 | } |
886 | |
887 | left -= HINIC_MBOX_SEG_LEN; |
888 | msg_seg += HINIC_MBOX_SEG_LEN; |
889 | |
890 | seq_id++; |
891 | header &= ~(HINIC_MBOX_HEADER_SET(HINIC_MBOX_HEADER_SEQID_MASK, |
892 | SEQID)); |
893 | header |= HINIC_MBOX_HEADER_SET(seq_id, SEQID); |
894 | } |
895 | |
896 | err_send_mbox_seg: |
897 | up(sem: &func_to_func->msg_send_sem); |
898 | |
899 | return err; |
900 | } |
901 | |
902 | static void |
903 | response_for_recv_func_mbox(struct hinic_mbox_func_to_func *func_to_func, |
904 | struct hinic_recv_mbox *recv_mbox, int err, |
905 | u16 out_size, u16 src_func_idx) |
906 | { |
907 | struct mbox_msg_info msg_info = {0}; |
908 | |
909 | if (recv_mbox->ack_type == MBOX_ACK) { |
910 | msg_info.msg_id = recv_mbox->msg_info.msg_id; |
911 | if (err == HINIC_MBOX_PF_BUSY_ACTIVE_FW) |
912 | msg_info.status = HINIC_MBOX_PF_BUSY_ACTIVE_FW; |
913 | else if (err == HINIC_MBOX_VF_CMD_ERROR) |
914 | msg_info.status = HINIC_MBOX_VF_CMD_ERROR; |
915 | else if (err) |
916 | msg_info.status = HINIC_MBOX_PF_SEND_ERR; |
917 | |
918 | /* if no data needs to response, set out_size to 1 */ |
919 | if (!out_size || err) |
920 | out_size = MBOX_MSG_NO_DATA_LEN; |
921 | |
922 | send_mbox_to_func(func_to_func, mod: recv_mbox->mod, cmd: recv_mbox->cmd, |
923 | msg: recv_mbox->buf_out, msg_len: out_size, dst_func: src_func_idx, |
924 | direction: HINIC_HWIF_RESPONSE, ack_type: MBOX_ACK, |
925 | msg_info: &msg_info); |
926 | } |
927 | } |
928 | |
929 | static void recv_func_mbox_handler(struct hinic_mbox_func_to_func *func_to_func, |
930 | struct hinic_recv_mbox *recv_mbox, |
931 | u16 src_func_idx) |
932 | { |
933 | void *buf_out = recv_mbox->buf_out; |
934 | u16 out_size = MBOX_MAX_BUF_SZ; |
935 | int err = 0; |
936 | |
937 | if (HINIC_IS_VF(func_to_func->hwif)) { |
938 | err = recv_vf_mbox_handler(func_to_func, recv_mbox, buf_out, |
939 | out_size: &out_size); |
940 | } else { |
941 | if (IS_PF_OR_PPF_SRC(src_func_idx)) |
942 | dev_warn(&func_to_func->hwif->pdev->dev, |
943 | "Unsupported pf2pf mbox msg\n" ); |
944 | else |
945 | err = recv_pf_from_vf_mbox_handler(func_to_func, |
946 | recv_mbox, |
947 | src_func_idx, |
948 | buf_out, out_size: &out_size); |
949 | } |
950 | |
951 | response_for_recv_func_mbox(func_to_func, recv_mbox, err, out_size, |
952 | src_func_idx); |
953 | kfree(objp: recv_mbox->buf_out); |
954 | kfree(objp: recv_mbox->mbox); |
955 | kfree(objp: recv_mbox); |
956 | } |
957 | |
958 | static void set_mbox_to_func_event(struct hinic_mbox_func_to_func *func_to_func, |
959 | enum mbox_event_state event_flag) |
960 | { |
961 | spin_lock(lock: &func_to_func->mbox_lock); |
962 | func_to_func->event_flag = event_flag; |
963 | spin_unlock(lock: &func_to_func->mbox_lock); |
964 | } |
965 | |
966 | static int mbox_resp_info_handler(struct hinic_mbox_func_to_func *func_to_func, |
967 | struct hinic_recv_mbox *mbox_for_resp, |
968 | enum hinic_mod_type mod, u16 cmd, |
969 | void *buf_out, u16 *out_size) |
970 | { |
971 | int err; |
972 | |
973 | if (mbox_for_resp->msg_info.status) { |
974 | err = mbox_for_resp->msg_info.status; |
975 | if (err != HINIC_MBOX_PF_BUSY_ACTIVE_FW) |
976 | dev_err(&func_to_func->hwif->pdev->dev, "Mbox response error(0x%x)\n" , |
977 | mbox_for_resp->msg_info.status); |
978 | return err; |
979 | } |
980 | |
981 | if (buf_out && out_size) { |
982 | if (*out_size < mbox_for_resp->mbox_len) { |
983 | dev_err(&func_to_func->hwif->pdev->dev, |
984 | "Invalid response mbox message length: %d for mod %d cmd %d, should less than: %d\n" , |
985 | mbox_for_resp->mbox_len, mod, cmd, *out_size); |
986 | return -EFAULT; |
987 | } |
988 | |
989 | if (mbox_for_resp->mbox_len) |
990 | memcpy(buf_out, mbox_for_resp->mbox, |
991 | mbox_for_resp->mbox_len); |
992 | |
993 | *out_size = mbox_for_resp->mbox_len; |
994 | } |
995 | |
996 | return 0; |
997 | } |
998 | |
999 | int hinic_mbox_to_func(struct hinic_mbox_func_to_func *func_to_func, |
1000 | enum hinic_mod_type mod, u16 cmd, u16 dst_func, |
1001 | void *buf_in, u16 in_size, void *buf_out, |
1002 | u16 *out_size, u32 timeout) |
1003 | { |
1004 | struct hinic_recv_mbox *mbox_for_resp; |
1005 | struct mbox_msg_info msg_info = {0}; |
1006 | unsigned long timeo; |
1007 | int err; |
1008 | |
1009 | mbox_for_resp = &func_to_func->mbox_resp[dst_func]; |
1010 | |
1011 | down(sem: &func_to_func->mbox_send_sem); |
1012 | |
1013 | init_completion(x: &mbox_for_resp->recv_done); |
1014 | |
1015 | msg_info.msg_id = MBOX_MSG_ID_INC(func_to_func); |
1016 | |
1017 | set_mbox_to_func_event(func_to_func, event_flag: EVENT_START); |
1018 | |
1019 | err = send_mbox_to_func(func_to_func, mod, cmd, msg: buf_in, msg_len: in_size, |
1020 | dst_func, direction: HINIC_HWIF_DIRECT_SEND, ack_type: MBOX_ACK, |
1021 | msg_info: &msg_info); |
1022 | if (err) { |
1023 | dev_err(&func_to_func->hwif->pdev->dev, "Send mailbox failed, msg_id: %d\n" , |
1024 | msg_info.msg_id); |
1025 | set_mbox_to_func_event(func_to_func, event_flag: EVENT_FAIL); |
1026 | goto err_send_mbox; |
1027 | } |
1028 | |
1029 | timeo = msecs_to_jiffies(m: timeout ? timeout : HINIC_MBOX_COMP_TIME); |
1030 | if (!wait_for_completion_timeout(x: &mbox_for_resp->recv_done, timeout: timeo)) { |
1031 | set_mbox_to_func_event(func_to_func, event_flag: EVENT_TIMEOUT); |
1032 | dev_err(&func_to_func->hwif->pdev->dev, |
1033 | "Send mbox msg timeout, msg_id: %d\n" , msg_info.msg_id); |
1034 | hinic_dump_aeq_info(hwdev: func_to_func->hwdev); |
1035 | err = -ETIMEDOUT; |
1036 | goto err_send_mbox; |
1037 | } |
1038 | |
1039 | set_mbox_to_func_event(func_to_func, event_flag: EVENT_END); |
1040 | |
1041 | err = mbox_resp_info_handler(func_to_func, mbox_for_resp, mod, cmd, |
1042 | buf_out, out_size); |
1043 | |
1044 | err_send_mbox: |
1045 | up(sem: &func_to_func->mbox_send_sem); |
1046 | |
1047 | return err; |
1048 | } |
1049 | |
1050 | static int mbox_func_params_valid(struct hinic_mbox_func_to_func *func_to_func, |
1051 | void *buf_in, u16 in_size) |
1052 | { |
1053 | if (in_size > HINIC_MBOX_DATA_SIZE) { |
1054 | dev_err(&func_to_func->hwif->pdev->dev, |
1055 | "Mbox msg len(%d) exceed limit(%d)\n" , |
1056 | in_size, HINIC_MBOX_DATA_SIZE); |
1057 | return -EINVAL; |
1058 | } |
1059 | |
1060 | return 0; |
1061 | } |
1062 | |
1063 | int hinic_mbox_to_pf(struct hinic_hwdev *hwdev, |
1064 | enum hinic_mod_type mod, u8 cmd, void *buf_in, |
1065 | u16 in_size, void *buf_out, u16 *out_size, u32 timeout) |
1066 | { |
1067 | struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func; |
1068 | int err = mbox_func_params_valid(func_to_func, buf_in, in_size); |
1069 | |
1070 | if (err) |
1071 | return err; |
1072 | |
1073 | if (!HINIC_IS_VF(hwdev->hwif)) { |
1074 | dev_err(&hwdev->hwif->pdev->dev, "Params error, func_type: %d\n" , |
1075 | HINIC_FUNC_TYPE(hwdev->hwif)); |
1076 | return -EINVAL; |
1077 | } |
1078 | |
1079 | return hinic_mbox_to_func(func_to_func, mod, cmd, |
1080 | dst_func: hinic_pf_id_of_vf_hw(hwif: hwdev->hwif), buf_in, |
1081 | in_size, buf_out, out_size, timeout); |
1082 | } |
1083 | |
1084 | int hinic_mbox_to_vf(struct hinic_hwdev *hwdev, |
1085 | enum hinic_mod_type mod, u16 vf_id, u8 cmd, void *buf_in, |
1086 | u16 in_size, void *buf_out, u16 *out_size, u32 timeout) |
1087 | { |
1088 | struct hinic_mbox_func_to_func *func_to_func; |
1089 | u16 dst_func_idx; |
1090 | int err; |
1091 | |
1092 | if (!hwdev) |
1093 | return -EINVAL; |
1094 | |
1095 | func_to_func = hwdev->func_to_func; |
1096 | err = mbox_func_params_valid(func_to_func, buf_in, in_size); |
1097 | if (err) |
1098 | return err; |
1099 | |
1100 | if (HINIC_IS_VF(hwdev->hwif)) { |
1101 | dev_err(&hwdev->hwif->pdev->dev, "Params error, func_type: %d\n" , |
1102 | HINIC_FUNC_TYPE(hwdev->hwif)); |
1103 | return -EINVAL; |
1104 | } |
1105 | |
1106 | if (!vf_id) { |
1107 | dev_err(&hwdev->hwif->pdev->dev, |
1108 | "VF id(%d) error!\n" , vf_id); |
1109 | return -EINVAL; |
1110 | } |
1111 | |
1112 | /* vf_offset_to_pf + vf_id is the vf's global function id of vf in |
1113 | * this pf |
1114 | */ |
1115 | dst_func_idx = hinic_glb_pf_vf_offset(hwif: hwdev->hwif) + vf_id; |
1116 | |
1117 | return hinic_mbox_to_func(func_to_func, mod, cmd, dst_func: dst_func_idx, buf_in, |
1118 | in_size, buf_out, out_size, timeout); |
1119 | } |
1120 | |
1121 | static int init_mbox_info(struct hinic_recv_mbox *mbox_info) |
1122 | { |
1123 | int err; |
1124 | |
1125 | mbox_info->seq_id = SEQ_ID_MAX_VAL; |
1126 | |
1127 | mbox_info->mbox = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL); |
1128 | if (!mbox_info->mbox) |
1129 | return -ENOMEM; |
1130 | |
1131 | mbox_info->buf_out = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL); |
1132 | if (!mbox_info->buf_out) { |
1133 | err = -ENOMEM; |
1134 | goto err_alloc_buf_out; |
1135 | } |
1136 | |
1137 | atomic_set(v: &mbox_info->msg_cnt, i: 0); |
1138 | |
1139 | return 0; |
1140 | |
1141 | err_alloc_buf_out: |
1142 | kfree(objp: mbox_info->mbox); |
1143 | |
1144 | return err; |
1145 | } |
1146 | |
1147 | static void clean_mbox_info(struct hinic_recv_mbox *mbox_info) |
1148 | { |
1149 | kfree(objp: mbox_info->buf_out); |
1150 | kfree(objp: mbox_info->mbox); |
1151 | } |
1152 | |
1153 | static int alloc_mbox_info(struct hinic_hwdev *hwdev, |
1154 | struct hinic_recv_mbox *mbox_info) |
1155 | { |
1156 | u16 func_idx, i; |
1157 | int err; |
1158 | |
1159 | for (func_idx = 0; func_idx < HINIC_MAX_FUNCTIONS; func_idx++) { |
1160 | err = init_mbox_info(mbox_info: &mbox_info[func_idx]); |
1161 | if (err) { |
1162 | dev_err(&hwdev->hwif->pdev->dev, "Failed to init function %d mbox info\n" , |
1163 | func_idx); |
1164 | goto err_init_mbox_info; |
1165 | } |
1166 | } |
1167 | |
1168 | return 0; |
1169 | |
1170 | err_init_mbox_info: |
1171 | for (i = 0; i < func_idx; i++) |
1172 | clean_mbox_info(mbox_info: &mbox_info[i]); |
1173 | |
1174 | return err; |
1175 | } |
1176 | |
1177 | static void free_mbox_info(struct hinic_recv_mbox *mbox_info) |
1178 | { |
1179 | u16 func_idx; |
1180 | |
1181 | for (func_idx = 0; func_idx < HINIC_MAX_FUNCTIONS; func_idx++) |
1182 | clean_mbox_info(mbox_info: &mbox_info[func_idx]); |
1183 | } |
1184 | |
1185 | static void prepare_send_mbox(struct hinic_mbox_func_to_func *func_to_func) |
1186 | { |
1187 | struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox; |
1188 | |
1189 | send_mbox->data = MBOX_AREA(func_to_func->hwif); |
1190 | } |
1191 | |
1192 | static int alloc_mbox_wb_status(struct hinic_mbox_func_to_func *func_to_func) |
1193 | { |
1194 | struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox; |
1195 | struct hinic_hwdev *hwdev = func_to_func->hwdev; |
1196 | u32 addr_h, addr_l; |
1197 | |
1198 | send_mbox->wb_vaddr = dma_alloc_coherent(dev: &hwdev->hwif->pdev->dev, |
1199 | MBOX_WB_STATUS_LEN, |
1200 | dma_handle: &send_mbox->wb_paddr, |
1201 | GFP_KERNEL); |
1202 | if (!send_mbox->wb_vaddr) |
1203 | return -ENOMEM; |
1204 | |
1205 | send_mbox->wb_status = send_mbox->wb_vaddr; |
1206 | |
1207 | addr_h = upper_32_bits(send_mbox->wb_paddr); |
1208 | addr_l = lower_32_bits(send_mbox->wb_paddr); |
1209 | |
1210 | hinic_hwif_write_reg(hwif: hwdev->hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_H_OFF, |
1211 | val: addr_h); |
1212 | hinic_hwif_write_reg(hwif: hwdev->hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_L_OFF, |
1213 | val: addr_l); |
1214 | |
1215 | return 0; |
1216 | } |
1217 | |
1218 | static void free_mbox_wb_status(struct hinic_mbox_func_to_func *func_to_func) |
1219 | { |
1220 | struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox; |
1221 | struct hinic_hwdev *hwdev = func_to_func->hwdev; |
1222 | |
1223 | hinic_hwif_write_reg(hwif: hwdev->hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_H_OFF, |
1224 | val: 0); |
1225 | hinic_hwif_write_reg(hwif: hwdev->hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_L_OFF, |
1226 | val: 0); |
1227 | |
1228 | dma_free_coherent(dev: &hwdev->hwif->pdev->dev, MBOX_WB_STATUS_LEN, |
1229 | cpu_addr: send_mbox->wb_vaddr, |
1230 | dma_handle: send_mbox->wb_paddr); |
1231 | } |
1232 | |
1233 | bool hinic_mbox_check_cmd_valid(struct hinic_hwdev *hwdev, |
1234 | struct vf_cmd_check_handle *cmd_handle, |
1235 | u16 vf_id, u8 cmd, void *buf_in, |
1236 | u16 in_size, u8 size) |
1237 | { |
1238 | u16 src_idx = vf_id + hinic_glb_pf_vf_offset(hwif: hwdev->hwif); |
1239 | int i; |
1240 | |
1241 | for (i = 0; i < size; i++) { |
1242 | if (cmd == cmd_handle[i].cmd) { |
1243 | if (cmd_handle[i].check_cmd) |
1244 | return cmd_handle[i].check_cmd(hwdev, src_idx, |
1245 | buf_in, in_size); |
1246 | else |
1247 | return true; |
1248 | } |
1249 | } |
1250 | |
1251 | dev_err(&hwdev->hwif->pdev->dev, |
1252 | "PF Receive VF(%d) unsupported cmd(0x%x)\n" , |
1253 | vf_id + hinic_glb_pf_vf_offset(hwdev->hwif), cmd); |
1254 | |
1255 | return false; |
1256 | } |
1257 | |
1258 | static bool hinic_cmdq_check_vf_ctxt(struct hinic_hwdev *hwdev, |
1259 | struct hinic_cmdq_ctxt *cmdq_ctxt) |
1260 | { |
1261 | struct hinic_cmdq_ctxt_info *ctxt_info = &cmdq_ctxt->ctxt_info; |
1262 | u64 curr_pg_pfn, wq_block_pfn; |
1263 | |
1264 | if (cmdq_ctxt->ppf_idx != HINIC_HWIF_PPF_IDX(hwdev->hwif) || |
1265 | cmdq_ctxt->cmdq_type > HINIC_MAX_CMDQ_TYPES) |
1266 | return false; |
1267 | |
1268 | curr_pg_pfn = HINIC_CMDQ_CTXT_PAGE_INFO_GET |
1269 | (ctxt_info->curr_wqe_page_pfn, CURR_WQE_PAGE_PFN); |
1270 | wq_block_pfn = HINIC_CMDQ_CTXT_BLOCK_INFO_GET |
1271 | (ctxt_info->wq_block_pfn, WQ_BLOCK_PFN); |
1272 | /* VF must use 0-level CLA */ |
1273 | if (curr_pg_pfn != wq_block_pfn) |
1274 | return false; |
1275 | |
1276 | return true; |
1277 | } |
1278 | |
1279 | static bool check_cmdq_ctxt(struct hinic_hwdev *hwdev, u16 func_idx, |
1280 | void *buf_in, u16 in_size) |
1281 | { |
1282 | if (!hinic_mbox_check_func_id_8B(hwdev, func_idx, buf_in, in_size)) |
1283 | return false; |
1284 | |
1285 | return hinic_cmdq_check_vf_ctxt(hwdev, cmdq_ctxt: buf_in); |
1286 | } |
1287 | |
1288 | #define HW_CTX_QPS_VALID(hw_ctxt) \ |
1289 | ((hw_ctxt)->rq_depth >= HINIC_QUEUE_MIN_DEPTH && \ |
1290 | (hw_ctxt)->rq_depth <= HINIC_QUEUE_MAX_DEPTH && \ |
1291 | (hw_ctxt)->sq_depth >= HINIC_QUEUE_MIN_DEPTH && \ |
1292 | (hw_ctxt)->sq_depth <= HINIC_QUEUE_MAX_DEPTH && \ |
1293 | (hw_ctxt)->rx_buf_sz_idx <= HINIC_MAX_RX_BUFFER_SIZE) |
1294 | |
1295 | static bool hw_ctxt_qps_param_valid(struct hinic_cmd_hw_ioctxt *hw_ctxt) |
1296 | { |
1297 | if (HW_CTX_QPS_VALID(hw_ctxt)) |
1298 | return true; |
1299 | |
1300 | if (!hw_ctxt->rq_depth && !hw_ctxt->sq_depth && |
1301 | !hw_ctxt->rx_buf_sz_idx) |
1302 | return true; |
1303 | |
1304 | return false; |
1305 | } |
1306 | |
1307 | static bool check_hwctxt(struct hinic_hwdev *hwdev, u16 func_idx, |
1308 | void *buf_in, u16 in_size) |
1309 | { |
1310 | struct hinic_cmd_hw_ioctxt *hw_ctxt = buf_in; |
1311 | |
1312 | if (!hinic_mbox_check_func_id_8B(hwdev, func_idx, buf_in, in_size)) |
1313 | return false; |
1314 | |
1315 | if (hw_ctxt->ppf_idx != HINIC_HWIF_PPF_IDX(hwdev->hwif)) |
1316 | return false; |
1317 | |
1318 | if (hw_ctxt->set_cmdq_depth) { |
1319 | if (hw_ctxt->cmdq_depth >= HINIC_QUEUE_MIN_DEPTH && |
1320 | hw_ctxt->cmdq_depth <= HINIC_QUEUE_MAX_DEPTH) |
1321 | return true; |
1322 | |
1323 | return false; |
1324 | } |
1325 | |
1326 | return hw_ctxt_qps_param_valid(hw_ctxt); |
1327 | } |
1328 | |
1329 | static bool check_set_wq_page_size(struct hinic_hwdev *hwdev, u16 func_idx, |
1330 | void *buf_in, u16 in_size) |
1331 | { |
1332 | struct hinic_wq_page_size *page_size_info = buf_in; |
1333 | |
1334 | if (!hinic_mbox_check_func_id_8B(hwdev, func_idx, buf_in, in_size)) |
1335 | return false; |
1336 | |
1337 | if (page_size_info->ppf_idx != HINIC_HWIF_PPF_IDX(hwdev->hwif)) |
1338 | return false; |
1339 | |
1340 | if (((1U << page_size_info->page_size) * SZ_4K) != |
1341 | HINIC_DEFAULT_WQ_PAGE_SIZE) |
1342 | return false; |
1343 | |
1344 | return true; |
1345 | } |
1346 | |
1347 | static struct vf_cmd_check_handle hw_cmd_support_vf[] = { |
1348 | {HINIC_COMM_CMD_START_FLR, hinic_mbox_check_func_id_8B}, |
1349 | {HINIC_COMM_CMD_DMA_ATTR_SET, hinic_mbox_check_func_id_8B}, |
1350 | {HINIC_COMM_CMD_CMDQ_CTXT_SET, check_cmdq_ctxt}, |
1351 | {HINIC_COMM_CMD_CMDQ_CTXT_GET, check_cmdq_ctxt}, |
1352 | {HINIC_COMM_CMD_HWCTXT_SET, check_hwctxt}, |
1353 | {HINIC_COMM_CMD_HWCTXT_GET, check_hwctxt}, |
1354 | {HINIC_COMM_CMD_SQ_HI_CI_SET, hinic_mbox_check_func_id_8B}, |
1355 | {HINIC_COMM_CMD_RES_STATE_SET, hinic_mbox_check_func_id_8B}, |
1356 | {HINIC_COMM_CMD_IO_RES_CLEAR, hinic_mbox_check_func_id_8B}, |
1357 | {HINIC_COMM_CMD_CEQ_CTRL_REG_WR_BY_UP, hinic_mbox_check_func_id_8B}, |
1358 | {HINIC_COMM_CMD_MSI_CTRL_REG_WR_BY_UP, hinic_mbox_check_func_id_8B}, |
1359 | {HINIC_COMM_CMD_MSI_CTRL_REG_RD_BY_UP, hinic_mbox_check_func_id_8B}, |
1360 | {HINIC_COMM_CMD_L2NIC_RESET, hinic_mbox_check_func_id_8B}, |
1361 | {HINIC_COMM_CMD_PAGESIZE_SET, check_set_wq_page_size}, |
1362 | }; |
1363 | |
1364 | static int comm_pf_mbox_handler(void *handle, u16 vf_id, u8 cmd, void *buf_in, |
1365 | u16 in_size, void *buf_out, u16 *out_size) |
1366 | { |
1367 | u8 size = ARRAY_SIZE(hw_cmd_support_vf); |
1368 | struct hinic_hwdev *hwdev = handle; |
1369 | struct hinic_pfhwdev *pfhwdev; |
1370 | int err = 0; |
1371 | |
1372 | pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); |
1373 | |
1374 | if (!hinic_mbox_check_cmd_valid(hwdev: handle, cmd_handle: hw_cmd_support_vf, vf_id, cmd, |
1375 | buf_in, in_size, size)) { |
1376 | dev_err(&hwdev->hwif->pdev->dev, |
1377 | "PF Receive VF: %d common cmd: 0x%x or mbox len: 0x%x is invalid\n" , |
1378 | vf_id + hinic_glb_pf_vf_offset(hwdev->hwif), cmd, |
1379 | in_size); |
1380 | return HINIC_MBOX_VF_CMD_ERROR; |
1381 | } |
1382 | |
1383 | if (cmd == HINIC_COMM_CMD_START_FLR) { |
1384 | *out_size = 0; |
1385 | } else { |
1386 | err = hinic_msg_to_mgmt(pf_to_mgmt: &pfhwdev->pf_to_mgmt, mod: HINIC_MOD_COMM, |
1387 | cmd, buf_in, in_size, buf_out, out_size, |
1388 | sync: HINIC_MGMT_MSG_SYNC); |
1389 | if (err && err != HINIC_MBOX_PF_BUSY_ACTIVE_FW) |
1390 | dev_err(&hwdev->hwif->pdev->dev, |
1391 | "PF mbox common callback handler err: %d\n" , |
1392 | err); |
1393 | } |
1394 | |
1395 | return err; |
1396 | } |
1397 | |
1398 | int hinic_func_to_func_init(struct hinic_hwdev *hwdev) |
1399 | { |
1400 | struct hinic_mbox_func_to_func *func_to_func; |
1401 | struct hinic_pfhwdev *pfhwdev; |
1402 | int err; |
1403 | |
1404 | pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); |
1405 | func_to_func = kzalloc(size: sizeof(*func_to_func), GFP_KERNEL); |
1406 | if (!func_to_func) |
1407 | return -ENOMEM; |
1408 | |
1409 | hwdev->func_to_func = func_to_func; |
1410 | func_to_func->hwdev = hwdev; |
1411 | func_to_func->hwif = hwdev->hwif; |
1412 | sema_init(sem: &func_to_func->mbox_send_sem, val: 1); |
1413 | sema_init(sem: &func_to_func->msg_send_sem, val: 1); |
1414 | spin_lock_init(&func_to_func->mbox_lock); |
1415 | func_to_func->workq = create_singlethread_workqueue(HINIC_MBOX_WQ_NAME); |
1416 | if (!func_to_func->workq) { |
1417 | dev_err(&hwdev->hwif->pdev->dev, "Failed to initialize MBOX workqueue\n" ); |
1418 | err = -ENOMEM; |
1419 | goto err_create_mbox_workq; |
1420 | } |
1421 | |
1422 | err = alloc_mbox_info(hwdev, mbox_info: func_to_func->mbox_send); |
1423 | if (err) { |
1424 | dev_err(&hwdev->hwif->pdev->dev, "Failed to alloc mem for mbox_active\n" ); |
1425 | goto err_alloc_mbox_for_send; |
1426 | } |
1427 | |
1428 | err = alloc_mbox_info(hwdev, mbox_info: func_to_func->mbox_resp); |
1429 | if (err) { |
1430 | dev_err(&hwdev->hwif->pdev->dev, "Failed to alloc mem for mbox_passive\n" ); |
1431 | goto err_alloc_mbox_for_resp; |
1432 | } |
1433 | |
1434 | err = alloc_mbox_wb_status(func_to_func); |
1435 | if (err) { |
1436 | dev_err(&hwdev->hwif->pdev->dev, "Failed to alloc mbox write back status\n" ); |
1437 | goto err_alloc_wb_status; |
1438 | } |
1439 | |
1440 | prepare_send_mbox(func_to_func); |
1441 | |
1442 | hinic_aeq_register_hw_cb(aeqs: &hwdev->aeqs, event: HINIC_MBX_FROM_FUNC, |
1443 | handle: &pfhwdev->hwdev, hwe_handler: hinic_mbox_func_aeqe_handler); |
1444 | hinic_aeq_register_hw_cb(aeqs: &hwdev->aeqs, event: HINIC_MBX_SEND_RSLT, |
1445 | handle: &pfhwdev->hwdev, hwe_handler: hinic_mbox_self_aeqe_handler); |
1446 | |
1447 | if (!HINIC_IS_VF(hwdev->hwif)) |
1448 | hinic_register_pf_mbox_cb(hwdev, mod: HINIC_MOD_COMM, |
1449 | callback: comm_pf_mbox_handler); |
1450 | |
1451 | return 0; |
1452 | |
1453 | err_alloc_wb_status: |
1454 | free_mbox_info(mbox_info: func_to_func->mbox_resp); |
1455 | |
1456 | err_alloc_mbox_for_resp: |
1457 | free_mbox_info(mbox_info: func_to_func->mbox_send); |
1458 | |
1459 | err_alloc_mbox_for_send: |
1460 | destroy_workqueue(wq: func_to_func->workq); |
1461 | |
1462 | err_create_mbox_workq: |
1463 | kfree(objp: func_to_func); |
1464 | |
1465 | return err; |
1466 | } |
1467 | |
1468 | void hinic_func_to_func_free(struct hinic_hwdev *hwdev) |
1469 | { |
1470 | struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func; |
1471 | |
1472 | hinic_aeq_unregister_hw_cb(aeqs: &hwdev->aeqs, event: HINIC_MBX_FROM_FUNC); |
1473 | hinic_aeq_unregister_hw_cb(aeqs: &hwdev->aeqs, event: HINIC_MBX_SEND_RSLT); |
1474 | |
1475 | hinic_unregister_pf_mbox_cb(hwdev, mod: HINIC_MOD_COMM); |
1476 | /* destroy workqueue before free related mbox resources in case of |
1477 | * illegal resource access |
1478 | */ |
1479 | destroy_workqueue(wq: func_to_func->workq); |
1480 | |
1481 | free_mbox_wb_status(func_to_func); |
1482 | free_mbox_info(mbox_info: func_to_func->mbox_resp); |
1483 | free_mbox_info(mbox_info: func_to_func->mbox_send); |
1484 | |
1485 | kfree(objp: func_to_func); |
1486 | } |
1487 | |
1488 | int hinic_vf_mbox_random_id_init(struct hinic_hwdev *hwdev) |
1489 | { |
1490 | u16 vf_offset; |
1491 | u8 vf_in_pf; |
1492 | int err = 0; |
1493 | |
1494 | if (HINIC_IS_VF(hwdev->hwif)) |
1495 | return 0; |
1496 | |
1497 | vf_offset = hinic_glb_pf_vf_offset(hwif: hwdev->hwif); |
1498 | |
1499 | for (vf_in_pf = 1; vf_in_pf <= hwdev->nic_cap.max_vf; vf_in_pf++) { |
1500 | err = set_vf_mbox_random_id(hwdev, func_id: vf_offset + vf_in_pf); |
1501 | if (err) |
1502 | break; |
1503 | } |
1504 | |
1505 | if (err == HINIC_MGMT_CMD_UNSUPPORTED) { |
1506 | hwdev->func_to_func->support_vf_random = false; |
1507 | err = 0; |
1508 | dev_warn(&hwdev->hwif->pdev->dev, "Mgmt is unsupported to set VF%d random id\n" , |
1509 | vf_in_pf - 1); |
1510 | } else if (!err) { |
1511 | hwdev->func_to_func->support_vf_random = true; |
1512 | } |
1513 | |
1514 | return err; |
1515 | } |
1516 | |