mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-18 23:19:34 +02:00
net: add READ_ONCE()/WRITE_ONCE() annotations for dev->prio_tc_map
Concurrent fast-path readers access dev->prio_tc_map (e.g. via skb_tx_hash(), netdev_get_prio_tc_map(), and qdiscs) while writers update entries in dev->prio_tc_map or reset/clear the map via netdev_reset_tc() and netdev_unbind_sb_channel(). Furthermore, memset() in netdev_reset_tc() and netdev_unbind_sb_channel() provides no guarantee of performing atomic word/byte stores. Add READ_ONCE() and WRITE_ONCE() annotations to netdev_get_prio_tc_map() and netdev_set_prio_tc_map(), replace memset() in dev.c with explicit WRITE_ONCE() loops, and update direct array accesses in qdiscs to use netdev_get_prio_tc_map(). Signed-off-by: Eric Dumazet <edumazet@google.com> Link: https://patch.msgid.link/20260812085440.3917924-4-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
0c6c32a8c8
commit
51b0aaafd9
@@ -2672,7 +2672,7 @@ 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
|
||||
@@ -2681,7 +2681,7 @@ int netdev_set_prio_tc_map(struct net_device *dev, u8 prio, u8 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;
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -3120,7 +3120,8 @@ void netdev_reset_tc(struct net_device *dev)
|
||||
WRITE_ONCE(dev->num_tc, 0);
|
||||
for (i = 0; i < TC_MAX_QUEUE; i++)
|
||||
WRITE_ONCE(dev->tc_to_txq[i].combined, 0);
|
||||
memset(dev->prio_tc_map, 0, sizeof(dev->prio_tc_map));
|
||||
for (i = 0; i <= TC_BITMASK; i++)
|
||||
WRITE_ONCE(dev->prio_tc_map[i], 0);
|
||||
}
|
||||
EXPORT_SYMBOL(netdev_reset_tc);
|
||||
|
||||
@@ -3168,7 +3169,8 @@ void netdev_unbind_sb_channel(struct net_device *dev,
|
||||
#endif
|
||||
for (i = 0; i < TC_MAX_QUEUE; i++)
|
||||
WRITE_ONCE(sb_dev->tc_to_txq[i].combined, 0);
|
||||
memset(sb_dev->prio_tc_map, 0, sizeof(sb_dev->prio_tc_map));
|
||||
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)
|
||||
|
||||
@@ -105,7 +105,8 @@ 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++) {
|
||||
struct netdev_tc_txq res;
|
||||
|
||||
@@ -1813,7 +1813,7 @@ static int taprio_mqprio_cmp(const struct net_device *dev,
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user