Loading drivers/net/wireless/ath/ath10k/ahb.c +5 −4 Original line number Diff line number Diff line Loading @@ -758,7 +758,7 @@ static int ath10k_ahb_probe(struct platform_device *pdev) enum ath10k_hw_rev hw_rev; size_t size; int ret; u32 chip_id; struct ath10k_bus_params bus_params; of_id = of_match_device(ath10k_ahb_of_match, &pdev->dev); if (!of_id) { Loading Loading @@ -814,14 +814,15 @@ static int ath10k_ahb_probe(struct platform_device *pdev) ath10k_pci_ce_deinit(ar); chip_id = ath10k_ahb_soc_read32(ar, SOC_CHIP_ID_ADDRESS); if (chip_id == 0xffffffff) { bus_params.dev_type = ATH10K_DEV_TYPE_LL; bus_params.chip_id = ath10k_ahb_soc_read32(ar, SOC_CHIP_ID_ADDRESS); if (bus_params.chip_id == 0xffffffff) { ath10k_err(ar, "failed to get chip id\n"); ret = -ENODEV; goto err_halt_device; } ret = ath10k_core_register(ar, chip_id); ret = ath10k_core_register(ar, &bus_params); if (ret) { ath10k_err(ar, "failed to register driver core: %d\n", ret); goto err_halt_device; Loading drivers/net/wireless/ath/ath10k/core.c +277 −265 Original line number Diff line number Diff line Loading @@ -693,149 +693,6 @@ static int ath10k_push_board_ext_data(struct ath10k *ar, const void *data, return 0; } static int ath10k_download_board_data(struct ath10k *ar, const void *data, size_t data_len) { u32 board_data_size = ar->hw_params.fw.board_size; u32 address; int ret; ret = ath10k_push_board_ext_data(ar, data, data_len); if (ret) { ath10k_err(ar, "could not push board ext data (%d)\n", ret); goto exit; } ret = ath10k_bmi_read32(ar, hi_board_data, &address); if (ret) { ath10k_err(ar, "could not read board data addr (%d)\n", ret); goto exit; } ret = ath10k_bmi_write_memory(ar, address, data, min_t(u32, board_data_size, data_len)); if (ret) { ath10k_err(ar, "could not write board data (%d)\n", ret); goto exit; } ret = ath10k_bmi_write32(ar, hi_board_data_initialized, 1); if (ret) { ath10k_err(ar, "could not write board data bit (%d)\n", ret); goto exit; } exit: return ret; } static int ath10k_download_cal_file(struct ath10k *ar, const struct firmware *file) { int ret; if (!file) return -ENOENT; if (IS_ERR(file)) return PTR_ERR(file); ret = ath10k_download_board_data(ar, file->data, file->size); if (ret) { ath10k_err(ar, "failed to download cal_file data: %d\n", ret); return ret; } ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cal file downloaded\n"); return 0; } static int ath10k_download_cal_dt(struct ath10k *ar, const char *dt_name) { struct device_node *node; int data_len; void *data; int ret; node = ar->dev->of_node; if (!node) /* Device Tree is optional, don't print any warnings if * there's no node for ath10k. */ return -ENOENT; if (!of_get_property(node, dt_name, &data_len)) { /* The calibration data node is optional */ return -ENOENT; } if (data_len != ar->hw_params.cal_data_len) { ath10k_warn(ar, "invalid calibration data length in DT: %d\n", data_len); ret = -EMSGSIZE; goto out; } data = kmalloc(data_len, GFP_KERNEL); if (!data) { ret = -ENOMEM; goto out; } ret = of_property_read_u8_array(node, dt_name, data, data_len); if (ret) { ath10k_warn(ar, "failed to read calibration data from DT: %d\n", ret); goto out_free; } ret = ath10k_download_board_data(ar, data, data_len); if (ret) { ath10k_warn(ar, "failed to download calibration data from Device Tree: %d\n", ret); goto out_free; } ret = 0; out_free: kfree(data); out: return ret; } static int ath10k_download_cal_eeprom(struct ath10k *ar) { size_t data_len; void *data = NULL; int ret; ret = ath10k_hif_fetch_cal_eeprom(ar, &data, &data_len); if (ret) { if (ret != -EOPNOTSUPP) ath10k_warn(ar, "failed to read calibration data from EEPROM: %d\n", ret); goto out_free; } ret = ath10k_download_board_data(ar, data, data_len); if (ret) { ath10k_warn(ar, "failed to download calibration data from EEPROM: %d\n", ret); goto out_free; } ret = 0; out_free: kfree(data); return ret; } static int ath10k_core_get_board_id_from_otp(struct ath10k *ar) { u32 result, address; Loading Loading @@ -986,64 +843,6 @@ static int ath10k_core_check_dt(struct ath10k *ar) return 0; } static int ath10k_download_and_run_otp(struct ath10k *ar) { u32 result, address = ar->hw_params.patch_load_addr; u32 bmi_otp_exe_param = ar->hw_params.otp_exe_param; int ret; ret = ath10k_download_board_data(ar, ar->running_fw->board_data, ar->running_fw->board_len); if (ret) { ath10k_err(ar, "failed to download board data: %d\n", ret); return ret; } /* OTP is optional */ if (!ar->running_fw->fw_file.otp_data || !ar->running_fw->fw_file.otp_len) { ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %pK otp_len %zd)!\n", ar->running_fw->fw_file.otp_data, ar->running_fw->fw_file.otp_len); return 0; } ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n", address, ar->running_fw->fw_file.otp_len); ret = ath10k_bmi_fast_download(ar, address, ar->running_fw->fw_file.otp_data, ar->running_fw->fw_file.otp_len); if (ret) { ath10k_err(ar, "could not write otp (%d)\n", ret); return ret; } /* As of now pre-cal is valid for 10_4 variants */ if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT || ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE) bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL; ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result); if (ret) { ath10k_err(ar, "could not execute otp (%d)\n", ret); return ret; } ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result); if (!(skip_otp || test_bit(ATH10K_FW_FEATURE_IGNORE_OTP_RESULT, ar->running_fw->fw_file.fw_features)) && result != 0) { ath10k_err(ar, "otp calibration failed: %d", result); return -EINVAL; } return 0; } static int ath10k_download_fw(struct ath10k *ar) { u32 address, data_len; Loading Loading @@ -1236,14 +1035,61 @@ static int ath10k_core_parse_bd_ie_board(struct ath10k *ar, return ret; } static int ath10k_core_search_bd(struct ath10k *ar, const char *boardname, const u8 *data, size_t len) { size_t ie_len; struct ath10k_fw_ie *hdr; int ret = -ENOENT, ie_id; while (len > sizeof(struct ath10k_fw_ie)) { hdr = (struct ath10k_fw_ie *)data; ie_id = le32_to_cpu(hdr->id); ie_len = le32_to_cpu(hdr->len); len -= sizeof(*hdr); data = hdr->data; if (len < ALIGN(ie_len, 4)) { ath10k_err(ar, "invalid length for board ie_id %d ie_len %zu len %zu\n", ie_id, ie_len, len); return -EINVAL; } switch (ie_id) { case ATH10K_BD_IE_BOARD: ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len, boardname); if (ret == -ENOENT) /* no match found, continue */ break; /* either found or error, so stop searching */ goto out; } /* jump over the padding */ ie_len = ALIGN(ie_len, 4); len -= ie_len; data += ie_len; } out: /* return result of parse_bd_ie_board() or -ENOENT */ return ret; } static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar, const char *boardname, const char *fallback_boardname, const char *filename) { size_t len, magic_len, ie_len; struct ath10k_fw_ie *hdr; size_t len, magic_len; const u8 *data; int ret, ie_id; int ret; ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, Loading Loading @@ -1281,69 +1127,23 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar, data += magic_len; len -= magic_len; while (len > sizeof(struct ath10k_fw_ie)) { hdr = (struct ath10k_fw_ie *)data; ie_id = le32_to_cpu(hdr->id); ie_len = le32_to_cpu(hdr->len); len -= sizeof(*hdr); data = hdr->data; if (len < ALIGN(ie_len, 4)) { ath10k_err(ar, "invalid length for board ie_id %d ie_len %zu len %zu\n", ie_id, ie_len, len); ret = -EINVAL; goto err; } switch (ie_id) { case ATH10K_BD_IE_BOARD: ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len, boardname); if (ret == -ENOENT && ar->id.bdf_ext[0] != '\0') { /* try default bdf if variant was not found */ char *s, *v = ",variant="; char boardname2[100]; strlcpy(boardname2, boardname, sizeof(boardname2)); s = strstr(boardname2, v); if (s) *s = '\0'; /* strip ",variant=%s" */ ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len, boardname2); } if (ret == -ENOENT) /* no match found, continue */ break; else if (ret) /* there was an error, bail out */ goto err; /* board data found */ goto out; } /* jump over the padding */ ie_len = ALIGN(ie_len, 4); /* attempt to find boardname in the IE list */ ret = ath10k_core_search_bd(ar, boardname, data, len); len -= ie_len; data += ie_len; } /* if we didn't find it and have a fallback name, try that */ if (ret == -ENOENT && fallback_boardname) ret = ath10k_core_search_bd(ar, fallback_boardname, data, len); out: if (!ar->normal_mode_fw.board_data || !ar->normal_mode_fw.board_len) { if (ret == -ENOENT) { ath10k_err(ar, "failed to fetch board data for %s from %s/%s\n", boardname, ar->hw_params.fw.dir, filename); ret = -ENODATA; goto err; } if (ret) goto err; return 0; err: Loading @@ -1352,12 +1152,12 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar, } static int ath10k_core_create_board_name(struct ath10k *ar, char *name, size_t name_len) size_t name_len, bool with_variant) { /* strlen(',variant=') + strlen(ar->id.bdf_ext) */ char variant[9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH] = { 0 }; if (ar->id.bdf_ext[0] != '\0') if (with_variant && ar->id.bdf_ext[0] != '\0') scnprintf(variant, sizeof(variant), ",variant=%s", ar->id.bdf_ext); Loading Loading @@ -1391,17 +1191,26 @@ static int ath10k_core_create_board_name(struct ath10k *ar, char *name, static int ath10k_core_fetch_board_file(struct ath10k *ar) { char boardname[100]; char boardname[100], fallback_boardname[100]; int ret; ret = ath10k_core_create_board_name(ar, boardname, sizeof(boardname)); ret = ath10k_core_create_board_name(ar, boardname, sizeof(boardname), true); if (ret) { ath10k_err(ar, "failed to create board name: %d", ret); return ret; } ret = ath10k_core_create_board_name(ar, fallback_boardname, sizeof(boardname), false); if (ret) { ath10k_err(ar, "failed to create fallback board name: %d", ret); return ret; } ar->bd_api = 2; ret = ath10k_core_fetch_board_data_api_n(ar, boardname, fallback_boardname, ATH10K_BOARD_API2_FILE); if (!ret) goto success; Loading @@ -1419,6 +1228,207 @@ static int ath10k_core_fetch_board_file(struct ath10k *ar) return 0; } static int ath10k_download_board_data(struct ath10k *ar, const void *data, size_t data_len) { u32 board_data_size = ar->hw_params.fw.board_size; u32 address; int ret; ret = ath10k_push_board_ext_data(ar, data, data_len); if (ret) { ath10k_err(ar, "could not push board ext data (%d)\n", ret); goto exit; } ret = ath10k_bmi_read32(ar, hi_board_data, &address); if (ret) { ath10k_err(ar, "could not read board data addr (%d)\n", ret); goto exit; } ret = ath10k_bmi_write_memory(ar, address, data, min_t(u32, board_data_size, data_len)); if (ret) { ath10k_err(ar, "could not write board data (%d)\n", ret); goto exit; } ret = ath10k_bmi_write32(ar, hi_board_data_initialized, 1); if (ret) { ath10k_err(ar, "could not write board data bit (%d)\n", ret); goto exit; } exit: return ret; } static int ath10k_download_and_run_otp(struct ath10k *ar) { u32 result, address = ar->hw_params.patch_load_addr; u32 bmi_otp_exe_param = ar->hw_params.otp_exe_param; int ret; ret = ath10k_download_board_data(ar, ar->running_fw->board_data, ar->running_fw->board_len); if (ret) { ath10k_err(ar, "failed to download board data: %d\n", ret); return ret; } /* OTP is optional */ if (!ar->running_fw->fw_file.otp_data || !ar->running_fw->fw_file.otp_len) { ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %pK otp_len %zd)!\n", ar->running_fw->fw_file.otp_data, ar->running_fw->fw_file.otp_len); return 0; } ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n", address, ar->running_fw->fw_file.otp_len); ret = ath10k_bmi_fast_download(ar, address, ar->running_fw->fw_file.otp_data, ar->running_fw->fw_file.otp_len); if (ret) { ath10k_err(ar, "could not write otp (%d)\n", ret); return ret; } /* As of now pre-cal is valid for 10_4 variants */ if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT || ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE) bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL; ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result); if (ret) { ath10k_err(ar, "could not execute otp (%d)\n", ret); return ret; } ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result); if (!(skip_otp || test_bit(ATH10K_FW_FEATURE_IGNORE_OTP_RESULT, ar->running_fw->fw_file.fw_features)) && result != 0) { ath10k_err(ar, "otp calibration failed: %d", result); return -EINVAL; } return 0; } static int ath10k_download_cal_file(struct ath10k *ar, const struct firmware *file) { int ret; if (!file) return -ENOENT; if (IS_ERR(file)) return PTR_ERR(file); ret = ath10k_download_board_data(ar, file->data, file->size); if (ret) { ath10k_err(ar, "failed to download cal_file data: %d\n", ret); return ret; } ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cal file downloaded\n"); return 0; } static int ath10k_download_cal_dt(struct ath10k *ar, const char *dt_name) { struct device_node *node; int data_len; void *data; int ret; node = ar->dev->of_node; if (!node) /* Device Tree is optional, don't print any warnings if * there's no node for ath10k. */ return -ENOENT; if (!of_get_property(node, dt_name, &data_len)) { /* The calibration data node is optional */ return -ENOENT; } if (data_len != ar->hw_params.cal_data_len) { ath10k_warn(ar, "invalid calibration data length in DT: %d\n", data_len); ret = -EMSGSIZE; goto out; } data = kmalloc(data_len, GFP_KERNEL); if (!data) { ret = -ENOMEM; goto out; } ret = of_property_read_u8_array(node, dt_name, data, data_len); if (ret) { ath10k_warn(ar, "failed to read calibration data from DT: %d\n", ret); goto out_free; } ret = ath10k_download_board_data(ar, data, data_len); if (ret) { ath10k_warn(ar, "failed to download calibration data from Device Tree: %d\n", ret); goto out_free; } ret = 0; out_free: kfree(data); out: return ret; } static int ath10k_download_cal_eeprom(struct ath10k *ar) { size_t data_len; void *data = NULL; int ret; ret = ath10k_hif_fetch_cal_eeprom(ar, &data, &data_len); if (ret) { if (ret != -EOPNOTSUPP) ath10k_warn(ar, "failed to read calibration data from EEPROM: %d\n", ret); goto out_free; } ret = ath10k_download_board_data(ar, data, data_len); if (ret) { ath10k_warn(ar, "failed to download calibration data from EEPROM: %d\n", ret); goto out_free; } ret = 0; out_free: kfree(data); return ret; } int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, struct ath10k_fw_file *fw_file) { Loading Loading @@ -2637,9 +2647,11 @@ static void ath10k_core_register_work(struct work_struct *work) return; } int ath10k_core_register(struct ath10k *ar, u32 chip_id) int ath10k_core_register(struct ath10k *ar, const struct ath10k_bus_params *bus_params) { ar->chip_id = chip_id; ar->chip_id = bus_params->chip_id; ar->dev_type = bus_params->dev_type; queue_work(ar->workqueue, &ar->register_work); return 0; Loading drivers/net/wireless/ath/ath10k/core.h +13 −1 Original line number Diff line number Diff line Loading @@ -769,6 +769,16 @@ struct ath10k_per_peer_tx_stats { u32 reserved2; }; enum ath10k_dev_type { ATH10K_DEV_TYPE_LL, ATH10K_DEV_TYPE_HL, }; struct ath10k_bus_params { u32 chip_id; enum ath10k_dev_type dev_type; }; struct ath10k { struct ath_common ath_common; struct ieee80211_hw *hw; Loading @@ -779,6 +789,7 @@ struct ath10k { enum ath10k_hw_rev hw_rev; u16 dev_id; u32 chip_id; enum ath10k_dev_type dev_type; u32 target_version; u8 fw_version_major; u32 fw_version_minor; Loading Loading @@ -1051,7 +1062,8 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, const struct ath10k_fw_components *fw_components); int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt); void ath10k_core_stop(struct ath10k *ar); int ath10k_core_register(struct ath10k *ar, u32 chip_id); int ath10k_core_register(struct ath10k *ar, const struct ath10k_bus_params *bus_params); void ath10k_core_unregister(struct ath10k *ar); #endif /* _CORE_H_ */ drivers/net/wireless/ath/ath10k/pci.c +7 −6 Original line number Diff line number Diff line Loading @@ -3420,7 +3420,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, struct ath10k *ar; struct ath10k_pci *ar_pci; enum ath10k_hw_rev hw_rev; u32 chip_id; struct ath10k_bus_params bus_params; bool pci_ps; int (*pci_soft_reset)(struct ath10k *ar); int (*pci_hard_reset)(struct ath10k *ar); Loading Loading @@ -3556,19 +3556,20 @@ static int ath10k_pci_probe(struct pci_dev *pdev, goto err_free_irq; } chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS); if (chip_id == 0xffffffff) { bus_params.dev_type = ATH10K_DEV_TYPE_LL; bus_params.chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS); if (bus_params.chip_id == 0xffffffff) { ath10k_err(ar, "failed to get chip id\n"); goto err_free_irq; } if (!ath10k_pci_chip_is_supported(pdev->device, chip_id)) { if (!ath10k_pci_chip_is_supported(pdev->device, bus_params.chip_id)) { ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n", pdev->device, chip_id); pdev->device, bus_params.chip_id); goto err_free_irq; } ret = ath10k_core_register(ar, chip_id); ret = ath10k_core_register(ar, &bus_params); if (ret) { ath10k_err(ar, "failed to register driver core: %d\n", ret); goto err_free_irq; Loading drivers/net/wireless/ath/ath10k/sdio.c +5 −3 Original line number Diff line number Diff line Loading @@ -1942,7 +1942,8 @@ static int ath10k_sdio_probe(struct sdio_func *func, struct ath10k_sdio *ar_sdio; struct ath10k *ar; enum ath10k_hw_rev hw_rev; u32 chip_id, dev_id_base; u32 dev_id_base; struct ath10k_bus_params bus_params; int ret, i; /* Assumption: All SDIO based chipsets (so far) are QCA6174 based. Loading Loading @@ -2036,9 +2037,10 @@ static int ath10k_sdio_probe(struct sdio_func *func, goto err_free_wq; } bus_params.dev_type = ATH10K_DEV_TYPE_HL; /* TODO: don't know yet how to get chip_id with SDIO */ chip_id = 0; ret = ath10k_core_register(ar, chip_id); bus_params.chip_id = 0; ret = ath10k_core_register(ar, &bus_params); if (ret) { ath10k_err(ar, "failed to register driver core: %d\n", ret); goto err_free_wq; Loading Loading
drivers/net/wireless/ath/ath10k/ahb.c +5 −4 Original line number Diff line number Diff line Loading @@ -758,7 +758,7 @@ static int ath10k_ahb_probe(struct platform_device *pdev) enum ath10k_hw_rev hw_rev; size_t size; int ret; u32 chip_id; struct ath10k_bus_params bus_params; of_id = of_match_device(ath10k_ahb_of_match, &pdev->dev); if (!of_id) { Loading Loading @@ -814,14 +814,15 @@ static int ath10k_ahb_probe(struct platform_device *pdev) ath10k_pci_ce_deinit(ar); chip_id = ath10k_ahb_soc_read32(ar, SOC_CHIP_ID_ADDRESS); if (chip_id == 0xffffffff) { bus_params.dev_type = ATH10K_DEV_TYPE_LL; bus_params.chip_id = ath10k_ahb_soc_read32(ar, SOC_CHIP_ID_ADDRESS); if (bus_params.chip_id == 0xffffffff) { ath10k_err(ar, "failed to get chip id\n"); ret = -ENODEV; goto err_halt_device; } ret = ath10k_core_register(ar, chip_id); ret = ath10k_core_register(ar, &bus_params); if (ret) { ath10k_err(ar, "failed to register driver core: %d\n", ret); goto err_halt_device; Loading
drivers/net/wireless/ath/ath10k/core.c +277 −265 Original line number Diff line number Diff line Loading @@ -693,149 +693,6 @@ static int ath10k_push_board_ext_data(struct ath10k *ar, const void *data, return 0; } static int ath10k_download_board_data(struct ath10k *ar, const void *data, size_t data_len) { u32 board_data_size = ar->hw_params.fw.board_size; u32 address; int ret; ret = ath10k_push_board_ext_data(ar, data, data_len); if (ret) { ath10k_err(ar, "could not push board ext data (%d)\n", ret); goto exit; } ret = ath10k_bmi_read32(ar, hi_board_data, &address); if (ret) { ath10k_err(ar, "could not read board data addr (%d)\n", ret); goto exit; } ret = ath10k_bmi_write_memory(ar, address, data, min_t(u32, board_data_size, data_len)); if (ret) { ath10k_err(ar, "could not write board data (%d)\n", ret); goto exit; } ret = ath10k_bmi_write32(ar, hi_board_data_initialized, 1); if (ret) { ath10k_err(ar, "could not write board data bit (%d)\n", ret); goto exit; } exit: return ret; } static int ath10k_download_cal_file(struct ath10k *ar, const struct firmware *file) { int ret; if (!file) return -ENOENT; if (IS_ERR(file)) return PTR_ERR(file); ret = ath10k_download_board_data(ar, file->data, file->size); if (ret) { ath10k_err(ar, "failed to download cal_file data: %d\n", ret); return ret; } ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cal file downloaded\n"); return 0; } static int ath10k_download_cal_dt(struct ath10k *ar, const char *dt_name) { struct device_node *node; int data_len; void *data; int ret; node = ar->dev->of_node; if (!node) /* Device Tree is optional, don't print any warnings if * there's no node for ath10k. */ return -ENOENT; if (!of_get_property(node, dt_name, &data_len)) { /* The calibration data node is optional */ return -ENOENT; } if (data_len != ar->hw_params.cal_data_len) { ath10k_warn(ar, "invalid calibration data length in DT: %d\n", data_len); ret = -EMSGSIZE; goto out; } data = kmalloc(data_len, GFP_KERNEL); if (!data) { ret = -ENOMEM; goto out; } ret = of_property_read_u8_array(node, dt_name, data, data_len); if (ret) { ath10k_warn(ar, "failed to read calibration data from DT: %d\n", ret); goto out_free; } ret = ath10k_download_board_data(ar, data, data_len); if (ret) { ath10k_warn(ar, "failed to download calibration data from Device Tree: %d\n", ret); goto out_free; } ret = 0; out_free: kfree(data); out: return ret; } static int ath10k_download_cal_eeprom(struct ath10k *ar) { size_t data_len; void *data = NULL; int ret; ret = ath10k_hif_fetch_cal_eeprom(ar, &data, &data_len); if (ret) { if (ret != -EOPNOTSUPP) ath10k_warn(ar, "failed to read calibration data from EEPROM: %d\n", ret); goto out_free; } ret = ath10k_download_board_data(ar, data, data_len); if (ret) { ath10k_warn(ar, "failed to download calibration data from EEPROM: %d\n", ret); goto out_free; } ret = 0; out_free: kfree(data); return ret; } static int ath10k_core_get_board_id_from_otp(struct ath10k *ar) { u32 result, address; Loading Loading @@ -986,64 +843,6 @@ static int ath10k_core_check_dt(struct ath10k *ar) return 0; } static int ath10k_download_and_run_otp(struct ath10k *ar) { u32 result, address = ar->hw_params.patch_load_addr; u32 bmi_otp_exe_param = ar->hw_params.otp_exe_param; int ret; ret = ath10k_download_board_data(ar, ar->running_fw->board_data, ar->running_fw->board_len); if (ret) { ath10k_err(ar, "failed to download board data: %d\n", ret); return ret; } /* OTP is optional */ if (!ar->running_fw->fw_file.otp_data || !ar->running_fw->fw_file.otp_len) { ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %pK otp_len %zd)!\n", ar->running_fw->fw_file.otp_data, ar->running_fw->fw_file.otp_len); return 0; } ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n", address, ar->running_fw->fw_file.otp_len); ret = ath10k_bmi_fast_download(ar, address, ar->running_fw->fw_file.otp_data, ar->running_fw->fw_file.otp_len); if (ret) { ath10k_err(ar, "could not write otp (%d)\n", ret); return ret; } /* As of now pre-cal is valid for 10_4 variants */ if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT || ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE) bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL; ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result); if (ret) { ath10k_err(ar, "could not execute otp (%d)\n", ret); return ret; } ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result); if (!(skip_otp || test_bit(ATH10K_FW_FEATURE_IGNORE_OTP_RESULT, ar->running_fw->fw_file.fw_features)) && result != 0) { ath10k_err(ar, "otp calibration failed: %d", result); return -EINVAL; } return 0; } static int ath10k_download_fw(struct ath10k *ar) { u32 address, data_len; Loading Loading @@ -1236,14 +1035,61 @@ static int ath10k_core_parse_bd_ie_board(struct ath10k *ar, return ret; } static int ath10k_core_search_bd(struct ath10k *ar, const char *boardname, const u8 *data, size_t len) { size_t ie_len; struct ath10k_fw_ie *hdr; int ret = -ENOENT, ie_id; while (len > sizeof(struct ath10k_fw_ie)) { hdr = (struct ath10k_fw_ie *)data; ie_id = le32_to_cpu(hdr->id); ie_len = le32_to_cpu(hdr->len); len -= sizeof(*hdr); data = hdr->data; if (len < ALIGN(ie_len, 4)) { ath10k_err(ar, "invalid length for board ie_id %d ie_len %zu len %zu\n", ie_id, ie_len, len); return -EINVAL; } switch (ie_id) { case ATH10K_BD_IE_BOARD: ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len, boardname); if (ret == -ENOENT) /* no match found, continue */ break; /* either found or error, so stop searching */ goto out; } /* jump over the padding */ ie_len = ALIGN(ie_len, 4); len -= ie_len; data += ie_len; } out: /* return result of parse_bd_ie_board() or -ENOENT */ return ret; } static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar, const char *boardname, const char *fallback_boardname, const char *filename) { size_t len, magic_len, ie_len; struct ath10k_fw_ie *hdr; size_t len, magic_len; const u8 *data; int ret, ie_id; int ret; ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, Loading Loading @@ -1281,69 +1127,23 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar, data += magic_len; len -= magic_len; while (len > sizeof(struct ath10k_fw_ie)) { hdr = (struct ath10k_fw_ie *)data; ie_id = le32_to_cpu(hdr->id); ie_len = le32_to_cpu(hdr->len); len -= sizeof(*hdr); data = hdr->data; if (len < ALIGN(ie_len, 4)) { ath10k_err(ar, "invalid length for board ie_id %d ie_len %zu len %zu\n", ie_id, ie_len, len); ret = -EINVAL; goto err; } switch (ie_id) { case ATH10K_BD_IE_BOARD: ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len, boardname); if (ret == -ENOENT && ar->id.bdf_ext[0] != '\0') { /* try default bdf if variant was not found */ char *s, *v = ",variant="; char boardname2[100]; strlcpy(boardname2, boardname, sizeof(boardname2)); s = strstr(boardname2, v); if (s) *s = '\0'; /* strip ",variant=%s" */ ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len, boardname2); } if (ret == -ENOENT) /* no match found, continue */ break; else if (ret) /* there was an error, bail out */ goto err; /* board data found */ goto out; } /* jump over the padding */ ie_len = ALIGN(ie_len, 4); /* attempt to find boardname in the IE list */ ret = ath10k_core_search_bd(ar, boardname, data, len); len -= ie_len; data += ie_len; } /* if we didn't find it and have a fallback name, try that */ if (ret == -ENOENT && fallback_boardname) ret = ath10k_core_search_bd(ar, fallback_boardname, data, len); out: if (!ar->normal_mode_fw.board_data || !ar->normal_mode_fw.board_len) { if (ret == -ENOENT) { ath10k_err(ar, "failed to fetch board data for %s from %s/%s\n", boardname, ar->hw_params.fw.dir, filename); ret = -ENODATA; goto err; } if (ret) goto err; return 0; err: Loading @@ -1352,12 +1152,12 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar, } static int ath10k_core_create_board_name(struct ath10k *ar, char *name, size_t name_len) size_t name_len, bool with_variant) { /* strlen(',variant=') + strlen(ar->id.bdf_ext) */ char variant[9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH] = { 0 }; if (ar->id.bdf_ext[0] != '\0') if (with_variant && ar->id.bdf_ext[0] != '\0') scnprintf(variant, sizeof(variant), ",variant=%s", ar->id.bdf_ext); Loading Loading @@ -1391,17 +1191,26 @@ static int ath10k_core_create_board_name(struct ath10k *ar, char *name, static int ath10k_core_fetch_board_file(struct ath10k *ar) { char boardname[100]; char boardname[100], fallback_boardname[100]; int ret; ret = ath10k_core_create_board_name(ar, boardname, sizeof(boardname)); ret = ath10k_core_create_board_name(ar, boardname, sizeof(boardname), true); if (ret) { ath10k_err(ar, "failed to create board name: %d", ret); return ret; } ret = ath10k_core_create_board_name(ar, fallback_boardname, sizeof(boardname), false); if (ret) { ath10k_err(ar, "failed to create fallback board name: %d", ret); return ret; } ar->bd_api = 2; ret = ath10k_core_fetch_board_data_api_n(ar, boardname, fallback_boardname, ATH10K_BOARD_API2_FILE); if (!ret) goto success; Loading @@ -1419,6 +1228,207 @@ static int ath10k_core_fetch_board_file(struct ath10k *ar) return 0; } static int ath10k_download_board_data(struct ath10k *ar, const void *data, size_t data_len) { u32 board_data_size = ar->hw_params.fw.board_size; u32 address; int ret; ret = ath10k_push_board_ext_data(ar, data, data_len); if (ret) { ath10k_err(ar, "could not push board ext data (%d)\n", ret); goto exit; } ret = ath10k_bmi_read32(ar, hi_board_data, &address); if (ret) { ath10k_err(ar, "could not read board data addr (%d)\n", ret); goto exit; } ret = ath10k_bmi_write_memory(ar, address, data, min_t(u32, board_data_size, data_len)); if (ret) { ath10k_err(ar, "could not write board data (%d)\n", ret); goto exit; } ret = ath10k_bmi_write32(ar, hi_board_data_initialized, 1); if (ret) { ath10k_err(ar, "could not write board data bit (%d)\n", ret); goto exit; } exit: return ret; } static int ath10k_download_and_run_otp(struct ath10k *ar) { u32 result, address = ar->hw_params.patch_load_addr; u32 bmi_otp_exe_param = ar->hw_params.otp_exe_param; int ret; ret = ath10k_download_board_data(ar, ar->running_fw->board_data, ar->running_fw->board_len); if (ret) { ath10k_err(ar, "failed to download board data: %d\n", ret); return ret; } /* OTP is optional */ if (!ar->running_fw->fw_file.otp_data || !ar->running_fw->fw_file.otp_len) { ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %pK otp_len %zd)!\n", ar->running_fw->fw_file.otp_data, ar->running_fw->fw_file.otp_len); return 0; } ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n", address, ar->running_fw->fw_file.otp_len); ret = ath10k_bmi_fast_download(ar, address, ar->running_fw->fw_file.otp_data, ar->running_fw->fw_file.otp_len); if (ret) { ath10k_err(ar, "could not write otp (%d)\n", ret); return ret; } /* As of now pre-cal is valid for 10_4 variants */ if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT || ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE) bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL; ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result); if (ret) { ath10k_err(ar, "could not execute otp (%d)\n", ret); return ret; } ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result); if (!(skip_otp || test_bit(ATH10K_FW_FEATURE_IGNORE_OTP_RESULT, ar->running_fw->fw_file.fw_features)) && result != 0) { ath10k_err(ar, "otp calibration failed: %d", result); return -EINVAL; } return 0; } static int ath10k_download_cal_file(struct ath10k *ar, const struct firmware *file) { int ret; if (!file) return -ENOENT; if (IS_ERR(file)) return PTR_ERR(file); ret = ath10k_download_board_data(ar, file->data, file->size); if (ret) { ath10k_err(ar, "failed to download cal_file data: %d\n", ret); return ret; } ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cal file downloaded\n"); return 0; } static int ath10k_download_cal_dt(struct ath10k *ar, const char *dt_name) { struct device_node *node; int data_len; void *data; int ret; node = ar->dev->of_node; if (!node) /* Device Tree is optional, don't print any warnings if * there's no node for ath10k. */ return -ENOENT; if (!of_get_property(node, dt_name, &data_len)) { /* The calibration data node is optional */ return -ENOENT; } if (data_len != ar->hw_params.cal_data_len) { ath10k_warn(ar, "invalid calibration data length in DT: %d\n", data_len); ret = -EMSGSIZE; goto out; } data = kmalloc(data_len, GFP_KERNEL); if (!data) { ret = -ENOMEM; goto out; } ret = of_property_read_u8_array(node, dt_name, data, data_len); if (ret) { ath10k_warn(ar, "failed to read calibration data from DT: %d\n", ret); goto out_free; } ret = ath10k_download_board_data(ar, data, data_len); if (ret) { ath10k_warn(ar, "failed to download calibration data from Device Tree: %d\n", ret); goto out_free; } ret = 0; out_free: kfree(data); out: return ret; } static int ath10k_download_cal_eeprom(struct ath10k *ar) { size_t data_len; void *data = NULL; int ret; ret = ath10k_hif_fetch_cal_eeprom(ar, &data, &data_len); if (ret) { if (ret != -EOPNOTSUPP) ath10k_warn(ar, "failed to read calibration data from EEPROM: %d\n", ret); goto out_free; } ret = ath10k_download_board_data(ar, data, data_len); if (ret) { ath10k_warn(ar, "failed to download calibration data from EEPROM: %d\n", ret); goto out_free; } ret = 0; out_free: kfree(data); return ret; } int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, struct ath10k_fw_file *fw_file) { Loading Loading @@ -2637,9 +2647,11 @@ static void ath10k_core_register_work(struct work_struct *work) return; } int ath10k_core_register(struct ath10k *ar, u32 chip_id) int ath10k_core_register(struct ath10k *ar, const struct ath10k_bus_params *bus_params) { ar->chip_id = chip_id; ar->chip_id = bus_params->chip_id; ar->dev_type = bus_params->dev_type; queue_work(ar->workqueue, &ar->register_work); return 0; Loading
drivers/net/wireless/ath/ath10k/core.h +13 −1 Original line number Diff line number Diff line Loading @@ -769,6 +769,16 @@ struct ath10k_per_peer_tx_stats { u32 reserved2; }; enum ath10k_dev_type { ATH10K_DEV_TYPE_LL, ATH10K_DEV_TYPE_HL, }; struct ath10k_bus_params { u32 chip_id; enum ath10k_dev_type dev_type; }; struct ath10k { struct ath_common ath_common; struct ieee80211_hw *hw; Loading @@ -779,6 +789,7 @@ struct ath10k { enum ath10k_hw_rev hw_rev; u16 dev_id; u32 chip_id; enum ath10k_dev_type dev_type; u32 target_version; u8 fw_version_major; u32 fw_version_minor; Loading Loading @@ -1051,7 +1062,8 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, const struct ath10k_fw_components *fw_components); int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt); void ath10k_core_stop(struct ath10k *ar); int ath10k_core_register(struct ath10k *ar, u32 chip_id); int ath10k_core_register(struct ath10k *ar, const struct ath10k_bus_params *bus_params); void ath10k_core_unregister(struct ath10k *ar); #endif /* _CORE_H_ */
drivers/net/wireless/ath/ath10k/pci.c +7 −6 Original line number Diff line number Diff line Loading @@ -3420,7 +3420,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, struct ath10k *ar; struct ath10k_pci *ar_pci; enum ath10k_hw_rev hw_rev; u32 chip_id; struct ath10k_bus_params bus_params; bool pci_ps; int (*pci_soft_reset)(struct ath10k *ar); int (*pci_hard_reset)(struct ath10k *ar); Loading Loading @@ -3556,19 +3556,20 @@ static int ath10k_pci_probe(struct pci_dev *pdev, goto err_free_irq; } chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS); if (chip_id == 0xffffffff) { bus_params.dev_type = ATH10K_DEV_TYPE_LL; bus_params.chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS); if (bus_params.chip_id == 0xffffffff) { ath10k_err(ar, "failed to get chip id\n"); goto err_free_irq; } if (!ath10k_pci_chip_is_supported(pdev->device, chip_id)) { if (!ath10k_pci_chip_is_supported(pdev->device, bus_params.chip_id)) { ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n", pdev->device, chip_id); pdev->device, bus_params.chip_id); goto err_free_irq; } ret = ath10k_core_register(ar, chip_id); ret = ath10k_core_register(ar, &bus_params); if (ret) { ath10k_err(ar, "failed to register driver core: %d\n", ret); goto err_free_irq; Loading
drivers/net/wireless/ath/ath10k/sdio.c +5 −3 Original line number Diff line number Diff line Loading @@ -1942,7 +1942,8 @@ static int ath10k_sdio_probe(struct sdio_func *func, struct ath10k_sdio *ar_sdio; struct ath10k *ar; enum ath10k_hw_rev hw_rev; u32 chip_id, dev_id_base; u32 dev_id_base; struct ath10k_bus_params bus_params; int ret, i; /* Assumption: All SDIO based chipsets (so far) are QCA6174 based. Loading Loading @@ -2036,9 +2037,10 @@ static int ath10k_sdio_probe(struct sdio_func *func, goto err_free_wq; } bus_params.dev_type = ATH10K_DEV_TYPE_HL; /* TODO: don't know yet how to get chip_id with SDIO */ chip_id = 0; ret = ath10k_core_register(ar, chip_id); bus_params.chip_id = 0; ret = ath10k_core_register(ar, &bus_params); if (ret) { ath10k_err(ar, "failed to register driver core: %d\n", ret); goto err_free_wq; Loading