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

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

diff -u --recursive --new-file v2.4.0-test8/linux/drivers/ieee1394/ohci1394.c linux/drivers/ieee1394/ohci1394.c
@@ -56,6 +56,8 @@
  *  . Apple PowerBook detection
  * Daniel Kobras <daniel.kobras@student.uni-tuebingen.de>
  *  . Reset the board properly before leaving + misc cleanups
+ * Leon van Stuivenberg <leonvs@iae.nl>
+ *  . Bug fixes
  */
 
 #include <linux/config.h>
@@ -253,7 +255,7 @@
 		return -1;
 	}
 	
-	size = ((self_id_count&0x0000EFFC)>>2) - 1;
+	size = ((self_id_count&0x00001FFC)>>2) - 1;
 	q++;
 
 	while (size > 0) {
@@ -652,6 +654,15 @@
 		 * FIXME: check that the packet data buffer
 		 * do not cross a page boundary 
 		 */
+		if (cross_bound((unsigned long)packet->data, 
+				packet->data_size)>0) {
+			/* FIXME: do something about it */
+			PRINT(KERN_ERR, ohci->id, __FUNCTION__
+			      ": packet data addr: %p size %d bytes "
+			      "cross page boundary", 
+			      packet->data, packet->data_size);
+		}
+
 		d->prg_cpu[idx]->end.address =
 			pci_map_single(ohci->dev, packet->data,
 				       packet->data_size, PCI_DMA_TODEVICE);
@@ -734,7 +745,7 @@
 	unsigned char tcode;
 	unsigned long flags;
 
-	if (packet->data_size >= ohci->max_packet_size) {
+	if (packet->data_size > ohci->max_packet_size) {
 		PRINT(KERN_ERR, ohci->id, 
 		      "transmit packet size = %d too big",
 		      packet->data_size);
@@ -803,11 +814,11 @@
 			u32 nodeId = reg_read(ohci, OHCI1394_NodeID);
 			if ((nodeId & (1<<30)) && (nodeId & 0x3f)) {
 				/*
-				 * enable cycleTimer cycleMaster cycleSource
+				 * enable cycleTimer, cycleMaster
 				 */
 				DBGMSG(ohci->id, "Cycle master enabled");
 				reg_write(ohci, OHCI1394_LinkControlSet, 
-					  0x00700000);
+					  0x00300000);
 			}
 		} else {
 			/* disable cycleTimer, cycleMaster, cycleSource */
@@ -830,61 +841,67 @@
                 break;
 
 	case ISO_LISTEN_CHANNEL:
+        {
+                int *isochannels, offset= OHCI1394_IRMultiChanMaskLoSet;
+                unsigned int channel= (unsigned int)arg;
+                unsigned int channelbit= channel;
+                u32 setMask= 0x00000001;
+
+                /* save people from themselves */
+                if (channel > 63)
+                        break;
+
+                if (channel > 31) {
+                        isochannels= &(((int*)&ohci->IR_channel_usage)[0]);
+                        channelbit-= 32;
+                        offset= OHCI1394_IRMultiChanMaskHiSet;
+                }
+                else
+                        isochannels= &(((int*)&ohci->IR_channel_usage)[1]);
 
-                spin_lock_irqsave(&ohci->IR_channel_lock, flags);
+                while(channelbit--) setMask= setMask << 1;
 
-                if (!test_and_set_bit(arg, &ohci->IR_channel_usage)) {
-                        DBGMSG(ohci->id,
-			       "listening enabled on channel %d", arg);
-
-                        if (arg > 31) {
-                                u32 setMask= 0x00000001;
-                                arg-= 32;
-                                while(arg--) setMask= setMask << 1;
-                                reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet,
-                                          setMask);
-                        } else {
-                                u32 setMask= 0x00000001;
-                                while(arg--) setMask= setMask << 1;
-                                reg_write(ohci, OHCI1394_IRMultiChanMaskLoSet,
-                                          setMask);
-                        }
+                spin_lock_irqsave(&ohci->IR_channel_lock, flags);
 
-                }
+                if (!test_and_set_bit(channelbit, isochannels))
+                        reg_write(ohci, offset, setMask);
 
                 spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
+                DBGMSG(ohci->id, "listening enabled on channel %u", channel);
                 break;
-
+        }
 	case ISO_UNLISTEN_CHANNEL:
+        {
+                int *isochannels, offset= OHCI1394_IRMultiChanMaskLoClear;
+                unsigned int channel= (unsigned int)arg;
+                unsigned int channelbit= channel;
+                u32 clearMask= 0x00000001;
+
+                /* save people from themselves */
+                if (channel > 63)
+                        break;
+
+                if (channel > 31) {
+                        isochannels= &(((int*)&ohci->IR_channel_usage)[0]);
+                        channelbit-= 32;
+                        offset= OHCI1394_IRMultiChanMaskHiClear;
+                }
+                else
+                        isochannels= &(((int*)&ohci->IR_channel_usage)[1]);
 
-                spin_lock_irqsave(&ohci->IR_channel_lock, flags);
+                while(channelbit--) clearMask= clearMask << 1;
 
-                if (test_and_clear_bit(arg, &ohci->IR_channel_usage)) {
-                        DBGMSG(ohci->id,
-			       "listening disabled on iso channel %d", arg);
-
-                        if (arg > 31) {
-                                u32 clearMask= 0x00000001;
-                                arg-= 32;
-                                while(arg--) clearMask= clearMask << 1;
-                                reg_write(ohci,
-                                          OHCI1394_IRMultiChanMaskHiClear,
-                                          clearMask);
-                        } else {
-                                u32 clearMask= 0x00000001;
-                                while(arg--) clearMask= clearMask << 1;
-                                reg_write(ohci,
-                                          OHCI1394_IRMultiChanMaskLoClear,
-                                          clearMask);
-                        }
+                spin_lock_irqsave(&ohci->IR_channel_lock, flags);
 
-                }
+                if (!test_and_clear_bit(channelbit, isochannels))
+                        reg_write(ohci, offset, clearMask);
 
                 spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
+                DBGMSG(ohci->id, "listening disabled on channel %u", channel);
                 break;
-
+        }
 	default:
-		PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet\n",
+		PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet",
 			cmd);
 		break;
 	}
@@ -904,6 +921,7 @@
 {
 	struct ti_ohci *ohci;
 	unsigned long flags;
+        struct hpsb_packet *nextpacket;
 
 	if (d==NULL) {
 		PRINT_G(KERN_ERR, "dma_trm_reset called with NULL arg");
@@ -919,8 +937,9 @@
 		PRINT(KERN_INFO, ohci->id, 
 		      "AT dma reset ctx=%d, aborting transmission", 
 		      d->ctx);
+                nextpacket = d->fifo_first->xnext;
 		hpsb_packet_sent(ohci->host, d->fifo_first, ACKX_ABORTED);
-		d->fifo_first = d->fifo_first->xnext;
+		d->fifo_first = nextpacket;
 	}
 	d->fifo_first = d->fifo_last = NULL;
 
@@ -929,9 +948,10 @@
 		PRINT(KERN_INFO, ohci->id, 
 		      "AT dma reset ctx=%d, aborting transmission", 
 		      d->ctx);
+                nextpacket = d->pending_first->xnext;
 		hpsb_packet_sent(ohci->host, d->pending_first, 
 				 ACKX_ABORTED);
-		d->pending_first = d->pending_first->xnext;
+		d->pending_first = nextpacket;
 	}
 	d->pending_first = d->pending_last = NULL;
 	
@@ -1072,6 +1092,20 @@
 		}
 		if (event & OHCI1394_selfIDComplete) {
 			if (host->in_bus_reset) {
+				/* 
+				 * Begin Fix (JSG): Check to make sure our 
+				 * node id is valid 
+				 */
+				node_id = reg_read(ohci, OHCI1394_NodeID); 
+				if (!(node_id & 0x80000000)) {
+					mdelay(1); /* phy is upset - 
+						    * this happens once in 
+						    * a while on hot-plugs...
+						    * give it a ms to recover 
+						    */
+				}
+				/* End Fix (JSG) */
+
 				node_id = reg_read(ohci, OHCI1394_NodeID);
 				if (node_id & 0x80000000) { /* NodeID valid */
 					phyid =  node_id & 0x0000003f;
@@ -1346,9 +1380,10 @@
 {
 	struct dma_trm_ctx *d = (struct dma_trm_ctx*)data;
 	struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
-	struct hpsb_packet *packet;
+	struct hpsb_packet *packet, *nextpacket;
 	unsigned long flags;
 	u32 ack;
+        size_t datasize;
 
 	spin_lock_irqsave(&d->lock, flags);
 
@@ -1363,7 +1398,8 @@
 
 	while (d->fifo_first) {
 		packet = d->fifo_first;
-		if (packet->data_size)
+                datasize = d->fifo_first->data_size;
+		if (datasize)
 			ack = d->prg_cpu[d->sent_ind]->end.status>>16;
 		else 
 			ack = d->prg_cpu[d->sent_ind]->begin.status>>16;
@@ -1372,20 +1408,40 @@
 			/* this packet hasn't been sent yet*/
 			break;
 
-		DBGMSG(ohci->id, 
-		       "Packet sent to node %d ack=0x%X spd=%d ctx=%d",
-		       (packet->header[0]>>16)&0x3f, ack&0x1f, (ack>>5)&0x3, 
-		       d->ctx);
+#ifdef OHCI1394_DEBUG
+		if (datasize)
+			DBGMSG(ohci->id,
+			       "Packet sent to node %d tcode=0x%X tLabel="
+			       "0x%02X ack=0x%X spd=%d dataLength=%d ctx=%d", 
+			       (d->prg_cpu[d->sent_ind]->data[1]>>16)&0x3f,
+			       (d->prg_cpu[d->sent_ind]->data[0]>>4)&0xf,
+			       (d->prg_cpu[d->sent_ind]->data[0]>>10)&0x3f,
+			       ack&0x1f, (ack>>5)&0x3, 
+			       d->prg_cpu[d->sent_ind]->data[3]>>16,
+			       d->ctx);
+		else 
+			DBGMSG(ohci->id,
+			       "Packet sent to node %d tcode=0x%X tLabel="
+			       "0x%02X ack=0x%X spd=%d data=0x%08X ctx=%d", 
+			       (d->prg_cpu[d->sent_ind]->data[1]>>16)&0x3f,
+			       (d->prg_cpu[d->sent_ind]->data[0]>>4)&0xf,
+			       (d->prg_cpu[d->sent_ind]->data[0]>>10)&0x3f,
+			       ack&0x1f, (ack>>5)&0x3, 
+			       d->prg_cpu[d->sent_ind]->data[3],
+			       d->ctx);
+#endif		
+
+                nextpacket = packet->xnext;
 		hpsb_packet_sent(ohci->host, packet, ack&0xf);
 
-		if (packet->data_size)
+		if (datasize)
 			pci_unmap_single(ohci->dev, 
 					 d->prg_cpu[d->sent_ind]->end.address,
-					 packet->data_size, PCI_DMA_TODEVICE);
+					 datasize, PCI_DMA_TODEVICE);
 
 		d->sent_ind = (d->sent_ind+1)%d->num_desc;
 		d->free_prgs++;
-		d->fifo_first = d->fifo_first->xnext;
+		d->fifo_first = nextpacket;
 	}
 	if (d->fifo_first==NULL) d->fifo_last=NULL;
 
@@ -1687,22 +1743,36 @@
 		FAIL("failed to allocate buffer config rom");
 	}
 
-	DBGMSG(ohci->id, "The 1st byte at offset 0x404 is: 0x%02x",
-	       *((char *)ohci->csr_config_rom_cpu+4));
-
 	/* 
 	 * self-id dma buffer allocation
 	 * FIXME: some early chips may need 8KB alignment for the 
-	 * selfid buffer
+	 * selfid buffer... if you have problems a temporary fic
+	 * is to allocate 8192 bytes instead of 2048
 	 */
 	ohci->selfid_buf_cpu = 
 		pci_alloc_consistent(ohci->dev, 2048, &ohci->selfid_buf_bus);
 	if (ohci->selfid_buf_cpu == NULL) {
 		FAIL("failed to allocate DMA buffer for self-id packets");
 	}
-	if ((unsigned long)ohci->selfid_buf_cpu & 0xfff)
+	if ((unsigned long)ohci->selfid_buf_cpu & 0x1fff)
 		PRINT(KERN_INFO, ohci->id, "Selfid buffer %p not aligned on "
-		      "8Kb boundary", ohci->selfid_buf_cpu);  
+		      "8Kb boundary... may cause pb on some CXD3222 chip", 
+		      ohci->selfid_buf_cpu);  
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
+	ohci->registers = ioremap_nocache(dev->base_address[0],
+					  OHCI1394_REGISTER_SIZE);
+#else
+	ohci->registers = ioremap_nocache(dev->resource[0].start,
+					  OHCI1394_REGISTER_SIZE);
+#endif
+
+	if (ohci->registers == NULL) {
+		FAIL("failed to remap registers - card not accessible");
+	}
+
+	PRINT(KERN_INFO, ohci->id, "remapped memory spaces reg 0x%p",
+	      ohci->registers);
 
 	ohci->ar_req_context = 
 		alloc_dma_rcv_ctx(ohci, 0, AR_REQ_NUM_DESC,
@@ -1711,7 +1781,9 @@
 				  OHCI1394_AsReqRcvContextControlClear,
 				  OHCI1394_AsReqRcvCommandPtr);
 
-	if (ohci->ar_req_context == NULL) return 1;
+	if (ohci->ar_req_context == NULL) {
+		FAIL("failed to allocate AR Req context");
+	}
 
 	ohci->ar_resp_context = 
 		alloc_dma_rcv_ctx(ohci, 1, AR_RESP_NUM_DESC,
@@ -1758,21 +1830,6 @@
         ohci->IR_channel_usage= 0x0000000000000000;
         spin_lock_init(&ohci->IR_channel_lock);
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
-	ohci->registers = ioremap_nocache(dev->base_address[0],
-					  OHCI1394_REGISTER_SIZE);
-#else
-	ohci->registers = ioremap_nocache(dev->resource[0].start,
-					  OHCI1394_REGISTER_SIZE);
-#endif
-
-	if (ohci->registers == NULL) {
-		FAIL("failed to remap registers - card not accessible");
-	}
-
-	PRINT(KERN_INFO, ohci->id, "remapped memory spaces reg 0x%p",
-	      ohci->registers);
-
 	if (!request_irq(dev->irq, ohci_irq_handler, SA_SHIRQ,
 			 OHCI1394_DRIVER_NAME, ohci)) {
 		PRINT(KERN_INFO, ohci->id, "allocated interrupt %d", dev->irq);
@@ -1782,6 +1839,9 @@
 
 	ohci_init_config_rom(ohci);
 
+	DBGMSG(ohci->id, "The 1st byte at offset 0x404 is: 0x%02x",
+	       *((char *)ohci->csr_config_rom_cpu+4));
+
 	return 0;
 #undef FAIL
 }
@@ -2116,7 +2176,7 @@
 	create_proc_read_entry ("ohci1394", 0, NULL, ohci1394_read_proc, NULL);
 #else
 	if (proc_register(&proc_root, &ohci_proc_entry)) {
-		PRINT_G(KERN_ERR, "unable to register proc file\n");
+		PRINT_G(KERN_ERR, "unable to register proc file");
 		return -EIO;
 	}
 #endif
@@ -2290,7 +2350,7 @@
 #endif
 #endif
 
-	PRINT_G(KERN_INFO, "removed " OHCI1394_DRIVER_NAME " module\n");
+	PRINT_G(KERN_INFO, "removed " OHCI1394_DRIVER_NAME " module");
 }
 
 int init_module(void)
@@ -2298,7 +2358,7 @@
 	memset(cards, 0, MAX_OHCI1394_CARDS * sizeof (struct ti_ohci));
 	
 	if (hpsb_register_lowlevel(get_ohci_template())) {
-		PRINT_G(KERN_ERR, "registering failed\n");
+		PRINT_G(KERN_ERR, "registering failed");
 		return -ENXIO;
 	} 
 	return 0;

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