Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932502AbeAKIho (ORCPT + 1 other); Thu, 11 Jan 2018 03:37:44 -0500 Received: from rnd-relay.smtp.broadcom.com ([192.19.229.170]:57789 "EHLO rnd-relay.smtp.broadcom.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932238AbeAKIgx (ORCPT ); Thu, 11 Jan 2018 03:36:53 -0500 From: Arend van Spriel To: Greg Koah Hartmann Cc: LKML , Arend van Spriel Subject: [PATCH V3 2/3] drivers: base: add coredump driver ops Date: Thu, 11 Jan 2018 09:36:38 +0100 Message-Id: <1515659799-23521-3-git-send-email-aspriel@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1515659799-23521-1-git-send-email-aspriel@gmail.com> References: <1515659799-23521-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. Signed-off-by: Arend van Spriel --- V2: - extended the commit message. V3: - no changes. --- 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