]> err.no Git - linux-2.6/blobdiff - drivers/net/tg3.c
Fix a potential NULL pointer dereference in write_bulk_callback() in drivers/net...
[linux-2.6] / drivers / net / tg3.c
index 1df129aa32991b9e6bd6cf4e7329b01de0030a88..887b9a5cfe48bed9bbd6978c4bcdca8e367dfbfd 100644 (file)
@@ -64,8 +64,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.77"
-#define DRV_MODULE_RELDATE     "May 31, 2007"
+#define DRV_MODULE_VERSION     "3.79"
+#define DRV_MODULE_RELDATE     "July 18, 2007"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -721,6 +721,44 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val)
        return ret;
 }
 
+static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable)
+{
+       u32 phy;
+
+       if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
+           (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES))
+               return;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               u32 ephy;
+
+               if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &ephy)) {
+                       tg3_writephy(tp, MII_TG3_EPHY_TEST,
+                                    ephy | MII_TG3_EPHY_SHADOW_EN);
+                       if (!tg3_readphy(tp, MII_TG3_EPHYTST_MISCCTRL, &phy)) {
+                               if (enable)
+                                       phy |= MII_TG3_EPHYTST_MISCCTRL_MDIX;
+                               else
+                                       phy &= ~MII_TG3_EPHYTST_MISCCTRL_MDIX;
+                               tg3_writephy(tp, MII_TG3_EPHYTST_MISCCTRL, phy);
+                       }
+                       tg3_writephy(tp, MII_TG3_EPHY_TEST, ephy);
+               }
+       } else {
+               phy = MII_TG3_AUXCTL_MISC_RDSEL_MISC |
+                     MII_TG3_AUXCTL_SHDWSEL_MISC;
+               if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, phy) &&
+                   !tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy)) {
+                       if (enable)
+                               phy |= MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
+                       else
+                               phy &= ~MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
+                       phy |= MII_TG3_AUXCTL_MISC_WREN;
+                       tg3_writephy(tp, MII_TG3_AUX_CTRL, phy);
+               }
+       }
+}
+
 static void tg3_phy_set_wirespeed(struct tg3 *tp)
 {
        u32 val;
@@ -1045,23 +1083,11 @@ out:
        }
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
-               u32 phy_reg;
-
                /* adjust output voltage */
                tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x12);
-
-               if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &phy_reg)) {
-                       u32 phy_reg2;
-
-                       tg3_writephy(tp, MII_TG3_EPHY_TEST,
-                                    phy_reg | MII_TG3_EPHY_SHADOW_EN);
-                       /* Enable auto-MDIX */
-                       if (!tg3_readphy(tp, 0x10, &phy_reg2))
-                               tg3_writephy(tp, 0x10, phy_reg2 | 0x4000);
-                       tg3_writephy(tp, MII_TG3_EPHY_TEST, phy_reg);
-               }
        }
 
+       tg3_phy_toggle_automdix(tp, 1);
        tg3_phy_set_wirespeed(tp);
        return 0;
 }
@@ -4821,6 +4847,59 @@ static int tg3_poll_fw(struct tg3 *tp)
        return 0;
 }
 
+/* Save PCI command register before chip reset */
+static void tg3_save_pci_state(struct tg3 *tp)
+{
+       u32 val;
+
+       pci_read_config_dword(tp->pdev, TG3PCI_COMMAND, &val);
+       tp->pci_cmd = val;
+}
+
+/* Restore PCI state after chip reset */
+static void tg3_restore_pci_state(struct tg3 *tp)
+{
+       u32 val;
+
+       /* Re-enable indirect register accesses. */
+       pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+                              tp->misc_host_ctrl);
+
+       /* Set MAX PCI retry to zero. */
+       val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE);
+       if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
+           (tp->tg3_flags & TG3_FLAG_PCIX_MODE))
+               val |= PCISTATE_RETRY_SAME_DMA;
+       pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
+
+       pci_write_config_dword(tp->pdev, TG3PCI_COMMAND, tp->pci_cmd);
+
+       /* Make sure PCI-X relaxed ordering bit is clear. */
+       pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val);
+       val &= ~PCIX_CAPS_RELAXED_ORDERING;
+       pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val);
+
+       if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
+               u32 val;
+
+               /* Chip reset on 5780 will reset MSI enable bit,
+                * so need to restore it.
+                */
+               if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
+                       u16 ctrl;
+
+                       pci_read_config_word(tp->pdev,
+                                            tp->msi_cap + PCI_MSI_FLAGS,
+                                            &ctrl);
+                       pci_write_config_word(tp->pdev,
+                                             tp->msi_cap + PCI_MSI_FLAGS,
+                                             ctrl | PCI_MSI_FLAGS_ENABLE);
+                       val = tr32(MSGINT_MODE);
+                       tw32(MSGINT_MODE, val | MSGINT_MODE_ENABLE);
+               }
+       }
+}
+
 static void tg3_stop_fw(struct tg3 *);
 
 /* tp->lock is held. */
@@ -4837,6 +4916,12 @@ static int tg3_chip_reset(struct tg3 *tp)
         */
        tp->nvram_lock_cnt = 0;
 
+       /* GRC_MISC_CFG core clock reset will clear the memory
+        * enable bit in PCI register 4 and the MSI enable bit
+        * on some chips, so we save relevant registers here.
+        */
+       tg3_save_pci_state(tp);
+
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
@@ -4935,50 +5020,14 @@ static int tg3_chip_reset(struct tg3 *tp)
                pci_write_config_dword(tp->pdev, 0xd8, 0xf5000);
        }
 
-       /* Re-enable indirect register accesses. */
-       pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
-                              tp->misc_host_ctrl);
-
-       /* Set MAX PCI retry to zero. */
-       val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE);
-       if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
-           (tp->tg3_flags & TG3_FLAG_PCIX_MODE))
-               val |= PCISTATE_RETRY_SAME_DMA;
-       pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
-
-       pci_restore_state(tp->pdev);
+       tg3_restore_pci_state(tp);
 
        tp->tg3_flags &= ~TG3_FLAG_CHIP_RESETTING;
 
-       /* Make sure PCI-X relaxed ordering bit is clear. */
-       pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val);
-       val &= ~PCIX_CAPS_RELAXED_ORDERING;
-       pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val);
-
-       if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
-               u32 val;
-
-               /* Chip reset on 5780 will reset MSI enable bit,
-                * so need to restore it.
-                */
-               if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
-                       u16 ctrl;
-
-                       pci_read_config_word(tp->pdev,
-                                            tp->msi_cap + PCI_MSI_FLAGS,
-                                            &ctrl);
-                       pci_write_config_word(tp->pdev,
-                                             tp->msi_cap + PCI_MSI_FLAGS,
-                                             ctrl | PCI_MSI_FLAGS_ENABLE);
-                       val = tr32(MSGINT_MODE);
-                       tw32(MSGINT_MODE, val | MSGINT_MODE_ENABLE);
-               }
-
+       val = 0;
+       if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
                val = tr32(MEMARB_MODE);
-               tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
-
-       } else
-               tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
+       tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
 
        if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) {
                tg3_stop_fw(tp);
@@ -8292,7 +8341,7 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data)
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
-               ethtool_op_set_tx_hw_csum(dev, data);
+               ethtool_op_set_tx_ipv6_csum(dev, data);
        else
                ethtool_op_set_tx_csum(dev, data);
 
@@ -8847,14 +8896,14 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
                                             phytest | MII_TG3_EPHY_SHADOW_EN);
                                if (!tg3_readphy(tp, 0x1b, &phy))
                                        tg3_writephy(tp, 0x1b, phy & ~0x20);
-                               if (!tg3_readphy(tp, 0x10, &phy))
-                                       tg3_writephy(tp, 0x10, phy & ~0x4000);
                                tg3_writephy(tp, MII_TG3_EPHY_TEST, phytest);
                        }
                        val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED100;
                } else
                        val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED1000;
 
+               tg3_phy_toggle_automdix(tp, 0);
+
                tg3_writephy(tp, MII_BMCR, val);
                udelay(40);
 
@@ -9435,11 +9484,13 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
                case FLASH_5755VENDOR_ATMEL_FLASH_1:
                case FLASH_5755VENDOR_ATMEL_FLASH_2:
                case FLASH_5755VENDOR_ATMEL_FLASH_3:
+               case FLASH_5755VENDOR_ATMEL_FLASH_5:
                        tp->nvram_jedecnum = JEDEC_ATMEL;
                        tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
                        tp->tg3_flags2 |= TG3_FLG2_FLASH;
                        tp->nvram_pagesize = 264;
-                       if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1)
+                       if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1 ||
+                           nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_5)
                                tp->nvram_size = (protect ? 0x3e200 : 0x80000);
                        else if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_2)
                                tp->nvram_size = (protect ? 0x1f200 : 0x40000);
@@ -10523,11 +10574,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                                continue;
                        }
                        if (pci_id->rev != PCI_ANY_ID) {
-                               u8 rev;
-
-                               pci_read_config_byte(bridge, PCI_REVISION_ID,
-                                                    &rev);
-                               if (rev > pci_id->rev)
+                               if (bridge->revision > pci_id->rev)
                                        continue;
                        }
                        if (bridge->subordinate &&
@@ -11954,7 +12001,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
         */
        if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) ||
            (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
-               pci_save_state(tp->pdev);
                tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
                tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
        }
@@ -11983,12 +12029,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
        tg3_init_coal(tp);
 
-       /* Now that we have fully setup the chip, save away a snapshot
-        * of the PCI config space.  We need to restore this after
-        * GRC_MISC_CFG core clock resets and some resume events.
-        */
-       pci_save_state(tp->pdev);
-
        pci_set_drvdata(pdev, dev);
 
        err = register_netdev(dev);