Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bus: mhi: pci-generic: Fix hibernation

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>

authored by

Loic Poulain and committed by
Greg Kroah-Hartman
5f0c2ee1 0b67808a

+35 -1
+35 -1
drivers/bus/mhi/pci_generic.c
··· 935 935 return ret; 936 936 } 937 937 938 + static int __maybe_unused mhi_pci_freeze(struct device *dev) 939 + { 940 + struct mhi_pci_device *mhi_pdev = dev_get_drvdata(dev); 941 + struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl; 942 + 943 + /* We want to stop all operations, hibernation does not guarantee that 944 + * device will be in the same state as before freezing, especially if 945 + * the intermediate restore kernel reinitializes MHI device with new 946 + * context. 947 + */ 948 + if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) { 949 + mhi_power_down(mhi_cntrl, false); 950 + mhi_unprepare_after_power_down(mhi_cntrl); 951 + } 952 + 953 + return 0; 954 + } 955 + 956 + static int __maybe_unused mhi_pci_restore(struct device *dev) 957 + { 958 + struct mhi_pci_device *mhi_pdev = dev_get_drvdata(dev); 959 + 960 + /* Reinitialize the device */ 961 + queue_work(system_long_wq, &mhi_pdev->recovery_work); 962 + 963 + return 0; 964 + } 965 + 938 966 static const struct dev_pm_ops mhi_pci_pm_ops = { 939 967 SET_RUNTIME_PM_OPS(mhi_pci_runtime_suspend, mhi_pci_runtime_resume, NULL) 940 - SET_SYSTEM_SLEEP_PM_OPS(mhi_pci_suspend, mhi_pci_resume) 968 + #ifdef CONFIG_PM_SLEEP 969 + .suspend = mhi_pci_suspend, 970 + .resume = mhi_pci_resume, 971 + .freeze = mhi_pci_freeze, 972 + .thaw = mhi_pci_restore, 973 + .restore = mhi_pci_restore, 974 + #endif 941 975 }; 942 976 943 977 static struct pci_driver mhi_pci_driver = {