diff options
Diffstat (limited to 'drivers/mfd/rtsx_pcr.c')
-rw-r--r-- | drivers/mfd/rtsx_pcr.c | 31 |
1 files changed, 19 insertions, 12 deletions
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index 67bb34ef0ebd..9016932f0267 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c @@ -752,7 +752,7 @@ static void rtsx_pci_card_detect(struct work_struct *work) struct delayed_work *dwork; struct rtsx_pcr *pcr; unsigned long flags; - unsigned int card_detect = 0; + unsigned int card_detect = 0, card_inserted, card_removed; u32 irq_status; dwork = to_delayed_work(work); @@ -760,25 +760,32 @@ static void rtsx_pci_card_detect(struct work_struct *work) dev_dbg(&(pcr->pci->dev), "--> %s\n", __func__); + mutex_lock(&pcr->pcr_mutex); spin_lock_irqsave(&pcr->lock, flags); irq_status = rtsx_pci_readl(pcr, RTSX_BIPR); dev_dbg(&(pcr->pci->dev), "irq_status: 0x%08x\n", irq_status); - if (pcr->card_inserted || pcr->card_removed) { + irq_status &= CARD_EXIST; + card_inserted = pcr->card_inserted & irq_status; + card_removed = pcr->card_removed; + pcr->card_inserted = 0; + pcr->card_removed = 0; + + spin_unlock_irqrestore(&pcr->lock, flags); + + if (card_inserted || card_removed) { dev_dbg(&(pcr->pci->dev), "card_inserted: 0x%x, card_removed: 0x%x\n", - pcr->card_inserted, pcr->card_removed); + card_inserted, card_removed); if (pcr->ops->cd_deglitch) - pcr->card_inserted = pcr->ops->cd_deglitch(pcr); + card_inserted = pcr->ops->cd_deglitch(pcr); - card_detect = pcr->card_inserted | pcr->card_removed; - pcr->card_inserted = 0; - pcr->card_removed = 0; + card_detect = card_inserted | card_removed; } - spin_unlock_irqrestore(&pcr->lock, flags); + mutex_unlock(&pcr->pcr_mutex); if ((card_detect & SD_EXIST) && pcr->slots[RTSX_SD_CARD].card_event) pcr->slots[RTSX_SD_CARD].card_event( @@ -830,10 +837,6 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id) } } - if (pcr->card_inserted || pcr->card_removed) - schedule_delayed_work(&pcr->carddet_work, - msecs_to_jiffies(200)); - if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) { if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) { pcr->trans_result = TRANS_RESULT_FAIL; @@ -846,6 +849,10 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id) } } + if (pcr->card_inserted || pcr->card_removed) + schedule_delayed_work(&pcr->carddet_work, + msecs_to_jiffies(200)); + spin_unlock(&pcr->lock); return IRQ_HANDLED; } |