iwlwifi patches intended for v6.2
* iwlmei fixes * Debug mechanism update for new devices (BZ) * Checksum offload fix for the new devices (BZ) * A few rate scale fixes and cleanups * A fix for iwlwifi debug mechanism * Start of MLO preparations - supporting new key API -----BEGIN PGP SIGNATURE----- iQJPBAABCAA5FiEE9cg2NujikJ5EMZusCDCCYA5zdzwFAmNs5fsbHGdyZWdvcnku Z3JlZW5tYW5AaW50ZWwuY29tAAoJEAgwgmAOc3c8HycP/29xLeQi5PDCuU4Y1oDq vp6ddZUwvfgNaeGn+hv4nbob/gpXzaWgXxum3QrE2AwB95U6UNjNLjCAKh+2HS3V tzClp5kNU6TWIwgUnfWfuGWQjqC5X9YOG+LLjKpDXZgm4StfMn5vg7U3temxIpye OA1Mdk992eJ+vp38zJmYIofh5GiZ/TXgxDoGMm5B2CeHyRt6WlUZh+9lFLXZ5maw JLfLqoAhQHs0WGGDSNjCCImmspCDiueiX07O3W9EO9A9Hmv6iSb1PDsxOcvcuxml YoeqgALtz3i6LIjeEtMi50dinlSr3THbxdBWQZF5QTpWZqvXvH5Zq9zq6ymU7f0Q tN35uIDgbY5W0ByXf021rTmifhHMwhiSp0WHdEgo/tKt9g1Zkr4FtoRL+JUbmRd9 CCGErUb/7nCAtSi/FKqvF1xUouFws38i4xbvBI1Vg9lfAwqx6MEfkxwrREW78jur byl5HYtBfASAPt0oWaSUMBCNQwPGdj0rmgQNAkR/bMgS+9YZdicG4uuSVJQp77/P unE0eOyBCIcZBQji9l3V8kuZuvm7mZrAJp5POlRyvhtd4szCboq/OF7ke7LKYJqo tsuO/ouvkFjIJXtYUtNOxU51lBWoACPYJBTXe/4qc3O2cSl3KDXMQ7HKU8eGK42V sE3yKbbwuIZAm+VYTgnY0Uy4 =ggBO -----END PGP SIGNATURE----- Merge tag 'iwlwifi-next-for-kalle-2022-11-06-v2' of http://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next iwlwifi patches intended for v6.2 * iwlmei fixes * Debug mechanism update for new devices (BZ) * Checksum offload fix for the new devices (BZ) * A few rate scale fixes and cleanups * A fix for iwlwifi debug mechanism * Start of MLO preparations - supporting new key API
This commit is contained in:
commit
e7e40cc655
@ -172,6 +172,13 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
|
||||
BIT(NL80211_BAND_6GHZ),
|
||||
};
|
||||
|
||||
static const struct iwl_ht_params iwl_gl_a_ht_params = {
|
||||
.stbc = false, /* we explicitly disable STBC for GL step A */
|
||||
.ldpc = true,
|
||||
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ) |
|
||||
BIT(NL80211_BAND_6GHZ),
|
||||
};
|
||||
|
||||
#define IWL_DEVICE_22000_COMMON \
|
||||
.ucode_api_max = IWL_22000_UCODE_API_MAX, \
|
||||
.ucode_api_min = IWL_22000_UCODE_API_MIN, \
|
||||
@ -249,7 +256,7 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
|
||||
}, \
|
||||
}
|
||||
|
||||
#define IWL_DEVICE_BZ \
|
||||
#define IWL_DEVICE_BZ_COMMON \
|
||||
.ucode_api_max = IWL_22000_UCODE_API_MAX, \
|
||||
.ucode_api_min = IWL_22000_UCODE_API_MIN, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
@ -261,12 +268,10 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
|
||||
.dccm2_len = IWL_22000_DCCM2_LEN, \
|
||||
.smem_offset = IWL_22000_SMEM_OFFSET, \
|
||||
.smem_len = IWL_22000_SMEM_LEN, \
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, \
|
||||
.apmg_not_supported = true, \
|
||||
.trans.mq_rx_supported = true, \
|
||||
.vht_mu_mimo_supported = true, \
|
||||
.mac_addr_from_csr = 0x30, \
|
||||
.ht_params = &iwl_22000_ht_params, \
|
||||
.nvm_ver = IWL_22000_NVM_VERSION, \
|
||||
.trans.use_tfh = true, \
|
||||
.trans.rf_id = true, \
|
||||
@ -313,6 +318,14 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
|
||||
}, \
|
||||
}
|
||||
|
||||
#define IWL_DEVICE_BZ \
|
||||
IWL_DEVICE_BZ_COMMON, \
|
||||
.ht_params = &iwl_22000_ht_params
|
||||
|
||||
#define IWL_DEVICE_GL_A \
|
||||
IWL_DEVICE_BZ_COMMON, \
|
||||
.ht_params = &iwl_gl_a_ht_params
|
||||
|
||||
const struct iwl_cfg_trans_params iwl_qnj_trans_cfg = {
|
||||
.mq_rx_supported = true,
|
||||
.use_tfh = true,
|
||||
@ -901,6 +914,7 @@ const struct iwl_cfg iwl_cfg_bz_a0_hr_b0 = {
|
||||
.fw_name_pre = IWL_BZ_A_HR_B_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
@ -908,6 +922,7 @@ const struct iwl_cfg iwl_cfg_bz_a0_gf_a0 = {
|
||||
.fw_name_pre = IWL_BZ_A_GF_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
@ -915,6 +930,7 @@ const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0 = {
|
||||
.fw_name_pre = IWL_BZ_A_GF4_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
@ -922,6 +938,7 @@ const struct iwl_cfg iwl_cfg_bz_a0_mr_a0 = {
|
||||
.fw_name_pre = IWL_BZ_A_MR_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
@ -929,6 +946,7 @@ const struct iwl_cfg iwl_cfg_bz_a0_fm_a0 = {
|
||||
.fw_name_pre = IWL_BZ_A_FM_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
@ -936,13 +954,15 @@ const struct iwl_cfg iwl_cfg_bz_a0_fm4_a0 = {
|
||||
.fw_name_pre = IWL_BZ_A_FM4_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_gl_a0_fm_a0 = {
|
||||
.fw_name_pre = IWL_GL_A_FM_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
IWL_DEVICE_GL_A,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
@ -950,6 +970,7 @@ const struct iwl_cfg iwl_cfg_gl_b0_fm_b0 = {
|
||||
.fw_name_pre = IWL_GL_B_FM_B_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
@ -957,6 +978,7 @@ const struct iwl_cfg iwl_cfg_bz_z0_gf_a0 = {
|
||||
.fw_name_pre = IWL_BZ_Z_GF_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
@ -964,6 +986,7 @@ const struct iwl_cfg iwl_cfg_bnj_a0_fm_a0 = {
|
||||
.fw_name_pre = IWL_BNJ_A_FM_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
@ -971,6 +994,7 @@ const struct iwl_cfg iwl_cfg_bnj_a0_fm4_a0 = {
|
||||
.fw_name_pre = IWL_BNJ_A_FM4_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
@ -978,6 +1002,7 @@ const struct iwl_cfg iwl_cfg_bnj_a0_gf_a0 = {
|
||||
.fw_name_pre = IWL_BNJ_A_GF_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
@ -985,6 +1010,7 @@ const struct iwl_cfg iwl_cfg_bnj_a0_gf4_a0 = {
|
||||
.fw_name_pre = IWL_BNJ_A_GF4_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
@ -992,6 +1018,7 @@ const struct iwl_cfg iwl_cfg_bnj_a0_hr_b0 = {
|
||||
.fw_name_pre = IWL_BNJ_A_HR_B_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
@ -999,6 +1026,7 @@ const struct iwl_cfg iwl_cfg_bnj_b0_fm_b0 = {
|
||||
.fw_name_pre = IWL_BNJ_B_FM_B_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
|
@ -71,6 +71,11 @@ enum iwl_data_path_subcmd_ids {
|
||||
*/
|
||||
SCD_QUEUE_CONFIG_CMD = 0x17,
|
||||
|
||||
/**
|
||||
* @SEC_KEY_CMD: security key command, uses &struct iwl_sec_key_cmd
|
||||
*/
|
||||
SEC_KEY_CMD = 0x18,
|
||||
|
||||
/**
|
||||
* @MONITOR_NOTIF: Datapath monitoring notification, using
|
||||
* &struct iwl_datapath_monitor_notif
|
||||
@ -403,4 +408,78 @@ struct iwl_scd_queue_cfg_cmd {
|
||||
} __packed u; /* TX_QUEUE_CFG_CMD_OPERATION_API_U_VER_1 */
|
||||
} __packed; /* TX_QUEUE_CFG_CMD_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* enum iwl_sec_key_flags - security key command key flags
|
||||
* @IWL_SEC_KEY_FLAG_CIPHER_MASK: cipher mask
|
||||
* @IWL_SEC_KEY_FLAG_CIPHER_WEP: WEP cipher
|
||||
* @IWL_SEC_KEY_FLAG_CIPHER_CCMP: CCMP/CMAC cipher
|
||||
* @IWL_SEC_KEY_FLAG_CIPHER_TKIP: TKIP cipher
|
||||
* @IWL_SEC_KEY_FLAG_CIPHER_GCMP: GCMP/GMAC cipher
|
||||
* @IWL_SEC_KEY_FLAG_NO_TX: don't install for TX
|
||||
* @IWL_SEC_KEY_FLAG_KEY_SIZE: large key size (WEP-104, GCMP-256, GMAC-256)
|
||||
* @IWL_SEC_KEY_FLAG_MFP: MFP is in used for this key
|
||||
* @IWL_SEC_KEY_FLAG_MCAST_KEY: this is a multicast key
|
||||
* @IWL_SEC_KEY_FLAG_SPP_AMSDU: SPP A-MSDU should be used
|
||||
*/
|
||||
enum iwl_sec_key_flags {
|
||||
IWL_SEC_KEY_FLAG_CIPHER_MASK = 0x07,
|
||||
IWL_SEC_KEY_FLAG_CIPHER_WEP = 0x01,
|
||||
IWL_SEC_KEY_FLAG_CIPHER_CCMP = 0x02,
|
||||
IWL_SEC_KEY_FLAG_CIPHER_TKIP = 0x03,
|
||||
IWL_SEC_KEY_FLAG_CIPHER_GCMP = 0x05,
|
||||
IWL_SEC_KEY_FLAG_NO_TX = 0x08,
|
||||
IWL_SEC_KEY_FLAG_KEY_SIZE = 0x10,
|
||||
IWL_SEC_KEY_FLAG_MFP = 0x20,
|
||||
IWL_SEC_KEY_FLAG_MCAST_KEY = 0x40,
|
||||
IWL_SEC_KEY_FLAG_SPP_AMSDU = 0x80,
|
||||
};
|
||||
|
||||
#define IWL_SEC_WEP_KEY_OFFSET 3
|
||||
|
||||
/**
|
||||
* struct iwl_sec_key_cmd - security key command
|
||||
* @action: action from &enum iwl_ctxt_action
|
||||
* @u.add.sta_mask: station mask for the new key
|
||||
* @u.add.key_id: key ID (0-7) for the new key
|
||||
* @u.add.key_flags: key flags per &enum iwl_sec_key_flags
|
||||
* @u.add.key: key material. WEP keys should start from &IWL_SEC_WEP_KEY_OFFSET.
|
||||
* @u.add.tkip_mic_rx_key: TKIP MIC RX key
|
||||
* @u.add.tkip_mic_tx_key: TKIP MIC TX key
|
||||
* @u.add.rx_seq: RX sequence counter value
|
||||
* @u.add.tx_seq: TX sequence counter value
|
||||
* @u.modify.old_sta_mask: old station mask
|
||||
* @u.modify.new_sta_mask: new station mask
|
||||
* @u.modify.key_id: key ID
|
||||
* @u.modify.key_flags: new key flags
|
||||
* @u.remove.sta_mask: station mask
|
||||
* @u.remove.key_id: key ID
|
||||
* @u.remove.key_flags: key flags
|
||||
*/
|
||||
struct iwl_sec_key_cmd {
|
||||
__le32 action;
|
||||
union {
|
||||
struct {
|
||||
__le32 sta_mask;
|
||||
__le32 key_id;
|
||||
__le32 key_flags;
|
||||
u8 key[32];
|
||||
u8 tkip_mic_rx_key[8];
|
||||
u8 tkip_mic_tx_key[8];
|
||||
__le64 rx_seq;
|
||||
__le64 tx_seq;
|
||||
} __packed add; /* SEC_KEY_ADD_CMD_API_S_VER_1 */
|
||||
struct {
|
||||
__le32 old_sta_mask;
|
||||
__le32 new_sta_mask;
|
||||
__le32 key_id;
|
||||
__le32 key_flags;
|
||||
} __packed modify; /* SEC_KEY_MODIFY_CMD_API_S_VER_1 */
|
||||
struct {
|
||||
__le32 sta_mask;
|
||||
__le32 key_id;
|
||||
__le32 key_flags;
|
||||
} __packed remove; /* SEC_KEY_REMOVE_CMD_API_S_VER_1 */
|
||||
} __packed u; /* SEC_KEY_OPERATION_API_U_VER_1 */
|
||||
} __packed; /* SEC_KEY_CMD_API_S_VER_1 */
|
||||
|
||||
#endif /* __iwl_fw_api_datapath_h__ */
|
||||
|
@ -590,6 +590,9 @@ static int iwl_dbg_tlv_alloc_fragments(struct iwl_fw_runtime *fwrt,
|
||||
if (alloc_id != IWL_FW_INI_ALLOCATION_ID_DBGC1)
|
||||
return -EIO;
|
||||
num_frags = 1;
|
||||
} else if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ &&
|
||||
alloc_id > IWL_FW_INI_ALLOCATION_ID_DBGC3) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
remain_pages = DIV_ROUND_UP(le32_to_cpu(fw_mon_cfg->req_size),
|
||||
@ -789,7 +792,7 @@ static void iwl_dbg_tlv_update_drams(struct iwl_fw_runtime *fwrt)
|
||||
dram_info->second_word = cpu_to_le32(DRAM_INFO_SECOND_MAGIC_WORD);
|
||||
|
||||
for (i = IWL_FW_INI_ALLOCATION_ID_DBGC1;
|
||||
i <= IWL_FW_INI_ALLOCATION_ID_DBGC3; i++) {
|
||||
i < IWL_FW_INI_ALLOCATION_NUM; i++) {
|
||||
ret = iwl_dbg_tlv_update_dram(fwrt, i, dram_info);
|
||||
if (!ret)
|
||||
dram_alloc = true;
|
||||
@ -1324,7 +1327,7 @@ static void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt)
|
||||
"WRT: removing allocation id %d from region id %d\n",
|
||||
le32_to_cpu(reg->dram_alloc_id), i);
|
||||
|
||||
failed_alloc &= ~le32_to_cpu(reg->dram_alloc_id);
|
||||
failed_alloc &= ~BIT(le32_to_cpu(reg->dram_alloc_id));
|
||||
fwrt->trans->dbg.unsupported_region_msk |= BIT(i);
|
||||
|
||||
kfree(*active_reg);
|
||||
|
@ -377,6 +377,7 @@ enum {
|
||||
#define PREG_PRPH_WPROT_22000 0xA04D00
|
||||
|
||||
#define SB_MODIFY_CFG_FLAG 0xA03088
|
||||
#define SB_CFG_RESIDES_IN_OTP_MASK 0x10
|
||||
#define SB_CPU_1_STATUS 0xA01E30
|
||||
#define SB_CPU_2_STATUS 0xA01E34
|
||||
#define UMAG_SB_CPU_1_STATUS 0xA038C0
|
||||
@ -500,4 +501,7 @@ enum {
|
||||
|
||||
#define REG_OTP_MINOR 0xA0333C
|
||||
|
||||
#define WFPM_LMAC2_PD_NOTIFICATION 0xA033CC
|
||||
#define WFPM_LMAC2_PD_RE_READ BIT(31)
|
||||
|
||||
#endif /* __iwl_prph_h__ */
|
||||
|
@ -220,6 +220,7 @@ struct iwl_mei_nvm {
|
||||
/**
|
||||
* enum iwl_mei_pairwise_cipher - cipher for UCAST key
|
||||
* @IWL_MEI_CIPHER_NONE: none
|
||||
* @IWL_MEI_CIPHER_TKIP: tkip
|
||||
* @IWL_MEI_CIPHER_CCMP: ccmp
|
||||
* @IWL_MEI_CIPHER_GCMP: gcmp
|
||||
* @IWL_MEI_CIPHER_GCMP_256: gcmp 256
|
||||
@ -228,6 +229,7 @@ struct iwl_mei_nvm {
|
||||
*/
|
||||
enum iwl_mei_pairwise_cipher {
|
||||
IWL_MEI_CIPHER_NONE = 0,
|
||||
IWL_MEI_CIPHER_TKIP = 2,
|
||||
IWL_MEI_CIPHER_CCMP = 4,
|
||||
IWL_MEI_CIPHER_GCMP = 8,
|
||||
IWL_MEI_CIPHER_GCMP_256 = 9,
|
||||
@ -446,9 +448,25 @@ void iwl_mei_host_associated(const struct iwl_mei_conn_info *conn_info,
|
||||
void iwl_mei_host_disassociated(void);
|
||||
|
||||
/**
|
||||
* iwl_mei_device_down() - must be called when the device is down
|
||||
* iwl_mei_device_state() - must be called when the device changes up/down state
|
||||
* @up: true if the device is up, false otherwise.
|
||||
*/
|
||||
void iwl_mei_device_down(void);
|
||||
void iwl_mei_device_state(bool up);
|
||||
|
||||
/**
|
||||
* iwl_mei_pldr_req() - must be called before loading the fw
|
||||
*
|
||||
* Return: 0 if the PLDR flow was successful and the fw can be loaded, negative
|
||||
* value otherwise.
|
||||
*/
|
||||
int iwl_mei_pldr_req(void);
|
||||
|
||||
/**
|
||||
* iwl_mei_alive_notif() - must be called when alive notificaiton is received
|
||||
* @success: true if received alive notification, false if waiting for the
|
||||
* notificaiton timed out.
|
||||
*/
|
||||
void iwl_mei_alive_notif(bool success);
|
||||
|
||||
#else
|
||||
|
||||
@ -497,7 +515,13 @@ static inline void iwl_mei_host_associated(const struct iwl_mei_conn_info *conn_
|
||||
static inline void iwl_mei_host_disassociated(void)
|
||||
{}
|
||||
|
||||
static inline void iwl_mei_device_down(void)
|
||||
static inline void iwl_mei_device_state(bool up)
|
||||
{}
|
||||
|
||||
static inline int iwl_mei_pldr_req(void)
|
||||
{ return 0; }
|
||||
|
||||
static inline void iwl_mei_alive_notif(bool success)
|
||||
{}
|
||||
|
||||
#endif /* CONFIG_IWLMEI */
|
||||
|
@ -147,9 +147,15 @@ struct iwl_mei_filters {
|
||||
* to send CSME_OWNERSHIP_CONFIRMED when the driver completes its down
|
||||
* flow.
|
||||
* @link_prot_state: true when we are in link protection PASSIVE
|
||||
* @device_down: true if the device is down. Used to remember to send
|
||||
* CSME_OWNERSHIP_CONFIRMED when the driver is already down.
|
||||
* @csa_throttle_end_wk: used when &csa_throttled is true
|
||||
* @pldr_wq: the wait queue for PLDR flow
|
||||
* @pldr_active: PLDR flow is in progress
|
||||
* @data_q_lock: protects the access to the data queues which are
|
||||
* accessed without the mutex.
|
||||
* @netdev_work: used to defer registering and unregistering of the netdev to
|
||||
* avoid taking the rtnl lock in the SAP messages handlers.
|
||||
* @sap_seq_no: the sequence number for the SAP messages
|
||||
* @seq_no: the sequence number for the SAP messages
|
||||
* @dbgfs_dir: the debugfs dir entry
|
||||
@ -167,8 +173,12 @@ struct iwl_mei {
|
||||
bool csa_throttled;
|
||||
bool csme_taking_ownership;
|
||||
bool link_prot_state;
|
||||
bool device_down;
|
||||
struct delayed_work csa_throttle_end_wk;
|
||||
wait_queue_head_t pldr_wq;
|
||||
bool pldr_active;
|
||||
spinlock_t data_q_lock;
|
||||
struct work_struct netdev_work;
|
||||
|
||||
atomic_t sap_seq_no;
|
||||
atomic_t seq_no;
|
||||
@ -588,13 +598,38 @@ static rx_handler_result_t iwl_mei_rx_handler(struct sk_buff **pskb)
|
||||
return res;
|
||||
}
|
||||
|
||||
static void iwl_mei_netdev_work(struct work_struct *wk)
|
||||
{
|
||||
struct iwl_mei *mei =
|
||||
container_of(wk, struct iwl_mei, netdev_work);
|
||||
struct net_device *netdev;
|
||||
|
||||
/*
|
||||
* First take rtnl and only then the mutex to avoid an ABBA
|
||||
* with iwl_mei_set_netdev()
|
||||
*/
|
||||
rtnl_lock();
|
||||
mutex_lock(&iwl_mei_mutex);
|
||||
|
||||
netdev = rcu_dereference_protected(iwl_mei_cache.netdev,
|
||||
lockdep_is_held(&iwl_mei_mutex));
|
||||
if (netdev) {
|
||||
if (mei->amt_enabled)
|
||||
netdev_rx_handler_register(netdev, iwl_mei_rx_handler,
|
||||
mei);
|
||||
else
|
||||
netdev_rx_handler_unregister(netdev);
|
||||
}
|
||||
|
||||
mutex_unlock(&iwl_mei_mutex);
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mei_handle_rx_start_ok(struct mei_cl_device *cldev,
|
||||
const struct iwl_sap_me_msg_start_ok *rsp,
|
||||
ssize_t len)
|
||||
{
|
||||
struct iwl_mei *mei = mei_cldev_get_drvdata(cldev);
|
||||
|
||||
if (len != sizeof(*rsp)) {
|
||||
dev_err(&cldev->dev,
|
||||
"got invalid SAP_ME_MSG_START_OK from CSME firmware\n");
|
||||
@ -613,13 +648,10 @@ iwl_mei_handle_rx_start_ok(struct mei_cl_device *cldev,
|
||||
|
||||
mutex_lock(&iwl_mei_mutex);
|
||||
set_bit(IWL_MEI_STATUS_SAP_CONNECTED, &iwl_mei_status);
|
||||
/* wifi driver has registered already */
|
||||
if (iwl_mei_cache.ops) {
|
||||
iwl_mei_send_sap_msg(mei->cldev,
|
||||
SAP_MSG_NOTIF_WIFIDR_UP);
|
||||
iwl_mei_cache.ops->sap_connected(iwl_mei_cache.priv);
|
||||
}
|
||||
|
||||
/*
|
||||
* We'll receive AMT_STATE SAP message in a bit and
|
||||
* that will continue the flow
|
||||
*/
|
||||
mutex_unlock(&iwl_mei_mutex);
|
||||
}
|
||||
|
||||
@ -712,6 +744,13 @@ static void iwl_mei_set_init_conf(struct iwl_mei *mei)
|
||||
.val = cpu_to_le32(iwl_mei_cache.rf_kill),
|
||||
};
|
||||
|
||||
/* wifi driver has registered already */
|
||||
if (iwl_mei_cache.ops) {
|
||||
iwl_mei_send_sap_msg(mei->cldev,
|
||||
SAP_MSG_NOTIF_WIFIDR_UP);
|
||||
iwl_mei_cache.ops->sap_connected(iwl_mei_cache.priv);
|
||||
}
|
||||
|
||||
iwl_mei_send_sap_msg(mei->cldev, SAP_MSG_NOTIF_WHO_OWNS_NIC);
|
||||
|
||||
if (iwl_mei_cache.conn_info) {
|
||||
@ -738,38 +777,23 @@ static void iwl_mei_handle_amt_state(struct mei_cl_device *cldev,
|
||||
const struct iwl_sap_msg_dw *dw)
|
||||
{
|
||||
struct iwl_mei *mei = mei_cldev_get_drvdata(cldev);
|
||||
struct net_device *netdev;
|
||||
|
||||
/*
|
||||
* First take rtnl and only then the mutex to avoid an ABBA
|
||||
* with iwl_mei_set_netdev()
|
||||
*/
|
||||
rtnl_lock();
|
||||
mutex_lock(&iwl_mei_mutex);
|
||||
|
||||
netdev = rcu_dereference_protected(iwl_mei_cache.netdev,
|
||||
lockdep_is_held(&iwl_mei_mutex));
|
||||
|
||||
if (mei->amt_enabled == !!le32_to_cpu(dw->val))
|
||||
goto out;
|
||||
|
||||
mei->amt_enabled = dw->val;
|
||||
|
||||
if (mei->amt_enabled) {
|
||||
if (netdev)
|
||||
netdev_rx_handler_register(netdev, iwl_mei_rx_handler, mei);
|
||||
|
||||
if (mei->amt_enabled)
|
||||
iwl_mei_set_init_conf(mei);
|
||||
} else {
|
||||
if (iwl_mei_cache.ops)
|
||||
iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, false);
|
||||
if (netdev)
|
||||
netdev_rx_handler_unregister(netdev);
|
||||
}
|
||||
else if (iwl_mei_cache.ops)
|
||||
iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, false, false);
|
||||
|
||||
schedule_work(&mei->netdev_work);
|
||||
|
||||
out:
|
||||
mutex_unlock(&iwl_mei_mutex);
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
static void iwl_mei_handle_nic_owner(struct mei_cl_device *cldev,
|
||||
@ -798,14 +822,18 @@ static void iwl_mei_handle_csme_taking_ownership(struct mei_cl_device *cldev,
|
||||
|
||||
mei->got_ownership = false;
|
||||
|
||||
/*
|
||||
* Remember to send CSME_OWNERSHIP_CONFIRMED when the wifi driver
|
||||
* is finished taking the device down.
|
||||
*/
|
||||
mei->csme_taking_ownership = true;
|
||||
if (iwl_mei_cache.ops && !mei->device_down) {
|
||||
/*
|
||||
* Remember to send CSME_OWNERSHIP_CONFIRMED when the wifi
|
||||
* driver is finished taking the device down.
|
||||
*/
|
||||
mei->csme_taking_ownership = true;
|
||||
|
||||
if (iwl_mei_cache.ops)
|
||||
iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, true);
|
||||
iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, true, true);
|
||||
} else {
|
||||
iwl_mei_send_sap_msg(cldev,
|
||||
SAP_MSG_NOTIF_CSME_OWNERSHIP_CONFIRMED);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mei_handle_nvm(struct mei_cl_device *cldev,
|
||||
@ -857,6 +885,15 @@ static void iwl_mei_handle_rx_host_own_req(struct mei_cl_device *cldev,
|
||||
iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, false);
|
||||
}
|
||||
|
||||
static void iwl_mei_handle_pldr_ack(struct mei_cl_device *cldev,
|
||||
const struct iwl_sap_pldr_ack_data *ack)
|
||||
{
|
||||
struct iwl_mei *mei = mei_cldev_get_drvdata(cldev);
|
||||
|
||||
mei->pldr_active = le32_to_cpu(ack->status) == SAP_PLDR_STATUS_SUCCESS;
|
||||
wake_up_all(&mei->pldr_wq);
|
||||
}
|
||||
|
||||
static void iwl_mei_handle_ping(struct mei_cl_device *cldev,
|
||||
const struct iwl_sap_hdr *hdr)
|
||||
{
|
||||
@ -937,6 +974,8 @@ static void iwl_mei_handle_sap_msg(struct mei_cl_device *cldev,
|
||||
iwl_mei_handle_can_release_ownership, 0);
|
||||
SAP_MSG_HANDLER(CSME_TAKING_OWNERSHIP,
|
||||
iwl_mei_handle_csme_taking_ownership, 0);
|
||||
SAP_MSG_HANDLER(PLDR_ACK, iwl_mei_handle_pldr_ack,
|
||||
sizeof(struct iwl_sap_pldr_ack_data));
|
||||
default:
|
||||
/*
|
||||
* This is not really an error, there are message that we decided
|
||||
@ -1313,6 +1352,62 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_mei_get_nvm);
|
||||
|
||||
#define IWL_MEI_PLDR_NUM_RETRIES 3
|
||||
|
||||
int iwl_mei_pldr_req(void)
|
||||
{
|
||||
struct iwl_mei *mei;
|
||||
int ret;
|
||||
struct iwl_sap_pldr_data msg = {
|
||||
.hdr.type = cpu_to_le16(SAP_MSG_NOTIF_PLDR),
|
||||
.hdr.len = cpu_to_le16(sizeof(msg) - sizeof(msg.hdr)),
|
||||
};
|
||||
int i;
|
||||
|
||||
mutex_lock(&iwl_mei_mutex);
|
||||
|
||||
/* In case we didn't have a bind */
|
||||
if (!iwl_mei_is_connected()) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mei = mei_cldev_get_drvdata(iwl_mei_global_cldev);
|
||||
|
||||
if (!mei) {
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!mei->amt_enabled) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < IWL_MEI_PLDR_NUM_RETRIES; i++) {
|
||||
ret = iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr);
|
||||
mutex_unlock(&iwl_mei_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = wait_event_timeout(mei->pldr_wq, mei->pldr_active, HZ / 2);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
/* Take the mutex for the next iteration */
|
||||
mutex_lock(&iwl_mei_mutex);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
ret = -ETIMEDOUT;
|
||||
out:
|
||||
mutex_unlock(&iwl_mei_mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_mei_pldr_req);
|
||||
|
||||
int iwl_mei_get_ownership(void)
|
||||
{
|
||||
struct iwl_mei *mei;
|
||||
@ -1352,32 +1447,40 @@ int iwl_mei_get_ownership(void)
|
||||
|
||||
ret = wait_event_timeout(mei->get_ownership_wq,
|
||||
mei->got_ownership, HZ / 2);
|
||||
if (!ret)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
mutex_lock(&iwl_mei_mutex);
|
||||
|
||||
/* In case we didn't have a bind */
|
||||
if (!iwl_mei_is_connected()) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mei = mei_cldev_get_drvdata(iwl_mei_global_cldev);
|
||||
|
||||
if (!mei) {
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = !mei->got_ownership;
|
||||
|
||||
return (!ret) ? -ETIMEDOUT : 0;
|
||||
out:
|
||||
mutex_unlock(&iwl_mei_mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_mei_get_ownership);
|
||||
|
||||
void iwl_mei_alive_notif(bool success)
|
||||
{
|
||||
struct iwl_mei *mei;
|
||||
struct iwl_sap_pldr_end_data msg = {
|
||||
.hdr.type = cpu_to_le16(SAP_MSG_NOTIF_PLDR_END),
|
||||
.hdr.len = cpu_to_le16(sizeof(msg) - sizeof(msg.hdr)),
|
||||
.status = success ? cpu_to_le32(SAP_PLDR_STATUS_SUCCESS) :
|
||||
cpu_to_le32(SAP_PLDR_STATUS_FAILURE),
|
||||
};
|
||||
|
||||
mutex_lock(&iwl_mei_mutex);
|
||||
|
||||
if (!iwl_mei_is_connected())
|
||||
goto out;
|
||||
|
||||
mei = mei_cldev_get_drvdata(iwl_mei_global_cldev);
|
||||
if (!mei || !mei->pldr_active)
|
||||
goto out;
|
||||
|
||||
mei->pldr_active = false;
|
||||
|
||||
iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr);
|
||||
out:
|
||||
mutex_unlock(&iwl_mei_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_mei_alive_notif);
|
||||
|
||||
void iwl_mei_host_associated(const struct iwl_mei_conn_info *conn_info,
|
||||
const struct iwl_mei_colloc_info *colloc_info)
|
||||
{
|
||||
@ -1413,10 +1516,7 @@ void iwl_mei_host_associated(const struct iwl_mei_conn_info *conn_info,
|
||||
|
||||
mei = mei_cldev_get_drvdata(iwl_mei_global_cldev);
|
||||
|
||||
if (!mei)
|
||||
goto out;
|
||||
|
||||
if (!mei->amt_enabled)
|
||||
if (!mei && !mei->amt_enabled)
|
||||
goto out;
|
||||
|
||||
iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr);
|
||||
@ -1435,7 +1535,7 @@ void iwl_mei_host_disassociated(void)
|
||||
struct iwl_sap_notif_host_link_down msg = {
|
||||
.hdr.type = cpu_to_le16(SAP_MSG_NOTIF_HOST_LINK_DOWN),
|
||||
.hdr.len = cpu_to_le16(sizeof(msg) - sizeof(msg.hdr)),
|
||||
.type = HOST_LINK_DOWN_TYPE_LONG,
|
||||
.type = HOST_LINK_DOWN_TYPE_TEMPORARY,
|
||||
};
|
||||
|
||||
mutex_lock(&iwl_mei_mutex);
|
||||
@ -1445,7 +1545,7 @@ void iwl_mei_host_disassociated(void)
|
||||
|
||||
mei = mei_cldev_get_drvdata(iwl_mei_global_cldev);
|
||||
|
||||
if (!mei)
|
||||
if (!mei && !mei->amt_enabled)
|
||||
goto out;
|
||||
|
||||
iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr);
|
||||
@ -1481,7 +1581,7 @@ void iwl_mei_set_rfkill_state(bool hw_rfkill, bool sw_rfkill)
|
||||
|
||||
mei = mei_cldev_get_drvdata(iwl_mei_global_cldev);
|
||||
|
||||
if (!mei)
|
||||
if (!mei && !mei->amt_enabled)
|
||||
goto out;
|
||||
|
||||
iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr);
|
||||
@ -1510,7 +1610,7 @@ void iwl_mei_set_nic_info(const u8 *mac_address, const u8 *nvm_address)
|
||||
|
||||
mei = mei_cldev_get_drvdata(iwl_mei_global_cldev);
|
||||
|
||||
if (!mei)
|
||||
if (!mei && !mei->amt_enabled)
|
||||
goto out;
|
||||
|
||||
iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr);
|
||||
@ -1538,7 +1638,7 @@ void iwl_mei_set_country_code(u16 mcc)
|
||||
|
||||
mei = mei_cldev_get_drvdata(iwl_mei_global_cldev);
|
||||
|
||||
if (!mei)
|
||||
if (!mei && !mei->amt_enabled)
|
||||
goto out;
|
||||
|
||||
iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr);
|
||||
@ -1564,7 +1664,7 @@ void iwl_mei_set_power_limit(const __le16 *power_limit)
|
||||
|
||||
mei = mei_cldev_get_drvdata(iwl_mei_global_cldev);
|
||||
|
||||
if (!mei)
|
||||
if (!mei && !mei->amt_enabled)
|
||||
goto out;
|
||||
|
||||
memcpy(msg.sar_chain_info_table, power_limit, sizeof(msg.sar_chain_info_table));
|
||||
@ -1616,7 +1716,7 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_mei_set_netdev);
|
||||
|
||||
void iwl_mei_device_down(void)
|
||||
void iwl_mei_device_state(bool up)
|
||||
{
|
||||
struct iwl_mei *mei;
|
||||
|
||||
@ -1630,7 +1730,9 @@ void iwl_mei_device_down(void)
|
||||
if (!mei)
|
||||
goto out;
|
||||
|
||||
if (!mei->csme_taking_ownership)
|
||||
mei->device_down = !up;
|
||||
|
||||
if (up || !mei->csme_taking_ownership)
|
||||
goto out;
|
||||
|
||||
iwl_mei_send_sap_msg(mei->cldev,
|
||||
@ -1639,7 +1741,7 @@ void iwl_mei_device_down(void)
|
||||
out:
|
||||
mutex_unlock(&iwl_mei_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_mei_device_down);
|
||||
EXPORT_SYMBOL_GPL(iwl_mei_device_state);
|
||||
|
||||
int iwl_mei_register(void *priv, const struct iwl_mei_ops *ops)
|
||||
{
|
||||
@ -1669,9 +1771,10 @@ int iwl_mei_register(void *priv, const struct iwl_mei_ops *ops)
|
||||
|
||||
/* we have already a SAP connection */
|
||||
if (iwl_mei_is_connected()) {
|
||||
iwl_mei_send_sap_msg(mei->cldev,
|
||||
SAP_MSG_NOTIF_WIFIDR_UP);
|
||||
ops->rfkill(priv, mei->link_prot_state);
|
||||
if (mei->amt_enabled)
|
||||
iwl_mei_send_sap_msg(mei->cldev,
|
||||
SAP_MSG_NOTIF_WIFIDR_UP);
|
||||
ops->rfkill(priv, mei->link_prot_state, false);
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
@ -1817,10 +1920,13 @@ static int iwl_mei_probe(struct mei_cl_device *cldev,
|
||||
INIT_DELAYED_WORK(&mei->csa_throttle_end_wk,
|
||||
iwl_mei_csa_throttle_end_wk);
|
||||
init_waitqueue_head(&mei->get_ownership_wq);
|
||||
init_waitqueue_head(&mei->pldr_wq);
|
||||
spin_lock_init(&mei->data_q_lock);
|
||||
INIT_WORK(&mei->netdev_work, iwl_mei_netdev_work);
|
||||
|
||||
mei_cldev_set_drvdata(cldev, mei);
|
||||
mei->cldev = cldev;
|
||||
mei->device_down = true;
|
||||
|
||||
do {
|
||||
ret = iwl_mei_alloc_shared_mem(cldev);
|
||||
@ -1884,6 +1990,7 @@ free:
|
||||
}
|
||||
|
||||
#define SEND_SAP_MAX_WAIT_ITERATION 10
|
||||
#define IWLMEI_DEVICE_DOWN_WAIT_ITERATION 50
|
||||
|
||||
static void iwl_mei_remove(struct mei_cl_device *cldev)
|
||||
{
|
||||
@ -1894,8 +2001,26 @@ static void iwl_mei_remove(struct mei_cl_device *cldev)
|
||||
* We are being removed while the bus is active, it means we are
|
||||
* going to suspend/ shutdown, so the NIC will disappear.
|
||||
*/
|
||||
if (mei_cldev_enabled(cldev) && iwl_mei_cache.ops)
|
||||
iwl_mei_cache.ops->nic_stolen(iwl_mei_cache.priv);
|
||||
if (mei_cldev_enabled(cldev) && iwl_mei_cache.ops) {
|
||||
unsigned int iter = IWLMEI_DEVICE_DOWN_WAIT_ITERATION;
|
||||
bool down = false;
|
||||
|
||||
/*
|
||||
* In case of suspend, wait for the mac to stop and don't remove
|
||||
* the interface. This will allow the interface to come back
|
||||
* on resume.
|
||||
*/
|
||||
while (!down && iter--) {
|
||||
mdelay(1);
|
||||
|
||||
mutex_lock(&iwl_mei_mutex);
|
||||
down = mei->device_down;
|
||||
mutex_unlock(&iwl_mei_mutex);
|
||||
}
|
||||
|
||||
if (!down)
|
||||
iwl_mei_cache.ops->nic_stolen(iwl_mei_cache.priv);
|
||||
}
|
||||
|
||||
if (rcu_access_pointer(iwl_mei_cache.netdev)) {
|
||||
struct net_device *dev;
|
||||
@ -1921,30 +2046,33 @@ static void iwl_mei_remove(struct mei_cl_device *cldev)
|
||||
|
||||
mutex_lock(&iwl_mei_mutex);
|
||||
|
||||
/*
|
||||
* Tell CSME that we are going down so that it won't access the
|
||||
* memory anymore, make sure this message goes through immediately.
|
||||
*/
|
||||
mei->csa_throttled = false;
|
||||
iwl_mei_send_sap_msg(mei->cldev,
|
||||
SAP_MSG_NOTIF_HOST_GOES_DOWN);
|
||||
if (mei->amt_enabled) {
|
||||
/*
|
||||
* Tell CSME that we are going down so that it won't access the
|
||||
* memory anymore, make sure this message goes through immediately.
|
||||
*/
|
||||
mei->csa_throttled = false;
|
||||
iwl_mei_send_sap_msg(mei->cldev,
|
||||
SAP_MSG_NOTIF_HOST_GOES_DOWN);
|
||||
|
||||
for (i = 0; i < SEND_SAP_MAX_WAIT_ITERATION; i++) {
|
||||
if (!iwl_mei_host_to_me_data_pending(mei))
|
||||
break;
|
||||
for (i = 0; i < SEND_SAP_MAX_WAIT_ITERATION; i++) {
|
||||
if (!iwl_mei_host_to_me_data_pending(mei))
|
||||
break;
|
||||
|
||||
msleep(5);
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we couldn't make sure that CSME saw the HOST_GOES_DOWN
|
||||
* message, it means that it will probably keep reading memory
|
||||
* that we are going to unmap and free, expect IOMMU error
|
||||
* messages.
|
||||
*/
|
||||
if (i == SEND_SAP_MAX_WAIT_ITERATION)
|
||||
dev_err(&mei->cldev->dev,
|
||||
"Couldn't get ACK from CSME on HOST_GOES_DOWN message\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* If we couldn't make sure that CSME saw the HOST_GOES_DOWN message,
|
||||
* it means that it will probably keep reading memory that we are going
|
||||
* to unmap and free, expect IOMMU error messages.
|
||||
*/
|
||||
if (i == SEND_SAP_MAX_WAIT_ITERATION)
|
||||
dev_err(&mei->cldev->dev,
|
||||
"Couldn't get ACK from CSME on HOST_GOES_DOWN message\n");
|
||||
|
||||
mutex_unlock(&iwl_mei_mutex);
|
||||
|
||||
/*
|
||||
@ -1976,6 +2104,7 @@ static void iwl_mei_remove(struct mei_cl_device *cldev)
|
||||
*/
|
||||
cancel_work_sync(&mei->send_csa_msg_wk);
|
||||
cancel_delayed_work_sync(&mei->csa_throttle_end_wk);
|
||||
cancel_work_sync(&mei->netdev_work);
|
||||
|
||||
/*
|
||||
* If someone waits for the ownership, let him know that we are going
|
||||
@ -1983,6 +2112,7 @@ static void iwl_mei_remove(struct mei_cl_device *cldev)
|
||||
* the device.
|
||||
*/
|
||||
wake_up_all(&mei->get_ownership_wq);
|
||||
wake_up_all(&mei->pldr_wq);
|
||||
|
||||
mutex_lock(&iwl_mei_mutex);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2021 Intel Corporation
|
||||
* Copyright (C) 2021-2022 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <uapi/linux/if_ether.h>
|
||||
@ -337,10 +337,14 @@ rx_handler_result_t iwl_mei_rx_filter(struct sk_buff *orig_skb,
|
||||
if (!*pass_to_csme)
|
||||
return RX_HANDLER_PASS;
|
||||
|
||||
if (ret == RX_HANDLER_PASS)
|
||||
if (ret == RX_HANDLER_PASS) {
|
||||
skb = skb_copy(orig_skb, GFP_ATOMIC);
|
||||
else
|
||||
|
||||
if (!skb)
|
||||
return RX_HANDLER_PASS;
|
||||
} else {
|
||||
skb = orig_skb;
|
||||
}
|
||||
|
||||
/* CSME wants the MAC header as well, push it back */
|
||||
skb_push(skb, skb->data - skb_mac_header(skb));
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2021 Intel Corporation
|
||||
* Copyright (C) 2021 - 2022 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __sap_h__
|
||||
@ -203,6 +203,7 @@ struct iwl_sap_me_msg_start_ok {
|
||||
* @SAP_MSG_NOTIF_NIC_OWNER: Payload is a DW. See &enum iwl_sap_nic_owner.
|
||||
* @SAP_MSG_NOTIF_CSME_CONN_STATUS: See &struct iwl_sap_notif_conn_status.
|
||||
* @SAP_MSG_NOTIF_NVM: See &struct iwl_sap_nvm.
|
||||
* @SAP_MSG_NOTIF_PLDR_ACK: See &struct iwl_sap_pldr_ack_data.
|
||||
* @SAP_MSG_NOTIF_FROM_CSME_MAX: Not used.
|
||||
*
|
||||
* @SAP_MSG_NOTIF_FROM_HOST_MIN: Not used.
|
||||
@ -226,6 +227,8 @@ struct iwl_sap_me_msg_start_ok {
|
||||
* @SAP_MSG_NOTIF_HOST_OWNERSHIP_CONFIRMED: No payload.
|
||||
* @SAP_MSG_NOTIF_SAR_LIMITS: See &struct iwl_sap_notif_sar_limits.
|
||||
* @SAP_MSG_NOTIF_GET_NVM: No payload. Triggers %SAP_MSG_NOTIF_NVM.
|
||||
* @SAP_MSG_NOTIF_PLDR: See &struct iwl_sap_pldr_data.
|
||||
* @SAP_MSG_NOTIF_PLDR_END: See &struct iwl_sap_pldr_end_data.
|
||||
* @SAP_MSG_NOTIF_FROM_HOST_MAX: Not used.
|
||||
*
|
||||
* @SAP_MSG_DATA_MIN: Not used.
|
||||
@ -258,6 +261,8 @@ enum iwl_sap_msg {
|
||||
SAP_MSG_NOTIF_NIC_OWNER = 511,
|
||||
SAP_MSG_NOTIF_CSME_CONN_STATUS = 512,
|
||||
SAP_MSG_NOTIF_NVM = 513,
|
||||
/* 514 - 517 not supported */
|
||||
SAP_MSG_NOTIF_PLDR_ACK = 518,
|
||||
SAP_MSG_NOTIF_FROM_CSME_MAX,
|
||||
|
||||
SAP_MSG_NOTIF_FROM_HOST_MIN = 1000,
|
||||
@ -279,6 +284,9 @@ enum iwl_sap_msg {
|
||||
SAP_MSG_NOTIF_HOST_OWNERSHIP_CONFIRMED = 1015,
|
||||
SAP_MSG_NOTIF_SAR_LIMITS = 1016,
|
||||
SAP_MSG_NOTIF_GET_NVM = 1017,
|
||||
/* 1018 - 1023 not supported */
|
||||
SAP_MSG_NOTIF_PLDR = 1024,
|
||||
SAP_MSG_NOTIF_PLDR_END = 1025,
|
||||
SAP_MSG_NOTIF_FROM_HOST_MAX,
|
||||
|
||||
SAP_MSG_DATA_MIN = 2000,
|
||||
@ -334,12 +342,14 @@ enum iwl_sap_wifi_auth_type {
|
||||
/**
|
||||
* enum iwl_sap_wifi_cipher_alg
|
||||
* @SAP_WIFI_CIPHER_ALG_NONE: TBD
|
||||
* @SAP_WIFI_CIPHER_ALG_TKIP: TBD
|
||||
* @SAP_WIFI_CIPHER_ALG_CCMP: TBD
|
||||
* @SAP_WIFI_CIPHER_ALG_GCMP: TBD
|
||||
* @SAP_WIFI_CIPHER_ALG_GCMP_256: TBD
|
||||
*/
|
||||
enum iwl_sap_wifi_cipher_alg {
|
||||
SAP_WIFI_CIPHER_ALG_NONE = IWL_MEI_CIPHER_NONE,
|
||||
SAP_WIFI_CIPHER_ALG_TKIP = IWL_MEI_CIPHER_TKIP,
|
||||
SAP_WIFI_CIPHER_ALG_CCMP = IWL_MEI_CIPHER_CCMP,
|
||||
SAP_WIFI_CIPHER_ALG_GCMP = IWL_MEI_CIPHER_GCMP,
|
||||
SAP_WIFI_CIPHER_ALG_GCMP_256 = IWL_MEI_CIPHER_GCMP_256,
|
||||
@ -730,4 +740,47 @@ struct iwl_sap_cb_data {
|
||||
u8 payload[];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_sap_pldr_data - payload of %SAP_MSG_NOTIF_PLDR
|
||||
* @hdr: The SAP header.
|
||||
* @version: SAP message version
|
||||
*/
|
||||
struct iwl_sap_pldr_data {
|
||||
struct iwl_sap_hdr hdr;
|
||||
__le32 version;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* enum iwl_sap_pldr_status -
|
||||
* @SAP_PLDR_STATUS_SUCCESS: PLDR started/ended successfully
|
||||
* @SAP_PLDR_STATUS_FAILURE: PLDR failed to start/end
|
||||
*/
|
||||
enum iwl_sap_pldr_status {
|
||||
SAP_PLDR_STATUS_SUCCESS = 0,
|
||||
SAP_PLDR_STATUS_FAILURE = 1,
|
||||
};
|
||||
|
||||
/*
|
||||
* struct iwl_sap_pldr_end_data - payload of %SAP_MSG_NOTIF_PLDR_END
|
||||
* @hdr: The SAP header.
|
||||
* @version: SAP message version
|
||||
* @status: PLDR end status
|
||||
*/
|
||||
struct iwl_sap_pldr_end_data {
|
||||
struct iwl_sap_hdr hdr;
|
||||
__le32 version;
|
||||
__le32 status;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* struct iwl_sap_pldr_ack_data - payload of %SAP_MSG_NOTIF_PLDR_ACK
|
||||
* @version: SAP message version
|
||||
* @status: CSME accept/refuse to the PLDR request
|
||||
*/
|
||||
struct iwl_sap_pldr_ack_data {
|
||||
struct iwl_sap_hdr hdr;
|
||||
__le32 version;
|
||||
__le32 status;
|
||||
} __packed;
|
||||
|
||||
#endif /* __sap_h__ */
|
||||
|
@ -7,6 +7,7 @@ iwlmvm-y += power.o coex.o
|
||||
iwlmvm-y += tt.o offloading.o tdls.o
|
||||
iwlmvm-y += ftm-responder.o ftm-initiator.o
|
||||
iwlmvm-y += rfi.o
|
||||
iwlmvm-y += mld-key.o
|
||||
iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
|
||||
iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o
|
||||
iwlmvm-$(CONFIG_PM) += d3.o
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@ -1248,7 +1248,7 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
|
||||
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
info = IEEE80211_SKB_CB(beacon);
|
||||
rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif);
|
||||
rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif);
|
||||
|
||||
beacon_cmd.flags =
|
||||
cpu_to_le16(iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw, rate));
|
||||
|
@ -404,6 +404,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
iwl_mei_alive_notif(!ret);
|
||||
|
||||
ret = iwl_pnvm_load(mvm->trans, &mvm->notif_wait);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Timeout waiting for PNVM load!\n");
|
||||
@ -1456,6 +1458,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
||||
struct ieee80211_channel *chan;
|
||||
struct cfg80211_chan_def chandef;
|
||||
struct ieee80211_supported_band *sband = NULL;
|
||||
u32 sb_cfg;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
@ -1463,6 +1466,10 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
sb_cfg = iwl_read_umac_prph(mvm->trans, SB_MODIFY_CFG_FLAG);
|
||||
if (!(sb_cfg & SB_CFG_RESIDES_IN_OTP_MASK) && iwl_mei_pldr_req())
|
||||
return ret;
|
||||
|
||||
ret = iwl_mvm_load_rt_fw(mvm);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
|
||||
@ -1665,6 +1672,8 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
||||
iwl_rfi_send_config_cmd(mvm, NULL);
|
||||
}
|
||||
|
||||
iwl_mvm_mei_device_state(mvm, true);
|
||||
|
||||
IWL_DEBUG_INFO(mvm, "RT uCode started.\n");
|
||||
return 0;
|
||||
error:
|
||||
|
@ -788,14 +788,40 @@ static u32 iwl_mvm_find_ie_offset(u8 *beacon, u8 eid, u32 frame_size)
|
||||
return ie - beacon;
|
||||
}
|
||||
|
||||
u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,
|
||||
struct ieee80211_vif *vif)
|
||||
static u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm,
|
||||
struct ieee80211_tx_info *info,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
unsigned long basic = vif->bss_conf.basic_rates;
|
||||
u16 lowest_cck = IWL_RATE_COUNT, lowest_ofdm = IWL_RATE_COUNT;
|
||||
u8 rate;
|
||||
if (info->band == NL80211_BAND_2GHZ && !vif->p2p)
|
||||
rate = IWL_FIRST_CCK_RATE;
|
||||
else
|
||||
rate = IWL_FIRST_OFDM_RATE;
|
||||
u32 i;
|
||||
|
||||
sband = mvm->hw->wiphy->bands[info->band];
|
||||
for_each_set_bit(i, &basic, BITS_PER_LONG) {
|
||||
u16 hw = sband->bitrates[i].hw_value;
|
||||
|
||||
if (hw >= IWL_FIRST_OFDM_RATE) {
|
||||
if (lowest_ofdm > hw)
|
||||
lowest_ofdm = hw;
|
||||
} else if (lowest_cck > hw) {
|
||||
lowest_cck = hw;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->band == NL80211_BAND_2GHZ && !vif->p2p) {
|
||||
if (lowest_cck != IWL_RATE_COUNT)
|
||||
rate = lowest_cck;
|
||||
else if (lowest_ofdm != IWL_RATE_COUNT)
|
||||
rate = lowest_ofdm;
|
||||
else
|
||||
rate = IWL_RATE_1M_INDEX;
|
||||
} else if (lowest_ofdm != IWL_RATE_COUNT) {
|
||||
rate = lowest_ofdm;
|
||||
} else {
|
||||
rate = IWL_RATE_6M_INDEX;
|
||||
}
|
||||
|
||||
return rate;
|
||||
}
|
||||
@ -812,6 +838,24 @@ u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx)
|
||||
return flags;
|
||||
}
|
||||
|
||||
u8 iwl_mvm_mac_ctxt_get_beacon_rate(struct iwl_mvm *mvm,
|
||||
struct ieee80211_tx_info *info,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_supported_band *sband =
|
||||
mvm->hw->wiphy->bands[info->band];
|
||||
u32 legacy = vif->bss_conf.beacon_tx_rate.control[info->band].legacy;
|
||||
|
||||
/* if beacon rate was configured try using it */
|
||||
if (hweight32(legacy) == 1) {
|
||||
u32 rate = ffs(legacy) - 1;
|
||||
|
||||
return sband->bitrates[rate].hw_value;
|
||||
}
|
||||
|
||||
return iwl_mvm_mac_ctxt_get_lowest_rate(mvm, info, vif);
|
||||
}
|
||||
|
||||
static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct sk_buff *beacon,
|
||||
@ -842,7 +886,7 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
|
||||
cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) <<
|
||||
RATE_MCS_ANT_POS);
|
||||
|
||||
rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif);
|
||||
rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif);
|
||||
|
||||
tx->rate_n_flags |=
|
||||
cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate));
|
||||
@ -926,7 +970,7 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(beacon);
|
||||
struct iwl_mac_beacon_cmd beacon_cmd = {};
|
||||
u8 rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif);
|
||||
u8 rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif);
|
||||
u16 flags;
|
||||
struct ieee80211_chanctx_conf *ctx;
|
||||
int channel;
|
||||
|
@ -374,6 +374,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||
hw->wiphy->n_cipher_suites++;
|
||||
}
|
||||
|
||||
wiphy_ext_feature_set(hw->wiphy,
|
||||
NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
|
||||
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_FTM_CALIBRATED)) {
|
||||
wiphy_ext_feature_set(hw->wiphy,
|
||||
@ -2306,6 +2309,9 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
||||
*/
|
||||
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
|
||||
&mvm->status)) {
|
||||
/* first remove remaining keys */
|
||||
iwl_mvm_sec_key_remove_ap(mvm, vif);
|
||||
|
||||
/*
|
||||
* Remove AP station now that
|
||||
* the MAC is unassoc
|
||||
@ -3059,6 +3065,9 @@ static void iwl_mvm_mei_host_associated(struct iwl_mvm *mvm,
|
||||
return;
|
||||
|
||||
switch (mvm_sta->pairwise_cipher) {
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
conn_info.pairwise_cipher = IWL_MEI_CIPHER_TKIP;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
conn_info.pairwise_cipher = IWL_MEI_CIPHER_CCMP;
|
||||
break;
|
||||
@ -3461,6 +3470,8 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
||||
struct iwl_mvm_sta *mvmsta = NULL;
|
||||
struct iwl_mvm_key_pn *ptk_pn;
|
||||
int keyidx = key->keyidx;
|
||||
u32 sec_key_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
|
||||
u8 sec_key_ver = iwl_fw_lookup_cmd_ver(mvm->fw, sec_key_id, 0);
|
||||
int ret, i;
|
||||
u8 key_offset;
|
||||
|
||||
@ -3600,7 +3611,12 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
||||
mvmsta->pairwise_cipher = key->cipher;
|
||||
|
||||
IWL_DEBUG_MAC80211(mvm, "set hwcrypto key\n");
|
||||
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, key_offset);
|
||||
|
||||
if (sec_key_ver)
|
||||
ret = iwl_mvm_sec_key_add(mvm, vif, sta, key);
|
||||
else
|
||||
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, key_offset);
|
||||
|
||||
if (ret) {
|
||||
IWL_WARN(mvm, "set key failed\n");
|
||||
key->hw_key_idx = STA_KEY_IDX_INVALID;
|
||||
@ -3653,7 +3669,10 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
IWL_DEBUG_MAC80211(mvm, "disable hwcrypto key\n");
|
||||
ret = iwl_mvm_remove_sta_key(mvm, vif, sta, key);
|
||||
if (sec_key_ver)
|
||||
ret = iwl_mvm_sec_key_del(mvm, vif, sta, key);
|
||||
else
|
||||
ret = iwl_mvm_remove_sta_key(mvm, vif, sta, key);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
226
drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
Normal file
226
drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
Normal file
@ -0,0 +1,226 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2022 Intel Corporation
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <net/mac80211.h>
|
||||
#include "mvm.h"
|
||||
#include "fw/api/context.h"
|
||||
#include "fw/api/datapath.h"
|
||||
|
||||
static u32 iwl_mvm_get_sec_sta_mask(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *keyconf)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP &&
|
||||
!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
|
||||
return BIT(mvmvif->mcast_sta.sta_id);
|
||||
|
||||
if (sta) {
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
|
||||
return BIT(mvmsta->sta_id);
|
||||
}
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION &&
|
||||
mvmvif->ap_sta_id != IWL_MVM_INVALID_STA)
|
||||
return BIT(mvmvif->ap_sta_id);
|
||||
|
||||
/* invalid */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *keyconf)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
u32 flags = 0;
|
||||
|
||||
if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
|
||||
flags |= IWL_SEC_KEY_FLAG_MCAST_KEY;
|
||||
|
||||
switch (keyconf->cipher) {
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
flags |= IWL_SEC_KEY_FLAG_KEY_SIZE;
|
||||
fallthrough;
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
flags |= IWL_SEC_KEY_FLAG_CIPHER_WEP;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
flags |= IWL_SEC_KEY_FLAG_CIPHER_TKIP;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
flags |= IWL_SEC_KEY_FLAG_CIPHER_CCMP;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
|
||||
flags |= IWL_SEC_KEY_FLAG_KEY_SIZE;
|
||||
fallthrough;
|
||||
case WLAN_CIPHER_SUITE_GCMP:
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
||||
flags |= IWL_SEC_KEY_FLAG_CIPHER_GCMP;
|
||||
break;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
if (!sta && vif->type == NL80211_IFTYPE_STATION &&
|
||||
mvmvif->ap_sta_id != IWL_MVM_INVALID_STA) {
|
||||
u8 sta_id = mvmvif->ap_sta_id;
|
||||
|
||||
sta = rcu_dereference_check(mvm->fw_id_to_mac_id[sta_id],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
}
|
||||
|
||||
if (!IS_ERR_OR_NULL(sta) && sta->mfp)
|
||||
flags |= IWL_SEC_KEY_FLAG_MFP;
|
||||
rcu_read_unlock();
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static int __iwl_mvm_sec_key_del(struct iwl_mvm *mvm, u32 sta_mask,
|
||||
u32 key_flags, u32 keyidx, u32 flags)
|
||||
{
|
||||
u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
|
||||
struct iwl_sec_key_cmd cmd = {
|
||||
.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
|
||||
.u.remove.sta_mask = cpu_to_le32(sta_mask),
|
||||
.u.remove.key_id = cpu_to_le32(keyidx),
|
||||
.u.remove.key_flags = cpu_to_le32(key_flags),
|
||||
};
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, cmd_id, flags, sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
int iwl_mvm_sec_key_add(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *keyconf)
|
||||
{
|
||||
u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf);
|
||||
u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf);
|
||||
u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
|
||||
struct iwl_sec_key_cmd cmd = {
|
||||
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
|
||||
.u.add.sta_mask = cpu_to_le32(sta_mask),
|
||||
.u.add.key_id = cpu_to_le32(keyconf->keyidx),
|
||||
.u.add.key_flags = cpu_to_le32(key_flags),
|
||||
.u.add.tx_seq = cpu_to_le64(atomic64_read(&keyconf->tx_pn)),
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(keyconf->keylen > sizeof(cmd.u.add.key)))
|
||||
return -EINVAL;
|
||||
|
||||
if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
|
||||
keyconf->cipher == WLAN_CIPHER_SUITE_WEP104)
|
||||
memcpy(cmd.u.add.key + IWL_SEC_WEP_KEY_OFFSET, keyconf->key,
|
||||
keyconf->keylen);
|
||||
else
|
||||
memcpy(cmd.u.add.key, keyconf->key, keyconf->keylen);
|
||||
|
||||
if (keyconf->cipher == WLAN_CIPHER_SUITE_TKIP) {
|
||||
memcpy(cmd.u.add.tkip_mic_rx_key,
|
||||
keyconf->key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
|
||||
8);
|
||||
memcpy(cmd.u.add.tkip_mic_tx_key,
|
||||
keyconf->key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY,
|
||||
8);
|
||||
}
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* For WEP, the same key is used for multicast and unicast so need to
|
||||
* upload it again. If this fails, remove the original as well.
|
||||
*/
|
||||
if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
|
||||
keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) {
|
||||
cmd.u.add.key_flags ^= cpu_to_le32(IWL_SEC_KEY_FLAG_MCAST_KEY);
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd);
|
||||
if (ret)
|
||||
__iwl_mvm_sec_key_del(mvm, sta_mask, key_flags,
|
||||
keyconf->keyidx, 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _iwl_mvm_sec_key_del(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
u32 flags)
|
||||
{
|
||||
u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf);
|
||||
u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf);
|
||||
int ret;
|
||||
|
||||
ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, keyconf->keyidx,
|
||||
flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* For WEP, delete the key again as unicast */
|
||||
if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
|
||||
keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) {
|
||||
key_flags ^= IWL_SEC_KEY_FLAG_MCAST_KEY;
|
||||
ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags,
|
||||
keyconf->keyidx, flags);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mvm_sec_key_del(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *keyconf)
|
||||
{
|
||||
return _iwl_mvm_sec_key_del(mvm, vif, sta, keyconf, 0);
|
||||
}
|
||||
|
||||
static void iwl_mvm_sec_key_remove_ap_iter(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key,
|
||||
void *data)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
|
||||
if (key->hw_key_idx == STA_KEY_IDX_INVALID)
|
||||
return;
|
||||
|
||||
if (sta)
|
||||
return;
|
||||
|
||||
_iwl_mvm_sec_key_del(mvm, vif, NULL, key, CMD_ASYNC);
|
||||
key->hw_key_idx = STA_KEY_IDX_INVALID;
|
||||
}
|
||||
|
||||
void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
u32 sec_key_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
|
||||
u8 sec_key_ver = iwl_fw_lookup_cmd_ver(mvm->fw, sec_key_id, 0);
|
||||
|
||||
if (WARN_ON(vif->type != NL80211_IFTYPE_STATION ||
|
||||
mvmvif->ap_sta_id == IWL_MVM_INVALID_STA))
|
||||
return;
|
||||
|
||||
if (!sec_key_ver)
|
||||
return;
|
||||
|
||||
ieee80211_iter_keys_rcu(mvm->hw, vif,
|
||||
iwl_mvm_sec_key_remove_ap_iter,
|
||||
NULL);
|
||||
}
|
@ -1644,7 +1644,8 @@ int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
|
||||
int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
|
||||
struct sk_buff *beacon,
|
||||
void *data, int len);
|
||||
u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,
|
||||
u8 iwl_mvm_mac_ctxt_get_beacon_rate(struct iwl_mvm *mvm,
|
||||
struct ieee80211_tx_info *info,
|
||||
struct ieee80211_vif *vif);
|
||||
u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw,
|
||||
u8 rate_idx);
|
||||
@ -2079,6 +2080,18 @@ void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw,
|
||||
struct dentry *dir);
|
||||
#endif
|
||||
|
||||
/* new MLD related APIs */
|
||||
int iwl_mvm_sec_key_add(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *keyconf);
|
||||
int iwl_mvm_sec_key_del(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *keyconf);
|
||||
void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif);
|
||||
|
||||
int iwl_rfi_send_config_cmd(struct iwl_mvm *mvm,
|
||||
struct iwl_rfi_lut_entry *rfi_table);
|
||||
struct iwl_rfi_freq_table_resp_cmd *iwl_rfi_get_freq_table(struct iwl_mvm *mvm);
|
||||
@ -2201,10 +2214,10 @@ static inline void iwl_mvm_mei_host_disassociated(struct iwl_mvm *mvm)
|
||||
iwl_mei_host_disassociated();
|
||||
}
|
||||
|
||||
static inline void iwl_mvm_mei_device_down(struct iwl_mvm *mvm)
|
||||
static inline void iwl_mvm_mei_device_state(struct iwl_mvm *mvm, bool up)
|
||||
{
|
||||
if (mvm->mei_registered)
|
||||
iwl_mei_device_down();
|
||||
iwl_mei_device_state(up);
|
||||
}
|
||||
|
||||
static inline void iwl_mvm_mei_set_sw_rfkill_state(struct iwl_mvm *mvm)
|
||||
|
@ -547,6 +547,7 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
|
||||
HCMD_NAME(TLC_MNG_CONFIG_CMD),
|
||||
HCMD_NAME(CHEST_COLLECTOR_FILTER_CONFIG_CMD),
|
||||
HCMD_NAME(SCD_QUEUE_CONFIG_CMD),
|
||||
HCMD_NAME(SEC_KEY_CMD),
|
||||
HCMD_NAME(MONITOR_NOTIF),
|
||||
HCMD_NAME(THERMAL_DUAL_CHAIN_REQUEST),
|
||||
HCMD_NAME(STA_PM_NOTIF),
|
||||
@ -1375,7 +1376,7 @@ void iwl_mvm_stop_device(struct iwl_mvm *mvm)
|
||||
iwl_trans_stop_device(mvm->trans);
|
||||
iwl_free_fw_paging(&mvm->fwrt);
|
||||
iwl_fw_dump_conf_clear(&mvm->fwrt);
|
||||
iwl_mvm_mei_device_down(mvm);
|
||||
iwl_mvm_mei_device_state(mvm, false);
|
||||
}
|
||||
|
||||
static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
|
||||
|
@ -1747,10 +1747,12 @@ static void iwl_mvm_rx_fill_status(struct iwl_mvm *mvm,
|
||||
|
||||
rx_status->rate_idx = rate;
|
||||
|
||||
if (WARN_ONCE(rate < 0 || rate > 0xFF,
|
||||
"Invalid rate flags 0x%x, band %d,\n",
|
||||
rate_n_flags, rx_status->band))
|
||||
if ((rate < 0 || rate > 0xFF) && net_ratelimit()) {
|
||||
IWL_ERR(mvm, "Invalid rate flags 0x%x, band %d,\n",
|
||||
rate_n_flags, rx_status->band);
|
||||
rx_status->rate_idx = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1954,6 +1954,9 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
||||
if (vif->cfg.assoc)
|
||||
return ret;
|
||||
|
||||
/* first remove remaining keys */
|
||||
iwl_mvm_sec_key_remove_ap(mvm, vif);
|
||||
|
||||
/* unassoc - go ahead - remove the AP STA now */
|
||||
mvmvif->ap_sta_id = IWL_MVM_INVALID_STA;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@ -183,7 +183,10 @@ static u32 iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
struct ieee80211_tx_info *info,
|
||||
bool amsdu)
|
||||
{
|
||||
if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
|
||||
if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ ||
|
||||
(mvm->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_BZ &&
|
||||
CSR_HW_REV_TYPE(mvm->trans->hw_rev) == IWL_CFG_MAC_TYPE_GL &&
|
||||
mvm->trans->hw_rev_step == SILICON_A_STEP))
|
||||
return iwl_mvm_tx_csum_pre_bz(mvm, skb, info, amsdu);
|
||||
return iwl_mvm_tx_csum_bz(mvm, skb, amsdu);
|
||||
}
|
||||
@ -1171,9 +1174,15 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
/* From now on, we cannot access info->control */
|
||||
iwl_mvm_skb_prepare_status(skb, dev_cmd);
|
||||
|
||||
/*
|
||||
* The IV is introduced by the HW for new tx api, and it is not present
|
||||
* in the skb, hence, don't tell iwl_mvm_mei_tx_copy_to_csme about the
|
||||
* IV for those devices.
|
||||
*/
|
||||
if (ieee80211_is_data(fc))
|
||||
iwl_mvm_mei_tx_copy_to_csme(mvm, skb,
|
||||
info->control.hw_key ?
|
||||
info->control.hw_key &&
|
||||
!iwl_mvm_has_new_tx_api(mvm) ?
|
||||
info->control.hw_key->iv_len : 0);
|
||||
|
||||
if (iwl_trans_tx(mvm->trans, skb, dev_cmd, txq_id))
|
||||
|
Loading…
x
Reference in New Issue
Block a user