# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.600.1.1 -> 1.600.1.2
#	drivers/usb/host/uhci-hcd.h	1.4     -> 1.5    
#	drivers/usb/host/uhci-hcd.c	1.11    -> 1.12   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/09/04	david-b@pacbell.net	1.600.1.2
# [PATCH] Re: [patch 2.5.31-bk5] uhci, misc
# 
# This patch has some small UHCI bugfixes
# 
#    - on submit error, frees memory and (!) returns error code
#    - root hub should disconnect only once
#    - pci pool code shouldn't be given GFP_DMA
#    - uses del_timer_sync(), which behaves on SMP, not del_timer()
# 
# and cleanups:
# 
#    - use container_of
#    - doesn't replicate so much hcd state
#    - no such status -ECONNABORTED
#    - uses bus_name in procfs, not "hc0", "hc1" etc
# --------------------------------------------
#
diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
--- a/drivers/usb/host/uhci-hcd.c	Thu Sep  5 08:51:45 2002
+++ b/drivers/usb/host/uhci-hcd.c	Thu Sep  5 08:51:45 2002
@@ -146,7 +146,7 @@
 	dma_addr_t dma_handle;
 	struct uhci_td *td;
 
-	td = pci_pool_alloc(uhci->td_pool, GFP_DMA | GFP_ATOMIC, &dma_handle);
+	td = pci_pool_alloc(uhci->td_pool, GFP_ATOMIC, &dma_handle);
 	if (!td)
 		return NULL;
 
@@ -325,7 +325,7 @@
 	dma_addr_t dma_handle;
 	struct uhci_qh *qh;
 
-	qh = pci_pool_alloc(uhci->qh_pool, GFP_DMA | GFP_ATOMIC, &dma_handle);
+	qh = pci_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle);
 	if (!qh)
 		return NULL;
 
@@ -1498,6 +1498,10 @@
 
 	spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
 
+	if (ret != -EINPROGRESS) {
+		uhci_destroy_urb_priv (uhci, urb);
+		return ret;
+	}
 	return 0;
 }
 
@@ -1806,8 +1810,7 @@
 
 	spin_lock_irqsave(&urb->lock, flags);
 
-	killed = (urb->status == -ENOENT || urb->status == -ECONNABORTED ||
-			urb->status == -ECONNRESET);
+ 	killed = (urb->status == -ENOENT || urb->status == -ECONNRESET);
 	resubmit_interrupt = (usb_pipetype(urb->pipe) == PIPE_INTERRUPT &&
 			urb->interval);
 
@@ -1828,9 +1831,7 @@
 	if (resubmit_interrupt)
 		/* Recheck the status. The completion handler may have */
 		/*  unlinked the resubmitting interrupt URB */
-		killed = (urb->status == -ENOENT ||
-			  urb->status == -ECONNABORTED ||
-			  urb->status == -ECONNRESET);
+		killed = (urb->status == -ENOENT || urb->status == -ECONNRESET);
 
 	if (resubmit_interrupt && !killed) {
 		urb->dev = dev;
@@ -2027,19 +2028,12 @@
         uhci->hcd.state = USB_STATE_READY;
 }
 
-#ifdef CONFIG_PROC_FS
-static int uhci_num = 0;
-#endif
-
 /*
  * De-allocate all resources..
  */
 static void release_uhci(struct uhci_hcd *uhci)
 {
 	int i;
-#ifdef CONFIG_PROC_FS
-	char buf[8];
-#endif
 
 	for (i = 0; i < UHCI_NUM_SKELQH; i++)
 		if (uhci->skelqh[i]) {
@@ -2064,15 +2058,13 @@
 	}
 
 	if (uhci->fl) {
-		pci_free_consistent(uhci->dev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle);
+		pci_free_consistent(uhci->hcd.pdev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle);
 		uhci->fl = NULL;
 	}
 
 #ifdef CONFIG_PROC_FS
 	if (uhci->proc_entry) {
-		sprintf(buf, "hc%d", uhci->num);
-
-		remove_proc_entry(buf, uhci_proc_root);
+		remove_proc_entry(uhci->hcd.self.bus_name, uhci_proc_root);
 		uhci->proc_entry = NULL;
 	}
 #endif
@@ -2097,33 +2089,20 @@
 static int __devinit uhci_start(struct usb_hcd *hcd)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-	struct pci_dev *dev = hcd->pdev;
 	int retval = -EBUSY;
 	int i, port;
+	unsigned io_size;
 	dma_addr_t dma_handle;
+	struct usb_device *udev;
 #ifdef CONFIG_PROC_FS
-	char buf[8];
 	struct proc_dir_entry *ent;
 #endif
 
-	uhci->dev = dev;
-
-	/* Should probably move to core/hcd.c */
-	if (pci_set_dma_mask(dev, 0xFFFFFFFF)) {
-		err("couldn't set PCI dma mask");
-		retval = -ENODEV;
-		goto err_pci_set_dma_mask;
-	}
-
-	uhci->io_addr = pci_resource_start(dev, hcd->region);
-	uhci->io_size = pci_resource_len(dev, hcd->region);
+	uhci->io_addr = (unsigned) hcd->regs;
+	io_size = pci_resource_len(hcd->pdev, hcd->region);
 
 #ifdef CONFIG_PROC_FS
-	uhci->num = uhci_num++;
-
-	sprintf(buf, "hc%d", uhci->num);
-
-	ent = create_proc_entry(buf, S_IFREG|S_IRUGO|S_IWUSR, uhci_proc_root);
+	ent = create_proc_entry(hcd->self.bus_name, S_IFREG|S_IRUGO|S_IWUSR, uhci_proc_root);
 	if (!ent) {
 		err("couldn't create uhci proc entry");
 		retval = -ENOMEM;
@@ -2159,7 +2138,7 @@
 
 	spin_lock_init(&uhci->frame_list_lock);
 
-	uhci->fl = pci_alloc_consistent(dev, sizeof(*uhci->fl), &dma_handle);
+	uhci->fl = pci_alloc_consistent(hcd->pdev, sizeof(*uhci->fl), &dma_handle);
 	if (!uhci->fl) {
 		err("unable to allocate consistent memory for frame list");
 		goto err_alloc_fl;
@@ -2169,15 +2148,15 @@
 
 	uhci->fl->dma_handle = dma_handle;
 
-	uhci->td_pool = pci_pool_create("uhci_td", dev,
-		sizeof(struct uhci_td), 16, 0, GFP_DMA | GFP_ATOMIC);
+	uhci->td_pool = pci_pool_create("uhci_td", hcd->pdev,
+		sizeof(struct uhci_td), 16, 0, GFP_ATOMIC);
 	if (!uhci->td_pool) {
 		err("unable to create td pci_pool");
 		goto err_create_td_pool;
 	}
 
-	uhci->qh_pool = pci_pool_create("uhci_qh", dev,
-		sizeof(struct uhci_qh), 16, 0, GFP_DMA | GFP_ATOMIC);
+	uhci->qh_pool = pci_pool_create("uhci_qh", hcd->pdev,
+		sizeof(struct uhci_qh), 16, 0, GFP_ATOMIC);
 	if (!uhci->qh_pool) {
 		err("unable to create qh pci_pool");
 		goto err_create_qh_pool;
@@ -2189,7 +2168,7 @@
 	/*  they may have more but give no way to determine how many they */
 	/*  have. However, according to the UHCI spec, Bit 7 is always set */
 	/*  to 1. So we try to use this to our advantage */
-	for (port = 0; port < (uhci->io_size - 0x10) / 2; port++) {
+	for (port = 0; port < (io_size - 0x10) / 2; port++) {
 		unsigned int portstatus;
 
 		portstatus = inw(uhci->io_addr + 0x10 + (port * 2));
@@ -2208,13 +2187,13 @@
 
 	uhci->rh_numports = port;
 
-	hcd->self.root_hub = uhci->rh_dev = usb_alloc_dev(NULL, &hcd->self);
-	if (!uhci->rh_dev) {
+	hcd->self.root_hub = udev = usb_alloc_dev(NULL, &hcd->self);
+	if (!udev) {
 		err("unable to allocate root hub");
 		goto err_alloc_root_hub;
 	}
 
-	uhci->skeltd[0] = uhci_alloc_td(uhci, uhci->rh_dev);
+	uhci->skeltd[0] = uhci_alloc_td(uhci, udev);
 	if (!uhci->skeltd[0]) {
 		err("unable to allocate TD 0");
 		goto err_alloc_skeltd;
@@ -2227,7 +2206,7 @@
 	for (i = 1; i < 9; i++) {
 		struct uhci_td *td;
 
-		td = uhci->skeltd[i] = uhci_alloc_td(uhci, uhci->rh_dev);
+		td = uhci->skeltd[i] = uhci_alloc_td(uhci, udev);
 		if (!td) {
 			err("unable to allocate TD %d", i);
 			goto err_alloc_skeltd;
@@ -2238,14 +2217,14 @@
 		td->link = cpu_to_le32(uhci->skeltd[i - 1]->dma_handle);
 	}
 
-	uhci->skel_term_td = uhci_alloc_td(uhci, uhci->rh_dev);
+	uhci->skel_term_td = uhci_alloc_td(uhci, udev);
 	if (!uhci->skel_term_td) {
 		err("unable to allocate skel TD term");
 		goto err_alloc_skeltd;
 	}
 
 	for (i = 0; i < UHCI_NUM_SKELQH; i++) {
-		uhci->skelqh[i] = uhci_alloc_qh(uhci, uhci->rh_dev);
+		uhci->skelqh[i] = uhci_alloc_qh(uhci, udev);
 		if (!uhci->skelqh[i]) {
 			err("unable to allocate QH %d", i);
 			goto err_alloc_skelqh;
@@ -2314,12 +2293,12 @@
 	init_stall_timer(hcd);
 
 	/* disable legacy emulation */
-	pci_write_config_word(dev, USBLEGSUP, USBLEGSUP_DEFAULT);
+	pci_write_config_word(hcd->pdev, USBLEGSUP, USBLEGSUP_DEFAULT);
 
-	usb_connect(uhci->rh_dev);
-        uhci->rh_dev->speed = USB_SPEED_FULL;
+	usb_connect(udev);
+	udev->speed = USB_SPEED_FULL;
 
-	if (usb_register_root_hub(uhci->rh_dev, &dev->dev) != 0) {
+	if (usb_register_root_hub(udev, &hcd->pdev->dev) != 0) {
 		err("unable to start root hub");
 		retval = -ENOMEM;
 		goto err_start_root_hub;
@@ -2333,7 +2312,7 @@
 err_start_root_hub:
 	reset_hc(uhci);
 
-	del_timer(&uhci->stall_timer);
+	del_timer_sync(&uhci->stall_timer);
 
 	for (i = 0; i < UHCI_NUM_SKELQH; i++)
 		if (uhci->skelqh[i]) {
@@ -2349,8 +2328,7 @@
 		}
 
 err_alloc_skeltd:
-	usb_free_dev(uhci->rh_dev);
-	uhci->rh_dev = NULL;
+	usb_free_dev(udev);
 
 err_alloc_root_hub:
 	pci_pool_destroy(uhci->qh_pool);
@@ -2361,19 +2339,17 @@
 	uhci->td_pool = NULL;
 
 err_create_td_pool:
-	pci_free_consistent(dev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle);
+	pci_free_consistent(hcd->pdev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle);
 	uhci->fl = NULL;
 
 err_alloc_fl:
 #ifdef CONFIG_PROC_FS
-	remove_proc_entry(buf, uhci_proc_root);
+	remove_proc_entry(hcd->self.bus_name, uhci_proc_root);
 	uhci->proc_entry = NULL;
 
 err_create_proc_entry:
 #endif
 
-err_pci_set_dma_mask:
-
 	return retval;
 }
 
@@ -2381,10 +2357,7 @@
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
-	if (uhci->rh_dev)
-		usb_disconnect(&uhci->rh_dev);
-
-	del_timer(&uhci->stall_timer);
+	del_timer_sync(&uhci->stall_timer);
 
 	/*
 	 * At this point, we're guaranteed that no new connects can be made
@@ -2413,7 +2386,7 @@
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
-	pci_set_master(uhci->dev);
+	pci_set_master(uhci->hcd.pdev);
 
 	reset_hc(uhci);
 	start_hc(uhci);
diff -Nru a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
--- a/drivers/usb/host/uhci-hcd.h	Thu Sep  5 08:51:45 2002
+++ b/drivers/usb/host/uhci-hcd.h	Thu Sep  5 08:51:45 2002
@@ -308,7 +308,7 @@
 	return 7;				/* int128 for 128-255 ms (Max.) */
 }
 
-#define hcd_to_uhci(hcd_ptr) list_entry(hcd_ptr, struct uhci_hcd, hcd)
+#define hcd_to_uhci(hcd_ptr) container_of(hcd_ptr, struct uhci_hcd, hcd)
 
 /*
  * This describes the full uhci information.
@@ -319,18 +319,13 @@
 struct uhci_hcd {
 	struct usb_hcd hcd;
 
-	struct pci_dev *dev;
-
 #ifdef CONFIG_PROC_FS
 	/* procfs */
-	int num;
 	struct proc_dir_entry *proc_entry;
 #endif
 
 	/* Grabbed from PCI */
-	int irq;
 	unsigned int io_addr;
-	unsigned int io_size;
 
 	struct pci_pool *qh_pool;
 	struct pci_pool *td_pool;
@@ -362,7 +357,6 @@
 	spinlock_t complete_list_lock;
 	struct list_head complete_list;		/* P: uhci->complete_list_lock */
 
-	struct usb_device *rh_dev;		/* Root hub */
 	int rh_numports;
 
 	struct timer_list stall_timer;
