summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>2011-08-18 00:35:00 +0200
committerPhilippe LANGLAIS <philippe.langlais@stericsson.com>2011-10-13 10:03:52 +0200
commit5b48061fc3276dadaceeff6c152e8f5b0f250c2e (patch)
tree8167dc4401f13917f0f3fb01c67e366e6366abac
parent3dded119d7f7479e563b20d89aafa0b165249e36 (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-xdrivers/staging/cw1200/ap.c24
-rw-r--r--drivers/staging/cw1200/wsm.c27
-rw-r--r--drivers/staging/cw1200/wsm.h17
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 {