aboutsummaryrefslogtreecommitdiffstats
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2010-05-20 11:10:12 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-20 11:10:12 -0700
commit19f23bdac78b23931f45121dd246fedad57597b1 (patch)
treeef45709a56cdf47165ec0acb1eb0377bb2dd9411
parent3dc984e689eddab9a8624360e8c8eccfc14104bd (diff)
downloadpatches-19f23bdac78b23931f45121dd246fedad57597b1.tar.gz
kobject network namespace patches and some usb serial fixes
-rw-r--r--driver-core/hotplug-netns-aware-uevent_helper.patch66
-rw-r--r--driver-core/kobj-send-hotplug-events-in-the-proper-namespace.patch60
-rw-r--r--driver-core/kobject-send-hotplug-events-in-all-network-namespaces.patch139
-rw-r--r--driver-core/net-expose-all-network-devices-in-a-namespaces-in-sysfs.patch173
-rw-r--r--driver-core/net-sysfs-fix-the-bitrot-in-network-device-kobject-namespace-support.patch90
-rw-r--r--driver-core/netlink-implment-netlink_broadcast_filtered.patch101
-rw-r--r--driver-core/netns-teach-network-device-kobjects-which-namespace-they-are-in.patch144
-rw-r--r--series24
-rw-r--r--usb/usb-aircable-fix-incorrect-write-buffer-length.patch28
-rw-r--r--usb/usb-change-the-scatterlist-type-in-struct-urb.patch4
-rw-r--r--usb/usb-clean-up-some-host-controller-sparse-warnings.patch12
-rw-r--r--usb/usb-fix-usbmon-and-dma-mapping-for-scatter-gather-urbs.patch2
-rw-r--r--usb/usb-ftdi_sio-fix-legacy-sio-device-header.patch32
-rw-r--r--usb/usb-io_ti-remove-unsused-private-counter.patch37
-rw-r--r--usb/usb-io_ti-use-kfifo-to-implement-write-buffering.patch349
-rw-r--r--usb/usb-ir-usb-fix-incorrect-write-buffer-length.patch38
-rw-r--r--usb/usb-kl5usb105-fix-memory-leak.patch28
-rw-r--r--usb/usb-kl5usb105-minor-clean-ups.patch228
-rw-r--r--usb/usb-kl5usb105-reimplement-using-generic-framework.patch556
-rw-r--r--usb/usb-musb-update-gfp-slab.h-includes.patch29
-rw-r--r--usb/usb-safe_serial-reimplement-read-using-generic-framework.patch97
-rw-r--r--usb/usb-safe_serial-reimplement-write-using-generic-framework.patch204
-rw-r--r--usb/usb-safe_serial-straighten-out-read-processing.patch82
-rw-r--r--usb/usb-ti_usb-use-kfifo-to-implement-write-buffering.patch302
-rw-r--r--usb/usb-xhci-correct-assumptions-about-number-of-rings-per-endpoint.patch70
-rw-r--r--usb/usb-xhci-fix-check-for-room-on-the-ring.patch66
-rw-r--r--usb/usb-xhci-fix-compiler-warning.patch2
-rw-r--r--usb/usb-xhci-fix-wrong-usage-of-macro-trb_type.patch6
-rw-r--r--usb/usb-xhci-limit-bus-sg_tablesize-to-62-trbs.patch36
-rw-r--r--usb/usb-xhci-set-stream-id-to-0-after-cleaning-up-stalls.patch2
-rw-r--r--usb/usb-xhci-transfer-ring-link-trb-activation-change.patch12
-rw-r--r--usb/xhci-add-memory-allocation-for-usb3-bulk-streams.patch4
32 files changed, 2966 insertions, 57 deletions
diff --git a/driver-core/hotplug-netns-aware-uevent_helper.patch b/driver-core/hotplug-netns-aware-uevent_helper.patch
new file mode 100644
index 00000000000000..efd833e08e6be6
--- /dev/null
+++ b/driver-core/hotplug-netns-aware-uevent_helper.patch
@@ -0,0 +1,66 @@
+From ebiederm@xmission.com Thu May 20 10:45:13 2010
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Tue, 4 May 2010 17:36:48 -0700
+Subject: hotplug: netns aware uevent_helper
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: Kay Sievers <kay.sievers@vrfy.org>, linux-kernel@vger.kernel.org, Tejun Heo <tj@kernel.org>, Cornelia Huck <cornelia.huck@de.ibm.com>, Eric Dumazet <eric.dumazet@gmail.com>, Benjamin LaHaise <bcrl@lhnet.ca>, Serge Hallyn <serue@us.ibm.com>, <netdev@vger.kernel.org>, David Miller <davem@davemloft.net>, "Eric W. Biederman" <ebiederm@xmission.com>
+Message-ID: <1273019809-16472-5-git-send-email-ebiederm@xmission.com>
+
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+It only makes sense for uevent_helper to get events
+in the intial namespaces. It's invocation is not
+per namespace and it is not clear how we could make
+it's invocation namespace aware.
+
+Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
+Acked-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ lib/kobject_uevent.c | 19 +++++++++++++++++--
+ 1 file changed, 17 insertions(+), 2 deletions(-)
+
+--- a/lib/kobject_uevent.c
++++ b/lib/kobject_uevent.c
+@@ -19,7 +19,7 @@
+ #include <linux/kobject.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
+-
++#include <linux/user_namespace.h>
+ #include <linux/socket.h>
+ #include <linux/skbuff.h>
+ #include <linux/netlink.h>
+@@ -99,6 +99,21 @@ static int kobj_bcast_filter(struct sock
+ return 0;
+ }
+
++static int kobj_usermode_filter(struct kobject *kobj)
++{
++ const struct kobj_ns_type_operations *ops;
++
++ ops = kobj_ns_ops(kobj);
++ if (ops) {
++ const void *init_ns, *ns;
++ ns = kobj->ktype->namespace(kobj);
++ init_ns = ops->initial_ns();
++ return ns != init_ns;
++ }
++
++ return 0;
++}
++
+ /**
+ * kobject_uevent_env - send an uevent with environmental data
+ *
+@@ -274,7 +289,7 @@ int kobject_uevent_env(struct kobject *k
+ #endif
+
+ /* call uevent_helper, usually only enabled during early boot */
+- if (uevent_helper[0]) {
++ if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
+ char *argv [3];
+
+ argv [0] = uevent_helper;
diff --git a/driver-core/kobj-send-hotplug-events-in-the-proper-namespace.patch b/driver-core/kobj-send-hotplug-events-in-the-proper-namespace.patch
new file mode 100644
index 00000000000000..9a71ae30fd9734
--- /dev/null
+++ b/driver-core/kobj-send-hotplug-events-in-the-proper-namespace.patch
@@ -0,0 +1,60 @@
+From ebiederm@xmission.com Thu May 20 10:44:38 2010
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Tue, 4 May 2010 17:36:47 -0700
+Subject: kobj: Send hotplug events in the proper namespace.
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: Kay Sievers <kay.sievers@vrfy.org>, linux-kernel@vger.kernel.org, Tejun Heo <tj@kernel.org>, Cornelia Huck <cornelia.huck@de.ibm.com>, Eric Dumazet <eric.dumazet@gmail.com>, Benjamin LaHaise <bcrl@lhnet.ca>, Serge Hallyn <serue@us.ibm.com>, <netdev@vger.kernel.org>, David Miller <davem@davemloft.net>, "Eric W. Biederman" <ebiederm@xmission.com>
+Message-ID: <1273019809-16472-4-git-send-email-ebiederm@xmission.com>
+
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+Utilize netlink_broacast_filtered to allow sending hotplug events
+in the proper namespace.
+
+Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
+Acked-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ lib/kobject_uevent.c | 22 ++++++++++++++++++++--
+ 1 file changed, 20 insertions(+), 2 deletions(-)
+
+--- a/lib/kobject_uevent.c
++++ b/lib/kobject_uevent.c
+@@ -83,6 +83,22 @@ out:
+ return ret;
+ }
+
++static int kobj_bcast_filter(struct sock *dsk, struct sk_buff *skb, void *data)
++{
++ struct kobject *kobj = data;
++ const struct kobj_ns_type_operations *ops;
++
++ ops = kobj_ns_ops(kobj);
++ if (ops) {
++ const void *sock_ns, *ns;
++ ns = kobj->ktype->namespace(kobj);
++ sock_ns = ops->netlink_ns(dsk);
++ return sock_ns != ns;
++ }
++
++ return 0;
++}
++
+ /**
+ * kobject_uevent_env - send an uevent with environmental data
+ *
+@@ -244,8 +260,10 @@ int kobject_uevent_env(struct kobject *k
+ }
+
+ NETLINK_CB(skb).dst_group = 1;
+- retval = netlink_broadcast(uevent_sock, skb, 0, 1,
+- GFP_KERNEL);
++ retval = netlink_broadcast_filtered(uevent_sock, skb,
++ 0, 1, GFP_KERNEL,
++ kobj_bcast_filter,
++ kobj);
+ /* ENOBUFS should be handled in userspace */
+ if (retval == -ENOBUFS)
+ retval = 0;
diff --git a/driver-core/kobject-send-hotplug-events-in-all-network-namespaces.patch b/driver-core/kobject-send-hotplug-events-in-all-network-namespaces.patch
new file mode 100644
index 00000000000000..fbd071d5e401cb
--- /dev/null
+++ b/driver-core/kobject-send-hotplug-events-in-all-network-namespaces.patch
@@ -0,0 +1,139 @@
+From ebiederm@xmission.com Thu May 20 10:40:26 2010
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Tue, 4 May 2010 17:36:44 -0700
+Subject: kobject: Send hotplug events in all network namespaces
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: Kay Sievers <kay.sievers@vrfy.org>, linux-kernel@vger.kernel.org, Tejun Heo <tj@kernel.org>, Cornelia Huck <cornelia.huck@de.ibm.com>, Eric Dumazet <eric.dumazet@gmail.com>, Benjamin LaHaise <bcrl@lhnet.ca>, Serge Hallyn <serue@us.ibm.com>, <netdev@vger.kernel.org>, David Miller <davem@davemloft.net>, "Eric W. Biederman" <ebiederm@xmission.com>
+Message-ID: <1273019809-16472-1-git-send-email-ebiederm@xmission.com>
+
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+Open a copy of the uevent kernel socket in each network
+namespace so we can send uevents in all network namespaces.
+
+Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
+Acked-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ lib/kobject_uevent.c | 68 +++++++++++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 60 insertions(+), 8 deletions(-)
+
+--- a/lib/kobject_uevent.c
++++ b/lib/kobject_uevent.c
+@@ -24,13 +24,19 @@
+ #include <linux/skbuff.h>
+ #include <linux/netlink.h>
+ #include <net/sock.h>
++#include <net/net_namespace.h>
+
+
+ u64 uevent_seqnum;
+ char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
+ static DEFINE_SPINLOCK(sequence_lock);
+-#if defined(CONFIG_NET)
+-static struct sock *uevent_sock;
++#ifdef CONFIG_NET
++struct uevent_sock {
++ struct list_head list;
++ struct sock *sk;
++};
++static LIST_HEAD(uevent_sock_list);
++static DEFINE_MUTEX(uevent_sock_mutex);
+ #endif
+
+ /* the strings here must match the enum in include/linux/kobject.h */
+@@ -100,6 +106,9 @@ int kobject_uevent_env(struct kobject *k
+ u64 seq;
+ int i = 0;
+ int retval = 0;
++#ifdef CONFIG_NET
++ struct uevent_sock *ue_sk;
++#endif
+
+ pr_debug("kobject: '%s' (%p): %s\n",
+ kobject_name(kobj), kobj, __func__);
+@@ -211,7 +220,9 @@ int kobject_uevent_env(struct kobject *k
+
+ #if defined(CONFIG_NET)
+ /* send netlink message */
+- if (uevent_sock) {
++ mutex_lock(&uevent_sock_mutex);
++ list_for_each_entry(ue_sk, &uevent_sock_list, list) {
++ struct sock *uevent_sock = ue_sk->sk;
+ struct sk_buff *skb;
+ size_t len;
+
+@@ -241,6 +252,7 @@ int kobject_uevent_env(struct kobject *k
+ } else
+ retval = -ENOMEM;
+ }
++ mutex_unlock(&uevent_sock_mutex);
+ #endif
+
+ /* call uevent_helper, usually only enabled during early boot */
+@@ -320,18 +332,58 @@ int add_uevent_var(struct kobj_uevent_en
+ EXPORT_SYMBOL_GPL(add_uevent_var);
+
+ #if defined(CONFIG_NET)
+-static int __init kobject_uevent_init(void)
++static int uevent_net_init(struct net *net)
+ {
+- uevent_sock = netlink_kernel_create(&init_net, NETLINK_KOBJECT_UEVENT,
+- 1, NULL, NULL, THIS_MODULE);
+- if (!uevent_sock) {
++ struct uevent_sock *ue_sk;
++
++ ue_sk = kzalloc(sizeof(*ue_sk), GFP_KERNEL);
++ if (!ue_sk)
++ return -ENOMEM;
++
++ ue_sk->sk = netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT,
++ 1, NULL, NULL, THIS_MODULE);
++ if (!ue_sk->sk) {
+ printk(KERN_ERR
+ "kobject_uevent: unable to create netlink socket!\n");
+ return -ENODEV;
+ }
+- netlink_set_nonroot(NETLINK_KOBJECT_UEVENT, NL_NONROOT_RECV);
++ mutex_lock(&uevent_sock_mutex);
++ list_add_tail(&ue_sk->list, &uevent_sock_list);
++ mutex_unlock(&uevent_sock_mutex);
+ return 0;
+ }
+
++static void uevent_net_exit(struct net *net)
++{
++ struct uevent_sock *ue_sk;
++
++ mutex_lock(&uevent_sock_mutex);
++ list_for_each_entry(ue_sk, &uevent_sock_list, list) {
++ if (sock_net(ue_sk->sk) == net)
++ goto found;
++ }
++ mutex_unlock(&uevent_sock_mutex);
++ return;
++
++found:
++ list_del(&ue_sk->list);
++ mutex_unlock(&uevent_sock_mutex);
++
++ netlink_kernel_release(ue_sk->sk);
++ kfree(ue_sk);
++}
++
++static struct pernet_operations uevent_net_ops = {
++ .init = uevent_net_init,
++ .exit = uevent_net_exit,
++};
++
++static int __init kobject_uevent_init(void)
++{
++ netlink_set_nonroot(NETLINK_KOBJECT_UEVENT, NL_NONROOT_RECV);
++ return register_pernet_subsys(&uevent_net_ops);
++}
++
++
+ postcore_initcall(kobject_uevent_init);
+ #endif
diff --git a/driver-core/net-expose-all-network-devices-in-a-namespaces-in-sysfs.patch b/driver-core/net-expose-all-network-devices-in-a-namespaces-in-sysfs.patch
new file mode 100644
index 00000000000000..b962aecfe68bc3
--- /dev/null
+++ b/driver-core/net-expose-all-network-devices-in-a-namespaces-in-sysfs.patch
@@ -0,0 +1,173 @@
+From ebiederm@xmission.com Thu May 20 10:46:13 2010
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Tue, 4 May 2010 17:36:49 -0700
+Subject: net: Expose all network devices in a namespaces in sysfs
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: Kay Sievers <kay.sievers@vrfy.org>, linux-kernel@vger.kernel.org, Tejun Heo <tj@kernel.org>, Cornelia Huck <cornelia.huck@de.ibm.com>, Eric Dumazet <eric.dumazet@gmail.com>, Benjamin LaHaise <bcrl@lhnet.ca>, Serge Hallyn <serue@us.ibm.com>, <netdev@vger.kernel.org>, David Miller <davem@davemloft.net>, "Eric W. Biederman" <ebiederm@xmission.com>
+Message-ID: <1273019809-16472-6-git-send-email-ebiederm@xmission.com>
+
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+This reverts commit aaf8cdc34ddba08122f02217d9d684e2f9f5d575.
+
+Drivers like the ipw2100 call device_create_group when they
+are initialized and device_remove_group when they are shutdown.
+Moving them between namespaces deletes their sysfs groups early.
+
+In particular the following call chain results.
+netdev_unregister_kobject -> device_del -> kobject_del -> sysfs_remove_dir
+With sysfs_remove_dir recursively deleting all of it's subdirectories,
+and nothing adding them back.
+
+Ouch!
+
+Therefore we need to call something that ultimate calls sysfs_mv_dir
+as that sysfs function can move sysfs directories between namespaces
+without deleting their subdirectories or their contents. Allowing
+us to avoid placing extra boiler plate into every driver that does
+something interesting with sysfs.
+
+Currently the function that provides that capability is device_rename.
+That is the code works without nasty side effects as originally written.
+
+So remove the misguided fix for moving devices between namespaces. The
+bug in the kobject layer that inspired it has now been recognized and
+fixed.
+
+Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
+Acked-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/core/dev.c | 28 +++++-----------------------
+ net/core/net-sysfs.c | 16 +---------------
+ net/core/net-sysfs.h | 1 -
+ 3 files changed, 6 insertions(+), 39 deletions(-)
+
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -984,15 +984,10 @@ int dev_change_name(struct net_device *d
+ return err;
+
+ rollback:
+- /* For now only devices in the initial network namespace
+- * are in sysfs.
+- */
+- if (net_eq(net, &init_net)) {
+- ret = device_rename(&dev->dev, dev->name);
+- if (ret) {
+- memcpy(dev->name, oldname, IFNAMSIZ);
+- return ret;
+- }
++ ret = device_rename(&dev->dev, dev->name);
++ if (ret) {
++ memcpy(dev->name, oldname, IFNAMSIZ);
++ return ret;
+ }
+
+ write_lock_bh(&dev_base_lock);
+@@ -5112,8 +5107,6 @@ int register_netdevice(struct net_device
+ if (dev->features & NETIF_F_SG)
+ dev->features |= NETIF_F_GSO;
+
+- netdev_initialize_kobject(dev);
+-
+ ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev);
+ ret = notifier_to_errno(ret);
+ if (ret)
+@@ -5634,15 +5627,6 @@ int dev_change_net_namespace(struct net_
+ if (dev->features & NETIF_F_NETNS_LOCAL)
+ goto out;
+
+-#ifdef CONFIG_SYSFS
+- /* Don't allow real devices to be moved when sysfs
+- * is enabled.
+- */
+- err = -EINVAL;
+- if (dev->dev.parent)
+- goto out;
+-#endif
+-
+ /* Ensure the device has been registrered */
+ err = -EINVAL;
+ if (dev->reg_state != NETREG_REGISTERED)
+@@ -5693,8 +5677,6 @@ int dev_change_net_namespace(struct net_
+ dev_unicast_flush(dev);
+ dev_addr_discard(dev);
+
+- netdev_unregister_kobject(dev);
+-
+ /* Actually switch the network namespace */
+ dev_net_set(dev, net);
+
+@@ -5707,7 +5689,7 @@ int dev_change_net_namespace(struct net_
+ }
+
+ /* Fixup kobjects */
+- err = netdev_register_kobject(dev);
++ err = device_rename(&dev->dev, dev->name);
+ WARN_ON(err);
+
+ /* Add the device back in the hashes */
+--- a/net/core/net-sysfs.c
++++ b/net/core/net-sysfs.c
+@@ -508,9 +508,6 @@ static int netdev_uevent(struct device *
+ struct net_device *dev = to_net_dev(d);
+ int retval;
+
+- if (!net_eq(dev_net(dev), &init_net))
+- return 0;
+-
+ /* pass interface to uevent. */
+ retval = add_uevent_var(env, "INTERFACE=%s", dev->name);
+ if (retval)
+@@ -569,9 +566,6 @@ void netdev_unregister_kobject(struct ne
+
+ kobject_get(&dev->kobj);
+
+- if (!net_eq(dev_net(net), &init_net))
+- return;
+-
+ device_del(dev);
+ }
+
+@@ -581,6 +575,7 @@ int netdev_register_kobject(struct net_d
+ struct device *dev = &(net->dev);
+ const struct attribute_group **groups = net->sysfs_groups;
+
++ device_initialize(dev);
+ dev->class = &net_class;
+ dev->platform_data = net;
+ dev->groups = groups;
+@@ -603,9 +598,6 @@ int netdev_register_kobject(struct net_d
+ #endif
+ #endif /* CONFIG_SYSFS */
+
+- if (!net_eq(dev_net(net), &init_net))
+- return 0;
+-
+ return device_add(dev);
+ }
+
+@@ -622,12 +614,6 @@ void netdev_class_remove_file(struct cla
+ EXPORT_SYMBOL(netdev_class_create_file);
+ EXPORT_SYMBOL(netdev_class_remove_file);
+
+-void netdev_initialize_kobject(struct net_device *net)
+-{
+- struct device *device = &(net->dev);
+- device_initialize(device);
+-}
+-
+ int netdev_kobject_init(void)
+ {
+ kobj_ns_type_register(&net_ns_type_operations);
+--- a/net/core/net-sysfs.h
++++ b/net/core/net-sysfs.h
+@@ -4,5 +4,4 @@
+ int netdev_kobject_init(void);
+ int netdev_register_kobject(struct net_device *);
+ void netdev_unregister_kobject(struct net_device *);
+-void netdev_initialize_kobject(struct net_device *);
+ #endif
diff --git a/driver-core/net-sysfs-fix-the-bitrot-in-network-device-kobject-namespace-support.patch b/driver-core/net-sysfs-fix-the-bitrot-in-network-device-kobject-namespace-support.patch
new file mode 100644
index 00000000000000..eb4f7980fce135
--- /dev/null
+++ b/driver-core/net-sysfs-fix-the-bitrot-in-network-device-kobject-namespace-support.patch
@@ -0,0 +1,90 @@
+From ebiederm@xmission.com Thu May 20 10:42:10 2010
+From: ebiederm@xmission.com (Eric W. Biederman)
+Date: Sun, 16 May 2010 21:59:45 -0700
+Subject: net/sysfs: Fix the bitrot in network device kobject namespace support
+To: "Serge E. Hallyn" <serue@us.ibm.com>
+Cc: Greg Kroah-Hartman <gregkh@suse.de>, Kay Sievers <kay.sievers@vrfy.org>, linux-kernel@vger.kernel.org, Tejun Heo <tj@kernel.org>, Cornelia Huck <cornelia.huck@de.ibm.com>, Eric Dumazet <eric.dumazet@gmail.com>, Benjamin LaHaise <bcrl@lhnet.ca>, netdev@vger.kernel.org, David Miller <davem@davemloft.net>
+Message-ID: <m1y6fj3yym.fsf_-_@fess.ebiederm.org>
+
+I had a couple of stupid bugs in:
+netns: Teach network device kobjects which namespace they are in.
+
+- I duplicated the Kconfig for the NET_NS
+- The build was broken when sysfs was not compiled in
+
+The sysfs breakage is because after I moved the operations
+for the sysfs to the kobject layer, to make things cleaner
+I forgot to move the ifdefs. Opps.
+
+I'm not quite certain how I got introduced a second NET_NS Kconfig,
+but it was probably a 3 way merge somewhere along the way that
+did not notice that the NET_NS Kconfig option had mvoed and thout
+that was a bug. It probably slipped in because it used to be the
+sysfs patches were the first patches in my network namespace patches.
+Some things just don't go like you would expect.
+
+Neither of these bugs actually affect anything in the common case
+but they should be fixed.
+
+Thanks to Serge for noticing they were present.
+
+Reported-by: Serge E. Hallyn <serue@us.ibm.com>
+Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com>
+Acked-by: David S. Miller <davem@davemloft.net>
+
+
+---
+ net/Kconfig | 8 --------
+ net/core/net-sysfs.c | 8 +++-----
+ 2 files changed, 3 insertions(+), 13 deletions(-)
+
+--- a/net/Kconfig
++++ b/net/Kconfig
+@@ -45,14 +45,6 @@ config COMPAT_NETLINK_MESSAGES
+
+ menu "Networking options"
+
+-config NET_NS
+- bool "Network namespace support"
+- default n
+- depends on EXPERIMENTAL && NAMESPACES
+- help
+- Allow user space to create what appear to be multiple instances
+- of the network stack.
+-
+ source "net/packet/Kconfig"
+ source "net/unix/Kconfig"
+ source "net/xfrm/Kconfig"
+--- a/net/core/net-sysfs.c
++++ b/net/core/net-sysfs.c
+@@ -468,6 +468,7 @@ static struct attribute_group wireless_g
+ .attrs = wireless_attrs,
+ };
+ #endif
++#endif /* CONFIG_SYSFS */
+
+ static const void *net_current_ns(void)
+ {
+@@ -496,11 +497,10 @@ static void net_kobj_ns_exit(struct net
+ kobj_ns_exit(KOBJ_NS_TYPE_NET, net);
+ }
+
+-static struct pernet_operations sysfs_net_ops = {
++static struct pernet_operations kobj_net_ops = {
+ .exit = net_kobj_ns_exit,
+ };
+
+-#endif /* CONFIG_SYSFS */
+
+ #ifdef CONFIG_HOTPLUG
+ static int netdev_uevent(struct device *d, struct kobj_uevent_env *env)
+@@ -631,8 +631,6 @@ void netdev_initialize_kobject(struct ne
+ int netdev_kobject_init(void)
+ {
+ kobj_ns_type_register(&net_ns_type_operations);
+-#ifdef CONFIG_SYSFS
+- register_pernet_subsys(&sysfs_net_ops);
+-#endif
++ register_pernet_subsys(&kobj_net_ops);
+ return class_register(&net_class);
+ }
diff --git a/driver-core/netlink-implment-netlink_broadcast_filtered.patch b/driver-core/netlink-implment-netlink_broadcast_filtered.patch
new file mode 100644
index 00000000000000..d09e273842d050
--- /dev/null
+++ b/driver-core/netlink-implment-netlink_broadcast_filtered.patch
@@ -0,0 +1,101 @@
+From ebiederm@xmission.com Thu May 20 10:43:10 2010
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Tue, 4 May 2010 17:36:46 -0700
+Subject: netlink: Implment netlink_broadcast_filtered
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: Kay Sievers <kay.sievers@vrfy.org>, linux-kernel@vger.kernel.org, Tejun Heo <tj@kernel.org>, Cornelia Huck <cornelia.huck@de.ibm.com>, Eric Dumazet <eric.dumazet@gmail.com>, Benjamin LaHaise <bcrl@lhnet.ca>, Serge Hallyn <serue@us.ibm.com>, <netdev@vger.kernel.org>, David Miller <davem@davemloft.net>, "Eric W. Biederman" <ebiederm@xmission.com>
+Message-ID: <1273019809-16472-3-git-send-email-ebiederm@xmission.com>
+
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+When netlink sockets are used to convey data that is in a namespace
+we need a way to select a subset of the listening sockets to deliver
+the packet to. For the network namespace we have been doing this
+by only transmitting packets in the correct network namespace.
+
+For data belonging to other namespaces netlink_bradcast_filtered
+provides a mechanism that allows us to examine the destination
+socket and to decide if we should transmit the specified packet
+to it.
+
+Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
+Acked-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/netlink.h | 4 ++++
+ net/netlink/af_netlink.c | 21 +++++++++++++++++++--
+ 2 files changed, 23 insertions(+), 2 deletions(-)
+
+--- a/include/linux/netlink.h
++++ b/include/linux/netlink.h
+@@ -188,6 +188,10 @@ extern int netlink_has_listeners(struct
+ extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock);
+ extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid,
+ __u32 group, gfp_t allocation);
++extern int netlink_broadcast_filtered(struct sock *ssk, struct sk_buff *skb,
++ __u32 pid, __u32 group, gfp_t allocation,
++ int (*filter)(struct sock *dsk, struct sk_buff *skb, void *data),
++ void *filter_data);
+ extern int netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code);
+ extern int netlink_register_notifier(struct notifier_block *nb);
+ extern int netlink_unregister_notifier(struct notifier_block *nb);
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -978,6 +978,8 @@ struct netlink_broadcast_data {
+ int delivered;
+ gfp_t allocation;
+ struct sk_buff *skb, *skb2;
++ int (*tx_filter)(struct sock *dsk, struct sk_buff *skb, void *data);
++ void *tx_data;
+ };
+
+ static inline int do_one_broadcast(struct sock *sk,
+@@ -1020,6 +1022,9 @@ static inline int do_one_broadcast(struc
+ p->failure = 1;
+ if (nlk->flags & NETLINK_BROADCAST_SEND_ERROR)
+ p->delivery_failure = 1;
++ } else if (p->tx_filter && p->tx_filter(sk, p->skb2, p->tx_data)) {
++ kfree_skb(p->skb2);
++ p->skb2 = NULL;
+ } else if (sk_filter(sk, p->skb2)) {
+ kfree_skb(p->skb2);
+ p->skb2 = NULL;
+@@ -1038,8 +1043,10 @@ out:
+ return 0;
+ }
+
+-int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
+- u32 group, gfp_t allocation)
++int netlink_broadcast_filtered(struct sock *ssk, struct sk_buff *skb, u32 pid,
++ u32 group, gfp_t allocation,
++ int (*filter)(struct sock *dsk, struct sk_buff *skb, void *data),
++ void *filter_data)
+ {
+ struct net *net = sock_net(ssk);
+ struct netlink_broadcast_data info;
+@@ -1059,6 +1066,8 @@ int netlink_broadcast(struct sock *ssk,
+ info.allocation = allocation;
+ info.skb = skb;
+ info.skb2 = NULL;
++ info.tx_filter = filter;
++ info.tx_data = filter_data;
+
+ /* While we sleep in clone, do not allow to change socket list */
+
+@@ -1083,6 +1092,14 @@ int netlink_broadcast(struct sock *ssk,
+ }
+ return -ESRCH;
+ }
++EXPORT_SYMBOL(netlink_broadcast_filtered);
++
++int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
++ u32 group, gfp_t allocation)
++{
++ return netlink_broadcast_filtered(ssk, skb, pid, group, allocation,
++ NULL, NULL);
++}
+ EXPORT_SYMBOL(netlink_broadcast);
+
+ struct netlink_set_err_data {
diff --git a/driver-core/netns-teach-network-device-kobjects-which-namespace-they-are-in.patch b/driver-core/netns-teach-network-device-kobjects-which-namespace-they-are-in.patch
new file mode 100644
index 00000000000000..7f03d756267bd7
--- /dev/null
+++ b/driver-core/netns-teach-network-device-kobjects-which-namespace-they-are-in.patch
@@ -0,0 +1,144 @@
+From ebiederm@xmission.com Thu May 20 10:41:04 2010
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Tue, 4 May 2010 17:36:45 -0700
+Subject: [PATCH 2/6] netns: Teach network device kobjects which namespace they are in.
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: Kay Sievers <kay.sievers@vrfy.org>, linux-kernel@vger.kernel.org, Tejun Heo <tj@kernel.org>, Cornelia Huck <cornelia.huck@de.ibm.com>, Eric Dumazet <eric.dumazet@gmail.com>, Benjamin LaHaise <bcrl@lhnet.ca>, Serge Hallyn <serue@us.ibm.com>, <netdev@vger.kernel.org>, David Miller <davem@davemloft.net>, "Eric W. Biederman" <ebiederm@xmission.com>
+Message-ID: <1273019809-16472-2-git-send-email-ebiederm@xmission.com>
+
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+The problem. Network devices show up in sysfs and with the network
+namespace active multiple devices with the same name can show up in
+the same directory, ouch!
+
+To avoid that problem and allow existing applications in network namespaces
+to see the same interface that is currently presented in sysfs, this
+patch enables the tagging directory support in sysfs.
+
+By using the network namespace pointers as tags to separate out the
+the sysfs directory entries we ensure that we don't have conflicts
+in the directories and applications only see a limited set of
+the network devices.
+
+Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
+Acked-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/kobject.h | 1 +
+ net/Kconfig | 8 ++++++++
+ net/core/net-sysfs.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 55 insertions(+)
+
+--- a/include/linux/kobject.h
++++ b/include/linux/kobject.h
+@@ -142,6 +142,7 @@ extern const struct sysfs_ops kobj_sysfs
+ */
+ enum kobj_ns_type {
+ KOBJ_NS_TYPE_NONE = 0,
++ KOBJ_NS_TYPE_NET,
+ KOBJ_NS_TYPES
+ };
+
+--- a/net/Kconfig
++++ b/net/Kconfig
+@@ -45,6 +45,14 @@ config COMPAT_NETLINK_MESSAGES
+
+ menu "Networking options"
+
++config NET_NS
++ bool "Network namespace support"
++ default n
++ depends on EXPERIMENTAL && NAMESPACES
++ help
++ Allow user space to create what appear to be multiple instances
++ of the network stack.
++
+ source "net/packet/Kconfig"
+ source "net/unix/Kconfig"
+ source "net/xfrm/Kconfig"
+--- a/net/core/net-sysfs.c
++++ b/net/core/net-sysfs.c
+@@ -14,7 +14,9 @@
+ #include <linux/netdevice.h>
+ #include <linux/if_arp.h>
+ #include <linux/slab.h>
++#include <linux/nsproxy.h>
+ #include <net/sock.h>
++#include <net/net_namespace.h>
+ #include <linux/rtnetlink.h>
+ #include <linux/wireless.h>
+ #include <net/wext.h>
+@@ -467,6 +469,37 @@ static struct attribute_group wireless_g
+ };
+ #endif
+
++static const void *net_current_ns(void)
++{
++ return current->nsproxy->net_ns;
++}
++
++static const void *net_initial_ns(void)
++{
++ return &init_net;
++}
++
++static const void *net_netlink_ns(struct sock *sk)
++{
++ return sock_net(sk);
++}
++
++static struct kobj_ns_type_operations net_ns_type_operations = {
++ .type = KOBJ_NS_TYPE_NET,
++ .current_ns = net_current_ns,
++ .netlink_ns = net_netlink_ns,
++ .initial_ns = net_initial_ns,
++};
++
++static void net_kobj_ns_exit(struct net *net)
++{
++ kobj_ns_exit(KOBJ_NS_TYPE_NET, net);
++}
++
++static struct pernet_operations sysfs_net_ops = {
++ .exit = net_kobj_ns_exit,
++};
++
+ #endif /* CONFIG_SYSFS */
+
+ #ifdef CONFIG_HOTPLUG
+@@ -507,6 +540,13 @@ static void netdev_release(struct device
+ kfree((char *)dev - dev->padded);
+ }
+
++static const void *net_namespace(struct device *d)
++{
++ struct net_device *dev;
++ dev = container_of(d, struct net_device, dev);
++ return dev_net(dev);
++}
++
+ static struct class net_class = {
+ .name = "net",
+ .dev_release = netdev_release,
+@@ -516,6 +556,8 @@ static struct class net_class = {
+ #ifdef CONFIG_HOTPLUG
+ .dev_uevent = netdev_uevent,
+ #endif
++ .ns_type = &net_ns_type_operations,
++ .namespace = net_namespace,
+ };
+
+ /* Delete sysfs entries but hold kobject reference until after all
+@@ -588,5 +630,9 @@ void netdev_initialize_kobject(struct ne
+
+ int netdev_kobject_init(void)
+ {
++ kobj_ns_type_register(&net_ns_type_operations);
++#ifdef CONFIG_SYSFS
++ register_pernet_subsys(&sysfs_net_ops);
++#endif
+ return class_register(&net_class);
+ }
diff --git a/series b/series
index e002920dc8c49c..1062d7b6eece3b 100644
--- a/series
+++ b/series
@@ -69,6 +69,14 @@ driver-core/pci-check-caps-from-sysfs-file-open-to-read-device-dependent-config-
driver-core/driver-core-fix-typo-in-drivers-base-core.c-for-config_module.patch
driver-core/driver-core-add-devname-module-aliases-to-allow-module-on-demand-auto-loading.patch
+driver-core/kobject-send-hotplug-events-in-all-network-namespaces.patch
+driver-core/netns-teach-network-device-kobjects-which-namespace-they-are-in.patch
+driver-core/net-sysfs-fix-the-bitrot-in-network-device-kobject-namespace-support.patch
+driver-core/netlink-implment-netlink_broadcast_filtered.patch
+driver-core/kobj-send-hotplug-events-in-the-proper-namespace.patch
+driver-core/hotplug-netns-aware-uevent_helper.patch
+driver-core/net-expose-all-network-devices-in-a-namespaces-in-sysfs.patch
+
#####################################
# TTY patches for after 2.6.34 is out
#####################################
@@ -105,6 +113,9 @@ tty/serial-tidy-remote_debug.patch
# USB stuff for after 2.6.34 is out
###################################
usb/usb-xhci-fix-issue-with-set-interface-after-stall.patch
+usb/usb-xhci-limit-bus-sg_tablesize-to-62-trbs.patch
+usb/usb-xhci-fix-check-for-room-on-the-ring.patch
+
usb/usb-make-hcd.h-public-drivers-dependency.patch
usb/usb-make-hub.h-public-drivers-dependency.patch
usb/usb-split-hub.h-into-ch11.h-and-merge-in-hcd.h.patch
@@ -320,6 +331,19 @@ usb/usb-oti6858-use-kfifo-to-implement-write-buffering.patch
usb/usb-oti6858-use-port-write-fifo.patch
usb/usb-usb-storage-trivial-debug-improvements.patch
usb/usb-storage-always-print-quirks.patch
+usb/usb-safe_serial-reimplement-write-using-generic-framework.patch
+usb/usb-safe_serial-reimplement-read-using-generic-framework.patch
+usb/usb-safe_serial-straighten-out-read-processing.patch
+usb/usb-aircable-fix-incorrect-write-buffer-length.patch
+usb/usb-ir-usb-fix-incorrect-write-buffer-length.patch
+usb/usb-ti_usb-use-kfifo-to-implement-write-buffering.patch
+usb/usb-io_ti-remove-unsused-private-counter.patch
+usb/usb-io_ti-use-kfifo-to-implement-write-buffering.patch
+usb/usb-kl5usb105-fix-memory-leak.patch
+usb/usb-kl5usb105-minor-clean-ups.patch
+usb/usb-kl5usb105-reimplement-using-generic-framework.patch
+usb/usb-ftdi_sio-fix-legacy-sio-device-header.patch
+usb/usb-musb-update-gfp-slab.h-includes.patch
# this goes in last.
usb/usb-remove-unused-usb_buffer_alloc-and-usb_buffer_free-macros.patch
diff --git a/usb/usb-aircable-fix-incorrect-write-buffer-length.patch b/usb/usb-aircable-fix-incorrect-write-buffer-length.patch
new file mode 100644
index 00000000000000..c68e04ff1c87a5
--- /dev/null
+++ b/usb/usb-aircable-fix-incorrect-write-buffer-length.patch
@@ -0,0 +1,28 @@
+From jhovold@gmail.com Thu May 20 10:57:22 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 19 May 2010 00:01:33 +0200
+Subject: USB: aircable: fix incorrect write-buffer length
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1274220101-13873-5-git-send-email-jhovold@gmail.com>
+
+
+Returned length should include header length.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/serial/aircable.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/serial/aircable.c
++++ b/drivers/usb/serial/aircable.c
+@@ -95,7 +95,7 @@ static int aircable_prepare_write_buffer
+ buf[1] = TX_HEADER_1;
+ put_unaligned_le16(count, &buf[2]);
+
+- return count;
++ return count + HCI_HEADER_LENGTH;
+ }
+
+ static int aircable_probe(struct usb_serial *serial,
diff --git a/usb/usb-change-the-scatterlist-type-in-struct-urb.patch b/usb/usb-change-the-scatterlist-type-in-struct-urb.patch
index 5a9fc08f9c2922..6c824eff32c6f5 100644
--- a/usb/usb-change-the-scatterlist-type-in-struct-urb.patch
+++ b/usb/usb-change-the-scatterlist-type-in-struct-urb.patch
@@ -114,7 +114,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
void *orig;
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
-@@ -1771,7 +1771,7 @@ static unsigned int count_sg_trbs_needed
+@@ -1788,7 +1788,7 @@ static unsigned int count_sg_trbs_needed
xhci_dbg(xhci, "count sg list trbs: \n");
num_trbs = 0;
@@ -123,7 +123,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
unsigned int previous_total_trbs = num_trbs;
unsigned int len = sg_dma_len(sg);
-@@ -1934,7 +1934,7 @@ static int queue_bulk_sg_tx(struct xhci_
+@@ -1951,7 +1951,7 @@ static int queue_bulk_sg_tx(struct xhci_
* the amount of memory allocated for this scatter-gather list.
* 3. TRBs buffers can't cross 64KB boundaries.
*/
diff --git a/usb/usb-clean-up-some-host-controller-sparse-warnings.patch b/usb/usb-clean-up-some-host-controller-sparse-warnings.patch
index 132befa10a999c..fef5aec9c95f8e 100644
--- a/usb/usb-clean-up-some-host-controller-sparse-warnings.patch
+++ b/usb/usb-clean-up-some-host-controller-sparse-warnings.patch
@@ -143,7 +143,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
}
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
-@@ -371,7 +371,7 @@ static struct xhci_segment *find_trb_seg
+@@ -388,7 +388,7 @@ static struct xhci_segment *find_trb_seg
cur_seg = cur_seg->next;
if (cur_seg == start_seg)
/* Looped over the entire list. Oops! */
@@ -152,7 +152,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
}
return cur_seg;
}
-@@ -565,7 +565,7 @@ static void handle_stopped_endpoint(stru
+@@ -582,7 +582,7 @@ static void handle_stopped_endpoint(stru
struct xhci_ring *ep_ring;
struct xhci_virt_ep *ep;
struct list_head *entry;
@@ -161,7 +161,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
struct xhci_td *last_unlinked_td;
struct xhci_dequeue_state deq_state;
-@@ -1098,7 +1098,7 @@ struct xhci_segment *trb_in_td(struct xh
+@@ -1115,7 +1115,7 @@ struct xhci_segment *trb_in_td(struct xh
do {
if (start_dma == 0)
@@ -170,7 +170,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
/* We may get an event for a Link TRB in the middle of a TD */
end_seg_dma = xhci_trb_virt_to_dma(cur_seg,
&cur_seg->trbs[TRBS_PER_SEGMENT - 1]);
-@@ -1120,7 +1120,7 @@ struct xhci_segment *trb_in_td(struct xh
+@@ -1137,7 +1137,7 @@ struct xhci_segment *trb_in_td(struct xh
suspect_dma <= end_trb_dma))
return cur_seg;
}
@@ -179,7 +179,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
} else {
/* Might still be somewhere in this segment */
if (suspect_dma >= start_dma && suspect_dma <= end_seg_dma)
-@@ -1130,7 +1130,7 @@ struct xhci_segment *trb_in_td(struct xh
+@@ -1147,7 +1147,7 @@ struct xhci_segment *trb_in_td(struct xh
start_dma = xhci_trb_virt_to_dma(cur_seg, &cur_seg->trbs[0]);
} while (cur_seg != start_seg);
@@ -188,7 +188,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
}
static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
-@@ -1206,11 +1206,11 @@ static int handle_tx_event(struct xhci_h
+@@ -1223,11 +1223,11 @@ static int handle_tx_event(struct xhci_h
struct xhci_ring *ep_ring;
unsigned int slot_id;
int ep_index;
diff --git a/usb/usb-fix-usbmon-and-dma-mapping-for-scatter-gather-urbs.patch b/usb/usb-fix-usbmon-and-dma-mapping-for-scatter-gather-urbs.patch
index 7500c711d8dde2..b48f6b4a6d3865 100644
--- a/usb/usb-fix-usbmon-and-dma-mapping-for-scatter-gather-urbs.patch
+++ b/usb/usb-fix-usbmon-and-dma-mapping-for-scatter-gather-urbs.patch
@@ -451,7 +451,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
qset_free_stds(qset, urb);
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
-@@ -1945,7 +1945,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+@@ -1962,7 +1962,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
int running_total, trb_buff_len, ret;
u64 addr;
diff --git a/usb/usb-ftdi_sio-fix-legacy-sio-device-header.patch b/usb/usb-ftdi_sio-fix-legacy-sio-device-header.patch
new file mode 100644
index 00000000000000..b7ea1678730034
--- /dev/null
+++ b/usb/usb-ftdi_sio-fix-legacy-sio-device-header.patch
@@ -0,0 +1,32 @@
+From jhovold@gmail.com Thu May 20 10:58:53 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 19 May 2010 00:01:41 +0200
+Subject: USB: ftdi_sio: fix legacy SIO-device header
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1274220101-13873-13-git-send-email-jhovold@gmail.com>
+
+
+Length field of header was incorrectly set to available payload space
+rather than the actual payload size.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/serial/ftdi_sio.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -1752,10 +1752,10 @@ static int ftdi_prepare_write_buffer(str
+ spin_lock_irqsave(&port->lock, flags);
+ for (i = 0; i < size - 1; i += priv->max_packet_size) {
+ len = min_t(int, size - i, priv->max_packet_size) - 1;
+- buffer[i] = (len << 2) + 1;
+ c = kfifo_out(&port->write_fifo, &buffer[i + 1], len);
+ if (!c)
+ break;
++ buffer[i] = (c << 2) + 1;
+ count += c + 1;
+ }
+ spin_unlock_irqrestore(&port->lock, flags);
diff --git a/usb/usb-io_ti-remove-unsused-private-counter.patch b/usb/usb-io_ti-remove-unsused-private-counter.patch
new file mode 100644
index 00000000000000..5475aa864c7182
--- /dev/null
+++ b/usb/usb-io_ti-remove-unsused-private-counter.patch
@@ -0,0 +1,37 @@
+From jhovold@gmail.com Thu May 20 10:58:03 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 19 May 2010 00:01:36 +0200
+Subject: USB: io_ti: remove unsused private counter
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1274220101-13873-8-git-send-email-jhovold@gmail.com>
+
+
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/serial/io_ti.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+--- a/drivers/usb/serial/io_ti.c
++++ b/drivers/usb/serial/io_ti.c
+@@ -56,10 +56,6 @@
+ #define EPROM_PAGE_SIZE 64
+
+
+-struct edgeport_uart_buf_desc {
+- __u32 count; /* Number of bytes currently in buffer */
+-};
+-
+ /* different hardware types */
+ #define HARDWARE_TYPE_930 0
+ #define HARDWARE_TYPE_TIUMP 1
+@@ -108,7 +104,6 @@ struct edgeport_port {
+ int baud_rate;
+ int close_pending;
+ int lsr_event;
+- struct edgeport_uart_buf_desc tx;
+ struct async_icount icount;
+ wait_queue_head_t delta_msr_wait; /* for handling sleeping while
+ waiting for msr change to
diff --git a/usb/usb-io_ti-use-kfifo-to-implement-write-buffering.patch b/usb/usb-io_ti-use-kfifo-to-implement-write-buffering.patch
new file mode 100644
index 00000000000000..a53a6423df2574
--- /dev/null
+++ b/usb/usb-io_ti-use-kfifo-to-implement-write-buffering.patch
@@ -0,0 +1,349 @@
+From jhovold@gmail.com Thu May 20 10:58:11 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 19 May 2010 00:01:37 +0200
+Subject: USB: io_ti: use kfifo to implement write buffering
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1274220101-13873-9-git-send-email-jhovold@gmail.com>
+
+
+Kill custom fifo implementation.
+
+Compile-only tested.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/serial/io_ti.c | 223 ++-------------------------------------------
+ 1 file changed, 13 insertions(+), 210 deletions(-)
+
+--- a/drivers/usb/serial/io_ti.c
++++ b/drivers/usb/serial/io_ti.c
+@@ -36,6 +36,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/mutex.h>
+ #include <linux/serial.h>
++#include <linux/kfifo.h>
+ #include <linux/ioctl.h>
+ #include <linux/firmware.h>
+ #include <linux/uaccess.h>
+@@ -83,14 +84,6 @@ struct product_info {
+ __u8 hardware_type; /* Type of hardware */
+ } __attribute__((packed));
+
+-/* circular buffer */
+-struct edge_buf {
+- unsigned int buf_size;
+- char *buf_buf;
+- char *buf_get;
+- char *buf_put;
+-};
+-
+ struct edgeport_port {
+ __u16 uart_base;
+ __u16 dma_address;
+@@ -114,7 +107,7 @@ struct edgeport_port {
+ spinlock_t ep_lock;
+ int ep_read_urb_state;
+ int ep_write_urb_in_use;
+- struct edge_buf *ep_out_buf;
++ struct kfifo write_fifo;
+ };
+
+ struct edgeport_serial {
+@@ -244,17 +237,6 @@ static void edge_send(struct tty_struct
+ static int edge_create_sysfs_attrs(struct usb_serial_port *port);
+ static int edge_remove_sysfs_attrs(struct usb_serial_port *port);
+
+-/* circular buffer */
+-static struct edge_buf *edge_buf_alloc(unsigned int size);
+-static void edge_buf_free(struct edge_buf *eb);
+-static void edge_buf_clear(struct edge_buf *eb);
+-static unsigned int edge_buf_data_avail(struct edge_buf *eb);
+-static unsigned int edge_buf_space_avail(struct edge_buf *eb);
+-static unsigned int edge_buf_put(struct edge_buf *eb, const char *buf,
+- unsigned int count);
+-static unsigned int edge_buf_get(struct edge_buf *eb, char *buf,
+- unsigned int count);
+-
+
+ static int ti_vread_sync(struct usb_device *dev, __u8 request,
+ __u16 value, __u16 index, u8 *data, int size)
+@@ -585,7 +567,7 @@ static void chase_port(struct edgeport_p
+ add_wait_queue(&tty->write_wait, &wait);
+ for (;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
+- if (edge_buf_data_avail(port->ep_out_buf) == 0
++ if (kfifo_len(&port->write_fifo) == 0
+ || timeout == 0 || signal_pending(current)
+ || !usb_get_intfdata(port->port->serial->interface))
+ /* disconnect */
+@@ -597,7 +579,7 @@ static void chase_port(struct edgeport_p
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&tty->write_wait, &wait);
+ if (flush)
+- edge_buf_clear(port->ep_out_buf);
++ kfifo_reset_out(&port->write_fifo);
+ spin_unlock_irqrestore(&port->ep_lock, flags);
+ tty_kref_put(tty);
+
+@@ -2084,7 +2066,6 @@ static int edge_write(struct tty_struct
+ const unsigned char *data, int count)
+ {
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+- unsigned long flags;
+
+ dbg("%s - port %d", __func__, port->number);
+
+@@ -2098,10 +2079,8 @@ static int edge_write(struct tty_struct
+ if (edge_port->close_pending == 1)
+ return -ENODEV;
+
+- spin_lock_irqsave(&edge_port->ep_lock, flags);
+- count = edge_buf_put(edge_port->ep_out_buf, data, count);
+- spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+-
++ count = kfifo_in_locked(&edge_port->write_fifo, data, count,
++ &edge_port->ep_lock);
+ edge_send(tty);
+
+ return count;
+@@ -2124,7 +2103,7 @@ static void edge_send(struct tty_struct
+ return;
+ }
+
+- count = edge_buf_get(edge_port->ep_out_buf,
++ count = kfifo_out(&edge_port->write_fifo,
+ port->write_urb->transfer_buffer,
+ port->bulk_out_size);
+
+@@ -2180,7 +2159,7 @@ static int edge_write_room(struct tty_st
+ return 0;
+
+ spin_lock_irqsave(&edge_port->ep_lock, flags);
+- room = edge_buf_space_avail(edge_port->ep_out_buf);
++ room = kfifo_avail(&edge_port->write_fifo);
+ spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+
+ dbg("%s - returns %d", __func__, room);
+@@ -2202,7 +2181,7 @@ static int edge_chars_in_buffer(struct t
+ return 0;
+
+ spin_lock_irqsave(&edge_port->ep_lock, flags);
+- chars = edge_buf_data_avail(edge_port->ep_out_buf);
++ chars = kfifo_len(&edge_port->write_fifo);
+ spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+
+ dbg("%s - returns %d", __func__, chars);
+@@ -2659,8 +2638,8 @@ static int edge_startup(struct usb_seria
+ goto cleanup;
+ }
+ spin_lock_init(&edge_port->ep_lock);
+- edge_port->ep_out_buf = edge_buf_alloc(EDGE_OUT_BUF_SIZE);
+- if (edge_port->ep_out_buf == NULL) {
++ if (kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE,
++ GFP_KERNEL)) {
+ dev_err(&serial->dev->dev, "%s - Out of memory\n",
+ __func__);
+ kfree(edge_port);
+@@ -2677,7 +2656,7 @@ static int edge_startup(struct usb_seria
+ cleanup:
+ for (--i; i >= 0; --i) {
+ edge_port = usb_get_serial_port_data(serial->port[i]);
+- edge_buf_free(edge_port->ep_out_buf);
++ kfifo_free(&edge_port->write_fifo);
+ kfree(edge_port);
+ usb_set_serial_port_data(serial->port[i], NULL);
+ }
+@@ -2708,7 +2687,7 @@ static void edge_release(struct usb_seri
+
+ for (i = 0; i < serial->num_ports; ++i) {
+ edge_port = usb_get_serial_port_data(serial->port[i]);
+- edge_buf_free(edge_port->ep_out_buf);
++ kfifo_free(&edge_port->write_fifo);
+ kfree(edge_port);
+ }
+ kfree(usb_get_serial_data(serial));
+@@ -2758,182 +2737,6 @@ static int edge_remove_sysfs_attrs(struc
+ }
+
+
+-/* Circular Buffer */
+-
+-/*
+- * edge_buf_alloc
+- *
+- * Allocate a circular buffer and all associated memory.
+- */
+-
+-static struct edge_buf *edge_buf_alloc(unsigned int size)
+-{
+- struct edge_buf *eb;
+-
+-
+- if (size == 0)
+- return NULL;
+-
+- eb = kmalloc(sizeof(struct edge_buf), GFP_KERNEL);
+- if (eb == NULL)
+- return NULL;
+-
+- eb->buf_buf = kmalloc(size, GFP_KERNEL);
+- if (eb->buf_buf == NULL) {
+- kfree(eb);
+- return NULL;
+- }
+-
+- eb->buf_size = size;
+- eb->buf_get = eb->buf_put = eb->buf_buf;
+-
+- return eb;
+-}
+-
+-
+-/*
+- * edge_buf_free
+- *
+- * Free the buffer and all associated memory.
+- */
+-
+-static void edge_buf_free(struct edge_buf *eb)
+-{
+- if (eb) {
+- kfree(eb->buf_buf);
+- kfree(eb);
+- }
+-}
+-
+-
+-/*
+- * edge_buf_clear
+- *
+- * Clear out all data in the circular buffer.
+- */
+-
+-static void edge_buf_clear(struct edge_buf *eb)
+-{
+- if (eb != NULL)
+- eb->buf_get = eb->buf_put;
+- /* equivalent to a get of all data available */
+-}
+-
+-
+-/*
+- * edge_buf_data_avail
+- *
+- * Return the number of bytes of data available in the circular
+- * buffer.
+- */
+-
+-static unsigned int edge_buf_data_avail(struct edge_buf *eb)
+-{
+- if (eb == NULL)
+- return 0;
+- return ((eb->buf_size + eb->buf_put - eb->buf_get) % eb->buf_size);
+-}
+-
+-
+-/*
+- * edge_buf_space_avail
+- *
+- * Return the number of bytes of space available in the circular
+- * buffer.
+- */
+-
+-static unsigned int edge_buf_space_avail(struct edge_buf *eb)
+-{
+- if (eb == NULL)
+- return 0;
+- return ((eb->buf_size + eb->buf_get - eb->buf_put - 1) % eb->buf_size);
+-}
+-
+-
+-/*
+- * edge_buf_put
+- *
+- * Copy data data from a user buffer and put it into the circular buffer.
+- * Restrict to the amount of space available.
+- *
+- * Return the number of bytes copied.
+- */
+-
+-static unsigned int edge_buf_put(struct edge_buf *eb, const char *buf,
+- unsigned int count)
+-{
+- unsigned int len;
+-
+-
+- if (eb == NULL)
+- return 0;
+-
+- len = edge_buf_space_avail(eb);
+- if (count > len)
+- count = len;
+-
+- if (count == 0)
+- return 0;
+-
+- len = eb->buf_buf + eb->buf_size - eb->buf_put;
+- if (count > len) {
+- memcpy(eb->buf_put, buf, len);
+- memcpy(eb->buf_buf, buf+len, count - len);
+- eb->buf_put = eb->buf_buf + count - len;
+- } else {
+- memcpy(eb->buf_put, buf, count);
+- if (count < len)
+- eb->buf_put += count;
+- else /* count == len */
+- eb->buf_put = eb->buf_buf;
+- }
+-
+- return count;
+-}
+-
+-
+-/*
+- * edge_buf_get
+- *
+- * Get data from the circular buffer and copy to the given buffer.
+- * Restrict to the amount of data available.
+- *
+- * Return the number of bytes copied.
+- */
+-
+-static unsigned int edge_buf_get(struct edge_buf *eb, char *buf,
+- unsigned int count)
+-{
+- unsigned int len;
+-
+-
+- if (eb == NULL)
+- return 0;
+-
+- len = edge_buf_data_avail(eb);
+- if (count > len)
+- count = len;
+-
+- if (count == 0)
+- return 0;
+-
+- len = eb->buf_buf + eb->buf_size - eb->buf_get;
+- if (count > len) {
+- memcpy(buf, eb->buf_get, len);
+- memcpy(buf+len, eb->buf_buf, count - len);
+- eb->buf_get = eb->buf_buf + count - len;
+- } else {
+- memcpy(buf, eb->buf_get, count);
+- if (count < len)
+- eb->buf_get += count;
+- else /* count == len */
+- eb->buf_get = eb->buf_buf;
+- }
+-
+- return count;
+-}
+-
+-
+ static struct usb_serial_driver edgeport_1port_device = {
+ .driver = {
+ .owner = THIS_MODULE,
diff --git a/usb/usb-ir-usb-fix-incorrect-write-buffer-length.patch b/usb/usb-ir-usb-fix-incorrect-write-buffer-length.patch
new file mode 100644
index 00000000000000..b19d435047cffb
--- /dev/null
+++ b/usb/usb-ir-usb-fix-incorrect-write-buffer-length.patch
@@ -0,0 +1,38 @@
+From jhovold@gmail.com Thu May 20 10:57:39 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 19 May 2010 00:01:34 +0200
+Subject: USB: ir-usb: fix incorrect write-buffer length
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1274220101-13873-6-git-send-email-jhovold@gmail.com>
+
+
+Returned length should include header length.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/serial/ir-usb.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/serial/ir-usb.c
++++ b/drivers/usb/serial/ir-usb.c
+@@ -307,6 +307,7 @@ static int ir_prepare_write_buffer(struc
+ void *dest, size_t size)
+ {
+ unsigned char *buf = dest;
++ int count;
+
+ /*
+ * The first byte of the packet we send to the device contains an
+@@ -317,8 +318,9 @@ static int ir_prepare_write_buffer(struc
+ */
+ *buf = ir_xbof | ir_baud;
+
+- return kfifo_out_locked(&port->write_fifo, buf + 1, size - 1,
++ count = kfifo_out_locked(&port->write_fifo, buf + 1, size - 1,
+ &port->lock);
++ return count + 1;
+ }
+
+ static void ir_process_read_urb(struct urb *urb)
diff --git a/usb/usb-kl5usb105-fix-memory-leak.patch b/usb/usb-kl5usb105-fix-memory-leak.patch
new file mode 100644
index 00000000000000..8611cdcdf38bda
--- /dev/null
+++ b/usb/usb-kl5usb105-fix-memory-leak.patch
@@ -0,0 +1,28 @@
+From jhovold@gmail.com Thu May 20 10:58:20 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 19 May 2010 00:01:38 +0200
+Subject: USB: kl5usb105: fix memory leak
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>, stable <stable@kernel.org>
+Message-ID: <1274220101-13873-10-git-send-email-jhovold@gmail.com>
+
+
+Private data was not freed on error path in startup.
+
+Cc: stable <stable@kernel.org>
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/serial/kl5kusb105.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/usb/serial/kl5kusb105.c
++++ b/drivers/usb/serial/kl5kusb105.c
+@@ -321,6 +321,7 @@ err_cleanup:
+ usb_free_urb(priv->write_urb_pool[j]);
+ }
+ }
++ kfree(priv);
+ usb_set_serial_port_data(serial->port[i], NULL);
+ }
+ return -ENOMEM;
diff --git a/usb/usb-kl5usb105-minor-clean-ups.patch b/usb/usb-kl5usb105-minor-clean-ups.patch
new file mode 100644
index 00000000000000..51e876e7c0202d
--- /dev/null
+++ b/usb/usb-kl5usb105-minor-clean-ups.patch
@@ -0,0 +1,228 @@
+From jhovold@gmail.com Thu May 20 10:58:29 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 19 May 2010 00:01:39 +0200
+Subject: USB: kl5usb105: minor clean ups
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1274220101-13873-11-git-send-email-jhovold@gmail.com>
+
+
+Whitespace changes and some removed comments.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/serial/kl5kusb105.c | 79 ++++++++++++++++------------------------
+ 1 file changed, 33 insertions(+), 46 deletions(-)
+
+--- a/drivers/usb/serial/kl5kusb105.c
++++ b/drivers/usb/serial/kl5kusb105.c
+@@ -107,7 +107,7 @@ static struct usb_driver kl5kusb105d_dri
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = id_table,
+- .no_dynamic_id = 1,
++ .no_dynamic_id = 1,
+ };
+
+ static struct usb_serial_driver kl5kusb105d_device = {
+@@ -115,26 +115,26 @@ static struct usb_serial_driver kl5kusb1
+ .owner = THIS_MODULE,
+ .name = "kl5kusb105d",
+ },
+- .description = "KL5KUSB105D / PalmConnect",
+- .usb_driver = &kl5kusb105d_driver,
+- .id_table = id_table,
+- .num_ports = 1,
+- .open = klsi_105_open,
+- .close = klsi_105_close,
+- .write = klsi_105_write,
+- .write_bulk_callback = klsi_105_write_bulk_callback,
+- .chars_in_buffer = klsi_105_chars_in_buffer,
+- .write_room = klsi_105_write_room,
+- .read_bulk_callback = klsi_105_read_bulk_callback,
+- .set_termios = klsi_105_set_termios,
+- /*.break_ctl = klsi_105_break_ctl,*/
+- .tiocmget = klsi_105_tiocmget,
+- .tiocmset = klsi_105_tiocmset,
+- .attach = klsi_105_startup,
+- .disconnect = klsi_105_disconnect,
+- .release = klsi_105_release,
+- .throttle = klsi_105_throttle,
+- .unthrottle = klsi_105_unthrottle,
++ .description = "KL5KUSB105D / PalmConnect",
++ .usb_driver = &kl5kusb105d_driver,
++ .id_table = id_table,
++ .num_ports = 1,
++ .open = klsi_105_open,
++ .close = klsi_105_close,
++ .write = klsi_105_write,
++ .write_bulk_callback = klsi_105_write_bulk_callback,
++ .chars_in_buffer = klsi_105_chars_in_buffer,
++ .write_room = klsi_105_write_room,
++ .read_bulk_callback = klsi_105_read_bulk_callback,
++ .set_termios = klsi_105_set_termios,
++ /*.break_ctl = klsi_105_break_ctl,*/
++ .tiocmget = klsi_105_tiocmget,
++ .tiocmset = klsi_105_tiocmset,
++ .attach = klsi_105_startup,
++ .disconnect = klsi_105_disconnect,
++ .release = klsi_105_release,
++ .throttle = klsi_105_throttle,
++ .unthrottle = klsi_105_unthrottle,
+ };
+
+ struct klsi_105_port_settings {
+@@ -189,7 +189,7 @@ static int klsi_105_chg_port_settings(st
+ settings->pktlen, settings->baudrate, settings->databits,
+ settings->unknown1, settings->unknown2);
+ return rc;
+-} /* klsi_105_chg_port_settings */
++}
+
+ /* translate a 16-bit status value from the device to linux's TIO bits */
+ static unsigned long klsi_105_status2linestate(const __u16 status)
+@@ -202,6 +202,7 @@ static unsigned long klsi_105_status2lin
+
+ return res;
+ }
++
+ /*
+ * Read line control via vendor command and return result through
+ * *line_state_p
+@@ -325,8 +326,7 @@ err_cleanup:
+ usb_set_serial_port_data(serial->port[i], NULL);
+ }
+ return -ENOMEM;
+-} /* klsi_105_startup */
+-
++}
+
+ static void klsi_105_disconnect(struct usb_serial *serial)
+ {
+@@ -352,8 +352,7 @@ static void klsi_105_disconnect(struct u
+ }
+ }
+ }
+-} /* klsi_105_disconnect */
+-
++}
+
+ static void klsi_105_release(struct usb_serial *serial)
+ {
+@@ -367,7 +366,7 @@ static void klsi_105_release(struct usb_
+
+ kfree(priv);
+ }
+-} /* klsi_105_release */
++}
+
+ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
+ {
+@@ -461,8 +460,7 @@ static int klsi_105_open(struct tty_str
+ exit:
+ kfree(cfg);
+ return retval;
+-} /* klsi_105_open */
+-
++}
+
+ static void klsi_105_close(struct usb_serial_port *port)
+ {
+@@ -498,8 +496,7 @@ static void klsi_105_close(struct usb_se
+ dev_info(&port->serial->dev->dev,
+ "port stats: %ld bytes in, %ld bytes out\n",
+ priv->bytes_in, priv->bytes_out);
+-} /* klsi_105_close */
+-
++}
+
+ /* We need to write a complete 64-byte data block and encode the
+ * number actually sent in the first double-byte, LSB-order. That
+@@ -507,7 +504,6 @@ static void klsi_105_close(struct usb_se
+ */
+ #define KLSI_105_DATA_OFFSET 2 /* in the bulk urb data block */
+
+-
+ static int klsi_105_write(struct tty_struct *tty,
+ struct usb_serial_port *port, const unsigned char *buf, int count)
+ {
+@@ -586,7 +582,7 @@ exit:
+ priv->bytes_out += bytes_sent;
+
+ return bytes_sent; /* that's how much we wrote */
+-} /* klsi_105_write */
++}
+
+ static void klsi_105_write_bulk_callback(struct urb *urb)
+ {
+@@ -602,8 +598,7 @@ static void klsi_105_write_bulk_callback
+ }
+
+ usb_serial_port_softint(port);
+-} /* klsi_105_write_bulk_completion_callback */
+-
++}
+
+ /* return number of characters currently in the writing process */
+ static int klsi_105_chars_in_buffer(struct tty_struct *tty)
+@@ -647,8 +642,6 @@ static int klsi_105_write_room(struct tt
+ return room;
+ }
+
+-
+-
+ static void klsi_105_read_bulk_callback(struct urb *urb)
+ {
+ struct usb_serial_port *port = urb->context;
+@@ -720,8 +713,7 @@ static void klsi_105_read_bulk_callback(
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+ __func__, rc);
+-} /* klsi_105_read_bulk_callback */
+-
++}
+
+ static void klsi_105_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port,
+@@ -888,8 +880,7 @@ static void klsi_105_set_termios(struct
+ klsi_105_chg_port_settings(port, cfg);
+ err:
+ kfree(cfg);
+-} /* klsi_105_set_termios */
+-
++}
+
+ #if 0
+ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
+@@ -907,7 +898,7 @@ static void mct_u232_break_ctl(struct tt
+ lcr |= MCT_U232_SET_BREAK;
+
+ mct_u232_set_line_ctrl(serial, lcr);
+-} /* mct_u232_break_ctl */
++}
+ #endif
+
+ static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file)
+@@ -986,7 +977,6 @@ static void klsi_105_unthrottle(struct t
+ }
+
+
+-
+ static int __init klsi_105_init(void)
+ {
+ int retval;
+@@ -1006,7 +996,6 @@ failed_usb_serial_register:
+ return retval;
+ }
+
+-
+ static void __exit klsi_105_exit(void)
+ {
+ usb_deregister(&kl5kusb105d_driver);
+@@ -1024,5 +1013,3 @@ MODULE_LICENSE("GPL");
+
+ module_param(debug, bool, S_IRUGO | S_IWUSR);
+ MODULE_PARM_DESC(debug, "enable extensive debugging messages");
+-
+-/* vim: set sts=8 ts=8 sw=8: */
diff --git a/usb/usb-kl5usb105-reimplement-using-generic-framework.patch b/usb/usb-kl5usb105-reimplement-using-generic-framework.patch
new file mode 100644
index 00000000000000..ff3f9bc4a9a615
--- /dev/null
+++ b/usb/usb-kl5usb105-reimplement-using-generic-framework.patch
@@ -0,0 +1,556 @@
+From jhovold@gmail.com Thu May 20 10:58:37 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 19 May 2010 00:01:40 +0200
+Subject: USB: kl5usb105: reimplement using generic framework
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1274220101-13873-12-git-send-email-jhovold@gmail.com>
+
+
+Kill custom read and write implementations (static per-port,
+singleton(!) urb pool).
+
+Also remove changelog header (can be retrieved through git).
+
+Read processing and write-buffer handling tested using a cp210x device
+in a loopback setup.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/serial/kl5kusb105.c | 380 ++++------------------------------------
+ 1 file changed, 47 insertions(+), 333 deletions(-)
+
+--- a/drivers/usb/serial/kl5kusb105.c
++++ b/drivers/usb/serial/kl5kusb105.c
+@@ -1,6 +1,7 @@
+ /*
+ * KLSI KL5KUSB105 chip RS232 converter driver
+ *
++ * Copyright (C) 2010 Johan Hovold <jhovold@gmail.com>
+ * Copyright (C) 2001 Utz-Uwe Haus <haus@uuhaus.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+@@ -34,17 +35,6 @@
+ * implement handshaking or decide that we do not support it
+ */
+
+-/* History:
+- * 0.3a - implemented pools of write URBs
+- * 0.3 - alpha version for public testing
+- * 0.2 - TIOCMGET works, so autopilot(1) can be used!
+- * 0.1 - can be used to do pilot-xfer -p /dev/ttyUSB0 -l
+- *
+- * The driver skeleton is mainly based on mct_u232.c and various other
+- * pieces of code shamelessly copied from the drivers/usb/serial/ directory.
+- */
+-
+-
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+ #include <linux/init.h>
+@@ -64,8 +54,8 @@ static int debug;
+ /*
+ * Version Information
+ */
+-#define DRIVER_VERSION "v0.3a"
+-#define DRIVER_AUTHOR "Utz-Uwe Haus <haus@uuhaus.de>"
++#define DRIVER_VERSION "v0.4"
++#define DRIVER_AUTHOR "Utz-Uwe Haus <haus@uuhaus.de>, Johan Hovold <jhovold@gmail.com>"
+ #define DRIVER_DESC "KLSI KL5KUSB105 chipset USB->Serial Converter driver"
+
+
+@@ -73,23 +63,17 @@ static int debug;
+ * Function prototypes
+ */
+ static int klsi_105_startup(struct usb_serial *serial);
+-static void klsi_105_disconnect(struct usb_serial *serial);
+ static void klsi_105_release(struct usb_serial *serial);
+ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port);
+ static void klsi_105_close(struct usb_serial_port *port);
+-static int klsi_105_write(struct tty_struct *tty,
+- struct usb_serial_port *port, const unsigned char *buf, int count);
+-static void klsi_105_write_bulk_callback(struct urb *urb);
+-static int klsi_105_chars_in_buffer(struct tty_struct *tty);
+-static int klsi_105_write_room(struct tty_struct *tty);
+-static void klsi_105_read_bulk_callback(struct urb *urb);
+ static void klsi_105_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old);
+-static void klsi_105_throttle(struct tty_struct *tty);
+-static void klsi_105_unthrottle(struct tty_struct *tty);
+ static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file);
+ static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
++static void klsi_105_process_read_urb(struct urb *urb);
++static int klsi_105_prepare_write_buffer(struct usb_serial_port *port,
++ void *dest, size_t size);
+
+ /*
+ * All of the device info needed for the KLSI converters.
+@@ -119,22 +103,19 @@ static struct usb_serial_driver kl5kusb1
+ .usb_driver = &kl5kusb105d_driver,
+ .id_table = id_table,
+ .num_ports = 1,
++ .bulk_out_size = 64,
+ .open = klsi_105_open,
+ .close = klsi_105_close,
+- .write = klsi_105_write,
+- .write_bulk_callback = klsi_105_write_bulk_callback,
+- .chars_in_buffer = klsi_105_chars_in_buffer,
+- .write_room = klsi_105_write_room,
+- .read_bulk_callback = klsi_105_read_bulk_callback,
+ .set_termios = klsi_105_set_termios,
+ /*.break_ctl = klsi_105_break_ctl,*/
+ .tiocmget = klsi_105_tiocmget,
+ .tiocmset = klsi_105_tiocmset,
+ .attach = klsi_105_startup,
+- .disconnect = klsi_105_disconnect,
+ .release = klsi_105_release,
+- .throttle = klsi_105_throttle,
+- .unthrottle = klsi_105_unthrottle,
++ .throttle = usb_serial_generic_throttle,
++ .unthrottle = usb_serial_generic_unthrottle,
++ .process_read_urb = klsi_105_process_read_urb,
++ .prepare_write_buffer = klsi_105_prepare_write_buffer,
+ };
+
+ struct klsi_105_port_settings {
+@@ -145,18 +126,11 @@ struct klsi_105_port_settings {
+ __u8 unknown2;
+ } __attribute__ ((packed));
+
+-/* we implement a pool of NUM_URBS urbs per usb_serial */
+-#define NUM_URBS 1
+-#define URB_TRANSFER_BUFFER_SIZE 64
+ struct klsi_105_private {
+ struct klsi_105_port_settings cfg;
+ struct ktermios termios;
+ unsigned long line_state; /* modem line settings */
+- /* write pool */
+- struct urb *write_urb_pool[NUM_URBS];
+ spinlock_t lock;
+- unsigned long bytes_in;
+- unsigned long bytes_out;
+ };
+
+
+@@ -259,7 +233,7 @@ static int klsi_105_get_line_state(struc
+ static int klsi_105_startup(struct usb_serial *serial)
+ {
+ struct klsi_105_private *priv;
+- int i, j;
++ int i;
+
+ /* check if we support the product id (see keyspan.c)
+ * FIXME
+@@ -283,29 +257,9 @@ static int klsi_105_startup(struct usb_s
+
+ priv->line_state = 0;
+
+- priv->bytes_in = 0;
+- priv->bytes_out = 0;
+ usb_set_serial_port_data(serial->port[i], priv);
+
+ spin_lock_init(&priv->lock);
+- for (j = 0; j < NUM_URBS; j++) {
+- struct urb *urb = usb_alloc_urb(0, GFP_KERNEL);
+-
+- priv->write_urb_pool[j] = urb;
+- if (urb == NULL) {
+- dev_err(&serial->dev->dev, "No more urbs???\n");
+- goto err_cleanup;
+- }
+-
+- urb->transfer_buffer =
+- kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+- if (!urb->transfer_buffer) {
+- dev_err(&serial->dev->dev,
+- "%s - out of memory for urb buffers.\n",
+- __func__);
+- goto err_cleanup;
+- }
+- }
+
+ /* priv->termios is left uninitalized until port opening */
+ init_waitqueue_head(&serial->port[i]->write_wait);
+@@ -316,56 +270,20 @@ static int klsi_105_startup(struct usb_s
+ err_cleanup:
+ for (; i >= 0; i--) {
+ priv = usb_get_serial_port_data(serial->port[i]);
+- for (j = 0; j < NUM_URBS; j++) {
+- if (priv->write_urb_pool[j]) {
+- kfree(priv->write_urb_pool[j]->transfer_buffer);
+- usb_free_urb(priv->write_urb_pool[j]);
+- }
+- }
+ kfree(priv);
+ usb_set_serial_port_data(serial->port[i], NULL);
+ }
+ return -ENOMEM;
+ }
+
+-static void klsi_105_disconnect(struct usb_serial *serial)
+-{
+- int i;
+-
+- dbg("%s", __func__);
+-
+- /* stop reads and writes on all ports */
+- for (i = 0; i < serial->num_ports; ++i) {
+- struct klsi_105_private *priv =
+- usb_get_serial_port_data(serial->port[i]);
+-
+- if (priv) {
+- /* kill our write urb pool */
+- int j;
+- struct urb **write_urbs = priv->write_urb_pool;
+-
+- for (j = 0; j < NUM_URBS; j++) {
+- if (write_urbs[j]) {
+- usb_kill_urb(write_urbs[j]);
+- usb_free_urb(write_urbs[j]);
+- }
+- }
+- }
+- }
+-}
+-
+ static void klsi_105_release(struct usb_serial *serial)
+ {
+ int i;
+
+ dbg("%s", __func__);
+
+- for (i = 0; i < serial->num_ports; ++i) {
+- struct klsi_105_private *priv =
+- usb_get_serial_port_data(serial->port[i]);
+-
+- kfree(priv);
+- }
++ for (i = 0; i < serial->num_ports; ++i)
++ kfree(usb_get_serial_port_data(serial->port[i]));
+ }
+
+ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
+@@ -416,18 +334,8 @@ static int klsi_105_open(struct tty_str
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* READ_ON and urb submission */
+- usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+- usb_rcvbulkpipe(port->serial->dev,
+- port->bulk_in_endpointAddress),
+- port->read_urb->transfer_buffer,
+- port->read_urb->transfer_buffer_length,
+- klsi_105_read_bulk_callback,
+- port);
+-
+- rc = usb_submit_urb(port->read_urb, GFP_KERNEL);
++ rc = usb_serial_generic_open(tty, port);
+ if (rc) {
+- dev_err(&port->dev, "%s - failed submitting read urb, "
+- "error %d\n", __func__, rc);
+ retval = rc;
+ goto exit;
+ }
+@@ -464,7 +372,6 @@ exit:
+
+ static void klsi_105_close(struct usb_serial_port *port)
+ {
+- struct klsi_105_private *priv = usb_get_serial_port_data(port);
+ int rc;
+
+ dbg("%s port %d", __func__, port->number);
+@@ -487,232 +394,61 @@ static void klsi_105_close(struct usb_se
+ mutex_unlock(&port->serial->disc_mutex);
+
+ /* shutdown our bulk reads and writes */
+- usb_kill_urb(port->write_urb);
+- usb_kill_urb(port->read_urb);
+- /* unlink our write pool */
+- /* FIXME */
++ usb_serial_generic_close(port);
++
+ /* wgg - do I need this? I think so. */
+ usb_kill_urb(port->interrupt_in_urb);
+- dev_info(&port->serial->dev->dev,
+- "port stats: %ld bytes in, %ld bytes out\n",
+- priv->bytes_in, priv->bytes_out);
+ }
+
+ /* We need to write a complete 64-byte data block and encode the
+ * number actually sent in the first double-byte, LSB-order. That
+ * leaves at most 62 bytes of payload.
+ */
+-#define KLSI_105_DATA_OFFSET 2 /* in the bulk urb data block */
+-
+-static int klsi_105_write(struct tty_struct *tty,
+- struct usb_serial_port *port, const unsigned char *buf, int count)
+-{
+- struct klsi_105_private *priv = usb_get_serial_port_data(port);
+- int result, size;
+- int bytes_sent = 0;
+-
+- dbg("%s - port %d", __func__, port->number);
+-
+- while (count > 0) {
+- /* try to find a free urb (write 0 bytes if none) */
+- struct urb *urb = NULL;
+- unsigned long flags;
+- int i;
+- /* since the pool is per-port we might not need
+- the spin lock !? */
+- spin_lock_irqsave(&priv->lock, flags);
+- for (i = 0; i < NUM_URBS; i++) {
+- if (priv->write_urb_pool[i]->status != -EINPROGRESS) {
+- urb = priv->write_urb_pool[i];
+- dbg("%s - using pool URB %d", __func__, i);
+- break;
+- }
+- }
+- spin_unlock_irqrestore(&priv->lock, flags);
+-
+- if (urb == NULL) {
+- dbg("%s - no more free urbs", __func__);
+- goto exit;
+- }
+-
+- if (urb->transfer_buffer == NULL) {
+- urb->transfer_buffer =
+- kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
+- if (urb->transfer_buffer == NULL) {
+- dev_err(&port->dev,
+- "%s - no more kernel memory...\n",
+- __func__);
+- goto exit;
+- }
+- }
+-
+- size = min(count, port->bulk_out_size - KLSI_105_DATA_OFFSET);
+- size = min(size, URB_TRANSFER_BUFFER_SIZE -
+- KLSI_105_DATA_OFFSET);
+-
+- memcpy(urb->transfer_buffer + KLSI_105_DATA_OFFSET, buf, size);
+-
+- /* write payload size into transfer buffer */
+- ((__u8 *)urb->transfer_buffer)[0] = (__u8) (size & 0xFF);
+- ((__u8 *)urb->transfer_buffer)[1] = (__u8) ((size & 0xFF00)>>8);
+-
+- /* set up our urb */
+- usb_fill_bulk_urb(urb, port->serial->dev,
+- usb_sndbulkpipe(port->serial->dev,
+- port->bulk_out_endpointAddress),
+- urb->transfer_buffer,
+- URB_TRANSFER_BUFFER_SIZE,
+- klsi_105_write_bulk_callback,
+- port);
+-
+- /* send the data out the bulk port */
+- result = usb_submit_urb(urb, GFP_ATOMIC);
+- if (result) {
+- dev_err(&port->dev,
+- "%s - failed submitting write urb, error %d\n",
+- __func__, result);
+- goto exit;
+- }
+- buf += size;
+- bytes_sent += size;
+- count -= size;
+- }
+-exit:
+- /* lockless, but it's for debug info only... */
+- priv->bytes_out += bytes_sent;
+-
+- return bytes_sent; /* that's how much we wrote */
+-}
+-
+-static void klsi_105_write_bulk_callback(struct urb *urb)
+-{
+- struct usb_serial_port *port = urb->context;
+- int status = urb->status;
+-
+- dbg("%s - port %d", __func__, port->number);
+-
+- if (status) {
+- dbg("%s - nonzero write bulk status received: %d", __func__,
+- status);
+- return;
+- }
+-
+- usb_serial_port_softint(port);
+-}
+-
+-/* return number of characters currently in the writing process */
+-static int klsi_105_chars_in_buffer(struct tty_struct *tty)
++#define KLSI_HDR_LEN 2
++static int klsi_105_prepare_write_buffer(struct usb_serial_port *port,
++ void *dest, size_t size)
+ {
+- struct usb_serial_port *port = tty->driver_data;
+- int chars = 0;
+- int i;
+- unsigned long flags;
+- struct klsi_105_private *priv = usb_get_serial_port_data(port);
+-
+- spin_lock_irqsave(&priv->lock, flags);
++ unsigned char *buf = dest;
++ int count;
+
+- for (i = 0; i < NUM_URBS; ++i) {
+- if (priv->write_urb_pool[i]->status == -EINPROGRESS)
+- chars += URB_TRANSFER_BUFFER_SIZE;
+- }
+-
+- spin_unlock_irqrestore(&priv->lock, flags);
++ count = kfifo_out_locked(&port->write_fifo, buf + KLSI_HDR_LEN, size,
++ &port->lock);
++ put_unaligned_le16(count, buf);
+
+- dbg("%s - returns %d", __func__, chars);
+- return chars;
++ return count + KLSI_HDR_LEN;
+ }
+
+-static int klsi_105_write_room(struct tty_struct *tty)
+-{
+- struct usb_serial_port *port = tty->driver_data;
+- unsigned long flags;
+- int i;
+- int room = 0;
+- struct klsi_105_private *priv = usb_get_serial_port_data(port);
+-
+- spin_lock_irqsave(&priv->lock, flags);
+- for (i = 0; i < NUM_URBS; ++i) {
+- if (priv->write_urb_pool[i]->status != -EINPROGRESS)
+- room += URB_TRANSFER_BUFFER_SIZE;
+- }
+-
+- spin_unlock_irqrestore(&priv->lock, flags);
+-
+- dbg("%s - returns %d", __func__, room);
+- return room;
+-}
+-
+-static void klsi_105_read_bulk_callback(struct urb *urb)
++/* The data received is preceded by a length double-byte in LSB-first order.
++ */
++static void klsi_105_process_read_urb(struct urb *urb)
+ {
+ struct usb_serial_port *port = urb->context;
+- struct klsi_105_private *priv = usb_get_serial_port_data(port);
+- struct tty_struct *tty;
+ unsigned char *data = urb->transfer_buffer;
+- int rc;
+- int status = urb->status;
++ struct tty_struct *tty;
++ unsigned len;
+
+- dbg("%s - port %d", __func__, port->number);
++ /* empty urbs seem to happen, we ignore them */
++ if (!urb->actual_length)
++ return;
+
+- /* The urb might have been killed. */
+- if (status) {
+- dbg("%s - nonzero read bulk status received: %d", __func__,
+- status);
++ if (urb->actual_length <= KLSI_HDR_LEN) {
++ dbg("%s - malformed packet", __func__);
+ return;
+ }
+
+- /* The data received is again preceded by a length double-byte in LSB-
+- * first order (see klsi_105_write() )
+- */
+- if (urb->actual_length == 0) {
+- /* empty urbs seem to happen, we ignore them */
+- /* dbg("%s - emtpy URB", __func__); */
+- ;
+- } else if (urb->actual_length <= 2) {
+- dbg("%s - size %d URB not understood", __func__,
+- urb->actual_length);
+- usb_serial_debug_data(debug, &port->dev, __func__,
+- urb->actual_length, data);
+- } else {
+- int bytes_sent = ((__u8 *) data)[0] +
+- ((unsigned int) ((__u8 *) data)[1] << 8);
+- tty = tty_port_tty_get(&port->port);
+- /* we should immediately resubmit the URB, before attempting
+- * to pass the data on to the tty layer. But that needs locking
+- * against re-entry an then mixed-up data because of
+- * intermixed tty_flip_buffer_push()s
+- * FIXME
+- */
+- usb_serial_debug_data(debug, &port->dev, __func__,
+- urb->actual_length, data);
++ tty = tty_port_tty_get(&port->port);
++ if (!tty)
++ return;
+
+- if (bytes_sent + 2 > urb->actual_length) {
+- dbg("%s - trying to read more data than available"
+- " (%d vs. %d)", __func__,
+- bytes_sent+2, urb->actual_length);
+- /* cap at implied limit */
+- bytes_sent = urb->actual_length - 2;
+- }
++ len = get_unaligned_le16(data);
++ if (len > urb->actual_length - KLSI_HDR_LEN) {
++ dbg("%s - packet length mismatch", __func__);
++ len = urb->actual_length - KLSI_HDR_LEN;
++ }
+
+- tty_insert_flip_string(tty, data + 2, bytes_sent);
+- tty_flip_buffer_push(tty);
+- tty_kref_put(tty);
+-
+- /* again lockless, but debug info only */
+- priv->bytes_in += bytes_sent;
+- }
+- /* Continue trying to always read */
+- usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+- usb_rcvbulkpipe(port->serial->dev,
+- port->bulk_in_endpointAddress),
+- port->read_urb->transfer_buffer,
+- port->read_urb->transfer_buffer_length,
+- klsi_105_read_bulk_callback,
+- port);
+- rc = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+- if (rc)
+- dev_err(&port->dev,
+- "%s - failed resubmitting read urb, error %d\n",
+- __func__, rc);
++ tty_insert_flip_string(tty, data + KLSI_HDR_LEN, len);
++ tty_flip_buffer_push(tty);
++ tty_kref_put(tty);
+ }
+
+ static void klsi_105_set_termios(struct tty_struct *tty,
+@@ -954,28 +690,6 @@ static int klsi_105_tiocmset(struct tty_
+ return retval;
+ }
+
+-static void klsi_105_throttle(struct tty_struct *tty)
+-{
+- struct usb_serial_port *port = tty->driver_data;
+- dbg("%s - port %d", __func__, port->number);
+- usb_kill_urb(port->read_urb);
+-}
+-
+-static void klsi_105_unthrottle(struct tty_struct *tty)
+-{
+- struct usb_serial_port *port = tty->driver_data;
+- int result;
+-
+- dbg("%s - port %d", __func__, port->number);
+-
+- port->read_urb->dev = port->serial->dev;
+- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+- if (result)
+- dev_err(&port->dev,
+- "%s - failed submitting read urb, error %d\n",
+- __func__, result);
+-}
+-
+
+ static int __init klsi_105_init(void)
+ {
diff --git a/usb/usb-musb-update-gfp-slab.h-includes.patch b/usb/usb-musb-update-gfp-slab.h-includes.patch
new file mode 100644
index 00000000000000..03df19d39384b3
--- /dev/null
+++ b/usb/usb-musb-update-gfp-slab.h-includes.patch
@@ -0,0 +1,29 @@
+From sfr@canb.auug.org.au Thu May 20 10:59:27 2010
+From: Tejun Heo <tj@kernel.org>
+Date: Thu, 20 May 2010 01:44:20 +1000
+Subject: usb: musb: update gfp/slab.h includes
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-next@vger.kernel.org, linux-kernel@vger.kernel.org, Tejun Heo <tj@kernel.org>
+Message-ID: <20100520014420.22a0e715.sfr@canb.auug.org.au>
+
+Implicit slab.h inclusion via percpu.h is about to go away. Make sure
+gfp.h or slab.h is included as necessary.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Cc: Stephen Rothwell <sfr@canb.auug.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/musb_debugfs.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/usb/musb/musb_debugfs.c
++++ b/drivers/usb/musb/musb_debugfs.c
+@@ -34,7 +34,6 @@
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+-#include <linux/slab.h>
+ #include <linux/init.h>
+ #include <linux/list.h>
+ #include <linux/kobject.h>
diff --git a/usb/usb-safe_serial-reimplement-read-using-generic-framework.patch b/usb/usb-safe_serial-reimplement-read-using-generic-framework.patch
new file mode 100644
index 00000000000000..4aad8f00a97e54
--- /dev/null
+++ b/usb/usb-safe_serial-reimplement-read-using-generic-framework.patch
@@ -0,0 +1,97 @@
+From jhovold@gmail.com Thu May 20 10:57:01 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 19 May 2010 00:01:31 +0200
+Subject: USB: safe_serial: reimplement read using generic framework
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1274220101-13873-3-git-send-email-jhovold@gmail.com>
+
+
+Use process_read_urb to implement read processing.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/safe_serial.c | 47 ++++++---------------------------------
+ 1 file changed, 8 insertions(+), 39 deletions(-)
+
+--- a/drivers/usb/serial/safe_serial.c
++++ b/drivers/usb/serial/safe_serial.c
+@@ -213,38 +213,20 @@ static __u16 __inline__ fcs_compute10(un
+ return fcs;
+ }
+
+-static void safe_read_bulk_callback(struct urb *urb)
++static void safe_process_read_urb(struct urb *urb)
+ {
+- struct usb_serial_port *port = urb->context;
++ struct usb_serial_port *port = urb->context;
+ unsigned char *data = urb->transfer_buffer;
+ unsigned char length = urb->actual_length;
+ struct tty_struct *tty;
+- int result;
+- int status = urb->status;
+
+- dbg("%s", __func__);
+-
+- if (status) {
+- dbg("%s - nonzero read bulk status received: %d",
+- __func__, status);
++ if (!length)
+ return;
+- }
+
+- dbg("safe_read_bulk_callback length: %d",
+- port->read_urb->actual_length);
+-#ifdef ECHO_RCV
+- {
+- int i;
+- unsigned char *cp = port->read_urb->transfer_buffer;
+- for (i = 0; i < port->read_urb->actual_length; i++) {
+- if ((i % 32) == 0)
+- printk("\nru[%02x] ", i);
+- printk("%02x ", *cp++);
+- }
+- printk("\n");
+- }
+-#endif
+ tty = tty_port_tty_get(&port->port);
++ if (!tty)
++ return;
++
+ if (safe) {
+ __u16 fcs;
+ fcs = fcs_compute10(data, length, CRC10_INITFCS);
+@@ -268,21 +250,8 @@ static void safe_read_bulk_callback(stru
+ tty_insert_flip_string(tty, data, length);
+ tty_flip_buffer_push(tty);
+ }
+- tty_kref_put(tty);
+
+- /* Continue trying to always read */
+- usb_fill_bulk_urb(urb, port->serial->dev,
+- usb_rcvbulkpipe(port->serial->dev,
+- port->bulk_in_endpointAddress),
+- urb->transfer_buffer, urb->transfer_buffer_length,
+- safe_read_bulk_callback, port);
+-
+- result = usb_submit_urb(urb, GFP_ATOMIC);
+- if (result)
+- dev_err(&port->dev,
+- "%s - failed resubmitting read urb, error %d\n",
+- __func__, result);
+- /* FIXME: Need a mechanism to retry later if this happens */
++ tty_kref_put(tty);
+ }
+
+ static int safe_prepare_write_buffer(struct usb_serial_port *port,
+@@ -343,7 +312,7 @@ static struct usb_serial_driver safe_dev
+ .id_table = id_table,
+ .usb_driver = &safe_driver,
+ .num_ports = 1,
+- .read_bulk_callback = safe_read_bulk_callback,
++ .process_read_urb = safe_process_read_urb,
+ .prepare_write_buffer = safe_prepare_write_buffer,
+ .attach = safe_startup,
+ };
diff --git a/usb/usb-safe_serial-reimplement-write-using-generic-framework.patch b/usb/usb-safe_serial-reimplement-write-using-generic-framework.patch
new file mode 100644
index 00000000000000..a2f927462f9a85
--- /dev/null
+++ b/usb/usb-safe_serial-reimplement-write-using-generic-framework.patch
@@ -0,0 +1,204 @@
+From jhovold@gmail.com Thu May 20 10:56:47 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 19 May 2010 00:01:30 +0200
+Subject: USB: safe_serial: reimplement write using generic framework
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1274220101-13873-2-git-send-email-jhovold@gmail.com>
+
+
+Kill custom single-urb write implementation.
+
+Note that this driver still depended on the write callback from the old
+generic framework.
+
+Tested against original read processing using a cp210x device in a
+loopback setup.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/safe_serial.c | 143 ++++++++-------------------------------
+ 1 file changed, 32 insertions(+), 111 deletions(-)
+
+--- a/drivers/usb/serial/safe_serial.c
++++ b/drivers/usb/serial/safe_serial.c
+@@ -1,6 +1,7 @@
+ /*
+ * Safe Encapsulated USB Serial Driver
+ *
++ * Copyright (C) 2010 Johan Hovold <jhovold@gmail.com>
+ * Copyright (C) 2001 Lineo
+ * Copyright (C) 2001 Hewlett-Packard
+ *
+@@ -84,8 +85,8 @@ static int debug;
+ static int safe = 1;
+ static int padded = CONFIG_USB_SERIAL_SAFE_PADDED;
+
+-#define DRIVER_VERSION "v0.0b"
+-#define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com"
++#define DRIVER_VERSION "v0.1"
++#define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com, Johan Hovold <jhovold@gmail.com>"
+ #define DRIVER_DESC "USB Safe Encapsulated Serial"
+
+ MODULE_AUTHOR(DRIVER_AUTHOR);
+@@ -284,119 +285,40 @@ static void safe_read_bulk_callback(stru
+ /* FIXME: Need a mechanism to retry later if this happens */
+ }
+
+-static int safe_write(struct tty_struct *tty, struct usb_serial_port *port,
+- const unsigned char *buf, int count)
++static int safe_prepare_write_buffer(struct usb_serial_port *port,
++ void *dest, size_t size)
+ {
+- unsigned char *data;
+- int result;
+- int i;
+- int packet_length;
+-
+- dbg("safe_write port: %p %d urb: %p count: %d",
+- port, port->number, port->write_urb, count);
+-
+- if (!port->write_urb) {
+- dbg("%s - write urb NULL", __func__);
+- return 0;
+- }
+-
+- dbg("safe_write write_urb: %d transfer_buffer_length",
+- port->write_urb->transfer_buffer_length);
+-
+- if (!port->write_urb->transfer_buffer_length) {
+- dbg("%s - write urb transfer_buffer_length zero", __func__);
+- return 0;
+- }
+- if (count == 0) {
+- dbg("%s - write request of 0 bytes", __func__);
+- return 0;
+- }
+- spin_lock_bh(&port->lock);
+- if (port->write_urb_busy) {
+- spin_unlock_bh(&port->lock);
+- dbg("%s - already writing", __func__);
+- return 0;
+- }
+- port->write_urb_busy = 1;
+- spin_unlock_bh(&port->lock);
+-
+- packet_length = port->bulk_out_size; /* get max packetsize */
+-
+- i = packet_length - (safe ? 2 : 0); /* get bytes to send */
+- count = (count > i) ? i : count;
+-
+-
+- /* get the data into the transfer buffer */
+- data = port->write_urb->transfer_buffer;
+- memset(data, '0', packet_length);
+-
+- memcpy(data, buf, count);
+-
+- if (safe) {
+- __u16 fcs;
+-
+- /* pad if necessary */
+- if (!padded)
+- packet_length = count + 2;
+- /* set count */
+- data[packet_length - 2] = count << 2;
+- data[packet_length - 1] = 0;
+-
+- /* compute fcs and insert into trailer */
+- fcs = fcs_compute10(data, packet_length, CRC10_INITFCS);
+- data[packet_length - 2] |= fcs >> 8;
+- data[packet_length - 1] |= fcs & 0xff;
+-
+- /* set length to send */
+- port->write_urb->transfer_buffer_length = packet_length;
++ unsigned char *buf = dest;
++ int count;
++ int trailer_len;
++ int pkt_len;
++ __u16 fcs;
++
++ trailer_len = safe ? 2 : 0;
++
++ count = kfifo_out_locked(&port->write_fifo, buf, size - trailer_len,
++ &port->lock);
++ if (!safe)
++ return count;
++
++ /* pad if necessary */
++ if (padded) {
++ pkt_len = size;
++ memset(buf + count, '0', pkt_len - count - trailer_len);
+ } else {
+- port->write_urb->transfer_buffer_length = count;
++ pkt_len = count + trailer_len;
+ }
+
+- usb_serial_debug_data(debug, &port->dev, __func__, count,
+- port->write_urb->transfer_buffer);
+-#ifdef ECHO_TX
+- {
+- int i;
+- unsigned char *cp = port->write_urb->transfer_buffer;
+- for (i = 0; i < port->write_urb->transfer_buffer_length; i++) {
+- if ((i % 32) == 0)
+- printk("\nsu[%02x] ", i);
+- printk("%02x ", *cp++);
+- }
+- printk("\n");
+- }
+-#endif
+- port->write_urb->dev = port->serial->dev;
+- result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+- if (result) {
+- port->write_urb_busy = 0;
+- dev_err(&port->dev,
+- "%s - failed submitting write urb, error %d\n",
+- __func__, result);
+- return 0;
+- }
+- dbg("%s urb: %p submitted", __func__, port->write_urb);
+-
+- return count;
+-}
+-
+-static int safe_write_room(struct tty_struct *tty)
+-{
+- struct usb_serial_port *port = tty->driver_data;
+- int room = 0; /* Default: no room */
+- unsigned long flags;
++ /* set count */
++ buf[pkt_len - 2] = count << 2;
++ buf[pkt_len - 1] = 0;
+
+- dbg("%s", __func__);
++ /* compute fcs and insert into trailer */
++ fcs = fcs_compute10(buf, pkt_len, CRC10_INITFCS);
++ buf[pkt_len - 2] |= fcs >> 8;
++ buf[pkt_len - 1] |= fcs & 0xff;
+
+- spin_lock_irqsave(&port->lock, flags);
+- if (port->write_urb_busy)
+- room = port->bulk_out_size - (safe ? 2 : 0);
+- spin_unlock_irqrestore(&port->lock, flags);
+-
+- if (room)
+- dbg("safe_write_room returns %d", room);
+- return room;
++ return pkt_len;
+ }
+
+ static int safe_startup(struct usb_serial *serial)
+@@ -421,9 +343,8 @@ static struct usb_serial_driver safe_dev
+ .id_table = id_table,
+ .usb_driver = &safe_driver,
+ .num_ports = 1,
+- .write = safe_write,
+- .write_room = safe_write_room,
+ .read_bulk_callback = safe_read_bulk_callback,
++ .prepare_write_buffer = safe_prepare_write_buffer,
+ .attach = safe_startup,
+ };
+
diff --git a/usb/usb-safe_serial-straighten-out-read-processing.patch b/usb/usb-safe_serial-straighten-out-read-processing.patch
new file mode 100644
index 00000000000000..80bcd6bc172bf9
--- /dev/null
+++ b/usb/usb-safe_serial-straighten-out-read-processing.patch
@@ -0,0 +1,82 @@
+From jhovold@gmail.com Thu May 20 10:57:10 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 19 May 2010 00:01:32 +0200
+Subject: USB: safe_serial: straighten out read processing
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1274220101-13873-4-git-send-email-jhovold@gmail.com>
+
+
+Clean up read processing logic.
+
+Tested using a cp210x device in a loopback setup.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/safe_serial.c | 43 +++++++++++++++++++--------------------
+ 1 file changed, 21 insertions(+), 22 deletions(-)
+
+--- a/drivers/usb/serial/safe_serial.c
++++ b/drivers/usb/serial/safe_serial.c
+@@ -218,7 +218,9 @@ static void safe_process_read_urb(struct
+ struct usb_serial_port *port = urb->context;
+ unsigned char *data = urb->transfer_buffer;
+ unsigned char length = urb->actual_length;
++ int actual_length;
+ struct tty_struct *tty;
++ __u16 fcs;
+
+ if (!length)
+ return;
+@@ -227,30 +229,27 @@ static void safe_process_read_urb(struct
+ if (!tty)
+ return;
+
+- if (safe) {
+- __u16 fcs;
+- fcs = fcs_compute10(data, length, CRC10_INITFCS);
+- if (!fcs) {
+- int actual_length = data[length - 2] >> 2;
+- if (actual_length <= (length - 2)) {
+- dev_info(&urb->dev->dev, "%s - actual: %d\n",
+- __func__, actual_length);
+- tty_insert_flip_string(tty,
+- data, actual_length);
+- tty_flip_buffer_push(tty);
+- } else {
+- dev_err(&port->dev,
+- "%s - inconsistent lengths %d:%d\n",
+- __func__, actual_length, length);
+- }
+- } else {
+- dev_err(&port->dev, "%s - bad CRC %x\n", __func__, fcs);
+- }
+- } else {
+- tty_insert_flip_string(tty, data, length);
+- tty_flip_buffer_push(tty);
++ if (!safe)
++ goto out;
++
++ fcs = fcs_compute10(data, length, CRC10_INITFCS);
++ if (fcs) {
++ dev_err(&port->dev, "%s - bad CRC %x\n", __func__, fcs);
++ goto err;
+ }
+
++ actual_length = data[length - 2] >> 2;
++ if (actual_length > (length - 2)) {
++ dev_err(&port->dev, "%s - inconsistent lengths %d:%d\n",
++ __func__, actual_length, length);
++ goto err;
++ }
++ dev_info(&urb->dev->dev, "%s - actual: %d\n", __func__, actual_length);
++ length = actual_length;
++out:
++ tty_insert_flip_string(tty, data, length);
++ tty_flip_buffer_push(tty);
++err:
+ tty_kref_put(tty);
+ }
+
diff --git a/usb/usb-ti_usb-use-kfifo-to-implement-write-buffering.patch b/usb/usb-ti_usb-use-kfifo-to-implement-write-buffering.patch
new file mode 100644
index 00000000000000..6a792b738ead11
--- /dev/null
+++ b/usb/usb-ti_usb-use-kfifo-to-implement-write-buffering.patch
@@ -0,0 +1,302 @@
+From jhovold@gmail.com Thu May 20 10:57:53 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 19 May 2010 00:01:35 +0200
+Subject: USB: ti_usb: use kfifo to implement write buffering
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1274220101-13873-7-git-send-email-jhovold@gmail.com>
+
+
+Kill custom fifo implementation.
+
+Compile-only tested.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/serial/ti_usb_3410_5052.c | 179 ++--------------------------------
+ 1 file changed, 14 insertions(+), 165 deletions(-)
+
+--- a/drivers/usb/serial/ti_usb_3410_5052.c
++++ b/drivers/usb/serial/ti_usb_3410_5052.c
+@@ -30,7 +30,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/ioctl.h>
+ #include <linux/serial.h>
+-#include <linux/circ_buf.h>
++#include <linux/kfifo.h>
+ #include <linux/mutex.h>
+ #include <linux/uaccess.h>
+ #include <linux/usb.h>
+@@ -40,7 +40,7 @@
+
+ /* Defines */
+
+-#define TI_DRIVER_VERSION "v0.9"
++#define TI_DRIVER_VERSION "v0.10"
+ #define TI_DRIVER_AUTHOR "Al Borchers <alborchers@steinerpoint.com>"
+ #define TI_DRIVER_DESC "TI USB 3410/5052 Serial Driver"
+
+@@ -82,7 +82,7 @@ struct ti_port {
+ spinlock_t tp_lock;
+ int tp_read_urb_state;
+ int tp_write_urb_in_use;
+- struct circ_buf *tp_write_buf;
++ struct kfifo write_fifo;
+ };
+
+ struct ti_device {
+@@ -144,15 +144,6 @@ static int ti_write_byte(struct ti_devic
+
+ static int ti_download_firmware(struct ti_device *tdev);
+
+-/* circular buffer */
+-static struct circ_buf *ti_buf_alloc(void);
+-static void ti_buf_free(struct circ_buf *cb);
+-static void ti_buf_clear(struct circ_buf *cb);
+-static int ti_buf_data_avail(struct circ_buf *cb);
+-static int ti_buf_space_avail(struct circ_buf *cb);
+-static int ti_buf_put(struct circ_buf *cb, const char *buf, int count);
+-static int ti_buf_get(struct circ_buf *cb, char *buf, int count);
+-
+
+ /* Data */
+
+@@ -450,8 +441,8 @@ static int ti_startup(struct usb_serial
+ tport->tp_closing_wait = closing_wait;
+ init_waitqueue_head(&tport->tp_msr_wait);
+ init_waitqueue_head(&tport->tp_write_wait);
+- tport->tp_write_buf = ti_buf_alloc();
+- if (tport->tp_write_buf == NULL) {
++ if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE,
++ GFP_KERNEL)) {
+ dev_err(&dev->dev, "%s - out of memory\n", __func__);
+ kfree(tport);
+ status = -ENOMEM;
+@@ -468,7 +459,7 @@ static int ti_startup(struct usb_serial
+ free_tports:
+ for (--i; i >= 0; --i) {
+ tport = usb_get_serial_port_data(serial->port[i]);
+- ti_buf_free(tport->tp_write_buf);
++ kfifo_free(&tport->write_fifo);
+ kfree(tport);
+ usb_set_serial_port_data(serial->port[i], NULL);
+ }
+@@ -490,7 +481,7 @@ static void ti_release(struct usb_serial
+ for (i = 0; i < serial->num_ports; ++i) {
+ tport = usb_get_serial_port_data(serial->port[i]);
+ if (tport) {
+- ti_buf_free(tport->tp_write_buf);
++ kfifo_free(&tport->write_fifo);
+ kfree(tport);
+ }
+ }
+@@ -701,7 +692,6 @@ static int ti_write(struct tty_struct *t
+ const unsigned char *data, int count)
+ {
+ struct ti_port *tport = usb_get_serial_port_data(port);
+- unsigned long flags;
+
+ dbg("%s - port %d", __func__, port->number);
+
+@@ -713,10 +703,8 @@ static int ti_write(struct tty_struct *t
+ if (tport == NULL || !tport->tp_is_open)
+ return -ENODEV;
+
+- spin_lock_irqsave(&tport->tp_lock, flags);
+- count = ti_buf_put(tport->tp_write_buf, data, count);
+- spin_unlock_irqrestore(&tport->tp_lock, flags);
+-
++ count = kfifo_in_locked(&tport->write_fifo, data, count,
++ &tport->tp_lock);
+ ti_send(tport);
+
+ return count;
+@@ -736,7 +724,7 @@ static int ti_write_room(struct tty_stru
+ return 0;
+
+ spin_lock_irqsave(&tport->tp_lock, flags);
+- room = ti_buf_space_avail(tport->tp_write_buf);
++ room = kfifo_avail(&tport->write_fifo);
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+
+ dbg("%s - returns %d", __func__, room);
+@@ -757,7 +745,7 @@ static int ti_chars_in_buffer(struct tty
+ return 0;
+
+ spin_lock_irqsave(&tport->tp_lock, flags);
+- chars = ti_buf_data_avail(tport->tp_write_buf);
++ chars = kfifo_len(&tport->write_fifo);
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+
+ dbg("%s - returns %d", __func__, chars);
+@@ -1309,7 +1297,7 @@ static void ti_send(struct ti_port *tpor
+ if (tport->tp_write_urb_in_use)
+ goto unlock;
+
+- count = ti_buf_get(tport->tp_write_buf,
++ count = kfifo_out(&tport->write_fifo,
+ port->write_urb->transfer_buffer,
+ port->bulk_out_size);
+
+@@ -1504,7 +1492,7 @@ static void ti_drain(struct ti_port *tpo
+ add_wait_queue(&tport->tp_write_wait, &wait);
+ for (;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
+- if (ti_buf_data_avail(tport->tp_write_buf) == 0
++ if (kfifo_len(&tport->write_fifo) == 0
+ || timeout == 0 || signal_pending(current)
+ || tdev->td_urb_error
+ || port->serial->disconnected) /* disconnect */
+@@ -1518,7 +1506,7 @@ static void ti_drain(struct ti_port *tpo
+
+ /* flush any remaining data in the buffer */
+ if (flush)
+- ti_buf_clear(tport->tp_write_buf);
++ kfifo_reset_out(&tport->write_fifo);
+
+ spin_unlock_irq(&tport->tp_lock);
+
+@@ -1761,142 +1749,3 @@ static int ti_download_firmware(struct t
+
+ return 0;
+ }
+-
+-
+-/* Circular Buffer Functions */
+-
+-/*
+- * ti_buf_alloc
+- *
+- * Allocate a circular buffer and all associated memory.
+- */
+-
+-static struct circ_buf *ti_buf_alloc(void)
+-{
+- struct circ_buf *cb;
+-
+- cb = kmalloc(sizeof(struct circ_buf), GFP_KERNEL);
+- if (cb == NULL)
+- return NULL;
+-
+- cb->buf = kmalloc(TI_WRITE_BUF_SIZE, GFP_KERNEL);
+- if (cb->buf == NULL) {
+- kfree(cb);
+- return NULL;
+- }
+-
+- ti_buf_clear(cb);
+-
+- return cb;
+-}
+-
+-
+-/*
+- * ti_buf_free
+- *
+- * Free the buffer and all associated memory.
+- */
+-
+-static void ti_buf_free(struct circ_buf *cb)
+-{
+- kfree(cb->buf);
+- kfree(cb);
+-}
+-
+-
+-/*
+- * ti_buf_clear
+- *
+- * Clear out all data in the circular buffer.
+- */
+-
+-static void ti_buf_clear(struct circ_buf *cb)
+-{
+- cb->head = cb->tail = 0;
+-}
+-
+-
+-/*
+- * ti_buf_data_avail
+- *
+- * Return the number of bytes of data available in the circular
+- * buffer.
+- */
+-
+-static int ti_buf_data_avail(struct circ_buf *cb)
+-{
+- return CIRC_CNT(cb->head, cb->tail, TI_WRITE_BUF_SIZE);
+-}
+-
+-
+-/*
+- * ti_buf_space_avail
+- *
+- * Return the number of bytes of space available in the circular
+- * buffer.
+- */
+-
+-static int ti_buf_space_avail(struct circ_buf *cb)
+-{
+- return CIRC_SPACE(cb->head, cb->tail, TI_WRITE_BUF_SIZE);
+-}
+-
+-
+-/*
+- * ti_buf_put
+- *
+- * Copy data data from a user buffer and put it into the circular buffer.
+- * Restrict to the amount of space available.
+- *
+- * Return the number of bytes copied.
+- */
+-
+-static int ti_buf_put(struct circ_buf *cb, const char *buf, int count)
+-{
+- int c, ret = 0;
+-
+- while (1) {
+- c = CIRC_SPACE_TO_END(cb->head, cb->tail, TI_WRITE_BUF_SIZE);
+- if (count < c)
+- c = count;
+- if (c <= 0)
+- break;
+- memcpy(cb->buf + cb->head, buf, c);
+- cb->head = (cb->head + c) & (TI_WRITE_BUF_SIZE-1);
+- buf += c;
+- count -= c;
+- ret += c;
+- }
+-
+- return ret;
+-}
+-
+-
+-/*
+- * ti_buf_get
+- *
+- * Get data from the circular buffer and copy to the given buffer.
+- * Restrict to the amount of data available.
+- *
+- * Return the number of bytes copied.
+- */
+-
+-static int ti_buf_get(struct circ_buf *cb, char *buf, int count)
+-{
+- int c, ret = 0;
+-
+- while (1) {
+- c = CIRC_CNT_TO_END(cb->head, cb->tail, TI_WRITE_BUF_SIZE);
+- if (count < c)
+- c = count;
+- if (c <= 0)
+- break;
+- memcpy(buf, cb->buf + cb->tail, c);
+- cb->tail = (cb->tail + c) & (TI_WRITE_BUF_SIZE-1);
+- buf += c;
+- count -= c;
+- ret += c;
+- }
+-
+- return ret;
+-}
diff --git a/usb/usb-xhci-correct-assumptions-about-number-of-rings-per-endpoint.patch b/usb/usb-xhci-correct-assumptions-about-number-of-rings-per-endpoint.patch
index 7d371450313f57..1e8ffcb7b1c963 100644
--- a/usb/usb-xhci-correct-assumptions-about-number-of-rings-per-endpoint.patch
+++ b/usb/usb-xhci-correct-assumptions-about-number-of-rings-per-endpoint.patch
@@ -179,7 +179,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
SCT_FOR_CTX(SCT_PRI_TR) |
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
-@@ -295,7 +295,8 @@ void xhci_ring_cmd_db(struct xhci_hcd *x
+@@ -312,7 +312,8 @@ void xhci_ring_cmd_db(struct xhci_hcd *x
static void ring_ep_doorbell(struct xhci_hcd *xhci,
unsigned int slot_id,
@@ -189,7 +189,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
{
struct xhci_virt_ep *ep;
unsigned int ep_state;
-@@ -314,7 +315,8 @@ static void ring_ep_doorbell(struct xhci
+@@ -331,7 +332,8 @@ static void ring_ep_doorbell(struct xhci
if (!(ep_state & EP_HALT_PENDING) && !(ep_state & SET_DEQ_PENDING)
&& !(ep_state & EP_HALTED)) {
field = xhci_readl(xhci, db_addr) & DB_MASK;
@@ -199,7 +199,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
/* Flush PCI posted writes - FIXME Matthew Wilcox says this
* isn't time-critical and we shouldn't make the CPU wait for
* the flush.
-@@ -323,6 +325,31 @@ static void ring_ep_doorbell(struct xhci
+@@ -340,6 +342,31 @@ static void ring_ep_doorbell(struct xhci
}
}
@@ -231,7 +231,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
/*
* Find the segment that trb is in. Start searching in start_seg.
* If we must move past a segment that has a link TRB with a toggle cycle state
-@@ -365,14 +392,23 @@ static struct xhci_segment *find_trb_seg
+@@ -382,14 +409,23 @@ static struct xhci_segment *find_trb_seg
*/
void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
unsigned int slot_id, unsigned int ep_index,
@@ -257,7 +257,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
state->new_cycle_state = 0;
xhci_dbg(xhci, "Finding segment containing stopped TRB.\n");
state->new_deq_seg = find_trb_seg(cur_td->start_seg,
-@@ -452,11 +488,13 @@ static void td_to_noop(struct xhci_hcd *
+@@ -469,11 +505,13 @@ static void td_to_noop(struct xhci_hcd *
}
static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
@@ -272,7 +272,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
struct xhci_dequeue_state *deq_state)
{
struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index];
-@@ -468,7 +506,7 @@ void xhci_queue_new_dequeue_state(struct
+@@ -485,7 +523,7 @@ void xhci_queue_new_dequeue_state(struct
deq_state->new_deq_ptr,
(unsigned long long)xhci_trb_virt_to_dma(deq_state->new_deq_seg, deq_state->new_deq_ptr),
deq_state->new_cycle_state);
@@ -281,7 +281,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
deq_state->new_deq_seg,
deq_state->new_deq_ptr,
(u32) deq_state->new_cycle_state);
-@@ -536,11 +574,10 @@ static void handle_stopped_endpoint(stru
+@@ -553,11 +591,10 @@ static void handle_stopped_endpoint(stru
slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
ep = &xhci->devs[slot_id]->eps[ep_index];
@@ -294,7 +294,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
return;
}
-@@ -554,15 +591,36 @@ static void handle_stopped_endpoint(stru
+@@ -571,15 +608,36 @@ static void handle_stopped_endpoint(stru
xhci_dbg(xhci, "Cancelling TD starting at %p, 0x%llx (dma).\n",
cur_td->first_trb,
(unsigned long long)xhci_trb_virt_to_dma(cur_td->start_seg, cur_td->first_trb));
@@ -333,7 +333,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
/*
* The event handler won't see a completion for this TD anymore,
* so remove it from the endpoint ring's TD list. Keep it in
-@@ -576,11 +634,13 @@ static void handle_stopped_endpoint(stru
+@@ -593,11 +651,13 @@ static void handle_stopped_endpoint(stru
/* If necessary, queue a Set Transfer Ring Dequeue Pointer command */
if (deq_state.new_deq_ptr && deq_state.new_deq_seg) {
xhci_queue_new_dequeue_state(xhci,
@@ -350,7 +350,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
}
ep->stopped_td = NULL;
ep->stopped_trb = NULL;
-@@ -740,6 +800,7 @@ static void handle_set_deq_completion(st
+@@ -757,6 +817,7 @@ static void handle_set_deq_completion(st
{
unsigned int slot_id;
unsigned int ep_index;
@@ -358,7 +358,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
struct xhci_ring *ep_ring;
struct xhci_virt_device *dev;
struct xhci_ep_ctx *ep_ctx;
-@@ -747,8 +808,19 @@ static void handle_set_deq_completion(st
+@@ -764,8 +825,19 @@ static void handle_set_deq_completion(st
slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
@@ -379,7 +379,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx);
-@@ -793,7 +865,8 @@ static void handle_set_deq_completion(st
+@@ -810,7 +882,8 @@ static void handle_set_deq_completion(st
}
dev->eps[ep_index].ep_state &= ~SET_DEQ_PENDING;
@@ -389,7 +389,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
}
static void handle_reset_ep_completion(struct xhci_hcd *xhci,
-@@ -802,11 +875,9 @@ static void handle_reset_ep_completion(s
+@@ -819,11 +892,9 @@ static void handle_reset_ep_completion(s
{
int slot_id;
unsigned int ep_index;
@@ -401,7 +401,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
/* This command will only fail if the endpoint wasn't halted,
* but we don't care.
*/
-@@ -824,9 +895,9 @@ static void handle_reset_ep_completion(s
+@@ -841,9 +912,9 @@ static void handle_reset_ep_completion(s
false);
xhci_ring_cmd_db(xhci);
} else {
@@ -413,7 +413,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
}
}
-@@ -912,8 +983,10 @@ static void handle_cmd_completion(struct
+@@ -929,8 +1000,10 @@ static void handle_cmd_completion(struct
/* Input ctx add_flags are the endpoint index plus one */
ep_index = xhci_last_valid_endpoint(ctrl_ctx->add_flags) - 1;
/* A usb_set_interface() call directly after clearing a halted
@@ -426,7 +426,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
*/
if (xhci->quirks & XHCI_RESET_EP_QUIRK &&
ep_index != (unsigned int) -1 &&
-@@ -926,10 +999,10 @@ static void handle_cmd_completion(struct
+@@ -943,10 +1016,10 @@ static void handle_cmd_completion(struct
xhci_dbg(xhci, "Completed config ep cmd - "
"last ep index = %d, state = %d\n",
ep_index, ep_state);
@@ -439,7 +439,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
break;
}
bandwidth_change:
-@@ -1062,12 +1135,14 @@ struct xhci_segment *trb_in_td(struct xh
+@@ -1079,12 +1152,14 @@ struct xhci_segment *trb_in_td(struct xh
static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
unsigned int slot_id, unsigned int ep_index,
@@ -454,7 +454,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
xhci_queue_reset_ep(xhci, slot_id, ep_index);
xhci_cleanup_stalled_ring(xhci, td->urb->dev, ep_index);
-@@ -1152,10 +1227,11 @@ static int handle_tx_event(struct xhci_h
+@@ -1169,10 +1244,11 @@ static int handle_tx_event(struct xhci_h
ep_index = TRB_TO_EP_ID(event->flags) - 1;
xhci_dbg(xhci, "%s - ep index = %d\n", __func__, ep_index);
ep = &xdev->eps[ep_index];
@@ -468,7 +468,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
return -ENODEV;
}
-@@ -1286,7 +1362,7 @@ static int handle_tx_event(struct xhci_h
+@@ -1303,7 +1379,7 @@ static int handle_tx_event(struct xhci_h
td->urb->actual_length = 0;
xhci_cleanup_halted_endpoint(xhci,
@@ -477,7 +477,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
goto td_cleanup;
}
/*
-@@ -1435,6 +1511,7 @@ static int handle_tx_event(struct xhci_h
+@@ -1452,6 +1528,7 @@ static int handle_tx_event(struct xhci_h
*/
ep->stopped_td = td;
ep->stopped_trb = event_trb;
@@ -485,7 +485,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
} else if (xhci_requires_manual_halt_cleanup(xhci,
ep_ctx, trb_comp_code)) {
/* Other types of errors halt the endpoint, but the
-@@ -1443,7 +1520,7 @@ static int handle_tx_event(struct xhci_h
+@@ -1460,7 +1537,7 @@ static int handle_tx_event(struct xhci_h
* xHCI hardware manually.
*/
xhci_cleanup_halted_endpoint(xhci,
@@ -494,7 +494,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
} else {
/* Update ring dequeue pointer */
while (ep_ring->dequeue != td->last_trb)
-@@ -1639,14 +1716,24 @@ static int prepare_ring(struct xhci_hcd
+@@ -1656,14 +1733,24 @@ static int prepare_ring(struct xhci_hcd
static int prepare_transfer(struct xhci_hcd *xhci,
struct xhci_virt_device *xdev,
unsigned int ep_index,
@@ -520,7 +520,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
ep_ctx->ep_info & EP_STATE_MASK,
num_trbs, mem_flags);
if (ret)
-@@ -1666,9 +1753,9 @@ static int prepare_transfer(struct xhci_
+@@ -1683,9 +1770,9 @@ static int prepare_transfer(struct xhci_
(*td)->urb = urb;
urb->hcpriv = (void *) (*td);
/* Add this TD to the tail of the endpoint ring's TD list */
@@ -533,7 +533,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
return 0;
}
-@@ -1734,7 +1821,7 @@ static void check_trb_math(struct urb *u
+@@ -1751,7 +1838,7 @@ static void check_trb_math(struct urb *u
}
static void giveback_first_trb(struct xhci_hcd *xhci, int slot_id,
@@ -542,7 +542,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
struct xhci_generic_trb *start_trb, struct xhci_td *td)
{
/*
-@@ -1743,7 +1830,7 @@ static void giveback_first_trb(struct xh
+@@ -1760,7 +1847,7 @@ static void giveback_first_trb(struct xh
*/
wmb();
start_trb->field[3] |= start_cycle;
@@ -551,7 +551,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
}
/*
-@@ -1817,12 +1904,16 @@ static int queue_bulk_sg_tx(struct xhci_
+@@ -1834,12 +1921,16 @@ static int queue_bulk_sg_tx(struct xhci_
struct xhci_generic_trb *start_trb;
int start_cycle;
@@ -570,7 +570,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
if (trb_buff_len < 0)
return trb_buff_len;
/*
-@@ -1931,7 +2022,8 @@ static int queue_bulk_sg_tx(struct xhci_
+@@ -1948,7 +2039,8 @@ static int queue_bulk_sg_tx(struct xhci_
} while (running_total < urb->transfer_buffer_length);
check_trb_math(urb, num_trbs, running_total);
@@ -580,7 +580,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
return 0;
}
-@@ -1953,7 +2045,9 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+@@ -1970,7 +2062,9 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
if (urb->num_sgs)
return queue_bulk_sg_tx(xhci, mem_flags, urb, slot_id, ep_index);
@@ -591,7 +591,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
num_trbs = 0;
/* How much data is (potentially) left before the 64KB boundary? */
-@@ -1980,7 +2074,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+@@ -1997,7 +2091,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
(unsigned long long)urb->transfer_dma,
num_trbs);
@@ -601,7 +601,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
num_trbs, urb, &td, mem_flags);
if (ret < 0)
return ret;
-@@ -2050,7 +2145,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+@@ -2067,7 +2162,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
} while (running_total < urb->transfer_buffer_length);
check_trb_math(urb, num_trbs, running_total);
@@ -611,7 +611,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
return 0;
}
-@@ -2067,7 +2163,9 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
+@@ -2084,7 +2180,9 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
u32 field, length_field;
struct xhci_td *td;
@@ -622,7 +622,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
/*
* Need to copy setup packet into setup TRB, so we can't use the setup
-@@ -2088,8 +2186,9 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
+@@ -2105,8 +2203,9 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
*/
if (urb->transfer_buffer_length > 0)
num_trbs++;
@@ -634,7 +634,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
if (ret < 0)
return ret;
-@@ -2144,7 +2243,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
+@@ -2161,7 +2260,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
/* Event on completion */
field | TRB_IOC | TRB_TYPE(TRB_STATUS) | ep_ring->cycle_state);
@@ -644,7 +644,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
return 0;
}
-@@ -2256,12 +2356,14 @@ int xhci_queue_stop_endpoint(struct xhci
+@@ -2273,12 +2373,14 @@ int xhci_queue_stop_endpoint(struct xhci
* This should not be used for endpoints that have streams enabled.
*/
static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
@@ -660,7 +660,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
u32 type = TRB_TYPE(TRB_SET_DEQ);
addr = xhci_trb_virt_to_dma(deq_seg, deq_ptr);
-@@ -2272,7 +2374,7 @@ static int queue_set_tr_deq(struct xhci_
+@@ -2289,7 +2391,7 @@ static int queue_set_tr_deq(struct xhci_
return 0;
}
return queue_command(xhci, lower_32_bits(addr) | cycle_state,
diff --git a/usb/usb-xhci-fix-check-for-room-on-the-ring.patch b/usb/usb-xhci-fix-check-for-room-on-the-ring.patch
new file mode 100644
index 00000000000000..096f3c94f33557
--- /dev/null
+++ b/usb/usb-xhci-fix-check-for-room-on-the-ring.patch
@@ -0,0 +1,66 @@
+From sarah.a.sharp@linux.intel.com Thu May 20 10:48:52 2010
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Tue, 18 May 2010 16:05:26 -0700
+Subject: USB: xhci: Fix check for room on the ring.
+To: Greg KH <gregkh@suse.de>
+Cc: John Youn <John.Youn@synopsys.com>, linux-usb@vger.kernel.org
+Message-ID: <20100518230526.GA6092@xanatos>
+Content-Disposition: inline
+
+
+The length of the scatter gather list a driver can enqueue is limited by
+the bus' sg_tablesize to 62 entries. Each entry will be described by at
+least one transfer request block (TRB). If the entry's buffer crosses a
+64KB boundary, then that entry will have to be described by two or more
+TRBs. So even if the USB device driver respects sg_tablesize, the whole
+scatter list may take more than 62 TRBs to describe, and won't fit on
+the ring.
+
+Don't assume that an empty ring means there is enough room on the
+transfer ring. The old code would unconditionally queue this too-large
+transfer, and over write the beginning of the transfer. This would mean
+the cycle bit was unchanged in those overwritten transfers, causing the
+hardware to think it didn't own the TRBs, and the host would seem to
+hang.
+
+Now drivers may see submit_urb() fail with -ENOMEM if the transfers are
+too big to fit on the ring.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -242,10 +242,27 @@ static int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring,
+ int i;
+ union xhci_trb *enq = ring->enqueue;
+ struct xhci_segment *enq_seg = ring->enq_seg;
++ struct xhci_segment *cur_seg;
++ unsigned int left_on_ring;
+
+ /* Check if ring is empty */
+- if (enq == ring->dequeue)
++ if (enq == ring->dequeue) {
++ /* Can't use link trbs */
++ left_on_ring = TRBS_PER_SEGMENT - 1;
++ for (cur_seg = enq_seg->next; cur_seg != enq_seg;
++ cur_seg = cur_seg->next)
++ left_on_ring += TRBS_PER_SEGMENT - 1;
++
++ /* Always need one TRB free in the ring. */
++ left_on_ring -= 1;
++ if (num_trbs > left_on_ring) {
++ xhci_warn(xhci, "Not enough room on ring; "
++ "need %u TRBs, %u TRBs left\n",
++ num_trbs, left_on_ring);
++ return 0;
++ }
+ return 1;
++ }
+ /* Make sure there's an extra empty TRB available */
+ for (i = 0; i <= num_trbs; ++i) {
+ if (enq == ring->dequeue)
+--
+1.6.3.3
+
diff --git a/usb/usb-xhci-fix-compiler-warning.patch b/usb/usb-xhci-fix-compiler-warning.patch
index 869d4e16460771..30a22e21f59830 100644
--- a/usb/usb-xhci-fix-compiler-warning.patch
+++ b/usb/usb-xhci-fix-compiler-warning.patch
@@ -14,7 +14,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
-@@ -1726,7 +1726,6 @@ static int prepare_ring(struct xhci_hcd
+@@ -1743,7 +1743,6 @@ static int prepare_ring(struct xhci_hcd
if (enqueue_is_link_trb(ep_ring)) {
struct xhci_ring *ring = ep_ring;
union xhci_trb *next;
diff --git a/usb/usb-xhci-fix-wrong-usage-of-macro-trb_type.patch b/usb/usb-xhci-fix-wrong-usage-of-macro-trb_type.patch
index 4e7dd916de1bb7..3a6ac0d146da24 100644
--- a/usb/usb-xhci-fix-wrong-usage-of-macro-trb_type.patch
+++ b/usb/usb-xhci-fix-wrong-usage-of-macro-trb_type.patch
@@ -22,7 +22,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
-@@ -373,7 +373,8 @@ static struct xhci_segment *find_trb_seg
+@@ -390,7 +390,8 @@ static struct xhci_segment *find_trb_seg
while (cur_seg->trbs > trb ||
&cur_seg->trbs[TRBS_PER_SEGMENT - 1] < trb) {
generic_trb = &cur_seg->trbs[TRBS_PER_SEGMENT - 1].generic;
@@ -32,7 +32,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
(generic_trb->field[3] & LINK_TOGGLE))
*cycle_state = ~(*cycle_state) & 0x1;
cur_seg = cur_seg->next;
-@@ -438,7 +439,7 @@ void xhci_find_new_dequeue_state(struct
+@@ -455,7 +456,7 @@ void xhci_find_new_dequeue_state(struct
BUG();
trb = &state->new_deq_ptr->generic;
@@ -41,7 +41,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
(trb->field[3] & LINK_TOGGLE))
state->new_cycle_state = ~(state->new_cycle_state) & 0x1;
next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr);
-@@ -1487,8 +1488,10 @@ static int handle_tx_event(struct xhci_h
+@@ -1504,8 +1505,10 @@ static int handle_tx_event(struct xhci_h
for (cur_trb = ep_ring->dequeue, cur_seg = ep_ring->deq_seg;
cur_trb != event_trb;
next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) {
diff --git a/usb/usb-xhci-limit-bus-sg_tablesize-to-62-trbs.patch b/usb/usb-xhci-limit-bus-sg_tablesize-to-62-trbs.patch
new file mode 100644
index 00000000000000..591281de20fb36
--- /dev/null
+++ b/usb/usb-xhci-limit-bus-sg_tablesize-to-62-trbs.patch
@@ -0,0 +1,36 @@
+From sarah.a.sharp@linux.intel.com Thu May 20 10:48:18 2010
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Tue, 18 May 2010 16:05:21 -0700
+Subject: USB: xhci: Limit bus sg_tablesize to 62 TRBs.
+To: Greg KH <gregkh@suse.de>
+Cc: John Youn <John.Youn@synopsys.com>, linux-usb@vger.kernel.org
+Message-ID: <20100518230521.GA6036@xanatos>
+Content-Disposition: inline
+
+
+When a scatter-gather list is enqueued to the xHCI driver, it translates
+each entry into a transfer request block (TRB). Only 63 TRBs can be
+used per ring segment, and there must be one additional TRB reserved to
+make sure the hardware does not think the ring is empty (so the enqueue
+pointer doesn't equal the dequeue pointer). Limit the bus sg_tablesize
+to 62 TRBs.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-pci.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -54,7 +54,7 @@ static int xhci_pci_setup(struct usb_hcd
+ struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+ int retval;
+
+- hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 1;
++ hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 2;
+
+ xhci->cap_regs = hcd->regs;
+ xhci->op_regs = hcd->regs +
diff --git a/usb/usb-xhci-set-stream-id-to-0-after-cleaning-up-stalls.patch b/usb/usb-xhci-set-stream-id-to-0-after-cleaning-up-stalls.patch
index be411d6ec60c92..ada1085f7f3862 100644
--- a/usb/usb-xhci-set-stream-id-to-0-after-cleaning-up-stalls.patch
+++ b/usb/usb-xhci-set-stream-id-to-0-after-cleaning-up-stalls.patch
@@ -21,7 +21,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
-@@ -1149,6 +1149,7 @@ static void xhci_cleanup_halted_endpoint
+@@ -1166,6 +1166,7 @@ static void xhci_cleanup_halted_endpoint
ep->stopped_td = NULL;
ep->stopped_trb = NULL;
diff --git a/usb/usb-xhci-transfer-ring-link-trb-activation-change.patch b/usb/usb-xhci-transfer-ring-link-trb-activation-change.patch
index d780c67e5b4663..37aaecf4cbb95e 100644
--- a/usb/usb-xhci-transfer-ring-link-trb-activation-change.patch
+++ b/usb/usb-xhci-transfer-ring-link-trb-activation-change.patch
@@ -65,9 +65,9 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
}
/* Toggle the cycle bit after the last ring segment. */
if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {
-@@ -243,6 +244,13 @@ static int room_on_ring(struct xhci_hcd
- union xhci_trb *enq = ring->enqueue;
- struct xhci_segment *enq_seg = ring->enq_seg;
+@@ -245,6 +246,13 @@ static int room_on_ring(struct xhci_hcd
+ struct xhci_segment *cur_seg;
+ unsigned int left_on_ring;
+ /* If we are currently pointing to a link TRB, advance the
+ * enqueue pointer before checking for space */
@@ -77,9 +77,9 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ }
+
/* Check if ring is empty */
- if (enq == ring->dequeue)
- return 1;
-@@ -1711,6 +1719,43 @@ static int prepare_ring(struct xhci_hcd
+ if (enq == ring->dequeue) {
+ /* Can't use link trbs */
+@@ -1728,6 +1736,43 @@ static int prepare_ring(struct xhci_hcd
xhci_err(xhci, "ERROR no room on ep ring\n");
return -ENOMEM;
}
diff --git a/usb/xhci-add-memory-allocation-for-usb3-bulk-streams.patch b/usb/xhci-add-memory-allocation-for-usb3-bulk-streams.patch
index 3b2cf069071721..6043170def5b43 100644
--- a/usb/xhci-add-memory-allocation-for-usb3-bulk-streams.patch
+++ b/usb/xhci-add-memory-allocation-for-usb3-bulk-streams.patch
@@ -488,7 +488,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
if (!xhci->cmd_ring)
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
-@@ -306,6 +306,10 @@ static void ring_ep_doorbell(struct xhci
+@@ -323,6 +323,10 @@ static void ring_ep_doorbell(struct xhci
ep_state = ep->ep_state;
/* Don't ring the doorbell for this endpoint if there are pending
* cancellations because the we don't want to interrupt processing.
@@ -499,7 +499,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
*/
if (!(ep_state & EP_HALT_PENDING) && !(ep_state & SET_DEQ_PENDING)
&& !(ep_state & EP_HALTED)) {
-@@ -899,8 +903,9 @@ static void handle_cmd_completion(struct
+@@ -916,8 +920,9 @@ static void handle_cmd_completion(struct
* Configure endpoint commands can come from the USB core
* configuration or alt setting changes, or because the HW
* needed an extra configure endpoint command after a reset