Exemplo n.º 1
0
/*
 * ---------------------------------------------------------------------------
 *  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;
}
Exemplo n.º 2
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() */
Exemplo n.º 3
0
/*
 * ---------------------------------------------------------------------------
 *  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() */
Exemplo n.º 4
0
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);
}