Add a notification chain for SOFT RESERVE resources that are added to the iomem resource tree when the SOFT_RESERVE_MANAGED config option is specified. Update the dax driver to register a notification handler for SOFT RESERVE resources so that any late added SOFT RESERVES can be consumed by the driver. Signed-off-by: Nathan Fontenot <nathan.fontenot@xxxxxxx> --- drivers/dax/hmem/hmem.c | 24 +++++++++++++++++++++++- include/linux/ioport.h | 11 +++++++++++ kernel/resource.c | 21 +++++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/dax/hmem/hmem.c b/drivers/dax/hmem/hmem.c index 088f4060d4d5..0e6b7558ca3d 100644 --- a/drivers/dax/hmem/hmem.c +++ b/drivers/dax/hmem/hmem.c @@ -126,14 +126,36 @@ static int hmem_register_device(const struct resource *res) return rc; } +static int dax_hmem_cb(struct notifier_block *nb, unsigned long action, + void *arg) +{ + return hmem_register_device((struct resource *)arg); +} + +static struct notifier_block dax_hmem_nb = { + .notifier_call = dax_hmem_cb, +}; + static int dax_hmem_platform_probe(struct platform_device *pdev) { + int rc; + dax_hmem_pdev = pdev; - return walk_hmem_resources(hmem_register_device); + rc = walk_hmem_resources(hmem_register_device); + + register_srmem_notifier(&dax_hmem_nb); + return rc; +} + +static void dax_hmem_platform_remove(struct platform_device *pdev) +{ + dax_hmem_pdev = NULL; + unregister_srmem_notifier(&dax_hmem_nb); } static struct platform_driver dax_hmem_platform_driver = { .probe = dax_hmem_platform_probe, + .remove = dax_hmem_platform_remove, .driver = { .name = "hmem_platform", }, diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 2c95cf0be45e..c173cdd5ab87 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -13,6 +13,7 @@ #include <linux/bits.h> #include <linux/compiler.h> #include <linux/minmax.h> +#include <linux/notifier.h> #include <linux/types.h> /* * Resources are tree-like, allowing @@ -254,8 +255,18 @@ resource_size_t resource_alignment(struct resource *res); void merge_srmem_resources(void); extern void release_srmem_region_adjustable(resource_size_t start, resource_size_t size); +int register_srmem_notifier(struct notifier_block *nb); +int unregister_srmem_notifier(struct notifier_block *nb); #else static inline void merge_srmem_resources(void) { } +static int register_srmem_notifier(struct notifier_block *nb) +{ + return 0; +} +static int unregister_srmem_notifier(struct notifier_block *nb) +{ + return 0; +} #endif static inline resource_size_t resource_size(const struct resource *res) diff --git a/kernel/resource.c b/kernel/resource.c index 9db420078a3f..3e117e3ba2a5 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -1471,6 +1471,26 @@ static void release_region_adjustable(struct resource *parent, } #ifdef CONFIG_SOFT_RESERVED_MANAGED + +static RAW_NOTIFIER_HEAD(srmem_chain); + +int register_srmem_notifier(struct notifier_block *nb) +{ + return raw_notifier_chain_register(&srmem_chain, nb); +} +EXPORT_SYMBOL(register_srmem_notifier); + +int unregister_srmem_notifier(struct notifier_block *nb) +{ + return raw_notifier_chain_unregister(&srmem_chain, nb); +} +EXPORT_SYMBOL(unregister_srmem_notifier); + +static int srmem_notify(void *v) +{ + return raw_notifier_call_chain(&srmem_chain, 0, v); +} + /** * merge_srmem_resources - merge srmem resources into the iomem resource tree * @@ -1497,6 +1517,7 @@ void merge_srmem_resources(void) __insert_resource(&srmem_resource, res); write_unlock(&resource_lock); + srmem_notify(res); } } EXPORT_SYMBOL_GPL(merge_srmem_resources); -- 2.43.0