diff options
author | Stephen Hemminger <shemminger@osdl.org> | 2006-09-26 14:57:42 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-09-27 17:56:31 -0400 |
commit | 2bb8c26242c2393b097a993ffe9b003ec9b85395 (patch) | |
tree | 3d800c046bbf663a31038605eb9d849b85b2eb66 /drivers | |
parent | 291ea6142b94cc3e3ae2216d3937a78697447471 (diff) |
[PATCH] sky2: use netif_tx_lock instead of LLTX
Use the netdevice transmit lock via netif_tx_lock rather than putting
lock in device specific code and using lockless transmit. The code is
cleaner using netif_tx_lock, and the performance is same.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/sky2.c | 57 | ||||
-rw-r--r-- | drivers/net/sky2.h | 1 |
2 files changed, 17 insertions, 41 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 64af764d0087..c83d7262a5a8 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -942,13 +942,13 @@ static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp | |||
942 | struct sky2_hw *hw = sky2->hw; | 942 | struct sky2_hw *hw = sky2->hw; |
943 | u16 port = sky2->port; | 943 | u16 port = sky2->port; |
944 | 944 | ||
945 | spin_lock_bh(&sky2->tx_lock); | 945 | netif_tx_lock_bh(dev); |
946 | 946 | ||
947 | sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_ON); | 947 | sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_ON); |
948 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_ON); | 948 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_ON); |
949 | sky2->vlgrp = grp; | 949 | sky2->vlgrp = grp; |
950 | 950 | ||
951 | spin_unlock_bh(&sky2->tx_lock); | 951 | netif_tx_unlock_bh(dev); |
952 | } | 952 | } |
953 | 953 | ||
954 | static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | 954 | static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) |
@@ -957,14 +957,14 @@ static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | |||
957 | struct sky2_hw *hw = sky2->hw; | 957 | struct sky2_hw *hw = sky2->hw; |
958 | u16 port = sky2->port; | 958 | u16 port = sky2->port; |
959 | 959 | ||
960 | spin_lock_bh(&sky2->tx_lock); | 960 | netif_tx_lock_bh(dev); |
961 | 961 | ||
962 | sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_OFF); | 962 | sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_OFF); |
963 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_OFF); | 963 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_OFF); |
964 | if (sky2->vlgrp) | 964 | if (sky2->vlgrp) |
965 | sky2->vlgrp->vlan_devices[vid] = NULL; | 965 | sky2->vlgrp->vlan_devices[vid] = NULL; |
966 | 966 | ||
967 | spin_unlock_bh(&sky2->tx_lock); | 967 | netif_tx_unlock_bh(dev); |
968 | } | 968 | } |
969 | #endif | 969 | #endif |
970 | 970 | ||
@@ -1202,8 +1202,6 @@ static unsigned tx_le_req(const struct sk_buff *skb) | |||
1202 | * A single packet can generate multiple list elements, and | 1202 | * A single packet can generate multiple list elements, and |
1203 | * the number of ring elements will probably be less than the number | 1203 | * the number of ring elements will probably be less than the number |
1204 | * of list elements used. | 1204 | * of list elements used. |
1205 | * | ||
1206 | * No BH disabling for tx_lock here (like tg3) | ||
1207 | */ | 1205 | */ |
1208 | static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | 1206 | static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) |
1209 | { | 1207 | { |
@@ -1217,27 +1215,8 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1217 | u16 mss; | 1215 | u16 mss; |
1218 | u8 ctrl; | 1216 | u8 ctrl; |
1219 | 1217 | ||
1220 | /* No BH disabling for tx_lock here. We are running in BH disabled | 1218 | if (unlikely(tx_avail(sky2) < tx_le_req(skb))) |
1221 | * context and TX reclaim runs via poll inside of a software | 1219 | return NETDEV_TX_BUSY; |
1222 | * interrupt, and no related locks in IRQ processing. | ||
1223 | */ | ||
1224 | if (!spin_trylock(&sky2->tx_lock)) | ||
1225 | return NETDEV_TX_LOCKED; | ||
1226 | |||
1227 | if (unlikely(tx_avail(sky2) < tx_le_req(skb))) { | ||
1228 | /* There is a known but harmless race with lockless tx | ||
1229 | * and netif_stop_queue. | ||
1230 | */ | ||
1231 | if (!netif_queue_stopped(dev)) { | ||
1232 | netif_stop_queue(dev); | ||
1233 | if (net_ratelimit()) | ||
1234 | printk(KERN_WARNING PFX "%s: ring full when queue awake!\n", | ||
1235 | dev->name); | ||
1236 | } | ||
1237 | spin_unlock(&sky2->tx_lock); | ||
1238 | |||
1239 | return NETDEV_TX_BUSY; | ||
1240 | } | ||
1241 | 1220 | ||
1242 | if (unlikely(netif_msg_tx_queued(sky2))) | 1221 | if (unlikely(netif_msg_tx_queued(sky2))) |
1243 | printk(KERN_DEBUG "%s: tx queued, slot %u, len %d\n", | 1222 | printk(KERN_DEBUG "%s: tx queued, slot %u, len %d\n", |
@@ -1352,8 +1331,6 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1352 | 1331 | ||
1353 | sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod); | 1332 | sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod); |
1354 | 1333 | ||
1355 | spin_unlock(&sky2->tx_lock); | ||
1356 | |||
1357 | dev->trans_start = jiffies; | 1334 | dev->trans_start = jiffies; |
1358 | return NETDEV_TX_OK; | 1335 | return NETDEV_TX_OK; |
1359 | } | 1336 | } |
@@ -1408,11 +1385,13 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) | |||
1408 | } | 1385 | } |
1409 | 1386 | ||
1410 | /* Cleanup all untransmitted buffers, assume transmitter not running */ | 1387 | /* Cleanup all untransmitted buffers, assume transmitter not running */ |
1411 | static void sky2_tx_clean(struct sky2_port *sky2) | 1388 | static void sky2_tx_clean(struct net_device *dev) |
1412 | { | 1389 | { |
1413 | spin_lock_bh(&sky2->tx_lock); | 1390 | struct sky2_port *sky2 = netdev_priv(dev); |
1391 | |||
1392 | netif_tx_lock_bh(dev); | ||
1414 | sky2_tx_complete(sky2, sky2->tx_prod); | 1393 | sky2_tx_complete(sky2, sky2->tx_prod); |
1415 | spin_unlock_bh(&sky2->tx_lock); | 1394 | netif_tx_unlock_bh(dev); |
1416 | } | 1395 | } |
1417 | 1396 | ||
1418 | /* Network shutdown */ | 1397 | /* Network shutdown */ |
@@ -1496,7 +1475,7 @@ static int sky2_down(struct net_device *dev) | |||
1496 | 1475 | ||
1497 | synchronize_irq(hw->pdev->irq); | 1476 | synchronize_irq(hw->pdev->irq); |
1498 | 1477 | ||
1499 | sky2_tx_clean(sky2); | 1478 | sky2_tx_clean(dev); |
1500 | sky2_rx_clean(sky2); | 1479 | sky2_rx_clean(sky2); |
1501 | 1480 | ||
1502 | pci_free_consistent(hw->pdev, RX_LE_BYTES, | 1481 | pci_free_consistent(hw->pdev, RX_LE_BYTES, |
@@ -1748,16 +1727,16 @@ static void sky2_tx_timeout(struct net_device *dev) | |||
1748 | } else if (report != sky2->tx_cons) { | 1727 | } else if (report != sky2->tx_cons) { |
1749 | printk(KERN_INFO PFX "status report lost?\n"); | 1728 | printk(KERN_INFO PFX "status report lost?\n"); |
1750 | 1729 | ||
1751 | spin_lock_bh(&sky2->tx_lock); | 1730 | netif_tx_lock_bh(dev); |
1752 | sky2_tx_complete(sky2, report); | 1731 | sky2_tx_complete(sky2, report); |
1753 | spin_unlock_bh(&sky2->tx_lock); | 1732 | netif_tx_unlock_bh(dev); |
1754 | } else { | 1733 | } else { |
1755 | printk(KERN_INFO PFX "hardware hung? flushing\n"); | 1734 | printk(KERN_INFO PFX "hardware hung? flushing\n"); |
1756 | 1735 | ||
1757 | sky2_write32(hw, Q_ADDR(txq, Q_CSR), BMU_STOP); | 1736 | sky2_write32(hw, Q_ADDR(txq, Q_CSR), BMU_STOP); |
1758 | sky2_write32(hw, Y2_QADDR(txq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); | 1737 | sky2_write32(hw, Y2_QADDR(txq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); |
1759 | 1738 | ||
1760 | sky2_tx_clean(sky2); | 1739 | sky2_tx_clean(dev); |
1761 | 1740 | ||
1762 | sky2_qset(hw, txq); | 1741 | sky2_qset(hw, txq); |
1763 | sky2_prefetch_init(hw, txq, sky2->tx_le_map, TX_RING_SIZE - 1); | 1742 | sky2_prefetch_init(hw, txq, sky2->tx_le_map, TX_RING_SIZE - 1); |
@@ -1927,9 +1906,9 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) | |||
1927 | struct sky2_port *sky2 = netdev_priv(dev); | 1906 | struct sky2_port *sky2 = netdev_priv(dev); |
1928 | 1907 | ||
1929 | if (netif_running(dev)) { | 1908 | if (netif_running(dev)) { |
1930 | spin_lock(&sky2->tx_lock); | 1909 | netif_tx_lock(dev); |
1931 | sky2_tx_complete(sky2, last); | 1910 | sky2_tx_complete(sky2, last); |
1932 | spin_unlock(&sky2->tx_lock); | 1911 | netif_tx_unlock(dev); |
1933 | } | 1912 | } |
1934 | } | 1913 | } |
1935 | 1914 | ||
@@ -3134,7 +3113,6 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
3134 | sky2->hw = hw; | 3113 | sky2->hw = hw; |
3135 | sky2->msg_enable = netif_msg_init(debug, default_msg); | 3114 | sky2->msg_enable = netif_msg_init(debug, default_msg); |
3136 | 3115 | ||
3137 | spin_lock_init(&sky2->tx_lock); | ||
3138 | /* Auto speed and flow control */ | 3116 | /* Auto speed and flow control */ |
3139 | sky2->autoneg = AUTONEG_ENABLE; | 3117 | sky2->autoneg = AUTONEG_ENABLE; |
3140 | sky2->tx_pause = 1; | 3118 | sky2->tx_pause = 1; |
@@ -3153,7 +3131,6 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
3153 | 3131 | ||
3154 | sky2->port = port; | 3132 | sky2->port = port; |
3155 | 3133 | ||
3156 | dev->features |= NETIF_F_LLTX; | ||
3157 | if (hw->chip_id != CHIP_ID_YUKON_EC_U) | 3134 | if (hw->chip_id != CHIP_ID_YUKON_EC_U) |
3158 | dev->features |= NETIF_F_TSO; | 3135 | dev->features |= NETIF_F_TSO; |
3159 | if (highmem) | 3136 | if (highmem) |
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index c1e45123d44f..403486a3831d 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h | |||
@@ -1789,7 +1789,6 @@ struct sky2_port { | |||
1789 | u32 msg_enable; | 1789 | u32 msg_enable; |
1790 | spinlock_t phy_lock; | 1790 | spinlock_t phy_lock; |
1791 | 1791 | ||
1792 | spinlock_t tx_lock ____cacheline_aligned_in_smp; | ||
1793 | struct tx_ring_info *tx_ring; | 1792 | struct tx_ring_info *tx_ring; |
1794 | struct sky2_tx_le *tx_le; | 1793 | struct sky2_tx_le *tx_le; |
1795 | u16 tx_cons; /* next le to check */ | 1794 | u16 tx_cons; /* next le to check */ |