2013-05-12 09:35:41

by Eliad Peller

[permalink] [raw]
Subject: [PATCH 1/4] wlcore: set default_wep_key when configured

From: Yoni Divinsky <[email protected]>

When associating to an AP with WEP set the
default key upon association by implementing
the set_deafult_key_idx op.

Fixes auto-arp sent with wrong key_idx bug.

Signed-off-by: Yoni Divinsky <[email protected]>
Signed-off-by: Eyal Shapira <[email protected]>
Signed-off-by: Eliad Peller <[email protected]>
---
drivers/net/wireless/ti/wlcore/main.c | 49 +++++++++++++++++++++++++++++------
drivers/net/wireless/ti/wlcore/tx.c | 2 +-
2 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index a018221..c384bad 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -3196,14 +3196,6 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
if (ret < 0)
return ret;

- /* the default WEP key needs to be configured at least once */
- if (key_type == KEY_WEP) {
- ret = wl12xx_cmd_set_default_wep_key(wl,
- wlvif->default_key,
- wlvif->sta.hlid);
- if (ret < 0)
- return ret;
- }
}

return 0;
@@ -3360,6 +3352,46 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
}
EXPORT_SYMBOL_GPL(wlcore_set_key);

+static void wl1271_op_set_default_key_idx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ int key_idx)
+{
+ struct wl1271 *wl = hw->priv;
+ struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+ int ret;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 set default key idx %d",
+ key_idx);
+
+ mutex_lock(&wl->mutex);
+
+ if (unlikely(wl->state != WLCORE_STATE_ON)) {
+ ret = -EAGAIN;
+ goto out_unlock;
+ }
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out_unlock;
+
+ wlvif->default_key = key_idx;
+
+ /* the default WEP key needs to be configured at least once */
+ if (wlvif->encryption_type == KEY_WEP) {
+ ret = wl12xx_cmd_set_default_wep_key(wl,
+ key_idx,
+ wlvif->sta.hlid);
+ if (ret < 0)
+ goto out_sleep;
+ }
+
+out_sleep:
+ wl1271_ps_elp_sleep(wl);
+
+out_unlock:
+ mutex_unlock(&wl->mutex);
+}
+
void wlcore_regdomain_config(struct wl1271 *wl)
{
int ret;
@@ -5352,6 +5384,7 @@ static const struct ieee80211_ops wl1271_ops = {
.ampdu_action = wl1271_op_ampdu_action,
.tx_frames_pending = wl1271_tx_frames_pending,
.set_bitrate_mask = wl12xx_set_bitrate_mask,
+ .set_default_unicast_key = wl1271_op_set_default_key_idx,
.channel_switch = wl12xx_op_channel_switch,
.flush = wlcore_op_flush,
.remain_on_channel = wlcore_op_remain_on_channel,
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index 004d02e..7e93fe6 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -386,7 +386,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
is_wep = (cipher == WLAN_CIPHER_SUITE_WEP40) ||
(cipher == WLAN_CIPHER_SUITE_WEP104);

- if (unlikely(is_wep && wlvif->default_key != idx)) {
+ if (WARN_ON(is_wep && wlvif->default_key != idx)) {
ret = wl1271_set_default_wep_key(wl, wlvif, idx);
if (ret < 0)
return ret;
--
1.8.1.2



2013-05-12 09:35:46

by Eliad Peller

[permalink] [raw]
Subject: [PATCH 4/4] wlcore: fix occasional AP TX stop after recovery

From: Victor Goldenshtein <[email protected]>

The fw_status wasn't zeroed during allocation, resulting
in uninitialized var usage, and finally causing AP
traffic stop after recovery.

The wrong value in fw_status_2->counters.tx_lnk_free_pkts
led to a bad lnk->allocated_pkts calculation in
wlcore_fw_status(), causing wl18xx_lnk_low_prio() to return
FALSE (lnk->allocated_pkts > thold).
This eventually blocked the link in wlcore_tx_work_locked(),
as wl1271_skb_dequeue() continuously returned NULL.

Fix it by zeroing wl->fw_status_1/2 during allocation.

Signed-off-by: Victor Goldenshtein <[email protected]>
Signed-off-by: Eliad Peller <[email protected]>
---
drivers/net/wireless/ti/wlcore/main.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index ecbbd38..2537391 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -970,7 +970,7 @@ static int wlcore_fw_wakeup(struct wl1271 *wl)

static int wl1271_setup(struct wl1271 *wl)
{
- wl->fw_status_1 = kmalloc(WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) +
+ wl->fw_status_1 = kzalloc(WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) +
sizeof(*wl->fw_status_2) +
wl->fw_status_priv_len, GFP_KERNEL);
if (!wl->fw_status_1)
@@ -980,7 +980,7 @@ static int wl1271_setup(struct wl1271 *wl)
(((u8 *) wl->fw_status_1) +
WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc));

- wl->tx_res_if = kmalloc(sizeof(*wl->tx_res_if), GFP_KERNEL);
+ wl->tx_res_if = kzalloc(sizeof(*wl->tx_res_if), GFP_KERNEL);
if (!wl->tx_res_if) {
kfree(wl->fw_status_1);
return -ENOMEM;
--
1.8.1.2


2013-05-12 09:35:43

by Eliad Peller

[permalink] [raw]
Subject: [PATCH 2/4] wlcore: cancel channel switch work on interface removal

From: Arik Nemtsov <[email protected]>

Otherwise, if the work is pending, we might get
a bad dereference after the interface is removed.

Signed-off-by: Arik Nemtsov <[email protected]>
Signed-off-by: Eliad Peller <[email protected]>
---
drivers/net/wireless/ti/wlcore/main.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index c384bad..ecbbd38 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -2589,6 +2589,7 @@ unlock:
cancel_work_sync(&wlvif->rx_streaming_enable_work);
cancel_work_sync(&wlvif->rx_streaming_disable_work);
cancel_delayed_work_sync(&wlvif->connection_loss_work);
+ cancel_delayed_work_sync(&wlvif->channel_switch_work);

mutex_lock(&wl->mutex);
}
--
1.8.1.2


2013-05-12 09:35:44

by Eliad Peller

[permalink] [raw]
Subject: [PATCH 3/4] wlcore: hold jiffies in unsigned long

From: Arik Nemtsov <[email protected]>

u32 can be incorrect (too small) for some architectures.

Signed-off-by: Arik Nemtsov <[email protected]>
Signed-off-by: Eliad Peller <[email protected]>
---
drivers/net/wireless/ti/wlcore/ps.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c
index 9654577..98066d4 100644
--- a/drivers/net/wireless/ti/wlcore/ps.c
+++ b/drivers/net/wireless/ti/wlcore/ps.c
@@ -110,7 +110,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
DECLARE_COMPLETION_ONSTACK(compl);
unsigned long flags;
int ret;
- u32 start_time = jiffies;
+ unsigned long start_time = jiffies;
bool pending = false;

/*
--
1.8.1.2


2013-06-17 09:14:56

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 1/4] wlcore: set default_wep_key when configured

On Sun, 2013-05-12 at 12:35 +0300, Eliad Peller wrote:
> From: Yoni Divinsky <[email protected]>
>
> When associating to an AP with WEP set the
> default key upon association by implementing
> the set_deafult_key_idx op.
>
> Fixes auto-arp sent with wrong key_idx bug.
>
> Signed-off-by: Yoni Divinsky <[email protected]>
> Signed-off-by: Eyal Shapira <[email protected]>
> Signed-off-by: Eliad Peller <[email protected]>
> ---

Applied this entire series. Thanks!

--
Luca.