From: sashiko-bot@kernel.org
To: "Zhengping Zhang" <zhengping.zhang@airoha.com>
Cc: linux-gpio@vger.kernel.org, devicetree@vger.kernel.org,
robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH 02/12] pinctrl: airoha: configure pin muxes on GPIO requests
Date: Tue, 10 Nov 2026 10:14:35 +0000 [thread overview]
Message-ID: <sashiko-outbox-206845@kernel.org> (raw)
In-Reply-To: <20261110094339.749110-3-zhengping.zhang@airoha.com>
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [Medium] pinctrl: airoha: pinmux ownership bypass and mux_setting
corruption with function_is_gpio()
- [Medium] pinctrl: airoha: false -EBUSY conflict in
airoha_pinmux_check_conflicts()
--
commit 9a9749c74aba6ad54ceaf9a1debe606913f398d5
Author: Zhengping Zhang <zhengping.zhang@airoha.com>
pinctrl: airoha: configure pin muxes on GPIO requests
This commit adds a gpio_request_enable callback to configure pin muxes when
a GPIO is requested and introduces optional conflict detection for shared
mux bits across pin groups and GPIO owners.
> diff --git a/drivers/pinctrl/airoha/pinctrl-airoha.c b/drivers/pinctrl/airoha/pinctrl-airoha.c
> index 8dd0881bba4ad..25562e51ebbdc 100644
> --- a/drivers/pinctrl/airoha/pinctrl-airoha.c
> +++ b/drivers/pinctrl/airoha/pinctrl-airoha.c
> @@ -400,57 +400,236 @@ static int airoha_pinctrl_add_gpiochip(struct airoha_pinctrl *pinctrl,
[ ... ]
> +/* Shared mux bits can affect pads outside the requested pin group. */
> +static bool
> +airoha_pinmux_groups_conflict(const struct airoha_pinctrl_func_group *a,
> + const struct airoha_pinctrl_func_group *b)
> +{
> + int i, j;
> +
> + for (i = 0; i < a->regmap_size; i++) {
> + for (j = 0; j < b->regmap_size; j++) {
> + u32 mask;
>
> - group = &func->groups[i];
> - if (strcmp(group->name, grp->grp.name))
> + if ((a->regmap[i].mux == AIROHA_FUNC_MUX) !=
> + (b->regmap[j].mux == AIROHA_FUNC_MUX) ||
> + a->regmap[i].offset != b->regmap[j].offset)
> + continue;
> +
> + mask = a->regmap[i].mask & b->regmap[j].mask;
> + if (mask & (a->regmap[i].val ^ b->regmap[j].val))
> + return true;
> + }
> + }
> +
> + return false;
> +}
[ ... ]
> +static int
> +airoha_pinmux_check_conflicts(struct pinctrl_dev *pctldev,
> + const struct airoha_pinctrl_func_group *group)
> +{
> + unsigned int i;
> +
> + for (i = 0; i < pctldev->desc->npins; i++) {
> + const struct airoha_pinctrl_func_group *active;
> + struct pinctrl_setting_mux setting;
> + unsigned int number = pctldev->desc->pins[i].number;
> + struct pin_desc *pin;
> + bool claimed, gpio_owned;
> +
> + pin = pin_desc_get(pctldev, number);
> + if (!pin)
> + continue;
> +
> + scoped_guard(mutex, &pin->mux_lock) {
> + claimed = pin->mux_usecount && pin->mux_setting;
> + gpio_owned = !!pin->gpio_owner;
> + if (claimed)
> + setting = *pin->mux_setting;
> + }
> +
> + /* GPIO requests need no explicit DTS pinctrl state. */
> + if (gpio_owned) {
> + active = airoha_pinmux_get_gpio_group(pctldev, number);
> + if (!active)
> + return -EOPNOTSUPP;
> + if (airoha_pinmux_groups_conflict(group, active))
> + goto conflict;
> + }
> +
> + if (!claimed)
> + continue;
> + active = airoha_pinmux_get_func_group(pctldev, setting.func,
> + setting.group);
> + if (!active)
> + return -EINVAL;
> + if (!airoha_pinmux_groups_conflict(group, active))
> + continue;
> +
> +conflict:
> + dev_err(pctldev->dev,
> + "group %s conflicts with shared mux bits of group %s\n",
> + group->name, active->name);
> + return -EBUSY;
> + }
> +
> + return 0;
> +}
[Severity: Medium]
Does airoha_pinmux_check_conflicts() reject valid two-group HSUART
configurations (groups = "hsuart", "hsuart_cts_rts") with -EBUSY on SoCs
that enable check_mux_conflicts?
On AN7581 and AN7583, hsuart_pins contains only the TX/RX pins and
hsuart_cts_rts_pins contains only the CTS/RTS pins, so enabling HSUART with
hardware flow control requires selecting both groups. However, in
uart_func_group, the "hsuart" entry includes GPIO_HSUART_CTS_RTS_MODE_MASK
in regmap[0].mask with val = GPIO_HSUART_MODE_MASK, whereas
"hsuart_cts_rts" sets the same mask with val = GPIO_HSUART_MODE_MASK |
GPIO_HSUART_CTS_RTS_MODE_MASK. When pinctrl_commit_state() enables the
second group after claiming the first, airoha_pinmux_groups_conflict() sees
differing values on GPIO_HSUART_CTS_RTS_MODE_MASK and fails the state
transition with -EBUSY.
[ ... ]
> +static int airoha_pinmux_set_mux(struct pinctrl_dev *pctldev,
> + unsigned int selector, unsigned int group)
> +{
> + struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
> + const struct airoha_pinctrl_func_group *config;
> + int i, err;
> +
> + config = airoha_pinmux_get_func_group(pctldev, selector, group);
> + if (!config)
> + return -EINVAL;
> +
> + guard(mutex)(&pinctrl->mux_lock);
> + if (pinctrl->check_mux_conflicts) {
> + struct group_desc *grp;
> +
> + /* The core permits GPIO-category muxes alongside GPIO owners. */
> + grp = pinctrl_generic_get_group(pctldev, group);
> + if (!pinmux_generic_function_is_gpio(pctldev, selector)) {
> + for (i = 0; i < grp->grp.npins; i++) {
> + struct pin_desc *pin;
> +
> + pin = pin_desc_get(pctldev, grp->grp.pins[i]);
> + if (!pin)
> + return -EINVAL;
> + scoped_guard(mutex, &pin->mux_lock) {
> + if (pin->gpio_owner)
> + return -EBUSY;
> + }
> + }
> + }
> +
> + err = airoha_pinmux_check_conflicts(pctldev, config);
> + if (err)
> + return err;
> }
>
> - return -EINVAL;
> + dev_dbg(pctldev->dev, "enable function %s group %s\n",
> + pinmux_generic_get_function_name(pctldev, selector),
> + config->name);
> +
> + return airoha_pinmux_apply_group(pinctrl, config);
> }
>
> static int airoha_pinmux_set_direction(struct pinctrl_dev *pctrl_dev,
> @@ -468,6 +647,8 @@ static int airoha_pinmux_set_direction(struct pinctrl_dev *pctrl_dev,
> }
>
> static const struct pinmux_ops airoha_pmxops = {
> + .gpio_request_enable = airoha_gpio_request_enable,
> + .function_is_gpio = pinmux_generic_function_is_gpio,
[Severity: Medium]
Can setting .function_is_gpio allow a second consumer to bypass pinmux
ownership and corrupt pin->mux_setting when a pin is already claimed by an
explicit GPIO-category pinctrl state?
When a pin's active pin->mux_setting has PINFUNCTION_FLAG_GPIO (via
PINCTRL_GPIO_FUNC_DESC), a second consumer calling pinmux_enable_setting()
on a group containing that pin causes pin_request() to set gpio_ok = true,
skip the mux_owner check, and increment pin->mux_usecount to 2:
drivers/pinctrl/pinmux.c:pin_request() {
...
if (gpio_range || ops->strict) {
if (desc->mux_usecount && !gpio_ok) {
dev_err(pctldev->dev,
"pin %s already requested by %s; cannot claim for %s\n",
desc->name, desc->mux_owner, owner);
goto out;
}
...
}
pinmux_enable_setting() then overwrites pin->mux_setting with the new
setting before calling airoha_pinmux_set_mux(). Because
airoha_pinmux_set_mux() only checks pin->gpio_owner, if the pin has no GPIO
descriptor owner, airoha_pinmux_check_conflicts() sees the already
overwritten pin->mux_setting and overwrites the first device's hardware mux
without detecting the conflict. Conversely, if airoha_pinmux_set_mux()
returns -EBUSY, pinmux_enable_setting()'s error path clears
pin->mux_setting to NULL while pin_free() only decrements pin->mux_usecount
to 1, hiding the first owner's active mux from subsequent conflict checks
and preventing pinmux_disable_setting() from releasing the pin.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261110094339.749110-1-zhengping.zhang@airoha.com?part=2
next prev parent reply other threads:[~2026-11-10 10:14 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 9:43 [PATCH 00/12] pinctrl: airoha: configure GPIO muxes explicitly and fix pad mappings Zhengping Zhang
2026-11-10 9:43 ` [PATCH 01/12] pinctrl: airoha: fix setting of GPIO direction Zhengping Zhang
2026-11-10 9:53 ` sashiko-bot
2026-11-10 9:43 ` [PATCH 02/12] pinctrl: airoha: configure pin muxes on GPIO requests Zhengping Zhang
2026-11-10 10:14 ` sashiko-bot [this message]
2026-11-10 9:43 ` [PATCH 03/12] dt-bindings: pinctrl: airoha: describe all EN7581 GPIO mux groups Zhengping Zhang
2026-11-10 9:43 ` [PATCH 04/12] pinctrl: airoha: an7581: fix PHY LED GPIO group assignments Zhengping Zhang
2026-11-10 9:43 ` [PATCH 05/12] pinctrl: airoha: an7581: select force GPIO mode on GPIO requests Zhengping Zhang
2026-11-10 10:00 ` sashiko-bot
2026-11-10 9:43 ` [PATCH 06/12] dt-bindings: pinctrl: airoha: describe all AN7583 GPIO mux groups Zhengping Zhang
2026-11-10 9:43 ` [PATCH 07/12] pinctrl: airoha: an7583: fix SPI pin mux config Zhengping Zhang
2026-11-10 9:43 ` [PATCH 08/12] pinctrl: airoha: an7583: fix eMMC " Zhengping Zhang
2026-11-10 9:43 ` [PATCH 09/12] pinctrl: airoha: an7583: use force GPIO mode for GPIO requests Zhengping Zhang
2026-11-10 9:56 ` sashiko-bot
2026-11-10 9:43 ` [PATCH 10/12] dt-bindings: pinctrl: airoha: describe all EN7523 GPIO mux groups Zhengping Zhang
2026-11-10 9:43 ` [PATCH 11/12] pinctrl: airoha: en7523: use force GPIO mode for GPIO requests Zhengping Zhang
2026-11-10 9:43 ` [PATCH 12/12] MAINTAINERS: add myself as Airoha pinctrl co-maintainer Zhengping Zhang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-206845@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=linux-gpio@vger.kernel.org \
--cc=robh@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=zhengping.zhang@airoha.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox