| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/08/12 09:29 | flow | patch-triage |
50mArgs:null Results: {
"EnableConfigs": [
"NET_SCH_MQPRIO",
"NET_SCH_TAPRIO",
"XPS"
],
"FocusSymbols": [
"netdev_set_tc_queue",
"netdev_set_num_tc",
"netdev_bind_sb_channel_queue",
"netdev_set_sb_channel",
"netdev_reset_tc",
"__netif_set_xps_queue",
"mqprio_qopt_reconstruct",
"netif_set_real_num_tx_queues"
],
"KMSANReasoning": "The patch series addresses data races by replacing direct accesses to `num_tc`, `tc_to_txq`, and `prio_tc_map` fields of `struct net_device` with `READ_ONCE()` and `WRITE_ONCE()`. To enable atomic 32-bit reads/writes for `tc_to_txq`, it introduces a union with a `u32 combined` field overlaying the `u16 count` and `u16 offset` fields. \n\n1. The `struct netdev_tc_txq` contains exactly two `u16` fields, which perfectly align to 4 bytes without any padding. Thus, reading or writing the `combined` `u32` field does not involve any uninitialized padding bytes.\n2. The modified structures are internal to the kernel. When data is passed to user space (e.g., via `mqprio_qopt_reconstruct`), the fields (`count` and `offset`) are copied individually, ensuring no uninitialized memory or padding is leaked.\n3. The changes do not introduce new allocations, complex uninitialized data structures, or altered bounds checking that could expose uninitialized memory.\n\nThe patch primarily fixes concurrency issues (data races) which are best detected by KCSAN, while any memory corruption would be caught by KASAN. There is no risk of uninitialized memory use or info-leaks that would necessitate a dedicated KMSAN fuzzing session.",
"NeedsKMSAN": false,
"Reasoning": "The patch modifies the core networking stack to use `READ_ONCE` and `WRITE_ONCE` for `num_tc`, `tc_to_txq`, and `prio_tc_map` in `struct net_device` to prevent data races. It also introduces a `combined` field in `struct netdev_tc_txq` to read/write `count` and `offset` atomically. These changes affect traffic class (TC) and transmit queue (txq) configurations, which are reachable from userspace via `tc` commands (e.g., configuring `mqprio` or `taprio` qdiscs) and sysfs. The changes also affect several network drivers. Fuzzing should focus on the core API functions used to configure these parameters.",
"WorthFuzzing": true
} |
| 1/1 | 2026/08/12 09:29 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 628ffde6d9efa9ce85afde1dead16850c4b3d1d6\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Wed Aug 12 09:29:57 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c\nindex 9e2c2fa16d7a5..1ced6df6eac8c 100644\n--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c\n+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c\n@@ -1163,7 +1163,7 @@ static u16 cxgb_select_queue(struct net_device *dev, struct sk_buff *skb,\n \t}\n #endif /* CONFIG_CHELSIO_T4_DCB */\n \n-\tif (dev-\u003enum_tc) {\n+\tif (netdev_get_num_tc(dev)) {\n \t\tstruct port_info *pi = netdev2pinfo(dev);\n \t\tu8 ver, proto;\n \ndiff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c\nindex 764d2a09668f5..6f1046c9cc515 100644\n--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c\n+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c\n@@ -1403,10 +1403,10 @@ static netdev_tx_t __dpaa2_eth_tx(struct sk_buff *skb,\n \tstruct dpaa2_eth_fq *fq;\n \tstruct netdev_queue *nq;\n \tstruct dpaa2_fd *fd;\n+\tint err, i, num_tc;\n \tu16 queue_mapping;\n \tvoid *swa = NULL;\n \tu8 prio = 0;\n-\tint err, i;\n \tu32 fd_len;\n \n \tpercpu_stats = this_cpu_ptr(priv-\u003epercpu_stats);\n@@ -1468,12 +1468,14 @@ static netdev_tx_t __dpaa2_eth_tx(struct sk_buff *skb,\n \t */\n \tqueue_mapping = skb_get_queue_mapping(skb);\n \n-\tif (net_dev-\u003enum_tc) {\n+\tnum_tc = netdev_get_num_tc(net_dev);\n+\n+\tif (num_tc) {\n \t\tprio = netdev_txq_to_tc(net_dev, queue_mapping);\n \t\t/* Hardware interprets priority level 0 as being the highest,\n \t\t * so we need to do a reverse mapping to the netdev tc index\n \t\t */\n-\t\tprio = net_dev-\u003enum_tc - prio - 1;\n+\t\tprio = num_tc - prio - 1;\n \t\t/* We have only one FQ array entry for all Tx hardware queues\n \t\t * with the same flow id (but different priority levels)\n \t\t */\n@@ -2913,7 +2915,7 @@ static int update_xps(struct dpaa2_eth_priv *priv)\n \t\treturn -ENOMEM;\n \n \tnum_queues = dpaa2_eth_queue_count(priv);\n-\tnetdev_queues = (net_dev-\u003enum_tc ? : 1) * num_queues;\n+\tnetdev_queues = (netdev_get_num_tc(net_dev) ? : 1) * num_queues;\n \n \t/* The first \u003cnum_queues\u003e entries in priv-\u003efq array are Tx/Tx conf\n \t * queues, so only process those\n@@ -2946,7 +2948,7 @@ static int dpaa2_eth_setup_mqprio(struct net_device *net_dev,\n \tnum_queues = dpaa2_eth_queue_count(priv);\n \tnum_tc = mqprio-\u003enum_tc;\n \n-\tif (num_tc == net_dev-\u003enum_tc)\n+\tif (num_tc == netdev_get_num_tc(net_dev))\n \t\treturn 0;\n \n \tif (num_tc \u003e dpaa2_eth_tc_count(priv)) {\ndiff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c\nindex 52de2bcbadbec..d23a45a34fa3c 100644\n--- a/drivers/net/ethernet/intel/igc/igc_tsn.c\n+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c\n@@ -182,14 +182,16 @@ static u32 igc_fpe_map_preempt_tc_to_queue(const struct igc_adapter *adapter,\n \tstruct net_device *dev = adapter-\u003enetdev;\n \tu32 i, queue = 0;\n \n-\tfor (i = 0; i \u003c dev-\u003enum_tc; i++) {\n+\tfor (i = 0; i \u003c netdev_get_num_tc(dev); i++) {\n+\t\tstruct netdev_tc_txq res;\n \t\tu32 offset, count;\n \n \t\tif (!(preemptible_tcs \u0026 BIT(i)))\n \t\t\tcontinue;\n \n-\t\toffset = dev-\u003etc_to_txq[i].offset;\n-\t\tcount = dev-\u003etc_to_txq[i].count;\n+\t\tres.combined = READ_ONCE(dev-\u003etc_to_txq[i].combined);\n+\t\toffset = res.offset;\n+\t\tcount = res.count;\n \t\tqueue |= GENMASK(offset + count - 1, offset);\n \t}\n \ndiff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c\nindex 8873a8cc4a185..f91856498eb2d 100644\n--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c\n+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c\n@@ -9273,10 +9273,11 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,\n \tif (sb_dev) {\n \t\tu8 tc = netdev_get_prio_tc_map(dev, skb-\u003epriority);\n \t\tstruct net_device *vdev = sb_dev;\n+\t\tstruct netdev_tc_txq res;\n \n-\t\ttxq = vdev-\u003etc_to_txq[tc].offset;\n-\t\ttxq += reciprocal_scale(skb_get_hash(skb),\n-\t\t\t\t\tvdev-\u003etc_to_txq[tc].count);\n+\t\tres.combined = READ_ONCE(vdev-\u003etc_to_txq[tc].combined);\n+\t\ttxq = res.offset;\n+\t\ttxq += reciprocal_scale(skb_get_hash(skb), res.count);\n \n \t\treturn txq;\n \t}\ndiff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c\nindex ca3d7c6b5210e..fc110a7d16e8d 100644\n--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c\n+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c\n@@ -3245,9 +3245,9 @@ static int mlx5e_update_tc_and_tx_queues(struct mlx5e_priv *priv)\n \tint i;\n \n \told_num_txqs = netdev-\u003ereal_num_tx_queues;\n-\told_ntc = netdev-\u003enum_tc ? : 1;\n+\told_ntc = netdev_get_num_tc(netdev) ? : 1;\n \tfor (i = 0; i \u003c ARRAY_SIZE(old_tc_to_txq); i++)\n-\t\told_tc_to_txq[i] = netdev-\u003etc_to_txq[i];\n+\t\told_tc_to_txq[i].combined = READ_ONCE(netdev-\u003etc_to_txq[i].combined);\n \n \tnch = priv-\u003echannels.params.num_channels;\n \tntc = priv-\u003echannels.params.mqprio.num_tc;\ndiff --git a/drivers/net/ethernet/sfc/falcon/net_driver.h b/drivers/net/ethernet/sfc/falcon/net_driver.h\nindex 7ab0db44720da..63016bbae115b 100644\n--- a/drivers/net/ethernet/sfc/falcon/net_driver.h\n+++ b/drivers/net/ethernet/sfc/falcon/net_driver.h\n@@ -1208,7 +1208,7 @@ ef4_channel_get_tx_queue(struct ef4_channel *channel, unsigned type)\n \n static inline bool ef4_tx_queue_used(struct ef4_tx_queue *tx_queue)\n {\n-\treturn !(tx_queue-\u003eefx-\u003enet_dev-\u003enum_tc \u003c 2 \u0026\u0026\n+\treturn !(netdev_get_num_tc(tx_queue-\u003eefx-\u003enet_dev) \u003c 2 \u0026\u0026\n \t\t tx_queue-\u003equeue \u0026 EF4_TXQ_TYPE_HIGHPRI);\n }\n \ndiff --git a/drivers/net/ethernet/sfc/falcon/tx.c b/drivers/net/ethernet/sfc/falcon/tx.c\nindex 9e18aaf44badd..2103b6fdf9683 100644\n--- a/drivers/net/ethernet/sfc/falcon/tx.c\n+++ b/drivers/net/ethernet/sfc/falcon/tx.c\n@@ -435,15 +435,19 @@ int ef4_setup_tc(struct net_device *net_dev, enum tc_setup_type type,\n \n \tmqprio-\u003ehw = TC_MQPRIO_HW_OFFLOAD_TCS;\n \n-\tif (num_tc == net_dev-\u003enum_tc)\n+\tif (num_tc == netdev_get_num_tc(net_dev))\n \t\treturn 0;\n \n \tfor (tc = 0; tc \u003c num_tc; tc++) {\n-\t\tnet_dev-\u003etc_to_txq[tc].offset = tc * efx-\u003en_tx_channels;\n-\t\tnet_dev-\u003etc_to_txq[tc].count = efx-\u003en_tx_channels;\n+\t\tstruct netdev_tc_txq res = {\n+\t\t\t.offset = tc * efx-\u003en_tx_channels,\n+\t\t\t.count = efx-\u003en_tx_channels,\n+\t\t};\n+\n+\t\tWRITE_ONCE(net_dev-\u003etc_to_txq[tc].combined, res.combined);\n \t}\n \n-\tif (num_tc \u003e net_dev-\u003enum_tc) {\n+\tif (num_tc \u003e netdev_get_num_tc(net_dev)) {\n \t\t/* Initialise high-priority queues as necessary */\n \t\tef4_for_each_channel(channel, efx) {\n \t\t\tef4_for_each_possible_channel_tx_queue(tx_queue,\n@@ -462,7 +466,7 @@ int ef4_setup_tc(struct net_device *net_dev, enum tc_setup_type type,\n \t\t}\n \t} else {\n \t\t/* Reduce number of classes before number of queues */\n-\t\tnet_dev-\u003enum_tc = num_tc;\n+\t\tWRITE_ONCE(net_dev-\u003enum_tc, num_tc);\n \t}\n \n \trc = netif_set_real_num_tx_queues(net_dev,\n@@ -477,7 +481,7 @@ int ef4_setup_tc(struct net_device *net_dev, enum tc_setup_type type,\n \t * it to ef4_fini_channels().\n \t */\n \n-\tnet_dev-\u003enum_tc = num_tc;\n+\tWRITE_ONCE(net_dev-\u003enum_tc, num_tc);\n \treturn 0;\n }\n \ndiff --git a/drivers/net/ethernet/sfc/siena/tx.c b/drivers/net/ethernet/sfc/siena/tx.c\nindex 91e87594ed1ea..67c77d67d9843 100644\n--- a/drivers/net/ethernet/sfc/siena/tx.c\n+++ b/drivers/net/ethernet/sfc/siena/tx.c\n@@ -376,15 +376,19 @@ int efx_siena_setup_tc(struct net_device *net_dev, enum tc_setup_type type,\n \n \tmqprio-\u003ehw = TC_MQPRIO_HW_OFFLOAD_TCS;\n \n-\tif (num_tc == net_dev-\u003enum_tc)\n+\tif (num_tc == netdev_get_num_tc(net_dev))\n \t\treturn 0;\n \n \tfor (tc = 0; tc \u003c num_tc; tc++) {\n-\t\tnet_dev-\u003etc_to_txq[tc].offset = tc * efx-\u003en_tx_channels;\n-\t\tnet_dev-\u003etc_to_txq[tc].count = efx-\u003en_tx_channels;\n+\t\tstruct netdev_tc_txq res = {\n+\t\t\t.offset = tc * efx-\u003en_tx_channels,\n+\t\t\t.count = efx-\u003en_tx_channels,\n+\t\t};\n+\n+\t\tWRITE_ONCE(net_dev-\u003etc_to_txq[tc].combined, res.combined);\n \t}\n \n-\tnet_dev-\u003enum_tc = num_tc;\n+\tWRITE_ONCE(net_dev-\u003enum_tc, num_tc);\n \n \treturn netif_set_real_num_tx_queues(net_dev,\n \t\t\t\t\t max_t(int, num_tc, 1) *\ndiff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c\nindex c54c702243517..c889204a7aa5d 100644\n--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c\n+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c\n@@ -217,8 +217,11 @@ int dwmac5_fpe_map_preemption_class(struct net_device *ndev,\n \t * and is direct one-to-one mapping.\"\n \t */\n \tfor (u32 tc = 0; tc \u003c num_tc; tc++) {\n-\t\tcount = ndev-\u003etc_to_txq[tc].count;\n-\t\toffset = ndev-\u003etc_to_txq[tc].offset;\n+\t\tstruct netdev_tc_txq res;\n+\n+\t\tres.combined = READ_ONCE(ndev-\u003etc_to_txq[tc].combined);\n+\t\tcount = res.count;\n+\t\toffset = res.offset;\n \n \t\tif (pclass \u0026 BIT(tc))\n \t\t\tpreemptible_txqs |= GENMASK(offset + count - 1, offset);\n@@ -275,8 +278,11 @@ int dwxgmac3_fpe_map_preemption_class(struct net_device *ndev,\n \t * any of the scheduling algorithms.\"\n \t */\n \tfor (u32 tc = 0; tc \u003c num_tc; tc++) {\n-\t\tcount = ndev-\u003etc_to_txq[tc].count;\n-\t\toffset = ndev-\u003etc_to_txq[tc].offset;\n+\t\tstruct netdev_tc_txq res;\n+\n+\t\tres.combined = READ_ONCE(ndev-\u003etc_to_txq[tc].combined);\n+\t\tcount = res.count;\n+\t\toffset = res.offset;\n \n \t\tif (pclass \u0026 BIT(tc))\n \t\t\tpreemptible_txqs |= GENMASK(offset + count - 1, offset);\ndiff --git a/drivers/net/ethernet/ti/cpsw_priv.c b/drivers/net/ethernet/ti/cpsw_priv.c\nindex 1f6f374551cb6..0580a7885d339 100644\n--- a/drivers/net/ethernet/ti/cpsw_priv.c\n+++ b/drivers/net/ethernet/ti/cpsw_priv.c\n@@ -949,7 +949,7 @@ static int cpsw_set_cbs(struct net_device *ndev,\n \t * limited first and for compliance with CPDMA rate limited channels\n \t * that also used in bacward order. FIFO0 cannot be rate limited.\n \t */\n-\tfifo = cpsw_tc_to_fifo(tc, ndev-\u003enum_tc);\n+\tfifo = cpsw_tc_to_fifo(tc, netdev_get_num_tc(ndev));\n \tif (!fifo) {\n \t\tdev_err(priv-\u003edev, \"Last tc%d can't be rate limited\", tc);\n \t\treturn -EINVAL;\ndiff --git a/include/linux/netdevice.h b/include/linux/netdevice.h\nindex db9dce7f0aa65..de307c01d33eb 100644\n--- a/include/linux/netdevice.h\n+++ b/include/linux/netdevice.h\n@@ -832,8 +832,13 @@ struct xps_dev_maps {\n #define TC_BITMASK\t15\n /* HW offloaded queuing disciplines txq count and offset maps */\n struct netdev_tc_txq {\n-\tu16 count;\n-\tu16 offset;\n+\tunion {\n+\t\tstruct {\n+\t\t\tu16 count;\n+\t\t\tu16 offset;\n+\t\t};\n+\t\tu32 combined;\n+\t};\n };\n \n #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)\n@@ -2666,16 +2671,16 @@ static inline bool netif_elide_gro(const struct net_device *dev)\n static inline\n int netdev_get_prio_tc_map(const struct net_device *dev, u32 prio)\n {\n-\treturn dev-\u003eprio_tc_map[prio \u0026 TC_BITMASK];\n+\treturn READ_ONCE(dev-\u003eprio_tc_map[prio \u0026 TC_BITMASK]);\n }\n \n static inline\n int netdev_set_prio_tc_map(struct net_device *dev, u8 prio, u8 tc)\n {\n-\tif (tc \u003e= dev-\u003enum_tc)\n+\tif (tc \u003e= READ_ONCE(dev-\u003enum_tc))\n \t\treturn -EINVAL;\n \n-\tdev-\u003eprio_tc_map[prio \u0026 TC_BITMASK] = tc \u0026 TC_BITMASK;\n+\tWRITE_ONCE(dev-\u003eprio_tc_map[prio \u0026 TC_BITMASK], tc \u0026 TC_BITMASK);\n \treturn 0;\n }\n \n@@ -2685,9 +2690,9 @@ int netdev_set_tc_queue(struct net_device *dev, u8 tc, u16 count, u16 offset);\n int netdev_set_num_tc(struct net_device *dev, u8 num_tc);\n \n static inline\n-int netdev_get_num_tc(struct net_device *dev)\n+int netdev_get_num_tc(const struct net_device *dev)\n {\n-\treturn dev-\u003enum_tc;\n+\treturn READ_ONCE(dev-\u003enum_tc);\n }\n \n static inline void net_prefetch(void *p)\n@@ -2714,7 +2719,7 @@ int netdev_bind_sb_channel_queue(struct net_device *dev,\n int netdev_set_sb_channel(struct net_device *dev, u16 channel);\n static inline int netdev_get_sb_channel(struct net_device *dev)\n {\n-\treturn max_t(int, -dev-\u003enum_tc, 0);\n+\treturn max_t(int, -READ_ONCE(dev-\u003enum_tc), 0);\n }\n \n static inline\ndiff --git a/net/core/dev.c b/net/core/dev.c\nindex fd0b445f5d38c..d52285ac01a54 100644\n--- a/net/core/dev.c\n+++ b/net/core/dev.c\n@@ -2656,13 +2656,15 @@ EXPORT_SYMBOL_GPL(dev_queue_xmit_nit);\n */\n static void netif_setup_tc(struct net_device *dev, unsigned int txq)\n {\n+\tstruct netdev_tc_txq res;\n \tint i;\n-\tstruct netdev_tc_txq *tc = \u0026dev-\u003etc_to_txq[0];\n+\n+\tres.combined = READ_ONCE(dev-\u003etc_to_txq[0].combined);\n \n \t/* If TC0 is invalidated disable TC mapping */\n-\tif (tc-\u003eoffset + tc-\u003ecount \u003e txq) {\n+\tif (res.offset + res.count \u003e txq) {\n \t\tnetdev_warn(dev, \"Number of in use tx queues changed invalidating tc mappings. Priority traffic classification disabled!\\n\");\n-\t\tdev-\u003enum_tc = 0;\n+\t\tWRITE_ONCE(dev-\u003enum_tc, 0);\n \t\treturn;\n \t}\n \n@@ -2670,8 +2672,8 @@ static void netif_setup_tc(struct net_device *dev, unsigned int txq)\n \tfor (i = 1; i \u003c TC_BITMASK + 1; i++) {\n \t\tint q = netdev_get_prio_tc_map(dev, i);\n \n-\t\ttc = \u0026dev-\u003etc_to_txq[q];\n-\t\tif (tc-\u003eoffset + tc-\u003ecount \u003e txq) {\n+\t\tres.combined = READ_ONCE(dev-\u003etc_to_txq[q].combined);\n+\t\tif (res.offset + res.count \u003e txq) {\n \t\t\tnetdev_warn(dev, \"Number of in use tx queues changed. Priority %i to tc mapping %i is no longer valid. Setting map to 0\\n\",\n \t\t\t\t i, q);\n \t\t\tnetdev_set_prio_tc_map(dev, i, 0);\n@@ -2681,13 +2683,16 @@ static void netif_setup_tc(struct net_device *dev, unsigned int txq)\n \n int netdev_txq_to_tc(struct net_device *dev, unsigned int txq)\n {\n-\tif (dev-\u003enum_tc) {\n+\tif (READ_ONCE(dev-\u003enum_tc)) {\n \t\tstruct netdev_tc_txq *tc = \u0026dev-\u003etc_to_txq[0];\n \t\tint i;\n \n \t\t/* walk through the TCs and see if it falls into any of them */\n \t\tfor (i = 0; i \u003c TC_MAX_QUEUE; i++, tc++) {\n-\t\t\tif ((txq - tc-\u003eoffset) \u003c tc-\u003ecount)\n+\t\t\tstruct netdev_tc_txq res;\n+\n+\t\t\tres.combined = READ_ONCE(tc-\u003ecombined);\n+\t\t\tif ((txq - res.offset) \u003c res.count)\n \t\t\t\treturn i;\n \t\t}\n \n@@ -2880,18 +2885,19 @@ int __netif_set_xps_queue(struct net_device *dev, const unsigned long *mask,\n \t\t\t u16 index, enum xps_map_type type)\n {\n \tstruct xps_dev_maps *dev_maps, *new_dev_maps = NULL, *old_dev_maps = NULL;\n+\tint maps_sz, num_tc = 1, tc = 0, dev_num_tc;\n \tconst unsigned long *online_mask = NULL;\n \tbool active = false, copy = false;\n \tint i, j, tci, numa_node_id = -2;\n-\tint maps_sz, num_tc = 1, tc = 0;\n \tstruct xps_map *map, *new_map;\n \tunsigned int nr_ids;\n \n \tWARN_ON_ONCE(index \u003e= dev-\u003enum_tx_queues);\n \n-\tif (dev-\u003enum_tc) {\n+\tdev_num_tc = READ_ONCE(dev-\u003enum_tc);\n+\tif (dev_num_tc) {\n \t\t/* Do not allow XPS on subordinate device directly */\n-\t\tnum_tc = dev-\u003enum_tc;\n+\t\tnum_tc = dev_num_tc;\n \t\tif (num_tc \u003c 0)\n \t\t\treturn -EINVAL;\n \n@@ -3107,28 +3113,36 @@ static void netdev_unbind_all_sb_channels(struct net_device *dev)\n \n void netdev_reset_tc(struct net_device *dev)\n {\n+\tint i;\n+\n #ifdef CONFIG_XPS\n \tnetif_reset_xps_queues_gt(dev, 0);\n #endif\n \tnetdev_unbind_all_sb_channels(dev);\n \n \t/* Reset TC configuration of device */\n-\tdev-\u003enum_tc = 0;\n-\tmemset(dev-\u003etc_to_txq, 0, sizeof(dev-\u003etc_to_txq));\n-\tmemset(dev-\u003eprio_tc_map, 0, sizeof(dev-\u003eprio_tc_map));\n+\tWRITE_ONCE(dev-\u003enum_tc, 0);\n+\tfor (i = 0; i \u003c TC_MAX_QUEUE; i++)\n+\t\tWRITE_ONCE(dev-\u003etc_to_txq[i].combined, 0);\n+\tfor (i = 0; i \u003c= TC_BITMASK; i++)\n+\t\tWRITE_ONCE(dev-\u003eprio_tc_map[i], 0);\n }\n EXPORT_SYMBOL(netdev_reset_tc);\n \n int netdev_set_tc_queue(struct net_device *dev, u8 tc, u16 count, u16 offset)\n {\n-\tif (tc \u003e= dev-\u003enum_tc)\n+\tstruct netdev_tc_txq res = {\n+\t\t.count = count,\n+\t\t.offset = offset,\n+\t};\n+\n+\tif (tc \u003e= READ_ONCE(dev-\u003enum_tc))\n \t\treturn -EINVAL;\n \n #ifdef CONFIG_XPS\n \tnetif_reset_xps_queues(dev, offset, count);\n #endif\n-\tdev-\u003etc_to_txq[tc].count = count;\n-\tdev-\u003etc_to_txq[tc].offset = offset;\n+\tWRITE_ONCE(dev-\u003etc_to_txq[tc].combined, res.combined);\n \treturn 0;\n }\n EXPORT_SYMBOL(netdev_set_tc_queue);\n@@ -3143,7 +3157,7 @@ int netdev_set_num_tc(struct net_device *dev, u8 num_tc)\n #endif\n \tnetdev_unbind_all_sb_channels(dev);\n \n-\tdev-\u003enum_tc = num_tc;\n+\tWRITE_ONCE(dev-\u003enum_tc, num_tc);\n \treturn 0;\n }\n EXPORT_SYMBOL(netdev_set_num_tc);\n@@ -3152,12 +3166,15 @@ void netdev_unbind_sb_channel(struct net_device *dev,\n \t\t\t struct net_device *sb_dev)\n {\n \tstruct netdev_queue *txq = \u0026dev-\u003e_tx[dev-\u003enum_tx_queues];\n+\tint i;\n \n #ifdef CONFIG_XPS\n \tnetif_reset_xps_queues_gt(sb_dev, 0);\n #endif\n-\tmemset(sb_dev-\u003etc_to_txq, 0, sizeof(sb_dev-\u003etc_to_txq));\n-\tmemset(sb_dev-\u003eprio_tc_map, 0, sizeof(sb_dev-\u003eprio_tc_map));\n+\tfor (i = 0; i \u003c TC_MAX_QUEUE; i++)\n+\t\tWRITE_ONCE(sb_dev-\u003etc_to_txq[i].combined, 0);\n+\tfor (i = 0; i \u003c= TC_BITMASK; i++)\n+\t\tWRITE_ONCE(sb_dev-\u003eprio_tc_map[i], 0);\n \n \twhile (txq-- != \u0026dev-\u003e_tx[0]) {\n \t\tif (txq-\u003esb_dev == sb_dev)\n@@ -3171,7 +3188,7 @@ int netdev_bind_sb_channel_queue(struct net_device *dev,\n \t\t\t\t u8 tc, u16 count, u16 offset)\n {\n \t/* Make certain the sb_dev and dev are already configured */\n-\tif (sb_dev-\u003enum_tc \u003e= 0 || tc \u003e= dev-\u003enum_tc)\n+\tif (READ_ONCE(sb_dev-\u003enum_tc) \u003e= 0 || tc \u003e= READ_ONCE(dev-\u003enum_tc))\n \t\treturn -EINVAL;\n \n \t/* We cannot hand out queues we don't have */\n@@ -3179,8 +3196,12 @@ int netdev_bind_sb_channel_queue(struct net_device *dev,\n \t\treturn -EINVAL;\n \n \t/* Record the mapping */\n-\tsb_dev-\u003etc_to_txq[tc].count = count;\n-\tsb_dev-\u003etc_to_txq[tc].offset = offset;\n+\tstruct netdev_tc_txq res = {\n+\t\t.count = count,\n+\t\t.offset = offset,\n+\t};\n+\n+\tWRITE_ONCE(sb_dev-\u003etc_to_txq[tc].combined, res.combined);\n \n \t/* Provide a way for Tx queue to find the tc_to_txq map or\n \t * XPS map for itself.\n@@ -3206,7 +3227,7 @@ int netdev_set_sb_channel(struct net_device *dev, u16 channel)\n \tif (channel \u003e S16_MAX)\n \t\treturn -EINVAL;\n \n-\tdev-\u003enum_tc = -channel;\n+\tWRITE_ONCE(dev-\u003enum_tc, -channel);\n \n \treturn 0;\n }\n@@ -3235,7 +3256,7 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)\n \t\tif (rc)\n \t\t\treturn rc;\n \n-\t\tif (dev-\u003enum_tc)\n+\t\tif (READ_ONCE(dev-\u003enum_tc))\n \t\t\tnetif_setup_tc(dev, txq);\n \n \t\tnet_shaper_set_real_num_tx_queues(dev, txq);\n@@ -3544,11 +3565,13 @@ static u16 skb_tx_hash(const struct net_device *dev,\n \tu16 qoffset = 0;\n \tu16 qcount = dev-\u003ereal_num_tx_queues;\n \n-\tif (dev-\u003enum_tc) {\n+\tif (READ_ONCE(dev-\u003enum_tc)) {\n \t\tu8 tc = netdev_get_prio_tc_map(dev, skb-\u003epriority);\n+\t\tstruct netdev_tc_txq res;\n \n-\t\tqoffset = sb_dev-\u003etc_to_txq[tc].offset;\n-\t\tqcount = sb_dev-\u003etc_to_txq[tc].count;\n+\t\tres.combined = READ_ONCE(sb_dev-\u003etc_to_txq[tc].combined);\n+\t\tqoffset = res.offset;\n+\t\tqcount = res.count;\n \t\tif (unlikely(!qcount)) {\n \t\t\tnet_warn_ratelimited(\"%s: invalid qcount, qoffset %u for tc %u\\n\",\n \t\t\t\t\t sb_dev-\u003ename, qoffset, tc);\ndiff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c\nindex 25546deacec80..352173df75785 100644\n--- a/net/core/net-sysfs.c\n+++ b/net/core/net-sysfs.c\n@@ -1432,7 +1432,7 @@ static ssize_t traffic_class_show(struct kobject *kobj, struct attribute *attr,\n \t/* If queue belongs to subordinate dev use its TC mapping */\n \tdev = netdev_get_tx_queue(dev, index)-\u003esb_dev ? : dev;\n \n-\tnum_tc = dev-\u003enum_tc;\n+\tnum_tc = READ_ONCE(dev-\u003enum_tc);\n \ttc = netdev_txq_to_tc(dev, index);\n \n \trtnl_unlock();\ndiff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c\nindex ae991fc25b43f..6ced7008ef5c8 100644\n--- a/net/sched/sch_mqprio.c\n+++ b/net/sched/sch_mqprio.c\n@@ -679,12 +679,14 @@ static int mqprio_dump_class_stats(struct Qdisc *sch, unsigned long cl,\n \trcu_read_lock();\n \tif (cl \u003e= TC_H_MIN_PRIORITY) {\n \t\tstruct net_device *dev = qdisc_dev(sch);\n-\t\tstruct netdev_tc_txq tc = dev-\u003etc_to_txq[cl \u0026 TC_BITMASK];\n+\t\tstruct netdev_tc_txq tc;\n \t\tstruct gnet_stats_queue qstats = {0};\n \t\tstruct gnet_stats_basic_sync bstats;\n \t\tu32 qlen = 0;\n \t\tint i;\n \n+\t\ttc.combined = READ_ONCE(dev-\u003etc_to_txq[cl \u0026 TC_BITMASK].combined);\n+\n \t\tgnet_stats_basic_sync_init(\u0026bstats);\n \n \t\tfor (i = tc.offset; i \u003c tc.offset + tc.count; i++) {\ndiff --git a/net/sched/sch_mqprio_lib.c b/net/sched/sch_mqprio_lib.c\nindex b3a5572c167b7..888935e34d438 100644\n--- a/net/sched/sch_mqprio_lib.c\n+++ b/net/sched/sch_mqprio_lib.c\n@@ -105,11 +105,15 @@ void mqprio_qopt_reconstruct(struct net_device *dev, struct tc_mqprio_qopt *qopt\n \tint tc, num_tc = netdev_get_num_tc(dev);\n \n \tqopt-\u003enum_tc = num_tc;\n-\tmemcpy(qopt-\u003eprio_tc_map, dev-\u003eprio_tc_map, sizeof(qopt-\u003eprio_tc_map));\n+\tfor (tc = 0; tc \u003c= TC_BITMASK; tc++)\n+\t\tqopt-\u003eprio_tc_map[tc] = netdev_get_prio_tc_map(dev, tc);\n \n \tfor (tc = 0; tc \u003c num_tc; tc++) {\n-\t\tqopt-\u003ecount[tc] = dev-\u003etc_to_txq[tc].count;\n-\t\tqopt-\u003eoffset[tc] = dev-\u003etc_to_txq[tc].offset;\n+\t\tstruct netdev_tc_txq res;\n+\n+\t\tres.combined = READ_ONCE(dev-\u003etc_to_txq[tc].combined);\n+\t\tqopt-\u003ecount[tc] = res.count;\n+\t\tqopt-\u003eoffset[tc] = res.offset;\n \t}\n }\n EXPORT_SYMBOL_GPL(mqprio_qopt_reconstruct);\ndiff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c\nindex 299234a5f0fe6..39ac5b97aa3af 100644\n--- a/net/sched/sch_taprio.c\n+++ b/net/sched/sch_taprio.c\n@@ -762,12 +762,13 @@ static struct sk_buff *taprio_dequeue_from_txq(struct Qdisc *sch, int txq,\n \n static void taprio_next_tc_txq(struct net_device *dev, int tc, int *txq)\n {\n-\tint offset = dev-\u003etc_to_txq[tc].offset;\n-\tint count = dev-\u003etc_to_txq[tc].count;\n+\tstruct netdev_tc_txq res;\n+\n+\tres.combined = READ_ONCE(dev-\u003etc_to_txq[tc].combined);\n \n \t(*txq)++;\n-\tif (*txq == offset + count)\n-\t\t*txq = offset;\n+\tif (*txq == res.offset + res.count)\n+\t\t*txq = res.offset;\n }\n \n /* Prioritize higher traffic classes, and select among TXQs belonging to the\n@@ -1184,7 +1185,7 @@ static int taprio_parse_mqprio_opt(struct net_device *dev,\n \tbool allow_overlapping_txqs = TXTIME_ASSIST_IS_ENABLED(taprio_flags);\n \n \tif (!qopt) {\n-\t\tif (!dev-\u003enum_tc) {\n+\t\tif (!netdev_get_num_tc(dev)) {\n \t\t\tNL_SET_ERR_MSG(extack, \"'mqprio' configuration is necessary\");\n \t\t\treturn -EINVAL;\n \t\t}\n@@ -1438,18 +1439,18 @@ static void taprio_offload_config_changed(struct taprio_sched *q)\n \n static u32 tc_map_to_queue_mask(struct net_device *dev, u32 tc_mask)\n {\n+\tint num_tc = netdev_get_num_tc(dev);\n \tu32 i, queue_mask = 0;\n \n-\tfor (i = 0; i \u003c dev-\u003enum_tc; i++) {\n-\t\tu32 offset, count;\n+\tfor (i = 0; i \u003c num_tc; i++) {\n+\t\tstruct netdev_tc_txq res;\n \n \t\tif (!(tc_mask \u0026 BIT(i)))\n \t\t\tcontinue;\n \n-\t\toffset = dev-\u003etc_to_txq[i].offset;\n-\t\tcount = dev-\u003etc_to_txq[i].count;\n+\t\tres.combined = READ_ONCE(dev-\u003etc_to_txq[i].combined);\n \n-\t\tqueue_mask |= GENMASK(offset + count - 1, offset);\n+\t\tqueue_mask |= GENMASK(res.offset + res.count - 1, res.offset);\n \t}\n \n \treturn queue_mask;\n@@ -1799,16 +1800,20 @@ static int taprio_mqprio_cmp(const struct net_device *dev,\n {\n \tint i;\n \n-\tif (!mqprio || mqprio-\u003enum_tc != dev-\u003enum_tc)\n+\tif (!mqprio || mqprio-\u003enum_tc != netdev_get_num_tc(dev))\n \t\treturn -1;\n \n-\tfor (i = 0; i \u003c mqprio-\u003enum_tc; i++)\n-\t\tif (dev-\u003etc_to_txq[i].count != mqprio-\u003ecount[i] ||\n-\t\t dev-\u003etc_to_txq[i].offset != mqprio-\u003eoffset[i])\n+\tfor (i = 0; i \u003c mqprio-\u003enum_tc; i++) {\n+\t\tstruct netdev_tc_txq res;\n+\n+\t\tres.combined = READ_ONCE(dev-\u003etc_to_txq[i].combined);\n+\t\tif (res.count != mqprio-\u003ecount[i] ||\n+\t\t res.offset != mqprio-\u003eoffset[i])\n \t\t\treturn -1;\n+\t}\n \n \tfor (i = 0; i \u003c= TC_BITMASK; i++)\n-\t\tif (dev-\u003eprio_tc_map[i] != mqprio-\u003eprio_tc_map[i])\n+\t\tif (netdev_get_prio_tc_map(dev, i) != mqprio-\u003eprio_tc_map[i])\n \t\t\treturn -1;\n \n \treturn 0;\n"
} |
| 2/1 | 2026/08/12 09:29 | agent | patch-evaluator |
49mModel:best-expensive Args: null Results: {
"EnableConfigs": [
"NET_SCH_MQPRIO",
"NET_SCH_TAPRIO",
"XPS"
],
"FocusSymbols": [
"netdev_set_tc_queue",
"netdev_set_num_tc",
"netdev_bind_sb_channel_queue",
"netdev_set_sb_channel",
"netdev_reset_tc",
"__netif_set_xps_queue",
"mqprio_qopt_reconstruct",
"netif_set_real_num_tx_queues"
],
"Reasoning": "The patch modifies the core networking stack to use `READ_ONCE` and `WRITE_ONCE` for `num_tc`, `tc_to_txq`, and `prio_tc_map` in `struct net_device` to prevent data races. It also introduces a `combined` field in `struct netdev_tc_txq` to read/write `count` and `offset` atomically. These changes affect traffic class (TC) and transmit queue (txq) configurations, which are reachable from userspace via `tc` commands (e.g., configuring `mqprio` or `taprio` qdiscs) and sysfs. The changes also affect several network drivers. Fuzzing should focus on the core API functions used to configure these parameters.",
"WorthFuzzing": true
}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 628ffde6d9efa9ce85afde1dead16850c4b3d1d6
Author: syz-cluster <triage@syzkaller.com>
Date: Wed Aug 12 09:29:57 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 9e2c2fa16d7a5..1ced6df6eac8c 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -1163,7 +1163,7 @@ static u16 cxgb_select_queue(struct net_device *dev, struct sk_buff *skb,
}
#endif /* CONFIG_CHELSIO_T4_DCB */
- if (dev->num_tc) {
+ if (netdev_get_num_tc(dev)) {
struct port_info *pi = netdev2pinfo(dev);
u8 ver, proto;
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index 764d2a09668f5..6f1046c9cc515 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -1403,10 +1403,10 @@ static netdev_tx_t __dpaa2_eth_tx(struct sk_buff *skb,
struct dpaa2_eth_fq *fq;
struct netdev_queue *nq;
struct dpaa2_fd *fd;
+ int err, i, num_tc;
u16 queue_mapping;
void *swa = NULL;
u8 prio = 0;
- int err, i;
u32 fd_len;
percpu_stats = this_cpu_ptr(priv->percpu_stats);
@@ -1468,12 +1468,14 @@ static netdev_tx_t __dpaa2_eth_tx(struct sk_buff *skb,
*/
queue_mapping = skb_get_queue_mapping(skb);
- if (net_dev->num_tc) {
+ num_tc = netdev_get_num_tc(net_dev);
+
+ if (num_tc) {
prio = netdev_txq_to_tc(net_dev, queue_mapping);
/* Hardware interprets priority level 0 as being the highest,
* so we need to do a reverse mapping to the netdev tc index
*/
- prio = net_dev->num_tc - prio - 1;
+ prio = num_tc - prio - 1;
/* We have only one FQ array entry for all Tx hardware queues
* with the same flow id (but different priority levels)
*/
@@ -2913,7 +2915,7 @@ static int update_xps(struct dpaa2_eth_priv *priv)
return -ENOMEM;
num_queues = dpaa2_eth_queue_count(priv);
- netdev_queues = (net_dev->num_tc ? : 1) * num_queues;
+ netdev_queues = (netdev_get_num_tc(net_dev) ? : 1) * num_queues;
/* The first <num_queues> entries in priv->fq array are Tx/Tx conf
* queues, so only process those
@@ -2946,7 +2948,7 @@ static int dpaa2_eth_setup_mqprio(struct net_device *net_dev,
num_queues = dpaa2_eth_queue_count(priv);
num_tc = mqprio->num_tc;
- if (num_tc == net_dev->num_tc)
+ if (num_tc == netdev_get_num_tc(net_dev))
return 0;
if (num_tc > dpaa2_eth_tc_count(priv)) {
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
index 52de2bcbadbec..d23a45a34fa3c 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
@@ -182,14 +182,16 @@ static u32 igc_fpe_map_preempt_tc_to_queue(const struct igc_adapter *adapter,
struct net_device *dev = adapter->netdev;
u32 i, queue = 0;
- for (i = 0; i < dev->num_tc; i++) {
+ for (i = 0; i < netdev_get_num_tc(dev); i++) {
+ struct netdev_tc_txq res;
u32 offset, count;
if (!(preemptible_tcs & BIT(i)))
continue;
- offset = dev->tc_to_txq[i].offset;
- count = dev->tc_to_txq[i].count;
+ res.combined = READ_ONCE(dev->tc_to_txq[i].combined);
+ offset = res.offset;
+ count = res.count;
queue |= GENMASK(offset + count - 1, offset);
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 8873a8cc4a185..f91856498eb2d 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -9273,10 +9273,11 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,
if (sb_dev) {
u8 tc = netdev_get_prio_tc_map(dev, skb->priority);
struct net_device *vdev = sb_dev;
+ struct netdev_tc_txq res;
- txq = vdev->tc_to_txq[tc].offset;
- txq += reciprocal_scale(skb_get_hash(skb),
- vdev->tc_to_txq[tc].count);
+ res.combined = READ_ONCE(vdev->tc_to_txq[tc].combined);
+ txq = res.offset;
+ txq += reciprocal_scale(skb_get_hash(skb), res.count);
return txq;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index ca3d7c6b5210e..fc110a7d16e8d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3245,9 +3245,9 @@ static int mlx5e_update_tc_and_tx_queues(struct mlx5e_priv *priv)
int i;
old_num_txqs = netdev->real_num_tx_queues;
- old_ntc = netdev->num_tc ? : 1;
+ old_ntc = netdev_get_num_tc(netdev) ? : 1;
for (i = 0; i < ARRAY_SIZE(old_tc_to_txq); i++)
- old_tc_to_txq[i] = netdev->tc_to_txq[i];
+ old_tc_to_txq[i].combined = READ_ONCE(netdev->tc_to_txq[i].combined);
nch = priv->channels.params.num_channels;
ntc = priv->channels.params.mqprio.num_tc;
diff --git a/drivers/net/ethernet/sfc/falcon/net_driver.h b/drivers/net/ethernet/sfc/falcon/net_driver.h
index 7ab0db44720da..63016bbae115b 100644
--- a/drivers/net/ethernet/sfc/falcon/net_driver.h
+++ b/drivers/net/ethernet/sfc/falcon/net_driver.h
@@ -1208,7 +1208,7 @@ ef4_channel_get_tx_queue(struct ef4_channel *channel, unsigned type)
static inline bool ef4_tx_queue_used(struct ef4_tx_queue *tx_queue)
{
- return !(tx_queue->efx->net_dev->num_tc < 2 &&
+ return !(netdev_get_num_tc(tx_queue->efx->net_dev) < 2 &&
tx_queue->queue & EF4_TXQ_TYPE_HIGHPRI);
}
diff --git a/drivers/net/ethernet/sfc/falcon/tx.c b/drivers/net/ethernet/sfc/falcon/tx.c
index 9e18aaf44badd..2103b6fdf9683 100644
--- a/drivers/net/ethernet/sfc/falcon/tx.c
+++ b/drivers/net/ethernet/sfc/falcon/tx.c
@@ -435,15 +435,19 @@ int ef4_setup_tc(struct net_device *net_dev, enum tc_setup_type type,
mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
- if (num_tc == net_dev->num_tc)
+ if (num_tc == netdev_get_num_tc(net_dev))
return 0;
for (tc = 0; tc < num_tc; tc++) {
- net_dev->tc_to_txq[tc].offset = tc * efx->n_tx_channels;
- net_dev->tc_to_txq[tc].count = efx->n_tx_channels;
+ struct netdev_tc_txq res = {
+ .offset = tc * efx->n_tx_channels,
+ .count = efx->n_tx_channels,
+ };
+
+ WRITE_ONCE(net_dev->tc_to_txq[tc].combined, res.combined);
}
- if (num_tc > net_dev->num_tc) {
+ if (num_tc > netdev_get_num_tc(net_dev)) {
/* Initialise high-priority queues as necessary */
ef4_for_each_channel(channel, efx) {
ef4_for_each_possible_channel_tx_queue(tx_queue,
@@ -462,7 +466,7 @@ int ef4_setup_tc(struct net_device *net_dev, enum tc_setup_type type,
}
} else {
/* Reduce number of classes before number of queues */
- net_dev->num_tc = num_tc;
+ WRITE_ONCE(net_dev->num_tc, num_tc);
}
rc = netif_set_real_num_tx_queues(net_dev,
@@ -477,7 +481,7 @@ int ef4_setup_tc(struct net_device *net_dev, enum tc_setup_type type,
* it to ef4_fini_channels().
*/
- net_dev->num_tc = num_tc;
+ WRITE_ONCE(net_dev->num_tc, num_tc);
return 0;
}
diff --git a/drivers/net/ethernet/sfc/siena/tx.c b/drivers/net/ethernet/sfc/siena/tx.c
index 91e87594ed1ea..67c77d67d9843 100644
--- a/drivers/net/ethernet/sfc/siena/tx.c
+++ b/drivers/net/ethernet/sfc/siena/tx.c
@@ -376,15 +376,19 @@ int efx_siena_setup_tc(struct net_device *net_dev, enum tc_setup_type type,
mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
- if (num_tc == net_dev->num_tc)
+ if (num_tc == netdev_get_num_tc(net_dev))
return 0;
for (tc = 0; tc < num_tc; tc++) {
- net_dev->tc_to_txq[tc].offset = tc * efx->n_tx_channels;
- net_dev->tc_to_txq[tc].count = efx->n_tx_channels;
+ struct netdev_tc_txq res = {
+ .offset = tc * efx->n_tx_channels,
+ .count = efx->n_tx_channels,
+ };
+
+ WRITE_ONCE(net_dev->tc_to_txq[tc].combined, res.combined);
}
- net_dev->num_tc = num_tc;
+ WRITE_ONCE(net_dev->num_tc, num_tc);
return netif_set_real_num_tx_queues(net_dev,
max_t(int, num_tc, 1) *
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
index c54c702243517..c889204a7aa5d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
@@ -217,8 +217,11 @@ int dwmac5_fpe_map_preemption_class(struct net_device *ndev,
* and is direct one-to-one mapping."
*/
for (u32 tc = 0; tc < num_tc; tc++) {
- count = ndev->tc_to_txq[tc].count;
- offset = ndev->tc_to_txq[tc].offset;
+ struct netdev_tc_txq res;
+
+ res.combined = READ_ONCE(ndev->tc_to_txq[tc].combined);
+ count = res.count;
+ offset = res.offset;
if (pclass & BIT(tc))
preemptible_txqs |= GENMASK(offset + count - 1, offset);
@@ -275,8 +278,11 @@ int dwxgmac3_fpe_map_preemption_class(struct net_device *ndev,
* any of the scheduling algorithms."
*/
for (u32 tc = 0; tc < num_tc; tc++) {
- count = ndev->tc_to_txq[tc].count;
- offset = ndev->tc_to_txq[tc].offset;
+ struct netdev_tc_txq res;
+
+ res.combined = READ_ONCE(ndev->tc_to_txq[tc].combined);
+ count = res.count;
+ offset = res.offset;
if (pclass & BIT(tc))
preemptible_txqs |= GENMASK(offset + count - 1, offset);
diff --git a/drivers/net/ethernet/ti/cpsw_priv.c b/drivers/net/ethernet/ti/cpsw_priv.c
index 1f6f374551cb6..0580a7885d339 100644
--- a/drivers/net/ethernet/ti/cpsw_priv.c
+++ b/drivers/net/ethernet/ti/cpsw_priv.c
@@ -949,7 +949,7 @@ static int cpsw_set_cbs(struct net_device *ndev,
* limited first and for compliance with CPDMA rate limited channels
* that also used in bacward order. FIFO0 cannot be rate limited.
*/
- fifo = cpsw_tc_to_fifo(tc, ndev->num_tc);
+ fifo = cpsw_tc_to_fifo(tc, netdev_get_num_tc(ndev));
if (!fifo) {
dev_err(priv->dev, "Last tc%d can't be rate limited", tc);
return -EINVAL;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index db9dce7f0aa65..de307c01d33eb 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -832,8 +832,13 @@ struct xps_dev_maps {
#define TC_BITMASK 15
/* HW offloaded queuing disciplines txq count and offset maps */
struct netdev_tc_txq {
- u16 count;
- u16 offset;
+ union {
+ struct {
+ u16 count;
+ u16 offset;
+ };
+ u32 combined;
+ };
};
#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
@@ -2666,16 +2671,16 @@ static inline bool netif_elide_gro(const struct net_device *dev)
static inline
int netdev_get_prio_tc_map(const struct net_device *dev, u32 prio)
{
- return dev->prio_tc_map[prio & TC_BITMASK];
+ return READ_ONCE(dev->prio_tc_map[prio & TC_BITMASK]);
}
static inline
int netdev_set_prio_tc_map(struct net_device *dev, u8 prio, u8 tc)
{
- if (tc >= dev->num_tc)
+ if (tc >= READ_ONCE(dev->num_tc))
return -EINVAL;
- dev->prio_tc_map[prio & TC_BITMASK] = tc & TC_BITMASK;
+ WRITE_ONCE(dev->prio_tc_map[prio & TC_BITMASK], tc & TC_BITMASK);
return 0;
}
@@ -2685,9 +2690,9 @@ int netdev_set_tc_queue(struct net_device *dev, u8 tc, u16 count, u16 offset);
int netdev_set_num_tc(struct net_device *dev, u8 num_tc);
static inline
-int netdev_get_num_tc(struct net_device *dev)
+int netdev_get_num_tc(const struct net_device *dev)
{
- return dev->num_tc;
+ return READ_ONCE(dev->num_tc);
}
static inline void net_prefetch(void *p)
@@ -2714,7 +2719,7 @@ int netdev_bind_sb_channel_queue(struct net_device *dev,
int netdev_set_sb_channel(struct net_device *dev, u16 channel);
static inline int netdev_get_sb_channel(struct net_device *dev)
{
- return max_t(int, -dev->num_tc, 0);
+ return max_t(int, -READ_ONCE(dev->num_tc), 0);
}
static inline
diff --git a/net/core/dev.c b/net/core/dev.c
index fd0b445f5d38c..d52285ac01a54 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2656,13 +2656,15 @@ EXPORT_SYMBOL_GPL(dev_queue_xmit_nit);
*/
static void netif_setup_tc(struct net_device *dev, unsigned int txq)
{
+ struct netdev_tc_txq res;
int i;
- struct netdev_tc_txq *tc = &dev->tc_to_txq[0];
+
+ res.combined = READ_ONCE(dev->tc_to_txq[0].combined);
/* If TC0 is invalidated disable TC mapping */
- if (tc->offset + tc->count > txq) {
+ if (res.offset + res.count > txq) {
netdev_warn(dev, "Number of in use tx queues changed invalidating tc mappings. Priority traffic classification disabled!\n");
- dev->num_tc = 0;
+ WRITE_ONCE(dev->num_tc, 0);
return;
}
@@ -2670,8 +2672,8 @@ static void netif_setup_tc(struct net_device *dev, unsigned int txq)
for (i = 1; i < TC_BITMASK + 1; i++) {
int q = netdev_get_prio_tc_map(dev, i);
- tc = &dev->tc_to_txq[q];
- if (tc->offset + tc->count > txq) {
+ res.combined = READ_ONCE(dev->tc_to_txq[q].combined);
+ if (res.offset + res.count > txq) {
netdev_warn(dev, "Number of in use tx queues changed. Priority %i to tc mapping %i is no longer valid. Setting map to 0\n",
i, q);
netdev_set_prio_tc_map(dev, i, 0);
@@ -2681,13 +2683,16 @@ static void netif_setup_tc(struct net_device *dev, unsigned int txq)
int netdev_txq_to_tc(struct net_device *dev, unsigned int txq)
{
- if (dev->num_tc) {
+ if (READ_ONCE(dev->num_tc)) {
struct netdev_tc_txq *tc = &dev->tc_to_txq[0];
int i;
/* walk through the TCs and see if it falls into any of them */
for (i = 0; i < TC_MAX_QUEUE; i++, tc++) {
- if ((txq - tc->offset) < tc->count)
+ struct netdev_tc_txq res;
+
+ res.combined = READ_ONCE(tc->combined);
+ if ((txq - res.offset) < res.count)
return i;
}
@@ -2880,18 +2885,19 @@ int __netif_set_xps_queue(struct net_device *dev, const unsigned long *mask,
u16 index, enum xps_map_type type)
{
struct xps_dev_maps *dev_maps, *new_dev_maps = NULL, *old_dev_maps = NULL;
+ int maps_sz, num_tc = 1, tc = 0, dev_num_tc;
const unsigned long *online_mask = NULL;
bool active = false, copy = false;
int i, j, tci, numa_node_id = -2;
- int maps_sz, num_tc = 1, tc = 0;
struct xps_map *map, *new_map;
unsigned int nr_ids;
WARN_ON_ONCE(index >= dev->num_tx_queues);
- if (dev->num_tc) {
+ dev_num_tc = READ_ONCE(dev->num_tc);
+ if (dev_num_tc) {
/* Do not allow XPS on subordinate device directly */
- num_tc = dev->num_tc;
+ num_tc = dev_num_tc;
if (num_tc < 0)
return -EINVAL;
@@ -3107,28 +3113,36 @@ static void netdev_unbind_all_sb_channels(struct net_device *dev)
void netdev_reset_tc(struct net_device *dev)
{
+ int i;
+
#ifdef CONFIG_XPS
netif_reset_xps_queues_gt(dev, 0);
#endif
netdev_unbind_all_sb_channels(dev);
/* Reset TC configuration of device */
- dev->num_tc = 0;
- memset(dev->tc_to_txq, 0, sizeof(dev->tc_to_txq));
- memset(dev->prio_tc_map, 0, sizeof(dev->prio_tc_map));
+ WRITE_ONCE(dev->num_tc, 0);
+ for (i = 0; i < TC_MAX_QUEUE; i++)
+ WRITE_ONCE(dev->tc_to_txq[i].combined, 0);
+ for (i = 0; i <= TC_BITMASK; i++)
+ WRITE_ONCE(dev->prio_tc_map[i], 0);
}
EXPORT_SYMBOL(netdev_reset_tc);
int netdev_set_tc_queue(struct net_device *dev, u8 tc, u16 count, u16 offset)
{
- if (tc >= dev->num_tc)
+ struct netdev_tc_txq res = {
+ .count = count,
+ .offset = offset,
+ };
+
+ if (tc >= READ_ONCE(dev->num_tc))
return -EINVAL;
#ifdef CONFIG_XPS
netif_reset_xps_queues(dev, offset, count);
#endif
- dev->tc_to_txq[tc].count = count;
- dev->tc_to_txq[tc].offset = offset;
+ WRITE_ONCE(dev->tc_to_txq[tc].combined, res.combined);
return 0;
}
EXPORT_SYMBOL(netdev_set_tc_queue);
@@ -3143,7 +3157,7 @@ int netdev_set_num_tc(struct net_device *dev, u8 num_tc)
#endif
netdev_unbind_all_sb_channels(dev);
- dev->num_tc = num_tc;
+ WRITE_ONCE(dev->num_tc, num_tc);
return 0;
}
EXPORT_SYMBOL(netdev_set_num_tc);
@@ -3152,12 +3166,15 @@ void netdev_unbind_sb_channel(struct net_device *dev,
struct net_device *sb_dev)
{
struct netdev_queue *txq = &dev->_tx[dev->num_tx_queues];
+ int i;
#ifdef CONFIG_XPS
netif_reset_xps_queues_gt(sb_dev, 0);
#endif
- memset(sb_dev->tc_to_txq, 0, sizeof(sb_dev->tc_to_txq));
- memset(sb_dev->prio_tc_map, 0, sizeof(sb_dev->prio_tc_map));
+ for (i = 0; i < TC_MAX_QUEUE; i++)
+ WRITE_ONCE(sb_dev->tc_to_txq[i].combined, 0);
+ for (i = 0; i <= TC_BITMASK; i++)
+ WRITE_ONCE(sb_dev->prio_tc_map[i], 0);
while (txq-- != &dev->_tx[0]) {
if (txq->sb_dev == sb_dev)
@@ -3171,7 +3188,7 @@ int netdev_bind_sb_channel_queue(struct net_device *dev,
u8 tc, u16 count, u16 offset)
{
/* Make certain the sb_dev and dev are already configured */
- if (sb_dev->num_tc >= 0 || tc >= dev->num_tc)
+ if (READ_ONCE(sb_dev->num_tc) >= 0 || tc >= READ_ONCE(dev->num_tc))
return -EINVAL;
/* We cannot hand out queues we don't have */
@@ -3179,8 +3196,12 @@ int netdev_bind_sb_channel_queue(struct net_device *dev,
return -EINVAL;
/* Record the mapping */
- sb_dev->tc_to_txq[tc].count = count;
- sb_dev->tc_to_txq[tc].offset = offset;
+ struct netdev_tc_txq res = {
+ .count = count,
+ .offset = offset,
+ };
+
+ WRITE_ONCE(sb_dev->tc_to_txq[tc].combined, res.combined);
/* Provide a way for Tx queue to find the tc_to_txq map or
* XPS map for itself.
@@ -3206,7 +3227,7 @@ int netdev_set_sb_channel(struct net_device *dev, u16 channel)
if (channel > S16_MAX)
return -EINVAL;
- dev->num_tc = -channel;
+ WRITE_ONCE(dev->num_tc, -channel);
return 0;
}
@@ -3235,7 +3256,7 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
if (rc)
return rc;
- if (dev->num_tc)
+ if (READ_ONCE(dev->num_tc))
netif_setup_tc(dev, txq);
net_shaper_set_real_num_tx_queues(dev, txq);
@@ -3544,11 +3565,13 @@ static u16 skb_tx_hash(const struct net_device *dev,
u16 qoffset = 0;
u16 qcount = dev->real_num_tx_queues;
- if (dev->num_tc) {
+ if (READ_ONCE(dev->num_tc)) {
u8 tc = netdev_get_prio_tc_map(dev, skb->priority);
+ struct netdev_tc_txq res;
- qoffset = sb_dev->tc_to_txq[tc].offset;
- qcount = sb_dev->tc_to_txq[tc].count;
+ res.combined = READ_ONCE(sb_dev->tc_to_txq[tc].combined);
+ qoffset = res.offset;
+ qcount = res.count;
if (unlikely(!qcount)) {
net_warn_ratelimited("%s: invalid qcount, qoffset %u for tc %u\n",
sb_dev->name, qoffset, tc);
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 25546deacec80..352173df75785 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -1432,7 +1432,7 @@ static ssize_t traffic_class_show(struct kobject *kobj, struct attribute *attr,
/* If queue belongs to subordinate dev use its TC mapping */
dev = netdev_get_tx_queue(dev, index)->sb_dev ? : dev;
- num_tc = dev->num_tc;
+ num_tc = READ_ONCE(dev->num_tc);
tc = netdev_txq_to_tc(dev, index);
rtnl_unlock();
diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c
index ae991fc25b43f..6ced7008ef5c8 100644
--- a/net/sched/sch_mqprio.c
+++ b/net/sched/sch_mqprio.c
@@ -679,12 +679,14 @@ static int mqprio_dump_class_stats(struct Qdisc *sch, unsigned long cl,
rcu_read_lock();
if (cl >= TC_H_MIN_PRIORITY) {
struct net_device *dev = qdisc_dev(sch);
- struct netdev_tc_txq tc = dev->tc_to_txq[cl & TC_BITMASK];
+ struct netdev_tc_txq tc;
struct gnet_stats_queue qstats = {0};
struct gnet_stats_basic_sync bstats;
u32 qlen = 0;
int i;
+ tc.combined = READ_ONCE(dev->tc_to_txq[cl & TC_BITMASK].combined);
+
gnet_stats_basic_sync_init(&bstats);
for (i = tc.offset; i < tc.offset + tc.count; i++) {
diff --git a/net/sched/sch_mqprio_lib.c b/net/sched/sch_mqprio_lib.c
index b3a5572c167b7..888935e34d438 100644
--- a/net/sched/sch_mqprio_lib.c
+++ b/net/sched/sch_mqprio_lib.c
@@ -105,11 +105,15 @@ void mqprio_qopt_reconstruct(struct net_device *dev, struct tc_mqprio_qopt *qopt
int tc, num_tc = netdev_get_num_tc(dev);
qopt->num_tc = num_tc;
- memcpy(qopt->prio_tc_map, dev->prio_tc_map, sizeof(qopt->prio_tc_map));
+ for (tc = 0; tc <= TC_BITMASK; tc++)
+ qopt->prio_tc_map[tc] = netdev_get_prio_tc_map(dev, tc);
for (tc = 0; tc < num_tc; tc++) {
- qopt->count[tc] = dev->tc_to_txq[tc].count;
- qopt->offset[tc] = dev->tc_to_txq[tc].offset;
+ struct netdev_tc_txq res;
+
+ res.combined = READ_ONCE(dev->tc_to_txq[tc].combined);
+ qopt->count[tc] = res.count;
+ qopt->offset[tc] = res.offset;
}
}
EXPORT_SYMBOL_GPL(mqprio_qopt_reconstruct);
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index 299234a5f0fe6..39ac5b97aa3af 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -762,12 +762,13 @@ static struct sk_buff *taprio_dequeue_from_txq(struct Qdisc *sch, int txq,
static void taprio_next_tc_txq(struct net_device *dev, int tc, int *txq)
{
- int offset = dev->tc_to_txq[tc].offset;
- int count = dev->tc_to_txq[tc].count;
+ struct netdev_tc_txq res;
+
+ res.combined = READ_ONCE(dev->tc_to_txq[tc].combined);
(*txq)++;
- if (*txq == offset + count)
- *txq = offset;
+ if (*txq == res.offset + res.count)
+ *txq = res.offset;
}
/* Prioritize higher traffic classes, and select among TXQs belonging to the
@@ -1184,7 +1185,7 @@ static int taprio_parse_mqprio_opt(struct net_device *dev,
bool allow_overlapping_txqs = TXTIME_ASSIST_IS_ENABLED(taprio_flags);
if (!qopt) {
- if (!dev->num_tc) {
+ if (!netdev_get_num_tc(dev)) {
NL_SET_ERR_MSG(extack, "'mqprio' configuration is necessary");
return -EINVAL;
}
@@ -1438,18 +1439,18 @@ static void taprio_offload_config_changed(struct taprio_sched *q)
static u32 tc_map_to_queue_mask(struct net_device *dev, u32 tc_mask)
{
+ int num_tc = netdev_get_num_tc(dev);
u32 i, queue_mask = 0;
- for (i = 0; i < dev->num_tc; i++) {
- u32 offset, count;
+ for (i = 0; i < num_tc; i++) {
+ struct netdev_tc_txq res;
if (!(tc_mask & BIT(i)))
continue;
- offset = dev->tc_to_txq[i].offset;
- count = dev->tc_to_txq[i].count;
+ res.combined = READ_ONCE(dev->tc_to_txq[i].combined);
- queue_mask |= GENMASK(offset + count - 1, offset);
+ queue_mask |= GENMASK(res.offset + res.count - 1, res.offset);
}
return queue_mask;
@@ -1799,16 +1800,20 @@ static int taprio_mqprio_cmp(const struct net_device *dev,
{
int i;
- if (!mqprio || mqprio->num_tc != dev->num_tc)
+ if (!mqprio || mqprio->num_tc != netdev_get_num_tc(dev))
return -1;
- for (i = 0; i < mqprio->num_tc; i++)
- if (dev->tc_to_txq[i].count != mqprio->count[i] ||
- dev->tc_to_txq[i].offset != mqprio->offset[i])
+ for (i = 0; i < mqprio->num_tc; i++) {
+ struct netdev_tc_txq res;
+
+ res.combined = READ_ONCE(dev->tc_to_txq[i].combined);
+ if (res.count != mqprio->count[i] ||
+ res.offset != mqprio->offset[i])
return -1;
+ }
for (i = 0; i <= TC_BITMASK; i++)
- if (dev->prio_tc_map[i] != mqprio->prio_tc_map[i])
+ if (netdev_get_prio_tc_map(dev, i) != mqprio->prio_tc_map[i])
return -1;
return 0;
|
| 3/2 | 2026/08/12 09:29 | llm | patch-evaluator |
47mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12266 output: 24 thoughts: 923 Thoughts: **Fuzzing Target Identification: Traffic Class and TXQ Synchronization** Okay, so we have this patch that's trying to eliminate data races in how traffic class and transmit queue information is accessed within the `net_device` struct. They're using `READ_ONCE` and `WRITE_ONCE`, and introducing this atomic `combined` field in `netdev_tc_txq`. This touches a bunch of stuff, the core networking stack itself and even driver-specific code, so definitely sounds like a place fuzzing could find something interesting. Looking at the changes, it seems like these modifications are centered around functions involved in configuring and using traffic classes and transmit queues. Functions like `netdev_txq_to_tc`, `netdev_set_tc_queue` etc. are the ones modified, and are accessible through user-space with `tc` commands and are also invoked during normal packet processing. Definitely a good target. Now, let's nail down which symbols to focus on. We've got a list of the modified functions, and I want to avoid anything that's *too* performance-critical, like `skb_tx_hash`, or the hot-path functions like `taprio_dequeue_from_txq`. So, the main ones I'm seeing as good initial targets are: `netdev_set_tc_queue`, `netdev_set_num_tc`, `netdev_bind_sb_channel_queue`, `netdev_set_sb_channel`, `netdev_reset_tc`, `__netif_set_xps_queue`, `mqprio_qopt_reconstruct`, and `taprio_parse_mqprio_opt`. Wait a minute, checking those focus symbols. Looks like a few of these are exported symbols! `netdev_set_tc_queue`, `netdev_set_num_tc`, `netdev_bind_sb_channel_queue`, `netdev_set_sb_channel`, `netdev_reset_tc`, and `mqprio_qopt_reconstruct` are all `EXPORT_SYMBOL` or `EXPORT_SYMBOL_GPL`. And, looking a little more closely, `__netif_set_xps_queue` isn't static either. Interesting. But then I have to go check `taprio_parse_mqprio_opt` because that one's static. |
| 4/2 | 2026/08/12 10:17 | tool | grepper |
0mArgs:{
"Expression": "taprio_parse_mqprio_opt"
}Results: {
"Output": "net/sched/sch_taprio.c=1129=static int parse_taprio_schedule(struct taprio_sched *q, struct nlattr **tb,\n--\nnet/sched/sch_taprio.c-1179-\nnet/sched/sch_taprio.c:1180:static int taprio_parse_mqprio_opt(struct net_device *dev,\nnet/sched/sch_taprio.c-1181-\t\t\t\t struct tc_mqprio_qopt *qopt,\n--\nnet/sched/sch_taprio.c=1822=static int taprio_change(struct Qdisc *sch, struct nlattr *opt,\n--\nnet/sched/sch_taprio.c-1871-\nnet/sched/sch_taprio.c:1872:\terr = taprio_parse_mqprio_opt(dev, mqprio, extack, q-\u003eflags);\nnet/sched/sch_taprio.c-1873-\tif (err \u003c 0)\n"
} |
| 5/2 | 2026/08/12 10:17 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 13999 output: 23 thoughts: 132 Thoughts: Okay, here's my assessment of the situation: **Refactoring Static Functions in MQPRIO Context** Right, so I'm looking at these functions within the MQPRIO context, and I've identified a couple of static ones that need attention. Specifically, I was considering `taprio_parse_mqprio_opt`, but it's static, so that's a non-starter. I need something that offers the same functionality, but is accessible. I think I'll pivot to `taprio_change` instead. That seems like a more appropriate replacement, given the restrictions. Then, there's `mqprio_dump_class_stats`. That one's also static, which presents the same challenge. I initially thought I could use the caller of `mqprio_dump_class_stats`, but it still seems less than ideal. Or perhaps I could just use `mqprio_dump_class`? Hmm. Wait a minute... `mqprio_dump_class_stats` is static, yes, *but* it's actually a callback. That changes things! Given that, I'm just going to go ahead and use `mqprio_qopt_reconstruct`. That seems like the cleanest and most direct path to what I need. Okay, now let's make sure `mqprio_qopt_reconstruct` does what I think it does. Let me check that. |
| 6/2 | 2026/08/12 10:17 | tool | grepper |
0mArgs:{
"Expression": "mqprio_qopt_reconstruct"
}Results: {
"Output": "net/sched/sch_mqprio.c=552=static int mqprio_dump(struct Qdisc *sch, struct sk_buff *skb)\n--\nnet/sched/sch_mqprio.c-595-\nnet/sched/sch_mqprio.c:596:\tmqprio_qopt_reconstruct(dev, \u0026opt);\nnet/sched/sch_mqprio.c-597-\topt.hw = priv-\u003ehw_offload;\n--\nnet/sched/sch_mqprio_lib.c=101=EXPORT_SYMBOL_GPL(mqprio_validate_qopt);\nnet/sched/sch_mqprio_lib.c-102-\nnet/sched/sch_mqprio_lib.c:103:void mqprio_qopt_reconstruct(struct net_device *dev, struct tc_mqprio_qopt *qopt)\nnet/sched/sch_mqprio_lib.c-104-{\n--\nnet/sched/sch_mqprio_lib.c-118-}\nnet/sched/sch_mqprio_lib.c:119:EXPORT_SYMBOL_GPL(mqprio_qopt_reconstruct);\nnet/sched/sch_mqprio_lib.c-120-\n--\nnet/sched/sch_mqprio_lib.h=11=int mqprio_validate_qopt(struct net_device *dev, struct tc_mqprio_qopt *qopt,\n--\nnet/sched/sch_mqprio_lib.h-14-\t\t\t struct netlink_ext_ack *extack);\nnet/sched/sch_mqprio_lib.h:15:void mqprio_qopt_reconstruct(struct net_device *dev,\nnet/sched/sch_mqprio_lib.h-16-\t\t\t struct tc_mqprio_qopt *qopt);\n--\nnet/sched/sch_taprio.c=1516=static int taprio_enable_offload(struct net_device *dev,\n--\nnet/sched/sch_taprio.c-1552-\toffload-\u003eextack = extack;\nnet/sched/sch_taprio.c:1553:\tmqprio_qopt_reconstruct(dev, \u0026offload-\u003emqprio.qopt);\nnet/sched/sch_taprio.c-1554-\toffload-\u003emqprio.extack = extack;\n--\nnet/sched/sch_taprio.c=2392=static int taprio_dump(struct Qdisc *sch, struct sk_buff *skb)\n--\nnet/sched/sch_taprio.c-2400-\nnet/sched/sch_taprio.c:2401:\tmqprio_qopt_reconstruct(dev, \u0026opt);\nnet/sched/sch_taprio.c-2402-\n"
} |
| 7/2 | 2026/08/12 10:17 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 15192 output: 27 thoughts: 35 Thoughts: Okay, here's my take on those thoughts, framed as my own: **Analyzing Queue Optimization** Alright, it looks like `mqprio_qopt_reconstruct` is performing well, that's good news. Now, I want to pivot and assess another key function that plays a role in TX queue management. I need to take a look at `netif_set_real_num_tx_queues` and see how it interacts with the current setup. I'm especially interested in understanding the interplay between these functions and how they influence overall performance. |
| 8/2 | 2026/08/12 10:17 | tool | grepper |
0mArgs:{
"Expression": "netif_set_real_num_tx_queues"
}Results: {
"Output": "\nFull output is too long, showing 500 out of 699 lines.\nUse more precise expression if possible.\n\nDocumentation/networking/netdevices.rst=381=Commonly used core helpers which force drivers to selectively opt-in to\nDocumentation/networking/netdevices.rst-382-``rtnl_lock`` protection include ``netdev_update_features()``,\nDocumentation/networking/netdevices.rst:383:``netif_set_real_num_tx_queues()``, and phylink helpers.\nDocumentation/networking/netdevices.rst-384-\n--\ndrivers/infiniband/ulp/ipoib/ipoib_main.c=555=int ipoib_set_mode(struct net_device *dev, const char *buf)\n--\ndrivers/infiniband/ulp/ipoib/ipoib_main.c-573-\t\tnetif_set_mtu(dev, ipoib_cm_max_mtu(dev));\ndrivers/infiniband/ulp/ipoib/ipoib_main.c:574:\t\tnetif_set_real_num_tx_queues(dev, 1);\ndrivers/infiniband/ulp/ipoib/ipoib_main.c-575-\t\tnetdev_unlock_ops(dev);\n--\ndrivers/infiniband/ulp/ipoib/ipoib_main.c-587-\t\tnetif_set_mtu(dev, min(priv-\u003emcast_mtu, dev-\u003emtu));\ndrivers/infiniband/ulp/ipoib/ipoib_main.c:588:\t\tnetif_set_real_num_tx_queues(dev, dev-\u003enum_tx_queues);\ndrivers/infiniband/ulp/ipoib/ipoib_main.c-589-\t\tnetdev_unlock_ops(dev);\n--\ndrivers/infiniband/ulp/ipoib/ipoib_main.c=2275=int ipoib_intf_init(struct ib_device *hca, u32 port, const char *name,\n--\ndrivers/infiniband/ulp/ipoib/ipoib_main.c-2299-\ndrivers/infiniband/ulp/ipoib/ipoib_main.c:2300:\t\trc = netif_set_real_num_tx_queues(dev, 1);\ndrivers/infiniband/ulp/ipoib/ipoib_main.c-2301-\t\tif (rc)\n--\ndrivers/net/ethernet/airoha/airoha_eth.c=2917=static int airoha_tc_htb_alloc_leaf_queue(struct net_device *netdev,\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-2939-\tif (num_tx_queues \u003e netdev-\u003ereal_num_tx_queues) {\ndrivers/net/ethernet/airoha/airoha_eth.c:2940:\t\terr = netif_set_real_num_tx_queues(netdev, num_tx_queues);\ndrivers/net/ethernet/airoha/airoha_eth.c-2941-\t\tif (err) {\n--\ndrivers/net/ethernet/airoha/airoha_eth.c=3135=static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue)\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-3149-\t\t\t\t\t AIROHA_NUM_QOS_CHANNELS) + 1;\ndrivers/net/ethernet/airoha/airoha_eth.c:3150:\tnetif_set_real_num_tx_queues(netdev, num_tx_queues);\ndrivers/net/ethernet/airoha/airoha_eth.c-3151-}\n--\ndrivers/net/ethernet/airoha/airoha_eth.c=3412=static int airoha_alloc_gdm_device(struct airoha_eth *eth,\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-3440-\t/* reserve hw queues for HTB offloading */\ndrivers/net/ethernet/airoha/airoha_eth.c:3441:\terr = netif_set_real_num_tx_queues(netdev, AIROHA_NUM_TX_RING);\ndrivers/net/ethernet/airoha/airoha_eth.c-3442-\tif (err)\n--\ndrivers/net/ethernet/amazon/ena/ena_netdev.c=2288=static int ena_open(struct net_device *netdev)\n--\ndrivers/net/ethernet/amazon/ena/ena_netdev.c-2293-\t/* Notify the stack of the actual queue counts. */\ndrivers/net/ethernet/amazon/ena/ena_netdev.c:2294:\trc = netif_set_real_num_tx_queues(netdev, adapter-\u003enum_io_queues);\ndrivers/net/ethernet/amazon/ena/ena_netdev.c-2295-\tif (rc) {\n--\ndrivers/net/ethernet/amd/xgbe/xgbe-drv.c=1253=static int xgbe_start(struct xgbe_prv_data *pdata)\n--\ndrivers/net/ethernet/amd/xgbe/xgbe-drv.c-1261-\t/* Set the number of queues */\ndrivers/net/ethernet/amd/xgbe/xgbe-drv.c:1262:\tret = netif_set_real_num_tx_queues(netdev, pdata-\u003etx_ring_count);\ndrivers/net/ethernet/amd/xgbe/xgbe-drv.c-1263-\tif (ret) {\n--\ndrivers/net/ethernet/apm/xgene/xgene_enet_main.c=991=static int xgene_enet_open(struct net_device *ndev)\n--\ndrivers/net/ethernet/apm/xgene/xgene_enet_main.c-996-\ndrivers/net/ethernet/apm/xgene/xgene_enet_main.c:997:\tret = netif_set_real_num_tx_queues(ndev, pdata-\u003etxq_cnt);\ndrivers/net/ethernet/apm/xgene/xgene_enet_main.c-998-\tif (ret)\n--\ndrivers/net/ethernet/aquantia/atlantic/aq_nic.c=495=int aq_nic_start(struct aq_nic_s *self)\n--\ndrivers/net/ethernet/aquantia/atlantic/aq_nic.c-584-\ndrivers/net/ethernet/aquantia/atlantic/aq_nic.c:585:\terr = netif_set_real_num_tx_queues(self-\u003endev,\ndrivers/net/ethernet/aquantia/atlantic/aq_nic.c-586-\t\t\t\t\t self-\u003eaq_vecs * cfg-\u003etcs);\n--\ndrivers/net/ethernet/atheros/alx/main.c=1201=static int __alx_open(struct alx_priv *alx, bool resume)\n--\ndrivers/net/ethernet/atheros/alx/main.c-1234-\ndrivers/net/ethernet/atheros/alx/main.c:1235:\tnetif_set_real_num_tx_queues(alx-\u003edev, alx-\u003enum_txq);\ndrivers/net/ethernet/atheros/alx/main.c-1236-\tnetif_set_real_num_rx_queues(alx-\u003edev, alx-\u003enum_rxq);\n--\ndrivers/net/ethernet/broadcom/bcmsysport.c=2301=static int bcm_sysport_map_queues(struct net_device *dev,\n--\ndrivers/net/ethernet/broadcom/bcmsysport.c-2324-\tif (priv-\u003eis_lite)\ndrivers/net/ethernet/broadcom/bcmsysport.c:2325:\t\tnetif_set_real_num_tx_queues(slave_dev,\ndrivers/net/ethernet/broadcom/bcmsysport.c-2326-\t\t\t\t\t slave_dev-\u003enum_tx_queues / 2);\n--\ndrivers/net/ethernet/broadcom/bnx2.c=6310=bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)\n--\ndrivers/net/ethernet/broadcom/bnx2.c-6355-\ndrivers/net/ethernet/broadcom/bnx2.c:6356:\tnetif_set_real_num_tx_queues(bp-\u003edev, bp-\u003enum_tx_rings);\ndrivers/net/ethernet/broadcom/bnx2.c-6357-\n--\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c=1993=static int bnx2x_set_real_num_queues(struct bnx2x *bp, int include_cnic)\n--\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c-2005-\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c:2006:\trc = netif_set_real_num_tx_queues(bp-\u003edev, tx);\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c-2007-\tif (rc) {\n--\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c=11349=static int bnxt_set_real_num_queues(struct bnxt *bp)\n--\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c-11353-\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c:11354:\trc = netif_set_real_num_tx_queues(dev, bp-\u003etx_nr_rings -\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c-11355-\t\t\t\t\t bp-\u003etx_nr_rings_xdp);\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=3968=static int bcmgenet_probe(struct platform_device *pdev)\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-4119-\t/* setup number of real queues + 1 */\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:4120:\tnetif_set_real_num_tx_queues(priv-\u003edev, priv-\u003ehw_params-\u003etx_queues + 1);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-4121-\tnetif_set_real_num_rx_queues(priv-\u003edev, priv-\u003ehw_params-\u003erx_queues + 1);\n--\ndrivers/net/ethernet/broadcom/tg3.c=11541=static bool tg3_enable_msix(struct tg3 *tp)\n--\ndrivers/net/ethernet/broadcom/tg3.c-11594-\ndrivers/net/ethernet/broadcom/tg3.c:11595:\tnetif_set_real_num_tx_queues(tp-\u003edev, tp-\u003etxq_cnt);\ndrivers/net/ethernet/broadcom/tg3.c-11596-\n--\ndrivers/net/ethernet/broadcom/tg3.c=11600=static void tg3_ints_init(struct tg3 *tp)\n--\ndrivers/net/ethernet/broadcom/tg3.c-11633-\t\ttp-\u003erxq_cnt = 1;\ndrivers/net/ethernet/broadcom/tg3.c:11634:\t\tnetif_set_real_num_tx_queues(tp-\u003edev, 1);\ndrivers/net/ethernet/broadcom/tg3.c-11635-\t\tnetif_set_real_num_rx_queues(tp-\u003edev, 1);\n--\ndrivers/net/ethernet/cavium/liquidio/lio_ethtool.c=1085=static int lio_reset_queues(struct net_device *netdev, uint32_t num_qs)\n--\ndrivers/net/ethernet/cavium/liquidio/lio_ethtool.c-1121-\ndrivers/net/ethernet/cavium/liquidio/lio_ethtool.c:1122:\t\tret = netif_set_real_num_tx_queues(netdev, num_qs);\ndrivers/net/ethernet/cavium/liquidio/lio_ethtool.c-1123-\t\tif (ret) {\n--\ndrivers/net/ethernet/cavium/liquidio/lio_main.c=3322=static int setup_nic_devices(struct octeon_device *octeon_dev)\n--\ndrivers/net/ethernet/cavium/liquidio/lio_main.c-3530-\ndrivers/net/ethernet/cavium/liquidio/lio_main.c:3531:\t\tretval = netif_set_real_num_tx_queues(netdev, num_iqueues);\ndrivers/net/ethernet/cavium/liquidio/lio_main.c-3532-\t\tif (retval) {\n--\ndrivers/net/ethernet/cavium/thunder/nicvf_main.c=491=int nicvf_set_real_num_queues(struct net_device *netdev,\n--\ndrivers/net/ethernet/cavium/thunder/nicvf_main.c-495-\ndrivers/net/ethernet/cavium/thunder/nicvf_main.c:496:\terr = netif_set_real_num_tx_queues(netdev, tx_queues);\ndrivers/net/ethernet/cavium/thunder/nicvf_main.c-497-\tif (err) {\n--\ndrivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c=1417=static int cxgb_open(struct net_device *dev)\n--\ndrivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c-1433-\ndrivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c:1434:\tnetif_set_real_num_tx_queues(dev, pi-\u003enqsets);\ndrivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c-1435-\terr = netif_set_real_num_rx_queues(dev, pi-\u003enqsets);\n--\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c=6571=static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)\n--\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c-7003-\t\tadapter-\u003eport[i]-\u003edev_port = pi-\u003elport;\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c:7004:\t\tnetif_set_real_num_tx_queues(adapter-\u003eport[i], pi-\u003enqsets);\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c-7005-\t\tnetif_set_real_num_rx_queues(adapter-\u003eport[i], pi-\u003enqsets);\n--\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c=424=static int cxgb4_mqprio_enable_offload(struct net_device *dev,\n--\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c-497-\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c:498:\tret = netif_set_real_num_tx_queues(dev, tot_qcount);\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c-499-\tif (ret)\n--\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c=528=static void cxgb4_mqprio_disable_offload(struct net_device *dev)\n--\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c-542-\tnetdev_reset_tc(dev);\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c:543:\tnetif_set_real_num_tx_queues(dev, pi-\u003enqsets);\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c-544-\n--\ndrivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c=2895=static int cxgb4vf_pci_probe(struct pci_dev *pdev,\n--\ndrivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c-3177-\ndrivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c:3178:\t\tnetif_set_real_num_tx_queues(netdev, pi-\u003enqsets);\ndrivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c-3179-\t\tnetif_set_real_num_rx_queues(netdev, pi-\u003enqsets);\n--\ndrivers/net/ethernet/cisco/enic/enic_main.c=2675=static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)\n--\ndrivers/net/ethernet/cisco/enic/enic_main.c-2852-\ndrivers/net/ethernet/cisco/enic/enic_main.c:2853:\tnetif_set_real_num_tx_queues(netdev, enic-\u003ewq_count);\ndrivers/net/ethernet/cisco/enic/enic_main.c-2854-\tnetif_set_real_num_rx_queues(netdev, enic-\u003erq_count);\n--\ndrivers/net/ethernet/emulex/benet/be_main.c=4642=static int be_setup_queues(struct be_adapter *adapter)\n--\ndrivers/net/ethernet/emulex/benet/be_main.c-4666-\ndrivers/net/ethernet/emulex/benet/be_main.c:4667:\tstatus = netif_set_real_num_tx_queues(netdev, adapter-\u003enum_tx_qs);\ndrivers/net/ethernet/emulex/benet/be_main.c-4668-\tif (status)\n--\ndrivers/net/ethernet/engleder/tsnep_main.c=2019=static int tsnep_netdev_open(struct net_device *netdev)\n--\ndrivers/net/ethernet/engleder/tsnep_main.c-2040-\ndrivers/net/ethernet/engleder/tsnep_main.c:2041:\tretval = netif_set_real_num_tx_queues(adapter-\u003enetdev,\ndrivers/net/ethernet/engleder/tsnep_main.c-2042-\t\t\t\t\t adapter-\u003enum_tx_queues);\n--\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c=369=static int dpaa_setup_tc(struct net_device *net_dev, enum tc_setup_type type,\n--\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c-405-\tpriv-\u003enum_tc = num_tc ? : 1;\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c:406:\tnetif_set_real_num_tx_queues(net_dev, priv-\u003enum_tc * num_txqs_per_tc);\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c-407-\treturn 0;\n--\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c=3304=static int dpaa_eth_probe(struct platform_device *pdev)\n--\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c-3506-\tpriv-\u003enum_tc = 1;\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c:3507:\tnetif_set_real_num_tx_queues(net_dev,\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c-3508-\t\t\t\t priv-\u003enum_tc * dpaa_num_txqs_per_tc());\n--\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c=2940=static int dpaa2_eth_setup_mqprio(struct net_device *net_dev,\n--\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c-2961-\t\tnetdev_reset_tc(net_dev);\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c:2962:\t\tnetif_set_real_num_tx_queues(net_dev, num_queues);\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c-2963-\t\tgoto out;\n--\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c-2966-\tnetdev_set_num_tc(net_dev, num_tc);\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c:2967:\tnetif_set_real_num_tx_queues(net_dev, num_tc * num_queues);\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c-2968-\n--\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c=4559=static int dpaa2_eth_netdev_init(struct net_device *net_dev)\n--\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c-4594-\tnum_queues = dpaa2_eth_queue_count(priv);\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c:4595:\terr = netif_set_real_num_tx_queues(net_dev, num_queues);\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c-4596-\tif (err) {\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c:4597:\t\tdev_err(dev, \"netif_set_real_num_tx_queues() failed\\n\");\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c-4598-\t\treturn err;\n--\ndrivers/net/ethernet/freescale/enetc/enetc.c=3153=void enetc_reset_tc_mqprio(struct net_device *ndev)\n--\ndrivers/net/ethernet/freescale/enetc/enetc.c-3163-\tnetdev_reset_tc(ndev);\ndrivers/net/ethernet/freescale/enetc/enetc.c:3164:\tnetif_set_real_num_tx_queues(ndev, num_stack_tx_queues);\ndrivers/net/ethernet/freescale/enetc/enetc.c-3165-\tpriv-\u003emin_num_stack_tx_queues = num_possible_cpus();\n--\ndrivers/net/ethernet/freescale/enetc/enetc.c=3180=int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)\n--\ndrivers/net/ethernet/freescale/enetc/enetc.c-3223-\ndrivers/net/ethernet/freescale/enetc/enetc.c:3224:\terr = netif_set_real_num_tx_queues(ndev, num_stack_tx_queues);\ndrivers/net/ethernet/freescale/enetc/enetc.c-3225-\tif (err)\n--\ndrivers/net/ethernet/freescale/enetc/enetc.c=3242=static int enetc_reconfigure_xdp_cb(struct enetc_ndev_priv *priv, void *ctx)\n--\ndrivers/net/ethernet/freescale/enetc/enetc.c-3250-\tnum_stack_tx_queues = enetc_num_stack_tx_queues(priv);\ndrivers/net/ethernet/freescale/enetc/enetc.c:3251:\terr = netif_set_real_num_tx_queues(priv-\u003endev, num_stack_tx_queues);\ndrivers/net/ethernet/freescale/enetc/enetc.c-3252-\tif (err) {\n--\ndrivers/net/ethernet/freescale/enetc/enetc.c=3554=int enetc_alloc_msix(struct enetc_ndev_priv *priv)\n--\ndrivers/net/ethernet/freescale/enetc/enetc.c-3588-\ndrivers/net/ethernet/freescale/enetc/enetc.c:3589:\terr = netif_set_real_num_tx_queues(priv-\u003endev, num_stack_tx_queues);\ndrivers/net/ethernet/freescale/enetc/enetc.c-3590-\tif (err)\n--\ndrivers/net/ethernet/fungible/funeth/funeth_main.c=1450=void fun_set_ring_count(struct net_device *netdev, unsigned int ntx,\n--\ndrivers/net/ethernet/fungible/funeth/funeth_main.c-1452-{\ndrivers/net/ethernet/fungible/funeth/funeth_main.c:1453:\tnetif_set_real_num_tx_queues(netdev, ntx);\ndrivers/net/ethernet/fungible/funeth/funeth_main.c-1454-\tif (nrx != netdev-\u003ereal_num_rx_queues) {\n--\ndrivers/net/ethernet/fungible/funeth/funeth_main.c=1549=static void fun_queue_defaults(struct net_device *dev, unsigned int nsqs)\n--\ndrivers/net/ethernet/fungible/funeth/funeth_main.c-1562-\ndrivers/net/ethernet/fungible/funeth/funeth_main.c:1563:\tnetif_set_real_num_tx_queues(dev, ntx);\ndrivers/net/ethernet/fungible/funeth/funeth_main.c-1564-\tnetif_set_real_num_rx_queues(dev, nrx);\n--\ndrivers/net/ethernet/fungible/funeth/funeth_main.c=1610=int fun_change_num_queues(struct net_device *dev, unsigned int ntx,\n--\ndrivers/net/ethernet/fungible/funeth/funeth_main.c-1661-\tif (ntx \u003c dev-\u003ereal_num_tx_queues)\ndrivers/net/ethernet/fungible/funeth/funeth_main.c:1662:\t\tnetif_set_real_num_tx_queues(dev, ntx);\ndrivers/net/ethernet/fungible/funeth/funeth_main.c-1663-\n--\ndrivers/net/ethernet/fungible/funeth/funeth_main.c-1668-\tif (ntx \u003e dev-\u003ereal_num_tx_queues)\ndrivers/net/ethernet/fungible/funeth/funeth_main.c:1669:\t\tnetif_set_real_num_tx_queues(dev, ntx);\ndrivers/net/ethernet/fungible/funeth/funeth_main.c-1670-\n--\ndrivers/net/ethernet/google/gve/gve_main.c=1397=static int gve_queues_start(struct gve_priv *priv,\n--\ndrivers/net/ethernet/google/gve/gve_main.c-1420-\ndrivers/net/ethernet/google/gve/gve_main.c:1421:\terr = netif_set_real_num_tx_queues(dev, priv-\u003etx_cfg.num_queues);\ndrivers/net/ethernet/google/gve/gve_main.c-1422-\tif (err)\n--\ndrivers/net/ethernet/hisilicon/hns/hns_enet.c=1464=static int hns_nic_net_open(struct net_device *ndev)\n--\ndrivers/net/ethernet/hisilicon/hns/hns_enet.c-1475-\ndrivers/net/ethernet/hisilicon/hns/hns_enet.c:1476:\tret = netif_set_real_num_tx_queues(ndev, h-\u003eq_num);\ndrivers/net/ethernet/hisilicon/hns/hns_enet.c-1477-\tif (ret \u003c 0) {\ndrivers/net/ethernet/hisilicon/hns/hns_enet.c:1478:\t\tnetdev_err(ndev, \"netif_set_real_num_tx_queues fail, ret=%d!\\n\",\ndrivers/net/ethernet/hisilicon/hns/hns_enet.c-1479-\t\t\t ret);\n--\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c=618=static int hns3_nic_set_real_num_queue(struct net_device *netdev)\n--\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c-640-\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c:641:\tret = netif_set_real_num_tx_queues(netdev, queue_size);\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c-642-\tif (ret) {\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c-643-\t\tnetdev_err(netdev,\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c:644:\t\t\t \"netif_set_real_num_tx_queues fail, ret=%d!\\n\", ret);\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c-645-\t\treturn ret;\n--\ndrivers/net/ethernet/huawei/hinic/hinic_main.c=417=int hinic_open(struct net_device *netdev)\n--\ndrivers/net/ethernet/huawei/hinic/hinic_main.c-457-\ndrivers/net/ethernet/huawei/hinic/hinic_main.c:458:\tnetif_set_real_num_tx_queues(netdev, nic_dev-\u003enum_qps);\ndrivers/net/ethernet/huawei/hinic/hinic_main.c-459-\tnetif_set_real_num_rx_queues(netdev, nic_dev-\u003enum_qps);\n--\ndrivers/net/ethernet/ibm/ibmveth.c=1117=static int ibmveth_set_channels(struct net_device *netdev,\n--\ndrivers/net/ethernet/ibm/ibmveth.c-1128-\tif (!(netdev-\u003eflags \u0026 IFF_UP))\ndrivers/net/ethernet/ibm/ibmveth.c:1129:\t\treturn netif_set_real_num_tx_queues(netdev, goal);\ndrivers/net/ethernet/ibm/ibmveth.c-1130-\n--\ndrivers/net/ethernet/ibm/ibmveth.c-1151-\t}\ndrivers/net/ethernet/ibm/ibmveth.c:1152:\trc = netif_set_real_num_tx_queues(netdev, goal);\ndrivers/net/ethernet/ibm/ibmveth.c-1153-\tif (rc) {\n--\ndrivers/net/ethernet/ibm/ibmveth.c=1797=static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)\n--\ndrivers/net/ethernet/ibm/ibmveth.c-1912-\ndrivers/net/ethernet/ibm/ibmveth.c:1913:\trc = netif_set_real_num_tx_queues(netdev, min(num_online_cpus(),\ndrivers/net/ethernet/ibm/ibmveth.c-1914-\t\t\t\t\t\t IBMVETH_DEFAULT_QUEUES));\n--\ndrivers/net/ethernet/ibm/ibmvnic.c=1737=static int set_real_num_queues(struct net_device *netdev)\n--\ndrivers/net/ethernet/ibm/ibmvnic.c-1744-\ndrivers/net/ethernet/ibm/ibmvnic.c:1745:\trc = netif_set_real_num_tx_queues(netdev, adapter-\u003ereq_tx_queues);\ndrivers/net/ethernet/ibm/ibmvnic.c-1746-\tif (rc) {\n--\ndrivers/net/ethernet/intel/fm10k/fm10k_netdev.c=437=int fm10k_open(struct net_device *netdev)\n--\ndrivers/net/ethernet/intel/fm10k/fm10k_netdev.c-460-\t/* Notify the stack of the actual queue counts */\ndrivers/net/ethernet/intel/fm10k/fm10k_netdev.c:461:\terr = netif_set_real_num_tx_queues(netdev,\ndrivers/net/ethernet/intel/fm10k/fm10k_netdev.c-462-\t\t\t\t\t interface-\u003enum_tx_queues);\n--\ndrivers/net/ethernet/intel/i40e/i40e_main.c=9055=static int i40e_netif_set_realnum_tx_rx_queues(struct i40e_vsi *vsi)\n--\ndrivers/net/ethernet/intel/i40e/i40e_main.c-9063-\ndrivers/net/ethernet/intel/i40e/i40e_main.c:9064:\treturn netif_set_real_num_tx_queues(vsi-\u003enetdev,\ndrivers/net/ethernet/intel/i40e/i40e_main.c-9065-\t\t\t\t\t vsi-\u003enum_queue_pairs);\n--\ndrivers/net/ethernet/intel/iavf/iavf_main.c=1951=static void iavf_finish_config(struct work_struct *work)\n--\ndrivers/net/ethernet/intel/iavf/iavf_main.c-1978-\t\tnetif_set_real_num_rx_queues(adapter-\u003enetdev, pairs);\ndrivers/net/ethernet/intel/iavf/iavf_main.c:1979:\t\tnetif_set_real_num_tx_queues(adapter-\u003enetdev, pairs);\ndrivers/net/ethernet/intel/iavf/iavf_main.c-1980-\n--\ndrivers/net/ethernet/intel/iavf/iavf_main.c-2003-\t\tnetif_set_real_num_rx_queues(adapter-\u003enetdev, pairs);\ndrivers/net/ethernet/intel/iavf/iavf_main.c:2004:\t\tnetif_set_real_num_tx_queues(adapter-\u003enetdev, pairs);\ndrivers/net/ethernet/intel/iavf/iavf_main.c-2005-\t\tbreak;\n--\ndrivers/net/ethernet/intel/iavf/iavf_main.c=3679=static int __iavf_setup_tc(struct net_device *netdev, void *type_data)\n--\ndrivers/net/ethernet/intel/iavf/iavf_main.c-3781-\tnetif_set_real_num_rx_queues(netdev, total_qps);\ndrivers/net/ethernet/intel/iavf/iavf_main.c:3782:\tnetif_set_real_num_tx_queues(netdev, total_qps);\ndrivers/net/ethernet/intel/iavf/iavf_main.c-3783-\n--\ndrivers/net/ethernet/intel/ice/ice_main.c=7473=int ice_vsi_open(struct ice_vsi *vsi)\n--\ndrivers/net/ethernet/intel/ice/ice_main.c-7502-\t\t/* Notify the stack of the actual queue counts. */\ndrivers/net/ethernet/intel/ice/ice_main.c:7503:\t\terr = netif_set_real_num_tx_queues(vsi-\u003enetdev, vsi-\u003enum_txq);\ndrivers/net/ethernet/intel/ice/ice_main.c-7504-\t\tif (err)\n--\ndrivers/net/ethernet/intel/idpf/idpf_lib.c=1432=static int idpf_set_real_num_queues(struct idpf_vport *vport)\n--\ndrivers/net/ethernet/intel/idpf/idpf_lib.c-1440-\ndrivers/net/ethernet/intel/idpf/idpf_lib.c:1441:\treturn netif_set_real_num_tx_queues(vport-\u003enetdev, txq);\ndrivers/net/ethernet/intel/idpf/idpf_lib.c-1442-}\n--\ndrivers/net/ethernet/intel/igb/igb_main.c=4139=static int __igb_open(struct net_device *netdev, bool resuming)\n--\ndrivers/net/ethernet/intel/igb/igb_main.c-4182-\t/* Notify the stack of the actual queue counts. */\ndrivers/net/ethernet/intel/igb/igb_main.c:4183:\terr = netif_set_real_num_tx_queues(adapter-\u003enetdev,\ndrivers/net/ethernet/intel/igb/igb_main.c-4184-\t\t\t\t\t adapter-\u003enum_tx_queues);\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c=7422=int ixgbe_open(struct net_device *netdev)\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c-7451-\tqueues = adapter-\u003enum_tx_queues;\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c:7452:\terr = netif_set_real_num_tx_queues(netdev, queues);\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c-7453-\tif (err)\n--\ndrivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c=3662=int ixgbevf_open(struct net_device *netdev)\n--\ndrivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c-3711-\t/* Notify the stack of the actual queue counts. */\ndrivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c:3712:\terr = netif_set_real_num_tx_queues(netdev, adapter-\u003enum_tx_queues);\ndrivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c-3713-\tif (err)\n--\ndrivers/net/ethernet/marvell/mv643xx_eth.c=3083=static int mv643xx_eth_probe(struct platform_device *pdev)\n--\ndrivers/net/ethernet/marvell/mv643xx_eth.c-3170-\tset_params(mp, pd);\ndrivers/net/ethernet/marvell/mv643xx_eth.c:3171:\tnetif_set_real_num_tx_queues(dev, mp-\u003etxq_count);\ndrivers/net/ethernet/marvell/mv643xx_eth.c-3172-\tnetif_set_real_num_rx_queues(dev, mp-\u003erxq_count);\n--\ndrivers/net/ethernet/marvell/octeon_ep/octep_main.c=705=static int octep_open(struct net_device *netdev)\n--\ndrivers/net/ethernet/marvell/octeon_ep/octep_main.c-721-\ndrivers/net/ethernet/marvell/octeon_ep/octep_main.c:722:\terr = netif_set_real_num_tx_queues(netdev, oct-\u003enum_oqs);\ndrivers/net/ethernet/marvell/octeon_ep/octep_main.c-723-\tif (err)\n--\ndrivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c=470=static int octep_vf_open(struct net_device *netdev)\n--\ndrivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c-486-\ndrivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c:487:\terr = netif_set_real_num_tx_queues(netdev, oct-\u003enum_oqs);\ndrivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c-488-\tif (err)\n--\ndrivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c=1316=int otx2_set_real_num_queues(struct net_device *netdev,\n--\ndrivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c-1320-\ndrivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c:1321:\terr = netif_set_real_num_tx_queues(netdev, tx_queues);\ndrivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c-1322-\tif (err) {\n--\ndrivers/net/ethernet/marvell/octeontx2/nic/qos.c=26=static void otx2_qos_update_tx_netdev_queues(struct otx2_nic *pfvf)\n--\ndrivers/net/ethernet/marvell/octeontx2/nic/qos.c-35-\ndrivers/net/ethernet/marvell/octeontx2/nic/qos.c:36:\terr = netif_set_real_num_tx_queues(pfvf-\u003enetdev, tx_queues);\ndrivers/net/ethernet/marvell/octeontx2/nic/qos.c-37-\tif (err) {\n--\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c=60=int mlx4_en_setup_tc(struct net_device *dev, u8 up)\n--\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c-69-\tnetdev_set_num_tc(dev, up);\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c:70:\tnetif_set_real_num_tx_queues(dev, priv-\u003etx_ring_num[TX]);\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c-71-\t/* Partition Tx queues evenly amongst UP's */\n--\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c=2716=static int mlx4_xdp_set(struct net_device *dev, struct bpf_prog *prog)\n--\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c-2785-\tif (tx_changed)\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c:2786:\t\tnetif_set_real_num_tx_queues(dev, priv-\u003etx_ring_num[TX]);\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c-2787-\n--\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c=3161=int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,\n--\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c-3173-\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c:3174:\tnetif_set_real_num_tx_queues(dev, prof-\u003etx_ring_num[TX]);\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c-3175-\tnetif_set_real_num_rx_queues(dev, prof-\u003erx_ring_num);\n--\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c-3317-\tdev-\u003ewatchdog_timeo = MLX4_EN_WATCHDOG_TIMEOUT;\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c:3318:\tnetif_set_real_num_tx_queues(dev, priv-\u003etx_ring_num[TX]);\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c-3319-\tnetif_set_real_num_rx_queues(dev, priv-\u003erx_ring_num);\n--\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c=3192=int mlx5e_update_tx_netdev_queues(struct mlx5e_priv *priv)\n--\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c-3206-\tnetdev_dbg(priv-\u003enetdev, \"Setting num_txqs %d\\n\", num_txqs);\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c:3207:\terr = netif_set_real_num_tx_queues(priv-\u003enetdev, num_txqs);\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c-3208-\tif (err)\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c:3209:\t\tnetdev_warn(priv-\u003enetdev, \"netif_set_real_num_tx_queues failed, %d\\n\", err);\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c-3210-\n--\ndrivers/net/ethernet/microsoft/mana/mana_en.c=3572=int mana_alloc_queues(struct net_device *ndev)\n--\ndrivers/net/ethernet/microsoft/mana/mana_en.c-3598-\ndrivers/net/ethernet/microsoft/mana/mana_en.c:3599:\terr = netif_set_real_num_tx_queues(ndev, apc-\u003enum_queues);\ndrivers/net/ethernet/microsoft/mana/mana_en.c-3600-\tif (err) {\ndrivers/net/ethernet/microsoft/mana/mana_en.c-3601-\t\tnetdev_err(ndev,\ndrivers/net/ethernet/microsoft/mana/mana_en.c:3602:\t\t\t \"netif_set_real_num_tx_queues () failed for ndev with num_queues %u : %d\\n\",\ndrivers/net/ethernet/microsoft/mana/mana_en.c-3603-\t\t\t apc-\u003enum_queues, err);\n--\ndrivers/net/ethernet/mscc/ocelot.c=2965=int ocelot_port_mqprio(struct ocelot *ocelot, int port,\n--\ndrivers/net/ethernet/mscc/ocelot.c-2994-\ndrivers/net/ethernet/mscc/ocelot.c:2995:\terr = netif_set_real_num_tx_queues(dev, num_tc);\ndrivers/net/ethernet/mscc/ocelot.c-2996-\tif (err)\n--\ndrivers/net/ethernet/myricom/myri10ge/myri10ge.c=924=static int myri10ge_reset(struct myri10ge_priv *mgp)\n--\ndrivers/net/ethernet/myricom/myri10ge/myri10ge.c-995-\t\tif (status != 0 \u0026\u0026 mgp-\u003edev-\u003ereal_num_tx_queues \u003e 1) {\ndrivers/net/ethernet/myricom/myri10ge/myri10ge.c:996:\t\t\tnetif_set_real_num_tx_queues(mgp-\u003edev, 1);\ndrivers/net/ethernet/myricom/myri10ge/myri10ge.c-997-\t\t\tcmd.data0 = mgp-\u003enum_slices;\n--\ndrivers/net/ethernet/myricom/myri10ge/myri10ge.c=3758=static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)\n--\ndrivers/net/ethernet/myricom/myri10ge/myri10ge.c-3858-\t}\ndrivers/net/ethernet/myricom/myri10ge/myri10ge.c:3859:\tnetif_set_real_num_tx_queues(netdev, mgp-\u003enum_slices);\ndrivers/net/ethernet/myricom/myri10ge/myri10ge.c-3860-\tnetif_set_real_num_rx_queues(netdev, mgp-\u003enum_slices);\n--\ndrivers/net/ethernet/netronome/nfp/nfp_net_common.c=1300=static int nfp_net_netdev_open(struct net_device *netdev)\n--\ndrivers/net/ethernet/netronome/nfp/nfp_net_common.c-1313-\ndrivers/net/ethernet/netronome/nfp/nfp_net_common.c:1314:\terr = netif_set_real_num_tx_queues(netdev, nn-\u003edp.num_stack_tx_rings);\ndrivers/net/ethernet/netronome/nfp/nfp_net_common.c-1315-\tif (err)\n--\ndrivers/net/ethernet/pensando/ionic/ionic_lif.c=2268=static int ionic_open(struct net_device *netdev)\n--\ndrivers/net/ethernet/pensando/ionic/ionic_lif.c-2286-\ndrivers/net/ethernet/pensando/ionic/ionic_lif.c:2287:\terr = netif_set_real_num_tx_queues(netdev, lif-\u003enxqs);\ndrivers/net/ethernet/pensando/ionic/ionic_lif.c-2288-\tif (err)\n--\ndrivers/net/ethernet/pensando/ionic/ionic_lif.c=2930=int ionic_reconfigure_queues(struct ionic_lif *lif,\n--\ndrivers/net/ethernet/pensando/ionic/ionic_lif.c-3039-\tif (qparam-\u003enxqs != lif-\u003enxqs) {\ndrivers/net/ethernet/pensando/ionic/ionic_lif.c:3040:\t\terr = netif_set_real_num_tx_queues(lif-\u003enetdev, qparam-\u003enxqs);\ndrivers/net/ethernet/pensando/ionic/ionic_lif.c-3041-\t\tif (err)\n--\ndrivers/net/ethernet/pensando/ionic/ionic_lif.c-3044-\t\tif (err) {\ndrivers/net/ethernet/pensando/ionic/ionic_lif.c:3045:\t\t\tnetif_set_real_num_tx_queues(lif-\u003enetdev, lif-\u003enxqs);\ndrivers/net/ethernet/pensando/ionic/ionic_lif.c-3046-\t\t\tgoto err_out_reinit_unlock;\n--\ndrivers/net/ethernet/qlogic/qede/qede_main.c=1886=static int qede_set_real_num_queues(struct qede_dev *edev)\n--\ndrivers/net/ethernet/qlogic/qede/qede_main.c-1889-\ndrivers/net/ethernet/qlogic/qede/qede_main.c:1890:\trc = netif_set_real_num_tx_queues(edev-\u003endev,\ndrivers/net/ethernet/qlogic/qede/qede_main.c-1891-\t\t\t\t\t QEDE_TSS_COUNT(edev) *\n--\ndrivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c=2228=static int qlcnic_set_real_num_queues(struct qlcnic_adapter *adapter,\n--\ndrivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c-2234-\tif (tx_queues) {\ndrivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c:2235:\t\terr = netif_set_real_num_tx_queues(netdev, tx_queues);\ndrivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c-2236-\t\tif (err) {\n--\ndrivers/net/ethernet/sfc/efx_channels.c=928=int efx_set_channels(struct efx_nic *efx)\n--\ndrivers/net/ethernet/sfc/efx_channels.c-951-\ndrivers/net/ethernet/sfc/efx_channels.c:952:\trc = netif_set_real_num_tx_queues(efx-\u003enet_dev, efx-\u003en_tx_channels);\ndrivers/net/ethernet/sfc/efx_channels.c-953-\tif (rc)\n--\ndrivers/net/ethernet/sfc/falcon/efx.c=1607=static int ef4_probe_nic(struct ef4_nic *efx)\n--\ndrivers/net/ethernet/sfc/falcon/efx.c-1651-\ndrivers/net/ethernet/sfc/falcon/efx.c:1652:\tnetif_set_real_num_tx_queues(efx-\u003enet_dev, efx-\u003en_tx_channels);\ndrivers/net/ethernet/sfc/falcon/efx.c-1653-\tnetif_set_real_num_rx_queues(efx-\u003enet_dev, efx-\u003en_rx_channels);\n--\ndrivers/net/ethernet/sfc/falcon/tx.c=418=int ef4_setup_tc(struct net_device *net_dev, enum tc_setup_type type,\n--\ndrivers/net/ethernet/sfc/falcon/tx.c-471-\ndrivers/net/ethernet/sfc/falcon/tx.c:472:\trc = netif_set_real_num_tx_queues(net_dev,\ndrivers/net/ethernet/sfc/falcon/tx.c-473-\t\t\t\t\t max_t(int, num_tc, 1) *\n\n"
} |
| 9/2 | 2026/08/12 10:17 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 29862 output: 23 thoughts: 39 Thoughts: Okay, here's my interpretation of those thoughts, tailored for an expert audience, presented in the first person: **Analyzing Network Device TX Queue Management** Right, `netif_set_real_num_tx_queues` is a key function, and its widespread export tells us it's a fundamental building block for a vast number of network drivers. That alone suggests careful consideration of its implications and side effects is crucial. Now, the next logical step, at least in my thinking process, is to immediately pivot and examine the relationship it has with `netdev_txq_to_tc`. I need to understand how these elements interoperate, particularly how the number of TX queues impacts traffic control configurations. The number of queues directly determines the scope of `netdev_txq_to_tc`'s applicability. We need to be aware of how the number of queues is set and how the traffic control is set with that number of queues. Given that `netif_set_real_num_tx_queues` is a low-level operation, I'm expecting to find that a strong dependency may be the case here. This needs to be understood. |
| 10/2 | 2026/08/12 10:17 | tool | grepper |
0mArgs:{
"Expression": "netdev_txq_to_tc"
}Results: {
"Output": "drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c=1394=static netdev_tx_t __dpaa2_eth_tx(struct sk_buff *skb,\n--\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c-1473-\tif (num_tc) {\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c:1474:\t\tprio = netdev_txq_to_tc(net_dev, queue_mapping);\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c-1475-\t\t/* Hardware interprets priority level 0 as being the highest,\n--\ndrivers/net/ethernet/ti/cpsw_priv.c=936=static int cpsw_set_cbs(struct net_device *ndev,\n--\ndrivers/net/ethernet/ti/cpsw_priv.c-945-\ndrivers/net/ethernet/ti/cpsw_priv.c:946:\ttc = netdev_txq_to_tc(priv-\u003endev, qopt-\u003equeue);\ndrivers/net/ethernet/ti/cpsw_priv.c-947-\n--\ninclude/linux/netdevice.h=2678=int netdev_set_prio_tc_map(struct net_device *dev, u8 prio, u8 tc)\n--\ninclude/linux/netdevice.h-2686-\ninclude/linux/netdevice.h:2687:int netdev_txq_to_tc(struct net_device *dev, unsigned int txq);\ninclude/linux/netdevice.h-2688-void netdev_reset_tc(struct net_device *dev);\n--\nnet/core/dev.c=2657=static void netif_setup_tc(struct net_device *dev, unsigned int txq)\n--\nnet/core/dev.c-2683-\nnet/core/dev.c:2684:int netdev_txq_to_tc(struct net_device *dev, unsigned int txq)\nnet/core/dev.c-2685-{\n--\nnet/core/dev.c-2704-}\nnet/core/dev.c:2705:EXPORT_SYMBOL(netdev_txq_to_tc);\nnet/core/dev.c-2706-\n--\nnet/core/dev.c=2884=int __netif_set_xps_queue(struct net_device *dev, const unsigned long *mask,\n--\nnet/core/dev.c-2906-\nnet/core/dev.c:2907:\t\ttc = netdev_txq_to_tc(dev, index);\nnet/core/dev.c-2908-\t\tif (tc \u003c 0)\n--\nnet/core/net-sysfs.c=1417=static ssize_t traffic_class_show(struct kobject *kobj, struct attribute *attr,\n--\nnet/core/net-sysfs.c-1435-\tnum_tc = READ_ONCE(dev-\u003enum_tc);\nnet/core/net-sysfs.c:1436:\ttc = netdev_txq_to_tc(dev, index);\nnet/core/net-sysfs.c-1437-\n--\nnet/core/net-sysfs.c=1742=static ssize_t xps_cpus_show(struct kobject *kobj, struct attribute *attr,\n--\nnet/core/net-sysfs.c-1760-\nnet/core/net-sysfs.c:1761:\ttc = netdev_txq_to_tc(dev, index);\nnet/core/net-sysfs.c-1762-\tif (tc \u003c 0) {\n--\nnet/core/net-sysfs.c=1822=static ssize_t xps_rxqs_show(struct kobject *kobj, struct attribute *attr,\n--\nnet/core/net-sysfs.c-1834-\nnet/core/net-sysfs.c:1835:\ttc = netdev_txq_to_tc(dev, index);\nnet/core/net-sysfs.c-1836-\n--\nnet/dsa/tag_ksz.c=253=static struct sk_buff *ksz9477_xmit(struct sk_buff *skb,\n--\nnet/dsa/tag_ksz.c-256-\tu16 queue_mapping = skb_get_queue_mapping(skb);\nnet/dsa/tag_ksz.c:257:\tu8 prio = netdev_txq_to_tc(dev, queue_mapping);\nnet/dsa/tag_ksz.c-258-\tstruct dsa_port *dp = dsa_user_to_port(dev);\n--\nnet/dsa/tag_ksz.c=376=static struct sk_buff *ksz9893_xmit(struct sk_buff *skb,\n--\nnet/dsa/tag_ksz.c-379-\tu16 queue_mapping = skb_get_queue_mapping(skb);\nnet/dsa/tag_ksz.c:380:\tu8 prio = netdev_txq_to_tc(dev, queue_mapping);\nnet/dsa/tag_ksz.c-381-\n--\nnet/dsa/tag_ksz.c=403=static struct sk_buff *ksz8463_xmit(struct sk_buff *skb,\n--\nnet/dsa/tag_ksz.c-406-\tu16 queue_mapping = skb_get_queue_mapping(skb);\nnet/dsa/tag_ksz.c:407:\tu8 prio = netdev_txq_to_tc(dev, queue_mapping);\nnet/dsa/tag_ksz.c-408-\n--\nnet/dsa/tag_ksz.c=489=static struct sk_buff *lan937x_xmit(struct sk_buff *skb,\n--\nnet/dsa/tag_ksz.c-492-\tu16 queue_mapping = skb_get_queue_mapping(skb);\nnet/dsa/tag_ksz.c:493:\tu8 prio = netdev_txq_to_tc(dev, queue_mapping);\nnet/dsa/tag_ksz.c-494-\tstruct dsa_port *dp = dsa_user_to_port(dev);\n--\nnet/dsa/tag_netc.c=62=static void *netc_fill_common_tp_tag(struct sk_buff *skb,\n--\nnet/dsa/tag_netc.c-67-\tu16 queue = skb_get_queue_mapping(skb);\nnet/dsa/tag_netc.c:68:\ts8 ipv = netdev_txq_to_tc(ndev, queue);\nnet/dsa/tag_netc.c-69-\tvoid *tag;\n--\nnet/dsa/tag_ocelot_8021q.c=67=static struct sk_buff *ocelot_xmit(struct sk_buff *skb,\n--\nnet/dsa/tag_ocelot_8021q.c-71-\tu16 queue_mapping = skb_get_queue_mapping(skb);\nnet/dsa/tag_ocelot_8021q.c:72:\tu8 pcp = netdev_txq_to_tc(netdev, queue_mapping);\nnet/dsa/tag_ocelot_8021q.c-73-\tu16 tx_vid = dsa_tag_8021q_standalone_vid(dp);\n--\nnet/dsa/tag_sja1105.c=267=static struct sk_buff *sja1105_xmit(struct sk_buff *skb,\n--\nnet/dsa/tag_sja1105.c-271-\tu16 queue_mapping = skb_get_queue_mapping(skb);\nnet/dsa/tag_sja1105.c:272:\tu8 pcp = netdev_txq_to_tc(netdev, queue_mapping);\nnet/dsa/tag_sja1105.c-273-\tu16 tx_vid = dsa_tag_8021q_standalone_vid(dp);\n--\nnet/dsa/tag_sja1105.c=294=static struct sk_buff *sja1110_xmit(struct sk_buff *skb,\n--\nnet/dsa/tag_sja1105.c-299-\tu16 queue_mapping = skb_get_queue_mapping(skb);\nnet/dsa/tag_sja1105.c:300:\tu8 pcp = netdev_txq_to_tc(netdev, queue_mapping);\nnet/dsa/tag_sja1105.c-301-\tu16 tx_vid = dsa_tag_8021q_standalone_vid(dp);\n--\nnet/dsa/tag_vsc73xx_8021q.c=12=vsc73xx_xmit(struct sk_buff *skb, struct net_device *netdev)\n--\nnet/dsa/tag_vsc73xx_8021q.c-28-\nnet/dsa/tag_vsc73xx_8021q.c:29:\tpcp = netdev_txq_to_tc(netdev, queue_mapping);\nnet/dsa/tag_vsc73xx_8021q.c-30-\n--\nnet/sched/sch_mqprio.c=653=static int mqprio_dump_class(struct Qdisc *sch, unsigned long cl,\n--\nnet/sched/sch_mqprio.c-658-\t\tstruct net_device *dev = qdisc_dev(sch);\nnet/sched/sch_mqprio.c:659:\t\tint tc = netdev_txq_to_tc(dev, cl - 1);\nnet/sched/sch_mqprio.c-660-\n"
} |
| 11/2 | 2026/08/12 10:17 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 32794 output: 22 thoughts: 29 Thoughts: Here's my summary, as though I'm thinking through this process: **Diving into Traffic Control with `netdev_txq_to_tc` and `netdev_set_num_tc`** Okay, so `netdev_txq_to_tc` is exported, that's interesting. It signals that this function has some broad applicability, a likely entry point for deeper investigation. My immediate thought is, let's see how this ties into traffic control and device configuration. Given its name, it probably plays a role in mapping transmit queues to traffic classes. To confirm that intuition, I should next check `netdev_set_num_tc`. It’s likely related, and the potential to modify the number of traffic classes supported is a good starting point for understanding how queues get assigned to TCs and the underlying TC configuration model. It might illuminate how the available TC numbers affect the behavior of `netdev_txq_to_tc`. This pairing probably represents a key section of the driver or kernel code. Now, where to begin the investigation? |
| 12/2 | 2026/08/12 10:17 | tool | grepper |
0mArgs:{
"Expression": "netdev_set_num_tc"
}Results: {
"Output": "drivers/net/ethernet/amd/xgbe/xgbe-dev.c=2630=static void xgbe_config_tc(struct xgbe_prv_data *pdata)\n--\ndrivers/net/ethernet/amd/xgbe/xgbe-dev.c-2638-\ndrivers/net/ethernet/amd/xgbe/xgbe-dev.c:2639:\tnetdev_set_num_tc(pdata-\u003enetdev, pdata-\u003enum_tcs);\ndrivers/net/ethernet/amd/xgbe/xgbe-dev.c-2640-\n--\ndrivers/net/ethernet/aquantia/atlantic/aq_nic.c=1642=int aq_nic_setup_tc_mqprio(struct aq_nic_s *self, u32 tcs, u8 *prio_tc_map)\n--\ndrivers/net/ethernet/aquantia/atlantic/aq_nic.c-1674-\ndrivers/net/ethernet/aquantia/atlantic/aq_nic.c:1675:\tnetdev_set_num_tc(self-\u003endev, cfg-\u003etcs);\ndrivers/net/ethernet/aquantia/atlantic/aq_nic.c-1676-\n--\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c=4254=int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)\n--\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c-4276-\t/* declare amount of supported traffic classes */\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c:4277:\tif (netdev_set_num_tc(dev, num_tc)) {\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c-4278-\t\tBNX2X_ERR(\"failed to declare %d traffic classes\\n\", num_tc);\n--\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c=15646=int bnxt_setup_mq_tc(struct net_device *dev, u8 tc)\n--\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c-15674-\t\tbp-\u003etx_nr_rings = bp-\u003etx_nr_rings_per_tc * tc;\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c:15675:\t\tnetdev_set_num_tc(dev, tc);\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c-15676-\t\tbp-\u003enum_tc = tc;\n--\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c=424=static int cxgb4_mqprio_enable_offload(struct net_device *dev,\n--\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c-476-\t */\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c:477:\tret = netdev_set_num_tc(dev, mqprio-\u003eqopt.num_tc);\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c-478-\tif (ret)\n--\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c=369=static int dpaa_setup_tc(struct net_device *net_dev, enum tc_setup_type type,\n--\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c-397-\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c:398:\tnetdev_set_num_tc(net_dev, num_tc);\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c-399-\n--\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c=2940=static int dpaa2_eth_setup_mqprio(struct net_device *net_dev,\n--\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c-2965-\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c:2966:\tnetdev_set_num_tc(net_dev, num_tc);\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c-2967-\tnetif_set_real_num_tx_queues(net_dev, num_tc * num_queues);\n--\ndrivers/net/ethernet/freescale/enetc/enetc.c=3180=int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)\n--\ndrivers/net/ethernet/freescale/enetc/enetc.c-3196-\ndrivers/net/ethernet/freescale/enetc/enetc.c:3197:\terr = netdev_set_num_tc(ndev, num_tc);\ndrivers/net/ethernet/freescale/enetc/enetc.c-3198-\tif (err)\n--\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c=618=static int hns3_nic_set_real_num_queue(struct net_device *netdev)\n--\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c-628-\t} else {\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c:629:\t\tret = netdev_set_num_tc(netdev, tc_info-\u003enum_tc);\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c-630-\t\tif (ret) {\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c-631-\t\t\tnetdev_err(netdev,\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c:632:\t\t\t\t \"netdev_set_num_tc fail, ret=%d!\\n\", ret);\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c-633-\t\t\treturn ret;\n--\ndrivers/net/ethernet/intel/fm10k/fm10k_netdev.c=1263=int fm10k_setup_tc(struct net_device *dev, u8 tc)\n--\ndrivers/net/ethernet/intel/fm10k/fm10k_netdev.c-1288-\tnetdev_reset_tc(dev);\ndrivers/net/ethernet/intel/fm10k/fm10k_netdev.c:1289:\tnetdev_set_num_tc(dev, tc);\ndrivers/net/ethernet/intel/fm10k/fm10k_netdev.c-1290-\n--\ndrivers/net/ethernet/intel/i40e/i40e_main.c=5650=static void i40e_vsi_config_netdev_tc(struct i40e_vsi *vsi, u8 enabled_tc)\n--\ndrivers/net/ethernet/intel/i40e/i40e_main.c-5667-\t/* Set up actual enabled TCs on the VSI */\ndrivers/net/ethernet/intel/i40e/i40e_main.c:5668:\tif (netdev_set_num_tc(netdev, vsi-\u003etc_config.numtc))\ndrivers/net/ethernet/intel/i40e/i40e_main.c-5669-\t\treturn;\n--\ndrivers/net/ethernet/intel/iavf/iavf_main.c=3679=static int __iavf_setup_tc(struct net_device *netdev, void *type_data)\n--\ndrivers/net/ethernet/intel/iavf/iavf_main.c-3766-\t\t/* Report the tc mapping up the stack */\ndrivers/net/ethernet/intel/iavf/iavf_main.c:3767:\t\tnetdev_set_num_tc(adapter-\u003enetdev, num_tc);\ndrivers/net/ethernet/intel/iavf/iavf_main.c-3768-\t\tfor (i = 0; i \u003c IAVF_MAX_TRAFFIC_CLASS; i++) {\n--\ndrivers/net/ethernet/intel/ice/ice_lib.c=3201=void ice_vsi_cfg_netdev_tc(struct ice_vsi *vsi, u8 ena_tc)\n--\ndrivers/net/ethernet/intel/ice/ice_lib.c-3224-\ndrivers/net/ethernet/intel/ice/ice_lib.c:3225:\tif (netdev_set_num_tc(netdev, numtc))\ndrivers/net/ethernet/intel/ice/ice_lib.c-3226-\t\treturn;\n--\ndrivers/net/ethernet/intel/igc/igc_main.c=6764=static int igc_tsn_enable_mqprio(struct igc_adapter *adapter,\n--\ndrivers/net/ethernet/intel/igc/igc_main.c-6805-\ndrivers/net/ethernet/intel/igc/igc_main.c:6806:\terr = netdev_set_num_tc(adapter-\u003enetdev, adapter-\u003enum_tc);\ndrivers/net/ethernet/intel/igc/igc_main.c-6807-\tif (err)\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c=500=static bool ixgbe_set_sriov_queues(struct ixgbe_adapter *adapter)\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c-606-\tif (vmdq_i \u003e 1)\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c:607:\t\tnetdev_set_num_tc(adapter-\u003enetdev, 1);\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c-608-\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c=9903=int ixgbe_setup_tc(struct net_device *dev, u8 tc)\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c-9936-\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c:9937:\t\tnetdev_set_num_tc(dev, tc);\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c-9938-\t\tixgbe_set_prio_tc_map(adapter);\n--\ndrivers/net/ethernet/marvell/mvneta.c=5240=static int mvneta_setup_mqprio(struct net_device *dev,\n--\ndrivers/net/ethernet/marvell/mvneta.c-5262-\ndrivers/net/ethernet/marvell/mvneta.c:5263:\tnetdev_set_num_tc(dev, mqprio-\u003eqopt.num_tc);\ndrivers/net/ethernet/marvell/mvneta.c-5264-\n--\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c=60=int mlx4_en_setup_tc(struct net_device *dev, u8 up)\n--\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c-68-\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c:69:\tnetdev_set_num_tc(dev, up);\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c-70-\tnetif_set_real_num_tx_queues(dev, priv-\u003etx_ring_num[TX]);\n--\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c=3165=static int mlx5e_netdev_set_tcs(struct net_device *netdev, u16 nch, u8 ntc,\n--\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c-3174-\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c:3175:\terr = netdev_set_num_tc(netdev, ntc);\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c-3176-\tif (err) {\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c:3177:\t\tnetdev_WARN(netdev, \"netdev_set_num_tc failed (%d), ntc = %d\\n\", err, ntc);\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c-3178-\t\treturn err;\n--\ndrivers/net/ethernet/microchip/lan966x/lan966x_mqprio.c=5=int lan966x_mqprio_add(struct lan966x_port *port, u8 num_tc)\n--\ndrivers/net/ethernet/microchip/lan966x/lan966x_mqprio.c-14-\ndrivers/net/ethernet/microchip/lan966x/lan966x_mqprio.c:15:\tnetdev_set_num_tc(port-\u003edev, num_tc);\ndrivers/net/ethernet/microchip/lan966x/lan966x_mqprio.c-16-\n--\ndrivers/net/ethernet/microchip/sparx5/sparx5_qos.c=476=int sparx5_tc_mqprio_add(struct net_device *ndev, u8 num_tc)\n--\ndrivers/net/ethernet/microchip/sparx5/sparx5_qos.c-485-\ndrivers/net/ethernet/microchip/sparx5/sparx5_qos.c:486:\tnetdev_set_num_tc(ndev, num_tc);\ndrivers/net/ethernet/microchip/sparx5/sparx5_qos.c-487-\n--\ndrivers/net/ethernet/mscc/ocelot.c=2965=int ocelot_port_mqprio(struct ocelot *ocelot, int port,\n--\ndrivers/net/ethernet/mscc/ocelot.c-2978-\ndrivers/net/ethernet/mscc/ocelot.c:2979:\terr = netdev_set_num_tc(dev, num_tc);\ndrivers/net/ethernet/mscc/ocelot.c-2980-\tif (err)\n--\ndrivers/net/ethernet/qlogic/qede/qede_main.c=615=static int qede_setup_tc(struct net_device *ndev, u8 num_tc)\n--\ndrivers/net/ethernet/qlogic/qede/qede_main.c-623-\tnetdev_reset_tc(ndev);\ndrivers/net/ethernet/qlogic/qede/qede_main.c:624:\tnetdev_set_num_tc(ndev, num_tc);\ndrivers/net/ethernet/qlogic/qede/qede_main.c-625-\n--\ndrivers/net/ethernet/stmicro/stmmac/stmmac_tc.c=1250=static int tc_setup_dwmac510_mqprio(struct stmmac_priv *priv,\n--\ndrivers/net/ethernet/stmicro/stmmac/stmmac_tc.c-1264-\ndrivers/net/ethernet/stmicro/stmmac/stmmac_tc.c:1265:\terr = netdev_set_num_tc(ndev, num_tc);\ndrivers/net/ethernet/stmicro/stmmac/stmmac_tc.c-1266-\tif (err)\n--\ndrivers/net/ethernet/ti/am65-cpsw-qos.c=203=static int am65_cpsw_setup_mqprio(struct net_device *ndev, void *type_data)\n--\ndrivers/net/ethernet/ti/am65-cpsw-qos.c-231-\ndrivers/net/ethernet/ti/am65-cpsw-qos.c:232:\tnetdev_set_num_tc(ndev, num_tc);\ndrivers/net/ethernet/ti/am65-cpsw-qos.c-233-\n--\ndrivers/net/ethernet/ti/cpsw_priv.c=996=static int cpsw_set_mqprio(struct net_device *ndev, void *type_data)\n--\ndrivers/net/ethernet/ti/cpsw_priv.c-1023-\ndrivers/net/ethernet/ti/cpsw_priv.c:1024:\t\tnetdev_set_num_tc(ndev, num_tc);\ndrivers/net/ethernet/ti/cpsw_priv.c-1025-\t\tfor (i = 0; i \u003c num_tc; i++) {\n--\ndrivers/net/ethernet/ti/netcp_core.c=1933=static int netcp_setup_tc(struct net_device *dev, enum tc_setup_type type,\n--\ndrivers/net/ethernet/ti/netcp_core.c-1955-\tif (num_tc) {\ndrivers/net/ethernet/ti/netcp_core.c:1956:\t\tnetdev_set_num_tc(dev, num_tc);\ndrivers/net/ethernet/ti/netcp_core.c-1957-\t\tfor (i = 0; i \u003c num_tc; i++)\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c=618=int ngbe_setup_tc(struct net_device *dev, u8 tc)\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-633-\tif (tc)\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:634:\t\tnetdev_set_num_tc(dev, tc);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-635-\telse\n--\ndrivers/net/ethernet/wangxun/txgbe/txgbe_main.c=611=int txgbe_setup_tc(struct net_device *dev, u8 tc)\n--\ndrivers/net/ethernet/wangxun/txgbe/txgbe_main.c-626-\tif (tc)\ndrivers/net/ethernet/wangxun/txgbe/txgbe_main.c:627:\t\tnetdev_set_num_tc(dev, tc);\ndrivers/net/ethernet/wangxun/txgbe/txgbe_main.c-628-\telse\n--\ndrivers/s390/net/qeth_core_main.c=6979=static void qeth_iqd_set_prio_tc_map(struct net_device *dev,\n--\ndrivers/s390/net/qeth_core_main.c-6992-\t/* One traffic class, spanning over all active ucast queues: */\ndrivers/s390/net/qeth_core_main.c:6993:\tnetdev_set_num_tc(dev, 1);\ndrivers/s390/net/qeth_core_main.c-6994-\tnetdev_set_tc_queue(dev, TC_IQD_UCAST, ucast_txqs,\n--\ninclude/linux/netdevice.h=2689=int netdev_set_tc_queue(struct net_device *dev, u8 tc, u16 count, u16 offset);\ninclude/linux/netdevice.h:2690:int netdev_set_num_tc(struct net_device *dev, u8 num_tc);\ninclude/linux/netdevice.h-2691-\n--\nnet/core/dev.c=3148=EXPORT_SYMBOL(netdev_set_tc_queue);\nnet/core/dev.c-3149-\nnet/core/dev.c:3150:int netdev_set_num_tc(struct net_device *dev, u8 num_tc)\nnet/core/dev.c-3151-{\n--\nnet/core/dev.c-3162-}\nnet/core/dev.c:3163:EXPORT_SYMBOL(netdev_set_num_tc);\nnet/core/dev.c-3164-\n--\nnet/sched/sch_mqprio.c=95=static void mqprio_destroy(struct Qdisc *sch)\n--\nnet/sched/sch_mqprio.c-111-\telse\nnet/sched/sch_mqprio.c:112:\t\tnetdev_set_num_tc(dev, 0);\nnet/sched/sch_mqprio.c-113-}\n--\nnet/sched/sch_mqprio.c=345=static int mqprio_init(struct Qdisc *sch, struct nlattr *opt,\n--\nnet/sched/sch_mqprio.c-416-\t} else {\nnet/sched/sch_mqprio.c:417:\t\tnetdev_set_num_tc(dev, qopt-\u003enum_tc);\nnet/sched/sch_mqprio.c-418-\t\tfor (i = 0; i \u003c qopt-\u003enum_tc; i++)\n--\nnet/sched/sch_taprio.c=1822=static int taprio_change(struct Qdisc *sch, struct nlattr *opt,\n--\nnet/sched/sch_taprio.c-1900-\tif (mqprio) {\nnet/sched/sch_taprio.c:1901:\t\terr = netdev_set_num_tc(dev, mqprio-\u003enum_tc);\nnet/sched/sch_taprio.c-1902-\t\tif (err)\n"
} |
| 13/2 | 2026/08/12 10:17 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 38827 output: 22 thoughts: 28 Thoughts: Here's my take on the thought process, as if it were my own: **Investigating Traffic Class (TC) Configuration** Okay, so `netdev_set_num_tc` is exported and available, which is good. That likely means there's a defined method for setting the number of Traffic Classes (TCs) on a network device. Since I'm familiar with network device management, I know setting the number of TCs is often a precursor to configuring the specific queues within those TCs. With the number of TCs set, I'd like to understand how the queues within the TC are configured. Therefore, the logical next step is to examine `netdev_set_tc_queue`. I'll want to see how this function interacts with the traffic classes that have been defined on the network interface. This will give me a better understanding of how the system is designed to handle per-TC queue configuration, and how it handles mapping traffic to specific queues. I'm hoping it's a relatively straightforward mechanism, leveraging the already defined `netdev_set_num_tc` function. I'll be looking closely at parameter handling and any potential interaction with other related netdev structures or functions. Let's dig in and see how it works. |
| 14/2 | 2026/08/12 10:17 | tool | grepper |
0mArgs:{
"Expression": "netdev_set_tc_queue"
}Results: {
"Output": "drivers/net/ethernet/amd/xgbe/xgbe-dev.c=2630=static void xgbe_config_tc(struct xgbe_prv_data *pdata)\n--\ndrivers/net/ethernet/amd/xgbe/xgbe-dev.c-2647-\t\t\t i, offset, queue - 1);\ndrivers/net/ethernet/amd/xgbe/xgbe-dev.c:2648:\t\tnetdev_set_tc_queue(pdata-\u003enetdev, i, queue - offset, offset);\ndrivers/net/ethernet/amd/xgbe/xgbe-dev.c-2649-\t\toffset = queue;\n--\ndrivers/net/ethernet/aquantia/atlantic/aq_nic.c=495=int aq_nic_start(struct aq_nic_s *self)\n--\ndrivers/net/ethernet/aquantia/atlantic/aq_nic.c-597-\ndrivers/net/ethernet/aquantia/atlantic/aq_nic.c:598:\t\tnetdev_set_tc_queue(self-\u003endev, i, self-\u003eaq_vecs, offset);\ndrivers/net/ethernet/aquantia/atlantic/aq_nic.c-599-\t}\n--\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c=4254=int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)\n--\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c-4307-\t\toffset = cos * BNX2X_NUM_NON_CNIC_QUEUES(bp);\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c:4308:\t\tnetdev_set_tc_queue(dev, cos, count, offset);\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c-4309-\t\tDP(BNX2X_MSG_SP | NETIF_MSG_IFUP,\n--\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c=11435=static void bnxt_setup_msix(struct bnxt *bp)\n--\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c-11447-\t\t\toff = BNXT_TC_TO_RING_BASE(bp, i);\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c:11448:\t\t\tnetdev_set_tc_queue(dev, i, count, off);\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c-11449-\t\t}\n--\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c=424=static int cxgb4_mqprio_enable_offload(struct net_device *dev,\n--\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c-490-\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c:491:\t\tret = netdev_set_tc_queue(dev, i, qcount, qoffset);\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c-492-\t\tif (ret)\n--\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c=369=static int dpaa_setup_tc(struct net_device *net_dev, enum tc_setup_type type,\n--\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c-400-\tfor (i = 0; i \u003c num_tc; i++)\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c:401:\t\tnetdev_set_tc_queue(net_dev, i, num_txqs_per_tc,\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c-402-\t\t\t\t i * num_txqs_per_tc);\n--\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c=2940=static int dpaa2_eth_setup_mqprio(struct net_device *net_dev,\n--\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c-2969-\tfor (i = 0; i \u003c num_tc; i++)\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c:2970:\t\tnetdev_set_tc_queue(net_dev, i, num_queues, i * num_queues);\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c-2971-\n--\ndrivers/net/ethernet/freescale/enetc/enetc.c=3180=int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)\n--\ndrivers/net/ethernet/freescale/enetc/enetc.c-3205-\ndrivers/net/ethernet/freescale/enetc/enetc.c:3206:\t\terr = netdev_set_tc_queue(ndev, tc, count, offset);\ndrivers/net/ethernet/freescale/enetc/enetc.c-3207-\t\tif (err)\n--\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c=618=static int hns3_nic_set_real_num_queue(struct net_device *netdev)\n--\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c-636-\t\tfor (i = 0; i \u003c tc_info-\u003enum_tc; i++)\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c:637:\t\t\tnetdev_set_tc_queue(netdev, i, tc_info-\u003etqp_count[i],\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c-638-\t\t\t\t\t tc_info-\u003etqp_offset[i]);\n--\ndrivers/net/ethernet/intel/fm10k/fm10k_main.c=1477=static bool fm10k_set_qos_queues(struct fm10k_intfc *interface)\n--\ndrivers/net/ethernet/intel/fm10k/fm10k_main.c-1506-\tfor (i = 0; i \u003c pcs; i++)\ndrivers/net/ethernet/intel/fm10k/fm10k_main.c:1507:\t\tnetdev_set_tc_queue(dev, i, rss_i, rss_i * i);\ndrivers/net/ethernet/intel/fm10k/fm10k_main.c-1508-\n--\ndrivers/net/ethernet/intel/i40e/i40e_main.c=5650=static void i40e_vsi_config_netdev_tc(struct i40e_vsi *vsi, u8 enabled_tc)\n--\ndrivers/net/ethernet/intel/i40e/i40e_main.c-5680-\t\tif (vsi-\u003etc_config.enabled_tc \u0026 BIT(i))\ndrivers/net/ethernet/intel/i40e/i40e_main.c:5681:\t\t\tnetdev_set_tc_queue(netdev,\ndrivers/net/ethernet/intel/i40e/i40e_main.c-5682-\t\t\t\t\tvsi-\u003etc_config.tc_info[i].netdev_tc,\n--\ndrivers/net/ethernet/intel/iavf/iavf_main.c=3679=static int __iavf_setup_tc(struct net_device *netdev, void *type_data)\n--\ndrivers/net/ethernet/intel/iavf/iavf_main.c-3772-\t\t\tif (i \u003c num_tc)\ndrivers/net/ethernet/intel/iavf/iavf_main.c:3773:\t\t\t\tnetdev_set_tc_queue(netdev, netdev_tc++, qcount,\ndrivers/net/ethernet/intel/iavf/iavf_main.c-3774-\t\t\t\t\t\t qoffset);\n--\ndrivers/net/ethernet/intel/ice/ice_lib.c=3201=void ice_vsi_cfg_netdev_tc(struct ice_vsi *vsi, u8 ena_tc)\n--\ndrivers/net/ethernet/intel/ice/ice_lib.c-3231-\t\tif (vsi-\u003etc_cfg.ena_tc \u0026 BIT(i))\ndrivers/net/ethernet/intel/ice/ice_lib.c:3232:\t\t\tnetdev_set_tc_queue(netdev,\ndrivers/net/ethernet/intel/ice/ice_lib.c-3233-\t\t\t\t\t vsi-\u003etc_cfg.tc_info[i].netdev_tc,\n--\ndrivers/net/ethernet/intel/ice/ice_lib.c-3241-\t\t\tbreak;\ndrivers/net/ethernet/intel/ice/ice_lib.c:3242:\t\tnetdev_set_tc_queue(netdev, i,\ndrivers/net/ethernet/intel/ice/ice_lib.c-3243-\t\t\t\t vsi-\u003emqprio_qopt.qopt.count[i],\n--\ndrivers/net/ethernet/intel/ice/ice_main.c=4064=int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx, bool locked)\n--\ndrivers/net/ethernet/intel/ice/ice_main.c-4099-\t\tif (vsi-\u003etc_cfg.ena_tc \u0026 BIT(i))\ndrivers/net/ethernet/intel/ice/ice_main.c:4100:\t\t\tnetdev_set_tc_queue(vsi-\u003enetdev,\ndrivers/net/ethernet/intel/ice/ice_main.c-4101-\t\t\t\t\t vsi-\u003etc_cfg.tc_info[i].netdev_tc,\n--\ndrivers/net/ethernet/intel/igc/igc_main.c=6764=static int igc_tsn_enable_mqprio(struct igc_adapter *adapter,\n--\ndrivers/net/ethernet/intel/igc/igc_main.c-6810-\tfor (i = 0; i \u003c adapter-\u003enum_tc; i++) {\ndrivers/net/ethernet/intel/igc/igc_main.c:6811:\t\terr = netdev_set_tc_queue(adapter-\u003enetdev, i, 1,\ndrivers/net/ethernet/intel/igc/igc_main.c-6812-\t\t\t\t\t adapter-\u003equeue_per_tc[i]);\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c=326=static bool ixgbe_set_dcb_sriov_queues(struct ixgbe_adapter *adapter)\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c-420-\tfor (i = 0; i \u003c tcs; i++)\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c:421:\t\tnetdev_set_tc_queue(adapter-\u003enetdev, i, 1, i);\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c-422-\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c=426=static bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter)\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c-480-\tfor (i = 0; i \u003c tcs; i++)\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c:481:\t\tnetdev_set_tc_queue(dev, i, rss_i, rss_i * i);\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c-482-\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c=500=static bool ixgbe_set_sriov_queues(struct ixgbe_adapter *adapter)\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c-609-\t/* populate TC0 for use by pool 0 */\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c:610:\tnetdev_set_tc_queue(adapter-\u003enetdev, 0,\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c-611-\t\t\t adapter-\u003enum_rx_queues_per_pool, 0);\n--\ndrivers/net/ethernet/marvell/mvneta.c=5240=static int mvneta_setup_mqprio(struct net_device *dev,\n--\ndrivers/net/ethernet/marvell/mvneta.c-5265-\tfor (tc = 0; tc \u003c mqprio-\u003eqopt.num_tc; tc++) {\ndrivers/net/ethernet/marvell/mvneta.c:5266:\t\tnetdev_set_tc_queue(dev, tc, mqprio-\u003eqopt.count[tc],\ndrivers/net/ethernet/marvell/mvneta.c-5267-\t\t\t\t mqprio-\u003eqopt.offset[tc]);\n--\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c=60=int mlx4_en_setup_tc(struct net_device *dev, u8 up)\n--\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c-72-\tfor (i = 0; i \u003c up; i++) {\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c:73:\t\tnetdev_set_tc_queue(dev, i, priv-\u003enum_tx_rings_p_up, offset);\ndrivers/net/ethernet/mellanox/mlx4/en_netdev.c-74-\t\toffset += priv-\u003enum_tx_rings_p_up;\n--\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c=3165=static int mlx5e_netdev_set_tcs(struct net_device *netdev, u16 nch, u8 ntc,\n--\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c-3185-\t\toffset = tc_to_txq[tc].offset;\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c:3186:\t\tnetdev_set_tc_queue(netdev, tc, count, offset);\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c-3187-\t}\n--\ndrivers/net/ethernet/microchip/lan966x/lan966x_mqprio.c=5=int lan966x_mqprio_add(struct lan966x_port *port, u8 num_tc)\n--\ndrivers/net/ethernet/microchip/lan966x/lan966x_mqprio.c-17-\tfor (i = 0; i \u003c num_tc; ++i)\ndrivers/net/ethernet/microchip/lan966x/lan966x_mqprio.c:18:\t\tnetdev_set_tc_queue(port-\u003edev, i, 1, i);\ndrivers/net/ethernet/microchip/lan966x/lan966x_mqprio.c-19-\n--\ndrivers/net/ethernet/microchip/sparx5/sparx5_qos.c=476=int sparx5_tc_mqprio_add(struct net_device *ndev, u8 num_tc)\n--\ndrivers/net/ethernet/microchip/sparx5/sparx5_qos.c-488-\tfor (i = 0; i \u003c num_tc; i++)\ndrivers/net/ethernet/microchip/sparx5/sparx5_qos.c:489:\t\tnetdev_set_tc_queue(ndev, i, 1, i);\ndrivers/net/ethernet/microchip/sparx5/sparx5_qos.c-490-\n--\ndrivers/net/ethernet/mscc/ocelot.c=2965=int ocelot_port_mqprio(struct ocelot *ocelot, int port,\n--\ndrivers/net/ethernet/mscc/ocelot.c-2989-\ndrivers/net/ethernet/mscc/ocelot.c:2990:\t\terr = netdev_set_tc_queue(dev, tc, 1, qopt-\u003eoffset[tc]);\ndrivers/net/ethernet/mscc/ocelot.c-2991-\t\tif (err)\n--\ndrivers/net/ethernet/qlogic/qede/qede_main.c=615=static int qede_setup_tc(struct net_device *ndev, u8 num_tc)\n--\ndrivers/net/ethernet/qlogic/qede/qede_main.c-628-\t\toffset = cos * QEDE_TSS_COUNT(edev);\ndrivers/net/ethernet/qlogic/qede/qede_main.c:629:\t\tnetdev_set_tc_queue(ndev, cos, count, offset);\ndrivers/net/ethernet/qlogic/qede/qede_main.c-630-\t}\n--\ndrivers/net/ethernet/stmicro/stmmac/stmmac_tc.c=1250=static int tc_setup_dwmac510_mqprio(struct stmmac_priv *priv,\n--\ndrivers/net/ethernet/stmicro/stmmac/stmmac_tc.c-1273-\ndrivers/net/ethernet/stmicro/stmmac/stmmac_tc.c:1274:\t\terr = netdev_set_tc_queue(ndev, tc, count, offset);\ndrivers/net/ethernet/stmicro/stmmac/stmmac_tc.c-1275-\t\tif (err)\n--\ndrivers/net/ethernet/ti/am65-cpsw-qos.c=203=static int am65_cpsw_setup_mqprio(struct net_device *ndev, void *type_data)\n--\ndrivers/net/ethernet/ti/am65-cpsw-qos.c-256-\t\toffset = qopt-\u003eoffset[tc];\ndrivers/net/ethernet/ti/am65-cpsw-qos.c:257:\t\tnetdev_set_tc_queue(ndev, tc, count, offset);\ndrivers/net/ethernet/ti/am65-cpsw-qos.c-258-\t}\n--\ndrivers/net/ethernet/ti/cpsw_priv.c=996=static int cpsw_set_mqprio(struct net_device *ndev, void *type_data)\n--\ndrivers/net/ethernet/ti/cpsw_priv.c-1027-\t\t\toffset = mqprio-\u003eqopt.offset[i];\ndrivers/net/ethernet/ti/cpsw_priv.c:1028:\t\t\tnetdev_set_tc_queue(ndev, i, count, offset);\ndrivers/net/ethernet/ti/cpsw_priv.c-1029-\t\t}\n--\ndrivers/net/ethernet/ti/netcp_core.c=1933=static int netcp_setup_tc(struct net_device *dev, enum tc_setup_type type,\n--\ndrivers/net/ethernet/ti/netcp_core.c-1957-\t\tfor (i = 0; i \u003c num_tc; i++)\ndrivers/net/ethernet/ti/netcp_core.c:1958:\t\t\tnetdev_set_tc_queue(dev, i, 1, i);\ndrivers/net/ethernet/ti/netcp_core.c-1959-\t} else {\n--\ndrivers/s390/net/qeth_core_main.c=6979=static void qeth_iqd_set_prio_tc_map(struct net_device *dev,\n--\ndrivers/s390/net/qeth_core_main.c-6993-\tnetdev_set_num_tc(dev, 1);\ndrivers/s390/net/qeth_core_main.c:6994:\tnetdev_set_tc_queue(dev, TC_IQD_UCAST, ucast_txqs,\ndrivers/s390/net/qeth_core_main.c-6995-\t\t\t QETH_IQD_MIN_UCAST_TXQ);\n--\ninclude/linux/netdevice.h=2688=void netdev_reset_tc(struct net_device *dev);\ninclude/linux/netdevice.h:2689:int netdev_set_tc_queue(struct net_device *dev, u8 tc, u16 count, u16 offset);\ninclude/linux/netdevice.h-2690-int netdev_set_num_tc(struct net_device *dev, u8 num_tc);\n--\nnet/core/dev.c=3130=EXPORT_SYMBOL(netdev_reset_tc);\nnet/core/dev.c-3131-\nnet/core/dev.c:3132:int netdev_set_tc_queue(struct net_device *dev, u8 tc, u16 count, u16 offset)\nnet/core/dev.c-3133-{\n--\nnet/core/dev.c-3147-}\nnet/core/dev.c:3148:EXPORT_SYMBOL(netdev_set_tc_queue);\nnet/core/dev.c-3149-\n--\nnet/sched/sch_mqprio.c=345=static int mqprio_init(struct Qdisc *sch, struct nlattr *opt,\n--\nnet/sched/sch_mqprio.c-418-\t\tfor (i = 0; i \u003c qopt-\u003enum_tc; i++)\nnet/sched/sch_mqprio.c:419:\t\t\tnetdev_set_tc_queue(dev, i,\nnet/sched/sch_mqprio.c-420-\t\t\t\t\t qopt-\u003ecount[i], qopt-\u003eoffset[i]);\n--\nnet/sched/sch_taprio.c=1822=static int taprio_change(struct Qdisc *sch, struct nlattr *opt,\n--\nnet/sched/sch_taprio.c-1904-\t\tfor (i = 0; i \u003c mqprio-\u003enum_tc; i++) {\nnet/sched/sch_taprio.c:1905:\t\t\tnetdev_set_tc_queue(dev, i,\nnet/sched/sch_taprio.c-1906-\t\t\t\t\t mqprio-\u003ecount[i],\n"
} |
| 15/2 | 2026/08/12 10:17 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 45058 output: 24 thoughts: 30 Thoughts: Here's my take on those thoughts, from an expert's perspective: **Diving into TC Queue Binding** Okay, so `netdev_set_tc_queue` is exposed, interesting. My immediate thought is, "What's the relationship, or more accurately, the *interaction* here with `netdev_bind_sb_channel_queue`?" My hunch is that they probably work together somehow, maybe even build upon each other. It's almost certain that there's some common purpose, as these functions will almost certainly be interacting with the same underlying structures. I need to understand how these elements function in concert, how and if they influence the traffic control (TC) settings. Is `netdev_set_tc_queue` for configuration, while `netdev_bind_sb_channel_queue` is for applying the configuration to a specific "channel" or data stream? Or is the binding step *dependent* on the TC queue being set up *first*? Gotta figure out the control flow to grasp the implications here. |
| 16/2 | 2026/08/12 10:17 | tool | grepper |
0mArgs:{
"Expression": "netdev_bind_sb_channel_queue"
}Results: {
"Output": "drivers/net/ethernet/intel/i40e/i40e_main.c=7827=static int i40e_fwd_ring_up(struct i40e_vsi *vsi, struct net_device *vdev,\n--\ndrivers/net/ethernet/intel/i40e/i40e_main.c-7840-\t\t\tfor (i = 0; i \u003c num_tc; i++)\ndrivers/net/ethernet/intel/i40e/i40e_main.c:7841:\t\t\t\tnetdev_bind_sb_channel_queue(vsi-\u003enetdev, vdev,\ndrivers/net/ethernet/intel/i40e/i40e_main.c-7842-\t\t\t\t\t\t\t i,\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c=5795=static int ixgbe_fwd_ring_up(struct ixgbe_adapter *adapter,\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c-5812-\tfor (i = 0; i \u003c num_tc; i++)\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c:5813:\t\tnetdev_bind_sb_channel_queue(adapter-\u003enetdev, vdev,\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c-5814-\t\t\t\t\t i, rss_i, baseq + (rss_i * i));\n--\ninclude/linux/netdevice.h=2714=void netdev_unbind_sb_channel(struct net_device *dev,\ninclude/linux/netdevice.h-2715-\t\t\t struct net_device *sb_dev);\ninclude/linux/netdevice.h:2716:int netdev_bind_sb_channel_queue(struct net_device *dev,\ninclude/linux/netdevice.h-2717-\t\t\t\t struct net_device *sb_dev,\n--\nnet/core/dev.c=3184=EXPORT_SYMBOL(netdev_unbind_sb_channel);\nnet/core/dev.c-3185-\nnet/core/dev.c:3186:int netdev_bind_sb_channel_queue(struct net_device *dev,\nnet/core/dev.c-3187-\t\t\t\t struct net_device *sb_dev,\n--\nnet/core/dev.c-3213-}\nnet/core/dev.c:3214:EXPORT_SYMBOL(netdev_bind_sb_channel_queue);\nnet/core/dev.c-3215-\n"
} |
| 17/2 | 2026/08/12 10:17 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 46004 output: 22 thoughts: 30 Thoughts: Here's a summary of my thought process, as requested: **Digging into the Network Device Subsystem** Okay, so `netdev_bind_sb_channel_queue` is exported. That's a good starting point. My initial thought is to figure out the relationship here. Knowing that it's exported means it's designed for use outside of the core subsystem, probably by a driver or some other module. Let's see how this works within the broader context. My next immediate instinct is to look into `netdev_set_sb_channel`. I suspect there's a connection between these two functions, and likely `netdev_set_sb_channel` will shed light on the purpose of this binding. I bet that's where the actual assignment or configuration is happening. I need to understand how the "sb" channel is set up and what the overall intention is. I need to see the dependencies. I have to see the data flow here. |
| 18/2 | 2026/08/12 10:17 | tool | grepper |
0mArgs:{
"Expression": "netdev_set_sb_channel"
}Results: {
"Output": "drivers/net/ethernet/intel/i40e/i40e_main.c=7782=static void i40e_free_macvlan_channels(struct i40e_vsi *vsi)\n--\ndrivers/net/ethernet/intel/i40e/i40e_main.c-7796-\t\t\tnetdev_unbind_sb_channel(vsi-\u003enetdev, ch-\u003efwd-\u003enetdev);\ndrivers/net/ethernet/intel/i40e/i40e_main.c:7797:\t\t\tnetdev_set_sb_channel(ch-\u003efwd-\u003enetdev, 0);\ndrivers/net/ethernet/intel/i40e/i40e_main.c-7798-\t\t\tkfree(ch-\u003efwd);\n--\ndrivers/net/ethernet/intel/i40e/i40e_main.c=8001=static void *i40e_fwd_add(struct net_device *netdev, struct net_device *vdev)\n--\ndrivers/net/ethernet/intel/i40e/i40e_main.c-8086-\tfwd-\u003ebit_no = avail_macvlan;\ndrivers/net/ethernet/intel/i40e/i40e_main.c:8087:\tnetdev_set_sb_channel(vdev, avail_macvlan);\ndrivers/net/ethernet/intel/i40e/i40e_main.c-8088-\tfwd-\u003enetdev = vdev;\n--\ndrivers/net/ethernet/intel/i40e/i40e_main.c-8097-\t\tnetdev_unbind_sb_channel(netdev, vdev);\ndrivers/net/ethernet/intel/i40e/i40e_main.c:8098:\t\tnetdev_set_sb_channel(vdev, 0);\ndrivers/net/ethernet/intel/i40e/i40e_main.c-8099-\n--\ndrivers/net/ethernet/intel/i40e/i40e_main.c=8111=static void i40e_del_all_macvlans(struct i40e_vsi *vsi)\n--\ndrivers/net/ethernet/intel/i40e/i40e_main.c-8131-\t\t\t\t\t\t\t ch-\u003efwd-\u003enetdev);\ndrivers/net/ethernet/intel/i40e/i40e_main.c:8132:\t\t\t\tnetdev_set_sb_channel(ch-\u003efwd-\u003enetdev, 0);\ndrivers/net/ethernet/intel/i40e/i40e_main.c-8133-\t\t\t\tkfree(ch-\u003efwd);\n--\ndrivers/net/ethernet/intel/i40e/i40e_main.c=8145=static void i40e_fwd_del(struct net_device *netdev, void *vdev)\n--\ndrivers/net/ethernet/intel/i40e/i40e_main.c-8167-\t\t\t\tnetdev_unbind_sb_channel(netdev, fwd-\u003enetdev);\ndrivers/net/ethernet/intel/i40e/i40e_main.c:8168:\t\t\t\tnetdev_set_sb_channel(fwd-\u003enetdev, 0);\ndrivers/net/ethernet/intel/i40e/i40e_main.c-8169-\t\t\t\tkfree(ch-\u003efwd);\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c=5795=static int ixgbe_fwd_ring_up(struct ixgbe_adapter *adapter,\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c-5841-\tnetdev_unbind_sb_channel(adapter-\u003enetdev, vdev);\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c:5842:\tnetdev_set_sb_channel(vdev, 0);\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c-5843-\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c=9845=static int ixgbe_reassign_macvlan_pool(struct net_device *vdev,\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c-9874-\tnetdev_unbind_sb_channel(adapter-\u003enetdev, vdev);\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c:9875:\tnetdev_set_sb_channel(vdev, 0);\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c-9876-\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c=10741=static void *ixgbe_fwd_add(struct net_device *pdev, struct net_device *vdev)\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c-10822-\tset_bit(pool, adapter-\u003efwd_bitmask);\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c:10823:\tnetdev_set_sb_channel(vdev, pool);\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c-10824-\taccel-\u003epool = pool;\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c=10837=static void ixgbe_fwd_del(struct net_device *pdev, void *priv)\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c-10866-\tnetdev_unbind_sb_channel(pdev, accel-\u003enetdev);\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c:10867:\tnetdev_set_sb_channel(accel-\u003enetdev, 0);\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c-10868-\n--\ninclude/linux/netdevice.h=2716=int netdev_bind_sb_channel_queue(struct net_device *dev,\n--\ninclude/linux/netdevice.h-2718-\t\t\t\t u8 tc, u16 count, u16 offset);\ninclude/linux/netdevice.h:2719:int netdev_set_sb_channel(struct net_device *dev, u16 channel);\ninclude/linux/netdevice.h-2720-static inline int netdev_get_sb_channel(struct net_device *dev)\n--\nnet/core/dev.c=3214=EXPORT_SYMBOL(netdev_bind_sb_channel_queue);\nnet/core/dev.c-3215-\nnet/core/dev.c:3216:int netdev_set_sb_channel(struct net_device *dev, u16 channel)\nnet/core/dev.c-3217-{\n--\nnet/core/dev.c-3233-}\nnet/core/dev.c:3234:EXPORT_SYMBOL(netdev_set_sb_channel);\nnet/core/dev.c-3235-\n"
} |
| 19/2 | 2026/08/12 10:17 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 48150 output: 20 thoughts: 26 Thoughts: Here's my take on the thought process, as if it were my own: **Investigating Network Device Traffic Control** Okay, so `netdev_set_sb_channel` is an exported function. That's good to know, means it's accessible. But what does it interact with? My immediate thought is to look at how it relates to the traffic control system. Let's see... what's the function that's most likely to be involved in resetting traffic control settings on a network device? Ah, yes, `netdev_reset_tc`. Let me check out that function. Where is it called, and how does it affect the network device? This could give some vital context to how `netdev_set_sb_channel` works, and where its importance lies within the broader TC structure. |
| 20/2 | 2026/08/12 10:17 | tool | grepper |
0mArgs:{
"Expression": "netdev_reset_tc"
}Results: {
"Output": "drivers/net/ethernet/amd/xgbe/xgbe-dev.c=2630=static void xgbe_config_tc(struct xgbe_prv_data *pdata)\n--\ndrivers/net/ethernet/amd/xgbe/xgbe-dev.c-2634-\ndrivers/net/ethernet/amd/xgbe/xgbe-dev.c:2635:\tnetdev_reset_tc(pdata-\u003enetdev);\ndrivers/net/ethernet/amd/xgbe/xgbe-dev.c-2636-\tif (!pdata-\u003enum_tcs)\n--\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c=2996=int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)\n--\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c-3057-\tbnx2x_tx_disable(bp);\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c:3058:\tnetdev_reset_tc(bp-\u003edev);\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c-3059-\n--\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c=4254=int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)\n--\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c-4264-\tif (!num_tc) {\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c:4265:\t\tnetdev_reset_tc(dev);\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c-4266-\t\treturn 0;\n--\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c=14144=static int bnx2x_eeh_nic_unload(struct bnx2x *bp)\n--\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c-14154-\tbnx2x_tx_disable(bp);\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c:14155:\tnetdev_reset_tc(bp-\u003edev);\ndrivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c-14156-\n--\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c=11658=int bnxt_reserve_rings(struct bnxt *bp, bool irq_re_init)\n--\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c-11703-\t\tnetdev_err(bp-\u003edev, \"tx ring reservation failure\\n\");\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c:11704:\t\tnetdev_reset_tc(bp-\u003edev);\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c-11705-\t\tbp-\u003enum_tc = 0;\n--\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c=15646=int bnxt_setup_mq_tc(struct net_device *dev, u8 tc)\n--\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c-15678-\t\tbp-\u003etx_nr_rings = bp-\u003etx_nr_rings_per_tc;\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c:15679:\t\tnetdev_reset_tc(dev);\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c-15680-\t\tbp-\u003enum_tc = 0;\n--\ndrivers/net/ethernet/cadence/macb_main.c=4474=static void macb_taprio_destroy(struct net_device *ndev)\n--\ndrivers/net/ethernet/cadence/macb_main.c-4480-\ndrivers/net/ethernet/cadence/macb_main.c:4481:\tnetdev_reset_tc(ndev);\ndrivers/net/ethernet/cadence/macb_main.c-4482-\tqueue_mask = BIT_U32(bp-\u003enum_queues) - 1;\n--\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c=424=static int cxgb4_mqprio_enable_offload(struct net_device *dev,\n--\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c-505-out_reset_tc:\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c:506:\tnetdev_reset_tc(dev);\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c-507-\ti = mqprio-\u003eqopt.num_tc;\n--\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c=528=static void cxgb4_mqprio_disable_offload(struct net_device *dev)\n--\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c-541-\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c:542:\tnetdev_reset_tc(dev);\ndrivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c-543-\tnetif_set_real_num_tx_queues(dev, pi-\u003enqsets);\n--\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c=369=static int dpaa_setup_tc(struct net_device *net_dev, enum tc_setup_type type,\n--\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c-387-\tif (!num_tc) {\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c:388:\t\tnetdev_reset_tc(net_dev);\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c-389-\t\tgoto out;\n--\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c=2940=static int dpaa2_eth_setup_mqprio(struct net_device *net_dev,\n--\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c-2960-\tif (!num_tc) {\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c:2961:\t\tnetdev_reset_tc(net_dev);\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c-2962-\t\tnetif_set_real_num_tx_queues(net_dev, num_queues);\n--\ndrivers/net/ethernet/freescale/enetc/enetc.c=3153=void enetc_reset_tc_mqprio(struct net_device *ndev)\n--\ndrivers/net/ethernet/freescale/enetc/enetc.c-3162-\ndrivers/net/ethernet/freescale/enetc/enetc.c:3163:\tnetdev_reset_tc(ndev);\ndrivers/net/ethernet/freescale/enetc/enetc.c-3164-\tnetif_set_real_num_tx_queues(ndev, num_stack_tx_queues);\n--\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c=618=static int hns3_nic_set_real_num_queue(struct net_device *netdev)\n--\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c-626-\tif (tc_info-\u003enum_tc \u003c= 1 \u0026\u0026 !tc_info-\u003emqprio_active) {\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c:627:\t\tnetdev_reset_tc(netdev);\ndrivers/net/ethernet/hisilicon/hns3/hns3_enet.c-628-\t} else {\n--\ndrivers/net/ethernet/intel/fm10k/fm10k_netdev.c=1263=int fm10k_setup_tc(struct net_device *dev, u8 tc)\n--\ndrivers/net/ethernet/intel/fm10k/fm10k_netdev.c-1287-\t/* we expect the prio_tc map to be repopulated later */\ndrivers/net/ethernet/intel/fm10k/fm10k_netdev.c:1288:\tnetdev_reset_tc(dev);\ndrivers/net/ethernet/intel/fm10k/fm10k_netdev.c-1289-\tnetdev_set_num_tc(dev, tc);\n--\ndrivers/net/ethernet/intel/i40e/i40e_main.c=5650=static void i40e_vsi_config_netdev_tc(struct i40e_vsi *vsi, u8 enabled_tc)\n--\ndrivers/net/ethernet/intel/i40e/i40e_main.c-5662-\tif (!enabled_tc) {\ndrivers/net/ethernet/intel/i40e/i40e_main.c:5663:\t\tnetdev_reset_tc(netdev);\ndrivers/net/ethernet/intel/i40e/i40e_main.c-5664-\t\treturn;\n--\ndrivers/net/ethernet/intel/iavf/iavf_main.c=3679=static int __iavf_setup_tc(struct net_device *netdev, void *type_data)\n--\ndrivers/net/ethernet/intel/iavf/iavf_main.c-3696-\t\t\t/* reset the tc configuration */\ndrivers/net/ethernet/intel/iavf/iavf_main.c:3697:\t\t\tnetdev_reset_tc(netdev);\ndrivers/net/ethernet/intel/iavf/iavf_main.c-3698-\t\t\tadapter-\u003enum_tc = 0;\n--\ndrivers/net/ethernet/intel/iavf/iavf_main.c-3764-\t\tadapter-\u003eaq_required |= IAVF_FLAG_AQ_ENABLE_CHANNELS;\ndrivers/net/ethernet/intel/iavf/iavf_main.c:3765:\t\tnetdev_reset_tc(netdev);\ndrivers/net/ethernet/intel/iavf/iavf_main.c-3766-\t\t/* Report the tc mapping up the stack */\n--\ndrivers/net/ethernet/intel/iavf/iavf_virtchnl.c=2292=void iavf_virtchnl_completion(struct iavf_adapter *adapter,\n--\ndrivers/net/ethernet/intel/iavf/iavf_virtchnl.c-2377-\t\t\tadapter-\u003ech_config.state = __IAVF_TC_INVALID;\ndrivers/net/ethernet/intel/iavf/iavf_virtchnl.c:2378:\t\t\tnetdev_reset_tc(netdev);\ndrivers/net/ethernet/intel/iavf/iavf_virtchnl.c-2379-\t\t\tnetif_tx_start_all_queues(netdev);\n--\ndrivers/net/ethernet/intel/ice/ice_lib.c=3201=void ice_vsi_cfg_netdev_tc(struct ice_vsi *vsi, u8 ena_tc)\n--\ndrivers/net/ethernet/intel/ice/ice_lib.c-3217-\tif (!ena_tc) {\ndrivers/net/ethernet/intel/ice/ice_lib.c:3218:\t\tnetdev_reset_tc(netdev);\ndrivers/net/ethernet/intel/ice/ice_lib.c-3219-\t\treturn;\n--\ndrivers/net/ethernet/intel/igc/igc_main.c=6764=static int igc_tsn_enable_mqprio(struct igc_adapter *adapter,\n--\ndrivers/net/ethernet/intel/igc/igc_main.c-6775-\t\tigc_fpe_clear_preempt_queue(adapter);\ndrivers/net/ethernet/intel/igc/igc_main.c:6776:\t\tnetdev_reset_tc(adapter-\u003enetdev);\ndrivers/net/ethernet/intel/igc/igc_main.c-6777-\t\tgoto apply;\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c=1170=static void ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter)\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c-1185-\t\te_dev_warn(\"Number of DCB TCs exceeds number of available queues. Disabling DCB support.\\n\");\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c:1186:\t\tnetdev_reset_tc(adapter-\u003enetdev);\ndrivers/net/ethernet/intel/ixgbe/ixgbe_lib.c-1187-\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c=9903=int ixgbe_setup_tc(struct net_device *dev, u8 tc)\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c-9947-\t} else {\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c:9948:\t\tnetdev_reset_tc(dev);\ndrivers/net/ethernet/intel/ixgbe/ixgbe_main.c-9949-\n--\ndrivers/net/ethernet/marvell/mvneta.c=5240=static int mvneta_setup_mqprio(struct net_device *dev,\n--\ndrivers/net/ethernet/marvell/mvneta.c-5258-\t\tmvneta_disable_per_queue_rate_limit(pp);\ndrivers/net/ethernet/marvell/mvneta.c:5259:\t\tnetdev_reset_tc(dev);\ndrivers/net/ethernet/marvell/mvneta.c-5260-\t\treturn 0;\n--\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c=3165=static int mlx5e_netdev_set_tcs(struct net_device *netdev, u16 nch, u8 ntc,\n--\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c-3169-\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c:3170:\tnetdev_reset_tc(netdev);\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c-3171-\n--\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c=6548=static void mlx5e_reset_channels(struct net_device *netdev)\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c-6549-{\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c:6550:\tnetdev_reset_tc(netdev);\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c-6551-}\n--\ndrivers/net/ethernet/microchip/lan966x/lan966x_mqprio.c=23=int lan966x_mqprio_del(struct lan966x_port *port)\ndrivers/net/ethernet/microchip/lan966x/lan966x_mqprio.c-24-{\ndrivers/net/ethernet/microchip/lan966x/lan966x_mqprio.c:25:\tnetdev_reset_tc(port-\u003edev);\ndrivers/net/ethernet/microchip/lan966x/lan966x_mqprio.c-26-\n--\ndrivers/net/ethernet/microchip/sparx5/sparx5_qos.c=497=int sparx5_tc_mqprio_del(struct net_device *ndev)\ndrivers/net/ethernet/microchip/sparx5/sparx5_qos.c-498-{\ndrivers/net/ethernet/microchip/sparx5/sparx5_qos.c:499:\tnetdev_reset_tc(ndev);\ndrivers/net/ethernet/microchip/sparx5/sparx5_qos.c-500-\n--\ndrivers/net/ethernet/mscc/ocelot.c=2957=static void ocelot_port_reset_mqprio(struct ocelot *ocelot, int port)\n--\ndrivers/net/ethernet/mscc/ocelot.c-2960-\ndrivers/net/ethernet/mscc/ocelot.c:2961:\tnetdev_reset_tc(dev);\ndrivers/net/ethernet/mscc/ocelot.c-2962-\tocelot_port_change_fp(ocelot, port, 0);\n--\ndrivers/net/ethernet/qlogic/qede/qede_main.c=615=static int qede_setup_tc(struct net_device *ndev, u8 num_tc)\n--\ndrivers/net/ethernet/qlogic/qede/qede_main.c-622-\ndrivers/net/ethernet/qlogic/qede/qede_main.c:623:\tnetdev_reset_tc(ndev);\ndrivers/net/ethernet/qlogic/qede/qede_main.c-624-\tnetdev_set_num_tc(ndev, num_tc);\n--\ndrivers/net/ethernet/stmicro/stmmac/stmmac_tc.c=1240=static void stmmac_reset_tc_mqprio(struct net_device *ndev,\n--\ndrivers/net/ethernet/stmicro/stmmac/stmmac_tc.c-1244-\ndrivers/net/ethernet/stmicro/stmmac/stmmac_tc.c:1245:\tnetdev_reset_tc(ndev);\ndrivers/net/ethernet/stmicro/stmmac/stmmac_tc.c-1246-\tnetif_set_real_num_tx_queues(ndev, priv-\u003eplat-\u003etx_queues_to_use);\n--\ndrivers/net/ethernet/ti/am65-cpsw-qos.c=186=static void am65_cpsw_reset_tc_mqprio(struct net_device *ndev)\n--\ndrivers/net/ethernet/ti/am65-cpsw-qos.c-194-\tam65_cpsw_tx_pn_shaper_reset(port);\ndrivers/net/ethernet/ti/am65-cpsw-qos.c:195:\tnetdev_reset_tc(ndev);\ndrivers/net/ethernet/ti/am65-cpsw-qos.c-196-\n--\ndrivers/net/ethernet/ti/cpsw_priv.c=996=static int cpsw_set_mqprio(struct net_device *ndev, void *type_data)\n--\ndrivers/net/ethernet/ti/cpsw_priv.c-1033-\t\t/* restore default configuration */\ndrivers/net/ethernet/ti/cpsw_priv.c:1034:\t\tnetdev_reset_tc(ndev);\ndrivers/net/ethernet/ti/cpsw_priv.c-1035-\t\ttx_prio_map = TX_PRIORITY_MAPPING;\n--\ndrivers/net/ethernet/ti/netcp_core.c=1933=static int netcp_setup_tc(struct net_device *dev, enum tc_setup_type type,\n--\ndrivers/net/ethernet/ti/netcp_core.c-1959-\t} else {\ndrivers/net/ethernet/ti/netcp_core.c:1960:\t\tnetdev_reset_tc(dev);\ndrivers/net/ethernet/ti/netcp_core.c-1961-\t}\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c=618=int ngbe_setup_tc(struct net_device *dev, u8 tc)\n--\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-635-\telse\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c:636:\t\tnetdev_reset_tc(dev);\ndrivers/net/ethernet/wangxun/ngbe/ngbe_main.c-637-\n--\ndrivers/net/ethernet/wangxun/txgbe/txgbe_main.c=611=int txgbe_setup_tc(struct net_device *dev, u8 tc)\n--\ndrivers/net/ethernet/wangxun/txgbe/txgbe_main.c-628-\telse\ndrivers/net/ethernet/wangxun/txgbe/txgbe_main.c:629:\t\tnetdev_reset_tc(dev);\ndrivers/net/ethernet/wangxun/txgbe/txgbe_main.c-630-\n--\ninclude/linux/netdevice.h=2687=int netdev_txq_to_tc(struct net_device *dev, unsigned int txq);\ninclude/linux/netdevice.h:2688:void netdev_reset_tc(struct net_device *dev);\ninclude/linux/netdevice.h-2689-int netdev_set_tc_queue(struct net_device *dev, u8 tc, u16 count, u16 offset);\n--\nnet/core/dev.c=3103=static void netdev_unbind_all_sb_channels(struct net_device *dev)\n--\nnet/core/dev.c-3113-\nnet/core/dev.c:3114:void netdev_reset_tc(struct net_device *dev)\nnet/core/dev.c-3115-{\n--\nnet/core/dev.c-3129-}\nnet/core/dev.c:3130:EXPORT_SYMBOL(netdev_reset_tc);\nnet/core/dev.c-3131-\n--\nnet/sched/sch_taprio.c=2032=static void taprio_destroy(struct Qdisc *sch)\n--\nnet/sched/sch_taprio.c-2056-\nnet/sched/sch_taprio.c:2057:\tnetdev_reset_tc(dev);\nnet/sched/sch_taprio.c-2058-\n"
} |
| 21/2 | 2026/08/12 10:17 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 54360 output: 24 thoughts: 28 Thoughts: Okay, here's my interpretation of those thoughts, tailored for an expert audience, presented in the first person: **Investigating Network Device Traffic Control Reset** Right, `netdev_reset_tc` is exposed. Okay, that's interesting. I immediately want to delve into how this function interacts with the XPS (Express Path Selection) queue setup. Let's see... the logical next step is to examine `__netif_set_xps_queue`. My experience tells me that a traffic control reset likely impacts XPS, potentially clearing or re-initializing the queue assignments. I need to understand the relationship between the TC parameters and the XPS setup to see the impact of such a reset. Is this function going to clear queues, re-calculate them, or just notify the XPS setup to reload the configurations? This connection is key. I'll need to look at how this is being used and the potential implications it can have on traffic shaping and performance. |
| 22/2 | 2026/08/12 10:17 | tool | grepper |
0mArgs:{
"Expression": "__netif_set_xps_queue"
}Results: {
"Output": "Documentation/networking/net_cachelines/net_device.rst=119=struct xdp_dev_bulk_queue__percpu* xdp_bulkq\nDocumentation/networking/net_cachelines/net_device.rst:120:struct xps_dev_maps* xps_maps[2] read_mostly __netif_set_xps_queue\nDocumentation/networking/net_cachelines/net_device.rst-121-struct bpf_mprog_entry tcx_egress read_mostly sch_handle_egress\n--\ndrivers/net/ethernet/ibm/ibmvnic.c=257=static void ibmvnic_set_affinity(struct ibmvnic_adapter *adapter)\n--\ndrivers/net/ethernet/ibm/ibmvnic.c-303-\ndrivers/net/ethernet/ibm/ibmvnic.c:304:\t\trc = __netif_set_xps_queue(adapter-\u003enetdev,\ndrivers/net/ethernet/ibm/ibmvnic.c-305-\t\t\t\t\t cpumask_bits(queue-\u003eaffinity_mask),\n--\ndrivers/net/virtio_net.c=3961=static void virtnet_set_affinity(struct virtnet_info *vi)\n--\ndrivers/net/virtio_net.c-3993-\t\tvirtqueue_set_affinity(vi-\u003esq[i].vq, mask);\ndrivers/net/virtio_net.c:3994:\t\t__netif_set_xps_queue(vi-\u003edev, cpumask_bits(mask), i, XPS_CPUS);\ndrivers/net/virtio_net.c-3995-\t\tcpumask_clear(mask);\n--\ninclude/linux/netdevice.h=4163=int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,\ninclude/linux/netdevice.h-4164-\t\t\tu16 index);\ninclude/linux/netdevice.h:4165:int __netif_set_xps_queue(struct net_device *dev, const unsigned long *mask,\ninclude/linux/netdevice.h-4166-\t\t\t u16 index, enum xps_map_type type);\n--\ninclude/linux/netdevice.h=4254=static inline int netif_set_xps_queue(struct net_device *dev,\n--\ninclude/linux/netdevice.h-4260-\ninclude/linux/netdevice.h:4261:static inline int __netif_set_xps_queue(struct net_device *dev,\ninclude/linux/netdevice.h-4262-\t\t\t\t\tconst unsigned long *mask,\n--\nnet/core/dev.c=2865=static void xps_copy_dev_maps(struct xps_dev_maps *dev_maps,\n--\nnet/core/dev.c-2883-/* Must be called under cpus_read_lock */\nnet/core/dev.c:2884:int __netif_set_xps_queue(struct net_device *dev, const unsigned long *mask,\nnet/core/dev.c-2885-\t\t\t u16 index, enum xps_map_type type)\n--\nnet/core/dev.c-3086-}\nnet/core/dev.c:3087:EXPORT_SYMBOL_GPL(__netif_set_xps_queue);\nnet/core/dev.c-3088-\nnet/core/dev.c=3089=int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,\n--\nnet/core/dev.c-3094-\tcpus_read_lock();\nnet/core/dev.c:3095:\tret = __netif_set_xps_queue(dev, cpumask_bits(mask), index, XPS_CPUS);\nnet/core/dev.c-3096-\tcpus_read_unlock();\n--\nnet/core/net-sysfs.c=1848=static ssize_t xps_rxqs_store(struct kobject *kobj, struct attribute *attr,\n--\nnet/core/net-sysfs.c-1879-\tcpus_read_lock();\nnet/core/net-sysfs.c:1880:\terr = __netif_set_xps_queue(dev, mask, index, XPS_RXQS);\nnet/core/net-sysfs.c-1881-\tcpus_read_unlock();\n"
} |
| 23/2 | 2026/08/12 10:17 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 55755 output: 22 thoughts: 287 Thoughts: **My Analysis of Potential Attack Surfaces** Okay, so I'm looking at this exported function, `__netif_set_xps_queue`, and seeing that it's being used by `xps_rxqs_store`, which is accessible through sysfs. That's a direct route into the system that I need to investigate. My focus needs to be on potential vulnerability points. So, I need to check: - `netdev_set_tc_queue` - `netdev_set_num_tc` - `netdev_bind_sb_channel_queue` - `netdev_set_sb_channel` - `netdev_reset_tc` - `__netif_set_xps_queue` - `mqprio_qopt_reconstruct` - `taprio_change` Let's see, ah, `taprio_change`... Yes, that's a Qdisc change callback. Good, that means it's accessible through the Qdisc interface, which is worth a look. And `mqprio_qopt_reconstruct`, ah, that's used in `mqprio_dump` and `taprio_dump`. And wait... `mqprio_dump` is a Qdisc dump callback. Interesting! That increases the attack surface here. Now, let's nail down what CONFIG options might be relevant to any vulnerabilities I find. For `mqprio` and `taprio`, I'll need to confirm that `NET_SCH_MQPRIO` and `NET_SCH_TAPRIO` are enabled. And for XPS, of course, I need to check for `XPS`. I'll dive into the Kconfig files now to verify the dependencies. |
| 24/2 | 2026/08/12 10:18 | tool | grepper |
0mArgs:{
"Expression": "config NET_SCH_MQPRIO"
}Results: {
"Output": "net/sched/Kconfig=156=config NET_SCH_ETF\n--\nnet/sched/Kconfig-166-\nnet/sched/Kconfig:167:config NET_SCH_MQPRIO_LIB\nnet/sched/Kconfig-168-\ttristate\n--\nnet/sched/Kconfig=207=config NET_SCH_DRR\n--\nnet/sched/Kconfig-217-\nnet/sched/Kconfig:218:config NET_SCH_MQPRIO\nnet/sched/Kconfig-219-\ttristate \"Multi-queue priority scheduler (MQPRIO)\"\n"
} |
| 25/2 | 2026/08/12 10:18 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 56618 output: 21 thoughts: 12 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience, presented in the first person: **Deep Dive on `NET_SCH_TAPRIO`** Alright, time to circle back and give `NET_SCH_TAPRIO` a good once-over. I need to refresh my understanding of how this particular scheduler functions. I'm especially interested in its implications for… well, pretty much everything network-related right now. The nuances here can make or break performance in certain critical applications, so it warrants a dedicated look. I want to quickly identify its strengths and also any potential weaknesses. I'll need to re-examine those design trade-offs, particularly those that impact queue management and traffic shaping. Let's see what I can learn, and how I can apply it to my projects. |
| 26/2 | 2026/08/12 10:18 | tool | grepper |
0mArgs:{
"Expression": "config NET_SCH_TAPRIO"
}Results: {
"Output": "net/sched/Kconfig=167=config NET_SCH_MQPRIO_LIB\n--\nnet/sched/Kconfig-171-\nnet/sched/Kconfig:172:config NET_SCH_TAPRIO\nnet/sched/Kconfig-173-\ttristate \"Time Aware Priority (taprio) Scheduler\"\n"
} |
| 27/2 | 2026/08/12 10:18 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 56915 output: 16 thoughts: 8 Thoughts: Okay, here's my attempt at summarizing the thought process, tailored for an expert audience, and written in the first person: **XPS Review - Initial Assessment** Alright, time to dive into the data. First, let's take a quick look at the `XPS` data. I need to get a baseline understanding of the surface chemistry. What are the key elements present? Any obvious contamination peaks I need to account for? I'll be looking for binding energy shifts to indicate oxidation states or chemical environments. Are the peak shapes and widths as expected for the material and preparation method? Any unexpected broadening could point to heterogeneity or even sample degradation. I'll need to correlate this with any SEM or EDS results. The angle-resolved XPS information might be particularly crucial here - it can give us an idea of the depth profile, and perhaps allow to distinguish between surface contaminants and bulk components. Need to compare it with any known standards or reference spectra for the expected composition. Time to make some mental notes, and then move forward into further analysis. |
| 28/2 | 2026/08/12 10:18 | tool | grepper |
0mArgs:{
"Expression": "config XPS"
}Results: {
"Output": "drivers/usb/host/Kconfig=209=config USB_EHCI_PCI\n--\ndrivers/usb/host/Kconfig-213-\ndrivers/usb/host/Kconfig:214:config XPS_USB_HCD_XILINX\ndrivers/usb/host/Kconfig-215-\tbool \"Use Xilinx usb host EHCI controller core\"\n--\nnet/Kconfig=322=config SOCK_RX_QUEUE_MAPPING\n--\nnet/Kconfig-324-\nnet/Kconfig:325:config XPS\nnet/Kconfig-326-\tbool\n"
} |
| 29/2 | 2026/08/12 10:18 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 57315 output: 16 thoughts: 22 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience and presented in the first person: **Digging into the `XPS` Boolean** Alright, so `XPS` is flagged as a boolean. My immediate thought is, "Okay, what's driving this thing?" I need to understand its dependencies. Is it a configuration flag? A result of some prior calculation or state check? I need to trace back from it to see what conditions set it to `true` or `false`. More importantly, I need to figure out which other parts of the system are *relying* on this boolean's state. What code branches, what algorithms, what data structures – they're all impacted, directly or indirectly, by the value of `XPS`. Time to start digging through the code and figure out what selects it. Understanding those dependencies is key. |
| 30/2 | 2026/08/12 10:18 | tool | grepper |
0mError:no matches Args: {
"Expression": "select XPS"
}Results: {
"error": "no matches"
} |
| 31/2 | 2026/08/12 10:18 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 57551 output: 32 thoughts: 15 Thoughts: Here's my take on those thoughts: **Navigating the Configuration Landscape** Okay, so I'm thinking... where do I begin to understand this feature? Let's dive right into the kernel configuration. The first thing I'm going to do is check `net/Kconfig`. That's the typical place to find the definition for anything network-related. I need to get a handle on the configuration options related to `config XPS`. Knowing where it's defined will give me a huge head start in understanding its purpose, dependencies, and any other associated configuration settings. This should be a good starting point for understanding how this feature is enabled, disabled, and configured. |
| 32/2 | 2026/08/12 10:18 | tool | read-file |
0mArgs:{
"File": "net/Kconfig",
"FirstLine": 320,
"LineCount": 20
}Results: {
"Contents": " 320:\t\t accelerate RFS.\n 321:\t\n 322:\tconfig SOCK_RX_QUEUE_MAPPING\n 323:\t\tbool\n 324:\t\n 325:\tconfig XPS\n 326:\t\tbool\n 327:\t\tdepends on SMP\n 328:\t\tselect SOCK_RX_QUEUE_MAPPING\n 329:\t\tdefault y\n 330:\t\n 331:\tconfig HWBM\n 332:\t\tbool\n 333:\t\n 334:\tconfig CGROUP_NET_PRIO\n 335:\t\tbool \"Network priority cgroup\"\n 336:\t\tdepends on CGROUPS\n 337:\t\tselect SOCK_CGROUP_DATA\n 338:\t\thelp\n 339:\t\t Cgroup subsystem for use in assigning processes to network priorities on\n"
} |
| 33/2 | 2026/08/12 10:18 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 57973 output: 19 thoughts: 356 Thoughts: **My Initial Assessment of the Patch** Okay, so looking at this, it seems that if the system is SMP, then XPS (Explicit Congestion Notification for packets) is enabled by default. That's good to know. Now, the patch itself is clearly touching a pretty extensive set of network device functions. I see it modifies functions like `netdev_set_tc_queue`, `netdev_set_num_tc`, and a bunch of others that deal with setting up and managing traffic classes, scheduling, and binding queues. This includes core functions and some deeper-level scheduling like the Secure Boot channel, packet hashing, and real queue count setting functions. Given the scope of changes, my initial instinct is that this is *definitely* worth fuzzing. The key functions to focus my attention on are `netdev_set_tc_queue`, `netdev_set_num_tc`, `netdev_bind_sb_channel_queue`, `netdev_set_sb_channel`, `netdev_reset_tc`, `__netif_set_xps_queue`, `mqprio_qopt_reconstruct`, and `taprio_change`. Now, is `taprio_change` the Qdisc change callback for taprio? Let me check. Yep, that's correct. Now, before I go deeper, let me just confirm that `mqprio_init` or `mqprio_change` are there. I need to understand where it's being initiated. |
| 34/2 | 2026/08/12 10:18 | tool | grepper |
0mError:no matches Args: {
"Expression": "mqprio_change"
}Results: {
"error": "no matches"
} |
| 35/2 | 2026/08/12 10:18 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 58682 output: 19 thoughts: 11 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience, presented in the first person: **Analyzing the Initialization Sequence** Alright, time to get my hands dirty. Let's see... the code's instructing me to look closely at `mqprio_init`. This implies we're dealing with message queue priority initialization. Given the scope of this project, I'm assuming we're setting up the foundational elements for a system that's likely using prioritized message passing – perhaps for a real-time system, kernel-level communications, or something similarly performance-critical. My immediate thoughts are, where does this fit within the larger system architecture? Is this the *only* initialization point, or are there dependencies on other subsystems that need to be in place *before* `mqprio_init` is invoked? I'll need to check the call graph to get a clearer picture of the control flow. I'm also curious about the data structures being initialized – is it a simple array of queues, a more sophisticated data structure like a priority heap or something more elaborate using locking primitives? I need to understand the underlying implementation before I can fully assess its potential bottlenecks or threading issues. I'm particularly interested in error handling. Are there sufficient checks for resource exhaustion or memory allocation failures? What happens if initialization fails midway through? A robust initialization routine is crucial for the reliability of the entire message queue system, so I'll be scrutinizing this part closely. Finally, I'll be keeping an eye out for potential races or synchronization problems. If multiple threads are involved in initialization (even indirectly), I need to be sure that this component is thread-safe and properly guarded. This is definitely where I'll be spending the bulk of my effort. |
| 36/2 | 2026/08/12 10:18 | tool | grepper |
0mArgs:{
"Expression": "mqprio_init"
}Results: {
"Output": "net/sched/bpf_qdisc.c=234=__bpf_kfunc int bpf_qdisc_init_prologue(struct Qdisc *sch,\n--\nnet/sched/bpf_qdisc.c-244-\t\t/* If qdisc_lookup() returns NULL, it means .init is called by\nnet/sched/bpf_qdisc.c:245:\t\t * qdisc_create_dflt() in mq/mqprio_init and the parent qdisc\nnet/sched/bpf_qdisc.c-246-\t\t * has not been added to qdisc_hash yet.\n--\nnet/sched/sch_mqprio.c=242=static int mqprio_parse_nlattr(struct Qdisc *sch, struct tc_mqprio_qopt *qopt,\n--\nnet/sched/sch_mqprio.c-344-\nnet/sched/sch_mqprio.c:345:static int mqprio_init(struct Qdisc *sch, struct nlattr *opt,\nnet/sched/sch_mqprio.c-346-\t\t struct netlink_ext_ack *extack)\n--\nnet/sched/sch_mqprio.c=768=static struct Qdisc_ops mqprio_qdisc_ops __read_mostly = {\n--\nnet/sched/sch_mqprio.c-771-\t.priv_size\t= sizeof(struct mqprio_sched),\nnet/sched/sch_mqprio.c:772:\t.init\t\t= mqprio_init,\nnet/sched/sch_mqprio.c-773-\t.destroy\t= mqprio_destroy,\n"
} |
| 37/2 | 2026/08/12 10:18 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 59507 output: 34 thoughts: 200 Thoughts: **Analyzing the Kernel Configuration for MQPRIO and TAPRIO Scheduling** Okay, so I've pinpointed `mqprio_init` as the primary initialization function for the MQPRIO scheduler. Now, the question is, should I include `netif_set_real_num_tx_queues`? It’s frequently used. My initial instinct is that it *might* be too hot – it’s called during device setup and reconfiguration, not during packet processing itself. So, based on that, I'd say it should be okay to include. Hang on a moment... `netif_set_real_num_tx_queues` is *exported* and used by numerous drivers. Given its widespread use, including it is definitely the right move. I need to make sure this is available to any drivers that might need it. Now, let's look at the configs: `NET_SCH_MQPRIO` and `NET_SCH_TAPRIO`. I need to determine if `NET_SCH_MQPRIO_LIB` is also required. Does it get selected by either of those? I'll need to double-check the Kconfig files for both `NET_SCH_MQPRIO` and `NET_SCH_TAPRIO` to confirm their dependencies and ensure that all necessary components are included in this configuration. |
| 38/2 | 2026/08/12 10:18 | tool | read-file |
0mArgs:{
"File": "net/sched/Kconfig",
"FirstLine": 167,
"LineCount": 20
}Results: {
"Contents": " 167:\tconfig NET_SCH_MQPRIO_LIB\n 168:\t\ttristate\n 169:\t\thelp\n 170:\t\t Common library for manipulating mqprio queue configurations.\n 171:\t\n 172:\tconfig NET_SCH_TAPRIO\n 173:\t\ttristate \"Time Aware Priority (taprio) Scheduler\"\n 174:\t\tselect NET_SCH_MQPRIO_LIB\n 175:\t\thelp\n 176:\t\t Say Y here if you want to use the Time Aware Priority (taprio) packet\n 177:\t\t scheduling algorithm.\n 178:\t\n 179:\t\t See the top of \u003cfile:net/sched/sch_taprio.c\u003e for more details.\n 180:\t\n 181:\t\t To compile this code as a module, choose M here: the\n 182:\t\t module will be called sch_taprio.\n 183:\t\n 184:\tconfig NET_SCH_GRED\n 185:\t\ttristate \"Generic Random Early Detection (GRED)\"\n 186:\t\thelp\n"
} |
| 39/2 | 2026/08/12 10:18 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 60325 output: 34 thoughts: 20 Thoughts: Here's my summary, as though I'm thinking through this process: **Network Scheduler Selection and the Underlying Library** Okay, so I'm looking at network schedulers, and this `NET_SCH_TAPRIO` option has been chosen. Immediately, my mind jumps to its implications. Selecting `NET_SCH_TAPRIO` *automatically* pulls in `NET_SCH_MQPRIO_LIB`. That's not surprising; I know TAPRIO (Time-Aware Priority) leverages the Multi-Queue Priority (MQPRIO) foundation. TAPRIO itself likely builds *upon* MQPRIO's capabilities for queue management and traffic shaping, adding the time-aware aspect on top. This is the expected dependency, given the layered architecture of the Linux networking stack. It tells me that my kernel configuration will be including the MQPRIO library to provide the underlying infrastructure that TAPRIO needs to operate, which makes perfect sense from an implementation standpoint. This selection strategy is efficient; it avoids redundant code and promotes a modular design. |
| 40/2 | 2026/08/12 10:18 | tool | read-file |
0mArgs:{
"File": "net/sched/Kconfig",
"FirstLine": 218,
"LineCount": 20
}Results: {
"Contents": " 218:\tconfig NET_SCH_MQPRIO\n 219:\t\ttristate \"Multi-queue priority scheduler (MQPRIO)\"\n 220:\t\tselect NET_SCH_MQPRIO_LIB\n 221:\t\thelp\n 222:\t\t Say Y here if you want to use the Multi-queue Priority scheduler.\n 223:\t\t This scheduler allows QOS to be offloaded on NICs that have support\n 224:\t\t for offloading QOS schedulers.\n 225:\t\n 226:\t\t To compile this driver as a module, choose M here: the module will\n 227:\t\t be called sch_mqprio.\n 228:\t\n 229:\t\t If unsure, say N.\n 230:\t\n 231:\tconfig NET_SCH_SKBPRIO\n 232:\t\ttristate \"SKB priority queue scheduler (SKBPRIO)\"\n 233:\t\thelp\n 234:\t\t Say Y here if you want to use the SKB priority queue\n 235:\t\t scheduler. This schedules packets according to skb-\u003epriority,\n 236:\t\t which is useful for request packets in DoS mitigation systems such\n 237:\t\t as Gatekeeper.\n"
} |
| 41/2 | 2026/08/12 10:18 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 60922 output: 31 thoughts: 538 Thoughts: **Refining the API Selection for Traffic Control Configuration** Okay, so I'm looking at how we're configuring traffic control, specifically with `MQPRIO` and `TAPRIO`. I've noted that enabling `NET_SCH_MQPRIO` implicitly selects `NET_SCH_MQPRIO_LIB`. My initial thought was to identify the key functions. My initial focus was on functions like `netdev_set_tc_queue`, `netdev_set_num_tc`, `netdev_bind_sb_channel_queue`, and so on. Now, the instructions are clear: we want non-static, non-inlined API entrypoints. Let me check the symbols of interest. Okay, `__netif_set_xps_queue` and `mqprio_qopt_reconstruct` are exported with `EXPORT_SYMBOL_GPL`, so those are good. Then I looked at `taprio_change`. It *is* static, but wait... it's a callback within the `taprio_qdisc_ops` struct. That's good - means it's not inlined, since its address is taken. Same for `mqprio_init`. So `taprio_change` and `mqprio_init` are ok. However, `mqprio_qopt_reconstruct` and others, are probably better. So, I'm going to refine that list, giving us a good selection of the right types of functions: `netdev_set_tc_queue`, `netdev_set_num_tc`, `netdev_bind_sb_channel_queue`, `netdev_set_sb_channel`, `netdev_reset_tc`, `__netif_set_xps_queue`, `mqprio_qopt_reconstruct`, and finally `netif_set_real_num_tx_queues`. This should give us a solid set of symbols to work with. |
| 42/2 | 2026/08/12 10:19 | tool | grepper |
0mArgs:{
"Expression": "EXPORT_SYMBOL.*netif_set_real_num_tx_queues"
}Results: {
"Output": "net/core/dev.c=3240=int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)\n--\nnet/core/dev.c-3280-}\nnet/core/dev.c:3281:EXPORT_SYMBOL(netif_set_real_num_tx_queues);\nnet/core/dev.c-3282-\n"
} |
| 43/2 | 2026/08/12 10:19 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 62030 output: 28 thoughts: 24 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Verification of XPS Queue Setting** Okay, it's confirmed; the data has been successfully exported. Now, my immediate concern shifts to the crucial function `__netif_set_xps_queue`. Given that the data is now out of its initial context, my verification efforts must now center on this particular function. I'll need to closely scrutinize its implementation and operation. I need to be sure the expected queues are properly set up. My assumptions about the state of this queue based on the export are crucial. I will need to be diligent here. This is a critical point to ensure the correctness of the overall process. |
| 44/2 | 2026/08/12 10:19 | tool | grepper |
0mArgs:{
"Expression": "EXPORT_SYMBOL.*__netif_set_xps_queue"
}Results: {
"Output": "net/core/dev.c=2884=int __netif_set_xps_queue(struct net_device *dev, const unsigned long *mask,\n--\nnet/core/dev.c-3086-}\nnet/core/dev.c:3087:EXPORT_SYMBOL_GPL(__netif_set_xps_queue);\nnet/core/dev.c-3088-\n"
} |
| 45/2 | 2026/08/12 10:19 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 62343 output: 27 thoughts: 23 Thoughts: Here's my take on the thought process, summarized as you requested: **Verification of Export and Functionality** Okay, it's confirmed, the data is exported successfully. Now, let's move on to the next critical step: verifying the functionality of `mqprio_qopt_reconstruct`. I need to ensure this particular reconstruction routine is operating as expected, since it's a key element in the overall process. Time to thoroughly test and validate its output. |
| 46/2 | 2026/08/12 10:19 | tool | grepper |
0mArgs:{
"Expression": "EXPORT_SYMBOL.*mqprio_qopt_reconstruct"
}Results: {
"Output": "net/sched/sch_mqprio_lib.c=103=void mqprio_qopt_reconstruct(struct net_device *dev, struct tc_mqprio_qopt *qopt)\n--\nnet/sched/sch_mqprio_lib.c-118-}\nnet/sched/sch_mqprio_lib.c:119:EXPORT_SYMBOL_GPL(mqprio_qopt_reconstruct);\nnet/sched/sch_mqprio_lib.c-120-\n"
} |
| 47/2 | 2026/08/12 10:19 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 62632 output: 314 thoughts: 927 Thoughts: **My Analysis of the Patch for Fuzzing Focus** Okay, so the code is exported, that's good. Now, I need to figure out the right symbols to prioritize for fuzzing. I need to avoid listing generic hot-path functions, to avoid skewed results. So, `netdev_txq_to_tc`, even though it *is* exported, gets excluded because it's called in hot paths like `__dpaa2_eth_tx` and `ksz9477_xmit`. Next, I look at inline functions in `include/linux/netdevice.h`. These are obviously not appropriate for the list. I skip over `netdev_get_num_tc`, `netdev_set_prio_tc_map`, `netdev_get_prio_tc_map`, and `netdev_get_sb_channel`, because they're all inline. That leaves me with a focused list of symbols: `netdev_set_tc_queue`, `netdev_set_num_tc`, `netdev_bind_sb_channel_queue`, `netdev_set_sb_channel`, `netdev_reset_tc`, `__netif_set_xps_queue`, `mqprio_qopt_reconstruct`, and `netif_set_real_num_tx_queues`. Now, for configuration options. I'll include `NET_SCH_MQPRIO` and `NET_SCH_TAPRIO` explicitly. And even though `XPS` defaults to 'y', it's good to call it out to be explicit. Let's make sure it's valid... yes, `config XPS` is in `net/Kconfig`. I've examined the changed files. While the patch touches driver-specific code like `cxgb4_main.c`, `dpaa2-eth.c`, etc., the core changes in `net/core/dev.c`, `net/core/net-sysfs.c`, `net/sched/sch_mqprio.c`, `net/sched/sch_mqprio_lib.c`, and `net/sched/sch_taprio.c` are where the fuzzing effort should be concentrated. These core changes are the most important part to fuzz, as they affect all drivers using these APIs. My understanding is that this patch is addressing data races, specifically by using `READ_ONCE` and `WRITE_ONCE` on fields like `num_tc`, `tc_to_txq`, and `prio_tc_map` within `struct net_device`. It also introduces the `combined` field in `struct netdev_tc_txq` for atomic `count` and `offset` read/writes. This affects TC and txq configurations, which can be configured from userspace using `tc` commands and sysfs. So, I need to fuzz the core API functions that manage these settings, and I believe my current list reflects this understanding. Alright, time to execute `set-results`. |
| 48/2 | 2026/08/12 10:19 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"NET_SCH_MQPRIO",
"NET_SCH_TAPRIO",
"XPS"
],
"FocusSymbols": [
"netdev_set_tc_queue",
"netdev_set_num_tc",
"netdev_bind_sb_channel_queue",
"netdev_set_sb_channel",
"netdev_reset_tc",
"__netif_set_xps_queue",
"mqprio_qopt_reconstruct",
"netif_set_real_num_tx_queues"
],
"Reasoning": "The patch modifies the core networking stack to use `READ_ONCE` and `WRITE_ONCE` for `num_tc`, `tc_to_txq`, and `prio_tc_map` in `struct net_device` to prevent data races. It also introduces a `combined` field in `struct netdev_tc_txq` to read/write `count` and `offset` atomically. These changes affect traffic class (TC) and transmit queue (txq) configurations, which are reachable from userspace via `tc` commands (e.g., configuring `mqprio` or `taprio` qdiscs) and sysfs. The changes also affect several network drivers. Fuzzing should focus on the core API functions used to configure these parameters.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"NET_SCH_MQPRIO",
"NET_SCH_TAPRIO",
"XPS"
],
"FocusSymbols": [
"netdev_set_tc_queue",
"netdev_set_num_tc",
"netdev_bind_sb_channel_queue",
"netdev_set_sb_channel",
"netdev_reset_tc",
"__netif_set_xps_queue",
"mqprio_qopt_reconstruct",
"netif_set_real_num_tx_queues"
],
"Reasoning": "The patch modifies the core networking stack to use `READ_ONCE` and `WRITE_ONCE` for `num_tc`, `tc_to_txq`, and `prio_tc_map` in `struct net_device` to prevent data races. It also introduces a `combined` field in `struct netdev_tc_txq` to read/write `count` and `offset` atomically. These changes affect traffic class (TC) and transmit queue (txq) configurations, which are reachable from userspace via `tc` commands (e.g., configuring `mqprio` or `taprio` qdiscs) and sysfs. The changes also affect several network drivers. Fuzzing should focus on the core API functions used to configure these parameters.",
"WorthFuzzing": true
} |
| 49/1 | 2026/08/12 10:19 | action | If |
0mArgs:{
"WorthFuzzing": true
}Results: null |
| 50/2 | 2026/08/12 10:19 | agent | kmsan-evaluator |
0mModel:best-expensive Args: null Results: {
"KMSANReasoning": "The patch series addresses data races by replacing direct accesses to `num_tc`, `tc_to_txq`, and `prio_tc_map` fields of `struct net_device` with `READ_ONCE()` and `WRITE_ONCE()`. To enable atomic 32-bit reads/writes for `tc_to_txq`, it introduces a union with a `u32 combined` field overlaying the `u16 count` and `u16 offset` fields. \n\n1. The `struct netdev_tc_txq` contains exactly two `u16` fields, which perfectly align to 4 bytes without any padding. Thus, reading or writing the `combined` `u32` field does not involve any uninitialized padding bytes.\n2. The modified structures are internal to the kernel. When data is passed to user space (e.g., via `mqprio_qopt_reconstruct`), the fields (`count` and `offset`) are copied individually, ensuring no uninitialized memory or padding is leaked.\n3. The changes do not introduce new allocations, complex uninitialized data structures, or altered bounds checking that could expose uninitialized memory.\n\nThe patch primarily fixes concurrency issues (data races) which are best detected by KCSAN, while any memory corruption would be caught by KASAN. There is no risk of uninitialized memory use or info-leaks that would necessitate a dedicated KMSAN fuzzing session.",
"NeedsKMSAN": false
}Instruction: You are an expert Linux kernel security engineer specializing in kernel memory
error detectors (KASAN and KMSAN). Your job is to review the provided patch series and
determine if the code changes justify spawning a dedicated KMSAN (KernelMemorySanitizer)
fuzzing session in addition to standard KASAN fuzzing.
CRITICAL DISTINCTION BETWEEN KASAN AND KMSAN:
- Standard KASAN kernel builds (upstream-apparmor-kasan.config) already enable
a comprehensive suite of debugging tools and sanitizers, including KASAN
(out-of-bounds accesses, use-after-free, double free, invalid free), LOCKDEP
(locking bugs and deadlocks), UB-sanitizers, and memory corruption checks.
- KMSAN (KernelMemorySanitizer) detects reads of UNINITIALIZED memory (stack, heap,
or page allocations) and kernel-to-user memory info-leaks.
Rule: THERE IS NO SENSE IN RUNNING A KMSAN SESSION IF A BUG CAN BE CAUGHT BY KASAN,
LOCKDEP, OR OTHER STANDARD BUG DETECTORS.
A dedicated KMSAN fuzzing session incurs significant resource costs. You must ONLY
set NeedsKMSAN=true if the code changes introduce or expose UNINITIALIZED MEMORY risks
that are detected ONLY by KMSAN.
Look holistically at the patch series and surrounding code. Even if no direct
uninitialized field accesses or new buffer allocations are added in the diff itself,
a patch may alter control flow, bounds checking, or data length calculations in ways
that change how the rest of the code operates on existing buffers (e.g. allowing
uninitialized stack/heap memory to be read, copied to user space, or used in control
flow). Do not hesitate to use your code access tools to inspect the surrounding code,
called functions, and callers.
Set NeedsKMSAN=true ONLY IF the patch introduces or modifies:
1. Kernel structures sent to user space (via copy_to_user, put_user, netlink skb
attributes, ioctl output arguments, socket options, or BPF buffers) where fields
or structure padding might not be fully initialized/zeroed.
2. Conditional logic or branching that depends on potentially uninitialized variables
or struct fields.
3. Allocation or initialization of complex data structures where uninitialized fields
could be read later in reachable code paths.
4. Bounds checks, lengths, or logic in a way that allows surrounding code to access
uninitialized bytes of existing buffers.
Set NeedsKMSAN=false IF:
- The code changes primarily risk out-of-bounds access, array overflows, NULL pointer
dereferences, locking deadlocks, or use-after-free bugs (these are already caught
by KASAN, LOCKDEP, or standard bug detectors).
- All stack/heap structures touched or introduced by the patch are fully zeroed
or initialized (e.g. using = {0}, memset, kzalloc) before being read or copied.
- The patch does not introduce any risk of uninitialized memory usage or info-leaks.
Use your code access tools to inspect the surrounding code if necessary, then provide
detailed KMSANReasoning contrasting KASAN vs KMSAN applicability for this patch.
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 628ffde6d9efa9ce85afde1dead16850c4b3d1d6
Author: syz-cluster <triage@syzkaller.com>
Date: Wed Aug 12 09:29:57 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 9e2c2fa16d7a5..1ced6df6eac8c 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -1163,7 +1163,7 @@ static u16 cxgb_select_queue(struct net_device *dev, struct sk_buff *skb,
}
#endif /* CONFIG_CHELSIO_T4_DCB */
- if (dev->num_tc) {
+ if (netdev_get_num_tc(dev)) {
struct port_info *pi = netdev2pinfo(dev);
u8 ver, proto;
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index 764d2a09668f5..6f1046c9cc515 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -1403,10 +1403,10 @@ static netdev_tx_t __dpaa2_eth_tx(struct sk_buff *skb,
struct dpaa2_eth_fq *fq;
struct netdev_queue *nq;
struct dpaa2_fd *fd;
+ int err, i, num_tc;
u16 queue_mapping;
void *swa = NULL;
u8 prio = 0;
- int err, i;
u32 fd_len;
percpu_stats = this_cpu_ptr(priv->percpu_stats);
@@ -1468,12 +1468,14 @@ static netdev_tx_t __dpaa2_eth_tx(struct sk_buff *skb,
*/
queue_mapping = skb_get_queue_mapping(skb);
- if (net_dev->num_tc) {
+ num_tc = netdev_get_num_tc(net_dev);
+
+ if (num_tc) {
prio = netdev_txq_to_tc(net_dev, queue_mapping);
/* Hardware interprets priority level 0 as being the highest,
* so we need to do a reverse mapping to the netdev tc index
*/
- prio = net_dev->num_tc - prio - 1;
+ prio = num_tc - prio - 1;
/* We have only one FQ array entry for all Tx hardware queues
* with the same flow id (but different priority levels)
*/
@@ -2913,7 +2915,7 @@ static int update_xps(struct dpaa2_eth_priv *priv)
return -ENOMEM;
num_queues = dpaa2_eth_queue_count(priv);
- netdev_queues = (net_dev->num_tc ? : 1) * num_queues;
+ netdev_queues = (netdev_get_num_tc(net_dev) ? : 1) * num_queues;
/* The first <num_queues> entries in priv->fq array are Tx/Tx conf
* queues, so only process those
@@ -2946,7 +2948,7 @@ static int dpaa2_eth_setup_mqprio(struct net_device *net_dev,
num_queues = dpaa2_eth_queue_count(priv);
num_tc = mqprio->num_tc;
- if (num_tc == net_dev->num_tc)
+ if (num_tc == netdev_get_num_tc(net_dev))
return 0;
if (num_tc > dpaa2_eth_tc_count(priv)) {
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
index 52de2bcbadbec..d23a45a34fa3c 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
@@ -182,14 +182,16 @@ static u32 igc_fpe_map_preempt_tc_to_queue(const struct igc_adapter *adapter,
struct net_device *dev = adapter->netdev;
u32 i, queue = 0;
- for (i = 0; i < dev->num_tc; i++) {
+ for (i = 0; i < netdev_get_num_tc(dev); i++) {
+ struct netdev_tc_txq res;
u32 offset, count;
if (!(preemptible_tcs & BIT(i)))
continue;
- offset = dev->tc_to_txq[i].offset;
- count = dev->tc_to_txq[i].count;
+ res.combined = READ_ONCE(dev->tc_to_txq[i].combined);
+ offset = res.offset;
+ count = res.count;
queue |= GENMASK(offset + count - 1, offset);
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 8873a8cc4a185..f91856498eb2d 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -9273,10 +9273,11 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,
if (sb_dev) {
u8 tc = netdev_get_prio_tc_map(dev, skb->priority);
struct net_device *vdev = sb_dev;
+ struct netdev_tc_txq res;
- txq = vdev->tc_to_txq[tc].offset;
- txq += reciprocal_scale(skb_get_hash(skb),
- vdev->tc_to_txq[tc].count);
+ res.combined = READ_ONCE(vdev->tc_to_txq[tc].combined);
+ txq = res.offset;
+ txq += reciprocal_scale(skb_get_hash(skb), res.count);
return txq;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index ca3d7c6b5210e..fc110a7d16e8d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3245,9 +3245,9 @@ static int mlx5e_update_tc_and_tx_queues(struct mlx5e_priv *priv)
int i;
old_num_txqs = netdev->real_num_tx_queues;
- old_ntc = netdev->num_tc ? : 1;
+ old_ntc = netdev_get_num_tc(netdev) ? : 1;
for (i = 0; i < ARRAY_SIZE(old_tc_to_txq); i++)
- old_tc_to_txq[i] = netdev->tc_to_txq[i];
+ old_tc_to_txq[i].combined = READ_ONCE(netdev->tc_to_txq[i].combined);
nch = priv->channels.params.num_channels;
ntc = priv->channels.params.mqprio.num_tc;
diff --git a/drivers/net/ethernet/sfc/falcon/net_driver.h b/drivers/net/ethernet/sfc/falcon/net_driver.h
index 7ab0db44720da..63016bbae115b 100644
--- a/drivers/net/ethernet/sfc/falcon/net_driver.h
+++ b/drivers/net/ethernet/sfc/falcon/net_driver.h
@@ -1208,7 +1208,7 @@ ef4_channel_get_tx_queue(struct ef4_channel *channel, unsigned type)
static inline bool ef4_tx_queue_used(struct ef4_tx_queue *tx_queue)
{
- return !(tx_queue->efx->net_dev->num_tc < 2 &&
+ return !(netdev_get_num_tc(tx_queue->efx->net_dev) < 2 &&
tx_queue->queue & EF4_TXQ_TYPE_HIGHPRI);
}
diff --git a/drivers/net/ethernet/sfc/falcon/tx.c b/drivers/net/ethernet/sfc/falcon/tx.c
index 9e18aaf44badd..2103b6fdf9683 100644
--- a/drivers/net/ethernet/sfc/falcon/tx.c
+++ b/drivers/net/ethernet/sfc/falcon/tx.c
@@ -435,15 +435,19 @@ int ef4_setup_tc(struct net_device *net_dev, enum tc_setup_type type,
mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
- if (num_tc == net_dev->num_tc)
+ if (num_tc == netdev_get_num_tc(net_dev))
return 0;
for (tc = 0; tc < num_tc; tc++) {
- net_dev->tc_to_txq[tc].offset = tc * efx->n_tx_channels;
- net_dev->tc_to_txq[tc].count = efx->n_tx_channels;
+ struct netdev_tc_txq res = {
+ .offset = tc * efx->n_tx_channels,
+ .count = efx->n_tx_channels,
+ };
+
+ WRITE_ONCE(net_dev->tc_to_txq[tc].combined, res.combined);
}
- if (num_tc > net_dev->num_tc) {
+ if (num_tc > netdev_get_num_tc(net_dev)) {
/* Initialise high-priority queues as necessary */
ef4_for_each_channel(channel, efx) {
ef4_for_each_possible_channel_tx_queue(tx_queue,
@@ -462,7 +466,7 @@ int ef4_setup_tc(struct net_device *net_dev, enum tc_setup_type type,
}
} else {
/* Reduce number of classes before number of queues */
- net_dev->num_tc = num_tc;
+ WRITE_ONCE(net_dev->num_tc, num_tc);
}
rc = netif_set_real_num_tx_queues(net_dev,
@@ -477,7 +481,7 @@ int ef4_setup_tc(struct net_device *net_dev, enum tc_setup_type type,
* it to ef4_fini_channels().
*/
- net_dev->num_tc = num_tc;
+ WRITE_ONCE(net_dev->num_tc, num_tc);
return 0;
}
diff --git a/drivers/net/ethernet/sfc/siena/tx.c b/drivers/net/ethernet/sfc/siena/tx.c
index 91e87594ed1ea..67c77d67d9843 100644
--- a/drivers/net/ethernet/sfc/siena/tx.c
+++ b/drivers/net/ethernet/sfc/siena/tx.c
@@ -376,15 +376,19 @@ int efx_siena_setup_tc(struct net_device *net_dev, enum tc_setup_type type,
mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
- if (num_tc == net_dev->num_tc)
+ if (num_tc == netdev_get_num_tc(net_dev))
return 0;
for (tc = 0; tc < num_tc; tc++) {
- net_dev->tc_to_txq[tc].offset = tc * efx->n_tx_channels;
- net_dev->tc_to_txq[tc].count = efx->n_tx_channels;
+ struct netdev_tc_txq res = {
+ .offset = tc * efx->n_tx_channels,
+ .count = efx->n_tx_channels,
+ };
+
+ WRITE_ONCE(net_dev->tc_to_txq[tc].combined, res.combined);
}
- net_dev->num_tc = num_tc;
+ WRITE_ONCE(net_dev->num_tc, num_tc);
return netif_set_real_num_tx_queues(net_dev,
max_t(int, num_tc, 1) *
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
index c54c702243517..c889204a7aa5d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
@@ -217,8 +217,11 @@ int dwmac5_fpe_map_preemption_class(struct net_device *ndev,
* and is direct one-to-one mapping."
*/
for (u32 tc = 0; tc < num_tc; tc++) {
- count = ndev->tc_to_txq[tc].count;
- offset = ndev->tc_to_txq[tc].offset;
+ struct netdev_tc_txq res;
+
+ res.combined = READ_ONCE(ndev->tc_to_txq[tc].combined);
+ count = res.count;
+ offset = res.offset;
if (pclass & BIT(tc))
preemptible_txqs |= GENMASK(offset + count - 1, offset);
@@ -275,8 +278,11 @@ int dwxgmac3_fpe_map_preemption_class(struct net_device *ndev,
* any of the scheduling algorithms."
*/
for (u32 tc = 0; tc < num_tc; tc++) {
- count = ndev->tc_to_txq[tc].count;
- offset = ndev->tc_to_txq[tc].offset;
+ struct netdev_tc_txq res;
+
+ res.combined = READ_ONCE(ndev->tc_to_txq[tc].combined);
+ count = res.count;
+ offset = res.offset;
if (pclass & BIT(tc))
preemptible_txqs |= GENMASK(offset + count - 1, offset);
diff --git a/drivers/net/ethernet/ti/cpsw_priv.c b/drivers/net/ethernet/ti/cpsw_priv.c
index 1f6f374551cb6..0580a7885d339 100644
--- a/drivers/net/ethernet/ti/cpsw_priv.c
+++ b/drivers/net/ethernet/ti/cpsw_priv.c
@@ -949,7 +949,7 @@ static int cpsw_set_cbs(struct net_device *ndev,
* limited first and for compliance with CPDMA rate limited channels
* that also used in bacward order. FIFO0 cannot be rate limited.
*/
- fifo = cpsw_tc_to_fifo(tc, ndev->num_tc);
+ fifo = cpsw_tc_to_fifo(tc, netdev_get_num_tc(ndev));
if (!fifo) {
dev_err(priv->dev, "Last tc%d can't be rate limited", tc);
return -EINVAL;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index db9dce7f0aa65..de307c01d33eb 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -832,8 +832,13 @@ struct xps_dev_maps {
#define TC_BITMASK 15
/* HW offloaded queuing disciplines txq count and offset maps */
struct netdev_tc_txq {
- u16 count;
- u16 offset;
+ union {
+ struct {
+ u16 count;
+ u16 offset;
+ };
+ u32 combined;
+ };
};
#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
@@ -2666,16 +2671,16 @@ static inline bool netif_elide_gro(const struct net_device *dev)
static inline
int netdev_get_prio_tc_map(const struct net_device *dev, u32 prio)
{
- return dev->prio_tc_map[prio & TC_BITMASK];
+ return READ_ONCE(dev->prio_tc_map[prio & TC_BITMASK]);
}
static inline
int netdev_set_prio_tc_map(struct net_device *dev, u8 prio, u8 tc)
{
- if (tc >= dev->num_tc)
+ if (tc >= READ_ONCE(dev->num_tc))
return -EINVAL;
- dev->prio_tc_map[prio & TC_BITMASK] = tc & TC_BITMASK;
+ WRITE_ONCE(dev->prio_tc_map[prio & TC_BITMASK], tc & TC_BITMASK);
return 0;
}
@@ -2685,9 +2690,9 @@ int netdev_set_tc_queue(struct net_device *dev, u8 tc, u16 count, u16 offset);
int netdev_set_num_tc(struct net_device *dev, u8 num_tc);
static inline
-int netdev_get_num_tc(struct net_device *dev)
+int netdev_get_num_tc(const struct net_device *dev)
{
- return dev->num_tc;
+ return READ_ONCE(dev->num_tc);
}
static inline void net_prefetch(void *p)
@@ -2714,7 +2719,7 @@ int netdev_bind_sb_channel_queue(struct net_device *dev,
int netdev_set_sb_channel(struct net_device *dev, u16 channel);
static inline int netdev_get_sb_channel(struct net_device *dev)
{
- return max_t(int, -dev->num_tc, 0);
+ return max_t(int, -READ_ONCE(dev->num_tc), 0);
}
static inline
diff --git a/net/core/dev.c b/net/core/dev.c
index fd0b445f5d38c..d52285ac01a54 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2656,13 +2656,15 @@ EXPORT_SYMBOL_GPL(dev_queue_xmit_nit);
*/
static void netif_setup_tc(struct net_device *dev, unsigned int txq)
{
+ struct netdev_tc_txq res;
int i;
- struct netdev_tc_txq *tc = &dev->tc_to_txq[0];
+
+ res.combined = READ_ONCE(dev->tc_to_txq[0].combined);
/* If TC0 is invalidated disable TC mapping */
- if (tc->offset + tc->count > txq) {
+ if (res.offset + res.count > txq) {
netdev_warn(dev, "Number of in use tx queues changed invalidating tc mappings. Priority traffic classification disabled!\n");
- dev->num_tc = 0;
+ WRITE_ONCE(dev->num_tc, 0);
return;
}
@@ -2670,8 +2672,8 @@ static void netif_setup_tc(struct net_device *dev, unsigned int txq)
for (i = 1; i < TC_BITMASK + 1; i++) {
int q = netdev_get_prio_tc_map(dev, i);
- tc = &dev->tc_to_txq[q];
- if (tc->offset + tc->count > txq) {
+ res.combined = READ_ONCE(dev->tc_to_txq[q].combined);
+ if (res.offset + res.count > txq) {
netdev_warn(dev, "Number of in use tx queues changed. Priority %i to tc mapping %i is no longer valid. Setting map to 0\n",
i, q);
netdev_set_prio_tc_map(dev, i, 0);
@@ -2681,13 +2683,16 @@ static void netif_setup_tc(struct net_device *dev, unsigned int txq)
int netdev_txq_to_tc(struct net_device *dev, unsigned int txq)
{
- if (dev->num_tc) {
+ if (READ_ONCE(dev->num_tc)) {
struct netdev_tc_txq *tc = &dev->tc_to_txq[0];
int i;
/* walk through the TCs and see if it falls into any of them */
for (i = 0; i < TC_MAX_QUEUE; i++, tc++) {
- if ((txq - tc->offset) < tc->count)
+ struct netdev_tc_txq res;
+
+ res.combined = READ_ONCE(tc->combined);
+ if ((txq - res.offset) < res.count)
return i;
}
@@ -2880,18 +2885,19 @@ int __netif_set_xps_queue(struct net_device *dev, const unsigned long *mask,
u16 index, enum xps_map_type type)
{
struct xps_dev_maps *dev_maps, *new_dev_maps = NULL, *old_dev_maps = NULL;
+ int maps_sz, num_tc = 1, tc = 0, dev_num_tc;
const unsigned long *online_mask = NULL;
bool active = false, copy = false;
int i, j, tci, numa_node_id = -2;
- int maps_sz, num_tc = 1, tc = 0;
struct xps_map *map, *new_map;
unsigned int nr_ids;
WARN_ON_ONCE(index >= dev->num_tx_queues);
- if (dev->num_tc) {
+ dev_num_tc = READ_ONCE(dev->num_tc);
+ if (dev_num_tc) {
/* Do not allow XPS on subordinate device directly */
- num_tc = dev->num_tc;
+ num_tc = dev_num_tc;
if (num_tc < 0)
return -EINVAL;
@@ -3107,28 +3113,36 @@ static void netdev_unbind_all_sb_channels(struct net_device *dev)
void netdev_reset_tc(struct net_device *dev)
{
+ int i;
+
#ifdef CONFIG_XPS
netif_reset_xps_queues_gt(dev, 0);
#endif
netdev_unbind_all_sb_channels(dev);
/* Reset TC configuration of device */
- dev->num_tc = 0;
- memset(dev->tc_to_txq, 0, sizeof(dev->tc_to_txq));
- memset(dev->prio_tc_map, 0, sizeof(dev->prio_tc_map));
+ WRITE_ONCE(dev->num_tc, 0);
+ for (i = 0; i < TC_MAX_QUEUE; i++)
+ WRITE_ONCE(dev->tc_to_txq[i].combined, 0);
+ for (i = 0; i <= TC_BITMASK; i++)
+ WRITE_ONCE(dev->prio_tc_map[i], 0);
}
EXPORT_SYMBOL(netdev_reset_tc);
int netdev_set_tc_queue(struct net_device *dev, u8 tc, u16 count, u16 offset)
{
- if (tc >= dev->num_tc)
+ struct netdev_tc_txq res = {
+ .count = count,
+ .offset = offset,
+ };
+
+ if (tc >= READ_ONCE(dev->num_tc))
return -EINVAL;
#ifdef CONFIG_XPS
netif_reset_xps_queues(dev, offset, count);
#endif
- dev->tc_to_txq[tc].count = count;
- dev->tc_to_txq[tc].offset = offset;
+ WRITE_ONCE(dev->tc_to_txq[tc].combined, res.combined);
return 0;
}
EXPORT_SYMBOL(netdev_set_tc_queue);
@@ -3143,7 +3157,7 @@ int netdev_set_num_tc(struct net_device *dev, u8 num_tc)
#endif
netdev_unbind_all_sb_channels(dev);
- dev->num_tc = num_tc;
+ WRITE_ONCE(dev->num_tc, num_tc);
return 0;
}
EXPORT_SYMBOL(netdev_set_num_tc);
@@ -3152,12 +3166,15 @@ void netdev_unbind_sb_channel(struct net_device *dev,
struct net_device *sb_dev)
{
struct netdev_queue *txq = &dev->_tx[dev->num_tx_queues];
+ int i;
#ifdef CONFIG_XPS
netif_reset_xps_queues_gt(sb_dev, 0);
#endif
- memset(sb_dev->tc_to_txq, 0, sizeof(sb_dev->tc_to_txq));
- memset(sb_dev->prio_tc_map, 0, sizeof(sb_dev->prio_tc_map));
+ for (i = 0; i < TC_MAX_QUEUE; i++)
+ WRITE_ONCE(sb_dev->tc_to_txq[i].combined, 0);
+ for (i = 0; i <= TC_BITMASK; i++)
+ WRITE_ONCE(sb_dev->prio_tc_map[i], 0);
while (txq-- != &dev->_tx[0]) {
if (txq->sb_dev == sb_dev)
@@ -3171,7 +3188,7 @@ int netdev_bind_sb_channel_queue(struct net_device *dev,
u8 tc, u16 count, u16 offset)
{
/* Make certain the sb_dev and dev are already configured */
- if (sb_dev->num_tc >= 0 || tc >= dev->num_tc)
+ if (READ_ONCE(sb_dev->num_tc) >= 0 || tc >= READ_ONCE(dev->num_tc))
return -EINVAL;
/* We cannot hand out queues we don't have */
@@ -3179,8 +3196,12 @@ int netdev_bind_sb_channel_queue(struct net_device *dev,
return -EINVAL;
/* Record the mapping */
- sb_dev->tc_to_txq[tc].count = count;
- sb_dev->tc_to_txq[tc].offset = offset;
+ struct netdev_tc_txq res = {
+ .count = count,
+ .offset = offset,
+ };
+
+ WRITE_ONCE(sb_dev->tc_to_txq[tc].combined, res.combined);
/* Provide a way for Tx queue to find the tc_to_txq map or
* XPS map for itself.
@@ -3206,7 +3227,7 @@ int netdev_set_sb_channel(struct net_device *dev, u16 channel)
if (channel > S16_MAX)
return -EINVAL;
- dev->num_tc = -channel;
+ WRITE_ONCE(dev->num_tc, -channel);
return 0;
}
@@ -3235,7 +3256,7 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
if (rc)
return rc;
- if (dev->num_tc)
+ if (READ_ONCE(dev->num_tc))
netif_setup_tc(dev, txq);
net_shaper_set_real_num_tx_queues(dev, txq);
@@ -3544,11 +3565,13 @@ static u16 skb_tx_hash(const struct net_device *dev,
u16 qoffset = 0;
u16 qcount = dev->real_num_tx_queues;
- if (dev->num_tc) {
+ if (READ_ONCE(dev->num_tc)) {
u8 tc = netdev_get_prio_tc_map(dev, skb->priority);
+ struct netdev_tc_txq res;
- qoffset = sb_dev->tc_to_txq[tc].offset;
- qcount = sb_dev->tc_to_txq[tc].count;
+ res.combined = READ_ONCE(sb_dev->tc_to_txq[tc].combined);
+ qoffset = res.offset;
+ qcount = res.count;
if (unlikely(!qcount)) {
net_warn_ratelimited("%s: invalid qcount, qoffset %u for tc %u\n",
sb_dev->name, qoffset, tc);
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 25546deacec80..352173df75785 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -1432,7 +1432,7 @@ static ssize_t traffic_class_show(struct kobject *kobj, struct attribute *attr,
/* If queue belongs to subordinate dev use its TC mapping */
dev = netdev_get_tx_queue(dev, index)->sb_dev ? : dev;
- num_tc = dev->num_tc;
+ num_tc = READ_ONCE(dev->num_tc);
tc = netdev_txq_to_tc(dev, index);
rtnl_unlock();
diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c
index ae991fc25b43f..6ced7008ef5c8 100644
--- a/net/sched/sch_mqprio.c
+++ b/net/sched/sch_mqprio.c
@@ -679,12 +679,14 @@ static int mqprio_dump_class_stats(struct Qdisc *sch, unsigned long cl,
rcu_read_lock();
if (cl >= TC_H_MIN_PRIORITY) {
struct net_device *dev = qdisc_dev(sch);
- struct netdev_tc_txq tc = dev->tc_to_txq[cl & TC_BITMASK];
+ struct netdev_tc_txq tc;
struct gnet_stats_queue qstats = {0};
struct gnet_stats_basic_sync bstats;
u32 qlen = 0;
int i;
+ tc.combined = READ_ONCE(dev->tc_to_txq[cl & TC_BITMASK].combined);
+
gnet_stats_basic_sync_init(&bstats);
for (i = tc.offset; i < tc.offset + tc.count; i++) {
diff --git a/net/sched/sch_mqprio_lib.c b/net/sched/sch_mqprio_lib.c
index b3a5572c167b7..888935e34d438 100644
--- a/net/sched/sch_mqprio_lib.c
+++ b/net/sched/sch_mqprio_lib.c
@@ -105,11 +105,15 @@ void mqprio_qopt_reconstruct(struct net_device *dev, struct tc_mqprio_qopt *qopt
int tc, num_tc = netdev_get_num_tc(dev);
qopt->num_tc = num_tc;
- memcpy(qopt->prio_tc_map, dev->prio_tc_map, sizeof(qopt->prio_tc_map));
+ for (tc = 0; tc <= TC_BITMASK; tc++)
+ qopt->prio_tc_map[tc] = netdev_get_prio_tc_map(dev, tc);
for (tc = 0; tc < num_tc; tc++) {
- qopt->count[tc] = dev->tc_to_txq[tc].count;
- qopt->offset[tc] = dev->tc_to_txq[tc].offset;
+ struct netdev_tc_txq res;
+
+ res.combined = READ_ONCE(dev->tc_to_txq[tc].combined);
+ qopt->count[tc] = res.count;
+ qopt->offset[tc] = res.offset;
}
}
EXPORT_SYMBOL_GPL(mqprio_qopt_reconstruct);
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index 299234a5f0fe6..39ac5b97aa3af 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -762,12 +762,13 @@ static struct sk_buff *taprio_dequeue_from_txq(struct Qdisc *sch, int txq,
static void taprio_next_tc_txq(struct net_device *dev, int tc, int *txq)
{
- int offset = dev->tc_to_txq[tc].offset;
- int count = dev->tc_to_txq[tc].count;
+ struct netdev_tc_txq res;
+
+ res.combined = READ_ONCE(dev->tc_to_txq[tc].combined);
(*txq)++;
- if (*txq == offset + count)
- *txq = offset;
+ if (*txq == res.offset + res.count)
+ *txq = res.offset;
}
/* Prioritize higher traffic classes, and select among TXQs belonging to the
@@ -1184,7 +1185,7 @@ static int taprio_parse_mqprio_opt(struct net_device *dev,
bool allow_overlapping_txqs = TXTIME_ASSIST_IS_ENABLED(taprio_flags);
if (!qopt) {
- if (!dev->num_tc) {
+ if (!netdev_get_num_tc(dev)) {
NL_SET_ERR_MSG(extack, "'mqprio' configuration is necessary");
return -EINVAL;
}
@@ -1438,18 +1439,18 @@ static void taprio_offload_config_changed(struct taprio_sched *q)
static u32 tc_map_to_queue_mask(struct net_device *dev, u32 tc_mask)
{
+ int num_tc = netdev_get_num_tc(dev);
u32 i, queue_mask = 0;
- for (i = 0; i < dev->num_tc; i++) {
- u32 offset, count;
+ for (i = 0; i < num_tc; i++) {
+ struct netdev_tc_txq res;
if (!(tc_mask & BIT(i)))
continue;
- offset = dev->tc_to_txq[i].offset;
- count = dev->tc_to_txq[i].count;
+ res.combined = READ_ONCE(dev->tc_to_txq[i].combined);
- queue_mask |= GENMASK(offset + count - 1, offset);
+ queue_mask |= GENMASK(res.offset + res.count - 1, res.offset);
}
return queue_mask;
@@ -1799,16 +1800,20 @@ static int taprio_mqprio_cmp(const struct net_device *dev,
{
int i;
- if (!mqprio || mqprio->num_tc != dev->num_tc)
+ if (!mqprio || mqprio->num_tc != netdev_get_num_tc(dev))
return -1;
- for (i = 0; i < mqprio->num_tc; i++)
- if (dev->tc_to_txq[i].count != mqprio->count[i] ||
- dev->tc_to_txq[i].offset != mqprio->offset[i])
+ for (i = 0; i < mqprio->num_tc; i++) {
+ struct netdev_tc_txq res;
+
+ res.combined = READ_ONCE(dev->tc_to_txq[i].combined);
+ if (res.count != mqprio->count[i] ||
+ res.offset != mqprio->offset[i])
return -1;
+ }
for (i = 0; i <= TC_BITMASK; i++)
- if (dev->prio_tc_map[i] != mqprio->prio_tc_map[i])
+ if (netdev_get_prio_tc_map(dev, i) != mqprio->prio_tc_map[i])
return -1;
return 0;
|
| 51/3 | 2026/08/12 10:19 | llm | kmsan-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12263 output: 337 thoughts: 3350 Thoughts: **Analysis of the Network Device Structure Modification for Data Race Prevention**
Okay, so this patch series fundamentally alters how the `net_device` structure's `num_tc`, `tc_to_txq`, and `prio_tc_map` fields are accessed. The goal, as I understand it, is to eliminate data races. This is absolutely critical in a kernel environment where multiple threads – especially the fast data path and configuration threads – are constantly vying for access. The primary mechanism is the introduction of `READ_ONCE` and `WRITE_ONCE` accessors along with a `union` within the `netdev_tc_txq` struct. I need to be *absolutely* certain that these changes don't introduce any new vulnerabilities, particularly related to uninitialized memory.
The core of the change lies in the `netdev_tc_txq` struct's modification: it now uses a `union` containing a struct with `count` and `offset` as `u16` members and a `u32 combined` field. The reasoning here is clear: it enables atomic 32-bit operations, which is crucial for preventing those pesky data races. The size is 4 bytes.
Now, let's drill down: Is there a risk of uninitialized memory being read or leaked? When the structure is initialized, for instance, in functions like `ef4_setup_tc`, the code uses designated initializers like:
```c
struct netdev_tc_txq res = {
.offset = tc * efx->n_tx_channels,
.count = efx->n_tx_channels,
};
```
This initialization initializes both `offset` and `count`, so the *entire* `combined` field gets initialized. This design is safe as `u16 count; u16 offset;` in a struct is guaranteed to have no padding. The combined field is only used to atomically read/write these two fields so the endianness does not matter in any way, as the 4 bytes are simply copied. The same pattern is present in all other locations, so there's no way that we can have an uninitialized value that gets used, as all local variables are fully initialized when used.
I need to confirm if anything's being sent to user space that could leak padding. I see that `mqprio_qopt_reconstruct` *does* copy from `tc_to_txq`, but it copies the `count` and `offset` fields individually:
```c
struct netdev_tc_txq res;
res.combined = READ_ONCE(dev->tc_to_txq[tc].combined);
qopt->count[tc] = res.count;
qopt->offset[tc] = res.offset;
```
This is absolutely safe; there's no way padding could leak because we are reading individual 16-bit fields! So no problem there.
Also, I have to consider the other operations:
* `netdev_set_tc_queue` initializes a local variable and writes to the correct memory area, so it's all good.
* `netdev_bind_sb_channel_queue` initializes a local variable and writes to the correct memory area, so it's all good.
* `netif_setup_tc` initializes a local variable and reads to set its combined value, so it's all good.
The rest of the changes are simply replacing direct assignments with `WRITE_ONCE` to fix data races, like the `memset` call being replaced by a loop with `WRITE_ONCE`, which is the intended behavior. The changes are all to remove the risk of data races by correctly and atomically reading and writing to the memory, so it is sound.
The critical point is this: The `netdev_tc_txq` union is designed so that the struct containing the two `u16` fields occupies the exact same space as the `u32 combined` field. This is important: The compiler will not introduce any padding because the struct members have compatible alignments and their sizes perfectly fit within the `u32`. Thus, when we write the struct `count` and `offset` values, we're writing to all 4 bytes. `READ_ONCE` and `WRITE_ONCE` guarantee atomic 32-bit reads and writes.
I have gone through every usage of `tc_to_txq`, `num_tc`, and `prio_tc_map` and confirmed that all the writes are fully initializing the data. There is no possibility of uninitialized memory being exposed.
In conclusion, these changes are sound. They focus solely on fixing data races by introducing atomic access via `READ_ONCE`
|
| 52/3 | 2026/08/12 10:20 | tool | set-results |
0mArgs:{
"KMSANReasoning": "The patch series addresses data races by replacing direct accesses to `num_tc`, `tc_to_txq`, and `prio_tc_map` fields of `struct net_device` with `READ_ONCE()` and `WRITE_ONCE()`. To enable atomic 32-bit reads/writes for `tc_to_txq`, it introduces a union with a `u32 combined` field overlaying the `u16 count` and `u16 offset` fields. \n\n1. The `struct netdev_tc_txq` contains exactly two `u16` fields, which perfectly align to 4 bytes without any padding. Thus, reading or writing the `combined` `u32` field does not involve any uninitialized padding bytes.\n2. The modified structures are internal to the kernel. When data is passed to user space (e.g., via `mqprio_qopt_reconstruct`), the fields (`count` and `offset`) are copied individually, ensuring no uninitialized memory or padding is leaked.\n3. The changes do not introduce new allocations, complex uninitialized data structures, or altered bounds checking that could expose uninitialized memory.\n\nThe patch primarily fixes concurrency issues (data races) which are best detected by KCSAN, while any memory corruption would be caught by KASAN. There is no risk of uninitialized memory use or info-leaks that would necessitate a dedicated KMSAN fuzzing session.",
"NeedsKMSAN": false
}Results: {
"KMSANReasoning": "The patch series addresses data races by replacing direct accesses to `num_tc`, `tc_to_txq`, and `prio_tc_map` fields of `struct net_device` with `READ_ONCE()` and `WRITE_ONCE()`. To enable atomic 32-bit reads/writes for `tc_to_txq`, it introduces a union with a `u32 combined` field overlaying the `u16 count` and `u16 offset` fields. \n\n1. The `struct netdev_tc_txq` contains exactly two `u16` fields, which perfectly align to 4 bytes without any padding. Thus, reading or writing the `combined` `u32` field does not involve any uninitialized padding bytes.\n2. The modified structures are internal to the kernel. When data is passed to user space (e.g., via `mqprio_qopt_reconstruct`), the fields (`count` and `offset`) are copied individually, ensuring no uninitialized memory or padding is leaked.\n3. The changes do not introduce new allocations, complex uninitialized data structures, or altered bounds checking that could expose uninitialized memory.\n\nThe patch primarily fixes concurrency issues (data races) which are best detected by KCSAN, while any memory corruption would be caught by KASAN. There is no risk of uninitialized memory use or info-leaks that would necessitate a dedicated KMSAN fuzzing session.",
"NeedsKMSAN": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|