@@ -34,6 +34,8 @@ static bool force_enable_dimms;
34
34
module_param (force_enable_dimms , bool , S_IRUGO |S_IWUSR );
35
35
MODULE_PARM_DESC (force_enable_dimms , "Ignore _STA (ACPI DIMM device) status" );
36
36
37
+ static struct workqueue_struct * nfit_wq ;
38
+
37
39
struct nfit_table_prev {
38
40
struct list_head spas ;
39
41
struct list_head memdevs ;
@@ -1961,6 +1963,39 @@ int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, acpi_size sz)
1961
1963
}
1962
1964
EXPORT_SYMBOL_GPL (acpi_nfit_init );
1963
1965
1966
+ struct acpi_nfit_flush_work {
1967
+ struct work_struct work ;
1968
+ struct completion cmp ;
1969
+ };
1970
+
1971
+ static void flush_probe (struct work_struct * work )
1972
+ {
1973
+ struct acpi_nfit_flush_work * flush ;
1974
+
1975
+ flush = container_of (work , typeof (* flush ), work );
1976
+ complete (& flush -> cmp );
1977
+ }
1978
+
1979
+ static int acpi_nfit_flush_probe (struct nvdimm_bus_descriptor * nd_desc )
1980
+ {
1981
+ struct acpi_nfit_desc * acpi_desc = to_acpi_nfit_desc (nd_desc );
1982
+ struct device * dev = acpi_desc -> dev ;
1983
+ struct acpi_nfit_flush_work flush ;
1984
+
1985
+ /* bounce the device lock to flush acpi_nfit_add / acpi_nfit_notify */
1986
+ device_lock (dev );
1987
+ device_unlock (dev );
1988
+
1989
+ /*
1990
+ * Scrub work could take 10s of seconds, userspace may give up so we
1991
+ * need to be interruptible while waiting.
1992
+ */
1993
+ INIT_WORK_ONSTACK (& flush .work , flush_probe );
1994
+ COMPLETION_INITIALIZER_ONSTACK (flush .cmp );
1995
+ queue_work (nfit_wq , & flush .work );
1996
+ return wait_for_completion_interruptible (& flush .cmp );
1997
+ }
1998
+
1964
1999
void acpi_nfit_desc_init (struct acpi_nfit_desc * acpi_desc , struct device * dev )
1965
2000
{
1966
2001
struct nvdimm_bus_descriptor * nd_desc ;
@@ -1971,6 +2006,7 @@ void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev)
1971
2006
nd_desc = & acpi_desc -> nd_desc ;
1972
2007
nd_desc -> provider_name = "ACPI.NFIT" ;
1973
2008
nd_desc -> ndctl = acpi_nfit_ctl ;
2009
+ nd_desc -> flush_probe = acpi_nfit_flush_probe ;
1974
2010
nd_desc -> attr_groups = acpi_nfit_attribute_groups ;
1975
2011
1976
2012
INIT_LIST_HEAD (& acpi_desc -> spa_maps );
@@ -2048,6 +2084,8 @@ static int acpi_nfit_remove(struct acpi_device *adev)
2048
2084
{
2049
2085
struct acpi_nfit_desc * acpi_desc = dev_get_drvdata (& adev -> dev );
2050
2086
2087
+ acpi_desc -> cancel = 1 ;
2088
+ flush_workqueue (nfit_wq );
2051
2089
nvdimm_bus_unregister (acpi_desc -> nvdimm_bus );
2052
2090
return 0 ;
2053
2091
}
@@ -2079,6 +2117,12 @@ static void acpi_nfit_notify(struct acpi_device *adev, u32 event)
2079
2117
acpi_desc -> nvdimm_bus = nvdimm_bus_register (dev , & acpi_desc -> nd_desc );
2080
2118
if (!acpi_desc -> nvdimm_bus )
2081
2119
goto out_unlock ;
2120
+ } else {
2121
+ /*
2122
+ * Finish previous registration before considering new
2123
+ * regions.
2124
+ */
2125
+ flush_workqueue (nfit_wq );
2082
2126
}
2083
2127
2084
2128
/* Evaluate _FIT */
@@ -2146,12 +2190,17 @@ static __init int nfit_init(void)
2146
2190
acpi_str_to_uuid (UUID_NFIT_BUS , nfit_uuid [NFIT_DEV_BUS ]);
2147
2191
acpi_str_to_uuid (UUID_NFIT_DIMM , nfit_uuid [NFIT_DEV_DIMM ]);
2148
2192
2193
+ nfit_wq = create_singlethread_workqueue ("nfit" );
2194
+ if (!nfit_wq )
2195
+ return - ENOMEM ;
2196
+
2149
2197
return acpi_bus_register_driver (& acpi_nfit_driver );
2150
2198
}
2151
2199
2152
2200
static __exit void nfit_exit (void )
2153
2201
{
2154
2202
acpi_bus_unregister_driver (& acpi_nfit_driver );
2203
+ destroy_workqueue (nfit_wq );
2155
2204
}
2156
2205
2157
2206
module_init (nfit_init );
0 commit comments