Received: by 2002:a05:6a10:22f:0:0:0:0 with SMTP id 15csp1266579pxk; Fri, 2 Oct 2020 05:33:04 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzpfPbayVY5PFyIX/vJulAnUz7NAOR+0f3dEq/iKdqyuQVGVliTfv8oByA3HqTLxlXLDIIv X-Received: by 2002:a05:6402:1c10:: with SMTP id ck16mr2071290edb.7.1601641983797; Fri, 02 Oct 2020 05:33:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1601641983; cv=none; d=google.com; s=arc-20160816; b=Xpd4XnX540gxWodSz+vVi1lJAN5ZSKsk5lERmSOzy/bGoxZp7KcnVYqwmIM7m/CiDO gPNbRVfuH/lK8p7PNiOttqvvnwX1lI05DT074ZMvEAQDSYNXUbyyoLxgvLxtqIhmV6uy 8eMovUsDvNVhCSyTqaJmnLyg+JvPkOOcgdbc7DW0w7oV2z2KCHh7Q2AhA96LOsGo17f9 6lu94Mwan2ZV3ucvrEt/5ZYzCSL+QUnU/atqQIFVxh193Yw+DBHbe7Aiw3LSPPxRo6JX TDKWX7QND1N+dCDEW9yEs4OzSxmaJUSY6owxuPlLVHd8kYOkLuloRVNsEZxTb6ek0dQB j1Mw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from; bh=JCWcNsaDln/ZX07Xovkf5xnTTXM0g48dQJtI3sk1W+0=; b=kiYSN5fJtMcgm6vqjZSHcuYhABPR7N1gGlXK2RpMBKwl1sHDR4cP0X1UNNALNpAXkW L/uR+e6iesk6DImbrQuwLZlEfwegWLanyCis5Kqhk8NDcaUXx4QeE039fY/Cz25GA4Nd e8P56qfSg300I4xftwYtJ2YTV30O60r1FfdLrlz4NbW9x63Cp8hI+RbMG6CjmFKdW4nU lA1XB7II/ASEIsntLVYQDp417I1UDT/FMOz0GMd+kYQ31X3OA02ZVCidVGQBwVaufSep YkiS6bEwdP1CR4AvXWr/URoGpi6Oi+DDK1fqjHE8Zpb+suVq0czlpiKRqQy/WDcL5/U1 Sz5w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id s24si855676edi.129.2020.10.02.05.32.40; Fri, 02 Oct 2020 05:33:03 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387785AbgJBMbV (ORCPT + 99 others); Fri, 2 Oct 2020 08:31:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36308 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387677AbgJBMbV (ORCPT ); Fri, 2 Oct 2020 08:31:21 -0400 Received: from smtp2-2.goneo.de (smtp2.goneo.de [IPv6:2001:1640:5::8:33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9C069C0613D0; Fri, 2 Oct 2020 05:31:20 -0700 (PDT) Received: from localhost (localhost [127.0.0.1]) by smtp2.goneo.de (Postfix) with ESMTP id AA89323F66A; Fri, 2 Oct 2020 14:31:17 +0200 (CEST) X-Virus-Scanned: by goneo X-Spam-Flag: NO X-Spam-Score: -2.997 X-Spam-Level: X-Spam-Status: No, score=-2.997 tagged_above=-999 tests=[ALL_TRUSTED=-1, AWL=-0.097, BAYES_00=-1.9] autolearn=ham Received: from smtp2.goneo.de ([127.0.0.1]) by localhost (smtp2.goneo.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Hs9TwZSDOHnW; Fri, 2 Oct 2020 14:31:16 +0200 (CEST) Received: from lem-wkst-02.lemonage.de. (hq.lemonage.de [87.138.178.34]) by smtp2.goneo.de (Postfix) with ESMTPA id 219A423F3EA; Fri, 2 Oct 2020 14:31:16 +0200 (CEST) From: poeschel@lemonage.de To: Thierry Reding , =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= , Lee Jones , linux-pwm@vger.kernel.org (open list:PWM SUBSYSTEM), linux-kernel@vger.kernel.org (open list) Cc: Lars Poeschel , Greg Kroah-Hartman Subject: [PATCH 1/2] pwm: sysfs: Set class on pwm devices Date: Fri, 2 Oct 2020 14:30:47 +0200 Message-Id: <20201002123048.3073128-1-poeschel@lemonage.de> X-Mailer: git-send-email 2.28.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Lars Poeschel This adds a class to exported pwm devices. Exporting a pwm through sysfs did not yield udev events. The dev_uevent_filter function does filter-out devices without a bus or class. This was already addressed in commit commit 7e5d1fd75c3d ("pwm: Set class for exported channels in sysfs") but this did cause problems and the commit got reverted with commit c289d6625237 ("Revert "pwm: Set class for exported channels in sysfs"") Problem with the previous approach was, that there is a clash if we have multiple pwmchips: echo 0 > pwmchip0/export echo 0 > pwmchip1/export would both export /sys/class/pwm/pwm0 . Now this patch changes the sysfs interface. We do include the pwmchip number into the pwm directory that gets exported. With the example above we get: /sys/class/pwm/pwm-0-0 /sys/class/pwm/pwm-1-0 We maintain ABI backward compatibility through symlinks. /sys/class/pwm/pwmchip0/pwm0 /sys/class/pwm/pwmchip1/pwm0 are now symbolic links to the new names. Cc: Greg Kroah-Hartman Signed-off-by: Lars Poeschel --- drivers/pwm/sysfs.c | 57 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 449dbc0f49ed..c708da17a857 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c @@ -240,8 +240,10 @@ static void pwm_export_release(struct device *child) static int pwm_export_child(struct device *parent, struct pwm_device *pwm) { + struct pwm_chip *chip = dev_get_drvdata(parent); struct pwm_export *export; char *pwm_prop[2]; + char *link_name; int ret; if (test_and_set_bit(PWMF_EXPORTED, &pwm->flags)) @@ -256,25 +258,39 @@ static int pwm_export_child(struct device *parent, struct pwm_device *pwm) export->pwm = pwm; mutex_init(&export->lock); + export->child.class = parent->class; export->child.release = pwm_export_release; export->child.parent = parent; export->child.devt = MKDEV(0, 0); export->child.groups = pwm_groups; - dev_set_name(&export->child, "pwm%u", pwm->hwpwm); + dev_set_name(&export->child, "pwm-%u-%u", chip->base, pwm->hwpwm); ret = device_register(&export->child); - if (ret) { - clear_bit(PWMF_EXPORTED, &pwm->flags); - put_device(&export->child); - export = NULL; - return ret; + if (ret) + goto error; + + link_name = kasprintf(GFP_KERNEL, "pwm%u", pwm->hwpwm); + if (link_name == NULL) { + ret = -ENOMEM; + goto dev_unregister; } - pwm_prop[0] = kasprintf(GFP_KERNEL, "EXPORT=pwm%u", pwm->hwpwm); + + pwm_prop[0] = kasprintf(GFP_KERNEL, "EXPORT=%s", + export->child.kobj.name); pwm_prop[1] = NULL; kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop); kfree(pwm_prop[0]); - return 0; + ret = sysfs_create_link(&parent->kobj, &export->child.kobj, link_name); + return ret; + +dev_unregister: + device_unregister(&export->child); +error: + clear_bit(PWMF_EXPORTED, &pwm->flags); + put_device(&export->child); + export = NULL; + return ret; } static int pwm_unexport_match(struct device *child, void *data) @@ -286,6 +302,7 @@ static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm) { struct device *child; char *pwm_prop[2]; + char *link_name; if (!test_and_clear_bit(PWMF_EXPORTED, &pwm->flags)) return -ENODEV; @@ -294,7 +311,11 @@ static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm) if (!child) return -ENODEV; - pwm_prop[0] = kasprintf(GFP_KERNEL, "UNEXPORT=pwm%u", pwm->hwpwm); + link_name = kasprintf(GFP_KERNEL, "pwm%u", pwm->hwpwm); + if (link_name) + sysfs_delete_link(&parent->kobj, &child->kobj, link_name); + + pwm_prop[0] = kasprintf(GFP_KERNEL, "UNEXPORT=%s", child->kobj.name); pwm_prop[1] = NULL; kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop); kfree(pwm_prop[0]); @@ -365,13 +386,29 @@ static ssize_t npwm_show(struct device *parent, struct device_attribute *attr, } static DEVICE_ATTR_RO(npwm); +static umode_t pwm_is_visible(struct kobject *kobj, struct attribute *attr, + int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + + if (dev->groups == pwm_groups) + return 0; + + return attr->mode; +} + static struct attribute *pwm_chip_attrs[] = { &dev_attr_export.attr, &dev_attr_unexport.attr, &dev_attr_npwm.attr, NULL, }; -ATTRIBUTE_GROUPS(pwm_chip); + +static const struct attribute_group pwm_chip_group = { + .attrs = pwm_chip_attrs, + .is_visible = pwm_is_visible, +}; +__ATTRIBUTE_GROUPS(pwm_chip); /* takes export->lock on success */ static struct pwm_export *pwm_class_get_state(struct device *parent, -- 2.28.0