patch-2.4.27 linux-2.4.27/drivers/ieee1394/video1394.c

Next file: linux-2.4.27/drivers/isdn/divert/divert_procfs.c
Previous file: linux-2.4.27/drivers/ieee1394/sbp2.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.26/drivers/ieee1394/video1394.c linux-2.4.27/drivers/ieee1394/video1394.c
@@ -21,6 +21,9 @@
 /* jds -- add private data to file to keep track of iso contexts associated
    with each open -- so release won't kill all iso transfers */
 
+/* Damien Douxchamps: Fix failure when the number of DMA pages per frame is
+   one */
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
@@ -405,33 +408,43 @@
 				(unsigned long)d->dma.kvirt));
 	ir_prg[0].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
 					1 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
-
-	/* the second descriptor will read PAGE_SIZE-4 bytes */
-	ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
-		DMA_CTL_BRANCH | (PAGE_SIZE-4));
-	ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf + 4) -
-					(unsigned long)d->dma.kvirt));
-	ir_prg[1].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
-					2 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
+	/* if there is *not* only one DMA page per frame (hence, d->nb_cmd==2) */
+ 	if (d->nb_cmd>2) {
+  	        /* the second descriptor will read PAGE_SIZE-4 bytes */
+	        ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
+					        DMA_CTL_BRANCH | (PAGE_SIZE-4));
+		ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf + 4) -
+						(unsigned long)d->dma.kvirt));
+		ir_prg[1].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
+					   2 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
 	
-	for (i=2;i<d->nb_cmd-1;i++) {
+		for (i=2;i<d->nb_cmd-1;i++) {
+		        ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | 
+							DMA_CTL_BRANCH | PAGE_SIZE);
+			ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
+							(buf+(i-1)*PAGE_SIZE) -
+							(unsigned long)d->dma.kvirt));
+
+			ir_prg[i].branchAddress =
+			             cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
+				     (i + 1) * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
+		}
+
+		/* the last descriptor will generate an interrupt */
 		ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | 
-			DMA_CTL_BRANCH | PAGE_SIZE);
+					        DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size);
 		ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
 					        (buf+(i-1)*PAGE_SIZE) -
-						(unsigned long)d->dma.kvirt));
-
-		ir_prg[i].branchAddress =
-			cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
-				(i + 1) * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
+					        (unsigned long)d->dma.kvirt));
+	}
+	else { 
+	       /* only one DMA page is used. Read d->left_size immediately and */
+	       /* generate an interrupt as this is also the last page */
+	       ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | 
+		                           DMA_CTL_IRQ | DMA_CTL_BRANCH | (d->left_size-4));
+	       ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
+		  			       (buf + 4) - (unsigned long)d->dma.kvirt));
 	}
-
-	/* the last descriptor will generate an interrupt */
-	ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | 
-		DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size);
-	ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
-					(buf+(i-1)*PAGE_SIZE) -
-					(unsigned long)d->dma.kvirt));
 }
 	
 static void initialize_dma_ir_ctx(struct dma_iso_ctx *d, int tag, int flags)

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