Commit 2785ce00 authored by Shaul Triebitz's avatar Shaul Triebitz Committed by Luca Coelho

iwlwifi: support new NVM response API

Support REGULATORY_NVM_GET_INFO_RSP_API_S_VER_4.
This API adds the new 6-7GHz channels.
Signed-off-by: default avatarShaul Triebitz <shaul.triebitz@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent b15ef67c
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright (C) 2018 Intel Corporation * Copyright(C) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright (C) 2018 Intel Corporation * Copyright(C) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -233,7 +233,8 @@ struct iwl_nvm_get_info_phy { ...@@ -233,7 +233,8 @@ struct iwl_nvm_get_info_phy {
__le32 rx_chains; __le32 rx_chains;
} __packed; /* REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */ } __packed; /* REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */
#define IWL_NUM_CHANNELS (51) #define IWL_NUM_CHANNELS_V1 51
#define IWL_NUM_CHANNELS 110
/** /**
* struct iwl_nvm_get_info_regulatory - regulatory information * struct iwl_nvm_get_info_regulatory - regulatory information
...@@ -241,12 +242,38 @@ struct iwl_nvm_get_info_phy { ...@@ -241,12 +242,38 @@ struct iwl_nvm_get_info_phy {
* @channel_profile: regulatory data of this channel * @channel_profile: regulatory data of this channel
* @reserved: reserved * @reserved: reserved
*/ */
struct iwl_nvm_get_info_regulatory { struct iwl_nvm_get_info_regulatory_v1 {
__le32 lar_enabled; __le32 lar_enabled;
__le16 channel_profile[IWL_NUM_CHANNELS]; __le16 channel_profile[IWL_NUM_CHANNELS_V1];
__le16 reserved; __le16 reserved;
} __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_1 */ } __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_1 */
/**
* struct iwl_nvm_get_info_regulatory - regulatory information
* @lar_enabled: is LAR enabled
* @n_channels: number of valid channels in the array
* @channel_profile: regulatory data of this channel
*/
struct iwl_nvm_get_info_regulatory {
__le32 lar_enabled;
__le32 n_channels;
__le32 channel_profile[IWL_NUM_CHANNELS];
} __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_2 */
/**
* struct iwl_nvm_get_info_rsp_v3 - response to get NVM data
* @general: general NVM data
* @mac_sku: data relating to MAC sku
* @phy_sku: data relating to PHY sku
* @regulatory: regulatory data
*/
struct iwl_nvm_get_info_rsp_v3 {
struct iwl_nvm_get_info_general general;
struct iwl_nvm_get_info_sku mac_sku;
struct iwl_nvm_get_info_phy phy_sku;
struct iwl_nvm_get_info_regulatory_v1 regulatory;
} __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_3 */
/** /**
* struct iwl_nvm_get_info_rsp - response to get NVM data * struct iwl_nvm_get_info_rsp - response to get NVM data
* @general: general NVM data * @general: general NVM data
...@@ -259,7 +286,7 @@ struct iwl_nvm_get_info_rsp { ...@@ -259,7 +286,7 @@ struct iwl_nvm_get_info_rsp {
struct iwl_nvm_get_info_sku mac_sku; struct iwl_nvm_get_info_sku mac_sku;
struct iwl_nvm_get_info_phy phy_sku; struct iwl_nvm_get_info_phy phy_sku;
struct iwl_nvm_get_info_regulatory regulatory; struct iwl_nvm_get_info_regulatory regulatory;
} __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_3 */ } __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_4 */
/** /**
* struct iwl_nvm_access_complete_cmd - NVM_ACCESS commands are completed * struct iwl_nvm_access_complete_cmd - NVM_ACCESS commands are completed
......
...@@ -272,6 +272,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t; ...@@ -272,6 +272,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t;
* version of the beacon notification. * version of the beacon notification.
* @IWL_UCODE_TLV_API_BEACON_FILTER_V4: This ucode supports v4 of * @IWL_UCODE_TLV_API_BEACON_FILTER_V4: This ucode supports v4 of
* BEACON_FILTER_CONFIG_API_S_VER_4. * BEACON_FILTER_CONFIG_API_S_VER_4.
* @IWL_UCODE_TLV_API_REGULATORY_NVM_INFO: This ucode supports v4 of
* REGULATORY_NVM_GET_INFO_RSP_API_S.
* @IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ: This ucode supports v7 of * @IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ: This ucode supports v7 of
* LOCATION_RANGE_REQ_CMD_API_S and v6 of LOCATION_RANGE_RESP_NTFY_API_S. * LOCATION_RANGE_REQ_CMD_API_S and v6 of LOCATION_RANGE_RESP_NTFY_API_S.
* *
...@@ -300,6 +302,7 @@ enum iwl_ucode_tlv_api { ...@@ -300,6 +302,7 @@ enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_REDUCE_TX_POWER = (__force iwl_ucode_tlv_api_t)45, IWL_UCODE_TLV_API_REDUCE_TX_POWER = (__force iwl_ucode_tlv_api_t)45,
IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF = (__force iwl_ucode_tlv_api_t)46, IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF = (__force iwl_ucode_tlv_api_t)46,
IWL_UCODE_TLV_API_BEACON_FILTER_V4 = (__force iwl_ucode_tlv_api_t)47, IWL_UCODE_TLV_API_BEACON_FILTER_V4 = (__force iwl_ucode_tlv_api_t)47,
IWL_UCODE_TLV_API_REGULATORY_NVM_INFO = (__force iwl_ucode_tlv_api_t)48,
IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ = (__force iwl_ucode_tlv_api_t)49, IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ = (__force iwl_ucode_tlv_api_t)49,
NUM_IWL_UCODE_TLV_API NUM_IWL_UCODE_TLV_API
......
...@@ -226,7 +226,7 @@ enum iwl_nvm_channel_flags { ...@@ -226,7 +226,7 @@ enum iwl_nvm_channel_flags {
}; };
static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level, static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
int chan, u16 flags) int chan, u32 flags)
{ {
#define CHECK_AND_PRINT_I(x) \ #define CHECK_AND_PRINT_I(x) \
((flags & NVM_CHANNEL_##x) ? " " #x : "") ((flags & NVM_CHANNEL_##x) ? " " #x : "")
...@@ -257,7 +257,7 @@ static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level, ...@@ -257,7 +257,7 @@ static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
} }
static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz, static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz,
u16 nvm_flags, const struct iwl_cfg *cfg) u32 nvm_flags, const struct iwl_cfg *cfg)
{ {
u32 flags = IEEE80211_CHAN_NO_HT40; u32 flags = IEEE80211_CHAN_NO_HT40;
...@@ -301,13 +301,13 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz, ...@@ -301,13 +301,13 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz,
static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
struct iwl_nvm_data *data, struct iwl_nvm_data *data,
const __le16 * const nvm_ch_flags, const void * const nvm_ch_flags,
u32 sbands_flags) u32 sbands_flags, bool v4)
{ {
int ch_idx; int ch_idx;
int n_channels = 0; int n_channels = 0;
struct ieee80211_channel *channel; struct ieee80211_channel *channel;
u16 ch_flags; u32 ch_flags;
int num_of_ch, num_2ghz_channels = NUM_2GHZ_CHANNELS; int num_of_ch, num_2ghz_channels = NUM_2GHZ_CHANNELS;
const u16 *nvm_chan; const u16 *nvm_chan;
...@@ -325,7 +325,12 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, ...@@ -325,7 +325,12 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) { for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) {
bool is_5ghz = (ch_idx >= num_2ghz_channels); bool is_5ghz = (ch_idx >= num_2ghz_channels);
ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx); if (v4)
ch_flags =
__le32_to_cpup((__le32 *)nvm_ch_flags + ch_idx);
else
ch_flags =
__le16_to_cpup((__le16 *)nvm_ch_flags + ch_idx);
if (is_5ghz && !data->sku_cap_band_52ghz_enable) if (is_5ghz && !data->sku_cap_band_52ghz_enable)
continue; continue;
...@@ -671,15 +676,15 @@ static void iwl_init_he_hw_capab(struct ieee80211_supported_band *sband, ...@@ -671,15 +676,15 @@ static void iwl_init_he_hw_capab(struct ieee80211_supported_band *sband,
static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
struct iwl_nvm_data *data, struct iwl_nvm_data *data,
const __le16 *nvm_ch_flags, u8 tx_chains, const void *nvm_ch_flags, u8 tx_chains,
u8 rx_chains, u32 sbands_flags) u8 rx_chains, u32 sbands_flags, bool v4)
{ {
int n_channels; int n_channels;
int n_used = 0; int n_used = 0;
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
n_channels = iwl_init_channel_map(dev, cfg, data, nvm_ch_flags, n_channels = iwl_init_channel_map(dev, cfg, data, nvm_ch_flags,
sbands_flags); sbands_flags, v4);
sband = &data->bands[NL80211_BAND_2GHZ]; sband = &data->bands[NL80211_BAND_2GHZ];
sband->band = NL80211_BAND_2GHZ; sband->band = NL80211_BAND_2GHZ;
sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS]; sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS];
...@@ -1016,7 +1021,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg, ...@@ -1016,7 +1021,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
sbands_flags |= IWL_NVM_SBANDS_FLAGS_NO_WIDE_IN_5GHZ; sbands_flags |= IWL_NVM_SBANDS_FLAGS_NO_WIDE_IN_5GHZ;
iwl_init_sbands(dev, cfg, data, ch_section, tx_chains, rx_chains, iwl_init_sbands(dev, cfg, data, ch_section, tx_chains, rx_chains,
sbands_flags); sbands_flags, false);
data->calib_version = 255; data->calib_version = 255;
return data; return data;
...@@ -1407,7 +1412,6 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, ...@@ -1407,7 +1412,6 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
const struct iwl_fw *fw) const struct iwl_fw *fw)
{ {
struct iwl_nvm_get_info cmd = {}; struct iwl_nvm_get_info cmd = {};
struct iwl_nvm_get_info_rsp *rsp;
struct iwl_nvm_data *nvm; struct iwl_nvm_data *nvm;
struct iwl_host_cmd hcmd = { struct iwl_host_cmd hcmd = {
.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL, .flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
...@@ -1422,12 +1426,24 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, ...@@ -1422,12 +1426,24 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
bool empty_otp; bool empty_otp;
u32 mac_flags; u32 mac_flags;
u32 sbands_flags = 0; u32 sbands_flags = 0;
/*
* All the values in iwl_nvm_get_info_rsp v4 are the same as
* in v3, except for the channel profile part of the
* regulatory. So we can just access the new struct, with the
* exception of the latter.
*/
struct iwl_nvm_get_info_rsp *rsp;
struct iwl_nvm_get_info_rsp_v3 *rsp_v3;
bool v4 = fw_has_api(&fw->ucode_capa,
IWL_UCODE_TLV_API_REGULATORY_NVM_INFO);
size_t rsp_size = v4 ? sizeof(*rsp) : sizeof(*rsp_v3);
void *channel_profile;
ret = iwl_trans_send_cmd(trans, &hcmd); ret = iwl_trans_send_cmd(trans, &hcmd);
if (ret) if (ret)
return ERR_PTR(ret); return ERR_PTR(ret);
if (WARN(iwl_rx_packet_payload_len(hcmd.resp_pkt) != sizeof(*rsp), if (WARN(iwl_rx_packet_payload_len(hcmd.resp_pkt) != rsp_size,
"Invalid payload len in NVM response from FW %d", "Invalid payload len in NVM response from FW %d",
iwl_rx_packet_payload_len(hcmd.resp_pkt))) { iwl_rx_packet_payload_len(hcmd.resp_pkt))) {
ret = -EINVAL; ret = -EINVAL;
...@@ -1489,11 +1505,15 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, ...@@ -1489,11 +1505,15 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
sbands_flags |= IWL_NVM_SBANDS_FLAGS_LAR; sbands_flags |= IWL_NVM_SBANDS_FLAGS_LAR;
} }
rsp_v3 = (void *)rsp;
channel_profile = v4 ? (void *)rsp->regulatory.channel_profile :
(void *)rsp_v3->regulatory.channel_profile;
iwl_init_sbands(trans->dev, trans->cfg, nvm, iwl_init_sbands(trans->dev, trans->cfg, nvm,
rsp->regulatory.channel_profile, rsp->regulatory.channel_profile,
nvm->valid_tx_ant & fw->valid_tx_ant, nvm->valid_tx_ant & fw->valid_tx_ant,
nvm->valid_rx_ant & fw->valid_rx_ant, nvm->valid_rx_ant & fw->valid_rx_ant,
sbands_flags); sbands_flags, v4);
iwl_free_resp(&hcmd); iwl_free_resp(&hcmd);
return nvm; return nvm;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment