static void smc_shutdown(struct net_device *dev) { struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; struct sk_buff *pending_skb; DBG(2, "%s: %s\n", CARDNAME, __func__); spin_lock_irq(&lp->lock); SMC_SELECT_BANK(lp, 2); SMC_SET_INT_MASK(lp, 0); pending_skb = lp->pending_tx_skb; lp->pending_tx_skb = NULL; spin_unlock_irq(&lp->lock); if (pending_skb) dev_kfree_skb(pending_skb); SMC_SELECT_BANK(lp, 0); SMC_SET_RCR(lp, RCR_CLEAR); SMC_SET_TCR(lp, TCR_CLEAR); #ifdef POWER_DOWN SMC_SELECT_BANK(lp, 1); SMC_SET_CONFIG(lp, SMC_GET_CONFIG(lp) & ~CONFIG_EPH_POWER_EN); #endif }
/* * this puts the device in an inactive state */ static void smc_shutdown(struct net_device *dev) { struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; struct sk_buff *pending_skb; DBG(2, "%s: %s\n", CARDNAME, __func__); /* no more interrupts for me */ spin_lock_irq(&lp->lock); SMC_SELECT_BANK(lp, 2); SMC_SET_INT_MASK(lp, 0); pending_skb = lp->pending_tx_skb; lp->pending_tx_skb = NULL; spin_unlock_irq(&lp->lock); if (pending_skb) dev_kfree_skb(pending_skb); /* and tell the card to stay away from that nasty outside world */ SMC_SELECT_BANK(lp, 0); SMC_SET_RCR(lp, RCR_CLEAR); SMC_SET_TCR(lp, TCR_CLEAR); #ifdef POWER_DOWN /* finally, shut the chip down */ SMC_SELECT_BANK(lp, 1); SMC_SET_CONFIG(lp, SMC_GET_CONFIG(lp) & ~CONFIG_EPH_POWER_EN); #endif }
static void smc_reset(struct net_device *dev) { struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; unsigned int ctl, cfg; struct sk_buff *pending_skb; DBG(2, "%s: %s\n", dev->name, __func__); spin_lock_irq(&lp->lock); SMC_SELECT_BANK(lp, 2); SMC_SET_INT_MASK(lp, 0); pending_skb = lp->pending_tx_skb; lp->pending_tx_skb = NULL; spin_unlock_irq(&lp->lock); if (pending_skb) { dev_kfree_skb(pending_skb); dev->stats.tx_errors++; dev->stats.tx_aborted_errors++; } SMC_SELECT_BANK(lp, 0); SMC_SET_RCR(lp, RCR_SOFTRST); SMC_SELECT_BANK(lp, 1); cfg = CONFIG_DEFAULT; if (lp->cfg.flags & SMC91X_NOWAIT) cfg |= CONFIG_NO_WAIT; cfg |= CONFIG_EPH_POWER_EN; SMC_SET_CONFIG(lp, cfg); udelay(1); SMC_SELECT_BANK(lp, 0); SMC_SET_RCR(lp, RCR_CLEAR); SMC_SET_TCR(lp, TCR_CLEAR); SMC_SELECT_BANK(lp, 1); ctl = SMC_GET_CTL(lp) | CTL_LE_ENABLE; if(!THROTTLE_TX_PKTS) ctl |= CTL_AUTO_RELEASE; else ctl &= ~CTL_AUTO_RELEASE; SMC_SET_CTL(lp, ctl); SMC_SELECT_BANK(lp, 2); SMC_SET_MMU_CMD(lp, MC_RESET); SMC_WAIT_MMU_BUSY(lp); }
/* * this does a soft reset on the device */ static void smc_reset(struct net_device *dev) { struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; unsigned int ctl, cfg; struct sk_buff *pending_skb; DBG(2, "%s: %s\n", dev->name, __func__); /* Disable all interrupts, block TX tasklet */ spin_lock_irq(&lp->lock); SMC_SELECT_BANK(lp, 2); SMC_SET_INT_MASK(lp, 0); pending_skb = lp->pending_tx_skb; lp->pending_tx_skb = NULL; spin_unlock_irq(&lp->lock); /* free any pending tx skb */ if (pending_skb) { dev_kfree_skb(pending_skb); dev->stats.tx_errors++; dev->stats.tx_aborted_errors++; } /* * This resets the registers mostly to defaults, but doesn't * affect EEPROM. That seems unnecessary */ SMC_SELECT_BANK(lp, 0); SMC_SET_RCR(lp, RCR_SOFTRST); /* * Setup the Configuration Register * This is necessary because the CONFIG_REG is not affected * by a soft reset */ SMC_SELECT_BANK(lp, 1); cfg = CONFIG_DEFAULT; /* * Setup for fast accesses if requested. If the card/system * can't handle it then there will be no recovery except for * a hard reset or power cycle */ if (lp->cfg.flags & SMC91X_NOWAIT) cfg |= CONFIG_NO_WAIT; /* * Release from possible power-down state * Configuration register is not affected by Soft Reset */ cfg |= CONFIG_EPH_POWER_EN; SMC_SET_CONFIG(lp, cfg); /* this should pause enough for the chip to be happy */ /* * elaborate? What does the chip _need_? --jgarzik * * This seems to be undocumented, but something the original * driver(s) have always done. Suspect undocumented timing * info/determined empirically. --rmk */ udelay(1); /* Disable transmit and receive functionality */ SMC_SELECT_BANK(lp, 0); SMC_SET_RCR(lp, RCR_CLEAR); SMC_SET_TCR(lp, TCR_CLEAR); SMC_SELECT_BANK(lp, 1); ctl = SMC_GET_CTL(lp) | CTL_LE_ENABLE; /* * Set the control register to automatically release successfully * transmitted packets, to make the best use out of our limited * memory */ if(!THROTTLE_TX_PKTS) ctl |= CTL_AUTO_RELEASE; else ctl &= ~CTL_AUTO_RELEASE; SMC_SET_CTL(lp, ctl); /* Reset the MMU */ SMC_SELECT_BANK(lp, 2); SMC_SET_MMU_CMD(lp, MC_RESET); SMC_WAIT_MMU_BUSY(lp); }