Skip to content
Permalink
Browse files
misc/pvpanic: probe multiple instances
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>
  • Loading branch information
mcarabas authored and intel-lab-lkp committed Feb 12, 2021
1 parent e69d90d commit 70eed71fbb1f23b28a401213c2dac3c27fcae323
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 17 deletions.
@@ -22,11 +22,12 @@ MODULE_AUTHOR("Hu Tao <hutao@cn.fujitsu.com>");
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;
}
@@ -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 @@ static struct notifier_block pvpanic_panic_nb = {
.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);
@@ -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_ */

0 comments on commit 70eed71

Please sign in to comment.