diff options
| author | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-02 16:47:04 -0700 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-02 16:47:04 -0700 |
| commit | 24ec1fda011aeaad77e34172651892e704c1076e (patch) | |
| tree | 9ffb519b3af6b32842a59ce2ef10051426b2aeb1 | |
| parent | 3e04eb00f19d12ec07922e9a32f049e046f3db4b (diff) | |
| download | patches-24ec1fda011aeaad77e34172651892e704c1076e.tar.gz | |
more patches
35 files changed, 3126 insertions, 966 deletions
diff --git a/driver-core/leds-remove-owner-field-from-attribute-initialization-in-bd2802-driver.patch b/driver-core/leds-remove-owner-field-from-attribute-initialization-in-bd2802-driver.patch new file mode 100644 index 00000000000000..87a4d284ef9f50 --- /dev/null +++ b/driver-core/leds-remove-owner-field-from-attribute-initialization-in-bd2802-driver.patch @@ -0,0 +1,59 @@ +From groeck@redback.com Mon Aug 2 16:30:34 2010 +From: Guenter Roeck <guenter.roeck@ericsson.com> +To: "James E.J. Bottomley" <James.Bottomley@suse.de>, + Richard Purdie <rpurdie@rpsys.net>, + Greg Kroah-Hartman <gregkh@suse.de>, + Benjamin Herrenschmidt <benh@kernel.crashing.org>, + Paul Mackerras <paulus@samba.org> +Cc: Jean Delvare <khali@linux-fr.org>, + Dmitry Torokhov <dtor@mail.ru>, Liam Girdwood <lrg@slimlogic.co.uk>, + Mark Brown <broonie@opensource.wolfsonmicro.com>, + Jani Nikula <ext-jani.1.nikula@nokia.com>, + Linus Walleij <linus.walleij@stericsson.com>, + Chris Wright <chrisw@sous-sol.org>, + Nick Cheng <nick.cheng@areca.com.tw>, + James Smart <james.smart@emulex.com>, + Alex Iannicelli <alex.iannicelli@emulex.com>, + "Eric W. Biederman" <ebiederm@aristanetworks.com>, + Benjamin Thery <benjamin.thery@bull.net>, Tejun Heo <tj@kernel.org>, + linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, + linuxppc-dev@ozlabs.org, Guenter Roeck <guenter.roeck@ericsson.com> +Subject: leds: Remove owner field from attribute initialization in bd2802 driver +Date: Wed, 28 Jul 2010 22:09:23 -0700 +Message-ID: <1280380166-29196-4-git-send-email-guenter.roeck@ericsson.com> + +Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> +Acked-by: Tejun Heo <tj@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/leds/leds-bd2802.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/leds/leds-bd2802.c ++++ b/drivers/leds/leds-bd2802.c +@@ -351,7 +351,7 @@ static ssize_t bd2802_store_reg##reg_add + return count; \ + } \ + static struct device_attribute bd2802_reg##reg_addr##_attr = { \ +- .attr = {.name = reg_name, .mode = 0644, .owner = THIS_MODULE}, \ ++ .attr = {.name = reg_name, .mode = 0644}, \ + .store = bd2802_store_reg##reg_addr, \ + }; + +@@ -482,7 +482,6 @@ static struct device_attribute bd2802_ad + .attr = { + .name = "advanced_configuration", + .mode = 0644, +- .owner = THIS_MODULE + }, + .show = bd2802_show_adv_conf, + .store = bd2802_store_adv_conf, +@@ -519,7 +518,6 @@ static struct device_attribute bd2802_## + .attr = { \ + .name = name_str, \ + .mode = 0644, \ +- .owner = THIS_MODULE \ + }, \ + .show = bd2802_show_##attr_name, \ + .store = bd2802_store_##attr_name, \ diff --git a/driver-core/powerpc-pci-remove-owner-field-from-attribute-initialization-in-pci-bridge-init.patch b/driver-core/powerpc-pci-remove-owner-field-from-attribute-initialization-in-pci-bridge-init.patch new file mode 100644 index 00000000000000..8e22751533dcbd --- /dev/null +++ b/driver-core/powerpc-pci-remove-owner-field-from-attribute-initialization-in-pci-bridge-init.patch @@ -0,0 +1,42 @@ +From groeck@redback.com Mon Aug 2 16:31:31 2010 +From: Guenter Roeck <guenter.roeck@ericsson.com> +To: "James E.J. Bottomley" <James.Bottomley@suse.de>, + Richard Purdie <rpurdie@rpsys.net>, + Greg Kroah-Hartman <gregkh@suse.de>, + Benjamin Herrenschmidt <benh@kernel.crashing.org>, + Paul Mackerras <paulus@samba.org> +Cc: Jean Delvare <khali@linux-fr.org>, + Dmitry Torokhov <dtor@mail.ru>, Liam Girdwood <lrg@slimlogic.co.uk>, + Mark Brown <broonie@opensource.wolfsonmicro.com>, + Jani Nikula <ext-jani.1.nikula@nokia.com>, + Linus Walleij <linus.walleij@stericsson.com>, + Chris Wright <chrisw@sous-sol.org>, + Nick Cheng <nick.cheng@areca.com.tw>, + James Smart <james.smart@emulex.com>, + Alex Iannicelli <alex.iannicelli@emulex.com>, + "Eric W. Biederman" <ebiederm@aristanetworks.com>, + Benjamin Thery <benjamin.thery@bull.net>, Tejun Heo <tj@kernel.org>, + linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, + linuxppc-dev@ozlabs.org, Guenter Roeck <guenter.roeck@ericsson.com> +Subject: powerpc/pci: Remove owner field from attribute initialization in PCI bridge init +Date: Wed, 28 Jul 2010 22:09:25 -0700 +Message-ID: <1280380166-29196-6-git-send-email-guenter.roeck@ericsson.com> + +Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> +Acked-by: Tejun Heo <tj@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + arch/powerpc/sysdev/mv64x60_pci.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/arch/powerpc/sysdev/mv64x60_pci.c ++++ b/arch/powerpc/sysdev/mv64x60_pci.c +@@ -73,7 +73,6 @@ static struct bin_attribute mv64x60_hs_r + .attr = { + .name = "hs_reg", + .mode = S_IRUGO | S_IWUSR, +- .owner = THIS_MODULE, + }, + .size = MV64X60_VAL_LEN_MAX, + .read = mv64x60_hs_reg_read, diff --git a/driver-core/regulator-remove-owner-field-from-attribute-initialization-in-regulator-core-driver.patch b/driver-core/regulator-remove-owner-field-from-attribute-initialization-in-regulator-core-driver.patch new file mode 100644 index 00000000000000..c954f679530515 --- /dev/null +++ b/driver-core/regulator-remove-owner-field-from-attribute-initialization-in-regulator-core-driver.patch @@ -0,0 +1,43 @@ +From groeck@redback.com Mon Aug 2 16:30:54 2010 +From: Guenter Roeck <guenter.roeck@ericsson.com> +To: "James E.J. Bottomley" <James.Bottomley@suse.de>, + Richard Purdie <rpurdie@rpsys.net>, + Greg Kroah-Hartman <gregkh@suse.de>, + Benjamin Herrenschmidt <benh@kernel.crashing.org>, + Paul Mackerras <paulus@samba.org> +Cc: Jean Delvare <khali@linux-fr.org>, + Dmitry Torokhov <dtor@mail.ru>, Liam Girdwood <lrg@slimlogic.co.uk>, + Mark Brown <broonie@opensource.wolfsonmicro.com>, + Jani Nikula <ext-jani.1.nikula@nokia.com>, + Linus Walleij <linus.walleij@stericsson.com>, + Chris Wright <chrisw@sous-sol.org>, + Nick Cheng <nick.cheng@areca.com.tw>, + James Smart <james.smart@emulex.com>, + Alex Iannicelli <alex.iannicelli@emulex.com>, + "Eric W. Biederman" <ebiederm@aristanetworks.com>, + Benjamin Thery <benjamin.thery@bull.net>, Tejun Heo <tj@kernel.org>, + linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, + linuxppc-dev@ozlabs.org, Guenter Roeck <guenter.roeck@ericsson.com> +Subject: regulator: Remove owner field from attribute initialization in regulator core driver +Date: Wed, 28 Jul 2010 22:09:24 -0700 +Message-ID: <1280380166-29196-5-git-send-email-guenter.roeck@ericsson.com> + +Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> +Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +Acked-by: Tejun Heo <tj@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/regulator/core.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -1025,7 +1025,6 @@ static struct regulator *create_regulato + if (regulator->dev_attr.attr.name == NULL) + goto attr_name_err; + +- regulator->dev_attr.attr.owner = THIS_MODULE; + regulator->dev_attr.attr.mode = 0444; + regulator->dev_attr.show = device_requested_uA_show; + err = device_create_file(dev, ®ulator->dev_attr); diff --git a/driver-core/scsi-remove-owner-field-from-attribute-initialization-in-arcmsr-driver.patch b/driver-core/scsi-remove-owner-field-from-attribute-initialization-in-arcmsr-driver.patch new file mode 100644 index 00000000000000..612d155dc4f98c --- /dev/null +++ b/driver-core/scsi-remove-owner-field-from-attribute-initialization-in-arcmsr-driver.patch @@ -0,0 +1,58 @@ +From groeck@redback.com Mon Aug 2 16:30:20 2010 +From: Guenter Roeck <guenter.roeck@ericsson.com> +To: "James E.J. Bottomley" <James.Bottomley@suse.de>, + Richard Purdie <rpurdie@rpsys.net>, + Greg Kroah-Hartman <gregkh@suse.de>, + Benjamin Herrenschmidt <benh@kernel.crashing.org>, + Paul Mackerras <paulus@samba.org> +Cc: Jean Delvare <khali@linux-fr.org>, + Dmitry Torokhov <dtor@mail.ru>, Liam Girdwood <lrg@slimlogic.co.uk>, + Mark Brown <broonie@opensource.wolfsonmicro.com>, + Jani Nikula <ext-jani.1.nikula@nokia.com>, + Linus Walleij <linus.walleij@stericsson.com>, + Chris Wright <chrisw@sous-sol.org>, + Nick Cheng <nick.cheng@areca.com.tw>, + James Smart <james.smart@emulex.com>, + Alex Iannicelli <alex.iannicelli@emulex.com>, + "Eric W. Biederman" <ebiederm@aristanetworks.com>, + Benjamin Thery <benjamin.thery@bull.net>, Tejun Heo <tj@kernel.org>, + linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, + linuxppc-dev@ozlabs.org, Guenter Roeck <guenter.roeck@ericsson.com> +Subject: scsi: Remove owner field from attribute initialization in ARCMSR driver +Date: Wed, 28 Jul 2010 22:09:22 -0700 +Message-ID: <1280380166-29196-3-git-send-email-guenter.roeck@ericsson.com> + +Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> +Acked-by: Tejun Heo <tj@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/scsi/arcmsr/arcmsr_attr.c | 3 --- + 1 file changed, 3 deletions(-) + +--- a/drivers/scsi/arcmsr/arcmsr_attr.c ++++ b/drivers/scsi/arcmsr/arcmsr_attr.c +@@ -192,7 +192,6 @@ static struct bin_attribute arcmsr_sysfs + .attr = { + .name = "mu_read", + .mode = S_IRUSR , +- .owner = THIS_MODULE, + }, + .size = 1032, + .read = arcmsr_sysfs_iop_message_read, +@@ -202,7 +201,6 @@ static struct bin_attribute arcmsr_sysfs + .attr = { + .name = "mu_write", + .mode = S_IWUSR, +- .owner = THIS_MODULE, + }, + .size = 1032, + .write = arcmsr_sysfs_iop_message_write, +@@ -212,7 +210,6 @@ static struct bin_attribute arcmsr_sysfs + .attr = { + .name = "mu_clear", + .mode = S_IWUSR, +- .owner = THIS_MODULE, + }, + .size = 1, + .write = arcmsr_sysfs_iop_message_clear, diff --git a/driver-core/scsi-remove-owner-field-from-attribute-initialization-in-lpfc-driver.patch b/driver-core/scsi-remove-owner-field-from-attribute-initialization-in-lpfc-driver.patch new file mode 100644 index 00000000000000..5c057d976b5b0d --- /dev/null +++ b/driver-core/scsi-remove-owner-field-from-attribute-initialization-in-lpfc-driver.patch @@ -0,0 +1,42 @@ +From groeck@redback.com Mon Aug 2 16:30:02 2010 +From: Guenter Roeck <guenter.roeck@ericsson.com> +To: "James E.J. Bottomley" <James.Bottomley@suse.de>, + Richard Purdie <rpurdie@rpsys.net>, + Greg Kroah-Hartman <gregkh@suse.de>, + Benjamin Herrenschmidt <benh@kernel.crashing.org>, + Paul Mackerras <paulus@samba.org> +Cc: Jean Delvare <khali@linux-fr.org>, + Dmitry Torokhov <dtor@mail.ru>, Liam Girdwood <lrg@slimlogic.co.uk>, + Mark Brown <broonie@opensource.wolfsonmicro.com>, + Jani Nikula <ext-jani.1.nikula@nokia.com>, + Linus Walleij <linus.walleij@stericsson.com>, + Chris Wright <chrisw@sous-sol.org>, + Nick Cheng <nick.cheng@areca.com.tw>, + James Smart <james.smart@emulex.com>, + Alex Iannicelli <alex.iannicelli@emulex.com>, + "Eric W. Biederman" <ebiederm@aristanetworks.com>, + Benjamin Thery <benjamin.thery@bull.net>, Tejun Heo <tj@kernel.org>, + linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, + linuxppc-dev@ozlabs.org, Guenter Roeck <guenter.roeck@ericsson.com> +Subject: scsi: Remove owner field from attribute initialization in LPFC driver +Date: Wed, 28 Jul 2010 22:09:21 -0700 +Message-ID: <1280380166-29196-2-git-send-email-guenter.roeck@ericsson.com> + +Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> +Acked-by: Tejun Heo <tj@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/scsi/lpfc/lpfc_attr.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/scsi/lpfc/lpfc_attr.c ++++ b/drivers/scsi/lpfc/lpfc_attr.c +@@ -2720,7 +2720,6 @@ static struct bin_attribute sysfs_drvr_s + .attr = { + .name = "lpfc_drvr_stat_data", + .mode = S_IRUSR, +- .owner = THIS_MODULE, + }, + .size = LPFC_MAX_TARGET * MAX_STAT_DATA_SIZE_PER_TARGET, + .read = sysfs_drvr_stat_data_read, diff --git a/driver-core/sysfs-remove-owner-field-from-sysfs-struct-attribute.patch b/driver-core/sysfs-remove-owner-field-from-sysfs-struct-attribute.patch new file mode 100644 index 00000000000000..4078f3eb6b9d9d --- /dev/null +++ b/driver-core/sysfs-remove-owner-field-from-sysfs-struct-attribute.patch @@ -0,0 +1,49 @@ +From groeck@redback.com Mon Aug 2 16:31:44 2010 +From: Guenter Roeck <guenter.roeck@ericsson.com> +To: "James E.J. Bottomley" <James.Bottomley@suse.de>, + Richard Purdie <rpurdie@rpsys.net>, + Greg Kroah-Hartman <gregkh@suse.de>, + Benjamin Herrenschmidt <benh@kernel.crashing.org>, + Paul Mackerras <paulus@samba.org> +Cc: Jean Delvare <khali@linux-fr.org>, + Dmitry Torokhov <dtor@mail.ru>, Liam Girdwood <lrg@slimlogic.co.uk>, + Mark Brown <broonie@opensource.wolfsonmicro.com>, + Jani Nikula <ext-jani.1.nikula@nokia.com>, + Linus Walleij <linus.walleij@stericsson.com>, + Chris Wright <chrisw@sous-sol.org>, + Nick Cheng <nick.cheng@areca.com.tw>, + James Smart <james.smart@emulex.com>, + Alex Iannicelli <alex.iannicelli@emulex.com>, + "Eric W. Biederman" <ebiederm@aristanetworks.com>, + Benjamin Thery <benjamin.thery@bull.net>, Tejun Heo <tj@kernel.org>, + linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, + linuxppc-dev@ozlabs.org, Guenter Roeck <guenter.roeck@ericsson.com> +Subject: sysfs: Remove owner field from sysfs struct attribute +Date: Wed, 28 Jul 2010 22:09:26 -0700 +Message-ID: <1280380166-29196-7-git-send-email-guenter.roeck@ericsson.com> + +Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> +Acked-by: Tejun Heo <tj@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + include/linux/sysfs.h | 6 ------ + 1 file changed, 6 deletions(-) + +--- a/include/linux/sysfs.h ++++ b/include/linux/sysfs.h +@@ -22,14 +22,8 @@ struct kobject; + struct module; + enum kobj_ns_type; + +-/* FIXME +- * The *owner field is no longer used. +- * x86 tree has been cleaned up. The owner +- * attribute is still left for other arches. +- */ + struct attribute { + const char *name; +- struct module *owner; + mode_t mode; + #ifdef CONFIG_DEBUG_LOCK_ALLOC + struct lock_class_key *key; @@ -50,6 +50,13 @@ driver-core/driver-core-fix-memory-leak-one-one-error-path-in-bus_register.patch driver-core/driver-core-add-bus_notify_bind_driver.patch driver-core/cgroupfs-create-sys-fs-cgroup-to-mount-cgroupfs-on.patch +driver-core/scsi-remove-owner-field-from-attribute-initialization-in-lpfc-driver.patch +driver-core/scsi-remove-owner-field-from-attribute-initialization-in-arcmsr-driver.patch +driver-core/leds-remove-owner-field-from-attribute-initialization-in-bd2802-driver.patch +driver-core/regulator-remove-owner-field-from-attribute-initialization-in-regulator-core-driver.patch +driver-core/powerpc-pci-remove-owner-field-from-attribute-initialization-in-pci-bridge-init.patch +driver-core/sysfs-remove-owner-field-from-sysfs-struct-attribute.patch + # can we really drop it? (nope, not yet...) #driver-core/driver-core-remove-config_sysfs_deprecated.patch @@ -123,6 +130,10 @@ tty/hsu-driver-for-medfield-high-speed-uart-device.patch tty/hsu-add-a-periodic-timer-to-check-dma-rx-channel.patch tty/hsu-some-code-cleanup.patch tty/hsu-call-pci-pm-hooks-in-suspend-resume-function.patch +tty/serial-max3107-fix-gpiolib-support.patch +tty/char-nozomi-fix-tty-count-counting.patch +tty/char-nozomi-set-tty-driver_data-appropriately.patch +tty/u6715-16550a-serial-driver-support.patch ################################### @@ -250,14 +261,32 @@ usb/usb-s3c-hsotg-add-support-for-external-usb-clock.patch usb/usb-s3c-hsotg-fix-compilation-problem.patch usb/usb-s3c-hsotg-modify-only-selected-bits-in-s3c_phypwr-register.patch usb/usb-s3c-hsotg-add-support-for-clock-gating.patch -usb/usb-powerpc-fsl_soc.c-remove-fsl-usb-platform-code.patch -usb/usb-add-of_platform-glue-driver-for-fsl-usb-dr-controller.patch -usb/usb-add-usb-ehci-support-for-mpc5121-soc.patch usb/usb-serial-enabling-support-for-segway-rmp-in-ftdi_sio.patch usb/usb-imx21-hcd-set-task-state-with-schedule_timeout_uninterruptible.patch usb/usb-gadget-file_storage-serial-parameter-even-if-not-test-mode.patch usb/usb-option-add-huawei-k3765-k4505-devices-to-work-properly.patch - +usb/usb-accept-rndis-configs-if-there-s-no-alternative.patch +usb/usb-ftdi_sio-device-id-for-navitator.patch +usb/usb-cp210x-add-four-new-device-ids.patch +usb/usb-add-usb-2.0-to-ssb-ohci-driver.patch +usb/usb-ehci-fix-remove-of-ehci-debugfs-dir.patch +usb/usb-usb-storage-implement-autosuspend.patch +usb/usb-add-usb-serial-ssu100-driver.patch +usb/usb-fix-linux-usb.h-kernel-doc-warnings.patch +usb/usb-xhci-performance-move-functions-that-find-ep-ring.patch +usb/usb-xhci-performance-move-interrupt-handlers-into-xhci-ring.c.patch +usb/usb-xhci-performance-move-xhci_work-into-xhci_irq.patch +usb/usb-xhci-remove-unnecessary-reads-of-irq_pending-register.patch +usb/usb-xhci-make-xhci_handle_event-static.patch +usb/usb-xhci-minimize-hw-event-ring-dequeue-pointer-writes.patch +usb/usb-xhci-make-xhci_set_hc_event_deq-static.patch +usb/usb-xhci-reduce-reads-and-writes-of-interrupter-registers.patch +usb/usb-xhci-don-t-flush-doorbell-writes.patch +usb/usb-xhci-set-dma-mask-for-host.patch +usb/usb-usbtest-avoid-to-free-coherent-buffer-in-atomic-context.patch +usb/usb-usbtest-support-test-device-with-only-one-iso-in-or-iso-out-endpoint.patch +usb/usb-fix-stuck-usb-generic-serial-driver.patch # staging stuff is now in the staging-next tree on git.kernel.org + diff --git a/tty/char-nozomi-fix-tty-count-counting.patch b/tty/char-nozomi-fix-tty-count-counting.patch new file mode 100644 index 00000000000000..43468a9b7f7610 --- /dev/null +++ b/tty/char-nozomi-fix-tty-count-counting.patch @@ -0,0 +1,34 @@ +From jslaby@suse.cz Mon Aug 2 16:02:43 2010 +From: Jiri Slaby <jslaby@suse.cz> +To: gregkh@suse.de +Cc: jirislaby@gmail.com, linux-kernel@vger.kernel.org, + Jiri Slaby <jslaby@suse.cz>, Alan Cox <alan@linux.intel.com> +Subject: Char: nozomi, fix tty->count counting +Date: Thu, 29 Jul 2010 11:09:47 +0200 +Message-Id: <1280394587-31670-1-git-send-email-jslaby@suse.cz> + +Currently ntty_install omits to increment tty count and we get the +following warnings: +Warning: dev (noz2) tty->count(0) != #fd's(1) in tty_open + +So to fix that, add one tty->count++ there. + +Signed-off-by: Jiri Slaby <jslaby@suse.cz> +Cc: Alan Cox <alan@linux.intel.com> +Cc: stable <stable@kernel.org> [.34, .35] +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/char/nozomi.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/char/nozomi.c ++++ b/drivers/char/nozomi.c +@@ -1611,6 +1611,7 @@ static int ntty_install(struct tty_drive + ret = tty_init_termios(tty); + if (ret == 0) { + tty_driver_kref_get(driver); ++ tty->count++; + driver->ttys[tty->index] = tty; + } + return ret; diff --git a/tty/char-nozomi-set-tty-driver_data-appropriately.patch b/tty/char-nozomi-set-tty-driver_data-appropriately.patch new file mode 100644 index 00000000000000..ad809a039c1d90 --- /dev/null +++ b/tty/char-nozomi-set-tty-driver_data-appropriately.patch @@ -0,0 +1,62 @@ +From jslaby@suse.cz Mon Aug 2 16:03:19 2010 +From: Jiri Slaby <jslaby@suse.cz> +To: gregkh@suse.de +Cc: jirislaby@gmail.com, linux-kernel@vger.kernel.org, + Jiri Slaby <jslaby@suse.cz>, Alan Cox <alan@linux.intel.com> +Subject: [PATCH 1/1] Char: nozomi, set tty->driver_data appropriately +Date: Thu, 29 Jul 2010 11:46:32 +0200 +Message-Id: <1280396792-32060-1-git-send-email-jslaby@suse.cz> + +Sorry, one more fix, this one depends on the other, so this is rather 2/2. +-- + +tty->driver_data is used all over the code, but never set. This +results in oopses like: +BUG: unable to handle kernel NULL pointer dereference at 0000000000000130 +IP: [<ffffffff814a0040>] mutex_lock+0x10/0x40 +... +Pid: 2157, comm: modem-manager Not tainted 2.6.34.1-0.1-desktop #1 2768DR7/2768DR7 +RIP: 0010:[<ffffffff814a0040>] [<ffffffff814a0040>] mutex_lock+0x10/0x40 +RSP: 0018:ffff88007b16fa50 EFLAGS: 00010286 +RAX: 0000000000000000 RBX: 0000000000000130 RCX: 0000000000000003 +RDX: 0000000000000003 RSI: 0000000000000286 RDI: 0000000000000130 +RBP: 0000000000001000 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000130 +R13: 0000000000000001 R14: 0000000000000000 R15: ffff88007b16feb4 +... +Call Trace: + [<ffffffffa077690d>] ntty_write_room+0x4d/0x90 [nozomi] +... + +Set tty->driver_data to the computed port in .install to not recompute it in +every place where needed. Switch .open to use driver_data too. + +Signed-off-by: Jiri Slaby <jslaby@suse.cz> +Cc: Alan Cox <alan@linux.intel.com> +Cc: stable <stable@kernel.org> [.34, .35] +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + drivers/char/nozomi.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/char/nozomi.c ++++ b/drivers/char/nozomi.c +@@ -1612,6 +1612,7 @@ static int ntty_install(struct tty_drive + if (ret == 0) { + tty_driver_kref_get(driver); + tty->count++; ++ tty->driver_data = port; + driver->ttys[tty->index] = tty; + } + return ret; +@@ -1640,7 +1641,7 @@ static int ntty_activate(struct tty_port + + static int ntty_open(struct tty_struct *tty, struct file *filp) + { +- struct port *port = get_port_by_tty(tty); ++ struct port *port = tty->driver_data; + return tty_port_open(&port->port, tty, filp); + } + diff --git a/tty/serial-max3107-fix-gpiolib-support.patch b/tty/serial-max3107-fix-gpiolib-support.patch new file mode 100644 index 00000000000000..cab4baeaacefc5 --- /dev/null +++ b/tty/serial-max3107-fix-gpiolib-support.patch @@ -0,0 +1,30 @@ +From alan@linux.intel.com Tue Jul 27 10:12:52 2010 +From: Alan Cox <alan@linux.intel.com> +Subject: serial: max3107: Fix gpiolib support +To: linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org, greg@kroah.com +Date: Tue, 27 Jul 2010 08:16:05 +0100 +Message-ID: <20100727071551.25761.146.stgit@localhost.localdomain> + +Because of the way gpiolib works we actually need to ifdef this in our +header file + +Signed-off-by: Alan Cox <alan@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/serial/max3107.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/serial/max3107.h ++++ b/drivers/serial/max3107.h +@@ -368,8 +368,10 @@ struct max3107_port { + /* SPI device structure */ + struct spi_device *spi; + ++#if defined(CONFIG_GPIOLIB) + /* GPIO chip stucture */ + struct gpio_chip chip; ++#endif + + /* Workqueue that does all the magic */ + struct workqueue_struct *workqueue; diff --git a/tty/u6715-16550a-serial-driver-support.patch b/tty/u6715-16550a-serial-driver-support.patch new file mode 100644 index 00000000000000..6208e0d5e5f2f8 --- /dev/null +++ b/tty/u6715-16550a-serial-driver-support.patch @@ -0,0 +1,169 @@ +From philippe.langlais@stericsson.com Mon Aug 2 16:04:14 2010 +From: Philippe Langlais <philippe.langlais@stericsson.com> +Cc: <alan@lxorguk.ukuu.org.uk>, <gregkh@suse.de>, + <ludovic.barre@stericsson.com>, <vincent.guittot@stericsson.com>, + Philippe Langlais <philippe.langlais@stericsson.com> +Subject: U6715 16550A serial driver support +Date: Thu, 29 Jul 2010 17:13:57 +0200 +Message-ID: <1280416437-25364-1-git-send-email-philippe.langlais@stericsson.com> + +UART Features extract from STEricsson U6715 data-sheet (arm926 SoC for mobile phone): +* Fully compatible with industry standard 16C550 and 16C450 from various +manufacturers +* RX and TX 64 byte FIFO reduces CPU interrupts +* Full double buffering +* Modem control signals include CTS, RTS, (and DSR, DTR on UART1 only) +* Automatic baud rate selection +* Manual or automatic RTS/CTS smart hardware flow control +* Programmable serial characteristics: +– Baud rate generation (50 to 3.25M baud) +– 5, 6, 7 or 8-bit characters +– Even, odd or no-parity bit generation and detection +– 1, 1.5 or 2 stop bit generation +* Independent control of transmit, receive, line status, data set interrupts and FIFOs +* Full status-reporting capabilities +* Separate DMA signaling for RX and TX +* Timed interrupt to spread receive interrupt on known duration +* DMA time-out interrupt to allow detection of end of reception +* Carkit pulse coding and decoding compliant with USB carkit control interface [40] + +In 16550A auto-configuration, if the fifo size is 64 then it's an U6 16550A port +Add set_termios hook & export serial8250_do_set_termios to change uart +clock following baudrate + +Signed-off-by: Philippe Langlais <philippe.langlais@stericsson.com> +Acked-by: Alan Cox <alan@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/serial/8250.c | 37 ++++++++++++++++++++++++++++++++++--- + include/linux/serial.h | 3 ++- + include/linux/serial_8250.h | 5 +++++ + include/linux/serial_core.h | 3 +++ + 4 files changed, 44 insertions(+), 4 deletions(-) + +--- a/drivers/serial/8250.c ++++ b/drivers/serial/8250.c +@@ -300,6 +300,13 @@ static const struct serial8250_config ua + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, + .flags = UART_CAP_FIFO | UART_CAP_AFE, + }, ++ [PORT_U6_16550A] = { ++ .name = "U6_16550A", ++ .fifo_size = 64, ++ .tx_loadsz = 64, ++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, ++ .flags = UART_CAP_FIFO | UART_CAP_AFE, ++ }, + }; + + #if defined (CONFIG_SERIAL_8250_AU1X00) +@@ -1075,6 +1082,15 @@ static void autoconfig_16550a(struct uar + DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 "); + } + serial_outp(up, UART_IER, iersave); ++ ++ /* ++ * We distinguish between 16550A and U6 16550A by counting ++ * how many bytes are in the FIFO. ++ */ ++ if (up->port.type == PORT_16550A && size_fifo(up) == 64) { ++ up->port.type = PORT_U6_16550A; ++ up->capabilities |= UART_CAP_AFE; ++ } + } + + /* +@@ -2229,9 +2245,9 @@ static unsigned int serial8250_get_divis + return quot; + } + +-static void +-serial8250_set_termios(struct uart_port *port, struct ktermios *termios, +- struct ktermios *old) ++void ++serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, ++ struct ktermios *old) + { + struct uart_8250_port *up = (struct uart_8250_port *)port; + unsigned char cval, fcr = 0; +@@ -2407,6 +2423,17 @@ serial8250_set_termios(struct uart_port + if (tty_termios_baud_rate(termios)) + tty_termios_encode_baud_rate(termios, baud, baud); + } ++EXPORT_SYMBOL(serial8250_do_set_termios); ++ ++static void ++serial8250_set_termios(struct uart_port *port, struct ktermios *termios, ++ struct ktermios *old) ++{ ++ if (port->set_termios) ++ port->set_termios(port, termios, old); ++ else ++ serial8250_do_set_termios(port, termios, old); ++} + + static void + serial8250_set_ldisc(struct uart_port *port, int new) +@@ -2989,6 +3016,7 @@ static int __devinit serial8250_probe(st + port.type = p->type; + port.serial_in = p->serial_in; + port.serial_out = p->serial_out; ++ port.set_termios = p->set_termios; + port.dev = &dev->dev; + port.irqflags |= irqflag; + ret = serial8250_register_port(&port); +@@ -3152,6 +3180,9 @@ int serial8250_register_port(struct uart + uart->port.serial_in = port->serial_in; + if (port->serial_out) + uart->port.serial_out = port->serial_out; ++ /* Possibly override set_termios call */ ++ if (port->set_termios) ++ uart->port.set_termios = port->set_termios; + + ret = uart_add_one_port(&serial8250_reg, &uart->port); + if (ret == 0) +--- a/include/linux/serial.h ++++ b/include/linux/serial.h +@@ -77,7 +77,8 @@ struct serial_struct { + #define PORT_16654 11 + #define PORT_16850 12 + #define PORT_RSA 13 /* RSA-DV II/S card */ +-#define PORT_MAX 13 ++#define PORT_U6_16550A 14 ++#define PORT_MAX 14 + + #define SERIAL_IO_PORT 0 + #define SERIAL_IO_HUB6 1 +--- a/include/linux/serial_8250.h ++++ b/include/linux/serial_8250.h +@@ -32,6 +32,9 @@ struct plat_serial8250_port { + unsigned int type; /* If UPF_FIXED_TYPE */ + unsigned int (*serial_in)(struct uart_port *, int); + void (*serial_out)(struct uart_port *, int, int); ++ void (*set_termios)(struct uart_port *, ++ struct ktermios *new, ++ struct ktermios *old); + }; + + /* +@@ -71,5 +74,7 @@ extern int early_serial_setup(struct uar + extern int serial8250_find_port(struct uart_port *p); + extern int serial8250_find_port_for_earlycon(void); + extern int setup_early_serial8250_console(char *cmdline); ++extern void serial8250_do_set_termios(struct uart_port *port, ++ struct ktermios *termios, struct ktermios *old); + + #endif +--- a/include/linux/serial_core.h ++++ b/include/linux/serial_core.h +@@ -282,6 +282,9 @@ struct uart_port { + unsigned char __iomem *membase; /* read/write[bwl] */ + unsigned int (*serial_in)(struct uart_port *, int); + void (*serial_out)(struct uart_port *, int, int); ++ void (*set_termios)(struct uart_port *, ++ struct ktermios *new, ++ struct ktermios *old); + unsigned int irq; /* irq number */ + unsigned long irqflags; /* irq flags */ + unsigned int uartclk; /* base uart clock */ diff --git a/usb/usb-accept-rndis-configs-if-there-s-no-alternative.patch b/usb/usb-accept-rndis-configs-if-there-s-no-alternative.patch new file mode 100644 index 00000000000000..bf94191771ec64 --- /dev/null +++ b/usb/usb-accept-rndis-configs-if-there-s-no-alternative.patch @@ -0,0 +1,40 @@ +From stern+4c5c36d6@rowland.harvard.edu Tue Jul 27 10:13:11 2010 +Date: Tue, 27 Jul 2010 11:28:42 -0400 (EDT) +From: Alan Stern <stern@rowland.harvard.edu> +To: Greg KH <greg@kroah.com> +cc: Adam Kropelin <akropel1@rochester.rr.com> +Subject: USB: accept RNDIS configs if there's no alternative +Message-ID: <Pine.LNX.4.44L0.1007271126520.1768-100000@iolanthe.rowland.org> + +This patch (as1410) makes a slight change to the strategy used for +choosing a default configuration. Currently we skip configs whose +first interface is RNDIS, if the kernel wasn't built with the +corresponding driver. This risks losing access to the other +interfaces in those configs. In addition, if there is only one config +then we will end up not configuring the device at all. + +This changes the logic; now such configurations will be skipped only +if there is at least one other config. + +Signed-off-by: Alan Stern <stern@rowland.harvard.edu> +Tested-by: Adam Kropelin <akropel1@rochester.rr.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/core/generic.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/usb/core/generic.c ++++ b/drivers/usb/core/generic.c +@@ -105,8 +105,10 @@ int usb_choose_configuration(struct usb_ + /* When the first config's first interface is one of Microsoft's + * pet nonstandard Ethernet-over-USB protocols, ignore it unless + * this kernel has enabled the necessary host side driver. ++ * But: Don't ignore it if it's the only config. + */ +- if (i == 0 && desc && (is_rndis(desc) || is_activesync(desc))) { ++ if (i == 0 && num_configs > 1 && desc && ++ (is_rndis(desc) || is_activesync(desc))) { + #if !defined(CONFIG_USB_NET_RNDIS_HOST) && !defined(CONFIG_USB_NET_RNDIS_HOST_MODULE) + continue; + #else diff --git a/usb/usb-add-of_platform-glue-driver-for-fsl-usb-dr-controller.patch b/usb/usb-add-of_platform-glue-driver-for-fsl-usb-dr-controller.patch deleted file mode 100644 index 0f12d9a906c03e..00000000000000 --- a/usb/usb-add-of_platform-glue-driver-for-fsl-usb-dr-controller.patch +++ /dev/null @@ -1,261 +0,0 @@ -From agust@denx.de Thu Jul 22 16:54:08 2010 -From: Anatolij Gustschin <agust@denx.de> -To: linux-usb@vger.kernel.org -Cc: linuxppc-dev@ozlabs.org, Greg Kroah-Hartman <gregkh@suse.de>, - David Brownell <dbrownell@users.sourceforge.net>, - Grant Likely <grant.likely@secretlab.ca>, - Detlev Zundel <dzu@denx.de>, Wolfgang Denk <wd@denx.de>, - Anatolij Gustschin <agust@denx.de>, - Kumar Gala <galak@kernel.crashing.org> -Subject: USB: add of_platform glue driver for FSL USB DR controller -Date: Thu, 22 Jul 2010 18:25:21 +0200 -Message-Id: <1279815922-27198-3-git-send-email-agust@denx.de> - -The driver creates platform devices based on the information -from USB nodes in the flat device tree. This is the replacement -for old arch fsl_soc usb code removed by the previous patch. -It uses usual of-style binding, available EHCI-HCD and UDC -drivers can be bound to the created devices. The new of-style -driver additionaly instantiates USB OTG platform device, as the -appropriate USB OTG driver will be added soon. - -Signed-off-by: Anatolij Gustschin <agust@denx.de> -Cc: Kumar Gala <galak@kernel.crashing.org> -Cc: Grant Likely <grant.likely@secretlab.ca> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/gadget/Kconfig | 1 - drivers/usb/host/Kconfig | 5 + - drivers/usb/host/Makefile | 1 - drivers/usb/host/fsl-mph-dr-of.c | 189 +++++++++++++++++++++++++++++++++++++++ - 4 files changed, 196 insertions(+) - ---- a/drivers/usb/gadget/Kconfig -+++ b/drivers/usb/gadget/Kconfig -@@ -158,6 +158,7 @@ config USB_GADGET_FSL_USB2 - boolean "Freescale Highspeed USB DR Peripheral Controller" - depends on FSL_SOC || ARCH_MXC - select USB_GADGET_DUALSPEED -+ select USB_FSL_MPH_DR_OF - help - Some of Freescale PowerPC processors have a High Speed - Dual-Role(DR) USB controller, which supports device mode. ---- a/drivers/usb/host/Kconfig -+++ b/drivers/usb/host/Kconfig -@@ -112,10 +112,15 @@ config XPS_USB_HCD_XILINX - support both high speed and full speed devices, or high speed - devices only. - -+config USB_FSL_MPH_DR_OF -+ bool -+ depends on PPC_OF -+ - config USB_EHCI_FSL - bool "Support for Freescale on-chip EHCI USB controller" - depends on USB_EHCI_HCD && FSL_SOC - select USB_EHCI_ROOT_HUB_TT -+ select USB_FSL_MPH_DR_OF - ---help--- - Variation of ARC USB block used in some Freescale chips. - ---- a/drivers/usb/host/Makefile -+++ b/drivers/usb/host/Makefile -@@ -33,4 +33,5 @@ obj-$(CONFIG_USB_R8A66597_HCD) += r8a665 - obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o - obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o - obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o -+obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o - ---- /dev/null -+++ b/drivers/usb/host/fsl-mph-dr-of.c -@@ -0,0 +1,189 @@ -+/* -+ * Setup platform devices needed by the Freescale multi-port host -+ * and/or dual-role USB controller modules based on the description -+ * in flat device tree. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/platform_device.h> -+#include <linux/fsl_devices.h> -+#include <linux/io.h> -+#include <linux/of_platform.h> -+ -+struct fsl_usb2_dev_data { -+ char *dr_mode; /* controller mode */ -+ char *drivers[3]; /* drivers to instantiate for this mode */ -+ enum fsl_usb2_operating_modes op_mode; /* operating mode */ -+}; -+ -+struct fsl_usb2_dev_data dr_mode_data[] __devinitdata = { -+ { -+ "host", -+ { "fsl-ehci", NULL, NULL, }, -+ FSL_USB2_DR_HOST, -+ }, -+ { -+ "otg", -+ { "fsl-ehci", "fsl-usb2-udc", "fsl-usb2-otg", }, -+ FSL_USB2_DR_OTG, -+ }, -+ { -+ "periferal", -+ { "fsl-usb2-udc", NULL, NULL, }, -+ FSL_USB2_DR_DEVICE, -+ }, -+}; -+ -+struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node *np) -+{ -+ const unsigned char *prop; -+ int i; -+ -+ prop = of_get_property(np, "dr_mode", NULL); -+ if (prop) { -+ for (i = 0; i < ARRAY_SIZE(dr_mode_data); i++) { -+ if (!strcmp(prop, dr_mode_data[i].dr_mode)) -+ return &dr_mode_data[i]; -+ } -+ } -+ return &dr_mode_data[0]; /* mode not specified, use host */ -+} -+ -+static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *phy_type) -+{ -+ if (!phy_type) -+ return FSL_USB2_PHY_NONE; -+ if (!strcasecmp(phy_type, "ulpi")) -+ return FSL_USB2_PHY_ULPI; -+ if (!strcasecmp(phy_type, "utmi")) -+ return FSL_USB2_PHY_UTMI; -+ if (!strcasecmp(phy_type, "utmi_wide")) -+ return FSL_USB2_PHY_UTMI_WIDE; -+ if (!strcasecmp(phy_type, "serial")) -+ return FSL_USB2_PHY_SERIAL; -+ -+ return FSL_USB2_PHY_NONE; -+} -+ -+struct platform_device * __devinit -+fsl_usb2_device_register(struct of_device *ofdev, -+ struct fsl_usb2_platform_data *pdata, -+ const char *name, int id) -+{ -+ struct platform_device *pdev; -+ const struct resource *res = ofdev->resource; -+ unsigned int num = ofdev->num_resources; -+ int retval; -+ -+ pdev = platform_device_alloc(name, id); -+ if (!pdev) { -+ retval = -ENOMEM; -+ goto error; -+ } -+ -+ pdev->dev.parent = &ofdev->dev; -+ -+ pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask; -+ pdev->dev.dma_mask = &pdev->archdata.dma_mask; -+ *pdev->dev.dma_mask = *ofdev->dev.dma_mask; -+ -+ retval = platform_device_add_data(pdev, pdata, sizeof(*pdata)); -+ if (retval) -+ goto error; -+ -+ if (num) { -+ retval = platform_device_add_resources(pdev, res, num); -+ if (retval) -+ goto error; -+ } -+ -+ retval = platform_device_add(pdev); -+ if (retval) -+ goto error; -+ -+ return pdev; -+ -+error: -+ platform_device_put(pdev); -+ return ERR_PTR(retval); -+} -+ -+static int __devinit fsl_usb2_mph_dr_of_probe(struct of_device *ofdev, -+ const struct of_device_id *match) -+{ -+ struct device_node *np = ofdev->dev.of_node; -+ struct platform_device *usb_dev; -+ struct fsl_usb2_platform_data data, *pdata; -+ struct fsl_usb2_dev_data *dev_data; -+ const unsigned char *prop; -+ static unsigned int idx; -+ int i; -+ -+ if (!of_device_is_available(np)) -+ return -ENODEV; -+ -+ pdata = match->data; -+ if (!pdata) { -+ memset(&data, 0, sizeof(data)); -+ pdata = &data; -+ } -+ -+ dev_data = get_dr_mode_data(np); -+ -+ if (of_device_is_compatible(np, "fsl-usb2-mph")) { -+ prop = of_get_property(np, "port0", NULL); -+ if (prop) -+ pdata->port_enables |= FSL_USB2_PORT0_ENABLED; -+ -+ prop = of_get_property(np, "port1", NULL); -+ if (prop) -+ pdata->port_enables |= FSL_USB2_PORT1_ENABLED; -+ -+ pdata->operating_mode = FSL_USB2_MPH_HOST; -+ } else { -+ /* setup mode selected in the device tree */ -+ pdata->operating_mode = dev_data->op_mode; -+ } -+ -+ prop = of_get_property(np, "phy_type", NULL); -+ pdata->phy_mode = determine_usb_phy(prop); -+ -+ for (i = 0; i < ARRAY_SIZE(dev_data->drivers); i++) { -+ if (!dev_data->drivers[i]) -+ continue; -+ usb_dev = fsl_usb2_device_register(ofdev, pdata, -+ dev_data->drivers[i], idx); -+ if (IS_ERR(usb_dev)) { -+ dev_err(&ofdev->dev, "Can't register usb device\n"); -+ return PTR_ERR(usb_dev); -+ } -+ } -+ idx++; -+ return 0; -+} -+ -+static const struct of_device_id fsl_usb2_mph_dr_of_match[] = { -+ { .compatible = "fsl-usb2-mph", }, -+ { .compatible = "fsl-usb2-dr", }, -+ {}, -+}; -+ -+static struct of_platform_driver fsl_usb2_mph_dr_driver = { -+ .driver = { -+ .name = "fsl-usb2-mph-dr", -+ .owner = THIS_MODULE, -+ .of_match_table = fsl_usb2_mph_dr_of_match, -+ }, -+ .probe = fsl_usb2_mph_dr_of_probe, -+}; -+ -+static int __init fsl_usb2_mph_dr_init(void) -+{ -+ return of_register_platform_driver(&fsl_usb2_mph_dr_driver); -+} -+fs_initcall(fsl_usb2_mph_dr_init); diff --git a/usb/usb-add-usb-2.0-to-ssb-ohci-driver.patch b/usb/usb-add-usb-2.0-to-ssb-ohci-driver.patch new file mode 100644 index 00000000000000..915151b6f379aa --- /dev/null +++ b/usb/usb-add-usb-2.0-to-ssb-ohci-driver.patch @@ -0,0 +1,99 @@ +From linux-usb-owner@vger.kernel.org Mon Aug 2 15:58:15 2010 +From: Hauke Mehrtens <hauke@hauke-m.de> +To: sshtylyov@mvista.com +Cc: linux-usb@vger.kernel.org, gregkh@suse.de, + Hauke Mehrtens <hauke@hauke-m.de>, + Steve Brown <sbrown@cortland.com> +Subject: USB: Add USB 2.0 to ssb ohci driver +Date: Wed, 28 Jul 2010 22:11:35 +0200 +Message-Id: <1280347895-4885-1-git-send-email-hauke@hauke-m.de> + +This adds USB 2.0 support to ssb ohci driver. +This patch was used in OpenWRT for a long time now. + +CC: Steve Brown <sbrown@cortland.com> +Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/ohci-ssb.c | 52 +++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 49 insertions(+), 3 deletions(-) + +--- a/drivers/usb/host/ohci-ssb.c ++++ b/drivers/usb/host/ohci-ssb.c +@@ -93,8 +93,11 @@ static void ssb_ohci_detach(struct ssb_d + { + struct usb_hcd *hcd = ssb_get_drvdata(dev); + ++ if (hcd->driver->shutdown) ++ hcd->driver->shutdown(hcd); + usb_remove_hcd(hcd); + iounmap(hcd->regs); ++ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + usb_put_hcd(hcd); + ssb_device_disable(dev, 0); + } +@@ -106,10 +109,52 @@ static int ssb_ohci_attach(struct ssb_de + int err = -ENOMEM; + u32 tmp, flags = 0; + +- if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) +- flags |= SSB_OHCI_TMSLOW_HOSTMODE; ++ if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) || ++ dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32))) ++ return -EOPNOTSUPP; + +- ssb_device_enable(dev, flags); ++ if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) { ++ /* Put the device into host-mode. */ ++ flags |= SSB_OHCI_TMSLOW_HOSTMODE; ++ ssb_device_enable(dev, flags); ++ } else if (dev->id.coreid == SSB_DEV_USB20_HOST) { ++ /* ++ * USB 2.0 special considerations: ++ * ++ * In addition to the standard SSB reset sequence, the Host ++ * Control Register must be programmed to bring the USB core ++ * and various phy components out of reset. ++ */ ++ ssb_device_enable(dev, 0); ++ ssb_write32(dev, 0x200, 0x7ff); ++ ++ /* Change Flush control reg */ ++ tmp = ssb_read32(dev, 0x400); ++ tmp &= ~8; ++ ssb_write32(dev, 0x400, tmp); ++ tmp = ssb_read32(dev, 0x400); ++ ++ /* Change Shim control reg */ ++ tmp = ssb_read32(dev, 0x304); ++ tmp &= ~0x100; ++ ssb_write32(dev, 0x304, tmp); ++ tmp = ssb_read32(dev, 0x304); ++ ++ udelay(1); ++ ++ /* Work around for 5354 failures */ ++ if (dev->id.revision == 2 && dev->bus->chip_id == 0x5354) { ++ /* Change syn01 reg */ ++ tmp = 0x00fe00fe; ++ ssb_write32(dev, 0x894, tmp); ++ ++ /* Change syn03 reg */ ++ tmp = ssb_read32(dev, 0x89c); ++ tmp |= 0x1; ++ ssb_write32(dev, 0x89c, tmp); ++ } ++ } else ++ ssb_device_enable(dev, 0); + + hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev, + dev_name(dev->dev)); +@@ -200,6 +245,7 @@ static int ssb_ohci_resume(struct ssb_de + static const struct ssb_device_id ssb_ohci_table[] = { + SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV), + SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV), ++ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV), + SSB_DEVTABLE_END + }; + MODULE_DEVICE_TABLE(ssb, ssb_ohci_table); diff --git a/usb/usb-add-usb-ehci-support-for-mpc5121-soc.patch b/usb/usb-add-usb-ehci-support-for-mpc5121-soc.patch deleted file mode 100644 index 6fa814f54f40e8..00000000000000 --- a/usb/usb-add-usb-ehci-support-for-mpc5121-soc.patch +++ /dev/null @@ -1,503 +0,0 @@ -From agust@denx.de Thu Jul 22 16:54:48 2010 -From: Anatolij Gustschin <agust@denx.de> -To: linux-usb@vger.kernel.org -Cc: linuxppc-dev@ozlabs.org, Greg Kroah-Hartman <gregkh@suse.de>, - David Brownell <dbrownell@users.sourceforge.net>, - Grant Likely <grant.likely@secretlab.ca>, - Detlev Zundel <dzu@denx.de>, Wolfgang Denk <wd@denx.de>, - Anatolij Gustschin <agust@denx.de> -Subject: USB: add USB EHCI support for MPC5121 SoC -Date: Thu, 22 Jul 2010 18:25:22 +0200 -Message-Id: <1279815922-27198-4-git-send-email-agust@denx.de> - -Extends FSL EHCI platform driver glue layer to support -MPC5121 USB controllers. MPC5121 Rev 2.0 silicon EHCI -registers are in big endian format. The appropriate flags -are set using the information in the platform data structure. -MPC83xx system interface registers are not available on -MPC512x, so the access to these registers is isolated in -MPC512x case. Furthermore the USB controller clocks -must be enabled before 512x register accesses which is -done by providing platform specific init callback. - -The MPC512x internal USB PHY doesn't provide supply voltage. -For boards using different power switches allow specifying -DRVVBUS and PWR_FAULT signal polarity of the MPC5121 internal -PHY using "fsl,invert-drvvbus" and "fsl,invert-pwr-fault" -properties in the device tree USB nodes. Adds documentation -for this new device tree bindings. - -Signed-off-by: Anatolij Gustschin <agust@denx.de> -Cc: Grant Likely <grant.likely@secretlab.ca> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - Documentation/powerpc/dts-bindings/fsl/usb.txt | 22 +++++ - drivers/usb/Kconfig | 1 - drivers/usb/host/Kconfig | 6 - - drivers/usb/host/ehci-fsl.c | 107 ++++++++++++++++++------- - drivers/usb/host/ehci-fsl.h | 19 ++++ - drivers/usb/host/ehci-mem.c | 2 - drivers/usb/host/fsl-mph-dr-of.c | 89 ++++++++++++++++++++ - include/linux/fsl_devices.h | 15 +++ - 8 files changed, 229 insertions(+), 32 deletions(-) - ---- a/Documentation/powerpc/dts-bindings/fsl/usb.txt -+++ b/Documentation/powerpc/dts-bindings/fsl/usb.txt -@@ -8,6 +8,7 @@ and additions : - Required properties : - - compatible : Should be "fsl-usb2-mph" for multi port host USB - controllers, or "fsl-usb2-dr" for dual role USB controllers -+ or "fsl,mpc5121-usb2-dr" for dual role USB controllers of MPC5121 - - phy_type : For multi port host USB controllers, should be one of - "ulpi", or "serial". For dual role USB controllers, should be - one of "ulpi", "utmi", "utmi_wide", or "serial". -@@ -33,6 +34,12 @@ Recommended properties : - - interrupt-parent : the phandle for the interrupt controller that - services interrupts for this device. - -+Optional properties : -+ - fsl,invert-drvvbus : boolean; for MPC5121 USB0 only. Indicates the -+ port power polarity of internal PHY signal DRVVBUS is inverted. -+ - fsl,invert-pwr-fault : boolean; for MPC5121 USB0 only. Indicates -+ the PWR_FAULT signal polarity is inverted. -+ - Example multi port host USB controller device node : - usb@22000 { - compatible = "fsl-usb2-mph"; -@@ -57,3 +64,18 @@ Example dual role USB controller device - dr_mode = "otg"; - phy = "ulpi"; - }; -+ -+Example dual role USB controller device node for MPC5121ADS: -+ -+ usb@4000 { -+ compatible = "fsl,mpc5121-usb2-dr"; -+ reg = <0x4000 0x1000>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ interrupt-parent = < &ipic >; -+ interrupts = <44 0x8>; -+ dr_mode = "otg"; -+ phy_type = "utmi_wide"; -+ fsl,invert-drvvbus; -+ fsl,invert-pwr-fault; -+ }; ---- a/drivers/usb/Kconfig -+++ b/drivers/usb/Kconfig -@@ -58,6 +58,7 @@ config USB_ARCH_HAS_OHCI - config USB_ARCH_HAS_EHCI - boolean - default y if PPC_83xx -+ default y if PPC_MPC512x - default y if SOC_AU1200 - default y if ARCH_IXP4XX - default y if ARCH_W90X900 ---- a/drivers/usb/host/Kconfig -+++ b/drivers/usb/host/Kconfig -@@ -93,12 +93,14 @@ config USB_EHCI_TT_NEWSCHED - - config USB_EHCI_BIG_ENDIAN_MMIO - bool -- depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX) -+ depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX || \ -+ XPS_USB_HCD_XILINX || PPC_MPC512x) - default y - - config USB_EHCI_BIG_ENDIAN_DESC - bool -- depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX) -+ depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \ -+ PPC_MPC512x) - default y - - config XPS_USB_HCD_XILINX ---- a/drivers/usb/host/ehci-fsl.c -+++ b/drivers/usb/host/ehci-fsl.c -@@ -116,13 +116,39 @@ static int usb_hcd_fsl_probe(const struc - goto err3; - } - -- /* Enable USB controller */ -- temp = in_be32(hcd->regs + 0x500); -- out_be32(hcd->regs + 0x500, temp | 0x4); -+ pdata->regs = hcd->regs; -+ -+ /* -+ * do platform specific init: check the clock, grab/config pins, etc. -+ */ -+ if (pdata->init && pdata->init(pdev)) { -+ retval = -ENODEV; -+ goto err3; -+ } -+ -+ /* -+ * Check if it is MPC5121 SoC, otherwise set pdata->have_sysif_regs -+ * flag for 83xx or 8536 system interface registers. -+ */ -+ if (pdata->big_endian_mmio) -+ temp = in_be32(hcd->regs + FSL_SOC_USB_ID); -+ else -+ temp = in_le32(hcd->regs + FSL_SOC_USB_ID); -+ -+ if ((temp & ID_MSK) != (~((temp & NID_MSK) >> 8) & ID_MSK)) -+ pdata->have_sysif_regs = 1; -+ -+ /* Enable USB controller, 83xx or 8536 */ -+ if (pdata->have_sysif_regs) -+ setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4); - - /* Set to Host mode */ -- temp = in_le32(hcd->regs + 0x1a8); -- out_le32(hcd->regs + 0x1a8, temp | 0x3); -+ if (pdata->big_endian_mmio) { -+ setbits32(hcd->regs + FSL_SOC_USB_USBMODE, USBMODE_CM_HOST); -+ } else { -+ clrsetbits_le32(hcd->regs + FSL_SOC_USB_USBMODE, -+ USBMODE_CM_MASK, USBMODE_CM_HOST); -+ } - - retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); - if (retval != 0) -@@ -137,6 +163,8 @@ static int usb_hcd_fsl_probe(const struc - usb_put_hcd(hcd); - err1: - dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval); -+ if (pdata->exit) -+ pdata->exit(pdev); - return retval; - } - -@@ -154,17 +182,30 @@ static int usb_hcd_fsl_probe(const struc - static void usb_hcd_fsl_remove(struct usb_hcd *hcd, - struct platform_device *pdev) - { -+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; -+ - usb_remove_hcd(hcd); -+ -+ /* -+ * do platform specific un-initialization: -+ * release iomux pins, disable clock, etc. -+ */ -+ if (pdata->exit) -+ pdata->exit(pdev); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - usb_put_hcd(hcd); - } - --static void mpc83xx_setup_phy(struct ehci_hcd *ehci, -- enum fsl_usb2_phy_modes phy_mode, -- unsigned int port_offset) -+static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, -+ enum fsl_usb2_phy_modes phy_mode, -+ unsigned int port_offset) - { -- u32 portsc = 0; -+ u32 portsc; -+ -+ portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]); -+ portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW); -+ - switch (phy_mode) { - case FSL_USB2_PHY_ULPI: - portsc |= PORT_PTS_ULPI; -@@ -184,20 +225,21 @@ static void mpc83xx_setup_phy(struct ehc - ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]); - } - --static void mpc83xx_usb_setup(struct usb_hcd *hcd) -+static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) - { -- struct ehci_hcd *ehci = hcd_to_ehci(hcd); -+ struct usb_hcd *hcd = ehci_to_hcd(ehci); - struct fsl_usb2_platform_data *pdata; - void __iomem *non_ehci = hcd->regs; - u32 temp; - -- pdata = -- (struct fsl_usb2_platform_data *)hcd->self.controller-> -- platform_data; -+ pdata = hcd->self.controller->platform_data; -+ - /* Enable PHY interface in the control reg. */ -- temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); -- out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004); -- out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b); -+ if (pdata->have_sysif_regs) { -+ temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); -+ out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004); -+ out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b); -+ } - - #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) - /* -@@ -214,7 +256,7 @@ static void mpc83xx_usb_setup(struct usb - - if ((pdata->operating_mode == FSL_USB2_DR_HOST) || - (pdata->operating_mode == FSL_USB2_DR_OTG)) -- mpc83xx_setup_phy(ehci, pdata->phy_mode, 0); -+ ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0); - - if (pdata->operating_mode == FSL_USB2_MPH_HOST) { - unsigned int chip, rev, svr; -@@ -228,27 +270,31 @@ static void mpc83xx_usb_setup(struct usb - ehci->has_fsl_port_bug = 1; - - if (pdata->port_enables & FSL_USB2_PORT0_ENABLED) -- mpc83xx_setup_phy(ehci, pdata->phy_mode, 0); -+ ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0); - if (pdata->port_enables & FSL_USB2_PORT1_ENABLED) -- mpc83xx_setup_phy(ehci, pdata->phy_mode, 1); -+ ehci_fsl_setup_phy(ehci, pdata->phy_mode, 1); - } - - /* put controller in host mode. */ -- ehci_writel(ehci, 0x00000003, non_ehci + FSL_SOC_USB_USBMODE); -+ temp = USBMODE_CM_HOST | (pdata->es ? USBMODE_ES : 0); -+ ehci_writel(ehci, temp, non_ehci + FSL_SOC_USB_USBMODE); -+ -+ if (pdata->have_sysif_regs) { - #ifdef CONFIG_PPC_85xx -- out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008); -- out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080); -+ out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008); -+ out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080); - #else -- out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c); -- out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040); -+ out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c); -+ out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040); - #endif -- out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); -+ out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); -+ } - } - - /* called after powerup, by probe or system-pm "wakeup" */ - static int ehci_fsl_reinit(struct ehci_hcd *ehci) - { -- mpc83xx_usb_setup(ehci_to_hcd(ehci)); -+ ehci_fsl_usb_setup(ehci); - ehci_port_power(ehci, 0); - - return 0; -@@ -259,6 +305,11 @@ static int ehci_fsl_setup(struct usb_hcd - { - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; -+ struct fsl_usb2_platform_data *pdata; -+ -+ pdata = hcd->self.controller->platform_data; -+ ehci->big_endian_desc = pdata->big_endian_desc; -+ ehci->big_endian_mmio = pdata->big_endian_mmio; - - /* EHCI registers start at offset 0x100 */ - ehci->caps = hcd->regs + 0x100; -@@ -372,7 +423,7 @@ static const struct hc_driver ehci_fsl_h - * generic hardware linkage - */ - .irq = ehci_irq, -- .flags = HCD_USB2, -+ .flags = HCD_USB2 | HCD_MEMORY, - - /* - * basic lifecycle operations ---- a/drivers/usb/host/ehci-fsl.h -+++ b/drivers/usb/host/ehci-fsl.h -@@ -1,4 +1,4 @@ --/* Copyright (c) 2005 freescale semiconductor -+/* Copyright (C) 2005-2010 Freescale Semiconductor, Inc. - * Copyright (c) 2005 MontaVista Software - * - * This program is free software; you can redistribute it and/or modify it -@@ -19,6 +19,11 @@ - #define _EHCI_FSL_H - - /* offsets for the non-ehci registers in the FSL SOC USB controller */ -+#define FSL_SOC_USB_ID 0x0 -+#define ID_MSK 0x3f -+#define NID_MSK 0x3f00 -+#define FSL_SOC_USB_SBUSCFG 0x90 -+#define FSL_SOC_USB_BURSTSIZE 0x160 - #define FSL_SOC_USB_ULPIVP 0x170 - #define FSL_SOC_USB_PORTSC1 0x184 - #define PORT_PTS_MSK (3<<30) -@@ -26,8 +31,20 @@ - #define PORT_PTS_ULPI (2<<30) - #define PORT_PTS_SERIAL (3<<30) - #define PORT_PTS_PTW (1<<28) -+#define PORT_PTS_PHCD (1<<23) - #define FSL_SOC_USB_PORTSC2 0x188 - #define FSL_SOC_USB_USBMODE 0x1a8 -+#define USBMODE_CM_MASK (3 << 0) /* controller mode mask */ -+#define USBMODE_CM_HOST (3 << 0) /* controller mode: host */ -+#define USBMODE_ES (1 << 2) /* (Big) Endian Select */ -+ -+#define FSL_SOC_USB_USBGENCTRL 0x200 -+#define USBGENCTRL_PPP (1 << 3) -+#define USBGENCTRL_PFP (1 << 2) -+#define FSL_SOC_USB_ISIPHYCTRL 0x204 -+#define ISIPHYCTRL_PXE (1) -+#define ISIPHYCTRL_PHYE (1 << 4) -+ - #define FSL_SOC_USB_SNOOP1 0x400 /* NOTE: big-endian */ - #define FSL_SOC_USB_SNOOP2 0x404 /* NOTE: big-endian */ - #define FSL_SOC_USB_AGECNTTHRSH 0x408 /* NOTE: big-endian */ ---- a/drivers/usb/host/ehci-mem.c -+++ b/drivers/usb/host/ehci-mem.c -@@ -40,7 +40,7 @@ static inline void ehci_qtd_init(struct - { - memset (qtd, 0, sizeof *qtd); - qtd->qtd_dma = dma; -- qtd->hw_token = cpu_to_le32 (QTD_STS_HALT); -+ qtd->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT); - qtd->hw_next = EHCI_LIST_END(ehci); - qtd->hw_alt_next = EHCI_LIST_END(ehci); - INIT_LIST_HEAD (&qtd->qtd_list); ---- a/drivers/usb/host/fsl-mph-dr-of.c -+++ b/drivers/usb/host/fsl-mph-dr-of.c -@@ -14,6 +14,7 @@ - #include <linux/fsl_devices.h> - #include <linux/io.h> - #include <linux/of_platform.h> -+#include <linux/clk.h> - - struct fsl_usb2_dev_data { - char *dr_mode; /* controller mode */ -@@ -146,6 +147,12 @@ static int __devinit fsl_usb2_mph_dr_of_ - - pdata->operating_mode = FSL_USB2_MPH_HOST; - } else { -+ if (of_get_property(np, "fsl,invert-drvvbus", NULL)) -+ pdata->invert_drvvbus = 1; -+ -+ if (of_get_property(np, "fsl,invert-pwr-fault", NULL)) -+ pdata->invert_pwr_fault = 1; -+ - /* setup mode selected in the device tree */ - pdata->operating_mode = dev_data->op_mode; - } -@@ -167,9 +174,91 @@ static int __devinit fsl_usb2_mph_dr_of_ - return 0; - } - -+#ifdef CONFIG_PPC_MPC512x -+ -+#define USBGENCTRL 0x200 /* NOTE: big endian */ -+#define GC_WU_INT_CLR (1 << 5) /* Wakeup int clear */ -+#define GC_ULPI_SEL (1 << 4) /* ULPI i/f select (usb0 only)*/ -+#define GC_PPP (1 << 3) /* Inv. Port Power Polarity */ -+#define GC_PFP (1 << 2) /* Inv. Power Fault Polarity */ -+#define GC_WU_ULPI_EN (1 << 1) /* Wakeup on ULPI event */ -+#define GC_WU_IE (1 << 1) /* Wakeup interrupt enable */ -+ -+#define ISIPHYCTRL 0x204 /* NOTE: big endian */ -+#define PHYCTRL_PHYE (1 << 4) /* On-chip UTMI PHY enable */ -+#define PHYCTRL_BSENH (1 << 3) /* Bit Stuff Enable High */ -+#define PHYCTRL_BSEN (1 << 2) /* Bit Stuff Enable */ -+#define PHYCTRL_LSFE (1 << 1) /* Line State Filter Enable */ -+#define PHYCTRL_PXE (1 << 0) /* PHY oscillator enable */ -+ -+int fsl_usb2_mpc5121_init(struct platform_device *pdev) -+{ -+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; -+ struct clk *clk; -+ char clk_name[10]; -+ int base, clk_num; -+ -+ base = pdev->resource->start & 0xf000; -+ if (base == 0x3000) -+ clk_num = 1; -+ else if (base == 0x4000) -+ clk_num = 2; -+ else -+ return -ENODEV; -+ -+ snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num); -+ clk = clk_get(&pdev->dev, clk_name); -+ if (IS_ERR(clk)) { -+ dev_err(&pdev->dev, "failed to get clk\n"); -+ return PTR_ERR(clk); -+ } -+ -+ clk_enable(clk); -+ pdata->clk = clk; -+ -+ if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) { -+ u32 reg = 0; -+ -+ if (pdata->invert_drvvbus) -+ reg |= GC_PPP; -+ -+ if (pdata->invert_pwr_fault) -+ reg |= GC_PFP; -+ -+ out_be32(pdata->regs + ISIPHYCTRL, PHYCTRL_PHYE | PHYCTRL_PXE); -+ out_be32(pdata->regs + USBGENCTRL, reg); -+ } -+ return 0; -+} -+ -+static void fsl_usb2_mpc5121_exit(struct platform_device *pdev) -+{ -+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; -+ -+ pdata->regs = NULL; -+ -+ if (pdata->clk) { -+ clk_disable(pdata->clk); -+ clk_put(pdata->clk); -+ } -+} -+ -+struct fsl_usb2_platform_data fsl_usb2_mpc5121_pd = { -+ .big_endian_desc = 1, -+ .big_endian_mmio = 1, -+ .es = 1, -+ .le_setup_buf = 1, -+ .init = fsl_usb2_mpc5121_init, -+ .exit = fsl_usb2_mpc5121_exit, -+}; -+#endif /* CONFIG_PPC_MPC512x */ -+ - static const struct of_device_id fsl_usb2_mph_dr_of_match[] = { - { .compatible = "fsl-usb2-mph", }, - { .compatible = "fsl-usb2-dr", }, -+#ifdef CONFIG_PPC_MPC512x -+ { .compatible = "fsl,mpc5121-usb2-dr", .data = &fsl_usb2_mpc5121_pd, }, -+#endif - {}, - }; - ---- a/include/linux/fsl_devices.h -+++ b/include/linux/fsl_devices.h -@@ -58,11 +58,26 @@ enum fsl_usb2_phy_modes { - FSL_USB2_PHY_SERIAL, - }; - -+struct clk; -+struct platform_device; -+ - struct fsl_usb2_platform_data { - /* board specific information */ - enum fsl_usb2_operating_modes operating_mode; - enum fsl_usb2_phy_modes phy_mode; - unsigned int port_enables; -+ -+ int (*init)(struct platform_device *); -+ void (*exit)(struct platform_device *); -+ void __iomem *regs; /* ioremap'd register base */ -+ struct clk *clk; -+ unsigned big_endian_mmio:1; -+ unsigned big_endian_desc:1; -+ unsigned es:1; /* need USBMODE:ES */ -+ unsigned le_setup_buf:1; -+ unsigned have_sysif_regs:1; -+ unsigned invert_drvvbus:1; -+ unsigned invert_pwr_fault:1; - }; - - /* Flags in fsl_usb2_mph_platform_data */ diff --git a/usb/usb-add-usb-serial-ssu100-driver.patch b/usb/usb-add-usb-serial-ssu100-driver.patch new file mode 100644 index 00000000000000..730854de6a9568 --- /dev/null +++ b/usb/usb-add-usb-serial-ssu100-driver.patch @@ -0,0 +1,749 @@ +From linux-usb-owner@vger.kernel.org Mon Aug 2 16:03:42 2010 +From: Bill Pemberton <wfp5p@virginia.edu> +To: linux-usb@vger.kernel.org +Subject: [PATCH] USB: add USB serial ssu100 driver +Date: Thu, 29 Jul 2010 11:05:41 -0400 +Message-Id: <1280415941-21770-1-git-send-email-wfp5p@virginia.edu> + +Add support for the Quatech SSU-100 single port usb to serial device. +This driver is based on the ftdi_sio.c driver and the original +serqt_usb driver from Quatech. + +Signed-off-by: Bill Pemberton <wfp5p@virginia.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/Kconfig | 9 + drivers/usb/serial/Makefile | 1 + drivers/usb/serial/ssu100.c | 698 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 708 insertions(+) + +--- a/drivers/usb/serial/Kconfig ++++ b/drivers/usb/serial/Kconfig +@@ -642,6 +642,15 @@ config USB_SERIAL_ZIO + To compile this driver as a module, choose M here: the + module will be called zio. + ++config USB_SERIAL_SSU100 ++ tristate "USB Quatech SSU-100 Single Port Serial Driver" ++ help ++ Say Y here if you want to use the Quatech SSU-100 single ++ port usb to serial adapter. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called ssu100. ++ + config USB_SERIAL_DEBUG + tristate "USB Debugging Device" + help +--- a/drivers/usb/serial/Makefile ++++ b/drivers/usb/serial/Makefile +@@ -51,6 +51,7 @@ obj-$(CONFIG_USB_SERIAL_SAFE) += safe_ + obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o + obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o + obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o ++obj-$(CONFIG_USB_SERIAL_SSU100) += ssu100.o + obj-$(CONFIG_USB_SERIAL_SYMBOL) += symbolserial.o + obj-$(CONFIG_USB_SERIAL_WWAN) += usb_wwan.o + obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o +--- /dev/null ++++ b/drivers/usb/serial/ssu100.c +@@ -0,0 +1,698 @@ ++/* ++ * usb-serial driver for Quatech SSU-100 ++ * ++ * based on ftdi_sio.c and the original serqt_usb.c from Quatech ++ * ++ */ ++ ++#include <linux/errno.h> ++#include <linux/init.h> ++#include <linux/slab.h> ++#include <linux/tty.h> ++#include <linux/tty_driver.h> ++#include <linux/tty_flip.h> ++#include <linux/module.h> ++#include <linux/serial.h> ++#include <linux/usb.h> ++#include <linux/usb/serial.h> ++#include <linux/uaccess.h> ++ ++#define QT_OPEN_CLOSE_CHANNEL 0xca ++#define QT_SET_GET_DEVICE 0xc2 ++#define QT_SET_GET_REGISTER 0xc0 ++#define QT_GET_SET_PREBUF_TRIG_LVL 0xcc ++#define QT_SET_ATF 0xcd ++#define QT_GET_SET_UART 0xc1 ++#define QT_TRANSFER_IN 0xc0 ++#define QT_HW_FLOW_CONTROL_MASK 0xc5 ++#define QT_SW_FLOW_CONTROL_MASK 0xc6 ++ ++#define MODEM_CTL_REGISTER 0x04 ++#define MODEM_STATUS_REGISTER 0x06 ++ ++ ++#define SERIAL_LSR_OE 0x02 ++#define SERIAL_LSR_PE 0x04 ++#define SERIAL_LSR_FE 0x08 ++#define SERIAL_LSR_BI 0x10 ++ ++#define SERIAL_LSR_TEMT 0x40 ++ ++#define SERIAL_MCR_DTR 0x01 ++#define SERIAL_MCR_RTS 0x02 ++#define SERIAL_MCR_LOOP 0x10 ++ ++#define SERIAL_MSR_CTS 0x10 ++#define SERIAL_MSR_CD 0x80 ++#define SERIAL_MSR_RI 0x40 ++#define SERIAL_MSR_DSR 0x20 ++#define SERIAL_MSR_MASK 0xf0 ++ ++#define SERIAL_CRTSCTS ((SERIAL_MCR_RTS << 8) | SERIAL_MSR_CTS) ++ ++#define SERIAL_8_DATA 0x03 ++#define SERIAL_7_DATA 0x02 ++#define SERIAL_6_DATA 0x01 ++#define SERIAL_5_DATA 0x00 ++ ++#define SERIAL_ODD_PARITY 0X08 ++#define SERIAL_EVEN_PARITY 0X18 ++ ++#define MAX_BAUD_RATE 460800 ++ ++#define ATC_DISABLED 0x00 ++#define DUPMODE_BITS 0xc0 ++#define RR_BITS 0x03 ++#define LOOPMODE_BITS 0x41 ++#define RS232_MODE 0x00 ++#define RTSCTS_TO_CONNECTOR 0x40 ++#define CLKS_X4 0x02 ++#define FULLPWRBIT 0x00000080 ++#define NEXT_BOARD_POWER_BIT 0x00000004 ++ ++static int debug = 1; ++ ++/* Version Information */ ++#define DRIVER_VERSION "v0.1" ++#define DRIVER_DESC "Quatech SSU-100 USB to Serial Driver" ++ ++#define USB_VENDOR_ID_QUATECH 0x061d /* Quatech VID */ ++#define QUATECH_SSU100 0xC020 /* SSU100 */ ++ ++static const struct usb_device_id id_table[] = { ++ {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU100)}, ++ {} /* Terminating entry */ ++}; ++ ++MODULE_DEVICE_TABLE(usb, id_table); ++ ++ ++static struct usb_driver ssu100_driver = { ++ .name = "ssu100", ++ .probe = usb_serial_probe, ++ .disconnect = usb_serial_disconnect, ++ .id_table = id_table, ++ .suspend = usb_serial_suspend, ++ .resume = usb_serial_resume, ++ .no_dynamic_id = 1, ++ .supports_autosuspend = 1, ++}; ++ ++struct ssu100_port_private { ++ u8 shadowLSR; ++ u8 shadowMSR; ++ wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ ++ unsigned short max_packet_size; ++}; ++ ++static void ssu100_release(struct usb_serial *serial) ++{ ++ struct ssu100_port_private *priv = usb_get_serial_port_data(*serial->port); ++ ++ dbg("%s", __func__); ++ kfree(priv); ++} ++ ++static inline int ssu100_control_msg(struct usb_device *dev, ++ u8 request, u16 data, u16 index) ++{ ++ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ++ request, 0x40, data, index, ++ NULL, 0, 300); ++} ++ ++static inline int ssu100_setdevice(struct usb_device *dev, u8 *data) ++{ ++ u16 x = ((u16)(data[1] << 8) | (u16)(data[0])); ++ ++ return ssu100_control_msg(dev, QT_SET_GET_DEVICE, x, 0); ++} ++ ++ ++static inline int ssu100_getdevice(struct usb_device *dev, u8 *data) ++{ ++ return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ++ QT_SET_GET_DEVICE, 0xc0, 0, 0, ++ data, 3, 300); ++} ++ ++static inline int ssu100_getregister(struct usb_device *dev, ++ unsigned short uart, ++ unsigned short reg, ++ u8 *data) ++{ ++ return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ++ QT_SET_GET_REGISTER, 0xc0, reg, ++ uart, data, sizeof(*data), 300); ++ ++} ++ ++ ++static inline int ssu100_setregister(struct usb_device *dev, ++ unsigned short uart, ++ u16 data) ++{ ++ u16 value = (data << 8) | MODEM_CTL_REGISTER; ++ ++ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ++ QT_SET_GET_REGISTER, 0x40, value, uart, ++ NULL, 0, 300); ++ ++} ++ ++#define set_mctrl(dev, set) update_mctrl((dev), (set), 0) ++#define clear_mctrl(dev, clear) update_mctrl((dev), 0, (clear)) ++ ++/* these do not deal with device that have more than 1 port */ ++static inline int update_mctrl(struct usb_device *dev, unsigned int set, ++ unsigned int clear) ++{ ++ unsigned urb_value; ++ int result; ++ ++ if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) { ++ dbg("%s - DTR|RTS not being set|cleared", __func__); ++ return 0; /* no change */ ++ } ++ ++ clear &= ~set; /* 'set' takes precedence over 'clear' */ ++ urb_value = 0; ++ if (set & TIOCM_DTR) ++ urb_value |= SERIAL_MCR_DTR; ++ if (set & TIOCM_RTS) ++ urb_value |= SERIAL_MCR_RTS; ++ ++ result = ssu100_setregister(dev, 0, urb_value); ++ if (result < 0) ++ dbg("%s Error from MODEM_CTRL urb", __func__); ++ ++ return result; ++} ++ ++static int ssu100_initdevice(struct usb_device *dev) ++{ ++ u8 *data; ++ int result = 0; ++ ++ dbg("%s", __func__); ++ ++ data = kzalloc(3, GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ result = ssu100_getdevice(dev, data); ++ if (result < 0) { ++ dbg("%s - get_device failed %i", __func__, result); ++ goto out; ++ } ++ ++ data[1] &= ~FULLPWRBIT; ++ ++ result = ssu100_setdevice(dev, data); ++ if (result < 0) { ++ dbg("%s - setdevice failed %i", __func__, result); ++ goto out; ++ } ++ ++ result = ssu100_control_msg(dev, QT_GET_SET_PREBUF_TRIG_LVL, 128, 0); ++ if (result < 0) { ++ dbg("%s - set prebuffer level failed %i", __func__, result); ++ goto out; ++ } ++ ++ result = ssu100_control_msg(dev, QT_SET_ATF, ATC_DISABLED, 0); ++ if (result < 0) { ++ dbg("%s - set ATFprebuffer level failed %i", __func__, result); ++ goto out; ++ } ++ ++ result = ssu100_getdevice(dev, data); ++ if (result < 0) { ++ dbg("%s - get_device failed %i", __func__, result); ++ goto out; ++ } ++ ++ data[0] &= ~(RR_BITS | DUPMODE_BITS); ++ data[0] |= CLKS_X4; ++ data[1] &= ~(LOOPMODE_BITS); ++ data[1] |= RS232_MODE; ++ ++ result = ssu100_setdevice(dev, data); ++ if (result < 0) { ++ dbg("%s - setdevice failed %i", __func__, result); ++ goto out; ++ } ++ ++out: kfree(data); ++ return result; ++ ++} ++ ++ ++static void ssu100_set_termios(struct tty_struct *tty, ++ struct usb_serial_port *port, ++ struct ktermios *old_termios) ++{ ++ struct usb_device *dev = port->serial->dev; ++ struct ktermios *termios = tty->termios; ++ u16 baud, divisor, remainder; ++ unsigned int cflag = termios->c_cflag; ++ u16 urb_value = 0; /* will hold the new flags */ ++ int result; ++ ++ dbg("%s", __func__); ++ ++ if (cflag & PARENB) { ++ if (cflag & PARODD) ++ urb_value |= SERIAL_ODD_PARITY; ++ else ++ urb_value |= SERIAL_EVEN_PARITY; ++ } ++ ++ switch (cflag & CSIZE) { ++ case CS5: ++ urb_value |= SERIAL_5_DATA; ++ break; ++ case CS6: ++ urb_value |= SERIAL_6_DATA; ++ break; ++ case CS7: ++ urb_value |= SERIAL_7_DATA; ++ break; ++ default: ++ case CS8: ++ urb_value |= SERIAL_8_DATA; ++ break; ++ } ++ ++ baud = tty_get_baud_rate(tty); ++ if (!baud) ++ baud = 9600; ++ ++ dbg("%s - got baud = %d\n", __func__, baud); ++ ++ ++ divisor = MAX_BAUD_RATE / baud; ++ remainder = MAX_BAUD_RATE % baud; ++ if (((remainder * 2) >= baud) && (baud != 110)) ++ divisor++; ++ ++ urb_value = urb_value << 8; ++ ++ result = ssu100_control_msg(dev, QT_GET_SET_UART, divisor, urb_value); ++ if (result < 0) ++ dbg("%s - set uart failed", __func__); ++ ++ if (cflag & CRTSCTS) ++ result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK, ++ SERIAL_CRTSCTS, 0); ++ else ++ result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK, ++ 0, 0); ++ if (result < 0) ++ dbg("%s - set HW flow control failed", __func__); ++ ++ if (I_IXOFF(tty) || I_IXON(tty)) { ++ u16 x = ((u16)(START_CHAR(tty) << 8) | (u16)(STOP_CHAR(tty))); ++ ++ result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK, ++ x, 0); ++ } else ++ result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK, ++ 0, 0); ++ ++ if (result < 0) ++ dbg("%s - set SW flow control failed", __func__); ++ ++} ++ ++ ++static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port) ++{ ++ struct usb_device *dev = port->serial->dev; ++ struct ssu100_port_private *priv = usb_get_serial_port_data(port); ++ u8 *data; ++ int result; ++ ++ dbg("%s - port %d", __func__, port->number); ++ ++ data = kzalloc(2, GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ++ QT_OPEN_CLOSE_CHANNEL, ++ QT_TRANSFER_IN, 0x01, ++ 0, data, 2, 300); ++ if (result < 0) { ++ dbg("%s - open failed %i", __func__, result); ++ kfree(data); ++ return result; ++ } ++ ++ priv->shadowLSR = data[0] & (SERIAL_LSR_OE | SERIAL_LSR_PE | ++ SERIAL_LSR_FE | SERIAL_LSR_BI); ++ ++ priv->shadowMSR = data[1] & (SERIAL_MSR_CTS | SERIAL_MSR_DSR | ++ SERIAL_MSR_RI | SERIAL_MSR_CD); ++ ++ kfree(data); ++ ++/* set to 9600 */ ++ result = ssu100_control_msg(dev, QT_GET_SET_UART, 0x30, 0x0300); ++ if (result < 0) ++ dbg("%s - set uart failed", __func__); ++ ++ if (tty) ++ ssu100_set_termios(tty, port, tty->termios); ++ ++ return usb_serial_generic_open(tty, port); ++} ++ ++static void ssu100_close(struct usb_serial_port *port) ++{ ++ dbg("%s", __func__); ++ usb_serial_generic_close(port); ++} ++ ++static int get_serial_info(struct usb_serial_port *port, ++ struct serial_struct __user *retinfo) ++{ ++ struct serial_struct tmp; ++ ++ if (!retinfo) ++ return -EFAULT; ++ ++ memset(&tmp, 0, sizeof(tmp)); ++ tmp.line = port->serial->minor; ++ tmp.port = 0; ++ tmp.irq = 0; ++ tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; ++ tmp.xmit_fifo_size = port->bulk_out_size; ++ tmp.baud_base = 9600; ++ tmp.close_delay = 5*HZ; ++ tmp.closing_wait = 30*HZ; ++ ++ if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) ++ return -EFAULT; ++ return 0; ++} ++ ++static int ssu100_ioctl(struct tty_struct *tty, struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ struct usb_serial_port *port = tty->driver_data; ++ struct ssu100_port_private *priv = usb_get_serial_port_data(port); ++ ++ dbg("%s cmd 0x%04x", __func__, cmd); ++ ++ switch (cmd) { ++ case TIOCGSERIAL: ++ return get_serial_info(port, ++ (struct serial_struct __user *) arg); ++ ++ case TIOCMIWAIT: ++ while (priv != NULL) { ++ u8 prevMSR = priv->shadowMSR & SERIAL_MSR_MASK; ++ interruptible_sleep_on(&priv->delta_msr_wait); ++ /* see if a signal did it */ ++ if (signal_pending(current)) ++ return -ERESTARTSYS; ++ else { ++ u8 diff = (priv->shadowMSR & SERIAL_MSR_MASK) ^ prevMSR; ++ if (!diff) ++ return -EIO; /* no change => error */ ++ ++ /* Return 0 if caller wanted to know about ++ these bits */ ++ ++ if (((arg & TIOCM_RNG) && (diff & SERIAL_MSR_RI)) || ++ ((arg & TIOCM_DSR) && (diff & SERIAL_MSR_DSR)) || ++ ((arg & TIOCM_CD) && (diff & SERIAL_MSR_CD)) || ++ ((arg & TIOCM_CTS) && (diff & SERIAL_MSR_CTS))) ++ return 0; ++ } ++ } ++ return 0; ++ ++ default: ++ break; ++ } ++ ++ dbg("%s arg not supported", __func__); ++ ++ return -ENOIOCTLCMD; ++} ++ ++static void ssu100_set_max_packet_size(struct usb_serial_port *port) ++{ ++ struct ssu100_port_private *priv = usb_get_serial_port_data(port); ++ struct usb_serial *serial = port->serial; ++ struct usb_device *udev = serial->dev; ++ ++ struct usb_interface *interface = serial->interface; ++ struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc; ++ ++ unsigned num_endpoints; ++ int i; ++ ++ num_endpoints = interface->cur_altsetting->desc.bNumEndpoints; ++ dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints); ++ ++ for (i = 0; i < num_endpoints; i++) { ++ dev_info(&udev->dev, "Endpoint %d MaxPacketSize %d\n", i+1, ++ interface->cur_altsetting->endpoint[i].desc.wMaxPacketSize); ++ ep_desc = &interface->cur_altsetting->endpoint[i].desc; ++ } ++ ++ /* set max packet size based on descriptor */ ++ priv->max_packet_size = ep_desc->wMaxPacketSize; ++ ++ dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size); ++} ++ ++static int ssu100_attach(struct usb_serial *serial) ++{ ++ struct ssu100_port_private *priv; ++ struct usb_serial_port *port = *serial->port; ++ ++ dbg("%s", __func__); ++ ++ priv = kzalloc(sizeof(*priv), GFP_KERNEL); ++ if (!priv) { ++ dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__, ++ sizeof(*priv)); ++ return -ENOMEM; ++ } ++ ++ init_waitqueue_head(&priv->delta_msr_wait); ++ usb_set_serial_port_data(port, priv); ++ ++ ssu100_set_max_packet_size(port); ++ ++ return ssu100_initdevice(serial->dev); ++} ++ ++static int ssu100_tiocmget(struct tty_struct *tty, struct file *file) ++{ ++ struct usb_serial_port *port = tty->driver_data; ++ struct usb_device *dev = port->serial->dev; ++ u8 *d; ++ int r; ++ ++ dbg("%s\n", __func__); ++ ++ d = kzalloc(2, GFP_KERNEL); ++ if (!d) ++ return -ENOMEM; ++ ++ r = ssu100_getregister(dev, 0, MODEM_CTL_REGISTER, d); ++ if (r < 0) ++ goto mget_out; ++ ++ r = ssu100_getregister(dev, 0, MODEM_STATUS_REGISTER, d+1); ++ if (r < 0) ++ goto mget_out; ++ ++ r = (d[0] & SERIAL_MCR_DTR ? TIOCM_DTR : 0) | ++ (d[0] & SERIAL_MCR_RTS ? TIOCM_RTS : 0) | ++ (d[1] & SERIAL_MSR_CTS ? TIOCM_CTS : 0) | ++ (d[1] & SERIAL_MSR_CD ? TIOCM_CAR : 0) | ++ (d[1] & SERIAL_MSR_RI ? TIOCM_RI : 0) | ++ (d[1] & SERIAL_MSR_DSR ? TIOCM_DSR : 0); ++ ++mget_out: ++ kfree(d); ++ return r; ++} ++ ++static int ssu100_tiocmset(struct tty_struct *tty, struct file *file, ++ unsigned int set, unsigned int clear) ++{ ++ struct usb_serial_port *port = tty->driver_data; ++ struct usb_device *dev = port->serial->dev; ++ ++ dbg("%s\n", __func__); ++ return update_mctrl(dev, set, clear); ++} ++ ++static void ssu100_dtr_rts(struct usb_serial_port *port, int on) ++{ ++ struct usb_device *dev = port->serial->dev; ++ ++ dbg("%s\n", __func__); ++ ++ mutex_lock(&port->serial->disc_mutex); ++ if (!port->serial->disconnected) { ++ /* Disable flow control */ ++ if (!on && ++ ssu100_setregister(dev, 0, 0) < 0) ++ dev_err(&port->dev, "error from flowcontrol urb\n"); ++ /* drop RTS and DTR */ ++ if (on) ++ set_mctrl(dev, TIOCM_DTR | TIOCM_RTS); ++ else ++ clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS); ++ } ++ mutex_unlock(&port->serial->disc_mutex); ++} ++ ++static int ssu100_process_packet(struct tty_struct *tty, ++ struct usb_serial_port *port, ++ struct ssu100_port_private *priv, ++ char *packet, int len) ++{ ++ int i; ++ char flag; ++ char *ch; ++ ++ dbg("%s - port %d", __func__, port->number); ++ ++ if (len < 4) { ++ dbg("%s - malformed packet", __func__); ++ return 0; ++ } ++ ++ if ((packet[0] == 0x1b) && (packet[1] == 0x1b) && ++ ((packet[2] == 0x00) || (packet[2] == 0x01))) { ++ if (packet[2] == 0x00) ++ priv->shadowLSR = packet[3] & (SERIAL_LSR_OE | ++ SERIAL_LSR_PE | ++ SERIAL_LSR_FE | ++ SERIAL_LSR_BI); ++ ++ if (packet[2] == 0x01) { ++ priv->shadowMSR = packet[3]; ++ wake_up_interruptible(&priv->delta_msr_wait); ++ } ++ ++ len -= 4; ++ ch = packet + 4; ++ } else ++ ch = packet; ++ ++ if (!len) ++ return 0; /* status only */ ++ ++ if (port->port.console && port->sysrq) { ++ for (i = 0; i < len; i++, ch++) { ++ if (!usb_serial_handle_sysrq_char(tty, port, *ch)) ++ tty_insert_flip_char(tty, *ch, flag); ++ } ++ } else ++ tty_insert_flip_string_fixed_flag(tty, ch, flag, len); ++ ++ return len; ++} ++ ++static void ssu100_process_read_urb(struct urb *urb) ++{ ++ struct usb_serial_port *port = urb->context; ++ struct ssu100_port_private *priv = usb_get_serial_port_data(port); ++ char *data = (char *)urb->transfer_buffer; ++ struct tty_struct *tty; ++ int count = 0; ++ int i; ++ int len; ++ ++ dbg("%s", __func__); ++ ++ tty = tty_port_tty_get(&port->port); ++ if (!tty) ++ return; ++ ++ for (i = 0; i < urb->actual_length; i += priv->max_packet_size) { ++ len = min_t(int, urb->actual_length - i, priv->max_packet_size); ++ count += ssu100_process_packet(tty, port, priv, &data[i], len); ++ } ++ ++ if (count) ++ tty_flip_buffer_push(tty); ++ tty_kref_put(tty); ++} ++ ++ ++static struct usb_serial_driver ssu100_device = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "ssu100", ++ }, ++ .description = DRIVER_DESC, ++ .id_table = id_table, ++ .usb_driver = &ssu100_driver, ++ .num_ports = 1, ++ .bulk_in_size = 256, ++ .bulk_out_size = 256, ++ .open = ssu100_open, ++ .close = ssu100_close, ++ .attach = ssu100_attach, ++ .release = ssu100_release, ++ .dtr_rts = ssu100_dtr_rts, ++ .process_read_urb = ssu100_process_read_urb, ++ .tiocmget = ssu100_tiocmget, ++ .tiocmset = ssu100_tiocmset, ++ .ioctl = ssu100_ioctl, ++ .set_termios = ssu100_set_termios, ++}; ++ ++static int __init ssu100_init(void) ++{ ++ int retval; ++ ++ dbg("%s", __func__); ++ ++ /* register with usb-serial */ ++ retval = usb_serial_register(&ssu100_device); ++ ++ if (retval) ++ goto failed_usb_sio_register; ++ ++ retval = usb_register(&ssu100_driver); ++ if (retval) ++ goto failed_usb_register; ++ ++ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" ++ DRIVER_DESC "\n"); ++ ++ return 0; ++ ++failed_usb_register: ++ usb_serial_deregister(&ssu100_device); ++failed_usb_sio_register: ++ return retval; ++} ++ ++static void __exit ssu100_exit(void) ++{ ++ usb_deregister(&ssu100_driver); ++ usb_serial_deregister(&ssu100_device); ++} ++ ++module_init(ssu100_init); ++module_exit(ssu100_exit); ++ ++MODULE_DESCRIPTION(DRIVER_DESC); ++MODULE_LICENSE("GPL"); ++ ++module_param(debug, bool, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(debug, "Debug enabled or not"); diff --git a/usb/usb-cp210x-add-four-new-device-ids.patch b/usb/usb-cp210x-add-four-new-device-ids.patch new file mode 100644 index 00000000000000..268f70a2fdee4f --- /dev/null +++ b/usb/usb-cp210x-add-four-new-device-ids.patch @@ -0,0 +1,33 @@ +From alessioigorbogani@gmail.com Mon Aug 2 15:57:57 2010 +From: Alessio Igor Bogani <abogani@texware.it> +To: Greg Kroah-Hartman <gregkh@suse.de>, + Craig Shelley <craig@microtron.org.uk>, + Johan Hovold <jhovold@gmail.com>, Alan Cox <alan@linux.intel.com>, + Michael Brunner <mibru@gmx.de> +Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, + Alessio Igor Bogani <abogani@texware.it> +Subject: USB: cp210x: Add four new device IDs +Date: Tue, 27 Jul 2010 23:05:14 +0200 +Message-Id: <1280264714-17175-1-git-send-email-abogani@texware.it> + +Signed-off-by: Alessio Igor Bogani <abogani@texware.it> +Cc: stable <stable@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/cp210x.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -126,6 +126,10 @@ static const struct usb_device_id id_tab + { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ + { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ + { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ ++ { USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */ ++ { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */ ++ { USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */ ++ { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */ + { } /* Terminating Entry */ + }; + diff --git a/usb/usb-ehci-fix-remove-of-ehci-debugfs-dir.patch b/usb/usb-ehci-fix-remove-of-ehci-debugfs-dir.patch new file mode 100644 index 00000000000000..0e1e8dcd96e44c --- /dev/null +++ b/usb/usb-ehci-fix-remove-of-ehci-debugfs-dir.patch @@ -0,0 +1,118 @@ +From tom.leiming@gmail.com Mon Aug 2 16:01:50 2010 +From: tom.leiming@gmail.com +To: greg@kroah.com, + stern@rowland.harvard.edu +Cc: linux-usb@vger.kernel.org, david-b@pacbell.net, alek.du@intel.com, Ming Lei <tom.leiming@gmail.com> +Subject: USB: ehci: fix remove of ehci debugfs dir +Date: Wed, 28 Jul 2010 22:33:28 +0800 +Message-Id: <1280327608-4376-1-git-send-email-tom.leiming@gmail.com> + +From: Ming Lei <tom.leiming@gmail.com> + +The patch below on gregkh tree only creates 'lpm' file under +ehci->debug_dir, but not removes it when unloading module, + + USB: EHCI: EHCI 1.1 addendum: preparation + +which can make loading of ehci-hcd module failed after unloading it. + +This patch replaces debugfs_remove with debugfs_remove_recursive +to remove ehci debugfs dir and files. It does fix the bug above, +and may simplify the removing procedure. + +Also, remove the debug_registers, debug_async and debug_periodic +field from ehci_hcd struct since they are useless now. + +Signed-off-by: Ming Lei <tom.leiming@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/ehci-dbg.c | 56 +++++++++++++++----------------------------- + drivers/usb/host/ehci.h | 4 --- + 2 files changed, 20 insertions(+), 40 deletions(-) + +--- a/drivers/usb/host/ehci-dbg.c ++++ b/drivers/usb/host/ehci-dbg.c +@@ -1049,49 +1049,33 @@ static inline void create_debug_files (s + + ehci->debug_dir = debugfs_create_dir(bus->bus_name, ehci_debug_root); + if (!ehci->debug_dir) +- goto dir_error; ++ return; ++ ++ if (!debugfs_create_file("async", S_IRUGO, ehci->debug_dir, bus, ++ &debug_async_fops)) ++ goto file_error; ++ ++ if (!debugfs_create_file("periodic", S_IRUGO, ehci->debug_dir, bus, ++ &debug_periodic_fops)) ++ goto file_error; ++ ++ if (!debugfs_create_file("registers", S_IRUGO, ehci->debug_dir, bus, ++ &debug_registers_fops)) ++ goto file_error; ++ ++ if (!debugfs_create_file("lpm", S_IRUGO|S_IWUGO, ehci->debug_dir, bus, ++ &debug_lpm_fops)) ++ goto file_error; + +- ehci->debug_async = debugfs_create_file("async", S_IRUGO, +- ehci->debug_dir, bus, +- &debug_async_fops); +- if (!ehci->debug_async) +- goto async_error; +- +- ehci->debug_periodic = debugfs_create_file("periodic", S_IRUGO, +- ehci->debug_dir, bus, +- &debug_periodic_fops); +- if (!ehci->debug_periodic) +- goto periodic_error; +- +- ehci->debug_registers = debugfs_create_file("registers", S_IRUGO, +- ehci->debug_dir, bus, +- &debug_registers_fops); +- +- ehci->debug_registers = debugfs_create_file("lpm", S_IRUGO|S_IWUGO, +- ehci->debug_dir, bus, +- &debug_lpm_fops); +- if (!ehci->debug_registers) +- goto registers_error; + return; + +-registers_error: +- debugfs_remove(ehci->debug_periodic); +-periodic_error: +- debugfs_remove(ehci->debug_async); +-async_error: +- debugfs_remove(ehci->debug_dir); +-dir_error: +- ehci->debug_periodic = NULL; +- ehci->debug_async = NULL; +- ehci->debug_dir = NULL; ++file_error: ++ debugfs_remove_recursive(ehci->debug_dir); + } + + static inline void remove_debug_files (struct ehci_hcd *ehci) + { +- debugfs_remove(ehci->debug_registers); +- debugfs_remove(ehci->debug_periodic); +- debugfs_remove(ehci->debug_async); +- debugfs_remove(ehci->debug_dir); ++ debugfs_remove_recursive(ehci->debug_dir); + } + + #endif /* STUB_DEBUG_FILES */ +--- a/drivers/usb/host/ehci.h ++++ b/drivers/usb/host/ehci.h +@@ -156,10 +156,6 @@ struct ehci_hcd { /* one per controlle + /* debug files */ + #ifdef DEBUG + struct dentry *debug_dir; +- struct dentry *debug_async; +- struct dentry *debug_periodic; +- struct dentry *debug_registers; +- struct dentry *debug_lpm; + #endif + }; + diff --git a/usb/usb-fix-linux-usb.h-kernel-doc-warnings.patch b/usb/usb-fix-linux-usb.h-kernel-doc-warnings.patch new file mode 100644 index 00000000000000..a3652d87fa661e --- /dev/null +++ b/usb/usb-fix-linux-usb.h-kernel-doc-warnings.patch @@ -0,0 +1,40 @@ +From linux-usb-owner@vger.kernel.org Mon Aug 2 16:04:48 2010 +Date: Thu, 29 Jul 2010 15:54:38 -0700 +From: Randy Dunlap <randy.dunlap@oracle.com> +Cc: gregkh@suse.de +Subject: USB:: fix linux/usb.h kernel-doc warnings +Message-Id: <20100729155438.d3a02177.randy.dunlap@oracle.com> + +From: Randy Dunlap <randy.dunlap@oracle.com> + +Fix kernel-doc warnings in linux/usb.h: + +Warning(include/linux/usb.h:185): No description found for parameter 'resetting_device' +Warning(include/linux/usb.h:1212): No description found for parameter 'stream_id' + +Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + include/linux/usb.h | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/include/linux/usb.h ++++ b/include/linux/usb.h +@@ -127,6 +127,8 @@ enum usb_interface_condition { + * queued reset so that usb_cancel_queued_reset() doesn't try to + * remove from the workqueue when running inside the worker + * thread. See __usb_queue_reset_device(). ++ * @resetting_device: USB core reset the device, so use alt setting 0 as ++ * current; needs bandwidth alloc after reset. + * + * USB device drivers attach to interfaces on a physical device. Each + * interface encapsulates a single high level function, such as feeding +@@ -1015,6 +1017,7 @@ typedef void (*usb_complete_t)(struct ur + * is a different endpoint (and pipe) from "out" endpoint two. + * The current configuration controls the existence, type, and + * maximum packet size of any given endpoint. ++ * @stream_id: the endpoint's stream ID for bulk streams + * @dev: Identifies the USB device to perform the request. + * @status: This is read in non-iso completion functions to get the + * status of the particular request. ISO requests only use it diff --git a/usb/usb-fix-stuck-usb-generic-serial-driver.patch b/usb/usb-fix-stuck-usb-generic-serial-driver.patch new file mode 100644 index 00000000000000..5beecacc94c3bc --- /dev/null +++ b/usb/usb-fix-stuck-usb-generic-serial-driver.patch @@ -0,0 +1,62 @@ +From dvomlehn@cisco.com Mon Aug 2 16:13:11 2010 +Date: Mon, 2 Aug 2010 10:46:00 -0700 +From: David VomLehn <dvomlehn@cisco.com> +To: linux-usb@vger.kernel.org +Cc: greg@kroah.com +Subject: USB: Fix stuck USB generic serial driver +Message-ID: <20100802174600.GA6845@dvomlehn-lnx2.corp.sa.net> +Content-Disposition: inline + +Fix USB console hang due to non-atomic URB allocation + +This is intended to fix a problem seen with the Amtel sam-ba tool by +Alexander Stein (alexander.stein@systec-electronic.com). It appears +when using an A91 controller. He bisected it to commit: + + 8e8dce065088833fc418bfa5fbf035cb0726c04c: USB: use kfifo to buffer usb-generic serial writes + +The current patch fixes a problem when using a USB serial device as the +kernel console and as /dev/console. The URB allocation is not atomic and +an URB can be doubly allocated, leading to a continual rejection of URB +submissions. The fix puts all pieces of the URB allocation in the same +spinlock-protected section of code. + +Having said that... + +This fix was developed because, after Alexander's email, I took a look +at my USB console and found that it, too, was experiencing a hang. I +assumed that this hang was the same as the one Alexander is seeing and +developed this fix. It's a good fix for *a* hang, but after thinking +about this a bit, I'm not sure this is a fix for *Alexander's* hang. + +Signed-off-by: David VomLehn <dvomlehn@cisco.com> +Cc: stable <stable@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/generic.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/usb/serial/generic.c ++++ b/drivers/usb/serial/generic.c +@@ -199,6 +199,9 @@ retry: + } + i = (int)find_first_bit(&port->write_urbs_free, + ARRAY_SIZE(port->write_urbs)); ++ if (i == ARRAY_SIZE(port->write_urbs)) ++ return 0; ++ clear_bit(i, &port->write_urbs_free); + spin_unlock_irqrestore(&port->lock, flags); + + urb = port->write_urbs[i]; +@@ -213,9 +216,9 @@ retry: + dev_err(&port->dev, "%s - error submitting urb: %d\n", + __func__, result); + clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags); ++ set_bit(i, &port->write_urbs_free); + return result; + } +- clear_bit(i, &port->write_urbs_free); + + spin_lock_irqsave(&port->lock, flags); + port->tx_bytes += count; diff --git a/usb/usb-ftdi_sio-device-id-for-navitator.patch b/usb/usb-ftdi_sio-device-id-for-navitator.patch new file mode 100644 index 00000000000000..0ca149c5391db9 --- /dev/null +++ b/usb/usb-ftdi_sio-device-id-for-navitator.patch @@ -0,0 +1,53 @@ +From dranch@trinnet.net Tue Jul 27 10:14:22 2010 +Date: Mon, 26 Jul 2010 19:44:33 -0700 +From: dranch@trinnet.net +To: greg@kroah.com, gregkh@suse.de, linux-kernel@vger.kernel.org +Cc: dranch@trinnet.net +Subject: USB: ftdi_sio: device id for Navitator +Message-ID: <20100727024433.GA29758@trinity4.trinnet.net> +Content-Disposition: inline + +This patch is to add a US Interface, Inc. "Navigator" USB device. +Specifically, it's a HAM Radio USB sound modem that also +incorporates three pairs of unique FTDI serial ports. The standard +Linux FTDI serial driver will only recognize the first two serial +ports of an unknown FDTI derived device and this patch adds in +recognition to these specific new IDs. + +Signed-off-by: David A. Ranch <dranch@trinnet.net> +Cc: stable <stable@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + + +--- + drivers/usb/serial/ftdi_sio.c | 3 +++ + drivers/usb/serial/ftdi_sio_ids.h | 5 +++++ + 2 files changed, 8 insertions(+) + +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -157,6 +157,9 @@ static struct usb_device_id id_table_com + { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_5_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_6_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_7_PID) }, ++ { USB_DEVICE(FTDI_VID, FTDI_USINT_CAT_PID) }, ++ { USB_DEVICE(FTDI_VID, FTDI_USINT_WKEY_PID) }, ++ { USB_DEVICE(FTDI_VID, FTDI_USINT_RS232_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) }, +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -40,6 +40,11 @@ + + #define FTDI_NXTCAM_PID 0xABB8 /* NXTCam for Mindstorms NXT */ + ++/* US Interface Navigator (http://www.usinterface.com/) */ ++#define FTDI_USINT_CAT_PID 0xb810 /* Navigator CAT and 2nd PTT lines */ ++#define FTDI_USINT_WKEY_PID 0xb811 /* Navigator WKEY and FSK lines */ ++#define FTDI_USINT_RS232_PID 0xb812 /* Navigator RS232 and CONFIG lines */ ++ + /* OOCDlink by Joern Kaipf <joernk@web.de> + * (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */ + #define FTDI_OOCDLINK_PID 0xbaf8 /* Amontec JTAGkey */ diff --git a/usb/usb-powerpc-fsl_soc.c-remove-fsl-usb-platform-code.patch b/usb/usb-powerpc-fsl_soc.c-remove-fsl-usb-platform-code.patch deleted file mode 100644 index a8fd3e68c83ae2..00000000000000 --- a/usb/usb-powerpc-fsl_soc.c-remove-fsl-usb-platform-code.patch +++ /dev/null @@ -1,198 +0,0 @@ -From agust@denx.de Thu Jul 22 16:53:55 2010 -From: Anatolij Gustschin <agust@denx.de> -To: linux-usb@vger.kernel.org -Cc: linuxppc-dev@ozlabs.org, Greg Kroah-Hartman <gregkh@suse.de>, - David Brownell <dbrownell@users.sourceforge.net>, - Grant Likely <grant.likely@secretlab.ca>, - Detlev Zundel <dzu@denx.de>, Wolfgang Denk <wd@denx.de>, - Anatolij Gustschin <agust@denx.de>, - Kumar Gala <galak@kernel.crashing.org> -Subject: USB: powerpc/fsl_soc.c: remove FSL USB platform code -Date: Thu, 22 Jul 2010 18:25:20 +0200 -Message-Id: <1279815922-27198-2-git-send-email-agust@denx.de> - -This removed code will be replaced by simple of_platform -driver for creation of FSL USB platform devices which is -added by next patch of the series. - -Signed-off-by: Anatolij Gustschin <agust@denx.de> -Cc: Kumar Gala <galak@kernel.crashing.org> -Cc: Grant Likely <grant.likely@secretlab.ca> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - arch/powerpc/sysdev/fsl_soc.c | 163 ------------------------------------------ - 1 file changed, 163 deletions(-) - ---- a/arch/powerpc/sysdev/fsl_soc.c -+++ b/arch/powerpc/sysdev/fsl_soc.c -@@ -209,169 +209,6 @@ static int __init of_add_fixed_phys(void - arch_initcall(of_add_fixed_phys); - #endif /* CONFIG_FIXED_PHY */ - --static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type) --{ -- if (!phy_type) -- return FSL_USB2_PHY_NONE; -- if (!strcasecmp(phy_type, "ulpi")) -- return FSL_USB2_PHY_ULPI; -- if (!strcasecmp(phy_type, "utmi")) -- return FSL_USB2_PHY_UTMI; -- if (!strcasecmp(phy_type, "utmi_wide")) -- return FSL_USB2_PHY_UTMI_WIDE; -- if (!strcasecmp(phy_type, "serial")) -- return FSL_USB2_PHY_SERIAL; -- -- return FSL_USB2_PHY_NONE; --} -- --static int __init fsl_usb_of_init(void) --{ -- struct device_node *np; -- unsigned int i = 0; -- struct platform_device *usb_dev_mph = NULL, *usb_dev_dr_host = NULL, -- *usb_dev_dr_client = NULL; -- int ret; -- -- for_each_compatible_node(np, NULL, "fsl-usb2-mph") { -- struct resource r[2]; -- struct fsl_usb2_platform_data usb_data; -- const unsigned char *prop = NULL; -- -- memset(&r, 0, sizeof(r)); -- memset(&usb_data, 0, sizeof(usb_data)); -- -- ret = of_address_to_resource(np, 0, &r[0]); -- if (ret) -- goto err; -- -- of_irq_to_resource(np, 0, &r[1]); -- -- usb_dev_mph = -- platform_device_register_simple("fsl-ehci", i, r, 2); -- if (IS_ERR(usb_dev_mph)) { -- ret = PTR_ERR(usb_dev_mph); -- goto err; -- } -- -- usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL; -- usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask; -- -- usb_data.operating_mode = FSL_USB2_MPH_HOST; -- -- prop = of_get_property(np, "port0", NULL); -- if (prop) -- usb_data.port_enables |= FSL_USB2_PORT0_ENABLED; -- -- prop = of_get_property(np, "port1", NULL); -- if (prop) -- usb_data.port_enables |= FSL_USB2_PORT1_ENABLED; -- -- prop = of_get_property(np, "phy_type", NULL); -- usb_data.phy_mode = determine_usb_phy(prop); -- -- ret = -- platform_device_add_data(usb_dev_mph, &usb_data, -- sizeof(struct -- fsl_usb2_platform_data)); -- if (ret) -- goto unreg_mph; -- i++; -- } -- -- for_each_compatible_node(np, NULL, "fsl-usb2-dr") { -- struct resource r[2]; -- struct fsl_usb2_platform_data usb_data; -- const unsigned char *prop = NULL; -- -- if (!of_device_is_available(np)) -- continue; -- -- memset(&r, 0, sizeof(r)); -- memset(&usb_data, 0, sizeof(usb_data)); -- -- ret = of_address_to_resource(np, 0, &r[0]); -- if (ret) -- goto unreg_mph; -- -- of_irq_to_resource(np, 0, &r[1]); -- -- prop = of_get_property(np, "dr_mode", NULL); -- -- if (!prop || !strcmp(prop, "host")) { -- usb_data.operating_mode = FSL_USB2_DR_HOST; -- usb_dev_dr_host = platform_device_register_simple( -- "fsl-ehci", i, r, 2); -- if (IS_ERR(usb_dev_dr_host)) { -- ret = PTR_ERR(usb_dev_dr_host); -- goto err; -- } -- } else if (prop && !strcmp(prop, "peripheral")) { -- usb_data.operating_mode = FSL_USB2_DR_DEVICE; -- usb_dev_dr_client = platform_device_register_simple( -- "fsl-usb2-udc", i, r, 2); -- if (IS_ERR(usb_dev_dr_client)) { -- ret = PTR_ERR(usb_dev_dr_client); -- goto err; -- } -- } else if (prop && !strcmp(prop, "otg")) { -- usb_data.operating_mode = FSL_USB2_DR_OTG; -- usb_dev_dr_host = platform_device_register_simple( -- "fsl-ehci", i, r, 2); -- if (IS_ERR(usb_dev_dr_host)) { -- ret = PTR_ERR(usb_dev_dr_host); -- goto err; -- } -- usb_dev_dr_client = platform_device_register_simple( -- "fsl-usb2-udc", i, r, 2); -- if (IS_ERR(usb_dev_dr_client)) { -- ret = PTR_ERR(usb_dev_dr_client); -- goto err; -- } -- } else { -- ret = -EINVAL; -- goto err; -- } -- -- prop = of_get_property(np, "phy_type", NULL); -- usb_data.phy_mode = determine_usb_phy(prop); -- -- if (usb_dev_dr_host) { -- usb_dev_dr_host->dev.coherent_dma_mask = 0xffffffffUL; -- usb_dev_dr_host->dev.dma_mask = &usb_dev_dr_host-> -- dev.coherent_dma_mask; -- if ((ret = platform_device_add_data(usb_dev_dr_host, -- &usb_data, sizeof(struct -- fsl_usb2_platform_data)))) -- goto unreg_dr; -- } -- if (usb_dev_dr_client) { -- usb_dev_dr_client->dev.coherent_dma_mask = 0xffffffffUL; -- usb_dev_dr_client->dev.dma_mask = &usb_dev_dr_client-> -- dev.coherent_dma_mask; -- if ((ret = platform_device_add_data(usb_dev_dr_client, -- &usb_data, sizeof(struct -- fsl_usb2_platform_data)))) -- goto unreg_dr; -- } -- i++; -- } -- return 0; -- --unreg_dr: -- if (usb_dev_dr_host) -- platform_device_unregister(usb_dev_dr_host); -- if (usb_dev_dr_client) -- platform_device_unregister(usb_dev_dr_client); --unreg_mph: -- if (usb_dev_mph) -- platform_device_unregister(usb_dev_mph); --err: -- return ret; --} -- --arch_initcall(fsl_usb_of_init); -- - #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) - static __be32 __iomem *rstcr; - diff --git a/usb/usb-usb-storage-implement-autosuspend.patch b/usb/usb-usb-storage-implement-autosuspend.patch new file mode 100644 index 00000000000000..ff1920e71d3102 --- /dev/null +++ b/usb/usb-usb-storage-implement-autosuspend.patch @@ -0,0 +1,67 @@ +From stern+4c5c36d6@rowland.harvard.edu Mon Aug 2 16:02:08 2010 +Date: Wed, 28 Jul 2010 17:12:39 -0400 (EDT) +From: Alan Stern <stern@rowland.harvard.edu> +To: James Bottomley <James.Bottomley@suse.de>, Greg KH <greg@kroah.com> +cc: Matthew Dharm <mdharm-usb@one-eyed-alien.net>, + Oliver Neukum <oliver@neukum.org>, + SCSI development list <linux-scsi@vger.kernel.org>, + USB Storage list <usb-storage@lists.one-eyed-alien.net> +Subject: USB: usb-storage: implement autosuspend +Message-ID: <Pine.LNX.4.44L0.1007281702030.1744-100000@iolanthe.rowland.org> + +This patch (as1400) adds runtime-PM support to usb-storage. It +utilizes the SCSI layer's runtime-PM implementation, so its scope is +limited. Currently the only effect is that disk-like devices (such as +card readers or flash drives) will be autosuspended if they aren't +mounted and their device files aren't open. This would apply, for +example, to card readers that don't contain a memory card. + +Unfortunately this won't interact very well with the removable-media +polling normally carried out by hal or DeviceKit. Maybe those +programs can be changed to use a longer polling interval, or maybe the +default autosuspend time for usb-storage should be set to something +below 1 second. + +Signed-off-by: Alan Stern <stern@rowland.harvard.edu> +Cc: James Bottomley <James.Bottomley@suse.de> +Cc: Matthew Dharm <mdharm-usb@one-eyed-alien.net> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/storage/usb.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/usb/storage/usb.c ++++ b/drivers/usb/storage/usb.c +@@ -336,6 +336,7 @@ static int usb_stor_control_thread(void + else { + US_DEBUG(usb_stor_show_command(us->srb)); + us->proto_handler(us->srb, us); ++ usb_mark_last_busy(us->pusb_dev); + } + + /* lock access to the state */ +@@ -845,6 +846,7 @@ static int usb_stor_scan_thread(void * _ + /* Should we unbind if no devices were detected? */ + } + ++ usb_autopm_put_interface(us->pusb_intf); + complete_and_exit(&us->scanning_done, 0); + } + +@@ -968,6 +970,7 @@ int usb_stor_probe2(struct us_data *us) + goto BadDevice; + } + ++ usb_autopm_get_interface_no_resume(us->pusb_intf); + wake_up_process(th); + + return 0; +@@ -1040,6 +1043,7 @@ static struct usb_driver usb_storage_dri + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = usb_storage_usb_ids, ++ .supports_autosuspend = 1, + .soft_unbind = 1, + }; + diff --git a/usb/usb-usbtest-avoid-to-free-coherent-buffer-in-atomic-context.patch b/usb/usb-usbtest-avoid-to-free-coherent-buffer-in-atomic-context.patch new file mode 100644 index 00000000000000..78a9e7f0a8f998 --- /dev/null +++ b/usb/usb-usbtest-avoid-to-free-coherent-buffer-in-atomic-context.patch @@ -0,0 +1,84 @@ +From tom.leiming@gmail.com Mon Aug 2 16:12:38 2010 +From: tom.leiming@gmail.com +To: greg@kroah.com, + stern@rowland.harvard.edu, + dbrownell@users.sourceforge.net +Cc: linux-usb@vger.kernel.org, Ming Lei <tom.leiming@gmail.com>, stable <stable@kernel.org> +Subject: USB: usbtest: avoid to free coherent buffer in atomic context +Date: Mon, 2 Aug 2010 22:09:01 +0800 +Message-Id: <1280758141-3035-1-git-send-email-tom.leiming@gmail.com> + +From: Ming Lei <tom.leiming@gmail.com> + +This patch fixes the warning below: +[30753.755998] ------------[ cut here ]------------ +[30753.755998] WARNING: at /home/tom/git/linux-2.6/linux-2.6-next/arch/x86/include/asm/dma-mapping.h:155 hcd_buffer_free+0xb1/0xd4 [usbcore]() +[30753.755998] Hardware name: 6475EK2 +[30753.755998] Modules linked in: uvcvideo ehci_hcd usbtest cdc_ether usbnet vfat fat usb_storage nfsd lockd nfs_acl auth_rpcgss exportfs mii tun videodev v4l1_compat v4l2_compat_ioctl32 fuse bridge stp llc sunrpc ipv6 cpufreq_ondemand acpi_cpufreq freq_table mperf kvm_intel kvm arc4 ecb ath5k usbhid mac80211 snd_hda_codec_conexant ch341 usbserial ath cfg80211 thinkpad_acpi snd_hda_intel pcspkr wmi hwmon yenta_socket iTCO_wdt iTCO_vendor_support i2c_i801 e1000e snd_hda_codec snd_hwdep snd_pcm snd_timer snd soundcore snd_page_alloc pata_acpi uhci_hcd ohci_hcd usbcore i915 drm_kms_helper drm i2c_algo_bit i2c_core video output [last unloaded: uvcvideo] +[30753.755998] Pid: 0, comm: swapper Tainted: G W 2.6.35-rc6-gkh-wl+ #49 +[30753.755998] Call Trace: +[30753.755998] <IRQ> [<ffffffff8104478a>] warn_slowpath_common+0x80/0x98 +[30753.755998] [<ffffffff810447b7>] warn_slowpath_null+0x15/0x17 +[30753.755998] [<ffffffffa00ce02d>] hcd_buffer_free+0xb1/0xd4 [usbcore] +[30753.755998] [<ffffffffa00c1345>] usb_free_coherent+0x1c/0x1e [usbcore] +[30753.755998] [<ffffffffa00b13e4>] simple_free_urb+0x23/0x2f [usbtest] +[30753.755998] [<ffffffffa00b210b>] iso_callback+0xbb/0x10f [usbtest] +[30753.755998] [<ffffffffa00c7390>] usb_hcd_giveback_urb+0x8c/0xc0 [usbcore] +[30753.755998] [<ffffffffa0449b35>] ehci_urb_done+0x84/0x95 [ehci_hcd] +[30753.755998] [<ffffffffa044b5a5>] ehci_work+0x41a/0x7dd [ehci_hcd] +[30753.755998] [<ffffffffa044e298>] ehci_irq+0x33b/0x370 [ehci_hcd] +[30753.755998] [<ffffffff8100fb05>] ? sched_clock+0x9/0xd +[30753.755998] [<ffffffff8105e641>] ? sched_clock_local+0x1c/0x82 +[30753.755998] [<ffffffff8105e76a>] ? sched_clock_cpu+0xc3/0xce +[30753.755998] [<ffffffff81067c7e>] ? trace_hardirqs_off+0xd/0xf +[30753.755998] [<ffffffff8105e7b8>] ? cpu_clock+0x43/0x5e +[30753.755998] [<ffffffffa00c6999>] usb_hcd_irq+0x45/0xa1 [usbcore] +[30753.755998] [<ffffffff81092e02>] handle_IRQ_event+0x20/0xa5 +[30753.755998] [<ffffffff81094cea>] handle_fasteoi_irq+0x92/0xd2 +[30753.755998] [<ffffffff8100c0ed>] handle_irq+0x1f/0x2a +[30753.755998] [<ffffffff8100b75d>] do_IRQ+0x57/0xbe +[30753.755998] [<ffffffff8136a693>] ret_from_intr+0x0/0x16 +[30753.755998] <EOI> [<ffffffff81223baa>] ? acpi_idle_enter_bm+0x231/0x269 +[30753.755998] [<ffffffff81223ba3>] ? acpi_idle_enter_bm+0x22a/0x269 +[30753.755998] [<ffffffff812c4b6b>] cpuidle_idle_call+0x99/0xce +[30753.755998] [<ffffffff81008dd5>] cpu_idle+0x61/0xaa +[30753.755998] [<ffffffff8136374b>] start_secondary+0x1c2/0x1c6 +[30753.755998] ---[ end trace 904cfaf7ab4cb1a2 ]--- + +Signed-off-by: Ming Lei <tom.leiming@gmail.com> +Cc: stable <stable@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/misc/usbtest.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/usb/misc/usbtest.c ++++ b/drivers/usb/misc/usbtest.c +@@ -1378,7 +1378,6 @@ static void iso_callback (struct urb *ur + break; + } + } +- simple_free_urb (urb); + + ctx->pending--; + if (ctx->pending == 0) { +@@ -1495,6 +1494,7 @@ test_iso_queue (struct usbtest_dev *dev, + } + + simple_free_urb (urbs [i]); ++ urbs[i] = NULL; + context.pending--; + context.submit_error = 1; + break; +@@ -1504,6 +1504,10 @@ test_iso_queue (struct usbtest_dev *dev, + + wait_for_completion (&context.done); + ++ for (i = 0; i < param->sglen; i++) { ++ if (urbs[i]) ++ simple_free_urb(urbs[i]); ++ } + /* + * Isochronous transfers are expected to fail sometimes. As an + * arbitrary limit, we will report an error if any submissions diff --git a/usb/usb-usbtest-support-test-device-with-only-one-iso-in-or-iso-out-endpoint.patch b/usb/usb-usbtest-support-test-device-with-only-one-iso-in-or-iso-out-endpoint.patch new file mode 100644 index 00000000000000..b25fd728bcbe5d --- /dev/null +++ b/usb/usb-usbtest-support-test-device-with-only-one-iso-in-or-iso-out-endpoint.patch @@ -0,0 +1,42 @@ +From linux-usb-owner@vger.kernel.org Mon Aug 2 16:12:50 2010 +From: tom.leiming@gmail.com +To: greg@kroah.com, stern@rowland.harvard.edu, + dbrownell@users.sourceforge.net +Cc: linux-usb@vger.kernel.org, Ming Lei <tom.leiming@gmail.com> +Subject: [PATCH] USB: usbtest: support test device with only one iso-in or iso-out endpoint +Date: Mon, 2 Aug 2010 22:09:17 +0800 +Message-Id: <1280758157-3068-1-git-send-email-tom.leiming@gmail.com> + +From: Ming Lei <tom.leiming@gmail.com> + +It is very common that one altsetting may include only one iso-in or iso-out +single endpoint, especially for high bandwidth endpoint, so support it. + +Signed-off-by: Ming Lei <tom.leiming@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/misc/usbtest.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/usb/misc/usbtest.c ++++ b/drivers/usb/misc/usbtest.c +@@ -136,7 +136,7 @@ try_iso: + iso_out = e; + } + } +- if ((in && out) || (iso_in && iso_out)) ++ if ((in && out) || iso_in || iso_out) + goto found; + } + return -EINVAL; +@@ -162,6 +162,9 @@ found: + dev->in_iso_pipe = usb_rcvisocpipe (udev, + iso_in->desc.bEndpointAddress + & USB_ENDPOINT_NUMBER_MASK); ++ } ++ ++ if (iso_out) { + dev->iso_out = &iso_out->desc; + dev->out_iso_pipe = usb_sndisocpipe (udev, + iso_out->desc.bEndpointAddress diff --git a/usb/usb-xhci-don-t-flush-doorbell-writes.patch b/usb/usb-xhci-don-t-flush-doorbell-writes.patch new file mode 100644 index 00000000000000..22e67807046373 --- /dev/null +++ b/usb/usb-xhci-don-t-flush-doorbell-writes.patch @@ -0,0 +1,39 @@ +From sarah.a.sharp@linux.intel.com Mon Aug 2 16:07:09 2010 +Date: Thu, 29 Jul 2010 22:13:17 -0700 +From: Sarah Sharp <sarah.a.sharp@linux.intel.com> +To: Greg KH <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org +Subject: USB: xhci: Don't flush doorbell writes. +Message-ID: <20100730051317.GA7617@xanatos> +Content-Disposition: inline + +To tell the host controller that there are transfers on the endpoint +rings, we need to ring the endpoint doorbell. This is a PCI MMIO write, +which can be delayed until another register read is queued. + +The previous code would flush the doorbell write by reading the doorbell +register after the write. This may take time, and it's not necessary to +force the host controller to know about the transfers right away. Don't +flush the doorbell register writes. + +Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/xhci-ring.c | 5 ----- + 1 file changed, 5 deletions(-) + +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -337,11 +337,6 @@ static void ring_ep_doorbell(struct xhci + field = xhci_readl(xhci, db_addr) & DB_MASK; + field |= EPI_TO_DB(ep_index) | STREAM_ID_TO_DB(stream_id); + xhci_writel(xhci, field, db_addr); +- /* Flush PCI posted writes - FIXME Matthew Wilcox says this +- * isn't time-critical and we shouldn't make the CPU wait for +- * the flush. +- */ +- xhci_readl(xhci, db_addr); + } + } + diff --git a/usb/usb-xhci-make-xhci_handle_event-static.patch b/usb/usb-xhci-make-xhci_handle_event-static.patch new file mode 100644 index 00000000000000..3915dc0ac22395 --- /dev/null +++ b/usb/usb-xhci-make-xhci_handle_event-static.patch @@ -0,0 +1,41 @@ +From sarah.a.sharp@linux.intel.com Mon Aug 2 16:06:16 2010 +Date: Thu, 29 Jul 2010 22:12:46 -0700 +From: Sarah Sharp <sarah.a.sharp@linux.intel.com> +To: Greg KH <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org +Subject: USB: xhci: Make xhci_handle_event() static. +Message-ID: <20100730051246.GA7368@xanatos> +Content-Disposition: inline + +xhci_handle_event() is now only called from within xhci-ring.c, so make it +static. + +Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/xhci-ring.c | 2 +- + drivers/usb/host/xhci.h | 1 - + 2 files changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1964,7 +1964,7 @@ cleanup: + * This function handles all OS-owned events on the event ring. It may drop + * xhci->lock between event processing (e.g. to pass up port status changes). + */ +-void xhci_handle_event(struct xhci_hcd *xhci) ++static void xhci_handle_event(struct xhci_hcd *xhci) + { + union xhci_trb *event; + int update_ptrs = 1; +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1400,7 +1400,6 @@ struct xhci_segment *trb_in_td(struct xh + int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code); + void xhci_ring_cmd_db(struct xhci_hcd *xhci); + void *xhci_setup_one_noop(struct xhci_hcd *xhci); +-void xhci_handle_event(struct xhci_hcd *xhci); + void xhci_set_hc_event_deq(struct xhci_hcd *xhci); + int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id); + int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, diff --git a/usb/usb-xhci-make-xhci_set_hc_event_deq-static.patch b/usb/usb-xhci-make-xhci_set_hc_event_deq-static.patch new file mode 100644 index 00000000000000..c3dcfaab180487 --- /dev/null +++ b/usb/usb-xhci-make-xhci_set_hc_event_deq-static.patch @@ -0,0 +1,96 @@ +From sarah.a.sharp@linux.intel.com Mon Aug 2 16:06:42 2010 +Date: Thu, 29 Jul 2010 22:12:56 -0700 +From: Sarah Sharp <sarah.a.sharp@linux.intel.com> +To: Greg KH <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org +Subject: USB: xhci: Make xhci_set_hc_event_deq() static. +Message-ID: <20100730051256.GA7471@xanatos> +Content-Disposition: inline + +Now that the event handler functions no longer use xhci_set_hc_event_deq() +to update the event ring dequeue pointer, that function is not used by +anything in xhci-ring.c. Move that function into xhci-mem.c and make it +static. + +Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/xhci-mem.c | 23 +++++++++++++++++++++++ + drivers/usb/host/xhci-ring.c | 22 ---------------------- + drivers/usb/host/xhci.h | 1 - + 3 files changed, 23 insertions(+), 23 deletions(-) + +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -1601,6 +1601,29 @@ static int xhci_check_trb_in_td_math(str + return 0; + } + ++static void xhci_set_hc_event_deq(struct xhci_hcd *xhci) ++{ ++ u64 temp; ++ dma_addr_t deq; ++ ++ deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, ++ xhci->event_ring->dequeue); ++ if (deq == 0 && !in_interrupt()) ++ xhci_warn(xhci, "WARN something wrong with SW event ring " ++ "dequeue ptr.\n"); ++ /* Update HC event ring dequeue pointer */ ++ temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); ++ temp &= ERST_PTR_MASK; ++ /* Don't clear the EHB bit (which is RW1C) because ++ * there might be more events to service. ++ */ ++ temp &= ~ERST_EHB; ++ xhci_dbg(xhci, "// Write event ring dequeue pointer, " ++ "preserving EHB bit\n"); ++ xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp, ++ &xhci->ir_set->erst_dequeue); ++} ++ + + int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) + { +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -301,28 +301,6 @@ static int room_on_ring(struct xhci_hcd + return 1; + } + +-void xhci_set_hc_event_deq(struct xhci_hcd *xhci) +-{ +- u64 temp; +- dma_addr_t deq; +- +- deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, +- xhci->event_ring->dequeue); +- if (deq == 0 && !in_interrupt()) +- xhci_warn(xhci, "WARN something wrong with SW event ring " +- "dequeue ptr.\n"); +- /* Update HC event ring dequeue pointer */ +- temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); +- temp &= ERST_PTR_MASK; +- /* Don't clear the EHB bit (which is RW1C) because +- * there might be more events to service. +- */ +- temp &= ~ERST_EHB; +- xhci_dbg(xhci, "// Write event ring dequeue pointer, preserving EHB bit\n"); +- xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp, +- &xhci->ir_set->erst_dequeue); +-} +- + /* Ring the host controller doorbell after placing a command on the ring */ + void xhci_ring_cmd_db(struct xhci_hcd *xhci) + { +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1400,7 +1400,6 @@ struct xhci_segment *trb_in_td(struct xh + int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code); + void xhci_ring_cmd_db(struct xhci_hcd *xhci); + void *xhci_setup_one_noop(struct xhci_hcd *xhci); +-void xhci_set_hc_event_deq(struct xhci_hcd *xhci); + int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id); + int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, + u32 slot_id); diff --git a/usb/usb-xhci-minimize-hw-event-ring-dequeue-pointer-writes.patch b/usb/usb-xhci-minimize-hw-event-ring-dequeue-pointer-writes.patch new file mode 100644 index 00000000000000..0bfee1d67b0430 --- /dev/null +++ b/usb/usb-xhci-minimize-hw-event-ring-dequeue-pointer-writes.patch @@ -0,0 +1,128 @@ +From sarah.a.sharp@linux.intel.com Mon Aug 2 16:06:29 2010 +Date: Thu, 29 Jul 2010 22:12:49 -0700 +From: Sarah Sharp <sarah.a.sharp@linux.intel.com> +To: Greg KH <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org, Andiry Xu <andiry.xu@amd.com> +Subject: USB: xhci: Minimize HW event ring dequeue pointer writes. +Message-ID: <20100730051249.GA7415@xanatos> +Content-Disposition: inline + +The xHCI specification suggests that writing the hardware event ring dequeue +pointer register too often can be an expensive operation for the xHCI hardware +to manage. It suggests minimizing the number of writes to that register. + +Originally, the driver wrote the event ring dequeue pointer after each +event was processed. Depending on how the event ring moderation register +is set up and how fast the transfers are completing, there may be several +events processed for each interrupt. This patch makes the hardware event +ring dequeue pointer be written only once per interrupt. + +Make the transfer event handler and port status event handler only write +the software event ring dequeue pointer. Move the updating of the +hardware event ring dequeue pointer into the interrupt function. Move the +contents of xhci_set_hc_event_deq() into the interrupt handler. The +interrupt handler must clear the event handler busy flag, so it might as +well also write the dequeue pointer to the same register. This eliminates +two 32-bit PCI reads and two 32-bit PCI writes. + +Reported-by: Andiry Xu <andiry.xu@amd.com> +Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/xhci-ring.c | 50 +++++++++++++++++++++++++++++++------------ + 1 file changed, 37 insertions(+), 13 deletions(-) + +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1184,7 +1184,6 @@ static void handle_port_status(struct xh + + /* Update event ring dequeue pointer before dropping the lock */ + inc_deq(xhci, xhci->event_ring, true); +- xhci_set_hc_event_deq(xhci); + + spin_unlock(&xhci->lock); + /* Pass this up to the core */ +@@ -1924,7 +1923,6 @@ cleanup: + */ + if (trb_comp_code == COMP_MISSED_INT || !ep->skip) { + inc_deq(xhci, xhci->event_ring, true); +- xhci_set_hc_event_deq(xhci); + } + + if (ret) { +@@ -2022,11 +2020,10 @@ static void xhci_handle_event(struct xhc + return; + } + +- if (update_ptrs) { +- /* Update SW and HC event ring dequeue pointer */ ++ if (update_ptrs) ++ /* Update SW event ring dequeue pointer */ + inc_deq(xhci, xhci->event_ring, true); +- xhci_set_hc_event_deq(xhci); +- } ++ + /* Are there more items on the event ring? */ + xhci_handle_event(xhci); + } +@@ -2042,6 +2039,8 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd + u32 status, irq_pending; + union xhci_trb *trb; + u64 temp_64; ++ union xhci_trb *event_ring_deq; ++ dma_addr_t deq; + + spin_lock(&xhci->lock); + trb = xhci->event_ring->dequeue; +@@ -2090,18 +2089,43 @@ hw_died: + irq_pending |= 0x3; + xhci_writel(xhci, irq_pending, &xhci->ir_set->irq_pending); + +- if (xhci->xhc_state & XHCI_STATE_DYING) ++ if (xhci->xhc_state & XHCI_STATE_DYING) { + xhci_dbg(xhci, "xHCI dying, ignoring interrupt. " + "Shouldn't IRQs be disabled?\n"); +- else +- /* FIXME this should be a delayed service routine +- * that clears the EHB. ++ /* Clear the event handler busy flag (RW1C); ++ * the event ring should be empty. + */ +- xhci_handle_event(xhci); ++ temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); ++ xhci_write_64(xhci, temp_64 | ERST_EHB, ++ &xhci->ir_set->erst_dequeue); ++ spin_unlock(&xhci->lock); ++ ++ return IRQ_HANDLED; ++ } ++ ++ event_ring_deq = xhci->event_ring->dequeue; ++ /* FIXME this should be a delayed service routine ++ * that clears the EHB. ++ */ ++ xhci_handle_event(xhci); + +- /* Clear the event handler busy flag (RW1C); event ring is empty. */ + temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); +- xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue); ++ /* If necessary, update the HW's version of the event ring deq ptr. */ ++ if (event_ring_deq != xhci->event_ring->dequeue) { ++ deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, ++ xhci->event_ring->dequeue); ++ if (deq == 0) ++ xhci_warn(xhci, "WARN something wrong with SW event " ++ "ring dequeue ptr.\n"); ++ /* Update HC event ring dequeue pointer */ ++ temp_64 &= ERST_PTR_MASK; ++ temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK); ++ } ++ ++ /* Clear the event handler busy flag (RW1C); event ring is empty. */ ++ temp_64 |= ERST_EHB; ++ xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue); ++ + spin_unlock(&xhci->lock); + + return IRQ_HANDLED; diff --git a/usb/usb-xhci-performance-move-functions-that-find-ep-ring.patch b/usb/usb-xhci-performance-move-functions-that-find-ep-ring.patch new file mode 100644 index 00000000000000..de7968d3252e48 --- /dev/null +++ b/usb/usb-xhci-performance-move-functions-that-find-ep-ring.patch @@ -0,0 +1,204 @@ +From sarah.a.sharp@linux.intel.com Mon Aug 2 16:05:02 2010 +Date: Thu, 29 Jul 2010 22:12:20 -0700 +From: Sarah Sharp <sarah.a.sharp@linux.intel.com> +To: Greg KH <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org +Subject: USB: xhci: Performance - move functions that find ep ring. +Message-ID: <20100730051220.GA6410@xanatos> +Content-Disposition: inline + +I've been using perf to measure the top symbols while transferring 1GB of data +on a USB 3.0 drive with dd. This is using the raw disk with /dev/sdb, with a +block size of 1K. + +During performance testing, the top symbol was xhci_triad_to_transfer_ring(), a +function that should return immediately if streams are not enabled for an +endpoint. It turned out that the functions to find the endpoint ring was +defined in xhci-mem.c and used in xhci-ring.c and xhci-hcd.c. I moved a copy of +xhci_triad_to_transfer_ring() and xhci_urb_to_transfer_ring() into xhci-ring.c +and declared them static. I also made a static version of +xhci_urb_to_transfer_ring() in xhci.c. + +This improved throughput on a 1GB read of the raw disk with dd from +186MB/s to 195MB/s, and perf reported sampling the xhci_triad_to_transfer_ring() +0.06% of the time, rather than 9.26% of the time. + +Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/xhci-mem.c | 43 ------------------------------------------ + drivers/usb/host/xhci-ring.c | 44 +++++++++++++++++++++++++++++++++++++++++++ + drivers/usb/host/xhci.c | 41 ++++++++++++++++++++++++++++++++++++++++ + drivers/usb/host/xhci.h | 5 ---- + 4 files changed, 85 insertions(+), 48 deletions(-) + +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -391,49 +391,6 @@ struct xhci_ring *xhci_stream_id_to_ring + return ep->stream_info->stream_rings[stream_id]; + } + +-struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci, +- unsigned int slot_id, unsigned int ep_index, +- unsigned int stream_id) +-{ +- struct xhci_virt_ep *ep; +- +- ep = &xhci->devs[slot_id]->eps[ep_index]; +- /* Common case: no streams */ +- if (!(ep->ep_state & EP_HAS_STREAMS)) +- return ep->ring; +- +- if (stream_id == 0) { +- xhci_warn(xhci, +- "WARN: Slot ID %u, ep index %u has streams, " +- "but URB has no stream ID.\n", +- slot_id, ep_index); +- return NULL; +- } +- +- if (stream_id < ep->stream_info->num_streams) +- return ep->stream_info->stream_rings[stream_id]; +- +- xhci_warn(xhci, +- "WARN: Slot ID %u, ep index %u has " +- "stream IDs 1 to %u allocated, " +- "but stream ID %u is requested.\n", +- slot_id, ep_index, +- ep->stream_info->num_streams - 1, +- stream_id); +- return NULL; +-} +- +-/* Get the right ring for the given URB. +- * If the endpoint supports streams, boundary check the URB's stream ID. +- * If the endpoint doesn't support streams, return the singular endpoint ring. +- */ +-struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, +- struct urb *urb) +-{ +- return xhci_triad_to_transfer_ring(xhci, urb->dev->slot_id, +- xhci_get_endpoint_index(&urb->ep->desc), urb->stream_id); +-} +- + #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING + static int xhci_test_radix_tree(struct xhci_hcd *xhci, + unsigned int num_streams, +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -419,6 +419,50 @@ static struct xhci_segment *find_trb_seg + return cur_seg; + } + ++ ++static struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci, ++ unsigned int slot_id, unsigned int ep_index, ++ unsigned int stream_id) ++{ ++ struct xhci_virt_ep *ep; ++ ++ ep = &xhci->devs[slot_id]->eps[ep_index]; ++ /* Common case: no streams */ ++ if (!(ep->ep_state & EP_HAS_STREAMS)) ++ return ep->ring; ++ ++ if (stream_id == 0) { ++ xhci_warn(xhci, ++ "WARN: Slot ID %u, ep index %u has streams, " ++ "but URB has no stream ID.\n", ++ slot_id, ep_index); ++ return NULL; ++ } ++ ++ if (stream_id < ep->stream_info->num_streams) ++ return ep->stream_info->stream_rings[stream_id]; ++ ++ xhci_warn(xhci, ++ "WARN: Slot ID %u, ep index %u has " ++ "stream IDs 1 to %u allocated, " ++ "but stream ID %u is requested.\n", ++ slot_id, ep_index, ++ ep->stream_info->num_streams - 1, ++ stream_id); ++ return NULL; ++} ++ ++/* Get the right ring for the given URB. ++ * If the endpoint supports streams, boundary check the URB's stream ID. ++ * If the endpoint doesn't support streams, return the singular endpoint ring. ++ */ ++static struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, ++ struct urb *urb) ++{ ++ return xhci_triad_to_transfer_ring(xhci, urb->dev->slot_id, ++ xhci_get_endpoint_index(&urb->ep->desc), urb->stream_id); ++} ++ + /* + * Move the xHC's endpoint ring dequeue pointer past cur_td. + * Record the new state of the xHC's endpoint ring dequeue segment, +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -916,6 +916,47 @@ dying: + return -ESHUTDOWN; + } + ++/* Get the right ring for the given URB. ++ * If the endpoint supports streams, boundary check the URB's stream ID. ++ * If the endpoint doesn't support streams, return the singular endpoint ring. ++ */ ++static struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, ++ struct urb *urb) ++{ ++ unsigned int slot_id; ++ unsigned int ep_index; ++ unsigned int stream_id; ++ struct xhci_virt_ep *ep; ++ ++ slot_id = urb->dev->slot_id; ++ ep_index = xhci_get_endpoint_index(&urb->ep->desc); ++ stream_id = urb->stream_id; ++ ep = &xhci->devs[slot_id]->eps[ep_index]; ++ /* Common case: no streams */ ++ if (!(ep->ep_state & EP_HAS_STREAMS)) ++ return ep->ring; ++ ++ if (stream_id == 0) { ++ xhci_warn(xhci, ++ "WARN: Slot ID %u, ep index %u has streams, " ++ "but URB has no stream ID.\n", ++ slot_id, ep_index); ++ return NULL; ++ } ++ ++ if (stream_id < ep->stream_info->num_streams) ++ return ep->stream_info->stream_rings[stream_id]; ++ ++ xhci_warn(xhci, ++ "WARN: Slot ID %u, ep index %u has " ++ "stream IDs 1 to %u allocated, " ++ "but stream ID %u is requested.\n", ++ slot_id, ep_index, ++ ep->stream_info->num_streams - 1, ++ stream_id); ++ return NULL; ++} ++ + /* + * Remove the URB's TD from the endpoint ring. This may cause the HC to stop + * USB transfers, potentially stopping in the middle of a TRB buffer. The HC +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1344,11 +1344,6 @@ void xhci_setup_no_streams_ep_input_ctx( + struct xhci_ring *xhci_dma_to_transfer_ring( + struct xhci_virt_ep *ep, + u64 address); +-struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, +- struct urb *urb); +-struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci, +- unsigned int slot_id, unsigned int ep_index, +- unsigned int stream_id); + struct xhci_ring *xhci_stream_id_to_ring( + struct xhci_virt_device *dev, + unsigned int ep_index, diff --git a/usb/usb-xhci-performance-move-interrupt-handlers-into-xhci-ring.c.patch b/usb/usb-xhci-performance-move-interrupt-handlers-into-xhci-ring.c.patch new file mode 100644 index 00000000000000..42b94be8694697 --- /dev/null +++ b/usb/usb-xhci-performance-move-interrupt-handlers-into-xhci-ring.c.patch @@ -0,0 +1,268 @@ +From sarah.a.sharp@linux.intel.com Mon Aug 2 16:05:17 2010 +Date: Thu, 29 Jul 2010 22:12:29 -0700 +From: Sarah Sharp <sarah.a.sharp@linux.intel.com> +To: Greg KH <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org +Subject: USB: xhci: Performance - move interrupt handlers into xhci-ring.c +Message-ID: <20100730051229.GA7229@xanatos> +Content-Disposition: inline + +Most of the work for interrupt handling is done in xhci-ring.c, so it makes +sense to move the functions that are first called when an interrupt happens +(xhci_irq() or xhci_msi_irq()) into xhci-ring.c, so that the compiler can better +optimize them. + +Shorten some lines to make it pass checkpatch. + +Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/xhci-ring.c | 103 +++++++++++++++++++++++++++++++++++++++++++ + drivers/usb/host/xhci.c | 103 ------------------------------------------- + drivers/usb/host/xhci.h | 1 + 3 files changed, 104 insertions(+), 103 deletions(-) + +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -2030,6 +2030,109 @@ void xhci_handle_event(struct xhci_hcd * + /* Are there more items on the event ring? */ + xhci_handle_event(xhci); + } ++/* ++ * Called in interrupt context when there might be work ++ * queued on the event ring ++ * ++ * xhci->lock must be held by caller. ++ */ ++static void xhci_work(struct xhci_hcd *xhci) ++{ ++ u32 temp; ++ u64 temp_64; ++ ++ /* ++ * Clear the op reg interrupt status first, ++ * so we can receive interrupts from other MSI-X interrupters. ++ * Write 1 to clear the interrupt status. ++ */ ++ temp = xhci_readl(xhci, &xhci->op_regs->status); ++ temp |= STS_EINT; ++ xhci_writel(xhci, temp, &xhci->op_regs->status); ++ /* FIXME when MSI-X is supported and there are multiple vectors */ ++ /* Clear the MSI-X event interrupt status */ ++ ++ /* Acknowledge the interrupt */ ++ temp = xhci_readl(xhci, &xhci->ir_set->irq_pending); ++ temp |= 0x3; ++ xhci_writel(xhci, temp, &xhci->ir_set->irq_pending); ++ ++ if (xhci->xhc_state & XHCI_STATE_DYING) ++ xhci_dbg(xhci, "xHCI dying, ignoring interrupt. " ++ "Shouldn't IRQs be disabled?\n"); ++ else ++ /* FIXME this should be a delayed service routine ++ * that clears the EHB. ++ */ ++ xhci_handle_event(xhci); ++ ++ /* Clear the event handler busy flag (RW1C); event ring is empty. */ ++ temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); ++ xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue); ++ /* Flush posted writes -- FIXME is this necessary? */ ++ xhci_readl(xhci, &xhci->ir_set->irq_pending); ++} ++ ++/* ++ * xHCI spec says we can get an interrupt, and if the HC has an error condition, ++ * we might get bad data out of the event ring. Section 4.10.2.7 has a list of ++ * indicators of an event TRB error, but we check the status *first* to be safe. ++ */ ++irqreturn_t xhci_irq(struct usb_hcd *hcd) ++{ ++ struct xhci_hcd *xhci = hcd_to_xhci(hcd); ++ u32 temp, temp2; ++ union xhci_trb *trb; ++ ++ spin_lock(&xhci->lock); ++ trb = xhci->event_ring->dequeue; ++ /* Check if the xHC generated the interrupt, or the irq is shared */ ++ temp = xhci_readl(xhci, &xhci->op_regs->status); ++ temp2 = xhci_readl(xhci, &xhci->ir_set->irq_pending); ++ if (temp == 0xffffffff && temp2 == 0xffffffff) ++ goto hw_died; ++ ++ if (!(temp & STS_EINT) && !ER_IRQ_PENDING(temp2)) { ++ spin_unlock(&xhci->lock); ++ xhci_warn(xhci, "Spurious interrupt.\n"); ++ return IRQ_NONE; ++ } ++ xhci_dbg(xhci, "op reg status = %08x\n", temp); ++ xhci_dbg(xhci, "ir set irq_pending = %08x\n", temp2); ++ xhci_dbg(xhci, "Event ring dequeue ptr:\n"); ++ xhci_dbg(xhci, "@%llx %08x %08x %08x %08x\n", ++ (unsigned long long) ++ xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, trb), ++ lower_32_bits(trb->link.segment_ptr), ++ upper_32_bits(trb->link.segment_ptr), ++ (unsigned int) trb->link.intr_target, ++ (unsigned int) trb->link.control); ++ ++ if (temp & STS_FATAL) { ++ xhci_warn(xhci, "WARNING: Host System Error\n"); ++ xhci_halt(xhci); ++hw_died: ++ xhci_to_hcd(xhci)->state = HC_STATE_HALT; ++ spin_unlock(&xhci->lock); ++ return -ESHUTDOWN; ++ } ++ ++ xhci_work(xhci); ++ spin_unlock(&xhci->lock); ++ ++ return IRQ_HANDLED; ++} ++ ++irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd) ++{ ++ irqreturn_t ret; ++ ++ set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); ++ ++ ret = xhci_irq(hcd); ++ ++ return ret; ++} + + /**** Endpoint Ring Operations ****/ + +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -172,17 +172,6 @@ int xhci_reset(struct xhci_hcd *xhci) + return handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000); + } + +-static irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd) +-{ +- irqreturn_t ret; +- +- set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); +- +- ret = xhci_irq(hcd); +- +- return ret; +-} +- + /* + * Free IRQs + * free all IRQs request +@@ -332,100 +321,8 @@ int xhci_init(struct usb_hcd *hcd) + return retval; + } + +-/* +- * Called in interrupt context when there might be work +- * queued on the event ring +- * +- * xhci->lock must be held by caller. +- */ +-static void xhci_work(struct xhci_hcd *xhci) +-{ +- u32 temp; +- u64 temp_64; +- +- /* +- * Clear the op reg interrupt status first, +- * so we can receive interrupts from other MSI-X interrupters. +- * Write 1 to clear the interrupt status. +- */ +- temp = xhci_readl(xhci, &xhci->op_regs->status); +- temp |= STS_EINT; +- xhci_writel(xhci, temp, &xhci->op_regs->status); +- /* FIXME when MSI-X is supported and there are multiple vectors */ +- /* Clear the MSI-X event interrupt status */ +- +- /* Acknowledge the interrupt */ +- temp = xhci_readl(xhci, &xhci->ir_set->irq_pending); +- temp |= 0x3; +- xhci_writel(xhci, temp, &xhci->ir_set->irq_pending); +- /* Flush posted writes */ +- xhci_readl(xhci, &xhci->ir_set->irq_pending); +- +- if (xhci->xhc_state & XHCI_STATE_DYING) +- xhci_dbg(xhci, "xHCI dying, ignoring interrupt. " +- "Shouldn't IRQs be disabled?\n"); +- else +- /* FIXME this should be a delayed service routine +- * that clears the EHB. +- */ +- xhci_handle_event(xhci); +- +- /* Clear the event handler busy flag (RW1C); the event ring should be empty. */ +- temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); +- xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue); +- /* Flush posted writes -- FIXME is this necessary? */ +- xhci_readl(xhci, &xhci->ir_set->irq_pending); +-} +- + /*-------------------------------------------------------------------------*/ + +-/* +- * xHCI spec says we can get an interrupt, and if the HC has an error condition, +- * we might get bad data out of the event ring. Section 4.10.2.7 has a list of +- * indicators of an event TRB error, but we check the status *first* to be safe. +- */ +-irqreturn_t xhci_irq(struct usb_hcd *hcd) +-{ +- struct xhci_hcd *xhci = hcd_to_xhci(hcd); +- u32 temp, temp2; +- union xhci_trb *trb; +- +- spin_lock(&xhci->lock); +- trb = xhci->event_ring->dequeue; +- /* Check if the xHC generated the interrupt, or the irq is shared */ +- temp = xhci_readl(xhci, &xhci->op_regs->status); +- temp2 = xhci_readl(xhci, &xhci->ir_set->irq_pending); +- if (temp == 0xffffffff && temp2 == 0xffffffff) +- goto hw_died; +- +- if (!(temp & STS_EINT) && !ER_IRQ_PENDING(temp2)) { +- spin_unlock(&xhci->lock); +- return IRQ_NONE; +- } +- xhci_dbg(xhci, "op reg status = %08x\n", temp); +- xhci_dbg(xhci, "ir set irq_pending = %08x\n", temp2); +- xhci_dbg(xhci, "Event ring dequeue ptr:\n"); +- xhci_dbg(xhci, "@%llx %08x %08x %08x %08x\n", +- (unsigned long long)xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, trb), +- lower_32_bits(trb->link.segment_ptr), +- upper_32_bits(trb->link.segment_ptr), +- (unsigned int) trb->link.intr_target, +- (unsigned int) trb->link.control); +- +- if (temp & STS_FATAL) { +- xhci_warn(xhci, "WARNING: Host System Error\n"); +- xhci_halt(xhci); +-hw_died: +- xhci_to_hcd(xhci)->state = HC_STATE_HALT; +- spin_unlock(&xhci->lock); +- return -ESHUTDOWN; +- } +- +- xhci_work(xhci); +- spin_unlock(&xhci->lock); +- +- return IRQ_HANDLED; +-} + + #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING + void xhci_event_ring_work(unsigned long arg) +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1371,6 +1371,7 @@ void xhci_stop(struct usb_hcd *hcd); + void xhci_shutdown(struct usb_hcd *hcd); + int xhci_get_frame(struct usb_hcd *hcd); + irqreturn_t xhci_irq(struct usb_hcd *hcd); ++irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd); + int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev); + void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev); + int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, diff --git a/usb/usb-xhci-performance-move-xhci_work-into-xhci_irq.patch b/usb/usb-xhci-performance-move-xhci_work-into-xhci_irq.patch new file mode 100644 index 00000000000000..b50eb913faf020 --- /dev/null +++ b/usb/usb-xhci-performance-move-xhci_work-into-xhci_irq.patch @@ -0,0 +1,115 @@ +From sarah.a.sharp@linux.intel.com Mon Aug 2 16:05:41 2010 +Date: Thu, 29 Jul 2010 22:12:38 -0700 +From: Sarah Sharp <sarah.a.sharp@linux.intel.com> +To: Greg KH <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org +Subject: USB: xhci: Performance - move xhci_work() into xhci_irq() +Message-ID: <20100730051238.GA7256@xanatos> +Content-Disposition: inline + +When we move xhci_work() into xhci_irq(), we don't need to read the operational +register status field twice. + +Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/xhci-ring.c | 73 +++++++++++++++++-------------------------- + 1 file changed, 30 insertions(+), 43 deletions(-) + +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -2030,48 +2030,6 @@ void xhci_handle_event(struct xhci_hcd * + /* Are there more items on the event ring? */ + xhci_handle_event(xhci); + } +-/* +- * Called in interrupt context when there might be work +- * queued on the event ring +- * +- * xhci->lock must be held by caller. +- */ +-static void xhci_work(struct xhci_hcd *xhci) +-{ +- u32 temp; +- u64 temp_64; +- +- /* +- * Clear the op reg interrupt status first, +- * so we can receive interrupts from other MSI-X interrupters. +- * Write 1 to clear the interrupt status. +- */ +- temp = xhci_readl(xhci, &xhci->op_regs->status); +- temp |= STS_EINT; +- xhci_writel(xhci, temp, &xhci->op_regs->status); +- /* FIXME when MSI-X is supported and there are multiple vectors */ +- /* Clear the MSI-X event interrupt status */ +- +- /* Acknowledge the interrupt */ +- temp = xhci_readl(xhci, &xhci->ir_set->irq_pending); +- temp |= 0x3; +- xhci_writel(xhci, temp, &xhci->ir_set->irq_pending); +- +- if (xhci->xhc_state & XHCI_STATE_DYING) +- xhci_dbg(xhci, "xHCI dying, ignoring interrupt. " +- "Shouldn't IRQs be disabled?\n"); +- else +- /* FIXME this should be a delayed service routine +- * that clears the EHB. +- */ +- xhci_handle_event(xhci); +- +- /* Clear the event handler busy flag (RW1C); event ring is empty. */ +- temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); +- xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue); +- /* Flush posted writes -- FIXME is this necessary? */ +- xhci_readl(xhci, &xhci->ir_set->irq_pending); +-} + + /* + * xHCI spec says we can get an interrupt, and if the HC has an error condition, +@@ -2083,6 +2041,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + u32 temp, temp2; + union xhci_trb *trb; ++ u64 temp_64; + + spin_lock(&xhci->lock); + trb = xhci->event_ring->dequeue; +@@ -2117,7 +2076,35 @@ hw_died: + return -ESHUTDOWN; + } + +- xhci_work(xhci); ++ /* ++ * Clear the op reg interrupt status first, ++ * so we can receive interrupts from other MSI-X interrupters. ++ * Write 1 to clear the interrupt status. ++ */ ++ temp |= STS_EINT; ++ xhci_writel(xhci, temp, &xhci->op_regs->status); ++ /* FIXME when MSI-X is supported and there are multiple vectors */ ++ /* Clear the MSI-X event interrupt status */ ++ ++ /* Acknowledge the interrupt */ ++ temp = xhci_readl(xhci, &xhci->ir_set->irq_pending); ++ temp |= 0x3; ++ xhci_writel(xhci, temp, &xhci->ir_set->irq_pending); ++ ++ if (xhci->xhc_state & XHCI_STATE_DYING) ++ xhci_dbg(xhci, "xHCI dying, ignoring interrupt. " ++ "Shouldn't IRQs be disabled?\n"); ++ else ++ /* FIXME this should be a delayed service routine ++ * that clears the EHB. ++ */ ++ xhci_handle_event(xhci); ++ ++ /* Clear the event handler busy flag (RW1C); event ring is empty. */ ++ temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); ++ xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue); ++ /* Flush posted writes -- FIXME is this necessary? */ ++ xhci_readl(xhci, &xhci->ir_set->irq_pending); + spin_unlock(&xhci->lock); + + return IRQ_HANDLED; diff --git a/usb/usb-xhci-reduce-reads-and-writes-of-interrupter-registers.patch b/usb/usb-xhci-reduce-reads-and-writes-of-interrupter-registers.patch new file mode 100644 index 00000000000000..d10c17408e181a --- /dev/null +++ b/usb/usb-xhci-reduce-reads-and-writes-of-interrupter-registers.patch @@ -0,0 +1,83 @@ +From sarah.a.sharp@linux.intel.com Mon Aug 2 16:06:55 2010 +Date: Thu, 29 Jul 2010 22:13:00 -0700 +From: Sarah Sharp <sarah.a.sharp@linux.intel.com> +To: Greg KH <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org +Subject: USB: xhci: Reduce reads and writes of interrupter registers. +Message-ID: <20100730051300.GA7561@xanatos> +Content-Disposition: inline + +The interrupter register set includes a register that says whether interrupts +are pending for each event ring (the IP bit). Each MSI-X vector will get its +own interrupter set with separate IP bits. The status register includes an +"Event Interrupt (EINT)" bit that is set when an IP bit is set in any of the +interrupters. + +When PCI interrupts are used, the EINT bit exactly mirrors the IP bit in the +single interrupter set, and it is a waste of time to check both registers when +trying to figure out if the xHC interrupted or another device on the shared IRQ +line interrupted. Only check the IP bit to reduce register reads. + +The IP bit is automatically cleared by the xHC when MSI or MSI-X is enabled. It +doesn't make sense to read that register to check for shared interrupts (since +MSI and MSI-X aren't shared). It also doesn't make sense to write to that +register to clear the IP bit, since it is cleared by the hardware. + +We can tell whether MSI or MSI-X is enabled by looking at the irq number in +hcd->irq. If it's -1, we know MSI or MSI-X is enabled. + +Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/xhci-ring.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -2014,7 +2014,7 @@ static void xhci_handle_event(struct xhc + irqreturn_t xhci_irq(struct usb_hcd *hcd) + { + struct xhci_hcd *xhci = hcd_to_xhci(hcd); +- u32 status, irq_pending; ++ u32 status; + union xhci_trb *trb; + u64 temp_64; + union xhci_trb *event_ring_deq; +@@ -2024,17 +2024,15 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd + trb = xhci->event_ring->dequeue; + /* Check if the xHC generated the interrupt, or the irq is shared */ + status = xhci_readl(xhci, &xhci->op_regs->status); +- irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); +- if (status == 0xffffffff && irq_pending == 0xffffffff) ++ if (status == 0xffffffff) + goto hw_died; + +- if (!(status & STS_EINT) && !ER_IRQ_PENDING(irq_pending)) { ++ if (!(status & STS_EINT)) { + spin_unlock(&xhci->lock); + xhci_warn(xhci, "Spurious interrupt.\n"); + return IRQ_NONE; + } + xhci_dbg(xhci, "op reg status = %08x\n", status); +- xhci_dbg(xhci, "ir set irq_pending = %08x\n", irq_pending); + xhci_dbg(xhci, "Event ring dequeue ptr:\n"); + xhci_dbg(xhci, "@%llx %08x %08x %08x %08x\n", + (unsigned long long) +@@ -2063,9 +2061,13 @@ hw_died: + /* FIXME when MSI-X is supported and there are multiple vectors */ + /* Clear the MSI-X event interrupt status */ + +- /* Acknowledge the interrupt */ +- irq_pending |= 0x3; +- xhci_writel(xhci, irq_pending, &xhci->ir_set->irq_pending); ++ if (hcd->irq != -1) { ++ u32 irq_pending; ++ /* Acknowledge the PCI interrupt */ ++ irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); ++ irq_pending |= 0x3; ++ xhci_writel(xhci, irq_pending, &xhci->ir_set->irq_pending); ++ } + + if (xhci->xhc_state & XHCI_STATE_DYING) { + xhci_dbg(xhci, "xHCI dying, ignoring interrupt. " diff --git a/usb/usb-xhci-remove-unnecessary-reads-of-irq_pending-register.patch b/usb/usb-xhci-remove-unnecessary-reads-of-irq_pending-register.patch new file mode 100644 index 00000000000000..71d1c650a34c5a --- /dev/null +++ b/usb/usb-xhci-remove-unnecessary-reads-of-irq_pending-register.patch @@ -0,0 +1,95 @@ +From sarah.a.sharp@linux.intel.com Mon Aug 2 16:06:01 2010 +Date: Thu, 29 Jul 2010 22:12:43 -0700 +From: Sarah Sharp <sarah.a.sharp@linux.intel.com> +To: Greg KH <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org +Subject: USB: xhci: Remove unnecessary reads of IRQ_PENDING register. +Message-ID: <20100730051243.GA7312@xanatos> +Content-Disposition: inline + +Remove a duplicate register read of the interrupt pending register from +xhci_irq(). Also, remove waiting on the posted write of that register. +The host will see it eventually. It will probably read the register +itself before deciding whether to interrupt the system again, forcing the +posted write to complete. + +Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/xhci-ring.c | 27 ++++++++++++--------------- + 1 file changed, 12 insertions(+), 15 deletions(-) + +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -2039,25 +2039,25 @@ void xhci_handle_event(struct xhci_hcd * + irqreturn_t xhci_irq(struct usb_hcd *hcd) + { + struct xhci_hcd *xhci = hcd_to_xhci(hcd); +- u32 temp, temp2; ++ u32 status, irq_pending; + union xhci_trb *trb; + u64 temp_64; + + spin_lock(&xhci->lock); + trb = xhci->event_ring->dequeue; + /* Check if the xHC generated the interrupt, or the irq is shared */ +- temp = xhci_readl(xhci, &xhci->op_regs->status); +- temp2 = xhci_readl(xhci, &xhci->ir_set->irq_pending); +- if (temp == 0xffffffff && temp2 == 0xffffffff) ++ status = xhci_readl(xhci, &xhci->op_regs->status); ++ irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); ++ if (status == 0xffffffff && irq_pending == 0xffffffff) + goto hw_died; + +- if (!(temp & STS_EINT) && !ER_IRQ_PENDING(temp2)) { ++ if (!(status & STS_EINT) && !ER_IRQ_PENDING(irq_pending)) { + spin_unlock(&xhci->lock); + xhci_warn(xhci, "Spurious interrupt.\n"); + return IRQ_NONE; + } +- xhci_dbg(xhci, "op reg status = %08x\n", temp); +- xhci_dbg(xhci, "ir set irq_pending = %08x\n", temp2); ++ xhci_dbg(xhci, "op reg status = %08x\n", status); ++ xhci_dbg(xhci, "ir set irq_pending = %08x\n", irq_pending); + xhci_dbg(xhci, "Event ring dequeue ptr:\n"); + xhci_dbg(xhci, "@%llx %08x %08x %08x %08x\n", + (unsigned long long) +@@ -2067,7 +2067,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd + (unsigned int) trb->link.intr_target, + (unsigned int) trb->link.control); + +- if (temp & STS_FATAL) { ++ if (status & STS_FATAL) { + xhci_warn(xhci, "WARNING: Host System Error\n"); + xhci_halt(xhci); + hw_died: +@@ -2081,15 +2081,14 @@ hw_died: + * so we can receive interrupts from other MSI-X interrupters. + * Write 1 to clear the interrupt status. + */ +- temp |= STS_EINT; +- xhci_writel(xhci, temp, &xhci->op_regs->status); ++ status |= STS_EINT; ++ xhci_writel(xhci, status, &xhci->op_regs->status); + /* FIXME when MSI-X is supported and there are multiple vectors */ + /* Clear the MSI-X event interrupt status */ + + /* Acknowledge the interrupt */ +- temp = xhci_readl(xhci, &xhci->ir_set->irq_pending); +- temp |= 0x3; +- xhci_writel(xhci, temp, &xhci->ir_set->irq_pending); ++ irq_pending |= 0x3; ++ xhci_writel(xhci, irq_pending, &xhci->ir_set->irq_pending); + + if (xhci->xhc_state & XHCI_STATE_DYING) + xhci_dbg(xhci, "xHCI dying, ignoring interrupt. " +@@ -2103,8 +2102,6 @@ hw_died: + /* Clear the event handler busy flag (RW1C); event ring is empty. */ + temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); + xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue); +- /* Flush posted writes -- FIXME is this necessary? */ +- xhci_readl(xhci, &xhci->ir_set->irq_pending); + spin_unlock(&xhci->lock); + + return IRQ_HANDLED; diff --git a/usb/usb-xhci-set-dma-mask-for-host.patch b/usb/usb-xhci-set-dma-mask-for-host.patch new file mode 100644 index 00000000000000..a00866b74aef92 --- /dev/null +++ b/usb/usb-xhci-set-dma-mask-for-host.patch @@ -0,0 +1,49 @@ +From sarah.a.sharp@linux.intel.com Mon Aug 2 16:07:23 2010 +Date: Thu, 29 Jul 2010 22:13:22 -0700 +From: Sarah Sharp <sarah.a.sharp@linux.intel.com> +To: Greg KH <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org +Subject: USB: xhci: Set DMA mask for host. +Message-ID: <20100730051322.GA7664@xanatos> +Content-Disposition: inline + +Tell the USB core that we can do DMA directly (instead of needing it to +memory-map the buffers for PIO). If the xHCI host supports 64-bit addresses, +set the DMA mask accordingly. Otherwise indicate the host can handle 32-bit DMA +addresses. + +This improves performance because the USB core doesn't have to spend time +remapping buffers in high memory into the 32-bit address range. + +Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/xhci-pci.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -53,6 +53,7 @@ static int xhci_pci_setup(struct usb_hcd + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); + int retval; ++ u32 temp; + + hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 2; + +@@ -93,6 +94,14 @@ static int xhci_pci_setup(struct usb_hcd + return retval; + xhci_dbg(xhci, "Reset complete\n"); + ++ temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params); ++ if (HCC_64BIT_ADDR(temp)) { ++ xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n"); ++ dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64)); ++ } else { ++ dma_set_mask(hcd->self.controller, DMA_BIT_MASK(32)); ++ } ++ + xhci_dbg(xhci, "Calling HCD init\n"); + /* Initialize HCD and host controller data structures. */ + retval = xhci_init(hcd); |
