aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2008-05-07 08:36:19 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-05-13 01:31:44 -0400
commit3273c2e8c66a21ae1c53b0c730ee937c6efde7e2 (patch)
treeee2a1f187c0310e229f51fbfc5fbbe7a5fce5b76 /drivers
parent05e3ec04460180f48810cddc2f78e80a725657ad (diff)
[netdrvr] sfc: sfc: Add self-test support
Add a set of self-tests accessible thorugh ethtool. Add hardware loopback and TX disable control code to support them. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/sfc/Makefile4
-rw-r--r--drivers/net/sfc/enum.h49
-rw-r--r--drivers/net/sfc/ethtool.c232
-rw-r--r--drivers/net/sfc/falcon.c5
-rw-r--r--drivers/net/sfc/falcon_hwdefs.h16
-rw-r--r--drivers/net/sfc/falcon_xmac.c72
-rw-r--r--drivers/net/sfc/mdio_10g.c78
-rw-r--r--drivers/net/sfc/mdio_10g.h22
-rw-r--r--drivers/net/sfc/net_driver.h14
-rw-r--r--drivers/net/sfc/rx.c10
-rw-r--r--drivers/net/sfc/selftest.c717
-rw-r--r--drivers/net/sfc/selftest.h50
-rw-r--r--drivers/net/sfc/tenxpress.c81
-rw-r--r--drivers/net/sfc/xfp_phy.c36
14 files changed, 1379 insertions, 7 deletions
diff --git a/drivers/net/sfc/Makefile b/drivers/net/sfc/Makefile
index 0f023447eafd..1d2daeec7ac1 100644
--- a/drivers/net/sfc/Makefile
+++ b/drivers/net/sfc/Makefile
@@ -1,5 +1,5 @@
1sfc-y += efx.o falcon.o tx.o rx.o falcon_xmac.o \ 1sfc-y += efx.o falcon.o tx.o rx.o falcon_xmac.o \
2 i2c-direct.o ethtool.o xfp_phy.o mdio_10g.o \ 2 i2c-direct.o selftest.o ethtool.o xfp_phy.o \
3 tenxpress.o boards.o sfe4001.o 3 mdio_10g.o tenxpress.o boards.o sfe4001.o
4 4
5obj-$(CONFIG_SFC) += sfc.o 5obj-$(CONFIG_SFC) += sfc.o
diff --git a/drivers/net/sfc/enum.h b/drivers/net/sfc/enum.h
index 43663a4619da..c53290d08e2b 100644
--- a/drivers/net/sfc/enum.h
+++ b/drivers/net/sfc/enum.h
@@ -10,6 +10,55 @@
10#ifndef EFX_ENUM_H 10#ifndef EFX_ENUM_H
11#define EFX_ENUM_H 11#define EFX_ENUM_H
12 12
13/**
14 * enum efx_loopback_mode - loopback modes
15 * @LOOPBACK_NONE: no loopback
16 * @LOOPBACK_XGMII: loopback within MAC at XGMII level
17 * @LOOPBACK_XGXS: loopback within MAC at XGXS level
18 * @LOOPBACK_XAUI: loopback within MAC at XAUI level
19 * @LOOPBACK_PHYXS: loopback within PHY at PHYXS level
20 * @LOOPBACK_PCS: loopback within PHY at PCS level
21 * @LOOPBACK_PMAPMD: loopback within PHY at PMAPMD level
22 * @LOOPBACK_NETWORK: reflecting loopback (even further than furthest!)
23 */
24/* Please keep in order and up-to-date w.r.t the following two #defines */
25enum efx_loopback_mode {
26 LOOPBACK_NONE = 0,
27 LOOPBACK_MAC = 1,
28 LOOPBACK_XGMII = 2,
29 LOOPBACK_XGXS = 3,
30 LOOPBACK_XAUI = 4,
31 LOOPBACK_PHY = 5,
32 LOOPBACK_PHYXS = 6,
33 LOOPBACK_PCS = 7,
34 LOOPBACK_PMAPMD = 8,
35 LOOPBACK_NETWORK = 9,
36 LOOPBACK_MAX
37};
38
39#define LOOPBACK_TEST_MAX LOOPBACK_PMAPMD
40
41extern const char *efx_loopback_mode_names[];
42#define LOOPBACK_MODE_NAME(mode) \
43 STRING_TABLE_LOOKUP(mode, efx_loopback_mode)
44#define LOOPBACK_MODE(efx) \
45 LOOPBACK_MODE_NAME(efx->loopback_mode)
46
47/* These loopbacks occur within the controller */
48#define LOOPBACKS_10G_INTERNAL ((1 << LOOPBACK_XGMII)| \
49 (1 << LOOPBACK_XGXS) | \
50 (1 << LOOPBACK_XAUI))
51
52#define LOOPBACK_MASK(_efx) \
53 (1 << (_efx)->loopback_mode)
54
55#define LOOPBACK_INTERNAL(_efx) \
56 ((LOOPBACKS_10G_INTERNAL & LOOPBACK_MASK(_efx)) ? 1 : 0)
57
58#define LOOPBACK_OUT_OF(_from, _to, _mask) \
59 (((LOOPBACK_MASK(_from) & (_mask)) && \
60 ((LOOPBACK_MASK(_to) & (_mask)) == 0)) ? 1 : 0)
61
13/*****************************************************************************/ 62/*****************************************************************************/
14 63
15/** 64/**
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index b756840e2a16..e2c75d101610 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -12,12 +12,26 @@
12#include <linux/ethtool.h> 12#include <linux/ethtool.h>
13#include <linux/rtnetlink.h> 13#include <linux/rtnetlink.h>
14#include "net_driver.h" 14#include "net_driver.h"
15#include "selftest.h"
15#include "efx.h" 16#include "efx.h"
16#include "ethtool.h" 17#include "ethtool.h"
17#include "falcon.h" 18#include "falcon.h"
18#include "gmii.h" 19#include "gmii.h"
19#include "mac.h" 20#include "mac.h"
20 21
22const char *efx_loopback_mode_names[] = {
23 [LOOPBACK_NONE] = "NONE",
24 [LOOPBACK_MAC] = "MAC",
25 [LOOPBACK_XGMII] = "XGMII",
26 [LOOPBACK_XGXS] = "XGXS",
27 [LOOPBACK_XAUI] = "XAUI",
28 [LOOPBACK_PHY] = "PHY",
29 [LOOPBACK_PHYXS] = "PHY(XS)",
30 [LOOPBACK_PCS] = "PHY(PCS)",
31 [LOOPBACK_PMAPMD] = "PHY(PMAPMD)",
32 [LOOPBACK_NETWORK] = "NETWORK",
33};
34
21static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable); 35static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable);
22 36
23struct ethtool_string { 37struct ethtool_string {
@@ -217,23 +231,179 @@ static void efx_ethtool_get_drvinfo(struct net_device *net_dev,
217 strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info)); 231 strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info));
218} 232}
219 233
234/**
235 * efx_fill_test - fill in an individual self-test entry
236 * @test_index: Index of the test
237 * @strings: Ethtool strings, or %NULL
238 * @data: Ethtool test results, or %NULL
239 * @test: Pointer to test result (used only if data != %NULL)
240 * @unit_format: Unit name format (e.g. "channel\%d")
241 * @unit_id: Unit id (e.g. 0 for "channel0")
242 * @test_format: Test name format (e.g. "loopback.\%s.tx.sent")
243 * @test_id: Test id (e.g. "PHY" for "loopback.PHY.tx_sent")
244 *
245 * Fill in an individual self-test entry.
246 */
247static void efx_fill_test(unsigned int test_index,
248 struct ethtool_string *strings, u64 *data,
249 int *test, const char *unit_format, int unit_id,
250 const char *test_format, const char *test_id)
251{
252 struct ethtool_string unit_str, test_str;
253
254 /* Fill data value, if applicable */
255 if (data)
256 data[test_index] = *test;
257
258 /* Fill string, if applicable */
259 if (strings) {
260 snprintf(unit_str.name, sizeof(unit_str.name),
261 unit_format, unit_id);
262 snprintf(test_str.name, sizeof(test_str.name),
263 test_format, test_id);
264 snprintf(strings[test_index].name,
265 sizeof(strings[test_index].name),
266 "%-9s%-17s", unit_str.name, test_str.name);
267 }
268}
269
270#define EFX_PORT_NAME "port%d", 0
271#define EFX_CHANNEL_NAME(_channel) "channel%d", _channel->channel
272#define EFX_TX_QUEUE_NAME(_tx_queue) "txq%d", _tx_queue->queue
273#define EFX_RX_QUEUE_NAME(_rx_queue) "rxq%d", _rx_queue->queue
274#define EFX_LOOPBACK_NAME(_mode, _counter) \
275 "loopback.%s." _counter, LOOPBACK_MODE_NAME(mode)
276
277/**
278 * efx_fill_loopback_test - fill in a block of loopback self-test entries
279 * @efx: Efx NIC
280 * @lb_tests: Efx loopback self-test results structure
281 * @mode: Loopback test mode
282 * @test_index: Starting index of the test
283 * @strings: Ethtool strings, or %NULL
284 * @data: Ethtool test results, or %NULL
285 */
286static int efx_fill_loopback_test(struct efx_nic *efx,
287 struct efx_loopback_self_tests *lb_tests,
288 enum efx_loopback_mode mode,
289 unsigned int test_index,
290 struct ethtool_string *strings, u64 *data)
291{
292 struct efx_tx_queue *tx_queue;
293
294 efx_for_each_tx_queue(tx_queue, efx) {
295 efx_fill_test(test_index++, strings, data,
296 &lb_tests->tx_sent[tx_queue->queue],
297 EFX_TX_QUEUE_NAME(tx_queue),
298 EFX_LOOPBACK_NAME(mode, "tx_sent"));
299 efx_fill_test(test_index++, strings, data,
300 &lb_tests->tx_done[tx_queue->queue],
301 EFX_TX_QUEUE_NAME(tx_queue),
302 EFX_LOOPBACK_NAME(mode, "tx_done"));
303 }
304 efx_fill_test(test_index++, strings, data,
305 &lb_tests->rx_good,
306 EFX_PORT_NAME,
307 EFX_LOOPBACK_NAME(mode, "rx_good"));
308 efx_fill_test(test_index++, strings, data,
309 &lb_tests->rx_bad,
310 EFX_PORT_NAME,
311 EFX_LOOPBACK_NAME(mode, "rx_bad"));
312
313 return test_index;
314}
315
316/**
317 * efx_ethtool_fill_self_tests - get self-test details
318 * @efx: Efx NIC
319 * @tests: Efx self-test results structure, or %NULL
320 * @strings: Ethtool strings, or %NULL
321 * @data: Ethtool test results, or %NULL
322 */
323static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
324 struct efx_self_tests *tests,
325 struct ethtool_string *strings,
326 u64 *data)
327{
328 struct efx_channel *channel;
329 unsigned int n = 0;
330 enum efx_loopback_mode mode;
331
332 /* Interrupt */
333 efx_fill_test(n++, strings, data, &tests->interrupt,
334 "core", 0, "interrupt", NULL);
335
336 /* Event queues */
337 efx_for_each_channel(channel, efx) {
338 efx_fill_test(n++, strings, data,
339 &tests->eventq_dma[channel->channel],
340 EFX_CHANNEL_NAME(channel),
341 "eventq.dma", NULL);
342 efx_fill_test(n++, strings, data,
343 &tests->eventq_int[channel->channel],
344 EFX_CHANNEL_NAME(channel),
345 "eventq.int", NULL);
346 efx_fill_test(n++, strings, data,
347 &tests->eventq_poll[channel->channel],
348 EFX_CHANNEL_NAME(channel),
349 "eventq.poll", NULL);
350 }
351
352 /* PHY presence */
353 efx_fill_test(n++, strings, data, &tests->phy_ok,
354 EFX_PORT_NAME, "phy_ok", NULL);
355
356 /* Loopback tests */
357 efx_fill_test(n++, strings, data, &tests->loopback_speed,
358 EFX_PORT_NAME, "loopback.speed", NULL);
359 efx_fill_test(n++, strings, data, &tests->loopback_full_duplex,
360 EFX_PORT_NAME, "loopback.full_duplex", NULL);
361 for (mode = LOOPBACK_NONE; mode < LOOPBACK_TEST_MAX; mode++) {
362 if (!(efx->loopback_modes & (1 << mode)))
363 continue;
364 n = efx_fill_loopback_test(efx,
365 &tests->loopback[mode], mode, n,
366 strings, data);
367 }
368
369 return n;
370}
371
220static int efx_ethtool_get_stats_count(struct net_device *net_dev) 372static int efx_ethtool_get_stats_count(struct net_device *net_dev)
221{ 373{
222 return EFX_ETHTOOL_NUM_STATS; 374 return EFX_ETHTOOL_NUM_STATS;
223} 375}
224 376
377static int efx_ethtool_self_test_count(struct net_device *net_dev)
378{
379 struct efx_nic *efx = net_dev->priv;
380
381 return efx_ethtool_fill_self_tests(efx, NULL, NULL, NULL);
382}
383
225static void efx_ethtool_get_strings(struct net_device *net_dev, 384static void efx_ethtool_get_strings(struct net_device *net_dev,
226 u32 string_set, u8 *strings) 385 u32 string_set, u8 *strings)
227{ 386{
387 struct efx_nic *efx = net_dev->priv;
228 struct ethtool_string *ethtool_strings = 388 struct ethtool_string *ethtool_strings =
229 (struct ethtool_string *)strings; 389 (struct ethtool_string *)strings;
230 int i; 390 int i;
231 391
232 if (string_set == ETH_SS_STATS) 392 switch (string_set) {
393 case ETH_SS_STATS:
233 for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) 394 for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++)
234 strncpy(ethtool_strings[i].name, 395 strncpy(ethtool_strings[i].name,
235 efx_ethtool_stats[i].name, 396 efx_ethtool_stats[i].name,
236 sizeof(ethtool_strings[i].name)); 397 sizeof(ethtool_strings[i].name));
398 break;
399 case ETH_SS_TEST:
400 efx_ethtool_fill_self_tests(efx, NULL,
401 ethtool_strings, NULL);
402 break;
403 default:
404 /* No other string sets */
405 break;
406 }
237} 407}
238 408
239static void efx_ethtool_get_stats(struct net_device *net_dev, 409static void efx_ethtool_get_stats(struct net_device *net_dev,
@@ -330,6 +500,64 @@ static u32 efx_ethtool_get_rx_csum(struct net_device *net_dev)
330 return efx->rx_checksum_enabled; 500 return efx->rx_checksum_enabled;
331} 501}
332 502
503static void efx_ethtool_self_test(struct net_device *net_dev,
504 struct ethtool_test *test, u64 *data)
505{
506 struct efx_nic *efx = net_dev->priv;
507 struct efx_self_tests efx_tests;
508 int offline, already_up;
509 int rc;
510
511 ASSERT_RTNL();
512 if (efx->state != STATE_RUNNING) {
513 rc = -EIO;
514 goto fail1;
515 }
516
517 /* We need rx buffers and interrupts. */
518 already_up = (efx->net_dev->flags & IFF_UP);
519 if (!already_up) {
520 rc = dev_open(efx->net_dev);
521 if (rc) {
522 EFX_ERR(efx, "failed opening device.\n");
523 goto fail2;
524 }
525 }
526
527 memset(&efx_tests, 0, sizeof(efx_tests));
528 offline = (test->flags & ETH_TEST_FL_OFFLINE);
529
530 /* Perform online self tests first */
531 rc = efx_online_test(efx, &efx_tests);
532 if (rc)
533 goto out;
534
535 /* Perform offline tests only if online tests passed */
536 if (offline) {
537 /* Stop the kernel from sending packets during the test. */
538 efx_stop_queue(efx);
539 rc = efx_flush_queues(efx);
540 if (!rc)
541 rc = efx_offline_test(efx, &efx_tests,
542 efx->loopback_modes);
543 efx_wake_queue(efx);
544 }
545
546 out:
547 if (!already_up)
548 dev_close(efx->net_dev);
549
550 EFX_LOG(efx, "%s all %sline self-tests\n",
551 rc == 0 ? "passed" : "failed", offline ? "off" : "on");
552
553 fail2:
554 fail1:
555 /* Fill ethtool results structures */
556 efx_ethtool_fill_self_tests(efx, &efx_tests, NULL, data);
557 if (rc)
558 test->flags |= ETH_TEST_FL_FAILED;
559}
560
333/* Restart autonegotiation */ 561/* Restart autonegotiation */
334static int efx_ethtool_nway_reset(struct net_device *net_dev) 562static int efx_ethtool_nway_reset(struct net_device *net_dev)
335{ 563{
@@ -480,6 +708,8 @@ struct ethtool_ops efx_ethtool_ops = {
480 .set_tso = efx_ethtool_set_tso, 708 .set_tso = efx_ethtool_set_tso,
481 .get_flags = ethtool_op_get_flags, 709 .get_flags = ethtool_op_get_flags,
482 .set_flags = ethtool_op_set_flags, 710 .set_flags = ethtool_op_set_flags,
711 .self_test_count = efx_ethtool_self_test_count,
712 .self_test = efx_ethtool_self_test,
483 .get_strings = efx_ethtool_get_strings, 713 .get_strings = efx_ethtool_get_strings,
484 .phys_id = efx_ethtool_phys_id, 714 .phys_id = efx_ethtool_phys_id,
485 .get_stats_count = efx_ethtool_get_stats_count, 715 .get_stats_count = efx_ethtool_get_stats_count,
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 247629cee5aa..b57cc68058c0 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -1732,7 +1732,8 @@ void falcon_drain_tx_fifo(struct efx_nic *efx)
1732 efx_oword_t temp; 1732 efx_oword_t temp;
1733 int count; 1733 int count;
1734 1734
1735 if (FALCON_REV(efx) < FALCON_REV_B0) 1735 if ((FALCON_REV(efx) < FALCON_REV_B0) ||
1736 (efx->loopback_mode != LOOPBACK_NONE))
1736 return; 1737 return;
1737 1738
1738 falcon_read(efx, &temp, MAC0_CTRL_REG_KER); 1739 falcon_read(efx, &temp, MAC0_CTRL_REG_KER);
@@ -2092,6 +2093,8 @@ static int falcon_probe_phy(struct efx_nic *efx)
2092 efx->phy_type); 2093 efx->phy_type);
2093 return -1; 2094 return -1;
2094 } 2095 }
2096
2097 efx->loopback_modes = LOOPBACKS_10G_INTERNAL | efx->phy_op->loopbacks;
2095 return 0; 2098 return 0;
2096} 2099}
2097 2100
diff --git a/drivers/net/sfc/falcon_hwdefs.h b/drivers/net/sfc/falcon_hwdefs.h
index 0485a63eaff6..06e2d68fc3d1 100644
--- a/drivers/net/sfc/falcon_hwdefs.h
+++ b/drivers/net/sfc/falcon_hwdefs.h
@@ -636,6 +636,14 @@
636#define XX_HIDRVA_WIDTH 1 636#define XX_HIDRVA_WIDTH 1
637#define XX_LODRVA_LBN 8 637#define XX_LODRVA_LBN 8
638#define XX_LODRVA_WIDTH 1 638#define XX_LODRVA_WIDTH 1
639#define XX_LPBKD_LBN 3
640#define XX_LPBKD_WIDTH 1
641#define XX_LPBKC_LBN 2
642#define XX_LPBKC_WIDTH 1
643#define XX_LPBKB_LBN 1
644#define XX_LPBKB_WIDTH 1
645#define XX_LPBKA_LBN 0
646#define XX_LPBKA_WIDTH 1
639 647
640#define XX_TXDRV_CTL_REG_MAC 0x12 648#define XX_TXDRV_CTL_REG_MAC 0x12
641#define XX_DEQD_LBN 28 649#define XX_DEQD_LBN 28
@@ -656,8 +664,14 @@
656#define XX_DTXA_WIDTH 4 664#define XX_DTXA_WIDTH 4
657 665
658/* XAUI XGXS core status register */ 666/* XAUI XGXS core status register */
659#define XX_FORCE_SIG_DECODE_FORCED 0xff
660#define XX_CORE_STAT_REG_MAC 0x16 667#define XX_CORE_STAT_REG_MAC 0x16
668#define XX_FORCE_SIG_LBN 24
669#define XX_FORCE_SIG_WIDTH 8
670#define XX_FORCE_SIG_DECODE_FORCED 0xff
671#define XX_XGXS_LB_EN_LBN 23
672#define XX_XGXS_LB_EN_WIDTH 1
673#define XX_XGMII_LB_EN_LBN 22
674#define XX_XGMII_LB_EN_WIDTH 1
661#define XX_ALIGN_DONE_LBN 20 675#define XX_ALIGN_DONE_LBN 20
662#define XX_ALIGN_DONE_WIDTH 1 676#define XX_ALIGN_DONE_WIDTH 1
663#define XX_SYNC_STAT_LBN 16 677#define XX_SYNC_STAT_LBN 16
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c
index b875c7b292df..a74b7931a3c4 100644
--- a/drivers/net/sfc/falcon_xmac.c
+++ b/drivers/net/sfc/falcon_xmac.c
@@ -241,7 +241,7 @@ static void falcon_mask_status_intr(struct efx_nic *efx, int enable)
241{ 241{
242 efx_dword_t reg; 242 efx_dword_t reg;
243 243
244 if (FALCON_REV(efx) < FALCON_REV_B0) 244 if ((FALCON_REV(efx) < FALCON_REV_B0) || LOOPBACK_INTERNAL(efx))
245 return; 245 return;
246 246
247 /* Flush the ISR */ 247 /* Flush the ISR */
@@ -288,6 +288,9 @@ int falcon_xaui_link_ok(struct efx_nic *efx)
288 efx_dword_t reg; 288 efx_dword_t reg;
289 int align_done, sync_status, link_ok = 0; 289 int align_done, sync_status, link_ok = 0;
290 290
291 if (LOOPBACK_INTERNAL(efx))
292 return 1;
293
291 /* Read link status */ 294 /* Read link status */
292 falcon_xmac_readl(efx, &reg, XX_CORE_STAT_REG_MAC); 295 falcon_xmac_readl(efx, &reg, XX_CORE_STAT_REG_MAC);
293 296
@@ -378,6 +381,61 @@ static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
378 falcon_xmac_writel(efx, &reg, XM_ADR_HI_REG_MAC); 381 falcon_xmac_writel(efx, &reg, XM_ADR_HI_REG_MAC);
379} 382}
380 383
384static void falcon_reconfigure_xgxs_core(struct efx_nic *efx)
385{
386 efx_dword_t reg;
387 int xgxs_loopback = (efx->loopback_mode == LOOPBACK_XGXS) ? 1 : 0;
388 int xaui_loopback = (efx->loopback_mode == LOOPBACK_XAUI) ? 1 : 0;
389 int xgmii_loopback =
390 (efx->loopback_mode == LOOPBACK_XGMII) ? 1 : 0;
391
392 /* XGXS block is flaky and will need to be reset if moving
393 * into our out of XGMII, XGXS or XAUI loopbacks. */
394 if (EFX_WORKAROUND_5147(efx)) {
395 int old_xgmii_loopback, old_xgxs_loopback, old_xaui_loopback;
396 int reset_xgxs;
397
398 falcon_xmac_readl(efx, &reg, XX_CORE_STAT_REG_MAC);
399 old_xgxs_loopback = EFX_DWORD_FIELD(reg, XX_XGXS_LB_EN);
400 old_xgmii_loopback = EFX_DWORD_FIELD(reg, XX_XGMII_LB_EN);
401
402 falcon_xmac_readl(efx, &reg, XX_SD_CTL_REG_MAC);
403 old_xaui_loopback = EFX_DWORD_FIELD(reg, XX_LPBKA);
404
405 /* The PHY driver may have turned XAUI off */
406 reset_xgxs = ((xgxs_loopback != old_xgxs_loopback) ||
407 (xaui_loopback != old_xaui_loopback) ||
408 (xgmii_loopback != old_xgmii_loopback));
409 if (reset_xgxs) {
410 falcon_xmac_readl(efx, &reg, XX_PWR_RST_REG_MAC);
411 EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSTX_EN, 1);
412 EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSRX_EN, 1);
413 falcon_xmac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
414 udelay(1);
415 EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSTX_EN, 0);
416 EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSRX_EN, 0);
417 falcon_xmac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
418 udelay(1);
419 }
420 }
421
422 falcon_xmac_readl(efx, &reg, XX_CORE_STAT_REG_MAC);
423 EFX_SET_DWORD_FIELD(reg, XX_FORCE_SIG,
424 (xgxs_loopback || xaui_loopback) ?
425 XX_FORCE_SIG_DECODE_FORCED : 0);
426 EFX_SET_DWORD_FIELD(reg, XX_XGXS_LB_EN, xgxs_loopback);
427 EFX_SET_DWORD_FIELD(reg, XX_XGMII_LB_EN, xgmii_loopback);
428 falcon_xmac_writel(efx, &reg, XX_CORE_STAT_REG_MAC);
429
430 falcon_xmac_readl(efx, &reg, XX_SD_CTL_REG_MAC);
431 EFX_SET_DWORD_FIELD(reg, XX_LPBKD, xaui_loopback);
432 EFX_SET_DWORD_FIELD(reg, XX_LPBKC, xaui_loopback);
433 EFX_SET_DWORD_FIELD(reg, XX_LPBKB, xaui_loopback);
434 EFX_SET_DWORD_FIELD(reg, XX_LPBKA, xaui_loopback);
435 falcon_xmac_writel(efx, &reg, XX_SD_CTL_REG_MAC);
436}
437
438
381/* Try and bring the Falcon side of the Falcon-Phy XAUI link fails 439/* Try and bring the Falcon side of the Falcon-Phy XAUI link fails
382 * to come back up. Bash it until it comes back up */ 440 * to come back up. Bash it until it comes back up */
383static int falcon_check_xaui_link_up(struct efx_nic *efx) 441static int falcon_check_xaui_link_up(struct efx_nic *efx)
@@ -386,7 +444,8 @@ static int falcon_check_xaui_link_up(struct efx_nic *efx)
386 tries = EFX_WORKAROUND_5147(efx) ? 5 : 1; 444 tries = EFX_WORKAROUND_5147(efx) ? 5 : 1;
387 max_tries = tries; 445 max_tries = tries;
388 446
389 if (efx->phy_type == PHY_TYPE_NONE) 447 if ((efx->loopback_mode == LOOPBACK_NETWORK) ||
448 (efx->phy_type == PHY_TYPE_NONE))
390 return 0; 449 return 0;
391 450
392 while (tries) { 451 while (tries) {
@@ -412,8 +471,13 @@ void falcon_reconfigure_xmac(struct efx_nic *efx)
412 falcon_mask_status_intr(efx, 0); 471 falcon_mask_status_intr(efx, 0);
413 472
414 falcon_deconfigure_mac_wrapper(efx); 473 falcon_deconfigure_mac_wrapper(efx);
474
475 efx->tx_disabled = LOOPBACK_INTERNAL(efx);
415 efx->phy_op->reconfigure(efx); 476 efx->phy_op->reconfigure(efx);
477
478 falcon_reconfigure_xgxs_core(efx);
416 falcon_reconfigure_xmac_core(efx); 479 falcon_reconfigure_xmac_core(efx);
480
417 falcon_reconfigure_mac_wrapper(efx); 481 falcon_reconfigure_mac_wrapper(efx);
418 482
419 /* Ensure XAUI link is up */ 483 /* Ensure XAUI link is up */
@@ -500,6 +564,10 @@ int falcon_check_xmac(struct efx_nic *efx)
500 unsigned xaui_link_ok; 564 unsigned xaui_link_ok;
501 int rc; 565 int rc;
502 566
567 if ((efx->loopback_mode == LOOPBACK_NETWORK) ||
568 (efx->phy_type == PHY_TYPE_NONE))
569 return 0;
570
503 falcon_mask_status_intr(efx, 0); 571 falcon_mask_status_intr(efx, 0);
504 xaui_link_ok = falcon_xaui_link_ok(efx); 572 xaui_link_ok = falcon_xaui_link_ok(efx);
505 573
diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c
index dc06bb0aa575..c4f540e93b79 100644
--- a/drivers/net/sfc/mdio_10g.c
+++ b/drivers/net/sfc/mdio_10g.c
@@ -44,6 +44,9 @@ static int mdio_clause45_check_mmd(struct efx_nic *efx, int mmd,
44 int status; 44 int status;
45 int phy_id = efx->mii.phy_id; 45 int phy_id = efx->mii.phy_id;
46 46
47 if (LOOPBACK_INTERNAL(efx))
48 return 0;
49
47 /* Read MMD STATUS2 to check it is responding. */ 50 /* Read MMD STATUS2 to check it is responding. */
48 status = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_STAT2); 51 status = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_STAT2);
49 if (((status >> MDIO_MMDREG_STAT2_PRESENT_LBN) & 52 if (((status >> MDIO_MMDREG_STAT2_PRESENT_LBN) &
@@ -164,6 +167,22 @@ int mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
164 int mmd = 0; 167 int mmd = 0;
165 int good; 168 int good;
166 169
170 /* If the port is in loopback, then we should only consider a subset
171 * of mmd's */
172 if (LOOPBACK_INTERNAL(efx))
173 return 1;
174 else if (efx->loopback_mode == LOOPBACK_NETWORK)
175 return 0;
176 else if (efx->loopback_mode == LOOPBACK_PHYXS)
177 mmd_mask &= ~(MDIO_MMDREG_DEVS0_PHYXS |
178 MDIO_MMDREG_DEVS0_PCS |
179 MDIO_MMDREG_DEVS0_PMAPMD);
180 else if (efx->loopback_mode == LOOPBACK_PCS)
181 mmd_mask &= ~(MDIO_MMDREG_DEVS0_PCS |
182 MDIO_MMDREG_DEVS0_PMAPMD);
183 else if (efx->loopback_mode == LOOPBACK_PMAPMD)
184 mmd_mask &= ~MDIO_MMDREG_DEVS0_PMAPMD;
185
167 while (mmd_mask) { 186 while (mmd_mask) {
168 if (mmd_mask & 1) { 187 if (mmd_mask & 1) {
169 /* Double reads because link state is latched, and a 188 /* Double reads because link state is latched, and a
@@ -182,6 +201,65 @@ int mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
182 return ok; 201 return ok;
183} 202}
184 203
204void mdio_clause45_transmit_disable(struct efx_nic *efx)
205{
206 int phy_id = efx->mii.phy_id;
207 int ctrl1, ctrl2;
208
209 ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
210 MDIO_MMDREG_TXDIS);
211 if (efx->tx_disabled)
212 ctrl2 |= (1 << MDIO_MMDREG_TXDIS_GLOBAL_LBN);
213 else
214 ctrl1 &= ~(1 << MDIO_MMDREG_TXDIS_GLOBAL_LBN);
215 if (ctrl1 != ctrl2)
216 mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
217 MDIO_MMDREG_TXDIS, ctrl2);
218}
219
220void mdio_clause45_phy_reconfigure(struct efx_nic *efx)
221{
222 int phy_id = efx->mii.phy_id;
223 int ctrl1, ctrl2;
224
225 /* Handle (with debouncing) PMA/PMD loopback */
226 ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
227 MDIO_MMDREG_CTRL1);
228
229 if (efx->loopback_mode == LOOPBACK_PMAPMD)
230 ctrl2 |= (1 << MDIO_PMAPMD_CTRL1_LBACK_LBN);
231 else
232 ctrl2 &= ~(1 << MDIO_PMAPMD_CTRL1_LBACK_LBN);
233
234 if (ctrl1 != ctrl2)
235 mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
236 MDIO_MMDREG_CTRL1, ctrl2);
237
238 /* Handle (with debouncing) PCS loopback */
239 ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS,
240 MDIO_MMDREG_CTRL1);
241 if (efx->loopback_mode == LOOPBACK_PCS)
242 ctrl2 |= (1 << MDIO_MMDREG_CTRL1_LBACK_LBN);
243 else
244 ctrl2 &= ~(1 << MDIO_MMDREG_CTRL1_LBACK_LBN);
245
246 if (ctrl1 != ctrl2)
247 mdio_clause45_write(efx, phy_id, MDIO_MMD_PCS,
248 MDIO_MMDREG_CTRL1, ctrl2);
249
250 /* Handle (with debouncing) PHYXS network loopback */
251 ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS,
252 MDIO_MMDREG_CTRL1);
253 if (efx->loopback_mode == LOOPBACK_NETWORK)
254 ctrl2 |= (1 << MDIO_MMDREG_CTRL1_LBACK_LBN);
255 else
256 ctrl2 &= ~(1 << MDIO_MMDREG_CTRL1_LBACK_LBN);
257
258 if (ctrl1 != ctrl2)
259 mdio_clause45_write(efx, phy_id, MDIO_MMD_PHYXS,
260 MDIO_MMDREG_CTRL1, ctrl2);
261}
262
185/** 263/**
186 * mdio_clause45_get_settings - Read (some of) the PHY settings over MDIO. 264 * mdio_clause45_get_settings - Read (some of) the PHY settings over MDIO.
187 * @efx: Efx NIC 265 * @efx: Efx NIC
diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h
index 338c62c1195b..cb99f3f4491c 100644
--- a/drivers/net/sfc/mdio_10g.h
+++ b/drivers/net/sfc/mdio_10g.h
@@ -44,11 +44,16 @@
44#define MDIO_MMDREG_DEVS1 (6) 44#define MDIO_MMDREG_DEVS1 (6)
45#define MDIO_MMDREG_CTRL2 (7) 45#define MDIO_MMDREG_CTRL2 (7)
46#define MDIO_MMDREG_STAT2 (8) 46#define MDIO_MMDREG_STAT2 (8)
47#define MDIO_MMDREG_TXDIS (9)
47 48
48/* Bits in MMDREG_CTRL1 */ 49/* Bits in MMDREG_CTRL1 */
49/* Reset */ 50/* Reset */
50#define MDIO_MMDREG_CTRL1_RESET_LBN (15) 51#define MDIO_MMDREG_CTRL1_RESET_LBN (15)
51#define MDIO_MMDREG_CTRL1_RESET_WIDTH (1) 52#define MDIO_MMDREG_CTRL1_RESET_WIDTH (1)
53/* Loopback */
54/* Loopback bit for WIS, PCS, PHYSX and DTEXS */
55#define MDIO_MMDREG_CTRL1_LBACK_LBN (14)
56#define MDIO_MMDREG_CTRL1_LBACK_WIDTH (1)
52 57
53/* Bits in MMDREG_STAT1 */ 58/* Bits in MMDREG_STAT1 */
54#define MDIO_MMDREG_STAT1_FAULT_LBN (7) 59#define MDIO_MMDREG_STAT1_FAULT_LBN (7)
@@ -56,6 +61,9 @@
56/* Link state */ 61/* Link state */
57#define MDIO_MMDREG_STAT1_LINK_LBN (2) 62#define MDIO_MMDREG_STAT1_LINK_LBN (2)
58#define MDIO_MMDREG_STAT1_LINK_WIDTH (1) 63#define MDIO_MMDREG_STAT1_LINK_WIDTH (1)
64/* Low power ability */
65#define MDIO_MMDREG_STAT1_LPABLE_LBN (1)
66#define MDIO_MMDREG_STAT1_LPABLE_WIDTH (1)
59 67
60/* Bits in ID reg */ 68/* Bits in ID reg */
61#define MDIO_ID_REV(_id32) (_id32 & 0xf) 69#define MDIO_ID_REV(_id32) (_id32 & 0xf)
@@ -76,6 +84,14 @@
76#define MDIO_MMDREG_STAT2_PRESENT_LBN (14) 84#define MDIO_MMDREG_STAT2_PRESENT_LBN (14)
77#define MDIO_MMDREG_STAT2_PRESENT_WIDTH (2) 85#define MDIO_MMDREG_STAT2_PRESENT_WIDTH (2)
78 86
87/* Bits in MMDREG_TXDIS */
88#define MDIO_MMDREG_TXDIS_GLOBAL_LBN (0)
89#define MDIO_MMDREG_TXDIS_GLOBAL_WIDTH (1)
90
91/* MMD-specific bits, ordered by MMD, then register */
92#define MDIO_PMAPMD_CTRL1_LBACK_LBN (0)
93#define MDIO_PMAPMD_CTRL1_LBACK_WIDTH (1)
94
79/* PMA type (4 bits) */ 95/* PMA type (4 bits) */
80#define MDIO_PMAPMD_CTRL2_10G_CX4 (0x0) 96#define MDIO_PMAPMD_CTRL2_10G_CX4 (0x0)
81#define MDIO_PMAPMD_CTRL2_10G_EW (0x1) 97#define MDIO_PMAPMD_CTRL2_10G_EW (0x1)
@@ -217,6 +233,12 @@ int mdio_clause45_check_mmds(struct efx_nic *efx,
217extern int mdio_clause45_links_ok(struct efx_nic *efx, 233extern int mdio_clause45_links_ok(struct efx_nic *efx,
218 unsigned int mmd_mask); 234 unsigned int mmd_mask);
219 235
236/* Generic transmit disable support though PMAPMD */
237extern void mdio_clause45_transmit_disable(struct efx_nic *efx);
238
239/* Generic part of reconfigure: set/clear loopback bits */
240extern void mdio_clause45_phy_reconfigure(struct efx_nic *efx);
241
220/* Read (some of) the PHY settings over MDIO */ 242/* Read (some of) the PHY settings over MDIO */
221extern void mdio_clause45_get_settings(struct efx_nic *efx, 243extern void mdio_clause45_get_settings(struct efx_nic *efx,
222 struct ethtool_cmd *ecmd); 244 struct ethtool_cmd *ecmd);
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 9c285fb6153c..59f261b4171f 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -448,6 +448,9 @@ struct efx_board {
448 struct efx_blinker blinker; 448 struct efx_blinker blinker;
449}; 449};
450 450
451#define STRING_TABLE_LOOKUP(val, member) \
452 member ## _names[val]
453
451enum efx_int_mode { 454enum efx_int_mode {
452 /* Be careful if altering to correct macro below */ 455 /* Be careful if altering to correct macro below */
453 EFX_INT_MODE_MSIX = 0, 456 EFX_INT_MODE_MSIX = 0,
@@ -520,6 +523,7 @@ enum efx_fc_type {
520 * @check_hw: Check hardware 523 * @check_hw: Check hardware
521 * @reset_xaui: Reset XAUI side of PHY for (software sequenced reset) 524 * @reset_xaui: Reset XAUI side of PHY for (software sequenced reset)
522 * @mmds: MMD presence mask 525 * @mmds: MMD presence mask
526 * @loopbacks: Supported loopback modes mask
523 */ 527 */
524struct efx_phy_operations { 528struct efx_phy_operations {
525 int (*init) (struct efx_nic *efx); 529 int (*init) (struct efx_nic *efx);
@@ -529,6 +533,7 @@ struct efx_phy_operations {
529 int (*check_hw) (struct efx_nic *efx); 533 int (*check_hw) (struct efx_nic *efx);
530 void (*reset_xaui) (struct efx_nic *efx); 534 void (*reset_xaui) (struct efx_nic *efx);
531 int mmds; 535 int mmds;
536 unsigned loopbacks;
532}; 537};
533 538
534/* 539/*
@@ -667,6 +672,7 @@ union efx_multicast_hash {
667 * @phy_op: PHY interface 672 * @phy_op: PHY interface
668 * @phy_data: PHY private data (including PHY-specific stats) 673 * @phy_data: PHY private data (including PHY-specific stats)
669 * @mii: PHY interface 674 * @mii: PHY interface
675 * @tx_disabled: PHY transmitter turned off
670 * @link_up: Link status 676 * @link_up: Link status
671 * @link_options: Link options (MII/GMII format) 677 * @link_options: Link options (MII/GMII format)
672 * @n_link_state_changes: Number of times the link has changed state 678 * @n_link_state_changes: Number of times the link has changed state
@@ -674,6 +680,9 @@ union efx_multicast_hash {
674 * @multicast_hash: Multicast hash table 680 * @multicast_hash: Multicast hash table
675 * @flow_control: Flow control flags - separate RX/TX so can't use link_options 681 * @flow_control: Flow control flags - separate RX/TX so can't use link_options
676 * @reconfigure_work: work item for dealing with PHY events 682 * @reconfigure_work: work item for dealing with PHY events
683 * @loopback_mode: Loopback status
684 * @loopback_modes: Supported loopback mode bitmask
685 * @loopback_selftest: Offline self-test private state
677 * 686 *
678 * The @priv field of the corresponding &struct net_device points to 687 * The @priv field of the corresponding &struct net_device points to
679 * this. 688 * this.
@@ -733,6 +742,7 @@ struct efx_nic {
733 struct efx_phy_operations *phy_op; 742 struct efx_phy_operations *phy_op;
734 void *phy_data; 743 void *phy_data;
735 struct mii_if_info mii; 744 struct mii_if_info mii;
745 unsigned tx_disabled;
736 746
737 int link_up; 747 int link_up;
738 unsigned int link_options; 748 unsigned int link_options;
@@ -744,6 +754,10 @@ struct efx_nic {
744 struct work_struct reconfigure_work; 754 struct work_struct reconfigure_work;
745 755
746 atomic_t rx_reset; 756 atomic_t rx_reset;
757 enum efx_loopback_mode loopback_mode;
758 unsigned int loopback_modes;
759
760 void *loopback_selftest;
747}; 761};
748 762
749/** 763/**
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c
index 9fd198442e8d..670622373ddf 100644
--- a/drivers/net/sfc/rx.c
+++ b/drivers/net/sfc/rx.c
@@ -19,6 +19,7 @@
19#include "rx.h" 19#include "rx.h"
20#include "efx.h" 20#include "efx.h"
21#include "falcon.h" 21#include "falcon.h"
22#include "selftest.h"
22#include "workarounds.h" 23#include "workarounds.h"
23 24
24/* Number of RX descriptors pushed at once. */ 25/* Number of RX descriptors pushed at once. */
@@ -683,6 +684,15 @@ void __efx_rx_packet(struct efx_channel *channel,
683 struct sk_buff *skb; 684 struct sk_buff *skb;
684 int lro = efx->net_dev->features & NETIF_F_LRO; 685 int lro = efx->net_dev->features & NETIF_F_LRO;
685 686
687 /* If we're in loopback test, then pass the packet directly to the
688 * loopback layer, and free the rx_buf here
689 */
690 if (unlikely(efx->loopback_selftest)) {
691 efx_loopback_rx_packet(efx, rx_buf->data, rx_buf->len);
692 efx_free_rx_buffer(efx, rx_buf);
693 goto done;
694 }
695
686 if (rx_buf->skb) { 696 if (rx_buf->skb) {
687 prefetch(skb_shinfo(rx_buf->skb)); 697 prefetch(skb_shinfo(rx_buf->skb));
688 698
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c
new file mode 100644
index 000000000000..cbda15946e8f
--- /dev/null
+++ b/drivers/net/sfc/selftest.c
@@ -0,0 +1,717 @@
1/****************************************************************************
2 * Driver for Solarflare Solarstorm network controllers and boards
3 * Copyright 2005-2006 Fen Systems Ltd.
4 * Copyright 2006-2008 Solarflare Communications Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation, incorporated herein by reference.
9 */
10
11#include <linux/netdevice.h>
12#include <linux/module.h>
13#include <linux/delay.h>
14#include <linux/kernel_stat.h>
15#include <linux/pci.h>
16#include <linux/ethtool.h>
17#include <linux/ip.h>
18#include <linux/in.h>
19#include <linux/udp.h>
20#include <linux/rtnetlink.h>
21#include <asm/io.h>
22#include "net_driver.h"
23#include "ethtool.h"
24#include "efx.h"
25#include "falcon.h"
26#include "selftest.h"
27#include "boards.h"
28#include "workarounds.h"
29#include "mac.h"
30
31/*
32 * Loopback test packet structure
33 *
34 * The self-test should stress every RSS vector, and unfortunately
35 * Falcon only performs RSS on TCP/UDP packets.
36 */
37struct efx_loopback_payload {
38 struct ethhdr header;
39 struct iphdr ip;
40 struct udphdr udp;
41 __be16 iteration;
42 const char msg[64];
43} __attribute__ ((packed));
44
45/* Loopback test source MAC address */
46static const unsigned char payload_source[ETH_ALEN] = {
47 0x00, 0x0f, 0x53, 0x1b, 0x1b, 0x1b,
48};
49
50static const char *payload_msg =
51 "Hello world! This is an Efx loopback test in progress!";
52
53/**
54 * efx_selftest_state - persistent state during a selftest
55 * @flush: Drop all packets in efx_loopback_rx_packet
56 * @packet_count: Number of packets being used in this test
57 * @skbs: An array of skbs transmitted
58 * @rx_good: RX good packet count
59 * @rx_bad: RX bad packet count
60 * @payload: Payload used in tests
61 */
62struct efx_selftest_state {
63 int flush;
64 int packet_count;
65 struct sk_buff **skbs;
66 atomic_t rx_good;
67 atomic_t rx_bad;
68 struct efx_loopback_payload payload;
69};
70
71/**************************************************************************
72 *
73 * Configurable values
74 *
75 **************************************************************************/
76
77/* Level of loopback testing
78 *
79 * The maximum packet burst length is 16**(n-1), i.e.
80 *
81 * - Level 0 : no packets
82 * - Level 1 : 1 packet
83 * - Level 2 : 17 packets (1 * 1 packet, 1 * 16 packets)
84 * - Level 3 : 273 packets (1 * 1 packet, 1 * 16 packet, 1 * 256 packets)
85 *
86 */
87static unsigned int loopback_test_level = 3;
88
89/**************************************************************************
90 *
91 * Interrupt and event queue testing
92 *
93 **************************************************************************/
94
95/* Test generation and receipt of interrupts */
96static int efx_test_interrupts(struct efx_nic *efx,
97 struct efx_self_tests *tests)
98{
99 struct efx_channel *channel;
100
101 EFX_LOG(efx, "testing interrupts\n");
102 tests->interrupt = -1;
103
104 /* Reset interrupt flag */
105 efx->last_irq_cpu = -1;
106 smp_wmb();
107
108 /* ACK each interrupting event queue. Receiving an interrupt due to
109 * traffic before a test event is raised is considered a pass */
110 efx_for_each_channel_with_interrupt(channel, efx) {
111 if (channel->work_pending)
112 efx_process_channel_now(channel);
113 if (efx->last_irq_cpu >= 0)
114 goto success;
115 }
116
117 falcon_generate_interrupt(efx);
118
119 /* Wait for arrival of test interrupt. */
120 EFX_LOG(efx, "waiting for test interrupt\n");
121 schedule_timeout_uninterruptible(HZ / 10);
122 if (efx->last_irq_cpu >= 0)
123 goto success;
124
125 EFX_ERR(efx, "timed out waiting for interrupt\n");
126 return -ETIMEDOUT;
127
128 success:
129 EFX_LOG(efx, "test interrupt (mode %d) seen on CPU%d\n",
130 efx->interrupt_mode, efx->last_irq_cpu);
131 tests->interrupt = 1;
132 return 0;
133}
134
135/* Test generation and receipt of non-interrupting events */
136static int efx_test_eventq(struct efx_channel *channel,
137 struct efx_self_tests *tests)
138{
139 unsigned int magic;
140
141 /* Channel specific code, limited to 20 bits */
142 magic = (0x00010150 + channel->channel);
143 EFX_LOG(channel->efx, "channel %d testing event queue with code %x\n",
144 channel->channel, magic);
145
146 tests->eventq_dma[channel->channel] = -1;
147 tests->eventq_int[channel->channel] = 1; /* fake pass */
148 tests->eventq_poll[channel->channel] = 1; /* fake pass */
149
150 /* Reset flag and zero magic word */
151 channel->efx->last_irq_cpu = -1;
152 channel->eventq_magic = 0;
153 smp_wmb();
154
155 falcon_generate_test_event(channel, magic);
156 udelay(1);
157
158 efx_process_channel_now(channel);
159 if (channel->eventq_magic != magic) {
160 EFX_ERR(channel->efx, "channel %d failed to see test event\n",
161 channel->channel);
162 return -ETIMEDOUT;
163 } else {
164 tests->eventq_dma[channel->channel] = 1;
165 }
166
167 return 0;
168}
169
170/* Test generation and receipt of interrupting events */
171static int efx_test_eventq_irq(struct efx_channel *channel,
172 struct efx_self_tests *tests)
173{
174 unsigned int magic, count;
175
176 /* Channel specific code, limited to 20 bits */
177 magic = (0x00010150 + channel->channel);
178 EFX_LOG(channel->efx, "channel %d testing event queue with code %x\n",
179 channel->channel, magic);
180
181 tests->eventq_dma[channel->channel] = -1;
182 tests->eventq_int[channel->channel] = -1;
183 tests->eventq_poll[channel->channel] = -1;
184
185 /* Reset flag and zero magic word */
186 channel->efx->last_irq_cpu = -1;
187 channel->eventq_magic = 0;
188 smp_wmb();
189
190 falcon_generate_test_event(channel, magic);
191
192 /* Wait for arrival of interrupt */
193 count = 0;
194 do {
195 schedule_timeout_uninterruptible(HZ / 100);
196
197 if (channel->work_pending)
198 efx_process_channel_now(channel);
199
200 if (channel->eventq_magic == magic)
201 goto eventq_ok;
202 } while (++count < 2);
203
204 EFX_ERR(channel->efx, "channel %d timed out waiting for event queue\n",
205 channel->channel);
206
207 /* See if interrupt arrived */
208 if (channel->efx->last_irq_cpu >= 0) {
209 EFX_ERR(channel->efx, "channel %d saw interrupt on CPU%d "
210 "during event queue test\n", channel->channel,
211 raw_smp_processor_id());
212 tests->eventq_int[channel->channel] = 1;
213 }
214
215 /* Check to see if event was received even if interrupt wasn't */
216 efx_process_channel_now(channel);
217 if (channel->eventq_magic == magic) {
218 EFX_ERR(channel->efx, "channel %d event was generated, but "
219 "failed to trigger an interrupt\n", channel->channel);
220 tests->eventq_dma[channel->channel] = 1;
221 }
222
223 return -ETIMEDOUT;
224 eventq_ok:
225 EFX_LOG(channel->efx, "channel %d event queue passed\n",
226 channel->channel);
227 tests->eventq_dma[channel->channel] = 1;
228 tests->eventq_int[channel->channel] = 1;
229 tests->eventq_poll[channel->channel] = 1;
230 return 0;
231}
232
233/**************************************************************************
234 *
235 * PHY testing
236 *
237 **************************************************************************/
238
239/* Check PHY presence by reading the PHY ID registers */
240static int efx_test_phy(struct efx_nic *efx,
241 struct efx_self_tests *tests)
242{
243 u16 physid1, physid2;
244 struct mii_if_info *mii = &efx->mii;
245 struct net_device *net_dev = efx->net_dev;
246
247 if (efx->phy_type == PHY_TYPE_NONE)
248 return 0;
249
250 EFX_LOG(efx, "testing PHY presence\n");
251 tests->phy_ok = -1;
252
253 physid1 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID1);
254 physid2 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID2);
255
256 if ((physid1 != 0x0000) && (physid1 != 0xffff) &&
257 (physid2 != 0x0000) && (physid2 != 0xffff)) {
258 EFX_LOG(efx, "found MII PHY %d ID 0x%x:%x\n",
259 mii->phy_id, physid1, physid2);
260 tests->phy_ok = 1;
261 return 0;
262 }
263
264 EFX_ERR(efx, "no MII PHY present with ID %d\n", mii->phy_id);
265 return -ENODEV;
266}
267
268/**************************************************************************
269 *
270 * Loopback testing
271 * NB Only one loopback test can be executing concurrently.
272 *
273 **************************************************************************/
274
275/* Loopback test RX callback
276 * This is called for each received packet during loopback testing.
277 */
278void efx_loopback_rx_packet(struct efx_nic *efx,
279 const char *buf_ptr, int pkt_len)
280{
281 struct efx_selftest_state *state = efx->loopback_selftest;
282 struct efx_loopback_payload *received;
283 struct efx_loopback_payload *payload;
284
285 BUG_ON(!buf_ptr);
286
287 /* If we are just flushing, then drop the packet */
288 if ((state == NULL) || state->flush)
289 return;
290
291 payload = &state->payload;
292
293 received = (struct efx_loopback_payload *)(char *) buf_ptr;
294 received->ip.saddr = payload->ip.saddr;
295 received->ip.check = payload->ip.check;
296
297 /* Check that header exists */
298 if (pkt_len < sizeof(received->header)) {
299 EFX_ERR(efx, "saw runt RX packet (length %d) in %s loopback "
300 "test\n", pkt_len, LOOPBACK_MODE(efx));
301 goto err;
302 }
303
304 /* Check that the ethernet header exists */
305 if (memcmp(&received->header, &payload->header, ETH_HLEN) != 0) {
306 EFX_ERR(efx, "saw non-loopback RX packet in %s loopback test\n",
307 LOOPBACK_MODE(efx));
308 goto err;
309 }
310
311 /* Check packet length */
312 if (pkt_len != sizeof(*payload)) {
313 EFX_ERR(efx, "saw incorrect RX packet length %d (wanted %d) in "
314 "%s loopback test\n", pkt_len, (int)sizeof(*payload),
315 LOOPBACK_MODE(efx));
316 goto err;
317 }
318
319 /* Check that IP header matches */
320 if (memcmp(&received->ip, &payload->ip, sizeof(payload->ip)) != 0) {
321 EFX_ERR(efx, "saw corrupted IP header in %s loopback test\n",
322 LOOPBACK_MODE(efx));
323 goto err;
324 }
325
326 /* Check that msg and padding matches */
327 if (memcmp(&received->msg, &payload->msg, sizeof(received->msg)) != 0) {
328 EFX_ERR(efx, "saw corrupted RX packet in %s loopback test\n",
329 LOOPBACK_MODE(efx));
330 goto err;
331 }
332
333 /* Check that iteration matches */
334 if (received->iteration != payload->iteration) {
335 EFX_ERR(efx, "saw RX packet from iteration %d (wanted %d) in "
336 "%s loopback test\n", ntohs(received->iteration),
337 ntohs(payload->iteration), LOOPBACK_MODE(efx));
338 goto err;
339 }
340
341 /* Increase correct RX count */
342 EFX_TRACE(efx, "got loopback RX in %s loopback test\n",
343 LOOPBACK_MODE(efx));
344
345 atomic_inc(&state->rx_good);
346 return;
347
348 err:
349#ifdef EFX_ENABLE_DEBUG
350 if (atomic_read(&state->rx_bad) == 0) {
351 EFX_ERR(efx, "received packet:\n");
352 print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
353 buf_ptr, pkt_len, 0);
354 EFX_ERR(efx, "expected packet:\n");
355 print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
356 &state->payload, sizeof(state->payload), 0);
357 }
358#endif
359 atomic_inc(&state->rx_bad);
360}
361
362/* Initialise an efx_selftest_state for a new iteration */
363static void efx_iterate_state(struct efx_nic *efx)
364{
365 struct efx_selftest_state *state = efx->loopback_selftest;
366 struct net_device *net_dev = efx->net_dev;
367 struct efx_loopback_payload *payload = &state->payload;
368
369 /* Initialise the layerII header */
370 memcpy(&payload->header.h_dest, net_dev->dev_addr, ETH_ALEN);
371 memcpy(&payload->header.h_source, &payload_source, ETH_ALEN);
372 payload->header.h_proto = htons(ETH_P_IP);
373
374 /* saddr set later and used as incrementing count */
375 payload->ip.daddr = htonl(INADDR_LOOPBACK);
376 payload->ip.ihl = 5;
377 payload->ip.check = htons(0xdead);
378 payload->ip.tot_len = htons(sizeof(*payload) - sizeof(struct ethhdr));
379 payload->ip.version = IPVERSION;
380 payload->ip.protocol = IPPROTO_UDP;
381
382 /* Initialise udp header */
383 payload->udp.source = 0;
384 payload->udp.len = htons(sizeof(*payload) - sizeof(struct ethhdr) -
385 sizeof(struct iphdr));
386 payload->udp.check = 0; /* checksum ignored */
387
388 /* Fill out payload */
389 payload->iteration = htons(ntohs(payload->iteration) + 1);
390 memcpy(&payload->msg, payload_msg, sizeof(payload_msg));
391
392 /* Fill out remaining state members */
393 atomic_set(&state->rx_good, 0);
394 atomic_set(&state->rx_bad, 0);
395 smp_wmb();
396}
397
398static int efx_tx_loopback(struct efx_tx_queue *tx_queue)
399{
400 struct efx_nic *efx = tx_queue->efx;
401 struct efx_selftest_state *state = efx->loopback_selftest;
402 struct efx_loopback_payload *payload;
403 struct sk_buff *skb;
404 int i, rc;
405
406 /* Transmit N copies of buffer */
407 for (i = 0; i < state->packet_count; i++) {
408 /* Allocate an skb, holding an extra reference for
409 * transmit completion counting */
410 skb = alloc_skb(sizeof(state->payload), GFP_KERNEL);
411 if (!skb)
412 return -ENOMEM;
413 state->skbs[i] = skb;
414 skb_get(skb);
415
416 /* Copy the payload in, incrementing the source address to
417 * exercise the rss vectors */
418 payload = ((struct efx_loopback_payload *)
419 skb_put(skb, sizeof(state->payload)));
420 memcpy(payload, &state->payload, sizeof(state->payload));
421 payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2));
422
423 /* Ensure everything we've written is visible to the
424 * interrupt handler. */
425 smp_wmb();
426
427 if (NET_DEV_REGISTERED(efx))
428 netif_tx_lock_bh(efx->net_dev);
429 rc = efx_xmit(efx, tx_queue, skb);
430 if (NET_DEV_REGISTERED(efx))
431 netif_tx_unlock_bh(efx->net_dev);
432
433 if (rc != NETDEV_TX_OK) {
434 EFX_ERR(efx, "TX queue %d could not transmit packet %d "
435 "of %d in %s loopback test\n", tx_queue->queue,
436 i + 1, state->packet_count, LOOPBACK_MODE(efx));
437
438 /* Defer cleaning up the other skbs for the caller */
439 kfree_skb(skb);
440 return -EPIPE;
441 }
442 }
443
444 return 0;
445}
446
447static int efx_rx_loopback(struct efx_tx_queue *tx_queue,
448 struct efx_loopback_self_tests *lb_tests)
449{
450 struct efx_nic *efx = tx_queue->efx;
451 struct efx_selftest_state *state = efx->loopback_selftest;
452 struct sk_buff *skb;
453 int tx_done = 0, rx_good, rx_bad;
454 int i, rc = 0;
455
456 if (NET_DEV_REGISTERED(efx))
457 netif_tx_lock_bh(efx->net_dev);
458
459 /* Count the number of tx completions, and decrement the refcnt. Any
460 * skbs not already completed will be free'd when the queue is flushed */
461 for (i=0; i < state->packet_count; i++) {
462 skb = state->skbs[i];
463 if (skb && !skb_shared(skb))
464 ++tx_done;
465 dev_kfree_skb_any(skb);
466 }
467
468 if (NET_DEV_REGISTERED(efx))
469 netif_tx_unlock_bh(efx->net_dev);
470
471 /* Check TX completion and received packet counts */
472 rx_good = atomic_read(&state->rx_good);
473 rx_bad = atomic_read(&state->rx_bad);
474 if (tx_done != state->packet_count) {
475 /* Don't free the skbs; they will be picked up on TX
476 * overflow or channel teardown.
477 */
478 EFX_ERR(efx, "TX queue %d saw only %d out of an expected %d "
479 "TX completion events in %s loopback test\n",
480 tx_queue->queue, tx_done, state->packet_count,
481 LOOPBACK_MODE(efx));
482 rc = -ETIMEDOUT;
483 /* Allow to fall through so we see the RX errors as well */
484 }
485
486 /* We may always be up to a flush away from our desired packet total */
487 if (rx_good != state->packet_count) {
488 EFX_LOG(efx, "TX queue %d saw only %d out of an expected %d "
489 "received packets in %s loopback test\n",
490 tx_queue->queue, rx_good, state->packet_count,
491 LOOPBACK_MODE(efx));
492 rc = -ETIMEDOUT;
493 /* Fall through */
494 }
495
496 /* Update loopback test structure */
497 lb_tests->tx_sent[tx_queue->queue] += state->packet_count;
498 lb_tests->tx_done[tx_queue->queue] += tx_done;
499 lb_tests->rx_good += rx_good;
500 lb_tests->rx_bad += rx_bad;
501
502 return rc;
503}
504
505static int
506efx_test_loopback(struct efx_tx_queue *tx_queue,
507 struct efx_loopback_self_tests *lb_tests)
508{
509 struct efx_nic *efx = tx_queue->efx;
510 struct efx_selftest_state *state = efx->loopback_selftest;
511 struct efx_channel *channel;
512 int i, rc = 0;
513
514 for (i = 0; i < loopback_test_level; i++) {
515 /* Determine how many packets to send */
516 state->packet_count = (efx->type->txd_ring_mask + 1) / 3;
517 state->packet_count = min(1 << (i << 2), state->packet_count);
518 state->skbs = kzalloc(sizeof(state->skbs[0]) *
519 state->packet_count, GFP_KERNEL);
520 state->flush = 0;
521
522 EFX_LOG(efx, "TX queue %d testing %s loopback with %d "
523 "packets\n", tx_queue->queue, LOOPBACK_MODE(efx),
524 state->packet_count);
525
526 efx_iterate_state(efx);
527 rc = efx_tx_loopback(tx_queue);
528
529 /* NAPI polling is not enabled, so process channels synchronously */
530 schedule_timeout_uninterruptible(HZ / 50);
531 efx_for_each_channel_with_interrupt(channel, efx) {
532 if (channel->work_pending)
533 efx_process_channel_now(channel);
534 }
535
536 rc |= efx_rx_loopback(tx_queue, lb_tests);
537 kfree(state->skbs);
538
539 if (rc) {
540 /* Wait a while to ensure there are no packets
541 * floating around after a failure. */
542 schedule_timeout_uninterruptible(HZ / 10);
543 return rc;
544 }
545 }
546
547 EFX_LOG(efx, "TX queue %d passed %s loopback test with a burst length "
548 "of %d packets\n", tx_queue->queue, LOOPBACK_MODE(efx),
549 state->packet_count);
550
551 return rc;
552}
553
554static int efx_test_loopbacks(struct efx_nic *efx,
555 struct efx_self_tests *tests,
556 unsigned int loopback_modes)
557{
558 struct efx_selftest_state *state = efx->loopback_selftest;
559 struct ethtool_cmd ecmd, ecmd_loopback;
560 struct efx_tx_queue *tx_queue;
561 enum efx_loopback_mode old_mode, mode;
562 int count, rc = 0, link_up;
563
564 rc = efx_ethtool_get_settings(efx->net_dev, &ecmd);
565 if (rc) {
566 EFX_ERR(efx, "could not get GMII settings\n");
567 return rc;
568 }
569 old_mode = efx->loopback_mode;
570
571 /* Disable autonegotiation for the purposes of loopback */
572 memcpy(&ecmd_loopback, &ecmd, sizeof(ecmd_loopback));
573 if (ecmd_loopback.autoneg == AUTONEG_ENABLE) {
574 ecmd_loopback.autoneg = AUTONEG_DISABLE;
575 ecmd_loopback.duplex = DUPLEX_FULL;
576 ecmd_loopback.speed = SPEED_10000;
577 }
578
579 rc = efx_ethtool_set_settings(efx->net_dev, &ecmd_loopback);
580 if (rc) {
581 EFX_ERR(efx, "could not disable autonegotiation\n");
582 goto out;
583 }
584 tests->loopback_speed = ecmd_loopback.speed;
585 tests->loopback_full_duplex = ecmd_loopback.duplex;
586
587 /* Test all supported loopback modes */
588 for (mode = LOOPBACK_NONE; mode < LOOPBACK_TEST_MAX; mode++) {
589 if (!(loopback_modes & (1 << mode)))
590 continue;
591
592 /* Move the port into the specified loopback mode. */
593 state->flush = 1;
594 efx->loopback_mode = mode;
595 efx_reconfigure_port(efx);
596
597 /* Wait for the PHY to signal the link is up */
598 count = 0;
599 do {
600 struct efx_channel *channel = &efx->channel[0];
601
602 falcon_check_xmac(efx);
603 schedule_timeout_uninterruptible(HZ / 10);
604 if (channel->work_pending)
605 efx_process_channel_now(channel);
606 /* Wait for PHY events to be processed */
607 flush_workqueue(efx->workqueue);
608 rmb();
609
610 /* efx->link_up can be 1 even if the XAUI link is down,
611 * (bug5762). Usually, it's not worth bothering with the
612 * difference, but for selftests, we need that extra
613 * guarantee that the link is really, really, up.
614 */
615 link_up = efx->link_up;
616 if (!falcon_xaui_link_ok(efx))
617 link_up = 0;
618
619 } while ((++count < 20) && !link_up);
620
621 /* The link should now be up. If it isn't, there is no point
622 * in attempting a loopback test */
623 if (!link_up) {
624 EFX_ERR(efx, "loopback %s never came up\n",
625 LOOPBACK_MODE(efx));
626 rc = -EIO;
627 goto out;
628 }
629
630 EFX_LOG(efx, "link came up in %s loopback in %d iterations\n",
631 LOOPBACK_MODE(efx), count);
632
633 /* Test every TX queue */
634 efx_for_each_tx_queue(tx_queue, efx) {
635 rc |= efx_test_loopback(tx_queue,
636 &tests->loopback[mode]);
637 if (rc)
638 goto out;
639 }
640 }
641
642 out:
643 /* Take out of loopback and restore PHY settings */
644 state->flush = 1;
645 efx->loopback_mode = old_mode;
646 efx_ethtool_set_settings(efx->net_dev, &ecmd);
647
648 return rc;
649}
650
651/**************************************************************************
652 *
653 * Entry points
654 *
655 *************************************************************************/
656
657/* Online (i.e. non-disruptive) testing
658 * This checks interrupt generation, event delivery and PHY presence. */
659int efx_online_test(struct efx_nic *efx, struct efx_self_tests *tests)
660{
661 struct efx_channel *channel;
662 int rc = 0;
663
664 EFX_LOG(efx, "performing online self-tests\n");
665
666 rc |= efx_test_interrupts(efx, tests);
667 efx_for_each_channel(channel, efx) {
668 if (channel->has_interrupt)
669 rc |= efx_test_eventq_irq(channel, tests);
670 else
671 rc |= efx_test_eventq(channel, tests);
672 }
673 rc |= efx_test_phy(efx, tests);
674
675 if (rc)
676 EFX_ERR(efx, "failed online self-tests\n");
677
678 return rc;
679}
680
681/* Offline (i.e. disruptive) testing
682 * This checks MAC and PHY loopback on the specified port. */
683int efx_offline_test(struct efx_nic *efx,
684 struct efx_self_tests *tests, unsigned int loopback_modes)
685{
686 struct efx_selftest_state *state;
687 int rc = 0;
688
689 EFX_LOG(efx, "performing offline self-tests\n");
690
691 /* Create a selftest_state structure to hold state for the test */
692 state = kzalloc(sizeof(*state), GFP_KERNEL);
693 if (state == NULL) {
694 rc = -ENOMEM;
695 goto out;
696 }
697
698 /* Set the port loopback_selftest member. From this point on
699 * all received packets will be dropped. Mark the state as
700 * "flushing" so all inflight packets are dropped */
701 BUG_ON(efx->loopback_selftest);
702 state->flush = 1;
703 efx->loopback_selftest = (void *)state;
704
705 rc = efx_test_loopbacks(efx, tests, loopback_modes);
706
707 efx->loopback_selftest = NULL;
708 wmb();
709 kfree(state);
710
711 out:
712 if (rc)
713 EFX_ERR(efx, "failed offline self-tests\n");
714
715 return rc;
716}
717
diff --git a/drivers/net/sfc/selftest.h b/drivers/net/sfc/selftest.h
new file mode 100644
index 000000000000..f6999c2b622d
--- /dev/null
+++ b/drivers/net/sfc/selftest.h
@@ -0,0 +1,50 @@
1/****************************************************************************
2 * Driver for Solarflare Solarstorm network controllers and boards
3 * Copyright 2005-2006 Fen Systems Ltd.
4 * Copyright 2006-2008 Solarflare Communications Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation, incorporated herein by reference.
9 */
10
11#ifndef EFX_SELFTEST_H
12#define EFX_SELFTEST_H
13
14#include "net_driver.h"
15
16/*
17 * Self tests
18 */
19
20struct efx_loopback_self_tests {
21 int tx_sent[EFX_MAX_TX_QUEUES];
22 int tx_done[EFX_MAX_TX_QUEUES];
23 int rx_good;
24 int rx_bad;
25};
26
27/* Efx self test results
28 * For fields which are not counters, 1 indicates success and -1
29 * indicates failure.
30 */
31struct efx_self_tests {
32 int interrupt;
33 int eventq_dma[EFX_MAX_CHANNELS];
34 int eventq_int[EFX_MAX_CHANNELS];
35 int eventq_poll[EFX_MAX_CHANNELS];
36 int phy_ok;
37 int loopback_speed;
38 int loopback_full_duplex;
39 struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX];
40};
41
42extern void efx_loopback_rx_packet(struct efx_nic *efx,
43 const char *buf_ptr, int pkt_len);
44extern int efx_online_test(struct efx_nic *efx,
45 struct efx_self_tests *tests);
46extern int efx_offline_test(struct efx_nic *efx,
47 struct efx_self_tests *tests,
48 unsigned int loopback_modes);
49
50#endif /* EFX_SELFTEST_H */
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index d8df031c711d..b1cd6deec01f 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -24,6 +24,11 @@
24 MDIO_MMDREG_DEVS0_PCS | \ 24 MDIO_MMDREG_DEVS0_PCS | \
25 MDIO_MMDREG_DEVS0_PHYXS) 25 MDIO_MMDREG_DEVS0_PHYXS)
26 26
27#define TENXPRESS_LOOPBACKS ((1 << LOOPBACK_PHYXS) | \
28 (1 << LOOPBACK_PCS) | \
29 (1 << LOOPBACK_PMAPMD) | \
30 (1 << LOOPBACK_NETWORK))
31
27/* We complain if we fail to see the link partner as 10G capable this many 32/* We complain if we fail to see the link partner as 10G capable this many
28 * times in a row (must be > 1 as sampling the autoneg. registers is racy) 33 * times in a row (must be > 1 as sampling the autoneg. registers is racy)
29 */ 34 */
@@ -72,6 +77,10 @@
72#define PMA_PMD_BIST_RXD_LBN (1) 77#define PMA_PMD_BIST_RXD_LBN (1)
73#define PMA_PMD_BIST_AFE_LBN (0) 78#define PMA_PMD_BIST_AFE_LBN (0)
74 79
80/* Special Software reset register */
81#define PMA_PMD_EXT_CTRL_REG 49152
82#define PMA_PMD_EXT_SSR_LBN 15
83
75#define BIST_MAX_DELAY (1000) 84#define BIST_MAX_DELAY (1000)
76#define BIST_POLL_DELAY (10) 85#define BIST_POLL_DELAY (10)
77 86
@@ -86,6 +95,11 @@
86#define PCS_TEST_SELECT_REG 0xd807 /* PRM 10.5.8 */ 95#define PCS_TEST_SELECT_REG 0xd807 /* PRM 10.5.8 */
87#define CLK312_EN_LBN 3 96#define CLK312_EN_LBN 3
88 97
98/* PHYXS registers */
99#define PHYXS_TEST1 (49162)
100#define LOOPBACK_NEAR_LBN (8)
101#define LOOPBACK_NEAR_WIDTH (1)
102
89/* Boot status register */ 103/* Boot status register */
90#define PCS_BOOT_STATUS_REG (0xd000) 104#define PCS_BOOT_STATUS_REG (0xd000)
91#define PCS_BOOT_FATAL_ERR_LBN (0) 105#define PCS_BOOT_FATAL_ERR_LBN (0)
@@ -106,7 +120,9 @@ MODULE_PARM_DESC(crc_error_reset_threshold,
106 120
107struct tenxpress_phy_data { 121struct tenxpress_phy_data {
108 enum tenxpress_state state; 122 enum tenxpress_state state;
123 enum efx_loopback_mode loopback_mode;
109 atomic_t bad_crc_count; 124 atomic_t bad_crc_count;
125 int tx_disabled;
110 int bad_lp_tries; 126 int bad_lp_tries;
111}; 127};
112 128
@@ -227,6 +243,35 @@ static int tenxpress_phy_init(struct efx_nic *efx)
227 return rc; 243 return rc;
228} 244}
229 245
246static int tenxpress_special_reset(struct efx_nic *efx)
247{
248 int rc, reg;
249
250 EFX_TRACE(efx, "%s\n", __func__);
251
252 /* Initiate reset */
253 reg = mdio_clause45_read(efx, efx->mii.phy_id,
254 MDIO_MMD_PMAPMD, PMA_PMD_EXT_CTRL_REG);
255 reg |= (1 << PMA_PMD_EXT_SSR_LBN);
256 mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
257 PMA_PMD_EXT_CTRL_REG, reg);
258
259 msleep(200);
260
261 /* Wait for the blocks to come out of reset */
262 rc = mdio_clause45_wait_reset_mmds(efx,
263 TENXPRESS_REQUIRED_DEVS);
264 if (rc < 0)
265 return rc;
266
267 /* Try and reconfigure the device */
268 rc = tenxpress_init(efx);
269 if (rc < 0)
270 return rc;
271
272 return 0;
273}
274
230static void tenxpress_set_bad_lp(struct efx_nic *efx, int bad_lp) 275static void tenxpress_set_bad_lp(struct efx_nic *efx, int bad_lp)
231{ 276{
232 struct tenxpress_phy_data *pd = efx->phy_data; 277 struct tenxpress_phy_data *pd = efx->phy_data;
@@ -301,11 +346,46 @@ static int tenxpress_link_ok(struct efx_nic *efx, int check_lp)
301 return ok; 346 return ok;
302} 347}
303 348
349static void tenxpress_phyxs_loopback(struct efx_nic *efx)
350{
351 int phy_id = efx->mii.phy_id;
352 int ctrl1, ctrl2;
353
354 ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS,
355 PHYXS_TEST1);
356 if (efx->loopback_mode == LOOPBACK_PHYXS)
357 ctrl2 |= (1 << LOOPBACK_NEAR_LBN);
358 else
359 ctrl2 &= ~(1 << LOOPBACK_NEAR_LBN);
360 if (ctrl1 != ctrl2)
361 mdio_clause45_write(efx, phy_id, MDIO_MMD_PHYXS,
362 PHYXS_TEST1, ctrl2);
363}
364
304static void tenxpress_phy_reconfigure(struct efx_nic *efx) 365static void tenxpress_phy_reconfigure(struct efx_nic *efx)
305{ 366{
367 struct tenxpress_phy_data *phy_data = efx->phy_data;
368 int loop_change = LOOPBACK_OUT_OF(phy_data, efx,
369 TENXPRESS_LOOPBACKS);
370
306 if (!tenxpress_state_is(efx, TENXPRESS_STATUS_NORMAL)) 371 if (!tenxpress_state_is(efx, TENXPRESS_STATUS_NORMAL))
307 return; 372 return;
308 373
374 /* When coming out of transmit disable, coming out of low power
375 * mode, or moving out of any PHY internal loopback mode,
376 * perform a special software reset */
377 if ((phy_data->tx_disabled && !efx->tx_disabled) ||
378 loop_change) {
379 (void) tenxpress_special_reset(efx);
380 falcon_reset_xaui(efx);
381 }
382
383 mdio_clause45_transmit_disable(efx);
384 mdio_clause45_phy_reconfigure(efx);
385 tenxpress_phyxs_loopback(efx);
386
387 phy_data->tx_disabled = efx->tx_disabled;
388 phy_data->loopback_mode = efx->loopback_mode;
309 efx->link_up = tenxpress_link_ok(efx, 0); 389 efx->link_up = tenxpress_link_ok(efx, 0);
310 efx->link_options = GM_LPA_10000FULL; 390 efx->link_options = GM_LPA_10000FULL;
311} 391}
@@ -433,4 +513,5 @@ struct efx_phy_operations falcon_tenxpress_phy_ops = {
433 .clear_interrupt = tenxpress_phy_clear_interrupt, 513 .clear_interrupt = tenxpress_phy_clear_interrupt,
434 .reset_xaui = tenxpress_reset_xaui, 514 .reset_xaui = tenxpress_reset_xaui,
435 .mmds = TENXPRESS_REQUIRED_DEVS, 515 .mmds = TENXPRESS_REQUIRED_DEVS,
516 .loopbacks = TENXPRESS_LOOPBACKS,
436}; 517};
diff --git a/drivers/net/sfc/xfp_phy.c b/drivers/net/sfc/xfp_phy.c
index 66dd5bf1eaa9..3b9f9ddbc372 100644
--- a/drivers/net/sfc/xfp_phy.c
+++ b/drivers/net/sfc/xfp_phy.c
@@ -24,6 +24,10 @@
24 MDIO_MMDREG_DEVS0_PMAPMD | \ 24 MDIO_MMDREG_DEVS0_PMAPMD | \
25 MDIO_MMDREG_DEVS0_PHYXS) 25 MDIO_MMDREG_DEVS0_PHYXS)
26 26
27#define XFP_LOOPBACKS ((1 << LOOPBACK_PCS) | \
28 (1 << LOOPBACK_PMAPMD) | \
29 (1 << LOOPBACK_NETWORK))
30
27/****************************************************************************/ 31/****************************************************************************/
28/* Quake-specific MDIO registers */ 32/* Quake-specific MDIO registers */
29#define MDIO_QUAKE_LED0_REG (0xD006) 33#define MDIO_QUAKE_LED0_REG (0xD006)
@@ -35,6 +39,10 @@ void xfp_set_led(struct efx_nic *p, int led, int mode)
35 mode); 39 mode);
36} 40}
37 41
42struct xfp_phy_data {
43 int tx_disabled;
44};
45
38#define XFP_MAX_RESET_TIME 500 46#define XFP_MAX_RESET_TIME 500
39#define XFP_RESET_WAIT 10 47#define XFP_RESET_WAIT 10
40 48
@@ -72,18 +80,31 @@ static int xfp_reset_phy(struct efx_nic *efx)
72 80
73static int xfp_phy_init(struct efx_nic *efx) 81static int xfp_phy_init(struct efx_nic *efx)
74{ 82{
83 struct xfp_phy_data *phy_data;
75 u32 devid = mdio_clause45_read_id(efx, MDIO_MMD_PHYXS); 84 u32 devid = mdio_clause45_read_id(efx, MDIO_MMD_PHYXS);
76 int rc; 85 int rc;
77 86
87 phy_data = kzalloc(sizeof(struct xfp_phy_data), GFP_KERNEL);
88 efx->phy_data = (void *) phy_data;
89
78 EFX_INFO(efx, "XFP: PHY ID reg %x (OUI %x model %x revision" 90 EFX_INFO(efx, "XFP: PHY ID reg %x (OUI %x model %x revision"
79 " %x)\n", devid, MDIO_ID_OUI(devid), MDIO_ID_MODEL(devid), 91 " %x)\n", devid, MDIO_ID_OUI(devid), MDIO_ID_MODEL(devid),
80 MDIO_ID_REV(devid)); 92 MDIO_ID_REV(devid));
81 93
94 phy_data->tx_disabled = efx->tx_disabled;
95
82 rc = xfp_reset_phy(efx); 96 rc = xfp_reset_phy(efx);
83 97
84 EFX_INFO(efx, "XFP: PHY init %s.\n", 98 EFX_INFO(efx, "XFP: PHY init %s.\n",
85 rc ? "failed" : "successful"); 99 rc ? "failed" : "successful");
100 if (rc < 0)
101 goto fail;
86 102
103 return 0;
104
105 fail:
106 kfree(efx->phy_data);
107 efx->phy_data = NULL;
87 return rc; 108 return rc;
88} 109}
89 110
@@ -110,6 +131,16 @@ static int xfp_phy_check_hw(struct efx_nic *efx)
110 131
111static void xfp_phy_reconfigure(struct efx_nic *efx) 132static void xfp_phy_reconfigure(struct efx_nic *efx)
112{ 133{
134 struct xfp_phy_data *phy_data = efx->phy_data;
135
136 /* Reset the PHY when moving from tx off to tx on */
137 if (phy_data->tx_disabled && !efx->tx_disabled)
138 xfp_reset_phy(efx);
139
140 mdio_clause45_transmit_disable(efx);
141 mdio_clause45_phy_reconfigure(efx);
142
143 phy_data->tx_disabled = efx->tx_disabled;
113 efx->link_up = xfp_link_ok(efx); 144 efx->link_up = xfp_link_ok(efx);
114 efx->link_options = GM_LPA_10000FULL; 145 efx->link_options = GM_LPA_10000FULL;
115} 146}
@@ -119,6 +150,10 @@ static void xfp_phy_fini(struct efx_nic *efx)
119{ 150{
120 /* Clobber the LED if it was blinking */ 151 /* Clobber the LED if it was blinking */
121 efx->board_info.blink(efx, 0); 152 efx->board_info.blink(efx, 0);
153
154 /* Free the context block */
155 kfree(efx->phy_data);
156 efx->phy_data = NULL;
122} 157}
123 158
124struct efx_phy_operations falcon_xfp_phy_ops = { 159struct efx_phy_operations falcon_xfp_phy_ops = {
@@ -129,4 +164,5 @@ struct efx_phy_operations falcon_xfp_phy_ops = {
129 .clear_interrupt = xfp_phy_clear_interrupt, 164 .clear_interrupt = xfp_phy_clear_interrupt,
130 .reset_xaui = efx_port_dummy_op_void, 165 .reset_xaui = efx_port_dummy_op_void,
131 .mmds = XFP_REQUIRED_DEVS, 166 .mmds = XFP_REQUIRED_DEVS,
167 .loopbacks = XFP_LOOPBACKS,
132}; 168};