From: Greg Kroah-Hartman Date: Tue, 15 Jan 2013 22:35:58 +0000 (-0800) Subject: 3.4-stable patches X-Git-Tag: v3.7.3~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=85c9f5f6912966aebc64d766b04672e287dde95c;p=thirdparty%2Fkernel%2Fstable-queue.git 3.4-stable patches added patches: staging-comedi-don-t-hijack-hardware-device-private-data.patch usb-fix-endpoint-disabling-for-failed-config-changes.patch --- diff --git a/queue-3.4/series b/queue-3.4/series index ce7dbb067d3..c968adcc4f6 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -166,4 +166,6 @@ ceph-don-t-add-dirty-inode-to-dirty-list-if-caps-is-in-migration.patch ceph-fix-__ceph_do_pending_vmtruncate.patch ceph-call-handle_cap_grant-for-cap-import-message.patch libceph-unlock-unprocessed-pages-in-start_read-error-path.patch +staging-comedi-don-t-hijack-hardware-device-private-data.patch staging-comedi-kconfig-comedi_ni_at_a2150-should-select-comedi_fc.patch +usb-fix-endpoint-disabling-for-failed-config-changes.patch diff --git a/queue-3.4/staging-comedi-don-t-hijack-hardware-device-private-data.patch b/queue-3.4/staging-comedi-don-t-hijack-hardware-device-private-data.patch new file mode 100644 index 00000000000..1d37ef7c8ca --- /dev/null +++ b/queue-3.4/staging-comedi-don-t-hijack-hardware-device-private-data.patch @@ -0,0 +1,156 @@ +From c43435d7722134ed1fda58ce1025f41029bd58ad Mon Sep 17 00:00:00 2001 +From: Ian Abbott +Date: Fri, 30 Mar 2012 17:14:58 +0100 +Subject: staging: comedi: don't hijack hardware device private data + +From: Ian Abbott + +commit c43435d7722134ed1fda58ce1025f41029bd58ad upstream. + +comedi_auto_config() associates a Comedi minor device number with an +auto-configured hardware device and comedi_auto_unconfig() disassociates +it. Currently, these use the hardware device's private data pointer to +point to some allocated storage holding the minor device number. This +is a bit of a waste of the hardware device's private data pointer, +preventing it from being used for something more useful by the low-level +comedi device drivers. For example, it would make more sense if +comedi_usb_auto_config() was passed a pointer to the struct +usb_interface instead of the struct usb_device, but this cannot be done +currently because the low-level comedi drivers already use the private +data pointer in the struct usb_interface for something more useful. + +This patch stops the comedi core hijacking the hardware device's private +data pointer. Instead, comedi_auto_config() stores a pointer to the +hardware device's struct device in the struct comedi_device_file_info +associated with the minor device number, and comedi_auto_unconfig() +calls new function comedi_find_board_minor() to recover the minor device +number associated with the hardware device. + +Signed-off-by: Ian Abbott +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/comedi/comedi_fops.c | 18 ++++++++++++++++++ + drivers/staging/comedi/comedidev.h | 1 + + drivers/staging/comedi/drivers.c | 34 ++++++++++------------------------ + drivers/staging/comedi/internal.h | 1 + + 4 files changed, 30 insertions(+), 24 deletions(-) + +--- a/drivers/staging/comedi/comedi_fops.c ++++ b/drivers/staging/comedi/comedi_fops.c +@@ -2210,6 +2210,7 @@ int comedi_alloc_board_minor(struct devi + kfree(info); + return -ENOMEM; + } ++ info->hardware_device = hardware_device; + comedi_device_init(info->device); + spin_lock_irqsave(&comedi_file_info_table_lock, flags); + for (i = 0; i < COMEDI_NUM_BOARD_MINORS; ++i) { +@@ -2298,6 +2299,23 @@ void comedi_free_board_minor(unsigned mi + } + } + ++int comedi_find_board_minor(struct device *hardware_device) ++{ ++ int minor; ++ struct comedi_device_file_info *info; ++ ++ for (minor = 0; minor < COMEDI_NUM_BOARD_MINORS; minor++) { ++ spin_lock(&comedi_file_info_table_lock); ++ info = comedi_file_info_table[minor]; ++ if (info && info->hardware_device == hardware_device) { ++ spin_unlock(&comedi_file_info_table_lock); ++ return minor; ++ } ++ spin_unlock(&comedi_file_info_table_lock); ++ } ++ return -ENODEV; ++} ++ + int comedi_alloc_subdevice_minor(struct comedi_device *dev, + struct comedi_subdevice *s) + { +--- a/drivers/staging/comedi/comedidev.h ++++ b/drivers/staging/comedi/comedidev.h +@@ -234,6 +234,7 @@ struct comedi_device_file_info { + struct comedi_device *device; + struct comedi_subdevice *read_subdevice; + struct comedi_subdevice *write_subdevice; ++ struct device *hardware_device; + }; + + #ifdef CONFIG_COMEDI_DEBUG +--- a/drivers/staging/comedi/drivers.c ++++ b/drivers/staging/comedi/drivers.c +@@ -822,25 +822,14 @@ static int comedi_auto_config(struct dev + int minor; + struct comedi_device_file_info *dev_file_info; + int retval; +- unsigned *private_data = NULL; + +- if (!comedi_autoconfig) { +- dev_set_drvdata(hardware_device, NULL); ++ if (!comedi_autoconfig) + return 0; +- } + + minor = comedi_alloc_board_minor(hardware_device); + if (minor < 0) + return minor; + +- private_data = kmalloc(sizeof(unsigned), GFP_KERNEL); +- if (private_data == NULL) { +- retval = -ENOMEM; +- goto cleanup; +- } +- *private_data = minor; +- dev_set_drvdata(hardware_device, private_data); +- + dev_file_info = comedi_get_device_file_info(minor); + + memset(&it, 0, sizeof(it)); +@@ -853,25 +842,22 @@ static int comedi_auto_config(struct dev + retval = comedi_device_attach(dev_file_info->device, &it); + mutex_unlock(&dev_file_info->device->mutex); + +-cleanup: +- if (retval < 0) { +- kfree(private_data); ++ if (retval < 0) + comedi_free_board_minor(minor); +- } + return retval; + } + + static void comedi_auto_unconfig(struct device *hardware_device) + { +- unsigned *minor = (unsigned *)dev_get_drvdata(hardware_device); +- if (minor == NULL) +- return; +- +- BUG_ON(*minor >= COMEDI_NUM_BOARD_MINORS); ++ int minor; + +- comedi_free_board_minor(*minor); +- dev_set_drvdata(hardware_device, NULL); +- kfree(minor); ++ if (hardware_device == NULL) ++ return; ++ minor = comedi_find_board_minor(hardware_device); ++ if (minor < 0) ++ return; ++ BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS); ++ comedi_free_board_minor(minor); + } + + int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name) +--- a/drivers/staging/comedi/internal.h ++++ b/drivers/staging/comedi/internal.h +@@ -7,6 +7,7 @@ int insn_inval(struct comedi_device *dev + struct comedi_insn *insn, unsigned int *data); + int comedi_alloc_board_minor(struct device *hardware_device); + void comedi_free_board_minor(unsigned minor); ++int comedi_find_board_minor(struct device *hardware_device); + void comedi_reset_async_buf(struct comedi_async *async); + int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, + unsigned long new_size); diff --git a/queue-3.4/usb-fix-endpoint-disabling-for-failed-config-changes.patch b/queue-3.4/usb-fix-endpoint-disabling-for-failed-config-changes.patch new file mode 100644 index 00000000000..cee94020b1a --- /dev/null +++ b/queue-3.4/usb-fix-endpoint-disabling-for-failed-config-changes.patch @@ -0,0 +1,103 @@ +From: Alan Stern +Date: Wed, 7 Nov 2012 10:31:30 -0500 +Subject: USB: fix endpoint-disabling for failed config changes + +commit 36caff5d795429c572443894e8789c2150dd796b upstream. + +This patch (as1631) fixes a bug that shows up when a config change +fails for a device under an xHCI controller. The controller needs to +be told to disable the endpoints that have been enabled for the new +config. The existing code does this, but before storing the +information about which endpoints were enabled! As a result, any +second attempt to install the new config is doomed to fail because +xhci-hcd will refuse to enable an endpoint that is already enabled. + +The patch optimistically initializes the new endpoints' device +structures before asking the device to switch to the new config. If +the request fails then the endpoint information is already stored, so +we can use usb_hcd_alloc_bandwidth() to disable the endpoints with no +trouble. The rest of the error path is slightly more complex now; we +have to disable the new interfaces and call put_device() rather than +simply deallocating them. + +Signed-off-by: Alan Stern +Reported-and-tested-by: Matthias Schniedermeyer +CC: Sarah Sharp +Signed-off-by: Greg Kroah-Hartman +[bwh: Backported to 3.2: adjust context] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/message.c | 53 ++++++++++++++++++++++++++------------------- + 1 file changed, 31 insertions(+), 22 deletions(-) + +--- a/drivers/usb/core/message.c ++++ b/drivers/usb/core/message.c +@@ -1770,28 +1770,8 @@ free_interfaces: + goto free_interfaces; + } + +- ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), +- USB_REQ_SET_CONFIGURATION, 0, configuration, 0, +- NULL, 0, USB_CTRL_SET_TIMEOUT); +- if (ret < 0) { +- /* All the old state is gone, so what else can we do? +- * The device is probably useless now anyway. +- */ +- cp = NULL; +- } +- +- dev->actconfig = cp; +- if (!cp) { +- usb_set_device_state(dev, USB_STATE_ADDRESS); +- usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); +- mutex_unlock(hcd->bandwidth_mutex); +- usb_autosuspend_device(dev); +- goto free_interfaces; +- } +- mutex_unlock(hcd->bandwidth_mutex); +- usb_set_device_state(dev, USB_STATE_CONFIGURED); +- +- /* Initialize the new interface structures and the ++ /* ++ * Initialize the new interface structures and the + * hc/hcd/usbcore interface/endpoint state. + */ + for (i = 0; i < nintf; ++i) { +@@ -1835,6 +1815,35 @@ free_interfaces: + } + kfree(new_interfaces); + ++ ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ++ USB_REQ_SET_CONFIGURATION, 0, configuration, 0, ++ NULL, 0, USB_CTRL_SET_TIMEOUT); ++ if (ret < 0 && cp) { ++ /* ++ * All the old state is gone, so what else can we do? ++ * The device is probably useless now anyway. ++ */ ++ usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); ++ for (i = 0; i < nintf; ++i) { ++ usb_disable_interface(dev, cp->interface[i], true); ++ put_device(&cp->interface[i]->dev); ++ cp->interface[i] = NULL; ++ } ++ cp = NULL; ++ } ++ ++ dev->actconfig = cp; ++ mutex_unlock(hcd->bandwidth_mutex); ++ ++ if (!cp) { ++ usb_set_device_state(dev, USB_STATE_ADDRESS); ++ ++ /* Leave LPM disabled while the device is unconfigured. */ ++ usb_autosuspend_device(dev); ++ return ret; ++ } ++ usb_set_device_state(dev, USB_STATE_CONFIGURED); ++ + if (cp->string == NULL && + !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) + cp->string = usb_cache_string(dev, cp->desc.iConfiguration);