Re: 3.12: kernel panic when resuming from suspend to RAM (x86_64)

micky
2013-12-10T01:55:27Z

Hi Francis:
On 12/10/2013 09:39 AM, wwang wrote:
> which is based on Thomas' patch.

Can you help us test this patch, we disable irq while suspend here.

From 6b2bd6d85780bfd8d4fe5289aee1b09dd655d2d4 Mon Sep 17 00:00:00 2001
From: Micky Ching <micky_ching@realsil.com.cn>
Date: Thu, 5 Dec 2013 16:44:19 +0800
Subject: [PATCH] mfd: rtsx: fix pci remove panic while resuming

On some special condition, when resume from suspend, the rtsx_pci will
being removed. And card insert/remove interrupt triggered during
removing, this will cause kernel panic, since in card detect work will
read pci register but device is no longer exist.

Signed-off-by: Micky Ching <micky_ching@realsil.com.cn>
---
drivers/mfd/rtsx_pcr.c | 21 ++++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c
index 11e20af..efdd9b9 100644
--- a/drivers/mfd/rtsx_pcr.c
+++ b/drivers/mfd/rtsx_pcr.c
@@ -1228,14 +1228,14 @@ static void rtsx_pci_remove(struct pci_dev *pcidev)

pcr->remove_pci = true;

- cancel_delayed_work(&pcr->carddet_work);
- cancel_delayed_work(&pcr->idle_work);
+ cancel_delayed_work_sync(&pcr->carddet_work);
+ cancel_delayed_work_sync(&pcr->idle_work);

mfd_remove_devices(&pcidev->dev);

dma_free_coherent(&(pcr->pci->dev), RTSX_RESV_BUF_LEN,
pcr->rtsx_resv_buf, pcr->rtsx_resv_buf_addr);
- free_irq(pcr->irq, (void *)pcr);
+ free_irq(pcr->irq, pcr);
if (pcr->msi_en)
pci_disable_msi(pcr->pci);
iounmap(pcr->remap_addr);
@@ -1268,8 +1268,13 @@ static int rtsx_pci_suspend(struct pci_dev
*pcidev, pm_message_t state)
handle = pci_get_drvdata(pcidev);
pcr = handle->pcr;

- cancel_delayed_work(&pcr->carddet_work);
- cancel_delayed_work(&pcr->idle_work);
+ spin_lock_irq(&pcr->lock);
+ rtsx_pci_writel(pcr, RTSX_BIER, 0);
+ pcr->bier = 0;
+ spin_unlock_irq(&pcr->lock);
+ cancel_delayed_work_sync(&pcr->carddet_work);
+ cancel_delayed_work_sync(&pcr->idle_work);
+ free_irq(pcr->irq, pcr);

mutex_lock(&pcr->pcr_mutex);

@@ -1295,6 +1300,12 @@ static int rtsx_pci_resume(struct pci_dev *pcidev)
handle = pci_get_drvdata(pcidev);
pcr = handle->pcr;

+ ret = rtsx_pci_acquire_irq(pcr);
+ if (ret < 0)
+ return ret;
+ synchronize_irq(pcr->irq);
+ rtsx_pci_enable_bus_int(pcr);
+
mutex_lock(&pcr->pcr_mutex);

pci_set_power_state(pcidev, PCI_D0);
--
1.7.9.5

--
Best Regards
Micky.