patch-2.3.47 linux/drivers/net/sunhme.c

Next file: linux/drivers/net/sunhme.h
Previous file: linux/drivers/net/sunbmac.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.46/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c
@@ -1,4 +1,4 @@
-/* $Id: sunhme.c,v 1.87 2000/02/10 21:14:22 davem Exp $
+/* $Id: sunhme.c,v 1.92 2000/02/18 13:49:22 davem Exp $
  * sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching,
  *           auto carrier detecting ethernet driver.  Also known as the
  *           "Happy Meal Ethernet" found on SunSwift SBUS cards.
@@ -152,6 +152,13 @@
 #define DEFAULT_IPG2       4 /* For all modes */
 #define DEFAULT_JAMSIZE    4 /* Toe jam */
 
+/* NOTE: In the descriptor writes one _must_ write the address
+ *	 member _first_.  The card must not be allowed to see
+ *	 the updated descriptor flags until the address is
+ *	 correct.  I've added a write memory barrier between
+ *	 the two stores so that I can sleep well at night... -DaveM
+ */
+
 #if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
 static void sbus_hme_write32(unsigned long reg, u32 val)
 {
@@ -166,13 +173,15 @@
 static void sbus_hme_write_rxd(struct happy_meal_rxd *rxd, u32 flags, u32 addr)
 {
 	rxd->rx_addr = addr;
+	wmb();
 	rxd->rx_flags = flags;
 }
 
 static void sbus_hme_write_txd(struct happy_meal_txd *txd, u32 flags, u32 addr)
 {
-	txd->tx_flags = flags;
 	txd->tx_addr = addr;
+	wmb();
+	txd->tx_flags = flags;
 }
 
 static u32 sbus_hme_read_desc32(u32 *p)
@@ -193,18 +202,20 @@
 static void pci_hme_write_rxd(struct happy_meal_rxd *rxd, u32 flags, u32 addr)
 {
 	rxd->rx_addr = cpu_to_le32(addr);
+	wmb();
 	rxd->rx_flags = cpu_to_le32(flags);
 }
 
 static void pci_hme_write_txd(struct happy_meal_txd *txd, u32 flags, u32 addr)
 {
-	txd->tx_flags = cpu_to_le32(flags);
 	txd->tx_addr = cpu_to_le32(addr);
+	wmb();
+	txd->tx_flags = cpu_to_le32(flags);
 }
 
 static u32 pci_hme_read_desc32(u32 *p)
 {
-	return cpu_to_le32(*p);
+	return cpu_to_le32p(p);
 }
 
 #define hme_write32(__hp, __reg, __val) \
@@ -217,12 +228,12 @@
 	((__hp)->write_txd((__txd), (__flags), (__addr)))
 #define hme_read_desc32(__hp, __p) \
 	((__hp)->read_desc32(__p))
-#define hme_dma_map(__hp, __ptr, __size) \
-	((__hp)->dma_map((__hp)->happy_dev, (__ptr), (__size)))
-#define hme_dma_unmap(__hp, __addr, __size) \
-	((__hp)->dma_unmap((__hp)->happy_dev, (__addr), (__size)))
-#define hme_dma_sync(__hp, __addr, __size) \
-	((__hp)->dma_sync((__hp)->happy_dev, (__addr), (__size)))
+#define hme_dma_map(__hp, __ptr, __size, __dir) \
+	((__hp)->dma_map((__hp)->happy_dev, (__ptr), (__size), (__dir)))
+#define hme_dma_unmap(__hp, __addr, __size, __dir) \
+	((__hp)->dma_unmap((__hp)->happy_dev, (__addr), (__size), (__dir)))
+#define hme_dma_sync(__hp, __addr, __size, __dir) \
+	((__hp)->dma_sync((__hp)->happy_dev, (__addr), (__size), (__dir)))
 #else
 #ifdef CONFIG_SBUS
 /* SBUS only compilation */
@@ -232,19 +243,21 @@
 	sbus_readl(__reg)
 #define hme_write_rxd(__hp, __rxd, __flags, __addr) \
 do {	(__rxd)->rx_addr = (__addr); \
+	wmb(); \
 	(__rxd)->rx_flags = (__flags); \
 } while(0)
 #define hme_write_txd(__hp, __txd, __flags, __addr) \
 do {	(__txd)->tx_addr = (__addr); \
+	wmb(); \
 	(__txd)->tx_flags = (__flags); \
 } while(0)
 #define hme_read_desc32(__hp, __p)	(*(__p))
-#define hme_dma_map(__hp, __ptr, __size) \
-	sbus_map_single((__hp)->happy_dev, (__ptr), (__size))
+#define hme_dma_map(__hp, __ptr, __size, __dir) \
+	sbus_map_single((__hp)->happy_dev, (__ptr), (__size), (__dir))
 #define hme_dma_unmap(__hp, __addr, __size) \
-	sbus_unmap_single((__hp)->happy_dev, (__addr), (__size))
-#define hme_dma_sync(__hp, __addr, __size) \
-	sbus_dma_sync_single((__hp)->happy_dev, (__addr), (__size))
+	sbus_unmap_single((__hp)->happy_dev, (__addr), (__size), (__dir))
+#define hme_dma_sync(__hp, __addr, __size, __dir) \
+	sbus_dma_sync_single((__hp)->happy_dev, (__addr), (__size), (__dir))
 #else
 /* PCI only compilation */
 #define hme_write32(__hp, __reg, __val) \
@@ -253,22 +266,28 @@
 	readl(__reg)
 #define hme_write_rxd(__hp, __rxd, __flags, __addr) \
 do {	(__rxd)->rx_addr = cpu_to_le32(__addr); \
+	wmb(); \
 	(__rxd)->rx_flags = cpu_to_le32(__flags); \
 } while(0)
 #define hme_write_txd(__hp, __txd, __flags, __addr) \
 do {	(__txd)->tx_addr = cpu_to_le32(__addr); \
+	wmb(); \
 	(__txd)->tx_flags = cpu_to_le32(__flags); \
 } while(0)
-#define hme_read_desc32(__hp, __p)	cpu_to_le32(*(__p))
-#define hme_dma_map(__hp, __ptr, __size) \
-	pci_map_single((__hp)->happy_dev, (__ptr), (__size))
-#define hme_dma_unmap(__hp, __addr, __size) \
-	pci_unmap_single((__hp)->happy_dev, (__addr), (__size))
-#define hme_dma_sync(__hp, __addr, __size) \
-	pci_dma_sync_single((__hp)->happy_dev, (__addr), (__size))
+#define hme_read_desc32(__hp, __p)	cpu_to_le32p(__p)
+#define hme_dma_map(__hp, __ptr, __size, __dir) \
+	pci_map_single((__hp)->happy_dev, (__ptr), (__size), (__dir))
+#define hme_dma_unmap(__hp, __addr, __size, __dir) \
+	pci_unmap_single((__hp)->happy_dev, (__addr), (__size), (__dir))
+#define hme_dma_sync(__hp, __addr, __size, __dir) \
+	pci_dma_sync_single((__hp)->happy_dev, (__addr), (__size), (__dir))
 #endif
 #endif
 
+#define DMA_BIDIRECTIONAL	SBUS_DMA_BIDIRECTIONAL
+#define DMA_FROMDEVICE		SBUS_DMA_FROMDEVICE
+#define DMA_TODEVICE		SBUS_DMA_TODEVICE
+
 /* Oh yes, the MIF BitBang is mighty fun to program.  BitBucket is more like it. */
 static void BB_PUT_BIT(struct happy_meal *hp, unsigned long tregs, int bit)
 {
@@ -1193,11 +1212,8 @@
 
 			rxd = &hp->happy_block->happy_meal_rxd[i];
 			dma_addr = hme_read_desc32(hp, &rxd->rx_addr);
-			hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE);
-			if (in_irq())
-				dev_kfree_skb_irq(skb);
-			else
-				dev_kfree_skb(skb);
+			hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE);
+			dev_kfree_skb_any(skb);
 			hp->rx_skbs[i] = NULL;
 		}
 	}
@@ -1210,11 +1226,8 @@
 
 			txd = &hp->happy_block->happy_meal_txd[i];
 			dma_addr = hme_read_desc32(hp, &txd->tx_addr);
-			hme_dma_unmap(hp, dma_addr, skb->len);
-			if (in_irq())
-				dev_kfree_skb_irq(skb);
-			else
-				dev_kfree_skb(skb);
+			hme_dma_unmap(hp, dma_addr, skb->len, DMA_TODEVICE);
+			dev_kfree_skb_any(skb);
 			hp->tx_skbs[i] = NULL;
 		}
 	}
@@ -1253,7 +1266,7 @@
 		skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET));
 		hme_write_rxd(hp, &hb->happy_meal_rxd[i],
 			      (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)),
-			      hme_dma_map(hp, skb->data, RX_BUF_ALLOC_SIZE));
+			      hme_dma_map(hp, skb->data, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE));
 		skb_reserve(skb, RX_OFFSET);
 	}
 
@@ -1895,7 +1908,7 @@
 			break;
 		dma_addr = hme_read_desc32(hp, &this->tx_addr);
 		skb = hp->tx_skbs[elem];
-		hme_dma_unmap(hp, dma_addr, skb->len);
+		hme_dma_unmap(hp, dma_addr, skb->len, DMA_TODEVICE);
 		hp->tx_skbs[elem] = NULL;
 		hp->net_stats.tx_bytes += skb->len;
 
@@ -1907,7 +1920,7 @@
 	hp->tx_old = elem;
 	TXD((">"));
 
-	if (test_bit(LINK_STATE_XOFF, &dev->state) &&
+	if (netif_queue_stopped(dev) &&
 	    TX_BUFFS_AVAIL(hp) > 0)
 		netif_wake_queue(dev);
 
@@ -1973,13 +1986,13 @@
 				drops++;
 				goto drop_it;
 			}
-			hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE);
+			hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE);
 			hp->rx_skbs[elem] = new_skb;
 			new_skb->dev = dev;
 			skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET));
 			hme_write_rxd(hp, this,
 				      (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)),
-				      hme_dma_map(hp, new_skb->data, RX_BUF_ALLOC_SIZE));
+				      hme_dma_map(hp, new_skb->data, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE));
 			skb_reserve(new_skb, RX_OFFSET);
 
 			/* Trim the original skb for the netif. */
@@ -1995,7 +2008,7 @@
 			copy_skb->dev = dev;
 			skb_reserve(copy_skb, 2);
 			skb_put(copy_skb, len);
-			hme_dma_sync(hp, dma_addr, len);
+			hme_dma_sync(hp, dma_addr, len, DMA_FROMDEVICE);
 			memcpy(copy_skb->data, skb->data, len);
 
 			/* Reuse original ring buffer. */
@@ -2178,7 +2191,7 @@
 	u32 mapping;
 
 	len = skb->len;
-	mapping = hme_dma_map(hp, skb->data, len);
+	mapping = hme_dma_map(hp, skb->data, len, DMA_TODEVICE);
 
 	spin_lock_irq(&hp->happy_lock);
 
@@ -2192,10 +2205,11 @@
 	if (TX_BUFFS_AVAIL(hp) <= 0)
 		netif_stop_queue(dev);
 
-	spin_unlock_irq(&hp->happy_lock);
-
 	/* Get it going. */
 	hme_write32(hp, hp->etxregs + ETX_PENDING, ETX_TP_DMAWAKEUP);
+
+	spin_unlock_irq(&hp->happy_lock);
+
 	dev->trans_start = jiffies;
 
 	tx_add_log(hp, TXLOG_ACTION_TXMIT, 0);
@@ -2642,9 +2656,9 @@
 	hp->read_desc32 = sbus_hme_read_desc32;
 	hp->write_txd = sbus_hme_write_txd;
 	hp->write_rxd = sbus_hme_write_rxd;
-	hp->dma_map = (u32 (*)(void *, void *, long))sbus_map_single;
-	hp->dma_unmap = (void (*)(void *, u32, long))sbus_unmap_single;
-	hp->dma_sync = (void (*)(void *, u32, long))sbus_dma_sync_single;
+	hp->dma_map = (u32 (*)(void *, void *, long, int))sbus_map_single;
+	hp->dma_unmap = (void (*)(void *, u32, long, int))sbus_unmap_single;
+	hp->dma_sync = (void (*)(void *, u32, long, int))sbus_dma_sync_single;
 	hp->read32 = sbus_hme_read32;
 	hp->write32 = sbus_hme_write32;
 #endif
@@ -2817,9 +2831,9 @@
 	hp->read_desc32 = pci_hme_read_desc32;
 	hp->write_txd = pci_hme_write_txd;
 	hp->write_rxd = pci_hme_write_rxd;
-	hp->dma_map = (u32 (*)(void *, void *, long))pci_map_single;
-	hp->dma_unmap = (void (*)(void *, u32, long))pci_unmap_single;
-	hp->dma_sync = (void (*)(void *, u32, long))pci_dma_sync_single;
+	hp->dma_map = (u32 (*)(void *, void *, long, int))pci_map_single;
+	hp->dma_unmap = (void (*)(void *, u32, long, int))pci_unmap_single;
+	hp->dma_sync = (void (*)(void *, u32, long, int))pci_dma_sync_single;
 	hp->read32 = pci_hme_read32;
 	hp->write32 = pci_hme_write32;
 #endif

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)