From patchwork Fri Apr 11 07:26:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Koichiro Den X-Patchwork-Id: 2071371 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4ZYpDX3xZtz1yHt for ; Fri, 11 Apr 2025 17:27:40 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1u38nn-0003JH-T8; Fri, 11 Apr 2025 07:27:51 +0000 Received: from smtp-relay-internal-1.internal ([10.131.114.114] helo=smtp-relay-internal-1.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1u38nl-0003AA-Mk for kernel-team@lists.ubuntu.com; Fri, 11 Apr 2025 07:27:49 +0000 Received: from mail-pg1-f198.google.com (mail-pg1-f198.google.com [209.85.215.198]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-1.canonical.com (Postfix) with ESMTPS id 75D65400AF for ; Fri, 11 Apr 2025 07:27:49 +0000 (UTC) Received: by mail-pg1-f198.google.com with SMTP id 41be03b00d2f7-af8d8e0689eso1889769a12.2 for ; Fri, 11 Apr 2025 00:27:49 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744356466; x=1744961266; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=+RsrGW5f2KjvMSwGY84aAXy1/6R8+Bqn/rtsfJi+F0E=; b=D9wVbnER6FZzxvCulrSAiJ0EXyMQE8Szx8l48oZf+siAVKsb246phJveBjCFtGnCVV DWG8exp0ltd3bPnzJUbqTuqo+8Cq4QZupss+Ts+u1QJYVKVlWTkPdhEwIG04stZ3iU3h HCx8iCRWF7XUR5Q9NJvGdeRsxJhiqchTVcXi36fUhTU6XXJuao/NEEm0Vm1y1wdpcspD L4ZhpAsxoO3S/WkoHmwKLobaE2FvlOGvl8UzEEb+LSZHzf4nmEnAxg5vICWKrQbdMhod DTwxpZO5cdX00buukV9vgpRkLSIsuKZ8SNo0XXlpXgwNAbCy/kAb6Rt8PCvFrdAafvhk RdSA== X-Gm-Message-State: AOJu0YxRFC0QuMWQzRQekMFm8znD5uk5i6f73HWXk95frX5SwZ2oOW8+ h8R0ByT2XHbyqf7J2mcF7OZ5TMVy4kL9QBDsDtE8MLtu0MURvBq4bsmAV+oCsJJTJj4vdAByj/0 kmYvhKcPLD7BEZP+XG3U6HcQxP/rEGYDH3DQfnsjj9vfvg9BFaaclzxwpX8MM82Otz6APnOYmef J3Fin5+UVVUw== X-Gm-Gg: ASbGncsGEX4gRy/d1tCJ5pxQ6xdxRwioHZErGj6K5OMsGk/3rtSZTgGoGVPr3FEm38B CvQw/jL8XeSUc0uBeGbLy8HYEGEB4zSHWv/5Jgb3PyomEdxEQNt9cYqHEbTkeONr8M3Wf1SrOzm CKzswUMwjQ9zGpTk7JX2thqaGtIUDfaudq00Us88aSbqNX37RefSH8HBLhmy4WwCvuN4jMSlySO xOKMI5dcFIKDOyU7+XERppoDxIJ4qrNf9cB+92t5igjAn7tr8D2JbUckrmZet+uXM7lYOB+j2m5 IaKRw9VM8hJuVlODqoI4Y1s9us9D5w== X-Received: by 2002:a17:902:ebc1:b0:224:13a4:d61e with SMTP id d9443c01a7336-22bea4fea1emr25716015ad.51.1744356466631; Fri, 11 Apr 2025 00:27:46 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGDrk3ZlGmITdMjVwL6wO1Xw0kyfBU+iM5t4WrVGq2fReiO41Cjpr306iEkmQ494bfMFc4LLQ== X-Received: by 2002:a17:902:ebc1:b0:224:13a4:d61e with SMTP id d9443c01a7336-22bea4fea1emr25715725ad.51.1744356466186; Fri, 11 Apr 2025 00:27:46 -0700 (PDT) Received: from localhost.localdomain ([240f:74:7be:1:f99c:bbee:3855:787c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-22ac7cda517sm42421105ad.250.2025.04.11.00.27.45 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Apr 2025 00:27:45 -0700 (PDT) From: Koichiro Den To: kernel-team@lists.ubuntu.com Subject: [SRU][N][PATCH 02/14] bitmap: Define a cleanup function for bitmaps Date: Fri, 11 Apr 2025 16:26:38 +0900 Message-ID: <260ed3b9ee6d29d616773cac185b975d1582ecd7.1744350640.git.koichiro.den@canonical.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: <174435057828.183979.10447742120666677608@z790sl> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Bartosz Golaszewski BugLink: https://bugs.launchpad.net/bugs/2103496 Add support for autopointers for bitmaps allocated with bitmap_alloc() et al. Signed-off-by: Bartosz Golaszewski Signed-off-by: Thomas Gleixner Reviewed-by: Andy Shevchenko Acked-by: Yury Norov Link: https://lore.kernel.org/r/20240122124243.44002-2-brgl@bgdev.pl (cherry picked from commit d12a82848eac28d248e67940378fe4a72b0a8cd3) Signed-off-by: Koichiro Den --- include/linux/bitmap.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index 2a71bb3f2454..d7ffed3353f8 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -131,6 +132,8 @@ unsigned long *bitmap_alloc_node(unsigned int nbits, gfp_t flags, int node); unsigned long *bitmap_zalloc_node(unsigned int nbits, gfp_t flags, int node); void bitmap_free(const unsigned long *bitmap); +DEFINE_FREE(bitmap, unsigned long *, if (_T) bitmap_free(_T)) + /* Managed variants of the above. */ unsigned long *devm_bitmap_alloc(struct device *dev, unsigned int nbits, gfp_t flags); From patchwork Fri Apr 11 07:26:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Koichiro Den X-Patchwork-Id: 2071373 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4ZYpDb0sKqz1yJZ for ; Fri, 11 Apr 2025 17:27:43 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1u38nr-0003XE-AL; Fri, 11 Apr 2025 07:27:55 +0000 Received: from smtp-relay-internal-0.internal ([10.131.114.225] helo=smtp-relay-internal-0.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1u38nn-0003En-GS for kernel-team@lists.ubuntu.com; Fri, 11 Apr 2025 07:27:51 +0000 Received: from mail-pl1-f198.google.com (mail-pl1-f198.google.com [209.85.214.198]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-0.canonical.com (Postfix) with ESMTPS id 0A91D3F169 for ; Fri, 11 Apr 2025 07:27:50 +0000 (UTC) Received: by mail-pl1-f198.google.com with SMTP id d9443c01a7336-22650077995so23867325ad.3 for ; Fri, 11 Apr 2025 00:27:49 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744356467; x=1744961267; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=m5b2WrwstZXzBBtKnhaqZo7EjBKygUuwpAfg2ky8XNw=; b=rMGQgdpZlNTlgzq1Cr+OLeK01rwgn5N4Rj3Gs1eoynHm/bQqJC/l6Pz7QmhMMQ0CZw 0tBDDU7KORivjjGILoL4thy+/lZnQBEI8Wr9CiJHAwCqaDh9oNyY6297WrkV18n7WC0r nEYmA74C77zUXUK4A8mdwW5JevnwUp1/Y5I4JBugCY/5ylhPzXDEJ7T+Kcf9wOBeFSY+ 1FOMLtQjZH5hrsed5vhLV65rWz7yOebprhVpfbxieOGHNxiZCo43bjNphHupFNKQLSbE 0hLHi/Kq23Qa7R9AutMYkGJxLgkVy4QAeLMNKFdqeZOKtpI8cNpbopzKTgykYwPzudX/ QDUQ== X-Gm-Message-State: AOJu0YyAxCpC+4mtVphMVLlSSgDsHYtScoltH+jxCoFuonZQwXtdQjjQ fs08yAudYXTMy4y3ujyRG6ps4WidaqUBAlP+DInZn4kxrFL28Whm+j0LugCK1W4NCSLKCyl6C/m 5a1XGLzljMlE8QK0+4KJ3m0lh5nL1Zd1QDHRBd4491AKqHS9nvJIW2uZBlbamJ1LbYd9PUddGbT Sj0cn5c4/1Qw== X-Gm-Gg: ASbGncsgCN4I5fFFmmoOxN2kFF2RpDkQB/nXXgElRq8tllIzIwNVUbpzZ8iLOeuelvj h1H1wtizz1+UcMzgA8xrrztGZ1lTPDGScDpjwL8jiKReeUbdHtUUPbXWUrEe6/38Xo/9PJ+gMRr RRYtiW1uQg3ldVM+054VBogr8NQ1FnteNIzcm464gh3UIF5w3089Stt9ZxtKMcks7FFPVT2tM8x TqndTPatNnrJ6a5TRK8wcIzPImLYXE9jwDcYUtrXsCCbCv7bHhE+HloNlhKvQ5nm8GZmzvdxPw+ +5wqU7dAzbvIpUBuK1+CEaa2cbdwTw== X-Received: by 2002:a17:902:ebd1:b0:224:1074:63a0 with SMTP id d9443c01a7336-22bea4ef9a8mr27229045ad.34.1744356467753; Fri, 11 Apr 2025 00:27:47 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFrHxpVN34bpqLRX+k0S26PN9poB7yTFLBc7mv6e6Bd4c1NDAgPMCFPWPHYiixB2TDRBm3q4w== X-Received: by 2002:a17:902:ebd1:b0:224:1074:63a0 with SMTP id d9443c01a7336-22bea4ef9a8mr27228905ad.34.1744356467429; Fri, 11 Apr 2025 00:27:47 -0700 (PDT) Received: from localhost.localdomain ([240f:74:7be:1:f99c:bbee:3855:787c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-22ac7cda517sm42421105ad.250.2025.04.11.00.27.46 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Apr 2025 00:27:47 -0700 (PDT) From: Koichiro Den To: kernel-team@lists.ubuntu.com Subject: [SRU][N][PATCH 03/14] gpio: aggregator: simplify aggr_parse() with scoped bitmap Date: Fri, 11 Apr 2025 16:26:39 +0900 Message-ID: <8526457db467813636114f3bf910da1082113368.1744350640.git.koichiro.den@canonical.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: <174435057828.183979.10447742120666677608@z790sl> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Bartosz Golaszewski BugLink: https://bugs.launchpad.net/bugs/2103496 The bitmap allocated in aggr_parse() is always freed before the function returns so use __free(bitmap) to simplify it and drop the goto label. Reviewed-by: Linus Walleij Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20240930163207.80276-1-brgl@bgdev.pl Signed-off-by: Bartosz Golaszewski (cherry picked from commit 22dec5aa596ef805cccbcd3fbe5ebffbcb4fa559) Signed-off-by: Koichiro Den --- drivers/gpio/gpio-aggregator.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 38e0fff9afe7..65f41cc3eafc 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -65,11 +65,11 @@ static int aggr_parse(struct gpio_aggregator *aggr) { char *args = skip_spaces(aggr->args); char *name, *offsets, *p; - unsigned long *bitmap; unsigned int i, n = 0; int error = 0; - bitmap = bitmap_alloc(AGGREGATOR_MAX_GPIOS, GFP_KERNEL); + unsigned long *bitmap __free(bitmap) = + bitmap_alloc(AGGREGATOR_MAX_GPIOS, GFP_KERNEL); if (!bitmap) return -ENOMEM; @@ -82,7 +82,7 @@ static int aggr_parse(struct gpio_aggregator *aggr) /* Named GPIO line */ error = aggr_add_gpio(aggr, name, U16_MAX, &n); if (error) - goto free_bitmap; + return error; name = offsets; continue; @@ -92,13 +92,13 @@ static int aggr_parse(struct gpio_aggregator *aggr) error = bitmap_parselist(offsets, bitmap, AGGREGATOR_MAX_GPIOS); if (error) { pr_err("Cannot parse %s: %d\n", offsets, error); - goto free_bitmap; + return error; } for_each_set_bit(i, bitmap, AGGREGATOR_MAX_GPIOS) { error = aggr_add_gpio(aggr, name, i, &n); if (error) - goto free_bitmap; + return error; } args = next_arg(args, &name, &p); @@ -106,12 +106,10 @@ static int aggr_parse(struct gpio_aggregator *aggr) if (!n) { pr_err("No GPIOs specified\n"); - error = -EINVAL; + return -EINVAL; } -free_bitmap: - bitmap_free(bitmap); - return error; + return 0; } static ssize_t new_device_store(struct device_driver *driver, const char *buf, From patchwork Fri Apr 11 07:26:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Koichiro Den X-Patchwork-Id: 2071372 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4ZYpDZ6r3Lz1yHt for ; Fri, 11 Apr 2025 17:27:42 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1u38nq-0003TJ-Fn; Fri, 11 Apr 2025 07:27:54 +0000 Received: from smtp-relay-internal-1.internal ([10.131.114.114] helo=smtp-relay-internal-1.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1u38nn-0003EE-7g for kernel-team@lists.ubuntu.com; Fri, 11 Apr 2025 07:27:51 +0000 Received: from mail-pl1-f200.google.com (mail-pl1-f200.google.com [209.85.214.200]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-1.canonical.com (Postfix) with ESMTPS id 90AD7400AF for ; Fri, 11 Apr 2025 07:27:50 +0000 (UTC) Received: by mail-pl1-f200.google.com with SMTP id d9443c01a7336-225ab228a37so15230675ad.2 for ; Fri, 11 Apr 2025 00:27:50 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744356469; x=1744961269; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=512ty5KKynv5bozfQVKcLi1tWYbnfRanlAvdcNmnRTk=; b=XVaQdRmNH+Kscjy4VMY93g/BQDBDNnL0eGgQyfVEfEhAvfZhNpNZZU/VHGkeg0oIwG plseAsauZtQgPb1izAed4m4T0yMKBwsH4CswgZcGgH/q9t48vqKL/VJxSXSdkyf/6QZ4 /gViVnC1AIEhcUc4HmKyOYup8HaUKLabTnKtDMdwsm9C+ouQwV75/pFX/dgdAwum2ftZ ZH4pGva8FaauDNNt+AZDoYQDMRnslfPbLM48VtlEJhd8dxLchf/BXzvivuTQomwqSNz5 Im4iOD4AWYmkJjb5eJpc8Vfq8JwqKf3KmVagmvM1leK3035KtcDe5X+Yd4Txe5KS0wfz q6EA== X-Gm-Message-State: AOJu0Yy+tkt5xMgtQzGpnUA992A3XTvSPwSQ11WFQc73IMtaSAmGjInj 5aWR81rZCAoaouDgElIeUUGRTStRlky1AEKAmWIxQmH0yKa2GOXzqLBv3auIEOU/5q1/AzX+Odl 3KCPen6I6A7zP04S5nWL08PEpj34XKATNEpQgIZUfAIev/nrli4hKh5RuYFCsBnWFbi6ZePyIpp bUw6UQv7Wekg== X-Gm-Gg: ASbGncvIXhlQvOIjm1tCfGwOYUIBnqOK3uAm7rfNt6DpvNmmSRNrW2lOo389xSweAWe bHp589/hDIUh9msAUMAfkzufpE7Fvii6QhXSG9eYnd4plFkQAlRSPNGyZP89gTFLtgKrRz49WwP ye7QCJWnpQN6SWuvgoX9sAk5qvHMct1xUySHcaCmmkdbF6F5sG9aKSfxCZDoDhRdRo5ggeHpWW0 Fekjv9/SRD0kDjIu5F7Wr5GyPCLdTIIo5MAM5ElCLmtf8UOFrWWhn1Psvm6zqN2vOBg89seyX4s mWiCgU6pn3SILfTOCRaWSLfY5ckerA== X-Received: by 2002:a17:902:e552:b0:223:f408:c3cf with SMTP id d9443c01a7336-22bea4ade61mr23962815ad.21.1744356469020; Fri, 11 Apr 2025 00:27:49 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEVq2HQRe8N1Xmcdhg/JuJPYu5OZo5i2x1SlkwVFcuKaTmj6gNQGeyI9V3DTWl00+WuRRDLog== X-Received: by 2002:a17:902:e552:b0:223:f408:c3cf with SMTP id d9443c01a7336-22bea4ade61mr23962635ad.21.1744356468554; Fri, 11 Apr 2025 00:27:48 -0700 (PDT) Received: from localhost.localdomain ([240f:74:7be:1:f99c:bbee:3855:787c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-22ac7cda517sm42421105ad.250.2025.04.11.00.27.47 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Apr 2025 00:27:48 -0700 (PDT) From: Koichiro Den To: kernel-team@lists.ubuntu.com Subject: [SRU][N][PATCH 04/14] gpio: aggregator: protect driver attr handlers against module unload Date: Fri, 11 Apr 2025 16:26:40 +0900 Message-ID: <96be5e01086b042c3803bcde327abdee8651ce96.1744350640.git.koichiro.den@canonical.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: <174435057828.183979.10447742120666677608@z790sl> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" BugLink: https://bugs.launchpad.net/bugs/2103496 Both new_device_store and delete_device_store touch module global resources (e.g. gpio_aggregator_lock). To prevent race conditions with module unload, a reference needs to be held. Add try_module_get() in these handlers. For new_device_store, this eliminates what appears to be the most dangerous scenario: if an id is allocated from gpio_aggregator_idr but platform_device_register has not yet been called or completed, a concurrent module unload could fail to unregister/delete the device, leaving behind a dangling platform device/GPIO forwarder. This can result in various issues. The following simple reproducer demonstrates these problems: #!/bin/bash while :; do # note: whether 'gpiochip0 0' exists or not does not matter. echo 'gpiochip0 0' > /sys/bus/platform/drivers/gpio-aggregator/new_device done & while :; do modprobe gpio-aggregator modprobe -r gpio-aggregator done & wait Starting with the following warning, several kinds of warnings will appear and the system may become unstable: ------------[ cut here ]------------ list_del corruption, ffff888103e2e980->next is LIST_POISON1 (dead000000000100) WARNING: CPU: 1 PID: 1327 at lib/list_debug.c:56 __list_del_entry_valid_or_report+0xa3/0x120 [...] RIP: 0010:__list_del_entry_valid_or_report+0xa3/0x120 [...] Call Trace: ? __list_del_entry_valid_or_report+0xa3/0x120 ? __warn.cold+0x93/0xf2 ? __list_del_entry_valid_or_report+0xa3/0x120 ? report_bug+0xe6/0x170 ? __irq_work_queue_local+0x39/0xe0 ? handle_bug+0x58/0x90 ? exc_invalid_op+0x13/0x60 ? asm_exc_invalid_op+0x16/0x20 ? __list_del_entry_valid_or_report+0xa3/0x120 gpiod_remove_lookup_table+0x22/0x60 new_device_store+0x315/0x350 [gpio_aggregator] kernfs_fop_write_iter+0x137/0x1f0 vfs_write+0x262/0x430 ksys_write+0x60/0xd0 do_syscall_64+0x6c/0x180 entry_SYSCALL_64_after_hwframe+0x76/0x7e [...] ---[ end trace 0000000000000000 ]--- Fixes: 828546e24280 ("gpio: Add GPIO Aggregator") Cc: stable@vger.kernel.org Signed-off-by: Koichiro Den Link: https://lore.kernel.org/r/20250224143134.3024598-2-koichiro.den@canonical.com Signed-off-by: Bartosz Golaszewski (cherry picked from commit 12f65d1203507f7db3ba59930fe29a3b8eee9945) Signed-off-by: Koichiro Den --- drivers/gpio/gpio-aggregator.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 65f41cc3eafc..d668ddb2e81d 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -119,10 +119,15 @@ static ssize_t new_device_store(struct device_driver *driver, const char *buf, struct platform_device *pdev; int res, id; + if (!try_module_get(THIS_MODULE)) + return -ENOENT; + /* kernfs guarantees string termination, so count + 1 is safe */ aggr = kzalloc(sizeof(*aggr) + count + 1, GFP_KERNEL); - if (!aggr) - return -ENOMEM; + if (!aggr) { + res = -ENOMEM; + goto put_module; + } memcpy(aggr->args, buf, count + 1); @@ -161,6 +166,7 @@ static ssize_t new_device_store(struct device_driver *driver, const char *buf, } aggr->pdev = pdev; + module_put(THIS_MODULE); return count; remove_table: @@ -175,6 +181,8 @@ static ssize_t new_device_store(struct device_driver *driver, const char *buf, kfree(aggr->lookups); free_ga: kfree(aggr); +put_module: + module_put(THIS_MODULE); return res; } @@ -203,13 +211,19 @@ static ssize_t delete_device_store(struct device_driver *driver, if (error) return error; + if (!try_module_get(THIS_MODULE)) + return -ENOENT; + mutex_lock(&gpio_aggregator_lock); aggr = idr_remove(&gpio_aggregator_idr, id); mutex_unlock(&gpio_aggregator_lock); - if (!aggr) + if (!aggr) { + module_put(THIS_MODULE); return -ENOENT; + } gpio_aggregator_free(aggr); + module_put(THIS_MODULE); return count; } static DRIVER_ATTR_WO(delete_device); From patchwork Fri Apr 11 07:26:41 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Koichiro Den X-Patchwork-Id: 2071374 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4ZYpDc4xjZz1yHt for ; Fri, 11 Apr 2025 17:27:44 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1u38nr-0003ZY-So; Fri, 11 Apr 2025 07:27:55 +0000 Received: from smtp-relay-internal-1.internal ([10.131.114.114] helo=smtp-relay-internal-1.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1u38no-0003Kr-Bu for kernel-team@lists.ubuntu.com; Fri, 11 Apr 2025 07:27:52 +0000 Received: from mail-pl1-f197.google.com (mail-pl1-f197.google.com [209.85.214.197]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-1.canonical.com (Postfix) with ESMTPS id F26F9400AF for ; Fri, 11 Apr 2025 07:27:51 +0000 (UTC) Received: by mail-pl1-f197.google.com with SMTP id d9443c01a7336-225429696a9so22305185ad.1 for ; Fri, 11 Apr 2025 00:27:51 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744356470; x=1744961270; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=CNbq/NpJ4KheRhANvZjV/MLV/ZCYE0gS1Y/uJVreU70=; b=NiCXg3Eztyych7Jbcc5hrp3b7MLrsEfv1UDTX4ec2Y/jvPxWg8fsAbWk5I7fake8X2 uvNmyTMvwxqLunUaaqTwEauLvCR0l+CGKZOc1cE/nx+nQp2ZQ87AlW0tnuqW1aU43gW0 o0CMxPcvt2HRSC2dPC/3aC2ZhXhOQJpobpBnFre5hSQ2WN+WuIlVhjfDKIhJIFRdlK6w TEq7y2CIJ3GX6l7eqqMnTodGgi9zy1WAGfsKLcFI+zHYWrVCQANrZRDjO9oyvKSjyENP 30QQPD9XVK4wGJHSUD1bvIRTuI/Kdgpco6mpqJTM16fQ4IUNxEm9w65Hf55XVZa8chzR 31HA== X-Gm-Message-State: AOJu0YzqHcKZb9cBn2BF7epPhDRf7kkVDoDvGILWjDeGOhSKBrdxILQW GPX7jZbiLx5bToMF+61qPhtJKKLbjFHg45P6ja/qJx6CV0sviYQAMRVIValGzylGNRks0AySipO mlrcNGltiPp4NdYn5ZKFlIz88U3I6OPGOR+MAIzdTGta4Pn5A8VUnBJrEq4bVVL1JHYZWJjoDYd unXsdJ0IB1Ng== X-Gm-Gg: ASbGncuoJDSxaY2z21vSV97l/sduAxLc5HwW7hXTUt8uTF6GOIpgaM8Z0vq6TuHSoLn 4h2rFTx1LR3YL7cPDPwasbPz1tJKqTKrwqbq0BT8W414l3KQ6XtfaCakI4yxN2X50h2l+k8mwaK wuEvYWBr/XDlxyt+PbOYij3aAtnw5/YVRDnLbM472v+orR9mDM2qLWgE91yemhFpTYGaUt3Vkao OLjUAuREgKR95s4Scay0PKZ6pZ2zrcTDlvQ00zJN+o2XWZpe4FjfIHDWLtaa2kPslxGYiChTTe4 ROY+fSmNkb8xK48Zo1mxs2KVHstWug== X-Received: by 2002:a17:902:dac1:b0:224:255b:c92e with SMTP id d9443c01a7336-22bea4a1e96mr27253795ad.3.1744356470135; Fri, 11 Apr 2025 00:27:50 -0700 (PDT) X-Google-Smtp-Source: AGHT+IH1HrBdL3vPNk59Qc+vGmIIa8GhCw5aikeuemL2L3vp+9ZHZiSm+48RvdBOsrzX+ZV2Kumqpg== X-Received: by 2002:a17:902:dac1:b0:224:255b:c92e with SMTP id d9443c01a7336-22bea4a1e96mr27253585ad.3.1744356469727; Fri, 11 Apr 2025 00:27:49 -0700 (PDT) Received: from localhost.localdomain ([240f:74:7be:1:f99c:bbee:3855:787c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-22ac7cda517sm42421105ad.250.2025.04.11.00.27.48 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Apr 2025 00:27:49 -0700 (PDT) From: Koichiro Den To: kernel-team@lists.ubuntu.com Subject: [SRU][N][PATCH 05/14] gpio: aggregator: reorder functions to prepare for configfs introduction Date: Fri, 11 Apr 2025 16:26:41 +0900 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: <174435057828.183979.10447742120666677608@z790sl> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" BugLink: https://bugs.launchpad.net/bugs/2103496 Reorder functions in drivers/gpio/gpio-aggregator.c to prepare for the configfs-based interface additions in subsequent commits. Arrange the code so that the configfs implementations will appear above the existing sysfs-specific code, since the latter will partly depend on the configfs interface implementations when it starts to expose the settings to configfs. The order in drivers/gpio/gpio-aggregator.c will be as follows: * Basic gpio_aggregator/gpio_aggregator_line representations * Common utility functions * GPIO Forwarder implementations * Configfs interface implementations * Sysfs interface implementations * Platform device implementations * Module init/exit implementations This separate commit ensures a clean diff for the subsequent commits. No functional change. Reviewed-by: Geert Uytterhoeven Signed-off-by: Koichiro Den Link: https://lore.kernel.org/r/20250407043019.4105613-2-koichiro.den@canonical.com Signed-off-by: Bartosz Golaszewski (cherry picked from commit 7a56efeabffd13a162073068b8e29113c65f9e64 linux-next) Signed-off-by: Koichiro Den --- drivers/gpio/gpio-aggregator.c | 380 +++++++++++++++++---------------- 1 file changed, 192 insertions(+), 188 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index d668ddb2e81d..893cd56de867 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -61,194 +61,6 @@ static int aggr_add_gpio(struct gpio_aggregator *aggr, const char *key, return 0; } -static int aggr_parse(struct gpio_aggregator *aggr) -{ - char *args = skip_spaces(aggr->args); - char *name, *offsets, *p; - unsigned int i, n = 0; - int error = 0; - - unsigned long *bitmap __free(bitmap) = - bitmap_alloc(AGGREGATOR_MAX_GPIOS, GFP_KERNEL); - if (!bitmap) - return -ENOMEM; - - args = next_arg(args, &name, &p); - while (*args) { - args = next_arg(args, &offsets, &p); - - p = get_options(offsets, 0, &error); - if (error == 0 || *p) { - /* Named GPIO line */ - error = aggr_add_gpio(aggr, name, U16_MAX, &n); - if (error) - return error; - - name = offsets; - continue; - } - - /* GPIO chip + offset(s) */ - error = bitmap_parselist(offsets, bitmap, AGGREGATOR_MAX_GPIOS); - if (error) { - pr_err("Cannot parse %s: %d\n", offsets, error); - return error; - } - - for_each_set_bit(i, bitmap, AGGREGATOR_MAX_GPIOS) { - error = aggr_add_gpio(aggr, name, i, &n); - if (error) - return error; - } - - args = next_arg(args, &name, &p); - } - - if (!n) { - pr_err("No GPIOs specified\n"); - return -EINVAL; - } - - return 0; -} - -static ssize_t new_device_store(struct device_driver *driver, const char *buf, - size_t count) -{ - struct gpio_aggregator *aggr; - struct platform_device *pdev; - int res, id; - - if (!try_module_get(THIS_MODULE)) - return -ENOENT; - - /* kernfs guarantees string termination, so count + 1 is safe */ - aggr = kzalloc(sizeof(*aggr) + count + 1, GFP_KERNEL); - if (!aggr) { - res = -ENOMEM; - goto put_module; - } - - memcpy(aggr->args, buf, count + 1); - - aggr->lookups = kzalloc(struct_size(aggr->lookups, table, 1), - GFP_KERNEL); - if (!aggr->lookups) { - res = -ENOMEM; - goto free_ga; - } - - mutex_lock(&gpio_aggregator_lock); - id = idr_alloc(&gpio_aggregator_idr, aggr, 0, 0, GFP_KERNEL); - mutex_unlock(&gpio_aggregator_lock); - - if (id < 0) { - res = id; - goto free_table; - } - - aggr->lookups->dev_id = kasprintf(GFP_KERNEL, "%s.%d", DRV_NAME, id); - if (!aggr->lookups->dev_id) { - res = -ENOMEM; - goto remove_idr; - } - - res = aggr_parse(aggr); - if (res) - goto free_dev_id; - - gpiod_add_lookup_table(aggr->lookups); - - pdev = platform_device_register_simple(DRV_NAME, id, NULL, 0); - if (IS_ERR(pdev)) { - res = PTR_ERR(pdev); - goto remove_table; - } - - aggr->pdev = pdev; - module_put(THIS_MODULE); - return count; - -remove_table: - gpiod_remove_lookup_table(aggr->lookups); -free_dev_id: - kfree(aggr->lookups->dev_id); -remove_idr: - mutex_lock(&gpio_aggregator_lock); - idr_remove(&gpio_aggregator_idr, id); - mutex_unlock(&gpio_aggregator_lock); -free_table: - kfree(aggr->lookups); -free_ga: - kfree(aggr); -put_module: - module_put(THIS_MODULE); - return res; -} - -static DRIVER_ATTR_WO(new_device); - -static void gpio_aggregator_free(struct gpio_aggregator *aggr) -{ - platform_device_unregister(aggr->pdev); - gpiod_remove_lookup_table(aggr->lookups); - kfree(aggr->lookups->dev_id); - kfree(aggr->lookups); - kfree(aggr); -} - -static ssize_t delete_device_store(struct device_driver *driver, - const char *buf, size_t count) -{ - struct gpio_aggregator *aggr; - unsigned int id; - int error; - - if (!str_has_prefix(buf, DRV_NAME ".")) - return -EINVAL; - - error = kstrtouint(buf + strlen(DRV_NAME "."), 10, &id); - if (error) - return error; - - if (!try_module_get(THIS_MODULE)) - return -ENOENT; - - mutex_lock(&gpio_aggregator_lock); - aggr = idr_remove(&gpio_aggregator_idr, id); - mutex_unlock(&gpio_aggregator_lock); - if (!aggr) { - module_put(THIS_MODULE); - return -ENOENT; - } - - gpio_aggregator_free(aggr); - module_put(THIS_MODULE); - return count; -} -static DRIVER_ATTR_WO(delete_device); - -static struct attribute *gpio_aggregator_attrs[] = { - &driver_attr_new_device.attr, - &driver_attr_delete_device.attr, - NULL -}; -ATTRIBUTE_GROUPS(gpio_aggregator); - -static int __exit gpio_aggregator_idr_remove(int id, void *p, void *data) -{ - gpio_aggregator_free(p); - return 0; -} - -static void __exit gpio_aggregator_remove_all(void) -{ - mutex_lock(&gpio_aggregator_lock); - idr_for_each(&gpio_aggregator_idr, gpio_aggregator_idr_remove, NULL); - idr_destroy(&gpio_aggregator_idr); - mutex_unlock(&gpio_aggregator_lock); -} - /* * GPIO Forwarder @@ -573,6 +385,184 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev, } +/* + * Sysfs interface + */ +static int aggr_parse(struct gpio_aggregator *aggr) +{ + char *args = skip_spaces(aggr->args); + char *name, *offsets, *p; + unsigned int i, n = 0; + int error = 0; + + unsigned long *bitmap __free(bitmap) = + bitmap_alloc(AGGREGATOR_MAX_GPIOS, GFP_KERNEL); + if (!bitmap) + return -ENOMEM; + + args = next_arg(args, &name, &p); + while (*args) { + args = next_arg(args, &offsets, &p); + + p = get_options(offsets, 0, &error); + if (error == 0 || *p) { + /* Named GPIO line */ + error = aggr_add_gpio(aggr, name, U16_MAX, &n); + if (error) + return error; + + name = offsets; + continue; + } + + /* GPIO chip + offset(s) */ + error = bitmap_parselist(offsets, bitmap, AGGREGATOR_MAX_GPIOS); + if (error) { + pr_err("Cannot parse %s: %d\n", offsets, error); + return error; + } + + for_each_set_bit(i, bitmap, AGGREGATOR_MAX_GPIOS) { + error = aggr_add_gpio(aggr, name, i, &n); + if (error) + return error; + } + + args = next_arg(args, &name, &p); + } + + if (!n) { + pr_err("No GPIOs specified\n"); + return -EINVAL; + } + + return 0; +} + +static ssize_t new_device_store(struct device_driver *driver, const char *buf, + size_t count) +{ + struct gpio_aggregator *aggr; + struct platform_device *pdev; + int res, id; + + if (!try_module_get(THIS_MODULE)) + return -ENOENT; + + /* kernfs guarantees string termination, so count + 1 is safe */ + aggr = kzalloc(sizeof(*aggr) + count + 1, GFP_KERNEL); + if (!aggr) { + res = -ENOMEM; + goto put_module; + } + + memcpy(aggr->args, buf, count + 1); + + aggr->lookups = kzalloc(struct_size(aggr->lookups, table, 1), + GFP_KERNEL); + if (!aggr->lookups) { + res = -ENOMEM; + goto free_ga; + } + + mutex_lock(&gpio_aggregator_lock); + id = idr_alloc(&gpio_aggregator_idr, aggr, 0, 0, GFP_KERNEL); + mutex_unlock(&gpio_aggregator_lock); + + if (id < 0) { + res = id; + goto free_table; + } + + aggr->lookups->dev_id = kasprintf(GFP_KERNEL, "%s.%d", DRV_NAME, id); + if (!aggr->lookups->dev_id) { + res = -ENOMEM; + goto remove_idr; + } + + res = aggr_parse(aggr); + if (res) + goto free_dev_id; + + gpiod_add_lookup_table(aggr->lookups); + + pdev = platform_device_register_simple(DRV_NAME, id, NULL, 0); + if (IS_ERR(pdev)) { + res = PTR_ERR(pdev); + goto remove_table; + } + + aggr->pdev = pdev; + module_put(THIS_MODULE); + return count; + +remove_table: + gpiod_remove_lookup_table(aggr->lookups); +free_dev_id: + kfree(aggr->lookups->dev_id); +remove_idr: + mutex_lock(&gpio_aggregator_lock); + idr_remove(&gpio_aggregator_idr, id); + mutex_unlock(&gpio_aggregator_lock); +free_table: + kfree(aggr->lookups); +free_ga: + kfree(aggr); +put_module: + module_put(THIS_MODULE); + return res; +} + +static DRIVER_ATTR_WO(new_device); + +static void gpio_aggregator_free(struct gpio_aggregator *aggr) +{ + platform_device_unregister(aggr->pdev); + gpiod_remove_lookup_table(aggr->lookups); + kfree(aggr->lookups->dev_id); + kfree(aggr->lookups); + kfree(aggr); +} + +static ssize_t delete_device_store(struct device_driver *driver, + const char *buf, size_t count) +{ + struct gpio_aggregator *aggr; + unsigned int id; + int error; + + if (!str_has_prefix(buf, DRV_NAME ".")) + return -EINVAL; + + error = kstrtouint(buf + strlen(DRV_NAME "."), 10, &id); + if (error) + return error; + + if (!try_module_get(THIS_MODULE)) + return -ENOENT; + + mutex_lock(&gpio_aggregator_lock); + aggr = idr_remove(&gpio_aggregator_idr, id); + mutex_unlock(&gpio_aggregator_lock); + if (!aggr) { + module_put(THIS_MODULE); + return -ENOENT; + } + + gpio_aggregator_free(aggr); + module_put(THIS_MODULE); + return count; +} +static DRIVER_ATTR_WO(delete_device); + +static struct attribute *gpio_aggregator_attrs[] = { + &driver_attr_new_device.attr, + &driver_attr_delete_device.attr, + NULL +}; +ATTRIBUTE_GROUPS(gpio_aggregator); + + /* * GPIO Aggregator platform device */ @@ -630,6 +620,20 @@ static struct platform_driver gpio_aggregator_driver = { }, }; +static int __exit gpio_aggregator_idr_remove(int id, void *p, void *data) +{ + gpio_aggregator_free(p); + return 0; +} + +static void __exit gpio_aggregator_remove_all(void) +{ + mutex_lock(&gpio_aggregator_lock); + idr_for_each(&gpio_aggregator_idr, gpio_aggregator_idr_remove, NULL); + idr_destroy(&gpio_aggregator_idr); + mutex_unlock(&gpio_aggregator_lock); +} + static int __init gpio_aggregator_init(void) { return platform_driver_register(&gpio_aggregator_driver); From patchwork Fri Apr 11 07:26:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Koichiro Den X-Patchwork-Id: 2071375 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4ZYpDf0rszz1yHt for ; Fri, 11 Apr 2025 17:27:46 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1u38ns-0003d0-GP; Fri, 11 Apr 2025 07:27:56 +0000 Received: from smtp-relay-internal-1.internal ([10.131.114.114] helo=smtp-relay-internal-1.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1u38np-0003Oz-QP for kernel-team@lists.ubuntu.com; Fri, 11 Apr 2025 07:27:53 +0000 Received: from mail-pg1-f197.google.com (mail-pg1-f197.google.com [209.85.215.197]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-1.canonical.com (Postfix) with ESMTPS id 3A7D2402F1 for ; Fri, 11 Apr 2025 07:27:53 +0000 (UTC) Received: by mail-pg1-f197.google.com with SMTP id 41be03b00d2f7-af91ea9e885so1629353a12.3 for ; Fri, 11 Apr 2025 00:27:53 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744356471; x=1744961271; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tV2PFa98tVyrVVP+npSmDplUBtTKAnGTyIxrNUDrPw0=; b=IuNkmosgutHZ88wqTLhzuO5hLpEZ2Wu4KGI5yRDK0UBUOSOBgeyyRJdDm9p1gLth9v CaU1UdAFP45nK6rWuZzRsDZmlU/vcOwwkv+5THwCvPh0+u9Or5kYj/lSswINf2aKOh1w lfTsV0eD/0nL3uHcbeB3lxk2Pbt0CdEfEtWdwAnzHZ5LGQbHDYITChHE5voZ9iz7u3tU kR6v5F5VMSbsPZVgJSLv6HlTbd1cevU8LL1ma+e3ENSv0e7IGfaBysUSghb81BG9mReV RIn1xBlbsANTszuwi8gOcp0Yfzilj4tEuOxv5s3vid7FhPDltinFNTRiTpu4FQtqu4Ub 24Kg== X-Gm-Message-State: AOJu0Yy6MG3JiuTUB3ryTdS6WHv18ec8PxM9NO+ET8QIO9QhEeUToxmV jAy1WtFBHlS7AwK+z1XRQoVfEiIQIAK5mpYVj+nOs/i+Om/yA0qROe5sbl3htwYVxFKpmKSYxQz eWlKbFI1tMB/YlVYgVOz5lcqN62Anczx1MIJa8mDvbVliPCqfxEu5P4hK9oiNc7elBkASBgy9+7 iIqhczw/AKIw== X-Gm-Gg: ASbGncsRENBn2UfOJnbyap0Iio6Q77FwnD939PGBVlBULMSVSXHXo7TqVfX2ja2FrGr clhZwE1eUXz0QZ4AWdEeocmkJA9iRLEG68tNT/Olx0ODysi5ATAUCDC9pi1IIny4UfFr8ed4wUz 1ClGfFEkTe+EKJnmCjG0wBFUvHLwdSaWrwyNV3zH/jG51RpC3VBW42uhPHOjlYBK8XzS091IC/e RLomqwDnn9fhgwihuHsV48/BjMiKghOIl+Heebd3zw76mh/vfBIFqPcKPDcssNd09x6Cm1Wv1SU cl71GIVlpgwTkR+dly74zlt3XPqZDA== X-Received: by 2002:a17:902:ce84:b0:224:179a:3b8f with SMTP id d9443c01a7336-22bea4bd079mr23352035ad.23.1744356471329; Fri, 11 Apr 2025 00:27:51 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFWfPmwBd1R1gU3q/t54mihj9MrGcZgGHpUWumT7AsHFCxEpLg21vZ/vmyck+uA8axOh579kA== X-Received: by 2002:a17:902:ce84:b0:224:179a:3b8f with SMTP id d9443c01a7336-22bea4bd079mr23351865ad.23.1744356471006; Fri, 11 Apr 2025 00:27:51 -0700 (PDT) Received: from localhost.localdomain ([240f:74:7be:1:f99c:bbee:3855:787c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-22ac7cda517sm42421105ad.250.2025.04.11.00.27.50 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Apr 2025 00:27:50 -0700 (PDT) From: Koichiro Den To: kernel-team@lists.ubuntu.com Subject: [SRU][N][PATCH 06/14] gpio: aggregator: unify function naming Date: Fri, 11 Apr 2025 16:26:42 +0900 Message-ID: <7c61e44c13ce9ab5920c0e3e574a346b13ba3e24.1744350640.git.koichiro.den@canonical.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: <174435057828.183979.10447742120666677608@z790sl> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" BugLink: https://bugs.launchpad.net/bugs/2103496 Unify function names to use gpio_aggregator_ prefix (except GPIO forwarder implementations, which remain unchanged in subsequent commits). While at it, rename the pre-existing gpio_aggregator_free() to gpio_aggregator_destory(), since that name will be used by new alloc/free functions introduced in the next commit, for which the name is more appropriate. No functional change. Signed-off-by: Koichiro Den Link: https://lore.kernel.org/r/20250407043019.4105613-3-koichiro.den@canonical.com Signed-off-by: Bartosz Golaszewski (cherry picked from commit 7616dd97ae22e5f69b24774455673d183d4191c9 linux-next) Signed-off-by: Koichiro Den --- drivers/gpio/gpio-aggregator.c | 37 ++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 893cd56de867..92cb18830d42 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -42,8 +42,8 @@ struct gpio_aggregator { static DEFINE_MUTEX(gpio_aggregator_lock); /* protects idr */ static DEFINE_IDR(gpio_aggregator_idr); -static int aggr_add_gpio(struct gpio_aggregator *aggr, const char *key, - int hwnum, unsigned int *n) +static int gpio_aggregator_add_gpio(struct gpio_aggregator *aggr, + const char *key, int hwnum, unsigned int *n) { struct gpiod_lookup_table *lookups; @@ -388,7 +388,7 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev, /* * Sysfs interface */ -static int aggr_parse(struct gpio_aggregator *aggr) +static int gpio_aggregator_parse(struct gpio_aggregator *aggr) { char *args = skip_spaces(aggr->args); char *name, *offsets, *p; @@ -407,7 +407,7 @@ static int aggr_parse(struct gpio_aggregator *aggr) p = get_options(offsets, 0, &error); if (error == 0 || *p) { /* Named GPIO line */ - error = aggr_add_gpio(aggr, name, U16_MAX, &n); + error = gpio_aggregator_add_gpio(aggr, name, U16_MAX, &n); if (error) return error; @@ -423,7 +423,7 @@ static int aggr_parse(struct gpio_aggregator *aggr) } for_each_set_bit(i, bitmap, AGGREGATOR_MAX_GPIOS) { - error = aggr_add_gpio(aggr, name, i, &n); + error = gpio_aggregator_add_gpio(aggr, name, i, &n); if (error) return error; } @@ -439,8 +439,8 @@ static int aggr_parse(struct gpio_aggregator *aggr) return 0; } -static ssize_t new_device_store(struct device_driver *driver, const char *buf, - size_t count) +static ssize_t gpio_aggregator_new_device_store(struct device_driver *driver, + const char *buf, size_t count) { struct gpio_aggregator *aggr; struct platform_device *pdev; @@ -480,7 +480,7 @@ static ssize_t new_device_store(struct device_driver *driver, const char *buf, goto remove_idr; } - res = aggr_parse(aggr); + res = gpio_aggregator_parse(aggr); if (res) goto free_dev_id; @@ -513,9 +513,10 @@ static ssize_t new_device_store(struct device_driver *driver, const char *buf, return res; } -static DRIVER_ATTR_WO(new_device); +static struct driver_attribute driver_attr_gpio_aggregator_new_device = + __ATTR(new_device, 0200, NULL, gpio_aggregator_new_device_store); -static void gpio_aggregator_free(struct gpio_aggregator *aggr) +static void gpio_aggregator_destroy(struct gpio_aggregator *aggr) { platform_device_unregister(aggr->pdev); gpiod_remove_lookup_table(aggr->lookups); @@ -524,8 +525,8 @@ static void gpio_aggregator_free(struct gpio_aggregator *aggr) kfree(aggr); } -static ssize_t delete_device_store(struct device_driver *driver, - const char *buf, size_t count) +static ssize_t gpio_aggregator_delete_device_store(struct device_driver *driver, + const char *buf, size_t count) { struct gpio_aggregator *aggr; unsigned int id; @@ -549,15 +550,17 @@ static ssize_t delete_device_store(struct device_driver *driver, return -ENOENT; } - gpio_aggregator_free(aggr); + gpio_aggregator_destroy(aggr); module_put(THIS_MODULE); return count; } -static DRIVER_ATTR_WO(delete_device); + +static struct driver_attribute driver_attr_gpio_aggregator_delete_device = + __ATTR(delete_device, 0200, NULL, gpio_aggregator_delete_device_store); static struct attribute *gpio_aggregator_attrs[] = { - &driver_attr_new_device.attr, - &driver_attr_delete_device.attr, + &driver_attr_gpio_aggregator_new_device.attr, + &driver_attr_gpio_aggregator_delete_device.attr, NULL }; ATTRIBUTE_GROUPS(gpio_aggregator); @@ -622,7 +625,7 @@ static struct platform_driver gpio_aggregator_driver = { static int __exit gpio_aggregator_idr_remove(int id, void *p, void *data) { - gpio_aggregator_free(p); + gpio_aggregator_destroy(p); return 0; } From patchwork Fri Apr 11 07:26:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Koichiro Den X-Patchwork-Id: 2071376 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4ZYpDh4sWsz1yHt for ; Fri, 11 Apr 2025 17:27:48 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1u38nv-0003pF-6V; Fri, 11 Apr 2025 07:27:59 +0000 Received: from smtp-relay-internal-1.internal ([10.131.114.114] helo=smtp-relay-internal-1.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1u38ns-0003Ua-PQ for kernel-team@lists.ubuntu.com; Fri, 11 Apr 2025 07:27:56 +0000 Received: from mail-pl1-f200.google.com (mail-pl1-f200.google.com [209.85.214.200]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-1.canonical.com (Postfix) with ESMTPS id 59494400AF for ; Fri, 11 Apr 2025 07:27:54 +0000 (UTC) Received: by mail-pl1-f200.google.com with SMTP id d9443c01a7336-229170fbe74so14214955ad.2 for ; Fri, 11 Apr 2025 00:27:54 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744356472; x=1744961272; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=EjT+z9DhbLon52nrw+r9YMwREsiKYQZHkZRglAKRCQI=; b=FH6zmc9CgWJDSroxKDw3v2UOFt2eavvGrLqsVxhxTUiDtwiBs8urTT3wFpvy0HZ2s5 7dsrh814/XMELveQRxVqTOq+c/J8/5/Lq8Hyx9flxwRLUlxVHuo+iGsYZrnR8PyAOSQr stm0NaGfE+g1JPBUfeVwhaGiXs3wJTUs+jZ00wnvomtjqBq817kq9A8CMAsdQfXpAp3X 6BBDy+z9nGyQx4gszOgNjnfOzbfNlVmjmlmSUBlBiP5KHUJFdSrtKWKiNDCKPwLrbsUc KTd+ouYY0IztT54oMD4WQaLML51p4laabaL6GMsRJBtraYuo7DsA2X8F++ZsjQCAFxu4 r5Vg== X-Gm-Message-State: AOJu0YzfKEkAM9UknNL1IMSlNfE2QwPa81bD1QrgWZL3mBre5KmvNjpL jUmty1WUzYooX4bumVe2W/ISwv92SptS0LFVPIMW3h0qSCzy7fcBDTWXxY8hQ3utd1/fxele3/i 87a6RSO5QqxKVLVtQsuWITQWxTdP7EtuuJYtAQTVCXIbRMpkbsJ8xoMVoBX89o3Id7eVElr3dBX JOyrGqJrRBdg== X-Gm-Gg: ASbGnctKf5odjfRwsY/kyEqTVY1BdznFo0KFmcahBxFRky2BNwnoQUX/mso0tn1Pm8K XkyD++xCtKYvs0Wq8j0dxNGKcMnmQSITyR5OzMO/AMScUhYZirVNVQ7Ip1E4rPH5fCSYjEYtNvG w6qeCtdTUMO1tW9y7MZ16sqYl/8CudpZcqo0lxS77cm3e3X+LuSWyx9yhl+hMwLSg+IgkzEdKnX x5a3R4pORWjTLl7JoFWBtDXRc1+e5VShOZY21ZAN36C9WZ/r+o4SzBTuvo1+aM/Gr4spTqucyI7 OeiLy58qf/VrQALVH/aFbETSTTB90w== X-Received: by 2002:a17:903:947:b0:223:5a6e:b20 with SMTP id d9443c01a7336-22bea4a336amr23186615ad.7.1744356472646; Fri, 11 Apr 2025 00:27:52 -0700 (PDT) X-Google-Smtp-Source: AGHT+IG3dAZwp/Tme/1OeYqYAk+CPkfa7FIVRdic6dJGASn587cZCfYBtC9bs9h4z7GicLnC7BiJtw== X-Received: by 2002:a17:903:947:b0:223:5a6e:b20 with SMTP id d9443c01a7336-22bea4a336amr23186425ad.7.1744356472284; Fri, 11 Apr 2025 00:27:52 -0700 (PDT) Received: from localhost.localdomain ([240f:74:7be:1:f99c:bbee:3855:787c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-22ac7cda517sm42421105ad.250.2025.04.11.00.27.51 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Apr 2025 00:27:51 -0700 (PDT) From: Koichiro Den To: kernel-team@lists.ubuntu.com Subject: [SRU][N][PATCH 07/14] gpio: aggregator: add gpio_aggregator_{alloc, free}() Date: Fri, 11 Apr 2025 16:26:43 +0900 Message-ID: <822e9ce07c8c3faccc76652e4804c8a37464bbdd.1744350640.git.koichiro.den@canonical.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: <174435057828.183979.10447742120666677608@z790sl> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" BugLink: https://bugs.launchpad.net/bugs/2103496 Prepare for the upcoming configfs interface. These functions will be used by both the existing sysfs interface and the new configfs interface, reducing code duplication. No functional change. Signed-off-by: Koichiro Den Link: https://lore.kernel.org/r/20250407043019.4105613-4-koichiro.den@canonical.com Signed-off-by: Bartosz Golaszewski (cherry picked from commit 88fe1d1a646b3b01dcc335c44e7b33ea510f620e linux-next) Signed-off-by: Koichiro Den --- drivers/gpio/gpio-aggregator.c | 58 +++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 92cb18830d42..f34581a76b06 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -36,12 +36,41 @@ struct gpio_aggregator { struct gpiod_lookup_table *lookups; struct platform_device *pdev; + int id; char args[]; }; static DEFINE_MUTEX(gpio_aggregator_lock); /* protects idr */ static DEFINE_IDR(gpio_aggregator_idr); +static int gpio_aggregator_alloc(struct gpio_aggregator **aggr, size_t arg_size) +{ + int ret; + + struct gpio_aggregator *new __free(kfree) = kzalloc( + sizeof(*new) + arg_size, GFP_KERNEL); + if (!new) + return -ENOMEM; + + scoped_guard(mutex, &gpio_aggregator_lock) + ret = idr_alloc(&gpio_aggregator_idr, new, 0, 0, GFP_KERNEL); + + if (ret < 0) + return ret; + + new->id = ret; + *aggr = no_free_ptr(new); + return 0; +} + +static void gpio_aggregator_free(struct gpio_aggregator *aggr) +{ + scoped_guard(mutex, &gpio_aggregator_lock) + idr_remove(&gpio_aggregator_idr, aggr->id); + + kfree(aggr); +} + static int gpio_aggregator_add_gpio(struct gpio_aggregator *aggr, const char *key, int hwnum, unsigned int *n) { @@ -444,17 +473,15 @@ static ssize_t gpio_aggregator_new_device_store(struct device_driver *driver, { struct gpio_aggregator *aggr; struct platform_device *pdev; - int res, id; + int res; if (!try_module_get(THIS_MODULE)) return -ENOENT; /* kernfs guarantees string termination, so count + 1 is safe */ - aggr = kzalloc(sizeof(*aggr) + count + 1, GFP_KERNEL); - if (!aggr) { - res = -ENOMEM; + res = gpio_aggregator_alloc(&aggr, count + 1); + if (res) goto put_module; - } memcpy(aggr->args, buf, count + 1); @@ -465,19 +492,10 @@ static ssize_t gpio_aggregator_new_device_store(struct device_driver *driver, goto free_ga; } - mutex_lock(&gpio_aggregator_lock); - id = idr_alloc(&gpio_aggregator_idr, aggr, 0, 0, GFP_KERNEL); - mutex_unlock(&gpio_aggregator_lock); - - if (id < 0) { - res = id; - goto free_table; - } - - aggr->lookups->dev_id = kasprintf(GFP_KERNEL, "%s.%d", DRV_NAME, id); + aggr->lookups->dev_id = kasprintf(GFP_KERNEL, "%s.%d", DRV_NAME, aggr->id); if (!aggr->lookups->dev_id) { res = -ENOMEM; - goto remove_idr; + goto free_table; } res = gpio_aggregator_parse(aggr); @@ -486,7 +504,7 @@ static ssize_t gpio_aggregator_new_device_store(struct device_driver *driver, gpiod_add_lookup_table(aggr->lookups); - pdev = platform_device_register_simple(DRV_NAME, id, NULL, 0); + pdev = platform_device_register_simple(DRV_NAME, aggr->id, NULL, 0); if (IS_ERR(pdev)) { res = PTR_ERR(pdev); goto remove_table; @@ -500,14 +518,10 @@ static ssize_t gpio_aggregator_new_device_store(struct device_driver *driver, gpiod_remove_lookup_table(aggr->lookups); free_dev_id: kfree(aggr->lookups->dev_id); -remove_idr: - mutex_lock(&gpio_aggregator_lock); - idr_remove(&gpio_aggregator_idr, id); - mutex_unlock(&gpio_aggregator_lock); free_table: kfree(aggr->lookups); free_ga: - kfree(aggr); + gpio_aggregator_free(aggr); put_module: module_put(THIS_MODULE); return res; From patchwork Fri Apr 11 07:26:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Koichiro Den X-Patchwork-Id: 2071378 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4ZYpDs0dS9z1yHt for ; Fri, 11 Apr 2025 17:27:57 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1u38o2-0004Ev-T0; Fri, 11 Apr 2025 07:28:07 +0000 Received: from smtp-relay-internal-1.internal ([10.131.114.114] helo=smtp-relay-internal-1.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1u38nv-0003hl-G7 for kernel-team@lists.ubuntu.com; Fri, 11 Apr 2025 07:27:59 +0000 Received: from mail-pl1-f197.google.com (mail-pl1-f197.google.com [209.85.214.197]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-1.canonical.com (Postfix) with ESMTPS id 362F140139 for ; Fri, 11 Apr 2025 07:27:57 +0000 (UTC) Received: by mail-pl1-f197.google.com with SMTP id d9443c01a7336-227ed471999so15314875ad.3 for ; Fri, 11 Apr 2025 00:27:57 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744356474; x=1744961274; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ota0bEdZdVgXkxLKj7KfBSlb/eLz23NZxpiAFemKs9k=; b=sEhkYC1StfcLjn4nnxPALUh9AzZgTKRfLuwb1m74O0cAy8CpbOX+eLVDWLh4tAwKJ0 VAb8xNKSoefTGyI1S7umQsyeCaZ9/MzUPfQon170WWAm6puJdt0iKtFVFPvKXPaohapi 1WEkK1dzJeD4FXWq9XI2dUV3t5kYZ7JnsJi8Nmzfon4RX1i9jdgYv/hZ/gPT2T6wueBn p4NjyCFxLrsOjv8C0u+5S6ccXbxbi2vL5pvTzclXn/8RB38IhA9uHcBYgBiiS8ADWKox q2kkUICMd6WCGYgJK2JX7ZwpPIKM3W9ZcnAxLjx0OpzhRRNUGB0Yk26v+vAyS6I9MxiL LFnQ== X-Gm-Message-State: AOJu0YzPqK1ORutMwIhwp6O5awfKhPuLM1IIluUpMU3xZTB5x0wrfcdA dAmzA87h0SUsz631W6H9EM7VLRyNQSc3IIWQsZbmAHBhx+rH1wTJOtGQAzxjKz9lj3dMhv6V4KW 01rbZigIy1EcN+hF056PV6Jgzh/Tot7O3HeFMfky09zcEJYC7EOO27mUbfAXbCuSj7+hShr7IfG 154PW4jvO+YA== X-Gm-Gg: ASbGncuM34umMAZuJcI67o0P0KBsn5mxFCt5z0el6KSLM9FIeKdGtfMvX4ymUVxqGEN DeCNzbtUPFIZpVnAhgxtwF8lY3E1mEdZbi7xBZdOtWY7sl7fqG+89RFoXO61+0Q8mN/ij9VFBOl /acyhsk1t306rZbWqO+LdlKkKjFGH3NH58M+Fxm8JoiQGoO2YhLQXaBgtiskdZpFQ53XQqPbPdQ OU96vabQaieEPIspTqOEwGgK/sT0vN7OtLxXUtpqbFXkzsb+A7o35jYt4wssr0kBgFPcctMuOT3 YUSJbQcnWpkw2aciPE14Bax2rIdykQ== X-Received: by 2002:a17:902:daca:b0:223:5e6a:57ab with SMTP id d9443c01a7336-22bea4efe4dmr26830815ad.39.1744356474247; Fri, 11 Apr 2025 00:27:54 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHKMffaQgNSYRM+qaFJIQgGFP+SjiGwUAU/zIWno2gGnH+aoEW8NfpXc3GCZ/GcVBnl1IKkMg== X-Received: by 2002:a17:902:daca:b0:223:5e6a:57ab with SMTP id d9443c01a7336-22bea4efe4dmr26830335ad.39.1744356473553; Fri, 11 Apr 2025 00:27:53 -0700 (PDT) Received: from localhost.localdomain ([240f:74:7be:1:f99c:bbee:3855:787c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-22ac7cda517sm42421105ad.250.2025.04.11.00.27.52 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Apr 2025 00:27:53 -0700 (PDT) From: Koichiro Den To: kernel-team@lists.ubuntu.com Subject: [SRU][N][PATCH 08/14] gpio: aggregator: introduce basic configfs interface Date: Fri, 11 Apr 2025 16:26:44 +0900 Message-ID: <92541dab28c82aaeb5075cb8d0f7741873add227.1744350640.git.koichiro.den@canonical.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: <174435057828.183979.10447742120666677608@z790sl> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" BugLink: https://bugs.launchpad.net/bugs/2103496 The existing sysfs 'new_device' interface has several limitations: * No way to determine when GPIO aggregator creation is complete. * No way to retrieve errors when creating a GPIO aggregator. * No way to trace a GPIO line of an aggregator back to its corresponding physical device. * The 'new_device' echo does not indicate which virtual gpiochip was created. * No way to assign names to GPIO lines exported through an aggregator. Introduce the new configfs interface for gpio-aggregator to address these limitations. It provides a more streamlined, modern, and extensible configuration method. For backward compatibility, the 'new_device' interface and its behavior is retained for now. This commit implements basic functionalities: /config/gpio-aggregator// /config/gpio-aggregator//live /config/gpio-aggregator//dev_name /config/gpio-aggregator/// /config/gpio-aggregator///key /config/gpio-aggregator///offset /config/gpio-aggregator///name Basic setup flow is: 1. Create a directory for a GPIO aggregator. 2. Create subdirectories for each line you want to instantiate. 3. In each line directory, configure the key and offset. The key/offset semantics are as follows: * If offset is >= 0: - key specifies the name of the chip this GPIO belongs to - offset specifies the line offset within that chip. * If offset is <0: - key needs to specify the GPIO line name. 4. Return to the aggregator's root directory and write '1' to the live attribute. For example, the command in the existing kernel doc: echo 'e6052000.gpio 19 e6050000.gpio 20-21' > new_device is equivalent to: mkdir /sys/kernel/config/gpio-aggregator/ # Change to name of your choice (e.g. "aggr0") cd /sys/kernel/config/gpio-aggregator/ mkdir line0 line1 line2 # Only "line" naming allowed. echo e6052000.gpio > line0/key echo 19 > line0/offset echo e6050000.gpio > line1/key echo 20 > line1/offset echo e6050000.gpio > line2/key echo 21 > line2/offset echo 1 > live The corresponding gpio_device id can be identified as follows: cd /sys/kernel/config/gpio-aggregator/ ls -d /sys/devices/platform/`cat dev_name`/gpiochip* Also, via configfs, custom GPIO line name can be set like this: cd /sys/kernel/config/gpio-aggregator/ echo "abc" > line1/name Signed-off-by: Koichiro Den Link: https://lore.kernel.org/r/20250407043019.4105613-5-koichiro.den@canonical.com [Bartosz: remove stray newlines] Signed-off-by: Bartosz Golaszewski (cherry picked from commit 86f162e73d2d81ef6d819c06a3b6c2fda77a79b8 linux-next) Signed-off-by: Koichiro Den --- drivers/gpio/Kconfig | 2 + drivers/gpio/gpio-aggregator.c | 637 ++++++++++++++++++++++++++++++++- 2 files changed, 626 insertions(+), 13 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 4a532952846f..72035b5555a1 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1806,6 +1806,8 @@ menu "Virtual GPIO drivers" config GPIO_AGGREGATOR tristate "GPIO Aggregator" + select CONFIGFS_FS + select DEV_SYNC_PROBE help Say yes here to enable the GPIO Aggregator, which provides a way to aggregate existing GPIO lines into a new virtual GPIO chip. diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index f34581a76b06..f492b7259ec5 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -9,10 +9,13 @@ #include #include +#include #include #include #include #include +#include +#include #include #include #include @@ -27,6 +30,8 @@ #include #include +#include "dev-sync-probe.h" + #define AGGREGATOR_MAX_GPIOS 512 /* @@ -34,12 +39,38 @@ */ struct gpio_aggregator { + struct dev_sync_probe_data probe_data; + struct config_group group; struct gpiod_lookup_table *lookups; - struct platform_device *pdev; + struct mutex lock; int id; + + /* List of gpio_aggregator_line. Always added in order */ + struct list_head list_head; + + /* used by legacy sysfs interface only */ + bool init_via_sysfs; char args[]; }; +struct gpio_aggregator_line { + struct config_group group; + struct gpio_aggregator *parent; + struct list_head entry; + + /* Line index within the aggregator device */ + unsigned int idx; + + /* Custom name for the virtual line */ + const char *name; + /* GPIO chip label or line name */ + const char *key; + /* Can be negative to indicate lookup by line name */ + int offset; + + enum gpio_lookup_flags flags; +}; + static DEFINE_MUTEX(gpio_aggregator_lock); /* protects idr */ static DEFINE_IDR(gpio_aggregator_idr); @@ -59,6 +90,8 @@ static int gpio_aggregator_alloc(struct gpio_aggregator **aggr, size_t arg_size) return ret; new->id = ret; + INIT_LIST_HEAD(&new->list_head); + mutex_init(&new->lock); *aggr = no_free_ptr(new); return 0; } @@ -68,6 +101,7 @@ static void gpio_aggregator_free(struct gpio_aggregator *aggr) scoped_guard(mutex, &gpio_aggregator_lock) idr_remove(&gpio_aggregator_idr, aggr->id); + mutex_destroy(&aggr->lock); kfree(aggr); } @@ -90,6 +124,71 @@ static int gpio_aggregator_add_gpio(struct gpio_aggregator *aggr, return 0; } +static bool gpio_aggregator_is_active(struct gpio_aggregator *aggr) +{ + lockdep_assert_held(&aggr->lock); + + return aggr->probe_data.pdev && platform_get_drvdata(aggr->probe_data.pdev); +} + +static size_t gpio_aggregator_count_lines(struct gpio_aggregator *aggr) +{ + lockdep_assert_held(&aggr->lock); + + return list_count_nodes(&aggr->list_head); +} + +static struct gpio_aggregator_line * +gpio_aggregator_line_alloc(struct gpio_aggregator *parent, unsigned int idx, + char *key, int offset) +{ + struct gpio_aggregator_line *line; + + line = kzalloc(sizeof(*line), GFP_KERNEL); + if (!line) + return ERR_PTR(-ENOMEM); + + if (key) { + line->key = kstrdup(key, GFP_KERNEL); + if (!line->key) { + kfree(line); + return ERR_PTR(-ENOMEM); + } + } + + line->flags = GPIO_LOOKUP_FLAGS_DEFAULT; + line->parent = parent; + line->idx = idx; + line->offset = offset; + INIT_LIST_HEAD(&line->entry); + + return line; +} + +static void gpio_aggregator_line_add(struct gpio_aggregator *aggr, + struct gpio_aggregator_line *line) +{ + struct gpio_aggregator_line *tmp; + + lockdep_assert_held(&aggr->lock); + + list_for_each_entry(tmp, &aggr->list_head, entry) { + if (tmp->idx > line->idx) { + list_add_tail(&line->entry, &tmp->entry); + return; + } + } + list_add_tail(&line->entry, &aggr->list_head); +} + +static void gpio_aggregator_line_del(struct gpio_aggregator *aggr, + struct gpio_aggregator_line *line) +{ + lockdep_assert_held(&aggr->lock); + + list_del(&line->entry); +} + /* * GPIO Forwarder @@ -413,6 +512,473 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev, return fwd; } +/* + * Configfs interface + */ + +static struct gpio_aggregator * +to_gpio_aggregator(struct config_item *item) +{ + struct config_group *group = to_config_group(item); + + return container_of(group, struct gpio_aggregator, group); +} + +static struct gpio_aggregator_line * +to_gpio_aggregator_line(struct config_item *item) +{ + struct config_group *group = to_config_group(item); + + return container_of(group, struct gpio_aggregator_line, group); +} + +static struct fwnode_handle * +gpio_aggregator_make_device_sw_node(struct gpio_aggregator *aggr) +{ + struct property_entry properties[2]; + struct gpio_aggregator_line *line; + size_t num_lines; + int n = 0; + + memset(properties, 0, sizeof(properties)); + + num_lines = gpio_aggregator_count_lines(aggr); + if (num_lines == 0) + return NULL; + + const char **line_names __free(kfree) = kcalloc( + num_lines, sizeof(*line_names), GFP_KERNEL); + if (!line_names) + return ERR_PTR(-ENOMEM); + + /* The list is always sorted as new elements are inserted in order. */ + list_for_each_entry(line, &aggr->list_head, entry) + line_names[n++] = line->name ?: ""; + + properties[0] = PROPERTY_ENTRY_STRING_ARRAY_LEN( + "gpio-line-names", + line_names, num_lines); + + return fwnode_create_software_node(properties, NULL); +} + +static int gpio_aggregator_activate(struct gpio_aggregator *aggr) +{ + struct platform_device_info pdevinfo; + struct gpio_aggregator_line *line; + struct fwnode_handle *swnode; + unsigned int n = 0; + int ret = 0; + + if (gpio_aggregator_count_lines(aggr) == 0) + return -EINVAL; + + aggr->lookups = kzalloc(struct_size(aggr->lookups, table, 1), + GFP_KERNEL); + if (!aggr->lookups) + return -ENOMEM; + + swnode = gpio_aggregator_make_device_sw_node(aggr); + if (IS_ERR(swnode)) + goto err_remove_lookups; + + memset(&pdevinfo, 0, sizeof(pdevinfo)); + pdevinfo.name = DRV_NAME; + pdevinfo.id = aggr->id; + pdevinfo.fwnode = swnode; + + /* The list is always sorted as new elements are inserted in order. */ + list_for_each_entry(line, &aggr->list_head, entry) { + /* + * - Either GPIO chip label or line name must be configured + * (i.e. line->key must be non-NULL) + * - Line directories must be named with sequential numeric + * suffixes starting from 0. (i.e. ./line0, ./line1, ...) + */ + if (!line->key || line->idx != n) { + ret = -EINVAL; + goto err_remove_swnode; + } + + if (line->offset < 0) + ret = gpio_aggregator_add_gpio(aggr, line->key, + U16_MAX, &n); + else + ret = gpio_aggregator_add_gpio(aggr, line->key, + line->offset, &n); + if (ret) + goto err_remove_swnode; + } + + aggr->lookups->dev_id = kasprintf(GFP_KERNEL, "%s.%d", DRV_NAME, aggr->id); + if (!aggr->lookups->dev_id) { + ret = -ENOMEM; + goto err_remove_swnode; + } + + gpiod_add_lookup_table(aggr->lookups); + + ret = dev_sync_probe_register(&aggr->probe_data, &pdevinfo); + if (ret) + goto err_remove_lookup_table; + + return 0; + +err_remove_lookup_table: + kfree(aggr->lookups->dev_id); + gpiod_remove_lookup_table(aggr->lookups); +err_remove_swnode: + fwnode_remove_software_node(swnode); +err_remove_lookups: + kfree(aggr->lookups); + + return ret; +} + +static void gpio_aggregator_deactivate(struct gpio_aggregator *aggr) +{ + dev_sync_probe_unregister(&aggr->probe_data); + gpiod_remove_lookup_table(aggr->lookups); + kfree(aggr->lookups->dev_id); + kfree(aggr->lookups); +} + +static void gpio_aggregator_lockup_configfs(struct gpio_aggregator *aggr, + bool lock) +{ + struct configfs_subsystem *subsys = aggr->group.cg_subsys; + struct gpio_aggregator_line *line; + + /* + * The device only needs to depend on leaf lines. This is + * sufficient to lock up all the configfs entries that the + * instantiated, alive device depends on. + */ + list_for_each_entry(line, &aggr->list_head, entry) { + if (lock) + configfs_depend_item_unlocked( + subsys, &line->group.cg_item); + else + configfs_undepend_item_unlocked( + &line->group.cg_item); + } +} + +static ssize_t +gpio_aggregator_line_key_show(struct config_item *item, char *page) +{ + struct gpio_aggregator_line *line = to_gpio_aggregator_line(item); + struct gpio_aggregator *aggr = line->parent; + + guard(mutex)(&aggr->lock); + + return sysfs_emit(page, "%s\n", line->key ?: ""); +} + +static ssize_t +gpio_aggregator_line_key_store(struct config_item *item, const char *page, + size_t count) +{ + struct gpio_aggregator_line *line = to_gpio_aggregator_line(item); + struct gpio_aggregator *aggr = line->parent; + + char *key __free(kfree) = kstrndup(skip_spaces(page), count, + GFP_KERNEL); + if (!key) + return -ENOMEM; + + strim(key); + + guard(mutex)(&aggr->lock); + + if (gpio_aggregator_is_active(aggr)) + return -EBUSY; + + kfree(line->key); + line->key = no_free_ptr(key); + + return count; +} +CONFIGFS_ATTR(gpio_aggregator_line_, key); + +static ssize_t +gpio_aggregator_line_name_show(struct config_item *item, char *page) +{ + struct gpio_aggregator_line *line = to_gpio_aggregator_line(item); + struct gpio_aggregator *aggr = line->parent; + + guard(mutex)(&aggr->lock); + + return sysfs_emit(page, "%s\n", line->name ?: ""); +} + +static ssize_t +gpio_aggregator_line_name_store(struct config_item *item, const char *page, + size_t count) +{ + struct gpio_aggregator_line *line = to_gpio_aggregator_line(item); + struct gpio_aggregator *aggr = line->parent; + + char *name __free(kfree) = kstrndup(skip_spaces(page), count, + GFP_KERNEL); + if (!name) + return -ENOMEM; + + strim(name); + + guard(mutex)(&aggr->lock); + + if (gpio_aggregator_is_active(aggr)) + return -EBUSY; + + kfree(line->name); + line->name = no_free_ptr(name); + + return count; +} +CONFIGFS_ATTR(gpio_aggregator_line_, name); + +static ssize_t +gpio_aggregator_line_offset_show(struct config_item *item, char *page) +{ + struct gpio_aggregator_line *line = to_gpio_aggregator_line(item); + struct gpio_aggregator *aggr = line->parent; + + guard(mutex)(&aggr->lock); + + return sysfs_emit(page, "%d\n", line->offset); +} + +static ssize_t +gpio_aggregator_line_offset_store(struct config_item *item, const char *page, + size_t count) +{ + struct gpio_aggregator_line *line = to_gpio_aggregator_line(item); + struct gpio_aggregator *aggr = line->parent; + int offset, ret; + + ret = kstrtoint(page, 0, &offset); + if (ret) + return ret; + + /* + * When offset == -1, 'key' represents a line name to lookup. + * When 0 <= offset < 65535, 'key' represents the label of the chip with + * the 'offset' value representing the line within that chip. + * + * GPIOLIB uses the U16_MAX value to indicate lookup by line name so + * the greatest offset we can accept is (U16_MAX - 1). + */ + if (offset > (U16_MAX - 1) || offset < -1) + return -EINVAL; + + guard(mutex)(&aggr->lock); + + if (gpio_aggregator_is_active(aggr)) + return -EBUSY; + + line->offset = offset; + + return count; +} +CONFIGFS_ATTR(gpio_aggregator_line_, offset); + +static struct configfs_attribute *gpio_aggregator_line_attrs[] = { + &gpio_aggregator_line_attr_key, + &gpio_aggregator_line_attr_name, + &gpio_aggregator_line_attr_offset, + NULL +}; + +static ssize_t +gpio_aggregator_device_dev_name_show(struct config_item *item, char *page) +{ + struct gpio_aggregator *aggr = to_gpio_aggregator(item); + struct platform_device *pdev; + + guard(mutex)(&aggr->lock); + + pdev = aggr->probe_data.pdev; + if (pdev) + return sysfs_emit(page, "%s\n", dev_name(&pdev->dev)); + + return sysfs_emit(page, "%s.%d\n", DRV_NAME, aggr->id); +} +CONFIGFS_ATTR_RO(gpio_aggregator_device_, dev_name); + +static ssize_t +gpio_aggregator_device_live_show(struct config_item *item, char *page) +{ + struct gpio_aggregator *aggr = to_gpio_aggregator(item); + + guard(mutex)(&aggr->lock); + + return sysfs_emit(page, "%c\n", + gpio_aggregator_is_active(aggr) ? '1' : '0'); +} + +static ssize_t +gpio_aggregator_device_live_store(struct config_item *item, const char *page, + size_t count) +{ + struct gpio_aggregator *aggr = to_gpio_aggregator(item); + int ret = 0; + bool live; + + ret = kstrtobool(page, &live); + if (ret) + return ret; + + if (!try_module_get(THIS_MODULE)) + return -ENOENT; + + if (live) + gpio_aggregator_lockup_configfs(aggr, true); + + scoped_guard(mutex, &aggr->lock) { + if (live == gpio_aggregator_is_active(aggr)) + ret = -EPERM; + else if (live) + ret = gpio_aggregator_activate(aggr); + else + gpio_aggregator_deactivate(aggr); + } + + /* + * Undepend is required only if device disablement (live == 0) + * succeeds or if device enablement (live == 1) fails. + */ + if (live == !!ret) + gpio_aggregator_lockup_configfs(aggr, false); + + module_put(THIS_MODULE); + + return ret ?: count; +} +CONFIGFS_ATTR(gpio_aggregator_device_, live); + +static struct configfs_attribute *gpio_aggregator_device_attrs[] = { + &gpio_aggregator_device_attr_dev_name, + &gpio_aggregator_device_attr_live, + NULL +}; + +static void +gpio_aggregator_line_release(struct config_item *item) +{ + struct gpio_aggregator_line *line = to_gpio_aggregator_line(item); + struct gpio_aggregator *aggr = line->parent; + + guard(mutex)(&aggr->lock); + + gpio_aggregator_line_del(aggr, line); + kfree(line->key); + kfree(line->name); + kfree(line); +} + +static struct configfs_item_operations gpio_aggregator_line_item_ops = { + .release = gpio_aggregator_line_release, +}; + +static const struct config_item_type gpio_aggregator_line_type = { + .ct_item_ops = &gpio_aggregator_line_item_ops, + .ct_attrs = gpio_aggregator_line_attrs, + .ct_owner = THIS_MODULE, +}; + +static void gpio_aggregator_device_release(struct config_item *item) +{ + struct gpio_aggregator *aggr = to_gpio_aggregator(item); + + /* + * If the aggregator is active, this code wouldn't be reached, + * so calling gpio_aggregator_deactivate() is always unnecessary. + */ + gpio_aggregator_free(aggr); +} + +static struct configfs_item_operations gpio_aggregator_device_item_ops = { + .release = gpio_aggregator_device_release, +}; + +static struct config_group * +gpio_aggregator_device_make_group(struct config_group *group, const char *name) +{ + struct gpio_aggregator *aggr = to_gpio_aggregator(&group->cg_item); + struct gpio_aggregator_line *line; + unsigned int idx; + int ret, nchar; + + ret = sscanf(name, "line%u%n", &idx, &nchar); + if (ret != 1 || nchar != strlen(name)) + return ERR_PTR(-EINVAL); + + guard(mutex)(&aggr->lock); + + if (gpio_aggregator_is_active(aggr)) + return ERR_PTR(-EBUSY); + + list_for_each_entry(line, &aggr->list_head, entry) + if (line->idx == idx) + return ERR_PTR(-EINVAL); + + line = gpio_aggregator_line_alloc(aggr, idx, NULL, -1); + if (!line) + return ERR_PTR(-ENOMEM); + + config_group_init_type_name(&line->group, name, &gpio_aggregator_line_type); + + gpio_aggregator_line_add(aggr, line); + + return &line->group; +} + +static struct configfs_group_operations gpio_aggregator_device_group_ops = { + .make_group = gpio_aggregator_device_make_group, +}; + +static const struct config_item_type gpio_aggregator_device_type = { + .ct_group_ops = &gpio_aggregator_device_group_ops, + .ct_item_ops = &gpio_aggregator_device_item_ops, + .ct_attrs = gpio_aggregator_device_attrs, + .ct_owner = THIS_MODULE, +}; + +static struct config_group * +gpio_aggregator_make_group(struct config_group *group, const char *name) +{ + struct gpio_aggregator *aggr; + int ret; + + /* arg space is unneeded */ + ret = gpio_aggregator_alloc(&aggr, 0); + if (ret) + return ERR_PTR(ret); + + config_group_init_type_name(&aggr->group, name, &gpio_aggregator_device_type); + dev_sync_probe_init(&aggr->probe_data); + + return &aggr->group; +} + +static struct configfs_group_operations gpio_aggregator_group_ops = { + .make_group = gpio_aggregator_make_group, +}; + +static const struct config_item_type gpio_aggregator_type = { + .ct_group_ops = &gpio_aggregator_group_ops, + .ct_owner = THIS_MODULE, +}; + +static struct configfs_subsystem gpio_aggregator_subsys = { + .su_group = { + .cg_item = { + .ci_namebuf = DRV_NAME, + .ci_type = &gpio_aggregator_type, + }, + }, +}; /* * Sysfs interface @@ -485,6 +1051,7 @@ static ssize_t gpio_aggregator_new_device_store(struct device_driver *driver, memcpy(aggr->args, buf, count + 1); + aggr->init_via_sysfs = true; aggr->lookups = kzalloc(struct_size(aggr->lookups, table, 1), GFP_KERNEL); if (!aggr->lookups) { @@ -510,7 +1077,7 @@ static ssize_t gpio_aggregator_new_device_store(struct device_driver *driver, goto remove_table; } - aggr->pdev = pdev; + aggr->probe_data.pdev = pdev; module_put(THIS_MODULE); return count; @@ -532,10 +1099,7 @@ static struct driver_attribute driver_attr_gpio_aggregator_new_device = static void gpio_aggregator_destroy(struct gpio_aggregator *aggr) { - platform_device_unregister(aggr->pdev); - gpiod_remove_lookup_table(aggr->lookups); - kfree(aggr->lookups->dev_id); - kfree(aggr->lookups); + gpio_aggregator_deactivate(aggr); kfree(aggr); } @@ -557,12 +1121,19 @@ static ssize_t gpio_aggregator_delete_device_store(struct device_driver *driver, return -ENOENT; mutex_lock(&gpio_aggregator_lock); - aggr = idr_remove(&gpio_aggregator_idr, id); - mutex_unlock(&gpio_aggregator_lock); - if (!aggr) { + aggr = idr_find(&gpio_aggregator_idr, id); + /* + * For simplicity, devices created via configfs cannot be deleted + * via sysfs. + */ + if (aggr && aggr->init_via_sysfs) + idr_remove(&gpio_aggregator_idr, id); + else { + mutex_unlock(&gpio_aggregator_lock); module_put(THIS_MODULE); return -ENOENT; } + mutex_unlock(&gpio_aggregator_lock); gpio_aggregator_destroy(aggr); module_put(THIS_MODULE); @@ -579,7 +1150,6 @@ static struct attribute *gpio_aggregator_attrs[] = { }; ATTRIBUTE_GROUPS(gpio_aggregator); - /* * GPIO Aggregator platform device */ @@ -639,21 +1209,61 @@ static struct platform_driver gpio_aggregator_driver = { static int __exit gpio_aggregator_idr_remove(int id, void *p, void *data) { + /* + * There should be no aggregator created via configfs, as their + * presence would prevent module unloading. + */ gpio_aggregator_destroy(p); return 0; } static void __exit gpio_aggregator_remove_all(void) { - mutex_lock(&gpio_aggregator_lock); + /* + * Configfs callbacks acquire gpio_aggregator_lock when accessing + * gpio_aggregator_idr, so to prevent lock inversion deadlock, we + * cannot protect idr_for_each invocation here with + * gpio_aggregator_lock, as gpio_aggregator_idr_remove() accesses + * configfs groups. Fortunately, the new_device/delete_device path + * and the module unload path are mutually exclusive, thanks to an + * explicit try_module_get inside of those driver attr handlers. + * Also, when we reach here, no configfs entries present or being + * created. Therefore, no need to protect with gpio_aggregator_lock + * below. + */ idr_for_each(&gpio_aggregator_idr, gpio_aggregator_idr_remove, NULL); idr_destroy(&gpio_aggregator_idr); - mutex_unlock(&gpio_aggregator_lock); } static int __init gpio_aggregator_init(void) { - return platform_driver_register(&gpio_aggregator_driver); + int ret = 0; + + config_group_init(&gpio_aggregator_subsys.su_group); + mutex_init(&gpio_aggregator_subsys.su_mutex); + ret = configfs_register_subsystem(&gpio_aggregator_subsys); + if (ret) { + pr_err("Failed to register the '%s' configfs subsystem: %d\n", + gpio_aggregator_subsys.su_group.cg_item.ci_namebuf, ret); + mutex_destroy(&gpio_aggregator_subsys.su_mutex); + return ret; + } + + /* + * CAVEAT: This must occur after configfs registration. Otherwise, + * a race condition could arise: driver attribute groups might be + * exposed and accessed by users before configfs registration + * completes. new_device_store() does not expect a partially + * initialized configfs state. + */ + ret = platform_driver_register(&gpio_aggregator_driver); + if (ret) { + pr_err("Failed to register the platform driver: %d\n", ret); + mutex_destroy(&gpio_aggregator_subsys.su_mutex); + configfs_unregister_subsystem(&gpio_aggregator_subsys); + } + + return ret; } module_init(gpio_aggregator_init); @@ -661,6 +1271,7 @@ static void __exit gpio_aggregator_exit(void) { gpio_aggregator_remove_all(); platform_driver_unregister(&gpio_aggregator_driver); + configfs_unregister_subsystem(&gpio_aggregator_subsys); } module_exit(gpio_aggregator_exit); From patchwork Fri Apr 11 07:26:45 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Koichiro Den X-Patchwork-Id: 2071377 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4ZYpDp24TQz1yHt for ; Fri, 11 Apr 2025 17:27:54 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1u38nz-00044H-Hk; Fri, 11 Apr 2025 07:28:03 +0000 Received: from smtp-relay-internal-0.internal ([10.131.114.225] helo=smtp-relay-internal-0.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1u38nu-0003iv-Gl for kernel-team@lists.ubuntu.com; Fri, 11 Apr 2025 07:27:58 +0000 Received: from mail-pl1-f198.google.com (mail-pl1-f198.google.com [209.85.214.198]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-0.canonical.com (Postfix) with ESMTPS id ECD073F169 for ; Fri, 11 Apr 2025 07:27:56 +0000 (UTC) Received: by mail-pl1-f198.google.com with SMTP id d9443c01a7336-22650077995so23868365ad.3 for ; Fri, 11 Apr 2025 00:27:56 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744356475; x=1744961275; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=wrHkupNep4P0pAsp8OGChBHkMUv9w/Htv88LfYUfaJg=; b=C6UQkV2IKmKLtgHEQP3bB6F9pEVNfZwa9dqrbnZr9+GJcpjq5Bi+O6LYlNl0+apy4n zXpO5BziArGZ9LdZiEl13aY2xuJUHGdzMfZ0B/1iyLQf+M/AnTN5gt84ykLahwFjz9uX IsmFB3CJL/otVoPUuY6PIlaazIPK6m2qEBVYjMqoMC9wSuhM7aQlGfwJhoUkY4iq64G0 nIAOxkLTCLNkg9M8Ys/dzXNflFN8DV0ViN21T0iBuVq8i7vqSxGF66Ua0WQMTNmTTYL7 hPc1rkSSBOB6Nq+QSARqN0tWpqbF40joLxDzLmE1BXrF5bLM4IUxQ1SWC7TJF3jD0CF6 hG1g== X-Gm-Message-State: AOJu0Yyw3rUq/RLM30WEcebw4u335jkZn2221RXs6rf5SwNmnj5+jFnE 1WoNrvtNO3Ef7vK7xxQzDAsLEoa+QWpqsNIKFz3x0nUkV06QU3CXCJCg3+RznErV5Sho7z+VYTC K9uAbBRFgZolFUkGpxsE/OLvHBla8ZvmvBkKkwJ0/6p5F95KMVsTj/mpljnU5Bo3BVHCGxd/xyj YYXSKolCePSw== X-Gm-Gg: ASbGncuiMmcJA21WjaOisrtsNfLtJPhS+BALnTKsKK2y8BgNe417AhN8X5PQTPIZ0xl iqgHr7WZywgAitmPSH6Dw/5oR2GhMKxECHaJO2KOzka+nTFC6zY11SQqVHg+k2J0b+uLtUcvyfY MA09VLd96wTkkUs6JbEa7cGAAJGLjcUl9Ro5qG4CMwdIq8dUJ3xAt/Odkd1yha5U30uOZCmYySa 3L3E/rPTFmKTG31+JGLM8q+l1BV97hD9yrbLKQ/1MZeRf6AdpoBxU9mTGF3b2oL0fFzLbnj43T+ Q5fMTCNea4F57XgMB1d/LdJKz8wpkQ== X-Received: by 2002:a17:902:c952:b0:224:1ec0:8a1a with SMTP id d9443c01a7336-22bea4fdb12mr25241415ad.51.1744356475097; Fri, 11 Apr 2025 00:27:55 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEJytHuanxG+ZaJP2L+cViesqHnczvVmVohePWRHacr0YCFP68LjSZye80fHaeQD1e81M07bA== X-Received: by 2002:a17:902:c952:b0:224:1ec0:8a1a with SMTP id d9443c01a7336-22bea4fdb12mr25241265ad.51.1744356474720; Fri, 11 Apr 2025 00:27:54 -0700 (PDT) Received: from localhost.localdomain ([240f:74:7be:1:f99c:bbee:3855:787c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-22ac7cda517sm42421105ad.250.2025.04.11.00.27.53 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Apr 2025 00:27:54 -0700 (PDT) From: Koichiro Den To: kernel-team@lists.ubuntu.com Subject: [SRU][N][PATCH 09/14] UBUNTU: [Config] updateconfigs for DEV_SYNC_PROBE Date: Fri, 11 Apr 2025 16:26:45 +0900 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: <174435057828.183979.10447742120666677608@z790sl> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" BugLink: https://bugs.launchpad.net/bugs/2103496 Signed-off-by: Koichiro Den --- debian.master/config/annotations | 1 + 1 file changed, 1 insertion(+) diff --git a/debian.master/config/annotations b/debian.master/config/annotations index 1a044e3e9d45..09b136c24d5d 100644 --- a/debian.master/config/annotations +++ b/debian.master/config/annotations @@ -3924,6 +3924,7 @@ CONFIG_DEV_DAX_HMEM policy<{'amd64': 'm', 'arm64': ' CONFIG_DEV_DAX_HMEM_DEVICES policy<{'amd64': 'y', 'arm64': 'y'}> CONFIG_DEV_DAX_KMEM policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm', 's390x': 'm'}> CONFIG_DEV_DAX_PMEM policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm'}> +CONFIG_DEV_SYNC_PROBE policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm', 'riscv64': 'm', 's390x': 'm'}> CONFIG_DHT11 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm', 'riscv64': 'm'}> CONFIG_DIAG288_WATCHDOG policy<{'s390x': 'm'}> CONFIG_DIMLIB policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y', 'riscv64': 'y', 's390x': 'y'}> From patchwork Fri Apr 11 07:26:46 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Koichiro Den X-Patchwork-Id: 2071379 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4ZYpDv0RmHz1yHt for ; Fri, 11 Apr 2025 17:27:59 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1u38o5-0004RR-OA; Fri, 11 Apr 2025 07:28:09 +0000 Received: from smtp-relay-internal-0.internal ([10.131.114.225] helo=smtp-relay-internal-0.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1u38nv-0003o2-Ug for kernel-team@lists.ubuntu.com; Fri, 11 Apr 2025 07:28:00 +0000 Received: from mail-pg1-f199.google.com (mail-pg1-f199.google.com [209.85.215.199]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-0.canonical.com (Postfix) with ESMTPS id D93EF3FB77 for ; Fri, 11 Apr 2025 07:27:57 +0000 (UTC) Received: by mail-pg1-f199.google.com with SMTP id 41be03b00d2f7-af534e796baso1127916a12.3 for ; Fri, 11 Apr 2025 00:27:57 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744356476; x=1744961276; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7VRUwPVIYBjWLmriN8iuIt4TEtiIrj93r/68+Uf/cUk=; b=KzGr1vVQ+HkpqpNjBCtmON+f/JJTNFbTtHFNzznC8zKgp8HmHy6MMv2NbpCZ0rlTWc J6gDPAowLF5kfhmv41SO5M3JlIZScRxneWWeESlhmWsu4/CoJvRxpIjNfi8R4EJcPnPt C6AcHSV+ONZpRAAO40uhAFZHE37rioULfwg3NidkT1xkFu0zX+D/FE4yaPKLCpNYxveP SRXafcP9qWtuf3sKG0feQS1lnHpM5fBEqU1eGgQPTBEDqjhhOV6P/C89yWdolreuIYeE DxRRpqQj9JFD6znBVDmlQ+Sovp+WRPQaWP5X6zYrZvsV24StWwqrB5D93uATUTd8aLFD 7Eeg== X-Gm-Message-State: AOJu0YyRMRsgB8hLyH95F4lTIX12GBtUEqIOEmU8usMrwIxUnej1t4R/ 9Ysas3X8tlIadwahaBHStIsCzcJFqBToPOcW+aUoJ/RlVaQHSdqiq2w7v4TGd8i+KSmiP5zDPVZ tlcBOYepmHWZi/LWu2Z7wn3LAoiSI1OkyA1GJ0fd/9hFw3XkIMgZJ8k3Jl9jCL79TrGtkC2QjnA TaEpMXBLEcKg== X-Gm-Gg: ASbGnctlMxgCl0YF1LE6fG7oUiKLU3WhZPULQM1MCt+6hmH1L1jM6xhW9q0E5Ori4Lz yrNODBBd6NfthYQQmNQFs6lb1nH74i2137fqbuooN0k6flY2OWXKA0u8oRy9UGz8z283t11A1Ys uowFced2XIv1hTcsHeZ+OT5GtLvYmU9NJxut8Z9IVQ0WcW87/RBhqe8StHwy4FY9D9vgEITIKM9 X3rgn7Rn/uPj4SydGIDc/bJbhNR0Q0koATdTvPBVpNHqsyUyPY/RxJ6GmsbKixYTSZxW+fsz+FV dF+VZf9Z0GoXcstXMjQZFHbQ1ZHEGA== X-Received: by 2002:a17:903:3c44:b0:224:162:a3e0 with SMTP id d9443c01a7336-22bea50dfb1mr24987295ad.49.1744356476184; Fri, 11 Apr 2025 00:27:56 -0700 (PDT) X-Google-Smtp-Source: AGHT+IF0f32kRBBA/FkHsyojrvAy+SPSlB2VDSYeIKdyCRueaTPSGBy8AMO4JHn34bs1lV/f4T0wJw== X-Received: by 2002:a17:903:3c44:b0:224:162:a3e0 with SMTP id d9443c01a7336-22bea50dfb1mr24987035ad.49.1744356475849; Fri, 11 Apr 2025 00:27:55 -0700 (PDT) Received: from localhost.localdomain ([240f:74:7be:1:f99c:bbee:3855:787c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-22ac7cda517sm42421105ad.250.2025.04.11.00.27.54 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Apr 2025 00:27:55 -0700 (PDT) From: Koichiro Den To: kernel-team@lists.ubuntu.com Subject: [SRU][N][PATCH 10/14] gpio: aggregator: rename 'name' to 'key' in gpio_aggregator_parse() Date: Fri, 11 Apr 2025 16:26:46 +0900 Message-ID: <573ba8bccdf55bb9311f1cdd74a62eb2cde4af82.1744350640.git.koichiro.den@canonical.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: <174435057828.183979.10447742120666677608@z790sl> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" BugLink: https://bugs.launchpad.net/bugs/2103496 Rename the local variable 'name' in gpio_aggregator_parse() to 'key' because struct gpio_aggregator_line now uses the 'name' field for the custom line name and the local variable actually represents a 'key'. This change prepares for the next but one commit. No functional change. Reviewed-by: Geert Uytterhoeven Signed-off-by: Koichiro Den Link: https://lore.kernel.org/r/20250407043019.4105613-6-koichiro.den@canonical.com Signed-off-by: Bartosz Golaszewski (cherry picked from commit 4ec2315d7fabeb08e9ad7995bd16f34118e4633b linux-next) Signed-off-by: Koichiro Den --- drivers/gpio/gpio-aggregator.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index f492b7259ec5..b00b2065e534 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -986,7 +986,7 @@ static struct configfs_subsystem gpio_aggregator_subsys = { static int gpio_aggregator_parse(struct gpio_aggregator *aggr) { char *args = skip_spaces(aggr->args); - char *name, *offsets, *p; + char *key, *offsets, *p; unsigned int i, n = 0; int error = 0; @@ -995,18 +995,18 @@ static int gpio_aggregator_parse(struct gpio_aggregator *aggr) if (!bitmap) return -ENOMEM; - args = next_arg(args, &name, &p); + args = next_arg(args, &key, &p); while (*args) { args = next_arg(args, &offsets, &p); p = get_options(offsets, 0, &error); if (error == 0 || *p) { /* Named GPIO line */ - error = gpio_aggregator_add_gpio(aggr, name, U16_MAX, &n); + error = gpio_aggregator_add_gpio(aggr, key, U16_MAX, &n); if (error) return error; - name = offsets; + key = offsets; continue; } @@ -1018,12 +1018,12 @@ static int gpio_aggregator_parse(struct gpio_aggregator *aggr) } for_each_set_bit(i, bitmap, AGGREGATOR_MAX_GPIOS) { - error = gpio_aggregator_add_gpio(aggr, name, i, &n); + error = gpio_aggregator_add_gpio(aggr, key, i, &n); if (error) return error; } - args = next_arg(args, &name, &p); + args = next_arg(args, &key, &p); } if (!n) { From patchwork Fri Apr 11 07:26:47 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Koichiro Den X-Patchwork-Id: 2071380 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4ZYpDx3HtRz1yHt for ; Fri, 11 Apr 2025 17:28:01 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1u38o8-0004gF-Li; Fri, 11 Apr 2025 07:28:12 +0000 Received: from smtp-relay-internal-1.internal ([10.131.114.114] helo=smtp-relay-internal-1.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1u38nw-0003tI-Nj for kernel-team@lists.ubuntu.com; Fri, 11 Apr 2025 07:28:00 +0000 Received: from mail-pl1-f198.google.com (mail-pl1-f198.google.com [209.85.214.198]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-1.canonical.com (Postfix) with ESMTPS id DF192400AF for ; Fri, 11 Apr 2025 07:27:59 +0000 (UTC) Received: by mail-pl1-f198.google.com with SMTP id d9443c01a7336-2242ce15cc3so13870975ad.1 for ; Fri, 11 Apr 2025 00:27:59 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744356477; x=1744961277; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=79A7XdhGDKPV8uL/DxcNXfGga2zfo7hU8mm+hG1OwPw=; b=JIaq3G8OrZUslijwMLrE/AcdG/a6ZiSFoM61JCt+9o54pHSLHKtLnP+SuPBPUdkdbv RU7im0/2WF5d2DlyyJlu6DTTLGyt2VmW9RGU2t/13i4q315WCIOc/7Ji/r0r957KojKT EG7BVzOX3zc7TBtcPsQjWDfrMwxFdpxwn30gXqQ6Rt5X4N7eNx4qaP4jCNliGZrR6bdR TJt1Tw2Gn48u2CGUMkFNEsuEHSXxjaTEfbj1VpSMkNoUSt7ObSGrrqnYXK7qYcMjqg8C RTK3PJD8slKiHqoWlOBJ5hwNYgap+30jHvEwI9RWK0h9r6b7a63UfPa02b8pnQl0JXUm oaDg== X-Gm-Message-State: AOJu0YzLtEUpU2NboI0NmsiUPnCbR+qI5LhRlTdEWcPgLDyL5Km7RM3v IIvCZ+5P/KTmbn6Z+c9772CFkWrfU8zEiuooTQkVYmqUlIeolkUvb21zs935+qi23GnEa2OSP0M 5/Bsug3TTA231t8PupZNFpM61+/4b4RBSGzUeGGbKQCh7f3gnIUylopAjhDBSH9DQKhGz537WtK JXC4+watG1rg== X-Gm-Gg: ASbGncsJBmJXsMrvQaBPM9dI7vvTQ3usyF5NMfAjiCdDJ9/oYyN+zGK8kQVgpJAfeUd QzyRpFr4qYqnBu08uq7Tyo5HelCeSq3xAA/ZU7Bwpjz7u0i+lbEfsdXfORjwEeI9IjD4MZ1WFay 47nLFK0MkLqybksRChNDLnaSel6yyb2IRcNUGpGGH3Xy5av/vbqF8ouG6znL8AVqL2vDQZ2jg86 lb/mKy74zcw3/dZztQ9u/eeFk6DF+6XmWYv/htnqVe9hPIZ9EVZ+ciEMWIByIQyMVLJs0OqOxP7 OFWEFCqn4gP87iEX2xwGEppZZbzIQg== X-Received: by 2002:a17:903:2310:b0:224:3c9:19ae with SMTP id d9443c01a7336-22bea4efe64mr30614515ad.34.1744356477559; Fri, 11 Apr 2025 00:27:57 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGLiYaap+QDbcgrc5ADLw1jWEoDCPsUsj29yYKoLlDccPOTbE6lNzpaVPwu6sc/Qf0veV54XA== X-Received: by 2002:a17:903:2310:b0:224:3c9:19ae with SMTP id d9443c01a7336-22bea4efe64mr30614175ad.34.1744356477097; Fri, 11 Apr 2025 00:27:57 -0700 (PDT) Received: from localhost.localdomain ([240f:74:7be:1:f99c:bbee:3855:787c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-22ac7cda517sm42421105ad.250.2025.04.11.00.27.56 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Apr 2025 00:27:56 -0700 (PDT) From: Koichiro Den To: kernel-team@lists.ubuntu.com Subject: [SRU][N][PATCH 11/14] gpio: aggregator: expose aggregator created via legacy sysfs to configfs Date: Fri, 11 Apr 2025 16:26:47 +0900 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: <174435057828.183979.10447742120666677608@z790sl> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" BugLink: https://bugs.launchpad.net/bugs/2103496 Expose settings for aggregators created using the sysfs 'new_device' interface to configfs. Once written to 'new_device', an "_sysfs." path appears in the configfs regardless of whether the probe succeeds. Consequently, users can no longer use that prefix for custom GPIO aggregator names. The 'live' attribute changes to 1 when the probe succeeds and the GPIO forwarder is instantiated. Note that the aggregator device created via sysfs is asynchronous, i.e. writing into 'new_device' returns without waiting for probe completion, and the probe may succeed, fail, or eventually succeed via deferred probe. Thus, the 'live' attribute may change from 0 to 1 asynchronously without notice. So, editing key/offset/name while it's waiting for deferred probe is prohibited. The configfs auto-generation relies on create_default_group(), which inherently prohibits rmdir(2). To align with the limitation, this commit also prohibits mkdir(2) for them. When users want to change the number of lines for an aggregator initialized via 'new_device', they need to tear down the device using 'delete_device' and reconfigure it from scratch. This does not break previous behavior; users of legacy sysfs interface simply gain additional almost read-only configfs exposure. Still, users can write to the 'live' attribute to toggle the device unless it's waiting for deferred probe. So once probe succeeds, they can deactivate it in the same manner as the devices initialized via configfs. Signed-off-by: Koichiro Den Link: https://lore.kernel.org/r/20250407043019.4105613-7-koichiro.den@canonical.com Signed-off-by: Bartosz Golaszewski (cherry picked from commit 83c8e3df642f5fde320278a5e6ce9e46f9689d1a linux-next) Signed-off-by: Koichiro Den --- drivers/gpio/gpio-aggregator.c | 138 ++++++++++++++++++++++++++++++--- 1 file changed, 126 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index b00b2065e534..6f4333553733 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -33,6 +33,7 @@ #include "dev-sync-probe.h" #define AGGREGATOR_MAX_GPIOS 512 +#define AGGREGATOR_LEGACY_PREFIX "_sysfs" /* * GPIO Aggregator sysfs interface @@ -131,6 +132,14 @@ static bool gpio_aggregator_is_active(struct gpio_aggregator *aggr) return aggr->probe_data.pdev && platform_get_drvdata(aggr->probe_data.pdev); } +/* Only aggregators created via legacy sysfs can be "activating". */ +static bool gpio_aggregator_is_activating(struct gpio_aggregator *aggr) +{ + lockdep_assert_held(&aggr->lock); + + return aggr->probe_data.pdev && !platform_get_drvdata(aggr->probe_data.pdev); +} + static size_t gpio_aggregator_count_lines(struct gpio_aggregator *aggr) { lockdep_assert_held(&aggr->lock); @@ -189,6 +198,30 @@ static void gpio_aggregator_line_del(struct gpio_aggregator *aggr, list_del(&line->entry); } +static void gpio_aggregator_free_lines(struct gpio_aggregator *aggr) +{ + struct gpio_aggregator_line *line, *tmp; + + list_for_each_entry_safe(line, tmp, &aggr->list_head, entry) { + configfs_unregister_group(&line->group); + /* + * Normally, we acquire aggr->lock within the configfs + * callback. However, in the legacy sysfs interface case, + * calling configfs_(un)register_group while holding + * aggr->lock could cause a deadlock. Fortunately, this is + * unnecessary because the new_device/delete_device path + * and the module unload path are mutually exclusive, + * thanks to an explicit try_module_get. That's why this + * minimal scoped_guard suffices. + */ + scoped_guard(mutex, &aggr->lock) + gpio_aggregator_line_del(aggr, line); + kfree(line->key); + kfree(line->name); + kfree(line); + } +} + /* * GPIO Forwarder @@ -691,7 +724,8 @@ gpio_aggregator_line_key_store(struct config_item *item, const char *page, guard(mutex)(&aggr->lock); - if (gpio_aggregator_is_active(aggr)) + if (gpio_aggregator_is_activating(aggr) || + gpio_aggregator_is_active(aggr)) return -EBUSY; kfree(line->key); @@ -728,7 +762,8 @@ gpio_aggregator_line_name_store(struct config_item *item, const char *page, guard(mutex)(&aggr->lock); - if (gpio_aggregator_is_active(aggr)) + if (gpio_aggregator_is_activating(aggr) || + gpio_aggregator_is_active(aggr)) return -EBUSY; kfree(line->name); @@ -774,7 +809,8 @@ gpio_aggregator_line_offset_store(struct config_item *item, const char *page, guard(mutex)(&aggr->lock); - if (gpio_aggregator_is_active(aggr)) + if (gpio_aggregator_is_activating(aggr) || + gpio_aggregator_is_active(aggr)) return -EBUSY; line->offset = offset; @@ -832,11 +868,12 @@ gpio_aggregator_device_live_store(struct config_item *item, const char *page, if (!try_module_get(THIS_MODULE)) return -ENOENT; - if (live) + if (live && !aggr->init_via_sysfs) gpio_aggregator_lockup_configfs(aggr, true); scoped_guard(mutex, &aggr->lock) { - if (live == gpio_aggregator_is_active(aggr)) + if (gpio_aggregator_is_activating(aggr) || + (live == gpio_aggregator_is_active(aggr))) ret = -EPERM; else if (live) ret = gpio_aggregator_activate(aggr); @@ -848,7 +885,7 @@ gpio_aggregator_device_live_store(struct config_item *item, const char *page, * Undepend is required only if device disablement (live == 0) * succeeds or if device enablement (live == 1) fails. */ - if (live == !!ret) + if (live == !!ret && !aggr->init_via_sysfs) gpio_aggregator_lockup_configfs(aggr, false); module_put(THIS_MODULE); @@ -892,7 +929,7 @@ static void gpio_aggregator_device_release(struct config_item *item) struct gpio_aggregator *aggr = to_gpio_aggregator(item); /* - * If the aggregator is active, this code wouldn't be reached, + * At this point, aggr is neither active nor activating, * so calling gpio_aggregator_deactivate() is always unnecessary. */ gpio_aggregator_free(aggr); @@ -914,6 +951,15 @@ gpio_aggregator_device_make_group(struct config_group *group, const char *name) if (ret != 1 || nchar != strlen(name)) return ERR_PTR(-EINVAL); + if (aggr->init_via_sysfs) + /* + * Aggregators created via legacy sysfs interface are exposed as + * default groups, which means rmdir(2) is prohibited for them. + * For simplicity, and to avoid confusion, we also prohibit + * mkdir(2). + */ + return ERR_PTR(-EPERM); + guard(mutex)(&aggr->lock); if (gpio_aggregator_is_active(aggr)) @@ -951,6 +997,14 @@ gpio_aggregator_make_group(struct config_group *group, const char *name) struct gpio_aggregator *aggr; int ret; + /* + * "_sysfs" prefix is reserved for auto-generated config group + * for devices create via legacy sysfs interface. + */ + if (strncmp(name, AGGREGATOR_LEGACY_PREFIX, + sizeof(AGGREGATOR_LEGACY_PREFIX)) == 0) + return ERR_PTR(-EINVAL); + /* arg space is unneeded */ ret = gpio_aggregator_alloc(&aggr, 0); if (ret) @@ -986,6 +1040,8 @@ static struct configfs_subsystem gpio_aggregator_subsys = { static int gpio_aggregator_parse(struct gpio_aggregator *aggr) { char *args = skip_spaces(aggr->args); + struct gpio_aggregator_line *line; + char name[CONFIGFS_ITEM_NAME_LEN]; char *key, *offsets, *p; unsigned int i, n = 0; int error = 0; @@ -1002,9 +1058,24 @@ static int gpio_aggregator_parse(struct gpio_aggregator *aggr) p = get_options(offsets, 0, &error); if (error == 0 || *p) { /* Named GPIO line */ + scnprintf(name, sizeof(name), "line%u", n); + line = gpio_aggregator_line_alloc(aggr, n, key, -1); + if (!line) { + error = -ENOMEM; + goto err; + } + config_group_init_type_name(&line->group, name, + &gpio_aggregator_line_type); + error = configfs_register_group(&aggr->group, + &line->group); + if (error) + goto err; + scoped_guard(mutex, &aggr->lock) + gpio_aggregator_line_add(aggr, line); + error = gpio_aggregator_add_gpio(aggr, key, U16_MAX, &n); if (error) - return error; + goto err; key = offsets; continue; @@ -1018,9 +1089,24 @@ static int gpio_aggregator_parse(struct gpio_aggregator *aggr) } for_each_set_bit(i, bitmap, AGGREGATOR_MAX_GPIOS) { + scnprintf(name, sizeof(name), "line%u", n); + line = gpio_aggregator_line_alloc(aggr, n, key, i); + if (!line) { + error = -ENOMEM; + goto err; + } + config_group_init_type_name(&line->group, name, + &gpio_aggregator_line_type); + error = configfs_register_group(&aggr->group, + &line->group); + if (error) + goto err; + scoped_guard(mutex, &aggr->lock) + gpio_aggregator_line_add(aggr, line); + error = gpio_aggregator_add_gpio(aggr, key, i, &n); if (error) - return error; + goto err; } args = next_arg(args, &key, &p); @@ -1028,15 +1114,20 @@ static int gpio_aggregator_parse(struct gpio_aggregator *aggr) if (!n) { pr_err("No GPIOs specified\n"); - return -EINVAL; + goto err; } return 0; + +err: + gpio_aggregator_free_lines(aggr); + return error; } static ssize_t gpio_aggregator_new_device_store(struct device_driver *driver, const char *buf, size_t count) { + char name[CONFIGFS_ITEM_NAME_LEN]; struct gpio_aggregator *aggr; struct platform_device *pdev; int res; @@ -1065,10 +1156,25 @@ static ssize_t gpio_aggregator_new_device_store(struct device_driver *driver, goto free_table; } - res = gpio_aggregator_parse(aggr); + scnprintf(name, sizeof(name), "%s.%d", AGGREGATOR_LEGACY_PREFIX, aggr->id); + config_group_init_type_name(&aggr->group, name, &gpio_aggregator_device_type); + + /* + * Since the device created by sysfs might be toggled via configfs + * 'live' attribute later, this initialization is needed. + */ + dev_sync_probe_init(&aggr->probe_data); + + /* Expose to configfs */ + res = configfs_register_group(&gpio_aggregator_subsys.su_group, + &aggr->group); if (res) goto free_dev_id; + res = gpio_aggregator_parse(aggr); + if (res) + goto unregister_group; + gpiod_add_lookup_table(aggr->lookups); pdev = platform_device_register_simple(DRV_NAME, aggr->id, NULL, 0); @@ -1083,6 +1189,8 @@ static ssize_t gpio_aggregator_new_device_store(struct device_driver *driver, remove_table: gpiod_remove_lookup_table(aggr->lookups); +unregister_group: + configfs_unregister_group(&aggr->group); free_dev_id: kfree(aggr->lookups->dev_id); free_table: @@ -1099,7 +1207,13 @@ static struct driver_attribute driver_attr_gpio_aggregator_new_device = static void gpio_aggregator_destroy(struct gpio_aggregator *aggr) { - gpio_aggregator_deactivate(aggr); + scoped_guard(mutex, &aggr->lock) { + if (gpio_aggregator_is_activating(aggr) || + gpio_aggregator_is_active(aggr)) + gpio_aggregator_deactivate(aggr); + } + gpio_aggregator_free_lines(aggr); + configfs_unregister_group(&aggr->group); kfree(aggr); } From patchwork Fri Apr 11 07:26:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Koichiro Den X-Patchwork-Id: 2071381 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4ZYpDz5n0rz1yHt for ; Fri, 11 Apr 2025 17:28:03 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1u38oB-0004z4-0X; Fri, 11 Apr 2025 07:28:15 +0000 Received: from smtp-relay-internal-1.internal ([10.131.114.114] helo=smtp-relay-internal-1.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1u38nx-0003w7-Bg for kernel-team@lists.ubuntu.com; Fri, 11 Apr 2025 07:28:01 +0000 Received: from mail-pg1-f197.google.com (mail-pg1-f197.google.com [209.85.215.197]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-1.canonical.com (Postfix) with ESMTPS id 54C5B40139 for ; Fri, 11 Apr 2025 07:28:00 +0000 (UTC) Received: by mail-pg1-f197.google.com with SMTP id 41be03b00d2f7-b00e4358a34so1123995a12.0 for ; Fri, 11 Apr 2025 00:28:00 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744356479; x=1744961279; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=dbtnNHlcSQqIis4ezm3k/i4X8N405Aa/YQATf/wYO9M=; b=bUEsE3TMZNJt/UNhYu7ZH/HXvlzSEF7OhoJ3r4+dCImd6dpfjcDv0sXVEd+1X6YUbq ph8z2CHt/LRsFSwbxTb6+mIVLS2X0rYB4CDrybH/Xngbm0WyDeV/zHL3xMK30sIyV1Li +Zbxqo9st7oMd3v+EAAAwLAHXZI+lA3i3pv2FgZxJnhXyqDWo2/wqtDw41PbNBwH8Viy mgbU3+5IcpEpnE3d/1f/t7niZIRDHxjUS64pzwcp4yyu3hmoPVDmz8kc3gLtAEGKXxL1 4rkiPHdPh73lpp197YDpZSd8CusMSItsTMva19+cDJ+jIrlm++l8gUIdKYuNlQR4Vs3B xufA== X-Gm-Message-State: AOJu0Yw0xURPx9h742WDsyZY5kmzbGv0+18bFaBa6YDcZEnXiv1Xeiiy ubvoD3j/ksNAn7RFYumjHu+vfDeOO7epToBpP9FiA3BO/6+eoyqWOSWYDyD7kJOsvuO/QIcaESk yBFFrS+t1kzb+lEOMmZFegRfOc7TKnq4LcrShU/FBhRZRihsf9MYcUUSCZKfCT9ceDkkC11jazQ 3A2R35NexQnw== X-Gm-Gg: ASbGncuqGaOogFiMh1yO9zlIqg99sKLiiANXY2CFYfeC5pFVjhwhClArpXu3uD5tgpt 4UTZOTlq6/mdSn2sERrRXRp/+Pjfidb1SQ0axhNjvXOycYWKhcUoTF71Hs6wwmFVnN3eZJmEqdM eFaU9mXi+MihuzLzVviRmVCDo/kAWboFE7suvlh6lcCNm/z9DCeamdMp84M4zLgOhsEpwtVPbCD c7ij3Hb2KiS8YgTUVIe5u7pDnk2zlwBg65TFBUDKn1jvjs8MrWJC+b2prWTao+3SaDMwJh4o5CY R/7XDVhVHQqDnFIbL44SLF6h+b9KWA== X-Received: by 2002:a17:90b:2e4b:b0:2ee:741c:e9f4 with SMTP id 98e67ed59e1d1-308236344acmr2985109a91.11.1744356478742; Fri, 11 Apr 2025 00:27:58 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFnCUM8i2+1UO+N1yreGYcVa5niM8uRoexNV3YGEIsv7w1hXI0cxOsuBdOwVhZxoT+9fe0kIA== X-Received: by 2002:a17:90b:2e4b:b0:2ee:741c:e9f4 with SMTP id 98e67ed59e1d1-308236344acmr2985078a91.11.1744356478300; Fri, 11 Apr 2025 00:27:58 -0700 (PDT) Received: from localhost.localdomain ([240f:74:7be:1:f99c:bbee:3855:787c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-22ac7cda517sm42421105ad.250.2025.04.11.00.27.57 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Apr 2025 00:27:57 -0700 (PDT) From: Koichiro Den To: kernel-team@lists.ubuntu.com Subject: [SRU][N][PATCH 12/14] gpio: aggregator: cancel deferred probe for devices created via configfs Date: Fri, 11 Apr 2025 16:26:48 +0900 Message-ID: <21ddce9f246003bb7cb60dd566e23991e225d2aa.1744350640.git.koichiro.den@canonical.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: <174435057828.183979.10447742120666677608@z790sl> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" BugLink: https://bugs.launchpad.net/bugs/2103496 For aggregators initialized via configfs, write 1 to 'live' waits for probe completion and returns an error if the probe fails, unlike the legacy sysfs interface, which is asynchronous. Since users control the liveness of the aggregator device and might be editing configurations while 'live' is 0, deferred probing is both unnatural and unsafe. Cancel deferred probe for purely configfs-based aggregators when probe fails. Signed-off-by: Koichiro Den Link: https://lore.kernel.org/r/20250407043019.4105613-8-koichiro.den@canonical.com Signed-off-by: Bartosz Golaszewski (cherry picked from commit 0269c768de1b5e430c3f9a6869261606c82abe90 linux-next) Signed-off-by: Koichiro Den --- drivers/gpio/gpio-aggregator.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 6f4333553733..6745692951f9 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -72,6 +72,10 @@ struct gpio_aggregator_line { enum gpio_lookup_flags flags; }; +struct gpio_aggregator_pdev_meta { + bool init_via_sysfs; +}; + static DEFINE_MUTEX(gpio_aggregator_lock); /* protects idr */ static DEFINE_IDR(gpio_aggregator_idr); @@ -1127,6 +1131,7 @@ static int gpio_aggregator_parse(struct gpio_aggregator *aggr) static ssize_t gpio_aggregator_new_device_store(struct device_driver *driver, const char *buf, size_t count) { + struct gpio_aggregator_pdev_meta meta = { .init_via_sysfs = true }; char name[CONFIGFS_ITEM_NAME_LEN]; struct gpio_aggregator *aggr; struct platform_device *pdev; @@ -1177,7 +1182,7 @@ static ssize_t gpio_aggregator_new_device_store(struct device_driver *driver, gpiod_add_lookup_table(aggr->lookups); - pdev = platform_device_register_simple(DRV_NAME, aggr->id, NULL, 0); + pdev = platform_device_register_data(NULL, DRV_NAME, aggr->id, &meta, sizeof(meta)); if (IS_ERR(pdev)) { res = PTR_ERR(pdev); goto remove_table; @@ -1270,7 +1275,9 @@ ATTRIBUTE_GROUPS(gpio_aggregator); static int gpio_aggregator_probe(struct platform_device *pdev) { + struct gpio_aggregator_pdev_meta *meta; struct device *dev = &pdev->dev; + bool init_via_sysfs = false; struct gpio_desc **descs; struct gpiochip_fwd *fwd; unsigned long features; @@ -1284,10 +1291,28 @@ static int gpio_aggregator_probe(struct platform_device *pdev) if (!descs) return -ENOMEM; + meta = dev_get_platdata(&pdev->dev); + if (meta && meta->init_via_sysfs) + init_via_sysfs = true; + for (i = 0; i < n; i++) { descs[i] = devm_gpiod_get_index(dev, NULL, i, GPIOD_ASIS); - if (IS_ERR(descs[i])) + if (IS_ERR(descs[i])) { + /* + * Deferred probing is not suitable when the aggregator + * is created via configfs. They should just retry later + * whenever they like. For device creation via sysfs, + * error is propagated without overriding for backward + * compatibility. .prevent_deferred_probe is kept unset + * for other cases. + */ + if (!init_via_sysfs && !dev_of_node(dev) && + descs[i] == ERR_PTR(-EPROBE_DEFER)) { + pr_warn("Deferred probe canceled for creation via configfs.\n"); + return -ENODEV; + } return PTR_ERR(descs[i]); + } } features = (uintptr_t)device_get_match_data(dev); From patchwork Fri Apr 11 07:26:49 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Koichiro Den X-Patchwork-Id: 2071382 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4ZYpF03bh7z1yJZ for ; Fri, 11 Apr 2025 17:28:04 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1u38oC-00056i-7P; Fri, 11 Apr 2025 07:28:16 +0000 Received: from smtp-relay-internal-1.internal ([10.131.114.114] helo=smtp-relay-internal-1.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1u38nz-00040R-5x for kernel-team@lists.ubuntu.com; Fri, 11 Apr 2025 07:28:03 +0000 Received: from mail-pl1-f200.google.com (mail-pl1-f200.google.com [209.85.214.200]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-1.canonical.com (Postfix) with ESMTPS id 6952B400AF for ; Fri, 11 Apr 2025 07:28:01 +0000 (UTC) Received: by mail-pl1-f200.google.com with SMTP id d9443c01a7336-227ed471999so15315545ad.3 for ; Fri, 11 Apr 2025 00:28:01 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744356480; x=1744961280; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=CZ6kElinfxeAlNz/rA9L6uEGTm7s2zy36MrQb/qdn0I=; b=NAJnuiU9VT6BWstd5v1X8Ud/v8xvIA2iuDTwy/7nf9ddJzIjOS7lauzl7pzWnPkw9g /3GukoC5NWrk1342yJ13yRQxMTnr9NE1HEy1M2nn9gt6rU6+i9N/815uMHMP0Sr6J+JQ TX/+z9EDWkd2avDN1qSbm51+OKJok1MxNPbMJvCYqUUpvt/myaSr7n8ts1+4G/O5Kwet paIIsHoSN+gxsS2i8DL/hH5jlIZP1YXsugpXFNCHgpREZ2Sju4hcLbrW3HjRpwiWgGr8 yCFxwRcilKmc9wiI6XwDxApixDIX9uExOvUpIb3+4Ed75aEVwc4Vwp4B59U1HwlCbZiT 1QVA== X-Gm-Message-State: AOJu0YwtlvKyQCiZ5/Isc0K7fXX97XAXRVS8N4TA76jI4Y5nzVDKOnlw 3cLd5A/Yh1xkPg14HoeF8N1aZfIS8w4Z9js/U7B90WHT3htPOhdiP89x58mjA9Zj0Ge55M/SRO4 uR0/EYpx68iomb0NRsHIgBZQITABtPboTICE5hm4641fnOcAuNQsC9PVrBa5MvjxnUMkZ4g+WtO cqxP1Y77JTgg== X-Gm-Gg: ASbGnctvkUjFwydXoOtHBfYH/6alcCk3E5dBJBvzkeBQ6/i6EkX3mJO6IJXLECXsSzj 56yxUOo7QeKFCzvTe5RvE4DsEo43ZuasVGp0jDAFg/+DcosKuL51mT7+IQBB9Cjxm0zJRCe+8r2 CRcksdpHpuXs46JgXLNzRz4gBsIs6R2MxFEoYilG8Xxgt+kSg+Z9ETItTRKwIJKrtOit7Zwf08J 6KsnZD91oga/MAa+00jQqFb8qmp9RAps1C+59fa2/Sgtwd6Jz5Uci4kxZblOWGY6DP9a/InvrfM 1mvKKexE20PMGNbRBQ4bxsf7z19uPg== X-Received: by 2002:a17:903:1b23:b0:215:89a0:416f with SMTP id d9443c01a7336-22bea4bd55bmr28191235ad.30.1744356479912; Fri, 11 Apr 2025 00:27:59 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEKteA8FovJGfaQeWzyFUkwrw78DqSNAgU4dogSbQuVStGMuUC6+GQVQlS20OHOCJfWUsIlZg== X-Received: by 2002:a17:903:1b23:b0:215:89a0:416f with SMTP id d9443c01a7336-22bea4bd55bmr28191075ad.30.1744356479553; Fri, 11 Apr 2025 00:27:59 -0700 (PDT) Received: from localhost.localdomain ([240f:74:7be:1:f99c:bbee:3855:787c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-22ac7cda517sm42421105ad.250.2025.04.11.00.27.58 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Apr 2025 00:27:59 -0700 (PDT) From: Koichiro Den To: kernel-team@lists.ubuntu.com Subject: [SRU][N][PATCH 13/14] Documentation: gpio: document configfs interface for gpio-aggregator Date: Fri, 11 Apr 2025 16:26:49 +0900 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: <174435057828.183979.10447742120666677608@z790sl> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" BugLink: https://bugs.launchpad.net/bugs/2103496 Add documentation for the newly added configfs-based interface for GPIO aggregator. Signed-off-by: Koichiro Den Link: https://lore.kernel.org/r/20250407043019.4105613-9-koichiro.den@canonical.com Signed-off-by: Bartosz Golaszewski (cherry picked from commit 10f94d092bba9ab08004c624c604e976e6e3cd22 linux-next) Signed-off-by: Koichiro Den --- .../admin-guide/gpio/gpio-aggregator.rst | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/Documentation/admin-guide/gpio/gpio-aggregator.rst b/Documentation/admin-guide/gpio/gpio-aggregator.rst index 5cd1e7221756..8374a9df9105 100644 --- a/Documentation/admin-guide/gpio/gpio-aggregator.rst +++ b/Documentation/admin-guide/gpio/gpio-aggregator.rst @@ -69,6 +69,113 @@ write-only attribute files in sysfs. $ echo gpio-aggregator.0 > delete_device +Aggregating GPIOs using Configfs +-------------------------------- + +**Group:** ``/config/gpio-aggregator`` + + This is the root directory of the gpio-aggregator configfs tree. + +**Group:** ``/config/gpio-aggregator/`` + + This directory represents a GPIO aggregator device. You can assign any + name to ```` (e.g. ``agg0``), except names starting with + ``_sysfs`` prefix, which are reserved for auto-generated configfs + entries corresponding to devices created via Sysfs. + +**Attribute:** ``/config/gpio-aggregator//live`` + + The ``live`` attribute allows to trigger the actual creation of the device + once it's fully configured. Accepted values are: + + * ``1``, ``yes``, ``true`` : enable the virtual device + * ``0``, ``no``, ``false`` : disable the virtual device + +**Attribute:** ``/config/gpio-aggregator//dev_name`` + + The read-only ``dev_name`` attribute exposes the name of the device as it + will appear in the system on the platform bus (e.g. ``gpio-aggregator.0``). + This is useful for identifying a character device for the newly created + aggregator. If it's ``gpio-aggregator.0``, + ``/sys/devices/platform/gpio-aggregator.0/gpiochipX`` path tells you that the + GPIO device id is ``X``. + +You must create subdirectories for each virtual line you want to +instantiate, named exactly as ``line0``, ``line1``, ..., ``lineY``, when +you want to instantiate ``Y+1`` (Y >= 0) lines. Configure all lines before +activating the device by setting ``live`` to 1. + +**Group:** ``/config/gpio-aggregator///`` + + This directory represents a GPIO line to include in the aggregator. + +**Attribute:** ``/config/gpio-aggregator///key`` + +**Attribute:** ``/config/gpio-aggregator///offset`` + + The default values after creating the ```` directory are: + + * ``key`` : + * ``offset`` : -1 + + ``key`` must always be explicitly configured, while ``offset`` depends. + Two configuration patterns exist for each ````: + + (a). For lookup by GPIO line name: + + * Set ``key`` to the line name. + * Ensure ``offset`` remains -1 (the default). + + (b). For lookup by GPIO chip name and the line offset within the chip: + + * Set ``key`` to the chip name. + * Set ``offset`` to the line offset (0 <= ``offset`` < 65535). + +**Attribute:** ``/config/gpio-aggregator///name`` + + The ``name`` attribute sets a custom name for lineY. If left unset, the + line will remain unnamed. + +Once the configuration is done, the ``'live'`` attribute must be set to 1 +in order to instantiate the aggregator device. It can be set back to 0 to +destroy the virtual device. The module will synchronously wait for the new +aggregator device to be successfully probed and if this doesn't happen, writing +to ``'live'`` will result in an error. This is a different behaviour from the +case when you create it using sysfs ``new_device`` interface. + +.. note:: + + For aggregators created via Sysfs, the configfs entries are + auto-generated and appear as ``/config/gpio-aggregator/_sysfs./``. You + cannot add or remove line directories with mkdir(2)/rmdir(2). To modify + lines, you must use the "delete_device" interface to tear down the + existing device and reconfigure it from scratch. However, you can still + toggle the aggregator with the ``live`` attribute and adjust the + ``key``, ``offset``, and ``name`` attributes for each line when ``live`` + is set to 0 by hand (i.e. it's not waiting for deferred probe). + +Sample configuration commands +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: sh + + # Create a directory for an aggregator device + $ mkdir /sys/kernel/config/gpio-aggregator/agg0 + + # Configure each line + $ mkdir /sys/kernel/config/gpio-aggregator/agg0/line0 + $ echo gpiochip0 > /sys/kernel/config/gpio-aggregator/agg0/line0/key + $ echo 6 > /sys/kernel/config/gpio-aggregator/agg0/line0/offset + $ echo test0 > /sys/kernel/config/gpio-aggregator/agg0/line0/name + $ mkdir /sys/kernel/config/gpio-aggregator/agg0/line1 + $ echo gpiochip0 > /sys/kernel/config/gpio-aggregator/agg0/line1/key + $ echo 7 > /sys/kernel/config/gpio-aggregator/agg0/line1/offset + $ echo test1 > /sys/kernel/config/gpio-aggregator/agg0/line1/name + + # Activate the aggregator device + $ echo 1 > /sys/kernel/config/gpio-aggregator/agg0/live + + Generic GPIO Driver ------------------- From patchwork Fri Apr 11 07:26:50 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Koichiro Den X-Patchwork-Id: 2071383 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4ZYpF12kRsz1yLl for ; Fri, 11 Apr 2025 17:28:05 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1u38oC-0005Cx-Ux; Fri, 11 Apr 2025 07:28:16 +0000 Received: from smtp-relay-internal-1.internal ([10.131.114.114] helo=smtp-relay-internal-1.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1u38o1-00046I-Co for kernel-team@lists.ubuntu.com; Fri, 11 Apr 2025 07:28:05 +0000 Received: from mail-pl1-f198.google.com (mail-pl1-f198.google.com [209.85.214.198]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-1.canonical.com (Postfix) with ESMTPS id 6AF9B40139 for ; Fri, 11 Apr 2025 07:28:03 +0000 (UTC) Received: by mail-pl1-f198.google.com with SMTP id d9443c01a7336-224364f2492so14193555ad.3 for ; Fri, 11 Apr 2025 00:28:03 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744356482; x=1744961282; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=IZ/lLH1g7ZBdFIghO7vkn0UTastMX5NLJd4EZFr6sDA=; b=LbiwOU6QuDt4DUo1Ur/dP/FIeRCRMNp5JlSI+NnE/vPTl53YkYJf2Ar/whwsG9YkSZ xBax859anXDRbQQePItNPecQmIRi136t5hM4FpfyATqecirBdntXGmfGcyDH3lyeQjsj vtWIpsyuobzR31oFYm6UoXruhbiq2FaWMGmRdvk7EZ5z6+GTR12EzKrvSUk1yEnrzfPD lYdYg7WDjYQyOStF3FNd1TTZs4h8gdhw4JicdVPz8EkmFijI4X/ImkwYsjiNAApW+Lh7 4NUwZnHABXZBcS/fBzx/8MKlJtqehSaGg2a38YFmygOzjOyfdS5f/mHPcRM80AhfJi7Y K51A== X-Gm-Message-State: AOJu0YwJAIexyg6cgRJNbFn0TNLVXRrYBOueO5rM6+UK87EcUfsio925 qWOoYp5/PorXGVpEeAMMnn1T8XMWg5sOuuEbuCNVtccDIkImiaIxwXhzxtI8SSQ5b23UOHQztaE MKvpo9zVlT0vcuxGw6FuyDsv+V+WTKpg8JJR6xztwt5RDlQi32MqlYSI19WRZKSvjH/mIq2f4le 8X+A3LChS8GA== X-Gm-Gg: ASbGnctpjW7EP58jFfoJp7qwGwZffC+l5WENJPZqEUSgi8UdoddZaZYGs1NXSqg52SZ aSsr3wo7XGlxg9gjWCafFT5d22gFCSDlZP7aK6tx6O32UdSpp3PiC6f9TVXmqQM35VRN7ZdYfew qwEUVv0y37baNRBTEJ2zQsVnlum/SybCt66huylLfJf2eIomHPf8s0PMKMcm9wtWCv8Gu9//OrI b04JP97z3z9UZ+d/Xgv1dNmfYxiis3nTInoU4kF8Ut/tNG+vjICueRAFLSKFajnOuvbj8ZpwZnE xrYeurEU9pqRVeNgmJlR6h1qCpKbeA== X-Received: by 2002:a17:903:17ce:b0:223:f408:c3f8 with SMTP id d9443c01a7336-22bea4b34a7mr27312295ad.14.1744356481570; Fri, 11 Apr 2025 00:28:01 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGjSbVODWtRI6AfPv7tnByLCFv7o9fmQ94riK92/ZHOgFzwcwbi1We0vjmpfOEZDHi7NbJ6jA== X-Received: by 2002:a17:903:17ce:b0:223:f408:c3f8 with SMTP id d9443c01a7336-22bea4b34a7mr27311795ad.14.1744356480801; Fri, 11 Apr 2025 00:28:00 -0700 (PDT) Received: from localhost.localdomain ([240f:74:7be:1:f99c:bbee:3855:787c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-22ac7cda517sm42421105ad.250.2025.04.11.00.27.59 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Apr 2025 00:28:00 -0700 (PDT) From: Koichiro Den To: kernel-team@lists.ubuntu.com Subject: [SRU][N][PATCH 14/14] selftests: gpio: add test cases for gpio-aggregator Date: Fri, 11 Apr 2025 16:26:50 +0900 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: <174435057828.183979.10447742120666677608@z790sl> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" BugLink: https://bugs.launchpad.net/bugs/2103496 Add a set of tests for gpio-aggregator module. This test covers both pre-existing new_device/delete_device interface and new configfs-based interface. Signed-off-by: Koichiro Den Link: https://lore.kernel.org/r/20250407043019.4105613-10-koichiro.den@canonical.com Signed-off-by: Bartosz Golaszewski (cherry picked from commit 6d7f0c1103ef3935eb3f302d09af4ef9e85212a3 linux-next) Signed-off-by: Koichiro Den --- tools/testing/selftests/gpio/Makefile | 2 +- tools/testing/selftests/gpio/config | 1 + .../testing/selftests/gpio/gpio-aggregator.sh | 723 ++++++++++++++++++ 3 files changed, 725 insertions(+), 1 deletion(-) create mode 100755 tools/testing/selftests/gpio/gpio-aggregator.sh diff --git a/tools/testing/selftests/gpio/Makefile b/tools/testing/selftests/gpio/Makefile index e0884390447d..7bfe315f7001 100644 --- a/tools/testing/selftests/gpio/Makefile +++ b/tools/testing/selftests/gpio/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 -TEST_PROGS := gpio-mockup.sh gpio-sim.sh +TEST_PROGS := gpio-mockup.sh gpio-sim.sh gpio-aggregator.sh TEST_FILES := gpio-mockup-sysfs.sh TEST_GEN_PROGS_EXTENDED := gpio-mockup-cdev gpio-chip-info gpio-line-name CFLAGS += -O2 -g -Wall $(KHDR_INCLUDES) diff --git a/tools/testing/selftests/gpio/config b/tools/testing/selftests/gpio/config index 409a8532facc..1287abeaac7e 100644 --- a/tools/testing/selftests/gpio/config +++ b/tools/testing/selftests/gpio/config @@ -2,3 +2,4 @@ CONFIG_GPIOLIB=y CONFIG_GPIO_CDEV=y CONFIG_GPIO_MOCKUP=m CONFIG_GPIO_SIM=m +CONFIG_GPIO_AGGREGATOR=m diff --git a/tools/testing/selftests/gpio/gpio-aggregator.sh b/tools/testing/selftests/gpio/gpio-aggregator.sh new file mode 100755 index 000000000000..f1bab62c4cd2 --- /dev/null +++ b/tools/testing/selftests/gpio/gpio-aggregator.sh @@ -0,0 +1,723 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 Bartosz Golaszewski +# Copyright (C) 2025 Koichiro Den + +BASE_DIR=$(dirname "$0") +CONFIGFS_SIM_DIR="/sys/kernel/config/gpio-sim" +CONFIGFS_AGG_DIR="/sys/kernel/config/gpio-aggregator" +SYSFS_AGG_DIR="/sys/bus/platform/drivers/gpio-aggregator" +MODULE="gpio-aggregator" + +fail() { + echo "$*" >&2 + echo "GPIO $MODULE test FAIL" + exit 1 +} + +skip() { + echo "$*" >&2 + echo "GPIO $MODULE test SKIP" + exit 4 +} + +# gpio-sim +sim_enable_chip() { + local CHIP=$1 + + echo 1 > "$CONFIGFS_SIM_DIR/$CHIP/live" || fail "Unable to enable the chip" +} + +sim_disable_chip() { + local CHIP=$1 + + echo 0 > "$CONFIGFS_SIM_DIR/$CHIP/live" || fail "Unable to disable the chip" +} + +sim_configfs_cleanup() { + local NOCHECK=${1:-0} + + for CHIP_DIR in "$CONFIGFS_SIM_DIR"/*; do + [ -d "$CHIP_DIR" ] || continue + echo 0 > "$CHIP_DIR/live" + find "$CHIP_DIR" -depth -type d -exec rmdir {} \; + done + [ "$NOCHECK" -eq 1 ] && return; + remaining=$(find "$CONFIGFS_SIM_DIR" -mindepth 1 -type d 2> /dev/null) + if [ -n "$remaining" ]; then + fail "Directories remain in $CONFIGFS_SIM_DIR: $remaining" + fi +} + +sim_get_chip_label() { + local CHIP=$1 + local BANK=$2 + local CHIP_NAME=$(cat "$CONFIGFS_SIM_DIR/$CHIP/$BANK/chip_name" 2> /dev/null) || \ + fail "Unable to read the chip name from configfs" + + $BASE_DIR/gpio-chip-info "/dev/$CHIP_NAME" label || \ + fail "Unable to read the chip label from the character device" +} + +# gpio-aggregator +agg_create_chip() { + local CHIP=$1 + + mkdir "$CONFIGFS_AGG_DIR/$CHIP" +} + +agg_remove_chip() { + local CHIP=$1 + + find "$CONFIGFS_AGG_DIR/$CHIP/" -depth -type d -exec rmdir {} \; || \ + fail "Unable to remove $CONFIGFS_AGG_DIR/$CHIP" +} + +agg_create_line() { + local CHIP=$1 + local LINE=$2 + + mkdir "$CONFIGFS_AGG_DIR/$CHIP/$LINE" +} + +agg_remove_line() { + local CHIP=$1 + local LINE=$2 + + rmdir "$CONFIGFS_AGG_DIR/$CHIP/$LINE" +} + +agg_set_key() { + local CHIP=$1 + local LINE=$2 + local KEY=$3 + + echo "$KEY" > "$CONFIGFS_AGG_DIR/$CHIP/$LINE/key" || fail "Unable to set the lookup key" +} + +agg_set_offset() { + local CHIP=$1 + local LINE=$2 + local OFFSET=$3 + + echo "$OFFSET" > "$CONFIGFS_AGG_DIR/$CHIP/$LINE/offset" || \ + fail "Unable to set the lookup offset" +} + +agg_set_line_name() { + local CHIP=$1 + local LINE=$2 + local NAME=$3 + + echo "$NAME" > "$CONFIGFS_AGG_DIR/$CHIP/$LINE/name" || fail "Unable to set the line name" +} + +agg_enable_chip() { + local CHIP=$1 + + echo 1 > "$CONFIGFS_AGG_DIR/$CHIP/live" || fail "Unable to enable the chip" +} + +agg_disable_chip() { + local CHIP=$1 + + echo 0 > "$CONFIGFS_AGG_DIR/$CHIP/live" || fail "Unable to disable the chip" +} + +agg_configfs_cleanup() { + local NOCHECK=${1:-0} + + for CHIP_DIR in "$CONFIGFS_AGG_DIR"/*; do + [ -d "$CHIP_DIR" ] || continue + echo 0 > "$CHIP_DIR/live" 2> /dev/null + find "$CHIP_DIR" -depth -type d -exec rmdir {} \; + done + [ "$NOCHECK" -eq 1 ] && return; + remaining=$(find "$CONFIGFS_AGG_DIR" -mindepth 1 -type d 2> /dev/null) + if [ -n "$remaining" ]; then + fail "Directories remain in $CONFIGFS_AGG_DIR: $remaining" + fi +} + +agg_configfs_dev_name() { + local CHIP=$1 + + cat "$CONFIGFS_AGG_DIR/$CHIP/dev_name" 2> /dev/null || \ + fail "Unable to read the device name from configfs" +} + +agg_configfs_chip_name() { + local CHIP=$1 + local DEV_NAME=$(agg_configfs_dev_name "$CHIP") + local CHIP_LIST=$(find "/sys/devices/platform/$DEV_NAME" \ + -maxdepth 1 -type d -name "gpiochip[0-9]*" 2> /dev/null) + local CHIP_COUNT=$(echo "$CHIP_LIST" | wc -l) + + if [ -z "$CHIP_LIST" ]; then + fail "No gpiochip in /sys/devices/platform/$DEV_NAME/" + elif [ "$CHIP_COUNT" -ne 1 ]; then + fail "Multiple gpiochips unexpectedly found: $CHIP_LIST" + fi + basename "$CHIP_LIST" +} + +agg_get_chip_num_lines() { + local CHIP=$1 + local N_DIR=$(ls -d $CONFIGFS_AGG_DIR/$CHIP/line[0-9]* 2> /dev/null | wc -l) + local N_LINES + + if [ "$(cat $CONFIGFS_AGG_DIR/$CHIP/live)" = 0 ]; then + echo "$N_DIR" + else + N_LINES=$( + $BASE_DIR/gpio-chip-info \ + "/dev/$(agg_configfs_chip_name "$CHIP")" num-lines + ) || fail "Unable to read the number of lines from the character device" + if [ $N_DIR != $N_LINES ]; then + fail "Discrepancy between two sources for the number of lines" + fi + echo "$N_LINES" + fi +} + +agg_get_chip_label() { + local CHIP=$1 + + $BASE_DIR/gpio-chip-info "/dev/$(agg_configfs_chip_name "$CHIP")" label || \ + fail "Unable to read the chip label from the character device" +} + +agg_get_line_name() { + local CHIP=$1 + local OFFSET=$2 + local NAME_CONFIGFS=$(cat "$CONFIGFS_AGG_DIR/$CHIP/line${OFFSET}/name") + local NAME_CDEV + + if [ "$(cat "$CONFIGFS_AGG_DIR/$CHIP/live")" = 0 ]; then + echo "$NAME_CONFIGFS" + else + NAME_CDEV=$( + $BASE_DIR/gpio-line-name \ + "/dev/$(agg_configfs_chip_name "$CHIP")" "$OFFSET" + ) || fail "Unable to read the line name from the character device" + if [ "$NAME_CONFIGFS" != "$NAME_CDEV" ]; then + fail "Discrepancy between two sources for the name of line" + fi + echo "$NAME_CDEV" + fi +} + + +# Load the modules. This will pull in configfs if needed too. +modprobe gpio-sim || skip "unable to load the gpio-sim module" +modprobe gpio-aggregator || skip "unable to load the gpio-aggregator module" + +# Make sure configfs is mounted at /sys/kernel/config. Wait a bit if needed. +for IDX in $(seq 5); do + if [ "$IDX" -eq "5" ]; then + skip "configfs not mounted at /sys/kernel/config" + fi + + mountpoint -q /sys/kernel/config && break + sleep 0.1 +done + +# If the module was already loaded: remove all previous chips +agg_configfs_cleanup +sim_configfs_cleanup + +trap "exit 1" SIGTERM SIGINT +trap "agg_configfs_cleanup 1; sim_configfs_cleanup 1" EXIT + +# Use gpio-sim chips as the test backend +for CHIP in $(seq -f "chip%g" 0 1); do + mkdir $CONFIGFS_SIM_DIR/$CHIP + for BANK in $(seq -f "bank%g" 0 1); do + mkdir -p "$CONFIGFS_SIM_DIR/$CHIP/$BANK" + echo "${CHIP}_${BANK}" > "$CONFIGFS_SIM_DIR/$CHIP/$BANK/label" || \ + fail "unable to set the chip label" + echo 16 > "$CONFIGFS_SIM_DIR/$CHIP/$BANK/num_lines" || \ + fail "unable to set the number of lines" + for IDX in $(seq 0 15); do + LINE_NAME="${CHIP}${BANK}_${IDX}" + LINE_DIR="$CONFIGFS_SIM_DIR/$CHIP/$BANK/line$IDX" + mkdir -p $LINE_DIR + echo "$LINE_NAME" > "$LINE_DIR/name" || fail "unable to set the line name" + done + done + sim_enable_chip "$CHIP" +done + +echo "1. GPIO aggregator creation/deletion" + +echo "1.1. Creation/deletion via configfs" + +echo "1.1.1. Minimum creation/deletion" +agg_create_chip agg0 +agg_create_line agg0 line0 +agg_set_key agg0 line0 "$(sim_get_chip_label chip0 bank0)" +agg_set_offset agg0 line0 5 +agg_set_line_name agg0 line0 test0 +agg_enable_chip agg0 +test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 1 || fail "chip unexpectedly dead" +test "$(agg_get_chip_label agg0)" = "$(agg_configfs_dev_name agg0)" || \ + fail "label is inconsistent" +test "$(agg_get_chip_num_lines agg0)" = "1" || fail "number of lines is not 1" +test "$(agg_get_line_name agg0 0)" = "test0" || fail "line name is unset" +agg_disable_chip agg0 +agg_remove_line agg0 line0 +agg_remove_chip agg0 + +echo "1.1.2. Complex creation/deletion" +agg_create_chip agg0 +agg_create_line agg0 line0 +agg_create_line agg0 line1 +agg_create_line agg0 line2 +agg_create_line agg0 line3 +agg_set_key agg0 line0 "$(sim_get_chip_label chip0 bank0)" +agg_set_key agg0 line1 "$(sim_get_chip_label chip0 bank1)" +agg_set_key agg0 line2 "$(sim_get_chip_label chip1 bank0)" +agg_set_key agg0 line3 "$(sim_get_chip_label chip1 bank1)" +agg_set_offset agg0 line0 1 +agg_set_offset agg0 line1 3 +agg_set_offset agg0 line2 5 +agg_set_offset agg0 line3 7 +agg_set_line_name agg0 line0 test0 +agg_set_line_name agg0 line1 test1 +agg_set_line_name agg0 line2 test2 +agg_set_line_name agg0 line3 test3 +agg_enable_chip agg0 +test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 1 || fail "chip unexpectedly dead" +test "$(agg_get_chip_label agg0)" = "$(agg_configfs_dev_name agg0)" || \ + fail "label is inconsistent" +test "$(agg_get_chip_num_lines agg0)" = "4" || fail "number of lines is not 1" +test "$(agg_get_line_name agg0 0)" = "test0" || fail "line name is unset" +test "$(agg_get_line_name agg0 1)" = "test1" || fail "line name is unset" +test "$(agg_get_line_name agg0 2)" = "test2" || fail "line name is unset" +test "$(agg_get_line_name agg0 3)" = "test3" || fail "line name is unset" +agg_disable_chip agg0 +agg_remove_line agg0 line0 +agg_remove_line agg0 line1 +agg_remove_line agg0 line2 +agg_remove_line agg0 line3 +agg_remove_chip agg0 + +echo "1.1.3. Can't instantiate a chip without any line" +agg_create_chip agg0 +echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled" +test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 0 || fail "chip unexpectedly alive" +agg_remove_chip agg0 + +echo "1.1.4. Can't instantiate a chip with invalid configuration" +agg_create_chip agg0 +agg_create_line agg0 line0 +agg_set_key agg0 line0 "chipX_bankX" +agg_set_offset agg0 line0 99 +agg_set_line_name agg0 line0 test0 +echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled" +test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 0 || fail "chip unexpectedly alive" +agg_remove_line agg0 line0 +agg_remove_chip agg0 + +echo "1.1.5. Can't instantiate a chip asynchronously via deferred probe" +agg_create_chip agg0 +agg_create_line agg0 line0 +agg_set_key agg0 line0 "chip0_bank0" +agg_set_offset agg0 line0 5 +agg_set_line_name agg0 line0 test0 +sim_disable_chip chip0 +echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled" +test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 0 || fail "chip unexpectedly alive" +sim_enable_chip chip0 +sleep 1 +test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 0 || \ + fail "chip unexpectedly transitioned to 'live' state" +agg_remove_line agg0 line0 +agg_remove_chip agg0 + +echo "1.2. Creation/deletion via sysfs" + +echo "1.2.1. Minimum creation/deletion" +echo "chip0_bank0 0" > "$SYSFS_AGG_DIR/new_device" +CHIPNAME=$(agg_configfs_chip_name _sysfs.0) +test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 1 || fail "chip unexpectedly dead" +test "$(agg_get_chip_label _sysfs.0)" = "$(agg_configfs_dev_name _sysfs.0)" || \ + fail "label is inconsistent" +test "$(agg_get_chip_num_lines _sysfs.0)" = "1" || fail "number of lines is not 1" +test "$(agg_get_line_name _sysfs.0 0)" = "" || fail "line name is unset" +echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device" +test -d $CONFIGFS_AGG_DIR/_sysfs.0 && fail "_sysfs.0 unexpectedly remains" +test -d /dev/${CHIPNAME} && fail "/dev/${CHIPNAME} unexpectedly remains" + +echo "1.2.2. Complex creation/deletion" +echo "chip0bank0_0 chip1_bank1 10-11" > "$SYSFS_AGG_DIR/new_device" +CHIPNAME=$(agg_configfs_chip_name _sysfs.0) +test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 1 || fail "chip unexpectedly dead" +test "$(agg_get_chip_label _sysfs.0)" = "$(agg_configfs_dev_name _sysfs.0)" || \ + fail "label is inconsistent" +test "$(agg_get_chip_num_lines _sysfs.0)" = "3" || fail "number of lines is not 3" +test "$(agg_get_line_name _sysfs.0 0)" = "" || fail "line name is unset" +test "$(agg_get_line_name _sysfs.0 1)" = "" || fail "line name is unset" +test "$(agg_get_line_name _sysfs.0 2)" = "" || fail "line name is unset" +echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device" +test -d $CONFIGFS_AGG_DIR/_sysfs.0 && fail "_sysfs.0 unexpectedly remains" +test -d /dev/${CHIPNAME} && fail "/dev/${CHIPNAME} unexpectedly remains" + +echo "1.2.3. Asynchronous creation with deferred probe" +sim_disable_chip chip0 +echo 'chip0_bank0 0' > $SYSFS_AGG_DIR/new_device +sleep 1 +test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 0 || fail "chip unexpectedly alive" +sim_enable_chip chip0 +sleep 1 +CHIPNAME=$(agg_configfs_chip_name _sysfs.0) +test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 1 || fail "chip unexpectedly remains dead" +test "$(agg_get_chip_label _sysfs.0)" = "$(agg_configfs_dev_name _sysfs.0)" || \ + fail "label is inconsistent" +test "$(agg_get_chip_num_lines _sysfs.0)" = "1" || fail "number of lines is not 1" +test "$(agg_get_line_name _sysfs.0 0)" = "" || fail "line name unexpectedly set" +echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device" +test -d $CONFIGFS_AGG_DIR/_sysfs.0 && fail "_sysfs.0 unexpectedly remains" +test -d /dev/${CHIPNAME} && fail "/dev/${CHIPNAME} unexpectedly remains" + +echo "1.2.4. Can't instantiate a chip with invalid configuration" +echo "xyz 0" > "$SYSFS_AGG_DIR/new_device" +test "$(cat $CONFIGFS_AGG_DIR/_sysfs.0/live)" = 0 || fail "chip unexpectedly alive" +echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device" + +echo "2. GPIO aggregator configuration" + +echo "2.1. Configuring aggregators instantiated via configfs" +setup_2_1() { + agg_create_chip agg0 + agg_create_line agg0 line0 + agg_create_line agg0 line1 + agg_set_key agg0 line0 "$(sim_get_chip_label chip0 bank0)" + agg_set_key agg0 line1 "$(sim_get_chip_label chip1 bank0)" + agg_set_offset agg0 line0 1 + agg_set_offset agg0 line1 3 + agg_set_line_name agg0 line0 test0 + agg_set_line_name agg0 line1 test1 + agg_enable_chip agg0 +} +teardown_2_1() { + agg_configfs_cleanup +} + +echo "2.1.1. While offline" + +echo "2.1.1.1. Line can be added/removed" +setup_2_1 +agg_disable_chip agg0 +agg_create_line agg0 line2 +agg_set_key agg0 line2 "$(sim_get_chip_label chip0 bank1)" +agg_set_offset agg0 line2 5 +agg_enable_chip agg0 +test "$(agg_get_chip_num_lines agg0)" = "3" || fail "number of lines is not 1" +teardown_2_1 + +echo "2.1.1.2. Line key can be modified" +setup_2_1 +agg_disable_chip agg0 +agg_set_key agg0 line0 "$(sim_get_chip_label chip0 bank1)" +agg_set_key agg0 line1 "$(sim_get_chip_label chip1 bank1)" +agg_enable_chip agg0 +teardown_2_1 + +echo "2.1.1.3. Line name can be modified" +setup_2_1 +agg_disable_chip agg0 +agg_set_line_name agg0 line0 new0 +agg_set_line_name agg0 line1 new1 +agg_enable_chip agg0 +test "$(agg_get_line_name agg0 0)" = "new0" || fail "line name is unset" +test "$(agg_get_line_name agg0 1)" = "new1" || fail "line name is unset" +teardown_2_1 + +echo "2.1.1.4. Line offset can be modified" +setup_2_1 +agg_disable_chip agg0 +agg_set_offset agg0 line0 5 +agg_set_offset agg0 line1 7 +agg_enable_chip agg0 +teardown_2_1 + +echo "2.1.1.5. Can re-enable a chip after valid reconfiguration" +setup_2_1 +agg_disable_chip agg0 +agg_set_key agg0 line0 "$(sim_get_chip_label chip1 bank1)" +agg_set_offset agg0 line0 15 +agg_set_key agg0 line1 "$(sim_get_chip_label chip0 bank1)" +agg_set_offset agg0 line0 14 +agg_create_line agg0 line2 +agg_set_key agg0 line2 "$(sim_get_chip_label chip0 bank1)" +agg_set_offset agg0 line2 13 +agg_enable_chip agg0 +test "$(agg_get_chip_num_lines agg0)" = "3" || fail "number of lines is not 1" +teardown_2_1 + +echo "2.1.1.7. Can't re-enable a chip with invalid reconfiguration" +setup_2_1 +agg_disable_chip agg0 +agg_set_key agg0 line0 invalidkey +echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled" +teardown_2_1 +setup_2_1 +agg_disable_chip agg0 +agg_set_offset agg0 line0 99 +echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled" +teardown_2_1 + +echo "2.1.2. While online" + +echo "2.1.2.1. Can't add/remove line" +setup_2_1 +mkdir "$CONFIGFS_AGG_DIR/agg0/line2" 2> /dev/null && fail "line unexpectedly added" +rmdir "$CONFIGFS_AGG_DIR/agg0/line1" 2> /dev/null && fail "line unexpectedly removed" +teardown_2_1 + +echo "2.1.2.2. Can't modify line key" +setup_2_1 +echo "chip1_bank1" > "$CONFIGFS_AGG_DIR/agg0/line0/key" 2> /dev/null && \ + fail "lookup key unexpectedly updated" +teardown_2_1 + +echo "2.1.2.3. Can't modify line name" +setup_2_1 +echo "new0" > "$CONFIGFS_AGG_DIR/agg0/line0/name" 2> /dev/null && \ + fail "name unexpectedly updated" +teardown_2_1 + +echo "2.1.2.4. Can't modify line offset" +setup_2_1 +echo "5" > "$CONFIGFS_AGG_DIR/agg0/line0/offset" 2> /dev/null && \ + fail "offset unexpectedly updated" +teardown_2_1 + +echo "2.2. Configuring aggregators instantiated via sysfs" +setup_2_2() { + echo "chip0_bank0 1 chip1_bank0 3" > "$SYSFS_AGG_DIR/new_device" +} +teardown_2_2() { + echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device" +} + +echo "2.2.1. While online" + +echo "2.2.1.1. Can toggle live" +setup_2_2 +agg_disable_chip _sysfs.0 +agg_enable_chip _sysfs.0 +teardown_2_2 + +echo "2.2.1.2. Can't add/remove line" +setup_2_2 +mkdir "$CONFIGFS_AGG_DIR/_sysfs.0/line2" 2> /dev/null && fail "line unexpectedly added" +rmdir "$CONFIGFS_AGG_DIR/_sysfs.0/line1" 2> /dev/null && fail "line unexpectedly removed" +teardown_2_2 + +echo "2.2.1.3. Can't modify line key" +setup_2_2 +echo "chip1_bank1" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/key" 2> /dev/null && \ + fail "lookup key unexpectedly updated" +teardown_2_2 + +echo "2.2.1.4. Can't modify line name" +setup_2_2 +echo "new0" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/name" 2> /dev/null && \ + fail "name unexpectedly updated" +teardown_2_2 + +echo "2.2.1.5. Can't modify line offset" +setup_2_2 +echo "5" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/offset" 2> /dev/null && \ + fail "offset unexpectedly updated" +teardown_2_2 + +echo "2.2.2. While waiting for deferred probe" + +echo "2.2.2.1. Can't add/remove line despite live = 0" +sim_disable_chip chip0 +setup_2_2 +mkdir "$CONFIGFS_AGG_DIR/_sysfs.0/line2" 2> /dev/null && fail "line unexpectedly added" +rmdir "$CONFIGFS_AGG_DIR/_sysfs.0/line1" 2> /dev/null && fail "line unexpectedly removed" +teardown_2_2 +sim_enable_chip chip0 + +echo "2.2.2.2. Can't modify line key" +sim_disable_chip chip0 +setup_2_2 +echo "chip1_bank1" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/key" 2> /dev/null && \ + fail "lookup key unexpectedly updated" +teardown_2_2 +sim_enable_chip chip0 + +echo "2.2.2.3. Can't modify line name" +sim_disable_chip chip0 +setup_2_2 +echo "new0" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/name" 2> /dev/null && \ + fail "name unexpectedly updated" +teardown_2_2 +sim_enable_chip chip0 + +echo "2.2.2.4. Can't modify line offset" +sim_disable_chip chip0 +setup_2_2 +echo 5 > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/offset" 2> /dev/null && \ + fail "offset unexpectedly updated" +teardown_2_2 +sim_enable_chip chip0 + +echo "2.2.2.5. Can't toggle live" +sim_disable_chip chip0 +setup_2_2 +test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 0 || fail "chip unexpectedly alive" +echo 1 > "$CONFIGFS_AGG_DIR/_sysfs.0/live" 2> /dev/null && fail "chip unexpectedly enabled" +teardown_2_2 +sim_enable_chip chip0 + +echo "2.2.3. While offline" + +echo "2.2.3.1. Can't add/remove line despite live = 0" +setup_2_2 +agg_disable_chip _sysfs.0 +mkdir "$CONFIGFS_AGG_DIR/_sysfs.0/line2" 2> /dev/null && fail "line unexpectedly added" +rmdir "$CONFIGFS_AGG_DIR/_sysfs.0/line1" 2> /dev/null && fail "line unexpectedly removed" +teardown_2_2 + +echo "2.2.3.2. Line key can be modified" +setup_2_2 +agg_disable_chip _sysfs.0 +agg_set_key _sysfs.0 line0 "$(sim_get_chip_label chip0 bank1)" +agg_set_key _sysfs.0 line1 "$(sim_get_chip_label chip1 bank1)" +agg_enable_chip _sysfs.0 +teardown_2_2 + +echo "2.2.3.3. Line name can be modified" +setup_2_2 +agg_disable_chip _sysfs.0 +agg_set_line_name _sysfs.0 line0 new0 +agg_set_line_name _sysfs.0 line1 new1 +agg_enable_chip _sysfs.0 +test "$(agg_get_line_name _sysfs.0 0)" = "new0" || fail "line name is unset" +test "$(agg_get_line_name _sysfs.0 1)" = "new1" || fail "line name is unset" +teardown_2_2 + +echo "2.2.3.4. Line offset can be modified" +setup_2_2 +agg_disable_chip _sysfs.0 +agg_set_offset _sysfs.0 line0 5 +agg_set_offset _sysfs.0 line1 7 +agg_enable_chip _sysfs.0 +teardown_2_2 + +echo "2.2.3.5. Can re-enable a chip with valid reconfiguration" +setup_2_2 +agg_disable_chip _sysfs.0 +agg_set_key _sysfs.0 line0 "$(sim_get_chip_label chip1 bank1)" +agg_set_offset _sysfs.0 line0 15 +agg_set_key _sysfs.0 line1 "$(sim_get_chip_label chip0 bank1)" +agg_set_offset _sysfs.0 line0 14 +agg_enable_chip _sysfs.0 +teardown_2_2 + +echo "2.2.3.6. Can't re-enable a chip with invalid reconfiguration" +setup_2_2 +agg_disable_chip _sysfs.0 +agg_set_key _sysfs.0 line0 invalidkey +echo 1 > "$CONFIGFS_AGG_DIR/_sysfs.0/live" 2> /dev/null && fail "chip unexpectedly enabled" +teardown_2_2 +setup_2_2 +agg_disable_chip _sysfs.0 +agg_set_offset _sysfs.0 line0 99 +echo 1 > "$CONFIGFS_AGG_DIR/_sysfs.0/live" 2> /dev/null && fail "chip unexpectedly enabled" +teardown_2_2 + +echo "3. Module unload" + +echo "3.1. Can't unload module if there is at least one device created via configfs" +agg_create_chip agg0 +modprobe -r gpio-aggregator 2> /dev/null +test -d /sys/module/gpio_aggregator || fail "module unexpectedly unloaded" +agg_remove_chip agg0 + +echo "3.2. Can unload module if there is no device created via configfs" +echo "chip0_bank0 1 chip1_bank0 3" > "$SYSFS_AGG_DIR/new_device" +modprobe -r gpio-aggregator 2> /dev/null +test -d /sys/module/gpio_aggregator && fail "module unexpectedly remains to be loaded" +modprobe gpio-aggregator 2> /dev/null + +echo "4. GPIO forwarder functional" +SETTINGS="chip0:bank0:2 chip0:bank1:4 chip1:bank0:6 chip1:bank1:8" +setup_4() { + local OFFSET=0 + agg_create_chip agg0 + for SETTING in $SETTINGS; do + CHIP=$(echo "$SETTING" | cut -d: -f1) + BANK=$(echo "$SETTING" | cut -d: -f2) + LINE=$(echo "$SETTING" | cut -d: -f3) + agg_create_line agg0 "line${OFFSET}" + agg_set_key agg0 "line${OFFSET}" "$(sim_get_chip_label "$CHIP" "$BANK")" + agg_set_offset agg0 "line${OFFSET}" "$LINE" + OFFSET=$(expr $OFFSET + 1) + done + agg_enable_chip agg0 +} +teardown_4() { + agg_configfs_cleanup +} + +echo "4.1. Forwarding set values" +setup_4 +OFFSET=0 +for SETTING in $SETTINGS; do + CHIP=$(echo "$SETTING" | cut -d: -f1) + BANK=$(echo "$SETTING" | cut -d: -f2) + LINE=$(echo "$SETTING" | cut -d: -f3) + DEVNAME=$(cat "$CONFIGFS_SIM_DIR/$CHIP/dev_name") + CHIPNAME=$(cat "$CONFIGFS_SIM_DIR/$CHIP/$BANK/chip_name") + VAL_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio${LINE}/value" + test $(cat $VAL_PATH) = "0" || fail "incorrect value read from sysfs" + $BASE_DIR/gpio-mockup-cdev -s 1 "/dev/$(agg_configfs_chip_name agg0)" "$OFFSET" & + mock_pid=$! + sleep 0.1 # FIXME Any better way? + test "$(cat $VAL_PATH)" = "1" || fail "incorrect value read from sysfs" + kill "$mock_pid" + OFFSET=$(expr $OFFSET + 1) +done +teardown_4 + +echo "4.2. Forwarding set config" +setup_4 +OFFSET=0 +for SETTING in $SETTINGS; do + CHIP=$(echo "$SETTING" | cut -d: -f1) + BANK=$(echo "$SETTING" | cut -d: -f2) + LINE=$(echo "$SETTING" | cut -d: -f3) + DEVNAME=$(cat "$CONFIGFS_SIM_DIR/$CHIP/dev_name") + CHIPNAME=$(cat "$CONFIGFS_SIM_DIR/$CHIP/$BANK/chip_name") + VAL_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio${LINE}/value" + $BASE_DIR/gpio-mockup-cdev -b pull-up "/dev/$(agg_configfs_chip_name agg0)" "$OFFSET" + test $(cat "$VAL_PATH") = "1" || fail "incorrect value read from sysfs" + OFFSET=$(expr $OFFSET + 1) +done +teardown_4 + +echo "5. Race condition verification" + +echo "5.1. Stress test of new_device/delete_device and module load/unload" +for _ in $(seq 1000); do + { + echo "dummy 0" > "$SYSFS_AGG_DIR/new_device" + cat "$CONFIGFS_AGG_DIR/_sysfs.0/dev_name" > "$SYSFS_AGG_DIR/delete_device" + } 2> /dev/null +done & +writer_pid=$! +while kill -0 "$writer_pid" 2> /dev/null; do + { + modprobe gpio-aggregator + modprobe -r gpio-aggregator + } 2> /dev/null +done + +echo "GPIO $MODULE test PASS"