Current documentation on RCU in ath11k_mac_op_ipv6_changed() says:
/* Note: read_lock_bh() calls rcu_read_lock() */
read_lock_bh(&idev->lock);
This is wrong because without enabling CONFIG_PREEMPT_RT
rcu_read_lock() is not called by read_lock_bh(). The reason
why current code works even in a CONFIG_PREEMPT_RT=n kernel
is because atomic_notifier_call_chain() already does that for
us, see:
int atomic_notifier_call_chain()
{
...
rcu_read_lock();
ret = notifier_call_chain(&nh->head, val, v, -1, NULL);
rcu_read_unlock();
...
}
and backtrace:
ath11k_mac_op_ipv6_changed
ieee80211_ifa6_changed
notifier_call_chain
atomic_notifier_call_chain
So update the comment to make it correct.
This is found during code review, compile tested only.
Fixes: feafe59c8975 ("wifi: ath11k: use RCU when accessing struct inet6_dev::ac_list")
Signed-off-by: Baochen Qiang <[email protected]>
---
drivers/net/wireless/ath/ath11k/mac.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index a1800c75d32b..29af015a16f9 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -9020,7 +9020,12 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw,
offload = &arvif->arp_ns_offload;
count = 0;
- /* Note: read_lock_bh() calls rcu_read_lock() */
+ /* The _ipv6_changed() is called with RCU lock already held in
+ * atomic_notifier_call_chain(), so we don't need to call
+ * rcu_read_lock() again here. But note that with CONFIG_PREEMPT_RT
+ * enabled, read_lock_bh() also calls rcu_read_lock(). This is OK
+ * because RCU read critical section is allowed to get nested.
+ */
read_lock_bh(&idev->lock);
memset(offload->ipv6_addr, 0, sizeof(offload->ipv6_addr));
base-commit: 6e7a5c6d5e38b93f9cc3289d66a597b9a4ca0403
--
2.25.1
On 5/30/2024 7:24 PM, Baochen Qiang wrote:
> Current documentation on RCU in ath11k_mac_op_ipv6_changed() says:
>
> /* Note: read_lock_bh() calls rcu_read_lock() */
> read_lock_bh(&idev->lock);
>
> This is wrong because without enabling CONFIG_PREEMPT_RT
> rcu_read_lock() is not called by read_lock_bh(). The reason
> why current code works even in a CONFIG_PREEMPT_RT=n kernel
> is because atomic_notifier_call_chain() already does that for
> us, see:
>
> int atomic_notifier_call_chain()
> {
> ...
> rcu_read_lock();
> ret = notifier_call_chain(&nh->head, val, v, -1, NULL);
> rcu_read_unlock();
> ...
> }
>
> and backtrace:
>
> ath11k_mac_op_ipv6_changed
> ieee80211_ifa6_changed
> notifier_call_chain
> atomic_notifier_call_chain
>
> So update the comment to make it correct.
>
> This is found during code review, compile tested only.
>
> Fixes: feafe59c8975 ("wifi: ath11k: use RCU when accessing struct inet6_dev::ac_list")
> Signed-off-by: Baochen Qiang <[email protected]>
Acked-by: Jeff Johnson <[email protected]>
Baochen Qiang <[email protected]> wrote:
> Current documentation on RCU in ath11k_mac_op_ipv6_changed() says:
>
> /* Note: read_lock_bh() calls rcu_read_lock() */
> read_lock_bh(&idev->lock);
>
> This is wrong because without enabling CONFIG_PREEMPT_RT
> rcu_read_lock() is not called by read_lock_bh(). The reason
> why current code works even in a CONFIG_PREEMPT_RT=n kernel
> is because atomic_notifier_call_chain() already does that for
> us, see:
>
> int atomic_notifier_call_chain()
> {
> ...
> rcu_read_lock();
> ret = notifier_call_chain(&nh->head, val, v, -1, NULL);
> rcu_read_unlock();
> ...
> }
>
> and backtrace:
>
> ath11k_mac_op_ipv6_changed
> ieee80211_ifa6_changed
> notifier_call_chain
> atomic_notifier_call_chain
>
> So update the comment to make it correct.
>
> This is found during code review, compile tested only.
>
> Fixes: feafe59c8975 ("wifi: ath11k: use RCU when accessing struct inet6_dev::ac_list")
> Signed-off-by: Baochen Qiang <[email protected]>
> Acked-by: Jeff Johnson <[email protected]>
> Signed-off-by: Kalle Valo <[email protected]>
Patch applied to ath-next branch of ath.git, thanks.
53d7c99719e2 wifi: ath11k: fix RCU documentation in ath11k_mac_op_ipv6_changed()
--
https://patchwork.kernel.org/project/linux-wireless/patch/[email protected]/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches