Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-19 Thread Francois Romieu
Pavel Machek  :
[...]
> Considering the memory barriers... is something like this neccessary
> in the via-rhine ?

Yes.

> AFAICT... we need a barrier after making sure that descriptor is no
> longer owned by DMA (to make sure we don't get stale data in rest of
> descriptor)... and we need a barrier before giving the descriptor to
> the dma, to make sure DMA engine sees the complete update?

I would not expect stale data while processing a single transmit
descriptor as the transmit completion does not use the rest of the
descriptor at all in the via-rhine driver. However I agree that transmit
descriptors should be read by the cpu with adequate ordering so the
dma_rmb() should stay.

Same kind of narrative for dma_wmb rhine_rx (s/read/written/ and
s/cpu/device/).

> diff --git a/drivers/net/ethernet/via/via-rhine.c 
> b/drivers/net/ethernet/via/via-rhine.c
> index ba5c542..3806e72 100644
> --- a/drivers/net/ethernet/via/via-rhine.c
> +++ b/drivers/net/ethernet/via/via-rhine.c
[...]
> @@ -2061,6 +2062,7 @@ static int rhine_rx(struct net_device *dev, int limit)
>  
>   if (desc_status & DescOwn)
>   break;
> + dma_rmb();
>  

I agree with your explanation for this one (late vlan processing in a 
different word from the same descriptor).

-- 
Ueimor


Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-19 Thread Lino Sanfilippo
Hi,

On 18.12.2016 19:30, Pavel Machek wrote:
> Hi!
> 
>> > - e1efa87241272104d6a12c8b9fcdc4f62634d447
>> 
>> Yep, a sync of the dma descriptors before the hardware gets ownership of the 
>> tx tail
>> idx is missing in the stmmac, too.
> 
> I can reproduce failure with 4.4 fairly easily. I tried with dma_
> variant of barriers, and it failed, too
> 
> [ 1018.410012] stmmac: early irq
> [ 1023.939702] fpga_cmd_read:wait_event timed out!
> [ 1033.128692] [ cut here ]
> [ 1033.133329] WARNING: CPU: 0 PID: 0 at net/sched/sch_generic.c:303
> dev_watchdog+0x264/0x284()
> [ 1033.141748] NETDEV WATCHDOG: eth0 (socfpga-dwmac): transmit queue 0
> timed out
> [ 1033.148861] Modules linked in:

This watchdog warning clearly says that for some reason the tx queue was stopped
but never woken up in a certain timespan (5 sec in our case, which is a lot).

Does this occur after the queue has been stopped and woken up again a few times 
or
is it already the first time the queue is stopped (and never woken up)? 

Regards,
Lino





Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-19 Thread Pavel Machek
Hi!

> Lino, have you considered via-rhine.c since its "move work from irq to
> workqueue context" changes that started in
> 7ab87ff4c770eed71e3777936299292739fcd0fe [*] ?
> 
> It's a shameless plug - originated in r8169.c - but it should be rather
> close to what the sxgbe and friends require. Thought / opinion ?
> 
> [*] Including fixes/changes in:
> - 3a5a883a8a663b930908cae4abe5ec913b9b2fd2
> - e1efa87241272104d6a12c8b9fcdc4f62634d447
> - 810f19bcb862f8889b27e0c9d9eceac9593925dd
> - e45af497950a89459a0c4b13ffd91e1729fffef4
> - a926592f5e4e900f3fa903298c4619a131e60963
> - 559bcac35facfed49ab4f408e162971612dcfdf3

Considering the memory barriers... is something like this neccessary
in the via-rhine?

AFAICT... we need a barrier after making sure that descriptor is no
longer owned by DMA (to make sure we don't get stale data in rest of
descriptor)... and we need a barrier before giving the descriptor to
the dma, to make sure DMA engine sees the complete update?

Thanks,
Pavel

diff --git a/drivers/net/ethernet/via/via-rhine.c 
b/drivers/net/ethernet/via/via-rhine.c
index ba5c542..3806e72 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -1952,6 +1952,7 @@ static void rhine_tx(struct net_device *dev)
  entry, txstatus);
if (txstatus & DescOwn)
break;
+   dma_rmb();
skb = rp->tx_skbuff[entry];
if (txstatus & 0x8000) {
netif_dbg(rp, tx_done, dev,
@@ -2061,6 +2062,7 @@ static int rhine_rx(struct net_device *dev, int limit)
 
if (desc_status & DescOwn)
break;
+   dma_rmb();
 
netif_dbg(rp, rx_status, dev, "%s() status %08x\n", __func__,
  desc_status);
@@ -2146,6 +2148,7 @@ static int rhine_rx(struct net_device *dev, int limit)
u64_stats_update_end(>rx_stats.syncp);
}
 give_descriptor_to_nic:
+   dma_wmb();
desc->rx_status = cpu_to_le32(DescOwn);
entry = (++rp->cur_rx) % RX_RING_SIZE;
}

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


signature.asc
Description: Digital signature


Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-18 Thread Pavel Machek
Hi!

> > For the same reason it's broken if it races with the transmit path: it
> > can release driver resources while the transmit path uses these.
> > 
> > Btw the points below may not matter/hurt much for a proof a concept
> > but they would need to be addressed as well:
> > 1) unchecked (and avoidable) extra error paths due to stmmac_release()
> > 2) racy cancel_work_sync. Low probability as it is, an irq + error could
> >take place right after cancel_work_sync
> 
> It was indeed only meant as a proof of concept. Nevertheless the race is not 
> good, since one can run into it when faking the tx error for testings 
> purposes.
> So below is a slightly improved version of the restart handling.
> Its not meant as a final version either. But maybe we can use it as a starting
> point.

Certainly works better than version we currently have in tree. I'm
running it in a loop, and it survived 10 minutes of testing so
far. (Previous version killed the hardware at first iteration.)

> Again the patch is only compile tested.

Tested-by: Pavel Machek 

Thanks!
Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


signature.asc
Description: Digital signature


Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-18 Thread Pavel Machek
Hi!

> > - e1efa87241272104d6a12c8b9fcdc4f62634d447
> 
> Yep, a sync of the dma descriptors before the hardware gets ownership of the 
> tx tail
> idx is missing in the stmmac, too.

I can reproduce failure with 4.4 fairly easily. I tried with dma_
variant of barriers, and it failed, too

[ 1018.410012] stmmac: early irq
[ 1023.939702] fpga_cmd_read:wait_event timed out!
[ 1033.128692] [ cut here ]
[ 1033.133329] WARNING: CPU: 0 PID: 0 at net/sched/sch_generic.c:303
dev_watchdog+0x264/0x284()
[ 1033.141748] NETDEV WATCHDOG: eth0 (socfpga-dwmac): transmit queue 0
timed out
[ 1033.148861] Modules linked in:

Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


signature.asc
Description: Digital signature


Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-18 Thread Pavel Machek
Hi!

> > - e1efa87241272104d6a12c8b9fcdc4f62634d447
> 
> Yep, a sync of the dma descriptors before the hardware gets ownership of the 
> tx tail
> idx is missing in the stmmac, too. 

Thanks for the hint. Actually, the driver uses smp_wmb() which is
completely crazy, and probably misses rmb() in clean_tx, too. Anyway,
I did not notice there are dma_ variants, too... we clearly need them.

Thanks and best regards,
Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


signature.asc
Description: Digital signature


Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-18 Thread Lino Sanfilippo
Hi,

On 18.12.2016 01:15, Francois Romieu wrote:
> Pavel Machek  :
> [...]
>> Won't this up/down the interface, in a way userspace can observe?
> 
> It won't up/down the interface as it doesn't exactly mimic what the
> network code does (there's more than rtnl_lock).
> 

Right. Userspace wont see link down/up, but it will see carrier off/on.
But this is AFAIK acceptable for a rare situation like a tx error.

> For the same reason it's broken if it races with the transmit path: it
> can release driver resources while the transmit path uses these.
> 
> Btw the points below may not matter/hurt much for a proof a concept
> but they would need to be addressed as well:
> 1) unchecked (and avoidable) extra error paths due to stmmac_release()
> 2) racy cancel_work_sync. Low probability as it is, an irq + error could
>take place right after cancel_work_sync

It was indeed only meant as a proof of concept. Nevertheless the race is not 
good, since one can run into it when faking the tx error for testings purposes.
So below is a slightly improved version of the restart handling.
Its not meant as a final version either. But maybe we can use it as a starting
point.

> Lino, have you considered via-rhine.c since its "move work from irq to
> workqueue context" changes that started in
> 7ab87ff4c770eed71e3777936299292739fcd0fe [*] ?
> It's a shameless plug - originated in r8169.c - but it should be rather
> close to what the sxgbe and friends require. Thought / opinion ?
> 

Not really. There are a few drivers that I use to look into if I want to know
how certain things are done correctly (e.g the sky2 or the intel drivers) 
because
I think they are well implemented.
But you seem to have put some thoughts into various race condition problems
in the via-rhine driver and I can image that sxgbe and stmmac still have some
of these issues, too.

> [*] Including fixes/changes in:
> - 3a5a883a8a663b930908cae4abe5ec913b9b2fd2

Ok, the issues you fixed here are concerning the tx_curr and tx_dirty
pointers. For now this is not needed in stmmac and sxgbe since the
tx completion handlers in both drivers are not lock-free like in 
the via-rhine.c but are synchronized with xmit by means of the xmit_lock.

> - e1efa87241272104d6a12c8b9fcdc4f62634d447

Yep, a sync of the dma descriptors before the hardware gets ownership of the tx 
tail
idx is missing in the stmmac, too. 

> - 810f19bcb862f8889b27e0c9d9eceac9593925dd
> - e45af497950a89459a0c4b13ffd91e1729fffef4
> - a926592f5e4e900f3fa903298c4619a131e60963

I think we should use netif_tx_disable() instead of netif_stop_queue(), too, in 
case of restart to avoid a possible schedule of the xmit function while we 
restart. 
So this is also part of the new patch.

Again the patch is only compile tested.

Regards,
Lino

---
 drivers/net/ethernet/stmicro/stmmac/stmmac.h  |  1 +
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 95 +++
 2 files changed, 63 insertions(+), 33 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h 
b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index eab04ae..9c240d7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -131,6 +131,7 @@ struct stmmac_priv {
u32 rx_tail_addr;
u32 tx_tail_addr;
u32 mss;
+   struct work_struct tx_err_work;
 
 #ifdef CONFIG_DEBUG_FS
struct dentry *dbgfs_dir;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c 
b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 3e40578..5762750 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1403,37 +1403,6 @@ static inline void stmmac_disable_dma_irq(struct 
stmmac_priv *priv)
 }
 
 /**
- * stmmac_tx_err - to manage the tx error
- * @priv: driver private structure
- * Description: it cleans the descriptors and restarts the transmission
- * in case of transmission errors.
- */
-static void stmmac_tx_err(struct stmmac_priv *priv)
-{
-   int i;
-   netif_stop_queue(priv->dev);
-
-   priv->hw->dma->stop_tx(priv->ioaddr);
-   dma_free_tx_skbufs(priv);
-   for (i = 0; i < DMA_TX_SIZE; i++)
-   if (priv->extend_desc)
-   priv->hw->desc->init_tx_desc(>dma_etx[i].basic,
-priv->mode,
-(i == DMA_TX_SIZE - 1));
-   else
-   priv->hw->desc->init_tx_desc(>dma_tx[i],
-priv->mode,
-(i == DMA_TX_SIZE - 1));
-   priv->dirty_tx = 0;
-   priv->cur_tx = 0;
-   netdev_reset_queue(priv->dev);
-   priv->hw->dma->start_tx(priv->ioaddr);
-
-   priv->dev->stats.tx_errors++;
-   netif_wake_queue(priv->dev);
-}
-
-/**
  * stmmac_dma_interrupt - DMA ISR
  * @priv: driver 

Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-17 Thread Francois Romieu
Pavel Machek  :
[...]
> Won't this up/down the interface, in a way userspace can observe?

It won't up/down the interface as it doesn't exactly mimic what the
network code does (there's more than rtnl_lock).

For the same reason it's broken if it races with the transmit path: it
can release driver resources while the transmit path uses these.

Btw the points below may not matter/hurt much for a proof a concept
but they would need to be addressed as well:
1) unchecked (and avoidable) extra error paths due to stmmac_release()
2) racy cancel_work_sync. Low probability as it is, an irq + error could
   take place right after cancel_work_sync

Lino, have you considered via-rhine.c since its "move work from irq to
workqueue context" changes that started in
7ab87ff4c770eed71e3777936299292739fcd0fe [*] ?

It's a shameless plug - originated in r8169.c - but it should be rather
close to what the sxgbe and friends require. Thought / opinion ?

[*] Including fixes/changes in:
- 3a5a883a8a663b930908cae4abe5ec913b9b2fd2
- e1efa87241272104d6a12c8b9fcdc4f62634d447
- 810f19bcb862f8889b27e0c9d9eceac9593925dd
- e45af497950a89459a0c4b13ffd91e1729fffef4
- a926592f5e4e900f3fa903298c4619a131e60963
- 559bcac35facfed49ab4f408e162971612dcfdf3

-- 
Ueimor


Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-17 Thread Pavel Machek
On Thu 2016-12-15 23:33:22, Lino Sanfilippo wrote:
> On 15.12.2016 22:32, Lino Sanfilippo wrote:
> 
> > Ah ok. Then maybe priv->hw->dma->stop_tx() does not do the job correctly 
> > (stop the
> > tx path properly) and the HW is still active on the tx path while the tx 
> > buffers are
> > freed. OTOH stmmac_release() also stops the phy before the tx (and rx) 
> > paths are stopped.
> > Did you try to stop the phy fist in stmmac_tx_err_work(), too?
> > 
> > Regards,
> > Lino
> > 
> 
> And this is the "sledgehammer" approach: Do a complete shutdown and restart
> of the hardware in case of tx error (against net-next and only
>compile tested).

Wow, thanks a lot. I'll try to get the driver back to the non-working
state, and try it.

I believe I have some idea what is wrong there. (Missing memory barriers).

> +static void stmmac_tx_err_work(struct work_struct *work)
> +{
> + struct stmmac_priv *priv = container_of(work, struct stmmac_priv,
> + tx_err_work);
> + /* restart netdev */
> + rtnl_lock();
> + stmmac_release(priv->dev);
> + stmmac_open(priv->dev);
> + rtnl_unlock();
> +}

Won't this up/down the interface, in a way userspace can observe?

Best regards,
Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


signature.asc
Description: Digital signature


Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-15 Thread Lino Sanfilippo
On 15.12.2016 22:32, Lino Sanfilippo wrote:

> Ah ok. Then maybe priv->hw->dma->stop_tx() does not do the job correctly 
> (stop the
> tx path properly) and the HW is still active on the tx path while the tx 
> buffers are
> freed. OTOH stmmac_release() also stops the phy before the tx (and rx) paths 
> are stopped.
> Did you try to stop the phy fist in stmmac_tx_err_work(), too?
> 
> Regards,
> Lino
> 

And this is the "sledgehammer" approach: Do a complete shutdown and restart
of the hardware in case of tx error (against net-next and only compile tested).

>From 0eda87ce6cbc2fb6d25653f30121f30f89332199 Mon Sep 17 00:00:00 2001
From: Lino Sanfilippo 
Date: Thu, 15 Dec 2016 23:18:15 +0100
Subject: [PATCH] Sledgehammer

---
 drivers/net/ethernet/stmicro/stmmac/stmmac.h  |  1 +
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 70 ++-
 2 files changed, 31 insertions(+), 40 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index eab04ae..9c240d7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -131,6 +131,7 @@ struct stmmac_priv {
 	u32 rx_tail_addr;
 	u32 tx_tail_addr;
 	u32 mss;
+	struct work_struct tx_err_work;
 
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *dbgfs_dir;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 3e40578..7546574 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1403,37 +1403,6 @@ static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv)
 }
 
 /**
- * stmmac_tx_err - to manage the tx error
- * @priv: driver private structure
- * Description: it cleans the descriptors and restarts the transmission
- * in case of transmission errors.
- */
-static void stmmac_tx_err(struct stmmac_priv *priv)
-{
-	int i;
-	netif_stop_queue(priv->dev);
-
-	priv->hw->dma->stop_tx(priv->ioaddr);
-	dma_free_tx_skbufs(priv);
-	for (i = 0; i < DMA_TX_SIZE; i++)
-		if (priv->extend_desc)
-			priv->hw->desc->init_tx_desc(>dma_etx[i].basic,
-		 priv->mode,
-		 (i == DMA_TX_SIZE - 1));
-		else
-			priv->hw->desc->init_tx_desc(>dma_tx[i],
-		 priv->mode,
-		 (i == DMA_TX_SIZE - 1));
-	priv->dirty_tx = 0;
-	priv->cur_tx = 0;
-	netdev_reset_queue(priv->dev);
-	priv->hw->dma->start_tx(priv->ioaddr);
-
-	priv->dev->stats.tx_errors++;
-	netif_wake_queue(priv->dev);
-}
-
-/**
  * stmmac_dma_interrupt - DMA ISR
  * @priv: driver private structure
  * Description: this is the DMA ISR. It is called by the main ISR.
@@ -1466,7 +1435,7 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv)
 			priv->xstats.threshold = tc;
 		}
 	} else if (unlikely(status == tx_hard_error))
-		stmmac_tx_err(priv);
+		schedule_work(>tx_err_work);
 }
 
 /**
@@ -1870,13 +1839,7 @@ static int stmmac_open(struct net_device *dev)
 	return ret;
 }
 
-/**
- *  stmmac_release - close entry point of the driver
- *  @dev : device pointer.
- *  Description:
- *  This is the stop entry point of the driver.
- */
-static int stmmac_release(struct net_device *dev)
+static int stmmac_do_release(struct net_device *dev)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 
@@ -1919,10 +1882,36 @@ static int stmmac_release(struct net_device *dev)
 #endif
 
 	stmmac_release_ptp(priv);
+}
+
+/**
+ *  stmmac_release - close entry point of the driver
+ *  @dev : device pointer.
+ *  Description:
+ *  This is the stop entry point of the driver.
+ */
+static int stmmac_release(struct net_device *dev)
+{
+	struct stmmac_priv *priv = netdev_priv(dev);
+
+	cancel_work_sync(>tx_err_work);
+
+	stmmac_do_release(dev);
 
 	return 0;
 }
 
+static void stmmac_tx_err_work(struct work_struct *work)
+{
+	struct stmmac_priv *priv = container_of(work, struct stmmac_priv,
+		tx_err_work);
+	/* restart netdev */
+	rtnl_lock();
+	stmmac_release(priv->dev);
+	stmmac_open(priv->dev);
+	rtnl_unlock();
+}
+
 /**
  *  stmmac_tso_allocator - close entry point of the driver
  *  @priv: driver private structure
@@ -2688,7 +2677,7 @@ static void stmmac_tx_timeout(struct net_device *dev)
 	struct stmmac_priv *priv = netdev_priv(dev);
 
 	/* Clear Tx resources and restart transmitting again */
-	stmmac_tx_err(priv);
+	schedule_work(>tx_err_work);
 }
 
 /**
@@ -3338,6 +3327,7 @@ int stmmac_dvr_probe(struct device *device,
 	netif_napi_add(ndev, >napi, stmmac_poll, 64);
 
 	spin_lock_init(>lock);
+	INIT_WORK(>tx_err_work, stmmac_tx_err_work);
 
 	ret = register_netdev(ndev);
 	if (ret) {
-- 
1.9.1



Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-15 Thread Lino Sanfilippo
On 15.12.2016 22:03, Pavel Machek wrote:

> 
> I actually did experiment with adding locking there, too, and no, no
> luck. It seems stmmac_tx_err() is more broken than just locking.
> 

Ah ok. Then maybe priv->hw->dma->stop_tx() does not do the job correctly (stop 
the
tx path properly) and the HW is still active on the tx path while the tx 
buffers are
freed. OTOH stmmac_release() also stops the phy before the tx (and rx) paths 
are stopped.
Did you try to stop the phy fist in stmmac_tx_err_work(), too?

Regards,
Lino



Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-15 Thread Pavel Machek
Hi!

> sorry for the late reply.

No problem. Thanks for the help.

> On 11.12.2016 21:11, Pavel Machek wrote:
> > 
> > Do you understand what stmmac_tx_err(priv); is supposed to do? In
> > particular, if it is called while the driver is working ok -- should
> > the driver survive that?
> 
> As far as I understood it is supposed to fixup an errorneous tx path, e.g. a
> missing tx completion for transmitted frames.
> 
> Some drivers do this by restarting only the HW parts responsible for tx, some
> others by restarting the complete hardware. 
> But IMO it should also be ok to be called if the HW is still working fine.
> 
> > Because it does not currently, and I don't know how to test that
> > code. Unplugging the cable does not provoke that.
> > 
> > I tried
> > 
> > } else if (unlikely(status == tx_hard_error))
> > stmmac_tx_err(priv);
> > +
> > +   {
> > +   static int i;
> > +   i++;
> > +   if (i==1000) {
> > +   i = 0;
> > +   printk("Simulated error\n");
> > +   stmmac_tx_err(priv);
> > +   }
> > +   }
> >  }
> > 
> 
> Ok, there is this race that Francois mentioned so it is not surprising that
> the driver does not survive the call of stmmac_tx_err() as it is called now.
> Thats why I suggested to do a proper shutdown and restart of the tx path to
> avoid the race.

I actually did experiment with adding locking there, too, and no, no
luck. It seems stmmac_tx_err() is more broken than just locking.

Best regards,
Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


signature.asc
Description: Digital signature


Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-15 Thread Lino Sanfilippo
Hi Pavel,

sorry for the late reply.

On 11.12.2016 21:11, Pavel Machek wrote:
> 
> Do you understand what stmmac_tx_err(priv); is supposed to do? In
> particular, if it is called while the driver is working ok -- should
> the driver survive that?

As far as I understood it is supposed to fixup an errorneous tx path, e.g. a
missing tx completion for transmitted frames.

Some drivers do this by restarting only the HW parts responsible for tx, some
others by restarting the complete hardware. 
But IMO it should also be ok to be called if the HW is still working fine.

> Because it does not currently, and I don't know how to test that
> code. Unplugging the cable does not provoke that.
> 
> I tried
> 
> } else if (unlikely(status == tx_hard_error))
> stmmac_tx_err(priv);
> +
> +   {
> +   static int i;
> +   i++;
> +   if (i==1000) {
> +   i = 0;
> +   printk("Simulated error\n");
> +   stmmac_tx_err(priv);
> +   }
> +   }
>  }
> 

Ok, there is this race that Francois mentioned so it is not surprising that
the driver does not survive the call of stmmac_tx_err() as it is called now.
Thats why I suggested to do a proper shutdown and restart of the tx path to
avoid the race.

Regards,
Lino





Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-11 Thread Pavel Machek
Hi!

> On 09.12.2016 12:21, Pavel Machek wrote:
> > On Fri 2016-12-09 00:19:43, Francois Romieu wrote:
> >> Lino Sanfilippo  :
> >> [...]
> >> > OTOH Pavel said that he actually could produce a deadlock. Now I wonder 
> >> > if
> >> > this is caused by that locking scheme (in a way I have not figured out 
> >> > yet)
> >> > or if it is a different issue.
> >> 
> >> stmmac_tx_err races with stmmac_xmit.
> > 
> > Umm, yes, that looks real.
> > 
> > And that means that removing tx_lock will not be completely trivial
> > :-(. Lino, any ideas there?
> > 
> 
> Ok, the race is there but it looks like a problem that is not related to 
> the use or removal of the private lock.

Well, removal of the private lock will make it trickier to fix :-(.

> By a glimpse into other drivers (e.g sky2 or e1000), a possible way to handle 
> a 
> tx error is to start a separate task and restart the tx path in that task 
> instead
> the irq handler (or timer in case of the watchdog).
> 
> In that task we could do:
> 1. deactivate napi
> 2. deactivate irqs
> 3. wait for running napi/irqs do complete (_sync)
> 4. call stmmac_tx_err()
> 5. reenable napi
> 6. reenable irqs
> 
> We have to ensure that no xmit() is executing while stmmac_tx_err() does the 
> cleanup,
> so stmmac_tx_err() should IMO rather call netif_tx_disable() instead of 
> netif_stop_queue()
> (the former grabs the xmit lock before it sets __QUEUE_STATE_DRV_XOFF to 
> disable
> the queue).

Do you understand what stmmac_tx_err(priv); is supposed to do? In
particular, if it is called while the driver is working ok -- should
the driver survive that?

Because it does not currently, and I don't know how to test that
code. Unplugging the cable does not provoke that.

I tried

} else if (unlikely(status == tx_hard_error))
stmmac_tx_err(priv);
+
+   {
+   static int i;
+   i++;
+   if (i==1000) {
+   i = 0;
+   printk("Simulated error\n");
+   stmmac_tx_err(priv);
+   }
+   }
 }

but the driver does not survive that :-(.

Best regards,
Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


signature.asc
Description: Digital signature


Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-09 Thread Lino Sanfilippo
Hi,

On 09.12.2016 12:21, Pavel Machek wrote:
> On Fri 2016-12-09 00:19:43, Francois Romieu wrote:
>> Lino Sanfilippo  :
>> [...]
>> > OTOH Pavel said that he actually could produce a deadlock. Now I wonder if
>> > this is caused by that locking scheme (in a way I have not figured out yet)
>> > or if it is a different issue.
>> 
>> stmmac_tx_err races with stmmac_xmit.
> 
> Umm, yes, that looks real.
> 
> And that means that removing tx_lock will not be completely trivial
> :-(. Lino, any ideas there?
> 

Ok, the race is there but it looks like a problem that is not related to 
the use or removal of the private lock.
By a glimpse into other drivers (e.g sky2 or e1000), a possible way to handle a 
tx error is to start a separate task and restart the tx path in that task 
instead
the irq handler (or timer in case of the watchdog).

In that task we could do:
1. deactivate napi
2. deactivate irqs
3. wait for running napi/irqs do complete (_sync)
4. call stmmac_tx_err()
5. reenable napi
6. reenable irqs

We have to ensure that no xmit() is executing while stmmac_tx_err() does the 
cleanup,
so stmmac_tx_err() should IMO rather call netif_tx_disable() instead of 
netif_stop_queue()
(the former grabs the xmit lock before it sets __QUEUE_STATE_DRV_XOFF to disable
the queue).

Regards,
Lino


Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-09 Thread Pavel Machek
On Fri 2016-12-09 00:19:43, Francois Romieu wrote:
> Lino Sanfilippo  :
> [...]
> > OTOH Pavel said that he actually could produce a deadlock. Now I wonder if
> > this is caused by that locking scheme (in a way I have not figured out yet)
> > or if it is a different issue.
> 
> stmmac_tx_err races with stmmac_xmit.

Umm, yes, that looks real.

And that means that removing tx_lock will not be completely trivial
:-(. Lino, any ideas there?

netif_tx_lock_irqsave() would help, but afaict that one does not
exist.

Plus, does someone know how to trigger the status == tx_hard_error? I
tried powering down the switch, but that did not do it.

Thanks, Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


signature.asc
Description: Digital signature


Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-08 Thread Francois Romieu
Lino Sanfilippo  :
[...]
> OTOH Pavel said that he actually could produce a deadlock. Now I wonder if
> this is caused by that locking scheme (in a way I have not figured out yet)
> or if it is a different issue.

stmmac_tx_err races with stmmac_xmit.

-- 
Ueimor


Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-08 Thread Lino Sanfilippo
On 08.12.2016 23:18, Pavel Machek wrote:
> On Thu 2016-12-08 23:12:10, Lino Sanfilippo wrote:
>> Hi,
>> 
>> On 08.12.2016 22:54, Pavel Machek wrote:
>> > On Thu 2016-12-08 21:32:12, Lino Sanfilippo wrote:
>> >> Hi,
>> >> 
>> >> On 08.12.2016 00:15, Francois Romieu wrote:
>> >> > Lino Sanfilippo  :
>> >> >> The driver uses a private lock for synchronization between the xmit
>> >> >> function and the xmit completion handler, but since the NETIF_F_LLTX 
>> >> >> flag
>> >> >> is not set, the xmit function is also called with the xmit_lock held.
>> >> >> 
>> >> >> On the other hand the xmit completion handler first takes the private 
>> >> >> lock
>> >> >> and (in case that the tx queue has been stopped) the xmit_lock, leading
>> >> >> to a reverse locking order and the potential danger of a deadlock.
>> >> > 
>> >> > netif_tx_stop_queue is used by:
>> >> > 1. xmit function before releasing lock and returning.
>> >> > 2. sxgbe_restart_tx_queue()
>> >> ><- sxgbe_tx_interrupt
>> >> ><- sxgbe_reset_all_tx_queues()
>> >> >   <- sxgbe_tx_timeout()
>> >> > 
>> >> > Given xmit won't be called again until tx queue is enabled, it's not 
>> >> > clear
>> >> > how a deadlock could happen due to #1.
>> >> > 
>> >> 
>> >> 
>> >> After spending more thoughts on this I tend to agree with you. Yes, we 
>> >> have the
>> >> different locking order for the xmit_lock and the private lock in two 
>> >> concurrent
>> >> threads. And one of the first things one learns about locking is that 
>> >> this is a
>> >> good way to create a deadlock sooner or later. But in our case the 
>> >> deadlock 
>> >> can only occur if the xmit function and the tx completion handler 
>> >> perceive different
>> >>  states for the tx queue, or to be more specific: 
>> >> the completion handler sees the tx queue in state "stopped" while the 
>> >> xmit handler 
>> >> sees it in state "running" at the same time. Only then both functions 
>> >> would try to
>> >> take both locks, which could lead to a deadlock.
>> >> 
>> >> OTOH Pavel said that he actually could produce a deadlock. Now I wonder 
>> >> if this is caused
>> >> by that locking scheme (in a way I have not figured out yet) or if it is 
>> >> a different issue.
>> > 
>> > Pavel has some problems, but that's on different hardware.. and it is
>> > possible that it is deadlock (or something else) somewhere else.
>> > 
>> 
>> Right, it is different hardware. But the locking situation in xmit function 
>> and tx completion handler
>> is very similar in both drivers. So if a deadlock is not possible in sxgbe 
>> it should 
>> also not be possible in stmmac (at least not due to the different locking 
>> order). 
>> So maybe there is no real issue that we could fix with removing the private 
>> lock and we should
>> keep it as it is.
> 
> Well.. the locking is pretty confused there. Having private lock that
> mirrors lock from network layer is confusing and ugly... that should
> be reason to fix it.
>   Pavel
> 

Ok. Then I will resend the patches for both drivers with a different (less 
dramatic) commit message
in which the change is not longer described as a fix for deadlock but rather as 
a code 
cleanup/improvement, ok?

Regards,
Lino



Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-08 Thread Pavel Machek
On Thu 2016-12-08 23:12:10, Lino Sanfilippo wrote:
> Hi,
> 
> On 08.12.2016 22:54, Pavel Machek wrote:
> > On Thu 2016-12-08 21:32:12, Lino Sanfilippo wrote:
> >> Hi,
> >> 
> >> On 08.12.2016 00:15, Francois Romieu wrote:
> >> > Lino Sanfilippo  :
> >> >> The driver uses a private lock for synchronization between the xmit
> >> >> function and the xmit completion handler, but since the NETIF_F_LLTX 
> >> >> flag
> >> >> is not set, the xmit function is also called with the xmit_lock held.
> >> >> 
> >> >> On the other hand the xmit completion handler first takes the private 
> >> >> lock
> >> >> and (in case that the tx queue has been stopped) the xmit_lock, leading
> >> >> to a reverse locking order and the potential danger of a deadlock.
> >> > 
> >> > netif_tx_stop_queue is used by:
> >> > 1. xmit function before releasing lock and returning.
> >> > 2. sxgbe_restart_tx_queue()
> >> ><- sxgbe_tx_interrupt
> >> ><- sxgbe_reset_all_tx_queues()
> >> >   <- sxgbe_tx_timeout()
> >> > 
> >> > Given xmit won't be called again until tx queue is enabled, it's not 
> >> > clear
> >> > how a deadlock could happen due to #1.
> >> > 
> >> 
> >> 
> >> After spending more thoughts on this I tend to agree with you. Yes, we 
> >> have the
> >> different locking order for the xmit_lock and the private lock in two 
> >> concurrent
> >> threads. And one of the first things one learns about locking is that this 
> >> is a
> >> good way to create a deadlock sooner or later. But in our case the 
> >> deadlock 
> >> can only occur if the xmit function and the tx completion handler perceive 
> >> different
> >>  states for the tx queue, or to be more specific: 
> >> the completion handler sees the tx queue in state "stopped" while the xmit 
> >> handler 
> >> sees it in state "running" at the same time. Only then both functions 
> >> would try to
> >> take both locks, which could lead to a deadlock.
> >> 
> >> OTOH Pavel said that he actually could produce a deadlock. Now I wonder if 
> >> this is caused
> >> by that locking scheme (in a way I have not figured out yet) or if it is a 
> >> different issue.
> > 
> > Pavel has some problems, but that's on different hardware.. and it is
> > possible that it is deadlock (or something else) somewhere else.
> > 
> 
> Right, it is different hardware. But the locking situation in xmit function 
> and tx completion handler
> is very similar in both drivers. So if a deadlock is not possible in sxgbe it 
> should 
> also not be possible in stmmac (at least not due to the different locking 
> order). 
> So maybe there is no real issue that we could fix with removing the private 
> lock and we should
> keep it as it is.

Well.. the locking is pretty confused there. Having private lock that
mirrors lock from network layer is confusing and ugly... that should
be reason to fix it.
Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


signature.asc
Description: Digital signature


Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-08 Thread Lino Sanfilippo
Hi,

On 08.12.2016 22:54, Pavel Machek wrote:
> On Thu 2016-12-08 21:32:12, Lino Sanfilippo wrote:
>> Hi,
>> 
>> On 08.12.2016 00:15, Francois Romieu wrote:
>> > Lino Sanfilippo  :
>> >> The driver uses a private lock for synchronization between the xmit
>> >> function and the xmit completion handler, but since the NETIF_F_LLTX flag
>> >> is not set, the xmit function is also called with the xmit_lock held.
>> >> 
>> >> On the other hand the xmit completion handler first takes the private lock
>> >> and (in case that the tx queue has been stopped) the xmit_lock, leading
>> >> to a reverse locking order and the potential danger of a deadlock.
>> > 
>> > netif_tx_stop_queue is used by:
>> > 1. xmit function before releasing lock and returning.
>> > 2. sxgbe_restart_tx_queue()
>> ><- sxgbe_tx_interrupt
>> ><- sxgbe_reset_all_tx_queues()
>> >   <- sxgbe_tx_timeout()
>> > 
>> > Given xmit won't be called again until tx queue is enabled, it's not clear
>> > how a deadlock could happen due to #1.
>> > 
>> 
>> 
>> After spending more thoughts on this I tend to agree with you. Yes, we have 
>> the
>> different locking order for the xmit_lock and the private lock in two 
>> concurrent
>> threads. And one of the first things one learns about locking is that this 
>> is a
>> good way to create a deadlock sooner or later. But in our case the deadlock 
>> can only occur if the xmit function and the tx completion handler perceive 
>> different
>>  states for the tx queue, or to be more specific: 
>> the completion handler sees the tx queue in state "stopped" while the xmit 
>> handler 
>> sees it in state "running" at the same time. Only then both functions would 
>> try to
>> take both locks, which could lead to a deadlock.
>> 
>> OTOH Pavel said that he actually could produce a deadlock. Now I wonder if 
>> this is caused
>> by that locking scheme (in a way I have not figured out yet) or if it is a 
>> different issue.
> 
> Pavel has some problems, but that's on different hardware.. and it is
> possible that it is deadlock (or something else) somewhere else.
> 

Right, it is different hardware. But the locking situation in xmit function and 
tx completion handler
is very similar in both drivers. So if a deadlock is not possible in sxgbe it 
should 
also not be possible in stmmac (at least not due to the different locking 
order). 
So maybe there is no real issue that we could fix with removing the private 
lock and we should
keep it as it is.

Regards,
Lino


Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-08 Thread Pavel Machek
On Thu 2016-12-08 21:32:12, Lino Sanfilippo wrote:
> Hi,
> 
> On 08.12.2016 00:15, Francois Romieu wrote:
> > Lino Sanfilippo  :
> >> The driver uses a private lock for synchronization between the xmit
> >> function and the xmit completion handler, but since the NETIF_F_LLTX flag
> >> is not set, the xmit function is also called with the xmit_lock held.
> >> 
> >> On the other hand the xmit completion handler first takes the private lock
> >> and (in case that the tx queue has been stopped) the xmit_lock, leading
> >> to a reverse locking order and the potential danger of a deadlock.
> > 
> > netif_tx_stop_queue is used by:
> > 1. xmit function before releasing lock and returning.
> > 2. sxgbe_restart_tx_queue()
> ><- sxgbe_tx_interrupt
> ><- sxgbe_reset_all_tx_queues()
> >   <- sxgbe_tx_timeout()
> > 
> > Given xmit won't be called again until tx queue is enabled, it's not clear
> > how a deadlock could happen due to #1.
> > 
> 
> 
> After spending more thoughts on this I tend to agree with you. Yes, we have 
> the
> different locking order for the xmit_lock and the private lock in two 
> concurrent
> threads. And one of the first things one learns about locking is that this is 
> a
> good way to create a deadlock sooner or later. But in our case the deadlock 
> can only occur if the xmit function and the tx completion handler perceive 
> different
>  states for the tx queue, or to be more specific: 
> the completion handler sees the tx queue in state "stopped" while the xmit 
> handler 
> sees it in state "running" at the same time. Only then both functions would 
> try to
> take both locks, which could lead to a deadlock.
> 
> OTOH Pavel said that he actually could produce a deadlock. Now I wonder if 
> this is caused
> by that locking scheme (in a way I have not figured out yet) or if it is a 
> different issue.

Pavel has some problems, but that's on different hardware.. and it is
possible that it is deadlock (or something else) somewhere else.

Best regards,
Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


signature.asc
Description: Digital signature


Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-08 Thread Lino Sanfilippo
Hi,

On 08.12.2016 00:15, Francois Romieu wrote:
> Lino Sanfilippo  :
>> The driver uses a private lock for synchronization between the xmit
>> function and the xmit completion handler, but since the NETIF_F_LLTX flag
>> is not set, the xmit function is also called with the xmit_lock held.
>> 
>> On the other hand the xmit completion handler first takes the private lock
>> and (in case that the tx queue has been stopped) the xmit_lock, leading
>> to a reverse locking order and the potential danger of a deadlock.
> 
> netif_tx_stop_queue is used by:
> 1. xmit function before releasing lock and returning.
> 2. sxgbe_restart_tx_queue()
><- sxgbe_tx_interrupt
><- sxgbe_reset_all_tx_queues()
>   <- sxgbe_tx_timeout()
> 
> Given xmit won't be called again until tx queue is enabled, it's not clear
> how a deadlock could happen due to #1.
> 


After spending more thoughts on this I tend to agree with you. Yes, we have the
different locking order for the xmit_lock and the private lock in two concurrent
threads. And one of the first things one learns about locking is that this is a
good way to create a deadlock sooner or later. But in our case the deadlock 
can only occur if the xmit function and the tx completion handler perceive 
different
 states for the tx queue, or to be more specific: 
the completion handler sees the tx queue in state "stopped" while the xmit 
handler 
sees it in state "running" at the same time. Only then both functions would try 
to
take both locks, which could lead to a deadlock.

OTOH Pavel said that he actually could produce a deadlock. Now I wonder if this 
is caused
by that locking scheme (in a way I have not figured out yet) or if it is a 
different issue.

Regards,
Lino


Re: [PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-07 Thread Francois Romieu
Lino Sanfilippo  :
> The driver uses a private lock for synchronization between the xmit
> function and the xmit completion handler, but since the NETIF_F_LLTX flag
> is not set, the xmit function is also called with the xmit_lock held.
> 
> On the other hand the xmit completion handler first takes the private lock
> and (in case that the tx queue has been stopped) the xmit_lock, leading
> to a reverse locking order and the potential danger of a deadlock.

netif_tx_stop_queue is used by:
1. xmit function before releasing lock and returning.
2. sxgbe_restart_tx_queue()
   <- sxgbe_tx_interrupt
   <- sxgbe_reset_all_tx_queues()
  <- sxgbe_tx_timeout()

Given xmit won't be called again until tx queue is enabled, it's not clear
how a deadlock could happen due to #1.

Regardless of deadlocks anywhere else, #2 has some serious problem due to
the lack of exclusion between the tx queue restart handler and the xmit
handler.

-- 
Ueimor


[PATCH 1/2] net: ethernet: sxgbe: remove private tx queue lock

2016-12-07 Thread Lino Sanfilippo
The driver uses a private lock for synchronization between the xmit
function and the xmit completion handler, but since the NETIF_F_LLTX flag
is not set, the xmit function is also called with the xmit_lock held.

On the other hand the xmit completion handler first takes the private lock
and (in case that the tx queue has been stopped) the xmit_lock, leading
to a reverse locking order and the potential danger of a deadlock.

Fix this by removing the private lock completely and synchronizing the xmit
function and completion handler solely by means of the xmit_lock. By doing
this also remove the now unnecessary double check for a stopped tx queue.

Signed-off-by: Lino Sanfilippo 
---
 drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h |  1 -
 drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c   | 27 +--
 2 files changed, 6 insertions(+), 22 deletions(-)

diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h 
b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
index 5cb51b6..c61f260 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
@@ -384,7 +384,6 @@ struct sxgbe_tx_queue {
dma_addr_t *tx_skbuff_dma;
struct sk_buff **tx_skbuff;
struct timer_list txtimer;
-   spinlock_t tx_lock; /* lock for tx queues */
unsigned int cur_tx;
unsigned int dirty_tx;
u32 tx_count_frames;
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c 
b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index ea44a24..22d3b0b 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -426,9 +426,6 @@ static int init_tx_ring(struct device *dev, u8 queue_no,
tx_ring->dirty_tx = 0;
tx_ring->cur_tx = 0;
 
-   /* initialise TX queue lock */
-   spin_lock_init(_ring->tx_lock);
-
return 0;
 
 dmamem_err:
@@ -743,7 +740,7 @@ static void sxgbe_tx_queue_clean(struct sxgbe_tx_queue 
*tqueue)
 
dev_txq = netdev_get_tx_queue(priv->dev, queue_no);
 
-   spin_lock(>tx_lock);
+   __netif_tx_lock(dev_txq, smp_processor_id());
 
priv->xstats.tx_clean++;
while (tqueue->dirty_tx != tqueue->cur_tx) {
@@ -781,18 +778,13 @@ static void sxgbe_tx_queue_clean(struct sxgbe_tx_queue 
*tqueue)
 
/* wake up queue */
if (unlikely(netif_tx_queue_stopped(dev_txq) &&
-sxgbe_tx_avail(tqueue, tx_rsize) > SXGBE_TX_THRESH(priv))) 
{
-   netif_tx_lock(priv->dev);
-   if (netif_tx_queue_stopped(dev_txq) &&
-   sxgbe_tx_avail(tqueue, tx_rsize) > SXGBE_TX_THRESH(priv)) {
-   if (netif_msg_tx_done(priv))
-   pr_debug("%s: restart transmit\n", __func__);
-   netif_tx_wake_queue(dev_txq);
-   }
-   netif_tx_unlock(priv->dev);
+   sxgbe_tx_avail(tqueue, tx_rsize) > SXGBE_TX_THRESH(priv))) {
+   if (netif_msg_tx_done(priv))
+   pr_debug("%s: restart transmit\n", __func__);
+   netif_tx_wake_queue(dev_txq);
}
 
-   spin_unlock(>tx_lock);
+   __netif_tx_unlock(dev_txq);
 }
 
 /**
@@ -1304,9 +1296,6 @@ static netdev_tx_t sxgbe_xmit(struct sk_buff *skb, struct 
net_device *dev)
  tqueue->hwts_tx_en)))
ctxt_desc_req = 1;
 
-   /* get the spinlock */
-   spin_lock(>tx_lock);
-
if (priv->tx_path_in_lpi_mode)
sxgbe_disable_eee_mode(priv);
 
@@ -1316,8 +1305,6 @@ static netdev_tx_t sxgbe_xmit(struct sk_buff *skb, struct 
net_device *dev)
netdev_err(dev, "%s: Tx Ring is full when %d queue is 
awake\n",
   __func__, txq_index);
}
-   /* release the spin lock in case of BUSY */
-   spin_unlock(>tx_lock);
return NETDEV_TX_BUSY;
}
 
@@ -1436,8 +1423,6 @@ static netdev_tx_t sxgbe_xmit(struct sk_buff *skb, struct 
net_device *dev)
 
priv->hw->dma->enable_dma_transmission(priv->ioaddr, txq_index);
 
-   spin_unlock(>tx_lock);
-
return NETDEV_TX_OK;
 }
 
-- 
1.9.1