lkml.org 
[lkml]   [2021]   [Feb]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 2/3] misc/pvpanic: probe multiple instances
    Date
    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
    \
     
     \ /
      Last update: 2021-02-12 21:21    [W:4.319 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site