wifi: ath11k: support firmware-2.bin
Subsystems (2)
v3 cover wifi: ath11k: support firmware-2.bin
From: Kalle Valo <[email protected]>
We need firmware-2.bin support in ath11k so that we can add ath11k specific meta data to firmware releases, for example feature flags so that ath11k can automatically detect what features the firmware release supports. Also makes it easier and more reliable to update the firmware for PCI devices as it's not possible to mix firmware files, everything will be in one file.
Please review and comment.
v3:
* patch 1: add "bus: mhi: host: ..." to title
* patch 1: add a comment to mhi_fw_load_handler()
* patch 1: check sbl_size
* patch 3: for smooth backwards compatibility don't print an error "failed to load firmware-2.bin: -2"
v2:
https://patchwork.kernel.org/project/linux-wireless/list/?series=727935&state=*&order=date
* mhi_fw_load_handler(): fold two lines into one
* struct mhi_controller_config: document that fbc_download needs to be set
* run pahole struct mhi_controller_config
Anilkumar Kolli (1):
wifi: ath11k: add firmware-2.bin support
Kalle Valo (2):
bus: mhi: host: allow MHI client drivers to provide the firmware via a
pointer
wifi: ath11k: qmi: refactor ath11k_qmi_m3_load()
drivers/bus/mhi/host/boot.c | 34 +++-- drivers/net/wireless/ath/ath11k/Makefile | 3 +- drivers/net/wireless/ath/ath11k/core.c | 8 ++ drivers/net/wireless/ath/ath11k/core.h | 15 +++ drivers/net/wireless/ath/ath11k/fw.c | 157 +++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/fw.h | 27 ++++ drivers/net/wireless/ath/ath11k/mhi.c | 18 ++- drivers/net/wireless/ath/ath11k/qmi.c | 54 +++++--- include/linux/mhi.h | 6 + 9 files changed, 289 insertions(+), 33 deletions(-) create mode 100644 drivers/net/wireless/ath/ath11k/fw.c create mode 100644 drivers/net/wireless/ath/ath11k/fw.h
base-commit: 4ab7f08db5310ded48a5c1f3ec3f2e177ba6b1c2
Signature · 1 line
2.30.2
PATCH v3 1/3 bus: mhi: host: allow MHI client drivers to provide the firmware via a pointer
From: Kalle Valo <[email protected]>
Currently MHI loads the firmware image from the path provided by client devices. ath11k needs to support firmware image embedded along with meta data (named as firmware-2.bin). So allow the client driver to request the firmware file from user space on it's own and provide the firmware image data and size to MHI via a pointer struct mhi_controller::fw_data.
This is an optional feature, if fw_data is NULL MHI load the firmware using the name from struct mhi_controller::fw_image string as before.
Tested with ath11k and WCN6855 hw2.0.
--- drivers/bus/mhi/host/boot.c | 34 +++++++++++++++++++++++++--------- include/linux/mhi.h | 6 ++++++ 2 files changed, 31 insertions(+), 9 deletions(-)
drivers/bus/mhi/host/boot.c +25 -9
@@ -365,12 +365,10 @@ int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl, }static void mhi_firmware_copy (struct mhi_controller *mhi_cntrl, -const struct firmware *firmware, +const u8 *buf,size_t remainder,struct image_info *img_info) { -size_t remainder = firmware->size;size_t to_cpy; -const u8 *buf = firmware->data;struct mhi_buf *mhi_buf = img_info->mhi_buf;struct bhi_vec_entry *bhi_vec = img_info->bhi_vec;
@@ -393,9 +391,10 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)struct device *dev = &mhi_cntrl->mhi_dev->dev;enum mhi_pm_state new_state;const char *fw_name; +const u8 *fw_data;void *buf;dma_addr_t dma_addr; -size_t size; +size_t size, fw_sz;int i, ret;if (MHI_PM_IN_ERROR_STATE (mhi_cntrl->pm_state)) {
@@ -425,6 +424,20 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) fw_name = (mhi_cntrl->ee ==MHI_EE_EDL ) ? mhi_cntrl->edl_image : mhi_cntrl->fw_image; +/* check if the driver has already provided the firmware data */ +if (!fw_name && mhi_cntrl->fbc_download && + mhi_cntrl->fw_data && mhi_cntrl->fw_sz) { +if (!mhi_cntrl->sbl_size) { +dev_err (dev,"fw_data provided but no sbl_size\n" ); + goto error_fw_load; + } + + size = mhi_cntrl->sbl_size; + fw_data = mhi_cntrl->fw_data; + fw_sz = mhi_cntrl->fw_sz; + goto skip_req_fw; + } +if (!fw_name || (mhi_cntrl->fbc_download && (!mhi_cntrl->sbl_size || !mhi_cntrl->seg_len))) { dev_err(dev,
@@ -444,6 +457,10 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)if (size > firmware->size) size = firmware->size; + fw_data = firmware->data; + fw_sz = firmware->size; + +skip_req_fw: buf =dma_alloc_coherent (mhi_cntrl->cntrl_dev, size, &dma_addr,GFP_KERNEL );if (!buf) {
@@ -452,7 +469,7 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) }/* Download image using BHI */ -memcpy (buf, firmware->data, size); +memcpy (buf, fw_data, size); ret =mhi_fw_load_bhi (mhi_cntrl, dma_addr, size);dma_free_coherent (mhi_cntrl->cntrl_dev, size, buf, dma_addr);
@@ -464,7 +481,7 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) }/* Wait for ready since EDL image was loaded */ -if (fw_name == mhi_cntrl->edl_image) { +if (fw_name && fw_name == mhi_cntrl->edl_image) {release_firmware (firmware); goto fw_load_ready_state; }
@@ -478,15 +495,14 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)* device transitioning into MHI READY state */ if (mhi_cntrl->fbc_download) { - ret =mhi_alloc_bhie_table (mhi_cntrl, &mhi_cntrl->fbc_image, - firmware->size); + ret =mhi_alloc_bhie_table (mhi_cntrl, &mhi_cntrl->fbc_image, fw_sz);if (ret) {release_firmware (firmware); goto error_fw_load; }/* Load the firmware into BHIE vec table */ -mhi_firmware_copy (mhi_cntrl, firmware, mhi_cntrl->fbc_image); +mhi_firmware_copy (mhi_cntrl, fw_data, fw_sz, mhi_cntrl->fbc_image); }release_firmware (firmware);
include/linux/mhi.h +6 -0
@@ -299,6 +299,10 @@ struct mhi_controller_config {* @iova_start: IOMMU starting address for data (required) * @iova_stop: IOMMU stop address for data (required) * @fw_image: Firmware image name for normal booting (optional) +* @fw_data: Firmware image data content for normal booting, used only +* if fw_image is NULL (optional) +* @fw_sz: Firmware image data size for normal booting, used only if fw_image +* is NULL and fbc_download is true (optional) * @edl_image: Firmware image name for emergency download mode (optional) * @rddm_size: RAM dump size that host should allocate for debugging purpose * @sbl_size: SBL image size downloaded through BHIe (optional)
@@ -384,6 +388,8 @@ struct mhi_controller {dma_addr_t iova_start;dma_addr_t iova_stop;const char *fw_image; +const u8 *fw_data; +size_t fw_sz;const char *edl_image;size_t rddm_size;size_t sbl_size;
Signature · 1 line
2.30.2
Re: [PATCH v3 1/3] bus: mhi: host: allow MHI client drivers to provide the firmware via a pointer
Quoted 122 lines · Kalle Valo
From: Kalle Valo <[email protected]>
Currently MHI loads the firmware image from the path provided by client devices. ath11k needs to support firmware image embedded along with meta data (named as firmware-2.bin). So allow the client driver to request the firmware file from user space on it's own and provide the firmware image data and size to MHI via a pointer struct
mhi_controller::fw_data.This is an optional feature, if
fw_datais NULL MHI load the firmware using the name from structmhi_controller::fw_imagestring as before.Tested with ath11k and WCN6855 hw2.0.
Signed-off-by Kalle Valo <[email protected]>--- drivers/bus/mhi/host/boot.c | 34 +++++++++++++++++++++++++--------- include/linux/mhi.h | 6 ++++++ 2 files changed, 31 insertions(+), 9 deletions(-)drivers/bus/mhi/host/boot.c +25
-9@@ -365,12 +365,10 @@ int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl, }static void mhi_firmware_copy (struct mhi_controller *mhi_cntrl, -const struct firmware *firmware, +const u8 *buf,size_t remainder,struct image_info *img_info) { -size_t remainder = firmware->size;size_t to_cpy; -const u8 *buf = firmware->data;struct mhi_buf *mhi_buf = img_info->mhi_buf;struct bhi_vec_entry *bhi_vec = img_info->bhi_vec;@@ -393,9 +391,10 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)struct device *dev = &mhi_cntrl->mhi_dev->dev;enum mhi_pm_state new_state;const char *fw_name; +const u8 *fw_data;void *buf;dma_addr_t dma_addr; -size_t size; +size_t size, fw_sz;int i, ret;if (MHI_PM_IN_ERROR_STATE (mhi_cntrl->pm_state)) {@@ -425,6 +424,20 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) fw_name = (mhi_cntrl->ee ==MHI_EE_EDL ) ? mhi_cntrl->edl_image : mhi_cntrl->fw_image; +/* check if the driver has already provided the firmware data */ +if (!fw_name && mhi_cntrl->fbc_download && + mhi_cntrl->fw_data && mhi_cntrl->fw_sz) { +if (!mhi_cntrl->sbl_size) { +dev_err (dev,"fw_data provided but no sbl_size\n" ); + goto error_fw_load; + } + + size = mhi_cntrl->sbl_size; + fw_data = mhi_cntrl->fw_data; + fw_sz = mhi_cntrl->fw_sz; + goto skip_req_fw; + } +if (!fw_name || (mhi_cntrl->fbc_download && (!mhi_cntrl->sbl_size || !mhi_cntrl->seg_len))) { dev_err(dev,@@ -444,6 +457,10 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)if (size > firmware->size) size = firmware->size; + fw_data = firmware->data; + fw_sz = firmware->size; + +skip_req_fw: buf =dma_alloc_coherent (mhi_cntrl->cntrl_dev, size, &dma_addr,GFP_KERNEL );if (!buf) {@@ -452,7 +469,7 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) }/* Download image using BHI */ -memcpy (buf, firmware->data, size); +memcpy (buf, fw_data, size); ret =mhi_fw_load_bhi (mhi_cntrl, dma_addr, size);dma_free_coherent (mhi_cntrl->cntrl_dev, size, buf, dma_addr);@@ -464,7 +481,7 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) }/* Wait for ready since EDL image was loaded */ -if (fw_name == mhi_cntrl->edl_image) { +if (fw_name && fw_name == mhi_cntrl->edl_image) {release_firmware (firmware); goto fw_load_ready_state; }@@ -478,15 +495,14 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)* device transitioning into MHI READY state */ if (mhi_cntrl->fbc_download) { - ret =mhi_alloc_bhie_table (mhi_cntrl, &mhi_cntrl->fbc_image, - firmware->size); + ret =mhi_alloc_bhie_table (mhi_cntrl, &mhi_cntrl->fbc_image, fw_sz);if (ret) {release_firmware (firmware); goto error_fw_load; }/* Load the firmware into BHIE vec table */ -mhi_firmware_copy (mhi_cntrl, firmware, mhi_cntrl->fbc_image); +mhi_firmware_copy (mhi_cntrl, fw_data, fw_sz, mhi_cntrl->fbc_image); }release_firmware (firmware);include/linux/mhi.h +0
-0
include/linux/mhi.h struct mhi_controller_config { · line 303
Quoted 5 lines
include/linux/mhi.h +2
-0@@ -299,6 +299,10 @@ struct mhi_controller_config {* @iova_start: IOMMU starting address for data (required) * @iova_stop: IOMMU stop address for data (required) * @fw_image: Firmware image name for normal booting (optional) +* @fw_data: Firmware image data content for normal booting, used only +* if fw_image is NULL (optional)
It looks like your implementation requires fbc_download to be set, and while you mention that for fw_sz, you don't mention it here. While I think this would be useful for non-fbc usecases, we don't have that use currently.
I think documenting the fbc_download requirement and letting the usecase that needs this for non-fbc extend it is reasonable.
With this,
Quoted 14 lines
include/linux/mhi.h +4
-0+* @fw_sz: Firmware image data size for normal booting, used only if fw_image +* is NULL and fbc_download is true (optional) * @edl_image: Firmware image name for emergency download mode (optional) * @rddm_size: RAM dump size that host should allocate for debugging purpose * @sbl_size: SBL image size downloaded through BHIe (optional) @@ -384,6 +388,8 @@ struct mhi_controller {dma_addr_t iova_start;dma_addr_t iova_stop;const char *fw_image; +const u8 *fw_data; +size_t fw_sz;const char *edl_image;size_t rddm_size;size_t sbl_size;
Signature · 3 lines
ath11k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath11k
Re: [PATCH v3 1/3] bus: mhi: host: allow MHI client drivers to provide the firmware via a pointer
Quoted 5 lines · Jeffrey Hugo
Quoted 5 lines
include/linux/mhi.h +0
-0@@ -299,6 +299,10 @@ struct mhi_controller_config {* @iova_start: IOMMU starting address for data (required) * @iova_stop: IOMMU stop address for data (required)
Quoted 8 lines
include/linux/mhi.h struct mhi_controller_config { · line 303
Quoted 3 lines
include/linux/mhi.h +2
-0* @fw_image: Firmware image name for normal booting (optional) +* @fw_data: Firmware image data content for normal booting, used only +* if fw_image is NULL (optional) It looks like your implementation requires
fbc_downloadto be set, and while you mention that forfw_sz, you don't mention it here. While I think this would be useful for non-fbc usecases, we don't have that use currently.
Thanks for the review. I submitted v4 to fix this.
Signature · 3 lines
https://patchwork.kernel.org/project/linux-wireless/list/ https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
Re: [PATCH v3 1/3] bus: mhi: host: allow MHI client drivers to provide the firmware via a pointer
In reply to Kalle ValoQuoted 8 lines · Kalle Valo
From: Kalle Valo <[email protected]>
Currently MHI loads the firmware image from the path provided by client devices. ath11k needs to support firmware image embedded along with meta data (named as firmware-2.bin). So allow the client driver to request the firmware file from user space on it's own and provide the firmware image data and size to MHI via a pointer struct
mhi_controller::fw_data.
Quoted 6 lines
This is an optional feature, if
fw_datais NULL MHI load the firmware using the name from structmhi_controller::fw_imagestring as before.Tested with ath11k and WCN6855 hw2.0.
Signed-off-by Kalle Valo <[email protected]>
- Mani
Quoted 131 lines
--- drivers/bus/mhi/host/boot.c | 34 +++++++++++++++++++++++++--------- include/linux/mhi.h | 6 ++++++ 2 files changed, 31 insertions(+), 9 deletions(-)drivers/bus/mhi/host/boot.c +25
-9@@ -365,12 +365,10 @@ int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl, }static void mhi_firmware_copy (struct mhi_controller *mhi_cntrl, -const struct firmware *firmware, +const u8 *buf,size_t remainder,struct image_info *img_info) { -size_t remainder = firmware->size;size_t to_cpy; -const u8 *buf = firmware->data;struct mhi_buf *mhi_buf = img_info->mhi_buf;struct bhi_vec_entry *bhi_vec = img_info->bhi_vec;@@ -393,9 +391,10 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)struct device *dev = &mhi_cntrl->mhi_dev->dev;enum mhi_pm_state new_state;const char *fw_name; +const u8 *fw_data;void *buf;dma_addr_t dma_addr; -size_t size; +size_t size, fw_sz;int i, ret;if (MHI_PM_IN_ERROR_STATE (mhi_cntrl->pm_state)) {@@ -425,6 +424,20 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) fw_name = (mhi_cntrl->ee ==MHI_EE_EDL ) ? mhi_cntrl->edl_image : mhi_cntrl->fw_image; +/* check if the driver has already provided the firmware data */ +if (!fw_name && mhi_cntrl->fbc_download && + mhi_cntrl->fw_data && mhi_cntrl->fw_sz) { +if (!mhi_cntrl->sbl_size) { +dev_err (dev,"fw_data provided but no sbl_size\n" ); + goto error_fw_load; + } + + size = mhi_cntrl->sbl_size; + fw_data = mhi_cntrl->fw_data; + fw_sz = mhi_cntrl->fw_sz; + goto skip_req_fw; + } +if (!fw_name || (mhi_cntrl->fbc_download && (!mhi_cntrl->sbl_size || !mhi_cntrl->seg_len))) { dev_err(dev,@@ -444,6 +457,10 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)if (size > firmware->size) size = firmware->size; + fw_data = firmware->data; + fw_sz = firmware->size; + +skip_req_fw: buf =dma_alloc_coherent (mhi_cntrl->cntrl_dev, size, &dma_addr,GFP_KERNEL );if (!buf) {@@ -452,7 +469,7 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) }/* Download image using BHI */ -memcpy (buf, firmware->data, size); +memcpy (buf, fw_data, size); ret =mhi_fw_load_bhi (mhi_cntrl, dma_addr, size);dma_free_coherent (mhi_cntrl->cntrl_dev, size, buf, dma_addr);@@ -464,7 +481,7 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) }/* Wait for ready since EDL image was loaded */ -if (fw_name == mhi_cntrl->edl_image) { +if (fw_name && fw_name == mhi_cntrl->edl_image) {release_firmware (firmware); goto fw_load_ready_state; }@@ -478,15 +495,14 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)* device transitioning into MHI READY state */ if (mhi_cntrl->fbc_download) { - ret =mhi_alloc_bhie_table (mhi_cntrl, &mhi_cntrl->fbc_image, - firmware->size); + ret =mhi_alloc_bhie_table (mhi_cntrl, &mhi_cntrl->fbc_image, fw_sz);if (ret) {release_firmware (firmware); goto error_fw_load; }/* Load the firmware into BHIE vec table */ -mhi_firmware_copy (mhi_cntrl, firmware, mhi_cntrl->fbc_image); +mhi_firmware_copy (mhi_cntrl, fw_data, fw_sz, mhi_cntrl->fbc_image); }release_firmware (firmware);include/linux/mhi.h +6
-0@@ -299,6 +299,10 @@ struct mhi_controller_config {* @iova_start: IOMMU starting address for data (required) * @iova_stop: IOMMU stop address for data (required) * @fw_image: Firmware image name for normal booting (optional) +* @fw_data: Firmware image data content for normal booting, used only +* if fw_image is NULL (optional) +* @fw_sz: Firmware image data size for normal booting, used only if fw_image +* is NULL and fbc_download is true (optional) * @edl_image: Firmware image name for emergency download mode (optional) * @rddm_size: RAM dump size that host should allocate for debugging purpose * @sbl_size: SBL image size downloaded through BHIe (optional) @@ -384,6 +388,8 @@ struct mhi_controller {dma_addr_t iova_start;dma_addr_t iova_stop;const char *fw_image; +const u8 *fw_data; +size_t fw_sz;const char *edl_image;size_t rddm_size;size_t sbl_size;Signature · 1 line
2.30.2
Signature · 1 line
மணிவண்ணன் சதாசிவம்
PATCH v3 2/3 wifi: ath11k: qmi: refactor ath11k_qmi_m3_load()
In reply to Kalle ValoFrom: Kalle Valo <[email protected]>
Simple refactoring to make it easier to add firmware-2.bin support in the following patch.
Earlier ath11k_qmi_m3_load() supported changing m3.bin contents while ath11k is running. But that's not going to actually work, m3.bin is supposed to the be same during the lifetime of ath11k, for example we don't support changing the firmware capabilities on the fly. Due to this ath11k requests m3.bin firmware file first and only then checks m3_mem->vaddr, so we are basically requesting the firmware file even if it's not needed. Reverse the code so that m3_mem buffer is checked first, and only if it doesn't exist, then m3.bin is requested from user space.
Checking for m3_mem->size is redundant when m3_mem->vaddr is NULL, we would not be able to use the buffer in that case. So remove the check for size.
Simplify the exit handling and use 'goto out'.
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.9
--- drivers/net/wireless/ath/ath11k/qmi.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
drivers/net/wireless/ath/ath11k/qmi.c +11 -7
@@ -2493,6 +2493,10 @@ static int ath11k_qmi_m3_load(struct ath11k_base *ab)char path[100 ];int ret; +if (m3_mem->vaddr) +/* m3 firmware buffer is already available in the DMA buffer */ +return 0 ; + fw =ath11k_core_firmware_request (ab,ATH11K_M3_FILE );if (IS_ERR (fw)) { ret =PTR_ERR (fw);
@@ -2502,25 +2506,25 @@ static int ath11k_qmi_m3_load(struct ath11k_base *ab)return ret; } -if (m3_mem->vaddr || m3_mem->size) - goto skip_m3_alloc; - m3_mem->vaddr =dma_alloc_coherent (ab->dev, fw->size, &m3_mem->paddr,GFP_KERNEL );if (!m3_mem->vaddr) {ath11k_err (ab,"failed to allocate memory for M3 with size %zu\n" , fw->size); -release_firmware (fw); -return -ENOMEM ; + ret = -ENOMEM ; + goto out; } -skip_m3_alloc:memcpy (m3_mem->vaddr, fw->data, fw->size); m3_mem->size = fw->size; + + ret =0 ; + +out:release_firmware (fw); -return 0 ; +return ret; }static void ath11k_qmi_m3_free (struct ath11k_base *ab)
Signature · 1 line
2.30.2
PATCH v3 3/3 wifi: ath11k: add firmware-2.bin support
In reply to Kalle ValoFrom: Anilkumar Kolli <[email protected]>
Firmware IE containers can dynamically provide various information what firmware supports. Also it can embed more than one image so updating firmware is easy, user just needs to update one file in /lib/firmware/.
The firmware API 2 or higher will use the IE container format, the current API 1 will not use the new format but it still is supported for some time. Firmware API 2 files are named as firmware-2.bin (which contains both amss.bin and m3.bin images) and API 1 files are amss.bin and m3.bin.
Currently ath11k PCI driver provides firmware binary (amss.bin) path to MHI driver, MHI driver reads firmware from filesystem and boots it. Add provision to read firmware files from ath11k driver and provide the amss.bin firmware data and size to MHI using a pointer.
Currently enum ath11k_fw_features is empty, the patches adding features will add the flags.
With AHB devices there's no amss.bin or m3.bin, so no changes in how AHB firmware files are used. But AHB devices can use future additions to the meta data, for example in enum ath11k_fw_features.
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.9
--- drivers/net/wireless/ath/ath11k/Makefile | 3 +- drivers/net/wireless/ath/ath11k/core.c | 8 ++ drivers/net/wireless/ath/ath11k/core.h | 15 +++ drivers/net/wireless/ath/ath11k/fw.c | 157 +++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/fw.h | 27 ++++ drivers/net/wireless/ath/ath11k/mhi.c | 18 ++- drivers/net/wireless/ath/ath11k/qmi.c | 36 ++++-- 7 files changed, 247 insertions(+), 17 deletions(-) create mode 100644 drivers/net/wireless/ath/ath11k/fw.c create mode 100644 drivers/net/wireless/ath/ath11k/fw.h
drivers/net/wireless/ath/ath11k/Makefile +2 -1
@@ -17,7 +17,8 @@ ath11k-y += core.o \ peer.o \ dbring.o \ hw.o \ - pcic.o + pcic.o \ + fw.o ath11k-$(CONFIG_ATH11K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o ath11k-$(CONFIG_NL80211_TESTMODE) += testmode.o
drivers/net/wireless/ath/ath11k/core.c +8 -0
@@ -16,6 +16,7 @@#include "debug.h" #include "hif.h" #include "wow.h" +#include "fw.h" unsigned int ath11k_debug_mask;EXPORT_SYMBOL (ath11k_debug_mask);
@@ -1942,6 +1943,12 @@ int ath11k_core_pre_init(struct ath11k_base *ab)return ret; } + ret =ath11k_fw_pre_init (ab); +if (ret) { +ath11k_err (ab,"failed to pre init firmware: %d" , ret); +return ret; + } +return 0 ; }EXPORT_SYMBOL (ath11k_core_pre_init);
@@ -1972,6 +1979,7 @@ void ath11k_core_deinit(struct ath11k_base *ab)ath11k_hif_power_down (ab);ath11k_mac_destroy (ab);ath11k_core_soc_destroy (ab); +ath11k_fw_destroy (ab); }EXPORT_SYMBOL (ath11k_core_deinit);
drivers/net/wireless/ath/ath11k/core.h +15 -0
@@ -15,6 +15,8 @@#include <linux/ctype.h> #include <linux/rhashtable.h> #include <linux/average.h> +#include <linux/firmware.h> +#include "qmi.h" #include "htc.h" #include "wmi.h"
@@ -29,6 +31,7 @@#include "dbring.h" #include "spectral.h" #include "wow.h" +#include "fw.h" #define SM (_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -978,6 +981,18 @@ struct ath11k_base {const struct ath11k_pci_ops *ops; } pci; +struct { +u32 api_version; + +const struct firmware *fw; +const u8 *amss_data; +size_t amss_len; +const u8 *m3_data; +size_t m3_len; + + DECLARE_BITMAP(fw_features, ATH11K_FW_FEATURE_COUNT); + } fw; +/* must be last */ u8 drv_priv[]__aligned(sizeof(void *)) ; };
drivers/net/wireless/ath/ath11k/fw.c new file +157 -0
157 lines not on this page · raw message
drivers/net/wireless/ath/ath11k/fw.h new file +27 -0
@@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause-Clear */ +/* +* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. +*/ + +#ifndef ATH11K_FW_H +#define ATH11K_FW_H + +#define ATH11K_FW_API2_FILE "firmware-2.bin" +#define ATH11K_FIRMWARE_MAGIC "QCOM-ATH11K-FW" + +enum ath11k_fw_ie_type { +ATH11K_FW_IE_TIMESTAMP =0 , +ATH11K_FW_IE_FEATURES =1 , +ATH11K_FW_IE_AMSS_IMAGE =2 , +ATH11K_FW_IE_M3_IMAGE =3 , +}; + +enum ath11k_fw_features { +/* keep last */ +ATH11K_FW_FEATURE_COUNT , +}; + +int ath11k_fw_pre_init (struct ath11k_base *ab); +void ath11k_fw_destroy (struct ath11k_base *ab); + +#endif /* ATH11K_FW_H */
drivers/net/wireless/ath/ath11k/mhi.c +13 -5
@@ -6,6 +6,7 @@#include <linux/msi.h> #include <linux/pci.h> +#include <linux/firmware.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/ioport.h>
@@ -389,16 +390,23 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)if (!mhi_ctrl)return -ENOMEM ; -ath11k_core_create_firmware_path (ab,ATH11K_AMSS_FILE , - ab_pci->amss_path, -sizeof (ab_pci->amss_path)); - ab_pci->mhi_ctrl = mhi_ctrl; mhi_ctrl->cntrl_dev = ab->dev; - mhi_ctrl->fw_image = ab_pci->amss_path; mhi_ctrl->regs = ab->mem; mhi_ctrl->reg_len = ab->mem_len; +if (ab->fw.amss_data && ab->fw.amss_len >0 ) { +/* use MHI firmware file from firmware-N.bin */ + mhi_ctrl->fw_data = ab->fw.amss_data; + mhi_ctrl->fw_sz = ab->fw.amss_len; + }else { +/* use the old separate mhi.bin MHI firmware file */ +ath11k_core_create_firmware_path (ab,ATH11K_AMSS_FILE , + ab_pci->amss_path, +sizeof (ab_pci->amss_path)); + mhi_ctrl->fw_image = ab_pci->amss_path; + } + ret =ath11k_mhi_get_msi (ab_pci);if (ret) {ath11k_err (ab,"failed to get msi for mhi\n" );
drivers/net/wireless/ath/ath11k/qmi.c +25 -11
@@ -2489,25 +2489,39 @@ static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab,static int ath11k_qmi_m3_load (struct ath11k_base *ab) {struct m3_mem_region *m3_mem = &ab->qmi.m3_mem; -const struct firmware *fw; +const struct firmware *fw =NULL ; +const void *m3_data;char path[100 ]; +size_t m3_len;int ret;if (m3_mem->vaddr)/* m3 firmware buffer is already available in the DMA buffer */ return 0 ; - fw =ath11k_core_firmware_request (ab,ATH11K_M3_FILE ); -if (IS_ERR (fw)) { - ret =PTR_ERR (fw); -ath11k_core_create_firmware_path (ab,ATH11K_M3_FILE , - path,sizeof (path)); -ath11k_err (ab,"failed to load %s: %d\n" , path, ret); -return ret; +if (ab->fw.m3_data && ab->fw.m3_len >0 ) { +/* firmware-N.bin had a m3 firmware file so use that */ + m3_data = ab->fw.m3_data; + m3_len = ab->fw.m3_len; + }else { +/* No m3 file in firmware-N.bin so try to request old +* separate m3.bin. +*/ + fw =ath11k_core_firmware_request (ab,ATH11K_M3_FILE ); +if (IS_ERR (fw)) { + ret =PTR_ERR (fw); +ath11k_core_create_firmware_path (ab,ATH11K_M3_FILE , + path,sizeof (path)); +ath11k_err (ab,"failed to load %s: %d\n" , path, ret); +return ret; + } + + m3_data = fw->data; + m3_len = fw->size; } m3_mem->vaddr =dma_alloc_coherent (ab->dev, - fw->size, &m3_mem->paddr, + m3_len, &m3_mem->paddr,GFP_KERNEL );if (!m3_mem->vaddr) { ath11k_err(ab, "failed to allocate memory for M3 with size %zu\n",
@@ -2516,8 +2530,8 @@ static int ath11k_qmi_m3_load(struct ath11k_base *ab) goto out; } -memcpy (m3_mem->vaddr, fw->data, fw->size); - m3_mem->size = fw->size; +memcpy (m3_mem->vaddr, m3_data, m3_len); + m3_mem->size = m3_len; ret =0 ;
Signature · 1 line
2.30.2