* [RFC rtw-next 1/2] wifi: rtw89: usb: add hw_info sysfs attribute
@ 2026-05-19 7:24 Ping-Ke Shih
2026-05-19 7:24 ` [RFC rtw-next 2/2] wifi: rtw89: usb: add sysfs write example Ping-Ke Shih
2026-05-19 7:37 ` [RFC rtw-next 1/2] wifi: rtw89: usb: add hw_info sysfs attribute Ping-Ke Shih
0 siblings, 2 replies; 6+ messages in thread
From: Ping-Ke Shih @ 2026-05-19 7:24 UTC (permalink / raw)
To: linux-wireless; +Cc: wenjie.tsai
From: Johnson Tsai <wenjie.tsai@realtek.com>
Expose the device's Serial Number (SN) and UUID from EFUSE through a
read-only `hw_info` sysfs attribute on the USB interface device.
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 SN and UUID
to bind specific configurations to a physical adapter. Currently,
standard wireless APIs do not expose this low-level hardware
information, making this sysfs node the only viable and necessary
solution for user space to extract this data.
Relying on debugfs or setuid binaries is unviable for production
environments, as explicitly requested by Valve (Steam). Steam frequently
runs inside unprivileged containers (e.g., Flatpak) where debugfs and
setuid binaries are inaccessible. Furthermore, many end-user systems
disable debugfs in their kernel configs, and strict access controls
(SELinux, AppArmor) block it regardless of permissions. Since Steam
installs as an unprivileged user, setuid deployments are impossible.
Consequently, exposing this data via a world-readable (0444) sysfs
node is the only functional approach to ensure reliable, unprivileged
access across diverse customer systems.
Example usage from user-space:
$ cat /sys/bus/usb/devices/2-3.1.2:1.0/hw_info
SN: 36 42 00 01 23
UUID: aa ec 2b 7c 0a 55 47 27 8d e0 b3 0f eb cc bb aa
User-space scripts can easily iterate over bound devices to extract
this information:
for dev in /sys/bus/usb/drivers/rtw89_8852cu/[0-9]*:*; do
dev_id=$(basename "$dev")
echo "--- Device: /sys/bus/usb/devices/$dev_id ---"
cat "$dev/hw_info"
done
Signed-off-by: Johnson Tsai <wenjie.tsai@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
Hi maintainers,
We are submitting this RFC to discuss the most appropriate upstream path for
exposing hardware-specific IDs to unprivileged container environments.
1. Given the strict environment limitations (Flatpak, missing debugfs, LSMs),
is a read-only sysfs attribute acceptable for this specific hardware data?
2. If exposing this globally via sysfs is not preferred, would it be acceptable
to restrict the creation of this node to specific vendor VID/PIDs only?
3. If sysfs is strictly a no-go for this use case, what is the upstream-recommended
method for an unprivileged, sandboxed application to retrieve eFuse data?
---
drivers/net/wireless/realtek/rtw89/usb.c | 51 +++++++++++++++++++++++-
1 file changed, 50 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c
index c6d55e669776..53dcb84af5c0 100644
--- a/drivers/net/wireless/realtek/rtw89/usb.c
+++ b/drivers/net/wireless/realtek/rtw89/usb.c
@@ -1059,6 +1059,41 @@ static void rtw89_usb_intf_deinit(struct rtw89_dev *rtwdev,
usb_set_intfdata(intf, NULL);
}
+static ssize_t hw_info_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct ieee80211_hw *hw;
+ struct rtw89_dev *rtwdev;
+ struct rtw89_efuse *efuse;
+ ssize_t ret;
+
+ device_lock(dev);
+
+ hw = usb_get_intfdata(intf);
+ if (!hw) {
+ device_unlock(dev);
+ return -ENODEV;
+ }
+
+ rtwdev = hw->priv;
+ efuse = &rtwdev->efuse;
+
+ ret = sysfs_emit(buf, "SN: %*ph\nUUID: %*ph\n",
+ (int)sizeof(efuse->sn), efuse->sn,
+ (int)sizeof(efuse->uuid), efuse->uuid);
+
+ device_unlock(dev);
+ return ret;
+}
+static DEVICE_ATTR_RO(hw_info);
+
+static struct attribute *rtw89_usb_attrs[] = {
+ &dev_attr_hw_info.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(rtw89_usb);
+
int rtw89_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -1118,10 +1153,16 @@ int rtw89_usb_probe(struct usb_interface *intf,
goto err_core_deinit;
}
+ ret = sysfs_create_groups(&intf->dev.kobj, rtw89_usb_groups);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to create sysfs groups: %d\n", ret);
+ goto err_core_deinit;
+ }
+
ret = rtw89_core_register(rtwdev);
if (ret) {
rtw89_err(rtwdev, "failed to register core\n");
- goto err_core_deinit;
+ goto err_remove_sysfs;
}
rtw89_usb_start_rx(rtwdev);
@@ -1130,6 +1171,8 @@ int rtw89_usb_probe(struct usb_interface *intf,
return 0;
+err_remove_sysfs:
+ sysfs_remove_groups(&intf->dev.kobj, rtw89_usb_groups);
err_core_deinit:
rtw89_core_deinit(rtwdev);
err_deinit_rx:
@@ -1154,12 +1197,18 @@ void rtw89_usb_disconnect(struct usb_interface *intf)
if (!hw)
return;
+ /* Clear intfdata immediately so any concurrent sysfs show waiting on
+ * device_lock will see NULL and bail out safely.
+ */
+ usb_set_intfdata(intf, NULL);
+
rtwdev = hw->priv;
rtwusb = rtw89_usb_priv(rtwdev);
rtw89_usb_cancel_rx_bufs(rtwusb);
rtw89_usb_cancel_tx_bufs(rtwusb);
+ sysfs_remove_groups(&intf->dev.kobj, rtw89_usb_groups);
rtw89_core_unregister(rtwdev);
rtw89_core_deinit(rtwdev);
rtw89_usb_deinit_rx(rtwdev);
base-commit: 7076af642955693935e60bc94546d105fb0395ca
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [RFC rtw-next 2/2] wifi: rtw89: usb: add sysfs write example
2026-05-19 7:24 [RFC rtw-next 1/2] wifi: rtw89: usb: add hw_info sysfs attribute Ping-Ke Shih
@ 2026-05-19 7:24 ` Ping-Ke Shih
2026-05-19 7:37 ` [RFC rtw-next 1/2] wifi: rtw89: usb: add hw_info sysfs attribute Ping-Ke Shih
1 sibling, 0 replies; 6+ messages in thread
From: Ping-Ke Shih @ 2026-05-19 7:24 UTC (permalink / raw)
To: linux-wireless; +Cc: wenjie.tsai
From: Johnson Tsai <wenjie.tsai@realtek.com>
Add a simple echo_sum sysfs attribute on the USB interface device as
an RFC example for discussing whether a writable sysfs interface is
acceptable for this driver.
The attribute accepts two integers from userspace, stores their sum in
driver private data, and exposes the result.
Signed-off-by: Johnson Tsai <wenjie.tsai@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/usb.c | 38 ++++++++++++++++++++++++
drivers/net/wireless/realtek/rtw89/usb.h | 2 ++
2 files changed, 40 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c
index 53dcb84af5c0..566618e9f3b8 100644
--- a/drivers/net/wireless/realtek/rtw89/usb.c
+++ b/drivers/net/wireless/realtek/rtw89/usb.c
@@ -1059,6 +1059,43 @@ static void rtw89_usb_intf_deinit(struct rtw89_dev *rtwdev,
usb_set_intfdata(intf, NULL);
}
+static ssize_t echo_sum_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct ieee80211_hw *hw = usb_get_intfdata(intf);
+ struct rtw89_usb *rtwusb;
+
+ if (!hw)
+ return -ENODEV;
+
+ rtwusb = rtw89_usb_priv(hw->priv);
+
+ return sysfs_emit(buf, "%u\n", rtwusb->echo_sum);
+}
+
+static ssize_t echo_sum_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct ieee80211_hw *hw = usb_get_intfdata(intf);
+ struct rtw89_usb *rtwusb;
+ int a, b;
+
+ if (!hw)
+ return -ENODEV;
+
+ if (sscanf(buf, "%d %d", &a, &b) != 2)
+ return -EINVAL;
+
+ rtwusb = rtw89_usb_priv(hw->priv);
+ rtwusb->echo_sum = a + b;
+
+ return count;
+}
+static DEVICE_ATTR_ADMIN_RW(echo_sum);
+
static ssize_t hw_info_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -1089,6 +1126,7 @@ static ssize_t hw_info_show(struct device *dev,
static DEVICE_ATTR_RO(hw_info);
static struct attribute *rtw89_usb_attrs[] = {
+ &dev_attr_echo_sum.attr,
&dev_attr_hw_info.attr,
NULL,
};
diff --git a/drivers/net/wireless/realtek/rtw89/usb.h b/drivers/net/wireless/realtek/rtw89/usb.h
index bdf312559743..9eba6264a9a2 100644
--- a/drivers/net/wireless/realtek/rtw89/usb.h
+++ b/drivers/net/wireless/realtek/rtw89/usb.h
@@ -87,6 +87,8 @@ struct rtw89_usb {
struct sk_buff_head tx_queue[RTW89_TXCH_NUM];
atomic_t tx_inflight[RTW89_TXCH_NUM];
+
+ u32 echo_sum;
};
static inline struct rtw89_usb *rtw89_usb_priv(struct rtw89_dev *rtwdev)
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* RE: [RFC rtw-next 1/2] wifi: rtw89: usb: add hw_info sysfs attribute
2026-05-19 7:24 [RFC rtw-next 1/2] wifi: rtw89: usb: add hw_info sysfs attribute Ping-Ke Shih
2026-05-19 7:24 ` [RFC rtw-next 2/2] wifi: rtw89: usb: add sysfs write example Ping-Ke Shih
@ 2026-05-19 7:37 ` Ping-Ke Shih
2026-05-19 12:11 ` Johannes Berg
1 sibling, 1 reply; 6+ messages in thread
From: Ping-Ke Shih @ 2026-05-19 7:37 UTC (permalink / raw)
To: linux-wireless@vger.kernel.org, johannes@sipsolutions.net; +Cc: Johnson Tsai
Hi Johannes,
Need your comments on usage of sysfs.
Ping-Ke Shih <pkshih@realtek.com> wrote:
> From: Johnson Tsai <wenjie.tsai@realtek.com>
>
> Expose the device's Serial Number (SN) and UUID from EFUSE through a
> read-only `hw_info` sysfs attribute on the USB interface device.
>
> 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 SN and UUID
> to bind specific configurations to a physical adapter. Currently,
> standard wireless APIs do not expose this low-level hardware
> information, making this sysfs node the only viable and necessary
> solution for user space to extract this data.
>
> Relying on debugfs or setuid binaries is unviable for production
> environments, as explicitly requested by Valve (Steam). Steam frequently
> runs inside unprivileged containers (e.g., Flatpak) where debugfs and
> setuid binaries are inaccessible. Furthermore, many end-user systems
> disable debugfs in their kernel configs, and strict access controls
> (SELinux, AppArmor) block it regardless of permissions. Since Steam
> installs as an unprivileged user, setuid deployments are impossible.
> Consequently, exposing this data via a world-readable (0444) sysfs
> node is the only functional approach to ensure reliable, unprivileged
> access across diverse customer systems.
>
> Example usage from user-space:
> $ cat /sys/bus/usb/devices/2-3.1.2:1.0/hw_info
> SN: 36 42 00 01 23
> UUID: aa ec 2b 7c 0a 55 47 27 8d e0 b3 0f eb cc bb aa
>
> User-space scripts can easily iterate over bound devices to extract
> this information:
> for dev in /sys/bus/usb/drivers/rtw89_8852cu/[0-9]*:*; do
> dev_id=$(basename "$dev")
> echo "--- Device: /sys/bus/usb/devices/$dev_id ---"
> cat "$dev/hw_info"
> done
>
> Signed-off-by: Johnson Tsai <wenjie.tsai@realtek.com>
> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
> ---
> Hi maintainers,
>
> We are submitting this RFC to discuss the most appropriate upstream path for
> exposing hardware-specific IDs to unprivileged container environments.
>
> 1. Given the strict environment limitations (Flatpak, missing debugfs, LSMs),
> is a read-only sysfs attribute acceptable for this specific hardware data?
> 2. If exposing this globally via sysfs is not preferred, would it be acceptable
> to restrict the creation of this node to specific vendor VID/PIDs only?
> 3. If sysfs is strictly a no-go for this use case, what is the upstream-recommended
> method for an unprivileged, sandboxed application to retrieve eFuse data?
I also looked up lore.kernel.org and only found a thread commented by Kalle [1].
However, it is not clear to us if sysfs is suitable to read efuse SN/UUID.
[1] https://lore.kernel.org/linux-wireless/87ziib3da5.fsf@kamboji.qca.qualcomm.com/
> ---
> drivers/net/wireless/realtek/rtw89/usb.c | 51 +++++++++++++++++++++++-
> 1 file changed, 50 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c
> index c6d55e669776..53dcb84af5c0 100644
> --- a/drivers/net/wireless/realtek/rtw89/usb.c
> +++ b/drivers/net/wireless/realtek/rtw89/usb.c
> @@ -1059,6 +1059,41 @@ static void rtw89_usb_intf_deinit(struct rtw89_dev *rtwdev,
> usb_set_intfdata(intf, NULL);
> }
>
> +static ssize_t hw_info_show(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct usb_interface *intf = to_usb_interface(dev);
> + struct ieee80211_hw *hw;
> + struct rtw89_dev *rtwdev;
> + struct rtw89_efuse *efuse;
> + ssize_t ret;
> +
> + device_lock(dev);
I think it isn't necessary to do lock/unlock in show ops. We will revise
it by v2.
[...]
Thanks
Ping-Ke
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC rtw-next 1/2] wifi: rtw89: usb: add hw_info sysfs attribute
2026-05-19 7:37 ` [RFC rtw-next 1/2] wifi: rtw89: usb: add hw_info sysfs attribute Ping-Ke Shih
@ 2026-05-19 12:11 ` Johannes Berg
2026-05-19 12:22 ` Greg KH
0 siblings, 1 reply; 6+ messages in thread
From: Johannes Berg @ 2026-05-19 12:11 UTC (permalink / raw)
To: Ping-Ke Shih, linux-wireless@vger.kernel.org; +Cc: Johnson Tsai, driver-core
Hi,
> > Example usage from user-space:
> > $ cat /sys/bus/usb/devices/2-3.1.2:1.0/hw_info
> > SN: 36 42 00 01 23
> > UUID: aa ec 2b 7c 0a 55 47 27 8d e0 b3 0f eb cc bb aa
Sysfs has a "one value per file" rule (soft rule according to the docs,
but harder in practice, I believe), so seems if anything that should be
two files. Maybe a UUID should also be formatted as such with %pU or
similar.
> I also looked up lore.kernel.org and only found a thread commented by Kalle [1].
> However, it is not clear to us if sysfs is suitable to read efuse SN/UUID.
>
> [1] https://lore.kernel.org/linux-wireless/87ziib3da5.fsf@kamboji.qca.qualcomm.com/
It seems to me this was more in the context of _writable_ files to do
some operations.
I don't think I have a problem with this, but sysfs also has
documentation requirements, and we should probably ask
driver-core@lists.linux.dev.
I'm not really quite sure I see the _point_ of identifying the serial
number of a wifi device in a container, but I guess you do.
johannes
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC rtw-next 1/2] wifi: rtw89: usb: add hw_info sysfs attribute
2026-05-19 12:11 ` Johannes Berg
@ 2026-05-19 12:22 ` Greg KH
2026-05-20 9:41 ` Johnson Tsai
0 siblings, 1 reply; 6+ messages in thread
From: Greg KH @ 2026-05-19 12:22 UTC (permalink / raw)
To: Johannes Berg
Cc: Ping-Ke Shih, linux-wireless@vger.kernel.org, Johnson Tsai,
driver-core
On Tue, May 19, 2026 at 02:11:32PM +0200, Johannes Berg wrote:
> Hi,
>
> > > Example usage from user-space:
> > > $ cat /sys/bus/usb/devices/2-3.1.2:1.0/hw_info
> > > SN: 36 42 00 01 23
> > > UUID: aa ec 2b 7c 0a 55 47 27 8d e0 b3 0f eb cc bb aa
>
> Sysfs has a "one value per file" rule (soft rule according to the docs,
> but harder in practice, I believe), so seems if anything that should be
> two files. Maybe a UUID should also be formatted as such with %pU or
> similar.
That should be 2 separate sysfs files please.
And yes, use %pU.
And be careful about exposing serial numbers to userspace, some systems
don't like normal users to read them so be sure to get the permissions
correct. We had to add some USB code for ALLOW_SERIAL_NUMBER to make it
so that systems can handle this if they want to.
And shouldn't this just be the USB serial number to start with? Why is
there a different string here? We already have a sysfs file for this
value.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [RFC rtw-next 1/2] wifi: rtw89: usb: add hw_info sysfs attribute
2026-05-19 12:22 ` Greg KH
@ 2026-05-20 9:41 ` Johnson Tsai
0 siblings, 0 replies; 6+ messages in thread
From: Johnson Tsai @ 2026-05-20 9:41 UTC (permalink / raw)
To: Greg KH, Johannes Berg
Cc: Ping-Ke Shih, linux-wireless@vger.kernel.org,
driver-core@lists.linux.dev, sabae@valvesoftware.com,
Charles Lohr
On Tuesday, May 19, 2026 20:23, Greg KH <gregkh@linuxfoundation.org> wrote:
> On Tue, May 19, 2026 at 02:11:32PM +0200, Johannes Berg wrote:
> > Hi,
> >
> > > > Example usage from user-space:
> > > > $ cat /sys/bus/usb/devices/2-3.1.2:1.0/hw_info
> > > > SN: 36 42 00 01 23
> > > > UUID: aa ec 2b 7c 0a 55 47 27 8d e0 b3 0f eb cc bb aa
> >
> > Sysfs has a "one value per file" rule (soft rule according to the
> > docs, but harder in practice, I believe), so seems if anything that
> > should be two files. Maybe a UUID should also be formatted as such
> > with %pU or similar.
>
> That should be 2 separate sysfs files please.
>
> And yes, use %pU.
The v2 patch will use separate `sn` and `uuid` attributes, with `uuid`
formatted via `%pU`. We also removed the spaces in `sn` to provide a clean
string.
Example usage from user-space:
$ cat /sys/bus/usb/devices/2-3.1.2:1.0/sn
3642000123
$ cat /sys/bus/usb/devices/2-3.1.2:1.0/uuid
aaec2b7c-0a55-4727-8de0-b30febccbbaa
>
> And be careful about exposing serial numbers to userspace, some systems
> don't like normal users to read them so be sure to get the permissions correct.
> We had to add some USB code for ALLOW_SERIAL_NUMBER to make it so that
> systems can handle this if they want to.
>
> And shouldn't this just be the USB serial number to start with? Why is there a
> different string here? We already have a sysfs file for this value.
Regarding the serial number and permission design, these are requirements
from Valve, so we have CC'd them here to provide the background.
Hi Elliot and Charles, could you please help explain the requirements and use case here?
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-05-20 9:41 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-19 7:24 [RFC rtw-next 1/2] wifi: rtw89: usb: add hw_info sysfs attribute Ping-Ke Shih
2026-05-19 7:24 ` [RFC rtw-next 2/2] wifi: rtw89: usb: add sysfs write example Ping-Ke Shih
2026-05-19 7:37 ` [RFC rtw-next 1/2] wifi: rtw89: usb: add hw_info sysfs attribute Ping-Ke Shih
2026-05-19 12:11 ` Johannes Berg
2026-05-19 12:22 ` Greg KH
2026-05-20 9:41 ` Johnson Tsai
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox