diff options
author | Vitaly Lubart <vitaly.lubart@intel.com> | 2023-10-15 11:05:40 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2023-10-18 11:01:34 +0300 |
commit | 34a674e99acd6ec4b541cd4c630e126ba1a4c22f (patch) | |
tree | 86d7ec0388c8a72c4ddd76ef3a834f155c8c2a3e /drivers/misc/mei/hw-me.c | |
parent | 3b54a111bb7e558e4a40e483ded7c123fe94382c (diff) | |
download | linux-34a674e99acd6ec4b541cd4c630e126ba1a4c22f.tar.xz |
mei: me: emit error only if reset was unexpected
GSC devices perform legal firmware initiated resets due to state transition
that may appear as unexpected to the driver. Lower the log level for those
devices to debug level and save the firmware status registers.
When the device comes out of the reset it is possible to check whether the
resets was due to a firmware error or an exception
and only than produce a warning.
Signed-off-by: Vitaly Lubart <vitaly.lubart@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Link: https://lore.kernel.org/r/20231015080540.95922-1-tomas.winkler@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mei/hw-me.c')
-rw-r--r-- | drivers/misc/mei/hw-me.c | 61 |
1 files changed, 58 insertions, 3 deletions
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index e72c0d78932e..d11a0740b47c 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -443,11 +443,22 @@ static void mei_gsc_pxp_check(struct mei_device *dev) struct mei_me_hw *hw = to_me_hw(dev); u32 fwsts5 = 0; - if (dev->pxp_mode == MEI_DEV_PXP_DEFAULT) + if (!kind_is_gsc(dev) && !kind_is_gscfi(dev)) return; hw->read_fws(dev, PCI_CFG_HFS_5, &fwsts5); trace_mei_pci_cfg_read(dev->dev, "PCI_CFG_HFS_5", PCI_CFG_HFS_5, fwsts5); + + if ((fwsts5 & GSC_CFG_HFS_5_BOOT_TYPE_MSK) == GSC_CFG_HFS_5_BOOT_TYPE_PXP) { + if (dev->gsc_reset_to_pxp == MEI_DEV_RESET_TO_PXP_DEFAULT) + dev->gsc_reset_to_pxp = MEI_DEV_RESET_TO_PXP_PERFORMED; + } else { + dev->gsc_reset_to_pxp = MEI_DEV_RESET_TO_PXP_DEFAULT; + } + + if (dev->pxp_mode == MEI_DEV_PXP_DEFAULT) + return; + if ((fwsts5 & GSC_CFG_HFS_5_BOOT_TYPE_MSK) == GSC_CFG_HFS_5_BOOT_TYPE_PXP) { dev_dbg(dev->dev, "pxp mode is ready 0x%08x\n", fwsts5); dev->pxp_mode = MEI_DEV_PXP_READY; @@ -483,6 +494,43 @@ static int mei_me_hw_ready_wait(struct mei_device *dev) } /** + * mei_me_check_fw_reset - check for the firmware reset error and exception conditions + * + * @dev: mei device + */ +static void mei_me_check_fw_reset(struct mei_device *dev) +{ + struct mei_fw_status fw_status; + char fw_sts_str[MEI_FW_STATUS_STR_SZ] = {0}; + int ret; + u32 fw_pm_event = 0; + + if (!dev->saved_fw_status_flag) + goto end; + + if (dev->gsc_reset_to_pxp == MEI_DEV_RESET_TO_PXP_PERFORMED) { + ret = mei_fw_status(dev, &fw_status); + if (!ret) { + fw_pm_event = fw_status.status[1] & PCI_CFG_HFS_2_PM_EVENT_MASK; + if (fw_pm_event != PCI_CFG_HFS_2_PM_CMOFF_TO_CMX_ERROR && + fw_pm_event != PCI_CFG_HFS_2_PM_CM_RESET_ERROR) + goto end; + } else { + dev_err(dev->dev, "failed to read firmware status: %d\n", ret); + } + } + + mei_fw_status2str(&dev->saved_fw_status, fw_sts_str, sizeof(fw_sts_str)); + dev_warn(dev->dev, "unexpected reset: fw_pm_event = 0x%x, dev_state = %u fw status = %s\n", + fw_pm_event, dev->saved_dev_state, fw_sts_str); + +end: + if (dev->gsc_reset_to_pxp == MEI_DEV_RESET_TO_PXP_PERFORMED) + dev->gsc_reset_to_pxp = MEI_DEV_RESET_TO_PXP_DONE; + dev->saved_fw_status_flag = false; +} + +/** * mei_me_hw_start - hw start routine * * @dev: mei device @@ -492,6 +540,8 @@ static int mei_me_hw_start(struct mei_device *dev) { int ret = mei_me_hw_ready_wait(dev); + if (kind_is_gsc(dev) || kind_is_gscfi(dev)) + mei_me_check_fw_reset(dev); if (ret) return ret; dev_dbg(dev->dev, "hw is ready\n"); @@ -1300,8 +1350,13 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id) /* check if ME wants a reset */ if (!mei_hw_is_ready(dev) && dev->dev_state != MEI_DEV_RESETTING) { - dev_warn(dev->dev, "FW not ready: resetting: dev_state = %d pxp = %d\n", - dev->dev_state, dev->pxp_mode); + if (kind_is_gsc(dev) || kind_is_gscfi(dev)) { + dev_dbg(dev->dev, "FW not ready: resetting: dev_state = %d\n", + dev->dev_state); + } else { + dev_warn(dev->dev, "FW not ready: resetting: dev_state = %d\n", + dev->dev_state); + } if (dev->dev_state == MEI_DEV_POWERING_DOWN || dev->dev_state == MEI_DEV_POWER_DOWN) mei_cl_all_disconnect(dev); |