aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/tg3.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r--drivers/net/tg3.c40
1 files changed, 36 insertions, 4 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 59d6e74a4a5..e5e901ecd80 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -64,8 +64,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.75"
-#define DRV_MODULE_RELDATE "March 23, 2007"
+#define DRV_MODULE_VERSION "3.76"
+#define DRV_MODULE_RELDATE "May 5, 2007"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -3019,6 +3019,16 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
}
}
+ if (tp->tg3_flags & TG3_FLAG_ASPM_WORKAROUND) {
+ u32 val = tr32(PCIE_PWR_MGMT_THRESH);
+ if (!netif_carrier_ok(tp->dev))
+ val = (val & ~PCIE_PWR_MGMT_L1_THRESH_MSK) |
+ tp->pwrmgmt_thresh;
+ else
+ val |= PCIE_PWR_MGMT_L1_THRESH_MSK;
+ tw32(PCIE_PWR_MGMT_THRESH, val);
+ }
+
return err;
}
@@ -3580,8 +3590,12 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id)
* Writing non-zero to intr-mbox-0 additional tells the
* NIC to stop sending us irqs, engaging "in-intr-handler"
* event coalescing.
+ *
+ * Flush the mailbox to de-assert the IRQ immediately to prevent
+ * spurious interrupts. The flush impacts performance but
+ * excessive spurious interrupts can be worse in some cases.
*/
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
+ tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
if (tg3_irq_sync(tp))
goto out;
sblk->status &= ~SD_STATUS_UPDATED;
@@ -3625,8 +3639,12 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id)
* writing non-zero to intr-mbox-0 additional tells the
* NIC to stop sending us irqs, engaging "in-intr-handler"
* event coalescing.
+ *
+ * Flush the mailbox to de-assert the IRQ immediately to prevent
+ * spurious interrupts. The flush impacts performance but
+ * excessive spurious interrupts can be worse in some cases.
*/
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
+ tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
if (tg3_irq_sync(tp))
goto out;
if (netif_rx_schedule_prep(dev)) {
@@ -10004,6 +10022,8 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT;
tp->tg3_flags2 |= TG3_FLG2_IS_NIC;
}
+ if (tr32(VCPU_CFGSHDW) & VCPU_CFGSHDW_ASPM_DBNC)
+ tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND;
return;
}
@@ -10131,6 +10151,14 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
/* bootcode if bit 18 is set */
if (cfg2 & (1 << 18))
tp->tg3_flags2 |= TG3_FLG2_SERDES_PREEMPHASIS;
+
+ if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
+ u32 cfg3;
+
+ tg3_read_mem(tp, NIC_SRAM_DATA_CFG_3, &cfg3);
+ if (cfg3 & NIC_SRAM_ASPM_DEBOUNCE)
+ tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND;
+ }
}
}
@@ -10998,6 +11026,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
*/
tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE;
+ if (tp->tg3_flags & TG3_FLAG_ASPM_WORKAROUND)
+ tp->pwrmgmt_thresh = tr32(PCIE_PWR_MGMT_THRESH) &
+ PCIE_PWR_MGMT_L1_THRESH_MSK;
+
return err;
}