[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