[PATCH 3/3] ath10k: implement firmware IE container support
Michal Kazior
michal.kazior at tieto.com
Thu Sep 26 01:46:16 EDT 2013
On 25 September 2013 23:08, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> +static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
> +{
> + size_t magic_len, len, ie_len;
> + struct ath10k_fw_ie *hdr;
> + const u8 *data;
> + int ie_id, i, index, bit;
> + __le32 *timestamp;
> +
> + ar->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, name);
> + if (IS_ERR(ar->firmware)) {
> + ath10k_err("Could not fetch firmware file '%s': %ld\n",
> + name, PTR_ERR(ar->firmware));
> + return PTR_ERR(ar->firmware);
> + }
> +
> + data = ar->firmware->data;
> + len = ar->firmware->size;
> +
> + /* magic also includes the null byte, check that as well */
> + magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1;
> +
> + if (len < magic_len) {
> + ath10k_err("firmware image too small to contain magic: %d\n",
> + len);
> + return -EINVAL;
> + }
> +
> + if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) {
> + ath10k_err("Invalid firmware magic\n");
> + return -EINVAL;
> + }
> +
> + /* jump over the padding */
> + magic_len = ALIGN(magic_len, 4);
> +
> + len -= magic_len;
> + data += magic_len;
> +
> + /* loop elements */
> + 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 += sizeof(*hdr);
> +
> + if (len < ie_len) {
> + ath10k_err("Invalid length for FW IE %d (%d < %d)\n",
> + ie_id, len, ie_len);
> + return -EINVAL;
> + }
> +
> + switch (ie_id) {
> + case ATH10K_FW_IE_FW_VERSION:
> + if (ie_len > sizeof(ar->hw->wiphy->fw_version) - 1)
> + break;
> +
> + memcpy(ar->hw->wiphy->fw_version, data, ie_len);
> + ar->hw->wiphy->fw_version[ie_len] = '\0';
> +
> + ath10k_dbg(ATH10K_DBG_BOOT,
> + "found fw version %s\n",
> + ar->hw->wiphy->fw_version);
> + break;
> + case ATH10K_FW_IE_TIMESTAMP:
> + if (ie_len != sizeof(u32))
> + break;
> +
> + timestamp = (__le32 *)data;
> +
> + ath10k_dbg(ATH10K_DBG_BOOT, "found fw timestamp %d\n",
> + le32_to_cpup(timestamp));
> + break;
> + case ATH10K_FW_IE_FEATURES:
> + ath10k_dbg(ATH10K_DBG_BOOT,
> + "found firmware features ie (%zd B)\n",
> + ie_len);
> +
> + for (i = 0; i < ATH10K_FW_FEATURE_COUNT; i++) {
> + index = i / 8;
> + bit = i % 8;
> +
> + if (index == ie_len)
> + break;
> +
> + if (data[index] & (1 << bit))
> + __set_bit(i, ar->fw_features);
> + }
> +
> + ath10k_dbg_dump(ATH10K_DBG_BOOT, "features", "",
> + ar->fw_features,
> + sizeof(ar->fw_features));
> + break;
> + case ATH10K_FW_IE_FW_IMAGE:
> + ath10k_dbg(ATH10K_DBG_BOOT,
> + "found fw image ie (%zd B)\n",
> + ie_len);
> +
> + ar->firmware_data = data;
> + ar->firmware_len = ie_len;
> +
> + break;
> + case ATH10K_FW_IE_OTP_IMAGE:
> + ath10k_dbg(ATH10K_DBG_BOOT,
> + "found otp image ie (%zd B)\n",
> + ie_len);
> +
> + ar->otp_data = data;
> + ar->otp_len = ie_len;
> +
> + break;
> + default:
> + ath10k_warn("Unknown FW IE: %u\n",
> + le32_to_cpu(hdr->id));
> + break;
> + }
> +
> + /* jump over the padding */
> + ie_len = ALIGN(ie_len, 4);
> +
> + len -= ie_len;
> + data += ie_len;
> + };
> +
> + return 0;
> +}
> +
> +static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
> +{
> + int ret;
> +
> + ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE);
> + if (ret == 0) {
> + ar->fw_api = 2;
> + goto out;
> + }
Did you skip board file intentionally?
Michał.
More information about the ath10k
mailing list