return data;
}
+/**
+ * enum iwl_pnvm_source - different PNVM possible sources
+ *
+ * @IWL_PNVM_SOURCE_NONE: No PNVM.
+ * @IWL_PNVM_SOURCE_BIOS: PNVM should be read from BIOS.
+ * @IWL_PNVM_SOURCE_EXTERNAL: read .pnvm external file
+ * @IWL_PNVM_SOURCE_EMBEDDED: PNVM is embedded in the .ucode file.
+ */
+enum iwl_pnvm_source {
+ IWL_PNVM_SOURCE_NONE,
+ IWL_PNVM_SOURCE_BIOS,
+ IWL_PNVM_SOURCE_EXTERNAL,
+ IWL_PNVM_SOURCE_EMBEDDED
+};
+
+static enum iwl_pnvm_source iwl_select_pnvm_source(struct iwl_trans *trans,
+ bool intel_sku)
+{
+
+ /* Get PNVM from BIOS for non-Intel SKU */
+ if (!intel_sku)
+ return IWL_PNVM_SOURCE_BIOS;
+
+ /* Before those devices, PNVM didn't exist at all */
+ if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
+ return IWL_PNVM_SOURCE_NONE;
+
+ /* After those devices, we moved to embedded PNVM */
+ if (trans->mac_cfg->device_family > IWL_DEVICE_FAMILY_AX210)
+ return IWL_PNVM_SOURCE_EMBEDDED;
+
+ /* For IWL_DEVICE_FAMILY_AX210, depends on the CRF */
+ if (CSR_HW_RFID_TYPE(trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_GF)
+ return IWL_PNVM_SOURCE_EXTERNAL;
+
+ return IWL_PNVM_SOURCE_NONE;
+}
+
static const u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len,
__le32 sku_id[3], const struct iwl_fw *fw)
{
struct pnvm_sku_package *package;
+ enum iwl_pnvm_source pnvm_src =
+ iwl_select_pnvm_source(trans_p, sku_id[2] == 0);
+ u8 *image = NULL;
- /* Get PNVM from BIOS for non-Intel SKU */
- if (sku_id[2]) {
+ IWL_DEBUG_FW(trans_p, "PNVM source %d\n", pnvm_src);
+
+ if (pnvm_src == IWL_PNVM_SOURCE_NONE)
+ return NULL;
+
+ if (pnvm_src == IWL_PNVM_SOURCE_BIOS) {
package = iwl_uefi_get_pnvm(trans_p, len);
if (!IS_ERR_OR_NULL(package)) {
- u8 *image = NULL;
-
if (*len >= sizeof(*package)) {
/* we need only the data */
*len -= sizeof(*package);
if (image)
return image;
}
+
+ /* PNVM doesn't exist in BIOS. Find the fallback source */
+ pnvm_src = iwl_select_pnvm_source(trans_p, true);
+ IWL_DEBUG_FW(trans_p, "PNVM in BIOS doesn't exist, try %d\n",
+ pnvm_src);
}
- if (fw->pnvm_data) {
- *len = fw->pnvm_size;
+ if (pnvm_src == IWL_PNVM_SOURCE_EXTERNAL) {
+ image = iwl_pnvm_get_from_fs(trans_p, len);
+ if (image)
+ return image;
+ }
+ if (pnvm_src == IWL_PNVM_SOURCE_EMBEDDED && fw->pnvm_data) {
+ *len = fw->pnvm_size;
return fw->pnvm_data;
}
- /* If it's not available, or for Intel SKU, try from the filesystem */
- return iwl_pnvm_get_from_fs(trans_p, len);
+ IWL_ERR(trans_p, "Couldn't get PNVM from required source: %d\n", pnvm_src);
+ return NULL;
}
static void