diff options
| author | Greg Kroah-Hartman <gregkh@suse.de> | 2008-08-06 17:04:07 -0700 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-08-06 17:04:07 -0700 |
| commit | 3e82bf52d32c3ce70099ef520b7eaa4ba7a1f89b (patch) | |
| tree | 1a6d033bf39960e98ab6f1789bbd366563d3fc7c /usb.current | |
| parent | 0f3e1982ff77f54a59c9a3e1e99a3b11001c8c70 (diff) | |
| download | patches-3e82bf52d32c3ce70099ef520b7eaa4ba7a1f89b.tar.gz | |
usb patches added
Diffstat (limited to 'usb.current')
12 files changed, 1225 insertions, 0 deletions
diff --git a/usb.current/usb-bandrich-bandluxe-c150-c250-hspa-data-card-driver.patch b/usb.current/usb-bandrich-bandluxe-c150-c250-hspa-data-card-driver.patch new file mode 100644 index 00000000000000..1b4d9c3508b718 --- /dev/null +++ b/usb.current/usb-bandrich-bandluxe-c150-c250-hspa-data-card-driver.patch @@ -0,0 +1,72 @@ +From upleong@bandrich.com Wed Aug 6 16:53:26 2008 +From: Leon Leong <upleong@bandrich.com> +Date: Fri, 1 Aug 2008 11:40:12 +0800 +Subject: USB: BandRich BandLuxe C150/C250 HSPA Data Card Driver +To: smurf@smurf.noris.de +Cc: linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org +Message-ID: <5ECB2A60-5E13-4DE1-86A1-6FA12DBCEF66@bandrich.com> + + +From: Leon Leong <upleong@bandrich.com> + +This patch adds the Product ID for the BandLuxe C150/C250 3.5G data +card series from BandRich Inc. +After detection, the data card works fine. + +It was patched against kernel 2.6.27-rc1 with -mm patch + +Signed-off-by: Leon Leong <upleong@bandrich.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/option.c | 32 ++++++++++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -186,6 +186,23 @@ static int option_send_setup(struct tty + #define BANDRICH_VENDOR_ID 0x1A8D + #define BANDRICH_PRODUCT_C100_1 0x1002 + #define BANDRICH_PRODUCT_C100_2 0x1003 ++#define BANDRICH_PRODUCT_1004 0x1004 ++#define BANDRICH_PRODUCT_1005 0x1005 ++#define BANDRICH_PRODUCT_1006 0x1006 ++#define BANDRICH_PRODUCT_1007 0x1007 ++#define BANDRICH_PRODUCT_1008 0x1008 ++#define BANDRICH_PRODUCT_1009 0x1009 ++#define BANDRICH_PRODUCT_100A 0x100a ++ ++#define BANDRICH_PRODUCT_100B 0x100b ++#define BANDRICH_PRODUCT_100C 0x100c ++#define BANDRICH_PRODUCT_100D 0x100d ++#define BANDRICH_PRODUCT_100E 0x100e ++ ++#define BANDRICH_PRODUCT_100F 0x100f ++#define BANDRICH_PRODUCT_1010 0x1010 ++#define BANDRICH_PRODUCT_1011 0x1011 ++#define BANDRICH_PRODUCT_1012 0x1012 + + #define AMOI_VENDOR_ID 0x1614 + #define AMOI_PRODUCT_9508 0x0800 +@@ -302,6 +319,21 @@ static struct usb_device_id option_ids[] + { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) }, + { 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_1004) }, ++ { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1005) }, ++ { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1006) }, ++ { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1007) }, ++ { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1008) }, ++ { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1009) }, ++ { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100A) }, ++ { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100B) }, ++ { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100C) }, ++ { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100D) }, ++ { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100E) }, ++ { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100F) }, ++ { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1010) }, ++ { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1011) }, ++ { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012) }, + { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) }, + { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) }, + { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */ diff --git a/usb.current/usb-cdc-acm.c-fix-compile-warnings.patch b/usb.current/usb-cdc-acm.c-fix-compile-warnings.patch new file mode 100644 index 00000000000000..33acdffb284b2c --- /dev/null +++ b/usb.current/usb-cdc-acm.c-fix-compile-warnings.patch @@ -0,0 +1,34 @@ +From tiwai@suse.de Wed Aug 6 16:54:23 2008 +From: Takashi Iwai <tiwai@suse.de> +Date: Thu, 31 Jul 2008 19:06:13 +0200 +Subject: USB: cdc-acm.c: Fix compile warnings +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: Andrew Morton <akpm@linux-foundation.org>, linux-kernel@vger.kernel.org +Message-ID: <s5hmyjyj856.wl%tiwai@suse.de> + + +The irq flags should be unsigned long. + + CC [M] drivers/usb/class/cdc-acm.o +drivers/usb/class/cdc-acm.c: In function 'acm_waker': +drivers/usb/class/cdc-acm.c:527: warning: comparison of distinct pointer types lacks a cast +drivers/usb/class/cdc-acm.c:529: warning: comparison of distinct pointer types lacks a cast + +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/class/cdc-acm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -512,7 +512,7 @@ static void acm_softint(struct work_stru + static void acm_waker(struct work_struct *waker) + { + struct acm *acm = container_of(waker, struct acm, waker); +- long flags; ++ unsigned long flags; + int rv; + + rv = usb_autopm_get_interface(acm->control); diff --git a/usb.current/usb-ftdi_sio-add-support-for-phi-fisco-data-cable.patch b/usb.current/usb-ftdi_sio-add-support-for-phi-fisco-data-cable.patch new file mode 100644 index 00000000000000..0192abf0ea7c3b --- /dev/null +++ b/usb.current/usb-ftdi_sio-add-support-for-phi-fisco-data-cable.patch @@ -0,0 +1,42 @@ +From lross@mail.ru Wed Aug 6 16:52:44 2008 +From: Lex Ross <lross@mail.ru> +Date: Wed, 06 Aug 2008 16:25:08 +0400 +Subject: USB: ftdi_sio: add support for PHI Fisco data cable (FT232BM based, VID/PID 0403:e40b) +To: linux-usb@vger.kernel.org +Message-ID: <E1KQi4i-0000Bj-00.lross-mail-ru@f102.mail.ru> + + +Support for PHI Fisco USB to Serial data cable (FTDI FT232BM based). +PHI Fisco cable is supplied for connecting Philips Xenium 9@9++ mobile phones. +PIDs were missing. + +Tested successfully with PHI Fisco Data Cable (VID/PID 0403:e40b) + +Signed-off-by: Lex V. Ross <lross@mail.ru> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/ftdi_sio.c | 1 + + drivers/usb/serial/ftdi_sio.h | 1 + + 2 files changed, 2 insertions(+) + +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -638,6 +638,7 @@ static struct usb_device_id id_table_com + { USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) }, + { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) }, ++ { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) }, + { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) }, +--- a/drivers/usb/serial/ftdi_sio.h ++++ b/drivers/usb/serial/ftdi_sio.h +@@ -526,6 +526,7 @@ + #define FTDI_ELV_WS500_PID 0xE0E9 /* PC-Wetterstation (WS 500) */ + #define FTDI_ELV_HS485_PID 0xE0EA /* USB to RS-485 adapter */ + #define FTDI_ELV_EM1010PC_PID 0xE0EF /* Engery monitor EM 1010 PC */ ++#define FTDI_PHI_FISCO_PID 0xE40B /* PHI Fisco USB to Serial cable */ + + /* + * Definitions for ID TECH (www.idt-net.com) devices diff --git a/usb.current/usb-hook-start_hnp-into-ohci-struct.patch b/usb.current/usb-hook-start_hnp-into-ohci-struct.patch new file mode 100644 index 00000000000000..a27209425485e7 --- /dev/null +++ b/usb.current/usb-hook-start_hnp-into-ohci-struct.patch @@ -0,0 +1,60 @@ +From dbaryshkov@gmail.com Wed Aug 6 16:42:44 2008 +From: Dmitry Baryshkov <dbaryshkov@gmail.com> +Date: Sun, 6 Jul 2008 14:26:30 +0400 +Subject: USB: Hook start_hnp into ohci struct +To: linux-usb@vger.kernel.org +Message-ID: <20080706102630.GA29934@doriath.ww600.siemens.net> +Content-Disposition: inline + + +Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com> +Acked-by: David Brownell <dbrownell@users.sourceforge.net> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + drivers/usb/host/ohci-hub.c | 4 +--- + drivers/usb/host/ohci-omap.c | 1 + + drivers/usb/host/ohci.h | 1 + + 3 files changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/usb/host/ohci.h ++++ b/drivers/usb/host/ohci.h +@@ -371,6 +371,7 @@ struct ohci_hcd { + * other external transceivers should be software-transparent + */ + struct otg_transceiver *transceiver; ++ void (*start_hnp)(struct ohci_hcd *ohci); + + /* + * memory management for queue data structures +--- a/drivers/usb/host/ohci-hub.c ++++ b/drivers/usb/host/ohci-hub.c +@@ -579,8 +579,6 @@ static int ohci_start_port_reset (struct + return 0; + } + +-static void start_hnp(struct ohci_hcd *ohci); +- + #else + + #define ohci_start_port_reset NULL +@@ -767,7 +765,7 @@ static int ohci_hub_control ( + #ifdef CONFIG_USB_OTG + if (hcd->self.otg_port == (wIndex + 1) + && hcd->self.b_hnp_enable) +- start_hnp(ohci); ++ ohci->start_hnp(ohci); + else + #endif + ohci_writel (ohci, RH_PS_PSS, +--- a/drivers/usb/host/ohci-omap.c ++++ b/drivers/usb/host/ohci-omap.c +@@ -225,6 +225,7 @@ static int ohci_omap_init(struct usb_hcd + dev_err(hcd->self.controller, "can't find transceiver\n"); + return -ENODEV; + } ++ ohci->start_hnp = start_hnp; + } + #endif + diff --git a/usb.current/usb-isp1760-don-t-be-noisy-about-short-packets.patch b/usb.current/usb-isp1760-don-t-be-noisy-about-short-packets.patch new file mode 100644 index 00000000000000..ec1caf48c9d904 --- /dev/null +++ b/usb.current/usb-isp1760-don-t-be-noisy-about-short-packets.patch @@ -0,0 +1,54 @@ +From sebastian@breakpoint.cc Wed Aug 6 16:48:32 2008 +From: Sebastian Siewior <sebastian@breakpoint.cc> +Date: Thu, 17 Jul 2008 20:09:29 +0200 +Subject: usb: isp1760: don't be noisy about short packets. +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org, Sebastian Siewior <sebastian@breakpoint.cc>, Alan Stern <stern@rowland.harvard.edu> +Message-ID: <1216318170-23126-2-git-send-email-sebastian@breakpoint.cc> + + +According to Alan Stern, short packets are quite normal under +certain circumstances. This printk was triggered by usb to +serial converters on every packet and some usb sticks triggered +a few of those while plugging the stick. +This printks are now hidden unless USB debug mode is activated. + +Cc: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Sebastian Siewior <sebastian@breakpoint.cc> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + drivers/usb/host/isp1760-hcd.c | 6 +++--- + drivers/usb/host/isp1760-hcd.h | 3 +++ + 2 files changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/usb/host/isp1760-hcd.c ++++ b/drivers/usb/host/isp1760-hcd.c +@@ -1128,11 +1128,11 @@ static void do_atl_int(struct usb_hcd *u + } else if (usb_pipebulk(urb->pipe) && (length < qtd->length)) { + /* short BULK received */ + +- printk(KERN_ERR "short bulk, %d instead %zu\n", length, +- qtd->length); + if (urb->transfer_flags & URB_SHORT_NOT_OK) { + urb->status = -EREMOTEIO; +- printk(KERN_ERR "not okey\n"); ++ isp1760_dbg(priv, "short bulk, %d instead %zu " ++ "with URB_SHORT_NOT_OK flag.\n", ++ length, qtd->length); + } + + if (urb->status == -EINPROGRESS) +--- a/drivers/usb/host/isp1760-hcd.h ++++ b/drivers/usb/host/isp1760-hcd.h +@@ -121,6 +121,9 @@ struct inter_packet_info { + typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh, + struct isp1760_qtd *qtd); + ++#define isp1760_dbg(priv, fmt, args...) \ ++ dev_dbg(priv_to_hcd(priv)->self.controller, fmt, ##args) ++ + #define isp1760_info(priv, fmt, args...) \ + dev_info(priv_to_hcd(priv)->self.controller, fmt, ##args) + diff --git a/usb.current/usb-isp1760-improve-pre-fetch-timing.patch b/usb.current/usb-isp1760-improve-pre-fetch-timing.patch new file mode 100644 index 00000000000000..dd4abb2203accf --- /dev/null +++ b/usb.current/usb-isp1760-improve-pre-fetch-timing.patch @@ -0,0 +1,143 @@ +From sebastian@breakpoint.cc Wed Aug 6 16:48:19 2008 +From: Sebastian Siewior <sebastian@breakpoint.cc> +Date: Thu, 17 Jul 2008 20:09:30 +0200 +Subject: usb: ISP1760: improve pre-fetch timing +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org, Enrico Scholz <enrico.scholz@sigma-chemnitz.de>, Sebastian Siewior <bigeasy@linutronix.de> +Message-ID: <1216318170-23126-3-git-send-email-sebastian@breakpoint.cc> + + +From: Enrico Scholz <enrico.scholz@sigma-chemnitz.de> + +ISP1760 requires a delay of 90ns between programming the address and +reading the data. Current driver solves this by a mdelay(1) which is +very heavy weighted and slow. This patch applies the workaround from +the ISP1760 FAQ by using two different banks for PTD and payload data +and using a common wait for them. This wait is done by an additional +ISP1760 access (whose timing constraints guarantee the 90ns delay). +This improves speed when reading from an USB stick from: + + $ time dd if=/dev/sda of=/dev/zero bs=65536 count=1638 + real 1m 15.43s + user 0m 0.44s + sys 0m 39.46s + +to + + $ time dd if=/dev/sda of=/dev/zero bs=65536 count=1638 + real 0m 18.53s + user 0m 0.16s + sys 0m 12.97s + +[bigeasy@linutronix.de: fixed comment formating, moved define into + header file, obey 80 char rule] + +Signed-off-by: Enrico Scholz <enrico.scholz@sigma-chemnitz.de> +Signed-off-by: Sebastian Siewior <bigeasy@linutronix.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/isp1760-hcd.c | 44 ++++++++++++++++++++++++++++------------- + drivers/usb/host/isp1760-hcd.h | 2 + + 2 files changed, 33 insertions(+), 13 deletions(-) + +--- a/drivers/usb/host/isp1760-hcd.c ++++ b/drivers/usb/host/isp1760-hcd.c +@@ -126,9 +126,8 @@ static void isp1760_writel(const unsigne + * doesn't quite work because some people have to enforce 32-bit access + */ + static void priv_read_copy(struct isp1760_hcd *priv, u32 *src, +- __u32 __iomem *dst, u32 offset, u32 len) ++ __u32 __iomem *dst, u32 len) + { +- struct usb_hcd *hcd = priv_to_hcd(priv); + u32 val; + u8 *buff8; + +@@ -136,11 +135,6 @@ static void priv_read_copy(struct isp176 + printk(KERN_ERR "ERROR: buffer: %p len: %d\n", src, len); + return; + } +- isp1760_writel(offset, hcd->regs + HC_MEMORY_REG); +- /* XXX +- * 90nsec delay, the spec says something how this could be avoided. +- */ +- mdelay(1); + + while (len >= 4) { + *src = __raw_readl(dst); +@@ -987,8 +981,20 @@ static void do_atl_int(struct usb_hcd *u + printk(KERN_ERR "qh is 0\n"); + continue; + } +- priv_read_copy(priv, (u32 *)&ptd, usb_hcd->regs + atl_regs, +- atl_regs, sizeof(ptd)); ++ isp1760_writel(atl_regs + ISP_BANK(0), usb_hcd->regs + ++ HC_MEMORY_REG); ++ isp1760_writel(payload + ISP_BANK(1), usb_hcd->regs + ++ HC_MEMORY_REG); ++ /* ++ * write bank1 address twice to ensure the 90ns delay (time ++ * between BANK0 write and the priv_read_copy() call is at ++ * least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 92ns) ++ */ ++ isp1760_writel(payload + ISP_BANK(1), usb_hcd->regs + ++ HC_MEMORY_REG); ++ ++ priv_read_copy(priv, (u32 *)&ptd, usb_hcd->regs + atl_regs + ++ ISP_BANK(0), sizeof(ptd)); + + dw1 = le32_to_cpu(ptd.dw1); + dw2 = le32_to_cpu(ptd.dw2); +@@ -1091,7 +1097,7 @@ static void do_atl_int(struct usb_hcd *u + case IN_PID: + priv_read_copy(priv, + priv->atl_ints[queue_entry].data_buffer, +- usb_hcd->regs + payload, payload, ++ usb_hcd->regs + payload + ISP_BANK(1), + length); + + case OUT_PID: +@@ -1206,8 +1212,20 @@ static void do_intl_int(struct usb_hcd * + continue; + } + +- priv_read_copy(priv, (u32 *)&ptd, usb_hcd->regs + int_regs, +- int_regs, sizeof(ptd)); ++ isp1760_writel(int_regs + ISP_BANK(0), usb_hcd->regs + ++ HC_MEMORY_REG); ++ isp1760_writel(payload + ISP_BANK(1), usb_hcd->regs + ++ HC_MEMORY_REG); ++ /* ++ * write bank1 address twice to ensure the 90ns delay (time ++ * between BANK0 write and the priv_read_copy() call is at ++ * least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 92ns) ++ */ ++ isp1760_writel(payload + ISP_BANK(1), usb_hcd->regs + ++ HC_MEMORY_REG); ++ ++ priv_read_copy(priv, (u32 *)&ptd, usb_hcd->regs + int_regs + ++ ISP_BANK(0), sizeof(ptd)); + dw1 = le32_to_cpu(ptd.dw1); + dw3 = le32_to_cpu(ptd.dw3); + check_int_err_status(le32_to_cpu(ptd.dw4)); +@@ -1242,7 +1260,7 @@ static void do_intl_int(struct usb_hcd * + case IN_PID: + priv_read_copy(priv, + priv->int_ints[queue_entry].data_buffer, +- usb_hcd->regs + payload , payload, ++ usb_hcd->regs + payload + ISP_BANK(1), + length); + case OUT_PID: + +--- a/drivers/usb/host/isp1760-hcd.h ++++ b/drivers/usb/host/isp1760-hcd.h +@@ -54,6 +54,8 @@ void deinit_kmem_cache(void); + #define BUFFER_MAP 0x7 + + #define HC_MEMORY_REG 0x33c ++#define ISP_BANK(x) ((x) << 16) ++ + #define HC_PORT1_CTRL 0x374 + #define PORT1_POWER (3 << 3) + #define PORT1_INIT1 (1 << 7) diff --git a/usb.current/usb-ohci-make-distrust_firmware-a-quirk.patch b/usb.current/usb-ohci-make-distrust_firmware-a-quirk.patch new file mode 100644 index 00000000000000..177a8358a2bed9 --- /dev/null +++ b/usb.current/usb-ohci-make-distrust_firmware-a-quirk.patch @@ -0,0 +1,65 @@ +From dbaryshkov@gmail.com Wed Aug 6 16:42:01 2008 +From: Dmitry Baryshkov <dbaryshkov@gmail.com> +Date: Sun, 6 Jul 2008 23:35:01 +0400 +Subject: USB: ohci: make distrust_firmware a quirk +To: Alan Stern <stern@rowland.harvard.edu> +Cc: linux-usb@vger.kernel.org +Message-ID: <20080706193501.GA14976@doriath.ww600.siemens.net> +Content-Disposition: inline + +From: Dmitry Baryshkov <dbaryshkov@gmail.com> + +Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com> +Acked-by: David Brownell <dbrownell@users.sourceforge.net> +Cc: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/ohci-hcd.c | 6 +++++- + drivers/usb/host/ohci-omap.c | 2 +- + drivers/usb/host/ohci.h | 1 + + 3 files changed, 7 insertions(+), 2 deletions(-) + +--- a/drivers/usb/host/ohci.h ++++ b/drivers/usb/host/ohci.h +@@ -399,6 +399,7 @@ struct ohci_hcd { + #define OHCI_QUIRK_ZFMICRO 0x20 /* Compaq ZFMicro chipset*/ + #define OHCI_QUIRK_NEC 0x40 /* lost interrupts */ + #define OHCI_QUIRK_FRAME_NO 0x80 /* no big endian frame_no shift */ ++#define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */ + // there are also chip quirks/bugs in init logic + + struct work_struct nec_work; /* Worker for NEC quirk */ +--- a/drivers/usb/host/ohci-hcd.c ++++ b/drivers/usb/host/ohci-hcd.c +@@ -483,6 +483,9 @@ static int ohci_init (struct ohci_hcd *o + int ret; + struct usb_hcd *hcd = ohci_to_hcd(ohci); + ++ if (distrust_firmware) ++ ohci->flags |= OHCI_QUIRK_HUB_POWER; ++ + disable (ohci); + ohci->regs = hcd->regs; + +@@ -689,7 +692,8 @@ retry: + temp |= RH_A_NOCP; + temp &= ~(RH_A_POTPGT | RH_A_NPS); + ohci_writel (ohci, temp, &ohci->regs->roothub.a); +- } else if ((ohci->flags & OHCI_QUIRK_AMD756) || distrust_firmware) { ++ } else if ((ohci->flags & OHCI_QUIRK_AMD756) || ++ (ohci->flags & OHCI_QUIRK_HUB_POWER)) { + /* hub power always on; required for AMD-756 and some + * Mac platforms. ganged overcurrent reporting, if any. + */ +--- a/drivers/usb/host/ohci-omap.c ++++ b/drivers/usb/host/ohci-omap.c +@@ -260,7 +260,7 @@ static int ohci_omap_init(struct usb_hcd + omap_cfg_reg(W4_USB_HIGHZ); + } + ohci_writel(ohci, rh, &ohci->regs->roothub.a); +- distrust_firmware = 0; ++ ohci->flags &= ~OHCI_QUIRK_HUB_POWER; + } else if (machine_is_nokia770()) { + /* We require a self-powered hub, which should have + * plenty of power. */ diff --git a/usb.current/usb-omap_udc-fix-compilation-with-debug-enabled.patch b/usb.current/usb-omap_udc-fix-compilation-with-debug-enabled.patch new file mode 100644 index 00000000000000..f158748d723b92 --- /dev/null +++ b/usb.current/usb-omap_udc-fix-compilation-with-debug-enabled.patch @@ -0,0 +1,37 @@ +From dbaryshkov@gmail.com Wed Aug 6 16:41:16 2008 +From: Dmitry Baryshkov <dbaryshkov@gmail.com> +Date: Sun, 6 Jul 2008 14:25:53 +0400 +Subject: USB: omap_udc: fix compilation with debug enabled +To: linux-usb@vger.kernel.org +Message-ID: <20080706102553.GA29914@doriath.ww600.siemens.net> +Content-Disposition: inline + + +Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com> +Acked-by: David Brownell <dbrownell@users.sourceforge.net> +Cc: stable <stable@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/gadget/omap_udc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/usb/gadget/omap_udc.c ++++ b/drivers/usb/gadget/omap_udc.c +@@ -54,6 +54,7 @@ + + #include <asm/arch/dma.h> + #include <asm/arch/usb.h> ++#include <asm/arch/control.h> + + #include "omap_udc.h" + +@@ -2313,7 +2314,7 @@ static int proc_otg_show(struct seq_file + tmp = OTG_REV_REG; + if (cpu_is_omap24xx()) { + ctrl_name = "control_devconf"; +- trans = CONTROL_DEVCONF_REG; ++ trans = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); + } else { + ctrl_name = "tranceiver_ctrl"; + trans = omap_readw(USB_TRANSCEIVER_CTRL); diff --git a/usb.current/usb-quirk-pll-power-down-mode.patch b/usb.current/usb-quirk-pll-power-down-mode.patch new file mode 100644 index 00000000000000..24f292073ed2a8 --- /dev/null +++ b/usb.current/usb-quirk-pll-power-down-mode.patch @@ -0,0 +1,260 @@ +From Libin.Yang@amd.com Wed Aug 6 16:45:35 2008 +From: Libin Yang <Libin.Yang@amd.com> +Date: Thu, 31 Jul 2008 10:31:50 +0800 +Subject: USB: quirk PLL power down mode +To: David Brownell <david-b@pacbell.net> +Cc: Greg KH <gregkh@suse.de>, linux-usb@vger.kernel.org, oliver@neukum.org, stern@rowland.harvard.edu +Message-ID: <1217471510.5418.3.camel@crane-laptop> + + +On some AMD 700 series southbridges, ISO OUT transfers (such as audio +playback through speakers) on the USB OHCI controller may be corrupted +when an A-Link express power saving feature is active. + +PLL power down mode in conjunction with link power management feature +L1 being enabled is the bad combination ... this patch prevents them +from being enabled when ISO transfers are pending. + +Signed-off-by: Crane Cai <crane.cai@amd.com> +Signed-off-by: Libin Yang <libin.yang@amd.com> +Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/ohci-hcd.c | 2 + drivers/usb/host/ohci-pci.c | 132 ++++++++++++++++++++++++++++++++++++++++++++ + drivers/usb/host/ohci-q.c | 6 ++ + drivers/usb/host/ohci.h | 20 ++++++ + 4 files changed, 160 insertions(+) + +--- a/drivers/usb/host/ohci.h ++++ b/drivers/usb/host/ohci.h +@@ -401,6 +401,7 @@ struct ohci_hcd { + #define OHCI_QUIRK_NEC 0x40 /* lost interrupts */ + #define OHCI_QUIRK_FRAME_NO 0x80 /* no big endian frame_no shift */ + #define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */ ++#define OHCI_QUIRK_AMD_ISO 0x200 /* ISO transfers*/ + // there are also chip quirks/bugs in init logic + + struct work_struct nec_work; /* Worker for NEC quirk */ +@@ -428,6 +429,12 @@ static inline int quirk_zfmicro(struct o + { + return ohci->flags & OHCI_QUIRK_ZFMICRO; + } ++static inline int quirk_amdiso(struct ohci_hcd *ohci) ++{ ++ return ohci->flags & OHCI_QUIRK_AMD_ISO; ++} ++static void quirk_amd_pll(int state); ++static void amd_iso_dev_put(void); + #else + static inline int quirk_nec(struct ohci_hcd *ohci) + { +@@ -437,6 +444,19 @@ static inline int quirk_zfmicro(struct o + { + return 0; + } ++static inline int quirk_amdiso(struct ohci_hcd *ohci) ++{ ++ return 0; ++} ++ ++static inline void quirk_amd_pll(int state) ++{ ++ return; ++} ++static inline void amd_iso_dev_put(void) ++{ ++ return; ++} + #endif + + /* convert between an hcd pointer and the corresponding ohci_hcd */ +--- a/drivers/usb/host/ohci-hcd.c ++++ b/drivers/usb/host/ohci-hcd.c +@@ -886,6 +886,8 @@ static void ohci_stop (struct usb_hcd *h + + if (quirk_zfmicro(ohci)) + del_timer(&ohci->unlink_watchdog); ++ if (quirk_amdiso(ohci)) ++ amd_iso_dev_put(); + + remove_debug_files (ohci); + ohci_mem_cleanup (ohci); +--- a/drivers/usb/host/ohci-pci.c ++++ b/drivers/usb/host/ohci-pci.c +@@ -18,6 +18,28 @@ + #error "This file is PCI bus glue. CONFIG_PCI must be defined." + #endif + ++#include <linux/pci.h> ++#include <linux/io.h> ++ ++ ++/* constants used to work around PM-related transfer ++ * glitches in some AMD 700 series southbridges ++ */ ++#define AB_REG_BAR 0xf0 ++#define AB_INDX(addr) ((addr) + 0x00) ++#define AB_DATA(addr) ((addr) + 0x04) ++#define AX_INDXC 0X30 ++#define AX_DATAC 0x34 ++ ++#define NB_PCIE_INDX_ADDR 0xe0 ++#define NB_PCIE_INDX_DATA 0xe4 ++#define PCIE_P_CNTL 0x10040 ++#define BIF_NB 0x10002 ++ ++static struct pci_dev *amd_smbus_dev; ++static struct pci_dev *amd_hb_dev; ++static int amd_ohci_iso_count; ++ + /*-------------------------------------------------------------------------*/ + + static int broken_suspend(struct usb_hcd *hcd) +@@ -143,6 +165,103 @@ static int ohci_quirk_nec(struct usb_hcd + return 0; + } + ++static int ohci_quirk_amd700(struct usb_hcd *hcd) ++{ ++ struct ohci_hcd *ohci = hcd_to_ohci(hcd); ++ u8 rev = 0; ++ ++ if (!amd_smbus_dev) ++ amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, ++ PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL); ++ if (!amd_smbus_dev) ++ return 0; ++ ++ pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev); ++ if ((rev > 0x3b) || (rev < 0x30)) { ++ pci_dev_put(amd_smbus_dev); ++ amd_smbus_dev = NULL; ++ return 0; ++ } ++ ++ amd_ohci_iso_count++; ++ ++ if (!amd_hb_dev) ++ amd_hb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x9600, NULL); ++ ++ ohci->flags |= OHCI_QUIRK_AMD_ISO; ++ ohci_dbg(ohci, "enabled AMD ISO transfers quirk\n"); ++ ++ return 0; ++} ++ ++/* ++ * The hardware normally enables the A-link power management feature, which ++ * lets the system lower the power consumption in idle states. ++ * ++ * Assume the system is configured to have USB 1.1 ISO transfers going ++ * to or from a USB device. Without this quirk, that stream may stutter ++ * or have breaks occasionally. For transfers going to speakers, this ++ * makes a very audible mess... ++ * ++ * That audio playback corruption is due to the audio stream getting ++ * interrupted occasionally when the link goes in lower power state ++ * This USB quirk prevents the link going into that lower power state ++ * during audio playback or other ISO operations. ++ */ ++static void quirk_amd_pll(int on) ++{ ++ u32 addr; ++ u32 val; ++ u32 bit = (on > 0) ? 1 : 0; ++ ++ pci_read_config_dword(amd_smbus_dev, AB_REG_BAR, &addr); ++ ++ /* BIT names/meanings are NDA-protected, sorry ... */ ++ ++ outl(AX_INDXC, AB_INDX(addr)); ++ outl(0x40, AB_DATA(addr)); ++ outl(AX_DATAC, AB_INDX(addr)); ++ val = inl(AB_DATA(addr)); ++ val &= ~((1 << 3) | (1 << 4) | (1 << 9)); ++ val |= (bit << 3) | ((!bit) << 4) | ((!bit) << 9); ++ outl(val, AB_DATA(addr)); ++ ++ if (amd_hb_dev) { ++ addr = PCIE_P_CNTL; ++ pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_ADDR, addr); ++ ++ pci_read_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, &val); ++ val &= ~(1 | (1 << 3) | (1 << 4) | (1 << 9) | (1 << 12)); ++ val |= bit | (bit << 3) | (bit << 12); ++ val |= ((!bit) << 4) | ((!bit) << 9); ++ pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, val); ++ ++ addr = BIF_NB; ++ pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_ADDR, addr); ++ ++ pci_read_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, &val); ++ val &= ~(1 << 8); ++ val |= bit << 8; ++ pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, val); ++ } ++} ++ ++static void amd_iso_dev_put(void) ++{ ++ amd_ohci_iso_count--; ++ if (amd_ohci_iso_count == 0) { ++ if (amd_smbus_dev) { ++ pci_dev_put(amd_smbus_dev); ++ amd_smbus_dev = NULL; ++ } ++ if (amd_hb_dev) { ++ pci_dev_put(amd_hb_dev); ++ amd_hb_dev = NULL; ++ } ++ } ++ ++} ++ + /* List of quirks for OHCI */ + static const struct pci_device_id ohci_pci_quirks[] = { + { +@@ -181,6 +300,19 @@ static const struct pci_device_id ohci_p + PCI_DEVICE(PCI_VENDOR_ID_ITE, 0x8152), + .driver_data = (unsigned long) broken_suspend, + }, ++ { ++ PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4397), ++ .driver_data = (unsigned long)ohci_quirk_amd700, ++ }, ++ { ++ PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4398), ++ .driver_data = (unsigned long)ohci_quirk_amd700, ++ }, ++ { ++ PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399), ++ .driver_data = (unsigned long)ohci_quirk_amd700, ++ }, ++ + /* FIXME for some of the early AMD 760 southbridges, OHCI + * won't work at all. blacklist them. + */ +--- a/drivers/usb/host/ohci-q.c ++++ b/drivers/usb/host/ohci-q.c +@@ -49,6 +49,9 @@ __acquires(ohci->lock) + switch (usb_pipetype (urb->pipe)) { + case PIPE_ISOCHRONOUS: + ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs--; ++ if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0 ++ && quirk_amdiso(ohci)) ++ quirk_amd_pll(1); + break; + case PIPE_INTERRUPT: + ohci_to_hcd(ohci)->self.bandwidth_int_reqs--; +@@ -677,6 +680,9 @@ static void td_submit_urb ( + data + urb->iso_frame_desc [cnt].offset, + urb->iso_frame_desc [cnt].length, urb, cnt); + } ++ if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0 ++ && quirk_amdiso(ohci)) ++ quirk_amd_pll(0); + periodic = ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs++ == 0 + && ohci_to_hcd(ohci)->self.bandwidth_int_reqs == 0; + break; diff --git a/usb.current/usb-return-error-code-instead-of-0-in-the-enqueue-function.patch b/usb.current/usb-return-error-code-instead-of-0-in-the-enqueue-function.patch new file mode 100644 index 00000000000000..c1554780d7c265 --- /dev/null +++ b/usb.current/usb-return-error-code-instead-of-0-in-the-enqueue-function.patch @@ -0,0 +1,32 @@ +From sebastian@breakpoint.cc Wed Aug 6 16:48:04 2008 +From: Sebastian Siewior <sebastian@breakpoint.cc> +Date: Thu, 17 Jul 2008 20:09:28 +0200 +Subject: usb: return error code instead of 0 in the enqueue function. +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org, Sebastian Siewior <sebastian@breakpoint.cc> +Message-ID: <1216318170-23126-1-git-send-email-sebastian@breakpoint.cc> + + +if the enqueue function returns -ESHUTDOWN or -ENOMEM then +we return 0 instead of an error. This leads to a timeout and +then to a dequeue request of an not enqueued urb. + +Signed-off-by: Sebastian Siewior <sebastian@breakpoint.cc> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/isp1760-hcd.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/usb/host/isp1760-hcd.c ++++ b/drivers/usb/host/isp1760-hcd.c +@@ -1615,8 +1615,7 @@ static int isp1760_urb_enqueue(struct us + return -EPIPE; + } + +- isp1760_prepare_enqueue(priv, urb, &qtd_list, mem_flags, pe); +- return 0; ++ return isp1760_prepare_enqueue(priv, urb, &qtd_list, mem_flags, pe); + } + + static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, diff --git a/usb.current/usb-serial-gadget-rx-path-data-loss-fixes.patch b/usb.current/usb-serial-gadget-rx-path-data-loss-fixes.patch new file mode 100644 index 00000000000000..71978257a053d4 --- /dev/null +++ b/usb.current/usb-serial-gadget-rx-path-data-loss-fixes.patch @@ -0,0 +1,391 @@ +From david-b@pacbell.net Wed Aug 6 16:44:52 2008 +From: David Brownell <david-b@pacbell.net> +Date: Mon, 7 Jul 2008 12:16:08 -0700 +Subject: USB: serial gadget: rx path data loss fixes +To: Greg KH <greg@kroah.com> +Cc: linux-usb@vger.kernel.org, Alan Cox <alan@lxorguk.ukuu.org.uk>, Matthieu CASTET <matthieu.castet@parrot.com> +Message-ID: <200807071216.09106.david-b@pacbell.net> +Content-Disposition: inline + + +From: David Brownell <dbrownell@users.sourceforge.net> + +Update RX path handling in new serial gadget code to cope better with +RX blockage: queue every RX packet until its contents can safely be +passed up to the ldisc. Most of the RX path work is now done in the +RX tasklet, instead of just the final "push to ldisc" step. This +addresses some cases of data loss: + + - A longstanding serial gadget bug: when tty_insert_flip_string() + didn't copy the entire buffer, the rest of the characters were + dropped! Now that packet stays queued until the rest of its data + is pushed to the ldisc. + + - Another longstanding issue: in the unlikely case that an RX + transfer returns data and also reports a fault, that data is + no longer discarded. + + - In the recently added RX throttling logic: it needs to stop + pushing data into the TTY layer, instead of just not submitting + new USB read requests. When the TTY is throttled long enough, + backpressure will eventually make the OUT endpoint NAK. + +Also: an #ifdef is removed (no longer necessary); and start switching +to a better convention for debug messages (prefix them with tty name). + +Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/gadget/u_serial.c | 236 +++++++++++++++++++++++++----------------- + 1 file changed, 146 insertions(+), 90 deletions(-) + +--- a/drivers/usb/gadget/u_serial.c ++++ b/drivers/usb/gadget/u_serial.c +@@ -52,6 +52,8 @@ + * is managed in userspace ... OBEX, PTP, and MTP have been mentioned. + */ + ++#define PREFIX "ttyGS" ++ + /* + * gserial is the lifecycle interface, used by USB functions + * gs_port is the I/O nexus, used by the tty driver +@@ -100,6 +102,8 @@ struct gs_port { + wait_queue_head_t close_wait; /* wait for last close */ + + struct list_head read_pool; ++ struct list_head read_queue; ++ unsigned n_read; + struct tasklet_struct push; + + struct list_head write_pool; +@@ -367,11 +371,9 @@ __acquires(&port->port_lock) + req->length = len; + list_del(&req->list); + +-#ifdef VERBOSE_DEBUG +- pr_debug("%s: %s, len=%d, 0x%02x 0x%02x 0x%02x ...\n", +- __func__, in->name, len, *((u8 *)req->buf), ++ pr_vdebug(PREFIX "%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n", ++ port->port_num, len, *((u8 *)req->buf), + *((u8 *)req->buf+1), *((u8 *)req->buf+2)); +-#endif + + /* Drop lock while we call out of driver; completions + * could be issued while we do so. Disconnection may +@@ -401,56 +403,6 @@ __acquires(&port->port_lock) + return status; + } + +-static void gs_rx_push(unsigned long _port) +-{ +- struct gs_port *port = (void *)_port; +- struct tty_struct *tty = port->port_tty; +- +- /* With low_latency, tty_flip_buffer_push() doesn't put its +- * real work through a workqueue, so the ldisc has a better +- * chance to keep up with peak USB data rates. +- */ +- if (tty) { +- tty_flip_buffer_push(tty); +- wake_up_interruptible(&tty->read_wait); +- } +-} +- +-/* +- * gs_recv_packet +- * +- * Called for each USB packet received. Reads the packet +- * header and stuffs the data in the appropriate tty buffer. +- * Returns 0 if successful, or a negative error number. +- * +- * Called during USB completion routine, on interrupt time. +- * With port_lock. +- */ +-static int gs_recv_packet(struct gs_port *port, char *packet, unsigned size) +-{ +- unsigned len; +- struct tty_struct *tty; +- +- /* I/O completions can continue for a while after close(), until the +- * request queue empties. Just discard any data we receive, until +- * something reopens this TTY ... as if there were no HW flow control. +- */ +- tty = port->port_tty; +- if (tty == NULL) { +- pr_vdebug("%s: ttyGS%d, after close\n", +- __func__, port->port_num); +- return -EIO; +- } +- +- len = tty_insert_flip_string(tty, packet, size); +- if (len > 0) +- tasklet_schedule(&port->push); +- if (len < size) +- pr_debug("%s: ttyGS%d, drop %d bytes\n", +- __func__, port->port_num, size - len); +- return 0; +-} +- + /* + * Context: caller owns port_lock, and port_usb is set + */ +@@ -469,9 +421,9 @@ __acquires(&port->port_lock) + int status; + struct tty_struct *tty; + +- /* no more rx if closed or throttled */ ++ /* no more rx if closed */ + tty = port->port_tty; +- if (!tty || test_bit(TTY_THROTTLED, &tty->flags)) ++ if (!tty) + break; + + req = list_entry(pool->next, struct usb_request, list); +@@ -500,36 +452,134 @@ __acquires(&port->port_lock) + return started; + } + +-static void gs_read_complete(struct usb_ep *ep, struct usb_request *req) ++/* ++ * RX tasklet takes data out of the RX queue and hands it up to the TTY ++ * layer until it refuses to take any more data (or is throttled back). ++ * Then it issues reads for any further data. ++ * ++ * If the RX queue becomes full enough that no usb_request is queued, ++ * the OUT endpoint may begin NAKing as soon as its FIFO fills up. ++ * So QUEUE_SIZE packets plus however many the FIFO holds (usually two) ++ * can be buffered before the TTY layer's buffers (currently 64 KB). ++ */ ++static void gs_rx_push(unsigned long _port) + { +- int status; +- struct gs_port *port = ep->driver_data; ++ struct gs_port *port = (void *)_port; ++ struct tty_struct *tty; ++ struct list_head *queue = &port->read_queue; ++ bool disconnect = false; ++ bool do_push = false; + +- spin_lock(&port->port_lock); +- list_add(&req->list, &port->read_pool); ++ /* hand any queued data to the tty */ ++ spin_lock_irq(&port->port_lock); ++ tty = port->port_tty; ++ while (!list_empty(queue)) { ++ struct usb_request *req; + +- switch (req->status) { +- case 0: +- /* normal completion */ +- status = gs_recv_packet(port, req->buf, req->actual); +- if (status && status != -EIO) +- pr_debug("%s: %s %s err %d\n", +- __func__, "recv", ep->name, status); +- gs_start_rx(port); +- break; ++ req = list_first_entry(queue, struct usb_request, list); + +- case -ESHUTDOWN: +- /* disconnect */ +- pr_vdebug("%s: %s shutdown\n", __func__, ep->name); +- break; ++ /* discard data if tty was closed */ ++ if (!tty) ++ goto recycle; + +- default: +- /* presumably a transient fault */ +- pr_warning("%s: unexpected %s status %d\n", +- __func__, ep->name, req->status); +- gs_start_rx(port); +- break; ++ /* leave data queued if tty was rx throttled */ ++ if (test_bit(TTY_THROTTLED, &tty->flags)) ++ break; ++ ++ switch (req->status) { ++ case -ESHUTDOWN: ++ disconnect = true; ++ pr_vdebug(PREFIX "%d: shutdown\n", port->port_num); ++ break; ++ ++ default: ++ /* presumably a transient fault */ ++ pr_warning(PREFIX "%d: unexpected RX status %d\n", ++ port->port_num, req->status); ++ /* FALLTHROUGH */ ++ case 0: ++ /* normal completion */ ++ break; ++ } ++ ++ /* push data to (open) tty */ ++ if (req->actual) { ++ char *packet = req->buf; ++ unsigned size = req->actual; ++ unsigned n; ++ int count; ++ ++ /* we may have pushed part of this packet already... */ ++ n = port->n_read; ++ if (n) { ++ packet += n; ++ size -= n; ++ } ++ ++ count = tty_insert_flip_string(tty, packet, size); ++ if (count) ++ do_push = true; ++ if (count != size) { ++ /* stop pushing; TTY layer can't handle more */ ++ port->n_read += count; ++ pr_vdebug(PREFIX "%d: rx block %d/%d\n", ++ port->port_num, ++ count, req->actual); ++ break; ++ } ++ port->n_read = 0; ++ } ++recycle: ++ list_move(&req->list, &port->read_pool); ++ } ++ ++ /* Push from tty to ldisc; this is immediate with low_latency, and ++ * may trigger callbacks to this driver ... so drop the spinlock. ++ */ ++ if (tty && do_push) { ++ spin_unlock_irq(&port->port_lock); ++ tty_flip_buffer_push(tty); ++ wake_up_interruptible(&tty->read_wait); ++ spin_lock_irq(&port->port_lock); ++ ++ /* tty may have been closed */ ++ tty = port->port_tty; + } ++ ++ ++ /* We want our data queue to become empty ASAP, keeping data ++ * in the tty and ldisc (not here). If we couldn't push any ++ * this time around, there may be trouble unless there's an ++ * implicit tty_unthrottle() call on its way... ++ * ++ * REVISIT we should probably add a timer to keep the tasklet ++ * from starving ... but it's not clear that case ever happens. ++ */ ++ if (!list_empty(queue) && tty) { ++ if (!test_bit(TTY_THROTTLED, &tty->flags)) { ++ if (do_push) ++ tasklet_schedule(&port->push); ++ else ++ pr_warning(PREFIX "%d: RX not scheduled?\n", ++ port->port_num); ++ } ++ } ++ ++ /* If we're still connected, refill the USB RX queue. */ ++ if (!disconnect && port->port_usb) ++ gs_start_rx(port); ++ ++ spin_unlock_irq(&port->port_lock); ++} ++ ++static void gs_read_complete(struct usb_ep *ep, struct usb_request *req) ++{ ++ struct gs_port *port = ep->driver_data; ++ ++ /* Queue all received data until the tty layer is ready for it. */ ++ spin_lock(&port->port_lock); ++ list_add_tail(&req->list, &port->read_queue); ++ tasklet_schedule(&port->push); + spin_unlock(&port->port_lock); + } + +@@ -625,6 +675,7 @@ static int gs_start_io(struct gs_port *p + } + + /* queue read requests */ ++ port->n_read = 0; + started = gs_start_rx(port); + + /* unblock any pending writes into our circular buffer */ +@@ -633,9 +684,10 @@ static int gs_start_io(struct gs_port *p + } else { + gs_free_requests(ep, head); + gs_free_requests(port->port_usb->in, &port->write_pool); ++ status = -EIO; + } + +- return started ? 0 : status; ++ return status; + } + + /*-------------------------------------------------------------------------*/ +@@ -809,8 +861,6 @@ static void gs_close(struct tty_struct * + else + gs_buf_clear(&port->port_write_buf); + +- tasklet_kill(&port->push); +- + tty->driver_data = NULL; + port->port_tty = NULL; + +@@ -911,15 +961,17 @@ static void gs_unthrottle(struct tty_str + { + struct gs_port *port = tty->driver_data; + unsigned long flags; +- unsigned started = 0; + + spin_lock_irqsave(&port->port_lock, flags); +- if (port->port_usb) +- started = gs_start_rx(port); ++ if (port->port_usb) { ++ /* Kickstart read queue processing. We don't do xon/xoff, ++ * rts/cts, or other handshaking with the host, but if the ++ * read queue backs up enough we'll be NAKing OUT packets. ++ */ ++ tasklet_schedule(&port->push); ++ pr_vdebug(PREFIX "%d: unthrottle\n", port->port_num); ++ } + spin_unlock_irqrestore(&port->port_lock, flags); +- +- pr_vdebug("gs_unthrottle: ttyGS%d, %d packets\n", +- port->port_num, started); + } + + static const struct tty_operations gs_tty_ops = { +@@ -953,6 +1005,7 @@ gs_port_alloc(unsigned port_num, struct + tasklet_init(&port->push, gs_rx_push, (unsigned long) port); + + INIT_LIST_HEAD(&port->read_pool); ++ INIT_LIST_HEAD(&port->read_queue); + INIT_LIST_HEAD(&port->write_pool); + + port->port_num = port_num; +@@ -997,7 +1050,7 @@ int __init gserial_setup(struct usb_gadg + + gs_tty_driver->owner = THIS_MODULE; + gs_tty_driver->driver_name = "g_serial"; +- gs_tty_driver->name = "ttyGS"; ++ gs_tty_driver->name = PREFIX; + /* uses dynamically assigned dev_t values */ + + gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; +@@ -1104,6 +1157,8 @@ void gserial_cleanup(void) + ports[i].port = NULL; + mutex_unlock(&ports[i].lock); + ++ tasklet_kill(&port->push); ++ + /* wait for old opens to finish */ + wait_event(port->close_wait, gs_closed(port)); + +@@ -1241,6 +1296,7 @@ void gserial_disconnect(struct gserial * + if (port->open_count == 0 && !port->openclose) + gs_buf_free(&port->port_write_buf); + gs_free_requests(gser->out, &port->read_pool); ++ gs_free_requests(gser->out, &port->read_queue); + gs_free_requests(gser->in, &port->write_pool); + spin_unlock_irqrestore(&port->port_lock, flags); + } diff --git a/usb.current/usb-update-to-documentation.patch b/usb.current/usb-update-to-documentation.patch new file mode 100644 index 00000000000000..5798c3c88dc072 --- /dev/null +++ b/usb.current/usb-update-to-documentation.patch @@ -0,0 +1,35 @@ +From oliver@neukum.org Wed Aug 6 16:39:58 2008 +From: Oliver Neukum <oliver@neukum.org> +Date: Fri, 4 Jul 2008 10:10:53 +0200 +Subject: USB: update to Documentation +To: Alan Stern <stern@rowland.harvard.edu> +Cc: Greg KH <greg@kroah.com>, linux-usb@vger.kernel.org +Message-ID: <200807041010.53563.oliver@neukum.org> +Content-Disposition: inline + + +this mentions a new deadlock due to advanced power management. + +Signed-off-by: Oliver Neukum <oneukum@suse.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + Documentation/usb/power-management.txt | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/Documentation/usb/power-management.txt ++++ b/Documentation/usb/power-management.txt +@@ -436,7 +436,12 @@ post_reset; the USB core guarantees that + suspend/resume events as well. + + If a driver wants to block all suspend/resume calls during some +-critical section, it can simply acquire udev->pm_mutex. ++critical section, it can simply acquire udev->pm_mutex. Note that ++calls to resume may be triggered indirectly. Block IO due to memory ++allocations can make the vm subsystem resume a device. Thus while ++holding this lock you must not allocate memory with GFP_KERNEL or ++GFP_NOFS. ++ + Alternatively, if the critical section might call some of the + usb_autopm_* routines, the driver can avoid deadlock by doing: + |
