Skip to content

Commit

Permalink
bus: mhi: pci-generic: Fix hibernation
Browse files Browse the repository at this point in the history
This patch fixes crash after resuming from hibernation. The issue
occurs when mhi stack is builtin and so part of the 'restore-kernel',
causing the device to be resumed from 'restored kernel' with a no
more valid context (memory mappings etc...) and leading to spurious
crashes.

This patch fixes the issue by implementing proper freeze/restore
callbacks.

Link: https://lore.kernel.org/r/1622571445-4505-1-git-send-email-loic.poulain@linaro.org
Reported-by: Shujun Wang <wsj20369@163.com>
Cc: stable <stable@vger.kernel.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Link: https://lore.kernel.org/r/20210606153741.20725-4-manivannan.sadhasivam@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Loic Poulain authored and Greg Kroah-Hartman committed Jun 9, 2021
1 parent 0b67808 commit 5f0c2ee
Showing 1 changed file with 35 additions and 1 deletion.
36 changes: 35 additions & 1 deletion drivers/bus/mhi/pci_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -935,9 +935,43 @@ static int __maybe_unused mhi_pci_resume(struct device *dev)
return ret;
}

static int __maybe_unused mhi_pci_freeze(struct device *dev)
{
struct mhi_pci_device *mhi_pdev = dev_get_drvdata(dev);
struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;

/* We want to stop all operations, hibernation does not guarantee that
* device will be in the same state as before freezing, especially if
* the intermediate restore kernel reinitializes MHI device with new
* context.
*/
if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) {
mhi_power_down(mhi_cntrl, false);
mhi_unprepare_after_power_down(mhi_cntrl);
}

return 0;
}

static int __maybe_unused mhi_pci_restore(struct device *dev)
{
struct mhi_pci_device *mhi_pdev = dev_get_drvdata(dev);

/* Reinitialize the device */
queue_work(system_long_wq, &mhi_pdev->recovery_work);

return 0;
}

static const struct dev_pm_ops mhi_pci_pm_ops = {
SET_RUNTIME_PM_OPS(mhi_pci_runtime_suspend, mhi_pci_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(mhi_pci_suspend, mhi_pci_resume)
#ifdef CONFIG_PM_SLEEP
.suspend = mhi_pci_suspend,
.resume = mhi_pci_resume,
.freeze = mhi_pci_freeze,
.thaw = mhi_pci_restore,
.restore = mhi_pci_restore,
#endif
};

static struct pci_driver mhi_pci_driver = {
Expand Down

0 comments on commit 5f0c2ee

Please sign in to comment.