patch-2.3.30 linux/drivers/usb/ohci-hcd.c

Next file: linux/drivers/usb/ohci-root-hub.c
Previous file: linux/drivers/usb/mouse.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.29/linux/drivers/usb/ohci-hcd.c linux/drivers/usb/ohci-hcd.c
@@ -90,7 +90,7 @@
 {  
 	struct usb_ohci_ed *ed = td->ed;
 	if(lw0 != NULL) {
-		if(0 < 0 && (status == USB_ST_DATAUNDERRUN || status == USB_ST_NOERROR)) 
+		if((status == USB_ST_DATAUNDERRUN || status == USB_ST_NOERROR)) 
 			((struct ohci_state * )lw0)->status = data_len;
 		else
 			((struct ohci_state * )lw0)->status = status;
@@ -123,7 +123,7 @@
  
 	ret = handler(status, data, data_len, dev_id);
 	if(ret == 0) return 0; /* 0 .. do not requeue  */
-	if(status > 0) return -1; /* error occured do not requeue ? */
+	if(status < 0) return -1; /* error occured do not requeue ? */
 	ohci_trans_req(ohci, ed, 0, NULL, data, (ed->hwINFO >> 16) & 0x3f, (__OHCI_BAG) handler, (__OHCI_BAG) dev_id, INT_IN, sohci_int_handler); /* requeue int request */
  
 	return 0;
@@ -342,15 +342,13 @@
  
 static int sohci_terminate_bulk(struct usb_device *usb_dev, void * ed) 
 {
-	DECLARE_WAITQUEUE(wait, current);
 	
 	OHCI_DEBUG( printk("USB HC TERM_BULK>>>:%4x\n", (unsigned int) ed);)
  	
-	current->state = TASK_UNINTERRUPTIBLE;
-    usb_ohci_rm_ep(usb_dev, (struct usb_ohci_ed *) ed, sohci_blocking_handler, NULL, &wait, SEND);
-    schedule();
-    remove_wait_queue(&op_wakeup, &wait); 
-	return 1;
+	ED_setSTATE((struct usb_ohci_ed *)ed, ED_STOP);
+	 
+    usb_ohci_rm_ep(usb_dev, (struct usb_ohci_ed *) ed, NULL, NULL, NULL, 0);
+	return 0;
 }
 
 static int sohci_alloc_dev(struct usb_device *usb_dev)
@@ -382,7 +380,7 @@
 	struct ohci_device *dev = usb_to_ohci(usb_dev);
 
 	OHCI_DEBUG(printk("USB HC ***** free %x\n", usb_dev->devnum);)
-
+	wait_ms(10);
 	if(usb_dev->devnum >= 0) {
 		current->state = TASK_UNINTERRUPTIBLE;
     	cnt = usb_ohci_rm_function(usb_dev, sohci_blocking_handler, NULL, &wait);
@@ -409,7 +407,7 @@
 
 	struct ohci * ohci = usb_dev->bus->hcpriv;
 	
-	return readl(&ohci->regs->fmnumber) & 0xffff;
+	return ohci->hc_area->hcca.frame_no & 0xffff;
 }
 
 
@@ -509,7 +507,9 @@
 	for (i = 0; i < id->frame_count; i++) {
 		if(td[i]) {
 			td[i]->type |= DEL;
-			ed = td[i]->ed; printk(" %d", i);	
+			ed = td[i]->ed; 
+			OHCI_DEBUG(printk(" %d", i);)	
+			td[i] = NULL;
 		}
 	} 
 	if(ed) usb_ohci_rm_ep(id->usb_dev, ed, NULL, NULL, NULL, TD_RM);
@@ -1100,7 +1100,7 @@
 	__u32 * td_hw; 
 	
 	for(ed = ohci->ed_rm_list; ed != NULL; ed = ed->ed_prev) {
-		 OHCI_DEBUG(printk("USB HC ed_rm_list: %4x :\n", ed->hwINFO);)
+		 OHCI_DEBUG(printk("USB HC ed_rm_list: %4x :next : %p\n", ed->hwINFO, ed->ed_prev);)
 		  
   			
 		for( td_hw = &(ed->hwHeadP); (*td_hw & 0xfffffff0) != ed->hwTailP; td_hw = &(td->hwNextTD)) {
@@ -1483,6 +1483,8 @@
 static int handle_apm_event(apm_event_t event)
 {
 	static int down = 0;
+	struct ohci * ohci;
+	struct list_head *ohci_l;
 
 	switch (event) {
 	case APM_SYS_SUSPEND:
@@ -1491,6 +1493,12 @@
 			printk(KERN_DEBUG "ohci: received extra suspend event\n");
 			break;
 		}
+		for(ohci_l = ohci_hcd_list.next; ohci_l != &ohci_hcd_list; ohci_l = ohci_l->next) {
+			ohci = list_entry(ohci_l, struct ohci, ohci_hcd_list);
+			OHCI_DEBUG(printk("USB OHCI suspend: %p\n", ohci);)
+			writel(0xff, &ohci->regs->control); /* Suspend */
+		}
+		wait_ms(10);
 		down = 1;
 		break;
 	case APM_NORMAL_RESUME:
@@ -1499,8 +1507,14 @@
 			printk(KERN_DEBUG "ohci: received bogus resume event\n");
 			break;
 		}
+		for(ohci_l = ohci_hcd_list.next; ohci_l != &ohci_hcd_list; ohci_l = ohci_l->next) {
+			ohci = list_entry(ohci_l, struct ohci, ohci_hcd_list);
+			OHCI_DEBUG(printk("USB OHCI resume: %p\n", ohci);)
+			writel(0x7f, &ohci->regs->control); /* Resume */
+			wait_ms(20);
+			writel(0xBF, &ohci->regs->control); /* Operational */
+		}
 		down = 0;
-//		start_hc(ohci);
 		break;
 	}
 	return 0;

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