From: Johnson Tsai <wenjie.tsai@realtek.com>
To: Greg KH <gregkh@linuxfoundation.org>, Ping-Ke Shih <pkshih@realtek.com>
Cc: "linux-wireless@vger.kernel.org" <linux-wireless@vger.kernel.org>,
"driver-core@lists.linux.dev" <driver-core@lists.linux.dev>,
"johannes@sipsolutions.net" <johannes@sipsolutions.net>,
Mh_chen <mh_chen@realtek.com>,
"charlesl@valvesoftware.com" <charlesl@valvesoftware.com>,
"sabae@valvesoftware.com" <sabae@valvesoftware.com>
Subject: RE: [PATCH v2 rtw-next 2/2] wifi: rtw89: usb: add serial_number and uuid sysfs attributes for 0x28de:0x2432
Date: Wed, 27 May 2026 11:46:15 +0000 [thread overview]
Message-ID: <ea36d1a110984db6a583d82449ee532e@realtek.com> (raw)
In-Reply-To: <2026052524-ammonia-zeppelin-9edb@gregkh>
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
prev parent reply other threads:[~2026-05-27 11:46 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
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 message]
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=ea36d1a110984db6a583d82449ee532e@realtek.com \
--to=wenjie.tsai@realtek.com \
--cc=charlesl@valvesoftware.com \
--cc=driver-core@lists.linux.dev \
--cc=gregkh@linuxfoundation.org \
--cc=johannes@sipsolutions.net \
--cc=linux-wireless@vger.kernel.org \
--cc=mh_chen@realtek.com \
--cc=pkshih@realtek.com \
--cc=sabae@valvesoftware.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