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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.