iwlwifi: mvm: prepare infrastructure for more TLV flags
authorEran Harary <eran.harary@intel.com>
Thu, 20 Feb 2014 09:00:01 +0000 (11:00 +0200)
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Sun, 23 Feb 2014 19:32:22 +0000 (21:32 +0200)
We use the TLV flags as a handshake between the firmware
and the driver. These flags allow the firmware to advertise
its capabilities and API version.
Since we are running short of bits, we add a new
infrastructure which is more scalable, yet backward
compatible.

We make now the difference between API changes and the
capabilities. Both can have an index which allows to scale
at will.

Signed-off-by: Eran Harary <eran.harary@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
drivers/net/wireless/iwlwifi/iwl-drv.c
drivers/net/wireless/iwlwifi/iwl-fw-file.h
drivers/net/wireless/iwlwifi/iwl-fw.h

index 662d9936485c409bdc7c759d1f8d10936ef7da40..d49e9b9ac06a8a12f8c232ea957b41c79ade9009 100644 (file)
@@ -404,6 +404,38 @@ static int iwl_set_default_calib(struct iwl_drv *drv, const u8 *data)
        return 0;
 }
 
+static int iwl_set_ucode_api_flags(struct iwl_drv *drv, const u8 *data,
+                                  struct iwl_ucode_capabilities *capa)
+{
+       const struct iwl_ucode_api *ucode_api = (void *)data;
+       u32 api_index = le32_to_cpu(ucode_api->api_index);
+
+       if (api_index >= IWL_API_ARRAY_SIZE) {
+               IWL_ERR(drv, "api_index larger than supported by driver\n");
+               return -EINVAL;
+       }
+
+       capa->api[api_index] = le32_to_cpu(ucode_api->api_flags);
+
+       return 0;
+}
+
+static int iwl_set_ucode_capabilities(struct iwl_drv *drv, const u8 *data,
+                                     struct iwl_ucode_capabilities *capa)
+{
+       const struct iwl_ucode_capa *ucode_capa = (void *)data;
+       u32 api_index = le32_to_cpu(ucode_capa->api_index);
+
+       if (api_index >= IWL_CAPABILITIES_ARRAY_SIZE) {
+               IWL_ERR(drv, "api_index larger than supported by driver\n");
+               return -EINVAL;
+       }
+
+       capa->capa[api_index] = le32_to_cpu(ucode_capa->api_capa);
+
+       return 0;
+}
+
 static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv,
                                    const struct firmware *ucode_raw,
                                    struct iwl_firmware_pieces *pieces)
@@ -638,6 +670,18 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
                         */
                        capa->flags = le32_to_cpup((__le32 *)tlv_data);
                        break;
+               case IWL_UCODE_TLV_API_CHANGES_SET:
+                       if (tlv_len != sizeof(struct iwl_ucode_api))
+                               goto invalid_tlv_len;
+                       if (iwl_set_ucode_api_flags(drv, tlv_data, capa))
+                               goto tlv_error;
+                       break;
+               case IWL_UCODE_TLV_ENABLED_CAPABILITIES:
+                       if (tlv_len != sizeof(struct iwl_ucode_capa))
+                               goto invalid_tlv_len;
+                       if (iwl_set_ucode_capabilities(drv, tlv_data, capa))
+                               goto tlv_error;
+                       break;
                case IWL_UCODE_TLV_INIT_EVTLOG_PTR:
                        if (tlv_len != sizeof(u32))
                                goto invalid_tlv_len;
index 88e2d6eb569f4f23ba7696178ffe96135dfdb508..b45e576a4b57feb01982edb99191a65a3ae38bca 100644 (file)
@@ -126,6 +126,8 @@ enum iwl_ucode_tlv_type {
        IWL_UCODE_TLV_SECURE_SEC_WOWLAN = 26,
        IWL_UCODE_TLV_NUM_OF_CPU        = 27,
        IWL_UCODE_TLV_CSCHEME           = 28,
+       IWL_UCODE_TLV_API_CHANGES_SET   = 29,
+       IWL_UCODE_TLV_ENABLED_CAPABILITIES      = 30,
 };
 
 struct iwl_ucode_tlv {
@@ -158,4 +160,19 @@ struct iwl_tlv_ucode_header {
        u8 data[0];
 };
 
+/*
+ * ucode TLVs
+ *
+ * ability to get extension for: flags & capabilities from ucode binaries files
+ */
+struct iwl_ucode_api {
+       __le32 api_index;
+       __le32 api_flags;
+} __packed;
+
+struct iwl_ucode_capa {
+       __le32 api_index;
+       __le32 api_capa;
+} __packed;
+
 #endif  /* __iwl_fw_file_h__ */
index af6b4528d499ff997512f0147ba4cd50464cfa28..f04ff871dc6d5f4a7bc52f6651bb06549c473e0c 100644 (file)
@@ -165,11 +165,15 @@ enum iwl_ucode_sec {
  * just an offset to the HW address.
  */
 #define IWL_UCODE_SECTION_MAX 12
+#define IWL_API_ARRAY_SIZE     1
+#define IWL_CAPABILITIES_ARRAY_SIZE    1
 
 struct iwl_ucode_capabilities {
        u32 max_probe_length;
        u32 standard_phy_calibration_size;
        u32 flags;
+       u32 api[IWL_API_ARRAY_SIZE];
+       u32 capa[IWL_CAPABILITIES_ARRAY_SIZE];
 };
 
 /* one for each uCode image (inst/data, init/runtime/wowlan) */