mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-21 06:50:25 +00:00

The WIPHY_DEBUGFS_READ_WRITE_FILE_OPS_MLD macro is intended to call read/write handlers with the wiphy lock held. However, the current implementation uses the MLD_DEBUGFS_READ_WRAPPER macro, which does not hold the wiphy lock during read operations. This fix updates the WIPHY_DEBUGFS_READ_WRITE_FILE_OPS_MLD macro to use the WIPHY_DEBUGFS_READ_WRAPPER_MLD macro instead, ensuring that the wiphy lock is held during both read and write operations. Signed-off-by: Pagadala Yesu Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com> Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> Link: https://patch.msgid.link/20250313002008.2001d2335e9d.I607a8bd12efc6d1190cef1fca44279dbdd2756ea@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
244 lines
8 KiB
C
244 lines
8 KiB
C
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
|
/*
|
|
* Copyright (C) 2024-2025 Intel Corporation
|
|
*/
|
|
#include "iface.h"
|
|
#include "sta.h"
|
|
|
|
#define MLD_DEBUGFS_OPEN_WRAPPER(name, buflen, argtype) \
|
|
struct dbgfs_##name##_data { \
|
|
argtype *arg; \
|
|
bool read_done; \
|
|
ssize_t rlen; \
|
|
char buf[buflen]; \
|
|
}; \
|
|
static int _iwl_dbgfs_##name##_open(struct inode *inode, \
|
|
struct file *file) \
|
|
{ \
|
|
struct dbgfs_##name##_data *data; \
|
|
\
|
|
if ((file->f_flags & O_ACCMODE) == O_RDWR) \
|
|
return -EOPNOTSUPP; \
|
|
\
|
|
data = kzalloc(sizeof(*data), GFP_KERNEL); \
|
|
if (!data) \
|
|
return -ENOMEM; \
|
|
\
|
|
data->read_done = false; \
|
|
data->arg = inode->i_private; \
|
|
file->private_data = data; \
|
|
\
|
|
return 0; \
|
|
}
|
|
|
|
#define MLD_DEBUGFS_READ_WRAPPER(name) \
|
|
static ssize_t _iwl_dbgfs_##name##_read(struct file *file, \
|
|
char __user *user_buf, \
|
|
size_t count, loff_t *ppos) \
|
|
{ \
|
|
struct dbgfs_##name##_data *data = file->private_data; \
|
|
\
|
|
if (!data->read_done) { \
|
|
data->read_done = true; \
|
|
data->rlen = iwl_dbgfs_##name##_read(data->arg, \
|
|
sizeof(data->buf),\
|
|
data->buf); \
|
|
} \
|
|
\
|
|
if (data->rlen < 0) \
|
|
return data->rlen; \
|
|
return simple_read_from_buffer(user_buf, count, ppos, \
|
|
data->buf, data->rlen); \
|
|
}
|
|
|
|
static int _iwl_dbgfs_release(struct inode *inode, struct file *file)
|
|
{
|
|
kfree(file->private_data);
|
|
return 0;
|
|
}
|
|
|
|
#define _MLD_DEBUGFS_READ_FILE_OPS(name, buflen, argtype) \
|
|
MLD_DEBUGFS_OPEN_WRAPPER(name, buflen, argtype) \
|
|
MLD_DEBUGFS_READ_WRAPPER(name) \
|
|
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
|
.read = _iwl_dbgfs_##name##_read, \
|
|
.open = _iwl_dbgfs_##name##_open, \
|
|
.llseek = generic_file_llseek, \
|
|
.release = _iwl_dbgfs_release, \
|
|
}
|
|
|
|
#define WIPHY_DEBUGFS_WRITE_HANDLER_WRAPPER(name) \
|
|
static ssize_t iwl_dbgfs_##name##_write_handler(struct wiphy *wiphy, \
|
|
struct file *file, char *buf, \
|
|
size_t count, void *data) \
|
|
{ \
|
|
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); \
|
|
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw); \
|
|
return iwl_dbgfs_##name##_write(mld, buf, count, data); \
|
|
}
|
|
|
|
static inline struct iwl_mld *
|
|
iwl_mld_from_link_sta(struct ieee80211_link_sta *link_sta)
|
|
{
|
|
struct ieee80211_vif *vif =
|
|
iwl_mld_sta_from_mac80211(link_sta->sta)->vif;
|
|
return iwl_mld_vif_from_mac80211(vif)->mld;
|
|
}
|
|
|
|
static inline struct iwl_mld *
|
|
iwl_mld_from_bss_conf(struct ieee80211_bss_conf *link)
|
|
{
|
|
return iwl_mld_vif_from_mac80211(link->vif)->mld;
|
|
}
|
|
|
|
static inline struct iwl_mld *iwl_mld_from_vif(struct ieee80211_vif *vif)
|
|
{
|
|
return iwl_mld_vif_from_mac80211(vif)->mld;
|
|
}
|
|
|
|
#define WIPHY_DEBUGFS_WRITE_WRAPPER(name, bufsz, objtype) \
|
|
WIPHY_DEBUGFS_WRITE_HANDLER_WRAPPER(name) \
|
|
static ssize_t __iwl_dbgfs_##name##_write(struct file *file, \
|
|
const char __user *user_buf, \
|
|
size_t count, loff_t *ppos) \
|
|
{ \
|
|
struct ieee80211_##objtype *arg = file->private_data; \
|
|
struct iwl_mld *mld = iwl_mld_from_##objtype(arg); \
|
|
char buf[bufsz] = {}; \
|
|
\
|
|
return wiphy_locked_debugfs_write(mld->wiphy, file, \
|
|
buf, sizeof(buf), \
|
|
user_buf, count, \
|
|
iwl_dbgfs_##name##_write_handler, \
|
|
arg); \
|
|
}
|
|
|
|
#define WIPHY_DEBUGFS_WRITE_FILE_OPS(name, bufsz, objtype) \
|
|
WIPHY_DEBUGFS_WRITE_WRAPPER(name, bufsz, objtype) \
|
|
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
|
.write = __iwl_dbgfs_##name##_write, \
|
|
.open = simple_open, \
|
|
.llseek = generic_file_llseek, \
|
|
}
|
|
|
|
#define WIPHY_DEBUGFS_READ_HANDLER_WRAPPER_MLD(name) \
|
|
static ssize_t iwl_dbgfs_##name##_read_handler(struct wiphy *wiphy, \
|
|
struct file *file, char *buf, \
|
|
size_t count, void *data) \
|
|
{ \
|
|
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); \
|
|
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw); \
|
|
return iwl_dbgfs_##name##_read(mld, buf, count); \
|
|
}
|
|
|
|
#define WIPHY_DEBUGFS_WRITE_HANDLER_WRAPPER_MLD(name) \
|
|
static ssize_t iwl_dbgfs_##name##_write_handler(struct wiphy *wiphy, \
|
|
struct file *file, char *buf, \
|
|
size_t count, void *data) \
|
|
{ \
|
|
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); \
|
|
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw); \
|
|
return iwl_dbgfs_##name##_write(mld, buf, count); \
|
|
}
|
|
|
|
#define WIPHY_DEBUGFS_WRITE_WRAPPER_MLD(name) \
|
|
WIPHY_DEBUGFS_WRITE_HANDLER_WRAPPER_MLD(name) \
|
|
static ssize_t __iwl_dbgfs_##name##_write(struct file *file, \
|
|
const char __user *user_buf, \
|
|
size_t count, loff_t *ppos) \
|
|
{ \
|
|
struct dbgfs_##name##_data *data = file->private_data; \
|
|
struct iwl_mld *mld = data->arg; \
|
|
\
|
|
return wiphy_locked_debugfs_write(mld->wiphy, file, \
|
|
data->buf, sizeof(data->buf), \
|
|
user_buf, count, \
|
|
iwl_dbgfs_##name##_write_handler, \
|
|
NULL); \
|
|
}
|
|
|
|
#define WIPHY_DEBUGFS_READ_WRAPPER_MLD(name) \
|
|
WIPHY_DEBUGFS_READ_HANDLER_WRAPPER_MLD(name) \
|
|
static ssize_t __iwl_dbgfs_##name##_read(struct file *file, \
|
|
char __user *user_buf, \
|
|
size_t count, loff_t *ppos) \
|
|
{ \
|
|
struct dbgfs_##name##_data *data = file->private_data; \
|
|
struct iwl_mld *mld = data->arg; \
|
|
\
|
|
if (!data->read_done) { \
|
|
data->read_done = true; \
|
|
data->rlen = wiphy_locked_debugfs_read(mld->wiphy, \
|
|
file, data->buf, sizeof(data->buf), \
|
|
user_buf, count, ppos, \
|
|
iwl_dbgfs_##name##_read_handler, NULL); \
|
|
return data->rlen; \
|
|
} \
|
|
\
|
|
if (data->rlen < 0) \
|
|
return data->rlen; \
|
|
return simple_read_from_buffer(user_buf, count, ppos, \
|
|
data->buf, data->rlen); \
|
|
}
|
|
|
|
#define WIPHY_DEBUGFS_READ_FILE_OPS_MLD(name, bufsz) \
|
|
MLD_DEBUGFS_OPEN_WRAPPER(name, bufsz, struct iwl_mld) \
|
|
WIPHY_DEBUGFS_READ_WRAPPER_MLD(name) \
|
|
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
|
.read = __iwl_dbgfs_##name##_read, \
|
|
.open = _iwl_dbgfs_##name##_open, \
|
|
.llseek = generic_file_llseek, \
|
|
.release = _iwl_dbgfs_release, \
|
|
}
|
|
|
|
#define WIPHY_DEBUGFS_WRITE_FILE_OPS_MLD(name, bufsz) \
|
|
MLD_DEBUGFS_OPEN_WRAPPER(name, bufsz, struct iwl_mld) \
|
|
WIPHY_DEBUGFS_WRITE_WRAPPER_MLD(name) \
|
|
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
|
.write = __iwl_dbgfs_##name##_write, \
|
|
.open = _iwl_dbgfs_##name##_open, \
|
|
.llseek = generic_file_llseek, \
|
|
.release = _iwl_dbgfs_release, \
|
|
}
|
|
|
|
#define WIPHY_DEBUGFS_READ_WRITE_FILE_OPS_MLD(name, bufsz) \
|
|
MLD_DEBUGFS_OPEN_WRAPPER(name, bufsz, struct iwl_mld) \
|
|
WIPHY_DEBUGFS_WRITE_WRAPPER_MLD(name) \
|
|
WIPHY_DEBUGFS_READ_WRAPPER_MLD(name) \
|
|
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
|
.write = __iwl_dbgfs_##name##_write, \
|
|
.read = __iwl_dbgfs_##name##_read, \
|
|
.open = _iwl_dbgfs_##name##_open, \
|
|
.llseek = generic_file_llseek, \
|
|
.release = _iwl_dbgfs_release, \
|
|
}
|
|
|
|
#define WIPHY_DEBUGFS_WRITE_WRAPPER_IEEE80211(name, bufsz, objtype) \
|
|
WIPHY_DEBUGFS_WRITE_HANDLER_WRAPPER(name) \
|
|
static ssize_t _iwl_dbgfs_##name##_write(struct file *file, \
|
|
const char __user *user_buf, \
|
|
size_t count, loff_t *ppos) \
|
|
{ \
|
|
struct dbgfs_##name##_data *data = file->private_data; \
|
|
struct ieee80211_##objtype *arg = data->arg; \
|
|
struct iwl_mld *mld = iwl_mld_from_##objtype(arg); \
|
|
char buf[bufsz] = {}; \
|
|
\
|
|
return wiphy_locked_debugfs_write(mld->wiphy, file, \
|
|
buf, sizeof(buf), \
|
|
user_buf, count, \
|
|
iwl_dbgfs_##name##_write_handler, \
|
|
arg); \
|
|
}
|
|
|
|
#define IEEE80211_WIPHY_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, objtype) \
|
|
MLD_DEBUGFS_OPEN_WRAPPER(name, bufsz, struct ieee80211_##objtype) \
|
|
WIPHY_DEBUGFS_WRITE_WRAPPER_IEEE80211(name, bufsz, objtype) \
|
|
MLD_DEBUGFS_READ_WRAPPER(name) \
|
|
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
|
.write = _iwl_dbgfs_##name##_write, \
|
|
.read = _iwl_dbgfs_##name##_read, \
|
|
.open = _iwl_dbgfs_##name##_open, \
|
|
.llseek = generic_file_llseek, \
|
|
.release = _iwl_dbgfs_release, \
|
|
}
|