1
2
3
4
5
6
7
8
9
10#include <linux/delay.h>
11#include <linux/moduleparam.h>
12#include <asm/cmpxchg.h>
13#include "net_driver.h"
14#include "nic.h"
15#include "io.h"
16#include "farch_regs.h"
17#include "mcdi_pcol.h"
18
19
20
21
22
23
24
25
26#define MCDI_RPC_TIMEOUT (10 * HZ)
27
28
29
30
31
32#define MCDI_STATUS_DELAY_US 100
33#define MCDI_STATUS_DELAY_COUNT 2500
34#define MCDI_STATUS_SLEEP_MS \
35 (MCDI_STATUS_DELAY_US * MCDI_STATUS_DELAY_COUNT / 1000)
36
37#define SEQ_MASK \
38 EFX_MASK32(EFX_WIDTH(MCDI_HEADER_SEQ))
39
40struct efx_mcdi_async_param {
41 struct list_head list;
42 unsigned int cmd;
43 size_t inlen;
44 size_t outlen;
45 bool quiet;
46 efx_mcdi_async_completer *complete;
47 unsigned long cookie;
48
49};
50
51static void efx_mcdi_timeout_async(unsigned long context);
52static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
53 bool *was_attached_out);
54static bool efx_mcdi_poll_once(struct efx_nic *efx);
55static void efx_mcdi_abandon(struct efx_nic *efx);
56
57#ifdef CONFIG_SFC_MCDI_LOGGING
58static bool mcdi_logging_default;
59module_param(mcdi_logging_default, bool, 0644);
60MODULE_PARM_DESC(mcdi_logging_default,
61 "Enable MCDI logging on newly-probed functions");
62#endif
63
64int efx_mcdi_init(struct efx_nic *efx)
65{
66 struct efx_mcdi_iface *mcdi;
67 bool already_attached;
68 int rc = -ENOMEM;
69
70 efx->mcdi = kzalloc(sizeof(*efx->mcdi), GFP_KERNEL);
71 if (!efx->mcdi)
72 goto fail;
73
74 mcdi = efx_mcdi(efx);
75 mcdi->efx = efx;
76#ifdef CONFIG_SFC_MCDI_LOGGING
77
78 mcdi->logging_buffer = (char *)__get_free_page(GFP_KERNEL);
79 if (!mcdi->logging_buffer)
80 goto fail1;
81 mcdi->logging_enabled = mcdi_logging_default;
82#endif
83 init_waitqueue_head(&mcdi->wq);
84 init_waitqueue_head(&mcdi->proxy_rx_wq);
85 spin_lock_init(&mcdi->iface_lock);
86 mcdi->state = MCDI_STATE_QUIESCENT;
87 mcdi->mode = MCDI_MODE_POLL;
88 spin_lock_init(&mcdi->async_lock);
89 INIT_LIST_HEAD(&mcdi->async_list);
90 setup_timer(&mcdi->async_timer, efx_mcdi_timeout_async,
91 (unsigned long)mcdi);
92
93 (void) efx_mcdi_poll_reboot(efx);
94 mcdi->new_epoch = true;
95
96
97 rc = efx_mcdi_handle_assertion(efx);
98 if (rc)
99 goto fail2;
100
101
102
103
104 rc = efx_mcdi_drv_attach(efx, true, &already_attached);
105 if (rc) {
106 netif_err(efx, probe, efx->net_dev,
107 "Unable to register driver with MCPU\n");
108 goto fail2;
109 }
110 if (already_attached)
111
112 netif_err(efx, probe, efx->net_dev,
113 "Host already registered with MCPU\n");
114
115 if (efx->mcdi->fn_flags &
116 (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_PRIMARY))
117 efx->primary = efx;
118
119 return 0;
120fail2:
121#ifdef CONFIG_SFC_MCDI_LOGGING
122 free_page((unsigned long)mcdi->logging_buffer);
123fail1:
124#endif
125 kfree(efx->mcdi);
126 efx->mcdi = NULL;
127fail:
128 return rc;
129}
130
131void efx_mcdi_detach(struct efx_nic *efx)
132{
133 if (!efx->mcdi)
134 return;
135
136 BUG_ON(efx->mcdi->iface.state != MCDI_STATE_QUIESCENT);
137
138
139 efx_mcdi_drv_attach(efx, false, NULL);
140}
141
142void efx_mcdi_fini(struct efx_nic *efx)
143{
144 if (!efx->mcdi)
145 return;
146
147#ifdef CONFIG_SFC_MCDI_LOGGING
148 free_page((unsigned long)efx->mcdi->iface.logging_buffer);
149#endif
150
151 kfree(efx->mcdi);
152}
153
154static void efx_mcdi_send_request(struct efx_nic *efx, unsigned cmd,
155 const efx_dword_t *inbuf, size_t inlen)
156{
157 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
158#ifdef CONFIG_SFC_MCDI_LOGGING
159 char *buf = mcdi->logging_buffer;
160#endif
161 efx_dword_t hdr[2];
162 size_t hdr_len;
163 u32 xflags, seqno;
164
165 BUG_ON(mcdi->state == MCDI_STATE_QUIESCENT);
166
167
168 spin_lock_bh(&mcdi->iface_lock);
169 ++mcdi->seqno;
170 spin_unlock_bh(&mcdi->iface_lock);
171
172 seqno = mcdi->seqno & SEQ_MASK;
173 xflags = 0;
174 if (mcdi->mode == MCDI_MODE_EVENTS)
175 xflags |= MCDI_HEADER_XFLAGS_EVREQ;
176
177 if (efx->type->mcdi_max_ver == 1) {
178
179 EFX_POPULATE_DWORD_7(hdr[0],
180 MCDI_HEADER_RESPONSE, 0,
181 MCDI_HEADER_RESYNC, 1,
182 MCDI_HEADER_CODE, cmd,
183 MCDI_HEADER_DATALEN, inlen,
184 MCDI_HEADER_SEQ, seqno,
185 MCDI_HEADER_XFLAGS, xflags,
186 MCDI_HEADER_NOT_EPOCH, !mcdi->new_epoch);
187 hdr_len = 4;
188 } else {
189
190 BUG_ON(inlen > MCDI_CTL_SDU_LEN_MAX_V2);
191 EFX_POPULATE_DWORD_7(hdr[0],
192 MCDI_HEADER_RESPONSE, 0,
193 MCDI_HEADER_RESYNC, 1,
194 MCDI_HEADER_CODE, MC_CMD_V2_EXTN,
195 MCDI_HEADER_DATALEN, 0,
196 MCDI_HEADER_SEQ, seqno,
197 MCDI_HEADER_XFLAGS, xflags,
198 MCDI_HEADER_NOT_EPOCH, !mcdi->new_epoch);
199 EFX_POPULATE_DWORD_2(hdr[1],
200 MC_CMD_V2_EXTN_IN_EXTENDED_CMD, cmd,
201 MC_CMD_V2_EXTN_IN_ACTUAL_LEN, inlen);
202 hdr_len = 8;
203 }
204
205#ifdef CONFIG_SFC_MCDI_LOGGING
206 if (mcdi->logging_enabled && !WARN_ON_ONCE(!buf)) {
207 int bytes = 0;
208 int i;
209
210
211
212 WARN_ON_ONCE(hdr_len % 4);
213 WARN_ON_ONCE(inlen % 4);
214
215
216
217
218 for (i = 0; i < hdr_len / 4 && bytes < PAGE_SIZE; i++)
219 bytes += snprintf(buf + bytes, PAGE_SIZE - bytes,
220 " %08x", le32_to_cpu(hdr[i].u32[0]));
221
222 for (i = 0; i < inlen / 4 && bytes < PAGE_SIZE; i++)
223 bytes += snprintf(buf + bytes, PAGE_SIZE - bytes,
224 " %08x", le32_to_cpu(inbuf[i].u32[0]));
225
226 netif_info(efx, hw, efx->net_dev, "MCDI RPC REQ:%s\n", buf);
227 }
228#endif
229
230 efx->type->mcdi_request(efx, hdr, hdr_len, inbuf, inlen);
231
232 mcdi->new_epoch = false;
233}
234
235static int efx_mcdi_errno(unsigned int mcdi_err)
236{
237 switch (mcdi_err) {
238 case 0:
239 return 0;
240#define TRANSLATE_ERROR(name) \
241 case MC_CMD_ERR_ ## name: \
242 return -name;
243 TRANSLATE_ERROR(EPERM);
244 TRANSLATE_ERROR(ENOENT);
245 TRANSLATE_ERROR(EINTR);
246 TRANSLATE_ERROR(EAGAIN);
247 TRANSLATE_ERROR(EACCES);
248 TRANSLATE_ERROR(EBUSY);
249 TRANSLATE_ERROR(EINVAL);
250 TRANSLATE_ERROR(EDEADLK);
251 TRANSLATE_ERROR(ENOSYS);
252 TRANSLATE_ERROR(ETIME);
253 TRANSLATE_ERROR(EALREADY);
254 TRANSLATE_ERROR(ENOSPC);
255#undef TRANSLATE_ERROR
256 case MC_CMD_ERR_ENOTSUP:
257 return -EOPNOTSUPP;
258 case MC_CMD_ERR_ALLOC_FAIL:
259 return -ENOBUFS;
260 case MC_CMD_ERR_MAC_EXIST:
261 return -EADDRINUSE;
262 default:
263 return -EPROTO;
264 }
265}
266
267static void efx_mcdi_read_response_header(struct efx_nic *efx)
268{
269 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
270 unsigned int respseq, respcmd, error;
271#ifdef CONFIG_SFC_MCDI_LOGGING
272 char *buf = mcdi->logging_buffer;
273#endif
274 efx_dword_t hdr;
275
276 efx->type->mcdi_read_response(efx, &hdr, 0, 4);
277 respseq = EFX_DWORD_FIELD(hdr, MCDI_HEADER_SEQ);
278 respcmd = EFX_DWORD_FIELD(hdr, MCDI_HEADER_CODE);
279 error = EFX_DWORD_FIELD(hdr, MCDI_HEADER_ERROR);
280
281 if (respcmd != MC_CMD_V2_EXTN) {
282 mcdi->resp_hdr_len = 4;
283 mcdi->resp_data_len = EFX_DWORD_FIELD(hdr, MCDI_HEADER_DATALEN);
284 } else {
285 efx->type->mcdi_read_response(efx, &hdr, 4, 4);
286 mcdi->resp_hdr_len = 8;
287 mcdi->resp_data_len =
288 EFX_DWORD_FIELD(hdr, MC_CMD_V2_EXTN_IN_ACTUAL_LEN);
289 }
290
291#ifdef CONFIG_SFC_MCDI_LOGGING
292 if (mcdi->logging_enabled && !WARN_ON_ONCE(!buf)) {
293 size_t hdr_len, data_len;
294 int bytes = 0;
295 int i;
296
297 WARN_ON_ONCE(mcdi->resp_hdr_len % 4);
298 hdr_len = mcdi->resp_hdr_len / 4;
299
300
301
302 data_len = DIV_ROUND_UP(mcdi->resp_data_len, 4);
303
304
305
306
307 for (i = 0; i < hdr_len && bytes < PAGE_SIZE; i++) {
308 efx->type->mcdi_read_response(efx, &hdr, (i * 4), 4);
309 bytes += snprintf(buf + bytes, PAGE_SIZE - bytes,
310 " %08x", le32_to_cpu(hdr.u32[0]));
311 }
312
313 for (i = 0; i < data_len && bytes < PAGE_SIZE; i++) {
314 efx->type->mcdi_read_response(efx, &hdr,
315 mcdi->resp_hdr_len + (i * 4), 4);
316 bytes += snprintf(buf + bytes, PAGE_SIZE - bytes,
317 " %08x", le32_to_cpu(hdr.u32[0]));
318 }
319
320 netif_info(efx, hw, efx->net_dev, "MCDI RPC RESP:%s\n", buf);
321 }
322#endif
323
324 mcdi->resprc_raw = 0;
325 if (error && mcdi->resp_data_len == 0) {
326 netif_err(efx, hw, efx->net_dev, "MC rebooted\n");
327 mcdi->resprc = -EIO;
328 } else if ((respseq ^ mcdi->seqno) & SEQ_MASK) {
329 netif_err(efx, hw, efx->net_dev,
330 "MC response mismatch tx seq 0x%x rx seq 0x%x\n",
331 respseq, mcdi->seqno);
332 mcdi->resprc = -EIO;
333 } else if (error) {
334 efx->type->mcdi_read_response(efx, &hdr, mcdi->resp_hdr_len, 4);
335 mcdi->resprc_raw = EFX_DWORD_FIELD(hdr, EFX_DWORD_0);
336 mcdi->resprc = efx_mcdi_errno(mcdi->resprc_raw);
337 } else {
338 mcdi->resprc = 0;
339 }
340}
341
342static bool efx_mcdi_poll_once(struct efx_nic *efx)
343{
344 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
345
346 rmb();
347 if (!efx->type->mcdi_poll_response(efx))
348 return false;
349
350 spin_lock_bh(&mcdi->iface_lock);
351 efx_mcdi_read_response_header(efx);
352 spin_unlock_bh(&mcdi->iface_lock);
353
354 return true;
355}
356
357static int efx_mcdi_poll(struct efx_nic *efx)
358{
359 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
360 unsigned long time, finish;
361 unsigned int spins;
362 int rc;
363
364
365 rc = efx_mcdi_poll_reboot(efx);
366 if (rc) {
367 spin_lock_bh(&mcdi->iface_lock);
368 mcdi->resprc = rc;
369 mcdi->resp_hdr_len = 0;
370 mcdi->resp_data_len = 0;
371 spin_unlock_bh(&mcdi->iface_lock);
372 return 0;
373 }
374
375
376
377
378
379 spins = TICK_USEC;
380 finish = jiffies + MCDI_RPC_TIMEOUT;
381
382 while (1) {
383 if (spins != 0) {
384 --spins;
385 udelay(1);
386 } else {
387 schedule_timeout_uninterruptible(1);
388 }
389
390 time = jiffies;
391
392 if (efx_mcdi_poll_once(efx))
393 break;
394
395 if (time_after(time, finish))
396 return -ETIMEDOUT;
397 }
398
399
400 return 0;
401}
402
403
404
405
406int efx_mcdi_poll_reboot(struct efx_nic *efx)
407{
408 if (!efx->mcdi)
409 return 0;
410
411 return efx->type->mcdi_poll_reboot(efx);
412}
413
414static bool efx_mcdi_acquire_async(struct efx_mcdi_iface *mcdi)
415{
416 return cmpxchg(&mcdi->state,
417 MCDI_STATE_QUIESCENT, MCDI_STATE_RUNNING_ASYNC) ==
418 MCDI_STATE_QUIESCENT;
419}
420
421static void efx_mcdi_acquire_sync(struct efx_mcdi_iface *mcdi)
422{
423
424
425
426 wait_event(mcdi->wq,
427 cmpxchg(&mcdi->state,
428 MCDI_STATE_QUIESCENT, MCDI_STATE_RUNNING_SYNC) ==
429 MCDI_STATE_QUIESCENT);
430}
431
432static int efx_mcdi_await_completion(struct efx_nic *efx)
433{
434 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
435
436 if (wait_event_timeout(mcdi->wq, mcdi->state == MCDI_STATE_COMPLETED,
437 MCDI_RPC_TIMEOUT) == 0)
438 return -ETIMEDOUT;
439
440
441
442
443
444
445
446
447
448 if (mcdi->mode == MCDI_MODE_POLL)
449 return efx_mcdi_poll(efx);
450
451 return 0;
452}
453
454
455
456
457static bool efx_mcdi_complete_sync(struct efx_mcdi_iface *mcdi)
458{
459 if (cmpxchg(&mcdi->state,
460 MCDI_STATE_RUNNING_SYNC, MCDI_STATE_COMPLETED) ==
461 MCDI_STATE_RUNNING_SYNC) {
462 wake_up(&mcdi->wq);
463 return true;
464 }
465
466 return false;
467}
468
469static void efx_mcdi_release(struct efx_mcdi_iface *mcdi)
470{
471 if (mcdi->mode == MCDI_MODE_EVENTS) {
472 struct efx_mcdi_async_param *async;
473 struct efx_nic *efx = mcdi->efx;
474
475
476 spin_lock_bh(&mcdi->async_lock);
477 async = list_first_entry_or_null(
478 &mcdi->async_list, struct efx_mcdi_async_param, list);
479 if (async) {
480 mcdi->state = MCDI_STATE_RUNNING_ASYNC;
481 efx_mcdi_send_request(efx, async->cmd,
482 (const efx_dword_t *)(async + 1),
483 async->inlen);
484 mod_timer(&mcdi->async_timer,
485 jiffies + MCDI_RPC_TIMEOUT);
486 }
487 spin_unlock_bh(&mcdi->async_lock);
488
489 if (async)
490 return;
491 }
492
493 mcdi->state = MCDI_STATE_QUIESCENT;
494 wake_up(&mcdi->wq);
495}
496
497
498
499
500
501
502static bool efx_mcdi_complete_async(struct efx_mcdi_iface *mcdi, bool timeout)
503{
504 struct efx_nic *efx = mcdi->efx;
505 struct efx_mcdi_async_param *async;
506 size_t hdr_len, data_len, err_len;
507 efx_dword_t *outbuf;
508 MCDI_DECLARE_BUF_ERR(errbuf);
509 int rc;
510
511 if (cmpxchg(&mcdi->state,
512 MCDI_STATE_RUNNING_ASYNC, MCDI_STATE_COMPLETED) !=
513 MCDI_STATE_RUNNING_ASYNC)
514 return false;
515
516 spin_lock(&mcdi->iface_lock);
517 if (timeout) {
518
519
520
521 ++mcdi->seqno;
522 ++mcdi->credits;
523 rc = -ETIMEDOUT;
524 hdr_len = 0;
525 data_len = 0;
526 } else {
527 rc = mcdi->resprc;
528 hdr_len = mcdi->resp_hdr_len;
529 data_len = mcdi->resp_data_len;
530 }
531 spin_unlock(&mcdi->iface_lock);
532
533
534
535
536
537 if (!timeout)
538 del_timer_sync(&mcdi->async_timer);
539
540 spin_lock(&mcdi->async_lock);
541 async = list_first_entry(&mcdi->async_list,
542 struct efx_mcdi_async_param, list);
543 list_del(&async->list);
544 spin_unlock(&mcdi->async_lock);
545
546 outbuf = (efx_dword_t *)(async + 1);
547 efx->type->mcdi_read_response(efx, outbuf, hdr_len,
548 min(async->outlen, data_len));
549 if (!timeout && rc && !async->quiet) {
550 err_len = min(sizeof(errbuf), data_len);
551 efx->type->mcdi_read_response(efx, errbuf, hdr_len,
552 sizeof(errbuf));
553 efx_mcdi_display_error(efx, async->cmd, async->inlen, errbuf,
554 err_len, rc);
555 }
556
557 if (async->complete)
558 async->complete(efx, async->cookie, rc, outbuf,
559 min(async->outlen, data_len));
560 kfree(async);
561
562 efx_mcdi_release(mcdi);
563
564 return true;
565}
566
567static void efx_mcdi_ev_cpl(struct efx_nic *efx, unsigned int seqno,
568 unsigned int datalen, unsigned int mcdi_err)
569{
570 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
571 bool wake = false;
572
573 spin_lock(&mcdi->iface_lock);
574
575 if ((seqno ^ mcdi->seqno) & SEQ_MASK) {
576 if (mcdi->credits)
577
578 --mcdi->credits;
579 else
580 netif_err(efx, hw, efx->net_dev,
581 "MC response mismatch tx seq 0x%x rx "
582 "seq 0x%x\n", seqno, mcdi->seqno);
583 } else {
584 if (efx->type->mcdi_max_ver >= 2) {
585
586 efx_mcdi_read_response_header(efx);
587 } else {
588 mcdi->resprc = efx_mcdi_errno(mcdi_err);
589 mcdi->resp_hdr_len = 4;
590 mcdi->resp_data_len = datalen;
591 }
592
593 wake = true;
594 }
595
596 spin_unlock(&mcdi->iface_lock);
597
598 if (wake) {
599 if (!efx_mcdi_complete_async(mcdi, false))
600 (void) efx_mcdi_complete_sync(mcdi);
601
602
603
604
605
606
607
608 }
609}
610
611static void efx_mcdi_timeout_async(unsigned long context)
612{
613 struct efx_mcdi_iface *mcdi = (struct efx_mcdi_iface *)context;
614
615 efx_mcdi_complete_async(mcdi, true);
616}
617
618static int
619efx_mcdi_check_supported(struct efx_nic *efx, unsigned int cmd, size_t inlen)
620{
621 if (efx->type->mcdi_max_ver < 0 ||
622 (efx->type->mcdi_max_ver < 2 &&
623 cmd > MC_CMD_CMD_SPACE_ESCAPE_7))
624 return -EINVAL;
625
626 if (inlen > MCDI_CTL_SDU_LEN_MAX_V2 ||
627 (efx->type->mcdi_max_ver < 2 &&
628 inlen > MCDI_CTL_SDU_LEN_MAX_V1))
629 return -EMSGSIZE;
630
631 return 0;
632}
633
634static bool efx_mcdi_get_proxy_handle(struct efx_nic *efx,
635 size_t hdr_len, size_t data_len,
636 u32 *proxy_handle)
637{
638 MCDI_DECLARE_BUF_ERR(testbuf);
639 const size_t buflen = sizeof(testbuf);
640
641 if (!proxy_handle || data_len < buflen)
642 return false;
643
644 efx->type->mcdi_read_response(efx, testbuf, hdr_len, buflen);
645 if (MCDI_DWORD(testbuf, ERR_CODE) == MC_CMD_ERR_PROXY_PENDING) {
646 *proxy_handle = MCDI_DWORD(testbuf, ERR_PROXY_PENDING_HANDLE);
647 return true;
648 }
649
650 return false;
651}
652
653static int _efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned int cmd,
654 size_t inlen,
655 efx_dword_t *outbuf, size_t outlen,
656 size_t *outlen_actual, bool quiet,
657 u32 *proxy_handle, int *raw_rc)
658{
659 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
660 MCDI_DECLARE_BUF_ERR(errbuf);
661 int rc;
662
663 if (mcdi->mode == MCDI_MODE_POLL)
664 rc = efx_mcdi_poll(efx);
665 else
666 rc = efx_mcdi_await_completion(efx);
667
668 if (rc != 0) {
669 netif_err(efx, hw, efx->net_dev,
670 "MC command 0x%x inlen %d mode %d timed out\n",
671 cmd, (int)inlen, mcdi->mode);
672
673 if (mcdi->mode == MCDI_MODE_EVENTS && efx_mcdi_poll_once(efx)) {
674 netif_err(efx, hw, efx->net_dev,
675 "MCDI request was completed without an event\n");
676 rc = 0;
677 }
678
679 efx_mcdi_abandon(efx);
680
681
682
683
684
685 spin_lock_bh(&mcdi->iface_lock);
686 ++mcdi->seqno;
687 ++mcdi->credits;
688 spin_unlock_bh(&mcdi->iface_lock);
689 }
690
691 if (proxy_handle)
692 *proxy_handle = 0;
693
694 if (rc != 0) {
695 if (outlen_actual)
696 *outlen_actual = 0;
697 } else {
698 size_t hdr_len, data_len, err_len;
699
700
701
702
703
704 spin_lock_bh(&mcdi->iface_lock);
705 rc = mcdi->resprc;
706 if (raw_rc)
707 *raw_rc = mcdi->resprc_raw;
708 hdr_len = mcdi->resp_hdr_len;
709 data_len = mcdi->resp_data_len;
710 err_len = min(sizeof(errbuf), data_len);
711 spin_unlock_bh(&mcdi->iface_lock);
712
713 BUG_ON(rc > 0);
714
715 efx->type->mcdi_read_response(efx, outbuf, hdr_len,
716 min(outlen, data_len));
717 if (outlen_actual)
718 *outlen_actual = data_len;
719
720 efx->type->mcdi_read_response(efx, errbuf, hdr_len, err_len);
721
722 if (cmd == MC_CMD_REBOOT && rc == -EIO) {
723
724 } else if (rc == -EIO || rc == -EINTR) {
725 netif_err(efx, hw, efx->net_dev, "MC reboot detected\n");
726 netif_dbg(efx, hw, efx->net_dev, "MC rebooted during command %d rc %d\n",
727 cmd, -rc);
728 if (efx->type->mcdi_reboot_detected)
729 efx->type->mcdi_reboot_detected(efx);
730 efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE);
731 } else if (proxy_handle && (rc == -EPROTO) &&
732 efx_mcdi_get_proxy_handle(efx, hdr_len, data_len,
733 proxy_handle)) {
734 mcdi->proxy_rx_status = 0;
735 mcdi->proxy_rx_handle = 0;
736 mcdi->state = MCDI_STATE_PROXY_WAIT;
737 } else if (rc && !quiet) {
738 efx_mcdi_display_error(efx, cmd, inlen, errbuf, err_len,
739 rc);
740 }
741
742 if (rc == -EIO || rc == -EINTR) {
743 msleep(MCDI_STATUS_SLEEP_MS);
744 efx_mcdi_poll_reboot(efx);
745 mcdi->new_epoch = true;
746 }
747 }
748
749 if (!proxy_handle || !*proxy_handle)
750 efx_mcdi_release(mcdi);
751 return rc;
752}
753
754static void efx_mcdi_proxy_abort(struct efx_mcdi_iface *mcdi)
755{
756 if (mcdi->state == MCDI_STATE_PROXY_WAIT) {
757
758 mcdi->proxy_rx_status = -EINTR;
759 wake_up(&mcdi->proxy_rx_wq);
760 }
761}
762
763static void efx_mcdi_ev_proxy_response(struct efx_nic *efx,
764 u32 handle, int status)
765{
766 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
767
768 WARN_ON(mcdi->state != MCDI_STATE_PROXY_WAIT);
769
770 mcdi->proxy_rx_status = efx_mcdi_errno(status);
771
772
773
774 wmb();
775 mcdi->proxy_rx_handle = handle;
776 wake_up(&mcdi->proxy_rx_wq);
777}
778
779static int efx_mcdi_proxy_wait(struct efx_nic *efx, u32 handle, bool quiet)
780{
781 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
782 int rc;
783
784
785 rc = wait_event_timeout(mcdi->proxy_rx_wq,
786 mcdi->proxy_rx_handle != 0 ||
787 mcdi->proxy_rx_status == -EINTR,
788 MCDI_RPC_TIMEOUT);
789
790 if (rc <= 0) {
791 netif_dbg(efx, hw, efx->net_dev,
792 "MCDI proxy timeout %d\n", handle);
793 return -ETIMEDOUT;
794 } else if (mcdi->proxy_rx_handle != handle) {
795 netif_warn(efx, hw, efx->net_dev,
796 "MCDI proxy unexpected handle %d (expected %d)\n",
797 mcdi->proxy_rx_handle, handle);
798 return -EINVAL;
799 }
800
801 return mcdi->proxy_rx_status;
802}
803
804static int _efx_mcdi_rpc(struct efx_nic *efx, unsigned int cmd,
805 const efx_dword_t *inbuf, size_t inlen,
806 efx_dword_t *outbuf, size_t outlen,
807 size_t *outlen_actual, bool quiet, int *raw_rc)
808{
809 u32 proxy_handle = 0;
810 int rc;
811
812 if (inbuf && inlen && (inbuf == outbuf)) {
813
814 WARN_ON(1);
815 return -EINVAL;
816 }
817
818 rc = efx_mcdi_rpc_start(efx, cmd, inbuf, inlen);
819 if (rc)
820 return rc;
821
822 rc = _efx_mcdi_rpc_finish(efx, cmd, inlen, outbuf, outlen,
823 outlen_actual, quiet, &proxy_handle, raw_rc);
824
825 if (proxy_handle) {
826
827
828
829
830 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
831
832 netif_dbg(efx, hw, efx->net_dev,
833 "MCDI waiting for proxy auth %d\n",
834 proxy_handle);
835 rc = efx_mcdi_proxy_wait(efx, proxy_handle, quiet);
836
837 if (rc == 0) {
838 netif_dbg(efx, hw, efx->net_dev,
839 "MCDI proxy retry %d\n", proxy_handle);
840
841
842 mcdi->state = MCDI_STATE_RUNNING_SYNC;
843 efx_mcdi_send_request(efx, cmd, inbuf, inlen);
844
845 rc = _efx_mcdi_rpc_finish(efx, cmd, inlen,
846 outbuf, outlen, outlen_actual,
847 quiet, NULL, raw_rc);
848 } else {
849 netif_cond_dbg(efx, hw, efx->net_dev, rc == -EPERM, err,
850 "MC command 0x%x failed after proxy auth rc=%d\n",
851 cmd, rc);
852
853 if (rc == -EINTR || rc == -EIO)
854 efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE);
855 efx_mcdi_release(mcdi);
856 }
857 }
858
859 return rc;
860}
861
862static int _efx_mcdi_rpc_evb_retry(struct efx_nic *efx, unsigned cmd,
863 const efx_dword_t *inbuf, size_t inlen,
864 efx_dword_t *outbuf, size_t outlen,
865 size_t *outlen_actual, bool quiet)
866{
867 int raw_rc = 0;
868 int rc;
869
870 rc = _efx_mcdi_rpc(efx, cmd, inbuf, inlen,
871 outbuf, outlen, outlen_actual, true, &raw_rc);
872
873 if ((rc == -EPROTO) && (raw_rc == MC_CMD_ERR_NO_EVB_PORT) &&
874 efx->type->is_vf) {
875
876
877
878
879 unsigned long abort_time = jiffies + MCDI_RPC_TIMEOUT;
880 unsigned int delay_us = 10000;
881
882 netif_dbg(efx, hw, efx->net_dev,
883 "%s: NO_EVB_PORT; will retry request\n",
884 __func__);
885
886 do {
887 usleep_range(delay_us, delay_us + 10000);
888 rc = _efx_mcdi_rpc(efx, cmd, inbuf, inlen,
889 outbuf, outlen, outlen_actual,
890 true, &raw_rc);
891 if (delay_us < 100000)
892 delay_us <<= 1;
893 } while ((rc == -EPROTO) &&
894 (raw_rc == MC_CMD_ERR_NO_EVB_PORT) &&
895 time_before(jiffies, abort_time));
896 }
897
898 if (rc && !quiet && !(cmd == MC_CMD_REBOOT && rc == -EIO))
899 efx_mcdi_display_error(efx, cmd, inlen,
900 outbuf, outlen, rc);
901
902 return rc;
903}
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd,
930 const efx_dword_t *inbuf, size_t inlen,
931 efx_dword_t *outbuf, size_t outlen,
932 size_t *outlen_actual)
933{
934 return _efx_mcdi_rpc_evb_retry(efx, cmd, inbuf, inlen, outbuf, outlen,
935 outlen_actual, false);
936}
937
938
939
940
941
942
943
944
945
946int efx_mcdi_rpc_quiet(struct efx_nic *efx, unsigned cmd,
947 const efx_dword_t *inbuf, size_t inlen,
948 efx_dword_t *outbuf, size_t outlen,
949 size_t *outlen_actual)
950{
951 return _efx_mcdi_rpc_evb_retry(efx, cmd, inbuf, inlen, outbuf, outlen,
952 outlen_actual, true);
953}
954
955int efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd,
956 const efx_dword_t *inbuf, size_t inlen)
957{
958 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
959 int rc;
960
961 rc = efx_mcdi_check_supported(efx, cmd, inlen);
962 if (rc)
963 return rc;
964
965 if (efx->mc_bist_for_other_fn)
966 return -ENETDOWN;
967
968 if (mcdi->mode == MCDI_MODE_FAIL)
969 return -ENETDOWN;
970
971 efx_mcdi_acquire_sync(mcdi);
972 efx_mcdi_send_request(efx, cmd, inbuf, inlen);
973 return 0;
974}
975
976static int _efx_mcdi_rpc_async(struct efx_nic *efx, unsigned int cmd,
977 const efx_dword_t *inbuf, size_t inlen,
978 size_t outlen,
979 efx_mcdi_async_completer *complete,
980 unsigned long cookie, bool quiet)
981{
982 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
983 struct efx_mcdi_async_param *async;
984 int rc;
985
986 rc = efx_mcdi_check_supported(efx, cmd, inlen);
987 if (rc)
988 return rc;
989
990 if (efx->mc_bist_for_other_fn)
991 return -ENETDOWN;
992
993 async = kmalloc(sizeof(*async) + ALIGN(max(inlen, outlen), 4),
994 GFP_ATOMIC);
995 if (!async)
996 return -ENOMEM;
997
998 async->cmd = cmd;
999 async->inlen = inlen;
1000 async->outlen = outlen;
1001 async->quiet = quiet;
1002 async->complete = complete;
1003 async->cookie = cookie;
1004 memcpy(async + 1, inbuf, inlen);
1005
1006 spin_lock_bh(&mcdi->async_lock);
1007
1008 if (mcdi->mode == MCDI_MODE_EVENTS) {
1009 list_add_tail(&async->list, &mcdi->async_list);
1010
1011
1012
1013
1014 if (mcdi->async_list.next == &async->list &&
1015 efx_mcdi_acquire_async(mcdi)) {
1016 efx_mcdi_send_request(efx, cmd, inbuf, inlen);
1017 mod_timer(&mcdi->async_timer,
1018 jiffies + MCDI_RPC_TIMEOUT);
1019 }
1020 } else {
1021 kfree(async);
1022 rc = -ENETDOWN;
1023 }
1024
1025 spin_unlock_bh(&mcdi->async_lock);
1026
1027 return rc;
1028}
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050int
1051efx_mcdi_rpc_async(struct efx_nic *efx, unsigned int cmd,
1052 const efx_dword_t *inbuf, size_t inlen, size_t outlen,
1053 efx_mcdi_async_completer *complete, unsigned long cookie)
1054{
1055 return _efx_mcdi_rpc_async(efx, cmd, inbuf, inlen, outlen, complete,
1056 cookie, false);
1057}
1058
1059int efx_mcdi_rpc_async_quiet(struct efx_nic *efx, unsigned int cmd,
1060 const efx_dword_t *inbuf, size_t inlen,
1061 size_t outlen, efx_mcdi_async_completer *complete,
1062 unsigned long cookie)
1063{
1064 return _efx_mcdi_rpc_async(efx, cmd, inbuf, inlen, outlen, complete,
1065 cookie, true);
1066}
1067
1068int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
1069 efx_dword_t *outbuf, size_t outlen,
1070 size_t *outlen_actual)
1071{
1072 return _efx_mcdi_rpc_finish(efx, cmd, inlen, outbuf, outlen,
1073 outlen_actual, false, NULL, NULL);
1074}
1075
1076int efx_mcdi_rpc_finish_quiet(struct efx_nic *efx, unsigned cmd, size_t inlen,
1077 efx_dword_t *outbuf, size_t outlen,
1078 size_t *outlen_actual)
1079{
1080 return _efx_mcdi_rpc_finish(efx, cmd, inlen, outbuf, outlen,
1081 outlen_actual, true, NULL, NULL);
1082}
1083
1084void efx_mcdi_display_error(struct efx_nic *efx, unsigned cmd,
1085 size_t inlen, efx_dword_t *outbuf,
1086 size_t outlen, int rc)
1087{
1088 int code = 0, err_arg = 0;
1089
1090 if (outlen >= MC_CMD_ERR_CODE_OFST + 4)
1091 code = MCDI_DWORD(outbuf, ERR_CODE);
1092 if (outlen >= MC_CMD_ERR_ARG_OFST + 4)
1093 err_arg = MCDI_DWORD(outbuf, ERR_ARG);
1094 netif_cond_dbg(efx, hw, efx->net_dev, rc == -EPERM, err,
1095 "MC command 0x%x inlen %zu failed rc=%d (raw=%d) arg=%d\n",
1096 cmd, inlen, rc, code, err_arg);
1097}
1098
1099
1100
1101
1102
1103void efx_mcdi_mode_poll(struct efx_nic *efx)
1104{
1105 struct efx_mcdi_iface *mcdi;
1106
1107 if (!efx->mcdi)
1108 return;
1109
1110 mcdi = efx_mcdi(efx);
1111
1112
1113
1114
1115 if (mcdi->mode == MCDI_MODE_POLL || mcdi->mode == MCDI_MODE_FAIL)
1116 return;
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126 mcdi->mode = MCDI_MODE_POLL;
1127
1128 efx_mcdi_complete_sync(mcdi);
1129}
1130
1131
1132
1133
1134void efx_mcdi_flush_async(struct efx_nic *efx)
1135{
1136 struct efx_mcdi_async_param *async, *next;
1137 struct efx_mcdi_iface *mcdi;
1138
1139 if (!efx->mcdi)
1140 return;
1141
1142 mcdi = efx_mcdi(efx);
1143
1144
1145 BUG_ON(mcdi->mode == MCDI_MODE_EVENTS);
1146
1147 del_timer_sync(&mcdi->async_timer);
1148
1149
1150
1151
1152
1153 if (mcdi->state == MCDI_STATE_RUNNING_ASYNC) {
1154 efx_mcdi_poll(efx);
1155 mcdi->state = MCDI_STATE_QUIESCENT;
1156 }
1157
1158
1159
1160
1161
1162
1163 list_for_each_entry_safe(async, next, &mcdi->async_list, list) {
1164 if (async->complete)
1165 async->complete(efx, async->cookie, -ENETDOWN, NULL, 0);
1166 list_del(&async->list);
1167 kfree(async);
1168 }
1169}
1170
1171void efx_mcdi_mode_event(struct efx_nic *efx)
1172{
1173 struct efx_mcdi_iface *mcdi;
1174
1175 if (!efx->mcdi)
1176 return;
1177
1178 mcdi = efx_mcdi(efx);
1179
1180
1181
1182
1183 if (mcdi->mode == MCDI_MODE_EVENTS || mcdi->mode == MCDI_MODE_FAIL)
1184 return;
1185
1186
1187
1188
1189
1190
1191
1192
1193 efx_mcdi_acquire_sync(mcdi);
1194 mcdi->mode = MCDI_MODE_EVENTS;
1195 efx_mcdi_release(mcdi);
1196}
1197
1198static void efx_mcdi_ev_death(struct efx_nic *efx, int rc)
1199{
1200 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226 spin_lock(&mcdi->iface_lock);
1227 efx_mcdi_proxy_abort(mcdi);
1228
1229 if (efx_mcdi_complete_sync(mcdi)) {
1230 if (mcdi->mode == MCDI_MODE_EVENTS) {
1231 mcdi->resprc = rc;
1232 mcdi->resp_hdr_len = 0;
1233 mcdi->resp_data_len = 0;
1234 ++mcdi->credits;
1235 }
1236 } else {
1237 int count;
1238
1239
1240 for (count = 0; count < MCDI_STATUS_DELAY_COUNT; ++count) {
1241 rc = efx_mcdi_poll_reboot(efx);
1242 if (rc)
1243 break;
1244 udelay(MCDI_STATUS_DELAY_US);
1245 }
1246
1247
1248
1249
1250
1251
1252
1253 if (!rc && efx->type->mcdi_reboot_detected)
1254 efx->type->mcdi_reboot_detected(efx);
1255
1256 mcdi->new_epoch = true;
1257
1258
1259 efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE);
1260 }
1261
1262 spin_unlock(&mcdi->iface_lock);
1263}
1264
1265
1266
1267
1268
1269
1270static void efx_mcdi_ev_bist(struct efx_nic *efx)
1271{
1272 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
1273
1274 spin_lock(&mcdi->iface_lock);
1275 efx->mc_bist_for_other_fn = true;
1276 efx_mcdi_proxy_abort(mcdi);
1277
1278 if (efx_mcdi_complete_sync(mcdi)) {
1279 if (mcdi->mode == MCDI_MODE_EVENTS) {
1280 mcdi->resprc = -EIO;
1281 mcdi->resp_hdr_len = 0;
1282 mcdi->resp_data_len = 0;
1283 ++mcdi->credits;
1284 }
1285 }
1286 mcdi->new_epoch = true;
1287 efx_schedule_reset(efx, RESET_TYPE_MC_BIST);
1288 spin_unlock(&mcdi->iface_lock);
1289}
1290
1291
1292
1293
1294static void efx_mcdi_abandon(struct efx_nic *efx)
1295{
1296 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
1297
1298 if (xchg(&mcdi->mode, MCDI_MODE_FAIL) == MCDI_MODE_FAIL)
1299 return;
1300 netif_dbg(efx, hw, efx->net_dev, "MCDI is timing out; trying to recover\n");
1301 efx_schedule_reset(efx, RESET_TYPE_MCDI_TIMEOUT);
1302}
1303
1304
1305void efx_mcdi_process_event(struct efx_channel *channel,
1306 efx_qword_t *event)
1307{
1308 struct efx_nic *efx = channel->efx;
1309 int code = EFX_QWORD_FIELD(*event, MCDI_EVENT_CODE);
1310 u32 data = EFX_QWORD_FIELD(*event, MCDI_EVENT_DATA);
1311
1312 switch (code) {
1313 case MCDI_EVENT_CODE_BADSSERT:
1314 netif_err(efx, hw, efx->net_dev,
1315 "MC watchdog or assertion failure at 0x%x\n", data);
1316 efx_mcdi_ev_death(efx, -EINTR);
1317 break;
1318
1319 case MCDI_EVENT_CODE_PMNOTICE:
1320 netif_info(efx, wol, efx->net_dev, "MCDI PM event.\n");
1321 break;
1322
1323 case MCDI_EVENT_CODE_CMDDONE:
1324 efx_mcdi_ev_cpl(efx,
1325 MCDI_EVENT_FIELD(*event, CMDDONE_SEQ),
1326 MCDI_EVENT_FIELD(*event, CMDDONE_DATALEN),
1327 MCDI_EVENT_FIELD(*event, CMDDONE_ERRNO));
1328 break;
1329
1330 case MCDI_EVENT_CODE_LINKCHANGE:
1331 efx_mcdi_process_link_change(efx, event);
1332 break;
1333 case MCDI_EVENT_CODE_SENSOREVT:
1334 efx_mcdi_sensor_event(efx, event);
1335 break;
1336 case MCDI_EVENT_CODE_SCHEDERR:
1337 netif_dbg(efx, hw, efx->net_dev,
1338 "MC Scheduler alert (0x%x)\n", data);
1339 break;
1340 case MCDI_EVENT_CODE_REBOOT:
1341 case MCDI_EVENT_CODE_MC_REBOOT:
1342 netif_info(efx, hw, efx->net_dev, "MC Reboot\n");
1343 efx_mcdi_ev_death(efx, -EIO);
1344 break;
1345 case MCDI_EVENT_CODE_MC_BIST:
1346 netif_info(efx, hw, efx->net_dev, "MC entered BIST mode\n");
1347 efx_mcdi_ev_bist(efx);
1348 break;
1349 case MCDI_EVENT_CODE_MAC_STATS_DMA:
1350
1351 break;
1352 case MCDI_EVENT_CODE_FLR:
1353 if (efx->type->sriov_flr)
1354 efx->type->sriov_flr(efx,
1355 MCDI_EVENT_FIELD(*event, FLR_VF));
1356 break;
1357 case MCDI_EVENT_CODE_PTP_RX:
1358 case MCDI_EVENT_CODE_PTP_FAULT:
1359 case MCDI_EVENT_CODE_PTP_PPS:
1360 efx_ptp_event(efx, event);
1361 break;
1362 case MCDI_EVENT_CODE_PTP_TIME:
1363 efx_time_sync_event(channel, event);
1364 break;
1365 case MCDI_EVENT_CODE_TX_FLUSH:
1366 case MCDI_EVENT_CODE_RX_FLUSH:
1367
1368
1369
1370
1371
1372
1373 BUILD_BUG_ON(MCDI_EVENT_TX_FLUSH_TO_DRIVER_LBN !=
1374 MCDI_EVENT_RX_FLUSH_TO_DRIVER_LBN);
1375 if (!MCDI_EVENT_FIELD(*event, TX_FLUSH_TO_DRIVER))
1376 efx_ef10_handle_drain_event(efx);
1377 break;
1378 case MCDI_EVENT_CODE_TX_ERR:
1379 case MCDI_EVENT_CODE_RX_ERR:
1380 netif_err(efx, hw, efx->net_dev,
1381 "%s DMA error (event: "EFX_QWORD_FMT")\n",
1382 code == MCDI_EVENT_CODE_TX_ERR ? "TX" : "RX",
1383 EFX_QWORD_VAL(*event));
1384 efx_schedule_reset(efx, RESET_TYPE_DMA_ERROR);
1385 break;
1386 case MCDI_EVENT_CODE_PROXY_RESPONSE:
1387 efx_mcdi_ev_proxy_response(efx,
1388 MCDI_EVENT_FIELD(*event, PROXY_RESPONSE_HANDLE),
1389 MCDI_EVENT_FIELD(*event, PROXY_RESPONSE_RC));
1390 break;
1391 default:
1392 netif_err(efx, hw, efx->net_dev, "Unknown MCDI event 0x%x\n",
1393 code);
1394 }
1395}
1396
1397
1398
1399
1400
1401
1402
1403
1404void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len)
1405{
1406 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_VERSION_OUT_LEN);
1407 size_t outlength;
1408 const __le16 *ver_words;
1409 size_t offset;
1410 int rc;
1411
1412 BUILD_BUG_ON(MC_CMD_GET_VERSION_IN_LEN != 0);
1413 rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, NULL, 0,
1414 outbuf, sizeof(outbuf), &outlength);
1415 if (rc)
1416 goto fail;
1417 if (outlength < MC_CMD_GET_VERSION_OUT_LEN) {
1418 rc = -EIO;
1419 goto fail;
1420 }
1421
1422 ver_words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_OUT_VERSION);
1423 offset = snprintf(buf, len, "%u.%u.%u.%u",
1424 le16_to_cpu(ver_words[0]), le16_to_cpu(ver_words[1]),
1425 le16_to_cpu(ver_words[2]), le16_to_cpu(ver_words[3]));
1426
1427
1428
1429
1430 if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0) {
1431 struct efx_ef10_nic_data *nic_data = efx->nic_data;
1432
1433 offset += snprintf(buf + offset, len - offset, " rx%x tx%x",
1434 nic_data->rx_dpcpu_fw_id,
1435 nic_data->tx_dpcpu_fw_id);
1436
1437
1438
1439
1440
1441 if (WARN_ON(offset >= len))
1442 buf[0] = 0;
1443 }
1444
1445 return;
1446
1447fail:
1448 netif_err(efx, probe, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
1449 buf[0] = 0;
1450}
1451
1452static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
1453 bool *was_attached)
1454{
1455 MCDI_DECLARE_BUF(inbuf, MC_CMD_DRV_ATTACH_IN_LEN);
1456 MCDI_DECLARE_BUF(outbuf, MC_CMD_DRV_ATTACH_EXT_OUT_LEN);
1457 size_t outlen;
1458 int rc;
1459
1460 MCDI_SET_DWORD(inbuf, DRV_ATTACH_IN_NEW_STATE,
1461 driver_operating ? 1 : 0);
1462 MCDI_SET_DWORD(inbuf, DRV_ATTACH_IN_UPDATE, 1);
1463 MCDI_SET_DWORD(inbuf, DRV_ATTACH_IN_FIRMWARE_ID, MC_CMD_FW_LOW_LATENCY);
1464
1465 rc = efx_mcdi_rpc_quiet(efx, MC_CMD_DRV_ATTACH, inbuf, sizeof(inbuf),
1466 outbuf, sizeof(outbuf), &outlen);
1467
1468
1469
1470
1471 if (rc == -EPERM) {
1472 netif_dbg(efx, probe, efx->net_dev,
1473 "efx_mcdi_drv_attach with fw-variant setting failed EPERM, trying without it\n");
1474 MCDI_SET_DWORD(inbuf, DRV_ATTACH_IN_FIRMWARE_ID,
1475 MC_CMD_FW_DONT_CARE);
1476 rc = efx_mcdi_rpc_quiet(efx, MC_CMD_DRV_ATTACH, inbuf,
1477 sizeof(inbuf), outbuf, sizeof(outbuf),
1478 &outlen);
1479 }
1480 if (rc) {
1481 efx_mcdi_display_error(efx, MC_CMD_DRV_ATTACH, sizeof(inbuf),
1482 outbuf, outlen, rc);
1483 goto fail;
1484 }
1485 if (outlen < MC_CMD_DRV_ATTACH_OUT_LEN) {
1486 rc = -EIO;
1487 goto fail;
1488 }
1489
1490 if (driver_operating) {
1491 if (outlen >= MC_CMD_DRV_ATTACH_EXT_OUT_LEN) {
1492 efx->mcdi->fn_flags =
1493 MCDI_DWORD(outbuf,
1494 DRV_ATTACH_EXT_OUT_FUNC_FLAGS);
1495 } else {
1496
1497 efx->mcdi->fn_flags =
1498 1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_LINKCTRL |
1499 1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_TRUSTED |
1500 (efx_port_num(efx) == 0) <<
1501 MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_PRIMARY;
1502 }
1503 }
1504
1505
1506
1507
1508
1509
1510 if (was_attached != NULL)
1511 *was_attached = MCDI_DWORD(outbuf, DRV_ATTACH_OUT_OLD_STATE);
1512 return 0;
1513
1514fail:
1515 netif_err(efx, probe, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
1516 return rc;
1517}
1518
1519int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
1520 u16 *fw_subtype_list, u32 *capabilities)
1521{
1522 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_BOARD_CFG_OUT_LENMAX);
1523 size_t outlen, i;
1524 int port_num = efx_port_num(efx);
1525 int rc;
1526
1527 BUILD_BUG_ON(MC_CMD_GET_BOARD_CFG_IN_LEN != 0);
1528
1529 BUILD_BUG_ON(MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_OFST & 1);
1530 BUILD_BUG_ON(MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_OFST & 1);
1531
1532 rc = efx_mcdi_rpc(efx, MC_CMD_GET_BOARD_CFG, NULL, 0,
1533 outbuf, sizeof(outbuf), &outlen);
1534 if (rc)
1535 goto fail;
1536
1537 if (outlen < MC_CMD_GET_BOARD_CFG_OUT_LENMIN) {
1538 rc = -EIO;
1539 goto fail;
1540 }
1541
1542 if (mac_address)
1543 ether_addr_copy(mac_address,
1544 port_num ?
1545 MCDI_PTR(outbuf, GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1) :
1546 MCDI_PTR(outbuf, GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0));
1547 if (fw_subtype_list) {
1548 for (i = 0;
1549 i < MCDI_VAR_ARRAY_LEN(outlen,
1550 GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST);
1551 i++)
1552 fw_subtype_list[i] = MCDI_ARRAY_WORD(
1553 outbuf, GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST, i);
1554 for (; i < MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MAXNUM; i++)
1555 fw_subtype_list[i] = 0;
1556 }
1557 if (capabilities) {
1558 if (port_num)
1559 *capabilities = MCDI_DWORD(outbuf,
1560 GET_BOARD_CFG_OUT_CAPABILITIES_PORT1);
1561 else
1562 *capabilities = MCDI_DWORD(outbuf,
1563 GET_BOARD_CFG_OUT_CAPABILITIES_PORT0);
1564 }
1565
1566 return 0;
1567
1568fail:
1569 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d len=%d\n",
1570 __func__, rc, (int)outlen);
1571
1572 return rc;
1573}
1574
1575int efx_mcdi_log_ctrl(struct efx_nic *efx, bool evq, bool uart, u32 dest_evq)
1576{
1577 MCDI_DECLARE_BUF(inbuf, MC_CMD_LOG_CTRL_IN_LEN);
1578 u32 dest = 0;
1579 int rc;
1580
1581 if (uart)
1582 dest |= MC_CMD_LOG_CTRL_IN_LOG_DEST_UART;
1583 if (evq)
1584 dest |= MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ;
1585
1586 MCDI_SET_DWORD(inbuf, LOG_CTRL_IN_LOG_DEST, dest);
1587 MCDI_SET_DWORD(inbuf, LOG_CTRL_IN_LOG_DEST_EVQ, dest_evq);
1588
1589 BUILD_BUG_ON(MC_CMD_LOG_CTRL_OUT_LEN != 0);
1590
1591 rc = efx_mcdi_rpc(efx, MC_CMD_LOG_CTRL, inbuf, sizeof(inbuf),
1592 NULL, 0, NULL);
1593 return rc;
1594}
1595
1596int efx_mcdi_nvram_types(struct efx_nic *efx, u32 *nvram_types_out)
1597{
1598 MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_TYPES_OUT_LEN);
1599 size_t outlen;
1600 int rc;
1601
1602 BUILD_BUG_ON(MC_CMD_NVRAM_TYPES_IN_LEN != 0);
1603
1604 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_TYPES, NULL, 0,
1605 outbuf, sizeof(outbuf), &outlen);
1606 if (rc)
1607 goto fail;
1608 if (outlen < MC_CMD_NVRAM_TYPES_OUT_LEN) {
1609 rc = -EIO;
1610 goto fail;
1611 }
1612
1613 *nvram_types_out = MCDI_DWORD(outbuf, NVRAM_TYPES_OUT_TYPES);
1614 return 0;
1615
1616fail:
1617 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
1618 __func__, rc);
1619 return rc;
1620}
1621
1622int efx_mcdi_nvram_info(struct efx_nic *efx, unsigned int type,
1623 size_t *size_out, size_t *erase_size_out,
1624 bool *protected_out)
1625{
1626 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_INFO_IN_LEN);
1627 MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_INFO_OUT_LEN);
1628 size_t outlen;
1629 int rc;
1630
1631 MCDI_SET_DWORD(inbuf, NVRAM_INFO_IN_TYPE, type);
1632
1633 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_INFO, inbuf, sizeof(inbuf),
1634 outbuf, sizeof(outbuf), &outlen);
1635 if (rc)
1636 goto fail;
1637 if (outlen < MC_CMD_NVRAM_INFO_OUT_LEN) {
1638 rc = -EIO;
1639 goto fail;
1640 }
1641
1642 *size_out = MCDI_DWORD(outbuf, NVRAM_INFO_OUT_SIZE);
1643 *erase_size_out = MCDI_DWORD(outbuf, NVRAM_INFO_OUT_ERASESIZE);
1644 *protected_out = !!(MCDI_DWORD(outbuf, NVRAM_INFO_OUT_FLAGS) &
1645 (1 << MC_CMD_NVRAM_INFO_OUT_PROTECTED_LBN));
1646 return 0;
1647
1648fail:
1649 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
1650 return rc;
1651}
1652
1653static int efx_mcdi_nvram_test(struct efx_nic *efx, unsigned int type)
1654{
1655 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_TEST_IN_LEN);
1656 MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_TEST_OUT_LEN);
1657 int rc;
1658
1659 MCDI_SET_DWORD(inbuf, NVRAM_TEST_IN_TYPE, type);
1660
1661 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_TEST, inbuf, sizeof(inbuf),
1662 outbuf, sizeof(outbuf), NULL);
1663 if (rc)
1664 return rc;
1665
1666 switch (MCDI_DWORD(outbuf, NVRAM_TEST_OUT_RESULT)) {
1667 case MC_CMD_NVRAM_TEST_PASS:
1668 case MC_CMD_NVRAM_TEST_NOTSUPP:
1669 return 0;
1670 default:
1671 return -EIO;
1672 }
1673}
1674
1675int efx_mcdi_nvram_test_all(struct efx_nic *efx)
1676{
1677 u32 nvram_types;
1678 unsigned int type;
1679 int rc;
1680
1681 rc = efx_mcdi_nvram_types(efx, &nvram_types);
1682 if (rc)
1683 goto fail1;
1684
1685 type = 0;
1686 while (nvram_types != 0) {
1687 if (nvram_types & 1) {
1688 rc = efx_mcdi_nvram_test(efx, type);
1689 if (rc)
1690 goto fail2;
1691 }
1692 type++;
1693 nvram_types >>= 1;
1694 }
1695
1696 return 0;
1697
1698fail2:
1699 netif_err(efx, hw, efx->net_dev, "%s: failed type=%u\n",
1700 __func__, type);
1701fail1:
1702 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
1703 return rc;
1704}
1705
1706
1707
1708
1709static int efx_mcdi_read_assertion(struct efx_nic *efx)
1710{
1711 MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_ASSERTS_IN_LEN);
1712 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_ASSERTS_OUT_LEN);
1713 unsigned int flags, index;
1714 const char *reason;
1715 size_t outlen;
1716 int retry;
1717 int rc;
1718
1719
1720
1721
1722
1723
1724 retry = 2;
1725 do {
1726 MCDI_SET_DWORD(inbuf, GET_ASSERTS_IN_CLEAR, 1);
1727 rc = efx_mcdi_rpc_quiet(efx, MC_CMD_GET_ASSERTS,
1728 inbuf, MC_CMD_GET_ASSERTS_IN_LEN,
1729 outbuf, sizeof(outbuf), &outlen);
1730 if (rc == -EPERM)
1731 return 0;
1732 } while ((rc == -EINTR || rc == -EIO) && retry-- > 0);
1733
1734 if (rc) {
1735 efx_mcdi_display_error(efx, MC_CMD_GET_ASSERTS,
1736 MC_CMD_GET_ASSERTS_IN_LEN, outbuf,
1737 outlen, rc);
1738 return rc;
1739 }
1740 if (outlen < MC_CMD_GET_ASSERTS_OUT_LEN)
1741 return -EIO;
1742
1743
1744 flags = MCDI_DWORD(outbuf, GET_ASSERTS_OUT_GLOBAL_FLAGS);
1745 if (flags == MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS)
1746 return 0;
1747
1748 reason = (flags == MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL)
1749 ? "system-level assertion"
1750 : (flags == MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL)
1751 ? "thread-level assertion"
1752 : (flags == MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED)
1753 ? "watchdog reset"
1754 : "unknown assertion";
1755 netif_err(efx, hw, efx->net_dev,
1756 "MCPU %s at PC = 0x%.8x in thread 0x%.8x\n", reason,
1757 MCDI_DWORD(outbuf, GET_ASSERTS_OUT_SAVED_PC_OFFS),
1758 MCDI_DWORD(outbuf, GET_ASSERTS_OUT_THREAD_OFFS));
1759
1760
1761 for (index = 0;
1762 index < MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_NUM;
1763 index++)
1764 netif_err(efx, hw, efx->net_dev, "R%.2d (?): 0x%.8x\n",
1765 1 + index,
1766 MCDI_ARRAY_DWORD(outbuf, GET_ASSERTS_OUT_GP_REGS_OFFS,
1767 index));
1768
1769 return 1;
1770}
1771
1772static int efx_mcdi_exit_assertion(struct efx_nic *efx)
1773{
1774 MCDI_DECLARE_BUF(inbuf, MC_CMD_REBOOT_IN_LEN);
1775 int rc;
1776
1777
1778
1779
1780
1781
1782
1783 BUILD_BUG_ON(MC_CMD_REBOOT_OUT_LEN != 0);
1784 MCDI_SET_DWORD(inbuf, REBOOT_IN_FLAGS,
1785 MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION);
1786 rc = efx_mcdi_rpc_quiet(efx, MC_CMD_REBOOT, inbuf, MC_CMD_REBOOT_IN_LEN,
1787 NULL, 0, NULL);
1788 if (rc == -EIO)
1789 rc = 0;
1790 if (rc)
1791 efx_mcdi_display_error(efx, MC_CMD_REBOOT, MC_CMD_REBOOT_IN_LEN,
1792 NULL, 0, rc);
1793 return rc;
1794}
1795
1796int efx_mcdi_handle_assertion(struct efx_nic *efx)
1797{
1798 int rc;
1799
1800 rc = efx_mcdi_read_assertion(efx);
1801 if (rc <= 0)
1802 return rc;
1803
1804 return efx_mcdi_exit_assertion(efx);
1805}
1806
1807void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
1808{
1809 MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_ID_LED_IN_LEN);
1810 int rc;
1811
1812 BUILD_BUG_ON(EFX_LED_OFF != MC_CMD_LED_OFF);
1813 BUILD_BUG_ON(EFX_LED_ON != MC_CMD_LED_ON);
1814 BUILD_BUG_ON(EFX_LED_DEFAULT != MC_CMD_LED_DEFAULT);
1815
1816 BUILD_BUG_ON(MC_CMD_SET_ID_LED_OUT_LEN != 0);
1817
1818 MCDI_SET_DWORD(inbuf, SET_ID_LED_IN_STATE, mode);
1819
1820 rc = efx_mcdi_rpc(efx, MC_CMD_SET_ID_LED, inbuf, sizeof(inbuf),
1821 NULL, 0, NULL);
1822}
1823
1824static int efx_mcdi_reset_func(struct efx_nic *efx)
1825{
1826 MCDI_DECLARE_BUF(inbuf, MC_CMD_ENTITY_RESET_IN_LEN);
1827 int rc;
1828
1829 BUILD_BUG_ON(MC_CMD_ENTITY_RESET_OUT_LEN != 0);
1830 MCDI_POPULATE_DWORD_1(inbuf, ENTITY_RESET_IN_FLAG,
1831 ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1);
1832 rc = efx_mcdi_rpc(efx, MC_CMD_ENTITY_RESET, inbuf, sizeof(inbuf),
1833 NULL, 0, NULL);
1834 return rc;
1835}
1836
1837static int efx_mcdi_reset_mc(struct efx_nic *efx)
1838{
1839 MCDI_DECLARE_BUF(inbuf, MC_CMD_REBOOT_IN_LEN);
1840 int rc;
1841
1842 BUILD_BUG_ON(MC_CMD_REBOOT_OUT_LEN != 0);
1843 MCDI_SET_DWORD(inbuf, REBOOT_IN_FLAGS, 0);
1844 rc = efx_mcdi_rpc(efx, MC_CMD_REBOOT, inbuf, sizeof(inbuf),
1845 NULL, 0, NULL);
1846
1847 if (rc == -EIO)
1848 return 0;
1849 if (rc == 0)
1850 rc = -EIO;
1851 return rc;
1852}
1853
1854enum reset_type efx_mcdi_map_reset_reason(enum reset_type reason)
1855{
1856 return RESET_TYPE_RECOVER_OR_ALL;
1857}
1858
1859int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method)
1860{
1861 int rc;
1862
1863
1864 if (method == RESET_TYPE_MCDI_TIMEOUT) {
1865 rc = pci_reset_function(efx->pci_dev);
1866 if (rc)
1867 return rc;
1868
1869 if (efx->mcdi) {
1870 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
1871 mcdi->mode = MCDI_MODE_POLL;
1872 }
1873 return 0;
1874 }
1875
1876
1877 rc = efx_mcdi_handle_assertion(efx);
1878 if (rc)
1879 return rc;
1880
1881 if (method == RESET_TYPE_DATAPATH)
1882 return 0;
1883 else if (method == RESET_TYPE_WORLD)
1884 return efx_mcdi_reset_mc(efx);
1885 else
1886 return efx_mcdi_reset_func(efx);
1887}
1888
1889static int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type,
1890 const u8 *mac, int *id_out)
1891{
1892 MCDI_DECLARE_BUF(inbuf, MC_CMD_WOL_FILTER_SET_IN_LEN);
1893 MCDI_DECLARE_BUF(outbuf, MC_CMD_WOL_FILTER_SET_OUT_LEN);
1894 size_t outlen;
1895 int rc;
1896
1897 MCDI_SET_DWORD(inbuf, WOL_FILTER_SET_IN_WOL_TYPE, type);
1898 MCDI_SET_DWORD(inbuf, WOL_FILTER_SET_IN_FILTER_MODE,
1899 MC_CMD_FILTER_MODE_SIMPLE);
1900 ether_addr_copy(MCDI_PTR(inbuf, WOL_FILTER_SET_IN_MAGIC_MAC), mac);
1901
1902 rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_SET, inbuf, sizeof(inbuf),
1903 outbuf, sizeof(outbuf), &outlen);
1904 if (rc)
1905 goto fail;
1906
1907 if (outlen < MC_CMD_WOL_FILTER_SET_OUT_LEN) {
1908 rc = -EIO;
1909 goto fail;
1910 }
1911
1912 *id_out = (int)MCDI_DWORD(outbuf, WOL_FILTER_SET_OUT_FILTER_ID);
1913
1914 return 0;
1915
1916fail:
1917 *id_out = -1;
1918 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
1919 return rc;
1920
1921}
1922
1923
1924int
1925efx_mcdi_wol_filter_set_magic(struct efx_nic *efx, const u8 *mac, int *id_out)
1926{
1927 return efx_mcdi_wol_filter_set(efx, MC_CMD_WOL_TYPE_MAGIC, mac, id_out);
1928}
1929
1930
1931int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out)
1932{
1933 MCDI_DECLARE_BUF(outbuf, MC_CMD_WOL_FILTER_GET_OUT_LEN);
1934 size_t outlen;
1935 int rc;
1936
1937 rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_GET, NULL, 0,
1938 outbuf, sizeof(outbuf), &outlen);
1939 if (rc)
1940 goto fail;
1941
1942 if (outlen < MC_CMD_WOL_FILTER_GET_OUT_LEN) {
1943 rc = -EIO;
1944 goto fail;
1945 }
1946
1947 *id_out = (int)MCDI_DWORD(outbuf, WOL_FILTER_GET_OUT_FILTER_ID);
1948
1949 return 0;
1950
1951fail:
1952 *id_out = -1;
1953 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
1954 return rc;
1955}
1956
1957
1958int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id)
1959{
1960 MCDI_DECLARE_BUF(inbuf, MC_CMD_WOL_FILTER_REMOVE_IN_LEN);
1961 int rc;
1962
1963 MCDI_SET_DWORD(inbuf, WOL_FILTER_REMOVE_IN_FILTER_ID, (u32)id);
1964
1965 rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_REMOVE, inbuf, sizeof(inbuf),
1966 NULL, 0, NULL);
1967 return rc;
1968}
1969
1970int efx_mcdi_flush_rxqs(struct efx_nic *efx)
1971{
1972 struct efx_channel *channel;
1973 struct efx_rx_queue *rx_queue;
1974 MCDI_DECLARE_BUF(inbuf,
1975 MC_CMD_FLUSH_RX_QUEUES_IN_LEN(EFX_MAX_CHANNELS));
1976 int rc, count;
1977
1978 BUILD_BUG_ON(EFX_MAX_CHANNELS >
1979 MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MAXNUM);
1980
1981 count = 0;
1982 efx_for_each_channel(channel, efx) {
1983 efx_for_each_channel_rx_queue(rx_queue, channel) {
1984 if (rx_queue->flush_pending) {
1985 rx_queue->flush_pending = false;
1986 atomic_dec(&efx->rxq_flush_pending);
1987 MCDI_SET_ARRAY_DWORD(
1988 inbuf, FLUSH_RX_QUEUES_IN_QID_OFST,
1989 count, efx_rx_queue_index(rx_queue));
1990 count++;
1991 }
1992 }
1993 }
1994
1995 rc = efx_mcdi_rpc(efx, MC_CMD_FLUSH_RX_QUEUES, inbuf,
1996 MC_CMD_FLUSH_RX_QUEUES_IN_LEN(count), NULL, 0, NULL);
1997 WARN_ON(rc < 0);
1998
1999 return rc;
2000}
2001
2002int efx_mcdi_wol_filter_reset(struct efx_nic *efx)
2003{
2004 int rc;
2005
2006 rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_RESET, NULL, 0, NULL, 0, NULL);
2007 return rc;
2008}
2009
2010int efx_mcdi_set_workaround(struct efx_nic *efx, u32 type, bool enabled,
2011 unsigned int *flags)
2012{
2013 MCDI_DECLARE_BUF(inbuf, MC_CMD_WORKAROUND_IN_LEN);
2014 MCDI_DECLARE_BUF(outbuf, MC_CMD_WORKAROUND_EXT_OUT_LEN);
2015 size_t outlen;
2016 int rc;
2017
2018 BUILD_BUG_ON(MC_CMD_WORKAROUND_OUT_LEN != 0);
2019 MCDI_SET_DWORD(inbuf, WORKAROUND_IN_TYPE, type);
2020 MCDI_SET_DWORD(inbuf, WORKAROUND_IN_ENABLED, enabled);
2021 rc = efx_mcdi_rpc(efx, MC_CMD_WORKAROUND, inbuf, sizeof(inbuf),
2022 outbuf, sizeof(outbuf), &outlen);
2023 if (rc)
2024 return rc;
2025
2026 if (!flags)
2027 return 0;
2028
2029 if (outlen >= MC_CMD_WORKAROUND_EXT_OUT_LEN)
2030 *flags = MCDI_DWORD(outbuf, WORKAROUND_EXT_OUT_FLAGS);
2031 else
2032 *flags = 0;
2033
2034 return 0;
2035}
2036
2037int efx_mcdi_get_workarounds(struct efx_nic *efx, unsigned int *impl_out,
2038 unsigned int *enabled_out)
2039{
2040 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_WORKAROUNDS_OUT_LEN);
2041 size_t outlen;
2042 int rc;
2043
2044 rc = efx_mcdi_rpc(efx, MC_CMD_GET_WORKAROUNDS, NULL, 0,
2045 outbuf, sizeof(outbuf), &outlen);
2046 if (rc)
2047 goto fail;
2048
2049 if (outlen < MC_CMD_GET_WORKAROUNDS_OUT_LEN) {
2050 rc = -EIO;
2051 goto fail;
2052 }
2053
2054 if (impl_out)
2055 *impl_out = MCDI_DWORD(outbuf, GET_WORKAROUNDS_OUT_IMPLEMENTED);
2056
2057 if (enabled_out)
2058 *enabled_out = MCDI_DWORD(outbuf, GET_WORKAROUNDS_OUT_ENABLED);
2059
2060 return 0;
2061
2062fail:
2063
2064
2065
2066 netif_cond_dbg(efx, hw, efx->net_dev, rc == -ENOSYS, err,
2067 "%s: failed rc=%d\n", __func__, rc);
2068 return rc;
2069}
2070
2071#ifdef CONFIG_SFC_MTD
2072
2073#define EFX_MCDI_NVRAM_LEN_MAX 128
2074
2075static int efx_mcdi_nvram_update_start(struct efx_nic *efx, unsigned int type)
2076{
2077 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_START_IN_LEN);
2078 int rc;
2079
2080 MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_START_IN_TYPE, type);
2081
2082 BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_START_OUT_LEN != 0);
2083
2084 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_START, inbuf, sizeof(inbuf),
2085 NULL, 0, NULL);
2086 return rc;
2087}
2088
2089static int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type,
2090 loff_t offset, u8 *buffer, size_t length)
2091{
2092 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_READ_IN_LEN);
2093 MCDI_DECLARE_BUF(outbuf,
2094 MC_CMD_NVRAM_READ_OUT_LEN(EFX_MCDI_NVRAM_LEN_MAX));
2095 size_t outlen;
2096 int rc;
2097
2098 MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_TYPE, type);
2099 MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_OFFSET, offset);
2100 MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_LENGTH, length);
2101
2102 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_READ, inbuf, sizeof(inbuf),
2103 outbuf, sizeof(outbuf), &outlen);
2104 if (rc)
2105 return rc;
2106
2107 memcpy(buffer, MCDI_PTR(outbuf, NVRAM_READ_OUT_READ_BUFFER), length);
2108 return 0;
2109}
2110
2111static int efx_mcdi_nvram_write(struct efx_nic *efx, unsigned int type,
2112 loff_t offset, const u8 *buffer, size_t length)
2113{
2114 MCDI_DECLARE_BUF(inbuf,
2115 MC_CMD_NVRAM_WRITE_IN_LEN(EFX_MCDI_NVRAM_LEN_MAX));
2116 int rc;
2117
2118 MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_TYPE, type);
2119 MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_OFFSET, offset);
2120 MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_LENGTH, length);
2121 memcpy(MCDI_PTR(inbuf, NVRAM_WRITE_IN_WRITE_BUFFER), buffer, length);
2122
2123 BUILD_BUG_ON(MC_CMD_NVRAM_WRITE_OUT_LEN != 0);
2124
2125 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_WRITE, inbuf,
2126 ALIGN(MC_CMD_NVRAM_WRITE_IN_LEN(length), 4),
2127 NULL, 0, NULL);
2128 return rc;
2129}
2130
2131static int efx_mcdi_nvram_erase(struct efx_nic *efx, unsigned int type,
2132 loff_t offset, size_t length)
2133{
2134 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_ERASE_IN_LEN);
2135 int rc;
2136
2137 MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_TYPE, type);
2138 MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_OFFSET, offset);
2139 MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_LENGTH, length);
2140
2141 BUILD_BUG_ON(MC_CMD_NVRAM_ERASE_OUT_LEN != 0);
2142
2143 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_ERASE, inbuf, sizeof(inbuf),
2144 NULL, 0, NULL);
2145 return rc;
2146}
2147
2148static int efx_mcdi_nvram_update_finish(struct efx_nic *efx, unsigned int type)
2149{
2150 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN);
2151 int rc;
2152
2153 MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_FINISH_IN_TYPE, type);
2154
2155 BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN != 0);
2156
2157 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_FINISH, inbuf, sizeof(inbuf),
2158 NULL, 0, NULL);
2159 return rc;
2160}
2161
2162int efx_mcdi_mtd_read(struct mtd_info *mtd, loff_t start,
2163 size_t len, size_t *retlen, u8 *buffer)
2164{
2165 struct efx_mcdi_mtd_partition *part = to_efx_mcdi_mtd_partition(mtd);
2166 struct efx_nic *efx = mtd->priv;
2167 loff_t offset = start;
2168 loff_t end = min_t(loff_t, start + len, mtd->size);
2169 size_t chunk;
2170 int rc = 0;
2171
2172 while (offset < end) {
2173 chunk = min_t(size_t, end - offset, EFX_MCDI_NVRAM_LEN_MAX);
2174 rc = efx_mcdi_nvram_read(efx, part->nvram_type, offset,
2175 buffer, chunk);
2176 if (rc)
2177 goto out;
2178 offset += chunk;
2179 buffer += chunk;
2180 }
2181out:
2182 *retlen = offset - start;
2183 return rc;
2184}
2185
2186int efx_mcdi_mtd_erase(struct mtd_info *mtd, loff_t start, size_t len)
2187{
2188 struct efx_mcdi_mtd_partition *part = to_efx_mcdi_mtd_partition(mtd);
2189 struct efx_nic *efx = mtd->priv;
2190 loff_t offset = start & ~((loff_t)(mtd->erasesize - 1));
2191 loff_t end = min_t(loff_t, start + len, mtd->size);
2192 size_t chunk = part->common.mtd.erasesize;
2193 int rc = 0;
2194
2195 if (!part->updating) {
2196 rc = efx_mcdi_nvram_update_start(efx, part->nvram_type);
2197 if (rc)
2198 goto out;
2199 part->updating = true;
2200 }
2201
2202
2203
2204
2205 while (offset < end) {
2206 rc = efx_mcdi_nvram_erase(efx, part->nvram_type, offset,
2207 chunk);
2208 if (rc)
2209 goto out;
2210 offset += chunk;
2211 }
2212out:
2213 return rc;
2214}
2215
2216int efx_mcdi_mtd_write(struct mtd_info *mtd, loff_t start,
2217 size_t len, size_t *retlen, const u8 *buffer)
2218{
2219 struct efx_mcdi_mtd_partition *part = to_efx_mcdi_mtd_partition(mtd);
2220 struct efx_nic *efx = mtd->priv;
2221 loff_t offset = start;
2222 loff_t end = min_t(loff_t, start + len, mtd->size);
2223 size_t chunk;
2224 int rc = 0;
2225
2226 if (!part->updating) {
2227 rc = efx_mcdi_nvram_update_start(efx, part->nvram_type);
2228 if (rc)
2229 goto out;
2230 part->updating = true;
2231 }
2232
2233 while (offset < end) {
2234 chunk = min_t(size_t, end - offset, EFX_MCDI_NVRAM_LEN_MAX);
2235 rc = efx_mcdi_nvram_write(efx, part->nvram_type, offset,
2236 buffer, chunk);
2237 if (rc)
2238 goto out;
2239 offset += chunk;
2240 buffer += chunk;
2241 }
2242out:
2243 *retlen = offset - start;
2244 return rc;
2245}
2246
2247int efx_mcdi_mtd_sync(struct mtd_info *mtd)
2248{
2249 struct efx_mcdi_mtd_partition *part = to_efx_mcdi_mtd_partition(mtd);
2250 struct efx_nic *efx = mtd->priv;
2251 int rc = 0;
2252
2253 if (part->updating) {
2254 part->updating = false;
2255 rc = efx_mcdi_nvram_update_finish(efx, part->nvram_type);
2256 }
2257
2258 return rc;
2259}
2260
2261void efx_mcdi_mtd_rename(struct efx_mtd_partition *part)
2262{
2263 struct efx_mcdi_mtd_partition *mcdi_part =
2264 container_of(part, struct efx_mcdi_mtd_partition, common);
2265 struct efx_nic *efx = part->mtd.priv;
2266
2267 snprintf(part->name, sizeof(part->name), "%s %s:%02x",
2268 efx->name, part->type_name, mcdi_part->fw_subtype);
2269}
2270
2271#endif
2272