Patch for the 3.10 version of the rt2800_usb driver to enable efuse write support.
This commit is contained in:
parent
f1c28ec52e
commit
df27cb7b8e
465
kernel/xxxx-rt2800_eeprom_efuse_write.diff
Normal file
465
kernel/xxxx-rt2800_eeprom_efuse_write.diff
Normal file
|
@ -0,0 +1,465 @@
|
|||
diff --git a/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800.h b/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800.h
|
||||
index 4db1088..1cdfe0c 100644
|
||||
--- a/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800.h
|
||||
+++ b/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800.h
|
||||
@@ -641,10 +641,18 @@
|
||||
#define EFUSE_CTRL 0x0580
|
||||
#define EFUSE_CTRL_ADDRESS_IN FIELD32(0x03fe0000)
|
||||
#define EFUSE_CTRL_MODE FIELD32(0x000000c0)
|
||||
+#define EFUSE_CTRL_ADDRESS_OUT FIELD32(0x0000003f)
|
||||
#define EFUSE_CTRL_KICK FIELD32(0x40000000)
|
||||
#define EFUSE_CTRL_PRESENT FIELD32(0x80000000)
|
||||
|
||||
/*
|
||||
+ * EFUSE MODE selection
|
||||
+ */
|
||||
+#define EFUSE_CTRL_MODE_READ_VIRTUAL 0
|
||||
+#define EFUSE_CTRL_MODE_READ_PHYSICAL 1
|
||||
+#define EFUSE_CTRL_MODE_WRITE_PHYSICAL 3
|
||||
+
|
||||
+/*
|
||||
* EFUSE_DATA0
|
||||
*/
|
||||
#define EFUSE_DATA0 0x0590
|
||||
diff --git a/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800lib.c b/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800lib.c
|
||||
index a658b4b..d4690fd 100644
|
||||
--- a/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800lib.c
|
||||
+++ b/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800lib.c
|
||||
@@ -4624,7 +4624,8 @@ int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_efuse_detect);
|
||||
|
||||
-static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
|
||||
+static u8 rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, u16 *eeprom,
|
||||
+ unsigned int addr, int physical)
|
||||
{
|
||||
u32 reg;
|
||||
u16 efuse_ctrl_reg;
|
||||
@@ -4632,6 +4633,7 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
|
||||
u16 efuse_data1_reg;
|
||||
u16 efuse_data2_reg;
|
||||
u16 efuse_data3_reg;
|
||||
+ u8 physaddr;
|
||||
|
||||
if (rt2x00_rt(rt2x00dev, RT3290)) {
|
||||
efuse_ctrl_reg = EFUSE_CTRL_3290;
|
||||
@@ -4649,38 +4651,195 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, ®);
|
||||
- rt2x00_set_field32(®, EFUSE_CTRL_ADDRESS_IN, i);
|
||||
- rt2x00_set_field32(®, EFUSE_CTRL_MODE, 0);
|
||||
+ rt2x00_set_field32(®, EFUSE_CTRL_ADDRESS_IN, addr);
|
||||
+ rt2x00_set_field32(®, EFUSE_CTRL_MODE,
|
||||
+ physical ? EFUSE_CTRL_MODE_READ_PHYSICAL :
|
||||
+ EFUSE_CTRL_MODE_READ_VIRTUAL);
|
||||
rt2x00_set_field32(®, EFUSE_CTRL_KICK, 1);
|
||||
rt2800_register_write_lock(rt2x00dev, efuse_ctrl_reg, reg);
|
||||
|
||||
/* Wait until the EEPROM has been loaded */
|
||||
rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, ®);
|
||||
+
|
||||
+ /* Get the physical block mapping */
|
||||
+ physaddr = rt2x00_get_field32(reg, EFUSE_CTRL_ADDRESS_OUT);
|
||||
+
|
||||
+ /* If we have no mapping for this address, don't bother reading. */
|
||||
+ if (!physical && physaddr == 0x3f) {
|
||||
+ memset(eeprom, 0xff, 16);
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
/* Apparently the data is read from end to start */
|
||||
rt2800_register_read_lock(rt2x00dev, efuse_data3_reg, ®);
|
||||
/* The returned value is in CPU order, but eeprom is le */
|
||||
- *(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg);
|
||||
+ *(u32 *)&eeprom[0] = cpu_to_le32(reg);
|
||||
rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, ®);
|
||||
- *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);
|
||||
+ *(u32 *)&eeprom[2] = cpu_to_le32(reg);
|
||||
rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, ®);
|
||||
- *(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg);
|
||||
+ *(u32 *)&eeprom[4] = cpu_to_le32(reg);
|
||||
rt2800_register_read_lock(rt2x00dev, efuse_data0_reg, ®);
|
||||
- *(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg);
|
||||
+ *(u32 *)&eeprom[6] = cpu_to_le32(reg);
|
||||
|
||||
+ done:
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
+
|
||||
+ return physaddr;
|
||||
}
|
||||
|
||||
-int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
|
||||
+int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev, u16 *eeprom,
|
||||
+ const u16 length)
|
||||
{
|
||||
unsigned int i;
|
||||
+ u8 addr;
|
||||
|
||||
- for (i = 0; i < EEPROM_SIZE / sizeof(u16); i += 8)
|
||||
- rt2800_efuse_read(rt2x00dev, i);
|
||||
+ for (i = 0; i < length / sizeof(u16); i += 8) {
|
||||
+ addr = rt2800_efuse_read(rt2x00dev, eeprom + i, i, 0);
|
||||
+ printk(KERN_INFO "efuse @ %x: physaddr %x\n", i * 2, addr);
|
||||
+ }
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse);
|
||||
|
||||
+static void rt2800_efuse_write_phys(struct rt2x00_dev *rt2x00dev, u16 *eeprom,
|
||||
+ unsigned int addr)
|
||||
+
|
||||
+{
|
||||
+ u32 reg;
|
||||
+ u16 efuse_ctrl_reg;
|
||||
+ u16 efuse_data0_reg;
|
||||
+ u16 efuse_data1_reg;
|
||||
+ u16 efuse_data2_reg;
|
||||
+ u16 efuse_data3_reg;
|
||||
+
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3290)) {
|
||||
+ efuse_ctrl_reg = EFUSE_CTRL_3290;
|
||||
+ efuse_data0_reg = EFUSE_DATA0_3290;
|
||||
+ efuse_data1_reg = EFUSE_DATA1_3290;
|
||||
+ efuse_data2_reg = EFUSE_DATA2_3290;
|
||||
+ efuse_data3_reg = EFUSE_DATA3_3290;
|
||||
+ } else {
|
||||
+ efuse_ctrl_reg = EFUSE_CTRL;
|
||||
+ efuse_data0_reg = EFUSE_DATA0;
|
||||
+ efuse_data1_reg = EFUSE_DATA1;
|
||||
+ efuse_data2_reg = EFUSE_DATA2;
|
||||
+ efuse_data3_reg = EFUSE_DATA3;
|
||||
+ }
|
||||
+ mutex_lock(&rt2x00dev->csr_mutex);
|
||||
+
|
||||
+ /* Apparently the data is written from end to start */
|
||||
+ /* And the data needs to be in CPU order (eeprom is LE) */
|
||||
+ rt2800_register_write_lock(rt2x00dev, efuse_data3_reg, le32_to_cpu(*(u32 *)&eeprom[0]));
|
||||
+ rt2800_register_write_lock(rt2x00dev, efuse_data2_reg, le32_to_cpu(*(u32 *)&eeprom[2]));
|
||||
+ rt2800_register_write_lock(rt2x00dev, efuse_data1_reg, le32_to_cpu(*(u32 *)&eeprom[4]));
|
||||
+ rt2800_register_write_lock(rt2x00dev, efuse_data0_reg, le32_to_cpu(*(u32 *)&eeprom[6]));
|
||||
+
|
||||
+ rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, ®);
|
||||
+ rt2x00_set_field32(®, EFUSE_CTRL_ADDRESS_IN, addr);
|
||||
+ rt2x00_set_field32(®, EFUSE_CTRL_MODE,
|
||||
+ EFUSE_CTRL_MODE_WRITE_PHYSICAL);
|
||||
+ rt2x00_set_field32(®, EFUSE_CTRL_KICK, 1);
|
||||
+ rt2800_register_write_lock(rt2x00dev, efuse_ctrl_reg, reg);
|
||||
+
|
||||
+ /* Wait until the EEPROM has been written */
|
||||
+ rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, ®);
|
||||
+
|
||||
+ mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
+}
|
||||
+
|
||||
+void rt2800_write_eeprom_efuse(struct rt2x00_dev *rt2x00dev, u16 *eeprom,
|
||||
+ const u16 length)
|
||||
+{
|
||||
+ unsigned int i, j;
|
||||
+ u16 startblock, endblock;
|
||||
+ u8 map[64], blocks;
|
||||
+ u8 map_update = 0;
|
||||
+
|
||||
+ endblock = 0x2fc; // based on device
|
||||
+ startblock = 0x2d0; // based on device
|
||||
+ blocks = 45; // based on device ( == startblock /16 )
|
||||
+
|
||||
+ /* Read in block map */
|
||||
+ for (i = startblock ; i < endblock ; i += 16) {
|
||||
+ u32 temp[4];
|
||||
+ rt2800_efuse_read(rt2x00dev, (u16 *)temp, i>>1, 1);
|
||||
+ for (j = 0 ; j < 4 ; j++)
|
||||
+ temp[j] = cpu_to_le32(temp[j]);
|
||||
+ memcpy(map + (i - startblock), temp, sizeof(temp));
|
||||
+ }
|
||||
+
|
||||
+ /* Figure out what's changed and write it */
|
||||
+ for (i = 0; i < length / sizeof(u16); i += 8) {
|
||||
+ u16 temp[8];
|
||||
+ u8 physblock;
|
||||
+ u8 newmap = 0;
|
||||
+
|
||||
+ physblock = rt2800_efuse_read(rt2x00dev, temp, i, 0);
|
||||
+ /* Don't bother if it's not been altered. */
|
||||
+ if (!memcmp(eeprom + i, temp, sizeof(temp)))
|
||||
+ continue;
|
||||
+
|
||||
+ printk(KERN_INFO "eFuse altered @ %02x, block 0x%02x\n",
|
||||
+ i * 2, physblock);
|
||||
+
|
||||
+ retry:
|
||||
+ /* Find a new block if necessary */
|
||||
+ if (physblock == 0x3f) {
|
||||
+ for (j = blocks - 1; j >= 0; j--)
|
||||
+ if (map[j] == 0)
|
||||
+ break;
|
||||
+ if (j < 0) {
|
||||
+ printk(KERN_WARNING "No available eFuse blocks, aborting!\n");
|
||||
+ return;
|
||||
+ }
|
||||
+ physblock = j;
|
||||
+ newmap = 1;
|
||||
+ printk(KERN_INFO "Allocating new eFuse block 0x%x\n", physblock);
|
||||
+ }
|
||||
+ /* Write updated data to eFuse */
|
||||
+ rt2800_efuse_write_phys(rt2x00dev, eeprom + i, physblock << 3);
|
||||
+
|
||||
+ /* Perform readback test to make sure it "took" */
|
||||
+ rt2800_efuse_read(rt2x00dev, temp, physblock << 3, 1);
|
||||
+ if (memcmp(eeprom + i, temp, sizeof(temp))) {
|
||||
+ printk(KERN_INFO "Block 0x%x readback failed -- marking invalid.\n", physblock);
|
||||
+ /* Invalidate existing map entry */
|
||||
+ for (j = 0; j < 8 ; j++) {
|
||||
+ if (!(map[physblock] & (1 << j))) {
|
||||
+ map[physblock] |= 1 << j;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ map_update = 1;
|
||||
+ physblock = 0x3f;
|
||||
+ goto retry;
|
||||
+ }
|
||||
+
|
||||
+ /* Update map */
|
||||
+ if (newmap) {
|
||||
+ u8 addr = i >> 3;
|
||||
+ /* Generate parity */
|
||||
+ addr |= ((~((addr & 0x01) ^ ( addr >> 1 & 0x01) ^ (addr >> 2 & 0x01) ^ (addr >> 3 & 0x01))) << 6) & 0x40;
|
||||
+ addr |= ((~( (addr >> 2 & 0x01) ^ (addr >> 3 & 0x01) ^ (addr >> 4 & 0x01) ^ ( addr >> 5 & 0x01))) << 7) & 0x80;
|
||||
+ map[physblock] = addr;
|
||||
+ map_update = 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (map_update) {
|
||||
+ /* Write updated map */
|
||||
+ for (i = startblock ; i < endblock ; i += 16) {
|
||||
+ u32 temp[4];
|
||||
+ memcpy(temp, map + (i - startblock), sizeof(temp));
|
||||
+ for (j = 0 ; j < 4 ; j++)
|
||||
+ temp[j] = le32_to_cpu(temp[j]);
|
||||
+ rt2800_efuse_write_phys(rt2x00dev, (u16 *)temp, i>>1);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(rt2800_write_eeprom_efuse);
|
||||
+
|
||||
static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
|
||||
diff --git a/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800lib.h b/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800lib.h
|
||||
index 6ec7394..0e86137 100644
|
||||
--- a/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800lib.h
|
||||
+++ b/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800lib.h
|
||||
@@ -207,7 +207,10 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev);
|
||||
void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev);
|
||||
|
||||
int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev);
|
||||
-int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev);
|
||||
+int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev, u16 *eeprom,
|
||||
+ const u16 length);
|
||||
+void rt2800_write_eeprom_efuse(struct rt2x00_dev *rt2x00dev, u16 *eeprom,
|
||||
+ const u16 length);
|
||||
|
||||
int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev);
|
||||
|
||||
diff --git a/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800pci.c b/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800pci.c
|
||||
index ded73da..7efc405 100644
|
||||
--- a/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800pci.c
|
||||
+++ b/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800pci.c
|
||||
@@ -180,7 +180,7 @@ static int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev)
|
||||
|
||||
static inline int rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
- return rt2800_read_eeprom_efuse(rt2x00dev);
|
||||
+ return rt2800_read_eeprom_efuse(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE);
|
||||
}
|
||||
#else
|
||||
static inline int rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
|
||||
diff --git a/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800usb.c b/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800usb.c
|
||||
index adcb848..3a4efff 100644
|
||||
--- a/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800usb.c
|
||||
+++ b/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2800usb.c
|
||||
@@ -732,6 +732,35 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
|
||||
rt2800_process_rxwi(entry, rxdesc);
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * EEPROM manipulation functions,
|
||||
+ */
|
||||
+static int rt2800usb_load_eeprom(struct rt2x00_dev *rt2x00dev,
|
||||
+ u16 *eeprom, const u16 length)
|
||||
+{
|
||||
+ u16 len = min_t(u16, length, EEPROM_SIZE);
|
||||
+
|
||||
+ if (rt2800_efuse_detect(rt2x00dev))
|
||||
+ rt2800_read_eeprom_efuse(rt2x00dev, eeprom, len);
|
||||
+ else
|
||||
+ rt2x00usb_eeprom_read(rt2x00dev, eeprom, len);
|
||||
+
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+static int rt2800usb_store_eeprom(struct rt2x00_dev *rt2x00dev,
|
||||
+ u16 *eeprom, const u16 length)
|
||||
+{
|
||||
+ u16 len = min_t(u16, length, EEPROM_SIZE);
|
||||
+
|
||||
+ if (rt2800_efuse_detect(rt2x00dev))
|
||||
+ rt2800_write_eeprom_efuse(rt2x00dev, eeprom, len);
|
||||
+ else
|
||||
+ rt2x00usb_eeprom_write(rt2x00dev, eeprom, len);
|
||||
+
|
||||
+ return length;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Device probe functions.
|
||||
*/
|
||||
@@ -740,7 +769,8 @@ static int rt2800usb_read_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
int retval;
|
||||
|
||||
if (rt2800_efuse_detect(rt2x00dev))
|
||||
- retval = rt2800_read_eeprom_efuse(rt2x00dev);
|
||||
+ retval = rt2800_read_eeprom_efuse(rt2x00dev, rt2x00dev->eeprom,
|
||||
+ EEPROM_SIZE);
|
||||
else
|
||||
retval = rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom,
|
||||
EEPROM_SIZE);
|
||||
@@ -848,6 +878,9 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
|
||||
.config = rt2800_config,
|
||||
.sta_add = rt2800_sta_add,
|
||||
.sta_remove = rt2800_sta_remove,
|
||||
+
|
||||
+ .eeprom_load = rt2800usb_load_eeprom,
|
||||
+ .eeprom_store = rt2800usb_store_eeprom,
|
||||
};
|
||||
|
||||
static const struct data_queue_desc rt2800usb_queue_rx = {
|
||||
diff --git a/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2x00.h b/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2x00.h
|
||||
index 086abb4..8165271 100644
|
||||
--- a/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2x00.h
|
||||
+++ b/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2x00.h
|
||||
@@ -646,6 +646,12 @@ struct rt2x00lib_ops {
|
||||
struct ieee80211_sta *sta);
|
||||
int (*sta_remove) (struct rt2x00_dev *rt2x00dev,
|
||||
int wcid);
|
||||
+
|
||||
+ /* EEPROM manipulation */
|
||||
+ int (*eeprom_load) (struct rt2x00_dev *rt2x00dev,
|
||||
+ u16 *eeprom, const u16 max_length);
|
||||
+ int (*eeprom_store) (struct rt2x00_dev *rt2x00dev,
|
||||
+ u16 *eeprom, const u16 max_length);
|
||||
};
|
||||
|
||||
/*
|
||||
diff --git a/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2x00debug.c b/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2x00debug.c
|
||||
index 3bb8caf..1b8de4b 100644
|
||||
--- a/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2x00debug.c
|
||||
+++ b/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2x00debug.c
|
||||
@@ -86,6 +86,7 @@ struct rt2x00debug_intf {
|
||||
struct dentry *csr_val_entry;
|
||||
struct dentry *eeprom_off_entry;
|
||||
struct dentry *eeprom_val_entry;
|
||||
+ struct dentry *eeprom_commit_entry;
|
||||
struct dentry *bbp_off_entry;
|
||||
struct dentry *bbp_val_entry;
|
||||
struct dentry *rf_off_entry;
|
||||
@@ -650,6 +651,44 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name,
|
||||
return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob);
|
||||
}
|
||||
|
||||
+static ssize_t rt2x00debug_eeprom_commit_write(struct file *file,
|
||||
+ const char __user *buf,
|
||||
+ size_t length,
|
||||
+ loff_t *offset)
|
||||
+{
|
||||
+ struct rt2x00debug_intf *intf = file->private_data;
|
||||
+
|
||||
+ if (intf->rt2x00dev->ops->lib->eeprom_store)
|
||||
+ intf->rt2x00dev->ops->lib->eeprom_store(intf->rt2x00dev,
|
||||
+ intf->rt2x00dev->eeprom,
|
||||
+ intf->rt2x00dev->ops->eeprom_size);
|
||||
+
|
||||
+ return length;
|
||||
+}
|
||||
+static ssize_t rt2x00debug_eeprom_commit_read(struct file *file,
|
||||
+ char __user *buf,
|
||||
+ size_t length,
|
||||
+ loff_t *offset)
|
||||
+{
|
||||
+ struct rt2x00debug_intf *intf = file->private_data;
|
||||
+
|
||||
+ if (intf->rt2x00dev->ops->lib->eeprom_load)
|
||||
+ intf->rt2x00dev->ops->lib->eeprom_load(intf->rt2x00dev,
|
||||
+ intf->rt2x00dev->eeprom,
|
||||
+ intf->rt2x00dev->ops->eeprom_size);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct file_operations rt2x00debug_fop_eeprom_commit = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .write = rt2x00debug_eeprom_commit_write,
|
||||
+ .read = rt2x00debug_eeprom_commit_read,
|
||||
+ .open = rt2x00debug_file_open,
|
||||
+ .release = rt2x00debug_file_release,
|
||||
+ .llseek = default_llseek,
|
||||
+};
|
||||
+
|
||||
void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
const struct rt2x00debug *debug = rt2x00dev->ops->debugfs;
|
||||
@@ -730,6 +769,13 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
|
||||
|
||||
#undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY
|
||||
|
||||
+ intf->eeprom_commit_entry =
|
||||
+ debugfs_create_file("eeprom_commit", S_IRUSR | S_IWUSR,
|
||||
+ intf->register_folder,
|
||||
+ intf, &rt2x00debug_fop_eeprom_commit);
|
||||
+ if (IS_ERR(intf->eeprom_commit_entry) || !intf->eeprom_commit_entry)
|
||||
+ goto exit;
|
||||
+
|
||||
intf->queue_folder =
|
||||
debugfs_create_dir("queue", intf->driver_folder);
|
||||
if (IS_ERR(intf->queue_folder) || !intf->queue_folder)
|
||||
@@ -786,6 +832,7 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
|
||||
debugfs_remove(intf->bbp_off_entry);
|
||||
debugfs_remove(intf->eeprom_val_entry);
|
||||
debugfs_remove(intf->eeprom_off_entry);
|
||||
+ debugfs_remove(intf->eeprom_commit_entry);
|
||||
debugfs_remove(intf->csr_val_entry);
|
||||
debugfs_remove(intf->csr_off_entry);
|
||||
debugfs_remove(intf->register_folder);
|
||||
diff --git a/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2x00usb.h b/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2x00usb.h
|
||||
index 323ca7b..f8ed3de 100644
|
||||
--- a/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2x00usb.h
|
||||
+++ b/packages/foss/compat-drivers/drivers/net/wireless/rt2x00/rt2x00usb.h
|
||||
@@ -203,6 +203,25 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev,
|
||||
}
|
||||
|
||||
/**
|
||||
+ * rt2x00usb_eeprom_write - Write eeprom to device
|
||||
+ * @rt2x00dev: Pointer to &struct rt2x00_dev
|
||||
+ * @eeprom: Pointer to eeprom array to copy the information from
|
||||
+ * @length: Number of bytes to write to the eeprom
|
||||
+ *
|
||||
+ * Simple wrapper around rt2x00usb_vendor_request to write the eeprom
|
||||
+ * to the device. Note that the eeprom argument _must_ be allocated using
|
||||
+ * kmalloc for correct handling inside the kernel USB layer.
|
||||
+ */
|
||||
+static inline int rt2x00usb_eeprom_write(struct rt2x00_dev *rt2x00dev,
|
||||
+ __le16 *eeprom, const u16 length)
|
||||
+{
|
||||
+ return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_WRITE,
|
||||
+ USB_VENDOR_REQUEST_OUT, 0, 0,
|
||||
+ eeprom, length,
|
||||
+ REGISTER_TIMEOUT16(length));
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
* rt2x00usb_register_read - Read 32bit register word
|
||||
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
|
||||
* @offset: Register offset
|
Loading…
Reference in a new issue