Commit 4ded3bfe authored by Johannes Berg's avatar Johannes Berg

wifi: mac80211: use wiphy locked debugfs for sdata/link

The debugfs files for netdevs (sdata) and links are removed
with the wiphy mutex held, which may deadlock. Use the new
wiphy locked debugfs to avoid that.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 3d529cd1
...@@ -22,88 +22,148 @@ ...@@ -22,88 +22,148 @@
#include "debugfs_netdev.h" #include "debugfs_netdev.h"
#include "driver-ops.h" #include "driver-ops.h"
struct ieee80211_if_read_sdata_data {
ssize_t (*format)(const struct ieee80211_sub_if_data *, char *, int);
struct ieee80211_sub_if_data *sdata;
};
static ssize_t ieee80211_if_read_sdata_handler(struct wiphy *wiphy,
struct file *file,
char *buf,
size_t bufsize,
void *data)
{
struct ieee80211_if_read_sdata_data *d = data;
return d->format(d->sdata, buf, bufsize);
}
static ssize_t ieee80211_if_read_sdata( static ssize_t ieee80211_if_read_sdata(
struct ieee80211_sub_if_data *sdata, struct file *file,
char __user *userbuf, char __user *userbuf,
size_t count, loff_t *ppos, size_t count, loff_t *ppos,
ssize_t (*format)(const struct ieee80211_sub_if_data *sdata, char *, int)) ssize_t (*format)(const struct ieee80211_sub_if_data *sdata, char *, int))
{ {
struct ieee80211_sub_if_data *sdata = file->private_data;
struct ieee80211_if_read_sdata_data data = {
.format = format,
.sdata = sdata,
};
char buf[200]; char buf[200];
ssize_t ret = -EINVAL;
wiphy_lock(sdata->local->hw.wiphy); return wiphy_locked_debugfs_read(sdata->local->hw.wiphy,
ret = (*format)(sdata, buf, sizeof(buf)); file, buf, sizeof(buf),
wiphy_unlock(sdata->local->hw.wiphy); userbuf, count, ppos,
ieee80211_if_read_sdata_handler,
&data);
}
if (ret >= 0) struct ieee80211_if_write_sdata_data {
ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret); ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int);
struct ieee80211_sub_if_data *sdata;
};
return ret; static ssize_t ieee80211_if_write_sdata_handler(struct wiphy *wiphy,
struct file *file,
char *buf,
size_t count,
void *data)
{
struct ieee80211_if_write_sdata_data *d = data;
return d->write(d->sdata, buf, count);
} }
static ssize_t ieee80211_if_write_sdata( static ssize_t ieee80211_if_write_sdata(
struct ieee80211_sub_if_data *sdata, struct file *file,
const char __user *userbuf, const char __user *userbuf,
size_t count, loff_t *ppos, size_t count, loff_t *ppos,
ssize_t (*write)(struct ieee80211_sub_if_data *sdata, const char *, int)) ssize_t (*write)(struct ieee80211_sub_if_data *sdata, const char *, int))
{ {
struct ieee80211_sub_if_data *sdata = file->private_data;
struct ieee80211_if_write_sdata_data data = {
.write = write,
.sdata = sdata,
};
char buf[64]; char buf[64];
ssize_t ret;
if (count >= sizeof(buf)) return wiphy_locked_debugfs_write(sdata->local->hw.wiphy,
return -E2BIG; file, buf, sizeof(buf),
userbuf, count,
ieee80211_if_write_sdata_handler,
&data);
}
if (copy_from_user(buf, userbuf, count)) struct ieee80211_if_read_link_data {
return -EFAULT; ssize_t (*format)(const struct ieee80211_link_data *, char *, int);
buf[count] = '\0'; struct ieee80211_link_data *link;
};
wiphy_lock(sdata->local->hw.wiphy); static ssize_t ieee80211_if_read_link_handler(struct wiphy *wiphy,
ret = (*write)(sdata, buf, count); struct file *file,
wiphy_unlock(sdata->local->hw.wiphy); char *buf,
size_t bufsize,
void *data)
{
struct ieee80211_if_read_link_data *d = data;
return ret; return d->format(d->link, buf, bufsize);
} }
static ssize_t ieee80211_if_read_link( static ssize_t ieee80211_if_read_link(
struct ieee80211_link_data *link, struct file *file,
char __user *userbuf, char __user *userbuf,
size_t count, loff_t *ppos, size_t count, loff_t *ppos,
ssize_t (*format)(const struct ieee80211_link_data *link, char *, int)) ssize_t (*format)(const struct ieee80211_link_data *link, char *, int))
{ {
struct ieee80211_link_data *link = file->private_data;
struct ieee80211_if_read_link_data data = {
.format = format,
.link = link,
};
char buf[200]; char buf[200];
ssize_t ret = -EINVAL;
wiphy_lock(link->sdata->local->hw.wiphy); return wiphy_locked_debugfs_read(link->sdata->local->hw.wiphy,
ret = (*format)(link, buf, sizeof(buf)); file, buf, sizeof(buf),
wiphy_unlock(link->sdata->local->hw.wiphy); userbuf, count, ppos,
ieee80211_if_read_link_handler,
&data);
}
if (ret >= 0) struct ieee80211_if_write_link_data {
ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret); ssize_t (*write)(struct ieee80211_link_data *, const char *, int);
struct ieee80211_link_data *link;
};
return ret; static ssize_t ieee80211_if_write_link_handler(struct wiphy *wiphy,
struct file *file,
char *buf,
size_t count,
void *data)
{
struct ieee80211_if_write_sdata_data *d = data;
return d->write(d->sdata, buf, count);
} }
static ssize_t ieee80211_if_write_link( static ssize_t ieee80211_if_write_link(
struct ieee80211_link_data *link, struct file *file,
const char __user *userbuf, const char __user *userbuf,
size_t count, loff_t *ppos, size_t count, loff_t *ppos,
ssize_t (*write)(struct ieee80211_link_data *link, const char *, int)) ssize_t (*write)(struct ieee80211_link_data *link, const char *, int))
{ {
struct ieee80211_link_data *link = file->private_data;
struct ieee80211_if_write_link_data data = {
.write = write,
.link = link,
};
char buf[64]; char buf[64];
ssize_t ret;
if (count >= sizeof(buf))
return -E2BIG;
if (copy_from_user(buf, userbuf, count)) return wiphy_locked_debugfs_write(link->sdata->local->hw.wiphy,
return -EFAULT; file, buf, sizeof(buf),
buf[count] = '\0'; userbuf, count,
ieee80211_if_write_link_handler,
wiphy_lock(link->sdata->local->hw.wiphy); &data);
ret = (*write)(link, buf, count);
wiphy_unlock(link->sdata->local->hw.wiphy);
return ret;
} }
#define IEEE80211_IF_FMT(name, type, field, format_string) \ #define IEEE80211_IF_FMT(name, type, field, format_string) \
...@@ -173,7 +233,7 @@ static ssize_t ieee80211_if_read_##name(struct file *file, \ ...@@ -173,7 +233,7 @@ static ssize_t ieee80211_if_read_##name(struct file *file, \
char __user *userbuf, \ char __user *userbuf, \
size_t count, loff_t *ppos) \ size_t count, loff_t *ppos) \
{ \ { \
return ieee80211_if_read_sdata(file->private_data, \ return ieee80211_if_read_sdata(file, \
userbuf, count, ppos, \ userbuf, count, ppos, \
ieee80211_if_fmt_##name); \ ieee80211_if_fmt_##name); \
} }
...@@ -183,7 +243,7 @@ static ssize_t ieee80211_if_write_##name(struct file *file, \ ...@@ -183,7 +243,7 @@ static ssize_t ieee80211_if_write_##name(struct file *file, \
const char __user *userbuf, \ const char __user *userbuf, \
size_t count, loff_t *ppos) \ size_t count, loff_t *ppos) \
{ \ { \
return ieee80211_if_write_sdata(file->private_data, userbuf, \ return ieee80211_if_write_sdata(file, userbuf, \
count, ppos, \ count, ppos, \
ieee80211_if_parse_##name); \ ieee80211_if_parse_##name); \
} }
...@@ -211,7 +271,7 @@ static ssize_t ieee80211_if_read_##name(struct file *file, \ ...@@ -211,7 +271,7 @@ static ssize_t ieee80211_if_read_##name(struct file *file, \
char __user *userbuf, \ char __user *userbuf, \
size_t count, loff_t *ppos) \ size_t count, loff_t *ppos) \
{ \ { \
return ieee80211_if_read_link(file->private_data, \ return ieee80211_if_read_link(file, \
userbuf, count, ppos, \ userbuf, count, ppos, \
ieee80211_if_fmt_##name); \ ieee80211_if_fmt_##name); \
} }
...@@ -221,7 +281,7 @@ static ssize_t ieee80211_if_write_##name(struct file *file, \ ...@@ -221,7 +281,7 @@ static ssize_t ieee80211_if_write_##name(struct file *file, \
const char __user *userbuf, \ const char __user *userbuf, \
size_t count, loff_t *ppos) \ size_t count, loff_t *ppos) \
{ \ { \
return ieee80211_if_write_link(file->private_data, userbuf, \ return ieee80211_if_write_link(file, userbuf, \
count, ppos, \ count, ppos, \
ieee80211_if_parse_##name); \ ieee80211_if_parse_##name); \
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment