From patchwork Tue Jan 22 12:06:42 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roland Stigge X-Patchwork-Id: 2018321 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id 49DB63FD1A for ; Tue, 22 Jan 2013 12:12:44 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TxceU-0006CS-02; Tue, 22 Jan 2013 12:08:30 +0000 Received: from mail.work-microwave.de ([62.245.205.51] helo=work-microwave.de) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TxcdV-0005eg-W7 for linux-arm-kernel@lists.infradead.org; Tue, 22 Jan 2013 12:07:39 +0000 Received: from rst-pc1.lan.work-microwave.de ([192.168.11.78]) (authenticated bits=0) by mail.work-microwave.de with ESMTP id r0MC75RC004315 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 22 Jan 2013 13:07:06 +0100 Received: by rst-pc1.lan.work-microwave.de (Postfix, from userid 1000) id 5C4EDAE08B; Tue, 22 Jan 2013 13:07:05 +0100 (CET) From: Roland Stigge To: gregkh@linuxfoundation.org, grant.likely@secretlab.ca, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, w.sang@pengutronix.de, jbe@pengutronix.de, plagnioj@jcrosoft.com, highguy@gmail.com, broonie@opensource.wolfsonmicro.com, daniel-gl@gmx.net, rmallon@gmail.com, sr@denx.de, wg@grandegger.com, mark.rutland@arm.com, nicolas.ferre@atmel.com Subject: [PATCH 4/6 v14] gpiolib: Fix default attributes for class Date: Tue, 22 Jan 2013 13:06:42 +0100 Message-Id: <1358856404-8975-5-git-send-email-stigge@antcom.de> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1358856404-8975-1-git-send-email-stigge@antcom.de> References: <1358856404-8975-1-git-send-email-stigge@antcom.de> X-FEAS-SYSTEM-WL: rst@work-microwave.de, 192.168.11.78 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130122_070730_588541_94F46B7C X-CRM114-Status: GOOD ( 16.38 ) X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Roland Stigge X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org There is a race condition between creating a gpio or gpiochip device and adding default attributes. This patch fixes this by defining the default attributes as dev_attrs of the class. For this, it was necessary to create a separate gpiochip_class besides gpio_class. Signed-off-by: Roland Stigge --- Documentation/ABI/testing/sysfs-gpio | 11 ++++ drivers/gpio/gpiolib.c | 78 ++++++++++++++--------------------- 2 files changed, 44 insertions(+), 45 deletions(-) --- linux-2.6.orig/Documentation/ABI/testing/sysfs-gpio +++ linux-2.6/Documentation/ABI/testing/sysfs-gpio @@ -20,6 +20,17 @@ Description: /value ... always readable, writes fail for input GPIOs /direction ... r/w as: in, out (default low); write: high, low /edge ... r/w as: none, falling, rising, both + +What: /sys/class/gpiochip/ +Date: October 2012 +KernelVersion: 3.7 +Contact: Roland Stigge +Description: + + Each gpiochip is represented by a separate device having the following + attributes: + + /sys/class/gpiochip /gpiochipN ... for each gpiochip; #N is its first GPIO /base ... (r/o) same as N /label ... (r/o) descriptive, not necessarily unique --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -362,9 +362,6 @@ static ssize_t gpio_value_store(struct d return status; } -static const DEVICE_ATTR(value, 0644, - gpio_value_show, gpio_value_store); - static irqreturn_t gpio_sysfs_irq(int irq, void *priv) { struct sysfs_dirent *value_sd = priv; @@ -585,19 +582,6 @@ static ssize_t gpio_active_low_store(str return status ? : size; } -static const DEVICE_ATTR(active_low, 0644, - gpio_active_low_show, gpio_active_low_store); - -static const struct attribute *gpio_attrs[] = { - &dev_attr_value.attr, - &dev_attr_active_low.attr, - NULL, -}; - -static const struct attribute_group gpio_attr_group = { - .attrs = (struct attribute **) gpio_attrs, -}; - /* * /sys/class/gpio/gpiochipN/ * /base ... matching gpio_chip.base (N) @@ -612,7 +596,6 @@ static ssize_t chip_base_show(struct dev return sprintf(buf, "%d\n", chip->base); } -static DEVICE_ATTR(base, 0444, chip_base_show, NULL); static ssize_t chip_label_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -621,7 +604,6 @@ static ssize_t chip_label_show(struct de return sprintf(buf, "%s\n", chip->label ? : ""); } -static DEVICE_ATTR(label, 0444, chip_label_show, NULL); static ssize_t chip_ngpio_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -630,18 +612,6 @@ static ssize_t chip_ngpio_show(struct de return sprintf(buf, "%u\n", chip->ngpio); } -static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL); - -static const struct attribute *gpiochip_attrs[] = { - &dev_attr_base.attr, - &dev_attr_label.attr, - &dev_attr_ngpio.attr, - NULL, -}; - -static const struct attribute_group gpiochip_attr_group = { - .attrs = (struct attribute **) gpiochip_attrs, -}; /* * /sys/class/gpio/export ... write-only @@ -720,11 +690,32 @@ static struct class_attribute gpio_class __ATTR_NULL, }; +static struct device_attribute gpio_attrs[] = { + __ATTR(active_low, 0644, gpio_active_low_show, gpio_active_low_store), + __ATTR(value, 0644, gpio_value_show, gpio_value_store), + __ATTR_NULL, +}; + static struct class gpio_class = { .name = "gpio", .owner = THIS_MODULE, - .class_attrs = gpio_class_attrs, + .class_attrs = gpio_class_attrs, + .dev_attrs = gpio_attrs, +}; + +static struct device_attribute gpiochip_attrs[] = { + __ATTR(label, 0444, chip_label_show, NULL), + __ATTR(base, 0444, chip_base_show, NULL), + __ATTR(ngpio, 0444, chip_ngpio_show, NULL), + __ATTR_NULL, +}; + +static struct class gpiochip_class = { + .name = "gpiochip", + .owner = THIS_MODULE, + + .dev_attrs = gpiochip_attrs, }; @@ -791,10 +782,6 @@ int gpio_export(unsigned gpio, bool dire goto fail_unlock; } - status = sysfs_create_group(&dev->kobj, &gpio_attr_group); - if (status) - goto fail_unregister_device; - if (direction_may_change) { status = device_create_file(dev, &dev_attr_direction); if (status) @@ -962,25 +949,22 @@ EXPORT_SYMBOL_GPL(gpio_unexport); static int gpiochip_export(struct gpio_chip *chip) { - int status; + int status = 0; struct device *dev; /* Many systems register gpio chips for SOC support very early, * before driver model support is available. In those cases we * export this later, in gpiolib_sysfs_init() ... here we just - * verify that _some_ field of gpio_class got initialized. + * verify that _some_ field of gpiochip_class got initialized. */ - if (!gpio_class.p) + if (!gpiochip_class.p) return 0; /* use chip->base for the ID; it's already known to be unique */ mutex_lock(&sysfs_lock); - dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip, - "gpiochip%d", chip->base); - if (!IS_ERR(dev)) { - status = sysfs_create_group(&dev->kobj, - &gpiochip_attr_group); - } else + dev = device_create(&gpiochip_class, chip->dev, MKDEV(0, 0), chip, + "gpiochip%d", chip->base); + if (IS_ERR(dev)) status = PTR_ERR(dev); chip->exported = (status == 0); mutex_unlock(&sysfs_lock); @@ -1008,7 +992,7 @@ static void gpiochip_unexport(struct gpi struct device *dev; mutex_lock(&sysfs_lock); - dev = class_find_device(&gpio_class, NULL, chip, match_export); + dev = class_find_device(&gpiochip_class, NULL, chip, match_export); if (dev) { put_device(dev); device_unregister(dev); @@ -1267,6 +1251,10 @@ static int __init gpiolib_sysfs_init(voi if (status < 0) return status; + status = class_register(&gpiochip_class); + if (status < 0) + return status; + status = class_register(&gpio_block_class); if (status < 0) return status;