]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/net/tg3.c
tg3: Use VPD fw version when present
[net-next-2.6.git] / drivers / net / tg3.c
index c7134c37936ed4d33aad556331de1bd11d3f700a..c002b9f97cdf86ef4966c53216d2ff30892ec2d7 100644 (file)
@@ -4335,8 +4335,11 @@ static void tg3_tx_recover(struct tg3 *tp)
        BUG_ON((tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) ||
               tp->write32_tx_mbox == tg3_write_indirect_mbox);
 
-       netdev_warn(tp->dev, "The system may be re-ordering memory-mapped I/O cycles to the network device, attempting to recover\n"
-                   "Please report the problem to the driver maintainer and include system chipset information.\n");
+       netdev_warn(tp->dev,
+                   "The system may be re-ordering memory-mapped I/O "
+                   "cycles to the network device, attempting to recover. "
+                   "Please report the problem to the driver maintainer "
+                   "and include system chipset information.\n");
 
        spin_lock(&tp->lock);
        tp->tg3_flags |= TG3_FLAG_TX_RECOVERY_PENDING;
@@ -5260,7 +5263,8 @@ static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
 
        err = tg3_init_hw(tp, reset_phy);
        if (err) {
-               netdev_err(tp->dev, "Failed to re-initialize device, aborting\n");
+               netdev_err(tp->dev,
+                          "Failed to re-initialize device, aborting\n");
                tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
                tg3_full_unlock(tp);
                del_timer_sync(&tp->timer);
@@ -5508,7 +5512,8 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
                        netif_tx_stop_queue(txq);
 
                        /* This is a hard error, log it. */
-                       netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
+                       netdev_err(dev,
+                                  "BUG! Tx Ring full when queue awake!\n");
                }
                return NETDEV_TX_BUSY;
        }
@@ -5711,7 +5716,8 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
                        netif_tx_stop_queue(txq);
 
                        /* This is a hard error, log it. */
-                       netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
+                       netdev_err(dev,
+                                  "BUG! Tx Ring full when queue awake!\n");
                }
                return NETDEV_TX_BUSY;
        }
@@ -6058,8 +6064,10 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
        /* Now allocate fresh SKBs for each rx ring. */
        for (i = 0; i < tp->rx_pending; i++) {
                if (tg3_alloc_rx_skb(tp, tpr, RXD_OPAQUE_RING_STD, i) < 0) {
-                       netdev_warn(tp->dev, "Using a smaller RX standard ring, only %d out of %d buffers were allocated successfully\n",
-                                   i, tp->rx_pending);
+                       netdev_warn(tp->dev,
+                                   "Using a smaller RX standard ring. Only "
+                                   "%d out of %d buffers were allocated "
+                                   "successfully\n", i, tp->rx_pending);
                        if (i == 0)
                                goto initfail;
                        tp->rx_pending = i;
@@ -6088,8 +6096,10 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
 
        for (i = 0; i < tp->rx_jumbo_pending; i++) {
                if (tg3_alloc_rx_skb(tp, tpr, RXD_OPAQUE_RING_JUMBO, i) < 0) {
-                       netdev_warn(tp->dev, "Using a smaller RX jumbo ring, only %d out of %d buffers were allocated successfully\n",
-                                   i, tp->rx_jumbo_pending);
+                       netdev_warn(tp->dev,
+                                   "Using a smaller RX jumbo ring. Only %d "
+                                   "out of %d buffers were allocated "
+                                   "successfully\n", i, tp->rx_jumbo_pending);
                        if (i == 0)
                                goto initfail;
                        tp->rx_jumbo_pending = i;
@@ -7158,7 +7168,8 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
 
        if (cpu_base == TX_CPU_BASE &&
            (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
-               netdev_err(tp->dev, "%s: Trying to load TX cpu firmware which is 5705\n",
+               netdev_err(tp->dev,
+                          "%s: Trying to load TX cpu firmware which is 5705\n",
                           __func__);
                return -EINVAL;
        }
@@ -7238,7 +7249,8 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
                udelay(1000);
        }
        if (i >= 5) {
-               netdev_err(tp->dev, "tg3_load_firmware fails to set RX CPU PC, is %08x should be %08x\n",
+               netdev_err(tp->dev, "%s fails to set RX CPU PC, is %08x "
+                          "should be %08x\n", __func__,
                           tr32(RX_CPU_BASE + CPU_PC), info.fw_base);
                return -ENODEV;
        }
@@ -7302,7 +7314,8 @@ static int tg3_load_tso_firmware(struct tg3 *tp)
                udelay(1000);
        }
        if (i >= 5) {
-               netdev_err(tp->dev, "%s fails to set CPU PC, is %08x should be %08x\n",
+               netdev_err(tp->dev,
+                          "%s fails to set CPU PC, is %08x should be %08x\n",
                           __func__, tr32(cpu_base + CPU_PC), info.fw_base);
                return -ENODEV;
        }
@@ -8627,8 +8640,9 @@ static int tg3_test_msi(struct tg3 *tp)
                return err;
 
        /* MSI test failed, go back to INTx mode */
-       netdev_warn(tp->dev, "No interrupt was generated using MSI, switching to INTx mode\n"
-                   "Please report this failure to the PCI maintainer and include system chipset information\n");
+       netdev_warn(tp->dev, "No interrupt was generated using MSI. Switching "
+                   "to INTx mode. Please report this failure to the PCI "
+                   "maintainer and include system chipset information\n");
 
        free_irq(tp->napi[0].irq_vec, &tp->napi[0]);
 
@@ -8740,7 +8754,8 @@ static void tg3_ints_init(struct tg3 *tp)
                /* All MSI supporting chips should support tagged
                 * status.  Assert that this is the case.
                 */
-               netdev_warn(tp->dev, "MSI without TAGGED? Not using MSI\n");
+               netdev_warn(tp->dev,
+                           "MSI without TAGGED_STATUS? Not using MSI\n");
                goto defcfg;
        }
 
@@ -11778,7 +11793,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
                tp->tg3_flags |= TG3_FLAG_NVRAM;
 
                if (tg3_nvram_lock(tp)) {
-                       netdev_warn(tp->dev, "Cannot get nvram lock, %s failed\n",
+                       netdev_warn(tp->dev,
+                                   "Cannot get nvram lock, %s failed\n",
                                    __func__);
                        return;
                }
@@ -12547,11 +12563,11 @@ skip_phy_reset:
        return err;
 }
 
-static void __devinit tg3_read_partno(struct tg3 *tp)
+static void __devinit tg3_read_vpd(struct tg3 *tp)
 {
-       unsigned char vpd_data[TG3_NVM_VPD_LEN];   /* in little-endian format */
+       u8 vpd_data[TG3_NVM_VPD_LEN];
        unsigned int block_end, rosize, len;
-       int i = 0;
+       int j, i = 0;
        u32 magic;
 
        if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) ||
@@ -12600,6 +12616,32 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
        if (block_end > TG3_NVM_VPD_LEN)
                goto out_not_found;
 
+       j = pci_vpd_find_info_keyword(vpd_data, i, rosize,
+                                     PCI_VPD_RO_KEYWORD_MFR_ID);
+       if (j > 0) {
+               len = pci_vpd_info_field_size(&vpd_data[j]);
+
+               j += PCI_VPD_INFO_FLD_HDR_SIZE;
+               if (j + len > block_end || len != 4 ||
+                   memcmp(&vpd_data[j], "1028", 4))
+                       goto partno;
+
+               j = pci_vpd_find_info_keyword(vpd_data, i, rosize,
+                                             PCI_VPD_RO_KEYWORD_VENDOR0);
+               if (j < 0)
+                       goto partno;
+
+               len = pci_vpd_info_field_size(&vpd_data[j]);
+
+               j += PCI_VPD_INFO_FLD_HDR_SIZE;
+               if (j + len > block_end)
+                       goto partno;
+
+               memcpy(tp->fw_ver, &vpd_data[j], len);
+               strncat(tp->fw_ver, " bc ", TG3_NVM_VPD_LEN - len - 1);
+       }
+
+partno:
        i = pci_vpd_find_info_keyword(vpd_data, i, rosize,
                                      PCI_VPD_RO_KEYWORD_PARTNO);
        if (i < 0)
@@ -12669,7 +12711,7 @@ static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
 static void __devinit tg3_read_bc_ver(struct tg3 *tp)
 {
        u32 val, offset, start, ver_offset;
-       int i;
+       int i, dst_off;
        bool newver = false;
 
        if (tg3_nvram_read(tp, 0xc, &offset) ||
@@ -12689,8 +12731,11 @@ static void __devinit tg3_read_bc_ver(struct tg3 *tp)
                        newver = true;
        }
 
+       dst_off = strlen(tp->fw_ver);
+
        if (newver) {
-               if (tg3_nvram_read(tp, offset + 8, &ver_offset))
+               if (TG3_VER_SIZE - dst_off < 16 ||
+                   tg3_nvram_read(tp, offset + 8, &ver_offset))
                        return;
 
                offset = offset + ver_offset - start;
@@ -12699,7 +12744,7 @@ static void __devinit tg3_read_bc_ver(struct tg3 *tp)
                        if (tg3_nvram_read_be32(tp, offset + i, &v))
                                return;
 
-                       memcpy(tp->fw_ver + i, &v, sizeof(v));
+                       memcpy(tp->fw_ver + dst_off + i, &v, sizeof(v));
                }
        } else {
                u32 major, minor;
@@ -12710,7 +12755,8 @@ static void __devinit tg3_read_bc_ver(struct tg3 *tp)
                major = (ver_offset & TG3_NVM_BCVER_MAJMSK) >>
                        TG3_NVM_BCVER_MAJSFT;
                minor = ver_offset & TG3_NVM_BCVER_MINMSK;
-               snprintf(&tp->fw_ver[0], 32, "v%d.%02d", major, minor);
+               snprintf(&tp->fw_ver[dst_off], TG3_VER_SIZE - dst_off,
+                        "v%d.%02d", major, minor);
        }
 }
 
@@ -12734,9 +12780,7 @@ static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val)
 {
        u32 offset, major, minor, build;
 
-       tp->fw_ver[0] = 's';
-       tp->fw_ver[1] = 'b';
-       tp->fw_ver[2] = '\0';
+       strncat(tp->fw_ver, "sb", TG3_VER_SIZE - strlen(tp->fw_ver) - 1);
 
        if ((val & TG3_EEPROM_SB_FORMAT_MASK) != TG3_EEPROM_SB_FORMAT_1)
                return;
@@ -12773,11 +12817,14 @@ static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val)
        if (minor > 99 || build > 26)
                return;
 
-       snprintf(&tp->fw_ver[2], 30, " v%d.%02d", major, minor);
+       offset = strlen(tp->fw_ver);
+       snprintf(&tp->fw_ver[offset], TG3_VER_SIZE - offset,
+                " v%d.%02d", major, minor);
 
        if (build > 0) {
-               tp->fw_ver[8] = 'a' + build - 1;
-               tp->fw_ver[9] = '\0';
+               offset = strlen(tp->fw_ver);
+               if (offset < TG3_VER_SIZE - 1)
+                       tp->fw_ver[offset] = 'a' + build - 1;
        }
 }
 
@@ -12864,12 +12911,13 @@ static void __devinit tg3_read_dash_ver(struct tg3 *tp)
 static void __devinit tg3_read_fw_ver(struct tg3 *tp)
 {
        u32 val;
+       bool vpd_vers = false;
 
-       if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) {
-               tp->fw_ver[0] = 's';
-               tp->fw_ver[1] = 'b';
-               tp->fw_ver[2] = '\0';
+       if (tp->fw_ver[0] != 0)
+               vpd_vers = true;
 
+       if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) {
+               strcat(tp->fw_ver, "sb");
                return;
        }
 
@@ -12886,11 +12934,12 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp)
                return;
 
        if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
-            (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
-               return;
+            (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) || vpd_vers)
+               goto done;
 
        tg3_read_mgmtfw_ver(tp);
 
+done:
        tp->fw_ver[TG3_VER_SIZE - 1] = 0;
 }
 
@@ -13603,7 +13652,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                tg3_mdio_fini(tp);
        }
 
-       tg3_read_partno(tp);
+       tg3_read_vpd(tp);
        tg3_read_fw_ver(tp);
 
        if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
@@ -14130,9 +14179,8 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
                /* Now read it back. */
                ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 0);
                if (ret) {
-                       dev_err(&tp->pdev->dev,
-                               "%s: Buffer read failed. err = %d\n",
-                               __func__, ret);
+                       dev_err(&tp->pdev->dev, "%s: Buffer read failed. "
+                               "err = %d\n", __func__, ret);
                        break;
                }
 
@@ -14733,11 +14781,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) {
                struct phy_device *phydev;
                phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR];
-               netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s)\n",
+               netdev_info(dev,
+                           "attached PHY driver [%s] (mii_bus:phy_addr=%s)\n",
                            phydev->drv->name, dev_name(&phydev->dev));
        } else
-               netdev_info(dev, "attached PHY is %s (%s Ethernet) (WireSpeed[%d])\n",
-                           tg3_phy_string(tp),
+               netdev_info(dev, "attached PHY is %s (%s Ethernet) "
+                           "(WireSpeed[%d])\n", tg3_phy_string(tp),
                            ((tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100Base-TX" :
                             ((tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) ? "1000Base-SX" :
                              "10/100/1000Base-T")),