mac80211: Generic TSF debugging
Alina Friedrichsen [Sat, 24 Jan 2009 06:09:59 +0000 (07:09 +0100)]
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>

drivers/net/wireless/ath5k/base.c
drivers/net/wireless/ath5k/debug.c
drivers/net/wireless/ath5k/debug.h
drivers/net/wireless/ath9k/core.h
drivers/net/wireless/ath9k/debug.c
drivers/net/wireless/ath9k/main.c
include/net/mac80211.h
net/mac80211/debugfs.c

index fa39f21..b3f41ac 100644 (file)
@@ -239,6 +239,7 @@ static int ath5k_get_stats(struct ieee80211_hw *hw,
 static int ath5k_get_tx_stats(struct ieee80211_hw *hw,
                struct ieee80211_tx_queue_stats *stats);
 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 int ath5k_beacon_update(struct ath5k_softc *sc,
                struct sk_buff *skb);
@@ -261,6 +262,7 @@ static struct ieee80211_ops ath5k_hw_ops = {
        .conf_tx        = NULL,
        .get_tx_stats   = ath5k_get_tx_stats,
        .get_tsf        = ath5k_get_tsf,
+       .set_tsf        = ath5k_set_tsf,
        .reset_tsf      = ath5k_reset_tsf,
        .bss_info_changed = ath5k_bss_info_changed,
 };
@@ -3111,6 +3113,14 @@ ath5k_get_tsf(struct ieee80211_hw *hw)
 }
 
 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
 ath5k_reset_tsf(struct ieee80211_hw *hw)
 {
        struct ath5k_softc *sc = hw->priv;
index 129b726..413ed68 100644 (file)
@@ -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 */
 
 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_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_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_registers);
-       debugfs_remove(sc->debug.debugfs_tsf);
        debugfs_remove(sc->debug.debugfs_beacon);
        debugfs_remove(sc->debug.debugfs_reset);
        debugfs_remove(sc->debug.debugfs_phydir);
index ffc5293..66f69f0 100644 (file)
@@ -72,7 +72,6 @@ struct ath5k_dbg_info {
        struct dentry           *debugfs_phydir;
        struct dentry           *debugfs_debug;
        struct dentry           *debugfs_registers;
-       struct dentry           *debugfs_tsf;
        struct dentry           *debugfs_beacon;
        struct dentry           *debugfs_reset;
 };
index acbd888..29251f8 100644 (file)
@@ -141,7 +141,6 @@ struct ath9k_debug {
        struct dentry *debugfs_phy;
        struct dentry *debugfs_dma;
        struct dentry *debugfs_interrupt;
-       struct dentry *debugfs_tsf;
        struct ath_stats stats;
 };
 
index 05e1f82..1680164 100644 (file)
@@ -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)
 {
        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)
                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;
 err:
        ath9k_exit_debug(sc);
@@ -303,7 +256,6 @@ err:
 
 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_dma);
        debugfs_remove(sc->sc_debug.debugfs_phy);
index 15a7f90..90e687b 100644 (file)
@@ -2451,6 +2451,14 @@ static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
        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)
 {
        struct ath_softc *sc = hw->priv;
@@ -2514,6 +2522,7 @@ struct ieee80211_ops ath9k_ops = {
        .bss_info_changed   = ath9k_bss_info_changed,
        .set_key            = ath9k_set_key,
        .get_tsf            = ath9k_get_tsf,
+       .set_tsf            = ath9k_set_tsf,
        .reset_tsf          = ath9k_reset_tsf,
        .ampdu_action       = ath9k_ampdu_action,
 };
index 8e65adf..e2144f0 100644 (file)
@@ -1359,7 +1359,11 @@ enum ieee80211_ampdu_mlme_action {
  *     hw->ampdu_queues items.
  *
  * @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.
  *
  * @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,
                            struct ieee80211_tx_queue_stats *stats);
        u64 (*get_tsf)(struct ieee80211_hw *hw);
+       void (*set_tsf)(struct ieee80211_hw *hw, u64 tsf);
        void (*reset_tsf)(struct ieee80211_hw *hw);
        int (*tx_last_beacon)(struct ieee80211_hw *hw);
        int (*ampdu_action)(struct ieee80211_hw *hw,
index 717d548..e37f557 100644 (file)
@@ -57,12 +57,61 @@ DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
                      local->hw.conf.long_frame_max_tx_count);
 DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d",
                      local->total_ps_buffered);
-DEBUGFS_READONLY_FILE(wep_iv, 20, "%#06x",
+DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x",
                      local->wep_iv & 0xffffff);
 DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s",
                      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 */