Commit 5b35746a authored by Linus Walleij's avatar Linus Walleij Committed by Ulf Hansson

Revert "mmc: mvsdio: Use sg_miter for PIO"

This reverts commit 2761822c.

When testing on real hardware the patch does not work.
Revert, try to acquire real hardware, and retry.
These systems typically don't have highmem anyway so the
impact is likely zero.

Cc: stable@vger.kernel.org
Reported-by: default avatarCharlie <g4sra@protonmail.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20240927-kirkwood-mmc-regression-v1-1-2e55bbbb7b19@linaro.orgSigned-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent c26339fa
...@@ -38,9 +38,8 @@ struct mvsd_host { ...@@ -38,9 +38,8 @@ struct mvsd_host {
unsigned int xfer_mode; unsigned int xfer_mode;
unsigned int intr_en; unsigned int intr_en;
unsigned int ctrl; unsigned int ctrl;
bool use_pio;
struct sg_mapping_iter sg_miter;
unsigned int pio_size; unsigned int pio_size;
void *pio_ptr;
unsigned int sg_frags; unsigned int sg_frags;
unsigned int ns_per_clk; unsigned int ns_per_clk;
unsigned int clock; unsigned int clock;
...@@ -115,18 +114,11 @@ static int mvsd_setup_data(struct mvsd_host *host, struct mmc_data *data) ...@@ -115,18 +114,11 @@ static int mvsd_setup_data(struct mvsd_host *host, struct mmc_data *data)
* data when the buffer is not aligned on a 64 byte * data when the buffer is not aligned on a 64 byte
* boundary. * boundary.
*/ */
unsigned int miter_flags = SG_MITER_ATOMIC; /* Used from IRQ */
if (data->flags & MMC_DATA_READ)
miter_flags |= SG_MITER_TO_SG;
else
miter_flags |= SG_MITER_FROM_SG;
host->pio_size = data->blocks * data->blksz; host->pio_size = data->blocks * data->blksz;
sg_miter_start(&host->sg_miter, data->sg, data->sg_len, miter_flags); host->pio_ptr = sg_virt(data->sg);
if (!nodma) if (!nodma)
dev_dbg(host->dev, "fallback to PIO for data\n"); dev_dbg(host->dev, "fallback to PIO for data at 0x%p size %d\n",
host->use_pio = true; host->pio_ptr, host->pio_size);
return 1; return 1;
} else { } else {
dma_addr_t phys_addr; dma_addr_t phys_addr;
...@@ -137,7 +129,6 @@ static int mvsd_setup_data(struct mvsd_host *host, struct mmc_data *data) ...@@ -137,7 +129,6 @@ static int mvsd_setup_data(struct mvsd_host *host, struct mmc_data *data)
phys_addr = sg_dma_address(data->sg); phys_addr = sg_dma_address(data->sg);
mvsd_write(MVSD_SYS_ADDR_LOW, (u32)phys_addr & 0xffff); mvsd_write(MVSD_SYS_ADDR_LOW, (u32)phys_addr & 0xffff);
mvsd_write(MVSD_SYS_ADDR_HI, (u32)phys_addr >> 16); mvsd_write(MVSD_SYS_ADDR_HI, (u32)phys_addr >> 16);
host->use_pio = false;
return 0; return 0;
} }
} }
...@@ -297,8 +288,8 @@ static u32 mvsd_finish_data(struct mvsd_host *host, struct mmc_data *data, ...@@ -297,8 +288,8 @@ static u32 mvsd_finish_data(struct mvsd_host *host, struct mmc_data *data,
{ {
void __iomem *iobase = host->base; void __iomem *iobase = host->base;
if (host->use_pio) { if (host->pio_ptr) {
sg_miter_stop(&host->sg_miter); host->pio_ptr = NULL;
host->pio_size = 0; host->pio_size = 0;
} else { } else {
dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_frags, dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_frags,
...@@ -353,12 +344,9 @@ static u32 mvsd_finish_data(struct mvsd_host *host, struct mmc_data *data, ...@@ -353,12 +344,9 @@ static u32 mvsd_finish_data(struct mvsd_host *host, struct mmc_data *data,
static irqreturn_t mvsd_irq(int irq, void *dev) static irqreturn_t mvsd_irq(int irq, void *dev)
{ {
struct mvsd_host *host = dev; struct mvsd_host *host = dev;
struct sg_mapping_iter *sgm = &host->sg_miter;
void __iomem *iobase = host->base; void __iomem *iobase = host->base;
u32 intr_status, intr_done_mask; u32 intr_status, intr_done_mask;
int irq_handled = 0; int irq_handled = 0;
u16 *p;
int s;
intr_status = mvsd_read(MVSD_NOR_INTR_STATUS); intr_status = mvsd_read(MVSD_NOR_INTR_STATUS);
dev_dbg(host->dev, "intr 0x%04x intr_en 0x%04x hw_state 0x%04x\n", dev_dbg(host->dev, "intr 0x%04x intr_en 0x%04x hw_state 0x%04x\n",
...@@ -382,36 +370,15 @@ static irqreturn_t mvsd_irq(int irq, void *dev) ...@@ -382,36 +370,15 @@ static irqreturn_t mvsd_irq(int irq, void *dev)
spin_lock(&host->lock); spin_lock(&host->lock);
/* PIO handling, if needed. Messy business... */ /* PIO handling, if needed. Messy business... */
if (host->use_pio) { if (host->pio_size &&
/*
* As we set sgm->consumed this always gives a valid buffer
* position.
*/
if (!sg_miter_next(sgm)) {
/* This should not happen */
dev_err(host->dev, "ran out of scatter segments\n");
spin_unlock(&host->lock);
host->intr_en &=
~(MVSD_NOR_RX_READY | MVSD_NOR_RX_FIFO_8W |
MVSD_NOR_TX_AVAIL | MVSD_NOR_TX_FIFO_8W);
mvsd_write(MVSD_NOR_INTR_EN, host->intr_en);
return IRQ_HANDLED;
}
p = sgm->addr;
s = sgm->length;
if (s > host->pio_size)
s = host->pio_size;
}
if (host->use_pio &&
(intr_status & host->intr_en & (intr_status & host->intr_en &
(MVSD_NOR_RX_READY | MVSD_NOR_RX_FIFO_8W))) { (MVSD_NOR_RX_READY | MVSD_NOR_RX_FIFO_8W))) {
u16 *p = host->pio_ptr;
int s = host->pio_size;
while (s >= 32 && (intr_status & MVSD_NOR_RX_FIFO_8W)) { while (s >= 32 && (intr_status & MVSD_NOR_RX_FIFO_8W)) {
readsw(iobase + MVSD_FIFO, p, 16); readsw(iobase + MVSD_FIFO, p, 16);
p += 16; p += 16;
s -= 32; s -= 32;
sgm->consumed += 32;
intr_status = mvsd_read(MVSD_NOR_INTR_STATUS); intr_status = mvsd_read(MVSD_NOR_INTR_STATUS);
} }
/* /*
...@@ -424,7 +391,6 @@ static irqreturn_t mvsd_irq(int irq, void *dev) ...@@ -424,7 +391,6 @@ static irqreturn_t mvsd_irq(int irq, void *dev)
put_unaligned(mvsd_read(MVSD_FIFO), p++); put_unaligned(mvsd_read(MVSD_FIFO), p++);
put_unaligned(mvsd_read(MVSD_FIFO), p++); put_unaligned(mvsd_read(MVSD_FIFO), p++);
s -= 4; s -= 4;
sgm->consumed += 4;
intr_status = mvsd_read(MVSD_NOR_INTR_STATUS); intr_status = mvsd_read(MVSD_NOR_INTR_STATUS);
} }
if (s && s < 4 && (intr_status & MVSD_NOR_RX_READY)) { if (s && s < 4 && (intr_status & MVSD_NOR_RX_READY)) {
...@@ -432,13 +398,10 @@ static irqreturn_t mvsd_irq(int irq, void *dev) ...@@ -432,13 +398,10 @@ static irqreturn_t mvsd_irq(int irq, void *dev)
val[0] = mvsd_read(MVSD_FIFO); val[0] = mvsd_read(MVSD_FIFO);
val[1] = mvsd_read(MVSD_FIFO); val[1] = mvsd_read(MVSD_FIFO);
memcpy(p, ((void *)&val) + 4 - s, s); memcpy(p, ((void *)&val) + 4 - s, s);
sgm->consumed += s;
s = 0; s = 0;
intr_status = mvsd_read(MVSD_NOR_INTR_STATUS); intr_status = mvsd_read(MVSD_NOR_INTR_STATUS);
} }
/* PIO transfer done */ if (s == 0) {
host->pio_size -= sgm->consumed;
if (host->pio_size == 0) {
host->intr_en &= host->intr_en &=
~(MVSD_NOR_RX_READY | MVSD_NOR_RX_FIFO_8W); ~(MVSD_NOR_RX_READY | MVSD_NOR_RX_FIFO_8W);
mvsd_write(MVSD_NOR_INTR_EN, host->intr_en); mvsd_write(MVSD_NOR_INTR_EN, host->intr_en);
...@@ -450,10 +413,14 @@ static irqreturn_t mvsd_irq(int irq, void *dev) ...@@ -450,10 +413,14 @@ static irqreturn_t mvsd_irq(int irq, void *dev)
} }
dev_dbg(host->dev, "pio %d intr 0x%04x hw_state 0x%04x\n", dev_dbg(host->dev, "pio %d intr 0x%04x hw_state 0x%04x\n",
s, intr_status, mvsd_read(MVSD_HW_STATE)); s, intr_status, mvsd_read(MVSD_HW_STATE));
host->pio_ptr = p;
host->pio_size = s;
irq_handled = 1; irq_handled = 1;
} else if (host->use_pio && } else if (host->pio_size &&
(intr_status & host->intr_en & (intr_status & host->intr_en &
(MVSD_NOR_TX_AVAIL | MVSD_NOR_TX_FIFO_8W))) { (MVSD_NOR_TX_AVAIL | MVSD_NOR_TX_FIFO_8W))) {
u16 *p = host->pio_ptr;
int s = host->pio_size;
/* /*
* The TX_FIFO_8W bit is unreliable. When set, bursting * The TX_FIFO_8W bit is unreliable. When set, bursting
* 16 halfwords all at once in the FIFO drops data. Actually * 16 halfwords all at once in the FIFO drops data. Actually
...@@ -464,7 +431,6 @@ static irqreturn_t mvsd_irq(int irq, void *dev) ...@@ -464,7 +431,6 @@ static irqreturn_t mvsd_irq(int irq, void *dev)
mvsd_write(MVSD_FIFO, get_unaligned(p++)); mvsd_write(MVSD_FIFO, get_unaligned(p++));
mvsd_write(MVSD_FIFO, get_unaligned(p++)); mvsd_write(MVSD_FIFO, get_unaligned(p++));
s -= 4; s -= 4;
sgm->consumed += 4;
intr_status = mvsd_read(MVSD_NOR_INTR_STATUS); intr_status = mvsd_read(MVSD_NOR_INTR_STATUS);
} }
if (s < 4) { if (s < 4) {
...@@ -473,13 +439,10 @@ static irqreturn_t mvsd_irq(int irq, void *dev) ...@@ -473,13 +439,10 @@ static irqreturn_t mvsd_irq(int irq, void *dev)
memcpy(((void *)&val) + 4 - s, p, s); memcpy(((void *)&val) + 4 - s, p, s);
mvsd_write(MVSD_FIFO, val[0]); mvsd_write(MVSD_FIFO, val[0]);
mvsd_write(MVSD_FIFO, val[1]); mvsd_write(MVSD_FIFO, val[1]);
sgm->consumed += s;
s = 0; s = 0;
intr_status = mvsd_read(MVSD_NOR_INTR_STATUS); intr_status = mvsd_read(MVSD_NOR_INTR_STATUS);
} }
/* PIO transfer done */ if (s == 0) {
host->pio_size -= sgm->consumed;
if (host->pio_size == 0) {
host->intr_en &= host->intr_en &=
~(MVSD_NOR_TX_AVAIL | MVSD_NOR_TX_FIFO_8W); ~(MVSD_NOR_TX_AVAIL | MVSD_NOR_TX_FIFO_8W);
mvsd_write(MVSD_NOR_INTR_EN, host->intr_en); mvsd_write(MVSD_NOR_INTR_EN, host->intr_en);
...@@ -487,6 +450,8 @@ static irqreturn_t mvsd_irq(int irq, void *dev) ...@@ -487,6 +450,8 @@ static irqreturn_t mvsd_irq(int irq, void *dev)
} }
dev_dbg(host->dev, "pio %d intr 0x%04x hw_state 0x%04x\n", dev_dbg(host->dev, "pio %d intr 0x%04x hw_state 0x%04x\n",
s, intr_status, mvsd_read(MVSD_HW_STATE)); s, intr_status, mvsd_read(MVSD_HW_STATE));
host->pio_ptr = p;
host->pio_size = s;
irq_handled = 1; irq_handled = 1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment