mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-01 08:04:22 +08:00
mac80211: Generic TSF debugging
This patch enables low-level driver independent debugging of the TSF and remove the driver specific things of ath5k and ath9k from the debugfs. Signed-off-by: Alina Friedrichsen <x-alina@gmx.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
3978e5bce6
commit
3b5d665b51
@ -239,6 +239,7 @@ static int ath5k_get_stats(struct ieee80211_hw *hw,
|
|||||||
static int ath5k_get_tx_stats(struct ieee80211_hw *hw,
|
static int ath5k_get_tx_stats(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_tx_queue_stats *stats);
|
struct ieee80211_tx_queue_stats *stats);
|
||||||
static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
|
static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
|
||||||
|
static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf);
|
||||||
static void ath5k_reset_tsf(struct ieee80211_hw *hw);
|
static void ath5k_reset_tsf(struct ieee80211_hw *hw);
|
||||||
static int ath5k_beacon_update(struct ath5k_softc *sc,
|
static int ath5k_beacon_update(struct ath5k_softc *sc,
|
||||||
struct sk_buff *skb);
|
struct sk_buff *skb);
|
||||||
@ -261,6 +262,7 @@ static struct ieee80211_ops ath5k_hw_ops = {
|
|||||||
.conf_tx = NULL,
|
.conf_tx = NULL,
|
||||||
.get_tx_stats = ath5k_get_tx_stats,
|
.get_tx_stats = ath5k_get_tx_stats,
|
||||||
.get_tsf = ath5k_get_tsf,
|
.get_tsf = ath5k_get_tsf,
|
||||||
|
.set_tsf = ath5k_set_tsf,
|
||||||
.reset_tsf = ath5k_reset_tsf,
|
.reset_tsf = ath5k_reset_tsf,
|
||||||
.bss_info_changed = ath5k_bss_info_changed,
|
.bss_info_changed = ath5k_bss_info_changed,
|
||||||
};
|
};
|
||||||
@ -3110,6 +3112,14 @@ ath5k_get_tsf(struct ieee80211_hw *hw)
|
|||||||
return ath5k_hw_get_tsf64(sc->ah);
|
return ath5k_hw_get_tsf64(sc->ah);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
|
||||||
|
{
|
||||||
|
struct ath5k_softc *sc = hw->priv;
|
||||||
|
|
||||||
|
ath5k_hw_set_tsf64(sc->ah, tsf);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ath5k_reset_tsf(struct ieee80211_hw *hw)
|
ath5k_reset_tsf(struct ieee80211_hw *hw)
|
||||||
{
|
{
|
||||||
|
@ -193,50 +193,6 @@ static const struct file_operations fops_registers = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* debugfs: TSF */
|
|
||||||
|
|
||||||
static ssize_t read_file_tsf(struct file *file, char __user *user_buf,
|
|
||||||
size_t count, loff_t *ppos)
|
|
||||||
{
|
|
||||||
struct ath5k_softc *sc = file->private_data;
|
|
||||||
char buf[100];
|
|
||||||
snprintf(buf, sizeof(buf), "0x%016llx\n",
|
|
||||||
(unsigned long long)ath5k_hw_get_tsf64(sc->ah));
|
|
||||||
return simple_read_from_buffer(user_buf, count, ppos, buf, 19);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t write_file_tsf(struct file *file,
|
|
||||||
const char __user *userbuf,
|
|
||||||
size_t count, loff_t *ppos)
|
|
||||||
{
|
|
||||||
struct ath5k_softc *sc = file->private_data;
|
|
||||||
char buf[21];
|
|
||||||
unsigned long long tsf;
|
|
||||||
|
|
||||||
if (copy_from_user(buf, userbuf, min(count, sizeof(buf) - 1)))
|
|
||||||
return -EFAULT;
|
|
||||||
buf[sizeof(buf) - 1] = '\0';
|
|
||||||
|
|
||||||
if (strncmp(buf, "reset", 5) == 0) {
|
|
||||||
ath5k_hw_reset_tsf(sc->ah);
|
|
||||||
printk(KERN_INFO "debugfs reset TSF\n");
|
|
||||||
} else {
|
|
||||||
tsf = simple_strtoul(buf, NULL, 0);
|
|
||||||
ath5k_hw_set_tsf64(sc->ah, tsf);
|
|
||||||
printk(KERN_INFO "debugfs set TSF to %#018llx\n", tsf);
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct file_operations fops_tsf = {
|
|
||||||
.read = read_file_tsf,
|
|
||||||
.write = write_file_tsf,
|
|
||||||
.open = ath5k_debugfs_open,
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* debugfs: beacons */
|
/* debugfs: beacons */
|
||||||
|
|
||||||
static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
|
static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
|
||||||
@ -430,9 +386,6 @@ ath5k_debug_init_device(struct ath5k_softc *sc)
|
|||||||
sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUGO,
|
sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUGO,
|
||||||
sc->debug.debugfs_phydir, sc, &fops_registers);
|
sc->debug.debugfs_phydir, sc, &fops_registers);
|
||||||
|
|
||||||
sc->debug.debugfs_tsf = debugfs_create_file("tsf", S_IWUSR | S_IRUGO,
|
|
||||||
sc->debug.debugfs_phydir, sc, &fops_tsf);
|
|
||||||
|
|
||||||
sc->debug.debugfs_beacon = debugfs_create_file("beacon", S_IWUSR | S_IRUGO,
|
sc->debug.debugfs_beacon = debugfs_create_file("beacon", S_IWUSR | S_IRUGO,
|
||||||
sc->debug.debugfs_phydir, sc, &fops_beacon);
|
sc->debug.debugfs_phydir, sc, &fops_beacon);
|
||||||
|
|
||||||
@ -451,7 +404,6 @@ ath5k_debug_finish_device(struct ath5k_softc *sc)
|
|||||||
{
|
{
|
||||||
debugfs_remove(sc->debug.debugfs_debug);
|
debugfs_remove(sc->debug.debugfs_debug);
|
||||||
debugfs_remove(sc->debug.debugfs_registers);
|
debugfs_remove(sc->debug.debugfs_registers);
|
||||||
debugfs_remove(sc->debug.debugfs_tsf);
|
|
||||||
debugfs_remove(sc->debug.debugfs_beacon);
|
debugfs_remove(sc->debug.debugfs_beacon);
|
||||||
debugfs_remove(sc->debug.debugfs_reset);
|
debugfs_remove(sc->debug.debugfs_reset);
|
||||||
debugfs_remove(sc->debug.debugfs_phydir);
|
debugfs_remove(sc->debug.debugfs_phydir);
|
||||||
|
@ -72,7 +72,6 @@ struct ath5k_dbg_info {
|
|||||||
struct dentry *debugfs_phydir;
|
struct dentry *debugfs_phydir;
|
||||||
struct dentry *debugfs_debug;
|
struct dentry *debugfs_debug;
|
||||||
struct dentry *debugfs_registers;
|
struct dentry *debugfs_registers;
|
||||||
struct dentry *debugfs_tsf;
|
|
||||||
struct dentry *debugfs_beacon;
|
struct dentry *debugfs_beacon;
|
||||||
struct dentry *debugfs_reset;
|
struct dentry *debugfs_reset;
|
||||||
};
|
};
|
||||||
|
@ -141,7 +141,6 @@ struct ath9k_debug {
|
|||||||
struct dentry *debugfs_phy;
|
struct dentry *debugfs_phy;
|
||||||
struct dentry *debugfs_dma;
|
struct dentry *debugfs_dma;
|
||||||
struct dentry *debugfs_interrupt;
|
struct dentry *debugfs_interrupt;
|
||||||
struct dentry *debugfs_tsf;
|
|
||||||
struct ath_stats stats;
|
struct ath_stats stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -223,48 +223,6 @@ static const struct file_operations fops_interrupt = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static ssize_t read_file_tsf(struct file *file, char __user *user_buf,
|
|
||||||
size_t count, loff_t *ppos)
|
|
||||||
{
|
|
||||||
struct ath_softc *sc = file->private_data;
|
|
||||||
char buf[100];
|
|
||||||
snprintf(buf, sizeof(buf), "0x%016llx\n",
|
|
||||||
(unsigned long long)ath9k_hw_gettsf64(sc->sc_ah));
|
|
||||||
return simple_read_from_buffer(user_buf, count, ppos, buf, 19);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t write_file_tsf(struct file *file,
|
|
||||||
const char __user *user_buf,
|
|
||||||
size_t count, loff_t *ppos)
|
|
||||||
{
|
|
||||||
struct ath_softc *sc = file->private_data;
|
|
||||||
char buf[21];
|
|
||||||
unsigned long long tsf;
|
|
||||||
|
|
||||||
if (copy_from_user(buf, user_buf, min(count, sizeof(buf) - 1)))
|
|
||||||
return -EFAULT;
|
|
||||||
buf[sizeof(buf) - 1] = '\0';
|
|
||||||
|
|
||||||
if (strncmp(buf, "reset", 5) == 0) {
|
|
||||||
ath9k_hw_reset_tsf(sc->sc_ah);
|
|
||||||
printk(KERN_INFO "debugfs reset TSF\n");
|
|
||||||
} else {
|
|
||||||
tsf = simple_strtoul(buf, NULL, 0);
|
|
||||||
ath9k_hw_settsf64(sc->sc_ah, tsf);
|
|
||||||
printk(KERN_INFO "debugfs set TSF to %#018llx\n", tsf);
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct file_operations fops_tsf = {
|
|
||||||
.read = read_file_tsf,
|
|
||||||
.write = write_file_tsf,
|
|
||||||
.open = ath9k_debugfs_open,
|
|
||||||
.owner = THIS_MODULE
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int ath9k_init_debug(struct ath_softc *sc)
|
int ath9k_init_debug(struct ath_softc *sc)
|
||||||
{
|
{
|
||||||
sc->sc_debug.debug_mask = ath9k_debug;
|
sc->sc_debug.debug_mask = ath9k_debug;
|
||||||
@ -290,11 +248,6 @@ int ath9k_init_debug(struct ath_softc *sc)
|
|||||||
if (!sc->sc_debug.debugfs_interrupt)
|
if (!sc->sc_debug.debugfs_interrupt)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
sc->sc_debug.debugfs_tsf = debugfs_create_file("tsf", S_IRUGO,
|
|
||||||
sc->sc_debug.debugfs_phy, sc, &fops_tsf);
|
|
||||||
if (!sc->sc_debug.debugfs_tsf)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
err:
|
||||||
ath9k_exit_debug(sc);
|
ath9k_exit_debug(sc);
|
||||||
@ -303,7 +256,6 @@ err:
|
|||||||
|
|
||||||
void ath9k_exit_debug(struct ath_softc *sc)
|
void ath9k_exit_debug(struct ath_softc *sc)
|
||||||
{
|
{
|
||||||
debugfs_remove(sc->sc_debug.debugfs_tsf);
|
|
||||||
debugfs_remove(sc->sc_debug.debugfs_interrupt);
|
debugfs_remove(sc->sc_debug.debugfs_interrupt);
|
||||||
debugfs_remove(sc->sc_debug.debugfs_dma);
|
debugfs_remove(sc->sc_debug.debugfs_dma);
|
||||||
debugfs_remove(sc->sc_debug.debugfs_phy);
|
debugfs_remove(sc->sc_debug.debugfs_phy);
|
||||||
|
@ -2451,6 +2451,14 @@ static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
|
|||||||
return tsf;
|
return tsf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
|
||||||
|
{
|
||||||
|
struct ath_softc *sc = hw->priv;
|
||||||
|
struct ath_hal *ah = sc->sc_ah;
|
||||||
|
|
||||||
|
ath9k_hw_settsf64(ah, tsf);
|
||||||
|
}
|
||||||
|
|
||||||
static void ath9k_reset_tsf(struct ieee80211_hw *hw)
|
static void ath9k_reset_tsf(struct ieee80211_hw *hw)
|
||||||
{
|
{
|
||||||
struct ath_softc *sc = hw->priv;
|
struct ath_softc *sc = hw->priv;
|
||||||
@ -2514,6 +2522,7 @@ struct ieee80211_ops ath9k_ops = {
|
|||||||
.bss_info_changed = ath9k_bss_info_changed,
|
.bss_info_changed = ath9k_bss_info_changed,
|
||||||
.set_key = ath9k_set_key,
|
.set_key = ath9k_set_key,
|
||||||
.get_tsf = ath9k_get_tsf,
|
.get_tsf = ath9k_get_tsf,
|
||||||
|
.set_tsf = ath9k_set_tsf,
|
||||||
.reset_tsf = ath9k_reset_tsf,
|
.reset_tsf = ath9k_reset_tsf,
|
||||||
.ampdu_action = ath9k_ampdu_action,
|
.ampdu_action = ath9k_ampdu_action,
|
||||||
};
|
};
|
||||||
|
@ -1359,7 +1359,11 @@ enum ieee80211_ampdu_mlme_action {
|
|||||||
* hw->ampdu_queues items.
|
* hw->ampdu_queues items.
|
||||||
*
|
*
|
||||||
* @get_tsf: Get the current TSF timer value from firmware/hardware. Currently,
|
* @get_tsf: Get the current TSF timer value from firmware/hardware. Currently,
|
||||||
* this is only used for IBSS mode debugging and, as such, is not a
|
* this is only used for IBSS mode BSSID merging and debugging. Is not a
|
||||||
|
* required function. Must be atomic.
|
||||||
|
*
|
||||||
|
* @set_tsf: Set the TSF timer to the specified value in the firmware/hardware.
|
||||||
|
* Currently, this is only used for IBSS mode debugging. Is not a
|
||||||
* required function. Must be atomic.
|
* required function. Must be atomic.
|
||||||
*
|
*
|
||||||
* @reset_tsf: Reset the TSF timer and allow firmware/hardware to synchronize
|
* @reset_tsf: Reset the TSF timer and allow firmware/hardware to synchronize
|
||||||
@ -1421,6 +1425,7 @@ struct ieee80211_ops {
|
|||||||
int (*get_tx_stats)(struct ieee80211_hw *hw,
|
int (*get_tx_stats)(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_tx_queue_stats *stats);
|
struct ieee80211_tx_queue_stats *stats);
|
||||||
u64 (*get_tsf)(struct ieee80211_hw *hw);
|
u64 (*get_tsf)(struct ieee80211_hw *hw);
|
||||||
|
void (*set_tsf)(struct ieee80211_hw *hw, u64 tsf);
|
||||||
void (*reset_tsf)(struct ieee80211_hw *hw);
|
void (*reset_tsf)(struct ieee80211_hw *hw);
|
||||||
int (*tx_last_beacon)(struct ieee80211_hw *hw);
|
int (*tx_last_beacon)(struct ieee80211_hw *hw);
|
||||||
int (*ampdu_action)(struct ieee80211_hw *hw,
|
int (*ampdu_action)(struct ieee80211_hw *hw,
|
||||||
|
@ -57,12 +57,61 @@ DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
|
|||||||
local->hw.conf.long_frame_max_tx_count);
|
local->hw.conf.long_frame_max_tx_count);
|
||||||
DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d",
|
DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d",
|
||||||
local->total_ps_buffered);
|
local->total_ps_buffered);
|
||||||
DEBUGFS_READONLY_FILE(wep_iv, 20, "%#06x",
|
DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x",
|
||||||
local->wep_iv & 0xffffff);
|
local->wep_iv & 0xffffff);
|
||||||
DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s",
|
DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s",
|
||||||
local->rate_ctrl ? local->rate_ctrl->ops->name : "<unset>");
|
local->rate_ctrl ? local->rate_ctrl->ops->name : "<unset>");
|
||||||
DEBUGFS_READONLY_FILE(tsf, 20, "%#018llx",
|
|
||||||
(unsigned long long) (local->ops->get_tsf ? local->ops->get_tsf(local_to_hw(local)) : 0));
|
static ssize_t tsf_read(struct file *file, char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct ieee80211_local *local = file->private_data;
|
||||||
|
u64 tsf = 0;
|
||||||
|
char buf[100];
|
||||||
|
|
||||||
|
if (local->ops->get_tsf)
|
||||||
|
tsf = local->ops->get_tsf(local_to_hw(local));
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "0x%016llx\n", (unsigned long long) tsf);
|
||||||
|
|
||||||
|
return simple_read_from_buffer(user_buf, count, ppos, buf, 19);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t tsf_write(struct file *file,
|
||||||
|
const char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct ieee80211_local *local = file->private_data;
|
||||||
|
unsigned long long tsf;
|
||||||
|
char buf[100];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
len = min(count, sizeof(buf) - 1);
|
||||||
|
if (copy_from_user(buf, user_buf, len))
|
||||||
|
return -EFAULT;
|
||||||
|
buf[len] = '\0';
|
||||||
|
|
||||||
|
if (strncmp(buf, "reset", 5) == 0) {
|
||||||
|
if (local->ops->reset_tsf) {
|
||||||
|
local->ops->reset_tsf(local_to_hw(local));
|
||||||
|
printk(KERN_INFO "%s: debugfs reset TSF\n", wiphy_name(local->hw.wiphy));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tsf = simple_strtoul(buf, NULL, 0);
|
||||||
|
if (local->ops->set_tsf) {
|
||||||
|
local->ops->set_tsf(local_to_hw(local), tsf);
|
||||||
|
printk(KERN_INFO "%s: debugfs set TSF to %#018llx\n", wiphy_name(local->hw.wiphy), tsf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations tsf_ops = {
|
||||||
|
.read = tsf_read,
|
||||||
|
.write = tsf_write,
|
||||||
|
.open = mac80211_open_file_generic
|
||||||
|
};
|
||||||
|
|
||||||
/* statistics stuff */
|
/* statistics stuff */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user