From a5a0cdd640258b80e116de11517dd6482ab6f229 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Mon, 2 Jan 2012 15:31:23 -0500 Subject: firmware: Fix an oops on reading fw_priv->fw in sysfs loading file commit eea915bb0d1358755f151eaefb8208a2d5f3e10c upstream. This oops was reported recently: firmware_loading_store+0xf9/0x17b dev_attr_store+0x20/0x22 sysfs_write_file+0x101/0x134 vfs_write+0xac/0xf3 sys_write+0x4a/0x6e system_call_fastpath+0x16/0x1b The complete backtrace was unfortunately not captured, but details can be found here: https://bugzilla.redhat.com/show_bug.cgi?id=769920 The cause is fairly clear. Its caused by the fact that firmware_loading_store has a case 0 in its switch statement that reads and writes the fw_priv->fw poniter without the protection of the fw_lock mutex. since there is a window between the time that _request_firmware sets fw_priv->fw to NULL and the time the corresponding sysfs file is unregistered, its possible for a user space application to race in, and write a zero to the loading file, causing a NULL dereference in firmware_loading_store. Fix it by extending the protection of the fw_lock mutex to cover all of the firware_loading_store function. Signed-off-by: Neil Horman Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 06ed6b4e7df5..3719c94be19c 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -226,13 +226,13 @@ static ssize_t firmware_loading_store(struct device *dev, int loading = simple_strtol(buf, NULL, 10); int i; + mutex_lock(&fw_lock); + + if (!fw_priv->fw) + goto out; + switch (loading) { case 1: - mutex_lock(&fw_lock); - if (!fw_priv->fw) { - mutex_unlock(&fw_lock); - break; - } firmware_free_data(fw_priv->fw); memset(fw_priv->fw, 0, sizeof(struct firmware)); /* If the pages are not owned by 'struct firmware' */ @@ -243,7 +243,6 @@ static ssize_t firmware_loading_store(struct device *dev, fw_priv->page_array_size = 0; fw_priv->nr_pages = 0; set_bit(FW_STATUS_LOADING, &fw_priv->status); - mutex_unlock(&fw_lock); break; case 0: if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) { @@ -274,7 +273,8 @@ static ssize_t firmware_loading_store(struct device *dev, fw_load_abort(fw_priv); break; } - +out: + mutex_unlock(&fw_lock); return count; } -- cgit v1.2.3 From 2289fb57dc2caea22e167bba67b0b52997bce28f Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 27 Dec 2011 12:22:51 -0600 Subject: rt2800usb: Move ID out of unknown commit 3f81f8f1524ccca24df1029b0cf825ecef5e5cdc upstream. Testing on the openSUSE wireless forum has shown that a Linksys WUSB54GC v3 with USB ID 1737:0077 works with rt2800usb when the ID is written to /sys/.../new_id. This ID can therefore be moved out of UNKNOWN. Signed-off-by: Larry Finger Acked-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2800usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 377876315b8d..3265b341e96d 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -976,6 +976,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x13b1, 0x0031) }, { USB_DEVICE(0x1737, 0x0070) }, { USB_DEVICE(0x1737, 0x0071) }, + { USB_DEVICE(0x1737, 0x0077) }, /* Logitec */ { USB_DEVICE(0x0789, 0x0162) }, { USB_DEVICE(0x0789, 0x0163) }, @@ -1171,7 +1172,6 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x1740, 0x0605) }, { USB_DEVICE(0x1740, 0x0615) }, /* Linksys */ - { USB_DEVICE(0x1737, 0x0077) }, { USB_DEVICE(0x1737, 0x0078) }, /* Logitec */ { USB_DEVICE(0x0789, 0x0168) }, -- cgit v1.2.3 From dfedad611959d25331b77459bc9a96fb7765127f Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 28 Dec 2011 00:10:16 +0000 Subject: offb: Fix setting of the pseudo-palette for >8bpp commit 1bb0b7d21584b3f878e2bc880db62351ddee5185 upstream. When using a >8bpp framebuffer, offb advertises truecolor, not directcolor, and doesn't touch the color map even if it has a corresponding access method for the real hardware. Thus it needs to set the pseudo-palette with all 3 components of the color, like other truecolor framebuffers, not with copies of the color index like a directcolor framebuffer would do. This went unnoticed for a long time because it's pretty hard to get offb to kick in with anything but 8bpp (old BootX under MacOS will do that and qemu does it). Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- drivers/video/offb.c | 50 +++++++++++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/video/offb.c b/drivers/video/offb.c index cb163a5397be..24e1fc6b5658 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -100,36 +100,32 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info) { struct offb_par *par = (struct offb_par *) info->par; - int i, depth; - u32 *pal = info->pseudo_palette; - - depth = info->var.bits_per_pixel; - if (depth == 16) - depth = (info->var.green.length == 5) ? 15 : 16; - - if (regno > 255 || - (depth == 16 && regno > 63) || - (depth == 15 && regno > 31)) - return 1; - - if (regno < 16) { - switch (depth) { - case 15: - pal[regno] = (regno << 10) | (regno << 5) | regno; - break; - case 16: - pal[regno] = (regno << 11) | (regno << 5) | regno; - break; - case 24: - pal[regno] = (regno << 16) | (regno << 8) | regno; - break; - case 32: - i = (regno << 8) | regno; - pal[regno] = (i << 16) | i; - break; + + if (info->fix.visual == FB_VISUAL_TRUECOLOR) { + u32 *pal = info->pseudo_palette; + u32 cr = red >> (16 - info->var.red.length); + u32 cg = green >> (16 - info->var.green.length); + u32 cb = blue >> (16 - info->var.blue.length); + u32 value; + + if (regno >= 16) + return -EINVAL; + + value = (cr << info->var.red.offset) | + (cg << info->var.green.offset) | + (cb << info->var.blue.offset); + if (info->var.transp.length > 0) { + u32 mask = (1 << info->var.transp.length) - 1; + mask <<= info->var.transp.offset; + value |= mask; } + pal[regno] = value; + return 0; } + if (regno > 255) + return -EINVAL; + red >>= 8; green >>= 8; blue >>= 8; -- cgit v1.2.3 From 69236e6011d14450a3ed033327d1e6e225b35027 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 3 Jan 2012 12:09:15 +1100 Subject: offb: Fix bug in calculating requested vram size commit c055fe0797b7bd8f6f21a13598a55a16d5c13ae7 upstream. We used to try to request 8 times more vram than needed, which would fail if the card has a too small BAR (observed with qemu & kvm). Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- drivers/video/offb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 24e1fc6b5658..3251a0236d56 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -377,7 +377,7 @@ static void __init offb_init_fb(const char *name, const char *full_name, int pitch, unsigned long address, int foreign_endian, struct device_node *dp) { - unsigned long res_size = pitch * height * (depth + 7) / 8; + unsigned long res_size = pitch * height; struct offb_par *par = &default_par; unsigned long res_start = address; struct fb_fix_screeninfo *fix; -- cgit v1.2.3 From dd4f146b63d18b2cc5b7f20c56ba270f6a45fd01 Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Mon, 19 Dec 2011 12:22:58 -0800 Subject: libertas: clean up scan thread handling commit afbca95f95f2bf7283a72670c24c1f6de00b1cb5 upstream. The libertas scan thread expects priv->scan_req to be non-NULL. In theory, it should always be set. In practice, we've seen the following oops: [ 8363.067444] Unable to handle kernel NULL pointer dereference at virtual address 00000004 [ 8363.067490] pgd = c0004000 [ 8363.078393] [00000004] *pgd=00000000 [ 8363.086711] Internal error: Oops: 17 [#1] PREEMPT [ 8363.091375] Modules linked in: fuse libertas_sdio libertas psmouse mousedev ov7670 mmp_camera joydev videobuf2_core videobuf2_dma_sg videobuf2_memops [last unloaded: scsi_wait_scan] [ 8363.107490] CPU: 0 Not tainted (3.0.0-gf7ccc69 #671) [ 8363.112799] PC is at lbs_scan_worker+0x108/0x5a4 [libertas] [ 8363.118326] LR is at 0x0 [ 8363.120836] pc : [] lr : [<00000000>] psr: 60000113 [ 8363.120845] sp : ee66bf48 ip : 00000000 fp : 00000000 [ 8363.120845] r10: ee2c2088 r9 : c04e2efc r8 : eef97005 [ 8363.132231] r7 : eee0716f r6 : ee2c02c0 r5 : ee2c2088 r4 : eee07160 [ 8363.137419] r3 : 00000000 r2 : a0000113 r1 : 00000001 r0 : eee07160 [ 8363.143896] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel [ 8363.157630] Control: 10c5387d Table: 2e754019 DAC: 00000015 [ 8363.163334] Process kworker/u:1 (pid: 25, stack limit = 0xee66a2f8) While I've not found a smoking gun, there are two places that raised red flags for me. The first is in _internal_start_scan, when we queue up a scan; we first queue the worker, and then set priv->scan_req. There's theoretically a 50mS delay which should be plenty, but doing things that way just seems racy (and not in the good way). The second is in the scan worker thread itself. Depending on the state of priv->scan_channel, we cancel pending scan runs and then requeue a run in 300mS. We then send the scan command down to the hardware, sleep, and if we get scan results for all the desired channels, we set priv->scan_req to NULL. However, it that's happened in less than 300mS, what happens with the pending scan run? This patch addresses both of those concerns. With the patch applied, we have not seen the oops in the past two weeks. Signed-off-by: Andres Salomon Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/libertas/cfg.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index a7f1ab28940d..db64ef154325 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -728,9 +728,11 @@ static void lbs_scan_worker(struct work_struct *work) le16_to_cpu(scan_cmd->hdr.size), lbs_ret_scan, 0); - if (priv->scan_channel >= priv->scan_req->n_channels) + if (priv->scan_channel >= priv->scan_req->n_channels) { /* Mark scan done */ + cancel_delayed_work(&priv->scan_work); lbs_scan_done(priv); + } /* Restart network */ if (carrier) @@ -759,12 +761,12 @@ static void _internal_start_scan(struct lbs_private *priv, bool internal, request->n_ssids, request->n_channels, request->ie_len); priv->scan_channel = 0; - queue_delayed_work(priv->work_thread, &priv->scan_work, - msecs_to_jiffies(50)); - priv->scan_req = request; priv->internal_scan = internal; + queue_delayed_work(priv->work_thread, &priv->scan_work, + msecs_to_jiffies(50)); + lbs_deb_leave(LBS_DEB_CFG80211); } -- cgit v1.2.3 From 618bbbe723e697e71b4533d3d8af554fbe5f3e16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 9 Dec 2011 22:16:07 +0100 Subject: bcma: support for suspend and resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 775ab52142b02237a54184238e922251c59a2b5c upstream. bcma used to lock up machine without enabling PCI or initializing CC. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/bcma/bcma_private.h | 3 +++ drivers/bcma/host_pci.c | 37 +++++++++++++++++++++++++++++++++++++ drivers/bcma/main.c | 16 ++++++++++++++++ 3 files changed, 56 insertions(+) (limited to 'drivers') diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 30a3085d3354..fda56bde36b8 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h @@ -18,6 +18,9 @@ void bcma_bus_unregister(struct bcma_bus *bus); int __init bcma_bus_early_register(struct bcma_bus *bus, struct bcma_device *core_cc, struct bcma_device *core_mips); +#ifdef CONFIG_PM +int bcma_bus_resume(struct bcma_bus *bus); +#endif /* scan.c */ int bcma_bus_scan(struct bcma_bus *bus); diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index 1b51d8b7ac80..990f5a8e9c19 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c @@ -224,6 +224,41 @@ static void bcma_host_pci_remove(struct pci_dev *dev) pci_set_drvdata(dev, NULL); } +#ifdef CONFIG_PM +static int bcma_host_pci_suspend(struct pci_dev *dev, pm_message_t state) +{ + /* Host specific */ + pci_save_state(dev); + pci_disable_device(dev); + pci_set_power_state(dev, pci_choose_state(dev, state)); + + return 0; +} + +static int bcma_host_pci_resume(struct pci_dev *dev) +{ + struct bcma_bus *bus = pci_get_drvdata(dev); + int err; + + /* Host specific */ + pci_set_power_state(dev, 0); + err = pci_enable_device(dev); + if (err) + return err; + pci_restore_state(dev); + + /* Bus specific */ + err = bcma_bus_resume(bus); + if (err) + return err; + + return 0; +} +#else /* CONFIG_PM */ +# define bcma_host_pci_suspend NULL +# define bcma_host_pci_resume NULL +#endif /* CONFIG_PM */ + static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, @@ -239,6 +274,8 @@ static struct pci_driver bcma_pci_bridge_driver = { .id_table = bcma_pci_bridge_tbl, .probe = bcma_host_pci_probe, .remove = bcma_host_pci_remove, + .suspend = bcma_host_pci_suspend, + .resume = bcma_host_pci_resume, }; int __init bcma_host_pci_init(void) diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 70c84b951098..10f92b371e58 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -240,6 +240,22 @@ int __init bcma_bus_early_register(struct bcma_bus *bus, return 0; } +#ifdef CONFIG_PM +int bcma_bus_resume(struct bcma_bus *bus) +{ + struct bcma_device *core; + + /* Init CC core */ + core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON); + if (core) { + bus->drv_cc.setup_done = false; + bcma_core_chipcommon_init(&bus->drv_cc); + } + + return 0; +} +#endif + int __bcma_driver_register(struct bcma_driver *drv, struct module *owner) { drv->drv.name = drv->name; -- cgit v1.2.3 From 240ecc4a6fa0449738920ea0658ed4508398091a Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Tue, 18 Oct 2011 09:23:41 +0200 Subject: wl12xx: Validate FEM index from ini file and FW commit 2131d3c2f99b081806fdae7662c92fe6acda52af upstream. Check for out of bound FEM index to prevent reading beyond ini memory end. Signed-off-by: Pontus Fuchs Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/wl12xx/cmd.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index a52299e548fa..54a0d667ff43 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -120,6 +120,11 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) if (!wl->nvs) return -ENODEV; + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from INI out of bounds"); + return -EINVAL; + } + gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); if (!gen_parms) return -ENOMEM; @@ -143,6 +148,12 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) gp->tx_bip_fem_manufacturer = gen_parms->general_params.tx_bip_fem_manufacturer; + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from FW out of bounds"); + ret = -EINVAL; + goto out; + } + wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); @@ -162,6 +173,11 @@ int wl128x_cmd_general_parms(struct wl1271 *wl) if (!wl->nvs) return -ENODEV; + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from ini out of bounds"); + return -EINVAL; + } + gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); if (!gen_parms) return -ENOMEM; @@ -186,6 +202,12 @@ int wl128x_cmd_general_parms(struct wl1271 *wl) gp->tx_bip_fem_manufacturer = gen_parms->general_params.tx_bip_fem_manufacturer; + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from FW out of bounds"); + ret = -EINVAL; + goto out; + } + wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); -- cgit v1.2.3 From 67d3bda61b6cf7b8c3166091ab44a07fbd9e091a Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Tue, 18 Oct 2011 09:23:42 +0200 Subject: wl12xx: Check buffer bound when processing nvs data commit f6efe96edd9c41c624c8f4ddbc4930c1a2d8f1e1 upstream. An nvs with malformed contents could cause the processing of the calibration data to read beyond the end of the buffer. Prevent this from happening by adding bound checking. Signed-off-by: Pontus Fuchs Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/wl12xx/boot.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index 681337914976..a7b327d2e41b 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -347,6 +347,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) nvs_ptr += 3; for (i = 0; i < burst_len; i++) { + if (nvs_ptr + 3 >= (u8 *) wl->nvs + nvs_len) + goto out_badnvs; + val = (nvs_ptr[0] | (nvs_ptr[1] << 8) | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24)); @@ -358,6 +361,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) nvs_ptr += 4; dest_addr += 4; } + + if (nvs_ptr >= (u8 *) wl->nvs + nvs_len) + goto out_badnvs; } /* @@ -369,6 +375,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) */ nvs_ptr = (u8 *)wl->nvs + ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4); + + if (nvs_ptr >= (u8 *) wl->nvs + nvs_len) + goto out_badnvs; + nvs_len -= nvs_ptr - (u8 *)wl->nvs; /* Now we must set the partition correctly */ @@ -384,6 +394,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) kfree(nvs_aligned); return 0; + +out_badnvs: + wl1271_error("nvs data is malformed"); + return -EILSEQ; } static void wl1271_boot_enable_interrupts(struct wl1271 *wl) -- cgit v1.2.3 From f92fed3f1de1942a61978c5e59bbed56eab4ac55 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Thu, 1 Dec 2011 12:13:44 +0100 Subject: wl12xx: Restore testmode ABI commit 3f1764945eaac532c20ab1f23afa352a40f797b2 upstream. Commit 80900d0140a7648587982c8f299830e900e49165 accidently broke the ABI for testmode commands. Restore the ABI again. Signed-off-by: Pontus Fuchs Signed-off-by: Luciano Coelho Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/wl12xx/testmode.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c index 4ae8effaee22..abfb120df118 100644 --- a/drivers/net/wireless/wl12xx/testmode.c +++ b/drivers/net/wireless/wl12xx/testmode.c @@ -36,6 +36,7 @@ enum wl1271_tm_commands { WL1271_TM_CMD_TEST, WL1271_TM_CMD_INTERROGATE, WL1271_TM_CMD_CONFIGURE, + WL1271_TM_CMD_NVS_PUSH, /* Not in use. Keep to not break ABI */ WL1271_TM_CMD_SET_PLT_MODE, WL1271_TM_CMD_RECOVER, -- cgit v1.2.3 From 0d878668d0a4663a4807d413532f3a99496eebf4 Mon Sep 17 00:00:00 2001 From: Ram Vepa Date: Fri, 23 Dec 2011 08:01:43 -0500 Subject: IB/qib: Fix a possible data corruption when receiving packets commit eddfb675256f49d14e8c5763098afe3eb2c93701 upstream. Prevent a receive data corruption by ensuring that the write to update the rcvhdrheadn register to generate an interrupt is at the very end of the receive processing. Signed-off-by: Ramkrishna Vepa Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/qib/qib_iba6120.c | 4 +++- drivers/infiniband/hw/qib/qib_iba7220.c | 4 +++- drivers/infiniband/hw/qib/qib_iba7322.c | 6 ++++-- 3 files changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c index 781a802a321f..4f18e2d332df 100644 --- a/drivers/infiniband/hw/qib/qib_iba6120.c +++ b/drivers/infiniband/hw/qib/qib_iba6120.c @@ -2076,9 +2076,11 @@ static void qib_6120_config_ctxts(struct qib_devdata *dd) static void qib_update_6120_usrhead(struct qib_ctxtdata *rcd, u64 hd, u32 updegr, u32 egrhd, u32 npkts) { - qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); if (updegr) qib_write_ureg(rcd->dd, ur_rcvegrindexhead, egrhd, rcd->ctxt); + mmiowb(); + qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); + mmiowb(); } static u32 qib_6120_hdrqempty(struct qib_ctxtdata *rcd) diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c index 439d3c503cd5..7ec4048731c9 100644 --- a/drivers/infiniband/hw/qib/qib_iba7220.c +++ b/drivers/infiniband/hw/qib/qib_iba7220.c @@ -2725,9 +2725,11 @@ static int qib_7220_set_loopback(struct qib_pportdata *ppd, const char *what) static void qib_update_7220_usrhead(struct qib_ctxtdata *rcd, u64 hd, u32 updegr, u32 egrhd, u32 npkts) { - qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); if (updegr) qib_write_ureg(rcd->dd, ur_rcvegrindexhead, egrhd, rcd->ctxt); + mmiowb(); + qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); + mmiowb(); } static u32 qib_7220_hdrqempty(struct qib_ctxtdata *rcd) diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 1d5895941e19..5a070e8c983d 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -4082,10 +4082,12 @@ static void qib_update_7322_usrhead(struct qib_ctxtdata *rcd, u64 hd, */ if (hd >> IBA7322_HDRHEAD_PKTINT_SHIFT) adjust_rcv_timeout(rcd, npkts); - qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); - qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); if (updegr) qib_write_ureg(rcd->dd, ur_rcvegrindexhead, egrhd, rcd->ctxt); + mmiowb(); + qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); + qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); + mmiowb(); } static u32 qib_7322_hdrqempty(struct qib_ctxtdata *rcd) -- cgit v1.2.3 From 585ea9bc6752c41d669ea0f4cee8f3954df326e0 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Tue, 3 Jan 2012 20:36:48 -0800 Subject: IB/uverbs: Protect QP multicast list commit e214a0fe2b382fa302c036ecd6e6ffe99e3b9875 upstream. Userspace verbs multicast attach/detach operations on a QP are done while holding the rwsem of the QP for reading. That's not sufficient since a reader lock allows more than one reader to acquire the lock. However, multicast attach/detach does list manipulation that can corrupt the list if multiple threads run in parallel. Fix this by acquiring the rwsem as a writer to serialize attach/detach operations. Add idr_write_qp() and put_qp_write() to encapsulate this. This fixes oops seen when running applications that perform multicast joins/leaves. Reported by: Mike Dubman Signed-off-by: Eli Cohen Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/core/uverbs_cmd.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 254f1649c734..e3db8ef4fe4e 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -241,11 +241,24 @@ static struct ib_qp *idr_read_qp(int qp_handle, struct ib_ucontext *context) return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context, 0); } +static struct ib_qp *idr_write_qp(int qp_handle, struct ib_ucontext *context) +{ + struct ib_uobject *uobj; + + uobj = idr_write_uobj(&ib_uverbs_qp_idr, qp_handle, context); + return uobj ? uobj->object : NULL; +} + static void put_qp_read(struct ib_qp *qp) { put_uobj_read(qp->uobject); } +static void put_qp_write(struct ib_qp *qp) +{ + put_uobj_write(qp->uobject); +} + static struct ib_srq *idr_read_srq(int srq_handle, struct ib_ucontext *context) { return idr_read_obj(&ib_uverbs_srq_idr, srq_handle, context, 0); @@ -2375,7 +2388,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - qp = idr_read_qp(cmd.qp_handle, file->ucontext); + qp = idr_write_qp(cmd.qp_handle, file->ucontext); if (!qp) return -EINVAL; @@ -2404,7 +2417,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, kfree(mcast); out_put: - put_qp_read(qp); + put_qp_write(qp); return ret ? ret : in_len; } @@ -2422,7 +2435,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - qp = idr_read_qp(cmd.qp_handle, file->ucontext); + qp = idr_write_qp(cmd.qp_handle, file->ucontext); if (!qp) return -EINVAL; @@ -2441,7 +2454,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, } out_put: - put_qp_read(qp); + put_qp_write(qp); return ret ? ret : in_len; } -- cgit v1.2.3 From 01b366aa69f33489d59d7a79702987752070fb3a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 2 Dec 2011 12:22:54 -0800 Subject: iwlagn: fix TID use bug commit 9a215e40d70ae63762963ab3ccc7f31dd966dc6a upstream. The driver everywhere uses max TID count as 9, which is wrong, it should be 8. I think the reason it uses 9 here is off-by-one confusion by whoever wrote this. We do use the value IWL_MAX_TID_COUNT for "not QoS/no TID" but that is completely correct even if it is 8 and not 9 since 0-7 are only valid. As a side effect, this fixes the following bug: Open BA session requested for 00:23:cd:16:8a:7e tid 8 ------------[ cut here ]------------ kernel BUG at drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h:350! ... when you do echo "tx start 8" > /sys/kernel/debug/ieee80211/*/*/*/*/agg_status Reported-by: Nikolay Martynov Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-commands.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 69d5f85d11e2..8b9ff2815784 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -809,7 +809,7 @@ struct iwl_qosparam_cmd { #define IWLAGN_STATION_COUNT 16 #define IWL_INVALID_STATION 255 -#define IWL_MAX_TID_COUNT 9 +#define IWL_MAX_TID_COUNT 8 #define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2) #define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8) -- cgit v1.2.3 From 0b58bf9909d4ef70275921fc1535f21390cf5bb5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 19 Dec 2011 14:00:59 -0800 Subject: iwlagn: fix (remove) use of PAGE_SIZE commit 106671369e6d046c0b3e1e72b18ad6dd9cb298b0 upstream. The ICT code erroneously uses PAGE_SIZE. The bug is that PAGE_SIZE isn't necessarily 4096, so on such platforms this code will not work correctly as we'll try to attempt to read an index in the table that the device never wrote, it always has 4096-byte pages. Additionally, the manual alignment code here is unnecessary -- Documentation/DMA-API-HOWTO.txt states: The cpu return address and the DMA bus master address are both guaranteed to be aligned to the smallest PAGE_SIZE order which is greater than or equal to the requested size. This invariant exists (for example) to guarantee that if you allocate a chunk which is smaller than or equal to 64 kilobytes, the extent of the buffer you receive will not cross a 64K boundary. Just use appropriate new constants and get rid of the alignment code. Cc: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 2 - drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 73 ++++++++++------------- 2 files changed, 31 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 2b6756e8b8f9..5c2928182892 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -219,9 +219,7 @@ struct iwl_trans_pcie { /* INT ICT Table */ __le32 *ict_tbl; - void *ict_tbl_vir; dma_addr_t ict_tbl_dma; - dma_addr_t aligned_ict_tbl_dma; int ict_index; u32 inta; bool use_ict; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 374c68cc1d70..1920237f13ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -1136,7 +1136,11 @@ void iwl_irq_tasklet(struct iwl_trans *trans) * ICT functions * ******************************************************************************/ -#define ICT_COUNT (PAGE_SIZE/sizeof(u32)) + +/* a device (PCI-E) page is 4096 bytes long */ +#define ICT_SHIFT 12 +#define ICT_SIZE (1 << ICT_SHIFT) +#define ICT_COUNT (ICT_SIZE / sizeof(u32)) /* Free dram table */ void iwl_free_isr_ict(struct iwl_trans *trans) @@ -1144,21 +1148,19 @@ void iwl_free_isr_ict(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - if (trans_pcie->ict_tbl_vir) { - dma_free_coherent(bus(trans)->dev, - (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - trans_pcie->ict_tbl_vir, + if (trans_pcie->ict_tbl) { + dma_free_coherent(bus(trans)->dev, ICT_SIZE, + trans_pcie->ict_tbl, trans_pcie->ict_tbl_dma); - trans_pcie->ict_tbl_vir = NULL; - memset(&trans_pcie->ict_tbl_dma, 0, - sizeof(trans_pcie->ict_tbl_dma)); - memset(&trans_pcie->aligned_ict_tbl_dma, 0, - sizeof(trans_pcie->aligned_ict_tbl_dma)); + trans_pcie->ict_tbl = NULL; + trans_pcie->ict_tbl_dma = 0; } } -/* allocate dram shared table it is a PAGE_SIZE aligned +/* + * allocate dram shared table, it is an aligned memory + * block of ICT_SIZE. * also reset all data related to ICT table interrupt. */ int iwl_alloc_isr_ict(struct iwl_trans *trans) @@ -1166,36 +1168,26 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - /* allocate shrared data table */ - trans_pcie->ict_tbl_vir = - dma_alloc_coherent(bus(trans)->dev, - (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - &trans_pcie->ict_tbl_dma, GFP_KERNEL); - if (!trans_pcie->ict_tbl_vir) + trans_pcie->ict_tbl = + dma_alloc_coherent(bus(trans)->dev, ICT_SIZE, + &trans_pcie->ict_tbl_dma, + GFP_KERNEL); + if (!trans_pcie->ict_tbl) return -ENOMEM; - /* align table to PAGE_SIZE boundary */ - trans_pcie->aligned_ict_tbl_dma = - ALIGN(trans_pcie->ict_tbl_dma, PAGE_SIZE); - - IWL_DEBUG_ISR(trans, "ict dma addr %Lx dma aligned %Lx diff %d\n", - (unsigned long long)trans_pcie->ict_tbl_dma, - (unsigned long long)trans_pcie->aligned_ict_tbl_dma, - (int)(trans_pcie->aligned_ict_tbl_dma - - trans_pcie->ict_tbl_dma)); + /* just an API sanity check ... it is guaranteed to be aligned */ + if (WARN_ON(trans_pcie->ict_tbl_dma & (ICT_SIZE - 1))) { + iwl_free_isr_ict(trans); + return -EINVAL; + } - trans_pcie->ict_tbl = trans_pcie->ict_tbl_vir + - (trans_pcie->aligned_ict_tbl_dma - - trans_pcie->ict_tbl_dma); + IWL_DEBUG_ISR(trans, "ict dma addr %Lx\n", + (unsigned long long)trans_pcie->ict_tbl_dma); - IWL_DEBUG_ISR(trans, "ict vir addr %p vir aligned %p diff %d\n", - trans_pcie->ict_tbl, trans_pcie->ict_tbl_vir, - (int)(trans_pcie->aligned_ict_tbl_dma - - trans_pcie->ict_tbl_dma)); + IWL_DEBUG_ISR(trans, "ict vir addr %p\n", trans_pcie->ict_tbl); /* reset table and index to all 0 */ - memset(trans_pcie->ict_tbl_vir, 0, - (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); + memset(trans_pcie->ict_tbl, 0, ICT_SIZE); trans_pcie->ict_index = 0; /* add periodic RX interrupt */ @@ -1213,23 +1205,20 @@ int iwl_reset_ict(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - if (!trans_pcie->ict_tbl_vir) + if (!trans_pcie->ict_tbl) return 0; spin_lock_irqsave(&trans->shrd->lock, flags); iwl_disable_interrupts(trans); - memset(&trans_pcie->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); + memset(trans_pcie->ict_tbl, 0, ICT_SIZE); - val = trans_pcie->aligned_ict_tbl_dma >> PAGE_SHIFT; + val = trans_pcie->ict_tbl_dma >> ICT_SHIFT; val |= CSR_DRAM_INT_TBL_ENABLE; val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; - IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%X " - "aligned dma address %Lx\n", - val, - (unsigned long long)trans_pcie->aligned_ict_tbl_dma); + IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%x\n", val); iwl_write32(bus(trans), CSR_DRAM_INT_TBL_REG, val); trans_pcie->use_ict = true; -- cgit v1.2.3 From 32eef9ed02e483cb39d0d70316ba35a5d4920b6b Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 1 Dec 2011 09:59:34 -0800 Subject: drivers: hv: Don't OOPS when you cannot init vmbus commit cf6a2eacbcb2593b5b91d0817915c4f0464bb534 upstream. The hv vmbus driver was causing an OOPS since it was trying to register drivers on top of the bus even if initialization of the bus has failed for some reason (such as the odd chance someone would run a hv enabled kernel in a non-hv environment). Signed-off-by: Sasha Levin Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/hv/vmbus_drv.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 0c048dd8013f..d3b0b4fba4d9 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -62,6 +62,14 @@ struct hv_device_info { struct hv_dev_port_info outbound; }; +static int vmbus_exists(void) +{ + if (hv_acpi_dev == NULL) + return -ENODEV; + + return 0; +} + static void get_channel_info(struct hv_device *device, struct hv_device_info *info) @@ -590,6 +598,10 @@ int __vmbus_driver_register(struct hv_driver *hv_driver, struct module *owner, c pr_info("registering driver %s\n", hv_driver->name); + ret = vmbus_exists(); + if (ret < 0) + return ret; + hv_driver->driver.name = hv_driver->name; hv_driver->driver.owner = owner; hv_driver->driver.mod_name = mod_name; @@ -614,6 +626,9 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver) { pr_info("unregistering driver %s\n", hv_driver->name); + if (!vmbus_exists()) + return; + driver_unregister(&hv_driver->driver); } @@ -776,6 +791,7 @@ static int __init hv_acpi_init(void) cleanup: acpi_bus_unregister_driver(&vmbus_acpi_driver); + hv_acpi_dev = NULL; return ret; } -- cgit v1.2.3 From d1883e7052eeffca3f42922bb31fa44d0992c6a6 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 27 Dec 2011 13:49:37 -0800 Subject: Drivers:hv: Fix a bug in vmbus_driver_unregister() commit 8f257a142fc3868d69de3f996b95d7bdbc509560 upstream. The function vmbus_exists() was introduced recently to deal with cases where the vmbus driver failed to initialize and yet other Hyper-V drivers attempted to register with the vmbus bus driver. This patch introduced a bug where vmbus_driver_unregister() would fail to unregister the driver. This patch fixes the problem. Signed-off-by: K. Y. Srinivasan Signed-off-by: Fuzhou Chen Cc: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/hv/vmbus_drv.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index d3b0b4fba4d9..d2d0a2a9676d 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -627,10 +627,7 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver) pr_info("unregistering driver %s\n", hv_driver->name); if (!vmbus_exists()) - return; - - driver_unregister(&hv_driver->driver); - + driver_unregister(&hv_driver->driver); } EXPORT_SYMBOL_GPL(vmbus_driver_unregister); -- cgit v1.2.3 From 7f35a6941c20af66dde1148b491e2f501192179b Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 16 Dec 2011 11:26:30 -0800 Subject: usbfs: Fix oops related to user namespace conversion. commit 1b41c8321e495337e877ca02d0b9680bc4112eff upstream. When running the Point Grey "flycap" program for their USB 3.0 camera (which was running as a USB 2.0 device for some reason), I trigger this oops whenever I try to open a video stream: Dec 15 16:48:34 puck kernel: [ 1798.715559] BUG: unable to handle kernel NULL pointer dereference at (null) Dec 15 16:48:34 puck kernel: [ 1798.719153] IP: [] free_async+0x1e/0x70 Dec 15 16:48:34 puck kernel: [ 1798.720991] PGD 6f833067 PUD 6fc56067 PMD 0 Dec 15 16:48:34 puck kernel: [ 1798.722815] Oops: 0002 [#1] SMP Dec 15 16:48:34 puck kernel: [ 1798.724627] CPU 0 Dec 15 16:48:34 puck kernel: [ 1798.724636] Modules linked in: ecryptfs encrypted_keys sha1_generic trusted binfmt_misc sha256_generic aesni_intel cryptd aes_x86_64 aes_generic parport_pc dm_crypt ppdev joydev snd_hda_codec_hdmi snd_hda_codec_conexant arc4 iwlwifi snd_hda_intel snd_hda_codec snd_hwdep snd_pcm thinkpad_acpi mac80211 snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq snd_timer btusb uvcvideo snd_seq_device bluetooth videodev psmouse snd v4l2_compat_ioctl32 serio_raw tpm_tis cfg80211 tpm tpm_bios nvram soundcore snd_page_alloc lp parport i915 xhci_hcd ahci libahci drm_kms_helper drm sdhci_pci sdhci e1000e i2c_algo_bit video Dec 15 16:48:34 puck kernel: [ 1798.734212] Dec 15 16:48:34 puck kernel: [ 1798.736162] Pid: 2713, comm: FlyCap2 Not tainted 3.2.0-rc5+ #28 LENOVO 4286CTO/4286CTO Dec 15 16:48:34 puck kernel: [ 1798.738148] RIP: 0010:[] [] free_async+0x1e/0x70 Dec 15 16:48:34 puck kernel: [ 1798.740134] RSP: 0018:ffff88005715fd78 EFLAGS: 00010296 Dec 15 16:48:34 puck kernel: [ 1798.742118] RAX: 00000000fffffff4 RBX: ffff88006fe8f900 RCX: 0000000000004118 Dec 15 16:48:34 puck kernel: [ 1798.744116] RDX: 0000000001000000 RSI: 0000000000016390 RDI: 0000000000000000 Dec 15 16:48:34 puck kernel: [ 1798.746087] RBP: ffff88005715fd88 R08: 0000000000000000 R09: ffffffff8146f22e Dec 15 16:48:34 puck kernel: [ 1798.748018] R10: ffff88006e520ac0 R11: 0000000000000001 R12: ffff88005715fe28 Dec 15 16:48:34 puck kernel: [ 1798.749916] R13: ffff88005d31df00 R14: ffff88006fe8f900 R15: 00007f688c995cb8 Dec 15 16:48:34 puck kernel: [ 1798.751785] FS: 00007f68a366da40(0000) GS:ffff880100200000(0000) knlGS:0000000000000000 Dec 15 16:48:34 puck kernel: [ 1798.753659] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 Dec 15 16:48:34 puck kernel: [ 1798.755509] CR2: 0000000000000000 CR3: 00000000706bb000 CR4: 00000000000406f0 Dec 15 16:48:34 puck kernel: [ 1798.757334] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 Dec 15 16:48:34 puck kernel: [ 1798.759124] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Dec 15 16:48:34 puck kernel: [ 1798.760871] Process FlyCap2 (pid: 2713, threadinfo ffff88005715e000, task ffff88006c675b80) Dec 15 16:48:34 puck kernel: [ 1798.762605] Stack: Dec 15 16:48:34 puck kernel: [ 1798.764297] ffff88005715fe28 0000000000000000 ffff88005715fe08 ffffffff81479058 Dec 15 16:48:34 puck kernel: [ 1798.766020] 0000000000000000 ffffea0000004000 ffff880000004118 0000000000000000 Dec 15 16:48:34 puck kernel: [ 1798.767750] ffff880000000001 ffff88006e520ac0 fffffff46fd81180 0000000000000000 Dec 15 16:48:34 puck kernel: [ 1798.769472] Call Trace: Dec 15 16:48:34 puck kernel: [ 1798.771147] [] proc_do_submiturb+0x778/0xa00 Dec 15 16:48:34 puck kernel: [ 1798.772798] [] usbdev_do_ioctl+0x24d/0x1200 Dec 15 16:48:34 puck kernel: [ 1798.774410] [] usbdev_ioctl+0xe/0x20 Dec 15 16:48:34 puck kernel: [ 1798.775975] [] do_vfs_ioctl+0x99/0x600 Dec 15 16:48:34 puck kernel: [ 1798.777534] [] sys_ioctl+0x91/0xa0 Dec 15 16:48:34 puck kernel: [ 1798.779088] [] system_call_fastpath+0x16/0x1b ec 15 16:48:34 puck kernel: [ 1798.780634] Code: 51 ff ff ff e9 29 ff ff ff 0f 1f 40 00 55 48 89 e5 53 48 83 ec 08 66 66 66 66 90 48 89 fb 48 8b 7f 18 e8 a6 ea c0 ff 4 8 8b 7b 20 ff 0f 0f 94 c0 84 c0 74 05 e8 d3 99 c1 ff 48 8b 43 40 48 8b Dec 15 16:48:34 puck kernel: [ 1798.783970] RIP [] free_async+0x1e/0x70 Dec 15 16:48:34 puck kernel: [ 1798.785630] RSP Dec 15 16:48:34 puck kernel: [ 1798.787274] CR2: 0000000000000000 Dec 15 16:48:34 puck kernel: [ 1798.794728] ---[ end trace 52894d3355f88d19 ]--- markup_oops.pl says the oops is in put_cred: ffffffff81478401: 48 89 e5 mov %rsp,%rbp ffffffff81478404: 53 push %rbx ffffffff81478405: 48 83 ec 08 sub $0x8,%rsp ffffffff81478409: e8 f2 c0 1a 00 callq ffffffff81624500 ffffffff8147840e: 48 89 fb mov %rdi,%rbx | %ebx => ffff88006fe8f900 put_pid(as->pid); ffffffff81478411: 48 8b 7f 18 mov 0x18(%rdi),%rdi ffffffff81478415: e8 a6 ea c0 ff callq ffffffff81086ec0 put_cred(as->cred); ffffffff8147841a: 48 8b 7b 20 mov 0x20(%rbx),%rdi | %edi => 0 %ebx = ffff88006fe8f900 */ static inline int atomic_dec_and_test(atomic_t *v) { unsigned char c; asm volatile(LOCK_PREFIX "decl %0; sete %1" *ffffffff8147841e: f0 ff 0f lock decl (%rdi) | %edi = 0 <--- faulting instruction ffffffff81478421: 0f 94 c0 sete %al static inline void put_cred(const struct cred *_cred) { struct cred *cred = (struct cred *) _cred; validate_creds(cred); if (atomic_dec_and_test(&(cred)->usage)) ffffffff81478424: 84 c0 test %al,%al ffffffff81478426: 74 05 je ffffffff8147842d __put_cred(cred); ffffffff81478428: e8 d3 99 c1 ff callq ffffffff81091e00 <__put_cred> kfree(as->urb->transfer_buffer); ffffffff8147842d: 48 8b 43 40 mov 0x40(%rbx),%rax ffffffff81478431: 48 8b 78 68 mov 0x68(%rax),%rdi ffffffff81478435: e8 a6 e1 ce ff callq ffffffff811665e0 kfree(as->urb->setup_packet); ffffffff8147843a: 48 8b 43 40 mov 0x40(%rbx),%rax ffffffff8147843e: 48 8b b8 90 00 00 00 mov 0x90(%rax),%rdi ffffffff81478445: e8 96 e1 ce ff callq ffffffff811665e0 usb_free_urb(as->urb); ffffffff8147844a: 48 8b 7b 40 mov 0x40(%rbx),%rdi ffffffff8147844e: e8 0d 6b ff ff callq ffffffff8146ef60 This bug seems to have been introduced by commit d178bc3a708f39cbfefc3fab37032d3f2511b4ec "user namespace: usb: make usb urbs user namespace aware (v2)" I'm not sure if this is right fix, but it does stop the oops. Unfortunately, the Point Grey software still refuses to work, but it's a closed source app, so I can't fix it. Signed-off-by: Sarah Sharp Acked-by: Serge Hallyn Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index e3beaf229ee3..7abf06004b7a 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -249,7 +249,8 @@ static struct async *alloc_async(unsigned int numisoframes) static void free_async(struct async *as) { put_pid(as->pid); - put_cred(as->cred); + if (as->cred) + put_cred(as->cred); kfree(as->urb->transfer_buffer); kfree(as->urb->setup_packet); usb_free_urb(as->urb); -- cgit v1.2.3 From b71bb82900b7491f47a0360f14d23dc30646433d Mon Sep 17 00:00:00 2001 From: Claudio Scordino Date: Fri, 16 Dec 2011 15:08:49 +0100 Subject: atmel_serial: fix spinlock lockup in RS485 code commit dbf1115d3f8c7052788aa4e6e46abd27f3b3eeba upstream. Patch to fix a spinlock lockup in the driver that sometimes happens when the tasklet starts. Signed-off-by: Claudio Scordino Signed-off-by: Dave Bender Tested-by: Dave Bender Acked-by: Nicolas Ferre Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 4c823f341d98..90c8e3a49220 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -212,8 +212,9 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); unsigned int mode; + unsigned long flags; - spin_lock(&port->lock); + spin_lock_irqsave(&port->lock, flags); /* Disable interrupts */ UART_PUT_IDR(port, atmel_port->tx_done_mask); @@ -244,7 +245,7 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) /* Enable interrupts */ UART_PUT_IER(port, atmel_port->tx_done_mask); - spin_unlock(&port->lock); + spin_unlock_irqrestore(&port->lock, flags); } -- cgit v1.2.3 From 30234e2694cbc1d6985cafc87db5cd4848493196 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 23 Dec 2011 14:02:55 +0100 Subject: drivers/usb/class/cdc-acm.c: clear dangling pointer commit e7c8e8605d0bafc705ff27f9da98a1668427cc0f upstream. On some failures, the country_code field of an acm structure is freed without freeing the acm structure itself. Elsewhere, operations including memcpy and kfree are performed on the country_code field. The patch sets the country_code field to NULL when it is freed, and likewise sets the country_code_size field to 0. Signed-off-by: Julia Lawall Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index a8078d0638fa..ea5e487448bf 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1183,6 +1183,8 @@ made_compressed_probe: i = device_create_file(&intf->dev, &dev_attr_wCountryCodes); if (i < 0) { kfree(acm->country_codes); + acm->country_codes = NULL; + acm->country_code_size = 0; goto skip_countries; } @@ -1191,6 +1193,8 @@ made_compressed_probe: if (i < 0) { device_remove_file(&intf->dev, &dev_attr_wCountryCodes); kfree(acm->country_codes); + acm->country_codes = NULL; + acm->country_code_size = 0; goto skip_countries; } } -- cgit v1.2.3 From d6b3d54200b7b29473041fe8c2e2f5382f2f0c80 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 5 Dec 2011 14:02:59 -0800 Subject: USB: isight: fix kernel bug when loading firmware commit 59bf5cf94f0fa3b08fb1258b52649077b7d0914d upstream. We were sending data on the stack when uploading firmware, which causes some machines fits, and is not allowed. Fix this by using the buffer we already had around for this very purpose. Reported-by: Wouter M. Koolen Tested-by: Wouter M. Koolen Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/isight_firmware.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/isight_firmware.c b/drivers/usb/misc/isight_firmware.c index fe1d44319d0a..8f725f651915 100644 --- a/drivers/usb/misc/isight_firmware.c +++ b/drivers/usb/misc/isight_firmware.c @@ -55,8 +55,9 @@ static int isight_firmware_load(struct usb_interface *intf, ptr = firmware->data; + buf[0] = 0x01; if (usb_control_msg - (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\1", 1, + (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, buf, 1, 300) != 1) { printk(KERN_ERR "Failed to initialise isight firmware loader\n"); @@ -100,8 +101,9 @@ static int isight_firmware_load(struct usb_interface *intf, } } + buf[0] = 0x00; if (usb_control_msg - (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\0", 1, + (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, buf, 1, 300) != 1) { printk(KERN_ERR "isight firmware loading completion failed\n"); ret = -ENODEV; -- cgit v1.2.3 From ab8887268c60a5dac0dc388c773a679470292c55 Mon Sep 17 00:00:00 2001 From: Huajun Li Date: Wed, 4 Jan 2012 19:25:33 +0800 Subject: usb: usb-storage doesn't support dynamic id currently, the patch disables the feature to fix an oops commit 1a3a026ba1b6bbfe0b7f79ab38cf991d691e7c9a upstream. Echo vendor and product number of a non usb-storage device to usb-storage driver's new_id, then plug in the device to host and you will find following oops msg, the root cause is usb_stor_probe1() refers invalid id entry if giving a dynamic id, so just disable the feature. [ 3105.018012] general protection fault: 0000 [#1] SMP DEBUG_PAGEALLOC [ 3105.018062] CPU 0 [ 3105.018075] Modules linked in: usb_storage usb_libusual bluetooth dm_crypt binfmt_misc snd_hda_codec_analog snd_hda_intel snd_hda_codec snd_hwdep hp_wmi ppdev sparse_keymap snd_pcm snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq snd_timer snd_seq_device psmouse snd serio_raw tpm_infineon soundcore i915 snd_page_alloc tpm_tis parport_pc tpm tpm_bios drm_kms_helper drm i2c_algo_bit video lp parport usbhid hid sg sr_mod sd_mod ehci_hcd uhci_hcd usbcore e1000e usb_common floppy [ 3105.018408] [ 3105.018419] Pid: 189, comm: khubd Tainted: G I 3.2.0-rc7+ #29 Hewlett-Packard HP Compaq dc7800p Convertible Minitower/0AACh [ 3105.018481] RIP: 0010:[] [] usb_stor_probe1+0x2fd/0xc20 [usb_storage] [ 3105.018536] RSP: 0018:ffff880056a3d830 EFLAGS: 00010286 [ 3105.018562] RAX: ffff880065f4e648 RBX: ffff88006bb28000 RCX: 0000000000000000 [ 3105.018597] RDX: ffff88006f23c7b0 RSI: 0000000000000001 RDI: 0000000000000206 [ 3105.018632] RBP: ffff880056a3d900 R08: 0000000000000000 R09: ffff880067365000 [ 3105.018665] R10: 00000000000002ac R11: 0000000000000010 R12: ffff6000b41a7340 [ 3105.018698] R13: ffff880065f4ef60 R14: ffff88006bb28b88 R15: ffff88006f23d270 [ 3105.018733] FS: 0000000000000000(0000) GS:ffff88007a200000(0000) knlGS:0000000000000000 [ 3105.018773] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 3105.018801] CR2: 00007fc99c8c4650 CR3: 0000000001e05000 CR4: 00000000000006f0 [ 3105.018835] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 3105.018870] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 3105.018906] Process khubd (pid: 189, threadinfo ffff880056a3c000, task ffff88005677a400) [ 3105.018945] Stack: [ 3105.018959] 0000000000000000 0000000000000000 ffff880056a3d8d0 0000000000000002 [ 3105.019011] 0000000000000000 ffff880056a3d918 ffff880000000000 0000000000000002 [ 3105.019058] ffff880056a3d8d0 0000000000000012 ffff880056a3d8d0 0000000000000006 [ 3105.019105] Call Trace: [ 3105.019128] [] storage_probe+0xa4/0xe0 [usb_storage] [ 3105.019173] [] usb_probe_interface+0x172/0x330 [usbcore] [ 3105.019211] [] driver_probe_device+0x257/0x3b0 [ 3105.019243] [] __device_attach+0x73/0x90 [ 3105.019272] [] ? __driver_attach+0x110/0x110 [ 3105.019303] [] bus_for_each_drv+0x9c/0xf0 [ 3105.019334] [] device_attach+0xf7/0x120 [ 3105.019364] [] bus_probe_device+0x45/0x80 [ 3105.019396] [] device_add+0x876/0x990 [ 3105.019434] [] usb_set_configuration+0x822/0x9e0 [usbcore] [ 3105.019479] [] generic_probe+0x62/0xf0 [usbcore] [ 3105.019518] [] usb_probe_device+0x66/0xb0 [usbcore] [ 3105.019555] [] driver_probe_device+0x257/0x3b0 [ 3105.019589] [] __device_attach+0x73/0x90 [ 3105.019617] [] ? __driver_attach+0x110/0x110 [ 3105.019648] [] bus_for_each_drv+0x9c/0xf0 [ 3105.019680] [] device_attach+0xf7/0x120 [ 3105.019709] [] bus_probe_device+0x45/0x80 [ 3105.021040] usb usb6: usb auto-resume [ 3105.021045] usb usb6: wakeup_rh [ 3105.024849] [] device_add+0x876/0x990 [ 3105.025086] [] usb_new_device+0x1e7/0x2b0 [usbcore] [ 3105.025086] [] hub_thread+0xb27/0x1ec0 [usbcore] [ 3105.025086] [] ? wake_up_bit+0x50/0x50 [ 3105.025086] [] ? usb_remote_wakeup+0xa0/0xa0 [usbcore] [ 3105.025086] [] kthread+0xd8/0xf0 [ 3105.025086] [] kernel_thread_helper+0x4/0x10 [ 3105.025086] [] ? _raw_spin_unlock_irq+0x50/0x80 [ 3105.025086] [] ? retint_restore_args+0x13/0x13 [ 3105.025086] [] ? __init_kthread_worker+0x80/0x80 [ 3105.025086] [] ? gs_change+0x13/0x13 [ 3105.025086] Code: 00 48 83 05 cd ad 00 00 01 48 83 05 cd ad 00 00 01 4c 8b ab 30 0c 00 00 48 8b 50 08 48 83 c0 30 48 89 45 a0 4c 89 a3 40 0c 00 00 <41> 0f b6 44 24 10 48 89 55 a8 3c ff 0f 84 b8 04 00 00 48 83 05 [ 3105.025086] RIP [] usb_stor_probe1+0x2fd/0xc20 [usb_storage] [ 3105.025086] RSP [ 3105.060037] hub 6-0:1.0: hub_resume [ 3105.062616] usb usb5: usb auto-resume [ 3105.064317] ehci_hcd 0000:00:1d.7: resume root hub [ 3105.094809] ---[ end trace a7919e7f17c0a727 ]--- [ 3105.130069] hub 5-0:1.0: hub_resume [ 3105.132131] usb usb4: usb auto-resume [ 3105.132136] usb usb4: wakeup_rh [ 3105.180059] hub 4-0:1.0: hub_resume [ 3106.290052] usb usb6: suspend_rh (auto-stop) [ 3106.290077] usb usb4: suspend_rh (auto-stop) Signed-off-by: Huajun Li Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index c325e69415a1..9e069efeefee 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -1073,6 +1073,7 @@ static struct usb_driver usb_storage_driver = { .id_table = usb_storage_usb_ids, .supports_autosuspend = 1, .soft_unbind = 1, + .no_dynamic_id = 1, }; static int __init usb_stor_init(void) -- cgit v1.2.3 From 966c248e661ce7d265caeb73c7d0aa68fbf8801a Mon Sep 17 00:00:00 2001 From: Tanmay Upadhyay Date: Thu, 8 Dec 2011 10:03:49 +0530 Subject: USB: pxa168: Fix compilation error commit 35657c4d72925936c7219cc5caac118ca632acc2 upstream. After commit c430131a02d677aa708f56342c1565edfdacb3c0 (Support controllers with big endian capability regs), HC_LENGTH takes two arguments. This patch fixes following compilation error: In file included from drivers/usb/host/ehci-hcd.c:1323: drivers/usb/host/ehci-pxa168.c:302:54: error: macro "HC_LENGTH" requires 2 arguments, but only 1 given In file included from drivers/usb/host/ehci-hcd.c:1323: drivers/usb/host/ehci-pxa168.c: In function 'ehci_pxa168_drv_probe': drivers/usb/host/ehci-pxa168.c:302: error: 'HC_LENGTH' undeclared (first use in this function) drivers/usb/host/ehci-pxa168.c:302: error: (Each undeclared identifier is reported only once drivers/usb/host/ehci-pxa168.c:302: error: for each function it appears in.) Signed-off-by: Tanmay Upadhyay Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-pxa168.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-pxa168.c b/drivers/usb/host/ehci-pxa168.c index ac0c16e8f539..8d0e7a22e711 100644 --- a/drivers/usb/host/ehci-pxa168.c +++ b/drivers/usb/host/ehci-pxa168.c @@ -299,7 +299,7 @@ static int __devinit ehci_pxa168_drv_probe(struct platform_device *pdev) ehci = hcd_to_ehci(hcd); ehci->caps = hcd->regs + 0x100; ehci->regs = hcd->regs + 0x100 + - HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); + HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); hcd->has_tt = 1; ehci->sbrn = 0x20; -- cgit v1.2.3 From dd857f5b4dc1d8d010da1711b71be789054fbcbe Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 3 Jan 2012 09:58:54 +0100 Subject: USB: add quirk for another camera commit 35284b3d2f68a8a3703745e629999469f78386b5 upstream. The Guillemot Webcam Hercules Dualpix Exchange camera has been reported with a second ID. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/quirks.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index ecf12e15a7ef..4c65eb6a867a 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -117,9 +117,12 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x06a3, 0x0006), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, - /* Guillemot Webcam Hercules Dualpix Exchange*/ + /* Guillemot Webcam Hercules Dualpix Exchange (2nd ID) */ { USB_DEVICE(0x06f8, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Guillemot Webcam Hercules Dualpix Exchange*/ + { USB_DEVICE(0x06f8, 0x3005), .driver_info = USB_QUIRK_RESET_RESUME }, + /* M-Systems Flash Disk Pioneers */ { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, -- cgit v1.2.3 From 945d49b38f4e3aa8a570b2fe51f179e7c2181b4d Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Mon, 19 Dec 2011 22:01:54 +0200 Subject: usb: musb: fix pm_runtime mismatch commit 772aed45b604c5ff171f0f12c12392d868333f79 upstream. In musb_init_controller() there's a pm_runtime_put(), but there's no pm_runtime_get(), which creates a mismatch that causes the driver to sleep when it shouldn't. This was introduced in 7acc619[1], but it wasn't triggered in my setup until 18a2689[2] was merged to Linus' branch at point df0914[3]. IOW; when PM is working as it was supposed to. However, it seems most of the time this is used in a way that keeps the counter above 0, so nobody noticed. Also, it seems to depend on the configuration used in versions before 3.1, but not later (or in it). I found the problem by loading isp1704_charger before any usb gadgets: http://article.gmane.org/gmane.linux.kernel/1226122 All versions after 2.6.39 are affected. [1] usb: musb: Idle path retention and offmode support for OMAP3 [2] OMAP2+: musb: hwmod adaptation for musb registration [3] Merge branch 'omap-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6 Cc: Hema HK Signed-off-by: Felipe Contreras Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index b63ab1570103..920f04e5f3a8 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2012,8 +2012,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) if (status < 0) goto fail3; - pm_runtime_put(musb->controller); - status = musb_init_debugfs(musb); if (status < 0) goto fail4; -- cgit v1.2.3 From b4868343c4dde5315ffebc08de71ddffdd1460d8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sun, 6 Nov 2011 19:06:21 +0100 Subject: USB: omninet: fix write_room commit 694c6301e515bad574af74b6552134c4d9dcb334 upstream. Fix regression introduced by commit 507ca9bc047666 ([PATCH] USB: add ability for usb-serial drivers to determine if their write urb is currently being used.) which inverted the logic in write_room so that it returns zero when the write urb is actually free. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/omninet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 60f38d5e64fc..0a8c1e64b247 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -315,7 +315,7 @@ static int omninet_write_room(struct tty_struct *tty) int room = 0; /* Default: no room */ /* FIXME: no consistent locking for write_urb_busy */ - if (wport->write_urb_busy) + if (!wport->write_urb_busy) room = wport->bulk_out_size - OMNINET_HEADERLEN; dbg("%s - returns %d", __func__, room); -- cgit v1.2.3 From 3ff8999cb9dabcac0cbb8a778f79fb991f2358c8 Mon Sep 17 00:00:00 2001 From: Janne Snabb Date: Wed, 28 Dec 2011 19:36:00 +0000 Subject: usb: option: add ZD Incorporated HSPA modem commit 3c8c9316710b83e906e425024153bf0929887b59 upstream. Add support for Chinese Noname HSPA USB modem which is apparently manufactured by a company called ZD Incorporated (based on texts in the Windows drivers). This product is available at least from Dealextreme (SKU 80032) and possibly in India with name Olive V-MW250. It is based on Qualcomm MSM6280 chip. I needed to also add "options usb-storage quirks=0685:7000:i" in modprobe configuration because udevd or the kernel keeps poking the embedded fake-cd-rom which fails and causes the device to reset. There might be a better way to accomplish the same. usb_modeswitch is not needed with this device. Signed-off-by: Janne Snabb Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 6dd64534fad0..c96b6b6509fb 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -476,6 +476,10 @@ static void option_instat_callback(struct urb *urb); #define VIETTEL_VENDOR_ID 0x2262 #define VIETTEL_PRODUCT_VT1000 0x0002 +/* ZD Incorporated */ +#define ZD_VENDOR_ID 0x0685 +#define ZD_PRODUCT_7000 0x7000 + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -1178,6 +1182,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU528) }, { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) }, { USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); -- cgit v1.2.3 From d2758dc6e9a3a0243e120df6132406f409ffd2bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20Schr=C3=B6der?= Date: Thu, 5 Jan 2012 20:34:40 +0100 Subject: USB: Add USB-ID for Multiplex RC serial adapter to cp210x.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 08e87d0d773dc9ca5faf4c3306e238ed0ea129b0 upstream. Hi, below patch adds the USB-ID of the serial adapters sold by Multiplex RC (www.multiplex-rc.de). Signed-off-by: Malte Schröder Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index fd67cc53545b..a1a324b30d2d 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -92,6 +92,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */ { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */ { USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */ + { USB_DEVICE(0x10C4, 0x81A9) }, /* Multiplex RC Interface */ { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */ { USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */ { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ -- cgit v1.2.3 From 4781ace0ddff8057f2c1bf1811ae4886f8b88876 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sat, 3 Dec 2011 23:41:31 +0100 Subject: usb: fix number of mapped SG DMA entries commit bc677d5b64644c399cd3db6a905453e611f402ab upstream. Add a new field num_mapped_sgs to struct urb so that we have a place to store the number of mapped entries and can also retain the original value of entries in num_sgs. Previously, usb_hcd_map_urb_for_dma() would overwrite this with the number of mapped entries, which would break dma_unmap_sg() because it requires the original number of entries. This fixes warnings like the following when using USB storage devices: ------------[ cut here ]------------ WARNING: at lib/dma-debug.c:902 check_unmap+0x4e4/0x695() ehci_hcd 0000:00:12.2: DMA-API: device driver frees DMA sg list with different entry count [map count=4] [unmap count=1] Modules linked in: ohci_hcd ehci_hcd Pid: 0, comm: kworker/0:1 Not tainted 3.2.0-rc2+ #319 Call Trace: [] warn_slowpath_common+0x80/0x98 [] warn_slowpath_fmt+0x41/0x43 [] check_unmap+0x4e4/0x695 [] ? trace_hardirqs_off+0xd/0xf [] ? _raw_spin_unlock_irqrestore+0x33/0x50 [] debug_dma_unmap_sg+0xeb/0x117 [] usb_hcd_unmap_urb_for_dma+0x71/0x188 [] unmap_urb_for_dma+0x20/0x22 [] usb_hcd_giveback_urb+0x5d/0xc0 [] ehci_urb_done+0xf7/0x10c [ehci_hcd] [] qh_completions+0x429/0x4bd [ehci_hcd] [] ehci_work+0x95/0x9c0 [ehci_hcd] ... ---[ end trace f29ac88a5a48c580 ]--- Mapped at: [] debug_dma_map_sg+0x45/0x139 [] usb_hcd_map_urb_for_dma+0x22e/0x478 [] usb_hcd_submit_urb+0x63f/0x6fa [] usb_submit_urb+0x2c7/0x2de [] usb_sg_wait+0x55/0x161 Signed-off-by: Clemens Ladisch Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 5 ++--- drivers/usb/host/ehci-q.c | 2 +- drivers/usb/host/uhci-q.c | 2 +- drivers/usb/host/whci/qset.c | 4 ++-- drivers/usb/host/xhci-ring.c | 4 ++-- 5 files changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 13222d352a61..179e3646241d 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1412,11 +1412,10 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, ret = -EAGAIN; else urb->transfer_flags |= URB_DMA_MAP_SG; - if (n != urb->num_sgs) { - urb->num_sgs = n; + urb->num_mapped_sgs = n; + if (n != urb->num_sgs) urb->transfer_flags |= URB_DMA_SG_COMBINED; - } } else if (urb->sg) { struct scatterlist *sg = urb->sg; urb->transfer_dma = dma_map_page( diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 4e4066c35a09..fef1db3da37f 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -647,7 +647,7 @@ qh_urb_transaction ( /* * data transfer stage: buffer setup */ - i = urb->num_sgs; + i = urb->num_mapped_sgs; if (len > 0 && i > 0) { sg = urb->sg; buf = sg_dma_address(sg); diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index f6ca80ee4cec..d2c6f5ac4626 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -943,7 +943,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, if (usb_pipein(urb->pipe)) status |= TD_CTRL_SPD; - i = urb->num_sgs; + i = urb->num_mapped_sgs; if (len > 0 && i > 0) { sg = urb->sg; data = sg_dma_address(sg); diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c index a403b53e86b9..76083ae92138 100644 --- a/drivers/usb/host/whci/qset.c +++ b/drivers/usb/host/whci/qset.c @@ -443,7 +443,7 @@ static int qset_add_urb_sg(struct whc *whc, struct whc_qset *qset, struct urb *u remaining = urb->transfer_buffer_length; - for_each_sg(urb->sg, sg, urb->num_sgs, i) { + for_each_sg(urb->sg, sg, urb->num_mapped_sgs, i) { dma_addr_t dma_addr; size_t dma_remaining; dma_addr_t sp, ep; @@ -561,7 +561,7 @@ static int qset_add_urb_sg_linearize(struct whc *whc, struct whc_qset *qset, remaining = urb->transfer_buffer_length; - for_each_sg(urb->sg, sg, urb->num_sgs, i) { + for_each_sg(urb->sg, sg, urb->num_mapped_sgs, i) { size_t len; size_t sg_remaining; void *orig; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 9f1d4b15d818..d28c5865f3ef 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2561,7 +2561,7 @@ static unsigned int count_sg_trbs_needed(struct xhci_hcd *xhci, struct urb *urb) struct scatterlist *sg; sg = NULL; - num_sgs = urb->num_sgs; + num_sgs = urb->num_mapped_sgs; temp = urb->transfer_buffer_length; xhci_dbg(xhci, "count sg list trbs: \n"); @@ -2745,7 +2745,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, return -EINVAL; num_trbs = count_sg_trbs_needed(xhci, urb); - num_sgs = urb->num_sgs; + num_sgs = urb->num_mapped_sgs; total_packet_count = roundup(urb->transfer_buffer_length, usb_endpoint_maxp(&urb->ep->desc)); -- cgit v1.2.3 From 5b511b783385bc68663e4729be7f169ce3061e6d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 4 Jan 2012 23:29:18 +0100 Subject: xhci: Properly handle COMP_2ND_BW_ERR commit 71d85724bdd947a3b42a88d08af79f290a1a767b upstream. I encountered a result of COMP_2ND_BW_ERR while improving how the pwc webcam driver handles not having the full usb1 bandwidth available to itself. I created the following test setup, a NEC xhci controller with a single TT USB 2 hub plugged into it, with a usb keyboard and a pwc webcam plugged into the usb2 hub. This caused the following to show up in dmesg when trying to stream from the pwc camera at its highest alt setting: xhci_hcd 0000:01:00.0: ERROR: unexpected command completion code 0x23. usb 6-2.1: Not enough bandwidth for altsetting 9 And usb_set_interface returned -EINVAL, which caused my pwc code to not do the right thing as it expected -ENOSPC. This patch makes the xhci driver properly handle COMP_2ND_BW_ERR and makes usb_set_interface return -ENOSPC as expected. This should be backported to stable kernels as old as 2.6.32. Signed-off-by: Hans de Goede Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 1 + drivers/usb/host/xhci.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index a1afb7c39f7e..36f9dd81c49e 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1620,6 +1620,7 @@ static int xhci_configure_endpoint_result(struct xhci_hcd *xhci, /* FIXME: can we allocate more resources for the HC? */ break; case COMP_BW_ERR: + case COMP_2ND_BW_ERR: dev_warn(&udev->dev, "Not enough bandwidth " "for new device state.\n"); ret = -ENOSPC; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 3c8fbd2772ea..09eda3a8e51c 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1033,7 +1033,6 @@ struct xhci_transfer_event { /* Invalid Stream ID Error */ #define COMP_STRID_ERR 34 /* Secondary Bandwidth Error - may be returned by a Configure Endpoint cmd */ -/* FIXME - check for this */ #define COMP_2ND_BW_ERR 35 /* Split Transaction Error */ #define COMP_SPLIT_ERR 36 -- cgit v1.2.3 From d2570fc048ca1307e64572c825e0d7908bd60a21 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 2 Jan 2012 13:35:41 +0200 Subject: usb: ch9: fix up MaxStreams helper commit 18b7ede5f7ee2092aedcb578d3ac30bd5d4fc23c upstream. [ removed the dwc3 portion of the patch as it didn't apply to older kernels - gregkh] According to USB 3.0 Specification Table 9-22, if bmAttributes [4:0] are set to zero, it means "no streams supported", but the way this helper was defined on Linux, we will *always* have one stream which might cause several problems. For example on DWC3, we would tell the controller endpoint has streams enabled and yet start transfers with Stream ID set to 0, which would goof up the host side. While doing that, convert the macro to an inline function due to the different checks we now need. Signed-off-by: Felipe Balbi Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 36f9dd81c49e..b33f0598ccfe 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -2797,8 +2797,7 @@ static int xhci_calculate_streams_and_bitmask(struct xhci_hcd *xhci, if (ret < 0) return ret; - max_streams = USB_SS_MAX_STREAMS( - eps[i]->ss_ep_comp.bmAttributes); + max_streams = usb_ss_max_streams(&eps[i]->ss_ep_comp); if (max_streams < (*num_streams - 1)) { xhci_dbg(xhci, "Ep 0x%x only supports %u stream IDs.\n", eps[i]->desc.bEndpointAddress, -- cgit v1.2.3 From 4a75c219087a4079e668c3e5836d64009446c0d3 Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Sat, 7 Jan 2012 12:15:16 -0800 Subject: asix: fix infinite loop in rx_fixup() commit 6c15d74defd38e7e7f8805392578b7a1d508097e upstream. At this point if skb->len happens to be 2, the subsequant skb_pull(skb, 4) call won't work and the skb->len won't be decreased and won't ever reach 0, resulting in an infinite loop. With an ASIX 88772 under heavy load, without this patch, rx_fixup() reaches an infinite loop in less than a minute. With this patch applied, no infinite loop even after hours of heavy load. Signed-off-by: Aurelien Jacobs Cc: Jussi Kivilinna Signed-off-by: David S. Miller --- drivers/net/usb/asix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index e95f0e60a9bc..dd2625a3371a 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -376,7 +376,7 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) skb_pull(skb, (size + 1) & 0xfffe); - if (skb->len == 0) + if (skb->len < sizeof(header)) break; head = (u8 *) skb->data; -- cgit v1.2.3 From f60d8cd0b0e0def00c9ac54bb4becae034138484 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Sat, 31 Dec 2011 13:26:46 +0000 Subject: bonding: fix error handling if slave is busy (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f7d9821a6a9c83450ac35e76d3709e32fd38b76f upstream. If slave device already has a receive handler registered, then the error unwind of bonding device enslave function is broken. The following will leave a pointer to freed memory in the slave device list, causing a later kernel panic. # modprobe dummy # ip li add dummy0-1 link dummy0 type macvlan # modprobe bonding # echo +dummy0 >/sys/class/net/bond0/bonding/slaves The fix is to detach the slave (which removes it from the list) in the unwind path. Signed-off-by: Stephen Hemminger Reviewed-by: Nicolas de Pesloüan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/bonding/bond_main.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 7f8756825b8a..e58aa2b7a153 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1822,7 +1822,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) "but new slave device does not support netpoll.\n", bond_dev->name); res = -EBUSY; - goto err_close; + goto err_detach; } } #endif @@ -1831,7 +1831,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) res = bond_create_slave_symlinks(bond_dev, slave_dev); if (res) - goto err_close; + goto err_detach; res = netdev_rx_handler_register(slave_dev, bond_handle_frame, new_slave); @@ -1852,6 +1852,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) err_dest_symlinks: bond_destroy_slave_symlinks(bond_dev, slave_dev); +err_detach: + write_lock_bh(&bond->lock); + bond_detach_slave(bond, new_slave); + write_unlock_bh(&bond->lock); + err_close: dev_close(slave_dev); -- cgit v1.2.3 From f9fd8d6232137e255fc9409a81cf282817472b6f Mon Sep 17 00:00:00 2001 From: Thilo-Alexander Ginkel Date: Sat, 17 Dec 2011 10:55:10 +0100 Subject: usb: cdc-acm: Fix acm_tty_hangup() vs. acm_tty_close() race [Not upstream as it was fixed differently for 3.3 with a much more "intrusive" rework of the driver - gregkh] There is a race condition involving acm_tty_hangup() and acm_tty_close() where hangup() would attempt to access tty->driver_data without proper locking and NULL checking after close() has potentially already set it to NULL. One possibility to (sporadically) trigger this behavior is to perform a suspend/resume cycle with a running WWAN data connection. This patch addresses the issue by introducing a NULL check for tty->driver_data in acm_tty_hangup() protected by open_mutex and exiting gracefully when hangup() is invoked on a device that has already been closed. Signed-off-by: Thilo-Alexander Ginkel Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index ea5e487448bf..e61d9c43e985 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -554,10 +554,18 @@ static void acm_port_down(struct acm *acm) static void acm_tty_hangup(struct tty_struct *tty) { - struct acm *acm = tty->driver_data; - tty_port_hangup(&acm->port); + struct acm *acm; + mutex_lock(&open_mutex); + acm = tty->driver_data; + + if (!acm) + goto out; + + tty_port_hangup(&acm->port); acm_port_down(acm); + +out: mutex_unlock(&open_mutex); } -- cgit v1.2.3