aboutsummaryrefslogtreecommitdiffstats
path: root/src/drivers
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2015-12-02 00:12:32 +0200
committerGerrit - the friendly Code Review server <code-review@localhost>2015-12-30 03:05:15 -0800
commite6c9bd4bfe7d5b615561dc658565010e072ca88f (patch)
treea79a98de145db2ea3d131bf8c66d28682b4ee761 /src/drivers
parent20c1104d002d61af3a12ee58e346a9f28937d620 (diff)
downloadandroid_external_wpa_supplicant_8-e6c9bd4bfe7d5b615561dc658565010e072ca88f.tar.gz
android_external_wpa_supplicant_8-e6c9bd4bfe7d5b615561dc658565010e072ca88f.tar.bz2
android_external_wpa_supplicant_8-e6c9bd4bfe7d5b615561dc658565010e072ca88f.zip
nl80211: Cancel all pending TX frame cookies
These needs to be cancelled so that the kernel driver does not get left with all old entries blocking other offchannel operations Git-commit: 759a8a3a99845af1c5c10685ec7cb9cf4daa4593 Git-repo : git://w1.fi/srv/git/hostap.git Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com> CRs-Fixed: 950786 Change-Id: Ia9a964c407c72384b606dbb1f033e110b8091b5c
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/driver_nl80211.c45
-rw-r--r--src/drivers/driver_nl80211.h3
2 files changed, 44 insertions, 4 deletions
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 43a49f24..6cd36c04 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -6154,6 +6154,20 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss,
if (cookie_out)
*cookie_out = no_ack ? (u64) -1 : cookie;
+
+ if (drv->num_send_action_cookies == MAX_SEND_ACTION_COOKIES) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Drop oldest pending send action cookie 0x%llx",
+ (long long unsigned int)
+ drv->send_action_cookies[0]);
+ os_memmove(&drv->send_action_cookies[0],
+ &drv->send_action_cookies[1],
+ (MAX_SEND_ACTION_COOKIES - 1) *
+ sizeof(u64));
+ drv->num_send_action_cookies--;
+ }
+ drv->send_action_cookies[drv->num_send_action_cookies] = cookie;
+ drv->num_send_action_cookies++;
}
fail:
@@ -6208,17 +6222,16 @@ static int wpa_driver_nl80211_send_action(struct i802_bss *bss,
}
-static void wpa_driver_nl80211_send_action_cancel_wait(void *priv)
+static void nl80211_frame_wait_cancel(struct i802_bss *bss, u64 cookie)
{
- struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
struct nl_msg *msg;
int ret;
wpa_printf(MSG_DEBUG, "nl80211: Cancel TX frame wait: cookie=0x%llx",
- (long long unsigned int) drv->send_action_cookie);
+ (long long unsigned int) cookie);
if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_FRAME_WAIT_CANCEL)) ||
- nla_put_u64(msg, NL80211_ATTR_COOKIE, drv->send_action_cookie)) {
+ nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie)) {
nlmsg_free(msg);
return;
}
@@ -6230,6 +6243,30 @@ static void wpa_driver_nl80211_send_action_cancel_wait(void *priv)
}
+static void wpa_driver_nl80211_send_action_cancel_wait(void *priv)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ unsigned int i;
+ u64 cookie;
+
+ /* Cancel the last pending TX cookie */
+ nl80211_frame_wait_cancel(bss, drv->send_action_cookie);
+
+ /*
+ * Cancel the other pending TX cookies, if any. This is needed since
+ * the driver may keep a list of all pending offchannel TX operations
+ * and free up the radio only once they have expired or cancelled.
+ */
+ for (i = drv->num_send_action_cookies; i > 0; i--) {
+ cookie = drv->send_action_cookies[i - 1];
+ if (cookie != drv->send_action_cookie)
+ nl80211_frame_wait_cancel(bss, cookie);
+ }
+ drv->num_send_action_cookies = 0;
+}
+
+
static int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq,
unsigned int duration)
{
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index 1536d2ff..ffb5fa7e 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -149,6 +149,9 @@ struct wpa_driver_nl80211_data {
u64 remain_on_chan_cookie;
u64 send_action_cookie;
+#define MAX_SEND_ACTION_COOKIES 20
+ u64 send_action_cookies[MAX_SEND_ACTION_COOKIES];
+ unsigned int num_send_action_cookies;
unsigned int last_mgmt_freq;