linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] Resurect RiscPC support
@ 2019-05-20 14:46 Russell King - ARM Linux admin
  2019-05-20 14:46 ` [PATCH 1/8] ARM: riscpc: replace gettimeoffset() with clocksource Russell King
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Russell King - ARM Linux admin @ 2019-05-20 14:46 UTC (permalink / raw)
  To: linux-arm-kernel

Support for RiscPC still mostly works, but there have been some
breakages along the way since 2.6 kernels (the last kernel I ran on my
RiscPC.)  Notable breakages are:

- Conversion to generic IRQ broke the keyboard.
- A patch to avoid modifying SG entries for IOMD DMA broke DMA support
  (which only affects expansion cards.)
- Cosmentic breakage due to printk() behavioural changes.
- The kernel size grew beyond the ability for the RISC OS boot loader
  application to cope, which has been resolved in the latest version of
  !Linux.

These issues are resolved in this series, as well as removing RiscPC's
usage of the old gettimeoffset facility.

However, RiscPC timekeeping suffers greatly on recent kernels compared
to 2.6 series kernels: the change to make all interrupt handlers run
with IRQs off means that we are no longer able to receive timer
interrupts while (eg) PIO data is being transferred to the internal
drive, which is a very time-consuming operation.  This is soo bad that
NTP is unable to fix the problem, and there is no way to resolve this
regression from a hardware point of view.

That said, using an external disk connected via an expansion card
allows the use of DMA, thereby allowing the problem to be bypassed.

Keeping RiscPC support alive in the kernel, however, is beneficial to
on-going maintanence of fs/adfs support, which still has users.

This patch series is currently against 5.1, but should merge with
v5.2-rc1.

Merge plan: I'll send a pull request to arm-soc for this in due course.

 arch/arm/Kconfig          |  1 -
 arch/arm/mach-rpc/dma.c   | 97 ++++++++++++++++++++++++-----------------------
 arch/arm/mach-rpc/ecard.c | 11 ++++--
 arch/arm/mach-rpc/irq.c   |  3 +-
 arch/arm/mach-rpc/time.c  | 38 ++++++++++++-------
 5 files changed, 83 insertions(+), 67 deletions(-)

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/8] ARM: riscpc: replace gettimeoffset() with clocksource
  2019-05-20 14:46 [PATCH 0/8] Resurect RiscPC support Russell King - ARM Linux admin
@ 2019-05-20 14:46 ` Russell King
  2019-05-20 14:46 ` [PATCH 2/8] ARM: riscpc: fix lack of keyboard interrupts after irq conversion Russell King
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Russell King @ 2019-05-20 14:46 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the old gettimeoffset() interface (which became buggy in
several ways) with a clocksource that atomically reads the count
and status from the timer, and corrects the count as appropriate
ensuring proper resolution of time without time warping backwards.

We keep the original periodic timer non-clock event implementation
to provide the kernel with a regular source of interrupts, which
are required to keep the clocksource properly updated.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 arch/arm/Kconfig         |  1 -
 arch/arm/mach-rpc/time.c | 38 +++++++++++++++++++++++++-------------
 2 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9aed25a6019b..08a4915a69d2 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -528,7 +528,6 @@ config ARCH_RPC
 	select ARCH_ACORN
 	select ARCH_MAY_HAVE_PC_FDC
 	select ARCH_SPARSEMEM_ENABLE
-	select ARCH_USES_GETTIMEOFFSET
 	select CPU_SA110
 	select FIQ
 	select HAVE_IDE
diff --git a/arch/arm/mach-rpc/time.c b/arch/arm/mach-rpc/time.c
index 2689771c1d38..1c84efc9db1f 100644
--- a/arch/arm/mach-rpc/time.c
+++ b/arch/arm/mach-rpc/time.c
@@ -13,7 +13,7 @@
  *   04-Dec-1997	RMK	Updated for new arch/arm/time.c
  *   13=Jun-2004	DS	Moved to arch/arm/common b/c shared w/CLPS7500
  */
-#include <linux/timex.h>
+#include <linux/clocksource.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
@@ -27,11 +27,15 @@
 #define RPC_CLOCK_FREQ 2000000
 #define RPC_LATCH DIV_ROUND_CLOSEST(RPC_CLOCK_FREQ, HZ)
 
-static u32 ioc_timer_gettimeoffset(void)
+static u32 ioc_time;
+
+static u64 ioc_timer_read(struct clocksource *cs)
 {
 	unsigned int count1, count2, status;
-	long offset;
+	unsigned long flags;
+	u32 ticks;
 
+	local_irq_save(flags);
 	ioc_writeb (0, IOC_T0LATCH);
 	barrier ();
 	count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
@@ -41,27 +45,34 @@ static u32 ioc_timer_gettimeoffset(void)
 	ioc_writeb (0, IOC_T0LATCH);
 	barrier ();
 	count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
+	ticks = ioc_time + RPC_LATCH - count2;
+	local_irq_restore(flags);
 
-	offset = count2;
 	if (count2 < count1) {
 		/*
-		 * We have not had an interrupt between reading count1
-		 * and count2.
+		 * The timer has not reloaded between reading count1 and
+		 * count2, check whether an interrupt was actually pending.
 		 */
 		if (status & (1 << 5))
-			offset -= RPC_LATCH;
+			ticks += RPC_LATCH;
 	} else if (count2 > count1) {
 		/*
-		 * We have just had another interrupt between reading
-		 * count1 and count2.
+		 * The timer has reloaded, so count2 indicates the new
+		 * count since the wrap.  The interrupt would not have
+		 * been processed, so add the missed ticks.
 		 */
-		offset -= RPC_LATCH;
+		ticks += RPC_LATCH;
 	}
 
-	offset = (RPC_LATCH - offset) * (tick_nsec / 1000);
-	return DIV_ROUND_CLOSEST(offset, RPC_LATCH) * 1000;
+	return ticks;
 }
 
+static struct clocksource ioctime_clocksource = {
+	.read = ioc_timer_read,
+	.mask = CLOCKSOURCE_MASK(32),
+	.rating = 100,
+};
+
 void __init ioctime_init(void)
 {
 	ioc_writeb(RPC_LATCH & 255, IOC_T0LTCHL);
@@ -72,6 +83,7 @@ void __init ioctime_init(void)
 static irqreturn_t
 ioc_timer_interrupt(int irq, void *dev_id)
 {
+	ioc_time += RPC_LATCH;
 	timer_tick();
 	return IRQ_HANDLED;
 }
@@ -86,7 +98,7 @@ static struct irqaction ioc_timer_irq = {
  */
 void __init ioc_timer_init(void)
 {
-	arch_gettimeoffset = ioc_timer_gettimeoffset;
+	WARN_ON(clocksource_register_hz(&ioctime_clocksource, RPC_CLOCK_FREQ));
 	ioctime_init();
 	setup_irq(IRQ_TIMER0, &ioc_timer_irq);
 }
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/8] ARM: riscpc: fix lack of keyboard interrupts after irq conversion
  2019-05-20 14:46 [PATCH 0/8] Resurect RiscPC support Russell King - ARM Linux admin
  2019-05-20 14:46 ` [PATCH 1/8] ARM: riscpc: replace gettimeoffset() with clocksource Russell King
@ 2019-05-20 14:46 ` Russell King
  2019-05-20 14:47 ` [PATCH 3/8] ARM: riscpc: fix ecard printing Russell King
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Russell King @ 2019-05-20 14:46 UTC (permalink / raw)
  To: linux-arm-kernel

Fix lack of keyboard interrupts for RiscPC due to incorrect conversion.

Fixes: e8d36d5dbb6a ("ARM: kill off set_irq_flags usage")
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 arch/arm/mach-rpc/irq.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-rpc/irq.c b/arch/arm/mach-rpc/irq.c
index b8a61cb11207..7f0f40178634 100644
--- a/arch/arm/mach-rpc/irq.c
+++ b/arch/arm/mach-rpc/irq.c
@@ -118,7 +118,7 @@ extern unsigned char rpc_default_fiq_start, rpc_default_fiq_end;
 
 void __init rpc_init_irq(void)
 {
-	unsigned int irq, clr, set = 0;
+	unsigned int irq, clr, set;
 
 	iomd_writeb(0, IOMD_IRQMASKA);
 	iomd_writeb(0, IOMD_IRQMASKB);
@@ -130,6 +130,7 @@ void __init rpc_init_irq(void)
 
 	for (irq = 0; irq < NR_IRQS; irq++) {
 		clr = IRQ_NOREQUEST;
+		set = 0;
 
 		if (irq <= 6 || (irq >= 9 && irq <= 15))
 			clr |= IRQ_NOPROBE;
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/8] ARM: riscpc: fix ecard printing
  2019-05-20 14:46 [PATCH 0/8] Resurect RiscPC support Russell King - ARM Linux admin
  2019-05-20 14:46 ` [PATCH 1/8] ARM: riscpc: replace gettimeoffset() with clocksource Russell King
  2019-05-20 14:46 ` [PATCH 2/8] ARM: riscpc: fix lack of keyboard interrupts after irq conversion Russell King
@ 2019-05-20 14:47 ` Russell King
  2019-05-20 14:47 ` [PATCH 4/8] ARM: riscpc: fix DMA Russell King
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Russell King @ 2019-05-20 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

Multiple printk() statements appear to get broken into separate lines,
which messes up the formatting.  Fix these up.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 arch/arm/mach-rpc/ecard.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-rpc/ecard.c b/arch/arm/mach-rpc/ecard.c
index 04b2f22c2739..3e7b81cc4274 100644
--- a/arch/arm/mach-rpc/ecard.c
+++ b/arch/arm/mach-rpc/ecard.c
@@ -496,18 +496,21 @@ static void ecard_dump_irq_state(void)
 	printk("Expansion card IRQ state:\n");
 
 	for (ec = cards; ec; ec = ec->next) {
+		const char *claimed;
+
 		if (ec->slot_no == 8)
 			continue;
 
-		printk("  %d: %sclaimed, ",
-		       ec->slot_no, ec->claimed ? "" : "not ");
+		claimed = ec->claimed ? "" : "not ";
 
 		if (ec->ops && ec->ops->irqpending &&
 		    ec->ops != &ecard_default_ops)
-			printk("irq %spending\n",
+			printk("  %d: %sclaimed irq %spending\n",
+			       ec->slot_no, claimed,
 			       ec->ops->irqpending(ec) ? "" : "not ");
 		else
-			printk("irqaddr %p, mask = %02X, status = %02X\n",
+			printk("  %d: %sclaimed irqaddr %p, mask = %02X, status = %02X\n",
+			       ec->slot_no, claimed,
 			       ec->irqaddr, ec->irqmask, readb(ec->irqaddr));
 	}
 }
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/8] ARM: riscpc: fix DMA
  2019-05-20 14:46 [PATCH 0/8] Resurect RiscPC support Russell King - ARM Linux admin
                   ` (2 preceding siblings ...)
  2019-05-20 14:47 ` [PATCH 3/8] ARM: riscpc: fix ecard printing Russell King
@ 2019-05-20 14:47 ` Russell King
  2019-05-20 14:47 ` [PATCH 5/8] ARM: riscpc: dma: eliminate "cur_sg" scatterlist usage Russell King
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Russell King @ 2019-05-20 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

DMA got broken a while back in two different ways:
1) a change in the behaviour of disable_irq() to wait for the interrupt
   to finish executing causes us to deadlock at the end of DMA.
2) a change to avoid modifying the scatterlist left the first transfer
   uninitialised.

DMA is only used with expansion cards, so has gone unnoticed.

Fixes: fa4e99899932 ("[ARM] dma: RiscPC: don't modify DMA SG entries")
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 arch/arm/mach-rpc/dma.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c
index fb48f3141fb4..c4c96661eb89 100644
--- a/arch/arm/mach-rpc/dma.c
+++ b/arch/arm/mach-rpc/dma.c
@@ -131,7 +131,7 @@ static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
 	} while (1);
 
 	idma->state = ~DMA_ST_AB;
-	disable_irq(irq);
+	disable_irq_nosync(irq);
 
 	return IRQ_HANDLED;
 }
@@ -174,6 +174,9 @@ static void iomd_enable_dma(unsigned int chan, dma_t *dma)
 				DMA_FROM_DEVICE : DMA_TO_DEVICE);
 		}
 
+		idma->dma_addr = idma->dma.sg->dma_address;
+		idma->dma_len = idma->dma.sg->length;
+
 		iomd_writeb(DMA_CR_C, dma_base + CR);
 		idma->state = DMA_ST_AB;
 	}
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/8] ARM: riscpc: dma: eliminate "cur_sg" scatterlist usage
  2019-05-20 14:46 [PATCH 0/8] Resurect RiscPC support Russell King - ARM Linux admin
                   ` (3 preceding siblings ...)
  2019-05-20 14:47 ` [PATCH 4/8] ARM: riscpc: fix DMA Russell King
@ 2019-05-20 14:47 ` Russell King
  2019-05-20 14:47 ` [PATCH 6/8] ARM: riscpc: dma: make state a local variable Russell King
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Russell King @ 2019-05-20 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

All we really need is the DMA address and size, we don't need the
baggage of a full scatterlist structure.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 arch/arm/mach-rpc/dma.c | 29 +++++++++++++++--------------
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c
index c4c96661eb89..37750c6493b4 100644
--- a/arch/arm/mach-rpc/dma.c
+++ b/arch/arm/mach-rpc/dma.c
@@ -30,7 +30,8 @@ struct iomd_dma {
 	unsigned int		state;
 	unsigned long		base;		/* Controller base address */
 	int			irq;		/* Controller IRQ */
-	struct scatterlist	cur_sg;		/* Current controller buffer */
+	dma_addr_t		cur_addr;
+	unsigned int		cur_len;
 	dma_addr_t		dma_addr;
 	unsigned int		dma_len;
 };
@@ -53,13 +54,13 @@ typedef enum {
 #define CR	(IOMD_IO0CR - IOMD_IO0CURA)
 #define ST	(IOMD_IO0ST - IOMD_IO0CURA)
 
-static void iomd_get_next_sg(struct scatterlist *sg, struct iomd_dma *idma)
+static void iomd_get_next_sg(struct iomd_dma *idma)
 {
 	unsigned long end, offset, flags = 0;
 
 	if (idma->dma.sg) {
-		sg->dma_address = idma->dma_addr;
-		offset = sg->dma_address & ~PAGE_MASK;
+		idma->cur_addr = idma->dma_addr;
+		offset = idma->cur_addr & ~PAGE_MASK;
 
 		end = offset + idma->dma_len;
 
@@ -69,7 +70,7 @@ static void iomd_get_next_sg(struct scatterlist *sg, struct iomd_dma *idma)
 		if (offset + TRANSFER_SIZE >= end)
 			flags |= DMA_END_L;
 
-		sg->length = end - TRANSFER_SIZE;
+		idma->cur_len = end - TRANSFER_SIZE;
 
 		idma->dma_len -= end - offset;
 		idma->dma_addr += end - offset;
@@ -87,11 +88,11 @@ static void iomd_get_next_sg(struct scatterlist *sg, struct iomd_dma *idma)
 		}
 	} else {
 		flags = DMA_END_S | DMA_END_L;
-		sg->dma_address = 0;
-		sg->length = 0;
+		idma->cur_addr = 0;
+		idma->cur_len = 0;
 	}
 
-	sg->length |= flags;
+	idma->cur_len |= flags;
 }
 
 static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
@@ -107,26 +108,26 @@ static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
 			return IRQ_HANDLED;
 
 		if ((idma->state ^ status) & DMA_ST_AB)
-			iomd_get_next_sg(&idma->cur_sg, idma);
+			iomd_get_next_sg(idma);
 
 		switch (status & (DMA_ST_OFL | DMA_ST_AB)) {
 		case DMA_ST_OFL:			/* OIA */
 		case DMA_ST_AB:				/* .IB */
-			iomd_writel(idma->cur_sg.dma_address, base + CURA);
-			iomd_writel(idma->cur_sg.length, base + ENDA);
+			iomd_writel(idma->cur_addr, base + CURA);
+			iomd_writel(idma->cur_len, base + ENDA);
 			idma->state = DMA_ST_AB;
 			break;
 
 		case DMA_ST_OFL | DMA_ST_AB:		/* OIB */
 		case 0:					/* .IA */
-			iomd_writel(idma->cur_sg.dma_address, base + CURB);
-			iomd_writel(idma->cur_sg.length, base + ENDB);
+			iomd_writel(idma->cur_addr, base + CURB);
+			iomd_writel(idma->cur_len, base + ENDB);
 			idma->state = 0;
 			break;
 		}
 
 		if (status & DMA_ST_OFL &&
-		    idma->cur_sg.length == (DMA_END_S|DMA_END_L))
+		    idma->cur_len == (DMA_END_S|DMA_END_L))
 			break;
 	} while (1);
 
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 6/8] ARM: riscpc: dma: make state a local variable
  2019-05-20 14:46 [PATCH 0/8] Resurect RiscPC support Russell King - ARM Linux admin
                   ` (4 preceding siblings ...)
  2019-05-20 14:47 ` [PATCH 5/8] ARM: riscpc: dma: eliminate "cur_sg" scatterlist usage Russell King
@ 2019-05-20 14:47 ` Russell King
  2019-05-20 14:47 ` [PATCH 7/8] ARM: riscpc: dma: improve address/length writing Russell King
  2019-05-20 14:47 ` [PATCH 8/8] ARM: riscpc: dma: use __iomem pointers for writing DMA Russell King
  7 siblings, 0 replies; 9+ messages in thread
From: Russell King @ 2019-05-20 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

Make state a local variable to avoid rewriting it in the DMA loop.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 arch/arm/mach-rpc/dma.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c
index 37750c6493b4..e2b9c95d853b 100644
--- a/arch/arm/mach-rpc/dma.c
+++ b/arch/arm/mach-rpc/dma.c
@@ -99,15 +99,15 @@ static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
 {
 	struct iomd_dma *idma = dev_id;
 	unsigned long base = idma->base;
+	unsigned int state = idma->state;
+	unsigned int status;
 
 	do {
-		unsigned int status;
-
 		status = iomd_readb(base + ST);
 		if (!(status & DMA_ST_INT))
-			return IRQ_HANDLED;
+			goto out;
 
-		if ((idma->state ^ status) & DMA_ST_AB)
+		if ((state ^ status) & DMA_ST_AB)
 			iomd_get_next_sg(idma);
 
 		switch (status & (DMA_ST_OFL | DMA_ST_AB)) {
@@ -115,14 +115,14 @@ static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
 		case DMA_ST_AB:				/* .IB */
 			iomd_writel(idma->cur_addr, base + CURA);
 			iomd_writel(idma->cur_len, base + ENDA);
-			idma->state = DMA_ST_AB;
+			state = DMA_ST_AB;
 			break;
 
 		case DMA_ST_OFL | DMA_ST_AB:		/* OIB */
 		case 0:					/* .IA */
 			iomd_writel(idma->cur_addr, base + CURB);
 			iomd_writel(idma->cur_len, base + ENDB);
-			idma->state = 0;
+			state = 0;
 			break;
 		}
 
@@ -131,9 +131,10 @@ static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
 			break;
 	} while (1);
 
-	idma->state = ~DMA_ST_AB;
+	state = ~DMA_ST_AB;
 	disable_irq_nosync(irq);
-
+out:
+	idma->state = state;
 	return IRQ_HANDLED;
 }
 
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 7/8] ARM: riscpc: dma: improve address/length writing
  2019-05-20 14:46 [PATCH 0/8] Resurect RiscPC support Russell King - ARM Linux admin
                   ` (5 preceding siblings ...)
  2019-05-20 14:47 ` [PATCH 6/8] ARM: riscpc: dma: make state a local variable Russell King
@ 2019-05-20 14:47 ` Russell King
  2019-05-20 14:47 ` [PATCH 8/8] ARM: riscpc: dma: use __iomem pointers for writing DMA Russell King
  7 siblings, 0 replies; 9+ messages in thread
From: Russell King @ 2019-05-20 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

Rearrange writing the DMA addresses to generate more efficient code.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 arch/arm/mach-rpc/dma.c | 26 +++++++++++---------------
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c
index e2b9c95d853b..6140472d148e 100644
--- a/arch/arm/mach-rpc/dma.c
+++ b/arch/arm/mach-rpc/dma.c
@@ -100,7 +100,7 @@ static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
 	struct iomd_dma *idma = dev_id;
 	unsigned long base = idma->base;
 	unsigned int state = idma->state;
-	unsigned int status;
+	unsigned int status, cur, end;
 
 	do {
 		status = iomd_readb(base + ST);
@@ -110,21 +110,17 @@ static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
 		if ((state ^ status) & DMA_ST_AB)
 			iomd_get_next_sg(idma);
 
-		switch (status & (DMA_ST_OFL | DMA_ST_AB)) {
-		case DMA_ST_OFL:			/* OIA */
-		case DMA_ST_AB:				/* .IB */
-			iomd_writel(idma->cur_addr, base + CURA);
-			iomd_writel(idma->cur_len, base + ENDA);
-			state = DMA_ST_AB;
-			break;
-
-		case DMA_ST_OFL | DMA_ST_AB:		/* OIB */
-		case 0:					/* .IA */
-			iomd_writel(idma->cur_addr, base + CURB);
-			iomd_writel(idma->cur_len, base + ENDB);
-			state = 0;
-			break;
+		// This efficiently implements state = OFL != AB ? AB : 0
+		state = ((status >> 2) ^ status) & DMA_ST_AB;
+		if (state) {
+			cur = CURA;
+			end = ENDA;
+		} else {
+			cur = CURB;
+			end = ENDB;
 		}
+		iomd_writel(idma->cur_addr, base + cur);
+		iomd_writel(idma->cur_len, base + end);
 
 		if (status & DMA_ST_OFL &&
 		    idma->cur_len == (DMA_END_S|DMA_END_L))
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 8/8] ARM: riscpc: dma: use __iomem pointers for writing DMA
  2019-05-20 14:46 [PATCH 0/8] Resurect RiscPC support Russell King - ARM Linux admin
                   ` (6 preceding siblings ...)
  2019-05-20 14:47 ` [PATCH 7/8] ARM: riscpc: dma: improve address/length writing Russell King
@ 2019-05-20 14:47 ` Russell King
  7 siblings, 0 replies; 9+ messages in thread
From: Russell King @ 2019-05-20 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

Use __iomem pointers for efficiency to write the DMA registers.
This avoids the compiler emitting several instructions for each access
to calculate the register address.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 arch/arm/mach-rpc/dma.c | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c
index 6140472d148e..eeda808a7320 100644
--- a/arch/arm/mach-rpc/dma.c
+++ b/arch/arm/mach-rpc/dma.c
@@ -27,9 +27,9 @@
 
 struct iomd_dma {
 	struct dma_struct	dma;
-	unsigned int		state;
-	unsigned long		base;		/* Controller base address */
+	void __iomem		*base;		/* Controller base address */
 	int			irq;		/* Controller IRQ */
+	unsigned int		state;
 	dma_addr_t		cur_addr;
 	unsigned int		cur_len;
 	dma_addr_t		dma_addr;
@@ -98,12 +98,12 @@ static void iomd_get_next_sg(struct iomd_dma *idma)
 static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
 {
 	struct iomd_dma *idma = dev_id;
-	unsigned long base = idma->base;
+	void __iomem *base = idma->base;
 	unsigned int state = idma->state;
 	unsigned int status, cur, end;
 
 	do {
-		status = iomd_readb(base + ST);
+		status = readb(base + ST);
 		if (!(status & DMA_ST_INT))
 			goto out;
 
@@ -119,8 +119,8 @@ static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
 			cur = CURB;
 			end = ENDB;
 		}
-		iomd_writel(idma->cur_addr, base + cur);
-		iomd_writel(idma->cur_len, base + end);
+		writel(idma->cur_addr, base + cur);
+		writel(idma->cur_len, base + end);
 
 		if (status & DMA_ST_OFL &&
 		    idma->cur_len == (DMA_END_S|DMA_END_L))
@@ -152,7 +152,7 @@ static void iomd_free_dma(unsigned int chan, dma_t *dma)
 static void iomd_enable_dma(unsigned int chan, dma_t *dma)
 {
 	struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
-	unsigned long dma_base = idma->base;
+	void __iomem *base = idma->base;
 	unsigned int ctrl = TRANSFER_SIZE | DMA_CR_E;
 
 	if (idma->dma.invalid) {
@@ -175,27 +175,27 @@ static void iomd_enable_dma(unsigned int chan, dma_t *dma)
 		idma->dma_addr = idma->dma.sg->dma_address;
 		idma->dma_len = idma->dma.sg->length;
 
-		iomd_writeb(DMA_CR_C, dma_base + CR);
+		writeb(DMA_CR_C, base + CR);
 		idma->state = DMA_ST_AB;
 	}
 
 	if (idma->dma.dma_mode == DMA_MODE_READ)
 		ctrl |= DMA_CR_D;
 
-	iomd_writeb(ctrl, dma_base + CR);
+	writeb(ctrl, base + CR);
 	enable_irq(idma->irq);
 }
 
 static void iomd_disable_dma(unsigned int chan, dma_t *dma)
 {
 	struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
-	unsigned long dma_base = idma->base;
+	void __iomem *base = idma->base;
 	unsigned long flags;
 
 	local_irq_save(flags);
 	if (idma->state != ~DMA_ST_AB)
 		disable_irq(idma->irq);
-	iomd_writeb(0, dma_base + CR);
+	writeb(0, base + CR);
 	local_irq_restore(flags);
 }
 
@@ -358,17 +358,17 @@ static int __init rpc_dma_init(void)
 	 */
 	iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT);
 
-	iomd_dma[DMA_0].base	= IOMD_IO0CURA;
+	iomd_dma[DMA_0].base	= IOMD_BASE + IOMD_IO0CURA;
 	iomd_dma[DMA_0].irq	= IRQ_DMA0;
-	iomd_dma[DMA_1].base	= IOMD_IO1CURA;
+	iomd_dma[DMA_1].base	= IOMD_BASE + IOMD_IO1CURA;
 	iomd_dma[DMA_1].irq	= IRQ_DMA1;
-	iomd_dma[DMA_2].base	= IOMD_IO2CURA;
+	iomd_dma[DMA_2].base	= IOMD_BASE + IOMD_IO2CURA;
 	iomd_dma[DMA_2].irq	= IRQ_DMA2;
-	iomd_dma[DMA_3].base	= IOMD_IO3CURA;
+	iomd_dma[DMA_3].base	= IOMD_BASE + IOMD_IO3CURA;
 	iomd_dma[DMA_3].irq	= IRQ_DMA3;
-	iomd_dma[DMA_S0].base	= IOMD_SD0CURA;
+	iomd_dma[DMA_S0].base	= IOMD_BASE + IOMD_SD0CURA;
 	iomd_dma[DMA_S0].irq	= IRQ_DMAS0;
-	iomd_dma[DMA_S1].base	= IOMD_SD1CURA;
+	iomd_dma[DMA_S1].base	= IOMD_BASE + IOMD_SD1CURA;
 	iomd_dma[DMA_S1].irq	= IRQ_DMAS1;
 
 	for (i = DMA_0; i <= DMA_S1; i++) {
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2019-05-20 14:48 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-20 14:46 [PATCH 0/8] Resurect RiscPC support Russell King - ARM Linux admin
2019-05-20 14:46 ` [PATCH 1/8] ARM: riscpc: replace gettimeoffset() with clocksource Russell King
2019-05-20 14:46 ` [PATCH 2/8] ARM: riscpc: fix lack of keyboard interrupts after irq conversion Russell King
2019-05-20 14:47 ` [PATCH 3/8] ARM: riscpc: fix ecard printing Russell King
2019-05-20 14:47 ` [PATCH 4/8] ARM: riscpc: fix DMA Russell King
2019-05-20 14:47 ` [PATCH 5/8] ARM: riscpc: dma: eliminate "cur_sg" scatterlist usage Russell King
2019-05-20 14:47 ` [PATCH 6/8] ARM: riscpc: dma: make state a local variable Russell King
2019-05-20 14:47 ` [PATCH 7/8] ARM: riscpc: dma: improve address/length writing Russell King
2019-05-20 14:47 ` [PATCH 8/8] ARM: riscpc: dma: use __iomem pointers for writing DMA Russell King

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).