blob: 1c8bf81bdc03b63ed0a3e29b03834470af4b55a2 [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"
Ben Hutchings8b8a95a2012-09-18 01:57:07 +010014#include "farch_regs.h"
Ben Hutchingsafd4aea2009-11-29 15:15:25 +000015#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 Hutchingsdf2cd8a2012-09-19 00:56:18 +010075 efx_dword_t hdr[2];
76 size_t hdr_len;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +000077 u32 xflags, seqno;
78
79 BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
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
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +010086 if (efx->type->mcdi_max_ver == 1) {
87 /* MCDI v1 */
88 EFX_POPULATE_DWORD_6(hdr[0],
89 MCDI_HEADER_RESPONSE, 0,
90 MCDI_HEADER_RESYNC, 1,
91 MCDI_HEADER_CODE, cmd,
92 MCDI_HEADER_DATALEN, inlen,
93 MCDI_HEADER_SEQ, seqno,
94 MCDI_HEADER_XFLAGS, xflags);
95 hdr_len = 4;
96 } else {
97 /* MCDI v2 */
98 BUG_ON(inlen > MCDI_CTL_SDU_LEN_MAX_V2);
99 EFX_POPULATE_DWORD_6(hdr[0],
100 MCDI_HEADER_RESPONSE, 0,
101 MCDI_HEADER_RESYNC, 1,
102 MCDI_HEADER_CODE, MC_CMD_V2_EXTN,
103 MCDI_HEADER_DATALEN, 0,
104 MCDI_HEADER_SEQ, seqno,
105 MCDI_HEADER_XFLAGS, xflags);
106 EFX_POPULATE_DWORD_2(hdr[1],
107 MC_CMD_V2_EXTN_IN_EXTENDED_CMD, cmd,
108 MC_CMD_V2_EXTN_IN_ACTUAL_LEN, inlen);
109 hdr_len = 8;
110 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000111
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100112 efx->type->mcdi_request(efx, hdr, hdr_len, inbuf, inlen);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000113}
114
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100115static int efx_mcdi_errno(unsigned int mcdi_err)
116{
117 switch (mcdi_err) {
118 case 0:
119 return 0;
120#define TRANSLATE_ERROR(name) \
121 case MC_CMD_ERR_ ## name: \
122 return -name;
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100123 TRANSLATE_ERROR(EPERM);
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100124 TRANSLATE_ERROR(ENOENT);
125 TRANSLATE_ERROR(EINTR);
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100126 TRANSLATE_ERROR(EAGAIN);
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100127 TRANSLATE_ERROR(EACCES);
128 TRANSLATE_ERROR(EBUSY);
129 TRANSLATE_ERROR(EINVAL);
130 TRANSLATE_ERROR(EDEADLK);
131 TRANSLATE_ERROR(ENOSYS);
132 TRANSLATE_ERROR(ETIME);
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100133 TRANSLATE_ERROR(EALREADY);
134 TRANSLATE_ERROR(ENOSPC);
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100135#undef TRANSLATE_ERROR
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100136 case MC_CMD_ERR_ALLOC_FAIL:
137 return -ENOBUFS;
138 case MC_CMD_ERR_MAC_EXIST:
139 return -EADDRINUSE;
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100140 default:
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100141 return -EPROTO;
142 }
143}
144
145static void efx_mcdi_read_response_header(struct efx_nic *efx)
146{
147 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
148 unsigned int respseq, respcmd, error;
149 efx_dword_t hdr;
150
151 efx->type->mcdi_read_response(efx, &hdr, 0, 4);
152 respseq = EFX_DWORD_FIELD(hdr, MCDI_HEADER_SEQ);
153 respcmd = EFX_DWORD_FIELD(hdr, MCDI_HEADER_CODE);
154 error = EFX_DWORD_FIELD(hdr, MCDI_HEADER_ERROR);
155
156 if (respcmd != MC_CMD_V2_EXTN) {
157 mcdi->resp_hdr_len = 4;
158 mcdi->resp_data_len = EFX_DWORD_FIELD(hdr, MCDI_HEADER_DATALEN);
159 } else {
160 efx->type->mcdi_read_response(efx, &hdr, 4, 4);
161 mcdi->resp_hdr_len = 8;
162 mcdi->resp_data_len =
163 EFX_DWORD_FIELD(hdr, MC_CMD_V2_EXTN_IN_ACTUAL_LEN);
164 }
165
166 if (error && mcdi->resp_data_len == 0) {
167 netif_err(efx, hw, efx->net_dev, "MC rebooted\n");
168 mcdi->resprc = -EIO;
169 } else if ((respseq ^ mcdi->seqno) & SEQ_MASK) {
170 netif_err(efx, hw, efx->net_dev,
171 "MC response mismatch tx seq 0x%x rx seq 0x%x\n",
172 respseq, mcdi->seqno);
173 mcdi->resprc = -EIO;
174 } else if (error) {
175 efx->type->mcdi_read_response(efx, &hdr, mcdi->resp_hdr_len, 4);
176 mcdi->resprc =
177 efx_mcdi_errno(EFX_DWORD_FIELD(hdr, EFX_DWORD_0));
178 } else {
179 mcdi->resprc = 0;
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100180 }
181}
182
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000183static int efx_mcdi_poll(struct efx_nic *efx)
184{
185 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
Ben Hutchingsebf98e72012-12-01 02:21:17 +0000186 unsigned long time, finish;
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100187 unsigned int spins;
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100188 int rc;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000189
190 /* Check for a reboot atomically with respect to efx_mcdi_copyout() */
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100191 rc = efx_mcdi_poll_reboot(efx);
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100192 if (rc) {
Ben Hutchings369327f2012-10-26 17:53:12 +0100193 spin_lock_bh(&mcdi->iface_lock);
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100194 mcdi->resprc = rc;
195 mcdi->resp_hdr_len = 0;
196 mcdi->resp_data_len = 0;
Ben Hutchings369327f2012-10-26 17:53:12 +0100197 spin_unlock_bh(&mcdi->iface_lock);
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100198 return 0;
199 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000200
201 /* Poll for completion. Poll quickly (once a us) for the 1st jiffy,
202 * because generally mcdi responses are fast. After that, back off
203 * and poll once a jiffy (approximately)
204 */
205 spins = TICK_USEC;
Ben Hutchingsebf98e72012-12-01 02:21:17 +0000206 finish = jiffies + MCDI_RPC_TIMEOUT;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000207
208 while (1) {
209 if (spins != 0) {
210 --spins;
211 udelay(1);
Ben Hutchings55029c12010-01-13 04:34:25 +0000212 } else {
213 schedule_timeout_uninterruptible(1);
214 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000215
Ben Hutchingsebf98e72012-12-01 02:21:17 +0000216 time = jiffies;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000217
Ben Hutchings86c432c2011-09-01 12:09:29 +0000218 rmb();
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100219 if (efx->type->mcdi_poll_response(efx))
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000220 break;
221
Ben Hutchingsebf98e72012-12-01 02:21:17 +0000222 if (time_after(time, finish))
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000223 return -ETIMEDOUT;
224 }
225
Ben Hutchings369327f2012-10-26 17:53:12 +0100226 spin_lock_bh(&mcdi->iface_lock);
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100227 efx_mcdi_read_response_header(efx);
Ben Hutchings369327f2012-10-26 17:53:12 +0100228 spin_unlock_bh(&mcdi->iface_lock);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000229
230 /* Return rc=0 like wait_event_timeout() */
231 return 0;
232}
233
Ben Hutchings876be082012-10-01 20:58:35 +0100234/* Test and clear MC-rebooted flag for this port/function; reset
235 * software state as necessary.
236 */
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000237int efx_mcdi_poll_reboot(struct efx_nic *efx)
238{
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100239 int rc;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000240
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100241 if (!efx->mcdi)
242 return 0;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000243
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100244 rc = efx->type->mcdi_poll_reboot(efx);
245 if (!rc)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000246 return 0;
247
Ben Hutchings876be082012-10-01 20:58:35 +0100248 /* MAC statistics have been cleared on the NIC; clear our copy
249 * so that efx_update_diff_stat() can continue to work.
250 */
251 memset(&efx->mac_stats, 0, sizeof(efx->mac_stats));
252
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100253 return rc;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000254}
255
256static void efx_mcdi_acquire(struct efx_mcdi_iface *mcdi)
257{
258 /* Wait until the interface becomes QUIESCENT and we win the race
259 * to mark it RUNNING. */
260 wait_event(mcdi->wq,
261 atomic_cmpxchg(&mcdi->state,
262 MCDI_STATE_QUIESCENT,
263 MCDI_STATE_RUNNING)
264 == MCDI_STATE_QUIESCENT);
265}
266
267static int efx_mcdi_await_completion(struct efx_nic *efx)
268{
269 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
270
271 if (wait_event_timeout(
272 mcdi->wq,
273 atomic_read(&mcdi->state) == MCDI_STATE_COMPLETED,
Ben Hutchingsebf98e72012-12-01 02:21:17 +0000274 MCDI_RPC_TIMEOUT) == 0)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000275 return -ETIMEDOUT;
276
277 /* Check if efx_mcdi_set_mode() switched us back to polled completions.
278 * In which case, poll for completions directly. If efx_mcdi_ev_cpl()
279 * completed the request first, then we'll just end up completing the
280 * request again, which is safe.
281 *
282 * We need an smp_rmb() to synchronise with efx_mcdi_mode_poll(), which
283 * wait_event_timeout() implicitly provides.
284 */
285 if (mcdi->mode == MCDI_MODE_POLL)
286 return efx_mcdi_poll(efx);
287
288 return 0;
289}
290
291static bool efx_mcdi_complete(struct efx_mcdi_iface *mcdi)
292{
293 /* If the interface is RUNNING, then move to COMPLETED and wake any
294 * waiters. If the interface isn't in RUNNING then we've received a
295 * duplicate completion after we've already transitioned back to
296 * QUIESCENT. [A subsequent invocation would increment seqno, so would
297 * have failed the seqno check].
298 */
299 if (atomic_cmpxchg(&mcdi->state,
300 MCDI_STATE_RUNNING,
301 MCDI_STATE_COMPLETED) == MCDI_STATE_RUNNING) {
302 wake_up(&mcdi->wq);
303 return true;
304 }
305
306 return false;
307}
308
309static void efx_mcdi_release(struct efx_mcdi_iface *mcdi)
310{
311 atomic_set(&mcdi->state, MCDI_STATE_QUIESCENT);
312 wake_up(&mcdi->wq);
313}
314
315static void efx_mcdi_ev_cpl(struct efx_nic *efx, unsigned int seqno,
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100316 unsigned int datalen, unsigned int mcdi_err)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000317{
318 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
319 bool wake = false;
320
321 spin_lock(&mcdi->iface_lock);
322
323 if ((seqno ^ mcdi->seqno) & SEQ_MASK) {
324 if (mcdi->credits)
325 /* The request has been cancelled */
326 --mcdi->credits;
327 else
Ben Hutchings62776d02010-06-23 11:30:07 +0000328 netif_err(efx, hw, efx->net_dev,
329 "MC response mismatch tx seq 0x%x rx "
330 "seq 0x%x\n", seqno, mcdi->seqno);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000331 } else {
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100332 if (efx->type->mcdi_max_ver >= 2) {
333 /* MCDI v2 responses don't fit in an event */
334 efx_mcdi_read_response_header(efx);
335 } else {
336 mcdi->resprc = efx_mcdi_errno(mcdi_err);
337 mcdi->resp_hdr_len = 4;
338 mcdi->resp_data_len = datalen;
339 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000340
341 wake = true;
342 }
343
344 spin_unlock(&mcdi->iface_lock);
345
346 if (wake)
347 efx_mcdi_complete(mcdi);
348}
349
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000350int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd,
Ben Hutchings9528b922012-09-14 17:31:41 +0100351 const efx_dword_t *inbuf, size_t inlen,
352 efx_dword_t *outbuf, size_t outlen,
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000353 size_t *outlen_actual)
354{
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100355 int rc;
356
357 rc = efx_mcdi_rpc_start(efx, cmd, inbuf, inlen);
358 if (rc)
359 return rc;
Stuart Hodgsonc3cba722012-07-16 17:40:47 +0100360 return efx_mcdi_rpc_finish(efx, cmd, inlen,
361 outbuf, outlen, outlen_actual);
362}
363
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100364int efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd,
365 const efx_dword_t *inbuf, size_t inlen)
Stuart Hodgsonc3cba722012-07-16 17:40:47 +0100366{
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000367 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
Stuart Hodgsonc3cba722012-07-16 17:40:47 +0100368
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100369 if (efx->type->mcdi_max_ver < 0 ||
370 (efx->type->mcdi_max_ver < 2 &&
371 cmd > MC_CMD_CMD_SPACE_ESCAPE_7))
372 return -EINVAL;
373
374 if (inlen > MCDI_CTL_SDU_LEN_MAX_V2 ||
375 (efx->type->mcdi_max_ver < 2 &&
376 inlen > MCDI_CTL_SDU_LEN_MAX_V1))
377 return -EMSGSIZE;
378
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000379 efx_mcdi_acquire(mcdi);
380
381 /* Serialise with efx_mcdi_ev_cpl() and efx_mcdi_ev_death() */
382 spin_lock_bh(&mcdi->iface_lock);
383 ++mcdi->seqno;
384 spin_unlock_bh(&mcdi->iface_lock);
385
386 efx_mcdi_copyin(efx, cmd, inbuf, inlen);
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100387 return 0;
Stuart Hodgsonc3cba722012-07-16 17:40:47 +0100388}
389
390int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
Ben Hutchings9528b922012-09-14 17:31:41 +0100391 efx_dword_t *outbuf, size_t outlen,
392 size_t *outlen_actual)
Stuart Hodgsonc3cba722012-07-16 17:40:47 +0100393{
394 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
395 int rc;
396
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000397 if (mcdi->mode == MCDI_MODE_POLL)
398 rc = efx_mcdi_poll(efx);
399 else
400 rc = efx_mcdi_await_completion(efx);
401
402 if (rc != 0) {
403 /* Close the race with efx_mcdi_ev_cpl() executing just too late
404 * and completing a request we've just cancelled, by ensuring
405 * that the seqno check therein fails.
406 */
407 spin_lock_bh(&mcdi->iface_lock);
408 ++mcdi->seqno;
409 ++mcdi->credits;
410 spin_unlock_bh(&mcdi->iface_lock);
411
Ben Hutchings62776d02010-06-23 11:30:07 +0000412 netif_err(efx, hw, efx->net_dev,
413 "MC command 0x%x inlen %d mode %d timed out\n",
414 cmd, (int)inlen, mcdi->mode);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000415 } else {
Ben Hutchings369327f2012-10-26 17:53:12 +0100416 size_t hdr_len, data_len;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000417
418 /* At the very least we need a memory barrier here to ensure
419 * we pick up changes from efx_mcdi_ev_cpl(). Protect against
420 * a spurious efx_mcdi_ev_cpl() running concurrently by
421 * acquiring the iface_lock. */
422 spin_lock_bh(&mcdi->iface_lock);
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100423 rc = mcdi->resprc;
Ben Hutchings369327f2012-10-26 17:53:12 +0100424 hdr_len = mcdi->resp_hdr_len;
425 data_len = mcdi->resp_data_len;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000426 spin_unlock_bh(&mcdi->iface_lock);
427
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100428 BUG_ON(rc > 0);
429
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000430 if (rc == 0) {
Ben Hutchings369327f2012-10-26 17:53:12 +0100431 efx->type->mcdi_read_response(efx, outbuf, hdr_len,
432 min(outlen, data_len));
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000433 if (outlen_actual != NULL)
Ben Hutchings369327f2012-10-26 17:53:12 +0100434 *outlen_actual = data_len;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000435 } else if (cmd == MC_CMD_REBOOT && rc == -EIO)
436 ; /* Don't reset if MC_CMD_REBOOT returns EIO */
437 else if (rc == -EIO || rc == -EINTR) {
Ben Hutchings62776d02010-06-23 11:30:07 +0000438 netif_err(efx, hw, efx->net_dev, "MC fatal error %d\n",
439 -rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000440 efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE);
441 } else
Ben Hutchingsf18ca362010-12-02 13:46:09 +0000442 netif_dbg(efx, hw, efx->net_dev,
Ben Hutchings62776d02010-06-23 11:30:07 +0000443 "MC command 0x%x inlen %d failed rc=%d\n",
444 cmd, (int)inlen, -rc);
Ben Hutchings3f713bf2011-12-20 23:39:31 +0000445
446 if (rc == -EIO || rc == -EINTR) {
447 msleep(MCDI_STATUS_SLEEP_MS);
448 efx_mcdi_poll_reboot(efx);
449 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000450 }
451
452 efx_mcdi_release(mcdi);
453 return rc;
454}
455
456void efx_mcdi_mode_poll(struct efx_nic *efx)
457{
458 struct efx_mcdi_iface *mcdi;
459
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100460 if (!efx->mcdi)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000461 return;
462
463 mcdi = efx_mcdi(efx);
464 if (mcdi->mode == MCDI_MODE_POLL)
465 return;
466
467 /* We can switch from event completion to polled completion, because
468 * mcdi requests are always completed in shared memory. We do this by
469 * switching the mode to POLL'd then completing the request.
470 * efx_mcdi_await_completion() will then call efx_mcdi_poll().
471 *
472 * We need an smp_wmb() to synchronise with efx_mcdi_await_completion(),
473 * which efx_mcdi_complete() provides for us.
474 */
475 mcdi->mode = MCDI_MODE_POLL;
476
477 efx_mcdi_complete(mcdi);
478}
479
480void efx_mcdi_mode_event(struct efx_nic *efx)
481{
482 struct efx_mcdi_iface *mcdi;
483
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100484 if (!efx->mcdi)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000485 return;
486
487 mcdi = efx_mcdi(efx);
488
489 if (mcdi->mode == MCDI_MODE_EVENTS)
490 return;
491
492 /* We can't switch from polled to event completion in the middle of a
493 * request, because the completion method is specified in the request.
494 * So acquire the interface to serialise the requestors. We don't need
495 * to acquire the iface_lock to change the mode here, but we do need a
496 * write memory barrier ensure that efx_mcdi_rpc() sees it, which
497 * efx_mcdi_acquire() provides.
498 */
499 efx_mcdi_acquire(mcdi);
500 mcdi->mode = MCDI_MODE_EVENTS;
501 efx_mcdi_release(mcdi);
502}
503
504static void efx_mcdi_ev_death(struct efx_nic *efx, int rc)
505{
506 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
507
508 /* If there is an outstanding MCDI request, it has been terminated
509 * either by a BADASSERT or REBOOT event. If the mcdi interface is
510 * in polled mode, then do nothing because the MC reboot handler will
511 * set the header correctly. However, if the mcdi interface is waiting
512 * for a CMDDONE event it won't receive it [and since all MCDI events
513 * are sent to the same queue, we can't be racing with
514 * efx_mcdi_ev_cpl()]
515 *
516 * There's a race here with efx_mcdi_rpc(), because we might receive
517 * a REBOOT event *before* the request has been copied out. In polled
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300518 * mode (during startup) this is irrelevant, because efx_mcdi_complete()
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000519 * is ignored. In event mode, this condition is just an edge-case of
520 * receiving a REBOOT event after posting the MCDI request. Did the mc
521 * reboot before or after the copyout? The best we can do always is
522 * just return failure.
523 */
524 spin_lock(&mcdi->iface_lock);
525 if (efx_mcdi_complete(mcdi)) {
526 if (mcdi->mode == MCDI_MODE_EVENTS) {
527 mcdi->resprc = rc;
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100528 mcdi->resp_hdr_len = 0;
529 mcdi->resp_data_len = 0;
Steve Hodgson18e3ee22010-12-02 13:46:55 +0000530 ++mcdi->credits;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000531 }
Ben Hutchings3f713bf2011-12-20 23:39:31 +0000532 } else {
533 int count;
534
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000535 /* Nobody was waiting for an MCDI request, so trigger a reset */
536 efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE);
537
Ben Hutchings3f713bf2011-12-20 23:39:31 +0000538 /* Consume the status word since efx_mcdi_rpc_finish() won't */
539 for (count = 0; count < MCDI_STATUS_DELAY_COUNT; ++count) {
540 if (efx_mcdi_poll_reboot(efx))
541 break;
542 udelay(MCDI_STATUS_DELAY_US);
543 }
544 }
545
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000546 spin_unlock(&mcdi->iface_lock);
547}
548
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000549/* Called from falcon_process_eventq for MCDI events */
550void efx_mcdi_process_event(struct efx_channel *channel,
551 efx_qword_t *event)
552{
553 struct efx_nic *efx = channel->efx;
554 int code = EFX_QWORD_FIELD(*event, MCDI_EVENT_CODE);
555 u32 data = EFX_QWORD_FIELD(*event, MCDI_EVENT_DATA);
556
557 switch (code) {
558 case MCDI_EVENT_CODE_BADSSERT:
Ben Hutchings62776d02010-06-23 11:30:07 +0000559 netif_err(efx, hw, efx->net_dev,
560 "MC watchdog or assertion failure at 0x%x\n", data);
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100561 efx_mcdi_ev_death(efx, -EINTR);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000562 break;
563
564 case MCDI_EVENT_CODE_PMNOTICE:
Ben Hutchings62776d02010-06-23 11:30:07 +0000565 netif_info(efx, wol, efx->net_dev, "MCDI PM event.\n");
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000566 break;
567
568 case MCDI_EVENT_CODE_CMDDONE:
569 efx_mcdi_ev_cpl(efx,
570 MCDI_EVENT_FIELD(*event, CMDDONE_SEQ),
571 MCDI_EVENT_FIELD(*event, CMDDONE_DATALEN),
572 MCDI_EVENT_FIELD(*event, CMDDONE_ERRNO));
573 break;
574
575 case MCDI_EVENT_CODE_LINKCHANGE:
576 efx_mcdi_process_link_change(efx, event);
577 break;
578 case MCDI_EVENT_CODE_SENSOREVT:
579 efx_mcdi_sensor_event(efx, event);
580 break;
581 case MCDI_EVENT_CODE_SCHEDERR:
Ben Hutchings62776d02010-06-23 11:30:07 +0000582 netif_info(efx, hw, efx->net_dev,
583 "MC Scheduler error address=0x%x\n", data);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000584 break;
585 case MCDI_EVENT_CODE_REBOOT:
Ben Hutchings62776d02010-06-23 11:30:07 +0000586 netif_info(efx, hw, efx->net_dev, "MC Reboot\n");
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100587 efx_mcdi_ev_death(efx, -EIO);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000588 break;
589 case MCDI_EVENT_CODE_MAC_STATS_DMA:
590 /* MAC stats are gather lazily. We can ignore this. */
591 break;
Ben Hutchingscd2d5b52012-02-14 00:48:07 +0000592 case MCDI_EVENT_CODE_FLR:
593 efx_sriov_flr(efx, MCDI_EVENT_FIELD(*event, FLR_VF));
594 break;
Stuart Hodgson7c236c42012-09-03 11:09:36 +0100595 case MCDI_EVENT_CODE_PTP_RX:
596 case MCDI_EVENT_CODE_PTP_FAULT:
597 case MCDI_EVENT_CODE_PTP_PPS:
598 efx_ptp_event(efx, event);
599 break;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000600
601 default:
Ben Hutchings62776d02010-06-23 11:30:07 +0000602 netif_err(efx, hw, efx->net_dev, "Unknown MCDI event 0x%x\n",
603 code);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000604 }
605}
606
607/**************************************************************************
608 *
609 * Specific request functions
610 *
611 **************************************************************************
612 */
613
Ben Hutchingse5f0fd22011-02-24 23:57:47 +0000614void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000615{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100616 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_VERSION_OUT_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000617 size_t outlength;
618 const __le16 *ver_words;
619 int rc;
620
621 BUILD_BUG_ON(MC_CMD_GET_VERSION_IN_LEN != 0);
622
623 rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, NULL, 0,
624 outbuf, sizeof(outbuf), &outlength);
625 if (rc)
626 goto fail;
627
Ben Hutchings05a93202011-12-20 00:44:06 +0000628 if (outlength < MC_CMD_GET_VERSION_OUT_LEN) {
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000629 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000630 goto fail;
631 }
632
633 ver_words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_OUT_VERSION);
Ben Hutchingse5f0fd22011-02-24 23:57:47 +0000634 snprintf(buf, len, "%u.%u.%u.%u",
635 le16_to_cpu(ver_words[0]), le16_to_cpu(ver_words[1]),
636 le16_to_cpu(ver_words[2]), le16_to_cpu(ver_words[3]));
637 return;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000638
639fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000640 netif_err(efx, probe, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingse5f0fd22011-02-24 23:57:47 +0000641 buf[0] = 0;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000642}
643
644int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
645 bool *was_attached)
646{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100647 MCDI_DECLARE_BUF(inbuf, MC_CMD_DRV_ATTACH_IN_LEN);
648 MCDI_DECLARE_BUF(outbuf, MC_CMD_DRV_ATTACH_OUT_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000649 size_t outlen;
650 int rc;
651
652 MCDI_SET_DWORD(inbuf, DRV_ATTACH_IN_NEW_STATE,
653 driver_operating ? 1 : 0);
654 MCDI_SET_DWORD(inbuf, DRV_ATTACH_IN_UPDATE, 1);
Ben Hutchingsf2b0bef2013-08-20 20:35:50 +0100655 MCDI_SET_DWORD(inbuf, DRV_ATTACH_IN_FIRMWARE_ID, MC_CMD_FW_LOW_LATENCY);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000656
657 rc = efx_mcdi_rpc(efx, MC_CMD_DRV_ATTACH, inbuf, sizeof(inbuf),
658 outbuf, sizeof(outbuf), &outlen);
659 if (rc)
660 goto fail;
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000661 if (outlen < MC_CMD_DRV_ATTACH_OUT_LEN) {
662 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000663 goto fail;
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000664 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000665
666 if (was_attached != NULL)
667 *was_attached = MCDI_DWORD(outbuf, DRV_ATTACH_OUT_OLD_STATE);
668 return 0;
669
670fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000671 netif_err(efx, probe, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000672 return rc;
673}
674
675int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
Matthew Slattery6aa9c7f2010-07-14 15:36:19 +0100676 u16 *fw_subtype_list, u32 *capabilities)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000677{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100678 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_BOARD_CFG_OUT_LENMAX);
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +0100679 size_t outlen, i;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000680 int port_num = efx_port_num(efx);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000681 int rc;
682
683 BUILD_BUG_ON(MC_CMD_GET_BOARD_CFG_IN_LEN != 0);
684
685 rc = efx_mcdi_rpc(efx, MC_CMD_GET_BOARD_CFG, NULL, 0,
686 outbuf, sizeof(outbuf), &outlen);
687 if (rc)
688 goto fail;
689
Ben Hutchings05a93202011-12-20 00:44:06 +0000690 if (outlen < MC_CMD_GET_BOARD_CFG_OUT_LENMIN) {
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000691 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000692 goto fail;
693 }
694
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000695 if (mac_address)
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +0100696 memcpy(mac_address,
697 port_num ?
698 MCDI_PTR(outbuf, GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1) :
699 MCDI_PTR(outbuf, GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0),
700 ETH_ALEN);
Ben Hutchingsbfeed902012-09-07 00:58:10 +0100701 if (fw_subtype_list) {
Ben Hutchingsbfeed902012-09-07 00:58:10 +0100702 for (i = 0;
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +0100703 i < MCDI_VAR_ARRAY_LEN(outlen,
704 GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST);
705 i++)
706 fw_subtype_list[i] = MCDI_ARRAY_WORD(
707 outbuf, GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST, i);
708 for (; i < MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MAXNUM; i++)
709 fw_subtype_list[i] = 0;
Ben Hutchingsbfeed902012-09-07 00:58:10 +0100710 }
Matthew Slattery6aa9c7f2010-07-14 15:36:19 +0100711 if (capabilities) {
712 if (port_num)
713 *capabilities = MCDI_DWORD(outbuf,
714 GET_BOARD_CFG_OUT_CAPABILITIES_PORT1);
715 else
716 *capabilities = MCDI_DWORD(outbuf,
717 GET_BOARD_CFG_OUT_CAPABILITIES_PORT0);
718 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000719
720 return 0;
721
722fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000723 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d len=%d\n",
724 __func__, rc, (int)outlen);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000725
726 return rc;
727}
728
729int efx_mcdi_log_ctrl(struct efx_nic *efx, bool evq, bool uart, u32 dest_evq)
730{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100731 MCDI_DECLARE_BUF(inbuf, MC_CMD_LOG_CTRL_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000732 u32 dest = 0;
733 int rc;
734
735 if (uart)
736 dest |= MC_CMD_LOG_CTRL_IN_LOG_DEST_UART;
737 if (evq)
738 dest |= MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ;
739
740 MCDI_SET_DWORD(inbuf, LOG_CTRL_IN_LOG_DEST, dest);
741 MCDI_SET_DWORD(inbuf, LOG_CTRL_IN_LOG_DEST_EVQ, dest_evq);
742
743 BUILD_BUG_ON(MC_CMD_LOG_CTRL_OUT_LEN != 0);
744
745 rc = efx_mcdi_rpc(efx, MC_CMD_LOG_CTRL, inbuf, sizeof(inbuf),
746 NULL, 0, NULL);
747 if (rc)
748 goto fail;
749
750 return 0;
751
752fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000753 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000754 return rc;
755}
756
757int efx_mcdi_nvram_types(struct efx_nic *efx, u32 *nvram_types_out)
758{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100759 MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_TYPES_OUT_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000760 size_t outlen;
761 int rc;
762
763 BUILD_BUG_ON(MC_CMD_NVRAM_TYPES_IN_LEN != 0);
764
765 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_TYPES, NULL, 0,
766 outbuf, sizeof(outbuf), &outlen);
767 if (rc)
768 goto fail;
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000769 if (outlen < MC_CMD_NVRAM_TYPES_OUT_LEN) {
770 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000771 goto fail;
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000772 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000773
774 *nvram_types_out = MCDI_DWORD(outbuf, NVRAM_TYPES_OUT_TYPES);
775 return 0;
776
777fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000778 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
779 __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000780 return rc;
781}
782
783int efx_mcdi_nvram_info(struct efx_nic *efx, unsigned int type,
784 size_t *size_out, size_t *erase_size_out,
785 bool *protected_out)
786{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100787 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_INFO_IN_LEN);
788 MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_INFO_OUT_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000789 size_t outlen;
790 int rc;
791
792 MCDI_SET_DWORD(inbuf, NVRAM_INFO_IN_TYPE, type);
793
794 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_INFO, inbuf, sizeof(inbuf),
795 outbuf, sizeof(outbuf), &outlen);
796 if (rc)
797 goto fail;
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000798 if (outlen < MC_CMD_NVRAM_INFO_OUT_LEN) {
799 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000800 goto fail;
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000801 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000802
803 *size_out = MCDI_DWORD(outbuf, NVRAM_INFO_OUT_SIZE);
804 *erase_size_out = MCDI_DWORD(outbuf, NVRAM_INFO_OUT_ERASESIZE);
805 *protected_out = !!(MCDI_DWORD(outbuf, NVRAM_INFO_OUT_FLAGS) &
Ben Hutchings05a93202011-12-20 00:44:06 +0000806 (1 << MC_CMD_NVRAM_INFO_OUT_PROTECTED_LBN));
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000807 return 0;
808
809fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000810 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000811 return rc;
812}
813
814int efx_mcdi_nvram_update_start(struct efx_nic *efx, unsigned int type)
815{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100816 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_START_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000817 int rc;
818
819 MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_START_IN_TYPE, type);
820
821 BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_START_OUT_LEN != 0);
822
823 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_START, inbuf, sizeof(inbuf),
824 NULL, 0, NULL);
825 if (rc)
826 goto fail;
827
828 return 0;
829
830fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000831 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000832 return rc;
833}
834
835int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type,
836 loff_t offset, u8 *buffer, size_t length)
837{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100838 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_READ_IN_LEN);
839 MCDI_DECLARE_BUF(outbuf,
840 MC_CMD_NVRAM_READ_OUT_LEN(EFX_MCDI_NVRAM_LEN_MAX));
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000841 size_t outlen;
842 int rc;
843
844 MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_TYPE, type);
845 MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_OFFSET, offset);
846 MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_LENGTH, length);
847
848 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_READ, inbuf, sizeof(inbuf),
849 outbuf, sizeof(outbuf), &outlen);
850 if (rc)
851 goto fail;
852
853 memcpy(buffer, MCDI_PTR(outbuf, NVRAM_READ_OUT_READ_BUFFER), length);
854 return 0;
855
856fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000857 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000858 return rc;
859}
860
861int efx_mcdi_nvram_write(struct efx_nic *efx, unsigned int type,
862 loff_t offset, const u8 *buffer, size_t length)
863{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100864 MCDI_DECLARE_BUF(inbuf,
865 MC_CMD_NVRAM_WRITE_IN_LEN(EFX_MCDI_NVRAM_LEN_MAX));
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000866 int rc;
867
868 MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_TYPE, type);
869 MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_OFFSET, offset);
870 MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_LENGTH, length);
871 memcpy(MCDI_PTR(inbuf, NVRAM_WRITE_IN_WRITE_BUFFER), buffer, length);
872
873 BUILD_BUG_ON(MC_CMD_NVRAM_WRITE_OUT_LEN != 0);
874
Ben Hutchings5a27e862010-01-25 15:49:59 -0800875 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_WRITE, inbuf,
876 ALIGN(MC_CMD_NVRAM_WRITE_IN_LEN(length), 4),
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000877 NULL, 0, NULL);
878 if (rc)
879 goto fail;
880
881 return 0;
882
883fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000884 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000885 return rc;
886}
887
888int efx_mcdi_nvram_erase(struct efx_nic *efx, unsigned int type,
889 loff_t offset, size_t length)
890{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100891 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_ERASE_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000892 int rc;
893
894 MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_TYPE, type);
895 MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_OFFSET, offset);
896 MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_LENGTH, length);
897
898 BUILD_BUG_ON(MC_CMD_NVRAM_ERASE_OUT_LEN != 0);
899
900 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_ERASE, inbuf, sizeof(inbuf),
901 NULL, 0, NULL);
902 if (rc)
903 goto fail;
904
905 return 0;
906
907fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000908 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000909 return rc;
910}
911
912int efx_mcdi_nvram_update_finish(struct efx_nic *efx, unsigned int type)
913{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100914 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000915 int rc;
916
917 MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_FINISH_IN_TYPE, type);
918
919 BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN != 0);
920
921 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_FINISH, inbuf, sizeof(inbuf),
922 NULL, 0, NULL);
923 if (rc)
924 goto fail;
925
926 return 0;
927
928fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000929 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000930 return rc;
931}
932
Ben Hutchings2e803402010-02-03 09:31:01 +0000933static int efx_mcdi_nvram_test(struct efx_nic *efx, unsigned int type)
934{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100935 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_TEST_IN_LEN);
936 MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_TEST_OUT_LEN);
Ben Hutchings2e803402010-02-03 09:31:01 +0000937 int rc;
938
939 MCDI_SET_DWORD(inbuf, NVRAM_TEST_IN_TYPE, type);
940
941 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_TEST, inbuf, sizeof(inbuf),
942 outbuf, sizeof(outbuf), NULL);
943 if (rc)
944 return rc;
945
946 switch (MCDI_DWORD(outbuf, NVRAM_TEST_OUT_RESULT)) {
947 case MC_CMD_NVRAM_TEST_PASS:
948 case MC_CMD_NVRAM_TEST_NOTSUPP:
949 return 0;
950 default:
951 return -EIO;
952 }
953}
954
955int efx_mcdi_nvram_test_all(struct efx_nic *efx)
956{
957 u32 nvram_types;
958 unsigned int type;
959 int rc;
960
961 rc = efx_mcdi_nvram_types(efx, &nvram_types);
962 if (rc)
Ben Hutchingsb548a982010-04-28 09:28:36 +0000963 goto fail1;
Ben Hutchings2e803402010-02-03 09:31:01 +0000964
965 type = 0;
966 while (nvram_types != 0) {
967 if (nvram_types & 1) {
968 rc = efx_mcdi_nvram_test(efx, type);
969 if (rc)
Ben Hutchingsb548a982010-04-28 09:28:36 +0000970 goto fail2;
Ben Hutchings2e803402010-02-03 09:31:01 +0000971 }
972 type++;
973 nvram_types >>= 1;
974 }
975
976 return 0;
Ben Hutchingsb548a982010-04-28 09:28:36 +0000977
978fail2:
Ben Hutchings62776d02010-06-23 11:30:07 +0000979 netif_err(efx, hw, efx->net_dev, "%s: failed type=%u\n",
980 __func__, type);
Ben Hutchingsb548a982010-04-28 09:28:36 +0000981fail1:
Ben Hutchings62776d02010-06-23 11:30:07 +0000982 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsb548a982010-04-28 09:28:36 +0000983 return rc;
Ben Hutchings2e803402010-02-03 09:31:01 +0000984}
985
Steve Hodgson8b2103a2010-02-03 09:30:17 +0000986static int efx_mcdi_read_assertion(struct efx_nic *efx)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000987{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100988 MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_ASSERTS_IN_LEN);
989 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_ASSERTS_OUT_LEN);
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +0100990 unsigned int flags, index;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000991 const char *reason;
992 size_t outlen;
993 int retry;
994 int rc;
995
Steve Hodgson8b2103a2010-02-03 09:30:17 +0000996 /* Attempt to read any stored assertion state before we reboot
997 * the mcfw out of the assertion handler. Retry twice, once
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000998 * because a boot-time assertion might cause this command to fail
999 * with EINTR. And once again because GET_ASSERTS can race with
1000 * MC_CMD_REBOOT running on the other port. */
1001 retry = 2;
1002 do {
Steve Hodgson8b2103a2010-02-03 09:30:17 +00001003 MCDI_SET_DWORD(inbuf, GET_ASSERTS_IN_CLEAR, 1);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001004 rc = efx_mcdi_rpc(efx, MC_CMD_GET_ASSERTS,
Steve Hodgson8b2103a2010-02-03 09:30:17 +00001005 inbuf, MC_CMD_GET_ASSERTS_IN_LEN,
1006 outbuf, sizeof(outbuf), &outlen);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001007 } while ((rc == -EINTR || rc == -EIO) && retry-- > 0);
1008
1009 if (rc)
1010 return rc;
1011 if (outlen < MC_CMD_GET_ASSERTS_OUT_LEN)
Ben Hutchings00bbb4a2010-04-28 09:27:14 +00001012 return -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001013
Steve Hodgson8b2103a2010-02-03 09:30:17 +00001014 /* Print out any recorded assertion state */
1015 flags = MCDI_DWORD(outbuf, GET_ASSERTS_OUT_GLOBAL_FLAGS);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001016 if (flags == MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS)
1017 return 0;
1018
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001019 reason = (flags == MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL)
1020 ? "system-level assertion"
1021 : (flags == MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL)
1022 ? "thread-level assertion"
1023 : (flags == MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED)
1024 ? "watchdog reset"
1025 : "unknown assertion";
Ben Hutchings62776d02010-06-23 11:30:07 +00001026 netif_err(efx, hw, efx->net_dev,
1027 "MCPU %s at PC = 0x%.8x in thread 0x%.8x\n", reason,
1028 MCDI_DWORD(outbuf, GET_ASSERTS_OUT_SAVED_PC_OFFS),
1029 MCDI_DWORD(outbuf, GET_ASSERTS_OUT_THREAD_OFFS));
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001030
1031 /* Print out the registers */
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +01001032 for (index = 0;
1033 index < MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_NUM;
1034 index++)
1035 netif_err(efx, hw, efx->net_dev, "R%.2d (?): 0x%.8x\n",
1036 1 + index,
1037 MCDI_ARRAY_DWORD(outbuf, GET_ASSERTS_OUT_GP_REGS_OFFS,
1038 index));
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001039
1040 return 0;
1041}
1042
Steve Hodgson8b2103a2010-02-03 09:30:17 +00001043static void efx_mcdi_exit_assertion(struct efx_nic *efx)
1044{
Ben Hutchings59cfc472012-09-14 17:30:10 +01001045 MCDI_DECLARE_BUF(inbuf, MC_CMD_REBOOT_IN_LEN);
Steve Hodgson8b2103a2010-02-03 09:30:17 +00001046
Ben Hutchings0f1e54a2012-07-02 23:37:40 +01001047 /* If the MC is running debug firmware, it might now be
1048 * waiting for a debugger to attach, but we just want it to
1049 * reboot. We set a flag that makes the command a no-op if it
1050 * has already done so. We don't know what return code to
1051 * expect (0 or -EIO), so ignore it.
1052 */
Steve Hodgson8b2103a2010-02-03 09:30:17 +00001053 BUILD_BUG_ON(MC_CMD_REBOOT_OUT_LEN != 0);
1054 MCDI_SET_DWORD(inbuf, REBOOT_IN_FLAGS,
1055 MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION);
Ben Hutchings0f1e54a2012-07-02 23:37:40 +01001056 (void) efx_mcdi_rpc(efx, MC_CMD_REBOOT, inbuf, MC_CMD_REBOOT_IN_LEN,
1057 NULL, 0, NULL);
Steve Hodgson8b2103a2010-02-03 09:30:17 +00001058}
1059
1060int efx_mcdi_handle_assertion(struct efx_nic *efx)
1061{
1062 int rc;
1063
1064 rc = efx_mcdi_read_assertion(efx);
1065 if (rc)
1066 return rc;
1067
1068 efx_mcdi_exit_assertion(efx);
1069
1070 return 0;
1071}
1072
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001073void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
1074{
Ben Hutchings59cfc472012-09-14 17:30:10 +01001075 MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_ID_LED_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001076 int rc;
1077
1078 BUILD_BUG_ON(EFX_LED_OFF != MC_CMD_LED_OFF);
1079 BUILD_BUG_ON(EFX_LED_ON != MC_CMD_LED_ON);
1080 BUILD_BUG_ON(EFX_LED_DEFAULT != MC_CMD_LED_DEFAULT);
1081
1082 BUILD_BUG_ON(MC_CMD_SET_ID_LED_OUT_LEN != 0);
1083
1084 MCDI_SET_DWORD(inbuf, SET_ID_LED_IN_STATE, mode);
1085
1086 rc = efx_mcdi_rpc(efx, MC_CMD_SET_ID_LED, inbuf, sizeof(inbuf),
1087 NULL, 0, NULL);
1088 if (rc)
Ben Hutchings62776d02010-06-23 11:30:07 +00001089 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
1090 __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001091}
1092
Ben Hutchings6bff8612012-09-18 02:33:52 +01001093static int efx_mcdi_reset_port(struct efx_nic *efx)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001094{
Ben Hutchings05a93202011-12-20 00:44:06 +00001095 int rc = efx_mcdi_rpc(efx, MC_CMD_ENTITY_RESET, NULL, 0, NULL, 0, NULL);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001096 if (rc)
Ben Hutchings62776d02010-06-23 11:30:07 +00001097 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
1098 __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001099 return rc;
1100}
1101
Ben Hutchings6bff8612012-09-18 02:33:52 +01001102static int efx_mcdi_reset_mc(struct efx_nic *efx)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001103{
Ben Hutchings59cfc472012-09-14 17:30:10 +01001104 MCDI_DECLARE_BUF(inbuf, MC_CMD_REBOOT_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001105 int rc;
1106
1107 BUILD_BUG_ON(MC_CMD_REBOOT_OUT_LEN != 0);
1108 MCDI_SET_DWORD(inbuf, REBOOT_IN_FLAGS, 0);
1109 rc = efx_mcdi_rpc(efx, MC_CMD_REBOOT, inbuf, sizeof(inbuf),
1110 NULL, 0, NULL);
1111 /* White is black, and up is down */
1112 if (rc == -EIO)
1113 return 0;
1114 if (rc == 0)
1115 rc = -EIO;
Ben Hutchings62776d02010-06-23 11:30:07 +00001116 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001117 return rc;
1118}
1119
Ben Hutchings6bff8612012-09-18 02:33:52 +01001120enum reset_type efx_mcdi_map_reset_reason(enum reset_type reason)
1121{
1122 return RESET_TYPE_RECOVER_OR_ALL;
1123}
1124
1125int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method)
1126{
1127 int rc;
1128
1129 /* Recover from a failed assertion pre-reset */
1130 rc = efx_mcdi_handle_assertion(efx);
1131 if (rc)
1132 return rc;
1133
1134 if (method == RESET_TYPE_WORLD)
1135 return efx_mcdi_reset_mc(efx);
1136 else
1137 return efx_mcdi_reset_port(efx);
1138}
1139
stephen hemmingerd2156972010-10-18 05:27:31 +00001140static int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type,
1141 const u8 *mac, int *id_out)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001142{
Ben Hutchings59cfc472012-09-14 17:30:10 +01001143 MCDI_DECLARE_BUF(inbuf, MC_CMD_WOL_FILTER_SET_IN_LEN);
1144 MCDI_DECLARE_BUF(outbuf, MC_CMD_WOL_FILTER_SET_OUT_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001145 size_t outlen;
1146 int rc;
1147
1148 MCDI_SET_DWORD(inbuf, WOL_FILTER_SET_IN_WOL_TYPE, type);
1149 MCDI_SET_DWORD(inbuf, WOL_FILTER_SET_IN_FILTER_MODE,
1150 MC_CMD_FILTER_MODE_SIMPLE);
1151 memcpy(MCDI_PTR(inbuf, WOL_FILTER_SET_IN_MAGIC_MAC), mac, ETH_ALEN);
1152
1153 rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_SET, inbuf, sizeof(inbuf),
1154 outbuf, sizeof(outbuf), &outlen);
1155 if (rc)
1156 goto fail;
1157
1158 if (outlen < MC_CMD_WOL_FILTER_SET_OUT_LEN) {
Ben Hutchings00bbb4a2010-04-28 09:27:14 +00001159 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001160 goto fail;
1161 }
1162
1163 *id_out = (int)MCDI_DWORD(outbuf, WOL_FILTER_SET_OUT_FILTER_ID);
1164
1165 return 0;
1166
1167fail:
1168 *id_out = -1;
Ben Hutchings62776d02010-06-23 11:30:07 +00001169 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001170 return rc;
1171
1172}
1173
1174
1175int
1176efx_mcdi_wol_filter_set_magic(struct efx_nic *efx, const u8 *mac, int *id_out)
1177{
1178 return efx_mcdi_wol_filter_set(efx, MC_CMD_WOL_TYPE_MAGIC, mac, id_out);
1179}
1180
1181
1182int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out)
1183{
Ben Hutchings59cfc472012-09-14 17:30:10 +01001184 MCDI_DECLARE_BUF(outbuf, MC_CMD_WOL_FILTER_GET_OUT_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001185 size_t outlen;
1186 int rc;
1187
1188 rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_GET, NULL, 0,
1189 outbuf, sizeof(outbuf), &outlen);
1190 if (rc)
1191 goto fail;
1192
1193 if (outlen < MC_CMD_WOL_FILTER_GET_OUT_LEN) {
Ben Hutchings00bbb4a2010-04-28 09:27:14 +00001194 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001195 goto fail;
1196 }
1197
1198 *id_out = (int)MCDI_DWORD(outbuf, WOL_FILTER_GET_OUT_FILTER_ID);
1199
1200 return 0;
1201
1202fail:
1203 *id_out = -1;
Ben Hutchings62776d02010-06-23 11:30:07 +00001204 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001205 return rc;
1206}
1207
1208
1209int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id)
1210{
Ben Hutchings59cfc472012-09-14 17:30:10 +01001211 MCDI_DECLARE_BUF(inbuf, MC_CMD_WOL_FILTER_REMOVE_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001212 int rc;
1213
1214 MCDI_SET_DWORD(inbuf, WOL_FILTER_REMOVE_IN_FILTER_ID, (u32)id);
1215
1216 rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_REMOVE, inbuf, sizeof(inbuf),
1217 NULL, 0, NULL);
1218 if (rc)
1219 goto fail;
1220
1221 return 0;
1222
1223fail:
Ben Hutchings62776d02010-06-23 11:30:07 +00001224 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001225 return rc;
1226}
1227
Ben Hutchingscd2d5b52012-02-14 00:48:07 +00001228int efx_mcdi_flush_rxqs(struct efx_nic *efx)
1229{
1230 struct efx_channel *channel;
1231 struct efx_rx_queue *rx_queue;
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +01001232 MCDI_DECLARE_BUF(inbuf,
1233 MC_CMD_FLUSH_RX_QUEUES_IN_LEN(EFX_MAX_CHANNELS));
Ben Hutchingscd2d5b52012-02-14 00:48:07 +00001234 int rc, count;
1235
Ben Hutchings45078372012-09-19 02:53:34 +01001236 BUILD_BUG_ON(EFX_MAX_CHANNELS >
1237 MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MAXNUM);
1238
Ben Hutchingscd2d5b52012-02-14 00:48:07 +00001239 count = 0;
1240 efx_for_each_channel(channel, efx) {
1241 efx_for_each_channel_rx_queue(rx_queue, channel) {
1242 if (rx_queue->flush_pending) {
1243 rx_queue->flush_pending = false;
1244 atomic_dec(&efx->rxq_flush_pending);
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +01001245 MCDI_SET_ARRAY_DWORD(
1246 inbuf, FLUSH_RX_QUEUES_IN_QID_OFST,
1247 count, efx_rx_queue_index(rx_queue));
1248 count++;
Ben Hutchingscd2d5b52012-02-14 00:48:07 +00001249 }
1250 }
1251 }
1252
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +01001253 rc = efx_mcdi_rpc(efx, MC_CMD_FLUSH_RX_QUEUES, inbuf,
1254 MC_CMD_FLUSH_RX_QUEUES_IN_LEN(count), NULL, 0, NULL);
Ben Hutchingsbbec9692012-09-11 18:25:13 +01001255 WARN_ON(rc < 0);
Ben Hutchingscd2d5b52012-02-14 00:48:07 +00001256
Ben Hutchingscd2d5b52012-02-14 00:48:07 +00001257 return rc;
1258}
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001259
1260int efx_mcdi_wol_filter_reset(struct efx_nic *efx)
1261{
1262 int rc;
1263
1264 rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_RESET, NULL, 0, NULL, 0, NULL);
1265 if (rc)
1266 goto fail;
1267
1268 return 0;
1269
1270fail:
Ben Hutchings62776d02010-06-23 11:30:07 +00001271 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001272 return rc;
1273}
1274