|
@@ -1280,6 +1280,59 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
|
|
|
return strcmp(buf, dmi->driver_data) < 0;
|
|
|
}
|
|
|
|
|
|
+static bool ahci_broken_lpm(struct pci_dev *pdev)
|
|
|
+{
|
|
|
+ static const struct dmi_system_id sysids[] = {
|
|
|
+ /* Various Lenovo 50 series have LPM issues with older BIOSen */
|
|
|
+ {
|
|
|
+ .matches = {
|
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
|
|
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X250"),
|
|
|
+ },
|
|
|
+ .driver_data = "20180406", /* 1.31 */
|
|
|
+ },
|
|
|
+ {
|
|
|
+ .matches = {
|
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
|
|
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L450"),
|
|
|
+ },
|
|
|
+ .driver_data = "20180420", /* 1.28 */
|
|
|
+ },
|
|
|
+ {
|
|
|
+ .matches = {
|
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
|
|
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T450s"),
|
|
|
+ },
|
|
|
+ .driver_data = "20180315", /* 1.33 */
|
|
|
+ },
|
|
|
+ {
|
|
|
+ .matches = {
|
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
|
|
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W541"),
|
|
|
+ },
|
|
|
+ /*
|
|
|
+ * Note date based on release notes, 2.35 has been
|
|
|
+ * reported to be good, but I've been unable to get
|
|
|
+ * a hold of the reporter to get the DMI BIOS date.
|
|
|
+ * TODO: fix this.
|
|
|
+ */
|
|
|
+ .driver_data = "20180310", /* 2.35 */
|
|
|
+ },
|
|
|
+ { } /* terminate list */
|
|
|
+ };
|
|
|
+ const struct dmi_system_id *dmi = dmi_first_match(sysids);
|
|
|
+ int year, month, date;
|
|
|
+ char buf[9];
|
|
|
+
|
|
|
+ if (!dmi)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
|
|
|
+ snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
|
|
|
+
|
|
|
+ return strcmp(buf, dmi->driver_data) < 0;
|
|
|
+}
|
|
|
+
|
|
|
static bool ahci_broken_online(struct pci_dev *pdev)
|
|
|
{
|
|
|
#define ENCODE_BUSDEVFN(bus, slot, func) \
|
|
@@ -1694,6 +1747,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
"quirky BIOS, skipping spindown on poweroff\n");
|
|
|
}
|
|
|
|
|
|
+ if (ahci_broken_lpm(pdev)) {
|
|
|
+ pi.flags |= ATA_FLAG_NO_LPM;
|
|
|
+ dev_warn(&pdev->dev,
|
|
|
+ "BIOS update required for Link Power Management support\n");
|
|
|
+ }
|
|
|
+
|
|
|
if (ahci_broken_suspend(pdev)) {
|
|
|
hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
|
|
|
dev_warn(&pdev->dev,
|