.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);
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)
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);
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;
if (wl->use_eeprom)
wl1251_read_eeprom_mac(wl);
+ if (wl->dump_eeprom)
+ wl1251_dump_eeprom(wl);
ret = wl1251_register_hw(wl);
if (ret)
ieee80211_free_hw(wl->hw);
+ if (wl->eeprom_dump != NULL)
+ kfree(wl->eeprom_dump);
+
return 0;
}
EXPORT_SYMBOL_GPL(wl1251_free_hw);
#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
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);
struct dentry *retry_count;
struct dentry *excessive_retries;
+
+ struct dentry *dump_nvs;
+ struct dentry *dump_full;
};
struct wl1251_if_operations {
void (*set_power)(bool enable);
int irq;
bool use_eeprom;
+ bool dump_eeprom;
spinlock_t wl_lock;
/* Most recently reported noise in dBm */
s8 noise;
+
+ void *eeprom_dump;
};
int wl1251_plt_start(struct wl1251 *wl);