Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965246AbeAJNyI (ORCPT + 1 other); Wed, 10 Jan 2018 08:54:08 -0500 Received: from rnd-relay.smtp.broadcom.com ([192.19.229.170]:45835 "EHLO rnd-relay.smtp.broadcom.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965054AbeAJNyD (ORCPT ); Wed, 10 Jan 2018 08:54:03 -0500 From: Arend van Spriel To: Greg Koah Hartmann Cc: LKML , Arend van Spriel Subject: [PATCH V2 2/3] drivers: base: add coredump driver ops Date: Wed, 10 Jan 2018 14:53:48 +0100 Message-Id: <1515592429-17420-3-git-send-email-aspriel@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1515592429-17420-1-git-send-email-aspriel@gmail.com> References: <1515592429-17420-1-git-send-email-aspriel@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Return-Path: 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. Instead of obtaining raw coredump data from the driver it is left to the coredump driver operation to invoke the devcoredump API as there are more ways to do that. Signed-off-by: Arend van Spriel --- V2: - extended the commit message. --- drivers/base/dd.c | 40 +++++++++++++++++++++++++++++++++------- include/linux/device.h | 2 +- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 533c82f..de6fd09 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -288,6 +288,18 @@ static void driver_bound(struct device *dev) 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) { int ret; @@ -297,14 +309,26 @@ static int driver_sysfs_add(struct device *dev) BUS_NOTIFY_BIND_DRIVER, dev); 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)); - if (ret == 0) { - ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj, - "driver"); - if (ret) - sysfs_remove_link(&dev->driver->p->kobj, - kobject_name(&dev->kobj)); - } + +fail: return ret; } @@ -313,6 +337,8 @@ static void driver_sysfs_remove(struct device *dev) struct device_driver *drv = dev->driver; 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(&dev->kobj, "driver"); } diff --git a/include/linux/device.h b/include/linux/device.h index 46cece5..cd3b47e 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -287,6 +287,7 @@ struct device_driver { const struct attribute_group **groups; const struct dev_pm_ops *pm; + int (*coredump) (struct device *dev); struct driver_private *p; }; @@ -300,7 +301,6 @@ extern struct device_driver *driver_find(const char *name, extern int driver_probe_done(void); extern void wait_for_device_probe(void); - /* sysfs interface for exporting driver attributes */ struct driver_attribute { -- 1.9.1