* [PATCH 0/8] wl12xx: some fixes and improvements for PLT mode
@ 2012-01-24 9:06 Luciano Coelho
2012-01-24 9:06 ` [PATCH 1/8] wl12xx: Acquire lock before stopping plt Luciano Coelho
` (8 more replies)
0 siblings, 9 replies; 10+ messages in thread
From: Luciano Coelho @ 2012-01-24 9:06 UTC (permalink / raw)
To: linux-wireless; +Cc: coelho
Hi,
This patchset fixes some bugs in PLT mode and adds support for 2 MAC
addresses based on the NVS file or in the device's fuse ROM.
This two patches I sent as part of the "wl12xx: read MAC from fuse
rom" series are superseded by this set.
Cheers,
Luca.
Ido Yariv (3):
wl12xx: Acquire lock before stopping plt
wl12xx: Power off after flushing work
wl12xx: Fix potential interrupt storm
Luciano Coelho (5):
wl12xx: cancel delayed elp work and clear flags when stopping PLT
wl12xx: move partition table definition to io.c
wl12xx: read chip ID and HW PG version during probe
wl12xx: use two MAC addresses based on the NVS or from fuse ROM
wl12xx: add testmode operation to read the BD_ADDR from Fuse ROM
drivers/net/wireless/wl12xx/boot.c | 102 ++-------------
drivers/net/wireless/wl12xx/boot.h | 10 --
drivers/net/wireless/wl12xx/debug.h | 1 +
drivers/net/wireless/wl12xx/io.c | 59 +++++++++
drivers/net/wireless/wl12xx/io.h | 2 +
drivers/net/wireless/wl12xx/main.c | 216 ++++++++++++++++++++++++++------
drivers/net/wireless/wl12xx/reg.h | 27 ++++
drivers/net/wireless/wl12xx/testmode.c | 50 ++++++++
drivers/net/wireless/wl12xx/wl12xx.h | 7 +-
9 files changed, 335 insertions(+), 139 deletions(-)
--
1.7.4.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/8] wl12xx: Acquire lock before stopping plt
2012-01-24 9:06 [PATCH 0/8] wl12xx: some fixes and improvements for PLT mode Luciano Coelho
@ 2012-01-24 9:06 ` Luciano Coelho
2012-01-24 9:06 ` [PATCH 2/8] wl12xx: Power off after flushing work Luciano Coelho
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Luciano Coelho @ 2012-01-24 9:06 UTC (permalink / raw)
To: linux-wireless; +Cc: coelho, Ido Yariv
From: Ido Yariv <ido@wizery.com>
__wl1271_plt_stop is called from both wl1271_plt_stop and
wl1271_unregister_hw. While wl1271_plt_stop acquires a mutex,
wl1271_unregister_hw does not.
Fix this by calling wl1271_plt_stop instead of __wl1271_plt_stop from
wl1271_unregister_hw.
Signed-off-by: Ido Yariv <ido@wizery.com>
---
drivers/net/wireless/wl12xx/main.c | 18 +++++-------------
1 files changed, 5 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 915d56c..fc4d4d5 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1391,13 +1391,15 @@ out:
return ret;
}
-static int __wl1271_plt_stop(struct wl1271 *wl)
+int wl1271_plt_stop(struct wl1271 *wl)
{
int ret = 0;
wl1271_notice("power down");
+ mutex_lock(&wl->mutex);
if (wl->state != WL1271_STATE_PLT) {
+ mutex_unlock(&wl->mutex);
wl1271_error("cannot power down because not in PLT "
"state: %d", wl->state);
ret = -EBUSY;
@@ -1410,25 +1412,15 @@ static int __wl1271_plt_stop(struct wl1271 *wl)
wl->rx_counter = 0;
mutex_unlock(&wl->mutex);
+
wl1271_disable_interrupts(wl);
wl1271_flush_deferred_work(wl);
cancel_work_sync(&wl->netstack_work);
cancel_work_sync(&wl->recovery_work);
- mutex_lock(&wl->mutex);
out:
return ret;
}
-int wl1271_plt_stop(struct wl1271 *wl)
-{
- int ret;
-
- mutex_lock(&wl->mutex);
- ret = __wl1271_plt_stop(wl);
- mutex_unlock(&wl->mutex);
- return ret;
-}
-
static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct wl1271 *wl = hw->priv;
@@ -4878,7 +4870,7 @@ static int wl1271_register_hw(struct wl1271 *wl)
static void wl1271_unregister_hw(struct wl1271 *wl)
{
if (wl->state == WL1271_STATE_PLT)
- __wl1271_plt_stop(wl);
+ wl1271_plt_stop(wl);
unregister_netdevice_notifier(&wl1271_dev_notifier);
ieee80211_unregister_hw(wl->hw);
--
1.7.4.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/8] wl12xx: Power off after flushing work
2012-01-24 9:06 [PATCH 0/8] wl12xx: some fixes and improvements for PLT mode Luciano Coelho
2012-01-24 9:06 ` [PATCH 1/8] wl12xx: Acquire lock before stopping plt Luciano Coelho
@ 2012-01-24 9:06 ` Luciano Coelho
2012-01-24 9:06 ` [PATCH 3/8] wl12xx: Fix potential interrupt storm Luciano Coelho
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Luciano Coelho @ 2012-01-24 9:06 UTC (permalink / raw)
To: linux-wireless; +Cc: coelho, Ido Yariv
From: Ido Yariv <ido@wizery.com>
When stopping plt, the chip is powered off before all current work items
are flushed and interrupts are disabled. This might introduce a race in
which the driver tries to communicate with a powered off chip.
Fix this by powering off the device only after interrupts are disabled
and all work items are flushed.
Signed-off-by: Ido Yariv <ido@wizery.com>
---
drivers/net/wireless/wl12xx/main.c | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index fc4d4d5..bf356a8 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1406,8 +1406,6 @@ int wl1271_plt_stop(struct wl1271 *wl)
goto out;
}
- wl1271_power_off(wl);
-
wl->state = WL1271_STATE_OFF;
wl->rx_counter = 0;
@@ -1417,6 +1415,11 @@ int wl1271_plt_stop(struct wl1271 *wl)
wl1271_flush_deferred_work(wl);
cancel_work_sync(&wl->netstack_work);
cancel_work_sync(&wl->recovery_work);
+
+ mutex_lock(&wl->mutex);
+ wl1271_power_off(wl);
+ mutex_unlock(&wl->mutex);
+
out:
return ret;
}
--
1.7.4.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/8] wl12xx: Fix potential interrupt storm
2012-01-24 9:06 [PATCH 0/8] wl12xx: some fixes and improvements for PLT mode Luciano Coelho
2012-01-24 9:06 ` [PATCH 1/8] wl12xx: Acquire lock before stopping plt Luciano Coelho
2012-01-24 9:06 ` [PATCH 2/8] wl12xx: Power off after flushing work Luciano Coelho
@ 2012-01-24 9:06 ` Luciano Coelho
2012-01-24 9:06 ` [PATCH 4/8] wl12xx: cancel delayed elp work and clear flags when stopping PLT Luciano Coelho
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Luciano Coelho @ 2012-01-24 9:06 UTC (permalink / raw)
To: linux-wireless; +Cc: coelho, Ido Yariv
From: Ido Yariv <ido@wizery.com>
The interrupt threaded handler exits immediately if the driver's state
is WL1271_STATE_OFF. As a result, the interrupt status is not read. If
the interrupt is level triggered, it will be fired again.
Fix this by disabling interrupts before setting the state to OFF.
Signed-off-by: Ido Yariv <ido@wizery.com>
---
drivers/net/wireless/wl12xx/main.c | 30 ++++++++++++++++++++++++++++--
1 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index bf356a8..27ca324 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1397,9 +1397,23 @@ int wl1271_plt_stop(struct wl1271 *wl)
wl1271_notice("power down");
+ /*
+ * Interrupts must be disabled before setting the state to OFF.
+ * Otherwise, the interrupt handler might be called and exit without
+ * reading the interrupt status.
+ */
+ wl1271_disable_interrupts(wl);
mutex_lock(&wl->mutex);
if (wl->state != WL1271_STATE_PLT) {
mutex_unlock(&wl->mutex);
+
+ /*
+ * This will not necessarily enable interrupts as interrupts
+ * may have been disabled when op_stop was called. It will,
+ * however, balance the above call to disable_interrupts().
+ */
+ wl1271_enable_interrupts(wl);
+
wl1271_error("cannot power down because not in PLT "
"state: %d", wl->state);
ret = -EBUSY;
@@ -1411,7 +1425,6 @@ int wl1271_plt_stop(struct wl1271 *wl)
mutex_unlock(&wl->mutex);
- wl1271_disable_interrupts(wl);
wl1271_flush_deferred_work(wl);
cancel_work_sync(&wl->netstack_work);
cancel_work_sync(&wl->recovery_work);
@@ -1773,11 +1786,25 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
+ /*
+ * Interrupts must be disabled before setting the state to OFF.
+ * Otherwise, the interrupt handler might be called and exit without
+ * reading the interrupt status.
+ */
+ wl1271_disable_interrupts(wl);
mutex_lock(&wl->mutex);
if (wl->state == WL1271_STATE_OFF) {
mutex_unlock(&wl->mutex);
+
+ /*
+ * This will not necessarily enable interrupts as interrupts
+ * may have been disabled when op_stop was called. It will,
+ * however, balance the above call to disable_interrupts().
+ */
+ wl1271_enable_interrupts(wl);
return;
}
+
/*
* this must be before the cancel_work calls below, so that the work
* functions don't perform further work.
@@ -1789,7 +1816,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
list_del(&wl->list);
mutex_unlock(&wl_list_mutex);
- wl1271_disable_interrupts(wl);
wl1271_flush_deferred_work(wl);
cancel_delayed_work_sync(&wl->scan_complete_work);
cancel_work_sync(&wl->netstack_work);
--
1.7.4.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/8] wl12xx: cancel delayed elp work and clear flags when stopping PLT
2012-01-24 9:06 [PATCH 0/8] wl12xx: some fixes and improvements for PLT mode Luciano Coelho
` (2 preceding siblings ...)
2012-01-24 9:06 ` [PATCH 3/8] wl12xx: Fix potential interrupt storm Luciano Coelho
@ 2012-01-24 9:06 ` Luciano Coelho
2012-01-24 9:06 ` [PATCH 5/8] wl12xx: move partition table definition to io.c Luciano Coelho
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Luciano Coelho @ 2012-01-24 9:06 UTC (permalink / raw)
To: linux-wireless; +Cc: coelho
In some cases a race condition can happen if we don't cancel any
pending ELP work before stopping PLT. With this commit we cancel ELP
work and clear the wl->flags bitmask. Also clean up the wl elements
after powering off.
Signed-off-by: Luciano Coelho <coelho@ti.com>
---
drivers/net/wireless/wl12xx/main.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 27ca324..6ec22b3 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1420,17 +1420,18 @@ int wl1271_plt_stop(struct wl1271 *wl)
goto out;
}
- wl->state = WL1271_STATE_OFF;
- wl->rx_counter = 0;
-
mutex_unlock(&wl->mutex);
wl1271_flush_deferred_work(wl);
cancel_work_sync(&wl->netstack_work);
cancel_work_sync(&wl->recovery_work);
+ cancel_delayed_work_sync(&wl->elp_work);
mutex_lock(&wl->mutex);
wl1271_power_off(wl);
+ wl->flags = 0;
+ wl->state = WL1271_STATE_OFF;
+ wl->rx_counter = 0;
mutex_unlock(&wl->mutex);
out:
--
1.7.4.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 5/8] wl12xx: move partition table definition to io.c
2012-01-24 9:06 [PATCH 0/8] wl12xx: some fixes and improvements for PLT mode Luciano Coelho
` (3 preceding siblings ...)
2012-01-24 9:06 ` [PATCH 4/8] wl12xx: cancel delayed elp work and clear flags when stopping PLT Luciano Coelho
@ 2012-01-24 9:06 ` Luciano Coelho
2012-01-24 9:06 ` [PATCH 6/8] wl12xx: read chip ID and HW PG version during probe Luciano Coelho
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Luciano Coelho @ 2012-01-24 9:06 UTC (permalink / raw)
To: linux-wireless; +Cc: coelho
Up till now we only needed to access the partition table in boot.c.
But to add support for reading the MAC address from the FUSE in
testmode, we will have to change the partition in testmode.c.
Thus, we move the partition table to io.c and export it via io.h. It
makes more sense to have it in the io part anyway.
Signed-off-by: Luciano Coelho <coelho@ti.com>
---
drivers/net/wireless/wl12xx/boot.c | 73 +++--------------------------------
drivers/net/wireless/wl12xx/io.c | 59 +++++++++++++++++++++++++++++
drivers/net/wireless/wl12xx/io.h | 2 +
3 files changed, 68 insertions(+), 66 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index 8f9cf5a..84d2951 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -33,65 +33,6 @@
#include "event.h"
#include "rx.h"
-static struct wl1271_partition_set part_table[PART_TABLE_LEN] = {
- [PART_DOWN] = {
- .mem = {
- .start = 0x00000000,
- .size = 0x000177c0
- },
- .reg = {
- .start = REGISTERS_BASE,
- .size = 0x00008800
- },
- .mem2 = {
- .start = 0x00000000,
- .size = 0x00000000
- },
- .mem3 = {
- .start = 0x00000000,
- .size = 0x00000000
- },
- },
-
- [PART_WORK] = {
- .mem = {
- .start = 0x00040000,
- .size = 0x00014fc0
- },
- .reg = {
- .start = REGISTERS_BASE,
- .size = 0x0000a000
- },
- .mem2 = {
- .start = 0x003004f8,
- .size = 0x00000004
- },
- .mem3 = {
- .start = 0x00040404,
- .size = 0x00000000
- },
- },
-
- [PART_DRPW] = {
- .mem = {
- .start = 0x00040000,
- .size = 0x00014fc0
- },
- .reg = {
- .start = DRPW_BASE,
- .size = 0x00006000
- },
- .mem2 = {
- .start = 0x00000000,
- .size = 0x00000000
- },
- .mem3 = {
- .start = 0x00000000,
- .size = 0x00000000
- }
- }
-};
-
static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
{
u32 cpu_ctrl;
@@ -181,13 +122,13 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
return -ENOMEM;
}
- memcpy(&partition, &part_table[PART_DOWN], sizeof(partition));
+ memcpy(&partition, &wl12xx_part_table[PART_DOWN], sizeof(partition));
partition.mem.start = dest;
wl1271_set_partition(wl, &partition);
/* 10.1 set partition limit and chunk num */
chunk_num = 0;
- partition_limit = part_table[PART_DOWN].mem.size;
+ partition_limit = wl12xx_part_table[PART_DOWN].mem.size;
while (chunk_num < fw_data_len / CHUNK_SIZE) {
/* 10.2 update partition, if needed */
@@ -195,7 +136,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
if (addr > partition_limit) {
addr = dest + chunk_num * CHUNK_SIZE;
partition_limit = chunk_num * CHUNK_SIZE +
- part_table[PART_DOWN].mem.size;
+ wl12xx_part_table[PART_DOWN].mem.size;
partition.mem.start = addr;
wl1271_set_partition(wl, &partition);
}
@@ -383,7 +324,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
nvs_len -= nvs_ptr - (u8 *)wl->nvs;
/* Now we must set the partition correctly */
- wl1271_set_partition(wl, &part_table[PART_WORK]);
+ wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]);
/* Copy the NVS tables to a new block to ensure alignment */
nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
@@ -492,7 +433,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
wl->event_box_addr = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR);
/* set the working partition to its "running" mode offset */
- wl1271_set_partition(wl, &part_table[PART_WORK]);
+ wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]);
wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x",
wl->cmd_box_addr, wl->event_box_addr);
@@ -769,7 +710,7 @@ int wl1271_load_firmware(struct wl1271 *wl)
wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
udelay(500);
- wl1271_set_partition(wl, &part_table[PART_DRPW]);
+ wl1271_set_partition(wl, &wl12xx_part_table[PART_DRPW]);
/* Read-modify-write DRPW_SCRATCH_START register (see next state)
to be used by DRPw FW. The RTRIM value will be added by the FW
@@ -788,7 +729,7 @@ int wl1271_load_firmware(struct wl1271 *wl)
wl1271_write32(wl, DRPW_SCRATCH_START, clk);
- wl1271_set_partition(wl, &part_table[PART_WORK]);
+ wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]);
/* Disable interrupts */
wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
diff --git a/drivers/net/wireless/wl12xx/io.c b/drivers/net/wireless/wl12xx/io.c
index 079ad38..c574a3b 100644
--- a/drivers/net/wireless/wl12xx/io.c
+++ b/drivers/net/wireless/wl12xx/io.c
@@ -45,6 +45,65 @@
#define OCP_STATUS_REQ_FAILED 0x20000
#define OCP_STATUS_RESP_ERROR 0x30000
+struct wl1271_partition_set wl12xx_part_table[PART_TABLE_LEN] = {
+ [PART_DOWN] = {
+ .mem = {
+ .start = 0x00000000,
+ .size = 0x000177c0
+ },
+ .reg = {
+ .start = REGISTERS_BASE,
+ .size = 0x00008800
+ },
+ .mem2 = {
+ .start = 0x00000000,
+ .size = 0x00000000
+ },
+ .mem3 = {
+ .start = 0x00000000,
+ .size = 0x00000000
+ },
+ },
+
+ [PART_WORK] = {
+ .mem = {
+ .start = 0x00040000,
+ .size = 0x00014fc0
+ },
+ .reg = {
+ .start = REGISTERS_BASE,
+ .size = 0x0000a000
+ },
+ .mem2 = {
+ .start = 0x003004f8,
+ .size = 0x00000004
+ },
+ .mem3 = {
+ .start = 0x00040404,
+ .size = 0x00000000
+ },
+ },
+
+ [PART_DRPW] = {
+ .mem = {
+ .start = 0x00040000,
+ .size = 0x00014fc0
+ },
+ .reg = {
+ .start = DRPW_BASE,
+ .size = 0x00006000
+ },
+ .mem2 = {
+ .start = 0x00000000,
+ .size = 0x00000000
+ },
+ .mem3 = {
+ .start = 0x00000000,
+ .size = 0x00000000
+ }
+ }
+};
+
bool wl1271_set_block_size(struct wl1271 *wl)
{
if (wl->if_ops->set_block_size) {
diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h
index d398cbc..4fb3dab 100644
--- a/drivers/net/wireless/wl12xx/io.h
+++ b/drivers/net/wireless/wl12xx/io.h
@@ -43,6 +43,8 @@
#define HW_ACCESS_PRAM_MAX_RANGE 0x3c000
+extern struct wl1271_partition_set wl12xx_part_table[PART_TABLE_LEN];
+
struct wl1271;
void wl1271_disable_interrupts(struct wl1271 *wl);
--
1.7.4.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 6/8] wl12xx: read chip ID and HW PG version during probe
2012-01-24 9:06 [PATCH 0/8] wl12xx: some fixes and improvements for PLT mode Luciano Coelho
` (4 preceding siblings ...)
2012-01-24 9:06 ` [PATCH 5/8] wl12xx: move partition table definition to io.c Luciano Coelho
@ 2012-01-24 9:06 ` Luciano Coelho
2012-01-24 9:06 ` [PATCH 7/8] wl12xx: use two MAC addresses based on the NVS or from fuse ROM Luciano Coelho
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Luciano Coelho @ 2012-01-24 9:06 UTC (permalink / raw)
To: linux-wireless; +Cc: coelho
In order to read the MAC addresses from the fuse ROM, we need to know
the chip ID and the HW PG version. We need to know the MAC address
during probe, because that's when we register our HW with mac80211.
To prepare for that, this patch reads the chip ID and HW PG version
during probe instead of doing it at boot time. We power the chip on
briefly in order to do that.
Signed-off-by: Luciano Coelho <coelho@ti.com>
---
drivers/net/wireless/wl12xx/boot.c | 15 ---------
drivers/net/wireless/wl12xx/debug.h | 1 +
drivers/net/wireless/wl12xx/main.c | 59 ++++++++++++++++++++++++++--------
3 files changed, 46 insertions(+), 29 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index 84d2951..599919e 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -488,19 +488,6 @@ static int wl1271_boot_write_irq_polarity(struct wl1271 *wl)
return 0;
}
-static void wl1271_boot_hw_version(struct wl1271 *wl)
-{
- u32 fuse;
-
- if (wl->chip.id == CHIP_ID_1283_PG20)
- fuse = wl1271_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1);
- else
- fuse = wl1271_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1);
- fuse = (fuse & PG_VER_MASK) >> PG_VER_OFFSET;
-
- wl->hw_pg_ver = (s8)fuse;
-}
-
static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
{
u16 spare_reg;
@@ -694,8 +681,6 @@ int wl1271_load_firmware(struct wl1271 *wl)
u32 tmp, clk;
int selected_clock = -1;
- wl1271_boot_hw_version(wl);
-
if (wl->chip.id == CHIP_ID_1283_PG20) {
ret = wl128x_boot_clk(wl, &selected_clock);
if (ret < 0)
diff --git a/drivers/net/wireless/wl12xx/debug.h b/drivers/net/wireless/wl12xx/debug.h
index b85fd8c4..ec0fdc2 100644
--- a/drivers/net/wireless/wl12xx/debug.h
+++ b/drivers/net/wireless/wl12xx/debug.h
@@ -51,6 +51,7 @@ enum {
DEBUG_FILTERS = BIT(15),
DEBUG_ADHOC = BIT(16),
DEBUG_AP = BIT(17),
+ DEBUG_PROBE = BIT(18),
DEBUG_MASTER = (DEBUG_ADHOC | DEBUG_AP),
DEBUG_ALL = ~0,
};
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 6ec22b3..315ffec 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1232,10 +1232,9 @@ static int wl1271_setup(struct wl1271 *wl)
return 0;
}
-static int wl1271_chip_wakeup(struct wl1271 *wl)
+static int wl12xx_set_power_on(struct wl1271 *wl)
{
- struct wl1271_partition_set partition;
- int ret = 0;
+ int ret;
msleep(WL1271_PRE_POWER_ON_SLEEP);
ret = wl1271_power_on(wl);
@@ -1245,20 +1244,22 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
wl1271_io_reset(wl);
wl1271_io_init(wl);
- /* We don't need a real memory partition here, because we only want
- * to use the registers at this point. */
- memset(&partition, 0, sizeof(partition));
- partition.reg.start = REGISTERS_BASE;
- partition.reg.size = REGISTERS_DOWN_SIZE;
- wl1271_set_partition(wl, &partition);
+ wl1271_set_partition(wl, &wl12xx_part_table[PART_DOWN]);
/* ELP module wake up */
wl1271_fw_wakeup(wl);
- /* whal_FwCtrl_BootSm() */
+out:
+ return ret;
+}
- /* 0. read chip id from CHIP_ID */
- wl->chip.id = wl1271_read32(wl, CHIP_ID_B);
+static int wl1271_chip_wakeup(struct wl1271 *wl)
+{
+ int ret = 0;
+
+ ret = wl12xx_set_power_on(wl);
+ if (ret < 0)
+ goto out;
/*
* For wl127x based devices we could use the default block
@@ -4855,6 +4856,29 @@ static struct bin_attribute fwlog_attr = {
.read = wl1271_sysfs_read_fwlog,
};
+static int wl12xx_get_hw_info(struct wl1271 *wl)
+{
+ int ret;
+ u32 die_info;
+
+ ret = wl12xx_set_power_on(wl);
+ if (ret < 0)
+ goto out;
+
+ wl->chip.id = wl1271_read32(wl, CHIP_ID_B);
+
+ if (wl->chip.id == CHIP_ID_1283_PG20)
+ die_info = wl1271_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1);
+ else
+ die_info = wl1271_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1);
+
+ wl->hw_pg_ver = (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET;
+
+ wl1271_power_off(wl);
+out:
+ return ret;
+}
+
static int wl1271_register_hw(struct wl1271 *wl)
{
int ret;
@@ -4862,6 +4886,12 @@ static int wl1271_register_hw(struct wl1271 *wl)
if (wl->mac80211_registered)
return 0;
+ ret = wl12xx_get_hw_info(wl);
+ if (ret < 0) {
+ wl1271_error("couldn't get hw info");
+ goto out;
+ }
+
ret = wl1271_fetch_nvs(wl);
if (ret == 0) {
/* NOTE: The wl->nvs->nvs element must be first, in
@@ -4883,7 +4913,7 @@ static int wl1271_register_hw(struct wl1271 *wl)
ret = ieee80211_register_hw(wl->hw);
if (ret < 0) {
wl1271_error("unable to register mac80211 hw: %d", ret);
- return ret;
+ goto out;
}
wl->mac80211_registered = true;
@@ -4894,7 +4924,8 @@ static int wl1271_register_hw(struct wl1271 *wl)
wl1271_notice("loaded");
- return 0;
+out:
+ return ret;
}
static void wl1271_unregister_hw(struct wl1271 *wl)
--
1.7.4.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 7/8] wl12xx: use two MAC addresses based on the NVS or from fuse ROM
2012-01-24 9:06 [PATCH 0/8] wl12xx: some fixes and improvements for PLT mode Luciano Coelho
` (5 preceding siblings ...)
2012-01-24 9:06 ` [PATCH 6/8] wl12xx: read chip ID and HW PG version during probe Luciano Coelho
@ 2012-01-24 9:06 ` Luciano Coelho
2012-01-24 9:06 ` [PATCH 8/8] wl12xx: add testmode operation to read the BD_ADDR from Fuse ROM Luciano Coelho
2012-02-15 10:12 ` [PATCH 0/8] wl12xx: some fixes and improvements for PLT mode Luciano Coelho
8 siblings, 0 replies; 10+ messages in thread
From: Luciano Coelho @ 2012-01-24 9:06 UTC (permalink / raw)
To: linux-wireless; +Cc: coelho, Arik Nemtsov, Igal Chernobelsky
Add support for two MAC addresses. If the NVS has a valid MAC
address, that takes precedence and we use two sequential address
starting from the one specified.
If the NVS doesn't contain a valid MAC address (ie. if it is set to
00:00:00:00:00:00), we check if the HW PG version in use has the
BD_ADDR written in the fuse ROM. If it does, we read it and derive
the two subsequent addresses for WLAN.
During production, 3 addresses are reserved per device. The first for
Bluetooth (burnt in the fuse ROM) and the following two for WLAN.
This patch has some code by Igal and Arik (squashed from internal
patches).
Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Igal Chernobelsky <igalc@ti.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
---
drivers/net/wireless/wl12xx/boot.c | 14 +++---
drivers/net/wireless/wl12xx/boot.h | 10 ----
drivers/net/wireless/wl12xx/main.c | 99 +++++++++++++++++++++++++++++++---
drivers/net/wireless/wl12xx/reg.h | 27 +++++++++
drivers/net/wireless/wl12xx/wl12xx.h | 7 ++-
5 files changed, 131 insertions(+), 26 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index 599919e..32a7f9b 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -258,12 +258,12 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
}
/* update current MAC address to NVS */
- nvs_ptr[11] = wl->mac_addr[0];
- nvs_ptr[10] = wl->mac_addr[1];
- nvs_ptr[6] = wl->mac_addr[2];
- nvs_ptr[5] = wl->mac_addr[3];
- nvs_ptr[4] = wl->mac_addr[4];
- nvs_ptr[3] = wl->mac_addr[5];
+ nvs_ptr[11] = wl->addresses[0].addr[0];
+ nvs_ptr[10] = wl->addresses[0].addr[1];
+ nvs_ptr[6] = wl->addresses[0].addr[2];
+ nvs_ptr[5] = wl->addresses[0].addr[3];
+ nvs_ptr[4] = wl->addresses[0].addr[4];
+ nvs_ptr[3] = wl->addresses[0].addr[5];
/*
* Layout before the actual NVS tables:
@@ -626,7 +626,7 @@ static int wl127x_boot_clk(struct wl1271 *wl)
u32 pause;
u32 clk;
- if (((wl->hw_pg_ver & PG_MAJOR_VER_MASK) >> PG_MAJOR_VER_OFFSET) < 3)
+ if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3)
wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
if (wl->ref_clock == CONF_REF_CLK_19_2_E ||
diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/boot.h
index 06dad93..c3adc09 100644
--- a/drivers/net/wireless/wl12xx/boot.h
+++ b/drivers/net/wireless/wl12xx/boot.h
@@ -55,16 +55,6 @@ struct wl1271_static_data {
#define OCP_REG_CLK_POLARITY 0x0cb2
#define OCP_REG_CLK_PULL 0x0cb4
-#define WL127X_REG_FUSE_DATA_2_1 0x050a
-#define WL128X_REG_FUSE_DATA_2_1 0x2152
-#define PG_VER_MASK 0x3c
-#define PG_VER_OFFSET 2
-
-#define PG_MAJOR_VER_MASK 0x3
-#define PG_MAJOR_VER_OFFSET 0x0
-#define PG_MINOR_VER_MASK 0xc
-#define PG_MINOR_VER_OFFSET 0x2
-
#define CMD_MBOX_ADDRESS 0x407B4
#define POLARITY_LOW BIT(1)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 315ffec..b9c70c6 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -2129,7 +2129,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
* we still need this in order to configure the fw
* while uploading the nvs
*/
- memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
+ memcpy(wl->addresses[0].addr, vif->addr, ETH_ALEN);
booted = wl12xx_init_fw(wl);
if (!booted) {
@@ -4856,6 +4856,76 @@ static struct bin_attribute fwlog_attr = {
.read = wl1271_sysfs_read_fwlog,
};
+static bool wl12xx_mac_in_fuse(struct wl1271 *wl)
+{
+ bool supported = false;
+ u8 major, minor;
+
+ if (wl->chip.id == CHIP_ID_1283_PG20) {
+ major = WL128X_PG_GET_MAJOR(wl->hw_pg_ver);
+ minor = WL128X_PG_GET_MINOR(wl->hw_pg_ver);
+
+ /* in wl128x we have the MAC address if the PG is >= (2, 1) */
+ if (major > 2 || (major == 2 && minor >= 1))
+ supported = true;
+ } else {
+ major = WL127X_PG_GET_MAJOR(wl->hw_pg_ver);
+ minor = WL127X_PG_GET_MINOR(wl->hw_pg_ver);
+
+ /* in wl127x we have the MAC address if the PG is >= (3, 1) */
+ if (major == 3 && minor >= 1)
+ supported = true;
+ }
+
+ wl1271_debug(DEBUG_PROBE,
+ "PG Ver major = %d minor = %d, MAC %s present",
+ major, minor, supported ? "is" : "is not");
+
+ return supported;
+}
+
+static void wl12xx_derive_mac_addresses(struct wl1271 *wl,
+ u32 oui, u32 nic, int n)
+{
+ int i;
+
+ wl1271_debug(DEBUG_PROBE, "base address: oui %06x nic %06x, n %d",
+ oui, nic, n);
+
+ if (nic + n - 1 > 0xffffff)
+ wl1271_warning("NIC part of the MAC address wraps around!");
+
+ for (i = 0; i < n; i++) {
+ wl->addresses[i].addr[0] = (u8)(oui >> 16);
+ wl->addresses[i].addr[1] = (u8)(oui >> 8);
+ wl->addresses[i].addr[2] = (u8) oui;
+ wl->addresses[i].addr[3] = (u8)(nic >> 16);
+ wl->addresses[i].addr[4] = (u8)(nic >> 8);
+ wl->addresses[i].addr[5] = (u8) nic;
+ nic++;
+ }
+
+ wl->hw->wiphy->n_addresses = n;
+ wl->hw->wiphy->addresses = wl->addresses;
+}
+
+static void wl12xx_get_fuse_mac(struct wl1271 *wl)
+{
+ u32 mac1, mac2;
+
+ wl1271_set_partition(wl, &wl12xx_part_table[PART_DRPW]);
+
+ mac1 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1);
+ mac2 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2);
+
+ /* these are the two parts of the BD_ADDR */
+ wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) +
+ ((mac1 & 0xff000000) >> 24);
+ wl->fuse_nic_addr = mac1 & 0xffffff;
+
+ wl1271_set_partition(wl, &wl12xx_part_table[PART_DOWN]);
+}
+
static int wl12xx_get_hw_info(struct wl1271 *wl)
{
int ret;
@@ -4874,6 +4944,13 @@ static int wl12xx_get_hw_info(struct wl1271 *wl)
wl->hw_pg_ver = (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET;
+ if (!wl12xx_mac_in_fuse(wl)) {
+ wl->fuse_oui_addr = 0;
+ wl->fuse_nic_addr = 0;
+ } else {
+ wl12xx_get_fuse_mac(wl);
+ }
+
wl1271_power_off(wl);
out:
return ret;
@@ -4882,6 +4959,7 @@ out:
static int wl1271_register_hw(struct wl1271 *wl)
{
int ret;
+ u32 oui_addr = 0, nic_addr = 0;
if (wl->mac80211_registered)
return 0;
@@ -4900,15 +4978,20 @@ static int wl1271_register_hw(struct wl1271 *wl)
*/
u8 *nvs_ptr = (u8 *)wl->nvs;
- wl->mac_addr[0] = nvs_ptr[11];
- wl->mac_addr[1] = nvs_ptr[10];
- wl->mac_addr[2] = nvs_ptr[6];
- wl->mac_addr[3] = nvs_ptr[5];
- wl->mac_addr[4] = nvs_ptr[4];
- wl->mac_addr[5] = nvs_ptr[3];
+ oui_addr =
+ (nvs_ptr[11] << 16) + (nvs_ptr[10] << 8) + nvs_ptr[6];
+ nic_addr =
+ (nvs_ptr[5] << 16) + (nvs_ptr[4] << 8) + nvs_ptr[3];
+ }
+
+ /* if the MAC address is zeroed in the NVS derive from fuse */
+ if (oui_addr == 0 && nic_addr == 0) {
+ oui_addr = wl->fuse_oui_addr;
+ /* fuse has the BD_ADDR, the WLAN addresses are the next two */
+ nic_addr = wl->fuse_nic_addr + 1;
}
- SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
+ wl12xx_derive_mac_addresses(wl, oui_addr, nic_addr, 2);
ret = ieee80211_register_hw(wl->hw);
if (ret < 0) {
diff --git a/drivers/net/wireless/wl12xx/reg.h b/drivers/net/wireless/wl12xx/reg.h
index df34d59..340db32 100644
--- a/drivers/net/wireless/wl12xx/reg.h
+++ b/drivers/net/wireless/wl12xx/reg.h
@@ -525,4 +525,31 @@ b12-b0 - Supported Rate indicator bits as defined below.
*/
#define INTR_TRIG_TX_PROC1 BIT(18)
+#define WL127X_REG_FUSE_DATA_2_1 0x050a
+#define WL128X_REG_FUSE_DATA_2_1 0x2152
+#define PG_VER_MASK 0x3c
+#define PG_VER_OFFSET 2
+
+#define WL127X_PG_MAJOR_VER_MASK 0x3
+#define WL127X_PG_MAJOR_VER_OFFSET 0x0
+#define WL127X_PG_MINOR_VER_MASK 0xc
+#define WL127X_PG_MINOR_VER_OFFSET 0x2
+
+#define WL128X_PG_MAJOR_VER_MASK 0xc
+#define WL128X_PG_MAJOR_VER_OFFSET 0x2
+#define WL128X_PG_MINOR_VER_MASK 0x3
+#define WL128X_PG_MINOR_VER_OFFSET 0x0
+
+#define WL127X_PG_GET_MAJOR(pg_ver) ((pg_ver & WL127X_PG_MAJOR_VER_MASK) >> \
+ WL127X_PG_MAJOR_VER_OFFSET)
+#define WL127X_PG_GET_MINOR(pg_ver) ((pg_ver & WL127X_PG_MINOR_VER_MASK) >> \
+ WL127X_PG_MINOR_VER_OFFSET)
+#define WL128X_PG_GET_MAJOR(pg_ver) ((pg_ver & WL128X_PG_MAJOR_VER_MASK) >> \
+ WL128X_PG_MAJOR_VER_OFFSET)
+#define WL128X_PG_GET_MINOR(pg_ver) ((pg_ver & WL128X_PG_MINOR_VER_MASK) >> \
+ WL128X_PG_MINOR_VER_OFFSET)
+
+#define WL12XX_REG_FUSE_BD_ADDR_1 0x00310eb4
+#define WL12XX_REG_FUSE_BD_ADDR_2 0x00310eb8
+
#endif
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index b2b09cd..1f629fa 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -313,7 +313,12 @@ struct wl1271 {
s8 hw_pg_ver;
- u8 mac_addr[ETH_ALEN];
+ /* address read from the fuse ROM */
+ u32 fuse_oui_addr;
+ u32 fuse_nic_addr;
+
+ /* we have up to 2 MAC addresses */
+ struct mac_address addresses[2];
int channel;
u8 system_hlid;
--
1.7.4.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 8/8] wl12xx: add testmode operation to read the BD_ADDR from Fuse ROM
2012-01-24 9:06 [PATCH 0/8] wl12xx: some fixes and improvements for PLT mode Luciano Coelho
` (6 preceding siblings ...)
2012-01-24 9:06 ` [PATCH 7/8] wl12xx: use two MAC addresses based on the NVS or from fuse ROM Luciano Coelho
@ 2012-01-24 9:06 ` Luciano Coelho
2012-02-15 10:12 ` [PATCH 0/8] wl12xx: some fixes and improvements for PLT mode Luciano Coelho
8 siblings, 0 replies; 10+ messages in thread
From: Luciano Coelho @ 2012-01-24 9:06 UTC (permalink / raw)
To: linux-wireless; +Cc: coelho
Add a testmode command to retrieve the BD_ADDR that is stored in the
Fuse ROM in newer PGs. In old PGs this operation is not supported.
The caller can then derive the MAC addresses from it.
Signed-off-by: Luciano Coelho <coelho@ti.com>
---
drivers/net/wireless/wl12xx/testmode.c | 50 ++++++++++++++++++++++++++++++++
1 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c
index 25093c0..b2e8183 100644
--- a/drivers/net/wireless/wl12xx/testmode.c
+++ b/drivers/net/wireless/wl12xx/testmode.c
@@ -30,6 +30,7 @@
#include "acx.h"
#include "reg.h"
#include "ps.h"
+#include "io.h"
#define WL1271_TM_MAX_DATA_LENGTH 1024
@@ -41,6 +42,7 @@ enum wl1271_tm_commands {
WL1271_TM_CMD_NVS_PUSH, /* Not in use. Keep to not break ABI */
WL1271_TM_CMD_SET_PLT_MODE,
WL1271_TM_CMD_RECOVER,
+ WL1271_TM_CMD_GET_MAC,
__WL1271_TM_CMD_AFTER_LAST
};
@@ -264,6 +266,52 @@ static int wl1271_tm_cmd_recover(struct wl1271 *wl, struct nlattr *tb[])
return 0;
}
+static int wl12xx_tm_cmd_get_mac(struct wl1271 *wl, struct nlattr *tb[])
+{
+ struct sk_buff *skb;
+ u8 mac_addr[ETH_ALEN];
+ int ret = 0;
+
+ mutex_lock(&wl->mutex);
+
+ if (wl->state != WL1271_STATE_PLT) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if(wl->fuse_oui_addr == 0 && wl->fuse_nic_addr == 0) {
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ mac_addr[0] = (u8)(wl->fuse_oui_addr >> 16);
+ mac_addr[1] = (u8)(wl->fuse_oui_addr >> 8);
+ mac_addr[2] = (u8) wl->fuse_oui_addr;
+ mac_addr[3] = (u8)(wl->fuse_nic_addr >> 16);
+ mac_addr[4] = (u8)(wl->fuse_nic_addr >> 8);
+ mac_addr[5] = (u8) wl->fuse_nic_addr;
+
+ skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, ETH_ALEN);
+ if (!skb) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ NLA_PUT(skb, WL1271_TM_ATTR_DATA, ETH_ALEN, mac_addr);
+ ret = cfg80211_testmode_reply(skb);
+ if (ret < 0)
+ goto out;
+
+out:
+ mutex_unlock(&wl->mutex);
+ return ret;
+
+nla_put_failure:
+ kfree_skb(skb);
+ ret = -EMSGSIZE;
+ goto out;
+}
+
int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len)
{
struct wl1271 *wl = hw->priv;
@@ -288,6 +336,8 @@ int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len)
return wl1271_tm_cmd_set_plt_mode(wl, tb);
case WL1271_TM_CMD_RECOVER:
return wl1271_tm_cmd_recover(wl, tb);
+ case WL1271_TM_CMD_GET_MAC:
+ return wl12xx_tm_cmd_get_mac(wl, tb);
default:
return -EOPNOTSUPP;
}
--
1.7.4.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 0/8] wl12xx: some fixes and improvements for PLT mode
2012-01-24 9:06 [PATCH 0/8] wl12xx: some fixes and improvements for PLT mode Luciano Coelho
` (7 preceding siblings ...)
2012-01-24 9:06 ` [PATCH 8/8] wl12xx: add testmode operation to read the BD_ADDR from Fuse ROM Luciano Coelho
@ 2012-02-15 10:12 ` Luciano Coelho
8 siblings, 0 replies; 10+ messages in thread
From: Luciano Coelho @ 2012-02-15 10:12 UTC (permalink / raw)
To: linux-wireless
On Tue, 2012-01-24 at 11:06 +0200, Luciano Coelho wrote:
> Hi,
>
> This patchset fixes some bugs in PLT mode and adds support for 2 MAC
> addresses based on the NVS file or in the device's fuse ROM.
>
> This two patches I sent as part of the "wl12xx: read MAC from fuse
> rom" series are superseded by this set.
Applied this set.
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2012-02-15 10:12 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-24 9:06 [PATCH 0/8] wl12xx: some fixes and improvements for PLT mode Luciano Coelho
2012-01-24 9:06 ` [PATCH 1/8] wl12xx: Acquire lock before stopping plt Luciano Coelho
2012-01-24 9:06 ` [PATCH 2/8] wl12xx: Power off after flushing work Luciano Coelho
2012-01-24 9:06 ` [PATCH 3/8] wl12xx: Fix potential interrupt storm Luciano Coelho
2012-01-24 9:06 ` [PATCH 4/8] wl12xx: cancel delayed elp work and clear flags when stopping PLT Luciano Coelho
2012-01-24 9:06 ` [PATCH 5/8] wl12xx: move partition table definition to io.c Luciano Coelho
2012-01-24 9:06 ` [PATCH 6/8] wl12xx: read chip ID and HW PG version during probe Luciano Coelho
2012-01-24 9:06 ` [PATCH 7/8] wl12xx: use two MAC addresses based on the NVS or from fuse ROM Luciano Coelho
2012-01-24 9:06 ` [PATCH 8/8] wl12xx: add testmode operation to read the BD_ADDR from Fuse ROM Luciano Coelho
2012-02-15 10:12 ` [PATCH 0/8] wl12xx: some fixes and improvements for PLT mode Luciano Coelho
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox