ath9k: Read and write the TSF via debugfs
authorAlina Friedrichsen <x-alina@gmx.net>
Fri, 23 Jan 2009 04:44:21 +0000 (05:44 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 29 Jan 2009 21:01:22 +0000 (16:01 -0500)
This patch adds an ath9k specific entry to read, write and reset the TSF into the debugfs, like in ath5k. This makes debugging the IBSS handling of wifi drivers _much_ easier.

Signed-off-by: Alina Friedrichsen <x-alina@gmx.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath9k/ath9k.h
drivers/net/wireless/ath9k/core.h
drivers/net/wireless/ath9k/debug.c
drivers/net/wireless/ath9k/hw.c

index f158cba0140751b29bd7cbb66b60888ef151d0f7..f44aab50a2d63cb99c768cbb2e14ee3e678b1da1 100644 (file)
@@ -899,6 +899,7 @@ void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask);
 bool ath9k_hw_setbssidmask(struct ath_hal *ah, const u8 *mask);
 void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, u16 assocId);
 u64 ath9k_hw_gettsf64(struct ath_hal *ah);
+void ath9k_hw_settsf64(struct ath_hal *ah, u64 tsf64);
 void ath9k_hw_reset_tsf(struct ath_hal *ah);
 bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, u32 setting);
 bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us);
index 29251f8dabb07a0417b2f0f8fdc4d8a4d61ec47a..acbd8881ef83467d65f79aeed9623688e6a9a0ee 100644 (file)
@@ -141,6 +141,7 @@ struct ath9k_debug {
        struct dentry *debugfs_phy;
        struct dentry *debugfs_dma;
        struct dentry *debugfs_interrupt;
+       struct dentry *debugfs_tsf;
        struct ath_stats stats;
 };
 
index a80ed576830f0238f07ac003a8c8c579d52c86cc..05e1f82cc7a160cdbf421934499fdaae55b60908 100644 (file)
@@ -222,6 +222,49 @@ static const struct file_operations fops_interrupt = {
        .owner = THIS_MODULE
 };
 
+
+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;
@@ -247,6 +290,11 @@ 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);
@@ -255,6 +303,7 @@ 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 f2922bab7761793214fd5ce8f3aed64c14e808b8..1a49743151ba90c9492a7d685d581a7973cfb456 100644 (file)
@@ -3755,6 +3755,13 @@ u64 ath9k_hw_gettsf64(struct ath_hal *ah)
        return tsf;
 }
 
+void ath9k_hw_settsf64(struct ath_hal *ah, u64 tsf64)
+{
+       REG_WRITE(ah, AR_TSF_L32, 0x00000000);
+       REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
+       REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
+}
+
 void ath9k_hw_reset_tsf(struct ath_hal *ah)
 {
        int count;