wl1251: NVS dump/load hacks
authorGrazvydas Ignotas <notasas@gmail.com>
Wed, 20 Mar 2013 23:41:09 +0000 (01:41 +0200)
committerGrazvydas Ignotas <notasas@gmail.com>
Wed, 20 Mar 2013 23:44:22 +0000 (01:44 +0200)
drivers/net/wireless/wl1251/debugfs.c
drivers/net/wireless/wl1251/main.c
drivers/net/wireless/wl1251/sdio.c
drivers/net/wireless/wl1251/wl1251.h

index 6c27400..66d75e3 100644 (file)
@@ -261,6 +261,42 @@ static const struct file_operations tx_queue_status_ops = {
        .llseek = generic_file_llseek,
 };
 
+static ssize_t dump_nvs_read(struct file *file, char __user *userbuf,
+                            size_t count, loff_t *ppos)
+{
+       struct wl1251 *wl = file->private_data;
+
+       if (wl->eeprom_dump == NULL)
+               return -EINVAL;
+
+       return simple_read_from_buffer(userbuf, count, ppos,
+               wl->eeprom_dump, 752);
+}
+
+static ssize_t dump_full_read(struct file *file, char __user *userbuf,
+                             size_t count, loff_t *ppos)
+{
+       struct wl1251 *wl = file->private_data;
+
+       if (wl->eeprom_dump == NULL)
+               return -EINVAL;
+
+       return simple_read_from_buffer(userbuf, count, ppos,
+               wl->eeprom_dump, 1024);
+}
+
+static const struct file_operations dump_nvs_ops = {
+       .read = dump_nvs_read,
+       .open = wl1251_open_file_generic,
+       .llseek = generic_file_llseek,
+};
+
+static const struct file_operations dump_full_ops = {
+       .read = dump_full_read,
+       .open = wl1251_open_file_generic,
+       .llseek = generic_file_llseek,
+};
+
 static void wl1251_debugfs_delete_files(struct wl1251 *wl)
 {
        DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow);
@@ -358,6 +394,11 @@ static void wl1251_debugfs_delete_files(struct wl1251 *wl)
        DEBUGFS_DEL(tx_queue_status);
        DEBUGFS_DEL(retry_count);
        DEBUGFS_DEL(excessive_retries);
+
+       if (wl->eeprom_dump != NULL) {
+               DEBUGFS_DEL(dump_nvs);
+               DEBUGFS_DEL(dump_full);
+       }
 }
 
 static int wl1251_debugfs_add_files(struct wl1251 *wl)
@@ -460,6 +501,12 @@ static int wl1251_debugfs_add_files(struct wl1251 *wl)
        DEBUGFS_ADD(retry_count, wl->debugfs.rootdir);
        DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir);
 
+       /* temporary (?) hack for EEPROM dumping */
+       if (wl->eeprom_dump != NULL) {
+               DEBUGFS_ADD(dump_nvs, wl->debugfs.rootdir);
+               DEBUGFS_ADD(dump_full, wl->debugfs.rootdir);
+       }
+
 out:
        if (ret < 0)
                wl1251_debugfs_delete_files(wl);
index cd487f6..0a27ae4 100644 (file)
@@ -1293,6 +1293,34 @@ static int wl1251_read_eeprom_mac(struct wl1251 *wl)
        return 0;
 }
 
+/* temporary (?) hack for EEPROM dumping
+ * (it seems this can only be done before fw is running) */
+static int wl1251_dump_eeprom(struct wl1251 *wl)
+{
+       int ret;
+
+       wl1251_set_partition(wl, 0, 0, REGISTERS_BASE, REGISTERS_DOWN_SIZE);
+
+       wl->eeprom_dump = kzalloc(1024, GFP_KERNEL);
+       if (wl->eeprom_dump == NULL) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       ret = wl1251_read_eeprom(wl, 0, wl->eeprom_dump, 1024);
+       if (ret != 0) {
+               wl1251_error("eeprom dump failed: %d", ret);
+               kfree(wl->eeprom_dump);
+               wl->eeprom_dump = NULL;
+               goto out;
+       }
+
+       wl1251_info("eeprom dumped.");
+
+out:
+       return ret;
+}
+
 static int wl1251_register_hw(struct wl1251 *wl)
 {
        int ret;
@@ -1342,6 +1370,8 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
 
        if (wl->use_eeprom)
                wl1251_read_eeprom_mac(wl);
+       if (wl->dump_eeprom)
+               wl1251_dump_eeprom(wl);
 
        ret = wl1251_register_hw(wl);
        if (ret)
@@ -1450,6 +1480,9 @@ int wl1251_free_hw(struct wl1251 *wl)
 
        ieee80211_free_hw(wl->hw);
 
+       if (wl->eeprom_dump != NULL)
+               kfree(wl->eeprom_dump);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(wl1251_free_hw);
index e2750a1..cc34bea 100644 (file)
 
 #include "wl1251.h"
 
+static bool force_nvs_file = false;
+module_param(force_nvs_file, bool, 0644);
+MODULE_PARM_DESC(force_nvs_file, "Force loading NVS data from file, "
+                                "not EEPROM. Default: n/N/0");
+static bool dump_eeprom = false;
+module_param(dump_eeprom, bool, 0644);
+MODULE_PARM_DESC(dump_eeprom, "Dump EEPROM on module load and makes it "
+                             "accessable through debugfs. Default: n/N/0");
+
 #ifndef SDIO_VENDOR_ID_TI
 #define SDIO_VENDOR_ID_TI              0x104c
 #endif
@@ -259,6 +268,10 @@ static int wl1251_sdio_probe(struct sdio_func *func,
                wl->use_eeprom = wl12xx_board_data->use_eeprom;
        }
 
+       if (force_nvs_file)
+               wl->use_eeprom = false;
+       wl->dump_eeprom = dump_eeprom;
+
        if (wl->irq) {
                irq_set_status_flags(wl->irq, IRQ_NOAUTOEN);
                ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl);
index c52136d..5c1ec78 100644 (file)
@@ -255,6 +255,9 @@ struct wl1251_debugfs {
 
        struct dentry *retry_count;
        struct dentry *excessive_retries;
+
+       struct dentry *dump_nvs;
+       struct dentry *dump_full;
 };
 
 struct wl1251_if_operations {
@@ -278,6 +281,7 @@ struct wl1251 {
        void (*set_power)(bool enable);
        int irq;
        bool use_eeprom;
+       bool dump_eeprom;
 
        spinlock_t wl_lock;
 
@@ -391,6 +395,8 @@ struct wl1251 {
 
        /* Most recently reported noise in dBm */
        s8 noise;
+
+       void *eeprom_dump;
 };
 
 int wl1251_plt_start(struct wl1251 *wl);