summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/wl12xx/cmd.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2012-03-09 23:57:30 +0400
committerJohn W. Linville <linville@tuxdriver.com>2012-03-09 23:57:30 +0400
commit74dd1521d0b4f940cdd3ce7b9d988836bef589b8 (patch)
tree42f3d4ee1d4e6d60a91aaadab771f766a3024bc0 /drivers/net/wireless/wl12xx/cmd.c
parent2f2d76cc3e938389feee671b46252dde6880b3b7 (diff)
parent1745e4405b2c0da6db2ec4b6bc0ad930612d8295 (diff)
downloadlinux-74dd1521d0b4f940cdd3ce7b9d988836bef589b8.tar.xz
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Diffstat (limited to 'drivers/net/wireless/wl12xx/cmd.c')
-rw-r--r--drivers/net/wireless/wl12xx/cmd.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index b776d9d5efe8..3414fc11e9ba 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -459,23 +459,39 @@ out:
int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
{
+ unsigned long flags;
u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS);
if (link >= WL12XX_MAX_LINKS)
return -EBUSY;
+ /* these bits are used by op_tx */
+ spin_lock_irqsave(&wl->wl_lock, flags);
__set_bit(link, wl->links_map);
__set_bit(link, wlvif->links_map);
+ spin_unlock_irqrestore(&wl->wl_lock, flags);
*hlid = link;
return 0;
}
void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
{
+ unsigned long flags;
+
if (*hlid == WL12XX_INVALID_LINK_ID)
return;
+ /* these bits are used by op_tx */
+ spin_lock_irqsave(&wl->wl_lock, flags);
__clear_bit(*hlid, wl->links_map);
__clear_bit(*hlid, wlvif->links_map);
+ spin_unlock_irqrestore(&wl->wl_lock, flags);
+
+ /*
+ * At this point op_tx() will not add more packets to the queues. We
+ * can purge them.
+ */
+ wl1271_tx_reset_link_queues(wl, *hlid);
+
*hlid = WL12XX_INVALID_LINK_ID;
}
@@ -515,7 +531,7 @@ static int wl12xx_cmd_role_start_dev(struct wl1271 *wl,
goto out_free;
}
cmd->device.hlid = wlvif->dev_hlid;
- cmd->device.session = wlvif->session_counter;
+ cmd->device.session = wl12xx_get_new_session_id(wl, wlvif);
wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d",
cmd->role_id, cmd->device.hlid, cmd->device.session);
@@ -1802,6 +1818,14 @@ int wl12xx_croc(struct wl1271 *wl, u8 role_id)
goto out;
__clear_bit(role_id, wl->roc_map);
+
+ /*
+ * Rearm the tx watchdog when removing the last ROC. This prevents
+ * recoveries due to just finished ROCs - when Tx hasn't yet had
+ * a chance to get out.
+ */
+ if (find_first_bit(wl->roc_map, WL12XX_MAX_ROLES) >= WL12XX_MAX_ROLES)
+ wl12xx_rearm_tx_watchdog_locked(wl);
out:
return ret;
}