patch-2.4.22 linux-2.4.22/arch/arm/kernel/dma-rpc.c

Next file: linux-2.4.22/arch/arm/kernel/dma.c
Previous file: linux-2.4.22/arch/arm/kernel/dma-riscstation.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.21/arch/arm/kernel/dma-rpc.c linux-2.4.22/arch/arm/kernel/dma-rpc.c
@@ -91,76 +91,40 @@
 	sg->length |= flags;
 }
 
-static inline void iomd_setup_dma_a(struct scatterlist *sg, dma_t *dma)
-{
-	iomd_writel(sg->dma_address, dma->dma_base + CURA);
-	iomd_writel(sg->length, dma->dma_base + ENDA);
-}
-
-static inline void iomd_setup_dma_b(struct scatterlist *sg, dma_t *dma)
-{
-	iomd_writel(sg->dma_address, dma->dma_base + CURB);
-	iomd_writel(sg->length, dma->dma_base + ENDB);
-}
-
 static void iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs)
 {
 	dma_t *dma = (dma_t *)dev_id;
-	unsigned int status = 0, no_buffer = dma->sg == NULL;
+	unsigned long base = dma->dma_base;
 
 	do {
-		switch (dma->state) {
-		case state_prog_a:
-			iomd_get_next_sg(&dma->cur_sg, dma);
-			iomd_setup_dma_a(&dma->cur_sg, dma);
-			dma->state = state_wait_a;
-
-		case state_wait_a:
-			status = iomd_readb(dma->dma_base + ST);
-			switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) {
-			case DMA_ST_OFL|DMA_ST_INT:
-				iomd_get_next_sg(&dma->cur_sg, dma);
-				iomd_setup_dma_a(&dma->cur_sg, dma);
-				break;
-
-			case DMA_ST_INT:
-				iomd_get_next_sg(&dma->cur_sg, dma);
-				iomd_setup_dma_b(&dma->cur_sg, dma);
-				dma->state = state_wait_b;
-				break;
-
-			case DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB:
-				iomd_setup_dma_b(&dma->cur_sg, dma);
-				dma->state = state_wait_b;
-				break;
-			}
+		unsigned int status;
+
+		status = iomd_readb(base + ST);
+		if (!(status & DMA_ST_INT))
+			return;
+
+		if (status & DMA_ST_OFL && !dma->sg)
+			break;
+
+		iomd_get_next_sg(&dma->cur_sg, dma);
+
+		switch (status & (DMA_ST_OFL | DMA_ST_AB)) {
+		case DMA_ST_OFL:			/* OIA */
+		case DMA_ST_AB:				/* .IB */
+			iomd_writel(dma->cur_sg.dma_address, base + CURA);
+			iomd_writel(dma->cur_sg.length, base + ENDA);
 			break;
 
-		case state_wait_b:
-			status = iomd_readb(dma->dma_base + ST);
-			switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) {
-			case DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB:
-				iomd_get_next_sg(&dma->cur_sg, dma);
-				iomd_setup_dma_b(&dma->cur_sg, dma);
-				break;
-
-			case DMA_ST_INT|DMA_ST_AB:
-				iomd_get_next_sg(&dma->cur_sg, dma);
-				iomd_setup_dma_a(&dma->cur_sg, dma);
-				dma->state = state_wait_a;
-				break;
-
-			case DMA_ST_OFL|DMA_ST_INT:
-				iomd_setup_dma_a(&dma->cur_sg, dma);
-				dma->state = state_wait_a;
-				break;
-			}
+		case DMA_ST_OFL | DMA_ST_AB:		/* OIB */
+		case 0:					/* .IA */
+			iomd_writel(dma->cur_sg.dma_address, base + CURB);
+			iomd_writel(dma->cur_sg.length, base + ENDB);
 			break;
 		}
-	} while (dma->sg && (status & DMA_ST_INT));
+	} while (1);
 
-	if (no_buffer)
-		disable_irq(irq);
+	iomd_writeb(0, base + CR);
+	disable_irq(irq);
 }
 
 static int iomd_request_dma(dmach_t channel, dma_t *dma)
@@ -194,7 +158,6 @@
 		}
 
 		iomd_writeb(DMA_CR_C, dma_base + CR);
-		dma->state = state_prog_a;
 	}
 		
 	if (dma->dma_mode == DMA_MODE_READ)
@@ -207,11 +170,15 @@
 static void iomd_disable_dma(dmach_t channel, dma_t *dma)
 {
 	unsigned long dma_base = dma->dma_base;
+	unsigned long flags;
 	unsigned int ctrl;
 
-	disable_irq(dma->dma_irq);
+	local_irq_save(flags);
 	ctrl = iomd_readb(dma_base + CR);
+	if (ctrl & DMA_CR_E)
+		disable_irq(dma->dma_irq);
 	iomd_writeb(ctrl & ~DMA_CR_E, dma_base + CR);
+	local_irq_restore(flags);
 }
 
 static int iomd_set_dma_speed(dmach_t channel, dma_t *dma, int cycle)

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)