From patchwork Fri Jan 27 20:48:37 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Hutchings X-Patchwork-Id: 138307 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 21C35B6F68 for ; Sat, 28 Jan 2012 07:48:44 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753935Ab2A0Usm (ORCPT ); Fri, 27 Jan 2012 15:48:42 -0500 Received: from exchange.solarflare.com ([216.237.3.220]:63696 "EHLO ocex02.SolarFlarecom.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1752836Ab2A0Usl (ORCPT ); Fri, 27 Jan 2012 15:48:41 -0500 Received: from [10.17.20.137] (10.17.20.137) by ocex02.SolarFlarecom.com (10.20.40.31) with Microsoft SMTP Server (TLS) id 14.1.355.2; Fri, 27 Jan 2012 12:48:40 -0800 Message-ID: <1327697317.2503.26.camel@bwh-desktop> Subject: [PATCH net-next 19/32] sfc: Remove dependence on NAPI polling in efx_test_eventq_irq() From: Ben Hutchings To: David Miller CC: , Date: Fri, 27 Jan 2012 20:48:37 +0000 In-Reply-To: <1327696858.2503.7.camel@bwh-desktop> References: <1327696858.2503.7.camel@bwh-desktop> Organization: Solarflare Communications X-Mailer: Evolution 3.2.2 (3.2.2-1.fc16) MIME-Version: 1.0 X-Originating-IP: [10.17.20.137] X-TM-AS-Product-Ver: SMEX-10.0.0.1412-6.800.1017-18670.006 X-TM-AS-Result: No--12.139800-0.000000-31 X-TM-AS-User-Approved-Sender: Yes X-TM-AS-User-Blocked-Sender: No Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org We cannot safely assume that the NAPI handler will complete within the 20 ms that we allow for the event self-test. The handler may be deferred for longer than this, particularly on realtime kernels. Instead, check whether either an event has been handled or (as in the old failure path) whether an interrupt has been received and an event has been delivered but not yet handled. Use napi_disable() to synchronize with the NAPI handler before checking, since it will clear events before updating eventq_read_ptr. Remove the test result chan.N.eventq.poll, since it is not an error if the NAPI handler does not run during the test. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ethtool.c | 4 -- drivers/net/ethernet/sfc/selftest.c | 79 ++++++++++++++++++----------------- drivers/net/ethernet/sfc/selftest.h | 1 - 3 files changed, 40 insertions(+), 44 deletions(-) diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index 1a7f7ba..ba90116 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -404,10 +404,6 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, &tests->eventq_int[channel->channel], EFX_CHANNEL_NAME(channel), "eventq.int", NULL); - efx_fill_test(n++, strings, data, - &tests->eventq_poll[channel->channel], - EFX_CHANNEL_NAME(channel), - "eventq.poll", NULL); } efx_fill_test(n++, strings, data, &tests->registers, diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c index 7718287..0f84789 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c @@ -161,11 +161,8 @@ static int efx_test_eventq_irq(struct efx_channel *channel, struct efx_self_tests *tests) { struct efx_nic *efx = channel->efx; - unsigned int read_ptr, count; - - tests->eventq_dma[channel->channel] = -1; - tests->eventq_int[channel->channel] = -1; - tests->eventq_poll[channel->channel] = -1; + unsigned int read_ptr; + bool napi_ran, dma_seen, int_seen; read_ptr = channel->eventq_read_ptr; channel->efx->last_irq_cpu = -1; @@ -173,44 +170,48 @@ static int efx_test_eventq_irq(struct efx_channel *channel, efx_nic_generate_test_event(channel); - /* Wait for arrival of interrupt */ - count = 0; - do { - schedule_timeout_uninterruptible(HZ / 100); - - if (ACCESS_ONCE(channel->eventq_read_ptr) != read_ptr) - goto eventq_ok; - } while (++count < 2); - - netif_err(efx, drv, efx->net_dev, - "channel %d timed out waiting for event queue\n", - channel->channel); - - /* See if interrupt arrived */ - if (channel->efx->last_irq_cpu >= 0) { - netif_err(efx, drv, efx->net_dev, - "channel %d saw interrupt on CPU%d " - "during event queue test\n", channel->channel, - raw_smp_processor_id()); - tests->eventq_int[channel->channel] = 1; + /* Wait for arrival of interrupt. NAPI processing may or may + * not complete in time, but we can cope in any case. + */ + msleep(10); + napi_disable(&channel->napi_str); + if (channel->eventq_read_ptr != read_ptr) { + napi_ran = true; + dma_seen = true; + int_seen = true; + } else { + napi_ran = false; + dma_seen = efx_nic_event_present(channel); + int_seen = efx->last_irq_cpu >= 0; } + napi_enable(&channel->napi_str); + efx_nic_eventq_read_ack(channel); + + tests->eventq_dma[channel->channel] = dma_seen ? 1 : -1; + tests->eventq_int[channel->channel] = int_seen ? 1 : -1; - /* Check to see if event was received even if interrupt wasn't */ - if (efx_nic_event_present(channel)) { + if (dma_seen && int_seen) { + netif_dbg(efx, drv, efx->net_dev, + "channel %d event queue passed (with%s NAPI)\n", + channel->channel, napi_ran ? "" : "out"); + return 0; + } else { + /* Report failure and whether either interrupt or DMA worked */ netif_err(efx, drv, efx->net_dev, - "channel %d event was generated, but " - "failed to trigger an interrupt\n", channel->channel); - tests->eventq_dma[channel->channel] = 1; + "channel %d timed out waiting for event queue\n", + channel->channel); + if (int_seen) + netif_err(efx, drv, efx->net_dev, + "channel %d saw interrupt " + "during event queue test\n", + channel->channel); + if (dma_seen) + netif_err(efx, drv, efx->net_dev, + "channel %d event was generated, but " + "failed to trigger an interrupt\n", + channel->channel); + return -ETIMEDOUT; } - - return -ETIMEDOUT; - eventq_ok: - netif_dbg(efx, drv, efx->net_dev, "channel %d event queue passed\n", - channel->channel); - tests->eventq_dma[channel->channel] = 1; - tests->eventq_int[channel->channel] = 1; - tests->eventq_poll[channel->channel] = 1; - return 0; } static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests, diff --git a/drivers/net/ethernet/sfc/selftest.h b/drivers/net/ethernet/sfc/selftest.h index dba5456..87abe2a 100644 --- a/drivers/net/ethernet/sfc/selftest.h +++ b/drivers/net/ethernet/sfc/selftest.h @@ -37,7 +37,6 @@ struct efx_self_tests { int interrupt; int eventq_dma[EFX_MAX_CHANNELS]; int eventq_int[EFX_MAX_CHANNELS]; - int eventq_poll[EFX_MAX_CHANNELS]; /* offline tests */ int registers; int phy_ext[EFX_MAX_PHY_TESTS];