/* Time after which the timer interrupt will re-enable ASPM */ #define ASPM_TIMER_MS 1000 /* Time for which interrupts are ignored after a timer has been scheduled */ #define ASPM_RESCHED_TIMER_MS (ASPM_TIMER_MS / 2) /* Two interrupts within this time trigger ASPM disable */ #define ASPM_TRIGGER_MS 1 #define ASPM_TRIGGER_NS (ASPM_TRIGGER_MS * 1000 * 1000ull) #define ASPM_L1_SUPPORTED(reg) \
((((reg) & PCI_EXP_LNKCAP_ASPMS) >> 10) & 0x2)
/* Disable ASPM L1 first in downstream component and then upstream */
pcie_capability_clear_and_set_word(dd->pcidev, PCI_EXP_LNKCTL,
PCI_EXP_LNKCTL_ASPMC, 0x0); if (parent)
pcie_capability_clear_and_set_word(parent, PCI_EXP_LNKCTL,
PCI_EXP_LNKCTL_ASPMC, 0x0);
}
spin_lock_irqsave(&rcd->aspm_lock, flags); /* PSM contexts are open */ if (!rcd->aspm_intr_enable) goto unlock;
prev = rcd->aspm_ts_last_intr;
now = ktime_get();
rcd->aspm_ts_last_intr = now;
/* An interrupt pair close together in time */
close_interrupts = ktime_to_ns(ktime_sub(now, prev)) < ASPM_TRIGGER_NS;
/* Don't push out our timer till this much time has elapsed */
restart_timer = ktime_to_ns(ktime_sub(now, rcd->aspm_ts_timer_sched)) >
ASPM_RESCHED_TIMER_MS * NSEC_PER_MSEC;
restart_timer = restart_timer && close_interrupts;
/* Disable ASPM and schedule timer */ if (rcd->aspm_enabled && close_interrupts) {
aspm_disable_inc(rcd->dd);
rcd->aspm_enabled = false;
restart_timer = true;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.