aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/nfit/core.c76
-rw-r--r--drivers/acpi/nfit/nfit.h1
-rw-r--r--tools/testing/nvdimm/test/nfit.c4
3 files changed, 51 insertions, 30 deletions
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 69c6cc77130c..261eea1d2906 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -2604,7 +2604,8 @@ static int acpi_nfit_register_regions(struct acpi_nfit_desc *acpi_desc)
2604 return rc; 2604 return rc;
2605 } 2605 }
2606 2606
2607 queue_work(nfit_wq, &acpi_desc->work); 2607 if (!acpi_desc->cancel)
2608 queue_work(nfit_wq, &acpi_desc->work);
2608 return 0; 2609 return 0;
2609} 2610}
2610 2611
@@ -2650,32 +2651,11 @@ static int acpi_nfit_desc_init_scrub_attr(struct acpi_nfit_desc *acpi_desc)
2650 return 0; 2651 return 0;
2651} 2652}
2652 2653
2653static void acpi_nfit_destruct(void *data) 2654static void acpi_nfit_unregister(void *data)
2654{ 2655{
2655 struct acpi_nfit_desc *acpi_desc = data; 2656 struct acpi_nfit_desc *acpi_desc = data;
2656 struct device *bus_dev = to_nvdimm_bus_dev(acpi_desc->nvdimm_bus);
2657 2657
2658 /*
2659 * Destruct under acpi_desc_lock so that nfit_handle_mce does not
2660 * race teardown
2661 */
2662 mutex_lock(&acpi_desc_lock);
2663 acpi_desc->cancel = 1;
2664 /*
2665 * Bounce the nvdimm bus lock to make sure any in-flight
2666 * acpi_nfit_ars_rescan() submissions have had a chance to
2667 * either submit or see ->cancel set.
2668 */
2669 device_lock(bus_dev);
2670 device_unlock(bus_dev);
2671
2672 flush_workqueue(nfit_wq);
2673 if (acpi_desc->scrub_count_state)
2674 sysfs_put(acpi_desc->scrub_count_state);
2675 nvdimm_bus_unregister(acpi_desc->nvdimm_bus); 2658 nvdimm_bus_unregister(acpi_desc->nvdimm_bus);
2676 acpi_desc->nvdimm_bus = NULL;
2677 list_del(&acpi_desc->list);
2678 mutex_unlock(&acpi_desc_lock);
2679} 2659}
2680 2660
2681int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *data, acpi_size sz) 2661int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *data, acpi_size sz)
@@ -2693,7 +2673,7 @@ int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *data, acpi_size sz)
2693 if (!acpi_desc->nvdimm_bus) 2673 if (!acpi_desc->nvdimm_bus)
2694 return -ENOMEM; 2674 return -ENOMEM;
2695 2675
2696 rc = devm_add_action_or_reset(dev, acpi_nfit_destruct, 2676 rc = devm_add_action_or_reset(dev, acpi_nfit_unregister,
2697 acpi_desc); 2677 acpi_desc);
2698 if (rc) 2678 if (rc)
2699 return rc; 2679 return rc;
@@ -2787,9 +2767,10 @@ static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc)
2787 2767
2788 /* bounce the init_mutex to make init_complete valid */ 2768 /* bounce the init_mutex to make init_complete valid */
2789 mutex_lock(&acpi_desc->init_mutex); 2769 mutex_lock(&acpi_desc->init_mutex);
2790 mutex_unlock(&acpi_desc->init_mutex); 2770 if (acpi_desc->cancel || acpi_desc->init_complete) {
2791 if (acpi_desc->init_complete) 2771 mutex_unlock(&acpi_desc->init_mutex);
2792 return 0; 2772 return 0;
2773 }
2793 2774
2794 /* 2775 /*
2795 * Scrub work could take 10s of seconds, userspace may give up so we 2776 * Scrub work could take 10s of seconds, userspace may give up so we
@@ -2798,6 +2779,7 @@ static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc)
2798 INIT_WORK_ONSTACK(&flush.work, flush_probe); 2779 INIT_WORK_ONSTACK(&flush.work, flush_probe);
2799 COMPLETION_INITIALIZER_ONSTACK(flush.cmp); 2780 COMPLETION_INITIALIZER_ONSTACK(flush.cmp);
2800 queue_work(nfit_wq, &flush.work); 2781 queue_work(nfit_wq, &flush.work);
2782 mutex_unlock(&acpi_desc->init_mutex);
2801 2783
2802 rc = wait_for_completion_interruptible(&flush.cmp); 2784 rc = wait_for_completion_interruptible(&flush.cmp);
2803 cancel_work_sync(&flush.work); 2785 cancel_work_sync(&flush.work);
@@ -2834,10 +2816,12 @@ int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc)
2834 if (work_busy(&acpi_desc->work)) 2816 if (work_busy(&acpi_desc->work))
2835 return -EBUSY; 2817 return -EBUSY;
2836 2818
2837 if (acpi_desc->cancel) 2819 mutex_lock(&acpi_desc->init_mutex);
2820 if (acpi_desc->cancel) {
2821 mutex_unlock(&acpi_desc->init_mutex);
2838 return 0; 2822 return 0;
2823 }
2839 2824
2840 mutex_lock(&acpi_desc->init_mutex);
2841 list_for_each_entry(nfit_spa, &acpi_desc->spas, list) { 2825 list_for_each_entry(nfit_spa, &acpi_desc->spas, list) {
2842 struct acpi_nfit_system_address *spa = nfit_spa->spa; 2826 struct acpi_nfit_system_address *spa = nfit_spa->spa;
2843 2827
@@ -2886,6 +2870,35 @@ static void acpi_nfit_put_table(void *table)
2886 acpi_put_table(table); 2870 acpi_put_table(table);
2887} 2871}
2888 2872
2873void acpi_nfit_shutdown(void *data)
2874{
2875 struct acpi_nfit_desc *acpi_desc = data;
2876 struct device *bus_dev = to_nvdimm_bus_dev(acpi_desc->nvdimm_bus);
2877
2878 /*
2879 * Destruct under acpi_desc_lock so that nfit_handle_mce does not
2880 * race teardown
2881 */
2882 mutex_lock(&acpi_desc_lock);
2883 list_del(&acpi_desc->list);
2884 mutex_unlock(&acpi_desc_lock);
2885
2886 mutex_lock(&acpi_desc->init_mutex);
2887 acpi_desc->cancel = 1;
2888 mutex_unlock(&acpi_desc->init_mutex);
2889
2890 /*
2891 * Bounce the nvdimm bus lock to make sure any in-flight
2892 * acpi_nfit_ars_rescan() submissions have had a chance to
2893 * either submit or see ->cancel set.
2894 */
2895 device_lock(bus_dev);
2896 device_unlock(bus_dev);
2897
2898 flush_workqueue(nfit_wq);
2899}
2900EXPORT_SYMBOL_GPL(acpi_nfit_shutdown);
2901
2889static int acpi_nfit_add(struct acpi_device *adev) 2902static int acpi_nfit_add(struct acpi_device *adev)
2890{ 2903{
2891 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; 2904 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -2933,12 +2946,15 @@ static int acpi_nfit_add(struct acpi_device *adev)
2933 rc = acpi_nfit_init(acpi_desc, (void *) tbl 2946 rc = acpi_nfit_init(acpi_desc, (void *) tbl
2934 + sizeof(struct acpi_table_nfit), 2947 + sizeof(struct acpi_table_nfit),
2935 sz - sizeof(struct acpi_table_nfit)); 2948 sz - sizeof(struct acpi_table_nfit));
2936 return rc; 2949
2950 if (rc)
2951 return rc;
2952 return devm_add_action_or_reset(dev, acpi_nfit_shutdown, acpi_desc);
2937} 2953}
2938 2954
2939static int acpi_nfit_remove(struct acpi_device *adev) 2955static int acpi_nfit_remove(struct acpi_device *adev)
2940{ 2956{
2941 /* see acpi_nfit_destruct */ 2957 /* see acpi_nfit_unregister */
2942 return 0; 2958 return 0;
2943} 2959}
2944 2960
diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h
index fac098bfa585..58fb7d68e04a 100644
--- a/drivers/acpi/nfit/nfit.h
+++ b/drivers/acpi/nfit/nfit.h
@@ -239,6 +239,7 @@ static inline struct acpi_nfit_desc *to_acpi_desc(
239 239
240const u8 *to_nfit_uuid(enum nfit_uuids id); 240const u8 *to_nfit_uuid(enum nfit_uuids id);
241int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *nfit, acpi_size sz); 241int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *nfit, acpi_size sz);
242void acpi_nfit_shutdown(void *data);
242void __acpi_nfit_notify(struct device *dev, acpi_handle handle, u32 event); 243void __acpi_nfit_notify(struct device *dev, acpi_handle handle, u32 event);
243void __acpi_nvdimm_notify(struct device *dev, u32 event); 244void __acpi_nvdimm_notify(struct device *dev, u32 event);
244int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, 245int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index d7fb1b894128..c2187178fb13 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -1851,6 +1851,10 @@ static int nfit_test_probe(struct platform_device *pdev)
1851 if (rc) 1851 if (rc)
1852 return rc; 1852 return rc;
1853 1853
1854 rc = devm_add_action_or_reset(&pdev->dev, acpi_nfit_shutdown, acpi_desc);
1855 if (rc)
1856 return rc;
1857
1854 if (nfit_test->setup != nfit_test0_setup) 1858 if (nfit_test->setup != nfit_test0_setup)
1855 return 0; 1859 return 0;
1856 1860