Skip to content

Commit 3d529cd

Browse files
committed
wifi: mac80211: use wiphy locked debugfs helpers for agg_status
The read is currently with RCU and the write can deadlock, convert both for the sake of illustration. Make mac80211 depend on cfg80211 debugfs to get the helpers, but mac80211 debugfs without it does nothing anyway. This also required some adjustments in ath9k. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
1 parent b590b9a commit 3d529cd

3 files changed

Lines changed: 44 additions & 36 deletions

File tree

drivers/net/wireless/ath/ath9k/Kconfig

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ config ATH9K_AHB
5757

5858
config ATH9K_DEBUGFS
5959
bool "Atheros ath9k debugging"
60-
depends on ATH9K && DEBUG_FS
61-
select MAC80211_DEBUGFS
60+
depends on ATH9K && DEBUG_FS && MAC80211_DEBUGFS
6261
select ATH9K_COMMON_DEBUG
6362
help
6463
Say Y, if you need access to ath9k's statistics for
@@ -70,7 +69,6 @@ config ATH9K_DEBUGFS
7069
config ATH9K_STATION_STATISTICS
7170
bool "Detailed station statistics"
7271
depends on ATH9K && ATH9K_DEBUGFS && DEBUG_FS
73-
select MAC80211_DEBUGFS
7472
default n
7573
help
7674
This option enables detailed statistics for association stations.

net/mac80211/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ config MAC80211_LEDS
8888

8989
config MAC80211_DEBUGFS
9090
bool "Export mac80211 internals in DebugFS"
91-
depends on MAC80211 && DEBUG_FS
91+
depends on MAC80211 && CFG80211_DEBUGFS
9292
help
9393
Select this to see extensive information about
9494
the internal state of mac80211 in debugfs.

net/mac80211/debugfs_sta.c

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -312,23 +312,14 @@ static ssize_t sta_aql_write(struct file *file, const char __user *userbuf,
312312
STA_OPS_RW(aql);
313313

314314

315-
static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
316-
size_t count, loff_t *ppos)
315+
static ssize_t sta_agg_status_do_read(struct wiphy *wiphy, struct file *file,
316+
char *buf, size_t bufsz, void *data)
317317
{
318-
char *buf, *p;
319-
ssize_t bufsz = 71 + IEEE80211_NUM_TIDS * 40;
318+
struct sta_info *sta = data;
319+
char *p = buf;
320320
int i;
321-
struct sta_info *sta = file->private_data;
322321
struct tid_ampdu_rx *tid_rx;
323322
struct tid_ampdu_tx *tid_tx;
324-
ssize_t ret;
325-
326-
buf = kzalloc(bufsz, GFP_KERNEL);
327-
if (!buf)
328-
return -ENOMEM;
329-
p = buf;
330-
331-
rcu_read_lock();
332323

333324
p += scnprintf(p, bufsz + buf - p, "next dialog_token: %#02x\n",
334325
sta->ampdu_mlme.dialog_token_allocator + 1);
@@ -338,8 +329,8 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
338329
for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
339330
bool tid_rx_valid;
340331

341-
tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[i]);
342-
tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[i]);
332+
tid_rx = wiphy_dereference(wiphy, sta->ampdu_mlme.tid_rx[i]);
333+
tid_tx = wiphy_dereference(wiphy, sta->ampdu_mlme.tid_tx[i]);
343334
tid_rx_valid = test_bit(i, sta->ampdu_mlme.agg_session_valid);
344335

345336
p += scnprintf(p, bufsz + buf - p, "%02d", i);
@@ -358,31 +349,39 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
358349
tid_tx ? skb_queue_len(&tid_tx->pending) : 0);
359350
p += scnprintf(p, bufsz + buf - p, "\n");
360351
}
361-
rcu_read_unlock();
362352

363-
ret = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
353+
return p - buf;
354+
}
355+
356+
static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
357+
size_t count, loff_t *ppos)
358+
{
359+
struct sta_info *sta = file->private_data;
360+
struct wiphy *wiphy = sta->local->hw.wiphy;
361+
size_t bufsz = 71 + IEEE80211_NUM_TIDS * 40;
362+
char *buf = kmalloc(bufsz, GFP_KERNEL);
363+
ssize_t ret;
364+
365+
if (!buf)
366+
return -ENOMEM;
367+
368+
ret = wiphy_locked_debugfs_read(wiphy, file, buf, bufsz,
369+
userbuf, count, ppos,
370+
sta_agg_status_do_read, sta);
364371
kfree(buf);
372+
365373
return ret;
366374
}
367375

368-
static ssize_t sta_agg_status_write(struct file *file, const char __user *userbuf,
369-
size_t count, loff_t *ppos)
376+
static ssize_t sta_agg_status_do_write(struct wiphy *wiphy, struct file *file,
377+
char *buf, size_t count, void *data)
370378
{
371-
char _buf[25] = {}, *buf = _buf;
372-
struct sta_info *sta = file->private_data;
379+
struct sta_info *sta = data;
373380
bool start, tx;
374381
unsigned long tid;
375-
char *pos;
382+
char *pos = buf;
376383
int ret, timeout = 5000;
377384

378-
if (count > sizeof(_buf))
379-
return -EINVAL;
380-
381-
if (copy_from_user(buf, userbuf, count))
382-
return -EFAULT;
383-
384-
buf[sizeof(_buf) - 1] = '\0';
385-
pos = buf;
386385
buf = strsep(&pos, " ");
387386
if (!buf)
388387
return -EINVAL;
@@ -420,7 +419,6 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu
420419
if (ret || tid >= IEEE80211_NUM_TIDS)
421420
return -EINVAL;
422421

423-
wiphy_lock(sta->local->hw.wiphy);
424422
if (tx) {
425423
if (start)
426424
ret = ieee80211_start_tx_ba_session(&sta->sta, tid,
@@ -432,10 +430,22 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu
432430
3, true);
433431
ret = 0;
434432
}
435-
wiphy_unlock(sta->local->hw.wiphy);
436433

437434
return ret ?: count;
438435
}
436+
437+
static ssize_t sta_agg_status_write(struct file *file,
438+
const char __user *userbuf,
439+
size_t count, loff_t *ppos)
440+
{
441+
struct sta_info *sta = file->private_data;
442+
struct wiphy *wiphy = sta->local->hw.wiphy;
443+
char _buf[26];
444+
445+
return wiphy_locked_debugfs_write(wiphy, file, _buf, sizeof(_buf),
446+
userbuf, count,
447+
sta_agg_status_do_write, sta);
448+
}
439449
STA_OPS_RW(agg_status);
440450

441451
/* link sta attributes */

0 commit comments

Comments
 (0)