patch-2.4.5 linux/drivers/net/bmac.c
Next file: linux/drivers/net/dmfe.c
Previous file: linux/drivers/net/appletalk/ipddp.c
Back to the patch index
Back to the overall index
- Lines: 320
- Date:
Wed May 16 09:58:36 2001
- Orig file:
v2.4.4/linux/drivers/net/bmac.c
- Orig date:
Tue Feb 13 13:15:05 2001
diff -u --recursive --new-file v2.4.4/linux/drivers/net/bmac.c linux/drivers/net/bmac.c
@@ -76,9 +76,6 @@
struct net_device_stats stats;
struct timer_list tx_timeout;
int timeout_active;
- int reset_and_enabled;
- int rx_allocated;
- int tx_allocated;
unsigned short hash_use_count[64];
unsigned short hash_table_mask[4];
struct net_device *next_bmac;
@@ -126,6 +123,7 @@
};
static struct net_device *bmac_devs;
+static unsigned char *bmac_emergency_rxbuf;
#ifdef CONFIG_PMAC_PBOOK
static int bmac_sleep_notify(struct pmu_sleep_notifier *self, int when);
@@ -151,9 +149,9 @@
static int bmac_transmit_packet(struct sk_buff *skb, struct net_device *dev);
static struct net_device_stats *bmac_stats(struct net_device *dev);
static void bmac_set_multicast(struct net_device *dev);
-static int bmac_reset_and_enable(struct net_device *dev, int enable);
+static void bmac_reset_and_enable(struct net_device *dev);
static void bmac_start_chip(struct net_device *dev);
-static int bmac_init_chip(struct net_device *dev);
+static void bmac_init_chip(struct net_device *dev);
static void bmac_init_registers(struct net_device *dev);
static void bmac_reset_chip(struct net_device *dev);
static int bmac_set_address(struct net_device *dev, void *addr);
@@ -185,17 +183,6 @@
}
static void
-dbdma_stop(volatile struct dbdma_regs *dmap)
-{
- dbdma_st32((volatile unsigned long *)&dmap->control,
- DBDMA_CLEAR(RUN) | DBDMA_SET(FLUSH));
- eieio();
-
- while (dbdma_ld32((volatile unsigned long *)&dmap->status) & (ACTIVE|FLUSH))
- eieio();
-}
-
-static void
dbdma_continue(volatile struct dbdma_regs *dmap)
{
dbdma_st32((volatile unsigned long *)&dmap->control,
@@ -467,12 +454,11 @@
}
}
-static int
+static void
bmac_init_chip(struct net_device *dev)
{
bmac_init_phy(dev);
bmac_init_registers(dev);
- return 1;
}
#ifdef CONFIG_PMAC_PBOOK
@@ -503,7 +489,7 @@
break;
case PBOOK_WAKE:
/* see if this is enough */
- bmac_reset_and_enable(bmac_devs, 1);
+ bmac_reset_and_enable(bmac_devs);
enable_irq(bmac_devs->irq);
enable_irq(bp->tx_dma_intr);
enable_irq(bp->rx_dma_intr);
@@ -569,9 +555,12 @@
}
static void
-bmac_construct_rxbuff(unsigned char *addr, volatile struct dbdma_cmd *cp)
+bmac_construct_rxbuff(struct sk_buff *skb, volatile struct dbdma_cmd *cp)
{
- dbdma_setcmd(cp, (INPUT_LAST | INTR_ALWAYS), RX_BUFLEN, virt_to_bus(addr), 0);
+ unsigned char *addr = skb? skb->data: bmac_emergency_rxbuf;
+
+ dbdma_setcmd(cp, (INPUT_LAST | INTR_ALWAYS), RX_BUFLEN,
+ virt_to_bus(addr), 0);
}
/* Bit-reverse one byte of an ethernet hardware address. */
@@ -586,7 +575,7 @@
}
-static int
+static void
bmac_init_tx_ring(struct bmac_data *bp)
{
volatile struct dbdma_regs *td = bp->tx_dma;
@@ -605,9 +594,6 @@
dbdma_reset(td);
out_le32(&td->wait_sel, 0x00200020);
out_le32(&td->cmdptr, virt_to_bus(bp->tx_cmds));
-
- return 1;
-
}
static int
@@ -615,22 +601,20 @@
{
volatile struct dbdma_regs *rd = bp->rx_dma;
int i;
+ struct sk_buff *skb;
/* initialize list of sk_buffs for receiving and set up recv dma */
- if (!bp->rx_allocated) {
- for (i = 0; i < N_RX_RING; i++) {
- bp->rx_bufs[i] = dev_alloc_skb(RX_BUFLEN+2);
- if (bp->rx_bufs[i] == NULL)
- return 0;
- skb_reserve(bp->rx_bufs[i], 2);
+ memset((char *)bp->rx_cmds, 0,
+ (N_RX_RING + 1) * sizeof(struct dbdma_cmd));
+ for (i = 0; i < N_RX_RING; i++) {
+ if ((skb = bp->rx_bufs[i]) == NULL) {
+ bp->rx_bufs[i] = skb = dev_alloc_skb(RX_BUFLEN+2);
+ if (skb != NULL)
+ skb_reserve(skb, 2);
}
- bp->rx_allocated = 1;
+ bmac_construct_rxbuff(skb, &bp->rx_cmds[i]);
}
- memset((char *)bp->rx_cmds, 0, (N_RX_RING+1) * sizeof(struct dbdma_cmd));
- for (i = 0; i < N_RX_RING; i++)
- bmac_construct_rxbuff(bp->rx_bufs[i]->data, &bp->rx_cmds[i]);
-
bp->rx_empty = 0;
bp->rx_fill = i;
@@ -706,27 +690,36 @@
cp = &bp->rx_cmds[i];
stat = ld_le16(&cp->xfer_status);
residual = ld_le16(&cp->res_count);
- if ((stat & ACTIVE) == 0) break;
+ if ((stat & ACTIVE) == 0)
+ break;
nb = RX_BUFLEN - residual - 2;
if (nb < (ETHERMINPACKET - ETHERCRC)) {
skb = NULL;
bp->stats.rx_length_errors++;
bp->stats.rx_errors++;
- } else skb = bp->rx_bufs[i];
+ } else {
+ skb = bp->rx_bufs[i];
+ bp->rx_bufs[i] = NULL;
+ }
if (skb != NULL) {
nb -= ETHERCRC;
skb_put(skb, nb);
skb->dev = dev;
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- bp->rx_bufs[i] = dev_alloc_skb(RX_BUFLEN+2);
- skb_reserve(bp->rx_bufs[i], 2);
- bmac_construct_rxbuff(bp->rx_bufs[i]->data, &bp->rx_cmds[i]);
+ dev->last_rx = jiffies;
++bp->stats.rx_packets;
bp->stats.rx_bytes += nb;
} else {
++bp->stats.rx_dropped;
}
+ dev->last_rx = jiffies;
+ if ((skb = bp->rx_bufs[i]) == NULL) {
+ bp->rx_bufs[i] = skb = dev_alloc_skb(RX_BUFLEN+2);
+ if (skb != NULL)
+ skb_reserve(bp->rx_bufs[i], 2);
+ }
+ bmac_construct_rxbuff(skb, &bp->rx_cmds[i]);
st_le16(&cp->res_count, 0);
st_le16(&cp->xfer_status, 0);
last = i;
@@ -772,7 +765,13 @@
if (txintcount < 10) {
XXDEBUG(("bmac_txdma_xfer_stat=%#0x\n", stat));
}
- if (!(stat & ACTIVE)) break;
+ if (!(stat & ACTIVE)) {
+ /*
+ * status field might not have been filled by DBDMA
+ */
+ if (cp == bus_to_virt(in_le32(&bp->tx_dma->cmdptr)))
+ break;
+ }
if (bp->tx_bufs[bp->tx_empty]) {
++bp->stats.tx_packets;
@@ -1215,7 +1214,7 @@
}
}
-static int bmac_reset_and_enable(struct net_device *dev, int enable)
+static void bmac_reset_and_enable(struct net_device *dev)
{
struct bmac_data *bp = dev->priv;
unsigned long flags;
@@ -1223,22 +1222,19 @@
unsigned char *data;
save_flags(flags); cli();
- bp->reset_and_enabled = 0;
bmac_reset_chip(dev);
- if (enable) {
- if (!bmac_init_tx_ring(bp) || !bmac_init_rx_ring(bp))
- return 0;
- if (!bmac_init_chip(dev))
- return 0;
- bmac_start_chip(dev);
- bmwrite(dev, INTDISABLE, EnableNormal);
- bp->reset_and_enabled = 1;
-
- /*
- * It seems that the bmac can't receive until it's transmitted
- * a packet. So we give it a dummy packet to transmit.
- */
- skb = dev_alloc_skb(ETHERMINPACKET);
+ bmac_init_tx_ring(bp);
+ bmac_init_rx_ring(bp);
+ bmac_init_chip(dev);
+ bmac_start_chip(dev);
+ bmwrite(dev, INTDISABLE, EnableNormal);
+
+ /*
+ * It seems that the bmac can't receive until it's transmitted
+ * a packet. So we give it a dummy packet to transmit.
+ */
+ skb = dev_alloc_skb(ETHERMINPACKET);
+ if (skb != NULL) {
data = skb_put(skb, ETHERMINPACKET);
memset(data, 0, ETHERMINPACKET);
memcpy(data, dev->dev_addr, 6);
@@ -1246,13 +1242,14 @@
bmac_transmit_packet(skb, dev);
}
restore_flags(flags);
- return 1;
}
static int __init bmac_probe(void)
{
struct device_node *bmac;
+ MOD_INC_USE_COUNT;
+
for (bmac = find_devices("bmac"); bmac != 0; bmac = bmac->next)
bmac_probe1(bmac, 0);
for (bmac = find_compatible_devices("network", "bmac+"); bmac != 0;
@@ -1265,7 +1262,10 @@
pmu_register_sleep_notifier(&bmac_sleep_notifier);
#endif
}
- return 0;
+
+ MOD_DEC_USE_COUNT;
+
+ return bmac_devs? 0: -ENODEV;
}
static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus)
@@ -1290,6 +1290,14 @@
}
}
+ if (bmac_emergency_rxbuf == NULL) {
+ bmac_emergency_rxbuf = kmalloc(RX_BUFLEN, GFP_KERNEL);
+ if (bmac_emergency_rxbuf == NULL) {
+ printk(KERN_ERR "BMAC: can't allocate emergency RX buffer\n");
+ return;
+ }
+ }
+
dev = init_etherdev(NULL, PRIV_BYTES);
if (!dev) {
printk(KERN_ERR "init_etherdev failed, out of memory for BMAC %s\n",
@@ -1390,9 +1398,7 @@
{
/* XXDEBUG(("bmac: enter open\n")); */
/* reset the chip */
- if (!bmac_reset_and_enable(dev, 1))
- return -ENOMEM;
-
+ bmac_reset_and_enable(dev);
dev->flags |= IFF_RUNNING;
return 0;
}
@@ -1428,7 +1434,6 @@
bp->rx_bufs[i] = NULL;
}
}
- bp->rx_allocated = 0;
XXDEBUG(("bmac: free tx bufs\n"));
for (i = 0; i<N_TX_RING; i++) {
if (bp->tx_bufs[i] != NULL) {
@@ -1436,7 +1441,6 @@
bp->tx_bufs[i] = NULL;
}
}
- bp->reset_and_enabled = 0;
XXDEBUG(("bmac: all bufs freed\n"));
return 0;
@@ -1607,6 +1611,11 @@
{
struct bmac_data *bp;
struct net_device *dev;
+
+ if (bmac_emergency_rxbuf != NULL) {
+ kfree(bmac_emergency_rxbuf);
+ bmac_emergency_rxbuf = NULL;
+ }
if (bmac_devs == 0)
return;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)