Configure and respond to a probe response offload query with
the relevant protocols supported currently by the driver.
Signed-off-by: Guy Eilam <[email protected]>
---
drivers/net/wireless/wl12xx/conf.h | 2 ++
drivers/net/wireless/wl12xx/main.c | 15 +++++++++++++++
2 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index 04bb8fb..714f9d4 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -1264,6 +1264,8 @@ struct conf_drv_settings {
struct conf_rate_policy_settings rate;
struct conf_hangover_settings hangover;
u8 hci_io_ds;
+ /* a bitmap of supported protocols for probe response offloading */
+ u32 probe_resp_offload;
};
#endif
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index f76be5a..0a7d020 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -373,6 +373,10 @@ static struct conf_drv_settings default_conf = {
.increase_time = 1,
.window_size = 16,
},
+ .probe_resp_offload =
+ BIT(NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS) |
+ BIT(NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2) |
+ BIT(NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P),
};
static char *fwlog_param;
@@ -4081,6 +4085,16 @@ static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx,
return 0;
}
+static int wl1271_op_get_probe_resp_offload(struct ieee80211_hw *hw,
+ u32 *supp_protocols)
+{
+ struct wl1271 *wl = hw->priv;
+
+ *supp_protocols = wl->conf.probe_resp_offload;
+
+ return 0;
+}
+
static int wl1271_allocate_sta(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct ieee80211_sta *sta)
@@ -4666,6 +4680,7 @@ static const struct ieee80211_ops wl1271_ops = {
.tx_frames_pending = wl1271_tx_frames_pending,
.set_bitrate_mask = wl12xx_set_bitrate_mask,
.channel_switch = wl12xx_op_channel_switch,
+ .get_probe_resp_offload = wl1271_op_get_probe_resp_offload,
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
};
--
1.7.4.1
When operating in AP-mode, replace probe-response template when a
notification is recieved from mac80211. We preserve the "legacy" way of
configuring a probe-response according to beacon for IBSS mode and for
versions of hostapd that do not support this feature.
Signed-off-by: Guy Eilam <[email protected]>
---
drivers/net/wireless/wl12xx/main.c | 57 +++++++++++++++++++++++++++++----
drivers/net/wireless/wl12xx/wl12xx.h | 1 +
2 files changed, 51 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 0a7d020..d91842d 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -3311,11 +3311,33 @@ static void wl12xx_remove_vendor_ie(struct sk_buff *skb,
skb_trim(skb, skb->len - len);
}
-static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl,
- struct ieee80211_vif *vif,
- u8 *probe_rsp_data,
- size_t probe_rsp_len,
- u32 rates)
+static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, u32 rates)
+{
+ struct sk_buff *skb;
+ int ret;
+
+ skb = ieee80211_proberesp_get(wl->hw, wl->vif);
+ if (!skb)
+ return -EINVAL;
+
+ ret = wl1271_cmd_template_set(wl,
+ CMD_TEMPL_AP_PROBE_RESPONSE,
+ skb->data,
+ skb->len, 0,
+ rates);
+
+ if (!ret)
+ set_bit(WL1271_FLAG_PROBE_RESP_SET, &wl->flags);
+
+ dev_kfree_skb(skb);
+ return ret;
+}
+
+static int wl1271_ap_set_probe_resp_tmpl_legacy(struct wl1271 *wl,
+ struct ieee80211_vif *vif,
+ u8 *probe_rsp_data,
+ size_t probe_rsp_len,
+ u32 rates)
{
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
@@ -3428,6 +3450,13 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
wlvif->beacon_int = bss_conf->beacon_int;
}
+ if ((changed & BSS_CHANGED_AP_PROBE_RESP) && is_ap) {
+ ret = wl1271_ap_set_probe_resp_tmpl(wl,
+ wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set));
+ if (ret < 0)
+ goto out;
+ }
+
if ((changed & BSS_CHANGED_BEACON)) {
struct ieee80211_hdr *hdr;
u32 min_rate;
@@ -3436,8 +3465,10 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif);
u16 tmpl_id;
- if (!beacon)
+ if (!beacon) {
+ ret = -EINVAL;
goto out;
+ }
wl1271_debug(DEBUG_MASTER, "beacon updated");
@@ -3458,6 +3489,13 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
goto out;
}
+ /*
+ * In case we already have a probe-resp beacon set explicitly
+ * by usermode, don't use the beacon data.
+ */
+ if (test_bit(WL1271_FLAG_PROBE_RESP_SET, &wl->flags))
+ goto end_bcn;
+
/* remove TIM ie from probe response */
wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset);
@@ -3476,7 +3514,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_PROBE_RESP);
if (is_ap)
- ret = wl1271_ap_set_probe_resp_tmpl(wl, vif,
+ ret = wl1271_ap_set_probe_resp_tmpl_legacy(wl, vif,
beacon->data,
beacon->len,
min_rate);
@@ -3486,12 +3524,15 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
beacon->data,
beacon->len, 0,
min_rate);
+end_bcn:
dev_kfree_skb(beacon);
if (ret < 0)
goto out;
}
out:
+ if (ret != 0)
+ wl1271_error("beacon info change failed: %d", ret);
return ret;
}
@@ -3548,6 +3589,8 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
goto out;
clear_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags);
+ clear_bit(WL1271_FLAG_PROBE_RESP_SET,
+ &wl->flags);
wl1271_debug(DEBUG_AP, "stopped AP");
}
}
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index b7036df..a117c9d 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -255,6 +255,7 @@ enum wl12xx_flags {
WL1271_FLAG_PENDING_WORK,
WL1271_FLAG_SOFT_GEMINI,
WL1271_FLAG_RECOVERY_IN_PROGRESS,
+ WL1271_FLAG_PROBE_RESP_SET,
};
enum wl12xx_vif_flags {
--
1.7.4.1