Skip to content

Commit 1eae4eb

Browse files
ahkokdavem330
authored andcommitted
e1000e: Disable L1 ASPM power savings for 82573 mobile variants
L1 ASPM link (pci-e link power savings) has significant benefits (~1W savings when link is active) but unfortunately does not work correctly on any of the chipsets that have 82573 on mobile platforms which causes various nuisances: - eeprom reads return garbage information leading to bad eeprom checksums - long ping times (up to 2 seconds) - complete system hangs (freeze/lockup) A lot of T60 owners have been plagued by this, but other mobile solutions also suffer from these symptoms. Disabling L1 ASPM before we activate the PCI-E link fixes all of these issues at the cost of some power consumption. Remove a workaround RDTR adjustment that is no longer needed with this new one. Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
1 parent 93ca161 commit 1eae4eb

File tree

4 files changed

+30
-9
lines changed

4 files changed

+30
-9
lines changed

drivers/net/e1000e/82571.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1343,7 +1343,6 @@ struct e1000_info e1000_82573_info = {
13431343
| FLAG_HAS_STATS_ICR_ICT
13441344
| FLAG_HAS_SMART_POWER_DOWN
13451345
| FLAG_HAS_AMT
1346-
| FLAG_HAS_ASPM
13471346
| FLAG_HAS_ERT
13481347
| FLAG_HAS_SWSM_ON_LOAD,
13491348
.pba = 20,

drivers/net/e1000e/e1000.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,6 @@ struct e1000_info {
288288
#define FLAG_HAS_CTRLEXT_ON_LOAD (1 << 5)
289289
#define FLAG_HAS_SWSM_ON_LOAD (1 << 6)
290290
#define FLAG_HAS_JUMBO_FRAMES (1 << 7)
291-
#define FLAG_HAS_ASPM (1 << 8)
292291
#define FLAG_HAS_STATS_ICR_ICT (1 << 9)
293292
#define FLAG_HAS_STATS_PTC_PRC (1 << 10)
294293
#define FLAG_HAS_SMART_POWER_DOWN (1 << 11)

drivers/net/e1000e/netdev.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3509,6 +3509,33 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
35093509
return 0;
35103510
}
35113511

3512+
static void e1000e_disable_l1aspm(struct pci_dev *pdev)
3513+
{
3514+
int pos;
3515+
u32 cap;
3516+
u16 val;
3517+
3518+
/*
3519+
* 82573 workaround - disable L1 ASPM on mobile chipsets
3520+
*
3521+
* L1 ASPM on various mobile (ich7) chipsets do not behave properly
3522+
* resulting in lost data or garbage information on the pci-e link
3523+
* level. This could result in (false) bad EEPROM checksum errors,
3524+
* long ping times (up to 2s) or even a system freeze/hang.
3525+
*
3526+
* Unfortunately this feature saves about 1W power consumption when
3527+
* active.
3528+
*/
3529+
pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
3530+
pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, &cap);
3531+
pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &val);
3532+
if (val & 0x2) {
3533+
dev_warn(&pdev->dev, "Disabling L1 ASPM\n");
3534+
val &= ~0x2;
3535+
pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, val);
3536+
}
3537+
}
3538+
35123539
#ifdef CONFIG_PM
35133540
static int e1000_resume(struct pci_dev *pdev)
35143541
{
@@ -3519,6 +3546,7 @@ static int e1000_resume(struct pci_dev *pdev)
35193546

35203547
pci_set_power_state(pdev, PCI_D0);
35213548
pci_restore_state(pdev);
3549+
e1000e_disable_l1aspm(pdev);
35223550
err = pci_enable_device(pdev);
35233551
if (err) {
35243552
dev_err(&pdev->dev,
@@ -3619,6 +3647,7 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
36193647
struct e1000_adapter *adapter = netdev_priv(netdev);
36203648
struct e1000_hw *hw = &adapter->hw;
36213649

3650+
e1000e_disable_l1aspm(pdev);
36223651
if (pci_enable_device(pdev)) {
36233652
dev_err(&pdev->dev,
36243653
"Cannot re-enable PCI device after reset.\n");
@@ -3720,6 +3749,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
37203749
u16 eeprom_data = 0;
37213750
u16 eeprom_apme_mask = E1000_EEPROM_APME;
37223751

3752+
e1000e_disable_l1aspm(pdev);
37233753
err = pci_enable_device(pdev);
37243754
if (err)
37253755
return err;

drivers/net/e1000e/param.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -262,13 +262,6 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
262262
.max = MAX_RXDELAY } }
263263
};
264264

265-
/* modify min and default if 82573 for slow ping w/a,
266-
* a value greater than 8 needs to be set for RDTR */
267-
if (adapter->flags & FLAG_HAS_ASPM) {
268-
opt.def = 32;
269-
opt.arg.r.min = 8;
270-
}
271-
272265
if (num_RxIntDelay > bd) {
273266
adapter->rx_int_delay = RxIntDelay[bd];
274267
e1000_validate_option(&adapter->rx_int_delay, &opt,

0 commit comments

Comments
 (0)