X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fnet%2Fsmc911x.c;h=6278734c735f3ba0b94346e761cccbfcf46ef270;hb=22bedad3ce112d5ca1eaf043d4990fa2ed698c87;hp=7c60df46fc65c99208d3e539abaeecc7d409fecf;hpb=726d722e41f1c329b7f04c5ee5aef02a60ac1991;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 7c60df4..6278734 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -92,6 +92,7 @@ module_param(tx_fifo_kb, int, 0400); MODULE_PARM_DESC(tx_fifo_kb,"transmit FIFO size in KB (1 0 #define DBG(n, args...) \ do { \ @@ -202,25 +153,19 @@ static void PRINT_PKT(u_char *buf, int length) /* this enables an interrupt in the interrupt mask register */ -#define SMC_ENABLE_INT(x) do { \ +#define SMC_ENABLE_INT(lp, x) do { \ unsigned int __mask; \ - unsigned long __flags; \ - spin_lock_irqsave(&lp->lock, __flags); \ - __mask = SMC_GET_INT_EN(); \ + __mask = SMC_GET_INT_EN((lp)); \ __mask |= (x); \ - SMC_SET_INT_EN(__mask); \ - spin_unlock_irqrestore(&lp->lock, __flags); \ + SMC_SET_INT_EN((lp), __mask); \ } while (0) /* this disables an interrupt from the interrupt mask register */ -#define SMC_DISABLE_INT(x) do { \ +#define SMC_DISABLE_INT(lp, x) do { \ unsigned int __mask; \ - unsigned long __flags; \ - spin_lock_irqsave(&lp->lock, __flags); \ - __mask = SMC_GET_INT_EN(); \ + __mask = SMC_GET_INT_EN((lp)); \ __mask &= ~(x); \ - SMC_SET_INT_EN(__mask); \ - spin_unlock_irqrestore(&lp->lock, __flags); \ + SMC_SET_INT_EN((lp), __mask); \ } while (0) /* @@ -228,22 +173,21 @@ static void PRINT_PKT(u_char *buf, int length) */ static void smc911x_reset(struct net_device *dev) { - unsigned long ioaddr = dev->base_addr; struct smc911x_local *lp = netdev_priv(dev); - unsigned int reg, timeout=0, resets=1; + unsigned int reg, timeout=0, resets=1, irq_cfg; unsigned long flags; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); /* Take out of PM setting first */ - if ((SMC_GET_PMT_CTRL() & PMT_CTRL_READY_) == 0) { + if ((SMC_GET_PMT_CTRL(lp) & PMT_CTRL_READY_) == 0) { /* Write to the bytetest will take out of powerdown */ - SMC_SET_BYTE_TEST(0); + SMC_SET_BYTE_TEST(lp, 0); timeout=10; do { udelay(10); - reg = SMC_GET_PMT_CTRL() & PMT_CTRL_READY_; - } while ( timeout-- && !reg); + reg = SMC_GET_PMT_CTRL(lp) & PMT_CTRL_READY_; + } while (--timeout && !reg); if (timeout == 0) { PRINTK("%s: smc911x_reset timeout waiting for PM restore\n", dev->name); return; @@ -252,22 +196,22 @@ static void smc911x_reset(struct net_device *dev) /* Disable all interrupts */ spin_lock_irqsave(&lp->lock, flags); - SMC_SET_INT_EN(0); + SMC_SET_INT_EN(lp, 0); spin_unlock_irqrestore(&lp->lock, flags); while (resets--) { - SMC_SET_HW_CFG(HW_CFG_SRST_); + SMC_SET_HW_CFG(lp, HW_CFG_SRST_); timeout=10; do { udelay(10); - reg = SMC_GET_HW_CFG(); + reg = SMC_GET_HW_CFG(lp); /* If chip indicates reset timeout then try again */ if (reg & HW_CFG_SRST_TO_) { PRINTK("%s: chip reset timeout, retrying...\n", dev->name); resets++; break; } - } while ( timeout-- && (reg & HW_CFG_SRST_)); + } while (--timeout && (reg & HW_CFG_SRST_)); } if (timeout == 0) { PRINTK("%s: smc911x_reset timeout waiting for reset\n", dev->name); @@ -276,33 +220,38 @@ static void smc911x_reset(struct net_device *dev) /* make sure EEPROM has finished loading before setting GPIO_CFG */ timeout=1000; - while ( timeout-- && (SMC_GET_E2P_CMD() & E2P_CMD_EPC_BUSY_)) { + while (--timeout && (SMC_GET_E2P_CMD(lp) & E2P_CMD_EPC_BUSY_)) udelay(10); - } + if (timeout == 0){ PRINTK("%s: smc911x_reset timeout waiting for EEPROM busy\n", dev->name); return; } /* Initialize interrupts */ - SMC_SET_INT_EN(0); - SMC_ACK_INT(-1); + SMC_SET_INT_EN(lp, 0); + SMC_ACK_INT(lp, -1); /* Reset the FIFO level and flow control settings */ - SMC_SET_HW_CFG((lp->tx_fifo_kb & 0xF) << 16); + SMC_SET_HW_CFG(lp, (lp->tx_fifo_kb & 0xF) << 16); //TODO: Figure out what appropriate pause time is - SMC_SET_FLOW(FLOW_FCPT_ | FLOW_FCEN_); - SMC_SET_AFC_CFG(lp->afc_cfg); + SMC_SET_FLOW(lp, FLOW_FCPT_ | FLOW_FCEN_); + SMC_SET_AFC_CFG(lp, lp->afc_cfg); /* Set to LED outputs */ - SMC_SET_GPIO_CFG(0x70070000); + SMC_SET_GPIO_CFG(lp, 0x70070000); /* * Deassert IRQ for 1*10us for edge type interrupts * and drive IRQ pin push-pull */ - SMC_SET_IRQ_CFG( (1 << 24) | INT_CFG_IRQ_EN_ | INT_CFG_IRQ_TYPE_ ); + irq_cfg = (1 << 24) | INT_CFG_IRQ_EN_ | INT_CFG_IRQ_TYPE_; +#ifdef SMC_DYNAMIC_BUS_CONFIG + if (lp->cfg.irq_polarity) + irq_cfg |= INT_CFG_IRQ_POL_; +#endif + SMC_SET_IRQ_CFG(lp, irq_cfg); /* clear anything saved */ if (lp->pending_tx_skb != NULL) { @@ -318,46 +267,43 @@ static void smc911x_reset(struct net_device *dev) */ static void smc911x_enable(struct net_device *dev) { - unsigned long ioaddr = dev->base_addr; struct smc911x_local *lp = netdev_priv(dev); unsigned mask, cfg, cr; unsigned long flags; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); - SMC_SET_MAC_ADDR(dev->dev_addr); + spin_lock_irqsave(&lp->lock, flags); + + SMC_SET_MAC_ADDR(lp, dev->dev_addr); /* Enable TX */ - cfg = SMC_GET_HW_CFG(); + cfg = SMC_GET_HW_CFG(lp); cfg &= HW_CFG_TX_FIF_SZ_ | 0xFFF; cfg |= HW_CFG_SF_; - SMC_SET_HW_CFG(cfg); - SMC_SET_FIFO_TDA(0xFF); + SMC_SET_HW_CFG(lp, cfg); + SMC_SET_FIFO_TDA(lp, 0xFF); /* Update TX stats on every 64 packets received or every 1 sec */ - SMC_SET_FIFO_TSL(64); - SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000); + SMC_SET_FIFO_TSL(lp, 64); + SMC_SET_GPT_CFG(lp, GPT_CFG_TIMER_EN_ | 10000); - spin_lock_irqsave(&lp->lock, flags); - SMC_GET_MAC_CR(cr); + SMC_GET_MAC_CR(lp, cr); cr |= MAC_CR_TXEN_ | MAC_CR_HBDIS_; - SMC_SET_MAC_CR(cr); - SMC_SET_TX_CFG(TX_CFG_TX_ON_); - spin_unlock_irqrestore(&lp->lock, flags); + SMC_SET_MAC_CR(lp, cr); + SMC_SET_TX_CFG(lp, TX_CFG_TX_ON_); /* Add 2 byte padding to start of packets */ - SMC_SET_RX_CFG((2<<8) & RX_CFG_RXDOFF_); + SMC_SET_RX_CFG(lp, (2<<8) & RX_CFG_RXDOFF_); /* Turn on receiver and enable RX */ if (cr & MAC_CR_RXEN_) DBG(SMC_DEBUG_RX, "%s: Receiver already enabled\n", dev->name); - spin_lock_irqsave(&lp->lock, flags); - SMC_SET_MAC_CR( cr | MAC_CR_RXEN_ ); - spin_unlock_irqrestore(&lp->lock, flags); + SMC_SET_MAC_CR(lp, cr | MAC_CR_RXEN_); /* Interrupt on every received packet */ - SMC_SET_FIFO_RSA(0x01); - SMC_SET_FIFO_RSL(0x00); + SMC_SET_FIFO_RSA(lp, 0x01); + SMC_SET_FIFO_RSL(lp, 0x00); /* now, enable interrupts */ mask = INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_ | INT_EN_RSFL_EN_ | @@ -368,7 +314,9 @@ static void smc911x_enable(struct net_device *dev) else { mask|=INT_EN_RDFO_EN_; } - SMC_ENABLE_INT(mask); + SMC_ENABLE_INT(lp, mask); + + spin_unlock_irqrestore(&lp->lock, flags); } /* @@ -376,44 +324,43 @@ static void smc911x_enable(struct net_device *dev) */ static void smc911x_shutdown(struct net_device *dev) { - unsigned long ioaddr = dev->base_addr; struct smc911x_local *lp = netdev_priv(dev); unsigned cr; unsigned long flags; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", CARDNAME, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", CARDNAME, __func__); /* Disable IRQ's */ - SMC_SET_INT_EN(0); + SMC_SET_INT_EN(lp, 0); /* Turn of Rx and TX */ spin_lock_irqsave(&lp->lock, flags); - SMC_GET_MAC_CR(cr); + SMC_GET_MAC_CR(lp, cr); cr &= ~(MAC_CR_TXEN_ | MAC_CR_RXEN_ | MAC_CR_HBDIS_); - SMC_SET_MAC_CR(cr); - SMC_SET_TX_CFG(TX_CFG_STOP_TX_); + SMC_SET_MAC_CR(lp, cr); + SMC_SET_TX_CFG(lp, TX_CFG_STOP_TX_); spin_unlock_irqrestore(&lp->lock, flags); } static inline void smc911x_drop_pkt(struct net_device *dev) { - unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); unsigned int fifo_count, timeout, reg; - DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n", CARDNAME, __FUNCTION__); - fifo_count = SMC_GET_RX_FIFO_INF() & 0xFFFF; + DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n", CARDNAME, __func__); + fifo_count = SMC_GET_RX_FIFO_INF(lp) & 0xFFFF; if (fifo_count <= 4) { /* Manually dump the packet data */ while (fifo_count--) - SMC_GET_RX_FIFO(); + SMC_GET_RX_FIFO(lp); } else { /* Fast forward through the bad packet */ - SMC_SET_RX_DP_CTRL(RX_DP_CTRL_FFWD_BUSY_); + SMC_SET_RX_DP_CTRL(lp, RX_DP_CTRL_FFWD_BUSY_); timeout=50; do { udelay(10); - reg = SMC_GET_RX_DP_CTRL() & RX_DP_CTRL_FFWD_BUSY_; - } while ( timeout-- && reg); + reg = SMC_GET_RX_DP_CTRL(lp) & RX_DP_CTRL_FFWD_BUSY_; + } while (--timeout && reg); if (timeout == 0) { PRINTK("%s: timeout waiting for RX fast forward\n", dev->name); } @@ -429,15 +376,14 @@ static inline void smc911x_drop_pkt(struct net_device *dev) static inline void smc911x_rcv(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; unsigned int pkt_len, status; struct sk_buff *skb; unsigned char *data; DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n", - dev->name, __FUNCTION__); - status = SMC_GET_RX_STS_FIFO(); - DBG(SMC_DEBUG_RX, "%s: Rx pkt len %d status 0x%08x \n", + dev->name, __func__); + status = SMC_GET_RX_STS_FIFO(lp); + DBG(SMC_DEBUG_RX, "%s: Rx pkt len %d status 0x%08x\n", dev->name, (status & 0x3fff0000) >> 16, status & 0xc000ffff); pkt_len = (status & RX_STS_PKT_LEN_) >> 16; if (status & RX_STS_ES_) { @@ -475,25 +421,24 @@ static inline void smc911x_rcv(struct net_device *dev) { unsigned int fifo; /* Lower the FIFO threshold if possible */ - fifo = SMC_GET_FIFO_INT(); + fifo = SMC_GET_FIFO_INT(lp); if (fifo & 0xFF) fifo--; DBG(SMC_DEBUG_RX, "%s: Setting RX stat FIFO threshold to %d\n", dev->name, fifo & 0xff); - SMC_SET_FIFO_INT(fifo); + SMC_SET_FIFO_INT(lp, fifo); /* Setup RX DMA */ - SMC_SET_RX_CFG(RX_CFG_RX_END_ALGN16_ | ((2<<8) & RX_CFG_RXDOFF_)); + SMC_SET_RX_CFG(lp, RX_CFG_RX_END_ALGN16_ | ((2<<8) & RX_CFG_RXDOFF_)); lp->rxdma_active = 1; lp->current_rx_skb = skb; - SMC_PULL_DATA(data, (pkt_len+2+15) & ~15); + SMC_PULL_DATA(lp, data, (pkt_len+2+15) & ~15); /* Packet processing deferred to DMA RX interrupt */ } #else - SMC_SET_RX_CFG(RX_CFG_RX_END_ALGN4_ | ((2<<8) & RX_CFG_RXDOFF_)); - SMC_PULL_DATA(data, pkt_len+2+3); + SMC_SET_RX_CFG(lp, RX_CFG_RX_END_ALGN4_ | ((2<<8) & RX_CFG_RXDOFF_)); + SMC_PULL_DATA(lp, data, pkt_len+2+3); DBG(SMC_DEBUG_PKTS, "%s: Received packet\n", dev->name); PRINT_PKT(data, ((pkt_len - 4) <= 64) ? pkt_len - 4 : 64); - dev->last_rx = jiffies; skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); dev->stats.rx_packets++; @@ -508,13 +453,11 @@ static inline void smc911x_rcv(struct net_device *dev) static void smc911x_hardware_send_pkt(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; struct sk_buff *skb; unsigned int cmdA, cmdB, len; unsigned char *buf; - unsigned long flags; - DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", dev->name, __func__); BUG_ON(lp->pending_tx_skb == NULL); skb = lp->pending_tx_skb; @@ -541,8 +484,8 @@ static void smc911x_hardware_send_pkt(struct net_device *dev) DBG(SMC_DEBUG_TX, "%s: TX PKT LENGTH 0x%04x (%d) BUF 0x%p CMDA 0x%08x CMDB 0x%08x\n", dev->name, len, len, buf, cmdA, cmdB); - SMC_SET_TX_FIFO(cmdA); - SMC_SET_TX_FIFO(cmdB); + SMC_SET_TX_FIFO(lp, cmdA); + SMC_SET_TX_FIFO(lp, cmdB); DBG(SMC_DEBUG_PKTS, "%s: Transmitted packet\n", dev->name); PRINT_PKT(buf, len <= 64 ? len : 64); @@ -550,19 +493,17 @@ static void smc911x_hardware_send_pkt(struct net_device *dev) /* Send pkt via PIO or DMA */ #ifdef SMC_USE_DMA lp->current_tx_skb = skb; - SMC_PUSH_DATA(buf, len); + SMC_PUSH_DATA(lp, buf, len); /* DMA complete IRQ will free buffer and set jiffies */ #else - SMC_PUSH_DATA(buf, len); + SMC_PUSH_DATA(lp, buf, len); dev->trans_start = jiffies; - dev_kfree_skb(skb); + dev_kfree_skb_irq(skb); #endif - spin_lock_irqsave(&lp->lock, flags); if (!lp->tx_throttle) { netif_wake_queue(dev); } - spin_unlock_irqrestore(&lp->lock, flags); - SMC_ENABLE_INT(INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_); + SMC_ENABLE_INT(lp, INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_); } /* @@ -574,28 +515,27 @@ static void smc911x_hardware_send_pkt(struct net_device *dev) static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; unsigned int free; unsigned long flags; DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", - dev->name, __FUNCTION__); + dev->name, __func__); + + spin_lock_irqsave(&lp->lock, flags); BUG_ON(lp->pending_tx_skb != NULL); - free = SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TDFREE_; + free = SMC_GET_TX_FIFO_INF(lp) & TX_FIFO_INF_TDFREE_; DBG(SMC_DEBUG_TX, "%s: TX free space %d\n", dev->name, free); /* Turn off the flow when running out of space in FIFO */ if (free <= SMC911X_TX_FIFO_LOW_THRESHOLD) { DBG(SMC_DEBUG_TX, "%s: Disabling data flow due to low FIFO space (%d)\n", dev->name, free); - spin_lock_irqsave(&lp->lock, flags); /* Reenable when at least 1 packet of size MTU present */ - SMC_SET_FIFO_TDA((SMC911X_TX_FIFO_LOW_THRESHOLD)/64); + SMC_SET_FIFO_TDA(lp, (SMC911X_TX_FIFO_LOW_THRESHOLD)/64); lp->tx_throttle = 1; netif_stop_queue(dev); - spin_unlock_irqrestore(&lp->lock, flags); } /* Drop packets when we run out of space in TX FIFO @@ -611,8 +551,9 @@ static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) lp->pending_tx_skb = NULL; dev->stats.tx_errors++; dev->stats.tx_dropped++; + spin_unlock_irqrestore(&lp->lock, flags); dev_kfree_skb(skb); - return 0; + return NETDEV_TX_OK; } #ifdef SMC_USE_DMA @@ -620,24 +561,23 @@ static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) /* If the DMA is already running then defer this packet Tx until * the DMA IRQ starts it */ - spin_lock_irqsave(&lp->lock, flags); if (lp->txdma_active) { DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: Tx DMA running, deferring packet\n", dev->name); lp->pending_tx_skb = skb; netif_stop_queue(dev); spin_unlock_irqrestore(&lp->lock, flags); - return 0; + return NETDEV_TX_OK; } else { DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: Activating Tx DMA\n", dev->name); lp->txdma_active = 1; } - spin_unlock_irqrestore(&lp->lock, flags); } #endif lp->pending_tx_skb = skb; smc911x_hardware_send_pkt(dev); + spin_unlock_irqrestore(&lp->lock, flags); - return 0; + return NETDEV_TX_OK; } /* @@ -647,19 +587,18 @@ static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) */ static void smc911x_tx(struct net_device *dev) { - unsigned long ioaddr = dev->base_addr; struct smc911x_local *lp = netdev_priv(dev); unsigned int tx_status; DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", - dev->name, __FUNCTION__); + dev->name, __func__); /* Collect the TX status */ - while (((SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TSUSED_) >> 16) != 0) { + while (((SMC_GET_TX_FIFO_INF(lp) & TX_FIFO_INF_TSUSED_) >> 16) != 0) { DBG(SMC_DEBUG_TX, "%s: Tx stat FIFO used 0x%04x\n", dev->name, - (SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TSUSED_) >> 16); - tx_status = SMC_GET_TX_STS_FIFO(); + (SMC_GET_TX_FIFO_INF(lp) & TX_FIFO_INF_TSUSED_) >> 16); + tx_status = SMC_GET_TX_STS_FIFO(lp); dev->stats.tx_packets++; dev->stats.tx_bytes+=tx_status>>16; DBG(SMC_DEBUG_TX, "%s: Tx FIFO tag 0x%04x status 0x%04x\n", @@ -697,13 +636,13 @@ static void smc911x_tx(struct net_device *dev) static int smc911x_phy_read(struct net_device *dev, int phyaddr, int phyreg) { - unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); unsigned int phydata; - SMC_GET_MII(phyreg, phyaddr, phydata); + SMC_GET_MII(lp, phyreg, phyaddr, phydata); DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%02x, phydata=0x%04x\n", - __FUNCTION__, phyaddr, phyreg, phydata); + __func__, phyaddr, phyreg, phydata); return phydata; } @@ -714,12 +653,12 @@ static int smc911x_phy_read(struct net_device *dev, int phyaddr, int phyreg) static void smc911x_phy_write(struct net_device *dev, int phyaddr, int phyreg, int phydata) { - unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", - __FUNCTION__, phyaddr, phyreg, phydata); + __func__, phyaddr, phyreg, phydata); - SMC_SET_MII(phyreg, phyaddr, phydata); + SMC_SET_MII(lp, phyreg, phyaddr, phydata); } /* @@ -728,12 +667,11 @@ static void smc911x_phy_write(struct net_device *dev, int phyaddr, int phyreg, */ static void smc911x_phy_detect(struct net_device *dev) { - unsigned long ioaddr = dev->base_addr; struct smc911x_local *lp = netdev_priv(dev); int phyaddr; unsigned int cfg, id1, id2; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); lp->phy_type = 0; @@ -742,32 +680,34 @@ static void smc911x_phy_detect(struct net_device *dev) * PHY#1 to PHY#31, and then PHY#0 last. */ switch(lp->version) { - case 0x115: - case 0x117: - cfg = SMC_GET_HW_CFG(); + case CHIP_9115: + case CHIP_9117: + case CHIP_9215: + case CHIP_9217: + cfg = SMC_GET_HW_CFG(lp); if (cfg & HW_CFG_EXT_PHY_DET_) { cfg &= ~HW_CFG_PHY_CLK_SEL_; cfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_; - SMC_SET_HW_CFG(cfg); + SMC_SET_HW_CFG(lp, cfg); udelay(10); /* Wait for clocks to stop */ cfg |= HW_CFG_EXT_PHY_EN_; - SMC_SET_HW_CFG(cfg); + SMC_SET_HW_CFG(lp, cfg); udelay(10); /* Wait for clocks to stop */ cfg &= ~HW_CFG_PHY_CLK_SEL_; cfg |= HW_CFG_PHY_CLK_SEL_EXT_PHY_; - SMC_SET_HW_CFG(cfg); + SMC_SET_HW_CFG(lp, cfg); udelay(10); /* Wait for clocks to stop */ cfg |= HW_CFG_SMI_SEL_; - SMC_SET_HW_CFG(cfg); + SMC_SET_HW_CFG(lp, cfg); for (phyaddr = 1; phyaddr < 32; ++phyaddr) { /* Read the PHY identifiers */ - SMC_GET_PHY_ID1(phyaddr & 31, id1); - SMC_GET_PHY_ID2(phyaddr & 31, id2); + SMC_GET_PHY_ID1(lp, phyaddr & 31, id1); + SMC_GET_PHY_ID2(lp, phyaddr & 31, id2); /* Make sure it is a valid identifier */ if (id1 != 0x0000 && id1 != 0xffff && @@ -779,11 +719,14 @@ static void smc911x_phy_detect(struct net_device *dev) break; } } + if (phyaddr < 32) + /* Found an external PHY */ + break; } default: /* Internal media only */ - SMC_GET_PHY_ID1(1, id1); - SMC_GET_PHY_ID2(1, id2); + SMC_GET_PHY_ID1(lp, 1, id1); + SMC_GET_PHY_ID2(lp, 1, id2); /* Save the PHY's address */ lp->mii.phy_id = 1; lp->phy_type = id1 << 16 | id2; @@ -800,16 +743,15 @@ static void smc911x_phy_detect(struct net_device *dev) static int smc911x_phy_fixed(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; int phyaddr = lp->mii.phy_id; int bmcr; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); /* Enter Link Disable state */ - SMC_GET_PHY_BMCR(phyaddr, bmcr); + SMC_GET_PHY_BMCR(lp, phyaddr, bmcr); bmcr |= BMCR_PDOWN; - SMC_SET_PHY_BMCR(phyaddr, bmcr); + SMC_SET_PHY_BMCR(lp, phyaddr, bmcr); /* * Set our fixed capabilities @@ -823,11 +765,11 @@ static int smc911x_phy_fixed(struct net_device *dev) bmcr |= BMCR_SPEED100; /* Write our capabilities to the phy control register */ - SMC_SET_PHY_BMCR(phyaddr, bmcr); + SMC_SET_PHY_BMCR(lp, phyaddr, bmcr); /* Re-Configure the Receive/Phy Control register */ bmcr &= ~BMCR_PDOWN; - SMC_SET_PHY_BMCR(phyaddr, bmcr); + SMC_SET_PHY_BMCR(lp, phyaddr, bmcr); return 1; } @@ -847,23 +789,22 @@ static int smc911x_phy_fixed(struct net_device *dev) static int smc911x_phy_reset(struct net_device *dev, int phy) { struct smc911x_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; int timeout; unsigned long flags; unsigned int reg; - DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __func__); spin_lock_irqsave(&lp->lock, flags); - reg = SMC_GET_PMT_CTRL(); + reg = SMC_GET_PMT_CTRL(lp); reg &= ~0xfffff030; reg |= PMT_CTRL_PHY_RST_; - SMC_SET_PMT_CTRL(reg); + SMC_SET_PMT_CTRL(lp, reg); spin_unlock_irqrestore(&lp->lock, flags); for (timeout = 2; timeout; timeout--) { msleep(50); spin_lock_irqsave(&lp->lock, flags); - reg = SMC_GET_PMT_CTRL(); + reg = SMC_GET_PMT_CTRL(lp); spin_unlock_irqrestore(&lp->lock, flags); if (!(reg & PMT_CTRL_PHY_RST_)) { /* extra delay required because the phy may @@ -888,13 +829,13 @@ static int smc911x_phy_reset(struct net_device *dev, int phy) */ static void smc911x_phy_powerdown(struct net_device *dev, int phy) { - unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); unsigned int bmcr; /* Enter Link Disable state */ - SMC_GET_PHY_BMCR(phy, bmcr); + SMC_GET_PHY_BMCR(lp, phy, bmcr); bmcr |= BMCR_PDOWN; - SMC_SET_PHY_BMCR(phy, bmcr); + SMC_SET_PHY_BMCR(lp, phy, bmcr); } /* @@ -908,16 +849,15 @@ static void smc911x_phy_powerdown(struct net_device *dev, int phy) static void smc911x_phy_check_media(struct net_device *dev, int init) { struct smc911x_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; int phyaddr = lp->mii.phy_id; unsigned int bmcr, cr; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) { /* duplex state has changed */ - SMC_GET_PHY_BMCR(phyaddr, bmcr); - SMC_GET_MAC_CR(cr); + SMC_GET_PHY_BMCR(lp, phyaddr, bmcr); + SMC_GET_MAC_CR(lp, cr); if (lp->mii.full_duplex) { DBG(SMC_DEBUG_MISC, "%s: Configuring for full-duplex mode\n", dev->name); bmcr |= BMCR_FULLDPLX; @@ -927,8 +867,8 @@ static void smc911x_phy_check_media(struct net_device *dev, int init) bmcr &= ~BMCR_FULLDPLX; cr &= ~MAC_CR_RCVOWN_; } - SMC_SET_PHY_BMCR(phyaddr, bmcr); - SMC_SET_MAC_CR(cr); + SMC_SET_PHY_BMCR(lp, phyaddr, bmcr); + SMC_SET_MAC_CR(lp, cr); } } @@ -946,24 +886,23 @@ static void smc911x_phy_configure(struct work_struct *work) struct smc911x_local *lp = container_of(work, struct smc911x_local, phy_configure); struct net_device *dev = lp->netdev; - unsigned long ioaddr = dev->base_addr; int phyaddr = lp->mii.phy_id; int my_phy_caps; /* My PHY capabilities */ int my_ad_caps; /* My Advertised capabilities */ int status; unsigned long flags; - DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __func__); /* * We should not be called if phy_type is zero. */ if (lp->phy_type == 0) - goto smc911x_phy_configure_exit_nolock; + return; if (smc911x_phy_reset(dev, phyaddr)) { printk("%s: PHY reset timed out\n", dev->name); - goto smc911x_phy_configure_exit_nolock; + return; } spin_lock_irqsave(&lp->lock, flags); @@ -971,7 +910,7 @@ static void smc911x_phy_configure(struct work_struct *work) * Enable PHY Interrupts (for register 18) * Interrupts listed here are enabled */ - SMC_SET_PHY_INT_MASK(phyaddr, PHY_INT_MASK_ENERGY_ON_ | + SMC_SET_PHY_INT_MASK(lp, phyaddr, PHY_INT_MASK_ENERGY_ON_ | PHY_INT_MASK_ANEG_COMP_ | PHY_INT_MASK_REMOTE_FAULT_ | PHY_INT_MASK_LINK_DOWN_); @@ -982,7 +921,7 @@ static void smc911x_phy_configure(struct work_struct *work) } /* Copy our capabilities from MII_BMSR to MII_ADVERTISE */ - SMC_GET_PHY_BMSR(phyaddr, my_phy_caps); + SMC_GET_PHY_BMSR(lp, phyaddr, my_phy_caps); if (!(my_phy_caps & BMSR_ANEGCAPABLE)) { printk(KERN_INFO "Auto negotiation NOT supported\n"); smc911x_phy_fixed(dev); @@ -1011,7 +950,7 @@ static void smc911x_phy_configure(struct work_struct *work) my_ad_caps &= ~(ADVERTISE_100FULL|ADVERTISE_10FULL); /* Update our Auto-Neg Advertisement Register */ - SMC_SET_PHY_MII_ADV(phyaddr, my_ad_caps); + SMC_SET_PHY_MII_ADV(lp, phyaddr, my_ad_caps); lp->mii.advertising = my_ad_caps; /* @@ -1020,20 +959,18 @@ static void smc911x_phy_configure(struct work_struct *work) * the link does not come up. */ udelay(10); - SMC_GET_PHY_MII_ADV(phyaddr, status); + SMC_GET_PHY_MII_ADV(lp, phyaddr, status); DBG(SMC_DEBUG_MISC, "%s: phy caps=0x%04x\n", dev->name, my_phy_caps); DBG(SMC_DEBUG_MISC, "%s: phy advertised caps=0x%04x\n", dev->name, my_ad_caps); /* Restart auto-negotiation process in order to advertise my caps */ - SMC_SET_PHY_BMCR(phyaddr, BMCR_ANENABLE | BMCR_ANRESTART); + SMC_SET_PHY_BMCR(lp, phyaddr, BMCR_ANENABLE | BMCR_ANRESTART); smc911x_phy_check_media(dev, 1); smc911x_phy_configure_exit: spin_unlock_irqrestore(&lp->lock, flags); -smc911x_phy_configure_exit_nolock: - lp->work_pending = 0; } /* @@ -1045,22 +982,21 @@ smc911x_phy_configure_exit_nolock: static void smc911x_phy_interrupt(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; int phyaddr = lp->mii.phy_id; int status; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); if (lp->phy_type == 0) return; smc911x_phy_check_media(dev, 0); /* read to clear status bits */ - SMC_GET_PHY_INT_SRC(phyaddr,status); + SMC_GET_PHY_INT_SRC(lp, phyaddr,status); DBG(SMC_DEBUG_MISC, "%s: PHY interrupt status 0x%04x\n", dev->name, status & 0xffff); DBG(SMC_DEBUG_MISC, "%s: AFC_CFG 0x%08x\n", - dev->name, SMC_GET_AFC_CFG()); + dev->name, SMC_GET_AFC_CFG(lp)); } /*--- END PHY CONTROL AND CONFIGURATION-------------------------------------*/ @@ -1072,32 +1008,31 @@ static void smc911x_phy_interrupt(struct net_device *dev) static irqreturn_t smc911x_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; - unsigned long ioaddr = dev->base_addr; struct smc911x_local *lp = netdev_priv(dev); unsigned int status, mask, timeout; unsigned int rx_overrun=0, cr, pkts; unsigned long flags; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); spin_lock_irqsave(&lp->lock, flags); /* Spurious interrupt check */ - if ((SMC_GET_IRQ_CFG() & (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) != + if ((SMC_GET_IRQ_CFG(lp) & (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) != (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) { spin_unlock_irqrestore(&lp->lock, flags); return IRQ_NONE; } - mask = SMC_GET_INT_EN(); - SMC_SET_INT_EN(0); + mask = SMC_GET_INT_EN(lp); + SMC_SET_INT_EN(lp, 0); /* set a timeout value, so I don't stay here forever */ timeout = 8; do { - status = SMC_GET_INT(); + status = SMC_GET_INT(lp); DBG(SMC_DEBUG_MISC, "%s: INT 0x%08x MASK 0x%08x OUTSIDE MASK 0x%08x\n", dev->name, status, mask, status & ~mask); @@ -1108,53 +1043,53 @@ static irqreturn_t smc911x_interrupt(int irq, void *dev_id) /* Handle SW interrupt condition */ if (status & INT_STS_SW_INT_) { - SMC_ACK_INT(INT_STS_SW_INT_); + SMC_ACK_INT(lp, INT_STS_SW_INT_); mask &= ~INT_EN_SW_INT_EN_; } /* Handle various error conditions */ if (status & INT_STS_RXE_) { - SMC_ACK_INT(INT_STS_RXE_); + SMC_ACK_INT(lp, INT_STS_RXE_); dev->stats.rx_errors++; } if (status & INT_STS_RXDFH_INT_) { - SMC_ACK_INT(INT_STS_RXDFH_INT_); - dev->stats.rx_dropped+=SMC_GET_RX_DROP(); + SMC_ACK_INT(lp, INT_STS_RXDFH_INT_); + dev->stats.rx_dropped+=SMC_GET_RX_DROP(lp); } /* Undocumented interrupt-what is the right thing to do here? */ if (status & INT_STS_RXDF_INT_) { - SMC_ACK_INT(INT_STS_RXDF_INT_); + SMC_ACK_INT(lp, INT_STS_RXDF_INT_); } /* Rx Data FIFO exceeds set level */ if (status & INT_STS_RDFL_) { if (IS_REV_A(lp->revision)) { rx_overrun=1; - SMC_GET_MAC_CR(cr); + SMC_GET_MAC_CR(lp, cr); cr &= ~MAC_CR_RXEN_; - SMC_SET_MAC_CR(cr); + SMC_SET_MAC_CR(lp, cr); DBG(SMC_DEBUG_RX, "%s: RX overrun\n", dev->name); dev->stats.rx_errors++; dev->stats.rx_fifo_errors++; } - SMC_ACK_INT(INT_STS_RDFL_); + SMC_ACK_INT(lp, INT_STS_RDFL_); } if (status & INT_STS_RDFO_) { if (!IS_REV_A(lp->revision)) { - SMC_GET_MAC_CR(cr); + SMC_GET_MAC_CR(lp, cr); cr &= ~MAC_CR_RXEN_; - SMC_SET_MAC_CR(cr); + SMC_SET_MAC_CR(lp, cr); rx_overrun=1; DBG(SMC_DEBUG_RX, "%s: RX overrun\n", dev->name); dev->stats.rx_errors++; dev->stats.rx_fifo_errors++; } - SMC_ACK_INT(INT_STS_RDFO_); + SMC_ACK_INT(lp, INT_STS_RDFO_); } /* Handle receive condition */ if ((status & INT_STS_RSFL_) || rx_overrun) { unsigned int fifo; DBG(SMC_DEBUG_RX, "%s: RX irq\n", dev->name); - fifo = SMC_GET_RX_FIFO_INF(); + fifo = SMC_GET_RX_FIFO_INF(lp); pkts = (fifo & RX_FIFO_INF_RXSUSED_) >> 16; DBG(SMC_DEBUG_RX, "%s: Rx FIFO pkts %d, bytes %d\n", dev->name, pkts, fifo & 0xFFFF ); @@ -1165,82 +1100,80 @@ static irqreturn_t smc911x_interrupt(int irq, void *dev_id) DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA, "%s: RX DMA active\n", dev->name); /* The DMA is already running so up the IRQ threshold */ - fifo = SMC_GET_FIFO_INT() & ~0xFF; + fifo = SMC_GET_FIFO_INT(lp) & ~0xFF; fifo |= pkts & 0xFF; DBG(SMC_DEBUG_RX, "%s: Setting RX stat FIFO threshold to %d\n", dev->name, fifo & 0xff); - SMC_SET_FIFO_INT(fifo); + SMC_SET_FIFO_INT(lp, fifo); } else #endif smc911x_rcv(dev); } - SMC_ACK_INT(INT_STS_RSFL_); + SMC_ACK_INT(lp, INT_STS_RSFL_); } /* Handle transmit FIFO available */ if (status & INT_STS_TDFA_) { DBG(SMC_DEBUG_TX, "%s: TX data FIFO space available irq\n", dev->name); - SMC_SET_FIFO_TDA(0xFF); + SMC_SET_FIFO_TDA(lp, 0xFF); lp->tx_throttle = 0; #ifdef SMC_USE_DMA if (!lp->txdma_active) #endif netif_wake_queue(dev); - SMC_ACK_INT(INT_STS_TDFA_); + SMC_ACK_INT(lp, INT_STS_TDFA_); } /* Handle transmit done condition */ #if 1 if (status & (INT_STS_TSFL_ | INT_STS_GPT_INT_)) { DBG(SMC_DEBUG_TX | SMC_DEBUG_MISC, "%s: Tx stat FIFO limit (%d) /GPT irq\n", - dev->name, (SMC_GET_FIFO_INT() & 0x00ff0000) >> 16); + dev->name, (SMC_GET_FIFO_INT(lp) & 0x00ff0000) >> 16); smc911x_tx(dev); - SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000); - SMC_ACK_INT(INT_STS_TSFL_); - SMC_ACK_INT(INT_STS_TSFL_ | INT_STS_GPT_INT_); + SMC_SET_GPT_CFG(lp, GPT_CFG_TIMER_EN_ | 10000); + SMC_ACK_INT(lp, INT_STS_TSFL_); + SMC_ACK_INT(lp, INT_STS_TSFL_ | INT_STS_GPT_INT_); } #else if (status & INT_STS_TSFL_) { - DBG(SMC_DEBUG_TX, "%s: TX status FIFO limit (%d) irq \n", dev->name, ); + DBG(SMC_DEBUG_TX, "%s: TX status FIFO limit (%d) irq\n", dev->name, ); smc911x_tx(dev); - SMC_ACK_INT(INT_STS_TSFL_); + SMC_ACK_INT(lp, INT_STS_TSFL_); } if (status & INT_STS_GPT_INT_) { DBG(SMC_DEBUG_RX, "%s: IRQ_CFG 0x%08x FIFO_INT 0x%08x RX_CFG 0x%08x\n", dev->name, - SMC_GET_IRQ_CFG(), - SMC_GET_FIFO_INT(), - SMC_GET_RX_CFG()); + SMC_GET_IRQ_CFG(lp), + SMC_GET_FIFO_INT(lp), + SMC_GET_RX_CFG(lp)); DBG(SMC_DEBUG_RX, "%s: Rx Stat FIFO Used 0x%02x " "Data FIFO Used 0x%04x Stat FIFO 0x%08x\n", dev->name, - (SMC_GET_RX_FIFO_INF() & 0x00ff0000) >> 16, - SMC_GET_RX_FIFO_INF() & 0xffff, - SMC_GET_RX_STS_FIFO_PEEK()); - SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000); - SMC_ACK_INT(INT_STS_GPT_INT_); + (SMC_GET_RX_FIFO_INF(lp) & 0x00ff0000) >> 16, + SMC_GET_RX_FIFO_INF(lp) & 0xffff, + SMC_GET_RX_STS_FIFO_PEEK(lp)); + SMC_SET_GPT_CFG(lp, GPT_CFG_TIMER_EN_ | 10000); + SMC_ACK_INT(lp, INT_STS_GPT_INT_); } #endif - /* Handle PHY interupt condition */ + /* Handle PHY interrupt condition */ if (status & INT_STS_PHY_INT_) { DBG(SMC_DEBUG_MISC, "%s: PHY irq\n", dev->name); smc911x_phy_interrupt(dev); - SMC_ACK_INT(INT_STS_PHY_INT_); + SMC_ACK_INT(lp, INT_STS_PHY_INT_); } } while (--timeout); /* restore mask state */ - SMC_SET_INT_EN(mask); + SMC_SET_INT_EN(lp, mask); DBG(SMC_DEBUG_MISC, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout); spin_unlock_irqrestore(&lp->lock, flags); - DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout); - return IRQ_HANDLED; } @@ -1253,7 +1186,7 @@ smc911x_tx_dma_irq(int dma, void *data) struct sk_buff *skb = lp->current_tx_skb; unsigned long flags; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: TX DMA irq handler\n", dev->name); /* Clear the DMA interrupt sources */ @@ -1289,7 +1222,7 @@ smc911x_rx_dma_irq(int dma, void *data) unsigned long flags; unsigned int pkts; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA, "%s: RX DMA irq handler\n", dev->name); /* Clear the DMA interrupt sources */ SMC_DMA_ACK_IRQ(dev, dma); @@ -1297,14 +1230,13 @@ smc911x_rx_dma_irq(int dma, void *data) BUG_ON(skb == NULL); lp->current_rx_skb = NULL; PRINT_PKT(skb->data, skb->len); - dev->last_rx = jiffies; skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); dev->stats.rx_packets++; dev->stats.rx_bytes += skb->len; + netif_rx(skb); spin_lock_irqsave(&lp->lock, flags); - pkts = (SMC_GET_RX_FIFO_INF() & RX_FIFO_INF_RXSUSED_) >> 16; + pkts = (SMC_GET_RX_FIFO_INF(lp) & RX_FIFO_INF_RXSUSED_) >> 16; if (pkts != 0) { smc911x_rcv(dev); }else { @@ -1334,32 +1266,28 @@ static void smc911x_poll_controller(struct net_device *dev) static void smc911x_timeout(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; int status, mask; unsigned long flags; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); spin_lock_irqsave(&lp->lock, flags); - status = SMC_GET_INT(); - mask = SMC_GET_INT_EN(); + status = SMC_GET_INT(lp); + mask = SMC_GET_INT_EN(lp); spin_unlock_irqrestore(&lp->lock, flags); - DBG(SMC_DEBUG_MISC, "%s: INT 0x%02x MASK 0x%02x \n", + DBG(SMC_DEBUG_MISC, "%s: INT 0x%02x MASK 0x%02x\n", dev->name, status, mask); /* Dump the current TX FIFO contents and restart */ - mask = SMC_GET_TX_CFG(); - SMC_SET_TX_CFG(mask | TX_CFG_TXS_DUMP_ | TX_CFG_TXD_DUMP_); + mask = SMC_GET_TX_CFG(lp); + SMC_SET_TX_CFG(lp, mask | TX_CFG_TXS_DUMP_ | TX_CFG_TXD_DUMP_); /* * Reconfiguring the PHY doesn't seem like a bad idea here, but * smc911x_phy_configure() calls msleep() which calls schedule_timeout() * which calls schedule(). Hence we use a work queue. */ - if (lp->phy_type != 0) { - if (schedule_work(&lp->phy_configure)) { - lp->work_pending = 1; - } - } + if (lp->phy_type != 0) + schedule_work(&lp->phy_configure); /* We can accept TX packets again */ dev->trans_start = jiffies; @@ -1375,22 +1303,14 @@ static void smc911x_timeout(struct net_device *dev) static void smc911x_set_multicast_list(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; unsigned int multicast_table[2]; unsigned int mcr, update_multicast = 0; unsigned long flags; - /* table for flipping the order of 5 bits */ - static const unsigned char invert5[] = - {0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0C, 0x1C, - 0x02, 0x12, 0x0A, 0x1A, 0x06, 0x16, 0x0E, 0x1E, - 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0D, 0x1D, - 0x03, 0x13, 0x0B, 0x1B, 0x07, 0x17, 0x0F, 0x1F}; - - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); spin_lock_irqsave(&lp->lock, flags); - SMC_GET_MAC_CR(mcr); + SMC_GET_MAC_CR(lp, mcr); spin_unlock_irqrestore(&lp->lock, flags); if (dev->flags & IFF_PROMISC) { @@ -1403,7 +1323,7 @@ static void smc911x_set_multicast_list(struct net_device *dev) * I don't need to zero the multicast table, because the flag is * checked before the table is */ - else if (dev->flags & IFF_ALLMULTI || dev->mc_count > 16) { + else if (dev->flags & IFF_ALLMULTI || netdev_mc_count(dev) > 16) { DBG(SMC_DEBUG_MISC, "%s: RCR_ALMUL\n", dev->name); mcr |= MAC_CR_MCPAS_; } @@ -1420,9 +1340,8 @@ static void smc911x_set_multicast_list(struct net_device *dev) * the number of the 32 bit register, while the low 5 bits are the bit * within that register. */ - else if (dev->mc_count) { - int i; - struct dev_mc_list *cur_addr; + else if (!netdev_mc_empty(dev)) { + struct netdev_hw_addr *ha; /* Set the Hash perfec mode */ mcr |= MAC_CR_HPFILT_; @@ -1430,24 +1349,18 @@ static void smc911x_set_multicast_list(struct net_device *dev) /* start with a table of all zeros: reject all */ memset(multicast_table, 0, sizeof(multicast_table)); - cur_addr = dev->mc_list; - for (i = 0; i < dev->mc_count; i++, cur_addr = cur_addr->next) { - int position; + netdev_for_each_mc_addr(ha, dev) { + u32 position; - /* do we have a pointer here? */ - if (!cur_addr) - break; /* make sure this is a multicast address - shouldn't this be a given if we have it here ? */ - if (!(*cur_addr->dmi_addr & 1)) - continue; + if (!(*ha->addr & 1)) + continue; - /* only use the low order bits */ - position = crc32_le(~0, cur_addr->dmi_addr, 6) & 0x3f; + /* upper 6 bits are used as hash index */ + position = ether_crc(ETH_ALEN, ha->addr)>>26; - /* do some messy swapping to put the bit in the right spot */ - multicast_table[invert5[position&0x1F]&0x1] |= - (1<>1)&0x1F]); + multicast_table[position>>5] |= 1 << (position&0x1f); } /* be sure I get rid of flags I might have set */ @@ -1469,13 +1382,13 @@ static void smc911x_set_multicast_list(struct net_device *dev) } spin_lock_irqsave(&lp->lock, flags); - SMC_SET_MAC_CR(mcr); + SMC_SET_MAC_CR(lp, mcr); if (update_multicast) { DBG(SMC_DEBUG_MISC, "%s: update mcast hash table 0x%08x 0x%08x\n", dev->name, multicast_table[0], multicast_table[1]); - SMC_SET_HASHL(multicast_table[0]); - SMC_SET_HASHH(multicast_table[1]); + SMC_SET_HASHL(lp, multicast_table[0]); + SMC_SET_HASHH(lp, multicast_table[1]); } spin_unlock_irqrestore(&lp->lock, flags); } @@ -1491,7 +1404,7 @@ smc911x_open(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); /* * Check that the address is valid. If its not, refuse @@ -1499,7 +1412,7 @@ smc911x_open(struct net_device *dev) * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx */ if (!is_valid_ether_addr(dev->dev_addr)) { - PRINTK("%s: no valid ethernet hw addr\n", __FUNCTION__); + PRINTK("%s: no valid ethernet hw addr\n", __func__); return -EINVAL; } @@ -1528,7 +1441,7 @@ static int smc911x_close(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); netif_stop_queue(dev); netif_carrier_off(dev); @@ -1539,16 +1452,8 @@ static int smc911x_close(struct net_device *dev) if (lp->phy_type != 0) { /* We need to ensure that no calls to * smc911x_phy_configure are pending. - - * flush_scheduled_work() cannot be called because we - * are running with the netlink semaphore held (from - * devinet_ioctl()) and the pending work queue - * contains linkwatch_event() (scheduled by - * netif_carrier_off() above). linkwatch_event() also - * wants the netlink semaphore. */ - while (lp->work_pending) - schedule(); + cancel_work_sync(&lp->phy_configure); smc911x_phy_powerdown(dev, lp->mii.phy_id); } @@ -1567,11 +1472,10 @@ static int smc911x_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd) { struct smc911x_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; int ret, status; unsigned long flags; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); cmd->maxtxpkt = 1; cmd->maxrxpkt = 1; @@ -1595,7 +1499,7 @@ smc911x_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd) else cmd->transceiver = XCVR_EXTERNAL; cmd->port = 0; - SMC_GET_PHY_SPECIAL(lp->mii.phy_id, status); + SMC_GET_PHY_SPECIAL(lp, lp->mii.phy_id, status); cmd->duplex = (status & (PHY_SPECIAL_SPD_10FULL_ | PHY_SPECIAL_SPD_100FULL_)) ? DUPLEX_FULL : DUPLEX_HALF; @@ -1636,7 +1540,7 @@ smc911x_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { strncpy(info->driver, CARDNAME, sizeof(info->driver)); strncpy(info->version, version, sizeof(info->version)); - strncpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info)); + strncpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info)); } static int smc911x_ethtool_nwayreset(struct net_device *dev) @@ -1676,7 +1580,6 @@ static int smc911x_ethtool_getregslen(struct net_device *dev) static void smc911x_ethtool_getregs(struct net_device *dev, struct ethtool_regs* regs, void *buf) { - unsigned long ioaddr = dev->base_addr; struct smc911x_local *lp = netdev_priv(dev); unsigned long flags; u32 reg,i,j=0; @@ -1684,17 +1587,17 @@ static void smc911x_ethtool_getregs(struct net_device *dev, regs->version = lp->version; for(i=ID_REV;i<=E2P_CMD;i+=4) { - data[j++] = SMC_inl(ioaddr,i); + data[j++] = SMC_inl(lp, i); } for(i=MAC_CR;i<=WUCSR;i++) { spin_lock_irqsave(&lp->lock, flags); - SMC_GET_MAC_CSR(i, reg); + SMC_GET_MAC_CSR(lp, i, reg); spin_unlock_irqrestore(&lp->lock, flags); data[j++] = reg; } for(i=0;i<=31;i++) { spin_lock_irqsave(&lp->lock, flags); - SMC_GET_MII(i, lp->mii.phy_id, reg); + SMC_GET_MII(lp, i, lp->mii.phy_id, reg); spin_unlock_irqrestore(&lp->lock, flags); data[j++] = reg & 0xFFFF; } @@ -1702,23 +1605,23 @@ static void smc911x_ethtool_getregs(struct net_device *dev, static int smc911x_ethtool_wait_eeprom_ready(struct net_device *dev) { - unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); unsigned int timeout; int e2p_cmd; - e2p_cmd = SMC_GET_E2P_CMD(); + e2p_cmd = SMC_GET_E2P_CMD(lp); for(timeout=10;(e2p_cmd & E2P_CMD_EPC_BUSY_) && timeout; timeout--) { if (e2p_cmd & E2P_CMD_EPC_TIMEOUT_) { PRINTK("%s: %s timeout waiting for EEPROM to respond\n", - dev->name, __FUNCTION__); + dev->name, __func__); return -EFAULT; } mdelay(1); - e2p_cmd = SMC_GET_E2P_CMD(); + e2p_cmd = SMC_GET_E2P_CMD(lp); } if (timeout == 0) { PRINTK("%s: %s timeout waiting for EEPROM CMD not busy\n", - dev->name, __FUNCTION__); + dev->name, __func__); return -ETIMEDOUT; } return 0; @@ -1727,12 +1630,12 @@ static int smc911x_ethtool_wait_eeprom_ready(struct net_device *dev) static inline int smc911x_ethtool_write_eeprom_cmd(struct net_device *dev, int cmd, int addr) { - unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); int ret; if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0) return ret; - SMC_SET_E2P_CMD(E2P_CMD_EPC_BUSY_ | + SMC_SET_E2P_CMD(lp, E2P_CMD_EPC_BUSY_ | ((cmd) & (0x7<<28)) | ((addr) & 0xFF)); return 0; @@ -1741,24 +1644,24 @@ static inline int smc911x_ethtool_write_eeprom_cmd(struct net_device *dev, static inline int smc911x_ethtool_read_eeprom_byte(struct net_device *dev, u8 *data) { - unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); int ret; if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0) return ret; - *data = SMC_GET_E2P_DATA(); + *data = SMC_GET_E2P_DATA(lp); return 0; } static inline int smc911x_ethtool_write_eeprom_byte(struct net_device *dev, u8 data) { - unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); int ret; if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0) return ret; - SMC_SET_E2P_DATA(data); + SMC_SET_E2P_DATA(lp, data); return 0; } @@ -1825,12 +1728,13 @@ static const struct ethtool_ops smc911x_ethtool_ops = { * This routine has a simple purpose -- make the SMC chip generate an * interrupt, so an auto-detect routine can detect it, and find the IRQ, */ -static int __init smc911x_findirq(unsigned long ioaddr) +static int __devinit smc911x_findirq(struct net_device *dev) { + struct smc911x_local *lp = netdev_priv(dev); int timeout = 20; unsigned long cookie; - DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "--> %s\n", __func__); cookie = probe_irq_on(); @@ -1838,7 +1742,7 @@ static int __init smc911x_findirq(unsigned long ioaddr) * Force a SW interrupt */ - SMC_SET_INT_EN(INT_EN_SW_INT_EN_); + SMC_SET_INT_EN(lp, INT_EN_SW_INT_EN_); /* * Wait until positive that the interrupt has been generated @@ -1846,7 +1750,7 @@ static int __init smc911x_findirq(unsigned long ioaddr) do { int int_status; udelay(10); - int_status = SMC_GET_INT_EN(); + int_status = SMC_GET_INT_EN(lp); if (int_status & INT_EN_SW_INT_EN_) break; /* got the interrupt */ } while (--timeout); @@ -1859,12 +1763,26 @@ static int __init smc911x_findirq(unsigned long ioaddr) */ /* and disable all interrupts again */ - SMC_SET_INT_EN(0); + SMC_SET_INT_EN(lp, 0); /* and return what I found */ return probe_irq_off(cookie); } +static const struct net_device_ops smc911x_netdev_ops = { + .ndo_open = smc911x_open, + .ndo_stop = smc911x_close, + .ndo_start_xmit = smc911x_hard_start_xmit, + .ndo_tx_timeout = smc911x_timeout, + .ndo_set_multicast_list = smc911x_set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = smc911x_poll_controller, +#endif +}; + /* * Function: smc911x_probe(unsigned long ioaddr) * @@ -1888,20 +1806,21 @@ static int __init smc911x_findirq(unsigned long ioaddr) * o actually GRAB the irq. * o GRAB the region */ -static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr) +static int __devinit smc911x_probe(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); int i, retval; unsigned int val, chip_id, revision; const char *version_string; + unsigned long irq_flags; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); /* First, see if the endian word is recognized */ - val = SMC_GET_BYTE_TEST(); + val = SMC_GET_BYTE_TEST(lp); DBG(SMC_DEBUG_MISC, "%s: endian probe returned 0x%04x\n", CARDNAME, val); if (val != 0x87654321) { - printk(KERN_ERR "Invalid chip endian 0x08%x\n",val); + printk(KERN_ERR "Invalid chip endian 0x%08x\n",val); retval = -ENODEV; goto err_out; } @@ -1911,7 +1830,7 @@ static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr) * recognize. These might need to be added to later, * as future revisions could be added. */ - chip_id = SMC_GET_PN(); + chip_id = SMC_GET_PN(lp); DBG(SMC_DEBUG_MISC, "%s: id probe returned 0x%04x\n", CARDNAME, chip_id); for(i=0;chip_ids[i].id != 0; i++) { if (chip_ids[i].id == chip_id) break; @@ -1923,7 +1842,7 @@ static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr) } version_string = chip_ids[i].name; - revision = SMC_GET_REV(); + revision = SMC_GET_REV(lp); DBG(SMC_DEBUG_MISC, "%s: revision = 0x%04x\n", CARDNAME, revision); /* At this point I'll assume that the chip is an SMC911x. */ @@ -1937,7 +1856,6 @@ static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr) } /* fill in some of the fields */ - dev->base_addr = ioaddr; lp->version = chip_ids[i].id; lp->revision = revision; lp->tx_fifo_kb = tx_fifo_kb; @@ -1996,7 +1914,7 @@ static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr) spin_lock_init(&lp->lock); /* Get the MAC address */ - SMC_GET_MAC_ADDR(dev->dev_addr); + SMC_GET_MAC_ADDR(lp, dev->dev_addr); /* now, reset the chip, and put it into a known state */ smc911x_reset(dev); @@ -2013,7 +1931,7 @@ static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr) trials = 3; while (trials--) { - dev->irq = smc911x_findirq(ioaddr); + dev->irq = smc911x_findirq(dev); if (dev->irq) break; /* kick the card and try again */ @@ -2031,16 +1949,9 @@ static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr) /* Fill in the fields of the device structure with ethernet values. */ ether_setup(dev); - dev->open = smc911x_open; - dev->stop = smc911x_close; - dev->hard_start_xmit = smc911x_hard_start_xmit; - dev->tx_timeout = smc911x_timeout; + dev->netdev_ops = &smc911x_netdev_ops; dev->watchdog_timeo = msecs_to_jiffies(watchdog); - dev->set_multicast_list = smc911x_set_multicast_list; dev->ethtool_ops = &smc911x_ethtool_ops; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = smc911x_poll_controller; -#endif INIT_WORK(&lp->phy_configure, smc911x_phy_configure); lp->mii.phy_id_mask = 0x1f; @@ -2061,9 +1972,15 @@ static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr) lp->ctl_rfduplx = 1; lp->ctl_rspeed = 100; +#ifdef SMC_DYNAMIC_BUS_CONFIG + irq_flags = lp->cfg.irq_flags; +#else + irq_flags = IRQF_SHARED | SMC_IRQ_SENSE; +#endif + /* Grab the IRQ */ - retval = request_irq(dev->irq, &smc911x_interrupt, - IRQF_SHARED | SMC_IRQ_SENSE, dev->name, dev); + retval = request_irq(dev->irq, smc911x_interrupt, + irq_flags, dev->name, dev); if (retval) goto err_out; @@ -2095,10 +2012,8 @@ static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr) "set using ifconfig\n", dev->name); } else { /* Print the Ethernet address */ - printk("%s: Ethernet addr: ", dev->name); - for (i = 0; i < 5; i++) - printk("%2.2x:", dev->dev_addr[i]); - printk("%2.2x\n", dev->dev_addr[5]); + printk("%s: Ethernet addr: %pM\n", + dev->name, dev->dev_addr); } if (lp->phy_type == 0) { @@ -2131,7 +2046,7 @@ err_out: * 0 --> there is a device * anything else, error */ -static int smc911x_drv_probe(struct platform_device *pdev) +static int __devinit smc911x_drv_probe(struct platform_device *pdev) { struct net_device *ndev; struct resource *res; @@ -2139,7 +2054,7 @@ static int smc911x_drv_probe(struct platform_device *pdev) unsigned int *addr; int ret; - DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "--> %s\n", __func__); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { ret = -ENODEV; @@ -2166,6 +2081,16 @@ static int smc911x_drv_probe(struct platform_device *pdev) ndev->irq = platform_get_irq(pdev, 0); lp = netdev_priv(ndev); lp->netdev = ndev; +#ifdef SMC_DYNAMIC_BUS_CONFIG + { + struct smc911x_platdata *pd = pdev->dev.platform_data; + if (!pd) { + ret = -EINVAL; + goto release_both; + } + memcpy(&lp->cfg, pd, sizeof(lp->cfg)); + } +#endif addr = ioremap(res->start, SMC911X_IO_EXTENT); if (!addr) { @@ -2174,7 +2099,9 @@ static int smc911x_drv_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, ndev); - ret = smc911x_probe(ndev, (unsigned long)addr); + lp->base = addr; + ndev->base_addr = res->start; + ret = smc911x_probe(ndev); if (ret != 0) { platform_set_drvdata(pdev, NULL); iounmap(addr); @@ -2195,12 +2122,13 @@ out: return ret; } -static int smc911x_drv_remove(struct platform_device *pdev) +static int __devexit smc911x_drv_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); + struct smc911x_local *lp = netdev_priv(ndev); struct resource *res; - DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "--> %s\n", __func__); platform_set_drvdata(pdev, NULL); unregister_netdev(ndev); @@ -2209,7 +2137,6 @@ static int smc911x_drv_remove(struct platform_device *pdev) #ifdef SMC_USE_DMA { - struct smc911x_local *lp = netdev_priv(ndev); if (lp->rxdma != -1) { SMC_DMA_FREE(dev, lp->rxdma); } @@ -2218,7 +2145,7 @@ static int smc911x_drv_remove(struct platform_device *pdev) } } #endif - iounmap((void *)ndev->base_addr); + iounmap(lp->base); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(res->start, SMC911X_IO_EXTENT); @@ -2229,16 +2156,16 @@ static int smc911x_drv_remove(struct platform_device *pdev) static int smc911x_drv_suspend(struct platform_device *dev, pm_message_t state) { struct net_device *ndev = platform_get_drvdata(dev); - unsigned long ioaddr = ndev->base_addr; + struct smc911x_local *lp = netdev_priv(ndev); - DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "--> %s\n", __func__); if (ndev) { if (netif_running(ndev)) { netif_device_detach(ndev); smc911x_shutdown(ndev); #if POWER_DOWN /* Set D2 - Energy detect only setting */ - SMC_SET_PMT_CTRL(2<<12); + SMC_SET_PMT_CTRL(lp, 2<<12); #endif } } @@ -2249,15 +2176,15 @@ static int smc911x_drv_resume(struct platform_device *dev) { struct net_device *ndev = platform_get_drvdata(dev); - DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "--> %s\n", __func__); if (ndev) { struct smc911x_local *lp = netdev_priv(ndev); if (netif_running(ndev)) { smc911x_reset(ndev); - smc911x_enable(ndev); if (lp->phy_type != 0) smc911x_phy_configure(&lp->phy_configure); + smc911x_enable(ndev); netif_device_attach(ndev); } } @@ -2266,11 +2193,12 @@ static int smc911x_drv_resume(struct platform_device *dev) static struct platform_driver smc911x_driver = { .probe = smc911x_drv_probe, - .remove = smc911x_drv_remove, + .remove = __devexit_p(smc911x_drv_remove), .suspend = smc911x_drv_suspend, .resume = smc911x_drv_resume, .driver = { .name = CARDNAME, + .owner = THIS_MODULE, }, };