ath10k: create debugfs interface to trigger fw crash
authorMichal Kazior <michal.kazior@tieto.com>
Mon, 22 Jul 2013 12:08:51 +0000 (14:08 +0200)
committerKalle Valo <kvalo@qca.qualcomm.com>
Tue, 30 Jul 2013 15:01:20 +0000 (18:01 +0300)
This can be useful for testing. To perform a
forced firmware crash write 'crash' to
'simulate_fw_crash' debugfs file. E.g.

  echo crash > /sys/kernel/debug/ieee80211/phy1/ath10k/simulate_fw_crash

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath10k/debug.c

index 65279f5347c8f2258900ca0e3da3ce4c55af2e23..3d65594fa098a40f638f73499d423e80d2a64a7e 100644 (file)
@@ -445,6 +445,60 @@ static const struct file_operations fops_fw_stats = {
        .llseek = default_llseek,
 };
 
+static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
+                                            char __user *user_buf,
+                                            size_t count, loff_t *ppos)
+{
+       const char buf[] = "To simulate firmware crash write the keyword"
+                          " `crash` to this file.\nThis will force firmware"
+                          " to report a crash to the host system.\n";
+       return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
+}
+
+static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
+                                             const char __user *user_buf,
+                                             size_t count, loff_t *ppos)
+{
+       struct ath10k *ar = file->private_data;
+       char buf[32] = {};
+       int ret;
+
+       mutex_lock(&ar->conf_mutex);
+
+       simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
+       if (strcmp(buf, "crash") && strcmp(buf, "crash\n")) {
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       if (ar->state != ATH10K_STATE_ON &&
+           ar->state != ATH10K_STATE_RESTARTED) {
+               ret = -ENETDOWN;
+               goto exit;
+       }
+
+       ath10k_info("simulating firmware crash\n");
+
+       ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);
+       if (ret)
+               ath10k_warn("failed to force fw hang (%d)\n", ret);
+
+       if (ret == 0)
+               ret = count;
+
+exit:
+       mutex_unlock(&ar->conf_mutex);
+       return ret;
+}
+
+static const struct file_operations fops_simulate_fw_crash = {
+       .read = ath10k_read_simulate_fw_crash,
+       .write = ath10k_write_simulate_fw_crash,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
 int ath10k_debug_create(struct ath10k *ar)
 {
        ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
@@ -461,6 +515,9 @@ int ath10k_debug_create(struct ath10k *ar)
        debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar,
                            &fops_wmi_services);
 
+       debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy,
+                           ar, &fops_simulate_fw_crash);
+
        return 0;
 }
 #endif /* CONFIG_ATH10K_DEBUGFS */