SUNHME: Fix missing NETIF_F_VLAN_CHALLENGED on PCI happy meals
[deliverable/linux.git] / drivers / net / tg3.c
index a402b5c018964ad3faab7d1ffb7214edc98c131c..09440d783e65542912bac932fa727a288df1891c 100644 (file)
@@ -64,8 +64,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.83"
-#define DRV_MODULE_RELDATE     "October 10, 2007"
+#define DRV_MODULE_VERSION     "3.85"
+#define DRV_MODULE_RELDATE     "October 18, 2007"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -200,6 +200,7 @@ static struct pci_device_id tg3_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906M)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5784)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5764)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5723)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761E)},
        {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
@@ -3576,7 +3577,7 @@ static int tg3_poll_work(struct tg3 *tp, int work_done, int budget)
        if (sblk->idx[0].tx_consumer != tp->tx_cons) {
                tg3_tx(tp);
                if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING))
-                       return 0;
+                       return work_done;
        }
 
        /* run RX thread, within the bounds set by NAPI.
@@ -3593,6 +3594,7 @@ static int tg3_poll(struct napi_struct *napi, int budget)
 {
        struct tg3 *tp = container_of(napi, struct tg3, napi);
        int work_done = 0;
+       struct tg3_hw_status *sblk = tp->hw_status;
 
        while (1) {
                work_done = tg3_poll_work(tp, work_done, budget);
@@ -3603,15 +3605,17 @@ static int tg3_poll(struct napi_struct *napi, int budget)
                if (unlikely(work_done >= budget))
                        break;
 
-               if (likely(!tg3_has_work(tp))) {
-                       struct tg3_hw_status *sblk = tp->hw_status;
-
-                       if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
-                               tp->last_tag = sblk->status_tag;
-                               rmb();
-                       } else
-                               sblk->status &= ~SD_STATUS_UPDATED;
+               if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
+                       /* tp->last_tag is used in tg3_restart_ints() below
+                        * to tell the hw how much work has been processed,
+                        * so we must read it before checking for more work.
+                        */
+                       tp->last_tag = sblk->status_tag;
+                       rmb();
+               } else
+                       sblk->status &= ~SD_STATUS_UPDATED;
 
+               if (likely(!tg3_has_work(tp))) {
                        netif_rx_complete(tp->dev, napi);
                        tg3_restart_ints(tp);
                        break;
@@ -3621,9 +3625,10 @@ static int tg3_poll(struct napi_struct *napi, int budget)
        return work_done;
 
 tx_recovery:
+       /* work_done is guaranteed to be less than budget. */
        netif_rx_complete(tp->dev, napi);
        schedule_work(&tp->reset_task);
-       return 0;
+       return work_done;
 }
 
 static void tg3_irq_quiesce(struct tg3 *tp)
@@ -5024,10 +5029,7 @@ static int tg3_poll_fw(struct tg3 *tp)
 /* 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;
+       pci_read_config_word(tp->pdev, PCI_COMMAND, &tp->pci_cmd);
 }
 
 /* Restore PCI state after chip reset */
@@ -5050,8 +5052,14 @@ static void tg3_restore_pci_state(struct tg3 *tp)
                       PCISTATE_ALLOW_APE_SHMEM_WR;
        pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
 
-       pci_write_config_dword(tp->pdev, TG3PCI_COMMAND, tp->pci_cmd);
+       pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd);
 
+       if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
+               pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
+                                     tp->pci_cacheline_sz);
+               pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
+                                     tp->pci_lat_timer);
+       }
        /* Make sure PCI-X relaxed ordering bit is clear. */
        if (tp->pcix_cap) {
                u16 pcix_cmd;
@@ -6985,9 +6993,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                break;
        };
 
-       /* Write our heartbeat update interval to APE. */
-       tg3_ape_write32(tp, TG3_APE_HOST_HEARTBEAT_INT_MS,
-                       APE_HOST_HEARTBEAT_INT_DISABLE);
+       if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
+               /* Write our heartbeat update interval to APE. */
+               tg3_ape_write32(tp, TG3_APE_HOST_HEARTBEAT_INT_MS,
+                               APE_HOST_HEARTBEAT_INT_DISABLE);
 
        tg3_write_sig_post_reset(tp, RESET_KIND_INIT);
 
@@ -9029,7 +9038,7 @@ static int tg3_do_mem_test(struct tg3 *tp, u32 offset, u32 len)
        int i;
        u32 j;
 
-       for (i = 0; i < sizeof(test_pattern)/sizeof(u32); i++) {
+       for (i = 0; i < ARRAY_SIZE(test_pattern); i++) {
                for (j = 0; j < len; j += 4) {
                        u32 val;
 
@@ -10809,9 +10818,24 @@ out_not_found:
                strcpy(tp->board_part_number, "none");
 }
 
+static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
+{
+       u32 val;
+
+       if (tg3_nvram_read_swab(tp, offset, &val) ||
+           (val & 0xfc000000) != 0x0c000000 ||
+           tg3_nvram_read_swab(tp, offset + 4, &val) ||
+           val != 0)
+               return 0;
+
+       return 1;
+}
+
 static void __devinit tg3_read_fw_ver(struct tg3 *tp)
 {
        u32 val, offset, start;
+       u32 ver_offset;
+       int i, bcnt;
 
        if (tg3_nvram_read_swab(tp, 0, &val))
                return;
@@ -10824,29 +10848,71 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp)
                return;
 
        offset = tg3_nvram_logical_addr(tp, offset);
-       if (tg3_nvram_read_swab(tp, offset, &val))
+
+       if (!tg3_fw_img_is_valid(tp, offset) ||
+           tg3_nvram_read_swab(tp, offset + 8, &ver_offset))
                return;
 
-       if ((val & 0xfc000000) == 0x0c000000) {
-               u32 ver_offset, addr;
-               int i;
+       offset = offset + ver_offset - start;
+       for (i = 0; i < 16; i += 4) {
+               if (tg3_nvram_read(tp, offset + i, &val))
+                       return;
+
+               val = le32_to_cpu(val);
+               memcpy(tp->fw_ver + i, &val, 4);
+       }
 
-               if (tg3_nvram_read_swab(tp, offset + 4, &val) ||
-                   tg3_nvram_read_swab(tp, offset + 8, &ver_offset))
+       if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
+            (tp->tg3_flags & TG3_FLG3_ENABLE_APE))
+               return;
+
+       for (offset = TG3_NVM_DIR_START;
+            offset < TG3_NVM_DIR_END;
+            offset += TG3_NVM_DIRENT_SIZE) {
+               if (tg3_nvram_read_swab(tp, offset, &val))
                        return;
 
-               if (val != 0)
+               if ((val >> TG3_NVM_DIRTYPE_SHIFT) == TG3_NVM_DIRTYPE_ASFINI)
+                       break;
+       }
+
+       if (offset == TG3_NVM_DIR_END)
+               return;
+
+       if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
+               start = 0x08000000;
+       else if (tg3_nvram_read_swab(tp, offset - 4, &start))
+               return;
+
+       if (tg3_nvram_read_swab(tp, offset + 4, &offset) ||
+           !tg3_fw_img_is_valid(tp, offset) ||
+           tg3_nvram_read_swab(tp, offset + 8, &val))
+               return;
+
+       offset += val - start;
+
+       bcnt = strlen(tp->fw_ver);
+
+       tp->fw_ver[bcnt++] = ',';
+       tp->fw_ver[bcnt++] = ' ';
+
+       for (i = 0; i < 4; i++) {
+               if (tg3_nvram_read(tp, offset, &val))
                        return;
 
-               addr = offset + ver_offset - start;
-               for (i = 0; i < 16; i += 4) {
-                       if (tg3_nvram_read(tp, addr + i, &val))
-                               return;
+               val = le32_to_cpu(val);
+               offset += sizeof(val);
 
-                       val = cpu_to_le32(val);
-                       memcpy(tp->fw_ver + i, &val, 4);
+               if (bcnt > TG3_VER_SIZE - sizeof(val)) {
+                       memcpy(&tp->fw_ver[bcnt], &val, TG3_VER_SIZE - bcnt);
+                       break;
                }
+
+               memcpy(&tp->fw_ver[bcnt], &val, sizeof(val));
+               bcnt += sizeof(val);
        }
+
+       tp->fw_ver[TG3_VER_SIZE - 1] = 0;
 }
 
 static struct pci_dev * __devinit tg3_find_peer(struct tg3 *);
This page took 0.030064 seconds and 5 git commands to generate.