diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/net/sfc/selftest.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/net/sfc/selftest.c')
-rw-r--r-- | drivers/net/sfc/selftest.c | 55 |
1 files changed, 26 insertions, 29 deletions
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c index 85f015f005d5..822f6c2a6a7c 100644 --- a/drivers/net/sfc/selftest.c +++ b/drivers/net/sfc/selftest.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /**************************************************************************** | 1 | /**************************************************************************** |
2 | * Driver for Solarflare Solarstorm network controllers and boards | 2 | * Driver for Solarflare Solarstorm network controllers and boards |
3 | * Copyright 2005-2006 Fen Systems Ltd. | 3 | * Copyright 2005-2006 Fen Systems Ltd. |
4 | * Copyright 2006-2009 Solarflare Communications Inc. | 4 | * Copyright 2006-2010 Solarflare Communications Inc. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 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 | 7 | * under the terms of the GNU General Public License version 2 as published |
@@ -48,6 +48,16 @@ static const unsigned char payload_source[ETH_ALEN] = { | |||
48 | static const char payload_msg[] = | 48 | static const char payload_msg[] = |
49 | "Hello world! This is an Efx loopback test in progress!"; | 49 | "Hello world! This is an Efx loopback test in progress!"; |
50 | 50 | ||
51 | /* Interrupt mode names */ | ||
52 | static const unsigned int efx_interrupt_mode_max = EFX_INT_MODE_MAX; | ||
53 | static const char *efx_interrupt_mode_names[] = { | ||
54 | [EFX_INT_MODE_MSIX] = "MSI-X", | ||
55 | [EFX_INT_MODE_MSI] = "MSI", | ||
56 | [EFX_INT_MODE_LEGACY] = "legacy", | ||
57 | }; | ||
58 | #define INT_MODE(efx) \ | ||
59 | STRING_TABLE_LOOKUP(efx->interrupt_mode, efx_interrupt_mode) | ||
60 | |||
51 | /** | 61 | /** |
52 | * efx_loopback_state - persistent state during a loopback selftest | 62 | * efx_loopback_state - persistent state during a loopback selftest |
53 | * @flush: Drop all packets in efx_loopback_rx_packet | 63 | * @flush: Drop all packets in efx_loopback_rx_packet |
@@ -121,8 +131,6 @@ static int efx_test_chip(struct efx_nic *efx, struct efx_self_tests *tests) | |||
121 | static int efx_test_interrupts(struct efx_nic *efx, | 131 | static int efx_test_interrupts(struct efx_nic *efx, |
122 | struct efx_self_tests *tests) | 132 | struct efx_self_tests *tests) |
123 | { | 133 | { |
124 | struct efx_channel *channel; | ||
125 | |||
126 | netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n"); | 134 | netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n"); |
127 | tests->interrupt = -1; | 135 | tests->interrupt = -1; |
128 | 136 | ||
@@ -130,15 +138,6 @@ static int efx_test_interrupts(struct efx_nic *efx, | |||
130 | efx->last_irq_cpu = -1; | 138 | efx->last_irq_cpu = -1; |
131 | smp_wmb(); | 139 | smp_wmb(); |
132 | 140 | ||
133 | /* ACK each interrupting event queue. Receiving an interrupt due to | ||
134 | * traffic before a test event is raised is considered a pass */ | ||
135 | efx_for_each_channel(channel, efx) { | ||
136 | if (channel->work_pending) | ||
137 | efx_process_channel_now(channel); | ||
138 | if (efx->last_irq_cpu >= 0) | ||
139 | goto success; | ||
140 | } | ||
141 | |||
142 | efx_nic_generate_interrupt(efx); | 141 | efx_nic_generate_interrupt(efx); |
143 | 142 | ||
144 | /* Wait for arrival of test interrupt. */ | 143 | /* Wait for arrival of test interrupt. */ |
@@ -163,13 +162,13 @@ static int efx_test_eventq_irq(struct efx_channel *channel, | |||
163 | struct efx_self_tests *tests) | 162 | struct efx_self_tests *tests) |
164 | { | 163 | { |
165 | struct efx_nic *efx = channel->efx; | 164 | struct efx_nic *efx = channel->efx; |
166 | unsigned int magic_count, count; | 165 | unsigned int read_ptr, count; |
167 | 166 | ||
168 | tests->eventq_dma[channel->channel] = -1; | 167 | tests->eventq_dma[channel->channel] = -1; |
169 | tests->eventq_int[channel->channel] = -1; | 168 | tests->eventq_int[channel->channel] = -1; |
170 | tests->eventq_poll[channel->channel] = -1; | 169 | tests->eventq_poll[channel->channel] = -1; |
171 | 170 | ||
172 | magic_count = channel->magic_count; | 171 | read_ptr = channel->eventq_read_ptr; |
173 | channel->efx->last_irq_cpu = -1; | 172 | channel->efx->last_irq_cpu = -1; |
174 | smp_wmb(); | 173 | smp_wmb(); |
175 | 174 | ||
@@ -180,10 +179,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel, | |||
180 | do { | 179 | do { |
181 | schedule_timeout_uninterruptible(HZ / 100); | 180 | schedule_timeout_uninterruptible(HZ / 100); |
182 | 181 | ||
183 | if (channel->work_pending) | 182 | if (ACCESS_ONCE(channel->eventq_read_ptr) != read_ptr) |
184 | efx_process_channel_now(channel); | ||
185 | |||
186 | if (channel->magic_count != magic_count) | ||
187 | goto eventq_ok; | 183 | goto eventq_ok; |
188 | } while (++count < 2); | 184 | } while (++count < 2); |
189 | 185 | ||
@@ -201,8 +197,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel, | |||
201 | } | 197 | } |
202 | 198 | ||
203 | /* Check to see if event was received even if interrupt wasn't */ | 199 | /* Check to see if event was received even if interrupt wasn't */ |
204 | efx_process_channel_now(channel); | 200 | if (efx_nic_event_present(channel)) { |
205 | if (channel->magic_count != magic_count) { | ||
206 | netif_err(efx, drv, efx->net_dev, | 201 | netif_err(efx, drv, efx->net_dev, |
207 | "channel %d event was generated, but " | 202 | "channel %d event was generated, but " |
208 | "failed to trigger an interrupt\n", channel->channel); | 203 | "failed to trigger an interrupt\n", channel->channel); |
@@ -506,7 +501,7 @@ efx_test_loopback(struct efx_tx_queue *tx_queue, | |||
506 | 501 | ||
507 | for (i = 0; i < 3; i++) { | 502 | for (i = 0; i < 3; i++) { |
508 | /* Determine how many packets to send */ | 503 | /* Determine how many packets to send */ |
509 | state->packet_count = EFX_TXQ_SIZE / 3; | 504 | state->packet_count = efx->txq_entries / 3; |
510 | state->packet_count = min(1 << (i << 2), state->packet_count); | 505 | state->packet_count = min(1 << (i << 2), state->packet_count); |
511 | state->skbs = kzalloc(sizeof(state->skbs[0]) * | 506 | state->skbs = kzalloc(sizeof(state->skbs[0]) * |
512 | state->packet_count, GFP_KERNEL); | 507 | state->packet_count, GFP_KERNEL); |
@@ -567,7 +562,7 @@ static int efx_wait_for_link(struct efx_nic *efx) | |||
567 | efx->type->monitor(efx); | 562 | efx->type->monitor(efx); |
568 | mutex_unlock(&efx->mac_lock); | 563 | mutex_unlock(&efx->mac_lock); |
569 | } else { | 564 | } else { |
570 | struct efx_channel *channel = &efx->channel[0]; | 565 | struct efx_channel *channel = efx_get_channel(efx, 0); |
571 | if (channel->work_pending) | 566 | if (channel->work_pending) |
572 | efx_process_channel_now(channel); | 567 | efx_process_channel_now(channel); |
573 | } | 568 | } |
@@ -594,6 +589,7 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests, | |||
594 | { | 589 | { |
595 | enum efx_loopback_mode mode; | 590 | enum efx_loopback_mode mode; |
596 | struct efx_loopback_state *state; | 591 | struct efx_loopback_state *state; |
592 | struct efx_channel *channel = efx_get_channel(efx, 0); | ||
597 | struct efx_tx_queue *tx_queue; | 593 | struct efx_tx_queue *tx_queue; |
598 | int rc = 0; | 594 | int rc = 0; |
599 | 595 | ||
@@ -633,8 +629,8 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests, | |||
633 | goto out; | 629 | goto out; |
634 | } | 630 | } |
635 | 631 | ||
636 | /* Test both types of TX queue */ | 632 | /* Test all enabled types of TX queue */ |
637 | efx_for_each_channel_tx_queue(tx_queue, &efx->channel[0]) { | 633 | efx_for_each_channel_tx_queue(tx_queue, channel) { |
638 | state->offload_csum = (tx_queue->queue & | 634 | state->offload_csum = (tx_queue->queue & |
639 | EFX_TXQ_TYPE_OFFLOAD); | 635 | EFX_TXQ_TYPE_OFFLOAD); |
640 | rc = efx_test_loopback(tx_queue, | 636 | rc = efx_test_loopback(tx_queue, |
@@ -699,12 +695,12 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, | |||
699 | /* Offline (i.e. disruptive) testing | 695 | /* Offline (i.e. disruptive) testing |
700 | * This checks MAC and PHY loopback on the specified port. */ | 696 | * This checks MAC and PHY loopback on the specified port. */ |
701 | 697 | ||
702 | /* force the carrier state off so the kernel doesn't transmit during | 698 | /* Detach the device so the kernel doesn't transmit during the |
703 | * the loopback test, and the watchdog timeout doesn't fire. Also put | 699 | * loopback test and the watchdog timeout doesn't fire. |
704 | * falcon into loopback for the register test. | ||
705 | */ | 700 | */ |
701 | netif_device_detach(efx->net_dev); | ||
702 | |||
706 | mutex_lock(&efx->mac_lock); | 703 | mutex_lock(&efx->mac_lock); |
707 | efx->port_inhibited = true; | ||
708 | if (efx->loopback_modes) { | 704 | if (efx->loopback_modes) { |
709 | /* We need the 312 clock from the PHY to test the XMAC | 705 | /* We need the 312 clock from the PHY to test the XMAC |
710 | * registers, so move into XGMII loopback if available */ | 706 | * registers, so move into XGMII loopback if available */ |
@@ -754,11 +750,12 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, | |||
754 | /* restore the PHY to the previous state */ | 750 | /* restore the PHY to the previous state */ |
755 | mutex_lock(&efx->mac_lock); | 751 | mutex_lock(&efx->mac_lock); |
756 | efx->phy_mode = phy_mode; | 752 | efx->phy_mode = phy_mode; |
757 | efx->port_inhibited = false; | ||
758 | efx->loopback_mode = loopback_mode; | 753 | efx->loopback_mode = loopback_mode; |
759 | __efx_reconfigure_port(efx); | 754 | __efx_reconfigure_port(efx); |
760 | mutex_unlock(&efx->mac_lock); | 755 | mutex_unlock(&efx->mac_lock); |
761 | 756 | ||
757 | netif_device_attach(efx->net_dev); | ||
758 | |||
762 | return rc_test; | 759 | return rc_test; |
763 | } | 760 | } |
764 | 761 | ||