aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/declance.c
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@linux-mips.org>2009-06-08 05:42:35 -0400
committerDavid S. Miller <davem@davemloft.net>2009-06-08 05:42:35 -0400
commit963267bc5d4de4a0da104a64300375d186575332 (patch)
treed8d3522224e2778f69d4294ed9f1dc5e9b0359ad /drivers/net/declance.c
parentfe93299a008a7056fe1790744b3a425ddf79a16b (diff)
declance: Restore tx descriptor ring locking
A driver overhaul on 29 Feb 2000 (!) broke locking around fiddling with the tx descriptor ring in start_xmit(); a follow-on "fix" removed the broken remnants altogether. Here's a patch to restore proper locking in the function -- the complement in the interrupt handler has been correct all the time. This *may* have been the reason for the occasional confusion of the chip -- triggering a tx timeout followed by a chip reset sequence -- seen on R4k-based DECstations with the onboard Ethernet interface. Another theory is the confusion is due to an unindentified problem -- perhaps a silicon erratum -- associated with the variation of the MT ASIC used to interface the R4k CPU to the rest of the system on these computers; with its aggressive write-back buffering the design is particularly weakly ordered when it comes to MMIO (in the absence of ordering barriers uncached reads are allowed to bypass earlier uncached writes, even if to the same location), which may trigger all kinds of corner cases in peripheral hardware as well as software. Either way this piece of code is buggy. Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/declance.c')
-rw-r--r--drivers/net/declance.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/net/declance.c b/drivers/net/declance.c
index b62405a69180..2b22e580c4de 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/declance.c
@@ -895,6 +895,7 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
895 struct lance_private *lp = netdev_priv(dev); 895 struct lance_private *lp = netdev_priv(dev);
896 volatile struct lance_regs *ll = lp->ll; 896 volatile struct lance_regs *ll = lp->ll;
897 volatile u16 *ib = (volatile u16 *)dev->mem_start; 897 volatile u16 *ib = (volatile u16 *)dev->mem_start;
898 unsigned long flags;
898 int entry, len; 899 int entry, len;
899 900
900 len = skb->len; 901 len = skb->len;
@@ -907,6 +908,8 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
907 908
908 dev->stats.tx_bytes += len; 909 dev->stats.tx_bytes += len;
909 910
911 spin_lock_irqsave(&lp->lock, flags);
912
910 entry = lp->tx_new; 913 entry = lp->tx_new;
911 *lib_ptr(ib, btx_ring[entry].length, lp->type) = (-len); 914 *lib_ptr(ib, btx_ring[entry].length, lp->type) = (-len);
912 *lib_ptr(ib, btx_ring[entry].misc, lp->type) = 0; 915 *lib_ptr(ib, btx_ring[entry].misc, lp->type) = 0;
@@ -925,6 +928,8 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
925 /* Kick the lance: transmit now */ 928 /* Kick the lance: transmit now */
926 writereg(&ll->rdp, LE_C0_INEA | LE_C0_TDMD); 929 writereg(&ll->rdp, LE_C0_INEA | LE_C0_TDMD);
927 930
931 spin_unlock_irqrestore(&lp->lock, flags);
932
928 dev->trans_start = jiffies; 933 dev->trans_start = jiffies;
929 dev_kfree_skb(skb); 934 dev_kfree_skb(skb);
930 935