mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 18:21:24 +02:00
iwlwifi features, notably:
- PNVM integrated in the ucode image - more cleanups in the transport layer -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQQM3A3Pv7vbm9vtjWbacY7uyt+OfQUCaG4v0AAKCRDacY7uyt+O fTaDAQCOJRC01eAL57AzxOf/YvT9zrN2dDR0NoBPqcfHmgJfWAEA4qEaqz9T5SPC ELoOuCYk3YibwIgZFeqQmy4VQaIl2g4= =/7vB -----END PGP SIGNATURE----- Merge tag 'iwlwifi-next-2025-07-09' of https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next Miri Korenblit says: ==================== iwlwifi features, notably: - PNVM integrated in the ucode image - more cleanups in the transport layer ==================== Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
commit
c8c5e97da9
|
|
@ -10,10 +10,10 @@
|
|||
#include "fw/api/txq.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_BZ_UCODE_API_MAX 99
|
||||
#define IWL_BZ_UCODE_API_MAX 102
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_BZ_UCODE_API_MIN 94
|
||||
#define IWL_BZ_UCODE_API_MIN 98
|
||||
|
||||
/* Memory offsets and lengths */
|
||||
#define IWL_BZ_SMEM_OFFSET 0x400000
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include "fw/api/txq.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_DR_UCODE_API_MAX 99
|
||||
#define IWL_DR_UCODE_API_MAX 102
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_DR_UCODE_API_MIN 98
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include "fw/api/txq.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_SC_UCODE_API_MAX 99
|
||||
#define IWL_SC_UCODE_API_MAX 102
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_SC_UCODE_API_MIN 98
|
||||
|
|
|
|||
|
|
@ -676,10 +676,9 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_trans *trans)
|
|||
CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM);
|
||||
|
||||
/* See if we got it */
|
||||
ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM,
|
||||
CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM,
|
||||
IWL_EEPROM_SEM_TIMEOUT);
|
||||
ret = iwl_poll_bits(trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM,
|
||||
IWL_EEPROM_SEM_TIMEOUT);
|
||||
if (ret >= 0) {
|
||||
IWL_DEBUG_EEPROM(trans->dev,
|
||||
"Acquired semaphore after %d tries.\n",
|
||||
|
|
@ -797,10 +796,9 @@ static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr,
|
|||
|
||||
iwl_write32(trans, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
|
||||
ret = iwl_poll_bit(trans, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
IWL_EEPROM_ACCESS_TIMEOUT);
|
||||
ret = iwl_poll_bits(trans, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
IWL_EEPROM_ACCESS_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
IWL_ERR(trans, "Time out reading OTP[%d]\n", addr);
|
||||
return ret;
|
||||
|
|
@ -993,10 +991,9 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size)
|
|||
iwl_write32(trans, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
|
||||
|
||||
ret = iwl_poll_bit(trans, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
IWL_EEPROM_ACCESS_TIMEOUT);
|
||||
ret = iwl_poll_bits(trans, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
IWL_EEPROM_ACCESS_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
IWL_ERR(trans,
|
||||
"Time out reading EEPROM[%d]\n", addr);
|
||||
|
|
|
|||
|
|
@ -1467,7 +1467,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
|||
/********************
|
||||
* 6. Setup services
|
||||
********************/
|
||||
if (iwl_setup_deferred_work(priv))
|
||||
err = iwl_setup_deferred_work(priv);
|
||||
if (err)
|
||||
goto out_uninit_drv;
|
||||
|
||||
iwl_setup_rx_handlers(priv);
|
||||
|
|
|
|||
|
|
@ -912,7 +912,7 @@ struct iwl_wowlan_mlo_gtk {
|
|||
} __packed; /* WOWLAN_MLO_GTK_KEY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_info_notif_v4 - WoWLAN information notification
|
||||
* struct iwl_wowlan_info_notif_v3 - WoWLAN information notification
|
||||
* @gtk: GTK data
|
||||
* @igtk: IGTK data
|
||||
* @bigtk: BIGTK data
|
||||
|
|
@ -927,12 +927,9 @@ struct iwl_wowlan_mlo_gtk {
|
|||
* @tid_tear_down: bit mask of tids whose BA sessions were closed
|
||||
* in suspend state
|
||||
* @station_id: station id
|
||||
* @num_mlo_link_keys: number of &struct iwl_wowlan_mlo_gtk structs
|
||||
* following this notif, or reserved in version < 4
|
||||
* @reserved2: reserved
|
||||
* @mlo_gtks: array of GTKs of size num_mlo_link_keys for version >= 4
|
||||
*/
|
||||
struct iwl_wowlan_info_notif_v4 {
|
||||
struct iwl_wowlan_info_notif_v3 {
|
||||
struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
|
||||
struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
|
||||
struct iwl_wowlan_igtk_status bigtk[WOWLAN_BIGTK_KEYS_NUM];
|
||||
|
|
@ -946,10 +943,8 @@ struct iwl_wowlan_info_notif_v4 {
|
|||
__le32 received_beacons;
|
||||
u8 tid_tear_down;
|
||||
u8 station_id;
|
||||
u8 num_mlo_link_keys;
|
||||
u8 reserved2;
|
||||
struct iwl_wowlan_mlo_gtk mlo_gtks[];
|
||||
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_3, _VER_4 */
|
||||
u8 reserved2[2];
|
||||
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_info_notif - WoWLAN information notification
|
||||
|
|
|
|||
|
|
@ -104,6 +104,9 @@ enum iwl_ucode_tlv_type {
|
|||
IWL_UCODE_TLV_CURRENT_PC = 68,
|
||||
IWL_UCODE_TLV_FSEQ_BIN_VERSION = 72,
|
||||
|
||||
/* contains sub-sections like PNVM file does (did) */
|
||||
IWL_UCODE_TLV_PNVM_DATA = 74,
|
||||
|
||||
IWL_UCODE_TLV_FW_NUM_STATIONS = IWL_UCODE_TLV_CONST_BASE + 0,
|
||||
IWL_UCODE_TLV_FW_NUM_LINKS = IWL_UCODE_TLV_CONST_BASE + 1,
|
||||
IWL_UCODE_TLV_FW_NUM_BEACONS = IWL_UCODE_TLV_CONST_BASE + 2,
|
||||
|
|
|
|||
|
|
@ -195,6 +195,8 @@ struct iwl_dump_exclude {
|
|||
* @phy_integration_ver_len: length of @phy_integration_ver
|
||||
* @dump_excl: image dump exclusion areas for RT image
|
||||
* @dump_excl_wowlan: image dump exclusion areas for WoWLAN image
|
||||
* @pnvm_data: PNVM data embedded in the .ucode file, if any
|
||||
* @pnvm_size: size of the embedded PNVM data
|
||||
*/
|
||||
struct iwl_fw {
|
||||
u32 ucode_ver;
|
||||
|
|
@ -227,6 +229,9 @@ struct iwl_fw {
|
|||
u32 phy_integration_ver_len;
|
||||
|
||||
struct iwl_dump_exclude dump_excl[2], dump_excl_wowlan[2];
|
||||
|
||||
const void *pnvm_data;
|
||||
u32 pnvm_size;
|
||||
};
|
||||
|
||||
static inline const char *get_fw_dbg_mode_string(int mode)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "fw/api/nvm-reg.h"
|
||||
#include "fw/api/alive.h"
|
||||
#include "fw/uefi.h"
|
||||
#include "fw/img.h"
|
||||
|
||||
#define IWL_PNVM_REDUCED_CAP_BIT BIT(25)
|
||||
|
||||
|
|
@ -264,8 +265,8 @@ static int iwl_pnvm_get_from_fs(struct iwl_trans *trans, u8 **data, size_t *len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len,
|
||||
__le32 sku_id[3])
|
||||
static const u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len,
|
||||
__le32 sku_id[3], const struct iwl_fw *fw)
|
||||
{
|
||||
struct pnvm_sku_package *package;
|
||||
u8 *image = NULL;
|
||||
|
|
@ -290,6 +291,12 @@ static u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len,
|
|||
}
|
||||
}
|
||||
|
||||
if (fw->pnvm_data) {
|
||||
*len = fw->pnvm_size;
|
||||
|
||||
return fw->pnvm_data;
|
||||
}
|
||||
|
||||
/* If it's not available, or for Intel SKU, try from the filesystem */
|
||||
if (iwl_pnvm_get_from_fs(trans_p, &image, len))
|
||||
return NULL;
|
||||
|
|
@ -298,11 +305,11 @@ static u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len,
|
|||
|
||||
static void
|
||||
iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans,
|
||||
const struct iwl_ucode_capabilities *capa,
|
||||
const struct iwl_fw *fw,
|
||||
__le32 sku_id[3])
|
||||
{
|
||||
struct iwl_pnvm_image *pnvm_data = NULL;
|
||||
u8 *data = NULL;
|
||||
const u8 *data = NULL;
|
||||
size_t length;
|
||||
int ret;
|
||||
|
||||
|
|
@ -313,7 +320,7 @@ iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans,
|
|||
if (trans->pnvm_loaded)
|
||||
goto set;
|
||||
|
||||
data = iwl_get_pnvm_image(trans, &length, sku_id);
|
||||
data = iwl_get_pnvm_image(trans, &length, sku_id, fw);
|
||||
if (!data) {
|
||||
trans->fail_to_parse_pnvm_image = true;
|
||||
return;
|
||||
|
|
@ -329,15 +336,17 @@ iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans,
|
|||
goto free;
|
||||
}
|
||||
|
||||
ret = iwl_trans_load_pnvm(trans, pnvm_data, capa);
|
||||
ret = iwl_trans_load_pnvm(trans, pnvm_data, &fw->ucode_capa);
|
||||
if (ret)
|
||||
goto free;
|
||||
IWL_DEBUG_INFO(trans, "loaded PNVM version %08x\n", pnvm_data->version);
|
||||
|
||||
set:
|
||||
iwl_trans_set_pnvm(trans, capa);
|
||||
iwl_trans_set_pnvm(trans, &fw->ucode_capa);
|
||||
free:
|
||||
kvfree(data);
|
||||
/* free only if it was allocated, i.e. not just embedded PNVM data */
|
||||
if (data != fw->pnvm_data)
|
||||
kvfree(data);
|
||||
kfree(pnvm_data);
|
||||
}
|
||||
|
||||
|
|
@ -392,8 +401,7 @@ iwl_pnvm_load_reduce_power_to_trans(struct iwl_trans *trans,
|
|||
|
||||
int iwl_pnvm_load(struct iwl_trans *trans,
|
||||
struct iwl_notif_wait_data *notif_wait,
|
||||
const struct iwl_ucode_capabilities *capa,
|
||||
__le32 sku_id[3])
|
||||
const struct iwl_fw *fw, __le32 sku_id[3])
|
||||
{
|
||||
struct iwl_notification_wait pnvm_wait;
|
||||
static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP,
|
||||
|
|
@ -403,8 +411,8 @@ int iwl_pnvm_load(struct iwl_trans *trans,
|
|||
if (!sku_id[0] && !sku_id[1] && !sku_id[2])
|
||||
return 0;
|
||||
|
||||
iwl_pnvm_load_pnvm_to_trans(trans, capa, sku_id);
|
||||
iwl_pnvm_load_reduce_power_to_trans(trans, capa, sku_id);
|
||||
iwl_pnvm_load_pnvm_to_trans(trans, fw, sku_id);
|
||||
iwl_pnvm_load_reduce_power_to_trans(trans, &fw->ucode_capa, sku_id);
|
||||
|
||||
iwl_init_notification_wait(notif_wait, &pnvm_wait,
|
||||
ntf_cmds, ARRAY_SIZE(ntf_cmds),
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "iwl-drv.h"
|
||||
#include "fw/notif-wait.h"
|
||||
#include "fw/img.h"
|
||||
|
||||
#define MVM_UCODE_PNVM_TIMEOUT (HZ / 4)
|
||||
|
||||
|
|
@ -14,8 +15,7 @@
|
|||
|
||||
int iwl_pnvm_load(struct iwl_trans *trans,
|
||||
struct iwl_notif_wait_data *notif_wait,
|
||||
const struct iwl_ucode_capabilities *capa,
|
||||
__le32 sku_id[3]);
|
||||
const struct iwl_fw *fw, __le32 sku_id[3]);
|
||||
|
||||
static inline
|
||||
void iwl_pnvm_get_fs_name(struct iwl_trans *trans,
|
||||
|
|
|
|||
|
|
@ -488,8 +488,8 @@ struct iwl_dev_info {
|
|||
rf_type:9,
|
||||
match_bw_limit:1,
|
||||
bw_limit:1,
|
||||
match_rf_step:1,
|
||||
rf_step:4,
|
||||
match_discrete:1,
|
||||
discrete:1,
|
||||
match_rf_id:1,
|
||||
rf_id:4,
|
||||
match_cdb:1,
|
||||
|
|
@ -499,12 +499,13 @@ struct iwl_dev_info {
|
|||
#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS)
|
||||
extern const struct iwl_dev_info iwl_dev_info_table[];
|
||||
extern const unsigned int iwl_dev_info_table_size;
|
||||
const struct iwl_dev_info *
|
||||
iwl_pci_find_dev_info(u16 device, u16 subsystem_device, u16 rf_type, u8 cdb,
|
||||
u8 rf_id, u8 bw_limit, u8 rf_step);
|
||||
extern const struct pci_device_id iwl_hw_card_ids[];
|
||||
#endif
|
||||
|
||||
const struct iwl_dev_info *
|
||||
iwl_pci_find_dev_info(u16 device, u16 subsystem_device, u16 rf_type, u8 cdb,
|
||||
u8 rf_id, u8 bw_limit, bool discrete);
|
||||
|
||||
/*
|
||||
* This list declares the config structures for all devices.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -136,6 +136,9 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv)
|
|||
kfree(drv->fw.phy_integration_ver);
|
||||
kfree(drv->trans->dbg.pc_data);
|
||||
drv->trans->dbg.pc_data = NULL;
|
||||
kvfree(drv->fw.pnvm_data);
|
||||
drv->fw.pnvm_data = NULL;
|
||||
drv->fw.pnvm_size = 0;
|
||||
|
||||
for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
|
||||
iwl_free_fw_img(drv, drv->fw.img + i);
|
||||
|
|
@ -1400,6 +1403,15 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
|||
drv->trans->dbg.num_pc =
|
||||
tlv_len / sizeof(struct iwl_pc_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_PNVM_DATA:
|
||||
if (drv->fw.pnvm_data)
|
||||
break;
|
||||
drv->fw.pnvm_data =
|
||||
kvmemdup(tlv_data, tlv_len, GFP_KERNEL);
|
||||
if (!drv->fw.pnvm_data)
|
||||
return -ENOMEM;
|
||||
drv->fw.pnvm_size = tlv_len;
|
||||
break;
|
||||
default:
|
||||
IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
|
||||
break;
|
||||
|
|
@ -2037,8 +2049,6 @@ static int __init iwl_drv_init(void)
|
|||
for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++)
|
||||
INIT_LIST_HEAD(&iwlwifi_opmode_table[i].drv);
|
||||
|
||||
pr_info(DRV_DESCRIPTION "\n");
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
/* Create the root of iwlwifi debugfs subsystem. */
|
||||
iwl_dbgfs_root = debugfs_create_dir(DRV_NAME, NULL);
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ IWL_EXPORT_SYMBOL(iwl_read32);
|
|||
|
||||
#define IWL_POLL_INTERVAL 10 /* microseconds */
|
||||
|
||||
int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout)
|
||||
int iwl_poll_bits_mask(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout)
|
||||
{
|
||||
int t = 0;
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
|
|||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_poll_bit);
|
||||
IWL_EXPORT_SYMBOL(iwl_poll_bits_mask);
|
||||
|
||||
u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
|
||||
{
|
||||
|
|
@ -477,7 +477,7 @@ int iwl_finish_nic_init(struct iwl_trans *trans)
|
|||
* device-internal resources is supported, e.g. iwl_write_prph()
|
||||
* and accesses to uCode SRAM.
|
||||
*/
|
||||
err = iwl_poll_bit(trans, CSR_GP_CNTRL, poll_ready, poll_ready, 25000);
|
||||
err = iwl_poll_bits(trans, CSR_GP_CNTRL, poll_ready, 25000);
|
||||
if (err < 0) {
|
||||
IWL_DEBUG_INFO(trans, "Failed to wake NIC\n");
|
||||
|
||||
|
|
|
|||
|
|
@ -23,8 +23,13 @@ static inline void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
|||
iwl_trans_set_bits_mask(trans, reg, mask, 0);
|
||||
}
|
||||
|
||||
int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout);
|
||||
int iwl_poll_bits_mask(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout);
|
||||
static inline int iwl_poll_bits(struct iwl_trans *trans, u32 addr, u32 bits,
|
||||
int timeout)
|
||||
{
|
||||
return iwl_poll_bits_mask(trans, addr, bits, bits, timeout);
|
||||
}
|
||||
int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
|
||||
int timeout);
|
||||
|
||||
|
|
|
|||
|
|
@ -268,7 +268,9 @@ static void iwl_trans_restart_wk(struct work_struct *wk)
|
|||
|
||||
struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
|
||||
struct device *dev,
|
||||
const struct iwl_mac_cfg *mac_cfg)
|
||||
const struct iwl_mac_cfg *mac_cfg,
|
||||
unsigned int txcmd_size,
|
||||
unsigned int txcmd_align)
|
||||
{
|
||||
struct iwl_trans *trans;
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
|
|
@ -290,35 +292,6 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
|
|||
|
||||
INIT_DELAYED_WORK(&trans->restart.wk, iwl_trans_restart_wk);
|
||||
|
||||
return trans;
|
||||
}
|
||||
|
||||
int iwl_trans_init(struct iwl_trans *trans)
|
||||
{
|
||||
int txcmd_size, txcmd_align;
|
||||
|
||||
/* check if name/num_rx_queues were set as a proxy for info being set */
|
||||
if (WARN_ON(!trans->info.name || !trans->info.num_rxqs))
|
||||
return -EINVAL;
|
||||
|
||||
if (!trans->mac_cfg->gen2) {
|
||||
txcmd_size = sizeof(struct iwl_tx_cmd_v6);
|
||||
txcmd_align = sizeof(void *);
|
||||
} else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
|
||||
txcmd_size = sizeof(struct iwl_tx_cmd_v9);
|
||||
txcmd_align = 64;
|
||||
} else {
|
||||
txcmd_size = sizeof(struct iwl_tx_cmd);
|
||||
txcmd_align = 128;
|
||||
}
|
||||
|
||||
txcmd_size += sizeof(struct iwl_cmd_header);
|
||||
txcmd_size += 36; /* biggest possible 802.11 header */
|
||||
|
||||
/* Ensure device TX cmd cannot reach/cross a page boundary in gen2 */
|
||||
if (WARN_ON(trans->mac_cfg->gen2 && txcmd_size >= txcmd_align))
|
||||
return -EINVAL;
|
||||
|
||||
snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name),
|
||||
"iwl_cmd_pool:%s", dev_name(trans->dev));
|
||||
trans->dev_cmd_pool =
|
||||
|
|
@ -326,9 +299,9 @@ int iwl_trans_init(struct iwl_trans *trans)
|
|||
txcmd_size, txcmd_align,
|
||||
SLAB_HWCACHE_ALIGN, NULL);
|
||||
if (!trans->dev_cmd_pool)
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
|
||||
return 0;
|
||||
return trans;
|
||||
}
|
||||
|
||||
void iwl_trans_free(struct iwl_trans *trans)
|
||||
|
|
|
|||
|
|
@ -1204,9 +1204,10 @@ static inline void iwl_trans_finish_sw_reset(struct iwl_trans *trans)
|
|||
* transport helper functions
|
||||
*****************************************************/
|
||||
struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
|
||||
struct device *dev,
|
||||
const struct iwl_mac_cfg *cfg_trans);
|
||||
int iwl_trans_init(struct iwl_trans *trans);
|
||||
struct device *dev,
|
||||
const struct iwl_mac_cfg *mac_cfg,
|
||||
unsigned int txcmd_size,
|
||||
unsigned int txcmd_align);
|
||||
void iwl_trans_free(struct iwl_trans *trans);
|
||||
|
||||
static inline bool iwl_trans_is_hw_error_value(u32 val)
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ static int iwl_mld_run_fw_init_sequence(struct iwl_mld *mld)
|
|||
return ret;
|
||||
|
||||
ret = iwl_pnvm_load(mld->trans, &mld->notif_wait,
|
||||
&mld->fw->ucode_capa, alive_data.sku_id);
|
||||
mld->fw, alive_data.sku_id);
|
||||
if (ret) {
|
||||
IWL_ERR(mld, "Timeout waiting for PNVM load %d\n", ret);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -299,18 +299,18 @@ void iwl_mld_ptp_init(struct iwl_mld *mld)
|
|||
PTR_ERR(mld->ptp_data.ptp_clock));
|
||||
mld->ptp_data.ptp_clock = NULL;
|
||||
} else {
|
||||
IWL_INFO(mld, "Registered PHC clock: %s, with index: %d\n",
|
||||
mld->ptp_data.ptp_clock_info.name,
|
||||
ptp_clock_index(mld->ptp_data.ptp_clock));
|
||||
IWL_DEBUG_INFO(mld, "Registered PHC clock: %s, with index: %d\n",
|
||||
mld->ptp_data.ptp_clock_info.name,
|
||||
ptp_clock_index(mld->ptp_data.ptp_clock));
|
||||
}
|
||||
}
|
||||
|
||||
void iwl_mld_ptp_remove(struct iwl_mld *mld)
|
||||
{
|
||||
if (mld->ptp_data.ptp_clock) {
|
||||
IWL_INFO(mld, "Unregistering PHC clock: %s, with index: %d\n",
|
||||
mld->ptp_data.ptp_clock_info.name,
|
||||
ptp_clock_index(mld->ptp_data.ptp_clock));
|
||||
IWL_DEBUG_INFO(mld, "Unregistering PHC clock: %s, with index: %d\n",
|
||||
mld->ptp_data.ptp_clock_info.name,
|
||||
ptp_clock_index(mld->ptp_data.ptp_clock));
|
||||
|
||||
ptp_clock_unregister(mld->ptp_data.ptp_clock);
|
||||
mld->ptp_data.ptp_clock = NULL;
|
||||
|
|
|
|||
|
|
@ -1474,9 +1474,6 @@ struct iwl_wowlan_status_data {
|
|||
struct iwl_multicast_key_data igtk;
|
||||
struct iwl_multicast_key_data bigtk[WOWLAN_BIGTK_KEYS_NUM];
|
||||
|
||||
int num_mlo_keys;
|
||||
struct iwl_wowlan_mlo_gtk mlo_keys[WOWLAN_MAX_MLO_KEYS];
|
||||
|
||||
u8 *wake_packet;
|
||||
};
|
||||
|
||||
|
|
@ -1790,8 +1787,7 @@ static void iwl_mvm_set_key_rx_seq_idx(struct ieee80211_key_conf *key,
|
|||
}
|
||||
|
||||
static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key,
|
||||
struct iwl_wowlan_status_data *status,
|
||||
bool installed)
|
||||
struct iwl_wowlan_status_data *status)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
@ -1815,7 +1811,7 @@ static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key,
|
|||
|
||||
/* handle the case where we didn't, last key only */
|
||||
if (status->gtk_seq[i].key_id == -1 &&
|
||||
(!status->num_of_gtk_rekeys || installed))
|
||||
(!status->num_of_gtk_rekeys))
|
||||
iwl_mvm_set_key_rx_seq_idx(key, status, i);
|
||||
}
|
||||
}
|
||||
|
|
@ -1966,7 +1962,7 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
|
|||
(status->gtk[1].len && keyidx == status->gtk[1].id))) {
|
||||
ieee80211_remove_key(key);
|
||||
} else {
|
||||
iwl_mvm_set_key_rx_seq(key, data->status, false);
|
||||
iwl_mvm_set_key_rx_seq(key, data->status);
|
||||
}
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
||||
|
|
@ -1986,167 +1982,6 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
|
|||
}
|
||||
}
|
||||
|
||||
struct iwl_mvm_d3_mlo_old_keys {
|
||||
u32 cipher[IEEE80211_MLD_MAX_NUM_LINKS][WOWLAN_MLO_GTK_KEY_NUM_TYPES];
|
||||
struct ieee80211_key_conf *key[IEEE80211_MLD_MAX_NUM_LINKS][8];
|
||||
};
|
||||
|
||||
static void iwl_mvm_mlo_key_ciphers(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key,
|
||||
void *data)
|
||||
{
|
||||
struct iwl_mvm_d3_mlo_old_keys *old_keys = data;
|
||||
enum iwl_wowlan_mlo_gtk_type key_type;
|
||||
|
||||
if (key->link_id < 0)
|
||||
return;
|
||||
|
||||
if (WARN_ON(key->link_id >= IEEE80211_MLD_MAX_NUM_LINKS ||
|
||||
key->keyidx >= 8))
|
||||
return;
|
||||
|
||||
if (WARN_ON(old_keys->key[key->link_id][key->keyidx]))
|
||||
return;
|
||||
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
case WLAN_CIPHER_SUITE_GCMP:
|
||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||
key_type = WOWLAN_MLO_GTK_KEY_TYPE_GTK;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
|
||||
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
if (key->keyidx == 4 || key->keyidx == 5) {
|
||||
key_type = WOWLAN_MLO_GTK_KEY_TYPE_IGTK;
|
||||
break;
|
||||
} else if (key->keyidx == 6 || key->keyidx == 7) {
|
||||
key_type = WOWLAN_MLO_GTK_KEY_TYPE_BIGTK;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
default:
|
||||
/* ignore WEP/TKIP or unknown ciphers */
|
||||
return;
|
||||
}
|
||||
|
||||
old_keys->cipher[key->link_id][key_type] = key->cipher;
|
||||
old_keys->key[key->link_id][key->keyidx] = key;
|
||||
}
|
||||
|
||||
static bool iwl_mvm_mlo_gtk_rekey(struct iwl_wowlan_status_data *status,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mvm *mvm)
|
||||
{
|
||||
int i;
|
||||
struct iwl_mvm_d3_mlo_old_keys *old_keys;
|
||||
bool ret = true;
|
||||
|
||||
IWL_DEBUG_WOWLAN(mvm, "Num of MLO Keys: %d\n", status->num_mlo_keys);
|
||||
if (!status->num_mlo_keys)
|
||||
return true;
|
||||
|
||||
old_keys = kzalloc(sizeof(*old_keys), GFP_KERNEL);
|
||||
if (!old_keys)
|
||||
return false;
|
||||
|
||||
/* find the cipher for each mlo key */
|
||||
ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_mlo_key_ciphers, old_keys);
|
||||
|
||||
for (i = 0; i < status->num_mlo_keys; i++) {
|
||||
struct iwl_wowlan_mlo_gtk *mlo_key = &status->mlo_keys[i];
|
||||
struct ieee80211_key_conf *key, *old_key;
|
||||
struct ieee80211_key_seq seq;
|
||||
DEFINE_RAW_FLEX(struct ieee80211_key_conf, conf, key,
|
||||
WOWLAN_KEY_MAX_SIZE);
|
||||
u16 flags = le16_to_cpu(mlo_key->flags);
|
||||
int j, link_id, key_id, key_type;
|
||||
|
||||
link_id = u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_LINK_ID_MSK);
|
||||
key_id = u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_KEY_ID_MSK);
|
||||
key_type = u16_get_bits(flags,
|
||||
WOWLAN_MLO_GTK_FLAG_KEY_TYPE_MSK);
|
||||
|
||||
if (!(vif->valid_links & BIT(link_id)))
|
||||
continue;
|
||||
|
||||
if (WARN_ON(link_id >= IEEE80211_MLD_MAX_NUM_LINKS ||
|
||||
key_id >= 8 ||
|
||||
key_type >= WOWLAN_MLO_GTK_KEY_NUM_TYPES))
|
||||
continue;
|
||||
|
||||
conf->cipher = old_keys->cipher[link_id][key_type];
|
||||
/* WARN_ON? */
|
||||
if (!conf->cipher)
|
||||
continue;
|
||||
|
||||
conf->keylen = 0;
|
||||
switch (conf->cipher) {
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
case WLAN_CIPHER_SUITE_GCMP:
|
||||
conf->keylen = WLAN_KEY_LEN_CCMP;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||
conf->keylen = WLAN_KEY_LEN_GCMP_256;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
||||
conf->keylen = WLAN_KEY_LEN_BIP_GMAC_128;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
|
||||
conf->keylen = WLAN_KEY_LEN_BIP_GMAC_256;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
conf->keylen = WLAN_KEY_LEN_AES_CMAC;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
|
||||
conf->keylen = WLAN_KEY_LEN_BIP_CMAC_256;
|
||||
break;
|
||||
}
|
||||
|
||||
if (WARN_ON(!conf->keylen ||
|
||||
conf->keylen > WOWLAN_KEY_MAX_SIZE))
|
||||
continue;
|
||||
|
||||
memcpy(conf->key, mlo_key->key, conf->keylen);
|
||||
conf->keyidx = key_id;
|
||||
|
||||
old_key = old_keys->key[link_id][key_id];
|
||||
if (old_key) {
|
||||
IWL_DEBUG_WOWLAN(mvm,
|
||||
"Remove MLO key id %d, link id %d\n",
|
||||
key_id, link_id);
|
||||
ieee80211_remove_key(old_key);
|
||||
}
|
||||
|
||||
IWL_DEBUG_WOWLAN(mvm, "Add MLO key id %d, link id %d\n",
|
||||
key_id, link_id);
|
||||
key = ieee80211_gtk_rekey_add(vif, conf, link_id);
|
||||
if (WARN_ON(IS_ERR(key))) {
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* mac80211 expects the pn in big-endian
|
||||
* also note that seq is a union of all cipher types
|
||||
* (ccmp, gcmp, cmac, gmac), and they all have the same
|
||||
* pn field (of length 6) so just copy it to ccmp.pn.
|
||||
*/
|
||||
for (j = 5; j >= 0; j--)
|
||||
seq.ccmp.pn[5 - j] = mlo_key->pn[j];
|
||||
|
||||
/* group keys are non-QoS and use TID 0 */
|
||||
ieee80211_set_key_rx_seq(key, 0, &seq);
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(old_keys);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mvm *mvm, u32 gtk_cipher)
|
||||
|
|
@ -2346,9 +2181,6 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!iwl_mvm_mlo_gtk_rekey(status, vif, mvm))
|
||||
return false;
|
||||
|
||||
ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid,
|
||||
(void *)&replay_ctr, GFP_KERNEL);
|
||||
}
|
||||
|
|
@ -2479,10 +2311,11 @@ static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,
|
|||
struct iwl_wowlan_status_data *status,
|
||||
u32 len)
|
||||
{
|
||||
u32 expected_len = sizeof(*data) +
|
||||
data->num_mlo_link_keys * sizeof(status->mlo_keys[0]);
|
||||
if (IWL_FW_CHECK(mvm, data->num_mlo_link_keys,
|
||||
"MLO is not supported, shouldn't receive MLO keys\n"))
|
||||
return;
|
||||
|
||||
if (len < expected_len) {
|
||||
if (len < sizeof(*data)) {
|
||||
IWL_ERR(mvm, "Invalid WoWLAN info notification!\n");
|
||||
status = NULL;
|
||||
return;
|
||||
|
|
@ -2511,33 +2344,17 @@ static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,
|
|||
le32_to_cpu(data->num_of_gtk_rekeys);
|
||||
status->received_beacons = le32_to_cpu(data->received_beacons);
|
||||
status->tid_tear_down = data->tid_tear_down;
|
||||
|
||||
if (data->num_mlo_link_keys) {
|
||||
status->num_mlo_keys = data->num_mlo_link_keys;
|
||||
if (IWL_FW_CHECK(mvm,
|
||||
status->num_mlo_keys > WOWLAN_MAX_MLO_KEYS,
|
||||
"Too many mlo keys: %d, max %d\n",
|
||||
status->num_mlo_keys, WOWLAN_MAX_MLO_KEYS))
|
||||
status->num_mlo_keys = WOWLAN_MAX_MLO_KEYS;
|
||||
memcpy(status->mlo_keys, data->mlo_gtks,
|
||||
status->num_mlo_keys * sizeof(status->mlo_keys[0]));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_parse_wowlan_info_notif_v4(struct iwl_mvm *mvm,
|
||||
struct iwl_wowlan_info_notif_v4 *data,
|
||||
iwl_mvm_parse_wowlan_info_notif_v3(struct iwl_mvm *mvm,
|
||||
struct iwl_wowlan_info_notif_v3 *data,
|
||||
struct iwl_wowlan_status_data *status,
|
||||
u32 len, bool has_mlo_keys)
|
||||
u32 len)
|
||||
{
|
||||
u32 i;
|
||||
u32 expected_len = sizeof(*data);
|
||||
|
||||
if (has_mlo_keys)
|
||||
expected_len += (data->num_mlo_link_keys *
|
||||
sizeof(status->mlo_keys[0]));
|
||||
|
||||
if (len < expected_len) {
|
||||
if (len < sizeof(*data)) {
|
||||
IWL_ERR(mvm, "Invalid WoWLAN info notification!\n");
|
||||
status = NULL;
|
||||
return;
|
||||
|
|
@ -2560,17 +2377,6 @@ iwl_mvm_parse_wowlan_info_notif_v4(struct iwl_mvm *mvm,
|
|||
le32_to_cpu(data->num_of_gtk_rekeys);
|
||||
status->received_beacons = le32_to_cpu(data->received_beacons);
|
||||
status->tid_tear_down = data->tid_tear_down;
|
||||
|
||||
if (has_mlo_keys && data->num_mlo_link_keys) {
|
||||
status->num_mlo_keys = data->num_mlo_link_keys;
|
||||
if (IWL_FW_CHECK(mvm,
|
||||
status->num_mlo_keys > WOWLAN_MAX_MLO_KEYS,
|
||||
"Too many mlo keys: %d, max %d\n",
|
||||
status->num_mlo_keys, WOWLAN_MAX_MLO_KEYS))
|
||||
status->num_mlo_keys = WOWLAN_MAX_MLO_KEYS;
|
||||
memcpy(status->mlo_keys, data->mlo_gtks,
|
||||
status->num_mlo_keys * sizeof(status->mlo_keys[0]));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -3316,19 +3122,23 @@ static bool iwl_mvm_wait_d3_notif(struct iwl_notif_wait_data *notif_wait,
|
|||
iwl_mvm_parse_wowlan_info_notif_v2(mvm, notif_v2,
|
||||
d3_data->status,
|
||||
len);
|
||||
} else if (wowlan_info_ver < 5) {
|
||||
struct iwl_wowlan_info_notif_v4 *notif =
|
||||
} else if (wowlan_info_ver == 3) {
|
||||
struct iwl_wowlan_info_notif_v3 *notif =
|
||||
(void *)pkt->data;
|
||||
|
||||
iwl_mvm_parse_wowlan_info_notif_v4(mvm, notif,
|
||||
d3_data->status, len,
|
||||
wowlan_info_ver > 3);
|
||||
} else {
|
||||
iwl_mvm_parse_wowlan_info_notif_v3(mvm, notif,
|
||||
d3_data->status, len);
|
||||
} else if (wowlan_info_ver == 5) {
|
||||
struct iwl_wowlan_info_notif *notif =
|
||||
(void *)pkt->data;
|
||||
|
||||
iwl_mvm_parse_wowlan_info_notif(mvm, notif,
|
||||
d3_data->status, len);
|
||||
} else {
|
||||
IWL_FW_CHECK(mvm, 1,
|
||||
"Firmware advertises unknown WoWLAN info notification %d!\n",
|
||||
wowlan_info_ver);
|
||||
return false;
|
||||
}
|
||||
|
||||
d3_data->notif_received |= IWL_D3_NOTIF_WOWLAN_INFO;
|
||||
|
|
|
|||
|
|
@ -432,7 +432,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
|||
iwl_trans_fw_alive(mvm->trans);
|
||||
|
||||
ret = iwl_pnvm_load(mvm->trans, &mvm->notif_wait,
|
||||
&mvm->fw->ucode_capa, alive_data.sku_id);
|
||||
mvm->fw, alive_data.sku_id);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Timeout waiting for PNVM load!\n");
|
||||
iwl_fw_set_current_image(&mvm->fwrt, old_type);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2021 - 2023 Intel Corporation
|
||||
* Copyright (C) 2021 - 2023, 2025 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "mvm.h"
|
||||
|
|
@ -298,9 +298,9 @@ void iwl_mvm_ptp_init(struct iwl_mvm *mvm)
|
|||
PTR_ERR(mvm->ptp_data.ptp_clock));
|
||||
mvm->ptp_data.ptp_clock = NULL;
|
||||
} else if (mvm->ptp_data.ptp_clock) {
|
||||
IWL_INFO(mvm, "Registered PHC clock: %s, with index: %d\n",
|
||||
mvm->ptp_data.ptp_clock_info.name,
|
||||
ptp_clock_index(mvm->ptp_data.ptp_clock));
|
||||
IWL_DEBUG_INFO(mvm, "Registered PHC clock: %s, with index: %d\n",
|
||||
mvm->ptp_data.ptp_clock_info.name,
|
||||
ptp_clock_index(mvm->ptp_data.ptp_clock));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -312,9 +312,9 @@ void iwl_mvm_ptp_init(struct iwl_mvm *mvm)
|
|||
void iwl_mvm_ptp_remove(struct iwl_mvm *mvm)
|
||||
{
|
||||
if (mvm->ptp_data.ptp_clock) {
|
||||
IWL_INFO(mvm, "Unregistering PHC clock: %s, with index: %d\n",
|
||||
mvm->ptp_data.ptp_clock_info.name,
|
||||
ptp_clock_index(mvm->ptp_data.ptp_clock));
|
||||
IWL_DEBUG_INFO(mvm, "Unregistering PHC clock: %s, with index: %d\n",
|
||||
mvm->ptp_data.ptp_clock_info.name,
|
||||
ptp_clock_index(mvm->ptp_data.ptp_clock));
|
||||
|
||||
ptp_clock_unregister(mvm->ptp_data.ptp_clock);
|
||||
mvm->ptp_data.ptp_clock = NULL;
|
||||
|
|
|
|||
|
|
@ -577,8 +577,10 @@ EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_hw_card_ids);
|
|||
.subdevice_m_h = _HIGHEST_BIT(m)
|
||||
#define RF_TYPE(n) .match_rf_type = 1, \
|
||||
.rf_type = IWL_CFG_RF_TYPE_##n
|
||||
#define RF_STEP(n) .match_rf_step = 1, \
|
||||
.rf_step = SILICON_##n##_STEP
|
||||
#define DISCRETE .match_discrete = 1, \
|
||||
.discrete = 1
|
||||
#define INTEGRATED .match_discrete = 1, \
|
||||
.discrete = 0
|
||||
#define RF_ID(n) .match_rf_id = 1, \
|
||||
.rf_id = IWL_CFG_RF_ID_##n
|
||||
#define NO_CDB .match_cdb = 1, .cdb = 0
|
||||
|
|
@ -1032,9 +1034,8 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info iwl_dev_info_table[] = {
|
|||
/* FM RF */
|
||||
IWL_DEV_INFO(iwl_rf_fm, iwl_be201_name, RF_TYPE(FM)),
|
||||
IWL_DEV_INFO(iwl_rf_fm, iwl_be401_name, RF_TYPE(FM), CDB),
|
||||
/* the discrete NICs got the RF B0, it's only for the name anyway */
|
||||
IWL_DEV_INFO(iwl_rf_fm, iwl_be200_name, RF_TYPE(FM),
|
||||
DEVICE(0x272B), RF_STEP(B)),
|
||||
DEVICE(0x272B), DISCRETE),
|
||||
IWL_DEV_INFO(iwl_rf_fm_160mhz, iwl_be202_name,
|
||||
RF_TYPE(FM), BW_LIMITED),
|
||||
|
||||
|
|
@ -1074,149 +1075,12 @@ const unsigned int iwl_dev_info_table_size = ARRAY_SIZE(iwl_dev_info_table);
|
|||
EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_dev_info_table_size);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Read rf id and cdb info from prph register and store it
|
||||
*/
|
||||
static void get_crf_id(struct iwl_trans *iwl_trans,
|
||||
struct iwl_trans_info *info)
|
||||
{
|
||||
u32 sd_reg_ver_addr;
|
||||
u32 hw_wfpm_id;
|
||||
u32 val = 0;
|
||||
u8 step;
|
||||
|
||||
if (iwl_trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
|
||||
sd_reg_ver_addr = SD_REG_VER_GEN2;
|
||||
else
|
||||
sd_reg_ver_addr = SD_REG_VER;
|
||||
|
||||
/* Enable access to peripheral registers */
|
||||
val = iwl_read_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG);
|
||||
val |= WFPM_AUX_CTL_AUX_IF_MAC_OWNER_MSK;
|
||||
iwl_write_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG, val);
|
||||
|
||||
/* Read crf info */
|
||||
info->hw_crf_id = iwl_read_prph_no_grab(iwl_trans, sd_reg_ver_addr);
|
||||
|
||||
/* Read cnv info */
|
||||
info->hw_cnv_id = iwl_read_prph_no_grab(iwl_trans, CNVI_AUX_MISC_CHIP);
|
||||
|
||||
/* For BZ-W, take B step also when A step is indicated */
|
||||
if (CSR_HW_REV_TYPE(info->hw_rev) == IWL_CFG_MAC_TYPE_BZ_W)
|
||||
step = SILICON_B_STEP;
|
||||
|
||||
/* In BZ, the MAC step must be read from the CNVI aux register */
|
||||
if (CSR_HW_REV_TYPE(info->hw_rev) == IWL_CFG_MAC_TYPE_BZ) {
|
||||
step = CNVI_AUX_MISC_CHIP_MAC_STEP(info->hw_cnv_id);
|
||||
|
||||
/* For BZ-U, take B step also when A step is indicated */
|
||||
if ((CNVI_AUX_MISC_CHIP_PROD_TYPE(info->hw_cnv_id) ==
|
||||
CNVI_AUX_MISC_CHIP_PROD_TYPE_BZ_U) &&
|
||||
step == SILICON_A_STEP)
|
||||
step = SILICON_B_STEP;
|
||||
}
|
||||
|
||||
if (CSR_HW_REV_TYPE(info->hw_rev) == IWL_CFG_MAC_TYPE_BZ ||
|
||||
CSR_HW_REV_TYPE(info->hw_rev) == IWL_CFG_MAC_TYPE_BZ_W) {
|
||||
info->hw_rev_step = step;
|
||||
info->hw_rev |= step;
|
||||
}
|
||||
|
||||
/* Read cdb info (also contains the jacket info if needed in the future */
|
||||
hw_wfpm_id = iwl_read_umac_prph_no_grab(iwl_trans, WFPM_OTP_CFG1_ADDR);
|
||||
IWL_INFO(iwl_trans, "Detected crf-id 0x%x, cnv-id 0x%x wfpm id 0x%x\n",
|
||||
info->hw_crf_id, info->hw_cnv_id, hw_wfpm_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* In case that there is no OTP on the NIC, map the rf id and cdb info
|
||||
* from the prph registers.
|
||||
*/
|
||||
static int map_crf_id(struct iwl_trans *iwl_trans,
|
||||
struct iwl_trans_info *info)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 val = info->hw_crf_id;
|
||||
u32 step_id = REG_CRF_ID_STEP(val);
|
||||
u32 slave_id = REG_CRF_ID_SLAVE(val);
|
||||
u32 jacket_id_cnv = REG_CRF_ID_SLAVE(info->hw_cnv_id);
|
||||
u32 hw_wfpm_id = iwl_read_umac_prph_no_grab(iwl_trans,
|
||||
WFPM_OTP_CFG1_ADDR);
|
||||
u32 jacket_id_wfpm = WFPM_OTP_CFG1_IS_JACKET(hw_wfpm_id);
|
||||
u32 cdb_id_wfpm = WFPM_OTP_CFG1_IS_CDB(hw_wfpm_id);
|
||||
|
||||
/* Map between crf id to rf id */
|
||||
switch (REG_CRF_ID_TYPE(val)) {
|
||||
case REG_CRF_ID_TYPE_JF_1:
|
||||
info->hw_rf_id = (IWL_CFG_RF_TYPE_JF1 << 12);
|
||||
break;
|
||||
case REG_CRF_ID_TYPE_JF_2:
|
||||
info->hw_rf_id = (IWL_CFG_RF_TYPE_JF2 << 12);
|
||||
break;
|
||||
case REG_CRF_ID_TYPE_HR_NONE_CDB_1X1:
|
||||
info->hw_rf_id = (IWL_CFG_RF_TYPE_HR1 << 12);
|
||||
break;
|
||||
case REG_CRF_ID_TYPE_HR_NONE_CDB:
|
||||
info->hw_rf_id = (IWL_CFG_RF_TYPE_HR2 << 12);
|
||||
break;
|
||||
case REG_CRF_ID_TYPE_HR_CDB:
|
||||
info->hw_rf_id = (IWL_CFG_RF_TYPE_HR2 << 12);
|
||||
break;
|
||||
case REG_CRF_ID_TYPE_GF:
|
||||
info->hw_rf_id = (IWL_CFG_RF_TYPE_GF << 12);
|
||||
break;
|
||||
case REG_CRF_ID_TYPE_FM:
|
||||
info->hw_rf_id = (IWL_CFG_RF_TYPE_FM << 12);
|
||||
break;
|
||||
case REG_CRF_ID_TYPE_WHP:
|
||||
info->hw_rf_id = (IWL_CFG_RF_TYPE_WH << 12);
|
||||
break;
|
||||
case REG_CRF_ID_TYPE_PE:
|
||||
info->hw_rf_id = (IWL_CFG_RF_TYPE_PE << 12);
|
||||
break;
|
||||
default:
|
||||
ret = -EIO;
|
||||
IWL_ERR(iwl_trans,
|
||||
"Can't find a correct rfid for crf id 0x%x\n",
|
||||
REG_CRF_ID_TYPE(val));
|
||||
goto out;
|
||||
|
||||
}
|
||||
|
||||
/* Set Step-id */
|
||||
info->hw_rf_id |= (step_id << 8);
|
||||
|
||||
/* Set CDB capabilities */
|
||||
if (cdb_id_wfpm || slave_id) {
|
||||
info->hw_rf_id += BIT(28);
|
||||
IWL_INFO(iwl_trans, "Adding cdb to rf id\n");
|
||||
}
|
||||
|
||||
/* Set Jacket capabilities */
|
||||
if (jacket_id_wfpm || jacket_id_cnv) {
|
||||
info->hw_rf_id += BIT(29);
|
||||
IWL_INFO(iwl_trans, "Adding jacket to rf id\n");
|
||||
}
|
||||
|
||||
IWL_INFO(iwl_trans,
|
||||
"Detected rf-type 0x%x step-id 0x%x slave-id 0x%x from crf id 0x%x\n",
|
||||
REG_CRF_ID_TYPE(val), step_id, slave_id, info->hw_rf_id);
|
||||
IWL_INFO(iwl_trans,
|
||||
"Detected cdb-id 0x%x jacket-id 0x%x from wfpm id 0x%x\n",
|
||||
cdb_id_wfpm, jacket_id_wfpm, hw_wfpm_id);
|
||||
IWL_INFO(iwl_trans, "Detected jacket-id 0x%x from cnvi id 0x%x\n",
|
||||
jacket_id_cnv, info->hw_cnv_id);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* PCI registers */
|
||||
#define PCI_CFG_RETRY_TIMEOUT 0x041
|
||||
|
||||
VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info *
|
||||
const struct iwl_dev_info *
|
||||
iwl_pci_find_dev_info(u16 device, u16 subsystem_device, u16 rf_type, u8 cdb,
|
||||
u8 rf_id, u8 bw_limit, u8 rf_step)
|
||||
u8 rf_id, u8 bw_limit, bool discrete)
|
||||
{
|
||||
int num_devices = ARRAY_SIZE(iwl_dev_info_table);
|
||||
int i;
|
||||
|
|
@ -1251,7 +1115,7 @@ iwl_pci_find_dev_info(u16 device, u16 subsystem_device, u16 rf_type, u8 cdb,
|
|||
if (dev_info->match_bw_limit && dev_info->bw_limit != bw_limit)
|
||||
continue;
|
||||
|
||||
if (dev_info->match_rf_step && dev_info->rf_step != rf_step)
|
||||
if (dev_info->match_discrete && dev_info->discrete != discrete)
|
||||
continue;
|
||||
|
||||
return dev_info;
|
||||
|
|
@ -1261,193 +1125,47 @@ iwl_pci_find_dev_info(u16 device, u16 subsystem_device, u16 rf_type, u8 cdb,
|
|||
}
|
||||
EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_pci_find_dev_info);
|
||||
|
||||
static void iwl_pcie_recheck_me_status(struct work_struct *wk)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = container_of(wk,
|
||||
typeof(*trans_pcie),
|
||||
me_recheck_wk.work);
|
||||
u32 val;
|
||||
|
||||
val = iwl_read32(trans_pcie->trans, CSR_HW_IF_CONFIG_REG);
|
||||
trans_pcie->me_present = !!(val & CSR_HW_IF_CONFIG_REG_IAMT_UP);
|
||||
}
|
||||
|
||||
static void iwl_pcie_check_me_status(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
u32 val;
|
||||
|
||||
trans_pcie->me_present = -1;
|
||||
|
||||
INIT_DELAYED_WORK(&trans_pcie->me_recheck_wk,
|
||||
iwl_pcie_recheck_me_status);
|
||||
|
||||
/* we don't have a good way of determining this until BZ */
|
||||
if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
|
||||
return;
|
||||
|
||||
val = iwl_read_prph(trans, CNVI_SCU_REG_FOR_ECO_1);
|
||||
if (val & CNVI_SCU_REG_FOR_ECO_1_WIAMT_KNOWN) {
|
||||
trans_pcie->me_present =
|
||||
!!(val & CNVI_SCU_REG_FOR_ECO_1_WIAMT_PRESENT);
|
||||
return;
|
||||
}
|
||||
|
||||
val = iwl_read32(trans, CSR_HW_IF_CONFIG_REG);
|
||||
if (val & (CSR_HW_IF_CONFIG_REG_ME_OWN |
|
||||
CSR_HW_IF_CONFIG_REG_IAMT_UP)) {
|
||||
trans_pcie->me_present = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* recheck again later, ME might still be initializing */
|
||||
schedule_delayed_work(&trans_pcie->me_recheck_wk, HZ);
|
||||
}
|
||||
|
||||
static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
const struct iwl_mac_cfg *trans;
|
||||
const struct iwl_dev_info *dev_info;
|
||||
struct iwl_trans_info info = {
|
||||
.hw_id = (pdev->device << 16) + pdev->subsystem_device,
|
||||
};
|
||||
struct iwl_trans *iwl_trans;
|
||||
struct iwl_trans_pcie *trans_pcie;
|
||||
const struct iwl_mac_cfg *mac_cfg = (void *)ent->driver_data;
|
||||
u8 __iomem *hw_base;
|
||||
u32 bar0, hw_rev;
|
||||
int ret;
|
||||
|
||||
trans = (void *)ent->driver_data;
|
||||
|
||||
iwl_trans = iwl_trans_pcie_alloc(pdev, trans, &info);
|
||||
if (IS_ERR(iwl_trans))
|
||||
return PTR_ERR(iwl_trans);
|
||||
|
||||
trans_pcie = IWL_TRANS_GET_PCIE_TRANS(iwl_trans);
|
||||
|
||||
iwl_trans_pcie_check_product_reset_status(pdev);
|
||||
iwl_trans_pcie_check_product_reset_mode(pdev);
|
||||
|
||||
/* set the things we know so far for the grab NIC access */
|
||||
iwl_trans_set_info(iwl_trans, &info);
|
||||
|
||||
/*
|
||||
* Let's try to grab NIC access early here. Sometimes, NICs may
|
||||
* fail to initialize, and if that happens it's better if we see
|
||||
* issues early on (and can reprobe, per the logic inside), than
|
||||
* first trying to load the firmware etc. and potentially only
|
||||
* detecting any problems when the first interface is brought up.
|
||||
*/
|
||||
ret = iwl_pcie_prepare_card_hw(iwl_trans);
|
||||
if (!ret) {
|
||||
ret = iwl_finish_nic_init(iwl_trans);
|
||||
/* reassign our BAR 0 if invalid due to possible runtime PM races */
|
||||
pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &bar0);
|
||||
if (bar0 == PCI_BASE_ADDRESS_MEM_TYPE_64) {
|
||||
ret = pci_assign_resource(pdev, 0);
|
||||
if (ret)
|
||||
goto out_free_trans;
|
||||
if (iwl_trans_grab_nic_access(iwl_trans)) {
|
||||
get_crf_id(iwl_trans, &info);
|
||||
/* all good */
|
||||
iwl_trans_release_nic_access(iwl_trans);
|
||||
} else {
|
||||
ret = -EIO;
|
||||
goto out_free_trans;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
info.hw_rf_id = iwl_read32(iwl_trans, CSR_HW_RF_ID);
|
||||
|
||||
/*
|
||||
* The RF_ID is set to zero in blank OTP so read version to
|
||||
* extract the RF_ID.
|
||||
* This is relevant only for family 9000 and up.
|
||||
*/
|
||||
if (iwl_trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_9000 &&
|
||||
!CSR_HW_RFID_TYPE(info.hw_rf_id) && map_crf_id(iwl_trans, &info)) {
|
||||
ret = -EINVAL;
|
||||
goto out_free_trans;
|
||||
}
|
||||
|
||||
IWL_INFO(iwl_trans, "PCI dev %04x/%04x, rev=0x%x, rfid=0x%x\n",
|
||||
pdev->device, pdev->subsystem_device,
|
||||
info.hw_rev, info.hw_rf_id);
|
||||
|
||||
dev_info = iwl_pci_find_dev_info(pdev->device, pdev->subsystem_device,
|
||||
CSR_HW_RFID_TYPE(info.hw_rf_id),
|
||||
CSR_HW_RFID_IS_CDB(info.hw_rf_id),
|
||||
IWL_SUBDEVICE_RF_ID(pdev->subsystem_device),
|
||||
IWL_SUBDEVICE_BW_LIM(pdev->subsystem_device),
|
||||
CSR_HW_RFID_STEP(info.hw_rf_id));
|
||||
if (dev_info) {
|
||||
iwl_trans->cfg = dev_info->cfg;
|
||||
info.name = dev_info->name;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_IWLMVM)
|
||||
/*
|
||||
* special-case 7265D, it has the same PCI IDs.
|
||||
*
|
||||
* Note that because we already pass the cfg to the transport above,
|
||||
* all the parameters that the transport uses must, until that is
|
||||
* changed, be identical to the ones in the 7265D configuration.
|
||||
*/
|
||||
if (iwl_trans->cfg == &iwl7265_cfg &&
|
||||
(info.hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_7265D)
|
||||
iwl_trans->cfg = &iwl7265d_cfg;
|
||||
#endif
|
||||
if (!iwl_trans->cfg) {
|
||||
pr_err("No config found for PCI dev %04x/%04x, rev=0x%x, rfid=0x%x\n",
|
||||
pdev->device, pdev->subsystem_device,
|
||||
info.hw_rev, info.hw_rf_id);
|
||||
ret = -EINVAL;
|
||||
goto out_free_trans;
|
||||
}
|
||||
|
||||
IWL_INFO(iwl_trans, "Detected %s\n", info.name);
|
||||
|
||||
if (iwl_trans->mac_cfg->mq_rx_supported) {
|
||||
if (WARN_ON(!iwl_trans->cfg->num_rbds)) {
|
||||
ret = -EINVAL;
|
||||
goto out_free_trans;
|
||||
}
|
||||
trans_pcie->num_rx_bufs = iwl_trans_get_num_rbds(iwl_trans);
|
||||
} else {
|
||||
trans_pcie->num_rx_bufs = RX_QUEUE_SIZE;
|
||||
}
|
||||
|
||||
if (!iwl_trans->mac_cfg->integrated) {
|
||||
u16 link_status;
|
||||
|
||||
pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &link_status);
|
||||
|
||||
info.pcie_link_speed =
|
||||
u16_get_bits(link_status, PCI_EXP_LNKSTA_CLS);
|
||||
}
|
||||
|
||||
iwl_trans_set_info(iwl_trans, &info);
|
||||
|
||||
ret = iwl_trans_init(iwl_trans);
|
||||
ret = pcim_enable_device(pdev);
|
||||
if (ret)
|
||||
goto out_free_trans;
|
||||
return ret;
|
||||
|
||||
pci_set_drvdata(pdev, iwl_trans);
|
||||
pci_set_master(pdev);
|
||||
|
||||
iwl_pcie_check_me_status(iwl_trans);
|
||||
|
||||
/* try to get ownership so that we'll know if we don't own it */
|
||||
iwl_pcie_prepare_card_hw(iwl_trans);
|
||||
|
||||
iwl_trans->drv = iwl_drv_start(iwl_trans);
|
||||
|
||||
if (IS_ERR(iwl_trans->drv)) {
|
||||
ret = PTR_ERR(iwl_trans->drv);
|
||||
goto out_free_trans;
|
||||
ret = pcim_request_all_regions(pdev, DRV_NAME);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Requesting all PCI BARs failed.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* register transport layer debugfs here */
|
||||
iwl_trans_pcie_dbgfs_register(iwl_trans);
|
||||
hw_base = pcim_iomap(pdev, 0, 0);
|
||||
if (!hw_base) {
|
||||
dev_err(&pdev->dev, "Failed to map BAR 0.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
/* We can't use iwl_read32 because trans wasn't allocated */
|
||||
hw_rev = readl(hw_base + CSR_HW_REV);
|
||||
if (hw_rev == 0xffffffff) {
|
||||
dev_err(&pdev->dev, "HW_REV=0xFFFFFFFF, PCI issues?\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
out_free_trans:
|
||||
iwl_trans_pcie_free(iwl_trans);
|
||||
return ret;
|
||||
return iwl_pci_gen1_2_probe(pdev, ent, mac_cfg, hw_base, hw_rev);
|
||||
}
|
||||
|
||||
static void iwl_pci_remove(struct pci_dev *pdev)
|
||||
|
|
|
|||
|
|
@ -538,10 +538,6 @@ iwl_trans_pcie_get_trans(struct iwl_trans_pcie *trans_pcie)
|
|||
* Convention: trans API functions: iwl_trans_pcie_XXX
|
||||
* Other functions: iwl_pcie_XXX
|
||||
*/
|
||||
struct iwl_trans
|
||||
*iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
const struct iwl_mac_cfg *mac_cfg,
|
||||
struct iwl_trans_info *info);
|
||||
void iwl_trans_pcie_free(struct iwl_trans *trans);
|
||||
void iwl_trans_pcie_free_pnvm_dram_regions(struct iwl_dram_regions *dram_regions,
|
||||
struct device *dev);
|
||||
|
|
@ -1081,6 +1077,10 @@ bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans);
|
|||
void __releases(nic_access_nobh)
|
||||
iwl_trans_pcie_release_nic_access(struct iwl_trans *trans);
|
||||
void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power);
|
||||
int iwl_pci_gen1_2_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent,
|
||||
const struct iwl_mac_cfg *mac_cfg,
|
||||
u8 __iomem *hw_base, u32 hw_rev);
|
||||
|
||||
/* transport gen 1 exported functions */
|
||||
void iwl_trans_pcie_fw_alive(struct iwl_trans *trans);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "fw/dbg.h"
|
||||
#include "fw/api/tx.h"
|
||||
#include "fw/acpi.h"
|
||||
#include "fw/api/tx.h"
|
||||
#include "mei/iwl-mei.h"
|
||||
#include "internal.h"
|
||||
#include "iwl-fh.h"
|
||||
|
|
@ -380,17 +381,15 @@ void iwl_pcie_apm_stop_master(struct iwl_trans *trans)
|
|||
iwl_set_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_REQ);
|
||||
|
||||
ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS,
|
||||
CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS,
|
||||
100);
|
||||
ret = iwl_poll_bits(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS,
|
||||
100);
|
||||
usleep_range(10000, 20000);
|
||||
} else {
|
||||
iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
|
||||
|
||||
ret = iwl_poll_bit(trans, CSR_RESET,
|
||||
CSR_RESET_REG_FLAG_MASTER_DISABLED,
|
||||
CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
|
||||
ret = iwl_poll_bits(trans, CSR_RESET,
|
||||
CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
|
|
@ -492,10 +491,9 @@ static int iwl_pcie_set_hw_ready(struct iwl_trans *trans)
|
|||
CSR_HW_IF_CONFIG_REG_PCI_OWN_SET);
|
||||
|
||||
/* See if we got it */
|
||||
ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_PCI_OWN_SET,
|
||||
CSR_HW_IF_CONFIG_REG_PCI_OWN_SET,
|
||||
HW_READY_TIMEOUT);
|
||||
ret = iwl_poll_bits(trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_PCI_OWN_SET,
|
||||
HW_READY_TIMEOUT);
|
||||
|
||||
if (ret >= 0)
|
||||
iwl_set_bit(trans, CSR_MBOX_SET_REG, CSR_MBOX_SET_REG_OS_ALIVE);
|
||||
|
|
@ -2354,7 +2352,7 @@ bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent)
|
|||
* 5000 series and later (including 1000 series) have non-volatile SRAM,
|
||||
* and do not save/restore SRAM when power cycling.
|
||||
*/
|
||||
ret = iwl_poll_bit(trans, CSR_GP_CNTRL, poll, mask, 15000);
|
||||
ret = iwl_poll_bits_mask(trans, CSR_GP_CNTRL, poll, mask, 15000);
|
||||
if (unlikely(ret < 0)) {
|
||||
u32 cntrl = iwl_read32(trans, CSR_GP_CNTRL);
|
||||
|
||||
|
|
@ -3686,36 +3684,56 @@ void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)
|
|||
iwl_trans_sync_nmi_with_addr(trans, inta_addr, sw_err_bit);
|
||||
}
|
||||
|
||||
struct iwl_trans *
|
||||
static int iwl_trans_pcie_set_txcmd_info(const struct iwl_mac_cfg *mac_cfg,
|
||||
unsigned int *txcmd_size,
|
||||
unsigned int *txcmd_align)
|
||||
{
|
||||
if (!mac_cfg->gen2) {
|
||||
*txcmd_size = sizeof(struct iwl_tx_cmd_v6);
|
||||
*txcmd_align = sizeof(void *);
|
||||
} else if (mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
|
||||
*txcmd_size = sizeof(struct iwl_tx_cmd_v9);
|
||||
*txcmd_align = 64;
|
||||
} else {
|
||||
*txcmd_size = sizeof(struct iwl_tx_cmd);
|
||||
*txcmd_align = 128;
|
||||
}
|
||||
|
||||
*txcmd_size += sizeof(struct iwl_cmd_header);
|
||||
*txcmd_size += 36; /* biggest possible 802.11 header */
|
||||
|
||||
/* Ensure device TX cmd cannot reach/cross a page boundary in gen2 */
|
||||
if (WARN_ON((mac_cfg->gen2 && *txcmd_size >= *txcmd_align)))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct iwl_trans *
|
||||
iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
const struct iwl_mac_cfg *mac_cfg,
|
||||
struct iwl_trans_info *info)
|
||||
struct iwl_trans_info *info, u8 __iomem *hw_base)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie, **priv;
|
||||
unsigned int txcmd_size, txcmd_align;
|
||||
struct iwl_trans *trans;
|
||||
unsigned int bc_tbl_n_entries;
|
||||
int ret, addr_size;
|
||||
u32 bar0;
|
||||
|
||||
/* reassign our BAR 0 if invalid due to possible runtime PM races */
|
||||
pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &bar0);
|
||||
if (bar0 == PCI_BASE_ADDRESS_MEM_TYPE_64) {
|
||||
ret = pci_assign_resource(pdev, 0);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
ret = pcim_enable_device(pdev);
|
||||
ret = iwl_trans_pcie_set_txcmd_info(mac_cfg, &txcmd_size,
|
||||
&txcmd_align);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie), &pdev->dev,
|
||||
mac_cfg);
|
||||
mac_cfg, txcmd_size, txcmd_align);
|
||||
if (!trans)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
trans_pcie->hw_base = hw_base;
|
||||
|
||||
/* Initialize the wait queue for commands */
|
||||
init_waitqueue_head(&trans_pcie->wait_command_queue);
|
||||
|
||||
|
|
@ -3813,8 +3831,6 @@ iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
|||
PCIE_LINK_STATE_CLKPM);
|
||||
}
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
addr_size = trans_pcie->txqs.tfd.addr_size;
|
||||
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(addr_size));
|
||||
if (ret) {
|
||||
|
|
@ -3826,19 +3842,6 @@ iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
|||
}
|
||||
}
|
||||
|
||||
ret = pcim_request_all_regions(pdev, DRV_NAME);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Requesting all PCI BARs failed.\n");
|
||||
goto out_no_pci;
|
||||
}
|
||||
|
||||
trans_pcie->hw_base = pcim_iomap(pdev, 0, 0);
|
||||
if (!trans_pcie->hw_base) {
|
||||
dev_err(&pdev->dev, "Could not ioremap PCI BAR 0.\n");
|
||||
ret = -ENODEV;
|
||||
goto out_no_pci;
|
||||
}
|
||||
|
||||
/* We disable the RETRY_TIMEOUT register (0x41) to keep
|
||||
* PCI Tx retries from interfering with C3 CPU state */
|
||||
pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
|
||||
|
|
@ -3846,13 +3849,6 @@ iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
|||
trans_pcie->pci_dev = pdev;
|
||||
iwl_disable_interrupts(trans);
|
||||
|
||||
info->hw_rev = iwl_read32(trans, CSR_HW_REV);
|
||||
if (info->hw_rev == 0xffffffff) {
|
||||
dev_err(&pdev->dev, "HW_REV=0xFFFFFFFF, PCI issues?\n");
|
||||
ret = -EIO;
|
||||
goto out_no_pci;
|
||||
}
|
||||
|
||||
/*
|
||||
* In the 8000 HW family the format of the 4 bytes of CSR_HW_REV have
|
||||
* changed, and now the revision step also includes bit 0-1 (no more
|
||||
|
|
@ -3952,3 +3948,326 @@ int iwl_trans_pcie_copy_imr(struct iwl_trans *trans,
|
|||
trans_pcie->imr_status = IMR_D2S_IDLE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read rf id and cdb info from prph register and store it
|
||||
*/
|
||||
static void get_crf_id(struct iwl_trans *iwl_trans,
|
||||
struct iwl_trans_info *info)
|
||||
{
|
||||
u32 sd_reg_ver_addr;
|
||||
u32 hw_wfpm_id;
|
||||
u32 val = 0;
|
||||
u8 step;
|
||||
|
||||
if (iwl_trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
|
||||
sd_reg_ver_addr = SD_REG_VER_GEN2;
|
||||
else
|
||||
sd_reg_ver_addr = SD_REG_VER;
|
||||
|
||||
/* Enable access to peripheral registers */
|
||||
val = iwl_read_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG);
|
||||
val |= WFPM_AUX_CTL_AUX_IF_MAC_OWNER_MSK;
|
||||
iwl_write_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG, val);
|
||||
|
||||
/* Read crf info */
|
||||
info->hw_crf_id = iwl_read_prph_no_grab(iwl_trans, sd_reg_ver_addr);
|
||||
|
||||
/* Read cnv info */
|
||||
info->hw_cnv_id = iwl_read_prph_no_grab(iwl_trans, CNVI_AUX_MISC_CHIP);
|
||||
|
||||
/* For BZ-W, take B step also when A step is indicated */
|
||||
if (CSR_HW_REV_TYPE(info->hw_rev) == IWL_CFG_MAC_TYPE_BZ_W)
|
||||
step = SILICON_B_STEP;
|
||||
|
||||
/* In BZ, the MAC step must be read from the CNVI aux register */
|
||||
if (CSR_HW_REV_TYPE(info->hw_rev) == IWL_CFG_MAC_TYPE_BZ) {
|
||||
step = CNVI_AUX_MISC_CHIP_MAC_STEP(info->hw_cnv_id);
|
||||
|
||||
/* For BZ-U, take B step also when A step is indicated */
|
||||
if ((CNVI_AUX_MISC_CHIP_PROD_TYPE(info->hw_cnv_id) ==
|
||||
CNVI_AUX_MISC_CHIP_PROD_TYPE_BZ_U) &&
|
||||
step == SILICON_A_STEP)
|
||||
step = SILICON_B_STEP;
|
||||
}
|
||||
|
||||
if (CSR_HW_REV_TYPE(info->hw_rev) == IWL_CFG_MAC_TYPE_BZ ||
|
||||
CSR_HW_REV_TYPE(info->hw_rev) == IWL_CFG_MAC_TYPE_BZ_W) {
|
||||
info->hw_rev_step = step;
|
||||
info->hw_rev |= step;
|
||||
}
|
||||
|
||||
/* Read cdb info (also contains the jacket info if needed in the future */
|
||||
hw_wfpm_id = iwl_read_umac_prph_no_grab(iwl_trans, WFPM_OTP_CFG1_ADDR);
|
||||
IWL_INFO(iwl_trans, "Detected crf-id 0x%x, cnv-id 0x%x wfpm id 0x%x\n",
|
||||
info->hw_crf_id, info->hw_cnv_id, hw_wfpm_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* In case that there is no OTP on the NIC, map the rf id and cdb info
|
||||
* from the prph registers.
|
||||
*/
|
||||
static int map_crf_id(struct iwl_trans *iwl_trans,
|
||||
struct iwl_trans_info *info)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 val = info->hw_crf_id;
|
||||
u32 step_id = REG_CRF_ID_STEP(val);
|
||||
u32 slave_id = REG_CRF_ID_SLAVE(val);
|
||||
u32 jacket_id_cnv = REG_CRF_ID_SLAVE(info->hw_cnv_id);
|
||||
u32 hw_wfpm_id = iwl_read_umac_prph_no_grab(iwl_trans,
|
||||
WFPM_OTP_CFG1_ADDR);
|
||||
u32 jacket_id_wfpm = WFPM_OTP_CFG1_IS_JACKET(hw_wfpm_id);
|
||||
u32 cdb_id_wfpm = WFPM_OTP_CFG1_IS_CDB(hw_wfpm_id);
|
||||
|
||||
/* Map between crf id to rf id */
|
||||
switch (REG_CRF_ID_TYPE(val)) {
|
||||
case REG_CRF_ID_TYPE_JF_1:
|
||||
info->hw_rf_id = (IWL_CFG_RF_TYPE_JF1 << 12);
|
||||
break;
|
||||
case REG_CRF_ID_TYPE_JF_2:
|
||||
info->hw_rf_id = (IWL_CFG_RF_TYPE_JF2 << 12);
|
||||
break;
|
||||
case REG_CRF_ID_TYPE_HR_NONE_CDB_1X1:
|
||||
info->hw_rf_id = (IWL_CFG_RF_TYPE_HR1 << 12);
|
||||
break;
|
||||
case REG_CRF_ID_TYPE_HR_NONE_CDB:
|
||||
info->hw_rf_id = (IWL_CFG_RF_TYPE_HR2 << 12);
|
||||
break;
|
||||
case REG_CRF_ID_TYPE_HR_CDB:
|
||||
info->hw_rf_id = (IWL_CFG_RF_TYPE_HR2 << 12);
|
||||
break;
|
||||
case REG_CRF_ID_TYPE_GF:
|
||||
info->hw_rf_id = (IWL_CFG_RF_TYPE_GF << 12);
|
||||
break;
|
||||
case REG_CRF_ID_TYPE_FM:
|
||||
info->hw_rf_id = (IWL_CFG_RF_TYPE_FM << 12);
|
||||
break;
|
||||
case REG_CRF_ID_TYPE_WHP:
|
||||
info->hw_rf_id = (IWL_CFG_RF_TYPE_WH << 12);
|
||||
break;
|
||||
case REG_CRF_ID_TYPE_PE:
|
||||
info->hw_rf_id = (IWL_CFG_RF_TYPE_PE << 12);
|
||||
break;
|
||||
default:
|
||||
ret = -EIO;
|
||||
IWL_ERR(iwl_trans,
|
||||
"Can't find a correct rfid for crf id 0x%x\n",
|
||||
REG_CRF_ID_TYPE(val));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Set Step-id */
|
||||
info->hw_rf_id |= (step_id << 8);
|
||||
|
||||
/* Set CDB capabilities */
|
||||
if (cdb_id_wfpm || slave_id) {
|
||||
info->hw_rf_id += BIT(28);
|
||||
IWL_INFO(iwl_trans, "Adding cdb to rf id\n");
|
||||
}
|
||||
|
||||
/* Set Jacket capabilities */
|
||||
if (jacket_id_wfpm || jacket_id_cnv) {
|
||||
info->hw_rf_id += BIT(29);
|
||||
IWL_INFO(iwl_trans, "Adding jacket to rf id\n");
|
||||
}
|
||||
|
||||
IWL_INFO(iwl_trans,
|
||||
"Detected rf-type 0x%x step-id 0x%x slave-id 0x%x from crf id 0x%x\n",
|
||||
REG_CRF_ID_TYPE(val), step_id, slave_id, info->hw_rf_id);
|
||||
IWL_INFO(iwl_trans,
|
||||
"Detected cdb-id 0x%x jacket-id 0x%x from wfpm id 0x%x\n",
|
||||
cdb_id_wfpm, jacket_id_wfpm, hw_wfpm_id);
|
||||
IWL_INFO(iwl_trans, "Detected jacket-id 0x%x from cnvi id 0x%x\n",
|
||||
jacket_id_cnv, info->hw_cnv_id);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iwl_pcie_recheck_me_status(struct work_struct *wk)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = container_of(wk,
|
||||
typeof(*trans_pcie),
|
||||
me_recheck_wk.work);
|
||||
u32 val;
|
||||
|
||||
val = iwl_read32(trans_pcie->trans, CSR_HW_IF_CONFIG_REG);
|
||||
trans_pcie->me_present = !!(val & CSR_HW_IF_CONFIG_REG_IAMT_UP);
|
||||
}
|
||||
|
||||
static void iwl_pcie_check_me_status(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
u32 val;
|
||||
|
||||
trans_pcie->me_present = -1;
|
||||
|
||||
INIT_DELAYED_WORK(&trans_pcie->me_recheck_wk,
|
||||
iwl_pcie_recheck_me_status);
|
||||
|
||||
/* we don't have a good way of determining this until BZ */
|
||||
if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
|
||||
return;
|
||||
|
||||
val = iwl_read_prph(trans, CNVI_SCU_REG_FOR_ECO_1);
|
||||
if (val & CNVI_SCU_REG_FOR_ECO_1_WIAMT_KNOWN) {
|
||||
trans_pcie->me_present =
|
||||
!!(val & CNVI_SCU_REG_FOR_ECO_1_WIAMT_PRESENT);
|
||||
return;
|
||||
}
|
||||
|
||||
val = iwl_read32(trans, CSR_HW_IF_CONFIG_REG);
|
||||
if (val & (CSR_HW_IF_CONFIG_REG_ME_OWN |
|
||||
CSR_HW_IF_CONFIG_REG_IAMT_UP)) {
|
||||
trans_pcie->me_present = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* recheck again later, ME might still be initializing */
|
||||
schedule_delayed_work(&trans_pcie->me_recheck_wk, HZ);
|
||||
}
|
||||
|
||||
int iwl_pci_gen1_2_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent,
|
||||
const struct iwl_mac_cfg *mac_cfg,
|
||||
u8 __iomem *hw_base, u32 hw_rev)
|
||||
{
|
||||
const struct iwl_dev_info *dev_info;
|
||||
struct iwl_trans_info info = {
|
||||
.hw_id = (pdev->device << 16) + pdev->subsystem_device,
|
||||
.hw_rev = hw_rev,
|
||||
};
|
||||
struct iwl_trans *iwl_trans;
|
||||
struct iwl_trans_pcie *trans_pcie;
|
||||
int ret;
|
||||
|
||||
iwl_trans = iwl_trans_pcie_alloc(pdev, mac_cfg, &info, hw_base);
|
||||
if (IS_ERR(iwl_trans))
|
||||
return PTR_ERR(iwl_trans);
|
||||
|
||||
trans_pcie = IWL_TRANS_GET_PCIE_TRANS(iwl_trans);
|
||||
|
||||
iwl_trans_pcie_check_product_reset_status(pdev);
|
||||
iwl_trans_pcie_check_product_reset_mode(pdev);
|
||||
|
||||
/* set the things we know so far for the grab NIC access */
|
||||
iwl_trans_set_info(iwl_trans, &info);
|
||||
|
||||
/*
|
||||
* Let's try to grab NIC access early here. Sometimes, NICs may
|
||||
* fail to initialize, and if that happens it's better if we see
|
||||
* issues early on (and can reprobe, per the logic inside), than
|
||||
* first trying to load the firmware etc. and potentially only
|
||||
* detecting any problems when the first interface is brought up.
|
||||
*/
|
||||
ret = iwl_pcie_prepare_card_hw(iwl_trans);
|
||||
if (!ret) {
|
||||
ret = iwl_finish_nic_init(iwl_trans);
|
||||
if (ret)
|
||||
goto out_free_trans;
|
||||
if (iwl_trans_grab_nic_access(iwl_trans)) {
|
||||
get_crf_id(iwl_trans, &info);
|
||||
/* all good */
|
||||
iwl_trans_release_nic_access(iwl_trans);
|
||||
} else {
|
||||
ret = -EIO;
|
||||
goto out_free_trans;
|
||||
}
|
||||
}
|
||||
|
||||
info.hw_rf_id = iwl_read32(iwl_trans, CSR_HW_RF_ID);
|
||||
|
||||
/*
|
||||
* The RF_ID is set to zero in blank OTP so read version to
|
||||
* extract the RF_ID.
|
||||
* This is relevant only for family 9000 and up.
|
||||
*/
|
||||
if (iwl_trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_9000 &&
|
||||
!CSR_HW_RFID_TYPE(info.hw_rf_id) && map_crf_id(iwl_trans, &info)) {
|
||||
ret = -EINVAL;
|
||||
goto out_free_trans;
|
||||
}
|
||||
|
||||
IWL_INFO(iwl_trans, "PCI dev %04x/%04x, rev=0x%x, rfid=0x%x\n",
|
||||
pdev->device, pdev->subsystem_device,
|
||||
info.hw_rev, info.hw_rf_id);
|
||||
|
||||
dev_info = iwl_pci_find_dev_info(pdev->device, pdev->subsystem_device,
|
||||
CSR_HW_RFID_TYPE(info.hw_rf_id),
|
||||
CSR_HW_RFID_IS_CDB(info.hw_rf_id),
|
||||
IWL_SUBDEVICE_RF_ID(pdev->subsystem_device),
|
||||
IWL_SUBDEVICE_BW_LIM(pdev->subsystem_device),
|
||||
!iwl_trans->mac_cfg->integrated);
|
||||
if (dev_info) {
|
||||
iwl_trans->cfg = dev_info->cfg;
|
||||
info.name = dev_info->name;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_IWLMVM)
|
||||
|
||||
/*
|
||||
* special-case 7265D, it has the same PCI IDs.
|
||||
*
|
||||
* Note that because we already pass the cfg to the transport above,
|
||||
* all the parameters that the transport uses must, until that is
|
||||
* changed, be identical to the ones in the 7265D configuration.
|
||||
*/
|
||||
if (iwl_trans->cfg == &iwl7265_cfg &&
|
||||
(info.hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_7265D)
|
||||
iwl_trans->cfg = &iwl7265d_cfg;
|
||||
#endif
|
||||
if (!iwl_trans->cfg) {
|
||||
pr_err("No config found for PCI dev %04x/%04x, rev=0x%x, rfid=0x%x\n",
|
||||
pdev->device, pdev->subsystem_device,
|
||||
info.hw_rev, info.hw_rf_id);
|
||||
ret = -EINVAL;
|
||||
goto out_free_trans;
|
||||
}
|
||||
|
||||
IWL_INFO(iwl_trans, "Detected %s\n", info.name);
|
||||
|
||||
if (iwl_trans->mac_cfg->mq_rx_supported) {
|
||||
if (WARN_ON(!iwl_trans->cfg->num_rbds)) {
|
||||
ret = -EINVAL;
|
||||
goto out_free_trans;
|
||||
}
|
||||
trans_pcie->num_rx_bufs = iwl_trans_get_num_rbds(iwl_trans);
|
||||
} else {
|
||||
trans_pcie->num_rx_bufs = RX_QUEUE_SIZE;
|
||||
}
|
||||
|
||||
if (!iwl_trans->mac_cfg->integrated) {
|
||||
u16 link_status;
|
||||
|
||||
pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &link_status);
|
||||
|
||||
info.pcie_link_speed =
|
||||
u16_get_bits(link_status, PCI_EXP_LNKSTA_CLS);
|
||||
}
|
||||
|
||||
iwl_trans_set_info(iwl_trans, &info);
|
||||
|
||||
pci_set_drvdata(pdev, iwl_trans);
|
||||
|
||||
iwl_pcie_check_me_status(iwl_trans);
|
||||
|
||||
/* try to get ownership so that we'll know if we don't own it */
|
||||
iwl_pcie_prepare_card_hw(iwl_trans);
|
||||
|
||||
iwl_trans->drv = iwl_drv_start(iwl_trans);
|
||||
|
||||
if (IS_ERR(iwl_trans->drv)) {
|
||||
ret = PTR_ERR(iwl_trans->drv);
|
||||
goto out_free_trans;
|
||||
}
|
||||
|
||||
/* register transport layer debugfs here */
|
||||
iwl_trans_pcie_dbgfs_register(iwl_trans);
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_trans:
|
||||
iwl_trans_pcie_free(iwl_trans);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -590,7 +590,7 @@ static void iwl_pcie_tx_stop_fh(struct iwl_trans *trans)
|
|||
}
|
||||
|
||||
/* Wait for DMA channels to be idle */
|
||||
ret = iwl_poll_bit(trans, FH_TSSR_TX_STATUS_REG, mask, mask, 5000);
|
||||
ret = iwl_poll_bits(trans, FH_TSSR_TX_STATUS_REG, mask, 5000);
|
||||
if (ret < 0)
|
||||
IWL_ERR(trans,
|
||||
"Failing on timeout while stopping DMA channel %d [0x%08x]\n",
|
||||
|
|
|
|||
|
|
@ -31,15 +31,6 @@ static void iwl_pci_print_dev_info(const char *pfx, const struct iwl_dev_info *d
|
|||
pos += scnprintf(buf + pos, sizeof(buf) - pos,
|
||||
" bw_limit=*");
|
||||
|
||||
if (di->match_rf_step)
|
||||
pos += scnprintf(buf + pos, sizeof(buf) - pos,
|
||||
" rf_step=%c",
|
||||
di->rf_step == SILICON_Z_STEP ? 'Z' :
|
||||
'A' + di->rf_step);
|
||||
else
|
||||
pos += scnprintf(buf + pos, sizeof(buf) - pos,
|
||||
" rf_step=*");
|
||||
|
||||
if (di->match_rf_id)
|
||||
pos += scnprintf(buf + pos, sizeof(buf) - pos,
|
||||
" rf_id=0x%x", di->rf_id);
|
||||
|
|
@ -54,6 +45,13 @@ static void iwl_pci_print_dev_info(const char *pfx, const struct iwl_dev_info *d
|
|||
pos += scnprintf(buf + pos, sizeof(buf) - pos,
|
||||
" cdb=*");
|
||||
|
||||
if (di->match_discrete)
|
||||
pos += scnprintf(buf + pos, sizeof(buf) - pos,
|
||||
" discrete=%d",
|
||||
di->discrete);
|
||||
else
|
||||
pos += scnprintf(buf + pos, sizeof(buf) - pos,
|
||||
" discrete=*");
|
||||
|
||||
printk(KERN_DEBUG "%sdev=%04x subdev=%04x/%04x%s\n",
|
||||
pfx, di->device, di->subdevice, subdevice_mask, buf);
|
||||
|
|
@ -70,7 +68,7 @@ static void devinfo_table_order(struct kunit *test)
|
|||
ret = iwl_pci_find_dev_info(di->device, di->subdevice,
|
||||
di->rf_type, di->cdb,
|
||||
di->rf_id, di->bw_limit,
|
||||
di->rf_step);
|
||||
di->discrete);
|
||||
if (!ret) {
|
||||
iwl_pci_print_dev_info("No entry found for: ", di);
|
||||
KUNIT_FAIL(test,
|
||||
|
|
@ -85,6 +83,32 @@ static void devinfo_table_order(struct kunit *test)
|
|||
}
|
||||
}
|
||||
|
||||
static void devinfo_discrete_match(struct kunit *test)
|
||||
{
|
||||
/*
|
||||
* Validate that any entries with discrete/integrated match have
|
||||
* the same config with the value inverted (if they match at all.)
|
||||
*/
|
||||
|
||||
for (int idx = 0; idx < iwl_dev_info_table_size; idx++) {
|
||||
const struct iwl_dev_info *di = &iwl_dev_info_table[idx];
|
||||
const struct iwl_dev_info *ret;
|
||||
|
||||
if (!di->match_discrete)
|
||||
continue;
|
||||
|
||||
ret = iwl_pci_find_dev_info(di->device, di->subdevice,
|
||||
di->rf_type, di->cdb,
|
||||
di->rf_id, di->bw_limit,
|
||||
!di->discrete);
|
||||
if (!ret)
|
||||
continue;
|
||||
KUNIT_EXPECT_PTR_EQ(test, di->cfg, ret->cfg);
|
||||
/* and check the name is different, that'd be the point of it */
|
||||
KUNIT_EXPECT_NE(test, strcmp(di->name, ret->name), 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void devinfo_names(struct kunit *test)
|
||||
{
|
||||
int idx;
|
||||
|
|
@ -216,6 +240,7 @@ static void devinfo_no_mac_cfg_dups(struct kunit *test)
|
|||
|
||||
static struct kunit_case devinfo_test_cases[] = {
|
||||
KUNIT_CASE(devinfo_table_order),
|
||||
KUNIT_CASE(devinfo_discrete_match),
|
||||
KUNIT_CASE(devinfo_names),
|
||||
KUNIT_CASE(devinfo_no_cfg_dups),
|
||||
KUNIT_CASE(devinfo_no_name_dups),
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user