netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* pull request: sfc 2012-03-09
@ 2012-03-10  0:46 Ben Hutchings
  2012-03-10  0:48 ` [PATCH net-next 01/10] sfc: Fix calculation of vf_i in map_vi_index() Ben Hutchings
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Ben Hutchings @ 2012-03-10  0:46 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers

[-- Attachment #1: Type: text/plain, Size: 2200 bytes --]

The following changes since commit ffcb97388b1d41b1db063eb041cb9af408662127:

  Merge branch 'master' of git://gitorious.org/linux-can/linux-can-next (2012-03-04 21:59:39 -0500)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next.git for-davem

(commit 460eeaa03c5c0af32a388337a6e1f0f1acd043ce)

1. Fix a bug in SR-IOV support that I introduced while cleaning it up
prior to upstreaming.
2. Show the part number for all boards at probe time, not just the ones
we have specific code for.
3. Improve self-test reliability, and test interrupts & events
immediately after bringing an interface up.
4. Improve adaptive IRQ moderation.
5. Various cleanup.

Ben.

Ben Hutchings (9):
      sfc: Remove redundant function efx_nic_has_mc()
      sfc: Update comments on efx_rx_packet_gro()
      sfc: Remove TX completions from adaptive IRQ scoring
      sfc: Raise self-test timeouts
      sfc: Test all event queues in parallel
      sfc: Encapsulate access to efx_{channel,nic}::last_irq_cpu in self-test
      sfc: Run event/IRQ self-test asynchronously when interface is brought up
      sfc: Remove efx_channel::last_eventq_read_ptr
      sfc: Log the part number on probe

Robert Stonehouse (1):
      sfc: Fix calculation of vf_i in map_vi_index()

 drivers/net/ethernet/sfc/efx.c           |   63 +++++++++-
 drivers/net/ethernet/sfc/efx.h           |    2 +-
 drivers/net/ethernet/sfc/falcon_boards.c |   13 --
 drivers/net/ethernet/sfc/net_driver.h    |    8 +-
 drivers/net/ethernet/sfc/nic.c           |   11 +-
 drivers/net/ethernet/sfc/nic.h           |   21 ++--
 drivers/net/ethernet/sfc/rx.c            |    7 +-
 drivers/net/ethernet/sfc/selftest.c      |  192 ++++++++++++++++++++---------
 drivers/net/ethernet/sfc/selftest.h      |    3 +
 drivers/net/ethernet/sfc/siena.c         |    3 +-
 drivers/net/ethernet/sfc/siena_sriov.c   |    2 +-
 11 files changed, 222 insertions(+), 103 deletions(-)

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH net-next 01/10] sfc: Fix calculation of vf_i in map_vi_index()
  2012-03-10  0:46 pull request: sfc 2012-03-09 Ben Hutchings
@ 2012-03-10  0:48 ` Ben Hutchings
  2012-03-10  0:49 ` [PATCH net-next 02/10] sfc: Remove redundant function efx_nic_has_mc() Ben Hutchings
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Ben Hutchings @ 2012-03-10  0:48 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers

From: Robert Stonehouse <rstonehouse@solarflare.com>

This was broken during refactoring to use efx_vf_size().

[bwh: Keep using efx_vf_size()]
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 drivers/net/ethernet/sfc/siena_sriov.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ethernet/sfc/siena_sriov.c b/drivers/net/ethernet/sfc/siena_sriov.c
index 80976e8..9cb3b84 100644
--- a/drivers/net/ethernet/sfc/siena_sriov.c
+++ b/drivers/net/ethernet/sfc/siena_sriov.c
@@ -514,7 +514,7 @@ static bool map_vi_index(struct efx_nic *efx, unsigned abs_index,
 
 	if (abs_index < EFX_VI_BASE)
 		return true;
-	vf_i = (abs_index - EFX_VI_BASE) * efx_vf_size(efx);
+	vf_i = (abs_index - EFX_VI_BASE) / efx_vf_size(efx);
 	if (vf_i >= efx->vf_init_count)
 		return true;
 
-- 
1.7.7.6



-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH net-next 02/10] sfc: Remove redundant function efx_nic_has_mc()
  2012-03-10  0:46 pull request: sfc 2012-03-09 Ben Hutchings
  2012-03-10  0:48 ` [PATCH net-next 01/10] sfc: Fix calculation of vf_i in map_vi_index() Ben Hutchings
@ 2012-03-10  0:49 ` Ben Hutchings
  2012-03-10  0:49 ` [PATCH net-next 03/10] sfc: Update comments on efx_rx_packet_gro() Ben Hutchings
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Ben Hutchings @ 2012-03-10  0:49 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers

This function is now used in only one place, where it always returns
true.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 drivers/net/ethernet/sfc/nic.h   |    4 ----
 drivers/net/ethernet/sfc/siena.c |    3 +--
 2 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index 246c414..ac12f7f 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -35,10 +35,6 @@ static inline int efx_nic_rev(struct efx_nic *efx)
 
 extern u32 efx_nic_fpga_ver(struct efx_nic *efx);
 
-static inline bool efx_nic_has_mc(struct efx_nic *efx)
-{
-	return efx_nic_rev(efx) >= EFX_REV_SIENA_A0;
-}
 /* NIC has two interlinked PCI functions for the same port. */
 static inline bool efx_nic_is_dual_func(struct efx_nic *efx)
 {
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index 7bea790..9f8d7ce 100644
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -409,8 +409,7 @@ static void siena_remove_nic(struct efx_nic *efx)
 	siena_reset_hw(efx, RESET_TYPE_ALL);
 
 	/* Relinquish the device back to the BMC */
-	if (efx_nic_has_mc(efx))
-		efx_mcdi_drv_attach(efx, false, NULL);
+	efx_mcdi_drv_attach(efx, false, NULL);
 
 	/* Tear down the private nic state */
 	kfree(efx->nic_data);
-- 
1.7.7.6



-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH net-next 03/10] sfc: Update comments on efx_rx_packet_gro()
  2012-03-10  0:46 pull request: sfc 2012-03-09 Ben Hutchings
  2012-03-10  0:48 ` [PATCH net-next 01/10] sfc: Fix calculation of vf_i in map_vi_index() Ben Hutchings
  2012-03-10  0:49 ` [PATCH net-next 02/10] sfc: Remove redundant function efx_nic_has_mc() Ben Hutchings
@ 2012-03-10  0:49 ` Ben Hutchings
  2012-03-10  0:49 ` [PATCH net-next 04/10] sfc: Remove TX completions from adaptive IRQ scoring Ben Hutchings
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Ben Hutchings @ 2012-03-10  0:49 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers

The in-tree driver has never supported Driverlink.  The rest of the
comments are rather redundant, but we can usefully state what the
requirements are on the buffer state.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 drivers/net/ethernet/sfc/rx.c |    7 ++-----
 1 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index 1ba290d..763fa2f 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -449,10 +449,8 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
 	efx_rx_queue_channel(rx_queue)->n_rx_overlength++;
 }
 
-/* Pass a received packet up through the generic GRO stack
- *
- * Handles driverlink veto, and passes the fragment up via
- * the appropriate GRO method
+/* Pass a received packet up through GRO.  GRO can handle pages
+ * regardless of checksum state and skbs with a good checksum.
  */
 static void efx_rx_packet_gro(struct efx_channel *channel,
 			      struct efx_rx_buffer *rx_buf,
@@ -461,7 +459,6 @@ static void efx_rx_packet_gro(struct efx_channel *channel,
 	struct napi_struct *napi = &channel->napi_str;
 	gro_result_t gro_result;
 
-	/* Pass the skb/page into the GRO engine */
 	if (rx_buf->flags & EFX_RX_BUF_PAGE) {
 		struct efx_nic *efx = channel->efx;
 		struct page *page = rx_buf->u.page;
-- 
1.7.7.6



-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH net-next 04/10] sfc: Remove TX completions from adaptive IRQ scoring
  2012-03-10  0:46 pull request: sfc 2012-03-09 Ben Hutchings
                   ` (2 preceding siblings ...)
  2012-03-10  0:49 ` [PATCH net-next 03/10] sfc: Update comments on efx_rx_packet_gro() Ben Hutchings
@ 2012-03-10  0:49 ` Ben Hutchings
  2012-03-10  0:50 ` [PATCH net-next 05/10] sfc: Raise self-test timeouts Ben Hutchings
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Ben Hutchings @ 2012-03-10  0:49 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers

RX and TX completions on the same event queue are generally not associated
with the same flows.  The inclusion of TX completions in the adaptive IRQ
score is more of a source of noise rather than useful feedback.  Therefore,
do not include them in the score, and adjust the default threshold scores
down.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 drivers/net/ethernet/sfc/efx.c |    4 ++--
 drivers/net/ethernet/sfc/nic.c |    1 -
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 1908ba7..00e13ab 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -163,12 +163,12 @@ static int phy_flash_cfg;
 module_param(phy_flash_cfg, int, 0644);
 MODULE_PARM_DESC(phy_flash_cfg, "Set PHYs into reflash mode initially");
 
-static unsigned irq_adapt_low_thresh = 10000;
+static unsigned irq_adapt_low_thresh = 8000;
 module_param(irq_adapt_low_thresh, uint, 0644);
 MODULE_PARM_DESC(irq_adapt_low_thresh,
 		 "Threshold score for reducing IRQ moderation");
 
-static unsigned irq_adapt_high_thresh = 20000;
+static unsigned irq_adapt_high_thresh = 16000;
 module_param(irq_adapt_high_thresh, uint, 0644);
 MODULE_PARM_DESC(irq_adapt_high_thresh,
 		 "Threshold score for increasing IRQ moderation");
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index 2bf4283..5da8af5 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -822,7 +822,6 @@ efx_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
 			channel, tx_ev_q_label % EFX_TXQ_TYPES);
 		tx_packets = ((tx_ev_desc_ptr - tx_queue->read_count) &
 			      tx_queue->ptr_mask);
-		channel->irq_mod_score += tx_packets;
 		efx_xmit_done(tx_queue, tx_ev_desc_ptr);
 	} else if (EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_WQ_FF_FULL)) {
 		/* Rewrite the FIFO write pointer */
-- 
1.7.7.6



-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH net-next 05/10] sfc: Raise self-test timeouts
  2012-03-10  0:46 pull request: sfc 2012-03-09 Ben Hutchings
                   ` (3 preceding siblings ...)
  2012-03-10  0:49 ` [PATCH net-next 04/10] sfc: Remove TX completions from adaptive IRQ scoring Ben Hutchings
@ 2012-03-10  0:50 ` Ben Hutchings
  2012-03-10  0:50 ` [PATCH net-next 06/10] sfc: Test all event queues in parallel Ben Hutchings
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Ben Hutchings @ 2012-03-10  0:50 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers

IRQ latency can be ridiculously high for various reasons, so our
current timeouts of 100 ms or 10 ms are too short.

Change the IRQ and event tests to use polling loops starting with a
delay of 1 tick and doubling that if necessary up to a maximum total
delay of approximately 1 second.

Raise the loopback packet RX timeout to 1 second.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 drivers/net/ethernet/sfc/selftest.c |   65 ++++++++++++++++++++++++----------
 1 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c
index febe2a9..dc330b9 100644
--- a/drivers/net/ethernet/sfc/selftest.c
+++ b/drivers/net/ethernet/sfc/selftest.c
@@ -25,6 +25,16 @@
 #include "selftest.h"
 #include "workarounds.h"
 
+/* IRQ latency can be enormous because:
+ * - All IRQs may be disabled on a CPU for a *long* time by e.g. a
+ *   slow serial console or an old IDE driver doing error recovery
+ * - The PREEMPT_RT patches mostly deal with this, but also allow a
+ *   tasklet or normal task to be given higher priority than our IRQ
+ *   threads
+ * Try to avoid blaming the hardware for this.
+ */
+#define IRQ_TIMEOUT HZ
+
 /*
  * Loopback test packet structure
  *
@@ -77,6 +87,9 @@ struct efx_loopback_state {
 	struct efx_loopback_payload payload;
 };
 
+/* How long to wait for all the packets to arrive (in ms) */
+#define LOOPBACK_TIMEOUT_MS 1000
+
 /**************************************************************************
  *
  * MII, NVRAM and register tests
@@ -130,6 +143,7 @@ static int efx_test_chip(struct efx_nic *efx, struct efx_self_tests *tests)
 static int efx_test_interrupts(struct efx_nic *efx,
 			       struct efx_self_tests *tests)
 {
+	unsigned long timeout, wait;
 	int cpu;
 
 	netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n");
@@ -140,13 +154,18 @@ static int efx_test_interrupts(struct efx_nic *efx,
 	smp_wmb();
 
 	efx_nic_generate_interrupt(efx);
+	timeout = jiffies + IRQ_TIMEOUT;
+	wait = 1;
 
 	/* Wait for arrival of test interrupt. */
 	netif_dbg(efx, drv, efx->net_dev, "waiting for test interrupt\n");
-	schedule_timeout_uninterruptible(HZ / 10);
-	cpu = ACCESS_ONCE(efx->last_irq_cpu);
-	if (cpu >= 0)
-		goto success;
+	do {
+		schedule_timeout_uninterruptible(wait);
+		cpu = ACCESS_ONCE(efx->last_irq_cpu);
+		if (cpu >= 0)
+			goto success;
+		wait *= 2;
+	} while (time_before(jiffies, timeout));
 
 	netif_err(efx, drv, efx->net_dev, "timed out waiting for interrupt\n");
 	return -ETIMEDOUT;
@@ -165,29 +184,37 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
 	struct efx_nic *efx = channel->efx;
 	unsigned int read_ptr;
 	bool napi_ran, dma_seen, int_seen;
+	unsigned long timeout, wait;
 
 	read_ptr = channel->eventq_read_ptr;
 	channel->last_irq_cpu = -1;
 	smp_wmb();
 
 	efx_nic_generate_test_event(channel);
+	timeout = jiffies + IRQ_TIMEOUT;
+	wait = 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 = ACCESS_ONCE(channel->last_irq_cpu) >= 0;
-	}
-	napi_enable(&channel->napi_str);
-	efx_nic_eventq_read_ack(channel);
+	do {
+		schedule_timeout_uninterruptible(wait);
+
+		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 = ACCESS_ONCE(channel->last_irq_cpu) >= 0;
+		}
+		napi_enable(&channel->napi_str);
+		efx_nic_eventq_read_ack(channel);
+
+		wait *= 2;
+	} while (!(dma_seen && int_seen) && time_before(jiffies, timeout));
 
 	tests->eventq_dma[channel->channel] = dma_seen ? 1 : -1;
 	tests->eventq_int[channel->channel] = int_seen ? 1 : -1;
@@ -516,10 +543,10 @@ efx_test_loopback(struct efx_tx_queue *tx_queue,
 		begin_rc = efx_begin_loopback(tx_queue);
 
 		/* This will normally complete very quickly, but be
-		 * prepared to wait up to 100 ms. */
+		 * prepared to wait much longer. */
 		msleep(1);
 		if (!efx_poll_loopback(efx)) {
-			msleep(100);
+			msleep(LOOPBACK_TIMEOUT_MS);
 			efx_poll_loopback(efx);
 		}
 
-- 
1.7.7.6



-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH net-next 06/10] sfc: Test all event queues in parallel
  2012-03-10  0:46 pull request: sfc 2012-03-09 Ben Hutchings
                   ` (4 preceding siblings ...)
  2012-03-10  0:50 ` [PATCH net-next 05/10] sfc: Raise self-test timeouts Ben Hutchings
@ 2012-03-10  0:50 ` Ben Hutchings
  2012-03-10  0:51 ` [PATCH net-next 07/10] sfc: Encapsulate access to efx_{channel,nic}::last_irq_cpu in self-test Ben Hutchings
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Ben Hutchings @ 2012-03-10  0:50 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers

In case all event queues are broken for some reason, this means it
will only take about a second to check them all, rather than up to 32
seconds.  This may also speed up testing in the successful case.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 drivers/net/ethernet/sfc/selftest.c |  114 ++++++++++++++++++++---------------
 1 files changed, 65 insertions(+), 49 deletions(-)

diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c
index dc330b9..e4b4c8a 100644
--- a/drivers/net/ethernet/sfc/selftest.c
+++ b/drivers/net/ethernet/sfc/selftest.c
@@ -178,69 +178,88 @@ static int efx_test_interrupts(struct efx_nic *efx,
 }
 
 /* Test generation and receipt of interrupting events */
-static int efx_test_eventq_irq(struct efx_channel *channel,
+static int efx_test_eventq_irq(struct efx_nic *efx,
 			       struct efx_self_tests *tests)
 {
-	struct efx_nic *efx = channel->efx;
-	unsigned int read_ptr;
-	bool napi_ran, dma_seen, int_seen;
+	struct efx_channel *channel;
+	unsigned int read_ptr[EFX_MAX_CHANNELS];
+	unsigned long napi_ran = 0, dma_pend = 0, int_pend = 0;
 	unsigned long timeout, wait;
 
-	read_ptr = channel->eventq_read_ptr;
-	channel->last_irq_cpu = -1;
-	smp_wmb();
+	BUILD_BUG_ON(EFX_MAX_CHANNELS > BITS_PER_LONG);
+
+	efx_for_each_channel(channel, efx) {
+		read_ptr[channel->channel] = channel->eventq_read_ptr;
+		set_bit(channel->channel, &dma_pend);
+		set_bit(channel->channel, &int_pend);
+		channel->last_irq_cpu = -1;
+		smp_wmb();
+		efx_nic_generate_test_event(channel);
+	}
 
-	efx_nic_generate_test_event(channel);
 	timeout = jiffies + IRQ_TIMEOUT;
 	wait = 1;
 
-	/* Wait for arrival of interrupt.  NAPI processing may or may
+	/* Wait for arrival of interrupts.  NAPI processing may or may
 	 * not complete in time, but we can cope in any case.
 	 */
 	do {
 		schedule_timeout_uninterruptible(wait);
 
-		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 = ACCESS_ONCE(channel->last_irq_cpu) >= 0;
+		efx_for_each_channel(channel, efx) {
+			napi_disable(&channel->napi_str);
+			if (channel->eventq_read_ptr !=
+			    read_ptr[channel->channel]) {
+				set_bit(channel->channel, &napi_ran);
+				clear_bit(channel->channel, &dma_pend);
+				clear_bit(channel->channel, &int_pend);
+			} else {
+				if (efx_nic_event_present(channel))
+					clear_bit(channel->channel, &dma_pend);
+				if (ACCESS_ONCE(channel->last_irq_cpu) >= 0)
+					clear_bit(channel->channel, &int_pend);
+			}
+			napi_enable(&channel->napi_str);
+			efx_nic_eventq_read_ack(channel);
 		}
-		napi_enable(&channel->napi_str);
-		efx_nic_eventq_read_ack(channel);
 
 		wait *= 2;
-	} while (!(dma_seen && int_seen) && time_before(jiffies, timeout));
-
-	tests->eventq_dma[channel->channel] = dma_seen ? 1 : -1;
-	tests->eventq_int[channel->channel] = int_seen ? 1 : -1;
+	} while ((dma_pend || int_pend) && time_before(jiffies, timeout));
 
-	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 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)
+	efx_for_each_channel(channel, efx) {
+		bool dma_seen = !test_bit(channel->channel, &dma_pend);
+		bool int_seen = !test_bit(channel->channel, &int_pend);
+
+		tests->eventq_dma[channel->channel] = dma_seen ? 1 : -1;
+		tests->eventq_int[channel->channel] = int_seen ? 1 : -1;
+
+		if (dma_seen && int_seen) {
+			netif_dbg(efx, drv, efx->net_dev,
+				  "channel %d event queue passed (with%s NAPI)\n",
+				  channel->channel,
+				  test_bit(channel->channel, &napi_ran) ?
+				  "" : "out");
+		} 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 %d timed out waiting for event queue\n",
 				  channel->channel);
-		return -ETIMEDOUT;
+			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 (dma_pend || int_pend) ? -ETIMEDOUT : 0;
 }
 
 static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests,
@@ -687,7 +706,6 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
 	enum efx_loopback_mode loopback_mode = efx->loopback_mode;
 	int phy_mode = efx->phy_mode;
 	enum reset_type reset_method = RESET_TYPE_INVISIBLE;
-	struct efx_channel *channel;
 	int rc_test = 0, rc_reset = 0, rc;
 
 	/* Online (i.e. non-disruptive) testing
@@ -705,11 +723,9 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
 	if (rc && !rc_test)
 		rc_test = rc;
 
-	efx_for_each_channel(channel, efx) {
-		rc = efx_test_eventq_irq(channel, tests);
-		if (rc && !rc_test)
-			rc_test = rc;
-	}
+	rc = efx_test_eventq_irq(efx, tests);
+	if (rc && !rc_test)
+		rc_test = rc;
 
 	if (rc_test)
 		return rc_test;
-- 
1.7.7.6



-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH net-next 07/10] sfc: Encapsulate access to efx_{channel,nic}::last_irq_cpu in self-test
  2012-03-10  0:46 pull request: sfc 2012-03-09 Ben Hutchings
                   ` (5 preceding siblings ...)
  2012-03-10  0:50 ` [PATCH net-next 06/10] sfc: Test all event queues in parallel Ben Hutchings
@ 2012-03-10  0:51 ` Ben Hutchings
  2012-03-10  0:51 ` [PATCH net-next 08/10] sfc: Run event/IRQ self-test asynchronously when interface is brought up Ben Hutchings
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Ben Hutchings @ 2012-03-10  0:51 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers

Cleanup in preparation for doing an event test on ifup.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 drivers/net/ethernet/sfc/nic.c      |    8 ++++++--
 drivers/net/ethernet/sfc/nic.h      |   13 +++++++++++--
 drivers/net/ethernet/sfc/selftest.c |   14 ++++----------
 3 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index 5da8af5..4c47b75 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -1332,8 +1332,10 @@ void efx_nic_remove_eventq(struct efx_channel *channel)
 }
 

-void efx_nic_generate_test_event(struct efx_channel *channel)
+void efx_nic_event_test_start(struct efx_channel *channel)
 {
+	channel->last_irq_cpu = -1;
+	smp_wmb();
 	efx_magic_event(channel, EFX_CHANNEL_MAGIC_TEST(channel));
 }
 
@@ -1382,8 +1384,10 @@ void efx_nic_disable_interrupts(struct efx_nic *efx)
  * Interrupt must already have been enabled, otherwise nasty things
  * may happen.
  */
-void efx_nic_generate_interrupt(struct efx_nic *efx)
+void efx_nic_irq_test_start(struct efx_nic *efx)
 {
+	efx->last_irq_cpu = -1;
+	smp_wmb();
 	efx_nic_interrupts(efx, true, true);
 }
 
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index ac12f7f..e0e8596 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -301,14 +301,23 @@ extern void falcon_update_stats_xmac(struct efx_nic *efx);
 /* Interrupts and test events */
 extern int efx_nic_init_interrupt(struct efx_nic *efx);
 extern void efx_nic_enable_interrupts(struct efx_nic *efx);
-extern void efx_nic_generate_test_event(struct efx_channel *channel);
-extern void efx_nic_generate_interrupt(struct efx_nic *efx);
+extern void efx_nic_event_test_start(struct efx_channel *channel);
+extern void efx_nic_irq_test_start(struct efx_nic *efx);
 extern void efx_nic_disable_interrupts(struct efx_nic *efx);
 extern void efx_nic_fini_interrupt(struct efx_nic *efx);
 extern irqreturn_t efx_nic_fatal_interrupt(struct efx_nic *efx);
 extern irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id);
 extern void falcon_irq_ack_a1(struct efx_nic *efx);
 
+static inline int efx_nic_event_test_irq_cpu(struct efx_channel *channel)
+{
+	return ACCESS_ONCE(channel->last_irq_cpu);
+}
+static inline int efx_nic_irq_test_irq_cpu(struct efx_nic *efx)
+{
+	return ACCESS_ONCE(efx->last_irq_cpu);
+}
+
 /* Global Resources */
 extern int efx_nic_flush_queues(struct efx_nic *efx);
 extern void falcon_start_nic_stats(struct efx_nic *efx);
diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c
index e4b4c8a..aa4ab53 100644
--- a/drivers/net/ethernet/sfc/selftest.c
+++ b/drivers/net/ethernet/sfc/selftest.c
@@ -149,11 +149,7 @@ static int efx_test_interrupts(struct efx_nic *efx,
 	netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n");
 	tests->interrupt = -1;
 
-	/* Reset interrupt flag */
-	efx->last_irq_cpu = -1;
-	smp_wmb();
-
-	efx_nic_generate_interrupt(efx);
+	efx_nic_irq_test_start(efx);
 	timeout = jiffies + IRQ_TIMEOUT;
 	wait = 1;
 
@@ -161,7 +157,7 @@ static int efx_test_interrupts(struct efx_nic *efx,
 	netif_dbg(efx, drv, efx->net_dev, "waiting for test interrupt\n");
 	do {
 		schedule_timeout_uninterruptible(wait);
-		cpu = ACCESS_ONCE(efx->last_irq_cpu);
+		cpu = efx_nic_irq_test_irq_cpu(efx);
 		if (cpu >= 0)
 			goto success;
 		wait *= 2;
@@ -192,9 +188,7 @@ static int efx_test_eventq_irq(struct efx_nic *efx,
 		read_ptr[channel->channel] = channel->eventq_read_ptr;
 		set_bit(channel->channel, &dma_pend);
 		set_bit(channel->channel, &int_pend);
-		channel->last_irq_cpu = -1;
-		smp_wmb();
-		efx_nic_generate_test_event(channel);
+		efx_nic_event_test_start(channel);
 	}
 
 	timeout = jiffies + IRQ_TIMEOUT;
@@ -216,7 +210,7 @@ static int efx_test_eventq_irq(struct efx_nic *efx,
 			} else {
 				if (efx_nic_event_present(channel))
 					clear_bit(channel->channel, &dma_pend);
-				if (ACCESS_ONCE(channel->last_irq_cpu) >= 0)
+				if (efx_nic_event_test_irq_cpu(channel) >= 0)
 					clear_bit(channel->channel, &int_pend);
 			}
 			napi_enable(&channel->napi_str);
-- 
1.7.7.6



-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH net-next 08/10] sfc: Run event/IRQ self-test asynchronously when interface is brought up
  2012-03-10  0:46 pull request: sfc 2012-03-09 Ben Hutchings
                   ` (6 preceding siblings ...)
  2012-03-10  0:51 ` [PATCH net-next 07/10] sfc: Encapsulate access to efx_{channel,nic}::last_irq_cpu in self-test Ben Hutchings
@ 2012-03-10  0:51 ` Ben Hutchings
  2012-03-10  0:52 ` [PATCH net-next 09/10] sfc: Remove efx_channel::last_eventq_read_ptr Ben Hutchings
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Ben Hutchings @ 2012-03-10  0:51 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers

Generate a test event on each event queue whenever the interface is
brought up, then after 1 second check that we have either handled a
test event or handled another IRQ for each event queue.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 drivers/net/ethernet/sfc/efx.c        |    6 ++++-
 drivers/net/ethernet/sfc/efx.h        |    2 +-
 drivers/net/ethernet/sfc/net_driver.h |    6 +++-
 drivers/net/ethernet/sfc/nic.c        |    4 +-
 drivers/net/ethernet/sfc/nic.h        |    2 +-
 drivers/net/ethernet/sfc/selftest.c   |   35 +++++++++++++++++++++++++++++++++
 drivers/net/ethernet/sfc/selftest.h   |    3 ++
 7 files changed, 51 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 00e13ab..7683e53 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -25,6 +25,7 @@
 #include "net_driver.h"
 #include "efx.h"
 #include "nic.h"
+#include "selftest.h"
 
 #include "mcdi.h"
 #include "workarounds.h"
@@ -1564,8 +1565,9 @@ static void efx_start_all(struct efx_nic *efx)
  * since we're holding the rtnl_lock at this point. */
 static void efx_flush_all(struct efx_nic *efx)
 {
-	/* Make sure the hardware monitor is stopped */
+	/* Make sure the hardware monitor and event self-test are stopped */
 	cancel_delayed_work_sync(&efx->monitor_work);
+	efx_selftest_async_cancel(efx);
 	/* Stop scheduled port reconfigurations */
 	cancel_work_sync(&efx->mac_work);
 }
@@ -1825,6 +1827,7 @@ static int efx_net_open(struct net_device *net_dev)
 	efx_link_status_changed(efx);
 
 	efx_start_all(efx);
+	efx_selftest_async_start(efx);
 	return 0;
 }
 
@@ -2375,6 +2378,7 @@ static int efx_init_struct(struct efx_nic *efx, const struct efx_nic_type *type,
 #endif
 	INIT_WORK(&efx->reset_work, efx_reset_work);
 	INIT_DELAYED_WORK(&efx->monitor_work, efx_monitor);
+	INIT_DELAYED_WORK(&efx->selftest_work, efx_selftest_async_work);
 	efx->pci_dev = pci_dev;
 	efx->msg_enable = debug;
 	efx->state = STATE_INIT;
diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h
index 4debfe0..be8f915 100644
--- a/drivers/net/ethernet/sfc/efx.h
+++ b/drivers/net/ethernet/sfc/efx.h
@@ -148,7 +148,7 @@ static inline void efx_schedule_channel(struct efx_channel *channel)
 
 static inline void efx_schedule_channel_irq(struct efx_channel *channel)
 {
-	channel->last_irq_cpu = raw_smp_processor_id();
+	channel->event_test_cpu = raw_smp_processor_id();
 	efx_schedule_channel(channel);
 }
 
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 0b95505..27fe85f 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -325,7 +325,7 @@ enum efx_rx_alloc_method {
  * @eventq_mask: Event queue pointer mask
  * @eventq_read_ptr: Event queue read pointer
  * @last_eventq_read_ptr: Last event queue read pointer value.
- * @last_irq_cpu: Last CPU to handle interrupt for this channel
+ * @event_test_cpu: Last CPU to handle interrupt or test event for this channel
  * @irq_count: Number of IRQs since last adaptive moderation decision
  * @irq_mod_score: IRQ moderation score
  * @rx_alloc_level: Watermark based heuristic counter for pushing descriptors
@@ -356,8 +356,8 @@ struct efx_channel {
 	unsigned int eventq_mask;
 	unsigned int eventq_read_ptr;
 	unsigned int last_eventq_read_ptr;
+	int event_test_cpu;
 
-	int last_irq_cpu;
 	unsigned int irq_count;
 	unsigned int irq_mod_score;
 #ifdef CONFIG_RFS_ACCEL
@@ -678,6 +678,7 @@ struct vfdi_status;
  * @irq_status: Interrupt status buffer
  * @irq_zero_count: Number of legacy IRQs seen with queue flags == 0
  * @irq_level: IRQ level/index for IRQs not triggered by an event queue
+ * @selftest_work: Work item for asynchronous self-test
  * @mtd_list: List of MTDs attached to the NIC
  * @nic_data: Hardware dependent state
  * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
@@ -791,6 +792,7 @@ struct efx_nic {
 	struct efx_buffer irq_status;
 	unsigned irq_zero_count;
 	unsigned irq_level;
+	struct delayed_work selftest_work;
 
 #ifdef CONFIG_SFC_MTD
 	struct list_head mtd_list;
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index 4c47b75..4a9a5be 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -1083,7 +1083,7 @@ efx_handle_generated_event(struct efx_channel *channel, efx_qword_t *event)
 	code = _EFX_CHANNEL_MAGIC_CODE(magic);
 
 	if (magic == EFX_CHANNEL_MAGIC_TEST(channel)) {
-		/* ignore */
+		channel->event_test_cpu = raw_smp_processor_id();
 	} else if (rx_queue && magic == EFX_CHANNEL_MAGIC_FILL(rx_queue)) {
 		/* The queue must be empty, so we won't receive any rx
 		 * events, so efx_process_channel() won't refill the
@@ -1334,7 +1334,7 @@ void efx_nic_remove_eventq(struct efx_channel *channel)
 
 void efx_nic_event_test_start(struct efx_channel *channel)
 {
-	channel->last_irq_cpu = -1;
+	channel->event_test_cpu = -1;
 	smp_wmb();
 	efx_magic_event(channel, EFX_CHANNEL_MAGIC_TEST(channel));
 }
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index e0e8596..f46e2ce 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -311,7 +311,7 @@ extern void falcon_irq_ack_a1(struct efx_nic *efx);
 
 static inline int efx_nic_event_test_irq_cpu(struct efx_channel *channel)
 {
-	return ACCESS_ONCE(channel->last_irq_cpu);
+	return ACCESS_ONCE(channel->event_test_cpu);
 }
 static inline int efx_nic_irq_test_irq_cpu(struct efx_nic *efx)
 {
diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c
index aa4ab53..de4c006 100644
--- a/drivers/net/ethernet/sfc/selftest.c
+++ b/drivers/net/ethernet/sfc/selftest.c
@@ -702,6 +702,8 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
 	enum reset_type reset_method = RESET_TYPE_INVISIBLE;
 	int rc_test = 0, rc_reset = 0, rc;
 
+	efx_selftest_async_cancel(efx);
+
 	/* Online (i.e. non-disruptive) testing
 	 * This checks interrupt generation, event delivery and PHY presence. */
 
@@ -794,3 +796,36 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
 	return rc_test;
 }
 
+void efx_selftest_async_start(struct efx_nic *efx)
+{
+	struct efx_channel *channel;
+
+	efx_for_each_channel(channel, efx)
+		efx_nic_event_test_start(channel);
+	schedule_delayed_work(&efx->selftest_work, IRQ_TIMEOUT);
+}
+
+void efx_selftest_async_cancel(struct efx_nic *efx)
+{
+	cancel_delayed_work_sync(&efx->selftest_work);
+}
+
+void efx_selftest_async_work(struct work_struct *data)
+{
+	struct efx_nic *efx = container_of(data, struct efx_nic,
+					   selftest_work.work);
+	struct efx_channel *channel;
+	int cpu;
+
+	efx_for_each_channel(channel, efx) {
+		cpu = efx_nic_event_test_irq_cpu(channel);
+		if (cpu < 0)
+			netif_err(efx, ifup, efx->net_dev,
+				  "channel %d failed to trigger an interrupt\n",
+				  channel->channel);
+		else
+			netif_dbg(efx, ifup, efx->net_dev,
+				  "channel %d triggered interrupt on CPU %d\n",
+				  channel->channel, cpu);
+	}
+}
diff --git a/drivers/net/ethernet/sfc/selftest.h b/drivers/net/ethernet/sfc/selftest.h
index 87abe2a..aed24b7 100644
--- a/drivers/net/ethernet/sfc/selftest.h
+++ b/drivers/net/ethernet/sfc/selftest.h
@@ -48,5 +48,8 @@ extern void efx_loopback_rx_packet(struct efx_nic *efx,
 extern int efx_selftest(struct efx_nic *efx,
 			struct efx_self_tests *tests,
 			unsigned flags);
+extern void efx_selftest_async_start(struct efx_nic *efx);
+extern void efx_selftest_async_cancel(struct efx_nic *efx);
+extern void efx_selftest_async_work(struct work_struct *data);
 
 #endif /* EFX_SELFTEST_H */
-- 
1.7.7.6



-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH net-next 09/10] sfc: Remove efx_channel::last_eventq_read_ptr
  2012-03-10  0:46 pull request: sfc 2012-03-09 Ben Hutchings
                   ` (7 preceding siblings ...)
  2012-03-10  0:51 ` [PATCH net-next 08/10] sfc: Run event/IRQ self-test asynchronously when interface is brought up Ben Hutchings
@ 2012-03-10  0:52 ` Ben Hutchings
  2012-03-10  0:53 ` [PATCH net-next 10/10] sfc: Log the part number on probe Ben Hutchings
  2012-03-10  2:56 ` pull request: sfc 2012-03-09 David Miller
  10 siblings, 0 replies; 12+ messages in thread
From: Ben Hutchings @ 2012-03-10  0:52 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers

This member has never been used in a production version of the driver.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 drivers/net/ethernet/sfc/net_driver.h |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 27fe85f..f0385e1 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -324,7 +324,6 @@ enum efx_rx_alloc_method {
  * @eventq: Event queue buffer
  * @eventq_mask: Event queue pointer mask
  * @eventq_read_ptr: Event queue read pointer
- * @last_eventq_read_ptr: Last event queue read pointer value.
  * @event_test_cpu: Last CPU to handle interrupt or test event for this channel
  * @irq_count: Number of IRQs since last adaptive moderation decision
  * @irq_mod_score: IRQ moderation score
@@ -355,7 +354,6 @@ struct efx_channel {
 	struct efx_special_buffer eventq;
 	unsigned int eventq_mask;
 	unsigned int eventq_read_ptr;
-	unsigned int last_eventq_read_ptr;
 	int event_test_cpu;
 
 	unsigned int irq_count;
-- 
1.7.7.6



-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH net-next 10/10] sfc: Log the part number on probe
  2012-03-10  0:46 pull request: sfc 2012-03-09 Ben Hutchings
                   ` (8 preceding siblings ...)
  2012-03-10  0:52 ` [PATCH net-next 09/10] sfc: Remove efx_channel::last_eventq_read_ptr Ben Hutchings
@ 2012-03-10  0:53 ` Ben Hutchings
  2012-03-10  2:56 ` pull request: sfc 2012-03-09 David Miller
  10 siblings, 0 replies; 12+ messages in thread
From: Ben Hutchings @ 2012-03-10  0:53 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers

During probe of each port, read and log the part number from VPD.
Remove the Falcon-specific board name lookup.

Initial version by Stuart Hodgson <smhodgson@solarflare.com>.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 drivers/net/ethernet/sfc/efx.c           |   53 ++++++++++++++++++++++++++++++
 drivers/net/ethernet/sfc/falcon_boards.c |   13 -------
 drivers/net/ethernet/sfc/nic.h           |    4 --
 3 files changed, 53 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 7683e53..3cbfbff 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -2497,6 +2497,57 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
 	free_netdev(efx->net_dev);
 };
 
+/* NIC VPD information
+ * Called during probe to display the part number of the
+ * installed NIC.  VPD is potentially very large but this should
+ * always appear within the first 512 bytes.
+ */
+#define SFC_VPD_LEN 512
+static void efx_print_product_vpd(struct efx_nic *efx)
+{
+	struct pci_dev *dev = efx->pci_dev;
+	char vpd_data[SFC_VPD_LEN];
+	ssize_t vpd_size;
+	int i, j;
+
+	/* Get the vpd data from the device */
+	vpd_size = pci_read_vpd(dev, 0, sizeof(vpd_data), vpd_data);
+	if (vpd_size <= 0) {
+		netif_err(efx, drv, efx->net_dev, "Unable to read VPD\n");
+		return;
+	}
+
+	/* Get the Read only section */
+	i = pci_vpd_find_tag(vpd_data, 0, vpd_size, PCI_VPD_LRDT_RO_DATA);
+	if (i < 0) {
+		netif_err(efx, drv, efx->net_dev, "VPD Read-only not found\n");
+		return;
+	}
+
+	j = pci_vpd_lrdt_size(&vpd_data[i]);
+	i += PCI_VPD_LRDT_TAG_SIZE;
+	if (i + j > vpd_size)
+		j = vpd_size - i;
+
+	/* Get the Part number */
+	i = pci_vpd_find_info_keyword(vpd_data, i, j, "PN");
+	if (i < 0) {
+		netif_err(efx, drv, efx->net_dev, "Part number not found\n");
+		return;
+	}
+
+	j = pci_vpd_info_field_size(&vpd_data[i]);
+	i += PCI_VPD_INFO_FLD_HDR_SIZE;
+	if (i + j > vpd_size) {
+		netif_err(efx, drv, efx->net_dev, "Incomplete part number\n");
+		return;
+	}
+
+	netif_info(efx, drv, efx->net_dev,
+		   "Part Number : %.*s\n", j, &vpd_data[i]);
+}
+
+
 /* Main body of NIC initialisation
  * This is called at module load (or hotplug insertion, theoretically).
  */
@@ -2586,6 +2637,8 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
 	netif_info(efx, probe, efx->net_dev,
 		   "Solarflare NIC detected\n");
 
+	efx_print_product_vpd(efx);
+
 	/* Set up basic I/O (BAR mappings etc) */
 	rc = efx_init_io(efx);
 	if (rc)
diff --git a/drivers/net/ethernet/sfc/falcon_boards.c b/drivers/net/ethernet/sfc/falcon_boards.c
index 2084cc6..8687a6c 100644
--- a/drivers/net/ethernet/sfc/falcon_boards.c
+++ b/drivers/net/ethernet/sfc/falcon_boards.c
@@ -709,8 +709,6 @@ static int sfe4003_init(struct efx_nic *efx)
 static const struct falcon_board_type board_types[] = {
 	{
 		.id		= FALCON_BOARD_SFE4001,
-		.ref_model	= "SFE4001",
-		.gen_type	= "10GBASE-T adapter",
 		.init		= sfe4001_init,
 		.init_phy	= efx_port_dummy_op_void,
 		.fini		= sfe4001_fini,
@@ -719,8 +717,6 @@ static const struct falcon_board_type board_types[] = {
 	},
 	{
 		.id		= FALCON_BOARD_SFE4002,
-		.ref_model	= "SFE4002",
-		.gen_type	= "XFP adapter",
 		.init		= sfe4002_init,
 		.init_phy	= sfe4002_init_phy,
 		.fini		= efx_fini_lm87,
@@ -729,8 +725,6 @@ static const struct falcon_board_type board_types[] = {
 	},
 	{
 		.id		= FALCON_BOARD_SFE4003,
-		.ref_model	= "SFE4003",
-		.gen_type	= "10GBASE-CX4 adapter",
 		.init		= sfe4003_init,
 		.init_phy	= sfe4003_init_phy,
 		.fini		= efx_fini_lm87,
@@ -739,8 +733,6 @@ static const struct falcon_board_type board_types[] = {
 	},
 	{
 		.id		= FALCON_BOARD_SFN4112F,
-		.ref_model	= "SFN4112F",
-		.gen_type	= "SFP+ adapter",
 		.init		= sfn4112f_init,
 		.init_phy	= sfn4112f_init_phy,
 		.fini		= efx_fini_lm87,
@@ -763,11 +755,6 @@ int falcon_probe_board(struct efx_nic *efx, u16 revision_info)
 			board->type = &board_types[i];
 
 	if (board->type) {
-		netif_info(efx, probe, efx->net_dev, "board is %s rev %c%d\n",
-			 (efx->pci_dev->subsystem_vendor ==
-			  PCI_VENDOR_ID_SOLARFLARE)
-			 ? board->type->ref_model : board->type->gen_type,
-			 'A' + board->major, board->minor);
 		return 0;
 	} else {
 		netif_err(efx, probe, efx->net_dev, "unknown board type %d\n",
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index f46e2ce..f48ccf6 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -69,8 +69,6 @@ enum {
 /**
  * struct falcon_board_type - board operations and type information
  * @id: Board type id, as found in NVRAM
- * @ref_model: Model number of Solarflare reference design
- * @gen_type: Generic board type description
  * @init: Allocate resources and initialise peripheral hardware
  * @init_phy: Do board-specific PHY initialisation
  * @fini: Shut down hardware and free resources
@@ -79,8 +77,6 @@ enum {
  */
 struct falcon_board_type {
 	u8 id;
-	const char *ref_model;
-	const char *gen_type;
 	int (*init) (struct efx_nic *nic);
 	void (*init_phy) (struct efx_nic *efx);
 	void (*fini) (struct efx_nic *nic);
-- 
1.7.7.6


-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: pull request: sfc 2012-03-09
  2012-03-10  0:46 pull request: sfc 2012-03-09 Ben Hutchings
                   ` (9 preceding siblings ...)
  2012-03-10  0:53 ` [PATCH net-next 10/10] sfc: Log the part number on probe Ben Hutchings
@ 2012-03-10  2:56 ` David Miller
  10 siblings, 0 replies; 12+ messages in thread
From: David Miller @ 2012-03-10  2:56 UTC (permalink / raw)
  To: bhutchings; +Cc: netdev, linux-net-drivers

From: Ben Hutchings <bhutchings@solarflare.com>
Date: Sat, 10 Mar 2012 00:46:49 +0000

> The following changes since commit ffcb97388b1d41b1db063eb041cb9af408662127:
> 
>   Merge branch 'master' of git://gitorious.org/linux-can/linux-can-next (2012-03-04 21:59:39 -0500)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next.git for-davem
> 
> (commit 460eeaa03c5c0af32a388337a6e1f0f1acd043ce)
> 
> 1. Fix a bug in SR-IOV support that I introduced while cleaning it up
> prior to upstreaming.
> 2. Show the part number for all boards at probe time, not just the ones
> we have specific code for.
> 3. Improve self-test reliability, and test interrupts & events
> immediately after bringing an interface up.
> 4. Improve adaptive IRQ moderation.
> 5. Various cleanup.

Pulled, thanks Ben.

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2012-03-10  2:56 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-10  0:46 pull request: sfc 2012-03-09 Ben Hutchings
2012-03-10  0:48 ` [PATCH net-next 01/10] sfc: Fix calculation of vf_i in map_vi_index() Ben Hutchings
2012-03-10  0:49 ` [PATCH net-next 02/10] sfc: Remove redundant function efx_nic_has_mc() Ben Hutchings
2012-03-10  0:49 ` [PATCH net-next 03/10] sfc: Update comments on efx_rx_packet_gro() Ben Hutchings
2012-03-10  0:49 ` [PATCH net-next 04/10] sfc: Remove TX completions from adaptive IRQ scoring Ben Hutchings
2012-03-10  0:50 ` [PATCH net-next 05/10] sfc: Raise self-test timeouts Ben Hutchings
2012-03-10  0:50 ` [PATCH net-next 06/10] sfc: Test all event queues in parallel Ben Hutchings
2012-03-10  0:51 ` [PATCH net-next 07/10] sfc: Encapsulate access to efx_{channel,nic}::last_irq_cpu in self-test Ben Hutchings
2012-03-10  0:51 ` [PATCH net-next 08/10] sfc: Run event/IRQ self-test asynchronously when interface is brought up Ben Hutchings
2012-03-10  0:52 ` [PATCH net-next 09/10] sfc: Remove efx_channel::last_eventq_read_ptr Ben Hutchings
2012-03-10  0:53 ` [PATCH net-next 10/10] sfc: Log the part number on probe Ben Hutchings
2012-03-10  2:56 ` pull request: sfc 2012-03-09 David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).