patch-2.4.0-test9 linux/drivers/ieee1394/video1394.c

Next file: linux/drivers/ieee1394/video1394.h
Previous file: linux/drivers/ieee1394/raw1394.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test8/linux/drivers/ieee1394/video1394.c linux/drivers/ieee1394/video1394.c
@@ -57,6 +57,10 @@
 #define ISO_RECEIVE 0
 #define ISO_TRANSMIT 1
 
+#ifndef virt_to_page
+#define virt_to_page(x) MAP_NR(x)
+#endif
+
 struct it_dma_prg {
 	struct dma_cmd begin;
 	quadlet_t data[4];
@@ -84,6 +88,7 @@
 	int cmdPtr;
 	int ctxMatch;
 	wait_queue_head_t waitq;
+        spinlock_t lock;
 };
 
 struct video_card {
@@ -144,7 +149,7 @@
  */
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
-#define page_address(x)	((void *) (x))
+#define page_address(x)	(x)
 #endif
 
 /* Given PGD from the address space's page table, return the kernel
@@ -163,7 +168,7 @@
                         pte = *ptep;
                         if(pte_present(pte)) {
 				ret = (unsigned long) page_address(pte_page(pte));
-				ret |= (adr & (PAGE_SIZE - 1));
+                                ret |= (adr & (PAGE_SIZE - 1));
 			}
                 }
         }
@@ -212,7 +217,7 @@
 	void * mem;
 	unsigned long adr, page;
         
-	mem=vmalloc(size);
+	mem=vmalloc_32(size);
 	if (mem) 
 	{
 		memset(mem, 0, size); /* Clear the ram out, 
@@ -374,7 +379,7 @@
 		
 		d->packet_size = packet_size;
 
-		if (PAGE_SIZE % packet_size || packet_size>2048) {
+		if (PAGE_SIZE % packet_size || packet_size>4096) {
 			PRINT(KERN_ERR, ohci->id, 
 			      "Packet size %d not yet supported\n",
 			      packet_size);
@@ -413,6 +418,8 @@
 	}
 	memset(d->buffer_status, 0, d->num_desc * sizeof(unsigned int));
 	
+        spin_lock_init(&d->lock);
+
 	PRINT(KERN_INFO, ohci->id, "Iso %s DMA: %d buffers "
 	      "of size %d allocated for a frame size %d, each with %d prgs",
 	      (type==ISO_RECEIVE) ? "receive" : "transmit",
@@ -531,12 +538,14 @@
 		return -EFAULT;
 	}
 
+	spin_lock(&d->lock);
 	for (i=0;i<d->num_desc;i++) {
 		if (d->ir_prg[i][d->nb_cmd-1].status & 0xFFFF0000) {
 			reset_ir_status(d, i);
 			d->buffer_status[i] = VIDEO1394_BUFFER_READY;
 		}
 	}
+	spin_unlock(&d->lock);
 	if (waitqueue_active(&d->waitq)) wake_up_interruptible(&d->waitq);
 	return 0;
 }
@@ -551,12 +560,14 @@
 		return -EFAULT;
 	}
 
+	spin_lock(&d->lock);
 	for (i=0;i<d->num_desc;i++) {
 		if (d->it_prg[i][d->nb_cmd-1].end.status & 0xFFFF0000) {
 			d->it_prg[i][d->nb_cmd-1].end.status = 0;
 			d->buffer_status[i] = VIDEO1394_BUFFER_READY;
 		}
 	}
+	spin_unlock(&d->lock);
 	if (waitqueue_active(&d->waitq)) wake_up_interruptible(&d->waitq);
 	return 0;
 }
@@ -664,6 +675,7 @@
 {
 	struct video_card *video = &video_cards[MINOR(inode->i_rdev)];
 	struct ti_ohci *ohci= video->ohci;
+	unsigned long flags;
 
 	switch(cmd)
 	{
@@ -832,9 +844,12 @@
 			return -EFAULT;
 		}
 		
-		if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) {
+		spin_lock_irqsave(&d->lock,flags);
+
+		if (d->buffer_status[v.buffer]==VIDEO1394_BUFFER_QUEUED) {
 			PRINT(KERN_ERR, ohci->id, 
 			      "buffer %d is already used",v.buffer);
+			spin_unlock_irqrestore(&d->lock,flags);
 			return -EFAULT;
 		}
 		
@@ -849,6 +864,8 @@
 
 		d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = 0;
 
+		spin_unlock_irqrestore(&d->lock,flags);
+
 		if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) 
 		{
 			DBGMSG(ohci->id, "Starting iso DMA ctx=%d",d->ctx);
@@ -890,16 +907,26 @@
 			return -EFAULT;
 		}
 
+		/*
+		 * I change the way it works so that it returns 
+		 * the last received frame.
+		 */
+		spin_lock_irqsave(&d->lock, flags);
 		switch(d->buffer_status[v.buffer]) {
 		case VIDEO1394_BUFFER_READY:
 			d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
-			return 0;
+			break;
 		case VIDEO1394_BUFFER_QUEUED:
 #if 1
 			while(d->buffer_status[v.buffer]!=
 			      VIDEO1394_BUFFER_READY) {
+				spin_unlock_irqrestore(&d->lock, flags);
 				interruptible_sleep_on(&d->waitq);
-				if(signal_pending(current)) return -EINTR;
+				spin_lock_irqsave(&d->lock, flags);
+				if(signal_pending(current)) {
+					spin_unlock_irqrestore(&d->lock,flags);
+					return -EINTR;
+				}
 			}
 #else
 			if (wait_event_interruptible(d->waitq, 
@@ -909,12 +936,30 @@
 				return -EINTR;
 #endif
 			d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
-			return 0;
+			break;
 		default:
 			PRINT(KERN_ERR, ohci->id, 
 			      "buffer %d is not queued",v.buffer);
+			spin_unlock_irqrestore(&d->lock, flags);
 			return -EFAULT;
 		}
+
+		/*
+		 * Look ahead to see how many more buffers have been received
+		 */
+		i=0;
+		while (d->buffer_status[(v.buffer+1)%d->num_desc]==
+		       VIDEO1394_BUFFER_READY) {
+			v.buffer=(v.buffer+1)%d->num_desc;
+			i++;
+		}
+		spin_unlock_irqrestore(&d->lock, flags);
+
+		v.buffer=i;
+		if(copy_to_user((void *)arg, &v, sizeof(v)))
+			return -EFAULT;
+
+		return 0;
 	}
 	case VIDEO1394_TALK_QUEUE_BUFFER:
 	{
@@ -935,9 +980,12 @@
 			return -EFAULT;
 		}
 		
+		spin_lock_irqsave(&d->lock,flags);
+
 		if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) {
 			PRINT(KERN_ERR, ohci->id, 
 			      "buffer %d is already used",v.buffer);
+			spin_unlock_irqrestore(&d->lock,flags);
 			return -EFAULT;
 		}
 		
@@ -957,6 +1005,8 @@
 		d->last_buffer = v.buffer;
 
 		d->it_prg[d->last_buffer][d->nb_cmd-1].end.branchAddress = 0;
+
+		spin_unlock_irqrestore(&d->lock,flags);
 
 		if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) 
 		{

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