patch-2.4.3 linux/drivers/usb/usb-ohci.c

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

diff -u --recursive --new-file v2.4.2/linux/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c
@@ -12,6 +12,7 @@
  * 
  * History:
  * 
+ * 2001/03/07 hcca allocation uses pci_alloc_consistent (Steve Longerbeam)
  * 2000/09/26 fixed races in removing the private portion of the urb
  * 2000/09/07 disable bulk and control lists when unlinking the last
  *	endpoint descriptor in order to avoid unrecoverable errors on
@@ -208,7 +209,7 @@
 	 __u32 * ed_p;
 	for (i= 0; i < 32; i++) {
 		j = 5;
-		ed_p = &(ohci->hcca.int_table [i]);
+		ed_p = &(ohci->hcca->int_table [i]);
 		if (*ed_p == 0)
 		    continue;
 		printk (KERN_DEBUG __FILE__ ": %s branch int %2d(%2x):", str, i, i);
@@ -371,7 +372,7 @@
 	ohci_dump_status (controller);
 	if (verbose)
 		ep_print_int_eds (controller, "hcca");
-	dbg ("hcca frame #%04x", controller->hcca.frame_no);
+	dbg ("hcca frame #%04x", controller->hcca->frame_no);
 	ohci_dump_roothub (controller, 1);
 }
 
@@ -555,7 +556,7 @@
 			if (urb->transfer_flags & USB_ISO_ASAP) { 
 				urb->start_frame = ((ed->state == ED_OPER)
 					? (ed->last_iso + 1)
-					: (le16_to_cpu (ohci->hcca.frame_no) + 10)) & 0xffff;
+					: (le16_to_cpu (ohci->hcca->frame_no) + 10)) & 0xffff;
 			}	
 			/* FALLTHROUGH */
 		case PIPE_INTERRUPT:
@@ -751,7 +752,7 @@
 				 * the controller won't ever be touching
 				 * these lists again!!
 				dl_del_list (ohci,
-					le16_to_cpu (ohci->hcca.frame_no) & 1);
+					le16_to_cpu (ohci->hcca->frame_no) & 1);
 				 */
 				warn ("TD leak, %d", cnt);
 
@@ -795,7 +796,7 @@
 {
 	ohci_t * ohci = usb_dev->bus->hcpriv;
 	
-	return le16_to_cpu (ohci->hcca.frame_no);
+	return le16_to_cpu (ohci->hcca->frame_no);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -914,7 +915,7 @@
 		
 		for (i = 0; i < ep_rev (6, interval); i += inter) {
 			inter = 1;
-			for (ed_p = &(ohci->hcca.int_table[ep_rev (5, i) + int_branch]); 
+			for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i) + int_branch]); 
 				(*ed_p != 0) && (((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->int_interval >= interval); 
 				ed_p = &(((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->hwNextED)) 
 					inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->int_interval);
@@ -935,7 +936,7 @@
 		} else {
 			for ( i = 0; i < 32; i += inter) {
 				inter = 1;
-				for (ed_p = &(ohci->hcca.int_table[ep_rev (5, i)]); 
+				for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i)]); 
 					*ed_p != 0; 
 					ed_p = &(((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->hwNextED)) 
 						inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->int_interval);
@@ -1009,7 +1010,7 @@
 		interval = ed->int_interval;
 
 		for (i = 0; i < ep_rev (6, interval); i += inter) {
-			for (ed_p = &(ohci->hcca.int_table[ep_rev (5, i) + int_branch]), inter = 1; 
+			for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i) + int_branch]), inter = 1; 
 				(*ed_p != 0) && (*ed_p != ed->hwNextED); 
 				ed_p = &(((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->hwNextED), 
 				inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->int_interval)) {				
@@ -1036,7 +1037,7 @@
 			ed->ed_prev->hwNextED = ed->hwNextED;
 		} else {
 			for (i = 0; i < 32; i++) {
-				for (ed_p = &(ohci->hcca.int_table[ep_rev (5, i)]); 
+				for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i)]); 
 						*ed_p != 0; 
 						ed_p = &(((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->hwNextED)) {
 					// inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->int_interval);
@@ -1148,7 +1149,7 @@
 		}
 	}
 
-	frame = le16_to_cpu (ohci->hcca.frame_no) & 0x1;
+	frame = le16_to_cpu (ohci->hcca->frame_no) & 0x1;
 	ed->ed_rm_list = ohci->ed_rm_list[frame];
 	ohci->ed_rm_list[frame] = ed;
 
@@ -1361,8 +1362,8 @@
   	
   	spin_lock_irqsave (&usb_ed_lock, flags);
   	
-	td_list_hc = le32_to_cpup (&ohci->hcca.done_head) & 0xfffffff0;
-	ohci->hcca.done_head = 0;
+	td_list_hc = le32_to_cpup (&ohci->hcca->done_head) & 0xfffffff0;
+	ohci->hcca->done_head = 0;
 	
 	while (td_list_hc) {		
 		td_list = (td_t *) bus_to_virt (td_list_hc);
@@ -2018,7 +2019,7 @@
 	writel (0, &ohci->regs->ed_controlhead);
 	writel (0, &ohci->regs->ed_bulkhead);
 	
-	writel (virt_to_bus (&ohci->hcca), &ohci->regs->hcca); /* a reset clears this */
+	writel (ohci->hcca_dma, &ohci->regs->hcca); /* a reset clears this */
    
   	fminterval = 0x2edf;
 	writel ((fminterval * 9) / 10, &ohci->regs->periodicstart);
@@ -2075,13 +2076,13 @@
 	struct ohci_regs * regs = ohci->regs;
  	int ints; 
 
-	if ((ohci->hcca.done_head != 0) && !(le32_to_cpup (&ohci->hcca.done_head) & 0x01)) {
+	if ((ohci->hcca->done_head != 0) && !(le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {
 		ints =  OHCI_INTR_WDH;
 	} else if ((ints = (readl (&regs->intrstatus) & readl (&regs->intrenable))) == 0) {
 		return;
 	} 
 
-	// dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca.frame_no));
+	// dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no));
 
 	if (ints & OHCI_INTR_UE) {
 		ohci->disabled++;
@@ -2111,7 +2112,7 @@
 	}
 
 	if (ints & OHCI_INTR_SF) { 
-		unsigned int frame = le16_to_cpu (ohci->hcca.frame_no) & 1;
+		unsigned int frame = le16_to_cpu (ohci->hcca->frame_no) & 1;
 		writel (OHCI_INTR_SF, &regs->intrdisable);	
 		if (ohci->ed_rm_list[!frame] != NULL) {
 			dl_del_list (ohci, !frame);
@@ -2139,7 +2140,15 @@
 		return NULL;
 		
 	memset (ohci, 0, sizeof (ohci_t));
-	
+
+	ohci->hcca = pci_alloc_consistent (dev, sizeof *ohci->hcca,
+			&ohci->hcca_dma);
+        if (!ohci->hcca) {
+                kfree (ohci);
+                return NULL;
+        }
+        memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
+
 	ohci->disabled = 1;
 	ohci->irq = -1;
 	ohci->regs = mem_base;   
@@ -2192,7 +2201,9 @@
     
 	/* unmap the IO address space */
 	iounmap (ohci->regs);
-       
+
+	pci_free_consistent (ohci->ohci_dev, sizeof *ohci->hcca,
+		ohci->hcca, ohci->hcca_dma);
 	kfree (ohci);
 }
 
@@ -2290,7 +2301,7 @@
 	
 	/* empty the interrupt branches */
 	for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0;
-	for (i = 0; i < NUM_INTS; i++) ohci->hcca.int_table[i] = 0;
+	for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table[i] = 0;
 	
 	/* no EDs to remove */
 	ohci->ed_rm_list [0] = NULL;
@@ -2320,6 +2331,13 @@
 	unsigned long mem_resource, mem_len;
 	void *mem_base;
 
+	/* blacklisted hardware? */
+	if (id->driver_data) {
+		info ("%s (%s): %s", dev->slot_name,
+			dev->name, (char *) id->driver_data);
+		return -ENODEV;
+	}
+
 	if (pci_enable_device(dev) < 0)
 		return -ENODEV;
 	
@@ -2484,6 +2502,20 @@
 /*-------------------------------------------------------------------------*/
 
 static const struct pci_device_id __devinitdata ohci_pci_ids [] = { {
+
+	/*
+	 * AMD-756 [Viper] USB has a serious erratum when used with
+	 * lowspeed devices like mice; oopses have been seen.  The
+	 * vendor workaround needs an NDA ... for now, blacklist it.
+	 */
+	vendor:		0x1022,
+	device:		0x740c,
+	subvendor:	PCI_ANY_ID,
+	subdevice:	PCI_ANY_ID,
+
+	driver_data:	(unsigned long) "blacklisted, erratum #4",
+
+} , {
 
 	/* handle any USB OHCI controller */
 	class: 		((PCI_CLASS_SERIAL_USB << 8) | 0x10),

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