ath9k: Add a debugfs file for WOW
authorSujith Manoharan <c_manoha@qca.qualcomm.com>
Fri, 30 Jan 2015 13:35:30 +0000 (19:05 +0530)
committerKalle Valo <kvalo@codeaurora.org>
Tue, 3 Feb 2015 13:31:07 +0000 (15:31 +0200)
This can be used to force WOW for cards that
are not present in the supported PCI ID list.

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/wow.c

index 803a7d4..20216c5 100644 (file)
@@ -1044,6 +1044,7 @@ struct ath_softc {
 
 #ifdef CONFIG_ATH9K_WOW
        u32 wow_intr_before_sleep;
+       bool force_wow;
 #endif
 };
 
index dd5d391..50a2e0a 100644 (file)
@@ -1043,6 +1043,69 @@ static const struct file_operations fops_ackto = {
 };
 #endif
 
+#ifdef CONFIG_ATH9K_WOW
+
+static ssize_t read_file_wow(struct file *file, char __user *user_buf,
+                            size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       unsigned int len = 0, size = 32;
+       ssize_t retval;
+       char *buf;
+
+       buf = kzalloc(size, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       len += scnprintf(buf + len, size - len, "WOW: %s\n",
+                        sc->force_wow ? "ENABLED" : "DISABLED");
+
+       if (len > size)
+               len = size;
+
+       retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       kfree(buf);
+
+       return retval;
+}
+
+static ssize_t write_file_wow(struct file *file, const char __user *user_buf,
+                             size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       unsigned long val;
+       char buf[32];
+       ssize_t len;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+
+       buf[len] = '\0';
+       if (kstrtoul(buf, 0, &val))
+               return -EINVAL;
+
+       if (val != 1)
+               return -EINVAL;
+
+       if (!sc->force_wow) {
+               sc->force_wow = true;
+               ath9k_init_wow(sc->hw);
+       }
+
+       return count;
+}
+
+static const struct file_operations fops_wow = {
+       .read = read_file_wow,
+       .write = write_file_wow,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+#endif
+
 static ssize_t read_file_tpc(struct file *file, char __user *user_buf,
                             size_t count, loff_t *ppos)
 {
@@ -1313,6 +1376,11 @@ int ath9k_init_debug(struct ath_hw *ah)
                            &fops_btcoex);
 #endif
 
+#ifdef CONFIG_ATH9K_WOW
+       debugfs_create_file("wow", S_IRUSR | S_IWUSR,
+                           sc->debug.debugfs_phy, sc, &fops_wow);
+#endif
+
 #ifdef CONFIG_ATH9K_DYNACK
        debugfs_create_file("ack_to", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
                            sc, &fops_ackto);
index d4cfbc3..4b3b565 100644 (file)
@@ -327,7 +327,7 @@ void ath9k_init_wow(struct ieee80211_hw *hw)
 {
        struct ath_softc *sc = hw->priv;
 
-       if (sc->driver_data & ATH9K_PCI_WOW) {
+       if ((sc->driver_data & ATH9K_PCI_WOW) || sc->force_wow) {
                hw->wiphy->wowlan = &ath9k_wowlan_support;
                device_init_wakeup(sc->dev, 1);
        }
@@ -337,6 +337,6 @@ void ath9k_deinit_wow(struct ieee80211_hw *hw)
 {
        struct ath_softc *sc = hw->priv;
 
-       if (sc->driver_data & ATH9K_PCI_WOW)
+       if ((sc->driver_data & ATH9K_PCI_WOW) || sc->force_wow)
                device_init_wakeup(sc->dev, 0);
 }