These patches progressively add implementation and fix bugs in the wl1271
driver. This patch set is the first of three.
First of all apologies for the huge number of patches - quite a few have
accumulated since our last contribution. The good news in this is that these
patches have now received relatively good verification against the
wireless-testing mac80211/cfg80211 stack.
For those who wonder who I am: I am the co-maintainer of the wl1271 driver,
submitting these patches now in place of Luciano Coelho, while he is enjoying
the last moments of his well deserved vacation.
Executive summary of the changes of this patch set:
- Fixes to NVS/calibration handling
- WMM implementation
- Functional ad-hoc
- Preparation for SDIO support
Juuso Oikarinen (11):
wl1271: Fix PSM entry
wl1271: Fix channel changing code
wl1271: Add SSID configuration for JOIN in ad-hoc
wl1271: Use NVS INI file configuration
wl1271: Retrieve device mac address from the nvs file
wl1271: Fix random MAC address setting
wl1271: Optimized RX path packet retrieval
wl1271: Fix key-remove error
wl1271: Fix WEP key handling
wl1271: Fix ad-hoc SSID update
wl1271: Fix beacon filter table configuration
Kalle Valo (5):
wl1271: modify wl1271_acx_ac_cfg() to use function parameters
wl1271: modify wl1271_acx_tid_cfg() to use function parameters
wl1271: implement WMM
wl1271: wakeup chip in op_conf_tx()
wl1271: add testmode support
Luciano Coelho (2):
wl1271: add most of the normal initialization commands to PLT mode
wl1271: skip 3 unused bytes from the NVS
Teemu Paasikivi (4):
wl1271: Moved common IO functions from wl271_spi.c to wl1271_io.c
wl1271: Renamed IO functions
wl1271: Added IO reset and init functions
wl1271: Added alloc and free hw functions
drivers/net/wireless/wl12xx/Makefile | 4 +-
drivers/net/wireless/wl12xx/wl1271.h | 34 ++-
drivers/net/wireless/wl12xx/wl1271_acx.c | 62 ++--
drivers/net/wireless/wl12xx/wl1271_acx.h | 13 +-
drivers/net/wireless/wl12xx/wl1271_boot.c | 106 +++---
drivers/net/wireless/wl12xx/wl1271_cmd.c | 136 ++------
drivers/net/wireless/wl12xx/wl1271_cmd.h | 88 +----
drivers/net/wireless/wl12xx/wl1271_conf.h | 144 +--------
drivers/net/wireless/wl12xx/wl1271_event.c | 50 +++-
drivers/net/wireless/wl12xx/wl1271_init.c | 38 ++-
drivers/net/wireless/wl12xx/wl1271_init.h | 4 +
drivers/net/wireless/wl12xx/wl1271_io.c | 213 +++++++++++
drivers/net/wireless/wl12xx/wl1271_io.h | 68 ++++
drivers/net/wireless/wl12xx/wl1271_main.c | 481 ++++++++++++++++---------
drivers/net/wireless/wl12xx/wl1271_ps.c | 22 +-
drivers/net/wireless/wl12xx/wl1271_ps.h | 3 +-
drivers/net/wireless/wl12xx/wl1271_rx.c | 11 +-
drivers/net/wireless/wl12xx/wl1271_spi.c | 157 --------
drivers/net/wireless/wl12xx/wl1271_spi.h | 30 --
drivers/net/wireless/wl12xx/wl1271_testmode.c | 283 +++++++++++++++
drivers/net/wireless/wl12xx/wl1271_testmode.h | 31 ++
drivers/net/wireless/wl12xx/wl1271_tx.c | 28 +-
drivers/net/wireless/wl12xx/wl1271_tx.h | 36 ++
23 files changed, 1196 insertions(+), 846 deletions(-)
create mode 100644 drivers/net/wireless/wl12xx/wl1271_io.c
create mode 100644 drivers/net/wireless/wl12xx/wl1271_io.h
create mode 100644 drivers/net/wireless/wl12xx/wl1271_testmode.c
create mode 100644 drivers/net/wireless/wl12xx/wl1271_testmode.h
From: Luciano Coelho <[email protected]>
We need to configure PLT mode almost in the same way as normal mode. Most of
the configuration functions need to be called also when entering PLT, with
the exception of a few RX and TX configuration (which cause mac80211 warnings
if enable while runnning PLT tests).
Signed-off-by: Luciano Coelho <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_init.c | 8 ++--
drivers/net/wireless/wl12xx/wl1271_init.h | 4 ++
drivers/net/wireless/wl12xx/wl1271_main.c | 85 ++++++++++++++++++++++++++---
3 files changed, 86 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index 78403da..86c30a8 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -49,7 +49,7 @@ static int wl1271_init_hwenc_config(struct wl1271 *wl)
return 0;
}
-static int wl1271_init_templates_config(struct wl1271 *wl)
+int wl1271_init_templates_config(struct wl1271 *wl)
{
int ret;
@@ -113,7 +113,7 @@ static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
return 0;
}
-static int wl1271_init_phy_config(struct wl1271 *wl)
+int wl1271_init_phy_config(struct wl1271 *wl)
{
int ret;
@@ -156,7 +156,7 @@ static int wl1271_init_beacon_filter(struct wl1271 *wl)
return 0;
}
-static int wl1271_init_pta(struct wl1271 *wl)
+int wl1271_init_pta(struct wl1271 *wl)
{
int ret;
@@ -171,7 +171,7 @@ static int wl1271_init_pta(struct wl1271 *wl)
return 0;
}
-static int wl1271_init_energy_detection(struct wl1271 *wl)
+int wl1271_init_energy_detection(struct wl1271 *wl)
{
int ret;
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.h b/drivers/net/wireless/wl12xx/wl1271_init.h
index 930677f..bc26f8c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.h
+++ b/drivers/net/wireless/wl12xx/wl1271_init.h
@@ -27,6 +27,10 @@
#include "wl1271.h"
int wl1271_hw_init_power_auth(struct wl1271 *wl);
+int wl1271_init_templates_config(struct wl1271 *wl);
+int wl1271_init_phy_config(struct wl1271 *wl);
+int wl1271_init_pta(struct wl1271 *wl);
+int wl1271_init_energy_detection(struct wl1271 *wl);
int wl1271_hw_init(struct wl1271 *wl);
#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index b5d53a3..e698dec 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -265,7 +265,9 @@ static void wl1271_conf_init(struct wl1271 *wl)
static int wl1271_plt_init(struct wl1271 *wl)
{
- int ret;
+ struct conf_tx_ac_category *conf_ac;
+ struct conf_tx_tid *conf_tid;
+ int ret, i;
ret = wl1271_cmd_general_parms(wl);
if (ret < 0)
@@ -275,15 +277,89 @@ static int wl1271_plt_init(struct wl1271 *wl)
if (ret < 0)
return ret;
+ ret = wl1271_init_templates_config(wl);
+ if (ret < 0)
+ return ret;
+
ret = wl1271_acx_init_mem_config(wl);
if (ret < 0)
return ret;
+ /* PHY layer config */
+ ret = wl1271_init_phy_config(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ ret = wl1271_acx_dco_itrim_params(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* Initialize connection monitoring thresholds */
+ ret = wl1271_acx_conn_monit_params(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* Bluetooth WLAN coexistence */
+ ret = wl1271_init_pta(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* Energy detection */
+ ret = wl1271_init_energy_detection(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* Default fragmentation threshold */
+ ret = wl1271_acx_frag_threshold(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* Default TID configuration */
+ for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
+ conf_tid = &wl->conf.tx.tid_conf[i];
+ ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id,
+ conf_tid->channel_type,
+ conf_tid->tsid,
+ conf_tid->ps_scheme,
+ conf_tid->ack_policy,
+ conf_tid->apsd_conf[0],
+ conf_tid->apsd_conf[1]);
+ if (ret < 0)
+ goto out_free_memmap;
+ }
+
+ /* Default AC configuration */
+ for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
+ conf_ac = &wl->conf.tx.ac_conf[i];
+ ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
+ conf_ac->cw_max, conf_ac->aifsn,
+ conf_ac->tx_op_limit);
+ if (ret < 0)
+ goto out_free_memmap;
+ }
+
+ /* Enable data path */
ret = wl1271_cmd_data_path(wl, 1);
if (ret < 0)
- return ret;
+ goto out_free_memmap;
+
+ /* Configure for CAM power saving (ie. always active) */
+ ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* configure PM */
+ ret = wl1271_acx_pm_config(wl);
+ if (ret < 0)
+ goto out_free_memmap;
return 0;
+
+ out_free_memmap:
+ kfree(wl->target_mem_map);
+ wl->target_mem_map = NULL;
+
+ return ret;
}
static void wl1271_disable_interrupts(struct wl1271 *wl)
@@ -653,11 +729,6 @@ int wl1271_plt_start(struct wl1271 *wl)
if (ret < 0)
goto irq_disable;
- /* Make sure power saving is disabled */
- ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
- if (ret < 0)
- goto irq_disable;
-
wl->state = WL1271_STATE_PLT;
wl1271_notice("firmware booted in PLT mode (%s)",
wl->chip.fw_ver);
--
1.6.3.3
From: Teemu Paasikivi <[email protected]>
Added reset and init functions to IO layer of the driver.
Signed-off-by: Teemu Paasikivi <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_io.c | 10 ++++++++++
drivers/net/wireless/wl12xx/wl1271_io.h | 2 ++
drivers/net/wireless/wl12xx/wl1271_main.c | 4 ++--
3 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.c b/drivers/net/wireless/wl12xx/wl1271_io.c
index 00f98bd..5cd94d5 100644
--- a/drivers/net/wireless/wl12xx/wl1271_io.c
+++ b/drivers/net/wireless/wl12xx/wl1271_io.c
@@ -115,6 +115,16 @@ int wl1271_set_partition(struct wl1271 *wl,
return 0;
}
+void wl1271_io_reset(struct wl1271 *wl)
+{
+ wl1271_spi_reset(wl);
+}
+
+void wl1271_io_init(struct wl1271 *wl)
+{
+ wl1271_spi_init(wl);
+}
+
void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf,
size_t len, bool fixed)
{
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h
index 859d571..fa9a0b3 100644
--- a/drivers/net/wireless/wl12xx/wl1271_io.h
+++ b/drivers/net/wireless/wl12xx/wl1271_io.h
@@ -27,6 +27,8 @@
struct wl1271;
+void wl1271_io_reset(struct wl1271 *wl);
+void wl1271_io_init(struct wl1271 *wl);
/* Raw target IO, address is not translated */
void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf,
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 4696895..66fb9a0 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -648,8 +648,8 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
msleep(WL1271_PRE_POWER_ON_SLEEP);
wl1271_power_on(wl);
msleep(WL1271_POWER_ON_SLEEP);
- wl1271_spi_reset(wl);
- wl1271_spi_init(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. */
--
1.6.3.3
From: Kalle Valo <[email protected]>
Testmode will be used to send PLT (Production Line Testing) commands
from user space.
Signed-off-by: Kalle Valo <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
---
drivers/net/wireless/wl12xx/Makefile | 1 +
drivers/net/wireless/wl12xx/wl1271.h | 2 +-
drivers/net/wireless/wl12xx/wl1271_main.c | 2 +
drivers/net/wireless/wl12xx/wl1271_testmode.c | 283 +++++++++++++++++++++++++
drivers/net/wireless/wl12xx/wl1271_testmode.h | 31 +++
5 files changed, 318 insertions(+), 1 deletions(-)
create mode 100644 drivers/net/wireless/wl12xx/wl1271_testmode.c
create mode 100644 drivers/net/wireless/wl12xx/wl1271_testmode.h
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile
index 62e37ad..d089b5d 100644
--- a/drivers/net/wireless/wl12xx/Makefile
+++ b/drivers/net/wireless/wl12xx/Makefile
@@ -11,4 +11,5 @@ wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \
wl1271_event.o wl1271_tx.o wl1271_rx.o \
wl1271_ps.o wl1271_acx.o wl1271_boot.o \
wl1271_init.o wl1271_debugfs.o
+wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o
obj-$(CONFIG_WL1271) += wl1271.o
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index b3a3402..97ea509 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -43,7 +43,7 @@ enum {
DEBUG_SPI = BIT(1),
DEBUG_BOOT = BIT(2),
DEBUG_MAILBOX = BIT(3),
- DEBUG_NETLINK = BIT(4),
+ DEBUG_TESTMODE = BIT(4),
DEBUG_EVENT = BIT(5),
DEBUG_TX = BIT(6),
DEBUG_RX = BIT(7),
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index fb1e6a8..aa8f79c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -46,6 +46,7 @@
#include "wl1271_debugfs.h"
#include "wl1271_cmd.h"
#include "wl1271_boot.h"
+#include "wl1271_testmode.h"
#define WL1271_BOOT_RETRIES 3
@@ -1955,6 +1956,7 @@ static const struct ieee80211_ops wl1271_ops = {
.bss_info_changed = wl1271_op_bss_info_changed,
.set_rts_threshold = wl1271_op_set_rts_threshold,
.conf_tx = wl1271_op_conf_tx,
+ CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
};
static int wl1271_register_hw(struct wl1271 *wl)
diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.c b/drivers/net/wireless/wl12xx/wl1271_testmode.c
new file mode 100644
index 0000000..3919102
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_testmode.c
@@ -0,0 +1,283 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#include "wl1271_testmode.h"
+
+#include <net/genetlink.h>
+
+#include "wl1271.h"
+#include "wl1271_spi.h"
+#include "wl1271_acx.h"
+
+#define WL1271_TM_MAX_DATA_LENGTH 1024
+
+enum wl1271_tm_commands {
+ WL1271_TM_CMD_UNSPEC,
+ WL1271_TM_CMD_TEST,
+ WL1271_TM_CMD_INTERROGATE,
+ WL1271_TM_CMD_CONFIGURE,
+ WL1271_TM_CMD_NVS_PUSH,
+ WL1271_TM_CMD_SET_PLT_MODE,
+
+ __WL1271_TM_CMD_AFTER_LAST
+};
+#define WL1271_TM_CMD_MAX (__WL1271_TM_CMD_AFTER_LAST - 1)
+
+enum wl1271_tm_attrs {
+ WL1271_TM_ATTR_UNSPEC,
+ WL1271_TM_ATTR_CMD_ID,
+ WL1271_TM_ATTR_ANSWER,
+ WL1271_TM_ATTR_DATA,
+ WL1271_TM_ATTR_IE_ID,
+ WL1271_TM_ATTR_PLT_MODE,
+
+ __WL1271_TM_ATTR_AFTER_LAST
+};
+#define WL1271_TM_ATTR_MAX (__WL1271_TM_ATTR_AFTER_LAST - 1)
+
+static struct nla_policy wl1271_tm_policy[WL1271_TM_ATTR_MAX + 1] = {
+ [WL1271_TM_ATTR_CMD_ID] = { .type = NLA_U32 },
+ [WL1271_TM_ATTR_ANSWER] = { .type = NLA_U8 },
+ [WL1271_TM_ATTR_DATA] = { .type = NLA_BINARY,
+ .len = WL1271_TM_MAX_DATA_LENGTH },
+ [WL1271_TM_ATTR_IE_ID] = { .type = NLA_U32 },
+ [WL1271_TM_ATTR_PLT_MODE] = { .type = NLA_U32 },
+};
+
+
+static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[])
+{
+ int buf_len, ret, len;
+ struct sk_buff *skb;
+ void *buf;
+ u8 answer = 0;
+
+ wl1271_debug(DEBUG_TESTMODE, "testmode cmd test");
+
+ if (!tb[WL1271_TM_ATTR_DATA])
+ return -EINVAL;
+
+ buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
+ buf_len = nla_len(tb[WL1271_TM_ATTR_DATA]);
+
+ if (tb[WL1271_TM_ATTR_ANSWER])
+ answer = nla_get_u8(tb[WL1271_TM_ATTR_ANSWER]);
+
+ if (buf_len > sizeof(struct wl1271_command))
+ return -EMSGSIZE;
+
+ mutex_lock(&wl->mutex);
+ ret = wl1271_cmd_test(wl, buf, buf_len, answer);
+ mutex_unlock(&wl->mutex);
+
+ if (ret < 0) {
+ wl1271_warning("testmode cmd test failed: %d", ret);
+ return ret;
+ }
+
+ if (answer) {
+ len = nla_total_size(buf_len);
+ skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, len);
+ if (!skb)
+ return -ENOMEM;
+
+ NLA_PUT(skb, WL1271_TM_ATTR_DATA, buf_len, buf);
+ ret = cfg80211_testmode_reply(skb);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+
+nla_put_failure:
+ kfree_skb(skb);
+ return -EMSGSIZE;
+}
+
+static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[])
+{
+ int ret;
+ struct wl1271_command *cmd;
+ struct sk_buff *skb;
+ u8 ie_id;
+
+ wl1271_debug(DEBUG_TESTMODE, "testmode cmd interrogate");
+
+ if (!tb[WL1271_TM_ATTR_IE_ID])
+ return -EINVAL;
+
+ ie_id = nla_get_u8(tb[WL1271_TM_ATTR_IE_ID]);
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd)
+ return -ENOMEM;
+
+ mutex_lock(&wl->mutex);
+ ret = wl1271_cmd_interrogate(wl, ie_id, cmd, sizeof(*cmd));
+ mutex_unlock(&wl->mutex);
+
+ if (ret < 0) {
+ wl1271_warning("testmode cmd interrogate failed: %d", ret);
+ return ret;
+ }
+
+ skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ NLA_PUT(skb, WL1271_TM_ATTR_DATA, sizeof(*cmd), cmd);
+
+ return 0;
+
+nla_put_failure:
+ kfree_skb(skb);
+ return -EMSGSIZE;
+}
+
+static int wl1271_tm_cmd_configure(struct wl1271 *wl, struct nlattr *tb[])
+{
+ int buf_len, ret;
+ void *buf;
+ u8 ie_id;
+
+ wl1271_debug(DEBUG_TESTMODE, "testmode cmd configure");
+
+ if (!tb[WL1271_TM_ATTR_DATA])
+ return -EINVAL;
+ if (!tb[WL1271_TM_ATTR_IE_ID])
+ return -EINVAL;
+
+ ie_id = nla_get_u8(tb[WL1271_TM_ATTR_IE_ID]);
+ buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
+ buf_len = nla_len(tb[WL1271_TM_ATTR_DATA]);
+
+ if (buf_len > sizeof(struct wl1271_command))
+ return -EMSGSIZE;
+
+ mutex_lock(&wl->mutex);
+ ret = wl1271_cmd_configure(wl, ie_id, buf, buf_len);
+ mutex_unlock(&wl->mutex);
+
+ if (ret < 0) {
+ wl1271_warning("testmode cmd configure failed: %d", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])
+{
+ int ret = 0;
+ size_t len;
+ void *buf;
+
+ wl1271_debug(DEBUG_TESTMODE, "testmode cmd nvs push");
+
+ if (!tb[WL1271_TM_ATTR_DATA])
+ return -EINVAL;
+
+ buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
+ len = nla_len(tb[WL1271_TM_ATTR_DATA]);
+
+ if (len != sizeof(struct wl1271_nvs_file)) {
+ wl1271_error("nvs size is not as expected: %zu != %zu",
+ len, sizeof(struct wl1271_nvs_file));
+ return -EMSGSIZE;
+ }
+
+ mutex_lock(&wl->mutex);
+
+ kfree(wl->nvs);
+
+ wl->nvs = kmalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL);
+ if (!wl->nvs) {
+ wl1271_error("could not allocate memory for the nvs file");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(wl->nvs, buf, len);
+
+ wl1271_debug(DEBUG_TESTMODE, "testmode pushed nvs");
+
+out:
+ mutex_unlock(&wl->mutex);
+
+ return ret;
+}
+
+static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[])
+{
+ u32 val;
+ int ret;
+
+ wl1271_debug(DEBUG_TESTMODE, "testmode cmd set plt mode");
+
+ if (!tb[WL1271_TM_ATTR_PLT_MODE])
+ return -EINVAL;
+
+ val = nla_get_u32(tb[WL1271_TM_ATTR_PLT_MODE]);
+
+ switch (val) {
+ case 0:
+ ret = wl1271_plt_stop(wl);
+ break;
+ case 1:
+ ret = wl1271_plt_start(wl);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len)
+{
+ struct wl1271 *wl = hw->priv;
+ struct nlattr *tb[WL1271_TM_ATTR_MAX + 1];
+ int err;
+
+ err = nla_parse(tb, WL1271_TM_ATTR_MAX, data, len, wl1271_tm_policy);
+ if (err)
+ return err;
+
+ if (!tb[WL1271_TM_ATTR_CMD_ID])
+ return -EINVAL;
+
+ switch (nla_get_u32(tb[WL1271_TM_ATTR_CMD_ID])) {
+ case WL1271_TM_CMD_TEST:
+ return wl1271_tm_cmd_test(wl, tb);
+ case WL1271_TM_CMD_INTERROGATE:
+ return wl1271_tm_cmd_interrogate(wl, tb);
+ case WL1271_TM_CMD_CONFIGURE:
+ return wl1271_tm_cmd_configure(wl, tb);
+ case WL1271_TM_CMD_NVS_PUSH:
+ return wl1271_tm_cmd_nvs_push(wl, tb);
+ case WL1271_TM_CMD_SET_PLT_MODE:
+ return wl1271_tm_cmd_set_plt_mode(wl, tb);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.h b/drivers/net/wireless/wl12xx/wl1271_testmode.h
new file mode 100644
index 0000000..c196d28
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_testmode.h
@@ -0,0 +1,31 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL1271_TESTMODE_H__
+#define __WL1271_TESTMODE_H__
+
+#include <net/mac80211.h>
+
+int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len);
+
+#endif /* __WL1271_TESTMODE_H__ */
--
1.6.3.3
From: Kalle Valo <[email protected]>
For WMM we need to configure each tid separately so modify
wl1271_acx_tid_cfg() to take the configuration from function parameters
instead.
Signed-off-by: Kalle Valo <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_acx.c | 31 ++++++++++++++---------------
drivers/net/wireless/wl12xx/wl1271_acx.h | 4 ++-
drivers/net/wireless/wl12xx/wl1271_init.c | 16 ++++++++++++--
3 files changed, 31 insertions(+), 20 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index 4b052ee..60f10dc 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -863,10 +863,12 @@ out:
return ret;
}
-int wl1271_acx_tid_cfg(struct wl1271 *wl)
+int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
+ u8 tsid, u8 ps_scheme, u8 ack_policy,
+ u32 apsd_conf0, u32 apsd_conf1)
{
struct acx_tid_config *acx;
- int i, ret = 0;
+ int ret = 0;
wl1271_debug(DEBUG_ACX, "acx tid config");
@@ -877,21 +879,18 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl)
goto out;
}
- for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
- struct conf_tx_tid *c = &(wl->conf.tx.tid_conf[i]);
- acx->queue_id = c->queue_id;
- acx->channel_type = c->channel_type;
- acx->tsid = c->tsid;
- acx->ps_scheme = c->ps_scheme;
- acx->ack_policy = c->ack_policy;
- acx->apsd_conf[0] = cpu_to_le32(c->apsd_conf[0]);
- acx->apsd_conf[1] = cpu_to_le32(c->apsd_conf[1]);
+ acx->queue_id = queue_id;
+ acx->channel_type = channel_type;
+ acx->tsid = tsid;
+ acx->ps_scheme = ps_scheme;
+ acx->ack_policy = ack_policy;
+ acx->apsd_conf[0] = cpu_to_le32(apsd_conf0);
+ acx->apsd_conf[1] = cpu_to_le32(apsd_conf1);
- ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx));
- if (ret < 0) {
- wl1271_warning("Setting of tid config failed: %d", ret);
- goto out;
- }
+ ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("Setting of tid config failed: %d", ret);
+ goto out;
}
out:
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index e5f5cbd..ac94a13 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -1072,7 +1072,9 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats);
int wl1271_acx_rate_policies(struct wl1271 *wl);
int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
u8 aifsn, u16 txop);
-int wl1271_acx_tid_cfg(struct wl1271 *wl);
+int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
+ u8 tsid, u8 ps_scheme, u8 ack_policy,
+ u32 apsd_conf0, u32 apsd_conf1);
int wl1271_acx_frag_threshold(struct wl1271 *wl);
int wl1271_acx_tx_config_options(struct wl1271 *wl);
int wl1271_acx_mem_cfg(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index 2b56a9e..78403da 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -196,6 +196,7 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
int wl1271_hw_init(struct wl1271 *wl)
{
struct conf_tx_ac_category *conf_ac;
+ struct conf_tx_tid *conf_tid;
int ret, i;
ret = wl1271_cmd_general_parms(wl);
@@ -275,9 +276,18 @@ int wl1271_hw_init(struct wl1271 *wl)
goto out_free_memmap;
/* Default TID configuration */
- ret = wl1271_acx_tid_cfg(wl);
- if (ret < 0)
- goto out_free_memmap;
+ for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
+ conf_tid = &wl->conf.tx.tid_conf[i];
+ ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id,
+ conf_tid->channel_type,
+ conf_tid->tsid,
+ conf_tid->ps_scheme,
+ conf_tid->ack_policy,
+ conf_tid->apsd_conf[0],
+ conf_tid->apsd_conf[1]);
+ if (ret < 0)
+ goto out_free_memmap;
+ }
/* Default AC configuration */
for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
--
1.6.3.3
From: Teemu Paasikivi <[email protected]>
Moved allocation and freeing of context structure of the driver to
separate functions from probe and remove functions.
Signed-off-by: Teemu Paasikivi <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_main.c | 80 +++++++++++++++++++----------
1 files changed, 53 insertions(+), 27 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 66fb9a0..2a864b2 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -2025,23 +2025,17 @@ static struct platform_device wl1271_device = {
};
#define WL1271_DEFAULT_CHANNEL 0
-static int __devinit wl1271_probe(struct spi_device *spi)
+
+static struct ieee80211_hw *wl1271_alloc_hw(void)
{
- struct wl12xx_platform_data *pdata;
struct ieee80211_hw *hw;
struct wl1271 *wl;
- int ret, i;
-
- pdata = spi->dev.platform_data;
- if (!pdata) {
- wl1271_error("no platform data");
- return -ENODEV;
- }
+ int i;
hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
if (!hw) {
wl1271_error("could not alloc ieee80211_hw");
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
}
wl = hw->priv;
@@ -2050,8 +2044,6 @@ static int __devinit wl1271_probe(struct spi_device *spi)
INIT_LIST_HEAD(&wl->list);
wl->hw = hw;
- dev_set_drvdata(&spi->dev, wl);
- wl->spi = spi;
skb_queue_head_init(&wl->tx_queue);
@@ -2078,6 +2070,54 @@ static int __devinit wl1271_probe(struct spi_device *spi)
wl->state = WL1271_STATE_OFF;
mutex_init(&wl->mutex);
+ /* Apply default driver configuration. */
+ wl1271_conf_init(wl);
+
+ return hw;
+}
+
+int wl1271_free_hw(struct wl1271 *wl)
+{
+ ieee80211_unregister_hw(wl->hw);
+
+ wl1271_debugfs_exit(wl);
+
+ kfree(wl->target_mem_map);
+ vfree(wl->fw);
+ wl->fw = NULL;
+ kfree(wl->nvs);
+ wl->nvs = NULL;
+
+ kfree(wl->fw_status);
+ kfree(wl->tx_res_if);
+
+ ieee80211_free_hw(wl->hw);
+
+ return 0;
+}
+
+static int __devinit wl1271_probe(struct spi_device *spi)
+{
+ struct wl12xx_platform_data *pdata;
+ struct ieee80211_hw *hw;
+ struct wl1271 *wl;
+ int ret;
+
+ pdata = spi->dev.platform_data;
+ if (!pdata) {
+ wl1271_error("no platform data");
+ return -ENODEV;
+ }
+
+ hw = wl1271_alloc_hw();
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+
+ wl = hw->priv;
+
+ dev_set_drvdata(&spi->dev, wl);
+ wl->spi = spi;
+
/* This is the only SPI value that we need to set here, the rest
* comes from the board-peripherals file */
spi->bits_per_word = 32;
@@ -2119,9 +2159,6 @@ static int __devinit wl1271_probe(struct spi_device *spi)
}
dev_set_drvdata(&wl1271_device.dev, wl);
- /* Apply default driver configuration. */
- wl1271_conf_init(wl);
-
ret = wl1271_init_ieee80211(wl);
if (ret)
goto out_platform;
@@ -2152,21 +2189,10 @@ static int __devexit wl1271_remove(struct spi_device *spi)
{
struct wl1271 *wl = dev_get_drvdata(&spi->dev);
- ieee80211_unregister_hw(wl->hw);
-
- wl1271_debugfs_exit(wl);
platform_device_unregister(&wl1271_device);
free_irq(wl->irq, wl);
- kfree(wl->target_mem_map);
- vfree(wl->fw);
- wl->fw = NULL;
- kfree(wl->nvs);
- wl->nvs = NULL;
- kfree(wl->fw_status);
- kfree(wl->tx_res_if);
-
- ieee80211_free_hw(wl->hw);
+ wl1271_free_hw(wl);
return 0;
}
--
1.6.3.3
Currently the PSM entry function assumes successful operation, and enables
ELP, BET and beacon filtering right away. This is bad, because the PSM
entry may fail due to environmental issues, which will cause the ELP, BET and
beacon filtering to be illegally enabled (because FW remains in active state.)
Fix this by enabling ELP, BET and beacon filtering only after successful entry,
and by ensuring the firmware is in active mode after the failure.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_cmd.c | 4 +-
drivers/net/wireless/wl12xx/wl1271_cmd.h | 2 +-
drivers/net/wireless/wl12xx/wl1271_event.c | 35 ++++++++++++++++++++++++++-
drivers/net/wireless/wl12xx/wl1271_main.c | 8 ++++--
drivers/net/wireless/wl12xx/wl1271_ps.c | 21 +++-------------
drivers/net/wireless/wl12xx/wl1271_ps.h | 3 +-
6 files changed, 47 insertions(+), 26 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index a74259b..dd2b5f0 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -555,7 +555,7 @@ out:
return ret;
}
-int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send)
{
struct wl1271_cmd_ps_params *ps_params = NULL;
int ret = 0;
@@ -576,7 +576,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
}
ps_params->ps_mode = ps_mode;
- ps_params->send_null_data = 1;
+ ps_params->send_null_data = send;
ps_params->retries = 5;
ps_params->hang_over_period = 128;
ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index 09fe912..ba433f4 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -38,7 +38,7 @@ int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
int wl1271_cmd_data_path(struct wl1271 *wl, bool enable);
-int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode);
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send);
int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
size_t len);
int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
index 0a145af..cecbae2 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -78,24 +78,55 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
switch (mbox->ps_status) {
case EVENT_ENTER_POWER_SAVE_FAIL:
+ wl1271_debug(DEBUG_PSM, "PSM entry failed");
+
if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
+ /* remain in active mode */
wl->psm_entry_retry = 0;
break;
}
if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) {
wl->psm_entry_retry++;
- ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
+ ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
+ true);
} else {
wl1271_error("PSM entry failed, giving up.\n");
+ /* make sure the firmware goes into active mode */
+ ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
+ false);
wl->psm_entry_retry = 0;
}
break;
case EVENT_ENTER_POWER_SAVE_SUCCESS:
wl->psm_entry_retry = 0;
+
+ /* enable beacon filtering */
+ ret = wl1271_acx_beacon_filter_opt(wl, true);
+ if (ret < 0)
+ break;
+
+ /* enable beacon early termination */
+ ret = wl1271_acx_bet_enable(wl, true);
+ if (ret < 0)
+ break;
+
+ /* go to extremely low power mode */
+ wl1271_ps_elp_sleep(wl);
+ if (ret < 0)
+ break;
break;
case EVENT_EXIT_POWER_SAVE_FAIL:
- wl1271_info("PSM exit failed");
+ wl1271_debug(DEBUG_PSM, "PSM exit failed");
+
+ if (test_bit(WL1271_FLAG_PSM, &wl->flags)) {
+ wl->psm_entry_retry = 0;
+ break;
+ }
+
+ /* make sure the firmware goes to active mode */
+ ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
+ false);
break;
case EVENT_EXIT_POWER_SAVE_SUCCESS:
default:
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index e4867b8..6f026fe 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1248,7 +1248,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
*/
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
wl1271_info("psm enabled");
- ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
+ ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
+ true);
}
} else if (!(conf->flags & IEEE80211_CONF_PS) &&
test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
@@ -1257,7 +1258,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags);
if (test_bit(WL1271_FLAG_PSM, &wl->flags))
- ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE);
+ ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
+ true);
}
if (conf->power_level != wl->power_level) {
@@ -1637,7 +1639,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
mode = STATION_POWER_SAVE_MODE;
- ret = wl1271_ps_set_mode(wl, mode);
+ ret = wl1271_ps_set_mode(wl, mode, true);
if (ret < 0)
goto out_sleep;
}
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c
index e407790..29f6700 100644
--- a/drivers/net/wireless/wl12xx/wl1271_ps.c
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.c
@@ -118,7 +118,8 @@ out:
return 0;
}
-int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode)
+int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
+ bool send)
{
int ret;
@@ -126,21 +127,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode)
case STATION_POWER_SAVE_MODE:
wl1271_debug(DEBUG_PSM, "entering psm");
- /* enable beacon filtering */
- ret = wl1271_acx_beacon_filter_opt(wl, true);
- if (ret < 0)
- return ret;
-
- /* enable beacon early termination */
- ret = wl1271_acx_bet_enable(wl, true);
- if (ret < 0)
- return ret;
-
- ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
- if (ret < 0)
- return ret;
-
- wl1271_ps_elp_sleep(wl);
+ ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE, send);
if (ret < 0)
return ret;
@@ -163,7 +150,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode)
if (ret < 0)
return ret;
- ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
+ ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE, send);
if (ret < 0)
return ret;
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.h b/drivers/net/wireless/wl12xx/wl1271_ps.h
index 779653d..940276f 100644
--- a/drivers/net/wireless/wl12xx/wl1271_ps.h
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.h
@@ -27,7 +27,8 @@
#include "wl1271.h"
#include "wl1271_acx.h"
-int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode);
+int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
+ bool send);
void wl1271_ps_elp_sleep(struct wl1271 *wl);
int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake);
void wl1271_elp_work(struct work_struct *work);
--
1.6.3.3
From: Kalle Valo <[email protected]>
Now that necessary commands for WMM are implemented, implement queue handling
for WMM. But WMM is not enabled yet, only one queue is used.
Based on a similar patch from wl1251.
Signed-off-by: Kalle Valo <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_main.c | 31 +++++++++++++++++++++++++
drivers/net/wireless/wl12xx/wl1271_tx.c | 10 +++++---
drivers/net/wireless/wl12xx/wl1271_tx.h | 36 +++++++++++++++++++++++++++++
3 files changed, 73 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index a3742c8..6f7a7d9 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1712,6 +1712,36 @@ out:
mutex_unlock(&wl->mutex);
}
+static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
+ const struct ieee80211_tx_queue_params *params)
+{
+ struct wl1271 *wl = hw->priv;
+ int ret;
+
+ mutex_lock(&wl->mutex);
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue);
+
+ ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue),
+ params->cw_min, params->cw_max,
+ params->aifs, params->txop);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue),
+ CONF_CHANNEL_TYPE_EDCF,
+ wl1271_tx_get_queue(queue),
+ CONF_PS_SCHEME_LEGACY_PSPOLL,
+ CONF_ACK_POLICY_LEGACY, 0, 0);
+ if (ret < 0)
+ goto out;
+
+out:
+ mutex_unlock(&wl->mutex);
+
+ return ret;
+}
+
/* can't be const, mac80211 writes to this */
static struct ieee80211_rate wl1271_rates[] = {
@@ -1877,6 +1907,7 @@ static const struct ieee80211_ops wl1271_ops = {
.hw_scan = wl1271_op_hw_scan,
.bss_info_changed = wl1271_op_bss_info_changed,
.set_rts_threshold = wl1271_op_set_rts_threshold,
+ .conf_tx = wl1271_op_conf_tx,
};
static int wl1271_register_hw(struct wl1271 *wl)
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
index a288cc3..f6815a9 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -87,7 +87,7 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
u32 extra, struct ieee80211_tx_info *control)
{
struct wl1271_tx_hw_descr *desc;
- int pad;
+ int pad, ac;
u16 tx_attr;
desc = (struct wl1271_tx_hw_descr *) skb->data;
@@ -107,9 +107,11 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
/* configure the tx attributes */
tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
- /* FIXME: do we know the packet priority? can we identify mgmt
- packets, and use max prio for them at least? */
- desc->tid = 0;
+
+ /* queue */
+ ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
+ desc->tid = wl1271_tx_ac_to_tid(ac);
+
desc->aid = TX_HW_DEFAULT_AID;
desc->reserved = 0;
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h
index 416396c..17e405a 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.h
@@ -123,6 +123,42 @@ struct wl1271_tx_hw_res_if {
struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN];
} __attribute__ ((packed));
+static inline int wl1271_tx_get_queue(int queue)
+{
+ /* FIXME: use best effort until WMM is enabled */
+ return CONF_TX_AC_BE;
+
+ switch (queue) {
+ case 0:
+ return CONF_TX_AC_VO;
+ case 1:
+ return CONF_TX_AC_VI;
+ case 2:
+ return CONF_TX_AC_BE;
+ case 3:
+ return CONF_TX_AC_BK;
+ default:
+ return CONF_TX_AC_BE;
+ }
+}
+
+/* wl1271 tx descriptor needs the tid and we need to convert it from ac */
+static inline int wl1271_tx_ac_to_tid(int ac)
+{
+ switch (ac) {
+ case 0:
+ return 0;
+ case 1:
+ return 2;
+ case 2:
+ return 4;
+ case 3:
+ return 6;
+ default:
+ return 0;
+ }
+}
+
void wl1271_tx_work(struct work_struct *work);
void wl1271_tx_complete(struct wl1271 *wl, u32 count);
void wl1271_tx_flush(struct wl1271 *wl);
--
1.6.3.3
The channel changing code would a) change the BSSID to a dummy on upon
channel change, breaking connectivity, and b) not update the channel number
at all for ad-hoc, breaking adhoc.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_main.c | 12 ++++++++++--
1 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 6f026fe..8b46b70 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1234,8 +1234,16 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
}
/* if the channel changes while joined, join again */
- if (channel != wl->channel && test_bit(WL1271_FLAG_JOINED, &wl->flags))
- wl1271_join_channel(wl, channel);
+ if (channel != wl->channel &&
+ test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
+ wl->channel = channel;
+ /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */
+ ret = wl1271_cmd_join(wl);
+ if (ret < 0)
+ wl1271_warning("cmd join to update channel failed %d",
+ ret);
+ } else
+ wl->channel = channel;
if (conf->flags & IEEE80211_CONF_PS &&
!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
--
1.6.3.3
Instead of acking RX packets read from the FW once all (of several possible)
buffered packets are retrieved, ack packets one by one as they are read. This
enables the FW to start receiving more packets from the network while the
host read operation is still ongoing.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Kalle Valo <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_rx.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c
index ca645f3..e8eee88 100644
--- a/drivers/net/wireless/wl12xx/wl1271_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.c
@@ -218,7 +218,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
wl->rx_counter++;
drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
+ wl1271_spi_write32(wl, RX_DRIVER_COUNTER_ADDRESS,
+ wl->rx_counter);
}
-
- wl1271_spi_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
}
--
1.6.3.3
Replace the hardcoded general and radio parameter configuration in the driver
with configuration taken from the NVS file directly. Also remove the driver
dependency to the structures with the parameter data.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Kalle Valo <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271.h | 32 ++++++-
drivers/net/wireless/wl12xx/wl1271_boot.c | 29 ++----
drivers/net/wireless/wl12xx/wl1271_cmd.c | 117 ++++--------------------
drivers/net/wireless/wl12xx/wl1271_cmd.h | 86 ++---------------
drivers/net/wireless/wl12xx/wl1271_conf.h | 144 +----------------------------
drivers/net/wireless/wl12xx/wl1271_main.c | 101 +-------------------
6 files changed, 77 insertions(+), 432 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index d0938db..b3a3402 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -109,7 +109,33 @@ enum {
#define WL1271_FW_NAME "wl1271-fw.bin"
#define WL1271_NVS_NAME "wl1271-nvs.bin"
-#define WL1271_NVS_LEN 468
+
+/* NVS data structure */
+#define WL1271_NVS_SECTION_SIZE 468
+
+#define WL1271_NVS_GENERAL_PARAMS_SIZE 57
+#define WL1271_NVS_GENERAL_PARAMS_SIZE_PADDED \
+ (WL1271_NVS_GENERAL_PARAMS_SIZE + 1)
+#define WL1271_NVS_STAT_RADIO_PARAMS_SIZE 17
+#define WL1271_NVS_STAT_RADIO_PARAMS_SIZE_PADDED \
+ (WL1271_NVS_STAT_RADIO_PARAMS_SIZE + 1)
+#define WL1271_NVS_DYN_RADIO_PARAMS_SIZE 65
+#define WL1271_NVS_DYN_RADIO_PARAMS_SIZE_PADDED \
+ (WL1271_NVS_DYN_RADIO_PARAMS_SIZE + 1)
+#define WL1271_NVS_FEM_COUNT 2
+#define WL1271_NVS_INI_SPARE_SIZE 124
+
+struct wl1271_nvs_file {
+ /* NVS section */
+ u8 nvs[WL1271_NVS_SECTION_SIZE];
+
+ /* INI section */
+ u8 general_params[WL1271_NVS_GENERAL_PARAMS_SIZE_PADDED];
+ u8 stat_radio_params[WL1271_NVS_STAT_RADIO_PARAMS_SIZE_PADDED];
+ u8 dyn_radio_params[WL1271_NVS_FEM_COUNT]
+ [WL1271_NVS_DYN_RADIO_PARAMS_SIZE_PADDED];
+ u8 ini_spare[WL1271_NVS_INI_SPARE_SIZE];
+} __attribute__ ((packed));
/*
* Enable/disable 802.11a support for WL1273
@@ -342,8 +368,7 @@ struct wl1271 {
u8 *fw;
size_t fw_len;
- u8 *nvs;
- size_t nvs_len;
+ struct wl1271_nvs_file *nvs;
u8 bssid[ETH_ALEN];
u8 mac_addr[ETH_ALEN];
@@ -461,6 +486,7 @@ int wl1271_plt_stop(struct wl1271 *wl);
static inline bool wl1271_11a_enabled(void)
{
+ /* FIXME: this could be determined based on the NVS-INI file */
#ifdef WL1271_80211A_ENABLED
return true;
#else
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index e803b87..bc3fe02 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -219,29 +219,22 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
size_t nvs_len, burst_len;
int i;
u32 dest_addr, val;
- u8 *nvs_ptr, *nvs, *nvs_aligned;
+ u8 *nvs_ptr, *nvs_aligned;
- nvs = wl->nvs;
- if (nvs == NULL)
+ if (wl->nvs == NULL)
return -ENODEV;
- if (wl->nvs_len < WL1271_NVS_LEN)
- return -EINVAL;
-
- nvs_ptr = nvs;
-
/* only the first part of the NVS needs to be uploaded */
- nvs_len = WL1271_NVS_LEN;
-
- /* FIXME: read init settings from the remaining part of the NVS */
+ nvs_len = sizeof(wl->nvs->nvs);
+ nvs_ptr = (u8 *)wl->nvs->nvs;
/* Update the device MAC address into the nvs */
- nvs[11] = wl->mac_addr[0];
- nvs[10] = wl->mac_addr[1];
- nvs[6] = wl->mac_addr[2];
- nvs[5] = wl->mac_addr[3];
- nvs[4] = wl->mac_addr[4];
- nvs[3] = wl->mac_addr[5];
+ 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];
/*
* Layout before the actual NVS tables:
@@ -283,7 +276,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
* is 7 bytes further.
*/
nvs_ptr += 7;
- nvs_len -= nvs_ptr - nvs;
+ nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs;
nvs_len = ALIGN(nvs_len, 4);
/* FIXME: The driver sets the partition here, but this is not needed,
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index dd2b5f0..54b5124 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -191,43 +191,19 @@ static int wl1271_cmd_cal(struct wl1271 *wl)
int wl1271_cmd_general_parms(struct wl1271 *wl)
{
struct wl1271_general_parms_cmd *gen_parms;
- struct conf_general_parms *g = &wl->conf.init.genparam;
int ret;
+ if (!wl->nvs)
+ return -ENODEV;
+
gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
if (!gen_parms)
return -ENOMEM;
gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM;
- gen_parms->ref_clk = g->ref_clk;
- gen_parms->settling_time = g->settling_time;
- gen_parms->clk_valid_on_wakeup = g->clk_valid_on_wakeup;
- gen_parms->dc2dcmode = g->dc2dcmode;
- gen_parms->single_dual_band = g->single_dual_band;
- gen_parms->tx_bip_fem_autodetect = g->tx_bip_fem_autodetect;
- gen_parms->tx_bip_fem_manufacturer = g->tx_bip_fem_manufacturer;
- gen_parms->settings = g->settings;
-
- gen_parms->sr_state = g->sr_state;
-
- memcpy(gen_parms->srf1,
- g->srf1,
- CONF_MAX_SMART_REFLEX_PARAMS);
- memcpy(gen_parms->srf2,
- g->srf2,
- CONF_MAX_SMART_REFLEX_PARAMS);
- memcpy(gen_parms->srf3,
- g->srf3,
- CONF_MAX_SMART_REFLEX_PARAMS);
- memcpy(gen_parms->sr_debug_table,
- g->sr_debug_table,
- CONF_MAX_SMART_REFLEX_PARAMS);
-
- gen_parms->sr_sen_n_p = g->sr_sen_n_p;
- gen_parms->sr_sen_n_p_gain = g->sr_sen_n_p_gain;
- gen_parms->sr_sen_nrn = g->sr_sen_nrn;
- gen_parms->sr_sen_prn = g->sr_sen_prn;
+ memcpy(gen_parms->params, wl->nvs->general_params,
+ WL1271_NVS_GENERAL_PARAMS_SIZE);
ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0);
if (ret < 0)
@@ -240,8 +216,11 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
int wl1271_cmd_radio_parms(struct wl1271 *wl)
{
struct wl1271_radio_parms_cmd *radio_parms;
- struct conf_radio_parms *r = &wl->conf.init.radioparam;
- int i, ret;
+ struct conf_radio_parms *rparam = &wl->conf.init.radioparam;
+ int ret;
+
+ if (!wl->nvs)
+ return -ENODEV;
radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL);
if (!radio_parms)
@@ -249,73 +228,13 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM;
- /* Static radio parameters */
- radio_parms->rx_trace_loss = r->rx_trace_loss;
- radio_parms->tx_trace_loss = r->tx_trace_loss;
- memcpy(radio_parms->rx_rssi_and_proc_compens,
- r->rx_rssi_and_proc_compens,
- CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE);
-
- memcpy(radio_parms->rx_trace_loss_5, r->rx_trace_loss_5,
- CONF_NUMBER_OF_SUB_BANDS_5);
- memcpy(radio_parms->tx_trace_loss_5, r->tx_trace_loss_5,
- CONF_NUMBER_OF_SUB_BANDS_5);
- memcpy(radio_parms->rx_rssi_and_proc_compens_5,
- r->rx_rssi_and_proc_compens_5,
- CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE);
-
- /* Dynamic radio parameters */
- radio_parms->tx_ref_pd_voltage = cpu_to_le16(r->tx_ref_pd_voltage);
- radio_parms->tx_ref_power = r->tx_ref_power;
- radio_parms->tx_offset_db = r->tx_offset_db;
-
- memcpy(radio_parms->tx_rate_limits_normal, r->tx_rate_limits_normal,
- CONF_NUMBER_OF_RATE_GROUPS);
- memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded,
- CONF_NUMBER_OF_RATE_GROUPS);
- memcpy(radio_parms->tx_rate_limits_extreme, r->tx_rate_limits_extreme,
- CONF_NUMBER_OF_RATE_GROUPS);
-
- memcpy(radio_parms->tx_channel_limits_11b, r->tx_channel_limits_11b,
- CONF_NUMBER_OF_CHANNELS_2_4);
- memcpy(radio_parms->tx_channel_limits_ofdm, r->tx_channel_limits_ofdm,
- CONF_NUMBER_OF_CHANNELS_2_4);
- memcpy(radio_parms->tx_pdv_rate_offsets, r->tx_pdv_rate_offsets,
- CONF_NUMBER_OF_RATE_GROUPS);
- memcpy(radio_parms->tx_ibias, r->tx_ibias, CONF_NUMBER_OF_RATE_GROUPS);
-
- radio_parms->rx_fem_insertion_loss = r->rx_fem_insertion_loss;
- radio_parms->degraded_low_to_normal_threshold =
- r->degraded_low_to_normal_threshold;
- radio_parms->degraded_normal_to_high_threshold =
- r->degraded_normal_to_high_threshold;
-
-
- for (i = 0; i < CONF_NUMBER_OF_SUB_BANDS_5; i++)
- radio_parms->tx_ref_pd_voltage_5[i] =
- cpu_to_le16(r->tx_ref_pd_voltage_5[i]);
- memcpy(radio_parms->tx_ref_power_5, r->tx_ref_power_5,
- CONF_NUMBER_OF_SUB_BANDS_5);
- memcpy(radio_parms->tx_offset_db_5, r->tx_offset_db_5,
- CONF_NUMBER_OF_SUB_BANDS_5);
- memcpy(radio_parms->tx_rate_limits_normal_5,
- r->tx_rate_limits_normal_5, CONF_NUMBER_OF_RATE_GROUPS);
- memcpy(radio_parms->tx_rate_limits_degraded_5,
- r->tx_rate_limits_degraded_5, CONF_NUMBER_OF_RATE_GROUPS);
- memcpy(radio_parms->tx_rate_limits_extreme_5,
- r->tx_rate_limits_extreme_5, CONF_NUMBER_OF_RATE_GROUPS);
- memcpy(radio_parms->tx_channel_limits_ofdm_5,
- r->tx_channel_limits_ofdm_5, CONF_NUMBER_OF_CHANNELS_5);
- memcpy(radio_parms->tx_pdv_rate_offsets_5, r->tx_pdv_rate_offsets_5,
- CONF_NUMBER_OF_RATE_GROUPS);
- memcpy(radio_parms->tx_ibias_5, r->tx_ibias_5,
- CONF_NUMBER_OF_RATE_GROUPS);
- memcpy(radio_parms->rx_fem_insertion_loss_5,
- r->rx_fem_insertion_loss_5, CONF_NUMBER_OF_SUB_BANDS_5);
- radio_parms->degraded_low_to_normal_threshold_5 =
- r->degraded_low_to_normal_threshold_5;
- radio_parms->degraded_normal_to_high_threshold_5 =
- r->degraded_normal_to_high_threshold_5;
+ memcpy(radio_parms->stat_radio_params, wl->nvs->stat_radio_params,
+ WL1271_NVS_STAT_RADIO_PARAMS_SIZE);
+ memcpy(radio_parms->dyn_radio_params,
+ wl->nvs->dyn_radio_params[rparam->fem],
+ WL1271_NVS_DYN_RADIO_PARAMS_SIZE);
+
+ /* FIXME: current NVS is missing 5GHz parameters */
wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ",
radio_parms, sizeof(*radio_parms));
@@ -1022,7 +941,7 @@ int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_warning("could not set keys");
- goto out;
+ goto out;
}
out:
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index ba433f4..2dc06c7 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -428,90 +428,24 @@ struct wl1271_general_parms_cmd {
struct wl1271_cmd_test_header test;
- u8 ref_clk;
- u8 settling_time;
- u8 clk_valid_on_wakeup;
- u8 dc2dcmode;
- u8 single_dual_band;
-
- u8 tx_bip_fem_autodetect;
- u8 tx_bip_fem_manufacturer;
- u8 settings;
-
- u8 sr_state;
-
- s8 srf1[CONF_MAX_SMART_REFLEX_PARAMS];
- s8 srf2[CONF_MAX_SMART_REFLEX_PARAMS];
- s8 srf3[CONF_MAX_SMART_REFLEX_PARAMS];
-
- s8 sr_debug_table[CONF_MAX_SMART_REFLEX_PARAMS];
-
- u8 sr_sen_n_p;
- u8 sr_sen_n_p_gain;
- u8 sr_sen_nrn;
- u8 sr_sen_prn;
-
- u8 padding[3];
+ u8 params[WL1271_NVS_GENERAL_PARAMS_SIZE];
+ s8 reserved[23];
} __attribute__ ((packed));
+#define WL1271_STAT_RADIO_PARAMS_5_SIZE 29
+#define WL1271_DYN_RADIO_PARAMS_5_SIZE 104
+
struct wl1271_radio_parms_cmd {
struct wl1271_cmd_header header;
struct wl1271_cmd_test_header test;
- /* Static radio parameters */
- /* 2.4GHz */
- u8 rx_trace_loss;
- u8 tx_trace_loss;
- s8 rx_rssi_and_proc_compens[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
-
- /* 5GHz */
- u8 rx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
- u8 tx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
- s8 rx_rssi_and_proc_compens_5[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
-
- /* Dynamic radio parameters */
- /* 2.4GHz */
- __le16 tx_ref_pd_voltage;
- u8 tx_ref_power;
- s8 tx_offset_db;
-
- s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS];
- s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS];
- s8 tx_rate_limits_extreme[CONF_NUMBER_OF_RATE_GROUPS];
+ u8 stat_radio_params[WL1271_NVS_STAT_RADIO_PARAMS_SIZE];
+ u8 stat_radio_params_5[WL1271_STAT_RADIO_PARAMS_5_SIZE];
- s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4];
- s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4];
- s8 tx_pdv_rate_offsets[CONF_NUMBER_OF_RATE_GROUPS];
-
- u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS];
- u8 rx_fem_insertion_loss;
-
- u8 degraded_low_to_normal_threshold;
- u8 degraded_normal_to_high_threshold;
-
- u8 padding1; /* our own padding, not in ref driver */
-
- /* 5GHz */
- __le16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5];
- u8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5];
- s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5];
-
- s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS];
- s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS];
- s8 tx_rate_limits_extreme_5[CONF_NUMBER_OF_RATE_GROUPS];
-
- s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5];
- s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS];
-
- /* FIXME: this is inconsistent with the types for 2.4GHz */
- s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS];
- s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
-
- u8 degraded_low_to_normal_threshold_5;
- u8 degraded_normal_to_high_threshold_5;
-
- u8 padding2[2];
+ u8 dyn_radio_params[WL1271_NVS_DYN_RADIO_PARAMS_SIZE];
+ u8 reserved;
+ u8 dyn_radio_params_5[WL1271_DYN_RADIO_PARAMS_5_SIZE];
} __attribute__ ((packed));
struct wl1271_cmd_cal_channel_tune {
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h
index 1993d63..6f9e75c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_conf.h
+++ b/drivers/net/wireless/wl12xx/wl1271_conf.h
@@ -735,81 +735,6 @@ enum single_dual_band_enum {
CONF_DUAL_BAND
};
-
-#define CONF_MAX_SMART_REFLEX_PARAMS 16
-
-struct conf_general_parms {
- /*
- * RF Reference Clock type / speed
- *
- * Range: CONF_REF_CLK_*
- */
- u8 ref_clk;
-
- /*
- * Settling time of the reference clock after boot.
- *
- * Range: u8
- */
- u8 settling_time;
-
- /*
- * Flag defining whether clock is valid on wakeup.
- *
- * Range: 0 - not valid on wakeup, 1 - valid on wakeup
- */
- u8 clk_valid_on_wakeup;
-
- /*
- * DC-to-DC mode.
- *
- * Range: Unknown
- */
- u8 dc2dcmode;
-
- /*
- * Flag defining whether used as single or dual-band.
- *
- * Range: CONF_SINGLE_BAND, CONF_DUAL_BAND
- */
- u8 single_dual_band;
-
- /*
- * TX bip fem autodetect flag.
- *
- * Range: Unknown
- */
- u8 tx_bip_fem_autodetect;
-
- /*
- * TX bip gem manufacturer.
- *
- * Range: Unknown
- */
- u8 tx_bip_fem_manufacturer;
-
- /*
- * Settings flags.
- *
- * Range: Unknown
- */
- u8 settings;
-
- /* Smart reflex settings */
- u8 sr_state;
-
- s8 srf1[CONF_MAX_SMART_REFLEX_PARAMS];
- s8 srf2[CONF_MAX_SMART_REFLEX_PARAMS];
- s8 srf3[CONF_MAX_SMART_REFLEX_PARAMS];
-
- s8 sr_debug_table[CONF_MAX_SMART_REFLEX_PARAMS];
-
- u8 sr_sen_n_p;
- u8 sr_sen_n_p_gain;
- u8 sr_sen_nrn;
- u8 sr_sen_prn;
-};
-
#define CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE 15
#define CONF_NUMBER_OF_SUB_BANDS_5 7
#define CONF_NUMBER_OF_RATE_GROUPS 6
@@ -818,78 +743,15 @@ struct conf_general_parms {
struct conf_radio_parms {
/*
- * Static radio parameters for 2.4GHz
- *
- * Range: unknown
- */
- u8 rx_trace_loss;
- u8 tx_trace_loss;
- s8 rx_rssi_and_proc_compens[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
-
- /*
- * Static radio parameters for 5GHz
- *
- * Range: unknown
- */
- u8 rx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
- u8 tx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
- s8 rx_rssi_and_proc_compens_5[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
-
- /*
- * Dynamic radio parameters for 2.4GHz
+ * FEM parameter set to use
*
- * Range: unknown
+ * Range: 0 or 1
*/
- u16 tx_ref_pd_voltage;
- u8 tx_ref_power;
- s8 tx_offset_db;
-
- s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS];
- s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS];
- s8 tx_rate_limits_extreme[CONF_NUMBER_OF_RATE_GROUPS];
-
- s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4];
- s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4];
- s8 tx_pdv_rate_offsets[CONF_NUMBER_OF_RATE_GROUPS];
-
- u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS];
- u8 rx_fem_insertion_loss;
-
- u8 degraded_low_to_normal_threshold;
- u8 degraded_normal_to_high_threshold;
-
-
- /*
- * Dynamic radio parameters for 5GHz
- *
- * Range: unknown
- */
- u16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5];
- u8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5];
- s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5];
-
- s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS];
- s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS];
- s8 tx_rate_limits_extreme_5[CONF_NUMBER_OF_RATE_GROUPS];
-
- s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5];
- s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS];
-
- /* FIXME: this is inconsistent with the types for 2.4GHz */
- s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS];
- s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
-
- u8 degraded_low_to_normal_threshold_5;
- u8 degraded_normal_to_high_threshold_5;
+ u8 fem;
};
struct conf_init_settings {
/*
- * Configure general parameters.
- */
- struct conf_general_parms genparam;
-
- /*
* Configure radio parameters.
*/
struct conf_radio_parms radioparam;
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 6f7a7d9..282c2bb 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -229,93 +229,8 @@ static struct conf_drv_settings default_conf = {
.psm_entry_retries = 3
},
.init = {
- .genparam = {
- .ref_clk = CONF_REF_CLK_38_4_E,
- .settling_time = 5,
- .clk_valid_on_wakeup = 0,
- .dc2dcmode = 0,
- .single_dual_band = CONF_SINGLE_BAND,
- .tx_bip_fem_autodetect = 1,
- .tx_bip_fem_manufacturer = 1,
- .settings = 1,
- .sr_state = 1,
- .srf1 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0,
- 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 },
- .srf2 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0,
- 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 },
- .srf3 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0,
- 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 },
- .sr_debug_table = { 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0 },
- .sr_sen_n_p = 0,
- .sr_sen_n_p_gain = 0,
- .sr_sen_nrn = 0,
- .sr_sen_prn = 0,
- },
.radioparam = {
- .rx_trace_loss = 0x24,
- .tx_trace_loss = 0x0,
- .rx_rssi_and_proc_compens = {
- 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8,
- 0xfc, 0x00, 0x80, 0x10, 0xf0, 0xf8,
- 0x00, 0x0a, 0x14 },
- .rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 },
- .tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 },
- .rx_rssi_and_proc_compens_5 = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00 },
- .tx_ref_pd_voltage = 0x1a9,
- .tx_ref_power = 0x80,
- .tx_offset_db = 0x0,
- .tx_rate_limits_normal = {
- 0x1d, 0x1f, 0x24, 0x28, 0x28, 0x29 },
- .tx_rate_limits_degraded = {
- 0x19, 0x1f, 0x22, 0x23, 0x27, 0x28 },
- .tx_rate_limits_extreme = {
- 0x19, 0x1c, 0x1e, 0x20, 0x24, 0x25 },
- .tx_channel_limits_11b = {
- 0x22, 0x50, 0x50, 0x50, 0x50, 0x50,
- 0x50, 0x50, 0x50, 0x50, 0x22, 0x50,
- 0x22, 0x50 },
- .tx_channel_limits_ofdm = {
- 0x20, 0x50, 0x50, 0x50, 0x50, 0x50,
- 0x50, 0x50, 0x50, 0x50, 0x20, 0x50,
- 0x20, 0x50 },
- .tx_pdv_rate_offsets = {
- 0x07, 0x08, 0x04, 0x02, 0x02, 0x00 },
- .tx_ibias = {
- 0x11, 0x11, 0x15, 0x11, 0x15, 0x0f },
- .rx_fem_insertion_loss = 0x0e,
- .degraded_low_to_normal_threshold = 0x1e,
- .degraded_normal_to_high_threshold = 0x2d,
- .tx_ref_pd_voltage_5 = {
- 0x0190, 0x01a4, 0x01c3, 0x01d8,
- 0x020a, 0x021c },
- .tx_ref_power_5 = {
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 },
- .tx_offset_db_5 = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
- .tx_rate_limits_normal_5 = {
- 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
- .tx_rate_limits_degraded_5 = {
- 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
- .tx_rate_limits_extreme_5 = {
- 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
- .tx_channel_limits_ofdm_5 = {
- 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
- 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
- 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
- 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
- 0x50, 0x50, 0x50 },
- .tx_pdv_rate_offsets_5 = {
- 0x01, 0x02, 0x02, 0x02, 0x02, 0x00 },
- .tx_ibias_5 = {
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },
- .rx_fem_insertion_loss_5 = {
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },
- .degraded_low_to_normal_threshold_5 = 0x00,
- .degraded_normal_to_high_threshold_5 = 0x00
+ .fem = 1,
}
},
.itrim = {
@@ -345,9 +260,6 @@ static void wl1271_conf_init(struct wl1271 *wl)
/* apply driver default configuration */
memcpy(&wl->conf, &default_conf, sizeof(default_conf));
-
- if (wl1271_11a_enabled())
- wl->conf.init.genparam.single_dual_band = CONF_DUAL_BAND;
}
@@ -567,15 +479,14 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
return ret;
}
- if (fw->size % 4) {
- wl1271_error("nvs size is not multiple of 32 bits: %zu",
- fw->size);
+ if (fw->size != sizeof(struct wl1271_nvs_file)) {
+ wl1271_error("nvs size is not as expected: %zu != %zu",
+ fw->size, sizeof(struct wl1271_nvs_file));
ret = -EILSEQ;
goto out;
}
- wl->nvs_len = fw->size;
- wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL);
+ wl->nvs = kmalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL);
if (!wl->nvs) {
wl1271_error("could not allocate memory for the nvs file");
@@ -583,7 +494,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
goto out;
}
- memcpy(wl->nvs, fw->data, wl->nvs_len);
+ memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file));
ret = 0;
--
1.6.3.3
From: Teemu Paasikivi <[email protected]>
In preparation for integration of SDIO implementation renamed some IO
functions from wl1271_spi_* form to wl1271_*.
Signed-off-by: Teemu Paasikivi <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_boot.c | 70 +++++++++++++--------------
drivers/net/wireless/wl12xx/wl1271_cmd.c | 15 +++---
drivers/net/wireless/wl12xx/wl1271_event.c | 9 ++--
drivers/net/wireless/wl12xx/wl1271_io.c | 24 +++++-----
drivers/net/wireless/wl12xx/wl1271_io.h | 29 +++++++++++
drivers/net/wireless/wl12xx/wl1271_main.c | 12 ++--
drivers/net/wireless/wl12xx/wl1271_ps.c | 1 +
drivers/net/wireless/wl12xx/wl1271_rx.c | 11 ++--
drivers/net/wireless/wl12xx/wl1271_spi.h | 30 ------------
drivers/net/wireless/wl12xx/wl1271_tx.c | 17 ++++---
10 files changed, 109 insertions(+), 109 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index fb3090c..2be76ee 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -27,6 +27,7 @@
#include "wl1271_reg.h"
#include "wl1271_boot.h"
#include "wl1271_spi.h"
+#include "wl1271_io.h"
#include "wl1271_event.h"
static struct wl1271_partition_set part_table[PART_TABLE_LEN] = {
@@ -93,19 +94,19 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
u32 cpu_ctrl;
/* 10.5.0 run the firmware (I) */
- cpu_ctrl = wl1271_spi_read32(wl, ACX_REG_ECPU_CONTROL);
+ cpu_ctrl = wl1271_read32(wl, ACX_REG_ECPU_CONTROL);
/* 10.5.1 run the firmware (II) */
cpu_ctrl |= flag;
- wl1271_spi_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
+ wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
}
static void wl1271_boot_fw_version(struct wl1271 *wl)
{
struct wl1271_static_data static_data;
- wl1271_spi_read(wl, wl->cmd_box_addr,
- &static_data, sizeof(static_data), false);
+ wl1271_read(wl, wl->cmd_box_addr, &static_data, sizeof(static_data),
+ false);
strncpy(wl->chip.fw_ver, static_data.fw_version,
sizeof(wl->chip.fw_ver));
@@ -164,7 +165,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
memcpy(chunk, p, CHUNK_SIZE);
wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
p, addr);
- wl1271_spi_write(wl, addr, chunk, CHUNK_SIZE, false);
+ wl1271_write(wl, addr, chunk, CHUNK_SIZE, false);
chunk_num++;
}
@@ -175,7 +176,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
memcpy(chunk, p, fw_data_len % CHUNK_SIZE);
wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x",
fw_data_len % CHUNK_SIZE, p, addr);
- wl1271_spi_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false);
+ wl1271_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false);
kfree(chunk);
return 0;
@@ -256,7 +257,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
wl1271_debug(DEBUG_BOOT,
"nvs burst write 0x%x: 0x%x",
dest_addr, val);
- wl1271_spi_write32(wl, dest_addr, val);
+ wl1271_write32(wl, dest_addr, val);
nvs_ptr += 4;
dest_addr += 4;
@@ -290,7 +291,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
/* FIXME: In wl1271, we upload everything at once.
No endianness handling needed here?! The ref driver doesn't do
anything about it at this point */
- wl1271_spi_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false);
+ wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false);
kfree(nvs_aligned);
return 0;
@@ -299,9 +300,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
static void wl1271_boot_enable_interrupts(struct wl1271 *wl)
{
enable_irq(wl->irq);
- wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK,
- WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
- wl1271_spi_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
+ wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
+ WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
+ wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
}
static int wl1271_boot_soft_reset(struct wl1271 *wl)
@@ -310,13 +311,12 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl)
u32 boot_data;
/* perform soft reset */
- wl1271_spi_write32(wl, ACX_REG_SLV_SOFT_RESET,
- ACX_SLV_SOFT_RESET_BIT);
+ wl1271_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
/* SOFT_RESET is self clearing */
timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
while (1) {
- boot_data = wl1271_spi_read32(wl, ACX_REG_SLV_SOFT_RESET);
+ boot_data = wl1271_read32(wl, ACX_REG_SLV_SOFT_RESET);
wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
break;
@@ -332,10 +332,10 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl)
}
/* disable Rx/Tx */
- wl1271_spi_write32(wl, ENABLE, 0x0);
+ wl1271_write32(wl, ENABLE, 0x0);
/* disable auto calibration on start*/
- wl1271_spi_write32(wl, SPARE_A2, 0xffff);
+ wl1271_write32(wl, SPARE_A2, 0xffff);
return 0;
}
@@ -347,7 +347,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
- chip_id = wl1271_spi_read32(wl, CHIP_ID_B);
+ chip_id = wl1271_read32(wl, CHIP_ID_B);
wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
@@ -360,8 +360,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
loop = 0;
while (loop++ < INIT_LOOP) {
udelay(INIT_LOOP_DELAY);
- interrupt = wl1271_spi_read32(wl,
- ACX_REG_INTERRUPT_NO_CLEAR);
+ interrupt = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
if (interrupt == 0xffffffff) {
wl1271_error("error reading hardware complete "
@@ -370,8 +369,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
}
/* check that ACX_INTR_INIT_COMPLETE is enabled */
else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) {
- wl1271_spi_write32(wl, ACX_REG_INTERRUPT_ACK,
- WL1271_ACX_INTR_INIT_COMPLETE);
+ wl1271_write32(wl, ACX_REG_INTERRUPT_ACK,
+ WL1271_ACX_INTR_INIT_COMPLETE);
break;
}
}
@@ -383,10 +382,10 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
}
/* get hardware config command mail box */
- wl->cmd_box_addr = wl1271_spi_read32(wl, REG_COMMAND_MAILBOX_PTR);
+ wl->cmd_box_addr = wl1271_read32(wl, REG_COMMAND_MAILBOX_PTR);
/* get hardware config event mail box */
- wl->event_box_addr = wl1271_spi_read32(wl, REG_EVENT_MAILBOX_PTR);
+ 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]);
@@ -459,9 +458,9 @@ int wl1271_boot(struct wl1271 *wl)
wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val);
}
- wl1271_spi_write32(wl, PLL_PARAMETERS, clk);
+ wl1271_write32(wl, PLL_PARAMETERS, clk);
- pause = wl1271_spi_read32(wl, PLL_PARAMETERS);
+ pause = wl1271_read32(wl, PLL_PARAMETERS);
wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);
@@ -470,10 +469,10 @@ int wl1271_boot(struct wl1271 *wl)
* 0x3ff (magic number ). How does
* this work?! */
pause |= WU_COUNTER_PAUSE_VAL;
- wl1271_spi_write32(wl, WU_COUNTER_PAUSE, pause);
+ wl1271_write32(wl, WU_COUNTER_PAUSE, pause);
/* Continue the ELP wake up sequence */
- wl1271_spi_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
+ wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
udelay(500);
wl1271_set_partition(wl, &part_table[PART_DRPW]);
@@ -483,18 +482,18 @@ int wl1271_boot(struct wl1271 *wl)
before taking DRPw out of reset */
wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START);
- clk = wl1271_spi_read32(wl, DRPW_SCRATCH_START);
+ clk = wl1271_read32(wl, DRPW_SCRATCH_START);
wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
/* 2 */
clk |= (REF_CLOCK << 1) << 4;
- wl1271_spi_write32(wl, DRPW_SCRATCH_START, clk);
+ wl1271_write32(wl, DRPW_SCRATCH_START, clk);
wl1271_set_partition(wl, &part_table[PART_WORK]);
/* Disable interrupts */
- wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
+ wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
ret = wl1271_boot_soft_reset(wl);
if (ret < 0)
@@ -509,23 +508,22 @@ int wl1271_boot(struct wl1271 *wl)
* ACX_EEPROMLESS_IND_REG */
wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG");
- wl1271_spi_write32(wl, ACX_EEPROMLESS_IND_REG,
- ACX_EEPROMLESS_IND_REG);
+ wl1271_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG);
- tmp = wl1271_spi_read32(wl, CHIP_ID_B);
+ tmp = wl1271_read32(wl, CHIP_ID_B);
wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
/* 6. read the EEPROM parameters */
- tmp = wl1271_spi_read32(wl, SCR_PAD2);
+ tmp = wl1271_read32(wl, SCR_PAD2);
ret = wl1271_boot_write_irq_polarity(wl);
if (ret < 0)
goto out;
/* FIXME: Need to check whether this is really what we want */
- wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK,
- WL1271_ACX_ALL_EVENTS_VECTOR);
+ wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
+ WL1271_ACX_ALL_EVENTS_VECTOR);
/* WL1271: The reference driver skips steps 7 to 10 (jumps directly
* to upload_fw) */
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 54b5124..36a64e0 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -30,6 +30,7 @@
#include "wl1271.h"
#include "wl1271_reg.h"
#include "wl1271_spi.h"
+#include "wl1271_io.h"
#include "wl1271_acx.h"
#include "wl12xx_80211.h"
#include "wl1271_cmd.h"
@@ -57,13 +58,13 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
WARN_ON(len % 4 != 0);
- wl1271_spi_write(wl, wl->cmd_box_addr, buf, len, false);
+ wl1271_write(wl, wl->cmd_box_addr, buf, len, false);
- wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);
+ wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);
timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT);
- intr = wl1271_spi_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+ intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) {
if (time_after(jiffies, timeout)) {
wl1271_error("command complete timeout");
@@ -73,13 +74,13 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
msleep(1);
- intr = wl1271_spi_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+ intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
}
/* read back the status code of the command */
if (res_len == 0)
res_len = sizeof(struct wl1271_cmd_header);
- wl1271_spi_read(wl, wl->cmd_box_addr, cmd, res_len, false);
+ wl1271_read(wl, wl->cmd_box_addr, cmd, res_len, false);
status = le16_to_cpu(cmd->status);
if (status != CMD_STATUS_SUCCESS) {
@@ -87,8 +88,8 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
ret = -EIO;
}
- wl1271_spi_write32(wl, ACX_REG_INTERRUPT_ACK,
- WL1271_ACX_INTR_CMD_COMPLETE);
+ wl1271_write32(wl, ACX_REG_INTERRUPT_ACK,
+ WL1271_ACX_INTR_CMD_COMPLETE);
out:
return ret;
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
index 2803e70..7468ef1 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -24,6 +24,7 @@
#include "wl1271.h"
#include "wl1271_reg.h"
#include "wl1271_spi.h"
+#include "wl1271_io.h"
#include "wl1271_event.h"
#include "wl1271_ps.h"
#include "wl12xx_80211.h"
@@ -214,7 +215,7 @@ int wl1271_event_unmask(struct wl1271 *wl)
void wl1271_event_mbox_config(struct wl1271 *wl)
{
- wl->mbox_ptr[0] = wl1271_spi_read32(wl, REG_EVENT_MAILBOX_PTR);
+ wl->mbox_ptr[0] = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR);
wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);
wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x",
@@ -232,8 +233,8 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
return -EINVAL;
/* first we read the mbox descriptor */
- wl1271_spi_read(wl, wl->mbox_ptr[mbox_num], &mbox,
- sizeof(struct event_mailbox), false);
+ wl1271_read(wl, wl->mbox_ptr[mbox_num], &mbox,
+ sizeof(struct event_mailbox), false);
/* process the descriptor */
ret = wl1271_event_process(wl, &mbox);
@@ -241,7 +242,7 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
return ret;
/* then we let the firmware know it can go on...*/
- wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
+ wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
return 0;
}
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.c b/drivers/net/wireless/wl12xx/wl1271_io.c
index dcb588b..00f98bd 100644
--- a/drivers/net/wireless/wl12xx/wl1271_io.c
+++ b/drivers/net/wireless/wl12xx/wl1271_io.c
@@ -124,10 +124,10 @@ void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf,
void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf,
size_t len, bool fixed)
{
- wl1271_spi_read(wl, addr, buf, len, fixed);
+ wl1271_spi_raw_read(wl, addr, buf, len, fixed);
}
-void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len,
+void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len,
bool fixed)
{
int physical;
@@ -137,8 +137,8 @@ void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len,
wl1271_spi_raw_read(wl, physical, buf, len, fixed);
}
-void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len,
- bool fixed)
+void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len,
+ bool fixed)
{
int physical;
@@ -147,12 +147,12 @@ void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len,
wl1271_spi_raw_write(wl, physical, buf, len, fixed);
}
-u32 wl1271_spi_read32(struct wl1271 *wl, int addr)
+u32 wl1271_read32(struct wl1271 *wl, int addr)
{
return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr));
}
-void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val)
+void wl1271_write32(struct wl1271 *wl, int addr, u32 val)
{
wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val);
}
@@ -161,13 +161,13 @@ void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val)
{
/* write address >> 1 + 0x30000 to OCP_POR_CTR */
addr = (addr >> 1) + 0x30000;
- wl1271_spi_write32(wl, OCP_POR_CTR, addr);
+ wl1271_write32(wl, OCP_POR_CTR, addr);
/* write value to OCP_POR_WDATA */
- wl1271_spi_write32(wl, OCP_DATA_WRITE, val);
+ wl1271_write32(wl, OCP_DATA_WRITE, val);
/* write 1 to OCP_CMD */
- wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_WRITE);
+ wl1271_write32(wl, OCP_CMD, OCP_CMD_WRITE);
}
u16 wl1271_top_reg_read(struct wl1271 *wl, int addr)
@@ -177,14 +177,14 @@ u16 wl1271_top_reg_read(struct wl1271 *wl, int addr)
/* write address >> 1 + 0x30000 to OCP_POR_CTR */
addr = (addr >> 1) + 0x30000;
- wl1271_spi_write32(wl, OCP_POR_CTR, addr);
+ wl1271_write32(wl, OCP_POR_CTR, addr);
/* write 2 to OCP_CMD */
- wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_READ);
+ wl1271_write32(wl, OCP_CMD, OCP_CMD_READ);
/* poll for data ready */
do {
- val = wl1271_spi_read32(wl, OCP_DATA_READ);
+ val = wl1271_read32(wl, OCP_DATA_READ);
} while (!(val & OCP_READY_MASK) && --timeout);
if (!timeout) {
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h
index 2dc6abb..859d571 100644
--- a/drivers/net/wireless/wl12xx/wl1271_io.h
+++ b/drivers/net/wireless/wl12xx/wl1271_io.h
@@ -34,4 +34,33 @@ void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf,
void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf,
size_t len, bool fixed);
+/* Translated target IO */
+void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len,
+ bool fixed);
+void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len,
+ bool fixed);
+u32 wl1271_read32(struct wl1271 *wl, int addr);
+void wl1271_write32(struct wl1271 *wl, int addr, u32 val);
+
+/* Top Register IO */
+void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val);
+u16 wl1271_top_reg_read(struct wl1271 *wl, int addr);
+
+int wl1271_set_partition(struct wl1271 *wl,
+ struct wl1271_partition_set *p);
+
+static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr)
+{
+ wl1271_raw_read(wl, addr, &wl->buffer_32,
+ sizeof(wl->buffer_32), false);
+
+ return wl->buffer_32;
+}
+
+static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val)
+{
+ wl->buffer_32 = val;
+ wl1271_raw_write(wl, addr, &wl->buffer_32,
+ sizeof(wl->buffer_32), false);
+}
#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index aa8f79c..4696895 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -38,6 +38,7 @@
#include "wl12xx_80211.h"
#include "wl1271_reg.h"
#include "wl1271_spi.h"
+#include "wl1271_io.h"
#include "wl1271_event.h"
#include "wl1271_tx.h"
#include "wl1271_rx.h"
@@ -386,8 +387,7 @@ static void wl1271_fw_status(struct wl1271 *wl,
u32 total = 0;
int i;
- wl1271_spi_read(wl, FW_STATUS_ADDR, status,
- sizeof(*status), false);
+ wl1271_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false);
wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
"drv_rx_counter = %d, tx_results_counter = %d)",
@@ -434,7 +434,7 @@ static void wl1271_irq_work(struct work_struct *work)
if (ret < 0)
goto out;
- wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
+ wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
wl1271_fw_status(wl, wl->fw_status);
intr = le32_to_cpu(wl->fw_status->intr);
@@ -476,8 +476,8 @@ static void wl1271_irq_work(struct work_struct *work)
}
out_sleep:
- wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK,
- WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
+ wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
+ WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
wl1271_ps_elp_sleep(wl);
out:
@@ -664,7 +664,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
/* whal_FwCtrl_BootSm() */
/* 0. read chip id from CHIP_ID */
- wl->chip.id = wl1271_spi_read32(wl, CHIP_ID_B);
+ wl->chip.id = wl1271_read32(wl, CHIP_ID_B);
/* 1. check if chip id is valid */
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c
index 29f6700..e2b1ebf 100644
--- a/drivers/net/wireless/wl12xx/wl1271_ps.c
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.c
@@ -24,6 +24,7 @@
#include "wl1271_reg.h"
#include "wl1271_ps.h"
#include "wl1271_spi.h"
+#include "wl1271_io.h"
#define WL1271_WAKEUP_TIMEOUT 500
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c
index e8eee88..6730f5b 100644
--- a/drivers/net/wireless/wl12xx/wl1271_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.c
@@ -26,6 +26,7 @@
#include "wl1271_reg.h"
#include "wl1271_rx.h"
#include "wl1271_spi.h"
+#include "wl1271_io.h"
static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status,
u32 drv_rx_counter)
@@ -166,7 +167,7 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
}
buf = skb_put(skb, length);
- wl1271_spi_read(wl, WL1271_SLV_MEM_DATA, buf, length, true);
+ wl1271_read(wl, WL1271_SLV_MEM_DATA, buf, length, true);
/* the data read starts with the descriptor */
desc = (struct wl1271_rx_descriptor *) buf;
@@ -210,15 +211,13 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
wl->rx_mem_pool_addr.addr + 4;
/* Choose the block we want to read */
- wl1271_spi_write(wl, WL1271_SLV_REG_DATA,
- &wl->rx_mem_pool_addr,
- sizeof(wl->rx_mem_pool_addr), false);
+ wl1271_write(wl, WL1271_SLV_REG_DATA, &wl->rx_mem_pool_addr,
+ sizeof(wl->rx_mem_pool_addr), false);
wl1271_rx_handle_data(wl, buf_size);
wl->rx_counter++;
drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
- wl1271_spi_write32(wl, RX_DRIVER_COUNTER_ADDRESS,
- wl->rx_counter);
+ wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
}
}
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.h b/drivers/net/wireless/wl12xx/wl1271_spi.h
index cb7df1c..a803596 100644
--- a/drivers/net/wireless/wl12xx/wl1271_spi.h
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.h
@@ -90,37 +90,7 @@ void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf,
void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf,
size_t len, bool fixed);
-/* Translated target IO */
-void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len,
- bool fixed);
-void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len,
- bool fixed);
-u32 wl1271_spi_read32(struct wl1271 *wl, int addr);
-void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val);
-
-/* Top Register IO */
-void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val);
-u16 wl1271_top_reg_read(struct wl1271 *wl, int addr);
-
/* INIT and RESET words */
void wl1271_spi_reset(struct wl1271 *wl);
void wl1271_spi_init(struct wl1271 *wl);
-int wl1271_set_partition(struct wl1271 *wl,
- struct wl1271_partition_set *p);
-
-static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr)
-{
- wl1271_spi_raw_read(wl, addr, &wl->buffer_32,
- sizeof(wl->buffer_32), false);
-
- return wl->buffer_32;
-}
-
-static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val)
-{
- wl->buffer_32 = val;
- wl1271_spi_raw_write(wl, addr, &wl->buffer_32,
- sizeof(wl->buffer_32), false);
-}
-
#endif /* __WL1271_SPI_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
index f9e0638..811e739 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -26,6 +26,7 @@
#include "wl1271.h"
#include "wl1271_spi.h"
+#include "wl1271_io.h"
#include "wl1271_reg.h"
#include "wl1271_ps.h"
#include "wl1271_tx.h"
@@ -165,11 +166,11 @@ static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb,
len = WL1271_TX_ALIGN(skb->len);
/* perform a fixed address block write with the packet */
- wl1271_spi_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true);
+ wl1271_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true);
/* write packet new counter into the write access register */
wl->tx_packets_count++;
- wl1271_spi_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count);
+ wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count);
desc = (struct wl1271_tx_hw_descr *) skb->data;
wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)",
@@ -375,8 +376,8 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count)
wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count);
/* read the tx results from the chipset */
- wl1271_spi_read(wl, le32_to_cpu(memmap->tx_result),
- wl->tx_res_if, sizeof(*wl->tx_res_if), false);
+ wl1271_read(wl, le32_to_cpu(memmap->tx_result),
+ wl->tx_res_if, sizeof(*wl->tx_res_if), false);
/* verify that the result buffer is not getting overrun */
if (count > TX_HW_RESULT_QUEUE_LEN) {
@@ -397,10 +398,10 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count)
}
/* write host counter to chipset (to ack) */
- wl1271_spi_write32(wl, le32_to_cpu(memmap->tx_result) +
- offsetof(struct wl1271_tx_hw_res_if,
- tx_result_host_counter),
- le32_to_cpu(wl->tx_res_if->tx_result_fw_counter));
+ wl1271_write32(wl, le32_to_cpu(memmap->tx_result) +
+ offsetof(struct wl1271_tx_hw_res_if,
+ tx_result_host_counter),
+ le32_to_cpu(wl->tx_res_if->tx_result_fw_counter));
}
/* caller must hold wl->mutex */
--
1.6.3.3
WEP key index handling was broken: the default key when using key 0 was never
specified to the FW, and if using other default than 0, it would be set on the
TX path for every single TX'd frame.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Kalle Valo <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_main.c | 8 ++++++++
drivers/net/wireless/wl12xx/wl1271_tx.c | 1 +
2 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 4a0a15b..459d9a0 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1475,6 +1475,14 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
wl1271_error("Could not add or replace key");
goto out_sleep;
}
+
+ /* the default WEP key needs to be configured at least once */
+ if (key_type == KEY_WEP) {
+ ret = wl1271_cmd_set_default_wep_key(wl,
+ wl->default_key);
+ if (ret < 0)
+ goto out_sleep;
+ }
break;
case DISABLE_KEY:
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
index f6815a9..f9e0638 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -203,6 +203,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb)
ret = wl1271_cmd_set_default_wep_key(wl, idx);
if (ret < 0)
return ret;
+ wl->default_key = idx;
}
}
--
1.6.3.3
If reverting to a random MAC address, the driver would not update it to the
NVS file, and hence the firmware frame filtering would not work properly.
So update the randomized MAC address to the NVS image.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Kalle Valo <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_main.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index e698dec..c7f5191 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -562,6 +562,14 @@ static int wl1271_update_mac_addr(struct wl1271 *wl)
static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
memcpy(wl->mac_addr, nokia_oui, 3);
get_random_bytes(wl->mac_addr + 3, 3);
+
+ /* update this address to the 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];
}
SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
--
1.6.3.3
From: Luciano Coelho <[email protected]>
Our NVS uploading mechanism had a bug that was causing it to pass three extra
zeros at the start of the NVS. This may be a problem in the NVS generation
application, but for now we fix it in the driver.
Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_boot.c | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index 57ba78d..fb3090c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -277,9 +277,14 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
wl1271_set_partition(wl, &part_table[PART_WORK]);
/* Copy the NVS tables to a new block to ensure alignment */
- nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
- if (!nvs_aligned)
- return -ENOMEM;
+ /* FIXME: We jump 3 more bytes before uploading the NVS. It seems
+ that our NVS files have three extra zeros here. I'm not sure whether
+ the problem is in our NVS generation or we should really jumpt these
+ 3 bytes here */
+ nvs_ptr += 3;
+
+ nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); if
+ (!nvs_aligned) return -ENOMEM;
/* And finally we upload the NVS tables */
/* FIXME: In wl1271, we upload everything at once.
--
1.6.3.3
From: Teemu Paasikivi <[email protected]>
In prepraration for integration of SDIO implementation moved some IO
functions common for SPI and SDIO to separate file.
Signed-off-by: Teemu Paasikivi <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
---
drivers/net/wireless/wl12xx/Makefile | 3 +-
drivers/net/wireless/wl12xx/wl1271_io.c | 203 ++++++++++++++++++++++++++++++
drivers/net/wireless/wl12xx/wl1271_io.h | 37 ++++++
drivers/net/wireless/wl12xx/wl1271_spi.c | 157 -----------------------
4 files changed, 242 insertions(+), 158 deletions(-)
create mode 100644 drivers/net/wireless/wl12xx/wl1271_io.c
create mode 100644 drivers/net/wireless/wl12xx/wl1271_io.h
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile
index d089b5d..f47ec94 100644
--- a/drivers/net/wireless/wl12xx/Makefile
+++ b/drivers/net/wireless/wl12xx/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o
wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \
wl1271_event.o wl1271_tx.o wl1271_rx.o \
wl1271_ps.o wl1271_acx.o wl1271_boot.o \
- wl1271_init.o wl1271_debugfs.o
+ wl1271_init.o wl1271_debugfs.o wl1271_io.o
+
wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o
obj-$(CONFIG_WL1271) += wl1271.o
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.c b/drivers/net/wireless/wl12xx/wl1271_io.c
new file mode 100644
index 0000000..dcb588b
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_io.c
@@ -0,0 +1,203 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/crc7.h>
+#include <linux/spi/spi.h>
+
+#include "wl1271.h"
+#include "wl12xx_80211.h"
+#include "wl1271_spi.h"
+#include "wl1271_io.h"
+
+static int wl1271_translate_addr(struct wl1271 *wl, int addr)
+{
+ /*
+ * To translate, first check to which window of addresses the
+ * particular address belongs. Then subtract the starting address
+ * of that window from the address. Then, add offset of the
+ * translated region.
+ *
+ * The translated regions occur next to each other in physical device
+ * memory, so just add the sizes of the preceeding address regions to
+ * get the offset to the new region.
+ *
+ * Currently, only the two first regions are addressed, and the
+ * assumption is that all addresses will fall into either of those
+ * two.
+ */
+ if ((addr >= wl->part.reg.start) &&
+ (addr < wl->part.reg.start + wl->part.reg.size))
+ return addr - wl->part.reg.start + wl->part.mem.size;
+ else
+ return addr - wl->part.mem.start;
+}
+
+/* Set the SPI partitions to access the chip addresses
+ *
+ * To simplify driver code, a fixed (virtual) memory map is defined for
+ * register and memory addresses. Because in the chipset, in different stages
+ * of operation, those addresses will move around, an address translation
+ * mechanism is required.
+ *
+ * There are four partitions (three memory and one register partition),
+ * which are mapped to two different areas of the hardware memory.
+ *
+ * Virtual address
+ * space
+ *
+ * | |
+ * ...+----+--> mem.start
+ * Physical address ... | |
+ * space ... | | [PART_0]
+ * ... | |
+ * 00000000 <--+----+... ...+----+--> mem.start + mem.size
+ * | | ... | |
+ * |MEM | ... | |
+ * | | ... | |
+ * mem.size <--+----+... | | {unused area)
+ * | | ... | |
+ * |REG | ... | |
+ * mem.size | | ... | |
+ * + <--+----+... ...+----+--> reg.start
+ * reg.size | | ... | |
+ * |MEM2| ... | | [PART_1]
+ * | | ... | |
+ * ...+----+--> reg.start + reg.size
+ * | |
+ *
+ */
+int wl1271_set_partition(struct wl1271 *wl,
+ struct wl1271_partition_set *p)
+{
+ /* copy partition info */
+ memcpy(&wl->part, p, sizeof(*p));
+
+ wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
+ p->mem.start, p->mem.size);
+ wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
+ p->reg.start, p->reg.size);
+ wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X",
+ p->mem2.start, p->mem2.size);
+ wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X",
+ p->mem3.start, p->mem3.size);
+
+ /* write partition info to the chipset */
+ wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start);
+ wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size);
+ wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start);
+ wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size);
+ wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start);
+ wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size);
+ wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start);
+
+ return 0;
+}
+
+void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf,
+ size_t len, bool fixed)
+{
+ wl1271_spi_raw_write(wl, addr, buf, len, fixed);
+}
+
+void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf,
+ size_t len, bool fixed)
+{
+ wl1271_spi_read(wl, addr, buf, len, fixed);
+}
+
+void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len,
+ bool fixed)
+{
+ int physical;
+
+ physical = wl1271_translate_addr(wl, addr);
+
+ wl1271_spi_raw_read(wl, physical, buf, len, fixed);
+}
+
+void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len,
+ bool fixed)
+{
+ int physical;
+
+ physical = wl1271_translate_addr(wl, addr);
+
+ wl1271_spi_raw_write(wl, physical, buf, len, fixed);
+}
+
+u32 wl1271_spi_read32(struct wl1271 *wl, int addr)
+{
+ return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr));
+}
+
+void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val)
+{
+ wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val);
+}
+
+void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val)
+{
+ /* write address >> 1 + 0x30000 to OCP_POR_CTR */
+ addr = (addr >> 1) + 0x30000;
+ wl1271_spi_write32(wl, OCP_POR_CTR, addr);
+
+ /* write value to OCP_POR_WDATA */
+ wl1271_spi_write32(wl, OCP_DATA_WRITE, val);
+
+ /* write 1 to OCP_CMD */
+ wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_WRITE);
+}
+
+u16 wl1271_top_reg_read(struct wl1271 *wl, int addr)
+{
+ u32 val;
+ int timeout = OCP_CMD_LOOP;
+
+ /* write address >> 1 + 0x30000 to OCP_POR_CTR */
+ addr = (addr >> 1) + 0x30000;
+ wl1271_spi_write32(wl, OCP_POR_CTR, addr);
+
+ /* write 2 to OCP_CMD */
+ wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_READ);
+
+ /* poll for data ready */
+ do {
+ val = wl1271_spi_read32(wl, OCP_DATA_READ);
+ } while (!(val & OCP_READY_MASK) && --timeout);
+
+ if (!timeout) {
+ wl1271_warning("Top register access timed out.");
+ return 0xffff;
+ }
+
+ /* check data status and return if OK */
+ if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK)
+ return val & 0xffff;
+ else {
+ wl1271_warning("Top register access returned error.");
+ return 0xffff;
+ }
+}
+
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h
new file mode 100644
index 0000000..2dc6abb
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_io.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL1271_IO_H__
+#define __WL1271_IO_H__
+
+struct wl1271;
+
+
+/* Raw target IO, address is not translated */
+void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf,
+ size_t len, bool fixed);
+void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf,
+ size_t len, bool fixed);
+
+#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c
index ee9564a..67a8293 100644
--- a/drivers/net/wireless/wl12xx/wl1271_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.c
@@ -30,28 +30,6 @@
#include "wl12xx_80211.h"
#include "wl1271_spi.h"
-static int wl1271_translate_addr(struct wl1271 *wl, int addr)
-{
- /*
- * To translate, first check to which window of addresses the
- * particular address belongs. Then subtract the starting address
- * of that window from the address. Then, add offset of the
- * translated region.
- *
- * The translated regions occur next to each other in physical device
- * memory, so just add the sizes of the preceeding address regions to
- * get the offset to the new region.
- *
- * Currently, only the two first regions are addressed, and the
- * assumption is that all addresses will fall into either of those
- * two.
- */
- if ((addr >= wl->part.reg.start) &&
- (addr < wl->part.reg.start + wl->part.reg.size))
- return addr - wl->part.reg.start + wl->part.mem.size;
- else
- return addr - wl->part.mem.start;
-}
void wl1271_spi_reset(struct wl1271 *wl)
{
@@ -133,67 +111,6 @@ void wl1271_spi_init(struct wl1271 *wl)
wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
}
-/* Set the SPI partitions to access the chip addresses
- *
- * To simplify driver code, a fixed (virtual) memory map is defined for
- * register and memory addresses. Because in the chipset, in different stages
- * of operation, those addresses will move around, an address translation
- * mechanism is required.
- *
- * There are four partitions (three memory and one register partition),
- * which are mapped to two different areas of the hardware memory.
- *
- * Virtual address
- * space
- *
- * | |
- * ...+----+--> mem.start
- * Physical address ... | |
- * space ... | | [PART_0]
- * ... | |
- * 00000000 <--+----+... ...+----+--> mem.start + mem.size
- * | | ... | |
- * |MEM | ... | |
- * | | ... | |
- * mem.size <--+----+... | | {unused area)
- * | | ... | |
- * |REG | ... | |
- * mem.size | | ... | |
- * + <--+----+... ...+----+--> reg.start
- * reg.size | | ... | |
- * |MEM2| ... | | [PART_1]
- * | | ... | |
- * ...+----+--> reg.start + reg.size
- * | |
- *
- */
-int wl1271_set_partition(struct wl1271 *wl,
- struct wl1271_partition_set *p)
-{
- /* copy partition info */
- memcpy(&wl->part, p, sizeof(*p));
-
- wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
- p->mem.start, p->mem.size);
- wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
- p->reg.start, p->reg.size);
- wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X",
- p->mem2.start, p->mem2.size);
- wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X",
- p->mem3.start, p->mem3.size);
-
- /* write partition info to the chipset */
- wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start);
- wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size);
- wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start);
- wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size);
- wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start);
- wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size);
- wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start);
-
- return 0;
-}
-
#define WL1271_BUSY_WORD_TIMEOUT 1000
/* FIXME: Check busy words, removed due to SPI bug */
@@ -338,77 +255,3 @@ void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf,
wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
}
-
-void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len,
- bool fixed)
-{
- int physical;
-
- physical = wl1271_translate_addr(wl, addr);
-
- wl1271_spi_raw_read(wl, physical, buf, len, fixed);
-}
-
-void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len,
- bool fixed)
-{
- int physical;
-
- physical = wl1271_translate_addr(wl, addr);
-
- wl1271_spi_raw_write(wl, physical, buf, len, fixed);
-}
-
-u32 wl1271_spi_read32(struct wl1271 *wl, int addr)
-{
- return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr));
-}
-
-void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val)
-{
- wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val);
-}
-
-void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val)
-{
- /* write address >> 1 + 0x30000 to OCP_POR_CTR */
- addr = (addr >> 1) + 0x30000;
- wl1271_spi_write32(wl, OCP_POR_CTR, addr);
-
- /* write value to OCP_POR_WDATA */
- wl1271_spi_write32(wl, OCP_DATA_WRITE, val);
-
- /* write 1 to OCP_CMD */
- wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_WRITE);
-}
-
-u16 wl1271_top_reg_read(struct wl1271 *wl, int addr)
-{
- u32 val;
- int timeout = OCP_CMD_LOOP;
-
- /* write address >> 1 + 0x30000 to OCP_POR_CTR */
- addr = (addr >> 1) + 0x30000;
- wl1271_spi_write32(wl, OCP_POR_CTR, addr);
-
- /* write 2 to OCP_CMD */
- wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_READ);
-
- /* poll for data ready */
- do {
- val = wl1271_spi_read32(wl, OCP_DATA_READ);
- } while (!(val & OCP_READY_MASK) && --timeout);
-
- if (!timeout) {
- wl1271_warning("Top register access timed out.");
- return 0xffff;
- }
-
- /* check data status and return if OK */
- if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK)
- return val & 0xffff;
- else {
- wl1271_warning("Top register access returned error.");
- return 0xffff;
- }
-}
--
1.6.3.3
The beacon filter table configuration ACX structure had certain elements
reversed, resulting in firmware instability in regard of the feature. Fix
the structure.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Kalle Valo <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_acx.h | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index ac94a13..aeccc98 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -2,7 +2,7 @@
* This file is part of wl1271
*
* Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
- * Copyright (C) 2008-2009 Nokia Corporation
+ * Copyright (C) 2008-2010 Nokia Corporation
*
* Contact: Luciano Coelho <[email protected]>
*
@@ -348,7 +348,7 @@ struct acx_beacon_filter_option {
* ACXBeaconFilterEntry (not 221)
* Byte Offset Size (Bytes) Definition
* =========== ============ ==========
- * 0 1 IE identifier
+ * 0 1 IE identifier
* 1 1 Treatment bit mask
*
* ACXBeaconFilterEntry (221)
@@ -381,8 +381,8 @@ struct acx_beacon_filter_ie_table {
struct acx_header header;
u8 num_ie;
- u8 table[BEACON_FILTER_TABLE_MAX_SIZE];
u8 pad[3];
+ u8 table[BEACON_FILTER_TABLE_MAX_SIZE];
} __attribute__ ((packed));
struct acx_conn_monit_params {
--
1.6.3.3
This patch adds code to extract the SSID from the beacon template used for
ad-hoc. The mac80211 currently does not provide the SSID, so this is a
workaround for that, for now.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_event.c | 10 +++-
drivers/net/wireless/wl12xx/wl1271_main.c | 69 +++++++++++++++++----------
2 files changed, 51 insertions(+), 28 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
index cecbae2..2803e70 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -92,7 +92,12 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
true);
} else {
wl1271_error("PSM entry failed, giving up.\n");
- /* make sure the firmware goes into active mode */
+ /* FIXME: this may need to be reconsidered. for now it
+ is not possible to indicate to the mac80211
+ afterwards that PSM entry failed. To maximize
+ functionality (receiving data and remaining
+ associated) make sure that we are in sync with the
+ AP in regard of PSM mode. */
ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
false);
wl->psm_entry_retry = 0;
@@ -124,7 +129,8 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
break;
}
- /* make sure the firmware goes to active mode */
+ /* make sure the firmware goes to active mode - the frame to
+ be sent next will indicate to the AP, that we are active. */
ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
false);
break;
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 8b46b70..a3742c8 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1549,6 +1549,23 @@ out:
return ret;
}
+static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *beacon)
+{
+ u8 *ptr = beacon->data +
+ offsetof(struct ieee80211_mgmt, u.beacon.variable);
+
+ /* find the location of the ssid in the beacon */
+ while (ptr < beacon->data + beacon->len) {
+ if (ptr[0] == WLAN_EID_SSID) {
+ wl->ssid_len = ptr[1];
+ memcpy(wl->ssid, ptr+2, wl->ssid_len);
+ return;
+ }
+ ptr += ptr[1];
+ }
+ wl1271_error("ad-hoc beacon template has no SSID!\n");
+}
+
static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
@@ -1566,40 +1583,17 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
if (ret < 0)
goto out;
- if ((changed & BSS_CHANGED_BSSID) &&
- /*
- * Now we know the correct bssid, so we send a new join command
- * and enable the BSSID filter
- */
- memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) {
- wl->rx_config |= CFG_BSSID_FILTER_EN;
- memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
- ret = wl1271_cmd_build_null_data(wl);
- if (ret < 0) {
- wl1271_warning("cmd buld null data failed %d",
- ret);
- goto out_sleep;
- }
- ret = wl1271_cmd_join(wl);
- if (ret < 0) {
- wl1271_warning("cmd join failed %d", ret);
- goto out_sleep;
- }
- set_bit(WL1271_FLAG_JOINED, &wl->flags);
- }
-
if (wl->bss_type == BSS_TYPE_IBSS) {
/* FIXME: This implements rudimentary ad-hoc support -
proper templates are on the wish list and notification
on when they change. This patch will update the templates
- on every call to this function. Also, the firmware will not
- answer to probe-requests as it does not have the proper
- SSID set in the JOIN command. The probe-response template
- is set nevertheless, as the FW will ASSERT without it */
+ on every call to this function. */
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
if (beacon) {
struct ieee80211_hdr *hdr;
+
+ wl1271_ssid_set(wl, beacon);
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON,
beacon->data,
beacon->len);
@@ -1624,6 +1618,29 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
}
}
+ if ((changed & BSS_CHANGED_BSSID) &&
+ /*
+ * Now we know the correct bssid, so we send a new join command
+ * and enable the BSSID filter
+ */
+ memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) {
+ wl->rx_config |= CFG_BSSID_FILTER_EN;
+ memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
+ ret = wl1271_cmd_build_null_data(wl);
+ if (ret < 0) {
+ wl1271_warning("cmd buld null data failed %d",
+ ret);
+ goto out_sleep;
+ }
+
+ ret = wl1271_cmd_join(wl);
+ if (ret < 0) {
+ wl1271_warning("cmd join failed %d", ret);
+ goto out_sleep;
+ }
+ set_bit(WL1271_FLAG_JOINED, &wl->flags);
+ }
+
if (changed & BSS_CHANGED_ASSOC) {
if (bss_conf->assoc) {
wl->aid = bss_conf->aid;
--
1.6.3.3
From: Kalle Valo <[email protected]>
elp_wakeup() was missing in op_conf_tx() which caused wakeup problems in
power save. I forgot to add this part when porting the patch from wl1251.
Signed-off-by: Kalle Valo <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_main.c | 11 +++++++++--
1 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index c7f5191..9de7df7 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1738,11 +1738,15 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue);
+ ret = wl1271_ps_elp_wakeup(wl, false);
+ if (ret < 0)
+ goto out;
+
ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue),
params->cw_min, params->cw_max,
params->aifs, params->txop);
if (ret < 0)
- goto out;
+ goto out_sleep;
ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue),
CONF_CHANNEL_TYPE_EDCF,
@@ -1750,7 +1754,10 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
CONF_PS_SCHEME_LEGACY_PSPOLL,
CONF_ACK_POLICY_LEGACY, 0, 0);
if (ret < 0)
- goto out;
+ goto out_sleep;
+
+out_sleep:
+ wl1271_ps_elp_sleep(wl);
out:
mutex_unlock(&wl->mutex);
--
1.6.3.3
Instead of always randomizing the MAC address, retrieve and configure the
MAC address from the device specific nvs file. For now, randomize an address
only if the address in the NVS is zero.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Kalle Valo <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_boot.c | 8 ------
drivers/net/wireless/wl12xx/wl1271_main.c | 36 +++++++++++++++++++++-------
2 files changed, 27 insertions(+), 17 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index bc3fe02..57ba78d 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -228,14 +228,6 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
nvs_len = sizeof(wl->nvs->nvs);
nvs_ptr = (u8 *)wl->nvs->nvs;
- /* Update the device MAC address into the 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];
-
/*
* Layout before the actual NVS tables:
* 1 byte : burst length.
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 282c2bb..b5d53a3 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -467,6 +467,32 @@ out:
return ret;
}
+static int wl1271_update_mac_addr(struct wl1271 *wl)
+{
+ int ret = 0;
+ u8 *nvs_ptr = (u8 *)wl->nvs->nvs;
+
+ /* get mac address from the 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];
+
+ /* FIXME: if it is a zero-address, we should bail out. Now, instead,
+ we randomize an address */
+ if (is_zero_ether_addr(wl->mac_addr)) {
+ static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
+ memcpy(wl->mac_addr, nokia_oui, 3);
+ get_random_bytes(wl->mac_addr + 3, 3);
+ }
+
+ SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
+
+ return ret;
+}
+
static int wl1271_fetch_nvs(struct wl1271 *wl)
{
const struct firmware *fw;
@@ -496,7 +522,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file));
- ret = 0;
+ ret = wl1271_update_mac_addr(wl);
out:
release_firmware(fw);
@@ -1893,7 +1919,6 @@ static int __devinit wl1271_probe(struct spi_device *spi)
struct ieee80211_hw *hw;
struct wl1271 *wl;
int ret, i;
- static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
pdata = spi->dev.platform_data;
if (!pdata) {
@@ -1938,13 +1963,6 @@ static int __devinit wl1271_probe(struct spi_device *spi)
spin_lock_init(&wl->wl_lock);
- /*
- * In case our MAC address is not correctly set,
- * we use a random but Nokia MAC.
- */
- memcpy(wl->mac_addr, nokia_oui, 3);
- get_random_bytes(wl->mac_addr + 3, 3);
-
wl->state = WL1271_STATE_OFF;
mutex_init(&wl->mutex);
--
1.6.3.3
If re-configuring the SSID while ad-hoc was already enabled, the beacon
template would be properly updated, but the SSID passed in the CMD_JOIN would
not - hence filtering etc would not work properly.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Kalle Valo <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_main.c | 23 ++++++++++++++++-------
1 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 459d9a0..fb1e6a8 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1,7 +1,7 @@
/*
* This file is part of wl1271
*
- * Copyright (C) 2008-2009 Nokia Corporation
+ * Copyright (C) 2008-2010 Nokia Corporation
*
* Contact: Luciano Coelho <[email protected]>
*
@@ -1604,6 +1604,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
{
enum wl1271_cmd_ps_mode mode;
struct wl1271 *wl = hw->priv;
+ bool do_join = false;
int ret;
wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed");
@@ -1646,6 +1647,9 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
dev_kfree_skb(beacon);
if (ret < 0)
goto out_sleep;
+
+ /* Need to update the SSID (for filtering etc) */
+ do_join = true;
}
}
@@ -1664,12 +1668,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
goto out_sleep;
}
- ret = wl1271_cmd_join(wl);
- if (ret < 0) {
- wl1271_warning("cmd join failed %d", ret);
- goto out_sleep;
- }
- set_bit(WL1271_FLAG_JOINED, &wl->flags);
+ /* Need to update the BSSID (for filtering etc) */
+ do_join = true;
}
if (changed & BSS_CHANGED_ASSOC) {
@@ -1736,6 +1736,15 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
}
}
+ if (do_join) {
+ ret = wl1271_cmd_join(wl);
+ if (ret < 0) {
+ wl1271_warning("cmd join failed %d", ret);
+ goto out_sleep;
+ }
+ set_bit(WL1271_FLAG_JOINED, &wl->flags);
+ }
+
out_sleep:
wl1271_ps_elp_sleep(wl);
--
1.6.3.3
From: Kalle Valo <[email protected]>
For WMM we need to configure each queue separately so modify
wl1271_acx_ac_cfg() to take the configuration from function parameters
instead.
Signed-off-by: Kalle Valo <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_acx.c | 31 +++++++++++++---------------
drivers/net/wireless/wl12xx/wl1271_acx.h | 3 +-
drivers/net/wireless/wl12xx/wl1271_init.c | 14 +++++++++---
3 files changed, 26 insertions(+), 22 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index 0b34348..4b052ee 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -830,12 +830,14 @@ out:
return ret;
}
-int wl1271_acx_ac_cfg(struct wl1271 *wl)
+int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
+ u8 aifsn, u16 txop)
{
struct acx_ac_cfg *acx;
- int i, ret = 0;
+ int ret = 0;
- wl1271_debug(DEBUG_ACX, "acx access category config");
+ wl1271_debug(DEBUG_ACX, "acx ac cfg %d cw_ming %d cw_max %d "
+ "aifs %d txop %d", ac, cw_min, cw_max, aifsn, txop);
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
@@ -844,21 +846,16 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl)
goto out;
}
- for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
- struct conf_tx_ac_category *c = &(wl->conf.tx.ac_conf[i]);
- acx->ac = c->ac;
- acx->cw_min = c->cw_min;
- acx->cw_max = cpu_to_le16(c->cw_max);
- acx->aifsn = c->aifsn;
- acx->reserved = 0;
- acx->tx_op_limit = cpu_to_le16(c->tx_op_limit);
+ acx->ac = ac;
+ acx->cw_min = cw_min;
+ acx->cw_max = cpu_to_le16(cw_max);
+ acx->aifsn = aifsn;
+ acx->tx_op_limit = cpu_to_le16(txop);
- ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx));
- if (ret < 0) {
- wl1271_warning("Setting of access category "
- "config: %d", ret);
- goto out;
- }
+ ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("acx ac cfg failed: %d", ret);
+ goto out;
}
out:
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index 1bb63af..e5f5cbd 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -1070,7 +1070,8 @@ int wl1271_acx_cts_protect(struct wl1271 *wl,
enum acx_ctsprotect_type ctsprotect);
int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats);
int wl1271_acx_rate_policies(struct wl1271 *wl);
-int wl1271_acx_ac_cfg(struct wl1271 *wl);
+int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
+ u8 aifsn, u16 txop);
int wl1271_acx_tid_cfg(struct wl1271 *wl);
int wl1271_acx_frag_threshold(struct wl1271 *wl);
int wl1271_acx_tx_config_options(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index c9848ee..2b56a9e 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -195,7 +195,8 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
int wl1271_hw_init(struct wl1271 *wl)
{
- int ret;
+ struct conf_tx_ac_category *conf_ac;
+ int ret, i;
ret = wl1271_cmd_general_parms(wl);
if (ret < 0)
@@ -279,9 +280,14 @@ int wl1271_hw_init(struct wl1271 *wl)
goto out_free_memmap;
/* Default AC configuration */
- ret = wl1271_acx_ac_cfg(wl);
- if (ret < 0)
- goto out_free_memmap;
+ for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
+ conf_ac = &wl->conf.tx.ac_conf[i];
+ ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
+ conf_ac->cw_max, conf_ac->aifsn,
+ conf_ac->tx_op_limit);
+ if (ret < 0)
+ goto out_free_memmap;
+ }
/* Configure TX rate classes */
ret = wl1271_acx_rate_policies(wl);
--
1.6.3.3
The new firmware does not allow removal of unicast keys - they will be
automatically removed on the next CMD_JOIN.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Kalle Valo <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_main.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 9de7df7..4a0a15b 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1478,6 +1478,13 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
break;
case DISABLE_KEY:
+ /* The wl1271 does not allow to remove unicast keys - they
+ will be cleared automatically on next CMD_JOIN. Ignore the
+ request silently, as we dont want the mac80211 to emit
+ an error message. */
+ if (!is_broadcast_ether_addr(addr))
+ break;
+
ret = wl1271_cmd_set_key(wl, KEY_REMOVE,
key_conf->keyidx, key_type,
key_conf->keylen, key_conf->key,
--
1.6.3.3