提交 481cea4a 编写于 作者: S Stephen Hemminger 提交者: David S. Miller

sky2: lock less transmit completion

Transmit completion can safely run lockless against transmit start.
In the normal case, completion is done from NAPI and only looks
at elements that are at the tail of the ring.  When doing shutdown
or reset, the transmiter should be completely block by NAPI disable
and blocking of transmit queue. 

Based on earlier work by Mike McCormack.
Signed-off-by: NStephen Hemminger <shemminger@vyatta.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 af18d8b8
...@@ -1741,8 +1741,12 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) ...@@ -1741,8 +1741,12 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
/* /*
* Free ring elements from starting at tx_cons until "done" * Free ring elements from starting at tx_cons until "done"
* *
* NB: the hardware will tell us about partial completion of multi-part * NB:
* 1. The hardware will tell us about partial completion of multi-part
* buffers so make sure not to free skb to early. * buffers so make sure not to free skb to early.
* 2. This may run in parallel start_xmit because the it only
* looks at the tail of the queue of FIFO (tx_cons), not
* the head (tx_prod)
*/ */
static void sky2_tx_complete(struct sky2_port *sky2, u16 done) static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
{ {
...@@ -1800,16 +1804,6 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) ...@@ -1800,16 +1804,6 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
netif_wake_queue(dev); netif_wake_queue(dev);
} }
/* Cleanup all untransmitted buffers, assume transmitter not running */
static void sky2_tx_clean(struct net_device *dev)
{
struct sky2_port *sky2 = netdev_priv(dev);
netif_tx_lock_bh(dev);
sky2_tx_complete(sky2, sky2->tx_prod);
netif_tx_unlock_bh(dev);
}
static void sky2_tx_reset(struct sky2_hw *hw, unsigned port) static void sky2_tx_reset(struct sky2_hw *hw, unsigned port)
{ {
/* Disable Force Sync bit and Enable Alloc bit */ /* Disable Force Sync bit and Enable Alloc bit */
...@@ -1901,7 +1895,9 @@ static int sky2_down(struct net_device *dev) ...@@ -1901,7 +1895,9 @@ static int sky2_down(struct net_device *dev)
sky2_tx_reset(hw, port); sky2_tx_reset(hw, port);
sky2_tx_clean(dev); /* Free any pending frames stuck in HW queue */
sky2_tx_complete(sky2, sky2->tx_prod);
sky2_rx_clean(sky2); sky2_rx_clean(sky2);
pci_free_consistent(hw->pdev, RX_LE_BYTES, pci_free_consistent(hw->pdev, RX_LE_BYTES,
...@@ -2378,11 +2374,8 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) ...@@ -2378,11 +2374,8 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
{ {
struct sky2_port *sky2 = netdev_priv(dev); struct sky2_port *sky2 = netdev_priv(dev);
if (likely(netif_running(dev) && !sky2->restarting)) { if (likely(netif_running(dev) && !sky2->restarting))
netif_tx_lock(dev);
sky2_tx_complete(sky2, last); sky2_tx_complete(sky2, last);
netif_tx_unlock(dev);
}
} }
static inline void sky2_skb_rx(const struct sky2_port *sky2, static inline void sky2_skb_rx(const struct sky2_port *sky2,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册