From: sashiko-bot@kernel.org
To: "Birger Koblitz" <mail@birger-koblitz.de>
Cc: linux-usb@vger.kernel.org
Subject: Re: [PATCH net-next v21 07/13] ax88179_178a: Add VLAN offload support for AX88179A
Date: Sun, 15 Nov 2026 10:51:54 +0000 [thread overview]
Message-ID: <sashiko-outbox-215420@kernel.org> (raw)
In-Reply-To: <20261114-ax88179a-v21-7-c2d34410bcbe@birger-koblitz.de>
Thank you for your contribution! Sashiko AI review found 5 potential
issues to consider:
- [Medium] net: usb: ax88179: uninitialized stack read and short USB
read in VLAN ops
- [Medium] net: usb: ax88179: unchecked USB writes in
ax88179a_set_features() loop
- [Medium] net: usb: ax88179_178a: TX VLAN tag drop race in
ax88179a_tx_fixup()
- [Low] net: usb: ax88179_178a: partial feature state in
ax88179a_set_features()
- [Low] net: usb: ax88179_178a: duplicated VLAN filter update logic in
add/kill vid
--
commit a2245f1909a4b4c924abeed75400e9c875dcb39c
Author: Birger Koblitz <mail@birger-koblitz.de>
ax88179_178a: Add VLAN offload support for AX88179A
This commit adds hardware VLAN offload and filtering callbacks
(NETIF_F_HW_VLAN_CTAG_TX, NETIF_F_HW_VLAN_CTAG_RX, and
NETIF_F_HW_VLAN_CTAG_FILTER) for AX88179A-based USB network devices.
> diff --git a/drivers/net/usb/ax88179a_devices.c b/drivers/net/usb/ax88179a_devices.c
> index 272e923656832..4207d2cc2b865 100644
> --- a/drivers/net/usb/ax88179a_devices.c
> +++ b/drivers/net/usb/ax88179a_devices.c
> @@ -258,6 +258,88 @@ static const struct ethtool_ops ax88179a_ethtool_ops = {
> .get_ts_info = ethtool_op_get_ts_info,
> };
>
> +static int ax88179a_vlan_rx_kill_vid(struct net_device *net, __be16 proto, u16 vid)
> +{
> + struct usbnet *dev = netdev_priv(net);
> + u16 reg16 = 0;
> + u8 vlan_ctrl;
> + int ret = 0;
> + u8 reg8 = 0;
> +
> + ret = ax88179_read_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, ®8);
> + if (ret < 0)
> + return ret;
> + vlan_ctrl = reg8;
> +
> + /* Address */
> + reg8 = (vid / 16);
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_ADDRESS, 1, 1, ®8);
> + if (ret < 0)
> + return ret;
> +
> + /* Data */
> + reg8 = vlan_ctrl | AX_VLAN_CONTROL_RD;
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, ®8);
> + if (ret < 0)
> + return ret;
> +
> + ret = ax88179_read_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_DATA0, 2, 2, ®16);
> + if (ret < 0)
> + return ret;
> + reg16 &= ~(1 << (vid % 16));
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_DATA0, 2, 2, ®16);
> + if (ret < 0)
> + return ret;
> +
> + reg8 = vlan_ctrl | AX_VLAN_CONTROL_WE;
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, ®8);
> + if (ret < 0)
> + return ret;
> +
> + return 0;
> +}
> +
> +static int ax88179a_vlan_rx_add_vid(struct net_device *net, __be16 proto, u16 vid)
> +{
> + struct usbnet *dev = netdev_priv(net);
> + u8 vlan_ctrl;
> + int ret = 0;
> + u16 reg16;
> + u8 reg8;
> +
> + ret = ax88179_read_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, ®8);
> + if (ret < 0)
> + return ret;
> + vlan_ctrl = reg8;
> +
> + /* Address */
> + reg8 = (vid / 16);
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_ADDRESS, 1, 1, ®8);
> + if (ret < 0)
> + return ret;
> +
> + /* Data */
> + reg8 = vlan_ctrl | AX_VLAN_CONTROL_RD;
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, ®8);
> + if (ret < 0)
> + return ret;
> +
> + ret = ax88179_read_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_DATA0, 2, 2, ®16);
> + if (ret < 0)
> + return ret;
> + reg16 |= (1 << (vid % 16));
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_DATA0, 2, 2, ®16);
> + if (ret < 0)
> + return ret;
> +
> + reg8 = vlan_ctrl | AX_VLAN_CONTROL_WE;
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, ®8);
> + if (ret < 0)
> + return ret;
> +
> + return 0;
> +}
[Severity: Medium]
Can a 0-byte USB read in ax88179a_vlan_rx_add_vid() or
ax88179a_set_features() write uninitialized stack memory into
AX88179A_VLAN_ID_CONTROL?
For 1-byte reads, ax88179_read_cmd() passes the caller's pointer directly
to __usbnet_read_cmd(), which only copies into the buffer when
usb_control_msg() returns > 0. If a control read returns 0, reg8 in
ax88179a_vlan_rx_add_vid() and tmp in ax88179a_set_features() remain
uninitialized because the callers only check ret < 0, and that stack byte
is then modified and written back to AX88179A_VLAN_ID_CONTROL.
Similarly, the 2-byte reads of AX88179A_VLAN_ID_DATA0 only check ret < 0
instead of ret < 2, so a short read leaves reg16 zeroed or partially
populated and causes the subsequent write to clear the other 15 VIDs in
the same (vid / 16) filter entry.
[Severity: Low]
This isn't a bug, but ax88179a_vlan_rx_kill_vid() and
ax88179a_vlan_rx_add_vid() duplicate the same five-step register sequence
and only differ in whether they clear or set BIT(vid % 16) in reg16.
Could they share a common helper taking a boolean flag?
[ ... ]
> @@ -517,6 +599,75 @@ static int ax88179a_mii_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
> return phylink_mii_ioctl(data->phylink, rq, cmd);
> }
>
> +static int ax88179a_set_features(struct net_device *net, netdev_features_t features)
> +{
> + struct usbnet *dev = netdev_priv(net);
> + netdev_features_t changed;
> + int ret;
> + u8 tmp;
> +
> + changed = net->features ^ features;
> +
> + ret = ax88179_set_features(net, features);
> + if (ret)
> + return ret;
> +
> + if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
> + if (features & NETIF_F_HW_VLAN_CTAG_FILTER) {
> + u8 vlan_state = 0;
> +
> + ret = ax88179_read_cmd(dev, AX_ACCESS_MAC,
> + AX88179A_VLAN_ID_CONTROL, 1, 1, &vlan_state);
> + if (ret < 0)
> + return ret;
> +
> + for (int i = 0; i < 256; i++) {
> + /* Address */
> + tmp = i;
> + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_ADDRESS,
> + 1, 1, &tmp);
> + /* Data */
> + ax88179_write_u16(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_DATA0,
> + 2, 0);
> + /* Write-Execute */
> + ax88179_write_u8(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL,
> + 1, vlan_state | AX_VLAN_CONTROL_WE);
> + }
[Severity: Medium]
Should the USB writes inside this loop check for errors?
If any write fails transiently while the final write enabling
AX_VLAN_CONTROL_VFE succeeds, hardware VLAN filtering is enabled over an
incompletely cleared filter table with stale VID entries. On a persistent
USB error, the loop also runs all 768 synchronous control transfers under
rtnl_lock instead of bailing out on the first failure.
> + vlan_state |= AX_VLAN_CONTROL_VFE;
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC,
> + AX88179A_VLAN_ID_CONTROL, 1, 1, &vlan_state);
> + if (ret < 0)
> + return ret;
> + } else {
> + ret = ax88179_read_cmd(dev, AX_ACCESS_MAC,
> + AX88179A_VLAN_ID_CONTROL, 1, 1, &tmp);
> + if (ret < 0)
> + return ret;
> + tmp &= ~AX_VLAN_CONTROL_VFE;
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC,
> + AX88179A_VLAN_ID_CONTROL, 1, 1, &tmp);
> + if (ret < 0)
> + return ret;
> + }
> + }
> +
> + if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
> + ret = ax88179_read_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL,
> + 1, 1, &tmp);
> + if (ret < 0)
> + return ret;
> + if (features & NETIF_F_HW_VLAN_CTAG_RX)
> + tmp |= AX_VLAN_CONTROL_VSO;
> + else
> + tmp &= ~AX_VLAN_CONTROL_VSO;
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL,
> + 1, 1, &tmp);
> + if (ret < 0)
> + return ret;
> + }
> + return 0;
> +}
[Severity: Low]
Can a late failure in ax88179a_set_features() leave hardware offload state
out of sync with net->features?
When multiple features are changed at once and a later register access
fails, __netdev_update_features() aborts without updating net->features or
repopulating the VLAN filter table, while earlier changes stay active in
hardware. For example, if enabling NETIF_F_HW_VLAN_CTAG_FILTER succeeds
and the NETIF_F_HW_VLAN_CTAG_RX step fails, AX_VLAN_CONTROL_VFE remains
enabled with an all-zero filter table, and any checksum bits already
toggled via XOR in ax88179_set_features() remain inverted relative to
net->features.
[ ... ]
> @@ -612,9 +766,11 @@ static int ax88179a_bind(struct usbnet *dev, struct usb_interface *intf)
> dev->mii.supports_gmii = 1;
>
> dev->net->features |= NETIF_F_SG | NETIF_F_IP_CSUM |
> - NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO;
> + NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO |
> + NETIF_F_HW_VLAN_CTAG_TX;
>
> dev->net->hw_features |= dev->net->features;
> + dev->net->hw_features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER;
[Severity: Medium]
Can toggling NETIF_F_HW_VLAN_CTAG_TX at runtime cause ax88179a_tx_fixup()
to transmit VLAN-tagged packets without their VLAN tag?
drivers/net/usb/ax88179a_devices.c:ax88179a_tx_fixup() {
...
if ((dev->net->features & NETIF_F_HW_VLAN_CTAG_TX) && (vlan_get_tag(skb, &tci) >= 0)) {
tx_desc |= AX179A_TX_DESC_VLAN;
tx_desc |= FIELD_PREP(AX179A_TX_DESC_VLAN_ID, (u64)tci);
}
...
}
CPU0 CPU1
dev_hard_start_xmit()
validate_xmit_skb()
validate_xmit_vlan()
/* tag left in skb->vlan_tci */
__netdev_update_features()
/* clears NETIF_F_HW_VLAN_CTAG_TX */
ndo_start_xmit()
ax88179a_tx_fixup()
/* skips AX179A_TX_DESC_VLAN */ <-- sent untagged
Now that NETIF_F_HW_VLAN_CTAG_TX is exposed in features and hw_features,
disabling it while packets validated under NETIF_F_HW_VLAN_CTAG_TX are in
flight causes both the feature check in ax88179a_tx_fixup() and
vlan_get_tag() to ignore skb->vlan_tci. Checking skb_vlan_tag_present(skb)
and reading the tag with skb_vlan_tag_get(skb) avoids dropping the tag.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261114-ax88179a-v21-0-c2d34410bcbe@birger-koblitz.de?part=7
next prev parent reply other threads:[~2026-11-15 10:51 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-14 10:50 [PATCH net-next v21 00/13] ax88179_178a: Add support for AX88179A-based chips Birger Koblitz
2026-11-14 10:50 ` [PATCH net-next v21 01/13] phylink: Add phylink_mac_interrupt Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:50 ` [PATCH net-next v21 02/13] phylib: Add support for PHYs with broken forced mode Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:50 ` [PATCH net-next v21 03/13] ax88179_178a: Split driver into library and device specific code Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:51 ` [PATCH net-next v21 04/13] ax88179_178a: Add HW support for AX179A-based chips Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:51 ` [PATCH net-next v21 05/13] ax88179_178a: Add EEE configuration support for AX88179A MACs Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:51 ` [PATCH net-next v21 06/13] ax88179_178a: Add EEE configuration support for AX88179A PHYs Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:51 ` [PATCH net-next v21 07/13] ax88179_178a: Add VLAN offload support for AX88179A Birger Koblitz
2026-11-15 10:51 ` sashiko-bot [this message]
2026-11-14 10:51 ` [PATCH net-next v21 08/13] ax88179_178a: Add AX179A/AX279 multicast configuration Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:51 ` [PATCH net-next v21 09/13] ax88179_178a: Add Suspend/resume support for AX88179A/772D/279 Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:51 ` [PATCH net-next v21 10/13] ax88179_178a: Add ethtool get_drvinfo Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:51 ` [PATCH net-next v21 11/13] ax88179_178a: Update driver name and information Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:51 ` [PATCH net-next v21 12/13] ax88179_178a: Add support for AX88179A/772D/279 EEPROM access Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:51 ` [PATCH net-next v21 13/13] ax88796b: Add support for AX88772D, AX88179A and AX88279 Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
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-215420@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=mail@birger-koblitz.de \
--cc=sashiko-reviews@lists.linux.dev \
/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.