Messages in this thread Patch in this message | | | From | Mihai Carabas <> | Subject | [PATCH v3 2/3] misc/pvpanic: probe multiple instances | Date | Fri, 12 Feb 2021 21:32:27 +0200 |
| |
Create the mecahism that allows multiple pvpanic instances to call pvpanic_probe and receive panic events. A global list will retain all the mapped addresses where to write panic events.
Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com> --- drivers/misc/pvpanic/pvpanic-mmio.c | 9 ++--- drivers/misc/pvpanic/pvpanic.c | 76 ++++++++++++++++++++++++++++++++----- drivers/misc/pvpanic/pvpanic.h | 5 +-- 3 files changed, 73 insertions(+), 17 deletions(-)
diff --git a/drivers/misc/pvpanic/pvpanic-mmio.c b/drivers/misc/pvpanic/pvpanic-mmio.c index 7454eeb..5425369 100644 --- a/drivers/misc/pvpanic/pvpanic-mmio.c +++ b/drivers/misc/pvpanic/pvpanic-mmio.c @@ -22,11 +22,12 @@ MODULE_DESCRIPTION("pvpanic device driver"); MODULE_LICENSE("GPL"); +static void __iomem *base; + static int pvpanic_mmio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct resource *res; - void __iomem *base; res = platform_get_mem_or_io(pdev, 0); if (!res) @@ -47,15 +48,13 @@ static int pvpanic_mmio_probe(struct platform_device *pdev) return -EINVAL; } - pvpanic_probe(base); - - return 0; + return pvpanic_probe(base); } static int pvpanic_mmio_remove(struct platform_device *pdev) { - pvpanic_remove(); + pvpanic_remove(base); return 0; } diff --git a/drivers/misc/pvpanic/pvpanic.c b/drivers/misc/pvpanic/pvpanic.c index 652ae01..43b65a3 100644 --- a/drivers/misc/pvpanic/pvpanic.c +++ b/drivers/misc/pvpanic/pvpanic.c @@ -14,15 +14,30 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/types.h> +#include <linux/cdev.h> +#include <linux/list.h> +#include <linux/slab.h> #include <uapi/misc/pvpanic.h> -static void __iomem *base; +struct pvpanic_instance { + void __iomem *base; + struct list_head list; +}; + +struct list_head pvpanic_list; +spinlock_t pvpanic_lock; static void pvpanic_send_event(unsigned int event) { - iowrite8(event, base); + struct pvpanic_instance *pi_cur; + + spin_lock(&pvpanic_lock); + list_for_each_entry(pi_cur, &pvpanic_list, list) { + iowrite8(event, pi_cur->base); + } + spin_unlock(&pvpanic_lock); } static int @@ -44,19 +59,62 @@ .priority = 1, /* let this called before broken drm_fb_helper */ }; -void pvpanic_probe(void __iomem *pbase) +int pvpanic_probe(void __iomem *pbase) { - base = pbase; - atomic_notifier_chain_register(&panic_notifier_list, - &pvpanic_panic_nb); + struct pvpanic_instance *pi; + + if(!pbase) + return -EINVAL; + + pi = kmalloc(sizeof(*pi), GFP_ATOMIC); + if (!pi) + return -ENOMEM; + + pi->base = pbase; + spin_lock(&pvpanic_lock); + list_add(&pi->list, &pvpanic_list); + spin_unlock(&pvpanic_lock); + + return 0; } EXPORT_SYMBOL_GPL(pvpanic_probe); -void pvpanic_remove(void) +void pvpanic_remove(void __iomem *pbase) +{ + struct pvpanic_instance *pi_cur, *pi_next; + + if(!pbase) + return -EINVAL; + + spin_lock(&pvpanic_lock); + list_for_each_entry_safe(pi_cur, pi_next, &pvpanic_list, list) { + if (pi_cur->base == pbase) { + list_del(&pi_cur->list); + kfree(pi_cur); + break; + } + } + spin_unlock(&pvpanic_lock); +} +EXPORT_SYMBOL_GPL(pvpanic_remove); + +static int pvpanic_init(void) { + INIT_LIST_HEAD(&pvpanic_list); + spin_lock_init(&pvpanic_lock); + + atomic_notifier_chain_register(&panic_notifier_list, + &pvpanic_panic_nb); + return 0; +} + +static void pvpanic_exit(void) +{ atomic_notifier_chain_unregister(&panic_notifier_list, &pvpanic_panic_nb); - base = NULL; + } -EXPORT_SYMBOL_GPL(pvpanic_remove); + +module_init(pvpanic_init); +module_exit(pvpanic_exit); diff --git a/drivers/misc/pvpanic/pvpanic.h b/drivers/misc/pvpanic/pvpanic.h index 7e75dce..02023d7 100644 --- a/drivers/misc/pvpanic/pvpanic.h +++ b/drivers/misc/pvpanic/pvpanic.h @@ -8,10 +8,9 @@ #ifndef PVPANIC_H_ #define PVPANIC_H_ - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -void pvpanic_probe(void __iomem *base); -void pvpanic_remove(void); +int pvpanic_probe(void __iomem *base); +void pvpanic_remove(void __iomem *base); #endif /* PVPANIC_H_ */ -- 1.8.3.1
| |