/* * --------------------------------------------------------------------------- * uf_release_firmware_files * * Release all buffers used to store firmware files * * Arguments: * priv Pointer to OS private struct. * * Returns: * None. * --------------------------------------------------------------------------- */ int uf_release_firmware_files(unifi_priv_t *priv) { uf_release_firmware(priv, &priv->fw_loader); uf_release_firmware(priv, &priv->fw_sta); return 0; }
/* * --------------------------------------------------------------------------- * unifi_fw_read_stop * * Called when the HIP driver has finished using the loader or * the firmware file. * The firmware buffer may be released now. * * Arguments: * ospriv Pointer to driver context. * dlpriv The pointer returned by unifi_fw_read_start() * * --------------------------------------------------------------------------- */ void unifi_fw_read_stop(void *ospriv, void *dlpriv) { unifi_priv_t *priv = (unifi_priv_t*)ospriv; struct dlpriv *dl_struct = (struct dlpriv *)dlpriv; func_enter(); if (dl_struct != NULL) { if (dl_struct->dl_data != NULL) { unifi_trace(priv, UDBG2, "Release f/w buffer %p, %d bytes\n", dl_struct->dl_data, dl_struct->dl_len); } uf_release_firmware(priv, dl_struct); } func_exit(); } /* unifi_fw_read_stop() */
/* * --------------------------------------------------------------------------- * uf_request_firmware_files * * Get the firmware files from userspace. * * Arguments: * priv Pointer to OS private struct. * is_fw type of firmware to load (UNIFI_FW_STA/LOADER) * * Returns: * None. * --------------------------------------------------------------------------- */ int uf_request_firmware_files(unifi_priv_t *priv, int is_fw) { /* uses the default method to get the firmware */ const struct firmware *fw_entry; int postfix; #define UNIFI_MAX_FW_PATH_LEN 38 char fw_name[UNIFI_MAX_FW_PATH_LEN]; int r; #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) if (priv->mib_data.length) { vfree(priv->mib_data.data); priv->mib_data.data = NULL; priv->mib_data.length = 0; } #endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT*/ postfix = priv->instance; if (is_fw == UNIFI_FW_STA) { /* Free kernel buffer and reload */ uf_release_firmware(priv, &priv->fw_sta); /* Synergy Adnroid: Support both A03, A04, A05 and fall back to sta.xbv for the default case. */ #ifdef ANDROID_BUILD printk("Unifi: Fetching firmware patch for firmware build %d\n", (int) priv->card_info.fw_build); switch(priv->card_info.fw_build) { case 0: /* Wait untill the firmware build number is known. */ return 0; break; case 611: scnprintf(fw_name, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s", postfix, "a03/sta.xbv"); break; case 657: scnprintf(fw_name, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s", postfix, "a04/sta.xbv"); break; case 743: scnprintf(fw_name, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s", postfix, "a05/sta.xbv"); break; default: scnprintf(fw_name, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s", postfix, "sta.xbv"); printk("Unifi: Unknown firmware build id, defaulting to: %s\n", fw_name); } #else scnprintf(fw_name, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s", postfix, "sta.xbv"); #endif r = request_firmware(&fw_entry, fw_name, priv->unifi_device); if (r == 0) { priv->fw_sta.dl_data = fw_entry->data; priv->fw_sta.dl_len = fw_entry->size; priv->fw_sta.fw_desc = (void *)fw_entry; } else { unifi_trace(priv, UDBG2, "Firmware file not available\n"); } } if (is_fw == UNIFI_FW_LOADER) { /* Free kernel buffer and reload */ uf_release_firmware(priv, &priv->fw_loader); /*scnprintf(fw_name, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s", postfix, "loader.xbv"); r = request_firmware(&fw_entry, fw_name, priv->unifi_device); - Removed to speed up firmware download while running PTest. (To my understanding the fw_loader is not needed for cinderella chips)*/ r = -1; if (r == 0) { priv->fw_loader.dl_data = fw_entry->data; priv->fw_loader.dl_len = fw_entry->size; priv->fw_loader.fw_desc = (void *)fw_entry; } else { unifi_trace(priv, UDBG2, "Loader file not available\n"); } } #ifdef CSR_SME_EMB r = uf_request_mib_file(priv); if (r) { return r; } uf_request_mac_address_file(priv); #endif /* CSR_SME_EMB */ return 0; } /* uf_request_firmware_files() */
int unifi_putest_dl_fw(unifi_priv_t *priv, unsigned char *arg) { #define UF_PUTEST_MAX_FW_FILE_NAME 16 #define UNIFI_MAX_FW_PATH_LEN 32 unsigned int fw_name_length; unsigned char fw_name[UF_PUTEST_MAX_FW_FILE_NAME+1]; unsigned char *name_buffer; int postfix; char fw_path[UNIFI_MAX_FW_PATH_LEN]; const struct firmware *fw_entry; struct dlpriv temp_fw_sta; int r; CsrInt32 csr_r; /* Get the f/w file name length */ if (get_user(fw_name_length, (unsigned int*)(((unifi_putest_command_t*)arg) + 1))) { unifi_error(priv, "unifi_putest_dl_fw: Failed to get the length argument\n"); return -EFAULT; } unifi_trace(priv, UDBG2, "unifi_putest_dl_fw: file name size = %d\n", fw_name_length); /* Sanity check for the f/w file name length */ if (fw_name_length > UF_PUTEST_MAX_FW_FILE_NAME) { unifi_error(priv, "unifi_putest_dl_fw: F/W file name is too long\n"); return -EINVAL; } /* Get the f/w file name */ name_buffer = ((unsigned char*)arg) + sizeof(unifi_putest_command_t) + sizeof(unsigned int); if (copy_from_user(fw_name, (void*)name_buffer, fw_name_length)) { unifi_error(priv, "unifi_putest_dl_fw: Failed to get the file name\n"); return -EFAULT; } fw_name[fw_name_length] = '\0'; unifi_trace(priv, UDBG2, "unifi_putest_dl_fw: file = %s\n", fw_name); /* Keep the existing f/w to a temp, we need to restore it later */ temp_fw_sta = priv->fw_sta; /* Get the putest f/w */ postfix = priv->instance; scnprintf(fw_path, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s", postfix, fw_name); r = request_firmware(&fw_entry, fw_path, priv->unifi_device); if (r == 0) { priv->fw_sta.fw_desc = (void *)fw_entry; priv->fw_sta.dl_data = fw_entry->data; priv->fw_sta.dl_len = fw_entry->size; } else { unifi_error(priv, "Firmware file not available\n"); return -EINVAL; } /* Application may have stopped the XAPs, but they are needed for reset */ csr_r = unifi_start_processors(priv->card); if (csr_r) { unifi_error(priv, "Failed to start XAPs. Hard reset required.\n"); } /* Download the f/w. On UF6xxx this will cause the f/w file to convert * into patch format and download via the ROM boot loader */ csr_r = unifi_download(priv->card, 0x0c00); if (csr_r < 0) { unifi_error(priv, "unifi_putest_dl_fw: failed to download the f/w\n"); goto free_fw; } /* Free the putest f/w... */ free_fw: uf_release_firmware(priv, &priv->fw_sta); /* ... and restore the original f/w */ priv->fw_sta = temp_fw_sta; return convert_csr_error(csr_r); }