--- linux/drivers/usb-2.4.4/usb-ohci.c	Wed Apr 25 14:10:49 2001
+++ linux/drivers/usb/usb-ohci.c	Tue May  8 12:01:53 2001
@@ -597,16 +597,19 @@
 	urb_priv->length = size;
 	urb_priv->ed = ed;	
 
-	/* allocate the TDs */
+	/* allocate the TDs (updating hash chains) */
+	spin_lock_irqsave (&usb_ed_lock, flags);
 	for (i = 0; i < size; i++) { 
-		urb_priv->td[i] = td_alloc (ohci, mem_flags);
+		urb_priv->td[i] = td_alloc (ohci, SLAB_ATOMIC);
 		if (!urb_priv->td[i]) {
 			urb_priv->length = i;
 			urb_free_priv (ohci, urb_priv);
+			spin_unlock_irqrestore (&usb_ed_lock, flags);
 			usb_dec_dev_use (urb->dev);	
 			return -ENOMEM;
 		}
 	}	
+	spin_unlock_irqrestore (&usb_ed_lock, flags);
 
 	if (ed->state == ED_NEW || (ed->state & ED_DEL)) {
 		urb_free_priv (ohci, urb_priv);
@@ -965,6 +968,8 @@
 		ed->hwNextED = 0;
 		if (ohci->ed_controltail == NULL) {
 			writel (ed->dma, &ohci->regs->ed_controlhead);
+			/* force that write to complete */
+			readl (&ohci->regs->ed_controlhead);
 		} else {
 			ohci->ed_controltail->hwNextED = cpu_to_le32 (ed->dma);
 		}
@@ -973,6 +978,8 @@
 			!ohci->ed_rm_list[1]) {
 			ohci->hc_control |= OHCI_CTRL_CLE;
 			writel (ohci->hc_control, &ohci->regs->control);
+			/* force that write to complete */
+			readl (&ohci->regs->control);
 		}
 		ohci->ed_controltail = edi;	  
 		break;
@@ -981,6 +988,8 @@
 		ed->hwNextED = 0;
 		if (ohci->ed_bulktail == NULL) {
 			writel (ed->dma, &ohci->regs->ed_bulkhead);
+			/* force that write to complete */
+			readl (&ohci->regs->ed_bulkhead);
 		} else {
 			ohci->ed_bulktail->hwNextED = cpu_to_le32 (ed->dma);
 		}
@@ -989,6 +998,8 @@
 			!ohci->ed_rm_list[1]) {
 			ohci->hc_control |= OHCI_CTRL_BLE;
 			writel (ohci->hc_control, &ohci->regs->control);
+			/* force that write to complete */
+			readl (&ohci->regs->control);
 		}
 		ohci->ed_bulktail = edi;	  
 		break;
@@ -1065,6 +1076,8 @@
 				writel (ohci->hc_control, &ohci->regs->control);
 			}
 			writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_controlhead);
+			/* force writes to complete */
+			readl (&ohci->regs->ed_controlhead);
 		} else {
 			ed->ed_prev->hwNextED = ed->hwNextED;
 		}
@@ -1082,6 +1095,8 @@
 				writel (ohci->hc_control, &ohci->regs->control);
 			}
 			writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_bulkhead);
+			/* force writes to complete */
+			readl (&ohci->regs->ed_bulkhead);
 		} else {
 			ed->ed_prev->hwNextED = ed->hwNextED;
 		}
@@ -1182,7 +1197,7 @@
 	if (ed->state == ED_NEW) {
 		ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */
   		/* dummy td; end of td list for ed */
-		td = td_alloc (ohci, mem_flags);
+		td = td_alloc (ohci, SLAB_ATOMIC);
 		/* hash the ed for later reverse mapping */
  		if (!td || !hash_add_ed (ohci, (ed_t *)ed)) {
 			/* out of memory */
@@ -1236,13 +1251,15 @@
 		switch (ed->type) {
 			case PIPE_CONTROL: /* stop control list */
 				ohci->hc_control &= ~OHCI_CTRL_CLE;
-				writel (ohci->hc_control, &ohci->regs->control); 
+				writel (ohci->hc_control, &ohci->regs->control);
   				break;
 			case PIPE_BULK: /* stop bulk list */
 				ohci->hc_control &= ~OHCI_CTRL_BLE;
-				writel (ohci->hc_control, &ohci->regs->control); 
+				writel (ohci->hc_control, &ohci->regs->control);
 				break;
 		}
+		/* force that write to complete */
+		readl (&ohci->regs->control);
 	}
 
 	frame = le16_to_cpu (ohci->hcca->frame_no) & 0x1;
@@ -1253,6 +1270,8 @@
 		/* enable SOF interrupt */
 		writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
 		writel (OHCI_INTR_SF, &ohci->regs->intrenable);
+		/* force writes to complete */
+		readl (&ohci->regs->intrenable);
 	}
 }
 
@@ -1356,6 +1375,8 @@
 			td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, urb, cnt);
 			cnt++;
 			writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
+			/* force that write to complete */
+			readl (&ohci->regs->control);
 			break;
 
 		case PIPE_INTERRUPT:
@@ -1381,6 +1402,8 @@
  				TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1;
 			td_fill (ohci, info, data, 0, urb, cnt++);
 			writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
+			/* force that write to complete */
+			readl (&ohci->regs->control);
 			break;
 
 		case PIPE_ISOCHRONOUS:
@@ -1607,6 +1630,8 @@
 				ohci->hc_control |= OHCI_CTRL_BLE;
 			writel (ohci->hc_control, &ohci->regs->control);   
 		}
+		/* force any pci writes to complete */
+		readl (&ohci->regs->control);
 	}
 
    	ohci->ed_rm_list[frame] = NULL;
@@ -2024,6 +2049,9 @@
 			dbg ("unsupported root hub command");
 			status = TD_CC_STALL;
 	}
+
+	/* force writes to complete */
+	readl (&ohci->regs->control);
 	
 #ifdef	DEBUG
 	// ohci_dump_roothub (ohci, 0);
@@ -2103,6 +2131,9 @@
 
   	/* Reset USB (needed by some controllers) */
 	writel (0, &ohci->regs->control);
+
+	/* force writes to complete */
+	readl (&ohci->regs->control);
       	
 	/* HC Reset requires max 10 ms delay */
 	writel (OHCI_HCR,  &ohci->regs->cmdstatus);
@@ -2149,6 +2180,9 @@
  	ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
 	ohci->disabled = 0;
  	writel (ohci->hc_control, &ohci->regs->control);
+
+	/* force writes to complete */
+	readl (&ohci->regs->control);
  
 	/* Choose the interrupts we care about now, others later on demand */
 	mask = OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO;
@@ -2248,6 +2282,7 @@
 		// Count and limit the retries though; either hardware or
 		// software errors can go forever...
 #endif
+		hc_reset (ohci);
 	}
   
 	if (ints & OHCI_INTR_WDH) {
@@ -2261,6 +2296,7 @@
 		writel (OHCI_INTR_SO, &regs->intrenable); 	 
 	}
 
+	// FIXME:  this assumes SOF (1/ms) interrupts don't get lost...
 	if (ints & OHCI_INTR_SF) { 
 		unsigned int frame = le16_to_cpu (ohci->hcca->frame_no) & 1;
 		writel (OHCI_INTR_SF, &regs->intrdisable);	
@@ -2282,6 +2318,9 @@
 
 	writel (ints, &regs->intrstatus);
 	writel (OHCI_INTR_MIE, &regs->intrenable);	
+
+	/* force any pci writes to complete */
+	readl (&ohci->regs->control);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -2340,6 +2379,9 @@
 {	
 	dbg ("USB HC release ohci usb-%s", ohci->ohci_dev->slot_name);
 
+	/* force any pci writes to complete */
+	readl (&ohci->regs->control);
+
 	/* disconnect all devices */    
 	if (ohci->bus->root_hub)
 		usb_disconnect (&ohci->bus->root_hub);
@@ -2427,6 +2469,7 @@
 
 	/* FIXME this is a second HC reset; why?? */
 	writel (ohci->hc_control = OHCI_USB_RESET, &ohci->regs->control);
+	readl (&ohci->regs->control);
 	wait_ms (10);
 
 	usb_register_bus (ohci->bus);
@@ -2504,6 +2547,11 @@
 
 	if (pci_enable_device(dev) < 0)
 		return -ENODEV;
+
+        if (!dev->irq) {
+        	err("found OHCI device with no IRQ assigned. check BIOS settings!");
+   	        return -ENODEV;
+        }
 	
 	/* we read its hardware registers as memory */
 	mem_resource = pci_resource_start(dev, 0);
@@ -2586,6 +2634,7 @@
 #endif
 	ohci->hc_control = OHCI_USB_SUSPEND;
 	writel (ohci->hc_control, &ohci->regs->control);
+	readl (&ohci->regs->control);
 	wait_ms (10);
 }
 
@@ -2628,6 +2677,7 @@
 				? "host" : "remote");
 		ohci->hc_control = OHCI_USB_RESUME;
 		writel (ohci->hc_control, &ohci->regs->control);
+		readl (&ohci->regs->control);
 		wait_ms (20);
 
 		temp = readl (&ohci->regs->control);
@@ -2650,6 +2700,7 @@
 #ifdef CONFIG_PMAC_PBOOK
 		enable_irq (ohci->irq);
 #endif
+		readl (&ohci->regs->control);
 		break;
 
 	default:
