| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/08/25 19:11 | flow | patch-triage |
3mArgs:null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"KMSANReasoning": "",
"NeedsKMSAN": false,
"Reasoning": "The patch adds support for the RTL8723BS SDIO wireless chip and modifies the SDIO TX/RX handling in the rtw88 driver. Since there is no virtual SDIO host controller or software-emulated SDIO device framework in the kernel (unlike USB gadget or mac80211_hwsim), and standard QEMU does not emulate SDIO devices, this code is impossible to reach in virtualized environments.",
"WorthFuzzing": false
} |
| 1/1 | 2026/08/25 19:11 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 92b4ff601f6b05a5efdc1c39846382a7ad36045c\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Tue Aug 25 19:11:25 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h\nindex c6e981ba79868..8f86f7c12de5a 100644\n--- a/drivers/net/wireless/realtek/rtw88/main.h\n+++ b/drivers/net/wireless/realtek/rtw88/main.h\n@@ -194,6 +194,7 @@ enum rtw_chip_type {\n \tRTW_CHIP_TYPE_8723D,\n \tRTW_CHIP_TYPE_8821C,\n \tRTW_CHIP_TYPE_8703B,\n+\tRTW_CHIP_TYPE_8723B,\n \tRTW_CHIP_TYPE_8821A,\n \tRTW_CHIP_TYPE_8812A,\n \tRTW_CHIP_TYPE_8814A,\n@@ -2194,6 +2195,12 @@ static inline bool rtw_chip_has_tx_stbc(struct rtw_dev *rtwdev)\n \treturn rtwdev-\u003echip-\u003etx_stbc;\n }\n \n+static inline bool rtw_is_8723bs(struct rtw_dev *rtwdev)\n+{\n+\treturn rtwdev-\u003echip-\u003eid == RTW_CHIP_TYPE_8723B \u0026\u0026\n+\t rtwdev-\u003ehci.type == RTW_HCI_TYPE_SDIO;\n+}\n+\n static inline u8 rtw_acquire_macid(struct rtw_dev *rtwdev)\n {\n \tunsigned long mac_id;\ndiff --git a/drivers/net/wireless/realtek/rtw88/rx.c b/drivers/net/wireless/realtek/rtw88/rx.c\nindex 01fd299abb7fe..fde21c840ac02 100644\n--- a/drivers/net/wireless/realtek/rtw88/rx.c\n+++ b/drivers/net/wireless/realtek/rtw88/rx.c\n@@ -253,10 +253,12 @@ static void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,\n \n \trtw_rx_addr_match(rtwdev, pkt_stat, hdr);\n \n-\t/* Rtl8723cs driver checks for size \u003c 14 or size \u003e 8192 and\n-\t * simply drops the packet.\n+\t/*\n+\t * Rtl8723cs and rtl8723bs drivers check for size \u003c 14 or size \u003e 8192\n+\t * and simply drop the packet.\n \t */\n-\tif (rtwdev-\u003echip-\u003eid == RTW_CHIP_TYPE_8703B \u0026\u0026 pkt_stat-\u003epkt_len == 0) {\n+\tif (pkt_stat-\u003epkt_len == 0 \u0026\u0026\n+\t (rtwdev-\u003echip-\u003eid == RTW_CHIP_TYPE_8703B || rtw_is_8723bs(rtwdev))) {\n \t\trx_status-\u003eflag |= RX_FLAG_NO_PSDU;\n \t\trtw_dbg(rtwdev, RTW_DBG_RX, \"zero length packet\");\n \t}\ndiff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c\nindex 5b40d74b16ee0..1a85ed1431b48 100644\n--- a/drivers/net/wireless/realtek/rtw88/sdio.c\n+++ b/drivers/net/wireless/realtek/rtw88/sdio.c\n@@ -20,6 +20,17 @@\n #include \"tx.h\"\n \n #define RTW_SDIO_INDIRECT_RW_RETRIES\t\t\t50\n+#define RTW_SDIO_OQT_TIMEOUT_MS\t\t\t\t1000\n+\n+/*\n+ * 8723BS SDIO TX FIFO back-pressure watermarks: stop the mac80211 queue once\n+ * the per-AC software FIFO fills past the high watermark, and wake it from the\n+ * TX drain path once it falls back to the low one. Bounds the queueing latency\n+ * that otherwise causes uplink bufferbloat / congestion collapse.\n+ */\n+#define RTW_SDIO_TX_FIFO_HIWATER\t\t\t16\n+#define RTW_SDIO_TX_FIFO_LOWATER\t\t\t8\n+#define RTW_SDIO_TX_RETRY_DELAY\t\t\tmsecs_to_jiffies(1)\n \n static bool rtw_sdio_is_bus_addr(u32 addr)\n {\n@@ -548,12 +559,164 @@ static int rtw_sdio_read_port(struct rtw_dev *rtwdev, u8 *buf, size_t count)\n \treturn ret;\n }\n \n+/*\n+ * The cached free page counters are a fast path hint only. The transmit\n+ * paths read and update them under tx_credit_lock; rtw_sdio_start() seeds\n+ * them outside it, so they are atomic_t. Whenever they claim there is not\n+ * enough room they are resynchronised from the chip before the caller gives\n+ * up, which also absorbs any drift.\n+ */\n+static void rtw_sdio_8723bs_store_free_txpg(struct rtw_dev *rtwdev,\n+\t\t\t\t\t u32 free_txpg)\n+{\n+\tstruct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev-\u003epriv;\n+\n+\tatomic_set(\u0026rtwsdio-\u003efree_pg_high,\n+\t\t u32_get_bits(free_txpg, BIT_FREE_TXPG_HIGH));\n+\tatomic_set(\u0026rtwsdio-\u003efree_pg_normal,\n+\t\t u32_get_bits(free_txpg, BIT_FREE_TXPG_NORMAL));\n+\tatomic_set(\u0026rtwsdio-\u003efree_pg_low,\n+\t\t u32_get_bits(free_txpg, BIT_FREE_TXPG_LOW));\n+\tatomic_set(\u0026rtwsdio-\u003efree_pg_pub,\n+\t\t u32_get_bits(free_txpg, BIT_FREE_TXPG_PUB));\n+}\n+\n+/*\n+ * Refresh the cached counters from the chip. Returns false when the chip\n+ * reports no free pages at all, which means the counts cannot be trusted\n+ * and the caller has to decide what to do instead.\n+ */\n+static bool rtw_sdio_8723bs_sync_free_txpg(struct rtw_dev *rtwdev)\n+{\n+\tu32 free_txpg = rtw_read32(rtwdev, REG_SDIO_FREE_TXPG);\n+\n+\tif (!free_txpg)\n+\t\treturn false;\n+\n+\trtw_sdio_8723bs_store_free_txpg(rtwdev, free_txpg);\n+\n+\treturn true;\n+}\n+\n+/*\n+ * Size of the public page pool: whatever the transmit page allocation has\n+ * left once the per queue pools are taken out. Fails if the allocation\n+ * cannot cover the reserved queues, since the remainder would underflow and\n+ * there would be no sensible pool to hand out.\n+ */\n+static int rtw_sdio_8723bs_pubq_num(struct rtw_dev *rtwdev, u16 *pubq_num)\n+{\n+\tconst struct rtw_page_table *pg_tbl = \u0026rtwdev-\u003echip-\u003epage_table[0];\n+\tu16 acq_pg_num = rtwdev-\u003efifo.acq_pg_num;\n+\tu16 reserved_num;\n+\n+\treserved_num = pg_tbl-\u003ehq_num + pg_tbl-\u003elq_num + pg_tbl-\u003enq_num +\n+\t\t pg_tbl-\u003eexq_num + pg_tbl-\u003egapq_num;\n+\tif (acq_pg_num \u003c= reserved_num) {\n+\t\trtw_err(rtwdev,\n+\t\t\t\"no transmit pages left for the public queue: %u of %u reserved\\n\",\n+\t\t\treserved_num, acq_pg_num);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t*pubq_num = acq_pg_num - reserved_num;\n+\n+\treturn 0;\n+}\n+\n+static int rtw_sdio_8723bs_init_free_txpg(struct rtw_dev *rtwdev)\n+{\n+\tstruct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev-\u003epriv;\n+\tconst struct rtw_page_table *pg_tbl;\n+\tu16 pubq_num;\n+\tint ret;\n+\n+\t/* Seed from the page table when the chip has nothing to report yet. */\n+\tif (!rtw_sdio_8723bs_sync_free_txpg(rtwdev)) {\n+\t\tret = rtw_sdio_8723bs_pubq_num(rtwdev, \u0026pubq_num);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tpg_tbl = \u0026rtwdev-\u003echip-\u003epage_table[0];\n+\t\tatomic_set(\u0026rtwsdio-\u003efree_pg_high, pg_tbl-\u003ehq_num);\n+\t\tatomic_set(\u0026rtwsdio-\u003efree_pg_normal, pg_tbl-\u003enq_num);\n+\t\tatomic_set(\u0026rtwsdio-\u003efree_pg_low, pg_tbl-\u003elq_num);\n+\t\tatomic_set(\u0026rtwsdio-\u003efree_pg_pub, pubq_num);\n+\t}\n+\n+\tatomic_set(\u0026rtwsdio-\u003etx_oqt_free,\n+\t\t rtw_read8(rtwdev, REG_SDIO_OQT_FREE_PG));\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Sum of the queue's dedicated counter and the public pool, clamped at zero:\n+ * a lost update between the check below and rtw_sdio_8723bs_consume_txpg()\n+ * can briefly drive a counter negative, and letting that wrap would hide the\n+ * shortage instead of triggering a resync from the chip.\n+ */\n+static unsigned int rtw_sdio_8723bs_pages_free(struct rtw_dev *rtwdev,\n+\t\t\t\t\t atomic_t *dedicated)\n+{\n+\tstruct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev-\u003epriv;\n+\tint free;\n+\n+\tfree = atomic_read(dedicated) + atomic_read(\u0026rtwsdio-\u003efree_pg_pub);\n+\n+\treturn free \u003e 0 ? free : 0;\n+}\n+\n+/*\n+ * The pool a queue draws from follows the transmit FIFO that\n+ * rtw_sdio_get_tx_addr() writes into, since that is the one the chip charges.\n+ * RTW_TX_QUEUE_MGMT is the exception: it goes to the extra FIFO, which\n+ * REG_SDIO_FREE_TXPG has no counter for and this chip allocates no pages to,\n+ * so it is accounted against the high pool and served from the public one.\n+ */\n+static atomic_t *rtw_sdio_8723bs_free_txpg(struct rtw_dev *rtwdev, u8 queue)\n+{\n+\tstruct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev-\u003epriv;\n+\n+\tswitch (queue) {\n+\tcase RTW_TX_QUEUE_VI:\n+\tcase RTW_TX_QUEUE_VO:\n+\t\treturn \u0026rtwsdio-\u003efree_pg_normal;\n+\tcase RTW_TX_QUEUE_BE:\n+\tcase RTW_TX_QUEUE_BK:\n+\t\treturn \u0026rtwsdio-\u003efree_pg_low;\n+\tcase RTW_TX_QUEUE_BCN:\n+\tcase RTW_TX_QUEUE_H2C:\n+\tcase RTW_TX_QUEUE_HI0:\n+\tcase RTW_TX_QUEUE_MGMT:\n+\t\treturn \u0026rtwsdio-\u003efree_pg_high;\n+\tdefault:\n+\t\treturn NULL;\n+\t}\n+}\n+\n static int rtw_sdio_check_free_txpg(struct rtw_dev *rtwdev, u8 queue,\n \t\t\t\t size_t count)\n {\n \tunsigned int pages_free, pages_needed;\n \n-\tif (rtw_chip_wcpu_8051(rtwdev)) {\n+\tif (rtw_is_8723bs(rtwdev)) {\n+\t\tatomic_t *dedicated;\n+\n+\t\tdedicated = rtw_sdio_8723bs_free_txpg(rtwdev, queue);\n+\t\tif (!dedicated) {\n+\t\t\trtw_warn(rtwdev, \"Unknown mapping for queue %u\\n\", queue);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tpages_free = rtw_sdio_8723bs_pages_free(rtwdev, dedicated);\n+\t\tpages_needed = DIV_ROUND_UP(count, rtwdev-\u003echip-\u003epage_size);\n+\t\tif (pages_needed \u003c= pages_free)\n+\t\t\treturn 0;\n+\n+\t\trtw_sdio_8723bs_sync_free_txpg(rtwdev);\n+\t\tpages_free = rtw_sdio_8723bs_pages_free(rtwdev, dedicated);\n+\t} else if (rtw_chip_wcpu_8051(rtwdev)) {\n \t\tu32 free_txpg;\n \n \t\tfree_txpg = rtw_sdio_read32(rtwdev, REG_SDIO_FREE_TXPG);\n@@ -632,35 +795,67 @@ static int rtw_sdio_check_free_txpg(struct rtw_dev *rtwdev, u8 queue,\n \treturn 0;\n }\n \n-static int rtw_sdio_write_port(struct rtw_dev *rtwdev, struct sk_buff *skb,\n-\t\t\t enum rtw_tx_queue_type queue)\n+static int rtw_sdio_8723bs_wait_tx_oqt(struct rtw_dev *rtwdev)\n {\n \tstruct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev-\u003epriv;\n-\tbool bus_claim;\n-\tsize_t txsize;\n-\tu32 txaddr;\n-\tint ret;\n+\tunsigned long deadline;\n+\tu8 free;\n \n-\ttxaddr = rtw_sdio_get_tx_addr(rtwdev, skb-\u003elen, queue);\n-\tif (!txaddr)\n-\t\treturn -EINVAL;\n+\tlockdep_assert_held(\u0026rtwsdio-\u003etx_credit_lock);\n \n-\ttxsize = sdio_align_size(rtwsdio-\u003esdio_func, skb-\u003elen);\n+\tif (atomic_add_unless(\u0026rtwsdio-\u003etx_oqt_free, -1, 0))\n+\t\treturn 0;\n \n-\tret = rtw_sdio_check_free_txpg(rtwdev, queue, txsize);\n-\tif (ret)\n-\t\treturn ret;\n+\tdeadline = jiffies + msecs_to_jiffies(RTW_SDIO_OQT_TIMEOUT_MS);\n+\tdo {\n+\t\tfree = rtw_read8(rtwdev, REG_SDIO_OQT_FREE_PG);\n+\t\tif (free) {\n+\t\t\tatomic_set(\u0026rtwsdio-\u003etx_oqt_free, free - 1);\n+\t\t\treturn 0;\n+\t\t}\n+\t\tusleep_range(1000, 2000);\n+\t} while (time_before(jiffies, deadline));\n \n-\tif (!IS_ALIGNED((unsigned long)skb-\u003edata, RTW_SDIO_DATA_PTR_ALIGN))\n-\t\trtw_warn(rtwdev, \"Got unaligned SKB in %s() for queue %u\\n\",\n-\t\t\t __func__, queue);\n+\treturn -EBUSY;\n+}\n+\n+static void rtw_sdio_8723bs_consume_txpg(struct rtw_dev *rtwdev, u8 queue,\n+\t\t\t\t\t unsigned int pages)\n+{\n+\tstruct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev-\u003epriv;\n+\tatomic_t *dedicated;\n+\tunsigned int taken;\n+\tint free;\n+\n+\tlockdep_assert_held(\u0026rtwsdio-\u003etx_credit_lock);\n+\n+\tdedicated = rtw_sdio_8723bs_free_txpg(rtwdev, queue);\n+\tif (!dedicated)\n+\t\treturn;\n+\n+\tfree = atomic_read(dedicated);\n+\ttaken = min_t(unsigned int, pages, free \u003e 0 ? free : 0);\n+\tatomic_sub(taken, dedicated);\n+\n+\tpages -= taken;\n+\tif (pages \u0026\u0026 atomic_sub_return(pages, \u0026rtwsdio-\u003efree_pg_pub) \u003c 0)\n+\t\tatomic_set(\u0026rtwsdio-\u003efree_pg_pub, 0);\n+}\n+\n+static int rtw_sdio_write_to_port(struct rtw_dev *rtwdev, struct sk_buff *skb,\n+\t\t\t\t u32 txaddr, size_t write_size)\n+{\n+\tstruct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev-\u003epriv;\n+\tbool bus_claim;\n+\tint ret;\n \n \tbus_claim = rtw_sdio_bus_claim_needed(rtwsdio);\n \n \tif (bus_claim)\n \t\tsdio_claim_host(rtwsdio-\u003esdio_func);\n \n-\tret = sdio_memcpy_toio(rtwsdio-\u003esdio_func, txaddr, skb-\u003edata, txsize);\n+\tret = sdio_memcpy_toio(rtwsdio-\u003esdio_func, txaddr, skb-\u003edata,\n+\t\t\t write_size);\n \n \tif (bus_claim)\n \t\tsdio_release_host(rtwsdio-\u003esdio_func);\n@@ -668,16 +863,112 @@ static int rtw_sdio_write_port(struct rtw_dev *rtwdev, struct sk_buff *skb,\n \tif (ret)\n \t\trtw_warn(rtwdev,\n \t\t\t \"Failed to write %zu byte(s) to SDIO port 0x%08x\",\n-\t\t\t txsize, txaddr);\n+\t\t\t write_size, txaddr);\n \n \treturn ret;\n }\n \n+/*\n+ * The free page check, the output queue wait and the accounting after the\n+ * transfer have to be one unit, or two writers can both pass the checks and\n+ * claim the same pages and output queue entry.\n+ */\n+static int rtw_sdio_8723bs_write_port(struct rtw_dev *rtwdev,\n+\t\t\t\t struct sk_buff *skb,\n+\t\t\t\t enum rtw_tx_queue_type queue, u32 txaddr,\n+\t\t\t\t size_t txsize, size_t write_size)\n+{\n+\tstruct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev-\u003epriv;\n+\tunsigned int pages;\n+\tint ret;\n+\n+\tlockdep_assert_held(\u0026rtwsdio-\u003etx_credit_lock);\n+\n+\tret = rtw_sdio_check_free_txpg(rtwdev, queue, txsize);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = rtw_sdio_8723bs_wait_tx_oqt(rtwdev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (!IS_ALIGNED((unsigned long)skb-\u003edata, RTW_SDIO_DATA_PTR_ALIGN))\n+\t\trtw_warn(rtwdev, \"Got unaligned SKB in %s() for queue %u\\n\",\n+\t\t\t __func__, queue);\n+\n+\tret = rtw_sdio_write_to_port(rtwdev, skb, txaddr, write_size);\n+\tif (ret) {\n+\t\t/* nothing was queued, so hand the output queue entry back */\n+\t\tatomic_inc(\u0026rtwsdio-\u003etx_oqt_free);\n+\t\treturn ret;\n+\t}\n+\n+\tpages = DIV_ROUND_UP(txsize, rtwdev-\u003echip-\u003epage_size);\n+\trtw_sdio_8723bs_consume_txpg(rtwdev, queue, pages);\n+\n+\treturn 0;\n+}\n+\n+static int rtw_sdio_write_port(struct rtw_dev *rtwdev, struct sk_buff *skb,\n+\t\t\t enum rtw_tx_queue_type queue)\n+{\n+\tstruct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev-\u003epriv;\n+\tsize_t write_size;\n+\tsize_t txsize;\n+\tu32 txaddr;\n+\tint ret;\n+\n+\ttxaddr = rtw_sdio_get_tx_addr(rtwdev, skb-\u003elen, queue);\n+\tif (!txaddr)\n+\t\treturn -EINVAL;\n+\n+\tif (!rtw_is_8723bs(rtwdev)) {\n+\t\ttxsize = sdio_align_size(rtwsdio-\u003esdio_func, skb-\u003elen);\n+\n+\t\tret = rtw_sdio_check_free_txpg(rtwdev, queue, txsize);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tif (!IS_ALIGNED((unsigned long)skb-\u003edata,\n+\t\t\t\tRTW_SDIO_DATA_PTR_ALIGN))\n+\t\t\trtw_warn(rtwdev,\n+\t\t\t\t \"Got unaligned SKB in %s() for queue %u\\n\",\n+\t\t\t\t __func__, queue);\n+\n+\t\treturn rtw_sdio_write_to_port(rtwdev, skb, txaddr, txsize);\n+\t}\n+\n+\ttxsize = round_up(skb-\u003elen, 4);\n+\twrite_size = txsize \u003e RTW_SDIO_BLOCK_SIZE ?\n+\t\t round_up(txsize, RTW_SDIO_BLOCK_SIZE) : txsize;\n+\n+\tif (write_size \u003e skb-\u003elen) {\n+\t\tsize_t pad_size = write_size - skb-\u003elen;\n+\n+\t\t/*\n+\t\t * __skb_pad() must not free the skb on failure: both callers\n+\t\t * still own it, one requeues it and the other frees it.\n+\t\t */\n+\t\tret = __skb_pad(skb, pad_size, false);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\tguard(mutex)(\u0026rtwsdio-\u003etx_credit_lock);\n+\n+\treturn rtw_sdio_8723bs_write_port(rtwdev, skb, queue, txaddr, txsize,\n+\t\t\t\t\t write_size);\n+}\n+\n static void rtw_sdio_init(struct rtw_dev *rtwdev)\n {\n \tstruct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev-\u003epriv;\n \n-\trtwsdio-\u003eirq_mask = REG_SDIO_HIMR_RX_REQUEST | REG_SDIO_HIMR_CPWM1;\n+\tif (rtw_is_8723bs(rtwdev))\n+\t\trtwsdio-\u003eirq_mask = REG_SDIO_HIMR_RX_REQUEST;\n+\telse\n+\t\trtwsdio-\u003eirq_mask = REG_SDIO_HIMR_RX_REQUEST |\n+\t\t\t\t REG_SDIO_HIMR_CPWM1;\n }\n \n static void rtw_sdio_enable_rx_aggregation(struct rtw_dev *rtwdev)\n@@ -685,6 +976,7 @@ static void rtw_sdio_enable_rx_aggregation(struct rtw_dev *rtwdev)\n \tu8 size, timeout;\n \n \tswitch (rtwdev-\u003echip-\u003eid) {\n+\tcase RTW_CHIP_TYPE_8723B:\n \tcase RTW_CHIP_TYPE_8703B:\n \tcase RTW_CHIP_TYPE_8821A:\n \tcase RTW_CHIP_TYPE_8812A:\n@@ -712,6 +1004,8 @@ static void rtw_sdio_enable_rx_aggregation(struct rtw_dev *rtwdev)\n \t\t FIELD_PREP(BIT_DMA_AGG_TO_V1, timeout));\n \n \trtw_write8_set(rtwdev, REG_RXDMA_MODE, BIT_DMA_MODE);\n+\tif (rtw_is_8723bs(rtwdev))\n+\t\trtw_write8_mask(rtwdev, REG_RXDMA_MODE, BIT_DMA_BURST_CNT, 0x3);\n }\n \n static void rtw_sdio_enable_interrupt(struct rtw_dev *rtwdev)\n@@ -749,9 +1043,61 @@ static int rtw_sdio_setup(struct rtw_dev *rtwdev)\n \treturn 0;\n }\n \n+/*\n+ * Reprogram the queue page allocation if the chip came up with none. This is\n+ * a repair path, not part of the normal start sequence: a non-zero free page\n+ * count means the allocation latched during power on and must be left alone,\n+ * and without a transmit page pool there is nothing to divide up either.\n+ */\n+static int rtw_sdio_8723bs_check_rqpn(struct rtw_dev *rtwdev)\n+{\n+\tconst struct rtw_chip_info *chip = rtwdev-\u003echip;\n+\tstruct rtw_fifo_conf *fifo = \u0026rtwdev-\u003efifo;\n+\tconst struct rtw_page_table *pg_tbl;\n+\tu32 free_txpg;\n+\tu16 pubq_num;\n+\tint ret;\n+\n+\tfree_txpg = rtw_read32(rtwdev, REG_SDIO_FREE_TXPG);\n+\tif (free_txpg || !fifo-\u003eacq_pg_num)\n+\t\treturn 0;\n+\n+\tret = rtw_sdio_8723bs_pubq_num(rtwdev, \u0026pubq_num);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tpg_tbl = \u0026chip-\u003epage_table[0];\n+\trtw_write32(rtwdev, REG_RQPN_NPQ,\n+\t\t BIT_RQPN_NE(pg_tbl-\u003enq_num, pg_tbl-\u003eexq_num));\n+\trtw_write32(rtwdev, REG_RQPN,\n+\t\t BIT_RQPN_HLP(pg_tbl-\u003ehq_num, pg_tbl-\u003elq_num, pubq_num));\n+\n+\treturn 0;\n+}\n+\n static int rtw_sdio_start(struct rtw_dev *rtwdev)\n {\n+\tu32 clear;\n+\n+\tif (rtw_is_8723bs(rtwdev)) {\n+\t\tint ret = rtw_sdio_8723bs_check_rqpn(rtwdev);\n+\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tret = rtw_sdio_8723bs_init_free_txpg(rtwdev);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n \trtw_sdio_enable_rx_aggregation(rtwdev);\n+\n+\tif (rtw_is_8723bs(rtwdev)) {\n+\t\tclear = rtw_read32(rtwdev, REG_SDIO_HISR) \u0026 RTW_SDIO_HISR_CLEAR_MASK;\n+\t\tif (clear)\n+\t\t\trtw_write32(rtwdev, REG_SDIO_HISR, clear);\n+\t}\n+\n \trtw_sdio_enable_interrupt(rtwdev);\n \n \treturn 0;\n@@ -815,7 +1161,11 @@ static void rtw_sdio_tx_kick_off(struct rtw_dev *rtwdev)\n {\n \tstruct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev-\u003epriv;\n \n-\tqueue_work(rtwsdio-\u003etxwq, \u0026rtwsdio-\u003etx_handler_data-\u003ework);\n+\t/*\n+\t * A retry may already be pending with a delay; re-arm it so a newly\n+\t * queued frame is not held back by it.\n+\t */\n+\tmod_delayed_work(rtwsdio-\u003etxwq, \u0026rtwsdio-\u003etx_handler_data-\u003ework, 0);\n }\n \n static void rtw_sdio_link_ps(struct rtw_dev *rtwdev, bool enter)\n@@ -831,6 +1181,8 @@ static void rtw_sdio_interface_cfg(struct rtw_dev *rtwdev)\n \n \tval = rtw_read32(rtwdev, REG_SDIO_TX_CTRL);\n \tval \u0026= 0xfff8;\n+\tif (rtw_is_8723bs(rtwdev))\n+\t\tval |= BIT_SDIO_TX_CTRL_ALWAYS_RECOGNIZE;\n \trtw_write32(rtwdev, REG_SDIO_TX_CTRL, val);\n }\n \n@@ -922,12 +1274,65 @@ static int rtw_sdio_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size)\n \treturn rtw_sdio_write_data(rtwdev, \u0026pkt_info, skb, RTW_TX_QUEUE_H2C);\n }\n \n+/*\n+ * Back-pressure on the data ACs (BK/BE/VI/VO): once the software FIFO fills\n+ * past the high watermark, stop the corresponding mac80211 queue so it stops\n+ * handing frames down, which bounds the queueing latency. The queue is woken\n+ * again from the TX drain path once the FIFO falls back to the low watermark.\n+ *\n+ * Both sides hold the TX queue lock across the length check and the flag\n+ * update, so a queue is only ever stopped while it really is above the\n+ * watermark, and the drain path always sees the flag the producer set.\n+ */\n+static void rtw_sdio_8723bs_stop_tx_queue(struct rtw_dev *rtwdev,\n+\t\t\t\t\t enum rtw_tx_queue_type queue,\n+\t\t\t\t\t u16 q_map)\n+{\n+\tstruct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev-\u003epriv;\n+\n+\tif (!rtw_is_8723bs(rtwdev) || queue \u003e= RTW_TX_QUEUE_BCN)\n+\t\treturn;\n+\n+\tguard(spinlock_irqsave)(\u0026rtwsdio-\u003etx_queue[queue].lock);\n+\n+\tif (rtwsdio-\u003etx_queue_stopped[queue])\n+\t\treturn;\n+\n+\tif (skb_queue_len(\u0026rtwsdio-\u003etx_queue[queue]) \u003c RTW_SDIO_TX_FIFO_HIWATER)\n+\t\treturn;\n+\n+\trtwsdio-\u003etx_queue_stopped[queue] = true;\n+\tieee80211_stop_queue(rtwdev-\u003ehw, q_map);\n+}\n+\n+static void rtw_sdio_8723bs_wake_tx_queue(struct rtw_dev *rtwdev,\n+\t\t\t\t\t enum rtw_tx_queue_type queue,\n+\t\t\t\t\t u16 q_map)\n+{\n+\tstruct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev-\u003epriv;\n+\n+\tif (!rtw_is_8723bs(rtwdev) || queue \u003e= RTW_TX_QUEUE_BCN)\n+\t\treturn;\n+\n+\tguard(spinlock_irqsave)(\u0026rtwsdio-\u003etx_queue[queue].lock);\n+\n+\tif (!rtwsdio-\u003etx_queue_stopped[queue])\n+\t\treturn;\n+\n+\tif (skb_queue_len(\u0026rtwsdio-\u003etx_queue[queue]) \u003e RTW_SDIO_TX_FIFO_LOWATER)\n+\t\treturn;\n+\n+\trtwsdio-\u003etx_queue_stopped[queue] = false;\n+\tieee80211_wake_queue(rtwdev-\u003ehw, q_map);\n+}\n+\n static int rtw_sdio_tx_write(struct rtw_dev *rtwdev,\n \t\t\t struct rtw_tx_pkt_info *pkt_info,\n \t\t\t struct sk_buff *skb)\n {\n \tstruct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev-\u003epriv;\n \tenum rtw_tx_queue_type queue = rtw_tx_queue_mapping(skb);\n+\tu16 q_map = skb_get_queue_mapping(skb);\n \tstruct rtw_sdio_tx_data *tx_data;\n \n \trtw_sdio_tx_skb_prepare(rtwdev, pkt_info, skb, queue);\n@@ -935,8 +1340,15 @@ static int rtw_sdio_tx_write(struct rtw_dev *rtwdev,\n \ttx_data = rtw_sdio_get_tx_data(skb);\n \ttx_data-\u003esn = pkt_info-\u003esn;\n \n+\t/*\n+\t * skb_queue_tail() publishes the skb to the TX worker, which may\n+\t * process and free it immediately, so nothing may touch the skb\n+\t * past this point.\n+\t */\n \tskb_queue_tail(\u0026rtwsdio-\u003etx_queue[queue], skb);\n \n+\trtw_sdio_8723bs_stop_tx_queue(rtwdev, queue, q_map);\n+\n \treturn 0;\n }\n \n@@ -1095,6 +1507,14 @@ static void rtw_sdio_handle_interrupt(struct sdio_func *sdio_func)\n \t\trtw_sdio_rx_isr(rtwdev);\n \t}\n \n+\t/*\n+\t * RTL8723BS keeps raising the interrupt after resume if undefined\n+\t * status bits are written back, so acknowledge only the bits this\n+\t * driver defines. Other chips keep the existing behaviour.\n+\t */\n+\tif (rtw_is_8723bs(rtwdev))\n+\t\thisr \u0026= RTW_SDIO_HISR_CLEAR_MASK;\n+\n \trtw_write32(rtwdev, REG_SDIO_HISR, hisr);\n \n \trtwsdio-\u003eirq_thread = NULL;\n@@ -1231,33 +1651,83 @@ static void rtw_sdio_indicate_tx_status(struct rtw_dev *rtwdev,\n \tieee80211_tx_status_irqsafe(hw, skb);\n }\n \n-static void rtw_sdio_process_tx_queue(struct rtw_dev *rtwdev,\n-\t\t\t\t enum rtw_tx_queue_type queue)\n+/*\n+ * Send one frame from @queue. Returns 0 when a frame was written, 1 when the\n+ * queue was empty and a negative errno when the write failed, in which case\n+ * the frame is put back at the head of the queue.\n+ */\n+static int rtw_sdio_process_tx_queue(struct rtw_dev *rtwdev,\n+\t\t\t\t enum rtw_tx_queue_type queue)\n {\n \tstruct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev-\u003epriv;\n \tstruct sk_buff *skb;\n+\tu16 q_map;\n \tint ret;\n \n \tskb = skb_dequeue(\u0026rtwsdio-\u003etx_queue[queue]);\n \tif (!skb)\n-\t\treturn;\n+\t\treturn 1;\n \n \tret = rtw_sdio_write_port(rtwdev, skb, queue);\n \tif (ret) {\n \t\tskb_queue_head(\u0026rtwsdio-\u003etx_queue[queue], skb);\n-\t\treturn;\n+\t\treturn ret;\n \t}\n \n+\t/* rtw_sdio_indicate_tx_status() consumes the skb, so read this first */\n+\tq_map = skb_get_queue_mapping(skb);\n+\n \trtw_sdio_indicate_tx_status(rtwdev, skb);\n+\n+\trtw_sdio_8723bs_wake_tx_queue(rtwdev, queue, q_map);\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Decide whether the RTL8723BS wants the TX work to run again, and if so\n+ * arrange it and tell the caller to stop draining. Two cases need it.\n+ *\n+ * A transmit page or output queue shortage and a failed skb expansion are\n+ * transient and leave the frame queued, so come back for it shortly. That\n+ * matters once the mac80211 queue can be stopped: a stopped queue is handed\n+ * no further frames, so nothing else would kick this work item and the access\n+ * category would stay stopped for good. The remaining errors are logged where\n+ * they happen and are not retried.\n+ *\n+ * After a management frame, restart from the highest priority queue so the\n+ * join sequence is not held up behind a data backlog.\n+ */\n+static bool rtw_sdio_8723bs_reschedule_tx(struct rtw_dev *rtwdev,\n+\t\t\t\t\t struct rtw_sdio_work_data *work_data,\n+\t\t\t\t\t enum rtw_tx_queue_type queue, int ret)\n+{\n+\tstruct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev-\u003epriv;\n+\tunsigned long delay;\n+\n+\tif (!rtw_is_8723bs(rtwdev))\n+\t\treturn false;\n+\n+\tif (ret == -EBUSY || ret == -ENOMEM)\n+\t\tdelay = RTW_SDIO_TX_RETRY_DELAY;\n+\telse if (ret == 0 \u0026\u0026 queue == RTW_TX_QUEUE_MGMT)\n+\t\tdelay = 0;\n+\telse\n+\t\treturn false;\n+\n+\tqueue_delayed_work(rtwsdio-\u003etxwq, \u0026work_data-\u003ework, delay);\n+\n+\treturn true;\n }\n \n static void rtw_sdio_tx_handler(struct work_struct *work)\n {\n \tstruct rtw_sdio_work_data *work_data =\n-\t\tcontainer_of(work, struct rtw_sdio_work_data, work);\n+\t\tcontainer_of(to_delayed_work(work), struct rtw_sdio_work_data,\n+\t\t\t work);\n \tstruct rtw_sdio *rtwsdio;\n \tstruct rtw_dev *rtwdev;\n-\tint limit, queue;\n+\tint limit, queue, ret;\n \n \trtwdev = work_data-\u003ertwdev;\n \trtwsdio = (struct rtw_sdio *)rtwdev-\u003epriv;\n@@ -1267,7 +1737,13 @@ static void rtw_sdio_tx_handler(struct work_struct *work)\n \n \tfor (queue = RTK_MAX_TX_QUEUE_NUM - 1; queue \u003e= 0; queue--) {\n \t\tfor (limit = 0; limit \u003c 1000; limit++) {\n-\t\t\trtw_sdio_process_tx_queue(rtwdev, queue);\n+\t\t\tret = rtw_sdio_process_tx_queue(rtwdev, queue);\n+\t\t\tif (ret \u003e 0)\n+\t\t\t\tbreak;\n+\n+\t\t\tif (rtw_sdio_8723bs_reschedule_tx(rtwdev, work_data,\n+\t\t\t\t\t\t\t queue, ret))\n+\t\t\t\treturn;\n \n \t\t\tif (skb_queue_empty(\u0026rtwsdio-\u003etx_queue[queue]))\n \t\t\t\tbreak;\n@@ -1294,18 +1770,23 @@ static int rtw_sdio_init_tx(struct rtw_dev *rtwdev)\n \t\treturn -ENOMEM;\n \t}\n \n-\tfor (i = 0; i \u003c RTK_MAX_TX_QUEUE_NUM; i++)\n+\tmutex_init(\u0026rtwsdio-\u003etx_credit_lock);\n+\n+\tfor (i = 0; i \u003c RTK_MAX_TX_QUEUE_NUM; i++) {\n \t\tskb_queue_head_init(\u0026rtwsdio-\u003etx_queue[i]);\n+\t\trtwsdio-\u003etx_queue_stopped[i] = false;\n+\t}\n \trtwsdio-\u003etx_handler_data = kmalloc_obj(*rtwsdio-\u003etx_handler_data);\n \tif (!rtwsdio-\u003etx_handler_data)\n \t\tgoto err_destroy_wq;\n \n \trtwsdio-\u003etx_handler_data-\u003ertwdev = rtwdev;\n-\tINIT_WORK(\u0026rtwsdio-\u003etx_handler_data-\u003ework, rtw_sdio_tx_handler);\n+\tINIT_DELAYED_WORK(\u0026rtwsdio-\u003etx_handler_data-\u003ework, rtw_sdio_tx_handler);\n \n \treturn 0;\n \n err_destroy_wq:\n+\tmutex_destroy(\u0026rtwsdio-\u003etx_credit_lock);\n \tdestroy_workqueue(rtwsdio-\u003etxwq);\n \treturn -ENOMEM;\n }\n@@ -1315,11 +1796,14 @@ static void rtw_sdio_deinit_tx(struct rtw_dev *rtwdev)\n \tstruct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev-\u003epriv;\n \tint i;\n \n+\tcancel_delayed_work_sync(\u0026rtwsdio-\u003etx_handler_data-\u003ework);\n \tdestroy_workqueue(rtwsdio-\u003etxwq);\n \tkfree(rtwsdio-\u003etx_handler_data);\n \n \tfor (i = 0; i \u003c RTK_MAX_TX_QUEUE_NUM; i++)\n \t\tieee80211_purge_tx_queue(rtwdev-\u003ehw, \u0026rtwsdio-\u003etx_queue[i]);\n+\n+\tmutex_destroy(\u0026rtwsdio-\u003etx_credit_lock);\n }\n \n int rtw_sdio_probe(struct sdio_func *sdio_func,\ndiff --git a/drivers/net/wireless/realtek/rtw88/sdio.h b/drivers/net/wireless/realtek/rtw88/sdio.h\nindex 457e8b02380e5..6e7e6009744b0 100644\n--- a/drivers/net/wireless/realtek/rtw88/sdio.h\n+++ b/drivers/net/wireless/realtek/rtw88/sdio.h\n@@ -22,6 +22,7 @@\n \n /* SDIO Tx Control */\n #define REG_SDIO_TX_CTRL\t\t\t(SDIO_LOCAL_OFFSET + 0x0000)\n+#define BIT_SDIO_TX_CTRL_ALWAYS_RECOGNIZE\tBIT(4)\n \n /*SDIO status timeout*/\n #define REG_SDIO_TIMEOUT\t\t\t(SDIO_LOCAL_OFFSET + 0x0002)\n@@ -77,6 +78,14 @@\n /* the following two are RTL8188 SDIO Specific */\n #define REG_SDIO_HISR_MCU_ERR\t\t\tBIT(28)\n #define REG_SDIO_HISR_TSF_BIT32_TOGGLE\t\tBIT(29)\n+#define RTW_SDIO_HISR_CLEAR_MASK\t\t\\\n+\t(REG_SDIO_HISR_TXERR | REG_SDIO_HISR_RXERR | \\\n+\t REG_SDIO_HISR_TXFOVW | REG_SDIO_HISR_RXFOVW | \\\n+\t REG_SDIO_HISR_TXBCNOK | REG_SDIO_HISR_TXBCNERR | \\\n+\t REG_SDIO_HISR_C2HCMD | REG_SDIO_HISR_CPWM1 | \\\n+\t REG_SDIO_HISR_CPWM2 | REG_SDIO_HISR_HSISR_IND | \\\n+\t REG_SDIO_HISR_GTINT3_IND | REG_SDIO_HISR_GTINT4_IND | \\\n+\t REG_SDIO_HISR_PSTIMEOUT | REG_SDIO_HISR_OCPINT)\n \n /* HCI Current Power Mode */\n #define REG_SDIO_HCPWM\t\t\t\t(SDIO_LOCAL_OFFSET + 0x0019)\n@@ -86,6 +95,10 @@\n #define REG_SDIO_OQT_FREE_PG\t\t\t(SDIO_LOCAL_OFFSET + 0x001E)\n /* Free Tx Buffer Page */\n #define REG_SDIO_FREE_TXPG\t\t\t(SDIO_LOCAL_OFFSET + 0x0020)\n+#define BIT_FREE_TXPG_HIGH\t\t\tGENMASK(7, 0)\n+#define BIT_FREE_TXPG_NORMAL\t\t\tGENMASK(15, 8)\n+#define BIT_FREE_TXPG_LOW\t\t\tGENMASK(23, 16)\n+#define BIT_FREE_TXPG_PUB\t\t\tGENMASK(31, 24)\n /* HCI Current Power Mode 1 */\n #define REG_SDIO_HCPWM1\t\t\t\t(SDIO_LOCAL_OFFSET + 0x0024)\n /* HCI Current Power Mode 2 */\n@@ -143,7 +156,7 @@ struct rtw_sdio_tx_data {\n };\n \n struct rtw_sdio_work_data {\n-\tstruct work_struct work;\n+\tstruct delayed_work work;\n \tstruct rtw_dev *rtwdev;\n };\n \n@@ -159,6 +172,15 @@ struct rtw_sdio {\n \tstruct workqueue_struct *txwq;\n \tstruct rtw_sdio_work_data *tx_handler_data;\n \tstruct sk_buff_head tx_queue[RTK_MAX_TX_QUEUE_NUM];\n+\tbool tx_queue_stopped[RTK_MAX_TX_QUEUE_NUM];\n+\n+\tatomic_t free_pg_high;\n+\tatomic_t free_pg_normal;\n+\tatomic_t free_pg_low;\n+\tatomic_t free_pg_pub;\n+\tatomic_t tx_oqt_free;\n+\t/* one writer at a time between the credit check and the accounting */\n+\tstruct mutex tx_credit_lock;\n };\n \n extern const struct dev_pm_ops rtw_sdio_pm_ops;\ndiff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c\nindex 8786bbb421c2b..4e110a457e71d 100644\n--- a/drivers/net/wireless/realtek/rtw88/tx.c\n+++ b/drivers/net/wireless/realtek/rtw88/tx.c\n@@ -208,8 +208,9 @@ void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn)\n \t__skb_queue_tail(\u0026tx_report-\u003equeue, skb);\n \tspin_unlock_irqrestore(\u0026tx_report-\u003eq_lock, flags);\n \n-\tif (rtwdev-\u003echip-\u003eid == RTW_CHIP_TYPE_8723D \u0026\u0026\n-\t rtwdev-\u003ehci.type == RTW_HCI_TYPE_USB)\n+\tif ((rtwdev-\u003echip-\u003eid == RTW_CHIP_TYPE_8723D \u0026\u0026\n+\t rtwdev-\u003ehci.type == RTW_HCI_TYPE_USB) ||\n+\t rtw_is_8723bs(rtwdev))\n \t\ttimeout = msecs_to_jiffies(2500);\n \n \tmod_timer(\u0026tx_report-\u003epurge_timer, jiffies + timeout);\n"
} |
| 2/1 | 2026/08/25 19:11 | agent | patch-evaluator |
3mModel:best-expensive Args: null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch adds support for the RTL8723BS SDIO wireless chip and modifies the SDIO TX/RX handling in the rtw88 driver. Since there is no virtual SDIO host controller or software-emulated SDIO device framework in the kernel (unlike USB gadget or mac80211_hwsim), and standard QEMU does not emulate SDIO devices, this code is impossible to reach in virtualized environments.",
"WorthFuzzing": false
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). - Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed, ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU. - Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove) that are executed only during PCI hot-unplug or sysfs driver unbind operations. If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. Prefer non-static, non-inlined API entrypoint functions over internal static helper functions (which are inlined by the compiler and do not have distinct symbol addresses). 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 92b4ff601f6b05a5efdc1c39846382a7ad36045c
Author: syz-cluster <triage@syzkaller.com>
Date: Tue Aug 25 19:11:25 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index c6e981ba79868..8f86f7c12de5a 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -194,6 +194,7 @@ enum rtw_chip_type {
RTW_CHIP_TYPE_8723D,
RTW_CHIP_TYPE_8821C,
RTW_CHIP_TYPE_8703B,
+ RTW_CHIP_TYPE_8723B,
RTW_CHIP_TYPE_8821A,
RTW_CHIP_TYPE_8812A,
RTW_CHIP_TYPE_8814A,
@@ -2194,6 +2195,12 @@ static inline bool rtw_chip_has_tx_stbc(struct rtw_dev *rtwdev)
return rtwdev->chip->tx_stbc;
}
+static inline bool rtw_is_8723bs(struct rtw_dev *rtwdev)
+{
+ return rtwdev->chip->id == RTW_CHIP_TYPE_8723B &&
+ rtwdev->hci.type == RTW_HCI_TYPE_SDIO;
+}
+
static inline u8 rtw_acquire_macid(struct rtw_dev *rtwdev)
{
unsigned long mac_id;
diff --git a/drivers/net/wireless/realtek/rtw88/rx.c b/drivers/net/wireless/realtek/rtw88/rx.c
index 01fd299abb7fe..fde21c840ac02 100644
--- a/drivers/net/wireless/realtek/rtw88/rx.c
+++ b/drivers/net/wireless/realtek/rtw88/rx.c
@@ -253,10 +253,12 @@ static void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
rtw_rx_addr_match(rtwdev, pkt_stat, hdr);
- /* Rtl8723cs driver checks for size < 14 or size > 8192 and
- * simply drops the packet.
+ /*
+ * Rtl8723cs and rtl8723bs drivers check for size < 14 or size > 8192
+ * and simply drop the packet.
*/
- if (rtwdev->chip->id == RTW_CHIP_TYPE_8703B && pkt_stat->pkt_len == 0) {
+ if (pkt_stat->pkt_len == 0 &&
+ (rtwdev->chip->id == RTW_CHIP_TYPE_8703B || rtw_is_8723bs(rtwdev))) {
rx_status->flag |= RX_FLAG_NO_PSDU;
rtw_dbg(rtwdev, RTW_DBG_RX, "zero length packet");
}
diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c
index 5b40d74b16ee0..1a85ed1431b48 100644
--- a/drivers/net/wireless/realtek/rtw88/sdio.c
+++ b/drivers/net/wireless/realtek/rtw88/sdio.c
@@ -20,6 +20,17 @@
#include "tx.h"
#define RTW_SDIO_INDIRECT_RW_RETRIES 50
+#define RTW_SDIO_OQT_TIMEOUT_MS 1000
+
+/*
+ * 8723BS SDIO TX FIFO back-pressure watermarks: stop the mac80211 queue once
+ * the per-AC software FIFO fills past the high watermark, and wake it from the
+ * TX drain path once it falls back to the low one. Bounds the queueing latency
+ * that otherwise causes uplink bufferbloat / congestion collapse.
+ */
+#define RTW_SDIO_TX_FIFO_HIWATER 16
+#define RTW_SDIO_TX_FIFO_LOWATER 8
+#define RTW_SDIO_TX_RETRY_DELAY msecs_to_jiffies(1)
static bool rtw_sdio_is_bus_addr(u32 addr)
{
@@ -548,12 +559,164 @@ static int rtw_sdio_read_port(struct rtw_dev *rtwdev, u8 *buf, size_t count)
return ret;
}
+/*
+ * The cached free page counters are a fast path hint only. The transmit
+ * paths read and update them under tx_credit_lock; rtw_sdio_start() seeds
+ * them outside it, so they are atomic_t. Whenever they claim there is not
+ * enough room they are resynchronised from the chip before the caller gives
+ * up, which also absorbs any drift.
+ */
+static void rtw_sdio_8723bs_store_free_txpg(struct rtw_dev *rtwdev,
+ u32 free_txpg)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+
+ atomic_set(&rtwsdio->free_pg_high,
+ u32_get_bits(free_txpg, BIT_FREE_TXPG_HIGH));
+ atomic_set(&rtwsdio->free_pg_normal,
+ u32_get_bits(free_txpg, BIT_FREE_TXPG_NORMAL));
+ atomic_set(&rtwsdio->free_pg_low,
+ u32_get_bits(free_txpg, BIT_FREE_TXPG_LOW));
+ atomic_set(&rtwsdio->free_pg_pub,
+ u32_get_bits(free_txpg, BIT_FREE_TXPG_PUB));
+}
+
+/*
+ * Refresh the cached counters from the chip. Returns false when the chip
+ * reports no free pages at all, which means the counts cannot be trusted
+ * and the caller has to decide what to do instead.
+ */
+static bool rtw_sdio_8723bs_sync_free_txpg(struct rtw_dev *rtwdev)
+{
+ u32 free_txpg = rtw_read32(rtwdev, REG_SDIO_FREE_TXPG);
+
+ if (!free_txpg)
+ return false;
+
+ rtw_sdio_8723bs_store_free_txpg(rtwdev, free_txpg);
+
+ return true;
+}
+
+/*
+ * Size of the public page pool: whatever the transmit page allocation has
+ * left once the per queue pools are taken out. Fails if the allocation
+ * cannot cover the reserved queues, since the remainder would underflow and
+ * there would be no sensible pool to hand out.
+ */
+static int rtw_sdio_8723bs_pubq_num(struct rtw_dev *rtwdev, u16 *pubq_num)
+{
+ const struct rtw_page_table *pg_tbl = &rtwdev->chip->page_table[0];
+ u16 acq_pg_num = rtwdev->fifo.acq_pg_num;
+ u16 reserved_num;
+
+ reserved_num = pg_tbl->hq_num + pg_tbl->lq_num + pg_tbl->nq_num +
+ pg_tbl->exq_num + pg_tbl->gapq_num;
+ if (acq_pg_num <= reserved_num) {
+ rtw_err(rtwdev,
+ "no transmit pages left for the public queue: %u of %u reserved\n",
+ reserved_num, acq_pg_num);
+ return -EINVAL;
+ }
+
+ *pubq_num = acq_pg_num - reserved_num;
+
+ return 0;
+}
+
+static int rtw_sdio_8723bs_init_free_txpg(struct rtw_dev *rtwdev)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ const struct rtw_page_table *pg_tbl;
+ u16 pubq_num;
+ int ret;
+
+ /* Seed from the page table when the chip has nothing to report yet. */
+ if (!rtw_sdio_8723bs_sync_free_txpg(rtwdev)) {
+ ret = rtw_sdio_8723bs_pubq_num(rtwdev, &pubq_num);
+ if (ret)
+ return ret;
+
+ pg_tbl = &rtwdev->chip->page_table[0];
+ atomic_set(&rtwsdio->free_pg_high, pg_tbl->hq_num);
+ atomic_set(&rtwsdio->free_pg_normal, pg_tbl->nq_num);
+ atomic_set(&rtwsdio->free_pg_low, pg_tbl->lq_num);
+ atomic_set(&rtwsdio->free_pg_pub, pubq_num);
+ }
+
+ atomic_set(&rtwsdio->tx_oqt_free,
+ rtw_read8(rtwdev, REG_SDIO_OQT_FREE_PG));
+
+ return 0;
+}
+
+/*
+ * Sum of the queue's dedicated counter and the public pool, clamped at zero:
+ * a lost update between the check below and rtw_sdio_8723bs_consume_txpg()
+ * can briefly drive a counter negative, and letting that wrap would hide the
+ * shortage instead of triggering a resync from the chip.
+ */
+static unsigned int rtw_sdio_8723bs_pages_free(struct rtw_dev *rtwdev,
+ atomic_t *dedicated)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ int free;
+
+ free = atomic_read(dedicated) + atomic_read(&rtwsdio->free_pg_pub);
+
+ return free > 0 ? free : 0;
+}
+
+/*
+ * The pool a queue draws from follows the transmit FIFO that
+ * rtw_sdio_get_tx_addr() writes into, since that is the one the chip charges.
+ * RTW_TX_QUEUE_MGMT is the exception: it goes to the extra FIFO, which
+ * REG_SDIO_FREE_TXPG has no counter for and this chip allocates no pages to,
+ * so it is accounted against the high pool and served from the public one.
+ */
+static atomic_t *rtw_sdio_8723bs_free_txpg(struct rtw_dev *rtwdev, u8 queue)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+
+ switch (queue) {
+ case RTW_TX_QUEUE_VI:
+ case RTW_TX_QUEUE_VO:
+ return &rtwsdio->free_pg_normal;
+ case RTW_TX_QUEUE_BE:
+ case RTW_TX_QUEUE_BK:
+ return &rtwsdio->free_pg_low;
+ case RTW_TX_QUEUE_BCN:
+ case RTW_TX_QUEUE_H2C:
+ case RTW_TX_QUEUE_HI0:
+ case RTW_TX_QUEUE_MGMT:
+ return &rtwsdio->free_pg_high;
+ default:
+ return NULL;
+ }
+}
+
static int rtw_sdio_check_free_txpg(struct rtw_dev *rtwdev, u8 queue,
size_t count)
{
unsigned int pages_free, pages_needed;
- if (rtw_chip_wcpu_8051(rtwdev)) {
+ if (rtw_is_8723bs(rtwdev)) {
+ atomic_t *dedicated;
+
+ dedicated = rtw_sdio_8723bs_free_txpg(rtwdev, queue);
+ if (!dedicated) {
+ rtw_warn(rtwdev, "Unknown mapping for queue %u\n", queue);
+ return -EINVAL;
+ }
+
+ pages_free = rtw_sdio_8723bs_pages_free(rtwdev, dedicated);
+ pages_needed = DIV_ROUND_UP(count, rtwdev->chip->page_size);
+ if (pages_needed <= pages_free)
+ return 0;
+
+ rtw_sdio_8723bs_sync_free_txpg(rtwdev);
+ pages_free = rtw_sdio_8723bs_pages_free(rtwdev, dedicated);
+ } else if (rtw_chip_wcpu_8051(rtwdev)) {
u32 free_txpg;
free_txpg = rtw_sdio_read32(rtwdev, REG_SDIO_FREE_TXPG);
@@ -632,35 +795,67 @@ static int rtw_sdio_check_free_txpg(struct rtw_dev *rtwdev, u8 queue,
return 0;
}
-static int rtw_sdio_write_port(struct rtw_dev *rtwdev, struct sk_buff *skb,
- enum rtw_tx_queue_type queue)
+static int rtw_sdio_8723bs_wait_tx_oqt(struct rtw_dev *rtwdev)
{
struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
- bool bus_claim;
- size_t txsize;
- u32 txaddr;
- int ret;
+ unsigned long deadline;
+ u8 free;
- txaddr = rtw_sdio_get_tx_addr(rtwdev, skb->len, queue);
- if (!txaddr)
- return -EINVAL;
+ lockdep_assert_held(&rtwsdio->tx_credit_lock);
- txsize = sdio_align_size(rtwsdio->sdio_func, skb->len);
+ if (atomic_add_unless(&rtwsdio->tx_oqt_free, -1, 0))
+ return 0;
- ret = rtw_sdio_check_free_txpg(rtwdev, queue, txsize);
- if (ret)
- return ret;
+ deadline = jiffies + msecs_to_jiffies(RTW_SDIO_OQT_TIMEOUT_MS);
+ do {
+ free = rtw_read8(rtwdev, REG_SDIO_OQT_FREE_PG);
+ if (free) {
+ atomic_set(&rtwsdio->tx_oqt_free, free - 1);
+ return 0;
+ }
+ usleep_range(1000, 2000);
+ } while (time_before(jiffies, deadline));
- if (!IS_ALIGNED((unsigned long)skb->data, RTW_SDIO_DATA_PTR_ALIGN))
- rtw_warn(rtwdev, "Got unaligned SKB in %s() for queue %u\n",
- __func__, queue);
+ return -EBUSY;
+}
+
+static void rtw_sdio_8723bs_consume_txpg(struct rtw_dev *rtwdev, u8 queue,
+ unsigned int pages)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ atomic_t *dedicated;
+ unsigned int taken;
+ int free;
+
+ lockdep_assert_held(&rtwsdio->tx_credit_lock);
+
+ dedicated = rtw_sdio_8723bs_free_txpg(rtwdev, queue);
+ if (!dedicated)
+ return;
+
+ free = atomic_read(dedicated);
+ taken = min_t(unsigned int, pages, free > 0 ? free : 0);
+ atomic_sub(taken, dedicated);
+
+ pages -= taken;
+ if (pages && atomic_sub_return(pages, &rtwsdio->free_pg_pub) < 0)
+ atomic_set(&rtwsdio->free_pg_pub, 0);
+}
+
+static int rtw_sdio_write_to_port(struct rtw_dev *rtwdev, struct sk_buff *skb,
+ u32 txaddr, size_t write_size)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ bool bus_claim;
+ int ret;
bus_claim = rtw_sdio_bus_claim_needed(rtwsdio);
if (bus_claim)
sdio_claim_host(rtwsdio->sdio_func);
- ret = sdio_memcpy_toio(rtwsdio->sdio_func, txaddr, skb->data, txsize);
+ ret = sdio_memcpy_toio(rtwsdio->sdio_func, txaddr, skb->data,
+ write_size);
if (bus_claim)
sdio_release_host(rtwsdio->sdio_func);
@@ -668,16 +863,112 @@ static int rtw_sdio_write_port(struct rtw_dev *rtwdev, struct sk_buff *skb,
if (ret)
rtw_warn(rtwdev,
"Failed to write %zu byte(s) to SDIO port 0x%08x",
- txsize, txaddr);
+ write_size, txaddr);
return ret;
}
+/*
+ * The free page check, the output queue wait and the accounting after the
+ * transfer have to be one unit, or two writers can both pass the checks and
+ * claim the same pages and output queue entry.
+ */
+static int rtw_sdio_8723bs_write_port(struct rtw_dev *rtwdev,
+ struct sk_buff *skb,
+ enum rtw_tx_queue_type queue, u32 txaddr,
+ size_t txsize, size_t write_size)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ unsigned int pages;
+ int ret;
+
+ lockdep_assert_held(&rtwsdio->tx_credit_lock);
+
+ ret = rtw_sdio_check_free_txpg(rtwdev, queue, txsize);
+ if (ret)
+ return ret;
+
+ ret = rtw_sdio_8723bs_wait_tx_oqt(rtwdev);
+ if (ret)
+ return ret;
+
+ if (!IS_ALIGNED((unsigned long)skb->data, RTW_SDIO_DATA_PTR_ALIGN))
+ rtw_warn(rtwdev, "Got unaligned SKB in %s() for queue %u\n",
+ __func__, queue);
+
+ ret = rtw_sdio_write_to_port(rtwdev, skb, txaddr, write_size);
+ if (ret) {
+ /* nothing was queued, so hand the output queue entry back */
+ atomic_inc(&rtwsdio->tx_oqt_free);
+ return ret;
+ }
+
+ pages = DIV_ROUND_UP(txsize, rtwdev->chip->page_size);
+ rtw_sdio_8723bs_consume_txpg(rtwdev, queue, pages);
+
+ return 0;
+}
+
+static int rtw_sdio_write_port(struct rtw_dev *rtwdev, struct sk_buff *skb,
+ enum rtw_tx_queue_type queue)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ size_t write_size;
+ size_t txsize;
+ u32 txaddr;
+ int ret;
+
+ txaddr = rtw_sdio_get_tx_addr(rtwdev, skb->len, queue);
+ if (!txaddr)
+ return -EINVAL;
+
+ if (!rtw_is_8723bs(rtwdev)) {
+ txsize = sdio_align_size(rtwsdio->sdio_func, skb->len);
+
+ ret = rtw_sdio_check_free_txpg(rtwdev, queue, txsize);
+ if (ret)
+ return ret;
+
+ if (!IS_ALIGNED((unsigned long)skb->data,
+ RTW_SDIO_DATA_PTR_ALIGN))
+ rtw_warn(rtwdev,
+ "Got unaligned SKB in %s() for queue %u\n",
+ __func__, queue);
+
+ return rtw_sdio_write_to_port(rtwdev, skb, txaddr, txsize);
+ }
+
+ txsize = round_up(skb->len, 4);
+ write_size = txsize > RTW_SDIO_BLOCK_SIZE ?
+ round_up(txsize, RTW_SDIO_BLOCK_SIZE) : txsize;
+
+ if (write_size > skb->len) {
+ size_t pad_size = write_size - skb->len;
+
+ /*
+ * __skb_pad() must not free the skb on failure: both callers
+ * still own it, one requeues it and the other frees it.
+ */
+ ret = __skb_pad(skb, pad_size, false);
+ if (ret)
+ return ret;
+ }
+
+ guard(mutex)(&rtwsdio->tx_credit_lock);
+
+ return rtw_sdio_8723bs_write_port(rtwdev, skb, queue, txaddr, txsize,
+ write_size);
+}
+
static void rtw_sdio_init(struct rtw_dev *rtwdev)
{
struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
- rtwsdio->irq_mask = REG_SDIO_HIMR_RX_REQUEST | REG_SDIO_HIMR_CPWM1;
+ if (rtw_is_8723bs(rtwdev))
+ rtwsdio->irq_mask = REG_SDIO_HIMR_RX_REQUEST;
+ else
+ rtwsdio->irq_mask = REG_SDIO_HIMR_RX_REQUEST |
+ REG_SDIO_HIMR_CPWM1;
}
static void rtw_sdio_enable_rx_aggregation(struct rtw_dev *rtwdev)
@@ -685,6 +976,7 @@ static void rtw_sdio_enable_rx_aggregation(struct rtw_dev *rtwdev)
u8 size, timeout;
switch (rtwdev->chip->id) {
+ case RTW_CHIP_TYPE_8723B:
case RTW_CHIP_TYPE_8703B:
case RTW_CHIP_TYPE_8821A:
case RTW_CHIP_TYPE_8812A:
@@ -712,6 +1004,8 @@ static void rtw_sdio_enable_rx_aggregation(struct rtw_dev *rtwdev)
FIELD_PREP(BIT_DMA_AGG_TO_V1, timeout));
rtw_write8_set(rtwdev, REG_RXDMA_MODE, BIT_DMA_MODE);
+ if (rtw_is_8723bs(rtwdev))
+ rtw_write8_mask(rtwdev, REG_RXDMA_MODE, BIT_DMA_BURST_CNT, 0x3);
}
static void rtw_sdio_enable_interrupt(struct rtw_dev *rtwdev)
@@ -749,9 +1043,61 @@ static int rtw_sdio_setup(struct rtw_dev *rtwdev)
return 0;
}
+/*
+ * Reprogram the queue page allocation if the chip came up with none. This is
+ * a repair path, not part of the normal start sequence: a non-zero free page
+ * count means the allocation latched during power on and must be left alone,
+ * and without a transmit page pool there is nothing to divide up either.
+ */
+static int rtw_sdio_8723bs_check_rqpn(struct rtw_dev *rtwdev)
+{
+ const struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_fifo_conf *fifo = &rtwdev->fifo;
+ const struct rtw_page_table *pg_tbl;
+ u32 free_txpg;
+ u16 pubq_num;
+ int ret;
+
+ free_txpg = rtw_read32(rtwdev, REG_SDIO_FREE_TXPG);
+ if (free_txpg || !fifo->acq_pg_num)
+ return 0;
+
+ ret = rtw_sdio_8723bs_pubq_num(rtwdev, &pubq_num);
+ if (ret)
+ return ret;
+
+ pg_tbl = &chip->page_table[0];
+ rtw_write32(rtwdev, REG_RQPN_NPQ,
+ BIT_RQPN_NE(pg_tbl->nq_num, pg_tbl->exq_num));
+ rtw_write32(rtwdev, REG_RQPN,
+ BIT_RQPN_HLP(pg_tbl->hq_num, pg_tbl->lq_num, pubq_num));
+
+ return 0;
+}
+
static int rtw_sdio_start(struct rtw_dev *rtwdev)
{
+ u32 clear;
+
+ if (rtw_is_8723bs(rtwdev)) {
+ int ret = rtw_sdio_8723bs_check_rqpn(rtwdev);
+
+ if (ret)
+ return ret;
+
+ ret = rtw_sdio_8723bs_init_free_txpg(rtwdev);
+ if (ret)
+ return ret;
+ }
+
rtw_sdio_enable_rx_aggregation(rtwdev);
+
+ if (rtw_is_8723bs(rtwdev)) {
+ clear = rtw_read32(rtwdev, REG_SDIO_HISR) & RTW_SDIO_HISR_CLEAR_MASK;
+ if (clear)
+ rtw_write32(rtwdev, REG_SDIO_HISR, clear);
+ }
+
rtw_sdio_enable_interrupt(rtwdev);
return 0;
@@ -815,7 +1161,11 @@ static void rtw_sdio_tx_kick_off(struct rtw_dev *rtwdev)
{
struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
- queue_work(rtwsdio->txwq, &rtwsdio->tx_handler_data->work);
+ /*
+ * A retry may already be pending with a delay; re-arm it so a newly
+ * queued frame is not held back by it.
+ */
+ mod_delayed_work(rtwsdio->txwq, &rtwsdio->tx_handler_data->work, 0);
}
static void rtw_sdio_link_ps(struct rtw_dev *rtwdev, bool enter)
@@ -831,6 +1181,8 @@ static void rtw_sdio_interface_cfg(struct rtw_dev *rtwdev)
val = rtw_read32(rtwdev, REG_SDIO_TX_CTRL);
val &= 0xfff8;
+ if (rtw_is_8723bs(rtwdev))
+ val |= BIT_SDIO_TX_CTRL_ALWAYS_RECOGNIZE;
rtw_write32(rtwdev, REG_SDIO_TX_CTRL, val);
}
@@ -922,12 +1274,65 @@ static int rtw_sdio_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size)
return rtw_sdio_write_data(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_H2C);
}
+/*
+ * Back-pressure on the data ACs (BK/BE/VI/VO): once the software FIFO fills
+ * past the high watermark, stop the corresponding mac80211 queue so it stops
+ * handing frames down, which bounds the queueing latency. The queue is woken
+ * again from the TX drain path once the FIFO falls back to the low watermark.
+ *
+ * Both sides hold the TX queue lock across the length check and the flag
+ * update, so a queue is only ever stopped while it really is above the
+ * watermark, and the drain path always sees the flag the producer set.
+ */
+static void rtw_sdio_8723bs_stop_tx_queue(struct rtw_dev *rtwdev,
+ enum rtw_tx_queue_type queue,
+ u16 q_map)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+
+ if (!rtw_is_8723bs(rtwdev) || queue >= RTW_TX_QUEUE_BCN)
+ return;
+
+ guard(spinlock_irqsave)(&rtwsdio->tx_queue[queue].lock);
+
+ if (rtwsdio->tx_queue_stopped[queue])
+ return;
+
+ if (skb_queue_len(&rtwsdio->tx_queue[queue]) < RTW_SDIO_TX_FIFO_HIWATER)
+ return;
+
+ rtwsdio->tx_queue_stopped[queue] = true;
+ ieee80211_stop_queue(rtwdev->hw, q_map);
+}
+
+static void rtw_sdio_8723bs_wake_tx_queue(struct rtw_dev *rtwdev,
+ enum rtw_tx_queue_type queue,
+ u16 q_map)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+
+ if (!rtw_is_8723bs(rtwdev) || queue >= RTW_TX_QUEUE_BCN)
+ return;
+
+ guard(spinlock_irqsave)(&rtwsdio->tx_queue[queue].lock);
+
+ if (!rtwsdio->tx_queue_stopped[queue])
+ return;
+
+ if (skb_queue_len(&rtwsdio->tx_queue[queue]) > RTW_SDIO_TX_FIFO_LOWATER)
+ return;
+
+ rtwsdio->tx_queue_stopped[queue] = false;
+ ieee80211_wake_queue(rtwdev->hw, q_map);
+}
+
static int rtw_sdio_tx_write(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
struct sk_buff *skb)
{
struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
enum rtw_tx_queue_type queue = rtw_tx_queue_mapping(skb);
+ u16 q_map = skb_get_queue_mapping(skb);
struct rtw_sdio_tx_data *tx_data;
rtw_sdio_tx_skb_prepare(rtwdev, pkt_info, skb, queue);
@@ -935,8 +1340,15 @@ static int rtw_sdio_tx_write(struct rtw_dev *rtwdev,
tx_data = rtw_sdio_get_tx_data(skb);
tx_data->sn = pkt_info->sn;
+ /*
+ * skb_queue_tail() publishes the skb to the TX worker, which may
+ * process and free it immediately, so nothing may touch the skb
+ * past this point.
+ */
skb_queue_tail(&rtwsdio->tx_queue[queue], skb);
+ rtw_sdio_8723bs_stop_tx_queue(rtwdev, queue, q_map);
+
return 0;
}
@@ -1095,6 +1507,14 @@ static void rtw_sdio_handle_interrupt(struct sdio_func *sdio_func)
rtw_sdio_rx_isr(rtwdev);
}
+ /*
+ * RTL8723BS keeps raising the interrupt after resume if undefined
+ * status bits are written back, so acknowledge only the bits this
+ * driver defines. Other chips keep the existing behaviour.
+ */
+ if (rtw_is_8723bs(rtwdev))
+ hisr &= RTW_SDIO_HISR_CLEAR_MASK;
+
rtw_write32(rtwdev, REG_SDIO_HISR, hisr);
rtwsdio->irq_thread = NULL;
@@ -1231,33 +1651,83 @@ static void rtw_sdio_indicate_tx_status(struct rtw_dev *rtwdev,
ieee80211_tx_status_irqsafe(hw, skb);
}
-static void rtw_sdio_process_tx_queue(struct rtw_dev *rtwdev,
- enum rtw_tx_queue_type queue)
+/*
+ * Send one frame from @queue. Returns 0 when a frame was written, 1 when the
+ * queue was empty and a negative errno when the write failed, in which case
+ * the frame is put back at the head of the queue.
+ */
+static int rtw_sdio_process_tx_queue(struct rtw_dev *rtwdev,
+ enum rtw_tx_queue_type queue)
{
struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
struct sk_buff *skb;
+ u16 q_map;
int ret;
skb = skb_dequeue(&rtwsdio->tx_queue[queue]);
if (!skb)
- return;
+ return 1;
ret = rtw_sdio_write_port(rtwdev, skb, queue);
if (ret) {
skb_queue_head(&rtwsdio->tx_queue[queue], skb);
- return;
+ return ret;
}
+ /* rtw_sdio_indicate_tx_status() consumes the skb, so read this first */
+ q_map = skb_get_queue_mapping(skb);
+
rtw_sdio_indicate_tx_status(rtwdev, skb);
+
+ rtw_sdio_8723bs_wake_tx_queue(rtwdev, queue, q_map);
+
+ return 0;
+}
+
+/*
+ * Decide whether the RTL8723BS wants the TX work to run again, and if so
+ * arrange it and tell the caller to stop draining. Two cases need it.
+ *
+ * A transmit page or output queue shortage and a failed skb expansion are
+ * transient and leave the frame queued, so come back for it shortly. That
+ * matters once the mac80211 queue can be stopped: a stopped queue is handed
+ * no further frames, so nothing else would kick this work item and the access
+ * category would stay stopped for good. The remaining errors are logged where
+ * they happen and are not retried.
+ *
+ * After a management frame, restart from the highest priority queue so the
+ * join sequence is not held up behind a data backlog.
+ */
+static bool rtw_sdio_8723bs_reschedule_tx(struct rtw_dev *rtwdev,
+ struct rtw_sdio_work_data *work_data,
+ enum rtw_tx_queue_type queue, int ret)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ unsigned long delay;
+
+ if (!rtw_is_8723bs(rtwdev))
+ return false;
+
+ if (ret == -EBUSY || ret == -ENOMEM)
+ delay = RTW_SDIO_TX_RETRY_DELAY;
+ else if (ret == 0 && queue == RTW_TX_QUEUE_MGMT)
+ delay = 0;
+ else
+ return false;
+
+ queue_delayed_work(rtwsdio->txwq, &work_data->work, delay);
+
+ return true;
}
static void rtw_sdio_tx_handler(struct work_struct *work)
{
struct rtw_sdio_work_data *work_data =
- container_of(work, struct rtw_sdio_work_data, work);
+ container_of(to_delayed_work(work), struct rtw_sdio_work_data,
+ work);
struct rtw_sdio *rtwsdio;
struct rtw_dev *rtwdev;
- int limit, queue;
+ int limit, queue, ret;
rtwdev = work_data->rtwdev;
rtwsdio = (struct rtw_sdio *)rtwdev->priv;
@@ -1267,7 +1737,13 @@ static void rtw_sdio_tx_handler(struct work_struct *work)
for (queue = RTK_MAX_TX_QUEUE_NUM - 1; queue >= 0; queue--) {
for (limit = 0; limit < 1000; limit++) {
- rtw_sdio_process_tx_queue(rtwdev, queue);
+ ret = rtw_sdio_process_tx_queue(rtwdev, queue);
+ if (ret > 0)
+ break;
+
+ if (rtw_sdio_8723bs_reschedule_tx(rtwdev, work_data,
+ queue, ret))
+ return;
if (skb_queue_empty(&rtwsdio->tx_queue[queue]))
break;
@@ -1294,18 +1770,23 @@ static int rtw_sdio_init_tx(struct rtw_dev *rtwdev)
return -ENOMEM;
}
- for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++)
+ mutex_init(&rtwsdio->tx_credit_lock);
+
+ for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++) {
skb_queue_head_init(&rtwsdio->tx_queue[i]);
+ rtwsdio->tx_queue_stopped[i] = false;
+ }
rtwsdio->tx_handler_data = kmalloc_obj(*rtwsdio->tx_handler_data);
if (!rtwsdio->tx_handler_data)
goto err_destroy_wq;
rtwsdio->tx_handler_data->rtwdev = rtwdev;
- INIT_WORK(&rtwsdio->tx_handler_data->work, rtw_sdio_tx_handler);
+ INIT_DELAYED_WORK(&rtwsdio->tx_handler_data->work, rtw_sdio_tx_handler);
return 0;
err_destroy_wq:
+ mutex_destroy(&rtwsdio->tx_credit_lock);
destroy_workqueue(rtwsdio->txwq);
return -ENOMEM;
}
@@ -1315,11 +1796,14 @@ static void rtw_sdio_deinit_tx(struct rtw_dev *rtwdev)
struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
int i;
+ cancel_delayed_work_sync(&rtwsdio->tx_handler_data->work);
destroy_workqueue(rtwsdio->txwq);
kfree(rtwsdio->tx_handler_data);
for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++)
ieee80211_purge_tx_queue(rtwdev->hw, &rtwsdio->tx_queue[i]);
+
+ mutex_destroy(&rtwsdio->tx_credit_lock);
}
int rtw_sdio_probe(struct sdio_func *sdio_func,
diff --git a/drivers/net/wireless/realtek/rtw88/sdio.h b/drivers/net/wireless/realtek/rtw88/sdio.h
index 457e8b02380e5..6e7e6009744b0 100644
--- a/drivers/net/wireless/realtek/rtw88/sdio.h
+++ b/drivers/net/wireless/realtek/rtw88/sdio.h
@@ -22,6 +22,7 @@
/* SDIO Tx Control */
#define REG_SDIO_TX_CTRL (SDIO_LOCAL_OFFSET + 0x0000)
+#define BIT_SDIO_TX_CTRL_ALWAYS_RECOGNIZE BIT(4)
/*SDIO status timeout*/
#define REG_SDIO_TIMEOUT (SDIO_LOCAL_OFFSET + 0x0002)
@@ -77,6 +78,14 @@
/* the following two are RTL8188 SDIO Specific */
#define REG_SDIO_HISR_MCU_ERR BIT(28)
#define REG_SDIO_HISR_TSF_BIT32_TOGGLE BIT(29)
+#define RTW_SDIO_HISR_CLEAR_MASK \
+ (REG_SDIO_HISR_TXERR | REG_SDIO_HISR_RXERR | \
+ REG_SDIO_HISR_TXFOVW | REG_SDIO_HISR_RXFOVW | \
+ REG_SDIO_HISR_TXBCNOK | REG_SDIO_HISR_TXBCNERR | \
+ REG_SDIO_HISR_C2HCMD | REG_SDIO_HISR_CPWM1 | \
+ REG_SDIO_HISR_CPWM2 | REG_SDIO_HISR_HSISR_IND | \
+ REG_SDIO_HISR_GTINT3_IND | REG_SDIO_HISR_GTINT4_IND | \
+ REG_SDIO_HISR_PSTIMEOUT | REG_SDIO_HISR_OCPINT)
/* HCI Current Power Mode */
#define REG_SDIO_HCPWM (SDIO_LOCAL_OFFSET + 0x0019)
@@ -86,6 +95,10 @@
#define REG_SDIO_OQT_FREE_PG (SDIO_LOCAL_OFFSET + 0x001E)
/* Free Tx Buffer Page */
#define REG_SDIO_FREE_TXPG (SDIO_LOCAL_OFFSET + 0x0020)
+#define BIT_FREE_TXPG_HIGH GENMASK(7, 0)
+#define BIT_FREE_TXPG_NORMAL GENMASK(15, 8)
+#define BIT_FREE_TXPG_LOW GENMASK(23, 16)
+#define BIT_FREE_TXPG_PUB GENMASK(31, 24)
/* HCI Current Power Mode 1 */
#define REG_SDIO_HCPWM1 (SDIO_LOCAL_OFFSET + 0x0024)
/* HCI Current Power Mode 2 */
@@ -143,7 +156,7 @@ struct rtw_sdio_tx_data {
};
struct rtw_sdio_work_data {
- struct work_struct work;
+ struct delayed_work work;
struct rtw_dev *rtwdev;
};
@@ -159,6 +172,15 @@ struct rtw_sdio {
struct workqueue_struct *txwq;
struct rtw_sdio_work_data *tx_handler_data;
struct sk_buff_head tx_queue[RTK_MAX_TX_QUEUE_NUM];
+ bool tx_queue_stopped[RTK_MAX_TX_QUEUE_NUM];
+
+ atomic_t free_pg_high;
+ atomic_t free_pg_normal;
+ atomic_t free_pg_low;
+ atomic_t free_pg_pub;
+ atomic_t tx_oqt_free;
+ /* one writer at a time between the credit check and the accounting */
+ struct mutex tx_credit_lock;
};
extern const struct dev_pm_ops rtw_sdio_pm_ops;
diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c
index 8786bbb421c2b..4e110a457e71d 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.c
+++ b/drivers/net/wireless/realtek/rtw88/tx.c
@@ -208,8 +208,9 @@ void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn)
__skb_queue_tail(&tx_report->queue, skb);
spin_unlock_irqrestore(&tx_report->q_lock, flags);
- if (rtwdev->chip->id == RTW_CHIP_TYPE_8723D &&
- rtwdev->hci.type == RTW_HCI_TYPE_USB)
+ if ((rtwdev->chip->id == RTW_CHIP_TYPE_8723D &&
+ rtwdev->hci.type == RTW_HCI_TYPE_USB) ||
+ rtw_is_8723bs(rtwdev))
timeout = msecs_to_jiffies(2500);
mod_timer(&tx_report->purge_timer, jiffies + timeout);
|
| 3/2 | 2026/08/25 19:11 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 14021 output: 28 thoughts: 550 Thoughts: **Reaching the Realtek SDIO Driver in a Virtualized Environment** Okay, so I have this patch, and it's modifying the Realtek `rtw88` wireless driver, specifically to support the RTL8723BS SDIO chip. We're talking about additions to the `enum rtw_chip_type`, a new helper function, and some targeted changes in how the driver handles RX and TX. There's a lot of work related to SDIO specifics, TX FIFO back-pressure, and queue management, which makes me think about whether this is even *reachable* in a virtualized context. The driver is `rtw88`, which is a wireless driver, but this specific patch centers around the SDIO interface. My immediate thought is, can SDIO devices be emulated or fuzzed? I know syzkaller has some support for fuzzing, but it's usually focused on USB or PCI. But wait, `rtw88` supports PCI, USB, and SDIO, so maybe syzkaller has something? I need to check if syzkaller can handle SDIO fuzzing or if this patch is even reachable under virtualization. This prompt is hinting at a potential problem because of the statement: "Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware". So, the key is SDIO emulation in QEMU or syzkaller. I need to find out if there's any SDIO host controller emulation. I need to search for "sdio" in the kernel source or syzkaller. I can't directly search syzkaller. Let's see if there's an equivalent of `vhci` for SDIO, or maybe some kind of virtual SDIO host controller. I'll search for "sdio" or "mmc" in `drivers/mmc/host/`. Okay, there's `CONFIG_MMC_TEST`, but that's for testing, not emulation. The crucial question is: is there a virtual SDIO host controller? I'll look for "vhci" or "dummy" in that directory to be sure. |
| 4/2 | 2026/08/25 19:11 | tool | grepper |
0mArgs:{
"Expression": "dummy",
"PathPrefix": "drivers/mmc/host/"
}Results: {
"Output": "drivers/mmc/host/cavium-thunderx.c=57=static int thunder_mmc_probe(struct pci_dev *pdev,\n--\ndrivers/mmc/host/cavium-thunderx.c-134-\t\t * mmc_of_parse and devm* require one device per slot.\ndrivers/mmc/host/cavium-thunderx.c:135:\t\t * Create a dummy device per slot and set the node pointer to\ndrivers/mmc/host/cavium-thunderx.c-136-\t\t * the slot. The easiest way to get this is using\n--\ndrivers/mmc/host/litex_mmc.c=450=static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)\n--\ndrivers/mmc/host/litex_mmc.c-455-\t * The SD specification requires at least 74 idle clocks before CMD0.\ndrivers/mmc/host/litex_mmc.c:456:\t * These dummy cycles is generated by writing LITEX_PHY_INITIALIZE.\ndrivers/mmc/host/litex_mmc.c-457-\t */\n--\ndrivers/mmc/host/omap.c=201=static void mmc_omap_select_slot(struct mmc_omap_slot *slot, int claimed)\n--\ndrivers/mmc/host/omap.c-235-\ndrivers/mmc/host/omap.c:236:\t\t/* Doing the dummy read here seems to work around some bug\ndrivers/mmc/host/omap.c-237-\t\t * at least in OMAP24xx silicon where the command would not\n--\ndrivers/mmc/host/rtsx_pci_sdmmc.c=208=static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,\n--\ndrivers/mmc/host/rtsx_pci_sdmmc.c-301-\t\t * The controller offloads the last byte {CRC-7, end bit 1'b1}\ndrivers/mmc/host/rtsx_pci_sdmmc.c:302:\t\t * of response type R2. Assign dummy CRC, 0, and end bit to the\ndrivers/mmc/host/rtsx_pci_sdmmc.c-303-\t\t * byte(ptr[16], goes into the LSB of resp[3] later).\n--\ndrivers/mmc/host/rtsx_usb_sdmmc.c=285=static void sd_send_cmd_get_rsp(struct rtsx_usb_sdmmc *host,\n--\ndrivers/mmc/host/rtsx_usb_sdmmc.c-425-\t\t * The controller offloads the last byte {CRC-7, end bit 1'b1}\ndrivers/mmc/host/rtsx_usb_sdmmc.c:426:\t\t * of response type R2. Assign dummy CRC, 0, and end bit to the\ndrivers/mmc/host/rtsx_usb_sdmmc.c-427-\t\t * byte(ptr[16], goes into the LSB of resp[3] later).\n--\ndrivers/mmc/host/sdhci-esdhc-imx.c-214-\ndrivers/mmc/host/sdhci-esdhc-imx.c:215:/* the controller has dummy pad for clock loopback */\ndrivers/mmc/host/sdhci-esdhc-imx.c-216-#define ESDHC_FLAG_DUMMY_PAD\t\tBIT(19)\n--\ndrivers/mmc/host/sdhci-pxav2.c=101=static u32 pxav1_irq(struct sdhci_host *host, u32 intmask)\n--\ndrivers/mmc/host/sdhci-pxav2.c-106-\tif (pxav2_host-\u003esdio_mrq \u0026\u0026 (intmask \u0026 SDHCI_INT_CMD_MASK)) {\ndrivers/mmc/host/sdhci-pxav2.c:107:\t\t/* The dummy CMD0 for the SDIO workaround just completed */\ndrivers/mmc/host/sdhci-pxav2.c-108-\t\tsdhci_writel(host, intmask \u0026 SDHCI_INT_CMD_MASK, SDHCI_INT_STATUS);\n--\ndrivers/mmc/host/sdhci-pxav2.c=123=static void pxav1_request_done(struct sdhci_host *host, struct mmc_request *mrq)\n--\ndrivers/mmc/host/sdhci-pxav2.c-136-\ndrivers/mmc/host/sdhci-pxav2.c:137:\t\t/* Clock is now stopped, so restart it by sending a dummy CMD0 */\ndrivers/mmc/host/sdhci-pxav2.c-138-\t\tpxav2_host = sdhci_pltfm_priv(sdhci_priv(host));\n--\ndrivers/mmc/host/sdhci-pxav2.c-149-\ndrivers/mmc/host/sdhci-pxav2.c:150:\t\t/* Don't finish this request until the dummy CMD0 finishes */\ndrivers/mmc/host/sdhci-pxav2.c-151-\t\treturn;\n--\ndrivers/mmc/host/sdhci.c=653=static int sdhci_pre_dma_transfer(struct sdhci_host *host,\n--\ndrivers/mmc/host/sdhci.c-689-\t\t\t\t\t mmc_get_dma_dir(data));\ndrivers/mmc/host/sdhci.c:690:\t\t/* Just a dummy value */\ndrivers/mmc/host/sdhci.c-691-\t\tsg_count = 1;\n"
} |
| 5/2 | 2026/08/25 19:11 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 16518 output: 26 thoughts: 238 Thoughts: **My SDIO Fuzzing Dilemma** Okay, so I'm looking at fuzzing this `rtw88` SDIO driver. My initial thought is, "Shoot, there's no virtual SDIO host controller in the kernel. That's going to make things difficult." Then I pause and think, "Wait a minute, is there *any* way to reach this code? Maybe through another path?" I remember `mac80211_hwsim`, but quickly dismiss it. It's a virtual MAC layer, not a virtual SDIO device, so no luck there. I know the target code is in `drivers/net/wireless/realtek/rtw88/sdio.c`. It's pretty clear that `rtw_sdio_probe` is the entry point, called when an SDIO device matches the expected IDs. The problem is, without a physical SDIO bus or a virtual host controller, `rtw_sdio_probe` just won't be called. So, where do I go from here? Time to see if syzkaller has any existing SDIO fuzzing setups I can leverage. I'll use `default_api:grepper` to search for "sdio" in the `drivers/virt/` and `drivers/misc/` directories. Maybe, just maybe, there's a virtual host controller interface (like a `vhci` for SDIO) I can use. Otherwise, I'm going to have to start thinking outside the box! |
| 6/2 | 2026/08/25 19:11 | tool | grepper |
0mError:no matches Args: {
"Expression": "sdio",
"PathPrefix": "drivers/virt/"
}Results: {
"error": "no matches"
} |
| 7/2 | 2026/08/25 19:11 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 17123 output: 29 thoughts: 332 Thoughts: **My QEMU SDIO Emulation Investigation** Okay, so I'm trying to figure out if a specific SDIO driver, like the one for the RTL8723BS, is actually reachable within a virtualized QEMU environment. My initial thought is to check if QEMU even has any SDIO emulation. I know it has `sdhci-pci`, which is an SD host controller, but that's not the same thing. Can I *plug* an SDIO device into it, or is it just for SD cards? QEMU is usually pretty sparse on emulating specific SDIO WiFi chips, from what I've seen. Then I re-read the prompt, and the key phrases jump out: "impossible to reach in virtualized environments like GCE or QEMU," especially when it comes to the limitations of software-emulated hardware. Specifically, the prompt mentions driver tear-down callbacks during PCI hot-unplug or driver unbind operations. It also mentions vendor-specific hardware that QEMU doesn't fully emulate. So, are we talking about the RTL8723BS SDIO driver, can *that* path be triggered in QEMU? If QEMU doesn't emulate the RTL8723BS SDIO *hardware*, and there's no equivalent software-emulated SDIO device framework – similar to how we have USB gadget for USB devices or vhci for HCI – then it seems almost certain the code path is unreachable. My next step is to see if there's any SDIO device emulation at the kernel level that might provide some sort of abstraction. |
| 8/2 | 2026/08/25 19:12 | tool | grepper |
0mArgs:{
"Expression": "sdio",
"PathPrefix": "drivers/mmc/core/"
}Results: {
"Output": "\nFull output is too long, showing 500 out of 2250 lines.\nUse more precise expression if possible.\n\ndrivers/mmc/core/Makefile=7=mmc_core-y\t\t\t:= core.o bus.o host.o \\\ndrivers/mmc/core/Makefile-8-\t\t\t\t mmc.o mmc_ops.o sd.o sd_ops.o \\\ndrivers/mmc/core/Makefile:9:\t\t\t\t sdio.o sdio_ops.o sdio_bus.o \\\ndrivers/mmc/core/Makefile:10:\t\t\t\t sdio_cis.o sdio_io.o sdio_irq.o sd_uhs2.o\\\ndrivers/mmc/core/Makefile-11-\t\t\t\t slot-gpio.o regulator.o\n--\ndrivers/mmc/core/Makefile=19=obj-$(CONFIG_MMC_TEST)\t\t+= mmc_test.o\ndrivers/mmc/core/Makefile:20:obj-$(CONFIG_SDIO_UART)\t\t+= sdio_uart.o\ndrivers/mmc/core/Makefile-21-mmc_core-$(CONFIG_MMC_CRYPTO)\t+= crypto.o\n--\ndrivers/mmc/core/bus.c-26-#include \"host.h\"\ndrivers/mmc/core/bus.c:27:#include \"sdio_cis.h\"\ndrivers/mmc/core/bus.c-28-#include \"bus.h\"\n--\ndrivers/mmc/core/bus.c=59=mmc_bus_uevent(const struct device *dev, struct kobj_uevent_env *env)\n--\ndrivers/mmc/core/bus.c-88-\ndrivers/mmc/core/bus.c:89:\tif (mmc_card_sdio(card) || mmc_card_sd_combo(card)) {\ndrivers/mmc/core/bus.c-90-\t\tretval = add_uevent_var(env, \"SDIO_ID=%04X:%04X\",\n--\ndrivers/mmc/core/bus.c-110-\t */\ndrivers/mmc/core/bus.c:111:\tif (mmc_card_sdio(card))\ndrivers/mmc/core/bus.c-112-\t\treturn 0;\n--\ndrivers/mmc/core/bus.c=264=static void mmc_release_card(struct device *dev)\n--\ndrivers/mmc/core/bus.c-267-\ndrivers/mmc/core/bus.c:268:\tsdio_free_common_cis(card);\ndrivers/mmc/core/bus.c-269-\n--\ndrivers/mmc/core/card.h-45-/*\ndrivers/mmc/core/card.h:46: * The world is not perfect and supplies us with broken mmc/sdio devices.\ndrivers/mmc/core/card.h-47- * For at least some of these bugs we need a work-around.\n--\ndrivers/mmc/core/core.c-41-#include \"host.h\"\ndrivers/mmc/core/core.c:42:#include \"sdio_bus.h\"\ndrivers/mmc/core/core.c-43-#include \"pwrseq.h\"\n--\ndrivers/mmc/core/core.c-46-#include \"sd_ops.h\"\ndrivers/mmc/core/core.c:47:#include \"sdio_ops.h\"\ndrivers/mmc/core/core.c-48-\n--\ndrivers/mmc/core/core.c=216=static void __mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)\n--\ndrivers/mmc/core/core.c-228-\t/*\ndrivers/mmc/core/core.c:229:\t * For sdio rw commands we must wait for card busy otherwise some\ndrivers/mmc/core/core.c:230:\t * sdio devices won't work properly.\ndrivers/mmc/core/core.c-231-\t * And bypass I/O abort, reset and bus suspend operations.\ndrivers/mmc/core/core.c-232-\t */\ndrivers/mmc/core/core.c:233:\tif (sdio_is_io_busy(mrq-\u003ecmd-\u003eopcode, mrq-\u003ecmd-\u003earg) \u0026\u0026\ndrivers/mmc/core/core.c-234-\t host-\u003eops-\u003ecard_busy) {\n--\ndrivers/mmc/core/core.c=660=void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)\n--\ndrivers/mmc/core/core.c-666-\t */\ndrivers/mmc/core/core.c:667:\tif (mmc_card_sdio(card)) {\ndrivers/mmc/core/core.c-668-\t\tdata-\u003etimeout_ns = 1000000000;\n--\ndrivers/mmc/core/core.c=2099=static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)\n--\ndrivers/mmc/core/core.c-2114-\t/*\ndrivers/mmc/core/core.c:2115:\t * sdio_reset sends CMD52 to reset card. Since we do not know\ndrivers/mmc/core/core.c-2116-\t * if the card is being re-initialized, just send it. CMD52\n--\ndrivers/mmc/core/core.c-2120-\tif (!(host-\u003ecaps2 \u0026 MMC_CAP2_NO_SDIO))\ndrivers/mmc/core/core.c:2121:\t\tsdio_reset(host);\ndrivers/mmc/core/core.c-2122-\n--\ndrivers/mmc/core/core.c-2133-\tif (!(host-\u003ecaps2 \u0026 MMC_CAP2_NO_SDIO))\ndrivers/mmc/core/core.c:2134:\t\tif (!mmc_attach_sdio(host))\ndrivers/mmc/core/core.c-2135-\t\t\treturn 0;\n--\ndrivers/mmc/core/core.c=2393=static int __init mmc_init(void)\n--\ndrivers/mmc/core/core.c-2404-\ndrivers/mmc/core/core.c:2405:\tret = sdio_register_bus();\ndrivers/mmc/core/core.c-2406-\tif (ret)\n--\ndrivers/mmc/core/core.c=2418=static void __exit mmc_exit(void)\ndrivers/mmc/core/core.c-2419-{\ndrivers/mmc/core/core.c:2420:\tsdio_unregister_bus();\ndrivers/mmc/core/core.c-2421-\tmmc_unregister_host_class();\n--\ndrivers/mmc/core/core.h=87=int mmc_attach_sd(struct mmc_host *host);\ndrivers/mmc/core/core.h:88:int mmc_attach_sdio(struct mmc_host *host);\ndrivers/mmc/core/core.h-89-int mmc_attach_sd_uhs2(struct mmc_host *host);\n--\ndrivers/mmc/core/host.c-29-#include \"pwrseq.h\"\ndrivers/mmc/core/host.c:30:#include \"sdio_ops.h\"\ndrivers/mmc/core/host.c-31-\n--\ndrivers/mmc/core/host.c=265=int mmc_of_parse(struct mmc_host *host)\n--\ndrivers/mmc/core/host.c-367-\t\thost-\u003ecaps |= MMC_CAP_HW_RESET;\ndrivers/mmc/core/host.c:368:\tif (device_property_read_bool(dev, \"cap-sdio-irq\"))\ndrivers/mmc/core/host.c-369-\t\thost-\u003ecaps |= MMC_CAP_SDIO_IRQ;\n--\ndrivers/mmc/core/host.c-393-\t\thost-\u003ecaps2 |= MMC_CAP2_HS400_ES;\ndrivers/mmc/core/host.c:394:\tif (device_property_read_bool(dev, \"no-sdio\"))\ndrivers/mmc/core/host.c-395-\t\thost-\u003ecaps2 |= MMC_CAP2_NO_SDIO;\n--\ndrivers/mmc/core/host.c=512=struct mmc_host *mmc_alloc_host(int extra, struct device *dev)\n--\ndrivers/mmc/core/host.c-558-\tINIT_DELAYED_WORK(\u0026host-\u003edetect, mmc_rescan);\ndrivers/mmc/core/host.c:559:\tINIT_WORK(\u0026host-\u003esdio_irq_work, sdio_irq_work);\ndrivers/mmc/core/host.c-560-\ttimer_setup(\u0026host-\u003eretune_timer, mmc_retune_timer, 0);\n--\ndrivers/mmc/core/host.c=610=static int mmc_validate_host_caps(struct mmc_host *host)\n--\ndrivers/mmc/core/host.c-614-\ndrivers/mmc/core/host.c:615:\tif (caps \u0026 MMC_CAP_SDIO_IRQ \u0026\u0026 !host-\u003eops-\u003eenable_sdio_irq) {\ndrivers/mmc/core/host.c:616:\t\tdev_warn(dev, \"missing -\u003eenable_sdio_irq() ops\\n\");\ndrivers/mmc/core/host.c-617-\t\treturn -EINVAL;\n--\ndrivers/mmc/core/quirks.h-13-#include \u003clinux/of.h\u003e\ndrivers/mmc/core/quirks.h:14:#include \u003clinux/mmc/sdio_ids.h\u003e\ndrivers/mmc/core/quirks.h-15-\n--\ndrivers/mmc/core/quirks.h=168=static const struct mmc_fixup __maybe_unused mmc_ext_csd_fixups[] = {\n--\ndrivers/mmc/core/quirks.h-188-\ndrivers/mmc/core/quirks.h:189:static const struct mmc_fixup __maybe_unused sdio_fixup_methods[] = {\ndrivers/mmc/core/quirks.h-190-\tSDIO_FIXUP(SDIO_VENDOR_ID_TI_WL1251, SDIO_DEVICE_ID_TI_WL1251,\n--\ndrivers/mmc/core/quirks.h-216-\ndrivers/mmc/core/quirks.h:217:static const struct mmc_fixup __maybe_unused sdio_card_init_methods[] = {\ndrivers/mmc/core/quirks.h-218-\tSDIO_FIXUP_COMPATIBLE(\"ti,wl1251\", wl1251_quirk, 0),\n--\ndrivers/mmc/core/sd.c=748=MMC_DEV_ATTR(revision, \"%u.%u\\n\", card-\u003emajor_rev, card-\u003eminor_rev);\ndrivers/mmc/core/sd.c-749-\ndrivers/mmc/core/sd.c:750:#define sdio_info_attr(num)\t\t\t\t\t\t\t\t\t\\\ndrivers/mmc/core/sd.c-751-static ssize_t info##num##_show(struct device *dev, struct device_attribute *attr, char *buf)\t\\\n--\ndrivers/mmc/core/sd.c=761=static DEVICE_ATTR_RO(info##num)\ndrivers/mmc/core/sd.c-762-\ndrivers/mmc/core/sd.c:763:sdio_info_attr(1);\ndrivers/mmc/core/sd.c:764:sdio_info_attr(2);\ndrivers/mmc/core/sd.c:765:sdio_info_attr(3);\ndrivers/mmc/core/sd.c:766:sdio_info_attr(4);\ndrivers/mmc/core/sd.c-767-\n--\ndrivers/mmc/core/sdio.c-2-/*\ndrivers/mmc/core/sdio.c:3: * linux/drivers/mmc/sdio.c\ndrivers/mmc/core/sdio.c-4- *\n--\ndrivers/mmc/core/sdio.c-14-#include \u003clinux/mmc/mmc.h\u003e\ndrivers/mmc/core/sdio.c:15:#include \u003clinux/mmc/sdio.h\u003e\ndrivers/mmc/core/sdio.c:16:#include \u003clinux/mmc/sdio_func.h\u003e\ndrivers/mmc/core/sdio.c:17:#include \u003clinux/mmc/sdio_ids.h\u003e\ndrivers/mmc/core/sdio.c-18-\n--\ndrivers/mmc/core/sdio.c-24-#include \"sd.h\"\ndrivers/mmc/core/sdio.c:25:#include \"sdio_bus.h\"\ndrivers/mmc/core/sdio.c-26-#include \"mmc_ops.h\"\ndrivers/mmc/core/sdio.c-27-#include \"sd_ops.h\"\ndrivers/mmc/core/sdio.c:28:#include \"sdio_ops.h\"\ndrivers/mmc/core/sdio.c:29:#include \"sdio_cis.h\"\ndrivers/mmc/core/sdio.c-30-\n--\ndrivers/mmc/core/sdio.c=35=MMC_DEV_ATTR(rca, \"0x%04x\\n\", card-\u003erca);\ndrivers/mmc/core/sdio.c-36-\ndrivers/mmc/core/sdio.c:37:#define sdio_info_attr(num)\t\t\t\t\t\t\t\t\t\\\ndrivers/mmc/core/sdio.c-38-static ssize_t info##num##_show(struct device *dev, struct device_attribute *attr, char *buf)\t\\\n--\ndrivers/mmc/core/sdio.c=48=static DEVICE_ATTR_RO(info##num)\ndrivers/mmc/core/sdio.c-49-\ndrivers/mmc/core/sdio.c:50:sdio_info_attr(1);\ndrivers/mmc/core/sdio.c:51:sdio_info_attr(2);\ndrivers/mmc/core/sdio.c:52:sdio_info_attr(3);\ndrivers/mmc/core/sdio.c:53:sdio_info_attr(4);\ndrivers/mmc/core/sdio.c-54-\ndrivers/mmc/core/sdio.c:55:static struct attribute *sdio_std_attrs[] = {\ndrivers/mmc/core/sdio.c-56-\t\u0026dev_attr_vendor.attr,\n--\ndrivers/mmc/core/sdio.c-66-};\ndrivers/mmc/core/sdio.c:67:ATTRIBUTE_GROUPS(sdio_std);\ndrivers/mmc/core/sdio.c-68-\ndrivers/mmc/core/sdio.c:69:static const struct device_type sdio_type = {\ndrivers/mmc/core/sdio.c:70:\t.groups = sdio_std_groups,\ndrivers/mmc/core/sdio.c-71-};\ndrivers/mmc/core/sdio.c-72-\ndrivers/mmc/core/sdio.c:73:static int sdio_read_fbr(struct sdio_func *func)\ndrivers/mmc/core/sdio.c-74-{\n--\ndrivers/mmc/core/sdio.c-102-\ndrivers/mmc/core/sdio.c:103:static int sdio_init_func(struct mmc_card *card, unsigned int fn)\ndrivers/mmc/core/sdio.c-104-{\ndrivers/mmc/core/sdio.c-105-\tint ret;\ndrivers/mmc/core/sdio.c:106:\tstruct sdio_func *func;\ndrivers/mmc/core/sdio.c-107-\n--\ndrivers/mmc/core/sdio.c-110-\ndrivers/mmc/core/sdio.c:111:\tfunc = sdio_alloc_func(card);\ndrivers/mmc/core/sdio.c-112-\tif (IS_ERR(func))\n--\ndrivers/mmc/core/sdio.c-117-\tif (!(card-\u003equirks \u0026 MMC_QUIRK_NONSTD_SDIO)) {\ndrivers/mmc/core/sdio.c:118:\t\tret = sdio_read_fbr(func);\ndrivers/mmc/core/sdio.c-119-\t\tif (ret)\n--\ndrivers/mmc/core/sdio.c-121-\ndrivers/mmc/core/sdio.c:122:\t\tret = sdio_read_func_cis(func);\ndrivers/mmc/core/sdio.c-123-\t\tif (ret)\n--\ndrivers/mmc/core/sdio.c-130-\ndrivers/mmc/core/sdio.c:131:\tcard-\u003esdio_func[fn - 1] = func;\ndrivers/mmc/core/sdio.c-132-\n--\ndrivers/mmc/core/sdio.c-139-\t */\ndrivers/mmc/core/sdio.c:140:\tsdio_remove_func(func);\ndrivers/mmc/core/sdio.c-141-\treturn ret;\n--\ndrivers/mmc/core/sdio.c-143-\ndrivers/mmc/core/sdio.c:144:static int sdio_read_cccr(struct mmc_card *card, u32 ocr)\ndrivers/mmc/core/sdio.c-145-{\n--\ndrivers/mmc/core/sdio.c-163-\ndrivers/mmc/core/sdio.c:164:\tcard-\u003ecccr.sdio_vsn = (data \u0026 0xf0) \u003e\u003e 4;\ndrivers/mmc/core/sdio.c-165-\n--\ndrivers/mmc/core/sdio.c-260-\ndrivers/mmc/core/sdio.c:261:static int sdio_enable_wide(struct mmc_card *card)\ndrivers/mmc/core/sdio.c-262-{\n--\ndrivers/mmc/core/sdio.c-293- * of the card. This may be required on certain setups of boards,\ndrivers/mmc/core/sdio.c:294: * controllers and embedded sdio device which do not need the card's\ndrivers/mmc/core/sdio.c-295- * pull-up. As a result, card detection is disabled and power is saved.\ndrivers/mmc/core/sdio.c-296- */\ndrivers/mmc/core/sdio.c:297:static int sdio_disable_cd(struct mmc_card *card)\ndrivers/mmc/core/sdio.c-298-{\n--\ndrivers/mmc/core/sdio.c-317- */\ndrivers/mmc/core/sdio.c:318:static int sdio_disable_wide(struct mmc_card *card)\ndrivers/mmc/core/sdio.c-319-{\n--\ndrivers/mmc/core/sdio.c-347-\ndrivers/mmc/core/sdio.c:348:static int sdio_disable_4bit_bus(struct mmc_card *card)\ndrivers/mmc/core/sdio.c-349-{\n--\ndrivers/mmc/core/sdio.c-351-\ndrivers/mmc/core/sdio.c:352:\tif (mmc_card_sdio(card))\ndrivers/mmc/core/sdio.c-353-\t\tgoto out;\n--\ndrivers/mmc/core/sdio.c-365-out:\ndrivers/mmc/core/sdio.c:366:\treturn sdio_disable_wide(card);\ndrivers/mmc/core/sdio.c-367-}\n--\ndrivers/mmc/core/sdio.c-369-\ndrivers/mmc/core/sdio.c:370:static int sdio_enable_4bit_bus(struct mmc_card *card)\ndrivers/mmc/core/sdio.c-371-{\n--\ndrivers/mmc/core/sdio.c-373-\ndrivers/mmc/core/sdio.c:374:\terr = sdio_enable_wide(card);\ndrivers/mmc/core/sdio.c-375-\tif (err \u003c= 0)\ndrivers/mmc/core/sdio.c-376-\t\treturn err;\ndrivers/mmc/core/sdio.c:377:\tif (mmc_card_sdio(card))\ndrivers/mmc/core/sdio.c-378-\t\tgoto out;\n--\ndrivers/mmc/core/sdio.c-382-\t\tif (err) {\ndrivers/mmc/core/sdio.c:383:\t\t\tsdio_disable_wide(card);\ndrivers/mmc/core/sdio.c-384-\t\t\treturn err;\n--\ndrivers/mmc/core/sdio.c-396- */\ndrivers/mmc/core/sdio.c:397:static int mmc_sdio_switch_hs(struct mmc_card *card, int enable)\ndrivers/mmc/core/sdio.c-398-{\n--\ndrivers/mmc/core/sdio.c-426- */\ndrivers/mmc/core/sdio.c:427:static int sdio_enable_hs(struct mmc_card *card)\ndrivers/mmc/core/sdio.c-428-{\n--\ndrivers/mmc/core/sdio.c-430-\ndrivers/mmc/core/sdio.c:431:\tret = mmc_sdio_switch_hs(card, true);\ndrivers/mmc/core/sdio.c:432:\tif (ret \u003c= 0 || mmc_card_sdio(card))\ndrivers/mmc/core/sdio.c-433-\t\treturn ret;\n--\ndrivers/mmc/core/sdio.c-436-\tif (ret \u003c= 0)\ndrivers/mmc/core/sdio.c:437:\t\tmmc_sdio_switch_hs(card, false);\ndrivers/mmc/core/sdio.c-438-\n--\ndrivers/mmc/core/sdio.c-441-\ndrivers/mmc/core/sdio.c:442:static unsigned mmc_sdio_get_max_clock(struct mmc_card *card)\ndrivers/mmc/core/sdio.c-443-{\n--\ndrivers/mmc/core/sdio.c-465-\ndrivers/mmc/core/sdio.c:466:static unsigned char host_drive_to_sdio_drive(int host_strength)\ndrivers/mmc/core/sdio.c-467-{\n--\ndrivers/mmc/core/sdio.c-481-\ndrivers/mmc/core/sdio.c:482:static void sdio_select_driver_type(struct mmc_card *card)\ndrivers/mmc/core/sdio.c-483-{\n--\ndrivers/mmc/core/sdio.c-503-\t\tcard_strength \u0026= ~(SDIO_DRIVE_DTSx_MASK\u003c\u003cSDIO_DRIVE_DTSx_SHIFT);\ndrivers/mmc/core/sdio.c:504:\t\tcard_strength |= host_drive_to_sdio_drive(drive_strength);\ndrivers/mmc/core/sdio.c-505-\n--\ndrivers/mmc/core/sdio.c-518-\ndrivers/mmc/core/sdio.c:519:static int sdio_set_bus_speed_mode(struct mmc_card *card)\ndrivers/mmc/core/sdio.c-520-{\n--\ndrivers/mmc/core/sdio.c-592- */\ndrivers/mmc/core/sdio.c:593:static int mmc_sdio_init_uhs_card(struct mmc_card *card)\ndrivers/mmc/core/sdio.c-594-{\n--\ndrivers/mmc/core/sdio.c-600-\t/* Switch to wider bus */\ndrivers/mmc/core/sdio.c:601:\terr = sdio_enable_4bit_bus(card);\ndrivers/mmc/core/sdio.c-602-\tif (err)\n--\ndrivers/mmc/core/sdio.c-605-\t/* Set the driver strength for the card */\ndrivers/mmc/core/sdio.c:606:\tsdio_select_driver_type(card);\ndrivers/mmc/core/sdio.c-607-\ndrivers/mmc/core/sdio.c-608-\t/* Set bus speed mode of the card */\ndrivers/mmc/core/sdio.c:609:\terr = sdio_set_bus_speed_mode(card);\ndrivers/mmc/core/sdio.c-610-\tif (err)\n--\ndrivers/mmc/core/sdio.c-624-\ndrivers/mmc/core/sdio.c:625:static int mmc_sdio_pre_init(struct mmc_host *host, u32 ocr,\ndrivers/mmc/core/sdio.c-626-\t\t\t struct mmc_card *card)\n--\ndrivers/mmc/core/sdio.c-632-\t * Reset the card by performing the same steps that are taken by\ndrivers/mmc/core/sdio.c:633:\t * mmc_rescan_try_freq() and mmc_attach_sdio() during a \"normal\" probe.\ndrivers/mmc/core/sdio.c-634-\t *\ndrivers/mmc/core/sdio.c:635:\t * sdio_reset() is technically not needed. Having just powered up the\ndrivers/mmc/core/sdio.c-636-\t * hardware, it should already be in reset state. However, some\n--\ndrivers/mmc/core/sdio.c-647-\ndrivers/mmc/core/sdio.c:648:\tsdio_reset(host);\ndrivers/mmc/core/sdio.c-649-\tmmc_go_idle(host);\n--\ndrivers/mmc/core/sdio.c-659- */\ndrivers/mmc/core/sdio.c:660:static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,\ndrivers/mmc/core/sdio.c-661-\t\t\t struct mmc_card *oldcard)\n--\ndrivers/mmc/core/sdio.c-699-\t */\ndrivers/mmc/core/sdio.c:700:\tcard = mmc_alloc_card(host, \u0026sdio_type);\ndrivers/mmc/core/sdio.c-701-\tif (IS_ERR(card))\n--\ndrivers/mmc/core/sdio.c-715-\ndrivers/mmc/core/sdio.c:716:\t\tif (oldcard \u0026\u0026 !mmc_card_sdio(oldcard)) {\ndrivers/mmc/core/sdio.c-717-\t\t\terr = -ENOENT;\n--\ndrivers/mmc/core/sdio.c-726-\t\thost-\u003eops-\u003einit_card(host, card);\ndrivers/mmc/core/sdio.c:727:\tmmc_fixup_device(card, sdio_card_init_methods);\ndrivers/mmc/core/sdio.c-728-\n--\ndrivers/mmc/core/sdio.c-738-\t * fails to check rocr \u0026 R4_18V_PRESENT, but we still need to\ndrivers/mmc/core/sdio.c:739:\t * try to init uhs card. sdio_read_cccr will take over this task\ndrivers/mmc/core/sdio.c-740-\t * to make sure which speed mode should work.\n--\ndrivers/mmc/core/sdio.c-744-\t\tif (err == -EAGAIN) {\ndrivers/mmc/core/sdio.c:745:\t\t\tmmc_sdio_pre_init(host, ocr_card, card);\ndrivers/mmc/core/sdio.c-746-\t\t\tretries--;\n--\ndrivers/mmc/core/sdio.c-814-\t */\ndrivers/mmc/core/sdio.c:815:\terr = sdio_read_cccr(card, ocr);\ndrivers/mmc/core/sdio.c-816-\tif (err) {\ndrivers/mmc/core/sdio.c:817:\t\tmmc_sdio_pre_init(host, ocr_card, card);\ndrivers/mmc/core/sdio.c-818-\t\tif (ocr \u0026 R4_18V_PRESENT) {\n--\ndrivers/mmc/core/sdio.c-828-\t */\ndrivers/mmc/core/sdio.c:829:\terr = sdio_read_common_cis(card);\ndrivers/mmc/core/sdio.c-830-\tif (err)\n--\ndrivers/mmc/core/sdio.c-843-\ndrivers/mmc/core/sdio.c:844:\tmmc_fixup_device(card, sdio_fixup_methods);\ndrivers/mmc/core/sdio.c-845-\n--\ndrivers/mmc/core/sdio.c-861-\t */\ndrivers/mmc/core/sdio.c:862:\terr = sdio_disable_cd(card);\ndrivers/mmc/core/sdio.c-863-\tif (err)\n--\ndrivers/mmc/core/sdio.c-868-\tif ((ocr \u0026 R4_18V_PRESENT) \u0026\u0026 card-\u003esw_caps.sd3_bus_mode) {\ndrivers/mmc/core/sdio.c:869:\t\terr = mmc_sdio_init_uhs_card(card);\ndrivers/mmc/core/sdio.c-870-\t\tif (err)\n--\ndrivers/mmc/core/sdio.c-875-\t\t */\ndrivers/mmc/core/sdio.c:876:\t\terr = sdio_enable_hs(card);\ndrivers/mmc/core/sdio.c-877-\t\tif (err \u003e 0)\n--\ndrivers/mmc/core/sdio.c-884-\t\t */\ndrivers/mmc/core/sdio.c:885:\t\tmmc_set_clock(host, mmc_sdio_get_max_clock(card));\ndrivers/mmc/core/sdio.c-886-\n--\ndrivers/mmc/core/sdio.c-889-\t\t */\ndrivers/mmc/core/sdio.c:890:\t\terr = sdio_enable_4bit_bus(card);\ndrivers/mmc/core/sdio.c-891-\t\tif (err)\n--\ndrivers/mmc/core/sdio.c-913-\ndrivers/mmc/core/sdio.c:914:static int mmc_sdio_reinit_card(struct mmc_host *host)\ndrivers/mmc/core/sdio.c-915-{\n--\ndrivers/mmc/core/sdio.c-917-\ndrivers/mmc/core/sdio.c:918:\tret = mmc_sdio_pre_init(host, host-\u003ecard-\u003eocr, NULL);\ndrivers/mmc/core/sdio.c-919-\tif (ret)\n--\ndrivers/mmc/core/sdio.c-921-\ndrivers/mmc/core/sdio.c:922:\treturn mmc_sdio_init_card(host, host-\u003ecard-\u003eocr, host-\u003ecard);\ndrivers/mmc/core/sdio.c-923-}\n--\ndrivers/mmc/core/sdio.c-927- */\ndrivers/mmc/core/sdio.c:928:static void mmc_sdio_remove(struct mmc_host *host)\ndrivers/mmc/core/sdio.c-929-{\n--\ndrivers/mmc/core/sdio.c-931-\ndrivers/mmc/core/sdio.c:932:\tfor (i = 0;i \u003c host-\u003ecard-\u003esdio_funcs;i++) {\ndrivers/mmc/core/sdio.c:933:\t\tif (host-\u003ecard-\u003esdio_func[i]) {\ndrivers/mmc/core/sdio.c:934:\t\t\tsdio_remove_func(host-\u003ecard-\u003esdio_func[i]);\ndrivers/mmc/core/sdio.c:935:\t\t\thost-\u003ecard-\u003esdio_func[i] = NULL;\ndrivers/mmc/core/sdio.c-936-\t\t}\n--\ndrivers/mmc/core/sdio.c-945- */\ndrivers/mmc/core/sdio.c:946:static int mmc_sdio_alive(struct mmc_host *host)\ndrivers/mmc/core/sdio.c-947-{\n--\ndrivers/mmc/core/sdio.c-957- */\ndrivers/mmc/core/sdio.c:958:static void mmc_sdio_detect(struct mmc_host *host)\ndrivers/mmc/core/sdio.c-959-{\n--\ndrivers/mmc/core/sdio.c-993-\tif (err) {\ndrivers/mmc/core/sdio.c:994:\t\tmmc_sdio_remove(host);\ndrivers/mmc/core/sdio.c-995-\n--\ndrivers/mmc/core/sdio.c-1007- */\ndrivers/mmc/core/sdio.c:1008:static int mmc_sdio_pre_suspend(struct mmc_host *host)\ndrivers/mmc/core/sdio.c-1009-{\n--\ndrivers/mmc/core/sdio.c-1011-\ndrivers/mmc/core/sdio.c:1012:\tfor (i = 0; i \u003c host-\u003ecard-\u003esdio_funcs; i++) {\ndrivers/mmc/core/sdio.c:1013:\t\tstruct sdio_func *func = host-\u003ecard-\u003esdio_func[i];\ndrivers/mmc/core/sdio.c:1014:\t\tif (func \u0026\u0026 sdio_func_present(func) \u0026\u0026 func-\u003edev.driver) {\ndrivers/mmc/core/sdio.c-1015-\t\t\tconst struct dev_pm_ops *pmops = func-\u003edev.driver-\u003epm;\n--\ndrivers/mmc/core/sdio.c-1032-\t/* Remove the SDIO card and let it be re-detected later on. */\ndrivers/mmc/core/sdio.c:1033:\tmmc_sdio_remove(host);\ndrivers/mmc/core/sdio.c-1034-\tmmc_claim_host(host);\n--\ndrivers/mmc/core/sdio.c-1045- */\ndrivers/mmc/core/sdio.c:1046:static int mmc_sdio_suspend(struct mmc_host *host)\ndrivers/mmc/core/sdio.c-1047-{\ndrivers/mmc/core/sdio.c:1048:\tWARN_ON(host-\u003esdio_irqs \u0026\u0026 !mmc_card_keep_power(host));\ndrivers/mmc/core/sdio.c-1049-\n--\ndrivers/mmc/core/sdio.c-1051-\tmmc_card_set_suspended(host-\u003ecard);\ndrivers/mmc/core/sdio.c:1052:\tcancel_work_sync(\u0026host-\u003esdio_irq_work);\ndrivers/mmc/core/sdio.c-1053-\n--\ndrivers/mmc/core/sdio.c-1055-\ndrivers/mmc/core/sdio.c:1056:\tif (mmc_card_keep_power(host) \u0026\u0026 mmc_card_wake_sdio_irq(host))\ndrivers/mmc/core/sdio.c:1057:\t\tsdio_disable_4bit_bus(host-\u003ecard);\ndrivers/mmc/core/sdio.c-1058-\n--\ndrivers/mmc/core/sdio.c-1070-\ndrivers/mmc/core/sdio.c:1071:static int mmc_sdio_resume(struct mmc_host *host)\ndrivers/mmc/core/sdio.c-1072-{\n--\ndrivers/mmc/core/sdio.c-1095-\t\t}\ndrivers/mmc/core/sdio.c:1096:\t\terr = mmc_sdio_reinit_card(host);\ndrivers/mmc/core/sdio.c:1097:\t} else if (mmc_card_wake_sdio_irq(host)) {\ndrivers/mmc/core/sdio.c-1098-\t\t/*\n--\ndrivers/mmc/core/sdio.c-1103-\t\tmmc_retune_hold_now(host);\ndrivers/mmc/core/sdio.c:1104:\t\terr = sdio_enable_4bit_bus(host-\u003ecard);\ndrivers/mmc/core/sdio.c-1105-\t\tmmc_retune_release(host);\n--\ndrivers/mmc/core/sdio.c-1113-\ndrivers/mmc/core/sdio.c:1114:\tif (host-\u003esdio_irqs) {\ndrivers/mmc/core/sdio.c-1115-\t\tif (!(host-\u003ecaps2 \u0026 MMC_CAP2_SDIO_IRQ_NOTHREAD))\ndrivers/mmc/core/sdio.c:1116:\t\t\twake_up_process(host-\u003esdio_irq_thread);\ndrivers/mmc/core/sdio.c-1117-\t\telse if (host-\u003ecaps \u0026 MMC_CAP_SDIO_IRQ)\ndrivers/mmc/core/sdio.c:1118:\t\t\tschedule_work(\u0026host-\u003esdio_irq_work);\ndrivers/mmc/core/sdio.c-1119-\t}\n--\ndrivers/mmc/core/sdio.c-1127-\ndrivers/mmc/core/sdio.c:1128:static int mmc_sdio_runtime_suspend(struct mmc_host *host)\ndrivers/mmc/core/sdio.c-1129-{\n--\ndrivers/mmc/core/sdio.c-1137-\ndrivers/mmc/core/sdio.c:1138:static int mmc_sdio_runtime_resume(struct mmc_host *host)\ndrivers/mmc/core/sdio.c-1139-{\n--\ndrivers/mmc/core/sdio.c-1144-\tmmc_power_up(host, host-\u003ecard-\u003eocr);\ndrivers/mmc/core/sdio.c:1145:\tret = mmc_sdio_reinit_card(host);\ndrivers/mmc/core/sdio.c-1146-\tmmc_release_host(host);\n--\ndrivers/mmc/core/sdio.c-1156- */\ndrivers/mmc/core/sdio.c:1157:static int mmc_sdio_hw_reset(struct mmc_host *host)\ndrivers/mmc/core/sdio.c-1158-{\n--\ndrivers/mmc/core/sdio.c-1165-\t */\ndrivers/mmc/core/sdio.c:1166:\tif (atomic_read(\u0026card-\u003esdio_funcs_probed) \u003e 1) {\ndrivers/mmc/core/sdio.c-1167-\t\tif (mmc_card_removed(card))\n--\ndrivers/mmc/core/sdio.c-1179-\tmmc_power_cycle(host, card-\u003eocr);\ndrivers/mmc/core/sdio.c:1180:\treturn mmc_sdio_reinit_card(host);\ndrivers/mmc/core/sdio.c-1181-}\ndrivers/mmc/core/sdio.c-1182-\ndrivers/mmc/core/sdio.c:1183:static int mmc_sdio_sw_reset(struct mmc_host *host)\ndrivers/mmc/core/sdio.c-1184-{\ndrivers/mmc/core/sdio.c-1185-\tmmc_set_clock(host, host-\u003ef_init);\ndrivers/mmc/core/sdio.c:1186:\tsdio_reset(host);\ndrivers/mmc/core/sdio.c-1187-\tmmc_go_idle(host);\n--\n\n"
} |
| 9/2 | 2026/08/25 19:12 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 28465 output: 29 thoughts: 495 Thoughts: **My SDIO Emulation Dilemma** Okay, so I'm looking at `CONFIG_MMC_TEST` and `CONFIG_SDIO_UART`, and immediately I'm thinking, "Can I actually *test* this SDIO stuff virtually?". My mind jumps to QEMU because, well, that's the go-to for virtualization. I remember `sdhci-pci.c` in `drivers/mmc/host/`, and how QEMU emulates that PCI controller. Great, QEMU does SD card emulation, so that's a positive. But the big question is, does QEMU do *SDIO* card emulation? And then the crushing realization hits: No. QEMU's SD card emulation doesn't support the SDIO specifics, the `CMD52/CMD53` stuff. This means standard QEMU can't handle emulating an SDIO device. Hmm, what about `mac80211_hwsim`? No, that emulates a mac80211 device, which isn't an SDIO card. What about a `vhci`-like approach? USB has `vhci`, but there's nothing similar for SDIO. Damn. So, how can I trigger `rtw_sdio_probe`? It's registered with `sdio_register_driver(&rtw_sdio_driver)`. The probe function gets called when the SDIO bus sees a matching vendor/device ID. The issue is that I can't inject those arbitrary SDIO devices like you would with USB's `dummy_hcd` and `gadget`. It looks like there's no virtual SDIO host controller to allow that, and QEMU doesn't emulate SDIO. So the code is basically unreachable in any kind of standard virtualized environment. Hold on, let me quickly double check if syzkaller has some SDIO fuzzing support. I can poke around for some `syz_sdio` pseudo-syscalls or similar. But the prompt says not to search for that directly since it's a syzkaller pseudo-syscall and not in the actual kernel code. Okay, fine, I’ll check if there's *any* kind of SDIO injection framework in the kernel. Maybe there is something like `sdio_dummy` or `sdio_vhci`. I need to search `drivers/virt/`, `drivers/misc/`, and `drivers/mmc/` for clues. |
| 10/2 | 2026/08/25 19:12 | tool | grepper |
0mError:no matches Args: {
"Expression": "sdio.*dummy",
"PathPrefix": "drivers/mmc/"
}Results: {
"error": "no matches"
} |
| 11/2 | 2026/08/25 19:12 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 29541 output: 27 thoughts: 17 Thoughts: Here's my thought process, as if I were the one thinking it: **Digging into the MMC Driver Landscape** Okay, so I need to find something related to `vhci`, and I have a feeling it's hanging out somewhere in the MMC driver code. My instinct tells me to start looking specifically within the `drivers/mmc/` directory. That's the most logical place to begin. Time to fire up my search tools and get cracking. Let's see what we turn up. |
| 12/2 | 2026/08/25 19:12 | tool | grepper |
0mError:no matches Args: {
"Expression": "vhci",
"PathPrefix": "drivers/mmc/"
}Results: {
"error": "no matches"
} |
| 13/2 | 2026/08/25 19:12 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 29707 output: 27 thoughts: 17 Thoughts: Here's my thought process, as it stands: **Navigating the Digital Landscape** Okay, so I need to find something, and I've got a fairly good idea where to start. My initial instinct is to use a search function. I'm thinking I want to explore the `drivers/mmc/` directory – that's where MMC (MultiMediaCard) drivers live, generally speaking, and I suspect the term `fuzz` is potentially relevant there. It could relate to a vulnerability, a testing methodology, or something else entirely. By searching for `fuzz` within that particular file tree, I'm increasing the likelihood of finding something contextually relevant and decreasing the amount of noise I have to filter through. This narrows the scope of the problem considerably, focusing my efforts on a specific area of interest. It's a pragmatic and efficient first step, and based on the results, I can branch off and widen or narrow my search from there. |
| 14/2 | 2026/08/25 19:12 | tool | grepper |
0mError:no matches Args: {
"Expression": "fuzz",
"PathPrefix": "drivers/mmc/"
}Results: {
"error": "no matches"
} |
| 15/2 | 2026/08/25 19:12 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 29967 output: 26 thoughts: 16 Thoughts: Here's my thought process, as if I were considering this search: **Diving into the MMC Driver Code** Okay, so I need to find something related to "inject" within the MMC driver code. My instinct is to start broad. I'll initiate a search directly within the `drivers/mmc/` directory. "Inject" is a potentially ambiguous term, depending on context, and I need to see what pops up. It could refer to injecting errors for testing, injecting commands, or something else entirely related to data handling. The search should give me a good initial overview of any relevant code sections. I expect to find things related to error handling, command sending, or perhaps even power cycling, depending on what the code refers to as "inject". Time to see what the search yields! |
| 16/2 | 2026/08/25 19:12 | tool | grepper |
0mArgs:{
"Expression": "inject",
"PathPrefix": "drivers/mmc/"
}Results: {
"Output": "drivers/mmc/core/core.c-22-#include \u003clinux/suspend.h\u003e\ndrivers/mmc/core/core.c:23:#include \u003clinux/fault-inject.h\u003e\ndrivers/mmc/core/core.c-24-#include \u003clinux/random.h\u003e\n--\ndrivers/mmc/core/core.c=63=static int mmc_schedule_delayed_work(struct delayed_work *work,\n--\ndrivers/mmc/core/core.c-78- * Internal function. Inject random data errors.\ndrivers/mmc/core/core.c:79: * If mmc_data is NULL no errors are injected.\ndrivers/mmc/core/core.c-80- */\n--\ndrivers/mmc/core/debugfs.c-13-#include \u003clinux/stat.h\u003e\ndrivers/mmc/core/debugfs.c:14:#include \u003clinux/fault-inject.h\u003e\ndrivers/mmc/core/debugfs.c-15-#include \u003clinux/time.h\u003e\n--\ndrivers/mmc/core/debugfs.c=31=module_param(fail_request, charp, 0);\ndrivers/mmc/core/debugfs.c:32:MODULE_PARM_DESC(fail_request, \"default fault injection attributes\");\ndrivers/mmc/core/debugfs.c-33-\n--\ndrivers/mmc/host/dw_mmc.c=1687=static enum hrtimer_restart dw_mci_fault_timer(struct hrtimer *t)\n--\ndrivers/mmc/host/dw_mmc.c-1694-\t/*\ndrivers/mmc/host/dw_mmc.c:1695:\t * Only inject an error if we haven't already got an error or data over\ndrivers/mmc/host/dw_mmc.c-1696-\t * interrupt.\n--\ndrivers/mmc/host/dw_mmc.c=1709=static void dw_mci_start_fault_timer(struct dw_mci *host)\n--\ndrivers/mmc/host/dw_mmc.c-1719-\t/*\ndrivers/mmc/host/dw_mmc.c:1720:\t * Try to inject the error at random points during the data transfer.\ndrivers/mmc/host/dw_mmc.c-1721-\t */\n--\ndrivers/mmc/host/dw_mmc.h-16-#include \u003clinux/reset.h\u003e\ndrivers/mmc/host/dw_mmc.h:17:#include \u003clinux/fault-inject.h\u003e\ndrivers/mmc/host/dw_mmc.h-18-#include \u003clinux/hrtimer.h\u003e\n--\ndrivers/mmc/host/litex_mmc.c=341=static void litex_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)\n--\ndrivers/mmc/host/litex_mmc.c-376-\t\t * LiteSDCard only supports 4-bit bus width; therefore, we MUST\ndrivers/mmc/host/litex_mmc.c:377:\t\t * inject a SET_BUS_WIDTH (acmd6) before the very first data\ndrivers/mmc/host/litex_mmc.c-378-\t\t * transfer, earlier than when the mmc subsystem would normally\n--\ndrivers/mmc/host/litex_mmc.c=450=static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)\n--\ndrivers/mmc/host/litex_mmc.c-467-\t * the mmc core sends its own acmd6 bus-width change notification,\ndrivers/mmc/host/litex_mmc.c:468:\t * which is redundant since we snoop on the command flow and inject\ndrivers/mmc/host/litex_mmc.c-469-\t * an early acmd6 before the first data transfer command is sent!\n--\ndrivers/mmc/host/litex_mmc.c=522=static int litex_mmc_probe(struct platform_device *pdev)\n--\ndrivers/mmc/host/litex_mmc.c-550-\t/*\ndrivers/mmc/host/litex_mmc.c:551:\t * LiteSDCard only supports 4-bit bus width; therefore, we MUST inject\ndrivers/mmc/host/litex_mmc.c-552-\t * a SET_BUS_WIDTH (acmd6) before the very first data transfer, earlier\n"
} |
| 17/2 | 2026/08/25 19:12 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 31328 output: 47 thoughts: 414 Thoughts: **My Analysis of the `rtw88` Driver and Syzkaller Exploitation**
Okay, so there's no native SDIO device injection framework directly available in the kernel. That's a hurdle. I'm wondering if there's an alternative probing path for the SDIO driver. Considering this specific driver is an SDIO driver, I need a way to present an SDIO device.
Looking at the code, specifically the `sdio_device_id` table:
```c
static const struct sdio_device_id rtw_sdio_id_table[] = {
{ SDIO_DEVICE(0x024c, 0xb723), .driver_data = RTW_CHIP_TYPE_8723B },
...
};
```
I realize I'm going to need either a real SDIO device or some sort of virtual SDIO host controller that can emulate those device IDs. That's the challenge.
Could Syzkaller leverage `mac80211_hwsim` to reach the `rtw88` code? No, after a quick check, I see that `mac80211_hwsim` is a completely separate driver that registers its own `mac80211` wiphy. There's no interaction with `rtw88` there. That avenue is closed.
Alright, moving on, can I use `usb_gadget` to emulate an RTL8723BS? It looks like the patch modifies `rtw88/sdio.c` and `rtw88/rx.c`. I need to understand how the code in `rtw88/rx.c` can be reached. There is this code:
```c
if (pkt_stat->pkt_len == 0 &&
(rtwdev->chip->id == RTW_CHIP_TYPE_8703B || rtw_is_8723bs(rtwdev))) {
```
I'm thinking this could be a potential point of entry, reachable if `rtwdev->chip->id == RTW_CHIP_TYPE_8703B`. The critical question now is whether the `8703B` chip is supported via USB or PCI, since I need to use either `usb_gadget` or something similar.
I'll check `drivers/net/wireless/realtek/rtw88/usb.c` and `pci.c` for `8703B` support. Hopefully, this chip type is accessible via a bus that is emulatable.
|
| 18/2 | 2026/08/25 19:12 | tool | grepper |
0mArgs:{
"Expression": "RTW_CHIP_TYPE_8703B",
"PathPrefix": "drivers/net/wireless/realtek/rtw88/"
}Results: {
"Output": "drivers/net/wireless/realtek/rtw88/mac.c=948=static int __rtw_download_firmware_legacy(struct rtw_dev *rtwdev,\n--\ndrivers/net/wireless/realtek/rtw88/mac.c-953-\t/* reset firmware if still present */\ndrivers/net/wireless/realtek/rtw88/mac.c:954:\tif (rtwdev-\u003echip-\u003eid == RTW_CHIP_TYPE_8703B \u0026\u0026\ndrivers/net/wireless/realtek/rtw88/mac.c-955-\t rtw_read8_mask(rtwdev, REG_MCUFW_CTRL, BIT_RAM_DL_SEL)) {\n--\ndrivers/net/wireless/realtek/rtw88/main.h=191=enum rtw_chip_type {\n--\ndrivers/net/wireless/realtek/rtw88/main.h-195-\tRTW_CHIP_TYPE_8821C,\ndrivers/net/wireless/realtek/rtw88/main.h:196:\tRTW_CHIP_TYPE_8703B,\ndrivers/net/wireless/realtek/rtw88/main.h-197-\tRTW_CHIP_TYPE_8723B,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c=1886=const struct rtw_chip_info rtw8703b_hw_spec = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1887-\t.ops = \u0026rtw8703b_ops,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1888:\t.id = RTW_CHIP_TYPE_8703B,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1889-\n--\ndrivers/net/wireless/realtek/rtw88/rx.c=197=static void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,\n--\ndrivers/net/wireless/realtek/rtw88/rx.c-260-\tif (pkt_stat-\u003epkt_len == 0 \u0026\u0026\ndrivers/net/wireless/realtek/rtw88/rx.c:261:\t (rtwdev-\u003echip-\u003eid == RTW_CHIP_TYPE_8703B || rtw_is_8723bs(rtwdev))) {\ndrivers/net/wireless/realtek/rtw88/rx.c-262-\t\trx_status-\u003eflag |= RX_FLAG_NO_PSDU;\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=974=static void rtw_sdio_enable_rx_aggregation(struct rtw_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-979-\tcase RTW_CHIP_TYPE_8723B:\ndrivers/net/wireless/realtek/rtw88/sdio.c:980:\tcase RTW_CHIP_TYPE_8703B:\ndrivers/net/wireless/realtek/rtw88/sdio.c-981-\tcase RTW_CHIP_TYPE_8821A:\n--\ndrivers/net/wireless/realtek/rtw88/usb.c=929=static void rtw_usb_dynamic_rx_agg(struct rtw_dev *rtwdev, bool enable)\n--\ndrivers/net/wireless/realtek/rtw88/usb.c-944-\t\tbreak;\ndrivers/net/wireless/realtek/rtw88/usb.c:945:\tcase RTW_CHIP_TYPE_8703B:\ndrivers/net/wireless/realtek/rtw88/usb.c-946-\t\t/* Likely not found in USB devices. */\n"
} |
| 19/2 | 2026/08/25 19:12 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 33396 output: 47 thoughts: 65 Thoughts: **Investigating the 87xx Series** Okay, so `8703B` isn't showing up in the standard USB device listings – that makes sense, I should have checked `rtw88/sdio.c` first. But, hold on a second... what about the `8723B` variant? Now *that* one rings a bell. Didn't some implementations use USB for that? Let's quickly verify by checking `rtw8723bu` and confirm if it's got the USB hooks. Time to dive into that specific driver and see if we can find the USB support I'm expecting. |
| 20/2 | 2026/08/25 19:12 | tool | grepper |
0mArgs:{
"Expression": "RTW_CHIP_TYPE_8723B",
"PathPrefix": "drivers/net/wireless/realtek/rtw88/"
}Results: {
"Output": "drivers/net/wireless/realtek/rtw88/main.h=191=enum rtw_chip_type {\n--\ndrivers/net/wireless/realtek/rtw88/main.h-196-\tRTW_CHIP_TYPE_8703B,\ndrivers/net/wireless/realtek/rtw88/main.h:197:\tRTW_CHIP_TYPE_8723B,\ndrivers/net/wireless/realtek/rtw88/main.h-198-\tRTW_CHIP_TYPE_8821A,\n--\ndrivers/net/wireless/realtek/rtw88/main.h=2198=static inline bool rtw_is_8723bs(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/main.h-2199-{\ndrivers/net/wireless/realtek/rtw88/main.h:2200:\treturn rtwdev-\u003echip-\u003eid == RTW_CHIP_TYPE_8723B \u0026\u0026\ndrivers/net/wireless/realtek/rtw88/main.h-2201-\t rtwdev-\u003ehci.type == RTW_HCI_TYPE_SDIO;\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=974=static void rtw_sdio_enable_rx_aggregation(struct rtw_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-978-\tswitch (rtwdev-\u003echip-\u003eid) {\ndrivers/net/wireless/realtek/rtw88/sdio.c:979:\tcase RTW_CHIP_TYPE_8723B:\ndrivers/net/wireless/realtek/rtw88/sdio.c-980-\tcase RTW_CHIP_TYPE_8703B:\n"
} |
| 21/2 | 2026/08/25 19:12 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 34143 output: 39 thoughts: 80 Thoughts: Here's my thought process, as it went down: **Investigating a Potentially Narrow Definition** Okay, so I see `8723B` is only defined within `main.h`, and, apparently, is solely utilized by `rtw_is_8723bs()`. That seems a bit... specific. It's making me wonder if this is a narrowly scoped identifier. Are we only dealing with a particular variant of something? My intuition is kicking in; what about other related products? I need to know. I'm thinking, is there anything similar, like, perhaps `rtw8723bu` or `rtw8723be` in the codebase? It's time to check the Makefile for this particular realtek wireless driver. That's the place that defines what's being built, and where the related code would likely be. I'll start there. |
| 22/2 | 2026/08/25 19:13 | tool | grepper |
0mArgs:{
"Expression": "8723",
"PathPrefix": "drivers/net/wireless/realtek/rtw88/Makefile"
}Results: {
"Output": "drivers/net/wireless/realtek/rtw88/Makefile=47=rtw88_8822cu-objs\t\t:= rtw8822cu.o\ndrivers/net/wireless/realtek/rtw88/Makefile-48-\ndrivers/net/wireless/realtek/rtw88/Makefile:49:obj-$(CONFIG_RTW88_8723X)\t+= rtw88_8723x.o\ndrivers/net/wireless/realtek/rtw88/Makefile:50:rtw88_8723x-objs\t\t:= rtw8723x.o\ndrivers/net/wireless/realtek/rtw88/Makefile-51-\n--\ndrivers/net/wireless/realtek/rtw88/Makefile=53=rtw88_8703b-objs\t\t:= rtw8703b.o rtw8703b_tables.o\ndrivers/net/wireless/realtek/rtw88/Makefile-54-\ndrivers/net/wireless/realtek/rtw88/Makefile:55:obj-$(CONFIG_RTW88_8723CS)\t+= rtw88_8723cs.o\ndrivers/net/wireless/realtek/rtw88/Makefile:56:rtw88_8723cs-objs\t\t:= rtw8723cs.o\ndrivers/net/wireless/realtek/rtw88/Makefile-57-\ndrivers/net/wireless/realtek/rtw88/Makefile:58:obj-$(CONFIG_RTW88_8723D)\t+= rtw88_8723d.o\ndrivers/net/wireless/realtek/rtw88/Makefile:59:rtw88_8723d-objs\t\t:= rtw8723d.o rtw8723d_table.o\ndrivers/net/wireless/realtek/rtw88/Makefile-60-\ndrivers/net/wireless/realtek/rtw88/Makefile:61:obj-$(CONFIG_RTW88_8723DE)\t+= rtw88_8723de.o\ndrivers/net/wireless/realtek/rtw88/Makefile:62:rtw88_8723de-objs\t\t:= rtw8723de.o\ndrivers/net/wireless/realtek/rtw88/Makefile-63-\ndrivers/net/wireless/realtek/rtw88/Makefile:64:obj-$(CONFIG_RTW88_8723DS)\t+= rtw88_8723ds.o\ndrivers/net/wireless/realtek/rtw88/Makefile:65:rtw88_8723ds-objs\t\t:= rtw8723ds.o\ndrivers/net/wireless/realtek/rtw88/Makefile-66-\ndrivers/net/wireless/realtek/rtw88/Makefile:67:obj-$(CONFIG_RTW88_8723DU)\t+= rtw88_8723du.o\ndrivers/net/wireless/realtek/rtw88/Makefile:68:rtw88_8723du-objs\t\t:= rtw8723du.o\ndrivers/net/wireless/realtek/rtw88/Makefile-69-\n"
} |
| 23/2 | 2026/08/25 19:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 35298 output: 39 thoughts: 86 Thoughts: **Investigating the Missing Driver in the Makefile** Okay, so I'm looking at this Makefile and I'm a bit puzzled. I'm not seeing any explicit mention of `rtw8723bs` in the build process. That strikes me as odd, given the nature of the project and what I know about the typical structure. Then again, I see this patch, which specifically adds the definitions for `RTW_CHIP_TYPE_8723B` and `rtw_is_8723bs()`. That's a strong indicator that this specific 8723bs hardware is supported or being integrated. Alright, so the definitions are there but where is the actual driver code itself? I'm missing something, so let me just take a quick inventory and confirm that there's even a `rtw8723bs.c` driver file to begin with. Time to check the directory structure and make sure I'm not missing something obvious. |
| 24/2 | 2026/08/25 19:13 | tool | grepper |
0mArgs:{
"Expression": "8723bs",
"PathPrefix": "drivers/net/wireless/realtek/rtw88/"
}Results: {
"Output": "drivers/net/wireless/realtek/rtw88/main.h=2193=static inline bool rtw_chip_has_tx_stbc(struct rtw_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw88/main.h-2197-\ndrivers/net/wireless/realtek/rtw88/main.h:2198:static inline bool rtw_is_8723bs(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/main.h-2199-{\n--\ndrivers/net/wireless/realtek/rtw88/rx.c=197=static void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,\n--\ndrivers/net/wireless/realtek/rtw88/rx.c-256-\t/*\ndrivers/net/wireless/realtek/rtw88/rx.c:257:\t * Rtl8723cs and rtl8723bs drivers check for size \u003c 14 or size \u003e 8192\ndrivers/net/wireless/realtek/rtw88/rx.c-258-\t * and simply drop the packet.\n--\ndrivers/net/wireless/realtek/rtw88/rx.c-260-\tif (pkt_stat-\u003epkt_len == 0 \u0026\u0026\ndrivers/net/wireless/realtek/rtw88/rx.c:261:\t (rtwdev-\u003echip-\u003eid == RTW_CHIP_TYPE_8703B || rtw_is_8723bs(rtwdev))) {\ndrivers/net/wireless/realtek/rtw88/rx.c-262-\t\trx_status-\u003eflag |= RX_FLAG_NO_PSDU;\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=518=static int rtw_sdio_read_port(struct rtw_dev *rtwdev, u8 *buf, size_t count)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-568- */\ndrivers/net/wireless/realtek/rtw88/sdio.c:569:static void rtw_sdio_8723bs_store_free_txpg(struct rtw_dev *rtwdev,\ndrivers/net/wireless/realtek/rtw88/sdio.c-570-\t\t\t\t\t u32 free_txpg)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-588- */\ndrivers/net/wireless/realtek/rtw88/sdio.c:589:static bool rtw_sdio_8723bs_sync_free_txpg(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/sdio.c-590-{\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-595-\ndrivers/net/wireless/realtek/rtw88/sdio.c:596:\trtw_sdio_8723bs_store_free_txpg(rtwdev, free_txpg);\ndrivers/net/wireless/realtek/rtw88/sdio.c-597-\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-606- */\ndrivers/net/wireless/realtek/rtw88/sdio.c:607:static int rtw_sdio_8723bs_pubq_num(struct rtw_dev *rtwdev, u16 *pubq_num)\ndrivers/net/wireless/realtek/rtw88/sdio.c-608-{\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-626-\ndrivers/net/wireless/realtek/rtw88/sdio.c:627:static int rtw_sdio_8723bs_init_free_txpg(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/sdio.c-628-{\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-634-\t/* Seed from the page table when the chip has nothing to report yet. */\ndrivers/net/wireless/realtek/rtw88/sdio.c:635:\tif (!rtw_sdio_8723bs_sync_free_txpg(rtwdev)) {\ndrivers/net/wireless/realtek/rtw88/sdio.c:636:\t\tret = rtw_sdio_8723bs_pubq_num(rtwdev, \u0026pubq_num);\ndrivers/net/wireless/realtek/rtw88/sdio.c-637-\t\tif (ret)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-654- * Sum of the queue's dedicated counter and the public pool, clamped at zero:\ndrivers/net/wireless/realtek/rtw88/sdio.c:655: * a lost update between the check below and rtw_sdio_8723bs_consume_txpg()\ndrivers/net/wireless/realtek/rtw88/sdio.c-656- * can briefly drive a counter negative, and letting that wrap would hide the\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-658- */\ndrivers/net/wireless/realtek/rtw88/sdio.c:659:static unsigned int rtw_sdio_8723bs_pages_free(struct rtw_dev *rtwdev,\ndrivers/net/wireless/realtek/rtw88/sdio.c-660-\t\t\t\t\t atomic_t *dedicated)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-676- */\ndrivers/net/wireless/realtek/rtw88/sdio.c:677:static atomic_t *rtw_sdio_8723bs_free_txpg(struct rtw_dev *rtwdev, u8 queue)\ndrivers/net/wireless/realtek/rtw88/sdio.c-678-{\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=698=static int rtw_sdio_check_free_txpg(struct rtw_dev *rtwdev, u8 queue,\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-702-\ndrivers/net/wireless/realtek/rtw88/sdio.c:703:\tif (rtw_is_8723bs(rtwdev)) {\ndrivers/net/wireless/realtek/rtw88/sdio.c-704-\t\tatomic_t *dedicated;\ndrivers/net/wireless/realtek/rtw88/sdio.c-705-\ndrivers/net/wireless/realtek/rtw88/sdio.c:706:\t\tdedicated = rtw_sdio_8723bs_free_txpg(rtwdev, queue);\ndrivers/net/wireless/realtek/rtw88/sdio.c-707-\t\tif (!dedicated) {\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-711-\ndrivers/net/wireless/realtek/rtw88/sdio.c:712:\t\tpages_free = rtw_sdio_8723bs_pages_free(rtwdev, dedicated);\ndrivers/net/wireless/realtek/rtw88/sdio.c-713-\t\tpages_needed = DIV_ROUND_UP(count, rtwdev-\u003echip-\u003epage_size);\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-716-\ndrivers/net/wireless/realtek/rtw88/sdio.c:717:\t\trtw_sdio_8723bs_sync_free_txpg(rtwdev);\ndrivers/net/wireless/realtek/rtw88/sdio.c:718:\t\tpages_free = rtw_sdio_8723bs_pages_free(rtwdev, dedicated);\ndrivers/net/wireless/realtek/rtw88/sdio.c-719-\t} else if (rtw_chip_wcpu_8051(rtwdev)) {\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-797-\ndrivers/net/wireless/realtek/rtw88/sdio.c:798:static int rtw_sdio_8723bs_wait_tx_oqt(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/sdio.c-799-{\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-821-\ndrivers/net/wireless/realtek/rtw88/sdio.c:822:static void rtw_sdio_8723bs_consume_txpg(struct rtw_dev *rtwdev, u8 queue,\ndrivers/net/wireless/realtek/rtw88/sdio.c-823-\t\t\t\t\t unsigned int pages)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-831-\ndrivers/net/wireless/realtek/rtw88/sdio.c:832:\tdedicated = rtw_sdio_8723bs_free_txpg(rtwdev, queue);\ndrivers/net/wireless/realtek/rtw88/sdio.c-833-\tif (!dedicated)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=845=static int rtw_sdio_write_to_port(struct rtw_dev *rtwdev, struct sk_buff *skb,\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-875- */\ndrivers/net/wireless/realtek/rtw88/sdio.c:876:static int rtw_sdio_8723bs_write_port(struct rtw_dev *rtwdev,\ndrivers/net/wireless/realtek/rtw88/sdio.c-877-\t\t\t\t struct sk_buff *skb,\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-890-\ndrivers/net/wireless/realtek/rtw88/sdio.c:891:\tret = rtw_sdio_8723bs_wait_tx_oqt(rtwdev);\ndrivers/net/wireless/realtek/rtw88/sdio.c-892-\tif (ret)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-906-\tpages = DIV_ROUND_UP(txsize, rtwdev-\u003echip-\u003epage_size);\ndrivers/net/wireless/realtek/rtw88/sdio.c:907:\trtw_sdio_8723bs_consume_txpg(rtwdev, queue, pages);\ndrivers/net/wireless/realtek/rtw88/sdio.c-908-\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=912=static int rtw_sdio_write_port(struct rtw_dev *rtwdev, struct sk_buff *skb,\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-924-\ndrivers/net/wireless/realtek/rtw88/sdio.c:925:\tif (!rtw_is_8723bs(rtwdev)) {\ndrivers/net/wireless/realtek/rtw88/sdio.c-926-\t\ttxsize = sdio_align_size(rtwsdio-\u003esdio_func, skb-\u003elen);\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-958-\ndrivers/net/wireless/realtek/rtw88/sdio.c:959:\treturn rtw_sdio_8723bs_write_port(rtwdev, skb, queue, txaddr, txsize,\ndrivers/net/wireless/realtek/rtw88/sdio.c-960-\t\t\t\t\t write_size);\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=963=static void rtw_sdio_init(struct rtw_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-966-\ndrivers/net/wireless/realtek/rtw88/sdio.c:967:\tif (rtw_is_8723bs(rtwdev))\ndrivers/net/wireless/realtek/rtw88/sdio.c-968-\t\trtwsdio-\u003eirq_mask = REG_SDIO_HIMR_RX_REQUEST;\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=974=static void rtw_sdio_enable_rx_aggregation(struct rtw_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1006-\trtw_write8_set(rtwdev, REG_RXDMA_MODE, BIT_DMA_MODE);\ndrivers/net/wireless/realtek/rtw88/sdio.c:1007:\tif (rtw_is_8723bs(rtwdev))\ndrivers/net/wireless/realtek/rtw88/sdio.c-1008-\t\trtw_write8_mask(rtwdev, REG_RXDMA_MODE, BIT_DMA_BURST_CNT, 0x3);\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=1040=static int rtw_sdio_setup(struct rtw_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1051- */\ndrivers/net/wireless/realtek/rtw88/sdio.c:1052:static int rtw_sdio_8723bs_check_rqpn(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/sdio.c-1053-{\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1064-\ndrivers/net/wireless/realtek/rtw88/sdio.c:1065:\tret = rtw_sdio_8723bs_pubq_num(rtwdev, \u0026pubq_num);\ndrivers/net/wireless/realtek/rtw88/sdio.c-1066-\tif (ret)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=1078=static int rtw_sdio_start(struct rtw_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1081-\ndrivers/net/wireless/realtek/rtw88/sdio.c:1082:\tif (rtw_is_8723bs(rtwdev)) {\ndrivers/net/wireless/realtek/rtw88/sdio.c:1083:\t\tint ret = rtw_sdio_8723bs_check_rqpn(rtwdev);\ndrivers/net/wireless/realtek/rtw88/sdio.c-1084-\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1087-\ndrivers/net/wireless/realtek/rtw88/sdio.c:1088:\t\tret = rtw_sdio_8723bs_init_free_txpg(rtwdev);\ndrivers/net/wireless/realtek/rtw88/sdio.c-1089-\t\tif (ret)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1094-\ndrivers/net/wireless/realtek/rtw88/sdio.c:1095:\tif (rtw_is_8723bs(rtwdev)) {\ndrivers/net/wireless/realtek/rtw88/sdio.c-1096-\t\tclear = rtw_read32(rtwdev, REG_SDIO_HISR) \u0026 RTW_SDIO_HISR_CLEAR_MASK;\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=1176=static void rtw_sdio_interface_cfg(struct rtw_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1183-\tval \u0026= 0xfff8;\ndrivers/net/wireless/realtek/rtw88/sdio.c:1184:\tif (rtw_is_8723bs(rtwdev))\ndrivers/net/wireless/realtek/rtw88/sdio.c-1185-\t\tval |= BIT_SDIO_TX_CTRL_ALWAYS_RECOGNIZE;\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=1265=static int rtw_sdio_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1286- */\ndrivers/net/wireless/realtek/rtw88/sdio.c:1287:static void rtw_sdio_8723bs_stop_tx_queue(struct rtw_dev *rtwdev,\ndrivers/net/wireless/realtek/rtw88/sdio.c-1288-\t\t\t\t\t enum rtw_tx_queue_type queue,\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1292-\ndrivers/net/wireless/realtek/rtw88/sdio.c:1293:\tif (!rtw_is_8723bs(rtwdev) || queue \u003e= RTW_TX_QUEUE_BCN)\ndrivers/net/wireless/realtek/rtw88/sdio.c-1294-\t\treturn;\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1307-\ndrivers/net/wireless/realtek/rtw88/sdio.c:1308:static void rtw_sdio_8723bs_wake_tx_queue(struct rtw_dev *rtwdev,\ndrivers/net/wireless/realtek/rtw88/sdio.c-1309-\t\t\t\t\t enum rtw_tx_queue_type queue,\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1313-\ndrivers/net/wireless/realtek/rtw88/sdio.c:1314:\tif (!rtw_is_8723bs(rtwdev) || queue \u003e= RTW_TX_QUEUE_BCN)\ndrivers/net/wireless/realtek/rtw88/sdio.c-1315-\t\treturn;\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=1329=static int rtw_sdio_tx_write(struct rtw_dev *rtwdev,\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1349-\ndrivers/net/wireless/realtek/rtw88/sdio.c:1350:\trtw_sdio_8723bs_stop_tx_queue(rtwdev, queue, q_map);\ndrivers/net/wireless/realtek/rtw88/sdio.c-1351-\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=1489=static void rtw_sdio_handle_interrupt(struct sdio_func *sdio_func)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1514-\t */\ndrivers/net/wireless/realtek/rtw88/sdio.c:1515:\tif (rtw_is_8723bs(rtwdev))\ndrivers/net/wireless/realtek/rtw88/sdio.c-1516-\t\thisr \u0026= RTW_SDIO_HISR_CLEAR_MASK;\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=1659=static int rtw_sdio_process_tx_queue(struct rtw_dev *rtwdev,\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1681-\ndrivers/net/wireless/realtek/rtw88/sdio.c:1682:\trtw_sdio_8723bs_wake_tx_queue(rtwdev, queue, q_map);\ndrivers/net/wireless/realtek/rtw88/sdio.c-1683-\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1700- */\ndrivers/net/wireless/realtek/rtw88/sdio.c:1701:static bool rtw_sdio_8723bs_reschedule_tx(struct rtw_dev *rtwdev,\ndrivers/net/wireless/realtek/rtw88/sdio.c-1702-\t\t\t\t\t struct rtw_sdio_work_data *work_data,\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1707-\ndrivers/net/wireless/realtek/rtw88/sdio.c:1708:\tif (!rtw_is_8723bs(rtwdev))\ndrivers/net/wireless/realtek/rtw88/sdio.c-1709-\t\treturn false;\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=1723=static void rtw_sdio_tx_handler(struct work_struct *work)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1743-\ndrivers/net/wireless/realtek/rtw88/sdio.c:1744:\t\t\tif (rtw_sdio_8723bs_reschedule_tx(rtwdev, work_data,\ndrivers/net/wireless/realtek/rtw88/sdio.c-1745-\t\t\t\t\t\t\t queue, ret))\n--\ndrivers/net/wireless/realtek/rtw88/tx.c=196=void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn)\n--\ndrivers/net/wireless/realtek/rtw88/tx.c-212-\t rtwdev-\u003ehci.type == RTW_HCI_TYPE_USB) ||\ndrivers/net/wireless/realtek/rtw88/tx.c:213:\t rtw_is_8723bs(rtwdev))\ndrivers/net/wireless/realtek/rtw88/tx.c-214-\t\ttimeout = msecs_to_jiffies(2500);\n"
} |
| 25/2 | 2026/08/25 19:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 41594 output: 41 thoughts: 71 Thoughts: **Investigating the rtw8723b Driver** Okay, so I'm looking into this `8723bs` issue, and it looks like the code mentions it specifically in `rtw88/sdio.c` and `rtw88/rx.c`. That's a bit odd. I'm used to seeing more modular drivers, so I'm immediately wondering where the actual `rtw8723b` driver implementation lives. Is it a separate file? Does it have a similar naming convention? My immediate instinct is to check for a file named something like `rtw8723b.c` or something analogous. Let's see if that exists first. Need to track down the primary driver file for this chip. |
| 26/2 | 2026/08/25 19:13 | tool | grepper |
0mError:no matches Args: {
"Expression": "rtw8723b",
"PathPrefix": "drivers/net/wireless/realtek/rtw88/"
}Results: {
"error": "no matches"
} |
| 27/2 | 2026/08/25 19:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 41886 output: 47 thoughts: 177 Thoughts: **Investigating the Missing Driver** Okay, so I see `RTW_CHIP_TYPE_8723B` has been added in `main.h`. That's the first clue. But, hold on... where's the actual driver file, `rtw8723b.c`? It's not immediately obvious. Something's not quite right. Let me quickly re-examine the commit diff. I need to make sure I haven't missed something subtle. Ah, okay, just as I suspected. The diff only modifies `main.h`, `rx.c`, `sdio.c`, `sdio.h`, and `tx.c`. No new driver source file. Alright, time to shift gears. This points to the likelihood that the support for `8723B` is integrated with an existing driver. My hunch is that it's likely handled either within `rtw8723x.c` or perhaps `rtw8723cs.c`. I'll start by checking those files directly for any mention of `RTW_CHIP_TYPE_8723B` to see if it's already accounted for. That will give me the answer quickly. |
| 28/2 | 2026/08/25 19:13 | tool | grepper |
0mArgs:{
"Expression": "RTW_CHIP_TYPE_8723B",
"PathPrefix": "drivers/net/wireless/realtek/rtw88/"
}Results: {
"Output": "drivers/net/wireless/realtek/rtw88/main.h=191=enum rtw_chip_type {\n--\ndrivers/net/wireless/realtek/rtw88/main.h-196-\tRTW_CHIP_TYPE_8703B,\ndrivers/net/wireless/realtek/rtw88/main.h:197:\tRTW_CHIP_TYPE_8723B,\ndrivers/net/wireless/realtek/rtw88/main.h-198-\tRTW_CHIP_TYPE_8821A,\n--\ndrivers/net/wireless/realtek/rtw88/main.h=2198=static inline bool rtw_is_8723bs(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/main.h-2199-{\ndrivers/net/wireless/realtek/rtw88/main.h:2200:\treturn rtwdev-\u003echip-\u003eid == RTW_CHIP_TYPE_8723B \u0026\u0026\ndrivers/net/wireless/realtek/rtw88/main.h-2201-\t rtwdev-\u003ehci.type == RTW_HCI_TYPE_SDIO;\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=974=static void rtw_sdio_enable_rx_aggregation(struct rtw_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-978-\tswitch (rtwdev-\u003echip-\u003eid) {\ndrivers/net/wireless/realtek/rtw88/sdio.c:979:\tcase RTW_CHIP_TYPE_8723B:\ndrivers/net/wireless/realtek/rtw88/sdio.c-980-\tcase RTW_CHIP_TYPE_8703B:\n"
} |
| 29/2 | 2026/08/25 19:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 42871 output: 39 thoughts: 103 Thoughts: **Investigating the RTW_CHIP_TYPE_8723B Designation** Okay, so it looks like `RTW_CHIP_TYPE_8723B` is only declared and used in `main.h` and `sdio.c`. That’s a start, but it doesn't explain how the driver *knows* to assign that value to `rtwdev->chip->id`. I need to figure out the assignment process. Where is that chip ID being determined and set? I need to trace the initialization flow. My next step is definitely to examine the `rtw_sdio_id_table`, assuming there *is* one, within `sdio.c` first. If it's not there, I'll need to broaden the search to look at `rtw8822bs.c` or any other relevant driver files that handle SDIO initialization or chip identification. There *has* to be some lookup table or conditional logic determining the chip type. Time to dig in and find it. |
| 30/2 | 2026/08/25 19:13 | tool | grepper |
0mArgs:{
"Expression": "8723B",
"PathPrefix": "drivers/net/wireless/realtek/rtw88/"
}Results: {
"Output": "drivers/net/wireless/realtek/rtw88/main.h=191=enum rtw_chip_type {\n--\ndrivers/net/wireless/realtek/rtw88/main.h-196-\tRTW_CHIP_TYPE_8703B,\ndrivers/net/wireless/realtek/rtw88/main.h:197:\tRTW_CHIP_TYPE_8723B,\ndrivers/net/wireless/realtek/rtw88/main.h-198-\tRTW_CHIP_TYPE_8821A,\n--\ndrivers/net/wireless/realtek/rtw88/main.h=2198=static inline bool rtw_is_8723bs(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/main.h-2199-{\ndrivers/net/wireless/realtek/rtw88/main.h:2200:\treturn rtwdev-\u003echip-\u003eid == RTW_CHIP_TYPE_8723B \u0026\u0026\ndrivers/net/wireless/realtek/rtw88/main.h-2201-\t rtwdev-\u003ehci.type == RTW_HCI_TYPE_SDIO;\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-25-/*\ndrivers/net/wireless/realtek/rtw88/sdio.c:26: * 8723BS SDIO TX FIFO back-pressure watermarks: stop the mac80211 queue once\ndrivers/net/wireless/realtek/rtw88/sdio.c-27- * the per-AC software FIFO fills past the high watermark, and wake it from the\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=974=static void rtw_sdio_enable_rx_aggregation(struct rtw_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-978-\tswitch (rtwdev-\u003echip-\u003eid) {\ndrivers/net/wireless/realtek/rtw88/sdio.c:979:\tcase RTW_CHIP_TYPE_8723B:\ndrivers/net/wireless/realtek/rtw88/sdio.c-980-\tcase RTW_CHIP_TYPE_8703B:\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=1489=static void rtw_sdio_handle_interrupt(struct sdio_func *sdio_func)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1510-\t/*\ndrivers/net/wireless/realtek/rtw88/sdio.c:1511:\t * RTL8723BS keeps raising the interrupt after resume if undefined\ndrivers/net/wireless/realtek/rtw88/sdio.c-1512-\t * status bits are written back, so acknowledge only the bits this\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=1659=static int rtw_sdio_process_tx_queue(struct rtw_dev *rtwdev,\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1687-/*\ndrivers/net/wireless/realtek/rtw88/sdio.c:1688: * Decide whether the RTL8723BS wants the TX work to run again, and if so\ndrivers/net/wireless/realtek/rtw88/sdio.c-1689- * arrange it and tell the caller to stop draining. Two cases need it.\n"
} |
| 31/2 | 2026/08/25 19:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 44174 output: 39 thoughts: 77 Thoughts: Here's my summary, as though I'm thinking through this myself: **Debugging a Potential Chip Identification Flaw** Okay, hold on a second. Something doesn't feel right with this chip identification logic. If `RTW_CHIP_TYPE_8723B` never actually gets assigned to `rtwdev->chip->id`, then the `rtw_is_8723bs()` function *will always* return false, regardless of the underlying hardware. That's a huge problem, and could lead to incorrect driver behavior and potentially even instability if it's relying on this identification. I need to figure out where `RTW_CHIP_TYPE_8723B` is supposed to be set. This means I need to quickly search the codebase for where that macro is actually assigned to that specific structure member. Time to do a quick grep or code search to pinpoint any other locations this value is used. I have a feeling this is a critical bug. |
| 32/2 | 2026/08/25 19:13 | tool | grepper |
0mArgs:{
"Expression": "8723B",
"PathPrefix": "drivers/net/wireless/realtek/rtw88/"
}Results: {
"Output": "drivers/net/wireless/realtek/rtw88/main.h=191=enum rtw_chip_type {\n--\ndrivers/net/wireless/realtek/rtw88/main.h-196-\tRTW_CHIP_TYPE_8703B,\ndrivers/net/wireless/realtek/rtw88/main.h:197:\tRTW_CHIP_TYPE_8723B,\ndrivers/net/wireless/realtek/rtw88/main.h-198-\tRTW_CHIP_TYPE_8821A,\n--\ndrivers/net/wireless/realtek/rtw88/main.h=2198=static inline bool rtw_is_8723bs(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/main.h-2199-{\ndrivers/net/wireless/realtek/rtw88/main.h:2200:\treturn rtwdev-\u003echip-\u003eid == RTW_CHIP_TYPE_8723B \u0026\u0026\ndrivers/net/wireless/realtek/rtw88/main.h-2201-\t rtwdev-\u003ehci.type == RTW_HCI_TYPE_SDIO;\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-25-/*\ndrivers/net/wireless/realtek/rtw88/sdio.c:26: * 8723BS SDIO TX FIFO back-pressure watermarks: stop the mac80211 queue once\ndrivers/net/wireless/realtek/rtw88/sdio.c-27- * the per-AC software FIFO fills past the high watermark, and wake it from the\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=974=static void rtw_sdio_enable_rx_aggregation(struct rtw_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-978-\tswitch (rtwdev-\u003echip-\u003eid) {\ndrivers/net/wireless/realtek/rtw88/sdio.c:979:\tcase RTW_CHIP_TYPE_8723B:\ndrivers/net/wireless/realtek/rtw88/sdio.c-980-\tcase RTW_CHIP_TYPE_8703B:\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=1489=static void rtw_sdio_handle_interrupt(struct sdio_func *sdio_func)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1510-\t/*\ndrivers/net/wireless/realtek/rtw88/sdio.c:1511:\t * RTL8723BS keeps raising the interrupt after resume if undefined\ndrivers/net/wireless/realtek/rtw88/sdio.c-1512-\t * status bits are written back, so acknowledge only the bits this\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=1659=static int rtw_sdio_process_tx_queue(struct rtw_dev *rtwdev,\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1687-/*\ndrivers/net/wireless/realtek/rtw88/sdio.c:1688: * Decide whether the RTL8723BS wants the TX work to run again, and if so\ndrivers/net/wireless/realtek/rtw88/sdio.c-1689- * arrange it and tell the caller to stop draining. Two cases need it.\n"
} |
| 33/2 | 2026/08/25 19:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 45436 output: 33 thoughts: 70 Thoughts: **Digging into the 8723B Chip Integration** Okay, hold on a second. I'm looking at `main.h` and I spot `RTW_CHIP_TYPE_8723B` being added. That's good, that's a signal. But immediately my mind jumps to a crucial question: is that enum value actually *assigned* to `rtwdev->chip->id` anywhere? I need to be sure the driver is actually *using* this defined type to identify the hardware. I can't just assume it's integrated, it needs to be wired in for it to be integrated. So, let's fire up a full kernel search, I'll go for a broad approach to be certain I don't miss anything subtle. Time to scour the entire codebase for that specific string, `RTW_CHIP_TYPE_8723B`. I need to understand the complete context around its use to be confident in this new chip's integration. |
| 34/2 | 2026/08/25 19:13 | tool | grepper |
0mArgs:{
"Expression": "RTW_CHIP_TYPE_8723B",
"PathPrefix": ""
}Results: {
"Output": "drivers/net/wireless/realtek/rtw88/main.h=191=enum rtw_chip_type {\n--\ndrivers/net/wireless/realtek/rtw88/main.h-196-\tRTW_CHIP_TYPE_8703B,\ndrivers/net/wireless/realtek/rtw88/main.h:197:\tRTW_CHIP_TYPE_8723B,\ndrivers/net/wireless/realtek/rtw88/main.h-198-\tRTW_CHIP_TYPE_8821A,\n--\ndrivers/net/wireless/realtek/rtw88/main.h=2198=static inline bool rtw_is_8723bs(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/main.h-2199-{\ndrivers/net/wireless/realtek/rtw88/main.h:2200:\treturn rtwdev-\u003echip-\u003eid == RTW_CHIP_TYPE_8723B \u0026\u0026\ndrivers/net/wireless/realtek/rtw88/main.h-2201-\t rtwdev-\u003ehci.type == RTW_HCI_TYPE_SDIO;\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=974=static void rtw_sdio_enable_rx_aggregation(struct rtw_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-978-\tswitch (rtwdev-\u003echip-\u003eid) {\ndrivers/net/wireless/realtek/rtw88/sdio.c:979:\tcase RTW_CHIP_TYPE_8723B:\ndrivers/net/wireless/realtek/rtw88/sdio.c-980-\tcase RTW_CHIP_TYPE_8703B:\n"
} |
| 35/2 | 2026/08/25 19:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 46251 output: 43 thoughts: 879 Thoughts: **Analyzing This Patch**
Okay, first things first, where is this even applied? It looks like I've just got a single patch here. Is there a larger series I should be looking at? I see a note about "syz-cluster: applied patch under review," but I only have this one diff to work with.
Alright, let's dive in. The key issue seems to revolve around `RTW_CHIP_TYPE_8723B`. If that's never actually assigned anywhere, then `rtw_is_8723bs()` will *always* evaluate to false. Hmm, wait, that has to be wrong, doesn't it? Let's check `rx.c`:
```c
if (pkt_stat->pkt_len == 0 &&
(rtwdev->chip->id == RTW_CHIP_TYPE_8703B || rtw_is_8723bs(rtwdev))) {
```
Okay, so it looks like this actually impacts `8703B` too! Hang on... let's compare with the original code:
```c
- /* Rtl8723cs driver checks for size < 14 or size > 8192 and
- * simply drops the packet.
- */
- if (rtwdev->chip->id == RTW_CHIP_TYPE_8703B && pkt_stat->pkt_len == 0) {
```
And the new code:
```c
+ /*
+ * Rtl8723cs and rtl8723bs drivers check for size < 14 or size > 8192
+ * and simply drop the packet.
+ */
+ if (pkt_stat->pkt_len == 0 &&
+ (rtwdev->chip->id == RTW_CHIP_TYPE_8703B || rtw_is_8723bs(rtwdev))) {
```
Aha! `8703B` was already accounted for. So this patch is mainly adding the `rtw_is_8723bs(rtwdev)` check, which, if that macro is always false, might lead to some interesting behavior.
Okay, let's shift gears. I see a change involving `rtw_sdio_tx_handler`. They've moved from `work_struct` to `delayed_work`.
```c
struct rtw_sdio_work_data *work_data =
- container_of(work, struct rtw_sdio_work_data, work);
+ container_of(to_delayed_work(work), struct rtw_sdio_work_data,
+ work);
```
And looking at `rtw_sdio_init_tx`:
```c
- INIT_WORK(&rtwsdio->tx_handler_data->work, rtw_sdio_tx_handler);
+ INIT_DELAYED_WORK(&rtwsdio->tx_handler_data->work, rtw_sdio_tx_handler);
```
Also, `rtw_sdio_tx_kick_off`:
```c
- queue_work(rtwsdio->txwq, &rtwsdio->tx_handler_data->work);
+ /*
+ * A retry may already be pending with a delay; re-arm it so a newly
+ * queued frame is not held back by it.
+ */
+ mod_delayed_work(rtwsdio->txwq, &rtwsdio->tx_handler_data->work, 0);
```
Wait a second... this affects *all* SDIO chips, not just the 8723bs! This is a core SDIO change in how the tx handler works for this driver. I'd better check which SDIO chips are supported under `rtw88`. I need to look at `rtw_sdio_id_table` in `drivers/net/wireless/realtek/rtw88/sdio.c`. This could have some significant implications for those devices.
|
| 36/2 | 2026/08/25 19:14 | tool | grepper |
0mError:no matches Args: {
"Expression": "rtw_sdio_id_table",
"PathPrefix": "drivers/net/wireless/realtek/rtw88/"
}Results: {
"error": "no matches"
} |
| 37/2 | 2026/08/25 19:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 48124 output: 40 thoughts: 22 Thoughts: Here's my thought process, as if I were considering that code: **Thinking About `sdio_device_id` in `rtw88`** Okay, first thing's first: I need to locate where `sdio_device_id` is defined within the `rtw88` driver. That identifier is pretty specific, so it should be a straightforward search. My mind immediately goes to the header files, because typically that's where device IDs and related structures are declared. I'll need to look in the standard places within the driver's source tree – likely `include/`, or maybe a subdirectory like `include/sdio/`. I'm expecting to find a list of `struct sdio_device_id` entries, which will be an array mapping SDIO device identifiers to driver-specific data structures or module parameters. I'm mentally preparing for the typical structure: vendor ID, device ID, subsystem vendor ID, subsystem device ID, and possibly a match flag. It's possible there are wildcards or masks involved for broader matching. I also anticipate that there might be a function that iterates through this array and probes the hardware, identifying a compatible SDIO device. I should probably be prepared to see references to this device ID in the probe function. If I find the declaration, I want to quickly evaluate: are there any quirks or special considerations listed in the documentation that apply to this driver? Is there a particular SDIO host controller I should keep in mind? Are there any potential issues that may be related to device matching? The code around the use of this ID will likely offer more insight, particularly regarding the error handling and device binding. Let's see what we can find! |
| 38/2 | 2026/08/25 19:14 | tool | grepper |
0mArgs:{
"Expression": "sdio_device_id",
"PathPrefix": "drivers/net/wireless/realtek/rtw88/"
}Results: {
"Output": "drivers/net/wireless/realtek/rtw88/rtw8723cs.c-10-\ndrivers/net/wireless/realtek/rtw88/rtw8723cs.c:11:static const struct sdio_device_id rtw_8723cs_id_table[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8723cs.c-12-\t{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8723ds.c-11-\ndrivers/net/wireless/realtek/rtw88/rtw8723ds.c:12:static const struct sdio_device_id rtw_8723ds_id_table[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8723ds.c-13-\t{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8821cs.c-11-\ndrivers/net/wireless/realtek/rtw88/rtw8821cs.c:12:static const struct sdio_device_id rtw_8821cs_id_table[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8821cs.c-13-\t{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8822bs.c-11-\ndrivers/net/wireless/realtek/rtw88/rtw8822bs.c:12:static const struct sdio_device_id rtw_8822bs_id_table[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8822bs.c-13-\t{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8822cs.c-11-\ndrivers/net/wireless/realtek/rtw88/rtw8822cs.c:12:static const struct sdio_device_id rtw_8822cs_id_table[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8822cs.c-13-\t{\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=1809=int rtw_sdio_probe(struct sdio_func *sdio_func,\ndrivers/net/wireless/realtek/rtw88/sdio.c:1810:\t\t const struct sdio_device_id *id)\ndrivers/net/wireless/realtek/rtw88/sdio.c-1811-{\n--\ndrivers/net/wireless/realtek/rtw88/sdio.h=151=struct sdio_func;\ndrivers/net/wireless/realtek/rtw88/sdio.h:152:struct sdio_device_id;\ndrivers/net/wireless/realtek/rtw88/sdio.h-153-\n--\ndrivers/net/wireless/realtek/rtw88/sdio.h=188=int rtw_sdio_probe(struct sdio_func *sdio_func,\ndrivers/net/wireless/realtek/rtw88/sdio.h:189:\t\t const struct sdio_device_id *id);\ndrivers/net/wireless/realtek/rtw88/sdio.h-190-void rtw_sdio_remove(struct sdio_func *sdio_func);\n"
} |
| 39/2 | 2026/08/25 19:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 49445 output: 41 thoughts: 237 Thoughts: **My Analysis of the SDIO Driver Patch** Okay, so I see these SDIO drivers: `rtw8723cs`, `rtw8723ds`, `rtw8821cs`, `rtw8822bs`, `rtw8822cs`. The patch I'm examining modifies `rtw_sdio_tx_handler`, which is, of course, used across all of these. But hold on a second... as I understand it, SDIO devices are not emulatable in standard QEMU; there isn't a virtual SDIO host controller within the kernel. This means `rtw_sdio_probe` is never going to be called in a virtualized environment. Consequently, if `rtw_sdio_probe` is never called, `rtw_sdio_init_tx` is also never called, and, therefore, the key function, `rtw_sdio_tx_handler`, never executes. Now I have to ask myself, is `rtw_sdio_tx_handler` *exclusively* used by SDIO? Yes, it's defined within `sdio.c`, so it seems it is. Now I need to confirm that `rtw_sdio_probe` isn't called from somewhere else. |
| 40/2 | 2026/08/25 19:14 | tool | grepper |
0mArgs:{
"Expression": "rtw_sdio_probe",
"PathPrefix": "drivers/net/wireless/realtek/rtw88/"
}Results: {
"Output": "drivers/net/wireless/realtek/rtw88/rtw8723cs.c=21=static struct sdio_driver rtw_8723cs_driver = {\n--\ndrivers/net/wireless/realtek/rtw88/rtw8723cs.c-23-\t.id_table = rtw_8723cs_id_table,\ndrivers/net/wireless/realtek/rtw88/rtw8723cs.c:24:\t.probe = rtw_sdio_probe,\ndrivers/net/wireless/realtek/rtw88/rtw8723cs.c-25-\t.remove = rtw_sdio_remove,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8723ds.c=27=static struct sdio_driver rtw_8723ds_driver = {\ndrivers/net/wireless/realtek/rtw88/rtw8723ds.c-28-\t.name = KBUILD_MODNAME,\ndrivers/net/wireless/realtek/rtw88/rtw8723ds.c:29:\t.probe = rtw_sdio_probe,\ndrivers/net/wireless/realtek/rtw88/rtw8723ds.c-30-\t.remove = rtw_sdio_remove,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8821cs.c=22=static struct sdio_driver rtw_8821cs_driver = {\ndrivers/net/wireless/realtek/rtw88/rtw8821cs.c-23-\t.name = KBUILD_MODNAME,\ndrivers/net/wireless/realtek/rtw88/rtw8821cs.c:24:\t.probe = rtw_sdio_probe,\ndrivers/net/wireless/realtek/rtw88/rtw8821cs.c-25-\t.remove = rtw_sdio_remove,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8822bs.c=22=static struct sdio_driver rtw_8822bs_driver = {\ndrivers/net/wireless/realtek/rtw88/rtw8822bs.c-23-\t.name = KBUILD_MODNAME,\ndrivers/net/wireless/realtek/rtw88/rtw8822bs.c:24:\t.probe = rtw_sdio_probe,\ndrivers/net/wireless/realtek/rtw88/rtw8822bs.c-25-\t.remove = rtw_sdio_remove,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8822cs.c=22=static struct sdio_driver rtw_8822cs_driver = {\ndrivers/net/wireless/realtek/rtw88/rtw8822cs.c-23-\t.name = KBUILD_MODNAME,\ndrivers/net/wireless/realtek/rtw88/rtw8822cs.c:24:\t.probe = rtw_sdio_probe,\ndrivers/net/wireless/realtek/rtw88/rtw8822cs.c-25-\t.remove = rtw_sdio_remove,\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c=1794=static void rtw_sdio_deinit_tx(struct rtw_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1808-\ndrivers/net/wireless/realtek/rtw88/sdio.c:1809:int rtw_sdio_probe(struct sdio_func *sdio_func,\ndrivers/net/wireless/realtek/rtw88/sdio.c-1810-\t\t const struct sdio_device_id *id)\n--\ndrivers/net/wireless/realtek/rtw88/sdio.c-1883-}\ndrivers/net/wireless/realtek/rtw88/sdio.c:1884:EXPORT_SYMBOL(rtw_sdio_probe);\ndrivers/net/wireless/realtek/rtw88/sdio.c-1885-\n--\ndrivers/net/wireless/realtek/rtw88/sdio.h=186=extern const struct dev_pm_ops rtw_sdio_pm_ops;\ndrivers/net/wireless/realtek/rtw88/sdio.h-187-\ndrivers/net/wireless/realtek/rtw88/sdio.h:188:int rtw_sdio_probe(struct sdio_func *sdio_func,\ndrivers/net/wireless/realtek/rtw88/sdio.h-189-\t\t const struct sdio_device_id *id);\n"
} |
| 41/2 | 2026/08/25 19:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 51255 output: 44 thoughts: 358 Thoughts: **Analyzing Reachability of a Code Change** Okay, so I'm looking at this code and initially, my thought was, "This is only touched by SDIO drivers." Since those are a pain in a virtual environment to probe, it seemed like this change wouldn't even be relevant to my usual work. But wait, I need to be more thorough. Is there *anything* else going on? Okay, digging into `rx.c`, I see a conditional change in `rtw_rx_fill_rx_status`. The code was modified to include the `rtw_is_8723bs` check. Now, `rtw_rx_fill_rx_status`... that's used for more than just SDIO, right? USB and PCI chips, too. I need to make sure I'm not missing something important here. So, I need to check if `RTW_CHIP_TYPE_8703B` is even supported via USB or PCI. I did check earlier in `usb.c` and found a comment that says it is likely NOT used in USB devices. Hmmm... but is there a `rtw8703b` driver? Yes, there is `rtw8703b.c`. I need to go over there and check that file to confirm, once and for all, that the chip isn't supported via PCI or USB. The comment in `usb.c` is not enough to convince me; I need to look into it deeper. |
| 42/2 | 2026/08/25 19:14 | tool | grepper |
0mError:no matches Args: {
"Expression": "rtw_8703b_driver",
"PathPrefix": "drivers/net/wireless/realtek/rtw88/"
}Results: {
"error": "no matches"
} |
| 43/2 | 2026/08/25 19:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 51996 output: 41 thoughts: 31 Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue: **Investigating the rtw8703b Driver** Right, let's dive into this. The objective is clear: I need to locate the driver files associated with the `rtw8703b` hardware. My first instinct, based on years of experience, is to zero in on the `drivers/net/wireless/realtek/rtw88/` directory within the kernel source. That path is pretty standard for Realtek wireless drivers, especially within the newer `rtw88` framework. It's a structured approach, almost procedural, but that's what's effective. The naming convention likely mirrors the device's internal codename; I'm expecting to find a header file, some source code (.c files), and maybe even a Kconfig and Makefile that are associated to the specific device. I'll need to use my intuition to determine which files I need to analyze. Time to get to work! |
| 44/2 | 2026/08/25 19:14 | tool | grepper |
0mArgs:{
"Expression": "rtw8703b",
"PathPrefix": "drivers/net/wireless/realtek/rtw88/"
}Results: {
"Output": "drivers/net/wireless/realtek/rtw88/Makefile=52=obj-$(CONFIG_RTW88_8703B)\t+= rtw88_8703b.o\ndrivers/net/wireless/realtek/rtw88/Makefile:53:rtw88_8703b-objs\t\t:= rtw8703b.o rtw8703b_tables.o\ndrivers/net/wireless/realtek/rtw88/Makefile-54-\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-11-#include \"rx.h\"\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:12:#include \"rtw8703b.h\"\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:13:#include \"rtw8703b_tables.h\"\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-14-#include \"rtw8723x.h\"\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c=45=static const struct coex_5g_afh_map afh_5g_8703b[] = { {0, 0, 0} };\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-47-/* Actually decreasing wifi TX power/RX gain isn't implemented in\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:48: * rtw8703b, but hopefully adjusting the BT side helps.\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-49- */\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c=59=static const struct coex_rf_para rf_para_rx_8703b[] = {\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-67-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:68:static const u32 rtw8703b_ofdm_swing_table[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-69-\t0x0b40002d, /* 0, -15.0dB */\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-113-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:114:static const u32 rtw8703b_cck_pwr_regs[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-115-\t0x0a22, 0x0a23, 0x0a24, 0x0a25, 0x0a26, 0x0a27, 0x0a28, 0x0a29,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-118-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:119:static const u8 rtw8703b_cck_swing_table[][16] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-120-\t{0x44, 0x42, 0x3C, 0x33, 0x28, 0x1C, 0x13, 0x0B, 0x05, 0x02,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-163-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:164:#define RTW_OFDM_SWING_TABLE_SIZE\tARRAY_SIZE(rtw8703b_ofdm_swing_table)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:165:#define RTW_CCK_SWING_TABLE_SIZE\tARRAY_SIZE(rtw8703b_cck_swing_table)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-166-\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c=522=static void try_mac_from_devicetree(struct rtw_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-537-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:538:static int rtw8703b_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-539-{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-552-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:553:static void rtw8703b_pwrtrack_init(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-554-{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-577-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:578:static void rtw8703b_phy_set_param(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-579-{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-663-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:664:\trtw8703b_pwrtrack_init(rtwdev);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-665-}\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-666-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:667:static bool rtw8703b_check_spur_ov_thres(struct rtw_dev *rtwdev,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-668-\t\t\t\t\t u32 freq, u32 thres)\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-685-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:686:static void rtw8703b_cfg_notch(struct rtw_dev *rtwdev, u8 channel, bool notch)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-687-{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-756-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:757:static void rtw8703b_spur_cal(struct rtw_dev *rtwdev, u8 channel)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-758-{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-774-\t} else {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:775:\t\trtw8703b_cfg_notch(rtwdev, channel, false);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-776-\t\treturn;\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-778-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:779:\tnotch = rtw8703b_check_spur_ov_thres(rtwdev, freq, SPUR_THRES);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:780:\trtw8703b_cfg_notch(rtwdev, channel, notch);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-781-}\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-782-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:783:static void rtw8703b_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-784-{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-814-\trtw_write_rf(rtwdev, RF_PATH_A, RF_RCK1, RFREG_MASK, rf_rck);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:815:\trtw8703b_spur_cal(rtwdev, channel);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-816-}\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c=819=static const struct rtw_backup_info cck_dfir_cfg[][CCK_DFIR_NR_8703B] = {\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-829-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:830:static void rtw8703b_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-831-\t\t\t\t u8 primary_ch_idx)\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-867-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:868:static void rtw8703b_set_channel(struct rtw_dev *rtwdev, u8 channel,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-869-\t\t\t\t u8 bw, u8 primary_chan_idx)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-870-{\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:871:\trtw8703b_set_channel_rf(rtwdev, channel, bw);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-872-\trtw_set_channel_mac(rtwdev, channel, bw, primary_chan_idx);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:873:\trtw8703b_set_channel_bb(rtwdev, channel, bw, primary_chan_idx);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-874-}\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c=969=static\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:970:void rtw8703b_iqk_config_mac(struct rtw_dev *rtwdev,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-971-\t\t\t const struct rtw8723x_iqk_backup_regs *backup)\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-981-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:982:static void rtw8703b_iqk_one_shot(struct rtw_dev *rtwdev, bool tx)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-983-{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1012-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1013:static void rtw8703b_iqk_txrx_path_post(struct rtw_dev *rtwdev,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1014-\t\t\t\t\tconst struct rtw8723x_iqk_backup_regs *backup)\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1023-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1024:static u8 rtw8703b_iqk_check_tx_failed(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1025-{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1050-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1051:static u8 rtw8703b_iqk_check_rx_failed(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1052-{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1079-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1080:static u8 rtw8703b_iqk_tx_path(struct rtw_dev *rtwdev,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1081-\t\t\t const struct rtw8723x_iqk_backup_regs *backup)\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1109-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1110:\trtw8703b_iqk_one_shot(rtwdev, true);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1111:\tstatus = rtw8703b_iqk_check_tx_failed(rtwdev);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1112-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1113:\trtw8703b_iqk_txrx_path_post(rtwdev, backup);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1114-\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1117-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1118:static u8 rtw8703b_iqk_rx_path(struct rtw_dev *rtwdev,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1119-\t\t\t const struct rtw8723x_iqk_backup_regs *backup)\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1154-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1155:\trtw8703b_iqk_one_shot(rtwdev, true);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1156-\t/* leave IQK mode */\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1157-\trtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, 0xffffff00, 0x000000);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1158:\tstatus = rtw8703b_iqk_check_tx_failed(rtwdev);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1159-\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1202-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1203:\trtw8703b_iqk_one_shot(rtwdev, false);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1204:\tstatus |= rtw8703b_iqk_check_rx_failed(rtwdev);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1205-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1206-restore:\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1207:\trtw8703b_iqk_txrx_path_post(rtwdev, backup);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1208-\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c=1212=static\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1213:void rtw8703b_iqk_one_round(struct rtw_dev *rtwdev, s32 result[][IQK_NR], u8 t,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1214-\t\t\t const struct rtw8723x_iqk_backup_regs *backup)\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1222-\trtw8723x_iqk_path_adda_on(rtwdev, ADDA_ON_VAL_8703B);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1223:\trtw8703b_iqk_config_mac(rtwdev, backup);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1224-\trtw_write32_mask(rtwdev, REG_CCK_ANT_SEL_11N, 0x0f000000, 0xf);\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1229-\tfor (i = 0; i \u003c PATH_IQK_RETRY; i++) {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1230:\t\ta_ok = rtw8703b_iqk_tx_path(rtwdev, backup);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1231-\t\tif (a_ok == IQK_TX_OK) {\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1248-\tfor (i = 0; i \u003c PATH_IQK_RETRY; i++) {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1249:\t\ta_ok = rtw8703b_iqk_rx_path(rtwdev, backup);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1250-\t\tif (a_ok == (IQK_TX_OK | IQK_RX_OK)) {\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c=1274=static\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1275:void rtw8703b_iqk_fill_a_matrix(struct rtw_dev *rtwdev, const s32 result[])\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1276-{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1320-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1321:static void rtw8703b_phy_calibration(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1322-{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1344-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1345:\t\trtw8703b_iqk_one_round(rtwdev, result, i, \u0026backup);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1346-\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1382-\t/* only path A is calibrated in rtl8703b */\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1383:\trtw8703b_iqk_fill_a_matrix(rtwdev, result[final_candidate]);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1384-\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1419-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1420:static void rtw8703b_set_iqk_matrix_by_result(struct rtw_dev *rtwdev,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1421-\t\t\t\t\t u32 ofdm_swing, u8 rf_path)\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1481-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1482:static void rtw8703b_set_iqk_matrix(struct rtw_dev *rtwdev, s8 ofdm_index,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1483-\t\t\t\t u8 rf_path)\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1490-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1491:\tofdm_swing = rtw8703b_ofdm_swing_table[ofdm_index];\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1492-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1493-\tif (dm_info-\u003eiqk.done) {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1494:\t\trtw8703b_set_iqk_matrix_by_result(rtwdev, ofdm_swing, rf_path);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1495-\t\treturn;\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1521-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1522:static void rtw8703b_pwrtrack_set_ofdm_pwr(struct rtw_dev *rtwdev, s8 swing_idx,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1523-\t\t\t\t\t s8 txagc_idx)\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1529-\t/* Only path A is calibrated for rtl8703b */\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1530:\trtw8703b_set_iqk_matrix(rtwdev, swing_idx, RF_PATH_A);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1531-}\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1532-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1533:static void rtw8703b_pwrtrack_set_cck_pwr(struct rtw_dev *rtwdev, s8 swing_idx,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1534-\t\t\t\t\t s8 txagc_idx)\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1541-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1542:\tBUILD_BUG_ON(ARRAY_SIZE(rtw8703b_cck_pwr_regs)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1543:\t\t != ARRAY_SIZE(rtw8703b_cck_swing_table[0]));\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1544-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1545:\tfor (int i = 0; i \u003c ARRAY_SIZE(rtw8703b_cck_pwr_regs); i++)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1546:\t\trtw_write8(rtwdev, rtw8703b_cck_pwr_regs[i],\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1547:\t\t\t rtw8703b_cck_swing_table[swing_idx][i]);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1548-}\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1549-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1550:static void rtw8703b_pwrtrack_set(struct rtw_dev *rtwdev, u8 path)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1551-{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1566-\tif (final_ofdm_swing_index \u003e limit_ofdm)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1567:\t\trtw8703b_pwrtrack_set_ofdm_pwr(rtwdev, limit_ofdm,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1568-\t\t\t\t\t final_ofdm_swing_index - limit_ofdm);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1569-\telse if (final_ofdm_swing_index \u003c 0)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1570:\t\trtw8703b_pwrtrack_set_ofdm_pwr(rtwdev, 0,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1571-\t\t\t\t\t final_ofdm_swing_index);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1572-\telse\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1573:\t\trtw8703b_pwrtrack_set_ofdm_pwr(rtwdev, final_ofdm_swing_index, 0);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1574-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1575-\tif (final_cck_swing_index \u003e limit_cck)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1576:\t\trtw8703b_pwrtrack_set_cck_pwr(rtwdev, limit_cck,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1577-\t\t\t\t\t final_cck_swing_index - limit_cck);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1578-\telse if (final_cck_swing_index \u003c 0)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1579:\t\trtw8703b_pwrtrack_set_cck_pwr(rtwdev, 0,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1580-\t\t\t\t\t final_cck_swing_index);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1581-\telse\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1582:\t\trtw8703b_pwrtrack_set_cck_pwr(rtwdev, final_cck_swing_index, 0);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1583-\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1586-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1587:static void rtw8703b_phy_pwrtrack(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1588-{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1627-\t\tdm_info-\u003edelta_power_index[path] = delta_cur;\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1628:\t\trtw8703b_pwrtrack_set(rtwdev, path);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1629-\t}\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1634-\tif (do_iqk)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1635:\t\trtw8703b_phy_calibration(rtwdev);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1636-}\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1637-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1638:static void rtw8703b_pwr_track(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1639-{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1654-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1655:\trtw8703b_phy_pwrtrack(rtwdev);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1656-\tdm_info-\u003epwr_trk_triggered = false;\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1658-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1659:static void rtw8703b_coex_set_gnt_fix(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1660-{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1662-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1663:static void rtw8703b_coex_set_gnt_debug(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1664-{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1666-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1667:static void rtw8703b_coex_set_rfe_type(struct rtw_dev *rtwdev)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1668-{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1684-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1685:static void rtw8703b_coex_set_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1686-{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1688-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1689:static void rtw8703b_coex_set_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain)\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1690-{\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1692-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1693:static const u8 rtw8703b_pwrtrk_2gb_n[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1694-\t0, 0, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1697-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1698:static const u8 rtw8703b_pwrtrk_2gb_p[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1699-\t0, 1, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7, 7, 7,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1702-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1703:static const u8 rtw8703b_pwrtrk_2ga_n[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1704-\t0, 0, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1707-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1708:static const u8 rtw8703b_pwrtrk_2ga_p[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1709-\t0, 1, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7, 7, 7,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1712-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1713:static const u8 rtw8703b_pwrtrk_2g_cck_b_n[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1714-\t0, 0, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1717-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1718:static const u8 rtw8703b_pwrtrk_2g_cck_b_p[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1719-\t0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 6, 6, 6,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1722-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1723:static const u8 rtw8703b_pwrtrk_2g_cck_a_n[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1724-\t0, 0, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1727-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1728:static const u8 rtw8703b_pwrtrk_2g_cck_a_p[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1729-\t0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 6, 6, 6,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1732-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1733:static const s8 rtw8703b_pwrtrk_xtal_n[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1734-\t0, 0, 0, -1, -1, -1, -1, -2, -2, -2, -3, -3, -3, -3, -3,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1737-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1738:static const s8 rtw8703b_pwrtrk_xtal_p[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1739-\t0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 1, 0, -1, -1, -1,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1742-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1743:static const struct rtw_pwr_track_tbl rtw8703b_rtw_pwr_track_tbl = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1744:\t.pwrtrk_2gb_n = rtw8703b_pwrtrk_2gb_n,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1745:\t.pwrtrk_2gb_p = rtw8703b_pwrtrk_2gb_p,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1746:\t.pwrtrk_2ga_n = rtw8703b_pwrtrk_2ga_n,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1747:\t.pwrtrk_2ga_p = rtw8703b_pwrtrk_2ga_p,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1748:\t.pwrtrk_2g_cckb_n = rtw8703b_pwrtrk_2g_cck_b_n,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1749:\t.pwrtrk_2g_cckb_p = rtw8703b_pwrtrk_2g_cck_b_p,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1750:\t.pwrtrk_2g_ccka_n = rtw8703b_pwrtrk_2g_cck_a_n,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1751:\t.pwrtrk_2g_ccka_p = rtw8703b_pwrtrk_2g_cck_a_p,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1752:\t.pwrtrk_xtal_n = rtw8703b_pwrtrk_xtal_n,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1753:\t.pwrtrk_xtal_p = rtw8703b_pwrtrk_xtal_p,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1754-};\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1755-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1756:static const struct rtw_rfe_def rtw8703b_rfe_defs[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1757:\t[0] = { .phy_pg_tbl\t= \u0026rtw8703b_bb_pg_tbl,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1758:\t\t.txpwr_lmt_tbl\t= \u0026rtw8703b_txpwr_lmt_tbl,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1759:\t\t.pwr_track_tbl\t= \u0026rtw8703b_rtw_pwr_track_tbl, },\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1760-};\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c=1805=static const struct coex_tdma_para tdma_sant_8703b[] = {\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1835-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1836:static const struct rtw_chip_ops rtw8703b_ops = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1837-\t.power_on\t\t= rtw_power_on,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1842-\t.shutdown\t\t= NULL,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1843:\t.read_efuse\t\t= rtw8703b_read_efuse,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1844:\t.phy_set_param\t\t= rtw8703b_phy_set_param,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1845:\t.set_channel\t\t= rtw8703b_set_channel,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1846-\t.query_phy_status\t= query_phy_status,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1854-\t.false_alarm_statistics\t= rtw8723x_false_alarm_statistics,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1855:\t.phy_calibration\t= rtw8703b_phy_calibration,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1856-\t.dpk_track\t\t= NULL,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1863-\t.cck_pd_set\t\t= NULL,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1864:\t.pwr_track\t\t= rtw8703b_pwr_track,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1865-\t.config_bfee\t\t= NULL,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1878-\t.coex_set_ant_switch\t= NULL,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1879:\t.coex_set_gnt_fix\t= rtw8703b_coex_set_gnt_fix,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1880:\t.coex_set_gnt_debug\t= rtw8703b_coex_set_gnt_debug,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1881:\t.coex_set_rfe_type\t= rtw8703b_coex_set_rfe_type,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1882:\t.coex_set_wl_tx_power\t= rtw8703b_coex_set_wl_tx_power,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1883:\t.coex_set_wl_rx_gain\t= rtw8703b_coex_set_wl_rx_gain,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1884-};\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1885-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1886:const struct rtw_chip_info rtw8703b_hw_spec = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1887:\t.ops = \u0026rtw8703b_ops,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1888-\t.id = RTW_CHIP_TYPE_8703B,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1889-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1890:\t.fw_name = \"rtw88/rtw8703b_fw.bin\",\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1891-\t.wlan_cpu = RTW_WCPU_8051,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1938-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1939:\t.mac_tbl = \u0026rtw8703b_mac_tbl,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1940:\t.agc_tbl = \u0026rtw8703b_agc_tbl,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1941:\t.bb_tbl = \u0026rtw8703b_bb_tbl,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1942:\t.rf_tbl = {\u0026rtw8703b_rf_a_tbl},\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1943-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1944:\t.rfe_defs = rtw8703b_rfe_defs,\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1945:\t.rfe_defs_size = ARRAY_SIZE(rtw8703b_rfe_defs),\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1946-\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1949-\t/* WOWLAN firmware exists, but not implemented yet */\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1950:\t.wow_fw_name = \"rtw88/rtw8703b_wow_fw.bin\",\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1951-\t.wowlan_stub = NULL,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-2000-};\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:2001:EXPORT_SYMBOL(rtw8703b_hw_spec);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-2002-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:2003:MODULE_FIRMWARE(\"rtw88/rtw8703b_fw.bin\");\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:2004:MODULE_FIRMWARE(\"rtw88/rtw8703b_wow_fw.bin\");\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-2005-\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.h-8-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.h:9:extern const struct rtw_chip_info rtw8703b_hw_spec;\ndrivers/net/wireless/realtek/rtw88/rtw8703b.h-10-\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-5-#include \"phy.h\"\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c:6:#include \"rtw8703b_tables.h\"\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-7-\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c:8:static const struct rtw_phy_pg_cfg_pair rtw8703b_bb_pg[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-9-\t{ 0, 0, 0, 0x00000e08, 0x0000ff00, 0x00003200, },\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-16-\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c:17:RTW_DECL_TABLE_BB_PG(rtw8703b_bb_pg);\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-18-\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-23- */\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c:24:static const struct rtw_txpwr_lmt_cfg_pair rtw8703b_txpwr_lmt[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-25-\t{0, 0, 0, 0, 1, 30},\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-194-\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c:195:RTW_DECL_TABLE_TXPWR_LMT(rtw8703b_txpwr_lmt);\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-196-\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c:197:static const u32 rtw8703b_mac[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-198-\t0x02F, 0x00000030,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-306-\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c:307:RTW_DECL_TABLE_PHY_COND(rtw8703b_mac, rtw_phy_cfg_mac);\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-308-\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c:309:static const u32 rtw8703b_agc[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-310-\t0xC78, 0xFC000101,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-633-\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c:634:RTW_DECL_TABLE_PHY_COND(rtw8703b_agc, rtw_phy_cfg_agc);\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-635-\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-636-/* init values for BB registers */\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c:637:static const u32 rtw8703b_bb[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-638-\t0x800, 0x83045700,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-841-\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c:842:RTW_DECL_TABLE_PHY_COND(rtw8703b_bb, rtw_phy_cfg_bb);\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-843-\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c:844:static const u32 rtw8703b_rf_a[] = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-845-\t0x018, 0x00008C01,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c-901-\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.c:902:RTW_DECL_TABLE_RF_RADIO(rtw8703b_rf_a, A);\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.h-6-\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.h:7:extern const struct rtw_table rtw8703b_bb_pg_tbl;\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.h:8:extern const struct rtw_table rtw8703b_txpwr_lmt_tbl;\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.h:9:extern const struct rtw_table rtw8703b_mac_tbl;\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.h:10:extern const struct rtw_table rtw8703b_agc_tbl;\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.h:11:extern const struct rtw_table rtw8703b_bb_tbl;\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.h:12:extern const struct rtw_table rtw8703b_rf_a_tbl;\ndrivers/net/wireless/realtek/rtw88/rtw8703b_tables.h-13-\n--\ndrivers/net/wireless/realtek/rtw88/rtw8723cs.c-7-#include \"main.h\"\ndrivers/net/wireless/realtek/rtw88/rtw8723cs.c:8:#include \"rtw8703b.h\"\ndrivers/net/wireless/realtek/rtw88/rtw8723cs.c-9-#include \"sdio.h\"\n--\ndrivers/net/wireless/realtek/rtw88/rtw8723cs.c=11=static const struct sdio_device_id rtw_8723cs_id_table[] = {\n--\ndrivers/net/wireless/realtek/rtw88/rtw8723cs.c-14-\t\t\t SDIO_DEVICE_ID_REALTEK_RTW8723CS),\ndrivers/net/wireless/realtek/rtw88/rtw8723cs.c:15:\t\t.driver_data = (kernel_ulong_t)\u0026rtw8703b_hw_spec,\ndrivers/net/wireless/realtek/rtw88/rtw8723cs.c-16-\t},\n"
} |
| 45/2 | 2026/08/25 19:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 68996 output: 45 thoughts: 211 Thoughts: **Analyzing the Realtek Driver Landscape** Okay, so I'm looking at this Realtek SDIO driver code for `rtw8723cs`, and it's immediately clear that it's leveraging `rtw8703b_hw_spec`. That's interesting, seeing how this particular SDIO device (`SDIO_DEVICE_ID_REALTEK_RTW8723CS`) is defined. The driver's `driver_data` field points directly to `rtw8703b_hw_spec`, implying a significant dependence on `RTW_CHIP_TYPE_8703B` within the `rtw8723cs` SDIO driver. Now, my immediate thought is to check for *broader* reuse. Is the `rtw8703b` hardware specification also being utilized by other Realtek drivers? Specifically, I need to investigate if this `rtw8703b` spec shows up in the USB or PCI driver implementations. I'll need to check the USB and PCI driver codebases and see if `rtw8703b` is used elsewhere. It's often the case that shared hardware specifications across different bus interfaces can streamline development and maintenance, so this cross-driver check is essential. |
| 46/2 | 2026/08/25 19:14 | tool | grepper |
0mArgs:{
"Expression": "rtw8703b_hw_spec",
"PathPrefix": "drivers/net/wireless/realtek/rtw88/"
}Results: {
"Output": "drivers/net/wireless/realtek/rtw88/rtw8703b.c=1836=static const struct rtw_chip_ops rtw8703b_ops = {\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1885-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:1886:const struct rtw_chip_info rtw8703b_hw_spec = {\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-1887-\t.ops = \u0026rtw8703b_ops,\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-2000-};\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c:2001:EXPORT_SYMBOL(rtw8703b_hw_spec);\ndrivers/net/wireless/realtek/rtw88/rtw8703b.c-2002-\n--\ndrivers/net/wireless/realtek/rtw88/rtw8703b.h-8-\ndrivers/net/wireless/realtek/rtw88/rtw8703b.h:9:extern const struct rtw_chip_info rtw8703b_hw_spec;\ndrivers/net/wireless/realtek/rtw88/rtw8703b.h-10-\n--\ndrivers/net/wireless/realtek/rtw88/rtw8723cs.c=11=static const struct sdio_device_id rtw_8723cs_id_table[] = {\n--\ndrivers/net/wireless/realtek/rtw88/rtw8723cs.c-14-\t\t\t SDIO_DEVICE_ID_REALTEK_RTW8723CS),\ndrivers/net/wireless/realtek/rtw88/rtw8723cs.c:15:\t\t.driver_data = (kernel_ulong_t)\u0026rtw8703b_hw_spec,\ndrivers/net/wireless/realtek/rtw88/rtw8723cs.c-16-\t},\n"
} |
| 47/2 | 2026/08/25 19:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 70123 output: 123 thoughts: 1238 Thoughts: **Patch Analysis: Unreachable SDIO Code in Virtualized Environments** Okay, let's break this down. My initial assessment is that `rtw8703b_hw_spec` is exclusively tied to `rtw8723cs`, which is an SDIO driver. I noticed `RTW_CHIP_TYPE_8723B` isn't used anywhere, which is a bit odd, but might be part of a larger, unsubmitted series. I need to focus on *this* patch as it is. The patch modifies `rtw_sdio_tx_handler` to use `delayed_work` instead of `work_struct`. This impacts all SDIO drivers within `rtw88`: `rtw8723cs`, `rtw8723ds`, `rtw8821cs`, `rtw8822bs`, `rtw8822cs`. The core issue here is that *all* these drivers are SDIO. SDIO devices are a problem. They can't be realistically emulated in standard QEMU. There's no virtual SDIO host controller to work with. So, all of the SDIO code in `rtw88` is inaccessible in a virtualized environment. I need to confirm if there is any alternate path to reach `rtw_sdio_tx_handler`. Looking at the code path, it's initialized within `rtw_sdio_init_tx`, which is called from `rtw_sdio_setup`, which is itself called from `rtw_sdio_probe`. `rtw_sdio_probe` is the probe function for these SDIO drivers. It's only going to be called if an SDIO device is present. Since there's no SDIO device, `rtw_sdio_probe` is never called. Therefore, the modified code is unreachable in environments like GCE or QEMU. Just to double-check, I'm checking if there's any chance of fuzzing these SDIO drivers. Syzkaller has `syz_usb_connect` for USB, `syz_vhci_inject` for Bluetooth HCI, `syz_mac80211_hwsim` for mac80211, and `syz_pci_connect` for PCI. However, there's no `syz_sdio_connect`. And QEMU can't emulate these specific SDIO WiFi chips. So, SDIO drivers are generally inaccessible. Reviewing the instructions, it says to return `WorthFuzzing=false` if the patch only contains code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware. This patch *exclusively* modifies code relating to SDIO drivers (`rtw88/sdio.c`, `rtw88/rx.c`, and `rtw88/tx.c` for SDIO chips). Since SDIO devices can't be emulated in QEMU, this definitively falls under that category. There are some modifications in `tx.c` and `rx.c` that involve `8723D` and `8703B`, respectively, but they are just conditional checks. They now include `rtw_is_8723bs()`. They don't change the existing behaviour for those chips. Therefore, the functional changes are strictly for SDIO devices, and since SDIO devices are not emulatable in QEMU, this patch is unreachable in a virtualized environment. I'm returning `WorthFuzzing=false` with the reasoning that the patch modifies SDIO driver code that is impossible to reach in virtualized environments because there's no software-emulated SDIO hardware framework available. |
| 48/2 | 2026/08/25 19:15 | tool | set-results |
0mArgs:{
"EnableConfigs": [],
"FocusSymbols": [],
"Reasoning": "The patch adds support for the RTL8723BS SDIO wireless chip and modifies the SDIO TX/RX handling in the rtw88 driver. Since there is no virtual SDIO host controller or software-emulated SDIO device framework in the kernel (unlike USB gadget or mac80211_hwsim), and standard QEMU does not emulate SDIO devices, this code is impossible to reach in virtualized environments.",
"WorthFuzzing": false
}Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch adds support for the RTL8723BS SDIO wireless chip and modifies the SDIO TX/RX handling in the rtw88 driver. Since there is no virtual SDIO host controller or software-emulated SDIO device framework in the kernel (unlike USB gadget or mac80211_hwsim), and standard QEMU does not emulate SDIO devices, this code is impossible to reach in virtualized environments.",
"WorthFuzzing": false
} |
| 49/1 | 2026/08/25 19:15 | action | If |
0mArgs:{
"WorthFuzzing": false
}Results: null |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|