Explorar o código

Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6: (35 commits)
  usb: add PRODUCT, TYPE to usb-interface events
  USB: resubmission unusual_devs modification for Nikon D80
  usb quirks: Add Canon EOS 5D (PC Connection mode) to the autosuspend blacklist
  USB: make EHCI initialize properly on PPC SOCs
  UEAGLE: Remove sysfs files on error case
  USB: fsl_usb2_udc: fix bug in processing setup requests
  USB: g_file_storage: fix bug in DMA buffer handling
  USB: update last_busy field correctly
  USB: fix DoS in pwc USB video driver
  USB: allow retry on descriptor fetch errors
  USB: unkill cxacru atm driver
  USB: Adding support for HTC Smartphones to ipaq
  USB: another quirky device
  USB: quirky mass storage device
  USB: ohci, fix oddball gcc warning
  usb-storage: fix bugs in the disconnect pathway
  usb: typo in usb R8A66597 HCD config
  USB: accept 1-byte Device Status replies, fixing some b0rken devices
  USB: blacklist Samsung ML-2010 printer
  usb-serial: fix oti6858.c segfault in termios handling
  ...
Linus Torvalds %!s(int64=18) %!d(string=hai) anos
pai
achega
9e1a3e31cb

+ 1 - 0
drivers/media/video/em28xx/em28xx-video.c

@@ -1772,6 +1772,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
 	if (dev->alt_max_pkt_size == NULL) {
 		em28xx_errdev("out of memory!\n");
 		em28xx_devused&=~(1<<nr);
+		kfree(dev);
 		return -ENOMEM;
 	}
 

+ 35 - 17
drivers/media/video/pwc/pwc-if.c

@@ -1196,12 +1196,19 @@ static int pwc_video_open(struct inode *inode, struct file *file)
 	return 0;
 }
 
+
+static void pwc_cleanup(struct pwc_device *pdev)
+{
+	pwc_remove_sysfs_files(pdev->vdev);
+	video_unregister_device(pdev->vdev);
+}
+
 /* Note that all cleanup is done in the reverse order as in _open */
 static int pwc_video_close(struct inode *inode, struct file *file)
 {
 	struct video_device *vdev = file->private_data;
 	struct pwc_device *pdev;
-	int i;
+	int i, hint;
 
 	PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
 
@@ -1224,8 +1231,9 @@ static int pwc_video_close(struct inode *inode, struct file *file)
 	pwc_isoc_cleanup(pdev);
 	pwc_free_buffers(pdev);
 
+	lock_kernel();
 	/* Turn off LEDS and power down camera, but only when not unplugged */
-	if (pdev->error_status != EPIPE) {
+	if (!pdev->unplugged) {
 		/* Turn LEDs off */
 		if (pwc_set_leds(pdev, 0, 0) < 0)
 			PWC_DEBUG_MODULE("Failed to set LED on/off time.\n");
@@ -1234,9 +1242,19 @@ static int pwc_video_close(struct inode *inode, struct file *file)
 			if (i < 0)
 				PWC_ERROR("Failed to power down camera (%d)\n", i);
 		}
+		pdev->vopen--;
+		PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", i);
+	} else {
+		pwc_cleanup(pdev);
+		/* Free memory (don't set pdev to 0 just yet) */
+		kfree(pdev);
+		/* search device_hint[] table if we occupy a slot, by any chance */
+		for (hint = 0; hint < MAX_DEV_HINTS; hint++)
+			if (device_hint[hint].pdev == pdev)
+				device_hint[hint].pdev = NULL;
 	}
-	pdev->vopen--;
-	PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
+	unlock_kernel();
+
 	return 0;
 }
 
@@ -1791,21 +1809,21 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
 	/* Alert waiting processes */
 	wake_up_interruptible(&pdev->frameq);
 	/* Wait until device is closed */
-	while (pdev->vopen)
-		schedule();
-	/* Device is now closed, so we can safely unregister it */
-	PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n");
-	pwc_remove_sysfs_files(pdev->vdev);
-	video_unregister_device(pdev->vdev);
-
-	/* Free memory (don't set pdev to 0 just yet) */
-	kfree(pdev);
+	if(pdev->vopen) {
+		pdev->unplugged = 1;
+	} else {
+		/* Device is closed, so we can safely unregister it */
+		PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n");
+		pwc_cleanup(pdev);
+		/* Free memory (don't set pdev to 0 just yet) */
+		kfree(pdev);
 
 disconnect_out:
-	/* search device_hint[] table if we occupy a slot, by any chance */
-	for (hint = 0; hint < MAX_DEV_HINTS; hint++)
-		if (device_hint[hint].pdev == pdev)
-			device_hint[hint].pdev = NULL;
+		/* search device_hint[] table if we occupy a slot, by any chance */
+		for (hint = 0; hint < MAX_DEV_HINTS; hint++)
+			if (device_hint[hint].pdev == pdev)
+				device_hint[hint].pdev = NULL;
+	}
 
 	unlock_kernel();
 }

+ 1 - 0
drivers/media/video/pwc/pwc.h

@@ -193,6 +193,7 @@ struct pwc_device
    char vsnapshot;		/* snapshot mode */
    char vsync;			/* used by isoc handler */
    char vmirror;		/* for ToUCaM series */
+	char unplugged;
 
    int cmd_len;
    unsigned char cmd_buf[13];

+ 1 - 0
drivers/usb/Kconfig

@@ -21,6 +21,7 @@ config USB_ARCH_HAS_HCD
 	default y if USB_ARCH_HAS_EHCI
 	default y if PCMCIA && !M32R			# sl811_cs
 	default y if ARM				# SL-811
+	default y if SUPERH				# r8a66597-hcd
 	default PCI
 
 # many non-PCI SOC chips embed OHCI

+ 1 - 2
drivers/usb/atm/cxacru.c

@@ -456,7 +456,6 @@ static int cxacru_start_wait_urb(struct urb *urb, struct completion *done,
 				 int* actual_length)
 {
 	struct timer_list timer;
-	int status = urb->status;
 
 	init_timer(&timer);
 	timer.expires = jiffies + msecs_to_jiffies(CMD_TIMEOUT);
@@ -468,7 +467,7 @@ static int cxacru_start_wait_urb(struct urb *urb, struct completion *done,
 
 	if (actual_length)
 		*actual_length = urb->actual_length;
-	return status;
+	return urb->status; /* must read status after completion */
 }
 
 static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm,

+ 4 - 1
drivers/usb/atm/ueagle-atm.c

@@ -1721,9 +1721,12 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
 
 	ret = uea_boot(sc);
 	if (ret < 0)
-		goto error;
+		goto error_rm_grp;
 
 	return 0;
+
+error_rm_grp:
+	sysfs_remove_group(&intf->dev.kobj, &attr_grp);
 error:
 	kfree(sc);
 	return ret;

+ 9 - 3
drivers/usb/class/cdc-acm.c

@@ -921,6 +921,10 @@ skip_normal_probe:
 			return -EINVAL;
 		}
 	}
+
+	/* Accept probe requests only for the control interface */
+	if (intf != control_interface)
+		return -ENODEV;
 	
 	if (usb_interface_claimed(data_interface)) { /* valid in this context */
 		dev_dbg(&intf->dev,"The data interface isn't available");
@@ -1109,10 +1113,12 @@ static void acm_disconnect(struct usb_interface *intf)
 		return;
 	}
 	if (acm->country_codes){
-		device_remove_file(&intf->dev, &dev_attr_wCountryCodes);
-		device_remove_file(&intf->dev, &dev_attr_iCountryCodeRelDate);
+		device_remove_file(&acm->control->dev,
+				&dev_attr_wCountryCodes);
+		device_remove_file(&acm->control->dev,
+				&dev_attr_iCountryCodeRelDate);
 	}
-	device_remove_file(&intf->dev, &dev_attr_bmCapabilities);
+	device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities);
 	acm->dev = NULL;
 	usb_set_intfdata(acm->control, NULL);
 	usb_set_intfdata(acm->data, NULL);

+ 4 - 5
drivers/usb/core/driver.c

@@ -1224,6 +1224,8 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
 	udev->auto_pm = 1;
 	udev->pm_usage_cnt += inc_usage_cnt;
 	WARN_ON(udev->pm_usage_cnt < 0);
+	if (inc_usage_cnt)
+		udev->last_busy = jiffies;
 	if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) {
 		if (udev->state == USB_STATE_SUSPENDED)
 			status = usb_resume_both(udev);
@@ -1232,8 +1234,6 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
 		else if (inc_usage_cnt)
 			udev->last_busy = jiffies;
 	} else if (inc_usage_cnt <= 0 && udev->pm_usage_cnt <= 0) {
-		if (inc_usage_cnt)
-			udev->last_busy = jiffies;
 		status = usb_suspend_both(udev, PMSG_SUSPEND);
 	}
 	usb_pm_unlock(udev);
@@ -1342,16 +1342,15 @@ static int usb_autopm_do_interface(struct usb_interface *intf,
 	else {
 		udev->auto_pm = 1;
 		intf->pm_usage_cnt += inc_usage_cnt;
+		udev->last_busy = jiffies;
 		if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) {
 			if (udev->state == USB_STATE_SUSPENDED)
 				status = usb_resume_both(udev);
 			if (status != 0)
 				intf->pm_usage_cnt -= inc_usage_cnt;
-			else if (inc_usage_cnt)
+			else
 				udev->last_busy = jiffies;
 		} else if (inc_usage_cnt <= 0 && intf->pm_usage_cnt <= 0) {
-			if (inc_usage_cnt)
-				udev->last_busy = jiffies;
 			status = usb_suspend_both(udev, PMSG_SUSPEND);
 		}
 	}

+ 2 - 1
drivers/usb/core/hub.c

@@ -1644,9 +1644,10 @@ static int finish_port_resume(struct usb_device *udev)
 	 * and device drivers will know about any resume quirks.
 	 */
 	if (status == 0) {
+		devstatus = 0;
 		status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
 		if (status >= 0)
-			status = (status == 2 ? 0 : -ENODEV);
+			status = (status > 0 ? 0 : -ENODEV);
 	}
 
 	if (status) {

+ 26 - 2
drivers/usb/core/message.c

@@ -637,12 +637,12 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char
 	memset(buf,0,size);	// Make sure we parse really received data
 
 	for (i = 0; i < 3; ++i) {
-		/* retry on length 0 or stall; some devices are flakey */
+		/* retry on length 0 or error; some devices are flakey */
 		result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 				USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
 				(type << 8) + index, 0, buf, size,
 				USB_CTRL_GET_TIMEOUT);
-		if (result == 0 || result == -EPIPE)
+		if (result <= 0 && result != -ETIMEDOUT)
 			continue;
 		if (result > 1 && ((u8 *)buf)[1] != type) {
 			result = -EPROTO;
@@ -1358,6 +1358,30 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp,
 	usb_dev = interface_to_usbdev(intf);
 	alt = intf->cur_altsetting;
 
+#ifdef CONFIG_USB_DEVICEFS
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "DEVICE=/proc/bus/usb/%03d/%03d",
+			   usb_dev->bus->busnum, usb_dev->devnum))
+		return -ENOMEM;
+#endif
+
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "PRODUCT=%x/%x/%x",
+			   le16_to_cpu(usb_dev->descriptor.idVendor),
+			   le16_to_cpu(usb_dev->descriptor.idProduct),
+			   le16_to_cpu(usb_dev->descriptor.bcdDevice)))
+		return -ENOMEM;
+
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "TYPE=%d/%d/%d",
+			   usb_dev->descriptor.bDeviceClass,
+			   usb_dev->descriptor.bDeviceSubClass,
+			   usb_dev->descriptor.bDeviceProtocol))
+		return -ENOMEM;
+
 	if (add_uevent_var(envp, num_envp, &i,
 		   buffer, buffer_size, &length,
 		   "INTERFACE=%d/%d/%d",

+ 12 - 0
drivers/usb/core/quirks.c

@@ -30,6 +30,8 @@
 static const struct usb_device_id usb_quirk_list[] = {
 	/* HP 5300/5370C scanner */
 	{ USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 },
+	/* Hewlett-Packard PhotoSmart 720 / PhotoSmart 935 (storage) */
+	{ USB_DEVICE(0x03f0, 0x4002), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
 	/* Acer Peripherals Inc. (now BenQ Corp.) Prisa 640BU */
 	{ USB_DEVICE(0x04a5, 0x207e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
 	/* Benq S2W 3300U */
@@ -56,6 +58,8 @@ static const struct usb_device_id usb_quirk_list[] = {
 	{ USB_DEVICE(0x04b8, 0x0121), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
 	/* Seiko Epson Corp.*/
 	{ USB_DEVICE(0x04b8, 0x0122), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+	/* Samsung ML-2010 printer */
+	{ USB_DEVICE(0x04e8, 0x326c), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
 	/* Samsung ML-2510 Series printer */
 	{ USB_DEVICE(0x04e8, 0x327e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
 	/* Elsa MicroLink 56k (V.250) */
@@ -64,12 +68,20 @@ static const struct usb_device_id usb_quirk_list[] = {
 	{ USB_DEVICE(0x05d8, 0x4005), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
 	/* Agfa Snapscan1212u */
 	{ USB_DEVICE(0x06bd, 0x2061), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+	/* Seagate RSS LLC */
+	{ USB_DEVICE(0x0bc2, 0x3000), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
 	/* Umax [hex] Astra 3400U */
 	{ USB_DEVICE(0x1606, 0x0060), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
 
 	/* Philips PSC805 audio device */
 	{ USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
 
+	/* Alcor multi-card reader */
+	{ USB_DEVICE(0x058f, 0x6366), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+
+	/* Canon EOS 5D in PC Connection mode */
+	{ USB_DEVICE(0x04a9, 0x3101), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+
 	/* RIM Blackberry */
 	{ USB_DEVICE(0x0fca, 0x0001), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
 	{ USB_DEVICE(0x0fca, 0x0004), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },

+ 0 - 2
drivers/usb/gadget/dummy_hcd.c

@@ -34,8 +34,6 @@
  * bypassing some hardware (and driver) issues.  UML could help too.
  */
 
-#define DEBUG
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>

+ 4 - 6
drivers/usb/gadget/file_storage.c

@@ -599,7 +599,6 @@ enum fsg_buffer_state {
 
 struct fsg_buffhd {
 	void				*buf;
-	dma_addr_t			dma;
 	enum fsg_buffer_state		state;
 	struct fsg_buffhd		*next;
 
@@ -1295,6 +1294,7 @@ static int class_setup_req(struct fsg_dev *fsg,
 	struct usb_request	*req = fsg->ep0req;
 	int			value = -EOPNOTSUPP;
 	u16			w_index = le16_to_cpu(ctrl->wIndex);
+	u16                     w_value = le16_to_cpu(ctrl->wValue);
 	u16			w_length = le16_to_cpu(ctrl->wLength);
 
 	if (!fsg->config)
@@ -1308,7 +1308,7 @@ static int class_setup_req(struct fsg_dev *fsg,
 			if (ctrl->bRequestType != (USB_DIR_OUT |
 					USB_TYPE_CLASS | USB_RECIP_INTERFACE))
 				break;
-			if (w_index != 0) {
+			if (w_index != 0 || w_value != 0) {
 				value = -EDOM;
 				break;
 			}
@@ -1324,7 +1324,7 @@ static int class_setup_req(struct fsg_dev *fsg,
 			if (ctrl->bRequestType != (USB_DIR_IN |
 					USB_TYPE_CLASS | USB_RECIP_INTERFACE))
 				break;
-			if (w_index != 0) {
+			if (w_index != 0 || w_value != 0) {
 				value = -EDOM;
 				break;
 			}
@@ -1343,7 +1343,7 @@ static int class_setup_req(struct fsg_dev *fsg,
 			if (ctrl->bRequestType != (USB_DIR_OUT |
 					USB_TYPE_CLASS | USB_RECIP_INTERFACE))
 				break;
-			if (w_index != 0) {
+			if (w_index != 0 || w_value != 0) {
 				value = -EDOM;
 				break;
 			}
@@ -2611,7 +2611,6 @@ static int send_status(struct fsg_dev *fsg)
 
 		fsg->intr_buffhd = bh;		// Point to the right buffhd
 		fsg->intreq->buf = bh->inreq->buf;
-		fsg->intreq->dma = bh->inreq->dma;
 		fsg->intreq->context = bh;
 		start_transfer(fsg, fsg->intr_in, fsg->intreq,
 				&fsg->intreq_busy, &bh->state);
@@ -3200,7 +3199,6 @@ reset:
 		if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0)
 			goto reset;
 		bh->inreq->buf = bh->outreq->buf = bh->buf;
-		bh->inreq->dma = bh->outreq->dma = bh->dma;
 		bh->inreq->context = bh->outreq->context = bh;
 		bh->inreq->complete = bulk_in_complete;
 		bh->outreq->complete = bulk_out_complete;

+ 41 - 36
drivers/usb/gadget/fsl_usb2_udc.c

@@ -1277,31 +1277,32 @@ static void setup_received_irq(struct fsl_udc *udc,
 
 	udc_reset_ep_queue(udc, 0);
 
+	/* We process some stardard setup requests here */
 	switch (setup->bRequest) {
-		/* Request that need Data+Status phase from udc */
 	case USB_REQ_GET_STATUS:
-		if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_STANDARD))
+		/* Data+Status phase from udc */
+		if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK))
 					!= (USB_DIR_IN | USB_TYPE_STANDARD))
 			break;
 		ch9getstatus(udc, setup->bRequestType, wValue, wIndex, wLength);
-		break;
+		return;
 
-		/* Requests that need Status phase from udc */
 	case USB_REQ_SET_ADDRESS:
+		/* Status phase from udc */
 		if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD
 						| USB_RECIP_DEVICE))
 			break;
 		ch9setaddress(udc, wValue, wIndex, wLength);
-		break;
+		return;
 
-		/* Handled by udc, no data, status by udc */
 	case USB_REQ_CLEAR_FEATURE:
 	case USB_REQ_SET_FEATURE:
-	{	/* status transaction */
+		/* Status phase from udc */
+	{
 		int rc = -EOPNOTSUPP;
 
-		if ((setup->bRequestType & USB_RECIP_MASK)
-				== USB_RECIP_ENDPOINT) {
+		if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK))
+				== (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD)) {
 			int pipe = get_pipe_by_windex(wIndex);
 			struct fsl_ep *ep;
 
@@ -1315,8 +1316,9 @@ static void setup_received_irq(struct fsl_udc *udc,
 						? 1 : 0);
 			spin_lock(&udc->lock);
 
-		} else if ((setup->bRequestType & USB_RECIP_MASK)
-				== USB_RECIP_DEVICE) {
+		} else if ((setup->bRequestType & (USB_RECIP_MASK
+				| USB_TYPE_MASK)) == (USB_RECIP_DEVICE
+				| USB_TYPE_STANDARD)) {
 			/* Note: The driver has not include OTG support yet.
 			 * This will be set when OTG support is added */
 			if (!udc->gadget.is_otg)
@@ -1329,39 +1331,42 @@ static void setup_received_irq(struct fsl_udc *udc,
 					USB_DEVICE_A_ALT_HNP_SUPPORT)
 				udc->gadget.a_alt_hnp_support = 1;
 			rc = 0;
-		}
+		} else
+			break;
+
 		if (rc == 0) {
 			if (ep0_prime_status(udc, EP_DIR_IN))
 				ep0stall(udc);
 		}
-		break;
+		return;
 	}
-		/* Requests handled by gadget */
-	default:
-		if (wLength) {
-			/* Data phase from gadget, status phase from udc */
-			udc->ep0_dir = (setup->bRequestType & USB_DIR_IN)
-					?  USB_DIR_IN : USB_DIR_OUT;
-			spin_unlock(&udc->lock);
-			if (udc->driver->setup(&udc->gadget,
-					&udc->local_setup_buff) < 0)
-				ep0stall(udc);
-			spin_lock(&udc->lock);
-			udc->ep0_state = (setup->bRequestType & USB_DIR_IN)
-					?  DATA_STATE_XMIT : DATA_STATE_RECV;
 
-		} else {
-			/* No data phase, IN status from gadget */
-			udc->ep0_dir = USB_DIR_IN;
-			spin_unlock(&udc->lock);
-			if (udc->driver->setup(&udc->gadget,
-					&udc->local_setup_buff) < 0)
-				ep0stall(udc);
-			spin_lock(&udc->lock);
-			udc->ep0_state = WAIT_FOR_OUT_STATUS;
-		}
+	default:
 		break;
 	}
+
+	/* Requests handled by gadget */
+	if (wLength) {
+		/* Data phase from gadget, status phase from udc */
+		udc->ep0_dir = (setup->bRequestType & USB_DIR_IN)
+				?  USB_DIR_IN : USB_DIR_OUT;
+		spin_unlock(&udc->lock);
+		if (udc->driver->setup(&udc->gadget,
+				&udc->local_setup_buff) < 0)
+			ep0stall(udc);
+		spin_lock(&udc->lock);
+		udc->ep0_state = (setup->bRequestType & USB_DIR_IN)
+				?  DATA_STATE_XMIT : DATA_STATE_RECV;
+	} else {
+		/* No data phase, IN status from gadget */
+		udc->ep0_dir = USB_DIR_IN;
+		spin_unlock(&udc->lock);
+		if (udc->driver->setup(&udc->gadget,
+				&udc->local_setup_buff) < 0)
+			ep0stall(udc);
+		spin_lock(&udc->lock);
+		udc->ep0_state = WAIT_FOR_OUT_STATUS;
+	}
 }
 
 /* Process request for Data or Status phase of ep0

+ 2 - 2
drivers/usb/gadget/pxa2xx_udc.c

@@ -967,7 +967,7 @@ static int pxa2xx_udc_pullup(struct usb_gadget *_gadget, int is_active)
 	udc = container_of(_gadget, struct pxa2xx_udc, gadget);
 
 	/* not all boards support pullup control */
-	if (!udc->mach->udc_command)
+	if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
 		return -EOPNOTSUPP;
 
 	is_active = (is_active != 0);
@@ -2309,7 +2309,7 @@ static int pxa2xx_udc_suspend(struct platform_device *dev, pm_message_t state)
 {
 	struct pxa2xx_udc	*udc = platform_get_drvdata(dev);
 
-	if (!udc->mach->udc_command)
+	if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
 		WARN("USB host won't detect disconnect!\n");
 	pullup(udc, 0);
 

+ 1 - 1
drivers/usb/host/Kconfig

@@ -237,7 +237,7 @@ config USB_SL811_CS
 	  module will be called "sl811_cs".
 
 config USB_R8A66597_HCD
-	tristate "R8A66597 HCD suppoort"
+	tristate "R8A66597 HCD support"
 	depends on USB
 	help
 	  The R8A66597 is a USB 2.0 host and peripheral controller.

+ 3 - 2
drivers/usb/host/ehci-au1xxx.c

@@ -1,8 +1,6 @@
 /*
  * EHCI HCD (Host Controller Driver) for USB.
  *
- * (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net>
- *
  * Bus Glue for AMD Alchemy Au1xxx
  *
  * Based on "ohci-au1xxx.c" by Matt Porter <mporter@kernel.crashing.org>
@@ -196,6 +194,9 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
 
 	/*
 	 * basic lifecycle operations
+	 *
+	 * FIXME -- ehci_init() doesn't do enough here.
+	 * See ehci-ppc-soc for a complete implementation.
 	 */
 	.reset = ehci_init,
 	.start = ehci_run,

+ 20 - 2
drivers/usb/host/ehci-ppc-soc.c

@@ -6,7 +6,7 @@
  * Bus Glue for PPC On-Chip EHCI driver
  * Tested on AMCC 440EPx
  *
- * Based on "ehci-au12xx.c" by David Brownell <dbrownell@users.sourceforge.net>
+ * Based on "ehci-au1xxx.c" by K.Boge <karsten.boge@amd.com>
  *
  * This file is licenced under the GPL.
  */
@@ -15,6 +15,24 @@
 
 extern int usb_disabled(void);
 
+/* called during probe() after chip reset completes */
+static int ehci_ppc_soc_setup(struct usb_hcd *hcd)
+{
+	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+	int		retval;
+
+	retval = ehci_halt(ehci);
+	if (retval)
+		return retval;
+
+	retval = ehci_init(hcd);
+	if (retval)
+		return retval;
+
+	ehci->sbrn = 0x20;
+	return ehci_reset(ehci);
+}
+
 /**
  * usb_ehci_ppc_soc_probe - initialize PPC-SoC-based HCDs
  * Context: !in_interrupt()
@@ -120,7 +138,7 @@ static const struct hc_driver ehci_ppc_soc_hc_driver = {
 	/*
 	 * basic lifecycle operations
 	 */
-	.reset = ehci_init,
+	.reset = ehci_ppc_soc_setup,
 	.start = ehci_run,
 	.stop = ehci_stop,
 	.shutdown = ehci_shutdown,

+ 1 - 1
drivers/usb/host/ohci-dbg.c

@@ -74,7 +74,7 @@ urb_print (struct urb * urb, char * str, int small)
 
 #define ohci_dbg_sw(ohci, next, size, format, arg...) \
 	do { \
-	if (next) { \
+	if (next != NULL) { \
 		unsigned s_len; \
 		s_len = scnprintf (*next, *size, format, ## arg ); \
 		*size -= s_len; *next += s_len; \

+ 0 - 2
drivers/usb/host/r8a66597-hcd.c

@@ -2208,8 +2208,6 @@ static int __init r8a66597_probe(struct platform_device *pdev)
 clean_up:
 	if (reg)
 		iounmap(reg);
-	if (res)
-		release_mem_region(res->start, 1);
 
 	return ret;
 }

+ 3 - 0
drivers/usb/host/u132-hcd.c

@@ -1520,12 +1520,15 @@ static void u132_hcd_endp_work_scheduler(struct work_struct *work)
                 }
         }
 }
+#ifdef CONFIG_PM
 
 static void port_power(struct u132 *u132, int pn, int is_on)
 {
         u132->port[pn].power = is_on;
 }
 
+#endif
+
 static void u132_power(struct u132 *u132, int is_on)
 {
         struct usb_hcd *hcd = u132_to_hcd(u132)

+ 0 - 1
drivers/usb/serial/airprime.c

@@ -18,7 +18,6 @@
 
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
-	{ USB_DEVICE(0x413c, 0x8115) }, /* Dell Wireless HSDPA 5500 */
 	{ },
 };
 MODULE_DEVICE_TABLE(usb, id_table);

+ 4 - 0
drivers/usb/serial/belkin_sa.c

@@ -383,6 +383,10 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
 	}
 
 	baud = tty_get_baud_rate(port->tty);
+	if (baud == 0) {
+		dbg("%s - tty_get_baud_rate says 0 baud", __FUNCTION__);
+		return;
+	}
 	urb_value = BELKIN_SA_BAUD(baud);
 	/* Clip to maximum speed */
 	if (urb_value == 0)

+ 2 - 0
drivers/usb/serial/ftdi_sio.c

@@ -538,6 +538,8 @@ static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_VCP_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_D2XX_PID) },
 	{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
+	{ USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) },
+	{ USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },

+ 3 - 0
drivers/usb/serial/ftdi_sio.h

@@ -430,6 +430,9 @@
  */
 #define EVOLUTION_VID		0xDEEE	/* Vendor ID */
 #define EVOLUTION_ER1_PID	0x0300	/* ER1 Control Module */
+#define EVO_8U232AM_PID	0x02FF	/* Evolution robotics RCM2 (FT232AM)*/
+#define EVO_HYBRID_PID		0x0302	/* Evolution robotics RCM4 PID (FT232BM)*/
+#define EVO_RCM4_PID		0x0303	/* Evolution robotics RCM4 PID */
 
 /* Pyramid Computer GmbH */
 #define FTDI_PYRAMID_PID	0xE6C8	/* Pyramid Appliance Display */

+ 47 - 46
drivers/usb/serial/garmin_gps.c

@@ -1,7 +1,7 @@
 /*
  * Garmin GPS driver
  *
- * Copyright (C) 2006 Hermann Kneissel herkne@users.sourceforge.net
+ * Copyright (C) 2006,2007 Hermann Kneissel herkne@users.sourceforge.net
  *
  * The latest version of the driver can be found at
  * http://sourceforge.net/projects/garmin-gps/
@@ -34,6 +34,7 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <asm/uaccess.h>
+#include <asm/atomic.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
@@ -52,7 +53,7 @@ static int debug = 0;
  */
 
 #define VERSION_MAJOR	0
-#define VERSION_MINOR	28
+#define VERSION_MINOR	31
 
 #define _STR(s) #s
 #define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b)
@@ -141,6 +142,8 @@ struct garmin_data {
 	__u8   inbuffer [GPS_IN_BUFSIZ];  /* tty -> usb */
 	__u8   outbuffer[GPS_OUT_BUFSIZ]; /* usb -> tty */
 	__u8   privpkt[4*6];
+	atomic_t req_count;
+	atomic_t resp_count;
 	spinlock_t lock;
 	struct list_head pktlist;
 };
@@ -171,8 +174,6 @@ struct garmin_data {
 #define CLEAR_HALT_REQUIRED       0x0001
 
 #define FLAGS_QUEUING             0x0100
-#define FLAGS_APP_RESP_SEEN       0x0200
-#define FLAGS_APP_REQ_SEEN        0x0400
 #define FLAGS_DROP_DATA           0x0800
 
 #define FLAGS_GSP_SKIP            0x1000
@@ -186,7 +187,8 @@ struct garmin_data {
 /* function prototypes */
 static void gsp_next_packet(struct garmin_data * garmin_data_p);
 static int  garmin_write_bulk(struct usb_serial_port *port,
-			     const unsigned char *buf, int count);
+			     const unsigned char *buf, int count,
+			     int dismiss_ack);
 
 /* some special packets to be send or received */
 static unsigned char const GARMIN_START_SESSION_REQ[]
@@ -233,9 +235,7 @@ static struct usb_driver garmin_driver = {
 
 static inline int noResponseFromAppLayer(struct garmin_data * garmin_data_p)
 {
-	return ((garmin_data_p->flags
-				& (FLAGS_APP_REQ_SEEN|FLAGS_APP_RESP_SEEN))
-	        == FLAGS_APP_REQ_SEEN);
+	return atomic_read(&garmin_data_p->req_count) == atomic_read(&garmin_data_p->resp_count);
 }
 
 
@@ -463,7 +463,7 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
 	usbdata[2] = __cpu_to_le32(size);
 
 	garmin_write_bulk (garmin_data_p->port, garmin_data_p->inbuffer,
-			   GARMIN_PKTHDR_LENGTH+size);
+			   GARMIN_PKTHDR_LENGTH+size, 0);
 
 	/* if this was an abort-transfer command, flush all
 	   queued data. */
@@ -818,7 +818,7 @@ static int nat_receive(struct garmin_data * garmin_data_p,
 			if (garmin_data_p->insize >= len) {
 				garmin_write_bulk (garmin_data_p->port,
 				                   garmin_data_p->inbuffer,
-				                   len);
+				                   len, 0);
 				garmin_data_p->insize = 0;
 
 				/* if this was an abort-transfer command,
@@ -893,10 +893,11 @@ static int garmin_clear(struct garmin_data * garmin_data_p)
 
 	struct usb_serial_port *port = garmin_data_p->port;
 
-	if (port != NULL && garmin_data_p->flags & FLAGS_APP_RESP_SEEN) {
+	if (port != NULL && atomic_read(&garmin_data_p->resp_count)) {
 		/* send a terminate command */
 		status = garmin_write_bulk(port, GARMIN_STOP_TRANSFER_REQ,
-		                           sizeof(GARMIN_STOP_TRANSFER_REQ));
+		                           sizeof(GARMIN_STOP_TRANSFER_REQ),
+					   1);
 	}
 
 	/* flush all queued data */
@@ -939,7 +940,8 @@ static int garmin_init_session(struct usb_serial_port *port)
 		dbg("%s - starting session ...", __FUNCTION__);
 		garmin_data_p->state = STATE_ACTIVE;
 		status = garmin_write_bulk(port, GARMIN_START_SESSION_REQ,
-		                           sizeof(GARMIN_START_SESSION_REQ));
+		                           sizeof(GARMIN_START_SESSION_REQ),
+					   0);
 
 		if (status >= 0) {
 
@@ -950,7 +952,8 @@ static int garmin_init_session(struct usb_serial_port *port)
 			/* not needed, but the win32 driver does it too ... */
 			status = garmin_write_bulk(port,
 						   GARMIN_START_SESSION_REQ2,
-			                           sizeof(GARMIN_START_SESSION_REQ2));
+			                           sizeof(GARMIN_START_SESSION_REQ2),
+						   0);
 			if (status >= 0) {
 				status = 0;
 				spin_lock_irqsave(&garmin_data_p->lock, flags);
@@ -987,6 +990,8 @@ static int garmin_open (struct usb_serial_port *port, struct file *filp)
 	garmin_data_p->mode  = initial_mode;
 	garmin_data_p->count = 0;
 	garmin_data_p->flags = 0;
+	atomic_set(&garmin_data_p->req_count, 0);
+	atomic_set(&garmin_data_p->resp_count, 0);
 	spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
 	/* shutdown any bulk reads that might be going on */
@@ -1035,28 +1040,39 @@ static void garmin_write_bulk_callback (struct urb *urb)
 {
 	unsigned long flags;
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
-	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 	int status = urb->status;
 
-	/* free up the transfer buffer, as usb_free_urb() does not do this */
-	kfree (urb->transfer_buffer);
+	if (port) {
+		struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 
-	dbg("%s - port %d", __FUNCTION__, port->number);
+		dbg("%s - port %d", __FUNCTION__, port->number);
 
-	if (status) {
-		dbg("%s - nonzero write bulk status received: %d",
-			__FUNCTION__, status);
-		spin_lock_irqsave(&garmin_data_p->lock, flags);
-		garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
-		spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+		if (GARMIN_LAYERID_APPL == getLayerId(urb->transfer_buffer)
+		    && (garmin_data_p->mode == MODE_GARMIN_SERIAL))  {
+			gsp_send_ack(garmin_data_p, ((__u8 *)urb->transfer_buffer)[4]);
+		}
+
+		if (status) {
+			dbg("%s - nonzero write bulk status received: %d",
+			    __FUNCTION__, urb->status);
+			spin_lock_irqsave(&garmin_data_p->lock, flags);
+			garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
+			spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+		}
+
+		usb_serial_port_softint(port);
 	}
 
-	usb_serial_port_softint(port);
+	/* Ignore errors that resulted from garmin_write_bulk with dismiss_ack=1 */
+
+	/* free up the transfer buffer, as usb_free_urb() does not do this */
+	kfree (urb->transfer_buffer);
 }
 
 
 static int garmin_write_bulk (struct usb_serial_port *port,
-			      const unsigned char *buf, int count)
+			      const unsigned char *buf, int count,
+			      int dismiss_ack)
 {
 	unsigned long flags;
 	struct usb_serial *serial = port->serial;
@@ -1093,13 +1109,12 @@ static int garmin_write_bulk (struct usb_serial_port *port,
 			 	usb_sndbulkpipe (serial->dev,
 				port->bulk_out_endpointAddress),
 				buffer, count,
-				garmin_write_bulk_callback, port);
+				garmin_write_bulk_callback,
+				dismiss_ack ? NULL : port);
 	urb->transfer_flags |= URB_ZERO_PACKET;
 
 	if (GARMIN_LAYERID_APPL == getLayerId(buffer)) {
-		spin_lock_irqsave(&garmin_data_p->lock, flags);
-		garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
-		spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+		atomic_inc(&garmin_data_p->req_count);
 		if (garmin_data_p->mode == MODE_GARMIN_SERIAL)  {
 			pkt_clear(garmin_data_p);
 			garmin_data_p->state = STATE_GSP_WAIT_DATA;
@@ -1114,13 +1129,6 @@ static int garmin_write_bulk (struct usb_serial_port *port,
 		        "failed with status = %d\n",
 				__FUNCTION__, status);
 		count = status;
-	} else {
-
-		if (GARMIN_LAYERID_APPL == getLayerId(buffer)
-		    && (garmin_data_p->mode == MODE_GARMIN_SERIAL))  {
-
-			gsp_send_ack(garmin_data_p, buffer[4]);
-		}
 	}
 
 	/* we are done with this urb, so let the host driver
@@ -1135,7 +1143,6 @@ static int garmin_write_bulk (struct usb_serial_port *port,
 static int garmin_write (struct usb_serial_port *port,
 			 const unsigned char *buf, int count)
 {
-	unsigned long flags;
 	int pktid, pktsiz, len;
 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 	__le32 *privpkt = (__le32 *)garmin_data_p->privpkt;
@@ -1186,9 +1193,7 @@ static int garmin_write (struct usb_serial_port *port,
 				break;
 
 			case PRIV_PKTID_RESET_REQ:
-				spin_lock_irqsave(&garmin_data_p->lock, flags);
-				garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
-				spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+				atomic_inc(&garmin_data_p->req_count);
 				break;
 
 			case PRIV_PKTID_SET_DEF_MODE:
@@ -1241,8 +1246,6 @@ static int garmin_chars_in_buffer (struct usb_serial_port *port)
 static void garmin_read_process(struct garmin_data * garmin_data_p,
 				 unsigned char *data, unsigned data_length)
 {
-	unsigned long flags;
-
 	if (garmin_data_p->flags & FLAGS_DROP_DATA) {
 		/* abort-transfer cmd is actice */
 		dbg("%s - pkt dropped", __FUNCTION__);
@@ -1254,9 +1257,7 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
 		   the device */
 		if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY,
 		                sizeof(GARMIN_APP_LAYER_REPLY))) {
-			spin_lock_irqsave(&garmin_data_p->lock, flags);
-			garmin_data_p->flags |= FLAGS_APP_RESP_SEEN;
-			spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+			atomic_inc(&garmin_data_p->resp_count);
 		}
 
 		/* if throttling is active or postprecessing is required

+ 1 - 0
drivers/usb/serial/ipaq.c

@@ -545,6 +545,7 @@ static struct usb_device_id ipaq_id_table [] = {
 	{ USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */
 	{ USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */
 	{ USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */
+	{ USB_DEVICE(0x0BB4, 0x00CF) }, /* HTC smartphone modems */
 	{ }                             /* Terminating entry */
 };
 

+ 7 - 3
drivers/usb/serial/option.c

@@ -110,6 +110,7 @@ static int  option_send_setup(struct usb_serial_port *port);
 #define HUAWEI_PRODUCT_E220			0x1003
 
 #define NOVATELWIRELESS_VENDOR_ID		0x1410
+#define DELL_VENDOR_ID				0x413C
 
 #define ANYDATA_VENDOR_ID			0x16d5
 #define ANYDATA_PRODUCT_ADU_E100A		0x6501
@@ -119,8 +120,6 @@ static int  option_send_setup(struct usb_serial_port *port);
 #define BANDRICH_PRODUCT_C100_1			0x1002
 #define BANDRICH_PRODUCT_C100_2			0x1003
 
-#define DELL_VENDOR_ID				0x413C
-
 static struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -171,11 +170,16 @@ static struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2110) }, /* Novatel Merlin ES620 / Merlin ES720 / Ovation U720 */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2130) }, /* Novatel Merlin ES620 SM Bus */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2410) }, /* Novatel EU740 */
+	{ USB_DEVICE(DELL_VENDOR_ID, 0x8114) },	/* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite EV620 CDMA/EV-DO */
+	{ USB_DEVICE(DELL_VENDOR_ID, 0x8115) },	/* Dell Wireless 5500 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
+	{ USB_DEVICE(DELL_VENDOR_ID, 0x8116) },	/* Dell Wireless 5505 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
+	{ USB_DEVICE(DELL_VENDOR_ID, 0x8117) },	/* Dell Wireless 5700 Mobile Broadband CDMA/EVDO ExpressCard == Novatel Merlin XV620 CDMA/EV-DO */
+	{ USB_DEVICE(DELL_VENDOR_ID, 0x8118) },	/* Dell Wireless 5510 Mobile Broadband HSDPA ExpressCard == Novatel Merlin XU870 HSDPA/3G */
+	{ USB_DEVICE(DELL_VENDOR_ID, 0x8128) },	/* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite E720 CDMA/EV-DO */
 	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },
 	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
 	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
 	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
-	{ USB_DEVICE(DELL_VENDOR_ID, 0x8118) },		/* Dell Wireless 5510 Mobile Broadband HSDPA ExpressCard */
 	{ } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);

+ 4 - 6
drivers/usb/serial/oti6858.c

@@ -818,19 +818,17 @@ static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
 
 	switch (cmd) {
 		case TCGETS:
-			if (copy_to_user(user_arg, port->tty->termios,
-						sizeof(struct ktermios))) {
+			if (kernel_termios_to_user_termios((struct ktermios __user *)arg,
+							   port->tty->termios))
 				return -EFAULT;
-			}
 			return 0;
 
 		case TCSETS:
 		case TCSETSW:	/* FIXME: this is not the same! */
 		case TCSETSF:	/* FIXME: this is not the same! */
-			if (copy_from_user(port->tty->termios, user_arg,
-						sizeof(struct ktermios))) {
+			if (user_termios_to_kernel_termios(port->tty->termios,
+						(struct ktermios __user *)arg))
 				return -EFAULT;
-			}
 			oti6858_set_termios(port, NULL);
 			return 0;
 

+ 3 - 3
drivers/usb/serial/safe_serial.c

@@ -74,13 +74,13 @@
 #include <linux/usb/serial.h>
 
 
-#ifndef CONFIG_USB_SAFE_PADDED
-#define CONFIG_USB_SAFE_PADDED 0
+#ifndef CONFIG_USB_SERIAL_SAFE_PADDED
+#define CONFIG_USB_SERIAL_SAFE_PADDED 0
 #endif
 
 static int debug;
 static int safe = 1;
-static int padded = CONFIG_USB_SAFE_PADDED;
+static int padded = CONFIG_USB_SERIAL_SAFE_PADDED;
 
 #define DRIVER_VERSION "v0.0b"
 #define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com"

+ 2 - 0
drivers/usb/serial/visor.c

@@ -104,6 +104,8 @@ static struct usb_device_id id_table [] = {
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID),
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
+	{ USB_DEVICE(ACER_VENDOR_ID, ACER_S10_ID),
+		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID), 
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID), 

+ 3 - 0
drivers/usb/serial/visor.h

@@ -48,6 +48,9 @@
 #define SONY_CLIE_UX50_ID		0x0144
 #define SONY_CLIE_TJ25_ID		0x0169
 
+#define ACER_VENDOR_ID			0x0502
+#define ACER_S10_ID			0x0001
+
 #define SAMSUNG_VENDOR_ID		0x04E8
 #define SAMSUNG_SCH_I330_ID		0x8001
 #define SAMSUNG_SPH_I500_ID		0x6601

+ 1 - 1
drivers/usb/storage/unusual_devs.h

@@ -342,7 +342,7 @@ UNUSUAL_DEV(  0x04b0, 0x040d, 0x0100, 0x0100,
 		US_FL_FIX_CAPACITY),
 
 /* Reported by Emil Larsson <emil@swip.net> */
-UNUSUAL_DEV(  0x04b0, 0x0411, 0x0100, 0x0100,
+UNUSUAL_DEV(  0x04b0, 0x0411, 0x0100, 0x0101,
 		"NIKON",
 		"NIKON DSC D80",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,

+ 6 - 27
drivers/usb/storage/usb.c

@@ -112,13 +112,6 @@ module_param(delay_use, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");
 
 
-/* These are used to make sure the module doesn't unload before all the
- * threads have exited.
- */
-static atomic_t total_threads = ATOMIC_INIT(0);
-static DECLARE_COMPLETION(threads_gone);
-
-
 /*
  * The entries in this table correspond, line for line,
  * with the entries of us_unusual_dev_list[].
@@ -879,9 +872,6 @@ static void quiesce_and_remove_host(struct us_data *us)
 	usb_stor_stop_transport(us);
 	wake_up(&us->delay_wait);
 
-	/* It doesn't matter if the SCSI-scanning thread is still running.
-	 * The thread will exit when it sees the DISCONNECTING flag. */
-
 	/* queuecommand won't accept any new commands and the control
 	 * thread won't execute a previously-queued command.  If there
 	 * is such a command pending, complete it with an error. */
@@ -891,12 +881,16 @@ static void quiesce_and_remove_host(struct us_data *us)
 		scsi_lock(host);
 		us->srb->scsi_done(us->srb);
 		us->srb = NULL;
+		complete(&us->notify);		/* in case of an abort */
 		scsi_unlock(host);
 	}
 	mutex_unlock(&us->dev_mutex);
 
 	/* Now we own no commands so it's safe to remove the SCSI host */
 	scsi_remove_host(host);
+
+	/* Wait for the SCSI-scanning thread to stop */
+	wait_for_completion(&us->scanning_done);
 }
 
 /* Second stage of disconnect processing: deallocate all resources */
@@ -947,9 +941,8 @@ retry:
 		/* Should we unbind if no devices were detected? */
 	}
 
-	scsi_host_put(us_to_host(us));
 	usb_autopm_put_interface(us->pusb_intf);
-	complete_and_exit(&threads_gone, 0);
+	complete_and_exit(&us->scanning_done, 0);
 }
 
 
@@ -984,6 +977,7 @@ static int storage_probe(struct usb_interface *intf,
 	init_MUTEX_LOCKED(&(us->sema));
 	init_completion(&(us->notify));
 	init_waitqueue_head(&us->delay_wait);
+	init_completion(&us->scanning_done);
 
 	/* Associate the us_data structure with the USB device */
 	result = associate_dev(us, intf);
@@ -1033,11 +1027,6 @@ static int storage_probe(struct usb_interface *intf,
 		goto BadDevice;
 	}
 
-	/* Take a reference to the host for the scanning thread and
-	 * count it among all the threads we have launched.  Then
-	 * start it up. */
-	scsi_host_get(us_to_host(us));
-	atomic_inc(&total_threads);
 	usb_autopm_get_interface(intf); /* dropped in the scanning thread */
 	wake_up_process(th);
 
@@ -1104,16 +1093,6 @@ static void __exit usb_stor_exit(void)
 	US_DEBUGP("-- calling usb_deregister()\n");
 	usb_deregister(&usb_storage_driver) ;
 
-	/* Don't return until all of our control and scanning threads
-	 * have exited.  Since each thread signals threads_gone as its
-	 * last act, we have to call wait_for_completion the right number
-	 * of times.
-	 */
-	while (atomic_read(&total_threads) > 0) {
-		wait_for_completion(&threads_gone);
-		atomic_dec(&total_threads);
-	}
-
 	usb_usual_clear_present(USB_US_TYPE_STOR);
 }
 

+ 1 - 0
drivers/usb/storage/usb.h

@@ -150,6 +150,7 @@ struct us_data {
 	struct semaphore	sema;		 /* to sleep thread on	    */
 	struct completion	notify;		 /* thread begin/end	    */
 	wait_queue_head_t	delay_wait;	 /* wait during scan, reset */
+	struct completion	scanning_done;	 /* wait for scan thread    */
 
 	/* subdriver information */
 	void			*extra;		 /* Any extra data          */