Linux wireless drivers development
 help / color / mirror / Atom feed
* [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

* [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 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 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 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 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

* 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

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