Commit 9e1a3e31 authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents de80af4c d65cc1b4
...@@ -1772,6 +1772,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, ...@@ -1772,6 +1772,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
if (dev->alt_max_pkt_size == NULL) { if (dev->alt_max_pkt_size == NULL) {
em28xx_errdev("out of memory!\n"); em28xx_errdev("out of memory!\n");
em28xx_devused&=~(1<<nr); em28xx_devused&=~(1<<nr);
kfree(dev);
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -1196,12 +1196,19 @@ static int pwc_video_open(struct inode *inode, struct file *file) ...@@ -1196,12 +1196,19 @@ static int pwc_video_open(struct inode *inode, struct file *file)
return 0; 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 */ /* Note that all cleanup is done in the reverse order as in _open */
static int pwc_video_close(struct inode *inode, struct file *file) static int pwc_video_close(struct inode *inode, struct file *file)
{ {
struct video_device *vdev = file->private_data; struct video_device *vdev = file->private_data;
struct pwc_device *pdev; struct pwc_device *pdev;
int i; int i, hint;
PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); 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) ...@@ -1224,8 +1231,9 @@ static int pwc_video_close(struct inode *inode, struct file *file)
pwc_isoc_cleanup(pdev); pwc_isoc_cleanup(pdev);
pwc_free_buffers(pdev); pwc_free_buffers(pdev);
lock_kernel();
/* Turn off LEDS and power down camera, but only when not unplugged */ /* Turn off LEDS and power down camera, but only when not unplugged */
if (pdev->error_status != EPIPE) { if (!pdev->unplugged) {
/* Turn LEDs off */ /* Turn LEDs off */
if (pwc_set_leds(pdev, 0, 0) < 0) if (pwc_set_leds(pdev, 0, 0) < 0)
PWC_DEBUG_MODULE("Failed to set LED on/off time.\n"); 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) ...@@ -1234,9 +1242,19 @@ static int pwc_video_close(struct inode *inode, struct file *file)
if (i < 0) if (i < 0)
PWC_ERROR("Failed to power down camera (%d)\n", i); PWC_ERROR("Failed to power down camera (%d)\n", i);
} }
}
pdev->vopen--; pdev->vopen--;
PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", 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;
}
unlock_kernel();
return 0; return 0;
} }
...@@ -1791,13 +1809,12 @@ static void usb_pwc_disconnect(struct usb_interface *intf) ...@@ -1791,13 +1809,12 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
/* Alert waiting processes */ /* Alert waiting processes */
wake_up_interruptible(&pdev->frameq); wake_up_interruptible(&pdev->frameq);
/* Wait until device is closed */ /* Wait until device is closed */
while (pdev->vopen) if(pdev->vopen) {
schedule(); pdev->unplugged = 1;
/* Device is now closed, so we can safely unregister it */ } else {
/* Device is closed, so we can safely unregister it */
PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n");
pwc_remove_sysfs_files(pdev->vdev); pwc_cleanup(pdev);
video_unregister_device(pdev->vdev);
/* Free memory (don't set pdev to 0 just yet) */ /* Free memory (don't set pdev to 0 just yet) */
kfree(pdev); kfree(pdev);
...@@ -1806,6 +1823,7 @@ static void usb_pwc_disconnect(struct usb_interface *intf) ...@@ -1806,6 +1823,7 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
for (hint = 0; hint < MAX_DEV_HINTS; hint++) for (hint = 0; hint < MAX_DEV_HINTS; hint++)
if (device_hint[hint].pdev == pdev) if (device_hint[hint].pdev == pdev)
device_hint[hint].pdev = NULL; device_hint[hint].pdev = NULL;
}
unlock_kernel(); unlock_kernel();
} }
......
...@@ -193,6 +193,7 @@ struct pwc_device ...@@ -193,6 +193,7 @@ struct pwc_device
char vsnapshot; /* snapshot mode */ char vsnapshot; /* snapshot mode */
char vsync; /* used by isoc handler */ char vsync; /* used by isoc handler */
char vmirror; /* for ToUCaM series */ char vmirror; /* for ToUCaM series */
char unplugged;
int cmd_len; int cmd_len;
unsigned char cmd_buf[13]; unsigned char cmd_buf[13];
......
...@@ -21,6 +21,7 @@ config USB_ARCH_HAS_HCD ...@@ -21,6 +21,7 @@ config USB_ARCH_HAS_HCD
default y if USB_ARCH_HAS_EHCI default y if USB_ARCH_HAS_EHCI
default y if PCMCIA && !M32R # sl811_cs default y if PCMCIA && !M32R # sl811_cs
default y if ARM # SL-811 default y if ARM # SL-811
default y if SUPERH # r8a66597-hcd
default PCI default PCI
# many non-PCI SOC chips embed OHCI # many non-PCI SOC chips embed OHCI
......
...@@ -456,7 +456,6 @@ static int cxacru_start_wait_urb(struct urb *urb, struct completion *done, ...@@ -456,7 +456,6 @@ static int cxacru_start_wait_urb(struct urb *urb, struct completion *done,
int* actual_length) int* actual_length)
{ {
struct timer_list timer; struct timer_list timer;
int status = urb->status;
init_timer(&timer); init_timer(&timer);
timer.expires = jiffies + msecs_to_jiffies(CMD_TIMEOUT); timer.expires = jiffies + msecs_to_jiffies(CMD_TIMEOUT);
...@@ -468,7 +467,7 @@ static int cxacru_start_wait_urb(struct urb *urb, struct completion *done, ...@@ -468,7 +467,7 @@ static int cxacru_start_wait_urb(struct urb *urb, struct completion *done,
if (actual_length) if (actual_length)
*actual_length = urb->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, static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm,
......
...@@ -1721,9 +1721,12 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, ...@@ -1721,9 +1721,12 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
ret = uea_boot(sc); ret = uea_boot(sc);
if (ret < 0) if (ret < 0)
goto error; goto error_rm_grp;
return 0; return 0;
error_rm_grp:
sysfs_remove_group(&intf->dev.kobj, &attr_grp);
error: error:
kfree(sc); kfree(sc);
return ret; return ret;
......
...@@ -922,6 +922,10 @@ static int acm_probe (struct usb_interface *intf, ...@@ -922,6 +922,10 @@ static int acm_probe (struct usb_interface *intf,
} }
} }
/* Accept probe requests only for the control interface */
if (intf != control_interface)
return -ENODEV;
if (usb_interface_claimed(data_interface)) { /* valid in this context */ if (usb_interface_claimed(data_interface)) { /* valid in this context */
dev_dbg(&intf->dev,"The data interface isn't available"); dev_dbg(&intf->dev,"The data interface isn't available");
return -EBUSY; return -EBUSY;
...@@ -1109,10 +1113,12 @@ static void acm_disconnect(struct usb_interface *intf) ...@@ -1109,10 +1113,12 @@ static void acm_disconnect(struct usb_interface *intf)
return; return;
} }
if (acm->country_codes){ if (acm->country_codes){
device_remove_file(&intf->dev, &dev_attr_wCountryCodes); device_remove_file(&acm->control->dev,
device_remove_file(&intf->dev, &dev_attr_iCountryCodeRelDate); &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; acm->dev = NULL;
usb_set_intfdata(acm->control, NULL); usb_set_intfdata(acm->control, NULL);
usb_set_intfdata(acm->data, NULL); usb_set_intfdata(acm->data, NULL);
......
...@@ -1224,6 +1224,8 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt) ...@@ -1224,6 +1224,8 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
udev->auto_pm = 1; udev->auto_pm = 1;
udev->pm_usage_cnt += inc_usage_cnt; udev->pm_usage_cnt += inc_usage_cnt;
WARN_ON(udev->pm_usage_cnt < 0); 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 (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) {
if (udev->state == USB_STATE_SUSPENDED) if (udev->state == USB_STATE_SUSPENDED)
status = usb_resume_both(udev); status = usb_resume_both(udev);
...@@ -1232,8 +1234,6 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt) ...@@ -1232,8 +1234,6 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
else if (inc_usage_cnt) else if (inc_usage_cnt)
udev->last_busy = jiffies; udev->last_busy = jiffies;
} else if (inc_usage_cnt <= 0 && udev->pm_usage_cnt <= 0) { } 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); status = usb_suspend_both(udev, PMSG_SUSPEND);
} }
usb_pm_unlock(udev); usb_pm_unlock(udev);
...@@ -1342,16 +1342,15 @@ static int usb_autopm_do_interface(struct usb_interface *intf, ...@@ -1342,16 +1342,15 @@ static int usb_autopm_do_interface(struct usb_interface *intf,
else { else {
udev->auto_pm = 1; udev->auto_pm = 1;
intf->pm_usage_cnt += inc_usage_cnt; intf->pm_usage_cnt += inc_usage_cnt;
udev->last_busy = jiffies;
if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) { if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) {
if (udev->state == USB_STATE_SUSPENDED) if (udev->state == USB_STATE_SUSPENDED)
status = usb_resume_both(udev); status = usb_resume_both(udev);
if (status != 0) if (status != 0)
intf->pm_usage_cnt -= inc_usage_cnt; intf->pm_usage_cnt -= inc_usage_cnt;
else if (inc_usage_cnt) else
udev->last_busy = jiffies; udev->last_busy = jiffies;
} else if (inc_usage_cnt <= 0 && intf->pm_usage_cnt <= 0) { } 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); status = usb_suspend_both(udev, PMSG_SUSPEND);
} }
} }
......
...@@ -1644,9 +1644,10 @@ static int finish_port_resume(struct usb_device *udev) ...@@ -1644,9 +1644,10 @@ static int finish_port_resume(struct usb_device *udev)
* and device drivers will know about any resume quirks. * and device drivers will know about any resume quirks.
*/ */
if (status == 0) { if (status == 0) {
devstatus = 0;
status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus); status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
if (status >= 0) if (status >= 0)
status = (status == 2 ? 0 : -ENODEV); status = (status > 0 ? 0 : -ENODEV);
} }
if (status) { if (status) {
......
...@@ -637,12 +637,12 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char ...@@ -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 memset(buf,0,size); // Make sure we parse really received data
for (i = 0; i < 3; ++i) { 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), result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
(type << 8) + index, 0, buf, size, (type << 8) + index, 0, buf, size,
USB_CTRL_GET_TIMEOUT); USB_CTRL_GET_TIMEOUT);
if (result == 0 || result == -EPIPE) if (result <= 0 && result != -ETIMEDOUT)
continue; continue;
if (result > 1 && ((u8 *)buf)[1] != type) { if (result > 1 && ((u8 *)buf)[1] != type) {
result = -EPROTO; result = -EPROTO;
...@@ -1358,6 +1358,30 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp, ...@@ -1358,6 +1358,30 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp,
usb_dev = interface_to_usbdev(intf); usb_dev = interface_to_usbdev(intf);
alt = intf->cur_altsetting; 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, if (add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length, buffer, buffer_size, &length,
"INTERFACE=%d/%d/%d", "INTERFACE=%d/%d/%d",
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
static const struct usb_device_id usb_quirk_list[] = { static const struct usb_device_id usb_quirk_list[] = {
/* HP 5300/5370C scanner */ /* HP 5300/5370C scanner */
{ USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 }, { 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 */ /* Acer Peripherals Inc. (now BenQ Corp.) Prisa 640BU */
{ USB_DEVICE(0x04a5, 0x207e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, { USB_DEVICE(0x04a5, 0x207e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Benq S2W 3300U */ /* Benq S2W 3300U */
...@@ -56,6 +58,8 @@ static const struct usb_device_id usb_quirk_list[] = { ...@@ -56,6 +58,8 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x04b8, 0x0121), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, { USB_DEVICE(0x04b8, 0x0121), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Seiko Epson Corp.*/ /* Seiko Epson Corp.*/
{ USB_DEVICE(0x04b8, 0x0122), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, { 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 */ /* Samsung ML-2510 Series printer */
{ USB_DEVICE(0x04e8, 0x327e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, { USB_DEVICE(0x04e8, 0x327e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Elsa MicroLink 56k (V.250) */ /* Elsa MicroLink 56k (V.250) */
...@@ -64,12 +68,20 @@ static const struct usb_device_id usb_quirk_list[] = { ...@@ -64,12 +68,20 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x05d8, 0x4005), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, { USB_DEVICE(0x05d8, 0x4005), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Agfa Snapscan1212u */ /* Agfa Snapscan1212u */
{ USB_DEVICE(0x06bd, 0x2061), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, { 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 */ /* Umax [hex] Astra 3400U */
{ USB_DEVICE(0x1606, 0x0060), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, { USB_DEVICE(0x1606, 0x0060), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Philips PSC805 audio device */ /* Philips PSC805 audio device */
{ USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME }, { 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 */ /* RIM Blackberry */
{ USB_DEVICE(0x0fca, 0x0001), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, { USB_DEVICE(0x0fca, 0x0001), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
{ USB_DEVICE(0x0fca, 0x0004), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, { USB_DEVICE(0x0fca, 0x0004), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
......
...@@ -34,8 +34,6 @@ ...@@ -34,8 +34,6 @@
* bypassing some hardware (and driver) issues. UML could help too. * bypassing some hardware (and driver) issues. UML could help too.
*/ */
#define DEBUG
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/delay.h> #include <linux/delay.h>
......
...@@ -599,7 +599,6 @@ enum fsg_buffer_state { ...@@ -599,7 +599,6 @@ enum fsg_buffer_state {
struct fsg_buffhd { struct fsg_buffhd {
void *buf; void *buf;
dma_addr_t dma;
enum fsg_buffer_state state; enum fsg_buffer_state state;
struct fsg_buffhd *next; struct fsg_buffhd *next;
...@@ -1295,6 +1294,7 @@ static int class_setup_req(struct fsg_dev *fsg, ...@@ -1295,6 +1294,7 @@ static int class_setup_req(struct fsg_dev *fsg,
struct usb_request *req = fsg->ep0req; struct usb_request *req = fsg->ep0req;
int value = -EOPNOTSUPP; int value = -EOPNOTSUPP;
u16 w_index = le16_to_cpu(ctrl->wIndex); u16 w_index = le16_to_cpu(ctrl->wIndex);
u16 w_value = le16_to_cpu(ctrl->wValue);
u16 w_length = le16_to_cpu(ctrl->wLength); u16 w_length = le16_to_cpu(ctrl->wLength);
if (!fsg->config) if (!fsg->config)
...@@ -1308,7 +1308,7 @@ static int class_setup_req(struct fsg_dev *fsg, ...@@ -1308,7 +1308,7 @@ static int class_setup_req(struct fsg_dev *fsg,
if (ctrl->bRequestType != (USB_DIR_OUT | if (ctrl->bRequestType != (USB_DIR_OUT |
USB_TYPE_CLASS | USB_RECIP_INTERFACE)) USB_TYPE_CLASS | USB_RECIP_INTERFACE))
break; break;
if (w_index != 0) { if (w_index != 0 || w_value != 0) {
value = -EDOM; value = -EDOM;
break; break;
} }
...@@ -1324,7 +1324,7 @@ static int class_setup_req(struct fsg_dev *fsg, ...@@ -1324,7 +1324,7 @@ static int class_setup_req(struct fsg_dev *fsg,
if (ctrl->bRequestType != (USB_DIR_IN | if (ctrl->bRequestType != (USB_DIR_IN |
USB_TYPE_CLASS | USB_RECIP_INTERFACE)) USB_TYPE_CLASS | USB_RECIP_INTERFACE))
break; break;
if (w_index != 0) { if (w_index != 0 || w_value != 0) {
value = -EDOM; value = -EDOM;
break; break;
} }
...@@ -1343,7 +1343,7 @@ static int class_setup_req(struct fsg_dev *fsg, ...@@ -1343,7 +1343,7 @@ static int class_setup_req(struct fsg_dev *fsg,
if (ctrl->bRequestType != (USB_DIR_OUT | if (ctrl->bRequestType != (USB_DIR_OUT |
USB_TYPE_CLASS | USB_RECIP_INTERFACE)) USB_TYPE_CLASS | USB_RECIP_INTERFACE))
break; break;
if (w_index != 0) { if (w_index != 0 || w_value != 0) {
value = -EDOM; value = -EDOM;
break; break;
} }
...@@ -2611,7 +2611,6 @@ static int send_status(struct fsg_dev *fsg) ...@@ -2611,7 +2611,6 @@ static int send_status(struct fsg_dev *fsg)
fsg->intr_buffhd = bh; // Point to the right buffhd fsg->intr_buffhd = bh; // Point to the right buffhd
fsg->intreq->buf = bh->inreq->buf; fsg->intreq->buf = bh->inreq->buf;
fsg->intreq->dma = bh->inreq->dma;
fsg->intreq->context = bh; fsg->intreq->context = bh;
start_transfer(fsg, fsg->intr_in, fsg->intreq, start_transfer(fsg, fsg->intr_in, fsg->intreq,
&fsg->intreq_busy, &bh->state); &fsg->intreq_busy, &bh->state);
...@@ -3200,7 +3199,6 @@ static int do_set_interface(struct fsg_dev *fsg, int altsetting) ...@@ -3200,7 +3199,6 @@ static int do_set_interface(struct fsg_dev *fsg, int altsetting)
if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0) if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0)
goto reset; goto reset;
bh->inreq->buf = bh->outreq->buf = bh->buf; 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->context = bh->outreq->context = bh;
bh->inreq->complete = bulk_in_complete; bh->inreq->complete = bulk_in_complete;
bh->outreq->complete = bulk_out_complete; bh->outreq->complete = bulk_out_complete;
......
...@@ -1277,31 +1277,32 @@ static void setup_received_irq(struct fsl_udc *udc, ...@@ -1277,31 +1277,32 @@ static void setup_received_irq(struct fsl_udc *udc,
udc_reset_ep_queue(udc, 0); udc_reset_ep_queue(udc, 0);
/* We process some stardard setup requests here */
switch (setup->bRequest) { switch (setup->bRequest) {
/* Request that need Data+Status phase from udc */
case USB_REQ_GET_STATUS: 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)) != (USB_DIR_IN | USB_TYPE_STANDARD))
break; break;
ch9getstatus(udc, setup->bRequestType, wValue, wIndex, wLength); ch9getstatus(udc, setup->bRequestType, wValue, wIndex, wLength);
break; return;
/* Requests that need Status phase from udc */
case USB_REQ_SET_ADDRESS: case USB_REQ_SET_ADDRESS:
/* Status phase from udc */
if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD
| USB_RECIP_DEVICE)) | USB_RECIP_DEVICE))
break; break;
ch9setaddress(udc, wValue, wIndex, wLength); ch9setaddress(udc, wValue, wIndex, wLength);
break; return;
/* Handled by udc, no data, status by udc */
case USB_REQ_CLEAR_FEATURE: case USB_REQ_CLEAR_FEATURE:
case USB_REQ_SET_FEATURE: case USB_REQ_SET_FEATURE:
{ /* status transaction */ /* Status phase from udc */
{
int rc = -EOPNOTSUPP; int rc = -EOPNOTSUPP;
if ((setup->bRequestType & USB_RECIP_MASK) if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK))
== USB_RECIP_ENDPOINT) { == (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD)) {
int pipe = get_pipe_by_windex(wIndex); int pipe = get_pipe_by_windex(wIndex);
struct fsl_ep *ep; struct fsl_ep *ep;
...@@ -1315,8 +1316,9 @@ static void setup_received_irq(struct fsl_udc *udc, ...@@ -1315,8 +1316,9 @@ static void setup_received_irq(struct fsl_udc *udc,
? 1 : 0); ? 1 : 0);
spin_lock(&udc->lock); spin_lock(&udc->lock);
} else if ((setup->bRequestType & USB_RECIP_MASK) } else if ((setup->bRequestType & (USB_RECIP_MASK
== USB_RECIP_DEVICE) { | USB_TYPE_MASK)) == (USB_RECIP_DEVICE
| USB_TYPE_STANDARD)) {
/* Note: The driver has not include OTG support yet. /* Note: The driver has not include OTG support yet.
* This will be set when OTG support is added */ * This will be set when OTG support is added */
if (!udc->gadget.is_otg) if (!udc->gadget.is_otg)
...@@ -1329,15 +1331,21 @@ static void setup_received_irq(struct fsl_udc *udc, ...@@ -1329,15 +1331,21 @@ static void setup_received_irq(struct fsl_udc *udc,
USB_DEVICE_A_ALT_HNP_SUPPORT) USB_DEVICE_A_ALT_HNP_SUPPORT)
udc->gadget.a_alt_hnp_support = 1; udc->gadget.a_alt_hnp_support = 1;
rc = 0; rc = 0;
} } else
break;
if (rc == 0) { if (rc == 0) {
if (ep0_prime_status(udc, EP_DIR_IN)) if (ep0_prime_status(udc, EP_DIR_IN))
ep0stall(udc); ep0stall(udc);
} }
return;
}
default:
break; break;
} }
/* Requests handled by gadget */ /* Requests handled by gadget */
default:
if (wLength) { if (wLength) {
/* Data phase from gadget, status phase from udc */ /* Data phase from gadget, status phase from udc */
udc->ep0_dir = (setup->bRequestType & USB_DIR_IN) udc->ep0_dir = (setup->bRequestType & USB_DIR_IN)
...@@ -1349,7 +1357,6 @@ static void setup_received_irq(struct fsl_udc *udc, ...@@ -1349,7 +1357,6 @@ static void setup_received_irq(struct fsl_udc *udc,
spin_lock(&udc->lock); spin_lock(&udc->lock);
udc->ep0_state = (setup->bRequestType & USB_DIR_IN) udc->ep0_state = (setup->bRequestType & USB_DIR_IN)
? DATA_STATE_XMIT : DATA_STATE_RECV; ? DATA_STATE_XMIT : DATA_STATE_RECV;
} else { } else {
/* No data phase, IN status from gadget */ /* No data phase, IN status from gadget */
udc->ep0_dir = USB_DIR_IN; udc->ep0_dir = USB_DIR_IN;
...@@ -1360,8 +1367,6 @@ static void setup_received_irq(struct fsl_udc *udc, ...@@ -1360,8 +1367,6 @@ static void setup_received_irq(struct fsl_udc *udc,
spin_lock(&udc->lock); spin_lock(&udc->lock);
udc->ep0_state = WAIT_FOR_OUT_STATUS; udc->ep0_state = WAIT_FOR_OUT_STATUS;
} }
break;
}
} }
/* Process request for Data or Status phase of ep0 /* Process request for Data or Status phase of ep0
......
...@@ -967,7 +967,7 @@ static int pxa2xx_udc_pullup(struct usb_gadget *_gadget, int is_active) ...@@ -967,7 +967,7 @@ static int pxa2xx_udc_pullup(struct usb_gadget *_gadget, int is_active)
udc = container_of(_gadget, struct pxa2xx_udc, gadget); udc = container_of(_gadget, struct pxa2xx_udc, gadget);
/* not all boards support pullup control */ /* not all boards support pullup control */
if (!udc->mach->udc_command) if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
return -EOPNOTSUPP; return -EOPNOTSUPP;
is_active = (is_active != 0); is_active = (is_active != 0);
...@@ -2309,7 +2309,7 @@ static int pxa2xx_udc_suspend(struct platform_device *dev, pm_message_t state) ...@@ -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); 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"); WARN("USB host won't detect disconnect!\n");
pullup(udc, 0); pullup(udc, 0);
......
...@@ -237,7 +237,7 @@ config USB_SL811_CS ...@@ -237,7 +237,7 @@ config USB_SL811_CS
module will be called "sl811_cs". module will be called "sl811_cs".
config USB_R8A66597_HCD config USB_R8A66597_HCD
tristate "R8A66597 HCD suppoort" tristate "R8A66597 HCD support"
depends on USB depends on USB
help help
The R8A66597 is a USB 2.0 host and peripheral controller. The R8A66597 is a USB 2.0 host and peripheral controller.
......
/* /*
* EHCI HCD (Host Controller Driver) for USB. * EHCI HCD (Host Controller Driver) for USB.
* *
* (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net>
*
* Bus Glue for AMD Alchemy Au1xxx * Bus Glue for AMD Alchemy Au1xxx
* *
* Based on "ohci-au1xxx.c" by Matt Porter <mporter@kernel.crashing.org> * 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 = { ...@@ -196,6 +194,9 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
/* /*
* basic lifecycle operations * basic lifecycle operations
*
* FIXME -- ehci_init() doesn't do enough here.
* See ehci-ppc-soc for a complete implementation.
*/ */
.reset = ehci_init, .reset = ehci_init,
.start = ehci_run, .start = ehci_run,
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Bus Glue for PPC On-Chip EHCI driver * Bus Glue for PPC On-Chip EHCI driver
* Tested on AMCC 440EPx * 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. * This file is licenced under the GPL.
*/ */
...@@ -15,6 +15,24 @@ ...@@ -15,6 +15,24 @@
extern int usb_disabled(void); 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 * usb_ehci_ppc_soc_probe - initialize PPC-SoC-based HCDs
* Context: !in_interrupt() * Context: !in_interrupt()
...@@ -120,7 +138,7 @@ static const struct hc_driver ehci_ppc_soc_hc_driver = { ...@@ -120,7 +138,7 @@ static const struct hc_driver ehci_ppc_soc_hc_driver = {
/* /*
* basic lifecycle operations * basic lifecycle operations
*/ */
.reset = ehci_init, .reset = ehci_ppc_soc_setup,
.start = ehci_run, .start = ehci_run,
.stop = ehci_stop, .stop = ehci_stop,
.shutdown = ehci_shutdown, .shutdown = ehci_shutdown,
......
...@@ -74,7 +74,7 @@ urb_print (struct urb * urb, char * str, int small) ...@@ -74,7 +74,7 @@ urb_print (struct urb * urb, char * str, int small)
#define ohci_dbg_sw(ohci, next, size, format, arg...) \ #define ohci_dbg_sw(ohci, next, size, format, arg...) \
do { \ do { \
if (next) { \ if (next != NULL) { \
unsigned s_len; \ unsigned s_len; \
s_len = scnprintf (*next, *size, format, ## arg ); \ s_len = scnprintf (*next, *size, format, ## arg ); \
*size -= s_len; *next += s_len; \ *size -= s_len; *next += s_len; \
......
...@@ -2208,8 +2208,6 @@ static int __init r8a66597_probe(struct platform_device *pdev) ...@@ -2208,8 +2208,6 @@ static int __init r8a66597_probe(struct platform_device *pdev)
clean_up: clean_up:
if (reg) if (reg)
iounmap(reg); iounmap(reg);
if (res)
release_mem_region(res->start, 1);
return ret; return ret;
} }
......
...@@ -1520,12 +1520,15 @@ static void u132_hcd_endp_work_scheduler(struct work_struct *work) ...@@ -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) static void port_power(struct u132 *u132, int pn, int is_on)
{ {
u132->port[pn].power = is_on; u132->port[pn].power = is_on;
} }
#endif
static void u132_power(struct u132 *u132, int is_on) static void u132_power(struct u132 *u132, int is_on)
{ {
struct usb_hcd *hcd = u132_to_hcd(u132) struct usb_hcd *hcd = u132_to_hcd(u132)
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
static struct usb_device_id id_table [] = { static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */ { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
{ USB_DEVICE(0x413c, 0x8115) }, /* Dell Wireless HSDPA 5500 */
{ }, { },
}; };
MODULE_DEVICE_TABLE(usb, id_table); MODULE_DEVICE_TABLE(usb, id_table);
......
...@@ -383,6 +383,10 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios ...@@ -383,6 +383,10 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
} }
baud = tty_get_baud_rate(port->tty); 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); urb_value = BELKIN_SA_BAUD(baud);
/* Clip to maximum speed */ /* Clip to maximum speed */
if (urb_value == 0) if (urb_value == 0)
......
...@@ -538,6 +538,8 @@ static struct usb_device_id id_table_combined [] = { ...@@ -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_VCP_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_D2XX_PID) }, { USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_D2XX_PID) },
{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_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_ARTEMIS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },
......
...@@ -430,6 +430,9 @@ ...@@ -430,6 +430,9 @@
*/ */
#define EVOLUTION_VID 0xDEEE /* Vendor ID */ #define EVOLUTION_VID 0xDEEE /* Vendor ID */
#define EVOLUTION_ER1_PID 0x0300 /* ER1 Control Module */ #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 */ /* Pyramid Computer GmbH */
#define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */ #define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */
......
/* /*
* Garmin GPS driver * 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 * The latest version of the driver can be found at
* http://sourceforge.net/projects/garmin-gps/ * http://sourceforge.net/projects/garmin-gps/
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/atomic.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/usb/serial.h> #include <linux/usb/serial.h>
...@@ -52,7 +53,7 @@ static int debug = 0; ...@@ -52,7 +53,7 @@ static int debug = 0;
*/ */
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 28 #define VERSION_MINOR 31
#define _STR(s) #s #define _STR(s) #s
#define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b) #define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b)
...@@ -141,6 +142,8 @@ struct garmin_data { ...@@ -141,6 +142,8 @@ struct garmin_data {
__u8 inbuffer [GPS_IN_BUFSIZ]; /* tty -> usb */ __u8 inbuffer [GPS_IN_BUFSIZ]; /* tty -> usb */
__u8 outbuffer[GPS_OUT_BUFSIZ]; /* usb -> tty */ __u8 outbuffer[GPS_OUT_BUFSIZ]; /* usb -> tty */
__u8 privpkt[4*6]; __u8 privpkt[4*6];
atomic_t req_count;
atomic_t resp_count;
spinlock_t lock; spinlock_t lock;
struct list_head pktlist; struct list_head pktlist;
}; };
...@@ -171,8 +174,6 @@ struct garmin_data { ...@@ -171,8 +174,6 @@ struct garmin_data {
#define CLEAR_HALT_REQUIRED 0x0001 #define CLEAR_HALT_REQUIRED 0x0001
#define FLAGS_QUEUING 0x0100 #define FLAGS_QUEUING 0x0100
#define FLAGS_APP_RESP_SEEN 0x0200
#define FLAGS_APP_REQ_SEEN 0x0400
#define FLAGS_DROP_DATA 0x0800 #define FLAGS_DROP_DATA 0x0800
#define FLAGS_GSP_SKIP 0x1000 #define FLAGS_GSP_SKIP 0x1000
...@@ -186,7 +187,8 @@ struct garmin_data { ...@@ -186,7 +187,8 @@ struct garmin_data {
/* function prototypes */ /* function prototypes */
static void gsp_next_packet(struct garmin_data * garmin_data_p); static void gsp_next_packet(struct garmin_data * garmin_data_p);
static int garmin_write_bulk(struct usb_serial_port *port, 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 */ /* some special packets to be send or received */
static unsigned char const GARMIN_START_SESSION_REQ[] static unsigned char const GARMIN_START_SESSION_REQ[]
...@@ -233,9 +235,7 @@ static struct usb_driver garmin_driver = { ...@@ -233,9 +235,7 @@ static struct usb_driver garmin_driver = {
static inline int noResponseFromAppLayer(struct garmin_data * garmin_data_p) static inline int noResponseFromAppLayer(struct garmin_data * garmin_data_p)
{ {
return ((garmin_data_p->flags return atomic_read(&garmin_data_p->req_count) == atomic_read(&garmin_data_p->resp_count);
& (FLAGS_APP_REQ_SEEN|FLAGS_APP_RESP_SEEN))
== FLAGS_APP_REQ_SEEN);
} }
...@@ -463,7 +463,7 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count) ...@@ -463,7 +463,7 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
usbdata[2] = __cpu_to_le32(size); usbdata[2] = __cpu_to_le32(size);
garmin_write_bulk (garmin_data_p->port, garmin_data_p->inbuffer, 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 /* if this was an abort-transfer command, flush all
queued data. */ queued data. */
...@@ -818,7 +818,7 @@ static int nat_receive(struct garmin_data * garmin_data_p, ...@@ -818,7 +818,7 @@ static int nat_receive(struct garmin_data * garmin_data_p,
if (garmin_data_p->insize >= len) { if (garmin_data_p->insize >= len) {
garmin_write_bulk (garmin_data_p->port, garmin_write_bulk (garmin_data_p->port,
garmin_data_p->inbuffer, garmin_data_p->inbuffer,
len); len, 0);
garmin_data_p->insize = 0; garmin_data_p->insize = 0;
/* if this was an abort-transfer command, /* if this was an abort-transfer command,
...@@ -893,10 +893,11 @@ static int garmin_clear(struct garmin_data * garmin_data_p) ...@@ -893,10 +893,11 @@ static int garmin_clear(struct garmin_data * garmin_data_p)
struct usb_serial_port *port = garmin_data_p->port; 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 */ /* send a terminate command */
status = garmin_write_bulk(port, GARMIN_STOP_TRANSFER_REQ, status = garmin_write_bulk(port, GARMIN_STOP_TRANSFER_REQ,
sizeof(GARMIN_STOP_TRANSFER_REQ)); sizeof(GARMIN_STOP_TRANSFER_REQ),
1);
} }
/* flush all queued data */ /* flush all queued data */
...@@ -939,7 +940,8 @@ static int garmin_init_session(struct usb_serial_port *port) ...@@ -939,7 +940,8 @@ static int garmin_init_session(struct usb_serial_port *port)
dbg("%s - starting session ...", __FUNCTION__); dbg("%s - starting session ...", __FUNCTION__);
garmin_data_p->state = STATE_ACTIVE; garmin_data_p->state = STATE_ACTIVE;
status = garmin_write_bulk(port, GARMIN_START_SESSION_REQ, status = garmin_write_bulk(port, GARMIN_START_SESSION_REQ,
sizeof(GARMIN_START_SESSION_REQ)); sizeof(GARMIN_START_SESSION_REQ),
0);
if (status >= 0) { if (status >= 0) {
...@@ -950,7 +952,8 @@ static int garmin_init_session(struct usb_serial_port *port) ...@@ -950,7 +952,8 @@ static int garmin_init_session(struct usb_serial_port *port)
/* not needed, but the win32 driver does it too ... */ /* not needed, but the win32 driver does it too ... */
status = garmin_write_bulk(port, status = garmin_write_bulk(port,
GARMIN_START_SESSION_REQ2, GARMIN_START_SESSION_REQ2,
sizeof(GARMIN_START_SESSION_REQ2)); sizeof(GARMIN_START_SESSION_REQ2),
0);
if (status >= 0) { if (status >= 0) {
status = 0; status = 0;
spin_lock_irqsave(&garmin_data_p->lock, flags); spin_lock_irqsave(&garmin_data_p->lock, flags);
...@@ -987,6 +990,8 @@ static int garmin_open (struct usb_serial_port *port, struct file *filp) ...@@ -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->mode = initial_mode;
garmin_data_p->count = 0; garmin_data_p->count = 0;
garmin_data_p->flags = 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); spin_unlock_irqrestore(&garmin_data_p->lock, flags);
/* shutdown any bulk reads that might be going on */ /* shutdown any bulk reads that might be going on */
...@@ -1035,28 +1040,39 @@ static void garmin_write_bulk_callback (struct urb *urb) ...@@ -1035,28 +1040,39 @@ static void garmin_write_bulk_callback (struct urb *urb)
{ {
unsigned long flags; unsigned long flags;
struct usb_serial_port *port = (struct usb_serial_port *)urb->context; 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; int status = urb->status;
/* free up the transfer buffer, as usb_free_urb() does not do this */ if (port) {
kfree (urb->transfer_buffer); 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 (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) { if (status) {
dbg("%s - nonzero write bulk status received: %d", dbg("%s - nonzero write bulk status received: %d",
__FUNCTION__, status); __FUNCTION__, urb->status);
spin_lock_irqsave(&garmin_data_p->lock, flags); spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->flags |= CLEAR_HALT_REQUIRED; garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
spin_unlock_irqrestore(&garmin_data_p->lock, flags); 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, 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; unsigned long flags;
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
...@@ -1093,13 +1109,12 @@ static int garmin_write_bulk (struct usb_serial_port *port, ...@@ -1093,13 +1109,12 @@ static int garmin_write_bulk (struct usb_serial_port *port,
usb_sndbulkpipe (serial->dev, usb_sndbulkpipe (serial->dev,
port->bulk_out_endpointAddress), port->bulk_out_endpointAddress),
buffer, count, buffer, count,
garmin_write_bulk_callback, port); garmin_write_bulk_callback,
dismiss_ack ? NULL : port);
urb->transfer_flags |= URB_ZERO_PACKET; urb->transfer_flags |= URB_ZERO_PACKET;
if (GARMIN_LAYERID_APPL == getLayerId(buffer)) { if (GARMIN_LAYERID_APPL == getLayerId(buffer)) {
spin_lock_irqsave(&garmin_data_p->lock, flags); atomic_inc(&garmin_data_p->req_count);
garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { if (garmin_data_p->mode == MODE_GARMIN_SERIAL) {
pkt_clear(garmin_data_p); pkt_clear(garmin_data_p);
garmin_data_p->state = STATE_GSP_WAIT_DATA; garmin_data_p->state = STATE_GSP_WAIT_DATA;
...@@ -1114,13 +1129,6 @@ static int garmin_write_bulk (struct usb_serial_port *port, ...@@ -1114,13 +1129,6 @@ static int garmin_write_bulk (struct usb_serial_port *port,
"failed with status = %d\n", "failed with status = %d\n",
__FUNCTION__, status); __FUNCTION__, status);
count = 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 /* 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, ...@@ -1135,7 +1143,6 @@ static int garmin_write_bulk (struct usb_serial_port *port,
static int garmin_write (struct usb_serial_port *port, static int garmin_write (struct usb_serial_port *port,
const unsigned char *buf, int count) const unsigned char *buf, int count)
{ {
unsigned long flags;
int pktid, pktsiz, len; int pktid, pktsiz, len;
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
__le32 *privpkt = (__le32 *)garmin_data_p->privpkt; __le32 *privpkt = (__le32 *)garmin_data_p->privpkt;
...@@ -1186,9 +1193,7 @@ static int garmin_write (struct usb_serial_port *port, ...@@ -1186,9 +1193,7 @@ static int garmin_write (struct usb_serial_port *port,
break; break;
case PRIV_PKTID_RESET_REQ: case PRIV_PKTID_RESET_REQ:
spin_lock_irqsave(&garmin_data_p->lock, flags); atomic_inc(&garmin_data_p->req_count);
garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
break; break;
case PRIV_PKTID_SET_DEF_MODE: case PRIV_PKTID_SET_DEF_MODE:
...@@ -1241,8 +1246,6 @@ static int garmin_chars_in_buffer (struct usb_serial_port *port) ...@@ -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, static void garmin_read_process(struct garmin_data * garmin_data_p,
unsigned char *data, unsigned data_length) unsigned char *data, unsigned data_length)
{ {
unsigned long flags;
if (garmin_data_p->flags & FLAGS_DROP_DATA) { if (garmin_data_p->flags & FLAGS_DROP_DATA) {
/* abort-transfer cmd is actice */ /* abort-transfer cmd is actice */
dbg("%s - pkt dropped", __FUNCTION__); dbg("%s - pkt dropped", __FUNCTION__);
...@@ -1254,9 +1257,7 @@ static void garmin_read_process(struct garmin_data * garmin_data_p, ...@@ -1254,9 +1257,7 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
the device */ the device */
if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY, if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY,
sizeof(GARMIN_APP_LAYER_REPLY))) { sizeof(GARMIN_APP_LAYER_REPLY))) {
spin_lock_irqsave(&garmin_data_p->lock, flags); atomic_inc(&garmin_data_p->resp_count);
garmin_data_p->flags |= FLAGS_APP_RESP_SEEN;
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
} }
/* if throttling is active or postprecessing is required /* if throttling is active or postprecessing is required
......
...@@ -545,6 +545,7 @@ static struct usb_device_id ipaq_id_table [] = { ...@@ -545,6 +545,7 @@ static struct usb_device_id ipaq_id_table [] = {
{ USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */ { USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */
{ USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */ { USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */
{ USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */ { USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */
{ USB_DEVICE(0x0BB4, 0x00CF) }, /* HTC smartphone modems */
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
......
...@@ -110,6 +110,7 @@ static int option_send_setup(struct usb_serial_port *port); ...@@ -110,6 +110,7 @@ static int option_send_setup(struct usb_serial_port *port);
#define HUAWEI_PRODUCT_E220 0x1003 #define HUAWEI_PRODUCT_E220 0x1003
#define NOVATELWIRELESS_VENDOR_ID 0x1410 #define NOVATELWIRELESS_VENDOR_ID 0x1410
#define DELL_VENDOR_ID 0x413C
#define ANYDATA_VENDOR_ID 0x16d5 #define ANYDATA_VENDOR_ID 0x16d5
#define ANYDATA_PRODUCT_ADU_E100A 0x6501 #define ANYDATA_PRODUCT_ADU_E100A 0x6501
...@@ -119,8 +120,6 @@ static int option_send_setup(struct usb_serial_port *port); ...@@ -119,8 +120,6 @@ static int option_send_setup(struct usb_serial_port *port);
#define BANDRICH_PRODUCT_C100_1 0x1002 #define BANDRICH_PRODUCT_C100_1 0x1002
#define BANDRICH_PRODUCT_C100_2 0x1003 #define BANDRICH_PRODUCT_C100_2 0x1003
#define DELL_VENDOR_ID 0x413C
static struct usb_device_id option_ids[] = { static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
...@@ -171,11 +170,16 @@ static struct usb_device_id option_ids[] = { ...@@ -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, 0x2110) }, /* Novatel Merlin ES620 / Merlin ES720 / Ovation U720 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2130) }, /* Novatel Merlin ES620 SM Bus */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2130) }, /* Novatel Merlin ES620 SM Bus */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2410) }, /* Novatel EU740 */ { 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_E100A) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, { 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_1) },
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) }, { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
{ USB_DEVICE(DELL_VENDOR_ID, 0x8118) }, /* Dell Wireless 5510 Mobile Broadband HSDPA ExpressCard */
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
MODULE_DEVICE_TABLE(usb, option_ids); MODULE_DEVICE_TABLE(usb, option_ids);
......
...@@ -818,19 +818,17 @@ static int oti6858_ioctl(struct usb_serial_port *port, struct file *file, ...@@ -818,19 +818,17 @@ static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
switch (cmd) { switch (cmd) {
case TCGETS: case TCGETS:
if (copy_to_user(user_arg, port->tty->termios, if (kernel_termios_to_user_termios((struct ktermios __user *)arg,
sizeof(struct ktermios))) { port->tty->termios))
return -EFAULT; return -EFAULT;
}
return 0; return 0;
case TCSETS: case TCSETS:
case TCSETSW: /* FIXME: this is not the same! */ case TCSETSW: /* FIXME: this is not the same! */
case TCSETSF: /* FIXME: this is not the same! */ case TCSETSF: /* FIXME: this is not the same! */
if (copy_from_user(port->tty->termios, user_arg, if (user_termios_to_kernel_termios(port->tty->termios,
sizeof(struct ktermios))) { (struct ktermios __user *)arg))
return -EFAULT; return -EFAULT;
}
oti6858_set_termios(port, NULL); oti6858_set_termios(port, NULL);
return 0; return 0;
......
...@@ -74,13 +74,13 @@ ...@@ -74,13 +74,13 @@
#include <linux/usb/serial.h> #include <linux/usb/serial.h>
#ifndef CONFIG_USB_SAFE_PADDED #ifndef CONFIG_USB_SERIAL_SAFE_PADDED
#define CONFIG_USB_SAFE_PADDED 0 #define CONFIG_USB_SERIAL_SAFE_PADDED 0
#endif #endif
static int debug; static int debug;
static int safe = 1; 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_VERSION "v0.0b"
#define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com" #define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com"
......
...@@ -104,6 +104,8 @@ static struct usb_device_id id_table [] = { ...@@ -104,6 +104,8 @@ static struct usb_device_id id_table [] = {
.driver_info = (kernel_ulong_t)&palm_os_4_probe }, .driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID), { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe }, .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), { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe }, .driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID), { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID),
......
...@@ -48,6 +48,9 @@ ...@@ -48,6 +48,9 @@
#define SONY_CLIE_UX50_ID 0x0144 #define SONY_CLIE_UX50_ID 0x0144
#define SONY_CLIE_TJ25_ID 0x0169 #define SONY_CLIE_TJ25_ID 0x0169
#define ACER_VENDOR_ID 0x0502
#define ACER_S10_ID 0x0001
#define SAMSUNG_VENDOR_ID 0x04E8 #define SAMSUNG_VENDOR_ID 0x04E8
#define SAMSUNG_SCH_I330_ID 0x8001 #define SAMSUNG_SCH_I330_ID 0x8001
#define SAMSUNG_SPH_I500_ID 0x6601 #define SAMSUNG_SPH_I500_ID 0x6601
......
...@@ -342,7 +342,7 @@ UNUSUAL_DEV( 0x04b0, 0x040d, 0x0100, 0x0100, ...@@ -342,7 +342,7 @@ UNUSUAL_DEV( 0x04b0, 0x040d, 0x0100, 0x0100,
US_FL_FIX_CAPACITY), US_FL_FIX_CAPACITY),
/* Reported by Emil Larsson <emil@swip.net> */ /* Reported by Emil Larsson <emil@swip.net> */
UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0100, UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0101,
"NIKON", "NIKON",
"NIKON DSC D80", "NIKON DSC D80",
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
......
...@@ -112,13 +112,6 @@ module_param(delay_use, uint, S_IRUGO | S_IWUSR); ...@@ -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"); 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, * The entries in this table correspond, line for line,
* with the entries of us_unusual_dev_list[]. * with the entries of us_unusual_dev_list[].
...@@ -879,9 +872,6 @@ static void quiesce_and_remove_host(struct us_data *us) ...@@ -879,9 +872,6 @@ static void quiesce_and_remove_host(struct us_data *us)
usb_stor_stop_transport(us); usb_stor_stop_transport(us);
wake_up(&us->delay_wait); 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 /* queuecommand won't accept any new commands and the control
* thread won't execute a previously-queued command. If there * thread won't execute a previously-queued command. If there
* is such a command pending, complete it with an error. */ * is such a command pending, complete it with an error. */
...@@ -891,12 +881,16 @@ static void quiesce_and_remove_host(struct us_data *us) ...@@ -891,12 +881,16 @@ static void quiesce_and_remove_host(struct us_data *us)
scsi_lock(host); scsi_lock(host);
us->srb->scsi_done(us->srb); us->srb->scsi_done(us->srb);
us->srb = NULL; us->srb = NULL;
complete(&us->notify); /* in case of an abort */
scsi_unlock(host); scsi_unlock(host);
} }
mutex_unlock(&us->dev_mutex); mutex_unlock(&us->dev_mutex);
/* Now we own no commands so it's safe to remove the SCSI host */ /* Now we own no commands so it's safe to remove the SCSI host */
scsi_remove_host(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 */ /* Second stage of disconnect processing: deallocate all resources */
...@@ -947,9 +941,8 @@ static int usb_stor_scan_thread(void * __us) ...@@ -947,9 +941,8 @@ static int usb_stor_scan_thread(void * __us)
/* Should we unbind if no devices were detected? */ /* Should we unbind if no devices were detected? */
} }
scsi_host_put(us_to_host(us));
usb_autopm_put_interface(us->pusb_intf); 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, ...@@ -984,6 +977,7 @@ static int storage_probe(struct usb_interface *intf,
init_MUTEX_LOCKED(&(us->sema)); init_MUTEX_LOCKED(&(us->sema));
init_completion(&(us->notify)); init_completion(&(us->notify));
init_waitqueue_head(&us->delay_wait); init_waitqueue_head(&us->delay_wait);
init_completion(&us->scanning_done);
/* Associate the us_data structure with the USB device */ /* Associate the us_data structure with the USB device */
result = associate_dev(us, intf); result = associate_dev(us, intf);
...@@ -1033,11 +1027,6 @@ static int storage_probe(struct usb_interface *intf, ...@@ -1033,11 +1027,6 @@ static int storage_probe(struct usb_interface *intf,
goto BadDevice; 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 */ usb_autopm_get_interface(intf); /* dropped in the scanning thread */
wake_up_process(th); wake_up_process(th);
...@@ -1104,16 +1093,6 @@ static void __exit usb_stor_exit(void) ...@@ -1104,16 +1093,6 @@ static void __exit usb_stor_exit(void)
US_DEBUGP("-- calling usb_deregister()\n"); US_DEBUGP("-- calling usb_deregister()\n");
usb_deregister(&usb_storage_driver) ; 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); usb_usual_clear_present(USB_US_TYPE_STOR);
} }
......
...@@ -150,6 +150,7 @@ struct us_data { ...@@ -150,6 +150,7 @@ struct us_data {
struct semaphore sema; /* to sleep thread on */ struct semaphore sema; /* to sleep thread on */
struct completion notify; /* thread begin/end */ struct completion notify; /* thread begin/end */
wait_queue_head_t delay_wait; /* wait during scan, reset */ wait_queue_head_t delay_wait; /* wait during scan, reset */
struct completion scanning_done; /* wait for scan thread */
/* subdriver information */ /* subdriver information */
void *extra; /* Any extra data */ void *extra; /* Any extra data */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment