diff options
author | Dan Williams <dan.j.williams@intel.com> | 2016-02-23 00:50:31 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2016-03-05 15:24:06 -0500 |
commit | 87bf572e19a092cc9cc77d5a00d543a2b628c142 (patch) | |
tree | ae275e80641400bccfbf39c168dbfc5178b44159 /drivers/acpi | |
parent | 1cf03c00e7c17d3cf13a267dac83b3162a16ba8c (diff) |
nfit: disable userspace initiated ars during scrub
While the nfit driver is issuing address range scrub commands and
reaping the results do not permit an ars_start command issued from
userspace. The scrub thread assumes that all ars completions are for
scrubs initiated by platform firmware at boot, or by the nfit driver.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/nfit.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c index 3646501b01d7..0def4ebf5d43 100644 --- a/drivers/acpi/nfit.c +++ b/drivers/acpi/nfit.c | |||
@@ -2186,6 +2186,28 @@ static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc) | |||
2186 | return wait_for_completion_interruptible(&flush.cmp); | 2186 | return wait_for_completion_interruptible(&flush.cmp); |
2187 | } | 2187 | } |
2188 | 2188 | ||
2189 | static int acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc, | ||
2190 | struct nvdimm *nvdimm, unsigned int cmd) | ||
2191 | { | ||
2192 | struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc); | ||
2193 | |||
2194 | if (nvdimm) | ||
2195 | return 0; | ||
2196 | if (cmd != ND_CMD_ARS_START) | ||
2197 | return 0; | ||
2198 | |||
2199 | /* | ||
2200 | * The kernel and userspace may race to initiate a scrub, but | ||
2201 | * the scrub thread is prepared to lose that initial race. It | ||
2202 | * just needs guarantees that any ars it initiates are not | ||
2203 | * interrupted by any intervening start reqeusts from userspace. | ||
2204 | */ | ||
2205 | if (work_busy(&acpi_desc->work)) | ||
2206 | return -EBUSY; | ||
2207 | |||
2208 | return 0; | ||
2209 | } | ||
2210 | |||
2189 | void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev) | 2211 | void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev) |
2190 | { | 2212 | { |
2191 | struct nvdimm_bus_descriptor *nd_desc; | 2213 | struct nvdimm_bus_descriptor *nd_desc; |
@@ -2197,6 +2219,7 @@ void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev) | |||
2197 | nd_desc->provider_name = "ACPI.NFIT"; | 2219 | nd_desc->provider_name = "ACPI.NFIT"; |
2198 | nd_desc->ndctl = acpi_nfit_ctl; | 2220 | nd_desc->ndctl = acpi_nfit_ctl; |
2199 | nd_desc->flush_probe = acpi_nfit_flush_probe; | 2221 | nd_desc->flush_probe = acpi_nfit_flush_probe; |
2222 | nd_desc->clear_to_send = acpi_nfit_clear_to_send; | ||
2200 | nd_desc->attr_groups = acpi_nfit_attribute_groups; | 2223 | nd_desc->attr_groups = acpi_nfit_attribute_groups; |
2201 | 2224 | ||
2202 | INIT_LIST_HEAD(&acpi_desc->spa_maps); | 2225 | INIT_LIST_HEAD(&acpi_desc->spa_maps); |