patch-2.4.10 linux/drivers/net/bmac.c
Next file: linux/drivers/net/cs89x0.c
Previous file: linux/drivers/net/au1000_eth.c
Back to the patch index
Back to the overall index
- Lines: 140
- Date:
Tue Sep 18 14:23:14 2001
- Orig file:
v2.4.9/linux/drivers/net/bmac.c
- Orig date:
Wed May 16 09:58:36 2001
diff -u --recursive --new-file v2.4.9/linux/drivers/net/bmac.c linux/drivers/net/bmac.c
@@ -76,6 +76,8 @@
struct net_device_stats stats;
struct timer_list tx_timeout;
int timeout_active;
+ int sleeping;
+ int opened;
unsigned short hash_use_count[64];
unsigned short hash_table_mask[4];
struct net_device *next_bmac;
@@ -466,11 +468,15 @@
bmac_sleep_notify(struct pmu_sleep_notifier *self, int when)
{
struct bmac_data *bp;
-
+ unsigned long flags;
+ unsigned short config;
+ struct net_device* dev = bmac_devs;
+ int i;
+
if (bmac_devs == 0)
return PBOOK_SLEEP_OK;
- bp = (struct bmac_data *) bmac_devs->priv;
+ bp = (struct bmac_data *) dev->priv;
switch (when) {
case PBOOK_SLEEP_REQUEST:
@@ -478,21 +484,57 @@
case PBOOK_SLEEP_REJECT:
break;
case PBOOK_SLEEP_NOW:
+ netif_device_detach(dev);
/* prolly should wait for dma to finish & turn off the chip */
- disable_irq(bmac_devs->irq);
+ save_flags(flags); cli();
+ if (bp->timeout_active) {
+ del_timer(&bp->tx_timeout);
+ bp->timeout_active = 0;
+ }
+ disable_irq(dev->irq);
disable_irq(bp->tx_dma_intr);
disable_irq(bp->rx_dma_intr);
+ bp->sleeping = 1;
+ restore_flags(flags);
+ if (bp->opened) {
+ volatile struct dbdma_regs *rd = bp->rx_dma;
+ volatile struct dbdma_regs *td = bp->tx_dma;
+
+ config = bmread(dev, RXCFG);
+ bmwrite(dev, RXCFG, (config & ~RxMACEnable));
+ config = bmread(dev, TXCFG);
+ bmwrite(dev, TXCFG, (config & ~TxMACEnable));
+ bmwrite(dev, INTDISABLE, DisableAll); /* disable all intrs */
+ /* disable rx and tx dma */
+ st_le32(&rd->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */
+ st_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */
+ /* free some skb's */
+ for (i=0; i<N_RX_RING; i++) {
+ if (bp->rx_bufs[i] != NULL) {
+ dev_kfree_skb(bp->rx_bufs[i]);
+ bp->rx_bufs[i] = NULL;
+ }
+ }
+ for (i = 0; i<N_TX_RING; i++) {
+ if (bp->tx_bufs[i] != NULL) {
+ dev_kfree_skb(bp->tx_bufs[i]);
+ bp->tx_bufs[i] = NULL;
+ }
+ }
+ }
feature_set(bp->node, FEATURE_BMac_reset);
- udelay(10000);
+ mdelay(10);
feature_clear(bp->node, FEATURE_BMac_IO_enable);
- udelay(10000);
+ mdelay(10);
break;
case PBOOK_WAKE:
/* see if this is enough */
- bmac_reset_and_enable(bmac_devs);
- enable_irq(bmac_devs->irq);
+ if (bp->opened)
+ bmac_reset_and_enable(dev);
+ enable_irq(dev->irq);
enable_irq(bp->tx_dma_intr);
enable_irq(bp->rx_dma_intr);
+ netif_device_attach(dev);
break;
}
return PBOOK_SLEEP_OK;
@@ -975,6 +1017,9 @@
unsigned short rx_cfg;
int i;
+ if (bp->sleeping)
+ return;
+
XXDEBUG(("bmac: enter bmac_set_multicast, n_addrs=%d\n", num_addrs));
if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
@@ -1228,7 +1273,8 @@
bmac_init_chip(dev);
bmac_start_chip(dev);
bmwrite(dev, INTDISABLE, EnableNormal);
-
+ bp->sleeping = 0;
+
/*
* It seems that the bmac can't receive until it's transmitted
* a packet. So we give it a dummy packet to transmit.
@@ -1396,8 +1442,10 @@
static int bmac_open(struct net_device *dev)
{
+ struct bmac_data *bp = (struct bmac_data *) dev->priv;
/* XXDEBUG(("bmac: enter open\n")); */
/* reset the chip */
+ bp->opened = 1;
bmac_reset_and_enable(dev);
dev->flags |= IFF_RUNNING;
return 0;
@@ -1443,6 +1491,8 @@
}
XXDEBUG(("bmac: all bufs freed\n"));
+ bp->opened = 0;
+
return 0;
}
@@ -1454,6 +1504,9 @@
struct sk_buff *skb;
unsigned long flags;
+ if (bp->sleeping)
+ return;
+
save_flags(flags); cli();
while (1) {
i = bp->tx_fill + 1;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)