patch-2.4.0-test6 linux/drivers/usb/usb-ohci.c

Next file: linux/drivers/usb/usb-uhci.c
Previous file: linux/drivers/usb/uhci.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c
@@ -65,6 +65,9 @@
  */
 #include <linux/adb.h>
 #include <linux/pmu.h>
+#ifndef CONFIG_PM
+#define CONFIG_PM
+#endif
 #endif
 
 
@@ -415,9 +418,11 @@
 	int i, size = 0;
 	unsigned long flags;
 	
-	if (!urb->dev || !urb->dev->bus) return -EINVAL;
+	if (!urb->dev || !urb->dev->bus)
+		return -EINVAL;
 	
-	if (urb->hcpriv) return -EINVAL; /* urb already in use */
+	if (urb->hcpriv)			/* urb already in use */
+		return -EINVAL;
 
 //	if(usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) 
 //		return -EPIPE;
@@ -435,8 +440,10 @@
 	
 	/* when controller's hung, permit only roothub cleanup attempts
 	 * such as powering down ports */
-	if (ohci->disabled)
+	if (ohci->disabled) {
+		usb_dec_dev_use (urb->dev);	
 		return -ESHUTDOWN;
+	}
 
 	/* every endpoint has a ed, locate and fill it */
 	if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1))) {
@@ -953,13 +960,20 @@
 	ed = ed_ret = &(usb_to_ohci (usb_dev)->ed[(usb_pipeendpoint (pipe) << 1) | 
 			(usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]);
 
-	if((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) 
-		return NULL; /* pending delete request */
+	if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) {
+		/* pending delete request */
+		spin_unlock (&usb_ed_lock);
+		return NULL;
+	}
 	
 	if (ed->state == ED_NEW) {
 		ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */
   		OHCI_ALLOC (td, sizeof (*td)); /* dummy td; end of td list for ed */
-  		if(!td) return NULL; /* out of memory */
+  		if (!td) {
+			/* out of memory */
+			spin_unlock (&usb_ed_lock);
+			return NULL;
+		}
 		ed->hwTailP = cpu_to_le32 (virt_to_bus (td));
 		ed->hwHeadP = ed->hwTailP;	
 		ed->state = ED_UNLINK;
@@ -1730,7 +1744,9 @@
 	urb_print (urb, "RET(rh)", usb_pipeout (urb->pipe));
 #endif
 
-	if (urb->complete) urb->complete (urb);
+	if (urb->complete)
+	    	urb->complete (urb);
+	usb_dec_dev_use (urb->dev);
 	return 0;
 }
 
@@ -1880,7 +1896,9 @@
 			ohci->ohci_dev->slot_name);
 		// e.g. due to PCI Master/Target Abort
 
-#ifndef	DEBUG
+#ifdef	DEBUG
+		ohci_dump (ohci, 1);
+#else
 		// FIXME: be optimistic, hope that bug won't repeat often.
 		// Make some non-interrupt context restart the controller.
 		// Count and limit the retries though; either hardware or
@@ -1910,6 +1928,8 @@
 	}
 	writel (ints, &regs->intrstatus);
 	writel (OHCI_INTR_MIE, &regs->intrenable);	
+
+	/* FIXME:  check URB timeouts */
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1921,7 +1941,7 @@
 	ohci_t * ohci;
 	struct usb_bus * bus;
 
-	ohci = (ohci_t *) __get_free_pages (GFP_KERNEL, 1);
+	ohci = (ohci_t *) kmalloc (sizeof *ohci, GFP_KERNEL);
 	if (!ohci)
 		return NULL;
 		
@@ -1932,7 +1952,7 @@
 
 	bus = usb_alloc_bus (&sohci_device_operations);
 	if (!bus) {
-		free_pages ((unsigned long) ohci, 1);
+		kfree (ohci);
 		return NULL;
 	}
 
@@ -1974,7 +1994,7 @@
 	/* unmap the IO address space */
 	iounmap (ohci->regs);
        
-	free_pages ((unsigned long) ohci, 1);	
+	kfree (ohci);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -2085,13 +2105,27 @@
 static int __devinit
 ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
 {
-	unsigned long mem_resource;
+	unsigned long mem_resource, mem_len;
 	u8 latency, limit;
 	void *mem_base;
 
 	if (pci_enable_device(dev) < 0)
 		return -ENODEV;
 	
+	/* we read its hardware registers as memory */
+	mem_resource = pci_resource_start(dev, 0);
+	mem_len = pci_resource_len(dev, 0);
+	if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) {
+		dbg ("controller already in use");
+		return -EBUSY;
+	}
+
+	mem_base = ioremap_nocache (mem_resource, mem_len);
+	if (!mem_base) {
+		err("Error mapping OHCI memory");
+		return -EFAULT;
+	}
+
 	/* controller writes into our memory */
 	pci_set_master (dev);
 	pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
@@ -2103,15 +2137,6 @@
 		}
 	}
 
-	/* we read its hardware registers as memory */
-	mem_resource = pci_resource_start(dev, 0);
-	/* request_mem_region ... */
-	mem_base = ioremap_nocache (mem_resource, 4096);
-	if (!mem_base) {
-		err("Error mapping OHCI memory");
-		return -EFAULT;
-	}
-
 	return hc_found_ohci (dev, dev->irq, mem_base);
 } 
 
@@ -2145,6 +2170,8 @@
 			&ohci->regs->control);
 
 	hc_release_ohci (ohci);
+
+	release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0));
 }
 
 
@@ -2233,7 +2260,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static const struct __devinitdata pci_device_id	ohci_pci_ids [] = { {
+static const struct pci_device_id __devinitdata ohci_pci_ids [] = { {
 
 	/* handle any USB OHCI controller */
 	class: 		((PCI_CLASS_SERIAL_USB << 8) | 0x10),
@@ -2328,4 +2355,5 @@
 #endif /* MODULE */
 
 
+MODULE_AUTHOR ("Roman Weissgaerber <weissg@vienna.at>");
 MODULE_DESCRIPTION ("USB OHCI Host Controller Driver");

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