diff options
author | Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com> | 2011-08-18 00:35:00 +0200 |
---|---|---|
committer | Philippe LANGLAIS <philippe.langlais@stericsson.com> | 2011-10-13 10:03:52 +0200 |
commit | 5b48061fc3276dadaceeff6c152e8f5b0f250c2e (patch) | |
tree | 8167dc4401f13917f0f3fb01c67e366e6366abac | |
parent | 3dded119d7f7479e563b20d89aafa0b165249e36 (diff) |
cw1200: Fix for firmware crash/hang in SoftAP with powersave.
* Firmware does not support block ACK in SoftAP mode and crashes
when BA-enabled settings are applied. Fix completly disables BA
when firmware is in SoftAP mode.
* Proper register is used for firmware assert line number diagnostic message.
* wsm_update_ie is implemented (cosmetical change).
Change-Id: I93bff4e59a1a6ab35f537097a46199cb8a1c34fa
Signed-off-by: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/29064
Reviewed-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com>
Tested-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com>
Reviewed-by: QATEST
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33510
Reviewed-by: Philippe LANGLAIS <philippe.langlais@stericsson.com>
-rwxr-xr-x | drivers/staging/cw1200/ap.c | 24 | ||||
-rw-r--r-- | drivers/staging/cw1200/wsm.c | 27 | ||||
-rw-r--r-- | drivers/staging/cw1200/wsm.h | 17 |
3 files changed, 56 insertions, 12 deletions
diff --git a/drivers/staging/cw1200/ap.c b/drivers/staging/cw1200/ap.c index 2a6d27f212f..39c11172544 100755 --- a/drivers/staging/cw1200/ap.c +++ b/drivers/staging/cw1200/ap.c @@ -115,34 +115,38 @@ void cw1200_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif, static int cw1200_set_tim_impl(struct cw1200_common *priv, bool aid0_bit_set) { - struct wsm_template_frame frame = { - .frame_type = WSM_FRAME_TYPE_BEACON, + struct sk_buff *skb; + struct wsm_update_ie update_ie = { + .what = WSM_UPDATE_IE_BEACON, + .count = 1, }; u16 tim_offset, tim_length; ap_printk(KERN_DEBUG "[AP] %s mcast: %s.\n", __func__, aid0_bit_set ? "ena" : "dis"); - frame.skb = ieee80211_beacon_get_tim(priv->hw, priv->vif, + skb = ieee80211_beacon_get_tim(priv->hw, priv->vif, &tim_offset, &tim_length); - if (WARN_ON(!frame.skb)) + if (WARN_ON(!skb)) return -ENOMEM; if (tim_offset && tim_length >= 6) { /* Ignore DTIM count from mac80211: * firmware handles DTIM internally. */ - frame.skb->data[tim_offset + 2] = 0; + skb->data[tim_offset + 2] = 0; /* Set/reset aid0 bit */ if (aid0_bit_set) - frame.skb->data[tim_offset + 4] |= 1; + skb->data[tim_offset + 4] |= 1; else - frame.skb->data[tim_offset + 4] &= ~1; + skb->data[tim_offset + 4] &= ~1; } - WARN_ON(wsm_set_template_frame(priv, &frame)); + update_ie.ies = &skb->data[tim_offset]; + update_ie.length = tim_length; + WARN_ON(wsm_update_ie(priv, &update_ie)); - dev_kfree_skb(frame.skb); + dev_kfree_skb(skb); return 0; } @@ -661,7 +665,7 @@ static int cw1200_start_ap(struct cw1200_common *priv) ret = WARN_ON(cw1200_upload_keys(priv)); if (!ret) { WARN_ON(wsm_set_block_ack_policy(priv, - priv->ba_tid_mask, priv->ba_tid_mask)); + 0, 0)); priv->join_status = CW1200_JOIN_STATUS_AP; cw1200_update_filtering(priv); } diff --git a/drivers/staging/cw1200/wsm.c b/drivers/staging/cw1200/wsm.c index 16ebfe658fe..37194870c56 100644 --- a/drivers/staging/cw1200/wsm.c +++ b/drivers/staging/cw1200/wsm.c @@ -768,6 +768,30 @@ nomem: return -ENOMEM; } +/* ******************************************************************** */ + +int wsm_update_ie(struct cw1200_common *priv, + const struct wsm_update_ie *arg) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + + wsm_cmd_lock(priv); + + WSM_PUT16(buf, arg->what); + WSM_PUT16(buf, arg->count); + WSM_PUT(buf, arg->ies, arg->length); + + ret = wsm_cmd_send(priv, buf, NULL, 0x001B, WSM_CMD_TIMEOUT); + + wsm_cmd_unlock(priv); + return ret; + +nomem: + wsm_cmd_unlock(priv); + return -ENOMEM; + +} /* ******************************************************************** */ /* WSM indication events implementation */ @@ -1122,7 +1146,7 @@ int wsm_handle_exception(struct cw1200_common *priv, u8 *data, size_t len) else wiphy_err(priv->hw->wiphy, "Firmware assert at %.*s, line %d\n", - sizeof(fname), fname, reg[0]); + sizeof(fname), fname, reg[1]); for (i = 0; i < 12; i += 4) wiphy_err(priv->hw->wiphy, @@ -1225,6 +1249,7 @@ int wsm_handle_rx(struct cw1200_common *priv, int id, case 0x0418: /* beacon_transmit */ case 0x0419: /* start_find */ case 0x041A: /* stop_find */ + case 0x041B: /* update_ie */ case 0x041C: /* map_link */ WARN_ON(wsm_arg != NULL); ret = wsm_generic_confirm(priv, wsm_arg, &wsm_buf); diff --git a/drivers/staging/cw1200/wsm.h b/drivers/staging/cw1200/wsm.h index 30db888e535..6b6d4a8049e 100644 --- a/drivers/staging/cw1200/wsm.h +++ b/drivers/staging/cw1200/wsm.h @@ -333,6 +333,11 @@ struct cw1200_common; #define WSM_RCPI_RSSI_DONT_USE_UPPER (BIT(2)) #define WSM_RCPI_RSSI_DONT_USE_LOWER (BIT(3)) +/* Update-ie constants */ +#define WSM_UPDATE_IE_BEACON (BIT(0)) +#define WSM_UPDATE_IE_PROBE_RESP (BIT(1)) +#define WSM_UPDATE_IE_PROBE_REQ (BIT(2)) + /* WSM events */ /* Error */ #define WSM_EVENT_ERROR (0) @@ -1168,7 +1173,17 @@ struct wsm_suspend_resume { typedef void (*wsm_suspend_resume_cb) (struct cw1200_common *priv, struct wsm_suspend_resume *arg); -/* 3.53 Update-IE request: Not implemented: not relevant. */ +/* 3.54 Update-IE request. */ +struct wsm_update_ie { + /* WSM_UPDATE_IE_... */ + /* [in] */ u16 what; + /* [in] */ u16 count; + /* [in] */ u8 *ies; + /* [in] */ size_t length; +}; + +int wsm_update_ie(struct cw1200_common *priv, + const struct wsm_update_ie *arg); /* 3.56 */ struct wsm_map_link { |