|
@@ -351,7 +351,7 @@ int sta_info_insert(struct sta_info *sta)
|
|
|
* NOTE: due to auto-freeing semantics this may only be done
|
|
|
* if the insertion is successful!
|
|
|
*/
|
|
|
- queue_work(local->hw.workqueue, &local->sta_debugfs_add);
|
|
|
+ schedule_work(&local->sta_debugfs_add);
|
|
|
#endif
|
|
|
|
|
|
if (ieee80211_vif_is_mesh(&sdata->vif))
|
|
@@ -476,16 +476,23 @@ void __sta_info_unlink(struct sta_info **sta)
|
|
|
*
|
|
|
* The rules are not trivial, but not too complex either:
|
|
|
* (1) pin_status is only modified under the sta_lock
|
|
|
- * (2) sta_info_debugfs_add_work() will set the status
|
|
|
+ * (2) STAs may only be pinned under the RTNL so that
|
|
|
+ * sta_info_flush() is guaranteed to actually destroy
|
|
|
+ * all STAs that are active for a given interface, this
|
|
|
+ * is required for correctness because otherwise we
|
|
|
+ * could notify a driver that an interface is going
|
|
|
+ * away and only after that (!) notify it about a STA
|
|
|
+ * on that interface going away.
|
|
|
+ * (3) sta_info_debugfs_add_work() will set the status
|
|
|
* to PINNED when it found an item that needs a new
|
|
|
* debugfs directory created. In that case, that item
|
|
|
* must not be freed although all *RCU* users are done
|
|
|
* with it. Hence, we tell the caller of _unlink()
|
|
|
* that the item is already gone (as can happen when
|
|
|
* two tasks try to unlink/destroy at the same time)
|
|
|
- * (3) We set the pin_status to DESTROY here when we
|
|
|
+ * (4) We set the pin_status to DESTROY here when we
|
|
|
* find such an item.
|
|
|
- * (4) sta_info_debugfs_add_work() will reset the pin_status
|
|
|
+ * (5) sta_info_debugfs_add_work() will reset the pin_status
|
|
|
* from PINNED to NORMAL when it is done with the item,
|
|
|
* but will check for DESTROY before resetting it in
|
|
|
* which case it will free the item.
|
|
@@ -617,6 +624,8 @@ static void sta_info_debugfs_add_work(struct work_struct *work)
|
|
|
struct sta_info *sta, *tmp;
|
|
|
unsigned long flags;
|
|
|
|
|
|
+ /* We need to keep the RTNL across the whole pinned status. */
|
|
|
+ rtnl_lock();
|
|
|
while (1) {
|
|
|
sta = NULL;
|
|
|
|
|
@@ -637,10 +646,9 @@ static void sta_info_debugfs_add_work(struct work_struct *work)
|
|
|
rate_control_add_sta_debugfs(sta);
|
|
|
|
|
|
sta = __sta_info_unpin(sta);
|
|
|
- rtnl_lock();
|
|
|
sta_info_destroy(sta);
|
|
|
- rtnl_unlock();
|
|
|
}
|
|
|
+ rtnl_unlock();
|
|
|
}
|
|
|
#endif
|
|
|
|
|
@@ -700,6 +708,15 @@ void sta_info_stop(struct ieee80211_local *local)
|
|
|
{
|
|
|
del_timer(&local->sta_cleanup);
|
|
|
cancel_work_sync(&local->sta_flush_work);
|
|
|
+#ifdef CONFIG_MAC80211_DEBUGFS
|
|
|
+ /*
|
|
|
+ * Make sure the debugfs adding work isn't pending after this
|
|
|
+ * because we're about to be destroyed. It doesn't matter
|
|
|
+ * whether it ran or not since we're going to flush all STAs
|
|
|
+ * anyway.
|
|
|
+ */
|
|
|
+ cancel_work_sync(&local->sta_debugfs_add);
|
|
|
+#endif
|
|
|
|
|
|
rtnl_lock();
|
|
|
sta_info_flush(local, NULL);
|