Commit c0212fb1 authored by David S. Miller's avatar David S. Miller
parents bfac3693 fcfa0604
...@@ -328,7 +328,8 @@ static int efx_poll(struct napi_struct *napi, int budget) ...@@ -328,7 +328,8 @@ static int efx_poll(struct napi_struct *napi, int budget)
* processing to finish, then directly poll (and ack ) the eventq. * processing to finish, then directly poll (and ack ) the eventq.
* Finally reenable NAPI and interrupts. * Finally reenable NAPI and interrupts.
* *
* Since we are touching interrupts the caller should hold the suspend lock * This is for use only during a loopback self-test. It must not
* deliver any packets up the stack as this can result in deadlock.
*/ */
void efx_process_channel_now(struct efx_channel *channel) void efx_process_channel_now(struct efx_channel *channel)
{ {
...@@ -336,6 +337,7 @@ void efx_process_channel_now(struct efx_channel *channel) ...@@ -336,6 +337,7 @@ void efx_process_channel_now(struct efx_channel *channel)
BUG_ON(channel->channel >= efx->n_channels); BUG_ON(channel->channel >= efx->n_channels);
BUG_ON(!channel->enabled); BUG_ON(!channel->enabled);
BUG_ON(!efx->loopback_selftest);
/* Disable interrupts and wait for ISRs to complete */ /* Disable interrupts and wait for ISRs to complete */
efx_nic_disable_interrupts(efx); efx_nic_disable_interrupts(efx);
...@@ -1436,7 +1438,7 @@ static void efx_start_all(struct efx_nic *efx) ...@@ -1436,7 +1438,7 @@ static void efx_start_all(struct efx_nic *efx)
* restart the transmit interface early so the watchdog timer stops */ * restart the transmit interface early so the watchdog timer stops */
efx_start_port(efx); efx_start_port(efx);
if (efx_dev_registered(efx)) if (efx_dev_registered(efx) && !efx->port_inhibited)
netif_tx_wake_all_queues(efx->net_dev); netif_tx_wake_all_queues(efx->net_dev);
efx_for_each_channel(channel, efx) efx_for_each_channel(channel, efx)
......
...@@ -152,6 +152,7 @@ static inline void efx_reado(struct efx_nic *efx, efx_oword_t *value, ...@@ -152,6 +152,7 @@ static inline void efx_reado(struct efx_nic *efx, efx_oword_t *value,
spin_lock_irqsave(&efx->biu_lock, flags); spin_lock_irqsave(&efx->biu_lock, flags);
value->u32[0] = _efx_readd(efx, reg + 0); value->u32[0] = _efx_readd(efx, reg + 0);
rmb();
value->u32[1] = _efx_readd(efx, reg + 4); value->u32[1] = _efx_readd(efx, reg + 4);
value->u32[2] = _efx_readd(efx, reg + 8); value->u32[2] = _efx_readd(efx, reg + 8);
value->u32[3] = _efx_readd(efx, reg + 12); value->u32[3] = _efx_readd(efx, reg + 12);
...@@ -174,6 +175,7 @@ static inline void efx_sram_readq(struct efx_nic *efx, void __iomem *membase, ...@@ -174,6 +175,7 @@ static inline void efx_sram_readq(struct efx_nic *efx, void __iomem *membase,
value->u64[0] = (__force __le64)__raw_readq(membase + addr); value->u64[0] = (__force __le64)__raw_readq(membase + addr);
#else #else
value->u32[0] = (__force __le32)__raw_readl(membase + addr); value->u32[0] = (__force __le32)__raw_readl(membase + addr);
rmb();
value->u32[1] = (__force __le32)__raw_readl(membase + addr + 4); value->u32[1] = (__force __le32)__raw_readl(membase + addr + 4);
#endif #endif
spin_unlock_irqrestore(&efx->biu_lock, flags); spin_unlock_irqrestore(&efx->biu_lock, flags);
......
...@@ -330,7 +330,6 @@ enum efx_rx_alloc_method { ...@@ -330,7 +330,6 @@ enum efx_rx_alloc_method {
* @eventq_mask: Event queue pointer mask * @eventq_mask: Event queue pointer mask
* @eventq_read_ptr: Event queue read pointer * @eventq_read_ptr: Event queue read pointer
* @last_eventq_read_ptr: Last event queue read pointer value. * @last_eventq_read_ptr: Last event queue read pointer value.
* @magic_count: Event queue test event count
* @irq_count: Number of IRQs since last adaptive moderation decision * @irq_count: Number of IRQs since last adaptive moderation decision
* @irq_mod_score: IRQ moderation score * @irq_mod_score: IRQ moderation score
* @rx_alloc_level: Watermark based heuristic counter for pushing descriptors * @rx_alloc_level: Watermark based heuristic counter for pushing descriptors
...@@ -360,7 +359,6 @@ struct efx_channel { ...@@ -360,7 +359,6 @@ struct efx_channel {
unsigned int eventq_mask; unsigned int eventq_mask;
unsigned int eventq_read_ptr; unsigned int eventq_read_ptr;
unsigned int last_eventq_read_ptr; unsigned int last_eventq_read_ptr;
unsigned int magic_count;
unsigned int irq_count; unsigned int irq_count;
unsigned int irq_mod_score; unsigned int irq_mod_score;
......
...@@ -84,7 +84,8 @@ static inline void efx_write_buf_tbl(struct efx_nic *efx, efx_qword_t *value, ...@@ -84,7 +84,8 @@ static inline void efx_write_buf_tbl(struct efx_nic *efx, efx_qword_t *value,
static inline efx_qword_t *efx_event(struct efx_channel *channel, static inline efx_qword_t *efx_event(struct efx_channel *channel,
unsigned int index) unsigned int index)
{ {
return ((efx_qword_t *) (channel->eventq.addr)) + index; return ((efx_qword_t *) (channel->eventq.addr)) +
(index & channel->eventq_mask);
} }
/* See if an event is present /* See if an event is present
...@@ -673,7 +674,8 @@ void efx_nic_eventq_read_ack(struct efx_channel *channel) ...@@ -673,7 +674,8 @@ void efx_nic_eventq_read_ack(struct efx_channel *channel)
efx_dword_t reg; efx_dword_t reg;
struct efx_nic *efx = channel->efx; struct efx_nic *efx = channel->efx;
EFX_POPULATE_DWORD_1(reg, FRF_AZ_EVQ_RPTR, channel->eventq_read_ptr); EFX_POPULATE_DWORD_1(reg, FRF_AZ_EVQ_RPTR,
channel->eventq_read_ptr & channel->eventq_mask);
efx_writed_table(efx, &reg, efx->type->evq_rptr_tbl_base, efx_writed_table(efx, &reg, efx->type->evq_rptr_tbl_base,
channel->channel); channel->channel);
} }
...@@ -908,7 +910,7 @@ efx_handle_generated_event(struct efx_channel *channel, efx_qword_t *event) ...@@ -908,7 +910,7 @@ efx_handle_generated_event(struct efx_channel *channel, efx_qword_t *event)
code = EFX_QWORD_FIELD(*event, FSF_AZ_DRV_GEN_EV_MAGIC); code = EFX_QWORD_FIELD(*event, FSF_AZ_DRV_GEN_EV_MAGIC);
if (code == EFX_CHANNEL_MAGIC_TEST(channel)) if (code == EFX_CHANNEL_MAGIC_TEST(channel))
++channel->magic_count; ; /* ignore */
else if (code == EFX_CHANNEL_MAGIC_FILL(channel)) else if (code == EFX_CHANNEL_MAGIC_FILL(channel))
/* The queue must be empty, so we won't receive any rx /* The queue must be empty, so we won't receive any rx
* events, so efx_process_channel() won't refill the * events, so efx_process_channel() won't refill the
...@@ -1015,8 +1017,7 @@ int efx_nic_process_eventq(struct efx_channel *channel, int budget) ...@@ -1015,8 +1017,7 @@ int efx_nic_process_eventq(struct efx_channel *channel, int budget)
/* Clear this event by marking it all ones */ /* Clear this event by marking it all ones */
EFX_SET_QWORD(*p_event); EFX_SET_QWORD(*p_event);
/* Increment read pointer */ ++read_ptr;
read_ptr = (read_ptr + 1) & channel->eventq_mask;
ev_code = EFX_QWORD_FIELD(event, FSF_AZ_EV_CODE); ev_code = EFX_QWORD_FIELD(event, FSF_AZ_EV_CODE);
...@@ -1060,6 +1061,13 @@ int efx_nic_process_eventq(struct efx_channel *channel, int budget) ...@@ -1060,6 +1061,13 @@ int efx_nic_process_eventq(struct efx_channel *channel, int budget)
return spent; return spent;
} }
/* Check whether an event is present in the eventq at the current
* read pointer. Only useful for self-test.
*/
bool efx_nic_event_present(struct efx_channel *channel)
{
return efx_event_present(efx_event(channel, channel->eventq_read_ptr));
}
/* Allocate buffer table entries for event queue */ /* Allocate buffer table entries for event queue */
int efx_nic_probe_eventq(struct efx_channel *channel) int efx_nic_probe_eventq(struct efx_channel *channel)
...@@ -1165,7 +1173,7 @@ static void efx_poll_flush_events(struct efx_nic *efx) ...@@ -1165,7 +1173,7 @@ static void efx_poll_flush_events(struct efx_nic *efx)
struct efx_tx_queue *tx_queue; struct efx_tx_queue *tx_queue;
struct efx_rx_queue *rx_queue; struct efx_rx_queue *rx_queue;
unsigned int read_ptr = channel->eventq_read_ptr; unsigned int read_ptr = channel->eventq_read_ptr;
unsigned int end_ptr = (read_ptr - 1) & channel->eventq_mask; unsigned int end_ptr = read_ptr + channel->eventq_mask - 1;
do { do {
efx_qword_t *event = efx_event(channel, read_ptr); efx_qword_t *event = efx_event(channel, read_ptr);
...@@ -1205,7 +1213,7 @@ static void efx_poll_flush_events(struct efx_nic *efx) ...@@ -1205,7 +1213,7 @@ static void efx_poll_flush_events(struct efx_nic *efx)
* it's ok to throw away every non-flush event */ * it's ok to throw away every non-flush event */
EFX_SET_QWORD(*event); EFX_SET_QWORD(*event);
read_ptr = (read_ptr + 1) & channel->eventq_mask; ++read_ptr;
} while (read_ptr != end_ptr); } while (read_ptr != end_ptr);
channel->eventq_read_ptr = read_ptr; channel->eventq_read_ptr = read_ptr;
......
...@@ -184,6 +184,7 @@ extern void efx_nic_fini_eventq(struct efx_channel *channel); ...@@ -184,6 +184,7 @@ extern void efx_nic_fini_eventq(struct efx_channel *channel);
extern void efx_nic_remove_eventq(struct efx_channel *channel); extern void efx_nic_remove_eventq(struct efx_channel *channel);
extern int efx_nic_process_eventq(struct efx_channel *channel, int rx_quota); extern int efx_nic_process_eventq(struct efx_channel *channel, int rx_quota);
extern void efx_nic_eventq_read_ack(struct efx_channel *channel); extern void efx_nic_eventq_read_ack(struct efx_channel *channel);
extern bool efx_nic_event_present(struct efx_channel *channel);
/* MAC/PHY */ /* MAC/PHY */
extern void falcon_drain_tx_fifo(struct efx_nic *efx); extern void falcon_drain_tx_fifo(struct efx_nic *efx);
......
...@@ -131,8 +131,6 @@ static int efx_test_chip(struct efx_nic *efx, struct efx_self_tests *tests) ...@@ -131,8 +131,6 @@ static int efx_test_chip(struct efx_nic *efx, struct efx_self_tests *tests)
static int efx_test_interrupts(struct efx_nic *efx, static int efx_test_interrupts(struct efx_nic *efx,
struct efx_self_tests *tests) struct efx_self_tests *tests)
{ {
struct efx_channel *channel;
netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n"); netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n");
tests->interrupt = -1; tests->interrupt = -1;
...@@ -140,15 +138,6 @@ static int efx_test_interrupts(struct efx_nic *efx, ...@@ -140,15 +138,6 @@ static int efx_test_interrupts(struct efx_nic *efx,
efx->last_irq_cpu = -1; efx->last_irq_cpu = -1;
smp_wmb(); smp_wmb();
/* ACK each interrupting event queue. Receiving an interrupt due to
* traffic before a test event is raised is considered a pass */
efx_for_each_channel(channel, efx) {
if (channel->work_pending)
efx_process_channel_now(channel);
if (efx->last_irq_cpu >= 0)
goto success;
}
efx_nic_generate_interrupt(efx); efx_nic_generate_interrupt(efx);
/* Wait for arrival of test interrupt. */ /* Wait for arrival of test interrupt. */
...@@ -173,13 +162,13 @@ static int efx_test_eventq_irq(struct efx_channel *channel, ...@@ -173,13 +162,13 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
struct efx_self_tests *tests) struct efx_self_tests *tests)
{ {
struct efx_nic *efx = channel->efx; struct efx_nic *efx = channel->efx;
unsigned int magic_count, count; unsigned int read_ptr, count;
tests->eventq_dma[channel->channel] = -1; tests->eventq_dma[channel->channel] = -1;
tests->eventq_int[channel->channel] = -1; tests->eventq_int[channel->channel] = -1;
tests->eventq_poll[channel->channel] = -1; tests->eventq_poll[channel->channel] = -1;
magic_count = channel->magic_count; read_ptr = channel->eventq_read_ptr;
channel->efx->last_irq_cpu = -1; channel->efx->last_irq_cpu = -1;
smp_wmb(); smp_wmb();
...@@ -190,10 +179,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel, ...@@ -190,10 +179,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
do { do {
schedule_timeout_uninterruptible(HZ / 100); schedule_timeout_uninterruptible(HZ / 100);
if (channel->work_pending) if (ACCESS_ONCE(channel->eventq_read_ptr) != read_ptr)
efx_process_channel_now(channel);
if (channel->magic_count != magic_count)
goto eventq_ok; goto eventq_ok;
} while (++count < 2); } while (++count < 2);
...@@ -211,8 +197,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel, ...@@ -211,8 +197,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
} }
/* Check to see if event was received even if interrupt wasn't */ /* Check to see if event was received even if interrupt wasn't */
efx_process_channel_now(channel); if (efx_nic_event_present(channel)) {
if (channel->magic_count != magic_count) {
netif_err(efx, drv, efx->net_dev, netif_err(efx, drv, efx->net_dev,
"channel %d event was generated, but " "channel %d event was generated, but "
"failed to trigger an interrupt\n", channel->channel); "failed to trigger an interrupt\n", channel->channel);
...@@ -770,6 +755,8 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, ...@@ -770,6 +755,8 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
__efx_reconfigure_port(efx); __efx_reconfigure_port(efx);
mutex_unlock(&efx->mac_lock); mutex_unlock(&efx->mac_lock);
netif_tx_wake_all_queues(efx->net_dev);
return rc_test; return rc_test;
} }
...@@ -435,7 +435,8 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index) ...@@ -435,7 +435,8 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
* queue state. */ * queue state. */
smp_mb(); smp_mb();
if (unlikely(netif_tx_queue_stopped(tx_queue->core_txq)) && if (unlikely(netif_tx_queue_stopped(tx_queue->core_txq)) &&
likely(efx->port_enabled)) { likely(efx->port_enabled) &&
likely(!efx->port_inhibited)) {
fill_level = tx_queue->insert_count - tx_queue->read_count; fill_level = tx_queue->insert_count - tx_queue->read_count;
if (fill_level < EFX_TXQ_THRESHOLD(efx)) { if (fill_level < EFX_TXQ_THRESHOLD(efx)) {
EFX_BUG_ON_PARANOID(!efx_dev_registered(efx)); EFX_BUG_ON_PARANOID(!efx_dev_registered(efx));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment