mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-04-05 05:54:25 +00:00
drivers: base: add coredump driver ops
This adds the coredump driver operation. When the driver defines it a coredump file is added in the sysfs folder of the device upon driver binding. The file is removed when the driver is unbound. User-space can trigger a coredump for this device by echo'ing to the coredump file. Signed-off-by: Arend van Spriel <aspriel@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
36d1d09af1
commit
3c47d19ff4
2 changed files with 34 additions and 8 deletions
|
@ -288,6 +288,18 @@ static void driver_bound(struct device *dev)
|
||||||
kobject_uevent(&dev->kobj, KOBJ_BIND);
|
kobject_uevent(&dev->kobj, KOBJ_BIND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t coredump_store(struct device *dev, struct device_attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
device_lock(dev);
|
||||||
|
if (dev->driver->coredump)
|
||||||
|
dev->driver->coredump(dev);
|
||||||
|
device_unlock(dev);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
static DEVICE_ATTR_WO(coredump);
|
||||||
|
|
||||||
static int driver_sysfs_add(struct device *dev)
|
static int driver_sysfs_add(struct device *dev)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -297,14 +309,26 @@ static int driver_sysfs_add(struct device *dev)
|
||||||
BUS_NOTIFY_BIND_DRIVER, dev);
|
BUS_NOTIFY_BIND_DRIVER, dev);
|
||||||
|
|
||||||
ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj,
|
ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj,
|
||||||
|
kobject_name(&dev->kobj));
|
||||||
|
if (ret)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj,
|
||||||
|
"driver");
|
||||||
|
if (ret)
|
||||||
|
goto rm_dev;
|
||||||
|
|
||||||
|
if (!IS_ENABLED(CONFIG_DEV_COREDUMP) || !dev->driver->coredump ||
|
||||||
|
!device_create_file(dev, &dev_attr_coredump))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
sysfs_remove_link(&dev->kobj, "driver");
|
||||||
|
|
||||||
|
rm_dev:
|
||||||
|
sysfs_remove_link(&dev->driver->p->kobj,
|
||||||
kobject_name(&dev->kobj));
|
kobject_name(&dev->kobj));
|
||||||
if (ret == 0) {
|
|
||||||
ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj,
|
fail:
|
||||||
"driver");
|
|
||||||
if (ret)
|
|
||||||
sysfs_remove_link(&dev->driver->p->kobj,
|
|
||||||
kobject_name(&dev->kobj));
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,6 +337,8 @@ static void driver_sysfs_remove(struct device *dev)
|
||||||
struct device_driver *drv = dev->driver;
|
struct device_driver *drv = dev->driver;
|
||||||
|
|
||||||
if (drv) {
|
if (drv) {
|
||||||
|
if (drv->coredump)
|
||||||
|
device_remove_file(dev, &dev_attr_coredump);
|
||||||
sysfs_remove_link(&drv->p->kobj, kobject_name(&dev->kobj));
|
sysfs_remove_link(&drv->p->kobj, kobject_name(&dev->kobj));
|
||||||
sysfs_remove_link(&dev->kobj, "driver");
|
sysfs_remove_link(&dev->kobj, "driver");
|
||||||
}
|
}
|
||||||
|
|
|
@ -287,6 +287,7 @@ struct device_driver {
|
||||||
const struct attribute_group **groups;
|
const struct attribute_group **groups;
|
||||||
|
|
||||||
const struct dev_pm_ops *pm;
|
const struct dev_pm_ops *pm;
|
||||||
|
int (*coredump) (struct device *dev);
|
||||||
|
|
||||||
struct driver_private *p;
|
struct driver_private *p;
|
||||||
};
|
};
|
||||||
|
@ -300,7 +301,6 @@ extern struct device_driver *driver_find(const char *name,
|
||||||
extern int driver_probe_done(void);
|
extern int driver_probe_done(void);
|
||||||
extern void wait_for_device_probe(void);
|
extern void wait_for_device_probe(void);
|
||||||
|
|
||||||
|
|
||||||
/* sysfs interface for exporting driver attributes */
|
/* sysfs interface for exporting driver attributes */
|
||||||
|
|
||||||
struct driver_attribute {
|
struct driver_attribute {
|
||||||
|
|
Loading…
Add table
Reference in a new issue