|
@@ -3544,9 +3544,14 @@ static int brcmf_dev_pno_clean(struct net_device *ndev)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static int brcmf_dev_pno_config(struct net_device *ndev)
|
|
|
+static int brcmf_dev_pno_config(struct brcmf_if *ifp,
|
|
|
+ struct cfg80211_sched_scan_request *request)
|
|
|
{
|
|
|
struct brcmf_pno_param_le pfn_param;
|
|
|
+ struct brcmf_pno_macaddr_le pfn_mac;
|
|
|
+ s32 err;
|
|
|
+ u8 *mac_mask;
|
|
|
+ int i;
|
|
|
|
|
|
memset(&pfn_param, 0, sizeof(pfn_param));
|
|
|
pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION);
|
|
@@ -3559,8 +3564,37 @@ static int brcmf_dev_pno_config(struct net_device *ndev)
|
|
|
/* set up pno scan fr */
|
|
|
pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME);
|
|
|
|
|
|
- return brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfn_set",
|
|
|
- &pfn_param, sizeof(pfn_param));
|
|
|
+ err = brcmf_fil_iovar_data_set(ifp, "pfn_set", &pfn_param,
|
|
|
+ sizeof(pfn_param));
|
|
|
+ if (err) {
|
|
|
+ brcmf_err("pfn_set failed, err=%d\n", err);
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Find out if mac randomization should be turned on */
|
|
|
+ if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER;
|
|
|
+ pfn_mac.flags = BRCMF_PFN_MAC_OUI_ONLY | BRCMF_PFN_SET_MAC_UNASSOC;
|
|
|
+
|
|
|
+ memcpy(pfn_mac.mac, request->mac_addr, ETH_ALEN);
|
|
|
+ mac_mask = request->mac_addr_mask;
|
|
|
+ for (i = 0; i < ETH_ALEN; i++) {
|
|
|
+ pfn_mac.mac[i] &= mac_mask[i];
|
|
|
+ pfn_mac.mac[i] |= get_random_int() & ~(mac_mask[i]);
|
|
|
+ }
|
|
|
+ /* Clear multi bit */
|
|
|
+ pfn_mac.mac[0] &= 0xFE;
|
|
|
+ /* Set locally administered */
|
|
|
+ pfn_mac.mac[0] |= 0x02;
|
|
|
+
|
|
|
+ err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac,
|
|
|
+ sizeof(pfn_mac));
|
|
|
+ if (err)
|
|
|
+ brcmf_err("pfn_macaddr failed, err=%d\n", err);
|
|
|
+
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
static int
|
|
@@ -3614,11 +3648,8 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
|
|
|
}
|
|
|
|
|
|
/* configure pno */
|
|
|
- ret = brcmf_dev_pno_config(ndev);
|
|
|
- if (ret < 0) {
|
|
|
- brcmf_err("PNO setup failed!! ret=%d\n", ret);
|
|
|
+ if (brcmf_dev_pno_config(ifp, request))
|
|
|
return -EINVAL;
|
|
|
- }
|
|
|
|
|
|
/* configure each match set */
|
|
|
for (i = 0; i < request->n_match_sets; i++) {
|
|
@@ -6455,6 +6486,15 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
|
|
|
goto wiphy_unreg_out;
|
|
|
}
|
|
|
|
|
|
+ /* Fill in some of the advertised nl80211 supported features */
|
|
|
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_RANDOM_MAC)) {
|
|
|
+ wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
|
|
|
+#ifdef CONFIG_PM
|
|
|
+ if (wiphy->wowlan->flags & WIPHY_WOWLAN_NET_DETECT)
|
|
|
+ wiphy->features |= NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
|
|
|
+#endif
|
|
|
+ }
|
|
|
+
|
|
|
return cfg;
|
|
|
|
|
|
wiphy_unreg_out:
|