diff options
29 files changed, 3850 insertions, 5 deletions
diff --git a/driver-core/fw_loader-fix-kconfig-dependency-warning-on-hotplug.patch b/driver-core/fw_loader-fix-kconfig-dependency-warning-on-hotplug.patch new file mode 100644 index 00000000000000..e820c63dfdf8a7 --- /dev/null +++ b/driver-core/fw_loader-fix-kconfig-dependency-warning-on-hotplug.patch @@ -0,0 +1,41 @@ +From randy.dunlap@oracle.com Tue Sep 21 15:25:06 2010 +Date: Sat, 18 Sep 2010 13:23:08 -0700 +From: Randy Dunlap <randy.dunlap@oracle.com> +Cc: gregkh@suse.de, akpm <akpm@linux-foundation.org> +Subject: FW_LOADER: fix kconfig dependency warning on HOTPLUG +Message-Id: <20100918132308.074b6c01.randy.dunlap@oracle.com> + +From: Randy Dunlap <randy.dunlap@oracle.com> + +Fix kconfig dependency warning for FW_LOADER. + +Lots of drivers select FW_LOADER without bothering to depend on +HOTPLUG and/or without selecting HOTPLUG. A kernel builds fine +when FW_LOADER is enabled, whether HOTPLUG is enabled or not, and +a kernel config file (make oldconfig) is not changed by this patch. +(Yes, drivers/base/firmware_class.c uses interfaces from linux/kobject.h, +which does have some CONFIG_HOTPLUG dependencies, but this patch does +not change that.) + +warning: (MICROCODE || MICROCODE_INTEL && MICROCODE || MICROCODE_AMD && MICROCODE || PCMCIA_LOAD_CIS && PCCARD && PCMCIA && EXPERIMENTAL || USB_IRDA && NET && IRDA && USB || BT_HCIBCM203X && NET && BT && USB || BT_HCIBFUSB && NET && BT && USB || BT_HCIBT3C && NET && BT && PCMCIA || BT_MRVL_SDIO && NET +... +!STAGING_EXCLUDE_BUILD && USB && (X86 || ARM) && WLAN || DRM_NOUVEAU && STAGING && !STAGING_EXCLUDE_BUILD && DRM && PCI || TI_ST && STAGING && !STAGING_EXCLUDE_BUILD && RFKILL || DELL_RBU && X86) selects FW_LOADER which has unmet direct dependencies (HOTPLUG) +(5200 byte line reduced a lot) + +Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/base/Kconfig | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/base/Kconfig ++++ b/drivers/base/Kconfig +@@ -71,7 +71,6 @@ config PREVENT_FIRMWARE_BUILD + + config FW_LOADER + tristate "Userspace firmware loading support" if EMBEDDED +- depends on HOTPLUG + default y + ---help--- + This option is provided for the case where no in-kernel-tree modules diff --git a/driver-core/sysfs-fail-bin-file-mmap-if-vma-close-is-implemented.patch b/driver-core/sysfs-fail-bin-file-mmap-if-vma-close-is-implemented.patch new file mode 100644 index 00000000000000..c196c2d32bd82c --- /dev/null +++ b/driver-core/sysfs-fail-bin-file-mmap-if-vma-close-is-implemented.patch @@ -0,0 +1,73 @@ +From ebiederm@xmission.com Tue Sep 21 15:25:56 2010 +From: Eric W. Biederman <ebiederm@aristanetworks.com> +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: Tejun Heo <tj@kernel.org>, Hugh Dickins <hughd@google.com> +Date: Mon, 20 Sep 2010 00:56:27 -0700 +Message-ID: <m1zkvc26hg.fsf@fess.ebiederm.org> +Subject: sysfs: Fail bin file mmap if vma close is implemented. + +From: Eric W. Biederman <ebiederm@aristanetworks.com> + +It is not reasonably possible to wrap vma->close(). To correctly +wrap close would imply calling close on any vmas that remain when +sysfs_remove_bin_file is called. Finding the proper lists walking +them getting the locking right etc, requires deep knowledge of the +mm subsystem and as such would require assistence from the mm +subsystem to implement. That assistence does not currently exist. + +Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + fs/sysfs/bin.c | 26 ++++++++------------------ + 1 file changed, 8 insertions(+), 18 deletions(-) + +--- a/fs/sysfs/bin.c ++++ b/fs/sysfs/bin.c +@@ -190,23 +190,6 @@ static void bin_vma_open(struct vm_area_ + sysfs_put_active(attr_sd); + } + +-static void bin_vma_close(struct vm_area_struct *vma) +-{ +- struct file *file = vma->vm_file; +- struct bin_buffer *bb = file->private_data; +- struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; +- +- if (!bb->vm_ops || !bb->vm_ops->close) +- return; +- +- if (!sysfs_get_active(attr_sd)) +- return; +- +- bb->vm_ops->close(vma); +- +- sysfs_put_active(attr_sd); +-} +- + static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf) + { + struct file *file = vma->vm_file; +@@ -331,7 +314,6 @@ static int bin_migrate(struct vm_area_st + + static const struct vm_operations_struct bin_vm_ops = { + .open = bin_vma_open, +- .close = bin_vma_close, + .fault = bin_fault, + .page_mkwrite = bin_page_mkwrite, + .access = bin_access, +@@ -377,6 +359,14 @@ static int mmap(struct file *file, struc + if (bb->mmapped && bb->vm_ops != vma->vm_ops) + goto out_put; + ++ /* ++ * It is not possible to successfully wrap close. ++ * So error if someone is trying to use close. ++ */ ++ rc = -EINVAL; ++ if (vma->vm_ops && vma->vm_ops->close) ++ goto out_put; ++ + rc = 0; + bb->mmapped = 1; + bb->vm_ops = vma->vm_ops; diff --git a/driver-core/sysfs-only-access-bin-file-vm_ops-with-the-active-lock.patch b/driver-core/sysfs-only-access-bin-file-vm_ops-with-the-active-lock.patch new file mode 100644 index 00000000000000..c96a61bca3ffb2 --- /dev/null +++ b/driver-core/sysfs-only-access-bin-file-vm_ops-with-the-active-lock.patch @@ -0,0 +1,150 @@ +From ebiederm@xmission.com Tue Sep 21 15:26:49 2010 +From: Eric W. Biederman <ebiederm@aristanetworks.com> +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: Tejun Heo <tj@kernel.org>, Hugh Dickins <hughd@google.com> +Date: Mon, 20 Sep 2010 00:57:03 -0700 +Message-ID: <m1vd6026gg.fsf@fess.ebiederm.org> +Subject: sysfs: only access bin file vm_ops with the active lock + +From: Eric W. Biederman <ebiederm@aristanetworks.com> + +bb->vm_ops is a cached copy of the vm_ops of the underlying +sysfs bin file, which means that after sysfs_bin_remove_file +completes it is only longer valid to deference bb->vm_ops. + +So move all of the tests of bb->vm_ops inside of where +we hold the sysfs active lock. + +Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + fs/sysfs/bin.c | 42 ++++++++++++++++++++++++++---------------- + 1 file changed, 26 insertions(+), 16 deletions(-) + +--- a/fs/sysfs/bin.c ++++ b/fs/sysfs/bin.c +@@ -179,13 +179,14 @@ static void bin_vma_open(struct vm_area_ + struct bin_buffer *bb = file->private_data; + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; + +- if (!bb->vm_ops || !bb->vm_ops->open) ++ if (!bb->vm_ops) + return; + + if (!sysfs_get_active(attr_sd)) + return; + +- bb->vm_ops->open(vma); ++ if (bb->vm_ops->open) ++ bb->vm_ops->open(vma); + + sysfs_put_active(attr_sd); + } +@@ -197,13 +198,15 @@ static int bin_fault(struct vm_area_stru + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; + int ret; + +- if (!bb->vm_ops || !bb->vm_ops->fault) ++ if (!bb->vm_ops) + return VM_FAULT_SIGBUS; + + if (!sysfs_get_active(attr_sd)) + return VM_FAULT_SIGBUS; + +- ret = bb->vm_ops->fault(vma, vmf); ++ ret = VM_FAULT_SIGBUS; ++ if (bb->vm_ops->fault) ++ ret = bb->vm_ops->fault(vma, vmf); + + sysfs_put_active(attr_sd); + return ret; +@@ -219,13 +222,12 @@ static int bin_page_mkwrite(struct vm_ar + if (!bb->vm_ops) + return VM_FAULT_SIGBUS; + +- if (!bb->vm_ops->page_mkwrite) +- return 0; +- + if (!sysfs_get_active(attr_sd)) + return VM_FAULT_SIGBUS; + +- ret = bb->vm_ops->page_mkwrite(vma, vmf); ++ ret = 0; ++ if (bb->vm_ops->page_mkwrite) ++ ret = bb->vm_ops->page_mkwrite(vma, vmf); + + sysfs_put_active(attr_sd); + return ret; +@@ -239,13 +241,15 @@ static int bin_access(struct vm_area_str + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; + int ret; + +- if (!bb->vm_ops || !bb->vm_ops->access) ++ if (!bb->vm_ops) + return -EINVAL; + + if (!sysfs_get_active(attr_sd)) + return -EINVAL; + +- ret = bb->vm_ops->access(vma, addr, buf, len, write); ++ ret = -EINVAL; ++ if (bb->vm_ops->access) ++ ret = bb->vm_ops->access(vma, addr, buf, len, write); + + sysfs_put_active(attr_sd); + return ret; +@@ -259,13 +263,15 @@ static int bin_set_policy(struct vm_area + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; + int ret; + +- if (!bb->vm_ops || !bb->vm_ops->set_policy) ++ if (!bb->vm_ops) + return 0; + + if (!sysfs_get_active(attr_sd)) + return -EINVAL; + +- ret = bb->vm_ops->set_policy(vma, new); ++ ret = 0; ++ if (bb->vm_ops->set_policy) ++ ret = bb->vm_ops->set_policy(vma, new); + + sysfs_put_active(attr_sd); + return ret; +@@ -279,13 +285,15 @@ static struct mempolicy *bin_get_policy( + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; + struct mempolicy *pol; + +- if (!bb->vm_ops || !bb->vm_ops->get_policy) ++ if (!bb->vm_ops) + return vma->vm_policy; + + if (!sysfs_get_active(attr_sd)) + return vma->vm_policy; + +- pol = bb->vm_ops->get_policy(vma, addr); ++ pol = vma->vm_policy; ++ if (bb->vm_ops->get_policy) ++ pol = bb->vm_ops->get_policy(vma, addr); + + sysfs_put_active(attr_sd); + return pol; +@@ -299,13 +307,15 @@ static int bin_migrate(struct vm_area_st + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; + int ret; + +- if (!bb->vm_ops || !bb->vm_ops->migrate) ++ if (!bb->vm_ops) + return 0; + + if (!sysfs_get_active(attr_sd)) + return 0; + +- ret = bb->vm_ops->migrate(vma, from, to, flags); ++ ret = 0; ++ if (bb->vm_ops->migrate) ++ ret = bb->vm_ops->migrate(vma, from, to, flags); + + sysfs_put_active(attr_sd); + return ret; diff --git a/driver-core/uio-cleanup-irq-handling.patch b/driver-core/uio-cleanup-irq-handling.patch new file mode 100644 index 00000000000000..3647e62e92358c --- /dev/null +++ b/driver-core/uio-cleanup-irq-handling.patch @@ -0,0 +1,88 @@ +From ebiederm@xmission.com Tue Sep 21 14:05:10 2010 +From: Eric W. Biederman <ebiederm@aristanetworks.com> +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: "Hans J. Koch" <hjk@linutronix.de> +Date: Tue, 14 Sep 2010 11:37:36 -0700 +Message-ID: <m1k4mo893j.fsf@fess.ebiederm.org> +Subject: uio: Cleanup irq handling. + + +Change the value of UIO_IRQ_NONE -2 to 0. 0 is well defined in the rest +of the kernel as the value to indicate an irq has not been assigned. + +Update the calls to request_irq and free_irq to only ignore UIO_IRQ_NONE +and UIO_IRQ_CUSTOM allowing the rest of the kernel's possible irq +numbers to be used. + +Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com> +Reviewed-by: Thomas Gleixner <tglx@linutronix.de> +Signed-off-by: Hans J. Koch <hjk@linutronix.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/uio/uio.c | 14 +++++++------- + include/linux/uio_driver.h | 2 +- + 2 files changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/uio/uio.c ++++ b/drivers/uio/uio.c +@@ -512,7 +512,7 @@ static unsigned int uio_poll(struct file + struct uio_listener *listener = filep->private_data; + struct uio_device *idev = listener->dev; + +- if (idev->info->irq == UIO_IRQ_NONE) ++ if (!idev->info->irq) + return -EIO; + + poll_wait(filep, &idev->wait, wait); +@@ -530,7 +530,7 @@ static ssize_t uio_read(struct file *fil + ssize_t retval; + s32 event_count; + +- if (idev->info->irq == UIO_IRQ_NONE) ++ if (!idev->info->irq) + return -EIO; + + if (count != sizeof(s32)) +@@ -578,7 +578,7 @@ static ssize_t uio_write(struct file *fi + ssize_t retval; + s32 irq_on; + +- if (idev->info->irq == UIO_IRQ_NONE) ++ if (!idev->info->irq) + return -EIO; + + if (count != sizeof(s32)) +@@ -825,9 +825,9 @@ int __uio_register_device(struct module + + info->uio_dev = idev; + +- if (idev->info->irq >= 0) { +- ret = request_irq(idev->info->irq, uio_interrupt, +- idev->info->irq_flags, idev->info->name, idev); ++ if (info->irq && (info->irq != UIO_IRQ_CUSTOM)) { ++ ret = request_irq(info->irq, uio_interrupt, ++ info->irq_flags, info->name, idev); + if (ret) + goto err_request_irq; + } +@@ -863,7 +863,7 @@ void uio_unregister_device(struct uio_in + + uio_free_minor(idev); + +- if (info->irq >= 0) ++ if (info->irq && (info->irq != UIO_IRQ_CUSTOM)) + free_irq(info->irq, idev); + + uio_dev_del_attributes(idev); +--- a/include/linux/uio_driver.h ++++ b/include/linux/uio_driver.h +@@ -108,7 +108,7 @@ extern void uio_event_notify(struct uio_ + + /* defines for uio_info->irq */ + #define UIO_IRQ_CUSTOM -1 +-#define UIO_IRQ_NONE -2 ++#define UIO_IRQ_NONE 0 + + /* defines for uio_mem->memtype */ + #define UIO_MEM_NONE 0 diff --git a/driver-core/uio-don-t-clear-driver-data.patch b/driver-core/uio-don-t-clear-driver-data.patch new file mode 100644 index 00000000000000..2ef7e82f4ee00c --- /dev/null +++ b/driver-core/uio-don-t-clear-driver-data.patch @@ -0,0 +1,70 @@ +From ebiederm@xmission.com Tue Sep 21 14:04:50 2010 +From: Eric W. Biederman <ebiederm@aristanetworks.com> +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: "Hans J. Koch" <hjk@linutronix.de> +Date: Tue, 14 Sep 2010 11:36:54 -0700 +Message-ID: <m1occ0894p.fsf@fess.ebiederm.org> +Subject: uio: Don't clear driver data + + +Currently uio sets it's driver data to NULL just as it is unregistering +attributes. sysfs maks the guaranatee that it will not call attributes +after device_destroy is called so this is unncessary and leads to lots +of unnecessary code in uio.c + +Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com> +Reviewed-by: Thomas Gleixner <tglx@linutronix.de> +Signed-off-by: Hans J. Koch <hjk@linutronix.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/uio/uio.c | 17 +++-------------- + 1 file changed, 3 insertions(+), 14 deletions(-) + +--- a/drivers/uio/uio.c ++++ b/drivers/uio/uio.c +@@ -229,10 +229,7 @@ static ssize_t show_name(struct device * + struct device_attribute *attr, char *buf) + { + struct uio_device *idev = dev_get_drvdata(dev); +- if (idev) +- return sprintf(buf, "%s\n", idev->info->name); +- else +- return -ENODEV; ++ return sprintf(buf, "%s\n", idev->info->name); + } + static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + +@@ -240,10 +237,7 @@ static ssize_t show_version(struct devic + struct device_attribute *attr, char *buf) + { + struct uio_device *idev = dev_get_drvdata(dev); +- if (idev) +- return sprintf(buf, "%s\n", idev->info->version); +- else +- return -ENODEV; ++ return sprintf(buf, "%s\n", idev->info->version); + } + static DEVICE_ATTR(version, S_IRUGO, show_version, NULL); + +@@ -251,11 +245,7 @@ static ssize_t show_event(struct device + struct device_attribute *attr, char *buf) + { + struct uio_device *idev = dev_get_drvdata(dev); +- if (idev) +- return sprintf(buf, "%u\n", +- (unsigned int)atomic_read(&idev->event)); +- else +- return -ENODEV; ++ return sprintf(buf, "%u\n", (unsigned int)atomic_read(&idev->event)); + } + static DEVICE_ATTR(event, S_IRUGO, show_event, NULL); + +@@ -878,7 +868,6 @@ void uio_unregister_device(struct uio_in + + uio_dev_del_attributes(idev); + +- dev_set_drvdata(idev->dev, NULL); + device_destroy(uio_class, MKDEV(uio_major, idev->minor)); + kfree(idev); + diff --git a/driver-core/uio-fix-lack-of-locking-in-init_uio_class.patch b/driver-core/uio-fix-lack-of-locking-in-init_uio_class.patch new file mode 100644 index 00000000000000..4f1a808eb77156 --- /dev/null +++ b/driver-core/uio-fix-lack-of-locking-in-init_uio_class.patch @@ -0,0 +1,164 @@ +From ebiederm@xmission.com Tue Sep 21 14:04:18 2010 +From: Eric W. Biederman <ebiederm@aristanetworks.com> +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: "Hans J. Koch" <hjk@linutronix.de> +Date: Tue, 14 Sep 2010 11:36:27 -0700 +Message-ID: <m1sk1c895g.fsf@fess.ebiederm.org> +Subject: uio: Fix lack of locking in init_uio_class + + +There is no locking in init_uio_class so multiple +drivers can race and create multiple uio classes. + +Fix this by simplifying the code. In particular always +register the uio class during module_init and make things +simpler. + +Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com> +Reviewed-by: Thomas Gleixner <tglx@linutronix.de> +Signed-off-by: Hans J. Koch <hjk@linutronix.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/uio/uio.c | 58 +++++++++++++----------------------------------------- + 1 file changed, 15 insertions(+), 43 deletions(-) + +--- a/drivers/uio/uio.c ++++ b/drivers/uio/uio.c +@@ -45,10 +45,7 @@ static DEFINE_IDR(uio_idr); + static const struct file_operations uio_fops; + + /* UIO class infrastructure */ +-static struct uio_class { +- struct kref kref; +- struct class *class; +-} *uio_class; ++static struct class *uio_class; + + /* Protect idr accesses */ + static DEFINE_MUTEX(minor_lock); +@@ -757,55 +754,35 @@ static void uio_major_cleanup(void) + + static int init_uio_class(void) + { +- int ret = 0; +- +- if (uio_class != NULL) { +- kref_get(&uio_class->kref); +- goto exit; +- } ++ struct class *class; ++ int ret; + + /* This is the first time in here, set everything up properly */ + ret = uio_major_init(); + if (ret) + goto exit; + +- uio_class = kzalloc(sizeof(*uio_class), GFP_KERNEL); +- if (!uio_class) { +- ret = -ENOMEM; +- goto err_kzalloc; +- } +- +- kref_init(&uio_class->kref); +- uio_class->class = class_create(THIS_MODULE, "uio"); +- if (IS_ERR(uio_class->class)) { +- ret = IS_ERR(uio_class->class); ++ class = class_create(THIS_MODULE, "uio"); ++ if (IS_ERR(class)) { ++ ret = IS_ERR(class); + printk(KERN_ERR "class_create failed for uio\n"); + goto err_class_create; + } ++ uio_class = class; + return 0; + + err_class_create: +- kfree(uio_class); +- uio_class = NULL; +-err_kzalloc: + uio_major_cleanup(); + exit: + return ret; + } + +-static void release_uio_class(struct kref *kref) ++static void release_uio_class(void) + { + /* Ok, we cheat as we know we only have one uio_class */ +- class_destroy(uio_class->class); +- kfree(uio_class); +- uio_major_cleanup(); ++ class_destroy(uio_class); + uio_class = NULL; +-} +- +-static void uio_class_destroy(void) +-{ +- if (uio_class) +- kref_put(&uio_class->kref, release_uio_class); ++ uio_major_cleanup(); + } + + /** +@@ -828,10 +805,6 @@ int __uio_register_device(struct module + + info->uio_dev = NULL; + +- ret = init_uio_class(); +- if (ret) +- return ret; +- + idev = kzalloc(sizeof(*idev), GFP_KERNEL); + if (!idev) { + ret = -ENOMEM; +@@ -847,7 +820,7 @@ int __uio_register_device(struct module + if (ret) + goto err_get_minor; + +- idev->dev = device_create(uio_class->class, parent, ++ idev->dev = device_create(uio_class, parent, + MKDEV(uio_major, idev->minor), idev, + "uio%d", idev->minor); + if (IS_ERR(idev->dev)) { +@@ -874,13 +847,12 @@ int __uio_register_device(struct module + err_request_irq: + uio_dev_del_attributes(idev); + err_uio_dev_add_attributes: +- device_destroy(uio_class->class, MKDEV(uio_major, idev->minor)); ++ device_destroy(uio_class, MKDEV(uio_major, idev->minor)); + err_device_create: + uio_free_minor(idev); + err_get_minor: + kfree(idev); + err_kzalloc: +- uio_class_destroy(); + return ret; + } + EXPORT_SYMBOL_GPL(__uio_register_device); +@@ -907,9 +879,8 @@ void uio_unregister_device(struct uio_in + uio_dev_del_attributes(idev); + + dev_set_drvdata(idev->dev, NULL); +- device_destroy(uio_class->class, MKDEV(uio_major, idev->minor)); ++ device_destroy(uio_class, MKDEV(uio_major, idev->minor)); + kfree(idev); +- uio_class_destroy(); + + return; + } +@@ -917,11 +888,12 @@ EXPORT_SYMBOL_GPL(uio_unregister_device) + + static int __init uio_init(void) + { +- return 0; ++ return init_uio_class(); + } + + static void __exit uio_exit(void) + { ++ release_uio_class(); + } + + module_init(uio_init) diff --git a/driver-core/uio-statically-allocate-uio_class-and-use-class-.dev_attrs.patch b/driver-core/uio-statically-allocate-uio_class-and-use-class-.dev_attrs.patch new file mode 100644 index 00000000000000..220113a1365a6f --- /dev/null +++ b/driver-core/uio-statically-allocate-uio_class-and-use-class-.dev_attrs.patch @@ -0,0 +1,178 @@ +From ebiederm@xmission.com Tue Sep 21 14:08:44 2010 +From: Eric W. Biederman <ebiederm@aristanetworks.com> +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: "Hans J. Koch" <hjk@linutronix.de> +Date: Tue, 14 Sep 2010 11:38:36 -0700 +Message-ID: <m18w34891v.fsf@fess.ebiederm.org> +Subject: uio: Statically allocate uio_class and use class .dev_attrs. + + +Instead of adding uio class attributes manually after the uio device has +been created and we have sent a uevent to userspace, use the class +attribute mechanism. This removes races and makes the code simpler. + +At the same time don't bother to dynamically allocate a struct class for +uio, just declare one statically. Less code is needed and it is easier +to set the class parameters.tune the class + +Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com> +Reviewed-by: Thomas Gleixner <tglx@linutronix.de> +Signed-off-by: Hans J. Koch <hjk@linutronix.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/uio/uio.c | 53 ++++++++++++++++++----------------------------------- + 1 file changed, 18 insertions(+), 35 deletions(-) + +--- a/drivers/uio/uio.c ++++ b/drivers/uio/uio.c +@@ -46,9 +46,6 @@ static struct cdev *uio_cdev; + static DEFINE_IDR(uio_idr); + static const struct file_operations uio_fops; + +-/* UIO class infrastructure */ +-static struct class *uio_class; +- + /* Protect idr accesses */ + static DEFINE_MUTEX(minor_lock); + +@@ -233,7 +230,6 @@ static ssize_t show_name(struct device * + struct uio_device *idev = dev_get_drvdata(dev); + return sprintf(buf, "%s\n", idev->info->name); + } +-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + + static ssize_t show_version(struct device *dev, + struct device_attribute *attr, char *buf) +@@ -241,7 +237,6 @@ static ssize_t show_version(struct devic + struct uio_device *idev = dev_get_drvdata(dev); + return sprintf(buf, "%s\n", idev->info->version); + } +-static DEVICE_ATTR(version, S_IRUGO, show_version, NULL); + + static ssize_t show_event(struct device *dev, + struct device_attribute *attr, char *buf) +@@ -249,17 +244,18 @@ static ssize_t show_event(struct device + struct uio_device *idev = dev_get_drvdata(dev); + return sprintf(buf, "%u\n", (unsigned int)atomic_read(&idev->event)); + } +-static DEVICE_ATTR(event, S_IRUGO, show_event, NULL); + +-static struct attribute *uio_attrs[] = { +- &dev_attr_name.attr, +- &dev_attr_version.attr, +- &dev_attr_event.attr, +- NULL, ++static struct device_attribute uio_class_attributes[] = { ++ __ATTR(name, S_IRUGO, show_name, NULL), ++ __ATTR(version, S_IRUGO, show_version, NULL), ++ __ATTR(event, S_IRUGO, show_event, NULL), ++ {} + }; + +-static struct attribute_group uio_attr_grp = { +- .attrs = uio_attrs, ++/* UIO class infrastructure */ ++static struct class uio_class = { ++ .name = "uio", ++ .dev_attrs = uio_class_attributes, + }; + + /* +@@ -276,10 +272,6 @@ static int uio_dev_add_attributes(struct + struct uio_port *port; + struct uio_portio *portio; + +- ret = sysfs_create_group(&idev->dev->kobj, &uio_attr_grp); +- if (ret) +- goto err_group; +- + for (mi = 0; mi < MAX_UIO_MAPS; mi++) { + mem = &idev->info->mem[mi]; + if (mem->size == 0) +@@ -347,8 +339,6 @@ err_map: + kobject_put(&map->kobj); + } + kobject_put(idev->map_dir); +- sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp); +-err_group: + dev_err(idev->dev, "error creating sysfs files (%d)\n", ret); + return ret; + } +@@ -374,8 +364,6 @@ static void uio_dev_del_attributes(struc + kobject_put(&port->portio->kobj); + } + kobject_put(idev->portio_dir); +- +- sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp); + } + + static int uio_get_minor(struct uio_device *idev) +@@ -775,7 +763,6 @@ static void uio_major_cleanup(void) + + static int init_uio_class(void) + { +- struct class *class; + int ret; + + /* This is the first time in here, set everything up properly */ +@@ -783,16 +770,14 @@ static int init_uio_class(void) + if (ret) + goto exit; + +- class = class_create(THIS_MODULE, "uio"); +- if (IS_ERR(class)) { +- ret = IS_ERR(class); +- printk(KERN_ERR "class_create failed for uio\n"); +- goto err_class_create; ++ ret = class_register(&uio_class); ++ if (ret) { ++ printk(KERN_ERR "class_register failed for uio\n"); ++ goto err_class_register; + } +- uio_class = class; + return 0; + +-err_class_create: ++err_class_register: + uio_major_cleanup(); + exit: + return ret; +@@ -800,9 +785,7 @@ exit: + + static void release_uio_class(void) + { +- /* Ok, we cheat as we know we only have one uio_class */ +- class_destroy(uio_class); +- uio_class = NULL; ++ class_unregister(&uio_class); + uio_major_cleanup(); + } + +@@ -841,7 +824,7 @@ int __uio_register_device(struct module + if (ret) + goto err_get_minor; + +- idev->dev = device_create(uio_class, parent, ++ idev->dev = device_create(&uio_class, parent, + MKDEV(uio_major, idev->minor), idev, + "uio%d", idev->minor); + if (IS_ERR(idev->dev)) { +@@ -868,7 +851,7 @@ int __uio_register_device(struct module + err_request_irq: + uio_dev_del_attributes(idev); + err_uio_dev_add_attributes: +- device_destroy(uio_class, MKDEV(uio_major, idev->minor)); ++ device_destroy(&uio_class, MKDEV(uio_major, idev->minor)); + err_device_create: + uio_free_minor(idev); + err_get_minor: +@@ -899,7 +882,7 @@ void uio_unregister_device(struct uio_in + + uio_dev_del_attributes(idev); + +- device_destroy(uio_class, MKDEV(uio_major, idev->minor)); ++ device_destroy(&uio_class, MKDEV(uio_major, idev->minor)); + kfree(idev); + + return; diff --git a/driver-core/uio-support-2-minor_bits-minors.patch b/driver-core/uio-support-2-minor_bits-minors.patch new file mode 100644 index 00000000000000..4f7b99d63e662a --- /dev/null +++ b/driver-core/uio-support-2-minor_bits-minors.patch @@ -0,0 +1,98 @@ +From ebiederm@xmission.com Tue Sep 21 14:06:15 2010 +From: Eric W. Biederman <ebiederm@aristanetworks.com> +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: "Hans J. Koch" <hjk@linutronix.de> +Date: Tue, 14 Sep 2010 11:38:06 -0700 +Message-ID: <m1eicw892p.fsf@fess.ebiederm.org> +Subject: uio: Support 2^MINOR_BITS minors + + +register_chrdev limits uio devices to 256 minor numbers which causes +problems on one system I have with 384+ uio devices. So instead set +UIO_MAX_DEVICES to the maximum number of minors and use +alloc_chrdev_region to reserve the uio minors. + +The final result is that the code works the same but the uio driver now +supports any minor the idr allocator comes up with. + +Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com> +Reviewed-by: Thomas Gleixner <tglx@linutronix.de> +Signed-off-by: Hans J. Koch <hjk@linutronix.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/uio/uio.c | 43 +++++++++++++++++++++++++++++++++++++------ + 1 file changed, 37 insertions(+), 6 deletions(-) + +--- a/drivers/uio/uio.c ++++ b/drivers/uio/uio.c +@@ -23,9 +23,10 @@ + #include <linux/sched.h> + #include <linux/string.h> + #include <linux/kobject.h> ++#include <linux/cdev.h> + #include <linux/uio_driver.h> + +-#define UIO_MAX_DEVICES 255 ++#define UIO_MAX_DEVICES (1U << MINORBITS) + + struct uio_device { + struct module *owner; +@@ -41,6 +42,7 @@ struct uio_device { + }; + + static int uio_major; ++static struct cdev *uio_cdev; + static DEFINE_IDR(uio_idr); + static const struct file_operations uio_fops; + +@@ -731,15 +733,44 @@ static const struct file_operations uio_ + + static int uio_major_init(void) + { +- uio_major = register_chrdev(0, "uio", &uio_fops); +- if (uio_major < 0) +- return uio_major; +- return 0; ++ static const char name[] = "uio"; ++ struct cdev *cdev = NULL; ++ dev_t uio_dev = 0; ++ int result; ++ ++ result = alloc_chrdev_region(&uio_dev, 0, UIO_MAX_DEVICES, name); ++ if (result) ++ goto out; ++ ++ result = -ENOMEM; ++ cdev = cdev_alloc(); ++ if (!cdev) ++ goto out_unregister; ++ ++ cdev->owner = THIS_MODULE; ++ cdev->ops = &uio_fops; ++ kobject_set_name(&cdev->kobj, "%s", name); ++ ++ result = cdev_add(cdev, uio_dev, UIO_MAX_DEVICES); ++ if (result) ++ goto out_put; ++ ++ uio_major = MAJOR(uio_dev); ++ uio_cdev = cdev; ++ result = 0; ++out: ++ return result; ++out_put: ++ kobject_put(&cdev->kobj); ++out_unregister: ++ unregister_chrdev_region(uio_dev, UIO_MAX_DEVICES); ++ goto out; + } + + static void uio_major_cleanup(void) + { +- unregister_chrdev(uio_major, "uio"); ++ unregister_chrdev_region(MKDEV(uio_major, 0), UIO_MAX_DEVICES); ++ cdev_del(uio_cdev); + } + + static int init_uio_class(void) @@ -19,6 +19,14 @@ gregkh/gkh-version.patch # USB patches for 2.6.36 ################################# usb.current/usb-fix-bug-in-initialization-of-interface-minor-numbers.patch +usb.current/usb-musb-gadget-fix-kernel-panic-if-using-out-ep-with-fifo_txrx-style.patch +usb.current/usb-musb-gadget-fix-bulk-in-infinit-hangs-in-double-buffer-case.patch +usb.current/usb-musb-gadget-enable-autoclear-for-out-transfer-in-both-dma-0-and-dma-1.patch +usb.current/usb-musb-gadget-fix-dma-length-for-out-transfer.patch +usb.current/usb-musb-gadget-complete-request-only-if-data-is-transfered-over.patch +usb.current/usb-musb-gadget-fix-dma-length-in-txstate.patch +usb.current/usb-musb-host-issue-a-memory-barrier-before-starting-dma.patch +usb.current/usb-musb-gadget-restart-request-on-clearing-endpoint-halt.patch ################################# @@ -50,6 +58,15 @@ driver-core/base-platform-simplifications-for-null-platform-data-resources-handl driver-core/driver-core-remove-config_sysfs_deprecated_v2-but-keep-it-for-block-devices.patch driver-core/sysfs-allow-boot-time-switching-between-deprecated-and-modern-sysfs-layout.patch +driver-core/uio-fix-lack-of-locking-in-init_uio_class.patch +driver-core/uio-don-t-clear-driver-data.patch +driver-core/uio-cleanup-irq-handling.patch +driver-core/uio-support-2-minor_bits-minors.patch +driver-core/uio-statically-allocate-uio_class-and-use-class-.dev_attrs.patch +driver-core/fw_loader-fix-kconfig-dependency-warning-on-hotplug.patch +driver-core/sysfs-fail-bin-file-mmap-if-vma-close-is-implemented.patch +driver-core/sysfs-only-access-bin-file-vm_ops-with-the-active-lock.patch + ##################################### # TTY patches for after 2.6.36 is out ##################################### @@ -76,11 +93,14 @@ tty/tty_io-check-return-code-of-tty_register_device.patch tty/serial-mrst_max3110-some-code-cleanup.patch tty/serial-mrst_max3110-make-the-irq-option-runtime.patch tty/serial-max3107-fix-memory-leaks-when-returning-on-error.patch - +tty/tty-make-tiocgicount-a-handler.patch +tty/tty-convert-the-usb-drivers-to-the-new-icount-interface.patch +tty/tty-icount-changeover-for-other-main-devices.patch ################################### # USB stuff for after 2.6.36 is out ################################### + usb/usb-add-intel-langwell-usb-otg-transceiver-driver.patch usb/usb-langwell-usb-client-driver-code-cleanup.patch usb/usb-langwell-usb-client-endpoint-initialization.patch @@ -127,9 +147,16 @@ usb/usb-teach-devices-file-about-wireless-and-superspeed-usb.patch usb/usb-host-oxu210hp-hcd-use-static-const-char-const-where-possible.patch usb/usb-ftdi_sio-add-pid-for-accesio-products.patch usb/usb-omap-ohci-missing-driver-unregister-in-module-exit.patch +usb/usb-cp210x-add-renesas-rx-stick-device-id.patch +usb/usb-option-add-new-onda-vendor-id-and-product-id-for-onda-mt825up.patch +usb/usb-cdc.h-ncm-typo-and-style-fixes.patch +usb/revert-usb-ncm-added-ncm.h-with-auxiliary-definitions.patch +usb/usb-cdc.h-ncm-add-missed-constants-and-structures.patch +usb/usb-atmel_usba_udc-force-vbus_pin-at-einval-when-gpio_request-failled.patch +usb/usb-serial-enable-usb-autosuspend-by-default-on-qcserial.patch +usb/usb-ftdi_sio-revert-usb-ftdi_sio-fix-dtr-rts-line-modes.patch # staging stuff for next is now in the staging-next tree on git.kernel.org - diff --git a/tty/tty-convert-the-usb-drivers-to-the-new-icount-interface.patch b/tty/tty-convert-the-usb-drivers-to-the-new-icount-interface.patch new file mode 100644 index 00000000000000..86ee1738dcc54b --- /dev/null +++ b/tty/tty-convert-the-usb-drivers-to-the-new-icount-interface.patch @@ -0,0 +1,654 @@ +From linux-kernel-owner@vger.kernel.org Tue Sep 21 14:30:42 2010 +From: Alan Cox <alan@linux.intel.com> +Subject: tty: Convert the USB drivers to the new icount interface +To: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, + greg@kroah.com, drosenberg@vsecurity.com +Date: Thu, 16 Sep 2010 18:21:40 +0100 +Message-ID: <20100916172131.25987.39706.stgit@localhost.localdomain> + +Simple pasting job using the new ops function. Also fix a couple of devices +directly returning the internal struct (which happens at this point to match +for the fields that matter but isn't correct or futureproof) + +Signed-off-by: Alan Cox <alan@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/net/usb/hso.c | 35 ++++++++++------------ + drivers/usb/serial/ark3116.c | 40 +++++++++++++------------ + drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/io_edgeport.c | 49 +++++++++++++++++------------- + drivers/usb/serial/io_tables.h | 4 ++ + drivers/usb/serial/io_ti.c | 29 +++++++++++++----- + drivers/usb/serial/mos7720.c | 54 ++++++++++++++++++---------------- + drivers/usb/serial/mos7840.c | 53 ++++++++++++++++++--------------- + drivers/usb/serial/ssu100.c | 46 +++++++++++++++------------- + drivers/usb/serial/ti_usb_3410_5052.c | 37 ++++++++++++++++++----- + 10 files changed, 203 insertions(+), 145 deletions(-) + +--- a/drivers/net/usb/hso.c ++++ b/drivers/net/usb/hso.c +@@ -1645,11 +1645,11 @@ hso_wait_modem_status(struct hso_serial + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ +-static int hso_get_count(struct hso_serial *serial, +- struct serial_icounter_struct __user *icnt) ++static int hso_get_count(struct tty_struct *tty, ++ struct serial_icounter_struct *icount) + { +- struct serial_icounter_struct icount; + struct uart_icount cnow; ++ struct hso_serial *serial = get_serial_by_tty(tty); + struct hso_tiocmget *tiocmget = serial->tiocmget; + + memset(&icount, 0, sizeof(struct serial_icounter_struct)); +@@ -1660,19 +1660,19 @@ static int hso_get_count(struct hso_seri + memcpy(&cnow, &tiocmget->icount, sizeof(struct uart_icount)); + spin_unlock_irq(&serial->serial_lock); + +- icount.cts = cnow.cts; +- icount.dsr = cnow.dsr; +- icount.rng = cnow.rng; +- icount.dcd = cnow.dcd; +- icount.rx = cnow.rx; +- icount.tx = cnow.tx; +- icount.frame = cnow.frame; +- icount.overrun = cnow.overrun; +- icount.parity = cnow.parity; +- icount.brk = cnow.brk; +- icount.buf_overrun = cnow.buf_overrun; ++ icount->cts = cnow.cts; ++ icount->dsr = cnow.dsr; ++ icount->rng = cnow.rng; ++ icount->dcd = cnow.dcd; ++ icount->rx = cnow.rx; ++ icount->tx = cnow.tx; ++ icount->frame = cnow.frame; ++ icount->overrun = cnow.overrun; ++ icount->parity = cnow.parity; ++ icount->brk = cnow.brk; ++ icount->buf_overrun = cnow.buf_overrun; + +- return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0; ++ return 0; + } + + +@@ -1764,10 +1764,6 @@ static int hso_serial_ioctl(struct tty_s + case TIOCMIWAIT: + ret = hso_wait_modem_status(serial, arg); + break; +- +- case TIOCGICOUNT: +- ret = hso_get_count(serial, uarg); +- break; + default: + ret = -ENOIOCTLCMD; + break; +@@ -3300,6 +3296,7 @@ static const struct tty_operations hso_s + .chars_in_buffer = hso_serial_chars_in_buffer, + .tiocmget = hso_serial_tiocmget, + .tiocmset = hso_serial_tiocmset, ++ .get_icount = hso_get_count, + .unthrottle = hso_unthrottle + }; + +--- a/drivers/usb/serial/ark3116.c ++++ b/drivers/usb/serial/ark3116.c +@@ -411,6 +411,26 @@ err_out: + return result; + } + ++static int ark3116_get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount) ++{ ++ struct usb_serial_port *port = tty->driver_data; ++ struct ark3116_private *priv = usb_get_serial_port_data(port); ++ struct async_icount cnow = priv->icount; ++ icount->cts = cnow.cts; ++ icount->dsr = cnow.dsr; ++ icount->rng = cnow.rng; ++ icount->dcd = cnow.dcd; ++ icount->rx = cnow.rx; ++ icount->tx = cnow.tx; ++ icount->frame = cnow.frame; ++ icount->overrun = cnow.overrun; ++ icount->parity = cnow.parity; ++ icount->brk = cnow.brk; ++ icount->buf_overrun = cnow.buf_overrun; ++ return 0; ++} ++ + static int ark3116_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) + { +@@ -460,25 +480,6 @@ static int ark3116_ioctl(struct tty_stru + return 0; + } + break; +- case TIOCGICOUNT: { +- struct serial_icounter_struct icount; +- struct async_icount cnow = priv->icount; +- memset(&icount, 0, sizeof(icount)); +- icount.cts = cnow.cts; +- icount.dsr = cnow.dsr; +- icount.rng = cnow.rng; +- icount.dcd = cnow.dcd; +- icount.rx = cnow.rx; +- icount.tx = cnow.tx; +- icount.frame = cnow.frame; +- icount.overrun = cnow.overrun; +- icount.parity = cnow.parity; +- icount.brk = cnow.brk; +- icount.buf_overrun = cnow.buf_overrun; +- if (copy_to_user(user_arg, &icount, sizeof(icount))) +- return -EFAULT; +- return 0; +- } + } + + return -ENOIOCTLCMD; +@@ -736,6 +737,7 @@ static struct usb_serial_driver ark3116_ + .ioctl = ark3116_ioctl, + .tiocmget = ark3116_tiocmget, + .tiocmset = ark3116_tiocmset, ++ .get_icount = ark3116_get_icount, + .open = ark3116_open, + .close = ark3116_close, + .break_ctl = ark3116_break_ctl, +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -2168,6 +2168,7 @@ static int ftdi_ioctl(struct tty_struct + * - mask passed in arg for lines of interest + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) + * Caller should use TIOCGICOUNT to see which one it was. ++ * (except that the driver doesn't support it !) + * + * This code is borrowed from linux/drivers/char/serial.c + */ +--- a/drivers/usb/serial/io_edgeport.c ++++ b/drivers/usb/serial/io_edgeport.c +@@ -222,6 +222,8 @@ static void edge_break(struct tty_struct + static int edge_tiocmget(struct tty_struct *tty, struct file *file); + static int edge_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear); ++static int edge_get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount); + static int edge_startup(struct usb_serial *serial); + static void edge_disconnect(struct usb_serial *serial); + static void edge_release(struct usb_serial *serial); +@@ -1624,6 +1626,31 @@ static int edge_tiocmget(struct tty_stru + return result; + } + ++static int edge_get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount) ++{ ++ struct usb_serial_port *port = tty->driver_data; ++ struct edgeport_port *edge_port = usb_get_serial_port_data(port); ++ struct async_icount cnow; ++ cnow = edge_port->icount; ++ ++ icount->cts = cnow.cts; ++ icount->dsr = cnow.dsr; ++ icount->rng = cnow.rng; ++ icount->dcd = cnow.dcd; ++ icount->rx = cnow.rx; ++ icount->tx = cnow.tx; ++ icount->frame = cnow.frame; ++ icount->overrun = cnow.overrun; ++ icount->parity = cnow.parity; ++ icount->brk = cnow.brk; ++ icount->buf_overrun = cnow.buf_overrun; ++ ++ dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", ++ __func__, port->number, icount->rx, icount->tx); ++ return 0; ++} ++ + static int get_serial_info(struct edgeport_port *edge_port, + struct serial_struct __user *retinfo) + { +@@ -1650,7 +1677,6 @@ static int get_serial_info(struct edgepo + } + + +- + /***************************************************************************** + * SerialIoctl + * this function handles any ioctl calls to the driver +@@ -1663,7 +1689,6 @@ static int edge_ioctl(struct tty_struct + struct edgeport_port *edge_port = usb_get_serial_port_data(port); + struct async_icount cnow; + struct async_icount cprev; +- struct serial_icounter_struct icount; + + dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); + +@@ -1702,26 +1727,6 @@ static int edge_ioctl(struct tty_struct + /* NOTREACHED */ + break; + +- case TIOCGICOUNT: +- cnow = edge_port->icount; +- memset(&icount, 0, sizeof(icount)); +- icount.cts = cnow.cts; +- icount.dsr = cnow.dsr; +- icount.rng = cnow.rng; +- icount.dcd = cnow.dcd; +- icount.rx = cnow.rx; +- icount.tx = cnow.tx; +- icount.frame = cnow.frame; +- icount.overrun = cnow.overrun; +- icount.parity = cnow.parity; +- icount.brk = cnow.brk; +- icount.buf_overrun = cnow.buf_overrun; +- +- dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", +- __func__, port->number, icount.rx, icount.tx); +- if (copy_to_user((void __user *)arg, &icount, sizeof(icount))) +- return -EFAULT; +- return 0; + } + return -ENOIOCTLCMD; + } +--- a/drivers/usb/serial/io_tables.h ++++ b/drivers/usb/serial/io_tables.h +@@ -123,6 +123,7 @@ static struct usb_serial_driver edgeport + .set_termios = edge_set_termios, + .tiocmget = edge_tiocmget, + .tiocmset = edge_tiocmset, ++ .get_icount = edge_get_icount, + .write = edge_write, + .write_room = edge_write_room, + .chars_in_buffer = edge_chars_in_buffer, +@@ -152,6 +153,7 @@ static struct usb_serial_driver edgeport + .set_termios = edge_set_termios, + .tiocmget = edge_tiocmget, + .tiocmset = edge_tiocmset, ++ .get_icount = edge_get_icount, + .write = edge_write, + .write_room = edge_write_room, + .chars_in_buffer = edge_chars_in_buffer, +@@ -181,6 +183,7 @@ static struct usb_serial_driver edgeport + .set_termios = edge_set_termios, + .tiocmget = edge_tiocmget, + .tiocmset = edge_tiocmset, ++ .get_icount = edge_get_icount, + .write = edge_write, + .write_room = edge_write_room, + .chars_in_buffer = edge_chars_in_buffer, +@@ -209,6 +212,7 @@ static struct usb_serial_driver epic_dev + .set_termios = edge_set_termios, + .tiocmget = edge_tiocmget, + .tiocmset = edge_tiocmset, ++ .get_icount = edge_get_icount, + .write = edge_write, + .write_room = edge_write_room, + .chars_in_buffer = edge_chars_in_buffer, +--- a/drivers/usb/serial/io_ti.c ++++ b/drivers/usb/serial/io_ti.c +@@ -2510,6 +2510,27 @@ static int edge_tiocmget(struct tty_stru + return result; + } + ++static int edge_get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount) ++{ ++ struct usb_serial_port *port = tty->driver_data; ++ struct edgeport_port *edge_port = usb_get_serial_port_data(port); ++ struct async_icount *ic = &edge_port->icount; ++ ++ icount->cts = ic->cts; ++ icount->dsr = ic->dsr; ++ icount->rng = ic->rng; ++ icount->dcd = ic->dcd; ++ icount->tx = ic->tx; ++ icount->rx = ic->rx; ++ icount->frame = ic->frame; ++ icount->parity = ic->parity; ++ icount->overrun = ic->overrun; ++ icount->brk = ic->brk; ++ icount->buf_overrun = ic->buf_overrun; ++ return 0; ++} ++ + static int get_serial_info(struct edgeport_port *edge_port, + struct serial_struct __user *retinfo) + { +@@ -2572,13 +2593,6 @@ static int edge_ioctl(struct tty_struct + } + /* not reached */ + break; +- case TIOCGICOUNT: +- dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, +- port->number, edge_port->icount.rx, edge_port->icount.tx); +- if (copy_to_user((void __user *)arg, &edge_port->icount, +- sizeof(edge_port->icount))) +- return -EFAULT; +- return 0; + } + return -ENOIOCTLCMD; + } +@@ -2758,6 +2772,7 @@ static struct usb_serial_driver edgeport + .set_termios = edge_set_termios, + .tiocmget = edge_tiocmget, + .tiocmset = edge_tiocmset, ++ .get_icount = edge_get_icount, + .write = edge_write, + .write_room = edge_write_room, + .chars_in_buffer = edge_chars_in_buffer, +--- a/drivers/usb/serial/mos7720.c ++++ b/drivers/usb/serial/mos7720.c +@@ -1896,10 +1896,37 @@ static int mos7720_tiocmset(struct tty_s + return 0; + } + ++static int mos7720_get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount) ++{ ++ struct usb_serial_port *port = tty->driver_data; ++ struct moschip_port *mos7720_port; ++ struct async_icount cnow; ++ ++ mos7720_port = usb_get_serial_port_data(port); ++ cnow = mos7720_port->icount; ++ ++ icount->cts = cnow.cts; ++ icount->dsr = cnow.dsr; ++ icount->rng = cnow.rng; ++ icount->dcd = cnow.dcd; ++ icount->rx = cnow.rx; ++ icount->tx = cnow.tx; ++ icount->frame = cnow.frame; ++ icount->overrun = cnow.overrun; ++ icount->parity = cnow.parity; ++ icount->brk = cnow.brk; ++ icount->buf_overrun = cnow.buf_overrun; ++ ++ dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, ++ port->number, icount->rx, icount->tx); ++ return 0; ++} ++ + static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd, + unsigned int __user *value) + { +- unsigned int mcr ; ++ unsigned int mcr; + unsigned int arg; + + struct usb_serial_port *port; +@@ -1973,7 +2000,6 @@ static int mos7720_ioctl(struct tty_stru + struct moschip_port *mos7720_port; + struct async_icount cnow; + struct async_icount cprev; +- struct serial_icounter_struct icount; + + mos7720_port = usb_get_serial_port_data(port); + if (mos7720_port == NULL) +@@ -2021,29 +2047,6 @@ static int mos7720_ioctl(struct tty_stru + } + /* NOTREACHED */ + break; +- +- case TIOCGICOUNT: +- cnow = mos7720_port->icount; +- +- memset(&icount, 0, sizeof(struct serial_icounter_struct)); +- +- icount.cts = cnow.cts; +- icount.dsr = cnow.dsr; +- icount.rng = cnow.rng; +- icount.dcd = cnow.dcd; +- icount.rx = cnow.rx; +- icount.tx = cnow.tx; +- icount.frame = cnow.frame; +- icount.overrun = cnow.overrun; +- icount.parity = cnow.parity; +- icount.brk = cnow.brk; +- icount.buf_overrun = cnow.buf_overrun; +- +- dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, +- port->number, icount.rx, icount.tx); +- if (copy_to_user((void __user *)arg, &icount, sizeof(icount))) +- return -EFAULT; +- return 0; + } + + return -ENOIOCTLCMD; +@@ -2212,6 +2215,7 @@ static struct usb_serial_driver moschip7 + .ioctl = mos7720_ioctl, + .tiocmget = mos7720_tiocmget, + .tiocmset = mos7720_tiocmset, ++ .get_icount = mos7720_get_icount, + .set_termios = mos7720_set_termios, + .write = mos7720_write, + .write_room = mos7720_write_room, +--- a/drivers/usb/serial/mos7840.c ++++ b/drivers/usb/serial/mos7840.c +@@ -2209,6 +2209,34 @@ static int mos7840_get_serial_info(struc + return 0; + } + ++static int mos7840_get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount) ++{ ++ struct usb_serial_port *port = tty->driver_data; ++ struct moschip_port *mos7840_port; ++ struct async_icount cnow; ++ ++ mos7840_port = mos7840_get_port_private(port); ++ cnow = mos7840_port->icount; ++ ++ smp_rmb(); ++ icount->cts = cnow.cts; ++ icount->dsr = cnow.dsr; ++ icount->rng = cnow.rng; ++ icount->dcd = cnow.dcd; ++ icount->rx = cnow.rx; ++ icount->tx = cnow.tx; ++ icount->frame = cnow.frame; ++ icount->overrun = cnow.overrun; ++ icount->parity = cnow.parity; ++ icount->brk = cnow.brk; ++ icount->buf_overrun = cnow.buf_overrun; ++ ++ dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, ++ port->number, icount->rx, icount->tx); ++ return 0; ++} ++ + /***************************************************************************** + * SerialIoctl + * this function handles any ioctl calls to the driver +@@ -2223,7 +2251,6 @@ static int mos7840_ioctl(struct tty_stru + + struct async_icount cnow; + struct async_icount cprev; +- struct serial_icounter_struct icount; + + if (mos7840_port_paranoia_check(port, __func__)) { + dbg("%s", "Invalid port"); +@@ -2282,29 +2309,6 @@ static int mos7840_ioctl(struct tty_stru + /* NOTREACHED */ + break; + +- case TIOCGICOUNT: +- cnow = mos7840_port->icount; +- smp_rmb(); +- +- memset(&icount, 0, sizeof(struct serial_icounter_struct)); +- +- icount.cts = cnow.cts; +- icount.dsr = cnow.dsr; +- icount.rng = cnow.rng; +- icount.dcd = cnow.dcd; +- icount.rx = cnow.rx; +- icount.tx = cnow.tx; +- icount.frame = cnow.frame; +- icount.overrun = cnow.overrun; +- icount.parity = cnow.parity; +- icount.brk = cnow.brk; +- icount.buf_overrun = cnow.buf_overrun; +- +- dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, +- port->number, icount.rx, icount.tx); +- if (copy_to_user(argp, &icount, sizeof(icount))) +- return -EFAULT; +- return 0; + default: + break; + } +@@ -2674,6 +2678,7 @@ static struct usb_serial_driver moschip7 + .break_ctl = mos7840_break, + .tiocmget = mos7840_tiocmget, + .tiocmset = mos7840_tiocmset, ++ .get_icount = mos7840_get_icount, + .attach = mos7840_startup, + .disconnect = mos7840_disconnect, + .release = mos7840_release, +--- a/drivers/usb/serial/ssu100.c ++++ b/drivers/usb/serial/ssu100.c +@@ -416,6 +416,30 @@ static int wait_modem_info(struct usb_se + return 0; + } + ++static int ssu100_get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount) ++{ ++ struct usb_serial_port *port = tty->driver_data; ++ struct ssu100_port_private *priv = usb_get_serial_port_data(port); ++ struct async_icount cnow = priv->icount; ++ ++ icount->cts = cnow.cts; ++ icount->dsr = cnow.dsr; ++ icount->rng = cnow.rng; ++ icount->dcd = cnow.dcd; ++ icount->rx = cnow.rx; ++ icount->tx = cnow.tx; ++ icount->frame = cnow.frame; ++ icount->overrun = cnow.overrun; ++ icount->parity = cnow.parity; ++ icount->brk = cnow.brk; ++ icount->buf_overrun = cnow.buf_overrun; ++ ++ return 0; ++} ++ ++ ++ + static int ssu100_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) + { +@@ -433,27 +457,6 @@ static int ssu100_ioctl(struct tty_struc + case TIOCMIWAIT: + return wait_modem_info(port, arg); + +- case TIOCGICOUNT: +- { +- struct serial_icounter_struct icount; +- struct async_icount cnow = priv->icount; +- memset(&icount, 0, sizeof(icount)); +- icount.cts = cnow.cts; +- icount.dsr = cnow.dsr; +- icount.rng = cnow.rng; +- icount.dcd = cnow.dcd; +- icount.rx = cnow.rx; +- icount.tx = cnow.tx; +- icount.frame = cnow.frame; +- icount.overrun = cnow.overrun; +- icount.parity = cnow.parity; +- icount.brk = cnow.brk; +- icount.buf_overrun = cnow.buf_overrun; +- if (copy_to_user(user_arg, &icount, sizeof(icount))) +- return -EFAULT; +- return 0; +- } +- + default: + break; + } +@@ -726,6 +729,7 @@ static struct usb_serial_driver ssu100_d + .process_read_urb = ssu100_process_read_urb, + .tiocmget = ssu100_tiocmget, + .tiocmset = ssu100_tiocmset, ++ .get_icount = ssu100_get_icount, + .ioctl = ssu100_ioctl, + .set_termios = ssu100_set_termios, + .disconnect = usb_serial_generic_disconnect, +--- a/drivers/usb/serial/ti_usb_3410_5052.c ++++ b/drivers/usb/serial/ti_usb_3410_5052.c +@@ -108,6 +108,8 @@ static void ti_throttle(struct tty_struc + static void ti_unthrottle(struct tty_struct *tty); + static int ti_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg); ++static int ti_get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount); + static void ti_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios); + static int ti_tiocmget(struct tty_struct *tty, struct file *file); +@@ -237,6 +239,7 @@ static struct usb_serial_driver ti_1port + .set_termios = ti_set_termios, + .tiocmget = ti_tiocmget, + .tiocmset = ti_tiocmset, ++ .get_icount = ti_get_icount, + .break_ctl = ti_break, + .read_int_callback = ti_interrupt_callback, + .read_bulk_callback = ti_bulk_in_callback, +@@ -265,6 +268,7 @@ static struct usb_serial_driver ti_2port + .set_termios = ti_set_termios, + .tiocmget = ti_tiocmget, + .tiocmset = ti_tiocmset, ++ .get_icount = ti_get_icount, + .break_ctl = ti_break, + .read_int_callback = ti_interrupt_callback, + .read_bulk_callback = ti_bulk_in_callback, +@@ -788,6 +792,31 @@ static void ti_unthrottle(struct tty_str + } + } + ++static int ti_get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount) ++{ ++ struct usb_serial_port *port = tty->driver_data; ++ struct ti_port *tport = usb_get_serial_port_data(port); ++ struct async_icount cnow = tport->tp_icount; ++ ++ dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", ++ __func__, port->number, ++ cnow.rx, cnow.tx); ++ ++ icount->cts = cnow.cts; ++ icount->dsr = cnow.dsr; ++ icount->rng = cnow.rng; ++ icount->dcd = cnow.dcd; ++ icount->rx = cnow.rx; ++ icount->tx = cnow.tx; ++ icount->frame = cnow.frame; ++ icount->overrun = cnow.overrun; ++ icount->parity = cnow.parity; ++ icount->brk = cnow.brk; ++ icount->buf_overrun = cnow.buf_overrun; ++ ++ return 0; ++} + + static int ti_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +@@ -830,14 +859,6 @@ static int ti_ioctl(struct tty_struct *t + cprev = cnow; + } + break; +- case TIOCGICOUNT: +- dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", +- __func__, port->number, +- tport->tp_icount.rx, tport->tp_icount.tx); +- if (copy_to_user((void __user *)arg, &tport->tp_icount, +- sizeof(tport->tp_icount))) +- return -EFAULT; +- return 0; + } + return -ENOIOCTLCMD; + } diff --git a/tty/tty-icount-changeover-for-other-main-devices.patch b/tty/tty-icount-changeover-for-other-main-devices.patch new file mode 100644 index 00000000000000..1b49fe122f80b7 --- /dev/null +++ b/tty/tty-icount-changeover-for-other-main-devices.patch @@ -0,0 +1,947 @@ +From linux-kernel-owner@vger.kernel.org Tue Sep 21 14:32:39 2010 +From: Alan Cox <alan@linux.intel.com> +Subject: tty: icount changeover for other main devices +To: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, + greg@kroah.com, drosenberg@vsecurity.com +Date: Thu, 16 Sep 2010 18:21:52 +0100 +Message-ID: <20100916172147.25987.72021.stgit@localhost.localdomain> + +Again basically cut and paste + +Signed-off-by: Alan Cox <alan@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + arch/ia64/hp/sim/simserial.c | 12 ------ + drivers/char/amiserial.c | 56 ++++++++++++++++------------- + drivers/char/cyclades.c | 49 +++++++++++++------------ + drivers/char/ip2/ip2main.c | 71 ++++++++++++++++++++++-------------- + drivers/char/mxser.c | 62 ++++++++++++++++++-------------- + drivers/char/nozomi.c | 35 ++++++++---------- + drivers/char/pcmcia/synclink_cs.c | 60 ++++++++++++++----------------- + drivers/char/synclink.c | 73 +++++++++++++++++--------------------- + drivers/char/synclink_gt.c | 55 +++++++++++++++------------- + drivers/char/synclinkmp.c | 61 ++++++++++++++----------------- + drivers/serial/68360serial.c | 51 +++++++++++++------------- + net/bluetooth/rfcomm/tty.c | 4 -- + 12 files changed, 296 insertions(+), 293 deletions(-) + +--- a/arch/ia64/hp/sim/simserial.c ++++ b/arch/ia64/hp/sim/simserial.c +@@ -395,7 +395,7 @@ static int rs_ioctl(struct tty_struct *t + { + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && +- (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { ++ (cmd != TIOCMIWAIT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } +@@ -433,16 +433,6 @@ static int rs_ioctl(struct tty_struct *t + case TIOCMIWAIT: + printk(KERN_INFO "rs_ioctl: TIOCMIWAIT: called\n"); + return 0; +- /* +- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) +- * Return: write counters to the user passed counter struct +- * NB: both 1->0 and 0->1 transitions are counted except for +- * RI where only 0->1 is counted. +- */ +- case TIOCGICOUNT: +- printk(KERN_INFO "rs_ioctl: TIOCGICOUNT called\n"); +- return 0; +- + case TIOCSERGWILD: + case TIOCSERSWILD: + /* "setserial -W" is called in Debian boot */ +--- a/drivers/char/amiserial.c ++++ b/drivers/char/amiserial.c +@@ -1263,6 +1263,36 @@ static int rs_break(struct tty_struct *t + return 0; + } + ++/* ++ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) ++ * Return: write counters to the user passed counter struct ++ * NB: both 1->0 and 0->1 transitions are counted except for ++ * RI where only 0->1 is counted. ++ */ ++static int rs_get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount) ++{ ++ struct async_struct *info = tty->driver_data; ++ struct async_icount cnow; ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ cnow = info->state->icount; ++ local_irq_restore(flags); ++ icount->cts = cnow.cts; ++ icount->dsr = cnow.dsr; ++ icount->rng = cnow.rng; ++ icount->dcd = cnow.dcd; ++ icount->rx = cnow.rx; ++ icount->tx = cnow.tx; ++ icount->frame = cnow.frame; ++ icount->overrun = cnow.overrun; ++ icount->parity = cnow.parity; ++ icount->brk = cnow.brk; ++ icount->buf_overrun = cnow.buf_overrun; ++ ++ return 0; ++} + + static int rs_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +@@ -1332,31 +1362,6 @@ static int rs_ioctl(struct tty_struct *t + } + /* NOTREACHED */ + +- /* +- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) +- * Return: write counters to the user passed counter struct +- * NB: both 1->0 and 0->1 transitions are counted except for +- * RI where only 0->1 is counted. +- */ +- case TIOCGICOUNT: +- local_irq_save(flags); +- cnow = info->state->icount; +- local_irq_restore(flags); +- icount.cts = cnow.cts; +- icount.dsr = cnow.dsr; +- icount.rng = cnow.rng; +- icount.dcd = cnow.dcd; +- icount.rx = cnow.rx; +- icount.tx = cnow.tx; +- icount.frame = cnow.frame; +- icount.overrun = cnow.overrun; +- icount.parity = cnow.parity; +- icount.brk = cnow.brk; +- icount.buf_overrun = cnow.buf_overrun; +- +- if (copy_to_user(argp, &icount, sizeof(icount))) +- return -EFAULT; +- return 0; + case TIOCSERGWILD: + case TIOCSERSWILD: + /* "setserial -W" is called in Debian boot */ +@@ -1958,6 +1963,7 @@ static const struct tty_operations seria + .wait_until_sent = rs_wait_until_sent, + .tiocmget = rs_tiocmget, + .tiocmset = rs_tiocmset, ++ .get_icount = rs_get_icount, + .proc_fops = &rs_proc_fops, + }; + +--- a/drivers/char/cyclades.c ++++ b/drivers/char/cyclades.c +@@ -2790,29 +2790,6 @@ cy_ioctl(struct tty_struct *tty, struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ +- case TIOCGICOUNT: { +- struct serial_icounter_struct sic = { }; +- +- spin_lock_irqsave(&info->card->card_lock, flags); +- cnow = info->icount; +- spin_unlock_irqrestore(&info->card->card_lock, flags); +- +- sic.cts = cnow.cts; +- sic.dsr = cnow.dsr; +- sic.rng = cnow.rng; +- sic.dcd = cnow.dcd; +- sic.rx = cnow.rx; +- sic.tx = cnow.tx; +- sic.frame = cnow.frame; +- sic.overrun = cnow.overrun; +- sic.parity = cnow.parity; +- sic.brk = cnow.brk; +- sic.buf_overrun = cnow.buf_overrun; +- +- if (copy_to_user(argp, &sic, sizeof(sic))) +- ret_val = -EFAULT; +- break; +- } + default: + ret_val = -ENOIOCTLCMD; + } +@@ -2823,6 +2800,31 @@ cy_ioctl(struct tty_struct *tty, struct + return ret_val; + } /* cy_ioctl */ + ++static int cy_get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *sic) ++{ ++ struct cyclades_port *info = tty->driver_data; ++ struct cyclades_icount cnow; /* Used to snapshot */ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&info->card->card_lock, flags); ++ cnow = info->icount; ++ spin_unlock_irqrestore(&info->card->card_lock, flags); ++ ++ sic->cts = cnow.cts; ++ sic->dsr = cnow.dsr; ++ sic->rng = cnow.rng; ++ sic->dcd = cnow.dcd; ++ sic->rx = cnow.rx; ++ sic->tx = cnow.tx; ++ sic->frame = cnow.frame; ++ sic->overrun = cnow.overrun; ++ sic->parity = cnow.parity; ++ sic->brk = cnow.brk; ++ sic->buf_overrun = cnow.buf_overrun; ++ return 0; ++} ++ + /* + * This routine allows the tty driver to be notified when + * device's termios settings have changed. Note that a +@@ -4084,6 +4086,7 @@ static const struct tty_operations cy_op + .wait_until_sent = cy_wait_until_sent, + .tiocmget = cy_tiocmget, + .tiocmset = cy_tiocmset, ++ .get_icount = cy_get_icount, + .proc_fops = &cyclades_proc_fops, + }; + +--- a/drivers/char/ip2/ip2main.c ++++ b/drivers/char/ip2/ip2main.c +@@ -183,6 +183,8 @@ static void ip2_hangup(PTTY); + static int ip2_tiocmget(struct tty_struct *tty, struct file *file); + static int ip2_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear); ++static int get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount); + + static void set_irq(int, int); + static void ip2_interrupt_bh(struct work_struct *work); +@@ -454,6 +456,7 @@ static const struct tty_operations ip2_o + .hangup = ip2_hangup, + .tiocmget = ip2_tiocmget, + .tiocmset = ip2_tiocmset, ++ .get_icount = ip2_get_icount, + .proc_fops = &ip2_proc_fops, + }; + +@@ -2297,34 +2300,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile + break; + + /* +- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) +- * Return: write counters to the user passed counter struct +- * NB: both 1->0 and 0->1 transitions are counted except for RI where +- * only 0->1 is counted. The controller is quite capable of counting +- * both, but this done to preserve compatibility with the standard +- * serial driver. +- */ +- case TIOCGICOUNT: +- ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc ); +- +- write_lock_irqsave(&pB->read_fifo_spinlock, flags); +- cnow = pCh->icount; +- write_unlock_irqrestore(&pB->read_fifo_spinlock, flags); +- p_cuser = argp; +- rc = put_user(cnow.cts, &p_cuser->cts); +- rc = put_user(cnow.dsr, &p_cuser->dsr); +- rc = put_user(cnow.rng, &p_cuser->rng); +- rc = put_user(cnow.dcd, &p_cuser->dcd); +- rc = put_user(cnow.rx, &p_cuser->rx); +- rc = put_user(cnow.tx, &p_cuser->tx); +- rc = put_user(cnow.frame, &p_cuser->frame); +- rc = put_user(cnow.overrun, &p_cuser->overrun); +- rc = put_user(cnow.parity, &p_cuser->parity); +- rc = put_user(cnow.brk, &p_cuser->brk); +- rc = put_user(cnow.buf_overrun, &p_cuser->buf_overrun); +- break; +- +- /* + * The rest are not supported by this driver. By returning -ENOIOCTLCMD they + * will be passed to the line discipline for it to handle. + */ +@@ -2348,6 +2323,46 @@ ip2_ioctl ( PTTY tty, struct file *pFile + return rc; + } + ++static int get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount) ++{ ++ i2ChanStrPtr pCh = DevTable[tty->index]; ++ i2eBordStrPtr pB; ++ struct async_icount cnow; /* kernel counter temp */ ++ unsigned long flags; ++ ++ if ( pCh == NULL ) ++ return -ENODEV; ++ ++ pB = pCh->pMyBord; ++ ++ /* ++ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) ++ * Return: write counters to the user passed counter struct ++ * NB: both 1->0 and 0->1 transitions are counted except for RI where ++ * only 0->1 is counted. The controller is quite capable of counting ++ * both, but this done to preserve compatibility with the standard ++ * serial driver. ++ */ ++ ++ write_lock_irqsave(&pB->read_fifo_spinlock, flags); ++ cnow = pCh->icount; ++ write_unlock_irqrestore(&pB->read_fifo_spinlock, flags); ++ ++ icount->cts = cnow.cts; ++ icount->dsr = cnow.dsr; ++ icount->rng = cnow.rng; ++ icount->dcd = cnow.dcd; ++ icount->rx = cnow.rx; ++ icount->tx = cnow.tx; ++ icount->frame = cnow.frame; ++ icount->overrun = cnow.overrun; ++ icount->parity = cnow.parity; ++ icount->brk = cnow.brk; ++ icount->buf_overrun = cnow.buf_overrun; ++ return 0; ++} ++ + /******************************************************************************/ + /* Function: GetSerialInfo() */ + /* Parameters: Pointer to channel structure */ +--- a/drivers/char/mxser.c ++++ b/drivers/char/mxser.c +@@ -1700,7 +1700,7 @@ static int mxser_ioctl(struct tty_struct + return 0; + } + +- if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT && ++ if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && + test_bit(TTY_IO_ERROR, &tty->flags)) + return -EIO; + +@@ -1730,32 +1730,6 @@ static int mxser_ioctl(struct tty_struct + + return wait_event_interruptible(info->port.delta_msr_wait, + mxser_cflags_changed(info, arg, &cnow)); +- /* +- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) +- * Return: write counters to the user passed counter struct +- * NB: both 1->0 and 0->1 transitions are counted except for +- * RI where only 0->1 is counted. +- */ +- case TIOCGICOUNT: { +- struct serial_icounter_struct icnt = { 0 }; +- spin_lock_irqsave(&info->slock, flags); +- cnow = info->icount; +- spin_unlock_irqrestore(&info->slock, flags); +- +- icnt.frame = cnow.frame; +- icnt.brk = cnow.brk; +- icnt.overrun = cnow.overrun; +- icnt.buf_overrun = cnow.buf_overrun; +- icnt.parity = cnow.parity; +- icnt.rx = cnow.rx; +- icnt.tx = cnow.tx; +- icnt.cts = cnow.cts; +- icnt.dsr = cnow.dsr; +- icnt.rng = cnow.rng; +- icnt.dcd = cnow.dcd; +- +- return copy_to_user(argp, &icnt, sizeof(icnt)) ? -EFAULT : 0; +- } + case MOXA_HighSpeedOn: + return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); + case MOXA_SDS_RSTICOUNTER: +@@ -1828,6 +1802,39 @@ static int mxser_ioctl(struct tty_struct + return 0; + } + ++ /* ++ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) ++ * Return: write counters to the user passed counter struct ++ * NB: both 1->0 and 0->1 transitions are counted except for ++ * RI where only 0->1 is counted. ++ */ ++ ++static int mxser_get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount) ++ ++{ ++ struct mxser_port *info = tty->driver_data; ++ struct async_icount cnow; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&info->slock, flags); ++ cnow = info->icount; ++ spin_unlock_irqrestore(&info->slock, flags); ++ ++ icount->frame = cnow.frame; ++ icount->brk = cnow.brk; ++ icount->overrun = cnow.overrun; ++ icount->buf_overrun = cnow.buf_overrun; ++ icount->parity = cnow.parity; ++ icount->rx = cnow.rx; ++ icount->tx = cnow.tx; ++ icount->cts = cnow.cts; ++ icount->dsr = cnow.dsr; ++ icount->rng = cnow.rng; ++ icount->dcd = cnow.dcd; ++ return 0; ++} ++ + static void mxser_stoprx(struct tty_struct *tty) + { + struct mxser_port *info = tty->driver_data; +@@ -2326,6 +2333,7 @@ static const struct tty_operations mxser + .wait_until_sent = mxser_wait_until_sent, + .tiocmget = mxser_tiocmget, + .tiocmset = mxser_tiocmset, ++ .get_icount = mxser_get_icount, + }; + + struct tty_port_operations mxser_port_ops = { +--- a/drivers/char/nozomi.c ++++ b/drivers/char/nozomi.c +@@ -1804,24 +1804,24 @@ static int ntty_cflags_changed(struct po + return ret; + } + +-static int ntty_ioctl_tiocgicount(struct port *port, void __user *argp) ++static int ntty_tiocgicount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount) + { ++ struct port *port = tty->driver_data; + const struct async_icount cnow = port->tty_icount; +- struct serial_icounter_struct icount; +- +- icount.cts = cnow.cts; +- icount.dsr = cnow.dsr; +- icount.rng = cnow.rng; +- icount.dcd = cnow.dcd; +- icount.rx = cnow.rx; +- icount.tx = cnow.tx; +- icount.frame = cnow.frame; +- icount.overrun = cnow.overrun; +- icount.parity = cnow.parity; +- icount.brk = cnow.brk; +- icount.buf_overrun = cnow.buf_overrun; + +- return copy_to_user(argp, &icount, sizeof(icount)) ? -EFAULT : 0; ++ icount->cts = cnow.cts; ++ icount->dsr = cnow.dsr; ++ icount->rng = cnow.rng; ++ icount->dcd = cnow.dcd; ++ icount->rx = cnow.rx; ++ icount->tx = cnow.tx; ++ icount->frame = cnow.frame; ++ icount->overrun = cnow.overrun; ++ icount->parity = cnow.parity; ++ icount->brk = cnow.brk; ++ icount->buf_overrun = cnow.buf_overrun; ++ return 0; + } + + static int ntty_ioctl(struct tty_struct *tty, struct file *file, +@@ -1840,9 +1840,7 @@ static int ntty_ioctl(struct tty_struct + rval = wait_event_interruptible(port->tty_wait, + ntty_cflags_changed(port, arg, &cprev)); + break; +- } case TIOCGICOUNT: +- rval = ntty_ioctl_tiocgicount(port, argp); +- break; ++ } + default: + DBG1("ERR: 0x%08X, %d", cmd, cmd); + break; +@@ -1922,6 +1920,7 @@ static const struct tty_operations tty_o + .chars_in_buffer = ntty_chars_in_buffer, + .tiocmget = ntty_tiocmget, + .tiocmset = ntty_tiocmset, ++ .get_icount = ntty_tiocgicount, + .install = ntty_install, + .cleanup = ntty_cleanup, + }; +--- a/drivers/char/pcmcia/synclink_cs.c ++++ b/drivers/char/pcmcia/synclink_cs.c +@@ -2215,6 +2215,32 @@ static int mgslpc_break(struct tty_struc + return 0; + } + ++static int mgslpc_get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount) ++{ ++ MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; ++ struct mgsl_icount cnow; /* kernel counter temps */ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&info->lock,flags); ++ cnow = info->icount; ++ spin_unlock_irqrestore(&info->lock,flags); ++ ++ icount->cts = cnow.cts; ++ icount->dsr = cnow.dsr; ++ icount->rng = cnow.rng; ++ icount->dcd = cnow.dcd; ++ icount->rx = cnow.rx; ++ icount->tx = cnow.tx; ++ icount->frame = cnow.frame; ++ icount->overrun = cnow.overrun; ++ icount->parity = cnow.parity; ++ icount->brk = cnow.brk; ++ icount->buf_overrun = cnow.buf_overrun; ++ ++ return 0; ++} ++ + /* Service an IOCTL request + * + * Arguments: +@@ -2230,11 +2256,7 @@ static int mgslpc_ioctl(struct tty_struc + unsigned int cmd, unsigned long arg) + { + MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; +- int error; +- struct mgsl_icount cnow; /* kernel counter temps */ +- struct serial_icounter_struct __user *p_cuser; /* user space */ + void __user *argp = (void __user *)arg; +- unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__, +@@ -2244,7 +2266,7 @@ static int mgslpc_ioctl(struct tty_struc + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && +- (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { ++ (cmd != TIOCMIWAIT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } +@@ -2274,34 +2296,6 @@ static int mgslpc_ioctl(struct tty_struc + return wait_events(info, argp); + case TIOCMIWAIT: + return modem_input_wait(info,(int)arg); +- case TIOCGICOUNT: +- spin_lock_irqsave(&info->lock,flags); +- cnow = info->icount; +- spin_unlock_irqrestore(&info->lock,flags); +- p_cuser = argp; +- PUT_USER(error,cnow.cts, &p_cuser->cts); +- if (error) return error; +- PUT_USER(error,cnow.dsr, &p_cuser->dsr); +- if (error) return error; +- PUT_USER(error,cnow.rng, &p_cuser->rng); +- if (error) return error; +- PUT_USER(error,cnow.dcd, &p_cuser->dcd); +- if (error) return error; +- PUT_USER(error,cnow.rx, &p_cuser->rx); +- if (error) return error; +- PUT_USER(error,cnow.tx, &p_cuser->tx); +- if (error) return error; +- PUT_USER(error,cnow.frame, &p_cuser->frame); +- if (error) return error; +- PUT_USER(error,cnow.overrun, &p_cuser->overrun); +- if (error) return error; +- PUT_USER(error,cnow.parity, &p_cuser->parity); +- if (error) return error; +- PUT_USER(error,cnow.brk, &p_cuser->brk); +- if (error) return error; +- PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun); +- if (error) return error; +- return 0; + default: + return -ENOIOCTLCMD; + } +--- a/drivers/char/synclink.c ++++ b/drivers/char/synclink.c +@@ -2925,6 +2925,38 @@ static int mgsl_break(struct tty_struct + + } /* end of mgsl_break() */ + ++/* ++ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) ++ * Return: write counters to the user passed counter struct ++ * NB: both 1->0 and 0->1 transitions are counted except for ++ * RI where only 0->1 is counted. ++ */ ++static int msgl_get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount) ++ ++{ ++ struct mgsl_struct * info = tty->driver_data; ++ struct mgsl_icount cnow; /* kernel counter temps */ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&info->irq_spinlock,flags); ++ cnow = info->icount; ++ spin_unlock_irqrestore(&info->irq_spinlock,flags); ++ ++ icount->cts = cnow.cts; ++ icount->dsr = cnow.dsr; ++ icount->rng = cnow.rng; ++ icount->dcd = cnow.dcd; ++ icount->rx = cnow.rx; ++ icount->tx = cnow.tx; ++ icount->frame = cnow.frame; ++ icount->overrun = cnow.overrun; ++ icount->parity = cnow.parity; ++ icount->brk = cnow.brk; ++ icount->buf_overrun = cnow.buf_overrun; ++ return 0; ++} ++ + /* mgsl_ioctl() Service an IOCTL request + * + * Arguments: +@@ -2949,7 +2981,7 @@ static int mgsl_ioctl(struct tty_struct + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && +- (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { ++ (cmd != TIOCMIWAIT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } +@@ -2959,11 +2991,7 @@ static int mgsl_ioctl(struct tty_struct + + static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg) + { +- int error; +- struct mgsl_icount cnow; /* kernel counter temps */ + void __user *argp = (void __user *)arg; +- struct serial_icounter_struct __user *p_cuser; /* user space */ +- unsigned long flags; + + switch (cmd) { + case MGSL_IOCGPARAMS: +@@ -2992,40 +3020,6 @@ static int mgsl_ioctl_common(struct mgsl + case TIOCMIWAIT: + return modem_input_wait(info,(int)arg); + +- /* +- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) +- * Return: write counters to the user passed counter struct +- * NB: both 1->0 and 0->1 transitions are counted except for +- * RI where only 0->1 is counted. +- */ +- case TIOCGICOUNT: +- spin_lock_irqsave(&info->irq_spinlock,flags); +- cnow = info->icount; +- spin_unlock_irqrestore(&info->irq_spinlock,flags); +- p_cuser = argp; +- PUT_USER(error,cnow.cts, &p_cuser->cts); +- if (error) return error; +- PUT_USER(error,cnow.dsr, &p_cuser->dsr); +- if (error) return error; +- PUT_USER(error,cnow.rng, &p_cuser->rng); +- if (error) return error; +- PUT_USER(error,cnow.dcd, &p_cuser->dcd); +- if (error) return error; +- PUT_USER(error,cnow.rx, &p_cuser->rx); +- if (error) return error; +- PUT_USER(error,cnow.tx, &p_cuser->tx); +- if (error) return error; +- PUT_USER(error,cnow.frame, &p_cuser->frame); +- if (error) return error; +- PUT_USER(error,cnow.overrun, &p_cuser->overrun); +- if (error) return error; +- PUT_USER(error,cnow.parity, &p_cuser->parity); +- if (error) return error; +- PUT_USER(error,cnow.brk, &p_cuser->brk); +- if (error) return error; +- PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun); +- if (error) return error; +- return 0; + default: + return -ENOIOCTLCMD; + } +@@ -4328,6 +4322,7 @@ static const struct tty_operations mgsl_ + .hangup = mgsl_hangup, + .tiocmget = tiocmget, + .tiocmset = tiocmset, ++ .get_icount = msgl_get_icount, + .proc_fops = &mgsl_proc_fops, + }; + +--- a/drivers/char/synclink_gt.c ++++ b/drivers/char/synclink_gt.c +@@ -1032,9 +1032,6 @@ static int ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) + { + struct slgt_info *info = tty->driver_data; +- struct mgsl_icount cnow; /* kernel counter temps */ +- struct serial_icounter_struct __user *p_cuser; /* user space */ +- unsigned long flags; + void __user *argp = (void __user *)arg; + int ret; + +@@ -1043,7 +1040,7 @@ static int ioctl(struct tty_struct *tty, + DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd)); + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && +- (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { ++ (cmd != TIOCMIWAIT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } +@@ -1053,24 +1050,6 @@ static int ioctl(struct tty_struct *tty, + return wait_mgsl_event(info, argp); + case TIOCMIWAIT: + return modem_input_wait(info,(int)arg); +- case TIOCGICOUNT: +- spin_lock_irqsave(&info->lock,flags); +- cnow = info->icount; +- spin_unlock_irqrestore(&info->lock,flags); +- p_cuser = argp; +- if (put_user(cnow.cts, &p_cuser->cts) || +- put_user(cnow.dsr, &p_cuser->dsr) || +- put_user(cnow.rng, &p_cuser->rng) || +- put_user(cnow.dcd, &p_cuser->dcd) || +- put_user(cnow.rx, &p_cuser->rx) || +- put_user(cnow.tx, &p_cuser->tx) || +- put_user(cnow.frame, &p_cuser->frame) || +- put_user(cnow.overrun, &p_cuser->overrun) || +- put_user(cnow.parity, &p_cuser->parity) || +- put_user(cnow.brk, &p_cuser->brk) || +- put_user(cnow.buf_overrun, &p_cuser->buf_overrun)) +- return -EFAULT; +- return 0; + case MGSL_IOCSGPIO: + return set_gpio(info, argp); + case MGSL_IOCGGPIO: +@@ -1117,6 +1096,33 @@ static int ioctl(struct tty_struct *tty, + return ret; + } + ++static int get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount) ++ ++{ ++ struct slgt_info *info = tty->driver_data; ++ struct mgsl_icount cnow; /* kernel counter temps */ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&info->lock,flags); ++ cnow = info->icount; ++ spin_unlock_irqrestore(&info->lock,flags); ++ ++ icount->cts = cnow.cts; ++ icount->dsr = cnow.dsr; ++ icount->rng = cnow.rng; ++ icount->dcd = cnow.dcd; ++ icount->rx = cnow.rx; ++ icount->tx = cnow.tx; ++ icount->frame = cnow.frame; ++ icount->overrun = cnow.overrun; ++ icount->parity = cnow.parity; ++ icount->brk = cnow.brk; ++ icount->buf_overrun = cnow.buf_overrun; ++ ++ return 0; ++} ++ + /* + * support for 32 bit ioctl calls on 64 bit systems + */ +@@ -1206,10 +1212,6 @@ static long slgt_compat_ioctl(struct tty + case MGSL_IOCSGPIO: + case MGSL_IOCGGPIO: + case MGSL_IOCWAITGPIO: +- case TIOCGICOUNT: +- rc = ioctl(tty, file, cmd, (unsigned long)(compat_ptr(arg))); +- break; +- + case MGSL_IOCSTXIDLE: + case MGSL_IOCTXENABLE: + case MGSL_IOCRXENABLE: +@@ -3642,6 +3644,7 @@ static const struct tty_operations ops = + .hangup = hangup, + .tiocmget = tiocmget, + .tiocmset = tiocmset, ++ .get_icount = get_icount, + .proc_fops = &synclink_gt_proc_fops, + }; + +--- a/drivers/char/synclinkmp.c ++++ b/drivers/char/synclinkmp.c +@@ -1258,10 +1258,6 @@ static int ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) + { + SLMP_INFO *info = tty->driver_data; +- int error; +- struct mgsl_icount cnow; /* kernel counter temps */ +- struct serial_icounter_struct __user *p_cuser; /* user space */ +- unsigned long flags; + void __user *argp = (void __user *)arg; + + if (debug_level >= DEBUG_LEVEL_INFO) +@@ -1272,7 +1268,7 @@ static int ioctl(struct tty_struct *tty, + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && +- (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { ++ (cmd != TIOCMIWAIT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } +@@ -1310,40 +1306,38 @@ static int ioctl(struct tty_struct *tty, + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ +- case TIOCGICOUNT: +- spin_lock_irqsave(&info->lock,flags); +- cnow = info->icount; +- spin_unlock_irqrestore(&info->lock,flags); +- p_cuser = argp; +- PUT_USER(error,cnow.cts, &p_cuser->cts); +- if (error) return error; +- PUT_USER(error,cnow.dsr, &p_cuser->dsr); +- if (error) return error; +- PUT_USER(error,cnow.rng, &p_cuser->rng); +- if (error) return error; +- PUT_USER(error,cnow.dcd, &p_cuser->dcd); +- if (error) return error; +- PUT_USER(error,cnow.rx, &p_cuser->rx); +- if (error) return error; +- PUT_USER(error,cnow.tx, &p_cuser->tx); +- if (error) return error; +- PUT_USER(error,cnow.frame, &p_cuser->frame); +- if (error) return error; +- PUT_USER(error,cnow.overrun, &p_cuser->overrun); +- if (error) return error; +- PUT_USER(error,cnow.parity, &p_cuser->parity); +- if (error) return error; +- PUT_USER(error,cnow.brk, &p_cuser->brk); +- if (error) return error; +- PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun); +- if (error) return error; +- return 0; + default: + return -ENOIOCTLCMD; + } + return 0; + } + ++static int get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount) ++{ ++ SLMP_INFO *info = tty->driver_data; ++ struct mgsl_icount cnow; /* kernel counter temps */ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&info->lock,flags); ++ cnow = info->icount; ++ spin_unlock_irqrestore(&info->lock,flags); ++ ++ icount->cts = cnow.cts; ++ icount->dsr = cnow.dsr; ++ icount->rng = cnow.rng; ++ icount->dcd = cnow.dcd; ++ icount->rx = cnow.rx; ++ icount->tx = cnow.tx; ++ icount->frame = cnow.frame; ++ icount->overrun = cnow.overrun; ++ icount->parity = cnow.parity; ++ icount->brk = cnow.brk; ++ icount->buf_overrun = cnow.buf_overrun; ++ ++ return 0; ++} ++ + /* + * /proc fs routines.... + */ +@@ -3909,6 +3903,7 @@ static const struct tty_operations ops = + .hangup = hangup, + .tiocmget = tiocmget, + .tiocmset = tiocmset, ++ .get_icount = get_icount, + .proc_fops = &synclinkmp_proc_fops, + }; + +--- a/drivers/serial/68360serial.c ++++ b/drivers/serial/68360serial.c +@@ -1381,6 +1381,30 @@ static void send_break(ser_info_t *info, + } + + ++/* ++ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) ++ * Return: write counters to the user passed counter struct ++ * NB: both 1->0 and 0->1 transitions are counted except for ++ * RI where only 0->1 is counted. ++ */ ++static int rs_360_get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount) ++{ ++ ser_info_t *info = (ser_info_t *)tty->driver_data; ++ struct async_icount cnow; ++ ++ local_irq_disable(); ++ cnow = info->state->icount; ++ local_irq_enable(); ++ ++ icount->cts = cnow.cts; ++ icount->dsr = cnow.dsr; ++ icount->rng = cnow.rng; ++ icount->dcd = cnow.dcd; ++ ++ return 0; ++} ++ + static int rs_360_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) + { +@@ -1394,7 +1418,7 @@ static int rs_360_ioctl(struct tty_struc + if (serial_paranoia_check(info, tty->name, "rs_ioctl")) + return -ENODEV; + +- if ((cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { ++ if (cmd != TIOCMIWAIT) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } +@@ -1477,31 +1501,6 @@ static int rs_360_ioctl(struct tty_struc + return 0; + #endif + +- /* +- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) +- * Return: write counters to the user passed counter struct +- * NB: both 1->0 and 0->1 transitions are counted except for +- * RI where only 0->1 is counted. +- */ +- case TIOCGICOUNT: +- local_irq_disable(); +- cnow = info->state->icount; +- local_irq_enable(); +- p_cuser = (struct serial_icounter_struct *) arg; +-/* error = put_user(cnow.cts, &p_cuser->cts); */ +-/* if (error) return error; */ +-/* error = put_user(cnow.dsr, &p_cuser->dsr); */ +-/* if (error) return error; */ +-/* error = put_user(cnow.rng, &p_cuser->rng); */ +-/* if (error) return error; */ +-/* error = put_user(cnow.dcd, &p_cuser->dcd); */ +-/* if (error) return error; */ +- +- put_user(cnow.cts, &p_cuser->cts); +- put_user(cnow.dsr, &p_cuser->dsr); +- put_user(cnow.rng, &p_cuser->rng); +- put_user(cnow.dcd, &p_cuser->dcd); +- return 0; + + default: + return -ENOIOCTLCMD; +--- a/net/bluetooth/rfcomm/tty.c ++++ b/net/bluetooth/rfcomm/tty.c +@@ -844,10 +844,6 @@ static int rfcomm_tty_ioctl(struct tty_s + BT_DBG("TIOCMIWAIT"); + break; + +- case TIOCGICOUNT: +- BT_DBG("TIOCGICOUNT"); +- break; +- + case TIOCGSERIAL: + BT_ERR("TIOCGSERIAL is not supported"); + return -ENOIOCTLCMD; diff --git a/tty/tty-make-tiocgicount-a-handler.patch b/tty/tty-make-tiocgicount-a-handler.patch new file mode 100644 index 00000000000000..063ac964172c6f --- /dev/null +++ b/tty/tty-make-tiocgicount-a-handler.patch @@ -0,0 +1,209 @@ +From linux-kernel-owner@vger.kernel.org Tue Sep 21 14:30:25 2010 +From: Alan Cox <alan@linux.intel.com> +Subject: tty: Make tiocgicount a handler +To: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, + greg@kroah.com, drosenberg@vsecurity.com +Date: Thu, 16 Sep 2010 18:21:24 +0100 +Message-ID: <20100916172113.25987.22944.stgit@localhost.localdomain> + +Dan Rosenberg noted that various drivers return the struct with uncleared +fields. Instead of spending forever trying to stomp all the drivers that +get it wrong (and every new driver) do the job in one place. + +This first patch adds the needed operations and hooks them up, including +the needed USB midlayer and serial core plumbing. + +Signed-off-by: Alan Cox <alan@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/char/tty_io.c | 21 +++++++++++++++++++++ + drivers/serial/serial_core.c | 35 ++++++++++++++++------------------- + drivers/usb/serial/usb-serial.c | 13 +++++++++++++ + include/linux/tty_driver.h | 9 +++++++++ + include/linux/usb/serial.h | 2 ++ + 5 files changed, 61 insertions(+), 19 deletions(-) + +--- a/drivers/char/tty_io.c ++++ b/drivers/char/tty_io.c +@@ -96,6 +96,7 @@ + #include <linux/bitops.h> + #include <linux/delay.h> + #include <linux/seq_file.h> ++#include <linux/serial.h> + + #include <linux/uaccess.h> + #include <asm/system.h> +@@ -2511,6 +2512,20 @@ static int tty_tiocmset(struct tty_struc + return tty->ops->tiocmset(tty, file, set, clear); + } + ++static int tty_tiocgicount(struct tty_struct *tty, void __user *arg) ++{ ++ int retval = -EINVAL; ++ struct serial_icounter_struct icount; ++ memset(&icount, 0, sizeof(icount)); ++ if (tty->ops->get_icount) ++ retval = tty->ops->get_icount(tty, &icount); ++ if (retval != 0) ++ return retval; ++ if (copy_to_user(arg, &icount, sizeof(icount))) ++ return -EFAULT; ++ return 0; ++} ++ + struct tty_struct *tty_pair_get_tty(struct tty_struct *tty) + { + if (tty->driver->type == TTY_DRIVER_TYPE_PTY && +@@ -2631,6 +2646,12 @@ long tty_ioctl(struct file *file, unsign + case TIOCMBIC: + case TIOCMBIS: + return tty_tiocmset(tty, file, cmd, p); ++ case TIOCGICOUNT: ++ retval = tty_tiocgicount(tty, p); ++ /* For the moment allow fall through to the old method */ ++ if (retval != -EINVAL) ++ return retval; ++ break; + case TCFLSH: + switch (arg) { + case TCIFLUSH: +--- a/drivers/serial/serial_core.c ++++ b/drivers/serial/serial_core.c +@@ -1074,10 +1074,10 @@ uart_wait_modem_status(struct uart_state + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ +-static int uart_get_count(struct uart_state *state, +- struct serial_icounter_struct __user *icnt) ++static int uart_get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount) + { +- struct serial_icounter_struct icount; ++ struct uart_state *state = tty->driver_data; + struct uart_icount cnow; + struct uart_port *uport = state->uart_port; + +@@ -1085,19 +1085,19 @@ static int uart_get_count(struct uart_st + memcpy(&cnow, &uport->icount, sizeof(struct uart_icount)); + spin_unlock_irq(&uport->lock); + +- icount.cts = cnow.cts; +- icount.dsr = cnow.dsr; +- icount.rng = cnow.rng; +- icount.dcd = cnow.dcd; +- icount.rx = cnow.rx; +- icount.tx = cnow.tx; +- icount.frame = cnow.frame; +- icount.overrun = cnow.overrun; +- icount.parity = cnow.parity; +- icount.brk = cnow.brk; +- icount.buf_overrun = cnow.buf_overrun; ++ icount->cts = cnow.cts; ++ icount->dsr = cnow.dsr; ++ icount->rng = cnow.rng; ++ icount->dcd = cnow.dcd; ++ icount->rx = cnow.rx; ++ icount->tx = cnow.tx; ++ icount->frame = cnow.frame; ++ icount->overrun = cnow.overrun; ++ icount->parity = cnow.parity; ++ icount->brk = cnow.brk; ++ icount->buf_overrun = cnow.buf_overrun; + +- return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0; ++ return 0; + } + + /* +@@ -1150,10 +1150,6 @@ uart_ioctl(struct tty_struct *tty, struc + case TIOCMIWAIT: + ret = uart_wait_modem_status(state, arg); + break; +- +- case TIOCGICOUNT: +- ret = uart_get_count(state, uarg); +- break; + } + + if (ret != -ENOIOCTLCMD) +@@ -2295,6 +2291,7 @@ static const struct tty_operations uart_ + #endif + .tiocmget = uart_tiocmget, + .tiocmset = uart_tiocmset, ++ .get_icount = uart_get_icount, + #ifdef CONFIG_CONSOLE_POLL + .poll_init = uart_poll_init, + .poll_get_char = uart_poll_get_char, +--- a/drivers/usb/serial/usb-serial.c ++++ b/drivers/usb/serial/usb-serial.c +@@ -519,6 +519,18 @@ static int serial_tiocmset(struct tty_st + return -EINVAL; + } + ++static int serial_get_icount(struct tty_struct *tty, ++ struct serial_icounter_struct *icount) ++{ ++ struct usb_serial_port *port = tty->driver_data; ++ ++ dbg("%s - port %d", __func__, port->number); ++ ++ if (port->serial->type->get_icount) ++ return port->serial->type->get_icount(tty, icount); ++ return -EINVAL; ++} ++ + /* + * We would be calling tty_wakeup here, but unfortunately some line + * disciplines have an annoying habit of calling tty->write from +@@ -1195,6 +1207,7 @@ static const struct tty_operations seria + .chars_in_buffer = serial_chars_in_buffer, + .tiocmget = serial_tiocmget, + .tiocmset = serial_tiocmset, ++ .get_icount = serial_get_icount, + .cleanup = serial_cleanup, + .install = serial_install, + .proc_fops = &serial_proc_fops, +--- a/include/linux/tty_driver.h ++++ b/include/linux/tty_driver.h +@@ -224,6 +224,12 @@ + * unless the tty also has a valid tty->termiox pointer. + * + * Optional: Called under the termios lock ++ * ++ * int (*get_icount)(struct tty_struct *tty, struct serial_icounter *icount); ++ * ++ * Called when the device receives a TIOCGICOUNT ioctl. Passed a kernel ++ * structure to complete. This method is optional and will only be called ++ * if provided (otherwise EINVAL will be returned). + */ + + #include <linux/fs.h> +@@ -232,6 +238,7 @@ + + struct tty_struct; + struct tty_driver; ++struct serial_icounter_struct; + + struct tty_operations { + struct tty_struct * (*lookup)(struct tty_driver *driver, +@@ -268,6 +275,8 @@ struct tty_operations { + unsigned int set, unsigned int clear); + int (*resize)(struct tty_struct *tty, struct winsize *ws); + int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew); ++ int (*get_icount)(struct tty_struct *tty, ++ struct serial_icounter_struct *icount); + #ifdef CONFIG_CONSOLE_POLL + int (*poll_init)(struct tty_driver *driver, int line, char *options); + int (*poll_get_char)(struct tty_driver *driver, int line); +--- a/include/linux/usb/serial.h ++++ b/include/linux/usb/serial.h +@@ -271,6 +271,8 @@ struct usb_serial_driver { + int (*tiocmget)(struct tty_struct *tty, struct file *file); + int (*tiocmset)(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear); ++ int (*get_icount)(struct tty_struct *tty, ++ struct serial_icounter_struct *icount); + /* Called by the tty layer for port level work. There may or may not + be an attached tty at this point */ + void (*dtr_rts)(struct usb_serial_port *port, int on); diff --git a/usb.current/usb-musb-gadget-complete-request-only-if-data-is-transfered-over.patch b/usb.current/usb-musb-gadget-complete-request-only-if-data-is-transfered-over.patch new file mode 100644 index 00000000000000..426849b372af00 --- /dev/null +++ b/usb.current/usb-musb-gadget-complete-request-only-if-data-is-transfered-over.patch @@ -0,0 +1,52 @@ +From balbi@ti.com Tue Sep 21 14:15:18 2010 +From: Ming Lei <tom.leiming@gmail.com> +To: Greg KH <greg@kroah.com> +Cc: Ming Lei <tom.leiming@gmail.com>, + David Brownell <dbrownell@users.sourceforge.net>, + Anand Gadiyar <gadiyar@ti.com>, Mike Frysinger <vapier@gentoo.org>, + Sergei Shtylyov <sshtylyov@ru.mvista.com>, Felipe Balbi <balbi@ti.com> +Subject: usb: musb: gadget: complete request only if data is transfered over +Date: Mon, 20 Sep 2010 10:32:05 +0300 +Message-Id: <1284967927-7163-6-git-send-email-balbi@ti.com> + +From: Ming Lei <tom.leiming@gmail.com> + +Complete the current request only if the data transfer is over. + +Signed-off-by: Ming Lei <tom.leiming@gmail.com> +Cc: David Brownell <dbrownell@users.sourceforge.net> +Cc: Anand Gadiyar <gadiyar@ti.com> +Cc: Mike Frysinger <vapier@gentoo.org> +Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/musb/musb_gadget.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -501,14 +501,14 @@ void musb_g_tx(struct musb *musb, u8 epn + request->zero = 0; + } + +- /* ... or if not, then complete it. */ +- musb_g_giveback(musb_ep, request, 0); +- +- request = musb_ep->desc ? next_request(musb_ep) : NULL; +- if (!request) { +- DBG(4, "%s idle now\n", +- musb_ep->end_point.name); +- return; ++ if (request->actual == request->length) { ++ musb_g_giveback(musb_ep, request, 0); ++ request = musb_ep->desc ? next_request(musb_ep) : NULL; ++ if (!request) { ++ DBG(4, "%s idle now\n", ++ musb_ep->end_point.name); ++ return; ++ } + } + } + diff --git a/usb.current/usb-musb-gadget-enable-autoclear-for-out-transfer-in-both-dma-0-and-dma-1.patch b/usb.current/usb-musb-gadget-enable-autoclear-for-out-transfer-in-both-dma-0-and-dma-1.patch new file mode 100644 index 00000000000000..ef0c63ceb1c5cb --- /dev/null +++ b/usb.current/usb-musb-gadget-enable-autoclear-for-out-transfer-in-both-dma-0-and-dma-1.patch @@ -0,0 +1,58 @@ +From balbi@ti.com Tue Sep 21 14:14:42 2010 +From: Ming Lei <tom.leiming@gmail.com> +To: Greg KH <greg@kroah.com> +Cc: Ming Lei <tom.leiming@gmail.com>, + David Brownell <dbrownell@users.sourceforge.net>, + Anand Gadiyar <gadiyar@ti.com>, Mike Frysinger <vapier@gentoo.org>, + Sergei Shtylyov <sshtylyov@ru.mvista.com>, Felipe Balbi <balbi@ti.com> +Subject: usb: musb: gadget: enable autoclear for OUT transfer in both DMA 0 and DMA 1 +Date: Mon, 20 Sep 2010 10:32:03 +0300 +Message-Id: <1284967927-7163-4-git-send-email-balbi@ti.com> + +From: Ming Lei <tom.leiming@gmail.com> + +This patch fixes one bugs of OUT transfer in double buffer case: + + -the current code only enable autoclear for dma mode 1, and not + for dma mode 0 + +Without this patch, test #5 of usbtest can't be passed if we +configure musb as g_zero and use fifo mode 3 to enable double +buffer mode. + +With this patch and the following patch(fix dma length), +on my beagle B5, test#5(queued bulk out) may go beyond +18Mbyte/s(seems dma mode 0 is quicker in double buffer case) +if musb is configured as g_zero and fifo mode 3 is taken, follows +the test command: + + #./testusb -D DEV_NAME -c 1024 -t 5 -s 32768 -g 8 [1] + +Also I have tested this patch can't make g_ether broken. + +[1],source of testusb : tools/usb/testusb.c under linux kernel; + +Signed-off-by: Ming Lei <tom.leiming@gmail.com> +Cc: David Brownell <dbrownell@users.sourceforge.net> +Cc: Anand Gadiyar <gadiyar@ti.com> +Cc: Mike Frysinger <vapier@gentoo.org> +Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/musb/musb_gadget.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -643,8 +643,8 @@ static void rxstate(struct musb *musb, s + */ + + csr |= MUSB_RXCSR_DMAENAB; +-#ifdef USE_MODE1 + csr |= MUSB_RXCSR_AUTOCLEAR; ++#ifdef USE_MODE1 + /* csr |= MUSB_RXCSR_DMAMODE; */ + + /* this special sequence (enabling and then diff --git a/usb.current/usb-musb-gadget-fix-bulk-in-infinit-hangs-in-double-buffer-case.patch b/usb.current/usb-musb-gadget-fix-bulk-in-infinit-hangs-in-double-buffer-case.patch new file mode 100644 index 00000000000000..7266a7f0477347 --- /dev/null +++ b/usb.current/usb-musb-gadget-fix-bulk-in-infinit-hangs-in-double-buffer-case.patch @@ -0,0 +1,73 @@ +From balbi@ti.com Tue Sep 21 14:13:45 2010 +From: Ming Lei <tom.leiming@gmail.com> +To: Greg KH <greg@kroah.com> +Cc: Ming Lei <tom.leiming@gmail.com>, + David Brownell <dbrownell@users.sourceforge.net>, + Anand Gadiyar <gadiyar@ti.com>, Mike Frysinger <vapier@gentoo.org>, + Sergei Shtylyov <sshtylyov@ru.mvista.com>, Felipe Balbi <balbi@ti.com> +Subject: usb: musb: gadget: fix bulk IN infinit hangs in double buffer case +Date: Mon, 20 Sep 2010 10:32:02 +0300 +Message-Id: <1284967927-7163-3-git-send-email-balbi@ti.com> + +From: Ming Lei <tom.leiming@gmail.com> + +This patch fixes one infinite hang of bulk IN transfer in double buffer +case, the hang can be observed easily by test #6 of usbtest if musb is +configured as g_zero and fifo mode 3 is taken to enable double fifo. + +In fact, the patch only removes the check for non-empty fifo before +loading data from new request into fifo since the check is not correct: + + -in double buffer case, fifo may accommodate more than one packet, + even though it has contained one packet already and is non-empty + + -since last DMA is completed before calling musb_g_tx, it is sure + that fifo may accommodate at least one packet + +Without applying the patch, new requst enqueued from .complte may not +have a chance to be loaded into fifo, then will never be completed and +cause infinite hangs. + +With the patch, on my beagle B5, test#6(queued bulk in) can be passed and +test result may go beyond 33Mbyte/s if musb is configured as g_zero and +fifo mode 3 is taken, follows the test command: + + #testusb -D DEV_NAME -c 1024 -t 6 -s 32768 -g 8 [1] + +[1], + -source of testusb : tools/usb/testusb.c under linux kernel; + +Signed-off-by: Ming Lei <tom.leiming@gmail.com> +Acked-by: Anand Gadiyar <gadiyar@ti.com> +Cc: David Brownell <dbrownell@users.sourceforge.net> +Cc: Anand Gadiyar <gadiyar@ti.com> +Cc: Mike Frysinger <vapier@gentoo.org> +Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/musb/musb_gadget.c | 12 ------------ + 1 file changed, 12 deletions(-) + +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -504,18 +504,6 @@ void musb_g_tx(struct musb *musb, u8 epn + /* ... or if not, then complete it. */ + musb_g_giveback(musb_ep, request, 0); + +- /* +- * Kickstart next transfer if appropriate; +- * the packet that just completed might not +- * be transmitted for hours or days. +- * REVISIT for double buffering... +- * FIXME revisit for stalls too... +- */ +- musb_ep_select(mbase, epnum); +- csr = musb_readw(epio, MUSB_TXCSR); +- if (csr & MUSB_TXCSR_FIFONOTEMPTY) +- return; +- + request = musb_ep->desc ? next_request(musb_ep) : NULL; + if (!request) { + DBG(4, "%s idle now\n", diff --git a/usb.current/usb-musb-gadget-fix-dma-length-for-out-transfer.patch b/usb.current/usb-musb-gadget-fix-dma-length-for-out-transfer.patch new file mode 100644 index 00000000000000..c84bbc7d6e4dc7 --- /dev/null +++ b/usb.current/usb-musb-gadget-fix-dma-length-for-out-transfer.patch @@ -0,0 +1,45 @@ +From balbi@ti.com Tue Sep 21 14:15:02 2010 +From: Ming Lei <tom.leiming@gmail.com> +To: Greg KH <greg@kroah.com> +Cc: Ming Lei <tom.leiming@gmail.com>, + David Brownell <dbrownell@users.sourceforge.net>, + Anand Gadiyar <gadiyar@ti.com>, Mike Frysinger <vapier@gentoo.org>, + Sergei Shtylyov <sshtylyov@ru.mvista.com>, Felipe Balbi <balbi@ti.com> +Subject: usb: musb: gadget: fix DMA length for OUT transfer +Date: Mon, 20 Sep 2010 10:32:04 +0300 +Message-Id: <1284967927-7163-5-git-send-email-balbi@ti.com> + +From: Ming Lei <tom.leiming@gmail.com> + +DMA length should not go beyond the availabe space of request buffer, +so fix it. + +Signed-off-by: Ming Lei <tom.leiming@gmail.com> +Acked-by: Anand Gadiyar <gadiyar@ti.com> +Cc: David Brownell <dbrownell@users.sourceforge.net> +Cc: Anand Gadiyar <gadiyar@ti.com> +Cc: Mike Frysinger <vapier@gentoo.org> +Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/musb/musb_gadget.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -659,10 +659,11 @@ static void rxstate(struct musb *musb, s + if (request->actual < request->length) { + int transfer_size = 0; + #ifdef USE_MODE1 +- transfer_size = min(request->length, ++ transfer_size = min(request->length - request->actual, + channel->max_len); + #else +- transfer_size = len; ++ transfer_size = min(request->length - request->actual, ++ (unsigned)len); + #endif + if (transfer_size <= musb_ep->packet_sz) + musb_ep->dma->desired_mode = 0; diff --git a/usb.current/usb-musb-gadget-fix-dma-length-in-txstate.patch b/usb.current/usb-musb-gadget-fix-dma-length-in-txstate.patch new file mode 100644 index 00000000000000..dbab9c2b61da1c --- /dev/null +++ b/usb.current/usb-musb-gadget-fix-dma-length-in-txstate.patch @@ -0,0 +1,90 @@ +From balbi@ti.com Tue Sep 21 14:15:40 2010 +From: Ming Lei <tom.leiming@gmail.com> +To: Greg KH <greg@kroah.com> +Cc: Ming Lei <tom.leiming@gmail.com>, + David Brownell <dbrownell@users.sourceforge.net>, + Anand Gadiyar <gadiyar@ti.com>, Mike Frysinger <vapier@gentoo.org>, + Sergei Shtylyov <sshtylyov@ru.mvista.com>, Felipe Balbi <balbi@ti.com> +Subject: usb: musb: gadget: fix dma length in txstate +Date: Mon, 20 Sep 2010 10:32:06 +0300 +Message-Id: <1284967927-7163-7-git-send-email-balbi@ti.com> + +From: Ming Lei <tom.leiming@gmail.com> + +DMA length should not go beyond the availabe space +of request buffer, so fix it. + +Also set max_len of cppi dma channel as max size of +int type, so make musb dma handling happier. + +Signed-off-by: Ming Lei <tom.leiming@gmail.com> +Cc: David Brownell <dbrownell@users.sourceforge.net> +Cc: Anand Gadiyar <gadiyar@ti.com> +Cc: Mike Frysinger <vapier@gentoo.org> +Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/musb/cppi_dma.c | 1 + + drivers/usb/musb/musb_gadget.c | 18 +++++++++--------- + 2 files changed, 10 insertions(+), 9 deletions(-) + +--- a/drivers/usb/musb/cppi_dma.c ++++ b/drivers/usb/musb/cppi_dma.c +@@ -322,6 +322,7 @@ cppi_channel_allocate(struct dma_control + index, transmit ? 'T' : 'R', cppi_ch); + cppi_ch->hw_ep = ep; + cppi_ch->channel.status = MUSB_DMA_STATUS_FREE; ++ cppi_ch->channel.max_len = 0x7fffffff; + + DBG(4, "Allocate CPPI%d %cX\n", index, transmit ? 'T' : 'R'); + return &cppi_ch->channel; +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -300,6 +300,11 @@ static void txstate(struct musb *musb, s + #ifndef CONFIG_MUSB_PIO_ONLY + if (is_dma_capable() && musb_ep->dma) { + struct dma_controller *c = musb->dma_controller; ++ size_t request_size; ++ ++ /* setup DMA, then program endpoint CSR */ ++ request_size = min_t(size_t, request->length - request->actual, ++ musb_ep->dma->max_len); + + use_dma = (request->dma != DMA_ADDR_INVALID); + +@@ -307,11 +312,6 @@ static void txstate(struct musb *musb, s + + #ifdef CONFIG_USB_INVENTRA_DMA + { +- size_t request_size; +- +- /* setup DMA, then program endpoint CSR */ +- request_size = min_t(size_t, request->length, +- musb_ep->dma->max_len); + if (request_size < musb_ep->packet_sz) + musb_ep->dma->desired_mode = 0; + else +@@ -373,8 +373,8 @@ static void txstate(struct musb *musb, s + use_dma = use_dma && c->channel_program( + musb_ep->dma, musb_ep->packet_sz, + 0, +- request->dma, +- request->length); ++ request->dma + request->actual, ++ request_size); + if (!use_dma) { + c->channel_release(musb_ep->dma); + musb_ep->dma = NULL; +@@ -386,8 +386,8 @@ static void txstate(struct musb *musb, s + use_dma = use_dma && c->channel_program( + musb_ep->dma, musb_ep->packet_sz, + request->zero, +- request->dma, +- request->length); ++ request->dma + request->actual, ++ request_size); + #endif + } + #endif diff --git a/usb.current/usb-musb-gadget-fix-kernel-panic-if-using-out-ep-with-fifo_txrx-style.patch b/usb.current/usb-musb-gadget-fix-kernel-panic-if-using-out-ep-with-fifo_txrx-style.patch new file mode 100644 index 00000000000000..989e68fcc738bf --- /dev/null +++ b/usb.current/usb-musb-gadget-fix-kernel-panic-if-using-out-ep-with-fifo_txrx-style.patch @@ -0,0 +1,152 @@ +From balbi@ti.com Tue Sep 21 14:13:17 2010 +From: Ming Lei <tom.leiming@gmail.com> +To: Greg KH <greg@kroah.com> +Cc: Ming Lei <tom.leiming@gmail.com>, + David Brownell <dbrownell@users.sourceforge.net>, + Anand Gadiyar <gadiyar@ti.com>, Mike Frysinger <vapier@gentoo.org>, + Sergei Shtylyov <sshtylyov@ru.mvista.com>, stable <stable@kernel.org>, + Felipe Balbi <balbi@ti.com> +Subject: usb: musb: gadget: fix kernel panic if using out ep with FIFO_TXRX style +Date: Mon, 20 Sep 2010 10:32:01 +0300 +Message-Id: <1284967927-7163-2-git-send-email-balbi@ti.com> + +From: Ming Lei <tom.leiming@gmail.com> + +For shared fifo hw endpoint(with FIFO_TXRX style), only ep_in +field of musb_hw_ep is intialized in musb_g_init_endpoints, and +ep_out is not initialized, but musb_g_rx and rxstate may access +ep_out field of musb_hw_ep by the method below: + + musb_ep = &musb->endpoints[epnum].ep_out + +which can cause the kernel panic[1] below, this patch fixes the issue +by getting 'musb_ep' from '&musb->endpoints[epnum].ep_in' for shared fifo +endpoint. + +[1], kernel panic +[root@OMAP3EVM /]# musb_interrupt 1583: ** IRQ peripheral usb0008 tx0000 rx4000 +musb_stage0_irq 460: <== Power=f0, DevCtl=99, int_usb=0x8 +musb_g_rx 772: <== (null), rxcsr 4007 ffffffe8 +musb_g_rx 786: iso overrun on ffffffe8 +Unable to handle kernel NULL pointer dereference at virtual address 00000008 +pgd = c0004000 +[00000008] *pgd=00000000 +Internal error: Oops: 17 [#1] PREEMPT +last sysfs file: /sys/devices/platform/musb_hdrc/usb1/usb_device/usbdev1.1/dev +Modules linked in: g_zero +CPU: 0 Tainted: G W (2.6.35-rc6-gkh-wl+ #92) +PC is at musb_g_rx+0xfc/0x2ec +LR is at vprintk+0x3f4/0x458 +pc : [<c02c07a4>] lr : [<c006ccb0>] psr: 20000193 +sp : c760bd78 ip : c03c9d70 fp : c760bdbc +r10: 00000000 r9 : fa0ab1e0 r8 : 0000000e +r7 : c7e80158 r6 : ffffffe8 r5 : 00000001 r4 : 00004003 +r3 : 00010003 r2 : c760bcd8 r1 : c03cd030 r0 : 0000002e +Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment kernel +Control: 10c5387d Table: 8778c019 DAC: 00000017 +Process kmemleak (pid: 421, stack limit = 0xc760a2e8) +Stack: (0xc760bd78 to 0xc760c000) +bd60: ffffffe8 c04b1b58 +bd80: ffffffe8 c7c01ac0 00000000 c7e80d24 c0084238 00000001 00000001 c7e80158 +bda0: 0000000e 00000008 00000099 000000f0 c760be04 c760bdc0 c02bcd68 c02c06b4 +bdc0: 00000099 00000008 00004000 c760bdd8 c03cc4f8 00000000 00000002 c7e80158 +bde0: c7d2e300 60000193 c760a000 0000005c 00000000 00000000 c760be24 c760be08 +be00: c02bcecc c02bc1ac c7d2e300 c7d2e300 0000005c c760a000 c760be54 c760be28 +be20: c00ad698 c02bce6c 00000000 c7d2e300 c067c258 0000005c c067c294 00000001 +be40: c760a000 00000000 c760be74 c760be58 c00af984 c00ad5fc 0000005c 00000000 +be60: 00000000 00000002 c760be8c c760be78 c0039080 c00af8d0 ffffffff fa200000 +be80: c760beec c760be90 c0039b6c c003900c 00000001 00000000 c7d1e240 00000000 +bea0: 00000000 c068bae8 00000000 60000013 00000001 00000000 00000000 c760beec +bec0: c0064ecc c760bed8 c00ff7d0 c003a0a8 60000013 ffffffff 00000000 c068bae8 +bee0: c760bf24 c760bef0 c00ff7d0 c0064ec4 00000001 00000000 c00ff700 00000000 +bf00: c0087f00 00000000 60000013 c0d76a70 c0e23795 00000001 c760bf4c c760bf28 +bf20: c00ffdd8 c00ff70c c068bb08 c068bae8 60000013 c0100938 c068bb30 00000000 +bf40: c760bf84 c760bf50 c010014c c00ffd84 00000001 00000000 c010000c 00012c00 +bf60: c7c33f04 00012c00 c7c33f04 00000000 c0100938 00000000 c760bf9c c760bf88 +bf80: c01009a8 c0100018 c760bfa8 c7c33f04 c760bff4 c760bfa0 c0088000 c0100944 +bfa0: c760bf98 00000000 00000000 00000001 dead4ead ffffffff ffffffff c08ba2bc +bfc0: 00000000 c049e7fa 00000000 c0087f70 c760bfd0 c760bfd0 c7c33f04 c0087f70 +bfe0: c006f5e8 00000013 00000000 c760bff8 c006f5e8 c0087f7c 7f0004ff df2000ff +Backtrace: +[<c02c06a8>] (musb_g_rx+0x0/0x2ec) from [<c02bcd68>] (musb_interrupt+0xbc8/0xcc0) +[<c02bc1a0>] (musb_interrupt+0x0/0xcc0) from [<c02bcecc>] (generic_interrupt+0x6c/0x84) +[<c02bce60>] (generic_interrupt+0x0/0x84) from [<c00ad698>] (handle_IRQ_event+0xa8/0x1ec) + r7:c760a000 r6:0000005c r5:c7d2e300 r4:c7d2e300 +[<c00ad5f0>] (handle_IRQ_event+0x0/0x1ec) from [<c00af984>] (handle_level_irq+0xc0/0x13c) +[<c00af8c4>] (handle_level_irq+0x0/0x13c) from [<c0039080>] (asm_do_IRQ+0x80/0xa0) + r7:00000002 r6:00000000 r5:00000000 r4:0000005c +[<c0039000>] (asm_do_IRQ+0x0/0xa0) from [<c0039b6c>] (__irq_svc+0x4c/0xb4) +Exception stack(0xc760be90 to 0xc760bed8) +be80: 00000001 00000000 c7d1e240 00000000 +bea0: 00000000 c068bae8 00000000 60000013 00000001 00000000 00000000 c760beec +bec0: c0064ecc c760bed8 c00ff7d0 c003a0a8 60000013 ffffffff + r5:fa200000 r4:ffffffff +[<c0064eb8>] (sub_preempt_count+0x0/0x100) from [<c00ff7d0>] (find_and_get_object+0xd0/0x110) + r5:c068bae8 r4:00000000 +[<c00ff700>] (find_and_get_object+0x0/0x110) from [<c00ffdd8>] (scan_block+0x60/0x104) + r8:00000001 r7:c0e23795 r6:c0d76a70 r5:60000013 r4:00000000 +[<c00ffd78>] (scan_block+0x0/0x104) from [<c010014c>] (kmemleak_scan+0x140/0x484) +[<c010000c>] (kmemleak_scan+0x0/0x484) from [<c01009a8>] (kmemleak_scan_thread+0x70/0xcc) + r8:00000000 r7:c0100938 r6:00000000 r5:c7c33f04 r4:00012c00 +[<c0100938>] (kmemleak_scan_thread+0x0/0xcc) from [<c0088000>] (kthread+0x90/0x98) + r5:c7c33f04 r4:c760bfa8 +[<c0087f70>] (kthread+0x0/0x98) from [<c006f5e8>] (do_exit+0x0/0x684) + r7:00000013 r6:c006f5e8 r5:c0087f70 r4:c7c33f04 +Code: e3002312 e58d6000 e2833e16 eb0422d5 (e5963020) +---[ end trace f3d5e96f75c297b7 ]--- + +Signed-off-by: Ming Lei <tom.leiming@gmail.com> +Reviewed-by: Sergei Shtylyov <sshtylyov@mvista.com> +Cc: David Brownell <dbrownell@users.sourceforge.net> +Cc: Anand Gadiyar <gadiyar@ti.com> +Cc: Mike Frysinger <vapier@gentoo.org> +Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com> +Cc: stable <stable@kernel.org> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/musb/musb_gadget.c | 20 +++++++++++++++++--- + 1 file changed, 17 insertions(+), 3 deletions(-) + +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -568,11 +568,19 @@ static void rxstate(struct musb *musb, s + { + const u8 epnum = req->epnum; + struct usb_request *request = &req->request; +- struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out; ++ struct musb_ep *musb_ep; + void __iomem *epio = musb->endpoints[epnum].regs; + unsigned fifo_count = 0; +- u16 len = musb_ep->packet_sz; ++ u16 len; + u16 csr = musb_readw(epio, MUSB_RXCSR); ++ struct musb_hw_ep *hw_ep = &musb->endpoints[epnum]; ++ ++ if (hw_ep->is_shared_fifo) ++ musb_ep = &hw_ep->ep_in; ++ else ++ musb_ep = &hw_ep->ep_out; ++ ++ len = musb_ep->packet_sz; + + /* We shouldn't get here while DMA is active, but we do... */ + if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) { +@@ -740,9 +748,15 @@ void musb_g_rx(struct musb *musb, u8 epn + u16 csr; + struct usb_request *request; + void __iomem *mbase = musb->mregs; +- struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out; ++ struct musb_ep *musb_ep; + void __iomem *epio = musb->endpoints[epnum].regs; + struct dma_channel *dma; ++ struct musb_hw_ep *hw_ep = &musb->endpoints[epnum]; ++ ++ if (hw_ep->is_shared_fifo) ++ musb_ep = &hw_ep->ep_in; ++ else ++ musb_ep = &hw_ep->ep_out; + + musb_ep_select(mbase, epnum); + diff --git a/usb.current/usb-musb-gadget-restart-request-on-clearing-endpoint-halt.patch b/usb.current/usb-musb-gadget-restart-request-on-clearing-endpoint-halt.patch new file mode 100644 index 00000000000000..4a011b07b3fbe0 --- /dev/null +++ b/usb.current/usb-musb-gadget-restart-request-on-clearing-endpoint-halt.patch @@ -0,0 +1,67 @@ +From 2f3bd798c231e982cc98d38abbda8fe5b2905ced Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov <sshtylyov@ru.mvista.com> +Date: Sat, 11 Sep 2010 13:23:12 -0500 +Subject: usb: musb: gadget: restart request on clearing endpoint halt + +Commit 46034dca515bc4ddca0399ae58106d1f5f0d809f (USB: musb_gadget_ep0: stop +abusing musb_gadget_set_halt()) forgot to restart a queued request after +clearing the endpoint halt feature. This results in a couple of USB resets +while enumerating the file-backed storage gadget due to CSW packet not being +sent for the MODE SENSE(10) command. + +Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> +Cc: stable@kernel.org +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/musb/musb_gadget.c | 2 +- + drivers/usb/musb/musb_gadget.h | 2 ++ + drivers/usb/musb/musb_gadget_ep0.c | 9 +++++++++ + 3 files changed, 12 insertions(+), 1 deletion(-) + +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -1084,7 +1084,7 @@ struct free_record { + /* + * Context: controller locked, IRQs blocked. + */ +-static void musb_ep_restart(struct musb *musb, struct musb_request *req) ++void musb_ep_restart(struct musb *musb, struct musb_request *req) + { + DBG(3, "<== %s request %p len %u on hw_ep%d\n", + req->tx ? "TX/IN" : "RX/OUT", +--- a/drivers/usb/musb/musb_gadget.h ++++ b/drivers/usb/musb/musb_gadget.h +@@ -105,4 +105,6 @@ extern void musb_gadget_cleanup(struct m + + extern void musb_g_giveback(struct musb_ep *, struct usb_request *, int); + ++extern void musb_ep_restart(struct musb *, struct musb_request *); ++ + #endif /* __MUSB_GADGET_H */ +--- a/drivers/usb/musb/musb_gadget_ep0.c ++++ b/drivers/usb/musb/musb_gadget_ep0.c +@@ -261,6 +261,7 @@ __acquires(musb->lock) + ctrlrequest->wIndex & 0x0f; + struct musb_ep *musb_ep; + struct musb_hw_ep *ep; ++ struct musb_request *request; + void __iomem *regs; + int is_in; + u16 csr; +@@ -302,6 +303,14 @@ __acquires(musb->lock) + musb_writew(regs, MUSB_RXCSR, csr); + } + ++ /* Maybe start the first request in the queue */ ++ request = to_musb_request( ++ next_request(musb_ep)); ++ if (!musb_ep->busy && request) { ++ DBG(3, "restarting the request\n"); ++ musb_ep_restart(musb, request); ++ } ++ + /* select ep0 again */ + musb_ep_select(mbase, 0); + } break; diff --git a/usb.current/usb-musb-host-issue-a-memory-barrier-before-starting-dma.patch b/usb.current/usb-musb-host-issue-a-memory-barrier-before-starting-dma.patch new file mode 100644 index 00000000000000..cdeb2fb176eb65 --- /dev/null +++ b/usb.current/usb-musb-host-issue-a-memory-barrier-before-starting-dma.patch @@ -0,0 +1,51 @@ +From balbi@ti.com Tue Sep 21 14:16:02 2010 +From: Santosh Shilimkar <santosh.shilimkar@ti.com> +To: Greg KH <greg@kroah.com> +Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>, + Maulik Mankad <x0082077@ti.com>, + Russell King <rmk+kernel@arm.linux.org.uk>, + Felipe Balbi <balbi@ti.com> +Subject: usb: musb: host: Issue a memory barrier before starting DMA +Date: Mon, 20 Sep 2010 10:32:07 +0300 +Message-Id: <1284967927-7163-8-git-send-email-balbi@ti.com> + +From: Santosh Shilimkar <santosh.shilimkar@ti.com> + +This patch fixes the issue which was observed while transfering +a large file ( > 20MB) over USB (OMAP MUSB controller acts as USB host) +to an attached USB thumb drive. + +It was found that CDB field of CBW packet was set to 0x0. This was +due to missing a barrier before DMA engine starts transfer. +This buffer is allocated using dma_alloc_coherent which gives +non-cacheble but bufferable memory and hence needed a write +memory barrier to flush the write buffer. + +More info on this thread is here: + http://www.spinics.net/lists/linux-omap/msg33987.html + +Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> +Signed-off-by: Maulik Mankad <x0082077@ti.com> +Cc: Russell King <rmk+kernel@arm.linux.org.uk> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/musb/musb_host.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -660,6 +660,12 @@ static bool musb_tx_dma_program(struct d + + qh->segsize = length; + ++ /* ++ * Ensure the data reaches to main memory before starting ++ * DMA transfer ++ */ ++ wmb(); ++ + if (!dma->channel_program(channel, pkt_size, mode, + urb->transfer_dma + offset, length)) { + dma->channel_release(channel); diff --git a/usb/revert-usb-ncm-added-ncm.h-with-auxiliary-definitions.patch b/usb/revert-usb-ncm-added-ncm.h-with-auxiliary-definitions.patch new file mode 100644 index 00000000000000..af9c0cc08f3d83 --- /dev/null +++ b/usb/revert-usb-ncm-added-ncm.h-with-auxiliary-definitions.patch @@ -0,0 +1,139 @@ +From ykaliuta@etselop.research.nokia.com Tue Sep 21 15:28:52 2010 +From: yauheni.kaliuta@nokia.com +To: linux-usb@vger.kernel.org +Cc: greg@kroah.com, <hans.petter.selasky@stericsson.com> +Subject: Revert "USB: ncm: added ncm.h with auxiliary definitions" +Date: Mon, 20 Sep 2010 15:40:27 +0300 +Message-Id: <1284986428-18195-3-git-send-email-yauheni.kaliuta@nokia.com> + +From: Yauheni Kaliuta <yauheni.kaliuta@nokia.com> + +This reverts commit 65e0b499105ec8ff3bc4ab7680873dec20127f9d. + +Since the host and gadget implementations are different, there is +no common code for the file, remove for now. + +Signed-off-by: Yauheni Kaliuta <yauheni.kaliuta@nokia.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + include/linux/usb/ncm.h | 114 ------------------------------------------------ + 1 file changed, 114 deletions(-) + +--- a/include/linux/usb/ncm.h ++++ /dev/null +@@ -1,114 +0,0 @@ +-/* +- * USB CDC NCM auxiliary definitions +- */ +- +-#ifndef __LINUX_USB_NCM_H +-#define __LINUX_USB_NCM_H +- +-#include <linux/types.h> +-#include <linux/usb/cdc.h> +-#include <asm/unaligned.h> +- +-#define NCM_NTB_MIN_IN_SIZE 2048 +-#define NCM_NTB_MIN_OUT_SIZE 2048 +- +-#define NCM_CONTROL_TIMEOUT (5 * 1000) +- +-/* bmNetworkCapabilities */ +- +-#define NCM_NCAP_ETH_FILTER (1 << 0) +-#define NCM_NCAP_NET_ADDRESS (1 << 1) +-#define NCM_NCAP_ENCAP_COMM (1 << 2) +-#define NCM_NCAP_MAX_DGRAM (1 << 3) +-#define NCM_NCAP_CRC_MODE (1 << 4) +- +-/* +- * Here are options for NCM Datagram Pointer table (NDP) parser. +- * There are 2 different formats: NDP16 and NDP32 in the spec (ch. 3), +- * in NDP16 offsets and sizes fields are 1 16bit word wide, +- * in NDP32 -- 2 16bit words wide. Also signatures are different. +- * To make the parser code the same, put the differences in the structure, +- * and switch pointers to the structures when the format is changed. +- */ +- +-struct ndp_parser_opts { +- u32 nth_sign; +- u32 ndp_sign; +- unsigned nth_size; +- unsigned ndp_size; +- unsigned ndplen_align; +- /* sizes in u16 units */ +- unsigned dgram_item_len; /* index or length */ +- unsigned block_length; +- unsigned fp_index; +- unsigned reserved1; +- unsigned reserved2; +- unsigned next_fp_index; +-}; +- +-#define INIT_NDP16_OPTS { \ +- .nth_sign = NCM_NTH16_SIGN, \ +- .ndp_sign = NCM_NDP16_NOCRC_SIGN, \ +- .nth_size = sizeof(struct usb_cdc_ncm_nth16), \ +- .ndp_size = sizeof(struct usb_cdc_ncm_ndp16), \ +- .ndplen_align = 4, \ +- .dgram_item_len = 1, \ +- .block_length = 1, \ +- .fp_index = 1, \ +- .reserved1 = 0, \ +- .reserved2 = 0, \ +- .next_fp_index = 1, \ +- } +- +- +-#define INIT_NDP32_OPTS { \ +- .nth_sign = NCM_NTH32_SIGN, \ +- .ndp_sign = NCM_NDP32_NOCRC_SIGN, \ +- .nth_size = sizeof(struct usb_cdc_ncm_nth32), \ +- .ndp_size = sizeof(struct usb_cdc_ncm_ndp32), \ +- .ndplen_align = 8, \ +- .dgram_item_len = 2, \ +- .block_length = 2, \ +- .fp_index = 2, \ +- .reserved1 = 1, \ +- .reserved2 = 2, \ +- .next_fp_index = 2, \ +- } +- +-static inline void put_ncm(__le16 **p, unsigned size, unsigned val) +-{ +- switch (size) { +- case 1: +- put_unaligned_le16((u16)val, *p); +- break; +- case 2: +- put_unaligned_le32((u32)val, *p); +- +- break; +- default: +- BUG(); +- } +- +- *p += size; +-} +- +-static inline unsigned get_ncm(__le16 **p, unsigned size) +-{ +- unsigned tmp; +- +- switch (size) { +- case 1: +- tmp = get_unaligned_le16(*p); +- break; +- case 2: +- tmp = get_unaligned_le32(*p); +- break; +- default: +- BUG(); +- } +- +- *p += size; +- return tmp; +-} +- +-#endif /* __LINUX_USB_NCM_H */ diff --git a/usb/usb-atmel_usba_udc-force-vbus_pin-at-einval-when-gpio_request-failled.patch b/usb/usb-atmel_usba_udc-force-vbus_pin-at-einval-when-gpio_request-failled.patch new file mode 100644 index 00000000000000..9ca716dead748b --- /dev/null +++ b/usb/usb-atmel_usba_udc-force-vbus_pin-at-einval-when-gpio_request-failled.patch @@ -0,0 +1,32 @@ +From linux-usb-owner@vger.kernel.org Tue Sep 21 15:31:25 2010 +From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> +To: linux-arm-kernel@lists.infradead.org +Cc: linux-usb@vger.kernel.org, + Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>, + Nicolas Ferre <nicolas.ferre@atmel.com> +Subject: USB: atmel_usba_udc: force vbus_pin at -EINVAL when gpio_request failled +Date: Mon, 20 Sep 2010 18:31:07 +0200 +Message-Id: <1285000267-22964-1-git-send-email-plagnioj@jcrosoft.com> + +to ensure gpio_is_valid return false + +Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> +Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/gadget/atmel_usba_udc.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/gadget/atmel_usba_udc.c ++++ b/drivers/usb/gadget/atmel_usba_udc.c +@@ -2015,6 +2015,9 @@ static int __init usba_udc_probe(struct + } else { + disable_irq(gpio_to_irq(udc->vbus_pin)); + } ++ } else { ++ /* gpio_request fail so use -EINVAL for gpio_is_valid */ ++ ubc->vbus_pin = -EINVAL; + } + } + diff --git a/usb/usb-cdc.h-ncm-add-missed-constants-and-structures.patch b/usb/usb-cdc.h-ncm-add-missed-constants-and-structures.patch new file mode 100644 index 00000000000000..8e047c4401824b --- /dev/null +++ b/usb/usb-cdc.h-ncm-add-missed-constants-and-structures.patch @@ -0,0 +1,110 @@ +From linux-usb-owner@vger.kernel.org Tue Sep 21 15:29:47 2010 +From: yauheni.kaliuta@nokia.com +To: linux-usb@vger.kernel.org +Cc: greg@kroah.com, <hans.petter.selasky@stericsson.com> +Subject: USB: cdc.h: ncm: add missed constants and structures +Date: Mon, 20 Sep 2010 15:40:28 +0300 +Message-Id: <1284986428-18195-4-git-send-email-yauheni.kaliuta@nokia.com> + +From: Yauheni Kaliuta <yauheni.kaliuta@nokia.com> + +Make a dedicated structure for datagram pointer entry. There is no +explicit declaration in the spec, but it's used by the host +implementation and makes the structure more clear. + +Add some missed constants from the spec + +Signed-off-by: Yauheni Kaliuta <yauheni.kaliuta@nokia.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + include/linux/usb/cdc.h | 57 ++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 55 insertions(+), 2 deletions(-) + +--- a/include/linux/usb/cdc.h ++++ b/include/linux/usb/cdc.h +@@ -32,6 +32,8 @@ + + #define USB_CDC_PROTO_EEM 7 + ++#define USB_CDC_NCM_PROTO_NTB 1 ++ + /*-------------------------------------------------------------------------*/ + + /* +@@ -325,14 +327,26 @@ struct usb_cdc_ncm_nth32 { + #define USB_CDC_NCM_NDP32_CRC_SIGN 0x316D636E /* ncm1 */ + #define USB_CDC_NCM_NDP32_NOCRC_SIGN 0x306D636E /* ncm0 */ + ++/* 16-bit NCM Datagram Pointer Entry */ ++struct usb_cdc_ncm_dpe16 { ++ __le16 wDatagramIndex; ++ __le16 wDatagramLength; ++} __attribute__((__packed__)); ++ + /* 16-bit NCM Datagram Pointer Table */ + struct usb_cdc_ncm_ndp16 { + __le32 dwSignature; + __le16 wLength; + __le16 wNextFpIndex; +- __u8 data[0]; ++ struct usb_cdc_ncm_dpe16 dpe16[0]; + } __attribute__ ((packed)); + ++/* 32-bit NCM Datagram Pointer Entry */ ++struct usb_cdc_ncm_dpe32 { ++ __le32 wDatagramIndex; ++ __le32 wDatagramLength; ++} __attribute__((__packed__)); ++ + /* 32-bit NCM Datagram Pointer Table */ + struct usb_cdc_ncm_ndp32 { + __le32 dwSignature; +@@ -340,7 +354,46 @@ struct usb_cdc_ncm_ndp32 { + __le16 wReserved6; + __le32 dwNextNdpIndex; + __le32 dwReserved12; +- __u8 data[0]; ++ struct usb_cdc_ncm_dpe32 dpe32[0]; + } __attribute__ ((packed)); + ++/* CDC NCM subclass 3.2.1 and 3.2.2 */ ++#define USB_CDC_NCM_NDP16_INDEX_MIN 0x000C ++#define USB_CDC_NCM_NDP32_INDEX_MIN 0x0010 ++ ++/* CDC NCM subclass 3.3.3 Datagram Formatting */ ++#define USB_CDC_NCM_DATAGRAM_FORMAT_CRC 0x30 ++#define USB_CDC_NCM_DATAGRAM_FORMAT_NOCRC 0X31 ++ ++/* CDC NCM subclass 4.2 NCM Communications Interface Protocol Code */ ++#define USB_CDC_NCM_PROTO_CODE_NO_ENCAP_COMMANDS 0x00 ++#define USB_CDC_NCM_PROTO_CODE_EXTERN_PROTO 0xFE ++ ++/* CDC NCM subclass 5.2.1 NCM Functional Descriptor, bmNetworkCapabilities */ ++#define USB_CDC_NCM_NCAP_ETH_FILTER (1 << 0) ++#define USB_CDC_NCM_NCAP_NET_ADDRESS (1 << 1) ++#define USB_CDC_NCM_NCAP_ENCAP_COMMAND (1 << 2) ++#define USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE (1 << 3) ++#define USB_CDC_NCM_NCAP_CRC_MODE (1 << 4) ++ ++/* CDC NCM subclass Table 6-3: NTB Parameter Structure */ ++#define USB_CDC_NCM_NTB16_SUPPORTED (1 << 0) ++#define USB_CDC_NCM_NTB32_SUPPORTED (1 << 1) ++ ++/* CDC NCM subclass Table 6-3: NTB Parameter Structure */ ++#define USB_CDC_NCM_NDP_ALIGN_MIN_SIZE 0x04 ++#define USB_CDC_NCM_NTB_MAX_LENGTH 0x1C ++ ++/* CDC NCM subclass 6.2.5 SetNtbFormat */ ++#define USB_CDC_NCM_NTB16_FORMAT 0x00 ++#define USB_CDC_NCM_NTB32_FORMAT 0x01 ++ ++/* CDC NCM subclass 6.2.7 SetNtbInputSize */ ++#define USB_CDC_NCM_NTB_MIN_IN_SIZE 2048 ++#define USB_CDC_NCM_NTB_MIN_OUT_SIZE 2048 ++ ++/* CDC NCM subclass 6.2.11 SetCrcMode */ ++#define USB_CDC_NCM_CRC_NOT_APPENDED 0x00 ++#define USB_CDC_NCM_CRC_APPENDED 0x01 ++ + #endif /* __LINUX_USB_CDC_H */ diff --git a/usb/usb-cdc.h-ncm-typo-and-style-fixes.patch b/usb/usb-cdc.h-ncm-typo-and-style-fixes.patch new file mode 100644 index 00000000000000..53096221a092a1 --- /dev/null +++ b/usb/usb-cdc.h-ncm-typo-and-style-fixes.patch @@ -0,0 +1,85 @@ +From linux-usb-owner@vger.kernel.org Tue Sep 21 15:27:23 2010 +From: yauheni.kaliuta@nokia.com +Cc: greg@kroah.com, <hans.petter.selasky@stericsson.com> +Subject: USB: cdc.h: ncm: typo and style fixes +Date: Mon, 20 Sep 2010 15:40:26 +0300 +Message-Id: <1284986428-18195-2-git-send-email-yauheni.kaliuta@nokia.com> + +From: Yauheni Kaliuta <yauheni.kaliuta@nokia.com> + +Some typos were in the initial commit, make the spelling +according to the spec. + +Add some more comments. + +Also change constant names according to the style of the rest +of the file + +Signed-off-by: Yauheni Kaliuta <yauheni.kaliuta@nokia.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + include/linux/usb/cdc.h | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +--- a/include/linux/usb/cdc.h ++++ b/include/linux/usb/cdc.h +@@ -274,13 +274,13 @@ struct usb_cdc_notification { + /* + * Class Specific structures and constants + * +- * CDC NCM parameter structure, CDC NCM subclass 6.2.1 ++ * CDC NCM NTB parameters structure, CDC NCM subclass 6.2.1 + * + */ + +-struct usb_cdc_ncm_ntb_parameter { ++struct usb_cdc_ncm_ntb_parameters { + __le16 wLength; +- __le16 bmNtbFormatSupported; ++ __le16 bmNtbFormatsSupported; + __le32 dwNtbInMaxSize; + __le16 wNdpInDivisor; + __le16 wNdpInPayloadRemainder; +@@ -297,8 +297,8 @@ struct usb_cdc_ncm_ntb_parameter { + * CDC NCM transfer headers, CDC NCM subclass 3.2 + */ + +-#define NCM_NTH16_SIGN 0x484D434E /* NCMH */ +-#define NCM_NTH32_SIGN 0x686D636E /* ncmh */ ++#define USB_CDC_NCM_NTH16_SIGN 0x484D434E /* NCMH */ ++#define USB_CDC_NCM_NTH32_SIGN 0x686D636E /* ncmh */ + + struct usb_cdc_ncm_nth16 { + __le32 dwSignature; +@@ -320,11 +320,12 @@ struct usb_cdc_ncm_nth32 { + * CDC NCM datagram pointers, CDC NCM subclass 3.3 + */ + +-#define NCM_NDP16_CRC_SIGN 0x314D434E /* NCM1 */ +-#define NCM_NDP16_NOCRC_SIGN 0x304D434E /* NCM0 */ +-#define NCM_NDP32_CRC_SIGN 0x316D636E /* ncm1 */ +-#define NCM_NDP32_NOCRC_SIGN 0x306D636E /* ncm0 */ ++#define USB_CDC_NCM_NDP16_CRC_SIGN 0x314D434E /* NCM1 */ ++#define USB_CDC_NCM_NDP16_NOCRC_SIGN 0x304D434E /* NCM0 */ ++#define USB_CDC_NCM_NDP32_CRC_SIGN 0x316D636E /* ncm1 */ ++#define USB_CDC_NCM_NDP32_NOCRC_SIGN 0x306D636E /* ncm0 */ + ++/* 16-bit NCM Datagram Pointer Table */ + struct usb_cdc_ncm_ndp16 { + __le32 dwSignature; + __le16 wLength; +@@ -332,11 +333,12 @@ struct usb_cdc_ncm_ndp16 { + __u8 data[0]; + } __attribute__ ((packed)); + ++/* 32-bit NCM Datagram Pointer Table */ + struct usb_cdc_ncm_ndp32 { + __le32 dwSignature; + __le16 wLength; + __le16 wReserved6; +- __le32 dwNextFpIndex; ++ __le32 dwNextNdpIndex; + __le32 dwReserved12; + __u8 data[0]; + } __attribute__ ((packed)); diff --git a/usb/usb-cp210x-add-renesas-rx-stick-device-id.patch b/usb/usb-cp210x-add-renesas-rx-stick-device-id.patch new file mode 100644 index 00000000000000..4bc25ea7acc190 --- /dev/null +++ b/usb/usb-cp210x-add-renesas-rx-stick-device-id.patch @@ -0,0 +1,51 @@ +From linux-usb-owner@vger.kernel.org Tue Sep 21 14:18:16 2010 +Date: Fri, 17 Sep 2010 11:09:06 -0400 +Message-Id: <201009171509.o8HF96DL013464@envy.delorie.com> +From: DJ Delorie <dj@delorie.com> +To: Greg Kroah-Hartman <gregkh@suse.de>, + Johan Hovold <jhovold@gmail.com>, + Alan Cox <alan@linux.intel.com>, + Craig Shelley <craig@microtron.org.uk>, + linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org +CC: dj@delorie.com +Subject: USB: cp210x: Add Renesas RX-Stick device ID + +RX610 development board by Renesas + +Bus 001 Device 024: ID 045b:0053 Hitachi, Ltd +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.10 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x045b Hitachi, Ltd + idProduct 0x0053 + bcdDevice 1.00 + iManufacturer 1 Silicon Labs + iProduct 2 RX-Stick + iSerial 3 0001 + . . . + +http://am.renesas.com/rx610stick + +Signed-off-by: DJ Delorie <dj@delorie.com> +Cc: stable <stable@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/cp210x.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -54,6 +54,7 @@ static int cp210x_carrier_raised(struct + static int debug; + + static const struct usb_device_id id_table[] = { ++ { USB_DEVICE(0x045B, 0x0053) }, /* Renesas RX610 RX-Stick */ + { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */ + { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ + { USB_DEVICE(0x0489, 0xE003) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ diff --git a/usb/usb-ftdi_sio-revert-usb-ftdi_sio-fix-dtr-rts-line-modes.patch b/usb/usb-ftdi_sio-revert-usb-ftdi_sio-fix-dtr-rts-line-modes.patch new file mode 100644 index 00000000000000..1a692127156357 --- /dev/null +++ b/usb/usb-ftdi_sio-revert-usb-ftdi_sio-fix-dtr-rts-line-modes.patch @@ -0,0 +1,57 @@ +From jhovold@gmail.com Tue Sep 21 15:33:57 2010 +From: Johan Hovold <jhovold@gmail.com> +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: Alan Cox <alan@linux.intel.com>, + Alan Stern <stern@rowland.harvard.edu>, Dave Mielke <dave@mielke.cc>, + Daniel Mack <daniel@caiaq.de>, Johan Hovold <jhovold@gmail.com>, + stable <stable@kernel.org> +Subject: USB: ftdi_sio: revert "USB: ftdi_sio: fix DTR/RTS line modes" +Date: Sun, 12 Sep 2010 16:31:45 +0200 +Message-Id: <1284301905-684-1-git-send-email-jhovold@gmail.com> + +This reverts commit 6a1a82df91fa0eb1cc76069a9efe5714d087eccd. + +RTS and DTR should not be modified based on CRTSCTS when calling +set_termios. + +Modem control lines are raised at port open by the tty layer and should stay +raised regardless of whether hardware flow control is enabled or not. + +This is in conformance with the way serial ports work today and many +applications depend on this behaviour to be able to talk to hardware +implementing hardware flow control (without the applications actually using +it). + +Hardware which expects different behaviour on these lines can always +use TIOCMSET/TIOCMBI[SC] after port open to change them. + +Reported-by: Daniel Mack <daniel@caiaq.de> +Reported-by: Dave Mielke <dave@mielke.cc> +Signed-off-by: Johan Hovold <jhovold@gmail.com> +Cc: stable <stable@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/ftdi_sio.c | 4 ---- + 1 file changed, 4 deletions(-) + +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -2029,8 +2029,6 @@ static void ftdi_set_termios(struct tty_ + "urb failed to set to rts/cts flow control\n"); + } + +- /* raise DTR/RTS */ +- set_mctrl(port, TIOCM_DTR | TIOCM_RTS); + } else { + /* + * Xon/Xoff code +@@ -2078,8 +2076,6 @@ static void ftdi_set_termios(struct tty_ + } + } + +- /* lower DTR/RTS */ +- clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); + } + return; + } diff --git a/usb/usb-gadget-don-t-save-bind-callback-in-struct-usb_gadget_driver.patch b/usb/usb-gadget-don-t-save-bind-callback-in-struct-usb_gadget_driver.patch index 96fc71f65726e1..f1c3666c64b9cb 100644 --- a/usb/usb-gadget-don-t-save-bind-callback-in-struct-usb_gadget_driver.patch +++ b/usb/usb-gadget-don-t-save-bind-callback-in-struct-usb_gadget_driver.patch @@ -980,7 +980,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> module_exit(udc_exit); --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c -@@ -1696,9 +1696,11 @@ void musb_gadget_cleanup(struct musb *mu +@@ -1699,9 +1699,11 @@ void musb_gadget_cleanup(struct musb *mu * -ENOMEM no memeory to perform the operation * * @param driver the gadget driver @@ -993,7 +993,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> { int retval; unsigned long flags; -@@ -1706,8 +1708,7 @@ int usb_gadget_register_driver(struct us +@@ -1709,8 +1711,7 @@ int usb_gadget_register_driver(struct us if (!driver || driver->speed != USB_SPEED_HIGH @@ -1003,7 +1003,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> return -EINVAL; /* driver must be initialized to support peripheral mode */ -@@ -1735,7 +1736,7 @@ int usb_gadget_register_driver(struct us +@@ -1738,7 +1739,7 @@ int usb_gadget_register_driver(struct us spin_unlock_irqrestore(&musb->lock, flags); if (retval == 0) { diff --git a/usb/usb-option-add-new-onda-vendor-id-and-product-id-for-onda-mt825up.patch b/usb/usb-option-add-new-onda-vendor-id-and-product-id-for-onda-mt825up.patch new file mode 100644 index 00000000000000..4bb83af0b5eec4 --- /dev/null +++ b/usb/usb-option-add-new-onda-vendor-id-and-product-id-for-onda-mt825up.patch @@ -0,0 +1,56 @@ +From linux-usb-owner@vger.kernel.org Tue Sep 21 14:18:37 2010 +Date: Fri, 17 Sep 2010 10:54:23 +0200 (CEST) +From: Enrico Mioso <mrkiko.rs@gmail.com> +To: smurf@smurf.noris.de +cc: gregkh@suse.de, Luca Lazzarin <luca.lazzarin@gmail.com>, + linux-usb@vger.kernel.org +Subject: USB: option: Add new ONDA vendor id and product id for ONDA MT825UP +Message-ID: <alpine.DEB.2.00.1009171047150.13442@atlantide2> + +From: Enrico Mioso <mrkiko.rs@gmail.com> + +This patch, adds to the option driver the Onda Communication +(http://www.ondacommunication.com) vendor id, and the MT825UP modem +device id. + +Note that many variants of this same device are being release here in +Italy (at least one or two per telephony operator). + +These devices are perfectly equivalent except for some predefined +settings (which can be changed of course). + +It should be noted that most ONDA devices are allready supported (they +used other vendor's ids in the past). The patch seems working fine here, +and the rest of the driver seems uninfluenced. + +Signed-off-by: Enrico Mioso <mrkiko.rs@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + drivers/usb/serial/option.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -392,6 +392,12 @@ static void option_instat_callback(struc + #define CELOT_VENDOR_ID 0x211f + #define CELOT_PRODUCT_CT680M 0x6801 + ++/* ONDA Communication vendor id */ ++#define ONDA_VENDOR_ID 0x1ee8 ++ ++/* ONDA MT825UP HSDPA 14.2 modem */ ++#define ONDA_MT825UP 0x000b ++ + /* some devices interfaces need special handling due to a number of reasons */ + enum option_blacklist_reason { + OPTION_BLACKLIST_NONE = 0, +@@ -942,6 +948,7 @@ static const struct usb_device_id option + { USB_DEVICE(CINTERION_VENDOR_ID, 0x0047) }, + { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) }, + { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */ ++ { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */ + { } /* Terminating entry */ + }; + MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/usb/usb-serial-enable-usb-autosuspend-by-default-on-qcserial.patch b/usb/usb-serial-enable-usb-autosuspend-by-default-on-qcserial.patch new file mode 100644 index 00000000000000..a92df2ffd55e1e --- /dev/null +++ b/usb/usb-serial-enable-usb-autosuspend-by-default-on-qcserial.patch @@ -0,0 +1,28 @@ +From mjg@redhat.com Tue Sep 21 15:31:46 2010 +From: Matthew Garrett <mjg@redhat.com> +To: gregkh@suse.de +Cc: linux-usb@vger.kernel.org, Matthew Garrett <mjg@redhat.com> +Subject: USB: serial: Enable USB autosuspend by default on qcserial +Date: Thu, 16 Sep 2010 14:00:51 -0400 +Message-Id: <1284660051-28195-1-git-send-email-mjg@redhat.com> + +Seems to work fine in my testing. + +Signed-off-by: Matthew Garrett <mjg@redhat.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/qcserial.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/usb/serial/qcserial.c ++++ b/drivers/usb/serial/qcserial.c +@@ -118,6 +118,8 @@ static int qcprobe(struct usb_serial *se + + spin_lock_init(&data->susp_lock); + ++ usb_enable_autosuspend(serial->dev); ++ + switch (nintf) { + case 1: + /* QDL mode */ |
