diff options
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 55 |
1 files changed, 38 insertions, 17 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index a54db9185747..00bd1e16c3ce 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/etherdevice.h> | 20 | #include <linux/etherdevice.h> |
21 | #include <linux/module.h> | ||
21 | #include <net/cfg80211.h> | 22 | #include <net/cfg80211.h> |
22 | #include <net/netlink.h> | 23 | #include <net/netlink.h> |
23 | 24 | ||
@@ -251,6 +252,10 @@ struct parsed_vndr_ies { | |||
251 | struct parsed_vndr_ie_info ie_info[VNDR_IE_PARSE_LIMIT]; | 252 | struct parsed_vndr_ie_info ie_info[VNDR_IE_PARSE_LIMIT]; |
252 | }; | 253 | }; |
253 | 254 | ||
255 | static int brcmf_roamoff; | ||
256 | module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR); | ||
257 | MODULE_PARM_DESC(roamoff, "do not use internal roaming engine"); | ||
258 | |||
254 | /* Quarter dBm units to mW | 259 | /* Quarter dBm units to mW |
255 | * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 | 260 | * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 |
256 | * Table is offset so the last entry is largest mW value that fits in | 261 | * Table is offset so the last entry is largest mW value that fits in |
@@ -4444,7 +4449,9 @@ static bool brcmf_is_linkdown(const struct brcmf_event_msg *e) | |||
4444 | u32 event = e->event_code; | 4449 | u32 event = e->event_code; |
4445 | u16 flags = e->flags; | 4450 | u16 flags = e->flags; |
4446 | 4451 | ||
4447 | if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) { | 4452 | if ((event == BRCMF_E_DEAUTH) || (event == BRCMF_E_DEAUTH_IND) || |
4453 | (event == BRCMF_E_DISASSOC_IND) || | ||
4454 | ((event == BRCMF_E_LINK) && (!(flags & BRCMF_EVENT_MSG_LINK)))) { | ||
4448 | brcmf_dbg(CONN, "Processing link down\n"); | 4455 | brcmf_dbg(CONN, "Processing link down\n"); |
4449 | return true; | 4456 | return true; |
4450 | } | 4457 | } |
@@ -4688,6 +4695,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, | |||
4688 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | 4695 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; |
4689 | struct ieee80211_channel *chan; | 4696 | struct ieee80211_channel *chan; |
4690 | s32 err = 0; | 4697 | s32 err = 0; |
4698 | u16 reason; | ||
4691 | 4699 | ||
4692 | if (ifp->vif->mode == WL_MODE_AP) { | 4700 | if (ifp->vif->mode == WL_MODE_AP) { |
4693 | err = brcmf_notify_connect_status_ap(cfg, ndev, e, data); | 4701 | err = brcmf_notify_connect_status_ap(cfg, ndev, e, data); |
@@ -4709,9 +4717,15 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, | |||
4709 | if (!brcmf_is_ibssmode(ifp->vif)) { | 4717 | if (!brcmf_is_ibssmode(ifp->vif)) { |
4710 | brcmf_bss_connect_done(cfg, ndev, e, false); | 4718 | brcmf_bss_connect_done(cfg, ndev, e, false); |
4711 | if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED, | 4719 | if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED, |
4712 | &ifp->vif->sme_state)) | 4720 | &ifp->vif->sme_state)) { |
4713 | cfg80211_disconnected(ndev, 0, NULL, 0, | 4721 | reason = 0; |
4722 | if (((e->event_code == BRCMF_E_DEAUTH_IND) || | ||
4723 | (e->event_code == BRCMF_E_DISASSOC_IND)) && | ||
4724 | (e->reason != WLAN_REASON_UNSPECIFIED)) | ||
4725 | reason = e->reason; | ||
4726 | cfg80211_disconnected(ndev, reason, NULL, 0, | ||
4714 | GFP_KERNEL); | 4727 | GFP_KERNEL); |
4728 | } | ||
4715 | } | 4729 | } |
4716 | brcmf_link_down(ifp->vif); | 4730 | brcmf_link_down(ifp->vif); |
4717 | brcmf_init_prof(ndev_to_prof(ndev)); | 4731 | brcmf_init_prof(ndev_to_prof(ndev)); |
@@ -4905,11 +4919,8 @@ static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg) | |||
4905 | 4919 | ||
4906 | cfg->scan_request = NULL; | 4920 | cfg->scan_request = NULL; |
4907 | cfg->pwr_save = true; | 4921 | cfg->pwr_save = true; |
4908 | cfg->roam_on = true; /* roam on & off switch. | 4922 | cfg->active_scan = true; /* we do active scan per default */ |
4909 | we enable roam per default */ | 4923 | cfg->dongle_up = false; /* dongle is not up yet */ |
4910 | cfg->active_scan = true; /* we do active scan for | ||
4911 | specific scan per default */ | ||
4912 | cfg->dongle_up = false; /* dongle is not up yet */ | ||
4913 | err = brcmf_init_priv_mem(cfg); | 4924 | err = brcmf_init_priv_mem(cfg); |
4914 | if (err) | 4925 | if (err) |
4915 | return err; | 4926 | return err; |
@@ -5029,7 +5040,7 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) | |||
5029 | } | 5040 | } |
5030 | 5041 | ||
5031 | static s32 | 5042 | static s32 |
5032 | brcmf_dongle_roam(struct brcmf_if *ifp, u32 roamvar, u32 bcn_timeout) | 5043 | brcmf_dongle_roam(struct brcmf_if *ifp, u32 bcn_timeout) |
5033 | { | 5044 | { |
5034 | s32 err = 0; | 5045 | s32 err = 0; |
5035 | __le32 roamtrigger[2]; | 5046 | __le32 roamtrigger[2]; |
@@ -5039,7 +5050,7 @@ brcmf_dongle_roam(struct brcmf_if *ifp, u32 roamvar, u32 bcn_timeout) | |||
5039 | * Setup timeout if Beacons are lost and roam is | 5050 | * Setup timeout if Beacons are lost and roam is |
5040 | * off to report link down | 5051 | * off to report link down |
5041 | */ | 5052 | */ |
5042 | if (roamvar) { | 5053 | if (brcmf_roamoff) { |
5043 | err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout); | 5054 | err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout); |
5044 | if (err) { | 5055 | if (err) { |
5045 | brcmf_err("bcn_timeout error (%d)\n", err); | 5056 | brcmf_err("bcn_timeout error (%d)\n", err); |
@@ -5051,8 +5062,9 @@ brcmf_dongle_roam(struct brcmf_if *ifp, u32 roamvar, u32 bcn_timeout) | |||
5051 | * Enable/Disable built-in roaming to allow supplicant | 5062 | * Enable/Disable built-in roaming to allow supplicant |
5052 | * to take care of roaming | 5063 | * to take care of roaming |
5053 | */ | 5064 | */ |
5054 | brcmf_dbg(INFO, "Internal Roaming = %s\n", roamvar ? "Off" : "On"); | 5065 | brcmf_dbg(INFO, "Internal Roaming = %s\n", |
5055 | err = brcmf_fil_iovar_int_set(ifp, "roam_off", roamvar); | 5066 | brcmf_roamoff ? "Off" : "On"); |
5067 | err = brcmf_fil_iovar_int_set(ifp, "roam_off", !!(brcmf_roamoff)); | ||
5056 | if (err) { | 5068 | if (err) { |
5057 | brcmf_err("roam_off error (%d)\n", err); | 5069 | brcmf_err("roam_off error (%d)\n", err); |
5058 | goto dongle_rom_out; | 5070 | goto dongle_rom_out; |
@@ -5294,6 +5306,8 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) | |||
5294 | u32 band_list[3]; | 5306 | u32 band_list[3]; |
5295 | u32 nmode; | 5307 | u32 nmode; |
5296 | u32 bw_cap[2] = { 0, 0 }; | 5308 | u32 bw_cap[2] = { 0, 0 }; |
5309 | u32 rxchain; | ||
5310 | u32 nchain; | ||
5297 | s8 phy; | 5311 | s8 phy; |
5298 | s32 err; | 5312 | s32 err; |
5299 | u32 nband; | 5313 | u32 nband; |
@@ -5330,6 +5344,16 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) | |||
5330 | brcmf_dbg(INFO, "nmode=%d, bw_cap=(%d, %d)\n", nmode, | 5344 | brcmf_dbg(INFO, "nmode=%d, bw_cap=(%d, %d)\n", nmode, |
5331 | bw_cap[IEEE80211_BAND_2GHZ], bw_cap[IEEE80211_BAND_5GHZ]); | 5345 | bw_cap[IEEE80211_BAND_2GHZ], bw_cap[IEEE80211_BAND_5GHZ]); |
5332 | 5346 | ||
5347 | err = brcmf_fil_iovar_int_get(ifp, "rxchain", &rxchain); | ||
5348 | if (err) { | ||
5349 | brcmf_err("rxchain error (%d)\n", err); | ||
5350 | nchain = 1; | ||
5351 | } else { | ||
5352 | for (nchain = 0; rxchain; nchain++) | ||
5353 | rxchain = rxchain & (rxchain - 1); | ||
5354 | } | ||
5355 | brcmf_dbg(INFO, "nchain=%d\n", nchain); | ||
5356 | |||
5333 | err = brcmf_construct_reginfo(cfg, bw_cap); | 5357 | err = brcmf_construct_reginfo(cfg, bw_cap); |
5334 | if (err) { | 5358 | if (err) { |
5335 | brcmf_err("brcmf_construct_reginfo failed (%d)\n", err); | 5359 | brcmf_err("brcmf_construct_reginfo failed (%d)\n", err); |
@@ -5358,10 +5382,7 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) | |||
5358 | band->ht_cap.ht_supported = true; | 5382 | band->ht_cap.ht_supported = true; |
5359 | band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | 5383 | band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; |
5360 | band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; | 5384 | band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; |
5361 | /* An HT shall support all EQM rates for one spatial | 5385 | memset(band->ht_cap.mcs.rx_mask, 0xff, nchain); |
5362 | * stream | ||
5363 | */ | ||
5364 | band->ht_cap.mcs.rx_mask[0] = 0xff; | ||
5365 | band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | 5386 | band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; |
5366 | bands[band->band] = band; | 5387 | bands[band->band] = band; |
5367 | } | 5388 | } |
@@ -5408,7 +5429,7 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) | |||
5408 | brcmf_dbg(INFO, "power save set to %s\n", | 5429 | brcmf_dbg(INFO, "power save set to %s\n", |
5409 | (power_mode ? "enabled" : "disabled")); | 5430 | (power_mode ? "enabled" : "disabled")); |
5410 | 5431 | ||
5411 | err = brcmf_dongle_roam(ifp, (cfg->roam_on ? 0 : 1), WL_BEACON_TIMEOUT); | 5432 | err = brcmf_dongle_roam(ifp, WL_BEACON_TIMEOUT); |
5412 | if (err) | 5433 | if (err) |
5413 | goto default_conf_out; | 5434 | goto default_conf_out; |
5414 | err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype, | 5435 | err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype, |