diff options
| author | Greg Kroah-Hartman <gregkh@suse.de> | 2008-04-30 11:42:38 -0700 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-04-30 11:42:38 -0700 |
| commit | eace7ec517d06ce69c55b1c8244bd8566471fe6e (patch) | |
| tree | 22d9189c706ffe286c3989a13bc8fd78a65d225c /usb | |
| parent | 75e56de690c85a25dded4577f2e0a8363f582588 (diff) | |
| download | patches-eace7ec517d06ce69c55b1c8244bd8566471fe6e.tar.gz | |
more patches added
Diffstat (limited to 'usb')
13 files changed, 1902 insertions, 2 deletions
diff --git a/usb/ti_usb-kick-firmware-into-user-space.patch b/usb/ti_usb-kick-firmware-into-user-space.patch new file mode 100644 index 00000000000000..f18f5705ae9792 --- /dev/null +++ b/usb/ti_usb-kick-firmware-into-user-space.patch @@ -0,0 +1,227 @@ +From alan@lxorguk.ukuu.org.uk Wed Apr 30 11:30:07 2008 +From: Alan Cox <alan@lxorguk.ukuu.org.uk> +Date: Tue, 29 Apr 2008 14:38:22 +0100 +Subject: ti_usb: kick firmware into user space +To: greg@kroah.com, linux-usb@vger.kernel.org +Message-ID: <20080429143822.19af46a5@core> + + +The patch leaves a compile it in option as distributions need time to +update to this, and hopefully to doing the same over time with more +serial drivers. Firmware belongs on disk (cheap) not in kernel non paged +memory. + +Signed-off-by: Alan Cox <alan@redhat.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/Kconfig | 8 ++ + drivers/usb/serial/ti_fw_3410.h | 4 + + drivers/usb/serial/ti_fw_5052.h | 5 + + drivers/usb/serial/ti_usb_3410_5052.c | 108 ++++++++++++++++++++++------------ + 4 files changed, 88 insertions(+), 37 deletions(-) + +--- a/drivers/usb/serial/Kconfig ++++ b/drivers/usb/serial/Kconfig +@@ -514,6 +514,14 @@ config USB_SERIAL_TI + To compile this driver as a module, choose M here: the + module will be called ti_usb_3410_5052. + ++config USB_SERIAL_TI_FIRMWARE ++ bool "USB TI 3410/5052 Firmware" ++ depends on USB_SERIAL_TI ++ help ++ say Y to include the firmware into the kernel for compatibility ++ with older setups. Say N if you have the firmware files installed ++ in /etc/firmware. ++ + config USB_SERIAL_CYBERJACK + tristate "USB REINER SCT cyberJack pinpad/e-com chipcard reader" + ---help--- +--- a/drivers/usb/serial/ti_fw_3410.h ++++ b/drivers/usb/serial/ti_fw_3410.h +@@ -882,4 +882,8 @@ static unsigned char ti_fw_3410[] = { + 0x00,0x00, + }; + ++static struct firmware fw_3410 = { ++ sizeof(ti_fw_3410), ++ ti_fw_3410 ++}; + #endif /* ifndef _TI_FW_3410_H_ */ +--- a/drivers/usb/serial/ti_fw_5052.h ++++ b/drivers/usb/serial/ti_fw_5052.h +@@ -882,4 +882,9 @@ static unsigned char ti_fw_5052[] = { + 0x00, + }; + ++static struct firmware fw_5052 = { ++ sizeof(ti_fw_5052), ++ ti_fw_5052 ++}; ++ + #endif /* ifndef _TI_FW_5052_H_ */ +--- a/drivers/usb/serial/ti_usb_3410_5052.c ++++ b/drivers/usb/serial/ti_usb_3410_5052.c +@@ -70,6 +70,7 @@ + + #include <linux/kernel.h> + #include <linux/errno.h> ++#include <linux/firmware.h> + #include <linux/init.h> + #include <linux/slab.h> + #include <linux/tty.h> +@@ -86,9 +87,14 @@ + #include <linux/usb/serial.h> + + #include "ti_usb_3410_5052.h" ++ ++#ifdef CONFIG_USB_SERIAL_TI_FIRMWARE ++/* Keep compatibility option for a while so we don't break systems ++ as we kick the firmware out into user space. In time this will ++ go away */ + #include "ti_fw_3410.h" /* firmware image for 3410 */ + #include "ti_fw_5052.h" /* firmware image for 5052 */ +- ++#endif + + /* Defines */ + +@@ -194,8 +200,7 @@ static int ti_command_in_sync(struct ti_ + static int ti_write_byte(struct ti_device *tdev, unsigned long addr, + __u8 mask, __u8 byte); + +-static int ti_download_firmware(struct ti_device *tdev, +- unsigned char *firmware, unsigned int firmware_size); ++static int ti_download_firmware(struct ti_device *tdev, int type); + + /* circular buffer */ + static struct circ_buf *ti_buf_alloc(void); +@@ -429,13 +434,10 @@ static int ti_startup(struct usb_serial + + /* if we have only 1 configuration, download firmware */ + if (dev->descriptor.bNumConfigurations == 1) { +- + if (tdev->td_is_3410) +- status = ti_download_firmware(tdev, ti_fw_3410, +- sizeof(ti_fw_3410)); ++ status = ti_download_firmware(tdev, 3410); + else +- status = ti_download_firmware(tdev, ti_fw_5052, +- sizeof(ti_fw_5052)); ++ status = ti_download_firmware(tdev, 5052); + if (status) + goto free_tdev; + +@@ -1656,50 +1658,82 @@ static int ti_write_byte(struct ti_devic + return status; + } + +- +-static int ti_download_firmware(struct ti_device *tdev, +- unsigned char *firmware, unsigned int firmware_size) ++static int ti_do_download(struct usb_device *dev, int pipe, ++ u8 *buffer, int size) + { +- int status = 0; +- int buffer_size; + int pos; +- int len; ++ u8 cs = 0; + int done; +- __u8 cs = 0; +- __u8 *buffer; +- struct usb_device *dev = tdev->td_serial->dev; + struct ti_firmware_header *header; +- unsigned int pipe = usb_sndbulkpipe(dev, +- tdev->td_serial->port[0]->bulk_out_endpointAddress); +- +- +- buffer_size = TI_FIRMWARE_BUF_SIZE + sizeof(struct ti_firmware_header); +- buffer = kmalloc(buffer_size, GFP_KERNEL); +- if (!buffer) { +- dev_err(&dev->dev, "%s - out of memory\n", __func__); +- return -ENOMEM; +- } +- +- memcpy(buffer, firmware, firmware_size); +- memset(buffer+firmware_size, 0xff, buffer_size-firmware_size); +- +- for(pos = sizeof(struct ti_firmware_header); pos < buffer_size; pos++) ++ int status; ++ int len; ++ ++ for(pos = sizeof(struct ti_firmware_header); pos < size; pos++) + cs = (__u8)(cs + buffer[pos]); + + header = (struct ti_firmware_header *)buffer; +- header->wLength = cpu_to_le16((__u16)(buffer_size - sizeof(struct ti_firmware_header))); ++ header->wLength = cpu_to_le16((__u16)(size ++ - sizeof(struct ti_firmware_header))); + header->bCheckSum = cs; + + dbg("%s - downloading firmware", __func__); +- for (pos = 0; pos < buffer_size; pos += done) { +- len = min(buffer_size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE); +- status = usb_bulk_msg(dev, pipe, buffer+pos, len, &done, 1000); ++ for (pos = 0; pos < size; pos += done) { ++ len = min(size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE); ++ status = usb_bulk_msg(dev, pipe, buffer + pos, len, ++ &done, 1000); + if (status) + break; + } ++ return status; ++} ++ + +- kfree(buffer); ++static int ti_download_firmware(struct ti_device *tdev, int type) ++{ ++ int status = -ENOMEM; ++ int buffer_size; ++ __u8 *buffer; ++ struct usb_device *dev = tdev->td_serial->dev; ++ unsigned int pipe = usb_sndbulkpipe(dev, ++ tdev->td_serial->port[0]->bulk_out_endpointAddress); ++ const struct firmware *fw_p; + ++#ifdef CONFIG_USB_SERIAL_TI_FIRMWARE ++ switch (type) { ++ case 3410: ++ fw_p = &fw_3410; ++ break; ++ case 5052: ++ fw_p = &fw_5052; ++ break; ++ default: ++ return -EINVAL; ++ } ++#else ++ char buf[32]; ++ sprintf(buf, "ti_usb-%d.bin", type); ++ ++ if (request_firmware(&fw_p, buf, &dev->dev)) { ++ dev_err(&dev->dev, "%s - firmware not found\n", __func__); ++ return -ENOENT; ++ } ++ if (fw_p->size > TI_FIRMWARE_BUF_SIZE) { ++ dev_err(&dev->dev, "%s - firmware too large\n", __func__); ++ return -ENOENT; ++ } ++#endif ++ ++ buffer_size = TI_FIRMWARE_BUF_SIZE + sizeof(struct ti_firmware_header); ++ buffer = kmalloc(buffer_size, GFP_KERNEL); ++ if (buffer) { ++ memcpy(buffer, fw_p->data, fw_p->size); ++ memset(buffer + fw_p->size, 0xff, buffer_size - fw_p->size); ++ ti_do_download(dev, pipe, buffer, fw_p->size); ++ kfree(buffer); ++ } ++#ifdef CONFIG_USB_SERIAL_TI_FIRMWARE ++ release_firmware(fw_p); ++#endif + if (status) { + dev_err(&dev->dev, "%s - error downloading firmware, %d\n", __func__, status); + return status; diff --git a/usb/usb-add-new-routine-for-checking-port-resume-type.patch b/usb/usb-add-new-routine-for-checking-port-resume-type.patch new file mode 100644 index 00000000000000..ca77ec06de55eb --- /dev/null +++ b/usb/usb-add-new-routine-for-checking-port-resume-type.patch @@ -0,0 +1,156 @@ +From stern@rowland.harvard.edu Wed Apr 30 11:30:50 2008 +From: Alan Stern <stern@rowland.harvard.edu> +Date: Mon, 28 Apr 2008 11:06:11 -0400 (EDT) +Subject: USB: add new routine for checking port-resume type +To: Greg KH <greg@kroah.com> +Cc: USB list <linux-usb@vger.kernel.org> +Message-ID: <Pine.LNX.4.44L0.0804281055310.5827-100000@iolanthe.rowland.org> + + +This patch (as1070) creates a new subroutine to check whether a device +can be resumed. This code is needed even when CONFIG_USB_SUSPEND +isn't set, because devices do suspend themselves when the root hub +(and hence the entire bus) is suspended, and power sessions can get +lost during a system sleep even without individual port suspends. + +The patch also fixes a loose end in USB-Persist reset-resume handling. +When a low- or full-speed device is attached to an EHCI's companion +controller, the port handoff during resume will cause the companion +port's connect-status-change feature to be set. If that flag isn't +cleared, the port-reset code will think it indicates that the device +has been unplugged and the reset-resume will fail. + +Signed-off-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/core/hub.c | 90 ++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 63 insertions(+), 27 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -1770,6 +1770,45 @@ static int hub_port_reset(struct usb_hub + + #ifdef CONFIG_PM + ++#define MASK_BITS (USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION | \ ++ USB_PORT_STAT_SUSPEND) ++#define WANT_BITS (USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION) ++ ++/* Determine whether the device on a port is ready for a normal resume, ++ * is ready for a reset-resume, or should be disconnected. ++ */ ++static int check_port_resume_type(struct usb_device *udev, ++ struct usb_hub *hub, int port1, ++ int status, unsigned portchange, unsigned portstatus) ++{ ++ /* Is the device still present? */ ++ if (status || (portstatus & MASK_BITS) != WANT_BITS) { ++ if (status >= 0) ++ status = -ENODEV; ++ } ++ ++ /* Can't do a normal resume if the port isn't enabled */ ++ else if (!(portstatus & USB_PORT_STAT_ENABLE) && !udev->reset_resume) ++ status = -ENODEV; ++ ++ if (status) { ++ dev_dbg(hub->intfdev, ++ "port %d status %04x.%04x after resume, %d\n", ++ port1, portchange, portstatus, status); ++ } else if (udev->reset_resume) { ++ ++ /* Late port handoff can set status-change bits */ ++ if (portchange & USB_PORT_STAT_C_CONNECTION) ++ clear_port_feature(hub->hdev, port1, ++ USB_PORT_FEAT_C_CONNECTION); ++ if (portchange & USB_PORT_STAT_C_ENABLE) ++ clear_port_feature(hub->hdev, port1, ++ USB_PORT_FEAT_C_ENABLE); ++ } ++ ++ return status; ++} ++ + #ifdef CONFIG_USB_SUSPEND + + /* +@@ -1974,7 +2013,6 @@ int usb_port_resume(struct usb_device *u + int port1 = udev->portnum; + int status; + u16 portchange, portstatus; +- unsigned mask_flags, want_flags; + + /* Skip the initial Clear-Suspend step for a remote wakeup */ + status = hub_port_status(hub, port1, &portstatus, &portchange); +@@ -2003,33 +2041,20 @@ int usb_port_resume(struct usb_device *u + */ + status = hub_port_status(hub, port1, &portstatus, &portchange); + +- SuspendCleared: +- if (udev->reset_resume) +- want_flags = USB_PORT_STAT_POWER +- | USB_PORT_STAT_CONNECTION; +- else +- want_flags = USB_PORT_STAT_POWER +- | USB_PORT_STAT_CONNECTION +- | USB_PORT_STAT_ENABLE; +- mask_flags = want_flags | USB_PORT_STAT_SUSPEND; +- +- if (status < 0 || (portstatus & mask_flags) != want_flags) { +- dev_dbg(hub->intfdev, +- "port %d status %04x.%04x after resume, %d\n", +- port1, portchange, portstatus, status); +- if (status >= 0) +- status = -ENODEV; +- } else { +- if (portchange & USB_PORT_STAT_C_SUSPEND) +- clear_port_feature(hub->hdev, port1, +- USB_PORT_FEAT_C_SUSPEND); +- /* TRSMRCY = 10 msec */ +- msleep(10); +- } ++ /* TRSMRCY = 10 msec */ ++ msleep(10); + } + ++ SuspendCleared: ++ if (status == 0) { ++ if (portchange & USB_PORT_STAT_C_SUSPEND) ++ clear_port_feature(hub->hdev, port1, ++ USB_PORT_FEAT_C_SUSPEND); ++ } + clear_bit(port1, hub->busy_bits); + ++ status = check_port_resume_type(udev, ++ hub, port1, status, portchange, portstatus); + if (status == 0) + status = finish_port_resume(udev); + if (status < 0) { +@@ -2062,12 +2087,23 @@ int usb_port_suspend(struct usb_device * + return 0; + } + ++/* However we may need to do a reset-resume */ ++ + int usb_port_resume(struct usb_device *udev) + { +- int status = 0; ++ struct usb_hub *hub = hdev_to_hub(udev->parent); ++ int port1 = udev->portnum; ++ int status; ++ u16 portchange, portstatus; + +- /* However we may need to do a reset-resume */ +- if (udev->reset_resume) { ++ status = hub_port_status(hub, port1, &portstatus, &portchange); ++ status = check_port_resume_type(udev, ++ hub, port1, status, portchange, portstatus); ++ ++ if (status) { ++ dev_dbg(&udev->dev, "can't resume, status %d\n", status); ++ hub_port_logical_disconnect(hub, port1); ++ } else if (udev->reset_resume) { + dev_dbg(&udev->dev, "reset-resume\n"); + status = usb_reset_device(udev); + } diff --git a/usb/usb-add-usb_dev_reset_delayed.patch b/usb/usb-add-usb_dev_reset_delayed.patch index 9295bc016005d6..197373ec3829cf 100644 --- a/usb/usb-add-usb_dev_reset_delayed.patch +++ b/usb/usb-add-usb_dev_reset_delayed.patch @@ -20,7 +20,7 @@ Signed-off-by: Inaky Perez-Gonzalez <inaky@linux.intel.com> --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c -@@ -3304,3 +3304,86 @@ int usb_reset_composite_device(struct us +@@ -3393,3 +3393,86 @@ int usb_reset_composite_device(struct us return ret; } EXPORT_SYMBOL_GPL(usb_reset_composite_device); diff --git a/usb/usb-combine-hub_activate-and-hub_restart.patch b/usb/usb-combine-hub_activate-and-hub_restart.patch new file mode 100644 index 00000000000000..a3c1e6d622038e --- /dev/null +++ b/usb/usb-combine-hub_activate-and-hub_restart.patch @@ -0,0 +1,130 @@ +From stern@rowland.harvard.edu Wed Apr 30 11:32:59 2008 +From: Alan Stern <stern@rowland.harvard.edu> +Date: Mon, 28 Apr 2008 11:07:17 -0400 (EDT) +Subject: USB: combine hub_activate and hub_restart +To: Greg KH <greg@kroah.com> +Cc: USB list <linux-usb@vger.kernel.org> +Message-ID: <Pine.LNX.4.44L0.0804281100130.5827-100000@iolanthe.rowland.org> + + +This patch (as1071) combines hub_activate() and hub_restart() into a +single routine. There's no point keeping them separate, since they +are always called together. + +Signed-off-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/core/hub.c | 49 +++++++++++++++++++++++-------------------------- + 1 file changed, 23 insertions(+), 26 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -551,22 +551,6 @@ static void hub_quiesce(struct usb_hub * + cancel_work_sync(&hub->tt.kevent); + } + +-static void hub_activate(struct usb_hub *hub) +-{ +- int status; +- +- hub->quiescing = 0; +- +- status = usb_submit_urb(hub->urb, GFP_NOIO); +- if (status < 0) +- dev_err(hub->intfdev, "activate --> %d\n", status); +- if (hub->has_indicators && blinkenlights) +- schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD); +- +- /* scan all ports ASAP */ +- kick_khubd(hub); +-} +- + static int hub_hub_status(struct usb_hub *hub, + u16 *status, u16 *change) + { +@@ -643,18 +627,24 @@ enum hub_activation_type { + HUB_INIT, HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME + }; + +-static void hub_restart(struct usb_hub *hub, enum hub_activation_type type) ++static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) + { + struct usb_device *hdev = hub->hdev; + int port1; ++ int status; + bool need_debounce_delay = false; + ++ /* After a resume, port power should still be on. ++ * For any other type of activation, turn it on. ++ */ ++ if (type != HUB_RESUME) ++ hub_power_on(hub); ++ + /* Check each port and set hub->change_bits to let khubd know + * which ports need attention. + */ + for (port1 = 1; port1 <= hdev->maxchild; ++port1) { + struct usb_device *udev = hdev->children[port1-1]; +- int status; + u16 portstatus, portchange; + + portstatus = portchange = 0; +@@ -729,7 +719,17 @@ static void hub_restart(struct usb_hub * + */ + if (need_debounce_delay) + msleep(HUB_DEBOUNCE_STABLE); +- hub_activate(hub); ++ ++ hub->quiescing = 0; ++ ++ status = usb_submit_urb(hub->urb, GFP_NOIO); ++ if (status < 0) ++ dev_err(hub->intfdev, "activate --> %d\n", status); ++ if (hub->has_indicators && blinkenlights) ++ schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD); ++ ++ /* Scan all ports that need attention */ ++ kick_khubd(hub); + } + + /* caller has locked the hub device */ +@@ -746,8 +746,7 @@ static int hub_post_reset(struct usb_int + { + struct usb_hub *hub = usb_get_intfdata(intf); + +- hub_power_on(hub); +- hub_restart(hub, HUB_POST_RESET); ++ hub_activate(hub, HUB_POST_RESET); + return 0; + } + +@@ -993,8 +992,7 @@ static int hub_configure(struct usb_hub + if (hub->has_indicators && blinkenlights) + hub->indicator [0] = INDICATOR_CYCLE; + +- hub_power_on(hub); +- hub_activate(hub); ++ hub_activate(hub, HUB_INIT); + return 0; + + fail: +@@ -2166,7 +2164,7 @@ static int hub_resume(struct usb_interfa + struct usb_hub *hub = usb_get_intfdata(intf); + + dev_dbg(&intf->dev, "%s\n", __func__); +- hub_restart(hub, HUB_RESUME); ++ hub_activate(hub, HUB_RESUME); + return 0; + } + +@@ -2175,8 +2173,7 @@ static int hub_reset_resume(struct usb_i + struct usb_hub *hub = usb_get_intfdata(intf); + + dev_dbg(&intf->dev, "%s\n", __func__); +- hub_power_on(hub); +- hub_restart(hub, HUB_RESET_RESUME); ++ hub_activate(hub, HUB_RESET_RESUME); + return 0; + } + diff --git a/usb/usb-combine-hub_quiesce-and-hub_stop.patch b/usb/usb-combine-hub_quiesce-and-hub_stop.patch new file mode 100644 index 00000000000000..7ac8b466bae7b6 --- /dev/null +++ b/usb/usb-combine-hub_quiesce-and-hub_stop.patch @@ -0,0 +1,132 @@ +From stern@rowland.harvard.edu Wed Apr 30 11:33:23 2008 +From: Alan Stern <stern@rowland.harvard.edu> +Date: Mon, 28 Apr 2008 11:07:31 -0400 (EDT) +Subject: USB: combine hub_quiesce and hub_stop +To: Greg KH <greg@kroah.com> +Cc: USB list <linux-usb@vger.kernel.org> +Message-ID: <Pine.LNX.4.44L0.0804281100360.5827-100000@iolanthe.rowland.org> + + +This patch (as1083) combines hub_quiesce() and hub_stop() into a +single routine. There's no point keeping them separate since they are +usually called together. + +Signed-off-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/core/hub.c | 63 ++++++++++++++++++++++++------------------------- + 1 file changed, 32 insertions(+), 31 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -538,19 +538,6 @@ static void hub_power_on(struct usb_hub + msleep(max(pgood_delay, (unsigned) 100)); + } + +-static void hub_quiesce(struct usb_hub *hub) +-{ +- /* (nonblocking) khubd and related activity won't re-trigger */ +- hub->quiescing = 1; +- +- /* (blocking) stop khubd and related activity */ +- usb_kill_urb(hub->urb); +- if (hub->has_indicators) +- cancel_delayed_work_sync(&hub->leds); +- if (hub->tt.hub) +- cancel_work_sync(&hub->tt.kevent); +-} +- + static int hub_hub_status(struct usb_hub *hub, + u16 *status, u16 *change) + { +@@ -609,20 +596,6 @@ static void hub_port_logical_disconnect( + kick_khubd(hub); + } + +-/* caller has locked the hub device */ +-static void hub_stop(struct usb_hub *hub) +-{ +- struct usb_device *hdev = hub->hdev; +- int i; +- +- /* Disconnect all the children */ +- for (i = 0; i < hdev->maxchild; ++i) { +- if (hdev->children[i]) +- usb_disconnect(&hdev->children[i]); +- } +- hub_quiesce(hub); +-} +- + enum hub_activation_type { + HUB_INIT, HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME + }; +@@ -732,12 +705,40 @@ static void hub_activate(struct usb_hub + kick_khubd(hub); + } + ++enum hub_quiescing_type { ++ HUB_DISCONNECT, HUB_PRE_RESET, HUB_SUSPEND ++}; ++ ++static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) ++{ ++ struct usb_device *hdev = hub->hdev; ++ int i; ++ ++ /* khubd and related activity won't re-trigger */ ++ hub->quiescing = 1; ++ ++ if (type != HUB_SUSPEND) { ++ /* Disconnect all the children */ ++ for (i = 0; i < hdev->maxchild; ++i) { ++ if (hdev->children[i]) ++ usb_disconnect(&hdev->children[i]); ++ } ++ } ++ ++ /* Stop khubd and related activity */ ++ usb_kill_urb(hub->urb); ++ if (hub->has_indicators) ++ cancel_delayed_work_sync(&hub->leds); ++ if (hub->tt.hub) ++ cancel_work_sync(&hub->tt.kevent); ++} ++ + /* caller has locked the hub device */ + static int hub_pre_reset(struct usb_interface *intf) + { + struct usb_hub *hub = usb_get_intfdata(intf); + +- hub_stop(hub); ++ hub_quiesce(hub, HUB_PRE_RESET); + return 0; + } + +@@ -1024,7 +1025,7 @@ static void hub_disconnect(struct usb_in + + /* Disconnect all children and quiesce the hub */ + hub->error = 0; +- hub_stop(hub); ++ hub_quiesce(hub, HUB_DISCONNECT); + + usb_set_intfdata (intf, NULL); + +@@ -2155,7 +2156,7 @@ static int hub_suspend(struct usb_interf + dev_dbg(&intf->dev, "%s\n", __func__); + + /* stop khubd and related activity */ +- hub_quiesce(hub); ++ hub_quiesce(hub, HUB_SUSPEND); + return 0; + } + +@@ -2898,7 +2899,7 @@ static void hub_events(void) + /* If the hub has died, clean up after it */ + if (hdev->state == USB_STATE_NOTATTACHED) { + hub->error = -ENODEV; +- hub_stop(hub); ++ hub_quiesce(hub, HUB_DISCONNECT); + goto loop; + } + diff --git a/usb/usb-create-attributes-before-sending-uevent.patch b/usb/usb-create-attributes-before-sending-uevent.patch index eec9198f13730e..c17ffdcddaa9c4 100644 --- a/usb/usb-create-attributes-before-sending-uevent.patch +++ b/usb/usb-create-attributes-before-sending-uevent.patch @@ -80,7 +80,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> destroy_endpoint_class(); --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c -@@ -1605,6 +1605,7 @@ free_interfaces: +@@ -1607,6 +1607,7 @@ free_interfaces: intf->dev.driver = NULL; intf->dev.bus = &usb_bus_type; intf->dev.type = &usb_if_device_type; diff --git a/usb/usb-debounce-before-unregistering.patch b/usb/usb-debounce-before-unregistering.patch new file mode 100644 index 00000000000000..fc9c1ee18cf57c --- /dev/null +++ b/usb/usb-debounce-before-unregistering.patch @@ -0,0 +1,93 @@ +From stern@rowland.harvard.edu Wed Apr 30 11:31:33 2008 +From: Alan Stern <stern@rowland.harvard.edu> +Date: Mon, 28 Apr 2008 11:06:28 -0400 (EDT) +Subject: USB: debounce before unregistering +To: Greg KH <greg@kroah.com> +Cc: USB list <linux-usb@vger.kernel.org> +Message-ID: <Pine.LNX.4.44L0.0804281056190.5827-100000@iolanthe.rowland.org> + + +This patch (as1080) makes a significant change to the way khubd +handles port connect-change and enable-change events. Both types of +event are now debounced, and the debouncing is carried out _before_ an +existing usb_device is unregistered, instead of afterward. + +This means that drivers will have to deal with longer runs of errors +when a device is unplugged, but they are supposed to be prepared for +that in any case. + +The advantage is that when an enable-change occurs (caused for example +by electromagnetic interference), the debouncing period will provide +time for the cause of the problem to die away. A simple port reset +(added in a forthcoming patch) will then allow us to recover from the +fault. + +Signed-off-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/core/hub.c | 31 +++++++++++++++++++------------ + 1 file changed, 19 insertions(+), 12 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2619,9 +2619,10 @@ static void hub_port_connect_change(stru + struct usb_device *hdev = hub->hdev; + struct device *hub_dev = hub->intfdev; + struct usb_hcd *hcd = bus_to_hcd(hdev->bus); +- u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); ++ unsigned wHubCharacteristics = ++ le16_to_cpu(hub->descriptor->wHubCharacteristics); + int status, i; +- ++ + dev_dbg (hub_dev, + "port %d, status %04x, change %04x, %s\n", + port1, portstatus, portchange, portspeed (portstatus)); +@@ -2630,30 +2631,36 @@ static void hub_port_connect_change(stru + set_port_led(hub, port1, HUB_LED_AUTO); + hub->indicator[port1-1] = INDICATOR_AUTO; + } +- +- /* Disconnect any existing devices under this port */ +- if (hdev->children[port1-1]) +- usb_disconnect(&hdev->children[port1-1]); +- clear_bit(port1, hub->change_bits); + + #ifdef CONFIG_USB_OTG + /* during HNP, don't repeat the debounce */ + if (hdev->bus->is_b_host) +- portchange &= ~USB_PORT_STAT_C_CONNECTION; ++ portchange &= ~(USB_PORT_STAT_C_CONNECTION | ++ USB_PORT_STAT_C_ENABLE); + #endif + +- if (portchange & USB_PORT_STAT_C_CONNECTION) { ++ /* Try to use the debounce delay for protection against ++ * port-enable changes caused, for example, by EMI. ++ */ ++ if (portchange & (USB_PORT_STAT_C_CONNECTION | ++ USB_PORT_STAT_C_ENABLE)) { + status = hub_port_debounce(hub, port1); + if (status < 0) { + if (printk_ratelimit()) + dev_err (hub_dev, "connect-debounce failed, " + "port %d disabled\n", port1); +- goto done; ++ portstatus &= ~USB_PORT_STAT_CONNECTION; ++ } else { ++ portstatus = status; + } +- portstatus = status; + } + +- /* Return now if nothing is connected */ ++ /* Disconnect any existing devices under this port */ ++ if (hdev->children[port1-1]) ++ usb_disconnect(&hdev->children[port1-1]); ++ clear_bit(port1, hub->change_bits); ++ ++ /* Return now if debouncing failed or nothing is connected */ + if (!(portstatus & USB_PORT_STAT_CONNECTION)) { + + /* maybe switch power back on (e.g. root hub was reset) */ diff --git a/usb/usb-gadget-peripheral-g_file_storage-bulk-only-transport-compliance-clear-feature-ignore.patch b/usb/usb-gadget-peripheral-g_file_storage-bulk-only-transport-compliance-clear-feature-ignore.patch new file mode 100644 index 00000000000000..d72b9774875e4e --- /dev/null +++ b/usb/usb-gadget-peripheral-g_file_storage-bulk-only-transport-compliance-clear-feature-ignore.patch @@ -0,0 +1,61 @@ +From dlopo@chipidea.mips.com Wed Apr 30 11:35:20 2008 +From: David Lopo <dlopo@chipidea.mips.com> +Date: Tue, 29 Apr 2008 10:14:38 +0100 +Subject: USB GADGET/PERIPHERAL: g_file_storage Bulk-Only Transport compliance, clear-feature ignore +To: greg@kroah.com, gregkh@suse.de +Cc: Alan Stern <stern@rowland.harvard.edu>, linux-usb@vger.kernel.org +Message-ID: <4816E6FE.20509@chipidea.mips.com> + + +From: David Lopo <lopo.david@gmail.com> + +Gadget tells controller driver to ignore Clear-Feature(HALT_ENDPOINT) + +Signed-off-by: David Lopo <lopo.david@gmail.com> +Acked-by: Alan Stern <stern@rowland.harvard.edu> +--- +--- + drivers/usb/gadget/file_storage.c | 25 ++++++++++++++++++++++++- + 1 file changed, 24 insertions(+), 1 deletion(-) + +--- a/drivers/usb/gadget/file_storage.c ++++ b/drivers/usb/gadget/file_storage.c +@@ -2307,6 +2307,29 @@ static int halt_bulk_in_endpoint(struct + return rc; + } + ++static int wedge_bulk_in_endpoint(struct fsg_dev *fsg) ++{ ++ int rc; ++ ++ DBG(fsg, "bulk-in set wedge\n"); ++ rc = usb_ep_set_wedge(fsg->bulk_in); ++ if (rc == -EAGAIN) ++ VDBG(fsg, "delayed bulk-in endpoint wedge\n"); ++ while (rc != 0) { ++ if (rc != -EAGAIN) { ++ WARN(fsg, "usb_ep_set_wedge -> %d\n", rc); ++ rc = 0; ++ break; ++ } ++ ++ /* Wait for a short time and then try again */ ++ if (msleep_interruptible(100) != 0) ++ return -EINTR; ++ rc = usb_ep_set_wedge(fsg->bulk_in); ++ } ++ return rc; ++} ++ + static int pad_with_zeros(struct fsg_dev *fsg) + { + struct fsg_buffhd *bh = fsg->next_buffhd_to_fill; +@@ -2957,7 +2980,7 @@ static int received_cbw(struct fsg_dev * + * We aren't required to halt the OUT endpoint; instead + * we can simply accept and discard any data received + * until the next reset. */ +- halt_bulk_in_endpoint(fsg); ++ wedge_bulk_in_endpoint(fsg); + set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); + return -EINVAL; + } diff --git a/usb/usb-gadget-peripheral-g_file_storage-bulk-only-transport-compliance.patch b/usb/usb-gadget-peripheral-g_file_storage-bulk-only-transport-compliance.patch new file mode 100644 index 00000000000000..dfaa09b6bce31f --- /dev/null +++ b/usb/usb-gadget-peripheral-g_file_storage-bulk-only-transport-compliance.patch @@ -0,0 +1,59 @@ +From dlopo@chipidea.mips.com Wed Apr 30 11:34:54 2008 +From: David Lopo <dlopo@chipidea.mips.com> +Date: Tue, 29 Apr 2008 10:12:37 +0100 +Subject: USB GADGET/PERIPHERAL: g_file_storage Bulk-Only Transport compliance +To: greg@kroah.com, gregkh@suse.de +Cc: stern@rowland.harvard.edu, linux-usb@vger.kernel.org +Message-ID: <4816E685.2040208@chipidea.mips.com> + + +From: David Lopo <lopo.david@gmail.com> + +Gadget can tell controller driver to ignore Clear-Feature(HALT_ENDPOINT) +This API change enables future support for Bulk-Only Transport compliance + +Signed-off-by: David Lopo <lopo.david@gmail.com> +Acked-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + include/linux/usb/gadget.h | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +--- a/include/linux/usb/gadget.h ++++ b/include/linux/usb/gadget.h +@@ -114,6 +114,8 @@ struct usb_ep_ops { + int (*dequeue) (struct usb_ep *ep, struct usb_request *req); + + int (*set_halt) (struct usb_ep *ep, int value); ++ int (*set_wedge) (struct usb_ep *ep); ++ + int (*fifo_status) (struct usb_ep *ep); + void (*fifo_flush) (struct usb_ep *ep); + }; +@@ -349,6 +351,25 @@ static inline int usb_ep_clear_halt(stru + } + + /** ++ * usb_ep_set_wedge - sets the halt feature and ignores clear requests ++ * @ep: the endpoint being wedged ++ * ++ * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT) ++ * requests. If the gadget driver clears the halt status, it will ++ * automatically unwedge the endpoint. ++ * ++ * Returns zero on success, else negative errno. ++ */ ++static inline int ++usb_ep_set_wedge(struct usb_ep *ep) ++{ ++ if (ep->ops->set_wedge) ++ return ep->ops->set_wedge(ep); ++ else ++ return ep->ops->set_halt(ep, 1); ++} ++ ++/** + * usb_ep_fifo_status - returns number of bytes in fifo, or error + * @ep: the endpoint whose fifo status is being checked. + * diff --git a/usb/usb-optimize-port-debouncing-during-hub-activation.patch b/usb/usb-optimize-port-debouncing-during-hub-activation.patch new file mode 100644 index 00000000000000..44b5dbbfabf5b7 --- /dev/null +++ b/usb/usb-optimize-port-debouncing-during-hub-activation.patch @@ -0,0 +1,99 @@ +From stern@rowland.harvard.edu Wed Apr 30 11:32:40 2008 +From: Alan Stern <stern@rowland.harvard.edu> +Date: Mon, 28 Apr 2008 11:07:07 -0400 (EDT) +Subject: USB: optimize port debouncing during hub activation +To: Greg KH <greg@kroah.com> +Cc: USB list <linux-usb@vger.kernel.org> +Message-ID: <Pine.LNX.4.44L0.0804281058350.5827-100000@iolanthe.rowland.org> + + +This patch (as1082) makes a small optimization to the way the hub +driver carries out port debouncing immediately after a hub is +activated (i.e., initialized, reset, or resumed). If any port-change +statuses are observed, the code will delay for a minimal debounce +period -- thereby making a good start at debouncing all the ports at +once. + +If this wasn't sufficient then khubd will debounce any port that still +requires attention. But in most cases it should suffice; it's rare +for a device to need more than a minimal debounce delay. (In the +cases of hub initialization or reset even that is most likely not +needed, since any devices plugged in at such times have probably been +attached for a while.) + +Signed-off-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/core/hub.c | 32 +++++++++++++++++++++++++++----- + 1 file changed, 27 insertions(+), 5 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -130,6 +130,10 @@ MODULE_PARM_DESC(use_both_schemes, + DECLARE_RWSEM(ehci_cf_port_reset_rwsem); + EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem); + ++#define HUB_DEBOUNCE_TIMEOUT 1500 ++#define HUB_DEBOUNCE_STEP 25 ++#define HUB_DEBOUNCE_STABLE 100 ++ + + static inline char *portspeed(int portstatus) + { +@@ -643,6 +647,7 @@ static void hub_restart(struct usb_hub * + { + struct usb_device *hdev = hub->hdev; + int port1; ++ bool need_debounce_delay = false; + + /* Check each port and set hub->change_bits to let khubd know + * which ports need attention. +@@ -673,6 +678,18 @@ static void hub_restart(struct usb_hub * + portstatus &= ~USB_PORT_STAT_ENABLE; + } + ++ /* Clear status-change flags; we'll debounce later */ ++ if (portchange & USB_PORT_STAT_C_CONNECTION) { ++ need_debounce_delay = true; ++ clear_port_feature(hub->hdev, port1, ++ USB_PORT_FEAT_C_CONNECTION); ++ } ++ if (portchange & USB_PORT_STAT_C_ENABLE) { ++ need_debounce_delay = true; ++ clear_port_feature(hub->hdev, port1, ++ USB_PORT_FEAT_C_ENABLE); ++ } ++ + if (!udev || udev->state == USB_STATE_NOTATTACHED) { + /* Tell khubd to disconnect the device or + * check for a new connection +@@ -702,6 +719,16 @@ static void hub_restart(struct usb_hub * + } + } + ++ /* If no port-status-change flags were set, we don't need any ++ * debouncing. If flags were set we can try to debounce the ++ * ports all at once right now, instead of letting khubd do them ++ * one at a time later on. ++ * ++ * If any port-status changes do occur during this delay, khubd ++ * will see them later and handle them normally. ++ */ ++ if (need_debounce_delay) ++ msleep(HUB_DEBOUNCE_STABLE); + hub_activate(hub); + } + +@@ -2199,11 +2226,6 @@ static inline int remote_wakeup(struct u + * every 25ms for transient disconnects. When the port status has been + * unchanged for 100ms it returns the port status. + */ +- +-#define HUB_DEBOUNCE_TIMEOUT 1500 +-#define HUB_DEBOUNCE_STEP 25 +-#define HUB_DEBOUNCE_STABLE 100 +- + static int hub_port_debounce(struct usb_hub *hub, int port1) + { + int ret; diff --git a/usb/usb-simplify-hub_restart-logic.patch b/usb/usb-simplify-hub_restart-logic.patch new file mode 100644 index 00000000000000..779e85fad6058e --- /dev/null +++ b/usb/usb-simplify-hub_restart-logic.patch @@ -0,0 +1,250 @@ +From stern@rowland.harvard.edu Wed Apr 30 11:32:02 2008 +From: Alan Stern <stern@rowland.harvard.edu> +Date: Mon, 28 Apr 2008 11:06:42 -0400 (EDT) +Subject: USB: simplify hub_restart() logic +To: Greg KH <greg@kroah.com> +Cc: USB list <linux-usb@vger.kernel.org> +Message-ID: <Pine.LNX.4.44L0.0804281057080.5827-100000@iolanthe.rowland.org> + + +This patch (as1081) straightens out the logic of the hub_restart() +routine. Each port of the hub is scanned and the driver makes sure +that ports which are supposed to be disabled really _are_ disabled. +Any ports with a significant change in status are flagged in +hub->change_bits, so that khubd can focus on them without the need to +scan all the ports a second time -- which means the hub->activating +flag is no longer needed. + +Also, it is now recognized explicitly that the only reason for +resuming a port which was not suspended is to carry out a reset-resume +operation, which happens only in a non-CONFIG_USB_SUSPEND setting. + +Signed-off-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/core/driver.c | 7 -- + drivers/usb/core/hub.c | 112 +++++++++++++++++++++------------------------- + 2 files changed, 53 insertions(+), 66 deletions(-) + +--- a/drivers/usb/core/driver.c ++++ b/drivers/usb/core/driver.c +@@ -805,8 +805,6 @@ static int usb_resume_device(struct usb_ + + if (udev->state == USB_STATE_NOTATTACHED) + goto done; +- if (udev->state != USB_STATE_SUSPENDED && !udev->reset_resume) +- goto done; + + /* Can't resume it if it doesn't have a driver. */ + if (udev->dev.driver == NULL) { +@@ -1173,11 +1171,8 @@ static int usb_resume_both(struct usb_de + * then we're stuck. */ + status = usb_resume_device(udev); + } +- } else { +- +- /* Needed for reset-resume */ ++ } else if (udev->reset_resume) + status = usb_resume_device(udev); +- } + + if (status == 0 && udev->actconfig) { + for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -72,7 +72,6 @@ struct usb_hub { + + unsigned limited_power:1; + unsigned quiescing:1; +- unsigned activating:1; + unsigned disconnected:1; + + unsigned has_indicators:1; +@@ -539,7 +538,6 @@ static void hub_quiesce(struct usb_hub * + { + /* (nonblocking) khubd and related activity won't re-trigger */ + hub->quiescing = 1; +- hub->activating = 0; + + /* (blocking) stop khubd and related activity */ + usb_kill_urb(hub->urb); +@@ -554,7 +552,6 @@ static void hub_activate(struct usb_hub + int status; + + hub->quiescing = 0; +- hub->activating = 1; + + status = usb_submit_urb(hub->urb, GFP_NOIO); + if (status < 0) +@@ -638,81 +635,83 @@ static void hub_stop(struct usb_hub *hub + hub_quiesce(hub); + } + +-#define HUB_RESET 1 +-#define HUB_RESUME 2 +-#define HUB_RESET_RESUME 3 +- +-#ifdef CONFIG_PM ++enum hub_activation_type { ++ HUB_INIT, HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME ++}; + +-static void hub_restart(struct usb_hub *hub, int type) ++static void hub_restart(struct usb_hub *hub, enum hub_activation_type type) + { + struct usb_device *hdev = hub->hdev; + int port1; + +- /* Check each of the children to see if they require +- * USB-PERSIST handling or disconnection. Also check +- * each unoccupied port to make sure it is still disabled. ++ /* Check each port and set hub->change_bits to let khubd know ++ * which ports need attention. + */ + for (port1 = 1; port1 <= hdev->maxchild; ++port1) { + struct usb_device *udev = hdev->children[port1-1]; +- int status = 0; ++ int status; + u16 portstatus, portchange; + +- if (!udev || udev->state == USB_STATE_NOTATTACHED) { +- if (type != HUB_RESET) { +- status = hub_port_status(hub, port1, +- &portstatus, &portchange); +- if (status == 0 && (portstatus & +- USB_PORT_STAT_ENABLE)) +- clear_port_feature(hdev, port1, +- USB_PORT_FEAT_ENABLE); +- } +- continue; ++ portstatus = portchange = 0; ++ status = hub_port_status(hub, port1, &portstatus, &portchange); ++ if (udev || (portstatus & USB_PORT_STAT_CONNECTION)) ++ dev_dbg(hub->intfdev, ++ "port %d: status %04x change %04x\n", ++ port1, portstatus, portchange); ++ ++ /* After anything other than HUB_RESUME (i.e., initialization ++ * or any sort of reset), every port should be disabled. ++ * Unconnected ports should likewise be disabled (paranoia), ++ * and so should ports for which we have no usb_device. ++ */ ++ if ((portstatus & USB_PORT_STAT_ENABLE) && ( ++ type != HUB_RESUME || ++ !(portstatus & USB_PORT_STAT_CONNECTION) || ++ !udev || ++ udev->state == USB_STATE_NOTATTACHED)) { ++ clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); ++ portstatus &= ~USB_PORT_STAT_ENABLE; + } + +- /* Was the power session lost while we were suspended? */ +- switch (type) { +- case HUB_RESET_RESUME: +- portstatus = 0; +- portchange = USB_PORT_STAT_C_CONNECTION; +- break; ++ if (!udev || udev->state == USB_STATE_NOTATTACHED) { ++ /* Tell khubd to disconnect the device or ++ * check for a new connection ++ */ ++ if (udev || (portstatus & USB_PORT_STAT_CONNECTION)) ++ set_bit(port1, hub->change_bits); + +- case HUB_RESET: +- case HUB_RESUME: +- status = hub_port_status(hub, port1, +- &portstatus, &portchange); +- break; +- } ++ } else if (portstatus & USB_PORT_STAT_ENABLE) { ++ /* The power session apparently survived the resume. ++ * If there was an overcurrent or suspend change ++ * (i.e., remote wakeup request), have khubd ++ * take care of it. ++ */ ++ if (portchange) ++ set_bit(port1, hub->change_bits); + +- /* For "USB_PERSIST"-enabled children we must +- * mark the child device for reset-resume and +- * turn off the various status changes to prevent +- * khubd from disconnecting it later. +- */ +- if (udev->persist_enabled && status == 0 && +- !(portstatus & USB_PORT_STAT_ENABLE)) { ++ } else if (udev->persist_enabled) { ++ /* Turn off the status changes to prevent khubd ++ * from disconnecting the device. ++ */ + if (portchange & USB_PORT_STAT_C_ENABLE) + clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_ENABLE); + if (portchange & USB_PORT_STAT_C_CONNECTION) + clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_CONNECTION); ++#ifdef CONFIG_PM + udev->reset_resume = 1; ++#endif ++ } else { ++ /* The power session is gone; tell khubd */ ++ usb_set_device_state(udev, USB_STATE_NOTATTACHED); ++ set_bit(port1, hub->change_bits); + } +- +- /* Otherwise for a reset_resume we must disconnect the child, +- * but as we may not lock the child device here +- * we have to do a "logical" disconnect. +- */ +- else if (type == HUB_RESET_RESUME) +- hub_port_logical_disconnect(hub, port1); + } + + hub_activate(hub); + } + +-#endif /* CONFIG_PM */ +- + /* caller has locked the hub device */ + static int hub_pre_reset(struct usb_interface *intf) + { +@@ -728,7 +727,7 @@ static int hub_post_reset(struct usb_int + struct usb_hub *hub = usb_get_intfdata(intf); + + hub_power_on(hub); +- hub_activate(hub); ++ hub_restart(hub, HUB_POST_RESET); + return 0; + } + +@@ -2887,7 +2886,7 @@ static void hub_events(void) + continue; + connect_change = test_bit(i, hub->change_bits); + if (!test_and_clear_bit(i, hub->event_bits) && +- !connect_change && !hub->activating) ++ !connect_change) + continue; + + ret = hub_port_status(hub, i, +@@ -2895,11 +2894,6 @@ static void hub_events(void) + if (ret < 0) + continue; + +- if (hub->activating && !hdev->children[i-1] && +- (portstatus & +- USB_PORT_STAT_CONNECTION)) +- connect_change = 1; +- + if (portchange & USB_PORT_STAT_C_CONNECTION) { + clear_port_feature(hdev, i, + USB_PORT_FEAT_C_CONNECTION); +@@ -2995,8 +2989,6 @@ static void hub_events(void) + } + } + +- hub->activating = 0; +- + loop_autopm: + /* Allow autosuspend if we're not going to run again */ + if (list_empty(&hub->event_list)) diff --git a/usb/usb-try-to-salvage-lost-power-sessions.patch b/usb/usb-try-to-salvage-lost-power-sessions.patch new file mode 100644 index 00000000000000..7ff2dc3d8cb248 --- /dev/null +++ b/usb/usb-try-to-salvage-lost-power-sessions.patch @@ -0,0 +1,181 @@ +From stern@rowland.harvard.edu Wed Apr 30 11:32:15 2008 +From: Alan Stern <stern@rowland.harvard.edu> +Date: Mon, 28 Apr 2008 11:06:55 -0400 (EDT) +Subject: USB: try to salvage lost power sessions +To: Greg KH <greg@kroah.com> +Cc: USB list <linux-usb@vger.kernel.org> +Message-ID: <Pine.LNX.4.44L0.0804281057480.5827-100000@iolanthe.rowland.org> + + +This patch (as1073) adds to khubd a way to recover from power-session +interruption caused by transient connect-change or enable-change +events. After the debouncing period, khubd attempts to do a +USB-Persist-style reset or reset-resume. If it works, the connection +will remain unscathed. + +The upshot is that we will be more immune to noise caused by EMI. The +grace period is on the order of 100 ms, so this won't permit recovery +from the "accidentally knocked the USB cable out of its socket" type +of event, but it's a start. + +As an added bonus, if a device was suspended when the system goes to +sleep then we no longer need to check for power-session interruptions +when the system wakes up. Khubd will naturally see the status change +while processing the device's parent hub and will do the right thing. + +The remote_wakeup() routine is changed; now it expects the caller to +acquire the device lock rather than acquiring the lock itself. + +Signed-off-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/core/driver.c | 13 +++------ + drivers/usb/core/hub.c | 62 +++++++++++++++++++++++++++++++++++----------- + 2 files changed, 53 insertions(+), 22 deletions(-) + +--- a/drivers/usb/core/driver.c ++++ b/drivers/usb/core/driver.c +@@ -1537,14 +1537,11 @@ static int usb_resume(struct device *dev + udev = to_usb_device(dev); + + /* If udev->skip_sys_resume is set then udev was already suspended +- * when the system suspend started, so we don't want to resume +- * udev during this system wakeup. However a reset-resume counts +- * as a wakeup event, so allow a reset-resume to occur if remote +- * wakeup is enabled. */ +- if (udev->skip_sys_resume) { +- if (!(udev->reset_resume && udev->do_remote_wakeup)) +- return -EHOSTUNREACH; +- } ++ * when the system sleep started, so we don't want to resume it ++ * during this system wakeup. ++ */ ++ if (udev->skip_sys_resume) ++ return 0; + return usb_external_resume_device(udev); + } + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -690,18 +690,11 @@ static void hub_restart(struct usb_hub * + set_bit(port1, hub->change_bits); + + } else if (udev->persist_enabled) { +- /* Turn off the status changes to prevent khubd +- * from disconnecting the device. +- */ +- if (portchange & USB_PORT_STAT_C_ENABLE) +- clear_port_feature(hub->hdev, port1, +- USB_PORT_FEAT_C_ENABLE); +- if (portchange & USB_PORT_STAT_C_CONNECTION) +- clear_port_feature(hub->hdev, port1, +- USB_PORT_FEAT_C_CONNECTION); + #ifdef CONFIG_PM + udev->reset_resume = 1; + #endif ++ set_bit(port1, hub->change_bits); ++ + } else { + /* The power session is gone; tell khubd */ + usb_set_device_state(udev, USB_STATE_NOTATTACHED); +@@ -2063,17 +2056,16 @@ int usb_port_resume(struct usb_device *u + return status; + } + ++/* caller has locked udev */ + static int remote_wakeup(struct usb_device *udev) + { + int status = 0; + +- usb_lock_device(udev); + if (udev->state == USB_STATE_SUSPENDED) { + dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-"); + usb_mark_last_busy(udev); + status = usb_external_resume_device(udev); + } +- usb_unlock_device(udev); + return status; + } + +@@ -2620,6 +2612,7 @@ static void hub_port_connect_change(stru + struct usb_hcd *hcd = bus_to_hcd(hdev->bus); + unsigned wHubCharacteristics = + le16_to_cpu(hub->descriptor->wHubCharacteristics); ++ struct usb_device *udev; + int status, i; + + dev_dbg (hub_dev, +@@ -2654,8 +2647,45 @@ static void hub_port_connect_change(stru + } + } + ++ /* Try to resuscitate an existing device */ ++ udev = hdev->children[port1-1]; ++ if ((portstatus & USB_PORT_STAT_CONNECTION) && udev && ++ udev->state != USB_STATE_NOTATTACHED) { ++ ++ usb_lock_device(udev); ++ if (portstatus & USB_PORT_STAT_ENABLE) { ++ status = 0; /* Nothing to do */ ++ } else if (!udev->persist_enabled) { ++ status = -ENODEV; /* Mustn't resuscitate */ ++ ++#ifdef CONFIG_USB_SUSPEND ++ } else if (udev->state == USB_STATE_SUSPENDED) { ++ /* For a suspended device, treat this as a ++ * remote wakeup event. ++ */ ++ if (udev->do_remote_wakeup) ++ status = remote_wakeup(udev); ++ ++ /* Otherwise leave it be; devices can't tell the ++ * difference between suspended and disabled. ++ */ ++ else ++ status = 0; ++#endif ++ ++ } else { ++ status = usb_reset_composite_device(udev, NULL); ++ } ++ usb_unlock_device(udev); ++ ++ if (status == 0) { ++ clear_bit(port1, hub->change_bits); ++ return; ++ } ++ } ++ + /* Disconnect any existing devices under this port */ +- if (hdev->children[port1-1]) ++ if (udev) + usb_disconnect(&hdev->children[port1-1]); + clear_bit(port1, hub->change_bits); + +@@ -2673,7 +2703,6 @@ static void hub_port_connect_change(stru + } + + for (i = 0; i < SET_CONFIG_TRIES; i++) { +- struct usb_device *udev; + + /* reallocate for each attempt, since references + * to the previous one can escape in various ways +@@ -2928,11 +2957,16 @@ static void hub_events(void) + } + + if (portchange & USB_PORT_STAT_C_SUSPEND) { ++ struct usb_device *udev; ++ + clear_port_feature(hdev, i, + USB_PORT_FEAT_C_SUSPEND); +- if (hdev->children[i-1]) { ++ udev = hdev->children[i-1]; ++ if (udev) { ++ usb_lock_device(udev); + ret = remote_wakeup(hdev-> + children[i-1]); ++ usb_unlock_device(udev); + if (ret < 0) + connect_change = 1; + } else { diff --git a/usb/usb_serial-some-coding-style-fixes.patch b/usb/usb_serial-some-coding-style-fixes.patch new file mode 100644 index 00000000000000..f828b71b854014 --- /dev/null +++ b/usb/usb_serial-some-coding-style-fixes.patch @@ -0,0 +1,512 @@ +From alan@lxorguk.ukuu.org.uk Wed Apr 30 11:28:49 2008 +From: Alan Cox <alan@lxorguk.ukuu.org.uk> +Date: Tue, 29 Apr 2008 14:35:39 +0100 +Subject: usb_serial: some coding style fixes +To: linux-usb@vger.kernel.org, greg@kroah.com +Message-ID: <20080429143539.35def80c@core> + + +Signed-off-by: Alan Cox <alan@redhat.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/aircable.c | 98 +++++++++++++++++++++--------------------- + drivers/usb/serial/airprime.c | 61 ++++++++++++++------------ + drivers/usb/serial/ark3116.c | 54 +++++++++++------------ + drivers/usb/serial/ch341.c | 2 + 4 files changed, 112 insertions(+), 103 deletions(-) + +--- a/drivers/usb/serial/aircable.c ++++ b/drivers/usb/serial/aircable.c +@@ -147,7 +147,7 @@ static void serial_buf_free(struct circ_ + */ + static int serial_buf_data_avail(struct circ_buf *cb) + { +- return CIRC_CNT(cb->head,cb->tail,AIRCABLE_BUF_SIZE); ++ return CIRC_CNT(cb->head, cb->tail, AIRCABLE_BUF_SIZE); + } + + /* +@@ -171,7 +171,7 @@ static int serial_buf_put(struct circ_bu + cb->head = (cb->head + c) & (AIRCABLE_BUF_SIZE-1); + buf += c; + count -= c; +- ret= c; ++ ret = c; + } + return ret; + } +@@ -197,7 +197,7 @@ static int serial_buf_get(struct circ_bu + cb->tail = (cb->tail + c) & (AIRCABLE_BUF_SIZE-1); + buf += c; + count -= c; +- ret= c; ++ ret = c; + } + return ret; + } +@@ -208,7 +208,7 @@ static void aircable_send(struct usb_ser + { + int count, result; + struct aircable_private *priv = usb_get_serial_port_data(port); +- unsigned char* buf; ++ unsigned char *buf; + __le16 *dbuf; + dbg("%s - port %d", __func__, port->number); + if (port->write_urb_busy) +@@ -229,7 +229,8 @@ static void aircable_send(struct usb_ser + buf[1] = TX_HEADER_1; + dbuf = (__le16 *)&buf[2]; + *dbuf = cpu_to_le16((u16)count); +- serial_buf_get(priv->tx_buf,buf + HCI_HEADER_LENGTH, MAX_HCI_FRAMESIZE); ++ serial_buf_get(priv->tx_buf, buf + HCI_HEADER_LENGTH, ++ MAX_HCI_FRAMESIZE); + + memcpy(port->write_urb->transfer_buffer, buf, + count + HCI_HEADER_LENGTH); +@@ -261,7 +262,7 @@ static void aircable_read(struct work_st + struct tty_struct *tty; + unsigned char *data; + int count; +- if (priv->rx_flags & THROTTLED){ ++ if (priv->rx_flags & THROTTLED) { + if (priv->rx_flags & ACTUALLY_THROTTLED) + schedule_work(&priv->rx_work); + return; +@@ -282,10 +283,10 @@ static void aircable_read(struct work_st + count = min(64, serial_buf_data_avail(priv->rx_buf)); + + if (count <= 0) +- return; //We have finished sending everything. ++ return; /* We have finished sending everything. */ + + tty_prepare_flip_string(tty, &data, count); +- if (!data){ ++ if (!data) { + err("%s- kzalloc(%d) failed.", __func__, count); + return; + } +@@ -304,9 +305,10 @@ static void aircable_read(struct work_st + static int aircable_probe(struct usb_serial *serial, + const struct usb_device_id *id) + { +- struct usb_host_interface *iface_desc = serial->interface->cur_altsetting; ++ struct usb_host_interface *iface_desc = serial->interface-> ++ cur_altsetting; + struct usb_endpoint_descriptor *endpoint; +- int num_bulk_out=0; ++ int num_bulk_out = 0; + int i; + + for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { +@@ -325,13 +327,13 @@ static int aircable_probe(struct usb_ser + return 0; + } + +-static int aircable_attach (struct usb_serial *serial) ++static int aircable_attach(struct usb_serial *serial) + { + struct usb_serial_port *port = serial->port[0]; + struct aircable_private *priv; + + priv = kzalloc(sizeof(struct aircable_private), GFP_KERNEL); +- if (!priv){ ++ if (!priv) { + err("%s- kmalloc(%Zd) failed.", __func__, + sizeof(struct aircable_private)); + return -ENOMEM; +@@ -392,7 +394,7 @@ static int aircable_write(struct usb_ser + + usb_serial_debug_data(debug, &port->dev, __func__, count, source); + +- if (!count){ ++ if (!count) { + dbg("%s - write request of 0 bytes", __func__); + return count; + } +@@ -418,31 +420,31 @@ static void aircable_write_bulk_callback + + /* This has been taken from cypress_m8.c cypress_write_int_callback */ + switch (status) { +- case 0: +- /* success */ +- break; +- case -ECONNRESET: +- case -ENOENT: +- case -ESHUTDOWN: +- /* this urb is terminated, clean up */ +- dbg("%s - urb shutting down with status: %d", +- __func__, status); +- port->write_urb_busy = 0; ++ case 0: ++ /* success */ ++ break; ++ case -ECONNRESET: ++ case -ENOENT: ++ case -ESHUTDOWN: ++ /* this urb is terminated, clean up */ ++ dbg("%s - urb shutting down with status: %d", ++ __func__, status); ++ port->write_urb_busy = 0; ++ return; ++ default: ++ /* error in the urb, so we have to resubmit it */ ++ dbg("%s - Overflow in write", __func__); ++ dbg("%s - nonzero write bulk status received: %d", ++ __func__, status); ++ port->write_urb->transfer_buffer_length = 1; ++ port->write_urb->dev = port->serial->dev; ++ result = usb_submit_urb(port->write_urb, GFP_ATOMIC); ++ if (result) ++ dev_err(&urb->dev->dev, ++ "%s - failed resubmitting write urb, error %d\n", ++ __func__, result); ++ else + return; +- default: +- /* error in the urb, so we have to resubmit it */ +- dbg("%s - Overflow in write", __func__); +- dbg("%s - nonzero write bulk status received: %d", +- __func__, status); +- port->write_urb->transfer_buffer_length = 1; +- port->write_urb->dev = port->serial->dev; +- result = usb_submit_urb(port->write_urb, GFP_ATOMIC); +- if (result) +- dev_err(&urb->dev->dev, +- "%s - failed resubmitting write urb, error %d\n", +- __func__, result); +- else +- return; + } + + port->write_urb_busy = 0; +@@ -472,11 +474,11 @@ static void aircable_read_bulk_callback( + dbg("%s - caught -EPROTO, resubmitting the urb", + __func__); + usb_fill_bulk_urb(port->read_urb, port->serial->dev, +- usb_rcvbulkpipe(port->serial->dev, +- port->bulk_in_endpointAddress), +- port->read_urb->transfer_buffer, +- port->read_urb->transfer_buffer_length, +- aircable_read_bulk_callback, port); ++ usb_rcvbulkpipe(port->serial->dev, ++ port->bulk_in_endpointAddress), ++ port->read_urb->transfer_buffer, ++ port->read_urb->transfer_buffer_length, ++ aircable_read_bulk_callback, port); + + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) +@@ -490,7 +492,7 @@ static void aircable_read_bulk_callback( + } + + usb_serial_debug_data(debug, &port->dev, __func__, +- urb->actual_length,urb->transfer_buffer); ++ urb->actual_length, urb->transfer_buffer); + + tty = port->tty; + if (tty && urb->actual_length) { +@@ -507,9 +509,9 @@ static void aircable_read_bulk_callback( + no_packages = urb->actual_length / (HCI_COMPLETE_FRAME); + + if (urb->actual_length % HCI_COMPLETE_FRAME != 0) +- no_packages+=1; ++ no_packages++; + +- for (i = 0; i < no_packages ;i++) { ++ for (i = 0; i < no_packages; i++) { + if (remaining > (HCI_COMPLETE_FRAME)) + package_length = HCI_COMPLETE_FRAME; + else +@@ -529,7 +531,7 @@ static void aircable_read_bulk_callback( + if (port->open_count) { + usb_fill_bulk_urb(port->read_urb, port->serial->dev, + usb_rcvbulkpipe(port->serial->dev, +- port->bulk_in_endpointAddress), ++ port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + aircable_read_bulk_callback, port); +@@ -602,7 +604,7 @@ static struct usb_serial_driver aircable + .unthrottle = aircable_unthrottle, + }; + +-static int __init aircable_init (void) ++static int __init aircable_init(void) + { + int retval; + retval = usb_serial_register(&aircable_device); +@@ -619,7 +621,7 @@ failed_usb_register: + return retval; + } + +-static void __exit aircable_exit (void) ++static void __exit aircable_exit(void) + { + usb_deregister(&aircable_driver); + usb_serial_deregister(&aircable_device); +--- a/drivers/usb/serial/airprime.c ++++ b/drivers/usb/serial/airprime.c +@@ -68,8 +68,9 @@ static int airprime_send_setup(struct us + val |= 0x02; + + return usb_control_msg(serial->dev, +- usb_rcvctrlpipe(serial->dev, 0), +- 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT); ++ usb_rcvctrlpipe(serial->dev, 0), ++ 0x22, 0x21, val, 0, NULL, 0, ++ USB_CTRL_SET_TIMEOUT); + } + + return 0; +@@ -90,17 +91,19 @@ static void airprime_read_bulk_callback( + __func__, status); + return; + } +- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); ++ usb_serial_debug_data(debug, &port->dev, __func__, ++ urb->actual_length, data); + + tty = port->tty; + if (tty && urb->actual_length) { +- tty_insert_flip_string (tty, data, urb->actual_length); +- tty_flip_buffer_push (tty); ++ tty_insert_flip_string(tty, data, urb->actual_length); ++ tty_flip_buffer_push(tty); + } + +- result = usb_submit_urb (urb, GFP_ATOMIC); ++ result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) +- dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", ++ dev_err(&port->dev, ++ "%s - failed resubmitting read urb, error %d\n", + __func__, result); + return; + } +@@ -115,7 +118,7 @@ static void airprime_write_bulk_callback + dbg("%s - port %d", __func__, port->number); + + /* free up the transfer buffer, as usb_free_urb() does not do this */ +- kfree (urb->transfer_buffer); ++ kfree(urb->transfer_buffer); + + if (status) + dbg("%s - nonzero write bulk status received: %d", +@@ -171,7 +174,7 @@ static int airprime_open(struct usb_seri + } + usb_fill_bulk_urb(urb, serial->dev, + usb_rcvbulkpipe(serial->dev, +- port->bulk_out_endpointAddress), ++ port->bulk_out_endpointAddress), + buffer, buffer_size, + airprime_read_bulk_callback, port); + result = usb_submit_urb(urb, GFP_KERNEL); +@@ -183,7 +186,8 @@ static int airprime_open(struct usb_seri + __func__, i, port->number, result); + goto errout; + } +- /* remember this urb so we can kill it when the port is closed */ ++ /* remember this urb so we can kill it when the ++ port is closed */ + priv->read_urbp[i] = urb; + } + +@@ -192,22 +196,22 @@ static int airprime_open(struct usb_seri + goto out; + + errout: +- /* some error happened, cancel any submitted urbs and clean up anything that +- got allocated successfully */ ++ /* some error happened, cancel any submitted urbs and clean up ++ anything that got allocated successfully */ + + while (i-- != 0) { + urb = priv->read_urbp[i]; + buffer = urb->transfer_buffer; +- usb_kill_urb (urb); +- usb_free_urb (urb); +- kfree (buffer); ++ usb_kill_urb(urb); ++ usb_free_urb(urb); ++ kfree(buffer); + } + + out: + return result; + } + +-static void airprime_close(struct usb_serial_port *port, struct file * filp) ++static void airprime_close(struct usb_serial_port *port, struct file *filp) + { + struct airprime_private *priv = usb_get_serial_port_data(port); + int i; +@@ -223,13 +227,13 @@ static void airprime_close(struct usb_se + mutex_unlock(&port->serial->disc_mutex); + + for (i = 0; i < NUM_READ_URBS; ++i) { +- usb_kill_urb (priv->read_urbp[i]); +- kfree (priv->read_urbp[i]->transfer_buffer); +- usb_free_urb (priv->read_urbp[i]); ++ usb_kill_urb(priv->read_urbp[i]); ++ kfree(priv->read_urbp[i]->transfer_buffer); ++ usb_free_urb(priv->read_urbp[i]); + } + + /* free up private structure */ +- kfree (priv); ++ kfree(priv); + usb_set_serial_port_data(port, NULL); + } + +@@ -259,10 +263,10 @@ static int airprime_write(struct usb_ser + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + dev_err(&port->dev, "no more free urbs\n"); +- kfree (buffer); ++ kfree(buffer); + return -ENOMEM; + } +- memcpy (buffer, buf, count); ++ memcpy(buffer, buf, count); + + usb_serial_debug_data(debug, &port->dev, __func__, count, buffer); + +@@ -279,7 +283,7 @@ static int airprime_write(struct usb_ser + "%s - usb_submit_urb(write bulk) failed with status = %d\n", + __func__, status); + count = status; +- kfree (buffer); ++ kfree(buffer); + } else { + spin_lock_irqsave(&priv->lock, flags); + ++priv->outstanding_urbs; +@@ -287,7 +291,7 @@ static int airprime_write(struct usb_ser + } + /* we are done with this urb, so let the host driver + * really free it when it is finished with it */ +- usb_free_urb (urb); ++ usb_free_urb(urb); + return count; + } + +@@ -315,8 +319,10 @@ static int __init airprime_init(void) + { + int retval; + +- airprime_device.num_ports = +- (endpoints > 0 && endpoints <= MAX_BULK_EPS) ? endpoints : NUM_BULK_EPS; ++ airprime_device.num_ports = endpoints; ++ if (endpoints < 0 || endpoints >= MAX_BULK_EPS) ++ airprime_device.num_ports = NUM_BULK_EPS; ++ + retval = usb_serial_register(&airprime_device); + if (retval) + return retval; +@@ -341,6 +347,7 @@ MODULE_LICENSE("GPL"); + module_param(debug, bool, S_IRUGO | S_IWUSR); + MODULE_PARM_DESC(debug, "Debug enabled"); + module_param(buffer_size, int, 0); +-MODULE_PARM_DESC(buffer_size, "Size of the transfer buffers in bytes (default 4096)"); ++MODULE_PARM_DESC(buffer_size, ++ "Size of the transfer buffers in bytes (default 4096)"); + module_param(endpoints, int, 0); + MODULE_PARM_DESC(endpoints, "Number of bulk EPs to configure (default 3)"); +--- a/drivers/usb/serial/ark3116.c ++++ b/drivers/usb/serial/ark3116.c +@@ -24,7 +24,7 @@ + #include <linux/usb.h> + #include <linux/usb/serial.h> + #include <linux/serial.h> +-#include <asm/uaccess.h> ++#include <linux/uaccess.h> + + + static int debug; +@@ -246,29 +246,29 @@ static void ark3116_set_termios(struct u + baud = tty_get_baud_rate(port->tty); + + switch (baud) { +- case 75: +- case 150: +- case 300: +- case 600: +- case 1200: +- case 1800: +- case 2400: +- case 4800: +- case 9600: +- case 19200: +- case 38400: +- case 57600: +- case 115200: +- case 230400: +- case 460800: +- /* Report the resulting rate back to the caller */ +- tty_encode_baud_rate(port->tty, baud, baud); +- break; +- /* set 9600 as default (if given baudrate is invalid for example) */ +- default: +- tty_encode_baud_rate(port->tty, 9600, 9600); +- case 0: +- baud = 9600; ++ case 75: ++ case 150: ++ case 300: ++ case 600: ++ case 1200: ++ case 1800: ++ case 2400: ++ case 4800: ++ case 9600: ++ case 19200: ++ case 38400: ++ case 57600: ++ case 115200: ++ case 230400: ++ case 460800: ++ /* Report the resulting rate back to the caller */ ++ tty_encode_baud_rate(port->tty, baud, baud); ++ break; ++ /* set 9600 as default (if given baudrate is invalid for example) */ ++ default: ++ tty_encode_baud_rate(port->tty, 9600, 9600); ++ case 0: ++ baud = 9600; + } + + /* +@@ -380,19 +380,19 @@ static int ark3116_ioctl(struct usb_seri + switch (cmd) { + case TIOCGSERIAL: + /* XXX: Some of these values are probably wrong. */ +- memset(&serstruct, 0, sizeof (serstruct)); ++ memset(&serstruct, 0, sizeof(serstruct)); + serstruct.type = PORT_16654; + serstruct.line = port->serial->minor; + serstruct.port = port->number; + serstruct.custom_divisor = 0; + serstruct.baud_base = 460800; + +- if (copy_to_user(user_arg, &serstruct, sizeof (serstruct))) ++ if (copy_to_user(user_arg, &serstruct, sizeof(serstruct))) + return -EFAULT; + + return 0; + case TIOCSSERIAL: +- if (copy_from_user(&serstruct, user_arg, sizeof (serstruct))) ++ if (copy_from_user(&serstruct, user_arg, sizeof(serstruct))) + return -EFAULT; + return 0; + default: +--- a/drivers/usb/serial/ch341.c ++++ b/drivers/usb/serial/ch341.c +@@ -130,7 +130,7 @@ static int ch341_get_status(struct usb_d + return -ENOMEM; + + r = ch341_control_in(dev, 0x95, 0x0706, 0, buffer, size); +- if ( r < 0) ++ if (r < 0) + goto out; + + /* Not having the datasheet for the CH341, we ignore the bytes returned |
