* [PATCH v2 rtw-next 0/2] wifi: rtw89: usb: read serial_number and uuid via sysfs
@ 2026-05-25 8:51 Ping-Ke Shih
2026-05-25 8:51 ` [PATCH v2 rtw-next 1/2] wifi: rtw89: add dev_id_quirks to driver_info for per-device quirk control Ping-Ke Shih
2026-05-25 8:51 ` [PATCH v2 rtw-next 2/2] wifi: rtw89: usb: add serial_number and uuid sysfs attributes for 0x28de:0x2432 Ping-Ke Shih
0 siblings, 2 replies; 8+ messages in thread
From: Ping-Ke Shih @ 2026-05-25 8:51 UTC (permalink / raw)
To: linux-wireless
Cc: driver-core, johannes, wenjie.tsai, mh_chen, charlesl, sabae
As what we learned in RFC v1, add sysfs entries
- /sys/class/ieee80211/phy0/rtw89_usb/serial_number
- /sys/class/ieee80211/phy0/rtw89_usb/uuid
These entries only present if specific USB device is in use. We add a
quirk as a flag for this.
Above info is fully documented in
Documentation/ABI/testing/sysfs-class-ieee80211-rtw89
v2:
- add specific sysfs entries in /sys/class/ieee80211/phy0/rtw89_usb/
* serial_number and uuid
- add Documentation/ABI/testing/sysfs-class-ieee80211-rtw89 to
describe ABI
- add sysfs entries by quirk according to specific device ID
- include patch 1/2 which does quirk infrastructure by device ID
v1 (RFC):
- https://lore.kernel.org/linux-wireless/20260519072415.25746-1-pkshih@realtek.com/
Johnson Tsai (2):
wifi: rtw89: add dev_id_quirks to driver_info for per-device quirk
control
wifi: rtw89: usb: add serial_number and uuid sysfs attributes for
0x28de:0x2432
.../ABI/testing/sysfs-class-ieee80211-rtw89 | 24 ++++++++
drivers/net/wireless/realtek/rtw89/core.c | 9 ++-
drivers/net/wireless/realtek/rtw89/core.h | 10 +++-
drivers/net/wireless/realtek/rtw89/pci.c | 3 +-
.../net/wireless/realtek/rtw89/rtw8851be.c | 1 +
.../net/wireless/realtek/rtw89/rtw8851bu.c | 1 +
.../net/wireless/realtek/rtw89/rtw8852ae.c | 1 +
.../net/wireless/realtek/rtw89/rtw8852au.c | 1 +
.../net/wireless/realtek/rtw89/rtw8852be.c | 1 +
.../net/wireless/realtek/rtw89/rtw8852bte.c | 1 +
.../net/wireless/realtek/rtw89/rtw8852bu.c | 1 +
drivers/net/wireless/realtek/rtw89/rtw8852c.c | 10 ++++
drivers/net/wireless/realtek/rtw89/rtw8852c.h | 6 +-
.../net/wireless/realtek/rtw89/rtw8852ce.c | 1 +
.../net/wireless/realtek/rtw89/rtw8852cu.c | 13 +++-
.../net/wireless/realtek/rtw89/rtw8922ae.c | 2 +
.../net/wireless/realtek/rtw89/rtw8922au.c | 1 +
.../net/wireless/realtek/rtw89/rtw8922de.c | 2 +
drivers/net/wireless/realtek/rtw89/usb.c | 60 ++++++++++++++++++-
19 files changed, 138 insertions(+), 10 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-class-ieee80211-rtw89
base-commit: 6b964941bbfe6e0f18b1a5e008486dbb62df440a
--
2.25.1
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v2 rtw-next 1/2] wifi: rtw89: add dev_id_quirks to driver_info for per-device quirk control 2026-05-25 8:51 [PATCH v2 rtw-next 0/2] wifi: rtw89: usb: read serial_number and uuid via sysfs Ping-Ke Shih @ 2026-05-25 8:51 ` Ping-Ke Shih 2026-05-25 19:31 ` Greg KH 2026-05-25 8:51 ` [PATCH v2 rtw-next 2/2] wifi: rtw89: usb: add serial_number and uuid sysfs attributes for 0x28de:0x2432 Ping-Ke Shih 1 sibling, 1 reply; 8+ messages in thread From: Ping-Ke Shih @ 2026-05-25 8:51 UTC (permalink / raw) To: linux-wireless Cc: driver-core, johannes, wenjie.tsai, mh_chen, charlesl, sabae From: Johnson Tsai <wenjie.tsai@realtek.com> Add a dev_id_quirks field to rtw89_driver_info so that per-device (VID/PID) quirks can be expressed independently of chip-level default_quirks. Apply the bitmap in rtw89_alloc_ieee80211_hw() so both USB and PCI probes benefit automatically. All existing driver_info structs initialize dev_id_quirks to 0; no behavior change. Signed-off-by: Johnson Tsai <wenjie.tsai@realtek.com> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> --- drivers/net/wireless/realtek/rtw89/core.c | 9 +++++++-- drivers/net/wireless/realtek/rtw89/core.h | 4 ++-- drivers/net/wireless/realtek/rtw89/pci.c | 3 +-- drivers/net/wireless/realtek/rtw89/rtw8851be.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8851bu.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852ae.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852au.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852be.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852bte.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852bu.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852ce.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852cu.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8922ae.c | 2 ++ drivers/net/wireless/realtek/rtw89/rtw8922au.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8922de.c | 2 ++ drivers/net/wireless/realtek/rtw89/usb.c | 3 +-- 16 files changed, 25 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index c1df3e2ba11e..68dad6090f87 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -7532,9 +7532,11 @@ EXPORT_SYMBOL(rtw89_core_unregister); struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device, u32 bus_data_size, - const struct rtw89_chip_info *chip, - const struct rtw89_chip_variant *variant) + const struct rtw89_driver_info *info) { + const unsigned long *dev_id_quirks = &info->dev_id_quirks; + const struct rtw89_chip_variant *variant = info->variant; + const struct rtw89_chip_info *chip = info->chip; struct rtw89_fw_info early_fw = {}; const struct firmware *firmware; struct ieee80211_hw *hw; @@ -7600,6 +7602,9 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device, rtwdev->fw.fw_format = fw_format; rtwdev->support_mlo = support_mlo; + bitmap_or(rtwdev->quirks, rtwdev->quirks, dev_id_quirks, + NUM_OF_RTW89_QUIRKS); + rtw89_debug(rtwdev, RTW89_DBG_CHAN, "probe driver %s chanctx\n", no_chanctx ? "without" : "with"); rtw89_debug(rtwdev, RTW89_DBG_CHAN, "probe driver %s MLO cap\n", diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 27d9a916d58c..e687216da5b6 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -4800,6 +4800,7 @@ struct rtw89_driver_info { const struct rtw89_chip_info *chip; const struct rtw89_chip_variant *variant; const struct dmi_system_id *quirks; + unsigned long dev_id_quirks; /* bitmap of rtw89_quirks */ union rtw89_bus_info bus; }; @@ -8126,8 +8127,7 @@ int rtw89_core_register(struct rtw89_dev *rtwdev); void rtw89_core_unregister(struct rtw89_dev *rtwdev); struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device, u32 bus_data_size, - const struct rtw89_chip_info *chip, - const struct rtw89_chip_variant *variant); + const struct rtw89_driver_info *info); void rtw89_free_ieee80211_hw(struct rtw89_dev *rtwdev); u8 rtw89_acquire_mac_id(struct rtw89_dev *rtwdev); void rtw89_release_mac_id(struct rtw89_dev *rtwdev, u8 mac_id); diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c index fe1152c560bd..102bae488180 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.c +++ b/drivers/net/wireless/realtek/rtw89/pci.c @@ -4772,8 +4772,7 @@ int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) info = (const struct rtw89_driver_info *)id->driver_data; rtwdev = rtw89_alloc_ieee80211_hw(&pdev->dev, - sizeof(struct rtw89_pci), - info->chip, info->variant); + sizeof(struct rtw89_pci), info); if (!rtwdev) { dev_err(&pdev->dev, "failed to allocate hw\n"); return -ENOMEM; diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851be.c b/drivers/net/wireless/realtek/rtw89/rtw8851be.c index ce59ac9f56ba..640672eb0d26 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851be.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851be.c @@ -73,6 +73,7 @@ static const struct rtw89_driver_info rtw89_8851be_info = { .chip = &rtw8851b_chip_info, .variant = NULL, .quirks = NULL, + .dev_id_quirks = 0, .bus = { .pci = &rtw8851b_pci_info, }, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851bu.c b/drivers/net/wireless/realtek/rtw89/rtw8851bu.c index 6a8d31544314..e7933174398e 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851bu.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851bu.c @@ -31,6 +31,7 @@ static const struct rtw89_driver_info rtw89_8851bu_info = { .chip = &rtw8851b_chip_info, .variant = NULL, .quirks = NULL, + .dev_id_quirks = 0, .bus = { .usb = &rtw8851b_usb_info, } diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852ae.c b/drivers/net/wireless/realtek/rtw89/rtw8852ae.c index 9e05e831569d..64306cdc1ee4 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852ae.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852ae.c @@ -71,6 +71,7 @@ static const struct rtw89_driver_info rtw89_8852ae_info = { .chip = &rtw8852a_chip_info, .variant = NULL, .quirks = NULL, + .dev_id_quirks = 0, .bus = { .pci = &rtw8852a_pci_info, }, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852au.c b/drivers/net/wireless/realtek/rtw89/rtw8852au.c index 4cced4619b7d..29b7f7769370 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852au.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852au.c @@ -33,6 +33,7 @@ static const struct rtw89_driver_info rtw89_8852au_info = { .chip = &rtw8852a_chip_info, .variant = NULL, .quirks = NULL, + .dev_id_quirks = 0, .bus = { .usb = &rtw8852a_usb_info, } diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852be.c b/drivers/net/wireless/realtek/rtw89/rtw8852be.c index 12db0d0be547..5bc0a6a99d1d 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852be.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852be.c @@ -73,6 +73,7 @@ static const struct rtw89_driver_info rtw89_8852be_info = { .chip = &rtw8852b_chip_info, .variant = NULL, .quirks = NULL, + .dev_id_quirks = 0, .bus = { .pci = &rtw8852b_pci_info, }, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bte.c b/drivers/net/wireless/realtek/rtw89/rtw8852bte.c index 8c995aa95325..49a72ca835ac 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852bte.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852bte.c @@ -79,6 +79,7 @@ static const struct rtw89_driver_info rtw89_8852bte_info = { .chip = &rtw8852bt_chip_info, .variant = NULL, .quirks = NULL, + .dev_id_quirks = 0, .bus = { .pci = &rtw8852bt_pci_info, }, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bu.c b/drivers/net/wireless/realtek/rtw89/rtw8852bu.c index 37111fed276f..308d3d570ff3 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852bu.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852bu.c @@ -31,6 +31,7 @@ static const struct rtw89_driver_info rtw89_8852bu_info = { .chip = &rtw8852b_chip_info, .variant = NULL, .quirks = NULL, + .dev_id_quirks = 0, .bus = { .usb = &rtw8852b_usb_info, } diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852ce.c b/drivers/net/wireless/realtek/rtw89/rtw8852ce.c index 150fed189414..3c64c0539205 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852ce.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852ce.c @@ -102,6 +102,7 @@ static const struct rtw89_driver_info rtw89_8852ce_info = { .chip = &rtw8852c_chip_info, .variant = NULL, .quirks = rtw8852c_pci_quirks, + .dev_id_quirks = 0, .bus = { .pci = &rtw8852c_pci_info, }, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852cu.c b/drivers/net/wireless/realtek/rtw89/rtw8852cu.c index 790fd1dec66d..8f89f9a31455 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852cu.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852cu.c @@ -33,6 +33,7 @@ static const struct rtw89_driver_info rtw89_8852cu_info = { .chip = &rtw8852c_chip_info, .variant = NULL, .quirks = NULL, + .dev_id_quirks = 0, .bus = { .usb = &rtw8852c_usb_info, }, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922ae.c b/drivers/net/wireless/realtek/rtw89/rtw8922ae.c index 90c62b757c57..5527a8db393b 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922ae.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922ae.c @@ -77,6 +77,7 @@ static const struct rtw89_driver_info rtw89_8922ae_info = { .chip = &rtw8922a_chip_info, .variant = NULL, .quirks = NULL, + .dev_id_quirks = 0, .bus = { .pci = &rtw8922a_pci_info, }, @@ -86,6 +87,7 @@ static const struct rtw89_driver_info rtw89_8922ae_vs_info = { .chip = &rtw8922a_chip_info, .variant = &rtw8922ae_vs_variant, .quirks = NULL, + .dev_id_quirks = 0, .bus = { .pci = &rtw8922a_pci_info, }, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922au.c b/drivers/net/wireless/realtek/rtw89/rtw8922au.c index 347bde171391..2b81de501d62 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922au.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922au.c @@ -32,6 +32,7 @@ static const struct rtw89_driver_info rtw89_8922au_info = { .chip = &rtw8922a_chip_info, .variant = NULL, .quirks = NULL, + .dev_id_quirks = 0, .bus = { .usb = &rtw8922a_usb_info, }, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922de.c b/drivers/net/wireless/realtek/rtw89/rtw8922de.c index f144e7fc76de..a1a81c338be3 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922de.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922de.c @@ -73,6 +73,7 @@ static const struct rtw89_driver_info rtw89_8922de_vs_info = { .chip = &rtw8922d_chip_info, .variant = &rtw8922de_vs_variant, .quirks = NULL, + .dev_id_quirks = 0, .bus = { .pci = &rtw8922d_pci_info, }, @@ -82,6 +83,7 @@ static const struct rtw89_driver_info rtw89_8922de_info = { .chip = &rtw8922d_chip_info, .variant = NULL, .quirks = NULL, + .dev_id_quirks = 0, .bus = { .pci = &rtw8922d_pci_info, }, diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c index c6d55e669776..88d7ec200837 100644 --- a/drivers/net/wireless/realtek/rtw89/usb.c +++ b/drivers/net/wireless/realtek/rtw89/usb.c @@ -1070,8 +1070,7 @@ int rtw89_usb_probe(struct usb_interface *intf, info = (const struct rtw89_driver_info *)id->driver_info; rtwdev = rtw89_alloc_ieee80211_hw(&intf->dev, - sizeof(struct rtw89_usb), - info->chip, info->variant); + sizeof(struct rtw89_usb), info); if (!rtwdev) { dev_err(&intf->dev, "failed to allocate hw\n"); return -ENOMEM; -- 2.25.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2 rtw-next 1/2] wifi: rtw89: add dev_id_quirks to driver_info for per-device quirk control 2026-05-25 8:51 ` [PATCH v2 rtw-next 1/2] wifi: rtw89: add dev_id_quirks to driver_info for per-device quirk control Ping-Ke Shih @ 2026-05-25 19:31 ` Greg KH 2026-05-26 1:09 ` Ping-Ke Shih 0 siblings, 1 reply; 8+ messages in thread From: Greg KH @ 2026-05-25 19:31 UTC (permalink / raw) To: Ping-Ke Shih Cc: linux-wireless, driver-core, johannes, wenjie.tsai, mh_chen, charlesl, sabae On Mon, May 25, 2026 at 04:51:47PM +0800, Ping-Ke Shih wrote: > --- a/drivers/net/wireless/realtek/rtw89/rtw8851be.c > +++ b/drivers/net/wireless/realtek/rtw89/rtw8851be.c > @@ -73,6 +73,7 @@ static const struct rtw89_driver_info rtw89_8851be_info = { > .chip = &rtw8851b_chip_info, > .variant = NULL, > .quirks = NULL, > + .dev_id_quirks = 0, Why are you manually adding a "= 0" for these when that's the default? No need to do so, only do it when it is set to something, right? thanks, greg k-h ^ permalink raw reply [flat|nested] 8+ messages in thread
* RE: [PATCH v2 rtw-next 1/2] wifi: rtw89: add dev_id_quirks to driver_info for per-device quirk control 2026-05-25 19:31 ` Greg KH @ 2026-05-26 1:09 ` Ping-Ke Shih 2026-05-27 11:48 ` Johnson Tsai 0 siblings, 1 reply; 8+ messages in thread From: Ping-Ke Shih @ 2026-05-26 1:09 UTC (permalink / raw) To: Greg KH Cc: linux-wireless@vger.kernel.org, driver-core@lists.linux.dev, johannes@sipsolutions.net, Johnson Tsai, Mh_chen, charlesl@valvesoftware.com, sabae@valvesoftware.com Greg KH <gregkh@linuxfoundation.org> wrote: > On Mon, May 25, 2026 at 04:51:47PM +0800, Ping-Ke Shih wrote: > > --- a/drivers/net/wireless/realtek/rtw89/rtw8851be.c > > +++ b/drivers/net/wireless/realtek/rtw89/rtw8851be.c > > @@ -73,6 +73,7 @@ static const struct rtw89_driver_info rtw89_8851be_info = { > > .chip = &rtw8851b_chip_info, > > .variant = NULL, > > .quirks = NULL, > > + .dev_id_quirks = 0, > > Why are you manually adding a "= 0" for these when that's the default? > No need to do so, only do it when it is set to something, right? I'd ask authors spending a little time to fill these default values because Realtek WiFi chips have many specific attributes for many chips, and somehow it gets messed. For example, - miss to fill value for a certain chip (people might only force on one chip he wants to fix) - for some cases, it should set 0 explicitly as the value (such as a threshold value of hardware register) - messed up the order of attributes People add a field along the existing field across all chips. If a field is omitted, somehow people might add the field at wrong place. - simply coding rule People might forget why, so I'd have a simple rule for them. I encountered these cases when I processed earlier Realtek WiFi drivers (rtlwifi, rtl8xxxu, rtw88), so I'd explicitly fill values to avoid them. Thanks Ping-Ke ^ permalink raw reply [flat|nested] 8+ messages in thread
* RE: [PATCH v2 rtw-next 1/2] wifi: rtw89: add dev_id_quirks to driver_info for per-device quirk control 2026-05-26 1:09 ` Ping-Ke Shih @ 2026-05-27 11:48 ` Johnson Tsai 0 siblings, 0 replies; 8+ messages in thread From: Johnson Tsai @ 2026-05-27 11:48 UTC (permalink / raw) To: Ping-Ke Shih, Greg KH Cc: linux-wireless@vger.kernel.org, driver-core@lists.linux.dev, johannes@sipsolutions.net, Mh_chen, charlesl@valvesoftware.com, sabae@valvesoftware.com On Tuesday, May 26, 2026 9:10, Ping-Ke Shih wrote: > Greg KH <gregkh@linuxfoundation.org> wrote: > > On Mon, May 25, 2026 at 04:51:47PM +0800, Ping-Ke Shih wrote: > > > --- a/drivers/net/wireless/realtek/rtw89/rtw8851be.c > > > +++ b/drivers/net/wireless/realtek/rtw89/rtw8851be.c > > > @@ -73,6 +73,7 @@ static const struct rtw89_driver_info > rtw89_8851be_info = { > > > .chip = &rtw8851b_chip_info, > > > .variant = NULL, > > > .quirks = NULL, > > > + .dev_id_quirks = 0, > > > > Why are you manually adding a "= 0" for these when that's the default? > > No need to do so, only do it when it is set to something, right? > > I'd ask authors spending a little time to fill these default values because > Realtek WiFi chips have many specific attributes for many chips, and > somehow it gets messed. For example, > - miss to fill value for a certain chip > (people might only force on one chip he wants to fix) > - for some cases, it should set 0 explicitly as the value > (such as a threshold value of hardware register) > - messed up the order of attributes > People add a field along the existing field across all chips. > If a field is omitted, somehow people might add the field at wrong place. > - simply coding rule > People might forget why, so I'd have a simple rule for them. > > I encountered these cases when I processed earlier Realtek WiFi drivers > (rtlwifi, rtl8xxxu, rtw88), so I'd explicitly fill values to avoid them. > Just a gentle follow-up on Ping-Ke's explanation regarding the explicit "= 0" initialization. If there are no further concerns on this, I will keep the current approach for this part and send out the v3 patch. Thanks, Johnson ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 rtw-next 2/2] wifi: rtw89: usb: add serial_number and uuid sysfs attributes for 0x28de:0x2432 2026-05-25 8:51 [PATCH v2 rtw-next 0/2] wifi: rtw89: usb: read serial_number and uuid via sysfs Ping-Ke Shih 2026-05-25 8:51 ` [PATCH v2 rtw-next 1/2] wifi: rtw89: add dev_id_quirks to driver_info for per-device quirk control Ping-Ke Shih @ 2026-05-25 8:51 ` Ping-Ke Shih 2026-05-25 19:32 ` Greg KH 1 sibling, 1 reply; 8+ messages in thread From: Ping-Ke Shih @ 2026-05-25 8:51 UTC (permalink / raw) To: linux-wireless Cc: driver-core, johannes, wenjie.tsai, mh_chen, charlesl, sabae From: Johnson Tsai <wenjie.tsai@realtek.com> Expose the device's Serial Number (SN) and UUID from EFUSE via two read-only sysfs attributes, `serial_number` and `uuid`, on the ieee80211 phy device under the `rtw89_usb` attribute group. This hardware identification information is essential for user-space applications to uniquely identify, track, and manage specific Wi-Fi adapters. For example, in automated factory provisioning or device management systems, user-space tools rely on the EFUSE serial number and UUID to bind configurations to specific physical adapters. Currently, standard wireless APIs do not expose this low-level hardware information, making these sysfs nodes the only viable solution for user space to extract this data. The attributes are gated behind a new RTW89_QUIRK_HW_INFO_SYSFS quirk, enabled only for the VID 0x28de / PID 0x2432 device via the dev_id_quirks field in rtw89_driver_info. Example usage from user-space: $ cat /sys/class/ieee80211/phy0/rtw89_usb/serial_number 3642000123 $ cat /sys/class/ieee80211/phy0/rtw89_usb/uuid aaec2b7c-0a55-4727-8de0-b30febccbbaa Cc: Elliot Saba <sabae@valvesoftware.com> Cc: Charles Lohr <charlesl@valvesoftware.com> Signed-off-by: Johnson Tsai <wenjie.tsai@realtek.com> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> --- .../ABI/testing/sysfs-class-ieee80211-rtw89 | 24 ++++++++ drivers/net/wireless/realtek/rtw89/core.h | 6 ++ drivers/net/wireless/realtek/rtw89/rtw8852c.c | 10 ++++ drivers/net/wireless/realtek/rtw89/rtw8852c.h | 6 +- .../net/wireless/realtek/rtw89/rtw8852cu.c | 12 +++- drivers/net/wireless/realtek/rtw89/usb.c | 57 +++++++++++++++++++ 6 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-class-ieee80211-rtw89 diff --git a/Documentation/ABI/testing/sysfs-class-ieee80211-rtw89 b/Documentation/ABI/testing/sysfs-class-ieee80211-rtw89 new file mode 100644 index 000000000000..7dfdce08a42f --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-ieee80211-rtw89 @@ -0,0 +1,24 @@ +What: /sys/class/ieee80211/phyX/rtw89_usb/serial_number +Date: May 2026 +Contact: Johnson Tsai <wenjie.tsai@realtek.com>, linux-wireless@vger.kernel.org +Description: (Read) Serial number burned into EFUSE of the RTL8852CU-based + USB Wi-Fi adapter. Only present on devices that set the + RTW89_QUIRK_HW_INFO_SYSFS quirk (currently VID 0x28de / + PID 0x2432). + + Format: %10phN (5 raw bytes printed as 10 lowercase hex + digits, no separators). + + Example: 3642000123 + +What: /sys/class/ieee80211/phyX/rtw89_usb/uuid +Date: May 2026 +Contact: Johnson Tsai <wenjie.tsai@realtek.com>, linux-wireless@vger.kernel.org +Description: (Read) UUID burned into EFUSE of the RTL8852CU-based USB Wi-Fi + adapter. Only present on devices that set the + RTW89_QUIRK_HW_INFO_SYSFS quirk (currently VID 0x28de / + PID 0x2432). + + Format: %pUb (RFC 4122 UUID in lowercase with hyphens). + + Example: aaec2b7c-0a55-4727-8de0-b30febccbbaa diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index e687216da5b6..09f17d958075 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -3615,6 +3615,9 @@ struct rtw89_sta_link { u32 data_tx_cnt_lmt:6; }; +#define RTW89_EFUSE_SN_LEN 5 +#define RTW89_EFUSE_UUID_LEN 16 + struct rtw89_efuse { bool valid; bool power_k_valid; @@ -3625,6 +3628,8 @@ struct rtw89_efuse { u8 adc_td; u8 bt_setting_2; u8 bt_setting_3; + u8 sn[RTW89_EFUSE_SN_LEN]; + u8 uuid[RTW89_EFUSE_UUID_LEN]; }; struct rtw89_phy_rate_pattern { @@ -5373,6 +5378,7 @@ enum rtw89_quirks { RTW89_QUIRK_PCI_BER, RTW89_QUIRK_THERMAL_PROT_120C, RTW89_QUIRK_THERMAL_PROT_110C, + RTW89_QUIRK_HW_INFO_SYSFS, NUM_OF_RTW89_QUIRKS, }; diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index 7bb1264bcaef..3861cce42b1b 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -621,6 +621,15 @@ static void rtw8852c_efuse_parsing_gain_offset(struct rtw89_dev *rtwdev, gain->offset_valid = valid; } +static void rtw8852c_efuse_copy_sn_uuid_usb(struct rtw89_dev *rtwdev, + const struct rtw8852c_efuse *map) +{ + struct rtw89_efuse *efuse = &rtwdev->efuse; + + memcpy(efuse->sn, map->u.sn, sizeof(efuse->sn)); + memcpy(efuse->uuid, map->u.uuid, sizeof(efuse->uuid)); +} + static int rtw8852c_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map, enum rtw89_efuse_block block) { @@ -640,6 +649,7 @@ static int rtw8852c_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map, break; case RTW89_HCI_TYPE_USB: ether_addr_copy(efuse->addr, map->u.mac_addr); + rtw8852c_efuse_copy_sn_uuid_usb(rtwdev, map); break; default: return -ENOTSUPP; diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.h b/drivers/net/wireless/realtek/rtw89/rtw8852c.h index 8585921ac6c4..b1d7c354c18e 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.h +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.h @@ -13,7 +13,11 @@ struct rtw8852c_u_efuse { u8 rsvd[0x88]; u8 mac_addr[ETH_ALEN]; -}; + u8 rsvd1[8]; + u8 sn[RTW89_EFUSE_SN_LEN]; + u8 rsvd2[29]; + u8 uuid[RTW89_EFUSE_UUID_LEN]; +} __packed; struct rtw8852c_e_efuse { u8 mac_addr[ETH_ALEN]; diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852cu.c b/drivers/net/wireless/realtek/rtw89/rtw8852cu.c index 8f89f9a31455..81ee96b0a048 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852cu.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852cu.c @@ -39,6 +39,16 @@ static const struct rtw89_driver_info rtw89_8852cu_info = { }, }; +static const struct rtw89_driver_info rtw89_8852cu_valve_info = { + .chip = &rtw8852c_chip_info, + .variant = NULL, + .quirks = NULL, + .dev_id_quirks = BIT(RTW89_QUIRK_HW_INFO_SYSFS), + .bus = { + .usb = &rtw8852c_usb_info, + }, +}; + static const struct usb_device_id rtw_8852cu_id_table[] = { { USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x03a6, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&rtw89_8852cu_info }, @@ -53,7 +63,7 @@ static const struct usb_device_id rtw_8852cu_id_table[] = { { USB_DEVICE_AND_INTERFACE_INFO(0x0db0, 0x991d, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&rtw89_8852cu_info }, { USB_DEVICE_AND_INTERFACE_INFO(0x28de, 0x2432, 0xff, 0xff, 0xff), - .driver_info = (kernel_ulong_t)&rtw89_8852cu_info }, + .driver_info = (kernel_ulong_t)&rtw89_8852cu_valve_info }, { USB_DEVICE_AND_INTERFACE_INFO(0x2c7c, 0x8206, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&rtw89_8852cu_info }, { USB_DEVICE_AND_INTERFACE_INFO(0x35b2, 0x0502, 0xff, 0xff, 0xff), diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c index 88d7ec200837..7e23d0a32025 100644 --- a/drivers/net/wireless/realtek/rtw89/usb.c +++ b/drivers/net/wireless/realtek/rtw89/usb.c @@ -1059,6 +1059,61 @@ static void rtw89_usb_intf_deinit(struct rtw89_dev *rtwdev, usb_set_intfdata(intf, NULL); } +static ssize_t serial_number_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct wiphy *wiphy = container_of(dev, struct wiphy, dev); + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct rtw89_dev *rtwdev = hw->priv; + struct rtw89_efuse *efuse = &rtwdev->efuse; + + return sysfs_emit(buf, "%*phN\n", + (int)sizeof(efuse->sn), efuse->sn); +} +static DEVICE_ATTR_RO(serial_number); + +static ssize_t uuid_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct wiphy *wiphy = container_of(dev, struct wiphy, dev); + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct rtw89_dev *rtwdev = hw->priv; + struct rtw89_efuse *efuse = &rtwdev->efuse; + + return sysfs_emit(buf, "%pUb\n", efuse->uuid); +} +static DEVICE_ATTR_RO(uuid); + +static struct attribute *rtw89_usb_attrs[] = { + &dev_attr_serial_number.attr, + &dev_attr_uuid.attr, + NULL, +}; + +static const struct attribute_group rtw89_usb_group = { + .name = "rtw89_usb", + .attrs = rtw89_usb_attrs, +}; +__ATTRIBUTE_GROUPS(rtw89_usb); + +static void rtw89_usb_sysfs_create(struct rtw89_dev *rtwdev) +{ + int ret; + + if (!test_bit(RTW89_QUIRK_HW_INFO_SYSFS, rtwdev->quirks)) + return; + + ret = sysfs_create_groups(&rtwdev->hw->wiphy->dev.kobj, + rtw89_usb_groups); + if (ret) + rtw89_warn(rtwdev, "failed to create sysfs groups: %d\n", ret); +} + +static void rtw89_usb_sysfs_remove(struct rtw89_dev *rtwdev) +{ + sysfs_remove_groups(&rtwdev->hw->wiphy->dev.kobj, rtw89_usb_groups); +} + int rtw89_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -1123,6 +1178,7 @@ int rtw89_usb_probe(struct usb_interface *intf, goto err_core_deinit; } + rtw89_usb_sysfs_create(rtwdev); rtw89_usb_start_rx(rtwdev); set_bit(RTW89_FLAG_PROBE_DONE, rtwdev->flags); @@ -1159,6 +1215,7 @@ void rtw89_usb_disconnect(struct usb_interface *intf) rtw89_usb_cancel_rx_bufs(rtwusb); rtw89_usb_cancel_tx_bufs(rtwusb); + rtw89_usb_sysfs_remove(rtwdev); rtw89_core_unregister(rtwdev); rtw89_core_deinit(rtwdev); rtw89_usb_deinit_rx(rtwdev); -- 2.25.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2 rtw-next 2/2] wifi: rtw89: usb: add serial_number and uuid sysfs attributes for 0x28de:0x2432 2026-05-25 8:51 ` [PATCH v2 rtw-next 2/2] wifi: rtw89: usb: add serial_number and uuid sysfs attributes for 0x28de:0x2432 Ping-Ke Shih @ 2026-05-25 19:32 ` Greg KH 2026-05-27 11:46 ` Johnson Tsai 0 siblings, 1 reply; 8+ messages in thread From: Greg KH @ 2026-05-25 19:32 UTC (permalink / raw) To: Ping-Ke Shih Cc: linux-wireless, driver-core, johannes, wenjie.tsai, mh_chen, charlesl, sabae On Mon, May 25, 2026 at 04:51:48PM +0800, Ping-Ke Shih wrote: > From: Johnson Tsai <wenjie.tsai@realtek.com> > > Expose the device's Serial Number (SN) and UUID from EFUSE via two > read-only sysfs attributes, `serial_number` and `uuid`, on the ieee80211 > phy device under the `rtw89_usb` attribute group. > > This hardware identification information is essential for user-space > applications to uniquely identify, track, and manage specific Wi-Fi > adapters. For example, in automated factory provisioning or device > management systems, user-space tools rely on the EFUSE serial number and > UUID to bind configurations to specific physical adapters. Currently, > standard wireless APIs do not expose this low-level hardware > information, making these sysfs nodes the only viable solution for > user space to extract this data. > > The attributes are gated behind a new RTW89_QUIRK_HW_INFO_SYSFS quirk, > enabled only for the VID 0x28de / PID 0x2432 device via the > dev_id_quirks field in rtw89_driver_info. > > Example usage from user-space: > $ cat /sys/class/ieee80211/phy0/rtw89_usb/serial_number > 3642000123 > $ cat /sys/class/ieee80211/phy0/rtw89_usb/uuid > aaec2b7c-0a55-4727-8de0-b30febccbbaa > > Cc: Elliot Saba <sabae@valvesoftware.com> > Cc: Charles Lohr <charlesl@valvesoftware.com> > Signed-off-by: Johnson Tsai <wenjie.tsai@realtek.com> > Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> > --- > .../ABI/testing/sysfs-class-ieee80211-rtw89 | 24 ++++++++ > drivers/net/wireless/realtek/rtw89/core.h | 6 ++ > drivers/net/wireless/realtek/rtw89/rtw8852c.c | 10 ++++ > drivers/net/wireless/realtek/rtw89/rtw8852c.h | 6 +- > .../net/wireless/realtek/rtw89/rtw8852cu.c | 12 +++- > drivers/net/wireless/realtek/rtw89/usb.c | 57 +++++++++++++++++++ > 6 files changed, 113 insertions(+), 2 deletions(-) > create mode 100644 Documentation/ABI/testing/sysfs-class-ieee80211-rtw89 > > diff --git a/Documentation/ABI/testing/sysfs-class-ieee80211-rtw89 b/Documentation/ABI/testing/sysfs-class-ieee80211-rtw89 > new file mode 100644 > index 000000000000..7dfdce08a42f > --- /dev/null > +++ b/Documentation/ABI/testing/sysfs-class-ieee80211-rtw89 > @@ -0,0 +1,24 @@ > +What: /sys/class/ieee80211/phyX/rtw89_usb/serial_number > +Date: May 2026 > +Contact: Johnson Tsai <wenjie.tsai@realtek.com>, linux-wireless@vger.kernel.org > +Description: (Read) Serial number burned into EFUSE of the RTL8852CU-based > + USB Wi-Fi adapter. Only present on devices that set the > + RTW89_QUIRK_HW_INFO_SYSFS quirk (currently VID 0x28de / > + PID 0x2432). > + > + Format: %10phN (5 raw bytes printed as 10 lowercase hex > + digits, no separators). > + > + Example: 3642000123 > + > +What: /sys/class/ieee80211/phyX/rtw89_usb/uuid > +Date: May 2026 > +Contact: Johnson Tsai <wenjie.tsai@realtek.com>, linux-wireless@vger.kernel.org > +Description: (Read) UUID burned into EFUSE of the RTL8852CU-based USB Wi-Fi > + adapter. Only present on devices that set the > + RTW89_QUIRK_HW_INFO_SYSFS quirk (currently VID 0x28de / > + PID 0x2432). > + > + Format: %pUb (RFC 4122 UUID in lowercase with hyphens). > + > + Example: aaec2b7c-0a55-4727-8de0-b30febccbbaa > diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h > index e687216da5b6..09f17d958075 100644 > --- a/drivers/net/wireless/realtek/rtw89/core.h > +++ b/drivers/net/wireless/realtek/rtw89/core.h > @@ -3615,6 +3615,9 @@ struct rtw89_sta_link { > u32 data_tx_cnt_lmt:6; > }; > > +#define RTW89_EFUSE_SN_LEN 5 > +#define RTW89_EFUSE_UUID_LEN 16 > + > struct rtw89_efuse { > bool valid; > bool power_k_valid; > @@ -3625,6 +3628,8 @@ struct rtw89_efuse { > u8 adc_td; > u8 bt_setting_2; > u8 bt_setting_3; > + u8 sn[RTW89_EFUSE_SN_LEN]; > + u8 uuid[RTW89_EFUSE_UUID_LEN]; > }; > > struct rtw89_phy_rate_pattern { > @@ -5373,6 +5378,7 @@ enum rtw89_quirks { > RTW89_QUIRK_PCI_BER, > RTW89_QUIRK_THERMAL_PROT_120C, > RTW89_QUIRK_THERMAL_PROT_110C, > + RTW89_QUIRK_HW_INFO_SYSFS, > > NUM_OF_RTW89_QUIRKS, > }; > diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c > index 7bb1264bcaef..3861cce42b1b 100644 > --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c > +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c > @@ -621,6 +621,15 @@ static void rtw8852c_efuse_parsing_gain_offset(struct rtw89_dev *rtwdev, > gain->offset_valid = valid; > } > > +static void rtw8852c_efuse_copy_sn_uuid_usb(struct rtw89_dev *rtwdev, > + const struct rtw8852c_efuse *map) > +{ > + struct rtw89_efuse *efuse = &rtwdev->efuse; > + > + memcpy(efuse->sn, map->u.sn, sizeof(efuse->sn)); > + memcpy(efuse->uuid, map->u.uuid, sizeof(efuse->uuid)); > +} > + > static int rtw8852c_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map, > enum rtw89_efuse_block block) > { > @@ -640,6 +649,7 @@ static int rtw8852c_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map, > break; > case RTW89_HCI_TYPE_USB: > ether_addr_copy(efuse->addr, map->u.mac_addr); > + rtw8852c_efuse_copy_sn_uuid_usb(rtwdev, map); > break; > default: > return -ENOTSUPP; > diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.h b/drivers/net/wireless/realtek/rtw89/rtw8852c.h > index 8585921ac6c4..b1d7c354c18e 100644 > --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.h > +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.h > @@ -13,7 +13,11 @@ > struct rtw8852c_u_efuse { > u8 rsvd[0x88]; > u8 mac_addr[ETH_ALEN]; > -}; > + u8 rsvd1[8]; > + u8 sn[RTW89_EFUSE_SN_LEN]; > + u8 rsvd2[29]; > + u8 uuid[RTW89_EFUSE_UUID_LEN]; > +} __packed; > > struct rtw8852c_e_efuse { > u8 mac_addr[ETH_ALEN]; > diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852cu.c b/drivers/net/wireless/realtek/rtw89/rtw8852cu.c > index 8f89f9a31455..81ee96b0a048 100644 > --- a/drivers/net/wireless/realtek/rtw89/rtw8852cu.c > +++ b/drivers/net/wireless/realtek/rtw89/rtw8852cu.c > @@ -39,6 +39,16 @@ static const struct rtw89_driver_info rtw89_8852cu_info = { > }, > }; > > +static const struct rtw89_driver_info rtw89_8852cu_valve_info = { > + .chip = &rtw8852c_chip_info, > + .variant = NULL, > + .quirks = NULL, > + .dev_id_quirks = BIT(RTW89_QUIRK_HW_INFO_SYSFS), > + .bus = { > + .usb = &rtw8852c_usb_info, > + }, > +}; > + > static const struct usb_device_id rtw_8852cu_id_table[] = { > { USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x03a6, 0xff, 0xff, 0xff), > .driver_info = (kernel_ulong_t)&rtw89_8852cu_info }, > @@ -53,7 +63,7 @@ static const struct usb_device_id rtw_8852cu_id_table[] = { > { USB_DEVICE_AND_INTERFACE_INFO(0x0db0, 0x991d, 0xff, 0xff, 0xff), > .driver_info = (kernel_ulong_t)&rtw89_8852cu_info }, > { USB_DEVICE_AND_INTERFACE_INFO(0x28de, 0x2432, 0xff, 0xff, 0xff), > - .driver_info = (kernel_ulong_t)&rtw89_8852cu_info }, > + .driver_info = (kernel_ulong_t)&rtw89_8852cu_valve_info }, > { USB_DEVICE_AND_INTERFACE_INFO(0x2c7c, 0x8206, 0xff, 0xff, 0xff), > .driver_info = (kernel_ulong_t)&rtw89_8852cu_info }, > { USB_DEVICE_AND_INTERFACE_INFO(0x35b2, 0x0502, 0xff, 0xff, 0xff), > diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c > index 88d7ec200837..7e23d0a32025 100644 > --- a/drivers/net/wireless/realtek/rtw89/usb.c > +++ b/drivers/net/wireless/realtek/rtw89/usb.c > @@ -1059,6 +1059,61 @@ static void rtw89_usb_intf_deinit(struct rtw89_dev *rtwdev, > usb_set_intfdata(intf, NULL); > } > > +static ssize_t serial_number_show(struct device *dev, > + struct device_attribute *attr, char *buf) > +{ > + struct wiphy *wiphy = container_of(dev, struct wiphy, dev); > + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); > + struct rtw89_dev *rtwdev = hw->priv; > + struct rtw89_efuse *efuse = &rtwdev->efuse; > + > + return sysfs_emit(buf, "%*phN\n", > + (int)sizeof(efuse->sn), efuse->sn); > +} > +static DEVICE_ATTR_RO(serial_number); > + > +static ssize_t uuid_show(struct device *dev, > + struct device_attribute *attr, char *buf) > +{ > + struct wiphy *wiphy = container_of(dev, struct wiphy, dev); > + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); > + struct rtw89_dev *rtwdev = hw->priv; > + struct rtw89_efuse *efuse = &rtwdev->efuse; > + > + return sysfs_emit(buf, "%pUb\n", efuse->uuid); > +} > +static DEVICE_ATTR_RO(uuid); > + > +static struct attribute *rtw89_usb_attrs[] = { > + &dev_attr_serial_number.attr, > + &dev_attr_uuid.attr, > + NULL, > +}; > + > +static const struct attribute_group rtw89_usb_group = { > + .name = "rtw89_usb", > + .attrs = rtw89_usb_attrs, > +}; > +__ATTRIBUTE_GROUPS(rtw89_usb); > + > +static void rtw89_usb_sysfs_create(struct rtw89_dev *rtwdev) > +{ > + int ret; > + > + if (!test_bit(RTW89_QUIRK_HW_INFO_SYSFS, rtwdev->quirks)) > + return; > + > + ret = sysfs_create_groups(&rtwdev->hw->wiphy->dev.kobj, > + rtw89_usb_groups); You just raced with userspace and lost, please use the is_visable callback instead, and make this the default group attributes. thanks, greg k-h ^ permalink raw reply [flat|nested] 8+ messages in thread
* RE: [PATCH v2 rtw-next 2/2] wifi: rtw89: usb: add serial_number and uuid sysfs attributes for 0x28de:0x2432 2026-05-25 19:32 ` Greg KH @ 2026-05-27 11:46 ` Johnson Tsai 0 siblings, 0 replies; 8+ messages in thread From: Johnson Tsai @ 2026-05-27 11:46 UTC (permalink / raw) To: Greg KH, Ping-Ke Shih Cc: linux-wireless@vger.kernel.org, driver-core@lists.linux.dev, johannes@sipsolutions.net, Mh_chen, charlesl@valvesoftware.com, sabae@valvesoftware.com On : Tuesday, May 26, 2026 3:33, Greg KH wrote: > On Mon, May 25, 2026 at 04:51:48PM +0800, Ping-Ke Shih wrote: > > From: Johnson Tsai <wenjie.tsai@realtek.com> > > > > Expose the device's Serial Number (SN) and UUID from EFUSE via two > > read-only sysfs attributes, `serial_number` and `uuid`, on the > > ieee80211 phy device under the `rtw89_usb` attribute group. > > > > This hardware identification information is essential for user-space > > applications to uniquely identify, track, and manage specific Wi-Fi > > adapters. For example, in automated factory provisioning or device > > management systems, user-space tools rely on the EFUSE serial number > > and UUID to bind configurations to specific physical adapters. > > Currently, standard wireless APIs do not expose this low-level > > hardware information, making these sysfs nodes the only viable > > solution for user space to extract this data. > > > > The attributes are gated behind a new RTW89_QUIRK_HW_INFO_SYSFS > quirk, > > enabled only for the VID 0x28de / PID 0x2432 device via the > > dev_id_quirks field in rtw89_driver_info. > > > > Example usage from user-space: > > $ cat /sys/class/ieee80211/phy0/rtw89_usb/serial_number > > 3642000123 > > $ cat /sys/class/ieee80211/phy0/rtw89_usb/uuid > > aaec2b7c-0a55-4727-8de0-b30febccbbaa > > > > Cc: Elliot Saba <sabae@valvesoftware.com> > > Cc: Charles Lohr <charlesl@valvesoftware.com> > > Signed-off-by: Johnson Tsai <wenjie.tsai@realtek.com> > > Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> > > --- > > .../ABI/testing/sysfs-class-ieee80211-rtw89 | 24 ++++++++ > > drivers/net/wireless/realtek/rtw89/core.h | 6 ++ > > drivers/net/wireless/realtek/rtw89/rtw8852c.c | 10 ++++ > > drivers/net/wireless/realtek/rtw89/rtw8852c.h | 6 +- > > .../net/wireless/realtek/rtw89/rtw8852cu.c | 12 +++- > > drivers/net/wireless/realtek/rtw89/usb.c | 57 +++++++++++++++++++ > > 6 files changed, 113 insertions(+), 2 deletions(-) create mode > > 100644 Documentation/ABI/testing/sysfs-class-ieee80211-rtw89 > > > > diff --git a/Documentation/ABI/testing/sysfs-class-ieee80211-rtw89 > > b/Documentation/ABI/testing/sysfs-class-ieee80211-rtw89 > > new file mode 100644 > > index 000000000000..7dfdce08a42f > > --- /dev/null > > +++ b/Documentation/ABI/testing/sysfs-class-ieee80211-rtw89 > > @@ -0,0 +1,24 @@ > > +What: /sys/class/ieee80211/phyX/rtw89_usb/serial_number > > +Date: May 2026 > > +Contact: Johnson Tsai <wenjie.tsai@realtek.com>, linux- > wireless@vger.kernel.org > > +Description: (Read) Serial number burned into EFUSE of the RTL8852CU- > based > > + USB Wi-Fi adapter. Only present on devices that set the > > + RTW89_QUIRK_HW_INFO_SYSFS quirk (currently VID 0x28de / > > + PID 0x2432). > > + > > + Format: %10phN (5 raw bytes printed as 10 lowercase hex > > + digits, no separators). > > + > > + Example: 3642000123 > > + > > +What: /sys/class/ieee80211/phyX/rtw89_usb/uuid > > +Date: May 2026 > > +Contact: Johnson Tsai <wenjie.tsai@realtek.com>, linux- > wireless@vger.kernel.org > > +Description: (Read) UUID burned into EFUSE of the RTL8852CU-based USB > Wi-Fi > > + adapter. Only present on devices that set the > > + RTW89_QUIRK_HW_INFO_SYSFS quirk (currently VID 0x28de / > > + PID 0x2432). > > + > > + Format: %pUb (RFC 4122 UUID in lowercase with hyphens). > > + > > + Example: aaec2b7c-0a55-4727-8de0-b30febccbbaa > > diff --git a/drivers/net/wireless/realtek/rtw89/core.h > > b/drivers/net/wireless/realtek/rtw89/core.h > > index e687216da5b6..09f17d958075 100644 > > --- a/drivers/net/wireless/realtek/rtw89/core.h > > +++ b/drivers/net/wireless/realtek/rtw89/core.h > > @@ -3615,6 +3615,9 @@ struct rtw89_sta_link { > > u32 data_tx_cnt_lmt:6; > > }; > > > > +#define RTW89_EFUSE_SN_LEN 5 > > +#define RTW89_EFUSE_UUID_LEN 16 > > + > > struct rtw89_efuse { > > bool valid; > > bool power_k_valid; > > @@ -3625,6 +3628,8 @@ struct rtw89_efuse { > > u8 adc_td; > > u8 bt_setting_2; > > u8 bt_setting_3; > > + u8 sn[RTW89_EFUSE_SN_LEN]; > > + u8 uuid[RTW89_EFUSE_UUID_LEN]; > > }; > > > > struct rtw89_phy_rate_pattern { > > @@ -5373,6 +5378,7 @@ enum rtw89_quirks { > > RTW89_QUIRK_PCI_BER, > > RTW89_QUIRK_THERMAL_PROT_120C, > > RTW89_QUIRK_THERMAL_PROT_110C, > > + RTW89_QUIRK_HW_INFO_SYSFS, > > > > NUM_OF_RTW89_QUIRKS, > > }; > > diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c > > b/drivers/net/wireless/realtek/rtw89/rtw8852c.c > > index 7bb1264bcaef..3861cce42b1b 100644 > > --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c > > +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c > > @@ -621,6 +621,15 @@ static void > rtw8852c_efuse_parsing_gain_offset(struct rtw89_dev *rtwdev, > > gain->offset_valid = valid; > > } > > > > +static void rtw8852c_efuse_copy_sn_uuid_usb(struct rtw89_dev *rtwdev, > > + const struct rtw8852c_efuse > > +*map) { > > + struct rtw89_efuse *efuse = &rtwdev->efuse; > > + > > + memcpy(efuse->sn, map->u.sn, sizeof(efuse->sn)); > > + memcpy(efuse->uuid, map->u.uuid, sizeof(efuse->uuid)); } > > + > > static int rtw8852c_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map, > > enum rtw89_efuse_block block) { @@ > > -640,6 +649,7 @@ static int rtw8852c_read_efuse(struct rtw89_dev > *rtwdev, u8 *log_map, > > break; > > case RTW89_HCI_TYPE_USB: > > ether_addr_copy(efuse->addr, map->u.mac_addr); > > + rtw8852c_efuse_copy_sn_uuid_usb(rtwdev, map); > > break; > > default: > > return -ENOTSUPP; > > diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.h > > b/drivers/net/wireless/realtek/rtw89/rtw8852c.h > > index 8585921ac6c4..b1d7c354c18e 100644 > > --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.h > > +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.h > > @@ -13,7 +13,11 @@ > > struct rtw8852c_u_efuse { > > u8 rsvd[0x88]; > > u8 mac_addr[ETH_ALEN]; > > -}; > > + u8 rsvd1[8]; > > + u8 sn[RTW89_EFUSE_SN_LEN]; > > + u8 rsvd2[29]; > > + u8 uuid[RTW89_EFUSE_UUID_LEN]; > > +} __packed; > > > > struct rtw8852c_e_efuse { > > u8 mac_addr[ETH_ALEN]; > > diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852cu.c > > b/drivers/net/wireless/realtek/rtw89/rtw8852cu.c > > index 8f89f9a31455..81ee96b0a048 100644 > > --- a/drivers/net/wireless/realtek/rtw89/rtw8852cu.c > > +++ b/drivers/net/wireless/realtek/rtw89/rtw8852cu.c > > @@ -39,6 +39,16 @@ static const struct rtw89_driver_info > rtw89_8852cu_info = { > > }, > > }; > > > > +static const struct rtw89_driver_info rtw89_8852cu_valve_info = { > > + .chip = &rtw8852c_chip_info, > > + .variant = NULL, > > + .quirks = NULL, > > + .dev_id_quirks = BIT(RTW89_QUIRK_HW_INFO_SYSFS), > > + .bus = { > > + .usb = &rtw8852c_usb_info, > > + }, > > +}; > > + > > static const struct usb_device_id rtw_8852cu_id_table[] = { > > { USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x03a6, 0xff, 0xff, 0xff), > > .driver_info = (kernel_ulong_t)&rtw89_8852cu_info }, @@ -53,7 > > +63,7 @@ static const struct usb_device_id rtw_8852cu_id_table[] = { > > { USB_DEVICE_AND_INTERFACE_INFO(0x0db0, 0x991d, 0xff, 0xff, 0xff), > > .driver_info = (kernel_ulong_t)&rtw89_8852cu_info }, > > { USB_DEVICE_AND_INTERFACE_INFO(0x28de, 0x2432, 0xff, 0xff, 0xff), > > - .driver_info = (kernel_ulong_t)&rtw89_8852cu_info }, > > + .driver_info = (kernel_ulong_t)&rtw89_8852cu_valve_info }, > > { USB_DEVICE_AND_INTERFACE_INFO(0x2c7c, 0x8206, 0xff, 0xff, 0xff), > > .driver_info = (kernel_ulong_t)&rtw89_8852cu_info }, > > { USB_DEVICE_AND_INTERFACE_INFO(0x35b2, 0x0502, 0xff, 0xff, > > 0xff), diff --git a/drivers/net/wireless/realtek/rtw89/usb.c > > b/drivers/net/wireless/realtek/rtw89/usb.c > > index 88d7ec200837..7e23d0a32025 100644 > > --- a/drivers/net/wireless/realtek/rtw89/usb.c > > +++ b/drivers/net/wireless/realtek/rtw89/usb.c > > @@ -1059,6 +1059,61 @@ static void rtw89_usb_intf_deinit(struct > rtw89_dev *rtwdev, > > usb_set_intfdata(intf, NULL); > > } > > > > +static ssize_t serial_number_show(struct device *dev, > > + struct device_attribute *attr, char > > +*buf) { > > + struct wiphy *wiphy = container_of(dev, struct wiphy, dev); > > + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); > > + struct rtw89_dev *rtwdev = hw->priv; > > + struct rtw89_efuse *efuse = &rtwdev->efuse; > > + > > + return sysfs_emit(buf, "%*phN\n", > > + (int)sizeof(efuse->sn), efuse->sn); } static > > +DEVICE_ATTR_RO(serial_number); > > + > > +static ssize_t uuid_show(struct device *dev, > > + struct device_attribute *attr, char *buf) { > > + struct wiphy *wiphy = container_of(dev, struct wiphy, dev); > > + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); > > + struct rtw89_dev *rtwdev = hw->priv; > > + struct rtw89_efuse *efuse = &rtwdev->efuse; > > + > > + return sysfs_emit(buf, "%pUb\n", efuse->uuid); } static > > +DEVICE_ATTR_RO(uuid); > > + > > +static struct attribute *rtw89_usb_attrs[] = { > > + &dev_attr_serial_number.attr, > > + &dev_attr_uuid.attr, > > + NULL, > > +}; > > + > > +static const struct attribute_group rtw89_usb_group = { > > + .name = "rtw89_usb", > > + .attrs = rtw89_usb_attrs, > > +}; > > +__ATTRIBUTE_GROUPS(rtw89_usb); > > + > > +static void rtw89_usb_sysfs_create(struct rtw89_dev *rtwdev) { > > + int ret; > > + > > + if (!test_bit(RTW89_QUIRK_HW_INFO_SYSFS, rtwdev->quirks)) > > + return; > > + > > + ret = sysfs_create_groups(&rtwdev->hw->wiphy->dev.kobj, > > + rtw89_usb_groups); > > You just raced with userspace and lost, please use the is_visable callback > instead, and make this the default group attributes. Thanks for the explanation. I see the problem now. The user space sysfs path remains identical, but the timing and mechanism are different. Using dev.kobj requires manual creation/removal outside the hardware lifecycle, whereas setting dev.groups will automatically handle creation/removal within the same hardware lifecycle to avoid the race condition. I will remove the manual sysfs creation and switch to default group attributes in v3. Specifically, the visibility of the entire group will be managed via the macro: /* Control the visibility of the entire attribute group */ .is_visible = SYSFS_GROUP_VISIBLE(rtw89_usb), And the group will be attached to the wiphy device default groups before registration: /* Attach the attribute group to the wiphy device */ rtwdev->hw->wiphy->dev.groups = rtw89_usb_groups; Thanks, Johnson ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-05-27 11:48 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-25 8:51 [PATCH v2 rtw-next 0/2] wifi: rtw89: usb: read serial_number and uuid via sysfs Ping-Ke Shih 2026-05-25 8:51 ` [PATCH v2 rtw-next 1/2] wifi: rtw89: add dev_id_quirks to driver_info for per-device quirk control Ping-Ke Shih 2026-05-25 19:31 ` Greg KH 2026-05-26 1:09 ` Ping-Ke Shih 2026-05-27 11:48 ` Johnson Tsai 2026-05-25 8:51 ` [PATCH v2 rtw-next 2/2] wifi: rtw89: usb: add serial_number and uuid sysfs attributes for 0x28de:0x2432 Ping-Ke Shih 2026-05-25 19:32 ` Greg KH 2026-05-27 11:46 ` Johnson Tsai
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox