[PATCH] ipw2100/ipw2200: jiffies_round -> jiffies_round_relative
[safe/jmp/linux-2.6] / drivers / net / bnx2.c
index 0e4928c..da767d3 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/dma-mapping.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <linux/delay.h>
@@ -56,8 +56,8 @@
 
 #define DRV_MODULE_NAME                "bnx2"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "1.6.6"
-#define DRV_MODULE_RELDATE     "October 2, 2007"
+#define DRV_MODULE_VERSION     "1.6.8"
+#define DRV_MODULE_RELDATE     "October 17, 2007"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -2633,15 +2633,11 @@ bnx2_has_work(struct bnx2 *bp)
        return 0;
 }
 
-static int
-bnx2_poll(struct napi_struct *napi, int budget)
+static int bnx2_poll_work(struct bnx2 *bp, int work_done, int budget)
 {
-       struct bnx2 *bp = container_of(napi, struct bnx2, napi);
-       struct net_device *dev = bp->dev;
        struct status_block *sblk = bp->status_blk;
        u32 status_attn_bits = sblk->status_attn_bits;
        u32 status_attn_bits_ack = sblk->status_attn_bits_ack;
-       int work_done = 0;
 
        if ((status_attn_bits & STATUS_ATTN_EVENTS) !=
            (status_attn_bits_ack & STATUS_ATTN_EVENTS)) {
@@ -2656,31 +2652,51 @@ bnx2_poll(struct napi_struct *napi, int budget)
                REG_RD(bp, BNX2_HC_COMMAND);
        }
 
-       if (bp->status_blk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)
+       if (sblk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)
                bnx2_tx_int(bp);
 
-       if (bp->status_blk->status_rx_quick_consumer_index0 != bp->hw_rx_cons)
-               work_done = bnx2_rx_int(bp, budget);
+       if (sblk->status_rx_quick_consumer_index0 != bp->hw_rx_cons)
+               work_done += bnx2_rx_int(bp, budget - work_done);
 
-       bp->last_status_idx = bp->status_blk->status_idx;
-       rmb();
+       return work_done;
+}
+
+static int bnx2_poll(struct napi_struct *napi, int budget)
+{
+       struct bnx2 *bp = container_of(napi, struct bnx2, napi);
+       int work_done = 0;
+       struct status_block *sblk = bp->status_blk;
+
+       while (1) {
+               work_done = bnx2_poll_work(bp, work_done, budget);
+
+               if (unlikely(work_done >= budget))
+                       break;
+
+               /* bp->last_status_idx is used below to tell the hw how
+                * much work has been processed, so we must read it before
+                * checking for more work.
+                */
+               bp->last_status_idx = sblk->status_idx;
+               rmb();
+               if (likely(!bnx2_has_work(bp))) {
+                       netif_rx_complete(bp->dev, napi);
+                       if (likely(bp->flags & USING_MSI_FLAG)) {
+                               REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+                                      BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+                                      bp->last_status_idx);
+                               break;
+                       }
+                       REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+                              BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+                              BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
+                              bp->last_status_idx);
 
-       if (!bnx2_has_work(bp)) {
-               netif_rx_complete(dev, napi);
-               if (likely(bp->flags & USING_MSI_FLAG)) {
                        REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
                               BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
                               bp->last_status_idx);
-                       return 0;
+                       break;
                }
-               REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
-                      BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
-                      BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
-                      bp->last_status_idx);
-
-               REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
-                      BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
-                      bp->last_status_idx);
        }
 
        return work_done;
@@ -3063,14 +3079,18 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
                        autoneg = bp->autoneg;
                        advertising = bp->advertising;
 
-                       bp->autoneg = AUTONEG_SPEED;
-                       bp->advertising = ADVERTISED_10baseT_Half |
-                               ADVERTISED_10baseT_Full |
-                               ADVERTISED_100baseT_Half |
-                               ADVERTISED_100baseT_Full |
-                               ADVERTISED_Autoneg;
+                       if (bp->phy_port == PORT_TP) {
+                               bp->autoneg = AUTONEG_SPEED;
+                               bp->advertising = ADVERTISED_10baseT_Half |
+                                       ADVERTISED_10baseT_Full |
+                                       ADVERTISED_100baseT_Half |
+                                       ADVERTISED_100baseT_Full |
+                                       ADVERTISED_Autoneg;
+                       }
 
-                       bnx2_setup_copper_phy(bp);
+                       spin_lock_bh(&bp->phy_lock);
+                       bnx2_setup_phy(bp, bp->phy_port);
+                       spin_unlock_bh(&bp->phy_lock);
 
                        bp->autoneg = autoneg;
                        bp->advertising = advertising;
@@ -3081,10 +3101,16 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
 
                        /* Enable port mode. */
                        val &= ~BNX2_EMAC_MODE_PORT;
-                       val |= BNX2_EMAC_MODE_PORT_MII |
-                              BNX2_EMAC_MODE_MPKT_RCVD |
+                       val |= BNX2_EMAC_MODE_MPKT_RCVD |
                               BNX2_EMAC_MODE_ACPI_RCVD |
                               BNX2_EMAC_MODE_MPKT;
+                       if (bp->phy_port == PORT_TP)
+                               val |= BNX2_EMAC_MODE_PORT_MII;
+                       else {
+                               val |= BNX2_EMAC_MODE_PORT_GMII;
+                               if (bp->line_speed == SPEED_2500)
+                                       val |= BNX2_EMAC_MODE_25G_MODE;
+                       }
 
                        REG_WR(bp, BNX2_EMAC_MODE, val);
 
@@ -3776,12 +3802,6 @@ bnx2_init_remote_phy(struct bnx2 *bp)
                return;
 
        if (val & BNX2_FW_CAP_REMOTE_PHY_CAPABLE) {
-               if (netif_running(bp->dev)) {
-                       val = BNX2_DRV_ACK_CAP_SIGNATURE |
-                             BNX2_FW_CAP_REMOTE_PHY_CAPABLE;
-                       REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_ACK_CAP_MB,
-                                  val);
-               }
                bp->phy_flags |= REMOTE_PHY_CAP_FLAG;
 
                val = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS);
@@ -3789,6 +3809,22 @@ bnx2_init_remote_phy(struct bnx2 *bp)
                        bp->phy_port = PORT_FIBRE;
                else
                        bp->phy_port = PORT_TP;
+
+               if (netif_running(bp->dev)) {
+                       u32 sig;
+
+                       if (val & BNX2_LINK_STATUS_LINK_UP) {
+                               bp->link_up = 1;
+                               netif_carrier_on(bp->dev);
+                       } else {
+                               bp->link_up = 0;
+                               netif_carrier_off(bp->dev);
+                       }
+                       sig = BNX2_DRV_ACK_CAP_SIGNATURE |
+                             BNX2_FW_CAP_REMOTE_PHY_CAPABLE;
+                       REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_ACK_CAP_MB,
+                                  sig);
+               }
        }
 }
 
@@ -3797,6 +3833,7 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
 {
        u32 val;
        int i, rc = 0;
+       u8 old_port;
 
        /* Wait for the current PCI transaction to complete before
         * issuing a reset. */
@@ -3875,8 +3912,9 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
                return rc;
 
        spin_lock_bh(&bp->phy_lock);
+       old_port = bp->phy_port;
        bnx2_init_remote_phy(bp);
-       if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+       if ((bp->phy_flags & REMOTE_PHY_CAP_FLAG) && old_port != bp->phy_port)
                bnx2_set_default_remote_link(bp);
        spin_unlock_bh(&bp->phy_lock);
 
@@ -4565,6 +4603,9 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
                bnx2_set_mac_loopback(bp);
        }
        else if (loopback_mode == BNX2_PHY_LOOPBACK) {
+               if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+                       return 0;
+
                bp->loopback = PHY_LOOPBACK;
                bnx2_set_phy_loopback(bp);
        }
@@ -4733,6 +4774,11 @@ bnx2_test_link(struct bnx2 *bp)
 {
        u32 bmsr;
 
+       if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) {
+               if (bp->link_up)
+                       return 0;
+               return -ENODEV;
+       }
        spin_lock_bh(&bp->phy_lock);
        bnx2_enable_bmsr1(bp);
        bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr);
@@ -6392,7 +6438,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
        /* enable device (incl. PCI PM wakeup), and bus-mastering */
        rc = pci_enable_device(pdev);
        if (rc) {
-               dev_err(&pdev->dev, "Cannot enable PCI device, aborting.");
+               dev_err(&pdev->dev, "Cannot enable PCI device, aborting.\n");
                goto err_out;
        }
 
@@ -6549,8 +6595,11 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
                if (i != 2)
                        bp->fw_version[j++] = '.';
        }
-       if (REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_FEATURE) &
-           BNX2_PORT_FEATURE_ASF_ENABLED) {
+       reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_FEATURE);
+       if (reg & BNX2_PORT_FEATURE_WOL_ENABLED)
+               bp->wol = 1;
+
+       if (reg & BNX2_PORT_FEATURE_ASF_ENABLED) {
                bp->flags |= ASF_ENABLE_FLAG;
 
                for (i = 0; i < 30; i++) {
@@ -6620,11 +6669,14 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
        bp->phy_port = PORT_TP;
        if (bp->phy_flags & PHY_SERDES_FLAG) {
                bp->phy_port = PORT_FIBRE;
-               bp->flags |= NO_WOL_FLAG;
+               reg = REG_RD_IND(bp, bp->shmem_base +
+                                    BNX2_SHARED_HW_CFG_CONFIG);
+               if (!(reg & BNX2_SHARED_HW_CFG_GIG_LINK_ON_VAUX)) {
+                       bp->flags |= NO_WOL_FLAG;
+                       bp->wol = 0;
+               }
                if (CHIP_NUM(bp) != CHIP_NUM_5706) {
                        bp->phy_addr = 2;
-                       reg = REG_RD_IND(bp, bp->shmem_base +
-                                        BNX2_SHARED_HW_CFG_CONFIG);
                        if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G)
                                bp->phy_flags |= PHY_2_5G_CAPABLE_FLAG;
                }
@@ -6639,8 +6691,10 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 
        if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
            (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
-           (CHIP_ID(bp) == CHIP_ID_5708_B1))
+           (CHIP_ID(bp) == CHIP_ID_5708_B1)) {
                bp->flags |= NO_WOL_FLAG;
+               bp->wol = 0;
+       }
 
        if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
                bp->tx_quick_cons_trip_int =