1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) Meta Platforms, Inc. and affiliates. */
3
4 #include <linux/bitfield.h>
5 #include <linux/etherdevice.h>
6 #include <linux/delay.h>
7 #include <linux/dev_printk.h>
8 #include <linux/dma-mapping.h>
9 #include <linux/gfp.h>
10 #include <linux/types.h>
11
12 #include "fbnic.h"
13 #include "fbnic_tlv.h"
14
__fbnic_mbx_wr_desc(struct fbnic_dev * fbd,int mbx_idx,int desc_idx,u64 desc)15 static void __fbnic_mbx_wr_desc(struct fbnic_dev *fbd, int mbx_idx,
16 int desc_idx, u64 desc)
17 {
18 u32 desc_offset = FBNIC_IPC_MBX(mbx_idx, desc_idx);
19
20 /* Write the upper 32b and then the lower 32b. Doing this the
21 * FW can then read lower, upper, lower to verify that the state
22 * of the descriptor wasn't changed mid-transaction.
23 */
24 fw_wr32(fbd, desc_offset + 1, upper_32_bits(desc));
25 fw_wrfl(fbd);
26 fw_wr32(fbd, desc_offset, lower_32_bits(desc));
27 }
28
__fbnic_mbx_invalidate_desc(struct fbnic_dev * fbd,int mbx_idx,int desc_idx,u32 desc)29 static void __fbnic_mbx_invalidate_desc(struct fbnic_dev *fbd, int mbx_idx,
30 int desc_idx, u32 desc)
31 {
32 u32 desc_offset = FBNIC_IPC_MBX(mbx_idx, desc_idx);
33
34 /* For initialization we write the lower 32b of the descriptor first.
35 * This way we can set the state to mark it invalid before we clear the
36 * upper 32b.
37 */
38 fw_wr32(fbd, desc_offset, desc);
39 fw_wrfl(fbd);
40 fw_wr32(fbd, desc_offset + 1, 0);
41 }
42
__fbnic_mbx_rd_desc(struct fbnic_dev * fbd,int mbx_idx,int desc_idx)43 u64 __fbnic_mbx_rd_desc(struct fbnic_dev *fbd, int mbx_idx, int desc_idx)
44 {
45 u32 desc_offset = FBNIC_IPC_MBX(mbx_idx, desc_idx);
46 u64 desc;
47
48 desc = fw_rd32(fbd, desc_offset);
49 desc |= (u64)fw_rd32(fbd, desc_offset + 1) << 32;
50
51 return desc;
52 }
53
fbnic_mbx_reset_desc_ring(struct fbnic_dev * fbd,int mbx_idx)54 static void fbnic_mbx_reset_desc_ring(struct fbnic_dev *fbd, int mbx_idx)
55 {
56 int desc_idx;
57
58 /* Disable DMA transactions from the device,
59 * and flush any transactions triggered during cleaning
60 */
61 switch (mbx_idx) {
62 case FBNIC_IPC_MBX_RX_IDX:
63 /* Clearing BME blocks the device from writing to the host
64 * but leaves the requests parked in the write pipeline. The
65 * write path only clears outstanding requests when both FLUSH
66 * and FLUSH_MODE are set; FLUSH_MODE lets them drain without
67 * landing on the host.
68 */
69 wr32(fbd, FBNIC_PUL_OB_TLP_HDR_AW_CFG,
70 FBNIC_PUL_OB_TLP_HDR_AW_CFG_FLUSH |
71 FBNIC_PUL_OB_TLP_HDR_AW_CFG_FLUSH_MODE);
72 break;
73 case FBNIC_IPC_MBX_TX_IDX:
74 wr32(fbd, FBNIC_PUL_OB_TLP_HDR_AR_CFG,
75 FBNIC_PUL_OB_TLP_HDR_AR_CFG_FLUSH);
76 break;
77 }
78
79 wrfl(fbd);
80
81 /* Initialize first descriptor to all 0s. Doing this gives us a
82 * solid stop for the firmware to hit when it is done looping
83 * through the ring.
84 */
85 __fbnic_mbx_invalidate_desc(fbd, mbx_idx, 0, 0);
86
87 /* We then fill the rest of the ring starting at the end and moving
88 * back toward descriptor 0 with skip descriptors that have no
89 * length nor address, and tell the firmware that they can skip
90 * them and just move past them to the one we initialized to 0.
91 */
92 for (desc_idx = FBNIC_IPC_MBX_DESC_LEN; --desc_idx;)
93 __fbnic_mbx_invalidate_desc(fbd, mbx_idx, desc_idx,
94 FBNIC_IPC_MBX_DESC_FW_CMPL |
95 FBNIC_IPC_MBX_DESC_HOST_CMPL);
96 }
97
fbnic_mbx_init(struct fbnic_dev * fbd)98 void fbnic_mbx_init(struct fbnic_dev *fbd)
99 {
100 int i;
101
102 /* Initialize lock to protect Tx ring */
103 spin_lock_init(&fbd->fw_tx_lock);
104
105 /* Reset FW Capabilities */
106 memset(&fbd->fw_cap, 0, sizeof(fbd->fw_cap));
107
108 /* Reinitialize mailbox memory */
109 for (i = 0; i < FBNIC_IPC_MBX_INDICES; i++)
110 memset(&fbd->mbx[i], 0, sizeof(struct fbnic_fw_mbx));
111
112 /* Do not auto-clear the FW mailbox interrupt, let SW clear it */
113 wr32(fbd, FBNIC_INTR_SW_AC_MODE(0), ~(1u << FBNIC_FW_MSIX_ENTRY));
114
115 /* Clear any stale causes in vector 0 as that is used for doorbell */
116 wr32(fbd, FBNIC_INTR_CLEAR(0), 1u << FBNIC_FW_MSIX_ENTRY);
117
118 for (i = 0; i < FBNIC_IPC_MBX_INDICES; i++)
119 fbnic_mbx_reset_desc_ring(fbd, i);
120 }
121
fbnic_mbx_map_msg(struct fbnic_dev * fbd,int mbx_idx,struct fbnic_tlv_msg * msg,u16 length,u8 eom)122 static int fbnic_mbx_map_msg(struct fbnic_dev *fbd, int mbx_idx,
123 struct fbnic_tlv_msg *msg, u16 length, u8 eom)
124 {
125 struct fbnic_fw_mbx *mbx = &fbd->mbx[mbx_idx];
126 u8 tail = mbx->tail;
127 dma_addr_t addr;
128 int direction;
129
130 if (!mbx->ready || !fbnic_fw_present(fbd))
131 return -ENODEV;
132
133 direction = (mbx_idx == FBNIC_IPC_MBX_RX_IDX) ? DMA_FROM_DEVICE :
134 DMA_TO_DEVICE;
135
136 if (mbx->head == ((tail + 1) % FBNIC_IPC_MBX_DESC_LEN))
137 return -EBUSY;
138
139 addr = dma_map_single(fbd->dev, msg, PAGE_SIZE, direction);
140 if (dma_mapping_error(fbd->dev, addr))
141 return -ENOSPC;
142
143 mbx->buf_info[tail].msg = msg;
144 mbx->buf_info[tail].addr = addr;
145
146 mbx->tail = (tail + 1) % FBNIC_IPC_MBX_DESC_LEN;
147
148 fw_wr32(fbd, FBNIC_IPC_MBX(mbx_idx, mbx->tail), 0);
149
150 __fbnic_mbx_wr_desc(fbd, mbx_idx, tail,
151 FIELD_PREP(FBNIC_IPC_MBX_DESC_LEN_MASK, length) |
152 (addr & FBNIC_IPC_MBX_DESC_ADDR_MASK) |
153 (eom ? FBNIC_IPC_MBX_DESC_EOM : 0) |
154 FBNIC_IPC_MBX_DESC_HOST_CMPL);
155
156 return 0;
157 }
158
fbnic_mbx_unmap_and_free_msg(struct fbnic_dev * fbd,int mbx_idx,int desc_idx)159 static void fbnic_mbx_unmap_and_free_msg(struct fbnic_dev *fbd, int mbx_idx,
160 int desc_idx)
161 {
162 struct fbnic_fw_mbx *mbx = &fbd->mbx[mbx_idx];
163 int direction;
164
165 if (!mbx->buf_info[desc_idx].msg)
166 return;
167
168 direction = (mbx_idx == FBNIC_IPC_MBX_RX_IDX) ? DMA_FROM_DEVICE :
169 DMA_TO_DEVICE;
170 dma_unmap_single(fbd->dev, mbx->buf_info[desc_idx].addr,
171 PAGE_SIZE, direction);
172
173 free_page((unsigned long)mbx->buf_info[desc_idx].msg);
174 mbx->buf_info[desc_idx].msg = NULL;
175 }
176
fbnic_mbx_clean_desc_ring(struct fbnic_dev * fbd,int mbx_idx)177 static void fbnic_mbx_clean_desc_ring(struct fbnic_dev *fbd, int mbx_idx)
178 {
179 int i;
180
181 fbnic_mbx_reset_desc_ring(fbd, mbx_idx);
182
183 for (i = FBNIC_IPC_MBX_DESC_LEN; i--;)
184 fbnic_mbx_unmap_and_free_msg(fbd, mbx_idx, i);
185 }
186
fbnic_mbx_clean(struct fbnic_dev * fbd)187 void fbnic_mbx_clean(struct fbnic_dev *fbd)
188 {
189 int i;
190
191 for (i = 0; i < FBNIC_IPC_MBX_INDICES; i++)
192 fbnic_mbx_clean_desc_ring(fbd, i);
193 }
194
195 #define FBNIC_MBX_MAX_PAGE_SIZE FIELD_MAX(FBNIC_IPC_MBX_DESC_LEN_MASK)
196 #define FBNIC_RX_PAGE_SIZE min_t(int, PAGE_SIZE, FBNIC_MBX_MAX_PAGE_SIZE)
197
fbnic_mbx_alloc_rx_msgs(struct fbnic_dev * fbd)198 static int fbnic_mbx_alloc_rx_msgs(struct fbnic_dev *fbd)
199 {
200 struct fbnic_fw_mbx *rx_mbx = &fbd->mbx[FBNIC_IPC_MBX_RX_IDX];
201 u8 tail = rx_mbx->tail, head = rx_mbx->head, count;
202 int err = 0;
203
204 /* Do nothing if mailbox is not ready, or we already have pages on
205 * the ring that can be used by the firmware
206 */
207 if (!rx_mbx->ready)
208 return -ENODEV;
209
210 /* Fill all but 1 unused descriptors in the Rx queue. */
211 count = (head - tail - 1) & (FBNIC_IPC_MBX_DESC_LEN - 1);
212 while (!err && count--) {
213 struct fbnic_tlv_msg *msg;
214
215 msg = (struct fbnic_tlv_msg *)__get_free_page(GFP_KERNEL);
216 if (!msg) {
217 err = -ENOMEM;
218 break;
219 }
220
221 err = fbnic_mbx_map_msg(fbd, FBNIC_IPC_MBX_RX_IDX, msg,
222 FBNIC_RX_PAGE_SIZE, 0);
223 if (err)
224 free_page((unsigned long)msg);
225 }
226
227 return err;
228 }
229
fbnic_mbx_map_tlv_msg(struct fbnic_dev * fbd,struct fbnic_tlv_msg * msg)230 static int fbnic_mbx_map_tlv_msg(struct fbnic_dev *fbd,
231 struct fbnic_tlv_msg *msg)
232 {
233 unsigned long flags;
234 int err;
235
236 spin_lock_irqsave(&fbd->fw_tx_lock, flags);
237
238 err = fbnic_mbx_map_msg(fbd, FBNIC_IPC_MBX_TX_IDX, msg,
239 le16_to_cpu(msg->hdr.len) * sizeof(u32), 1);
240
241 spin_unlock_irqrestore(&fbd->fw_tx_lock, flags);
242
243 return err;
244 }
245
fbnic_mbx_set_cmpl_slot(struct fbnic_dev * fbd,struct fbnic_fw_completion * cmpl_data)246 static int fbnic_mbx_set_cmpl_slot(struct fbnic_dev *fbd,
247 struct fbnic_fw_completion *cmpl_data)
248 {
249 struct fbnic_fw_mbx *tx_mbx = &fbd->mbx[FBNIC_IPC_MBX_TX_IDX];
250 int free = -EXFULL;
251 int i;
252
253 if (!tx_mbx->ready)
254 return -ENODEV;
255
256 for (i = 0; i < FBNIC_MBX_CMPL_SLOTS; i++) {
257 if (!fbd->cmpl_data[i])
258 free = i;
259 else if (fbd->cmpl_data[i]->msg_type == cmpl_data->msg_type)
260 return -EEXIST;
261 }
262
263 if (free == -EXFULL)
264 return -EXFULL;
265
266 fbd->cmpl_data[free] = cmpl_data;
267
268 return 0;
269 }
270
fbnic_mbx_clear_cmpl_slot(struct fbnic_dev * fbd,struct fbnic_fw_completion * cmpl_data)271 static void fbnic_mbx_clear_cmpl_slot(struct fbnic_dev *fbd,
272 struct fbnic_fw_completion *cmpl_data)
273 {
274 int i;
275
276 for (i = 0; i < FBNIC_MBX_CMPL_SLOTS; i++) {
277 if (fbd->cmpl_data[i] == cmpl_data) {
278 fbd->cmpl_data[i] = NULL;
279 break;
280 }
281 }
282 }
283
fbnic_mbx_process_tx_msgs(struct fbnic_dev * fbd)284 static void fbnic_mbx_process_tx_msgs(struct fbnic_dev *fbd)
285 {
286 struct fbnic_fw_mbx *tx_mbx = &fbd->mbx[FBNIC_IPC_MBX_TX_IDX];
287 u8 head = tx_mbx->head;
288 u64 desc;
289
290 while (head != tx_mbx->tail) {
291 desc = __fbnic_mbx_rd_desc(fbd, FBNIC_IPC_MBX_TX_IDX, head);
292 if (!(desc & FBNIC_IPC_MBX_DESC_FW_CMPL))
293 break;
294
295 if (desc & FBNIC_IPC_MBX_DESC_FW_ERR) {
296 tx_mbx->resp_error++;
297 dev_warn_ratelimited(fbd->dev,
298 "FW completed a Tx mailbox request with an error\n");
299 }
300
301 fbnic_mbx_unmap_and_free_msg(fbd, FBNIC_IPC_MBX_TX_IDX, head);
302
303 head++;
304 head %= FBNIC_IPC_MBX_DESC_LEN;
305 }
306
307 /* Record head for next interrupt */
308 tx_mbx->head = head;
309 }
310
fbnic_mbx_set_cmpl(struct fbnic_dev * fbd,struct fbnic_fw_completion * cmpl_data)311 int fbnic_mbx_set_cmpl(struct fbnic_dev *fbd,
312 struct fbnic_fw_completion *cmpl_data)
313 {
314 unsigned long flags;
315 int err;
316
317 spin_lock_irqsave(&fbd->fw_tx_lock, flags);
318 err = fbnic_mbx_set_cmpl_slot(fbd, cmpl_data);
319 spin_unlock_irqrestore(&fbd->fw_tx_lock, flags);
320
321 return err;
322 }
323
fbnic_mbx_map_req_w_cmpl(struct fbnic_dev * fbd,struct fbnic_tlv_msg * msg,struct fbnic_fw_completion * cmpl_data)324 static int fbnic_mbx_map_req_w_cmpl(struct fbnic_dev *fbd,
325 struct fbnic_tlv_msg *msg,
326 struct fbnic_fw_completion *cmpl_data)
327 {
328 unsigned long flags;
329 int err;
330
331 spin_lock_irqsave(&fbd->fw_tx_lock, flags);
332 if (cmpl_data) {
333 err = fbnic_mbx_set_cmpl_slot(fbd, cmpl_data);
334 if (err)
335 goto unlock_mbx;
336 }
337
338 err = fbnic_mbx_map_msg(fbd, FBNIC_IPC_MBX_TX_IDX, msg,
339 le16_to_cpu(msg->hdr.len) * sizeof(u32), 1);
340
341 /* If we successfully reserved a completion and msg failed
342 * then clear completion data for next caller
343 */
344 if (err && cmpl_data)
345 fbnic_mbx_clear_cmpl_slot(fbd, cmpl_data);
346
347 unlock_mbx:
348 spin_unlock_irqrestore(&fbd->fw_tx_lock, flags);
349
350 return err;
351 }
352
fbnic_mbx_clear_cmpl(struct fbnic_dev * fbd,struct fbnic_fw_completion * fw_cmpl)353 void fbnic_mbx_clear_cmpl(struct fbnic_dev *fbd,
354 struct fbnic_fw_completion *fw_cmpl)
355 {
356 unsigned long flags;
357
358 spin_lock_irqsave(&fbd->fw_tx_lock, flags);
359 fbnic_mbx_clear_cmpl_slot(fbd, fw_cmpl);
360 spin_unlock_irqrestore(&fbd->fw_tx_lock, flags);
361 }
362
fbnic_fw_release_cmpl_data(struct kref * kref)363 static void fbnic_fw_release_cmpl_data(struct kref *kref)
364 {
365 struct fbnic_fw_completion *cmpl_data;
366
367 cmpl_data = container_of(kref, struct fbnic_fw_completion,
368 ref_count);
369 kfree(cmpl_data);
370 }
371
372 static struct fbnic_fw_completion *
fbnic_fw_get_cmpl_by_type(struct fbnic_dev * fbd,u32 msg_type)373 fbnic_fw_get_cmpl_by_type(struct fbnic_dev *fbd, u32 msg_type)
374 {
375 struct fbnic_fw_completion *cmpl_data = NULL;
376 unsigned long flags;
377 int i;
378
379 spin_lock_irqsave(&fbd->fw_tx_lock, flags);
380 for (i = 0; i < FBNIC_MBX_CMPL_SLOTS; i++) {
381 if (fbd->cmpl_data[i] &&
382 fbd->cmpl_data[i]->msg_type == msg_type) {
383 cmpl_data = fbd->cmpl_data[i];
384 kref_get(&cmpl_data->ref_count);
385 break;
386 }
387 }
388
389 spin_unlock_irqrestore(&fbd->fw_tx_lock, flags);
390
391 return cmpl_data;
392 }
393
394 /**
395 * fbnic_fw_xmit_test_msg - Create and transmit a test message to FW mailbox
396 * @fbd: FBNIC device structure
397 * @cmpl: fw completion struct
398 *
399 * Return: zero on success, negative value on failure
400 *
401 * Generates a single page mailbox test message and places it in the Tx
402 * mailbox queue. Expectation is that the FW will validate that the nested
403 * value matches the external values, and then will echo them back to us.
404 *
405 * Also sets a completion slot for use in the completion wait calls when
406 * the cmpl arg is non-NULL.
407 */
fbnic_fw_xmit_test_msg(struct fbnic_dev * fbd,struct fbnic_fw_completion * cmpl)408 int fbnic_fw_xmit_test_msg(struct fbnic_dev *fbd,
409 struct fbnic_fw_completion *cmpl)
410 {
411 struct fbnic_tlv_msg *test_msg;
412 int err;
413
414 test_msg = fbnic_tlv_test_create(fbd);
415 if (!test_msg)
416 return -ENOMEM;
417
418 err = fbnic_mbx_map_req_w_cmpl(fbd, test_msg, cmpl);
419 if (err)
420 free_page((unsigned long)test_msg);
421
422 return err;
423 }
424
425 /**
426 * fbnic_fw_xmit_simple_msg - Transmit a simple single TLV message w/o data
427 * @fbd: FBNIC device structure
428 * @msg_type: ENUM value indicating message type to send
429 *
430 * Return:
431 * One the following values:
432 * -EOPNOTSUPP: Is not ASIC so mailbox is not supported
433 * -ENODEV: Device I/O error
434 * -ENOMEM: Failed to allocate message
435 * -EBUSY: No space in mailbox
436 * -ENOSPC: DMA mapping failed
437 *
438 * This function sends a single TLV header indicating the host wants to take
439 * some action. However there are no other side effects which means that any
440 * response will need to be caught via a completion if this action is
441 * expected to kick off a resultant action.
442 */
fbnic_fw_xmit_simple_msg(struct fbnic_dev * fbd,u32 msg_type)443 static int fbnic_fw_xmit_simple_msg(struct fbnic_dev *fbd, u32 msg_type)
444 {
445 struct fbnic_tlv_msg *msg;
446 int err = 0;
447
448 if (!fbnic_fw_present(fbd))
449 return -ENODEV;
450
451 msg = fbnic_tlv_msg_alloc(msg_type);
452 if (!msg)
453 return -ENOMEM;
454
455 err = fbnic_mbx_map_tlv_msg(fbd, msg);
456 if (err)
457 free_page((unsigned long)msg);
458
459 return err;
460 }
461
fbnic_mbx_init_desc_ring(struct fbnic_dev * fbd,int mbx_idx)462 static int fbnic_mbx_init_desc_ring(struct fbnic_dev *fbd, int mbx_idx)
463 {
464 u8 tlp_attr = fbd->relaxed_ord ? FBNIC_TLP_ATTR_RO : 0;
465 struct fbnic_fw_mbx *mbx = &fbd->mbx[mbx_idx];
466
467 mbx->ready = true;
468
469 switch (mbx_idx) {
470 case FBNIC_IPC_MBX_RX_IDX:
471 /* Enable DMA writes from the device */
472 wr32(fbd, FBNIC_PUL_OB_TLP_HDR_AW_CFG,
473 FBNIC_PUL_OB_TLP_HDR_AW_CFG_BME |
474 FIELD_PREP(FBNIC_PUL_OB_TLP_HDR_AW_CFG_RDE_ATTR,
475 tlp_attr) |
476 FIELD_PREP(FBNIC_PUL_OB_TLP_HDR_AW_CFG_TQM_ATTR,
477 tlp_attr));
478
479 /* Make sure we have a page for the FW to write to */
480 return fbnic_mbx_alloc_rx_msgs(fbd);
481 case FBNIC_IPC_MBX_TX_IDX:
482 /* Enable DMA reads from the device */
483 wr32(fbd, FBNIC_PUL_OB_TLP_HDR_AR_CFG,
484 FBNIC_PUL_OB_TLP_HDR_AR_CFG_BME |
485 FIELD_PREP(FBNIC_PUL_OB_TLP_HDR_AR_CFG_TDE_ATTR,
486 tlp_attr) |
487 FIELD_PREP(FBNIC_PUL_OB_TLP_HDR_AR_CFG_RQM_ATTR,
488 tlp_attr) |
489 FIELD_PREP(FBNIC_PUL_OB_TLP_HDR_AR_CFG_TQM_ATTR,
490 tlp_attr));
491 break;
492 }
493
494 return 0;
495 }
496
fbnic_mbx_event(struct fbnic_dev * fbd)497 static bool fbnic_mbx_event(struct fbnic_dev *fbd)
498 {
499 /* We only need to do this on the first interrupt following reset.
500 * this primes the mailbox so that we will have cleared all the
501 * skip descriptors.
502 */
503 if (!(rd32(fbd, FBNIC_INTR_STATUS(0)) & (1u << FBNIC_FW_MSIX_ENTRY)))
504 return false;
505
506 wr32(fbd, FBNIC_INTR_CLEAR(0), 1u << FBNIC_FW_MSIX_ENTRY);
507
508 return true;
509 }
510
511 /**
512 * fbnic_fw_xmit_ownership_msg - Create and transmit a host ownership message
513 * to FW mailbox
514 *
515 * @fbd: FBNIC device structure
516 * @take_ownership: take/release the ownership
517 *
518 * Return: zero on success, negative value on failure
519 *
520 * Notifies the firmware that the driver either takes ownership of the NIC
521 * (when @take_ownership is true) or releases it.
522 */
fbnic_fw_xmit_ownership_msg(struct fbnic_dev * fbd,bool take_ownership)523 int fbnic_fw_xmit_ownership_msg(struct fbnic_dev *fbd, bool take_ownership)
524 {
525 unsigned long req_time = jiffies;
526 struct fbnic_tlv_msg *msg;
527 int err = 0;
528
529 if (!fbnic_fw_present(fbd))
530 return -ENODEV;
531
532 msg = fbnic_tlv_msg_alloc(FBNIC_TLV_MSG_ID_OWNERSHIP_REQ);
533 if (!msg)
534 return -ENOMEM;
535
536 if (take_ownership) {
537 err = fbnic_tlv_attr_put_flag(msg, FBNIC_FW_OWNERSHIP_FLAG);
538 if (err)
539 goto free_message;
540 }
541
542 /* Initialize heartbeat, set last response to 1 second in the past
543 * so that we will trigger a timeout if the firmware doesn't respond
544 */
545 fbd->last_heartbeat_response = req_time - HZ;
546 fbd->last_heartbeat_request = req_time;
547
548 /* Set prev_firmware_time to 0 to avoid triggering firmware crash
549 * detection until we receive the second uptime in a heartbeat resp.
550 */
551 fbd->prev_firmware_time = 0;
552
553 err = fbnic_mbx_map_tlv_msg(fbd, msg);
554 if (err)
555 goto free_message;
556
557 /* Set heartbeat detection based on if we are taking ownership */
558 fbd->fw_heartbeat_enabled = take_ownership;
559
560 return err;
561
562 free_message:
563 free_page((unsigned long)msg);
564 return err;
565 }
566
567 static const struct fbnic_tlv_index fbnic_fw_cap_resp_index[] = {
568 FBNIC_TLV_ATTR_U32(FBNIC_FW_CAP_RESP_VERSION),
569 FBNIC_TLV_ATTR_FLAG(FBNIC_FW_CAP_RESP_BMC_PRESENT),
570 FBNIC_TLV_ATTR_MAC_ADDR(FBNIC_FW_CAP_RESP_BMC_MAC_ADDR),
571 FBNIC_TLV_ATTR_ARRAY(FBNIC_FW_CAP_RESP_BMC_MAC_ARRAY),
572 FBNIC_TLV_ATTR_U32(FBNIC_FW_CAP_RESP_STORED_VERSION),
573 FBNIC_TLV_ATTR_U32(FBNIC_FW_CAP_RESP_ACTIVE_FW_SLOT),
574 FBNIC_TLV_ATTR_STRING(FBNIC_FW_CAP_RESP_VERSION_COMMIT_STR,
575 FBNIC_FW_CAP_RESP_COMMIT_MAX_SIZE),
576 FBNIC_TLV_ATTR_U32(FBNIC_FW_CAP_RESP_BMC_ALL_MULTI),
577 FBNIC_TLV_ATTR_U32(FBNIC_FW_CAP_RESP_FW_LINK_SPEED),
578 FBNIC_TLV_ATTR_U32(FBNIC_FW_CAP_RESP_FW_LINK_FEC),
579 FBNIC_TLV_ATTR_STRING(FBNIC_FW_CAP_RESP_STORED_COMMIT_STR,
580 FBNIC_FW_CAP_RESP_COMMIT_MAX_SIZE),
581 FBNIC_TLV_ATTR_U32(FBNIC_FW_CAP_RESP_CMRT_VERSION),
582 FBNIC_TLV_ATTR_U32(FBNIC_FW_CAP_RESP_STORED_CMRT_VERSION),
583 FBNIC_TLV_ATTR_STRING(FBNIC_FW_CAP_RESP_CMRT_COMMIT_STR,
584 FBNIC_FW_CAP_RESP_COMMIT_MAX_SIZE),
585 FBNIC_TLV_ATTR_STRING(FBNIC_FW_CAP_RESP_STORED_CMRT_COMMIT_STR,
586 FBNIC_FW_CAP_RESP_COMMIT_MAX_SIZE),
587 FBNIC_TLV_ATTR_U32(FBNIC_FW_CAP_RESP_UEFI_VERSION),
588 FBNIC_TLV_ATTR_STRING(FBNIC_FW_CAP_RESP_UEFI_COMMIT_STR,
589 FBNIC_FW_CAP_RESP_COMMIT_MAX_SIZE),
590 FBNIC_TLV_ATTR_U32(FBNIC_FW_CAP_RESP_ANTI_ROLLBACK_VERSION),
591 FBNIC_TLV_ATTR_LAST
592 };
593
fbnic_fw_parse_bmc_addrs(u8 bmc_mac_addr[][ETH_ALEN],struct fbnic_tlv_msg * attr,int len)594 static int fbnic_fw_parse_bmc_addrs(u8 bmc_mac_addr[][ETH_ALEN],
595 struct fbnic_tlv_msg *attr, int len)
596 {
597 int attr_len = le16_to_cpu(attr->hdr.len) / sizeof(u32) - 1;
598 struct fbnic_tlv_msg *mac_results[8];
599 int err, i = 0;
600
601 /* Make sure we have enough room to process all the MAC addresses */
602 if (len > 8)
603 return -ENOSPC;
604
605 /* Parse the array */
606 err = fbnic_tlv_attr_parse_array(&attr[1], attr_len, mac_results,
607 fbnic_fw_cap_resp_index,
608 FBNIC_FW_CAP_RESP_BMC_MAC_ADDR, len);
609 if (err)
610 return err;
611
612 /* Copy results into MAC addr array */
613 for (i = 0; i < len && mac_results[i]; i++)
614 fbnic_tlv_attr_addr_copy(bmc_mac_addr[i], mac_results[i]);
615
616 /* Zero remaining unused addresses */
617 while (i < len)
618 eth_zero_addr(bmc_mac_addr[i++]);
619
620 return 0;
621 }
622
fbnic_fw_parse_cap_resp(void * opaque,struct fbnic_tlv_msg ** results)623 static int fbnic_fw_parse_cap_resp(void *opaque, struct fbnic_tlv_msg **results)
624 {
625 u32 all_multi = 0, version = 0;
626 struct fbnic_dev *fbd = opaque;
627 bool bmc_present;
628 int err;
629
630 version = fta_get_uint(results, FBNIC_FW_CAP_RESP_VERSION);
631 fbd->fw_cap.running.mgmt.version = version;
632 if (!fbd->fw_cap.running.mgmt.version)
633 return -EINVAL;
634
635 if (fbd->fw_cap.running.mgmt.version < MIN_FW_VER_CODE) {
636 char required_ver[FBNIC_FW_VER_MAX_SIZE];
637 char running_ver[FBNIC_FW_VER_MAX_SIZE];
638
639 fbnic_mk_fw_ver_str(fbd->fw_cap.running.mgmt.version,
640 running_ver);
641 fbnic_mk_fw_ver_str(MIN_FW_VER_CODE, required_ver);
642 dev_err(fbd->dev, "Device firmware version(%s) is older than minimum required version(%s)\n",
643 running_ver, required_ver);
644 /* Disable TX mailbox to prevent card use until firmware is
645 * updated.
646 */
647 fbd->mbx[FBNIC_IPC_MBX_TX_IDX].ready = false;
648 return -EINVAL;
649 }
650
651 if (fta_get_str(results, FBNIC_FW_CAP_RESP_VERSION_COMMIT_STR,
652 fbd->fw_cap.running.mgmt.commit,
653 FBNIC_FW_CAP_RESP_COMMIT_MAX_SIZE) <= 0)
654 dev_warn(fbd->dev, "Firmware did not send mgmt commit!\n");
655
656 version = fta_get_uint(results, FBNIC_FW_CAP_RESP_STORED_VERSION);
657 fbd->fw_cap.stored.mgmt.version = version;
658 fta_get_str(results, FBNIC_FW_CAP_RESP_STORED_COMMIT_STR,
659 fbd->fw_cap.stored.mgmt.commit,
660 FBNIC_FW_CAP_RESP_COMMIT_MAX_SIZE);
661
662 version = fta_get_uint(results, FBNIC_FW_CAP_RESP_CMRT_VERSION);
663 fbd->fw_cap.running.bootloader.version = version;
664 fta_get_str(results, FBNIC_FW_CAP_RESP_CMRT_COMMIT_STR,
665 fbd->fw_cap.running.bootloader.commit,
666 FBNIC_FW_CAP_RESP_COMMIT_MAX_SIZE);
667
668 version = fta_get_uint(results, FBNIC_FW_CAP_RESP_STORED_CMRT_VERSION);
669 fbd->fw_cap.stored.bootloader.version = version;
670 fta_get_str(results, FBNIC_FW_CAP_RESP_STORED_CMRT_COMMIT_STR,
671 fbd->fw_cap.stored.bootloader.commit,
672 FBNIC_FW_CAP_RESP_COMMIT_MAX_SIZE);
673
674 version = fta_get_uint(results, FBNIC_FW_CAP_RESP_UEFI_VERSION);
675 fbd->fw_cap.stored.undi.version = version;
676 fta_get_str(results, FBNIC_FW_CAP_RESP_UEFI_COMMIT_STR,
677 fbd->fw_cap.stored.undi.commit,
678 FBNIC_FW_CAP_RESP_COMMIT_MAX_SIZE);
679
680 fbd->fw_cap.active_slot =
681 fta_get_uint(results, FBNIC_FW_CAP_RESP_ACTIVE_FW_SLOT);
682 fbd->fw_cap.link_speed =
683 fta_get_uint(results, FBNIC_FW_CAP_RESP_FW_LINK_SPEED);
684 fbd->fw_cap.link_fec =
685 fta_get_uint(results, FBNIC_FW_CAP_RESP_FW_LINK_FEC);
686
687 bmc_present = !!results[FBNIC_FW_CAP_RESP_BMC_PRESENT];
688 if (bmc_present) {
689 struct fbnic_tlv_msg *attr;
690
691 attr = results[FBNIC_FW_CAP_RESP_BMC_MAC_ARRAY];
692 if (!attr)
693 return -EINVAL;
694
695 err = fbnic_fw_parse_bmc_addrs(fbd->fw_cap.bmc_mac_addr,
696 attr, 4);
697 if (err)
698 return err;
699
700 all_multi =
701 fta_get_uint(results, FBNIC_FW_CAP_RESP_BMC_ALL_MULTI);
702 } else {
703 memset(fbd->fw_cap.bmc_mac_addr, 0,
704 sizeof(fbd->fw_cap.bmc_mac_addr));
705 }
706
707 fbd->fw_cap.bmc_present = bmc_present;
708
709 if (results[FBNIC_FW_CAP_RESP_BMC_ALL_MULTI] || !bmc_present)
710 fbd->fw_cap.all_multi = all_multi;
711
712 fbd->fw_cap.anti_rollback_version =
713 fta_get_uint(results, FBNIC_FW_CAP_RESP_ANTI_ROLLBACK_VERSION);
714
715 /* Always assume we need a BMC reinit */
716 fbd->fw_cap.need_bmc_tcam_reinit = true;
717
718 return 0;
719 }
720
721 static const struct fbnic_tlv_index fbnic_ownership_resp_index[] = {
722 FBNIC_TLV_ATTR_U64(FBNIC_FW_OWNERSHIP_TIME),
723 FBNIC_TLV_ATTR_LAST
724 };
725
fbnic_fw_parse_ownership_resp(void * opaque,struct fbnic_tlv_msg ** results)726 static int fbnic_fw_parse_ownership_resp(void *opaque,
727 struct fbnic_tlv_msg **results)
728 {
729 struct fbnic_dev *fbd = (struct fbnic_dev *)opaque;
730
731 /* Count the ownership response as a heartbeat reply */
732 fbd->last_heartbeat_response = jiffies;
733
734 /* Capture firmware time for logging and firmware crash check */
735 fbd->firmware_time = fta_get_uint(results, FBNIC_FW_OWNERSHIP_TIME);
736
737 return 0;
738 }
739
740 static const struct fbnic_tlv_index fbnic_heartbeat_resp_index[] = {
741 FBNIC_TLV_ATTR_U64(FBNIC_FW_HEARTBEAT_UPTIME),
742 FBNIC_TLV_ATTR_LAST
743 };
744
fbnic_fw_parse_heartbeat_resp(void * opaque,struct fbnic_tlv_msg ** results)745 static int fbnic_fw_parse_heartbeat_resp(void *opaque,
746 struct fbnic_tlv_msg **results)
747 {
748 struct fbnic_dev *fbd = (struct fbnic_dev *)opaque;
749
750 fbd->last_heartbeat_response = jiffies;
751
752 /* Capture firmware time for logging and firmware crash check */
753 fbd->firmware_time = fta_get_uint(results, FBNIC_FW_HEARTBEAT_UPTIME);
754
755 return 0;
756 }
757
fbnic_fw_xmit_heartbeat_message(struct fbnic_dev * fbd)758 static int fbnic_fw_xmit_heartbeat_message(struct fbnic_dev *fbd)
759 {
760 unsigned long req_time = jiffies;
761 struct fbnic_tlv_msg *msg;
762 int err = 0;
763
764 if (!fbnic_fw_present(fbd))
765 return -ENODEV;
766
767 msg = fbnic_tlv_msg_alloc(FBNIC_TLV_MSG_ID_HEARTBEAT_REQ);
768 if (!msg)
769 return -ENOMEM;
770
771 err = fbnic_mbx_map_tlv_msg(fbd, msg);
772 if (err)
773 goto free_message;
774
775 fbd->last_heartbeat_request = req_time;
776 fbd->prev_firmware_time = fbd->firmware_time;
777
778 return err;
779
780 free_message:
781 free_page((unsigned long)msg);
782 return err;
783 }
784
fbnic_fw_heartbeat_current(struct fbnic_dev * fbd)785 static bool fbnic_fw_heartbeat_current(struct fbnic_dev *fbd)
786 {
787 unsigned long last_response = fbd->last_heartbeat_response;
788 unsigned long last_request = fbd->last_heartbeat_request;
789
790 return !time_before(last_response, last_request);
791 }
792
fbnic_fw_init_heartbeat(struct fbnic_dev * fbd,bool poll)793 int fbnic_fw_init_heartbeat(struct fbnic_dev *fbd, bool poll)
794 {
795 int err = -ETIMEDOUT;
796 int attempts = 50;
797
798 if (!fbnic_fw_present(fbd))
799 return -ENODEV;
800
801 while (attempts--) {
802 msleep(200);
803 if (poll)
804 fbnic_mbx_poll(fbd);
805
806 if (!fbnic_fw_heartbeat_current(fbd))
807 continue;
808
809 /* Place new message on mailbox to elicit a response */
810 err = fbnic_fw_xmit_heartbeat_message(fbd);
811 if (err)
812 dev_warn(fbd->dev,
813 "Failed to send heartbeat message: %d\n",
814 err);
815 break;
816 }
817
818 return err;
819 }
820
fbnic_fw_check_heartbeat(struct fbnic_dev * fbd)821 void fbnic_fw_check_heartbeat(struct fbnic_dev *fbd)
822 {
823 unsigned long last_request = fbd->last_heartbeat_request;
824 int err;
825
826 /* Do not check heartbeat or send another request until current
827 * period has expired. Otherwise we might start spamming requests.
828 */
829 if (time_is_after_jiffies(last_request + FW_HEARTBEAT_PERIOD))
830 return;
831
832 /* We already reported no mailbox. Wait for it to come back */
833 if (!fbd->fw_heartbeat_enabled)
834 return;
835
836 /* Was the last heartbeat response long time ago? */
837 if (!fbnic_fw_heartbeat_current(fbd) ||
838 fbd->firmware_time < fbd->prev_firmware_time) {
839 dev_warn(fbd->dev,
840 "Firmware did not respond to heartbeat message\n");
841 fbd->fw_heartbeat_enabled = false;
842 }
843
844 /* Place new message on mailbox to elicit a response */
845 err = fbnic_fw_xmit_heartbeat_message(fbd);
846 if (err)
847 dev_warn(fbd->dev, "Failed to send heartbeat message\n");
848 }
849
850 /**
851 * fbnic_fw_xmit_coredump_info_msg - Create and transmit a coredump info message
852 * @fbd: FBNIC device structure
853 * @cmpl_data: Structure to store info in
854 * @force: Force coredump event if one hasn't already occurred
855 *
856 * Return: zero on success, negative errno on failure
857 *
858 * Asks the FW for info related to coredump. If a coredump doesn't exist it
859 * can optionally force one if force is true.
860 */
fbnic_fw_xmit_coredump_info_msg(struct fbnic_dev * fbd,struct fbnic_fw_completion * cmpl_data,bool force)861 int fbnic_fw_xmit_coredump_info_msg(struct fbnic_dev *fbd,
862 struct fbnic_fw_completion *cmpl_data,
863 bool force)
864 {
865 struct fbnic_tlv_msg *msg;
866 int err = 0;
867
868 msg = fbnic_tlv_msg_alloc(FBNIC_TLV_MSG_ID_COREDUMP_GET_INFO_REQ);
869 if (!msg)
870 return -ENOMEM;
871
872 if (force) {
873 err = fbnic_tlv_attr_put_flag(msg, FBNIC_FW_COREDUMP_REQ_INFO_CREATE);
874 if (err)
875 goto free_msg;
876 }
877
878 err = fbnic_mbx_map_req_w_cmpl(fbd, msg, cmpl_data);
879 if (err)
880 goto free_msg;
881
882 return 0;
883
884 free_msg:
885 free_page((unsigned long)msg);
886 return err;
887 }
888
889 static const struct fbnic_tlv_index fbnic_coredump_info_resp_index[] = {
890 FBNIC_TLV_ATTR_FLAG(FBNIC_FW_COREDUMP_INFO_AVAILABLE),
891 FBNIC_TLV_ATTR_U32(FBNIC_FW_COREDUMP_INFO_SIZE),
892 FBNIC_TLV_ATTR_S32(FBNIC_FW_COREDUMP_INFO_ERROR),
893 FBNIC_TLV_ATTR_LAST
894 };
895
896 static int
fbnic_fw_parse_coredump_info_resp(void * opaque,struct fbnic_tlv_msg ** results)897 fbnic_fw_parse_coredump_info_resp(void *opaque, struct fbnic_tlv_msg **results)
898 {
899 struct fbnic_fw_completion *cmpl_data;
900 struct fbnic_dev *fbd = opaque;
901 u32 msg_type;
902 s32 err;
903
904 /* Verify we have a completion pointer to provide with data */
905 msg_type = FBNIC_TLV_MSG_ID_COREDUMP_GET_INFO_RESP;
906 cmpl_data = fbnic_fw_get_cmpl_by_type(fbd, msg_type);
907 if (!cmpl_data)
908 return -ENOSPC;
909
910 err = fta_get_sint(results, FBNIC_FW_COREDUMP_INFO_ERROR);
911 if (err)
912 goto msg_err;
913
914 if (!results[FBNIC_FW_COREDUMP_INFO_AVAILABLE]) {
915 err = -ENOENT;
916 goto msg_err;
917 }
918
919 cmpl_data->u.coredump_info.size =
920 fta_get_uint(results, FBNIC_FW_COREDUMP_INFO_SIZE);
921
922 msg_err:
923 cmpl_data->result = err;
924 complete(&cmpl_data->done);
925 fbnic_fw_put_cmpl(cmpl_data);
926
927 return err;
928 }
929
930 /**
931 * fbnic_fw_xmit_coredump_read_msg - Create and transmit a coredump read request
932 * @fbd: FBNIC device structure
933 * @cmpl_data: Completion struct to store coredump
934 * @offset: Offset into coredump requested
935 * @length: Length of section of coredump to fetch
936 *
937 * Return: zero on success, negative errno on failure
938 *
939 * Asks the firmware to provide a section of the coredump back in a message.
940 * The response will have an offset and size matching the values provided.
941 */
fbnic_fw_xmit_coredump_read_msg(struct fbnic_dev * fbd,struct fbnic_fw_completion * cmpl_data,u32 offset,u32 length)942 int fbnic_fw_xmit_coredump_read_msg(struct fbnic_dev *fbd,
943 struct fbnic_fw_completion *cmpl_data,
944 u32 offset, u32 length)
945 {
946 struct fbnic_tlv_msg *msg;
947 int err = 0;
948
949 msg = fbnic_tlv_msg_alloc(FBNIC_TLV_MSG_ID_COREDUMP_READ_REQ);
950 if (!msg)
951 return -ENOMEM;
952
953 if (offset) {
954 err = fbnic_tlv_attr_put_int(msg, FBNIC_FW_COREDUMP_READ_OFFSET,
955 offset);
956 if (err)
957 goto free_message;
958 }
959
960 if (length) {
961 err = fbnic_tlv_attr_put_int(msg, FBNIC_FW_COREDUMP_READ_LENGTH,
962 length);
963 if (err)
964 goto free_message;
965 }
966
967 err = fbnic_mbx_map_req_w_cmpl(fbd, msg, cmpl_data);
968 if (err)
969 goto free_message;
970
971 return 0;
972
973 free_message:
974 free_page((unsigned long)msg);
975 return err;
976 }
977
978 static const struct fbnic_tlv_index fbnic_coredump_resp_index[] = {
979 FBNIC_TLV_ATTR_U32(FBNIC_FW_COREDUMP_READ_OFFSET),
980 FBNIC_TLV_ATTR_U32(FBNIC_FW_COREDUMP_READ_LENGTH),
981 FBNIC_TLV_ATTR_RAW_DATA(FBNIC_FW_COREDUMP_READ_DATA),
982 FBNIC_TLV_ATTR_S32(FBNIC_FW_COREDUMP_READ_ERROR),
983 FBNIC_TLV_ATTR_LAST
984 };
985
fbnic_fw_parse_coredump_resp(void * opaque,struct fbnic_tlv_msg ** results)986 static int fbnic_fw_parse_coredump_resp(void *opaque,
987 struct fbnic_tlv_msg **results)
988 {
989 struct fbnic_fw_completion *cmpl_data;
990 u32 index, last_offset, last_length;
991 struct fbnic_dev *fbd = opaque;
992 struct fbnic_tlv_msg *data_hdr;
993 u32 length, offset;
994 u32 msg_type;
995 s32 err;
996
997 /* Verify we have a completion pointer to provide with data */
998 msg_type = FBNIC_TLV_MSG_ID_COREDUMP_READ_RESP;
999 cmpl_data = fbnic_fw_get_cmpl_by_type(fbd, msg_type);
1000 if (!cmpl_data)
1001 return -ENOSPC;
1002
1003 err = fta_get_sint(results, FBNIC_FW_COREDUMP_READ_ERROR);
1004 if (err)
1005 goto msg_err;
1006
1007 data_hdr = results[FBNIC_FW_COREDUMP_READ_DATA];
1008 if (!data_hdr) {
1009 err = -ENODATA;
1010 goto msg_err;
1011 }
1012
1013 offset = fta_get_uint(results, FBNIC_FW_COREDUMP_READ_OFFSET);
1014 length = fta_get_uint(results, FBNIC_FW_COREDUMP_READ_LENGTH);
1015
1016 if (length > le16_to_cpu(data_hdr->hdr.len) - sizeof(u32)) {
1017 dev_err(fbd->dev, "length greater than size of message\n");
1018 err = -EINVAL;
1019 goto msg_err;
1020 }
1021
1022 /* Only the last offset can have a length != stride */
1023 last_length =
1024 (cmpl_data->u.coredump.size % cmpl_data->u.coredump.stride) ? :
1025 cmpl_data->u.coredump.stride;
1026 last_offset = cmpl_data->u.coredump.size - last_length;
1027
1028 /* Verify offset and length */
1029 if (offset % cmpl_data->u.coredump.stride || offset > last_offset) {
1030 dev_err(fbd->dev, "offset %d out of range\n", offset);
1031 err = -EINVAL;
1032 } else if (length != ((offset == last_offset) ?
1033 last_length : cmpl_data->u.coredump.stride)) {
1034 dev_err(fbd->dev, "length %d out of range for offset %d\n",
1035 length, offset);
1036 err = -EINVAL;
1037 }
1038 if (err)
1039 goto msg_err;
1040
1041 /* If data pointer is NULL it is already filled, just skip the copy */
1042 index = offset / cmpl_data->u.coredump.stride;
1043 if (!cmpl_data->u.coredump.data[index])
1044 goto msg_err;
1045
1046 /* Copy data and mark index filled by setting pointer to NULL */
1047 memcpy(cmpl_data->u.coredump.data[index],
1048 fbnic_tlv_attr_get_value_ptr(data_hdr), length);
1049 cmpl_data->u.coredump.data[index] = NULL;
1050
1051 msg_err:
1052 cmpl_data->result = err;
1053 complete(&cmpl_data->done);
1054 fbnic_fw_put_cmpl(cmpl_data);
1055
1056 return err;
1057 }
1058
fbnic_fw_xmit_fw_start_upgrade(struct fbnic_dev * fbd,struct fbnic_fw_completion * cmpl_data,unsigned int id,unsigned int len)1059 int fbnic_fw_xmit_fw_start_upgrade(struct fbnic_dev *fbd,
1060 struct fbnic_fw_completion *cmpl_data,
1061 unsigned int id, unsigned int len)
1062 {
1063 struct fbnic_tlv_msg *msg;
1064 int err;
1065
1066 if (!fbnic_fw_present(fbd))
1067 return -ENODEV;
1068
1069 if (!len)
1070 return -EINVAL;
1071
1072 msg = fbnic_tlv_msg_alloc(FBNIC_TLV_MSG_ID_FW_START_UPGRADE_REQ);
1073 if (!msg)
1074 return -ENOMEM;
1075
1076 err = fbnic_tlv_attr_put_int(msg, FBNIC_FW_START_UPGRADE_SECTION, id);
1077 if (err)
1078 goto free_message;
1079
1080 err = fbnic_tlv_attr_put_int(msg, FBNIC_FW_START_UPGRADE_IMAGE_LENGTH,
1081 len);
1082 if (err)
1083 goto free_message;
1084
1085 err = fbnic_mbx_map_req_w_cmpl(fbd, msg, cmpl_data);
1086 if (err)
1087 goto free_message;
1088
1089 return 0;
1090
1091 free_message:
1092 free_page((unsigned long)msg);
1093 return err;
1094 }
1095
1096 static const struct fbnic_tlv_index fbnic_fw_start_upgrade_resp_index[] = {
1097 FBNIC_TLV_ATTR_S32(FBNIC_FW_START_UPGRADE_ERROR),
1098 FBNIC_TLV_ATTR_LAST
1099 };
1100
fbnic_fw_parse_fw_start_upgrade_resp(void * opaque,struct fbnic_tlv_msg ** results)1101 static int fbnic_fw_parse_fw_start_upgrade_resp(void *opaque,
1102 struct fbnic_tlv_msg **results)
1103 {
1104 struct fbnic_fw_completion *cmpl_data;
1105 struct fbnic_dev *fbd = opaque;
1106 u32 msg_type;
1107 s32 err;
1108
1109 /* Verify we have a completion pointer */
1110 msg_type = FBNIC_TLV_MSG_ID_FW_START_UPGRADE_REQ;
1111 cmpl_data = fbnic_fw_get_cmpl_by_type(fbd, msg_type);
1112 if (!cmpl_data)
1113 return -ENOSPC;
1114
1115 /* Check for errors */
1116 err = fta_get_sint(results, FBNIC_FW_START_UPGRADE_ERROR);
1117
1118 cmpl_data->result = err;
1119 complete(&cmpl_data->done);
1120 fbnic_fw_put_cmpl(cmpl_data);
1121
1122 return 0;
1123 }
1124
fbnic_fw_xmit_fw_write_chunk(struct fbnic_dev * fbd,const u8 * data,u32 offset,u16 length,int cancel_error)1125 int fbnic_fw_xmit_fw_write_chunk(struct fbnic_dev *fbd,
1126 const u8 *data, u32 offset, u16 length,
1127 int cancel_error)
1128 {
1129 struct fbnic_tlv_msg *msg;
1130 int err;
1131
1132 msg = fbnic_tlv_msg_alloc(FBNIC_TLV_MSG_ID_FW_WRITE_CHUNK_RESP);
1133 if (!msg)
1134 return -ENOMEM;
1135
1136 /* Report error to FW to cancel upgrade */
1137 if (cancel_error) {
1138 err = fbnic_tlv_attr_put_int(msg, FBNIC_FW_WRITE_CHUNK_ERROR,
1139 cancel_error);
1140 if (err)
1141 goto free_message;
1142 }
1143
1144 if (data) {
1145 err = fbnic_tlv_attr_put_int(msg, FBNIC_FW_WRITE_CHUNK_OFFSET,
1146 offset);
1147 if (err)
1148 goto free_message;
1149
1150 err = fbnic_tlv_attr_put_int(msg, FBNIC_FW_WRITE_CHUNK_LENGTH,
1151 length);
1152 if (err)
1153 goto free_message;
1154
1155 err = fbnic_tlv_attr_put_value(msg, FBNIC_FW_WRITE_CHUNK_DATA,
1156 data + offset, length);
1157 if (err)
1158 goto free_message;
1159 }
1160
1161 err = fbnic_mbx_map_tlv_msg(fbd, msg);
1162 if (err)
1163 goto free_message;
1164
1165 return 0;
1166
1167 free_message:
1168 free_page((unsigned long)msg);
1169 return err;
1170 }
1171
1172 static const struct fbnic_tlv_index fbnic_fw_write_chunk_req_index[] = {
1173 FBNIC_TLV_ATTR_U32(FBNIC_FW_WRITE_CHUNK_OFFSET),
1174 FBNIC_TLV_ATTR_U32(FBNIC_FW_WRITE_CHUNK_LENGTH),
1175 FBNIC_TLV_ATTR_LAST
1176 };
1177
fbnic_fw_parse_fw_write_chunk_req(void * opaque,struct fbnic_tlv_msg ** results)1178 static int fbnic_fw_parse_fw_write_chunk_req(void *opaque,
1179 struct fbnic_tlv_msg **results)
1180 {
1181 struct fbnic_fw_completion *cmpl_data;
1182 struct fbnic_dev *fbd = opaque;
1183 u32 msg_type;
1184 u32 offset;
1185 u32 length;
1186
1187 /* Verify we have a completion pointer */
1188 msg_type = FBNIC_TLV_MSG_ID_FW_WRITE_CHUNK_REQ;
1189 cmpl_data = fbnic_fw_get_cmpl_by_type(fbd, msg_type);
1190 if (!cmpl_data)
1191 return -ENOSPC;
1192
1193 /* Pull length/offset pair and mark it as complete */
1194 offset = fta_get_uint(results, FBNIC_FW_WRITE_CHUNK_OFFSET);
1195 length = fta_get_uint(results, FBNIC_FW_WRITE_CHUNK_LENGTH);
1196 cmpl_data->u.fw_update.offset = offset;
1197 cmpl_data->u.fw_update.length = length;
1198
1199 complete(&cmpl_data->done);
1200 fbnic_fw_put_cmpl(cmpl_data);
1201
1202 return 0;
1203 }
1204
1205 static const struct fbnic_tlv_index fbnic_fw_finish_upgrade_req_index[] = {
1206 FBNIC_TLV_ATTR_S32(FBNIC_FW_FINISH_UPGRADE_ERROR),
1207 FBNIC_TLV_ATTR_LAST
1208 };
1209
fbnic_fw_parse_fw_finish_upgrade_req(void * opaque,struct fbnic_tlv_msg ** results)1210 static int fbnic_fw_parse_fw_finish_upgrade_req(void *opaque,
1211 struct fbnic_tlv_msg **results)
1212 {
1213 struct fbnic_fw_completion *cmpl_data;
1214 struct fbnic_dev *fbd = opaque;
1215 u32 msg_type;
1216 s32 err;
1217
1218 /* Verify we have a completion pointer */
1219 msg_type = FBNIC_TLV_MSG_ID_FW_WRITE_CHUNK_REQ;
1220 cmpl_data = fbnic_fw_get_cmpl_by_type(fbd, msg_type);
1221 if (!cmpl_data)
1222 return -ENOSPC;
1223
1224 /* Check for errors */
1225 err = fta_get_sint(results, FBNIC_FW_FINISH_UPGRADE_ERROR);
1226
1227 /* Close out update by incrementing offset by length which should
1228 * match the total size of the component. Set length to 0 since no
1229 * new chunks will be requested.
1230 */
1231 cmpl_data->u.fw_update.offset += cmpl_data->u.fw_update.length;
1232 cmpl_data->u.fw_update.length = 0;
1233
1234 cmpl_data->result = err;
1235 complete(&cmpl_data->done);
1236 fbnic_fw_put_cmpl(cmpl_data);
1237
1238 return 0;
1239 }
1240
1241 /**
1242 * fbnic_fw_xmit_qsfp_read_msg - Transmit a QSFP read request
1243 * @fbd: FBNIC device structure
1244 * @cmpl_data: Structure to store EEPROM response in
1245 * @page: Refers to page number on page enabled QSFP modules
1246 * @bank: Refers to a collection of pages
1247 * @offset: Offset into QSFP EEPROM requested
1248 * @length: Length of section of QSFP EEPROM to fetch
1249 *
1250 * Return: zero on success, negative value on failure
1251 *
1252 * Asks the firmware to provide a section of the QSFP EEPROM back in a
1253 * message. The response will have an offset and size matching the values
1254 * provided.
1255 */
fbnic_fw_xmit_qsfp_read_msg(struct fbnic_dev * fbd,struct fbnic_fw_completion * cmpl_data,u32 page,u32 bank,u32 offset,u32 length)1256 int fbnic_fw_xmit_qsfp_read_msg(struct fbnic_dev *fbd,
1257 struct fbnic_fw_completion *cmpl_data,
1258 u32 page, u32 bank, u32 offset, u32 length)
1259 {
1260 struct fbnic_tlv_msg *msg;
1261 int err = 0;
1262
1263 if (!length || length > TLV_MAX_DATA)
1264 return -EINVAL;
1265
1266 msg = fbnic_tlv_msg_alloc(FBNIC_TLV_MSG_ID_QSFP_READ_REQ);
1267 if (!msg)
1268 return -ENOMEM;
1269
1270 err = fbnic_tlv_attr_put_int(msg, FBNIC_FW_QSFP_BANK, bank);
1271 if (err)
1272 goto free_message;
1273
1274 err = fbnic_tlv_attr_put_int(msg, FBNIC_FW_QSFP_PAGE, page);
1275 if (err)
1276 goto free_message;
1277
1278 err = fbnic_tlv_attr_put_int(msg, FBNIC_FW_QSFP_OFFSET, offset);
1279 if (err)
1280 goto free_message;
1281
1282 err = fbnic_tlv_attr_put_int(msg, FBNIC_FW_QSFP_LENGTH, length);
1283 if (err)
1284 goto free_message;
1285
1286 err = fbnic_mbx_map_req_w_cmpl(fbd, msg, cmpl_data);
1287 if (err)
1288 goto free_message;
1289
1290 return 0;
1291
1292 free_message:
1293 free_page((unsigned long)msg);
1294 return err;
1295 }
1296
1297 static const struct fbnic_tlv_index fbnic_qsfp_read_resp_index[] = {
1298 FBNIC_TLV_ATTR_U32(FBNIC_FW_QSFP_BANK),
1299 FBNIC_TLV_ATTR_U32(FBNIC_FW_QSFP_PAGE),
1300 FBNIC_TLV_ATTR_U32(FBNIC_FW_QSFP_OFFSET),
1301 FBNIC_TLV_ATTR_U32(FBNIC_FW_QSFP_LENGTH),
1302 FBNIC_TLV_ATTR_RAW_DATA(FBNIC_FW_QSFP_DATA),
1303 FBNIC_TLV_ATTR_S32(FBNIC_FW_QSFP_ERROR),
1304 FBNIC_TLV_ATTR_LAST
1305 };
1306
fbnic_fw_parse_qsfp_read_resp(void * opaque,struct fbnic_tlv_msg ** results)1307 static int fbnic_fw_parse_qsfp_read_resp(void *opaque,
1308 struct fbnic_tlv_msg **results)
1309 {
1310 struct fbnic_fw_completion *cmpl_data;
1311 struct fbnic_dev *fbd = opaque;
1312 struct fbnic_tlv_msg *data_hdr;
1313 u32 length, offset, page, bank;
1314 u8 *data;
1315 s32 err;
1316
1317 /* Verify we have a completion pointer to provide with data */
1318 cmpl_data = fbnic_fw_get_cmpl_by_type(fbd,
1319 FBNIC_TLV_MSG_ID_QSFP_READ_RESP);
1320 if (!cmpl_data)
1321 return -ENOSPC;
1322
1323 bank = fta_get_uint(results, FBNIC_FW_QSFP_BANK);
1324 if (bank != cmpl_data->u.qsfp.bank) {
1325 dev_warn(fbd->dev, "bank not equal to bank requested: %d vs %d\n",
1326 bank, cmpl_data->u.qsfp.bank);
1327 err = -EINVAL;
1328 goto msg_err;
1329 }
1330
1331 page = fta_get_uint(results, FBNIC_FW_QSFP_PAGE);
1332 if (page != cmpl_data->u.qsfp.page) {
1333 dev_warn(fbd->dev, "page not equal to page requested: %d vs %d\n",
1334 page, cmpl_data->u.qsfp.page);
1335 err = -EINVAL;
1336 goto msg_err;
1337 }
1338
1339 offset = fta_get_uint(results, FBNIC_FW_QSFP_OFFSET);
1340 length = fta_get_uint(results, FBNIC_FW_QSFP_LENGTH);
1341
1342 if (length != cmpl_data->u.qsfp.length ||
1343 offset != cmpl_data->u.qsfp.offset) {
1344 dev_warn(fbd->dev,
1345 "offset/length not equal to size requested: %d/%d vs %d/%d\n",
1346 offset, length,
1347 cmpl_data->u.qsfp.offset, cmpl_data->u.qsfp.length);
1348 err = -EINVAL;
1349 goto msg_err;
1350 }
1351
1352 err = fta_get_sint(results, FBNIC_FW_QSFP_ERROR);
1353 if (err)
1354 goto msg_err;
1355
1356 data_hdr = results[FBNIC_FW_QSFP_DATA];
1357 if (!data_hdr) {
1358 err = -ENODATA;
1359 goto msg_err;
1360 }
1361
1362 /* Copy data */
1363 data = fbnic_tlv_attr_get_value_ptr(data_hdr);
1364 memcpy(cmpl_data->u.qsfp.data, data, length);
1365 msg_err:
1366 cmpl_data->result = err;
1367 complete(&cmpl_data->done);
1368 fbnic_fw_put_cmpl(cmpl_data);
1369
1370 return err;
1371 }
1372
1373 /**
1374 * fbnic_fw_xmit_tsene_read_msg - Create and transmit a sensor read request
1375 * @fbd: FBNIC device structure
1376 * @cmpl_data: Completion data structure to store sensor response
1377 *
1378 * Asks the firmware to provide an update with the latest sensor data.
1379 * The response will contain temperature and voltage readings.
1380 *
1381 * Return: 0 on success, negative error value on failure
1382 */
fbnic_fw_xmit_tsene_read_msg(struct fbnic_dev * fbd,struct fbnic_fw_completion * cmpl_data)1383 int fbnic_fw_xmit_tsene_read_msg(struct fbnic_dev *fbd,
1384 struct fbnic_fw_completion *cmpl_data)
1385 {
1386 struct fbnic_tlv_msg *msg;
1387 int err;
1388
1389 if (!fbnic_fw_present(fbd))
1390 return -ENODEV;
1391
1392 msg = fbnic_tlv_msg_alloc(FBNIC_TLV_MSG_ID_TSENE_READ_REQ);
1393 if (!msg)
1394 return -ENOMEM;
1395
1396 err = fbnic_mbx_map_req_w_cmpl(fbd, msg, cmpl_data);
1397 if (err)
1398 goto free_message;
1399
1400 return 0;
1401
1402 free_message:
1403 free_page((unsigned long)msg);
1404 return err;
1405 }
1406
1407 static const struct fbnic_tlv_index fbnic_tsene_read_resp_index[] = {
1408 FBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_THERM),
1409 FBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_VOLT),
1410 FBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_ERROR),
1411 FBNIC_TLV_ATTR_LAST
1412 };
1413
fbnic_fw_parse_tsene_read_resp(void * opaque,struct fbnic_tlv_msg ** results)1414 static int fbnic_fw_parse_tsene_read_resp(void *opaque,
1415 struct fbnic_tlv_msg **results)
1416 {
1417 struct fbnic_fw_completion *cmpl_data;
1418 struct fbnic_dev *fbd = opaque;
1419 s32 err_resp;
1420 int err = 0;
1421
1422 /* Verify we have a completion pointer to provide with data */
1423 cmpl_data = fbnic_fw_get_cmpl_by_type(fbd,
1424 FBNIC_TLV_MSG_ID_TSENE_READ_RESP);
1425 if (!cmpl_data)
1426 return -ENOSPC;
1427
1428 err_resp = fta_get_sint(results, FBNIC_FW_TSENE_ERROR);
1429 if (err_resp)
1430 goto msg_err;
1431
1432 if (!results[FBNIC_FW_TSENE_THERM] || !results[FBNIC_FW_TSENE_VOLT]) {
1433 err = -EINVAL;
1434 goto msg_err;
1435 }
1436
1437 cmpl_data->u.tsene.millidegrees =
1438 fta_get_sint(results, FBNIC_FW_TSENE_THERM);
1439 cmpl_data->u.tsene.millivolts =
1440 fta_get_sint(results, FBNIC_FW_TSENE_VOLT);
1441
1442 msg_err:
1443 cmpl_data->result = err_resp ? : err;
1444 complete(&cmpl_data->done);
1445 fbnic_fw_put_cmpl(cmpl_data);
1446
1447 return err;
1448 }
1449
1450 static const struct fbnic_tlv_index fbnic_fw_log_req_index[] = {
1451 FBNIC_TLV_ATTR_U32(FBNIC_FW_LOG_MSEC),
1452 FBNIC_TLV_ATTR_U64(FBNIC_FW_LOG_INDEX),
1453 FBNIC_TLV_ATTR_STRING(FBNIC_FW_LOG_MSG, FBNIC_FW_LOG_MAX_SIZE),
1454 FBNIC_TLV_ATTR_U32(FBNIC_FW_LOG_LENGTH),
1455 FBNIC_TLV_ATTR_ARRAY(FBNIC_FW_LOG_MSEC_ARRAY),
1456 FBNIC_TLV_ATTR_ARRAY(FBNIC_FW_LOG_INDEX_ARRAY),
1457 FBNIC_TLV_ATTR_ARRAY(FBNIC_FW_LOG_MSG_ARRAY),
1458 FBNIC_TLV_ATTR_LAST
1459 };
1460
fbnic_fw_process_log_array(struct fbnic_tlv_msg ** results,u16 length,u16 arr_type_idx,u16 attr_type_idx,struct fbnic_tlv_msg ** tlv_array_out)1461 static int fbnic_fw_process_log_array(struct fbnic_tlv_msg **results,
1462 u16 length, u16 arr_type_idx,
1463 u16 attr_type_idx,
1464 struct fbnic_tlv_msg **tlv_array_out)
1465 {
1466 struct fbnic_tlv_msg *attr;
1467 int attr_len;
1468 int err;
1469
1470 if (!results[attr_type_idx])
1471 return -EINVAL;
1472
1473 tlv_array_out[0] = results[attr_type_idx];
1474
1475 if (!length)
1476 return 0;
1477
1478 if (!results[arr_type_idx])
1479 return -EINVAL;
1480
1481 attr = results[arr_type_idx];
1482 attr_len = le16_to_cpu(attr->hdr.len) / sizeof(u32) - 1;
1483 err = fbnic_tlv_attr_parse_array(&attr[1], attr_len, &tlv_array_out[1],
1484 fbnic_fw_log_req_index,
1485 attr_type_idx,
1486 length);
1487 if (err)
1488 return err;
1489
1490 return 0;
1491 }
1492
fbnic_fw_parse_logs(struct fbnic_dev * fbd,struct fbnic_tlv_msg ** msec_tlv,struct fbnic_tlv_msg ** index_tlv,struct fbnic_tlv_msg ** log_tlv,int count)1493 static int fbnic_fw_parse_logs(struct fbnic_dev *fbd,
1494 struct fbnic_tlv_msg **msec_tlv,
1495 struct fbnic_tlv_msg **index_tlv,
1496 struct fbnic_tlv_msg **log_tlv,
1497 int count)
1498 {
1499 int i;
1500
1501 for (i = 0; i < count; i++) {
1502 char log[FBNIC_FW_LOG_MAX_SIZE];
1503 ssize_t len;
1504 u64 index;
1505 u32 msec;
1506 int err;
1507
1508 if (!msec_tlv[i] || !index_tlv[i] || !log_tlv[i]) {
1509 dev_warn(fbd->dev, "Received log message with missing attributes!\n");
1510 return -EINVAL;
1511 }
1512
1513 index = fbnic_tlv_attr_get_signed(index_tlv[i], 0);
1514 msec = fbnic_tlv_attr_get_signed(msec_tlv[i], 0);
1515 len = fbnic_tlv_attr_get_string(log_tlv[i], log,
1516 FBNIC_FW_LOG_MAX_SIZE);
1517 if (len < 0)
1518 return len;
1519
1520 err = fbnic_fw_log_write(fbd, index, msec, log);
1521 if (err)
1522 return err;
1523 }
1524
1525 return 0;
1526 }
1527
fbnic_fw_parse_log_req(void * opaque,struct fbnic_tlv_msg ** results)1528 static int fbnic_fw_parse_log_req(void *opaque,
1529 struct fbnic_tlv_msg **results)
1530 {
1531 struct fbnic_tlv_msg *index_tlv[FBNIC_FW_MAX_LOG_HISTORY];
1532 struct fbnic_tlv_msg *msec_tlv[FBNIC_FW_MAX_LOG_HISTORY];
1533 struct fbnic_tlv_msg *log_tlv[FBNIC_FW_MAX_LOG_HISTORY];
1534 struct fbnic_dev *fbd = opaque;
1535 u16 length;
1536 int err;
1537
1538 length = fta_get_uint(results, FBNIC_FW_LOG_LENGTH);
1539 if (length >= FBNIC_FW_MAX_LOG_HISTORY)
1540 return -E2BIG;
1541
1542 err = fbnic_fw_process_log_array(results, length,
1543 FBNIC_FW_LOG_MSEC_ARRAY,
1544 FBNIC_FW_LOG_MSEC, msec_tlv);
1545 if (err)
1546 return err;
1547
1548 err = fbnic_fw_process_log_array(results, length,
1549 FBNIC_FW_LOG_INDEX_ARRAY,
1550 FBNIC_FW_LOG_INDEX, index_tlv);
1551 if (err)
1552 return err;
1553
1554 err = fbnic_fw_process_log_array(results, length,
1555 FBNIC_FW_LOG_MSG_ARRAY,
1556 FBNIC_FW_LOG_MSG, log_tlv);
1557 if (err)
1558 return err;
1559
1560 err = fbnic_fw_parse_logs(fbd, msec_tlv, index_tlv, log_tlv,
1561 length + 1);
1562 if (err)
1563 return err;
1564
1565 return 0;
1566 }
1567
fbnic_fw_xmit_send_logs(struct fbnic_dev * fbd,bool enable,bool send_log_history)1568 int fbnic_fw_xmit_send_logs(struct fbnic_dev *fbd, bool enable,
1569 bool send_log_history)
1570 {
1571 struct fbnic_tlv_msg *msg;
1572 int err;
1573
1574 if (fbd->fw_cap.running.mgmt.version < MIN_FW_VER_CODE_LOG) {
1575 dev_warn(fbd->dev, "Firmware version is too old to support firmware logs!\n");
1576 return -EOPNOTSUPP;
1577 }
1578
1579 msg = fbnic_tlv_msg_alloc(FBNIC_TLV_MSG_ID_LOG_SEND_LOGS_REQ);
1580 if (!msg)
1581 return -ENOMEM;
1582
1583 if (enable) {
1584 err = fbnic_tlv_attr_put_flag(msg, FBNIC_SEND_LOGS);
1585 if (err)
1586 goto free_message;
1587
1588 /* Report request for version 1 of logs */
1589 err = fbnic_tlv_attr_put_int(msg, FBNIC_SEND_LOGS_VERSION,
1590 FBNIC_FW_LOG_VERSION);
1591 if (err)
1592 goto free_message;
1593
1594 if (send_log_history) {
1595 err = fbnic_tlv_attr_put_flag(msg,
1596 FBNIC_SEND_LOGS_HISTORY);
1597 if (err)
1598 goto free_message;
1599 }
1600 }
1601
1602 err = fbnic_mbx_map_tlv_msg(fbd, msg);
1603 if (err)
1604 goto free_message;
1605
1606 return 0;
1607
1608 free_message:
1609 free_page((unsigned long)msg);
1610 return err;
1611 }
1612
1613 static int
fbnic_fw_parser_test(void * opaque,struct fbnic_tlv_msg ** results)1614 fbnic_fw_parser_test(void *opaque, struct fbnic_tlv_msg **results)
1615 {
1616 struct fbnic_fw_completion *cmpl;
1617 struct fbnic_dev *fbd = opaque;
1618 int err;
1619
1620 /* find cmpl */
1621 cmpl = fbnic_fw_get_cmpl_by_type(fbd, FBNIC_TLV_MSG_ID_TEST);
1622 if (!cmpl)
1623 return -ENOSPC;
1624
1625 err = fbnic_tlv_parser_test(opaque, results);
1626
1627 cmpl->result = err;
1628 complete(&cmpl->done);
1629 fbnic_fw_put_cmpl(cmpl);
1630
1631 return err;
1632 }
1633
1634 static const struct fbnic_tlv_parser fbnic_fw_tlv_parser[] = {
1635 FBNIC_TLV_PARSER(TEST, fbnic_tlv_test_index, fbnic_fw_parser_test),
1636 FBNIC_TLV_PARSER(FW_CAP_RESP, fbnic_fw_cap_resp_index,
1637 fbnic_fw_parse_cap_resp),
1638 FBNIC_TLV_PARSER(OWNERSHIP_RESP, fbnic_ownership_resp_index,
1639 fbnic_fw_parse_ownership_resp),
1640 FBNIC_TLV_PARSER(HEARTBEAT_RESP, fbnic_heartbeat_resp_index,
1641 fbnic_fw_parse_heartbeat_resp),
1642 FBNIC_TLV_PARSER(COREDUMP_GET_INFO_RESP,
1643 fbnic_coredump_info_resp_index,
1644 fbnic_fw_parse_coredump_info_resp),
1645 FBNIC_TLV_PARSER(COREDUMP_READ_RESP, fbnic_coredump_resp_index,
1646 fbnic_fw_parse_coredump_resp),
1647 FBNIC_TLV_PARSER(FW_START_UPGRADE_RESP,
1648 fbnic_fw_start_upgrade_resp_index,
1649 fbnic_fw_parse_fw_start_upgrade_resp),
1650 FBNIC_TLV_PARSER(FW_WRITE_CHUNK_REQ,
1651 fbnic_fw_write_chunk_req_index,
1652 fbnic_fw_parse_fw_write_chunk_req),
1653 FBNIC_TLV_PARSER(FW_FINISH_UPGRADE_REQ,
1654 fbnic_fw_finish_upgrade_req_index,
1655 fbnic_fw_parse_fw_finish_upgrade_req),
1656 FBNIC_TLV_PARSER(QSFP_READ_RESP,
1657 fbnic_qsfp_read_resp_index,
1658 fbnic_fw_parse_qsfp_read_resp),
1659 FBNIC_TLV_PARSER(TSENE_READ_RESP,
1660 fbnic_tsene_read_resp_index,
1661 fbnic_fw_parse_tsene_read_resp),
1662 FBNIC_TLV_PARSER(LOG_MSG_REQ,
1663 fbnic_fw_log_req_index,
1664 fbnic_fw_parse_log_req),
1665 FBNIC_TLV_MSG_ERROR
1666 };
1667
fbnic_mbx_process_rx_msgs(struct fbnic_dev * fbd)1668 static void fbnic_mbx_process_rx_msgs(struct fbnic_dev *fbd)
1669 {
1670 struct fbnic_fw_mbx *rx_mbx = &fbd->mbx[FBNIC_IPC_MBX_RX_IDX];
1671 u8 head = rx_mbx->head, tail = rx_mbx->tail;
1672 u64 desc, length;
1673
1674 while (head != rx_mbx->tail) {
1675 struct fbnic_tlv_msg *msg;
1676 int err;
1677
1678 desc = __fbnic_mbx_rd_desc(fbd, FBNIC_IPC_MBX_RX_IDX, head);
1679 if (!(desc & FBNIC_IPC_MBX_DESC_FW_CMPL))
1680 break;
1681
1682 if (desc & FBNIC_IPC_MBX_DESC_FW_ERR) {
1683 rx_mbx->resp_error++;
1684 dev_warn_ratelimited(fbd->dev,
1685 "FW reported an error on an Rx mailbox message; dropping\n");
1686 goto next_page;
1687 }
1688
1689 dma_sync_single_for_cpu(fbd->dev, rx_mbx->buf_info[head].addr,
1690 FBNIC_RX_PAGE_SIZE, DMA_FROM_DEVICE);
1691
1692 msg = rx_mbx->buf_info[head].msg;
1693
1694 length = FIELD_GET(FBNIC_IPC_MBX_DESC_LEN_MASK, desc);
1695
1696 /* Ignore NULL mailbox descriptors */
1697 if (!length)
1698 goto next_page;
1699
1700 /* Report descriptors with length greater than page size */
1701 if (length > PAGE_SIZE) {
1702 dev_warn(fbd->dev,
1703 "Invalid mailbox descriptor length: %lld\n",
1704 length);
1705 goto next_page;
1706 }
1707
1708 if (le16_to_cpu(msg->hdr.len) * sizeof(u32) > length)
1709 dev_warn(fbd->dev, "Mailbox message length mismatch\n");
1710
1711 /* If parsing fails dump contents of message to dmesg */
1712 err = fbnic_tlv_msg_parse(fbd, msg, fbnic_fw_tlv_parser);
1713 if (err) {
1714 dev_warn(fbd->dev, "Unable to process message: %d\n",
1715 err);
1716 print_hex_dump(KERN_WARNING, "fbnic:",
1717 DUMP_PREFIX_OFFSET, 16, 2,
1718 msg, length, true);
1719 }
1720
1721 dev_dbg(fbd->dev, "Parsed msg type %d\n", msg->hdr.type);
1722 next_page:
1723 fw_wr32(fbd, FBNIC_IPC_MBX(FBNIC_IPC_MBX_RX_IDX, head), 0);
1724
1725 rx_mbx->buf_info[tail] = rx_mbx->buf_info[head];
1726 rx_mbx->buf_info[head].msg = NULL;
1727 rx_mbx->buf_info[head].addr = 0;
1728
1729 __fbnic_mbx_wr_desc(fbd, FBNIC_IPC_MBX_RX_IDX, tail,
1730 FIELD_PREP(FBNIC_IPC_MBX_DESC_LEN_MASK,
1731 FBNIC_RX_PAGE_SIZE) |
1732 (rx_mbx->buf_info[tail].addr &
1733 FBNIC_IPC_MBX_DESC_ADDR_MASK) |
1734 FBNIC_IPC_MBX_DESC_HOST_CMPL);
1735
1736 head = (head + 1) & (FBNIC_IPC_MBX_DESC_LEN - 1);
1737 tail = (tail + 1) & (FBNIC_IPC_MBX_DESC_LEN - 1);
1738 }
1739
1740 /* Record head for next interrupt */
1741 rx_mbx->head = head;
1742 rx_mbx->tail = tail;
1743 }
1744
fbnic_mbx_poll(struct fbnic_dev * fbd)1745 void fbnic_mbx_poll(struct fbnic_dev *fbd)
1746 {
1747 fbnic_mbx_event(fbd);
1748
1749 fbnic_mbx_process_tx_msgs(fbd);
1750 fbnic_mbx_process_rx_msgs(fbd);
1751 }
1752
fbnic_mbx_poll_tx_ready(struct fbnic_dev * fbd)1753 int fbnic_mbx_poll_tx_ready(struct fbnic_dev *fbd)
1754 {
1755 struct fbnic_fw_mbx *tx_mbx = &fbd->mbx[FBNIC_IPC_MBX_TX_IDX];
1756 struct fbnic_fw_mbx *rx_mbx = &fbd->mbx[FBNIC_IPC_MBX_RX_IDX];
1757 unsigned long timeout = jiffies + 10 * HZ + 1;
1758 u64 tx_resp_error, rx_resp_error;
1759 int err, i;
1760
1761 do {
1762 if (!time_is_after_jiffies(timeout))
1763 return -ETIMEDOUT;
1764
1765 /* Force the firmware to trigger an interrupt response to
1766 * avoid the mailbox getting stuck closed if the interrupt
1767 * is reset.
1768 */
1769 fbnic_mbx_reset_desc_ring(fbd, FBNIC_IPC_MBX_TX_IDX);
1770
1771 /* Immediate fail if BAR4 went away */
1772 if (!fbnic_fw_present(fbd))
1773 return -ENODEV;
1774
1775 msleep(20);
1776 } while (!fbnic_mbx_event(fbd));
1777
1778 /* FW has shown signs of life. Enable DMA and start Tx/Rx */
1779 for (i = 0; i < FBNIC_IPC_MBX_INDICES; i++) {
1780 err = fbnic_mbx_init_desc_ring(fbd, i);
1781 if (err)
1782 goto clean_mbx;
1783 }
1784
1785 /* Request an update from the firmware. This should overwrite
1786 * mgmt.version once we get the actual version from the firmware
1787 * in the capabilities request message.
1788 */
1789 send_cap_req:
1790 tx_resp_error = tx_mbx->resp_error;
1791 rx_resp_error = rx_mbx->resp_error;
1792 err = fbnic_fw_xmit_simple_msg(fbd, FBNIC_TLV_MSG_ID_HOST_CAP_REQ);
1793 if (err)
1794 goto clean_mbx;
1795
1796 /* Poll until we get a current management firmware version, use "1"
1797 * to indicate we entered the polling state waiting for a response
1798 */
1799 for (fbd->fw_cap.running.mgmt.version = 1;
1800 fbd->fw_cap.running.mgmt.version < MIN_FW_VER_CODE;) {
1801 if (!tx_mbx->ready)
1802 err = -ENODEV;
1803 if (err)
1804 goto clean_mbx;
1805
1806 msleep(20);
1807 fbnic_mbx_poll(fbd);
1808
1809 /* A valid capabilities response ends the poll. Check it
1810 * before the FW_ERR retry below so a response parsed in the
1811 * same poll as an unrelated FW_ERR is not discarded.
1812 */
1813 if (fbd->fw_cap.running.mgmt.version >= MIN_FW_VER_CODE)
1814 break;
1815
1816 /* set err, but wait till mgmt.version check to report it */
1817 if (!time_is_after_jiffies(timeout)) {
1818 err = -ETIMEDOUT;
1819 continue;
1820 }
1821
1822 /* The FW can flag our capabilities request (Tx) or its
1823 * response (Rx) with FW_ERR, in which case it produced no
1824 * usable response. The ring is not wedged, so re-issue the
1825 * request instead of spinning until the timeout.
1826 */
1827 if (tx_mbx->resp_error != tx_resp_error ||
1828 rx_mbx->resp_error != rx_resp_error)
1829 goto send_cap_req;
1830 }
1831
1832 return 0;
1833 clean_mbx:
1834 /* Cleanup Rx buffers and disable mailbox */
1835 fbnic_mbx_clean(fbd);
1836 return err;
1837 }
1838
__fbnic_fw_evict_cmpl(struct fbnic_fw_completion * cmpl_data)1839 static void __fbnic_fw_evict_cmpl(struct fbnic_fw_completion *cmpl_data)
1840 {
1841 cmpl_data->result = -EPIPE;
1842 complete(&cmpl_data->done);
1843 }
1844
fbnic_mbx_evict_all_cmpl(struct fbnic_dev * fbd)1845 static void fbnic_mbx_evict_all_cmpl(struct fbnic_dev *fbd)
1846 {
1847 int i;
1848
1849 for (i = 0; i < FBNIC_MBX_CMPL_SLOTS; i++) {
1850 struct fbnic_fw_completion *cmpl_data = fbd->cmpl_data[i];
1851
1852 if (cmpl_data)
1853 __fbnic_fw_evict_cmpl(cmpl_data);
1854 }
1855
1856 memset(fbd->cmpl_data, 0, sizeof(fbd->cmpl_data));
1857 }
1858
fbnic_mbx_flush_tx(struct fbnic_dev * fbd)1859 void fbnic_mbx_flush_tx(struct fbnic_dev *fbd)
1860 {
1861 unsigned long timeout = jiffies + 10 * HZ + 1;
1862 struct fbnic_fw_mbx *tx_mbx;
1863 u8 tail;
1864
1865 /* Record current Rx stats */
1866 tx_mbx = &fbd->mbx[FBNIC_IPC_MBX_TX_IDX];
1867
1868 spin_lock_irq(&fbd->fw_tx_lock);
1869
1870 /* Clear ready to prevent any further attempts to transmit */
1871 tx_mbx->ready = false;
1872
1873 /* Read tail to determine the last tail state for the ring */
1874 tail = tx_mbx->tail;
1875
1876 /* Flush any completions as we are no longer processing Rx */
1877 fbnic_mbx_evict_all_cmpl(fbd);
1878
1879 spin_unlock_irq(&fbd->fw_tx_lock);
1880
1881 /* Give firmware time to process packet,
1882 * we will wait up to 10 seconds which is 500 waits of 20ms.
1883 */
1884 do {
1885 u8 head = tx_mbx->head;
1886
1887 /* Tx ring is empty once head == tail */
1888 if (head == tail)
1889 break;
1890
1891 msleep(20);
1892 fbnic_mbx_process_tx_msgs(fbd);
1893 } while (time_is_after_jiffies(timeout));
1894 }
1895
1896 /**
1897 * fbnic_fw_mbx_self_test() - verify firmware interface
1898 * @fbd: device to test
1899 *
1900 * This function tests the interfaces to/from the firmware.
1901 *
1902 * Return: See enum fbnic_fw_self_test_codes
1903 **/
fbnic_fw_mbx_self_test(struct fbnic_dev * fbd)1904 enum fbnic_fw_self_test_codes fbnic_fw_mbx_self_test(struct fbnic_dev *fbd)
1905 {
1906 enum fbnic_fw_self_test_codes err;
1907 struct fbnic_fw_completion *cmpl;
1908
1909 /* Skip test if FW interface is not present */
1910 if (!fbnic_fw_present(fbd))
1911 return FBNIC_TEST_FW_NO_FIRMWARE;
1912
1913 cmpl = fbnic_fw_alloc_cmpl(FBNIC_TLV_MSG_ID_TEST);
1914 if (!cmpl)
1915 return FBNIC_TEST_FW_NO_CMPL;
1916
1917 /* Load a test message onto the FW mailbox interface
1918 * and arm the completion.
1919 */
1920 err = fbnic_fw_xmit_test_msg(fbd, cmpl);
1921 if (err) {
1922 err = FBNIC_TEST_FW_NO_XMIT;
1923 goto exit_free;
1924 }
1925
1926 /* Verify we received a message back */
1927 if (!fbnic_mbx_wait_for_cmpl(cmpl)) {
1928 err = FBNIC_TEST_FW_NO_MSG;
1929 goto exit_cleanup;
1930 }
1931
1932 /* Verify there were no parsing errors */
1933 if (cmpl->result)
1934 err = FBNIC_TEST_FW_PARSE;
1935 exit_cleanup:
1936 fbnic_mbx_clear_cmpl(fbd, cmpl);
1937 exit_free:
1938 fbnic_fw_put_cmpl(cmpl);
1939
1940 return err;
1941 }
1942
fbnic_fw_xmit_rpc_macda_sync(struct fbnic_dev * fbd)1943 int fbnic_fw_xmit_rpc_macda_sync(struct fbnic_dev *fbd)
1944 {
1945 struct fbnic_tlv_msg *mac_array;
1946 int i, addr_count = 0, err;
1947 struct fbnic_tlv_msg *msg;
1948 u32 rx_flags = 0;
1949
1950 /* Nothing to do if there is no FW to sync with */
1951 if (!fbd->mbx[FBNIC_IPC_MBX_TX_IDX].ready)
1952 return 0;
1953
1954 msg = fbnic_tlv_msg_alloc(FBNIC_TLV_MSG_ID_RPC_MAC_SYNC_REQ);
1955 if (!msg)
1956 return -ENOMEM;
1957
1958 mac_array = fbnic_tlv_attr_nest_start(msg,
1959 FBNIC_FW_RPC_MAC_SYNC_UC_ARRAY);
1960 if (!mac_array)
1961 goto free_message_nospc;
1962
1963 /* Populate the unicast MAC addrs and capture PROMISC/ALLMULTI flags */
1964 for (addr_count = 0, i = FBNIC_RPC_TCAM_MACDA_PROMISC_IDX;
1965 i >= fbd->mac_addr_boundary; i--) {
1966 struct fbnic_mac_addr *mac_addr = &fbd->mac_addr[i];
1967
1968 if (mac_addr->state != FBNIC_TCAM_S_VALID)
1969 continue;
1970 if (test_bit(FBNIC_MAC_ADDR_T_ALLMULTI, mac_addr->act_tcam))
1971 rx_flags |= FW_RPC_MAC_SYNC_RX_FLAGS_ALLMULTI;
1972 if (test_bit(FBNIC_MAC_ADDR_T_PROMISC, mac_addr->act_tcam))
1973 rx_flags |= FW_RPC_MAC_SYNC_RX_FLAGS_PROMISC;
1974 if (!test_bit(FBNIC_MAC_ADDR_T_UNICAST, mac_addr->act_tcam))
1975 continue;
1976 if (addr_count == FW_RPC_MAC_SYNC_UC_ARRAY_SIZE) {
1977 rx_flags |= FW_RPC_MAC_SYNC_RX_FLAGS_PROMISC;
1978 continue;
1979 }
1980
1981 err = fbnic_tlv_attr_put_value(mac_array,
1982 FBNIC_FW_RPC_MAC_SYNC_MAC_ADDR,
1983 mac_addr->value.addr8,
1984 ETH_ALEN);
1985 if (err)
1986 goto free_message;
1987 addr_count++;
1988 }
1989
1990 /* Close array */
1991 fbnic_tlv_attr_nest_stop(msg);
1992
1993 mac_array = fbnic_tlv_attr_nest_start(msg,
1994 FBNIC_FW_RPC_MAC_SYNC_MC_ARRAY);
1995 if (!mac_array)
1996 goto free_message_nospc;
1997
1998 /* Repeat for multicast addrs, record BROADCAST/ALLMULTI flags */
1999 for (addr_count = 0, i = FBNIC_RPC_TCAM_MACDA_BROADCAST_IDX;
2000 i < fbd->mac_addr_boundary; i++) {
2001 struct fbnic_mac_addr *mac_addr = &fbd->mac_addr[i];
2002
2003 if (mac_addr->state != FBNIC_TCAM_S_VALID)
2004 continue;
2005 if (test_bit(FBNIC_MAC_ADDR_T_BROADCAST, mac_addr->act_tcam))
2006 rx_flags |= FW_RPC_MAC_SYNC_RX_FLAGS_BROADCAST;
2007 if (test_bit(FBNIC_MAC_ADDR_T_ALLMULTI, mac_addr->act_tcam))
2008 rx_flags |= FW_RPC_MAC_SYNC_RX_FLAGS_ALLMULTI;
2009 if (!test_bit(FBNIC_MAC_ADDR_T_MULTICAST, mac_addr->act_tcam))
2010 continue;
2011 if (addr_count == FW_RPC_MAC_SYNC_MC_ARRAY_SIZE) {
2012 rx_flags |= FW_RPC_MAC_SYNC_RX_FLAGS_ALLMULTI;
2013 continue;
2014 }
2015
2016 err = fbnic_tlv_attr_put_value(mac_array,
2017 FBNIC_FW_RPC_MAC_SYNC_MAC_ADDR,
2018 mac_addr->value.addr8,
2019 ETH_ALEN);
2020 if (err)
2021 goto free_message;
2022 addr_count++;
2023 }
2024
2025 /* Close array */
2026 fbnic_tlv_attr_nest_stop(msg);
2027
2028 /* Report flags at end of list */
2029 err = fbnic_tlv_attr_put_int(msg, FBNIC_FW_RPC_MAC_SYNC_RX_FLAGS,
2030 rx_flags);
2031 if (err)
2032 goto free_message;
2033
2034 /* Send message off to FW notifying it of current RPC config */
2035 err = fbnic_mbx_map_tlv_msg(fbd, msg);
2036 if (err)
2037 goto free_message;
2038 return 0;
2039 free_message_nospc:
2040 err = -ENOSPC;
2041 free_message:
2042 free_page((unsigned long)msg);
2043 return err;
2044 }
2045
fbnic_get_fw_ver_commit_str(struct fbnic_dev * fbd,char * fw_version,const size_t str_sz)2046 void fbnic_get_fw_ver_commit_str(struct fbnic_dev *fbd, char *fw_version,
2047 const size_t str_sz)
2048 {
2049 struct fbnic_fw_ver *mgmt = &fbd->fw_cap.running.mgmt;
2050 const char *delim = "";
2051
2052 if (mgmt->commit[0])
2053 delim = "_";
2054
2055 fbnic_mk_full_fw_ver_str(mgmt->version, delim, mgmt->commit,
2056 fw_version, str_sz);
2057 }
2058
__fbnic_fw_alloc_cmpl(u32 msg_type,size_t priv_size)2059 struct fbnic_fw_completion *__fbnic_fw_alloc_cmpl(u32 msg_type,
2060 size_t priv_size)
2061 {
2062 struct fbnic_fw_completion *cmpl;
2063
2064 cmpl = kzalloc(sizeof(*cmpl) + priv_size, GFP_KERNEL);
2065 if (!cmpl)
2066 return NULL;
2067
2068 cmpl->msg_type = msg_type;
2069 init_completion(&cmpl->done);
2070 kref_init(&cmpl->ref_count);
2071
2072 return cmpl;
2073 }
2074
fbnic_fw_alloc_cmpl(u32 msg_type)2075 struct fbnic_fw_completion *fbnic_fw_alloc_cmpl(u32 msg_type)
2076 {
2077 return __fbnic_fw_alloc_cmpl(msg_type, 0);
2078 }
2079
fbnic_fw_put_cmpl(struct fbnic_fw_completion * fw_cmpl)2080 void fbnic_fw_put_cmpl(struct fbnic_fw_completion *fw_cmpl)
2081 {
2082 kref_put(&fw_cmpl->ref_count, fbnic_fw_release_cmpl_data);
2083 }
2084