From patchwork Tue Apr 21 15:42:20 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johan Hovold X-Patchwork-Id: 463368 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 2F52F14011D for ; Wed, 22 Apr 2015 01:46:57 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="verification failed; unprotected key" header.d=gmail.com header.i=@gmail.com header.b=VGeSlRwQ; dkim-adsp=none (unprotected policy); dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932392AbbDUPqi (ORCPT ); Tue, 21 Apr 2015 11:46:38 -0400 Received: from mail-lb0-f182.google.com ([209.85.217.182]:36393 "EHLO mail-lb0-f182.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755750AbbDUPoD (ORCPT ); Tue, 21 Apr 2015 11:44:03 -0400 Received: by lbbqq2 with SMTP id qq2so158817163lbb.3; Tue, 21 Apr 2015 08:44:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=7v+TtsZCInPmDkbLybIrNKCurbpzcM3SL7F1xwTu1qs=; b=VGeSlRwQ8/2tUgFcsVC3SaE85827RRWMquMLrhZztmeO2w0GFVF2XgwJUozOqm0+Gt WxNGO+qQEK0e4eFR+4qMmGILNVPFtMQonLrurylVYAURKPA7hFZJ+lI5G1BuNzeQZqBf CBkb4q9Kb3yk4CHkuBGgb1Nst6OPEL9SZ6HyOwbVmIIwOx0qCK13vx2KPjC1Og6L+P1I VGqk2sEdtVp4DY9R3ejU1BKw24SGjaU8UFSmNfqcNCLDFhmcdNUjlKPoXqKuStDplrxy faYk1LH5ItnrF+3BjjF5iSrsjOIm/11LBem6k6ZR7To9rBktKbhSL83/nPACeCiFLF8n fXHA== X-Received: by 10.112.119.163 with SMTP id kv3mr20872852lbb.101.1429631042035; Tue, 21 Apr 2015 08:44:02 -0700 (PDT) Received: from xi.terra (c193-14-96-226.cust.tele2.se. [193.14.96.226]) by mx.google.com with ESMTPSA id pn1sm489144lbc.6.2015.04.21.08.44.00 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 21 Apr 2015 08:44:01 -0700 (PDT) Received: from johan by xi.terra with local (Exim 4.84) (envelope-from ) id 1YkaKM-00074j-Gw; Tue, 21 Apr 2015 17:43:10 +0200 From: Johan Hovold To: Linus Walleij Cc: Alexandre Courbot , linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, Johan Hovold Subject: [PATCH 12/23] gpio: sysfs: add gpiod class-device data Date: Tue, 21 Apr 2015 17:42:20 +0200 Message-Id: <1429630951-27082-13-git-send-email-johan@kernel.org> X-Mailer: git-send-email 2.0.5 In-Reply-To: <1429630951-27082-1-git-send-email-johan@kernel.org> References: <1429630951-27082-1-git-send-email-johan@kernel.org> Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Add gpiod class-device data. This is a first step in getting rid of the insane gpio-descriptor flag overloading, backward irq-interface implementation, and course grained sysfs-interface locking (a single static mutex for every operation on all exported gpios in a system). Signed-off-by: Johan Hovold --- drivers/gpio/gpiolib-sysfs.c | 62 ++++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index b77f29cd1603..4cc90f7ce14b 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -6,9 +6,14 @@ #include #include #include +#include #include "gpiolib.h" +struct gpiod_data { + struct gpio_desc *desc; +}; + static DEFINE_IDR(dirent_idr); @@ -41,7 +46,8 @@ static DEFINE_MUTEX(sysfs_lock); static ssize_t direction_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct gpio_desc *desc = dev_get_drvdata(dev); + struct gpiod_data *data = dev_get_drvdata(dev); + struct gpio_desc *desc = data->desc; ssize_t status; mutex_lock(&sysfs_lock); @@ -58,7 +64,8 @@ static ssize_t direction_show(struct device *dev, static ssize_t direction_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - struct gpio_desc *desc = dev_get_drvdata(dev); + struct gpiod_data *data = dev_get_drvdata(dev); + struct gpio_desc *desc = data->desc; ssize_t status; mutex_lock(&sysfs_lock); @@ -80,7 +87,8 @@ static DEVICE_ATTR_RW(direction); static ssize_t value_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct gpio_desc *desc = dev_get_drvdata(dev); + struct gpiod_data *data = dev_get_drvdata(dev); + struct gpio_desc *desc = data->desc; ssize_t status; mutex_lock(&sysfs_lock); @@ -94,7 +102,8 @@ static ssize_t value_show(struct device *dev, static ssize_t value_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - struct gpio_desc *desc = dev_get_drvdata(dev); + struct gpiod_data *data = dev_get_drvdata(dev); + struct gpio_desc *desc = data->desc; ssize_t status; mutex_lock(&sysfs_lock); @@ -210,7 +219,8 @@ static const struct { static ssize_t edge_show(struct device *dev, struct device_attribute *attr, char *buf) { - const struct gpio_desc *desc = dev_get_drvdata(dev); + struct gpiod_data *data = dev_get_drvdata(dev); + struct gpio_desc *desc = data->desc; unsigned long mask; ssize_t status = 0; int i; @@ -232,7 +242,8 @@ static ssize_t edge_show(struct device *dev, static ssize_t edge_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - struct gpio_desc *desc = dev_get_drvdata(dev); + struct gpiod_data *data = dev_get_drvdata(dev); + struct gpio_desc *desc = data->desc; ssize_t status; int i; @@ -282,7 +293,8 @@ static int sysfs_set_active_low(struct gpio_desc *desc, struct device *dev, static ssize_t active_low_show(struct device *dev, struct device_attribute *attr, char *buf) { - const struct gpio_desc *desc = dev_get_drvdata(dev); + struct gpiod_data *data = dev_get_drvdata(dev); + struct gpio_desc *desc = data->desc; ssize_t status; mutex_lock(&sysfs_lock); @@ -298,7 +310,8 @@ static ssize_t active_low_show(struct device *dev, static ssize_t active_low_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - struct gpio_desc *desc = dev_get_drvdata(dev); + struct gpiod_data *data = dev_get_drvdata(dev); + struct gpio_desc *desc = data->desc; ssize_t status; long value; @@ -318,7 +331,8 @@ static umode_t gpio_is_visible(struct kobject *kobj, struct attribute *attr, int n) { struct device *dev = container_of(kobj, struct device, kobj); - struct gpio_desc *desc = dev_get_drvdata(dev); + struct gpiod_data *data = dev_get_drvdata(dev); + struct gpio_desc *desc = data->desc; umode_t mode = attr->mode; bool show_direction = test_bit(FLAG_SYSFS_DIR, &desc->flags); @@ -510,6 +524,7 @@ static struct class gpio_class = { int gpiod_export(struct gpio_desc *desc, bool direction_may_change) { struct gpio_chip *chip; + struct gpiod_data *data; unsigned long flags; int status; const char *ioname = NULL; @@ -534,7 +549,7 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) /* check if chip is being removed */ if (!chip || !chip->cdev) { status = -ENODEV; - goto fail_unlock; + goto err_unlock; } spin_lock_irqsave(&gpio_lock, flags); @@ -546,7 +561,7 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) test_bit(FLAG_REQUESTED, &desc->flags), test_bit(FLAG_EXPORT, &desc->flags)); status = -EPERM; - goto fail_unlock; + goto err_unlock; } if (chip->direction_input && chip->direction_output && @@ -556,33 +571,45 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) spin_unlock_irqrestore(&gpio_lock, flags); + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto err_unlock; + } + + data->desc = desc; + offset = gpio_chip_hwgpio(desc); if (chip->names && chip->names[offset]) ioname = chip->names[offset]; dev = device_create_with_groups(&gpio_class, chip->dev, - MKDEV(0, 0), desc, gpio_groups, + MKDEV(0, 0), data, gpio_groups, ioname ? ioname : "gpio%u", desc_to_gpio(desc)); if (IS_ERR(dev)) { status = PTR_ERR(dev); - goto fail_unlock; + goto err_free_data; } set_bit(FLAG_EXPORT, &desc->flags); mutex_unlock(&sysfs_lock); return 0; -fail_unlock: +err_free_data: + kfree(data); +err_unlock: mutex_unlock(&sysfs_lock); gpiod_dbg(desc, "%s: status %d\n", __func__, status); return status; } EXPORT_SYMBOL_GPL(gpiod_export); -static int match_export(struct device *dev, const void *data) +static int match_export(struct device *dev, const void *desc) { - return dev_get_drvdata(dev) == data; + struct gpiod_data *data = dev_get_drvdata(dev); + + return data->desc == desc; } /** @@ -638,6 +665,7 @@ EXPORT_SYMBOL_GPL(gpiod_export_link); */ void gpiod_unexport(struct gpio_desc *desc) { + struct gpiod_data *data; int status = 0; struct device *dev = NULL; @@ -661,6 +689,7 @@ void gpiod_unexport(struct gpio_desc *desc) mutex_unlock(&sysfs_lock); if (dev) { + data = dev_get_drvdata(dev); device_unregister(dev); /* * Release irq after deregistration to prevent race with @@ -668,6 +697,7 @@ void gpiod_unexport(struct gpio_desc *desc) */ gpio_setup_irq(desc, dev, 0); put_device(dev); + kfree(data); } if (status)