wl12xx: add device role commands
authorEliad Peller <eliad@wizery.com>
Sun, 14 Aug 2011 10:17:09 +0000 (13:17 +0300)
committerLuciano Coelho <coelho@ti.com>
Mon, 22 Aug 2011 09:35:24 +0000 (12:35 +0300)
The device role is a special role used for rx and tx frames
prior to association (as the STA role can get packets only
from its associated bssid)

Since this role is required for the sta association process,
we enable it when a new sta interface is created.

Signed-off-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
drivers/net/wireless/wl12xx/cmd.c
drivers/net/wireless/wl12xx/main.c
drivers/net/wireless/wl12xx/wl12xx.h

index b13eed129a926d4f83e335a7897ad729ce39f16d..e29343ed6ea2c69dbe5f4b43218e62aa82a2b0ef 100644 (file)
@@ -458,6 +458,97 @@ static void wl12xx_free_link(struct wl1271 *wl, u8 *hlid)
        *hlid = WL12XX_INVALID_LINK_ID;
 }
 
+int wl12xx_cmd_role_start_dev(struct wl1271 *wl)
+{
+       struct wl12xx_cmd_role_start *cmd;
+       int ret;
+
+       cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+       if (!cmd) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wl->dev_role_id);
+
+       cmd->role_id = wl->dev_role_id;
+       if (wl->band == IEEE80211_BAND_5GHZ)
+               cmd->band = WL12XX_BAND_5GHZ;
+       cmd->channel = wl->channel;
+
+       if (wl->dev_hlid == WL12XX_INVALID_LINK_ID) {
+               ret = wl12xx_allocate_link(wl, &wl->dev_hlid);
+               if (ret)
+                       goto out_free;
+       }
+       cmd->device.hlid = wl->dev_hlid;
+       cmd->device.session = wl->session_counter;
+
+       wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d",
+                    cmd->role_id, cmd->device.hlid, cmd->device.session);
+
+       ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
+       if (ret < 0) {
+               wl1271_error("failed to initiate cmd role enable");
+               goto err_hlid;
+       }
+
+       goto out_free;
+
+err_hlid:
+       /* clear links on error */
+       __clear_bit(wl->dev_hlid, wl->links_map);
+       wl->dev_hlid = WL12XX_INVALID_LINK_ID;
+
+
+out_free:
+       kfree(cmd);
+
+out:
+       return ret;
+}
+
+int wl12xx_cmd_role_stop_dev(struct wl1271 *wl)
+{
+       struct wl12xx_cmd_role_stop *cmd;
+       int ret;
+
+       if (WARN_ON(wl->dev_hlid == WL12XX_INVALID_LINK_ID))
+               return -EINVAL;
+
+       cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+       if (!cmd) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       wl1271_debug(DEBUG_CMD, "cmd role stop dev");
+
+       cmd->role_id = wl->dev_role_id;
+       cmd->disc_type = DISCONNECT_IMMEDIATE;
+       cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED);
+
+       ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0);
+       if (ret < 0) {
+               wl1271_error("failed to initiate cmd role stop");
+               goto out_free;
+       }
+
+       ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID);
+       if (ret < 0) {
+               wl1271_error("cmd role stop dev event completion error");
+               goto out_free;
+       }
+
+       wl12xx_free_link(wl, &wl->dev_hlid);
+
+out_free:
+       kfree(cmd);
+
+out:
+       return ret;
+}
+
 int wl12xx_cmd_role_start_sta(struct wl1271 *wl)
 {
        struct wl12xx_cmd_role_start *cmd;
index 3e77f59e3397a54018bfc6715ab33d3503078689..7b0b7c34ef761555377c0fcdfa18ccd8d260c1ee 100644 (file)
@@ -1866,6 +1866,20 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
                if (ret < 0)
                        goto power_off;
 
+               if (wl->bss_type == BSS_TYPE_STA_BSS) {
+                       /*
+                        * The device role is a special role used for
+                        * rx and tx frames prior to association (as
+                        * the STA role can get packets only from
+                        * its associated bssid)
+                        */
+                       ret = wl12xx_cmd_role_enable(wl,
+                                                        WL1271_ROLE_DEVICE,
+                                                        &wl->dev_role_id);
+                       if (ret < 0)
+                               goto irq_disable;
+               }
+
                ret = wl12xx_cmd_role_enable(wl, role_type, &wl->role_id);
                if (ret < 0)
                        goto irq_disable;
@@ -1965,6 +1979,12 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
                if (ret < 0)
                        goto deinit;
 
+               if (wl->bss_type == BSS_TYPE_STA_BSS) {
+                       ret = wl12xx_cmd_role_disable(wl, &wl->dev_role_id);
+                       if (ret < 0)
+                               goto deinit;
+               }
+
                ret = wl12xx_cmd_role_disable(wl, &wl->role_id);
                if (ret < 0)
                        goto deinit;
@@ -1973,6 +1993,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
        }
 deinit:
        wl->sta_hlid = WL12XX_INVALID_LINK_ID;
+       wl->dev_hlid = WL12XX_INVALID_LINK_ID;
 
        /*
         * this must be before the cancel_work calls below, so that the work
@@ -2023,6 +2044,7 @@ deinit:
        wl->ap_ps_map = 0;
        wl->sched_scanning = false;
        wl->role_id = WL12XX_INVALID_ROLE_ID;
+       wl->dev_role_id = WL12XX_INVALID_ROLE_ID;
        memset(wl->roles_map, 0, sizeof(wl->roles_map));
        memset(wl->links_map, 0, sizeof(wl->links_map));
 
@@ -4365,7 +4387,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
        wl->tx_security_last_seq_lsb = 0;
        wl->role_id = WL12XX_INVALID_ROLE_ID;
        wl->sta_hlid = WL12XX_INVALID_LINK_ID;
-
+       wl->dev_role_id = WL12XX_INVALID_ROLE_ID;
+       wl->dev_hlid = WL12XX_INVALID_LINK_ID;
        setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer,
                    (unsigned long) wl);
        wl->fwlog_size = 0;
index 3d43875163e12e8abe8ba3344f8b181e296bc995..ab46664969ec88443db0351665eaedac40c814a0 100644 (file)
@@ -394,6 +394,7 @@ struct wl1271 {
        u8 ssid_len;
        int channel;
        u8 role_id;
+       u8 dev_role_id;
        u8 sta_hlid;
        u8 dev_hlid;