static int msmsdcc_pio_irq(int irq, void *dev_id) { struct msmsdcc_host *host = dev_id; void __iomem *base = host->base; uint32_t status; status = readl(base + MMCISTATUS); #if IRQ_DEBUG msmsdcc_print_status(host, "irq1-r", status); #endif /* SEMC:LC: Update for DMS00768370 start */ //do { /*original*/ while(host->pio.sg){ /* SEMC:LC: Update for DMS00768370 end */ unsigned long flags; unsigned int remain, len; char *buffer; if (!(status & (MCI_TXFIFOHALFEMPTY | MCI_RXDATAAVLBL))) { if (host->curr.xfer_remain == 0 || !msmsdcc_piopoll) break; if (msmsdcc_spin_on_status(host, (MCI_TXFIFOHALFEMPTY | MCI_RXDATAAVLBL), PIO_SPINMAX)) { break; } } /* Map the current scatter buffer */ local_irq_save(flags); buffer = kmap_atomic(sg_page(host->pio.sg), KM_BIO_SRC_IRQ) + host->pio.sg->offset; buffer += host->pio.sg_off; remain = host->pio.sg->length - host->pio.sg_off; len = 0; if (status & MCI_RXACTIVE) len = msmsdcc_pio_read(host, buffer, remain); if (status & MCI_TXACTIVE) len = msmsdcc_pio_write(host, buffer, remain, status); /* Unmap the buffer */ kunmap_atomic(buffer, KM_BIO_SRC_IRQ); local_irq_restore(flags); host->pio.sg_off += len; host->curr.xfer_remain -= len; host->curr.data_xfered += len; remain -= len; if (remain == 0) { /* This sg page is full - do some housekeeping */ if (status & MCI_RXACTIVE && host->curr.user_pages) flush_dcache_page(sg_page(host->pio.sg)); if (!--host->pio.sg_len) { memset(&host->pio, 0, sizeof(host->pio)); break; } /* Advance to next sg */ host->pio.sg++; host->pio.sg_off = 0; } status = readl(base + MMCISTATUS); /* SEMC:LC: Update for DMS00768370 start */ //} while (1); /*original*/ } /* SEMC:LC: Update for DMS00768370 end */ if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE) writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1); /* ATHENV */ #ifdef ATH_PATCH if (!host->curr.xfer_remain) { if (host->pdev_id == ATH_WLAN_SLOT) { if (readl(host->base + MMCIMASK0) & MCI_SDIOINTOPERMASK) writel(MCI_SDIOINTOPERMASK, base + MMCIMASK1); else writel(0, base + MMCIMASK1); } else { writel(0, base + MMCIMASK1); } } #else if (!host->curr.xfer_remain) writel(0, base + MMCIMASK1); #endif /* ATHENV */ return IRQ_HANDLED; }
static irqreturn_t msmsdcc_pio_irq(int irq, void *dev_id) { struct msmsdcc_host *host = dev_id; void __iomem *base = host->base; uint32_t status; status = readl(base + MMCISTATUS); #if IRQ_DEBUG msmsdcc_print_status(host, "irq1-r", status); #endif /* SEMC_BEGIN (Crash on irq when data already handled - DMS00718508) */ // do { while (host->pio.sg) { /* SEMC_END (Crash on irq when data already handled - DMS00718508) */ unsigned long flags; unsigned int remain, len; char *buffer; if (!(status & (MCI_TXFIFOHALFEMPTY | MCI_RXDATAAVLBL))) { if (host->curr.xfer_remain == 0 || !msmsdcc_piopoll) break; if (msmsdcc_spin_on_status(host, (MCI_TXFIFOHALFEMPTY | MCI_RXDATAAVLBL), PIO_SPINMAX)) { break; } } /* Map the current scatter buffer */ local_irq_save(flags); buffer = kmap_atomic(sg_page(host->pio.sg), KM_BIO_SRC_IRQ) + host->pio.sg->offset; buffer += host->pio.sg_off; remain = host->pio.sg->length - host->pio.sg_off; len = 0; if (status & MCI_RXACTIVE) len = msmsdcc_pio_read(host, buffer, remain); if (status & MCI_TXACTIVE) len = msmsdcc_pio_write(host, buffer, remain, status); /* Unmap the buffer */ kunmap_atomic(buffer, KM_BIO_SRC_IRQ); local_irq_restore(flags); host->pio.sg_off += len; host->curr.xfer_remain -= len; host->curr.data_xfered += len; remain -= len; if (remain == 0) { /* This sg page is full - do some housekeeping */ if (status & MCI_RXACTIVE && host->curr.user_pages) flush_dcache_page(sg_page(host->pio.sg)); if (!--host->pio.sg_len) { memset(&host->pio, 0, sizeof(host->pio)); break; } /* Advance to next sg */ host->pio.sg++; host->pio.sg_off = 0; } status = readl(base + MMCISTATUS); /* SEMC_BEGIN (Crash on irq when data already handled - DMS00718508) */ // } while (1); } /* SEMC_END (Crash on irq when data already handled - DMS00718508) */ if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE) writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1); if (!host->curr.xfer_remain) writel(0, base + MMCIMASK1); return IRQ_HANDLED; }
static irqreturn_t msmsdcc_pio_irq(int irq, void *dev_id) { struct msmsdcc_host *host = dev_id; void __iomem *base = host->base; uint32_t status; status = readl(base + MMCISTATUS); #if IRQ_DEBUG msmsdcc_print_status(host, "irq1-r", status); #endif do { unsigned long flags; unsigned int remain, len; char *buffer; if (!(status & (MCI_TXFIFOHALFEMPTY | MCI_RXDATAAVLBL))) break; /* Map the current scatter buffer */ local_irq_save(flags); buffer = kmap_atomic(sg_page(host->pio.sg), KM_BIO_SRC_IRQ) + host->pio.sg->offset; buffer += host->pio.sg_off; remain = host->pio.sg->length - host->pio.sg_off; len = 0; if (status & MCI_RXACTIVE) len = msmsdcc_pio_read(host, buffer, remain); if (status & MCI_TXACTIVE) len = msmsdcc_pio_write(host, buffer, remain, status); /* Unmap the buffer */ kunmap_atomic(buffer, KM_BIO_SRC_IRQ); local_irq_restore(flags); host->pio.sg_off += len; host->curr.xfer_remain -= len; host->curr.data_xfered += len; remain -= len; if (remain) /* Done with this page? */ break; /* Nope */ if (status & MCI_RXACTIVE && host->curr.user_pages) flush_dcache_page(sg_page(host->pio.sg)); if (!--host->pio.sg_len) { memset(&host->pio, 0, sizeof(host->pio)); break; } /* Advance to next sg */ host->pio.sg++; host->pio.sg_off = 0; status = readl(base + MMCISTATUS); } while (1); if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE) { writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1); if (!host->curr.xfer_remain) { /* Delay needed (same port was just written) */ msmsdcc_delay(host); writel(0, base + MMCIMASK1); } } else if (!host->curr.xfer_remain) writel(0, base + MMCIMASK1); return IRQ_HANDLED; }