netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] napi_synchronize: waiting for NAPI
       [not found] <20071017202640.171902388@linux-foundation.org>
@ 2007-10-17 20:26 ` Stephen Hemminger
  2007-10-18  0:21   ` Jeff Garzik
  2007-10-18  0:28   ` Benjamin Herrenschmidt
  2007-10-17 20:26 ` [PATCH 2/2] sky2: shutdown cleanup Stephen Hemminger
  1 sibling, 2 replies; 6+ messages in thread
From: Stephen Hemminger @ 2007-10-17 20:26 UTC (permalink / raw)
  To: David S. Miller, Jeff Garzik; +Cc: netdev

[-- Attachment #1: napi-synchronize.patch --]
[-- Type: text/plain, Size: 1039 bytes --]

Some drivers with shared NAPI need a synchronization barrier.
Also suggested by Benjamin Herrenschmidt for EMAC.

Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>

--- a/include/linux/netdevice.h	2007-10-17 08:45:32.000000000 -0700
+++ b/include/linux/netdevice.h	2007-10-17 08:47:54.000000000 -0700
@@ -407,6 +407,24 @@ static inline void napi_enable(struct na
 	clear_bit(NAPI_STATE_SCHED, &n->state);
 }
 
+#ifdef CONFIG_SMP
+/**
+ *	napi_synchronize - wait until NAPI is not running
+ *	@n: napi context
+ *
+ * Wait until NAPI is done being scheduled on this context.
+ * Waits till any outstanding processing completes but
+ * does not disable future activations.
+ */
+static inline void napi_synchronize(const struct napi_struct *n)
+{
+	while (test_bit(NAPI_STATE_SCHED, &n->state))
+		msleep(1);
+}
+#else
+# define napi_synchronize(n)	barrier()
+#endif
+
 /*
  *	The DEVICE structure.
  *	Actually, this whole structure is a big mistake.  It mixes I/O

-- 
Stephen Hemminger <shemminger@linux-foundation.org>


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

* [PATCH 2/2] sky2: shutdown cleanup
       [not found] <20071017202640.171902388@linux-foundation.org>
  2007-10-17 20:26 ` [PATCH 1/2] napi_synchronize: waiting for NAPI Stephen Hemminger
@ 2007-10-17 20:26 ` Stephen Hemminger
  1 sibling, 0 replies; 6+ messages in thread
From: Stephen Hemminger @ 2007-10-17 20:26 UTC (permalink / raw)
  To: David S. Miller, Jeff Garzik; +Cc: netdev

[-- Attachment #1: sky2-shutdown-cleanup.patch --]
[-- Type: text/plain, Size: 4485 bytes --]

Solve issues with dual port devices due to shared NAPI.
 * shutting down one device shouldn't kill other one.
 * suspend shouldn't hang.
Also fix potential race between restart and shutdown.

Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>

--- a/drivers/net/sky2.c	2007-10-17 10:17:56.000000000 -0700
+++ b/drivers/net/sky2.c	2007-10-17 13:12:06.000000000 -0700
@@ -1384,13 +1384,9 @@ static int sky2_up(struct net_device *de
 	sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map,
 			   TX_RING_SIZE - 1);
 
-	napi_enable(&hw->napi);
-
 	err = sky2_rx_start(sky2);
-	if (err) {
-		napi_disable(&hw->napi);
+	if (err)
 		goto err_out;
-	}
 
 	/* Enable interrupts from phy/mac for port */
 	imask = sky2_read32(hw, B0_IMSK);
@@ -1679,13 +1675,13 @@ static int sky2_down(struct net_device *
 	/* Stop more packets from being queued */
 	netif_stop_queue(dev);
 
-	napi_disable(&hw->napi);
-
 	/* Disable port IRQ */
 	imask = sky2_read32(hw, B0_IMSK);
 	imask &= ~portirq_msk[port];
 	sky2_write32(hw, B0_IMSK, imask);
 
+	synchronize_irq(hw->pdev->irq);
+
 	sky2_gmac_reset(hw, port);
 
 	/* Stop transmitter */
@@ -1699,6 +1695,9 @@ static int sky2_down(struct net_device *
 	ctrl &= ~(GM_GPCR_TX_ENA | GM_GPCR_RX_ENA);
 	gma_write16(hw, port, GM_GP_CTRL, ctrl);
 
+	/* Make sure no packets are pending */
+	napi_synchronize(&hw->napi);
+
 	sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
 
 	/* Workaround shared GMAC reset */
@@ -1736,8 +1735,6 @@ static int sky2_down(struct net_device *
 	/* turn off LED's */
 	sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
 
-	synchronize_irq(hw->pdev->irq);
-
 	sky2_tx_clean(dev);
 	sky2_rx_clean(sky2);
 
@@ -2048,9 +2045,6 @@ static int sky2_change_mtu(struct net_de
 	err = sky2_rx_start(sky2);
 	sky2_write32(hw, B0_IMSK, imask);
 
-	/* Unconditionally re-enable NAPI because even if we
-	 * call dev_close() that will do a napi_disable().
-	 */
 	napi_enable(&hw->napi);
 
 	if (err)
@@ -2915,6 +2909,7 @@ static void sky2_restart(struct work_str
 	rtnl_lock();
 	sky2_write32(hw, B0_IMSK, 0);
 	sky2_read32(hw, B0_IMSK);
+	napi_disable(&hw->napi);
 
 	for (i = 0; i < hw->ports; i++) {
 		dev = hw->dev[i];
@@ -2924,6 +2919,7 @@ static void sky2_restart(struct work_str
 
 	sky2_reset(hw);
 	sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
+	napi_enable(&hw->napi);
 
 	for (i = 0; i < hw->ports; i++) {
 		dev = hw->dev[i];
@@ -4191,7 +4187,6 @@ static int __devinit sky2_probe(struct p
 		err = -ENOMEM;
 		goto err_out_free_pci;
 	}
-	netif_napi_add(dev, &hw->napi, sky2_poll, NAPI_WEIGHT);
 
 	if (!disable_msi && pci_enable_msi(pdev) == 0) {
 		err = sky2_test_msi(hw);
@@ -4207,6 +4202,8 @@ static int __devinit sky2_probe(struct p
 		goto err_out_free_netdev;
 	}
 
+	netif_napi_add(dev, &hw->napi, sky2_poll, NAPI_WEIGHT);
+
 	err = request_irq(pdev->irq, sky2_intr,
 			  (hw->flags & SKY2_HW_USE_MSI) ? 0 : IRQF_SHARED,
 			  dev->name, hw);
@@ -4215,6 +4212,7 @@ static int __devinit sky2_probe(struct p
 		goto err_out_unregister;
 	}
 	sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
+	napi_enable(&hw->napi);
 
 	sky2_show_addr(dev);
 
@@ -4265,23 +4263,18 @@ err_out:
 static void __devexit sky2_remove(struct pci_dev *pdev)
 {
 	struct sky2_hw *hw = pci_get_drvdata(pdev);
-	struct net_device *dev0, *dev1;
+	int i;
 
 	if (!hw)
 		return;
 
 	del_timer_sync(&hw->watchdog_timer);
+	cancel_work_sync(&hw->restart_work);
 
-	flush_scheduled_work();
+	for (i = hw->ports; i >= 0; --i)
+		unregister_netdev(hw->dev[i]);
 
 	sky2_write32(hw, B0_IMSK, 0);
-	synchronize_irq(hw->pdev->irq);
-
-	dev0 = hw->dev[0];
-	dev1 = hw->dev[1];
-	if (dev1)
-		unregister_netdev(dev1);
-	unregister_netdev(dev0);
 
 	sky2_power_aux(hw);
 
@@ -4296,9 +4289,9 @@ static void __devexit sky2_remove(struct
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 
-	if (dev1)
-		free_netdev(dev1);
-	free_netdev(dev0);
+	for (i = hw->ports; i >= 0; --i)
+		free_netdev(hw->dev[i]);
+
 	iounmap(hw->regs);
 	kfree(hw);
 
@@ -4328,6 +4321,7 @@ static int sky2_suspend(struct pci_dev *
 	}
 
 	sky2_write32(hw, B0_IMSK, 0);
+	napi_disable(&hw->napi);
 	sky2_power_aux(hw);
 
 	pci_save_state(pdev);
@@ -4362,8 +4356,8 @@ static int sky2_resume(struct pci_dev *p
 		pci_write_config_dword(pdev, PCI_DEV_REG3, 0);
 
 	sky2_reset(hw);
-
 	sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
+	napi_enable(&hw->napi);
 
 	for (i = 0; i < hw->ports; i++) {
 		struct net_device *dev = hw->dev[i];

-- 
Stephen Hemminger <shemminger@linux-foundation.org>


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

* Re: [PATCH 1/2] napi_synchronize: waiting for NAPI
  2007-10-17 20:26 ` [PATCH 1/2] napi_synchronize: waiting for NAPI Stephen Hemminger
@ 2007-10-18  0:21   ` Jeff Garzik
  2007-10-18  0:28   ` Benjamin Herrenschmidt
  1 sibling, 0 replies; 6+ messages in thread
From: Jeff Garzik @ 2007-10-18  0:21 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: David S. Miller, netdev

applied 1-2



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

* Re: [PATCH 1/2] napi_synchronize: waiting for NAPI
  2007-10-17 20:26 ` [PATCH 1/2] napi_synchronize: waiting for NAPI Stephen Hemminger
  2007-10-18  0:21   ` Jeff Garzik
@ 2007-10-18  0:28   ` Benjamin Herrenschmidt
  2007-10-18  1:26     ` Stephen Hemminger
  1 sibling, 1 reply; 6+ messages in thread
From: Benjamin Herrenschmidt @ 2007-10-18  0:28 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: David S. Miller, Jeff Garzik, netdev


On Wed, 2007-10-17 at 13:26 -0700, Stephen Hemminger wrote:
> plain text document attachment (napi-synchronize.patch)
> Some drivers with shared NAPI need a synchronization barrier.
> Also suggested by Benjamin Herrenschmidt for EMAC.
> 
> Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>

Just saw this patch, sorry, missed it. Same as you sent me on another
reply, I still think it needs the smp barrier. Can you have a look at
the one I posted today ?

Cheers,
Ben.



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

* Re: [PATCH 1/2] napi_synchronize: waiting for NAPI
  2007-10-18  0:28   ` Benjamin Herrenschmidt
@ 2007-10-18  1:26     ` Stephen Hemminger
  2007-10-18  1:33       ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 6+ messages in thread
From: Stephen Hemminger @ 2007-10-18  1:26 UTC (permalink / raw)
  To: benh; +Cc: David S. Miller, Jeff Garzik, netdev

On Thu, 18 Oct 2007 10:28:09 +1000
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:

> 
> On Wed, 2007-10-17 at 13:26 -0700, Stephen Hemminger wrote:
> > plain text document attachment (napi-synchronize.patch)
> > Some drivers with shared NAPI need a synchronization barrier.
> > Also suggested by Benjamin Herrenschmidt for EMAC.
> > 
> > Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
> 
> Just saw this patch, sorry, missed it. Same as you sent me on another
> reply, I still think it needs the smp barrier. Can you have a look at
> the one I posted today ?
> 
> Cheers,
> Ben.

Could you give a concrete example as to why it needs a smp barrier?
The test_bit is going to get a consistent result. Are you worried about
operations ordering before the test_bit()? In that case, one of those
smp_mb__before_xxx functions is probably what is needed.


-- 
Stephen Hemminger <shemminger@linux-foundation.org>

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

* Re: [PATCH 1/2] napi_synchronize: waiting for NAPI
  2007-10-18  1:26     ` Stephen Hemminger
@ 2007-10-18  1:33       ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 6+ messages in thread
From: Benjamin Herrenschmidt @ 2007-10-18  1:33 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: David S. Miller, Jeff Garzik, netdev


On Wed, 2007-10-17 at 18:26 -0700, Stephen Hemminger wrote:
> 
> Could you give a concrete example as to why it needs a smp barrier?
> The test_bit is going to get a consistent result. Are you worried about
> operations ordering before the test_bit()? In that case, one of those
> smp_mb__before_xxx functions is probably what is needed.

test_bit is just a read, without any ordering constraint. It can thus be
totally mixed with anything before.

we want to synchronize. Basically, make sure that whatever we did before
the call is visible to whatever we are synchronizing with (NAPI poll in
our case). That is, in our case, that a previous/concurrent NAPI poll
(that hasn't seen the effect of what we did before) is complete or any
new one will have seen that effect.

thus we need a barrier. At least a read barrier semantic to avoid the
test_bit to dance around and be speculated but I think a full barrier
also making sure that any previous store is visible before we preform
the read is also necessary in pretty much any usage scenario of this
function. I believe this is also a bug in synchronize_irq and possibly
even in napi_disable(). I sent a patch for synchronize_irq() a minute
ago.

Besides, it's not like this was a hot path :-)

Cheers,
Ben.



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

end of thread, other threads:[~2007-10-18  1:33 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20071017202640.171902388@linux-foundation.org>
2007-10-17 20:26 ` [PATCH 1/2] napi_synchronize: waiting for NAPI Stephen Hemminger
2007-10-18  0:21   ` Jeff Garzik
2007-10-18  0:28   ` Benjamin Herrenschmidt
2007-10-18  1:26     ` Stephen Hemminger
2007-10-18  1:33       ` Benjamin Herrenschmidt
2007-10-17 20:26 ` [PATCH 2/2] sky2: shutdown cleanup Stephen Hemminger

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).