blob: 2c5ee893feeb3031d35f4a54376348ba6a048af1 [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 Hutchings9528b922012-09-14 17:31:41 +0100115static void
116efx_mcdi_copyout(struct efx_nic *efx, efx_dword_t *outbuf, size_t outlen)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000117{
118 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000119
120 BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000121
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100122 efx->type->mcdi_read_response(efx, outbuf, mcdi->resp_hdr_len, outlen);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000123}
124
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100125static int efx_mcdi_errno(unsigned int mcdi_err)
126{
127 switch (mcdi_err) {
128 case 0:
129 return 0;
130#define TRANSLATE_ERROR(name) \
131 case MC_CMD_ERR_ ## name: \
132 return -name;
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100133 TRANSLATE_ERROR(EPERM);
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100134 TRANSLATE_ERROR(ENOENT);
135 TRANSLATE_ERROR(EINTR);
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100136 TRANSLATE_ERROR(EAGAIN);
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100137 TRANSLATE_ERROR(EACCES);
138 TRANSLATE_ERROR(EBUSY);
139 TRANSLATE_ERROR(EINVAL);
140 TRANSLATE_ERROR(EDEADLK);
141 TRANSLATE_ERROR(ENOSYS);
142 TRANSLATE_ERROR(ETIME);
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100143 TRANSLATE_ERROR(EALREADY);
144 TRANSLATE_ERROR(ENOSPC);
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100145#undef TRANSLATE_ERROR
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100146 case MC_CMD_ERR_ALLOC_FAIL:
147 return -ENOBUFS;
148 case MC_CMD_ERR_MAC_EXIST:
149 return -EADDRINUSE;
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100150 default:
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100151 return -EPROTO;
152 }
153}
154
155static void efx_mcdi_read_response_header(struct efx_nic *efx)
156{
157 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
158 unsigned int respseq, respcmd, error;
159 efx_dword_t hdr;
160
161 efx->type->mcdi_read_response(efx, &hdr, 0, 4);
162 respseq = EFX_DWORD_FIELD(hdr, MCDI_HEADER_SEQ);
163 respcmd = EFX_DWORD_FIELD(hdr, MCDI_HEADER_CODE);
164 error = EFX_DWORD_FIELD(hdr, MCDI_HEADER_ERROR);
165
166 if (respcmd != MC_CMD_V2_EXTN) {
167 mcdi->resp_hdr_len = 4;
168 mcdi->resp_data_len = EFX_DWORD_FIELD(hdr, MCDI_HEADER_DATALEN);
169 } else {
170 efx->type->mcdi_read_response(efx, &hdr, 4, 4);
171 mcdi->resp_hdr_len = 8;
172 mcdi->resp_data_len =
173 EFX_DWORD_FIELD(hdr, MC_CMD_V2_EXTN_IN_ACTUAL_LEN);
174 }
175
176 if (error && mcdi->resp_data_len == 0) {
177 netif_err(efx, hw, efx->net_dev, "MC rebooted\n");
178 mcdi->resprc = -EIO;
179 } else if ((respseq ^ mcdi->seqno) & SEQ_MASK) {
180 netif_err(efx, hw, efx->net_dev,
181 "MC response mismatch tx seq 0x%x rx seq 0x%x\n",
182 respseq, mcdi->seqno);
183 mcdi->resprc = -EIO;
184 } else if (error) {
185 efx->type->mcdi_read_response(efx, &hdr, mcdi->resp_hdr_len, 4);
186 mcdi->resprc =
187 efx_mcdi_errno(EFX_DWORD_FIELD(hdr, EFX_DWORD_0));
188 } else {
189 mcdi->resprc = 0;
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100190 }
191}
192
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000193static int efx_mcdi_poll(struct efx_nic *efx)
194{
195 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
Ben Hutchingsebf98e72012-12-01 02:21:17 +0000196 unsigned long time, finish;
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100197 unsigned int spins;
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100198 int rc;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000199
200 /* Check for a reboot atomically with respect to efx_mcdi_copyout() */
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100201 rc = efx_mcdi_poll_reboot(efx);
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100202 if (rc) {
203 mcdi->resprc = rc;
204 mcdi->resp_hdr_len = 0;
205 mcdi->resp_data_len = 0;
206 return 0;
207 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000208
209 /* Poll for completion. Poll quickly (once a us) for the 1st jiffy,
210 * because generally mcdi responses are fast. After that, back off
211 * and poll once a jiffy (approximately)
212 */
213 spins = TICK_USEC;
Ben Hutchingsebf98e72012-12-01 02:21:17 +0000214 finish = jiffies + MCDI_RPC_TIMEOUT;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000215
216 while (1) {
217 if (spins != 0) {
218 --spins;
219 udelay(1);
Ben Hutchings55029c12010-01-13 04:34:25 +0000220 } else {
221 schedule_timeout_uninterruptible(1);
222 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000223
Ben Hutchingsebf98e72012-12-01 02:21:17 +0000224 time = jiffies;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000225
Ben Hutchings86c432c2011-09-01 12:09:29 +0000226 rmb();
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100227 if (efx->type->mcdi_poll_response(efx))
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000228 break;
229
Ben Hutchingsebf98e72012-12-01 02:21:17 +0000230 if (time_after(time, finish))
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000231 return -ETIMEDOUT;
232 }
233
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100234 efx_mcdi_read_response_header(efx);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000235
236 /* Return rc=0 like wait_event_timeout() */
237 return 0;
238}
239
Ben Hutchings876be082012-10-01 20:58:35 +0100240/* Test and clear MC-rebooted flag for this port/function; reset
241 * software state as necessary.
242 */
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000243int efx_mcdi_poll_reboot(struct efx_nic *efx)
244{
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100245 int rc;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000246
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100247 if (!efx->mcdi)
248 return 0;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000249
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100250 rc = efx->type->mcdi_poll_reboot(efx);
251 if (!rc)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000252 return 0;
253
Ben Hutchings876be082012-10-01 20:58:35 +0100254 /* MAC statistics have been cleared on the NIC; clear our copy
255 * so that efx_update_diff_stat() can continue to work.
256 */
257 memset(&efx->mac_stats, 0, sizeof(efx->mac_stats));
258
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100259 return rc;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000260}
261
262static void efx_mcdi_acquire(struct efx_mcdi_iface *mcdi)
263{
264 /* Wait until the interface becomes QUIESCENT and we win the race
265 * to mark it RUNNING. */
266 wait_event(mcdi->wq,
267 atomic_cmpxchg(&mcdi->state,
268 MCDI_STATE_QUIESCENT,
269 MCDI_STATE_RUNNING)
270 == MCDI_STATE_QUIESCENT);
271}
272
273static int efx_mcdi_await_completion(struct efx_nic *efx)
274{
275 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
276
277 if (wait_event_timeout(
278 mcdi->wq,
279 atomic_read(&mcdi->state) == MCDI_STATE_COMPLETED,
Ben Hutchingsebf98e72012-12-01 02:21:17 +0000280 MCDI_RPC_TIMEOUT) == 0)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000281 return -ETIMEDOUT;
282
283 /* Check if efx_mcdi_set_mode() switched us back to polled completions.
284 * In which case, poll for completions directly. If efx_mcdi_ev_cpl()
285 * completed the request first, then we'll just end up completing the
286 * request again, which is safe.
287 *
288 * We need an smp_rmb() to synchronise with efx_mcdi_mode_poll(), which
289 * wait_event_timeout() implicitly provides.
290 */
291 if (mcdi->mode == MCDI_MODE_POLL)
292 return efx_mcdi_poll(efx);
293
294 return 0;
295}
296
297static bool efx_mcdi_complete(struct efx_mcdi_iface *mcdi)
298{
299 /* If the interface is RUNNING, then move to COMPLETED and wake any
300 * waiters. If the interface isn't in RUNNING then we've received a
301 * duplicate completion after we've already transitioned back to
302 * QUIESCENT. [A subsequent invocation would increment seqno, so would
303 * have failed the seqno check].
304 */
305 if (atomic_cmpxchg(&mcdi->state,
306 MCDI_STATE_RUNNING,
307 MCDI_STATE_COMPLETED) == MCDI_STATE_RUNNING) {
308 wake_up(&mcdi->wq);
309 return true;
310 }
311
312 return false;
313}
314
315static void efx_mcdi_release(struct efx_mcdi_iface *mcdi)
316{
317 atomic_set(&mcdi->state, MCDI_STATE_QUIESCENT);
318 wake_up(&mcdi->wq);
319}
320
321static void efx_mcdi_ev_cpl(struct efx_nic *efx, unsigned int seqno,
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100322 unsigned int datalen, unsigned int mcdi_err)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000323{
324 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
325 bool wake = false;
326
327 spin_lock(&mcdi->iface_lock);
328
329 if ((seqno ^ mcdi->seqno) & SEQ_MASK) {
330 if (mcdi->credits)
331 /* The request has been cancelled */
332 --mcdi->credits;
333 else
Ben Hutchings62776d02010-06-23 11:30:07 +0000334 netif_err(efx, hw, efx->net_dev,
335 "MC response mismatch tx seq 0x%x rx "
336 "seq 0x%x\n", seqno, mcdi->seqno);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000337 } else {
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100338 if (efx->type->mcdi_max_ver >= 2) {
339 /* MCDI v2 responses don't fit in an event */
340 efx_mcdi_read_response_header(efx);
341 } else {
342 mcdi->resprc = efx_mcdi_errno(mcdi_err);
343 mcdi->resp_hdr_len = 4;
344 mcdi->resp_data_len = datalen;
345 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000346
347 wake = true;
348 }
349
350 spin_unlock(&mcdi->iface_lock);
351
352 if (wake)
353 efx_mcdi_complete(mcdi);
354}
355
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000356int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd,
Ben Hutchings9528b922012-09-14 17:31:41 +0100357 const efx_dword_t *inbuf, size_t inlen,
358 efx_dword_t *outbuf, size_t outlen,
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000359 size_t *outlen_actual)
360{
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100361 int rc;
362
363 rc = efx_mcdi_rpc_start(efx, cmd, inbuf, inlen);
364 if (rc)
365 return rc;
Stuart Hodgsonc3cba722012-07-16 17:40:47 +0100366 return efx_mcdi_rpc_finish(efx, cmd, inlen,
367 outbuf, outlen, outlen_actual);
368}
369
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100370int efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd,
371 const efx_dword_t *inbuf, size_t inlen)
Stuart Hodgsonc3cba722012-07-16 17:40:47 +0100372{
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000373 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
Stuart Hodgsonc3cba722012-07-16 17:40:47 +0100374
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100375 if (efx->type->mcdi_max_ver < 0 ||
376 (efx->type->mcdi_max_ver < 2 &&
377 cmd > MC_CMD_CMD_SPACE_ESCAPE_7))
378 return -EINVAL;
379
380 if (inlen > MCDI_CTL_SDU_LEN_MAX_V2 ||
381 (efx->type->mcdi_max_ver < 2 &&
382 inlen > MCDI_CTL_SDU_LEN_MAX_V1))
383 return -EMSGSIZE;
384
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000385 efx_mcdi_acquire(mcdi);
386
387 /* Serialise with efx_mcdi_ev_cpl() and efx_mcdi_ev_death() */
388 spin_lock_bh(&mcdi->iface_lock);
389 ++mcdi->seqno;
390 spin_unlock_bh(&mcdi->iface_lock);
391
392 efx_mcdi_copyin(efx, cmd, inbuf, inlen);
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100393 return 0;
Stuart Hodgsonc3cba722012-07-16 17:40:47 +0100394}
395
396int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
Ben Hutchings9528b922012-09-14 17:31:41 +0100397 efx_dword_t *outbuf, size_t outlen,
398 size_t *outlen_actual)
Stuart Hodgsonc3cba722012-07-16 17:40:47 +0100399{
400 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
401 int rc;
402
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000403 if (mcdi->mode == MCDI_MODE_POLL)
404 rc = efx_mcdi_poll(efx);
405 else
406 rc = efx_mcdi_await_completion(efx);
407
408 if (rc != 0) {
409 /* Close the race with efx_mcdi_ev_cpl() executing just too late
410 * and completing a request we've just cancelled, by ensuring
411 * that the seqno check therein fails.
412 */
413 spin_lock_bh(&mcdi->iface_lock);
414 ++mcdi->seqno;
415 ++mcdi->credits;
416 spin_unlock_bh(&mcdi->iface_lock);
417
Ben Hutchings62776d02010-06-23 11:30:07 +0000418 netif_err(efx, hw, efx->net_dev,
419 "MC command 0x%x inlen %d mode %d timed out\n",
420 cmd, (int)inlen, mcdi->mode);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000421 } else {
422 size_t resplen;
423
424 /* At the very least we need a memory barrier here to ensure
425 * we pick up changes from efx_mcdi_ev_cpl(). Protect against
426 * a spurious efx_mcdi_ev_cpl() running concurrently by
427 * acquiring the iface_lock. */
428 spin_lock_bh(&mcdi->iface_lock);
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100429 rc = mcdi->resprc;
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100430 resplen = mcdi->resp_data_len;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000431 spin_unlock_bh(&mcdi->iface_lock);
432
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100433 BUG_ON(rc > 0);
434
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000435 if (rc == 0) {
436 efx_mcdi_copyout(efx, outbuf,
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100437 min(outlen, mcdi->resp_data_len));
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000438 if (outlen_actual != NULL)
439 *outlen_actual = resplen;
440 } else if (cmd == MC_CMD_REBOOT && rc == -EIO)
441 ; /* Don't reset if MC_CMD_REBOOT returns EIO */
442 else if (rc == -EIO || rc == -EINTR) {
Ben Hutchings62776d02010-06-23 11:30:07 +0000443 netif_err(efx, hw, efx->net_dev, "MC fatal error %d\n",
444 -rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000445 efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE);
446 } else
Ben Hutchingsf18ca362010-12-02 13:46:09 +0000447 netif_dbg(efx, hw, efx->net_dev,
Ben Hutchings62776d02010-06-23 11:30:07 +0000448 "MC command 0x%x inlen %d failed rc=%d\n",
449 cmd, (int)inlen, -rc);
Ben Hutchings3f713bf2011-12-20 23:39:31 +0000450
451 if (rc == -EIO || rc == -EINTR) {
452 msleep(MCDI_STATUS_SLEEP_MS);
453 efx_mcdi_poll_reboot(efx);
454 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000455 }
456
457 efx_mcdi_release(mcdi);
458 return rc;
459}
460
461void efx_mcdi_mode_poll(struct efx_nic *efx)
462{
463 struct efx_mcdi_iface *mcdi;
464
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100465 if (!efx->mcdi)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000466 return;
467
468 mcdi = efx_mcdi(efx);
469 if (mcdi->mode == MCDI_MODE_POLL)
470 return;
471
472 /* We can switch from event completion to polled completion, because
473 * mcdi requests are always completed in shared memory. We do this by
474 * switching the mode to POLL'd then completing the request.
475 * efx_mcdi_await_completion() will then call efx_mcdi_poll().
476 *
477 * We need an smp_wmb() to synchronise with efx_mcdi_await_completion(),
478 * which efx_mcdi_complete() provides for us.
479 */
480 mcdi->mode = MCDI_MODE_POLL;
481
482 efx_mcdi_complete(mcdi);
483}
484
485void efx_mcdi_mode_event(struct efx_nic *efx)
486{
487 struct efx_mcdi_iface *mcdi;
488
Ben Hutchingsf3ad5002012-09-18 02:33:56 +0100489 if (!efx->mcdi)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000490 return;
491
492 mcdi = efx_mcdi(efx);
493
494 if (mcdi->mode == MCDI_MODE_EVENTS)
495 return;
496
497 /* We can't switch from polled to event completion in the middle of a
498 * request, because the completion method is specified in the request.
499 * So acquire the interface to serialise the requestors. We don't need
500 * to acquire the iface_lock to change the mode here, but we do need a
501 * write memory barrier ensure that efx_mcdi_rpc() sees it, which
502 * efx_mcdi_acquire() provides.
503 */
504 efx_mcdi_acquire(mcdi);
505 mcdi->mode = MCDI_MODE_EVENTS;
506 efx_mcdi_release(mcdi);
507}
508
509static void efx_mcdi_ev_death(struct efx_nic *efx, int rc)
510{
511 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
512
513 /* If there is an outstanding MCDI request, it has been terminated
514 * either by a BADASSERT or REBOOT event. If the mcdi interface is
515 * in polled mode, then do nothing because the MC reboot handler will
516 * set the header correctly. However, if the mcdi interface is waiting
517 * for a CMDDONE event it won't receive it [and since all MCDI events
518 * are sent to the same queue, we can't be racing with
519 * efx_mcdi_ev_cpl()]
520 *
521 * There's a race here with efx_mcdi_rpc(), because we might receive
522 * a REBOOT event *before* the request has been copied out. In polled
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300523 * mode (during startup) this is irrelevant, because efx_mcdi_complete()
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000524 * is ignored. In event mode, this condition is just an edge-case of
525 * receiving a REBOOT event after posting the MCDI request. Did the mc
526 * reboot before or after the copyout? The best we can do always is
527 * just return failure.
528 */
529 spin_lock(&mcdi->iface_lock);
530 if (efx_mcdi_complete(mcdi)) {
531 if (mcdi->mode == MCDI_MODE_EVENTS) {
532 mcdi->resprc = rc;
Ben Hutchingsdf2cd8a2012-09-19 00:56:18 +0100533 mcdi->resp_hdr_len = 0;
534 mcdi->resp_data_len = 0;
Steve Hodgson18e3ee22010-12-02 13:46:55 +0000535 ++mcdi->credits;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000536 }
Ben Hutchings3f713bf2011-12-20 23:39:31 +0000537 } else {
538 int count;
539
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000540 /* Nobody was waiting for an MCDI request, so trigger a reset */
541 efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE);
542
Ben Hutchings3f713bf2011-12-20 23:39:31 +0000543 /* Consume the status word since efx_mcdi_rpc_finish() won't */
544 for (count = 0; count < MCDI_STATUS_DELAY_COUNT; ++count) {
545 if (efx_mcdi_poll_reboot(efx))
546 break;
547 udelay(MCDI_STATUS_DELAY_US);
548 }
549 }
550
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000551 spin_unlock(&mcdi->iface_lock);
552}
553
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000554/* Called from falcon_process_eventq for MCDI events */
555void efx_mcdi_process_event(struct efx_channel *channel,
556 efx_qword_t *event)
557{
558 struct efx_nic *efx = channel->efx;
559 int code = EFX_QWORD_FIELD(*event, MCDI_EVENT_CODE);
560 u32 data = EFX_QWORD_FIELD(*event, MCDI_EVENT_DATA);
561
562 switch (code) {
563 case MCDI_EVENT_CODE_BADSSERT:
Ben Hutchings62776d02010-06-23 11:30:07 +0000564 netif_err(efx, hw, efx->net_dev,
565 "MC watchdog or assertion failure at 0x%x\n", data);
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100566 efx_mcdi_ev_death(efx, -EINTR);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000567 break;
568
569 case MCDI_EVENT_CODE_PMNOTICE:
Ben Hutchings62776d02010-06-23 11:30:07 +0000570 netif_info(efx, wol, efx->net_dev, "MCDI PM event.\n");
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000571 break;
572
573 case MCDI_EVENT_CODE_CMDDONE:
574 efx_mcdi_ev_cpl(efx,
575 MCDI_EVENT_FIELD(*event, CMDDONE_SEQ),
576 MCDI_EVENT_FIELD(*event, CMDDONE_DATALEN),
577 MCDI_EVENT_FIELD(*event, CMDDONE_ERRNO));
578 break;
579
580 case MCDI_EVENT_CODE_LINKCHANGE:
581 efx_mcdi_process_link_change(efx, event);
582 break;
583 case MCDI_EVENT_CODE_SENSOREVT:
584 efx_mcdi_sensor_event(efx, event);
585 break;
586 case MCDI_EVENT_CODE_SCHEDERR:
Ben Hutchings62776d02010-06-23 11:30:07 +0000587 netif_info(efx, hw, efx->net_dev,
588 "MC Scheduler error address=0x%x\n", data);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000589 break;
590 case MCDI_EVENT_CODE_REBOOT:
Ben Hutchings62776d02010-06-23 11:30:07 +0000591 netif_info(efx, hw, efx->net_dev, "MC Reboot\n");
Ben Hutchings5bc283e2012-10-08 21:43:00 +0100592 efx_mcdi_ev_death(efx, -EIO);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000593 break;
594 case MCDI_EVENT_CODE_MAC_STATS_DMA:
595 /* MAC stats are gather lazily. We can ignore this. */
596 break;
Ben Hutchingscd2d5b52012-02-14 00:48:07 +0000597 case MCDI_EVENT_CODE_FLR:
598 efx_sriov_flr(efx, MCDI_EVENT_FIELD(*event, FLR_VF));
599 break;
Stuart Hodgson7c236c42012-09-03 11:09:36 +0100600 case MCDI_EVENT_CODE_PTP_RX:
601 case MCDI_EVENT_CODE_PTP_FAULT:
602 case MCDI_EVENT_CODE_PTP_PPS:
603 efx_ptp_event(efx, event);
604 break;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000605
606 default:
Ben Hutchings62776d02010-06-23 11:30:07 +0000607 netif_err(efx, hw, efx->net_dev, "Unknown MCDI event 0x%x\n",
608 code);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000609 }
610}
611
612/**************************************************************************
613 *
614 * Specific request functions
615 *
616 **************************************************************************
617 */
618
Ben Hutchingse5f0fd22011-02-24 23:57:47 +0000619void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000620{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100621 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_VERSION_OUT_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000622 size_t outlength;
623 const __le16 *ver_words;
624 int rc;
625
626 BUILD_BUG_ON(MC_CMD_GET_VERSION_IN_LEN != 0);
627
628 rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, NULL, 0,
629 outbuf, sizeof(outbuf), &outlength);
630 if (rc)
631 goto fail;
632
Ben Hutchings05a93202011-12-20 00:44:06 +0000633 if (outlength < MC_CMD_GET_VERSION_OUT_LEN) {
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000634 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000635 goto fail;
636 }
637
638 ver_words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_OUT_VERSION);
Ben Hutchingse5f0fd22011-02-24 23:57:47 +0000639 snprintf(buf, len, "%u.%u.%u.%u",
640 le16_to_cpu(ver_words[0]), le16_to_cpu(ver_words[1]),
641 le16_to_cpu(ver_words[2]), le16_to_cpu(ver_words[3]));
642 return;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000643
644fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000645 netif_err(efx, probe, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingse5f0fd22011-02-24 23:57:47 +0000646 buf[0] = 0;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000647}
648
649int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
650 bool *was_attached)
651{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100652 MCDI_DECLARE_BUF(inbuf, MC_CMD_DRV_ATTACH_IN_LEN);
653 MCDI_DECLARE_BUF(outbuf, MC_CMD_DRV_ATTACH_OUT_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000654 size_t outlen;
655 int rc;
656
657 MCDI_SET_DWORD(inbuf, DRV_ATTACH_IN_NEW_STATE,
658 driver_operating ? 1 : 0);
659 MCDI_SET_DWORD(inbuf, DRV_ATTACH_IN_UPDATE, 1);
Ben Hutchingsf2b0bef2013-08-20 20:35:50 +0100660 MCDI_SET_DWORD(inbuf, DRV_ATTACH_IN_FIRMWARE_ID, MC_CMD_FW_LOW_LATENCY);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000661
662 rc = efx_mcdi_rpc(efx, MC_CMD_DRV_ATTACH, inbuf, sizeof(inbuf),
663 outbuf, sizeof(outbuf), &outlen);
664 if (rc)
665 goto fail;
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000666 if (outlen < MC_CMD_DRV_ATTACH_OUT_LEN) {
667 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000668 goto fail;
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000669 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000670
671 if (was_attached != NULL)
672 *was_attached = MCDI_DWORD(outbuf, DRV_ATTACH_OUT_OLD_STATE);
673 return 0;
674
675fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000676 netif_err(efx, probe, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000677 return rc;
678}
679
680int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
Matthew Slattery6aa9c7f2010-07-14 15:36:19 +0100681 u16 *fw_subtype_list, u32 *capabilities)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000682{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100683 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_BOARD_CFG_OUT_LENMAX);
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +0100684 size_t outlen, i;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000685 int port_num = efx_port_num(efx);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000686 int rc;
687
688 BUILD_BUG_ON(MC_CMD_GET_BOARD_CFG_IN_LEN != 0);
689
690 rc = efx_mcdi_rpc(efx, MC_CMD_GET_BOARD_CFG, NULL, 0,
691 outbuf, sizeof(outbuf), &outlen);
692 if (rc)
693 goto fail;
694
Ben Hutchings05a93202011-12-20 00:44:06 +0000695 if (outlen < MC_CMD_GET_BOARD_CFG_OUT_LENMIN) {
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000696 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000697 goto fail;
698 }
699
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000700 if (mac_address)
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +0100701 memcpy(mac_address,
702 port_num ?
703 MCDI_PTR(outbuf, GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1) :
704 MCDI_PTR(outbuf, GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0),
705 ETH_ALEN);
Ben Hutchingsbfeed902012-09-07 00:58:10 +0100706 if (fw_subtype_list) {
Ben Hutchingsbfeed902012-09-07 00:58:10 +0100707 for (i = 0;
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +0100708 i < MCDI_VAR_ARRAY_LEN(outlen,
709 GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST);
710 i++)
711 fw_subtype_list[i] = MCDI_ARRAY_WORD(
712 outbuf, GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST, i);
713 for (; i < MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MAXNUM; i++)
714 fw_subtype_list[i] = 0;
Ben Hutchingsbfeed902012-09-07 00:58:10 +0100715 }
Matthew Slattery6aa9c7f2010-07-14 15:36:19 +0100716 if (capabilities) {
717 if (port_num)
718 *capabilities = MCDI_DWORD(outbuf,
719 GET_BOARD_CFG_OUT_CAPABILITIES_PORT1);
720 else
721 *capabilities = MCDI_DWORD(outbuf,
722 GET_BOARD_CFG_OUT_CAPABILITIES_PORT0);
723 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000724
725 return 0;
726
727fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000728 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d len=%d\n",
729 __func__, rc, (int)outlen);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000730
731 return rc;
732}
733
734int efx_mcdi_log_ctrl(struct efx_nic *efx, bool evq, bool uart, u32 dest_evq)
735{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100736 MCDI_DECLARE_BUF(inbuf, MC_CMD_LOG_CTRL_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000737 u32 dest = 0;
738 int rc;
739
740 if (uart)
741 dest |= MC_CMD_LOG_CTRL_IN_LOG_DEST_UART;
742 if (evq)
743 dest |= MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ;
744
745 MCDI_SET_DWORD(inbuf, LOG_CTRL_IN_LOG_DEST, dest);
746 MCDI_SET_DWORD(inbuf, LOG_CTRL_IN_LOG_DEST_EVQ, dest_evq);
747
748 BUILD_BUG_ON(MC_CMD_LOG_CTRL_OUT_LEN != 0);
749
750 rc = efx_mcdi_rpc(efx, MC_CMD_LOG_CTRL, inbuf, sizeof(inbuf),
751 NULL, 0, NULL);
752 if (rc)
753 goto fail;
754
755 return 0;
756
757fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000758 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000759 return rc;
760}
761
762int efx_mcdi_nvram_types(struct efx_nic *efx, u32 *nvram_types_out)
763{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100764 MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_TYPES_OUT_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000765 size_t outlen;
766 int rc;
767
768 BUILD_BUG_ON(MC_CMD_NVRAM_TYPES_IN_LEN != 0);
769
770 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_TYPES, NULL, 0,
771 outbuf, sizeof(outbuf), &outlen);
772 if (rc)
773 goto fail;
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000774 if (outlen < MC_CMD_NVRAM_TYPES_OUT_LEN) {
775 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000776 goto fail;
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000777 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000778
779 *nvram_types_out = MCDI_DWORD(outbuf, NVRAM_TYPES_OUT_TYPES);
780 return 0;
781
782fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000783 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
784 __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000785 return rc;
786}
787
788int efx_mcdi_nvram_info(struct efx_nic *efx, unsigned int type,
789 size_t *size_out, size_t *erase_size_out,
790 bool *protected_out)
791{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100792 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_INFO_IN_LEN);
793 MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_INFO_OUT_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000794 size_t outlen;
795 int rc;
796
797 MCDI_SET_DWORD(inbuf, NVRAM_INFO_IN_TYPE, type);
798
799 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_INFO, inbuf, sizeof(inbuf),
800 outbuf, sizeof(outbuf), &outlen);
801 if (rc)
802 goto fail;
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000803 if (outlen < MC_CMD_NVRAM_INFO_OUT_LEN) {
804 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000805 goto fail;
Ben Hutchings00bbb4a2010-04-28 09:27:14 +0000806 }
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000807
808 *size_out = MCDI_DWORD(outbuf, NVRAM_INFO_OUT_SIZE);
809 *erase_size_out = MCDI_DWORD(outbuf, NVRAM_INFO_OUT_ERASESIZE);
810 *protected_out = !!(MCDI_DWORD(outbuf, NVRAM_INFO_OUT_FLAGS) &
Ben Hutchings05a93202011-12-20 00:44:06 +0000811 (1 << MC_CMD_NVRAM_INFO_OUT_PROTECTED_LBN));
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000812 return 0;
813
814fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000815 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000816 return rc;
817}
818
819int efx_mcdi_nvram_update_start(struct efx_nic *efx, unsigned int type)
820{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100821 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_START_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000822 int rc;
823
824 MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_START_IN_TYPE, type);
825
826 BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_START_OUT_LEN != 0);
827
828 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_START, inbuf, sizeof(inbuf),
829 NULL, 0, NULL);
830 if (rc)
831 goto fail;
832
833 return 0;
834
835fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000836 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000837 return rc;
838}
839
840int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type,
841 loff_t offset, u8 *buffer, size_t length)
842{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100843 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_READ_IN_LEN);
844 MCDI_DECLARE_BUF(outbuf,
845 MC_CMD_NVRAM_READ_OUT_LEN(EFX_MCDI_NVRAM_LEN_MAX));
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000846 size_t outlen;
847 int rc;
848
849 MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_TYPE, type);
850 MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_OFFSET, offset);
851 MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_LENGTH, length);
852
853 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_READ, inbuf, sizeof(inbuf),
854 outbuf, sizeof(outbuf), &outlen);
855 if (rc)
856 goto fail;
857
858 memcpy(buffer, MCDI_PTR(outbuf, NVRAM_READ_OUT_READ_BUFFER), length);
859 return 0;
860
861fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000862 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000863 return rc;
864}
865
866int efx_mcdi_nvram_write(struct efx_nic *efx, unsigned int type,
867 loff_t offset, const u8 *buffer, size_t length)
868{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100869 MCDI_DECLARE_BUF(inbuf,
870 MC_CMD_NVRAM_WRITE_IN_LEN(EFX_MCDI_NVRAM_LEN_MAX));
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000871 int rc;
872
873 MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_TYPE, type);
874 MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_OFFSET, offset);
875 MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_LENGTH, length);
876 memcpy(MCDI_PTR(inbuf, NVRAM_WRITE_IN_WRITE_BUFFER), buffer, length);
877
878 BUILD_BUG_ON(MC_CMD_NVRAM_WRITE_OUT_LEN != 0);
879
Ben Hutchings5a27e862010-01-25 15:49:59 -0800880 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_WRITE, inbuf,
881 ALIGN(MC_CMD_NVRAM_WRITE_IN_LEN(length), 4),
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000882 NULL, 0, NULL);
883 if (rc)
884 goto fail;
885
886 return 0;
887
888fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000889 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000890 return rc;
891}
892
893int efx_mcdi_nvram_erase(struct efx_nic *efx, unsigned int type,
894 loff_t offset, size_t length)
895{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100896 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_ERASE_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000897 int rc;
898
899 MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_TYPE, type);
900 MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_OFFSET, offset);
901 MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_LENGTH, length);
902
903 BUILD_BUG_ON(MC_CMD_NVRAM_ERASE_OUT_LEN != 0);
904
905 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_ERASE, inbuf, sizeof(inbuf),
906 NULL, 0, NULL);
907 if (rc)
908 goto fail;
909
910 return 0;
911
912fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000913 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000914 return rc;
915}
916
917int efx_mcdi_nvram_update_finish(struct efx_nic *efx, unsigned int type)
918{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100919 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000920 int rc;
921
922 MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_FINISH_IN_TYPE, type);
923
924 BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN != 0);
925
926 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_FINISH, inbuf, sizeof(inbuf),
927 NULL, 0, NULL);
928 if (rc)
929 goto fail;
930
931 return 0;
932
933fail:
Ben Hutchings62776d02010-06-23 11:30:07 +0000934 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000935 return rc;
936}
937
Ben Hutchings2e803402010-02-03 09:31:01 +0000938static int efx_mcdi_nvram_test(struct efx_nic *efx, unsigned int type)
939{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100940 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_TEST_IN_LEN);
941 MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_TEST_OUT_LEN);
Ben Hutchings2e803402010-02-03 09:31:01 +0000942 int rc;
943
944 MCDI_SET_DWORD(inbuf, NVRAM_TEST_IN_TYPE, type);
945
946 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_TEST, inbuf, sizeof(inbuf),
947 outbuf, sizeof(outbuf), NULL);
948 if (rc)
949 return rc;
950
951 switch (MCDI_DWORD(outbuf, NVRAM_TEST_OUT_RESULT)) {
952 case MC_CMD_NVRAM_TEST_PASS:
953 case MC_CMD_NVRAM_TEST_NOTSUPP:
954 return 0;
955 default:
956 return -EIO;
957 }
958}
959
960int efx_mcdi_nvram_test_all(struct efx_nic *efx)
961{
962 u32 nvram_types;
963 unsigned int type;
964 int rc;
965
966 rc = efx_mcdi_nvram_types(efx, &nvram_types);
967 if (rc)
Ben Hutchingsb548a982010-04-28 09:28:36 +0000968 goto fail1;
Ben Hutchings2e803402010-02-03 09:31:01 +0000969
970 type = 0;
971 while (nvram_types != 0) {
972 if (nvram_types & 1) {
973 rc = efx_mcdi_nvram_test(efx, type);
974 if (rc)
Ben Hutchingsb548a982010-04-28 09:28:36 +0000975 goto fail2;
Ben Hutchings2e803402010-02-03 09:31:01 +0000976 }
977 type++;
978 nvram_types >>= 1;
979 }
980
981 return 0;
Ben Hutchingsb548a982010-04-28 09:28:36 +0000982
983fail2:
Ben Hutchings62776d02010-06-23 11:30:07 +0000984 netif_err(efx, hw, efx->net_dev, "%s: failed type=%u\n",
985 __func__, type);
Ben Hutchingsb548a982010-04-28 09:28:36 +0000986fail1:
Ben Hutchings62776d02010-06-23 11:30:07 +0000987 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsb548a982010-04-28 09:28:36 +0000988 return rc;
Ben Hutchings2e803402010-02-03 09:31:01 +0000989}
990
Steve Hodgson8b2103a2010-02-03 09:30:17 +0000991static int efx_mcdi_read_assertion(struct efx_nic *efx)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000992{
Ben Hutchings59cfc472012-09-14 17:30:10 +0100993 MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_ASSERTS_IN_LEN);
994 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_ASSERTS_OUT_LEN);
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +0100995 unsigned int flags, index;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +0000996 const char *reason;
997 size_t outlen;
998 int retry;
999 int rc;
1000
Steve Hodgson8b2103a2010-02-03 09:30:17 +00001001 /* Attempt to read any stored assertion state before we reboot
1002 * the mcfw out of the assertion handler. Retry twice, once
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001003 * because a boot-time assertion might cause this command to fail
1004 * with EINTR. And once again because GET_ASSERTS can race with
1005 * MC_CMD_REBOOT running on the other port. */
1006 retry = 2;
1007 do {
Steve Hodgson8b2103a2010-02-03 09:30:17 +00001008 MCDI_SET_DWORD(inbuf, GET_ASSERTS_IN_CLEAR, 1);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001009 rc = efx_mcdi_rpc(efx, MC_CMD_GET_ASSERTS,
Steve Hodgson8b2103a2010-02-03 09:30:17 +00001010 inbuf, MC_CMD_GET_ASSERTS_IN_LEN,
1011 outbuf, sizeof(outbuf), &outlen);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001012 } while ((rc == -EINTR || rc == -EIO) && retry-- > 0);
1013
1014 if (rc)
1015 return rc;
1016 if (outlen < MC_CMD_GET_ASSERTS_OUT_LEN)
Ben Hutchings00bbb4a2010-04-28 09:27:14 +00001017 return -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001018
Steve Hodgson8b2103a2010-02-03 09:30:17 +00001019 /* Print out any recorded assertion state */
1020 flags = MCDI_DWORD(outbuf, GET_ASSERTS_OUT_GLOBAL_FLAGS);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001021 if (flags == MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS)
1022 return 0;
1023
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001024 reason = (flags == MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL)
1025 ? "system-level assertion"
1026 : (flags == MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL)
1027 ? "thread-level assertion"
1028 : (flags == MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED)
1029 ? "watchdog reset"
1030 : "unknown assertion";
Ben Hutchings62776d02010-06-23 11:30:07 +00001031 netif_err(efx, hw, efx->net_dev,
1032 "MCPU %s at PC = 0x%.8x in thread 0x%.8x\n", reason,
1033 MCDI_DWORD(outbuf, GET_ASSERTS_OUT_SAVED_PC_OFFS),
1034 MCDI_DWORD(outbuf, GET_ASSERTS_OUT_THREAD_OFFS));
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001035
1036 /* Print out the registers */
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +01001037 for (index = 0;
1038 index < MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_NUM;
1039 index++)
1040 netif_err(efx, hw, efx->net_dev, "R%.2d (?): 0x%.8x\n",
1041 1 + index,
1042 MCDI_ARRAY_DWORD(outbuf, GET_ASSERTS_OUT_GP_REGS_OFFS,
1043 index));
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001044
1045 return 0;
1046}
1047
Steve Hodgson8b2103a2010-02-03 09:30:17 +00001048static void efx_mcdi_exit_assertion(struct efx_nic *efx)
1049{
Ben Hutchings59cfc472012-09-14 17:30:10 +01001050 MCDI_DECLARE_BUF(inbuf, MC_CMD_REBOOT_IN_LEN);
Steve Hodgson8b2103a2010-02-03 09:30:17 +00001051
Ben Hutchings0f1e54a2012-07-02 23:37:40 +01001052 /* If the MC is running debug firmware, it might now be
1053 * waiting for a debugger to attach, but we just want it to
1054 * reboot. We set a flag that makes the command a no-op if it
1055 * has already done so. We don't know what return code to
1056 * expect (0 or -EIO), so ignore it.
1057 */
Steve Hodgson8b2103a2010-02-03 09:30:17 +00001058 BUILD_BUG_ON(MC_CMD_REBOOT_OUT_LEN != 0);
1059 MCDI_SET_DWORD(inbuf, REBOOT_IN_FLAGS,
1060 MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION);
Ben Hutchings0f1e54a2012-07-02 23:37:40 +01001061 (void) efx_mcdi_rpc(efx, MC_CMD_REBOOT, inbuf, MC_CMD_REBOOT_IN_LEN,
1062 NULL, 0, NULL);
Steve Hodgson8b2103a2010-02-03 09:30:17 +00001063}
1064
1065int efx_mcdi_handle_assertion(struct efx_nic *efx)
1066{
1067 int rc;
1068
1069 rc = efx_mcdi_read_assertion(efx);
1070 if (rc)
1071 return rc;
1072
1073 efx_mcdi_exit_assertion(efx);
1074
1075 return 0;
1076}
1077
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001078void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
1079{
Ben Hutchings59cfc472012-09-14 17:30:10 +01001080 MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_ID_LED_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001081 int rc;
1082
1083 BUILD_BUG_ON(EFX_LED_OFF != MC_CMD_LED_OFF);
1084 BUILD_BUG_ON(EFX_LED_ON != MC_CMD_LED_ON);
1085 BUILD_BUG_ON(EFX_LED_DEFAULT != MC_CMD_LED_DEFAULT);
1086
1087 BUILD_BUG_ON(MC_CMD_SET_ID_LED_OUT_LEN != 0);
1088
1089 MCDI_SET_DWORD(inbuf, SET_ID_LED_IN_STATE, mode);
1090
1091 rc = efx_mcdi_rpc(efx, MC_CMD_SET_ID_LED, inbuf, sizeof(inbuf),
1092 NULL, 0, NULL);
1093 if (rc)
Ben Hutchings62776d02010-06-23 11:30:07 +00001094 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
1095 __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001096}
1097
Ben Hutchings6bff8612012-09-18 02:33:52 +01001098static int efx_mcdi_reset_port(struct efx_nic *efx)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001099{
Ben Hutchings05a93202011-12-20 00:44:06 +00001100 int rc = efx_mcdi_rpc(efx, MC_CMD_ENTITY_RESET, NULL, 0, NULL, 0, NULL);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001101 if (rc)
Ben Hutchings62776d02010-06-23 11:30:07 +00001102 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
1103 __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001104 return rc;
1105}
1106
Ben Hutchings6bff8612012-09-18 02:33:52 +01001107static int efx_mcdi_reset_mc(struct efx_nic *efx)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001108{
Ben Hutchings59cfc472012-09-14 17:30:10 +01001109 MCDI_DECLARE_BUF(inbuf, MC_CMD_REBOOT_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001110 int rc;
1111
1112 BUILD_BUG_ON(MC_CMD_REBOOT_OUT_LEN != 0);
1113 MCDI_SET_DWORD(inbuf, REBOOT_IN_FLAGS, 0);
1114 rc = efx_mcdi_rpc(efx, MC_CMD_REBOOT, inbuf, sizeof(inbuf),
1115 NULL, 0, NULL);
1116 /* White is black, and up is down */
1117 if (rc == -EIO)
1118 return 0;
1119 if (rc == 0)
1120 rc = -EIO;
Ben Hutchings62776d02010-06-23 11:30:07 +00001121 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001122 return rc;
1123}
1124
Ben Hutchings6bff8612012-09-18 02:33:52 +01001125enum reset_type efx_mcdi_map_reset_reason(enum reset_type reason)
1126{
1127 return RESET_TYPE_RECOVER_OR_ALL;
1128}
1129
1130int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method)
1131{
1132 int rc;
1133
1134 /* Recover from a failed assertion pre-reset */
1135 rc = efx_mcdi_handle_assertion(efx);
1136 if (rc)
1137 return rc;
1138
1139 if (method == RESET_TYPE_WORLD)
1140 return efx_mcdi_reset_mc(efx);
1141 else
1142 return efx_mcdi_reset_port(efx);
1143}
1144
stephen hemmingerd2156972010-10-18 05:27:31 +00001145static int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type,
1146 const u8 *mac, int *id_out)
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001147{
Ben Hutchings59cfc472012-09-14 17:30:10 +01001148 MCDI_DECLARE_BUF(inbuf, MC_CMD_WOL_FILTER_SET_IN_LEN);
1149 MCDI_DECLARE_BUF(outbuf, MC_CMD_WOL_FILTER_SET_OUT_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001150 size_t outlen;
1151 int rc;
1152
1153 MCDI_SET_DWORD(inbuf, WOL_FILTER_SET_IN_WOL_TYPE, type);
1154 MCDI_SET_DWORD(inbuf, WOL_FILTER_SET_IN_FILTER_MODE,
1155 MC_CMD_FILTER_MODE_SIMPLE);
1156 memcpy(MCDI_PTR(inbuf, WOL_FILTER_SET_IN_MAGIC_MAC), mac, ETH_ALEN);
1157
1158 rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_SET, inbuf, sizeof(inbuf),
1159 outbuf, sizeof(outbuf), &outlen);
1160 if (rc)
1161 goto fail;
1162
1163 if (outlen < MC_CMD_WOL_FILTER_SET_OUT_LEN) {
Ben Hutchings00bbb4a2010-04-28 09:27:14 +00001164 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001165 goto fail;
1166 }
1167
1168 *id_out = (int)MCDI_DWORD(outbuf, WOL_FILTER_SET_OUT_FILTER_ID);
1169
1170 return 0;
1171
1172fail:
1173 *id_out = -1;
Ben Hutchings62776d02010-06-23 11:30:07 +00001174 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001175 return rc;
1176
1177}
1178
1179
1180int
1181efx_mcdi_wol_filter_set_magic(struct efx_nic *efx, const u8 *mac, int *id_out)
1182{
1183 return efx_mcdi_wol_filter_set(efx, MC_CMD_WOL_TYPE_MAGIC, mac, id_out);
1184}
1185
1186
1187int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out)
1188{
Ben Hutchings59cfc472012-09-14 17:30:10 +01001189 MCDI_DECLARE_BUF(outbuf, MC_CMD_WOL_FILTER_GET_OUT_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001190 size_t outlen;
1191 int rc;
1192
1193 rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_GET, NULL, 0,
1194 outbuf, sizeof(outbuf), &outlen);
1195 if (rc)
1196 goto fail;
1197
1198 if (outlen < MC_CMD_WOL_FILTER_GET_OUT_LEN) {
Ben Hutchings00bbb4a2010-04-28 09:27:14 +00001199 rc = -EIO;
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001200 goto fail;
1201 }
1202
1203 *id_out = (int)MCDI_DWORD(outbuf, WOL_FILTER_GET_OUT_FILTER_ID);
1204
1205 return 0;
1206
1207fail:
1208 *id_out = -1;
Ben Hutchings62776d02010-06-23 11:30:07 +00001209 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001210 return rc;
1211}
1212
1213
1214int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id)
1215{
Ben Hutchings59cfc472012-09-14 17:30:10 +01001216 MCDI_DECLARE_BUF(inbuf, MC_CMD_WOL_FILTER_REMOVE_IN_LEN);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001217 int rc;
1218
1219 MCDI_SET_DWORD(inbuf, WOL_FILTER_REMOVE_IN_FILTER_ID, (u32)id);
1220
1221 rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_REMOVE, inbuf, sizeof(inbuf),
1222 NULL, 0, NULL);
1223 if (rc)
1224 goto fail;
1225
1226 return 0;
1227
1228fail:
Ben Hutchings62776d02010-06-23 11:30:07 +00001229 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001230 return rc;
1231}
1232
Ben Hutchingscd2d5b52012-02-14 00:48:07 +00001233int efx_mcdi_flush_rxqs(struct efx_nic *efx)
1234{
1235 struct efx_channel *channel;
1236 struct efx_rx_queue *rx_queue;
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +01001237 MCDI_DECLARE_BUF(inbuf,
1238 MC_CMD_FLUSH_RX_QUEUES_IN_LEN(EFX_MAX_CHANNELS));
Ben Hutchingscd2d5b52012-02-14 00:48:07 +00001239 int rc, count;
1240
Ben Hutchings45078372012-09-19 02:53:34 +01001241 BUILD_BUG_ON(EFX_MAX_CHANNELS >
1242 MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MAXNUM);
1243
Ben Hutchingscd2d5b52012-02-14 00:48:07 +00001244 count = 0;
1245 efx_for_each_channel(channel, efx) {
1246 efx_for_each_channel_rx_queue(rx_queue, channel) {
1247 if (rx_queue->flush_pending) {
1248 rx_queue->flush_pending = false;
1249 atomic_dec(&efx->rxq_flush_pending);
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +01001250 MCDI_SET_ARRAY_DWORD(
1251 inbuf, FLUSH_RX_QUEUES_IN_QID_OFST,
1252 count, efx_rx_queue_index(rx_queue));
1253 count++;
Ben Hutchingscd2d5b52012-02-14 00:48:07 +00001254 }
1255 }
1256 }
1257
Ben Hutchingsc5bb0e92012-09-14 17:31:33 +01001258 rc = efx_mcdi_rpc(efx, MC_CMD_FLUSH_RX_QUEUES, inbuf,
1259 MC_CMD_FLUSH_RX_QUEUES_IN_LEN(count), NULL, 0, NULL);
Ben Hutchingsbbec9692012-09-11 18:25:13 +01001260 WARN_ON(rc < 0);
Ben Hutchingscd2d5b52012-02-14 00:48:07 +00001261
Ben Hutchingscd2d5b52012-02-14 00:48:07 +00001262 return rc;
1263}
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001264
1265int efx_mcdi_wol_filter_reset(struct efx_nic *efx)
1266{
1267 int rc;
1268
1269 rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_RESET, NULL, 0, NULL, 0, NULL);
1270 if (rc)
1271 goto fail;
1272
1273 return 0;
1274
1275fail:
Ben Hutchings62776d02010-06-23 11:30:07 +00001276 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
Ben Hutchingsafd4aea2009-11-29 15:15:25 +00001277 return rc;
1278}
1279