]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/bnx2.c
r8169: update the phy init for the 8168C
[linux-2.6-omap-h63xx.git] / drivers / net / bnx2.c
index 73d4a579790c5761f42aac5ddb3000ec0ba26d73..78ed633ceb829e121161a8a230a1350d9de06017 100644 (file)
@@ -56,8 +56,8 @@
 
 #define DRV_MODULE_NAME                "bnx2"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "1.6.5"
-#define DRV_MODULE_RELDATE     "September 20, 2007"
+#define DRV_MODULE_VERSION     "1.6.7"
+#define DRV_MODULE_RELDATE     "October 10, 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;
 
-       if (!bnx2_has_work(bp)) {
-               netif_rx_complete(dev, napi);
-               if (likely(bp->flags & USING_MSI_FLAG)) {
+               /* 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);
-                       return 0;
-               }
-               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);
+                       REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+                              BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+                              bp->last_status_idx);
+                       break;
+               }
        }
 
        return work_done;
@@ -2761,48 +2777,6 @@ bnx2_set_rx_mode(struct net_device *dev)
        spin_unlock_bh(&bp->phy_lock);
 }
 
-/* To be moved to generic lib/ */
-static int
-bnx2_gunzip(void *gunzip_buf, unsigned sz, u8 *zbuf, int len)
-{
-       struct z_stream_s *strm;
-       int rc;
-
-       /* gzip header (1f,8b,08... 10 bytes total + possible asciz filename)
-        * is stripped */
-
-       rc = -ENOMEM;
-       strm = kmalloc(sizeof(*strm), GFP_KERNEL);
-       if (strm == NULL)
-               goto gunzip_nomem2;
-       strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
-       if (strm->workspace == NULL)
-               goto gunzip_nomem3;
-
-       strm->next_in = zbuf;
-       strm->avail_in = len;
-       strm->next_out = gunzip_buf;
-       strm->avail_out = sz;
-
-       rc = zlib_inflateInit2(strm, -MAX_WBITS);
-       if (rc == Z_OK) {
-               rc = zlib_inflate(strm, Z_FINISH);
-               /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */
-               if (rc == Z_STREAM_END)
-                       rc = sz - strm->avail_out;
-               else
-                       rc = -EINVAL;
-               zlib_inflateEnd(strm);
-       } else
-               rc = -EINVAL;
-
-       kfree(strm->workspace);
-gunzip_nomem3:
-       kfree(strm);
-gunzip_nomem2:
-       return rc;
-}
-
 static void
 load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len,
        u32 rv2p_proc)
@@ -2852,21 +2826,16 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
        /* Load the Text area. */
        offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base);
        if (fw->gz_text) {
-               u32 *text;
                int j;
 
-               text = vmalloc(FW_BUF_SIZE);
-               if (!text)
-                       return -ENOMEM;
-               rc = bnx2_gunzip(text, FW_BUF_SIZE, fw->gz_text, fw->gz_text_len);
-               if (rc < 0) {
-                       vfree(text);
+               rc = zlib_inflate_blob(fw->text, FW_BUF_SIZE, fw->gz_text,
+                                      fw->gz_text_len);
+               if (rc < 0)
                        return rc;
-               }
+
                for (j = 0; j < (fw->text_len / 4); j++, offset += 4) {
-                       REG_WR_IND(bp, offset, cpu_to_le32(text[j]));
+                       REG_WR_IND(bp, offset, cpu_to_le32(fw->text[j]));
                }
-               vfree(text);
        }
 
        /* Load the Data area. */
@@ -2881,21 +2850,21 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
 
        /* Load the SBSS area. */
        offset = cpu_reg->spad_base + (fw->sbss_addr - cpu_reg->mips_view_base);
-       if (fw->sbss) {
+       if (fw->sbss_len) {
                int j;
 
                for (j = 0; j < (fw->sbss_len / 4); j++, offset += 4) {
-                       REG_WR_IND(bp, offset, fw->sbss[j]);
+                       REG_WR_IND(bp, offset, 0);
                }
        }
 
        /* Load the BSS area. */
        offset = cpu_reg->spad_base + (fw->bss_addr - cpu_reg->mips_view_base);
-       if (fw->bss) {
+       if (fw->bss_len) {
                int j;
 
                for (j = 0; j < (fw->bss_len/4); j++, offset += 4) {
-                       REG_WR_IND(bp, offset, fw->bss[j]);
+                       REG_WR_IND(bp, offset, 0);
                }
        }
 
@@ -2935,20 +2904,17 @@ bnx2_init_cpus(struct bnx2 *bp)
        text = vmalloc(FW_BUF_SIZE);
        if (!text)
                return -ENOMEM;
-       rc = bnx2_gunzip(text, FW_BUF_SIZE, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1));
-       if (rc < 0) {
-               vfree(text);
+       rc = zlib_inflate_blob(text, FW_BUF_SIZE, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1));
+       if (rc < 0)
                goto init_cpu_err;
-       }
+
        load_rv2p_fw(bp, text, rc /* == len */, RV2P_PROC1);
 
-       rc = bnx2_gunzip(text, FW_BUF_SIZE, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2));
-       if (rc < 0) {
-               vfree(text);
+       rc = zlib_inflate_blob(text, FW_BUF_SIZE, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2));
+       if (rc < 0)
                goto init_cpu_err;
-       }
+
        load_rv2p_fw(bp, text, rc /* == len */, RV2P_PROC2);
-       vfree(text);
 
        /* Initialize the RX Processor. */
        cpu_reg.mode = BNX2_RXP_CPU_MODE;
@@ -2969,6 +2935,7 @@ bnx2_init_cpus(struct bnx2 *bp)
        else
                fw = &bnx2_rxp_fw_06;
 
+       fw->text = text;
        rc = load_cpu_fw(bp, &cpu_reg, fw);
        if (rc)
                goto init_cpu_err;
@@ -2992,6 +2959,7 @@ bnx2_init_cpus(struct bnx2 *bp)
        else
                fw = &bnx2_txp_fw_06;
 
+       fw->text = text;
        rc = load_cpu_fw(bp, &cpu_reg, fw);
        if (rc)
                goto init_cpu_err;
@@ -3015,6 +2983,7 @@ bnx2_init_cpus(struct bnx2 *bp)
        else
                fw = &bnx2_tpat_fw_06;
 
+       fw->text = text;
        rc = load_cpu_fw(bp, &cpu_reg, fw);
        if (rc)
                goto init_cpu_err;
@@ -3038,6 +3007,7 @@ bnx2_init_cpus(struct bnx2 *bp)
        else
                fw = &bnx2_com_fw_06;
 
+       fw->text = text;
        rc = load_cpu_fw(bp, &cpu_reg, fw);
        if (rc)
                goto init_cpu_err;
@@ -3059,11 +3029,13 @@ bnx2_init_cpus(struct bnx2 *bp)
        if (CHIP_NUM(bp) == CHIP_NUM_5709) {
                fw = &bnx2_cp_fw_09;
 
+               fw->text = text;
                rc = load_cpu_fw(bp, &cpu_reg, fw);
                if (rc)
                        goto init_cpu_err;
        }
 init_cpu_err:
+       vfree(text);
        return rc;
 }
 
@@ -3820,12 +3792,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);
@@ -3833,6 +3799,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);
+               }
        }
 }
 
@@ -3841,6 +3823,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. */
@@ -3919,8 +3902,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);
 
@@ -4609,6 +4593,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);
        }
@@ -4777,6 +4764,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);
@@ -6593,8 +6585,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++) {
@@ -6664,11 +6659,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;
                }
@@ -6683,8 +6681,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 =