iwlwifi: mvm: fix bug in set_hw_address function
[cascardo/linux.git] / drivers / net / wireless / iwlwifi / iwl-nvm-parse.c
index 85eee79..f0ae038 100644 (file)
@@ -174,7 +174,9 @@ static struct ieee80211_rate iwl_cfg80211_rates[] = {
  * @NVM_CHANNEL_IBSS: usable as an IBSS channel
  * @NVM_CHANNEL_ACTIVE: active scanning allowed
  * @NVM_CHANNEL_RADAR: radar detection required
- * @NVM_CHANNEL_DFS: dynamic freq selection candidate
+ * @NVM_CHANNEL_INDOOR_ONLY: only indoor use is allowed
+ * @NVM_CHANNEL_GO_CONCURRENT: GO operation is allowed when connected to BSS
+ *     on same channel on 2.4 or same UNII band on 5.2
  * @NVM_CHANNEL_WIDE: 20 MHz channel okay (?)
  * @NVM_CHANNEL_40MHZ: 40 MHz channel okay (?)
  * @NVM_CHANNEL_80MHZ: 80 MHz channel okay (?)
@@ -185,7 +187,8 @@ enum iwl_nvm_channel_flags {
        NVM_CHANNEL_IBSS = BIT(1),
        NVM_CHANNEL_ACTIVE = BIT(3),
        NVM_CHANNEL_RADAR = BIT(4),
-       NVM_CHANNEL_DFS = BIT(7),
+       NVM_CHANNEL_INDOOR_ONLY = BIT(5),
+       NVM_CHANNEL_GO_CONCURRENT = BIT(6),
        NVM_CHANNEL_WIDE = BIT(8),
        NVM_CHANNEL_40MHZ = BIT(9),
        NVM_CHANNEL_80MHZ = BIT(10),
@@ -273,6 +276,16 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
                if (ch_flags & NVM_CHANNEL_RADAR)
                        channel->flags |= IEEE80211_CHAN_RADAR;
 
+               if (ch_flags & NVM_CHANNEL_INDOOR_ONLY)
+                       channel->flags |= IEEE80211_CHAN_INDOOR_ONLY;
+
+               /* Set the GO concurrent flag only in case that NO_IR is set.
+                * Otherwise it is meaningless
+                */
+               if ((ch_flags & NVM_CHANNEL_GO_CONCURRENT) &&
+                   (channel->flags & IEEE80211_CHAN_NO_IR))
+                       channel->flags |= IEEE80211_CHAN_GO_CONCURRENT;
+
                /* Initialize regulatory-based run-time data */
 
                /*
@@ -282,7 +295,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
                channel->max_power = DEFAULT_MAX_TX_POWER;
                is_5ghz = channel->band == IEEE80211_BAND_5GHZ;
                IWL_DEBUG_EEPROM(dev,
-                                "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n",
+                                "Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n",
                                 channel->hw_value,
                                 is_5ghz ? "5.2" : "2.4",
                                 CHECK_AND_PRINT_I(VALID),
@@ -290,7 +303,8 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
                                 CHECK_AND_PRINT_I(ACTIVE),
                                 CHECK_AND_PRINT_I(RADAR),
                                 CHECK_AND_PRINT_I(WIDE),
-                                CHECK_AND_PRINT_I(DFS),
+                                CHECK_AND_PRINT_I(INDOOR_ONLY),
+                                CHECK_AND_PRINT_I(GO_CONCURRENT),
                                 ch_flags,
                                 channel->max_power,
                                 ((ch_flags & NVM_CHANNEL_IBSS) &&
@@ -462,7 +476,8 @@ static void iwl_set_hw_address(const struct iwl_cfg *cfg,
        data->hw_addr[5] = hw_addr[4];
 }
 
-static void iwl_set_hw_address_family_8000(const struct iwl_cfg *cfg,
+static void iwl_set_hw_address_family_8000(struct device *dev,
+                                          const struct iwl_cfg *cfg,
                                           struct iwl_nvm_data *data,
                                           const __le16 *mac_override,
                                           const __le16 *nvm_hw)
@@ -481,20 +496,28 @@ static void iwl_set_hw_address_family_8000(const struct iwl_cfg *cfg,
                data->hw_addr[4] = hw_addr[5];
                data->hw_addr[5] = hw_addr[4];
 
-               if (is_valid_ether_addr(hw_addr))
+               if (is_valid_ether_addr(data->hw_addr))
                        return;
+
+               IWL_ERR_DEV(dev,
+                           "mac address from nvm override section is not valid\n");
        }
 
-       /* take the MAC address from the OTP */
-       hw_addr = (const u8 *)(nvm_hw + HW_ADDR0_FAMILY_8000);
-       data->hw_addr[0] = hw_addr[3];
-       data->hw_addr[1] = hw_addr[2];
-       data->hw_addr[2] = hw_addr[1];
-       data->hw_addr[3] = hw_addr[0];
+       if (nvm_hw) {
+               /* take the MAC address from the OTP */
+               hw_addr = (const u8 *)(nvm_hw + HW_ADDR0_FAMILY_8000);
+               data->hw_addr[0] = hw_addr[3];
+               data->hw_addr[1] = hw_addr[2];
+               data->hw_addr[2] = hw_addr[1];
+               data->hw_addr[3] = hw_addr[0];
+
+               hw_addr = (const u8 *)(nvm_hw + HW_ADDR1_FAMILY_8000);
+               data->hw_addr[4] = hw_addr[1];
+               data->hw_addr[5] = hw_addr[0];
+               return;
+       }
 
-       hw_addr = (const u8 *)(nvm_hw + HW_ADDR1_FAMILY_8000);
-       data->hw_addr[4] = hw_addr[1];
-       data->hw_addr[5] = hw_addr[0];
+       IWL_ERR_DEV(dev, "mac address is not found\n");
 }
 
 struct iwl_nvm_data *
@@ -556,7 +579,8 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
                                rx_chains);
        } else {
                /* MAC address in family 8000 */
-               iwl_set_hw_address_family_8000(cfg, data, mac_override, nvm_hw);
+               iwl_set_hw_address_family_8000(dev, cfg, data, mac_override,
+                                              nvm_hw);
 
                iwl_init_sbands(dev, cfg, data, regulatory,
                                sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains,