7373/* NVM offsets (in words) definitions */
7474enum wkp_nvm_offsets {
7575 /* NVM HW-Section offset (in words) definitions */
76+ SUBSYSTEM_ID = 0x0A ,
7677 HW_ADDR = 0x15 ,
7778
7879 /* NVM SW-Section offset (in words) definitions */
@@ -257,13 +258,12 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz,
257258static int iwl_init_channel_map (struct device * dev , const struct iwl_cfg * cfg ,
258259 struct iwl_nvm_data * data ,
259260 const __le16 * const nvm_ch_flags ,
260- bool lar_supported )
261+ bool lar_supported , bool no_wide_in_5ghz )
261262{
262263 int ch_idx ;
263264 int n_channels = 0 ;
264265 struct ieee80211_channel * channel ;
265266 u16 ch_flags ;
266- bool is_5ghz ;
267267 int num_of_ch , num_2ghz_channels ;
268268 const u8 * nvm_chan ;
269269
@@ -278,12 +278,20 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
278278 }
279279
280280 for (ch_idx = 0 ; ch_idx < num_of_ch ; ch_idx ++ ) {
281+ bool is_5ghz = (ch_idx >= num_2ghz_channels );
282+
281283 ch_flags = __le16_to_cpup (nvm_ch_flags + ch_idx );
282284
283- if (ch_idx >= num_2ghz_channels &&
284- !data -> sku_cap_band_52GHz_enable )
285+ if (is_5ghz && !data -> sku_cap_band_52GHz_enable )
285286 continue ;
286287
288+ /* workaround to disable wide channels in 5GHz */
289+ if (no_wide_in_5ghz && is_5ghz ) {
290+ ch_flags &= ~(NVM_CHANNEL_40MHZ |
291+ NVM_CHANNEL_80MHZ |
292+ NVM_CHANNEL_160MHZ );
293+ }
294+
287295 if (!lar_supported && !(ch_flags & NVM_CHANNEL_VALID )) {
288296 /*
289297 * Channels might become valid later if lar is
@@ -303,8 +311,8 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
303311 n_channels ++ ;
304312
305313 channel -> hw_value = nvm_chan [ch_idx ];
306- channel -> band = ( ch_idx < num_2ghz_channels ) ?
307- IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ ;
314+ channel -> band = is_5ghz ?
315+ IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ ;
308316 channel -> center_freq =
309317 ieee80211_channel_to_frequency (
310318 channel -> hw_value , channel -> band );
@@ -316,7 +324,6 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
316324 * is not used in mvm, and is used for backwards compatibility
317325 */
318326 channel -> max_power = IWL_DEFAULT_MAX_TX_POWER ;
319- is_5ghz = channel -> band == IEEE80211_BAND_5GHZ ;
320327
321328 /* don't put limitations in case we're using LAR */
322329 if (!lar_supported )
@@ -405,7 +412,8 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
405412static void iwl_init_sbands (struct device * dev , const struct iwl_cfg * cfg ,
406413 struct iwl_nvm_data * data ,
407414 const __le16 * ch_section ,
408- u8 tx_chains , u8 rx_chains , bool lar_supported )
415+ u8 tx_chains , u8 rx_chains , bool lar_supported ,
416+ bool no_wide_in_5ghz )
409417{
410418 int n_channels ;
411419 int n_used = 0 ;
@@ -414,12 +422,14 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
414422 if (cfg -> device_family != IWL_DEVICE_FAMILY_8000 )
415423 n_channels = iwl_init_channel_map (
416424 dev , cfg , data ,
417- & ch_section [NVM_CHANNELS ], lar_supported );
425+ & ch_section [NVM_CHANNELS ], lar_supported ,
426+ no_wide_in_5ghz );
418427 else
419428 n_channels = iwl_init_channel_map (
420429 dev , cfg , data ,
421430 & ch_section [NVM_CHANNELS_FAMILY_8000 ],
422- lar_supported );
431+ lar_supported ,
432+ no_wide_in_5ghz );
423433
424434 sband = & data -> bands [IEEE80211_BAND_2GHZ ];
425435 sband -> band = IEEE80211_BAND_2GHZ ;
@@ -582,6 +592,39 @@ static void iwl_set_hw_address_family_8000(struct device *dev,
582592
583593#define IWL_4165_DEVICE_ID 0x5501
584594
595+ static bool
596+ iwl_nvm_no_wide_in_5ghz (struct device * dev , const struct iwl_cfg * cfg ,
597+ const __le16 * nvm_hw )
598+ {
599+ /*
600+ * Workaround a bug in Indonesia SKUs where the regulatory in
601+ * some 7000-family OTPs erroneously allow wide channels in
602+ * 5GHz. To check for Indonesia, we take the SKU value from
603+ * bits 1-4 in the subsystem ID and check if it is either 5 or
604+ * 9. In those cases, we need to force-disable wide channels
605+ * in 5GHz otherwise the FW will throw a sysassert when we try
606+ * to use them.
607+ */
608+ if (cfg -> device_family == IWL_DEVICE_FAMILY_7000 ) {
609+ /*
610+ * Unlike the other sections in the NVM, the hw
611+ * section uses big-endian.
612+ */
613+ u16 subsystem_id = be16_to_cpup ((const __be16 * )nvm_hw
614+ + SUBSYSTEM_ID );
615+ u8 sku = (subsystem_id & 0x1e ) >> 1 ;
616+
617+ if (sku == 5 || sku == 9 ) {
618+ IWL_DEBUG_EEPROM (dev ,
619+ "disabling wide channels in 5GHz (0x%0x %d)\n" ,
620+ subsystem_id , sku );
621+ return true;
622+ }
623+ }
624+
625+ return false;
626+ }
627+
585628struct iwl_nvm_data *
586629iwl_parse_nvm_data (struct device * dev , const struct iwl_cfg * cfg ,
587630 const __le16 * nvm_hw , const __le16 * nvm_sw ,
@@ -591,6 +634,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
591634 u32 mac_addr0 , u32 mac_addr1 , u32 hw_id )
592635{
593636 struct iwl_nvm_data * data ;
637+ bool no_wide_in_5ghz = iwl_nvm_no_wide_in_5ghz (dev , cfg , nvm_hw );
594638 u32 sku ;
595639 u32 radio_cfg ;
596640 u16 lar_config ;
@@ -657,7 +701,8 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
657701 iwl_set_hw_address (cfg , data , nvm_hw );
658702
659703 iwl_init_sbands (dev , cfg , data , nvm_sw ,
660- tx_chains , rx_chains , lar_fw_supported );
704+ tx_chains , rx_chains , lar_fw_supported ,
705+ no_wide_in_5ghz );
661706 } else {
662707 u16 lar_offset = data -> nvm_version < 0xE39 ?
663708 NVM_LAR_OFFSET_FAMILY_8000_OLD :
@@ -673,7 +718,8 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
673718
674719 iwl_init_sbands (dev , cfg , data , regulatory ,
675720 tx_chains , rx_chains ,
676- lar_fw_supported && data -> lar_enabled );
721+ lar_fw_supported && data -> lar_enabled ,
722+ no_wide_in_5ghz );
677723 }
678724
679725 data -> calib_version = 255 ;
0 commit comments