Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3c47d19f authored by Arend van Spriel's avatar Arend van Spriel Committed by Greg Kroah-Hartman
Browse files

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: default avatarArend van Spriel <aspriel@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 36d1d09a
Loading
Loading
Loading
Loading
+33 −7
Original line number Original line Diff line number Diff line
@@ -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;
@@ -298,13 +310,25 @@ static int driver_sysfs_add(struct device *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));
				kobject_name(&dev->kobj));
	if (ret == 0) {
	if (ret)
		goto fail;

	ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj,
	ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj,
				"driver");
				"driver");
	if (ret)
	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,
	sysfs_remove_link(&dev->driver->p->kobj,
			  kobject_name(&dev->kobj));
			  kobject_name(&dev->kobj));
	}

fail:
	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");
	}
	}
+1 −1
Original line number Original line Diff line number Diff line
@@ -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 {