aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac
diff options
context:
space:
mode:
authorArend van Spriel <arend@broadcom.com>2014-07-12 02:49:41 -0400
committerJohn W. Linville <linville@tuxdriver.com>2014-07-15 16:00:15 -0400
commitb48d891676f756d48b4d0ee131e4a7a5d43ca417 (patch)
tree96b060ee545726ea98719671cc3cafa115d40cf7 /drivers/net/wireless/brcm80211/brcmfmac
parentaa70b4fa43dfe5dc3df2161d814ccaa7897d73c9 (diff)
brcmfmac: rework wiphy structure setup
Instead of waiting for IFF_UP of the primary net device to determine the band and channel information of the wiphy structure, this is now done during driver initialization in brcmf_cfg80211_attach(). The channel information is obtained from the device and the 2G band is updated when 40MHz bandwidth is enabled for that band. Before this change the band and channel objects were common between multiple brcmfmac devices in the system, which make that information rather unreliable. That is also fixed with this reworked implementation. Reviewed-by: Hante Meuleman <meuleman@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c566
1 files changed, 298 insertions, 268 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index d0b48dd4f154..d3bb4e0f4480 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -103,24 +103,6 @@ static bool check_vif_up(struct brcmf_cfg80211_vif *vif)
103 return true; 103 return true;
104} 104}
105 105
106#define CHAN2G(_channel, _freq, _flags) { \
107 .band = IEEE80211_BAND_2GHZ, \
108 .center_freq = (_freq), \
109 .hw_value = (_channel), \
110 .flags = (_flags), \
111 .max_antenna_gain = 0, \
112 .max_power = 30, \
113}
114
115#define CHAN5G(_channel, _flags) { \
116 .band = IEEE80211_BAND_5GHZ, \
117 .center_freq = 5000 + (5 * (_channel)), \
118 .hw_value = (_channel), \
119 .flags = (_flags), \
120 .max_antenna_gain = 0, \
121 .max_power = 30, \
122}
123
124#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2) 106#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
125#define RATETAB_ENT(_rateid, _flags) \ 107#define RATETAB_ENT(_rateid, _flags) \
126 { \ 108 { \
@@ -149,58 +131,17 @@ static struct ieee80211_rate __wl_rates[] = {
149#define wl_g_rates (__wl_rates + 0) 131#define wl_g_rates (__wl_rates + 0)
150#define wl_g_rates_size 12 132#define wl_g_rates_size 12
151 133
152static struct ieee80211_channel __wl_2ghz_channels[] = { 134/* Band templates duplicated per wiphy. The channel info
153 CHAN2G(1, 2412, 0), 135 * is filled in after querying the device.
154 CHAN2G(2, 2417, 0), 136 */
155 CHAN2G(3, 2422, 0), 137static const struct ieee80211_supported_band __wl_band_2ghz = {
156 CHAN2G(4, 2427, 0),
157 CHAN2G(5, 2432, 0),
158 CHAN2G(6, 2437, 0),
159 CHAN2G(7, 2442, 0),
160 CHAN2G(8, 2447, 0),
161 CHAN2G(9, 2452, 0),
162 CHAN2G(10, 2457, 0),
163 CHAN2G(11, 2462, 0),
164 CHAN2G(12, 2467, 0),
165 CHAN2G(13, 2472, 0),
166 CHAN2G(14, 2484, 0),
167};
168
169static struct ieee80211_channel __wl_5ghz_a_channels[] = {
170 CHAN5G(34, 0), CHAN5G(36, 0),
171 CHAN5G(38, 0), CHAN5G(40, 0),
172 CHAN5G(42, 0), CHAN5G(44, 0),
173 CHAN5G(46, 0), CHAN5G(48, 0),
174 CHAN5G(52, 0), CHAN5G(56, 0),
175 CHAN5G(60, 0), CHAN5G(64, 0),
176 CHAN5G(100, 0), CHAN5G(104, 0),
177 CHAN5G(108, 0), CHAN5G(112, 0),
178 CHAN5G(116, 0), CHAN5G(120, 0),
179 CHAN5G(124, 0), CHAN5G(128, 0),
180 CHAN5G(132, 0), CHAN5G(136, 0),
181 CHAN5G(140, 0), CHAN5G(149, 0),
182 CHAN5G(153, 0), CHAN5G(157, 0),
183 CHAN5G(161, 0), CHAN5G(165, 0),
184 CHAN5G(184, 0), CHAN5G(188, 0),
185 CHAN5G(192, 0), CHAN5G(196, 0),
186 CHAN5G(200, 0), CHAN5G(204, 0),
187 CHAN5G(208, 0), CHAN5G(212, 0),
188 CHAN5G(216, 0),
189};
190
191static struct ieee80211_supported_band __wl_band_2ghz = {
192 .band = IEEE80211_BAND_2GHZ, 138 .band = IEEE80211_BAND_2GHZ,
193 .channels = __wl_2ghz_channels,
194 .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
195 .bitrates = wl_g_rates, 139 .bitrates = wl_g_rates,
196 .n_bitrates = wl_g_rates_size, 140 .n_bitrates = wl_g_rates_size,
197 .ht_cap = {IEEE80211_HT_CAP_SUP_WIDTH_20_40, true},
198}; 141};
199 142
200static struct ieee80211_supported_band __wl_band_5ghz_a = { 143static const struct ieee80211_supported_band __wl_band_5ghz_a = {
201 .band = IEEE80211_BAND_5GHZ, 144 .band = IEEE80211_BAND_5GHZ,
202 .channels = __wl_5ghz_a_channels,
203 .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
204 .bitrates = wl_a_rates, 145 .bitrates = wl_a_rates,
205 .n_bitrates = wl_a_rates_size, 146 .n_bitrates = wl_a_rates_size,
206}; 147};
@@ -4913,25 +4854,77 @@ dongle_scantime_out:
4913 return err; 4854 return err;
4914} 4855}
4915 4856
4857/* Filter the list of channels received from firmware counting only
4858 * the 20MHz channels. The wiphy band data only needs those which get
4859 * flagged to indicate if they can take part in higher bandwidth.
4860 */
4861static void brcmf_count_20mhz_channels(struct brcmf_cfg80211_info *cfg,
4862 struct brcmf_chanspec_list *chlist,
4863 u32 chcnt[])
4864{
4865 u32 total = le32_to_cpu(chlist->count);
4866 struct brcmu_chan ch;
4867 int i;
4868
4869 for (i = 0; i <= total; i++) {
4870 ch.chspec = (u16)le32_to_cpu(chlist->element[i]);
4871 cfg->d11inf.decchspec(&ch);
4872
4873 /* Firmware gives a ordered list. We skip non-20MHz
4874 * channels is 2G. For 5G we can abort upon reaching
4875 * a non-20MHz channel in the list.
4876 */
4877 if (ch.bw != BRCMU_CHAN_BW_20) {
4878 if (ch.band == BRCMU_CHAN_BAND_5G)
4879 break;
4880 else
4881 continue;
4882 }
4883
4884 if (ch.band == BRCMU_CHAN_BAND_2G)
4885 chcnt[0] += 1;
4886 else if (ch.band == BRCMU_CHAN_BAND_5G)
4887 chcnt[1] += 1;
4888 }
4889}
4890
4891static void brcmf_update_bw40_channel_flag(struct ieee80211_channel *channel,
4892 struct brcmu_chan *ch)
4893{
4894 u32 ht40_flag;
4916 4895
4917static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, 4896 ht40_flag = channel->flags & IEEE80211_CHAN_NO_HT40;
4918 u32 bw_cap[]) 4897 if (ch->sb == BRCMU_CHAN_SB_U) {
4898 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
4899 channel->flags &= ~IEEE80211_CHAN_NO_HT40;
4900 channel->flags |= IEEE80211_CHAN_NO_HT40PLUS;
4901 } else {
4902 /* It should be one of
4903 * IEEE80211_CHAN_NO_HT40 or
4904 * IEEE80211_CHAN_NO_HT40PLUS
4905 */
4906 channel->flags &= ~IEEE80211_CHAN_NO_HT40;
4907 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
4908 channel->flags |= IEEE80211_CHAN_NO_HT40MINUS;
4909 }
4910}
4911
4912static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
4913 u32 bw_cap[])
4919{ 4914{
4920 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); 4915 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
4921 struct ieee80211_channel *band_chan_arr; 4916 struct ieee80211_supported_band *band;
4917 struct ieee80211_channel *channel;
4918 struct wiphy *wiphy;
4922 struct brcmf_chanspec_list *list; 4919 struct brcmf_chanspec_list *list;
4923 struct brcmu_chan ch; 4920 struct brcmu_chan ch;
4924 s32 err; 4921 int err;
4925 u8 *pbuf; 4922 u8 *pbuf;
4926 u32 i, j; 4923 u32 i, j;
4927 u32 total; 4924 u32 total;
4928 enum ieee80211_band band; 4925 u32 chaninfo;
4929 u32 channel; 4926 u32 chcnt[2] = { 0, 0 };
4930 u32 *n_cnt;
4931 u32 index; 4927 u32 index;
4932 u32 ht40_flag;
4933 bool update;
4934 u32 array_size;
4935 4928
4936 pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL); 4929 pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
4937 4930
@@ -4944,11 +4937,45 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg,
4944 BRCMF_DCMD_MEDLEN); 4937 BRCMF_DCMD_MEDLEN);
4945 if (err) { 4938 if (err) {
4946 brcmf_err("get chanspecs error (%d)\n", err); 4939 brcmf_err("get chanspecs error (%d)\n", err);
4947 goto exit; 4940 goto fail_pbuf;
4948 } 4941 }
4949 4942
4950 __wl_band_2ghz.n_channels = 0; 4943 brcmf_count_20mhz_channels(cfg, list, chcnt);
4951 __wl_band_5ghz_a.n_channels = 0; 4944 wiphy = cfg_to_wiphy(cfg);
4945 if (chcnt[0]) {
4946 band = kmemdup(&__wl_band_2ghz, sizeof(__wl_band_2ghz),
4947 GFP_KERNEL);
4948 if (band == NULL) {
4949 err = -ENOMEM;
4950 goto fail_pbuf;
4951 }
4952 band->channels = kcalloc(chcnt[0], sizeof(*channel),
4953 GFP_KERNEL);
4954 if (band->channels == NULL) {
4955 kfree(band);
4956 err = -ENOMEM;
4957 goto fail_pbuf;
4958 }
4959 band->n_channels = 0;
4960 wiphy->bands[IEEE80211_BAND_2GHZ] = band;
4961 }
4962 if (chcnt[1]) {
4963 band = kmemdup(&__wl_band_5ghz_a, sizeof(__wl_band_5ghz_a),
4964 GFP_KERNEL);
4965 if (band == NULL) {
4966 err = -ENOMEM;
4967 goto fail_band2g;
4968 }
4969 band->channels = kcalloc(chcnt[1], sizeof(*channel),
4970 GFP_KERNEL);
4971 if (band->channels == NULL) {
4972 kfree(band);
4973 err = -ENOMEM;
4974 goto fail_band2g;
4975 }
4976 band->n_channels = 0;
4977 wiphy->bands[IEEE80211_BAND_5GHZ] = band;
4978 }
4952 4979
4953 total = le32_to_cpu(list->count); 4980 total = le32_to_cpu(list->count);
4954 for (i = 0; i < total; i++) { 4981 for (i = 0; i < total; i++) {
@@ -4956,105 +4983,88 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg,
4956 cfg->d11inf.decchspec(&ch); 4983 cfg->d11inf.decchspec(&ch);
4957 4984
4958 if (ch.band == BRCMU_CHAN_BAND_2G) { 4985 if (ch.band == BRCMU_CHAN_BAND_2G) {
4959 band_chan_arr = __wl_2ghz_channels; 4986 band = wiphy->bands[IEEE80211_BAND_2GHZ];
4960 array_size = ARRAY_SIZE(__wl_2ghz_channels);
4961 n_cnt = &__wl_band_2ghz.n_channels;
4962 band = IEEE80211_BAND_2GHZ;
4963 } else if (ch.band == BRCMU_CHAN_BAND_5G) { 4987 } else if (ch.band == BRCMU_CHAN_BAND_5G) {
4964 band_chan_arr = __wl_5ghz_a_channels; 4988 band = wiphy->bands[IEEE80211_BAND_5GHZ];
4965 array_size = ARRAY_SIZE(__wl_5ghz_a_channels);
4966 n_cnt = &__wl_band_5ghz_a.n_channels;
4967 band = IEEE80211_BAND_5GHZ;
4968 } else { 4989 } else {
4969 brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec); 4990 brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec);
4970 continue; 4991 continue;
4971 } 4992 }
4972 if (!(bw_cap[band] & WLC_BW_40MHZ_BIT) && 4993 if (!(bw_cap[band->band] & WLC_BW_40MHZ_BIT) &&
4973 ch.bw == BRCMU_CHAN_BW_40) 4994 ch.bw == BRCMU_CHAN_BW_40)
4974 continue; 4995 continue;
4975 if (!(bw_cap[band] & WLC_BW_80MHZ_BIT) && 4996 if (!(bw_cap[band->band] & WLC_BW_80MHZ_BIT) &&
4976 ch.bw == BRCMU_CHAN_BW_80) 4997 ch.bw == BRCMU_CHAN_BW_80)
4977 continue; 4998 continue;
4978 update = false; 4999
4979 for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) { 5000 channel = band->channels;
4980 if (band_chan_arr[j].hw_value == ch.chnum) { 5001 index = band->n_channels;
4981 update = true; 5002 for (j = 0; j < band->n_channels; j++) {
5003 if (channel[j].hw_value == ch.chnum) {
5004 index = j;
4982 break; 5005 break;
4983 } 5006 }
4984 } 5007 }
4985 if (update) 5008 channel[index].center_freq =
4986 index = j; 5009 ieee80211_channel_to_frequency(ch.chnum, band->band);
4987 else 5010 channel[index].hw_value = ch.chnum;
4988 index = *n_cnt; 5011
4989 if (index < array_size) { 5012 /* assuming the chanspecs order is HT20,
4990 band_chan_arr[index].center_freq = 5013 * HT40 upper, HT40 lower, and VHT80.
4991 ieee80211_channel_to_frequency(ch.chnum, band); 5014 */
4992 band_chan_arr[index].hw_value = ch.chnum; 5015 if (ch.bw == BRCMU_CHAN_BW_80) {
4993 5016 channel[index].flags &= ~IEEE80211_CHAN_NO_80MHZ;
4994 /* assuming the chanspecs order is HT20, 5017 } else if (ch.bw == BRCMU_CHAN_BW_40) {
4995 * HT40 upper, HT40 lower, and VHT80. 5018 brcmf_update_bw40_channel_flag(&channel[index], &ch);
5019 } else {
5020 /* disable other bandwidths for now as mentioned
5021 * order assure they are enabled for subsequent
5022 * chanspecs.
4996 */ 5023 */
4997 if (ch.bw == BRCMU_CHAN_BW_80) { 5024 channel[index].flags = IEEE80211_CHAN_NO_HT40 |
4998 band_chan_arr[index].flags &= 5025 IEEE80211_CHAN_NO_80MHZ;
4999 ~IEEE80211_CHAN_NO_80MHZ; 5026 ch.bw = BRCMU_CHAN_BW_20;
5000 } else if (ch.bw == BRCMU_CHAN_BW_40) { 5027 cfg->d11inf.encchspec(&ch);
5001 ht40_flag = band_chan_arr[index].flags & 5028 chaninfo = ch.chspec;
5002 IEEE80211_CHAN_NO_HT40; 5029 err = brcmf_fil_bsscfg_int_get(ifp, "per_chan_info",
5003 if (ch.sb == BRCMU_CHAN_SB_U) { 5030 &chaninfo);
5004 if (ht40_flag == IEEE80211_CHAN_NO_HT40) 5031 if (!err) {
5005 band_chan_arr[index].flags &= 5032 if (chaninfo & WL_CHAN_RADAR)
5006 ~IEEE80211_CHAN_NO_HT40; 5033 channel[index].flags |=
5007 band_chan_arr[index].flags |= 5034 (IEEE80211_CHAN_RADAR |
5008 IEEE80211_CHAN_NO_HT40PLUS; 5035 IEEE80211_CHAN_NO_IR);
5009 } else { 5036 if (chaninfo & WL_CHAN_PASSIVE)
5010 /* It should be one of 5037 channel[index].flags |=
5011 * IEEE80211_CHAN_NO_HT40 or 5038 IEEE80211_CHAN_NO_IR;
5012 * IEEE80211_CHAN_NO_HT40PLUS
5013 */
5014 band_chan_arr[index].flags &=
5015 ~IEEE80211_CHAN_NO_HT40;
5016 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
5017 band_chan_arr[index].flags |=
5018 IEEE80211_CHAN_NO_HT40MINUS;
5019 }
5020 } else {
5021 /* disable other bandwidths for now as mentioned
5022 * order assure they are enabled for subsequent
5023 * chanspecs.
5024 */
5025 band_chan_arr[index].flags =
5026 IEEE80211_CHAN_NO_HT40 |
5027 IEEE80211_CHAN_NO_80MHZ;
5028 ch.bw = BRCMU_CHAN_BW_20;
5029 cfg->d11inf.encchspec(&ch);
5030 channel = ch.chspec;
5031 err = brcmf_fil_bsscfg_int_get(ifp,
5032 "per_chan_info",
5033 &channel);
5034 if (!err) {
5035 if (channel & WL_CHAN_RADAR)
5036 band_chan_arr[index].flags |=
5037 (IEEE80211_CHAN_RADAR |
5038 IEEE80211_CHAN_NO_IR);
5039 if (channel & WL_CHAN_PASSIVE)
5040 band_chan_arr[index].flags |=
5041 IEEE80211_CHAN_NO_IR;
5042 }
5043 } 5039 }
5044 if (!update)
5045 (*n_cnt)++;
5046 } 5040 }
5041 if (index == band->n_channels)
5042 band->n_channels++;
5047 } 5043 }
5048exit: 5044 kfree(pbuf);
5045 return 0;
5046
5047fail_band2g:
5048 kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
5049 kfree(wiphy->bands[IEEE80211_BAND_2GHZ]);
5050 wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
5051fail_pbuf:
5049 kfree(pbuf); 5052 kfree(pbuf);
5050 return err; 5053 return err;
5051} 5054}
5052 5055
5053static int brcmf_enable_bw40_2g(struct brcmf_if *ifp) 5056static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg)
5054{ 5057{
5058 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
5059 struct ieee80211_supported_band *band;
5055 struct brcmf_fil_bwcap_le band_bwcap; 5060 struct brcmf_fil_bwcap_le band_bwcap;
5061 struct brcmf_chanspec_list *list;
5062 u8 *pbuf;
5056 u32 val; 5063 u32 val;
5057 int err; 5064 int err;
5065 struct brcmu_chan ch;
5066 u32 num_chan;
5067 int i, j;
5058 5068
5059 /* verify support for bw_cap command */ 5069 /* verify support for bw_cap command */
5060 val = WLC_BAND_5G; 5070 val = WLC_BAND_5G;
@@ -5071,6 +5081,50 @@ static int brcmf_enable_bw40_2g(struct brcmf_if *ifp)
5071 val = WLC_N_BW_40ALL; 5081 val = WLC_N_BW_40ALL;
5072 err = brcmf_fil_iovar_int_set(ifp, "mimo_bw_cap", val); 5082 err = brcmf_fil_iovar_int_set(ifp, "mimo_bw_cap", val);
5073 } 5083 }
5084
5085 if (!err) {
5086 /* update channel info in 2G band */
5087 pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
5088
5089 if (pbuf == NULL)
5090 return -ENOMEM;
5091
5092 ch.band = BRCMU_CHAN_BAND_2G;
5093 ch.bw = BRCMU_CHAN_BW_40;
5094 ch.chnum = 0;
5095 cfg->d11inf.encchspec(&ch);
5096
5097 /* pass encoded chanspec in query */
5098 *(__le16 *)pbuf = cpu_to_le16(ch.chspec);
5099
5100 err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf,
5101 BRCMF_DCMD_MEDLEN);
5102 if (err) {
5103 brcmf_err("get chanspecs error (%d)\n", err);
5104 kfree(pbuf);
5105 return err;
5106 }
5107
5108 band = cfg_to_wiphy(cfg)->bands[IEEE80211_BAND_2GHZ];
5109 list = (struct brcmf_chanspec_list *)pbuf;
5110 num_chan = le32_to_cpu(list->count);
5111 for (i = 0; i < num_chan; i++) {
5112 ch.chspec = (u16)le32_to_cpu(list->element[i]);
5113 cfg->d11inf.decchspec(&ch);
5114 if (WARN_ON(ch.band != BRCMU_CHAN_BAND_2G))
5115 continue;
5116 if (WARN_ON(ch.bw != BRCMU_CHAN_BW_40))
5117 continue;
5118 for (j = 0; j < band->n_channels; j++) {
5119 if (band->channels[j].hw_value == ch.chnum)
5120 break;
5121 }
5122 if (WARN_ON(j == band->n_channels))
5123 continue;
5124
5125 brcmf_update_bw40_channel_flag(&band->channels[j], &ch);
5126 }
5127 }
5074 return err; 5128 return err;
5075} 5129}
5076 5130
@@ -5164,44 +5218,19 @@ static void brcmf_update_vht_cap(struct ieee80211_supported_band *band,
5164 band->vht_cap.vht_mcs.tx_mcs_map = mcs_map; 5218 band->vht_cap.vht_mcs.tx_mcs_map = mcs_map;
5165} 5219}
5166 5220
5167static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) 5221static int brcmf_setup_wiphybands(struct wiphy *wiphy)
5168{ 5222{
5223 struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
5169 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); 5224 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
5170 struct wiphy *wiphy;
5171 s32 phy_list;
5172 u32 band_list[3];
5173 u32 nmode = 0; 5225 u32 nmode = 0;
5174 u32 vhtmode = 0; 5226 u32 vhtmode = 0;
5175 u32 bw_cap[2] = { 0, 0 }; 5227 u32 bw_cap[2] = { WLC_BW_20MHZ_BIT, WLC_BW_20MHZ_BIT };
5176 u32 rxchain; 5228 u32 rxchain;
5177 u32 nchain; 5229 u32 nchain;
5178 s8 phy; 5230 int err;
5179 s32 err;
5180 u32 nband;
5181 s32 i; 5231 s32 i;
5182 struct ieee80211_supported_band *bands[2] = { NULL, NULL };
5183 struct ieee80211_supported_band *band; 5232 struct ieee80211_supported_band *band;
5184 5233
5185 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST,
5186 &phy_list, sizeof(phy_list));
5187 if (err) {
5188 brcmf_err("BRCMF_C_GET_PHYLIST error (%d)\n", err);
5189 return err;
5190 }
5191
5192 phy = ((char *)&phy_list)[0];
5193 brcmf_dbg(INFO, "BRCMF_C_GET_PHYLIST reported: %c phy\n", phy);
5194
5195
5196 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST,
5197 &band_list, sizeof(band_list));
5198 if (err) {
5199 brcmf_err("BRCMF_C_GET_BANDLIST error (%d)\n", err);
5200 return err;
5201 }
5202 brcmf_dbg(INFO, "BRCMF_C_GET_BANDLIST reported: 0x%08x 0x%08x 0x%08x phy\n",
5203 band_list[0], band_list[1], band_list[2]);
5204
5205 (void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode); 5234 (void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode);
5206 err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode); 5235 err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode);
5207 if (err) { 5236 if (err) {
@@ -5223,38 +5252,25 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
5223 } 5252 }
5224 brcmf_dbg(INFO, "nchain=%d\n", nchain); 5253 brcmf_dbg(INFO, "nchain=%d\n", nchain);
5225 5254
5226 err = brcmf_construct_reginfo(cfg, bw_cap); 5255 err = brcmf_construct_chaninfo(cfg, bw_cap);
5227 if (err) { 5256 if (err) {
5228 brcmf_err("brcmf_construct_reginfo failed (%d)\n", err); 5257 brcmf_err("brcmf_construct_chaninfo failed (%d)\n", err);
5229 return err; 5258 return err;
5230 } 5259 }
5231 5260
5232 nband = band_list[0]; 5261 wiphy = cfg_to_wiphy(cfg);
5233 5262 for (i = 0; i < ARRAY_SIZE(wiphy->bands); i++) {
5234 for (i = 1; i <= nband && i < ARRAY_SIZE(band_list); i++) { 5263 band = wiphy->bands[i];
5235 band = NULL; 5264 if (band == NULL)
5236 if ((band_list[i] == WLC_BAND_5G) &&
5237 (__wl_band_5ghz_a.n_channels > 0))
5238 band = &__wl_band_5ghz_a;
5239 else if ((band_list[i] == WLC_BAND_2G) &&
5240 (__wl_band_2ghz.n_channels > 0))
5241 band = &__wl_band_2ghz;
5242 else
5243 continue; 5265 continue;
5244 5266
5245 if (nmode) 5267 if (nmode)
5246 brcmf_update_ht_cap(band, bw_cap, nchain); 5268 brcmf_update_ht_cap(band, bw_cap, nchain);
5247 if (vhtmode) 5269 if (vhtmode)
5248 brcmf_update_vht_cap(band, bw_cap, nchain); 5270 brcmf_update_vht_cap(band, bw_cap, nchain);
5249 bands[band->band] = band;
5250 } 5271 }
5251 5272
5252 wiphy = cfg_to_wiphy(cfg); 5273 return 0;
5253 wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
5254 wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
5255 wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
5256
5257 return err;
5258} 5274}
5259 5275
5260static const struct ieee80211_iface_limit brcmf_iface_limits[] = { 5276static const struct ieee80211_iface_limit brcmf_iface_limits[] = {
@@ -5321,18 +5337,9 @@ static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
5321 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; 5337 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
5322} 5338}
5323 5339
5324static struct wiphy *brcmf_setup_wiphy(struct brcmf_if *ifp, 5340static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
5325 struct device *phydev)
5326{ 5341{
5327 struct wiphy *wiphy; 5342 struct ieee80211_iface_combination ifc_combo;
5328 s32 err = 0;
5329
5330 wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
5331 if (!wiphy) {
5332 brcmf_err("Could not allocate wiphy device\n");
5333 return ERR_PTR(-ENOMEM);
5334 }
5335 set_wiphy_dev(wiphy, phydev);
5336 wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; 5343 wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
5337 wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; 5344 wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
5338 wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; 5345 wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
@@ -5343,11 +5350,13 @@ static struct wiphy *brcmf_setup_wiphy(struct brcmf_if *ifp,
5343 BIT(NL80211_IFTYPE_P2P_GO) | 5350 BIT(NL80211_IFTYPE_P2P_GO) |
5344 BIT(NL80211_IFTYPE_P2P_DEVICE); 5351 BIT(NL80211_IFTYPE_P2P_DEVICE);
5345 /* need VSDB firmware feature for concurrent channels */ 5352 /* need VSDB firmware feature for concurrent channels */
5353 ifc_combo = brcmf_iface_combos[0];
5346 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) 5354 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
5347 brcmf_iface_combos[0].num_different_channels = 2; 5355 ifc_combo.num_different_channels = 2;
5348 wiphy->iface_combinations = brcmf_iface_combos; 5356 wiphy->iface_combinations = kmemdup(&ifc_combo,
5357 sizeof(ifc_combo),
5358 GFP_KERNEL);
5349 wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos); 5359 wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
5350 wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
5351 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; 5360 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
5352 wiphy->cipher_suites = __wl_cipher_suites; 5361 wiphy->cipher_suites = __wl_cipher_suites;
5353 wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); 5362 wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
@@ -5360,27 +5369,12 @@ static struct wiphy *brcmf_setup_wiphy(struct brcmf_if *ifp,
5360 wiphy->mgmt_stypes = brcmf_txrx_stypes; 5369 wiphy->mgmt_stypes = brcmf_txrx_stypes;
5361 wiphy->max_remain_on_channel_duration = 5000; 5370 wiphy->max_remain_on_channel_duration = 5000;
5362 brcmf_wiphy_pno_params(wiphy); 5371 brcmf_wiphy_pno_params(wiphy);
5363 brcmf_dbg(INFO, "Registering custom regulatory\n");
5364 wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
5365 wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
5366 5372
5367 /* vendor commands/events support */ 5373 /* vendor commands/events support */
5368 wiphy->vendor_commands = brcmf_vendor_cmds; 5374 wiphy->vendor_commands = brcmf_vendor_cmds;
5369 wiphy->n_vendor_commands = BRCMF_VNDR_CMDS_LAST - 1; 5375 wiphy->n_vendor_commands = BRCMF_VNDR_CMDS_LAST - 1;
5370 5376
5371 err = wiphy_register(wiphy); 5377 return brcmf_setup_wiphybands(wiphy);
5372 if (err < 0) {
5373 brcmf_err("Could not register wiphy device (%d)\n", err);
5374 wiphy_free(wiphy);
5375 return ERR_PTR(err);
5376 }
5377 return wiphy;
5378}
5379
5380
5381static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_info *cfg)
5382{
5383 return brcmf_update_wiphybands(cfg);
5384} 5378}
5385 5379
5386static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) 5380static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
@@ -5418,9 +5412,6 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
5418 NULL, NULL); 5412 NULL, NULL);
5419 if (err) 5413 if (err)
5420 goto default_conf_out; 5414 goto default_conf_out;
5421 err = brcmf_dongle_probecap(cfg);
5422 if (err)
5423 goto default_conf_out;
5424 5415
5425 brcmf_configure_arp_offload(ifp, true); 5416 brcmf_configure_arp_offload(ifp, true);
5426 5417
@@ -5548,6 +5539,20 @@ int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg,
5548 vif_event_equals(event, action), timeout); 5539 vif_event_equals(event, action), timeout);
5549} 5540}
5550 5541
5542static void brcmf_free_wiphy(struct wiphy *wiphy)
5543{
5544 kfree(wiphy->iface_combinations);
5545 if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
5546 kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
5547 kfree(wiphy->bands[IEEE80211_BAND_2GHZ]);
5548 }
5549 if (wiphy->bands[IEEE80211_BAND_5GHZ]) {
5550 kfree(wiphy->bands[IEEE80211_BAND_5GHZ]->channels);
5551 kfree(wiphy->bands[IEEE80211_BAND_5GHZ]);
5552 }
5553 wiphy_free(wiphy);
5554}
5555
5551struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, 5556struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
5552 struct device *busdev) 5557 struct device *busdev)
5553{ 5558{
@@ -5558,6 +5563,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
5558 struct brcmf_if *ifp; 5563 struct brcmf_if *ifp;
5559 s32 err = 0; 5564 s32 err = 0;
5560 s32 io_type; 5565 s32 io_type;
5566 u16 *cap = NULL;
5561 5567
5562 if (!ndev) { 5568 if (!ndev) {
5563 brcmf_err("ndev is invalid\n"); 5569 brcmf_err("ndev is invalid\n");
@@ -5565,9 +5571,12 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
5565 } 5571 }
5566 5572
5567 ifp = netdev_priv(ndev); 5573 ifp = netdev_priv(ndev);
5568 wiphy = brcmf_setup_wiphy(ifp, busdev); 5574 wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
5569 if (IS_ERR(wiphy)) 5575 if (!wiphy) {
5576 brcmf_err("Could not allocate wiphy device\n");
5570 return NULL; 5577 return NULL;
5578 }
5579 set_wiphy_dev(wiphy, busdev);
5571 5580
5572 cfg = wiphy_priv(wiphy); 5581 cfg = wiphy_priv(wiphy);
5573 cfg->wiphy = wiphy; 5582 cfg->wiphy = wiphy;
@@ -5576,10 +5585,8 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
5576 INIT_LIST_HEAD(&cfg->vif_list); 5585 INIT_LIST_HEAD(&cfg->vif_list);
5577 5586
5578 vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION, false); 5587 vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION, false);
5579 if (IS_ERR(vif)) { 5588 if (IS_ERR(vif))
5580 wiphy_free(wiphy); 5589 goto wiphy_out;
5581 return NULL;
5582 }
5583 5590
5584 vif->ifp = ifp; 5591 vif->ifp = ifp;
5585 vif->wdev.netdev = ndev; 5592 vif->wdev.netdev = ndev;
@@ -5589,58 +5596,81 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
5589 err = wl_init_priv(cfg); 5596 err = wl_init_priv(cfg);
5590 if (err) { 5597 if (err) {
5591 brcmf_err("Failed to init iwm_priv (%d)\n", err); 5598 brcmf_err("Failed to init iwm_priv (%d)\n", err);
5592 goto cfg80211_attach_out; 5599 brcmf_free_vif(vif);
5600 goto wiphy_out;
5593 } 5601 }
5594 ifp->vif = vif; 5602 ifp->vif = vif;
5595 5603
5596 err = brcmf_p2p_attach(cfg); 5604 /* determine d11 io type before wiphy setup */
5605 err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION, &io_type);
5597 if (err) { 5606 if (err) {
5598 brcmf_err("P2P initilisation failed (%d)\n", err); 5607 brcmf_err("Failed to get D11 version (%d)\n", err);
5599 goto cfg80211_p2p_attach_out; 5608 goto priv_out;
5600 } 5609 }
5601 err = brcmf_btcoex_attach(cfg); 5610 cfg->d11inf.io_type = (u8)io_type;
5602 if (err) { 5611 brcmu_d11_attach(&cfg->d11inf);
5603 brcmf_err("BT-coex initialisation failed (%d)\n", err); 5612
5604 brcmf_p2p_detach(&cfg->p2p); 5613 err = brcmf_setup_wiphy(wiphy, ifp);
5605 goto cfg80211_p2p_attach_out; 5614 if (err < 0)
5615 goto priv_out;
5616
5617 brcmf_dbg(INFO, "Registering custom regulatory\n");
5618 wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
5619 wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
5620
5621 /* firmware defaults to 40MHz disabled in 2G band. We signal
5622 * cfg80211 here that we do and have it decide we can enable
5623 * it. But first check if device does support 2G operation.
5624 */
5625 if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
5626 cap = &wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap;
5627 *cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
5628 }
5629 err = wiphy_register(wiphy);
5630 if (err < 0) {
5631 brcmf_err("Could not register wiphy device (%d)\n", err);
5632 goto priv_out;
5606 } 5633 }
5607 5634
5608 /* If cfg80211 didn't disable 40MHz HT CAP in wiphy_register(), 5635 /* If cfg80211 didn't disable 40MHz HT CAP in wiphy_register(),
5609 * setup 40MHz in 2GHz band and enable OBSS scanning. 5636 * setup 40MHz in 2GHz band and enable OBSS scanning.
5610 */ 5637 */
5611 if (wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap & 5638 if (cap && (*cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) {
5612 IEEE80211_HT_CAP_SUP_WIDTH_20_40) { 5639 err = brcmf_enable_bw40_2g(cfg);
5613 err = brcmf_enable_bw40_2g(ifp);
5614 if (!err) 5640 if (!err)
5615 err = brcmf_fil_iovar_int_set(ifp, "obss_coex", 5641 err = brcmf_fil_iovar_int_set(ifp, "obss_coex",
5616 BRCMF_OBSS_COEX_AUTO); 5642 BRCMF_OBSS_COEX_AUTO);
5643 else
5644 *cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
5617 } 5645 }
5618 /* clear for now and rely on update later */
5619 wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.ht_supported = false;
5620 wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap = 0;
5621 5646
5622 err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1); 5647 err = brcmf_p2p_attach(cfg);
5623 if (err) { 5648 if (err) {
5624 brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err); 5649 brcmf_err("P2P initilisation failed (%d)\n", err);
5625 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS; 5650 goto wiphy_unreg_out;
5651 }
5652 err = brcmf_btcoex_attach(cfg);
5653 if (err) {
5654 brcmf_err("BT-coex initialisation failed (%d)\n", err);
5655 brcmf_p2p_detach(&cfg->p2p);
5656 goto wiphy_unreg_out;
5626 } 5657 }
5627 5658
5628 err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION, 5659 err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1);
5629 &io_type);
5630 if (err) { 5660 if (err) {
5631 brcmf_err("Failed to get D11 version (%d)\n", err); 5661 brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err);
5632 goto cfg80211_p2p_attach_out; 5662 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS;
5633 } 5663 }
5634 cfg->d11inf.io_type = (u8)io_type;
5635 brcmu_d11_attach(&cfg->d11inf);
5636 5664
5637 return cfg; 5665 return cfg;
5638 5666
5639cfg80211_p2p_attach_out: 5667wiphy_unreg_out:
5668 wiphy_unregister(cfg->wiphy);
5669priv_out:
5640 wl_deinit_priv(cfg); 5670 wl_deinit_priv(cfg);
5641
5642cfg80211_attach_out:
5643 brcmf_free_vif(vif); 5671 brcmf_free_vif(vif);
5672wiphy_out:
5673 brcmf_free_wiphy(wiphy);
5644 return NULL; 5674 return NULL;
5645} 5675}
5646 5676
@@ -5653,5 +5683,5 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
5653 wiphy_unregister(cfg->wiphy); 5683 wiphy_unregister(cfg->wiphy);
5654 brcmf_btcoex_detach(cfg); 5684 brcmf_btcoex_detach(cfg);
5655 wl_deinit_priv(cfg); 5685 wl_deinit_priv(cfg);
5656 wiphy_free(cfg->wiphy); 5686 brcmf_free_wiphy(cfg->wiphy);
5657} 5687}