diff options
Diffstat (limited to 'drivers/acpi/nfit/core.c')
-rw-r--r-- | drivers/acpi/nfit/core.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index 7c479002e798..b072cfc5f20e 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -1699,7 +1699,7 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc, { struct acpi_device *adev, *adev_dimm; struct device *dev = acpi_desc->dev; - unsigned long dsm_mask; + unsigned long dsm_mask, label_mask; const guid_t *guid; int i; int family = -1; @@ -1771,6 +1771,16 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc, 1ULL << i)) set_bit(i, &nfit_mem->dsm_mask); + /* + * Prefer the NVDIMM_FAMILY_INTEL label read commands if present + * due to their better semantics handling locked capacity. + */ + label_mask = 1 << ND_CMD_GET_CONFIG_SIZE | 1 << ND_CMD_GET_CONFIG_DATA + | 1 << ND_CMD_SET_CONFIG_DATA; + if (family == NVDIMM_FAMILY_INTEL + && (dsm_mask & label_mask) == label_mask) + return 0; + if (acpi_nvdimm_has_method(adev_dimm, "_LSI") && acpi_nvdimm_has_method(adev_dimm, "_LSR")) { dev_dbg(dev, "%s: has _LSR\n", dev_name(&adev_dimm->dev)); @@ -2559,7 +2569,12 @@ static void ars_complete(struct acpi_nfit_desc *acpi_desc, test_bit(ARS_SHORT, &nfit_spa->ars_state) ? "short" : "long"); clear_bit(ARS_SHORT, &nfit_spa->ars_state); - set_bit(ARS_DONE, &nfit_spa->ars_state); + if (test_and_clear_bit(ARS_REQ_REDO, &nfit_spa->ars_state)) { + set_bit(ARS_SHORT, &nfit_spa->ars_state); + set_bit(ARS_REQ, &nfit_spa->ars_state); + dev_dbg(dev, "ARS: processing scrub request received while in progress\n"); + } else + set_bit(ARS_DONE, &nfit_spa->ars_state); } static int ars_status_process_records(struct acpi_nfit_desc *acpi_desc) @@ -3256,9 +3271,10 @@ int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc, unsigned long flags) if (test_bit(ARS_FAILED, &nfit_spa->ars_state)) continue; - if (test_and_set_bit(ARS_REQ, &nfit_spa->ars_state)) + if (test_and_set_bit(ARS_REQ, &nfit_spa->ars_state)) { busy++; - else { + set_bit(ARS_REQ_REDO, &nfit_spa->ars_state); + } else { if (test_bit(ARS_SHORT, &flags)) set_bit(ARS_SHORT, &nfit_spa->ars_state); scheduled++; |