Loading MAINTAINERS +1 −0 Original line number Diff line number Diff line Loading @@ -1595,6 +1595,7 @@ M: Arend van Spriel <arend@broadcom.com> M: Franky (Zhenhui) Lin <frankyl@broadcom.com> M: Kan Yan <kanyan@broadcom.com> L: linux-wireless@vger.kernel.org L: brcm80211-dev-list@broadcom.com S: Supported F: drivers/net/wireless/brcm80211/ Loading drivers/bcma/scan.c +6 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,12 @@ static const struct bcma_device_id_name bcma_arm_device_names[] = { static const struct bcma_device_id_name bcma_bcm_device_names[] = { { BCMA_CORE_OOB_ROUTER, "OOB Router" }, { BCMA_CORE_4706_CHIPCOMMON, "BCM4706 ChipCommon" }, { BCMA_CORE_4706_SOC_RAM, "BCM4706 SOC RAM" }, { BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" }, { BCMA_CORE_AMEMC, "AMEMC (DDR)" }, { BCMA_CORE_ALTA, "ALTA (I2S)" }, { BCMA_CORE_4706_MAC_GBIT_COMMON, "BCM4706 GBit MAC Common" }, { BCMA_CORE_INVALID, "Invalid" }, { BCMA_CORE_CHIPCOMMON, "ChipCommon" }, { BCMA_CORE_ILINE20, "ILine 20" }, Loading drivers/net/wireless/ath/ath6kl/cfg80211.c +174 −34 Original line number Diff line number Diff line Loading @@ -53,6 +53,11 @@ #define DEFAULT_BG_SCAN_PERIOD 60 struct ath6kl_cfg80211_match_probe_ssid { struct cfg80211_ssid ssid; u8 flag; }; static struct ieee80211_rate ath6kl_rates[] = { RATETAB_ENT(10, 0x1, 0), RATETAB_ENT(20, 0x2, 0), Loading Loading @@ -576,6 +581,9 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, vif->nw_type = vif->next_mode; /* enable enhanced bmiss detection if applicable */ ath6kl_cfg80211_sta_bmiss_enhance(vif, true); if (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) nw_subtype = SUBTYPE_P2PCLIENT; Loading Loading @@ -852,20 +860,6 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason, } } /* * Send a disconnect command to target when a disconnect event is * received with reason code other than 3 (DISCONNECT_CMD - disconnect * request from host) to make the firmware stop trying to connect even * after giving disconnect event. There will be one more disconnect * event for this disconnect command with reason code DISCONNECT_CMD * which will be notified to cfg80211. */ if (reason != DISCONNECT_CMD) { ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx); return; } clear_bit(CONNECT_PEND, &vif->flags); if (vif->sme_state == SME_CONNECTING) { Loading @@ -875,32 +869,96 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason, WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); } else if (vif->sme_state == SME_CONNECTED) { cfg80211_disconnected(vif->ndev, reason, cfg80211_disconnected(vif->ndev, proto_reason, NULL, 0, GFP_KERNEL); } vif->sme_state = SME_DISCONNECTED; /* * Send a disconnect command to target when a disconnect event is * received with reason code other than 3 (DISCONNECT_CMD - disconnect * request from host) to make the firmware stop trying to connect even * after giving disconnect event. There will be one more disconnect * event for this disconnect command with reason code DISCONNECT_CMD * which won't be notified to cfg80211. */ if (reason != DISCONNECT_CMD) ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx); } static int ath6kl_set_probed_ssids(struct ath6kl *ar, struct ath6kl_vif *vif, struct cfg80211_ssid *ssids, int n_ssids) struct cfg80211_ssid *ssids, int n_ssids, struct cfg80211_match_set *match_set, int n_match_ssid) { u8 i; u8 i, j, index_to_add, ssid_found = false; struct ath6kl_cfg80211_match_probe_ssid ssid_list[MAX_PROBED_SSIDS]; if (n_ssids > MAX_PROBED_SSID_INDEX) memset(ssid_list, 0, sizeof(ssid_list)); if (n_ssids > MAX_PROBED_SSIDS || n_match_ssid > MAX_PROBED_SSIDS) return -EINVAL; for (i = 0; i < n_ssids; i++) { memcpy(ssid_list[i].ssid.ssid, ssids[i].ssid, ssids[i].ssid_len); ssid_list[i].ssid.ssid_len = ssids[i].ssid_len; if (ssids[i].ssid_len) ssid_list[i].flag = SPECIFIC_SSID_FLAG; else ssid_list[i].flag = ANY_SSID_FLAG; if (n_match_ssid == 0) ssid_list[i].flag |= MATCH_SSID_FLAG; } index_to_add = i; for (i = 0; i < n_match_ssid; i++) { ssid_found = false; for (j = 0; j < n_ssids; j++) { if ((match_set[i].ssid.ssid_len == ssid_list[j].ssid.ssid_len) && (!memcmp(ssid_list[j].ssid.ssid, match_set[i].ssid.ssid, match_set[i].ssid.ssid_len))) { ssid_list[j].flag |= MATCH_SSID_FLAG; ssid_found = true; break; } } if (ssid_found) continue; if (index_to_add >= MAX_PROBED_SSIDS) continue; ssid_list[index_to_add].ssid.ssid_len = match_set[i].ssid.ssid_len; memcpy(ssid_list[index_to_add].ssid.ssid, match_set[i].ssid.ssid, match_set[i].ssid.ssid_len); ssid_list[index_to_add].flag |= MATCH_SSID_FLAG; index_to_add++; } for (i = 0; i < index_to_add; i++) { ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, ssids[i].ssid_len ? SPECIFIC_SSID_FLAG : ANY_SSID_FLAG, ssids[i].ssid_len, ssids[i].ssid); ssid_list[i].flag, ssid_list[i].ssid.ssid_len, ssid_list[i].ssid.ssid); } /* Make sure no old entries are left behind */ for (i = n_ssids; i < MAX_PROBED_SSID_INDEX; i++) { for (i = index_to_add; i < MAX_PROBED_SSIDS; i++) { ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, DISABLE_SSID_FLAG, 0, NULL); } Loading Loading @@ -934,7 +992,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, } ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, request->n_ssids); request->n_ssids, NULL, 0); if (ret < 0) return ret; Loading @@ -943,7 +1001,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, WMI_FRAME_PROBE_REQ, request->ie, request->ie_len); if (ret) { ath6kl_err("failed to set Probe Request appie for scan"); ath6kl_err("failed to set Probe Request appie for scan\n"); return ret; } Loading Loading @@ -1512,6 +1570,9 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy, } } /* need to clean up enhanced bmiss detection fw state */ ath6kl_cfg80211_sta_bmiss_enhance(vif, false); set_iface_type: switch (type) { case NL80211_IFTYPE_STATION: Loading Loading @@ -2074,7 +2135,9 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST)) return -EINVAL; if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags)) { if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags) && test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, ar->fw_capabilities)) { ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx, false); if (ret) Loading Loading @@ -2209,7 +2272,9 @@ static int ath6kl_wow_resume(struct ath6kl *ar) ar->state = ATH6KL_STATE_ON; if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags)) { if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags) && test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, ar->fw_capabilities)) { ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx, true); if (ret) Loading Loading @@ -2475,7 +2540,7 @@ void ath6kl_check_wow_status(struct ath6kl *ar) static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band, bool ht_enable) { struct ath6kl_htcap *htcap = &vif->htcap; struct ath6kl_htcap *htcap = &vif->htcap[band]; if (htcap->ht_enable == ht_enable) return 0; Loading Loading @@ -2585,6 +2650,30 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif, return 0; } void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable) { int err; if (WARN_ON(!test_bit(WMI_READY, &vif->ar->flag))) return; if (vif->nw_type != INFRA_NETWORK) return; if (!test_bit(ATH6KL_FW_CAPABILITY_BMISS_ENHANCE, vif->ar->fw_capabilities)) return; ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s fw bmiss enhance\n", enable ? "enable" : "disable"); err = ath6kl_wmi_sta_bmiss_enhance_cmd(vif->ar->wmi, vif->fw_vif_idx, enable); if (err) ath6kl_err("failed to %s enhanced bmiss detection: %d\n", enable ? "enable" : "disable", err); } static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon, u8 *rsn_capab) { Loading Loading @@ -2665,9 +2754,15 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, /* TODO: * info->interval * info->dtim_period */ ret = ath6kl_wmi_ap_set_dtim_cmd(ar->wmi, vif->fw_vif_idx, info->dtim_period); /* ignore error, just print a warning and continue normally */ if (ret) ath6kl_warn("Failed to set dtim_period in beacon: %d\n", ret); if (info->beacon.head == NULL) return -EINVAL; mgmt = (struct ieee80211_mgmt *) info->beacon.head; Loading Loading @@ -3131,9 +3226,23 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, ath6kl_cfg80211_scan_complete_event(vif, true); ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, request->n_ssids); request->n_ssids, request->match_sets, request->n_match_sets); if (ret < 0) return ret; if (!request->n_match_sets) { ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, ALL_BSS_FILTER, 0); if (ret < 0) return ret; } else { ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, MATCHED_SSID_FILTER, 0); if (ret < 0) return ret; } /* fw uses seconds, also make sure that it's >0 */ interval = max_t(u16, 1, request->interval / 1000); Loading @@ -3156,7 +3265,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, WMI_FRAME_PROBE_REQ, request->ie, request->ie_len); if (ret) { ath6kl_warn("Failed to set probe request IE for scheduled scan: %d", ath6kl_warn("Failed to set probe request IE for scheduled scan: %d\n", ret); return ret; } Loading Loading @@ -3188,6 +3297,18 @@ static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy, return 0; } static int ath6kl_cfg80211_set_bitrate(struct wiphy *wiphy, struct net_device *dev, const u8 *addr, const struct cfg80211_bitrate_mask *mask) { struct ath6kl *ar = ath6kl_priv(dev); struct ath6kl_vif *vif = netdev_priv(dev); return ath6kl_wmi_set_bitrate_mask(ar->wmi, vif->fw_vif_idx, mask); } static const struct ieee80211_txrx_stypes ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = { [NL80211_IFTYPE_STATION] = { Loading Loading @@ -3253,6 +3374,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { .mgmt_frame_register = ath6kl_mgmt_frame_register, .sched_scan_start = ath6kl_cfg80211_sscan_start, .sched_scan_stop = ath6kl_cfg80211_sscan_stop, .set_bitrate_mask = ath6kl_cfg80211_set_bitrate, }; void ath6kl_cfg80211_stop(struct ath6kl_vif *vif) Loading Loading @@ -3380,7 +3502,8 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL; vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME; vif->bg_scan_period = 0; vif->htcap.ht_enable = true; vif->htcap[IEEE80211_BAND_2GHZ].ht_enable = true; vif->htcap[IEEE80211_BAND_5GHZ].ht_enable = true; memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); if (fw_vif_idx != 0) Loading Loading @@ -3440,7 +3563,13 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) } /* max num of ssids that can be probed during scanning */ wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; wiphy->max_scan_ssids = MAX_PROBED_SSIDS; /* max num of ssids that can be matched after scan */ if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST, ar->fw_capabilities)) wiphy->max_match_sets = MAX_PROBED_SSIDS; wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ switch (ar->hw.cap) { case WMI_11AN_CAP: Loading Loading @@ -3477,6 +3606,17 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) ath6kl_band_5ghz.ht_cap.cap = 0; ath6kl_band_5ghz.ht_cap.ht_supported = false; } if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES) { ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff; ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff; } else { ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; } if (band_2gig) wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; if (band_5gig) Loading @@ -3497,7 +3637,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) wiphy->wowlan.pattern_min_len = 1; wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; wiphy->max_sched_scan_ssids = MAX_PROBED_SSID_INDEX; wiphy->max_sched_scan_ssids = MAX_PROBED_SSIDS; ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | WIPHY_FLAG_HAVE_AP_SME | Loading drivers/net/wireless/ath/ath6kl/cfg80211.h +2 −0 Original line number Diff line number Diff line Loading @@ -62,5 +62,7 @@ void ath6kl_cfg80211_cleanup(struct ath6kl *ar); struct ath6kl *ath6kl_cfg80211_create(void); void ath6kl_cfg80211_destroy(struct ath6kl *ar); /* TODO: remove this once ath6kl_vif_cleanup() is moved to cfg80211.c */ void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable); #endif /* ATH6KL_CFG80211_H */ drivers/net/wireless/ath/ath6kl/core.h +32 −6 Original line number Diff line number Diff line Loading @@ -100,6 +100,21 @@ enum ath6kl_fw_capability { /* Firmware has support to override rsn cap of rsn ie */ ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, /* * Multicast support in WOW and host awake mode. * Allow all multicast in host awake mode. * Apply multicast filter in WOW mode. */ ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, /* Firmware supports enhanced bmiss detection */ ATH6KL_FW_CAPABILITY_BMISS_ENHANCE, /* * FW supports matching of ssid in schedule scan */ ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST, /* this needs to be last */ ATH6KL_FW_CAPABILITY_MAX, }; Loading @@ -112,6 +127,10 @@ struct ath6kl_fw_ie { u8 data[0]; }; enum ath6kl_hw_flags { ATH6KL_HW_FLAG_64BIT_RATES = BIT(0), }; #define ATH6KL_FW_API2_FILE "fw-2.bin" #define ATH6KL_FW_API3_FILE "fw-3.bin" Loading Loading @@ -196,7 +215,7 @@ struct ath6kl_fw_ie { #define AGGR_NUM_OF_FREE_NETBUFS 16 #define AGGR_RX_TIMEOUT 400 /* in ms */ #define AGGR_RX_TIMEOUT 100 /* in ms */ #define WMI_TIMEOUT (2 * HZ) Loading Loading @@ -245,7 +264,6 @@ struct skb_hold_q { struct rxtid { bool aggr; bool progress; bool timer_mon; u16 win_sz; u16 seq_next; Loading @@ -254,9 +272,15 @@ struct rxtid { struct sk_buff_head q; /* * FIXME: No clue what this should protect. Apparently it should * protect some of the fields above but they are also accessed * without taking the lock. * lock mainly protects seq_next and hold_q. Movement of seq_next * needs to be protected between aggr_timeout() and * aggr_process_recv_frm(). hold_q will be holding the pending * reorder frames and it's access should also be protected. * Some of the other fields like hold_q_sz, win_sz and aggr are * initialized/reset when receiving addba/delba req, also while * deleting aggr state all the pending buffers are flushed before * resetting these fields, so there should not be any race in accessing * these fields. */ spinlock_t lock; }; Loading Loading @@ -541,7 +565,7 @@ struct ath6kl_vif { struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1]; struct aggr_info *aggr_cntxt; struct ath6kl_htcap htcap; struct ath6kl_htcap htcap[IEEE80211_NUM_BANDS]; struct timer_list disconnect_timer; struct timer_list sched_scan_timer; Loading Loading @@ -684,6 +708,8 @@ struct ath6kl { u32 testscript_addr; enum wmi_phy_cap cap; u32 flags; struct ath6kl_hw_fw { const char *dir; const char *otp; Loading Loading
MAINTAINERS +1 −0 Original line number Diff line number Diff line Loading @@ -1595,6 +1595,7 @@ M: Arend van Spriel <arend@broadcom.com> M: Franky (Zhenhui) Lin <frankyl@broadcom.com> M: Kan Yan <kanyan@broadcom.com> L: linux-wireless@vger.kernel.org L: brcm80211-dev-list@broadcom.com S: Supported F: drivers/net/wireless/brcm80211/ Loading
drivers/bcma/scan.c +6 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,12 @@ static const struct bcma_device_id_name bcma_arm_device_names[] = { static const struct bcma_device_id_name bcma_bcm_device_names[] = { { BCMA_CORE_OOB_ROUTER, "OOB Router" }, { BCMA_CORE_4706_CHIPCOMMON, "BCM4706 ChipCommon" }, { BCMA_CORE_4706_SOC_RAM, "BCM4706 SOC RAM" }, { BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" }, { BCMA_CORE_AMEMC, "AMEMC (DDR)" }, { BCMA_CORE_ALTA, "ALTA (I2S)" }, { BCMA_CORE_4706_MAC_GBIT_COMMON, "BCM4706 GBit MAC Common" }, { BCMA_CORE_INVALID, "Invalid" }, { BCMA_CORE_CHIPCOMMON, "ChipCommon" }, { BCMA_CORE_ILINE20, "ILine 20" }, Loading
drivers/net/wireless/ath/ath6kl/cfg80211.c +174 −34 Original line number Diff line number Diff line Loading @@ -53,6 +53,11 @@ #define DEFAULT_BG_SCAN_PERIOD 60 struct ath6kl_cfg80211_match_probe_ssid { struct cfg80211_ssid ssid; u8 flag; }; static struct ieee80211_rate ath6kl_rates[] = { RATETAB_ENT(10, 0x1, 0), RATETAB_ENT(20, 0x2, 0), Loading Loading @@ -576,6 +581,9 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, vif->nw_type = vif->next_mode; /* enable enhanced bmiss detection if applicable */ ath6kl_cfg80211_sta_bmiss_enhance(vif, true); if (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) nw_subtype = SUBTYPE_P2PCLIENT; Loading Loading @@ -852,20 +860,6 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason, } } /* * Send a disconnect command to target when a disconnect event is * received with reason code other than 3 (DISCONNECT_CMD - disconnect * request from host) to make the firmware stop trying to connect even * after giving disconnect event. There will be one more disconnect * event for this disconnect command with reason code DISCONNECT_CMD * which will be notified to cfg80211. */ if (reason != DISCONNECT_CMD) { ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx); return; } clear_bit(CONNECT_PEND, &vif->flags); if (vif->sme_state == SME_CONNECTING) { Loading @@ -875,32 +869,96 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason, WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); } else if (vif->sme_state == SME_CONNECTED) { cfg80211_disconnected(vif->ndev, reason, cfg80211_disconnected(vif->ndev, proto_reason, NULL, 0, GFP_KERNEL); } vif->sme_state = SME_DISCONNECTED; /* * Send a disconnect command to target when a disconnect event is * received with reason code other than 3 (DISCONNECT_CMD - disconnect * request from host) to make the firmware stop trying to connect even * after giving disconnect event. There will be one more disconnect * event for this disconnect command with reason code DISCONNECT_CMD * which won't be notified to cfg80211. */ if (reason != DISCONNECT_CMD) ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx); } static int ath6kl_set_probed_ssids(struct ath6kl *ar, struct ath6kl_vif *vif, struct cfg80211_ssid *ssids, int n_ssids) struct cfg80211_ssid *ssids, int n_ssids, struct cfg80211_match_set *match_set, int n_match_ssid) { u8 i; u8 i, j, index_to_add, ssid_found = false; struct ath6kl_cfg80211_match_probe_ssid ssid_list[MAX_PROBED_SSIDS]; if (n_ssids > MAX_PROBED_SSID_INDEX) memset(ssid_list, 0, sizeof(ssid_list)); if (n_ssids > MAX_PROBED_SSIDS || n_match_ssid > MAX_PROBED_SSIDS) return -EINVAL; for (i = 0; i < n_ssids; i++) { memcpy(ssid_list[i].ssid.ssid, ssids[i].ssid, ssids[i].ssid_len); ssid_list[i].ssid.ssid_len = ssids[i].ssid_len; if (ssids[i].ssid_len) ssid_list[i].flag = SPECIFIC_SSID_FLAG; else ssid_list[i].flag = ANY_SSID_FLAG; if (n_match_ssid == 0) ssid_list[i].flag |= MATCH_SSID_FLAG; } index_to_add = i; for (i = 0; i < n_match_ssid; i++) { ssid_found = false; for (j = 0; j < n_ssids; j++) { if ((match_set[i].ssid.ssid_len == ssid_list[j].ssid.ssid_len) && (!memcmp(ssid_list[j].ssid.ssid, match_set[i].ssid.ssid, match_set[i].ssid.ssid_len))) { ssid_list[j].flag |= MATCH_SSID_FLAG; ssid_found = true; break; } } if (ssid_found) continue; if (index_to_add >= MAX_PROBED_SSIDS) continue; ssid_list[index_to_add].ssid.ssid_len = match_set[i].ssid.ssid_len; memcpy(ssid_list[index_to_add].ssid.ssid, match_set[i].ssid.ssid, match_set[i].ssid.ssid_len); ssid_list[index_to_add].flag |= MATCH_SSID_FLAG; index_to_add++; } for (i = 0; i < index_to_add; i++) { ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, ssids[i].ssid_len ? SPECIFIC_SSID_FLAG : ANY_SSID_FLAG, ssids[i].ssid_len, ssids[i].ssid); ssid_list[i].flag, ssid_list[i].ssid.ssid_len, ssid_list[i].ssid.ssid); } /* Make sure no old entries are left behind */ for (i = n_ssids; i < MAX_PROBED_SSID_INDEX; i++) { for (i = index_to_add; i < MAX_PROBED_SSIDS; i++) { ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, DISABLE_SSID_FLAG, 0, NULL); } Loading Loading @@ -934,7 +992,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, } ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, request->n_ssids); request->n_ssids, NULL, 0); if (ret < 0) return ret; Loading @@ -943,7 +1001,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, WMI_FRAME_PROBE_REQ, request->ie, request->ie_len); if (ret) { ath6kl_err("failed to set Probe Request appie for scan"); ath6kl_err("failed to set Probe Request appie for scan\n"); return ret; } Loading Loading @@ -1512,6 +1570,9 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy, } } /* need to clean up enhanced bmiss detection fw state */ ath6kl_cfg80211_sta_bmiss_enhance(vif, false); set_iface_type: switch (type) { case NL80211_IFTYPE_STATION: Loading Loading @@ -2074,7 +2135,9 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST)) return -EINVAL; if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags)) { if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags) && test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, ar->fw_capabilities)) { ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx, false); if (ret) Loading Loading @@ -2209,7 +2272,9 @@ static int ath6kl_wow_resume(struct ath6kl *ar) ar->state = ATH6KL_STATE_ON; if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags)) { if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags) && test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, ar->fw_capabilities)) { ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx, true); if (ret) Loading Loading @@ -2475,7 +2540,7 @@ void ath6kl_check_wow_status(struct ath6kl *ar) static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band, bool ht_enable) { struct ath6kl_htcap *htcap = &vif->htcap; struct ath6kl_htcap *htcap = &vif->htcap[band]; if (htcap->ht_enable == ht_enable) return 0; Loading Loading @@ -2585,6 +2650,30 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif, return 0; } void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable) { int err; if (WARN_ON(!test_bit(WMI_READY, &vif->ar->flag))) return; if (vif->nw_type != INFRA_NETWORK) return; if (!test_bit(ATH6KL_FW_CAPABILITY_BMISS_ENHANCE, vif->ar->fw_capabilities)) return; ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s fw bmiss enhance\n", enable ? "enable" : "disable"); err = ath6kl_wmi_sta_bmiss_enhance_cmd(vif->ar->wmi, vif->fw_vif_idx, enable); if (err) ath6kl_err("failed to %s enhanced bmiss detection: %d\n", enable ? "enable" : "disable", err); } static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon, u8 *rsn_capab) { Loading Loading @@ -2665,9 +2754,15 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, /* TODO: * info->interval * info->dtim_period */ ret = ath6kl_wmi_ap_set_dtim_cmd(ar->wmi, vif->fw_vif_idx, info->dtim_period); /* ignore error, just print a warning and continue normally */ if (ret) ath6kl_warn("Failed to set dtim_period in beacon: %d\n", ret); if (info->beacon.head == NULL) return -EINVAL; mgmt = (struct ieee80211_mgmt *) info->beacon.head; Loading Loading @@ -3131,9 +3226,23 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, ath6kl_cfg80211_scan_complete_event(vif, true); ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, request->n_ssids); request->n_ssids, request->match_sets, request->n_match_sets); if (ret < 0) return ret; if (!request->n_match_sets) { ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, ALL_BSS_FILTER, 0); if (ret < 0) return ret; } else { ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, MATCHED_SSID_FILTER, 0); if (ret < 0) return ret; } /* fw uses seconds, also make sure that it's >0 */ interval = max_t(u16, 1, request->interval / 1000); Loading @@ -3156,7 +3265,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, WMI_FRAME_PROBE_REQ, request->ie, request->ie_len); if (ret) { ath6kl_warn("Failed to set probe request IE for scheduled scan: %d", ath6kl_warn("Failed to set probe request IE for scheduled scan: %d\n", ret); return ret; } Loading Loading @@ -3188,6 +3297,18 @@ static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy, return 0; } static int ath6kl_cfg80211_set_bitrate(struct wiphy *wiphy, struct net_device *dev, const u8 *addr, const struct cfg80211_bitrate_mask *mask) { struct ath6kl *ar = ath6kl_priv(dev); struct ath6kl_vif *vif = netdev_priv(dev); return ath6kl_wmi_set_bitrate_mask(ar->wmi, vif->fw_vif_idx, mask); } static const struct ieee80211_txrx_stypes ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = { [NL80211_IFTYPE_STATION] = { Loading Loading @@ -3253,6 +3374,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { .mgmt_frame_register = ath6kl_mgmt_frame_register, .sched_scan_start = ath6kl_cfg80211_sscan_start, .sched_scan_stop = ath6kl_cfg80211_sscan_stop, .set_bitrate_mask = ath6kl_cfg80211_set_bitrate, }; void ath6kl_cfg80211_stop(struct ath6kl_vif *vif) Loading Loading @@ -3380,7 +3502,8 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL; vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME; vif->bg_scan_period = 0; vif->htcap.ht_enable = true; vif->htcap[IEEE80211_BAND_2GHZ].ht_enable = true; vif->htcap[IEEE80211_BAND_5GHZ].ht_enable = true; memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); if (fw_vif_idx != 0) Loading Loading @@ -3440,7 +3563,13 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) } /* max num of ssids that can be probed during scanning */ wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; wiphy->max_scan_ssids = MAX_PROBED_SSIDS; /* max num of ssids that can be matched after scan */ if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST, ar->fw_capabilities)) wiphy->max_match_sets = MAX_PROBED_SSIDS; wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ switch (ar->hw.cap) { case WMI_11AN_CAP: Loading Loading @@ -3477,6 +3606,17 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) ath6kl_band_5ghz.ht_cap.cap = 0; ath6kl_band_5ghz.ht_cap.ht_supported = false; } if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES) { ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff; ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff; } else { ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; } if (band_2gig) wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; if (band_5gig) Loading @@ -3497,7 +3637,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) wiphy->wowlan.pattern_min_len = 1; wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; wiphy->max_sched_scan_ssids = MAX_PROBED_SSID_INDEX; wiphy->max_sched_scan_ssids = MAX_PROBED_SSIDS; ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | WIPHY_FLAG_HAVE_AP_SME | Loading
drivers/net/wireless/ath/ath6kl/cfg80211.h +2 −0 Original line number Diff line number Diff line Loading @@ -62,5 +62,7 @@ void ath6kl_cfg80211_cleanup(struct ath6kl *ar); struct ath6kl *ath6kl_cfg80211_create(void); void ath6kl_cfg80211_destroy(struct ath6kl *ar); /* TODO: remove this once ath6kl_vif_cleanup() is moved to cfg80211.c */ void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable); #endif /* ATH6KL_CFG80211_H */
drivers/net/wireless/ath/ath6kl/core.h +32 −6 Original line number Diff line number Diff line Loading @@ -100,6 +100,21 @@ enum ath6kl_fw_capability { /* Firmware has support to override rsn cap of rsn ie */ ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, /* * Multicast support in WOW and host awake mode. * Allow all multicast in host awake mode. * Apply multicast filter in WOW mode. */ ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, /* Firmware supports enhanced bmiss detection */ ATH6KL_FW_CAPABILITY_BMISS_ENHANCE, /* * FW supports matching of ssid in schedule scan */ ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST, /* this needs to be last */ ATH6KL_FW_CAPABILITY_MAX, }; Loading @@ -112,6 +127,10 @@ struct ath6kl_fw_ie { u8 data[0]; }; enum ath6kl_hw_flags { ATH6KL_HW_FLAG_64BIT_RATES = BIT(0), }; #define ATH6KL_FW_API2_FILE "fw-2.bin" #define ATH6KL_FW_API3_FILE "fw-3.bin" Loading Loading @@ -196,7 +215,7 @@ struct ath6kl_fw_ie { #define AGGR_NUM_OF_FREE_NETBUFS 16 #define AGGR_RX_TIMEOUT 400 /* in ms */ #define AGGR_RX_TIMEOUT 100 /* in ms */ #define WMI_TIMEOUT (2 * HZ) Loading Loading @@ -245,7 +264,6 @@ struct skb_hold_q { struct rxtid { bool aggr; bool progress; bool timer_mon; u16 win_sz; u16 seq_next; Loading @@ -254,9 +272,15 @@ struct rxtid { struct sk_buff_head q; /* * FIXME: No clue what this should protect. Apparently it should * protect some of the fields above but they are also accessed * without taking the lock. * lock mainly protects seq_next and hold_q. Movement of seq_next * needs to be protected between aggr_timeout() and * aggr_process_recv_frm(). hold_q will be holding the pending * reorder frames and it's access should also be protected. * Some of the other fields like hold_q_sz, win_sz and aggr are * initialized/reset when receiving addba/delba req, also while * deleting aggr state all the pending buffers are flushed before * resetting these fields, so there should not be any race in accessing * these fields. */ spinlock_t lock; }; Loading Loading @@ -541,7 +565,7 @@ struct ath6kl_vif { struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1]; struct aggr_info *aggr_cntxt; struct ath6kl_htcap htcap; struct ath6kl_htcap htcap[IEEE80211_NUM_BANDS]; struct timer_list disconnect_timer; struct timer_list sched_scan_timer; Loading Loading @@ -684,6 +708,8 @@ struct ath6kl { u32 testscript_addr; enum wmi_phy_cap cap; u32 flags; struct ath6kl_hw_fw { const char *dir; const char *otp; Loading