EXPORT_SYMBOL_GPL(qca_send_pre_shutdown_cmd);
 
 static void qca_tlv_check_data(struct qca_fw_config *config,
-               const struct firmware *fw, enum qca_btsoc_type soc_type)
+               u8 *fw_data, enum qca_btsoc_type soc_type)
 {
        const u8 *data;
        u32 type_len;
        struct tlv_type_nvm *tlv_nvm;
        uint8_t nvm_baud_rate = config->user_baud_rate;
 
-       tlv = (struct tlv_type_hdr *)fw->data;
+       tlv = (struct tlv_type_hdr *)fw_data;
 
        type_len = le32_to_cpu(tlv->type_len);
        length = (type_len >> 8) & 0x00ffffff;
                                 enum qca_btsoc_type soc_type)
 {
        const struct firmware *fw;
+       u8 *data;
        const u8 *segment;
-       int ret, remain, i = 0;
+       int ret, size, remain, i = 0;
 
        bt_dev_info(hdev, "QCA Downloading %s", config->fwname);
 
                return ret;
        }
 
-       qca_tlv_check_data(config, fw, soc_type);
+       size = fw->size;
+       data = vmalloc(fw->size);
+       if (!data) {
+               bt_dev_err(hdev, "QCA Failed to allocate memory for file: %s",
+                          config->fwname);
+               release_firmware(fw);
+               return -ENOMEM;
+       }
+
+       memcpy(data, fw->data, size);
+       release_firmware(fw);
+
+       qca_tlv_check_data(config, data, soc_type);
 
-       segment = fw->data;
-       remain = fw->size;
+       segment = data;
+       remain = size;
        while (remain > 0) {
                int segsize = min(MAX_SIZE_PER_TLV_SEGMENT, remain);
 
                ret = qca_inject_cmd_complete_event(hdev);
 
 out:
-       release_firmware(fw);
+       vfree(data);
 
        return ret;
 }