wl12xx: use dynamic hlids for AP-mode
authorArik Nemtsov <arik@wizery.com>
Sun, 14 Aug 2011 10:17:21 +0000 (13:17 +0300)
committerLuciano Coelho <coelho@ti.com>
Mon, 22 Aug 2011 09:35:27 +0000 (12:35 +0300)
Using hlid=0 in AP mode is a bug. Dynamically allocate HLIDs.

Set the "first sta hlid" as 3. This will have to be changed
when multiple vifs will be supported.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
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/tx.c
drivers/net/wireless/wl12xx/wl12xx.h

index 7c5d7384536114c7293c540b38ee75188abdb0b3..025fb14184d6be863a743768c24ac4d72d707419 100644 (file)
@@ -682,11 +682,19 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
                goto out;
        }
 
+       ret = wl12xx_allocate_link(wl, &wl->ap_global_hlid);
+       if (ret < 0)
+               goto out_free;
+
+       ret = wl12xx_allocate_link(wl, &wl->ap_bcast_hlid);
+       if (ret < 0)
+               goto out_free_global;
+
        cmd->role_id = wl->role_id;
        cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period);
        cmd->ap.bss_index = WL1271_AP_BSS_INDEX;
-       cmd->ap.global_hlid = WL1271_AP_GLOBAL_HLID;
-       cmd->ap.broadcast_hlid = WL1271_AP_BROADCAST_HLID;
+       cmd->ap.global_hlid = wl->ap_global_hlid;
+       cmd->ap.broadcast_hlid = wl->ap_bcast_hlid;
        cmd->ap.basic_rate_set = cpu_to_le32(wl->basic_rate_set);
        cmd->ap.beacon_interval = cpu_to_le16(wl->beacon_int);
        cmd->ap.dtim_interval = bss_conf->dtim_period;
@@ -713,9 +721,17 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
        ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
        if (ret < 0) {
                wl1271_error("failed to initiate cmd role start ap");
-               goto out_free;
+               goto out_free_bcast;
        }
 
+       goto out_free;
+
+out_free_bcast:
+       wl12xx_free_link(wl, &wl->ap_bcast_hlid);
+
+out_free_global:
+       wl12xx_free_link(wl, &wl->ap_global_hlid);
+
 out_free:
        kfree(cmd);
 
@@ -744,6 +760,9 @@ int wl12xx_cmd_role_stop_ap(struct wl1271 *wl)
                goto out_free;
        }
 
+       wl12xx_free_link(wl, &wl->ap_bcast_hlid);
+       wl12xx_free_link(wl, &wl->ap_global_hlid);
+
 out_free:
        kfree(cmd);
 
@@ -1253,7 +1272,7 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
        if (!cmd)
                return -ENOMEM;
 
-       if (hlid == WL1271_AP_BROADCAST_HLID) {
+       if (hlid == wl->ap_bcast_hlid) {
                if (key_type == KEY_WEP)
                        lid_type = WEP_DEFAULT_LID_TYPE;
                else
index 157c46237d9f9b894447e64b187039b91cef9ecd..ea150b5ff9f50b8dc92c63072d51cab744c8cb77 100644 (file)
@@ -1972,8 +1972,11 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
                wl1271_ps_elp_sleep(wl);
        }
 deinit:
+       /* clear all hlids (except system_hlid) */
        wl->sta_hlid = WL12XX_INVALID_LINK_ID;
        wl->dev_hlid = WL12XX_INVALID_LINK_ID;
+       wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID;
+       wl->ap_global_hlid = WL12XX_INVALID_LINK_ID;
 
        /*
         * this must be before the cancel_work calls below, so that the work
@@ -2538,7 +2541,7 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl)
 
        if (wep_key_added) {
                ret = wl12xx_cmd_set_default_wep_key(wl, wl->default_key,
-                                                    WL1271_AP_BROADCAST_HLID);
+                                                    wl->ap_bcast_hlid);
                if (ret < 0)
                        goto out;
        }
@@ -2563,7 +2566,7 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
                        wl_sta = (struct wl1271_station *)sta->drv_priv;
                        hlid = wl_sta->hlid;
                } else {
-                       hlid = WL1271_AP_BROADCAST_HLID;
+                       hlid = wl->ap_bcast_hlid;
                }
 
                if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
@@ -4449,6 +4452,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
        wl->dev_role_id = WL12XX_INVALID_ROLE_ID;
        wl->dev_hlid = WL12XX_INVALID_LINK_ID;
        wl->session_counter = 0;
+       wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID;
+       wl->ap_global_hlid = WL12XX_INVALID_LINK_ID;
        setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer,
                    (unsigned long) wl);
        wl->fwlog_size = 0;
index 057db6f86bee1b70ddc5dbbcbfa0b45503f2cfb3..1240f4094a8bf1a7fea438cb2cdb0a2563bf8277 100644 (file)
@@ -38,7 +38,7 @@ static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id)
 
        if (is_ap)
                ret = wl12xx_cmd_set_default_wep_key(wl, id,
-                                                    WL1271_AP_BROADCAST_HLID);
+                                                    wl->ap_bcast_hlid);
        else
                ret = wl12xx_cmd_set_default_wep_key(wl, id, wl->sta_hlid);
 
@@ -168,9 +168,9 @@ u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb)
 
                hdr = (struct ieee80211_hdr *)skb->data;
                if (ieee80211_is_mgmt(hdr->frame_control))
-                       return WL1271_AP_GLOBAL_HLID;
+                       return wl->ap_global_hlid;
                else
-                       return WL1271_AP_BROADCAST_HLID;
+                       return wl->ap_bcast_hlid;
        }
 }
 
@@ -317,17 +317,12 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
                else
                        rate_idx = ACX_TX_BASIC_RATE;
        } else {
-               switch (hlid) {
-               case WL1271_AP_GLOBAL_HLID:
+               if (hlid == wl->ap_global_hlid)
                        rate_idx = ACX_TX_AP_MODE_MGMT_RATE;
-                       break;
-               case WL1271_AP_BROADCAST_HLID:
+               else if (hlid == wl->ap_bcast_hlid)
                        rate_idx = ACX_TX_AP_MODE_BCST_RATE;
-                       break;
-               default:
+               else
                        rate_idx = ac;
-                       break;
-               }
        }
 
        tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY;
index a136795352c81155ed23f96b6f1ae36a8a6e67c5..1313dc5b855e14bb39457fcc4723df21a0a38f5f 100644 (file)
@@ -141,10 +141,15 @@ extern u32 wl12xx_debug_level;
 #define WL12XX_MAX_LINKS           8
 #define WL12XX_INVALID_ROLE_ID     0xff
 #define WL12XX_INVALID_LINK_ID     0xff
+
+/* Defined by FW as 0. Will not be freed or allocated. */
 #define WL12XX_SYSTEM_HLID         0
-#define WL1271_AP_GLOBAL_HLID      0
-#define WL1271_AP_BROADCAST_HLID   1
-#define WL1271_AP_STA_HLID_START   2
+
+/*
+ * TODO: we currently don't support multirole. remove
+ * this constant from the code when we do.
+ */
+#define WL1271_AP_STA_HLID_START   3
 
 /*
  * When in AP-mode, we allow (at least) this number of mem-blocks
@@ -398,6 +403,8 @@ struct wl1271 {
        u8 system_hlid;
        u8 sta_hlid;
        u8 dev_hlid;
+       u8 ap_global_hlid;
+       u8 ap_bcast_hlid;
 
        unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)];
        unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];