From 1afb0ae4217423f7864cba0684362de99782fa4e Mon Sep 17 00:00:00 2001 From: Haim Dreyfuss Date: Sun, 3 Apr 2016 19:55:59 +0300 Subject: [PATCH] iwlwifi: allow combining different phy images with mac images Currently there is one to one function between device id to it's ucode. The new generation devices allows to combine different phy and mac images. Now we have two different ucode images with the same device id. Read RF ID to identify phy image and overwrite it if needed. Signed-off-by: Haim Dreyfuss Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-9000.c | 29 +++++++++++++++++-- .../net/wireless/intel/iwlwifi/iwl-config.h | 3 ++ drivers/net/wireless/intel/iwlwifi/iwl-csr.h | 15 ++++++++++ .../net/wireless/intel/iwlwifi/iwl-trans.h | 2 ++ drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 10 +++++++ .../net/wireless/intel/iwlwifi/pcie/trans.c | 2 ++ 6 files changed, 58 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c index 86a55996ea75..a0eeb536ad72 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c @@ -72,9 +72,15 @@ #define IWL9000_SMEM_OFFSET 0x400000 #define IWL9000_SMEM_LEN 0x68000 -#define IWL9000_FW_PRE "iwlwifi-9000-" +#define IWL9000_FW_PRE "iwlwifi-9000-pu-a0-lc-a0-" +#define IWL9260_FW_PRE "iwlwifi-9260-th-a0-jf-a0-" +#define IWL9260LC_FW_PRE "iwlwifi-9260-th-a0-lc-a0-" #define IWL9000_MODULE_FIRMWARE(api) \ IWL9000_FW_PRE "-" __stringify(api) ".ucode" +#define IWL9260_MODULE_FIRMWARE(api) \ + IWL9260_FW_PRE "-" __stringify(api) ".ucode" +#define IWL9260LC_MODULE_FIRMWARE(api) \ + IWL9260LC_FW_PRE "-" __stringify(api) ".ucode" #define NVM_HW_SECTION_NUM_FAMILY_9000 10 @@ -138,11 +144,26 @@ static const struct iwl_tt_params iwl9000_tt_params = { .apmg_not_supported = true, \ .mq_rx_supported = true, \ .vht_mu_mimo_supported = true, \ - .mac_addr_from_csr = true + .mac_addr_from_csr = true, \ + .rf_id = true const struct iwl_cfg iwl9260_2ac_cfg = { .name = "Intel(R) Dual Band Wireless AC 9260", - .fw_name_pre = IWL9000_FW_PRE, + .fw_name_pre = IWL9260_FW_PRE, + IWL_DEVICE_9000, + .ht_params = &iwl9000_ht_params, + .nvm_ver = IWL9000_NVM_VERSION, + .nvm_calib_ver = IWL9000_TX_POWER_VERSION, + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, +}; + +/* + * TODO the struct below is for internal testing only this should be + * removed by EO 2016~ + */ +const struct iwl_cfg iwl9260lc_2ac_cfg = { + .name = "Intel(R) Dual Band Wireless AC 9260", + .fw_name_pre = IWL9260LC_FW_PRE, IWL_DEVICE_9000, .ht_params = &iwl9000_ht_params, .nvm_ver = IWL9000_NVM_VERSION, @@ -161,3 +182,5 @@ const struct iwl_cfg iwl5165_2ac_cfg = { }; MODULE_FIRMWARE(IWL9000_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL9260_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL9260LC_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 2e71e886627c..6eef5dc50293 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -314,6 +314,7 @@ struct iwl_pwr_tx_backoff { * @smem_len: the length of SMEM * @mq_rx_supported: multi-queue rx support * @vht_mu_mimo_supported: VHT MU-MIMO support + * @rf_id: need to read rf_id to determine the firmware image * * We enable the driver to be backward compatible wrt. hardware features. * API differences in uCode shouldn't be handled here but through TLVs @@ -367,6 +368,7 @@ struct iwl_cfg { bool apmg_not_supported; bool mq_rx_supported; bool vht_mu_mimo_supported; + bool rf_id; }; /* @@ -440,6 +442,7 @@ extern const struct iwl_cfg iwl8260_2ac_sdio_cfg; extern const struct iwl_cfg iwl8265_2ac_sdio_cfg; extern const struct iwl_cfg iwl4165_2ac_sdio_cfg; extern const struct iwl_cfg iwl9260_2ac_cfg; +extern const struct iwl_cfg iwl9260lc_2ac_cfg; extern const struct iwl_cfg iwl5165_2ac_cfg; #endif /* CONFIG_IWLMVM */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h index b978f6cae55c..b52913448c4a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h @@ -107,6 +107,17 @@ */ #define CSR_HW_REV (CSR_BASE+0x028) +/* + * RF ID revision info + * Bit fields: + * 31:24: Reserved (set to 0x0) + * 23:12: Type + * 11:8: Step (A - 0x0, B - 0x1, etc) + * 7:4: Dash + * 3:0: Flavor + */ +#define CSR_HW_RF_ID (CSR_BASE+0x09c) + /* * EEPROM and OTP (one-time-programmable) memory reads * @@ -333,6 +344,10 @@ enum { #define CSR_HW_REV_TYPE_7265D (0x0000210) #define CSR_HW_REV_TYPE_NONE (0x00001F0) +/* RF_ID value */ +#define CSR_HW_RF_ID_TYPE_JF (0x00105000) +#define CSR_HW_RF_ID_TYPE_LC (0x00101000) + /* EEPROM REG */ #define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001) #define CSR_EEPROM_REG_BIT_CMD (0x00000002) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index fa4ab4b9436f..8193d36ae2dd 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -753,6 +753,7 @@ enum iwl_plat_pm_mode { * @dev - pointer to struct device * that represents the device * @max_skb_frags: maximum number of fragments an SKB can have when transmitted. * 0 indicates that frag SKBs (NETIF_F_SG) aren't supported. + * @hw_rf_id a u32 with the device RF ID * @hw_id: a u32 with the ID of the device / sub-device. * Set during transport allocation. * @hw_id_str: a string with info about HW ID. Set during transport allocation. @@ -797,6 +798,7 @@ struct iwl_trans { struct device *dev; u32 max_skb_frags; u32 hw_rev; + u32 hw_rf_id; u32 hw_id; char hw_id_str[52]; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 8f139d0550d9..a588b05e38eb 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -596,6 +596,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); const struct iwl_cfg *cfg_7265d __maybe_unused = NULL; + const struct iwl_cfg *cfg_9260lc __maybe_unused = NULL; struct iwl_trans *iwl_trans; struct iwl_trans_pcie *trans_pcie; int ret; @@ -623,6 +624,15 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) cfg = cfg_7265d; iwl_trans->cfg = cfg_7265d; } + + if (iwl_trans->cfg->rf_id) { + if (cfg == &iwl9260_2ac_cfg) + cfg_9260lc = &iwl9260lc_2ac_cfg; + if (cfg_9260lc && iwl_trans->hw_rf_id == CSR_HW_RF_ID_TYPE_LC) { + cfg = cfg_9260lc; + iwl_trans->cfg = cfg_9260lc; + } + } #endif pci_set_drvdata(pdev, iwl_trans); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 37e134d10fd5..eb9bdf0ba02a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -2907,6 +2907,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, } } + trans->hw_rf_id = iwl_read32(trans, CSR_HW_RF_ID); + iwl_pcie_set_interrupt_capa(pdev, trans); trans->hw_id = (pdev->device << 16) + pdev->subsystem_device; snprintf(trans->hw_id_str, sizeof(trans->hw_id_str),