[PATCH] via-rhine: change mdelay to msleep and remove from ISR path
[safe/jmp/linux-2.6] / drivers / net / bnx2.c
index da903b3..3a2ace0 100644 (file)
@@ -14,8 +14,8 @@
 
 #define DRV_MODULE_NAME                "bnx2"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "1.2.19"
-#define DRV_MODULE_RELDATE     "May 23, 2005"
+#define DRV_MODULE_VERSION     "1.2.21"
+#define DRV_MODULE_RELDATE     "September 7, 2005"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -1350,15 +1350,13 @@ bnx2_tx_int(struct bnx2 *bp)
        bp->tx_cons = sw_cons;
 
        if (unlikely(netif_queue_stopped(bp->dev))) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&bp->tx_lock, flags);
+               spin_lock(&bp->tx_lock);
                if ((netif_queue_stopped(bp->dev)) &&
                    (bnx2_tx_avail(bp) > MAX_SKB_FRAGS)) {
 
                        netif_wake_queue(bp->dev);
                }
-               spin_unlock_irqrestore(&bp->tx_lock, flags);
+               spin_unlock(&bp->tx_lock);
        }
 }
 
@@ -1535,20 +1533,18 @@ bnx2_msi(int irq, void *dev_instance, struct pt_regs *regs)
        struct net_device *dev = dev_instance;
        struct bnx2 *bp = dev->priv;
 
+       prefetch(bp->status_blk);
        REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
                BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
                BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
 
        /* Return here if interrupt is disabled. */
-       if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
-               return IRQ_RETVAL(1);
-       }
+       if (unlikely(atomic_read(&bp->intr_sem) != 0))
+               return IRQ_HANDLED;
 
-       if (netif_rx_schedule_prep(dev)) {
-               __netif_rx_schedule(dev);
-       }
+       netif_rx_schedule(dev);
 
-       return IRQ_RETVAL(1);
+       return IRQ_HANDLED;
 }
 
 static irqreturn_t
@@ -1563,25 +1559,22 @@ bnx2_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
         * When using MSI, the MSI message will always complete after
         * the status block write.
         */
-       if ((bp->status_blk->status_idx == bp->last_status_idx) ||
+       if ((bp->status_blk->status_idx == bp->last_status_idx) &&
            (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) &
             BNX2_PCICFG_MISC_STATUS_INTA_VALUE))
-               return IRQ_RETVAL(0);
+               return IRQ_NONE;
 
        REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
                BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
                BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
 
        /* Return here if interrupt is shared and is disabled. */
-       if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
-               return IRQ_RETVAL(1);
-       }
+       if (unlikely(atomic_read(&bp->intr_sem) != 0))
+               return IRQ_HANDLED;
 
-       if (netif_rx_schedule_prep(dev)) {
-               __netif_rx_schedule(dev);
-       }
+       netif_rx_schedule(dev);
 
-       return IRQ_RETVAL(1);
+       return IRQ_HANDLED;
 }
 
 static int
@@ -1598,11 +1591,9 @@ bnx2_poll(struct net_device *dev, int *budget)
                (bp->status_blk->status_attn_bits_ack &
                STATUS_ATTN_BITS_LINK_STATE)) {
 
-               unsigned long flags;
-
-               spin_lock_irqsave(&bp->phy_lock, flags);
+               spin_lock(&bp->phy_lock);
                bnx2_phy_int(bp);
-               spin_unlock_irqrestore(&bp->phy_lock, flags);
+               spin_unlock(&bp->phy_lock);
        }
 
        if (bp->status_blk->status_tx_quick_consumer_index0 != bp->tx_cons) {
@@ -1645,9 +1636,8 @@ bnx2_set_rx_mode(struct net_device *dev)
        struct bnx2 *bp = dev->priv;
        u32 rx_mode, sort_mode;
        int i;
-       unsigned long flags;
 
-       spin_lock_irqsave(&bp->phy_lock, flags);
+       spin_lock_bh(&bp->phy_lock);
 
        rx_mode = bp->rx_mode & ~(BNX2_EMAC_RX_MODE_PROMISCUOUS |
                                  BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG);
@@ -1708,7 +1698,7 @@ bnx2_set_rx_mode(struct net_device *dev)
        REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode);
        REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode | BNX2_RPM_SORT_USER0_ENA);
 
-       spin_unlock_irqrestore(&bp->phy_lock, flags);
+       spin_unlock_bh(&bp->phy_lock);
 }
 
 static void
@@ -2015,14 +2005,14 @@ bnx2_init_cpus(struct bnx2 *bp)
 }
 
 static int
-bnx2_set_power_state(struct bnx2 *bp, int state)
+bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
 {
        u16 pmcsr;
 
        pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr);
 
        switch (state) {
-       case 0: {
+       case PCI_D0: {
                u32 val;
 
                pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
@@ -2043,7 +2033,7 @@ bnx2_set_power_state(struct bnx2 *bp, int state)
                REG_WR(bp, BNX2_RPM_CONFIG, val);
                break;
        }
-       case 3: {
+       case PCI_D3hot: {
                int i;
                u32 val, wol_msg;
 
@@ -3768,10 +3758,10 @@ bnx2_test_link(struct bnx2 *bp)
 {
        u32 bmsr;
 
-       spin_lock_irq(&bp->phy_lock);
+       spin_lock_bh(&bp->phy_lock);
        bnx2_read_phy(bp, MII_BMSR, &bmsr);
        bnx2_read_phy(bp, MII_BMSR, &bmsr);
-       spin_unlock_irq(&bp->phy_lock);
+       spin_unlock_bh(&bp->phy_lock);
                
        if (bmsr & BMSR_LSTATUS) {
                return 0;
@@ -3828,9 +3818,8 @@ bnx2_timer(unsigned long data)
 
        if ((bp->phy_flags & PHY_SERDES_FLAG) &&
            (CHIP_NUM(bp) == CHIP_NUM_5706)) {
-               unsigned long flags;
 
-               spin_lock_irqsave(&bp->phy_lock, flags);
+               spin_lock(&bp->phy_lock);
                if (bp->serdes_an_pending) {
                        bp->serdes_an_pending--;
                }
@@ -3884,7 +3873,7 @@ bnx2_timer(unsigned long data)
                else
                        bp->current_interval = bp->timer_interval;
 
-               spin_unlock_irqrestore(&bp->phy_lock, flags);
+               spin_unlock(&bp->phy_lock);
        }
 
 bnx2_restart_timer:
@@ -3898,7 +3887,7 @@ bnx2_open(struct net_device *dev)
        struct bnx2 *bp = dev->priv;
        int rc;
 
-       bnx2_set_power_state(bp, 0);
+       bnx2_set_power_state(bp, PCI_D0);
        bnx2_disable_int(bp);
 
        rc = bnx2_alloc_mem(bp);
@@ -4168,14 +4157,12 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
        dev->trans_start = jiffies;
 
        if (unlikely(bnx2_tx_avail(bp) <= MAX_SKB_FRAGS)) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&bp->tx_lock, flags);
+               spin_lock(&bp->tx_lock);
                netif_stop_queue(dev);
                
                if (bnx2_tx_avail(bp) > MAX_SKB_FRAGS)
                        netif_wake_queue(dev);
-               spin_unlock_irqrestore(&bp->tx_lock, flags);
+               spin_unlock(&bp->tx_lock);
        }
 
        return NETDEV_TX_OK;
@@ -4211,7 +4198,7 @@ bnx2_close(struct net_device *dev)
        bnx2_free_mem(bp);
        bp->link_up = 0;
        netif_carrier_off(bp->dev);
-       bnx2_set_power_state(bp, 3);
+       bnx2_set_power_state(bp, PCI_D3hot);
        return 0;
 }
 
@@ -4411,11 +4398,11 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        bp->req_line_speed = req_line_speed;
        bp->req_duplex = req_duplex;
 
-       spin_lock_irq(&bp->phy_lock);
+       spin_lock_bh(&bp->phy_lock);
 
        bnx2_setup_phy(bp);
 
-       spin_unlock_irq(&bp->phy_lock);
+       spin_unlock_bh(&bp->phy_lock);
 
        return 0;
 }
@@ -4485,16 +4472,16 @@ bnx2_nway_reset(struct net_device *dev)
                return -EINVAL;
        }
 
-       spin_lock_irq(&bp->phy_lock);
+       spin_lock_bh(&bp->phy_lock);
 
        /* Force a link down visible on the other side */
        if (bp->phy_flags & PHY_SERDES_FLAG) {
                bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
-               spin_unlock_irq(&bp->phy_lock);
+               spin_unlock_bh(&bp->phy_lock);
 
                msleep(20);
 
-               spin_lock_irq(&bp->phy_lock);
+               spin_lock_bh(&bp->phy_lock);
                if (CHIP_NUM(bp) == CHIP_NUM_5706) {
                        bp->current_interval = SERDES_AN_TIMEOUT;
                        bp->serdes_an_pending = 1;
@@ -4506,7 +4493,7 @@ bnx2_nway_reset(struct net_device *dev)
        bmcr &= ~BMCR_LOOPBACK;
        bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART | BMCR_ANENABLE);
 
-       spin_unlock_irq(&bp->phy_lock);
+       spin_unlock_bh(&bp->phy_lock);
 
        return 0;
 }
@@ -4692,11 +4679,11 @@ bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
                bp->autoneg &= ~AUTONEG_FLOW_CTRL;
        }
 
-       spin_lock_irq(&bp->phy_lock);
+       spin_lock_bh(&bp->phy_lock);
 
        bnx2_setup_phy(bp);
 
-       spin_unlock_irq(&bp->phy_lock);
+       spin_unlock_bh(&bp->phy_lock);
 
        return 0;
 }
@@ -5028,6 +5015,7 @@ static struct ethtool_ops bnx2_ethtool_ops = {
        .phys_id                = bnx2_phys_id,
        .get_stats_count        = bnx2_get_stats_count,
        .get_ethtool_stats      = bnx2_get_ethtool_stats,
+       .get_perm_addr          = ethtool_op_get_perm_addr,
 };
 
 /* Called with rtnl_lock */
@@ -5046,9 +5034,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        case SIOCGMIIREG: {
                u32 mii_regval;
 
-               spin_lock_irq(&bp->phy_lock);
+               spin_lock_bh(&bp->phy_lock);
                err = bnx2_read_phy(bp, data->reg_num & 0x1f, &mii_regval);
-               spin_unlock_irq(&bp->phy_lock);
+               spin_unlock_bh(&bp->phy_lock);
 
                data->val_out = mii_regval;
 
@@ -5059,9 +5047,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
 
-               spin_lock_irq(&bp->phy_lock);
+               spin_lock_bh(&bp->phy_lock);
                err = bnx2_write_phy(bp, data->reg_num & 0x1f, data->val_in);
-               spin_unlock_irq(&bp->phy_lock);
+               spin_unlock_bh(&bp->phy_lock);
 
                return err;
 
@@ -5079,6 +5067,9 @@ bnx2_change_mac_addr(struct net_device *dev, void *p)
        struct sockaddr *addr = p;
        struct bnx2 *bp = dev->priv;
 
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EINVAL;
+
        memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
        if (netif_running(dev))
                bnx2_set_mac_addr(bp);
@@ -5214,7 +5205,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
                               BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
                               BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP);
 
-       bnx2_set_power_state(bp, 0);
+       bnx2_set_power_state(bp, PCI_D0);
 
        bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
 
@@ -5377,6 +5368,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 err_out_unmap:
        if (bp->regview) {
                iounmap(bp->regview);
+               bp->regview = NULL;
        }
 
 err_out_release:
@@ -5451,6 +5443,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        pci_set_drvdata(pdev, dev);
 
        memcpy(dev->dev_addr, bp->mac_addr, 6);
+       memcpy(dev->perm_addr, bp->mac_addr, 6);
        bp->name = board_info[ent->driver_data].name,
        printk(KERN_INFO "%s: %s (%c%d) PCI%s %s %dMHz found at mem %lx, "
                "IRQ %d, ",
@@ -5505,7 +5498,7 @@ bnx2_remove_one(struct pci_dev *pdev)
 }
 
 static int
-bnx2_suspend(struct pci_dev *pdev, u32 state)
+bnx2_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct bnx2 *bp = dev->priv;
@@ -5523,7 +5516,7 @@ bnx2_suspend(struct pci_dev *pdev, u32 state)
                reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
        bnx2_reset_chip(bp, reset_code);
        bnx2_free_skbs(bp);
-       bnx2_set_power_state(bp, state);
+       bnx2_set_power_state(bp, pci_choose_state(pdev, state));
        return 0;
 }
 
@@ -5536,7 +5529,7 @@ bnx2_resume(struct pci_dev *pdev)
        if (!netif_running(dev))
                return 0;
 
-       bnx2_set_power_state(bp, 0);
+       bnx2_set_power_state(bp, PCI_D0);
        netif_device_attach(dev);
        bnx2_init_nic(bp);
        bnx2_netif_start(bp);