blob: d7d3a8a9cd15c6dba2086713ffa717bda4671e06 [file] [log] [blame]
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001/****************************************************************************
2 * Driver for Solarflare Solarstorm network controllers and boards
Ben Hutchings0a6f40c2011-02-25 00:01:34 +00003 * Copyright 2008-2011 Solarflare Communications Inc.
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00004 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published
7 * by the Free Software Foundation, incorporated herein by reference.
8 */
9
10#include <linux/delay.h>
11#include "net_driver.h"
12#include "nic.h"
13#include "io.h"
14#include "regs.h"
15#include "mcdi_pcol.h"
16#include "phy.h"
17
18/**************************************************************************
19 *
20 * Management-Controller-to-Driver Interface
21 *
22 **************************************************************************
23 */
24
Ben Hutchingsebf98e72012-12-01 02:21:17 +000025#define MCDI_RPC_TIMEOUT (10 * HZ)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +000026
Ben Hutchings3f713bf2011-12-20 23:39:31 +000027/* A reboot/assertion causes the MCDI status word to be set after the
28 * command word is set or a REBOOT event is sent. If we notice a reboot
29 * via these mechanisms then wait 10ms for the status word to be set. */
30#define MCDI_STATUS_DELAY_US 100
31#define MCDI_STATUS_DELAY_COUNT 100
32#define MCDI_STATUS_SLEEP_MS \
33 (MCDI_STATUS_DELAY_US * MCDI_STATUS_DELAY_COUNT / 1000)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +000034
35#define SEQ_MASK \
36 EFX_MASK32(EFX_WIDTH(MCDI_HEADER_SEQ))
37
38static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx)
39{
Ben Hutchingsf3ad5002012-09-18 02:33:56 +010040 EFX_BUG_ON_PARANOID(!efx->mcdi);
41 return &efx->mcdi->iface;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +000042}
43
Ben Hutchingsf073dde2012-09-18 02:33:55 +010044int efx_mcdi_init(struct efx_nic *efx)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +000045{
46 struct efx_mcdi_iface *mcdi;
47
Ben Hutchingsf3ad5002012-09-18 02:33:56 +010048 efx->mcdi = kzalloc(sizeof(*efx->mcdi), GFP_KERNEL);
49 if (!efx->mcdi)
50 return -ENOMEM;
51
Ben Hutchingsafd4aea2009-11-29 15:15:25 +000052 mcdi = efx_mcdi(efx);
53 init_waitqueue_head(&mcdi->wq);
54 spin_lock_init(&mcdi->iface_lock);
55 atomic_set(&mcdi->state, MCDI_STATE_QUIESCENT);
56 mcdi->mode = MCDI_MODE_POLL;
57
58 (void) efx_mcdi_poll_reboot(efx);
Ben Hutchingsf073dde2012-09-18 02:33:55 +010059
60 /* Recover from a failed assertion before probing */
61 return efx_mcdi_handle_assertion(efx);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +000062}
63
Ben Hutchingsf3ad5002012-09-18 02:33:56 +010064void efx_mcdi_fini(struct efx_nic *efx)
65{
66 BUG_ON(efx->mcdi &&
67 atomic_read(&efx->mcdi->iface.state) != MCDI_STATE_QUIESCENT);
68 kfree(efx->mcdi);
69}
70
Ben Hutchingsafd4aea2009-11-29 15:15:25 +000071static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
Ben Hutchings9528b922012-09-14 17:31:41 +010072 const efx_dword_t *inbuf, size_t inlen)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +000073{
74 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +000075 efx_dword_t hdr;
76 u32 xflags, seqno;
77
78 BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
Ben Hutchings9528b922012-09-14 17:31:41 +010079 BUG_ON(inlen > MCDI_CTL_SDU_LEN_MAX_V1);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +000080
81 seqno = mcdi->seqno & SEQ_MASK;
82 xflags = 0;
83 if (mcdi->mode == MCDI_MODE_EVENTS)
84 xflags |= MCDI_HEADER_XFLAGS_EVREQ;
85
86 EFX_POPULATE_DWORD_6(hdr,
87 MCDI_HEADER_RESPONSE, 0,
88 MCDI_HEADER_RESYNC, 1,
89 MCDI_HEADER_CODE, cmd,
90 MCDI_HEADER_DATALEN, inlen,
91 MCDI_HEADER_SEQ, seqno,
92 MCDI_HEADER_XFLAGS, xflags);
93
Ben Hutchingsf3ad5002012-09-18 02:33:56 +010094 efx->type->mcdi_request(efx, &hdr, 4, inbuf, inlen);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +000095}
96
Ben Hutchings9528b922012-09-14 17:31:41 +010097static void
98efx_mcdi_copyout(struct efx_nic *efx, efx_dword_t *outbuf, size_t outlen)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +000099{
100 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000101
102 BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
Ben Hutchings9528b922012-09-14 17:31:41 +0100103 BUG_ON(outlen > MCDI_CTL_SDU_LEN_MAX_V1);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000104
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100105 efx->type->mcdi_read_response(efx, outbuf, 4, outlen);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000106}
107
108static int efx_mcdi_poll(struct efx_nic *efx)
109{
110 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
Ben Hutchingsebf98e72012-12-01 02:21:17 +0000111 unsigned long time, finish;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000112 unsigned int respseq, respcmd, error;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000113 unsigned int rc, spins;
114 efx_dword_t reg;
115
116 /* Check for a reboot atomically with respect to efx_mcdi_copyout() */
Ben Hutchingse0bf54c2010-02-19 13:29:27 +0000117 rc = -efx_mcdi_poll_reboot(efx);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000118 if (rc)
119 goto out;
120
121 /* Poll for completion. Poll quickly (once a us) for the 1st jiffy,
122 * because generally mcdi responses are fast. After that, back off
123 * and poll once a jiffy (approximately)
124 */
125 spins = TICK_USEC;
Ben Hutchingsebf98e72012-12-01 02:21:17 +0000126 finish = jiffies + MCDI_RPC_TIMEOUT;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000127
128 while (1) {
129 if (spins != 0) {
130 --spins;
131 udelay(1);
Ben Hutchings55029c12010-01-13 04:34:25 +0000132 } else {
133 schedule_timeout_uninterruptible(1);
134 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000135
Ben Hutchingsebf98e72012-12-01 02:21:17 +0000136 time = jiffies;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000137
Ben Hutchings86c432c2011-09-01 12:09:29 +0000138 rmb();
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100139 if (efx->type->mcdi_poll_response(efx))
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000140 break;
141
Ben Hutchingsebf98e72012-12-01 02:21:17 +0000142 if (time_after(time, finish))
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000143 return -ETIMEDOUT;
144 }
145
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100146 efx->type->mcdi_read_response(efx, &reg, 0, 4);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000147 mcdi->resplen = EFX_DWORD_FIELD(reg, MCDI_HEADER_DATALEN);
148 respseq = EFX_DWORD_FIELD(reg, MCDI_HEADER_SEQ);
149 respcmd = EFX_DWORD_FIELD(reg, MCDI_HEADER_CODE);
150 error = EFX_DWORD_FIELD(reg, MCDI_HEADER_ERROR);
151
152 if (error && mcdi->resplen == 0) {
Ben Hutchings62776d02010-06-23 11:30:07 +0000153 netif_err(efx, hw, efx->net_dev, "MC rebooted\n");
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000154 rc = EIO;
155 } else if ((respseq ^ mcdi->seqno) & SEQ_MASK) {
Ben Hutchings62776d02010-06-23 11:30:07 +0000156 netif_err(efx, hw, efx->net_dev,
157 "MC response mismatch tx seq 0x%x rx seq 0x%x\n",
158 respseq, mcdi->seqno);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000159 rc = EIO;
160 } else if (error) {
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100161 efx->type->mcdi_read_response(efx, &reg, 4, 4);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000162 switch (EFX_DWORD_FIELD(reg, EFX_DWORD_0)) {
163#define TRANSLATE_ERROR(name) \
164 case MC_CMD_ERR_ ## name: \
165 rc = name; \
166 break
167 TRANSLATE_ERROR(ENOENT);
168 TRANSLATE_ERROR(EINTR);
169 TRANSLATE_ERROR(EACCES);
170 TRANSLATE_ERROR(EBUSY);
171 TRANSLATE_ERROR(EINVAL);
172 TRANSLATE_ERROR(EDEADLK);
173 TRANSLATE_ERROR(ENOSYS);
174 TRANSLATE_ERROR(ETIME);
175#undef TRANSLATE_ERROR
176 default:
177 rc = EIO;
178 break;
179 }
180 } else
181 rc = 0;
182
183out:
184 mcdi->resprc = rc;
185 if (rc)
186 mcdi->resplen = 0;
187
188 /* Return rc=0 like wait_event_timeout() */
189 return 0;
190}
191
Ben Hutchings876be082012-10-01 20:58:35 +0100192/* Test and clear MC-rebooted flag for this port/function; reset
193 * software state as necessary.
194 */
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000195int efx_mcdi_poll_reboot(struct efx_nic *efx)
196{
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100197 int rc;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000198
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100199 if (!efx->mcdi)
200 return 0;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000201
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100202 rc = efx->type->mcdi_poll_reboot(efx);
203 if (!rc)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000204 return 0;
205
Ben Hutchings876be082012-10-01 20:58:35 +0100206 /* MAC statistics have been cleared on the NIC; clear our copy
207 * so that efx_update_diff_stat() can continue to work.
208 */
209 memset(&efx->mac_stats, 0, sizeof(efx->mac_stats));
210
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100211 return rc;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000212}
213
214static void efx_mcdi_acquire(struct efx_mcdi_iface *mcdi)
215{
216 /* Wait until the interface becomes QUIESCENT and we win the race
217 * to mark it RUNNING. */
218 wait_event(mcdi->wq,
219 atomic_cmpxchg(&mcdi->state,
220 MCDI_STATE_QUIESCENT,
221 MCDI_STATE_RUNNING)
222 == MCDI_STATE_QUIESCENT);
223}
224
225static int efx_mcdi_await_completion(struct efx_nic *efx)
226{
227 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
228
229 if (wait_event_timeout(
230 mcdi->wq,
231 atomic_read(&mcdi->state) == MCDI_STATE_COMPLETED,
Ben Hutchingsebf98e72012-12-01 02:21:17 +0000232 MCDI_RPC_TIMEOUT) == 0)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000233 return -ETIMEDOUT;
234
235 /* Check if efx_mcdi_set_mode() switched us back to polled completions.
236 * In which case, poll for completions directly. If efx_mcdi_ev_cpl()
237 * completed the request first, then we'll just end up completing the
238 * request again, which is safe.
239 *
240 * We need an smp_rmb() to synchronise with efx_mcdi_mode_poll(), which
241 * wait_event_timeout() implicitly provides.
242 */
243 if (mcdi->mode == MCDI_MODE_POLL)
244 return efx_mcdi_poll(efx);
245
246 return 0;
247}
248
249static bool efx_mcdi_complete(struct efx_mcdi_iface *mcdi)
250{
251 /* If the interface is RUNNING, then move to COMPLETED and wake any
252 * waiters. If the interface isn't in RUNNING then we've received a
253 * duplicate completion after we've already transitioned back to
254 * QUIESCENT. [A subsequent invocation would increment seqno, so would
255 * have failed the seqno check].
256 */
257 if (atomic_cmpxchg(&mcdi->state,
258 MCDI_STATE_RUNNING,
259 MCDI_STATE_COMPLETED) == MCDI_STATE_RUNNING) {
260 wake_up(&mcdi->wq);
261 return true;
262 }
263
264 return false;
265}
266
267static void efx_mcdi_release(struct efx_mcdi_iface *mcdi)
268{
269 atomic_set(&mcdi->state, MCDI_STATE_QUIESCENT);
270 wake_up(&mcdi->wq);
271}
272
273static void efx_mcdi_ev_cpl(struct efx_nic *efx, unsigned int seqno,
274 unsigned int datalen, unsigned int errno)
275{
276 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
277 bool wake = false;
278
279 spin_lock(&mcdi->iface_lock);
280
281 if ((seqno ^ mcdi->seqno) & SEQ_MASK) {
282 if (mcdi->credits)
283 /* The request has been cancelled */
284 --mcdi->credits;
285 else
Ben Hutchings62776d02010-06-23 11:30:07 +0000286 netif_err(efx, hw, efx->net_dev,
287 "MC response mismatch tx seq 0x%x rx "
288 "seq 0x%x\n", seqno, mcdi->seqno);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000289 } else {
290 mcdi->resprc = errno;
291 mcdi->resplen = datalen;
292
293 wake = true;
294 }
295
296 spin_unlock(&mcdi->iface_lock);
297
298 if (wake)
299 efx_mcdi_complete(mcdi);
300}
301
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000302int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd,
Ben Hutchings9528b922012-09-14 17:31:41 +0100303 const efx_dword_t *inbuf, size_t inlen,
304 efx_dword_t *outbuf, size_t outlen,
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000305 size_t *outlen_actual)
306{
Stuart Hodgsonc3cba722012-07-16 17:40:47 +0100307 efx_mcdi_rpc_start(efx, cmd, inbuf, inlen);
308 return efx_mcdi_rpc_finish(efx, cmd, inlen,
309 outbuf, outlen, outlen_actual);
310}
311
Ben Hutchings9528b922012-09-14 17:31:41 +0100312void efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd,
313 const efx_dword_t *inbuf, size_t inlen)
Stuart Hodgsonc3cba722012-07-16 17:40:47 +0100314{
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000315 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
Stuart Hodgsonc3cba722012-07-16 17:40:47 +0100316
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000317 efx_mcdi_acquire(mcdi);
318
319 /* Serialise with efx_mcdi_ev_cpl() and efx_mcdi_ev_death() */
320 spin_lock_bh(&mcdi->iface_lock);
321 ++mcdi->seqno;
322 spin_unlock_bh(&mcdi->iface_lock);
323
324 efx_mcdi_copyin(efx, cmd, inbuf, inlen);
Stuart Hodgsonc3cba722012-07-16 17:40:47 +0100325}
326
327int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
Ben Hutchings9528b922012-09-14 17:31:41 +0100328 efx_dword_t *outbuf, size_t outlen,
329 size_t *outlen_actual)
Stuart Hodgsonc3cba722012-07-16 17:40:47 +0100330{
331 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
332 int rc;
333
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000334 if (mcdi->mode == MCDI_MODE_POLL)
335 rc = efx_mcdi_poll(efx);
336 else
337 rc = efx_mcdi_await_completion(efx);
338
339 if (rc != 0) {
340 /* Close the race with efx_mcdi_ev_cpl() executing just too late
341 * and completing a request we've just cancelled, by ensuring
342 * that the seqno check therein fails.
343 */
344 spin_lock_bh(&mcdi->iface_lock);
345 ++mcdi->seqno;
346 ++mcdi->credits;
347 spin_unlock_bh(&mcdi->iface_lock);
348
Ben Hutchings62776d02010-06-23 11:30:07 +0000349 netif_err(efx, hw, efx->net_dev,
350 "MC command 0x%x inlen %d mode %d timed out\n",
351 cmd, (int)inlen, mcdi->mode);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000352 } else {
353 size_t resplen;
354
355 /* At the very least we need a memory barrier here to ensure
356 * we pick up changes from efx_mcdi_ev_cpl(). Protect against
357 * a spurious efx_mcdi_ev_cpl() running concurrently by
358 * acquiring the iface_lock. */
359 spin_lock_bh(&mcdi->iface_lock);
360 rc = -mcdi->resprc;
361 resplen = mcdi->resplen;
362 spin_unlock_bh(&mcdi->iface_lock);
363
364 if (rc == 0) {
365 efx_mcdi_copyout(efx, outbuf,
Ben Hutchings9528b922012-09-14 17:31:41 +0100366 min(outlen, mcdi->resplen));
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000367 if (outlen_actual != NULL)
368 *outlen_actual = resplen;
369 } else if (cmd == MC_CMD_REBOOT && rc == -EIO)
370 ; /* Don't reset if MC_CMD_REBOOT returns EIO */
371 else if (rc == -EIO || rc == -EINTR) {
Ben Hutchings62776d02010-06-23 11:30:07 +0000372 netif_err(efx, hw, efx->net_dev, "MC fatal error %d\n",
373 -rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000374 efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE);
375 } else
Ben Hutchingsf18ca362010-12-02 13:46:09 +0000376 netif_dbg(efx, hw, efx->net_dev,
Ben Hutchings62776d02010-06-23 11:30:07 +0000377 "MC command 0x%x inlen %d failed rc=%d\n",
378 cmd, (int)inlen, -rc);
Ben Hutchings3f713bf2011-12-20 23:39:31 +0000379
380 if (rc == -EIO || rc == -EINTR) {
381 msleep(MCDI_STATUS_SLEEP_MS);
382 efx_mcdi_poll_reboot(efx);
383 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000384 }
385
386 efx_mcdi_release(mcdi);
387 return rc;
388}
389
390void efx_mcdi_mode_poll(struct efx_nic *efx)
391{
392 struct efx_mcdi_iface *mcdi;
393
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100394 if (!efx->mcdi)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000395 return;
396
397 mcdi = efx_mcdi(efx);
398 if (mcdi->mode == MCDI_MODE_POLL)
399 return;
400
401 /* We can switch from event completion to polled completion, because
402 * mcdi requests are always completed in shared memory. We do this by
403 * switching the mode to POLL'd then completing the request.
404 * efx_mcdi_await_completion() will then call efx_mcdi_poll().
405 *
406 * We need an smp_wmb() to synchronise with efx_mcdi_await_completion(),
407 * which efx_mcdi_complete() provides for us.
408 */
409 mcdi->mode = MCDI_MODE_POLL;
410
411 efx_mcdi_complete(mcdi);
412}
413
414void efx_mcdi_mode_event(struct efx_nic *efx)
415{
416 struct efx_mcdi_iface *mcdi;
417
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100418 if (!efx->mcdi)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000419 return;
420
421 mcdi = efx_mcdi(efx);
422
423 if (mcdi->mode == MCDI_MODE_EVENTS)
424 return;
425
426 /* We can't switch from polled to event completion in the middle of a
427 * request, because the completion method is specified in the request.
428 * So acquire the interface to serialise the requestors. We don't need
429 * to acquire the iface_lock to change the mode here, but we do need a
430 * write memory barrier ensure that efx_mcdi_rpc() sees it, which
431 * efx_mcdi_acquire() provides.
432 */
433 efx_mcdi_acquire(mcdi);
434 mcdi->mode = MCDI_MODE_EVENTS;
435 efx_mcdi_release(mcdi);
436}
437
438static void efx_mcdi_ev_death(struct efx_nic *efx, int rc)
439{
440 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
441
442 /* If there is an outstanding MCDI request, it has been terminated
443 * either by a BADASSERT or REBOOT event. If the mcdi interface is
444 * in polled mode, then do nothing because the MC reboot handler will
445 * set the header correctly. However, if the mcdi interface is waiting
446 * for a CMDDONE event it won't receive it [and since all MCDI events
447 * are sent to the same queue, we can't be racing with
448 * efx_mcdi_ev_cpl()]
449 *
450 * There's a race here with efx_mcdi_rpc(), because we might receive
451 * a REBOOT event *before* the request has been copied out. In polled
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300452 * mode (during startup) this is irrelevant, because efx_mcdi_complete()
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000453 * is ignored. In event mode, this condition is just an edge-case of
454 * receiving a REBOOT event after posting the MCDI request. Did the mc
455 * reboot before or after the copyout? The best we can do always is
456 * just return failure.
457 */
458 spin_lock(&mcdi->iface_lock);
459 if (efx_mcdi_complete(mcdi)) {
460 if (mcdi->mode == MCDI_MODE_EVENTS) {
461 mcdi->resprc = rc;
462 mcdi->resplen = 0;
Steve Hodgson18e3ee22010-12-02 13:46:55 +0000463 ++mcdi->credits;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000464 }
Ben Hutchings3f713bf2011-12-20 23:39:31 +0000465 } else {
466 int count;
467
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000468 /* Nobody was waiting for an MCDI request, so trigger a reset */
469 efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE);
470
Ben Hutchings3f713bf2011-12-20 23:39:31 +0000471 /* Consume the status word since efx_mcdi_rpc_finish() won't */
472 for (count = 0; count < MCDI_STATUS_DELAY_COUNT; ++count) {
473 if (efx_mcdi_poll_reboot(efx))
474 break;
475 udelay(MCDI_STATUS_DELAY_US);
476 }
477 }
478
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000479 spin_unlock(&mcdi->iface_lock);
480}
481
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000482/* Called from falcon_process_eventq for MCDI events */
483void efx_mcdi_process_event(struct efx_channel *channel,
484 efx_qword_t *event)
485{
486 struct efx_nic *efx = channel->efx;
487 int code = EFX_QWORD_FIELD(*event, MCDI_EVENT_CODE);
488 u32 data = EFX_QWORD_FIELD(*event, MCDI_EVENT_DATA);
489
490 switch (code) {
491 case MCDI_EVENT_CODE_BADSSERT:
Ben Hutchings62776d02010-06-23 11:30:07 +0000492 netif_err(efx, hw, efx->net_dev,
493 "MC watchdog or assertion failure at 0x%x\n", data);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000494 efx_mcdi_ev_death(efx, EINTR);
495 break;
496
497 case MCDI_EVENT_CODE_PMNOTICE:
Ben Hutchings62776d02010-06-23 11:30:07 +0000498 netif_info(efx, wol, efx->net_dev, "MCDI PM event.\n");
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000499 break;
500
501 case MCDI_EVENT_CODE_CMDDONE:
502 efx_mcdi_ev_cpl(efx,
503 MCDI_EVENT_FIELD(*event, CMDDONE_SEQ),
504 MCDI_EVENT_FIELD(*event, CMDDONE_DATALEN),
505 MCDI_EVENT_FIELD(*event, CMDDONE_ERRNO));
506 break;
507
508 case MCDI_EVENT_CODE_LINKCHANGE:
509 efx_mcdi_process_link_change(efx, event);
510 break;
511 case MCDI_EVENT_CODE_SENSOREVT:
512 efx_mcdi_sensor_event(efx, event);
513 break;
514 case MCDI_EVENT_CODE_SCHEDERR:
Ben Hutchings62776d02010-06-23 11:30:07 +0000515 netif_info(efx, hw, efx->net_dev,
516 "MC Scheduler error address=0x%x\n", data);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000517 break;
518 case MCDI_EVENT_CODE_REBOOT:
Ben Hutchings62776d02010-06-23 11:30:07 +0000519 netif_info(efx, hw, efx->net_dev, "MC Reboot\n");
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000520 efx_mcdi_ev_death(efx, EIO);
521 break;
522 case MCDI_EVENT_CODE_MAC_STATS_DMA:
523 /* MAC stats are gather lazily. We can ignore this. */
524 break;
Ben Hutchingscd2d5b52012-02-14 00:48:07 +0000525 case MCDI_EVENT_CODE_FLR:
526 efx_sriov_flr(efx, MCDI_EVENT_FIELD(*event, FLR_VF));
527 break;
Stuart Hodgson7c236c42012-09-03 11:09:36 +0100528 case MCDI_EVENT_CODE_PTP_RX:
529 case MCDI_EVENT_CODE_PTP_FAULT:
530 case MCDI_EVENT_CODE_PTP_PPS:
531 efx_ptp_event(efx, event);
532 break;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000533
534 default:
Ben Hutchings62776d02010-06-23 11:30:07 +0000535 netif_err(efx, hw, efx->net_dev, "Unknown MCDI event 0x%x\n",
536 code);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000537 }
538}
539
540/**************************************************************************
541 *
542 * Specific request functions
543 *
544 **************************************************************************
545 */
546
Ben Hutchingse5f0fd22011-02-24 23:57:47 +0000547void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000548{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100549 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_VERSION_OUT_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000550 size_t outlength;
551 const __le16 *ver_words;
552 int rc;
553
554 BUILD_BUG_ON(MC_CMD_GET_VERSION_IN_LEN != 0);
555
556 rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, NULL, 0,
557 outbuf, sizeof(outbuf), &outlength);
558 if (rc)
559 goto fail;
560
Ben Hutchings05a93202011-12-20 00:44:06 +0000561 if (outlength < MC_CMD_GET_VERSION_OUT_LEN) {
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000562 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000563 goto fail;
564 }
565
566 ver_words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_OUT_VERSION);
Ben Hutchingse5f0fd22011-02-24 23:57:47 +0000567 snprintf(buf, len, "%u.%u.%u.%u",
568 le16_to_cpu(ver_words[0]), le16_to_cpu(ver_words[1]),
569 le16_to_cpu(ver_words[2]), le16_to_cpu(ver_words[3]));
570 return;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000571
572fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000573 netif_err(efx, probe, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingse5f0fd22011-02-24 23:57:47 +0000574 buf[0] = 0;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000575}
576
577int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
578 bool *was_attached)
579{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100580 MCDI_DECLARE_BUF(inbuf, MC_CMD_DRV_ATTACH_IN_LEN);
581 MCDI_DECLARE_BUF(outbuf, MC_CMD_DRV_ATTACH_OUT_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000582 size_t outlen;
583 int rc;
584
585 MCDI_SET_DWORD(inbuf, DRV_ATTACH_IN_NEW_STATE,
586 driver_operating ? 1 : 0);
587 MCDI_SET_DWORD(inbuf, DRV_ATTACH_IN_UPDATE, 1);
588
589 rc = efx_mcdi_rpc(efx, MC_CMD_DRV_ATTACH, inbuf, sizeof(inbuf),
590 outbuf, sizeof(outbuf), &outlen);
591 if (rc)
592 goto fail;
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000593 if (outlen < MC_CMD_DRV_ATTACH_OUT_LEN) {
594 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000595 goto fail;
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000596 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000597
598 if (was_attached != NULL)
599 *was_attached = MCDI_DWORD(outbuf, DRV_ATTACH_OUT_OLD_STATE);
600 return 0;
601
602fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000603 netif_err(efx, probe, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000604 return rc;
605}
606
607int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
Matthew Slattery6aa9c7f2010-07-14 15:36:19 +0100608 u16 *fw_subtype_list, u32 *capabilities)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000609{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100610 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_BOARD_CFG_OUT_LENMAX);
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +0100611 size_t outlen, i;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000612 int port_num = efx_port_num(efx);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000613 int rc;
614
615 BUILD_BUG_ON(MC_CMD_GET_BOARD_CFG_IN_LEN != 0);
616
617 rc = efx_mcdi_rpc(efx, MC_CMD_GET_BOARD_CFG, NULL, 0,
618 outbuf, sizeof(outbuf), &outlen);
619 if (rc)
620 goto fail;
621
Ben Hutchings05a93202011-12-20 00:44:06 +0000622 if (outlen < MC_CMD_GET_BOARD_CFG_OUT_LENMIN) {
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000623 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000624 goto fail;
625 }
626
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000627 if (mac_address)
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +0100628 memcpy(mac_address,
629 port_num ?
630 MCDI_PTR(outbuf, GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1) :
631 MCDI_PTR(outbuf, GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0),
632 ETH_ALEN);
Ben Hutchingsbfeed902012-09-07 00:58:10 +0100633 if (fw_subtype_list) {
Ben Hutchingsbfeed902012-09-07 00:58:10 +0100634 for (i = 0;
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +0100635 i < MCDI_VAR_ARRAY_LEN(outlen,
636 GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST);
637 i++)
638 fw_subtype_list[i] = MCDI_ARRAY_WORD(
639 outbuf, GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST, i);
640 for (; i < MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MAXNUM; i++)
641 fw_subtype_list[i] = 0;
Ben Hutchingsbfeed902012-09-07 00:58:10 +0100642 }
Matthew Slattery6aa9c7f2010-07-14 15:36:19 +0100643 if (capabilities) {
644 if (port_num)
645 *capabilities = MCDI_DWORD(outbuf,
646 GET_BOARD_CFG_OUT_CAPABILITIES_PORT1);
647 else
648 *capabilities = MCDI_DWORD(outbuf,
649 GET_BOARD_CFG_OUT_CAPABILITIES_PORT0);
650 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000651
652 return 0;
653
654fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000655 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d len=%d\n",
656 __func__, rc, (int)outlen);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000657
658 return rc;
659}
660
661int efx_mcdi_log_ctrl(struct efx_nic *efx, bool evq, bool uart, u32 dest_evq)
662{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100663 MCDI_DECLARE_BUF(inbuf, MC_CMD_LOG_CTRL_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000664 u32 dest = 0;
665 int rc;
666
667 if (uart)
668 dest |= MC_CMD_LOG_CTRL_IN_LOG_DEST_UART;
669 if (evq)
670 dest |= MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ;
671
672 MCDI_SET_DWORD(inbuf, LOG_CTRL_IN_LOG_DEST, dest);
673 MCDI_SET_DWORD(inbuf, LOG_CTRL_IN_LOG_DEST_EVQ, dest_evq);
674
675 BUILD_BUG_ON(MC_CMD_LOG_CTRL_OUT_LEN != 0);
676
677 rc = efx_mcdi_rpc(efx, MC_CMD_LOG_CTRL, inbuf, sizeof(inbuf),
678 NULL, 0, NULL);
679 if (rc)
680 goto fail;
681
682 return 0;
683
684fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000685 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000686 return rc;
687}
688
689int efx_mcdi_nvram_types(struct efx_nic *efx, u32 *nvram_types_out)
690{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100691 MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_TYPES_OUT_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000692 size_t outlen;
693 int rc;
694
695 BUILD_BUG_ON(MC_CMD_NVRAM_TYPES_IN_LEN != 0);
696
697 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_TYPES, NULL, 0,
698 outbuf, sizeof(outbuf), &outlen);
699 if (rc)
700 goto fail;
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000701 if (outlen < MC_CMD_NVRAM_TYPES_OUT_LEN) {
702 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000703 goto fail;
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000704 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000705
706 *nvram_types_out = MCDI_DWORD(outbuf, NVRAM_TYPES_OUT_TYPES);
707 return 0;
708
709fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000710 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
711 __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000712 return rc;
713}
714
715int efx_mcdi_nvram_info(struct efx_nic *efx, unsigned int type,
716 size_t *size_out, size_t *erase_size_out,
717 bool *protected_out)
718{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100719 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_INFO_IN_LEN);
720 MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_INFO_OUT_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000721 size_t outlen;
722 int rc;
723
724 MCDI_SET_DWORD(inbuf, NVRAM_INFO_IN_TYPE, type);
725
726 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_INFO, inbuf, sizeof(inbuf),
727 outbuf, sizeof(outbuf), &outlen);
728 if (rc)
729 goto fail;
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000730 if (outlen < MC_CMD_NVRAM_INFO_OUT_LEN) {
731 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000732 goto fail;
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000733 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000734
735 *size_out = MCDI_DWORD(outbuf, NVRAM_INFO_OUT_SIZE);
736 *erase_size_out = MCDI_DWORD(outbuf, NVRAM_INFO_OUT_ERASESIZE);
737 *protected_out = !!(MCDI_DWORD(outbuf, NVRAM_INFO_OUT_FLAGS) &
Ben Hutchings05a93202011-12-20 00:44:06 +0000738 (1 << MC_CMD_NVRAM_INFO_OUT_PROTECTED_LBN));
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000739 return 0;
740
741fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000742 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000743 return rc;
744}
745
746int efx_mcdi_nvram_update_start(struct efx_nic *efx, unsigned int type)
747{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100748 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_START_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000749 int rc;
750
751 MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_START_IN_TYPE, type);
752
753 BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_START_OUT_LEN != 0);
754
755 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_START, inbuf, sizeof(inbuf),
756 NULL, 0, NULL);
757 if (rc)
758 goto fail;
759
760 return 0;
761
762fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000763 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000764 return rc;
765}
766
767int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type,
768 loff_t offset, u8 *buffer, size_t length)
769{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100770 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_READ_IN_LEN);
771 MCDI_DECLARE_BUF(outbuf,
772 MC_CMD_NVRAM_READ_OUT_LEN(EFX_MCDI_NVRAM_LEN_MAX));
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000773 size_t outlen;
774 int rc;
775
776 MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_TYPE, type);
777 MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_OFFSET, offset);
778 MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_LENGTH, length);
779
780 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_READ, inbuf, sizeof(inbuf),
781 outbuf, sizeof(outbuf), &outlen);
782 if (rc)
783 goto fail;
784
785 memcpy(buffer, MCDI_PTR(outbuf, NVRAM_READ_OUT_READ_BUFFER), length);
786 return 0;
787
788fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000789 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000790 return rc;
791}
792
793int efx_mcdi_nvram_write(struct efx_nic *efx, unsigned int type,
794 loff_t offset, const u8 *buffer, size_t length)
795{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100796 MCDI_DECLARE_BUF(inbuf,
797 MC_CMD_NVRAM_WRITE_IN_LEN(EFX_MCDI_NVRAM_LEN_MAX));
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000798 int rc;
799
800 MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_TYPE, type);
801 MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_OFFSET, offset);
802 MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_LENGTH, length);
803 memcpy(MCDI_PTR(inbuf, NVRAM_WRITE_IN_WRITE_BUFFER), buffer, length);
804
805 BUILD_BUG_ON(MC_CMD_NVRAM_WRITE_OUT_LEN != 0);
806
Ben Hutchings5a27e862010-01-25 15:49:59 -0800807 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_WRITE, inbuf,
808 ALIGN(MC_CMD_NVRAM_WRITE_IN_LEN(length), 4),
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000809 NULL, 0, NULL);
810 if (rc)
811 goto fail;
812
813 return 0;
814
815fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000816 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000817 return rc;
818}
819
820int efx_mcdi_nvram_erase(struct efx_nic *efx, unsigned int type,
821 loff_t offset, size_t length)
822{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100823 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_ERASE_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000824 int rc;
825
826 MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_TYPE, type);
827 MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_OFFSET, offset);
828 MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_LENGTH, length);
829
830 BUILD_BUG_ON(MC_CMD_NVRAM_ERASE_OUT_LEN != 0);
831
832 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_ERASE, inbuf, sizeof(inbuf),
833 NULL, 0, NULL);
834 if (rc)
835 goto fail;
836
837 return 0;
838
839fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000840 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000841 return rc;
842}
843
844int efx_mcdi_nvram_update_finish(struct efx_nic *efx, unsigned int type)
845{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100846 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000847 int rc;
848
849 MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_FINISH_IN_TYPE, type);
850
851 BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN != 0);
852
853 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_FINISH, inbuf, sizeof(inbuf),
854 NULL, 0, NULL);
855 if (rc)
856 goto fail;
857
858 return 0;
859
860fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000861 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000862 return rc;
863}
864
Ben Hutchings2e803402010-02-03 09:31:01 +0000865static int efx_mcdi_nvram_test(struct efx_nic *efx, unsigned int type)
866{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100867 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_TEST_IN_LEN);
868 MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_TEST_OUT_LEN);
Ben Hutchings2e803402010-02-03 09:31:01 +0000869 int rc;
870
871 MCDI_SET_DWORD(inbuf, NVRAM_TEST_IN_TYPE, type);
872
873 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_TEST, inbuf, sizeof(inbuf),
874 outbuf, sizeof(outbuf), NULL);
875 if (rc)
876 return rc;
877
878 switch (MCDI_DWORD(outbuf, NVRAM_TEST_OUT_RESULT)) {
879 case MC_CMD_NVRAM_TEST_PASS:
880 case MC_CMD_NVRAM_TEST_NOTSUPP:
881 return 0;
882 default:
883 return -EIO;
884 }
885}
886
887int efx_mcdi_nvram_test_all(struct efx_nic *efx)
888{
889 u32 nvram_types;
890 unsigned int type;
891 int rc;
892
893 rc = efx_mcdi_nvram_types(efx, &nvram_types);
894 if (rc)
Ben Hutchingsb548a982010-04-28 09:28:36 +0000895 goto fail1;
Ben Hutchings2e803402010-02-03 09:31:01 +0000896
897 type = 0;
898 while (nvram_types != 0) {
899 if (nvram_types & 1) {
900 rc = efx_mcdi_nvram_test(efx, type);
901 if (rc)
Ben Hutchingsb548a982010-04-28 09:28:36 +0000902 goto fail2;
Ben Hutchings2e803402010-02-03 09:31:01 +0000903 }
904 type++;
905 nvram_types >>= 1;
906 }
907
908 return 0;
Ben Hutchingsb548a982010-04-28 09:28:36 +0000909
910fail2:
Ben Hutchings62776d02010-06-23 11:30:07 +0000911 netif_err(efx, hw, efx->net_dev, "%s: failed type=%u\n",
912 __func__, type);
Ben Hutchingsb548a982010-04-28 09:28:36 +0000913fail1:
Ben Hutchings62776d02010-06-23 11:30:07 +0000914 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsb548a982010-04-28 09:28:36 +0000915 return rc;
Ben Hutchings2e803402010-02-03 09:31:01 +0000916}
917
Steve Hodgson8b2103a2010-02-03 09:30:17 +0000918static int efx_mcdi_read_assertion(struct efx_nic *efx)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000919{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100920 MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_ASSERTS_IN_LEN);
921 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_ASSERTS_OUT_LEN);
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +0100922 unsigned int flags, index;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000923 const char *reason;
924 size_t outlen;
925 int retry;
926 int rc;
927
Steve Hodgson8b2103a2010-02-03 09:30:17 +0000928 /* Attempt to read any stored assertion state before we reboot
929 * the mcfw out of the assertion handler. Retry twice, once
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000930 * because a boot-time assertion might cause this command to fail
931 * with EINTR. And once again because GET_ASSERTS can race with
932 * MC_CMD_REBOOT running on the other port. */
933 retry = 2;
934 do {
Steve Hodgson8b2103a2010-02-03 09:30:17 +0000935 MCDI_SET_DWORD(inbuf, GET_ASSERTS_IN_CLEAR, 1);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000936 rc = efx_mcdi_rpc(efx, MC_CMD_GET_ASSERTS,
Steve Hodgson8b2103a2010-02-03 09:30:17 +0000937 inbuf, MC_CMD_GET_ASSERTS_IN_LEN,
938 outbuf, sizeof(outbuf), &outlen);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000939 } while ((rc == -EINTR || rc == -EIO) && retry-- > 0);
940
941 if (rc)
942 return rc;
943 if (outlen < MC_CMD_GET_ASSERTS_OUT_LEN)
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000944 return -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000945
Steve Hodgson8b2103a2010-02-03 09:30:17 +0000946 /* Print out any recorded assertion state */
947 flags = MCDI_DWORD(outbuf, GET_ASSERTS_OUT_GLOBAL_FLAGS);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000948 if (flags == MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS)
949 return 0;
950
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000951 reason = (flags == MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL)
952 ? "system-level assertion"
953 : (flags == MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL)
954 ? "thread-level assertion"
955 : (flags == MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED)
956 ? "watchdog reset"
957 : "unknown assertion";
Ben Hutchings62776d02010-06-23 11:30:07 +0000958 netif_err(efx, hw, efx->net_dev,
959 "MCPU %s at PC = 0x%.8x in thread 0x%.8x\n", reason,
960 MCDI_DWORD(outbuf, GET_ASSERTS_OUT_SAVED_PC_OFFS),
961 MCDI_DWORD(outbuf, GET_ASSERTS_OUT_THREAD_OFFS));
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000962
963 /* Print out the registers */
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +0100964 for (index = 0;
965 index < MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_NUM;
966 index++)
967 netif_err(efx, hw, efx->net_dev, "R%.2d (?): 0x%.8x\n",
968 1 + index,
969 MCDI_ARRAY_DWORD(outbuf, GET_ASSERTS_OUT_GP_REGS_OFFS,
970 index));
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000971
972 return 0;
973}
974
Steve Hodgson8b2103a2010-02-03 09:30:17 +0000975static void efx_mcdi_exit_assertion(struct efx_nic *efx)
976{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100977 MCDI_DECLARE_BUF(inbuf, MC_CMD_REBOOT_IN_LEN);
Steve Hodgson8b2103a2010-02-03 09:30:17 +0000978
Ben Hutchings0f1e54a2012-07-02 23:37:40 +0100979 /* If the MC is running debug firmware, it might now be
980 * waiting for a debugger to attach, but we just want it to
981 * reboot. We set a flag that makes the command a no-op if it
982 * has already done so. We don't know what return code to
983 * expect (0 or -EIO), so ignore it.
984 */
Steve Hodgson8b2103a2010-02-03 09:30:17 +0000985 BUILD_BUG_ON(MC_CMD_REBOOT_OUT_LEN != 0);
986 MCDI_SET_DWORD(inbuf, REBOOT_IN_FLAGS,
987 MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION);
Ben Hutchings0f1e54a2012-07-02 23:37:40 +0100988 (void) efx_mcdi_rpc(efx, MC_CMD_REBOOT, inbuf, MC_CMD_REBOOT_IN_LEN,
989 NULL, 0, NULL);
Steve Hodgson8b2103a2010-02-03 09:30:17 +0000990}
991
992int efx_mcdi_handle_assertion(struct efx_nic *efx)
993{
994 int rc;
995
996 rc = efx_mcdi_read_assertion(efx);
997 if (rc)
998 return rc;
999
1000 efx_mcdi_exit_assertion(efx);
1001
1002 return 0;
1003}
1004
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001005void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
1006{
Ben Hutchings59cfc472012-09-14 17:30:10 +01001007 MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_ID_LED_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001008 int rc;
1009
1010 BUILD_BUG_ON(EFX_LED_OFF != MC_CMD_LED_OFF);
1011 BUILD_BUG_ON(EFX_LED_ON != MC_CMD_LED_ON);
1012 BUILD_BUG_ON(EFX_LED_DEFAULT != MC_CMD_LED_DEFAULT);
1013
1014 BUILD_BUG_ON(MC_CMD_SET_ID_LED_OUT_LEN != 0);
1015
1016 MCDI_SET_DWORD(inbuf, SET_ID_LED_IN_STATE, mode);
1017
1018 rc = efx_mcdi_rpc(efx, MC_CMD_SET_ID_LED, inbuf, sizeof(inbuf),
1019 NULL, 0, NULL);
1020 if (rc)
Ben Hutchings62776d02010-06-23 11:30:07 +00001021 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
1022 __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001023}
1024
Ben Hutchings6bff8612012-09-18 02:33:52 +01001025static int efx_mcdi_reset_port(struct efx_nic *efx)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001026{
Ben Hutchings05a93202011-12-20 00:44:06 +00001027 int rc = efx_mcdi_rpc(efx, MC_CMD_ENTITY_RESET, NULL, 0, NULL, 0, NULL);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001028 if (rc)
Ben Hutchings62776d02010-06-23 11:30:07 +00001029 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
1030 __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001031 return rc;
1032}
1033
Ben Hutchings6bff8612012-09-18 02:33:52 +01001034static int efx_mcdi_reset_mc(struct efx_nic *efx)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001035{
Ben Hutchings59cfc472012-09-14 17:30:10 +01001036 MCDI_DECLARE_BUF(inbuf, MC_CMD_REBOOT_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001037 int rc;
1038
1039 BUILD_BUG_ON(MC_CMD_REBOOT_OUT_LEN != 0);
1040 MCDI_SET_DWORD(inbuf, REBOOT_IN_FLAGS, 0);
1041 rc = efx_mcdi_rpc(efx, MC_CMD_REBOOT, inbuf, sizeof(inbuf),
1042 NULL, 0, NULL);
1043 /* White is black, and up is down */
1044 if (rc == -EIO)
1045 return 0;
1046 if (rc == 0)
1047 rc = -EIO;
Ben Hutchings62776d02010-06-23 11:30:07 +00001048 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001049 return rc;
1050}
1051
Ben Hutchings6bff8612012-09-18 02:33:52 +01001052enum reset_type efx_mcdi_map_reset_reason(enum reset_type reason)
1053{
1054 return RESET_TYPE_RECOVER_OR_ALL;
1055}
1056
1057int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method)
1058{
1059 int rc;
1060
1061 /* Recover from a failed assertion pre-reset */
1062 rc = efx_mcdi_handle_assertion(efx);
1063 if (rc)
1064 return rc;
1065
1066 if (method == RESET_TYPE_WORLD)
1067 return efx_mcdi_reset_mc(efx);
1068 else
1069 return efx_mcdi_reset_port(efx);
1070}
1071
stephen hemmingerd2156972010-10-18 05:27:31 +00001072static int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type,
1073 const u8 *mac, int *id_out)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001074{
Ben Hutchings59cfc472012-09-14 17:30:10 +01001075 MCDI_DECLARE_BUF(inbuf, MC_CMD_WOL_FILTER_SET_IN_LEN);
1076 MCDI_DECLARE_BUF(outbuf, MC_CMD_WOL_FILTER_SET_OUT_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001077 size_t outlen;
1078 int rc;
1079
1080 MCDI_SET_DWORD(inbuf, WOL_FILTER_SET_IN_WOL_TYPE, type);
1081 MCDI_SET_DWORD(inbuf, WOL_FILTER_SET_IN_FILTER_MODE,
1082 MC_CMD_FILTER_MODE_SIMPLE);
1083 memcpy(MCDI_PTR(inbuf, WOL_FILTER_SET_IN_MAGIC_MAC), mac, ETH_ALEN);
1084
1085 rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_SET, inbuf, sizeof(inbuf),
1086 outbuf, sizeof(outbuf), &outlen);
1087 if (rc)
1088 goto fail;
1089
1090 if (outlen < MC_CMD_WOL_FILTER_SET_OUT_LEN) {
Ben Hutchings00bbb4a2010-04-28 09:27:14 +00001091 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001092 goto fail;
1093 }
1094
1095 *id_out = (int)MCDI_DWORD(outbuf, WOL_FILTER_SET_OUT_FILTER_ID);
1096
1097 return 0;
1098
1099fail:
1100 *id_out = -1;
Ben Hutchings62776d02010-06-23 11:30:07 +00001101 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001102 return rc;
1103
1104}
1105
1106
1107int
1108efx_mcdi_wol_filter_set_magic(struct efx_nic *efx, const u8 *mac, int *id_out)
1109{
1110 return efx_mcdi_wol_filter_set(efx, MC_CMD_WOL_TYPE_MAGIC, mac, id_out);
1111}
1112
1113
1114int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out)
1115{
Ben Hutchings59cfc472012-09-14 17:30:10 +01001116 MCDI_DECLARE_BUF(outbuf, MC_CMD_WOL_FILTER_GET_OUT_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001117 size_t outlen;
1118 int rc;
1119
1120 rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_GET, NULL, 0,
1121 outbuf, sizeof(outbuf), &outlen);
1122 if (rc)
1123 goto fail;
1124
1125 if (outlen < MC_CMD_WOL_FILTER_GET_OUT_LEN) {
Ben Hutchings00bbb4a2010-04-28 09:27:14 +00001126 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001127 goto fail;
1128 }
1129
1130 *id_out = (int)MCDI_DWORD(outbuf, WOL_FILTER_GET_OUT_FILTER_ID);
1131
1132 return 0;
1133
1134fail:
1135 *id_out = -1;
Ben Hutchings62776d02010-06-23 11:30:07 +00001136 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001137 return rc;
1138}
1139
1140
1141int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id)
1142{
Ben Hutchings59cfc472012-09-14 17:30:10 +01001143 MCDI_DECLARE_BUF(inbuf, MC_CMD_WOL_FILTER_REMOVE_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001144 int rc;
1145
1146 MCDI_SET_DWORD(inbuf, WOL_FILTER_REMOVE_IN_FILTER_ID, (u32)id);
1147
1148 rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_REMOVE, inbuf, sizeof(inbuf),
1149 NULL, 0, NULL);
1150 if (rc)
1151 goto fail;
1152
1153 return 0;
1154
1155fail:
Ben Hutchings62776d02010-06-23 11:30:07 +00001156 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001157 return rc;
1158}
1159
Ben Hutchingscd2d5b52012-02-14 00:48:07 +00001160int efx_mcdi_flush_rxqs(struct efx_nic *efx)
1161{
1162 struct efx_channel *channel;
1163 struct efx_rx_queue *rx_queue;
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +01001164 MCDI_DECLARE_BUF(inbuf,
1165 MC_CMD_FLUSH_RX_QUEUES_IN_LEN(EFX_MAX_CHANNELS));
Ben Hutchingscd2d5b52012-02-14 00:48:07 +00001166 int rc, count;
1167
Ben Hutchings45078372012-09-19 02:53:34 +01001168 BUILD_BUG_ON(EFX_MAX_CHANNELS >
1169 MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MAXNUM);
1170
Ben Hutchingscd2d5b52012-02-14 00:48:07 +00001171 count = 0;
1172 efx_for_each_channel(channel, efx) {
1173 efx_for_each_channel_rx_queue(rx_queue, channel) {
1174 if (rx_queue->flush_pending) {
1175 rx_queue->flush_pending = false;
1176 atomic_dec(&efx->rxq_flush_pending);
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +01001177 MCDI_SET_ARRAY_DWORD(
1178 inbuf, FLUSH_RX_QUEUES_IN_QID_OFST,
1179 count, efx_rx_queue_index(rx_queue));
1180 count++;
Ben Hutchingscd2d5b52012-02-14 00:48:07 +00001181 }
1182 }
1183 }
1184
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +01001185 rc = efx_mcdi_rpc(efx, MC_CMD_FLUSH_RX_QUEUES, inbuf,
1186 MC_CMD_FLUSH_RX_QUEUES_IN_LEN(count), NULL, 0, NULL);
Ben Hutchingsbbec9692012-09-11 18:25:13 +01001187 WARN_ON(rc < 0);
Ben Hutchingscd2d5b52012-02-14 00:48:07 +00001188
Ben Hutchingscd2d5b52012-02-14 00:48:07 +00001189 return rc;
1190}
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001191
1192int efx_mcdi_wol_filter_reset(struct efx_nic *efx)
1193{
1194 int rc;
1195
1196 rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_RESET, NULL, 0, NULL, 0, NULL);
1197 if (rc)
1198 goto fail;
1199
1200 return 0;
1201
1202fail:
Ben Hutchings62776d02010-06-23 11:30:07 +00001203 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001204 return rc;
1205}
1206