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
- Lines: 271
- Date:
Fri Feb 18 15:07:20 2000
- Orig file:
v2.3.46/linux/drivers/net/sunhme.c
- Orig date:
Sat Feb 12 11:22:10 2000
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)