We currently track fetch and load status separately, but the 2 are
actually sequential in the uc lifetime (fetch must complete before we
can attempt the load!). Unifying the 2 variables we can better follow
the sequential states and improve our trackng of the uC state.
Also, sprinkle some GEM_BUG_ON to make sure we transition correctly
between states.
v2: rename states, add the running state (Michal), drop some logs in
the fetch path (Michal, Chris)
v3: re-rename states, extend early status check to all helpers (Michal)
Suggested-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20190725001813.4740-5-daniele.ceraolospurio@intel.com
int intel_guc_resume(struct intel_guc *guc);
struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size);
int intel_guc_resume(struct intel_guc *guc);
struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size);
-static inline bool intel_guc_is_loaded(struct intel_guc *guc)
+static inline bool intel_guc_is_running(struct intel_guc *guc)
- return intel_uc_fw_is_loaded(&guc->fw);
+ return intel_uc_fw_is_running(&guc->fw);
}
static inline int intel_guc_sanitize(struct intel_guc *guc)
}
static inline int intel_guc_sanitize(struct intel_guc *guc)
*/
int intel_guc_fw_upload(struct intel_guc *guc)
{
*/
int intel_guc_fw_upload(struct intel_guc *guc)
{
- return intel_uc_fw_upload(&guc->fw, guc_fw_xfer);
+ int ret = intel_uc_fw_upload(&guc->fw, guc_fw_xfer);
+ if (!ret)
+ guc->fw.status = INTEL_UC_FIRMWARE_RUNNING;
+
+ return ret;
* the case, instead of trying (in vain) to communicate with it, let's
* just cleanup the doorbell HW and our internal state.
*/
* the case, instead of trying (in vain) to communicate with it, let's
* just cleanup the doorbell HW and our internal state.
*/
- if (intel_guc_is_loaded(client->guc))
+ if (intel_guc_is_running(client->guc))
destroy_doorbell(client);
else
__fini_doorbell(client);
destroy_doorbell(client);
else
__fini_doorbell(client);
struct intel_guc *guc = >->uc.guc;
int ret;
struct intel_guc *guc = >->uc.guc;
int ret;
- if (huc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS)
- return -ENOEXEC;
+ GEM_BUG_ON(!intel_uc_fw_is_loaded(&huc->fw));
+ GEM_BUG_ON(intel_huc_is_authenticated(huc));
ret = intel_guc_auth_huc(guc,
intel_guc_ggtt_offset(guc, huc->rsa_data));
ret = intel_guc_auth_huc(guc,
intel_guc_ggtt_offset(guc, huc->rsa_data));
+ huc->fw.status = INTEL_UC_FIRMWARE_RUNNING;
+
- huc->fw.load_status = INTEL_UC_FIRMWARE_FAIL;
+ huc->fw.status = INTEL_UC_FIRMWARE_FAIL;
DRM_ERROR("HuC: Authentication failed %d\n", ret);
return ret;
DRM_ERROR("HuC: Authentication failed %d\n", ret);
return ret;
+static inline bool intel_huc_is_authenticated(struct intel_huc *huc)
+{
+ return intel_uc_fw_is_running(&huc->fw);
+}
+
{
struct intel_guc *guc = &uc->guc;
{
struct intel_guc *guc = &uc->guc;
- if (!intel_guc_is_loaded(guc))
+ if (!intel_guc_is_running(guc))
return;
GEM_BUG_ON(!intel_uc_fw_supported(&guc->fw));
return;
GEM_BUG_ON(!intel_uc_fw_supported(&guc->fw));
{
struct intel_guc *guc = &uc->guc;
{
struct intel_guc *guc = &uc->guc;
- if (!intel_guc_is_loaded(guc))
+ if (!intel_guc_is_running(guc))
return;
guc_stop_communication(guc);
return;
guc_stop_communication(guc);
struct intel_guc *guc = &uc->guc;
int err;
struct intel_guc *guc = &uc->guc;
int err;
- if (!intel_guc_is_loaded(guc))
+ if (!intel_guc_is_running(guc))
return;
err = intel_guc_suspend(guc);
return;
err = intel_guc_suspend(guc);
struct intel_guc *guc = &uc->guc;
intel_wakeref_t wakeref;
struct intel_guc *guc = &uc->guc;
intel_wakeref_t wakeref;
- if (!intel_guc_is_loaded(guc))
+ if (!intel_guc_is_running(guc))
return;
with_intel_runtime_pm(&uc_to_gt(uc)->i915->runtime_pm, wakeref)
return;
with_intel_runtime_pm(&uc_to_gt(uc)->i915->runtime_pm, wakeref)
struct intel_guc *guc = &uc->guc;
int err;
struct intel_guc *guc = &uc->guc;
int err;
- if (!intel_guc_is_loaded(guc))
+ if (!intel_guc_is_running(guc))
return 0;
guc_enable_communication(guc);
return 0;
guc_enable_communication(guc);
struct drm_i915_private *i915)
{
/*
struct drm_i915_private *i915)
{
/*
- * we use FIRMWARE_UNINITIALIZED to detect checks against fetch_status
+ * we use FIRMWARE_UNINITIALIZED to detect checks against uc_fw->status
* before we're looked at the HW caps to see if we have uc support
*/
BUILD_BUG_ON(INTEL_UC_FIRMWARE_UNINITIALIZED);
* before we're looked at the HW caps to see if we have uc support
*/
BUILD_BUG_ON(INTEL_UC_FIRMWARE_UNINITIALIZED);
- GEM_BUG_ON(uc_fw->fetch_status);
- GEM_BUG_ON(uc_fw->load_status);
+ GEM_BUG_ON(uc_fw->status);
GEM_BUG_ON(uc_fw->path);
uc_fw->type = type;
GEM_BUG_ON(uc_fw->path);
uc_fw->type = type;
__uc_fw_auto_select(uc_fw, INTEL_INFO(i915)->platform,
INTEL_REVID(i915));
__uc_fw_auto_select(uc_fw, INTEL_INFO(i915)->platform,
INTEL_REVID(i915));
- if (uc_fw->path) {
- uc_fw->fetch_status = INTEL_UC_FIRMWARE_NOT_STARTED;
- uc_fw->load_status = INTEL_UC_FIRMWARE_NOT_STARTED;
- } else {
- uc_fw->fetch_status = INTEL_UC_FIRMWARE_NOT_SUPPORTED;
- uc_fw->load_status = INTEL_UC_FIRMWARE_NOT_SUPPORTED;
- }
+ if (uc_fw->path)
+ uc_fw->status = INTEL_UC_FIRMWARE_SELECTED;
+ else
+ uc_fw->status = INTEL_UC_FIRMWARE_NOT_SUPPORTED;
GEM_BUG_ON(!intel_uc_fw_supported(uc_fw));
GEM_BUG_ON(!intel_uc_fw_supported(uc_fw));
- DRM_DEBUG_DRIVER("%s fw fetch %s\n",
- intel_uc_fw_type_repr(uc_fw->type), uc_fw->path);
-
- uc_fw->fetch_status = INTEL_UC_FIRMWARE_PENDING;
- DRM_DEBUG_DRIVER("%s fw fetch %s\n",
- intel_uc_fw_type_repr(uc_fw->type),
- intel_uc_fw_status_repr(uc_fw->fetch_status));
-
err = request_firmware(&fw, uc_fw->path, &pdev->dev);
err = request_firmware(&fw, uc_fw->path, &pdev->dev);
- if (err) {
- DRM_DEBUG_DRIVER("%s fw request_firmware err=%d\n",
- intel_uc_fw_type_repr(uc_fw->type), err);
DRM_DEBUG_DRIVER("%s fw size %zu ptr %p\n",
intel_uc_fw_type_repr(uc_fw->type), fw->size, fw);
DRM_DEBUG_DRIVER("%s fw size %zu ptr %p\n",
intel_uc_fw_type_repr(uc_fw->type), fw->size, fw);
uc_fw->obj = obj;
uc_fw->size = fw->size;
uc_fw->obj = obj;
uc_fw->size = fw->size;
- uc_fw->fetch_status = INTEL_UC_FIRMWARE_SUCCESS;
- DRM_DEBUG_DRIVER("%s fw fetch %s\n",
- intel_uc_fw_type_repr(uc_fw->type),
- intel_uc_fw_status_repr(uc_fw->fetch_status));
+ uc_fw->status = INTEL_UC_FIRMWARE_AVAILABLE;
release_firmware(fw);
return;
fail:
release_firmware(fw);
return;
fail:
- uc_fw->fetch_status = INTEL_UC_FIRMWARE_FAIL;
- DRM_DEBUG_DRIVER("%s fw fetch %s\n",
- intel_uc_fw_type_repr(uc_fw->type),
- intel_uc_fw_status_repr(uc_fw->fetch_status));
+ uc_fw->status = INTEL_UC_FIRMWARE_MISSING;
DRM_WARN("%s: Failed to fetch firmware %s (error %d)\n",
intel_uc_fw_type_repr(uc_fw->type), uc_fw->path, err);
DRM_WARN("%s: Failed to fetch firmware %s (error %d)\n",
intel_uc_fw_type_repr(uc_fw->type), uc_fw->path, err);
DRM_DEBUG_DRIVER("%s fw load %s\n",
intel_uc_fw_type_repr(uc_fw->type), uc_fw->path);
DRM_DEBUG_DRIVER("%s fw load %s\n",
intel_uc_fw_type_repr(uc_fw->type), uc_fw->path);
- if (uc_fw->fetch_status != INTEL_UC_FIRMWARE_SUCCESS)
- return -ENOEXEC;
-
- uc_fw->load_status = INTEL_UC_FIRMWARE_PENDING;
- DRM_DEBUG_DRIVER("%s fw load %s\n",
- intel_uc_fw_type_repr(uc_fw->type),
- intel_uc_fw_status_repr(uc_fw->load_status));
+ /* make sure the status was cleared the last time we reset the uc */
+ GEM_BUG_ON(intel_uc_fw_is_loaded(uc_fw));
+ if (!intel_uc_fw_is_available(uc_fw))
+ return -ENOEXEC;
/* Call custom loader */
intel_uc_fw_ggtt_bind(uc_fw);
err = xfer(uc_fw);
/* Call custom loader */
intel_uc_fw_ggtt_bind(uc_fw);
err = xfer(uc_fw);
- uc_fw->load_status = INTEL_UC_FIRMWARE_SUCCESS;
- DRM_DEBUG_DRIVER("%s fw load %s\n",
- intel_uc_fw_type_repr(uc_fw->type),
- intel_uc_fw_status_repr(uc_fw->load_status));
+ uc_fw->status = INTEL_UC_FIRMWARE_TRANSFERRED;
+ DRM_DEBUG_DRIVER("%s fw xfer completed\n",
+ intel_uc_fw_type_repr(uc_fw->type));
DRM_INFO("%s: Loaded firmware %s (version %u.%u)\n",
intel_uc_fw_type_repr(uc_fw->type),
DRM_INFO("%s: Loaded firmware %s (version %u.%u)\n",
intel_uc_fw_type_repr(uc_fw->type),
- uc_fw->load_status = INTEL_UC_FIRMWARE_FAIL;
- DRM_DEBUG_DRIVER("%s fw load %s\n",
- intel_uc_fw_type_repr(uc_fw->type),
- intel_uc_fw_status_repr(uc_fw->load_status));
+ uc_fw->status = INTEL_UC_FIRMWARE_FAIL;
+ DRM_DEBUG_DRIVER("%s fw load failed\n",
+ intel_uc_fw_type_repr(uc_fw->type));
DRM_WARN("%s: Failed to load firmware %s (error %d)\n",
intel_uc_fw_type_repr(uc_fw->type), uc_fw->path, err);
DRM_WARN("%s: Failed to load firmware %s (error %d)\n",
intel_uc_fw_type_repr(uc_fw->type), uc_fw->path, err);
- if (uc_fw->fetch_status != INTEL_UC_FIRMWARE_SUCCESS)
+ /* this should happen before the load! */
+ GEM_BUG_ON(intel_uc_fw_is_loaded(uc_fw));
+
+ if (!intel_uc_fw_is_available(uc_fw))
return -ENOEXEC;
err = i915_gem_object_pin_pages(uc_fw->obj);
return -ENOEXEC;
err = i915_gem_object_pin_pages(uc_fw->obj);
void intel_uc_fw_fini(struct intel_uc_fw *uc_fw)
{
void intel_uc_fw_fini(struct intel_uc_fw *uc_fw)
{
- if (uc_fw->fetch_status != INTEL_UC_FIRMWARE_SUCCESS)
+ if (!intel_uc_fw_is_available(uc_fw))
return;
i915_gem_object_unpin_pages(uc_fw->obj);
return;
i915_gem_object_unpin_pages(uc_fw->obj);
if (obj)
i915_gem_object_put(obj);
if (obj)
i915_gem_object_put(obj);
- uc_fw->fetch_status = INTEL_UC_FIRMWARE_NOT_STARTED;
+ uc_fw->status = INTEL_UC_FIRMWARE_SELECTED;
{
drm_printf(p, "%s firmware: %s\n",
intel_uc_fw_type_repr(uc_fw->type), uc_fw->path);
{
drm_printf(p, "%s firmware: %s\n",
intel_uc_fw_type_repr(uc_fw->type), uc_fw->path);
- drm_printf(p, "\tstatus: fetch %s, load %s\n",
- intel_uc_fw_status_repr(uc_fw->fetch_status),
- intel_uc_fw_status_repr(uc_fw->load_status));
+ drm_printf(p, "\tstatus: %s\n",
+ intel_uc_fw_status_repr(uc_fw->status));
drm_printf(p, "\tversion: wanted %u.%u, found %u.%u\n",
uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted,
uc_fw->major_ver_found, uc_fw->minor_ver_found);
drm_printf(p, "\tversion: wanted %u.%u, found %u.%u\n",
uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted,
uc_fw->major_ver_found, uc_fw->minor_ver_found);
#define INTEL_UC_FIRMWARE_URL "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/i915"
enum intel_uc_fw_status {
#define INTEL_UC_FIRMWARE_URL "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/i915"
enum intel_uc_fw_status {
- INTEL_UC_FIRMWARE_NOT_SUPPORTED = -2, /* no uc HW */
- INTEL_UC_FIRMWARE_FAIL = -1,
+ INTEL_UC_FIRMWARE_FAIL = -3, /* failed to xfer or init/auth the fw */
+ INTEL_UC_FIRMWARE_MISSING = -2, /* blob not found on the system */
+ INTEL_UC_FIRMWARE_NOT_SUPPORTED = -1, /* no uc HW */
INTEL_UC_FIRMWARE_UNINITIALIZED = 0, /* used to catch checks done too early */
INTEL_UC_FIRMWARE_UNINITIALIZED = 0, /* used to catch checks done too early */
- INTEL_UC_FIRMWARE_NOT_STARTED = 1,
- INTEL_UC_FIRMWARE_PENDING,
- INTEL_UC_FIRMWARE_SUCCESS
+ INTEL_UC_FIRMWARE_SELECTED, /* selected the blob we want to load */
+ INTEL_UC_FIRMWARE_AVAILABLE, /* blob found and copied in mem */
+ INTEL_UC_FIRMWARE_TRANSFERRED, /* dma xfer done */
+ INTEL_UC_FIRMWARE_RUNNING /* init/auth done */
};
enum intel_uc_fw_type {
};
enum intel_uc_fw_type {
const char *path;
size_t size;
struct drm_i915_gem_object *obj;
const char *path;
size_t size;
struct drm_i915_gem_object *obj;
- enum intel_uc_fw_status fetch_status;
- enum intel_uc_fw_status load_status;
+ enum intel_uc_fw_status status;
/*
* The firmware build process will generate a version header file with major and
/*
* The firmware build process will generate a version header file with major and
const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status)
{
switch (status) {
const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status)
{
switch (status) {
- case INTEL_UC_FIRMWARE_NOT_SUPPORTED:
- return "N/A - uc HW not available";
case INTEL_UC_FIRMWARE_FAIL:
return "FAIL";
case INTEL_UC_FIRMWARE_FAIL:
return "FAIL";
+ case INTEL_UC_FIRMWARE_MISSING:
+ return "MISSING";
+ case INTEL_UC_FIRMWARE_NOT_SUPPORTED:
+ return "N/A";
case INTEL_UC_FIRMWARE_UNINITIALIZED:
return "UNINITIALIZED";
case INTEL_UC_FIRMWARE_UNINITIALIZED:
return "UNINITIALIZED";
- case INTEL_UC_FIRMWARE_NOT_STARTED:
- return "NOT_STARTED";
- case INTEL_UC_FIRMWARE_PENDING:
- return "PENDING";
- case INTEL_UC_FIRMWARE_SUCCESS:
- return "SUCCESS";
+ case INTEL_UC_FIRMWARE_SELECTED:
+ return "SELECTED";
+ case INTEL_UC_FIRMWARE_AVAILABLE:
+ return "AVAILABLE";
+ case INTEL_UC_FIRMWARE_TRANSFERRED:
+ return "TRANSFERRED";
+ case INTEL_UC_FIRMWARE_RUNNING:
+ return "RUNNING";
+static inline enum intel_uc_fw_status
+__intel_uc_fw_status(struct intel_uc_fw *uc_fw)
+{
+ /* shouldn't call this before checking hw/blob availability */
+ GEM_BUG_ON(uc_fw->status == INTEL_UC_FIRMWARE_UNINITIALIZED);
+ return uc_fw->status;
+}
+
+static inline bool intel_uc_fw_is_available(struct intel_uc_fw *uc_fw)
+{
+ return __intel_uc_fw_status(uc_fw) >= INTEL_UC_FIRMWARE_AVAILABLE;
+}
+
static inline bool intel_uc_fw_is_loaded(struct intel_uc_fw *uc_fw)
{
static inline bool intel_uc_fw_is_loaded(struct intel_uc_fw *uc_fw)
{
- return uc_fw->load_status == INTEL_UC_FIRMWARE_SUCCESS;
+ return __intel_uc_fw_status(uc_fw) >= INTEL_UC_FIRMWARE_TRANSFERRED;
+}
+
+static inline bool intel_uc_fw_is_running(struct intel_uc_fw *uc_fw)
+{
+ return __intel_uc_fw_status(uc_fw) == INTEL_UC_FIRMWARE_RUNNING;
}
static inline bool intel_uc_fw_supported(struct intel_uc_fw *uc_fw)
{
}
static inline bool intel_uc_fw_supported(struct intel_uc_fw *uc_fw)
{
- /* shouldn't call this before checking hw/blob availability */
- GEM_BUG_ON(uc_fw->fetch_status == INTEL_UC_FIRMWARE_UNINITIALIZED);
- return uc_fw->fetch_status != INTEL_UC_FIRMWARE_NOT_SUPPORTED;
+ return __intel_uc_fw_status(uc_fw) != INTEL_UC_FIRMWARE_NOT_SUPPORTED;
}
static inline void intel_uc_fw_sanitize(struct intel_uc_fw *uc_fw)
{
if (intel_uc_fw_is_loaded(uc_fw))
}
static inline void intel_uc_fw_sanitize(struct intel_uc_fw *uc_fw)
{
if (intel_uc_fw_is_loaded(uc_fw))
- uc_fw->load_status = INTEL_UC_FIRMWARE_PENDING;
+ uc_fw->status = INTEL_UC_FIRMWARE_AVAILABLE;
*/
static inline u32 intel_uc_fw_get_upload_size(struct intel_uc_fw *uc_fw)
{
*/
static inline u32 intel_uc_fw_get_upload_size(struct intel_uc_fw *uc_fw)
{
- if (uc_fw->fetch_status != INTEL_UC_FIRMWARE_SUCCESS)
+ if (!intel_uc_fw_is_available(uc_fw))
return 0;
return uc_fw->header_size + uc_fw->ucode_size;
return 0;
return uc_fw->header_size + uc_fw->ucode_size;