From 725dd00a99dd5fb94af55115bf7ade59624c8bc3 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Sun, 30 Sep 2012 13:19:19 +0400 Subject: serial: sccnxp: Allows the driver to be compiled as a module Signed-off-by: Alexander Shiyan Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 233fbaaf2559..2a53be5f010d 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1150,7 +1150,7 @@ config SERIAL_SC26XX_CONSOLE Support for Console on SC2681/SC2692 serial ports. config SERIAL_SCCNXP - bool "SCCNXP serial port support" + tristate "SCCNXP serial port support" depends on !SERIAL_SC26XX select SERIAL_CORE default n @@ -1162,7 +1162,7 @@ config SERIAL_SCCNXP config SERIAL_SCCNXP_CONSOLE bool "Console on SCCNXP serial port" - depends on SERIAL_SCCNXP + depends on SERIAL_SCCNXP=y select SERIAL_CORE_CONSOLE help Support for console on SCCNXP serial ports. -- cgit v1.2.3-55-g7522 From ee98581f624a6ce0f17706d7ff2a161aacfb977a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 27 Sep 2012 20:38:26 +0200 Subject: staging: serial: dgrp: Add missing #include On m68k: drivers/staging/dgrp/dgrp_mon_ops.c: In function ‘dgrp_mon_read’: drivers/staging/dgrp/dgrp_mon_ops.c:304: error: implicit declaration of function ‘copy_to_user’ drivers/staging/dgrp/dgrp_specproc.c: In function ‘config_proc_write’: drivers/staging/dgrp/dgrp_specproc.c:470: error: implicit declaration of function ‘copy_from_user’ drivers/staging/dgrp/dgrp_tty.c: In function ‘drp_wmove’: drivers/staging/dgrp/dgrp_tty.c:1284: error: implicit declaration of function ‘copy_from_user’ drivers/staging/dgrp/dgrp_tty.c: In function ‘get_modem_info’: drivers/staging/dgrp/dgrp_tty.c:2267: error: implicit declaration of function ‘put_user’ drivers/staging/dgrp/dgrp_tty.c: In function ‘set_modem_info’: drivers/staging/dgrp/dgrp_tty.c:2283: error: implicit declaration of function ‘access_ok’ drivers/staging/dgrp/dgrp_tty.c:2283: error: ‘VERIFY_READ’ undeclared (first use in this function) drivers/staging/dgrp/dgrp_tty.c:2283: error: (Each undeclared identifier is reported only once drivers/staging/dgrp/dgrp_tty.c:2283: error: for each function it appears in.) drivers/staging/dgrp/dgrp_tty.c:2287: error: implicit declaration of function ‘get_user’ drivers/staging/dgrp/dgrp_tty.c: In function ‘dgrp_tty_digigetedelay’: drivers/staging/dgrp/dgrp_tty.c:2474: error: implicit declaration of function ‘copy_to_user’ drivers/staging/dgrp/dgrp_tty.c: In function ‘dgrp_tty_ioctl’: drivers/staging/dgrp/dgrp_tty.c:2618: error: ‘VERIFY_WRITE’ undeclared (first use in this function) Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgrp/dgrp_mon_ops.c | 1 + drivers/staging/dgrp/dgrp_specproc.c | 1 + drivers/staging/dgrp/dgrp_tty.c | 1 + 3 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/dgrp/dgrp_mon_ops.c b/drivers/staging/dgrp/dgrp_mon_ops.c index 268dcb95204b..4792d056a365 100644 --- a/drivers/staging/dgrp/dgrp_mon_ops.c +++ b/drivers/staging/dgrp/dgrp_mon_ops.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "dgrp_common.h" diff --git a/drivers/staging/dgrp/dgrp_specproc.c b/drivers/staging/dgrp/dgrp_specproc.c index 28f5c9ab6b43..a5840e7d6665 100644 --- a/drivers/staging/dgrp/dgrp_specproc.c +++ b/drivers/staging/dgrp/dgrp_specproc.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include "dgrp_common.h" diff --git a/drivers/staging/dgrp/dgrp_tty.c b/drivers/staging/dgrp/dgrp_tty.c index 7d7de873870c..72f6fcfa9878 100644 --- a/drivers/staging/dgrp/dgrp_tty.c +++ b/drivers/staging/dgrp/dgrp_tty.c @@ -40,6 +40,7 @@ #include #include #include +#include #include "dgrp_common.h" -- cgit v1.2.3-55-g7522 From b70936d9ffbf0f45f4fa13a03122f015f13ecdb0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 5 Oct 2012 09:34:37 -0700 Subject: tty: serial: sccnxp: Fix bug with unterminated platform_id list The build even tells you that this is a bad thing: drivers/tty/serial/sccnxp: struct platform_device_id is 32 bytes. The last of 8 is: 0x73 0x63 0x36 0x38 0x36 0x39 0x32 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x54 0x0c 0x01 0x00 0x00 0x00 0x00 0x00 FATAL: drivers/tty/serial/sccnxp: struct platform_device_id is not terminated with a NULL entry! So fix this problem up before someone oopses their box when loading the driver, as this breaks the build. Cc: Alexander Shiyan Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sccnxp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index b7086d004f5f..e821068cd95b 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c @@ -971,6 +971,7 @@ static const struct platform_device_id sccnxp_id_table[] = { { "sc28202", SCCNXP_TYPE_SC28202 }, { "sc68681", SCCNXP_TYPE_SC68681 }, { "sc68692", SCCNXP_TYPE_SC68692 }, + { }, }; MODULE_DEVICE_TABLE(platform, sccnxp_id_table); -- cgit v1.2.3-55-g7522 From c77d7162a7ae451c2e895d7ef7fbeb0906107472 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sat, 6 Oct 2012 10:20:16 +0200 Subject: drm/i915: remove useless BUG_ON which caused a regression in 3.5. starting an old X server causes a kernel BUG since commit 1b50247a8d: ------------[ cut here ]------------ kernel BUG at drivers/gpu/drm/i915/i915_gem.c:3661! invalid opcode: 0000 [#1] SMP Modules linked in: snd_seq_dummy snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device snd_pcm_oss snd_mixer_oss uvcvideo +videobuf2_core videodev videobuf2_vmalloc videobuf2_memops uhci_hcd ath9k mac80211 snd_hda_codec_realtek ath9k_common microcode +ath9k_hw psmouse serio_raw sg ath cfg80211 atl1c lpc_ich mfd_core ehci_hcd snd_hda_intel snd_hda_codec snd_hwdep snd_pcm rtc_cmos +snd_timer snd evdev eeepc_laptop snd_page_alloc sparse_keymap Pid: 2866, comm: X Not tainted 3.5.6-rc1-eeepc #1 ASUSTeK Computer INC. 1005HA/1005HA EIP: 0060:[] EFLAGS: 00013297 CPU: 0 EIP is at i915_gem_entervt_ioctl+0xf1/0x110 EAX: f5941df4 EBX: f5940000 ECX: 00000000 EDX: 00020000 ESI: f5835400 EDI: 00000000 EBP: f51d7e38 ESP: f51d7e20 DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 CR0: 8005003b CR2: b760e0a0 CR3: 351b6000 CR4: 000007d0 DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 DR6: ffff0ff0 DR7: 00000400 Process X (pid: 2866, ti=f51d6000 task=f61af8d0 task.ti=f51d6000) Stack: 00000001 00000000 f5835414 f51d7e84 f5835400 f54f85c0 f51d7f10 c12b530b 00000001 c151b139 c14751b6 c152e030 00000b32 00006459 00000059 0000e200 00000001 00000000 00006459 c159ddd0 c12dc1a0 ffffffea 00000000 00000000 Call Trace: [] drm_ioctl+0x2eb/0x440 [] ? i915_gem_init+0xe0/0xe0 [] ? enqueue_hrtimer+0x1b/0x50 [] ? __hrtimer_start_range_ns+0x161/0x330 [] ? lock_hrtimer_base+0x23/0x50 [] ? hrtimer_try_to_cancel+0x33/0x70 [] ? drm_version+0x90/0x90 [] vfs_ioctl+0x31/0x50 [] do_vfs_ioctl+0x64/0x510 [] ? hrtimer_nanosleep+0x8e/0x100 [] ? update_rmtp+0x80/0x80 [] sys_ioctl+0x39/0x60 [] syscall_call+0x7/0xb Code: 83 c4 0c 5b 5e 5f 5d c3 c7 44 24 04 2c 05 53 c1 c7 04 24 6f ef 47 c1 e8 6e e0 fd ff c7 83 38 1e 00 00 00 00 00 00 e9 3f ff ff +ff <0f> 0b eb fe 0f 0b eb fe 8d b4 26 00 00 00 00 0f 0b eb fe 8d b6 EIP: [] i915_gem_entervt_ioctl+0xf1/0x110 SS:ESP 0068:f51d7e20 ---[ end trace dd332ec083cbd513 ]--- The crash happens here in i915_gem_entervt_ioctl() : 3659 BUG_ON(!list_empty(&dev_priv->mm.active_list)); 3660 BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); -> 3661 BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); 3662 mutex_unlock(&dev->struct_mutex); Quoting Chris : "That BUG_ON there is silly and can simply be removed. The check is to verify that no batches were submitted to the kernel whilst the UMS/GEM client was suspended - to which the BUG_ONs are a crude approximation. Furthermore, the checks are too late, since it means we attempted to program the hardware whilst it was in an invalid state, the BUG_ONs are the least of your concerns at that point." Note that this regression has been introduced in commit 1b50247a8ddde4af5aaa0e6bc125615372ce6c16 Author: Chris Wilson Date: Tue Apr 24 15:47:30 2012 +0100 drm/i915: Remove the list of pinned inactive objects Cc: Chris Wilson Signed-off-by: Willy Tarreau [danvet: Added note about the regressing commit and cc: stable.] Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b55eee38af76..53de95c05b16 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4099,7 +4099,6 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data, } BUG_ON(!list_empty(&dev_priv->mm.active_list)); - BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); mutex_unlock(&dev->struct_mutex); ret = drm_irq_install(dev); -- cgit v1.2.3-55-g7522 From 6ce9410047f9f06c1b3336d5215402b77d6fd70f Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 4 Oct 2012 19:20:03 +0200 Subject: drm/i915: paper over a pipe-enable vs pageflip race I've discovered this on my ivb machine while stress-testing the new flip_tests. Only harmful effect observed is that the timestamp is a bit bogus. Note that this is empirical duct-tape: I've noticed that we seem to only ever miss the very first vblank irq right after enabling the pipe. And with this hack applied I couldn't reproduce the failure case anywhere else any more. Tested-by: Imre Deak Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 67912febb322..9cecfd73b0b1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3253,6 +3253,16 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) if (HAS_PCH_CPT(dev)) intel_cpt_verify_modeset(dev, intel_crtc->pipe); + + /* + * There seems to be a race in PCH platform hw (at least on some + * outputs) where an enabled pipe still completes any pageflip right + * away (as if the pipe is off) instead of waiting for vblank. As soon + * as the first vblank happend, everything works as expected. Hence just + * wait for one vblank before returning to avoid strange things + * happening. + */ + intel_wait_for_vblank(dev, intel_crtc->pipe); } static void ironlake_crtc_disable(struct drm_crtc *crtc) -- cgit v1.2.3-55-g7522 From d01f87c0ffa96cb44faa78710711eb6e974b891c Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 4 Oct 2012 09:53:43 -0700 Subject: USB: Enable LPM after a failed probe. Before a driver is probed, we want to disable USB 3.0 Link Power Management (LPM), in case the driver needs hub-initiated LPM disabled. After the probe finishes, we want to attempt to re-enable LPM, order to balance the LPM ref count. When a probe fails (such as when libusual doesn't want to bind to a USB 3.0 mass storage device), make sure to balance the LPM ref counts by re-enabling LPM. This patch should be backported to kernels as old as 3.5, that contain the commit 8306095fd2c1100e8244c09bf560f97aca5a311d "USB: Disable USB 3.0 LPM in critical sections." Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/core/driver.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index ddd820d25288..6056db7af410 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -367,6 +367,10 @@ static int usb_probe_interface(struct device *dev) intf->condition = USB_INTERFACE_UNBOUND; usb_cancel_queued_reset(intf); + /* If the LPM disable succeeded, balance the ref counts. */ + if (!lpm_disable_error) + usb_unlocked_enable_lpm(udev); + /* Unbound interfaces are always runtime-PM-disabled and -suspended */ if (driver->supports_autosuspend) pm_runtime_disable(dev); -- cgit v1.2.3-55-g7522 From ae8963adb4ad8c5f2a89ca1d99fb7bb721e7599f Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 3 Oct 2012 11:18:05 -0700 Subject: usb: Don't enable LPM if the exit latency is zero. Some USB 3.0 devices signal that they don't implement Link PM by having all zeroes in the U1/U2 exit latencies in their SuperSpeed BOS descriptor. Don found that a Western Digital device he has experiences transfer errors when LPM is enabled. The lsusb shows the U1/U2 exit latencies are set to zero: Binary Object Store Descriptor: bLength 5 bDescriptorType 15 wTotalLength 22 bNumDeviceCaps 2 SuperSpeed USB Device Capability: bLength 10 bDescriptorType 16 bDevCapabilityType 3 bmAttributes 0x00 Latency Tolerance Messages (LTM) Supported wSpeedsSupported 0x000e Device can operate at Full Speed (12Mbps) Device can operate at High Speed (480Mbps) Device can operate at SuperSpeed (5Gbps) bFunctionalitySupport 1 Lowest fully-functional device speed is Full Speed (12Mbps) bU1DevExitLat 0 micro seconds bU2DevExitLat 0 micro seconds The fix is to not enable LPM for a particular link state if we find its corresponding exit latency is zero. This patch should be backported to kernels as old as 3.5, that contain the commit 1ea7e0e8e3d0f50901d335ea4178ab2aa8c88201 "USB: Add support to enable/disable USB3 link states." Signed-off-by: Sarah Sharp Reported-by: Don Zickus Tested-by: Don Zickus Cc: stable@vger.kernel.org --- drivers/usb/core/hub.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 673ee4696262..8f0478709323 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3415,6 +3415,16 @@ static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev, enum usb3_link_state state) { int timeout; + __u8 u1_mel = udev->bos->ss_cap->bU1devExitLat; + __le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat; + + /* If the device says it doesn't have *any* exit latency to come out of + * U1 or U2, it's probably lying. Assume it doesn't implement that link + * state. + */ + if ((state == USB3_LPM_U1 && u1_mel == 0) || + (state == USB3_LPM_U2 && u2_mel == 0)) + return; /* We allow the host controller to set the U1/U2 timeout internally * first, so that it can change its schedule to account for the -- cgit v1.2.3-55-g7522 From 65a95b75bc5afa7bbb844e222481044c1c4767eb Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 5 Oct 2012 10:32:07 -0700 Subject: usb: Send Set SEL before enabling parent U1/U2 timeout. The Set SEL control transfer tells a device the exit latencies associated with a device-initated U1 or U2 exit. Since a parent hub may initiate a transition to U1 soon after a downstream port's U1 timeout is set, we need to make sure the device receives the Set SEL transfer before the parent hub timeout is set. This patch should be backported to kernels as old as 3.5, that contain the commit 1ea7e0e8e3d0f50901d335ea4178ab2aa8c88201 "USB: Add support to enable/disable USB3 link states." Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/core/hub.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 8f0478709323..b8e11fff17be 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3319,16 +3319,6 @@ static int usb_set_device_initiated_lpm(struct usb_device *udev, } if (enable) { - /* - * First, let the device know about the exit latencies - * associated with the link state we're about to enable. - */ - ret = usb_req_set_sel(udev, state); - if (ret < 0) { - dev_warn(&udev->dev, "Set SEL for device-initiated " - "%s failed.\n", usb3_lpm_names[state]); - return -EBUSY; - } /* * Now send the control transfer to enable device-initiated LPM * for either U1 or U2. @@ -3414,7 +3404,7 @@ static int usb_set_lpm_timeout(struct usb_device *udev, static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev, enum usb3_link_state state) { - int timeout; + int timeout, ret; __u8 u1_mel = udev->bos->ss_cap->bU1devExitLat; __le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat; @@ -3426,6 +3416,17 @@ static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev, (state == USB3_LPM_U2 && u2_mel == 0)) return; + /* + * First, let the device know about the exit latencies + * associated with the link state we're about to enable. + */ + ret = usb_req_set_sel(udev, state); + if (ret < 0) { + dev_warn(&udev->dev, "Set SEL for device-initiated %s failed.\n", + usb3_lpm_names[state]); + return; + } + /* We allow the host controller to set the U1/U2 timeout internally * first, so that it can change its schedule to account for the * additional latency to send data to a device in a lower power -- cgit v1.2.3-55-g7522 From 1510a1a2d0946b34422fe8816187f274a5086904 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 5 Oct 2012 10:30:35 -0700 Subject: usb: trival: Fix debugging units mistake. SEL and PEL are in microseconds, not milliseconds. Also, fix a split string that will trigger checkpatch warnings. Signed-off-by: Sarah Sharp --- drivers/usb/core/hub.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b8e11fff17be..64854d76f529 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3241,8 +3241,7 @@ static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state) (state == USB3_LPM_U2 && (u2_sel > USB3_LPM_MAX_U2_SEL_PEL || u2_pel > USB3_LPM_MAX_U2_SEL_PEL))) { - dev_dbg(&udev->dev, "Device-initiated %s disabled due " - "to long SEL %llu ms or PEL %llu ms\n", + dev_dbg(&udev->dev, "Device-initiated %s disabled due to long SEL %llu us or PEL %llu us\n", usb3_lpm_names[state], u1_sel, u1_pel); return -EINVAL; } -- cgit v1.2.3-55-g7522 From f880b67dcbdedb49453f88d2ccb1a0937b046d82 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 9 Oct 2012 10:33:52 +0000 Subject: ARM: Xen: fix initial build problems * The XEN_BALLOON code requires the balloon infrastructure that is not getting built on ARM. * The tmem hypercall is not available on ARM * ARMv6 does not support cmpxchg on 16-bit words that are used in the Xen grant table code, so we must ensure that Xen support is only built on ARMv7-only kernels not combined ARMv6/v7 kernels. * sys-hypervisor.c needs to include linux/err.h in order to use the IS_ERR/PTR_ERR/ERR_PTR family of functions. Signed-off-by: Arnd Bergmann Acked-by: Ian Campbell Cc: Stefano Stabellini Cc: Konrad Rzeszutek Wilk Cc: Jeremy Fitzhardinge Cc: xen-devel@lists.xensource.com --- arch/arm/Kconfig | 1 + drivers/xen/Kconfig | 2 ++ drivers/xen/sys-hypervisor.c | 1 + 3 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 6d2f7f5c0036..e1d6ab2b3c93 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1846,6 +1846,7 @@ config XEN_DOM0 config XEN bool "Xen guest support on ARM (EXPERIMENTAL)" depends on EXPERIMENTAL && ARM && OF + depends on CPU_V7 && !CPU_V6 help Say Y if you want to run Linux in a Virtual Machine on Xen on ARM. diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index d4dffcd52873..126d8ce591ce 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -3,6 +3,7 @@ menu "Xen driver support" config XEN_BALLOON bool "Xen memory balloon driver" + depends on !ARM default y help The balloon driver allows the Xen domain to request more memory from @@ -145,6 +146,7 @@ config SWIOTLB_XEN config XEN_TMEM bool + depends on !ARM default y if (CLEANCACHE || FRONTSWAP) help Shim to interface in-kernel Transcendent Memory hooks diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c index 5e5ad7e28858..66a0a1475acf 100644 --- a/drivers/xen/sys-hypervisor.c +++ b/drivers/xen/sys-hypervisor.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3-55-g7522 From ea065f13cc0a037b55698bb1021ea0927d0046d1 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 30 Apr 2012 16:26:31 +0000 Subject: SCSI: ARM: ncr5380/oak uses no interrupts The ncr5380 driver is included by multiple board specific drivers, which may or may not use the interrupt handler. The oak variant doesn't, and should set the DONT_USE_INTR macro. Without this patch, building rpc_defconfig results in: drivers/scsi/arm/../NCR5380.c:1160:20: warning: 'oakscsi_intr' defined but not used [-Wunused-function] Signed-off-by: Arnd Bergmann Cc: Russell King Cc: "James E.J. Bottomley" Cc: linux-arm-kernel@lists.infradead.org Cc: linux-scsi@vger.kernel.org --- drivers/scsi/arm/oak.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index d25f944b59c2..fc6a5aabf66e 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -21,6 +21,7 @@ /*#define PSEUDO_DMA*/ #define OAKSCSI_PUBLIC_RELEASE 1 +#define DONT_USE_INTR #define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) #define NCR5380_local_declare() void __iomem *_base -- cgit v1.2.3-55-g7522 From 48968177312e01737c018fdb2430b703831cbc2e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 30 Apr 2012 16:26:27 +0000 Subject: SCSI: ARM: make fas216_dumpinfo function conditional The fas216_dumpinfo function is only used by __fas216_checkmagic, which is conditionally compiled, so we should put both functions inside of the same #ifdef. Without this patch, building rpc_defconfig results in: drivers/scsi/arm/fas216.c:182:13: warning: 'fas216_dumpinfo' defined but not used [-Wunused-function] Signed-off-by: Arnd Bergmann Cc: Russell King Cc: "James E.J. Bottomley" Cc: linux-arm-kernel@lists.infradead.org Cc: linux-scsi@vger.kernel.org --- drivers/scsi/arm/fas216.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c index 6206a666a8ec..737554c37d9e 100644 --- a/drivers/scsi/arm/fas216.c +++ b/drivers/scsi/arm/fas216.c @@ -179,6 +179,7 @@ static void print_SCp(struct scsi_pointer *SCp, const char *prefix, const char * SCp->buffers_residual, suffix); } +#ifdef CHECK_STRUCTURE static void fas216_dumpinfo(FAS216_Info *info) { static int used = 0; @@ -223,7 +224,6 @@ static void fas216_dumpinfo(FAS216_Info *info) info->internal_done, info->magic_end); } -#ifdef CHECK_STRUCTURE static void __fas216_checkmagic(FAS216_Info *info, const char *func) { int corruption = 0; -- cgit v1.2.3-55-g7522 From 8855e49b64668463d0db2f0deca7b517fdb63eee Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 4 Aug 2012 21:41:34 +0000 Subject: USB: EHCI: mark ehci_orion_conf_mbus_windows __devinit The __devinit section is going away soon, but while it's still there, we get a correct warning about ehci_orion_conf_mbus_windows being discarded before its caller, so it should be marked __devinit rather than __init. Without this patch, building dove_defconfig results in: WARNING: drivers/usb/host/built-in.o(.devinit.text+0x8a4): Section mismatch in reference from the function ehci_orion_drv_probe() to the function .init.text:ehci_orion_conf_mbus_windows() The function __devinit ehci_orion_drv_probe() references a function __init ehci_orion_conf_mbus_windows(). If ehci_orion_conf_mbus_windows is only used by ehci_orion_drv_probe then annotate ehci_orion_conf_mbus_windows with a matching annotation. Signed-off-by: Arnd Bergmann Acked-by: Alan Stern Cc: Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org --- drivers/usb/host/ehci-orion.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 8892d3642cef..1f5dd5ee5b79 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -160,7 +160,7 @@ static const struct hc_driver ehci_orion_hc_driver = { .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; -static void __init +static void __devinit ehci_orion_conf_mbus_windows(struct usb_hcd *hcd, const struct mbus_dram_target_info *dram) { -- cgit v1.2.3-55-g7522 From 26b6e44afb58432a5e998da0343757404f9de9ee Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Sun, 7 Oct 2012 08:51:07 -0700 Subject: drm/i915: Set guardband clipping workaround bit in the right register. A previous patch, namely: commit bf97b276ca04cee9ab65ffd378fa8e6aedd71ff6 Author: Daniel Vetter Date: Wed Apr 11 20:42:41 2012 +0200 drm/i915: implement w/a for incorrect guarband clipping accidentally set bit 5 in 3D_CHICKEN, which has nothing to do with clipping. This patch changes it to be set in 3D_CHICKEN3, where it belongs. The game "Dante" demonstrates random clipping issues when guardband clipping is enabled and bit 5 of 3D_CHICKEN3 isn't set. So the workaround is actually necessary. Cc: Daniel Vetter Cc: Oliver McFadden Acked-by: Paul Menzel Signed-off-by: Kenneth Graunke Reviewed-by: Mika Kuoppala Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 2 +- drivers/gpu/drm/i915/intel_pm.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 64c1be0a9cfd..a4162ddff6c5 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -521,7 +521,7 @@ */ # define _3D_CHICKEN2_WM_READ_PIPELINED (1 << 14) #define _3D_CHICKEN3 0x02090 -#define _3D_CHICKEN_SF_DISABLE_FASTCLIP_CULL (1 << 5) +#define _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL (1 << 5) #define MI_MODE 0x0209c # define VS_TIMER_DISPATCH (1 << 6) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b3b4b6cea8b0..72f41aaa71ff 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3442,8 +3442,8 @@ static void gen6_init_clock_gating(struct drm_device *dev) GEN6_RCCUNIT_CLOCK_GATE_DISABLE); /* Bspec says we need to always set all mask bits. */ - I915_WRITE(_3D_CHICKEN, (0xFFFF << 16) | - _3D_CHICKEN_SF_DISABLE_FASTCLIP_CULL); + I915_WRITE(_3D_CHICKEN3, (0xFFFF << 16) | + _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL); /* * According to the spec the following bits should be -- cgit v1.2.3-55-g7522 From acb868d3d710b09a356d848e0cd44d9713a9e274 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 26 Sep 2012 13:47:30 +0100 Subject: drm/i915: Disallow preallocation of requests The intention was to allow the caller to avoid a failure to queue a request having already written commands to the ring. However, this is a moot point as the i915_add_request() can fail for other reasons than a mere allocation failure and those failure cases are more likely than ENOMEM. So the overlay code already had to handle i915_add_request() failures, and due to commit 3bb73aba1ed5198a2c1dfaac4f3c95459930d84a Author: Chris Wilson Date: Fri Jul 20 12:40:59 2012 +0100 drm/i915: Allow late allocation of request for i915_add_request() the error handling code in intel_overlay.c was subject to causing double-frees, as found by coverity. Rather than further complicate i915_add_request() and callers, realise the battle is lost and adapt intel_overlay.c to take advantage of the late allocation of requests. v2: Handle callers passing in a NULL seqno. v3: Ditto. This time for sure. Signed-off-by: Chris Wilson Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 15 ++++---- drivers/gpu/drm/i915/intel_overlay.c | 72 ++++++++---------------------------- 3 files changed, 24 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4f2831aa5fed..d5138c3a156b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1427,7 +1427,7 @@ int __must_check i915_gpu_idle(struct drm_device *dev); int __must_check i915_gem_idle(struct drm_device *dev); int i915_add_request(struct intel_ring_buffer *ring, struct drm_file *file, - struct drm_i915_gem_request *request); + u32 *seqno); int __must_check i915_wait_seqno(struct intel_ring_buffer *ring, uint32_t seqno); int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 53de95c05b16..04b0c070cdf8 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1956,11 +1956,12 @@ i915_gem_next_request_seqno(struct intel_ring_buffer *ring) int i915_add_request(struct intel_ring_buffer *ring, struct drm_file *file, - struct drm_i915_gem_request *request) + u32 *out_seqno) { drm_i915_private_t *dev_priv = ring->dev->dev_private; - uint32_t seqno; + struct drm_i915_gem_request *request; u32 request_ring_position; + u32 seqno; int was_empty; int ret; @@ -1975,11 +1976,9 @@ i915_add_request(struct intel_ring_buffer *ring, if (ret) return ret; - if (request == NULL) { - request = kmalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL) - return -ENOMEM; - } + request = kmalloc(sizeof(*request), GFP_KERNEL); + if (request == NULL) + return -ENOMEM; seqno = i915_gem_next_request_seqno(ring); @@ -2031,6 +2030,8 @@ i915_add_request(struct intel_ring_buffer *ring, } } + if (out_seqno) + *out_seqno = seqno; return 0; } diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index afd0f30ab882..555912f510a9 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -210,7 +210,6 @@ static void intel_overlay_unmap_regs(struct intel_overlay *overlay, } static int intel_overlay_do_wait_request(struct intel_overlay *overlay, - struct drm_i915_gem_request *request, void (*tail)(struct intel_overlay *)) { struct drm_device *dev = overlay->dev; @@ -219,12 +218,10 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay, int ret; BUG_ON(overlay->last_flip_req); - ret = i915_add_request(ring, NULL, request); - if (ret) { - kfree(request); - return ret; - } - overlay->last_flip_req = request->seqno; + ret = i915_add_request(ring, NULL, &overlay->last_flip_req); + if (ret) + return ret; + overlay->flip_tail = tail; ret = i915_wait_seqno(ring, overlay->last_flip_req); if (ret) @@ -241,7 +238,6 @@ static int intel_overlay_on(struct intel_overlay *overlay) struct drm_device *dev = overlay->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; - struct drm_i915_gem_request *request; int ret; BUG_ON(overlay->active); @@ -249,17 +245,9 @@ static int intel_overlay_on(struct intel_overlay *overlay) WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE)); - request = kzalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL) { - ret = -ENOMEM; - goto out; - } - ret = intel_ring_begin(ring, 4); - if (ret) { - kfree(request); - goto out; - } + if (ret) + return ret; intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON); intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE); @@ -267,9 +255,7 @@ static int intel_overlay_on(struct intel_overlay *overlay) intel_ring_emit(ring, MI_NOOP); intel_ring_advance(ring); - ret = intel_overlay_do_wait_request(overlay, request, NULL); -out: - return ret; + return intel_overlay_do_wait_request(overlay, NULL); } /* overlay needs to be enabled in OCMD reg */ @@ -279,17 +265,12 @@ static int intel_overlay_continue(struct intel_overlay *overlay, struct drm_device *dev = overlay->dev; drm_i915_private_t *dev_priv = dev->dev_private; struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; - struct drm_i915_gem_request *request; u32 flip_addr = overlay->flip_addr; u32 tmp; int ret; BUG_ON(!overlay->active); - request = kzalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL) - return -ENOMEM; - if (load_polyphase_filter) flip_addr |= OFC_UPDATE; @@ -299,22 +280,14 @@ static int intel_overlay_continue(struct intel_overlay *overlay, DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp); ret = intel_ring_begin(ring, 2); - if (ret) { - kfree(request); + if (ret) return ret; - } + intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); intel_ring_emit(ring, flip_addr); intel_ring_advance(ring); - ret = i915_add_request(ring, NULL, request); - if (ret) { - kfree(request); - return ret; - } - - overlay->last_flip_req = request->seqno; - return 0; + return i915_add_request(ring, NULL, &overlay->last_flip_req); } static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay) @@ -350,15 +323,10 @@ static int intel_overlay_off(struct intel_overlay *overlay) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; u32 flip_addr = overlay->flip_addr; - struct drm_i915_gem_request *request; int ret; BUG_ON(!overlay->active); - request = kzalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL) - return -ENOMEM; - /* According to intel docs the overlay hw may hang (when switching * off) without loading the filter coeffs. It is however unclear whether * this applies to the disabling of the overlay or to the switching off @@ -366,10 +334,9 @@ static int intel_overlay_off(struct intel_overlay *overlay) flip_addr |= OFC_UPDATE; ret = intel_ring_begin(ring, 6); - if (ret) { - kfree(request); + if (ret) return ret; - } + /* wait for overlay to go idle */ intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); intel_ring_emit(ring, flip_addr); @@ -380,8 +347,7 @@ static int intel_overlay_off(struct intel_overlay *overlay) intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); intel_ring_advance(ring); - return intel_overlay_do_wait_request(overlay, request, - intel_overlay_off_tail); + return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail); } /* recover from an interruption due to a signal @@ -426,24 +392,16 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay) return 0; if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) { - struct drm_i915_gem_request *request; - /* synchronous slowpath */ - request = kzalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL) - return -ENOMEM; - ret = intel_ring_begin(ring, 2); - if (ret) { - kfree(request); + if (ret) return ret; - } intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); intel_ring_emit(ring, MI_NOOP); intel_ring_advance(ring); - ret = intel_overlay_do_wait_request(overlay, request, + ret = intel_overlay_do_wait_request(overlay, intel_overlay_release_old_vid_tail); if (ret) return ret; -- cgit v1.2.3-55-g7522 From 1cf8378906b2d5a6449147914fe04c56d6f4fd87 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 10 Oct 2012 12:11:52 +0100 Subject: drm/i915: fixup i915_gem_object_get_page inline helper Note that just because we have n == MAX elements left, does not imply that there are only MAX elements left in the scatterlist and so we may not be on the last chain, and the nth element may in fact be a chain ptr. This is exercised by the improved hangman tests and the gem_exec_big test in i-g-t. This regression has been introduced in commit 9da3da660d8c19a54f6e93361d147509be3fff84 Author: Chris Wilson Date: Fri Jun 1 15:20:22 2012 +0100 drm/i915: Replace the array of pages with a scatterlist v2: KISS, replace the direct lookup with a for_each_sg() [danvet] v3: Try to be clever again. Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d5138c3a156b..b84f7861e438 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1341,9 +1341,14 @@ int __must_check i915_gem_object_get_pages(struct drm_i915_gem_object *obj); static inline struct page *i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n) { struct scatterlist *sg = obj->pages->sgl; - while (n >= SG_MAX_SINGLE_ALLOC) { + int nents = obj->pages->nents; + while (nents > SG_MAX_SINGLE_ALLOC) { + if (n < SG_MAX_SINGLE_ALLOC - 1) + break; + sg = sg_chain_ptr(sg + SG_MAX_SINGLE_ALLOC - 1); n -= SG_MAX_SINGLE_ALLOC - 1; + nents -= SG_MAX_SINGLE_ALLOC - 1; } return sg_page(sg+n); } -- cgit v1.2.3-55-g7522 From 9169d3a88072b20f42e68a946e916bd7dfbc7f2c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 10 Oct 2012 23:14:01 +0200 Subject: drm/i915: disable wc gtt pte mappings on gen2 It doesn't work since the gtt pte range sits in the middle of the mmio bar. We didn't notice that since both my and Chris' gen2 machines don't support PAT and hence all wc io mapping request will automatically be demoted to uc. This regression has been introduce in commit edef7e685da05c13cce50c0126189c80fe2c8f71 Author: Chris Wilson Date: Fri Sep 14 11:57:47 2012 +0100 agp/intel: Use a write-combining map for updating PTEs Reported-by: Egbert Eich Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=55834 Acked-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/char/agp/intel-gtt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index e01f5eaaec82..38390f7c6ab6 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -667,7 +667,7 @@ static int intel_gtt_init(void) gtt_map_size = intel_private.base.gtt_total_entries * 4; intel_private.gtt = NULL; - if (INTEL_GTT_GEN < 6) + if (INTEL_GTT_GEN < 6 && INTEL_GTT_GEN > 2) intel_private.gtt = ioremap_wc(intel_private.gtt_bus_addr, gtt_map_size); if (intel_private.gtt == NULL) -- cgit v1.2.3-55-g7522 From ccd0d36e2a8ab8b4d314ff87779366ada33ffe00 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 10 Oct 2012 23:13:59 +0200 Subject: drm/i915: rip out the pipe A quirk for i855gm This seems to be the root-cause that breaks resume on my i855gm when I apply the "drm/i915: fixup the plane->pipe fixup code" patch. And that code doesn't even run on my machine, so it's pure timing changes causing the regression. Furthermore resume has been constantly switching between working and broken on this machine ever since kms support has been merged, seemingly with no related change as a root cause. And always with the same symptoms of the backlight lighting up, but the lvds panel only displaying black. Also, of both i855gm variants only one is in the table. And in the past we've only ever removed entries from this quirk table because it breaks things. So let's just remove it - in case there's indeed a bios out there relying on a running pipe A, we can add back in a more precise quirk entry, like all the others (save for i830/i845). Tested-by: Chris Wilson #855gm Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9cecfd73b0b1..f3b2d18482d8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7902,8 +7902,7 @@ static struct intel_quirk intel_quirks[] = { /* ThinkPad T60 needs pipe A force quirk (bug #16494) */ { 0x2782, 0x17aa, 0x201a, quirk_pipea_force }, - /* 855 & before need to leave pipe A & dpll A up */ - { 0x3582, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, + /* 830/845 need to leave pipe A & dpll A up */ { 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, { 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, -- cgit v1.2.3-55-g7522 From fa55583797d12b10928a1813f3dcf066637caf5e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 10 Oct 2012 23:14:00 +0200 Subject: drm/i915: fixup the plane->pipe fixup code We need to check whether the _other plane is on our pipe, not whether our plane is on the other pipe. Otherwise if not both pipes/planes are active, we won't properly clean up the mess and set up our desired plane->pipe mapping. v2: Fixup the logic, I've totally fumbled it. Noticed by Chris Wilson. v3: I've checked Bspec, and the flexible plane->pipe mapping is a gen2/3 feature, so test for that instead of PCH_SPLIT v4: Check whether we indeed have 2 pipes before checking the other pipe, to avoid upsetting i845g/i865g. Noticed by Chris Wilson. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=51265 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=49838 Tested-by: Dave Airlie Tested-by: Chris Wilson #855gm Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f3b2d18482d8..3511effa01ec 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8058,29 +8058,42 @@ static void intel_enable_pipe_a(struct drm_device *dev) } +static bool +intel_check_plane_mapping(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + u32 reg, val; + + if (dev_priv->num_pipe == 1) + return true; + + reg = DSPCNTR(!crtc->plane); + val = I915_READ(reg); + + if ((val & DISPLAY_PLANE_ENABLE) && + (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe)) + return false; + + return true; +} + static void intel_sanitize_crtc(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - u32 reg, val; + u32 reg; /* Clear any frame start delays used for debugging left by the BIOS */ reg = PIPECONF(crtc->pipe); I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK); /* We need to sanitize the plane -> pipe mapping first because this will - * disable the crtc (and hence change the state) if it is wrong. */ - if (!HAS_PCH_SPLIT(dev)) { + * disable the crtc (and hence change the state) if it is wrong. Note + * that gen4+ has a fixed plane -> pipe mapping. */ + if (INTEL_INFO(dev)->gen < 4 && !intel_check_plane_mapping(crtc)) { struct intel_connector *connector; bool plane; - reg = DSPCNTR(crtc->plane); - val = I915_READ(reg); - - if ((val & DISPLAY_PLANE_ENABLE) == 0 && - (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe)) - goto ok; - DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n", crtc->base.base.id); @@ -8104,7 +8117,6 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) WARN_ON(crtc->active); crtc->base.enabled = false; } -ok: if (dev_priv->quirks & QUIRK_PIPEA_FORCE && crtc->pipe == PIPE_A && !crtc->active) { -- cgit v1.2.3-55-g7522 From 4afa0ace429624fde392b29d05a803672a41192e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 11 Oct 2012 18:43:52 +0200 Subject: drm/i915/dvo-ch7xxx: fix get_hw_state The boot-up state seems to be all-zeros, so it's safer to check for the bits that need to be set when the dvo encoder is in the dpms on state, than checking the bits we set when it's in the off state. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=55047 Tested-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/dvo_ch7xxx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c index 38f3a6cb8c7d..3edd981e0770 100644 --- a/drivers/gpu/drm/i915/dvo_ch7xxx.c +++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c @@ -303,10 +303,10 @@ static bool ch7xxx_get_hw_state(struct intel_dvo_device *dvo) ch7xxx_readb(dvo, CH7xxx_PM, &val); - if (val & CH7xxx_PM_FPD) - return false; - else + if (val & (CH7xxx_PM_DVIL | CH7xxx_PM_DVIP)) return true; + else + return false; } static void ch7xxx_dump_regs(struct intel_dvo_device *dvo) -- cgit v1.2.3-55-g7522 From eda2d7f582d51a4b5e01d48845ea28321357b136 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 10 Oct 2012 18:35:28 -0300 Subject: drm/i915: HSW CRW stability magic This magic brings stability to HSW CRW machines. Signed-off-by: Rodrigo Vivi Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 04b0c070cdf8..bb941f8cd556 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3961,6 +3961,9 @@ i915_gem_init_hw(struct drm_device *dev) if (!intel_enable_gtt()) return -EIO; + if (IS_HASWELL(dev) && (I915_READ(0x120010) == 1)) + I915_WRITE(0x9008, I915_READ(0x9008) | 0xf0000); + i915_gem_l3_remap(dev); i915_gem_init_swizzling(dev); -- cgit v1.2.3-55-g7522 From be3cd5e37716bcf1579f63bdd919345a1f9692b9 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 12 Oct 2012 10:33:05 +0300 Subject: drm/i915: fix non-DP-D eDP backlight cleanup and module reload Backlight is initialized for eDP, but cleaned up only for eDP on DP-D port. This leaves behind a dangling backlight interface on module unload on machines that have eDP connected to something other than DP-D, and breaks the backlight interface for subsequent module reloads. Fix the cleanup, and thus module reload on affected machines. Reported-by: Imre Deak Signed-off-by: Jani Nikula Reviewed-by: Mika Kuoppala Tested-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c14d407d41e8..bd2c34a0aa9a 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2370,8 +2370,9 @@ static void intel_dp_destroy(struct drm_connector *connector) { struct drm_device *dev = connector->dev; + struct intel_dp *intel_dp = intel_attached_dp(connector); - if (intel_dpd_is_edp(dev)) + if (is_edp(intel_dp)) intel_panel_destroy_backlight(dev); drm_sysfs_connector_remove(connector); -- cgit v1.2.3-55-g7522 From fdc858a466b738d35d3492bc7cf77b1dac98bf7c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 30 Apr 2012 13:50:56 +0000 Subject: pcmcia: sharpsl: don't discard sharpsl_pcmcia_ops The sharpsl_pcmcia_ops structure gets passed into sa11xx_drv_pcmcia_probe, where it gets accessed at run-time, unlike all other pcmcia drivers that pass their structures into platform_device_add_data, which makes a copy. This means the gcc warning is valid and the structure must not be marked as __initdata. Without this patch, building collie_defconfig results in: drivers/pcmcia/pxa2xx_sharpsl.c:22:31: fatal error: mach-pxa/hardware.h: No such file or directory compilation terminated. make[3]: *** [drivers/pcmcia/pxa2xx_sharpsl.o] Error 1 make[2]: *** [drivers/pcmcia] Error 2 make[1]: *** [drivers] Error 2 make: *** [sub-make] Error 2 Signed-off-by: Arnd Bergmann Cc: Dominik Brodowski Cc: Russell King Cc: Pavel Machek Cc: linux-pcmcia@lists.infradead.org Cc: Jochen Friedrich Cc: stable@vger.kernel.org --- drivers/pcmcia/pxa2xx_sharpsl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c index b066273b6b4f..7dd879ce514d 100644 --- a/drivers/pcmcia/pxa2xx_sharpsl.c +++ b/drivers/pcmcia/pxa2xx_sharpsl.c @@ -194,7 +194,7 @@ static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) sharpsl_pcmcia_init_reset(skt); } -static struct pcmcia_low_level sharpsl_pcmcia_ops __initdata = { +static struct pcmcia_low_level sharpsl_pcmcia_ops = { .owner = THIS_MODULE, .hw_init = sharpsl_pcmcia_hw_init, .socket_state = sharpsl_pcmcia_socket_state, -- cgit v1.2.3-55-g7522 From f2bab3eb4198ad49895e4cde0216beb3a1a88e31 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 2 Oct 2012 11:17:06 -0700 Subject: hwmon: (pmbus) remove CONFIG_EXPERIMENTAL This config item has not carried much meaning for a while now and is almost always enabled by default. As agreed during the Linux kernel summit, remove it. CC: Guenter Roeck CC: Jean Delvare Signed-off-by: Kees Cook Signed-off-by: Guenter Roeck --- drivers/hwmon/pmbus/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig index 2ca6a5a4f5a7..60745a535821 100644 --- a/drivers/hwmon/pmbus/Kconfig +++ b/drivers/hwmon/pmbus/Kconfig @@ -4,7 +4,7 @@ menuconfig PMBUS tristate "PMBus support" - depends on I2C && EXPERIMENTAL + depends on I2C default n help Say yes here if you want to enable PMBus support. -- cgit v1.2.3-55-g7522 From 1102dcab849313bd5a340b299b5cf61b518fbc0f Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 9 Oct 2012 13:23:57 -0700 Subject: hwmon: (coretemp) Add support for Atom CE4110/4150/4170 TjMax for the CE4100 series of Atom CPUs was previously reported to be 110 degrees C. cpuinfo logs on the web show existing CPU types CE4110, CE4150, and CE4170, reported as "model name : Intel(R) Atom(TM) CPU CE41{1|5|7}0 @ 1.{2|6}0GHz" with model 28 (0x1c) and stepping 10 (0x0a). Add the three known variants to the tjmax table. Signed-off-by: Guenter Roeck cc: stable@vger.kernel.org Acked-by: Jean Delvare --- Documentation/hwmon/coretemp | 1 + drivers/hwmon/coretemp.c | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/hwmon/coretemp b/Documentation/hwmon/coretemp index c86b50c03ea8..f17256f069ba 100644 --- a/Documentation/hwmon/coretemp +++ b/Documentation/hwmon/coretemp @@ -105,6 +105,7 @@ Process Processor TjMax(C) 330/230 125 E680/660/640/620 90 E680T/660T/640T/620T 110 + CE4170/4150/4110 110 45nm Core2 Processors Solo ULV SU3500/3300 100 diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 984a3f13923b..47b8d84b489d 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -205,8 +205,11 @@ static const struct tjmax __cpuinitconst tjmax_table[] = { { "CPU N455", 100000 }, { "CPU N470", 100000 }, { "CPU N475", 100000 }, - { "CPU 230", 100000 }, - { "CPU 330", 125000 }, + { "CPU 230", 100000 }, /* Model 0x1c, stepping 2 */ + { "CPU 330", 125000 }, /* Model 0x1c, stepping 2 */ + { "CPU CE4110", 110000 }, /* Model 0x1c, stepping 10 */ + { "CPU CE4150", 110000 }, /* Model 0x1c, stepping 10 */ + { "CPU CE4170", 110000 }, /* Model 0x1c, stepping 10 */ }; static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, -- cgit v1.2.3-55-g7522 From 0dd4d5cbe4c38165dc9b3ad329ebb23f24d74fdb Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 15 Oct 2012 14:08:48 +0900 Subject: sh: Fix up more fallout from pointless ARM __iomem churn. It was already pointed out how to fix these cases before the offending patches were merged, but unsurprisingly, that didn't happen. As this change is entirely superfluous to begin with, simply shut things up by casting everything away. Signed-off-by: Paul Mundt --- drivers/sh/intc/access.c | 45 +++++++++++++++++++++++++++------------------ drivers/sh/intc/chip.c | 4 ++-- drivers/tty/serial/sh-sci.c | 3 ++- 3 files changed, 31 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/sh/intc/access.c b/drivers/sh/intc/access.c index f892ae1d212a..114390f967d2 100644 --- a/drivers/sh/intc/access.c +++ b/drivers/sh/intc/access.c @@ -75,54 +75,61 @@ unsigned long intc_get_field_from_handle(unsigned int value, unsigned int handle static unsigned long test_8(unsigned long addr, unsigned long h, unsigned long ignore) { - return intc_get_field_from_handle(__raw_readb(addr), h); + void __iomem *ptr = (void __iomem *)addr; + return intc_get_field_from_handle(__raw_readb(ptr), h); } static unsigned long test_16(unsigned long addr, unsigned long h, unsigned long ignore) { - return intc_get_field_from_handle(__raw_readw(addr), h); + void __iomem *ptr = (void __iomem *)addr; + return intc_get_field_from_handle(__raw_readw(ptr), h); } static unsigned long test_32(unsigned long addr, unsigned long h, unsigned long ignore) { - return intc_get_field_from_handle(__raw_readl(addr), h); + void __iomem *ptr = (void __iomem *)addr; + return intc_get_field_from_handle(__raw_readl(ptr), h); } static unsigned long write_8(unsigned long addr, unsigned long h, unsigned long data) { - __raw_writeb(intc_set_field_from_handle(0, data, h), addr); - (void)__raw_readb(addr); /* Defeat write posting */ + void __iomem *ptr = (void __iomem *)addr; + __raw_writeb(intc_set_field_from_handle(0, data, h), ptr); + (void)__raw_readb(ptr); /* Defeat write posting */ return 0; } static unsigned long write_16(unsigned long addr, unsigned long h, unsigned long data) { - __raw_writew(intc_set_field_from_handle(0, data, h), addr); - (void)__raw_readw(addr); /* Defeat write posting */ + void __iomem *ptr = (void __iomem *)addr; + __raw_writew(intc_set_field_from_handle(0, data, h), ptr); + (void)__raw_readw(ptr); /* Defeat write posting */ return 0; } static unsigned long write_32(unsigned long addr, unsigned long h, unsigned long data) { - __raw_writel(intc_set_field_from_handle(0, data, h), addr); - (void)__raw_readl(addr); /* Defeat write posting */ + void __iomem *ptr = (void __iomem *)addr; + __raw_writel(intc_set_field_from_handle(0, data, h), ptr); + (void)__raw_readl(ptr); /* Defeat write posting */ return 0; } static unsigned long modify_8(unsigned long addr, unsigned long h, unsigned long data) { + void __iomem *ptr = (void __iomem *)addr; unsigned long flags; unsigned int value; local_irq_save(flags); - value = intc_set_field_from_handle(__raw_readb(addr), data, h); - __raw_writeb(value, addr); - (void)__raw_readb(addr); /* Defeat write posting */ + value = intc_set_field_from_handle(__raw_readb(ptr), data, h); + __raw_writeb(value, ptr); + (void)__raw_readb(ptr); /* Defeat write posting */ local_irq_restore(flags); return 0; } @@ -130,12 +137,13 @@ static unsigned long modify_8(unsigned long addr, unsigned long h, static unsigned long modify_16(unsigned long addr, unsigned long h, unsigned long data) { + void __iomem *ptr = (void __iomem *)addr; unsigned long flags; unsigned int value; local_irq_save(flags); - value = intc_set_field_from_handle(__raw_readw(addr), data, h); - __raw_writew(value, addr); - (void)__raw_readw(addr); /* Defeat write posting */ + value = intc_set_field_from_handle(__raw_readw(ptr), data, h); + __raw_writew(value, ptr); + (void)__raw_readw(ptr); /* Defeat write posting */ local_irq_restore(flags); return 0; } @@ -143,12 +151,13 @@ static unsigned long modify_16(unsigned long addr, unsigned long h, static unsigned long modify_32(unsigned long addr, unsigned long h, unsigned long data) { + void __iomem *ptr = (void __iomem *)addr; unsigned long flags; unsigned int value; local_irq_save(flags); - value = intc_set_field_from_handle(__raw_readl(addr), data, h); - __raw_writel(value, addr); - (void)__raw_readl(addr); /* Defeat write posting */ + value = intc_set_field_from_handle(__raw_readl(ptr), data, h); + __raw_writel(value, ptr); + (void)__raw_readl(ptr); /* Defeat write posting */ local_irq_restore(flags); return 0; } diff --git a/drivers/sh/intc/chip.c b/drivers/sh/intc/chip.c index 012df2676a26..46427b48e2f1 100644 --- a/drivers/sh/intc/chip.c +++ b/drivers/sh/intc/chip.c @@ -83,7 +83,7 @@ static void intc_mask_ack(struct irq_data *data) unsigned int irq = data->irq; struct intc_desc_int *d = get_intc_desc(irq); unsigned long handle = intc_get_ack_handle(irq); - unsigned long addr; + void __iomem *addr; intc_disable(data); @@ -91,7 +91,7 @@ static void intc_mask_ack(struct irq_data *data) if (handle) { unsigned int value; - addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); + addr = (void __iomem *)INTC_REG(d, _INTC_ADDR_D(handle), 0); value = intc_set_field_from_handle(0, 1, handle); switch (_INTC_FN(handle)) { diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 9be296cf7295..6ee59001d61d 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -530,7 +530,8 @@ static inline int sci_rxd_in(struct uart_port *port) if (s->cfg->port_reg <= 0) return 1; - return !!__raw_readb(s->cfg->port_reg); + /* Cast for ARM damage */ + return !!__raw_readb((void __iomem *)s->cfg->port_reg); } /* ********************************************************************** * -- cgit v1.2.3-55-g7522 From 47dbec59c37ab02946a6db7ac30c3bf6ca02630c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 28 Sep 2012 23:36:16 +0200 Subject: pinctrl: samsung: use __devinit section for init code The samsung pinctrl driver has a probe function that is __devinit and that calls a lot of other functions that are marked __init, which kbuild complains about. Marking everything __devinit means that the code does not discarded when CONFIG_HOTPLUG is set, which is a little more wasteful, but also more consistent Without this patch, building exynos_defconfig results in: WARNING: drivers/pinctrl/built-in.o(.devinit.text+0x124): Section mismatch in reference from the function samsung_pinctrl_probe() to the function .init.text:samsung_gpiolib_register() The function __devinit samsung_pinctrl_probe() references a function __init samsung_gpiolib_register(). If samsung_gpiolib_register is only used by samsung_pinctrl_probe then annotate samsung_gpiolib_register with a matching annotation. Signed-off-by: Arnd Bergmann Cc: Thomas Abraham Cc: Linus Walleij Cc: Stephen Warren Cc: Kukjin Kim Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-samsung.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index dd108a94acf9..861cd5f04d5e 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c @@ -513,7 +513,7 @@ static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset, * Parse the pin names listed in the 'samsung,pins' property and convert it * into a list of gpio numbers are create a pin group from it. */ -static int __init samsung_pinctrl_parse_dt_pins(struct platform_device *pdev, +static int __devinit samsung_pinctrl_parse_dt_pins(struct platform_device *pdev, struct device_node *cfg_np, struct pinctrl_desc *pctl, unsigned int **pin_list, unsigned int *npins) { @@ -560,7 +560,7 @@ static int __init samsung_pinctrl_parse_dt_pins(struct platform_device *pdev, * from device node of the pin-controller. A pin group is formed with all * the pins listed in the "samsung,pins" property. */ -static int __init samsung_pinctrl_parse_dt(struct platform_device *pdev, +static int __devinit samsung_pinctrl_parse_dt(struct platform_device *pdev, struct samsung_pinctrl_drv_data *drvdata) { struct device *dev = &pdev->dev; @@ -655,7 +655,7 @@ static int __init samsung_pinctrl_parse_dt(struct platform_device *pdev, } /* register the pinctrl interface with the pinctrl subsystem */ -static int __init samsung_pinctrl_register(struct platform_device *pdev, +static int __devinit samsung_pinctrl_register(struct platform_device *pdev, struct samsung_pinctrl_drv_data *drvdata) { struct pinctrl_desc *ctrldesc = &drvdata->pctl; @@ -729,7 +729,7 @@ static int __init samsung_pinctrl_register(struct platform_device *pdev, } /* register the gpiolib interface with the gpiolib subsystem */ -static int __init samsung_gpiolib_register(struct platform_device *pdev, +static int __devinit samsung_gpiolib_register(struct platform_device *pdev, struct samsung_pinctrl_drv_data *drvdata) { struct gpio_chip *gc; @@ -762,7 +762,7 @@ static int __init samsung_gpiolib_register(struct platform_device *pdev, } /* unregister the gpiolib interface with the gpiolib subsystem */ -static int __init samsung_gpiolib_unregister(struct platform_device *pdev, +static int __devinit samsung_gpiolib_unregister(struct platform_device *pdev, struct samsung_pinctrl_drv_data *drvdata) { int ret = gpiochip_remove(drvdata->gc); -- cgit v1.2.3-55-g7522 From 8c6871979d903b8b0e4cd78a59d84afc262611bf Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 8 Oct 2012 11:40:36 +0200 Subject: pinctrl: bcm2835: Use existing pointer to struct device The pointer to "pdev->dev" is already stored in "dev", so use it in devm_request_and_ioremap(). Signed-off-by: Tobias Klauser Acked-by: Stephen Warren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-bcm2835.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c index a4adee633fa9..3e0cc0ddb418 100644 --- a/drivers/pinctrl/pinctrl-bcm2835.c +++ b/drivers/pinctrl/pinctrl-bcm2835.c @@ -960,7 +960,7 @@ static int __devinit bcm2835_pinctrl_probe(struct platform_device *pdev) return err; } - pc->base = devm_request_and_ioremap(&pdev->dev, &iomem); + pc->base = devm_request_and_ioremap(dev, &iomem); if (!pc->base) return -EADDRNOTAVAIL; -- cgit v1.2.3-55-g7522 From 1cd6dc2e3c2dbececb60a3a5ca52af645d9be205 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 7 Oct 2012 21:28:20 +0800 Subject: pinctrl: remove duplicated include from pinctrl-bcm2835.c Remove duplicated include. dpatch engine is used to auto generate this patch. (https://github.com/weiyj/dpatch) Signed-off-by: Wei Yongjun Acked-by: Stephen Warren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-bcm2835.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c index 3e0cc0ddb418..956d585309b3 100644 --- a/drivers/pinctrl/pinctrl-bcm2835.c +++ b/drivers/pinctrl/pinctrl-bcm2835.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3-55-g7522 From 3ee73aa077d1468b293bb208814a8c240eefa9b7 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 7 Oct 2012 22:01:15 +0800 Subject: pinctrl: fix return value in bcm2835_pinctrl_probe() In case of error, the function pinctrl_register() returns NULL not ERR_PTR(). The PTR_ERR() in the return value should be replaced with error no. dpatch engine is used to auto generate this patch. (https://github.com/weiyj/dpatch) Signed-off-by: Wei Yongjun Acked-by: Stephen Warren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-bcm2835.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c index 956d585309b3..7e9be18ec2d2 100644 --- a/drivers/pinctrl/pinctrl-bcm2835.c +++ b/drivers/pinctrl/pinctrl-bcm2835.c @@ -1031,7 +1031,7 @@ static int __devinit bcm2835_pinctrl_probe(struct platform_device *pdev) pc->pctl_dev = pinctrl_register(&bcm2835_pinctrl_desc, dev, pc); if (!pc->pctl_dev) { gpiochip_remove(&pc->gpio_chip); - return PTR_ERR(pc->pctl_dev); + return -EINVAL; } pc->gpio_range = bcm2835_pinctrl_gpio_range; -- cgit v1.2.3-55-g7522 From 7bec207427c2efb79471a2e80906aabd132fd460 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 9 Oct 2012 15:35:56 +0000 Subject: pinctrl: sirf: remove sirfsoc_gpio_set_pull function The prima2 platform advertises needing no mach/gpio.h header file, but its pinctrl driver now has a sirfsoc_gpio_set_pull function that uses constants defined in arch/arm/mach-prima2/include/mach/gpio.h, which fails to build. Fortunately, the sirfsoc_gpio_set_pull is not used anywhere in the kernel, so we can safely remove it. Any out of tree drivers using it will have to be converted to use proper pinctrl functions to do the same. Without this patch, building prima2_defconfig results in: drivers/pinctrl/pinctrl-sirf.c: In function 'sirfsoc_gpio_set_pull': drivers/pinctrl/pinctrl-sirf.c:1331:7: error: 'SIRFSOC_GPIO_PULL_NONE' undeclared (first use in this function) drivers/pinctrl/pinctrl-sirf.c:1331:7: note: each undeclared identifier is reported only once for each function it appears in drivers/pinctrl/pinctrl-sirf.c:1334:7: error: 'SIRFSOC_GPIO_PULL_UP' undeclared (first use in this function) drivers/pinctrl/pinctrl-sirf.c:1338:7: error: 'SIRFSOC_GPIO_PULL_DOWN' undeclared (first use in this function) Signed-off-by: Arnd Bergmann Acked-by: Barry Song Signed-off-by: Linus Walleij --- arch/arm/mach-prima2/include/mach/gpio.h | 13 ------------ drivers/pinctrl/pinctrl-sirf.c | 35 -------------------------------- 2 files changed, 48 deletions(-) delete mode 100644 arch/arm/mach-prima2/include/mach/gpio.h (limited to 'drivers') diff --git a/arch/arm/mach-prima2/include/mach/gpio.h b/arch/arm/mach-prima2/include/mach/gpio.h deleted file mode 100644 index 1904bb03876e..000000000000 --- a/arch/arm/mach-prima2/include/mach/gpio.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __MACH_GPIO_H -#define __MACH_GPIO_H - -/* Pull up/down values */ -enum sirfsoc_gpio_pull { - SIRFSOC_GPIO_PULL_NONE, - SIRFSOC_GPIO_PULL_UP, - SIRFSOC_GPIO_PULL_DOWN, -}; - -void sirfsoc_gpio_set_pull(unsigned gpio, unsigned mode); - -#endif diff --git a/drivers/pinctrl/pinctrl-sirf.c b/drivers/pinctrl/pinctrl-sirf.c index 675497c15149..9ecacf3d0a75 100644 --- a/drivers/pinctrl/pinctrl-sirf.c +++ b/drivers/pinctrl/pinctrl-sirf.c @@ -1323,41 +1323,6 @@ static inline struct sirfsoc_gpio_bank *sirfsoc_gpio_to_bank(unsigned int gpio) return &sgpio_bank[gpio / SIRFSOC_GPIO_BANK_SIZE]; } -void sirfsoc_gpio_set_pull(unsigned gpio, unsigned mode) -{ - struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(gpio); - int idx = sirfsoc_gpio_to_offset(gpio); - u32 val, offset; - unsigned long flags; - - offset = SIRFSOC_GPIO_CTRL(bank->id, idx); - - spin_lock_irqsave(&sgpio_lock, flags); - - val = readl(bank->chip.regs + offset); - - switch (mode) { - case SIRFSOC_GPIO_PULL_NONE: - val &= ~SIRFSOC_GPIO_CTL_PULL_MASK; - break; - case SIRFSOC_GPIO_PULL_UP: - val |= SIRFSOC_GPIO_CTL_PULL_MASK; - val |= SIRFSOC_GPIO_CTL_PULL_HIGH; - break; - case SIRFSOC_GPIO_PULL_DOWN: - val |= SIRFSOC_GPIO_CTL_PULL_MASK; - val &= ~SIRFSOC_GPIO_CTL_PULL_HIGH; - break; - default: - break; - } - - writel(val, bank->chip.regs + offset); - - spin_unlock_irqrestore(&sgpio_lock, flags); -} -EXPORT_SYMBOL(sirfsoc_gpio_set_pull); - static inline struct sirfsoc_gpio_bank *sirfsoc_irqchip_to_bank(struct gpio_chip *chip) { return container_of(to_of_mm_gpio_chip(chip), struct sirfsoc_gpio_bank, chip); -- cgit v1.2.3-55-g7522 From b51b16a36fd8fd27b2e392a86f2637deaaf4267f Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 10 Oct 2012 20:59:32 +0800 Subject: pinctrl: remove duplicated include from pinctrl-xway.c Remove duplicated include. dpatch engine is used to auto generate this patch. (https://github.com/weiyj/dpatch) Signed-off-by: Wei Yongjun Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-xway.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c index f8d917d40c92..b9bcaec66223 100644 --- a/drivers/pinctrl/pinctrl-xway.c +++ b/drivers/pinctrl/pinctrl-xway.c @@ -17,8 +17,6 @@ #include #include #include -#include -#include #include #include "pinctrl-lantiq.h" -- cgit v1.2.3-55-g7522 From b7213702662e2139be92c4a3efe6682529f7a729 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 11 Oct 2012 14:33:42 +0200 Subject: pinctrl/nomadik: provide stubs for legacy Nomadik The compilation of the pinctrl driver failed on the legacy Nomadik NHK8815 platform because it was not providing the PRCMU interfaces needed to support the extended alternate functions used by the ux500 series. Solve this by providing some stubs for the legacy platform, to avoid too much #ifdefs in the code per se. Theoretically this actually allows the Nomadik and Ux500 to have a single kernel image with support for the PRCM registers on the Ux500 (though they have incompatible archs, but the spirit is there). Reported-by: Arnd Bergmann Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-nomadik.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index fec9c30133d4..f640f13f73ca 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -30,7 +30,20 @@ #include /* Since we request GPIOs from ourself */ #include +/* + * For the U8500 archs, use the PRCMU register interface, for the older + * Nomadik, provide some stubs. The functions using these will only be + * called on the U8500 series. + */ +#ifdef CONFIG_ARCH_U8500 #include +#else +static inline u32 prcmu_read(unsigned int reg) { + return 0; +} +static inline void prcmu_write(unsigned int reg, u32 value) {} +static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {} +#endif #include -- cgit v1.2.3-55-g7522 From 51f58c68a364363b29c07668c90af19c9b8a8c85 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 11 Oct 2012 16:33:44 +0200 Subject: pinctrl/nomadik: always use the simple irqdomain Since the simple irqdomain will fall back to a linear domain if the first_irq provided is <= 0, just use this, just make sure the first_irq is negative in the device tree case. Cc: Rob Herring Acked-by: Lee Jones Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-nomadik.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index f640f13f73ca..01aea1c3b5fa 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -1281,6 +1281,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) struct clk *clk; int secondary_irq; void __iomem *base; + int irq_start = -1; int irq; int ret; @@ -1384,19 +1385,11 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) platform_set_drvdata(dev, nmk_chip); - if (np) { - /* The DT case will just grab a set of IRQ numbers */ - nmk_chip->domain = irq_domain_add_linear(np, NMK_GPIO_PER_CHIP, - &nmk_gpio_irq_simple_ops, nmk_chip); - } else { - /* Non-DT legacy mode, use hardwired IRQ numbers */ - int irq_start; - + if (!np) irq_start = NOMADIK_GPIO_TO_IRQ(pdata->first_gpio); - nmk_chip->domain = irq_domain_add_simple(NULL, + nmk_chip->domain = irq_domain_add_simple(NULL, NMK_GPIO_PER_CHIP, irq_start, &nmk_gpio_irq_simple_ops, nmk_chip); - } if (!nmk_chip->domain) { dev_err(&dev->dev, "failed to create irqdomain\n"); ret = -ENOSYS; -- cgit v1.2.3-55-g7522 From 041d81f493d90c940ec41f0ec98bc7c4f2fba431 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 4 Oct 2012 11:58:00 +0300 Subject: usb: dwc3: gadget: fix 'endpoint always busy' bug If a USB transfer has already been started, meaning we have already issued StartTransfer command to that particular endpoint, DWC3_EP_BUSY flag has also already been set. When we try to cancel this transfer which is already in controller's cache, we will not receive XferComplete event and we must clear DWC3_EP_BUSY in order to allow subsequent requests to be properly started. The best place to clear that flag is right after issuing DWC3_DEPCMD_ENDTRANSFER. Cc: stable@vger.kernel.org # v3.4 v3.5 v3.6 Reported-by: Moiz Sonasath Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c9e729a4bf65..7b7deddf6a52 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1904,7 +1904,7 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum) ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms); WARN_ON_ONCE(ret); dep->resource_index = 0; - + dep->flags &= ~DWC3_EP_BUSY; udelay(100); } -- cgit v1.2.3-55-g7522 From 6ff1f3d3bd7c69c62ca5773b1b684bce42eff06a Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Mon, 15 Oct 2012 11:20:22 +0200 Subject: usb: musb: am35xx: drop spurious unplugging a device On AM3517, tx and rx interrupt are detected together with the disconnect event. This generates a kernel panic in musb_interrupt, because rx / tx are handled after disconnect. This issue was seen on a Technexion's TAM3517 SOM. Unplugging a device, tx / rx interrupts together with disconnect are detected. This brings to kernel panic like this: [ 68.526153] Unable to handle kernel NULL pointer dereference at virtual address 00000011 [ 68.534698] pgd = c0004000 [ 68.537536] [00000011] *pgd=00000000 [ 68.541351] Internal error: Oops: 17 [#1] ARM [ 68.545928] Modules linked in: [ 68.549163] CPU: 0 Not tainted (3.6.0-rc5-00020-g9e05905 #178) [ 68.555694] PC is at rxstate+0x8/0xdc [ 68.559539] LR is at musb_interrupt+0x98/0x858 [ 68.564239] pc : [] lr : [] psr: 40000193 [ 68.564239] sp : ce83fb40 ip : d0906410 fp : 00000000 [ 68.576293] r10: 00000000 r9 : cf3b0e40 r8 : 00000002 [ 68.581817] r7 : 00000019 r6 : 00000001 r5 : 00000001 r4 : 000000d4 [ 68.588684] r3 : 00000000 r2 : 00000000 r1 : ffffffcc r0 : cf23c108 [ 68.595550] Flags: nZcv IRQs off FIQs on Mode SVC_32 ISA ARM Segment ke Note: this behavior is not seen with a USB hub, while it is easy to reproduce connecting a USB-pen directly to the USB-A of the board. Drop tx / rx interrupts if disconnect is detected. Signed-off-by: Stefano Babic CC: Felipe Balbi Cc: stable@vger.kernel.org # 3.5 3.6 Tested-by: Dmitry Lifshitz Tested-by: Igor Grinberg Signed-off-by: Felipe Balbi --- drivers/usb/musb/am35x.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index 457f25e62c51..c964d6af178b 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c @@ -305,6 +305,12 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) ret = IRQ_HANDLED; } + /* Drop spurious RX and TX if device is disconnected */ + if (musb->int_usb & MUSB_INTR_DISCONNECT) { + musb->int_tx = 0; + musb->int_rx = 0; + } + if (musb->int_tx || musb->int_rx || musb->int_usb) ret |= musb_interrupt(musb); -- cgit v1.2.3-55-g7522 From 01b8daf71b2fd2f6ece5f063a089abf4b13f1d6e Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Sat, 13 Oct 2012 19:20:18 +0530 Subject: usb: dwc3: shutdown usb_phy when removing the device We call usb_phy_init() from dwc3_core_init() during probe, so adding usb_phy_shutdown() to dwc3_core_exit() while removing the device so we don't keep PHYs turned on, consuming power, unnecessarily. Signed-off-by: Vivek Gautam Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index b415c0c859d3..c14ebc975ba4 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -409,6 +409,10 @@ static void dwc3_core_exit(struct dwc3 *dwc) { dwc3_event_buffers_cleanup(dwc); dwc3_free_event_buffers(dwc); + + usb_phy_shutdown(dwc->usb2_phy); + usb_phy_shutdown(dwc->usb3_phy); + } #define DWC3_ALIGN_MASK (16 - 1) -- cgit v1.2.3-55-g7522 From 0b2ffb78c0ef83bb03f594fec2adc13ac6ac427b Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 4 Oct 2012 02:32:41 +0200 Subject: usb: gadget: Make webcam gadget select USB_LIBCOMPOSITE Composite gadget support is now available as a library instead of being built with each gadget. Composite drivers need to select USB_LIBCOMPOSITE. Signed-off-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index dfb51a45496c..e0ff51b89529 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -952,6 +952,7 @@ endif config USB_G_WEBCAM tristate "USB Webcam Gadget" depends on VIDEO_DEV + select USB_LIBCOMPOSITE help The Webcam Gadget acts as a composite USB Audio and Video Class device. It provides a userspace API to process UVC control requests -- cgit v1.2.3-55-g7522 From a1871936c0f4f10850a5671c5deb1a92fcca1155 Mon Sep 17 00:00:00 2001 From: Luca Tettamanti Date: Wed, 3 Oct 2012 15:00:19 +0200 Subject: drm/radeon: use %zu for formatting size_t Fixes compiler warnings on 32bit. Signed-off-by: Luca Tettamanti Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_acpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_acpi.c b/drivers/gpu/drm/radeon/radeon_acpi.c index b0a5688c67f8..ecb7e3374a56 100644 --- a/drivers/gpu/drm/radeon/radeon_acpi.c +++ b/drivers/gpu/drm/radeon/radeon_acpi.c @@ -201,7 +201,7 @@ static int radeon_atif_verify_interface(acpi_handle handle, size = *(u16 *) info->buffer.pointer; if (size < 12) { - DRM_INFO("ATIF buffer is too small: %lu\n", size); + DRM_INFO("ATIF buffer is too small: %zu\n", size); err = -EINVAL; goto out; } @@ -485,7 +485,7 @@ static int radeon_atcs_verify_interface(acpi_handle handle, size = *(u16 *) info->buffer.pointer; if (size < 8) { - DRM_INFO("ATCS buffer is too small: %lu\n", size); + DRM_INFO("ATCS buffer is too small: %zu\n", size); err = -EINVAL; goto out; } -- cgit v1.2.3-55-g7522 From cd23492af3d4401c02c48a4bebe5995c9498eac5 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 4 Oct 2012 09:10:10 -0400 Subject: drm/radeon: fix compilation with backlight disabled Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_acpi.c | 2 ++ drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 42 ++++++++++++------------- 2 files changed, 23 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_acpi.c b/drivers/gpu/drm/radeon/radeon_acpi.c index ecb7e3374a56..196d28d99570 100644 --- a/drivers/gpu/drm/radeon/radeon_acpi.c +++ b/drivers/gpu/drm/radeon/radeon_acpi.c @@ -370,6 +370,7 @@ int radeon_atif_handler(struct radeon_device *rdev, radeon_set_backlight_level(rdev, enc, req.backlight_level); +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) if (rdev->is_atom_bios) { struct radeon_encoder_atom_dig *dig = enc->enc_priv; backlight_force_update(dig->bl_dev, @@ -379,6 +380,7 @@ int radeon_atif_handler(struct radeon_device *rdev, backlight_force_update(dig->bl_dev, BACKLIGHT_UPDATE_HOTKEY); } +#endif } } /* TODO: check other events */ diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 92487e614778..fb15b62ff984 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -269,27 +269,6 @@ static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = { .disable = radeon_legacy_encoder_disable, }; -#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) - -static uint8_t radeon_legacy_lvds_level(struct backlight_device *bd) -{ - struct radeon_backlight_privdata *pdata = bl_get_data(bd); - uint8_t level; - - /* Convert brightness to hardware level */ - if (bd->props.brightness < 0) - level = 0; - else if (bd->props.brightness > RADEON_MAX_BL_LEVEL) - level = RADEON_MAX_BL_LEVEL; - else - level = bd->props.brightness; - - if (pdata->negative) - level = RADEON_MAX_BL_LEVEL - level; - - return level; -} - u8 radeon_legacy_get_backlight_level(struct radeon_encoder *radeon_encoder) { @@ -331,6 +310,27 @@ radeon_legacy_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 leve radeon_legacy_lvds_update(&radeon_encoder->base, dpms_mode); } +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) + +static uint8_t radeon_legacy_lvds_level(struct backlight_device *bd) +{ + struct radeon_backlight_privdata *pdata = bl_get_data(bd); + uint8_t level; + + /* Convert brightness to hardware level */ + if (bd->props.brightness < 0) + level = 0; + else if (bd->props.brightness > RADEON_MAX_BL_LEVEL) + level = RADEON_MAX_BL_LEVEL; + else + level = bd->props.brightness; + + if (pdata->negative) + level = RADEON_MAX_BL_LEVEL - level; + + return level; +} + static int radeon_legacy_backlight_update_status(struct backlight_device *bd) { struct radeon_backlight_privdata *pdata = bl_get_data(bd); -- cgit v1.2.3-55-g7522 From 29dbe3bcd2e28e71823febdca989d63d5c27d152 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 5 Oct 2012 10:22:02 -0400 Subject: drm/radeon: allocate PPLLs from low to high The order shouldn't matter, but there have been problems reported on certain older asics. This behaves more like the original code before the PPLL allocation rework. Signed-off-by: Alex Deucher Cc: Markus Trippelsdorf --- drivers/gpu/drm/radeon/atombios_crtc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 96184d02c8d9..2e566e123e9e 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1690,10 +1690,10 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) } /* all other cases */ pll_in_use = radeon_get_pll_use_mask(crtc); - if (!(pll_in_use & (1 << ATOM_PPLL2))) - return ATOM_PPLL2; if (!(pll_in_use & (1 << ATOM_PPLL1))) return ATOM_PPLL1; + if (!(pll_in_use & (1 << ATOM_PPLL2))) + return ATOM_PPLL2; DRM_ERROR("unable to allocate a PPLL\n"); return ATOM_PPLL_INVALID; } else { @@ -1715,10 +1715,10 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) } /* all other cases */ pll_in_use = radeon_get_pll_use_mask(crtc); - if (!(pll_in_use & (1 << ATOM_PPLL2))) - return ATOM_PPLL2; if (!(pll_in_use & (1 << ATOM_PPLL1))) return ATOM_PPLL1; + if (!(pll_in_use & (1 << ATOM_PPLL2))) + return ATOM_PPLL2; DRM_ERROR("unable to allocate a PPLL\n"); return ATOM_PPLL_INVALID; } else { -- cgit v1.2.3-55-g7522 From 23d4f1f246a98dde1dc485e0be9a647126630347 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 8 Oct 2012 09:45:46 -0400 Subject: drm/radeon: update comments to clarify VM setup (v2) The actual set up and assignment of VM page tables is done on the fly in radeon_gart.c. v2: update vm size comments Signed-off-by: Alex Deucher Reviewed-by: Christian König --- drivers/gpu/drm/radeon/ni.c | 4 ++++ drivers/gpu/drm/radeon/radeon_device.c | 4 ++++ drivers/gpu/drm/radeon/si.c | 7 ++++--- 3 files changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 8bcb554ea0c5..83dc0852d5c9 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -770,6 +770,10 @@ static int cayman_pcie_gart_enable(struct radeon_device *rdev) WREG32(0x15DC, 0); /* empty context1-7 */ + /* Assign the pt base to something valid for now; the pts used for + * the VMs are determined by the application and setup and assigned + * on the fly in the vm part of radeon_gart.c + */ for (i = 1; i < 8; i++) { WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (i << 2), 0); WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), 0); diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 64a42647f08a..bd13ca09eb62 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1018,6 +1018,10 @@ int radeon_device_init(struct radeon_device *rdev, return r; /* initialize vm here */ mutex_init(&rdev->vm_manager.lock); + /* Adjust VM size here. + * Currently set to 4GB ((1 << 20) 4k pages). + * Max GPUVM size for cayman and SI is 40 bits. + */ rdev->vm_manager.max_pfn = 1 << 20; INIT_LIST_HEAD(&rdev->vm_manager.lru_vm); diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index f79633a036c3..df8dd7701643 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2407,12 +2407,13 @@ static int si_pcie_gart_enable(struct radeon_device *rdev) WREG32(0x15DC, 0); /* empty context1-15 */ - /* FIXME start with 4G, once using 2 level pt switch to full - * vm size space - */ /* set vm size, must be a multiple of 4 */ WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0); WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn); + /* Assign the pt base to something valid for now; the pts used for + * the VMs are determined by the application and setup and assigned + * on the fly in the vm part of radeon_gart.c + */ for (i = 1; i < 16; i++) { if (i < 8) WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), -- cgit v1.2.3-55-g7522 From 90a51a329258e3c868f6f4c1fb264ca01c590c57 Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 9 Oct 2012 13:31:17 +0200 Subject: drm/radeon: allocate page tables on demand v4 Based on Dmitries work, but splitting the code into page directory and page table handling makes it far more readable and (hopefully) more reliable. Allocations of page tables are made from the SA on demand, that should still work fine since all page tables are of the same size. Also using the fact that allocations from the SA are mostly continuously (except for end of buffer wraps and under very high memory pressure) to group updates send to the chipset specific code into larger chunks. v3: mostly a rewrite of Dmitries previous patch. v4: fix some typos and coding style Signed-off-by: Dmitry Cherkasov Signed-off-by: Christian König Tested-by: Michel Dänzer Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ni.c | 2 +- drivers/gpu/drm/radeon/radeon.h | 11 +- drivers/gpu/drm/radeon/radeon_gart.c | 322 +++++++++++++++++++++++++++-------- 3 files changed, 262 insertions(+), 73 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 83dc0852d5c9..ab8d1f5fe68a 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -1580,7 +1580,7 @@ void cayman_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) radeon_ring_write(ring, 0); radeon_ring_write(ring, PACKET0(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (vm->id << 2), 0)); - radeon_ring_write(ring, vm->last_pfn); + radeon_ring_write(ring, rdev->vm_manager.max_pfn); radeon_ring_write(ring, PACKET0(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2), 0)); radeon_ring_write(ring, vm->pd_gpu_addr >> 12); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index b04c06444d8b..bc6b56bf274a 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -663,9 +663,14 @@ struct radeon_vm { struct list_head list; struct list_head va; unsigned id; - unsigned last_pfn; - u64 pd_gpu_addr; - struct radeon_sa_bo *sa_bo; + + /* contains the page directory */ + struct radeon_sa_bo *page_directory; + uint64_t pd_gpu_addr; + + /* array of page tables, one for each page directory entry */ + struct radeon_sa_bo **page_tables; + struct mutex mutex; /* last fence for cs using this vm */ struct radeon_fence *fence; diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index f0c06d196b75..98b170a0df90 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -422,6 +422,18 @@ void radeon_gart_fini(struct radeon_device *rdev) * TODO bind a default page at vm initialization for default address */ +/** + * radeon_vm_num_pde - return the number of page directory entries + * + * @rdev: radeon_device pointer + * + * Calculate the number of page directory entries (cayman+). + */ +static unsigned radeon_vm_num_pdes(struct radeon_device *rdev) +{ + return rdev->vm_manager.max_pfn >> RADEON_VM_BLOCK_SIZE; +} + /** * radeon_vm_directory_size - returns the size of the page directory in bytes * @@ -431,7 +443,7 @@ void radeon_gart_fini(struct radeon_device *rdev) */ static unsigned radeon_vm_directory_size(struct radeon_device *rdev) { - return (rdev->vm_manager.max_pfn >> RADEON_VM_BLOCK_SIZE) * 8; + return RADEON_GPU_PAGE_ALIGN(radeon_vm_num_pdes(rdev) * 8); } /** @@ -451,11 +463,11 @@ int radeon_vm_manager_init(struct radeon_device *rdev) if (!rdev->vm_manager.enabled) { /* allocate enough for 2 full VM pts */ - size = RADEON_GPU_PAGE_ALIGN(radeon_vm_directory_size(rdev)); - size += RADEON_GPU_PAGE_ALIGN(rdev->vm_manager.max_pfn * 8); + size = radeon_vm_directory_size(rdev); + size += rdev->vm_manager.max_pfn * 8; size *= 2; r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager, - size, + RADEON_GPU_PAGE_ALIGN(size), RADEON_GEM_DOMAIN_VRAM); if (r) { dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n", @@ -476,7 +488,7 @@ int radeon_vm_manager_init(struct radeon_device *rdev) /* restore page table */ list_for_each_entry(vm, &rdev->vm_manager.lru_vm, list) { - if (vm->sa_bo == NULL) + if (vm->page_directory == NULL) continue; list_for_each_entry(bo_va, &vm->va, vm_list) { @@ -500,16 +512,25 @@ static void radeon_vm_free_pt(struct radeon_device *rdev, struct radeon_vm *vm) { struct radeon_bo_va *bo_va; + int i; - if (!vm->sa_bo) + if (!vm->page_directory) return; list_del_init(&vm->list); - radeon_sa_bo_free(rdev, &vm->sa_bo, vm->fence); + radeon_sa_bo_free(rdev, &vm->page_directory, vm->fence); list_for_each_entry(bo_va, &vm->va, vm_list) { bo_va->valid = false; } + + if (vm->page_tables == NULL) + return; + + for (i = 0; i < radeon_vm_num_pdes(rdev); i++) + radeon_sa_bo_free(rdev, &vm->page_tables[i], vm->fence); + + kfree(vm->page_tables); } /** @@ -545,6 +566,35 @@ void radeon_vm_manager_fini(struct radeon_device *rdev) rdev->vm_manager.enabled = false; } +/** + * radeon_vm_evict - evict page table to make room for new one + * + * @rdev: radeon_device pointer + * @vm: VM we want to allocate something for + * + * Evict a VM from the lru, making sure that it isn't @vm. (cayman+). + * Returns 0 for success, -ENOMEM for failure. + * + * Global and local mutex must be locked! + */ +int radeon_vm_evict(struct radeon_device *rdev, struct radeon_vm *vm) +{ + struct radeon_vm *vm_evict; + + if (list_empty(&rdev->vm_manager.lru_vm)) + return -ENOMEM; + + vm_evict = list_first_entry(&rdev->vm_manager.lru_vm, + struct radeon_vm, list); + if (vm_evict == vm) + return -ENOMEM; + + mutex_lock(&vm_evict->mutex); + radeon_vm_free_pt(rdev, vm_evict); + mutex_unlock(&vm_evict->mutex); + return 0; +} + /** * radeon_vm_alloc_pt - allocates a page table for a VM * @@ -559,20 +609,15 @@ void radeon_vm_manager_fini(struct radeon_device *rdev) */ int radeon_vm_alloc_pt(struct radeon_device *rdev, struct radeon_vm *vm) { - struct radeon_vm *vm_evict; - int r; + unsigned pd_size, pts_size; u64 *pd_addr; - int tables_size; + int r; if (vm == NULL) { return -EINVAL; } - /* allocate enough to cover the current VM size */ - tables_size = RADEON_GPU_PAGE_ALIGN(radeon_vm_directory_size(rdev)); - tables_size += RADEON_GPU_PAGE_ALIGN(vm->last_pfn * 8); - - if (vm->sa_bo != NULL) { + if (vm->page_directory != NULL) { /* update lru */ list_del_init(&vm->list); list_add_tail(&vm->list, &rdev->vm_manager.lru_vm); @@ -580,25 +625,34 @@ int radeon_vm_alloc_pt(struct radeon_device *rdev, struct radeon_vm *vm) } retry: - r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager, &vm->sa_bo, - tables_size, RADEON_GPU_PAGE_SIZE, false); + pd_size = RADEON_GPU_PAGE_ALIGN(radeon_vm_directory_size(rdev)); + r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager, + &vm->page_directory, pd_size, + RADEON_GPU_PAGE_SIZE, false); if (r == -ENOMEM) { - if (list_empty(&rdev->vm_manager.lru_vm)) { + r = radeon_vm_evict(rdev, vm); + if (r) return r; - } - vm_evict = list_first_entry(&rdev->vm_manager.lru_vm, struct radeon_vm, list); - mutex_lock(&vm_evict->mutex); - radeon_vm_free_pt(rdev, vm_evict); - mutex_unlock(&vm_evict->mutex); goto retry; } else if (r) { return r; } - pd_addr = radeon_sa_bo_cpu_addr(vm->sa_bo); - vm->pd_gpu_addr = radeon_sa_bo_gpu_addr(vm->sa_bo); - memset(pd_addr, 0, tables_size); + vm->pd_gpu_addr = radeon_sa_bo_gpu_addr(vm->page_directory); + + /* Initially clear the page directory */ + pd_addr = radeon_sa_bo_cpu_addr(vm->page_directory); + memset(pd_addr, 0, pd_size); + + pts_size = radeon_vm_num_pdes(rdev) * sizeof(struct radeon_sa_bo *); + vm->page_tables = kzalloc(pts_size, GFP_KERNEL); + + if (vm->page_tables == NULL) { + DRM_ERROR("Cannot allocate memory for page table array\n"); + radeon_sa_bo_free(rdev, &vm->page_directory, vm->fence); + return -ENOMEM; + } list_add_tail(&vm->list, &rdev->vm_manager.lru_vm); return radeon_vm_bo_update_pte(rdev, vm, rdev->ring_tmp_bo.bo, @@ -793,20 +847,6 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev, } mutex_lock(&vm->mutex); - if (last_pfn > vm->last_pfn) { - /* release mutex and lock in right order */ - mutex_unlock(&vm->mutex); - mutex_lock(&rdev->vm_manager.lock); - mutex_lock(&vm->mutex); - /* and check again */ - if (last_pfn > vm->last_pfn) { - /* grow va space 32M by 32M */ - unsigned align = ((32 << 20) >> 12) - 1; - radeon_vm_free_pt(rdev, vm); - vm->last_pfn = (last_pfn + align) & ~align; - } - mutex_unlock(&rdev->vm_manager.lock); - } head = &vm->va; last_offset = 0; list_for_each_entry(tmp, &vm->va, vm_list) { @@ -864,6 +904,155 @@ uint64_t radeon_vm_map_gart(struct radeon_device *rdev, uint64_t addr) return result; } +/** + * radeon_vm_update_pdes - make sure that page directory is valid + * + * @rdev: radeon_device pointer + * @vm: requested vm + * @start: start of GPU address range + * @end: end of GPU address range + * + * Allocates new page tables if necessary + * and updates the page directory (cayman+). + * Returns 0 for success, error for failure. + * + * Global and local mutex must be locked! + */ +static int radeon_vm_update_pdes(struct radeon_device *rdev, + struct radeon_vm *vm, + uint64_t start, uint64_t end) +{ + static const uint32_t incr = RADEON_VM_PTE_COUNT * 8; + + uint64_t last_pde = ~0, last_pt = ~0; + unsigned count = 0; + uint64_t pt_idx; + int r; + + start = (start / RADEON_GPU_PAGE_SIZE) >> RADEON_VM_BLOCK_SIZE; + end = (end / RADEON_GPU_PAGE_SIZE) >> RADEON_VM_BLOCK_SIZE; + + /* walk over the address space and update the page directory */ + for (pt_idx = start; pt_idx <= end; ++pt_idx) { + uint64_t pde, pt; + + if (vm->page_tables[pt_idx]) + continue; + +retry: + r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager, + &vm->page_tables[pt_idx], + RADEON_VM_PTE_COUNT * 8, + RADEON_GPU_PAGE_SIZE, false); + + if (r == -ENOMEM) { + r = radeon_vm_evict(rdev, vm); + if (r) + return r; + goto retry; + } else if (r) { + return r; + } + + pde = vm->pd_gpu_addr + pt_idx * 8; + + pt = radeon_sa_bo_gpu_addr(vm->page_tables[pt_idx]); + + if (((last_pde + 8 * count) != pde) || + ((last_pt + incr * count) != pt)) { + + if (count) { + radeon_asic_vm_set_page(rdev, last_pde, + last_pt, count, incr, + RADEON_VM_PAGE_VALID); + } + + count = 1; + last_pde = pde; + last_pt = pt; + } else { + ++count; + } + } + + if (count) { + radeon_asic_vm_set_page(rdev, last_pde, last_pt, count, + incr, RADEON_VM_PAGE_VALID); + + } + + return 0; +} + +/** + * radeon_vm_update_ptes - make sure that page tables are valid + * + * @rdev: radeon_device pointer + * @vm: requested vm + * @start: start of GPU address range + * @end: end of GPU address range + * @dst: destination address to map to + * @flags: mapping flags + * + * Update the page tables in the range @start - @end (cayman+). + * + * Global and local mutex must be locked! + */ +static void radeon_vm_update_ptes(struct radeon_device *rdev, + struct radeon_vm *vm, + uint64_t start, uint64_t end, + uint64_t dst, uint32_t flags) +{ + static const uint64_t mask = RADEON_VM_PTE_COUNT - 1; + + uint64_t last_pte = ~0, last_dst = ~0; + unsigned count = 0; + uint64_t addr; + + start = start / RADEON_GPU_PAGE_SIZE; + end = end / RADEON_GPU_PAGE_SIZE; + + /* walk over the address space and update the page tables */ + for (addr = start; addr < end; ) { + uint64_t pt_idx = addr >> RADEON_VM_BLOCK_SIZE; + unsigned nptes; + uint64_t pte; + + if ((addr & ~mask) == (end & ~mask)) + nptes = end - addr; + else + nptes = RADEON_VM_PTE_COUNT - (addr & mask); + + pte = radeon_sa_bo_gpu_addr(vm->page_tables[pt_idx]); + pte += (addr & mask) * 8; + + if (((last_pte + 8 * count) != pte) || + ((count + nptes) > 1 << 11)) { + + if (count) { + radeon_asic_vm_set_page(rdev, last_pte, + last_dst, count, + RADEON_GPU_PAGE_SIZE, + flags); + } + + count = nptes; + last_pte = pte; + last_dst = dst; + } else { + count += nptes; + } + + addr += nptes; + dst += nptes * RADEON_GPU_PAGE_SIZE; + } + + if (count) { + radeon_asic_vm_set_page(rdev, last_pte, last_dst, count, + RADEON_GPU_PAGE_SIZE, flags); + } +} + /** * radeon_vm_bo_update_pte - map a bo into the vm page table * @@ -887,12 +1076,11 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev, struct radeon_semaphore *sem = NULL; struct radeon_bo_va *bo_va; unsigned nptes, npdes, ndw; - uint64_t pe, addr; - uint64_t pfn; + uint64_t addr; int r; /* nothing to do if vm isn't bound */ - if (vm->sa_bo == NULL) + if (vm->page_directory == NULL) return 0; bo_va = radeon_vm_bo_find(vm, bo); @@ -939,25 +1127,29 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev, } } - /* estimate number of dw needed */ - /* reserve space for 32-bit padding */ - ndw = 32; - nptes = radeon_bo_ngpu_pages(bo); - pfn = (bo_va->soffset / RADEON_GPU_PAGE_SIZE); + /* assume two extra pdes in case the mapping overlaps the borders */ + npdes = (nptes >> RADEON_VM_BLOCK_SIZE) + 2; + + /* estimate number of dw needed */ + /* semaphore, fence and padding */ + ndw = 32; - /* handle cases where a bo spans several pdes */ - npdes = (ALIGN(pfn + nptes, RADEON_VM_PTE_COUNT) - - (pfn & ~(RADEON_VM_PTE_COUNT - 1))) >> RADEON_VM_BLOCK_SIZE; + if (RADEON_VM_BLOCK_SIZE > 11) + /* reserve space for one header for every 2k dwords */ + ndw += (nptes >> 11) * 3; + else + /* reserve space for one header for + every (1 << BLOCK_SIZE) entries */ + ndw += (nptes >> RADEON_VM_BLOCK_SIZE) * 3; - /* reserve space for one header for every 2k dwords */ - ndw += (nptes >> 11) * 3; /* reserve space for pte addresses */ ndw += nptes * 2; /* reserve space for one header for every 2k dwords */ ndw += (npdes >> 11) * 3; + /* reserve space for pde addresses */ ndw += npdes * 2; @@ -971,22 +1163,14 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev, radeon_fence_note_sync(vm->fence, ridx); } - /* update page table entries */ - pe = vm->pd_gpu_addr; - pe += radeon_vm_directory_size(rdev); - pe += (bo_va->soffset / RADEON_GPU_PAGE_SIZE) * 8; - - radeon_asic_vm_set_page(rdev, pe, addr, nptes, - RADEON_GPU_PAGE_SIZE, bo_va->flags); - - /* update page directory entries */ - addr = pe; - - pe = vm->pd_gpu_addr; - pe += ((bo_va->soffset / RADEON_GPU_PAGE_SIZE) >> RADEON_VM_BLOCK_SIZE) * 8; + r = radeon_vm_update_pdes(rdev, vm, bo_va->soffset, bo_va->eoffset); + if (r) { + radeon_ring_unlock_undo(rdev, ring); + return r; + } - radeon_asic_vm_set_page(rdev, pe, addr, npdes, - RADEON_VM_PTE_COUNT * 8, RADEON_VM_PAGE_VALID); + radeon_vm_update_ptes(rdev, vm, bo_va->soffset, bo_va->eoffset, + addr, bo_va->flags); radeon_fence_unref(&vm->fence); r = radeon_fence_emit(rdev, &vm->fence, ridx); @@ -997,6 +1181,7 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev, radeon_ring_unlock_commit(rdev, ring); radeon_semaphore_free(rdev, &sem, vm->fence); radeon_fence_unref(&vm->last_flush); + return 0; } @@ -1068,7 +1253,6 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) vm->id = 0; vm->fence = NULL; - vm->last_pfn = 0; mutex_init(&vm->mutex); INIT_LIST_HEAD(&vm->list); INIT_LIST_HEAD(&vm->va); -- cgit v1.2.3-55-g7522 From d72d43cfc5847c176edabc72e6431ba691322c98 Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 9 Oct 2012 13:31:18 +0200 Subject: drm/radeon: don't add the IB pool to all VMs v2 We want to use VMs without the IB pool in the future. v2: also remove it from radeon_vm_finish. Signed-off-by: Christian König Reviewed-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon.h | 2 +- drivers/gpu/drm/radeon/radeon_gart.c | 34 +++------------------------------- drivers/gpu/drm/radeon/radeon_kms.c | 22 +++++++++++++++++++++- 3 files changed, 25 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index bc6b56bf274a..54cf9b594ca6 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1848,7 +1848,7 @@ extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size */ int radeon_vm_manager_init(struct radeon_device *rdev); void radeon_vm_manager_fini(struct radeon_device *rdev); -int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm); +void radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm); void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm); int radeon_vm_alloc_pt(struct radeon_device *rdev, struct radeon_vm *vm); struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev, diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 98b170a0df90..7e21ea32242a 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -602,7 +602,6 @@ int radeon_vm_evict(struct radeon_device *rdev, struct radeon_vm *vm) * @vm: vm to bind * * Allocate a page table for the requested vm (cayman+). - * Also starts to populate the page table. * Returns 0 for success, error for failure. * * Global and local mutex must be locked! @@ -655,8 +654,7 @@ retry: } list_add_tail(&vm->list, &rdev->vm_manager.lru_vm); - return radeon_vm_bo_update_pte(rdev, vm, rdev->ring_tmp_bo.bo, - &rdev->ring_tmp_bo.bo->tbo.mem); + return 0; } /** @@ -1241,30 +1239,15 @@ void radeon_vm_bo_invalidate(struct radeon_device *rdev, * @rdev: radeon_device pointer * @vm: requested vm * - * Init @vm (cayman+). - * Map the IB pool and any other shared objects into the VM - * by default as it's used by all VMs. - * Returns 0 for success, error for failure. + * Init @vm fields (cayman+). */ -int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) +void radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) { - struct radeon_bo_va *bo_va; - int r; - vm->id = 0; vm->fence = NULL; mutex_init(&vm->mutex); INIT_LIST_HEAD(&vm->list); INIT_LIST_HEAD(&vm->va); - - /* map the ib pool buffer at 0 in virtual address space, set - * read only - */ - bo_va = radeon_vm_bo_add(rdev, vm, rdev->ring_tmp_bo.bo); - r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET, - RADEON_VM_PAGE_READABLE | - RADEON_VM_PAGE_SNOOPED); - return r; } /** @@ -1286,17 +1269,6 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) radeon_vm_free_pt(rdev, vm); mutex_unlock(&rdev->vm_manager.lock); - /* remove all bo at this point non are busy any more because unbind - * waited for the last vm fence to signal - */ - r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); - if (!r) { - bo_va = radeon_vm_bo_find(vm, rdev->ring_tmp_bo.bo); - list_del_init(&bo_va->bo_list); - list_del_init(&bo_va->vm_list); - radeon_bo_unreserve(rdev->ring_tmp_bo.bo); - kfree(bo_va); - } if (!list_empty(&vm->va)) { dev_err(rdev->dev, "still active bo inside vm\n"); } diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 83b8d8aa71c0..dc781c49b96b 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -419,6 +419,7 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) /* new gpu have virtual address space support */ if (rdev->family >= CHIP_CAYMAN) { struct radeon_fpriv *fpriv; + struct radeon_bo_va *bo_va; int r; fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL); @@ -426,7 +427,15 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) return -ENOMEM; } - r = radeon_vm_init(rdev, &fpriv->vm); + radeon_vm_init(rdev, &fpriv->vm); + + /* map the ib pool buffer read only into + * virtual address space */ + bo_va = radeon_vm_bo_add(rdev, &fpriv->vm, + rdev->ring_tmp_bo.bo); + r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET, + RADEON_VM_PAGE_READABLE | + RADEON_VM_PAGE_SNOOPED); if (r) { radeon_vm_fini(rdev, &fpriv->vm); kfree(fpriv); @@ -454,6 +463,17 @@ void radeon_driver_postclose_kms(struct drm_device *dev, /* new gpu have virtual address space support */ if (rdev->family >= CHIP_CAYMAN && file_priv->driver_priv) { struct radeon_fpriv *fpriv = file_priv->driver_priv; + struct radeon_bo_va *bo_va; + int r; + + r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); + if (!r) { + bo_va = radeon_vm_bo_find(&fpriv->vm, + rdev->ring_tmp_bo.bo); + if (bo_va) + radeon_vm_bo_rmv(rdev, bo_va); + radeon_bo_unreserve(rdev->ring_tmp_bo.bo); + } radeon_vm_fini(rdev, &fpriv->vm); kfree(fpriv); -- cgit v1.2.3-55-g7522 From 13e55c38f8ba4bb15ff9b51e2c5e7801c0f29526 Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 9 Oct 2012 13:31:19 +0200 Subject: drm/radeon: separate pt alloc from lru add Make it possible to allocate a persistent page table. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_cs.c | 1 + drivers/gpu/drm/radeon/radeon_gart.c | 20 ++++++++++++++++---- 3 files changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 54cf9b594ca6..8c42d54c2e26 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1851,6 +1851,7 @@ void radeon_vm_manager_fini(struct radeon_device *rdev); void radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm); void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm); int radeon_vm_alloc_pt(struct radeon_device *rdev, struct radeon_vm *vm); +void radeon_vm_add_to_lru(struct radeon_device *rdev, struct radeon_vm *vm); struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev, struct radeon_vm *vm, int ring); void radeon_vm_fence(struct radeon_device *rdev, diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index cb7b7c062fef..41672cc563fb 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -478,6 +478,7 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev, } out: + radeon_vm_add_to_lru(rdev, vm); mutex_unlock(&vm->mutex); mutex_unlock(&rdev->vm_manager.lock); return r; diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 7e21ea32242a..a7677dd1ce98 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -617,9 +617,6 @@ int radeon_vm_alloc_pt(struct radeon_device *rdev, struct radeon_vm *vm) } if (vm->page_directory != NULL) { - /* update lru */ - list_del_init(&vm->list); - list_add_tail(&vm->list, &rdev->vm_manager.lru_vm); return 0; } @@ -653,10 +650,25 @@ retry: return -ENOMEM; } - list_add_tail(&vm->list, &rdev->vm_manager.lru_vm); return 0; } +/** + * radeon_vm_add_to_lru - add VMs page table to LRU list + * + * @rdev: radeon_device pointer + * @vm: vm to add to LRU + * + * Add the allocated page table to the LRU list (cayman+). + * + * Global mutex must be locked! + */ +void radeon_vm_add_to_lru(struct radeon_device *rdev, struct radeon_vm *vm) +{ + list_del_init(&vm->list); + list_add_tail(&vm->list, &rdev->vm_manager.lru_vm); +} + /** * radeon_vm_grab_id - allocate the next free VMID * -- cgit v1.2.3-55-g7522 From c1a7ca0de38c23a15f652b1693afd56c9f07b16c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 8 Oct 2012 12:15:13 -0400 Subject: drm/radeon/cayman: set VM max pfn at MC init No need to emit them at VM flush as we no longer use variable sized page tables now that we support 2 level page tables. This matches the behavior of SI (which does not support variable sized page tables). Signed-off-by: Alex Deucher Reviewed-by: Christian König --- drivers/gpu/drm/radeon/ni.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index ab8d1f5fe68a..8c74c729586d 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -776,7 +776,7 @@ static int cayman_pcie_gart_enable(struct radeon_device *rdev) */ for (i = 1; i < 8; i++) { WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (i << 2), 0); - WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), 0); + WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), rdev->vm_manager.max_pfn); WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), rdev->gart.table_addr >> 12); } @@ -1576,12 +1576,6 @@ void cayman_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) if (vm == NULL) return; - radeon_ring_write(ring, PACKET0(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (vm->id << 2), 0)); - radeon_ring_write(ring, 0); - - radeon_ring_write(ring, PACKET0(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (vm->id << 2), 0)); - radeon_ring_write(ring, rdev->vm_manager.max_pfn); - radeon_ring_write(ring, PACKET0(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2), 0)); radeon_ring_write(ring, vm->pd_gpu_addr >> 12); -- cgit v1.2.3-55-g7522 From 3691feea9826771d853d28d37b6b6e34758fa66d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 8 Oct 2012 17:46:27 -0400 Subject: drm/radeon: check if pcie gen 2 is already enabled (v2) If so, skip enabling it to save time. v2: coding style fixes Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/evergreen.c | 7 ++++++- drivers/gpu/drm/radeon/r600.c | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index a1f49c5fd74b..14313ad43b76 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -3431,9 +3431,14 @@ void evergreen_pcie_gen2_enable(struct radeon_device *rdev) if (!(mask & DRM_PCIE_SPEED_50)) return; + speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); + if (speed_cntl & LC_CURRENT_DATA_RATE) { + DRM_INFO("PCIE gen 2 link speeds already enabled\n"); + return; + } + DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); - speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) || (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) { diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 70c800ff6190..cda280d157da 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3703,6 +3703,12 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev) if (!(mask & DRM_PCIE_SPEED_50)) return; + speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); + if (speed_cntl & LC_CURRENT_DATA_RATE) { + DRM_INFO("PCIE gen 2 link speeds already enabled\n"); + return; + } + DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); /* 55 nm r6xx asics */ -- cgit v1.2.3-55-g7522 From 082918471139b07964967cfe5f70230909c82ae1 Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Mon, 15 Oct 2012 08:21:39 +0200 Subject: drm/radeon: Don't destroy I2C Bus Rec in radeon_ext_tmds_enc_destroy(). radeon_i2c_fini() walks thru the list of I2C bus recs rdev->i2c_bus[] to destroy each of them. radeon_ext_tmds_enc_destroy() however also has code to destroy it's associated I2C bus rec which has been obtained by radeon_i2c_lookup() and is therefore also in the i2c_bus[] list. This causes a double free resulting in a kernel panic when unloading the radeon driver. Removing destroy code from radeon_ext_tmds_enc_destroy() fixes this problem. agd5f: fix compiler warning Signed-off-by: Egbert Eich Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index fb15b62ff984..a13ad9d707cf 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -991,11 +991,7 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder, static void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv; - if (tmds) { - if (tmds->i2c_bus) - radeon_i2c_destroy(tmds->i2c_bus); - } + /* don't destroy the i2c bus record here, this will be done in radeon_i2c_fini */ kfree(radeon_encoder->enc_priv); drm_encoder_cleanup(encoder); kfree(radeon_encoder); -- cgit v1.2.3-55-g7522 From 8ad33cdf97639e2a1601b6dd8629d351c1c50198 Mon Sep 17 00:00:00 2001 From: Thomas Friebel Date: Mon, 15 Oct 2012 13:16:22 -0400 Subject: drm/radeon: fix spelling typos in debugging output Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_ring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index bba66902c83b..47634f27f2e5 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -305,7 +305,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v) { #if DRM_DEBUG_CODE if (ring->count_dw <= 0) { - DRM_ERROR("radeon: writting more dword to ring than expected !\n"); + DRM_ERROR("radeon: writing more dwords to the ring than expected!\n"); } #endif ring->ring[ring->wptr++] = v; -- cgit v1.2.3-55-g7522 From e270b302e4771cde91e713ae17da31c1afc9a135 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Wed, 10 Oct 2012 11:13:06 -0700 Subject: brcmfmac: handle all exceptions as an error. in brcmf_usb_probe_cb only return code ENOLINK was seen as an error. This is wrong, all error codes should be returned to usb subsystem. Reviewed-by: Arend Van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Franky Lin Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index a2b4b1e71017..7a6dfdc67b6c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -1339,7 +1339,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo, } ret = brcmf_bus_start(dev); - if (ret == -ENOLINK) { + if (ret) { brcmf_dbg(ERROR, "dongle is not responding\n"); brcmf_detach(dev); goto fail; -- cgit v1.2.3-55-g7522 From a180b83bb1f036c587bdb93ac6171b94ff49133c Mon Sep 17 00:00:00 2001 From: Franky Lin Date: Wed, 10 Oct 2012 11:13:09 -0700 Subject: brcmfmac: use control channel in roamed status reporting Channel reported in scan results passed to cfg80211 is control channel. But chanspec is reported while notifying cfg80211 about roamed update. Cfg80211 complains because it could not find the bss in the list. Report control channel while calling cfg80211_roamed. Signed-off-by: Franky Lin Signed-off-by: John W. Linville --- .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 26 +++++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index c1abaa6db59e..48f08ae9062c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -4606,12 +4606,13 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, struct brcmf_cfg80211_profile *profile = cfg->profile; struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); struct wiphy *wiphy = cfg_to_wiphy(cfg); - struct brcmf_channel_info_le channel_le; - struct ieee80211_channel *notify_channel; + struct ieee80211_channel *notify_channel = NULL; struct ieee80211_supported_band *band; + struct brcmf_bss_info_le *bi; u32 freq; s32 err = 0; u32 target_channel; + u8 *buf; WL_TRACE("Enter\n"); @@ -4619,11 +4620,22 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, memcpy(profile->bssid, e->addr, ETH_ALEN); brcmf_update_bss_info(cfg); - brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le, - sizeof(channel_le)); + buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); + if (buf == NULL) { + err = -ENOMEM; + goto done; + } + + /* data sent to dongle has to be little endian */ + *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX); + err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX); + + if (err) + goto done; - target_channel = le32_to_cpu(channel_le.target_channel); - WL_CONN("Roamed to channel %d\n", target_channel); + bi = (struct brcmf_bss_info_le *)(buf + 4); + target_channel = bi->ctl_ch ? bi->ctl_ch : + CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec)); if (target_channel <= CH_MAX_2G_CHANNEL) band = wiphy->bands[IEEE80211_BAND_2GHZ]; @@ -4633,6 +4645,8 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, freq = ieee80211_channel_to_frequency(target_channel, band->band); notify_channel = ieee80211_get_channel(wiphy, freq); +done: + kfree(buf); cfg80211_roamed(ndev, notify_channel, (u8 *)profile->bssid, conn_info->req_ie, conn_info->req_ie_len, conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); -- cgit v1.2.3-55-g7522 From 5dd161ff7b46029c9da4f4ef8b214b8ba4316445 Mon Sep 17 00:00:00 2001 From: Franky Lin Date: Wed, 10 Oct 2012 11:13:10 -0700 Subject: brcmfmac: set dongle mode accordingly when interface up The mode of WiFi dongle should be initialized in brcmf_cfg80211_up which get called when network interface is brought up. Otherwise brcmf_cfg80211_get_station would return error. Signed-off-by: Franky Lin Signed-off-by: John W. Linville --- .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 38 ++-------------------- 1 file changed, 2 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 48f08ae9062c..2c66bae77b37 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -5200,41 +5200,6 @@ brcmf_cfg80211_event(struct net_device *ndev, schedule_work(&cfg->event_work); } -static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype) -{ - s32 infra = 0; - s32 err = 0; - - switch (iftype) { - case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_WDS: - WL_ERR("type (%d) : currently we do not support this mode\n", - iftype); - err = -EINVAL; - return err; - case NL80211_IFTYPE_ADHOC: - infra = 0; - break; - case NL80211_IFTYPE_STATION: - infra = 1; - break; - case NL80211_IFTYPE_AP: - infra = 1; - break; - default: - err = -EINVAL; - WL_ERR("invalid type (%d)\n", iftype); - return err; - } - err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra); - if (err) { - WL_ERR("WLC_SET_INFRA error (%d)\n", err); - return err; - } - - return 0; -} - static s32 brcmf_dongle_eventmsg(struct net_device *ndev) { /* Room for "event_msgs" + '\0' + bitvec */ @@ -5453,7 +5418,8 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) WL_BEACON_TIMEOUT); if (err) goto default_conf_out; - err = brcmf_dongle_mode(ndev, wdev->iftype); + err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype, + NULL, NULL); if (err && err != -EINPROGRESS) goto default_conf_out; err = brcmf_dongle_probecap(cfg); -- cgit v1.2.3-55-g7522 From 3e4f319dacc60c1b4537b85329d393ad18bf7501 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 10 Oct 2012 11:13:12 -0700 Subject: brcmfmac: fix end of loop check (signedness bug) The problem here is that we loop until "remained_buf_len" is less than zero, but since it is unsigned, it never is. "remained_buf_len" has to be large enough to hold the value from "mgmt_ie_buf_len". That variable is type u32, but it only holds small values so I have changed to both variables to int. Also I removed the bogus initialization from "mgmt_ie_buf_len" so that GCC can detect if it is used unitialized. I moved the declaration of "remained_buf_len" closer to where it is used so it's easier to read. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Hante Meuleman Signed-off-by: Dan Carpenter Signed-off-by: Franky Lin Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 2c66bae77b37..411dfe7c7ff0 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -3972,7 +3972,7 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg, u8 *iovar_ie_buf; u8 *curr_ie_buf; u8 *mgmt_ie_buf = NULL; - u32 mgmt_ie_buf_len = 0; + int mgmt_ie_buf_len; u32 *mgmt_ie_len = 0; u32 del_add_ie_buf_len = 0; u32 total_ie_buf_len = 0; @@ -3982,7 +3982,7 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg, struct parsed_vndr_ie_info *vndrie_info; s32 i; u8 *ptr; - u32 remained_buf_len; + int remained_buf_len; WL_TRACE("bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag); iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); -- cgit v1.2.3-55-g7522 From 1fffa905adffbf0d3767fc978ef09afb830275eb Mon Sep 17 00:00:00 2001 From: Piotr Haber Date: Thu, 11 Oct 2012 14:05:15 +0200 Subject: bcma: fix unregistration of cores When cores are unregistered, entries need to be removed from cores list in a safe manner. Reported-by: Stanislaw Gruszka Reviewed-by: Arend Van Spriel Signed-off-by: Piotr Haber Cc: stable@vger.kernel.org Signed-off-by: John W. Linville --- drivers/bcma/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 432aeeedfd5e..d865470bc951 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -158,9 +158,10 @@ static int bcma_register_cores(struct bcma_bus *bus) static void bcma_unregister_cores(struct bcma_bus *bus) { - struct bcma_device *core; + struct bcma_device *core, *tmp; - list_for_each_entry(core, &bus->cores, list) { + list_for_each_entry_safe(core, tmp, &bus->cores, list) { + list_del(&core->list); if (core->dev_registered) device_unregister(&core->dev); } -- cgit v1.2.3-55-g7522 From bf11315eeda510ea4fc1a2bf972d8155d31d89b4 Mon Sep 17 00:00:00 2001 From: Stanislav Yakovlev Date: Mon, 15 Oct 2012 14:14:32 +0000 Subject: net/wireless: ipw2200: Fix panic occurring in ipw_handle_promiscuous_tx() The driver does not count space of radiotap fields when allocating skb for radiotap packet. This leads to kernel panic with the following call trace: ... [67607.676067] [] error_code+0x67/0x6c [67607.676067] [] ? skb_put+0x91/0xa0 [67607.676067] [] ? ipw_handle_promiscuous_tx+0x16b/0x2d0 [ipw2200] [67607.676067] [] ipw_handle_promiscuous_tx+0x16b/0x2d0 [ipw2200] [67607.676067] [] ipw_net_hard_start_xmit+0x8b/0x90 [ipw2200] [67607.676067] [] libipw_xmit+0x55a/0x980 [libipw] [67607.676067] [] dev_hard_start_xmit+0x218/0x4d0 ... This bug was found by VittGam. https://bugzilla.kernel.org/show_bug.cgi?id=43255 Cc: stable@kernel.org Signed-off-by: Stanislav Yakovlev Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 935120fc8c93..768bf612533e 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -10472,7 +10472,7 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv, } else len = src->len; - dst = alloc_skb(len + sizeof(*rt_hdr), GFP_ATOMIC); + dst = alloc_skb(len + sizeof(*rt_hdr) + sizeof(u16)*2, GFP_ATOMIC); if (!dst) continue; -- cgit v1.2.3-55-g7522 From d79550a7bc35c16476ebdc27c78378d8093390ec Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 11 Oct 2012 09:56:35 +0300 Subject: gpio-timberdale: fix a potential wrapping issue ->last_ier is an unsigned long but the high bits can't be used int the original code because the shift wraps. Cc: stable@kernel.org Signed-off-by: Dan Carpenter Signed-off-by: Linus Walleij --- drivers/gpio/gpio-timberdale.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index 031c6adf5b65..1a3e2b9b4772 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -116,7 +116,7 @@ static void timbgpio_irq_disable(struct irq_data *d) unsigned long flags; spin_lock_irqsave(&tgpio->lock, flags); - tgpio->last_ier &= ~(1 << offset); + tgpio->last_ier &= ~(1UL << offset); iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); spin_unlock_irqrestore(&tgpio->lock, flags); } @@ -128,7 +128,7 @@ static void timbgpio_irq_enable(struct irq_data *d) unsigned long flags; spin_lock_irqsave(&tgpio->lock, flags); - tgpio->last_ier |= 1 << offset; + tgpio->last_ier |= 1UL << offset; iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); spin_unlock_irqrestore(&tgpio->lock, flags); } -- cgit v1.2.3-55-g7522 From 3e5bde8ef4cc9e719b492726dd82a43d29468cd0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 15 Oct 2012 22:13:12 +0200 Subject: serial/8250_hp300: Missing 8250 register interface conversion bits commit 2655a2c76f80d91da34faa8f4e114d1793435ed3 ("8250: use the 8250 register interface not the legacy one") forgot to fully switch one instance of struct uart_port to struct uart_8250_port, causing the following compile failure: drivers/tty/serial/8250/8250_hp300.c: In function ‘hpdca_init_one’: drivers/tty/serial/8250/8250_hp300.c:174: error: ‘uart’ undeclared (first use in this function) drivers/tty/serial/8250/8250_hp300.c:174: error: (Each undeclared identifier is reported only once drivers/tty/serial/8250/8250_hp300.c:174: error: for each function it appears in.) This went unnoticed in -next, as CONFIG_HPDCA is not set to y by allmodconfig. Reported-by: Fengguang Wu Cc: Alan Cox Cc: Philip Blundell Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_hp300.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c index 8f1dd2cc00a8..f3d0edf46644 100644 --- a/drivers/tty/serial/8250/8250_hp300.c +++ b/drivers/tty/serial/8250/8250_hp300.c @@ -162,7 +162,7 @@ int __init hp300_setup_serial_console(void) static int __devinit hpdca_init_one(struct dio_dev *d, const struct dio_device_id *ent) { - struct uart_port port; + struct uart_8250_port uart; int line; #ifdef CONFIG_SERIAL_8250_CONSOLE @@ -174,19 +174,19 @@ static int __devinit hpdca_init_one(struct dio_dev *d, memset(&uart, 0, sizeof(uart)); /* Memory mapped I/O */ - port.iotype = UPIO_MEM; - port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF; - port.irq = d->ipl; - port.uartclk = HPDCA_BAUD_BASE * 16; - port.mapbase = (d->resource.start + UART_OFFSET); - port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE); - port.regshift = 1; - port.dev = &d->dev; + uart.port.iotype = UPIO_MEM; + uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF; + uart.port.irq = d->ipl; + uart.port.uartclk = HPDCA_BAUD_BASE * 16; + uart.port.mapbase = (d->resource.start + UART_OFFSET); + uart.port.membase = (char *)(uart.port.mapbase + DIO_VIRADDRBASE); + uart.port.regshift = 1; + uart.port.dev = &d->dev; line = serial8250_register_8250_port(&uart); if (line < 0) { printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d" - " irq %d failed\n", d->scode, port.irq); + " irq %d failed\n", d->scode, uart.port.irq); return -ENOMEM; } -- cgit v1.2.3-55-g7522 From dd8e8c4a2c902d8350b702e7bc7c2799e5e7e331 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Mon, 15 Oct 2012 13:40:15 -0700 Subject: thermal, cpufreq: Fix build when CPU_FREQ_TABLE isn't configured Commit 023614183768 ("thermal: add generic cpufreq cooling implementation") requires cpufreq_frequency_get_table(), but that function is only defined for CONFIG_CPU_FREQ_TABLE resulting in the following build error: drivers/built-in.o: In function `cpufreq_get_max_state': drivers/thermal/cpu_cooling.c:259: undefined reference to `cpufreq_frequency_get_table' drivers/built-in.o: In function `get_cpu_frequency': drivers/thermal/cpu_cooling.c:129: undefined reference to `cpufreq_frequency_get_table' Fix it by selecting CONFIG_CPU_FREQ_TABLE for such a configuration. It turns out CONFIG_EXYNOS_THERMAL also needs CONFIG_CPU_FREQ_TABLE, so select it there as well. Signed-off-by: David Rientjes Signed-off-by: Linus Torvalds --- drivers/thermal/Kconfig | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index edfd67d25013..e1cb6bd75f60 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -22,6 +22,7 @@ config THERMAL_HWMON config CPU_THERMAL bool "generic cpu cooling support" depends on THERMAL && CPU_FREQ + select CPU_FREQ_TABLE help This implements the generic cpu cooling mechanism through frequency reduction, cpu hotplug and any other ways of reducing temperature. An @@ -50,6 +51,7 @@ config RCAR_THERMAL config EXYNOS_THERMAL tristate "Temperature sensor on Samsung EXYNOS" depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5) && THERMAL + select CPU_FREQ_TABLE help If you say yes here you get support for TMU (Thermal Managment Unit) on SAMSUNG EXYNOS series of SoC. -- cgit v1.2.3-55-g7522 From bd6126bd0766cb0e03a4d832cc3611dff5ea8e50 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 16 Oct 2012 10:15:45 +1000 Subject: drm: radeon: fix printk format warning drivers/gpu/drm/radeon/radeon_atpx_handler.c:151:3: warning: format '%lu' expects type 'long unsigned int', but argument 2 has type 'size_t' [airlied: Alex had others fixed already, except for atpx one] Signed-off-by: Randy Dunlap Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_atpx_handler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 582e99449c12..1aa3f910b993 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -148,7 +148,7 @@ static int radeon_atpx_verify_interface(struct radeon_atpx *atpx) size = *(u16 *) info->buffer.pointer; if (size < 8) { - printk("ATPX buffer is too small: %lu\n", size); + printk("ATPX buffer is too small: %zu\n", size); err = -EINVAL; goto out; } -- cgit v1.2.3-55-g7522 From 7b8505300525d7e802ecf52ae160bc63f4ba28d7 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 16 Oct 2012 10:28:21 +1000 Subject: drm: fix warning on 32-bit. This cast was causing a warning on 32-bit builds. Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index cdf8b1e7602d..441ebc1bdbef 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c @@ -239,7 +239,7 @@ int drm_vma_info(struct seq_file *m, void *data) mutex_lock(&dev->struct_mutex); seq_printf(m, "vma use count: %d, high_memory = %pK, 0x%pK\n", atomic_read(&dev->vma_count), - high_memory, (void *)virt_to_phys(high_memory)); + high_memory, (void *)(unsigned long)virt_to_phys(high_memory)); list_for_each_entry(pt, &dev->vmalist, head) { vma = pt->vma; -- cgit v1.2.3-55-g7522 From a5f5af8698a5cb3a68608a40a8782bdf8263cb97 Mon Sep 17 00:00:00 2001 From: Martin Peres Date: Thu, 4 Oct 2012 00:28:21 +0200 Subject: drm/nouveau/hwmon: fix the initialization condition Signed-off-by: Martin Peres Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_pm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c index b9d5335df742..47677e3f8d7e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c @@ -706,8 +706,7 @@ nouveau_hwmon_init(struct drm_device *dev) struct device *hwmon_dev; int ret = 0; - if (!therm || !therm->temp_get || !therm->attr_get || - !therm->attr_set || therm->temp_get(therm) < 0) + if (!therm || !therm->temp_get || !therm->attr_get || !therm->attr_set) return -ENODEV; hwmon_dev = hwmon_device_register(&dev->pdev->dev); -- cgit v1.2.3-55-g7522 From a6fd5cf3c986dab3950185a53ef02a399bf2cf2b Mon Sep 17 00:00:00 2001 From: Martin Peres Date: Thu, 4 Oct 2012 00:44:19 +0200 Subject: drm/nouveau/pm: fix a typo related to the move to the therm subdev Reported-by: Vekin on IRC Reported-by: Emil Velikov Signed-off-by: Martin Peres Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c index 47677e3f8d7e..75314a1befc6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c @@ -52,7 +52,7 @@ nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl, { struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_pm *pm = nouveau_pm(dev); - struct nouveau_therm *therm = nouveau_therm(drm); + struct nouveau_therm *therm = nouveau_therm(drm->device); int ret; /*XXX: not on all boards, we should control based on temperature -- cgit v1.2.3-55-g7522 From eed6187d9f19535ac9339b684537f8535bf563b7 Mon Sep 17 00:00:00 2001 From: Martin Peres Date: Thu, 4 Oct 2012 01:00:13 +0200 Subject: drm/nouveau/pm: do not stop reclocking if failing to set the fan speed With the introduction of fan management modes, fan may not be drivable. We should allow reclocking nonetheless. This return was stupid to begin with since it may have left the card in an intermediate state (clocks corresponding to a perflvl and voltage corresponding to another one). The reclocking code will need to be rewritten in a near-future in order to provide a better error handling. Reported-by: Marcin Slusarz Signed-off-by: Martin Peres Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_pm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c index 75314a1befc6..112d0deeb6d5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c @@ -64,7 +64,6 @@ nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl, ret = therm->fan_set(therm, perflvl->fanspeed); if (ret && ret != -ENODEV) { NV_ERROR(drm, "fanspeed set failed: %d\n", ret); - return ret; } } -- cgit v1.2.3-55-g7522 From 5db4c6c5dd26f7737c1fa45ea73549b8aef6e395 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Thu, 11 Oct 2012 23:53:48 +0200 Subject: drm/nv50/fb: fix double free of vram mm nouveau_fb_destroy already calls nouveau_mm_fini on vram mm. Signed-off-by: Marcin Slusarz Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c index 436e9efe7ef5..42d7539e6525 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c @@ -277,7 +277,6 @@ nv50_fb_dtor(struct nouveau_object *object) __free_page(priv->r100c08_page); } - nouveau_mm_fini(&priv->base.vram); nouveau_fb_destroy(&priv->base); } -- cgit v1.2.3-55-g7522 From df1b4b91e5dae04782f65f657d771b23ca3bdc99 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 14 Oct 2012 01:58:26 +0400 Subject: drm/nouveau: only call ttm_agp_tt_create when __OS_HAS_AGP ttm_agp_tt_create is itself defined under CONFIG_AGP, so there's no point calling it otherwise. Signed-off-by: Max Filippov Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bo.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 259e5f1adf47..35ac57f0aab6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -456,6 +456,7 @@ static struct ttm_tt * nouveau_ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size, uint32_t page_flags, struct page *dummy_read) { +#if __OS_HAS_AGP struct nouveau_drm *drm = nouveau_bdev(bdev); struct drm_device *dev = drm->dev; @@ -463,6 +464,7 @@ nouveau_ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size, return ttm_agp_tt_create(bdev, dev->agp->bridge, size, page_flags, dummy_read); } +#endif return nouveau_sgdma_create_ttm(bdev, size, page_flags, dummy_read); } -- cgit v1.2.3-55-g7522 From 565f571c48f01a681243a356e9083f5cf24b432e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 16 Oct 2012 16:25:08 +1000 Subject: drm/nouveau/bios: fix typo in error message Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c index 9ed6e728a94c..7d750382a833 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c @@ -43,7 +43,7 @@ dcb_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) *ver = nv_ro08(bios, dcb); if (*ver >= 0x41) { - nv_warn(bios, "DCB *ver 0x%02x unknown\n", *ver); + nv_warn(bios, "DCB version 0x%02x unknown\n", *ver); return 0x0000; } else if (*ver >= 0x30) { -- cgit v1.2.3-55-g7522 From 8a00b6af4cc547725f231c8367ddc7cb56b2cf76 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 16 Oct 2012 16:40:53 +1000 Subject: nouveau: fix warning on 32-bit build. Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/core/subdev/therm/fan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c index b29237970fa0..523178685180 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c @@ -134,7 +134,7 @@ nouveau_therm_fan_sense(struct nouveau_therm *therm) end = ptimer->read(ptimer); if (cycles == 5) { - tach = (u64)60000000000; + tach = (u64)60000000000ULL; do_div(tach, (end - start)); return tach; } else -- cgit v1.2.3-55-g7522 From 6478d414fe4ee3114e760fb6d6df0f8e2f66186a Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Sun, 14 Oct 2012 16:33:11 +0200 Subject: DRM/i915: Don't delete DPLL Multiplier during DAC init. The DPLL multipiler is set up in intel_display.c:i9xx_update_pll() called from i9xx_crtc_mode_set(). There the DPLL multiplier is adjusted so that the SDVO gets a sufficient bus clock. When cloning a CRTC between an SDVO driven encoder and the standard DAC the DAC setup code reseted the multiplier value to 1 thus undoing the correct setup. There is no need to touch the multiplier in the DAC setup code: the correct value (i.e. 1 in case no SDVO encoder is used) is set by i9xx_update_pll() already. A comment at the code suggested that this code is a left over from the days when there was no setup for clone modes. Signed-off-by: Egbert Eich Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_crt.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index c42b9809f86d..ae3a3d545ef2 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -220,20 +220,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, intel_encoder_to_crt(to_intel_encoder(encoder)); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_i915_private *dev_priv = dev->dev_private; - int dpll_md_reg; - u32 adpa, dpll_md; - - dpll_md_reg = DPLL_MD(intel_crtc->pipe); - - /* - * Disable separate mode multiplier used when cloning SDVO to CRT - * XXX this needs to be adjusted when we really are cloning - */ - if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { - dpll_md = I915_READ(dpll_md_reg); - I915_WRITE(dpll_md_reg, - dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); - } + u32 adpa; adpa = ADPA_HOTPLUG_BITS; if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) -- cgit v1.2.3-55-g7522 From 5f85f176c2f1c9d2a23f60ca0b99e4d0aa5a26a7 Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Sun, 14 Oct 2012 15:46:38 +0200 Subject: DRM/i915: Add QUIRK_INVERT_BRIGHTNESS for NCR machines. NCR machines with LVDS panels using Intel chipsets need to have the QUIRK_INVERT_BRIGHTNESS bit set. Unfortunately NCR doesn't set a meaningful subvendor/subdevice ID, therefore we add a DMI dependent quirk list. Signed-off-by: Egbert Eich [danvet: fixup whitespace fail.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3511effa01ec..68495da433e6 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7892,6 +7892,34 @@ struct intel_quirk { void (*hook)(struct drm_device *dev); }; +/* For systems that don't have a meaningful PCI subdevice/subvendor ID */ +struct intel_dmi_quirk { + void (*hook)(struct drm_device *dev); + const struct dmi_system_id (*dmi_id_list)[]; +}; + +static int intel_dmi_reverse_brightness(const struct dmi_system_id *id) +{ + DRM_INFO("Backlight polarity reversed on %s\n", id->ident); + return 1; +} + +static const struct intel_dmi_quirk intel_dmi_quirks[] = { + { + .dmi_id_list = &(const struct dmi_system_id[]) { + { + .callback = intel_dmi_reverse_brightness, + .ident = "NCR Corporation", + .matches = {DMI_MATCH(DMI_SYS_VENDOR, "NCR Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, ""), + }, + }, + { } /* terminating entry */ + }, + .hook = quirk_invert_brightness, + }, +}; + static struct intel_quirk intel_quirks[] = { /* HP Mini needs pipe A force quirk (LP: #322104) */ { 0x27ae, 0x103c, 0x361a, quirk_pipea_force }, @@ -7931,6 +7959,10 @@ static void intel_init_quirks(struct drm_device *dev) q->subsystem_device == PCI_ANY_ID)) q->hook(dev); } + for (i = 0; i < ARRAY_SIZE(intel_dmi_quirks); i++) { + if (dmi_check_system(*intel_dmi_quirks[i].dmi_id_list) != 0) + intel_dmi_quirks[i].hook(dev); + } } /* Disable the VGA plane that we never use */ -- cgit v1.2.3-55-g7522 From e3b86d6941c7e5f90be05d986fce1fcb40c68d6b Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Sat, 13 Oct 2012 14:30:15 +0200 Subject: DRM/i915: Don't clone SDVO LVDS with analog. SDVO LVDS are not clonable as the input mode gets adjusted by the LVDS encoder. Signed-off-by: Egbert Eich Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sdvo.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 39c319827f91..3a7251ad9a73 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2278,10 +2278,8 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1; } - /* SDVO LVDS is cloneable because the SDVO encoder does the upscaling, - * as opposed to native LVDS, where we upscale with the panel-fitter - * (and hence only the native LVDS resolution could be cloned). */ - intel_sdvo->base.cloneable = true; + /* SDVO LVDS is not cloneable because the input mode gets adjusted by the encoder */ + intel_sdvo->base.cloneable = false; intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) -- cgit v1.2.3-55-g7522 From e751823da27d37d25e5543abef2dc031f8813bc8 Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Sat, 13 Oct 2012 14:29:31 +0200 Subject: DRM/i915: Restore sdvo_flags after dtd->mode->dtd Roundrtrip. For TV and LVDS encoders intel_sdvo_set_input_timings_for_mode() is called to pass a mode to the sdvo chip and retrieve a dtd containing information needed to calculate the adjusted_mode which is done by intel_sdvo_get_dtd_from_mode(). To set this adjusted_mode as input mode for the sdvo chip, a dtd is recalculated using intel_sdvo_get_mode_from_dtd(). During this round trip the sdvo_flags contained in the dtd obtained from the hardware are lost. Since these flags cannot be ignored in all cases this patch preserves and restores them. This regression has been introduced in commit 6651819b4b4fc3caa6964c5d825eb4bb996f3905 Author: Daniel Vetter Date: Sun Apr 1 19:16:18 2012 +0200 drm/i915: handle input/output sdvo timings separately in mode_set Signed-off-by: Egbert Eich Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sdvo.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 3a7251ad9a73..d2e8c9f4d6d5 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -140,6 +140,11 @@ struct intel_sdvo { /* DDC bus used by this SDVO encoder */ uint8_t ddc_bus; + + /* + * the sdvo flag gets lost in round trip: dtd->adjusted_mode->dtd + */ + uint8_t dtd_sdvo_flags; }; struct intel_sdvo_connector { @@ -985,6 +990,7 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo, return false; intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); + intel_sdvo->dtd_sdvo_flags = input_dtd.part2.sdvo_flags; return true; } @@ -1093,6 +1099,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, * adjusted_mode. */ intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); + if (intel_sdvo->is_tv || intel_sdvo->is_lvds) + input_dtd.part2.sdvo_flags = intel_sdvo->dtd_sdvo_flags; if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd)) DRM_INFO("Setting input timings on %s failed\n", SDVO_NAME(intel_sdvo)); -- cgit v1.2.3-55-g7522 From b06fbda328490ec471e72659a9bf69f16a1c8dc9 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 16 Oct 2012 09:50:25 +0200 Subject: Revert "drm/i915: Try harder to complete DP training pattern 1" This reverts commit 2477367083b3eaa97f87993ab26627a02f350551. If (for whatever reason) the DP sink device never asks for the maximal voltage level, we never don't hit the check that should bail us out after 5 retries of the same voltage. Which leads to an endless loop in the DP link training code, which hangs the driver. Now some more DP link training experiments on eDP panels seem to indicate that our training algorithm isn't robust enough anyway and needs more work. Hence for 3.7-fixes, let's just revert the regressing commit instead of trying to apply more duct-tape. Reported-by: Oleksij Rempel Acked-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index bd2c34a0aa9a..e37ca2cd4f99 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1798,7 +1798,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) break; if (i == intel_dp->lane_count && voltage_tries == 5) { - if (++loop_tries == 5) { + ++loop_tries; + if (loop_tries == 5) { DRM_DEBUG_KMS("too many full retries, give up\n"); break; } @@ -1808,11 +1809,15 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) } /* Check to see if we've tried the same voltage 5 times */ - if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) { - voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; - voltage_tries = 0; - } else + if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { ++voltage_tries; + if (voltage_tries == 5) { + DRM_DEBUG_KMS("too many voltage retries, give up\n"); + break; + } + } else + voltage_tries = 0; + voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; /* Compute new intel_dp->train_set as requested by target */ intel_get_adjust_train(intel_dp, link_status); -- cgit v1.2.3-55-g7522 From c2fa3edc58a262dfcb7aea78e24661e90e00098c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 15 Oct 2012 23:24:55 -0700 Subject: usb: renesas_usbhs: fixup __usbhs_for_each_pipe 1st pos __usbhs_for_each_pipe() is the macro which moves around each pipe, but it has a bug which didn't care about 1st pipe's position. Because of this bug, it moves around pipe0, pipe2, pipe3 ... even though it requested pipe1, pipe2, pipe3... This patch modifies it. Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/pipe.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index 08786c06dcf1..3d80c7b1fd1b 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h @@ -54,7 +54,7 @@ struct usbhs_pipe_info { * pipe list */ #define __usbhs_for_each_pipe(start, pos, info, i) \ - for (i = start, pos = (info)->pipe; \ + for (i = start, pos = (info)->pipe + i; \ i < (info)->size; \ i++, pos = (info)->pipe + i) -- cgit v1.2.3-55-g7522 From d5c6a1e024dd5acd6ad2e1a6eb6a2fd5c15c50f1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 11 Oct 2012 21:49:38 -0700 Subject: usb: renesas_usbhs: fixup interrupt status clear method When interrupt happened, renesas_usbhs driver gets irq status by usbhs_status_get_each_irq(), and cleared all status by using 0. But, this method is incorrect, since extra interrupt might occur between them. This patch cleared corresponding bits only Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/mod.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c index 35c5208f3249..61933a90e5bf 100644 --- a/drivers/usb/renesas_usbhs/mod.c +++ b/drivers/usb/renesas_usbhs/mod.c @@ -273,9 +273,9 @@ static irqreturn_t usbhs_interrupt(int irq, void *data) usbhs_write(priv, INTSTS0, ~irq_state.intsts0 & INTSTS0_MAGIC); usbhs_write(priv, INTSTS1, ~irq_state.intsts1 & INTSTS1_MAGIC); - usbhs_write(priv, BRDYSTS, 0); - usbhs_write(priv, NRDYSTS, 0); - usbhs_write(priv, BEMPSTS, 0); + usbhs_write(priv, BRDYSTS, ~irq_state.brdysts); + usbhs_write(priv, NRDYSTS, ~irq_state.nrdysts); + usbhs_write(priv, BEMPSTS, ~irq_state.bempsts); /* * call irq callback functions -- cgit v1.2.3-55-g7522 From 69da85edbab5cd42909d3ba65b3dad1c1fb40206 Mon Sep 17 00:00:00 2001 From: Alexandre Pereira da Silva Date: Mon, 15 Oct 2012 09:47:35 -0300 Subject: usb: gadget: lpc32xx_udc: Fix compatibility with STOTG04 The STOTG04 is an replacement for ISP1301. Most of the registers on STOTG04 are the same as on ISP1301, but the register ISP1301_I2C_OTG_CONTROL_2 (address 0x10) doesn't exist on the ST part. This is a work around for this by using the interrupt source register that should behave the same on both parts and has the needed information. Tested-by: Roland Stigge Signed-off-by: Alexandre Pereira da Silva Signed-off-by: Felipe Balbi --- drivers/usb/gadget/lpc32xx_udc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c index f696fb9b136d..21a9861dabf0 100644 --- a/drivers/usb/gadget/lpc32xx_udc.c +++ b/drivers/usb/gadget/lpc32xx_udc.c @@ -2930,10 +2930,10 @@ static void vbus_work(struct work_struct *work) /* Get the VBUS status from the transceiver */ value = i2c_smbus_read_byte_data(udc->isp1301_i2c_client, - ISP1301_I2C_OTG_CONTROL_2); + ISP1301_I2C_INTERRUPT_SOURCE); /* VBUS on or off? */ - if (value & OTG_B_SESS_VLD) + if (value & INT_SESS_VLD) udc->vbus = 1; else udc->vbus = 0; -- cgit v1.2.3-55-g7522 From c2ff5cf5294bcbd7fa50f7d860e90a66db7e5059 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 16 Oct 2012 14:52:51 +0200 Subject: iommu/amd: Work around wrong IOAPIC device-id in IVRS table On some systems the BIOS puts the wrong device-id for the IO-APIC into the IVRS table. The result is that interrupt remapping is not working for the IO-APIC irqs. This usually means a kernel panic at boot because the timer is not working. Fix this kernel panic by disabling interrupt remapping if this problem is discovered in the IVRS table. Reported-by: Andrew Oakley Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu_init.c | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 18b0d99bd4d6..81837b0710a9 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -1599,21 +1599,46 @@ static void __init free_on_init_error(void) #endif } +/* SB IOAPIC is always on this device in AMD systems */ +#define IOAPIC_SB_DEVID ((0x00 << 8) | PCI_DEVFN(0x14, 0)) + static bool __init check_ioapic_information(void) { + bool ret, has_sb_ioapic; int idx; - for (idx = 0; idx < nr_ioapics; idx++) { - int id = mpc_ioapic_id(idx); + has_sb_ioapic = false; + ret = false; - if (get_ioapic_devid(id) < 0) { - pr_err(FW_BUG "AMD-Vi: IO-APIC[%d] not in IVRS table\n", id); - pr_err("AMD-Vi: Disabling interrupt remapping due to BIOS Bug\n"); - return false; + for (idx = 0; idx < nr_ioapics; idx++) { + int devid, id = mpc_ioapic_id(idx); + + devid = get_ioapic_devid(id); + if (devid < 0) { + pr_err(FW_BUG "AMD-Vi: IOAPIC[%d] not in IVRS table\n", id); + ret = false; + } else if (devid == IOAPIC_SB_DEVID) { + has_sb_ioapic = true; + ret = true; } } - return true; + if (!has_sb_ioapic) { + /* + * We expect the SB IOAPIC to be listed in the IVRS + * table. The system timer is connected to the SB IOAPIC + * and if we don't have it in the list the system will + * panic at boot time. This situation usually happens + * when the BIOS is buggy and provides us the wrong + * device id for the IOAPIC in the system. + */ + pr_err(FW_BUG "AMD-Vi: No southbridge IOAPIC found in IVRS table\n"); + } + + if (!ret) + pr_err("AMD-Vi: Disabling interrupt remapping due to BIOS Bug(s)\n"); + + return ret; } static void __init free_dma_resources(void) -- cgit v1.2.3-55-g7522 From 8f7b8db6e0557c8437adf9371e020cd89a7e85dc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 25 Sep 2012 16:40:12 +0200 Subject: iwlwifi: fix 6000 series channel switch command The channel switch command for 6000 series devices is larger than the maximum inline command size of 320 bytes. The command is therefore refused with a warning. Fix this by allocating the command and using the NOCOPY mechanism. Cc: stable@kernel.org Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/dvm/devices.c | 39 ++++++++++++++++++------------ 1 file changed, 24 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c index 349c205d5f62..da5862064195 100644 --- a/drivers/net/wireless/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/iwlwifi/dvm/devices.c @@ -518,7 +518,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, * See iwlagn_mac_channel_switch. */ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - struct iwl6000_channel_switch_cmd cmd; + struct iwl6000_channel_switch_cmd *cmd; u32 switch_time_in_usec, ucode_switch_time; u16 ch; u32 tsf_low; @@ -527,18 +527,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, struct ieee80211_vif *vif = ctx->vif; struct iwl_host_cmd hcmd = { .id = REPLY_CHANNEL_SWITCH, - .len = { sizeof(cmd), }, + .len = { sizeof(*cmd), }, .flags = CMD_SYNC, - .data = { &cmd, }, + .dataflags[0] = IWL_HCMD_DFL_NOCOPY, }; + int err; - cmd.band = priv->band == IEEE80211_BAND_2GHZ; + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + hcmd.data[0] = cmd; + + cmd->band = priv->band == IEEE80211_BAND_2GHZ; ch = ch_switch->channel->hw_value; IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", ctx->active.channel, ch); - cmd.channel = cpu_to_le16(ch); - cmd.rxon_flags = ctx->staging.flags; - cmd.rxon_filter_flags = ctx->staging.filter_flags; + cmd->channel = cpu_to_le16(ch); + cmd->rxon_flags = ctx->staging.flags; + cmd->rxon_filter_flags = ctx->staging.filter_flags; switch_count = ch_switch->count; tsf_low = ch_switch->timestamp & 0x0ffffffff; /* @@ -554,23 +561,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, switch_count = 0; } if (switch_count <= 1) - cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); + cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time); else { switch_time_in_usec = vif->bss_conf.beacon_int * switch_count * TIME_UNIT; ucode_switch_time = iwl_usecs_to_beacons(priv, switch_time_in_usec, beacon_interval); - cmd.switch_time = iwl_add_beacon_time(priv, - priv->ucode_beacon_time, - ucode_switch_time, - beacon_interval); + cmd->switch_time = iwl_add_beacon_time(priv, + priv->ucode_beacon_time, + ucode_switch_time, + beacon_interval); } IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", - cmd.switch_time); - cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; + cmd->switch_time); + cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; - return iwl_dvm_send_cmd(priv, &hcmd); + err = iwl_dvm_send_cmd(priv, &hcmd); + kfree(cmd); + return err; } struct iwl_lib_ops iwl6000_lib = { -- cgit v1.2.3-55-g7522 From 916ca14aaf12a7191118adb51bb95e3c7866380d Mon Sep 17 00:00:00 2001 From: David S. Miller Date: Tue, 16 Oct 2012 09:34:01 -0700 Subject: sparc64: Add global PMU register dumping via sysrq. Signed-off-by: David S. Miller --- Documentation/sysrq.txt | 1 + arch/sparc/include/asm/ptrace.h | 13 ++++- arch/sparc/include/asm/smp_64.h | 2 + arch/sparc/kernel/process_64.c | 120 +++++++++++++++++++++++++++++++++------- arch/sparc/kernel/smp_64.c | 11 ++++ arch/sparc/mm/ultra.S | 64 ++++++++++++++++++++- drivers/tty/sysrq.c | 1 + 7 files changed, 189 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt index 642f84495b29..2a4cdda4828e 100644 --- a/Documentation/sysrq.txt +++ b/Documentation/sysrq.txt @@ -116,6 +116,7 @@ On all - write a character to /proc/sysrq-trigger. e.g.: 'w' - Dumps tasks that are in uninterruptable (blocked) state. 'x' - Used by xmon interface on ppc/powerpc platforms. + Show global PMU Registers on sparc64. 'y' - Show global CPU Registers [SPARC-64 specific] diff --git a/arch/sparc/include/asm/ptrace.h b/arch/sparc/include/asm/ptrace.h index 0c6f6b068289..da43bdc62294 100644 --- a/arch/sparc/include/asm/ptrace.h +++ b/arch/sparc/include/asm/ptrace.h @@ -42,7 +42,18 @@ struct global_reg_snapshot { struct thread_info *thread; unsigned long pad1; }; -extern struct global_reg_snapshot global_reg_snapshot[NR_CPUS]; + +struct global_pmu_snapshot { + unsigned long pcr[4]; + unsigned long pic[4]; +}; + +union global_cpu_snapshot { + struct global_reg_snapshot reg; + struct global_pmu_snapshot pmu; +}; + +extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS]; #define force_successful_syscall_return() \ do { current_thread_info()->syscall_noerror = 1; \ diff --git a/arch/sparc/include/asm/smp_64.h b/arch/sparc/include/asm/smp_64.h index 29862a9e9065..dd3bef4b9896 100644 --- a/arch/sparc/include/asm/smp_64.h +++ b/arch/sparc/include/asm/smp_64.h @@ -48,6 +48,7 @@ extern void smp_fill_in_sib_core_maps(void); extern void cpu_play_dead(void); extern void smp_fetch_global_regs(void); +extern void smp_fetch_global_pmu(void); struct seq_file; void smp_bogo(struct seq_file *); @@ -65,6 +66,7 @@ extern void __cpu_die(unsigned int cpu); #define hard_smp_processor_id() 0 #define smp_fill_in_sib_core_maps() do { } while (0) #define smp_fetch_global_regs() do { } while (0) +#define smp_fetch_global_pmu() do { } while (0) #endif /* !(CONFIG_SMP) */ diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index fcaa59421126..d778248ef3f8 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,7 @@ #include #include #include +#include #include "kstack.h" @@ -204,18 +206,22 @@ void show_regs(struct pt_regs *regs) show_stack(current, (unsigned long *) regs->u_regs[UREG_FP]); } -struct global_reg_snapshot global_reg_snapshot[NR_CPUS]; -static DEFINE_SPINLOCK(global_reg_snapshot_lock); +union global_cpu_snapshot global_cpu_snapshot[NR_CPUS]; +static DEFINE_SPINLOCK(global_cpu_snapshot_lock); static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, int this_cpu) { + struct global_reg_snapshot *rp; + flushw_all(); - global_reg_snapshot[this_cpu].tstate = regs->tstate; - global_reg_snapshot[this_cpu].tpc = regs->tpc; - global_reg_snapshot[this_cpu].tnpc = regs->tnpc; - global_reg_snapshot[this_cpu].o7 = regs->u_regs[UREG_I7]; + rp = &global_cpu_snapshot[this_cpu].reg; + + rp->tstate = regs->tstate; + rp->tpc = regs->tpc; + rp->tnpc = regs->tnpc; + rp->o7 = regs->u_regs[UREG_I7]; if (regs->tstate & TSTATE_PRIV) { struct reg_window *rw; @@ -223,17 +229,17 @@ static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, rw = (struct reg_window *) (regs->u_regs[UREG_FP] + STACK_BIAS); if (kstack_valid(tp, (unsigned long) rw)) { - global_reg_snapshot[this_cpu].i7 = rw->ins[7]; + rp->i7 = rw->ins[7]; rw = (struct reg_window *) (rw->ins[6] + STACK_BIAS); if (kstack_valid(tp, (unsigned long) rw)) - global_reg_snapshot[this_cpu].rpc = rw->ins[7]; + rp->rpc = rw->ins[7]; } } else { - global_reg_snapshot[this_cpu].i7 = 0; - global_reg_snapshot[this_cpu].rpc = 0; + rp->i7 = 0; + rp->rpc = 0; } - global_reg_snapshot[this_cpu].thread = tp; + rp->thread = tp; } /* In order to avoid hangs we do not try to synchronize with the @@ -261,9 +267,9 @@ void arch_trigger_all_cpu_backtrace(void) if (!regs) regs = tp->kregs; - spin_lock_irqsave(&global_reg_snapshot_lock, flags); + spin_lock_irqsave(&global_cpu_snapshot_lock, flags); - memset(global_reg_snapshot, 0, sizeof(global_reg_snapshot)); + memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot)); this_cpu = raw_smp_processor_id(); @@ -272,7 +278,7 @@ void arch_trigger_all_cpu_backtrace(void) smp_fetch_global_regs(); for_each_online_cpu(cpu) { - struct global_reg_snapshot *gp = &global_reg_snapshot[cpu]; + struct global_reg_snapshot *gp = &global_cpu_snapshot[cpu].reg; __global_reg_poll(gp); @@ -295,9 +301,9 @@ void arch_trigger_all_cpu_backtrace(void) } } - memset(global_reg_snapshot, 0, sizeof(global_reg_snapshot)); + memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot)); - spin_unlock_irqrestore(&global_reg_snapshot_lock, flags); + spin_unlock_irqrestore(&global_cpu_snapshot_lock, flags); } #ifdef CONFIG_MAGIC_SYSRQ @@ -309,16 +315,90 @@ static void sysrq_handle_globreg(int key) static struct sysrq_key_op sparc_globalreg_op = { .handler = sysrq_handle_globreg, - .help_msg = "Globalregs", + .help_msg = "global-regs(Y)", .action_msg = "Show Global CPU Regs", }; -static int __init sparc_globreg_init(void) +static void __global_pmu_self(int this_cpu) +{ + struct global_pmu_snapshot *pp; + int i, num; + + pp = &global_cpu_snapshot[this_cpu].pmu; + + num = 1; + if (tlb_type == hypervisor && + sun4v_chip_type >= SUN4V_CHIP_NIAGARA4) + num = 4; + + for (i = 0; i < num; i++) { + pp->pcr[i] = pcr_ops->read_pcr(i); + pp->pic[i] = pcr_ops->read_pic(i); + } +} + +static void __global_pmu_poll(struct global_pmu_snapshot *pp) +{ + int limit = 0; + + while (!pp->pcr[0] && ++limit < 100) { + barrier(); + udelay(1); + } +} + +static void pmu_snapshot_all_cpus(void) { - return register_sysrq_key('y', &sparc_globalreg_op); + unsigned long flags; + int this_cpu, cpu; + + spin_lock_irqsave(&global_cpu_snapshot_lock, flags); + + memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot)); + + this_cpu = raw_smp_processor_id(); + + __global_pmu_self(this_cpu); + + smp_fetch_global_pmu(); + + for_each_online_cpu(cpu) { + struct global_pmu_snapshot *pp = &global_cpu_snapshot[cpu].pmu; + + __global_pmu_poll(pp); + + printk("%c CPU[%3d]: PCR[%08lx:%08lx:%08lx:%08lx] PIC[%08lx:%08lx:%08lx:%08lx]\n", + (cpu == this_cpu ? '*' : ' '), cpu, + pp->pcr[0], pp->pcr[1], pp->pcr[2], pp->pcr[3], + pp->pic[0], pp->pic[1], pp->pic[2], pp->pic[3]); + } + + memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot)); + + spin_unlock_irqrestore(&global_cpu_snapshot_lock, flags); +} + +static void sysrq_handle_globpmu(int key) +{ + pmu_snapshot_all_cpus(); +} + +static struct sysrq_key_op sparc_globalpmu_op = { + .handler = sysrq_handle_globpmu, + .help_msg = "global-pmu(X)", + .action_msg = "Show Global PMU Regs", +}; + +static int __init sparc_sysrq_init(void) +{ + int ret = register_sysrq_key('y', &sparc_globalreg_op); + + if (!ret) + ret = register_sysrq_key('x', &sparc_globalpmu_op); + return ret; } -core_initcall(sparc_globreg_init); +core_initcall(sparc_sysrq_init); #endif diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index 781bcb10b8bd..d94b878577b7 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c @@ -852,6 +852,8 @@ extern unsigned long xcall_flush_tlb_mm; extern unsigned long xcall_flush_tlb_pending; extern unsigned long xcall_flush_tlb_kernel_range; extern unsigned long xcall_fetch_glob_regs; +extern unsigned long xcall_fetch_glob_pmu; +extern unsigned long xcall_fetch_glob_pmu_n4; extern unsigned long xcall_receive_signal; extern unsigned long xcall_new_mmu_context_version; #ifdef CONFIG_KGDB @@ -1000,6 +1002,15 @@ void smp_fetch_global_regs(void) smp_cross_call(&xcall_fetch_glob_regs, 0, 0, 0); } +void smp_fetch_global_pmu(void) +{ + if (tlb_type == hypervisor && + sun4v_chip_type >= SUN4V_CHIP_NIAGARA4) + smp_cross_call(&xcall_fetch_glob_pmu_n4, 0, 0, 0); + else + smp_cross_call(&xcall_fetch_glob_pmu, 0, 0, 0); +} + /* We know that the window frames of the user have been flushed * to the stack before we get here because all callers of us * are flush_tlb_*() routines, and these run after flush_cache_*() diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S index 874162a11ceb..f8e13d421fcb 100644 --- a/arch/sparc/mm/ultra.S +++ b/arch/sparc/mm/ultra.S @@ -481,8 +481,8 @@ xcall_sync_tick: .globl xcall_fetch_glob_regs xcall_fetch_glob_regs: - sethi %hi(global_reg_snapshot), %g1 - or %g1, %lo(global_reg_snapshot), %g1 + sethi %hi(global_cpu_snapshot), %g1 + or %g1, %lo(global_cpu_snapshot), %g1 __GET_CPUID(%g2) sllx %g2, 6, %g3 add %g1, %g3, %g1 @@ -509,6 +509,66 @@ xcall_fetch_glob_regs: stx %g3, [%g1 + GR_SNAP_THREAD] retry + .globl xcall_fetch_glob_pmu +xcall_fetch_glob_pmu: + sethi %hi(global_cpu_snapshot), %g1 + or %g1, %lo(global_cpu_snapshot), %g1 + __GET_CPUID(%g2) + sllx %g2, 6, %g3 + add %g1, %g3, %g1 + rd %pic, %g7 + stx %g7, [%g1 + (4 * 8)] + rd %pcr, %g7 + stx %g7, [%g1 + (0 * 8)] + retry + + .globl xcall_fetch_glob_pmu_n4 +xcall_fetch_glob_pmu_n4: + sethi %hi(global_cpu_snapshot), %g1 + or %g1, %lo(global_cpu_snapshot), %g1 + __GET_CPUID(%g2) + sllx %g2, 6, %g3 + add %g1, %g3, %g1 + + ldxa [%g0] ASI_PIC, %g7 + stx %g7, [%g1 + (4 * 8)] + mov 0x08, %g3 + ldxa [%g3] ASI_PIC, %g7 + stx %g7, [%g1 + (5 * 8)] + mov 0x10, %g3 + ldxa [%g3] ASI_PIC, %g7 + stx %g7, [%g1 + (6 * 8)] + mov 0x18, %g3 + ldxa [%g3] ASI_PIC, %g7 + stx %g7, [%g1 + (7 * 8)] + + mov %o0, %g2 + mov %o1, %g3 + mov %o5, %g7 + + mov HV_FAST_VT_GET_PERFREG, %o5 + mov 3, %o0 + ta HV_FAST_TRAP + stx %o1, [%g1 + (3 * 8)] + mov HV_FAST_VT_GET_PERFREG, %o5 + mov 2, %o0 + ta HV_FAST_TRAP + stx %o1, [%g1 + (2 * 8)] + mov HV_FAST_VT_GET_PERFREG, %o5 + mov 1, %o0 + ta HV_FAST_TRAP + stx %o1, [%g1 + (1 * 8)] + mov HV_FAST_VT_GET_PERFREG, %o5 + mov 0, %o0 + ta HV_FAST_TRAP + stx %o1, [%g1 + (0 * 8)] + + mov %g2, %o0 + mov %g3, %o1 + mov %g7, %o5 + + retry + #ifdef DCACHE_ALIASING_POSSIBLE .align 32 .globl xcall_flush_dcache_page_cheetah diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 05728894a88c..16ee6cee07da 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -452,6 +452,7 @@ static struct sysrq_key_op *sysrq_key_table[36] = { NULL, /* v */ &sysrq_showstate_blocked_op, /* w */ /* x: May be registered on ppc/powerpc for xmon */ + /* x: May be registered on sparc64 for global PMU dump */ NULL, /* x */ /* y: May be registered on sparc64 for global register dump */ NULL, /* y */ -- cgit v1.2.3-55-g7522 From 7bdce71822f471433dd3014692e9096996c7b5f0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 15 Oct 2012 18:20:52 +0200 Subject: USB: ark3116: fix NULL-pointer dereference Fix NULL-pointer dereference at release by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is NULL when release is called. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ark3116.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index cf2522c397d3..bd50a8a41a0f 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -125,9 +125,6 @@ static inline int calc_divisor(int bps) static int ark3116_attach(struct usb_serial *serial) { - struct usb_serial_port *port = serial->port[0]; - struct ark3116_private *priv; - /* make sure we have our end-points */ if ((serial->num_bulk_in == 0) || (serial->num_bulk_out == 0) || @@ -142,8 +139,15 @@ static int ark3116_attach(struct usb_serial *serial) return -EINVAL; } - priv = kzalloc(sizeof(struct ark3116_private), - GFP_KERNEL); + return 0; +} + +static int ark3116_port_probe(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + struct ark3116_private *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -198,18 +202,15 @@ static int ark3116_attach(struct usb_serial *serial) return 0; } -static void ark3116_release(struct usb_serial *serial) +static int ark3116_port_remove(struct usb_serial_port *port) { - struct usb_serial_port *port = serial->port[0]; struct ark3116_private *priv = usb_get_serial_port_data(port); /* device is closed, so URBs and DMA should be down */ - - usb_set_serial_port_data(port, NULL); - mutex_destroy(&priv->hw_lock); - kfree(priv); + + return 0; } static void ark3116_init_termios(struct tty_struct *tty) @@ -723,7 +724,8 @@ static struct usb_serial_driver ark3116_device = { .id_table = id_table, .num_ports = 1, .attach = ark3116_attach, - .release = ark3116_release, + .port_probe = ark3116_port_probe, + .port_remove = ark3116_port_remove, .set_termios = ark3116_set_termios, .init_termios = ark3116_init_termios, .ioctl = ark3116_ioctl, -- cgit v1.2.3-55-g7522 From a9556040119a63d06fd5238d47f5b683fba4178b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 15 Oct 2012 18:20:54 +0200 Subject: USB: cyberjack: fix port-data memory leak Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that the write waitqueue was initialised but never used. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cyberjack.c | 49 ++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 2a7aecc72237..4ee77dcbe690 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -55,9 +55,9 @@ #define CYBERJACK_PRODUCT_ID 0x0100 /* Function prototypes */ -static int cyberjack_startup(struct usb_serial *serial); static void cyberjack_disconnect(struct usb_serial *serial); -static void cyberjack_release(struct usb_serial *serial); +static int cyberjack_port_probe(struct usb_serial_port *port); +static int cyberjack_port_remove(struct usb_serial_port *port); static int cyberjack_open(struct tty_struct *tty, struct usb_serial_port *port); static void cyberjack_close(struct usb_serial_port *port); @@ -83,9 +83,9 @@ static struct usb_serial_driver cyberjack_device = { .description = "Reiner SCT Cyberjack USB card reader", .id_table = id_table, .num_ports = 1, - .attach = cyberjack_startup, .disconnect = cyberjack_disconnect, - .release = cyberjack_release, + .port_probe = cyberjack_port_probe, + .port_remove = cyberjack_port_remove, .open = cyberjack_open, .close = cyberjack_close, .write = cyberjack_write, @@ -107,56 +107,45 @@ struct cyberjack_private { short wrsent; /* Data already sent */ }; -/* do some startup allocations not currently performed by usb_serial_probe() */ -static int cyberjack_startup(struct usb_serial *serial) +static int cyberjack_port_probe(struct usb_serial_port *port) { struct cyberjack_private *priv; - int i; + int result; - /* allocate the private data structure */ priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL); if (!priv) return -ENOMEM; - /* set initial values */ spin_lock_init(&priv->lock); priv->rdtodo = 0; priv->wrfilled = 0; priv->wrsent = 0; - usb_set_serial_port_data(serial->port[0], priv); - init_waitqueue_head(&serial->port[0]->write_wait); + usb_set_serial_port_data(port, priv); - for (i = 0; i < serial->num_ports; ++i) { - int result; - result = usb_submit_urb(serial->port[i]->interrupt_in_urb, - GFP_KERNEL); - if (result) - dev_err(&serial->dev->dev, - "usb_submit_urb(read int) failed\n"); - dev_dbg(&serial->dev->dev, "%s - usb_submit_urb(int urb)\n", - __func__); - } + result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); + if (result) + dev_err(&port->dev, "usb_submit_urb(read int) failed\n"); return 0; } -static void cyberjack_disconnect(struct usb_serial *serial) +static int cyberjack_port_remove(struct usb_serial_port *port) { - int i; + struct cyberjack_private *priv; - for (i = 0; i < serial->num_ports; ++i) - usb_kill_urb(serial->port[i]->interrupt_in_urb); + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } -static void cyberjack_release(struct usb_serial *serial) +static void cyberjack_disconnect(struct usb_serial *serial) { int i; - for (i = 0; i < serial->num_ports; ++i) { - /* My special items, the standard routines free my urbs */ - kfree(usb_get_serial_port_data(serial->port[i])); - } + for (i = 0; i < serial->num_ports; ++i) + usb_kill_urb(serial->port[i]->interrupt_in_urb); } static int cyberjack_open(struct tty_struct *tty, -- cgit v1.2.3-55-g7522 From fa919751a2d26a88140fc5810124dd81644efe51 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 15 Oct 2012 18:20:53 +0200 Subject: USB: belkin_sa: fix port-data memory leak Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that the write waitqueue was initialised but never used. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/belkin_sa.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index 99449424193f..ea29556f0d72 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -45,8 +45,8 @@ #define DRIVER_DESC "USB Belkin Serial converter driver" /* function prototypes for a Belkin USB Serial Adapter F5U103 */ -static int belkin_sa_startup(struct usb_serial *serial); -static void belkin_sa_release(struct usb_serial *serial); +static int belkin_sa_port_probe(struct usb_serial_port *port); +static int belkin_sa_port_remove(struct usb_serial_port *port); static int belkin_sa_open(struct tty_struct *tty, struct usb_serial_port *port); static void belkin_sa_close(struct usb_serial_port *port); @@ -88,8 +88,8 @@ static struct usb_serial_driver belkin_device = { .break_ctl = belkin_sa_break_ctl, .tiocmget = belkin_sa_tiocmget, .tiocmset = belkin_sa_tiocmset, - .attach = belkin_sa_startup, - .release = belkin_sa_release, + .port_probe = belkin_sa_port_probe, + .port_remove = belkin_sa_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -118,17 +118,15 @@ struct belkin_sa_private { (c), BELKIN_SA_SET_REQUEST_TYPE, \ (v), 0, NULL, 0, WDR_TIMEOUT) -/* do some startup allocations not currently performed by usb_serial_probe() */ -static int belkin_sa_startup(struct usb_serial *serial) +static int belkin_sa_port_probe(struct usb_serial_port *port) { - struct usb_device *dev = serial->dev; + struct usb_device *dev = port->serial->dev; struct belkin_sa_private *priv; - /* allocate the private data structure */ priv = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL); if (!priv) - return -1; /* error */ - /* set initial values for control structures */ + return -ENOMEM; + spin_lock_init(&priv->lock); priv->control_state = 0; priv->last_lsr = 0; @@ -140,18 +138,19 @@ static int belkin_sa_startup(struct usb_serial *serial) le16_to_cpu(dev->descriptor.bcdDevice), priv->bad_flow_control); - init_waitqueue_head(&serial->port[0]->write_wait); - usb_set_serial_port_data(serial->port[0], priv); + usb_set_serial_port_data(port, priv); return 0; } -static void belkin_sa_release(struct usb_serial *serial) +static int belkin_sa_port_remove(struct usb_serial_port *port) { - int i; + struct belkin_sa_private *priv; - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static int belkin_sa_open(struct tty_struct *tty, -- cgit v1.2.3-55-g7522 From 4295fe7791a1b20c90cbaaa6f23f2fb94218b8a7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 15 Oct 2012 15:47:20 +0200 Subject: USB: cp210x: fix port-data memory leak Fix port data memory leak by replacing port private data with serial private data. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release. The private data is used to store the control interface number, but as this is the same for all ports on an interface it should be stored as usb-serial data anyway. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 28af5acc3360..eb033fc92a15 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -162,7 +162,7 @@ static const struct usb_device_id id_table[] = { MODULE_DEVICE_TABLE(usb, id_table); -struct cp210x_port_private { +struct cp210x_serial_private { __u8 bInterfaceNumber; }; @@ -276,7 +276,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request, unsigned int *data, int size) { struct usb_serial *serial = port->serial; - struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); + struct cp210x_serial_private *spriv = usb_get_serial_data(serial); __le32 *buf; int result, i, length; @@ -292,7 +292,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request, /* Issue the request, attempting to read 'size' bytes */ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), request, REQTYPE_INTERFACE_TO_HOST, 0x0000, - port_priv->bInterfaceNumber, buf, size, + spriv->bInterfaceNumber, buf, size, USB_CTRL_GET_TIMEOUT); /* Convert data into an array of integers */ @@ -323,7 +323,7 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, unsigned int *data, int size) { struct usb_serial *serial = port->serial; - struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); + struct cp210x_serial_private *spriv = usb_get_serial_data(serial); __le32 *buf; int result, i, length; @@ -345,13 +345,13 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), request, REQTYPE_HOST_TO_INTERFACE, 0x0000, - port_priv->bInterfaceNumber, buf, size, + spriv->bInterfaceNumber, buf, size, USB_CTRL_SET_TIMEOUT); } else { result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), request, REQTYPE_HOST_TO_INTERFACE, data[0], - port_priv->bInterfaceNumber, NULL, 0, + spriv->bInterfaceNumber, NULL, 0, USB_CTRL_SET_TIMEOUT); } @@ -845,36 +845,30 @@ static void cp210x_break_ctl (struct tty_struct *tty, int break_state) static int cp210x_startup(struct usb_serial *serial) { - struct cp210x_port_private *port_priv; - int i; + struct usb_host_interface *cur_altsetting; + struct cp210x_serial_private *spriv; /* cp210x buffers behave strangely unless device is reset */ usb_reset_device(serial->dev); - for (i = 0; i < serial->num_ports; i++) { - port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); - if (!port_priv) - return -ENOMEM; + spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); + if (!spriv) + return -ENOMEM; - port_priv->bInterfaceNumber = - serial->interface->cur_altsetting->desc.bInterfaceNumber; + cur_altsetting = serial->interface->cur_altsetting; + spriv->bInterfaceNumber = cur_altsetting->desc.bInterfaceNumber; - usb_set_serial_port_data(serial->port[i], port_priv); - } + usb_set_serial_data(serial, spriv); return 0; } static void cp210x_release(struct usb_serial *serial) { - struct cp210x_port_private *port_priv; - int i; + struct cp210x_serial_private *spriv; - for (i = 0; i < serial->num_ports; i++) { - port_priv = usb_get_serial_port_data(serial->port[i]); - kfree(port_priv); - usb_set_serial_port_data(serial->port[i], NULL); - } + spriv = usb_get_serial_data(serial); + kfree(spriv); } module_usb_serial_driver(serial_drivers, id_table); -- cgit v1.2.3-55-g7522 From 8bf769eb5f6efc33f95088850f33fcc05d28b508 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 15 Oct 2012 15:47:21 +0200 Subject: USB: pl2303: fix port-data memory leak Fix port-data memory leak by allocating and freeing port data in port_probe/remove rather than in attach/release, and by introducing serial private data to store the device type which is interface rather than port specific. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 90 +++++++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 892ebdc7a364..600241901361 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -133,12 +133,15 @@ enum pl2303_type { HX, /* HX version of the pl2303 chip */ }; +struct pl2303_serial_private { + enum pl2303_type type; +}; + struct pl2303_private { spinlock_t lock; wait_queue_head_t delta_msr_wait; u8 line_control; u8 line_status; - enum pl2303_type type; }; static int pl2303_vendor_read(__u16 value, __u16 index, @@ -167,14 +170,19 @@ static int pl2303_vendor_write(__u16 value, __u16 index, static int pl2303_startup(struct usb_serial *serial) { - struct pl2303_private *priv; + struct pl2303_serial_private *spriv; enum pl2303_type type = type_0; unsigned char *buf; - int i; + + spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); + if (!spriv) + return -ENOMEM; buf = kmalloc(10, GFP_KERNEL); - if (buf == NULL) + if (!buf) { + kfree(spriv); return -ENOMEM; + } if (serial->dev->descriptor.bDeviceClass == 0x02) type = type_0; @@ -186,15 +194,8 @@ static int pl2303_startup(struct usb_serial *serial) type = type_1; dev_dbg(&serial->interface->dev, "device type: %d\n", type); - for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL); - if (!priv) - goto cleanup; - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->delta_msr_wait); - priv->type = type; - usb_set_serial_port_data(serial->port[i], priv); - } + spriv->type = type; + usb_set_serial_data(serial, spriv); pl2303_vendor_read(0x8484, 0, serial, buf); pl2303_vendor_write(0x0404, 0, serial); @@ -213,15 +214,40 @@ static int pl2303_startup(struct usb_serial *serial) kfree(buf); return 0; +} -cleanup: - kfree(buf); - for (--i; i >= 0; --i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i], NULL); - } - return -ENOMEM; +static void pl2303_release(struct usb_serial *serial) +{ + struct pl2303_serial_private *spriv; + + spriv = usb_get_serial_data(serial); + kfree(spriv); +} + +static int pl2303_port_probe(struct usb_serial_port *port) +{ + struct pl2303_private *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->delta_msr_wait); + + usb_set_serial_port_data(port, priv); + + return 0; +} + +static int pl2303_port_remove(struct usb_serial_port *port) +{ + struct pl2303_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static int set_control_lines(struct usb_device *dev, u8 value) @@ -240,6 +266,7 @@ static void pl2303_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; + struct pl2303_serial_private *spriv = usb_get_serial_data(serial); struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int cflag; @@ -323,7 +350,7 @@ static void pl2303_set_termios(struct tty_struct *tty, } if (baud > 1228800) { /* type_0, type_1 only support up to 1228800 baud */ - if (priv->type != HX) + if (spriv->type != HX) baud = 1228800; else if (baud > 6000000) baud = 6000000; @@ -426,7 +453,7 @@ static void pl2303_set_termios(struct tty_struct *tty, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); if (cflag & CRTSCTS) { - if (priv->type == HX) + if (spriv->type == HX) pl2303_vendor_write(0x0, 0x61, serial); else pl2303_vendor_write(0x0, 0x41, serial); @@ -468,10 +495,10 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port) { struct ktermios tmp_termios; struct usb_serial *serial = port->serial; - struct pl2303_private *priv = usb_get_serial_port_data(port); + struct pl2303_serial_private *spriv = usb_get_serial_data(serial); int result; - if (priv->type != HX) { + if (spriv->type != HX) { usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); } else { @@ -655,17 +682,6 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state) dev_err(&port->dev, "error sending break = %d\n", result); } -static void pl2303_release(struct usb_serial *serial) -{ - int i; - struct pl2303_private *priv; - - for (i = 0; i < serial->num_ports; ++i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - } -} - static void pl2303_update_line_status(struct usb_serial_port *port, unsigned char *data, unsigned int actual_length) @@ -827,6 +843,8 @@ static struct usb_serial_driver pl2303_device = { .read_int_callback = pl2303_read_int_callback, .attach = pl2303_startup, .release = pl2303_release, + .port_probe = pl2303_port_probe, + .port_remove = pl2303_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { -- cgit v1.2.3-55-g7522 From db5c8b524444d4fc6b1f32d368a50a3729e50002 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 10 Oct 2012 14:10:21 -0400 Subject: USB: fix port probing and removal in garmin_gps This patch (as1615) fixes a bug in the Garmin USB serial driver. It uses attach, disconnect, and release routines to carry out actions that should be handled by port_probe and port_remove routines, because they access port-specific data. The bug causes an oops when the device in unplugged, because the private data for each port structure now gets erased when the port is unbound from the driver, resulting in a null-pointer dereference. Signed-off-by: Alan Stern Reported--by: Markus Schauler Tested-by: Markus Schauler Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/garmin_gps.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 3ee92648c02d..203358d7e7bc 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -1405,11 +1405,10 @@ static void timeout_handler(unsigned long data) -static int garmin_attach(struct usb_serial *serial) +static int garmin_port_probe(struct usb_serial_port *port) { - int status = 0; - struct usb_serial_port *port = serial->port[0]; - struct garmin_data *garmin_data_p = NULL; + int status; + struct garmin_data *garmin_data_p; garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL); if (garmin_data_p == NULL) { @@ -1434,22 +1433,14 @@ static int garmin_attach(struct usb_serial *serial) } -static void garmin_disconnect(struct usb_serial *serial) +static int garmin_port_remove(struct usb_serial_port *port) { - struct usb_serial_port *port = serial->port[0]; struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); usb_kill_urb(port->interrupt_in_urb); del_timer_sync(&garmin_data_p->timer); -} - - -static void garmin_release(struct usb_serial *serial) -{ - struct usb_serial_port *port = serial->port[0]; - struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); - kfree(garmin_data_p); + return 0; } @@ -1466,9 +1457,8 @@ static struct usb_serial_driver garmin_device = { .close = garmin_close, .throttle = garmin_throttle, .unthrottle = garmin_unthrottle, - .attach = garmin_attach, - .disconnect = garmin_disconnect, - .release = garmin_release, + .port_probe = garmin_port_probe, + .port_remove = garmin_port_remove, .write = garmin_write, .write_room = garmin_write_room, .write_bulk_callback = garmin_write_bulk_callback, -- cgit v1.2.3-55-g7522 From a48221a26e4914b7e2d8a1749b6115212bac8bee Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Tue, 16 Oct 2012 15:24:01 +0200 Subject: gpio-74x164: Fix buffer allocation size The new registers handling in the gpio-74x164 driver allocates chip->registers * 8 bytes where only one byte per register is necessary. This patch fixes this. Signed-off-by: Roland Stigge Signed-off-by: Linus Walleij --- drivers/gpio/gpio-74x164.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index ed3e55161bdc..f05e54258ffb 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -153,7 +153,7 @@ static int __devinit gen_74x164_probe(struct spi_device *spi) } chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers; - chip->buffer = devm_kzalloc(&spi->dev, chip->gpio_chip.ngpio, GFP_KERNEL); + chip->buffer = devm_kzalloc(&spi->dev, chip->registers, GFP_KERNEL); if (!chip->buffer) { ret = -ENOMEM; goto exit_destroy; -- cgit v1.2.3-55-g7522 From 55462cf30ad9768fff6a6d36db21879146a39bdf Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sun, 14 Oct 2012 04:30:56 +0000 Subject: vlan: fix bond/team enslave of vlan challenged slave/port In vlan_uses_dev() check for number of vlan devs rather than existence of vlan_info. The reason is that vlan id 0 is there without appropriate vlan dev on it by default which prevented from enslaving vlan challenged dev. Reported-by: Jon Stanley Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 2 +- net/8021q/vlan_core.c | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index b721902bb6b4..b2530b002125 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1519,7 +1519,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) /* no need to lock since we're protected by rtnl_lock */ if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) { pr_debug("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name); - if (bond_vlan_used(bond)) { + if (vlan_uses_dev(bond_dev)) { pr_err("%s: Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n", bond_dev->name, slave_dev->name, bond_dev->name); return -EPERM; diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index fbbf1fa00940..65e06abe023f 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -366,6 +366,13 @@ EXPORT_SYMBOL(vlan_vids_del_by_dev); bool vlan_uses_dev(const struct net_device *dev) { - return rtnl_dereference(dev->vlan_info) ? true : false; + struct vlan_info *vlan_info; + + ASSERT_RTNL(); + + vlan_info = rtnl_dereference(dev->vlan_info); + if (!vlan_info) + return false; + return vlan_info->grp.nr_vlan_devs ? true : false; } EXPORT_SYMBOL(vlan_uses_dev); -- cgit v1.2.3-55-g7522 From 1c8161a8249fa32408e3c073f992141c9d257332 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Mon, 15 Oct 2012 19:21:17 +0000 Subject: smsgiucv: reestablish IUCV path after resume smsg_pm_restore_thaw() uses wrong checking before reconnecting the IUCV path to *MSG. It is corrected with this patch. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/smsgiucv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c index 207b7d742443..d8f990b6b332 100644 --- a/drivers/s390/net/smsgiucv.c +++ b/drivers/s390/net/smsgiucv.c @@ -157,7 +157,7 @@ static int smsg_pm_restore_thaw(struct device *dev) #ifdef CONFIG_PM_DEBUG printk(KERN_WARNING "smsg_pm_restore_thaw\n"); #endif - if (smsg_path && iucv_path_connected) { + if (smsg_path && !iucv_path_connected) { memset(smsg_path, 0, sizeof(*smsg_path)); smsg_path->msglim = 255; smsg_path->flags = 0; -- cgit v1.2.3-55-g7522 From 2efaf5ff7fa2d45debc27cd9b3d235df61d641fb Mon Sep 17 00:00:00 2001 From: Stefan Raspl Date: Mon, 15 Oct 2012 19:21:18 +0000 Subject: qeth: fix deadlock between recovery and bonding driver The recovery thread, when failing, tears down the respective interface. To do so, it needs to obtain the rtnl lock first, as the interface configuration is changed. If another process tries to modify an interface setting at the same time, that process can obtain the rtnl lock first, but the respective callback in the qeth driver will block until recovery has completed - which cannot happen since the calling process already obtained it. In one particular case, the bonding driver acquired the rtnl lock to modify the card's MAC address, while the recovery failed at the same time due to the card being removed. Hence qeth_l2_set_mac_address (implicitly holding the rtnl lock) was waiting on qeth_l2_recover, which deadlocked when waiting on the rtnl lock. This patch uses rtnl_trylock instead of rtnl_lock in the recovery thread. If the lock cannot be obtained, the interface will be left up, but the card state remains in CARD_STATE_RECOVER, which will prevent any further activities on the card. Signed-off-by: Stefan Raspl Signed-off-by: Frank Blaschka Reviewed-by: Ursula Braun Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l2_main.c | 11 ++++++----- drivers/s390/net/qeth_l3_main.c | 11 ++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 2db409330c21..e67e0258aec5 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -1141,11 +1141,12 @@ static int qeth_l2_recover(void *ptr) dev_info(&card->gdev->dev, "Device successfully recovered!\n"); else { - rtnl_lock(); - dev_close(card->dev); - rtnl_unlock(); - dev_warn(&card->gdev->dev, "The qeth device driver " - "failed to recover an error on the device\n"); + if (rtnl_trylock()) { + dev_close(card->dev); + rtnl_unlock(); + dev_warn(&card->gdev->dev, "The qeth device driver " + "failed to recover an error on the device\n"); + } } qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 4cd310cb5bdf..5ba390658498 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -3510,11 +3510,12 @@ static int qeth_l3_recover(void *ptr) dev_info(&card->gdev->dev, "Device successfully recovered!\n"); else { - rtnl_lock(); - dev_close(card->dev); - rtnl_unlock(); - dev_warn(&card->gdev->dev, "The qeth device driver " - "failed to recover an error on the device\n"); + if (rtnl_trylock()) { + dev_close(card->dev); + rtnl_unlock(); + dev_warn(&card->gdev->dev, "The qeth device driver " + "failed to recover an error on the device\n"); + } } qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); -- cgit v1.2.3-55-g7522 From 2384d6aa079de7c16c7877220d3cd4c6f4f50767 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Tue, 16 Oct 2012 01:28:27 +0000 Subject: bnx2x: fix handling mf storage modes Since commit a3348722 AFEX FCoE function is continuously reset. The patch prevents the resetting and removes debug print to stop garbaging syslog. Signed-off-by: Dmitry Kravkov Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 10 +++++++--- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 24220992413f..4833b6a9031c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -2957,9 +2957,13 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) skb_shinfo(skb)->nr_frags + BDS_PER_TX_PKT + NEXT_CNT_PER_TX_PKT(MAX_BDS_PER_TX_PKT))) { - bnx2x_fp_qstats(bp, txdata->parent_fp)->driver_xoff++; - netif_tx_stop_queue(txq); - BNX2X_ERR("BUG! Tx ring full when queue awake!\n"); + /* Handle special storage cases separately */ + if (txdata->tx_ring_size != 0) { + BNX2X_ERR("BUG! Tx ring full when queue awake!\n"); + bnx2x_fp_qstats(bp, txdata->parent_fp)->driver_xoff++; + netif_tx_stop_queue(txq); + } + return NETDEV_TX_BUSY; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 71971a161bd1..614981c02264 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -126,7 +126,7 @@ static inline int bnx2x_exe_queue_add(struct bnx2x *bp, /* Check if this request is ok */ rc = o->validate(bp, o->owner, elem); if (rc) { - BNX2X_ERR("Preamble failed: %d\n", rc); + DP(BNX2X_MSG_SP, "Preamble failed: %d\n", rc); goto free_and_exit; } } -- cgit v1.2.3-55-g7522 From 4033741ff9f727fbf5efb9337c826703534d49b7 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 16 Oct 2012 15:53:37 -0500 Subject: ACPI: Reorder IPMI driver before any other ACPI drivers Drivers may make calls that require the ACPI IPMI driver to have been initialised already, so make sure that it appears earlier in the build order. Signed-off-by: Matthew Garrett Signed-off-by: Corey Minyard Signed-off-by: Linus Torvalds --- drivers/acpi/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 47199e2a9130..82422fe90f81 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -47,6 +47,10 @@ acpi-y += video_detect.o endif # These are (potentially) separate modules + +# IPMI may be used by other drivers, so it has to initialise before them +obj-$(CONFIG_ACPI_IPMI) += acpi_ipmi.o + obj-$(CONFIG_ACPI_AC) += ac.o obj-$(CONFIG_ACPI_BUTTON) += button.o obj-$(CONFIG_ACPI_FAN) += fan.o @@ -70,6 +74,5 @@ processor-y += processor_idle.o processor_thermal.o processor-$(CONFIG_CPU_FREQ) += processor_perflib.o obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o -obj-$(CONFIG_ACPI_IPMI) += acpi_ipmi.o obj-$(CONFIG_ACPI_APEI) += apei/ -- cgit v1.2.3-55-g7522 From 061475b65c126454aaaaddcbd40e7118424fc860 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 16 Oct 2012 15:53:38 -0500 Subject: IPMI: Change link order IPMI must be initialised before ACPI in order to ensure that any IPMI services are available before ACPI driver initialisation attempts to use any IPMI operation regions. Signed-off-by: Matthew Garrett Signed-off-by: Corey Minyard Signed-off-by: Linus Torvalds --- drivers/Makefile | 4 ++++ drivers/char/Makefile | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/Makefile b/drivers/Makefile index 03da5b663aef..a16a8d001ae0 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -17,6 +17,10 @@ obj-$(CONFIG_PARISC) += parisc/ obj-$(CONFIG_RAPIDIO) += rapidio/ obj-y += video/ obj-y += idle/ + +# IPMI must come before ACPI in order to provide IPMI opregion support +obj-$(CONFIG_IPMI_HANDLER) += char/ipmi/ + obj-$(CONFIG_ACPI) += acpi/ obj-$(CONFIG_SFI) += sfi/ # PnP must come after ACPI since it will eventually need to check if acpi diff --git a/drivers/char/Makefile b/drivers/char/Makefile index d0b27a39f1d4..7ff1d0d208a7 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -52,7 +52,6 @@ obj-$(CONFIG_TELCLOCK) += tlclk.o obj-$(CONFIG_MWAVE) += mwave/ obj-$(CONFIG_AGP) += agp/ obj-$(CONFIG_PCMCIA) += pcmcia/ -obj-$(CONFIG_IPMI_HANDLER) += ipmi/ obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o obj-$(CONFIG_TCG_TPM) += tpm/ -- cgit v1.2.3-55-g7522 From 9ebca93bf3b350910c66516cbec68899eeddfd8e Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 16 Oct 2012 15:53:39 -0500 Subject: IPMI: Fix some uninitialized warning There was a spot where the compiler couldn't tell some variables would be set. So initialize them to make the warning go away. Signed-off-by: Corey Minyard Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 2c29942b1326..a0c84bb30856 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -1880,7 +1880,7 @@ int ipmi_request_supply_msgs(ipmi_user_t user, struct ipmi_recv_msg *supplied_recv, int priority) { - unsigned char saddr, lun; + unsigned char saddr = 0, lun = 0; int rv; if (!user) -- cgit v1.2.3-55-g7522 From a6c16c2803089f032f86fe15e952176c0713d6e3 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 16 Oct 2012 15:53:40 -0500 Subject: IPMI: Detect register spacing on PCI interfaces The IPMI spec defines a way to detect register spacing for PCI interfaces, so implement it. Signed-off-by: Steven Hsieh Signed-off-by: Corey Minyard Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 83f85cf7fb1b..32a6c7e256bd 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -2424,6 +2424,38 @@ static void ipmi_pci_cleanup(struct smi_info *info) pci_disable_device(pdev); } +static int __devinit ipmi_pci_probe_regspacing(struct smi_info *info) +{ + if (info->si_type == SI_KCS) { + unsigned char status; + int regspacing; + + info->io.regsize = DEFAULT_REGSIZE; + info->io.regshift = 0; + info->io_size = 2; + info->handlers = &kcs_smi_handlers; + + /* detect 1, 4, 16byte spacing */ + for (regspacing = DEFAULT_REGSPACING; regspacing <= 16;) { + info->io.regspacing = regspacing; + if (info->io_setup(info)) { + dev_err(info->dev, + "Could not setup I/O space\n"); + return DEFAULT_REGSPACING; + } + /* write invalid cmd */ + info->io.outputb(&info->io, 1, 0x10); + /* read status back */ + status = info->io.inputb(&info->io, 1); + info->io_cleanup(info); + if (status) + return regspacing; + regspacing *= 4; + } + } + return DEFAULT_REGSPACING; +} + static int __devinit ipmi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -2476,8 +2508,8 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, } info->io.addr_data = pci_resource_start(pdev, 0); - info->io.regspacing = DEFAULT_REGSPACING; - info->io.regsize = DEFAULT_REGSPACING; + info->io.regspacing = ipmi_pci_probe_regspacing(info); + info->io.regsize = DEFAULT_REGSIZE; info->io.regshift = 0; info->irq = pdev->irq; -- cgit v1.2.3-55-g7522 From d856f1eb56ae3d935fb502441aa37b650aeba683 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 14 Oct 2012 04:32:55 +0200 Subject: spi: mxs: Assign message status after transfer finished In the current code implementing the MXS SPI driver, every transferred message had assigned status = 0, which is not correct. Properly assign status returned from the I/O functions. Signed-off-by: Marek Vasut Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index edf1360ab09e..5a63bcd7a23d 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -480,7 +480,7 @@ static int mxs_spi_transfer_one(struct spi_master *master, first = last = 0; } - m->status = 0; + m->status = status; spi_finalize_current_message(master); return status; -- cgit v1.2.3-55-g7522 From 44968466cfb969f960dbe422bbc785117f497729 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 14 Oct 2012 04:32:56 +0200 Subject: spi: mxs: Terminate DMA in case of DMA timeout In case the SPI DMA times out, the DMA might still be in some kind of inconsistent state. Issue dmaengine_terminate_all() on the particular channel to kill off all operations before continuing. Signed-off-by: Marek Vasut Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index 5a63bcd7a23d..86dd04d6bc87 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -323,6 +323,7 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, if (!ret) { dev_err(ssp->dev, "DMA transfer timeout\n"); ret = -ETIMEDOUT; + dmaengine_terminate_all(ssp->dmach); goto err_vmalloc; } -- cgit v1.2.3-55-g7522 From 0243c53634987ce7a3d1e39ae55c17800d9436c8 Mon Sep 17 00:00:00 2001 From: Shimoda, Yoshihiro Date: Thu, 2 Aug 2012 17:17:33 +0900 Subject: spi: spi-rspi: fix build error for the latest shdma driver Because the latest shdma driver changed, it caused build error in the spi-rspi driver. This patch fixed the build error. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 56 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 4894bde4bbff..30faf6d4ab91 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -147,8 +147,6 @@ struct rspi_data { unsigned char spsr; /* for dmaengine */ - struct sh_dmae_slave dma_tx; - struct sh_dmae_slave dma_rx; struct dma_chan *chan_tx; struct dma_chan *chan_rx; int irq; @@ -663,20 +661,16 @@ static irqreturn_t rspi_irq(int irq, void *_sr) return ret; } -static bool rspi_filter(struct dma_chan *chan, void *filter_param) -{ - chan->private = filter_param; - return true; -} - -static void __devinit rspi_request_dma(struct rspi_data *rspi, - struct platform_device *pdev) +static int __devinit rspi_request_dma(struct rspi_data *rspi, + struct platform_device *pdev) { struct rspi_plat_data *rspi_pd = pdev->dev.platform_data; dma_cap_mask_t mask; + struct dma_slave_config cfg; + int ret; if (!rspi_pd) - return; + return 0; /* The driver assumes no error. */ rspi->dma_width_16bit = rspi_pd->dma_width_16bit; @@ -684,21 +678,35 @@ static void __devinit rspi_request_dma(struct rspi_data *rspi, if (rspi_pd->dma_rx_id && rspi_pd->dma_tx_id) { dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - rspi->dma_rx.slave_id = rspi_pd->dma_rx_id; - rspi->chan_rx = dma_request_channel(mask, rspi_filter, - &rspi->dma_rx); - if (rspi->chan_rx) - dev_info(&pdev->dev, "Use DMA when rx.\n"); + rspi->chan_rx = dma_request_channel(mask, shdma_chan_filter, + (void *)rspi_pd->dma_rx_id); + if (rspi->chan_rx) { + cfg.slave_id = rspi_pd->dma_rx_id; + cfg.direction = DMA_DEV_TO_MEM; + ret = dmaengine_slave_config(rspi->chan_rx, &cfg); + if (!ret) + dev_info(&pdev->dev, "Use DMA when rx.\n"); + else + return ret; + } } if (rspi_pd->dma_tx_id) { dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - rspi->dma_tx.slave_id = rspi_pd->dma_tx_id; - rspi->chan_tx = dma_request_channel(mask, rspi_filter, - &rspi->dma_tx); - if (rspi->chan_tx) - dev_info(&pdev->dev, "Use DMA when tx\n"); + rspi->chan_tx = dma_request_channel(mask, shdma_chan_filter, + (void *)rspi_pd->dma_tx_id); + if (rspi->chan_tx) { + cfg.slave_id = rspi_pd->dma_tx_id; + cfg.direction = DMA_MEM_TO_DEV; + ret = dmaengine_slave_config(rspi->chan_tx, &cfg); + if (!ret) + dev_info(&pdev->dev, "Use DMA when tx\n"); + else + return ret; + } } + + return 0; } static void __devexit rspi_release_dma(struct rspi_data *rspi) @@ -788,7 +796,11 @@ static int __devinit rspi_probe(struct platform_device *pdev) } rspi->irq = irq; - rspi_request_dma(rspi, pdev); + ret = rspi_request_dma(rspi, pdev); + if (ret < 0) { + dev_err(&pdev->dev, "rspi_request_dma failed.\n"); + goto error4; + } ret = spi_register_master(master); if (ret < 0) { -- cgit v1.2.3-55-g7522 From a7c2e1aad6c846f316641bbaa54cf999aeaa7ebc Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 17 Oct 2012 11:17:16 +0200 Subject: drm/i915: shut up spurious WARN in the gtt fault handler -ENOSPC can happen if userspace is being simplistic and tries to map a too big object. To aid further spurious WARN debugging, also print out the error code. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=56017 Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index bb941f8cd556..45888d2ed534 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1408,8 +1408,10 @@ out: return VM_FAULT_NOPAGE; case -ENOMEM: return VM_FAULT_OOM; + case -ENOSPC: + return VM_FAULT_SIGBUS; default: - WARN_ON_ONCE(ret); + WARN_ONCE(ret, "unhandled error in i915_gem_fault: %i\n", ret); return VM_FAULT_SIGBUS; } } -- cgit v1.2.3-55-g7522 From 5784ee4dcbb896f5367855540b264e21a0c33854 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Mon, 15 Oct 2012 15:50:25 +0800 Subject: regmap: select REGMAP if REGMAP_MMIO and REGMAP_IRQ enabled The regmap_mmio and regmap_irq depend on regmap core, if not select, we may not compile regmap core and meet compiling errors as follows if REGMAP_MMIO is selected by client drivers: drivers/mfd/syscon.c:94:15: error: variable 'syscon_regmap_config' has initializer but incomplete type drivers/mfd/syscon.c:95:2: error: unknown field 'reg_bits' specified in initializer drivers/mfd/syscon.c:95:2: warning: excess elements in struct initializer [enabled by default] drivers/mfd/syscon.c:95:2: warning: (near initialization for 'syscon_regmap_config') [enabled by default] drivers/mfd/syscon.c:96:2: error: unknown field 'val_bits' specified in initializer drivers/mfd/syscon.c:96:2: warning: excess elements in struct initializer [enabled by default] drivers/mfd/syscon.c:96:2: warning: (near initialization for 'syscon_regmap_config') [enabled by default] drivers/mfd/syscon.c:97:2: error: unknown field 'reg_stride' specified in initializer drivers/mfd/syscon.c:97:2: warning: excess elements in struct initializer [enabled by default] drivers/mfd/syscon.c:97:2: warning: (near initialization for 'syscon_regmap_config') [enabled by default] drivers/mfd/syscon.c: In function 'syscon_probe': drivers/mfd/syscon.c:124:2: error: invalid use of undefined type 'struct regmap_config' drivers/mfd/syscon.c:125:2: error: implicit declaration of function 'devm_regmap_init_mmio' [-Werror=implicit-function-declaration] drivers/mfd/syscon.c:125:17: warning: assignment makes pointer from integer without a cast [enabled by default] cc1: some warnings being treated as errors drivers/mfd/Kconfig: config MFD_SYSCON bool "System Controller Register R/W Based on Regmap" depends on OF select REGMAP_MMIO help Select this option to enable accessing system control registers via regmap. Signed-off-by: Dong Aisheng Signed-off-by: Mark Brown --- drivers/base/regmap/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig index 6be390bd8bd1..f0d30543fcce 100644 --- a/drivers/base/regmap/Kconfig +++ b/drivers/base/regmap/Kconfig @@ -3,7 +3,7 @@ # subsystems should select the appropriate symbols. config REGMAP - default y if (REGMAP_I2C || REGMAP_SPI) + default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_MMIO || REGMAP_IRQ) select LZO_COMPRESS select LZO_DECOMPRESS select IRQ_DOMAIN if REGMAP_IRQ -- cgit v1.2.3-55-g7522 From c10356b9846b13651a8a24c3a31e029ffe6eafd9 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 30 Apr 2012 16:31:27 +0000 Subject: spi/s3c64xx: use correct dma_transfer_direction type There is a subtle difference between dma_transfer_direction and dma_data_direction: the former is used by the dmaengine framework, while the latter is used by the dma-mapping API. Although the purpose is comparable, the actual values are different and must not be mixed. In this case, the driver just wants to use dma_transfer_direction. Without this patch, building s3c6400_defconfig results in: drivers/spi/spi-s3c64xx.c: In function 's3c64xx_spi_dmacb': drivers/spi/spi-s3c64xx.c:239:21: warning: comparison between 'enum dma_data_direction' and 'enum dma_transfer_direction' [-Wenum-compare] As pointed out by Kukjin Kim, this also changes the use of constants from DMA_FROM_DEVICE/DMA_TO_DEVICE to DMA_DEV_TO_MEM/DMA_MEM_TO_DEV. Signed-off-by: Arnd Bergmann Acked-by: Kukjin Kim Cc: Ben Dooks Cc: Grant Likely Cc: linux-arm-kernel@lists.infradead.org Cc: linux-samsung-soc@vger.kernel.org Cc: spi-devel-general@lists.sourceforge.net --- drivers/spi/spi-s3c64xx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index d1c8441f638c..cd43b4b985a5 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -132,7 +132,7 @@ struct s3c64xx_spi_dma_data { unsigned ch; - enum dma_data_direction direction; + enum dma_transfer_direction direction; enum dma_ch dmach; struct property *dma_prop; }; @@ -1065,11 +1065,11 @@ static int __devinit s3c64xx_spi_get_dmares( if (tx) { dma_data = &sdd->tx_dma; - dma_data->direction = DMA_TO_DEVICE; + dma_data->direction = DMA_MEM_TO_DEV; chan_str = "tx"; } else { dma_data = &sdd->rx_dma; - dma_data->direction = DMA_FROM_DEVICE; + dma_data->direction = DMA_DEV_TO_MEM; chan_str = "rx"; } -- cgit v1.2.3-55-g7522 From 7cf8c9f7810ec1b9feaaa7914aaec4fc73c0c5d5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 30 Sep 2012 16:23:27 +0800 Subject: gpio: mvebu: Add missing breaks in mvebu_gpio_irq_set_type Signed-off-by: Axel Lin Acked-by: Andrew Lunn Acked-by: Thomas Petazzoni Acked-by: Linus Walleij Signed-off-by: Jason Cooper --- drivers/gpio/gpio-mvebu.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 902af437eaf2..7a874129e5d8 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -381,11 +381,13 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type) u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); u &= ~(1 << pin); writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip)); + break; case IRQ_TYPE_EDGE_FALLING: case IRQ_TYPE_LEVEL_LOW: u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); u |= 1 << pin; writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip)); + break; case IRQ_TYPE_EDGE_BOTH: { u32 v; @@ -401,6 +403,7 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type) else u &= ~(1 << pin); /* rising */ writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip)); + break; } } return 0; -- cgit v1.2.3-55-g7522 From 154f3ebf53edcfbe28728452b4ab37a118581125 Mon Sep 17 00:00:00 2001 From: Pritesh Raithatha Date: Wed, 17 Oct 2012 17:09:36 +0530 Subject: pinctrl: tegra: set low power mode bank width to 2 Cc: stable@kernel.org Signed-off-by: Pritesh Raithatha Acked-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-tegra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c index 729b686c3ad2..7da0b371fd65 100644 --- a/drivers/pinctrl/pinctrl-tegra.c +++ b/drivers/pinctrl/pinctrl-tegra.c @@ -464,7 +464,7 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx, *bank = g->drv_bank; *reg = g->drv_reg; *bit = g->lpmd_bit; - *width = 1; + *width = 2; break; case TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH: *bank = g->drv_bank; -- cgit v1.2.3-55-g7522 From a03690e44468dcd3088f6600ab036d17bd2130ff Mon Sep 17 00:00:00 2001 From: Pritesh Raithatha Date: Wed, 17 Oct 2012 11:51:37 +0530 Subject: pinctrl: tegra: correct bank for pingroup and drv pingroup Cc: stable@kernel.org Signed-off-by: Pritesh Raithatha Acked-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-tegra30.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c index 0386fdf0da16..7894f14c7059 100644 --- a/drivers/pinctrl/pinctrl-tegra30.c +++ b/drivers/pinctrl/pinctrl-tegra30.c @@ -3345,10 +3345,10 @@ static const struct tegra_function tegra30_functions[] = { FUNCTION(vi_alt3), }; -#define MUXCTL_REG_A 0x3000 -#define PINGROUP_REG_A 0x868 +#define DRV_PINGROUP_REG_A 0x868 /* bank 0 */ +#define PINGROUP_REG_A 0x3000 /* bank 1 */ -#define PINGROUP_REG_Y(r) ((r) - MUXCTL_REG_A) +#define PINGROUP_REG_Y(r) ((r) - PINGROUP_REG_A) #define PINGROUP_REG_N(r) -1 #define PINGROUP(pg_name, f0, f1, f2, f3, f_safe, r, od, ior) \ @@ -3364,25 +3364,25 @@ static const struct tegra_function tegra30_functions[] = { }, \ .func_safe = TEGRA_MUX_ ## f_safe, \ .mux_reg = PINGROUP_REG_Y(r), \ - .mux_bank = 0, \ + .mux_bank = 1, \ .mux_bit = 0, \ .pupd_reg = PINGROUP_REG_Y(r), \ - .pupd_bank = 0, \ + .pupd_bank = 1, \ .pupd_bit = 2, \ .tri_reg = PINGROUP_REG_Y(r), \ - .tri_bank = 0, \ + .tri_bank = 1, \ .tri_bit = 4, \ .einput_reg = PINGROUP_REG_Y(r), \ - .einput_bank = 0, \ + .einput_bank = 1, \ .einput_bit = 5, \ .odrain_reg = PINGROUP_REG_##od(r), \ - .odrain_bank = 0, \ + .odrain_bank = 1, \ .odrain_bit = 6, \ .lock_reg = PINGROUP_REG_Y(r), \ - .lock_bank = 0, \ + .lock_bank = 1, \ .lock_bit = 7, \ .ioreset_reg = PINGROUP_REG_##ior(r), \ - .ioreset_bank = 0, \ + .ioreset_bank = 1, \ .ioreset_bit = 8, \ .drv_reg = -1, \ } @@ -3401,8 +3401,8 @@ static const struct tegra_function tegra30_functions[] = { .odrain_reg = -1, \ .lock_reg = -1, \ .ioreset_reg = -1, \ - .drv_reg = ((r) - PINGROUP_REG_A), \ - .drv_bank = 1, \ + .drv_reg = ((r) - DRV_PINGROUP_REG_A), \ + .drv_bank = 0, \ .hsm_bit = hsm_b, \ .schmitt_bit = schmitt_b, \ .lpmd_bit = lpmd_b, \ -- cgit v1.2.3-55-g7522 From 0a3af268644e0217ea22d6899a76187f930e9590 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Mon, 15 Oct 2012 17:16:23 -0300 Subject: drm/i915: Insert i915_preliminary_hw_support variable. On the worst scenario, users with new hardwares and old kernel from enabling times can get black screens. So, from now on, this perliminary_hw_support module parameter shall be used by all upcoming platforms that are still under enabling. The second option would be to merge the pci ids after basic modeset works, but that makes testing and development while bringing up hw a rather tedious afair. Although it is uncomfortable for developers use this extra variable it brings more stability for end users. Signed-off-by: Rodrigo Vivi Reviewed-by: Dave Airlie [danvet: dropped the i915_ param prefix, i915.i915_ is just tedious.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 13 +++++++++++++ drivers/gpu/drm/i915/i915_drv.h | 1 + 2 files changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index a7837e556945..16564755406d 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -119,6 +119,13 @@ module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600); MODULE_PARM_DESC(i915_enable_ppgtt, "Enable PPGTT (default: true)"); +unsigned int i915_preliminary_hw_support __read_mostly = 0; +module_param_named(preliminary_hw_support, i915_preliminary_hw_support, int, 0600); +MODULE_PARM_DESC(preliminary_hw_support, + "Enable preliminary hardware support. " + "Enable Haswell and ValleyView Support. " + "(default: false)"); + static struct drm_driver driver; extern int intel_agp_enabled; @@ -827,6 +834,12 @@ i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct intel_device_info *intel_info = (struct intel_device_info *) ent->driver_data; + if (intel_info->is_haswell || intel_info->is_valleyview) + if(!i915_preliminary_hw_support) { + DRM_ERROR("Preliminary hardware support disabled\n"); + return -ENODEV; + } + /* Only bind to function 0 of the device. Early generations * used function 1 as a placeholder for multi-head. This causes * us confusion instead, especially on the systems where both diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b84f7861e438..f511fa2f4168 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1217,6 +1217,7 @@ extern int i915_enable_rc6 __read_mostly; extern int i915_enable_fbc __read_mostly; extern bool i915_enable_hangcheck __read_mostly; extern int i915_enable_ppgtt __read_mostly; +extern unsigned int i915_preliminary_hw_support __read_mostly; extern int i915_suspend(struct drm_device *dev, pm_message_t state); extern int i915_resume(struct drm_device *dev); -- cgit v1.2.3-55-g7522 From 2c76a12ae9f5e6e2afc400bfbdd8b326e7d36b2a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Oct 2012 16:09:23 -0300 Subject: [media] Kconfig: Fix dependencies for driver autoselect options This option is a merge of both analog TV and DVB CUSTOMISE. At the merge, the dependencies were not done right: the menu currently appears only for analog TV. It should also be opened for digital TV. As there are other I2C devices there (flash devices, etc) that aren't related to either one, it is better to make it generic enough to open for all media devices with video. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/Kconfig | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index dd13e3a4c272..4ef0d80b57f4 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -163,19 +163,21 @@ source "drivers/media/common/Kconfig" # config MEDIA_SUBDRV_AUTOSELECT - bool "Autoselect analog and hybrid tuner modules to build" - depends on MEDIA_TUNER + bool "Autoselect tuners and i2c modules to build" + depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_CAMERA_SUPPORT default y help - By default, a TV driver auto-selects all possible tuners - thar could be used by the driver. + By default, a media driver auto-selects all possible i2c + devices that are used by any of the supported devices. This is generally the right thing to do, except when there - are strict constraints with regards to the kernel size. + are strict constraints with regards to the kernel size, + like on embedded systems. - Use this option with care, as deselecting tuner drivers which - are in fact necessary will result in TV devices which cannot - be tuned due to lack of the tuning driver. + Use this option with care, as deselecting ancillary drivers which + are, in fact, necessary will result in the lack of the needed + functionality for your device (it may not tune or may not have + the need demodulers). If unsure say Y. -- cgit v1.2.3-55-g7522 From 014639003c77a51fc319c9fdf225e7747cb6e18d Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Sat, 13 Oct 2012 12:20:36 +0200 Subject: usbdevfs: Fix broken scatter-gather transfer The handling of large output bulk transfers is broken; the same user page is read over and over again. Fixed with this patch. Cc: stable Acked-by: Peter Stuge Acked-by: Hans de Goede Acked-by: Alan Stern Signed-off-by: Henrik Rydberg Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index e0356cb859b5..b78fbe222b72 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1348,6 +1348,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, ret = -EFAULT; goto error; } + uurb->buffer += u; } totlen -= u; } -- cgit v1.2.3-55-g7522 From c5211187f7ff8e8dbff4ebf7c011ac4c0ffe319c Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 16 Oct 2012 21:21:21 +0800 Subject: USB: cdc-acm: fix pipe type of write endpoint If the write endpoint is interrupt type, usb_sndintpipe() should be passed to usb_fill_int_urb() instead of usb_sndbulkpipe(). Cc: Oliver Neukum Signed-off-by: Ming Lei Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 981f2132d128..572f4e7bd3ff 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1233,7 +1233,7 @@ made_compressed_probe: if (usb_endpoint_xfer_int(epwrite)) usb_fill_int_urb(snd->urb, usb_dev, - usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), + usb_sndintpipe(usb_dev, epwrite->bEndpointAddress), NULL, acm->writesize, acm_write_bulk, snd, epwrite->bInterval); else usb_fill_bulk_urb(snd->urb, usb_dev, -- cgit v1.2.3-55-g7522 From 09eeffb70c086692064f4224490d1cd2ffe43bdd Mon Sep 17 00:00:00 2001 From: Tony Prisk Date: Sun, 14 Oct 2012 16:22:34 +1300 Subject: usb: Missing dma_mask in uhci-platform.c when probed from device-tree Device-tree probed devices don't get a dev.dma_mask set. This patch sets a default 32bit mask on platforms using devicetree. Without this patch, arch-vt8500 cannot detect uhci attached devices. Signed-off-by: Tony Prisk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-platform.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c index e4780491df4a..68ebf20e1519 100644 --- a/drivers/usb/host/uhci-platform.c +++ b/drivers/usb/host/uhci-platform.c @@ -60,6 +60,7 @@ static const struct hc_driver uhci_platform_hc_driver = { .hub_control = uhci_hub_control, }; +static u64 platform_uhci_dma_mask = DMA_BIT_MASK(32); static int __devinit uhci_hcd_platform_probe(struct platform_device *pdev) { @@ -71,6 +72,14 @@ static int __devinit uhci_hcd_platform_probe(struct platform_device *pdev) if (usb_disabled()) return -ENODEV; + /* + * Right now device-tree probed devices don't get dma_mask set. + * Since shared usb code relies on it, set it here for now. + * Once we have dma capability bindings this can go away. + */ + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &platform_uhci_dma_mask; + hcd = usb_create_hcd(&uhci_platform_hc_driver, &pdev->dev, pdev->name); if (!hcd) -- cgit v1.2.3-55-g7522 From 6e1babb3ff2651376f2e9843569fcb39cfe4686b Mon Sep 17 00:00:00 2001 From: Tony Prisk Date: Sun, 14 Oct 2012 16:22:35 +1300 Subject: usb: Missing dma_mask in ehci-vt8500.c when probed from device-tree Device-tree probed devices don't get a dev.dma_mask set. This patch sets a default 32bit mask on arch-vt8500 when using devicetree. Without this patch, arch-vt8500 cannot detect ehci attached devices. Signed-off-by: Tony Prisk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-vt8500.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c index 96722bfebc84..d3c9a3e397b9 100644 --- a/drivers/usb/host/ehci-vt8500.c +++ b/drivers/usb/host/ehci-vt8500.c @@ -85,6 +85,8 @@ static const struct hc_driver vt8500_ehci_hc_driver = { .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; +static u64 vt8500_ehci_dma_mask = DMA_BIT_MASK(32); + static int vt8500_ehci_drv_probe(struct platform_device *pdev) { struct usb_hcd *hcd; @@ -95,6 +97,14 @@ static int vt8500_ehci_drv_probe(struct platform_device *pdev) if (usb_disabled()) return -ENODEV; + /* + * Right now device-tree probed devices don't get dma_mask set. + * Since shared usb code relies on it, set it here for now. + * Once we have dma capability bindings this can go away. + */ + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &vt8500_ehci_dma_mask; + if (pdev->resource[1].flags != IORESOURCE_IRQ) { pr_debug("resource[1] is not IORESOURCE_IRQ"); return -ENOMEM; -- cgit v1.2.3-55-g7522 From 301a29da6e891e7eb95c843af0ecdbe86d01f723 Mon Sep 17 00:00:00 2001 From: Nicolas Boullis Date: Tue, 16 Oct 2012 00:06:23 +0200 Subject: usb: acm: fix the computation of the number of data bits The current code assumes that CSIZE is 0000060, which appears to be wrong on some arches (such as powerpc). Signed-off-by: Nicolas Boullis Acked-by: Oliver Neukum Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 572f4e7bd3ff..6e49ec6f3adc 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -817,10 +817,6 @@ static const __u32 acm_tty_speed[] = { 2500000, 3000000, 3500000, 4000000 }; -static const __u8 acm_tty_size[] = { - 5, 6, 7, 8 -}; - static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old) { @@ -834,7 +830,21 @@ static void acm_tty_set_termios(struct tty_struct *tty, newline.bParityType = termios->c_cflag & PARENB ? (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0; - newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4]; + switch (termios->c_cflag & CSIZE) { + case CS5: + newline.bDataBits = 5; + break; + case CS6: + newline.bDataBits = 6; + break; + case CS7: + newline.bDataBits = 7; + break; + case CS8: + default: + newline.bDataBits = 8; + break; + } /* FIXME: Needs to clear unsupported bits in the termios */ acm->clocal = ((termios->c_cflag & CLOCAL) != 0); -- cgit v1.2.3-55-g7522 From 5c1a0f418d8d985f3a62849bcac43fc5404cc592 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 13:34:55 +0200 Subject: USB: cypress_m8: fix port-data memory leak Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cypress_m8.c | 75 ++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 1befce21e173..f0da1279c114 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -123,10 +123,10 @@ struct cypress_private { }; /* function prototypes for the Cypress USB to serial device */ -static int cypress_earthmate_startup(struct usb_serial *serial); -static int cypress_hidcom_startup(struct usb_serial *serial); -static int cypress_ca42v2_startup(struct usb_serial *serial); -static void cypress_release(struct usb_serial *serial); +static int cypress_earthmate_port_probe(struct usb_serial_port *port); +static int cypress_hidcom_port_probe(struct usb_serial_port *port); +static int cypress_ca42v2_port_probe(struct usb_serial_port *port); +static int cypress_port_remove(struct usb_serial_port *port); static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port); static void cypress_close(struct usb_serial_port *port); static void cypress_dtr_rts(struct usb_serial_port *port, int on); @@ -156,8 +156,8 @@ static struct usb_serial_driver cypress_earthmate_device = { .description = "DeLorme Earthmate USB", .id_table = id_table_earthmate, .num_ports = 1, - .attach = cypress_earthmate_startup, - .release = cypress_release, + .port_probe = cypress_earthmate_port_probe, + .port_remove = cypress_port_remove, .open = cypress_open, .close = cypress_close, .dtr_rts = cypress_dtr_rts, @@ -182,8 +182,8 @@ static struct usb_serial_driver cypress_hidcom_device = { .description = "HID->COM RS232 Adapter", .id_table = id_table_cyphidcomrs232, .num_ports = 1, - .attach = cypress_hidcom_startup, - .release = cypress_release, + .port_probe = cypress_hidcom_port_probe, + .port_remove = cypress_port_remove, .open = cypress_open, .close = cypress_close, .dtr_rts = cypress_dtr_rts, @@ -208,8 +208,8 @@ static struct usb_serial_driver cypress_ca42v2_device = { .description = "Nokia CA-42 V2 Adapter", .id_table = id_table_nokiaca42v2, .num_ports = 1, - .attach = cypress_ca42v2_startup, - .release = cypress_release, + .port_probe = cypress_ca42v2_port_probe, + .port_remove = cypress_port_remove, .open = cypress_open, .close = cypress_close, .dtr_rts = cypress_dtr_rts, @@ -438,10 +438,10 @@ static void cypress_set_dead(struct usb_serial_port *port) *****************************************************************************/ -static int generic_startup(struct usb_serial *serial) +static int cypress_generic_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct cypress_private *priv; - struct usb_serial_port *port = serial->port[0]; priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); if (!priv) @@ -490,14 +490,16 @@ static int generic_startup(struct usb_serial *serial) } -static int cypress_earthmate_startup(struct usb_serial *serial) +static int cypress_earthmate_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct cypress_private *priv; - struct usb_serial_port *port = serial->port[0]; + int ret; - if (generic_startup(serial)) { + ret = cypress_generic_port_probe(port); + if (ret) { dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); - return 1; + return ret; } priv = usb_get_serial_port_data(port); @@ -518,56 +520,53 @@ static int cypress_earthmate_startup(struct usb_serial *serial) } return 0; -} /* cypress_earthmate_startup */ - +} -static int cypress_hidcom_startup(struct usb_serial *serial) +static int cypress_hidcom_port_probe(struct usb_serial_port *port) { struct cypress_private *priv; - struct usb_serial_port *port = serial->port[0]; + int ret; - if (generic_startup(serial)) { + ret = cypress_generic_port_probe(port); + if (ret) { dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); - return 1; + return ret; } priv = usb_get_serial_port_data(port); priv->chiptype = CT_CYPHIDCOM; return 0; -} /* cypress_hidcom_startup */ - +} -static int cypress_ca42v2_startup(struct usb_serial *serial) +static int cypress_ca42v2_port_probe(struct usb_serial_port *port) { struct cypress_private *priv; - struct usb_serial_port *port = serial->port[0]; + int ret; - if (generic_startup(serial)) { + ret = cypress_generic_port_probe(port); + if (ret) { dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); - return 1; + return ret; } priv = usb_get_serial_port_data(port); priv->chiptype = CT_CA42V2; return 0; -} /* cypress_ca42v2_startup */ - +} -static void cypress_release(struct usb_serial *serial) +static int cypress_port_remove(struct usb_serial_port *port) { struct cypress_private *priv; - /* all open ports are closed at this point */ - priv = usb_get_serial_port_data(serial->port[0]); + priv = usb_get_serial_port_data(port); - if (priv) { - kfifo_free(&priv->write_fifo); - kfree(priv); - } -} + kfifo_free(&priv->write_fifo); + kfree(priv); + return 0; +} static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port) { -- cgit v1.2.3-55-g7522 From 95940a04bfe8a4d246f4ca17c6a3b00148bdead0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 13:35:02 +0200 Subject: USB: kobil_sct: fix port-data memory leak Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/kobil_sct.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 5c4d2fbd4e11..c9ca7a5b12e0 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -54,8 +54,8 @@ /* Function prototypes */ -static int kobil_startup(struct usb_serial *serial); -static void kobil_release(struct usb_serial *serial); +static int kobil_port_probe(struct usb_serial_port *probe); +static int kobil_port_remove(struct usb_serial_port *probe); static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port); static void kobil_close(struct usb_serial_port *port); static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, @@ -89,8 +89,8 @@ static struct usb_serial_driver kobil_device = { .description = "KOBIL USB smart card terminal", .id_table = id_table, .num_ports = 1, - .attach = kobil_startup, - .release = kobil_release, + .port_probe = kobil_port_probe, + .port_remove = kobil_port_remove, .ioctl = kobil_ioctl, .set_termios = kobil_set_termios, .init_termios = kobil_init_termios, @@ -117,9 +117,10 @@ struct kobil_private { }; -static int kobil_startup(struct usb_serial *serial) +static int kobil_port_probe(struct usb_serial_port *port) { int i; + struct usb_serial *serial = port->serial; struct kobil_private *priv; struct usb_device *pdev; struct usb_host_config *actconfig; @@ -149,7 +150,7 @@ static int kobil_startup(struct usb_serial *serial) dev_dbg(&serial->dev->dev, "KOBIL KAAN SIM detected\n"); break; } - usb_set_serial_port_data(serial->port[0], priv); + usb_set_serial_port_data(port, priv); /* search for the necessary endpoints */ pdev = serial->dev; @@ -179,12 +180,14 @@ static int kobil_startup(struct usb_serial *serial) } -static void kobil_release(struct usb_serial *serial) +static int kobil_port_remove(struct usb_serial_port *port) { - int i; + struct kobil_private *priv; - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static void kobil_init_termios(struct tty_struct *tty) -- cgit v1.2.3-55-g7522 From c27f3efc56080a246f6ab7f57f0a6f56d256d769 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 13:34:57 +0200 Subject: USB: io_edgeport: fix port-data memory leak Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_edgeport.c | 54 +++++++++++++++++++++------------------- drivers/usb/serial/io_tables.h | 8 ++++++ 2 files changed, 37 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 8e6faaf3580c..5acc0d13864a 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -225,6 +225,8 @@ static int edge_get_icount(struct tty_struct *tty, static int edge_startup(struct usb_serial *serial); static void edge_disconnect(struct usb_serial *serial); static void edge_release(struct usb_serial *serial); +static int edge_port_probe(struct usb_serial_port *port); +static int edge_port_remove(struct usb_serial_port *port); #include "io_tables.h" /* all of the devices that this driver supports */ @@ -2875,10 +2877,9 @@ static void load_application_firmware(struct edgeport_serial *edge_serial) static int edge_startup(struct usb_serial *serial) { struct edgeport_serial *edge_serial; - struct edgeport_port *edge_port; struct usb_device *dev; struct device *ddev = &serial->dev->dev; - int i, j; + int i; int response; bool interrupt_in_found; bool bulk_in_found; @@ -2961,25 +2962,6 @@ static int edge_startup(struct usb_serial *serial) /* we set up the pointers to the endpoints in the edge_open function, * as the structures aren't created yet. */ - /* set up our port private structures */ - for (i = 0; i < serial->num_ports; ++i) { - edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL); - if (edge_port == NULL) { - dev_err(ddev, "%s - Out of memory\n", __func__); - for (j = 0; j < i; ++j) { - kfree(usb_get_serial_port_data(serial->port[j])); - usb_set_serial_port_data(serial->port[j], - NULL); - } - usb_set_serial_data(serial, NULL); - kfree(edge_serial); - return -ENOMEM; - } - spin_lock_init(&edge_port->ep_lock); - edge_port->port = serial->port[i]; - usb_set_serial_port_data(serial->port[i], edge_port); - } - response = 0; if (edge_serial->is_epic) { @@ -3120,14 +3102,36 @@ static void edge_disconnect(struct usb_serial *serial) static void edge_release(struct usb_serial *serial) { struct edgeport_serial *edge_serial = usb_get_serial_data(serial); - int i; - - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); kfree(edge_serial); } +static int edge_port_probe(struct usb_serial_port *port) +{ + struct edgeport_port *edge_port; + + edge_port = kzalloc(sizeof(*edge_port), GFP_KERNEL); + if (!edge_port) + return -ENOMEM; + + spin_lock_init(&edge_port->ep_lock); + edge_port->port = port; + + usb_set_serial_port_data(port, edge_port); + + return 0; +} + +static int edge_port_remove(struct usb_serial_port *port) +{ + struct edgeport_port *edge_port; + + edge_port = usb_get_serial_port_data(port); + kfree(edge_port); + + return 0; +} + module_usb_serial_driver(serial_drivers, id_table_combined); MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h index 350afddb55ba..1511dd0ad324 100644 --- a/drivers/usb/serial/io_tables.h +++ b/drivers/usb/serial/io_tables.h @@ -110,6 +110,8 @@ static struct usb_serial_driver edgeport_2port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -139,6 +141,8 @@ static struct usb_serial_driver edgeport_4port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -168,6 +172,8 @@ static struct usb_serial_driver edgeport_8port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -197,6 +203,8 @@ static struct usb_serial_driver epic_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, -- cgit v1.2.3-55-g7522 From 3124d1d71d3df59d40b913b5481df58099e811d1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 13:34:56 +0200 Subject: USB: f81232: fix port-data memory leak Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/f81232.c | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index 244477107e2f..6e4eb57d0177 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -318,39 +318,30 @@ static int f81232_ioctl(struct tty_struct *tty, return -ENOIOCTLCMD; } -static int f81232_startup(struct usb_serial *serial) +static int f81232_port_probe(struct usb_serial_port *port) { struct f81232_private *priv; - int i; - for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc(sizeof(struct f81232_private), GFP_KERNEL); - if (!priv) - goto cleanup; - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->delta_msr_wait); - usb_set_serial_port_data(serial->port[i], priv); - } - return 0; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; -cleanup: - for (--i; i >= 0; --i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i], NULL); - } - return -ENOMEM; + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->delta_msr_wait); + + usb_set_serial_port_data(port, priv); + + return 0; } -static void f81232_release(struct usb_serial *serial) +static int f81232_port_remove(struct usb_serial_port *port) { - int i; struct f81232_private *priv; - for (i = 0; i < serial->num_ports; ++i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - } + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static struct usb_serial_driver f81232_device = { @@ -373,8 +364,8 @@ static struct usb_serial_driver f81232_device = { .tiocmset = f81232_tiocmset, .process_read_urb = f81232_process_read_urb, .read_int_callback = f81232_read_int_callback, - .attach = f81232_startup, - .release = f81232_release, + .port_probe = f81232_port_probe, + .port_remove = f81232_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { -- cgit v1.2.3-55-g7522 From 94ab71ce288921490ca857e25ad174e1921b1e29 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 13:35:00 +0200 Subject: USB: keyspan_pda: fix port-data memory leak Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that the write waitqueue was initialised but never used. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/keyspan_pda.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index ca43ecb4a2bd..bb87e29c4ac2 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -713,29 +713,33 @@ MODULE_FIRMWARE("keyspan_pda/keyspan_pda.fw"); MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw"); #endif -static int keyspan_pda_startup(struct usb_serial *serial) +static int keyspan_pda_port_probe(struct usb_serial_port *port) { struct keyspan_pda_private *priv; - /* allocate the private data structures for all ports. Well, for all - one ports. */ - priv = kmalloc(sizeof(struct keyspan_pda_private), GFP_KERNEL); if (!priv) - return 1; /* error */ - usb_set_serial_port_data(serial->port[0], priv); - init_waitqueue_head(&serial->port[0]->write_wait); + return -ENOMEM; + INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write); INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle); - priv->serial = serial; - priv->port = serial->port[0]; + priv->serial = port->serial; + priv->port = port; + + usb_set_serial_port_data(port, priv); + return 0; } -static void keyspan_pda_release(struct usb_serial *serial) +static int keyspan_pda_port_remove(struct usb_serial_port *port) { - kfree(usb_get_serial_port_data(serial->port[0])); + struct keyspan_pda_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } #ifdef KEYSPAN @@ -786,8 +790,8 @@ static struct usb_serial_driver keyspan_pda_device = { .break_ctl = keyspan_pda_break_ctl, .tiocmget = keyspan_pda_tiocmget, .tiocmset = keyspan_pda_tiocmset, - .attach = keyspan_pda_startup, - .release = keyspan_pda_release, + .port_probe = keyspan_pda_port_probe, + .port_remove = keyspan_pda_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { -- cgit v1.2.3-55-g7522 From 003615302a16579531932576bcd9582ddeba9018 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 13:34:58 +0200 Subject: USB: io_ti: fix port-data memory leak Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_ti.c | 91 +++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index a2209cd45093..9ae65d679f02 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2532,12 +2532,7 @@ static void edge_break(struct tty_struct *tty, int break_state) static int edge_startup(struct usb_serial *serial) { struct edgeport_serial *edge_serial; - struct edgeport_port *edge_port; - struct usb_device *dev; int status; - int i; - - dev = serial->dev; /* create our private serial structure */ edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL); @@ -2555,40 +2550,7 @@ static int edge_startup(struct usb_serial *serial) return status; } - /* set up our port private structures */ - for (i = 0; i < serial->num_ports; ++i) { - edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL); - if (edge_port == NULL) { - dev_err(&serial->dev->dev, "%s - Out of memory\n", - __func__); - goto cleanup; - } - spin_lock_init(&edge_port->ep_lock); - if (kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE, - GFP_KERNEL)) { - dev_err(&serial->dev->dev, "%s - Out of memory\n", - __func__); - kfree(edge_port); - goto cleanup; - } - edge_port->port = serial->port[i]; - edge_port->edge_serial = edge_serial; - usb_set_serial_port_data(serial->port[i], edge_port); - edge_port->bUartMode = default_uart_mode; - } - return 0; - -cleanup: - for (--i; i >= 0; --i) { - edge_port = usb_get_serial_port_data(serial->port[i]); - kfifo_free(&edge_port->write_fifo); - kfree(edge_port); - usb_set_serial_port_data(serial->port[i], NULL); - } - kfree(edge_serial); - usb_set_serial_data(serial, NULL); - return -ENOMEM; } static void edge_disconnect(struct usb_serial *serial) @@ -2597,17 +2559,54 @@ static void edge_disconnect(struct usb_serial *serial) static void edge_release(struct usb_serial *serial) { - int i; + kfree(usb_get_serial_data(serial)); +} + +static int edge_port_probe(struct usb_serial_port *port) +{ struct edgeport_port *edge_port; + int ret; - for (i = 0; i < serial->num_ports; ++i) { - edge_port = usb_get_serial_port_data(serial->port[i]); + edge_port = kzalloc(sizeof(*edge_port), GFP_KERNEL); + if (!edge_port) + return -ENOMEM; + + ret = kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE, + GFP_KERNEL); + if (ret) { + kfree(edge_port); + return -ENOMEM; + } + + ret = edge_create_sysfs_attrs(port); + if (ret) { kfifo_free(&edge_port->write_fifo); kfree(edge_port); + return ret; } - kfree(usb_get_serial_data(serial)); + + spin_lock_init(&edge_port->ep_lock); + edge_port->port = port; + edge_port->edge_serial = usb_get_serial_data(port->serial); + edge_port->bUartMode = default_uart_mode; + + usb_set_serial_port_data(port, edge_port); + + return 0; } +static int edge_port_remove(struct usb_serial_port *port) +{ + struct edgeport_port *edge_port; + + edge_port = usb_get_serial_port_data(port); + + edge_remove_sysfs_attrs(port); + kfifo_free(&edge_port->write_fifo); + kfree(edge_port); + + return 0; +} /* Sysfs Attributes */ @@ -2667,8 +2666,8 @@ static struct usb_serial_driver edgeport_1port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, - .port_probe = edge_create_sysfs_attrs, - .port_remove = edge_remove_sysfs_attrs, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -2698,8 +2697,8 @@ static struct usb_serial_driver edgeport_2port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, - .port_probe = edge_create_sysfs_attrs, - .port_remove = edge_remove_sysfs_attrs, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, -- cgit v1.2.3-55-g7522 From 99a6f73c495c420df826e5b267fb073fd6766fc3 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 13:35:01 +0200 Subject: USB: kl5kusb105: fix port-data memory leak Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that the write waitqueue was initialised but never used. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/kl5kusb105.c | 68 +++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 3f6d7376c02d..1f4517864cd2 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -60,8 +60,8 @@ /* * Function prototypes */ -static int klsi_105_startup(struct usb_serial *serial); -static void klsi_105_release(struct usb_serial *serial); +static int klsi_105_port_probe(struct usb_serial_port *port); +static int klsi_105_port_remove(struct usb_serial_port *port); static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port); static void klsi_105_close(struct usb_serial_port *port); static void klsi_105_set_termios(struct tty_struct *tty, @@ -99,8 +99,8 @@ static struct usb_serial_driver kl5kusb105d_device = { /*.break_ctl = klsi_105_break_ctl,*/ .tiocmget = klsi_105_tiocmget, .tiocmset = klsi_105_tiocmset, - .attach = klsi_105_startup, - .release = klsi_105_release, + .port_probe = klsi_105_port_probe, + .port_remove = klsi_105_port_remove, .throttle = usb_serial_generic_throttle, .unthrottle = usb_serial_generic_unthrottle, .process_read_urb = klsi_105_process_read_urb, @@ -223,60 +223,40 @@ static int klsi_105_get_line_state(struct usb_serial_port *port, * Driver's tty interface functions */ -static int klsi_105_startup(struct usb_serial *serial) +static int klsi_105_port_probe(struct usb_serial_port *port) { struct klsi_105_private *priv; - int i; - /* check if we support the product id (see keyspan.c) - * FIXME - */ + priv = kmalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; - /* allocate the private data structure */ - for (i = 0; i < serial->num_ports; i++) { - priv = kmalloc(sizeof(struct klsi_105_private), - GFP_KERNEL); - if (!priv) { - dev_dbg(&serial->interface->dev, - "%s - kmalloc for klsi_105_private failed.\n", - __func__); - i--; - goto err_cleanup; - } - /* set initial values for control structures */ - priv->cfg.pktlen = 5; - priv->cfg.baudrate = kl5kusb105a_sio_b9600; - priv->cfg.databits = kl5kusb105a_dtb_8; - priv->cfg.unknown1 = 0; - priv->cfg.unknown2 = 1; + /* set initial values for control structures */ + priv->cfg.pktlen = 5; + priv->cfg.baudrate = kl5kusb105a_sio_b9600; + priv->cfg.databits = kl5kusb105a_dtb_8; + priv->cfg.unknown1 = 0; + priv->cfg.unknown2 = 1; - priv->line_state = 0; + priv->line_state = 0; - usb_set_serial_port_data(serial->port[i], priv); + spin_lock_init(&priv->lock); - spin_lock_init(&priv->lock); + /* priv->termios is left uninitialized until port opening */ - /* priv->termios is left uninitialized until port opening */ - init_waitqueue_head(&serial->port[i]->write_wait); - } + usb_set_serial_port_data(port, priv); return 0; - -err_cleanup: - for (; i >= 0; i--) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i], NULL); - } - return -ENOMEM; } -static void klsi_105_release(struct usb_serial *serial) +static int klsi_105_port_remove(struct usb_serial_port *port) { - int i; + struct klsi_105_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); + return 0; } static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) -- cgit v1.2.3-55-g7522 From 53636555b9190f88320d9d46cf142f8797895456 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 13:34:59 +0200 Subject: USB: iuu_phoenix: fix port-data memory leak Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/iuu_phoenix.c | 62 ++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 01da3ea36e89..959f71e31dca 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -72,63 +72,45 @@ struct iuu_private { u32 clk; }; - -static void iuu_free_buf(struct iuu_private *priv) -{ - kfree(priv->buf); - kfree(priv->writebuf); -} - -static int iuu_alloc_buf(struct usb_serial *serial, struct iuu_private *priv) -{ - priv->buf = kzalloc(256, GFP_KERNEL); - priv->writebuf = kzalloc(256, GFP_KERNEL); - if (!priv->buf || !priv->writebuf) { - iuu_free_buf(priv); - dev_dbg(&serial->dev->dev, "%s problem allocation buffer\n", __func__); - return -ENOMEM; - } - dev_dbg(&serial->dev->dev, "%s - Privates buffers allocation success\n", __func__); - return 0; -} - -static int iuu_startup(struct usb_serial *serial) +static int iuu_port_probe(struct usb_serial_port *port) { struct iuu_private *priv; priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL); - dev_dbg(&serial->dev->dev, "%s- priv allocation success\n", __func__); if (!priv) return -ENOMEM; - if (iuu_alloc_buf(serial, priv)) { + + priv->buf = kzalloc(256, GFP_KERNEL); + if (!priv->buf) { kfree(priv); return -ENOMEM; } + + priv->writebuf = kzalloc(256, GFP_KERNEL); + if (!priv->writebuf) { + kfree(priv->buf); + kfree(priv); + return -ENOMEM; + } + priv->vcc = vcc_default; spin_lock_init(&priv->lock); init_waitqueue_head(&priv->delta_msr_wait); - usb_set_serial_port_data(serial->port[0], priv); + + usb_set_serial_port_data(port, priv); + return 0; } -/* Release function */ -static void iuu_release(struct usb_serial *serial) +static int iuu_port_remove(struct usb_serial_port *port) { - struct usb_serial_port *port = serial->port[0]; struct iuu_private *priv = usb_get_serial_port_data(port); - if (!port) - return; - - if (priv) { - iuu_free_buf(priv); - dev_dbg(&port->dev, "%s - I will free all\n", __func__); - usb_set_serial_port_data(port, NULL); - dev_dbg(&port->dev, "%s - priv is not anymore in port structure\n", __func__); - kfree(priv); + kfree(priv->writebuf); + kfree(priv->buf); + kfree(priv); - dev_dbg(&port->dev, "%s priv is now kfree\n", __func__); - } + return 0; } static int iuu_tiocmset(struct tty_struct *tty, @@ -1225,8 +1207,8 @@ static struct usb_serial_driver iuu_device = { .tiocmset = iuu_tiocmset, .set_termios = iuu_set_termios, .init_termios = iuu_init_termios, - .attach = iuu_startup, - .release = iuu_release, + .port_probe = iuu_port_probe, + .port_remove = iuu_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { -- cgit v1.2.3-55-g7522 From 289b076f89c2c3260e914dad18ae12f193ea86d5 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 16:31:32 +0200 Subject: USB: oti6858: fix port-data memory leak Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/oti6858.c | 68 ++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 933241f03fd8..cee9a52ca891 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -137,8 +137,8 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty); static int oti6858_tiocmget(struct tty_struct *tty); static int oti6858_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); -static int oti6858_startup(struct usb_serial *serial); -static void oti6858_release(struct usb_serial *serial); +static int oti6858_port_probe(struct usb_serial_port *port); +static int oti6858_port_remove(struct usb_serial_port *port); /* device info */ static struct usb_serial_driver oti6858_device = { @@ -161,8 +161,8 @@ static struct usb_serial_driver oti6858_device = { .write_bulk_callback = oti6858_write_bulk_callback, .write_room = oti6858_write_room, .chars_in_buffer = oti6858_chars_in_buffer, - .attach = oti6858_startup, - .release = oti6858_release, + .port_probe = oti6858_port_probe, + .port_remove = oti6858_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -331,36 +331,33 @@ static void send_data(struct work_struct *work) usb_serial_port_softint(port); } -static int oti6858_startup(struct usb_serial *serial) +static int oti6858_port_probe(struct usb_serial_port *port) { - struct usb_serial_port *port = serial->port[0]; struct oti6858_private *priv; - int i; - - for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc(sizeof(struct oti6858_private), GFP_KERNEL); - if (!priv) - break; - - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->intr_wait); -/* INIT_WORK(&priv->setup_work, setup_line, serial->port[i]); */ -/* INIT_WORK(&priv->write_work, send_data, serial->port[i]); */ - priv->port = port; - INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line); - INIT_DELAYED_WORK(&priv->delayed_write_work, send_data); - - usb_set_serial_port_data(serial->port[i], priv); - } - if (i == serial->num_ports) - return 0; - for (--i; i >= 0; --i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i], NULL); - } - return -ENOMEM; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->intr_wait); + priv->port = port; + INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line); + INIT_DELAYED_WORK(&priv->delayed_write_work, send_data); + + usb_set_serial_port_data(port, priv); + + return 0; +} + +static int oti6858_port_remove(struct usb_serial_port *port) +{ + struct oti6858_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port, @@ -709,15 +706,6 @@ static int oti6858_ioctl(struct tty_struct *tty, return -ENOIOCTLCMD; } - -static void oti6858_release(struct usb_serial *serial) -{ - int i; - - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); -} - static void oti6858_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; -- cgit v1.2.3-55-g7522 From 51ef847df74632e7cfdf952afc3887de105b8b35 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 16:31:35 +0200 Subject: USB: ti_usb_3410_5052: fix port-data memory leak Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 88 +++++++++++++++++------------------ 1 file changed, 43 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 6f49392cda5b..f2530d2ef3c4 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -97,6 +97,8 @@ struct ti_device { static int ti_startup(struct usb_serial *serial); static void ti_release(struct usb_serial *serial); +static int ti_port_probe(struct usb_serial_port *port); +static int ti_port_remove(struct usb_serial_port *port); static int ti_open(struct tty_struct *tty, struct usb_serial_port *port); static void ti_close(struct usb_serial_port *port); static int ti_write(struct tty_struct *tty, struct usb_serial_port *port, @@ -221,6 +223,8 @@ static struct usb_serial_driver ti_1port_device = { .num_ports = 1, .attach = ti_startup, .release = ti_release, + .port_probe = ti_port_probe, + .port_remove = ti_port_remove, .open = ti_open, .close = ti_close, .write = ti_write, @@ -249,6 +253,8 @@ static struct usb_serial_driver ti_2port_device = { .num_ports = 2, .attach = ti_startup, .release = ti_release, + .port_probe = ti_port_probe, + .port_remove = ti_port_remove, .open = ti_open, .close = ti_close, .write = ti_write, @@ -347,11 +353,8 @@ module_exit(ti_exit); static int ti_startup(struct usb_serial *serial) { struct ti_device *tdev; - struct ti_port *tport; struct usb_device *dev = serial->dev; int status; - int i; - dev_dbg(&dev->dev, "%s - product 0x%4X, num configurations %d, configuration value %d", @@ -399,42 +402,8 @@ static int ti_startup(struct usb_serial *serial) goto free_tdev; } - /* set up port structures */ - for (i = 0; i < serial->num_ports; ++i) { - tport = kzalloc(sizeof(struct ti_port), GFP_KERNEL); - if (tport == NULL) { - dev_err(&dev->dev, "%s - out of memory\n", __func__); - status = -ENOMEM; - goto free_tports; - } - spin_lock_init(&tport->tp_lock); - tport->tp_uart_base_addr = (i == 0 ? - TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR); - tport->tp_closing_wait = closing_wait; - init_waitqueue_head(&tport->tp_msr_wait); - init_waitqueue_head(&tport->tp_write_wait); - if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, - GFP_KERNEL)) { - dev_err(&dev->dev, "%s - out of memory\n", __func__); - kfree(tport); - status = -ENOMEM; - goto free_tports; - } - tport->tp_port = serial->port[i]; - tport->tp_tdev = tdev; - usb_set_serial_port_data(serial->port[i], tport); - tport->tp_uart_mode = 0; /* default is RS232 */ - } - return 0; -free_tports: - for (--i; i >= 0; --i) { - tport = usb_get_serial_port_data(serial->port[i]); - kfifo_free(&tport->write_fifo); - kfree(tport); - usb_set_serial_port_data(serial->port[i], NULL); - } free_tdev: kfree(tdev); usb_set_serial_data(serial, NULL); @@ -444,21 +413,50 @@ free_tdev: static void ti_release(struct usb_serial *serial) { - int i; struct ti_device *tdev = usb_get_serial_data(serial); + + kfree(tdev); +} + +static int ti_port_probe(struct usb_serial_port *port) +{ struct ti_port *tport; - for (i = 0; i < serial->num_ports; ++i) { - tport = usb_get_serial_port_data(serial->port[i]); - if (tport) { - kfifo_free(&tport->write_fifo); - kfree(tport); - } + tport = kzalloc(sizeof(*tport), GFP_KERNEL); + if (!tport) + return -ENOMEM; + + spin_lock_init(&tport->tp_lock); + if (port == port->serial->port[0]) + tport->tp_uart_base_addr = TI_UART1_BASE_ADDR; + else + tport->tp_uart_base_addr = TI_UART2_BASE_ADDR; + tport->tp_closing_wait = closing_wait; + init_waitqueue_head(&tport->tp_msr_wait); + init_waitqueue_head(&tport->tp_write_wait); + if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) { + kfree(tport); + return -ENOMEM; } + tport->tp_port = port; + tport->tp_tdev = usb_get_serial_data(port->serial); + tport->tp_uart_mode = 0; /* default is RS232 */ - kfree(tdev); + usb_set_serial_port_data(port, tport); + + return 0; } +static int ti_port_remove(struct usb_serial_port *port) +{ + struct ti_port *tport; + + tport = usb_get_serial_port_data(port); + kfifo_free(&tport->write_fifo); + kfree(tport); + + return 0; +} static int ti_open(struct tty_struct *tty, struct usb_serial_port *port) { -- cgit v1.2.3-55-g7522 From 638b9e15233c9570bce65301aa9877235316b9f0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 16:31:34 +0200 Subject: USB: ssu100: fix port-data memory leak Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ssu100.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 015810b3785b..868d1e6852e2 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -67,13 +67,6 @@ struct ssu100_port_private { struct async_icount icount; }; -static void ssu100_release(struct usb_serial *serial) -{ - struct ssu100_port_private *priv = usb_get_serial_port_data(*serial->port); - - kfree(priv); -} - static inline int ssu100_control_msg(struct usb_device *dev, u8 request, u16 data, u16 index) { @@ -441,22 +434,34 @@ static int ssu100_ioctl(struct tty_struct *tty, } static int ssu100_attach(struct usb_serial *serial) +{ + return ssu100_initdevice(serial->dev); +} + +static int ssu100_port_probe(struct usb_serial_port *port) { struct ssu100_port_private *priv; - struct usb_serial_port *port = *serial->port; priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) { - dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__, - sizeof(*priv)); + if (!priv) return -ENOMEM; - } spin_lock_init(&priv->status_lock); init_waitqueue_head(&priv->delta_msr_wait); + usb_set_serial_port_data(port, priv); - return ssu100_initdevice(serial->dev); + return 0; +} + +static int ssu100_port_remove(struct usb_serial_port *port) +{ + struct ssu100_port_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static int ssu100_tiocmget(struct tty_struct *tty) @@ -647,7 +652,8 @@ static struct usb_serial_driver ssu100_device = { .open = ssu100_open, .close = ssu100_close, .attach = ssu100_attach, - .release = ssu100_release, + .port_probe = ssu100_port_probe, + .port_remove = ssu100_port_remove, .dtr_rts = ssu100_dtr_rts, .process_read_urb = ssu100_process_read_urb, .tiocmget = ssu100_tiocmget, -- cgit v1.2.3-55-g7522 From bf90ff5f3b8f67e5b42df4ea4fd543f8010a2676 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 16:31:33 +0200 Subject: USB: spcp8x5: fix port-data memory leak Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/spcp8x5.c | 46 +++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 9716efe92955..769c137f8975 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -157,13 +157,10 @@ struct spcp8x5_private { u8 line_status; }; -/* desc : when device plug in,this function would be called. - * thanks to usb_serial subsystem,then do almost every things for us. And what - * we should do just alloc the buffer */ -static int spcp8x5_startup(struct usb_serial *serial) +static int spcp8x5_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct spcp8x5_private *priv; - int i; enum spcp8x5_type type = SPCP825_007_TYPE; u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); @@ -180,34 +177,27 @@ static int spcp8x5_startup(struct usb_serial *serial) type = SPCP825_PHILIP_TYPE; dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type); - for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc(sizeof(struct spcp8x5_private), GFP_KERNEL); - if (!priv) - goto cleanup; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->delta_msr_wait); - priv->type = type; - usb_set_serial_port_data(serial->port[i] , priv); - } + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->delta_msr_wait); + priv->type = type; + + usb_set_serial_port_data(port , priv); return 0; -cleanup: - for (--i; i >= 0; --i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i] , NULL); - } - return -ENOMEM; } -/* call when the device plug out. free all the memory alloced by probe */ -static void spcp8x5_release(struct usb_serial *serial) +static int spcp8x5_port_remove(struct usb_serial_port *port) { - int i; + struct spcp8x5_private *priv; - for (i = 0; i < serial->num_ports; i++) - kfree(usb_get_serial_port_data(serial->port[i])); + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } /* set the modem control line of the device. @@ -649,8 +639,8 @@ static struct usb_serial_driver spcp8x5_device = { .ioctl = spcp8x5_ioctl, .tiocmget = spcp8x5_tiocmget, .tiocmset = spcp8x5_tiocmset, - .attach = spcp8x5_startup, - .release = spcp8x5_release, + .port_probe = spcp8x5_port_probe, + .port_remove = spcp8x5_port_remove, .process_read_urb = spcp8x5_process_read_urb, }; -- cgit v1.2.3-55-g7522 From 47b1e689db637ca6778c49d6c971af928cf0fb1d Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Mon, 8 Oct 2012 19:41:58 -0500 Subject: of/address: sparse fixes drivers/of/address.c:66:29: warning: incorrect type in argument 1 (different base types) drivers/of/address.c:66:29: expected restricted __be32 const [usertype] *cell drivers/of/address.c:66:29: got unsigned int [usertype] *addr drivers/of/address.c:87:32: warning: incorrect type in argument 1 (different base types) drivers/of/address.c:87:32: expected restricted __be32 const [usertype] *cell drivers/of/address.c:87:32: got unsigned int [usertype] *addr drivers/of/address.c:91:30: warning: incorrect type in assignment (different base types) drivers/of/address.c:91:30: expected unsigned int [unsigned] [usertype] drivers/of/address.c:91:30: got restricted __be32 [usertype] drivers/of/address.c:92:22: warning: incorrect type in assignment (different base types) drivers/of/address.c:92:22: expected unsigned int [unsigned] [usertype] drivers/of/address.c:92:22: got restricted __be32 [usertype] drivers/of/address.c:147:35: warning: incorrect type in argument 1 (different base types) drivers/of/address.c:147:35: expected restricted __be32 const [usertype] *addr drivers/of/address.c:147:35: got unsigned int [usertype] *addr drivers/of/address.c:157:34: warning: incorrect type in argument 1 (different base types) drivers/of/address.c:157:34: expected restricted __be32 const [usertype] *cell drivers/of/address.c:157:34: got unsigned int [usertype] * drivers/of/address.c:256:29: warning: restricted __be32 degrades to integer drivers/of/address.c:256:36: warning: restricted __be32 degrades to integer drivers/of/address.c:262:34: warning: incorrect type in argument 1 (different base types) drivers/of/address.c:262:34: expected restricted __be32 const [usertype] *cell drivers/of/address.c:262:34: got unsigned int [usertype] * drivers/of/address.c:372:41: warning: incorrect type in argument 1 (different base types) drivers/of/address.c:372:41: expected restricted __be32 const [usertype] *cell drivers/of/address.c:372:41: got unsigned int [usertype] *addr drivers/of/address.c:395:53: warning: incorrect type in argument 2 (different base types) drivers/of/address.c:395:53: expected restricted __be32 const [usertype] *addr drivers/of/address.c:395:53: got unsigned int [usertype] *addr drivers/of/address.c:443:50: warning: incorrect type in argument 2 (different base types) drivers/of/address.c:443:50: expected restricted __be32 const [usertype] *addr drivers/of/address.c:443:50: got unsigned int * drivers/of/address.c:455:49: warning: incorrect type in argument 1 (different base types) drivers/of/address.c:455:49: expected restricted __be32 const [usertype] *cell drivers/of/address.c:455:49: got unsigned int * drivers/of/address.c:480:60: warning: incorrect type in argument 2 (different base types) drivers/of/address.c:480:60: expected restricted __be32 const [usertype] *addr drivers/of/address.c:480:60: got unsigned int * drivers/of/address.c:412:5: warning: symbol '__of_translate_address' was not declared. Should it be static? drivers/of/address.c:520:14: error: symbol 'of_get_address' redeclared with different type (originally declared at include/linux/of_address.h:22) - different base types Signed-off-by: Kim Phillips Signed-off-by: Rob Herring --- drivers/of/address.c | 24 ++++++++++++------------ include/linux/of_address.h | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/of/address.c b/drivers/of/address.c index 72e496f1e9b0..0125524c08c4 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -37,9 +37,9 @@ struct of_bus { int (*match)(struct device_node *parent); void (*count_cells)(struct device_node *child, int *addrc, int *sizec); - u64 (*map)(u32 *addr, const __be32 *range, + u64 (*map)(__be32 *addr, const __be32 *range, int na, int ns, int pna); - int (*translate)(u32 *addr, u64 offset, int na); + int (*translate)(__be32 *addr, u64 offset, int na); unsigned int (*get_flags)(const __be32 *addr); }; @@ -56,7 +56,7 @@ static void of_bus_default_count_cells(struct device_node *dev, *sizec = of_n_size_cells(dev); } -static u64 of_bus_default_map(u32 *addr, const __be32 *range, +static u64 of_bus_default_map(__be32 *addr, const __be32 *range, int na, int ns, int pna) { u64 cp, s, da; @@ -82,7 +82,7 @@ static u64 of_bus_default_map(u32 *addr, const __be32 *range, return da - cp; } -static int of_bus_default_translate(u32 *addr, u64 offset, int na) +static int of_bus_default_translate(__be32 *addr, u64 offset, int na) { u64 a = of_read_number(addr, na); memset(addr, 0, na * 4); @@ -138,7 +138,7 @@ static unsigned int of_bus_pci_get_flags(const __be32 *addr) return flags; } -static u64 of_bus_pci_map(u32 *addr, const __be32 *range, int na, int ns, +static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns, int pna) { u64 cp, s, da; @@ -165,7 +165,7 @@ static u64 of_bus_pci_map(u32 *addr, const __be32 *range, int na, int ns, return da - cp; } -static int of_bus_pci_translate(u32 *addr, u64 offset, int na) +static int of_bus_pci_translate(__be32 *addr, u64 offset, int na) { return of_bus_default_translate(addr + 1, offset, na - 1); } @@ -247,7 +247,7 @@ static void of_bus_isa_count_cells(struct device_node *child, *sizec = 1; } -static u64 of_bus_isa_map(u32 *addr, const __be32 *range, int na, int ns, +static u64 of_bus_isa_map(__be32 *addr, const __be32 *range, int na, int ns, int pna) { u64 cp, s, da; @@ -270,7 +270,7 @@ static u64 of_bus_isa_map(u32 *addr, const __be32 *range, int na, int ns, return da - cp; } -static int of_bus_isa_translate(u32 *addr, u64 offset, int na) +static int of_bus_isa_translate(__be32 *addr, u64 offset, int na) { return of_bus_default_translate(addr + 1, offset, na - 1); } @@ -338,7 +338,7 @@ static struct of_bus *of_match_bus(struct device_node *np) } static int of_translate_one(struct device_node *parent, struct of_bus *bus, - struct of_bus *pbus, u32 *addr, + struct of_bus *pbus, __be32 *addr, int na, int ns, int pna, const char *rprop) { const __be32 *ranges; @@ -409,12 +409,12 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, * that can be mapped to a cpu physical address). This is not really specified * that way, but this is traditionally the way IBM at least do things */ -u64 __of_translate_address(struct device_node *dev, const __be32 *in_addr, - const char *rprop) +static u64 __of_translate_address(struct device_node *dev, + const __be32 *in_addr, const char *rprop) { struct device_node *parent = NULL; struct of_bus *bus, *pbus; - u32 addr[OF_MAX_ADDR_CELLS]; + __be32 addr[OF_MAX_ADDR_CELLS]; int na, ns, pna, pns; u64 result = OF_BAD_ADDR; diff --git a/include/linux/of_address.h b/include/linux/of_address.h index c3cdc1025c30..a1984dd037da 100644 --- a/include/linux/of_address.h +++ b/include/linux/of_address.h @@ -19,7 +19,7 @@ extern void __iomem *of_iomap(struct device_node *device, int index); * the address space flags too. The PCI version uses a BAR number * instead of an absolute index */ -extern const u32 *of_get_address(struct device_node *dev, int index, +extern const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, unsigned int *flags); #ifndef pci_address_to_pio @@ -44,7 +44,7 @@ static inline void __iomem *of_iomap(struct device_node *device, int index) { return NULL; } -static inline const u32 *of_get_address(struct device_node *dev, int index, +static inline const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, unsigned int *flags) { return NULL; -- cgit v1.2.3-55-g7522 From d2e4151821dc4d1db414de287f6e3503c1718815 Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Mon, 8 Oct 2012 19:42:04 -0500 Subject: of/irq: sparse fixes drivers/of/irq.c:195:57: warning: restricted __be32 degrades to integer drivers/of/irq.c:196:51: warning: restricted __be32 degrades to integer drivers/of/irq.c:199:57: warning: restricted __be32 degrades to integer drivers/of/irq.c:201:58: warning: restricted __be32 degrades to integer drivers/of/irq.c:470:37: warning: incorrect type in assignment (different modifiers) drivers/of/irq.c:470:37: expected int ( *[usertype] irq_init_cb )( ... ) drivers/of/irq.c:470:37: got void const *const data drivers/of/irq.c:96:5: error: symbol 'of_irq_map_raw' redeclared with different type (originally declared at include/linux/of_irq.h:61) - incompatible argument 2 (different base types) drivers/of/of_pci_irq.c:91:40: warning: incorrect type in argument 2 (different base types) drivers/of/of_pci_irq.c:91:40: expected unsigned int const [usertype] *intspec drivers/of/of_pci_irq.c:91:40: got restricted __be32 * drivers/of/of_pci_irq.c:91:53: warning: incorrect type in argument 4 (different base types) drivers/of/of_pci_irq.c:91:53: expected unsigned int const [usertype] *addr drivers/of/of_pci_irq.c:91:53: got restricted __be32 * Signed-off-by: Kim Phillips Signed-off-by: Rob Herring --- drivers/of/irq.c | 8 +++++--- include/linux/of_irq.h | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/of/irq.c b/drivers/of/irq.c index a23ec7779997..a3c1c5aae6a9 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -192,11 +192,13 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec, /* Compare specifiers */ match = 1; for (i = 0; i < addrsize && match; ++i) { - u32 mask = imask ? imask[i] : 0xffffffffu; + __be32 mask = imask ? imask[i] + : cpu_to_be32(0xffffffffu); match = ((addr[i] ^ imap[i]) & mask) == 0; } for (; i < (addrsize + intsize) && match; ++i) { - u32 mask = imask ? imask[i] : 0xffffffffu; + __be32 mask = imask ? imask[i] + : cpu_to_be32(0xffffffffu); match = ((intspec[i-addrsize] ^ imap[i]) & mask) == 0; } @@ -465,7 +467,7 @@ void __init of_irq_init(const struct of_device_id *matches) pr_debug("of_irq_init: init %s @ %p, parent %p\n", match->compatible, desc->dev, desc->interrupt_parent); - irq_init_cb = match->data; + irq_init_cb = (of_irq_init_cb_t)match->data; ret = irq_init_cb(desc->dev, desc->interrupt_parent); if (ret) { kfree(desc); diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h index b8e241125201..535cecf1e02f 100644 --- a/include/linux/of_irq.h +++ b/include/linux/of_irq.h @@ -58,8 +58,8 @@ static inline int of_irq_map_oldworld(struct device_node *device, int index, #endif /* CONFIG_PPC32 && CONFIG_PPC_PMAC */ -extern int of_irq_map_raw(struct device_node *parent, const u32 *intspec, - u32 ointsize, const u32 *addr, +extern int of_irq_map_raw(struct device_node *parent, const __be32 *intspec, + u32 ointsize, const __be32 *addr, struct of_irq *out_irq); extern int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq); -- cgit v1.2.3-55-g7522 From 24fb530f990394915e8daceeca2a4a4e929e156f Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Mon, 8 Oct 2012 19:42:11 -0500 Subject: of/platform: sparse fix drivers/of/platform.c:110:59: warning: incorrect type in argument 2 (different base types) drivers/of/platform.c:110:59: expected restricted __be32 const [usertype] *addr drivers/of/platform.c:110:59: got unsigned int const [usertype] *[assigned] reg Signed-off-by: Kim Phillips Signed-off-by: Rob Herring --- drivers/of/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 9bdeaf30b17d..b80891b43816 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -76,7 +76,7 @@ void of_device_make_bus_id(struct device *dev) { static atomic_t bus_no_reg_magic; struct device_node *node = dev->of_node; - const u32 *reg; + const __be32 *reg; u64 addr; const __be32 *addrp; int magic; -- cgit v1.2.3-55-g7522 From d7c4660c12adc5c66351253af381259686fa08a4 Mon Sep 17 00:00:00 2001 From: Bill Pemberton Date: Tue, 9 Oct 2012 14:18:19 -0400 Subject: staging: dgrp: check for NULL pointer in (un)register_proc_table register_proc_table and unregister_proc_table didn't deal with the possibility that the *table pointer could be NULL. Check for this and return if table is NULL. Reported-by: Fengguang Wu Signed-off-by: Bill Pemberton Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgrp/dgrp_specproc.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/dgrp/dgrp_specproc.c b/drivers/staging/dgrp/dgrp_specproc.c index a5840e7d6665..24327c3bad83 100644 --- a/drivers/staging/dgrp/dgrp_specproc.c +++ b/drivers/staging/dgrp/dgrp_specproc.c @@ -229,6 +229,9 @@ static void register_proc_table(struct dgrp_proc_entry *table, int len; mode_t mode; + if (table == NULL) + return; + for (; table->id; table++) { /* Can't do anything without a proc name. */ if (!table->name) @@ -297,6 +300,9 @@ static void unregister_proc_table(struct dgrp_proc_entry *table, struct proc_dir_entry *de; struct nd_struct *tmp; + if (table == NULL) + return; + list_for_each_entry(tmp, &nd_struct_list, list) { if ((table == dgrp_net_table) && (tmp->nd_net_de)) { unregister_dgrp_device(tmp->nd_net_de); -- cgit v1.2.3-55-g7522 From 178e485a0ebbfdb7165b4363d8fea2a07d650c0b Mon Sep 17 00:00:00 2001 From: Bill Pemberton Date: Tue, 9 Oct 2012 14:18:20 -0400 Subject: staging: dgrp: check return value of alloc_tty_driver alloc_tty_driver was always assumed to succeed. Add code to check the return value and return -ENOMEM if alloc_tty_driver fails. Reported-by: Fengguang Wu Signed-off-by: Bill Pemberton Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgrp/dgrp_tty.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/dgrp/dgrp_tty.c b/drivers/staging/dgrp/dgrp_tty.c index 72f6fcfa9878..e125b03598d7 100644 --- a/drivers/staging/dgrp/dgrp_tty.c +++ b/drivers/staging/dgrp/dgrp_tty.c @@ -3173,6 +3173,9 @@ dgrp_tty_init(struct nd_struct *nd) */ nd->nd_serial_ttdriver = alloc_tty_driver(CHAN_MAX); + if (!nd->nd_serial_ttdriver) + return -ENOMEM; + sprintf(nd->nd_serial_name, "tty_dgrp_%s_", id); nd->nd_serial_ttdriver->owner = THIS_MODULE; @@ -3232,6 +3235,9 @@ dgrp_tty_init(struct nd_struct *nd) } nd->nd_callout_ttdriver = alloc_tty_driver(CHAN_MAX); + if (!nd->nd_callout_ttdriver) + return -ENOMEM; + sprintf(nd->nd_callout_name, "cu_dgrp_%s_", id); nd->nd_callout_ttdriver->owner = THIS_MODULE; @@ -3269,6 +3275,9 @@ dgrp_tty_init(struct nd_struct *nd) nd->nd_xprint_ttdriver = alloc_tty_driver(CHAN_MAX); + if (!nd->nd_xprint_ttdriver) + return -ENOMEM; + sprintf(nd->nd_xprint_name, "pr_dgrp_%s_", id); nd->nd_xprint_ttdriver->owner = THIS_MODULE; -- cgit v1.2.3-55-g7522 From 0978c9499944d0670338fd048a3bdb1624dc66dc Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 18 Oct 2012 10:52:17 +0200 Subject: USB: iuu_phoenix: fix sysfs-attribute creation Make sure sysfs attributes are created at port probe. A recent patch ("USB: iuu_phoenix: fix port-data memory leak") removed the sysfs-attribute creation by mistake. Reported-by: Yuanhan Liu Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/iuu_phoenix.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 959f71e31dca..cd5533e81de7 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -53,6 +53,8 @@ static int iuu_cardout; static bool xmas; static int vcc_default = 5; +static int iuu_create_sysfs_attrs(struct usb_serial_port *port); +static int iuu_remove_sysfs_attrs(struct usb_serial_port *port); static void read_rxcmd_callback(struct urb *urb); struct iuu_private { @@ -75,6 +77,7 @@ struct iuu_private { static int iuu_port_probe(struct usb_serial_port *port) { struct iuu_private *priv; + int ret; priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL); if (!priv) @@ -99,6 +102,14 @@ static int iuu_port_probe(struct usb_serial_port *port) usb_set_serial_port_data(port, priv); + ret = iuu_create_sysfs_attrs(port); + if (ret) { + kfree(priv->writebuf); + kfree(priv->buf); + kfree(priv); + return ret; + } + return 0; } @@ -106,6 +117,7 @@ static int iuu_port_remove(struct usb_serial_port *port) { struct iuu_private *priv = usb_get_serial_port_data(port); + iuu_remove_sysfs_attrs(port); kfree(priv->writebuf); kfree(priv->buf); kfree(priv); @@ -1197,8 +1209,6 @@ static struct usb_serial_driver iuu_device = { .num_ports = 1, .bulk_in_size = 512, .bulk_out_size = 512, - .port_probe = iuu_create_sysfs_attrs, - .port_remove = iuu_remove_sysfs_attrs, .open = iuu_open, .close = iuu_close, .write = iuu_uart_write, -- cgit v1.2.3-55-g7522 From 5d8c61bc283826827e1f06816c146bfc507d3834 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 18 Oct 2012 11:43:28 +0200 Subject: USB: io_ti: fix sysfs-attribute creation Make sure port data is initialised before creating sysfs attributes to avoid a race. A recent patch ("USB: io_ti: fix port-data memory leak") got the sysfs-attribute creation and port-data initialisation ordering wrong. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_ti.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 9ae65d679f02..60023c2d2a31 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2578,13 +2578,6 @@ static int edge_port_probe(struct usb_serial_port *port) return -ENOMEM; } - ret = edge_create_sysfs_attrs(port); - if (ret) { - kfifo_free(&edge_port->write_fifo); - kfree(edge_port); - return ret; - } - spin_lock_init(&edge_port->ep_lock); edge_port->port = port; edge_port->edge_serial = usb_get_serial_data(port->serial); @@ -2592,6 +2585,13 @@ static int edge_port_probe(struct usb_serial_port *port) usb_set_serial_port_data(port, edge_port); + ret = edge_create_sysfs_attrs(port); + if (ret) { + kfifo_free(&edge_port->write_fifo); + kfree(edge_port); + return ret; + } + return 0; } -- cgit v1.2.3-55-g7522 From 470809741a28c3092279f4e1f3f432e534d46068 Mon Sep 17 00:00:00 2001 From: Alexis R. Cortes Date: Wed, 17 Oct 2012 14:09:12 -0500 Subject: usb: host: xhci: New system added for Compliance Mode Patch on SN65LVPE502CP This minor change adds a new system to which the "Fix Compliance Mode on SN65LVPE502CP Hardware" patch has to be applied also. System added: Vendor: Hewlett-Packard. System Model: Z1 Signed-off-by: Alexis R. Cortes Acked-by: Sarah Sharp Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 8d7fcbbe6ade..7d462bf20092 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -479,7 +479,8 @@ static bool compliance_mode_recovery_timer_quirk_check(void) if (strstr(dmi_product_name, "Z420") || strstr(dmi_product_name, "Z620") || - strstr(dmi_product_name, "Z820")) + strstr(dmi_product_name, "Z820") || + strstr(dmi_product_name, "Z1")) return true; return false; -- cgit v1.2.3-55-g7522 From 1452df6f1b7e396d89c2a1fdbdc0e0e839f97671 Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Thu, 18 Oct 2012 17:19:53 +0200 Subject: USB: option: blacklist net interface on ZTE devices Based on information from the ZTE Windows drivers. Cc: Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 68 ++++++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 30cff03e9f01..7e46894d784e 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -503,11 +503,19 @@ static const struct option_blacklist_info net_intf5_blacklist = { .reserved = BIT(5), }; +static const struct option_blacklist_info net_intf6_blacklist = { + .reserved = BIT(6), +}; + static const struct option_blacklist_info zte_mf626_blacklist = { .sendsetup = BIT(0) | BIT(1), .reserved = BIT(4), }; +static const struct option_blacklist_info zte_1255_blacklist = { + .reserved = BIT(3) | BIT(4), +}; + static const struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -853,13 +861,19 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0117, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0122, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf6_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) }, @@ -872,7 +886,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) }, @@ -886,7 +901,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) }, @@ -1002,18 +1018,24 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1169, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1170, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1244, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1246, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1248, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1249, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1250, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1251, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1253, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&zte_1255_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1257, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1258, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1259, 0xff, 0xff, 0xff) }, @@ -1071,15 +1093,21 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) }, -- cgit v1.2.3-55-g7522 From 4b35f1c52943851b310afb09047bfe991ac8f5ae Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Thu, 18 Oct 2012 17:14:17 +0200 Subject: USB: option: add more ZTE devices Cc: Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 7e46894d784e..54d4148d01d1 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -895,6 +895,12 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */ + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0199, 0xff, 0xff, 0xff), /* ZTE MF820S */ + .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */ + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff), @@ -903,6 +909,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1021, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) }, @@ -1080,8 +1088,16 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1401, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1424, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1425, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1426, 0xff, 0xff, 0xff), /* ZTE MF91 */ + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, -- cgit v1.2.3-55-g7522 From aa92b33c6b93b5ef4ccbaa72afa9c387a96c2ee2 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Fri, 12 Oct 2012 10:22:25 +0200 Subject: s390/cio: use generic bitmap functions Use generic bitmap functions in the subchannel id bitmap to simplify and de-bloat the code. Signed-off-by: Sebastian Ott Acked-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/idset.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/idset.c b/drivers/s390/cio/idset.c index e6d5f8c49524..f0973a04ec49 100644 --- a/drivers/s390/cio/idset.c +++ b/drivers/s390/cio/idset.c @@ -1,9 +1,10 @@ /* - * Copyright IBM Corp. 2007 + * Copyright IBM Corp. 2007, 2012 * Author(s): Peter Oberparleiter */ #include +#include #include #include "idset.h" #include "css.h" @@ -111,20 +112,13 @@ int idset_sch_get_first(struct idset *set, struct subchannel_id *schid) int idset_is_empty(struct idset *set) { - int bitnum; - - bitnum = find_first_bit(set->bitmap, set->num_ssid * set->num_id); - if (bitnum >= set->num_ssid * set->num_id) - return 1; - return 0; + return bitmap_empty(set->bitmap, set->num_ssid * set->num_id); } void idset_add_set(struct idset *to, struct idset *from) { - unsigned long i, len; + int len = min(__BITOPS_WORDS(to->num_ssid * to->num_id), + __BITOPS_WORDS(from->num_ssid * from->num_id)); - len = min(__BITOPS_WORDS(to->num_ssid * to->num_id), - __BITOPS_WORDS(from->num_ssid * from->num_id)); - for (i = 0; i < len ; i++) - to->bitmap[i] |= from->bitmap[i]; + bitmap_or(to->bitmap, to->bitmap, from->bitmap, len); } -- cgit v1.2.3-55-g7522 From cec8546638dc634824b629e33968d6c68f8b07d6 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Mon, 15 Oct 2012 12:24:56 +0200 Subject: s390/css: stop stsch loop after cc 3 Receiving cc=3 from store subchannel means 2 things: * the subchannel is not provided * there are no further subchannels in this subchannel set With this patch we abort the store subchannel loop after cc=3 (or an exception) and clear the subsequent bits in the subchannel id set. Reported-by: Cornelia Huck Signed-off-by: Sebastian Ott Acked-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/css.c | 7 ++++++- drivers/s390/cio/idset.c | 8 ++++++++ drivers/s390/cio/idset.h | 3 ++- 3 files changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index b4d572f65f07..fd00afd8b850 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -377,7 +377,11 @@ static int css_evaluate_new_subchannel(struct subchannel_id schid, int slow) /* Will be done on the slow path. */ return -EAGAIN; } - if (stsch_err(schid, &schib) || !css_sch_is_valid(&schib)) { + if (stsch_err(schid, &schib)) { + /* Subchannel is not provided. */ + return -ENXIO; + } + if (!css_sch_is_valid(&schib)) { /* Unusable - ignore. */ return 0; } @@ -536,6 +540,7 @@ static int slow_eval_unknown_fn(struct subchannel_id schid, void *data) case -ENOMEM: case -EIO: /* These should abort looping */ + idset_sch_del_subseq(slow_subchannel_set, schid); break; default: rc = 0; diff --git a/drivers/s390/cio/idset.c b/drivers/s390/cio/idset.c index f0973a04ec49..199bc6791177 100644 --- a/drivers/s390/cio/idset.c +++ b/drivers/s390/cio/idset.c @@ -90,6 +90,14 @@ void idset_sch_del(struct idset *set, struct subchannel_id schid) idset_del(set, schid.ssid, schid.sch_no); } +/* Clear ids starting from @schid up to end of subchannel set. */ +void idset_sch_del_subseq(struct idset *set, struct subchannel_id schid) +{ + int pos = schid.ssid * set->num_id + schid.sch_no; + + bitmap_clear(set->bitmap, pos, set->num_id - schid.sch_no); +} + int idset_sch_contains(struct idset *set, struct subchannel_id schid) { return idset_contains(set, schid.ssid, schid.sch_no); diff --git a/drivers/s390/cio/idset.h b/drivers/s390/cio/idset.h index 3d943f03591e..06d3bc01bb09 100644 --- a/drivers/s390/cio/idset.h +++ b/drivers/s390/cio/idset.h @@ -1,5 +1,5 @@ /* - * Copyright IBM Corp. 2007 + * Copyright IBM Corp. 2007, 2012 * Author(s): Peter Oberparleiter */ @@ -17,6 +17,7 @@ void idset_fill(struct idset *set); struct idset *idset_sch_new(void); void idset_sch_add(struct idset *set, struct subchannel_id id); void idset_sch_del(struct idset *set, struct subchannel_id id); +void idset_sch_del_subseq(struct idset *set, struct subchannel_id schid); int idset_sch_contains(struct idset *set, struct subchannel_id id); int idset_sch_get_first(struct idset *set, struct subchannel_id *id); int idset_is_empty(struct idset *set); -- cgit v1.2.3-55-g7522 From 8a095030f7551d07860fd54890d1bcdc77630c29 Mon Sep 17 00:00:00 2001 From: Doug Ledford Date: Wed, 17 Oct 2012 03:23:55 +0000 Subject: IB/mlx4: Fix build error on platforms where UL is not 64 bits Line 110 uses UL as a compiler cast for the 0x constant, but it's not large enough to hold a 64-bit value on a 32-bit arch. Signed-off-by: Doug Ledford [ Use "-1" instead of "FFFFFFFFFFFFFFFFULL". - Roland ] Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx4/alias_GUID.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx4/alias_GUID.c b/drivers/infiniband/hw/mlx4/alias_GUID.c index d2fb38d43571..2f215b93db6b 100644 --- a/drivers/infiniband/hw/mlx4/alias_GUID.c +++ b/drivers/infiniband/hw/mlx4/alias_GUID.c @@ -107,7 +107,7 @@ static __be64 get_cached_alias_guid(struct mlx4_ib_dev *dev, int port, int index { if (index >= NUM_ALIAS_GUID_PER_PORT) { pr_err("%s: ERROR: asked for index:%d\n", __func__, index); - return (__force __be64) ((u64) 0xFFFFFFFFFFFFFFFFUL); + return (__force __be64) -1; } return *(__be64 *)&dev->sriov.demux[port - 1].guid_cache[index]; } -- cgit v1.2.3-55-g7522 From 2c75d2ccb6e5ffb96ce8624ef4c1f7ba5bd96499 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Wed, 17 Oct 2012 16:42:58 +0000 Subject: IB/mlx4: Fix QP1 P_Key processing in the Primary Physical Function (PPF) In the MAD paravirtualization code, one of the checks performed when forwarding QP1 (GSI) packets from wire to slave was a P_Key check: the P_Key received in the MAD must be present in the guest's paravirtualized P_Key table, and at least one of the (packet P_Key, guest P_Key) must be a full-membership P_Key. However, if everyone involved has only limited membership in the default P_Key, then packets sent by full-member remote hosts arrive at the PPF but are not passed on to the VFs with the current P_Key1 check. Fix this as follows: 1. Don't care if P_Key received over wire is full or not. If it successfully passed HW checks on the real QP1, then simply pass it to guest regardless of whether the guest has full or limited membership in its P_Key table. 2. If the guest (including paravirtualized master) has both full and limited P_Key forms in its table, preferentially pass the paravirtualized P_Key index of the full P_Key form in the tunnel header. 3. In the multicast join flow (mlx4/mcg.c), use the index for the default P_Key (wherever it is located) in replies generated from within the mcg module (previously, P_Key index 0 was used in all cases). Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx4/mad.c | 85 +++++++++++++++++++--------------------- drivers/infiniband/hw/mlx4/mcg.c | 3 +- 2 files changed, 42 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 21a794152d15..0a903c129f0a 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -409,38 +409,45 @@ int mlx4_ib_find_real_gid(struct ib_device *ibdev, u8 port, __be64 guid) } -static int get_pkey_phys_indices(struct mlx4_ib_dev *ibdev, u8 port, u8 ph_pkey_ix, - u8 *full_pk_ix, u8 *partial_pk_ix, - int *is_full_member) +static int find_slave_port_pkey_ix(struct mlx4_ib_dev *dev, int slave, + u8 port, u16 pkey, u16 *ix) { - u16 search_pkey; - int fm; - int err = 0; - u16 pk; + int i, ret; + u8 unassigned_pkey_ix, pkey_ix, partial_ix = 0xFF; + u16 slot_pkey; - err = ib_get_cached_pkey(&ibdev->ib_dev, port, ph_pkey_ix, &search_pkey); - if (err) - return err; + if (slave == mlx4_master_func_num(dev->dev)) + return ib_find_cached_pkey(&dev->ib_dev, port, pkey, ix); - fm = (search_pkey & 0x8000) ? 1 : 0; - if (fm) { - *full_pk_ix = ph_pkey_ix; - search_pkey &= 0x7FFF; - } else { - *partial_pk_ix = ph_pkey_ix; - search_pkey |= 0x8000; - } + unassigned_pkey_ix = dev->dev->phys_caps.pkey_phys_table_len[port] - 1; - if (ib_find_exact_cached_pkey(&ibdev->ib_dev, port, search_pkey, &pk)) - pk = 0xFFFF; + for (i = 0; i < dev->dev->caps.pkey_table_len[port]; i++) { + if (dev->pkeys.virt2phys_pkey[slave][port - 1][i] == unassigned_pkey_ix) + continue; - if (fm) - *partial_pk_ix = (pk & 0xFF); - else - *full_pk_ix = (pk & 0xFF); + pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][i]; - *is_full_member = fm; - return err; + ret = ib_get_cached_pkey(&dev->ib_dev, port, pkey_ix, &slot_pkey); + if (ret) + continue; + if ((slot_pkey & 0x7FFF) == (pkey & 0x7FFF)) { + if (slot_pkey & 0x8000) { + *ix = (u16) pkey_ix; + return 0; + } else { + /* take first partial pkey index found */ + if (partial_ix == 0xFF) + partial_ix = pkey_ix; + } + } + } + + if (partial_ix < 0xFF) { + *ix = (u16) partial_ix; + return 0; + } + + return -EINVAL; } int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port, @@ -458,10 +465,8 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port, unsigned tun_tx_ix = 0; int dqpn; int ret = 0; - int i; - int is_full_member = 0; u16 tun_pkey_ix; - u8 ph_pkey_ix, full_pk_ix = 0, partial_pk_ix = 0; + u16 cached_pkey; if (dest_qpt > IB_QPT_GSI) return -EINVAL; @@ -481,27 +486,17 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port, else tun_qp = &tun_ctx->qp[1]; - /* compute pkey index for slave */ - /* get physical pkey -- virtualized Dom0 pkey to phys*/ + /* compute P_Key index to put in tunnel header for slave */ if (dest_qpt) { - ph_pkey_ix = - dev->pkeys.virt2phys_pkey[mlx4_master_func_num(dev->dev)][port - 1][wc->pkey_index]; - - /* now, translate this to the slave pkey index */ - ret = get_pkey_phys_indices(dev, port, ph_pkey_ix, &full_pk_ix, - &partial_pk_ix, &is_full_member); + u16 pkey_ix; + ret = ib_get_cached_pkey(&dev->ib_dev, port, wc->pkey_index, &cached_pkey); if (ret) return -EINVAL; - for (i = 0; i < dev->dev->caps.pkey_table_len[port]; i++) { - if ((dev->pkeys.virt2phys_pkey[slave][port - 1][i] == full_pk_ix) || - (is_full_member && - (dev->pkeys.virt2phys_pkey[slave][port - 1][i] == partial_pk_ix))) - break; - } - if (i == dev->dev->caps.pkey_table_len[port]) + ret = find_slave_port_pkey_ix(dev, slave, port, cached_pkey, &pkey_ix); + if (ret) return -EINVAL; - tun_pkey_ix = i; + tun_pkey_ix = pkey_ix; } else tun_pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][0]; diff --git a/drivers/infiniband/hw/mlx4/mcg.c b/drivers/infiniband/hw/mlx4/mcg.c index 3c3b54c3fdd9..44ff480f79f5 100644 --- a/drivers/infiniband/hw/mlx4/mcg.c +++ b/drivers/infiniband/hw/mlx4/mcg.c @@ -233,7 +233,8 @@ static int send_mad_to_slave(int slave, struct mlx4_ib_demux_ctx *ctx, ib_query_ah(dev->sm_ah[ctx->port - 1], &ah_attr); - wc.pkey_index = 0; + if (ib_find_cached_pkey(&dev->ib_dev, ctx->port, IB_DEFAULT_PKEY_FULL, &wc.pkey_index)) + return -EINVAL; wc.sl = 0; wc.dlid_path_bits = 0; wc.port_num = ctx->port; -- cgit v1.2.3-55-g7522 From bef83ed92caca45a394344a14b0234aea977da6e Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Wed, 17 Oct 2012 16:42:59 +0000 Subject: IB/mlx4: Synchronize cleanup of MCGs in MCG paravirtualization A client re-register event invokes cleanup of all MCGs. This is required to protect against misbehaved guests leading to corruption of join/leave database. However, since cleaning up the MCGs is a heavy operation, it is pushed to a work queue for further processing. Client re-register is also propagated to ULPs (e.g IPoIB). However, since the cleanup is performed in a workqueue, the ULP could leave and re-join groups before the cleanup occurs. In this case, when the cleanup takes place, it prunes the (newly-joined) MCGs and the ULP is left without actual MCGs while believing it joined them. Fix this by setting the flushing flag before invoking the cleanup task and clearing it after flushing is complete. Signed-off-by: Eli Cohen Reviewed-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx4/mcg.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx4/mcg.c b/drivers/infiniband/hw/mlx4/mcg.c index 44ff480f79f5..25b2cdff00f8 100644 --- a/drivers/infiniband/hw/mlx4/mcg.c +++ b/drivers/infiniband/hw/mlx4/mcg.c @@ -1075,10 +1075,6 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy unsigned long end; int count; - if (ctx->flushing) - return; - - ctx->flushing = 1; for (i = 0; i < MAX_VFS; ++i) clean_vf_mcast(ctx, i); @@ -1108,9 +1104,6 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy force_clean_group(group); } mutex_unlock(&ctx->mcg_table_lock); - - if (!destroy_wq) - ctx->flushing = 0; } struct clean_work { @@ -1124,6 +1117,7 @@ static void mcg_clean_task(struct work_struct *work) struct clean_work *cw = container_of(work, struct clean_work, work); _mlx4_ib_mcg_port_cleanup(cw->ctx, cw->destroy_wq); + cw->ctx->flushing = 0; kfree(cw); } @@ -1131,13 +1125,20 @@ void mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy_wq) { struct clean_work *work; + if (ctx->flushing) + return; + + ctx->flushing = 1; + if (destroy_wq) { _mlx4_ib_mcg_port_cleanup(ctx, destroy_wq); + ctx->flushing = 0; return; } work = kmalloc(sizeof *work, GFP_KERNEL); if (!work) { + ctx->flushing = 0; mcg_warn("failed allocating work for cleanup\n"); return; } -- cgit v1.2.3-55-g7522 From 7ae9d71e8df27a3ab60a05ae3add08728debc09c Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Thu, 18 Oct 2012 17:07:01 +0800 Subject: pinctrl: remove mutex lock in groups show Mutex is locked duplicatly by pinconf_groups_show() and pin_config_group_get(). It results dead lock. So avoid to lock mutex in pinconf_groups_show(). Cc: stable@kernel.org Signed-off-by: Haojian Zhuang Signed-off-by: Linus Walleij --- drivers/pinctrl/pinconf.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index 43f474cdc110..baee2cc46a17 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -537,8 +537,6 @@ static int pinconf_groups_show(struct seq_file *s, void *what) seq_puts(s, "Pin config settings per pin group\n"); seq_puts(s, "Format: group (name): configs\n"); - mutex_lock(&pinctrl_mutex); - while (selector < ngroups) { const char *gname = pctlops->get_group_name(pctldev, selector); @@ -549,8 +547,6 @@ static int pinconf_groups_show(struct seq_file *s, void *what) selector++; } - mutex_unlock(&pinctrl_mutex); - return 0; } -- cgit v1.2.3-55-g7522 From af1b85e49089f945deb46258b0fc4bc9910afb22 Mon Sep 17 00:00:00 2001 From: Jay Purohit Date: Sun, 14 Oct 2012 07:07:21 +0000 Subject: usb/ipheth: Add iPhone 5 support I noticed that the iPhone ethernet driver did not support iPhone 5. I quickly added support to it in my kernel, here's a patch. Signed-off-by: Jay Purohit Acked-by: Valdis Kletnieks Signed-off-by: Jan Ceuleers Signed-off-by: David S. Miller --- drivers/net/usb/ipheth.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index a28a983d465e..534d8becbbdc 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -62,6 +62,7 @@ #define USB_PRODUCT_IPAD 0x129a #define USB_PRODUCT_IPHONE_4_VZW 0x129c #define USB_PRODUCT_IPHONE_4S 0x12a0 +#define USB_PRODUCT_IPHONE_5 0x12a8 #define IPHETH_USBINTF_CLASS 255 #define IPHETH_USBINTF_SUBCLASS 253 @@ -113,6 +114,10 @@ static struct usb_device_id ipheth_table[] = { USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S, IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, IPHETH_USBINTF_PROTO) }, + { USB_DEVICE_AND_INTERFACE_INFO( + USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_5, + IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, + IPHETH_USBINTF_PROTO) }, { } }; MODULE_DEVICE_TABLE(usb, ipheth_table); -- cgit v1.2.3-55-g7522 From 0ca7111a38f053ae7b8829ee32fca6f9ef47550a Mon Sep 17 00:00:00 2001 From: Matus Ujhelyi Date: Sun, 14 Oct 2012 19:07:16 +0000 Subject: phy: add AT803x driver This driver add support for wake over lan on AT803x phys. Signed-off-by: Matus Ujhelyi Signed-off-by: David S. Miller --- drivers/net/phy/Kconfig | 5 ++ drivers/net/phy/Makefile | 1 + drivers/net/phy/at803x.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 drivers/net/phy/at803x.c (limited to 'drivers') diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 983bbf4d5ef6..961f0b293913 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -15,6 +15,11 @@ if PHYLIB comment "MII PHY device drivers" +config AT803X_PHY + tristate "Drivers for Atheros AT803X PHYs" + ---help--- + Currently supports the AT8030 and AT8035 model + config AMD_PHY tristate "Drivers for the AMD PHYs" ---help--- diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 426674debae4..9645e389a58d 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_STE10XP) += ste10Xp.o obj-$(CONFIG_MICREL_PHY) += micrel.o obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o +obj-$(CONFIG_AT803X_PHY) += at803x.o obj-$(CONFIG_AMD_PHY) += amd.o obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c new file mode 100644 index 000000000000..45cbc10de01c --- /dev/null +++ b/drivers/net/phy/at803x.c @@ -0,0 +1,176 @@ +/* + * drivers/net/phy/at803x.c + * + * Driver for Atheros 803x PHY + * + * Author: Matus Ujhelyi + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include + +#define AT803X_INTR_ENABLE 0x12 +#define AT803X_INTR_STATUS 0x13 +#define AT803X_WOL_ENABLE 0x01 +#define AT803X_DEVICE_ADDR 0x03 +#define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C +#define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B +#define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A +#define AT803X_MMD_ACCESS_CONTROL 0x0D +#define AT803X_MMD_ACCESS_CONTROL_DATA 0x0E +#define AT803X_FUNC_DATA 0x4003 + +MODULE_DESCRIPTION("Atheros 803x PHY driver"); +MODULE_AUTHOR("Matus Ujhelyi"); +MODULE_LICENSE("GPL"); + +static void at803x_set_wol_mac_addr(struct phy_device *phydev) +{ + struct net_device *ndev = phydev->attached_dev; + const u8 *mac; + unsigned int i, offsets[] = { + AT803X_LOC_MAC_ADDR_32_47_OFFSET, + AT803X_LOC_MAC_ADDR_16_31_OFFSET, + AT803X_LOC_MAC_ADDR_0_15_OFFSET, + }; + + if (!ndev) + return; + + mac = (const u8 *) ndev->dev_addr; + + if (!is_valid_ether_addr(mac)) + return; + + for (i = 0; i < 3; i++) { + phy_write(phydev, AT803X_MMD_ACCESS_CONTROL, + AT803X_DEVICE_ADDR); + phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA, + offsets[i]); + phy_write(phydev, AT803X_MMD_ACCESS_CONTROL, + AT803X_FUNC_DATA); + phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA, + mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); + } +} + +static int at803x_config_init(struct phy_device *phydev) +{ + int val; + u32 features; + int status; + + features = SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_AUI | + SUPPORTED_FIBRE | SUPPORTED_BNC; + + val = phy_read(phydev, MII_BMSR); + if (val < 0) + return val; + + if (val & BMSR_ANEGCAPABLE) + features |= SUPPORTED_Autoneg; + if (val & BMSR_100FULL) + features |= SUPPORTED_100baseT_Full; + if (val & BMSR_100HALF) + features |= SUPPORTED_100baseT_Half; + if (val & BMSR_10FULL) + features |= SUPPORTED_10baseT_Full; + if (val & BMSR_10HALF) + features |= SUPPORTED_10baseT_Half; + + if (val & BMSR_ESTATEN) { + val = phy_read(phydev, MII_ESTATUS); + if (val < 0) + return val; + + if (val & ESTATUS_1000_TFULL) + features |= SUPPORTED_1000baseT_Full; + if (val & ESTATUS_1000_THALF) + features |= SUPPORTED_1000baseT_Half; + } + + phydev->supported = features; + phydev->advertising = features; + + /* enable WOL */ + at803x_set_wol_mac_addr(phydev); + status = phy_write(phydev, AT803X_INTR_ENABLE, AT803X_WOL_ENABLE); + status = phy_read(phydev, AT803X_INTR_STATUS); + + return 0; +} + +/* ATHEROS 8035 */ +static struct phy_driver at8035_driver = { + .phy_id = 0x004dd072, + .name = "Atheros 8035 ethernet", + .phy_id_mask = 0xffffffef, + .config_init = at803x_config_init, + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .driver = { + .owner = THIS_MODULE, + }, +}; + +/* ATHEROS 8030 */ +static struct phy_driver at8030_driver = { + .phy_id = 0x004dd076, + .name = "Atheros 8030 ethernet", + .phy_id_mask = 0xffffffef, + .config_init = at803x_config_init, + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .driver = { + .owner = THIS_MODULE, + }, +}; + +static int __init atheros_init(void) +{ + int ret; + + ret = phy_driver_register(&at8035_driver); + if (ret) + goto err1; + + ret = phy_driver_register(&at8030_driver); + if (ret) + goto err2; + + return 0; + +err2: + phy_driver_unregister(&at8035_driver); +err1: + return ret; +} + +static void __exit atheros_exit(void) +{ + phy_driver_unregister(&at8035_driver); + phy_driver_unregister(&at8030_driver); +} + +module_init(atheros_init); +module_exit(atheros_exit); + +static struct mdio_device_id __maybe_unused atheros_tbl[] = { + { 0x004dd076, 0xffffffef }, + { 0x004dd072, 0xffffffef }, + { } +}; + +MODULE_DEVICE_TABLE(mdio, atheros_tbl); -- cgit v1.2.3-55-g7522 From c6846ee148e07e4cfae4de486532efb02d238938 Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Thu, 18 Oct 2012 05:11:29 +0000 Subject: net: qmi_wwan: adding more ZTE devices Analyzed a few Windows driver description files, supporting this long list of devices: %ztewwan.DeviceDesc0002% = ztewwan.ndi, USB\VID_19D2&PID_0002&MI_01 %ztewwan.DeviceDesc0012% = ztewwan.ndi, USB\VID_19D2&PID_0012&MI_01 %ztewwan.DeviceDesc0017% = ztewwan.ndi, USB\VID_19D2&PID_0017&MI_03 %ztewwan.DeviceDesc0021% = ztewwan.ndi, USB\VID_19D2&PID_0021&MI_04 %ztewwan.DeviceDesc0025% = ztewwan.ndi, USB\VID_19D2&PID_0025&MI_01 %ztewwan.DeviceDesc0031% = ztewwan.ndi, USB\VID_19D2&PID_0031&MI_04 %ztewwan.DeviceDesc0042% = ztewwan.ndi, USB\VID_19D2&PID_0042&MI_04 %ztewwan.DeviceDesc0049% = ztewwan.ndi, USB\VID_19D2&PID_0049&MI_05 %ztewwan.DeviceDesc0052% = ztewwan.ndi, USB\VID_19D2&PID_0052&MI_04 %ztewwan.DeviceDesc0055% = ztewwan.ndi, USB\VID_19D2&PID_0055&MI_01 %ztewwan.DeviceDesc0058% = ztewwan.ndi, USB\VID_19D2&PID_0058&MI_04 %ztewwan.DeviceDesc0063% = ztewwan.ndi, USB\VID_19D2&PID_0063&MI_04 %ztewwan.DeviceDesc2002% = ztewwan.ndi, USB\VID_19D2&PID_2002&MI_04 %ztewwan.DeviceDesc0104% = ztewwan.ndi, USB\VID_19D2&PID_0104&MI_04 %ztewwan.DeviceDesc0113% = ztewwan.ndi, USB\VID_19D2&PID_0113&MI_05 %ztewwan.DeviceDesc0118% = ztewwan.ndi, USB\VID_19D2&PID_0118&MI_05 %ztewwan.DeviceDesc0121% = ztewwan.ndi, USB\VID_19D2&PID_0121&MI_05 %ztewwan.DeviceDesc0123% = ztewwan.ndi, USB\VID_19D2&PID_0123&MI_04 %ztewwan.DeviceDesc0124% = ztewwan.ndi, USB\VID_19D2&PID_0124&MI_05 %ztewwan.DeviceDesc0125% = ztewwan.ndi, USB\VID_19D2&PID_0125&MI_06 %ztewwan.DeviceDesc0126% = ztewwan.ndi, USB\VID_19D2&PID_0126&MI_05 %ztewwan.DeviceDesc1008% = ztewwan.ndi, USB\VID_19D2&PID_1008&MI_04 %ztewwan.DeviceDesc1010% = ztewwan.ndi, USB\VID_19D2&PID_1010&MI_04 %ztewwan.DeviceDesc1012% = ztewwan.ndi, USB\VID_19D2&PID_1012&MI_04 %ztewwan.DeviceDesc1402% = ztewwan.ndi, USB\VID_19D2&PID_1402&MI_02 %ztewwan.DeviceDesc0157% = ztewwan.ndi, USB\VID_19D2&PID_0157&MI_05 %ztewwan.DeviceDesc0158% = ztewwan.ndi, USB\VID_19D2&PID_0158&MI_03 %ztewwan.DeviceDesc1401% = ztewwan.ndi, USB\VID_19D2&PID_1401&MI_02 %ztewwan.DeviceDesc0130% = ztewwan.ndi, USB\VID_19D2&PID_0130&MI_01 %ztewwan.DeviceDesc0133% = ztewwan.ndi, USB\VID_19D2&PID_0133&MI_03 %ztewwan.DeviceDesc0176% = ztewwan.ndi, USB\VID_19D2&PID_0176&MI_03 %ztewwan.DeviceDesc0178% = ztewwan.ndi, USB\VID_19D2&PID_0178&MI_03 %ztewwan.DeviceDesc0168% = ztewwan.ndi, USB\VID_19D2&PID_0168&MI_04 ;EuFi890 %ztewwan.DeviceDesc0191% = ztewwan.ndi, USB\VID_19D2&PID_0191&MI_04 ;AL621 %ztewwan.DeviceDesc0167% = ztewwan.ndi, USB\VID_19D2&PID_0167&MI_04 ;MF821 %ztewwan.DeviceDesc0199% = ztewwan.ndi, USB\VID_19D2&PID_0199&MI_01 %ztewwan.DeviceDesc0200% = ztewwan.ndi, USB\VID_19D2&PID_0200&MI_01 %ztewwan.DeviceDesc0257% = ztewwan.ndi, USB\VID_19D2&PID_0257&MI_03 ;MF821V %ztewwan.DeviceDesc1018% = ztewwan.ndi, USB\VID_19D2&PID_1018&MI_03 ;MF91 %ztewwan.DeviceDesc1426% = ztewwan.ndi, USB\VID_19D2&PID_1426&MI_02 ;0141 %ztewwan.DeviceDesc1247% = ztewwan.ndi, USB\VID_19D2&PID_1247&MI_04 %ztewwan.DeviceDesc1425% = ztewwan.ndi, USB\VID_19D2&PID_1425&MI_02 %ztewwan.DeviceDesc1424% = ztewwan.ndi, USB\VID_19D2&PID_1424&MI_02 %ztewwan.DeviceDesc1252% = ztewwan.ndi, USB\VID_19D2&PID_1252&MI_04 %ztewwan.DeviceDesc1254% = ztewwan.ndi, USB\VID_19D2&PID_1254&MI_04 %ztewwan.DeviceDesc1255A% = ztewwan.ndi, USB\VID_19D2&PID_1255&MI_03 %ztewwan.DeviceDesc1255B% = ztewwan.ndi, USB\VID_19D2&PID_1255&MI_04 %ztewwan.DeviceDesc1256% = ztewwan.ndi, USB\VID_19D2&PID_1256&MI_04 %ztewwan.DeviceDesc1245% = ztewwanCombB.ndi, USB\VID_19D2&PID_1245&MI_04 %ztewwan.DeviceDesc1021% = ztewwan.ndi, USB\VID_19D2&PID_1021&MI_02 Adding the ones we were missing. Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'drivers') diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 6883c371c59f..9d23ba2fe981 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -371,16 +371,57 @@ static const struct usb_device_id products[] = { }, /* 3. Combined interface devices matching on interface number */ + {QMI_FIXED_INTF(0x19d2, 0x0002, 1)}, + {QMI_FIXED_INTF(0x19d2, 0x0012, 1)}, + {QMI_FIXED_INTF(0x19d2, 0x0017, 3)}, + {QMI_FIXED_INTF(0x19d2, 0x0021, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x0025, 1)}, + {QMI_FIXED_INTF(0x19d2, 0x0031, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x0042, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x0049, 5)}, + {QMI_FIXED_INTF(0x19d2, 0x0052, 4)}, {QMI_FIXED_INTF(0x19d2, 0x0055, 1)}, /* ZTE (Vodafone) K3520-Z */ + {QMI_FIXED_INTF(0x19d2, 0x0058, 4)}, {QMI_FIXED_INTF(0x19d2, 0x0063, 4)}, /* ZTE (Vodafone) K3565-Z */ {QMI_FIXED_INTF(0x19d2, 0x0104, 4)}, /* ZTE (Vodafone) K4505-Z */ + {QMI_FIXED_INTF(0x19d2, 0x0113, 5)}, + {QMI_FIXED_INTF(0x19d2, 0x0118, 5)}, + {QMI_FIXED_INTF(0x19d2, 0x0121, 5)}, + {QMI_FIXED_INTF(0x19d2, 0x0123, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x0124, 5)}, + {QMI_FIXED_INTF(0x19d2, 0x0125, 6)}, + {QMI_FIXED_INTF(0x19d2, 0x0126, 5)}, + {QMI_FIXED_INTF(0x19d2, 0x0130, 1)}, + {QMI_FIXED_INTF(0x19d2, 0x0133, 3)}, + {QMI_FIXED_INTF(0x19d2, 0x0141, 5)}, {QMI_FIXED_INTF(0x19d2, 0x0157, 5)}, /* ZTE MF683 */ + {QMI_FIXED_INTF(0x19d2, 0x0158, 3)}, {QMI_FIXED_INTF(0x19d2, 0x0167, 4)}, /* ZTE MF820D */ + {QMI_FIXED_INTF(0x19d2, 0x0168, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x0176, 3)}, + {QMI_FIXED_INTF(0x19d2, 0x0178, 3)}, + {QMI_FIXED_INTF(0x19d2, 0x0191, 4)}, /* ZTE EuFi890 */ + {QMI_FIXED_INTF(0x19d2, 0x0199, 1)}, /* ZTE MF820S */ + {QMI_FIXED_INTF(0x19d2, 0x0200, 1)}, + {QMI_FIXED_INTF(0x19d2, 0x0257, 3)}, /* ZTE MF821 */ {QMI_FIXED_INTF(0x19d2, 0x0326, 4)}, /* ZTE MF821D */ {QMI_FIXED_INTF(0x19d2, 0x1008, 4)}, /* ZTE (Vodafone) K3570-Z */ {QMI_FIXED_INTF(0x19d2, 0x1010, 4)}, /* ZTE (Vodafone) K3571-Z */ + {QMI_FIXED_INTF(0x19d2, 0x1012, 4)}, {QMI_FIXED_INTF(0x19d2, 0x1018, 3)}, /* ZTE (Vodafone) K5006-Z */ + {QMI_FIXED_INTF(0x19d2, 0x1021, 2)}, + {QMI_FIXED_INTF(0x19d2, 0x1245, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x1247, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x1252, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x1254, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x1255, 3)}, + {QMI_FIXED_INTF(0x19d2, 0x1255, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x1256, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x1401, 2)}, {QMI_FIXED_INTF(0x19d2, 0x1402, 2)}, /* ZTE MF60 */ + {QMI_FIXED_INTF(0x19d2, 0x1424, 2)}, + {QMI_FIXED_INTF(0x19d2, 0x1425, 2)}, + {QMI_FIXED_INTF(0x19d2, 0x1426, 2)}, /* ZTE MF91 */ {QMI_FIXED_INTF(0x19d2, 0x2002, 4)}, /* ZTE (Vodafone) K3765-Z */ {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)}, /* Sierra Wireless MC7700 */ {QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */ -- cgit v1.2.3-55-g7522 From 8735cf94afc1a63526417762c288501fc239c12d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 15 Oct 2012 10:35:00 +0100 Subject: staging:iio: Fix adis16201 channel offsets and scales Most of the channel offsets and scales in the adis16201 are incorrect: * Temperature scale is off by a factor of 1000 * Voltage scale is off by a factor of 1000 * Acceleration scale is in g instead of m/(s**2) * Temperature offset is completely wrong This patch fixes these issues. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16201_core.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c index 8e37d6e04277..b12ca68cd9e4 100644 --- a/drivers/staging/iio/accel/adis16201_core.c +++ b/drivers/staging/iio/accel/adis16201_core.c @@ -310,30 +310,32 @@ static int adis16201_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: - *val = 0; - if (chan->channel == 0) - *val2 = 1220; - else - *val2 = 610; + if (chan->channel == 0) { + *val = 1; + *val2 = 220000; /* 1.22 mV */ + } else { + *val = 0; + *val2 = 610000; /* 0.610 mV */ + } return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: - *val = 0; - *val2 = -470000; + *val = -470; /* 0.47 C */ + *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: *val = 0; - *val2 = 462500; - return IIO_VAL_INT_PLUS_MICRO; + *val2 = IIO_G_TO_M_S_2(462400); /* 0.4624 mg */ + return IIO_VAL_INT_PLUS_NANO; case IIO_INCLI: *val = 0; - *val2 = 100000; + *val2 = 100000; /* 0.1 degree */ return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } break; case IIO_CHAN_INFO_OFFSET: - *val = 25; + *val = 25000 / -470 - 1278; /* 25 C = 1278 */ return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: switch (chan->type) { -- cgit v1.2.3-55-g7522 From 10dda40fb605c6468045906b0bce08e2e12c0aca Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 15 Oct 2012 10:35:00 +0100 Subject: staging:iio: Fix adis16203 channel offsets and scales Most of the channel offsets and scales in the adis16203 are incorrect: * Temperature scale is off by a factor of 1000 * Voltage scale is off by a factor of 1000 * Temperature offset is completely wrong This patch fixes these issues. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16203_core.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c index 002fa9dfc375..e7b3441115ae 100644 --- a/drivers/staging/iio/accel/adis16203_core.c +++ b/drivers/staging/iio/accel/adis16203_core.c @@ -316,25 +316,27 @@ static int adis16203_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: - *val = 0; - if (chan->channel == 0) - *val2 = 1220; - else - *val2 = 610; + if (chan->channel == 0) { + *val = 1; + *val2 = 220000; /* 1.22 mV */ + } else { + *val = 0; + *val2 = 610000; /* 0.61 mV */ + } return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: - *val = 0; - *val2 = -470000; + *val = -470; /* -0.47 C */ + *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_INCLI: *val = 0; - *val2 = 25000; + *val2 = 25000; /* 0.025 degree */ return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } case IIO_CHAN_INFO_OFFSET: - *val = 25; + *val = 25000 / -470 - 1278; /* 25 C = 1278 */ return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: bits = 14; -- cgit v1.2.3-55-g7522 From 9cc19b81d7363f630593ad7ceab9fa12a105fc25 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 15 Oct 2012 10:35:00 +0100 Subject: staging:iio: Fix adis16204 channel offsets and scales Most of the channel offsets and scales in the adis16204 are incorrect: * Temperature scale is off by a factor of 1000 * Voltage scale is off by a factor of 1000 * Acceleration is scale is in g instead of m/(s**2) * Temperature offset is completely wrong This patch fixes these issues. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16204_core.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c index 05bdb7c2c8e3..c6234c2f46aa 100644 --- a/drivers/staging/iio/accel/adis16204_core.c +++ b/drivers/staging/iio/accel/adis16204_core.c @@ -317,26 +317,28 @@ static int adis16204_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: - *val = 0; - if (chan->channel == 0) - *val2 = 1220; - else - *val2 = 610; + if (chan->channel == 0) { + *val = 1; + *val2 = 220000; /* 1.22 mV */ + } else { + *val = 0; + *val2 = 610000; /* 0.61 mV */ + } return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: - *val = 0; - *val2 = -470000; + *val = -470; /* 0.47 C */ + *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: *val = 0; switch (chan->channel2) { case IIO_MOD_X: case IIO_MOD_ROOT_SUM_SQUARED_X_Y: - *val2 = 17125; + *val2 = IIO_G_TO_M_S_2(17125); /* 17.125 mg */ break; case IIO_MOD_Y: case IIO_MOD_Z: - *val2 = 8407; + *val2 = IIO_G_TO_M_S_2(8407); /* 8.407 mg */ break; } return IIO_VAL_INT_PLUS_MICRO; @@ -345,7 +347,7 @@ static int adis16204_read_raw(struct iio_dev *indio_dev, } break; case IIO_CHAN_INFO_OFFSET: - *val = 25; + *val = 25000 / -470 - 1278; /* 25 C = 1278 */ return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: case IIO_CHAN_INFO_PEAK: -- cgit v1.2.3-55-g7522 From d5304b771203b62430776f3fca4823670282cbe4 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 15 Oct 2012 10:35:00 +0100 Subject: staging:iio: Fix adis16209 channel offsets and scales Most of the channel offsets and scales in the adis16209 are incorrect: * Temperature scale is of by a factor of 1000 * Voltage scale is of by a factor of 1000 * Temperature offset is completely wrong * Rotational position scale is missing This patch fixes these issues. Also use the IIO_G_TO_M_S_2 macro for the acceleration scale since this makes it much easier to compare it with the value given in the datasheet. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16209_core.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c index b7333bfe0b2f..7ee974b45d7d 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -343,28 +343,29 @@ static int adis16209_read_raw(struct iio_dev *indio_dev, case IIO_VOLTAGE: *val = 0; if (chan->channel == 0) - *val2 = 305180; + *val2 = 305180; /* 0.30518 mV */ else - *val2 = 610500; + *val2 = 610500; /* 0.6105 mV */ return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: - *val = 0; - *val2 = -470000; + *val = -470; /* -0.47 C */ + *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: *val = 0; - *val2 = 2394; - return IIO_VAL_INT_PLUS_MICRO; + *val2 = IIO_G_TO_M_S_2(244140); /* 0.244140 mg */ + return IIO_VAL_INT_PLUS_NANO; case IIO_INCLI: + case IIO_ROT: *val = 0; - *val2 = 436; + *val2 = 25000; /* 0.025 degree */ return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } break; case IIO_CHAN_INFO_OFFSET: - *val = 25; + *val = 25000 / -470 - 0x4FE; /* 25 C = 0x4FE */ return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: switch (chan->type) { @@ -491,6 +492,7 @@ static const struct iio_chan_spec adis16209_channels[] = { .modified = 1, .channel2 = IIO_MOD_X, .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = rot, .scan_index = ADIS16209_SCAN_ROT, .scan_type = { -- cgit v1.2.3-55-g7522 From 45240340568a799fa140645af2a45600dfe68694 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 15 Oct 2012 10:35:00 +0100 Subject: staging:iio: Fix adis16220 channel offsets and scales Most of the channel offsets and scales in the adis16220 are incorrect: * Temperature scale is off by a factor of 1000 * Voltage scale is off by a factor of 1000 * Acceleration seems to have a typo "187042" since it should be instead of "1887042" * Temperature offset is completely wrong This patch fixes these issues. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16220_core.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index c755089c7117..eaadd9df3f78 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -486,7 +486,7 @@ static int adis16220_read_raw(struct iio_dev *indio_dev, break; case IIO_CHAN_INFO_OFFSET: if (chan->type == IIO_TEMP) { - *val = 25; + *val = 25000 / -470 - 1278; /* 25 C = 1278 */ return IIO_VAL_INT; } addrind = 1; @@ -495,19 +495,22 @@ static int adis16220_read_raw(struct iio_dev *indio_dev, addrind = 2; break; case IIO_CHAN_INFO_SCALE: - *val = 0; switch (chan->type) { case IIO_TEMP: - *val2 = -470000; + *val = -470; /* -0.47 C */ + *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: - *val2 = 1887042; + *val2 = IIO_G_TO_M_S_2(19073); /* 19.073 g */ return IIO_VAL_INT_PLUS_MICRO; case IIO_VOLTAGE: - if (chan->channel == 0) - *val2 = 0012221; - else /* Should really be dependent on VDD */ - *val2 = 305; + if (chan->channel == 0) { + *val = 1; + *val2 = 220700; /* 1.2207 mV */ + } else { + /* Should really be dependent on VDD */ + *val2 = 305180; /* 305.18 uV */ + } return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; -- cgit v1.2.3-55-g7522 From acba41f81f4380ad24905df4c3c0ad7f272b338f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 15 Oct 2012 10:35:00 +0100 Subject: staging:iio: Fix adis16240 channel offsets and scales Most of the channel offsets and scales in the adis16240 are incorrect: * Temperature scale is of by a factor of 1000 * Voltage scale is of by a factor of 1000 * Temperature offset is completely wrong * Peak scale is completely wrong This patch fixes these issues. Also use the IIO_G_TO_M_S_2 macro for the acceleration scale since this makes it much easier to compare it to the value given in the datasheet. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16240_core.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c index 0fc26a49d681..35e093973d5c 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -373,30 +373,31 @@ static int adis16240_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: - *val = 0; - if (chan->channel == 0) - *val2 = 4880; - else + if (chan->channel == 0) { + *val = 4; + *val2 = 880000; /* 4.88 mV */ + return IIO_VAL_INT_PLUS_MICRO; + } else { return -EINVAL; - return IIO_VAL_INT_PLUS_MICRO; + } case IIO_TEMP: - *val = 0; - *val2 = 244000; + *val = 244; /* 0.244 C */ + *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: *val = 0; - *val2 = 504062; + *val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */ return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } break; case IIO_CHAN_INFO_PEAK_SCALE: - *val = 6; - *val2 = 629295; + *val = 0; + *val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */ return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_OFFSET: - *val = 25; + *val = 25000 / 244 - 0x133; /* 25 C = 0x133 */ return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: bits = 10; -- cgit v1.2.3-55-g7522 From 7e72a54c08c3a3d296c11139774e13cc80424060 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 15 Oct 2012 10:35:00 +0100 Subject: staging:iio: Fix adis16260 channel offsets and scales Most of the channel offsets and scales in the adis16260 are incorrect: * Temperature scale is off by a factor of 1000 * Voltage scale is off by a factor of 1000 * Temperature offset is completely wrong This patch fixes these issues. Also use the IIO_DEGREE_TO_RAD for the angle velocity since this makes it much easier to compare it to the value given in the datasheet. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/gyro/adis16260_core.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c index 9571c03aa4cc..aa964a2d8290 100644 --- a/drivers/staging/iio/gyro/adis16260_core.c +++ b/drivers/staging/iio/gyro/adis16260_core.c @@ -498,28 +498,33 @@ static int adis16260_read_raw(struct iio_dev *indio_dev, switch (chan->type) { case IIO_ANGL_VEL: *val = 0; - if (spi_get_device_id(st->us)->driver_data) - *val2 = 320; - else - *val2 = 1278; + if (spi_get_device_id(st->us)->driver_data) { + /* 0.01832 degree / sec */ + *val2 = IIO_DEGREE_TO_RAD(18320); + } else { + /* 0.07326 degree / sec */ + *val2 = IIO_DEGREE_TO_RAD(73260); + } return IIO_VAL_INT_PLUS_MICRO; case IIO_VOLTAGE: - *val = 0; - if (chan->channel == 0) - *val2 = 18315; - else - *val2 = 610500; + if (chan->channel == 0) { + *val = 1; + *val2 = 831500; /* 1.8315 mV */ + } else { + *val = 0; + *val2 = 610500; /* 610.5 uV */ + } return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: - *val = 0; - *val2 = 145300; + *val = 145; + *val2 = 300000; /* 0.1453 C */ return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } break; case IIO_CHAN_INFO_OFFSET: - *val = 25; + *val = 250000 / 1453; /* 25 C = 0x00 */ return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: switch (chan->type) { -- cgit v1.2.3-55-g7522 From 1cf8c97f94a07e6d6461ae81b62abc2134b52c24 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 15 Oct 2012 10:35:00 +0100 Subject: staging:iio: Fix adis16400 channel offsets and scales Most of the channel offsets and scales in the adis16400 are incorrect: * Voltage scale is off by a factor of 1000 * Temperature scale is off by a factor of 1000 * Temperature offset is completely wrong * Some of the acceleration scales are either completely wrong or have the wrong unit * Some of the angular velocity scale are either completely wrong or have the wrong unit This patch fixes these issues. For consistency it also converts scales which are correct to use the IIO_G_TO_M_S_2 and IIO_DEGREE_TO_RAD macro. This makes it much easier to compare it to the value given in the datasheet. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/imu/adis16400_core.c | 53 ++++++++++++++++---------------- 1 file changed, 27 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index b302c9ba2712..dccea95496f5 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -553,10 +553,13 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_MICRO; case IIO_VOLTAGE: *val = 0; - if (chan->channel == 0) - *val2 = 2418; - else - *val2 = 806; + if (chan->channel == 0) { + *val = 2; + *val2 = 418000; /* 2.418 mV */ + } else { + *val = 0; + *val2 = 805800; /* 805.8 uV */ + } return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: *val = 0; @@ -564,11 +567,11 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_MICRO; case IIO_MAGN: *val = 0; - *val2 = 500; + *val2 = 500; /* 0.5 mgauss */ return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: - *val = 0; - *val2 = 140000; + *val = 140; /* 0.14 C */ + *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; @@ -585,10 +588,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, *val = val16; return IIO_VAL_INT; case IIO_CHAN_INFO_OFFSET: - /* currently only temperature */ - *val = 198; - *val2 = 160000; - return IIO_VAL_INT_PLUS_MICRO; + *val = 2500 / 14; /* 25 C = 0x00 */ + return IIO_VAL_INT; case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: mutex_lock(&indio_dev->mlock); /* Need both the number of taps and the sampling frequency */ @@ -1058,7 +1059,7 @@ static struct adis16400_chip_info adis16400_chips[] = { [ADIS16300] = { .channels = adis16300_channels, .num_channels = ARRAY_SIZE(adis16300_channels), - .gyro_scale_micro = 873, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ .accel_scale_micro = 5884, .default_scan_mask = (1 << ADIS16400_SCAN_SUPPLY) | (1 << ADIS16400_SCAN_GYRO_X) | (1 << ADIS16400_SCAN_ACC_X) | @@ -1070,8 +1071,8 @@ static struct adis16400_chip_info adis16400_chips[] = { [ADIS16334] = { .channels = adis16334_channels, .num_channels = ARRAY_SIZE(adis16334_channels), - .gyro_scale_micro = 873, - .accel_scale_micro = 981, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */ .default_scan_mask = (1 << ADIS16400_SCAN_GYRO_X) | (1 << ADIS16400_SCAN_GYRO_Y) | (1 << ADIS16400_SCAN_GYRO_Z) | (1 << ADIS16400_SCAN_ACC_X) | (1 << ADIS16400_SCAN_ACC_Y) | @@ -1080,8 +1081,8 @@ static struct adis16400_chip_info adis16400_chips[] = { [ADIS16350] = { .channels = adis16350_channels, .num_channels = ARRAY_SIZE(adis16350_channels), - .gyro_scale_micro = 872664, - .accel_scale_micro = 24732, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(73260), /* 0.07326 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(2522), /* 0.002522 g */ .default_scan_mask = 0x7FF, .flags = ADIS16400_NO_BURST, }, @@ -1090,8 +1091,8 @@ static struct adis16400_chip_info adis16400_chips[] = { .num_channels = ARRAY_SIZE(adis16350_channels), .flags = ADIS16400_HAS_PROD_ID, .product_id = 0x3FE8, - .gyro_scale_micro = 1279, - .accel_scale_micro = 24732, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */ .default_scan_mask = 0x7FF, }, [ADIS16362] = { @@ -1099,8 +1100,8 @@ static struct adis16400_chip_info adis16400_chips[] = { .num_channels = ARRAY_SIZE(adis16350_channels), .flags = ADIS16400_HAS_PROD_ID, .product_id = 0x3FEA, - .gyro_scale_micro = 1279, - .accel_scale_micro = 24732, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(333), /* 0.333 mg */ .default_scan_mask = 0x7FF, }, [ADIS16364] = { @@ -1108,8 +1109,8 @@ static struct adis16400_chip_info adis16400_chips[] = { .num_channels = ARRAY_SIZE(adis16350_channels), .flags = ADIS16400_HAS_PROD_ID, .product_id = 0x3FEC, - .gyro_scale_micro = 1279, - .accel_scale_micro = 24732, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */ .default_scan_mask = 0x7FF, }, [ADIS16365] = { @@ -1117,8 +1118,8 @@ static struct adis16400_chip_info adis16400_chips[] = { .num_channels = ARRAY_SIZE(adis16350_channels), .flags = ADIS16400_HAS_PROD_ID, .product_id = 0x3FED, - .gyro_scale_micro = 1279, - .accel_scale_micro = 24732, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */ .default_scan_mask = 0x7FF, }, [ADIS16400] = { @@ -1126,8 +1127,8 @@ static struct adis16400_chip_info adis16400_chips[] = { .num_channels = ARRAY_SIZE(adis16400_channels), .flags = ADIS16400_HAS_PROD_ID, .product_id = 0x4015, - .gyro_scale_micro = 873, - .accel_scale_micro = 32656, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */ .default_scan_mask = 0xFFF, } }; -- cgit v1.2.3-55-g7522 From 760ebc0d2af519dde91e39d22927d2be1bc57190 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 15 Oct 2012 10:35:00 +0100 Subject: staging:iio:adis16400: Report correct temperature scale and offset Temperature scale and offset differ between the different devices supported by this driver. Right now the driver always reports the temperature scale and offset of the adis16400 regardless of which chip variant is used. This patch adds two new attributes to the chip_info struct, one for the temperature scale and one for the temperature offset. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/imu/adis16400.h | 2 ++ drivers/staging/iio/imu/adis16400_core.c | 23 ++++++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/imu/adis16400.h b/drivers/staging/iio/imu/adis16400.h index d59d7ac856a9..77c601da1846 100644 --- a/drivers/staging/iio/imu/adis16400.h +++ b/drivers/staging/iio/imu/adis16400.h @@ -139,6 +139,8 @@ struct adis16400_chip_info { const long flags; unsigned int gyro_scale_micro; unsigned int accel_scale_micro; + int temp_scale_nano; + int temp_offset; unsigned long default_scan_mask; }; diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index dccea95496f5..eaed87ff1c86 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -570,8 +570,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, *val2 = 500; /* 0.5 mgauss */ return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: - *val = 140; /* 0.14 C */ - *val2 = 0; + *val = st->variant->temp_scale_nano / 1000000; + *val2 = (st->variant->temp_scale_nano % 1000000); return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; @@ -588,7 +588,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, *val = val16; return IIO_VAL_INT; case IIO_CHAN_INFO_OFFSET: - *val = 2500 / 14; /* 25 C = 0x00 */ + /* currently only temperature */ + *val = st->variant->temp_offset; return IIO_VAL_INT; case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: mutex_lock(&indio_dev->mlock); @@ -1061,6 +1062,8 @@ static struct adis16400_chip_info adis16400_chips[] = { .num_channels = ARRAY_SIZE(adis16300_channels), .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ .accel_scale_micro = 5884, + .temp_scale_nano = 140000000, /* 0.14 C */ + .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ .default_scan_mask = (1 << ADIS16400_SCAN_SUPPLY) | (1 << ADIS16400_SCAN_GYRO_X) | (1 << ADIS16400_SCAN_ACC_X) | (1 << ADIS16400_SCAN_ACC_Y) | (1 << ADIS16400_SCAN_ACC_Z) | @@ -1073,6 +1076,8 @@ static struct adis16400_chip_info adis16400_chips[] = { .num_channels = ARRAY_SIZE(adis16334_channels), .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */ + .temp_scale_nano = 67850000, /* 0.06785 C */ + .temp_offset = 25000000 / 67850, /* 25 C = 0x00 */ .default_scan_mask = (1 << ADIS16400_SCAN_GYRO_X) | (1 << ADIS16400_SCAN_GYRO_Y) | (1 << ADIS16400_SCAN_GYRO_Z) | (1 << ADIS16400_SCAN_ACC_X) | (1 << ADIS16400_SCAN_ACC_Y) | @@ -1083,6 +1088,8 @@ static struct adis16400_chip_info adis16400_chips[] = { .num_channels = ARRAY_SIZE(adis16350_channels), .gyro_scale_micro = IIO_DEGREE_TO_RAD(73260), /* 0.07326 deg/s */ .accel_scale_micro = IIO_G_TO_M_S_2(2522), /* 0.002522 g */ + .temp_scale_nano = 145300000, /* 0.1453 C */ + .temp_offset = 25000000 / 145300, /* 25 C = 0x00 */ .default_scan_mask = 0x7FF, .flags = ADIS16400_NO_BURST, }, @@ -1093,6 +1100,8 @@ static struct adis16400_chip_info adis16400_chips[] = { .product_id = 0x3FE8, .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */ + .temp_scale_nano = 136000000, /* 0.136 C */ + .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .default_scan_mask = 0x7FF, }, [ADIS16362] = { @@ -1102,6 +1111,8 @@ static struct adis16400_chip_info adis16400_chips[] = { .product_id = 0x3FEA, .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ .accel_scale_micro = IIO_G_TO_M_S_2(333), /* 0.333 mg */ + .temp_scale_nano = 136000000, /* 0.136 C */ + .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .default_scan_mask = 0x7FF, }, [ADIS16364] = { @@ -1111,6 +1122,8 @@ static struct adis16400_chip_info adis16400_chips[] = { .product_id = 0x3FEC, .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */ + .temp_scale_nano = 136000000, /* 0.136 C */ + .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .default_scan_mask = 0x7FF, }, [ADIS16365] = { @@ -1120,6 +1133,8 @@ static struct adis16400_chip_info adis16400_chips[] = { .product_id = 0x3FED, .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */ + .temp_scale_nano = 136000000, /* 0.136 C */ + .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .default_scan_mask = 0x7FF, }, [ADIS16400] = { @@ -1130,6 +1145,8 @@ static struct adis16400_chip_info adis16400_chips[] = { .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */ .default_scan_mask = 0xFFF, + .temp_scale_nano = 140000000, /* 0.14 C */ + .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ } }; -- cgit v1.2.3-55-g7522 From 2e132e4692d627fd8aa0a1833e647d517531cb99 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 15 Oct 2012 10:35:00 +0100 Subject: staging:iio:adis16400: Fixup adis16336 temp channel attributes The temperature channel has a calibbias attribute which it should not have, but the offset attribute is missing. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/imu/adis16400_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index eaed87ff1c86..3144a7b1e1c4 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -1037,7 +1037,7 @@ static const struct iio_chan_spec adis16334_channels[] = { .indexed = 1, .channel = 0, .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = temp0, .scan_index = ADIS16400_SCAN_TEMP, -- cgit v1.2.3-55-g7522 From d479c911789e14a19b86ca09b0b634f1449c8c6b Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Fri, 19 Oct 2012 10:24:12 -0400 Subject: USB: ehci-fsl: Return valid error in ehci_fsl_setup_phy ehci_fsl_setup_phy is supposed to return an int, but had a void return value in the case of controller_ver being invalid. Introduced by commit 3735ba8db8e6 ("powerpc/usb: fix bug of CPU hang when missing USB PHY clock"), which missed one return. Signed-off-by: Ben Collins Cc: Shengzhou Liu Cc: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/usb/host/ehci-fsl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 9bfde82078ec..0d2f35ca93f1 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -222,7 +222,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, if (pdata->controller_ver < 0) { dev_warn(hcd->self.controller, "Could not get controller version\n"); - return; + return -ENODEV; } portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]); -- cgit v1.2.3-55-g7522 From 98f9c3c137cea016c57c9fd60b3caf88eb34e4cd Mon Sep 17 00:00:00 2001 From: Andreas Larsson Date: Wed, 17 Oct 2012 09:36:00 +0100 Subject: iio: Remove duplicates for light/ in Kconfig and Makefile Signed-off-by: Andreas Larsson Signed-off-by: Jonathan Cameron --- drivers/iio/Kconfig | 1 - drivers/iio/Makefile | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index 6e3f143fc71d..fc937aca71fb 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig @@ -62,7 +62,6 @@ source "drivers/iio/frequency/Kconfig" source "drivers/iio/dac/Kconfig" source "drivers/iio/common/Kconfig" source "drivers/iio/gyro/Kconfig" -source "drivers/iio/light/Kconfig" source "drivers/iio/magnetometer/Kconfig" endif # IIO diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index f7fa3c0867b4..761f2b65ac52 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile @@ -18,5 +18,4 @@ obj-y += frequency/ obj-y += dac/ obj-y += common/ obj-y += gyro/ -obj-y += light/ obj-y += magnetometer/ -- cgit v1.2.3-55-g7522 From 16757372ffa5ee0ef7e82f73a6adbb054a434a13 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 19 Oct 2012 11:54:21 -0700 Subject: xen: Fix annoying compile-time warning Commit cb6b6df111e4 ("xen/pv-on-hvm kexec: add quirk for Xen 3.4 and shutdown watches.") added the xen_strict_xenbus_quirk() function with an old K&R-style declaration without proper typing, causing gcc to rightly complain: drivers/xen/xenbus/xenbus_xs.c:628:13: warning: function declaration isn’t a prototype [-Wstrict-prototypes] because we really don't live in caves using stone-age tools any more, and the kernel has always used properly typed ANSI C function declarations. So if a function doesn't take arguments, we tell the compiler so explicitly by adding the proper "void" in the prototype. I'm sure there are tons of other examples of this kind of stuff in the tree, but this is the one that hits my workstation config, so.. Signed-off-by: Linus Torvalds --- drivers/xen/xenbus/xenbus_xs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index 48220e129f85..f5dda83ad7a5 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c @@ -625,7 +625,7 @@ static struct xenbus_watch *find_watch(const char *token) * so if we are running on anything older than 4 do not attempt to read * control/platform-feature-xs_reset_watches. */ -static bool xen_strict_xenbus_quirk() +static bool xen_strict_xenbus_quirk(void) { uint32_t eax, ebx, ecx, edx, base; -- cgit v1.2.3-55-g7522 From e9d1aa05da264cf7e1906b81a90d6abfdbe3700b Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Fri, 12 Oct 2012 14:36:56 -0400 Subject: xen/xenbus: Fix compile warning. We were missing the 'void' on the parameter arguments. Reported-by: Fengguang Wu Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xenbus/xenbus_xs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index 48220e129f85..f5dda83ad7a5 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c @@ -625,7 +625,7 @@ static struct xenbus_watch *find_watch(const char *token) * so if we are running on anything older than 4 do not attempt to read * control/platform-feature-xs_reset_watches. */ -static bool xen_strict_xenbus_quirk() +static bool xen_strict_xenbus_quirk(void) { uint32_t eax, ebx, ecx, edx, base; -- cgit v1.2.3-55-g7522 From 8a5248fe10b101104d92d01438f918e899414fd1 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Wed, 17 Oct 2012 11:55:55 +0200 Subject: xen PV passthru: assign SR-IOV virtual functions to separate virtual slots VFs are reported as single-function devices in PCI_HEADER_TYPE, which causes pci_scan_slot() in the PV domU to skip all VFs beyond #0 in the pciback-provided slot. Avoid this by assigning each VF to a separate virtual slot. Acked-by: Jan Beulich Signed-off-by: Laszlo Ersek Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xen-pciback/vpci.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/xen/xen-pciback/vpci.c b/drivers/xen/xen-pciback/vpci.c index 46d140baebd8..0f478ac483cd 100644 --- a/drivers/xen/xen-pciback/vpci.c +++ b/drivers/xen/xen-pciback/vpci.c @@ -89,9 +89,15 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev, mutex_lock(&vpci_dev->lock); - /* Keep multi-function devices together on the virtual PCI bus */ - for (slot = 0; slot < PCI_SLOT_MAX; slot++) { - if (!list_empty(&vpci_dev->dev_list[slot])) { + /* + * Keep multi-function devices together on the virtual PCI bus, except + * virtual functions. + */ + if (!dev->is_virtfn) { + for (slot = 0; slot < PCI_SLOT_MAX; slot++) { + if (list_empty(&vpci_dev->dev_list[slot])) + continue; + t = list_entry(list_first(&vpci_dev->dev_list[slot]), struct pci_dev_entry, list); @@ -116,7 +122,7 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev, pci_name(dev), slot); list_add_tail(&dev_entry->list, &vpci_dev->dev_list[slot]); - func = PCI_FUNC(dev->devfn); + func = dev->is_virtfn ? 0 : PCI_FUNC(dev->devfn); goto unlock; } } -- cgit v1.2.3-55-g7522 From 7644bdac7f4d3e5910f4d3f86f1f2b098d1212ca Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 17 Oct 2012 09:39:08 +0100 Subject: xen: xenbus: quirk uses x86 specific cpuid This breaks on ARM. This quirk is not necessary on ARM because no hypervisors of that vintage exist for that architecture (port is too new). Signed-off-by: Ian Campbell [v1: Moved the ifdef inside the function per Jan Beulich suggestion] Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xenbus/xenbus_xs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index f5dda83ad7a5..acedeabe589c 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c @@ -627,6 +627,7 @@ static struct xenbus_watch *find_watch(const char *token) */ static bool xen_strict_xenbus_quirk(void) { +#ifdef CONFIG_X86 uint32_t eax, ebx, ecx, edx, base; base = xen_cpuid_base(); @@ -634,6 +635,7 @@ static bool xen_strict_xenbus_quirk(void) if ((eax >> 16) < 4) return true; +#endif return false; } -- cgit v1.2.3-55-g7522 From 609b0b8c4608d59be261dde748f1ff1eccd748ba Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 17 Oct 2012 09:39:09 +0100 Subject: xen: sysfs: include err.h for PTR_ERR etc Fixes build error on ARM: drivers/xen/sys-hypervisor.c: In function 'uuid_show_fallback': drivers/xen/sys-hypervisor.c:127:2: error: implicit declaration of function 'IS_ERR' [-Werror=implicit-function-declaration] drivers/xen/sys-hypervisor.c:128:3: error: implicit declaration of function 'PTR_ERR' [-Werror=implicit-function-declaration] Acked-by: Stefano Stabellini Signed-off-by: Ian Campbell Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/sys-hypervisor.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c index 5e5ad7e28858..66a0a1475acf 100644 --- a/drivers/xen/sys-hypervisor.c +++ b/drivers/xen/sys-hypervisor.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3-55-g7522 From 37ea0fcb6a3f3318bf45888e624722a2945cec04 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 17 Oct 2012 09:39:10 +0100 Subject: xen: sysfs: fix build warning. Define PRI macros for xen_ulong_t and xen_pfn_t and use to fix: drivers/xen/sys-hypervisor.c:288:4: warning: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'xen_ulong_t' [-Wformat] Ideally this would use PRIx64 on ARM but these (or equivalent) don't seem to be available in the kernel. Acked-by: Stefano Stabellini Signed-off-by: Ian Campbell Signed-off-by: Konrad Rzeszutek Wilk --- arch/arm/include/asm/xen/interface.h | 2 ++ arch/x86/include/asm/xen/interface.h | 2 ++ drivers/xen/sys-hypervisor.c | 3 ++- 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/arch/arm/include/asm/xen/interface.h b/arch/arm/include/asm/xen/interface.h index ae05e56dd17d..62160f259b0e 100644 --- a/arch/arm/include/asm/xen/interface.h +++ b/arch/arm/include/asm/xen/interface.h @@ -31,7 +31,9 @@ /* Explicitly size integers that represent pfns in the interface with * Xen so that we can have one ABI that works for 32 and 64 bit guests. */ typedef uint64_t xen_pfn_t; +#define PRI_xen_pfn "llx" typedef uint64_t xen_ulong_t; +#define PRI_xen_ulong "llx" /* Guest handles for primitive C types. */ __DEFINE_GUEST_HANDLE(uchar, unsigned char); __DEFINE_GUEST_HANDLE(uint, unsigned int); diff --git a/arch/x86/include/asm/xen/interface.h b/arch/x86/include/asm/xen/interface.h index 28fc6211a79a..c5b13e76d730 100644 --- a/arch/x86/include/asm/xen/interface.h +++ b/arch/x86/include/asm/xen/interface.h @@ -51,7 +51,9 @@ * with Xen so that on ARM we can have one ABI that works for 32 and 64 * bit guests. */ typedef unsigned long xen_pfn_t; +#define PRI_xen_pfn "lx" typedef unsigned long xen_ulong_t; +#define PRI_xen_ulong "lx" /* Guest handles for primitive C types. */ __DEFINE_GUEST_HANDLE(uchar, unsigned char); __DEFINE_GUEST_HANDLE(uint, unsigned int); diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c index 66a0a1475acf..96453f8a85c5 100644 --- a/drivers/xen/sys-hypervisor.c +++ b/drivers/xen/sys-hypervisor.c @@ -285,7 +285,8 @@ static ssize_t virtual_start_show(struct hyp_sysfs_attr *attr, char *buffer) ret = HYPERVISOR_xen_version(XENVER_platform_parameters, parms); if (!ret) - ret = sprintf(buffer, "%lx\n", parms->virt_start); + ret = sprintf(buffer, "%"PRI_xen_ulong"\n", + parms->virt_start); kfree(parms); } -- cgit v1.2.3-55-g7522 From bf86ad8095d4684ada0d37bb1355ede2c88a5e4e Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 17 Oct 2012 09:39:12 +0100 Subject: xen: events: pirq_check_eoi_map is X86 specific On ARM I see: drivers/xen/events.c:280:13: warning: 'pirq_check_eoi_map' defined but not used [-Wunused-function] Signed-off-by: Ian Campbell Cc: Stefano Stabellini Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/events.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 59e10a1286d5..912ac81b6dbf 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -115,7 +115,9 @@ struct irq_info { #define PIRQ_SHAREABLE (1 << 1) static int *evtchn_to_irq; +#ifdef CONFIG_X86 static unsigned long *pirq_eoi_map; +#endif static bool (*pirq_needs_eoi)(unsigned irq); static DEFINE_PER_CPU(unsigned long [NR_EVENT_CHANNELS/BITS_PER_LONG], @@ -277,10 +279,12 @@ static unsigned int cpu_from_evtchn(unsigned int evtchn) return ret; } +#ifdef CONFIG_X86 static bool pirq_check_eoi_map(unsigned irq) { return test_bit(pirq_from_irq(irq), pirq_eoi_map); } +#endif static bool pirq_needs_eoi_flag(unsigned irq) { -- cgit v1.2.3-55-g7522 From ef32f89298c094b6ed76c0c4981b7a51e939cb71 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 17 Oct 2012 09:39:14 +0100 Subject: xen: grant: use xen_pfn_t type for frame_list. This correctly sizes it as 64 bit on ARM but leaves it as unsigned long on x86 (therefore no intended change on x86). The long and ulong guest handles are now unused (and a bit dangerous) so remove them. Acked-by: Stefano Stabellini Signed-off-by: Ian Campbell Signed-off-by: Konrad Rzeszutek Wilk --- arch/arm/include/asm/xen/interface.h | 2 -- arch/arm/xen/grant-table.c | 2 +- arch/x86/include/asm/xen/interface.h | 2 -- drivers/xen/grant-table.c | 8 ++++---- include/xen/grant_table.h | 2 +- include/xen/interface/grant_table.h | 2 +- 6 files changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/arch/arm/include/asm/xen/interface.h b/arch/arm/include/asm/xen/interface.h index 62160f259b0e..1d6ef9c2d1d9 100644 --- a/arch/arm/include/asm/xen/interface.h +++ b/arch/arm/include/asm/xen/interface.h @@ -37,10 +37,8 @@ typedef uint64_t xen_ulong_t; /* Guest handles for primitive C types. */ __DEFINE_GUEST_HANDLE(uchar, unsigned char); __DEFINE_GUEST_HANDLE(uint, unsigned int); -__DEFINE_GUEST_HANDLE(ulong, unsigned long); DEFINE_GUEST_HANDLE(char); DEFINE_GUEST_HANDLE(int); -DEFINE_GUEST_HANDLE(long); DEFINE_GUEST_HANDLE(void); DEFINE_GUEST_HANDLE(uint64_t); DEFINE_GUEST_HANDLE(uint32_t); diff --git a/arch/arm/xen/grant-table.c b/arch/arm/xen/grant-table.c index dbd1330c0196..859a9bb002d5 100644 --- a/arch/arm/xen/grant-table.c +++ b/arch/arm/xen/grant-table.c @@ -33,7 +33,7 @@ #include #include -int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, +int arch_gnttab_map_shared(xen_pfn_t *frames, unsigned long nr_gframes, unsigned long max_nr_gframes, void **__shared) { diff --git a/arch/x86/include/asm/xen/interface.h b/arch/x86/include/asm/xen/interface.h index c5b13e76d730..ca9487d4f176 100644 --- a/arch/x86/include/asm/xen/interface.h +++ b/arch/x86/include/asm/xen/interface.h @@ -57,10 +57,8 @@ typedef unsigned long xen_ulong_t; /* Guest handles for primitive C types. */ __DEFINE_GUEST_HANDLE(uchar, unsigned char); __DEFINE_GUEST_HANDLE(uint, unsigned int); -__DEFINE_GUEST_HANDLE(ulong, unsigned long); DEFINE_GUEST_HANDLE(char); DEFINE_GUEST_HANDLE(int); -DEFINE_GUEST_HANDLE(long); DEFINE_GUEST_HANDLE(void); DEFINE_GUEST_HANDLE(uint64_t); DEFINE_GUEST_HANDLE(uint32_t); diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 3a567b15600b..39aefa890110 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -84,7 +84,7 @@ struct gnttab_ops { * nr_gframes is the number of frames to map grant table. Returning * GNTST_okay means success and negative value means failure. */ - int (*map_frames)(unsigned long *frames, unsigned int nr_gframes); + int (*map_frames)(xen_pfn_t *frames, unsigned int nr_gframes); /* * Release a list of frames which are mapped in map_frames for grant * entry status. @@ -958,7 +958,7 @@ static unsigned nr_status_frames(unsigned nr_grant_frames) return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP; } -static int gnttab_map_frames_v1(unsigned long *frames, unsigned int nr_gframes) +static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes) { int rc; @@ -975,7 +975,7 @@ static void gnttab_unmap_frames_v1(void) arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames); } -static int gnttab_map_frames_v2(unsigned long *frames, unsigned int nr_gframes) +static int gnttab_map_frames_v2(xen_pfn_t *frames, unsigned int nr_gframes) { uint64_t *sframes; unsigned int nr_sframes; @@ -1027,7 +1027,7 @@ static void gnttab_unmap_frames_v2(void) static int gnttab_map(unsigned int start_idx, unsigned int end_idx) { struct gnttab_setup_table setup; - unsigned long *frames; + xen_pfn_t *frames; unsigned int nr_gframes = end_idx + 1; int rc; diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index ba0d77529a29..962b7df5eabf 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h @@ -170,7 +170,7 @@ gnttab_set_unmap_op(struct gnttab_unmap_grant_ref *unmap, phys_addr_t addr, unmap->dev_bus_addr = 0; } -int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, +int arch_gnttab_map_shared(xen_pfn_t *frames, unsigned long nr_gframes, unsigned long max_nr_gframes, void **__shared); int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes, diff --git a/include/xen/interface/grant_table.h b/include/xen/interface/grant_table.h index f9f8b975ae74..e40fae9bf11a 100644 --- a/include/xen/interface/grant_table.h +++ b/include/xen/interface/grant_table.h @@ -310,7 +310,7 @@ struct gnttab_setup_table { uint32_t nr_frames; /* OUT parameters. */ int16_t status; /* GNTST_* */ - GUEST_HANDLE(ulong) frame_list; + GUEST_HANDLE(xen_pfn_t) frame_list; }; DEFINE_GUEST_HANDLE_STRUCT(gnttab_setup_table); -- cgit v1.2.3-55-g7522 From ee678518eb386f513ac7fd374f7e8b8792ee79f8 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 17 Oct 2012 09:39:15 +0100 Subject: xen: balloon: don't include e820.h This breaks on !X86 and AFAICT is not required on X86 either. Acked-by: Stefano Stabellini Signed-off-by: Ian Campbell Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/balloon.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 31ab82fda38a..d7bd1b323775 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -55,7 +55,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3-55-g7522 From 965c0aaafe3e75d4e65cd4ec862915869bde3abd Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 17 Oct 2012 09:39:16 +0100 Subject: xen: balloon: use correct type for frame_list This is now a xen_pfn_t. Signed-off-by: Ian Campbell Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/balloon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index d7bd1b323775..d6886d90ccfd 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -87,7 +87,7 @@ struct balloon_stats balloon_stats; EXPORT_SYMBOL_GPL(balloon_stats); /* We increase/decrease in batches which fit in a page */ -static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)]; +static xen_pfn_t frame_list[PAGE_SIZE / sizeof(unsigned long)]; #ifdef CONFIG_HIGHMEM #define inc_totalhigh_pages() (totalhigh_pages++) -- cgit v1.2.3-55-g7522 From 801e7fb738c1049d93417dd8c2c4bf9cf567b668 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 17 Oct 2012 09:39:11 +0100 Subject: xen: dbgp: Fix warning when CONFIG_PCI is not enabled. I saw this on ARM: linux/drivers/xen/dbgp.c:11:23: warning: unused variable 'ctrlr' [-Wunused-variable] Acked-by: Stefano Stabellini Signed-off-by: Ian Campbell Acked-by: Jan Beulich Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/dbgp.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/xen/dbgp.c b/drivers/xen/dbgp.c index 42569c77ccc8..f3ccc80a455f 100644 --- a/drivers/xen/dbgp.c +++ b/drivers/xen/dbgp.c @@ -8,7 +8,9 @@ static int xen_dbgp_op(struct usb_hcd *hcd, int op) { +#ifdef CONFIG_PCI const struct device *ctrlr = hcd_to_bus(hcd)->controller; +#endif struct physdev_dbgp_op dbgp; if (!xen_initial_domain()) -- cgit v1.2.3-55-g7522 From c31407a3672aaebb4acddf90944a114fa5c8af7b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 18 Oct 2012 21:07:01 +0100 Subject: drm/i915: Add no-lvds quirk for Supermicro X7SPA-H Reported-and-tested-by: Francois Tigeot Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=55375 Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lvds.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 40d72bd64e11..224ae5fab0f6 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -778,6 +778,14 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_BOARD_NAME, "D525TUD"), }, }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "Supermicro X7SPA-H", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"), + DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"), + }, + }, { } /* terminating entry */ }; -- cgit v1.2.3-55-g7522 From 74ce6b6c63262defba91c4d790b3f91074793c0d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 19 Oct 2012 15:51:06 +0100 Subject: drm/i915: Initialize obj->pages before use by i915_gem_object_do_bit17_swizzle() If we leave obj->pages set to NULL before attempting to deswizzle them, then an OOPS is well deserved. Fixes regression introduced in commit 9da3da660d8c19a54f6e93361d147509be3fff84 Author: Chris Wilson Date: Fri Jun 1 15:20:22 2012 +0100 drm/i915: Replace the array of pages with a scatterlist Reported-and-tested-by: Krzysztof Kolasa Signed-off-by: Chris Wilson Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 45888d2ed534..8bc7ba76ace1 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1825,10 +1825,11 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) sg_set_page(sg, page, PAGE_SIZE, 0); } + obj->pages = st; + if (i915_gem_object_needs_bit17_swizzle(obj)) i915_gem_object_do_bit_17_swizzle(obj); - obj->pages = st; return 0; err_pages: -- cgit v1.2.3-55-g7522 From dc36d7e7cd422d69b15e7ec7cc1f021f581a6b6d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 19 Oct 2012 13:56:52 -0700 Subject: drivers/video/backlight/lm3639_bl.c: return proper error in lm3639_bled_mode_store() error paths Signed-off-by: Axel Lin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/lm3639_bl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c index c6915c6c3cd1..585949b57055 100644 --- a/drivers/video/backlight/lm3639_bl.c +++ b/drivers/video/backlight/lm3639_bl.c @@ -206,11 +206,11 @@ static ssize_t lm3639_bled_mode_store(struct device *dev, out: dev_err(pchip->dev, "%s:i2c access fail to register\n", __func__); - return size; + return ret; out_input: dev_err(pchip->dev, "%s:input conversion fail\n", __func__); - return size; + return ret; } -- cgit v1.2.3-55-g7522 From bac716966094e39c8027428993a57b79f2dd6c97 Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Fri, 19 Oct 2012 13:56:55 -0700 Subject: firmware/memmap: avoid type conflicts with the generic memmap_init() Fix this build error: drivers/firmware/memmap.c:240:19: error: conflicting types for 'memmap_init' arch/ia64/include/asm/pgtable.h:565:17: note: previous declaration of 'memmap_init' was here Signed-off-by: Fengguang Wu Cc: Bernhard Walle Cc: Glauber Costa Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/firmware/memmap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c index c1cdc9236666..90723e65b081 100644 --- a/drivers/firmware/memmap.c +++ b/drivers/firmware/memmap.c @@ -237,7 +237,7 @@ static ssize_t memmap_attr_show(struct kobject *kobj, * firmware_map_add() or firmware_map_add_early() afterwards, the entries * are not added to sysfs. */ -static int __init memmap_init(void) +static int __init firmware_memmap_init(void) { struct firmware_map_entry *entry; @@ -246,5 +246,5 @@ static int __init memmap_init(void) return 0; } -late_initcall(memmap_init); +late_initcall(firmware_memmap_init); -- cgit v1.2.3-55-g7522 From 0be1fecd7ee61b5a6d2b2e94b052b8a070b946ef Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Mon, 22 Oct 2012 10:44:55 +1100 Subject: md faulty: use disk_stack_limits() in: fe86cdce block: do not artificially constrain max_sectors for stacking drivers max_sectors defaults to UINT_MAX. md faulty wasn't using disk_stack_limits(), so inherited this large value as well. This triggered a bug in XFS when stressed over md_faulty, when a very large bio_alloc() failed. That was on an older kernel, and I can't reproduce exactly the same thing upstream, but I think the fix is appropriate in any case. Thanks to Mike Snitzer for pointing out the problem. Signed-off-by: Eric Sandeen Signed-off-by: NeilBrown --- drivers/md/faulty.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c index 45135f69509c..5e7dc772f5de 100644 --- a/drivers/md/faulty.c +++ b/drivers/md/faulty.c @@ -315,8 +315,11 @@ static int run(struct mddev *mddev) } conf->nfaults = 0; - rdev_for_each(rdev, mddev) + rdev_for_each(rdev, mddev) { conf->rdev = rdev; + disk_stack_limits(mddev->gendisk, rdev->bdev, + rdev->data_offset << 9); + } md_set_array_sectors(mddev, faulty_size(mddev, 0, 0)); mddev->private = conf; -- cgit v1.2.3-55-g7522 From 9a4da2cd99e4edfee1e48c5e2b4928eaefb56006 Mon Sep 17 00:00:00 2001 From: Vipul Pandya Date: Fri, 19 Oct 2012 02:09:53 +0000 Subject: cxgb4: Remove unnecessary #ifdef condition This patch also fixes the build failure caused due to removal of #ifdef CONFIG_CHELSIO_T4_OFFLOAD condition Signed-off-by: Vipul Pandya Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 19 ++++++++++++++++ drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 29 +++++-------------------- drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 3 +++ 3 files changed, 27 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index a4da893ac1e1..378988b5709a 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -251,6 +251,8 @@ struct adapter_params { unsigned char rev; /* chip revision */ unsigned char offload; + unsigned char bypass; + unsigned int ofldq_wr_cred; }; @@ -642,6 +644,23 @@ extern int dbfifo_int_thresh; #define for_each_port(adapter, iter) \ for (iter = 0; iter < (adapter)->params.nports; ++iter) +static inline int is_bypass(struct adapter *adap) +{ + return adap->params.bypass; +} + +static inline int is_bypass_device(int device) +{ + /* this should be set based upon device capabilities */ + switch (device) { + case 0x440b: + case 0x440c: + return 1; + default: + return 0; + } +} + static inline unsigned int core_ticks_per_usec(const struct adapter *adap) { return adap->params.vpd.cclk / 1000; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 604f4f87f550..c1cde11b0c6d 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -3513,18 +3513,6 @@ static int adap_init0_no_config(struct adapter *adapter, int reset) if (ret < 0) goto bye; -#ifndef CONFIG_CHELSIO_T4_OFFLOAD - /* - * If we're a pure NIC driver then disable all offloading facilities. - * This will allow the firmware to optimize aspects of the hardware - * configuration which will result in improved performance. - */ - caps_cmd.ofldcaps = 0; - caps_cmd.iscsicaps = 0; - caps_cmd.rdmacaps = 0; - caps_cmd.fcoecaps = 0; -#endif - if (caps_cmd.niccaps & htons(FW_CAPS_CONFIG_NIC_VM)) { if (!vf_acls) caps_cmd.niccaps ^= htons(FW_CAPS_CONFIG_NIC_VM); @@ -3745,6 +3733,7 @@ static int adap_init0(struct adapter *adap) u32 v, port_vec; enum dev_state state; u32 params[7], val[7]; + struct fw_caps_config_cmd caps_cmd; int reset = 1, j; /* @@ -3898,6 +3887,9 @@ static int adap_init0(struct adapter *adap) goto bye; } + if (is_bypass_device(adap->pdev->device)) + adap->params.bypass = 1; + /* * Grab some of our basic fundamental operating parameters. */ @@ -3940,13 +3932,12 @@ static int adap_init0(struct adapter *adap) adap->tids.aftid_end = val[1]; } -#ifdef CONFIG_CHELSIO_T4_OFFLOAD /* * Get device capabilities so we can determine what resources we need * to manage. */ memset(&caps_cmd, 0, sizeof(caps_cmd)); - caps_cmd.op_to_write = htonl(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) | + caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | FW_CMD_REQUEST | FW_CMD_READ); caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd)); ret = t4_wr_mbox(adap, adap->mbox, &caps_cmd, sizeof(caps_cmd), @@ -3991,15 +3982,6 @@ static int adap_init0(struct adapter *adap) adap->vres.ddp.size = val[4] - val[3] + 1; adap->params.ofldq_wr_cred = val[5]; - params[0] = FW_PARAM_PFVF(ETHOFLD_START); - params[1] = FW_PARAM_PFVF(ETHOFLD_END); - ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2, - params, val); - if ((val[0] != val[1]) && (ret >= 0)) { - adap->tids.uotid_base = val[0]; - adap->tids.nuotids = val[1] - val[0] + 1; - } - adap->params.offload = 1; } if (caps_cmd.rdmacaps) { @@ -4048,7 +4030,6 @@ static int adap_init0(struct adapter *adap) } #undef FW_PARAM_PFVF #undef FW_PARAM_DEV -#endif /* CONFIG_CHELSIO_T4_OFFLOAD */ /* * These are finalized by FW initialization, load their values now. diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h index 1b899fea1a91..39bec73ff87c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h @@ -102,6 +102,9 @@ struct tid_info { unsigned int ftid_base; unsigned int aftid_base; unsigned int aftid_end; + /* Server filter region */ + unsigned int sftid_base; + unsigned int nsftids; spinlock_t atid_lock ____cacheline_aligned_in_smp; union aopen_entry *afree; -- cgit v1.2.3-55-g7522 From 2c14575f99ddd5b8384c5b460687ceba181900d8 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Fri, 5 Oct 2012 12:26:32 +0200 Subject: drm/nouveau: handle same-fb page flips It's questionable use case, but weston/wayland already relies on this behaviour, and other drivers don't care about it, so it's a matter of compatibility. Without it, process invoking such page flip hangs in unkillable state, trying to reserve the same buffer twice. Signed-off-by: Marcin Slusarz Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_display.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 61f370d000e9..53ee3037d309 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -530,9 +530,11 @@ nouveau_page_flip_reserve(struct nouveau_bo *old_bo, if (ret) goto fail; - ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0); - if (ret) - goto fail_unreserve; + if (likely(old_bo != new_bo)) { + ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0); + if (ret) + goto fail_unreserve; + } return 0; @@ -551,8 +553,10 @@ nouveau_page_flip_unreserve(struct nouveau_bo *old_bo, nouveau_bo_fence(new_bo, fence); ttm_bo_unreserve(&new_bo->bo); - nouveau_bo_fence(old_bo, fence); - ttm_bo_unreserve(&old_bo->bo); + if (likely(old_bo != new_bo)) { + nouveau_bo_fence(old_bo, fence); + ttm_bo_unreserve(&old_bo->bo); + } nouveau_bo_unpin(old_bo); } -- cgit v1.2.3-55-g7522 From 90e2889c4e24e2bde8f226402b46c66e18162860 Mon Sep 17 00:00:00 2001 From: Martin Peres Date: Sat, 20 Oct 2012 11:03:36 +0200 Subject: drm/nouveau/bios: improve error handling when reading the vbios from ACPI Reported-by: Pawel Sikora Signed-off-by: Martin Peres Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/bios/base.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index dcb5c2befc92..f65bfedcce66 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c @@ -188,8 +188,10 @@ nouveau_bios_shadow_acpi(struct nouveau_bios *bios) int ret, cnt, i; u8 data[3]; - if (!nouveau_acpi_rom_supported(pdev)) + if (!nouveau_acpi_rom_supported(pdev)) { + bios->data = NULL; return; + } bios->size = 0; if (nouveau_acpi_get_bios_chunk(data, 0, 3) == 3) -- cgit v1.2.3-55-g7522 From 92485cef52c2de0f98efdf527ea39cef2b9fc416 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Mon, 22 Oct 2012 00:20:32 +0200 Subject: drm/nouveau: fix nouveau_mm/nouveau_mm_node leak v2: use already existing parent Signed-off-by: Marcin Slusarz Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/core/gpuobj.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/core/core/gpuobj.c b/drivers/gpu/drm/nouveau/core/core/gpuobj.c index 1f34549aff18..70586fde69cf 100644 --- a/drivers/gpu/drm/nouveau/core/core/gpuobj.c +++ b/drivers/gpu/drm/nouveau/core/core/gpuobj.c @@ -39,6 +39,11 @@ nouveau_gpuobj_destroy(struct nouveau_gpuobj *gpuobj) nv_wo32(gpuobj, i, 0x00000000); } + if (gpuobj->node) { + nouveau_mm_free(&nv_gpuobj(gpuobj->parent)->heap, + &gpuobj->node); + } + if (gpuobj->heap.block_size) nouveau_mm_fini(&gpuobj->heap); -- cgit v1.2.3-55-g7522 From 0bab097a9b18d7ad1a65c9263b3f896fc1f4b6ff Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Mon, 22 Oct 2012 00:21:39 +0200 Subject: drm/nouveau: warn when trying to free mm which is still in use Signed-off-by: Marcin Slusarz Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/core/mm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/core/core/mm.c b/drivers/gpu/drm/nouveau/core/core/mm.c index bfddf87926dd..4d6206448670 100644 --- a/drivers/gpu/drm/nouveau/core/core/mm.c +++ b/drivers/gpu/drm/nouveau/core/core/mm.c @@ -236,7 +236,7 @@ nouveau_mm_fini(struct nouveau_mm *mm) int nodes = 0; list_for_each_entry(node, &mm->nodes, nl_entry) { - if (nodes++ == mm->heap_nodes) + if (WARN_ON(nodes++ == mm->heap_nodes)) return -EBUSY; } -- cgit v1.2.3-55-g7522 From 00e4845bad84689fbaacc86bc54a0b99d5d3c1fc Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Mon, 22 Oct 2012 09:59:20 +1000 Subject: drm/nouveau: validate vbios size Without checking, we could detect vbios size as 0, allocate 0-byte array (kmalloc returns invalid pointer for such allocation) and crash in nouveau_bios_score while checking for vbios signature. Reported-by: Heinz Diehl Signed-off-by: Marcin Slusarz Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/bios/base.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index f65bfedcce66..3a84ad4f171a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c @@ -72,7 +72,7 @@ nouveau_bios_shadow_of(struct nouveau_bios *bios) } data = of_get_property(dn, "NVDA,BMP", &size); - if (data) { + if (data && size) { bios->size = size; bios->data = kmalloc(bios->size, GFP_KERNEL); if (bios->data) @@ -104,6 +104,9 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios) goto out; bios->size = nv_rd08(bios, 0x700002) * 512; + if (!bios->size) + goto out; + bios->data = kmalloc(bios->size, GFP_KERNEL); if (bios->data) { for (i = 0; i < bios->size; i++) @@ -155,6 +158,9 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios) /* read entire bios image to system memory */ bios->size = nv_rd08(bios, 0x300002) * 512; + if (!bios->size) + goto out; + bios->data = kmalloc(bios->size, GFP_KERNEL); if (bios->data) { for (i = 0; i < bios->size; i++) @@ -196,6 +202,8 @@ nouveau_bios_shadow_acpi(struct nouveau_bios *bios) bios->size = 0; if (nouveau_acpi_get_bios_chunk(data, 0, 3) == 3) bios->size = data[2] * 512; + if (!bios->size) + return; bios->data = kmalloc(bios->size, GFP_KERNEL); for (i = 0; bios->data && i < bios->size; i += cnt) { @@ -231,12 +239,14 @@ nouveau_bios_shadow_pci(struct nouveau_bios *bios) static int nouveau_bios_score(struct nouveau_bios *bios, const bool writeable) { - if (!bios->data || bios->data[0] != 0x55 || bios->data[1] != 0xAA) { + if (bios->size < 3 || !bios->data || bios->data[0] != 0x55 || + bios->data[1] != 0xAA) { nv_info(bios, "... signature not found\n"); return 0; } - if (nvbios_checksum(bios->data, bios->data[2] * 512)) { + if (nvbios_checksum(bios->data, + min_t(u32, bios->data[2] * 512, bios->size))) { nv_info(bios, "... checksum invalid\n"); /* if a ro image is somewhat bad, it's probably all rubbish */ return writeable ? 2 : 1; -- cgit v1.2.3-55-g7522 From 8dee001d98813c4cfa0be92ae3da7cabdc954c63 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 7 Aug 2012 14:46:32 +0530 Subject: extcon: Remove duplicate inclusion of extcon.h header file extcon.h header file was included twice. Signed-off-by: Sachin Kamat Signed-off-by: Sachin Kamat Signed-off-by: MyungJoo Ham --- drivers/extcon/extcon-gpio.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c index 3cc152e690b0..71d3ab7b3d8d 100644 --- a/drivers/extcon/extcon-gpio.c +++ b/drivers/extcon/extcon-gpio.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3-55-g7522 From 3cafbd4e5005dbef78b32f2e0fe3ab00a955c6c1 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Fri, 31 Aug 2012 14:00:19 +0530 Subject: extcon-max8997: remove usage of ret in max8997_muic_handle_charger_type_detach actually we can do returns with error or success with out ret in this function, so remove the ret variable, and reduce a very little (4byte) space on stack of this function Signed-off-by: Devendra Naga Signed-off-by: MyungJoo Ham --- drivers/extcon/extcon-max8997.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c index ef9090a4271d..77b66b0cc8f5 100644 --- a/drivers/extcon/extcon-max8997.c +++ b/drivers/extcon/extcon-max8997.c @@ -271,8 +271,6 @@ out: static int max8997_muic_handle_charger_type_detach( struct max8997_muic_info *info) { - int ret = 0; - switch (info->pre_charger_type) { case MAX8997_CHARGER_TYPE_USB: extcon_set_cable_state(info->edev, "USB", false); @@ -290,11 +288,11 @@ static int max8997_muic_handle_charger_type_detach( extcon_set_cable_state(info->edev, "Fast-charger", false); break; default: - ret = -EINVAL; + return -EINVAL; break; } - return ret; + return 0; } static int max8997_muic_handle_charger_type(struct max8997_muic_info *info, -- cgit v1.2.3-55-g7522 From 0cf6ad8a18f7f7bdbb81975188d9e0656ef277dd Mon Sep 17 00:00:00 2001 From: anish kumar Date: Thu, 30 Aug 2012 00:35:09 +0530 Subject: extcon: standard cable names definition and declaration changed With this change now individual drivers can use standard cable names as below: static const char *arizona_cable[] = { extcon_cable_name[EXTCON_USB], extcon_cable_name[EXTCON_USB_HOST], "CUSTOM_CABLE" NULL, } Signed-off-by: anish kumar Signed-off-by: MyungJoo Ham --- drivers/extcon/extcon-class.c | 4 +--- include/linux/extcon.h | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 946a3188b2b7..1e1a3f17a782 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -41,7 +41,7 @@ * every single port-type of the following cable names. Please choose cable * names that are actually used in your extcon device. */ -const char *extcon_cable_name[] = { +const char extcon_cable_name[][CABLE_NAME_MAX + 1] = { [EXTCON_USB] = "USB", [EXTCON_USB_HOST] = "USB-Host", [EXTCON_TA] = "TA", @@ -62,8 +62,6 @@ const char *extcon_cable_name[] = { [EXTCON_VIDEO_IN] = "Video-in", [EXTCON_VIDEO_OUT] = "Video-out", [EXTCON_MECHANICAL] = "Mechanical", - - NULL, }; static struct class *extcon_class; diff --git a/include/linux/extcon.h b/include/linux/extcon.h index 7443a560c9d0..2c26c14cd710 100644 --- a/include/linux/extcon.h +++ b/include/linux/extcon.h @@ -68,7 +68,7 @@ enum extcon_cable_name { EXTCON_VIDEO_OUT, EXTCON_MECHANICAL, }; -extern const char *extcon_cable_name[]; +extern const char extcon_cable_name[][CABLE_NAME_MAX + 1]; struct extcon_cable; -- cgit v1.2.3-55-g7522 From 28c0ada62d39eaafef03d88a4e6f4c5bcb6e1b6c Mon Sep 17 00:00:00 2001 From: anish kumar Date: Thu, 30 Aug 2012 00:35:10 +0530 Subject: extcon: optimising the check_mutually_exclusive function Rather than re-inventing the wheel we can use the hamming function to calculate the number of bits set to check for violation of exclusivity. Signed-off-by: anish kumar Signed-off-by: MyungJoo Ham --- drivers/extcon/extcon-class.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 1e1a3f17a782..1ce76a8d777b 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -89,17 +89,13 @@ static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state) return 0; for (i = 0; edev->mutually_exclusive[i]; i++) { - int count = 0, j; + int weight; u32 correspondants = new_state & edev->mutually_exclusive[i]; - u32 exp = 1; - - for (j = 0; j < 32; j++) { - if (exp & correspondants) - count++; - if (count > 1) - return i + 1; - exp <<= 1; - } + + /* calculate the total number of bits set */ + weight = hweight32(correspondants); + if (weight > 1) + return i + 1; } return 0; -- cgit v1.2.3-55-g7522 From d1626a965141b1e600efad29947b6c36dab183c3 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 22 Oct 2012 10:08:19 +1000 Subject: drm/nouveau/bios: fetch full 4KiB block to determine ACPI ROM image size Buggy firmware leads to bad things happening otherwise.. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/bios/base.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index 3a84ad4f171a..70ca7d5a1aa1 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c @@ -192,7 +192,6 @@ nouveau_bios_shadow_acpi(struct nouveau_bios *bios) { struct pci_dev *pdev = nv_device(bios)->pdev; int ret, cnt, i; - u8 data[3]; if (!nouveau_acpi_rom_supported(pdev)) { bios->data = NULL; @@ -200,8 +199,13 @@ nouveau_bios_shadow_acpi(struct nouveau_bios *bios) } bios->size = 0; - if (nouveau_acpi_get_bios_chunk(data, 0, 3) == 3) - bios->size = data[2] * 512; + bios->data = kmalloc(4096, GFP_KERNEL); + if (bios->data) { + if (nouveau_acpi_get_bios_chunk(bios->data, 0, 4096) == 4096) + bios->size = bios->data[2] * 512; + kfree(bios->data); + } + if (!bios->size) return; -- cgit v1.2.3-55-g7522 From 4bf24c02150a4c5e31d397342b1157496f1881ee Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 22 Oct 2012 10:56:07 +1000 Subject: drm/nv41/vm: don't init hw pciegart on boards with agp bridge Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c | 3 ++- drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c index 0203e1e12caa..49050d991e75 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c @@ -92,7 +92,8 @@ nv41_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nv04_vmmgr_priv *priv; int ret; - if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) { + if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) || + !nouveau_boolopt(device->cfgopt, "NvPCIE", true)) { return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass, data, size, pobject); } diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c index 0ac18d05a146..aa8131436e3d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c @@ -163,7 +163,8 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nv04_vmmgr_priv *priv; int ret; - if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) { + if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) || + !nouveau_boolopt(device->cfgopt, "NvPCIE", true)) { return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass, data, size, pobject); } -- cgit v1.2.3-55-g7522 From 2c25b7399570ebdcf737c5af67c9d26a1771c002 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 22 Oct 2012 13:40:36 +1000 Subject: drm/nouveau/fb: fix reporting of memory type on GF8+ IGPs Purely a cosmetic issue at this point. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c index 42d7539e6525..27fb1af7a779 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c @@ -237,6 +237,7 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.ram.stolen = (u64)nv_rd32(priv, 0x100e10) << 12; + priv->base.ram.type = NV_MEM_TYPE_STOLEN; break; default: ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size, -- cgit v1.2.3-55-g7522 From 5e5a195ecc8cc0280d169d6da33c959df6336e9f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 22 Oct 2012 14:10:16 +1000 Subject: drm/nouveau/clock: fix missing pll type/addr when matching default entry This issue is a regression from 70790f4f819875e8f390871fd15bbbf823f28e1b, and causes us to miss a special-case for C51 (NV4E) chipsets and return the wrong reference frequency for the VPLLs. Should fix fdo#56202 Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/bios/pll.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c b/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c index 5e5f4cddae3c..f835501203e5 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c @@ -157,11 +157,10 @@ pll_map_reg(struct nouveau_bios *bios, u32 reg, u32 *type, u8 *ver, u8 *len) while (map->reg) { if (map->reg == reg && *ver >= 0x20) { u16 addr = (data += hdr); + *type = map->type; while (cnt--) { - if (nv_ro32(bios, data) == map->reg) { - *type = map->type; + if (nv_ro32(bios, data) == map->reg) return data; - } data += *len; } return addr; @@ -200,11 +199,10 @@ pll_map_type(struct nouveau_bios *bios, u8 type, u32 *reg, u8 *ver, u8 *len) while (map->reg) { if (map->type == type && *ver >= 0x20) { u16 addr = (data += hdr); + *reg = map->reg; while (cnt--) { - if (nv_ro32(bios, data) == map->reg) { - *reg = map->reg; + if (nv_ro32(bios, data) == map->reg) return data; - } data += *len; } return addr; -- cgit v1.2.3-55-g7522 From 4a215aade0baa0487d4644d7aef6f166c84c516e Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 21 Oct 2012 17:57:20 -0700 Subject: Input: fix use-after-free introduced with dynamic minor changes Commit 7f8d4cad1e4e ("Input: extend the number of event (and other) devices") made evdev, joydev and mousedev to embed struct cdev into their respective structures representing input devices. Unfortunately character device structure may outlive the parent structure unless we do not set it up as parent of character device so that it will stay pinned until character device is freed. Also, now that parent structure is pinned while character device exists we do not need to pin and unpin it every time user opens or closes it. Reported-by: Dave Jones Signed-off-by: Dmitry Torokhov Acked-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/input/evdev.c | 3 +-- drivers/input/joydev.c | 3 +-- drivers/input/mousedev.c | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 6ae2ac47c9c8..f0f8928b3c8a 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -292,7 +292,6 @@ static int evdev_release(struct inode *inode, struct file *file) kfree(client); evdev_close_device(evdev); - put_device(&evdev->dev); return 0; } @@ -331,7 +330,6 @@ static int evdev_open(struct inode *inode, struct file *file) file->private_data = client; nonseekable_open(inode, file); - get_device(&evdev->dev); return 0; err_free_client: @@ -1001,6 +999,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, goto err_free_evdev; cdev_init(&evdev->cdev, &evdev_fops); + evdev->cdev.kobj.parent = &evdev->dev.kobj; error = cdev_add(&evdev->cdev, evdev->dev.devt, 1); if (error) goto err_unregister_handle; diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index b62b5891f399..f362883c94e3 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -243,7 +243,6 @@ static int joydev_release(struct inode *inode, struct file *file) kfree(client); joydev_close_device(joydev); - put_device(&joydev->dev); return 0; } @@ -270,7 +269,6 @@ static int joydev_open(struct inode *inode, struct file *file) file->private_data = client; nonseekable_open(inode, file); - get_device(&joydev->dev); return 0; err_free_client: @@ -858,6 +856,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, goto err_free_joydev; cdev_init(&joydev->cdev, &joydev_fops); + joydev->cdev.kobj.parent = &joydev->dev.kobj; error = cdev_add(&joydev->cdev, joydev->dev.devt, 1); if (error) goto err_unregister_handle; diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index a1b4c37956b2..8f02e3d0e712 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -523,7 +523,6 @@ static int mousedev_release(struct inode *inode, struct file *file) kfree(client); mousedev_close_device(mousedev); - put_device(&mousedev->dev); return 0; } @@ -558,7 +557,6 @@ static int mousedev_open(struct inode *inode, struct file *file) file->private_data = client; nonseekable_open(inode, file); - get_device(&mousedev->dev); return 0; err_free_client: @@ -892,6 +890,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev, } cdev_init(&mousedev->cdev, &mousedev_fops); + mousedev->cdev.kobj.parent = &mousedev->dev.kobj; error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1); if (error) goto err_unregister_handle; -- cgit v1.2.3-55-g7522 From 373304fe10fc46e68815c7116709ad292695dfd1 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 9 Oct 2012 12:01:01 +0800 Subject: firmware loader: cancel uncache work before caching firmware Under 'Opportunistic sleep' situation, system sleep might be triggered very frequently, so the uncahce work may not be completed before caching firmware during next suspend. This patch cancels the uncache work before caching firmware to fix the problem above. Also this patch optimizes the cacheing firmware mechanism a bit by only storing one firmware cache entry for one firmware image. So if the firmware is still cached during suspend, it doesn't need to be loaded from user space any more. Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 81541452887b..d06a8d0534bf 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -1142,17 +1142,27 @@ exit: return fce; } -static int fw_cache_piggyback_on_request(const char *name) +static int __fw_entry_found(const char *name) { struct firmware_cache *fwc = &fw_cache; struct fw_cache_entry *fce; - int ret = 0; - spin_lock(&fwc->name_lock); list_for_each_entry(fce, &fwc->fw_names, list) { if (!strcmp(fce->name, name)) - goto found; + return 1; } + return 0; +} + +static int fw_cache_piggyback_on_request(const char *name) +{ + struct firmware_cache *fwc = &fw_cache; + struct fw_cache_entry *fce; + int ret = 0; + + spin_lock(&fwc->name_lock); + if (__fw_entry_found(name)) + goto found; fce = alloc_fw_cache_entry(name); if (fce) { @@ -1229,11 +1239,19 @@ static void dev_cache_fw_image(struct device *dev, void *data) list_del(&fce->list); spin_lock(&fwc->name_lock); - fwc->cnt++; - list_add(&fce->list, &fwc->fw_names); + /* only one cache entry for one firmware */ + if (!__fw_entry_found(fce->name)) { + fwc->cnt++; + list_add(&fce->list, &fwc->fw_names); + } else { + free_fw_cache_entry(fce); + fce = NULL; + } spin_unlock(&fwc->name_lock); - async_schedule(__async_dev_cache_fw_image, (void *)fce); + if (fce) + async_schedule(__async_dev_cache_fw_image, + (void *)fce); } } @@ -1275,6 +1293,9 @@ static void device_cache_fw_images(void) pr_debug("%s\n", __func__); + /* cancel uncache work */ + cancel_delayed_work_sync(&fwc->work); + /* * use small loading timeout for caching devices' firmware * because all these firmware images have been loaded -- cgit v1.2.3-55-g7522 From 253c9240ee09fd2a05d315ea44ac037a893d8981 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 9 Oct 2012 12:01:02 +0800 Subject: firmware loader: fix one reqeust_firmware race Several loading requests may be pending on one same firmware buf, and this patch moves fw_map_pages_buf() before complete_all(&fw_buf->completion) and let all requests see the mapped 'buf->data' once the loading is completed. Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index d06a8d0534bf..f2882511a9c1 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -423,6 +423,18 @@ static void firmware_free_data(const struct firmware *fw) #ifndef PAGE_KERNEL_RO #define PAGE_KERNEL_RO PAGE_KERNEL #endif + +/* one pages buffer should be mapped/unmapped only once */ +static int fw_map_pages_buf(struct firmware_buf *buf) +{ + if (buf->data) + vunmap(buf->data); + buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO); + if (!buf->data) + return -ENOMEM; + return 0; +} + /** * firmware_loading_store - set value in the 'loading' control file * @dev: device pointer @@ -467,6 +479,14 @@ static ssize_t firmware_loading_store(struct device *dev, if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) { set_bit(FW_STATUS_DONE, &fw_buf->status); clear_bit(FW_STATUS_LOADING, &fw_buf->status); + + /* + * Several loading requests may be pending on + * one same firmware buf, so let all requests + * see the mapped 'buf->data' once the loading + * is completed. + * */ + fw_map_pages_buf(fw_buf); complete_all(&fw_buf->completion); break; } @@ -670,15 +690,6 @@ exit: return fw_priv; } -/* one pages buffer is mapped/unmapped only once */ -static int fw_map_pages_buf(struct firmware_buf *buf) -{ - buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO); - if (!buf->data) - return -ENOMEM; - return 0; -} - /* store the pages buffer info firmware from buf */ static void fw_set_page_data(struct firmware_buf *buf, struct firmware *fw) { @@ -884,9 +895,6 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, if (!retval && f_dev->parent) fw_add_devm_name(f_dev->parent, buf->fw_id); - if (!retval) - retval = fw_map_pages_buf(buf); - /* * After caching firmware image is started, let it piggyback * on request firmware. -- cgit v1.2.3-55-g7522 From 746058f4304343507e48d39f80d7a3b0d8550e3a Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 9 Oct 2012 12:01:03 +0800 Subject: firmware loader: let direct loading back on 'firmware_buf' Firstly 'firmware_buf' is introduced to make all loading requests to share one firmware kernel buffer, so firmware_buf should be used in direct loading for saving memory and speedup firmware loading. Secondly, the commit below abb139e75c2cdbb955e840d6331cb5863e409d0e(firmware:teach the kernel to load firmware files directly from the filesystem) introduces direct loading for fixing udev regression, but it bypasses the firmware cache meachnism, so this patch enables caching firmware for direct loading case since it is still needed to solve drivers' dependency during system resume. Cc: Linus Torvalds Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 171 ++++++++++++++++++++++++------------------ 1 file changed, 100 insertions(+), 71 deletions(-) (limited to 'drivers') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index f2882511a9c1..a095d84ddfd9 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -36,68 +36,6 @@ MODULE_AUTHOR("Manuel Estrada Sainz"); MODULE_DESCRIPTION("Multi purpose firmware loading support"); MODULE_LICENSE("GPL"); -static const char *fw_path[] = { - "/lib/firmware/updates/" UTS_RELEASE, - "/lib/firmware/updates", - "/lib/firmware/" UTS_RELEASE, - "/lib/firmware" -}; - -/* Don't inline this: 'struct kstat' is biggish */ -static noinline long fw_file_size(struct file *file) -{ - struct kstat st; - if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st)) - return -1; - if (!S_ISREG(st.mode)) - return -1; - if (st.size != (long)st.size) - return -1; - return st.size; -} - -static bool fw_read_file_contents(struct file *file, struct firmware *fw) -{ - long size; - char *buf; - - size = fw_file_size(file); - if (size < 0) - return false; - buf = vmalloc(size); - if (!buf) - return false; - if (kernel_read(file, 0, buf, size) != size) { - vfree(buf); - return false; - } - fw->data = buf; - fw->size = size; - return true; -} - -static bool fw_get_filesystem_firmware(struct firmware *fw, const char *name) -{ - int i; - bool success = false; - char *path = __getname(); - - for (i = 0; i < ARRAY_SIZE(fw_path); i++) { - struct file *file; - snprintf(path, PATH_MAX, "%s/%s", fw_path[i], name); - - file = filp_open(path, O_RDONLY, 0); - if (IS_ERR(file)) - continue; - success = fw_read_file_contents(file, fw); - fput(file); - if (success) - break; - } - __putname(path); - return success; -} - /* Builtin firmware support */ #ifdef CONFIG_FW_LOADER @@ -150,6 +88,11 @@ enum { FW_STATUS_ABORT, }; +enum fw_buf_fmt { + VMALLOC_BUF, /* used in direct loading */ + PAGE_BUF, /* used in loading via userspace */ +}; + static int loading_timeout = 60; /* In seconds */ static inline long firmware_loading_timeout(void) @@ -187,6 +130,7 @@ struct firmware_buf { struct completion completion; struct firmware_cache *fwc; unsigned long status; + enum fw_buf_fmt fmt; void *data; size_t size; struct page **pages; @@ -240,6 +184,7 @@ static struct firmware_buf *__allocate_fw_buf(const char *fw_name, strcpy(buf->fw_id, fw_name); buf->fwc = fwc; init_completion(&buf->completion); + buf->fmt = VMALLOC_BUF; pr_debug("%s: fw-%s buf=%p\n", __func__, fw_name, buf); @@ -307,10 +252,14 @@ static void __fw_free_buf(struct kref *ref) list_del(&buf->list); spin_unlock(&fwc->lock); - vunmap(buf->data); - for (i = 0; i < buf->nr_pages; i++) - __free_page(buf->pages[i]); - kfree(buf->pages); + + if (buf->fmt == PAGE_BUF) { + vunmap(buf->data); + for (i = 0; i < buf->nr_pages; i++) + __free_page(buf->pages[i]); + kfree(buf->pages); + } else + vfree(buf->data); kfree(buf); } @@ -319,6 +268,69 @@ static void fw_free_buf(struct firmware_buf *buf) kref_put(&buf->ref, __fw_free_buf); } +/* direct firmware loading support */ +static const char *fw_path[] = { + "/lib/firmware/updates/" UTS_RELEASE, + "/lib/firmware/updates", + "/lib/firmware/" UTS_RELEASE, + "/lib/firmware" +}; + +/* Don't inline this: 'struct kstat' is biggish */ +static noinline long fw_file_size(struct file *file) +{ + struct kstat st; + if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st)) + return -1; + if (!S_ISREG(st.mode)) + return -1; + if (st.size != (long)st.size) + return -1; + return st.size; +} + +static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf) +{ + long size; + char *buf; + + size = fw_file_size(file); + if (size < 0) + return false; + buf = vmalloc(size); + if (!buf) + return false; + if (kernel_read(file, 0, buf, size) != size) { + vfree(buf); + return false; + } + fw_buf->data = buf; + fw_buf->size = size; + return true; +} + +static bool fw_get_filesystem_firmware(struct firmware_buf *buf) +{ + int i; + bool success = false; + char *path = __getname(); + + for (i = 0; i < ARRAY_SIZE(fw_path); i++) { + struct file *file; + snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id); + + file = filp_open(path, O_RDONLY, 0); + if (IS_ERR(file)) + continue; + success = fw_read_file_contents(file, buf); + fput(file); + if (success) + break; + } + __putname(path); + return success; +} + static struct firmware_priv *to_firmware_priv(struct device *dev) { return container_of(dev, struct firmware_priv, dev); @@ -427,6 +439,9 @@ static void firmware_free_data(const struct firmware *fw) /* one pages buffer should be mapped/unmapped only once */ static int fw_map_pages_buf(struct firmware_buf *buf) { + if (buf->fmt != PAGE_BUF) + return 0; + if (buf->data) vunmap(buf->data); buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO); @@ -789,11 +804,6 @@ _request_firmware_prepare(const struct firmware **firmware_p, const char *name, return NULL; } - if (fw_get_filesystem_firmware(firmware, name)) { - dev_dbg(device, "firmware: direct-loading firmware %s\n", name); - return NULL; - } - ret = fw_lookup_and_allocate_buf(name, &fw_cache, &buf); if (!ret) fw_priv = fw_create_instance(firmware, name, device, @@ -843,6 +853,21 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, struct device *f_dev = &fw_priv->dev; struct firmware_buf *buf = fw_priv->buf; struct firmware_cache *fwc = &fw_cache; + int direct_load = 0; + + /* try direct loading from fs first */ + if (fw_get_filesystem_firmware(buf)) { + dev_dbg(f_dev->parent, "firmware: direct-loading" + " firmware %s\n", buf->fw_id); + + set_bit(FW_STATUS_DONE, &buf->status); + complete_all(&buf->completion); + direct_load = 1; + goto handle_fw; + } + + /* fall back on userspace loading */ + buf->fmt = PAGE_BUF; dev_set_uevent_suppress(f_dev, true); @@ -881,6 +906,7 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, del_timer_sync(&fw_priv->timeout); +handle_fw: mutex_lock(&fw_lock); if (!buf->size || test_bit(FW_STATUS_ABORT, &buf->status)) retval = -ENOENT; @@ -910,6 +936,9 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, fw_priv->buf = NULL; mutex_unlock(&fw_lock); + if (direct_load) + goto err_put_dev; + device_remove_file(f_dev, &dev_attr_loading); err_del_bin_attr: device_remove_bin_file(f_dev, &firmware_attr_data); -- cgit v1.2.3-55-g7522 From d28d3882bd1fdb88ae4e02f11b091a92b0e5068b Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 9 Oct 2012 12:01:04 +0800 Subject: firmware loader: sync firmware cache by async_synchronize_full_domain async.c has provided synchronization mechanism on async_schedule_*, so use async_synchronize_full_domain to sync caching firmware instead of reinventing the wheel. Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 34 ++++++---------------------------- 1 file changed, 6 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index a095d84ddfd9..8945f4e489ed 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -116,8 +116,6 @@ struct firmware_cache { spinlock_t name_lock; struct list_head fw_names; - wait_queue_head_t wait_queue; - int cnt; struct delayed_work work; struct notifier_block pm_notify; @@ -1166,6 +1164,8 @@ int uncache_firmware(const char *fw_name) } #ifdef CONFIG_PM_SLEEP +static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain); + static struct fw_cache_entry *alloc_fw_cache_entry(const char *name) { struct fw_cache_entry *fce; @@ -1232,12 +1232,6 @@ static void __async_dev_cache_fw_image(void *fw_entry, free_fw_cache_entry(fce); } - - spin_lock(&fwc->name_lock); - fwc->cnt--; - spin_unlock(&fwc->name_lock); - - wake_up(&fwc->wait_queue); } /* called with dev->devres_lock held */ @@ -1278,7 +1272,6 @@ static void dev_cache_fw_image(struct device *dev, void *data) spin_lock(&fwc->name_lock); /* only one cache entry for one firmware */ if (!__fw_entry_found(fce->name)) { - fwc->cnt++; list_add(&fce->list, &fwc->fw_names); } else { free_fw_cache_entry(fce); @@ -1287,8 +1280,9 @@ static void dev_cache_fw_image(struct device *dev, void *data) spin_unlock(&fwc->name_lock); if (fce) - async_schedule(__async_dev_cache_fw_image, - (void *)fce); + async_schedule_domain(__async_dev_cache_fw_image, + (void *)fce, + &fw_cache_domain); } } @@ -1350,21 +1344,7 @@ static void device_cache_fw_images(void) mutex_unlock(&fw_lock); /* wait for completion of caching firmware for all devices */ - spin_lock(&fwc->name_lock); - for (;;) { - prepare_to_wait(&fwc->wait_queue, &wait, - TASK_UNINTERRUPTIBLE); - if (!fwc->cnt) - break; - - spin_unlock(&fwc->name_lock); - - schedule(); - - spin_lock(&fwc->name_lock); - } - spin_unlock(&fwc->name_lock); - finish_wait(&fwc->wait_queue, &wait); + async_synchronize_full_domain(&fw_cache_domain); loading_timeout = old_timeout; } @@ -1452,9 +1432,7 @@ static void __init fw_cache_init(void) #ifdef CONFIG_PM_SLEEP spin_lock_init(&fw_cache.name_lock); INIT_LIST_HEAD(&fw_cache.fw_names); - fw_cache.cnt = 0; - init_waitqueue_head(&fw_cache.wait_queue); INIT_DELAYED_WORK(&fw_cache.work, device_uncache_fw_images_work); -- cgit v1.2.3-55-g7522 From 32c631f9f2566d09d32abc2f4c7aa24c6d8b5641 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Fri, 12 Oct 2012 21:10:11 +0000 Subject: RDMA/cxgb4: Don't free chunk that we have failed to allocate In the error path of registering memory when there's a failure to allocate a chunk from the memory pool, we try to free the same chunk we just failed to allocate, which will BUG(). Signed-off-by: Thadeu Lima de Souza Cascardo Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb4/mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c index 57e07c61ace2..afd81790ab3c 100644 --- a/drivers/infiniband/hw/cxgb4/mem.c +++ b/drivers/infiniband/hw/cxgb4/mem.c @@ -468,7 +468,7 @@ struct ib_mr *c4iw_register_phys_mem(struct ib_pd *pd, ret = alloc_pbl(mhp, npages); if (ret) { kfree(page_list); - goto err_pbl; + goto err; } ret = write_pbl(&mhp->rhp->rdev, page_list, mhp->attr.pbl_addr, -- cgit v1.2.3-55-g7522 From 3b6054da68f9b0d5ed6a7ed0f42a79e61904352c Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Mon, 1 Oct 2012 22:21:12 +0300 Subject: usb hub: send clear_tt_buffer_complete events when canceling TT clear work There is a race condition in the USB hub code with regard to handling TT clear requests that can get the HCD driver in a deadlock. Usually when an TT clear request is scheduled it will be executed immediately: <7>[ 6.077583] usb 2-1.3: unlink qh1-0e01/f4d4db00 start 0 [1/2 us] <3>[ 6.078041] usb 2-1: clear tt buffer port 3, a3 ep2 t04048d82 <7>[ 6.078299] hub_tt_work:731 <7>[ 9.309089] usb 2-1.5: link qh1-0e01/f4d506c0 start 0 [1/2 us] <7>[ 9.324526] ehci_hcd 0000:00:1d.0: reused qh f4d4db00 schedule <7>[ 9.324539] usb 2-1.3: link qh1-0e01/f4d4db00 start 0 [1/2 us] <7>[ 9.341530] usb 1-1.1: link qh4-0e01/f397aec0 start 2 [1/2 us] <7>[ 10.116159] usb 2-1.3: unlink qh1-0e01/f4d4db00 start 0 [1/2 us] <3>[ 10.116459] usb 2-1: clear tt buffer port 3, a3 ep2 t04048d82 <7>[ 10.116537] hub_tt_work:731 However, if a suspend operation is triggered before hub_tt_work is scheduled, hub_quiesce will cancel the work without notifying the HCD driver: <3>[ 35.033941] usb 2-1: clear tt buffer port 3, a3 ep2 t04048d80 <5>[ 35.034022] sd 0:0:0:0: [sda] Stopping disk <7>[ 35.034039] hub 2-1:1.0: hub_suspend <7>[ 35.034067] usb 2-1: unlink qh256-0001/f3b1ab00 start 1 [1/0 us] <7>[ 35.035085] hub 1-0:1.0: hub_suspend <7>[ 35.035102] usb usb1: bus suspend, wakeup 0 <7>[ 35.035106] ehci_hcd 0000:00:1a.0: suspend root hub <7>[ 35.035298] hub 2-0:1.0: hub_suspend <7>[ 35.035313] usb usb2: bus suspend, wakeup 0 <7>[ 35.035315] ehci_hcd 0000:00:1d.0: suspend root hub <6>[ 35.250017] PM: suspend of devices complete after 216.979 msecs <6>[ 35.250822] PM: late suspend of devices complete after 0.799 msecs <7>[ 35.252343] ehci_hcd 0000:00:1d.0: wakeup: 1 <7>[ 35.262923] ehci_hcd 0000:00:1d.0: --> PCI D3hot <7>[ 35.263302] ehci_hcd 0000:00:1a.0: wakeup: 1 <7>[ 35.273912] ehci_hcd 0000:00:1a.0: --> PCI D3hot <6>[ 35.274254] PM: noirq suspend of devices complete after 23.442 msecs <6>[ 35.274975] ACPI: Preparing to enter system sleep state S3 <6>[ 35.292666] PM: Saving platform NVS memory <7>[ 35.295030] Disabling non-boot CPUs ... <6>[ 35.297351] CPU 1 is now offline <6>[ 35.300345] CPU 2 is now offline <6>[ 35.303929] CPU 3 is now offline <7>[ 35.303931] lockdep: fixing up alternatives. <6>[ 35.304825] Extended CMOS year: 2000 When the device will resume the EHCI driver will get stuck in ehci_endpoint_disable waiting for the tt_clearing flag to reset: <0>[ 47.610967] usb 2-1.3: **** DPM device timeout **** <7>[ 47.610972] f2f11c60 00000092 f2f11c0c c10624a5 00000003 f4c6e880 c1c8a4c0 c1c8a4c0 <7>[ 47.610983] 15c55698 0000000b f56b34c0 f2a45b70 f4c6e880 00000082 f2a4602c f2f11c30 <7>[ 47.610993] c10787f8 f4cac000 f2a45b70 00000000 f4cac010 f2f11c58 00000046 00000001 <7>[ 47.611004] Call Trace: <7>[ 47.611006] [] ? sched_clock_cpu+0xf5/0x160 <7>[ 47.611019] [] ? lock_release_holdtime.part.22+0x88/0xf0 <7>[ 47.611026] [] ? lock_timer_base.isra.35+0x26/0x50 <7>[ 47.611034] [] ? schedule_timeout+0x133/0x290 <7>[ 47.611044] [] schedule+0x1e/0x50 <7>[ 47.611051] [] schedule_timeout+0x138/0x290 <7>[ 47.611057] [] ? sched_clock_cpu+0xf5/0x160 <7>[ 47.611063] [] ? usleep_range+0x40/0x40 <7>[ 47.611070] [] schedule_timeout_uninterruptible+0x15/0x20 <7>[ 47.611077] [] ehci_endpoint_disable+0x64/0x160 <7>[ 47.611084] [] ? usb_hcd_flush_endpoint+0x10e/0x1d0 <7>[ 47.611092] [] ? sysfs_add_file+0x13/0x20 <7>[ 47.611100] [] usb_hcd_disable_endpoint+0x29/0x40 <7>[ 47.611107] [] usb_disable_endpoint+0x5c/0x80 <7>[ 47.611111] [] usb_disable_interface+0x37/0x50 <7>[ 47.611116] [] usb_reset_and_verify_device+0x4b0/0x640 <7>[ 47.611122] [] ? hub_port_status+0xb5/0x100 <7>[ 47.611129] [] usb_port_resume+0xd5/0x220 <7>[ 47.611136] [] generic_resume+0xf/0x30 <7>[ 47.611142] [] usb_resume+0x133/0x180 <7>[ 47.611147] [] ? usb_dev_thaw+0x10/0x10 <7>[ 47.611152] [] usb_dev_resume+0xd/0x10 <7>[ 47.611157] [] dpm_run_callback+0x40/0xb0 <7>[ 47.611164] [] ? pm_runtime_enable+0x43/0x70 <7>[ 47.611171] [] device_resume+0x1a6/0x2c0 <7>[ 47.611177] [] ? dpm_show_time+0xe0/0xe0 <7>[ 47.611183] [] async_resume+0x19/0x40 <7>[ 47.611189] [] async_run_entry_fn+0x64/0x160 <7>[ 47.611196] [] ? process_one_work+0x104/0x480 <7>[ 47.611203] [] ? process_one_work+0x10c/0x480 <7>[ 47.611209] [] process_one_work+0x180/0x480 <7>[ 47.611215] [] ? process_one_work+0x104/0x480 <7>[ 47.611220] [] ? async_schedule+0x10/0x10 <7>[ 47.611226] [] worker_thread+0x11c/0x2f0 <7>[ 47.611233] [] ? manage_workers.isra.27+0x1f0/0x1f0 <7>[ 47.611239] [] kthread+0x78/0x80 <7>[ 47.611244] [] ? timer_cpu_notify+0xd6/0x20d <7>[ 47.611253] [] ? __init_kthread_worker+0x60/0x60 <7>[ 47.611258] [] kernel_thread_helper+0x6/0xd <7>[ 47.611283] ------------[ cut here ]------------ This patch changes hub_quiesce behavior to flush the TT clear work instead of canceling it, to make sure that no TT clear request remains uncompleted before suspend. Signed-off-by: Octavian Purdila Acked-by: Alan Stern Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 64854d76f529..1181e917fec7 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -739,13 +739,16 @@ static void hub_tt_work(struct work_struct *work) int limit = 100; spin_lock_irqsave (&hub->tt.lock, flags); - while (--limit && !list_empty (&hub->tt.clear_list)) { + while (!list_empty(&hub->tt.clear_list)) { struct list_head *next; struct usb_tt_clear *clear; struct usb_device *hdev = hub->hdev; const struct hc_driver *drv; int status; + if (!hub->quiescing && --limit < 0) + break; + next = hub->tt.clear_list.next; clear = list_entry (next, struct usb_tt_clear, clear_list); list_del (&clear->clear_list); @@ -1210,7 +1213,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) if (hub->has_indicators) cancel_delayed_work_sync(&hub->leds); if (hub->tt.hub) - cancel_work_sync(&hub->tt.clear_work); + flush_work_sync(&hub->tt.clear_work); } /* caller has locked the hub device */ -- cgit v1.2.3-55-g7522 From 6681e63399926651cc29bcb9d92229b6f1cf1daa Mon Sep 17 00:00:00 2001 From: Fred Brooks Date: Tue, 2 Oct 2012 11:10:26 +0100 Subject: staging: comedi: ni_daq_700: fix dio subdevice regression Here is a small patch to fix a problem caused by a previous patch that removed the callback function. The callback remove patch: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=1de02225358988e8fd48d1dc3fd12336bbae258a I finally booted my dev machine on the latest kernel (running Debian here so it's still on 3.2 normally) to test the ni_daq_700 driver with my test program and noticed this bug. Shift the DIO_R read result to bits 8..15 Digital direction configuration: channels 0-7 output, 8-15 input (8225 device emu as port A output, port B input, port C N/A). Cc: # 3.6.x Signed-off-by: Fred Brooks Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_daq_700.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 2ba0ade45c64..68d7c6a5db7d 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -95,7 +95,7 @@ static int daq700_dio_insn_bits(struct comedi_device *dev, } data[1] = s->state & 0xff; - data[1] |= inb(dev->iobase + DIO_R); + data[1] |= inb(dev->iobase + DIO_R) << 8; return insn->n; } -- cgit v1.2.3-55-g7522 From f4dd2367f3ad276fe49c89a522267ea5ccb6bf80 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 3 Oct 2012 16:25:15 +0100 Subject: staging: comedi: 8255_pci: fix possible NULL deref during detach `pci_8255_detach()` will be called by the comedi core if `pci_8255_attach_pci()` returns an error. It currently assumes that both `board` (assigned from the return value of `comedi_board(dev)`) and `devpriv` (assigned from `dev->private`) are non-null, but they might be null, leading to a null pointer dereference. `pci_8255_detach()` doesn't need to do anything if either `board` or `devpriv` are null, so just return early in this case. Cc: # 3.6.x Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255_pci.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c index 7dff3c01dc29..d00aff6671df 100644 --- a/drivers/staging/comedi/drivers/8255_pci.c +++ b/drivers/staging/comedi/drivers/8255_pci.c @@ -289,6 +289,8 @@ static void pci_8255_detach(struct comedi_device *dev) struct comedi_subdevice *s; int i; + if (!board || !devpriv) + return; if (dev->subdevices) { for (i = 0; i < board->n_8255; i++) { s = &dev->subdevices[i]; -- cgit v1.2.3-55-g7522 From dfb2540e91e1f63765bc3ff497ad0b714d774261 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 3 Oct 2012 16:25:16 +0100 Subject: staging: comedi: amplc_dio200: fix possible NULL deref during detach `dio200_detach()` is called by the comedi core to clean up if either `dio200_attach()` or `dio200_attach_pci()` return an error. It assigns `thisboard` to the return value of `comedi_board(dev)` and assumes it is non-null. In the case of a previous call to `dio200_attach()` it won't be `NULL` because the comedi core will have pointed it to one of the elements of `dio200_boards[]`, but in the case of a previous call to `dio200_attach_pci()` it could be `NULL`, leading to a null pointer dereference. Check that `thisboard` is valid at the top of `dio200_detach()` and return early if it is `NULL`. This is okay because the only other thing that could have been allocated is `dev->private` and that is freed by the comedi core, not by this function. Cc: # 3.6.x Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_dio200.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 08f305210a69..29eb52d11d2f 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -1410,6 +1410,8 @@ static void dio200_detach(struct comedi_device *dev) const struct dio200_layout_struct *layout; unsigned n; + if (!thisboard) + return; if (dev->irq) free_irq(dev->irq, dev); if (dev->subdevices) { -- cgit v1.2.3-55-g7522 From aaeb61a97b7159ebe30b18a422d04eeabfa8790b Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 3 Oct 2012 16:25:17 +0100 Subject: staging: comedi: amplc_pc236: fix invalid register access during detach `pc236_detach()` is called by the comedi core if it attempted to attach a device and failed. `pc236_detach()` calls `pc236_intr_disable()` if the comedi device private data pointer (`devpriv`) is non-null. This test is insufficient as `pc236_intr_disable()` accesses hardware registers and the attach routine may have failed before it has saved their I/O base addresses. Fix it by checking `dev->iobase` is non-zero before calling `pc236_intr_disable()` as that means the I/O base addresses have been saved and the hardware registers can be accessed. It also implies the comedi device private data pointer is valid, so there is no need to check it. Cc: # 3.5.x, 3.6.x Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc236.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index eacb5e4735d7..36768b2b30ae 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -573,9 +573,8 @@ static int __devinit pc236_attach_pci(struct comedi_device *dev, static void pc236_detach(struct comedi_device *dev) { const struct pc236_board *thisboard = comedi_board(dev); - struct pc236_private *devpriv = dev->private; - if (devpriv) + if (dev->iobase) pc236_intr_disable(dev); if (dev->irq) free_irq(dev->irq, dev); -- cgit v1.2.3-55-g7522 From 2db012bd40b889d8e5483d3daa07af04c4c109d8 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 3 Oct 2012 16:25:18 +0100 Subject: staging: comedi: amplc_pc236: fix possible NULL deref during detach `pc236_detach()` is called by the comedi core to clean up if either `pc236_attach()` or `pc236_attach_pci()` returns an error. It sets `thisboard` to the return value of `comedi_board(dev)` and assumes it is non-null. This is a valid assumption if `pc236_attach()` fails, but not if `pc236_attach_pci()` fails, leading to a possible NULL pointer dereference. Check `thisboard` at the top of `pc236_detach()` and return early if it is `NULL`. This is okay because the only other thing that could have been allocated is `dev->private` and that is freed by the comedi core, not by this function. Cc: # 3.6.x Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc236.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index 36768b2b30ae..4e4f3c15df87 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -574,6 +574,8 @@ static void pc236_detach(struct comedi_device *dev) { const struct pc236_board *thisboard = comedi_board(dev); + if (!thisboard) + return; if (dev->iobase) pc236_intr_disable(dev); if (dev->irq) -- cgit v1.2.3-55-g7522 From 1d1171ffda585c1cab7bd7cf4bd8f8fd5923fb4a Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 3 Oct 2012 16:25:19 +0100 Subject: staging: comedi: amplc_pc263: fix possible NULL deref during detach `pc263_detach()` is called by the comedi core to clean up if either `pc263_attach()` or `pc263_attach_pci()` returns an error. It sets `thisboard` to the return value of `comedi_board(dev)` and assumes it is non-null. This is a valid assumption if `pc263_attach()` fails, but not if `pc263_attach_pci()` fails, leading to a possible NULL pointer dereference. Check `thisboard` at the top of `pc263_detach()` and return early if it is `NULL`. This is okay because no other resources need cleaning up in this case. Cc: # 3.6.x Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc263.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 60830ccfb903..d0a4c441228b 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -323,6 +323,8 @@ static void pc263_detach(struct comedi_device *dev) { const struct pc263_board *thisboard = comedi_board(dev); + if (!thisboard) + return; if (is_isa_board(thisboard)) { if (dev->iobase) release_region(dev->iobase, PC263_IO_SIZE); -- cgit v1.2.3-55-g7522 From ee280d134f2e05e0172369a53fbe202dbfc527fa Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 3 Oct 2012 16:25:20 +0100 Subject: staging: comedi: das08: fix possible NULL deref during detach `das08_detach()` is called by the comedi core to clean up if either `das08_attach()` or `das08_attach_pci()` returns an error. It sets `thisboard` to the return value of `comedi_board(dev)` and assumes it is non-null. This is a valid assumption if `das08_attach()` fails, but not if `das08_attach_pci()` fails, leading to a possible NULL pointer dereference. Check `thisboard` at the top of `das08_detach()` and return early if it is `NULL`. This is okay because the only other thing that could have been allocated is `dev->private` and that is freed by the comedi core, not by this function. Cc: # 3.6.x Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 5fd21fa6c1c7..c304528cfb13 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -846,6 +846,8 @@ static void __maybe_unused das08_detach(struct comedi_device *dev) { const struct das08_board_struct *thisboard = comedi_board(dev); + if (!thisboard) + return; das08_common_detach(dev); if (is_isa_board(thisboard)) { if (dev->iobase) -- cgit v1.2.3-55-g7522 From 922b67c1ac53014d80649a961a2fde700cd065d8 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 3 Oct 2012 16:25:21 +0100 Subject: staging: comedi: ni_labpc: fix possible NULL deref during detach `labpc_common_detach()` is called by the comedi core to clean up if either `labpc_attach()` (including the one in the "ni_labpc_cs" module) or `labpc_attach_pci()` returns an error. It assumes the `thisboard` macro (expanding to `((struct labpc_board_struct *)dev->board_ptr)`) is non-null. This is a valid assumption if `labpc_attach()` fails, but not if `labpc_attach_pci()` fails, leading to a possible NULL pointer dereference. Check `thisboard` at the top of `labpc_common_detach()` and return early if it is `NULL`. This is okay because the only other thing that could have been allocated is `dev->private` and that is freed by the comedi core, not by this function. Cc: # 3.6.x Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 28b91a6c3789..b5a19a0863fb 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -772,6 +772,8 @@ void labpc_common_detach(struct comedi_device *dev) { struct comedi_subdevice *s; + if (!thisboard) + return; if (dev->subdevices) { s = &dev->subdevices[2]; subdev_8255_cleanup(dev, s); -- cgit v1.2.3-55-g7522 From 8a6e29d6d037de0dd62fe6648ba9b29866db5416 Mon Sep 17 00:00:00 2001 From: Joe Jin Date: Sun, 21 Oct 2012 14:40:36 +0000 Subject: qla3xxx: Ensure request/response queue addr writes to the registers Before use the request and response queue addr, make sure it has wrote to the registers. Signed-off-by: Joe Jin Cc: Jitendra Kalsaria Cc: Ron Mercer Acked-by: Jitendra Kalsaria Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qla3xxx.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c index df09b1cb742f..6407d0d77e81 100644 --- a/drivers/net/ethernet/qlogic/qla3xxx.c +++ b/drivers/net/ethernet/qlogic/qla3xxx.c @@ -2525,6 +2525,13 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev) qdev->req_q_size = (u32) (NUM_REQ_Q_ENTRIES * sizeof(struct ob_mac_iocb_req)); + qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb); + + /* The barrier is required to ensure request and response queue + * addr writes to the registers. + */ + wmb(); + qdev->req_q_virt_addr = pci_alloc_consistent(qdev->pdev, (size_t) qdev->req_q_size, @@ -2536,8 +2543,6 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev) return -ENOMEM; } - qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb); - qdev->rsp_q_virt_addr = pci_alloc_consistent(qdev->pdev, (size_t) qdev->rsp_q_size, -- cgit v1.2.3-55-g7522 From 675d66b0ed5fd170d6a44cf8dbb3fa56a5347bdb Mon Sep 17 00:00:00 2001 From: Arve Hjønnevåg Date: Tue, 16 Oct 2012 15:29:54 -0700 Subject: Staging: android: binder: Fix memory leak on thread/process exit If a thread or process exited while a reply, one-way transaction or death notification was pending, the struct holding the pending work was leaked. Signed-off-by: Arve Hjønnevåg Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/binder.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 7b0ba92e7e46..db6c4c5c2551 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -2419,14 +2419,38 @@ static void binder_release_work(struct list_head *list) struct binder_transaction *t; t = container_of(w, struct binder_transaction, work); - if (t->buffer->target_node && !(t->flags & TF_ONE_WAY)) + if (t->buffer->target_node && + !(t->flags & TF_ONE_WAY)) { binder_send_failed_reply(t, BR_DEAD_REPLY); + } else { + binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, + "binder: undelivered transaction %d\n", + t->debug_id); + t->buffer->transaction = NULL; + kfree(t); + binder_stats_deleted(BINDER_STAT_TRANSACTION); + } } break; case BINDER_WORK_TRANSACTION_COMPLETE: { + binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, + "binder: undelivered TRANSACTION_COMPLETE\n"); kfree(w); binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); } break; + case BINDER_WORK_DEAD_BINDER_AND_CLEAR: + case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: { + struct binder_ref_death *death; + + death = container_of(w, struct binder_ref_death, work); + binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, + "binder: undelivered death notification, %p\n", + death->cookie); + kfree(death); + binder_stats_deleted(BINDER_STAT_DEATH); + } break; default: + pr_err("binder: unexpected work type, %d, not freed\n", + w->type); break; } } @@ -2899,6 +2923,7 @@ static void binder_deferred_release(struct binder_proc *proc) nodes++; rb_erase(&node->rb_node, &proc->nodes); list_del_init(&node->work.entry); + binder_release_work(&node->async_todo); if (hlist_empty(&node->refs)) { kfree(node); binder_stats_deleted(BINDER_STAT_NODE); @@ -2937,6 +2962,7 @@ static void binder_deferred_release(struct binder_proc *proc) binder_delete_ref(ref); } binder_release_work(&proc->todo); + binder_release_work(&proc->delivered_death); buffers = 0; while ((n = rb_first(&proc->allocated_buffers))) { -- cgit v1.2.3-55-g7522 From 585650dcec88e704a19bb226a34b6a7166111623 Mon Sep 17 00:00:00 2001 From: Arve Hjønnevåg Date: Tue, 16 Oct 2012 15:29:55 -0700 Subject: Staging: android: binder: Allow using highmem for binder buffers The default kernel mapping for the pages allocated for the binder buffers is never used. Set the __GFP_HIGHMEM flag when allocating these pages so we don't needlessly use low memory pages that may be required elsewhere. Signed-off-by: Arve Hjønnevåg Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/binder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index db6c4c5c2551..5d4610babd8a 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -567,7 +567,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE]; BUG_ON(*page); - *page = alloc_page(GFP_KERNEL | __GFP_ZERO); + *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); if (*page == NULL) { pr_err("binder: %d: binder_alloc_buf failed " "for page at %p\n", proc->pid, page_addr); -- cgit v1.2.3-55-g7522 From 170ed807340b4db0a5e010c2e4da43cf5a2c9a29 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Mon, 15 Oct 2012 15:38:34 +0800 Subject: usb/xhci: release xhci->lock during turning on/off usb port's acpi power resource and checking the existence of port's power resource When setting usb port's acpi power resource, there will be some xhci hub requests. This will cause dead lock since xhci->lock has been held before setting acpi power resource in the xhci_hub_control(). The usb_acpi_power_manageable() function might fall into sleep so release xhci->lock before invoking it. Signed-off-by: Lan Tianyu Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-hub.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index aa90ad4d4fd5..65d416c08cef 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -809,11 +809,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = xhci_readl(xhci, port_array[wIndex]); xhci_dbg(xhci, "set port power, actual port %d status = 0x%x\n", wIndex, temp); + spin_unlock_irqrestore(&xhci->lock, flags); temp = usb_acpi_power_manageable(hcd->self.root_hub, wIndex); if (temp) usb_acpi_set_power_state(hcd->self.root_hub, wIndex, true); + spin_lock_irqsave(&xhci->lock, flags); break; case USB_PORT_FEAT_RESET: temp = (temp | PORT_RESET); @@ -917,11 +919,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, xhci_writel(xhci, temp & ~PORT_POWER, port_array[wIndex]); + spin_unlock_irqrestore(&xhci->lock, flags); temp = usb_acpi_power_manageable(hcd->self.root_hub, wIndex); if (temp) usb_acpi_set_power_state(hcd->self.root_hub, wIndex, false); + spin_lock_irqsave(&xhci->lock, flags); break; default: goto error; -- cgit v1.2.3-55-g7522 From 27c411c95a8e9ed92be658abf1d63e22873a3a66 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Mon, 15 Oct 2012 15:38:35 +0800 Subject: usb/xhci: Remove (__force__ __u16) before assigning DeviceRemovable and assign directly. Struct usb_hub_descriptor.ss.DeviceRemovable has been defined as __le16 and (__force__ __u16) doesn't need. Signed-off-by: Lan Tianyu Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-hub.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 65d416c08cef..a686cf4905bb 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -151,9 +151,8 @@ static void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, if (portsc & PORT_DEV_REMOVE) port_removable |= 1 << (i + 1); } - memset(&desc->u.ss.DeviceRemovable, - (__force __u16) cpu_to_le16(port_removable), - sizeof(__u16)); + + desc->u.ss.DeviceRemovable = cpu_to_le16(port_removable); } static void xhci_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, -- cgit v1.2.3-55-g7522 From c8f2f0db1d0294aaf37e8a85bea9bbc4aaf5c0fe Mon Sep 17 00:00:00 2001 From: Nitin Gupta Date: Wed, 10 Oct 2012 17:42:18 -0700 Subject: staging: zram: Fix handling of incompressible pages Change 130f315a (staging: zram: remove special handle of uncompressed page) introduced a bug in the handling of incompressible pages which resulted in memory allocation failure for such pages. When a page expands on compression, say from 4K to 4K+30, we were trying to do zsmalloc(pool, 4K+30). However, the maximum size which zsmalloc can allocate is PAGE_SIZE (for obvious reasons), so such allocation requests always return failure (0). For a page that has compressed size larger than the original size (this may happen with already compressed or random data), there is no point storing the compressed version as that would take more space and would also require time for decompression when needed again. So, the fix is to store any page, whose compressed size exceeds a threshold (max_zpage_size), as-it-is i.e. without compression. Memory required for storing this uncompressed page can then be requested from zsmalloc which supports PAGE_SIZE sized allocations. Lastly, the fix checks that we do not attempt to "decompress" the page which we stored in the uncompressed form -- we just memcpy() out such pages. Signed-off-by: Nitin Gupta Reported-by: viechweg@gmail.com Reported-by: paerley@gmail.com Reported-by: wu.tommy@gmail.com Acked-by: Minchan Kim Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zram/zram_drv.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index 653b074035f7..6edefde23722 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -223,8 +223,13 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, cmem = zs_map_object(zram->mem_pool, zram->table[index].handle, ZS_MM_RO); - ret = lzo1x_decompress_safe(cmem, zram->table[index].size, + if (zram->table[index].size == PAGE_SIZE) { + memcpy(uncmem, cmem, PAGE_SIZE); + ret = LZO_E_OK; + } else { + ret = lzo1x_decompress_safe(cmem, zram->table[index].size, uncmem, &clen); + } if (is_partial_io(bvec)) { memcpy(user_mem + bvec->bv_offset, uncmem + offset, @@ -342,8 +347,11 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, goto out; } - if (unlikely(clen > max_zpage_size)) + if (unlikely(clen > max_zpage_size)) { zram_stat_inc(&zram->stats.bad_compress); + src = uncmem; + clen = PAGE_SIZE; + } handle = zs_malloc(zram->mem_pool, clen); if (!handle) { -- cgit v1.2.3-55-g7522 From 23d84ed9c81b6f09c270da00b00e8582fab7ca70 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Tue, 9 Oct 2012 19:40:39 +0100 Subject: staging: omapdrm: fix allocation size for page addresses array Signed-off-by: Rob Clark Signed-off-by: Vincent Penquerc'h Signed-off-by: Greg Kroah-Hartman --- drivers/staging/omapdrm/omap_gem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/omapdrm/omap_gem.c b/drivers/staging/omapdrm/omap_gem.c index 3434e6ec0142..66e2c2f8a239 100644 --- a/drivers/staging/omapdrm/omap_gem.c +++ b/drivers/staging/omapdrm/omap_gem.c @@ -246,7 +246,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj) * DSS, GPU, etc. are not cache coherent: */ if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) { - addrs = kmalloc(npages * sizeof(addrs), GFP_KERNEL); + addrs = kmalloc(npages * sizeof(*addrs), GFP_KERNEL); if (!addrs) { ret = -ENOMEM; goto free_pages; @@ -257,7 +257,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj) 0, PAGE_SIZE, DMA_BIDIRECTIONAL); } } else { - addrs = kzalloc(npages * sizeof(addrs), GFP_KERNEL); + addrs = kzalloc(npages * sizeof(*addrs), GFP_KERNEL); if (!addrs) { ret = -ENOMEM; goto free_pages; -- cgit v1.2.3-55-g7522 From b3ca610a22c6f4708783b918ddbc22f4cb74589f Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 11 Oct 2012 09:34:11 -0700 Subject: staging: ramster: depends on NET ramster uses network interfaces that are only present when CONFIG_NET is enabled, so it should depend on NET. Fixes these build errors: drivers/built-in.o: In function `sc_kref_release': tcp.c:(.text+0x24b9af): undefined reference to `sock_release' drivers/built-in.o: In function `r2net_open_listening_sock': tcp.c:(.text+0x24ca2b): undefined reference to `sock_create' tcp.c:(.text+0x24cb91): undefined reference to `sock_release' drivers/built-in.o: In function `r2net_recv_tcp_msg': tcp.c:(.text+0x24cdbd): undefined reference to `sock_recvmsg' drivers/built-in.o: In function `r2net_send_tcp_msg': tcp.c:(.text+0x24d341): undefined reference to `sock_sendmsg' drivers/built-in.o: In function `r2net_start_connect': tcp.c:(.text+0x24d8fa): undefined reference to `sock_create' drivers/built-in.o: In function `r2net_shutdown_sc': tcp.c:(.text+0x24e30c): undefined reference to `kernel_sock_shutdown' drivers/built-in.o: In function `r2net_accept_one': tcp.c:(.text+0x24f392): undefined reference to `sock_create_lite' tcp.c:(.text+0x24f3c3): undefined reference to `sock_release' drivers/built-in.o: In function `r2net_stop_listening': (.text+0x250f63): undefined reference to `sock_release' Signed-off-by: Randy Dunlap Cc: konrad.wilk@oracle.com Acked-by: Dan Magenheimer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ramster/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/ramster/Kconfig b/drivers/staging/ramster/Kconfig index 843c54101438..3abf6619dace 100644 --- a/drivers/staging/ramster/Kconfig +++ b/drivers/staging/ramster/Kconfig @@ -18,6 +18,7 @@ config ZCACHE2 config RAMSTER bool "Cross-machine RAM capacity sharing, aka peer-to-peer tmem" depends on CONFIGFS_FS=y && SYSFS=y && !HIGHMEM && ZCACHE2=y + depends on NET # must ensure struct page is 8-byte aligned select HAVE_ALIGNED_STRUCT_PAGE if !64_BIT default n -- cgit v1.2.3-55-g7522 From 2978af545b9a1ed221e23fb24ae4559bec6ad70d Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Tue, 23 Oct 2012 00:53:58 +0200 Subject: ACPI: Fix memory leak in acpi_bind_one() Memory is allocated with kzalloc() and assigned to 'physical_node'. Then 'physical_node->node_id' is initialized with a call to 'find_first_zero_bit()', if that results in a value greater than ACPI_MAX_PHYSICAL_NODE we'll end up jumping to the 'err:' label and there leave the function and let 'physical_node' go out of scope and leak the memory we allocated. This patch fixes the leak by simply freeing the unused/unneeded memory pointed to by 'physical_node' just before we jump to 'err:'. [rjw: The problem has been introduced by commit 1033f90 (ACPI: Allow ACPI binding with USB-3.0 hub), which is new in 3.7-rc.] Signed-off-by: Jesper Juhl Reviewed-by: Toshi Kani Reviewed-by: Yasuaki Ishimatsu Acked-by: David Rientjes Signed-off-by: Rafael J. Wysocki --- drivers/acpi/glue.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index d1a2d74033e9..08373086cd7e 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -159,6 +159,7 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) { retval = -ENOSPC; mutex_unlock(&acpi_dev->physical_node_lock); + kfree(physical_node); goto err; } -- cgit v1.2.3-55-g7522 From debe081aaa4d247b9957ac2336d84deab32d9909 Mon Sep 17 00:00:00 2001 From: jhbird.choi@samsung.com Date: Tue, 23 Oct 2012 00:54:38 +0200 Subject: PM / Domains: Fix memory leak on error path in pm_genpd_attach_cpuidle If pm_genpd_attach_cpudidle failed we leak memory stored in 'cpu_data'. Signed-off-by: Jonghwan Choi Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index c22b869245d9..96b71b6536d6 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1862,7 +1862,7 @@ int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state) cpuidle_drv = cpuidle_driver_ref(); if (!cpuidle_drv) { ret = -ENODEV; - goto out; + goto err_drv; } if (cpuidle_drv->state_count <= state) { ret = -EINVAL; @@ -1884,6 +1884,9 @@ int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state) err: cpuidle_driver_unref(); + + err_drv: + kfree(cpu_data); goto out; } -- cgit v1.2.3-55-g7522 From e4df1cbcc1f329e53a1fff7450b2229e0addff20 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Tue, 23 Oct 2012 00:55:10 +0200 Subject: cpufreq / powernow-k8: Remove usage of smp_processor_id() in preemptible code Commit 6889125b8b4e09c5e53e6ecab3433bed1ce198c9 (cpufreq/powernow-k8: workqueue user shouldn't migrate the kworker to another CPU) causes powernow-k8 to trigger a preempt warning, e.g.: BUG: using smp_processor_id() in preemptible [00000000] code: cpufreq/3776 caller is powernowk8_target+0x20/0x49 Pid: 3776, comm: cpufreq Not tainted 3.6.0 #9 Call Trace: [] debug_smp_processor_id+0xc7/0xe0 [] powernowk8_target+0x20/0x49 [] __cpufreq_driver_target+0x82/0x8a [] cpufreq_governor_performance+0x4e/0x54 [] __cpufreq_governor+0x8c/0xc9 [] __cpufreq_set_policy+0x1a9/0x21e [] store_scaling_governor+0x16f/0x19b [] ? cpufreq_update_policy+0x124/0x124 [] ? _raw_spin_unlock_irqrestore+0x2c/0x49 [] store+0x60/0x88 [] sysfs_write_file+0xf4/0x130 [] vfs_write+0xb5/0x151 [] sys_write+0x4a/0x71 [] system_call_fastpath+0x16/0x1b Fix this by by always using work_on_cpu(). Signed-off-by: Andreas Herrmann Cc: stable@vger.kernel.org Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/powernow-k8.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 129e80bfff22..c16a3a593ba4 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1052,14 +1052,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq, .relation = relation }; - /* - * Must run on @pol->cpu. cpufreq core is responsible for ensuring - * that we're bound to the current CPU and pol->cpu stays online. - */ - if (smp_processor_id() == pol->cpu) - return powernowk8_target_fn(&pta); - else - return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta); + return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta); } /* Driver entry point to verify the policy and range of frequencies */ -- cgit v1.2.3-55-g7522 From e37736777254ce1abc85493a5cacbefe5983b896 Mon Sep 17 00:00:00 2001 From: Tu, Xiaobing Date: Tue, 23 Oct 2012 01:03:00 +0200 Subject: Fix memory leak in cpufreq stats. When system enters sleep, non-boot CPUs will be disabled. Cpufreq stats sysfs is created when the CPU is up, but it is not freed when the CPU is going down. This will cause memory leak. Signed-off-by: xiaobing tu Signed-off-by: guifang tang Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq_stats.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index b40ee1403be9..399831690fed 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -328,6 +328,7 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb, cpufreq_update_policy(cpu); break; case CPU_DOWN_PREPARE: + case CPU_DOWN_PREPARE_FROZEN: cpufreq_stats_free_sysfs(cpu); break; case CPU_DEAD: -- cgit v1.2.3-55-g7522 From e0d78d08e3c06ebe2eb45b4d84f8cd5d1b13d371 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Sat, 20 Oct 2012 10:32:46 +0000 Subject: drm: fb: cma: Fix typo in debug message The debug message showing the resolution of a framebuffer to be allocated is missing a closing parenthesis. Signed-off-by: Thierry Reding Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fb_cma_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 09e11a5d921a..d6c80a34b830 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -206,7 +206,7 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper, size_t size; int ret; - DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n", + DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n", sizes->surface_width, sizes->surface_height, sizes->surface_bpp); -- cgit v1.2.3-55-g7522 From 028132451667ffd25b6814d47a622ec03cb8cba7 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Sat, 20 Oct 2012 10:32:47 +0000 Subject: drm: fb: cma: Fail gracefully on allocation failure The drm_gem_cma_create() function never returns NULL but rather an error encoded in the return value using the ERR_PTR() macro. Callers therefore need to check for errors using the IS_ERR() macro. This change allows drivers to handle contiguous DMA allocation failures gracefully. Signed-off-by: Thierry Reding Acked-by: Sascha Hauer Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fb_cma_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index d6c80a34b830..fd9d0af4d536 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -220,7 +220,7 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper, size = mode_cmd.pitches[0] * mode_cmd.height; obj = drm_gem_cma_create(dev, size); - if (!obj) + if (IS_ERR(obj)) return -ENOMEM; fbi = framebuffer_alloc(0, dev->dev); -- cgit v1.2.3-55-g7522 From 08bce0ac3bdc9d8e57d3f4b8edf3e787e623eccc Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Tue, 16 Oct 2012 21:47:35 +0000 Subject: drm/debugfs: remove redundant info from gem_names It's a relic of "drm: Convert proc files to seq_file and introduce debugfs", which wrongly converted DRM_INFO + sprintf to 2 seq_printfs. Signed-off-by: Marcin Slusarz Cc: Ben Gamari Cc: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_info.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index 441ebc1bdbef..d4b20ceda3fb 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c @@ -205,8 +205,6 @@ static int drm_gem_one_name_info(int id, void *ptr, void *data) struct drm_gem_object *obj = ptr; struct seq_file *m = data; - seq_printf(m, "name %d size %zd\n", obj->name, obj->size); - seq_printf(m, "%6d %8zd %7d %8d\n", obj->name, obj->size, atomic_read(&obj->handle_count), -- cgit v1.2.3-55-g7522 From a16d4f86019a72b3e8cbb89abff769b25b53ab69 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Oct 2012 18:03:42 +0000 Subject: drm: platform: Don't initialize driver-private data Platform device drivers usually use the driver-private data for their own purposes. Having it overwritten by drm_platform_init() is confusing and error-prone. Signed-off-by: Thierry Reding Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_platform.c | 1 - drivers/gpu/drm/shmobile/shmob_drm_drv.c | 12 +++++------- 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c index aaeb6f8d69ce..b8a282ea8751 100644 --- a/drivers/gpu/drm/drm_platform.c +++ b/drivers/gpu/drm/drm_platform.c @@ -64,7 +64,6 @@ int drm_get_platform_dev(struct platform_device *platdev, } if (drm_core_check_feature(dev, DRIVER_MODESET)) { - dev_set_drvdata(&platdev->dev, dev); ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); if (ret) goto err_g1; diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c index c71d493fd0c5..1c350fc4e449 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c @@ -201,6 +201,8 @@ static int shmob_drm_load(struct drm_device *dev, unsigned long flags) goto done; } + platform_set_drvdata(pdev, sdev); + done: if (ret) shmob_drm_unload(dev); @@ -299,11 +301,9 @@ static struct drm_driver shmob_drm_driver = { #if CONFIG_PM_SLEEP static int shmob_drm_pm_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct drm_device *ddev = platform_get_drvdata(pdev); - struct shmob_drm_device *sdev = ddev->dev_private; + struct shmob_drm_device *sdev = dev_get_drvdata(dev); - drm_kms_helper_poll_disable(ddev); + drm_kms_helper_poll_disable(sdev->ddev); shmob_drm_crtc_suspend(&sdev->crtc); return 0; @@ -311,9 +311,7 @@ static int shmob_drm_pm_suspend(struct device *dev) static int shmob_drm_pm_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct drm_device *ddev = platform_get_drvdata(pdev); - struct shmob_drm_device *sdev = ddev->dev_private; + struct shmob_drm_device *sdev = dev_get_drvdata(dev); mutex_lock(&sdev->ddev->mode_config.mutex); shmob_drm_crtc_resume(&sdev->crtc); -- cgit v1.2.3-55-g7522 From 7bc17a7837bf4ec8fd2d63438c0b6b0160c454c1 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 22 Oct 2012 12:51:25 +0000 Subject: drm/ttm: Fix a theoretical race The ttm_mem_evict_first function could theoretically drop the lru lock without retrying if a reservation from off the LRU list ended up waiting. However, since currently there are no users that could cause a wait in that situation so this is not suitable for stable Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 402ab69f9f99..d42631cade5a 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -817,11 +817,11 @@ retry: goto retry; } - ret = ttm_bo_reserve_locked(bo, false, no_wait_reserve, false, 0); + ret = ttm_bo_reserve_locked(bo, false, true, false, 0); if (unlikely(ret == -EBUSY)) { spin_unlock(&glob->lru_lock); - if (likely(!no_wait_gpu)) + if (likely(!no_wait_reserve)) ret = ttm_bo_wait_unreserved(bo, interruptible); kref_put(&bo->list_kref, ttm_bo_release_list); -- cgit v1.2.3-55-g7522 From b8e902f24fdd16c4373ddc37a4e150c4afe9c6db Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 22 Oct 2012 12:51:26 +0000 Subject: drm/ttm: Fix a theoretical race in ttm_bo_cleanup_refs() In theory, that function could release the lru lock between checking for bo on ddestroy list and a successful reserve if the bo was already reserved, and the function was called with waiting reserves allowed. However, all current reservers of a bo on the ddestroy list would atomically take the bo off the list after a successful reserve so this race should not have been hit, so no need to backport for stable. This patch also fixes a case found by Maarten Lankhorst where ttm_mem_evict_first called with no_wait_gpu would incorrectly spin waiting for bo idle if trying to evict a busy buffer that also sits on the ddestroy list. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index d42631cade5a..bf6e4b5a73b5 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -580,6 +580,7 @@ retry: if (unlikely(ret != 0)) return ret; +retry_reserve: spin_lock(&glob->lru_lock); if (unlikely(list_empty(&bo->ddestroy))) { @@ -587,14 +588,20 @@ retry: return 0; } - ret = ttm_bo_reserve_locked(bo, interruptible, - no_wait_reserve, false, 0); + ret = ttm_bo_reserve_locked(bo, false, true, false, 0); - if (unlikely(ret != 0)) { + if (unlikely(ret == -EBUSY)) { spin_unlock(&glob->lru_lock); - return ret; + if (likely(!no_wait_reserve)) + ret = ttm_bo_wait_unreserved(bo, interruptible); + if (unlikely(ret != 0)) + return ret; + + goto retry_reserve; } + BUG_ON(ret != 0); + /** * We can re-check for sync object without taking * the bo::lock since setting the sync object requires @@ -811,10 +818,7 @@ retry: no_wait_reserve, no_wait_gpu); kref_put(&bo->list_kref, ttm_bo_release_list); - if (likely(ret == 0 || ret == -ERESTARTSYS)) - return ret; - - goto retry; + return ret; } ret = ttm_bo_reserve_locked(bo, false, true, false, 0); -- cgit v1.2.3-55-g7522 From e408a9ff3c7c371d0e2a47a9eb8fa3de48fea30d Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Mon, 22 Oct 2012 04:43:23 +0000 Subject: pch_gbe: create functions for MAC_RX {en,dis}able Move MAC_RX-related bits into separate functions. Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller --- .../net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 26 +++++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index b2a94d02a521..d5190bf94ba0 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -420,6 +420,22 @@ static void pch_gbe_mac_reset_rx(struct pch_gbe_hw *hw) return; } +static void pch_gbe_disable_mac_rx(struct pch_gbe_hw *hw) +{ + u32 rctl; + /* Disables Receive MAC */ + rctl = ioread32(&hw->reg->MAC_RX_EN); + iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN); +} + +static void pch_gbe_enable_mac_rx(struct pch_gbe_hw *hw) +{ + u32 rctl; + /* Enables Receive MAC */ + rctl = ioread32(&hw->reg->MAC_RX_EN); + iowrite32((rctl | PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN); +} + /** * pch_gbe_mac_init_rx_addrs - Initialize receive address's * @hw: Pointer to the HW structure @@ -913,7 +929,7 @@ static void pch_gbe_setup_rctl(struct pch_gbe_adapter *adapter) static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter) { struct pch_gbe_hw *hw = &adapter->hw; - u32 rdba, rdlen, rctl, rxdma; + u32 rdba, rdlen, rxdma; pr_debug("dma adr = 0x%08llx size = 0x%08x\n", (unsigned long long)adapter->rx_ring->dma, @@ -921,9 +937,7 @@ static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter) pch_gbe_mac_force_mac_fc(hw); - /* Disables Receive MAC */ - rctl = ioread32(&hw->reg->MAC_RX_EN); - iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN); + pch_gbe_disable_mac_rx(hw); /* Disables Receive DMA */ rxdma = ioread32(&hw->reg->DMA_CTRL); @@ -1355,8 +1369,8 @@ static void pch_gbe_start_receive(struct pch_gbe_hw *hw) rxdma = ioread32(&hw->reg->DMA_CTRL); rxdma |= PCH_GBE_RX_DMA_EN; iowrite32(rxdma, &hw->reg->DMA_CTRL); - /* Enables Receive */ - iowrite32(PCH_GBE_MRE_MAC_RX_EN, &hw->reg->MAC_RX_EN); + + pch_gbe_enable_mac_rx(hw); return; } -- cgit v1.2.3-55-g7522 From 9c0314e111a540620441b27aeedb55f572f812f5 Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Mon, 22 Oct 2012 04:43:24 +0000 Subject: pch_gbe: don't re-set RX_FIFO_ERR flag in napi_poll If we were in RX_FIFO_ERR state and entered pch_gbe_napi_poll(), we'll anyway clean some rx space and thus can continue to receive more packets. Currently, we re-set the RX_FIFO_ERR in situations when we've exhausted our budget for RX cleaning or cleaned some TX packets. Removing it gives us +20%-40% speed increase and a lot less of RX_FIFO_ERRors reported. Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller --- drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index d5190bf94ba0..4ffad780c7ac 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -2419,7 +2419,6 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget) int work_done = 0; bool poll_end_flag = false; bool cleaned = false; - u32 int_en; pr_debug("budget : %d\n", budget); @@ -2436,19 +2435,13 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget) if (poll_end_flag) { napi_complete(napi); - if (adapter->rx_stop_flag) { - adapter->rx_stop_flag = false; - pch_gbe_start_receive(&adapter->hw); - } pch_gbe_irq_enable(adapter); - } else - if (adapter->rx_stop_flag) { - adapter->rx_stop_flag = false; - pch_gbe_start_receive(&adapter->hw); - int_en = ioread32(&adapter->hw.reg->INT_EN); - iowrite32((int_en | PCH_GBE_INT_RX_FIFO_ERR), - &adapter->hw.reg->INT_EN); - } + } + + if (adapter->rx_stop_flag) { + adapter->rx_stop_flag = false; + pch_gbe_start_receive(&adapter->hw); + } pr_debug("poll_end_flag : %d work_done : %d budget : %d\n", poll_end_flag, work_done, budget); -- cgit v1.2.3-55-g7522 From a35279f002c5843c2b2faaa4538963c8eb18446c Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Mon, 22 Oct 2012 04:43:25 +0000 Subject: pch_gbe: don't reset MAC_RX on FIFO overflow Currently, when FIFO_ERR happens, we stop the dma, wait for it to become idle and then reset the whole MAC_RX logic (and after that we must re-set multicast addresses and also re-enable MAC_RX when we're finally ready to accept new packets). This leads to CRC errors on high number of incoming packets and is not needed according to the datasheet. This patch fixes it by the following steps: 1) remove this reset in pch_gbe_stop_receive(), which causes some functions to not be used anywhere 2) remove already unused functions pch_gbe_wait_clr_bit_irq() and pch_gbe_mac_reset_rx() to correctly build 3) move pch_gbe_enable_mac_rx() out of pch_gbe_start_receive() to pch_gbe_up() where it's only needed after we've removed the MAC_RX reset 4) rename pch_gbe_start/stop_receive() to pch_gbe_enable/disable_dma_rx() to more precisely reflect what the functions are now doing. After these changes we already don't see the CRC errors and gain some increase in RX processing speed. Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller --- .../net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 66 ++-------------------- 1 file changed, 6 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 4ffad780c7ac..a8854d04c275 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -338,26 +338,6 @@ static void pch_gbe_wait_clr_bit(void *reg, u32 bit) pr_err("Error: busy bit is not cleared\n"); } -/** - * pch_gbe_wait_clr_bit_irq - Wait to clear a bit for interrupt context - * @reg: Pointer of register - * @busy: Busy bit - */ -static int pch_gbe_wait_clr_bit_irq(void *reg, u32 bit) -{ - u32 tmp; - int ret = -1; - /* wait busy */ - tmp = 20; - while ((ioread32(reg) & bit) && --tmp) - udelay(5); - if (!tmp) - pr_err("Error: busy bit is not cleared\n"); - else - ret = 0; - return ret; -} - /** * pch_gbe_mac_mar_set - Set MAC address register * @hw: Pointer to the HW structure @@ -409,17 +389,6 @@ static void pch_gbe_mac_reset_hw(struct pch_gbe_hw *hw) return; } -static void pch_gbe_mac_reset_rx(struct pch_gbe_hw *hw) -{ - /* Read the MAC addresses. and store to the private data */ - pch_gbe_mac_read_mac_addr(hw); - iowrite32(PCH_GBE_RX_RST, &hw->reg->RESET); - pch_gbe_wait_clr_bit_irq(&hw->reg->RESET, PCH_GBE_RX_RST); - /* Setup the MAC addresses */ - pch_gbe_mac_mar_set(hw, hw->mac.addr, 0); - return; -} - static void pch_gbe_disable_mac_rx(struct pch_gbe_hw *hw) { u32 rctl; @@ -1330,38 +1299,17 @@ void pch_gbe_update_stats(struct pch_gbe_adapter *adapter) spin_unlock_irqrestore(&adapter->stats_lock, flags); } -static void pch_gbe_stop_receive(struct pch_gbe_adapter *adapter) +static void pch_gbe_disable_dma_rx(struct pch_gbe_hw *hw) { - struct pch_gbe_hw *hw = &adapter->hw; u32 rxdma; - u16 value; - int ret; /* Disable Receive DMA */ rxdma = ioread32(&hw->reg->DMA_CTRL); rxdma &= ~PCH_GBE_RX_DMA_EN; iowrite32(rxdma, &hw->reg->DMA_CTRL); - /* Wait Rx DMA BUS is IDLE */ - ret = pch_gbe_wait_clr_bit_irq(&hw->reg->RX_DMA_ST, PCH_GBE_IDLE_CHECK); - if (ret) { - /* Disable Bus master */ - pci_read_config_word(adapter->pdev, PCI_COMMAND, &value); - value &= ~PCI_COMMAND_MASTER; - pci_write_config_word(adapter->pdev, PCI_COMMAND, value); - /* Stop Receive */ - pch_gbe_mac_reset_rx(hw); - /* Enable Bus master */ - value |= PCI_COMMAND_MASTER; - pci_write_config_word(adapter->pdev, PCI_COMMAND, value); - } else { - /* Stop Receive */ - pch_gbe_mac_reset_rx(hw); - } - /* reprogram multicast address register after reset */ - pch_gbe_set_multi(adapter->netdev); } -static void pch_gbe_start_receive(struct pch_gbe_hw *hw) +static void pch_gbe_enable_dma_rx(struct pch_gbe_hw *hw) { u32 rxdma; @@ -1369,9 +1317,6 @@ static void pch_gbe_start_receive(struct pch_gbe_hw *hw) rxdma = ioread32(&hw->reg->DMA_CTRL); rxdma |= PCH_GBE_RX_DMA_EN; iowrite32(rxdma, &hw->reg->DMA_CTRL); - - pch_gbe_enable_mac_rx(hw); - return; } /** @@ -1407,7 +1352,7 @@ static irqreturn_t pch_gbe_intr(int irq, void *data) int_en = ioread32(&hw->reg->INT_EN); iowrite32((int_en & ~PCH_GBE_INT_RX_FIFO_ERR), &hw->reg->INT_EN); - pch_gbe_stop_receive(adapter); + pch_gbe_disable_dma_rx(&adapter->hw); int_st |= ioread32(&hw->reg->INT_ST); int_st = int_st & ioread32(&hw->reg->INT_EN); } @@ -2014,7 +1959,8 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) pch_gbe_alloc_tx_buffers(adapter, tx_ring); pch_gbe_alloc_rx_buffers(adapter, rx_ring, rx_ring->count); adapter->tx_queue_len = netdev->tx_queue_len; - pch_gbe_start_receive(&adapter->hw); + pch_gbe_enable_dma_rx(&adapter->hw); + pch_gbe_enable_mac_rx(&adapter->hw); mod_timer(&adapter->watchdog_timer, jiffies); @@ -2440,7 +2386,7 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget) if (adapter->rx_stop_flag) { adapter->rx_stop_flag = false; - pch_gbe_start_receive(&adapter->hw); + pch_gbe_enable_dma_rx(&adapter->hw); } pr_debug("poll_end_flag : %d work_done : %d budget : %d\n", -- cgit v1.2.3-55-g7522 From ca749b2a2e72b39b3a46d1e4d096e338bf714a3c Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 17 Oct 2012 22:17:35 +0200 Subject: usb: musb: dsps: fix res_name length The res_name is used for the name construction of a DT property as follows: sprintf(res_name, "port%d-mode", id); Hence, res_name must be at least 11 characters long in order to store the name including the terminating '\0'. While at it, use to snprintf() rather than sprintf() when accessing this buffer. Reported-by: David Binderman Signed-off-by: Daniel Mack Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_dsps.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 444346e1e10d..ff5f112053d2 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -458,11 +458,11 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) struct platform_device *musb; struct resource *res; struct resource resources[2]; - char res_name[10]; + char res_name[11]; int ret, musbid; /* get memory resource */ - sprintf(res_name, "musb%d", id); + snprintf(res_name, sizeof(res_name), "musb%d", id); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name); if (!res) { dev_err(dev, "%s get mem resource failed\n", res_name); @@ -473,7 +473,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) resources[0] = *res; /* get irq resource */ - sprintf(res_name, "musb%d-irq", id); + snprintf(res_name, sizeof(res_name), "musb%d-irq", id); res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name); if (!res) { dev_err(dev, "%s get irq resource failed\n", res_name); @@ -530,7 +530,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps); of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits); - sprintf(res_name, "port%d-mode", id); + snprintf(res_name, sizeof(res_name), "port%d-mode", id); of_property_read_u32(np, res_name, (u32 *)&pdata->mode); of_property_read_u32(np, "power", (u32 *)&pdata->power); config->multipoint = of_property_read_bool(np, "multipoint"); -- cgit v1.2.3-55-g7522 From 000b7f5127900f695668191353a3291832c1914e Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 22 Oct 2012 13:51:11 +0800 Subject: usb: gadget: net2272: fix missing unlock on error in net2272_irq() Add the missing unlock on the error handle path in function net2272_irq(). Signed-off-by: Wei Yongjun Signed-off-by: Felipe Balbi --- drivers/usb/gadget/net2272.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c index 43ac7482fa91..c009263a47e3 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c @@ -2069,8 +2069,10 @@ static irqreturn_t net2272_irq(int irq, void *_dev) #if defined(PLX_PCI_RDK2) /* see if PCI int for us by checking irqstat */ intcsr = readl(dev->rdk2.fpga_base_addr + RDK2_IRQSTAT); - if (!intcsr & (1 << NET2272_PCI_IRQ)) + if (!intcsr & (1 << NET2272_PCI_IRQ)) { + spin_unlock(&dev->lock); return IRQ_NONE; + } /* check dma interrupts */ #endif /* Platform/devcice interrupt handler */ -- cgit v1.2.3-55-g7522 From 4f053a24eca933ec10ce68eef61d38d179f34e50 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 16 Oct 2012 23:31:33 -0700 Subject: usb: renesas_usbhs: fixup: avoid NULL access on error case pipe detach If renesas_usbhs or DMAEngine interrupt didn't happen by a certain cause, urb->ep will be NULL by usb time out. Then, host mode will access to it and crash kernel. This patch fixes it. Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/mod_host.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index 9b69a1323294..069cd765400c 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c @@ -334,6 +334,11 @@ static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv, struct device *dev = usbhs_priv_to_dev(priv); unsigned long flags; + if (unlikely(!uep)) { + dev_err(dev, "no uep\n"); + return; + } + /******************** spin lock ********************/ usbhs_lock(priv, flags); -- cgit v1.2.3-55-g7522 From 1cb60156defa4f23d5318ea1ddd400f25b2d0ce5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 16 Oct 2012 23:33:30 -0700 Subject: usb: renesas_usbhs: fixup dma transfer stall renesas_usbhs driver can switch DMA/PIO transfer by using handler, and each handler have push/pop direction. But unfortunately, current dma push handler didn't a path which calls usbhs_pipe_enable(). Thus, dma transfer never happened. this patch fixes it. Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 143c4e9e1be4..c021b202c0f3 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -795,6 +795,7 @@ static void xfer_work(struct work_struct *work) dev_dbg(dev, " %s %d (%d/ %d)\n", fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero); + usbhs_pipe_enable(pipe); usbhsf_dma_start(pipe, fifo); dma_async_issue_pending(chan); } -- cgit v1.2.3-55-g7522 From 0dc77b6dabec8fd298392018cc0de5214af2dc43 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Mon, 24 Sep 2012 15:32:31 +0900 Subject: extcon: Unregister compat class at module unload to fix oops If you compile extcon with CONFIG_ANDROID and then load and unload the module you get a simple oops as the driver does not unregister its compat class and thus cannot register it again. Full trace: root@(none):~# modprobe extcon_class root@(none):~# rmmod extcon_class root@(none):~# modprobe extcon_class ------------[ cut here ]------------ WARNING: at fs/sysfs/dir.c:536 sysfs_add_one+0xde/0x100() sysfs: cannot create duplicate filename '/class/switch' Modules linked in: extcon_class(+) [last unloaded: extcon_class] Call Trace: 9f451a00: [<602a58bc>] printk+0x0/0xa8 9f451a18: [<60039b43>] warn_slowpath_common+0x93/0xd0 9f451a28: [<6012c6de>] sysfs_add_one+0xde/0x100 9f451a50: [<601d3d90>] strcat+0x0/0x40 9f451a68: [<60039cdc>] warn_slowpath_fmt+0x9c/0xa0 9f451a90: [<6002fe32>] unblock_signals+0x0/0x84 9f451ab0: [<60039c40>] warn_slowpath_fmt+0x0/0xa0 9f451ac0: [<6002fe32>] unblock_signals+0x0/0x84 9f451ae8: [<6012bd97>] sysfs_pathname.isra.10+0x57/0x70 9f451b00: [<601d3d90>] strcat+0x0/0x40 9f451b18: [<6012bd97>] sysfs_pathname.isra.10+0x57/0x70 9f451b48: [<6012c6de>] sysfs_add_one+0xde/0x100 9f451b78: [<6012c96f>] create_dir+0x8f/0x100 9f451bc0: [] extcon_class_init+0x0/0x12 [extcon_class] 9f451bd8: [<6012cda6>] sysfs_create_dir+0xa6/0x1c0 9f451be8: [<601d89f1>] kvasprintf+0x81/0xa0 9f451bf8: [<601cf0f0>] kobject_get+0x0/0x50 9f451c18: [<601cf396>] kobject_add_internal+0x96/0x280 9f451c60: [] extcon_class_init+0x0/0x12 [extcon_class] 9f451c78: [<601cfb93>] kobject_add+0xd3/0x140 9f451cc0: [<601cfac0>] kobject_add+0x0/0x140 9f451cd0: [<6002fe32>] unblock_signals+0x0/0x84 9f451cf8: [<6002fffc>] set_signals+0x29/0x3f 9f451d28: [<600c1de1>] kmem_cache_alloc+0xe1/0x100 9f451d78: [<601cffa0>] kobject_create_and_add+0x50/0xa0 9f451da8: [<601fbe76>] class_compat_register+0x56/0x80 9f451dc8: [] create_extcon_class+0x88/0xd0 [extcon_class] 9f451de8: [] extcon_class_init+0x10/0x12 [extcon_class] 9f451df8: [<600189a8>] do_one_initcall+0x48/0x1f0 9f451e20: [<60061920>] blocking_notifier_call_chain+0x0/0x20 9f451e30: [<60061920>] blocking_notifier_call_chain+0x0/0x20 9f451e58: [<6007e3c3>] sys_init_module+0xa3/0x280 9f451e88: [<6001e2ad>] handle_syscall+0x8d/0x90 9f451ea8: [<60033370>] userspace+0x405/0x531 9f451ee8: [<6001e380>] copy_chunk_to_user+0x0/0x40 9f451ef8: [<6001e5cd>] do_op_one_page+0x14d/0x220 9f451fd8: [<6001a355>] fork_handler+0x95/0xa0 ---[ end trace dd512cc03fe1c367 ]--- ------------[ cut here ]------------ WARNING: at lib/kobject.c:196 kobject_add_internal+0x26e/0x280() kobject_add_internal failed for switch with -EEXIST, don't try to register things with the same name in the same directory. Modules linked in: extcon_class(+) [last unloaded: extcon_class] Call Trace: 9f451ad0: [<602a58bc>] printk+0x0/0xa8 9f451ae8: [<60039b43>] warn_slowpath_common+0x93/0xd0 9f451af8: [<601cf56e>] kobject_add_internal+0x26e/0x280 9f451b18: [<601cf140>] kobject_put+0x0/0x70 9f451b20: [] extcon_class_init+0x0/0x12 [extcon_class] 9f451b38: [<60039cdc>] warn_slowpath_fmt+0x9c/0xa0 9f451b88: [<60039c40>] warn_slowpath_fmt+0x0/0xa0 9f451bc0: [] extcon_class_init+0x0/0x12 [extcon_class] 9f451bd8: [<6012cda6>] sysfs_create_dir+0xa6/0x1c0 9f451be8: [<601d89f1>] kvasprintf+0x81/0xa0 9f451bf8: [<601cf0f0>] kobject_get+0x0/0x50 9f451c18: [<601cf56e>] kobject_add_internal+0x26e/0x280 9f451c60: [] extcon_class_init+0x0/0x12 [extcon_class] 9f451c78: [<601cfb93>] kobject_add+0xd3/0x140 9f451cc0: [<601cfac0>] kobject_add+0x0/0x140 9f451cd0: [<6002fe32>] unblock_signals+0x0/0x84 9f451cf8: [<6002fffc>] set_signals+0x29/0x3f 9f451d28: [<600c1de1>] kmem_cache_alloc+0xe1/0x100 9f451d78: [<601cffa0>] kobject_create_and_add+0x50/0xa0 9f451da8: [<601fbe76>] class_compat_register+0x56/0x80 9f451dc8: [] create_extcon_class+0x88/0xd0 [extcon_class] 9f451de8: [] extcon_class_init+0x10/0x12 [extcon_class] 9f451df8: [<600189a8>] do_one_initcall+0x48/0x1f0 9f451e20: [<60061920>] blocking_notifier_call_chain+0x0/0x20 9f451e30: [<60061920>] blocking_notifier_call_chain+0x0/0x20 9f451e58: [<6007e3c3>] sys_init_module+0xa3/0x280 9f451e88: [<6001e2ad>] handle_syscall+0x8d/0x90 9f451ea8: [<60033370>] userspace+0x405/0x531 9f451ee8: [<6001e380>] copy_chunk_to_user+0x0/0x40 9f451ef8: [<6001e5cd>] do_op_one_page+0x14d/0x220 9f451fd8: [<6001a355>] fork_handler+0x95/0xa0 ---[ end trace dd512cc03fe1c368 ]--- kobject_create_and_add: kobject_add error: -17 ------------[ cut here ]------------ WARNING: at drivers/extcon/extcon_class.c:545 create_extcon_class+0xbc/0xd0 [extcon_class]() cannot allocate Modules linked in: extcon_class(+) [last unloaded: extcon_class] Call Trace: 9f451c80: [<602a58bc>] printk+0x0/0xa8 9f451c98: [<60039b43>] warn_slowpath_common+0x93/0xd0 9f451ca0: [<6002fe32>] unblock_signals+0x0/0x84 9f451ca8: [] create_extcon_class+0xbc/0xd0 [extcon_class] 9f451cd0: [] extcon_class_init+0x0/0x12 [extcon_class] 9f451ce8: [<60039cdc>] warn_slowpath_fmt+0x9c/0xa0 9f451d20: [<6002fe32>] unblock_signals+0x0/0x84 9f451d28: [<60039c40>] warn_slowpath_fmt+0x0/0xa0 9f451d48: [<6002fffc>] set_signals+0x29/0x3f 9f451d58: [<601cf172>] kobject_put+0x32/0x70 9f451d78: [<600c22c3>] kfree+0xb3/0x100 9f451da8: [<601fbe9a>] class_compat_register+0x7a/0x80 9f451dc8: [] create_extcon_class+0xbc/0xd0 [extcon_class] 9f451de8: [] extcon_class_init+0x10/0x12 [extcon_class] 9f451df8: [<600189a8>] do_one_initcall+0x48/0x1f0 9f451e20: [<60061920>] blocking_notifier_call_chain+0x0/0x20 9f451e30: [<60061920>] blocking_notifier_call_chain+0x0/0x20 9f451e58: [<6007e3c3>] sys_init_module+0xa3/0x280 9f451e88: [<6001e2ad>] handle_syscall+0x8d/0x90 9f451ea8: [<60033370>] userspace+0x405/0x531 9f451ee8: [<6001e380>] copy_chunk_to_user+0x0/0x40 9f451ef8: [<6001e5cd>] do_op_one_page+0x14d/0x220 9f451fd8: [<6001a355>] fork_handler+0x95/0xa0 ---[ end trace dd512cc03fe1c369 ]--- FATAL: Error inserting extcon_class (/lib/modules/3.6.0-rc6-00178-g811315f/kernel/drivers/extcon/extcon_class.ko): Cannot allocate memory This patch fixes this. Cc: stable@vger.kernel.org Signed-off-by: Peter Huewe Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-class.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 1ce76a8d777b..63715cdfe988 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -819,6 +819,9 @@ module_init(extcon_class_init); static void __exit extcon_class_exit(void) { +#if defined(CONFIG_ANDROID) + class_compat_unregister(switch_class); +#endif class_destroy(extcon_class); } module_exit(extcon_class_exit); -- cgit v1.2.3-55-g7522 From 824a1bc045cef278aec15bef35d8d0b59ce77856 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Mon, 24 Sep 2012 15:36:24 +0900 Subject: extcon: unregister compat link on cleanup Since extcon registers this compat link at device registration (extcon_dev_register), we should probably remove them at deregistration/cleanup. Cc: stable@vger.kernel.org Signed-off-by: Peter Huewe Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-class.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 63715cdfe988..54dc00b7b9f6 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -570,6 +570,10 @@ static void extcon_cleanup(struct extcon_dev *edev, bool skip) kfree(edev->cables); } +#if defined(CONFIG_ANDROID) + if (switch_class) + class_compat_remove_link(switch_class, edev->dev, NULL); +#endif device_unregister(edev->dev); put_device(edev->dev); } -- cgit v1.2.3-55-g7522 From 5cd3c277ebc64e4bc30c5eb6412edd43b5730a4f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 26 Sep 2012 08:10:03 +0900 Subject: extcon: Fix return value in extcon_register_interest() Propagate the value returned from extcon_find_cable_index() instead of -ENODEV. For readability, -EINVAL is returned in place of the variable. Signed-off-by: Sachin Kamat Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-class.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 54dc00b7b9f6..79f5dbae0147 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -469,7 +469,7 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj, obj->cable_index = extcon_find_cable_index(obj->edev, cable_name); if (obj->cable_index < 0) - return -ENODEV; + return -EINVAL; obj->user_nb = nb; -- cgit v1.2.3-55-g7522 From 03019759b98de92b5507c8c2f6e253a35d59c868 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 2 Oct 2012 09:14:59 +0900 Subject: extcon: adc-jack: Fix checking return value of request_any_context_irq On failure, request_any_context_irq() returns a negative value. On success, it returns either IRQC_IS_HARDIRQ or IRQC_IS_NESTED. Also ensure adc_jack_probe() return 0 on success. Signed-off-by: Axel Lin Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-adc-jack.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c index 725eb5aa8d8c..2cc6bec9f625 100644 --- a/drivers/extcon/extcon-adc-jack.c +++ b/drivers/extcon/extcon-adc-jack.c @@ -161,13 +161,12 @@ static int __devinit adc_jack_probe(struct platform_device *pdev) err = request_any_context_irq(data->irq, adc_jack_irq_thread, pdata->irq_flags, pdata->name, data); - if (err) { + if (err < 0) { dev_err(&pdev->dev, "error: irq %d\n", data->irq); - err = -EINVAL; goto err_irq; } - goto out; + return 0; err_irq: extcon_dev_unregister(&data->edev); -- cgit v1.2.3-55-g7522 From d9310e35a8d5aefad73b2f2387503082da0bea04 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 2 Oct 2012 09:16:53 +0900 Subject: extcon: adc-jack: Add missing MODULE_LICENSE This driver can be built as a module, add MODULE_LICENSE for it. For completeness, also adds MODULE_AUTHOR and MODULE_DESCRIPTION. Signed-off-by: Axel Lin Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-adc-jack.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c index 2cc6bec9f625..e87196f6d2d2 100644 --- a/drivers/extcon/extcon-adc-jack.c +++ b/drivers/extcon/extcon-adc-jack.c @@ -14,6 +14,7 @@ * */ +#include #include #include #include @@ -195,3 +196,7 @@ static struct platform_driver adc_jack_driver = { }; module_platform_driver(adc_jack_driver); + +MODULE_AUTHOR("MyungJoo Ham "); +MODULE_DESCRIPTION("ADC Jack extcon driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3-55-g7522 From 909f9ec0a42eeff94dbcac226664d225a11f10d6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 4 Oct 2012 09:53:45 +0900 Subject: extcon: Fix kerneldoc for extcon_set_cable_state and extcon_set_cable_state_ Signed-off-by: Axel Lin Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-class.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 79f5dbae0147..c27d58d6bbd2 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -356,7 +356,7 @@ int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name) EXPORT_SYMBOL_GPL(extcon_get_cable_state); /** - * extcon_get_cable_state_() - Set the status of a specific cable. + * extcon_set_cable_state_() - Set the status of a specific cable. * @edev: the extcon device that has the cable. * @index: cable index that can be retrieved by extcon_find_cable_index(). * @cable_state: the new cable status. The default semantics is @@ -376,7 +376,7 @@ int extcon_set_cable_state_(struct extcon_dev *edev, EXPORT_SYMBOL_GPL(extcon_set_cable_state_); /** - * extcon_get_cable_state() - Set the status of a specific cable. + * extcon_set_cable_state() - Set the status of a specific cable. * @edev: the extcon device that has the cable. * @cable_name: cable name. * @cable_state: the new cable status. The default semantics is -- cgit v1.2.3-55-g7522 From bf2627d66d416ff438f37643d32866aa93947be6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 4 Oct 2012 09:55:23 +0900 Subject: extcon: max77693: Use max77693_update_reg for rmw operations This simplifies the code. Signed-off-by: Axel Lin Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-max77693.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index e21387e2da5c..e0ed622a0df0 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c @@ -239,25 +239,19 @@ const char *max77693_extcon_cable[] = { static int max77693_muic_set_debounce_time(struct max77693_muic_info *info, enum max77693_muic_adc_debounce_time time) { - int ret = 0; - u8 ctrl3; + int ret; switch (time) { case ADC_DEBOUNCE_TIME_5MS: case ADC_DEBOUNCE_TIME_10MS: case ADC_DEBOUNCE_TIME_25MS: case ADC_DEBOUNCE_TIME_38_62MS: - ret = max77693_read_reg(info->max77693->regmap_muic, - MAX77693_MUIC_REG_CTRL3, &ctrl3); - ctrl3 &= ~CONTROL3_ADCDBSET_MASK; - ctrl3 |= (time << CONTROL3_ADCDBSET_SHIFT); - - ret = max77693_write_reg(info->max77693->regmap_muic, - MAX77693_MUIC_REG_CTRL3, ctrl3); - if (ret) { + ret = max77693_update_reg(info->max77693->regmap_muic, + MAX77693_MUIC_REG_CTRL3, + time << CONTROL3_ADCDBSET_SHIFT, + CONTROL3_ADCDBSET_MASK); + if (ret) dev_err(info->dev, "failed to set ADC debounce time\n"); - ret = -EINVAL; - } break; default: dev_err(info->dev, "invalid ADC debounce time\n"); -- cgit v1.2.3-55-g7522 From f8457d574f680a98c77846a15df13086ab1ab426 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Mon, 8 Oct 2012 14:41:49 +0900 Subject: extcon: MAX77693: Add platform data for MUIC device to initialize registers This patch add platform data for MUIC device to initialize register on probe() call because it should unmask interrupt mask register and initialize some register related to MUIC device. Signed-off-by: Chanwoo Choi Signed-off-by: Myungjoo Ham Signed-off-by: Kyungmin Park --- drivers/extcon/extcon-max77693.c | 27 +++++++++++++++++++++++++++ include/linux/mfd/max77693.h | 13 +++++++++++++ 2 files changed, 40 insertions(+) (limited to 'drivers') diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index e0ed622a0df0..cffeab65051e 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c @@ -651,6 +651,8 @@ out: static int __devinit max77693_muic_probe(struct platform_device *pdev) { struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent); + struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev); + struct max77693_muic_platform_data *muic_pdata = pdata->muic_data; struct max77693_muic_info *info; int ret, i; u8 id; @@ -721,6 +723,31 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev) goto err_extcon; } + /* Initialize MUIC register by using platform data */ + for (i = 0 ; i < muic_pdata->num_init_data ; i++) { + enum max77693_irq_source irq_src = MAX77693_IRQ_GROUP_NR; + + max77693_write_reg(info->max77693->regmap_muic, + muic_pdata->init_data[i].addr, + muic_pdata->init_data[i].data); + + switch (muic_pdata->init_data[i].addr) { + case MAX77693_MUIC_REG_INTMASK1: + irq_src = MUIC_INT1; + break; + case MAX77693_MUIC_REG_INTMASK2: + irq_src = MUIC_INT2; + break; + case MAX77693_MUIC_REG_INTMASK3: + irq_src = MUIC_INT3; + break; + } + + if (irq_src < MAX77693_IRQ_GROUP_NR) + info->max77693->irq_masks_cur[irq_src] + = muic_pdata->init_data[i].data; + } + /* Check revision number of MUIC device*/ ret = max77693_read_reg(info->max77693->regmap_muic, MAX77693_MUIC_REG_ID, &id); diff --git a/include/linux/mfd/max77693.h b/include/linux/mfd/max77693.h index 1d28ae90384e..fe03b2d35d4f 100644 --- a/include/linux/mfd/max77693.h +++ b/include/linux/mfd/max77693.h @@ -30,7 +30,20 @@ #ifndef __LINUX_MFD_MAX77693_H #define __LINUX_MFD_MAX77693_H +struct max77693_reg_data { + u8 addr; + u8 data; +}; + +struct max77693_muic_platform_data { + struct max77693_reg_data *init_data; + int num_init_data; +}; + struct max77693_platform_data { int wakeup; + + /* muic data */ + struct max77693_muic_platform_data *muic_data; }; #endif /* __LINUX_MFD_MAX77693_H */ -- cgit v1.2.3-55-g7522 From 57e7cd37059bb00cd56b60b95b8799af0db91e18 Mon Sep 17 00:00:00 2001 From: anish kumar Date: Mon, 22 Oct 2012 09:43:33 +0900 Subject: extcon: driver model release call not needed There was a case where free and list_del can be called twice on the same pointer.So fixed it by re-arranging the code and removing a function which was not needed. Signed-off-by: anish kumar Signed-off-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/extcon/extcon-class.c | 75 ++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index c27d58d6bbd2..39d3e4d48472 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -545,47 +545,9 @@ static int create_extcon_class(void) return 0; } -static void extcon_cleanup(struct extcon_dev *edev, bool skip) -{ - mutex_lock(&extcon_dev_list_lock); - list_del(&edev->entry); - mutex_unlock(&extcon_dev_list_lock); - - if (!skip && get_device(edev->dev)) { - int index; - - if (edev->mutually_exclusive && edev->max_supported) { - for (index = 0; edev->mutually_exclusive[index]; - index++) - kfree(edev->d_attrs_muex[index].attr.name); - kfree(edev->d_attrs_muex); - kfree(edev->attrs_muex); - } - - for (index = 0; index < edev->max_supported; index++) - kfree(edev->cables[index].attr_g.name); - - if (edev->max_supported) { - kfree(edev->extcon_dev_type.groups); - kfree(edev->cables); - } - -#if defined(CONFIG_ANDROID) - if (switch_class) - class_compat_remove_link(switch_class, edev->dev, NULL); -#endif - device_unregister(edev->dev); - put_device(edev->dev); - } - - kfree(edev->dev); -} - static void extcon_dev_release(struct device *dev) { - struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev); - - extcon_cleanup(edev, true); + kfree(dev); } static const char *muex_name = "mutually_exclusive"; @@ -811,7 +773,40 @@ EXPORT_SYMBOL_GPL(extcon_dev_register); */ void extcon_dev_unregister(struct extcon_dev *edev) { - extcon_cleanup(edev, false); + int index; + + mutex_lock(&extcon_dev_list_lock); + list_del(&edev->entry); + mutex_unlock(&extcon_dev_list_lock); + + if (IS_ERR_OR_NULL(get_device(edev->dev))) { + dev_err(edev->dev, "Failed to unregister extcon_dev (%s)\n", + dev_name(edev->dev)); + return; + } + + if (edev->mutually_exclusive && edev->max_supported) { + for (index = 0; edev->mutually_exclusive[index]; + index++) + kfree(edev->d_attrs_muex[index].attr.name); + kfree(edev->d_attrs_muex); + kfree(edev->attrs_muex); + } + + for (index = 0; index < edev->max_supported; index++) + kfree(edev->cables[index].attr_g.name); + + if (edev->max_supported) { + kfree(edev->extcon_dev_type.groups); + kfree(edev->cables); + } + +#if defined(CONFIG_ANDROID) + if (switch_class) + class_compat_remove_link(switch_class, edev->dev, NULL); +#endif + device_unregister(edev->dev); + put_device(edev->dev); } EXPORT_SYMBOL_GPL(extcon_dev_unregister); -- cgit v1.2.3-55-g7522 From 44b7bccf7c5372eab3408593ab2142a5dcde03f6 Mon Sep 17 00:00:00 2001 From: anish kumar Date: Mon, 22 Oct 2012 10:11:43 +0900 Subject: extcon: trivial: kfree missed from remove path Extcon core doesn't free the memory when we do unregister. Kfree is added in the remove path as it was missing. Signed-off-by: anish kumar Signed-off-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/extcon/extcon-max77693.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index cffeab65051e..a17d0d91ada2 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c @@ -783,6 +783,7 @@ static int __devexit max77693_muic_remove(struct platform_device *pdev) free_irq(muic_irqs[i].virq, info); cancel_work_sync(&info->irq_work); extcon_dev_unregister(info->edev); + kfree(info->edev); kfree(info); return 0; -- cgit v1.2.3-55-g7522 From 4f2de3bf177e57417963eec6a131a7bb2d2b660d Mon Sep 17 00:00:00 2001 From: Jenny TC Date: Thu, 18 Oct 2012 21:00:32 +0900 Subject: extcon : register for cable interest by cable name There are some scnearios where a driver/framework needs to register interest for a particular cable without specifying the extcon device name. One such scenario is charger notifications. The platform will have charger cabel which will be bound to any extcon device. It's not mandatory for the charger driver to know which extcon device it should use. This patch enables the support for registering interest for a cable just by cable name wihtout specifying the extcon device name Signed-off-by: Jenny TC Signed-off-by: MyungJoo Ham Tested-by: Chanwoo Choi -- Kernel-doc comment added by MyungJoo Ham --- drivers/extcon/extcon-class.c | 44 +++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 39d3e4d48472..d398821097f3 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -441,6 +441,8 @@ static int _call_per_cable(struct notifier_block *nb, unsigned long val, * extcon device. * @obj: an empty extcon_specific_cable_nb object to be returned. * @extcon_name: the name of extcon device. + * if NULL, extcon_register_interest will register + * every cable with the target cable_name given. * @cable_name: the target cable name. * @nb: the notifier block to get notified. * @@ -460,22 +462,44 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj, const char *extcon_name, const char *cable_name, struct notifier_block *nb) { - if (!obj || !extcon_name || !cable_name || !nb) + if (!obj || !cable_name || !nb) return -EINVAL; - obj->edev = extcon_get_extcon_dev(extcon_name); - if (!obj->edev) - return -ENODEV; + if (extcon_name) { + obj->edev = extcon_get_extcon_dev(extcon_name); + if (!obj->edev) + return -ENODEV; - obj->cable_index = extcon_find_cable_index(obj->edev, cable_name); - if (obj->cable_index < 0) - return -EINVAL; + obj->cable_index = extcon_find_cable_index(obj->edev, cable_name); + if (obj->cable_index < 0) + return -ENODEV; - obj->user_nb = nb; + obj->user_nb = nb; - obj->internal_nb.notifier_call = _call_per_cable; + obj->internal_nb.notifier_call = _call_per_cable; - return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb); + return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb); + } else { + struct class_dev_iter iter; + struct extcon_dev *extd; + struct device *dev; + + if (!extcon_class) + return -ENODEV; + class_dev_iter_init(&iter, extcon_class, NULL, NULL); + while ((dev = class_dev_iter_next(&iter))) { + extd = (struct extcon_dev *)dev_get_drvdata(dev); + + if (extcon_find_cable_index(extd, cable_name) < 0) + continue; + + class_dev_iter_exit(&iter); + return extcon_register_interest(obj, extd->name, + cable_name, nb); + } + + return -ENODEV; + } } /** -- cgit v1.2.3-55-g7522 From 268300be0e1a0b06582af55251294b268c3d4654 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 19 Oct 2012 17:06:54 +0200 Subject: pinctrl/nomadik: use irq_create_mapping() Since in the DT case, the linear domain path will not allocate descriptors for the IRQs, we need to use irq_create_mapping() for mapping hwirqs to Linux IRQs, so these descriptors get created on-the-fly in this case. ChangeLog v1->v2: - Just use irq_create_mapping() in the .to_irq function since this is called before unmasking or enabling any interrupt lines, so irq_find_mapping() should be sufficient for the IRQ handler function. Cc: Lee Jones Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-nomadik.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 01aea1c3b5fa..db5e0b3bd8be 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -1056,7 +1056,7 @@ static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset) struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); - return irq_find_mapping(nmk_chip->domain, offset); + return irq_create_mapping(nmk_chip->domain, offset); } #ifdef CONFIG_DEBUG_FS -- cgit v1.2.3-55-g7522 From b4dd784ba8af03bf1f9ee5118c792d7abd4919bd Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 22 Oct 2012 12:58:09 +0800 Subject: pinctrl: fix missing unlock on error in pinctrl_groups_show() Add the missing unlock on the error handle path in function pinctrl_groups_show(). Cc: stable@kernel.org Signed-off-by: Wei Yongjun Signed-off-by: Linus Walleij --- drivers/pinctrl/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 0f1ec9e8ff14..2e39c04fc16b 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -1061,8 +1061,10 @@ static int pinctrl_groups_show(struct seq_file *s, void *what) seq_printf(s, "group: %s\n", gname); for (i = 0; i < num_pins; i++) { pname = pin_get_name(pctldev, pins[i]); - if (WARN_ON(!pname)) + if (WARN_ON(!pname)) { + mutex_unlock(&pinctrl_mutex); return -EINVAL; + } seq_printf(s, "pin %d (%s)\n", pins[i], pname); } seq_puts(s, "\n"); -- cgit v1.2.3-55-g7522 From 832b6cdf72fdc32cacba242a749402d28f4648f0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 23 Oct 2012 09:50:17 +0200 Subject: pinctrl/nomadik: use zero as default irq_start The irqdomain semantics were supposed to be such that a linear domain would be used if the passed first_irq was zero or negative, but I got it wrong so only passing zero as first_irq will work properly. Well, zero is NO_IRQ these days so let's pass zero. The semantics of irqdomain_add_simple() will be fixed in a separate patch. Acked-by: Lee Jones Reported-by: Rikard Olsson Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-nomadik.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index db5e0b3bd8be..8bfbad60fcee 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -1281,7 +1281,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) struct clk *clk; int secondary_irq; void __iomem *base; - int irq_start = -1; + int irq_start = 0; int irq; int ret; -- cgit v1.2.3-55-g7522 From 38843e29217bc6b6fce80a5bf19d1636ee337c77 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 23 Oct 2012 11:44:42 +0200 Subject: pinctrl/nomadik: pass DT node to the irqdomain When creating the simple irqdomain, pass the DT node pointer along, as is apropriate. Acked-by: Lee Jones Reported-by: Gabriel Fernandez Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-nomadik.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 8bfbad60fcee..cf82d9ce4dee 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -1387,7 +1387,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) if (!np) irq_start = NOMADIK_GPIO_TO_IRQ(pdata->first_gpio); - nmk_chip->domain = irq_domain_add_simple(NULL, + nmk_chip->domain = irq_domain_add_simple(np, NMK_GPIO_PER_CHIP, irq_start, &nmk_gpio_irq_simple_ops, nmk_chip); if (!nmk_chip->domain) { -- cgit v1.2.3-55-g7522 From a9193983f4f292a82a00c72971c17ec0ee8c6c15 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 22 Oct 2012 12:55:55 +0200 Subject: drm/i915: fix overlay on i830M The overlay on the i830M has a peculiar failure mode: It works the first time around after boot-up, but consistenly hangs the second time it's used. Chris Wilson has dug out a nice errata: "1.5.12 Clock Gating Disable for Display Register Address Offset: 06200h–06203h "Bit 3 Ovrunit Clock Gating Disable. 0 = Clock gating controlled by unit enabling logic 1 = Disable clock gating function DevALM Errata ALM049: Overlay Clock Gating Must be Disabled: Overlay & L2 Cache clock gating must be disabled in order to prevent device hangs when turning off overlay.SW must turn off Ovrunit clock gating (6200h) and L2 Cache clock gating (C8h)." Now I've nowhere found that 0xc8 register and hence couldn't apply the l2 cache workaround. But I've remembered that part of the magic that the OVERLAY_ON/OFF commands are supposed to do is to rearrange cache allocations so that the overlay scaler has some scratch space. And while pondering how that could explain the hang the 2nd time we enable the overlay, I've remembered that the old ums overlay code did _not_ issue the OVERLAY_OFF cmd. And indeed, disabling the OFF cmd results in the overlay working flawlessly, so I guess we can workaround the lack of the above workaround by simply never disabling the overlay engine once it's enabled. Note that we have the first part of the above w/a already implemented in i830_init_clock_gating - leave that as-is to avoid surprises. v2: Add a comment in the code. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=47827 Cc: stable@vger.kernel.org Tested-by: Rhys Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_overlay.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 495625914e4a..d7bc817f51a0 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -341,9 +341,17 @@ static int intel_overlay_off(struct intel_overlay *overlay) intel_ring_emit(ring, flip_addr); intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); /* turn overlay off */ - intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); - intel_ring_emit(ring, flip_addr); - intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + if (IS_I830(dev)) { + /* Workaround: Don't disable the overlay fully, since otherwise + * it dies on the next OVERLAY_ON cmd. */ + intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(ring, MI_NOOP); + } else { + intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); + intel_ring_emit(ring, flip_addr); + intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + } intel_ring_advance(ring); return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail); -- cgit v1.2.3-55-g7522 From 7f6658ef35a470cd641ea35a1da409c4bc5bae1e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 21 Oct 2012 23:26:29 +0200 Subject: drm/i915: VGA needs to be on pipe A on i830M The bit doesn't stick, and the output is always cloned from pipe A, even when it's supposed to scan out from pipe B. Shuts up annoying warnings from the modeset-rework, too. I've noticed that with this patch we know get and unknown connection state since the code can't find a suitable pipe for load detection. But that beats the previous state of affairs, where it tried to use pipe B, actually used pipe A and concluded that something is connected (although it's the LVDS on pipe A and nothing on the VGA connector on pipe B). I've tried to make load detect work by remapping the pipe->planes stuff, so that crtc 0 will use pipe B and hence we still have something left for load-detect on pipe A. But alas, that upset the hw a bit. So there's still some things to figure out, but this here will at least paper over some of the problems. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=51265 Acked-by: Chris Wilson [danvet: extend the commit message a bit with recent observations.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_crt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index f78061af7045..b726b478a4f5 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -729,7 +729,7 @@ void intel_crt_init(struct drm_device *dev) crt->base.type = INTEL_OUTPUT_ANALOG; crt->base.cloneable = true; - if (IS_HASWELL(dev)) + if (IS_HASWELL(dev) || IS_I830(dev)) crt->base.crtc_mask = (1 << 0); else crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); -- cgit v1.2.3-55-g7522 From 446c82fc44da5ae24a205d7130571614dc6969d3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 18 Oct 2012 09:29:44 +0200 Subject: drivers: dma-contiguous: Don't redefine SZ_1M Use the definition from linux/sizes.h instead. Signed-off-by: Laurent Pinchart Signed-off-by: Marek Szyprowski --- drivers/base/dma-contiguous.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index 9a1469474f55..612afcc5a938 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -27,15 +27,12 @@ #include #include #include +#include #include #include #include #include -#ifndef SZ_1M -#define SZ_1M (1 << 20) -#endif - struct cma { unsigned long base_pfn; unsigned long count; -- cgit v1.2.3-55-g7522 From ba4d93bc9ea4510a145161f0af3537b4f380af01 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 18 Oct 2012 09:29:44 +0200 Subject: drivers: dma-coherent: Fix typo in dma_mmap_from_coherent documentation The function documentation incorrectly references dma_release_coherent. Fix it. Don't mention a specific function name as dma_mmap_from_coherent as multiple callers. Signed-off-by: Laurent Pinchart Signed-off-by: Marek Szyprowski --- drivers/base/dma-coherent.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c index 560a7173f810..bc256b641027 100644 --- a/drivers/base/dma-coherent.c +++ b/drivers/base/dma-coherent.c @@ -191,9 +191,8 @@ EXPORT_SYMBOL(dma_release_from_coherent); * This checks whether the memory was allocated from the per-device * coherent memory pool and if so, maps that memory to the provided vma. * - * Returns 1 if we correctly mapped the memory, or 0 if - * dma_release_coherent() should proceed with mapping memory from - * generic pools. + * Returns 1 if we correctly mapped the memory, or 0 if the caller should + * proceed with mapping memory from generic pools. */ int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma, void *vaddr, size_t size, int *ret) -- cgit v1.2.3-55-g7522 From 5e97f3f918c27c68c092bdca7917266615aec62f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 18 Oct 2012 09:29:44 +0200 Subject: drivers: cma: Fix wrong CMA selected region size default value Kconfig lists CMA_SIZE_SEL_ABSOLUTE as the default value fo the CMA selected region size, but that option isn't available in the defined choices. Set the default to CMA_SIZE_SEL_MBYTES instead. Signed-off-by: Laurent Pinchart Signed-off-by: Marek Szyprowski --- drivers/base/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 08b4c5209384..b34b5cda5ae1 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -236,7 +236,7 @@ config CMA_SIZE_PERCENTAGE choice prompt "Selected region size" - default CMA_SIZE_SEL_ABSOLUTE + default CMA_SIZE_SEL_MBYTES config CMA_SIZE_SEL_MBYTES bool "Use mega bytes value only" -- cgit v1.2.3-55-g7522 From 213d27a42ce1646989966011d2af8563feac5635 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 5 Oct 2012 17:51:11 +0200 Subject: spi/pl022: Revert recent runtime PM changes [Originally sent by Ulf as two changes, squashed down into one with a redone changelog, thanks to Russell King for analysis. -- broonie] This reverts commit 688723 (spi/pl022: enable runtime PM) and commit 2fb30d (spi/pl022: fix spi-pl022 pm enable at probe). Commit "spi/pl022: enable runtime PM" introduced runtime PM issues as it interacted badly with the work Russell King had done to move core runtime PM handling into the bus. Due to that commit, "spi/pl022: fix spi-pl022 pm enable at probe" was merged to fix part of those issues. Instead of adding another fix, let's clean up and revert everything back to when it was already fine. Signed-off-by: Ulf Hansson Reviewed-by: Linus Walleij Signed-off-by: Mark Brown Revert "spi/pl022: enable runtime PM" Conflicts: drivers/spi/spi-pl022.c --- drivers/spi/spi-pl022.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 919464102d33..a1db91a99b89 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2186,8 +2186,6 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n", adev->res.start, pl022->virtbase); - pm_runtime_resume(dev); - pl022->clk = devm_clk_get(&adev->dev, NULL); if (IS_ERR(pl022->clk)) { status = PTR_ERR(pl022->clk); @@ -2292,7 +2290,6 @@ pl022_remove(struct amba_device *adev) clk_disable(pl022->clk); clk_unprepare(pl022->clk); - pm_runtime_disable(&adev->dev); amba_release_regions(adev); tasklet_disable(&pl022->pump_transfers); spi_unregister_master(pl022->master); -- cgit v1.2.3-55-g7522 From 1518d7fb5d42aec6ec7349b3be8712af132b46fa Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 17 Oct 2012 12:42:13 -0400 Subject: drm/radeon: fix sparse warning Reported-by: Fengguang Wu Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_gart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index a7677dd1ce98..4f6b09e78159 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -577,7 +577,7 @@ void radeon_vm_manager_fini(struct radeon_device *rdev) * * Global and local mutex must be locked! */ -int radeon_vm_evict(struct radeon_device *rdev, struct radeon_vm *vm) +static int radeon_vm_evict(struct radeon_device *rdev, struct radeon_vm *vm) { struct radeon_vm *vm_evict; -- cgit v1.2.3-55-g7522 From 614499b4d844dcceae5ae2f1e53a2963789a8933 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 17 Oct 2012 17:20:24 -0400 Subject: drm/radeon: give each backlight a unique id In cases where we have multiple radeons with backlight controls. Should fix: https://bugzilla.kernel.org/show_bug.cgi?id=48941 Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/atombios_encoders.c | 5 ++++- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 49cbb3795a10..ba498f8e47a2 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -184,6 +184,7 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder, struct radeon_backlight_privdata *pdata; struct radeon_encoder_atom_dig *dig; u8 backlight_level; + char bl_name[16]; if (!radeon_encoder->enc_priv) return; @@ -203,7 +204,9 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder, memset(&props, 0, sizeof(props)); props.max_brightness = RADEON_MAX_BL_LEVEL; props.type = BACKLIGHT_RAW; - bd = backlight_device_register("radeon_bl", &drm_connector->kdev, + snprintf(bl_name, sizeof(bl_name), + "radeon_bl%d", dev->primary->index); + bd = backlight_device_register(bl_name, &drm_connector->kdev, pdata, &radeon_atom_backlight_ops, &props); if (IS_ERR(bd)) { DRM_ERROR("Backlight registration failed\n"); diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index a13ad9d707cf..0063df9d166d 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -370,6 +370,7 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder, struct backlight_properties props; struct radeon_backlight_privdata *pdata; uint8_t backlight_level; + char bl_name[16]; if (!radeon_encoder->enc_priv) return; @@ -389,7 +390,9 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder, memset(&props, 0, sizeof(props)); props.max_brightness = RADEON_MAX_BL_LEVEL; props.type = BACKLIGHT_RAW; - bd = backlight_device_register("radeon_bl", &drm_connector->kdev, + snprintf(bl_name, sizeof(bl_name), + "radeon_bl%d", dev->primary->index); + bd = backlight_device_register(bl_name, &drm_connector->kdev, pdata, &radeon_backlight_ops, &props); if (IS_ERR(bd)) { DRM_ERROR("Backlight registration failed\n"); -- cgit v1.2.3-55-g7522 From c71721324c612f7f040657ce9917d87f530f9784 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 19 Oct 2012 13:27:04 -0400 Subject: drm/radeon: add error output if VM CS fails on cayman So we know why the CS was rejected. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/evergreen_cs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 573ed1bc6cf7..30271b641913 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -2829,6 +2829,7 @@ static bool evergreen_vm_reg_valid(u32 reg) case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS: return true; default: + DRM_ERROR("Invalid register 0x%x in CS\n", reg); return false; } } -- cgit v1.2.3-55-g7522 From 58f8cf56f937840aa3c1416eed29f595159c60a3 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 22 Oct 2012 17:42:35 +0200 Subject: drm/radeon: fix PFP sync in vm_flush Otherwise the next IB might start reading commands with the page table still invalid. Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ni.c | 4 ++++ drivers/gpu/drm/radeon/nid.h | 1 + drivers/gpu/drm/radeon/si.c | 4 ++++ 3 files changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 8c74c729586d..19b7fe1248be 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -1586,4 +1586,8 @@ void cayman_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) /* bits 0-7 are the VM contexts0-7 */ radeon_ring_write(ring, PACKET0(VM_INVALIDATE_REQUEST, 0)); radeon_ring_write(ring, 1 << vm->id); + + /* sync PFP to ME, otherwise we might get invalid PFP reads */ + radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); + radeon_ring_write(ring, 0x0); } diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index 2423d1b5d385..cbef6815907a 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h @@ -502,6 +502,7 @@ #define PACKET3_MPEG_INDEX 0x3A #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D +#define PACKET3_PFP_SYNC_ME 0x42 #define PACKET3_SURFACE_SYNC 0x43 # define PACKET3_CB0_DEST_BASE_ENA (1 << 6) # define PACKET3_CB1_DEST_BASE_ENA (1 << 7) diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index df8dd7701643..da184de021bd 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2868,6 +2868,10 @@ void si_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2); radeon_ring_write(ring, 0); radeon_ring_write(ring, 1 << vm->id); + + /* sync PFP to ME, otherwise we might get invalid PFP reads */ + radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); + radeon_ring_write(ring, 0x0); } /* -- cgit v1.2.3-55-g7522 From f9fdffa51dff6744726507c641d8151fadbc7cd7 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 22 Oct 2012 17:42:36 +0200 Subject: drm/radeon: fix cayman_vm_set_page v2 Handle requests that won't fit into a single packet. v2: pe needs to increase as well. Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ni.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 19b7fe1248be..81e6a568c29d 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -1538,26 +1538,31 @@ void cayman_vm_set_page(struct radeon_device *rdev, uint64_t pe, { struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index]; uint32_t r600_flags = cayman_vm_page_flags(rdev, flags); - int i; - radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, 1 + count * 2)); - radeon_ring_write(ring, pe); - radeon_ring_write(ring, upper_32_bits(pe) & 0xff); - for (i = 0; i < count; ++i) { - uint64_t value = 0; - if (flags & RADEON_VM_PAGE_SYSTEM) { - value = radeon_vm_map_gart(rdev, addr); - value &= 0xFFFFFFFFFFFFF000ULL; - addr += incr; - - } else if (flags & RADEON_VM_PAGE_VALID) { - value = addr; - addr += incr; - } + while (count) { + unsigned ndw = 1 + count * 2; + if (ndw > 0x3FFF) + ndw = 0x3FFF; + + radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, ndw)); + radeon_ring_write(ring, pe); + radeon_ring_write(ring, upper_32_bits(pe) & 0xff); + for (; ndw > 1; ndw -= 2, --count, pe += 8) { + uint64_t value = 0; + if (flags & RADEON_VM_PAGE_SYSTEM) { + value = radeon_vm_map_gart(rdev, addr); + value &= 0xFFFFFFFFFFFFF000ULL; + addr += incr; + + } else if (flags & RADEON_VM_PAGE_VALID) { + value = addr; + addr += incr; + } - value |= r600_flags; - radeon_ring_write(ring, value); - radeon_ring_write(ring, upper_32_bits(value)); + value |= r600_flags; + radeon_ring_write(ring, value); + radeon_ring_write(ring, upper_32_bits(value)); + } } } -- cgit v1.2.3-55-g7522 From d7025d893897da3e2c26943c57e40d2296146f82 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 22 Oct 2012 17:42:37 +0200 Subject: drm/radeon: fix si_set_page v2 Handle requests that won't fit into a single packet. v2: pe needs to increase as well. Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index da184de021bd..b0db712060fb 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2808,26 +2808,31 @@ void si_vm_set_page(struct radeon_device *rdev, uint64_t pe, { struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index]; uint32_t r600_flags = cayman_vm_page_flags(rdev, flags); - int i; - uint64_t value; - radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 2 + count * 2)); - radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | - WRITE_DATA_DST_SEL(1))); - radeon_ring_write(ring, pe); - radeon_ring_write(ring, upper_32_bits(pe)); - for (i = 0; i < count; ++i) { - if (flags & RADEON_VM_PAGE_SYSTEM) { - value = radeon_vm_map_gart(rdev, addr); - value &= 0xFFFFFFFFFFFFF000ULL; - } else if (flags & RADEON_VM_PAGE_VALID) - value = addr; - else - value = 0; - addr += incr; - value |= r600_flags; - radeon_ring_write(ring, value); - radeon_ring_write(ring, upper_32_bits(value)); + while (count) { + unsigned ndw = 2 + count * 2; + if (ndw > 0x3FFE) + ndw = 0x3FFE; + + radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, ndw)); + radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | + WRITE_DATA_DST_SEL(1))); + radeon_ring_write(ring, pe); + radeon_ring_write(ring, upper_32_bits(pe)); + for (; ndw > 2; ndw -= 2, --count, pe += 8) { + uint64_t value; + if (flags & RADEON_VM_PAGE_SYSTEM) { + value = radeon_vm_map_gart(rdev, addr); + value &= 0xFFFFFFFFFFFFF000ULL; + } else if (flags & RADEON_VM_PAGE_VALID) + value = addr; + else + value = 0; + addr += incr; + value |= r600_flags; + radeon_ring_write(ring, value); + radeon_ring_write(ring, upper_32_bits(value)); + } } } -- cgit v1.2.3-55-g7522 From 204a393c5b88106d7485e20ec834add1013e410a Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 22 Oct 2012 17:42:38 +0200 Subject: drm/radeon: remove set_page check from VM code It's better to handle this in the chipset specific code. Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_gart.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 4f6b09e78159..926dc9db644f 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -1036,8 +1036,7 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev, pte = radeon_sa_bo_gpu_addr(vm->page_tables[pt_idx]); pte += (addr & mask) * 8; - if (((last_pte + 8 * count) != pte) || - ((count + nptes) > 1 << 11)) { + if ((last_pte + 8 * count) != pte) { if (count) { radeon_asic_vm_set_page(rdev, last_pte, -- cgit v1.2.3-55-g7522 From 08eda32b13c045b6219464764d6028d86d3c58a8 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 22 Oct 2012 17:42:39 +0200 Subject: drm/radeon: fix header size estimation in VM code Only NI uses 3dw headers, SI uses 4dw headers. Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_gart.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 926dc9db644f..e9e8953e74a8 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -1147,17 +1147,17 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev, if (RADEON_VM_BLOCK_SIZE > 11) /* reserve space for one header for every 2k dwords */ - ndw += (nptes >> 11) * 3; + ndw += (nptes >> 11) * 4; else /* reserve space for one header for every (1 << BLOCK_SIZE) entries */ - ndw += (nptes >> RADEON_VM_BLOCK_SIZE) * 3; + ndw += (nptes >> RADEON_VM_BLOCK_SIZE) * 4; /* reserve space for pte addresses */ ndw += nptes * 2; /* reserve space for one header for every 2k dwords */ - ndw += (npdes >> 11) * 3; + ndw += (npdes >> 11) * 4; /* reserve space for pde addresses */ ndw += npdes * 2; -- cgit v1.2.3-55-g7522 From 3cf164c8dee834cef9dac4e7325f89a207339ac8 Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Sun, 21 Oct 2012 14:59:22 +0000 Subject: mlx4_core: Remove annoying debug messages from SR-IOV flow These debug prints left behind by commits c82e9aa0a8bc ("mlx4_core: resource tracking for HCA resources used by guests"), 54679e148287 ("mlx4: Implement QP paravirtualization and maintain phys_pkey_cache for smp_snoop") and 993c401e2079 ("mlx4_core: Add IB port-state machine and port mgmt event propagation") make it pretty hard to actually use the mlx4_core debug messages when running in SRIOV/IB mode -- for example, the module load sequence of a device with one VF yielded 631 debug prints, with 408 of them being from this set. Let's just remove them. Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/net/ethernet/mellanox/mlx4/eq.c | 6 ------ drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | 6 ------ 2 files changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index 51c764901ad2..194221b75b90 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -329,9 +329,6 @@ int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave, ctx = &priv->mfunc.master.slave_state[slave]; spin_lock_irqsave(&ctx->lock, flags); - mlx4_dbg(dev, "%s: slave: %d, current state: %d new event :%d\n", - __func__, slave, cur_state, event); - switch (cur_state) { case SLAVE_PORT_DOWN: if (MLX4_PORT_STATE_DEV_EVENT_PORT_UP == event) @@ -366,9 +363,6 @@ int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave, goto out; } ret = mlx4_get_slave_port_state(dev, slave, port); - mlx4_dbg(dev, "%s: slave: %d, current state: %d new event" - " :%d gen_event: %d\n", - __func__, slave, cur_state, event, *gen_event); out: spin_unlock_irqrestore(&ctx->lock, flags); diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 926c911c0ac4..b05705f50f0f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -330,9 +330,6 @@ static void update_pkey_index(struct mlx4_dev *dev, int slave, new_index = priv->virt2phys_pkey[slave][port - 1][orig_index]; *(u8 *)(inbox->buf + 35) = new_index; - - mlx4_dbg(dev, "port = %d, orig pkey index = %d, " - "new pkey index = %d\n", port, orig_index, new_index); } static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox, @@ -351,9 +348,6 @@ static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox, if (optpar & MLX4_QP_OPTPAR_ALT_ADDR_PATH) qp_ctx->alt_path.mgid_index = slave & 0x7F; } - - mlx4_dbg(dev, "slave %d, new gid index: 0x%x ", - slave, qp_ctx->pri_path.mgid_index); } static int mpt_mask(struct mlx4_dev *dev) -- cgit v1.2.3-55-g7522 From 41929ed2656bab8af1734bf5d0088385e72e294f Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Sun, 21 Oct 2012 14:59:23 +0000 Subject: mlx4_core: Perform correct resource cleanup if mlx4_QUERY_ADAPTER() fails Fixed the resource cleanup to act correctly and prevent a kernel oops when mlx4_QUERY_ADAPTER() fails. Signed-off-by: Dotan Barak Reviewed-by: Jack Morgenstein Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/net/ethernet/mellanox/mlx4/main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 80df2ab0177c..2aa80afd98d2 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1405,7 +1405,10 @@ unmap_bf: unmap_bf_area(dev); err_close: - mlx4_close_hca(dev); + if (mlx4_is_slave(dev)) + mlx4_slave_exit(dev); + else + mlx4_CLOSE_HCA(dev, 0); err_free_icm: if (!mlx4_is_slave(dev)) -- cgit v1.2.3-55-g7522 From bb698ca41ba574b3066ebbc5766e5980ae0051ca Mon Sep 17 00:00:00 2001 From: Wolfgang Grandegger Date: Wed, 10 Oct 2012 21:10:42 +0200 Subject: can: flexcan: disable bus error interrupts for the i.MX6q This patch adds some Flexcan version info and removes the feature flag FLEXCAN_HAS_BROKEN_ERR_STATE for the i.MX6Q. It also has the line [TR]WRN_INT properly connected. Cc: Hui Wang Cc: Shawn Guo Signed-off-by: Wolfgang Grandegger [mkl: convert to incremental patch] Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index c78ecfca1e45..a412bf6d73ef 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -144,9 +144,22 @@ #define FLEXCAN_MB_CODE_MASK (0xf0ffffff) -/* FLEXCAN hardware feature flags */ +/* + * FLEXCAN hardware feature flags + * + * Below is some version info we got: + * SOC Version IP-Version Glitch- [TR]WRN_INT + * Filter? connected? + * MX25 FlexCAN2 03.00.00.00 no no + * MX28 FlexCAN2 03.00.04.00 yes yes + * MX35 FlexCAN2 03.00.00.00 no no + * MX53 FlexCAN2 03.00.00.00 yes no + * MX6s FlexCAN3 10.00.12.00 yes yes + * + * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected. + */ #define FLEXCAN_HAS_V10_FEATURES BIT(1) /* For core version >= 10 */ -#define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* Broken error state handling */ +#define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* [TR]WRN_INT not connected */ /* Structure of the message buffer */ struct flexcan_mb { @@ -205,7 +218,7 @@ static struct flexcan_devtype_data fsl_p1010_devtype_data = { }; static struct flexcan_devtype_data fsl_imx28_devtype_data; static struct flexcan_devtype_data fsl_imx6q_devtype_data = { - .features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_BROKEN_ERR_STATE, + .features = FLEXCAN_HAS_V10_FEATURES, }; static const struct can_bittiming_const flexcan_bittiming_const = { -- cgit v1.2.3-55-g7522 From b8977285ecb0033b0bd9a99d4355f9c0bc8708f1 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 23 Oct 2012 14:01:51 -0600 Subject: drivers/block: remove CONFIG_EXPERIMENTAL This config item has not carried much meaning for a while now and is almost always enabled by default. As agreed during the Linux kernel summit, remove it. CC: Greg Kroah-Hartman CC: Asai Thambi S P CC: Pete Zaitcev CC: Cong Wang CC: Jens Axboe Signed-off-by: Kees Cook Signed-off-by: Jens Axboe --- drivers/block/Kconfig | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index f529407db93f..6983a65c8df3 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -166,8 +166,8 @@ config BLK_DEV_DAC960 module will be called DAC960. config BLK_DEV_UMEM - tristate "Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)" - depends on PCI && EXPERIMENTAL + tristate "Micro Memory MM5415 Battery Backed RAM support" + depends on PCI ---help--- Saying Y here will include support for the MM5415 family of battery backed (Non-volatile) RAM cards. @@ -430,8 +430,8 @@ config CDROM_PKTCDVD_BUFFERS a disc is opened for writing. config CDROM_PKTCDVD_WCACHE - bool "Enable write caching (EXPERIMENTAL)" - depends on CDROM_PKTCDVD && EXPERIMENTAL + bool "Enable write caching" + depends on CDROM_PKTCDVD help If enabled, write caching will be set for the CD-R/W device. For now this option is dangerous unless the CD-RW media is known good, as we @@ -508,8 +508,8 @@ config XEN_BLKDEV_BACKEND config VIRTIO_BLK - tristate "Virtio block driver (EXPERIMENTAL)" - depends on EXPERIMENTAL && VIRTIO + tristate "Virtio block driver" + depends on VIRTIO ---help--- This is the virtual block driver for virtio. It can be used with lguest or QEMU based VMMs (like KVM or Xen). Say Y or M. @@ -528,7 +528,7 @@ config BLK_DEV_HD config BLK_DEV_RBD tristate "Rados block device (RBD)" - depends on INET && EXPERIMENTAL && BLOCK + depends on INET && BLOCK select CEPH_LIB select LIBCRC32C select CRYPTO_AES -- cgit v1.2.3-55-g7522 From 966e7a854177097083683176ced871558b631a12 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 17 Oct 2012 12:17:50 +0200 Subject: xhci: endianness xhci_calculate_intel_u2_timeout An le16 is accessed without conversion. This patch should be backported to kernels as old as 3.5, that contain the commit e3567d2c15a7a8e2f992a5f7c7683453ca406d82 "xhci: Add Intel U1/U2 timeout policy." Signed-off-by: Oliver Neukum Signed-off-by: Sarah Sharp CC: stable@vger.kernel.org --- drivers/usb/host/xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7d462bf20092..8d3c454dad76 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4142,7 +4142,7 @@ static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev, (xhci_service_interval_to_ns(desc) > timeout_ns)) timeout_ns = xhci_service_interval_to_ns(desc); - u2_del_ns = udev->bos->ss_cap->bU2DevExitLat * 1000; + u2_del_ns = le16_to_cpu(udev->bos->ss_cap->bU2DevExitLat) * 1000ULL; if (u2_del_ns > timeout_ns) timeout_ns = u2_del_ns; -- cgit v1.2.3-55-g7522 From 16b45fdf9c4e82f5d3bc53aa70737650e7c8d5ed Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 17 Oct 2012 10:16:16 +0200 Subject: xhci: fix integer overflow xhci_service_interval_to_ns() returns long long to avoid an overflow. However, the type cast happens too late. The fix is to force ULL from the beginning. This patch should be backported to kernels as old as 3.5, that contain the commit e3567d2c15a7a8e2f992a5f7c7683453ca406d82 "xhci: Add Intel U1/U2 timeout policy." Signed-off-by: Oliver Neukum Signed-off-by: Sarah Sharp CC: stable@vger.kernel.org --- drivers/usb/host/xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 8d3c454dad76..9ec939646b42 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4021,7 +4021,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev) static unsigned long long xhci_service_interval_to_ns( struct usb_endpoint_descriptor *desc) { - return (1 << (desc->bInterval - 1)) * 125 * 1000; + return (1ULL << (desc->bInterval - 1)) * 125 * 1000; } static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev, -- cgit v1.2.3-55-g7522 From 197ef5ef37d91686545872703bb6d756a53898ea Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 23 Oct 2012 20:29:15 -0400 Subject: USB: Add missing license tag to ezusb driver. ezusb: module license 'unspecified' taints kernel Signed-off-by: Dave Jones Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/ezusb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/misc/ezusb.c b/drivers/usb/misc/ezusb.c index 4223d761223d..6589268a6515 100644 --- a/drivers/usb/misc/ezusb.c +++ b/drivers/usb/misc/ezusb.c @@ -158,3 +158,4 @@ int ezusb_fx2_ihex_firmware_download(struct usb_device *dev, } EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-55-g7522 From 036546bf950b7916dcc051eb0d450e23028b487a Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Tue, 23 Oct 2012 11:33:12 +0300 Subject: usb hub: use flush_work instead of flush_work_sync flush_work_sync and flush_work are now the same and flush_work_sync has been deprecated. This fixes the following warning: drivers/usb/core/hub.c: In function hub_quiesce: drivers/usb/core/hub.c:1216:3: warning: flush_work_sync is deprecated (declared at include/linux/workqueue.h:448) [-Wdeprecated-declarations] Reported-by: Fengguang Wu Signed-off-by: Octavian Purdila Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 1181e917fec7..1af04bdeaf0c 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1213,7 +1213,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) if (hub->has_indicators) cancel_delayed_work_sync(&hub->leds); if (hub->tt.hub) - flush_work_sync(&hub->tt.clear_work); + flush_work(&hub->tt.clear_work); } /* caller has locked the hub device */ -- cgit v1.2.3-55-g7522 From 720dfd250e48a8c7fd1b2b8645955413989c4ee0 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 21 Oct 2012 19:58:30 +0800 Subject: dmaengine: imx-dma: fix missing unlock on error in imxdma_xfer_desc() Add the missing unlock on the error handling path in function imxdma_xfer_desc(). Signed-off-by: Wei Yongjun Cc: stable Signed-off-by: Vinod Koul --- drivers/dma/imx-dma.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index f11b5b2b1a1c..7d9554cc4976 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -474,8 +474,10 @@ static int imxdma_xfer_desc(struct imxdma_desc *d) slot = i; break; } - if (slot < 0) + if (slot < 0) { + spin_unlock_irqrestore(&imxdma->lock, flags); return -EBUSY; + } imxdma->slots_2d[slot].xsr = d->x; imxdma->slots_2d[slot].ysr = d->y; -- cgit v1.2.3-55-g7522 From c57d75c099e55500b620f50a207e61b9e20ecd29 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 23 Oct 2012 10:17:05 +0200 Subject: gpio: mvebu: correctly set the value in direction_output() The ->direction_output() operation of gpio_chip is supposed to set the direction to output but also to set the GPIO to an initial value. Unfortunately, this last part was not done until now, causing for example the LEDs to not be properly set to their default initial value. This patch fixes this by calling the mvebu_gpio_set() function from mvebu_gpio_direction_output() before configuring the GPIO as an output GPIO. Signed-off-by: Thomas Petazzoni Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mvebu.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 902af437eaf2..1bb43e3f9a61 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -244,6 +244,8 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin, if (ret) return ret; + mvebu_gpio_set(chip, pin, value); + spin_lock_irqsave(&mvchip->lock, flags); u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)); u &= ~(1 << pin); -- cgit v1.2.3-55-g7522 From fc09e3672ed623f9c8e73ded3cbcd2cfcf304aac Mon Sep 17 00:00:00 2001 From: Stephane Grosjean Date: Tue, 23 Oct 2012 12:37:17 +0200 Subject: can: sja1000: fix/add miniPCIe/cPCI PC/104Plus PCI/104e PEAK-System boards This patch adds the support for 4 new PCI boards based on the SJA1000 CAN controller, from PEAK-System Technik: . PCAN-miniPCIe (PCI-Express Mini slots, available as single or dual-channel) . PCAN-cPCI (CompactPCI format, available as single or dual-channel) . PCAN-PC/104-Plus (PC/104-Plus system, av. as 1, 2 or 4 channels) . PCAN-PCI/104-Express (PCI/104-Express system, av. as 1 or 2 channels) This patch also fixes a typo in existing "PEAK_MPCI_DEVICE_ID" identifier (missing "e" for Express). Finally, it also changes the author as well as it updates the module supported devices list. Signed-off-by: Stephane Grosjean Acked-by: Oliver Hartkopp Acked-by: Wolfgang Grandegger Signed-off-by: Marc Kleine-Budde --- drivers/net/can/sja1000/peak_pci.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c index f5b82aeb2540..6525dbcca4e3 100644 --- a/drivers/net/can/sja1000/peak_pci.c +++ b/drivers/net/can/sja1000/peak_pci.c @@ -30,9 +30,10 @@ #include "sja1000.h" -MODULE_AUTHOR("Wolfgang Grandegger "); +MODULE_AUTHOR("Stephane Grosjean "); MODULE_DESCRIPTION("Socket-CAN driver for PEAK PCAN PCI family cards"); MODULE_SUPPORTED_DEVICE("PEAK PCAN PCI/PCIe/PCIeC miniPCI CAN cards"); +MODULE_SUPPORTED_DEVICE("PEAK PCAN miniPCIe/cPCI PC/104+ PCI/104e CAN Cards"); MODULE_LICENSE("GPL v2"); #define DRV_NAME "peak_pci" @@ -64,7 +65,11 @@ struct peak_pci_chan { #define PEAK_PCI_DEVICE_ID 0x0001 /* for PCI/PCIe slot cards */ #define PEAK_PCIEC_DEVICE_ID 0x0002 /* for ExpressCard slot cards */ #define PEAK_PCIE_DEVICE_ID 0x0003 /* for nextgen PCIe slot cards */ -#define PEAK_MPCI_DEVICE_ID 0x0008 /* The miniPCI slot cards */ +#define PEAK_CPCI_DEVICE_ID 0x0004 /* for nextgen cPCI slot cards */ +#define PEAK_MPCI_DEVICE_ID 0x0005 /* for nextgen miniPCI slot cards */ +#define PEAK_PC_104P_DEVICE_ID 0x0006 /* PCAN-PC/104+ cards */ +#define PEAK_PCI_104E_DEVICE_ID 0x0007 /* PCAN-PCI/104 Express cards */ +#define PEAK_MPCIE_DEVICE_ID 0x0008 /* The miniPCIe slot cards */ #define PEAK_PCI_CHAN_MAX 4 @@ -76,6 +81,10 @@ static DEFINE_PCI_DEVICE_TABLE(peak_pci_tbl) = { {PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, {PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, {PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {PEAK_PCI_VENDOR_ID, PEAK_MPCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, #ifdef CONFIG_CAN_PEAK_PCIEC {PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, #endif -- cgit v1.2.3-55-g7522 From 5997e089e4c3a7f0958a8fb0a54ec2b5a6f06168 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Thu, 27 Sep 2012 16:35:38 +0800 Subject: dmaengine: sirf: fix a typo in dma_prep_interleaved either DEV_TO_MEM or MEM_TO_DEV is supported, so change OR to AND. Signed-off-by: Barry Song Cc: stable Signed-off-by: Vinod Koul --- drivers/dma/sirf-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c index 64385cde044b..649fd6c965eb 100644 --- a/drivers/dma/sirf-dma.c +++ b/drivers/dma/sirf-dma.c @@ -428,7 +428,7 @@ static struct dma_async_tx_descriptor *sirfsoc_dma_prep_interleaved( unsigned long iflags; int ret; - if ((xt->dir != DMA_MEM_TO_DEV) || (xt->dir != DMA_DEV_TO_MEM)) { + if ((xt->dir != DMA_MEM_TO_DEV) && (xt->dir != DMA_DEV_TO_MEM)) { ret = -EINVAL; goto err_dir; } -- cgit v1.2.3-55-g7522 From 26fd12209c08fe947be1828896ef4ffc5bd0e6df Mon Sep 17 00:00:00 2001 From: Barry Song Date: Thu, 27 Sep 2012 16:36:10 +0800 Subject: dmaengine: sirf: fix a typo in moving running dma_desc to active queue list_move_tail(&schan->queued, &schan->active) makes the list_empty(schan->queued) undefined, we either should change it to: list_move_tail(schan->queued.next, &schan->active) or list_move_tail(&sdesc->node, &schan->active) Signed-off-by: Barry Song Cc: stable Signed-off-by: Vinod Koul --- drivers/dma/sirf-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c index 649fd6c965eb..d451caace806 100644 --- a/drivers/dma/sirf-dma.c +++ b/drivers/dma/sirf-dma.c @@ -109,7 +109,7 @@ static void sirfsoc_dma_execute(struct sirfsoc_dma_chan *schan) sdesc = list_first_entry(&schan->queued, struct sirfsoc_dma_desc, node); /* Move the first queued descriptor to active list */ - list_move_tail(&schan->queued, &schan->active); + list_move_tail(&sdesc->node, &schan->active); /* Start the DMA transfer */ writel_relaxed(sdesc->width, sdma->base + SIRFSOC_DMA_WIDTH_0 + -- cgit v1.2.3-55-g7522 From b6e0e543f75729f207b9c72b0162ae61170635b2 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 21 Oct 2012 12:52:39 +0200 Subject: drm/i915: clear the entire sdvo infoframe buffer Like in the case of native hdmi, which is fixed already in commit adf00b26d18e1b3570451296e03bcb20e4798cdd Author: Paulo Zanoni Date: Tue Sep 25 13:23:34 2012 -0300 drm/i915: make sure we write all the DIP data bytes we need to clear the entire sdvo buffer to avoid upsetting the display. Since infoframe buffer writing is now a bit more elaborate, extract it into it's own function. This will be useful if we ever get around to properly update the ELD for sdvo. Also #define proper names for the two buffer indexes with fixed usage. v2: Cite the right commit above, spotted by Paulo Zanoni. v3: I'm too stupid to paste the right commit. v4: Ben Hutchings noticed that I've failed to handle an underflow in my loop logic, breaking it for i >= length + 8. Since I've just lost C programmer license, use his solution. Also, make the frustrated 0-base buffer size a notch more clear. Reported-and-tested-by: Jürg Billeter Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=25732 Cc: stable@vger.kernel.org Cc: Paulo Zanoni Cc: Ben Hutchings Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sdvo.c | 62 +++++++++++++++++++++++----------- drivers/gpu/drm/i915/intel_sdvo_regs.h | 2 ++ 2 files changed, 44 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index c01d97db0061..79d308da29ff 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -894,6 +894,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo) } #endif +static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo, + unsigned if_index, uint8_t tx_rate, + uint8_t *data, unsigned length) +{ + uint8_t set_buf_index[2] = { if_index, 0 }; + uint8_t hbuf_size, tmp[8]; + int i; + + if (!intel_sdvo_set_value(intel_sdvo, + SDVO_CMD_SET_HBUF_INDEX, + set_buf_index, 2)) + return false; + + if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO, + &hbuf_size, 1)) + return false; + + /* Buffer size is 0 based, hooray! */ + hbuf_size++; + + DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n", + if_index, length, hbuf_size); + + for (i = 0; i < hbuf_size; i += 8) { + memset(tmp, 0, 8); + if (i < length) + memcpy(tmp, data + i, min_t(unsigned, 8, length - i)); + + if (!intel_sdvo_set_value(intel_sdvo, + SDVO_CMD_SET_HBUF_DATA, + tmp, 8)) + return false; + } + + return intel_sdvo_set_value(intel_sdvo, + SDVO_CMD_SET_HBUF_TXRATE, + &tx_rate, 1); +} + static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) { struct dip_infoframe avi_if = { @@ -901,11 +940,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) .ver = DIP_VERSION_AVI, .len = DIP_LEN_AVI, }; - uint8_t tx_rate = SDVO_HBUF_TX_VSYNC; - uint8_t set_buf_index[2] = { 1, 0 }; uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)]; - uint64_t *data = (uint64_t *)sdvo_data; - unsigned i; intel_dip_infoframe_csum(&avi_if); @@ -915,22 +950,9 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) sdvo_data[3] = avi_if.checksum; memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi)); - if (!intel_sdvo_set_value(intel_sdvo, - SDVO_CMD_SET_HBUF_INDEX, - set_buf_index, 2)) - return false; - - for (i = 0; i < sizeof(sdvo_data); i += 8) { - if (!intel_sdvo_set_value(intel_sdvo, - SDVO_CMD_SET_HBUF_DATA, - data, 8)) - return false; - data++; - } - - return intel_sdvo_set_value(intel_sdvo, - SDVO_CMD_SET_HBUF_TXRATE, - &tx_rate, 1); + return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF, + SDVO_HBUF_TX_VSYNC, + sdvo_data, sizeof(sdvo_data)); } static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h index 9d030142ee43..770bdd6ecd9f 100644 --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h @@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg { #define SDVO_CMD_SET_AUDIO_STAT 0x91 #define SDVO_CMD_GET_AUDIO_STAT 0x92 #define SDVO_CMD_SET_HBUF_INDEX 0x93 + #define SDVO_HBUF_INDEX_ELD 0 + #define SDVO_HBUF_INDEX_AVI_IF 1 #define SDVO_CMD_GET_HBUF_INDEX 0x94 #define SDVO_CMD_GET_HBUF_INFO 0x95 #define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96 -- cgit v1.2.3-55-g7522 From 168bfeef7bba3f9784f7540b053e4ac72b769ce9 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 23 Oct 2012 14:09:39 -0700 Subject: amd64_edac:__amd64_set_scrub_rate(): avoid overindexing scrubrates[] If none of the elements in scrubrates[] matches, this loop will cause __amd64_set_scrub_rate() to incorrectly use the n+1th element. As the function is designed to use the final scrubrates[] element in the case of no match, we can fix this bug by simply terminating the array search at the n-1th element. Boris: this code is fragile anyway, see here why: http://marc.info/?l=linux-kernel&m=135102834131236&w=2 It will be rewritten more robustly soonish. Reported-by: Denis Kirjanov Cc: stable@vger.kernel.org Cc: Doug Thompson Signed-off-by: Andrew Morton Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 5a297a26211d..cc8e7c78a23c 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -170,8 +170,11 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate) * memory controller and apply to register. Search for the first * bandwidth entry that is greater or equal than the setting requested * and program that. If at last entry, turn off DRAM scrubbing. + * + * If no suitable bandwidth is found, turn off DRAM scrubbing entirely + * by falling back to the last element in scrubrates[]. */ - for (i = 0; i < ARRAY_SIZE(scrubrates); i++) { + for (i = 0; i < ARRAY_SIZE(scrubrates) - 1; i++) { /* * skip scrub rates which aren't recommended * (see F10 BKDG, F3x58) @@ -181,12 +184,6 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate) if (scrubrates[i].bandwidth <= new_bw) break; - - /* - * if no suitable bandwidth found, turn off DRAM scrubbing - * entirely by falling back to the last element in the - * scrubrates array. - */ } scrubval = scrubrates[i].scrubval; -- cgit v1.2.3-55-g7522 From d0078e72314df2e5ede03f2102cddde06767c374 Mon Sep 17 00:00:00 2001 From: Hiro Sugawara Date: Thu, 18 Oct 2012 08:35:10 +0300 Subject: iommu/tegra: smmu: Fix deadly typo Fix a deadly typo in macro definition. Cc: stable@vger.kernel.org Signed-off-by: Hiro Sugawara Signed-off-by: Hiroshi Doyu Signed-off-by: Joerg Roedel --- drivers/iommu/tegra-smmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 0b4d62e0c645..a649f146d17b 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -200,7 +200,7 @@ enum { #define SMMU_ADDR_TO_PFN(addr) ((addr) >> 12) #define SMMU_ADDR_TO_PDN(addr) ((addr) >> 22) -#define SMMU_PDN_TO_ADDR(addr) ((pdn) << 22) +#define SMMU_PDN_TO_ADDR(pdn) ((pdn) << 22) #define _READABLE (1 << SMMU_PTB_DATA_ASID_READABLE_SHIFT) #define _WRITABLE (1 << SMMU_PTB_DATA_ASID_WRITABLE_SHIFT) -- cgit v1.2.3-55-g7522 From 1bcb04f758c7d3ab9a454525c004bdb8c0fccd98 Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 23 Oct 2012 15:53:16 +0200 Subject: drm/radeon: fix and simplify pot argument checks v3 GART and VRAM size limits need to be a power of two. Fix values greater than 1GB and simplify those checks a bit. v2: also fix radeon_vram_limit usage, and simplify test even more. v3: agd5f: fix spelling as noticed by Klaus Schnass Signed-off-by: Christian König Reviewed-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_device.c | 60 ++++++++++++++-------------------- 1 file changed, 24 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index bd13ca09eb62..e2f5f888c374 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -355,6 +355,8 @@ int radeon_wb_init(struct radeon_device *rdev) */ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base) { + uint64_t limit = (uint64_t)radeon_vram_limit << 20; + mc->vram_start = base; if (mc->mc_vram_size > (0xFFFFFFFF - base + 1)) { dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n"); @@ -368,8 +370,8 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 mc->mc_vram_size = mc->aper_size; } mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; - if (radeon_vram_limit && radeon_vram_limit < mc->real_vram_size) - mc->real_vram_size = radeon_vram_limit; + if (limit && limit < mc->real_vram_size) + mc->real_vram_size = limit; dev_info(rdev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n", mc->mc_vram_size >> 20, mc->vram_start, mc->vram_end, mc->real_vram_size >> 20); @@ -834,6 +836,19 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state) return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; } +/** + * radeon_check_pot_argument - check that argument is a power of two + * + * @arg: value to check + * + * Validates that a certain argument is a power of two (all asics). + * Returns true if argument is valid. + */ +static bool radeon_check_pot_argument(int arg) +{ + return (arg & (arg - 1)) == 0; +} + /** * radeon_check_arguments - validate module params * @@ -845,52 +860,25 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state) static void radeon_check_arguments(struct radeon_device *rdev) { /* vramlimit must be a power of two */ - switch (radeon_vram_limit) { - case 0: - case 4: - case 8: - case 16: - case 32: - case 64: - case 128: - case 256: - case 512: - case 1024: - case 2048: - case 4096: - break; - default: + if (!radeon_check_pot_argument(radeon_vram_limit)) { dev_warn(rdev->dev, "vram limit (%d) must be a power of 2\n", radeon_vram_limit); radeon_vram_limit = 0; - break; } - radeon_vram_limit = radeon_vram_limit << 20; + /* gtt size must be power of two and greater or equal to 32M */ - switch (radeon_gart_size) { - case 4: - case 8: - case 16: + if (radeon_gart_size < 32) { dev_warn(rdev->dev, "gart size (%d) too small forcing to 512M\n", radeon_gart_size); radeon_gart_size = 512; - break; - case 32: - case 64: - case 128: - case 256: - case 512: - case 1024: - case 2048: - case 4096: - break; - default: + + } else if (!radeon_check_pot_argument(radeon_gart_size)) { dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n", radeon_gart_size); radeon_gart_size = 512; - break; } - rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; + rdev->mc.gtt_size = (uint64_t)radeon_gart_size << 20; + /* AGP mode can only be -1, 1, 2, 4, 8 */ switch (radeon_agpmode) { case -1: -- cgit v1.2.3-55-g7522 From 59240ee3e8f0dbd3d35db90cc4960143cb14be85 Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 23 Oct 2012 15:53:17 +0200 Subject: drm/radeon: use vzalloc for gart pages When allocating more than 2GB of GART the array of pages gets to big for kzalloc, use vzalloc instead. Signed-off-by: Christian König Reviewed-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_gart.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index e9e8953e74a8..4debd60e5aa6 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -355,14 +355,13 @@ int radeon_gart_init(struct radeon_device *rdev) DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n", rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages); /* Allocate pages table */ - rdev->gart.pages = kzalloc(sizeof(void *) * rdev->gart.num_cpu_pages, - GFP_KERNEL); + rdev->gart.pages = vzalloc(sizeof(void *) * rdev->gart.num_cpu_pages); if (rdev->gart.pages == NULL) { radeon_gart_fini(rdev); return -ENOMEM; } - rdev->gart.pages_addr = kzalloc(sizeof(dma_addr_t) * - rdev->gart.num_cpu_pages, GFP_KERNEL); + rdev->gart.pages_addr = vzalloc(sizeof(dma_addr_t) * + rdev->gart.num_cpu_pages); if (rdev->gart.pages_addr == NULL) { radeon_gart_fini(rdev); return -ENOMEM; @@ -388,8 +387,8 @@ void radeon_gart_fini(struct radeon_device *rdev) radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages); } rdev->gart.ready = false; - kfree(rdev->gart.pages); - kfree(rdev->gart.pages_addr); + vfree(rdev->gart.pages); + vfree(rdev->gart.pages_addr); rdev->gart.pages = NULL; rdev->gart.pages_addr = NULL; -- cgit v1.2.3-55-g7522 From 6c0d112f1fb4abba724065daa8ffbc9f0e171dc1 Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 23 Oct 2012 15:53:18 +0200 Subject: drm/radeon: move size limits to gem_object_create. Driver internal users shouldn't be limited in their allocation size. Signed-off-by: Christian König Reviewed-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_gem.c | 10 ++++++++++ drivers/gpu/drm/radeon/radeon_object.c | 9 --------- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index f38fbcc46935..dfee7bb03ab0 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -53,6 +53,7 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size, struct drm_gem_object **obj) { struct radeon_bo *robj; + unsigned long max_size; int r; *obj = NULL; @@ -60,6 +61,15 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size, if (alignment < PAGE_SIZE) { alignment = PAGE_SIZE; } + + /* maximun bo size is the minimun btw visible vram and gtt size */ + max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size); + if (size > max_size) { + printk(KERN_WARNING "%s:%d alloc size %dMb bigger than %ldMb limit\n", + __func__, __LINE__, size >> 20, max_size >> 20); + return -ENOMEM; + } + r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, NULL, &robj); if (r) { if (r != -ERESTARTSYS) diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 8b27dd6e3144..f404944931f5 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -105,7 +105,6 @@ int radeon_bo_create(struct radeon_device *rdev, struct radeon_bo *bo; enum ttm_bo_type type; unsigned long page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT; - unsigned long max_size = 0; size_t acc_size; int r; @@ -121,14 +120,6 @@ int radeon_bo_create(struct radeon_device *rdev, } *bo_ptr = NULL; - /* maximun bo size is the minimun btw visible vram and gtt size */ - max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size); - if ((page_align << PAGE_SHIFT) >= max_size) { - printk(KERN_WARNING "%s:%d alloc size %ldM bigger than %ldMb limit\n", - __func__, __LINE__, page_align >> (20 - PAGE_SHIFT), max_size >> 20); - return -ENOMEM; - } - acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size, sizeof(struct radeon_bo)); -- cgit v1.2.3-55-g7522 From 0fe7158c8a61ffdd71789de054fbee257c34d054 Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 23 Oct 2012 15:53:19 +0200 Subject: drm/radeon: move the retry to gem_object_create When internal users want VRAM we shouldn't return GART memory instead. Signed-off-by: Christian König Reviewed-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_gem.c | 8 +++++++- drivers/gpu/drm/radeon/radeon_object.c | 10 ---------- 2 files changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index dfee7bb03ab0..fe5c1f6b7957 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -70,11 +70,17 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size, return -ENOMEM; } +retry: r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, NULL, &robj); if (r) { - if (r != -ERESTARTSYS) + if (r != -ERESTARTSYS) { + if (initial_domain == RADEON_GEM_DOMAIN_VRAM) { + initial_domain |= RADEON_GEM_DOMAIN_GTT; + goto retry; + } DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n", size, initial_domain, alignment, r); + } return r; } *obj = &robj->gem_base; diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index f404944931f5..b91118ccef86 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -123,7 +123,6 @@ int radeon_bo_create(struct radeon_device *rdev, acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size, sizeof(struct radeon_bo)); -retry: bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); if (bo == NULL) return -ENOMEM; @@ -145,15 +144,6 @@ retry: acc_size, sg, &radeon_ttm_bo_destroy); up_read(&rdev->pm.mclk_lock); if (unlikely(r != 0)) { - if (r != -ERESTARTSYS) { - if (domain == RADEON_GEM_DOMAIN_VRAM) { - domain |= RADEON_GEM_DOMAIN_GTT; - goto retry; - } - dev_err(rdev->dev, - "object_init failed for (%lu, 0x%08X)\n", - size, domain); - } return r; } *bo_ptr = bo; -- cgit v1.2.3-55-g7522 From c9bd773c6dd4a52f32e64af5dbbf9b3834f8569a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 23 Oct 2012 12:42:42 -0400 Subject: drm/radeon: fix ATPX function documentation The ATPX code no longer handles ATRM. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_atpx_handler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 1aa3f910b993..5c5e5bb00f56 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -373,11 +373,11 @@ static int radeon_atpx_power_state(enum vga_switcheroo_client_id id, } /** - * radeon_atpx_pci_probe_handle - look up the ATRM and ATPX handles + * radeon_atpx_pci_probe_handle - look up the ATPX handle * * @pdev: pci device * - * Look up the ATPX and ATRM handles (all asics). + * Look up the ATPX handles (all asics). * Returns true if the handles are found, false if not. */ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) -- cgit v1.2.3-55-g7522 From 0b90365e7a32317b948583c4b5c2712d84610b08 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 23 Oct 2012 17:57:54 -0400 Subject: drm/radeon: fix ATPX regression in acpi rework Copy and paste typo in the apci rework. Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=49351 Signed-off-by: Alex Deucher Reviewed-by: Jerome Glisse --- drivers/gpu/drm/radeon/radeon_atpx_handler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 5c5e5bb00f56..37f6a907aea4 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -87,7 +87,7 @@ static union acpi_object *radeon_atpx_call(acpi_handle handle, int function, atpx_arg_elements[1].integer.value = 0; } - status = acpi_evaluate_object(handle, "ATPX", &atpx_arg, &buffer); + status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer); /* Fail only if calling the method fails and ATPX is supported */ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { -- cgit v1.2.3-55-g7522 From 0c7e92075f6e61bfc90ec2664c034b04bc157315 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 14 Oct 2012 22:15:48 +0200 Subject: rtlwifi: pass rx setup error code to caller If _rtl_usb_receive fails, the device is probably not ready. Hence the error code should be passed to the caller, so it can react accordingly and notify the user. Signed-off-by: Christian Lamparter Acked-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 030beb45d8b0..e3ea4b346889 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -673,7 +673,7 @@ static int rtl_usb_start(struct ieee80211_hw *hw) set_hal_start(rtlhal); /* Start bulk IN */ - _rtl_usb_receive(hw); + err = _rtl_usb_receive(hw); } return err; -- cgit v1.2.3-55-g7522 From 761ce8c41ed20ee3af77f2df527edc3f92e6f3bf Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 16 Oct 2012 14:34:12 +0200 Subject: rt2x00: usb: fix reset resume Patch fixes warnings like below happened on resume: WARNING: at net/mac80211/driver-ops.h:12 check_sdata_in_driver+0x32/0x34() Problem is that in __ieee80211_susped() we remove sdata (i.e wlan0 interface) and then during resume we call usb_unbind_interface() -> ieee80211_unregister_hw() with sdata removed. Patch fixes problem by adding .reset_resume calback, hence we do not unbind usb device on resume. This callback can be the same as normal .resume callback, sice we do all needed initalization during interface start, which is performed on resume [ ieee80211_resume() -> ieee80211_reconfig() -> rt2x00mac_start() -> rt2x00lib_start ]. Resolves: https://bugzilla.kernel.org/show_bug.cgi?id=48041 Reported-by: David Herrmann Reported-and-tested-by: Stephen Boyd Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 1 + drivers/net/wireless/rt2x00/rt2800usb.c | 1 + drivers/net/wireless/rt2x00/rt73usb.c | 1 + 3 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index a12e84f892be..6b2e1e431dd2 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1988,6 +1988,7 @@ static struct usb_driver rt2500usb_driver = { .disconnect = rt2x00usb_disconnect, .suspend = rt2x00usb_suspend, .resume = rt2x00usb_resume, + .reset_resume = rt2x00usb_resume, .disable_hub_initiated_lpm = 1, }; diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index c9e9370eb789..3b8fb5a603f2 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -1282,6 +1282,7 @@ static struct usb_driver rt2800usb_driver = { .disconnect = rt2x00usb_disconnect, .suspend = rt2x00usb_suspend, .resume = rt2x00usb_resume, + .reset_resume = rt2x00usb_resume, .disable_hub_initiated_lpm = 1, }; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index e5eb43b3eee7..24eec66e9fd2 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2535,6 +2535,7 @@ static struct usb_driver rt73usb_driver = { .disconnect = rt2x00usb_disconnect, .suspend = rt2x00usb_suspend, .resume = rt2x00usb_resume, + .reset_resume = rt2x00usb_resume, .disable_hub_initiated_lpm = 1, }; -- cgit v1.2.3-55-g7522 From 763cbac07674a648f1377b21ca66f577c103fa9a Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Tue, 16 Oct 2012 21:31:49 +0530 Subject: ath9k_htc: Add PID/VID for a Ubiquiti WiFiStation Roger says, Ubiquiti produce 2 versions of their WiFiStation USB adapter. One has an internal antenna, the other has an external antenna and name suffix EXT. They have separate USB ids and in distribution openSUSE 12.2 (kernel 3.4.6), file /usr/share/usb.ids shows: 0cf3 Atheros Communications, Inc. ... b002 Ubiquiti WiFiStation 802.11n [Atheros AR9271] b003 Ubiquiti WiFiStationEXT 802.11n [Atheros AR9271] Add b002 Ubiquiti WiFiStation in the PID/VID list. Reported-by: Roger Price Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 924c4616c3d9..f5dda84176c3 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -38,6 +38,7 @@ static struct usb_device_id ath9k_hif_usb_ids[] = { { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */ { USB_DEVICE(0x040D, 0x3801) }, /* VIA */ { USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */ + { USB_DEVICE(0x0cf3, 0xb002) }, /* Ubiquiti WifiStation */ { USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */ { USB_DEVICE(0x0cf3, 0x7015), -- cgit v1.2.3-55-g7522 From 73b26df5fa1a6245d6fc982362518b620bc7c2fe Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 17 Oct 2012 13:50:43 +0200 Subject: Revert "ath9k_hw: Updated AR9003 tx gain table for 5GHz" This reverts commit a240dc7b3c7463bd60cf0a9b2a90f52f78aae0fd. This commit is reducing tx power by at least 10 db on some devices, e.g. the Buffalo WZR-HP-G450H. Signed-off-by: Felix Fietkau Cc: stable@vger.kernel.org Cc: rmanohar@qca.qualcomm.com Signed-off-by: John W. Linville --- .../net/wireless/ath/ath9k/ar9003_2p2_initvals.h | 164 ++++++++++----------- 1 file changed, 82 insertions(+), 82 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 89bf94d4d8a1..6f7cf49eff4d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -534,107 +534,107 @@ static const u32 ar9300_2p2_baseband_core[][2] = { static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, + {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400}, - {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402}, - {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404}, - {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603}, - {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02}, - {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04}, - {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20}, - {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20}, - {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22}, - {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24}, - {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640}, - {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x5a08442e, 0x5a08442e, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x5e0a4431, 0x5e0a4431, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, + {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, + {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, + {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, + {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400}, - {0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402}, - {0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603}, - {0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02}, - {0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04}, - {0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20}, - {0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20}, - {0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22}, - {0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24}, - {0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640}, - {0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660}, - {0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861}, - {0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81}, - {0x0000a5cc, 0x5a88442e, 0x5a88442e, 0x47801a83, 0x47801a83}, - {0x0000a5d0, 0x5e8a4431, 0x5e8a4431, 0x4a801c84, 0x4a801c84}, - {0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3}, - {0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5}, - {0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9}, - {0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb}, - {0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, + {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, + {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, + {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, + {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, + {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, + {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, + {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, + {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, + {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, + {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, + {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861}, + {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81}, + {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83}, + {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84}, + {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3}, + {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5}, + {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9}, + {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb}, + {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, - {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, - {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, - {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000}, - {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501}, - {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501}, - {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, + {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, + {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, + {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, + {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, - {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, - {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, + {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, + {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, + {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, + {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, }; -- cgit v1.2.3-55-g7522 From 9495b31ad7e2b479501abb36a62789d59ee406fc Mon Sep 17 00:00:00 2001 From: Yuanhan Liu Date: Thu, 18 Oct 2012 18:10:56 +0800 Subject: brcmfmac: fix potential NULL dereference Fix a samtch warnings catched by Fengguang's 0-DAY system: + drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c:3572 brcmf_cfg80211_sched_scan_start() error: we previously assumed 'request' could be null (see line 3571) Cc: John W. Linville Signed-off-by: Yuanhan Liu Acked-by: Franky Lin Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 411dfe7c7ff0..a6f1e8166008 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -3569,7 +3569,7 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, if (!request || !request->n_ssids || !request->n_match_sets) { WL_ERR("Invalid sched scan req!! n_ssids:%d\n", - request->n_ssids); + request ? request->n_ssids : 0); return -EINVAL; } -- cgit v1.2.3-55-g7522 From dcd5c79c9a3a7ac08bdce089fec810677ce6efe8 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Fri, 19 Oct 2012 19:01:59 -0700 Subject: mwifiex: return -EBUSY if specific scan request cannot be honored Previous patch "mwifiex: return -EBUSY if scan request cannot.." corrected regular scan request only. There is another case for specific scan that needs the same handling. Also, removed !req_ssid check as it has already been validated by caller. Signed-off-by: Bing Zhao Signed-off-by: Paul Stewart Reviewed-by: Ryan Cairns Signed-off-by: Amitkumar Karwar Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/scan.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 00b658d3b6ec..9171aaedbccd 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -1843,21 +1843,18 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, struct cfg80211_ssid *req_ssid) { struct mwifiex_adapter *adapter = priv->adapter; - int ret = 0; + int ret; struct mwifiex_user_scan_cfg *scan_cfg; - if (!req_ssid) - return -1; - if (adapter->scan_processing) { - dev_dbg(adapter->dev, "cmd: Scan already in process...\n"); - return ret; + dev_err(adapter->dev, "cmd: Scan already in process...\n"); + return -EBUSY; } if (priv->scan_block) { - dev_dbg(adapter->dev, + dev_err(adapter->dev, "cmd: Scan is blocked during association...\n"); - return ret; + return -EBUSY; } scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); -- cgit v1.2.3-55-g7522 From 6fcf2b10533bf51c67f0286ddba16e958e7ed972 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Fri, 19 Oct 2012 19:02:00 -0700 Subject: mwifiex: clean up scan state on error De-reference and deallocate scan state on failure. Signed-off-by: Bing Zhao Signed-off-by: Paul Stewart Tested-by: Paul Stewart Reviewed-by: Ryan Cairns Signed-off-by: Amitkumar Karwar Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 0679458a1bac..780d3e168297 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1825,8 +1825,6 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, return -EBUSY; } - priv->scan_request = request; - priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); if (!priv->user_scan_cfg) { @@ -1834,6 +1832,8 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, return -ENOMEM; } + priv->scan_request = request; + priv->user_scan_cfg->num_ssids = request->n_ssids; priv->user_scan_cfg->ssid_list = request->ssids; @@ -1870,6 +1870,9 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, ret = mwifiex_scan_networks(priv, priv->user_scan_cfg); if (ret) { dev_err(priv->adapter->dev, "scan failed: %d\n", ret); + priv->scan_request = NULL; + kfree(priv->user_scan_cfg); + priv->user_scan_cfg = NULL; return ret; } -- cgit v1.2.3-55-g7522 From f89ff6441df06abc2d95f3ef67525923032d6283 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 24 Oct 2012 08:57:16 -0500 Subject: b43: Fix oops on unload when firmware not found When b43 fails to find firmware when loaded, a subsequent unload will oops due to calling ieee80211_unregister_hw() when the corresponding register call was never made. Commit 2d838bb608e2d1f6cb4280e76748cb812dc822e7 fixed the same problem for b43legacy. Signed-off-by: Larry Finger Tested-by: Markus Kanet Cc: Stable [V3.3.0+ (the patch will need to be refactored)] Cc: Markus Kanet Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 73730e94e0ac..c5a99c8c8168 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -5404,6 +5404,8 @@ static void b43_bcma_remove(struct bcma_device *core) cancel_work_sync(&wldev->restart_work); B43_WARN_ON(!wl); + if (!wldev->fw.ucode.data) + return; /* NULL if firmware never loaded */ if (wl->current_dev == wldev && wl->hw_registred) { b43_leds_stop(wldev); ieee80211_unregister_hw(wl->hw); @@ -5478,6 +5480,8 @@ static void b43_ssb_remove(struct ssb_device *sdev) cancel_work_sync(&wldev->restart_work); B43_WARN_ON(!wl); + if (!wldev->fw.ucode.data) + return; /* NULL if firmware never loaded */ if (wl->current_dev == wldev && wl->hw_registred) { b43_leds_stop(wldev); ieee80211_unregister_hw(wl->hw); -- cgit v1.2.3-55-g7522 From f7bc5051667b74c3861f79eed98c60d5c3b883f7 Mon Sep 17 00:00:00 2001 From: Lennart Sorensen Date: Wed, 24 Oct 2012 10:23:09 -0400 Subject: USB: serial: Fix memory leak in sierra_release() I found a memory leak in sierra_release() (well sierra_probe() I guess) that looses 8 bytes each time the driver releases a device. Signed-off-by: Len Sorensen Acked-by: Johan Hovold Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 01d882cf3775..76ef95bcbbf2 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -959,6 +959,7 @@ static void sierra_release(struct usb_serial *serial) continue; kfree(portdata); } + kfree(serial->private); } #ifdef CONFIG_PM -- cgit v1.2.3-55-g7522 From a4f743851f74fc3e0cc40c13082e65c24139f481 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 16 Oct 2012 17:09:22 +0300 Subject: Revert "serial: omap: fix software flow control" This reverts commit 957ee7270d632245b43f6feb0e70d9a5e9ea6cf6 (serial: omap: fix software flow control). As Russell has pointed out, that commit isn't fixing Software Flow Control at all, and it actually makes it even more broken. It was agreed to revert this commit and use Russell's latest UART patches instead. Cc: Russell King Signed-off-by: Felipe Balbi Acked-by: Tony Lindgren Signed-off-by: Greg Kroah-Hartman --- arch/arm/plat-omap/include/plat/omap-serial.h | 4 ++-- drivers/tty/serial/omap-serial.c | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h index f4a4cd014795..1957a8516e93 100644 --- a/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/arch/arm/plat-omap/include/plat/omap-serial.h @@ -40,10 +40,10 @@ #define OMAP_UART_WER_MOD_WKUP 0X7F /* Enable XON/XOFF flow control on output */ -#define OMAP_UART_SW_TX 0x8 +#define OMAP_UART_SW_TX 0x04 /* Enable XON/XOFF flow control on input */ -#define OMAP_UART_SW_RX 0x2 +#define OMAP_UART_SW_RX 0x04 #define OMAP_UART_SYSC_RESET 0X07 #define OMAP_UART_TCR_TRIG 0X0F diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 6ede6fd92b4c..6d3d26a607b9 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -671,19 +671,19 @@ serial_omap_configure_xonxoff /* * IXON Flag: - * Flow control for OMAP.TX - * OMAP.RX should listen for XON/XOFF + * Enable XON/XOFF flow control on output. + * Transmit XON1, XOFF1 */ if (termios->c_iflag & IXON) - up->efr |= OMAP_UART_SW_RX; + up->efr |= OMAP_UART_SW_TX; /* * IXOFF Flag: - * Flow control for OMAP.RX - * OMAP.TX should send XON/XOFF + * Enable XON/XOFF flow control on input. + * Receiver compares XON1, XOFF1. */ if (termios->c_iflag & IXOFF) - up->efr |= OMAP_UART_SW_TX; + up->efr |= OMAP_UART_SW_RX; serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); -- cgit v1.2.3-55-g7522 From d7870af7e2e3a91b462075ec1ca669b482215187 Mon Sep 17 00:00:00 2001 From: Michael Shigorin Date: Mon, 22 Oct 2012 12:18:56 +0300 Subject: usb-storage: add unusual_devs entry for Casio EX-N1 digital camera This commit sets removable subclass for Casio EX-N1 digital camera. The patch has been tested within an ALT Linux kernel: http://git.altlinux.org/people/led/packages/?p=kernel-image-3.0.git;a=commitdiff;h=c0fd891836e89fe0c93a4d536a59216d90e4e3e7 See also https://bugzilla.kernel.org/show_bug.cgi?id=49221 Signed-off-by: Oleksandr Chumachenko Signed-off-by: Michael Shigorin Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 779cd954abcb..d305a5aa3a5d 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1004,6 +1004,12 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999, USB_SC_8070, USB_PR_CB, NULL, US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ), +/* Submitted by Oleksandr Chumachenko */ +UNUSUAL_DEV( 0x07cf, 0x1167, 0x0100, 0x0100, + "Casio", + "EX-N1 DigitalCamera", + USB_SC_8070, USB_PR_DEVICE, NULL, 0), + /* Submitted by Hartmut Wahl */ UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001, "Samsung", -- cgit v1.2.3-55-g7522 From e297da6e0e39b81d1abd156c5b60321b2097fb1b Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Wed, 24 Oct 2012 13:43:47 +0300 Subject: staging: ipack: add missing include (implicit declaration of function 'kfree') On ARCH=alpha make allmodconfig: linux-2.6/drivers/staging/ipack/bridges/tpci200.c: In function 'tpci200_free_irq': linux-2.6/drivers/staging/ipack/bridges/tpci200.c:188:2: error: implicit declaration of function 'kfree' [-Werror=implicit-function-declaration] linux-2.6/drivers/staging/ipack/bridges/tpci200.c: In function 'tpci200_request_irq': linux-2.6/drivers/staging/ipack/bridges/tpci200.c:215:2: error: implicit declaration of function 'kzalloc' [-Werror=implicit-function-declaration] Fixed by adding header CC: Greg Kroah-Hartman CC: Samuel Iglesias Gonsalvez CC: Jens Taprogge CC: "Miguel Gómez" CC: devel@driverdev.osuosl.org Signed-off-by: Sergei Trofimovich Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ipack/bridges/tpci200.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index bb8aa70281cd..46d6657280b8 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -12,6 +12,7 @@ */ #include +#include #include "tpci200.h" static u16 tpci200_status_timeout[] = { -- cgit v1.2.3-55-g7522 From 1392550240aaa72ce3a094a38bd23525cd67ce60 Mon Sep 17 00:00:00 2001 From: K. Y. Srinivasan Date: Fri, 12 Oct 2012 13:22:42 -0700 Subject: Drivers: hv: Cleanup error handling in vmbus_open() Fix a memory leak in the error handling path in the function vmbus_open(). Signed-off-by: K. Y. Srinivasan Reviewed-by: Haiyang Zhang Reported-by: Jason Wang Cc: Stable Acked-by: Jason Wang Signed-off-by: Greg Kroah-Hartman --- drivers/hv/channel.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 406537420fff..f4c3d28cd1fc 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -146,14 +146,14 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, if (ret != 0) { err = ret; - goto errorout; + goto error0; } ret = hv_ringbuffer_init( &newchannel->inbound, in, recv_ringbuffer_size); if (ret != 0) { err = ret; - goto errorout; + goto error0; } @@ -168,7 +168,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, if (ret != 0) { err = ret; - goto errorout; + goto error0; } /* Create and init the channel open message */ @@ -177,7 +177,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, GFP_KERNEL); if (!open_info) { err = -ENOMEM; - goto errorout; + goto error0; } init_completion(&open_info->waitevent); @@ -193,7 +193,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, if (userdatalen > MAX_USER_DEFINED_BYTES) { err = -EINVAL; - goto errorout; + goto error0; } if (userdatalen) @@ -208,19 +208,18 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, sizeof(struct vmbus_channel_open_channel)); if (ret != 0) - goto cleanup; + goto error1; t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ); if (t == 0) { err = -ETIMEDOUT; - goto errorout; + goto error1; } if (open_info->response.open_result.status) err = open_info->response.open_result.status; -cleanup: spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); list_del(&open_info->msglistentry); spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); @@ -228,9 +227,12 @@ cleanup: kfree(open_info); return err; -errorout: - hv_ringbuffer_cleanup(&newchannel->outbound); - hv_ringbuffer_cleanup(&newchannel->inbound); +error1: + spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); + list_del(&open_info->msglistentry); + spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); + +error0: free_pages((unsigned long)out, get_order(send_ringbuffer_size + recv_ringbuffer_size)); kfree(open_info); -- cgit v1.2.3-55-g7522 From b8cac0bbed33065ac42b3791efefec5dc233f7c1 Mon Sep 17 00:00:00 2001 From: Omar Ramirez Luna Date: Wed, 24 Oct 2012 17:09:15 -0500 Subject: staging: tidspbridge: request the right irq for mmu Requested irq for mmu is currently conflicting with a DMA irq due to recent changes to irq header files, now the offset for the start of the interrupt controller numbering has changed. This should be removed during a future migration to omap-iommu, for now it is hardcoded. Signed-off-by: Omar Ramirez Luna Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/include/dspbridge/host_os.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/tidspbridge/include/dspbridge/host_os.h b/drivers/staging/tidspbridge/include/dspbridge/host_os.h index ed00d3da3205..5e2f4d82d925 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/host_os.h +++ b/drivers/staging/tidspbridge/include/dspbridge/host_os.h @@ -47,8 +47,8 @@ #include #include -/* TODO -- Remove, once BP defines them */ -#define INT_DSP_MMU_IRQ 28 +/* TODO -- Remove, once omap-iommu is used */ +#define INT_DSP_MMU_IRQ (28 + NR_IRQS) #define PRCM_VDD1 1 -- cgit v1.2.3-55-g7522 From 53e3e3f19f3a0c4c38e28eb4af7acfee325db375 Mon Sep 17 00:00:00 2001 From: Omar Ramirez Luna Date: Wed, 24 Oct 2012 17:09:16 -0500 Subject: staging: tidspbridge: drop const from custom mmu implementation Custom mmu functions receive a 'const void __iomem *', all the callers pass a 'void __iomem *', so drop the const to fix the warnings like: warning: passing argument 2 of '__raw_writel' discards qualifiers from pointer target type ../io.h:88: note: expected 'volatile void *' but argument is of type 'const void *' Signed-off-by: Omar Ramirez Luna Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/hw/hw_mmu.c | 40 ++++++++++++++++----------------- drivers/staging/tidspbridge/hw/hw_mmu.h | 28 +++++++++++------------ 2 files changed, 34 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/tidspbridge/hw/hw_mmu.c b/drivers/staging/tidspbridge/hw/hw_mmu.c index 71cb82293649..a1594504ad58 100644 --- a/drivers/staging/tidspbridge/hw/hw_mmu.c +++ b/drivers/staging/tidspbridge/hw/hw_mmu.c @@ -78,7 +78,7 @@ static hw_status mmu_flush_entry(const void __iomem *base_address); * INPUTS: * * Identifier : base_address - * TypE : const u32 + * Type : void __iomem * * Description : Base Address of instance of MMU module * * Identifier : page_sz @@ -112,7 +112,7 @@ static hw_status mmu_flush_entry(const void __iomem *base_address); * * METHOD: : Check the Input parameters and set the CAM entry. */ -static hw_status mmu_set_cam_entry(const void __iomem *base_address, +static hw_status mmu_set_cam_entry(void __iomem *base_address, const u32 page_sz, const u32 preserved_bit, const u32 valid_bit, @@ -124,7 +124,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address, * INPUTS: * * Identifier : base_address - * Type : const u32 + * Type : void __iomem * * Description : Base Address of instance of MMU module * * Identifier : physical_addr @@ -157,7 +157,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address, * * METHOD: : Check the Input parameters and set the RAM entry. */ -static hw_status mmu_set_ram_entry(const void __iomem *base_address, +static hw_status mmu_set_ram_entry(void __iomem *base_address, const u32 physical_addr, enum hw_endianism_t endianism, enum hw_element_size_t element_size, @@ -165,7 +165,7 @@ static hw_status mmu_set_ram_entry(const void __iomem *base_address, /* HW FUNCTIONS */ -hw_status hw_mmu_enable(const void __iomem *base_address) +hw_status hw_mmu_enable(void __iomem *base_address) { hw_status status = 0; @@ -174,7 +174,7 @@ hw_status hw_mmu_enable(const void __iomem *base_address) return status; } -hw_status hw_mmu_disable(const void __iomem *base_address) +hw_status hw_mmu_disable(void __iomem *base_address) { hw_status status = 0; @@ -183,7 +183,7 @@ hw_status hw_mmu_disable(const void __iomem *base_address) return status; } -hw_status hw_mmu_num_locked_set(const void __iomem *base_address, +hw_status hw_mmu_num_locked_set(void __iomem *base_address, u32 num_locked_entries) { hw_status status = 0; @@ -193,7 +193,7 @@ hw_status hw_mmu_num_locked_set(const void __iomem *base_address, return status; } -hw_status hw_mmu_victim_num_set(const void __iomem *base_address, +hw_status hw_mmu_victim_num_set(void __iomem *base_address, u32 victim_entry_num) { hw_status status = 0; @@ -203,7 +203,7 @@ hw_status hw_mmu_victim_num_set(const void __iomem *base_address, return status; } -hw_status hw_mmu_event_ack(const void __iomem *base_address, u32 irq_mask) +hw_status hw_mmu_event_ack(void __iomem *base_address, u32 irq_mask) { hw_status status = 0; @@ -212,7 +212,7 @@ hw_status hw_mmu_event_ack(const void __iomem *base_address, u32 irq_mask) return status; } -hw_status hw_mmu_event_disable(const void __iomem *base_address, u32 irq_mask) +hw_status hw_mmu_event_disable(void __iomem *base_address, u32 irq_mask) { hw_status status = 0; u32 irq_reg; @@ -224,7 +224,7 @@ hw_status hw_mmu_event_disable(const void __iomem *base_address, u32 irq_mask) return status; } -hw_status hw_mmu_event_enable(const void __iomem *base_address, u32 irq_mask) +hw_status hw_mmu_event_enable(void __iomem *base_address, u32 irq_mask) { hw_status status = 0; u32 irq_reg; @@ -236,7 +236,7 @@ hw_status hw_mmu_event_enable(const void __iomem *base_address, u32 irq_mask) return status; } -hw_status hw_mmu_event_status(const void __iomem *base_address, u32 *irq_mask) +hw_status hw_mmu_event_status(void __iomem *base_address, u32 *irq_mask) { hw_status status = 0; @@ -245,7 +245,7 @@ hw_status hw_mmu_event_status(const void __iomem *base_address, u32 *irq_mask) return status; } -hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, u32 *addr) +hw_status hw_mmu_fault_addr_read(void __iomem *base_address, u32 *addr) { hw_status status = 0; @@ -255,7 +255,7 @@ hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, u32 *addr) return status; } -hw_status hw_mmu_ttb_set(const void __iomem *base_address, u32 ttb_phys_addr) +hw_status hw_mmu_ttb_set(void __iomem *base_address, u32 ttb_phys_addr) { hw_status status = 0; u32 load_ttb; @@ -267,7 +267,7 @@ hw_status hw_mmu_ttb_set(const void __iomem *base_address, u32 ttb_phys_addr) return status; } -hw_status hw_mmu_twl_enable(const void __iomem *base_address) +hw_status hw_mmu_twl_enable(void __iomem *base_address) { hw_status status = 0; @@ -276,7 +276,7 @@ hw_status hw_mmu_twl_enable(const void __iomem *base_address) return status; } -hw_status hw_mmu_twl_disable(const void __iomem *base_address) +hw_status hw_mmu_twl_disable(void __iomem *base_address) { hw_status status = 0; @@ -323,7 +323,7 @@ hw_status hw_mmu_tlb_flush(const void __iomem *base_address, u32 virtual_addr, return status; } -hw_status hw_mmu_tlb_add(const void __iomem *base_address, +hw_status hw_mmu_tlb_add(void __iomem *base_address, u32 physical_addr, u32 virtual_addr, u32 page_sz, @@ -516,7 +516,7 @@ static hw_status mmu_flush_entry(const void __iomem *base_address) } /* mmu_set_cam_entry */ -static hw_status mmu_set_cam_entry(const void __iomem *base_address, +static hw_status mmu_set_cam_entry(void __iomem *base_address, const u32 page_sz, const u32 preserved_bit, const u32 valid_bit, @@ -536,7 +536,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address, } /* mmu_set_ram_entry */ -static hw_status mmu_set_ram_entry(const void __iomem *base_address, +static hw_status mmu_set_ram_entry(void __iomem *base_address, const u32 physical_addr, enum hw_endianism_t endianism, enum hw_element_size_t element_size, @@ -556,7 +556,7 @@ static hw_status mmu_set_ram_entry(const void __iomem *base_address, } -void hw_mmu_tlb_flush_all(const void __iomem *base) +void hw_mmu_tlb_flush_all(void __iomem *base) { __raw_writel(1, base + MMU_GFLUSH); } diff --git a/drivers/staging/tidspbridge/hw/hw_mmu.h b/drivers/staging/tidspbridge/hw/hw_mmu.h index 1458a2c6027b..1cdd0827beba 100644 --- a/drivers/staging/tidspbridge/hw/hw_mmu.h +++ b/drivers/staging/tidspbridge/hw/hw_mmu.h @@ -42,44 +42,44 @@ struct hw_mmu_map_attrs_t { bool donotlockmpupage; }; -extern hw_status hw_mmu_enable(const void __iomem *base_address); +extern hw_status hw_mmu_enable(void __iomem *base_address); -extern hw_status hw_mmu_disable(const void __iomem *base_address); +extern hw_status hw_mmu_disable(void __iomem *base_address); -extern hw_status hw_mmu_num_locked_set(const void __iomem *base_address, +extern hw_status hw_mmu_num_locked_set(void __iomem *base_address, u32 num_locked_entries); -extern hw_status hw_mmu_victim_num_set(const void __iomem *base_address, +extern hw_status hw_mmu_victim_num_set(void __iomem *base_address, u32 victim_entry_num); /* For MMU faults */ -extern hw_status hw_mmu_event_ack(const void __iomem *base_address, +extern hw_status hw_mmu_event_ack(void __iomem *base_address, u32 irq_mask); -extern hw_status hw_mmu_event_disable(const void __iomem *base_address, +extern hw_status hw_mmu_event_disable(void __iomem *base_address, u32 irq_mask); -extern hw_status hw_mmu_event_enable(const void __iomem *base_address, +extern hw_status hw_mmu_event_enable(void __iomem *base_address, u32 irq_mask); -extern hw_status hw_mmu_event_status(const void __iomem *base_address, +extern hw_status hw_mmu_event_status(void __iomem *base_address, u32 *irq_mask); -extern hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, +extern hw_status hw_mmu_fault_addr_read(void __iomem *base_address, u32 *addr); /* Set the TT base address */ -extern hw_status hw_mmu_ttb_set(const void __iomem *base_address, +extern hw_status hw_mmu_ttb_set(void __iomem *base_address, u32 ttb_phys_addr); -extern hw_status hw_mmu_twl_enable(const void __iomem *base_address); +extern hw_status hw_mmu_twl_enable(void __iomem *base_address); -extern hw_status hw_mmu_twl_disable(const void __iomem *base_address); +extern hw_status hw_mmu_twl_disable(void __iomem *base_address); extern hw_status hw_mmu_tlb_flush(const void __iomem *base_address, u32 virtual_addr, u32 page_sz); -extern hw_status hw_mmu_tlb_add(const void __iomem *base_address, +extern hw_status hw_mmu_tlb_add(void __iomem *base_address, u32 physical_addr, u32 virtual_addr, u32 page_sz, @@ -97,7 +97,7 @@ extern hw_status hw_mmu_pte_set(const u32 pg_tbl_va, extern hw_status hw_mmu_pte_clear(const u32 pg_tbl_va, u32 virtual_addr, u32 page_size); -void hw_mmu_tlb_flush_all(const void __iomem *base); +void hw_mmu_tlb_flush_all(void __iomem *base); static inline u32 hw_mmu_pte_addr_l1(u32 l1_base, u32 va) { -- cgit v1.2.3-55-g7522 From 3c8676967bce1c9b8723129625a2125b7704674f Mon Sep 17 00:00:00 2001 From: Omar Ramirez Luna Date: Wed, 24 Oct 2012 17:09:17 -0500 Subject: staging: tidspbridge: change type to __iomem for per and core addresses Currently per_pm_base and core_pm_base are declared as u32, however _raw_* changed the data type, since: 195bbca ARM: 7500/1: io: avoid writeback addressing modes for __raw_ accessors This should fix warnings for per and core accesses: warning: passing argument 2 of '__raw_writel' makes pointer from integer without a cast ../io.h:88: note: expected 'volatile void *' but argument is of type 'u32' Signed-off-by: Omar Ramirez Luna Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h | 4 ++-- drivers/staging/tidspbridge/rmgr/drv.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h b/drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h index 60a278136bdf..b32c75673ab4 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h +++ b/drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h @@ -53,8 +53,8 @@ struct cfg_hostres { u32 chnl_buf_size; u32 num_chnls; void __iomem *per_base; - u32 per_pm_base; - u32 core_pm_base; + void __iomem *per_pm_base; + void __iomem *core_pm_base; void __iomem *dmmu_base; }; diff --git a/drivers/staging/tidspbridge/rmgr/drv.c b/drivers/staging/tidspbridge/rmgr/drv.c index 6795205b0155..db1da28cecba 100644 --- a/drivers/staging/tidspbridge/rmgr/drv.c +++ b/drivers/staging/tidspbridge/rmgr/drv.c @@ -667,10 +667,10 @@ int drv_request_bridge_res_dsp(void **phost_resources) OMAP_DSP_MEM3_SIZE); host_res->per_base = ioremap(OMAP_PER_CM_BASE, OMAP_PER_CM_SIZE); - host_res->per_pm_base = (u32) ioremap(OMAP_PER_PRM_BASE, - OMAP_PER_PRM_SIZE); - host_res->core_pm_base = (u32) ioremap(OMAP_CORE_PRM_BASE, - OMAP_CORE_PRM_SIZE); + host_res->per_pm_base = ioremap(OMAP_PER_PRM_BASE, + OMAP_PER_PRM_SIZE); + host_res->core_pm_base = ioremap(OMAP_CORE_PRM_BASE, + OMAP_CORE_PRM_SIZE); host_res->dmmu_base = ioremap(OMAP_DMMU_BASE, OMAP_DMMU_SIZE); -- cgit v1.2.3-55-g7522 From 7de8a0cf48a023058642c69145630d51709aa174 Mon Sep 17 00:00:00 2001 From: Omar Ramirez Luna Date: Wed, 24 Oct 2012 17:09:18 -0500 Subject: staging: tidspbridge: ioremap dsp sync addr Change the type of sync_addr to 'void __iomem *' and ioremap the physical address in the shared memory so we can access it using _raw_*. While at it, drop 'dw_' prefix. Fix the warning associated with dsp's sync_addr: warning: passing argument 2 of '__raw_writel' makes pointer from integer without a cast ../io.h:88: note: expected 'volatile void *' but argument is of type 'u32' Signed-off-by: Omar Ramirez Luna Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/core/tiomap3430.c | 37 +++++++++++++++++++-------- 1 file changed, 26 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/tidspbridge/core/tiomap3430.c b/drivers/staging/tidspbridge/core/tiomap3430.c index 066a3ceec65e..f619fb3c56d2 100644 --- a/drivers/staging/tidspbridge/core/tiomap3430.c +++ b/drivers/staging/tidspbridge/core/tiomap3430.c @@ -126,7 +126,8 @@ static int mem_map_vmalloc(struct bridge_dev_context *dev_context, u32 ul_num_bytes, struct hw_mmu_map_attrs_t *hw_attrs); -bool wait_for_start(struct bridge_dev_context *dev_context, u32 dw_sync_addr); +bool wait_for_start(struct bridge_dev_context *dev_context, + void __iomem *sync_addr); /* ----------------------------------- Globals */ @@ -363,10 +364,11 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt, { int status = 0; struct bridge_dev_context *dev_context = dev_ctxt; - u32 dw_sync_addr = 0; + void __iomem *sync_addr; u32 ul_shm_base; /* Gpp Phys SM base addr(byte) */ u32 ul_shm_base_virt; /* Dsp Virt SM base addr */ u32 ul_tlb_base_virt; /* Base of MMU TLB entry */ + u32 shm_sync_pa; /* Offset of shm_base_virt from tlb_base_virt */ u32 ul_shm_offset_virt; s32 entry_ndx; @@ -397,15 +399,22 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt, /* Kernel logical address */ ul_shm_base = dev_context->atlb_entry[0].gpp_va + ul_shm_offset_virt; + /* SHM physical sync address */ + shm_sync_pa = dev_context->atlb_entry[0].gpp_pa + ul_shm_offset_virt + + SHMSYNCOFFSET; + /* 2nd wd is used as sync field */ - dw_sync_addr = ul_shm_base + SHMSYNCOFFSET; + sync_addr = ioremap(shm_sync_pa, SZ_32); + if (!sync_addr) + return -ENOMEM; + /* Write a signature into the shm base + offset; this will * get cleared when the DSP program starts. */ if ((ul_shm_base_virt == 0) || (ul_shm_base == 0)) { pr_err("%s: Illegal SM base\n", __func__); status = -EPERM; } else - __raw_writel(0xffffffff, dw_sync_addr); + __raw_writel(0xffffffff, sync_addr); if (!status) { resources = dev_context->resources; @@ -419,8 +428,10 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt, * function is made available. */ void __iomem *ctrl = ioremap(0x48002000, SZ_4K); - if (!ctrl) + if (!ctrl) { + iounmap(sync_addr); return -ENOMEM; + } (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK, OMAP3430_RST1_IVA2_MASK, OMAP3430_IVA2_MOD, @@ -588,15 +599,15 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt, (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK, 0, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL); - dev_dbg(bridge, "Waiting for Sync @ 0x%x\n", dw_sync_addr); + dev_dbg(bridge, "Waiting for Sync @ 0x%x\n", *(u32 *)sync_addr); dev_dbg(bridge, "DSP c_int00 Address = 0x%x\n", dsp_addr); if (dsp_debug) - while (__raw_readw(dw_sync_addr)) + while (__raw_readw(sync_addr)) ; /* Wait for DSP to clear word in shared memory */ /* Read the Location */ - if (!wait_for_start(dev_context, dw_sync_addr)) + if (!wait_for_start(dev_context, sync_addr)) status = -ETIMEDOUT; dev_get_symbol(dev_context->dev_obj, "_WDT_enable", &wdt_en); @@ -612,7 +623,7 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt, /* Write the synchronization bit to indicate the * completion of OPP table update to DSP */ - __raw_writel(0XCAFECAFE, dw_sync_addr); + __raw_writel(0XCAFECAFE, sync_addr); /* update board state */ dev_context->brd_state = BRD_RUNNING; @@ -621,6 +632,9 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt, dev_context->brd_state = BRD_UNKNOWN; } } + + iounmap(sync_addr); + return status; } @@ -1796,12 +1810,13 @@ static int mem_map_vmalloc(struct bridge_dev_context *dev_context, * ======== wait_for_start ======== * Wait for the singal from DSP that it has started, or time out. */ -bool wait_for_start(struct bridge_dev_context *dev_context, u32 dw_sync_addr) +bool wait_for_start(struct bridge_dev_context *dev_context, + void __iomem *sync_addr) { u16 timeout = TIHELEN_ACKTIMEOUT; /* Wait for response from board */ - while (__raw_readw(dw_sync_addr) && --timeout) + while (__raw_readw(sync_addr) && --timeout) udelay(10); /* If timed out: return false */ -- cgit v1.2.3-55-g7522 From 5ae4fd94a3b2d2b285cff294a5a23c52e21db208 Mon Sep 17 00:00:00 2001 From: Omar Ramirez Luna Date: Wed, 24 Oct 2012 17:09:19 -0500 Subject: staging: tidspbridge: ioremap physical address of the stack segment in shm Due to data type change, readl can no longer receive a u32. Signed-off-by: Omar Ramirez Luna Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/rmgr/node.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/tidspbridge/rmgr/node.c b/drivers/staging/tidspbridge/rmgr/node.c index c2fc6137c770..294e9b40f516 100644 --- a/drivers/staging/tidspbridge/rmgr/node.c +++ b/drivers/staging/tidspbridge/rmgr/node.c @@ -304,8 +304,7 @@ int node_allocate(struct proc_object *hprocessor, u32 pul_value; u32 dynext_base; u32 off_set = 0; - u32 ul_stack_seg_addr, ul_stack_seg_val; - u32 ul_gpp_mem_base; + u32 ul_stack_seg_val; struct cfg_hostres *host_res; struct bridge_dev_context *pbridge_context; u32 mapped_addr = 0; @@ -581,6 +580,9 @@ func_cont: if (strcmp((char *) pnode->dcd_props.obj_data.node_obj.ndb_props. stack_seg_name, STACKSEGLABEL) == 0) { + void __iomem *stack_seg; + u32 stack_seg_pa; + status = hnode_mgr->nldr_fxns. get_fxn_addr(pnode->nldr_node_obj, "DYNEXT_BEG", @@ -608,14 +610,21 @@ func_cont: goto func_end; } - ul_gpp_mem_base = (u32) host_res->mem_base[1]; off_set = pul_value - dynext_base; - ul_stack_seg_addr = ul_gpp_mem_base + off_set; - ul_stack_seg_val = readl(ul_stack_seg_addr); + stack_seg_pa = host_res->mem_phys[1] + off_set; + stack_seg = ioremap(stack_seg_pa, SZ_32); + if (!stack_seg) { + status = -ENOMEM; + goto func_end; + } + + ul_stack_seg_val = readl(stack_seg); + + iounmap(stack_seg); dev_dbg(bridge, "%s: StackSegVal = 0x%x, StackSegAddr =" " 0x%x\n", __func__, ul_stack_seg_val, - ul_stack_seg_addr); + host_res->mem_base[1] + off_set); pnode->create_args.asa.task_arg_obj.stack_seg = ul_stack_seg_val; -- cgit v1.2.3-55-g7522 From 4d3f120ae7473b96f114b187856e89e08571fc83 Mon Sep 17 00:00:00 2001 From: Omar Ramirez Luna Date: Wed, 24 Oct 2012 17:09:20 -0500 Subject: staging: tidspbridge: delete unused mmu functions This should get rid of warnings of the type: warning: passing argument 1 of '' discards qualifiers from pointer target type note: expected 'void *' but argument is of type 'const void *' Signed-off-by: Omar Ramirez Luna Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/hw/hw_mmu.c | 75 --------------------------------- drivers/staging/tidspbridge/hw/hw_mmu.h | 3 -- 2 files changed, 78 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/tidspbridge/hw/hw_mmu.c b/drivers/staging/tidspbridge/hw/hw_mmu.c index a1594504ad58..50244a474178 100644 --- a/drivers/staging/tidspbridge/hw/hw_mmu.c +++ b/drivers/staging/tidspbridge/hw/hw_mmu.c @@ -47,31 +47,6 @@ enum hw_mmu_page_size_t { HW_MMU_SUPERSECTION }; -/* - * FUNCTION : mmu_flush_entry - * - * INPUTS: - * - * Identifier : base_address - * Type : const u32 - * Description : Base Address of instance of MMU module - * - * RETURNS: - * - * Type : hw_status - * Description : 0 -- No errors occurred - * RET_BAD_NULL_PARAM -- A Pointer - * Parameter was set to NULL - * - * PURPOSE: : Flush the TLB entry pointed by the - * lock counter register - * even if this entry is set protected - * - * METHOD: : Check the Input parameter and Flush a - * single entry in the TLB. - */ -static hw_status mmu_flush_entry(const void __iomem *base_address); - /* * FUNCTION : mmu_set_cam_entry * @@ -285,44 +260,6 @@ hw_status hw_mmu_twl_disable(void __iomem *base_address) return status; } -hw_status hw_mmu_tlb_flush(const void __iomem *base_address, u32 virtual_addr, - u32 page_sz) -{ - hw_status status = 0; - u32 virtual_addr_tag; - enum hw_mmu_page_size_t pg_size_bits; - - switch (page_sz) { - case HW_PAGE_SIZE4KB: - pg_size_bits = HW_MMU_SMALL_PAGE; - break; - - case HW_PAGE_SIZE64KB: - pg_size_bits = HW_MMU_LARGE_PAGE; - break; - - case HW_PAGE_SIZE1MB: - pg_size_bits = HW_MMU_SECTION; - break; - - case HW_PAGE_SIZE16MB: - pg_size_bits = HW_MMU_SUPERSECTION; - break; - - default: - return -EINVAL; - } - - /* Generate the 20-bit tag from virtual address */ - virtual_addr_tag = ((virtual_addr & MMU_ADDR_MASK) >> 12); - - mmu_set_cam_entry(base_address, pg_size_bits, 0, 0, virtual_addr_tag); - - mmu_flush_entry(base_address); - - return status; -} - hw_status hw_mmu_tlb_add(void __iomem *base_address, u32 physical_addr, u32 virtual_addr, @@ -503,18 +440,6 @@ hw_status hw_mmu_pte_clear(const u32 pg_tbl_va, u32 virtual_addr, u32 page_size) return status; } -/* mmu_flush_entry */ -static hw_status mmu_flush_entry(const void __iomem *base_address) -{ - hw_status status = 0; - u32 flush_entry_data = 0x1; - - /* write values to register */ - MMUMMU_FLUSH_ENTRY_WRITE_REGISTER32(base_address, flush_entry_data); - - return status; -} - /* mmu_set_cam_entry */ static hw_status mmu_set_cam_entry(void __iomem *base_address, const u32 page_sz, diff --git a/drivers/staging/tidspbridge/hw/hw_mmu.h b/drivers/staging/tidspbridge/hw/hw_mmu.h index 1cdd0827beba..1c50bb36edfe 100644 --- a/drivers/staging/tidspbridge/hw/hw_mmu.h +++ b/drivers/staging/tidspbridge/hw/hw_mmu.h @@ -76,9 +76,6 @@ extern hw_status hw_mmu_twl_enable(void __iomem *base_address); extern hw_status hw_mmu_twl_disable(void __iomem *base_address); -extern hw_status hw_mmu_tlb_flush(const void __iomem *base_address, - u32 virtual_addr, u32 page_sz); - extern hw_status hw_mmu_tlb_add(void __iomem *base_address, u32 physical_addr, u32 virtual_addr, -- cgit v1.2.3-55-g7522 From a2fc66ce9f4669daeebc03d6891917b894c752a8 Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Tue, 23 Oct 2012 04:54:34 +0000 Subject: pch_gbe: fix error handling in pch_gbe_up() If we fail to allocate rx buffers pool by any reason, we'll just return with an error, however we've previously successfully requested an irq. Fix this by releasing the irq before returning the error. Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller --- drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index a8854d04c275..4c4fe5b1a29a 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -1930,12 +1930,12 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) struct net_device *netdev = adapter->netdev; struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring; struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring; - int err; + int err = -EINVAL; /* Ensure we have a valid MAC */ if (!is_valid_ether_addr(adapter->hw.mac.addr)) { pr_err("Error: Invalid MAC address\n"); - return -EINVAL; + goto out; } /* hardware has been reset, we need to reload some things */ @@ -1948,13 +1948,13 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) err = pch_gbe_request_irq(adapter); if (err) { - pr_err("Error: can't bring device up\n"); - return err; + pr_err("Error: can't bring device up - irq request failed\n"); + goto out; } err = pch_gbe_alloc_rx_buffers_pool(adapter, rx_ring, rx_ring->count); if (err) { - pr_err("Error: can't bring device up\n"); - return err; + pr_err("Error: can't bring device up - alloc rx buffers pool failed\n"); + goto freeirq; } pch_gbe_alloc_tx_buffers(adapter, tx_ring); pch_gbe_alloc_rx_buffers(adapter, rx_ring, rx_ring->count); @@ -1969,6 +1969,11 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) netif_start_queue(adapter->netdev); return 0; + +freeirq: + pch_gbe_free_irq(adapter); +out: + return err; } /** -- cgit v1.2.3-55-g7522 From b2b3392cfc0f5af0f621b3d95aba459f2d5c0e28 Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Tue, 23 Oct 2012 12:11:55 +0000 Subject: NET_VENDOR_TI: make available for am33xx as well The cpsw/davinci mdio ip cores are present on am33xx, so make NET_VENDOR_TI visible for it as well. Signed-off-by: Peter Korsgaard Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig index b26cbda5efa9..2c41894d5472 100644 --- a/drivers/net/ethernet/ti/Kconfig +++ b/drivers/net/ethernet/ti/Kconfig @@ -5,7 +5,7 @@ config NET_VENDOR_TI bool "Texas Instruments (TI) devices" default y - depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3)) + depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3 || SOC_AM33XX)) ---help--- If you have a network (Ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available from -- cgit v1.2.3-55-g7522 From 2b9c128e9580e79db48bd3aacb2b4873544e01e8 Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Wed, 24 Oct 2012 05:21:36 +0000 Subject: gianfar_ptp: use iomem, not ioports resource tree in probe When using a 36 bit dtb file, the driver complains "resource busy". Investigating the source of the message leads one to the gianfar_ptp_probe function. Since the type of the device resource requested in this function is IORESOURCE_MEM, it should use "iomem_resource" instead of "ioports_resource". Signed-off-by: Wei Yang Cc: Claudiu Manoil Cc: Timur Tabi Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/gianfar_ptp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/gianfar_ptp.c b/drivers/net/ethernet/freescale/gianfar_ptp.c index b9db0e040563..2e5daee0438a 100644 --- a/drivers/net/ethernet/freescale/gianfar_ptp.c +++ b/drivers/net/ethernet/freescale/gianfar_ptp.c @@ -478,7 +478,7 @@ static int gianfar_ptp_probe(struct platform_device *dev) pr_err("no resource\n"); goto no_resource; } - if (request_resource(&ioport_resource, etsects->rsrc)) { + if (request_resource(&iomem_resource, etsects->rsrc)) { pr_err("resource busy\n"); goto no_resource; } -- cgit v1.2.3-55-g7522 From 910a578f7e9400a78a3b13aba0b4d2df16a2cb05 Mon Sep 17 00:00:00 2001 From: Michael S. Tsirkin Date: Wed, 24 Oct 2012 20:37:51 +0200 Subject: vhost: fix mergeable bufs on BE hosts We copy head count to a 16 bit field, this works by chance on LE but on BE guest gets 0. Fix it up. Signed-off-by: Michael S. Tsirkin Tested-by: Alexander Graf Cc: stable@vger.kernel.org Signed-off-by: David S. Miller --- drivers/vhost/net.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 072cbbadbc36..7f93f34b7f91 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -379,7 +379,8 @@ static void handle_rx(struct vhost_net *net) .hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE }; size_t total_len = 0; - int err, headcount, mergeable; + int err, mergeable; + s16 headcount; size_t vhost_hlen, sock_hlen; size_t vhost_len, sock_len; /* TODO: check that we are running from vhost_worker? */ -- cgit v1.2.3-55-g7522 From ae495e844a77344fdaedbb2ad97d925d096e9f0d Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Thu, 25 Oct 2012 00:38:01 -0700 Subject: Input: egalax_ts - get gpio from devicetree The irq_to_gpio() is old, most platforms use GENERIC_GPIO framework and don't support this API anymore. The i.MX6q sabrelite platform equips an egalax touchscreen controller, and this platform already transfered to GENERIC_GPIO framework, to support this driver, we use a more generic way to get gpio. Add a return value checking for waking up the controller in the probe function, this guarantee only a workable device can pass init. [dmitry.torokhov@gmail.com: Make driver depend on CONFIG_OF as it is now required.] Acked-by Zhang Jiejing Reviewed-by: Shawn Guo Signed-off-by: Hui Wang Signed-off-by: Dmitry Torokhov --- .../bindings/input/touchscreen/egalax-ts.txt | 19 ++++++++++++++++++ drivers/input/touchscreen/Kconfig | 2 +- drivers/input/touchscreen/egalax_ts.c | 23 ++++++++++++++++++++-- 3 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt new file mode 100644 index 000000000000..df70318a617f --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt @@ -0,0 +1,19 @@ +* EETI eGalax Multiple Touch Controller + +Required properties: +- compatible: must be "eeti,egalax_ts" +- reg: i2c slave address +- interrupt-parent: the phandle for the interrupt controller +- interrupts: touch controller interrupt +- wakeup-gpios: the gpio pin to be used for waking up the controller + as well as uased as irq pin + +Example: + + egalax_ts@04 { + compatible = "eeti,egalax_ts"; + reg = <0x04>; + interrupt-parent = <&gpio1>; + interrupts = <9 2>; + wakeup-gpios = <&gpio1 9 0>; + }; diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 1ba232cbc09d..f7668b24c378 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -239,7 +239,7 @@ config TOUCHSCREEN_EETI config TOUCHSCREEN_EGALAX tristate "EETI eGalax multi-touch panel support" - depends on I2C + depends on I2C && OF help Say Y here to enable support for I2C connected EETI eGalax multi-touch panels. diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c index c1e3460f1195..13fa62fdfb0b 100644 --- a/drivers/input/touchscreen/egalax_ts.c +++ b/drivers/input/touchscreen/egalax_ts.c @@ -28,6 +28,7 @@ #include #include #include +#include /* * Mouse Mode: some panel may configure the controller to mouse mode, @@ -122,9 +123,17 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id) /* wake up controller by an falling edge of interrupt gpio. */ static int egalax_wake_up_device(struct i2c_client *client) { - int gpio = irq_to_gpio(client->irq); + struct device_node *np = client->dev.of_node; + int gpio; int ret; + if (!np) + return -ENODEV; + + gpio = of_get_named_gpio(np, "wakeup-gpios", 0); + if (!gpio_is_valid(gpio)) + return -ENODEV; + ret = gpio_request(gpio, "egalax_irq"); if (ret < 0) { dev_err(&client->dev, @@ -181,7 +190,11 @@ static int __devinit egalax_ts_probe(struct i2c_client *client, ts->input_dev = input_dev; /* controller may be in sleep, wake it up. */ - egalax_wake_up_device(client); + error = egalax_wake_up_device(client); + if (error) { + dev_err(&client->dev, "Failed to wake up the controller\n"); + goto err_free_dev; + } ret = egalax_firmware_version(client); if (ret < 0) { @@ -274,11 +287,17 @@ static int egalax_ts_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(egalax_ts_pm_ops, egalax_ts_suspend, egalax_ts_resume); +static struct of_device_id egalax_ts_dt_ids[] = { + { .compatible = "eeti,egalax_ts" }, + { /* sentinel */ } +}; + static struct i2c_driver egalax_ts_driver = { .driver = { .name = "egalax_ts", .owner = THIS_MODULE, .pm = &egalax_ts_pm_ops, + .of_match_table = of_match_ptr(egalax_ts_dt_ids), }, .id_table = egalax_ts_id, .probe = egalax_ts_probe, -- cgit v1.2.3-55-g7522 From 88fd449e734a4264347e12b8ff74ccb33a9b9a35 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 24 Oct 2012 23:53:02 -0700 Subject: Input: wacom - add INPUT_PROP_DIRECT flag to Cintiq 24HD Signed-off-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index c3468c8dbd89..c30d4c937952 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1449,6 +1449,9 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0); + + __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); + wacom_setup_cintiq(wacom_wac); break; -- cgit v1.2.3-55-g7522 From 50dde8686eec41bf3d7cbec7a6f76c073ab01903 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:28:59 +0200 Subject: USB: metro-usb: fix port-data memory leak Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that the call to metrousb_clean (close) in shutdown was redundant. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/metro-usb.c | 50 +++++++++++------------------------------- 1 file changed, 13 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 0b257ddffbdb..25cb97c25ad4 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -271,51 +271,27 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr return retval; } -static void metrousb_shutdown(struct usb_serial *serial) +static int metrousb_port_probe(struct usb_serial_port *port) { - int i = 0; + struct metrousb_private *metro_priv; - dev_dbg(&serial->dev->dev, "%s\n", __func__); + metro_priv = kzalloc(sizeof(*metro_priv), GFP_KERNEL); + if (!metro_priv) + return -ENOMEM; - /* Stop reading and writing on all ports. */ - for (i = 0; i < serial->num_ports; ++i) { - /* Close any open urbs. */ - metrousb_cleanup(serial->port[i]); + spin_lock_init(&metro_priv->lock); - /* Free memory. */ - kfree(usb_get_serial_port_data(serial->port[i])); - usb_set_serial_port_data(serial->port[i], NULL); + usb_set_serial_port_data(port, metro_priv); - dev_dbg(&serial->dev->dev, "%s - freed port number=%d\n", - __func__, serial->port[i]->number); - } + return 0; } -static int metrousb_startup(struct usb_serial *serial) +static int metrousb_port_remove(struct usb_serial_port *port) { struct metrousb_private *metro_priv; - struct usb_serial_port *port; - int i = 0; - - dev_dbg(&serial->dev->dev, "%s\n", __func__); - /* Loop through the serial ports setting up the private structures. - * Currently we only use one port. */ - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - - /* Declare memory. */ - metro_priv = kzalloc(sizeof(struct metrousb_private), GFP_KERNEL); - if (!metro_priv) - return -ENOMEM; - - /* Initialize memory. */ - spin_lock_init(&metro_priv->lock); - usb_set_serial_port_data(port, metro_priv); - - dev_dbg(&serial->dev->dev, "%s - port number=%d\n ", - __func__, port->number); - } + metro_priv = usb_get_serial_port_data(port); + kfree(metro_priv); return 0; } @@ -414,8 +390,8 @@ static struct usb_serial_driver metrousb_device = { .close = metrousb_cleanup, .read_int_callback = metrousb_read_int_callback, .write_int_callback = metrousb_write_int_callback, - .attach = metrousb_startup, - .release = metrousb_shutdown, + .port_probe = metrousb_port_probe, + .port_remove = metrousb_port_remove, .throttle = metrousb_throttle, .unthrottle = metrousb_unthrottle, .tiocmget = metrousb_tiocmget, -- cgit v1.2.3-55-g7522 From 2ee44fbeac92c36e53779a57ee84cfee1affe418 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:00 +0200 Subject: USB: metro-usb: fix io after disconnect Make sure no control urb is submitted during close after a disconnect by checking the disconnected flag. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/metro-usb.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 25cb97c25ad4..6f29c74eb769 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -179,16 +179,13 @@ static void metrousb_cleanup(struct usb_serial_port *port) { dev_dbg(&port->dev, "%s\n", __func__); - if (port->serial->dev) { - /* Shutdown any interrupt in urbs. */ - if (port->interrupt_in_urb) { - usb_unlink_urb(port->interrupt_in_urb); - usb_kill_urb(port->interrupt_in_urb); - } - - /* Send deactivate cmd to device */ + usb_unlink_urb(port->interrupt_in_urb); + usb_kill_urb(port->interrupt_in_urb); + + mutex_lock(&port->serial->disc_mutex); + if (!port->serial->disconnected) metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port); - } + mutex_unlock(&port->serial->disc_mutex); } static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) -- cgit v1.2.3-55-g7522 From c129197c99550d356cf5f69b046994dd53cd1b9d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:01 +0200 Subject: USB: whiteheat: fix memory leak in error path Make sure command buffer is deallocated in case of errors during attach. Cc: Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/whiteheat.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 346c7efc20b0..cfd155e2b6a2 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -333,6 +333,7 @@ no_firmware: "%s: please contact support@connecttech.com\n", serial->type->description); kfree(result); + kfree(command); return -ENODEV; no_command_private: -- cgit v1.2.3-55-g7522 From c467206ed6bcce26c83d0435612cc4fee2527305 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:02 +0200 Subject: USB: whiteheat: fix port-data memory leak Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that the fifth port (command port) is never registered as a port device and thus should be handled in attach and release. Compile-only tested. Cc: Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/whiteheat.c | 59 +++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index cfd155e2b6a2..b9fca3586d74 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -83,6 +83,8 @@ static int whiteheat_firmware_attach(struct usb_serial *serial); /* function prototypes for the Connect Tech WhiteHEAT serial converter */ static int whiteheat_attach(struct usb_serial *serial); static void whiteheat_release(struct usb_serial *serial); +static int whiteheat_port_probe(struct usb_serial_port *port); +static int whiteheat_port_remove(struct usb_serial_port *port); static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port); static void whiteheat_close(struct usb_serial_port *port); @@ -117,6 +119,8 @@ static struct usb_serial_driver whiteheat_device = { .num_ports = 4, .attach = whiteheat_attach, .release = whiteheat_release, + .port_probe = whiteheat_port_probe, + .port_remove = whiteheat_port_remove, .open = whiteheat_open, .close = whiteheat_close, .ioctl = whiteheat_ioctl, @@ -218,15 +222,12 @@ static int whiteheat_attach(struct usb_serial *serial) { struct usb_serial_port *command_port; struct whiteheat_command_private *command_info; - struct usb_serial_port *port; - struct whiteheat_private *info; struct whiteheat_hw_info *hw_info; int pipe; int ret; int alen; __u8 *command; __u8 *result; - int i; command_port = serial->port[COMMAND_PORT]; @@ -285,22 +286,6 @@ static int whiteheat_attach(struct usb_serial *serial) serial->type->description, hw_info->sw_major_rev, hw_info->sw_minor_rev); - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - - info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL); - if (info == NULL) { - dev_err(&port->dev, - "%s: Out of memory for port structures\n", - serial->type->description); - goto no_private; - } - - info->mcr = 0; - - usb_set_serial_port_data(port, info); - } - command_info = kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL); if (command_info == NULL) { @@ -337,13 +322,6 @@ no_firmware: return -ENODEV; no_command_private: - for (i = serial->num_ports - 1; i >= 0; i--) { - port = serial->port[i]; - info = usb_get_serial_port_data(port); - kfree(info); -no_private: - ; - } kfree(result); no_result_buffer: kfree(command); @@ -351,21 +329,36 @@ no_command_buffer: return -ENOMEM; } - static void whiteheat_release(struct usb_serial *serial) { struct usb_serial_port *command_port; - struct whiteheat_private *info; - int i; /* free up our private data for our command port */ command_port = serial->port[COMMAND_PORT]; kfree(usb_get_serial_port_data(command_port)); +} - for (i = 0; i < serial->num_ports; i++) { - info = usb_get_serial_port_data(serial->port[i]); - kfree(info); - } +static int whiteheat_port_probe(struct usb_serial_port *port) +{ + struct whiteheat_private *info; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + usb_set_serial_port_data(port, info); + + return 0; +} + +static int whiteheat_port_remove(struct usb_serial_port *port) +{ + struct whiteheat_private *info; + + info = usb_get_serial_port_data(port); + kfree(info); + + return 0; } static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port) -- cgit v1.2.3-55-g7522 From 456c5be56ed070a4d883c60b587bcc1c97a8cf3e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:03 +0200 Subject: USB: ch341: fix port-data memory leak Fix port-data memory leak by moving port data allocation to port_probe and actually implementing deallocation. Note that this driver has never even bothered to try to deallocate it's port data... Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ch341.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index e9c7046ae355..d255f66e708e 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -242,13 +242,11 @@ out: kfree(buffer); return r; } -/* allocate private data */ -static int ch341_attach(struct usb_serial *serial) +static int ch341_port_probe(struct usb_serial_port *port) { struct ch341_private *priv; int r; - /* private data */ priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -258,17 +256,27 @@ static int ch341_attach(struct usb_serial *serial) priv->baud_rate = DEFAULT_BAUD_RATE; priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR; - r = ch341_configure(serial->dev, priv); + r = ch341_configure(port->serial->dev, priv); if (r < 0) goto error; - usb_set_serial_port_data(serial->port[0], priv); + usb_set_serial_port_data(port, priv); return 0; error: kfree(priv); return r; } +static int ch341_port_remove(struct usb_serial_port *port) +{ + struct ch341_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; +} + static int ch341_carrier_raised(struct usb_serial_port *port) { struct ch341_private *priv = usb_get_serial_port_data(port); @@ -304,7 +312,7 @@ static void ch341_close(struct usb_serial_port *port) static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port) { struct usb_serial *serial = port->serial; - struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]); + struct ch341_private *priv = usb_get_serial_port_data(port); int r; priv->baud_rate = DEFAULT_BAUD_RATE; @@ -608,7 +616,8 @@ static struct usb_serial_driver ch341_device = { .tiocmget = ch341_tiocmget, .tiocmset = ch341_tiocmset, .read_int_callback = ch341_read_int_callback, - .attach = ch341_attach, + .port_probe = ch341_port_probe, + .port_remove = ch341_port_remove, .reset_resume = ch341_reset_resume, }; -- cgit v1.2.3-55-g7522 From fb44ff854e148bc5c5982dad32da98b7a0989d2d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:04 +0200 Subject: USB: digi_acceleport: fix port-data memory leak Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that the oob port is never registered as a port device and should thus be handled in attach and release. Compile-only tested. Cc: Peter Berger Cc: Al Borchers Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/digi_acceleport.c | 117 ++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index c86f68c6b078..b50fa1c6d885 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -244,6 +244,8 @@ static int digi_startup_device(struct usb_serial *serial); static int digi_startup(struct usb_serial *serial); static void digi_disconnect(struct usb_serial *serial); static void digi_release(struct usb_serial *serial); +static int digi_port_probe(struct usb_serial_port *port); +static int digi_port_remove(struct usb_serial_port *port); static void digi_read_bulk_callback(struct urb *urb); static int digi_read_inb_callback(struct urb *urb); static int digi_read_oob_callback(struct urb *urb); @@ -294,6 +296,8 @@ static struct usb_serial_driver digi_acceleport_2_device = { .attach = digi_startup, .disconnect = digi_disconnect, .release = digi_release, + .port_probe = digi_port_probe, + .port_remove = digi_port_remove, }; static struct usb_serial_driver digi_acceleport_4_device = { @@ -320,6 +324,8 @@ static struct usb_serial_driver digi_acceleport_4_device = { .attach = digi_startup, .disconnect = digi_disconnect, .release = digi_release, + .port_probe = digi_port_probe, + .port_remove = digi_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -1240,59 +1246,50 @@ static int digi_startup_device(struct usb_serial *serial) return ret; } - -static int digi_startup(struct usb_serial *serial) +static int digi_port_init(struct usb_serial_port *port, unsigned port_num) { - - int i; struct digi_port *priv; - struct digi_serial *serial_priv; - /* allocate the private data structures for all ports */ - /* number of regular ports + 1 for the out-of-band port */ - for (i = 0; i < serial->type->num_ports + 1; i++) { - /* allocate port private structure */ - priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL); - if (priv == NULL) { - while (--i >= 0) - kfree(usb_get_serial_port_data(serial->port[i])); - return 1; /* error */ - } + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; - /* initialize port private structure */ - spin_lock_init(&priv->dp_port_lock); - priv->dp_port_num = i; - priv->dp_out_buf_len = 0; - priv->dp_write_urb_in_use = 0; - priv->dp_modem_signals = 0; - init_waitqueue_head(&priv->dp_modem_change_wait); - priv->dp_transmit_idle = 0; - init_waitqueue_head(&priv->dp_transmit_idle_wait); - priv->dp_throttled = 0; - priv->dp_throttle_restart = 0; - init_waitqueue_head(&priv->dp_flush_wait); - init_waitqueue_head(&priv->dp_close_wait); - INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); - priv->dp_port = serial->port[i]; - /* initialize write wait queue for this port */ - init_waitqueue_head(&serial->port[i]->write_wait); - - usb_set_serial_port_data(serial->port[i], priv); - } + spin_lock_init(&priv->dp_port_lock); + priv->dp_port_num = port_num; + init_waitqueue_head(&priv->dp_modem_change_wait); + init_waitqueue_head(&priv->dp_transmit_idle_wait); + init_waitqueue_head(&priv->dp_flush_wait); + init_waitqueue_head(&priv->dp_close_wait); + INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); + priv->dp_port = port; - /* allocate serial private structure */ - serial_priv = kmalloc(sizeof(struct digi_serial), GFP_KERNEL); - if (serial_priv == NULL) { - for (i = 0; i < serial->type->num_ports + 1; i++) - kfree(usb_get_serial_port_data(serial->port[i])); - return 1; /* error */ - } + init_waitqueue_head(&port->write_wait); + + usb_set_serial_port_data(port, priv); + + return 0; +} + +static int digi_startup(struct usb_serial *serial) +{ + struct digi_serial *serial_priv; + int ret; + + serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL); + if (!serial_priv) + return -ENOMEM; - /* initialize serial private structure */ spin_lock_init(&serial_priv->ds_serial_lock); serial_priv->ds_oob_port_num = serial->type->num_ports; serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num]; - serial_priv->ds_device_started = 0; + + ret = digi_port_init(serial_priv->ds_oob_port, + serial_priv->ds_oob_port_num); + if (ret) { + kfree(serial_priv); + return ret; + } + usb_set_serial_data(serial, serial_priv); return 0; @@ -1313,15 +1310,35 @@ static void digi_disconnect(struct usb_serial *serial) static void digi_release(struct usb_serial *serial) { - int i; + struct digi_serial *serial_priv; + struct digi_port *priv; + + serial_priv = usb_get_serial_data(serial); + + priv = usb_get_serial_port_data(serial_priv->ds_oob_port); + kfree(priv); - /* free the private data structures for all ports */ - /* number of regular ports + 1 for the out-of-band port */ - for (i = 0; i < serial->type->num_ports + 1; i++) - kfree(usb_get_serial_port_data(serial->port[i])); - kfree(usb_get_serial_data(serial)); + kfree(serial_priv); } +static int digi_port_probe(struct usb_serial_port *port) +{ + unsigned port_num; + + port_num = port->number - port->serial->minor; + + return digi_port_init(port, port_num); +} + +static int digi_port_remove(struct usb_serial_port *port) +{ + struct digi_port *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; +} static void digi_read_bulk_callback(struct urb *urb) { -- cgit v1.2.3-55-g7522 From 4230af572f95b3115bba1ee6fb95681f3851ab26 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:05 +0200 Subject: USB: mos7720: fix port-data memory leak Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that this patch also fixes a second port-data memory leak in the error path of attach, should parallel-port initialisation fail. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7720.c | 62 +++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 1bf1ad066666..75267421aad8 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1966,9 +1966,7 @@ static int mos7720_ioctl(struct tty_struct *tty, static int mos7720_startup(struct usb_serial *serial) { - struct moschip_port *mos7720_port; struct usb_device *dev; - int i; char data; u16 product; int ret_val; @@ -1999,29 +1997,6 @@ static int mos7720_startup(struct usb_serial *serial) serial->port[1]->interrupt_in_buffer = NULL; } - - /* set up serial port private structures */ - for (i = 0; i < serial->num_ports; ++i) { - mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); - if (mos7720_port == NULL) { - dev_err(&dev->dev, "%s - Out of memory\n", __func__); - return -ENOMEM; - } - - /* Initialize all port interrupt end point to port 0 int - * endpoint. Our device has only one interrupt endpoint - * common to all ports */ - serial->port[i]->interrupt_in_endpointAddress = - serial->port[0]->interrupt_in_endpointAddress; - - mos7720_port->port = serial->port[i]; - usb_set_serial_port_data(serial->port[i], mos7720_port); - - dev_dbg(&dev->dev, "port number is %d\n", serial->port[i]->number); - dev_dbg(&dev->dev, "serial number is %d\n", serial->minor); - } - - /* setting configuration feature to one */ usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ); @@ -2049,8 +2024,6 @@ static int mos7720_startup(struct usb_serial *serial) static void mos7720_release(struct usb_serial *serial) { - int i; - #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT /* close the parallel port */ @@ -2089,9 +2062,36 @@ static void mos7720_release(struct usb_serial *serial) kref_put(&mos_parport->ref_count, destroy_mos_parport); } #endif - /* free private structure allocated for serial port */ - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); +} + +static int mos7720_port_probe(struct usb_serial_port *port) +{ + struct moschip_port *mos7720_port; + + mos7720_port = kzalloc(sizeof(*mos7720_port), GFP_KERNEL); + if (!mos7720_port) + return -ENOMEM; + + /* Initialize all port interrupt end point to port 0 int endpoint. + * Our device has only one interrupt endpoint common to all ports. + */ + port->interrupt_in_endpointAddress = + port->serial->port[0]->interrupt_in_endpointAddress; + mos7720_port->port = port; + + usb_set_serial_port_data(port, mos7720_port); + + return 0; +} + +static int mos7720_port_remove(struct usb_serial_port *port) +{ + struct moschip_port *mos7720_port; + + mos7720_port = usb_get_serial_port_data(port); + kfree(mos7720_port); + + return 0; } static struct usb_serial_driver moschip7720_2port_driver = { @@ -2109,6 +2109,8 @@ static struct usb_serial_driver moschip7720_2port_driver = { .probe = mos77xx_probe, .attach = mos7720_startup, .release = mos7720_release, + .port_probe = mos7720_port_probe, + .port_remove = mos7720_port_remove, .ioctl = mos7720_ioctl, .tiocmget = mos7720_tiocmget, .tiocmset = mos7720_tiocmset, -- cgit v1.2.3-55-g7522 From feffa7ca6008ab859dd7ab7448a5a899bf0aa98f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:06 +0200 Subject: USB: omninet: fix port-data memory leak Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/omninet.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 6def58b79382..9ab73d295774 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -44,8 +44,8 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); static int omninet_write_room(struct tty_struct *tty); static void omninet_disconnect(struct usb_serial *serial); -static void omninet_release(struct usb_serial *serial); -static int omninet_attach(struct usb_serial *serial); +static int omninet_port_probe(struct usb_serial_port *port); +static int omninet_port_remove(struct usb_serial_port *port); static const struct usb_device_id id_table[] = { { USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) }, @@ -62,7 +62,8 @@ static struct usb_serial_driver zyxel_omninet_device = { .description = "ZyXEL - omni.net lcd plus usb", .id_table = id_table, .num_ports = 1, - .attach = omninet_attach, + .port_probe = omninet_port_probe, + .port_remove = omninet_port_remove, .open = omninet_open, .close = omninet_close, .write = omninet_write, @@ -70,7 +71,6 @@ static struct usb_serial_driver zyxel_omninet_device = { .read_bulk_callback = omninet_read_bulk_callback, .write_bulk_callback = omninet_write_bulk_callback, .disconnect = omninet_disconnect, - .release = omninet_release, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -112,18 +112,26 @@ struct omninet_data { __u8 od_outseq; /* Sequence number for bulk_out URBs */ }; -static int omninet_attach(struct usb_serial *serial) +static int omninet_port_probe(struct usb_serial_port *port) { struct omninet_data *od; - struct usb_serial_port *port = serial->port[0]; od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL); - if (!od) { - dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", - __func__, sizeof(struct omninet_data)); + if (!od) return -ENOMEM; - } + usb_set_serial_port_data(port, od); + + return 0; +} + +static int omninet_port_remove(struct usb_serial_port *port) +{ + struct omninet_data *od; + + od = usb_get_serial_port_data(port); + kfree(od); + return 0; } @@ -279,14 +287,6 @@ static void omninet_disconnect(struct usb_serial *serial) usb_kill_urb(wport->write_urb); } - -static void omninet_release(struct usb_serial *serial) -{ - struct usb_serial_port *port = serial->port[0]; - - kfree(usb_get_serial_port_data(port)); -} - module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); -- cgit v1.2.3-55-g7522 From b8a0055050b6294826171641b182c09f78f4cc63 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:07 +0200 Subject: USB: quatech2: fix memory leak in error path Fix memory leak in attach error path where the read urb was never freed. Cc: Bill Pemberton Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/quatech2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 2cdfdcc90b37..5adb7428fbb1 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -823,6 +823,7 @@ static int qt2_setup_urbs(struct usb_serial *serial) if (status != 0) { dev_err(&serial->dev->dev, "%s - submit read urb failed %i\n", __func__, status); + usb_free_urb(serial_priv->read_urb); return status; } -- cgit v1.2.3-55-g7522 From 40d04738491d7ac1aa708ba434ff3480ec9e1b96 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:08 +0200 Subject: USB: quatech2: fix port-data memory leaks Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that this also fixes memory leaks in the error path of attach where the write urbs were not freed on errors. Make sure all interface-data deallocation is done in release by moving the read urb deallocation from disconnect. Note that the write urb is killed during close so that the call in disconnect was superfluous. Compile-only tested. Cc: Bill Pemberton Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/quatech2.c | 121 ++++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 5adb7428fbb1..8d0c4a0b6a7b 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -143,12 +143,12 @@ static void qt2_read_bulk_callback(struct urb *urb); static void qt2_release(struct usb_serial *serial) { - int i; + struct qt2_serial_private *serial_priv; - kfree(usb_get_serial_data(serial)); + serial_priv = usb_get_serial_data(serial); - for (i = 0; i < serial->num_ports; i++) - kfree(usb_get_serial_port_data(serial->port[i])); + usb_free_urb(serial_priv->read_urb); + kfree(serial_priv); } static inline int calc_baud_divisor(int baudrate) @@ -464,21 +464,9 @@ static void qt2_close(struct usb_serial_port *port) static void qt2_disconnect(struct usb_serial *serial) { struct qt2_serial_private *serial_priv = usb_get_serial_data(serial); - struct qt2_port_private *port_priv; - int i; if (serial_priv->read_urb->status == -EINPROGRESS) usb_kill_urb(serial_priv->read_urb); - - usb_free_urb(serial_priv->read_urb); - - for (i = 0; i < serial->num_ports; i++) { - port_priv = usb_get_serial_port_data(serial->port[i]); - - if (port_priv->write_urb->status == -EINPROGRESS) - usb_kill_urb(port_priv->write_urb); - usb_free_urb(port_priv->write_urb); - } } static int get_serial_info(struct usb_serial_port *port, @@ -773,11 +761,9 @@ static void qt2_read_bulk_callback(struct urb *urb) static int qt2_setup_urbs(struct usb_serial *serial) { - struct usb_serial_port *port; struct usb_serial_port *port0; struct qt2_serial_private *serial_priv; - struct qt2_port_private *port_priv; - int pcount, status; + int status; port0 = serial->port[0]; @@ -795,30 +781,6 @@ static int qt2_setup_urbs(struct usb_serial *serial) sizeof(serial_priv->read_buffer), qt2_read_bulk_callback, serial); - /* setup write_urb for each port */ - for (pcount = 0; pcount < serial->num_ports; pcount++) { - - port = serial->port[pcount]; - port_priv = usb_get_serial_port_data(port); - - port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!port_priv->write_urb) { - dev_err(&serial->dev->dev, - "failed to alloc write_urb for port %i\n", - pcount); - return -ENOMEM; - } - - usb_fill_bulk_urb(port_priv->write_urb, - serial->dev, - usb_sndbulkpipe(serial->dev, - port0-> - bulk_out_endpointAddress), - port_priv->write_buffer, - sizeof(port_priv->write_buffer), - qt2_write_bulk_callback, port); - } - status = usb_submit_urb(serial_priv->read_urb, GFP_KERNEL); if (status != 0) { dev_err(&serial->dev->dev, @@ -828,14 +790,12 @@ static int qt2_setup_urbs(struct usb_serial *serial) } return 0; - } static int qt2_attach(struct usb_serial *serial) { struct qt2_serial_private *serial_priv; - struct qt2_port_private *port_priv; - int status, pcount; + int status; /* power on unit */ status = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), @@ -855,26 +815,6 @@ static int qt2_attach(struct usb_serial *serial) usb_set_serial_data(serial, serial_priv); - for (pcount = 0; pcount < serial->num_ports; pcount++) { - port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); - if (!port_priv) { - dev_err(&serial->dev->dev, - "%s- kmalloc(%Zd) failed.\n", __func__, - sizeof(*port_priv)); - pcount--; - status = -ENOMEM; - goto attach_failed; - } - - spin_lock_init(&port_priv->lock); - spin_lock_init(&port_priv->urb_lock); - init_waitqueue_head(&port_priv->delta_msr_wait); - - port_priv->port = serial->port[pcount]; - - usb_set_serial_port_data(serial->port[pcount], port_priv); - } - status = qt2_setup_urbs(serial); if (status != 0) goto attach_failed; @@ -882,14 +822,53 @@ static int qt2_attach(struct usb_serial *serial) return 0; attach_failed: - for (/* empty */; pcount >= 0; pcount--) { - port_priv = usb_get_serial_port_data(serial->port[pcount]); - kfree(port_priv); - } kfree(serial_priv); return status; } +static int qt2_port_probe(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + struct qt2_port_private *port_priv; + u8 bEndpointAddress; + + port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); + if (!port_priv) + return -ENOMEM; + + spin_lock_init(&port_priv->lock); + spin_lock_init(&port_priv->urb_lock); + init_waitqueue_head(&port_priv->delta_msr_wait); + port_priv->port = port; + + port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!port_priv->write_urb) { + kfree(port_priv); + return -ENOMEM; + } + bEndpointAddress = serial->port[0]->bulk_out_endpointAddress; + usb_fill_bulk_urb(port_priv->write_urb, serial->dev, + usb_sndbulkpipe(serial->dev, bEndpointAddress), + port_priv->write_buffer, + sizeof(port_priv->write_buffer), + qt2_write_bulk_callback, port); + + usb_set_serial_port_data(port, port_priv); + + return 0; +} + +static int qt2_port_remove(struct usb_serial_port *port) +{ + struct qt2_port_private *port_priv; + + port_priv = usb_get_serial_port_data(port); + usb_free_urb(port_priv->write_urb); + kfree(port_priv); + + return 0; +} + static int qt2_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; @@ -1128,6 +1107,8 @@ static struct usb_serial_driver qt2_device = { .attach = qt2_attach, .release = qt2_release, .disconnect = qt2_disconnect, + .port_probe = qt2_port_probe, + .port_remove = qt2_port_remove, .dtr_rts = qt2_dtr_rts, .break_ctl = qt2_break_ctl, .tiocmget = qt2_tiocmget, -- cgit v1.2.3-55-g7522 From 8e512ab0b675da20e023439a5811e3f2554e6852 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:09 +0200 Subject: USB: quatech2: fix close and disconnect urb handling Kill urbs unconditionally at close and disconnect. Note that URB status is not valid outside of completion handler. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/quatech2.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 8d0c4a0b6a7b..7e8d8f32b634 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -423,8 +423,7 @@ static void qt2_close(struct usb_serial_port *port) port_priv->is_open = false; spin_lock_irqsave(&port_priv->urb_lock, flags); - if (port_priv->write_urb->status == -EINPROGRESS) - usb_kill_urb(port_priv->write_urb); + usb_kill_urb(port_priv->write_urb); port_priv->urb_in_use = false; spin_unlock_irqrestore(&port_priv->urb_lock, flags); @@ -465,8 +464,7 @@ static void qt2_disconnect(struct usb_serial *serial) { struct qt2_serial_private *serial_priv = usb_get_serial_data(serial); - if (serial_priv->read_urb->status == -EINPROGRESS) - usb_kill_urb(serial_priv->read_urb); + usb_kill_urb(serial_priv->read_urb); } static int get_serial_info(struct usb_serial_port *port, -- cgit v1.2.3-55-g7522 From 2f0295adf6438188c4cd0868f2b1976a2b034e1d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:10 +0200 Subject: USB: quatech2: fix io after disconnect Make sure no control urb is submitted during close after a disconnect by checking the disconnected flag. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/quatech2.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 7e8d8f32b634..ffcfc962ab10 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -427,6 +427,12 @@ static void qt2_close(struct usb_serial_port *port) port_priv->urb_in_use = false; spin_unlock_irqrestore(&port_priv->urb_lock, flags); + mutex_lock(&port->serial->disc_mutex); + if (port->serial->disconnected) { + mutex_unlock(&port->serial->disc_mutex); + return; + } + /* flush the port transmit buffer */ i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), @@ -458,6 +464,7 @@ static void qt2_close(struct usb_serial_port *port) dev_err(&port->dev, "%s - close port failed %i\n", __func__, i); + mutex_unlock(&port->serial->disc_mutex); } static void qt2_disconnect(struct usb_serial *serial) -- cgit v1.2.3-55-g7522 From ea0dbebffe118724cd4df7d9b071ea8ee48d48f0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:11 +0200 Subject: USB: opticon: fix DMA from stack Make sure to allocate the control-message buffer dynamically as some platforms cannot do DMA from stack. Note that only the first byte of the old buffer was used. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 41b1647306eb..459c28889fe4 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -155,7 +155,11 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype, { struct usb_serial *serial = port->serial; int retval; - u8 buffer[2]; + u8 *buffer; + + buffer = kzalloc(1, GFP_KERNEL); + if (!buffer) + return -ENOMEM; buffer[0] = val; /* Send the message to the vendor control endpoint @@ -164,6 +168,7 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype, requesttype, USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, 0, 0, buffer, 1, 0); + kfree(buffer); return retval; } -- cgit v1.2.3-55-g7522 From acbf0e5263de563e25f7c104868e4490b9e72b13 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:12 +0200 Subject: USB: opticon: fix memory leak in error path Fix memory leak in write error path. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 459c28889fe4..6aba731d4864 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -286,7 +286,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, if (!dr) { dev_err(&port->dev, "out of memory\n"); count = -ENOMEM; - goto error; + goto error_no_dr; } dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT; @@ -316,6 +316,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, return count; error: + kfree(dr); +error_no_dr: usb_free_urb(urb); error_no_urb: kfree(buffer); -- cgit v1.2.3-55-g7522 From a8f2ae7a3aa59079d7e7e1ddf5007f03532f458c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:13 +0200 Subject: USB: mct_u232: fix port-data memory leak Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that the write waitqueue was initialised but never used. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mct_u232.c | 45 ++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index f3947712e137..a8bce134ffba 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -49,7 +49,8 @@ * Function prototypes */ static int mct_u232_startup(struct usb_serial *serial); -static void mct_u232_release(struct usb_serial *serial); +static int mct_u232_port_probe(struct usb_serial_port *port); +static int mct_u232_port_remove(struct usb_serial_port *remove); static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port); static void mct_u232_close(struct usb_serial_port *port); static void mct_u232_dtr_rts(struct usb_serial_port *port, int on); @@ -99,7 +100,8 @@ static struct usb_serial_driver mct_u232_device = { .tiocmget = mct_u232_tiocmget, .tiocmset = mct_u232_tiocmset, .attach = mct_u232_startup, - .release = mct_u232_release, + .port_probe = mct_u232_port_probe, + .port_remove = mct_u232_port_remove, .ioctl = mct_u232_ioctl, .get_icount = mct_u232_get_icount, }; @@ -388,18 +390,8 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port, static int mct_u232_startup(struct usb_serial *serial) { - struct mct_u232_private *priv; struct usb_serial_port *port, *rport; - priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL); - if (!priv) - return -ENOMEM; - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->msr_wait); - usb_set_serial_port_data(serial->port[0], priv); - - init_waitqueue_head(&serial->port[0]->write_wait); - /* Puh, that's dirty */ port = serial->port[0]; rport = serial->port[1]; @@ -412,18 +404,31 @@ static int mct_u232_startup(struct usb_serial *serial) return 0; } /* mct_u232_startup */ +static int mct_u232_port_probe(struct usb_serial_port *port) +{ + struct mct_u232_private *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; -static void mct_u232_release(struct usb_serial *serial) + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->msr_wait); + + usb_set_serial_port_data(port, priv); + + return 0; +} + +static int mct_u232_port_remove(struct usb_serial_port *port) { struct mct_u232_private *priv; - int i; - for (i = 0; i < serial->num_ports; ++i) { - /* My special items, the standard routines free my urbs */ - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - } -} /* mct_u232_release */ + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; +} static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port) { -- cgit v1.2.3-55-g7522 From 5260e458f5eff269a43e4f1e9c47186c57b88ddb Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:14 +0200 Subject: USB: mct_u232: fix broken close Make sure generic close is called at close. The driver relies on the generic write implementation but did not call generic close. Note that the call to kill the read urb is not redundant, as mct_u232 uses an interrupt urb from the second port as the read urb and that generic close therefore fails to kill it. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mct_u232.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index a8bce134ffba..8a2081004107 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -520,12 +520,14 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on) static void mct_u232_close(struct usb_serial_port *port) { - if (port->serial->dev) { - /* shutdown our urbs */ - usb_kill_urb(port->write_urb); - usb_kill_urb(port->read_urb); - usb_kill_urb(port->interrupt_in_urb); - } + /* + * Must kill the read urb as it is actually an interrupt urb, which + * generic close thus fails to kill. + */ + usb_kill_urb(port->read_urb); + usb_kill_urb(port->interrupt_in_urb); + + usb_serial_generic_close(port); } /* mct_u232_close */ -- cgit v1.2.3-55-g7522 From f79b2d0fe81eecb412dc48e87a119afc690da8e9 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:15 +0200 Subject: USB: keyspan: fix NULL-pointer dereferences and memory leaks Fix NULL-pointer dereference at release by moving port data allocation and deallocation to port_probe and port_remove. Fix NULL-pointer dereference at disconnect by stopping port urbs at port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer accessible at disconnect or release. Note that this patch also fixes port and interface-data memory leaks in the error path of attach should port initialisation fail for any port. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/keyspan.c | 181 +++++++++++++++++++++---------------------- drivers/usb/serial/keyspan.h | 8 ++ 2 files changed, 96 insertions(+), 93 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 29c943d737d0..7179b0c5f814 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -1374,13 +1374,9 @@ static struct callbacks { data in device_details */ static void keyspan_setup_urbs(struct usb_serial *serial) { - int i, j; struct keyspan_serial_private *s_priv; const struct keyspan_device_details *d_details; - struct usb_serial_port *port; - struct keyspan_port_private *p_priv; struct callbacks *cback; - int endp; s_priv = usb_get_serial_data(serial); d_details = s_priv->device_details; @@ -1404,45 +1400,6 @@ static void keyspan_setup_urbs(struct usb_serial *serial) (serial, d_details->glocont_endpoint, USB_DIR_OUT, serial, s_priv->glocont_buf, GLOCONT_BUFLEN, cback->glocont_callback); - - /* Setup endpoints for each port specific thing */ - for (i = 0; i < d_details->num_ports; i++) { - port = serial->port[i]; - p_priv = usb_get_serial_port_data(port); - - /* Do indat endpoints first, once for each flip */ - endp = d_details->indat_endpoints[i]; - for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) { - p_priv->in_urbs[j] = keyspan_setup_urb - (serial, endp, USB_DIR_IN, port, - p_priv->in_buffer[j], 64, - cback->indat_callback); - } - for (; j < 2; ++j) - p_priv->in_urbs[j] = NULL; - - /* outdat endpoints also have flip */ - endp = d_details->outdat_endpoints[i]; - for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) { - p_priv->out_urbs[j] = keyspan_setup_urb - (serial, endp, USB_DIR_OUT, port, - p_priv->out_buffer[j], 64, - cback->outdat_callback); - } - for (; j < 2; ++j) - p_priv->out_urbs[j] = NULL; - - /* inack endpoint */ - p_priv->inack_urb = keyspan_setup_urb - (serial, d_details->inack_endpoints[i], USB_DIR_IN, - port, p_priv->inack_buffer, 1, cback->inack_callback); - - /* outcont endpoint */ - p_priv->outcont_urb = keyspan_setup_urb - (serial, d_details->outcont_endpoints[i], USB_DIR_OUT, - port, p_priv->outcont_buffer, 64, - cback->outcont_callback); - } } /* usa19 function doesn't require prescaler */ @@ -2407,9 +2364,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port) static int keyspan_startup(struct usb_serial *serial) { int i, err; - struct usb_serial_port *port; struct keyspan_serial_private *s_priv; - struct keyspan_port_private *p_priv; const struct keyspan_device_details *d_details; for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i) @@ -2432,19 +2387,6 @@ static int keyspan_startup(struct usb_serial *serial) s_priv->device_details = d_details; usb_set_serial_data(serial, s_priv); - /* Now setup per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - p_priv = kzalloc(sizeof(struct keyspan_port_private), - GFP_KERNEL); - if (!p_priv) { - dev_dbg(&port->dev, "%s - kmalloc for keyspan_port_private (%d) failed!.\n", __func__, i); - return 1; - } - p_priv->device_details = d_details; - usb_set_serial_port_data(port, p_priv); - } - keyspan_setup_urbs(serial); if (s_priv->instat_urb != NULL) { @@ -2463,59 +2405,112 @@ static int keyspan_startup(struct usb_serial *serial) static void keyspan_disconnect(struct usb_serial *serial) { - int i, j; - struct usb_serial_port *port; - struct keyspan_serial_private *s_priv; - struct keyspan_port_private *p_priv; + struct keyspan_serial_private *s_priv; s_priv = usb_get_serial_data(serial); - /* Stop reading/writing urbs */ stop_urb(s_priv->instat_urb); stop_urb(s_priv->glocont_urb); stop_urb(s_priv->indat_urb); - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - p_priv = usb_get_serial_port_data(port); - stop_urb(p_priv->inack_urb); - stop_urb(p_priv->outcont_urb); - for (j = 0; j < 2; j++) { - stop_urb(p_priv->in_urbs[j]); - stop_urb(p_priv->out_urbs[j]); - } - } +} + +static void keyspan_release(struct usb_serial *serial) +{ + struct keyspan_serial_private *s_priv; + + s_priv = usb_get_serial_data(serial); - /* Now free them */ usb_free_urb(s_priv->instat_urb); usb_free_urb(s_priv->indat_urb); usb_free_urb(s_priv->glocont_urb); - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - p_priv = usb_get_serial_port_data(port); - usb_free_urb(p_priv->inack_urb); - usb_free_urb(p_priv->outcont_urb); - for (j = 0; j < 2; j++) { - usb_free_urb(p_priv->in_urbs[j]); - usb_free_urb(p_priv->out_urbs[j]); - } - } + + kfree(s_priv); } -static void keyspan_release(struct usb_serial *serial) +static int keyspan_port_probe(struct usb_serial_port *port) { - int i; - struct usb_serial_port *port; - struct keyspan_serial_private *s_priv; + struct usb_serial *serial = port->serial; + struct keyspan_port_private *s_priv; + struct keyspan_port_private *p_priv; + const struct keyspan_device_details *d_details; + struct callbacks *cback; + int endp; + int port_num; + int i; s_priv = usb_get_serial_data(serial); + d_details = s_priv->device_details; - kfree(s_priv); + p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL); + if (!p_priv) + return -ENOMEM; - /* Now free per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - kfree(usb_get_serial_port_data(port)); + s_priv = usb_get_serial_data(port->serial); + p_priv->device_details = d_details; + + /* Setup values for the various callback routines */ + cback = &keyspan_callbacks[d_details->msg_format]; + + port_num = port->number - port->serial->minor; + + /* Do indat endpoints first, once for each flip */ + endp = d_details->indat_endpoints[port_num]; + for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) { + p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp, + USB_DIR_IN, port, + p_priv->in_buffer[i], 64, + cback->indat_callback); + } + /* outdat endpoints also have flip */ + endp = d_details->outdat_endpoints[port_num]; + for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) { + p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp, + USB_DIR_OUT, port, + p_priv->out_buffer[i], 64, + cback->outdat_callback); + } + /* inack endpoint */ + p_priv->inack_urb = keyspan_setup_urb(serial, + d_details->inack_endpoints[port_num], + USB_DIR_IN, port, + p_priv->inack_buffer, 1, + cback->inack_callback); + /* outcont endpoint */ + p_priv->outcont_urb = keyspan_setup_urb(serial, + d_details->outcont_endpoints[port_num], + USB_DIR_OUT, port, + p_priv->outcont_buffer, 64, + cback->outcont_callback); + + usb_set_serial_port_data(port, p_priv); + + return 0; +} + +static int keyspan_port_remove(struct usb_serial_port *port) +{ + struct keyspan_port_private *p_priv; + int i; + + p_priv = usb_get_serial_port_data(port); + + stop_urb(p_priv->inack_urb); + stop_urb(p_priv->outcont_urb); + for (i = 0; i < 2; i++) { + stop_urb(p_priv->in_urbs[i]); + stop_urb(p_priv->out_urbs[i]); + } + + usb_free_urb(p_priv->inack_urb); + usb_free_urb(p_priv->outcont_urb); + for (i = 0; i < 2; i++) { + usb_free_urb(p_priv->in_urbs[i]); + usb_free_urb(p_priv->out_urbs[i]); } + + kfree(p_priv); + + return 0; } MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index 0a8a40b5711e..0273dda303a4 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -42,6 +42,8 @@ static void keyspan_dtr_rts (struct usb_serial_port *port, int on); static int keyspan_startup (struct usb_serial *serial); static void keyspan_disconnect (struct usb_serial *serial); static void keyspan_release (struct usb_serial *serial); +static int keyspan_port_probe(struct usb_serial_port *port); +static int keyspan_port_remove(struct usb_serial_port *port); static int keyspan_write_room (struct tty_struct *tty); static int keyspan_write (struct tty_struct *tty, @@ -567,6 +569,8 @@ static struct usb_serial_driver keyspan_1port_device = { .attach = keyspan_startup, .disconnect = keyspan_disconnect, .release = keyspan_release, + .port_probe = keyspan_port_probe, + .port_remove = keyspan_port_remove, }; static struct usb_serial_driver keyspan_2port_device = { @@ -589,6 +593,8 @@ static struct usb_serial_driver keyspan_2port_device = { .attach = keyspan_startup, .disconnect = keyspan_disconnect, .release = keyspan_release, + .port_probe = keyspan_port_probe, + .port_remove = keyspan_port_remove, }; static struct usb_serial_driver keyspan_4port_device = { @@ -611,6 +617,8 @@ static struct usb_serial_driver keyspan_4port_device = { .attach = keyspan_startup, .disconnect = keyspan_disconnect, .release = keyspan_release, + .port_probe = keyspan_port_probe, + .port_remove = keyspan_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { -- cgit v1.2.3-55-g7522 From b8f0e82044c9ba40e92340c8a6d47d6bd6d819bc Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:16 +0200 Subject: USB: usb-wwan: fix multiple memory leaks in error paths Fix port-data memory leak in usb-serial probe error path by moving port data allocation to port_probe. Since commit a1028f0abf ("usb: usb_wwan: replace release and disconnect with a port_remove hook") port data is deallocated in port_remove. This leaves a possibility for memory leaks if usb-serial probe fails after attach but before the port in question has been successfully registered. Note that this patch also fixes two additional memory leaks in the error path of attach should port initialisation fail for any port as the urbs were never freed and neither was the data of any of the successfully initialised ports. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ipw.c | 2 +- drivers/usb/serial/option.c | 2 +- drivers/usb/serial/qcserial.c | 2 +- drivers/usb/serial/usb-wwan.h | 2 +- drivers/usb/serial/usb_wwan.c | 124 +++++++++++++++++------------------------- 5 files changed, 54 insertions(+), 78 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 20a132ec39e2..add45b7d8aa7 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -304,8 +304,8 @@ static struct usb_serial_driver ipw_device = { .open = ipw_open, .close = ipw_close, .probe = ipw_probe, - .attach = usb_wwan_startup, .release = ipw_release, + .port_probe = usb_wwan_port_probe, .port_remove = usb_wwan_port_remove, .dtr_rts = ipw_dtr_rts, .write = usb_wwan_write, diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 54d4148d01d1..eb4bdd4a0106 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1288,8 +1288,8 @@ static struct usb_serial_driver option_1port_device = { .tiocmget = usb_wwan_tiocmget, .tiocmset = usb_wwan_tiocmset, .ioctl = usb_wwan_ioctl, - .attach = usb_wwan_startup, .release = option_release, + .port_probe = usb_wwan_port_probe, .port_remove = usb_wwan_port_remove, .read_int_callback = option_instat_callback, #ifdef CONFIG_PM diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index c3ddb65c05f2..8dd2280dff63 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -285,8 +285,8 @@ static struct usb_serial_driver qcdevice = { .write = usb_wwan_write, .write_room = usb_wwan_write_room, .chars_in_buffer = usb_wwan_chars_in_buffer, - .attach = usb_wwan_startup, .release = qc_release, + .port_probe = usb_wwan_port_probe, .port_remove = usb_wwan_port_remove, #ifdef CONFIG_PM .suspend = usb_wwan_suspend, diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h index 1f034d2397c6..684739b8efd0 100644 --- a/drivers/usb/serial/usb-wwan.h +++ b/drivers/usb/serial/usb-wwan.h @@ -8,7 +8,7 @@ extern void usb_wwan_dtr_rts(struct usb_serial_port *port, int on); extern int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port); extern void usb_wwan_close(struct usb_serial_port *port); -extern int usb_wwan_startup(struct usb_serial *serial); +extern int usb_wwan_port_probe(struct usb_serial_port *port); extern int usb_wwan_port_remove(struct usb_serial_port *port); extern int usb_wwan_write_room(struct tty_struct *tty); extern void usb_wwan_set_termios(struct tty_struct *tty, diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index e42aa398ed37..61a73ad1a187 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -447,10 +447,12 @@ void usb_wwan_close(struct usb_serial_port *port) EXPORT_SYMBOL(usb_wwan_close); /* Helper functions used by usb_wwan_setup_urbs */ -static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint, +static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port, + int endpoint, int dir, void *ctx, char *buf, int len, void (*callback) (struct urb *)) { + struct usb_serial *serial = port->serial; struct urb *urb; if (endpoint == -1) @@ -472,101 +474,75 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint, return urb; } -/* Setup urbs */ -static void usb_wwan_setup_urbs(struct usb_serial *serial) +int usb_wwan_port_probe(struct usb_serial_port *port) { - int i, j; - struct usb_serial_port *port; struct usb_wwan_port_private *portdata; + struct urb *urb; + u8 *buffer; + int err; + int i; - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - portdata = usb_get_serial_port_data(port); + portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); + if (!portdata) + return -ENOMEM; - /* Do indat endpoints first */ - for (j = 0; j < N_IN_URB; ++j) { - portdata->in_urbs[j] = usb_wwan_setup_urb(serial, - port-> - bulk_in_endpointAddress, - USB_DIR_IN, - port, - portdata-> - in_buffer[j], - IN_BUFLEN, - usb_wwan_indat_callback); - } + init_usb_anchor(&portdata->delayed); - /* outdat endpoints */ - for (j = 0; j < N_OUT_URB; ++j) { - portdata->out_urbs[j] = usb_wwan_setup_urb(serial, - port-> - bulk_out_endpointAddress, - USB_DIR_OUT, - port, - portdata-> - out_buffer - [j], - OUT_BUFLEN, - usb_wwan_outdat_callback); - } + for (i = 0; i < N_IN_URB; i++) { + buffer = (u8 *)__get_free_page(GFP_KERNEL); + if (!buffer) + goto bail_out_error; + portdata->in_buffer[i] = buffer; + + urb = usb_wwan_setup_urb(port, port->bulk_in_endpointAddress, + USB_DIR_IN, port, + buffer, IN_BUFLEN, + usb_wwan_indat_callback); + portdata->in_urbs[i] = urb; } -} - -int usb_wwan_startup(struct usb_serial *serial) -{ - int i, j, err; - struct usb_serial_port *port; - struct usb_wwan_port_private *portdata; - u8 *buffer; - /* Now setup per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); - if (!portdata) { - dev_dbg(&port->dev, "%s: kmalloc for usb_wwan_port_private (%d) failed!.\n", - __func__, i); - return 1; - } - init_usb_anchor(&portdata->delayed); + for (i = 0; i < N_OUT_URB; i++) { + if (port->bulk_out_endpointAddress == -1) + continue; - for (j = 0; j < N_IN_URB; j++) { - buffer = (u8 *) __get_free_page(GFP_KERNEL); - if (!buffer) - goto bail_out_error; - portdata->in_buffer[j] = buffer; - } + buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL); + if (!buffer) + goto bail_out_error2; + portdata->out_buffer[i] = buffer; - for (j = 0; j < N_OUT_URB; j++) { - buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL); - if (!buffer) - goto bail_out_error2; - portdata->out_buffer[j] = buffer; - } + urb = usb_wwan_setup_urb(port, port->bulk_out_endpointAddress, + USB_DIR_OUT, port, + buffer, OUT_BUFLEN, + usb_wwan_outdat_callback); + portdata->out_urbs[i] = urb; + } - usb_set_serial_port_data(port, portdata); + usb_set_serial_port_data(port, portdata); - if (!port->interrupt_in_urb) - continue; + if (port->interrupt_in_urb) { err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (err) dev_dbg(&port->dev, "%s: submit irq_in urb failed %d\n", __func__, err); } - usb_wwan_setup_urbs(serial); + return 0; bail_out_error2: - for (j = 0; j < N_OUT_URB; j++) - kfree(portdata->out_buffer[j]); + for (i = 0; i < N_OUT_URB; i++) { + usb_free_urb(portdata->out_urbs[i]); + kfree(portdata->out_buffer[i]); + } bail_out_error: - for (j = 0; j < N_IN_URB; j++) - if (portdata->in_buffer[j]) - free_page((unsigned long)portdata->in_buffer[j]); + for (i = 0; i < N_IN_URB; i++) { + usb_free_urb(portdata->in_urbs[i]); + free_page((unsigned long)portdata->in_buffer[i]); + } kfree(portdata); - return 1; + + return -ENOMEM; } -EXPORT_SYMBOL(usb_wwan_startup); +EXPORT_SYMBOL_GPL(usb_wwan_port_probe); int usb_wwan_port_remove(struct usb_serial_port *port) { -- cgit v1.2.3-55-g7522 From 7e41f9bcdd2e813ea2a3c40db291d87ea06b559f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:17 +0200 Subject: USB: sierra: fix memory leak in attach error path Make sure port private data is deallocated on errors in attach. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 76ef95bcbbf2..2cb27e49d4ac 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -905,7 +905,7 @@ static int sierra_startup(struct usb_serial *serial) dev_dbg(&port->dev, "%s: kmalloc for " "sierra_port_private (%d) failed!\n", __func__, i); - return -ENOMEM; + goto err; } spin_lock_init(&portdata->lock); init_usb_anchor(&portdata->active); @@ -942,6 +942,13 @@ static int sierra_startup(struct usb_serial *serial) } return 0; +err: + for (--i; i >= 0; --i) { + portdata = usb_get_serial_port_data(serial->port[i]); + kfree(portdata); + } + + return -ENOMEM; } static void sierra_release(struct usb_serial *serial) -- cgit v1.2.3-55-g7522 From 084817d79399ab5ccab2f90a148b0369912a8369 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:18 +0200 Subject: USB: sierra: fix memory leak in probe error path Move interface data allocation to attach so that it is deallocated on errors in usb-serial probe. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 2cb27e49d4ac..bb2ecaf3296b 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -161,7 +161,6 @@ static int sierra_probe(struct usb_serial *serial, { int result = 0; struct usb_device *udev; - struct sierra_intf_private *data; u8 ifnum; udev = serial->dev; @@ -188,11 +187,6 @@ static int sierra_probe(struct usb_serial *serial, return -ENODEV; } - data = serial->private = kzalloc(sizeof(struct sierra_intf_private), GFP_KERNEL); - if (!data) - return -ENOMEM; - spin_lock_init(&data->susp_lock); - return result; } @@ -885,11 +879,20 @@ static void sierra_dtr_rts(struct usb_serial_port *port, int on) static int sierra_startup(struct usb_serial *serial) { struct usb_serial_port *port; + struct sierra_intf_private *intfdata; struct sierra_port_private *portdata; struct sierra_iface_info *himemoryp = NULL; int i; u8 ifnum; + intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL); + if (!intfdata) + return -ENOMEM; + + spin_lock_init(&intfdata->susp_lock); + + usb_set_serial_data(serial, intfdata); + /* Set Device mode to D0 */ sierra_set_power_state(serial->dev, 0x0000); @@ -947,6 +950,7 @@ err: portdata = usb_get_serial_port_data(serial->port[i]); kfree(portdata); } + kfree(intfdata); return -ENOMEM; } -- cgit v1.2.3-55-g7522 From f525c05babc7938cc1d4236550fd8a659fb05960 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:19 +0200 Subject: USB: sierra: fix port-data memory leak Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note also that urb-count for multi-port interfaces has not been changed even though the usb-serial port number is now determined from the port and interface minor numbers. Compile-only tested. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 125 ++++++++++++++++++++------------------------ 1 file changed, 58 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index bb2ecaf3296b..270860f6bb2a 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -878,12 +878,7 @@ static void sierra_dtr_rts(struct usb_serial_port *port, int on) static int sierra_startup(struct usb_serial *serial) { - struct usb_serial_port *port; struct sierra_intf_private *intfdata; - struct sierra_port_private *portdata; - struct sierra_iface_info *himemoryp = NULL; - int i; - u8 ifnum; intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL); if (!intfdata) @@ -900,77 +895,71 @@ static int sierra_startup(struct usb_serial *serial) if (nmea) sierra_vsc_set_nmea(serial->dev, 1); - /* Now setup per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); - if (!portdata) { - dev_dbg(&port->dev, "%s: kmalloc for " - "sierra_port_private (%d) failed!\n", - __func__, i); - goto err; - } - spin_lock_init(&portdata->lock); - init_usb_anchor(&portdata->active); - init_usb_anchor(&portdata->delayed); - ifnum = i; - /* Assume low memory requirements */ - portdata->num_out_urbs = N_OUT_URB; - portdata->num_in_urbs = N_IN_URB; - - /* Determine actual memory requirements */ - if (serial->num_ports == 1) { - /* Get interface number for composite device */ - ifnum = sierra_calc_interface(serial); - himemoryp = - (struct sierra_iface_info *)&typeB_interface_list; - if (is_himemory(ifnum, himemoryp)) { - portdata->num_out_urbs = N_OUT_URB_HM; - portdata->num_in_urbs = N_IN_URB_HM; - } - } - else { - himemoryp = - (struct sierra_iface_info *)&typeA_interface_list; - if (is_himemory(i, himemoryp)) { - portdata->num_out_urbs = N_OUT_URB_HM; - portdata->num_in_urbs = N_IN_URB_HM; - } - } - dev_dbg(&serial->dev->dev, - "Memory usage (urbs) interface #%d, in=%d, out=%d\n", - ifnum,portdata->num_in_urbs, portdata->num_out_urbs ); - /* Set the port private data pointer */ - usb_set_serial_port_data(port, portdata); + return 0; +} + +static void sierra_release(struct usb_serial *serial) +{ + struct sierra_intf_private *intfdata; + + intfdata = usb_get_serial_data(serial); + kfree(intfdata); +} + +static int sierra_port_probe(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + struct sierra_port_private *portdata; + const struct sierra_iface_info *himemoryp; + u8 ifnum; + + portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); + if (!portdata) + return -ENOMEM; + + spin_lock_init(&portdata->lock); + init_usb_anchor(&portdata->active); + init_usb_anchor(&portdata->delayed); + + /* Assume low memory requirements */ + portdata->num_out_urbs = N_OUT_URB; + portdata->num_in_urbs = N_IN_URB; + + /* Determine actual memory requirements */ + if (serial->num_ports == 1) { + /* Get interface number for composite device */ + ifnum = sierra_calc_interface(serial); + himemoryp = &typeB_interface_list; + } else { + /* This is really the usb-serial port number of the interface + * rather than the interface number. + */ + ifnum = port->number - serial->minor; + himemoryp = &typeA_interface_list; } - return 0; -err: - for (--i; i >= 0; --i) { - portdata = usb_get_serial_port_data(serial->port[i]); - kfree(portdata); + if (is_himemory(ifnum, himemoryp)) { + portdata->num_out_urbs = N_OUT_URB_HM; + portdata->num_in_urbs = N_IN_URB_HM; } - kfree(intfdata); - return -ENOMEM; + dev_dbg(&port->dev, + "Memory usage (urbs) interface #%d, in=%d, out=%d\n", + ifnum, portdata->num_in_urbs, portdata->num_out_urbs); + + usb_set_serial_port_data(port, portdata); + + return 0; } -static void sierra_release(struct usb_serial *serial) +static int sierra_port_remove(struct usb_serial_port *port) { - int i; - struct usb_serial_port *port; struct sierra_port_private *portdata; - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - if (!port) - continue; - portdata = usb_get_serial_port_data(port); - if (!portdata) - continue; - kfree(portdata); - } - kfree(serial->private); + portdata = usb_get_serial_port_data(port); + kfree(portdata); + + return 0; } #ifdef CONFIG_PM @@ -1074,6 +1063,8 @@ static struct usb_serial_driver sierra_device = { .tiocmset = sierra_tiocmset, .attach = sierra_startup, .release = sierra_release, + .port_probe = sierra_port_probe, + .port_remove = sierra_port_remove, .suspend = sierra_suspend, .resume = sierra_resume, .read_int_callback = sierra_instat_callback, -- cgit v1.2.3-55-g7522 From 65a4cdbb170e4ec1a7fa0e94936d47e24a17b0e8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 13:35:09 +0200 Subject: USB: mos7840: fix urb leak at release Make sure control urb is freed at release. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index d6d4eeca8c68..35ad3f5c4c0e 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2645,6 +2645,7 @@ static void mos7840_release(struct usb_serial *serial) del_timer_sync(&mos7840_port->led_timer1); del_timer_sync(&mos7840_port->led_timer2); } + usb_free_urb(mos7840_port->control_urb); kfree(mos7840_port->ctrl_buf); kfree(mos7840_port->dr); kfree(mos7840_port); -- cgit v1.2.3-55-g7522 From 3eb55cc4ed88eee3b5230f66abcdbd2a91639eda Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 13:35:10 +0200 Subject: USB: mos7840: fix port-device leak in error path The driver set the usb-serial port pointers to NULL on errors in attach, effectively preventing usb-serial core from decrementing the port ref counters and releasing the port devices and associated data. Cc: Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 35ad3f5c4c0e..c5e5a6c8d69e 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2587,7 +2587,6 @@ error: kfree(mos7840_port->ctrl_buf); usb_free_urb(mos7840_port->control_urb); kfree(mos7840_port); - serial->port[i] = NULL; } return status; } -- cgit v1.2.3-55-g7522 From a997448c89905b80aa4022f734f03685e733d711 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 15:42:39 +0200 Subject: USB: ipw: fix interface-data memory leak in error path Move interface data allocation to attach so that it is deallocated should usb-serial probe fail. Signed-off-by: Johan Hovold Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ipw.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index add45b7d8aa7..4264821a3b34 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -203,8 +203,7 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port) return 0; } -/* fake probe - only to allocate data structures */ -static int ipw_probe(struct usb_serial *serial, const struct usb_device_id *id) +static int ipw_attach(struct usb_serial *serial) { struct usb_wwan_intf_private *data; @@ -303,7 +302,7 @@ static struct usb_serial_driver ipw_device = { .num_ports = 1, .open = ipw_open, .close = ipw_close, - .probe = ipw_probe, + .attach = ipw_attach, .release = ipw_release, .port_probe = usb_wwan_port_probe, .port_remove = usb_wwan_port_remove, -- cgit v1.2.3-55-g7522 From c2dd4a8eac7821fed2c2d19e4607d0986b53b0fe Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 15:42:40 +0200 Subject: USB: option: fix interface-data memory leak in error path Move interface data allocation to attach so that it is deallocated should usb-serial probe fail. Note that the usb device id is stored at probe so that it can be used in attach to determine send-setup blacklisting. Signed-off-by: Johan Hovold Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index eb4bdd4a0106..5dee7d61241e 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -47,6 +47,7 @@ /* Function prototypes */ static int option_probe(struct usb_serial *serial, const struct usb_device_id *id); +static int option_attach(struct usb_serial *serial); static void option_release(struct usb_serial *serial); static int option_send_setup(struct usb_serial_port *port); static void option_instat_callback(struct urb *urb); @@ -1288,6 +1289,7 @@ static struct usb_serial_driver option_1port_device = { .tiocmget = usb_wwan_tiocmget, .tiocmset = usb_wwan_tiocmset, .ioctl = usb_wwan_ioctl, + .attach = option_attach, .release = option_release, .port_probe = usb_wwan_port_probe, .port_remove = usb_wwan_port_remove, @@ -1335,8 +1337,6 @@ static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason, static int option_probe(struct usb_serial *serial, const struct usb_device_id *id) { - struct usb_wwan_intf_private *data; - struct option_private *priv; struct usb_interface_descriptor *iface_desc = &serial->interface->cur_altsetting->desc; struct usb_device_descriptor *dev_desc = &serial->dev->descriptor; @@ -1374,6 +1374,19 @@ static int option_probe(struct usb_serial *serial, iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA) return -ENODEV; + /* Store device id so we can use it during attach. */ + usb_set_serial_data(serial, (void *)id); + + return 0; +} + +static int option_attach(struct usb_serial *serial) +{ + struct usb_interface_descriptor *iface_desc; + const struct usb_device_id *id; + struct usb_wwan_intf_private *data; + struct option_private *priv; + data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL); if (!data) return -ENOMEM; @@ -1384,6 +1397,10 @@ static int option_probe(struct usb_serial *serial, return -ENOMEM; } + /* Retrieve device id stored at probe. */ + id = usb_get_serial_data(serial); + iface_desc = &serial->interface->cur_altsetting->desc; + priv->bInterfaceNumber = iface_desc->bInterfaceNumber; data->private = priv; -- cgit v1.2.3-55-g7522 From 961be09e1ead58509ed4bed0d5819a15d8613d8d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 15:42:41 +0200 Subject: USB: qcserial: fix interface-data memory leak in error path Move interface data allocation to attach so that it is deallocated should usb-serial probe fail. Signed-off-by: Johan Hovold Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/qcserial.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 8dd2280dff63..aa148c21ea40 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -138,7 +138,6 @@ MODULE_DEVICE_TABLE(usb, id_table); static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) { - struct usb_wwan_intf_private *data; struct usb_host_interface *intf = serial->interface->cur_altsetting; struct device *dev = &serial->dev->dev; int retval = -ENODEV; @@ -154,13 +153,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) ifnum = intf->desc.bInterfaceNumber; dev_dbg(dev, "This Interface = %d\n", ifnum); - data = kzalloc(sizeof(struct usb_wwan_intf_private), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - spin_lock_init(&data->susp_lock); - if (nintf == 1) { /* QDL mode */ /* Gobi 2000 has a single altsetting, older ones have two */ @@ -253,20 +245,28 @@ done: } } - /* Set serial->private if not returning error */ - if (retval == 0) - usb_set_serial_data(serial, data); - else - kfree(data); - return retval; } +static int qc_attach(struct usb_serial *serial) +{ + struct usb_wwan_intf_private *data; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + spin_lock_init(&data->susp_lock); + + usb_set_serial_data(serial, data); + + return 0; +} + static void qc_release(struct usb_serial *serial) { struct usb_wwan_intf_private *priv = usb_get_serial_data(serial); - /* Free the private data allocated in qcprobe */ usb_set_serial_data(serial, NULL); kfree(priv); } @@ -285,6 +285,7 @@ static struct usb_serial_driver qcdevice = { .write = usb_wwan_write, .write_room = usb_wwan_write_room, .chars_in_buffer = usb_wwan_chars_in_buffer, + .attach = qc_attach, .release = qc_release, .port_probe = usb_wwan_port_probe, .port_remove = usb_wwan_port_remove, -- cgit v1.2.3-55-g7522 From 28c3ae9a8cf45f439c9a0779ebd0256e2ae72813 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 18:56:32 +0200 Subject: USB: mos7840: remove NULL-urb submission The private int_urb is never allocated so the submission from the control completion handler will always fail. Remove this odd piece of broken code. Signed-off-by: Johan Hovold Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index c5e5a6c8d69e..f2c4bb709747 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -218,7 +218,6 @@ struct moschip_port { int port_num; /*Actual port number in the device(1,2,etc) */ struct urb *write_urb; /* write URB for this port */ struct urb *read_urb; /* read URB for this port */ - struct urb *int_urb; __u8 shadowLCR; /* last LCR value received */ __u8 shadowMCR; /* last MCR value received */ char open; @@ -478,7 +477,6 @@ static void mos7840_control_callback(struct urb *urb) struct moschip_port *mos7840_port; struct device *dev = &urb->dev->dev; __u8 regval = 0x0; - int result = 0; int status = urb->status; mos7840_port = urb->context; @@ -495,7 +493,7 @@ static void mos7840_control_callback(struct urb *urb) return; default: dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status); - goto exit; + return; } dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length); @@ -508,16 +506,6 @@ static void mos7840_control_callback(struct urb *urb) mos7840_handle_new_msr(mos7840_port, regval); else if (mos7840_port->MsrLsr == 1) mos7840_handle_new_lsr(mos7840_port, regval); - -exit: - spin_lock(&mos7840_port->pool_lock); - if (!mos7840_port->zombie) - result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC); - spin_unlock(&mos7840_port->pool_lock); - if (result) { - dev_err(dev, "%s - Error %d submitting interrupt urb\n", - __func__, result); - } } static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, -- cgit v1.2.3-55-g7522 From e681b66f2e19fadbe8a7e2a17900978cb6bc921f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 18:56:33 +0200 Subject: USB: mos7840: remove invalid disconnect handling Remove private zombie flag used to signal disconnect and to prevent control urb from being submitted from interrupt urb completion handler. The control urb will not be re-submitted as both the control urb and the interrupt urb is killed on disconnect. Signed-off-by: Johan Hovold Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index f2c4bb709747..84f8c106e5e9 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -222,7 +222,6 @@ struct moschip_port { __u8 shadowMCR; /* last MCR value received */ char open; char open_ports; - char zombie; wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */ int delta_msr_cond; @@ -674,14 +673,7 @@ static void mos7840_interrupt_callback(struct urb *urb) wreg = MODEM_STATUS_REGISTER; break; } - spin_lock(&mos7840_port->pool_lock); - if (!mos7840_port->zombie) { - rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data); - } else { - spin_unlock(&mos7840_port->pool_lock); - return; - } - spin_unlock(&mos7840_port->pool_lock); + rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data); } } } @@ -2598,9 +2590,6 @@ static void mos7840_disconnect(struct usb_serial *serial) for (i = 0; i < serial->num_ports; ++i) { mos7840_port = mos7840_get_port_private(serial->port[i]); if (mos7840_port) { - spin_lock_irqsave(&mos7840_port->pool_lock, flags); - mos7840_port->zombie = 1; - spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); usb_kill_urb(mos7840_port->control_urb); } } -- cgit v1.2.3-55-g7522 From 80c00750f0c9867a65b30a17880939b6bc660a77 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 18:56:34 +0200 Subject: USB: mos7840: fix port-data memory leak Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that the indentation was kept intact using a do-while(0) in order to facilitate review. A follow-up patch will remove it. Compile-only tested. Signed-off-by: Johan Hovold Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 219 ++++++++++++++++++------------------------- 1 file changed, 89 insertions(+), 130 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 84f8c106e5e9..bc3df86134fe 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2327,49 +2327,45 @@ static int mos7840_calc_num_ports(struct usb_serial *serial) return mos7840_num_ports; } -/**************************************************************************** - * mos7840_startup - ****************************************************************************/ - -static int mos7840_startup(struct usb_serial *serial) +static int mos7840_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct moschip_port *mos7840_port; - struct usb_device *dev; - int i, status; + int status; + int pnum; __u16 Data; - dev = serial->dev; - /* we set up the pointers to the endpoints in the mos7840_open * * function, as the structures aren't created yet. */ - /* set up port private structures */ - for (i = 0; i < serial->num_ports; ++i) { - dev_dbg(&dev->dev, "mos7840_startup: configuring port %d............\n", i); + pnum = port->number - serial->minor; + + /* FIXME: remove do-while(0) loop used to keep stable patch minimal. + */ + do { + dev_dbg(&port->dev, "mos7840_startup: configuring port %d............\n", pnum); mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); if (mos7840_port == NULL) { - dev_err(&dev->dev, "%s - Out of memory\n", __func__); - status = -ENOMEM; - i--; /* don't follow NULL pointer cleaning up */ - goto error; + dev_err(&port->dev, "%s - Out of memory\n", __func__); + return -ENOMEM; } /* Initialize all port interrupt end point to port 0 int * endpoint. Our device has only one interrupt end point * common to all port */ - mos7840_port->port = serial->port[i]; - mos7840_set_port_private(serial->port[i], mos7840_port); + mos7840_port->port = port; + mos7840_set_port_private(port, mos7840_port); spin_lock_init(&mos7840_port->pool_lock); /* minor is not initialised until later by * usb-serial.c:get_free_serial() and cannot therefore be used * to index device instances */ - mos7840_port->port_num = i + 1; - dev_dbg(&dev->dev, "serial->port[i]->number = %d\n", serial->port[i]->number); - dev_dbg(&dev->dev, "serial->port[i]->serial->minor = %d\n", serial->port[i]->serial->minor); - dev_dbg(&dev->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); - dev_dbg(&dev->dev, "serial->minor = %d\n", serial->minor); + mos7840_port->port_num = pnum + 1; + dev_dbg(&port->dev, "port->number = %d\n", port->number); + dev_dbg(&port->dev, "port->serial->minor = %d\n", port->serial->minor); + dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); + dev_dbg(&port->dev, "serial->minor = %d\n", serial->minor); if (mos7840_port->port_num == 1) { mos7840_port->SpRegOffset = 0x0; @@ -2396,115 +2392,115 @@ static int mos7840_startup(struct usb_serial *serial) mos7840_port->ControlRegOffset = 0xd; mos7840_port->DcrRegOffset = 0x1c; } - mos7840_dump_serial_port(serial->port[i], mos7840_port); - mos7840_set_port_private(serial->port[i], mos7840_port); + mos7840_dump_serial_port(port, mos7840_port); + mos7840_set_port_private(port, mos7840_port); /* enable rx_disable bit in control register */ - status = mos7840_get_reg_sync(serial->port[i], + status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data); if (status < 0) { - dev_dbg(&dev->dev, "Reading ControlReg failed status-0x%x\n", status); + dev_dbg(&port->dev, "Reading ControlReg failed status-0x%x\n", status); break; } else - dev_dbg(&dev->dev, "ControlReg Reading success val is %x, status%d\n", Data, status); + dev_dbg(&port->dev, "ControlReg Reading success val is %x, status%d\n", Data, status); Data |= 0x08; /* setting driver done bit */ Data |= 0x04; /* sp1_bit to have cts change reflect in modem status reg */ /* Data |= 0x20; //rx_disable bit */ - status = mos7840_set_reg_sync(serial->port[i], + status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data); if (status < 0) { - dev_dbg(&dev->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status); + dev_dbg(&port->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status); break; } else - dev_dbg(&dev->dev, "ControlReg Writing success(rx_disable) status%d\n", status); + dev_dbg(&port->dev, "ControlReg Writing success(rx_disable) status%d\n", status); /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 and 0x24 in DCR3 */ Data = 0x01; - status = mos7840_set_reg_sync(serial->port[i], + status = mos7840_set_reg_sync(port, (__u16) (mos7840_port->DcrRegOffset + 0), Data); if (status < 0) { - dev_dbg(&dev->dev, "Writing DCR0 failed status-0x%x\n", status); + dev_dbg(&port->dev, "Writing DCR0 failed status-0x%x\n", status); break; } else - dev_dbg(&dev->dev, "DCR0 Writing success status%d\n", status); + dev_dbg(&port->dev, "DCR0 Writing success status%d\n", status); Data = 0x05; - status = mos7840_set_reg_sync(serial->port[i], + status = mos7840_set_reg_sync(port, (__u16) (mos7840_port->DcrRegOffset + 1), Data); if (status < 0) { - dev_dbg(&dev->dev, "Writing DCR1 failed status-0x%x\n", status); + dev_dbg(&port->dev, "Writing DCR1 failed status-0x%x\n", status); break; } else - dev_dbg(&dev->dev, "DCR1 Writing success status%d\n", status); + dev_dbg(&port->dev, "DCR1 Writing success status%d\n", status); Data = 0x24; - status = mos7840_set_reg_sync(serial->port[i], + status = mos7840_set_reg_sync(port, (__u16) (mos7840_port->DcrRegOffset + 2), Data); if (status < 0) { - dev_dbg(&dev->dev, "Writing DCR2 failed status-0x%x\n", status); + dev_dbg(&port->dev, "Writing DCR2 failed status-0x%x\n", status); break; } else - dev_dbg(&dev->dev, "DCR2 Writing success status%d\n", status); + dev_dbg(&port->dev, "DCR2 Writing success status%d\n", status); /* write values in clkstart0x0 and clkmulti 0x20 */ Data = 0x0; - status = mos7840_set_reg_sync(serial->port[i], + status = mos7840_set_reg_sync(port, CLK_START_VALUE_REGISTER, Data); if (status < 0) { - dev_dbg(&dev->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); + dev_dbg(&port->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); break; } else - dev_dbg(&dev->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status); + dev_dbg(&port->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status); Data = 0x20; - status = mos7840_set_reg_sync(serial->port[i], + status = mos7840_set_reg_sync(port, CLK_MULTI_REGISTER, Data); if (status < 0) { - dev_dbg(&dev->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); + dev_dbg(&port->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); goto error; } else - dev_dbg(&dev->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status); + dev_dbg(&port->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status); /* write value 0x0 to scratchpad register */ Data = 0x00; - status = mos7840_set_uart_reg(serial->port[i], + status = mos7840_set_uart_reg(port, SCRATCH_PAD_REGISTER, Data); if (status < 0) { - dev_dbg(&dev->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); + dev_dbg(&port->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); break; } else - dev_dbg(&dev->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status); + dev_dbg(&port->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status); /* Zero Length flag register */ if ((mos7840_port->port_num != 1) && (serial->num_ports == 2)) { Data = 0xff; - status = mos7840_set_reg_sync(serial->port[i], + status = mos7840_set_reg_sync(port, (__u16) (ZLP_REG1 + ((__u16)mos7840_port->port_num)), Data); - dev_dbg(&dev->dev, "ZLIP offset %x\n", + dev_dbg(&port->dev, "ZLIP offset %x\n", (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num))); if (status < 0) { - dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 2, status); + dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 2, status); break; } else - dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 2, status); + dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 2, status); } else { Data = 0xff; - status = mos7840_set_reg_sync(serial->port[i], + status = mos7840_set_reg_sync(port, (__u16) (ZLP_REG1 + ((__u16)mos7840_port->port_num) - 0x1), Data); - dev_dbg(&dev->dev, "ZLIP offset %x\n", + dev_dbg(&port->dev, "ZLIP offset %x\n", (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1)); if (status < 0) { - dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 1, status); + dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 1, status); break; } else - dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 1, status); + dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 1, status); } mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); @@ -2541,92 +2537,56 @@ static int mos7840_startup(struct usb_serial *serial) mos7840_port->led_flag = false; /* Turn off LED */ - mos7840_set_led_sync(serial->port[i], + mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300); } - } + } while (0); - /* Zero Length flag enable */ - Data = 0x0f; - status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); - if (status < 0) { - dev_dbg(&dev->dev, "Writing ZLP_REG5 failed status-0x%x\n", status); - goto error; - } else - dev_dbg(&dev->dev, "ZLP_REG5 Writing success status%d\n", status); - - /* setting configuration feature to one */ - usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, MOS_WDR_TIMEOUT); + if (pnum == serial->num_ports - 1) { + /* Zero Length flag enable */ + Data = 0x0f; + status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing ZLP_REG5 failed status-0x%x\n", status); + goto error; + } else + dev_dbg(&port->dev, "ZLP_REG5 Writing success status%d\n", status); + + /* setting configuration feature to one */ + usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + 0x03, 0x00, 0x01, 0x00, NULL, 0x00, + MOS_WDR_TIMEOUT); + } return 0; error: - for (/* nothing */; i >= 0; i--) { - mos7840_port = mos7840_get_port_private(serial->port[i]); + kfree(mos7840_port->dr); + kfree(mos7840_port->ctrl_buf); + usb_free_urb(mos7840_port->control_urb); + kfree(mos7840_port); - kfree(mos7840_port->dr); - kfree(mos7840_port->ctrl_buf); - usb_free_urb(mos7840_port->control_urb); - kfree(mos7840_port); - } return status; } -/**************************************************************************** - * mos7840_disconnect - * This function is called whenever the device is removed from the usb bus. - ****************************************************************************/ - -static void mos7840_disconnect(struct usb_serial *serial) +static int mos7840_port_remove(struct usb_serial_port *port) { - int i; - unsigned long flags; struct moschip_port *mos7840_port; - /* check for the ports to be closed,close the ports and disconnect */ + mos7840_port = mos7840_get_port_private(port); - /* free private structure allocated for serial port * - * stop reads and writes on all ports */ + if (mos7840_port->has_led) { + /* Turn off LED */ + mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300); - for (i = 0; i < serial->num_ports; ++i) { - mos7840_port = mos7840_get_port_private(serial->port[i]); - if (mos7840_port) { - usb_kill_urb(mos7840_port->control_urb); - } + del_timer_sync(&mos7840_port->led_timer1); + del_timer_sync(&mos7840_port->led_timer2); } -} - -/**************************************************************************** - * mos7840_release - * This function is called when the usb_serial structure is freed. - ****************************************************************************/ - -static void mos7840_release(struct usb_serial *serial) -{ - int i; - struct moschip_port *mos7840_port; + usb_kill_urb(mos7840_port->control_urb); + usb_free_urb(mos7840_port->control_urb); + kfree(mos7840_port->ctrl_buf); + kfree(mos7840_port->dr); + kfree(mos7840_port); - /* check for the ports to be closed,close the ports and disconnect */ - - /* free private structure allocated for serial port * - * stop reads and writes on all ports */ - - for (i = 0; i < serial->num_ports; ++i) { - mos7840_port = mos7840_get_port_private(serial->port[i]); - if (mos7840_port) { - if (mos7840_port->has_led) { - /* Turn off LED */ - mos7840_set_led_sync(mos7840_port->port, - MODEM_CONTROL_REGISTER, 0x0300); - - del_timer_sync(&mos7840_port->led_timer1); - del_timer_sync(&mos7840_port->led_timer2); - } - usb_free_urb(mos7840_port->control_urb); - kfree(mos7840_port->ctrl_buf); - kfree(mos7840_port->dr); - kfree(mos7840_port); - } - } + return 0; } static struct usb_serial_driver moschip7840_4port_device = { @@ -2654,9 +2614,8 @@ static struct usb_serial_driver moschip7840_4port_device = { .tiocmget = mos7840_tiocmget, .tiocmset = mos7840_tiocmset, .get_icount = mos7840_get_icount, - .attach = mos7840_startup, - .disconnect = mos7840_disconnect, - .release = mos7840_release, + .port_probe = mos7840_port_probe, + .port_remove = mos7840_port_remove, .read_bulk_callback = mos7840_bulk_in_callback, .read_int_callback = mos7840_interrupt_callback, }; -- cgit v1.2.3-55-g7522 From ae685effe70cbe11fc269741629022f76005ea99 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 18:56:35 +0200 Subject: USB: mos7840: fix port_probe flow Remove temporary do-while(0) loop used to keep changes minimal. Fixup indentation, remove some line breaks, and replace break with goto to maintain flow. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 349 ++++++++++++++++++++----------------------- 1 file changed, 166 insertions(+), 183 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index bc3df86134fe..1cf3375ec1af 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2340,208 +2340,191 @@ static int mos7840_port_probe(struct usb_serial_port *port) pnum = port->number - serial->minor; - /* FIXME: remove do-while(0) loop used to keep stable patch minimal. - */ - do { - dev_dbg(&port->dev, "mos7840_startup: configuring port %d............\n", pnum); - mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); - if (mos7840_port == NULL) { - dev_err(&port->dev, "%s - Out of memory\n", __func__); - return -ENOMEM; - } - - /* Initialize all port interrupt end point to port 0 int - * endpoint. Our device has only one interrupt end point - * common to all port */ - - mos7840_port->port = port; - mos7840_set_port_private(port, mos7840_port); - spin_lock_init(&mos7840_port->pool_lock); - - /* minor is not initialised until later by - * usb-serial.c:get_free_serial() and cannot therefore be used - * to index device instances */ - mos7840_port->port_num = pnum + 1; - dev_dbg(&port->dev, "port->number = %d\n", port->number); - dev_dbg(&port->dev, "port->serial->minor = %d\n", port->serial->minor); - dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); - dev_dbg(&port->dev, "serial->minor = %d\n", serial->minor); - - if (mos7840_port->port_num == 1) { - mos7840_port->SpRegOffset = 0x0; - mos7840_port->ControlRegOffset = 0x1; - mos7840_port->DcrRegOffset = 0x4; - } else if ((mos7840_port->port_num == 2) - && (serial->num_ports == 4)) { - mos7840_port->SpRegOffset = 0x8; - mos7840_port->ControlRegOffset = 0x9; - mos7840_port->DcrRegOffset = 0x16; - } else if ((mos7840_port->port_num == 2) - && (serial->num_ports == 2)) { - mos7840_port->SpRegOffset = 0xa; - mos7840_port->ControlRegOffset = 0xb; - mos7840_port->DcrRegOffset = 0x19; - } else if ((mos7840_port->port_num == 3) - && (serial->num_ports == 4)) { - mos7840_port->SpRegOffset = 0xa; - mos7840_port->ControlRegOffset = 0xb; - mos7840_port->DcrRegOffset = 0x19; - } else if ((mos7840_port->port_num == 4) - && (serial->num_ports == 4)) { - mos7840_port->SpRegOffset = 0xc; - mos7840_port->ControlRegOffset = 0xd; - mos7840_port->DcrRegOffset = 0x1c; - } - mos7840_dump_serial_port(port, mos7840_port); - mos7840_set_port_private(port, mos7840_port); + dev_dbg(&port->dev, "mos7840_startup: configuring port %d\n", pnum); + mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); + if (mos7840_port == NULL) { + dev_err(&port->dev, "%s - Out of memory\n", __func__); + return -ENOMEM; + } - /* enable rx_disable bit in control register */ - status = mos7840_get_reg_sync(port, - mos7840_port->ControlRegOffset, &Data); - if (status < 0) { - dev_dbg(&port->dev, "Reading ControlReg failed status-0x%x\n", status); - break; - } else - dev_dbg(&port->dev, "ControlReg Reading success val is %x, status%d\n", Data, status); - Data |= 0x08; /* setting driver done bit */ - Data |= 0x04; /* sp1_bit to have cts change reflect in - modem status reg */ + /* Initialize all port interrupt end point to port 0 int + * endpoint. Our device has only one interrupt end point + * common to all port */ + + mos7840_port->port = port; + mos7840_set_port_private(port, mos7840_port); + spin_lock_init(&mos7840_port->pool_lock); + + /* minor is not initialised until later by + * usb-serial.c:get_free_serial() and cannot therefore be used + * to index device instances */ + mos7840_port->port_num = pnum + 1; + dev_dbg(&port->dev, "port->number = %d\n", port->number); + dev_dbg(&port->dev, "port->serial->minor = %d\n", port->serial->minor); + dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); + dev_dbg(&port->dev, "serial->minor = %d\n", serial->minor); + + if (mos7840_port->port_num == 1) { + mos7840_port->SpRegOffset = 0x0; + mos7840_port->ControlRegOffset = 0x1; + mos7840_port->DcrRegOffset = 0x4; + } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 4)) { + mos7840_port->SpRegOffset = 0x8; + mos7840_port->ControlRegOffset = 0x9; + mos7840_port->DcrRegOffset = 0x16; + } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 2)) { + mos7840_port->SpRegOffset = 0xa; + mos7840_port->ControlRegOffset = 0xb; + mos7840_port->DcrRegOffset = 0x19; + } else if ((mos7840_port->port_num == 3) && (serial->num_ports == 4)) { + mos7840_port->SpRegOffset = 0xa; + mos7840_port->ControlRegOffset = 0xb; + mos7840_port->DcrRegOffset = 0x19; + } else if ((mos7840_port->port_num == 4) && (serial->num_ports == 4)) { + mos7840_port->SpRegOffset = 0xc; + mos7840_port->ControlRegOffset = 0xd; + mos7840_port->DcrRegOffset = 0x1c; + } + mos7840_dump_serial_port(port, mos7840_port); + mos7840_set_port_private(port, mos7840_port); + + /* enable rx_disable bit in control register */ + status = mos7840_get_reg_sync(port, + mos7840_port->ControlRegOffset, &Data); + if (status < 0) { + dev_dbg(&port->dev, "Reading ControlReg failed status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "ControlReg Reading success val is %x, status%d\n", Data, status); + Data |= 0x08; /* setting driver done bit */ + Data |= 0x04; /* sp1_bit to have cts change reflect in + modem status reg */ + + /* Data |= 0x20; //rx_disable bit */ + status = mos7840_set_reg_sync(port, + mos7840_port->ControlRegOffset, Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "ControlReg Writing success(rx_disable) status%d\n", status); + + /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 + and 0x24 in DCR3 */ + Data = 0x01; + status = mos7840_set_reg_sync(port, + (__u16) (mos7840_port->DcrRegOffset + 0), Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing DCR0 failed status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "DCR0 Writing success status%d\n", status); - /* Data |= 0x20; //rx_disable bit */ - status = mos7840_set_reg_sync(port, - mos7840_port->ControlRegOffset, Data); - if (status < 0) { - dev_dbg(&port->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status); - break; - } else - dev_dbg(&port->dev, "ControlReg Writing success(rx_disable) status%d\n", status); + Data = 0x05; + status = mos7840_set_reg_sync(port, + (__u16) (mos7840_port->DcrRegOffset + 1), Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing DCR1 failed status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "DCR1 Writing success status%d\n", status); - /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 - and 0x24 in DCR3 */ - Data = 0x01; - status = mos7840_set_reg_sync(port, - (__u16) (mos7840_port->DcrRegOffset + 0), Data); - if (status < 0) { - dev_dbg(&port->dev, "Writing DCR0 failed status-0x%x\n", status); - break; - } else - dev_dbg(&port->dev, "DCR0 Writing success status%d\n", status); + Data = 0x24; + status = mos7840_set_reg_sync(port, + (__u16) (mos7840_port->DcrRegOffset + 2), Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing DCR2 failed status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "DCR2 Writing success status%d\n", status); - Data = 0x05; - status = mos7840_set_reg_sync(port, - (__u16) (mos7840_port->DcrRegOffset + 1), Data); - if (status < 0) { - dev_dbg(&port->dev, "Writing DCR1 failed status-0x%x\n", status); - break; - } else - dev_dbg(&port->dev, "DCR1 Writing success status%d\n", status); + /* write values in clkstart0x0 and clkmulti 0x20 */ + Data = 0x0; + status = mos7840_set_reg_sync(port, CLK_START_VALUE_REGISTER, Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status); - Data = 0x24; - status = mos7840_set_reg_sync(port, - (__u16) (mos7840_port->DcrRegOffset + 2), Data); - if (status < 0) { - dev_dbg(&port->dev, "Writing DCR2 failed status-0x%x\n", status); - break; - } else - dev_dbg(&port->dev, "DCR2 Writing success status%d\n", status); + Data = 0x20; + status = mos7840_set_reg_sync(port, CLK_MULTI_REGISTER, Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); + goto error; + } else + dev_dbg(&port->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status); - /* write values in clkstart0x0 and clkmulti 0x20 */ - Data = 0x0; + /* write value 0x0 to scratchpad register */ + Data = 0x00; + status = mos7840_set_uart_reg(port, SCRATCH_PAD_REGISTER, Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status); + + /* Zero Length flag register */ + if ((mos7840_port->port_num != 1) && (serial->num_ports == 2)) { + Data = 0xff; status = mos7840_set_reg_sync(port, - CLK_START_VALUE_REGISTER, Data); + (__u16) (ZLP_REG1 + + ((__u16)mos7840_port->port_num)), Data); + dev_dbg(&port->dev, "ZLIP offset %x\n", + (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num))); if (status < 0) { - dev_dbg(&port->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); - break; + dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 2, status); + goto out; } else - dev_dbg(&port->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status); - - Data = 0x20; + dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 2, status); + } else { + Data = 0xff; status = mos7840_set_reg_sync(port, - CLK_MULTI_REGISTER, Data); - if (status < 0) { - dev_dbg(&port->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); - goto error; - } else - dev_dbg(&port->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status); - - /* write value 0x0 to scratchpad register */ - Data = 0x00; - status = mos7840_set_uart_reg(port, - SCRATCH_PAD_REGISTER, Data); + (__u16) (ZLP_REG1 + + ((__u16)mos7840_port->port_num) - 0x1), Data); + dev_dbg(&port->dev, "ZLIP offset %x\n", + (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1)); if (status < 0) { - dev_dbg(&port->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); - break; + dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 1, status); + goto out; } else - dev_dbg(&port->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status); + dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 1, status); - /* Zero Length flag register */ - if ((mos7840_port->port_num != 1) - && (serial->num_ports == 2)) { - - Data = 0xff; - status = mos7840_set_reg_sync(port, - (__u16) (ZLP_REG1 + - ((__u16)mos7840_port->port_num)), Data); - dev_dbg(&port->dev, "ZLIP offset %x\n", - (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num))); - if (status < 0) { - dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 2, status); - break; - } else - dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 2, status); - } else { - Data = 0xff; - status = mos7840_set_reg_sync(port, - (__u16) (ZLP_REG1 + - ((__u16)mos7840_port->port_num) - 0x1), Data); - dev_dbg(&port->dev, "ZLIP offset %x\n", - (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1)); - if (status < 0) { - dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 1, status); - break; - } else - dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 1, status); - - } - mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); - mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); - mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), - GFP_KERNEL); - if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || - !mos7840_port->dr) { - status = -ENOMEM; - goto error; - } - - mos7840_port->has_led = false; + } + mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); + mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); + mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), + GFP_KERNEL); + if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || + !mos7840_port->dr) { + status = -ENOMEM; + goto error; + } - /* Initialize LED timers */ - if (device_type == MOSCHIP_DEVICE_ID_7810) { - mos7840_port->has_led = true; + mos7840_port->has_led = false; - init_timer(&mos7840_port->led_timer1); - mos7840_port->led_timer1.function = mos7840_led_off; - mos7840_port->led_timer1.expires = - jiffies + msecs_to_jiffies(LED_ON_MS); - mos7840_port->led_timer1.data = - (unsigned long)mos7840_port; + /* Initialize LED timers */ + if (device_type == MOSCHIP_DEVICE_ID_7810) { + mos7840_port->has_led = true; - init_timer(&mos7840_port->led_timer2); - mos7840_port->led_timer2.function = - mos7840_led_flag_off; - mos7840_port->led_timer2.expires = - jiffies + msecs_to_jiffies(LED_OFF_MS); - mos7840_port->led_timer2.data = - (unsigned long)mos7840_port; + init_timer(&mos7840_port->led_timer1); + mos7840_port->led_timer1.function = mos7840_led_off; + mos7840_port->led_timer1.expires = + jiffies + msecs_to_jiffies(LED_ON_MS); + mos7840_port->led_timer1.data = (unsigned long)mos7840_port; - mos7840_port->led_flag = false; + init_timer(&mos7840_port->led_timer2); + mos7840_port->led_timer2.function = mos7840_led_flag_off; + mos7840_port->led_timer2.expires = + jiffies + msecs_to_jiffies(LED_OFF_MS); + mos7840_port->led_timer2.data = (unsigned long)mos7840_port; - /* Turn off LED */ - mos7840_set_led_sync(port, - MODEM_CONTROL_REGISTER, 0x0300); - } - } while (0); + mos7840_port->led_flag = false; + /* Turn off LED */ + mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300); + } +out: if (pnum == serial->num_ports - 1) { /* Zero Length flag enable */ Data = 0x0f; -- cgit v1.2.3-55-g7522 From c323dc023b9501e5d09582ec7efd1d40a9001d99 Mon Sep 17 00:00:00 2001 From: Anisse Astier Date: Tue, 9 Oct 2012 12:22:36 +0200 Subject: ehci: fix Lucid nohandoff pci quirk to be more generic with BIOS versions BIOS vendors keep changing the BIOS versions. Only match the beginning of the string to match all Lucid tablets with board name M11JB. Signed-off-by: Anisse Astier Cc: Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/pci-quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 966d1484ee79..ead45259bf15 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -545,7 +545,7 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = { /* Pegatron Lucid (Ordissimo AIRIS) */ .matches = { DMI_MATCH(DMI_BOARD_NAME, "M11JB"), - DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"), + DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), }, }, { } -- cgit v1.2.3-55-g7522 From 8daf8b6086f9d575200cd0aa3797e26137255609 Mon Sep 17 00:00:00 2001 From: Anisse Astier Date: Tue, 9 Oct 2012 12:22:37 +0200 Subject: ehci: Add yet-another Lucid nohandoff pci quirk Board name changed on another shipping Lucid tablet. Signed-off-by: Anisse Astier Cc: Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/pci-quirks.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index ead45259bf15..39f9e4a9a2d3 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -548,6 +548,13 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = { DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), }, }, + { + /* Pegatron Lucid (Ordissimo) */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "Ordissimo"), + DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), + }, + }, { } }; -- cgit v1.2.3-55-g7522 From 2cb55a2f47a3c695a0105b7fc04a3b70c3bc4e4f Mon Sep 17 00:00:00 2001 From: Yuanhan Liu Date: Tue, 16 Oct 2012 22:59:04 +0800 Subject: sonypi: suspend/resume callbacks should be conditionally compiled on CONFIG_PM_SLEEP This will fix warnings like following when CONFIG_PM_SLEEP is not set: warning: 'xxx_suspend' defined but not used [-Wunused-function] warning: 'xxx_resume' defined but not used [-Wunused-function] Because SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) Only references the callbacks on CONFIG_PM_SLEEP (instead of CONFIG_PM). Cc: Mattia Dongili Cc: Arnd Bergmann Cc: platform-driver-x86@vger.kernel.org Signed-off-by: Yuanhan Liu Signed-off-by: Fengguang Wu Signed-off-by: Greg Kroah-Hartman --- drivers/char/sonypi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 320debbe32fa..9b4f0116ff21 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -1456,7 +1456,7 @@ static int __devexit sonypi_remove(struct platform_device *dev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int old_camera_power; static int sonypi_suspend(struct device *dev) -- cgit v1.2.3-55-g7522 From 43a09f7fb01fa1e091416a2aa49b6c666458c1ee Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 16 Oct 2012 13:17:43 -0700 Subject: xhci: Fix potential NULL ptr deref in command cancellation. The command cancellation code doesn't check whether find_trb_seg() couldn't find the segment that contains the TRB to be canceled. This could cause a NULL pointer deference later in the function when next_trb is called. It's unlikely to happen unless something is wrong with the command ring pointers, so add some debugging in case it happens. This patch should be backported to stable kernels as old as 3.0, that contain the commit b63f4053cc8aa22a98e3f9a97845afe6c15d0a0d "xHCI: handle command after aborting the command ring". Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/host/xhci-ring.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index c6ebb176dc4f..4e1a8946b8d1 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1228,6 +1228,17 @@ static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd) cur_seg = find_trb_seg(xhci->cmd_ring->first_seg, xhci->cmd_ring->dequeue, &cycle_state); + if (!cur_seg) { + xhci_warn(xhci, "Command ring mismatch, dequeue = %p %llx (dma)\n", + xhci->cmd_ring->dequeue, + (unsigned long long) + xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, + xhci->cmd_ring->dequeue)); + xhci_debug_ring(xhci, xhci->cmd_ring); + xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring); + return; + } + /* find the command trb matched by cd from command ring */ for (cmd_trb = xhci->cmd_ring->dequeue; cmd_trb != xhci->cmd_ring->enqueue; -- cgit v1.2.3-55-g7522 From b80313422a1551cc1d4f3e2d532fe633154ae5dd Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 16 Oct 2012 13:26:22 -0700 Subject: xhci: Fix missing break in xhci_evaluate_context_result. Coverity complains that xhci_evaluate_context_result() is missing a break statement after the COMP_EBADSLT switch case. It's not a big deal, since we wanted to return the same error code as the case statement below it does. The end result would be one that a Slot Disabled error completion code would also print the warning message associated with a Context State error code. No other bad behavior would result. It's not worth backporting to stable kernels, since it only fixes an issue with too much debugging. Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 9ec939646b42..ffe2e2e5c6ab 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1817,6 +1817,8 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci, case COMP_EBADSLT: dev_warn(&udev->dev, "WARN: slot not enabled for" "evaluate context command.\n"); + ret = -EINVAL; + break; case COMP_CTX_STATE: dev_warn(&udev->dev, "WARN: invalid context state for " "evaluate context command.\n"); -- cgit v1.2.3-55-g7522 From 7e5f77f9bc30cb5338802df184b26d1365afca09 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 16 Oct 2012 13:33:45 -0700 Subject: xhci: trivial: Remove assigned but unused slot_ctx. Remove the variable slot_ctx from xhci_dbg_ctx(), since it is assigned but unused. Caught by Coverity. Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-dbg.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index 4b436f5a4171..5f3a7c74aa8d 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -544,7 +544,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci, int i; /* Fields are 32 bits wide, DMA addresses are in bytes */ int field_size = 32 / 8; - struct xhci_slot_ctx *slot_ctx; dma_addr_t dma = ctx->dma; int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params); @@ -570,7 +569,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci, dbg_rsvd64(xhci, (u64 *)ctrl_ctx, dma); } - slot_ctx = xhci_get_slot_ctx(xhci, ctx); xhci_dbg_slot_ctx(xhci, ctx); xhci_dbg_ep_ctx(xhci, ctx, last_ep); } -- cgit v1.2.3-55-g7522 From df0379065b3850cd42447b59578a2f9362047487 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 16 Oct 2012 13:33:45 -0700 Subject: xhci: trivial: Remove assigned but unused ep_ctx. Remove the variable ep_ctx from xhci_add_endpoint(), since it is assigned but unused. Caught by Coverity. Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index ffe2e2e5c6ab..c9e419f29b74 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1627,7 +1627,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct xhci_hcd *xhci; struct xhci_container_ctx *in_ctx, *out_ctx; unsigned int ep_index; - struct xhci_ep_ctx *ep_ctx; struct xhci_slot_ctx *slot_ctx; struct xhci_input_control_ctx *ctrl_ctx; u32 added_ctxs; @@ -1663,7 +1662,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, out_ctx = virt_dev->out_ctx; ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); ep_index = xhci_get_endpoint_index(&ep->desc); - ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); /* If this endpoint is already in use, and the upper layers are trying * to add it again without dropping it, reject the addition. -- cgit v1.2.3-55-g7522 From fd6de5300e6fcad5621ef7e78eb227de9d4c8b79 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 25 Oct 2012 13:37:48 -0700 Subject: backlight: ili9320: add missing SPI dependency Add this missing SPI dependency and prevent the driver from building without SPI, because functions of the spi driver are used in this driver. drivers/video/backlight/ili9320.c:51: undefined reference to `spi_sync' Also, a prompt string for CONFIG_LCD_ILI9320 is added for explicit selection. Signed-off-by: Jingoo Han Cc: Richard Purdie Cc: Ben Dooks Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index c101697a4ba7..765a945f8ea1 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -60,7 +60,8 @@ config LCD_LTV350QV The LTV350QV panel is present on all ATSTK1000 boards. config LCD_ILI9320 - tristate + tristate "ILI Technology ILI9320 controller support" + depends on SPI help If you have a panel based on the ILI9320 controller chip then say y to include a power driver for it. -- cgit v1.2.3-55-g7522 From d5ea7b5ec1ee4dac868143806c0bd94855754677 Mon Sep 17 00:00:00 2001 From: Hein Tibosch Date: Thu, 25 Oct 2012 13:38:05 -0700 Subject: drivers/dma/dw_dmac: make driver's endianness configurable The dw_dmac driver was originally developed for avr32 to be used with the Synopsys DesignWare AHB DMA controller. Starting from 2.6.38, access to the device's i/o memory was done with the little-endian readl/writel functions(1) This broke the driver for the avr32 platform, because it needs big (native) endian accessors. This patch makes the endianness configurable using 'DW_DMAC_BIG_ENDIAN_IO', which will default be true for AVR32 I submitted this patch before(2) but then waited for Andy to finish other changes to the same module(3). (1) https://patchwork.kernel.org/patch/608211 (2) https://lkml.org/lkml/2012/8/26/148 (3) https://lkml.org/lkml/2012/9/21/173 Signed-off-by: Hein Tibosch Acked-by: Arnd Bergmann Cc: Andy Shevchenko Acked-by: Viresh Kumar Cc: Hans-Christian Egtvedt Cc: Ludovic Desroches Cc: Havard Skinnemoen Cc: Nicolas Ferre Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/dma/Kconfig | 11 +++++++++++ drivers/dma/dw_dmac_regs.h | 18 +++++++++++++----- 2 files changed, 24 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 677cd6e4e1a1..d4c12180c654 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -90,6 +90,17 @@ config DW_DMAC Support the Synopsys DesignWare AHB DMA controller. This can be integrated in chips such as the Atmel AT32ap7000. +config DW_DMAC_BIG_ENDIAN_IO + bool "Use big endian I/O register access" + default y if AVR32 + depends on DW_DMAC + help + Say yes here to use big endian I/O access when reading and writing + to the DMA controller registers. This is needed on some platforms, + like the Atmel AVR32 architecture. + + If unsure, use the default setting. + config AT_HDMAC tristate "Atmel AHB DMA support" depends on ARCH_AT91 diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h index ff39fa6cd2bc..88965597b7d0 100644 --- a/drivers/dma/dw_dmac_regs.h +++ b/drivers/dma/dw_dmac_regs.h @@ -98,9 +98,17 @@ struct dw_dma_regs { u32 DW_PARAMS; }; +#ifdef CONFIG_DW_DMAC_BIG_ENDIAN_IO +#define dma_readl_native ioread32be +#define dma_writel_native iowrite32be +#else +#define dma_readl_native readl +#define dma_writel_native writel +#endif + /* To access the registers in early stage of probe */ #define dma_read_byaddr(addr, name) \ - readl((addr) + offsetof(struct dw_dma_regs, name)) + dma_readl_native((addr) + offsetof(struct dw_dma_regs, name)) /* Bitfields in DW_PARAMS */ #define DW_PARAMS_NR_CHAN 8 /* number of channels */ @@ -216,9 +224,9 @@ __dwc_regs(struct dw_dma_chan *dwc) } #define channel_readl(dwc, name) \ - readl(&(__dwc_regs(dwc)->name)) + dma_readl_native(&(__dwc_regs(dwc)->name)) #define channel_writel(dwc, name, val) \ - writel((val), &(__dwc_regs(dwc)->name)) + dma_writel_native((val), &(__dwc_regs(dwc)->name)) static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan) { @@ -246,9 +254,9 @@ static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw) } #define dma_readl(dw, name) \ - readl(&(__dw_regs(dw)->name)) + dma_readl_native(&(__dw_regs(dw)->name)) #define dma_writel(dw, name, val) \ - writel((val), &(__dw_regs(dw)->name)) + dma_writel_native((val), &(__dw_regs(dw)->name)) #define channel_set_bit(dw, reg, mask) \ dma_writel(dw, reg, ((mask) << 8) | (mask)) -- cgit v1.2.3-55-g7522 From fee0de7791f967c2c5f0d43eb7b7261761b45e64 Mon Sep 17 00:00:00 2001 From: Jan Luebbe Date: Thu, 25 Oct 2012 13:38:11 -0700 Subject: drivers/rtc/rtc-imxdi.c: add missing spin lock initialization Signed-off-by: Jan Luebbe Cc: Alessandro Zummo Cc: Roland Stigge Cc: Grant Likely Tested-by: Roland Stigge Cc: Sascha Hauer Cc: Russell King Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-imxdi.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index 891cd6c61d0a..4eed51044c5d 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c @@ -392,6 +392,8 @@ static int dryice_rtc_probe(struct platform_device *pdev) if (imxdi->ioaddr == NULL) return -ENOMEM; + spin_lock_init(&imxdi->irq_lock); + imxdi->irq = platform_get_irq(pdev, 0); if (imxdi->irq < 0) return imxdi->irq; -- cgit v1.2.3-55-g7522 From aea2bf6a57a9e4596bfad164f986ba10ddc6adf3 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Sun, 21 Oct 2012 00:38:03 -0700 Subject: Input: wacom - handle split-sensor devices with internal hubs Like our other pen-and-touch products, the Cintiq 24HD touch needs data to be shared between its two sensors to facilitate proximity-based palm rejection. Unlike other tablets that report sensor data through separate interfaces of the same USB device, the Cintiq 24HD touch has separate USB devices that are connected to an internal USB hub. This patch makes it possible to designate the USB VID/PID of the other device so that the two may share data. To ensure we don't accidentally link to a sensor from a physically separate device (if several have been plugged in), we limit the search to siblings (i.e., devices directly connected to the same hub). Signed-off-by: Jason Gerecke Signed-off-by: Dmitry Torokhov Signed-off-by: Linus Torvalds --- drivers/input/tablet/wacom_sys.c | 32 +++++++++++++++++++++++++++++++- drivers/input/tablet/wacom_wac.c | 3 ++- drivers/input/tablet/wacom_wac.h | 2 ++ 3 files changed, 35 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 9edf9806cff9..8b89e15bcf32 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -613,6 +613,30 @@ struct wacom_usbdev_data { static LIST_HEAD(wacom_udev_list); static DEFINE_MUTEX(wacom_udev_list_lock); +static struct usb_device *wacom_get_sibling(struct usb_device *dev, int vendor, int product) +{ + int port1; + struct usb_device *sibling; + + if (vendor == 0 && product == 0) + return dev; + + if (dev->parent == NULL) + return NULL; + + usb_hub_for_each_child(dev->parent, port1, sibling) { + struct usb_device_descriptor *d; + if (sibling == NULL) + continue; + + d = &sibling->descriptor; + if (d->idVendor == vendor && d->idProduct == product) + return sibling; + } + + return NULL; +} + static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev) { struct wacom_usbdev_data *data; @@ -1257,13 +1281,19 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); if (features->quirks & WACOM_QUIRK_MULTI_INPUT) { + struct usb_device *other_dev; + /* Append the device type to the name */ strlcat(wacom_wac->name, features->device_type == BTN_TOOL_PEN ? " Pen" : " Finger", sizeof(wacom_wac->name)); - error = wacom_add_shared_data(wacom_wac, dev); + + other_dev = wacom_get_sibling(dev, features->oVid, features->oPid); + if (other_dev == NULL || wacom_get_usbdev_data(other_dev) == NULL) + other_dev = dev; + error = wacom_add_shared_data(wacom_wac, other_dev); if (error) goto fail3; } diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index c3468c8dbd89..21d1f4eaff53 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1340,7 +1340,8 @@ void wacom_setup_device_quirks(struct wacom_features *features) /* these device have multiple inputs */ if (features->type >= WIRELESS || - (features->type >= INTUOS5S && features->type <= INTUOS5L)) + (features->type >= INTUOS5S && features->type <= INTUOS5L) || + (features->oVid && features->oPid)) features->quirks |= WACOM_QUIRK_MULTI_INPUT; /* quirk for bamboo touch with 2 low res touches */ diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 96c185cc301e..3f926ec19ef9 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -109,6 +109,8 @@ struct wacom_features { int distance_fuzz; unsigned quirks; unsigned touch_max; + int oVid; + int oPid; }; struct wacom_shared { -- cgit v1.2.3-55-g7522 From b1e4279e4ef5549bf6ebf8f6f17dd26f0af8e8a2 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Sun, 21 Oct 2012 00:38:04 -0700 Subject: Input: wacom - add touch sensor support for Cintiq 24HD touch Decode multitouch reports from the touch sensor of the Cintiq 24HD touch. Signed-off-by: Jason Gerecke Signed-off-by: Dmitry Torokhov Signed-off-by: Linus Torvalds --- drivers/input/tablet/wacom_sys.c | 19 ++++++++- drivers/input/tablet/wacom_wac.c | 85 +++++++++++++++++++++++++++++++++++++++- drivers/input/tablet/wacom_wac.h | 3 ++ 3 files changed, 104 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 8b89e15bcf32..2c1e12bf2ab4 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -391,7 +391,7 @@ static int wacom_parse_hid(struct usb_interface *intf, features->pktlen = WACOM_PKGLEN_TPC2FG; } - if (features->type == MTSCREEN) + if (features->type == MTSCREEN || WACOM_24HDT) features->pktlen = WACOM_PKGLEN_MTOUCH; if (features->type == BAMBOO_PT) { @@ -402,6 +402,14 @@ static int wacom_parse_hid(struct usb_interface *intf, features->x_max = get_unaligned_le16(&report[i + 8]); i += 15; + } else if (features->type == WACOM_24HDT) { + features->x_max = + get_unaligned_le16(&report[i + 3]); + features->x_phy = + get_unaligned_le16(&report[i + 8]); + features->unit = report[i - 1]; + features->unitExpo = report[i - 3]; + i += 12; } else { features->x_max = get_unaligned_le16(&report[i + 3]); @@ -434,6 +442,12 @@ static int wacom_parse_hid(struct usb_interface *intf, features->y_phy = get_unaligned_le16(&report[i + 6]); i += 7; + } else if (type == WACOM_24HDT) { + features->y_max = + get_unaligned_le16(&report[i + 3]); + features->y_phy = + get_unaligned_le16(&report[i - 2]); + i += 7; } else if (type == BAMBOO_PT) { features->y_phy = get_unaligned_le16(&report[i + 3]); @@ -541,6 +555,9 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat /* MT Tablet PC touch */ return wacom_set_device_mode(intf, 3, 4, 4); } + else if (features->type == WACOM_24HDT) { + return wacom_set_device_mode(intf, 18, 3, 2); + } } else if (features->device_type == BTN_TOOL_PEN) { if (features->type <= BAMBOO_PT && features->type != WIRELESS) { return wacom_set_device_mode(intf, 2, 2, 2); diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 21d1f4eaff53..aa6010131179 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -806,6 +806,70 @@ static int find_slot_from_contactid(struct wacom_wac *wacom, int contactid) return -1; } +static int int_dist(int x1, int y1, int x2, int y2) +{ + int x = x2 - x1; + int y = y2 - y1; + + return int_sqrt(x*x + y*y); +} + +static int wacom_24hdt_irq(struct wacom_wac *wacom) +{ + struct input_dev *input = wacom->input; + char *data = wacom->data; + int i; + int current_num_contacts = data[61]; + int contacts_to_send = 0; + + /* + * First packet resets the counter since only the first + * packet in series will have non-zero current_num_contacts. + */ + if (current_num_contacts) + wacom->num_contacts_left = current_num_contacts; + + /* There are at most 4 contacts per packet */ + contacts_to_send = min(4, wacom->num_contacts_left); + + for (i = 0; i < contacts_to_send; i++) { + int offset = (WACOM_BYTES_PER_24HDT_PACKET * i) + 1; + bool touch = data[offset] & 0x1 && !wacom->shared->stylus_in_proximity; + int id = data[offset + 1]; + int slot = find_slot_from_contactid(wacom, id); + + if (slot < 0) + continue; + input_mt_slot(input, slot); + input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); + + if (touch) { + int t_x = le16_to_cpup((__le16 *)&data[offset + 2]); + int c_x = le16_to_cpup((__le16 *)&data[offset + 4]); + int t_y = le16_to_cpup((__le16 *)&data[offset + 6]); + int c_y = le16_to_cpup((__le16 *)&data[offset + 8]); + int w = le16_to_cpup((__le16 *)&data[offset + 10]); + int h = le16_to_cpup((__le16 *)&data[offset + 12]); + + input_report_abs(input, ABS_MT_POSITION_X, t_x); + input_report_abs(input, ABS_MT_POSITION_Y, t_y); + input_report_abs(input, ABS_MT_TOUCH_MAJOR, min(w,h)); + input_report_abs(input, ABS_MT_WIDTH_MAJOR, min(w, h) + int_dist(t_x, t_y, c_x, c_y)); + input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h)); + input_report_abs(input, ABS_MT_ORIENTATION, w > h); + } + wacom->slots[slot] = touch ? id : -1; + } + + input_mt_report_pointer_emulation(input, true); + + wacom->num_contacts_left -= contacts_to_send; + if (wacom->num_contacts_left <= 0) + wacom->num_contacts_left = 0; + + return 1; +} + static int wacom_mt_touch(struct wacom_wac *wacom) { struct input_dev *input = wacom->input; @@ -1255,6 +1319,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) sync = wacom_intuos_irq(wacom_wac); break; + case WACOM_24HDT: + sync = wacom_24hdt_irq(wacom_wac); + break; + case INTUOS5S: case INTUOS5: case INTUOS5L: @@ -1576,6 +1644,15 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, __set_bit(INPUT_PROP_POINTER, input_dev->propbit); break; + case WACOM_24HDT: + if (features->device_type == BTN_TOOL_FINGER) { + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, features->x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, 0, features->y_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); + } + /* fall through */ + case MTSCREEN: if (features->device_type == BTN_TOOL_FINGER) { wacom_wac->slots = kmalloc(features->touch_max * @@ -1870,8 +1947,11 @@ static const struct wacom_features wacom_features_0xF4 = { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xF8 = - { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, - 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, /* Pen */ + 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 }; +static const struct wacom_features wacom_features_0xF6 = + { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */ + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10 }; static const struct wacom_features wacom_features_0x3F = { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, 63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; @@ -2114,6 +2194,7 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x47) }, { USB_DEVICE_WACOM(0xF4) }, { USB_DEVICE_WACOM(0xF8) }, + { USB_DEVICE_WACOM(0xF6) }, { USB_DEVICE_WACOM(0xFA) }, { USB_DEVICE_LENOVO(0x6004) }, { } diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 3f926ec19ef9..345f1e76975e 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -29,6 +29,7 @@ /* wacom data size per MT contact */ #define WACOM_BYTES_PER_MT_PACKET 11 +#define WACOM_BYTES_PER_24HDT_PACKET 14 /* device IDs */ #define STYLUS_DEVICE_ID 0x02 @@ -49,6 +50,7 @@ #define WACOM_REPORT_TPCHID 15 #define WACOM_REPORT_TPCST 16 #define WACOM_REPORT_TPC1FGE 18 +#define WACOM_REPORT_24HDT 1 /* device quirks */ #define WACOM_QUIRK_MULTI_INPUT 0x0001 @@ -81,6 +83,7 @@ enum { WACOM_MO, WIRELESS, BAMBOO_PT, + WACOM_24HDT, TABLETPC, /* add new TPC below */ TABLETPCE, TABLETPC2FG, -- cgit v1.2.3-55-g7522 From 879dca019dc43a1622edca3e7dde644b14b5acc5 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 26 Oct 2012 01:05:56 +0200 Subject: ACPI: missing break We handle NOTIFY_THROTTLING so don't then fall through to unsupported event. Signed-off-by: Alan Cox Signed-off-by: Rafael J. Wysocki --- drivers/acpi/processor_driver.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index e78c2a52ea46..bd4e5dca3ff7 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -409,6 +409,7 @@ static void acpi_processor_notify(struct acpi_device *device, u32 event) acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, dev_name(&device->dev), event, 0); + break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); -- cgit v1.2.3-55-g7522 From c6fdd8e5d0c65bb8821dc6da26ee1a2ddd58b3cc Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Wed, 24 Oct 2012 08:44:32 +0000 Subject: bas_gigaset: fix pre_reset handling The delayed work function int_in_work() may call usb_reset_device() and thus, indirectly, the driver's pre_reset method. Trying to cancel the work synchronously in that situation would deadlock. Fix by avoiding cancel_work_sync() in the pre_reset method. If the reset was NOT initiated by int_in_work() this might cause int_in_work() to run after the post_reset method, with urb_int_in already resubmitted, so handle that case gracefully. Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/bas-gigaset.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 527588708948..c44950d3eb7b 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -617,7 +617,13 @@ static void int_in_work(struct work_struct *work) if (rc == 0) /* success, resubmit interrupt read URB */ rc = usb_submit_urb(urb, GFP_ATOMIC); - if (rc != 0 && rc != -ENODEV) { + + switch (rc) { + case 0: /* success */ + case -ENODEV: /* device gone */ + case -EINVAL: /* URB already resubmitted, or terminal badness */ + break; + default: /* failure: try to recover by resetting the device */ dev_err(cs->dev, "clear halt failed: %s\n", get_usb_rcmsg(rc)); rc = usb_lock_device_for_reset(ucs->udev, ucs->interface); if (rc == 0) { @@ -2442,7 +2448,9 @@ static void gigaset_disconnect(struct usb_interface *interface) } /* gigaset_suspend - * This function is called before the USB connection is suspended. + * This function is called before the USB connection is suspended + * or before the USB device is reset. + * In the latter case, message == PMSG_ON. */ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) { @@ -2498,7 +2506,12 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) del_timer_sync(&ucs->timer_atrdy); del_timer_sync(&ucs->timer_cmd_in); del_timer_sync(&ucs->timer_int_in); - cancel_work_sync(&ucs->int_in_wq); + + /* don't try to cancel int_in_wq from within reset as it + * might be the one requesting the reset + */ + if (message.event != PM_EVENT_ON) + cancel_work_sync(&ucs->int_in_wq); gig_dbg(DEBUG_SUSPEND, "suspend complete"); return 0; -- cgit v1.2.3-55-g7522 From ad2fab36d7922401c4576fb7ea9b21a47a29a17f Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Thu, 25 Oct 2012 14:03:03 +0300 Subject: gpiolib: Don't return -EPROBE_DEFER to sysfs, or for invalid gpios gpios requested with invalid numbers, or gpios requested from userspace via sysfs should not try to be deferred on failure. Cc: stable@kernel.org Signed-off-by: Mathias Nyman Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5d6c71edc739..1c8d9e3380e1 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -623,9 +623,11 @@ static ssize_t export_store(struct class *class, */ status = gpio_request(gpio, "sysfs"); - if (status < 0) + if (status < 0) { + if (status == -EPROBE_DEFER) + status = -ENODEV; goto done; - + } status = gpio_export(gpio, true); if (status < 0) gpio_free(gpio); @@ -1191,8 +1193,10 @@ int gpio_request(unsigned gpio, const char *label) spin_lock_irqsave(&gpio_lock, flags); - if (!gpio_is_valid(gpio)) + if (!gpio_is_valid(gpio)) { + status = -EINVAL; goto done; + } desc = &gpio_desc[gpio]; chip = desc->chip; if (chip == NULL) -- cgit v1.2.3-55-g7522 From 7208ca300725ebc1dd4c60511ed67a69c684eb91 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Thu, 25 Oct 2012 01:12:47 +0000 Subject: net/mlx4_en: Fix double-release-range in tx-rings The QP range is reserved as a single block. However, when freeing the en resources, the tx-ring QPs are released both in mlx4_en_destroy_tx_ring (one at a time) and in mlx4_en_free_resources (as a block release). Fix by eliminating the one-at-a-time release in mlx4_en_destroy_tx_ring. Signed-off-by: Jack Morgenstein Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_tx.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index c10e3a6de09f..0a51095fd8d6 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -143,7 +143,6 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv, mlx4_bf_free(mdev->dev, &ring->bf); mlx4_qp_remove(mdev->dev, &ring->qp); mlx4_qp_free(mdev->dev, &ring->qp); - mlx4_qp_release_range(mdev->dev, ring->qpn, 1); mlx4_en_unmap_buffer(&ring->wqres.buf); mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size); kfree(ring->bounce_buf); -- cgit v1.2.3-55-g7522 From 2b39a06198a0fbaf44a69f435c5d2b4280a0c10e Mon Sep 17 00:00:00 2001 From: Moni Shoua Date: Thu, 25 Oct 2012 01:12:48 +0000 Subject: net/mlx4_en: Don't use vlan tag value as an indication for vlan presence The vlan tag can be zero. This is why it can't serve as an indication that packet requires VLAN header in the TX flow. Signed-off-by: Moni Shoua Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 0a51095fd8d6..b35094c590ba 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -711,7 +711,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) if (bounce) tx_desc = mlx4_en_bounce_to_desc(priv, ring, index, desc_size); - if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tag) { + if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tx_tag_present(skb)) { *(__be32 *) (&tx_desc->ctrl.vlan_tag) |= cpu_to_be32(ring->doorbell_qpn); op_own |= htonl((bf_index & 0xffff) << 8); /* Ensure new descirptor hits memory -- cgit v1.2.3-55-g7522 From bfc0d8c3de31a51e671e2c1564fd194fa6b00179 Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Thu, 25 Oct 2012 01:12:49 +0000 Subject: net/mlx4_core: Unmap UAR also in the case of error flow If a failure takes place during the EQ creation, we need to unmap the UAR memory block too. Signed-off-by: Dotan Barak Signed-off-by: Uri Habusha Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/eq.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index 51c764901ad2..083767b55c8c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -843,6 +843,18 @@ static void __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, struct mlx4_eq *eq) return priv->eq_table.uar_map[index] + 0x800 + 8 * (eq->eqn % 4); } +static void mlx4_unmap_uar(struct mlx4_dev *dev) +{ + struct mlx4_priv *priv = mlx4_priv(dev); + int i; + + for (i = 0; i < mlx4_num_eq_uar(dev); ++i) + if (priv->eq_table.uar_map[i]) { + iounmap(priv->eq_table.uar_map[i]); + priv->eq_table.uar_map[i] = NULL; + } +} + static int mlx4_create_eq(struct mlx4_dev *dev, int nent, u8 intr, struct mlx4_eq *eq) { @@ -1207,6 +1219,7 @@ err_out_unmap: mlx4_free_irqs(dev); err_out_bitmap: + mlx4_unmap_uar(dev); mlx4_bitmap_cleanup(&priv->eq_table.bitmap); err_out_free: @@ -1231,10 +1244,7 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev) if (!mlx4_is_slave(dev)) mlx4_unmap_clr_int(dev); - for (i = 0; i < mlx4_num_eq_uar(dev); ++i) - if (priv->eq_table.uar_map[i]) - iounmap(priv->eq_table.uar_map[i]); - + mlx4_unmap_uar(dev); mlx4_bitmap_cleanup(&priv->eq_table.bitmap); kfree(priv->eq_table.uar_map); -- cgit v1.2.3-55-g7522 From 39707c2a3ba5011038b363f84d37c8a98d2d9db1 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Thu, 25 Oct 2012 18:17:54 +0000 Subject: net: usb: Fix memory leak on Tx data path Driver anchors the tx urbs and defers the urb submission if a transmit request comes when the interface is suspended. Anchoring urb increments the urb reference count. These deferred urbs are later accessed by calling usb_get_from_anchor() for submission during interface resume. usb_get_from_anchor() unanchors the urb but urb reference count remains same. This causes the urb reference count to remain non-zero after usb_free_urb() gets called and urb never gets freed. Hence call usb_put_urb() after anchoring the urb to properly balance the reference count for these deferred urbs. Also, unanchor these deferred urbs during disconnect, to free them up. Signed-off-by: Hemant Kumar Acked-by: Oliver Neukum Signed-off-by: David S. Miller --- drivers/net/usb/usbnet.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index f9819d10b1f9..cb04f900cc46 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1158,6 +1158,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, usb_anchor_urb(urb, &dev->deferred); /* no use to process more packets */ netif_stop_queue(net); + usb_put_urb(urb); spin_unlock_irqrestore(&dev->txq.lock, flags); netdev_dbg(dev->net, "Delaying transmission for resumption\n"); goto deferred; @@ -1310,6 +1311,8 @@ void usbnet_disconnect (struct usb_interface *intf) cancel_work_sync(&dev->kevent); + usb_scuttle_anchored_urbs(&dev->deferred); + if (dev->driver_info->unbind) dev->driver_info->unbind (dev, intf); -- cgit v1.2.3-55-g7522 From f8295ec22cb0f1ee6849b862addbfa3ea9320755 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 24 Oct 2012 12:10:34 +0000 Subject: qmi_wwan/cdc_ether: move Novatel 551 and E362 to qmi_wwan These devices provide QMI and ethernet functionality via a standard CDC ethernet descriptor. But when driven by cdc_ether, the QMI functionality is unavailable because only cdc_ether can claim the USB interface. Thus blacklist the devices in cdc_ether and add their IDs to qmi_wwan, which enables both QMI and ethernet simultaneously. Signed-off-by: Dan Williams Cc: stable@vger.kernel.org Acked-by: Greg Kroah-Hartman Acked-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/cdc_ether.c | 41 ++++++++++++++++++++++++++--------------- drivers/net/usb/qmi_wwan.c | 14 ++++++++++++++ 2 files changed, 40 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index a03de7197049..d0129827602b 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -592,6 +592,32 @@ static const struct usb_device_id products [] = { .driver_info = 0, }, +/* Novatel USB551L and MC551 - handled by qmi_wwan */ +{ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_PRODUCT + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = NOVATEL_VENDOR_ID, + .idProduct = 0xB001, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, + .bInterfaceProtocol = USB_CDC_PROTO_NONE, + .driver_info = 0, +}, + +/* Novatel E362 - handled by qmi_wwan */ +{ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_PRODUCT + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = NOVATEL_VENDOR_ID, + .idProduct = 0x9010, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, + .bInterfaceProtocol = USB_CDC_PROTO_NONE, + .driver_info = 0, +}, + /* * WHITELIST!!! * @@ -604,21 +630,6 @@ static const struct usb_device_id products [] = { * because of bugs/quirks in a given product (like Zaurus, above). */ { - /* Novatel USB551L */ - /* This match must come *before* the generic CDC-ETHER match so that - * we get FLAG_WWAN set on the device, since it's descriptors are - * generic CDC-ETHER. - */ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR - | USB_DEVICE_ID_MATCH_PRODUCT - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = NOVATEL_VENDOR_ID, - .idProduct = 0xB001, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, - .bInterfaceProtocol = USB_CDC_PROTO_NONE, - .driver_info = (unsigned long)&wwan_info, -}, { /* ZTE (Vodafone) K3805-Z */ .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 9d23ba2fe981..3b566fa0f8e6 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -369,6 +369,20 @@ static const struct usb_device_id products[] = { USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff), .driver_info = (unsigned long)&qmi_wwan_info, }, + { /* Novatel USB551L and MC551 */ + USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0xb001, + USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, + USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&qmi_wwan_info, + }, + { /* Novatel E362 */ + USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0x9010, + USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, + USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&qmi_wwan_info, + }, /* 3. Combined interface devices matching on interface number */ {QMI_FIXED_INTF(0x19d2, 0x0002, 1)}, -- cgit v1.2.3-55-g7522 From 3da3fff8006c608f19a51859d44ba47ca8b41461 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 25 Oct 2012 07:25:20 +0000 Subject: tilegx: fix some issues in the SW TSO support This change correctly computes the header length and data length in the fragments to avoid a bug where we would end up with extremely slow performance. Also adopt use of skb_frag_size() accessor. Signed-off-by: Chris Metcalf Cc: stable@vger.kernel.org [v3.6] Signed-off-by: David S. Miller --- drivers/net/ethernet/tile/tilegx.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c index 4e2a1628484d..4e9810013850 100644 --- a/drivers/net/ethernet/tile/tilegx.c +++ b/drivers/net/ethernet/tile/tilegx.c @@ -1334,11 +1334,11 @@ static int tso_count_edescs(struct sk_buff *skb) { struct skb_shared_info *sh = skb_shinfo(skb); unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - unsigned int data_len = skb->data_len + skb->hdr_len - sh_len; + unsigned int data_len = skb->len - sh_len; unsigned int p_len = sh->gso_size; long f_id = -1; /* id of the current fragment */ - long f_size = skb->hdr_len; /* size of the current fragment */ - long f_used = sh_len; /* bytes used from the current fragment */ + long f_size = skb_headlen(skb) - sh_len; /* current fragment size */ + long f_used = 0; /* bytes used from the current fragment */ long n; /* size of the current piece of payload */ int num_edescs = 0; int segment; @@ -1353,7 +1353,7 @@ static int tso_count_edescs(struct sk_buff *skb) /* Advance as needed. */ while (f_used >= f_size) { f_id++; - f_size = sh->frags[f_id].size; + f_size = skb_frag_size(&sh->frags[f_id]); f_used = 0; } @@ -1384,13 +1384,13 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers, struct iphdr *ih; struct tcphdr *th; unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - unsigned int data_len = skb->data_len + skb->hdr_len - sh_len; + unsigned int data_len = skb->len - sh_len; unsigned char *data = skb->data; unsigned int ih_off, th_off, p_len; unsigned int isum_seed, tsum_seed, id, seq; long f_id = -1; /* id of the current fragment */ - long f_size = skb->hdr_len; /* size of the current fragment */ - long f_used = sh_len; /* bytes used from the current fragment */ + long f_size = skb_headlen(skb) - sh_len; /* current fragment size */ + long f_used = 0; /* bytes used from the current fragment */ long n; /* size of the current piece of payload */ int segment; @@ -1405,7 +1405,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers, isum_seed = ((0xFFFF - ih->check) + (0xFFFF - ih->tot_len) + (0xFFFF - ih->id)); - tsum_seed = th->check + (0xFFFF ^ htons(sh_len + data_len)); + tsum_seed = th->check + (0xFFFF ^ htons(skb->len)); id = ntohs(ih->id); seq = ntohl(th->seq); @@ -1444,7 +1444,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers, /* Advance as needed. */ while (f_used >= f_size) { f_id++; - f_size = sh->frags[f_id].size; + f_size = skb_frag_size(&sh->frags[f_id]); f_used = 0; } @@ -1478,14 +1478,14 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue, struct tile_net_priv *priv = netdev_priv(dev); struct skb_shared_info *sh = skb_shinfo(skb); unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - unsigned int data_len = skb->data_len + skb->hdr_len - sh_len; + unsigned int data_len = skb->len - sh_len; unsigned int p_len = sh->gso_size; gxio_mpipe_edesc_t edesc_head = { { 0 } }; gxio_mpipe_edesc_t edesc_body = { { 0 } }; long f_id = -1; /* id of the current fragment */ - long f_size = skb->hdr_len; /* size of the current fragment */ - long f_used = sh_len; /* bytes used from the current fragment */ - void *f_data = skb->data; + long f_size = skb_headlen(skb) - sh_len; /* current fragment size */ + long f_used = 0; /* bytes used from the current fragment */ + void *f_data = skb->data + sh_len; long n; /* size of the current piece of payload */ unsigned long tx_packets = 0, tx_bytes = 0; unsigned int csum_start; @@ -1516,15 +1516,18 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue, /* Egress the payload. */ while (p_used < p_len) { + void *va; /* Advance as needed. */ while (f_used >= f_size) { f_id++; - f_size = sh->frags[f_id].size; - f_used = 0; + f_size = skb_frag_size(&sh->frags[f_id]); f_data = tile_net_frag_buf(&sh->frags[f_id]); + f_used = 0; } + va = f_data + f_used; + /* Use bytes from the current fragment. */ n = p_len - p_used; if (n > f_size - f_used) @@ -1533,7 +1536,7 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue, p_used += n; /* Egress a piece of the payload. */ - edesc_body.va = va_to_tile_io_addr(f_data) + f_used; + edesc_body.va = va_to_tile_io_addr(va); edesc_body.xfer_size = n; edesc_body.bound = !(p_used < p_len); gxio_mpipe_equeue_put_at(equeue, edesc_body, slot); -- cgit v1.2.3-55-g7522 From e86b618547bb0c7db96aa70491112f032b3bec1c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 25 Oct 2012 10:57:38 +0300 Subject: drm/i915: be less verbose about inability to provide vendor backlight commit 28dcc2d60cb570d9f549c329b2f51400553412a1 Author: Jani Nikula Date: Mon Sep 3 16:25:12 2012 +0300 drm/i915: do not expose a dysfunctional backlight interface to userspace prevents backlight interface creation if the BIOS has not set the backlight PWM CTL registers that contain the max PWM value. It's apparently normal on those machines, so demote the message about it to debug level. Reported-by: Orion Poplawski Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=56330 Signed-off-by: Jani Nikula Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_panel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index e019b2369861..e2aacd329545 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -435,7 +435,7 @@ int intel_panel_setup_backlight(struct drm_device *dev) props.type = BACKLIGHT_RAW; props.max_brightness = _intel_panel_get_max_backlight(dev); if (props.max_brightness == 0) { - DRM_ERROR("Failed to get maximum backlight value\n"); + DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n"); return -ENODEV; } dev_priv->backlight = -- cgit v1.2.3-55-g7522 From 1623392af9da983f3ad088a75076c9da05e5600d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 26 Oct 2012 12:06:41 +0100 Subject: drm/i915: Only kick out vesafb if we takeover the fbcon with KMS Otherwise we may remove the only console for a nomodeset system. We became more aggressive in our kicking with commit e188719a2891f01b3100dca4ae3a055fb5a7ab52 Author: Daniel Vetter Date: Tue Jun 12 11:28:17 2012 +0200 drm/i915: kick any firmware framebuffers before claiming the gtt Reported-and-tested-by: monnier@iro.umontreal.ca Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=54615 Signed-off-by: Chris Wilson Cc: stable@vger.kernel.org # v3.6 Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index c9bfd83dde64..61ae104dca8c 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1505,7 +1505,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto put_gmch; } - i915_kick_out_firmware_fb(dev_priv); + if (drm_core_check_feature(dev, DRIVER_MODESET)) + i915_kick_out_firmware_fb(dev_priv); pci_set_master(dev->pdev); -- cgit v1.2.3-55-g7522 From 29c08cdabd323adf7fcc0d26077383d4daf7b09a Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 9 Oct 2012 12:12:14 -0700 Subject: qla2xxx: Add missing ->vport_slock while calling qlt_update_vp_map All other callers of qlt_update_vp_map() already hold ->vport_slock while updating the vp target map, so go ahead and add the missing ->vport_slock within qla24xx_disable_vp() code. Cc: Saurav Kashyap Cc: Chad Dupuis Cc: Arun Easi Cc: Andrew Vasquez Cc: Jiri Kosina Cc: Roland Dreier Acked-by: Saurav Kashyap Signed-off-by: Nicholas Bellinger --- drivers/scsi/qla2xxx/qla_mid.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index bd4708a422cd..20fd974f903a 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -149,6 +149,7 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) int qla24xx_disable_vp(scsi_qla_host_t *vha) { + unsigned long flags; int ret; ret = qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL); @@ -156,7 +157,9 @@ qla24xx_disable_vp(scsi_qla_host_t *vha) atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); /* Remove port id from vp target map */ + spin_lock_irqsave(&vha->hw->vport_slock, flags); qlt_update_vp_map(vha, RESET_AL_PA); + spin_unlock_irqrestore(&vha->hw->vport_slock, flags); qla2x00_mark_vp_devices_dead(vha); atomic_set(&vha->vp_state, VP_FAILED); -- cgit v1.2.3-55-g7522 From c046aa0f0f47719a38854fc6383216392b130704 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 11 Oct 2012 13:41:31 -0700 Subject: tcm_qla2xxx: Format VPD page 83h SCSI name string according to SPC My draft of SPC-4 says the following about the SCSI name string in inquiry VPD page 83h: The SCSI NAME STRING field starts with either: a) the four UTF-8 characters 'eui.' concatenated with 16, 24, or 32 hexadecimal digits (i.e., the UTF-8 characters 0 through 9 and A through F) for an EUI-64 based identifier (see 7.8.6.5). The first hexadecimal digit shall be the most significant four bits of the first byte (i.e., most significant byte) of the EUI-64 based identifier; b) the four UTF-8 characters 'naa.' concatenated with 16 or 32 hexadecimal digits for an NAA identifier (see 7.8.6.6). The first hexadecimal digit shall be the most significant four bits of the first byte (i.e., most significant byte) of the NAA identifier; or c) the four UTF-8 characters 'iqn.' concatenated with an iSCSI Name for an iSCSI-name based identifier (see iSCSI). However, the .tpg_get_wwn method for tcm_qla2xxx formats the WWN so the SCSI name string looks like "52:4a:93:7d:24:5f:b2:12,t,0x0001". This patch corrects the code so that VPD 83h gives a SPC-compliant SCSI name string like "naa.524a937d245fb212,t,0x0001" while leavig other uses alone (so configfs will still work with ':' separated WWNs). Signed-off-by: Roland Dreier Cc: Chad Dupuis Cc: Arun Easi Cc: Saurav Kashyap Signed-off-by: Nicholas Bellinger --- drivers/scsi/qla2xxx/tcm_qla2xxx.c | 4 +++- drivers/scsi/qla2xxx/tcm_qla2xxx.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 2358c16c4c8e..d8211ccc413a 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -237,7 +237,7 @@ static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg) struct tcm_qla2xxx_tpg, se_tpg); struct tcm_qla2xxx_lport *lport = tpg->lport; - return &lport->lport_name[0]; + return lport->lport_naa_name; } static char *tcm_qla2xxx_npiv_get_fabric_wwn(struct se_portal_group *se_tpg) @@ -1534,6 +1534,7 @@ static struct se_wwn *tcm_qla2xxx_make_lport( lport->lport_wwpn = wwpn; tcm_qla2xxx_format_wwn(&lport->lport_name[0], TCM_QLA2XXX_NAMELEN, wwpn); + sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) wwpn); ret = tcm_qla2xxx_init_lport(lport); if (ret != 0) @@ -1601,6 +1602,7 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport( lport->lport_npiv_wwnn = npiv_wwnn; tcm_qla2xxx_npiv_format_wwn(&lport->lport_npiv_name[0], TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn); + sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) npiv_wwpn); /* FIXME: tcm_qla2xxx_npiv_make_lport */ ret = -ENOSYS; diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.h b/drivers/scsi/qla2xxx/tcm_qla2xxx.h index 825498103352..9ba075fe9781 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.h +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.h @@ -61,6 +61,8 @@ struct tcm_qla2xxx_lport { u64 lport_npiv_wwnn; /* ASCII formatted WWPN for FC Target Lport */ char lport_name[TCM_QLA2XXX_NAMELEN]; + /* ASCII formatted naa WWPN for VPD page 83 etc */ + char lport_naa_name[TCM_QLA2XXX_NAMELEN]; /* ASCII formatted WWPN+WWNN for NPIV FC Target Lport */ char lport_npiv_name[TCM_QLA2XXX_NPIV_NAMELEN]; /* map for fc_port pointers in 24-bit FC Port ID space */ -- cgit v1.2.3-55-g7522 From c8292d1da53fa60c7516ab03a9d83f7ea266d335 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 11 Oct 2012 13:41:32 -0700 Subject: qla2xxx: Update target lookup session tables when a target session changes It is possible for the target code to change the loop_id or s_id of a target session in reaction to an FC fabric change. However, the session structures are stored in tables that are indexed by these two keys, and if we just change the session structure but leave the pointers to it in the old places in the table, havoc can ensue. For example, a new session might come along that should go in the old slot in the table and overwrite the old session pointer. To handle this, add a new tgt_ops->update_sess() method that also updates the "by loop_id" and "by s_id" lookup tables when a session changes, so that the keys where a session pointer is stored in these tables always matches the keys in the session structure itself. (nab: Drop unnecessary double inversion with FCF_CONF_COMP_SUPPORTED usage) Signed-off-by: Roland Dreier Cc: Chad Dupuis Cc: Arun Easi Cc: Saurav Kashyap Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/scsi/qla2xxx/qla_target.c | 25 ++++++------- drivers/scsi/qla2xxx/qla_target.h | 1 + drivers/scsi/qla2xxx/tcm_qla2xxx.c | 73 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 0e09d8f433d1..62aa5584f644 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -557,6 +557,7 @@ static bool qlt_check_fcport_exist(struct scsi_qla_host *vha, int pmap_len; fc_port_t *fcport; int global_resets; + unsigned long flags; retry: global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count); @@ -625,10 +626,10 @@ retry: sess->s_id.b.area, sess->loop_id, fcport->d_id.b.domain, fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id); - sess->s_id = fcport->d_id; - sess->loop_id = fcport->loop_id; - sess->conf_compl_supported = !!(fcport->flags & - FCF_CONF_COMP_SUPPORTED); + spin_lock_irqsave(&ha->hardware_lock, flags); + ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, + (fcport->flags & FCF_CONF_COMP_SUPPORTED)); + spin_unlock_irqrestore(&ha->hardware_lock, flags); res = true; @@ -740,10 +741,9 @@ static struct qla_tgt_sess *qlt_create_sess( qlt_undelete_sess(sess); kref_get(&sess->se_sess->sess_kref); - sess->s_id = fcport->d_id; - sess->loop_id = fcport->loop_id; - sess->conf_compl_supported = !!(fcport->flags & - FCF_CONF_COMP_SUPPORTED); + ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, + (fcport->flags & FCF_CONF_COMP_SUPPORTED)); + if (sess->local && !local) sess->local = 0; spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -796,8 +796,7 @@ static struct qla_tgt_sess *qlt_create_sess( */ kref_get(&sess->se_sess->sess_kref); - sess->conf_compl_supported = !!(fcport->flags & - FCF_CONF_COMP_SUPPORTED); + sess->conf_compl_supported = (fcport->flags & FCF_CONF_COMP_SUPPORTED); BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name)); memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name)); @@ -869,10 +868,8 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007, "Reappeared sess %p\n", sess); } - sess->s_id = fcport->d_id; - sess->loop_id = fcport->loop_id; - sess->conf_compl_supported = !!(fcport->flags & - FCF_CONF_COMP_SUPPORTED); + ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, + (fcport->flags & FCF_CONF_COMP_SUPPORTED)); } if (sess && sess->local) { diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 170af1571214..bad749561ec2 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -648,6 +648,7 @@ struct qla_tgt_func_tmpl { int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *, void *, uint8_t *, uint16_t); + void (*update_sess)(struct qla_tgt_sess *, port_id_t, uint16_t, bool); struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *, const uint16_t); struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *, diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index d8211ccc413a..3d74f2f39ae1 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -1457,6 +1457,78 @@ static int tcm_qla2xxx_check_initiator_node_acl( return 0; } +static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id, + uint16_t loop_id, bool conf_compl_supported) +{ + struct qla_tgt *tgt = sess->tgt; + struct qla_hw_data *ha = tgt->ha; + struct tcm_qla2xxx_lport *lport = ha->tgt.target_lport_ptr; + struct se_node_acl *se_nacl = sess->se_sess->se_node_acl; + struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl, + struct tcm_qla2xxx_nacl, se_node_acl); + u32 key; + + + if (sess->loop_id != loop_id || sess->s_id.b24 != s_id.b24) + pr_info("Updating session %p from port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x loop_id %d -> %d s_id %x:%x:%x -> %x:%x:%x\n", + sess, + sess->port_name[0], sess->port_name[1], + sess->port_name[2], sess->port_name[3], + sess->port_name[4], sess->port_name[5], + sess->port_name[6], sess->port_name[7], + sess->loop_id, loop_id, + sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa, + s_id.b.domain, s_id.b.area, s_id.b.al_pa); + + if (sess->loop_id != loop_id) { + /* + * Because we can shuffle loop IDs around and we + * update different sessions non-atomically, we might + * have overwritten this session's old loop ID + * already, and we might end up overwriting some other + * session that will be updated later. So we have to + * be extra careful and we can't warn about those things... + */ + if (lport->lport_loopid_map[sess->loop_id].se_nacl == se_nacl) + lport->lport_loopid_map[sess->loop_id].se_nacl = NULL; + + lport->lport_loopid_map[loop_id].se_nacl = se_nacl; + + sess->loop_id = loop_id; + } + + if (sess->s_id.b24 != s_id.b24) { + key = (((u32) sess->s_id.b.domain << 16) | + ((u32) sess->s_id.b.area << 8) | + ((u32) sess->s_id.b.al_pa)); + + if (btree_lookup32(&lport->lport_fcport_map, key)) + WARN(btree_remove32(&lport->lport_fcport_map, key) != se_nacl, + "Found wrong se_nacl when updating s_id %x:%x:%x\n", + sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa); + else + WARN(1, "No lport_fcport_map entry for s_id %x:%x:%x\n", + sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa); + + key = (((u32) s_id.b.domain << 16) | + ((u32) s_id.b.area << 8) | + ((u32) s_id.b.al_pa)); + + if (btree_lookup32(&lport->lport_fcport_map, key)) { + WARN(1, "Already have lport_fcport_map entry for s_id %x:%x:%x\n", + s_id.b.domain, s_id.b.area, s_id.b.al_pa); + btree_update32(&lport->lport_fcport_map, key, se_nacl); + } else { + btree_insert32(&lport->lport_fcport_map, key, se_nacl, GFP_ATOMIC); + } + + sess->s_id = s_id; + nacl->nport_id = key; + } + + sess->conf_compl_supported = conf_compl_supported; +} + /* * Calls into tcm_qla2xxx used by qla2xxx LLD I/O path. */ @@ -1467,6 +1539,7 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = { .free_cmd = tcm_qla2xxx_free_cmd, .free_mcmd = tcm_qla2xxx_free_mcmd, .free_session = tcm_qla2xxx_free_session, + .update_sess = tcm_qla2xxx_update_sess, .check_initiator_node_acl = tcm_qla2xxx_check_initiator_node_acl, .find_sess_by_s_id = tcm_qla2xxx_find_sess_by_s_id, .find_sess_by_loop_id = tcm_qla2xxx_find_sess_by_loop_id, -- cgit v1.2.3-55-g7522 From e13d5fef88c40b87c8430f8274c3a9ca32ef90bc Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 26 Oct 2012 15:35:45 -0700 Subject: target: Fix double-free of se_cmd in target_complete_tmr_failure Fabric drivers currently expect to internally release se_cmd in the event of a TMR failure during target_submit_tmr(), which means the immediate call to transport_generic_free_cmd() after TFO->queue_tm_rsp() from within target_complete_tmr_failure() workqueue context is wrong. This is done as some fabrics expect TMR operations to be acknowledged before releasing the descriptor, so the assumption that core is releasing se_cmd associated TMR memory is incorrect. This fixes a OOPs where transport_generic_free_cmd() was being called more than once. This bug was originally observed with tcm_qla2xxx fabric ports. Cc: Christoph Hellwig Cc: Roland Dreier Cc: Andy Grover Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index c33baff86aa6..9097155e9ebe 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1616,7 +1616,6 @@ static void target_complete_tmr_failure(struct work_struct *work) se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST; se_cmd->se_tfo->queue_tm_rsp(se_cmd); - transport_generic_free_cmd(se_cmd, 0); } /** -- cgit v1.2.3-55-g7522 From 1a1ff38c4cebf23be8bf0009a76b082a13bd25cb Mon Sep 17 00:00:00 2001 From: Bernhard Kohl Date: Wed, 24 Oct 2012 15:53:58 +0200 Subject: target: reintroduce some obsolete SCSI-2 commands With kernel 3.6 some obsolete SCSI-2 commands including SEEK_10 have have been removed by commit 1fd032ee10d2816c947f5d5b9abda95e728f0a8f "target: move code for CDB emulation". There are still clients out there which use these old SCSI-2 commands. This mainly happens when running VMs with legacy guest systems, connected via SCSI command pass-through to iSCSI targets. Make them happy and return status GOOD. Many real SCSI disks or external iSCSI storage devices still support these old commands. So let's make LIO backward compatible as well. This patch adds support for the previously removed SEEK_10 and additionally the SEEK_6 and REZERO_UNIT commands. Signed-off-by: Bernhard Kohl Reviewed-by: Christoph Hellwig Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_sbc.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 868f8aa04f13..a6e27d967c7b 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -135,6 +135,12 @@ static int sbc_emulate_verify(struct se_cmd *cmd) return 0; } +static int sbc_emulate_noop(struct se_cmd *cmd) +{ + target_complete_cmd(cmd, GOOD); + return 0; +} + static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors) { return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors; @@ -531,6 +537,18 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops) size = 0; cmd->execute_cmd = sbc_emulate_verify; break; + case REZERO_UNIT: + case SEEK_6: + case SEEK_10: + /* + * There are still clients out there which use these old SCSI-2 + * commands. This mainly happens when running VMs with legacy + * guest systems, connected via SCSI command pass-through to + * iSCSI targets. Make them happy and return status GOOD. + */ + size = 0; + cmd->execute_cmd = sbc_emulate_noop; + break; default: ret = spc_parse_cdb(cmd, &size); if (ret) -- cgit v1.2.3-55-g7522 From c9c55d9211150b589d2d39a45cf5f96c70a51a47 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 26 Oct 2012 14:26:04 -0500 Subject: gpio/omap: fix off-mode bug: clear debounce settings on free/reset This change was originally titled "gpio/omap: fix off-mode bug: clear debounce clock enable mask on free/reset". The title has been updated slightly to reflect (what should be) the final fix. When a GPIO is freed or shutdown, we need to ensure that any debounce settings are cleared and if the GPIO is the only GPIO in the bank that is currently using debounce, then disable the debounce clock as well to save power. Currently, the debounce settings are not cleared on a GPIO free or shutdown and so during a context restore on subsequent off-mode transition, the previous debounce values are restored from the shadow copies (bank->context.debounce*) leading to mismatch state between driver state and hardware state. This was discovered when board code was doing gpio_request_one() gpio_set_debounce() gpio_free() which was leaving the GPIO debounce settings in a confused state. If that GPIO bank is subsequently used with off-mode enabled, bogus state would be restored, leaving GPIO debounce enabled which then prevented the CORE powerdomain from transitioning. To fix this, introduce a new function called _clear_gpio_debounce() to clear any debounce settings when the GPIO is freed or shutdown. If this GPIO is the last debounce-enabled GPIO in the bank, the debounce will also be cut. Please note that we cannot use _gpio_dbck_disable() to disable the debounce clock because this has been specifically created for the gpio suspend path and is intended to shutdown the debounce clock while debounce is enabled. Special thanks to Kevin Hilman for root causing the bug. This fix is a collaborative effort with inputs from Kevin Hilman, Grazvydas Ignotas and Santosh Shilimkar. Testing: - This has been unit tested on an OMAP3430 Beagle board, by requesting a gpio, enabling debounce and then freeing the gpio and checking the register contents, the saved register context and the debounce clock state. - Kevin Hilman tested on 37xx/EVM board which configures GPIO debounce for the ads7846 touchscreen in its board file using the above sequence, and so was failing off-mode tests in dynamic idle. Verified that off-mode tests are passing with this patch. V5 changes: - Corrected author Reported-by: Paul Walmsley Cc: Igor Grinberg Cc: Grazvydas Ignotas Cc: Jon Hunter Signed-off-by: Jon Hunter Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Acked-by: Santosh Shilimkar Signed-off-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'drivers') diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 94cbc842fbc3..d335af1d4d85 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -251,6 +251,40 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, } } +/** + * _clear_gpio_debounce - clear debounce settings for a gpio + * @bank: the gpio bank we're acting upon + * @gpio: the gpio number on this @gpio + * + * If a gpio is using debounce, then clear the debounce enable bit and if + * this is the only gpio in this bank using debounce, then clear the debounce + * time too. The debounce clock will also be disabled when calling this function + * if this is the only gpio in the bank using debounce. + */ +static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio) +{ + u32 gpio_bit = GPIO_BIT(bank, gpio); + + if (!bank->dbck_flag) + return; + + if (!(bank->dbck_enable_mask & gpio_bit)) + return; + + bank->dbck_enable_mask &= ~gpio_bit; + bank->context.debounce_en &= ~gpio_bit; + __raw_writel(bank->context.debounce_en, + bank->base + bank->regs->debounce_en); + + if (!bank->dbck_enable_mask) { + bank->context.debounce = 0; + __raw_writel(bank->context.debounce, bank->base + + bank->regs->debounce); + clk_disable(bank->dbck); + bank->dbck_enabled = false; + } +} + static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio, unsigned trigger) { @@ -539,6 +573,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio) _set_gpio_irqenable(bank, gpio, 0); _clear_gpio_irqstatus(bank, gpio); _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); + _clear_gpio_debounce(bank, gpio); } /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */ -- cgit v1.2.3-55-g7522 From 31d178bffcff4c468c8c65bc42d9f4c0a7b8e3ec Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 28 Oct 2012 21:37:00 +0100 Subject: i2c-stub: Move to drivers/i2c Move the i2c-stub driver to drivers/i2c, to match the Kconfig entry. This is less confusing that way. I also fixed all checkpatch warnings and errors. Signed-off-by: Jean Delvare Cc: Peter Huewe --- drivers/i2c/Makefile | 1 + drivers/i2c/busses/Makefile | 1 - drivers/i2c/busses/i2c-stub.c | 222 ------------------------------------------ drivers/i2c/i2c-stub.c | 220 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 221 insertions(+), 223 deletions(-) delete mode 100644 drivers/i2c/busses/i2c-stub.c create mode 100644 drivers/i2c/i2c-stub.c (limited to 'drivers') diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index beee6b2d361d..1722f50f2473 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o obj-$(CONFIG_I2C_MUX) += i2c-mux.o obj-y += algos/ busses/ muxes/ +obj-$(CONFIG_I2C_STUB) += i2c-stub.o ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG CFLAGS_i2c-core.o := -Wno-deprecated-declarations diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 2d33d62952c1..395b516ffa08 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -85,7 +85,6 @@ obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o -obj-$(CONFIG_I2C_STUB) += i2c-stub.o obj-$(CONFIG_SCx200_ACB) += scx200_acb.o obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c deleted file mode 100644 index b1b3447942c9..000000000000 --- a/drivers/i2c/busses/i2c-stub.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - i2c-stub.c - I2C/SMBus chip emulator - - Copyright (c) 2004 Mark M. Hoffman - Copyright (C) 2007 Jean Delvare - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#define DEBUG 1 - -#include -#include -#include -#include -#include -#include - -#define MAX_CHIPS 10 -#define STUB_FUNC (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \ - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \ - I2C_FUNC_SMBUS_I2C_BLOCK) - -static unsigned short chip_addr[MAX_CHIPS]; -module_param_array(chip_addr, ushort, NULL, S_IRUGO); -MODULE_PARM_DESC(chip_addr, - "Chip addresses (up to 10, between 0x03 and 0x77)"); - -static unsigned long functionality = STUB_FUNC; -module_param(functionality, ulong, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(functionality, "Override functionality bitfield"); - -struct stub_chip { - u8 pointer; - u16 words[256]; /* Byte operations use the LSB as per SMBus - specification */ -}; - -static struct stub_chip *stub_chips; - -/* Return negative errno on error. */ -static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, - char read_write, u8 command, int size, union i2c_smbus_data * data) -{ - s32 ret; - int i, len; - struct stub_chip *chip = NULL; - - /* Search for the right chip */ - for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) { - if (addr == chip_addr[i]) { - chip = stub_chips + i; - break; - } - } - if (!chip) - return -ENODEV; - - switch (size) { - - case I2C_SMBUS_QUICK: - dev_dbg(&adap->dev, "smbus quick - addr 0x%02x\n", addr); - ret = 0; - break; - - case I2C_SMBUS_BYTE: - if (read_write == I2C_SMBUS_WRITE) { - chip->pointer = command; - dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " - "wrote 0x%02x.\n", - addr, command); - } else { - data->byte = chip->words[chip->pointer++] & 0xff; - dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " - "read 0x%02x.\n", - addr, data->byte); - } - - ret = 0; - break; - - case I2C_SMBUS_BYTE_DATA: - if (read_write == I2C_SMBUS_WRITE) { - chip->words[command] &= 0xff00; - chip->words[command] |= data->byte; - dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " - "wrote 0x%02x at 0x%02x.\n", - addr, data->byte, command); - } else { - data->byte = chip->words[command] & 0xff; - dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " - "read 0x%02x at 0x%02x.\n", - addr, data->byte, command); - } - chip->pointer = command + 1; - - ret = 0; - break; - - case I2C_SMBUS_WORD_DATA: - if (read_write == I2C_SMBUS_WRITE) { - chip->words[command] = data->word; - dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, " - "wrote 0x%04x at 0x%02x.\n", - addr, data->word, command); - } else { - data->word = chip->words[command]; - dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, " - "read 0x%04x at 0x%02x.\n", - addr, data->word, command); - } - - ret = 0; - break; - - case I2C_SMBUS_I2C_BLOCK_DATA: - len = data->block[0]; - if (read_write == I2C_SMBUS_WRITE) { - for (i = 0; i < len; i++) { - chip->words[command + i] &= 0xff00; - chip->words[command + i] |= data->block[1 + i]; - } - dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, " - "wrote %d bytes at 0x%02x.\n", - addr, len, command); - } else { - for (i = 0; i < len; i++) { - data->block[1 + i] = - chip->words[command + i] & 0xff; - } - dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, " - "read %d bytes at 0x%02x.\n", - addr, len, command); - } - - ret = 0; - break; - - default: - dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n"); - ret = -EOPNOTSUPP; - break; - } /* switch (size) */ - - return ret; -} - -static u32 stub_func(struct i2c_adapter *adapter) -{ - return STUB_FUNC & functionality; -} - -static const struct i2c_algorithm smbus_algorithm = { - .functionality = stub_func, - .smbus_xfer = stub_xfer, -}; - -static struct i2c_adapter stub_adapter = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = &smbus_algorithm, - .name = "SMBus stub driver", -}; - -static int __init i2c_stub_init(void) -{ - int i, ret; - - if (!chip_addr[0]) { - printk(KERN_ERR "i2c-stub: Please specify a chip address\n"); - return -ENODEV; - } - - for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) { - if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) { - printk(KERN_ERR "i2c-stub: Invalid chip address " - "0x%02x\n", chip_addr[i]); - return -EINVAL; - } - - printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n", - chip_addr[i]); - } - - /* Allocate memory for all chips at once */ - stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL); - if (!stub_chips) { - printk(KERN_ERR "i2c-stub: Out of memory\n"); - return -ENOMEM; - } - - ret = i2c_add_adapter(&stub_adapter); - if (ret) - kfree(stub_chips); - return ret; -} - -static void __exit i2c_stub_exit(void) -{ - i2c_del_adapter(&stub_adapter); - kfree(stub_chips); -} - -MODULE_AUTHOR("Mark M. Hoffman "); -MODULE_DESCRIPTION("I2C stub driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_stub_init); -module_exit(i2c_stub_exit); - diff --git a/drivers/i2c/i2c-stub.c b/drivers/i2c/i2c-stub.c new file mode 100644 index 000000000000..d0a9c590c3cd --- /dev/null +++ b/drivers/i2c/i2c-stub.c @@ -0,0 +1,220 @@ +/* + i2c-stub.c - I2C/SMBus chip emulator + + Copyright (c) 2004 Mark M. Hoffman + Copyright (C) 2007, 2012 Jean Delvare + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#define DEBUG 1 + +#include +#include +#include +#include +#include +#include + +#define MAX_CHIPS 10 +#define STUB_FUNC (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \ + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \ + I2C_FUNC_SMBUS_I2C_BLOCK) + +static unsigned short chip_addr[MAX_CHIPS]; +module_param_array(chip_addr, ushort, NULL, S_IRUGO); +MODULE_PARM_DESC(chip_addr, + "Chip addresses (up to 10, between 0x03 and 0x77)"); + +static unsigned long functionality = STUB_FUNC; +module_param(functionality, ulong, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(functionality, "Override functionality bitfield"); + +struct stub_chip { + u8 pointer; + u16 words[256]; /* Byte operations use the LSB as per SMBus + specification */ +}; + +static struct stub_chip *stub_chips; + +/* Return negative errno on error. */ +static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags, + char read_write, u8 command, int size, union i2c_smbus_data *data) +{ + s32 ret; + int i, len; + struct stub_chip *chip = NULL; + + /* Search for the right chip */ + for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) { + if (addr == chip_addr[i]) { + chip = stub_chips + i; + break; + } + } + if (!chip) + return -ENODEV; + + switch (size) { + + case I2C_SMBUS_QUICK: + dev_dbg(&adap->dev, "smbus quick - addr 0x%02x\n", addr); + ret = 0; + break; + + case I2C_SMBUS_BYTE: + if (read_write == I2C_SMBUS_WRITE) { + chip->pointer = command; + dev_dbg(&adap->dev, + "smbus byte - addr 0x%02x, wrote 0x%02x.\n", + addr, command); + } else { + data->byte = chip->words[chip->pointer++] & 0xff; + dev_dbg(&adap->dev, + "smbus byte - addr 0x%02x, read 0x%02x.\n", + addr, data->byte); + } + + ret = 0; + break; + + case I2C_SMBUS_BYTE_DATA: + if (read_write == I2C_SMBUS_WRITE) { + chip->words[command] &= 0xff00; + chip->words[command] |= data->byte; + dev_dbg(&adap->dev, + "smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\n", + addr, data->byte, command); + } else { + data->byte = chip->words[command] & 0xff; + dev_dbg(&adap->dev, + "smbus byte data - addr 0x%02x, read 0x%02x at 0x%02x.\n", + addr, data->byte, command); + } + chip->pointer = command + 1; + + ret = 0; + break; + + case I2C_SMBUS_WORD_DATA: + if (read_write == I2C_SMBUS_WRITE) { + chip->words[command] = data->word; + dev_dbg(&adap->dev, + "smbus word data - addr 0x%02x, wrote 0x%04x at 0x%02x.\n", + addr, data->word, command); + } else { + data->word = chip->words[command]; + dev_dbg(&adap->dev, + "smbus word data - addr 0x%02x, read 0x%04x at 0x%02x.\n", + addr, data->word, command); + } + + ret = 0; + break; + + case I2C_SMBUS_I2C_BLOCK_DATA: + len = data->block[0]; + if (read_write == I2C_SMBUS_WRITE) { + for (i = 0; i < len; i++) { + chip->words[command + i] &= 0xff00; + chip->words[command + i] |= data->block[1 + i]; + } + dev_dbg(&adap->dev, + "i2c block data - addr 0x%02x, wrote %d bytes at 0x%02x.\n", + addr, len, command); + } else { + for (i = 0; i < len; i++) { + data->block[1 + i] = + chip->words[command + i] & 0xff; + } + dev_dbg(&adap->dev, + "i2c block data - addr 0x%02x, read %d bytes at 0x%02x.\n", + addr, len, command); + } + + ret = 0; + break; + + default: + dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n"); + ret = -EOPNOTSUPP; + break; + } /* switch (size) */ + + return ret; +} + +static u32 stub_func(struct i2c_adapter *adapter) +{ + return STUB_FUNC & functionality; +} + +static const struct i2c_algorithm smbus_algorithm = { + .functionality = stub_func, + .smbus_xfer = stub_xfer, +}; + +static struct i2c_adapter stub_adapter = { + .owner = THIS_MODULE, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, + .algo = &smbus_algorithm, + .name = "SMBus stub driver", +}; + +static int __init i2c_stub_init(void) +{ + int i, ret; + + if (!chip_addr[0]) { + pr_err("i2c-stub: Please specify a chip address\n"); + return -ENODEV; + } + + for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) { + if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) { + pr_err("i2c-stub: Invalid chip address 0x%02x\n", + chip_addr[i]); + return -EINVAL; + } + + pr_info("i2c-stub: Virtual chip at 0x%02x\n", chip_addr[i]); + } + + /* Allocate memory for all chips at once */ + stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL); + if (!stub_chips) { + pr_err("i2c-stub: Out of memory\n"); + return -ENOMEM; + } + + ret = i2c_add_adapter(&stub_adapter); + if (ret) + kfree(stub_chips); + return ret; +} + +static void __exit i2c_stub_exit(void) +{ + i2c_del_adapter(&stub_adapter); + kfree(stub_chips); +} + +MODULE_AUTHOR("Mark M. Hoffman "); +MODULE_DESCRIPTION("I2C stub driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_stub_init); +module_exit(i2c_stub_exit); -- cgit v1.2.3-55-g7522 From 79e3e5b894926d3c7b1efc69e0c5be723ceb88bd Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 28 Oct 2012 21:37:01 +0100 Subject: i2c-i801: Simplify dependency towards GPIOLIB Arbitrarily selecting GPIOLIB causes trouble on some architectures, so don't do that. Instead, just make the optional multiplexing code depend on CONFIG_I2C_MUX_GPIO instead of CONFIG_I2C_MUX for now. We can revisit if the i2c-i801 driver ever supports other multiplexing flavors. Also make that optional code depend on DMI, as it won't do anything without that. Signed-off-by: Jean Delvare Cc: Fengguang Wu --- drivers/i2c/busses/Kconfig | 1 - drivers/i2c/busses/i2c-i801.c | 9 ++++++--- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 65dd599a0262..e9df4612b7eb 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -81,7 +81,6 @@ config I2C_I801 tristate "Intel 82801 (ICH/PCH)" depends on PCI select CHECK_SIGNATURE if X86 && DMI - select GPIOLIB if I2C_MUX help If you say yes to this option, support will be included for the Intel 801 family of mainboard I2C interfaces. Specifically, the following diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 37793156bd93..3bc3f7302035 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -82,7 +82,8 @@ #include #include -#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE +#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ + defined CONFIG_DMI #include #include #include @@ -192,7 +193,8 @@ struct i801_priv { int len; u8 *data; -#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE +#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ + defined CONFIG_DMI const struct i801_mux_config *mux_drvdata; struct platform_device *mux_pdev; #endif @@ -921,7 +923,8 @@ static void __init input_apanel_init(void) {} static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {} #endif /* CONFIG_X86 && CONFIG_DMI */ -#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE +#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ + defined CONFIG_DMI static struct i801_mux_config i801_mux_config_asus_z8_d12 = { .gpio_chip = "gpio_ich", .values = { 0x02, 0x03 }, -- cgit v1.2.3-55-g7522 From 28901f579486a69cfdf7f294a3b5a97b173fb74a Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 28 Oct 2012 21:37:01 +0100 Subject: i2c-i801: Fix comment Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-i801.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 3bc3f7302035..6abc00d59881 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1062,7 +1062,7 @@ static unsigned int __devinit i801_get_adapter_class(struct i801_priv *priv) id = dmi_first_match(mux_dmi_table); if (id) { - /* Remove from branch classes from trunk */ + /* Remove branch classes from trunk */ mux_config = id->driver_data; for (i = 0; i < mux_config->n_values; i++) class &= ~mux_config->classes[i]; -- cgit v1.2.3-55-g7522 From 8c6e30936a7893a85f6222084f0f26aceb81137a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 26 Oct 2012 00:31:11 +0200 Subject: ath9k: fix stale pointers potentially causing access to free'd skbs bf->bf_next is only while buffers are chained as part of an A-MPDU in the tx queue. When a tid queue is flushed (e.g. on tearing down an aggregation session), frames can be enqueued again as normal transmission, without bf_next being cleared. This can lead to the old pointer being dereferenced again later. This patch might fix crashes and "Failed to stop TX DMA!" messages. Signed-off-by: Felix Fietkau Cc: stable@vger.kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 378bd70256b2..1ffca7511fa8 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -312,6 +312,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) } bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); + bf->bf_next = NULL; list_del(&bf->list); spin_unlock_bh(&sc->tx.txbuflock); @@ -1774,6 +1775,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, list_add_tail(&bf->list, &bf_head); bf->bf_state.bf_type = 0; + bf->bf_next = NULL; bf->bf_lastbf = bf; ath_tx_fill_desc(sc, bf, txq, fi->framelen); ath_tx_txqaddbuf(sc, txq, &bf_head, false); -- cgit v1.2.3-55-g7522 From d034fbf08b6fe86271d0d0bd332edabeb5749fd6 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Mon, 29 Oct 2012 18:50:47 +0100 Subject: hwmon, fam15h_power: Change email address, MAINTAINERS entry Signed-off-by: Andreas Herrmann Signed-off-by: Guenter Roeck --- Documentation/hwmon/fam15h_power | 2 +- MAINTAINERS | 2 +- drivers/hwmon/fam15h_power.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/Documentation/hwmon/fam15h_power b/Documentation/hwmon/fam15h_power index a92918e0bd69..80654813d04a 100644 --- a/Documentation/hwmon/fam15h_power +++ b/Documentation/hwmon/fam15h_power @@ -10,7 +10,7 @@ Supported chips: BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors (not yet published) -Author: Andreas Herrmann +Author: Andreas Herrmann Description ----------- diff --git a/MAINTAINERS b/MAINTAINERS index 1fa907441f8f..a4e81367a3a1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -503,7 +503,7 @@ F: include/linux/altera_uart.h F: include/linux/altera_jtaguart.h AMD FAM15H PROCESSOR POWER MONITORING DRIVER -M: Andreas Herrmann +M: Andreas Herrmann L: lm-sensors@lm-sensors.org S: Maintained F: Documentation/hwmon/fam15h_power diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 68ad7d255512..4f4110407387 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -2,7 +2,7 @@ * fam15h_power.c - AMD Family 15h processor power monitoring * * Copyright (c) 2011 Advanced Micro Devices, Inc. - * Author: Andreas Herrmann + * Author: Andreas Herrmann * * * This driver is free software; you can redistribute it and/or @@ -28,7 +28,7 @@ #include MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor"); -MODULE_AUTHOR("Andreas Herrmann "); +MODULE_AUTHOR("Andreas Herrmann "); MODULE_LICENSE("GPL"); /* D18F3 */ -- cgit v1.2.3-55-g7522 From b216e12d062d060f2c7b1a49b4b6a6a442cae79c Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Mon, 29 Oct 2012 23:45:30 -0700 Subject: Input: wacom - correct bad Cintiq 24HD check Signed-off-by: Fengguang Wu Signed-off-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 2c1e12bf2ab4..858ad446de91 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -391,7 +391,7 @@ static int wacom_parse_hid(struct usb_interface *intf, features->pktlen = WACOM_PKGLEN_TPC2FG; } - if (features->type == MTSCREEN || WACOM_24HDT) + if (features->type == MTSCREEN || features->type == WACOM_24HDT) features->pktlen = WACOM_PKGLEN_MTOUCH; if (features->type == BAMBOO_PT) { -- cgit v1.2.3-55-g7522 From 904adede088f2a6976e417d1d5cf72c9fe686814 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Mon, 29 Oct 2012 23:45:09 -0700 Subject: Input: pxa27x_keypad - clear pending interrupts on keypad config Bootloader can leave interrupt bit pending, and it confuses driver. Signed-off-by: Vasily Khoruzhick Acked-by: Robert Jarzmik Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/pxa27x_keypad.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 803ff6fe021e..cad9d5dd5973 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -368,6 +368,9 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad) unsigned int mask = 0, direct_key_num = 0; unsigned long kpc = 0; + /* clear pending interrupt bit */ + keypad_readl(KPC); + /* enable matrix keys with automatic scan */ if (pdata->matrix_key_rows && pdata->matrix_key_cols) { kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL; -- cgit v1.2.3-55-g7522 From e07577e1ddf6d2d31961df897e7ff05c0aeb8d0f Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Mon, 29 Oct 2012 22:30:56 -0700 Subject: Input: lpc32xx-keys - select INPUT_MATRIXKMAP This adds a "select" dependency of KEYBOARD_LPC32XX on INPUT_MATRIXKMAP, as the other drivers are doing in this regard. This fixes the following compile error if KEYBOARD_LPC32XX is enabled but INPUT_MATRIXKMAP is not: drivers/input/keyboard/lpc32xx-keys.c:230: undefined reference to `matrix_keypad_build_keymap' Signed-off-by: Roland Stigge Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index b4b65af8612a..de0874054e9f 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -335,6 +335,7 @@ config KEYBOARD_LOCOMO config KEYBOARD_LPC32XX tristate "LPC32XX matrix key scanner support" depends on ARCH_LPC32XX && OF + select INPUT_MATRIXKMAP help Say Y here if you want to use NXP LPC32XX SoC key scanner interface, connected to a key matrix. -- cgit v1.2.3-55-g7522 From 2911758f14e36a7cd5c7367f951dcb8817552f71 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Mon, 13 Aug 2012 10:53:17 -0400 Subject: xen/blkback: Fix compile warning drivers/block/xen-blkback/xenbus.c:260:5: warning: symbol 'xenvbd_sysfs_addif' was not declared. Should it be static? drivers/block/xen-blkback/xenbus.c:284:6: warning: symbol 'xenvbd_sysfs_delif' was not declared. Should it be static? Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/xenbus.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 4f66171c6683..d0fed5582a42 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -196,7 +196,7 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif) } } -void xen_blkif_free(struct xen_blkif *blkif) +static void xen_blkif_free(struct xen_blkif *blkif) { if (!atomic_dec_and_test(&blkif->refcnt)) BUG(); @@ -257,7 +257,7 @@ static struct attribute_group xen_vbdstat_group = { VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor); VBD_SHOW(mode, "%s\n", be->mode); -int xenvbd_sysfs_addif(struct xenbus_device *dev) +static int xenvbd_sysfs_addif(struct xenbus_device *dev) { int error; @@ -281,7 +281,7 @@ fail1: device_remove_file(&dev->dev, &dev_attr_physical_device); return error; } -void xenvbd_sysfs_delif(struct xenbus_device *dev) +static void xenvbd_sysfs_delif(struct xenbus_device *dev) { sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group); device_remove_file(&dev->dev, &dev_attr_mode); -- cgit v1.2.3-55-g7522 From b54e1f88897bcacc2cd359f48ea3b39eaf55f084 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Mon, 27 Aug 2012 20:56:51 -0300 Subject: floppy: don't call alloc_ordered_workqueue inside the alloc_disk loop Since commit 070ad7e ("floppy: convert to delayed work and single-thread wq"), we end up calling alloc_ordered_workqueue multiple times inside the loop, which shouldn't be intended. Besides the leak, other side effect in the current code is if blk_init_queue fails, we would end up calling unregister_blkdev even if we didn't call yet register_blkdev. Just moved the allocation of floppy_wq before the loop, and adjusted the code accordingly. Cc: stable@vger.kernel.org # 3.5+ Acked-by: Vivek Goyal Reviewed-by: Ben Hutchings Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Jiri Kosina Signed-off-by: Jens Axboe --- drivers/block/floppy.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 17c675c52295..83112f08a41d 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4137,6 +4137,10 @@ static int __init do_floppy_init(void) raw_cmd = NULL; + floppy_wq = alloc_ordered_workqueue("floppy", 0); + if (!floppy_wq) + return -ENOMEM; + for (dr = 0; dr < N_DRIVE; dr++) { disks[dr] = alloc_disk(1); if (!disks[dr]) { @@ -4144,16 +4148,10 @@ static int __init do_floppy_init(void) goto out_put_disk; } - floppy_wq = alloc_ordered_workqueue("floppy", 0); - if (!floppy_wq) { - err = -ENOMEM; - goto out_put_disk; - } - disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock); if (!disks[dr]->queue) { err = -ENOMEM; - goto out_destroy_workq; + goto out_put_disk; } blk_queue_max_hw_sectors(disks[dr]->queue, 64); @@ -4317,8 +4315,6 @@ out_release_dma: out_unreg_region: blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); platform_driver_unregister(&floppy_driver); -out_destroy_workq: - destroy_workqueue(floppy_wq); out_unreg_blkdev: unregister_blkdev(FLOPPY_MAJOR, "fd"); out_put_disk: @@ -4334,6 +4330,7 @@ out_put_disk: } put_disk(disks[dr]); } + destroy_workqueue(floppy_wq); return err; } -- cgit v1.2.3-55-g7522 From 238ab78469c6ab7845b43d5061cd3c92331b2452 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Mon, 27 Aug 2012 20:56:52 -0300 Subject: floppy: do put_disk on current dr if blk_init_queue fails If blk_init_queue fails, we do not call put_disk on the current dr (dr is decremented first in the error handling loop). Cc: stable@vger.kernel.org Reviewed-by: Ben Hutchings Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Jiri Kosina Signed-off-by: Jens Axboe --- drivers/block/floppy.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 83112f08a41d..9a558b63e78f 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4150,6 +4150,7 @@ static int __init do_floppy_init(void) disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock); if (!disks[dr]->queue) { + put_disk(disks[dr]); err = -ENOMEM; goto out_put_disk; } -- cgit v1.2.3-55-g7522 From d60e7ec18c3fb2cbf90969ccd42889eb2d03aef9 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Mon, 27 Aug 2012 20:56:54 -0300 Subject: floppy: properly handle failure on add_disk loop On floppy initialization, if something failed inside the loop we call add_disk, there was no cleanup of previous iterations in the error handling. Cc: stable@vger.kernel.org Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Jiri Kosina Signed-off-by: Jens Axboe --- drivers/block/floppy.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 9a558b63e78f..2c7257334b64 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4292,7 +4292,7 @@ static int __init do_floppy_init(void) err = platform_device_register(&floppy_device[drive]); if (err) - goto out_release_dma; + goto out_remove_drives; err = device_create_file(&floppy_device[drive].dev, &dev_attr_cmos); @@ -4310,6 +4310,15 @@ static int __init do_floppy_init(void) out_unreg_platform_dev: platform_device_unregister(&floppy_device[drive]); +out_remove_drives: + while (drive--) { + if ((allowed_drive_mask & (1 << drive)) && + fdc_state[FDC(drive)].version != FDC_NONE) { + del_gendisk(disks[drive]); + device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos); + platform_device_unregister(&floppy_device[drive]); + } + } out_release_dma: if (atomic_read(&usage_count)) floppy_release_irq_and_dma(); -- cgit v1.2.3-55-g7522 From 8d3ab4ebfd7435bc248873de47d0ca23076c4973 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Mon, 27 Aug 2012 20:56:55 -0300 Subject: floppy: use common function to check if floppies can be registered The same checks to see if a drive can be or is registered are repeated through the code, factor out the checks in a common function and replace the repeated checks with it. Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Jiri Kosina Signed-off-by: Jens Axboe --- drivers/block/floppy.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 2c7257334b64..d54b234a1a67 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4109,12 +4109,19 @@ static struct platform_driver floppy_driver = { static struct platform_device floppy_device[N_DRIVE]; +static bool floppy_available(int drive) +{ + if (!(allowed_drive_mask & (1 << drive))) + return false; + if (fdc_state[FDC(drive)].version == FDC_NONE) + return false; + return true; +} + static struct kobject *floppy_find(dev_t dev, int *part, void *data) { int drive = (*part & 3) | ((*part & 0x80) >> 5); - if (drive >= N_DRIVE || - !(allowed_drive_mask & (1 << drive)) || - fdc_state[FDC(drive)].version == FDC_NONE) + if (drive >= N_DRIVE || !floppy_available(drive)) return NULL; if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type)) return NULL; @@ -4281,9 +4288,7 @@ static int __init do_floppy_init(void) } for (drive = 0; drive < N_DRIVE; drive++) { - if (!(allowed_drive_mask & (1 << drive))) - continue; - if (fdc_state[FDC(drive)].version == FDC_NONE) + if (!floppy_available(drive)) continue; floppy_device[drive].name = floppy_device_name; @@ -4312,8 +4317,7 @@ out_unreg_platform_dev: platform_device_unregister(&floppy_device[drive]); out_remove_drives: while (drive--) { - if ((allowed_drive_mask & (1 << drive)) && - fdc_state[FDC(drive)].version != FDC_NONE) { + if (floppy_available(drive)) { del_gendisk(disks[drive]); device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos); platform_device_unregister(&floppy_device[drive]); @@ -4558,8 +4562,7 @@ static void __exit floppy_module_exit(void) for (drive = 0; drive < N_DRIVE; drive++) { del_timer_sync(&motor_off_timer[drive]); - if ((allowed_drive_mask & (1 << drive)) && - fdc_state[FDC(drive)].version != FDC_NONE) { + if (floppy_available(drive)) { del_gendisk(disks[drive]); device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos); platform_device_unregister(&floppy_device[drive]); -- cgit v1.2.3-55-g7522 From 1a4ae43e4feb570901667782678772fd31c1b125 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Tue, 30 Oct 2012 08:36:07 +0100 Subject: floppy: remove dr, reuse drive on do_floppy_init This is a small cleanup, that also may turn error handling of unitialized disks more readable. We don't need a separate variable to track allocated disks, remove dr and reuse drive variable instead. Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Jiri Kosina Signed-off-by: Jens Axboe --- drivers/block/floppy.c | 48 ++++++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index d54b234a1a67..1c49d7173966 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4131,8 +4131,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data) static int __init do_floppy_init(void) { - int i, unit, drive; - int err, dr; + int i, unit, drive, err; set_debugt(); interruptjiffies = resultjiffies = jiffies; @@ -4148,29 +4147,28 @@ static int __init do_floppy_init(void) if (!floppy_wq) return -ENOMEM; - for (dr = 0; dr < N_DRIVE; dr++) { - disks[dr] = alloc_disk(1); - if (!disks[dr]) { + for (drive = 0; drive < N_DRIVE; drive++) { + disks[drive] = alloc_disk(1); + if (!disks[drive]) { err = -ENOMEM; goto out_put_disk; } - disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock); - if (!disks[dr]->queue) { - put_disk(disks[dr]); + disks[drive]->queue = blk_init_queue(do_fd_request, &floppy_lock); + if (!disks[drive]->queue) { err = -ENOMEM; goto out_put_disk; } - blk_queue_max_hw_sectors(disks[dr]->queue, 64); - disks[dr]->major = FLOPPY_MAJOR; - disks[dr]->first_minor = TOMINOR(dr); - disks[dr]->fops = &floppy_fops; - sprintf(disks[dr]->disk_name, "fd%d", dr); + blk_queue_max_hw_sectors(disks[drive]->queue, 64); + disks[drive]->major = FLOPPY_MAJOR; + disks[drive]->first_minor = TOMINOR(drive); + disks[drive]->fops = &floppy_fops; + sprintf(disks[drive]->disk_name, "fd%d", drive); - init_timer(&motor_off_timer[dr]); - motor_off_timer[dr].data = dr; - motor_off_timer[dr].function = motor_off_callback; + init_timer(&motor_off_timer[drive]); + motor_off_timer[drive].data = drive; + motor_off_timer[drive].function = motor_off_callback; } err = register_blkdev(FLOPPY_MAJOR, "fd"); @@ -4332,17 +4330,15 @@ out_unreg_region: out_unreg_blkdev: unregister_blkdev(FLOPPY_MAJOR, "fd"); out_put_disk: - while (dr--) { - del_timer_sync(&motor_off_timer[dr]); - if (disks[dr]->queue) { - blk_cleanup_queue(disks[dr]->queue); - /* - * put_disk() is not paired with add_disk() and - * will put queue reference one extra time. fix it. - */ - disks[dr]->queue = NULL; + for (drive = 0; drive < N_DRIVE; drive++) { + if (!disks[drive]) + break; + if (disks[drive]->queue) { + del_timer_sync(&motor_off_timer[drive]); + blk_cleanup_queue(disks[drive]->queue); + disks[drive]->queue = NULL; } - put_disk(disks[dr]); + put_disk(disks[drive]); } destroy_workqueue(floppy_wq); return err; -- cgit v1.2.3-55-g7522 From 654dbef2146d6bc56886495d44b661148f016e62 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 27 Aug 2012 12:28:57 +0800 Subject: xen/blkback: use kmem_cache_zalloc instead of kmem_cache_alloc/memset Using kmem_cache_zalloc() instead of kmem_cache_alloc() and memset(). spatch with a semantic match is used to found this problem. (http://coccinelle.lip6.fr/) Signed-off-by: Wei Yongjun Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/xenbus.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index d0fed5582a42..f58434c2617c 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -105,11 +105,10 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid) { struct xen_blkif *blkif; - blkif = kmem_cache_alloc(xen_blkif_cachep, GFP_KERNEL); + blkif = kmem_cache_zalloc(xen_blkif_cachep, GFP_KERNEL); if (!blkif) return ERR_PTR(-ENOMEM); - memset(blkif, 0, sizeof(*blkif)); blkif->domid = domid; spin_lock_init(&blkif->blk_ring_lock); atomic_set(&blkif->refcnt, 1); -- cgit v1.2.3-55-g7522 From 2541aa799ff711fdd85dfbced58ea815a5968674 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 9 Sep 2012 12:40:50 +0200 Subject: cciss: remove unneeded memset() The memory return by kzalloc() or kmem_cache_zalloc() has already be set to zero, so remove useless memset(0). spatch with a semantic match is used to found this problem. (http://coccinelle.lip6.fr/) Signed-off-by: Wei Yongjun Cc: Mike Miller Cc: Jens Axboe Cc: Stephen M. Cameron Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- drivers/block/cciss.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index b0f553b26d0f..ca83f96756ad 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -5205,7 +5205,6 @@ static void cciss_shutdown(struct pci_dev *pdev) return; } /* write all data in the battery backed cache to disk */ - memset(flush_buf, 0, 4); return_code = sendcmd_withirq(h, CCISS_CACHE_FLUSH, flush_buf, 4, 0, CTLR_LUNID, TYPE_CMD); kfree(flush_buf); -- cgit v1.2.3-55-g7522 From b7010ede4342d3ab9f9a0c51c1aa50139aacadaf Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sun, 9 Sep 2012 12:47:47 +0200 Subject: cciss: select CONFIG_CHECK_SIGNATURE The patch cciss-use-check_signature.patch in -mm tree introduced a build error: drivers/built-in.o: In function `CISS_signature_present': drivers/block/cciss.c:4270: undefined reference to `check_signature' Add missing CONFIG_CHECK_SIGNATURE to fix this issue. Reported-by: Fengguang Wu Signed-off-by: Akinobu Mita Cc: Fengguang Wu Cc: Mike Miller Cc: Jens Axboe Acked-by: "Stephen M. Cameron" Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- drivers/block/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 6983a65c8df3..824e09c4d0d7 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -131,6 +131,7 @@ config BLK_CPQ_DA config BLK_CPQ_CISS_DA tristate "Compaq Smart Array 5xxx support" depends on PCI + select CHECK_SIGNATURE help This is the driver for Compaq Smart Array 5xxx controllers. Everyone using these boards should say Y here. -- cgit v1.2.3-55-g7522 From 1f999572f244f266c5b1b855025723541b0b475d Mon Sep 17 00:00:00 2001 From: Oliver Chick Date: Fri, 21 Sep 2012 10:04:18 +0100 Subject: xen/blkback: Change xen_vbd's flush_support and discard_secure to have type unsigned int, rather than bool Changing the type of bdev parameters to be unsigned int :1, rather than bool. This is more consistent with the types of other features in the block drivers. Signed-off-by: Oliver Chick Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Jens Axboe --- drivers/block/xen-blkback/common.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 9ad3b5ec1dc1..9a54623e52d7 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -158,8 +158,8 @@ struct xen_vbd { struct block_device *bdev; /* Cached size parameter. */ sector_t size; - bool flush_support; - bool discard_secure; + unsigned int flush_support:1; + unsigned int discard_secure:1; }; struct backend_info; -- cgit v1.2.3-55-g7522 From 4453bc88f0f7be6d84b50b2e1c1ed239c45fb14a Mon Sep 17 00:00:00 2001 From: Selvan Mani Date: Thu, 27 Sep 2012 14:36:43 +0200 Subject: mtip32xx:Added appropriate timeout value for secure erase Added appropriate timeout value for secure erase based on identify device data Signed-off-by: Asai Thambi S P Signed-off-by: Selvan Mani Signed-off-by: Jens Axboe --- drivers/block/mtip32xx/mtip32xx.c | 19 +++++++++++++++---- drivers/block/mtip32xx/mtip32xx.h | 3 +++ 2 files changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index f946d31d6917..adc6f36564cf 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -2035,8 +2035,9 @@ static unsigned int implicit_sector(unsigned char command, } return rv; } - -static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout) +static void mtip_set_timeout(struct driver_data *dd, + struct host_to_dev_fis *fis, + unsigned int *timeout, u8 erasemode) { switch (fis->command) { case ATA_CMD_DOWNLOAD_MICRO: @@ -2044,7 +2045,10 @@ static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout) break; case ATA_CMD_SEC_ERASE_UNIT: case 0xFC: - *timeout = 240000; /* 4 minutes */ + if (erasemode) + *timeout = ((*(dd->port->identify + 90) * 2) * 60000); + else + *timeout = ((*(dd->port->identify + 89) * 2) * 60000); break; case ATA_CMD_STANDBYNOW1: *timeout = 120000; /* 2 minutes */ @@ -2087,6 +2091,7 @@ static int exec_drive_taskfile(struct driver_data *dd, unsigned int transfer_size; unsigned long task_file_data; int intotal = outtotal + req_task->out_size; + int erasemode = 0; taskout = req_task->out_size; taskin = req_task->in_size; @@ -2212,7 +2217,13 @@ static int exec_drive_taskfile(struct driver_data *dd, fis.lba_hi, fis.device); - mtip_set_timeout(&fis, &timeout); + /* check for erase mode support during secure erase.*/ + if ((fis.command == ATA_CMD_SEC_ERASE_UNIT) + && (outbuf[0] & MTIP_SEC_ERASE_MODE)) { + erasemode = 1; + } + + mtip_set_timeout(dd, &fis, &timeout, erasemode); /* Determine the correct transfer size.*/ if (force_single_sector) diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h index 18627a1d04c5..5f4a917bd8bb 100644 --- a/drivers/block/mtip32xx/mtip32xx.h +++ b/drivers/block/mtip32xx/mtip32xx.h @@ -33,6 +33,9 @@ /* offset of Device Control register in PCIe extended capabilites space */ #define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET 0x48 +/* check for erase mode support during secure erase */ +#define MTIP_SEC_ERASE_MODE 0x3 + /* # of times to retry timed out/failed IOs */ #define MTIP_MAX_RETRIES 2 -- cgit v1.2.3-55-g7522 From a1ecac3b0656a68259927c234e505804d33a7b83 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Fri, 28 Sep 2012 10:42:23 +0200 Subject: loop: Make explicit loop device destruction lazy xfstests has always had random failures of tests due to loop devices failing to be torn down and hence leaving filesytems that cannot be unmounted. This causes test runs to immediately stop. Over the past 6 or 7 years we've added hacks like explicit unmount -d commands for loop mounts, losetup -d after unmount -d fails, etc, but still the problems persist. Recently, the frequency of loop related failures increased again to the point that xfstests 259 will reliably fail with a stray loop device that was not torn down. That is despite the fact the test is above as simple as it gets - loop 5 or 6 times running mkfs.xfs with different paramters: lofile=$(losetup -f) losetup $lofile "$testfile" "$MKFS_XFS_PROG" -b size=512 $lofile >/dev/null || echo "mkfs failed!" sync losetup -d $lofile And losteup -d $lofile is failing with EBUSY on 1-3 of these loops every time the test is run. Turns out that blkid is running simultaneously with losetup -d, and so it sees an elevated reference count and returns EBUSY. But why is blkid running? It's obvious, isn't it? udev has decided to try and find out what is on the block device as a result of a creation notification. And it is racing with mkfs, so might still be scanning the device when mkfs finishes and we try to tear it down. So, make losetup -d force autoremove behaviour. That is, when the last reference goes away, tear down the device. xfstests wants it *gone*, not causing random teardown failures when we know that all the operations the tests have specifically run on the device have completed and are no longer referencing the loop device. Signed-off-by: Dave Chinner Signed-off-by: Jens Axboe --- drivers/block/loop.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/block/loop.c b/drivers/block/loop.c index e9d594fd12cb..54046e51160a 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -976,8 +976,21 @@ static int loop_clr_fd(struct loop_device *lo) if (lo->lo_state != Lo_bound) return -ENXIO; - if (lo->lo_refcnt > 1) /* we needed one fd for the ioctl */ - return -EBUSY; + /* + * If we've explicitly asked to tear down the loop device, + * and it has an elevated reference count, set it for auto-teardown when + * the last reference goes away. This stops $!~#$@ udev from + * preventing teardown because it decided that it needs to run blkid on + * the loopback device whenever they appear. xfstests is notorious for + * failing tests because blkid via udev races with a losetup + * /do something like mkfs/losetup -d causing the losetup -d + * command to fail with EBUSY. + */ + if (lo->lo_refcnt > 1) { + lo->lo_flags |= LO_FLAGS_AUTOCLEAR; + mutex_unlock(&lo->lo_ctl_mutex); + return 0; + } if (filp == NULL) return -EINVAL; -- cgit v1.2.3-55-g7522 From a67baeb77375199bbd842fa308cb565164dd1f19 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Wed, 24 Oct 2012 12:39:02 +0100 Subject: xen/gntdev: don't leak memory from IOCTL_GNTDEV_MAP_GRANT_REF map->kmap_ops allocated in gntdev_alloc_map() wasn't freed by gntdev_put_map(). Add a gntdev_free_map() helper function to free everything allocated by gntdev_alloc_map(). Signed-off-by: David Vrabel Cc: stable@vger.kernel.org Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/gntdev.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 610bfc6be177..2e22df2f7a3f 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -105,6 +105,21 @@ static void gntdev_print_maps(struct gntdev_priv *priv, #endif } +static void gntdev_free_map(struct grant_map *map) +{ + if (map == NULL) + return; + + if (map->pages) + free_xenballooned_pages(map->count, map->pages); + kfree(map->pages); + kfree(map->grants); + kfree(map->map_ops); + kfree(map->unmap_ops); + kfree(map->kmap_ops); + kfree(map); +} + static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) { struct grant_map *add; @@ -142,12 +157,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) return add; err: - kfree(add->pages); - kfree(add->grants); - kfree(add->map_ops); - kfree(add->unmap_ops); - kfree(add->kmap_ops); - kfree(add); + gntdev_free_map(add); return NULL; } @@ -198,17 +208,9 @@ static void gntdev_put_map(struct grant_map *map) evtchn_put(map->notify.event); } - if (map->pages) { - if (!use_ptemod) - unmap_grant_pages(map, 0, map->count); - - free_xenballooned_pages(map->count, map->pages); - } - kfree(map->pages); - kfree(map->grants); - kfree(map->map_ops); - kfree(map->unmap_ops); - kfree(map); + if (map->pages && !use_ptemod) + unmap_grant_pages(map, 0, map->count); + gntdev_free_map(map); } /* ------------------------------------------------------------------ */ -- cgit v1.2.3-55-g7522 From 01bc825f6311ba2878ae353418eee575d3051594 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Thu, 18 Oct 2012 11:03:37 +0100 Subject: xen-fbfront: handle backend CLOSED without CLOSING Backend drivers shouldn't transistion to CLOSED unless the frontend is CLOSED. If a backend does transition to CLOSED too soon then the frontend may not see the CLOSING state and will not properly shutdown. So, treat an unexpected backend CLOSED state the same as CLOSING. Acked-by: Florian Tobias Schandinat Signed-off-by: David Vrabel Signed-off-by: Konrad Rzeszutek Wilk --- drivers/video/xen-fbfront.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c index b7f5173ff9e9..917bb5681684 100644 --- a/drivers/video/xen-fbfront.c +++ b/drivers/video/xen-fbfront.c @@ -641,7 +641,6 @@ static void xenfb_backend_changed(struct xenbus_device *dev, case XenbusStateReconfiguring: case XenbusStateReconfigured: case XenbusStateUnknown: - case XenbusStateClosed: break; case XenbusStateInitWait: @@ -670,6 +669,10 @@ InitWait: info->feature_resize = val; break; + case XenbusStateClosed: + if (dev->state == XenbusStateClosed) + break; + /* Missed the backend's CLOSING state -- fallthrough */ case XenbusStateClosing: xenbus_frontend_closed(dev); break; -- cgit v1.2.3-55-g7522 From 2ebb939ab9c6a2484866c5eae4184c83c2b21af8 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Thu, 18 Oct 2012 11:03:38 +0100 Subject: xen-kbdfront: handle backend CLOSED without CLOSING Backend drivers shouldn't transistion to CLOSED unless the frontend is CLOSED. If a backend does transition to CLOSED too soon then the frontend may not see the CLOSING state and will not properly shutdown. So, treat an unexpected backend CLOSED state the same as CLOSING. Acked-by: Dmitry Torokhov Signed-off-by: David Vrabel Signed-off-by: Konrad Rzeszutek Wilk --- drivers/input/misc/xen-kbdfront.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index 02ca8680ea5b..6f7d99013031 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -311,7 +311,6 @@ static void xenkbd_backend_changed(struct xenbus_device *dev, case XenbusStateReconfiguring: case XenbusStateReconfigured: case XenbusStateUnknown: - case XenbusStateClosed: break; case XenbusStateInitWait: @@ -350,6 +349,10 @@ InitWait: break; + case XenbusStateClosed: + if (dev->state == XenbusStateClosed) + break; + /* Missed the backend's CLOSING state -- fallthrough */ case XenbusStateClosing: xenbus_frontend_closed(dev); break; -- cgit v1.2.3-55-g7522 From 1bcaba51eba549748917f7d6eb41900ff9ee3d5f Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Wed, 17 Oct 2012 13:14:09 -0400 Subject: xen/xenbus: fix overflow check in xenbus_file_write() Acked-by: Ian Campbell Reported-by: Dan Carpenter Signed-off-by: Jan Beulich [v1: Rebased on upstream] Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xenbus/xenbus_dev_frontend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c index 89f76252a16f..ac727028e658 100644 --- a/drivers/xen/xenbus/xenbus_dev_frontend.c +++ b/drivers/xen/xenbus/xenbus_dev_frontend.c @@ -458,7 +458,7 @@ static ssize_t xenbus_file_write(struct file *filp, goto out; /* Can't write a xenbus message larger we can buffer */ - if ((len + u->len) > sizeof(u->u.buffer)) { + if (len > sizeof(u->u.buffer) - u->len) { /* On error, dump existing buffer */ u->len = 0; rc = -EINVAL; -- cgit v1.2.3-55-g7522 From bf7e1abe434ba9e22e8dc04a4cba4ab504b788b8 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 25 Oct 2012 09:51:39 +0200 Subject: rt2800: validate step value for temperature compensation Some hardware has correct (!= 0xff) value of tssi_bounds[4] in the EEPROM, but step is equal to 0xff. This results on ridiculous delta calculations and completely broke TX power settings. Reported-and-tested-by: Pavel Lucik Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 01dc8891070c..59474ae0aec0 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2449,7 +2449,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) /* * Check if temperature compensation is supported. */ - if (tssi_bounds[4] == 0xff) + if (tssi_bounds[4] == 0xff || step == 0xff) return 0; /* -- cgit v1.2.3-55-g7522 From 6fe7cc71bbf3a0bc28c9cec3c00bc11e81344412 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Mon, 29 Oct 2012 13:25:20 +0100 Subject: ath9k: Test for TID only in BlockAcks while checking tx status The ath9k xmit functions for AMPDUs can send frames as non-aggregate in case only one frame is currently available. The client will then answer using a normal Ack instead of a BlockAck. This acknowledgement has no TID stored and therefore the hardware is not able to provide us the corresponding TID. The TID set by the hardware in the tx status descriptor has to be seen as undefined and not as a valid TID value for normal acknowledgements. Doing otherwise results in a massive amount of retransmissions and stalls of connections. Users may experience low bandwidth and complete connection stalls in environments with transfers using multiple TIDs. This regression was introduced in b11b160defc48e4daa283f785192ea3a23a51f8e ("ath9k: validate the TID in the tx status information"). Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich Cc: stable@vger.kernel.org Acked-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 1ffca7511fa8..741918a2027b 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -394,7 +394,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first; u32 ba[WME_BA_BMP_SIZE >> 5]; int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; - bool rc_update = true; + bool rc_update = true, isba; struct ieee80211_tx_rate rates[4]; struct ath_frame_info *fi; int nframes; @@ -438,13 +438,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; tid = ATH_AN_2_TID(an, tidno); seq_first = tid->seq_start; + isba = ts->ts_flags & ATH9K_TX_BA; /* * The hardware occasionally sends a tx status for the wrong TID. * In this case, the BA status cannot be considered valid and all * subframes need to be retransmitted + * + * Only BlockAcks have a TID and therefore normal Acks cannot be + * checked */ - if (tidno != ts->tid) + if (isba && tidno != ts->tid) txok = false; isaggr = bf_isaggr(bf); -- cgit v1.2.3-55-g7522 From 8fcff5f13773aa3898df1d13a1615d468079cb15 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 27 Oct 2012 15:28:58 +0200 Subject: GPIO: mvebu-gpio: Don't initialize the mask_cache Due to the SMP nature of some of the chips, which have per CPU registers, the driver does not use the generic irq_gc_mask_set_bit() & irq_gc_mask_clr_bit() functions, which only support a single register. The driver has its own implementation of these functions, which can pick the correct register depending on the CPU being used. The functions do however use the gc->mask_cache value. The call to irq_setup_generic_chip() was passing IRQ_GC_INIT_MASK_CACHE, which caused the gc->mask_cache to be initialized to the contents of some random register. This resulted in unexpected interrupts been delivered from random GPIO lines. Signed-off-by: Andrew Lunn Tested-by: Jamie Lentin Acked-by: Thomas Petazzoni Tested-by: Michael Walle Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mvebu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 1bb43e3f9a61..fec421fe59b2 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -643,7 +643,7 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev) ct->handler = handle_edge_irq; ct->chip.name = mvchip->chip.label; - irq_setup_generic_chip(gc, IRQ_MSK(ngpios), IRQ_GC_INIT_MASK_CACHE, + irq_setup_generic_chip(gc, IRQ_MSK(ngpios), 0, IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); /* Setup irq domain on top of the generic chip. */ -- cgit v1.2.3-55-g7522 From 02b898f2f04e418094f0093a3ad0b415bcdbe8eb Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 31 Oct 2012 11:42:03 +1100 Subject: md/raid1: Fix assembling of arrays containing Replacements. setup_conf in raid1.c uses conf->raid_disks before assigning a value. It is used when including 'Replacement' devices. The consequence is that assembling an array which contains a replacement will misbehave and either not include the replacement, or not include the device being replaced. Though this doesn't lead directly to data corruption, it could lead to reduced data safety. So use mddev->raid_disks, which is initialised, instead. Bug was introduced by commit c19d57980b38a5bb613a898937a1cf85f422fb9b md/raid1: recognise replacements when assembling arrays. in 3.3, so fix is suitable for 3.3.y thru 3.6.y. Cc: stable@vger.kernel.org Signed-off-by: NeilBrown --- drivers/md/raid1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 8034fbd6190c..636bae0405e8 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2710,7 +2710,7 @@ static struct r1conf *setup_conf(struct mddev *mddev) || disk_idx < 0) continue; if (test_bit(Replacement, &rdev->flags)) - disk = conf->mirrors + conf->raid_disks + disk_idx; + disk = conf->mirrors + mddev->raid_disks + disk_idx; else disk = conf->mirrors + disk_idx; -- cgit v1.2.3-55-g7522 From ed30be077e705e0dff53bfc51d23feb8aeeab78f Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Wed, 31 Oct 2012 11:42:30 +1100 Subject: MD RAID10: Fix oops when creating RAID10 arrays via dm-raid.c Commit 2863b9eb didn't take into account the changes to add TRIM support to RAID10 (commit 532a2a3fb). That is, when using dm-raid.c to create the RAID10 arrays, there is no mddev->gendisk or mddev->queue. The code added to support TRIM simply assumes that mddev->queue is available without checking. The result is an oops any time dm-raid.c attempts to create a RAID10 device. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/raid10.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 906ccbd0f7dc..d1295aff4173 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1783,7 +1783,7 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev) clear_bit(Unmerged, &rdev->flags); } md_integrity_add_rdev(rdev, mddev); - if (blk_queue_discard(bdev_get_queue(rdev->bdev))) + if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev))) queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); print_conf(conf); @@ -3613,11 +3613,14 @@ static int run(struct mddev *mddev) discard_supported = true; } - if (discard_supported) - queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); - else - queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); - + if (mddev->queue) { + if (discard_supported) + queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, + mddev->queue); + else + queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, + mddev->queue); + } /* need to check that every block has at least one working mirror */ if (!enough(conf, -1)) { printk(KERN_ERR "md/raid10:%s: not enough operational mirrors.\n", -- cgit v1.2.3-55-g7522 From cee59f15a60cc6269a25e3f6fbf1a577d6ab8115 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 29 Oct 2012 09:03:07 +1000 Subject: drm/nouveau: silence modesetting spam on pre-gf8 chipsets Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv04_dac.c | 16 ++++++++-------- drivers/gpu/drm/nouveau/nv04_dfp.c | 14 +++++++------- drivers/gpu/drm/nouveau/nv04_tv.c | 9 ++++----- 3 files changed, 19 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c index 347a3bd78d04..64f7020fb605 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/nv04_dac.c @@ -220,7 +220,7 @@ out: NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode); if (blue == 0x18) { - NV_INFO(drm, "Load detected on head A\n"); + NV_DEBUG(drm, "Load detected on head A\n"); return connector_status_connected; } @@ -338,8 +338,8 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) if (nv17_dac_sample_load(encoder) & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { - NV_INFO(drm, "Load detected on output %c\n", - '@' + ffs(dcb->or)); + NV_DEBUG(drm, "Load detected on output %c\n", + '@' + ffs(dcb->or)); return connector_status_connected; } else { return connector_status_disconnected; @@ -413,9 +413,9 @@ static void nv04_dac_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", - drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), - nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); + NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", + drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), + nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable) @@ -461,8 +461,8 @@ static void nv04_dac_dpms(struct drm_encoder *encoder, int mode) return; nv_encoder->last_dpms = mode; - NV_INFO(drm, "Setting dpms mode %d on vga encoder (output %d)\n", - mode, nv_encoder->dcb->index); + NV_DEBUG(drm, "Setting dpms mode %d on vga encoder (output %d)\n", + mode, nv_encoder->dcb->index); nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); } diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index da55d7642c8c..184cdf806761 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -476,9 +476,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", - drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), - nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); + NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", + drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), + nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) @@ -520,8 +520,8 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) return; nv_encoder->last_dpms = mode; - NV_INFO(drm, "Setting dpms mode %d on lvds encoder (output %d)\n", - mode, nv_encoder->dcb->index); + NV_DEBUG(drm, "Setting dpms mode %d on lvds encoder (output %d)\n", + mode, nv_encoder->dcb->index); if (was_powersaving && is_powersaving_dpms(mode)) return; @@ -565,8 +565,8 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode) return; nv_encoder->last_dpms = mode; - NV_INFO(drm, "Setting dpms mode %d on tmds encoder (output %d)\n", - mode, nv_encoder->dcb->index); + NV_DEBUG(drm, "Setting dpms mode %d on tmds encoder (output %d)\n", + mode, nv_encoder->dcb->index); nv04_dfp_update_backlight(encoder, mode); nv04_dfp_update_fp_control(encoder, mode); diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c index 099fbeda6e2e..62e826a139b3 100644 --- a/drivers/gpu/drm/nouveau/nv04_tv.c +++ b/drivers/gpu/drm/nouveau/nv04_tv.c @@ -75,8 +75,8 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode) struct nv04_mode_state *state = &nv04_display(dev)->mode_reg; uint8_t crtc1A; - NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n", - mode, nv_encoder->dcb->index); + NV_DEBUG(drm, "Setting dpms mode %d on TV encoder (output %d)\n", + mode, nv_encoder->dcb->index); state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK); @@ -167,9 +167,8 @@ static void nv04_tv_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", - drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, - '@' + ffs(nv_encoder->dcb->or)); + NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", + drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } static void nv04_tv_destroy(struct drm_encoder *encoder) -- cgit v1.2.3-55-g7522 From 1249ac592a2f995fef977be33abf077bdb57b3aa Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 30 Oct 2012 15:07:58 +1000 Subject: drm/nouveau/i2c: fix typo when checking nvio i2c port validity Reported-by: Mathieu Chouquet-Stringer Tested-by: Mathieu Chouquet-Stringer Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/i2c/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index 3d2c88310f98..dbfc2abf0cfe 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c @@ -292,7 +292,7 @@ nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, case DCB_I2C_NVIO_BIT: port->drive = info.drive & 0x0f; if (device->card_type < NV_D0) { - if (info.drive >= ARRAY_SIZE(nv50_i2c_port)) + if (port->drive >= ARRAY_SIZE(nv50_i2c_port)) break; port->drive = nv50_i2c_port[port->drive]; port->sense = port->drive; -- cgit v1.2.3-55-g7522 From a7dbf00433fa9dc6f4a3828a17d56a9df2bd06b1 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 31 Oct 2012 11:19:40 +1000 Subject: drm/nouveau: allow creation of zero-sized mm Useful for places where a given chipset may or may not have a given resource, and we want to avoid having to spray checks for the mm's existance around everywhere. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/core/mm.c | 9 ++++++--- drivers/gpu/drm/nouveau/core/include/core/mm.h | 1 - 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/core/core/mm.c b/drivers/gpu/drm/nouveau/core/core/mm.c index 4d6206448670..a6d3cd6490f7 100644 --- a/drivers/gpu/drm/nouveau/core/core/mm.c +++ b/drivers/gpu/drm/nouveau/core/core/mm.c @@ -218,13 +218,16 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block) node = kzalloc(sizeof(*node), GFP_KERNEL); if (!node) return -ENOMEM; - node->offset = roundup(offset, mm->block_size); - node->length = rounddown(offset + length, mm->block_size) - node->offset; + + if (length) { + node->offset = roundup(offset, mm->block_size); + node->length = rounddown(offset + length, mm->block_size); + node->length -= node->offset; + } list_add_tail(&node->nl_entry, &mm->nodes); list_add_tail(&node->fl_entry, &mm->free); mm->heap_nodes++; - mm->heap_size += length; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/include/core/mm.h b/drivers/gpu/drm/nouveau/core/include/core/mm.h index 9ee9bf4028ca..975137ba34a6 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/mm.h +++ b/drivers/gpu/drm/nouveau/core/include/core/mm.h @@ -19,7 +19,6 @@ struct nouveau_mm { u32 block_size; int heap_nodes; - u32 heap_size; }; int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block); -- cgit v1.2.3-55-g7522 From 5cad16acd25b16681a060d28d10eeacf98d07701 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 31 Oct 2012 10:51:00 +1000 Subject: drm/nv50/fb: prevent oops on chipsets without compression tags Unconditionally create the tagram mm, even if there's zero tags. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c index 27fb1af7a779..5f570806143a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c @@ -219,13 +219,11 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ((priv->base.ram.size & 0x000000ff) << 32); tags = nv_rd32(priv, 0x100320); - if (tags) { - ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1); - if (ret) - return ret; + ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1); + if (ret) + return ret; - nv_debug(priv, "%d compression tags\n", tags); - } + nv_debug(priv, "%d compression tags\n", tags); size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail; switch (device->chipset) { -- cgit v1.2.3-55-g7522 From 9430738d80223a1cd791a2baa74fa170d3df1262 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 31 Oct 2012 12:11:15 +1000 Subject: drm/nouveau: resurrect headless mode since rework Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_display.c | 34 +++++++++++++++++-------------- drivers/gpu/drm/nouveau/nouveau_drm.c | 34 +++++++++++++++++++------------ drivers/gpu/drm/nouveau/nouveau_drm.h | 2 ++ drivers/gpu/drm/nouveau/nouveau_irq.c | 16 ++++++++------- 4 files changed, 51 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index d2f8ffeed742..0185837d9862 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -360,23 +360,26 @@ nouveau_display_create(struct drm_device *dev) drm_kms_helper_poll_init(dev); drm_kms_helper_poll_disable(dev); - if (nv_device(drm->device)->card_type < NV_50) - ret = nv04_display_create(dev); - else - if (nv_device(drm->device)->card_type < NV_D0) - ret = nv50_display_create(dev); - else - ret = nvd0_display_create(dev); - if (ret) - goto disp_create_err; - - if (dev->mode_config.num_crtc) { - ret = drm_vblank_init(dev, dev->mode_config.num_crtc); + if (nouveau_modeset == 1) { + if (nv_device(drm->device)->card_type < NV_50) + ret = nv04_display_create(dev); + else + if (nv_device(drm->device)->card_type < NV_D0) + ret = nv50_display_create(dev); + else + ret = nvd0_display_create(dev); if (ret) - goto vblank_err; + goto disp_create_err; + + if (dev->mode_config.num_crtc) { + ret = drm_vblank_init(dev, dev->mode_config.num_crtc); + if (ret) + goto vblank_err; + } + + nouveau_backlight_init(dev); } - nouveau_backlight_init(dev); return 0; vblank_err: @@ -395,7 +398,8 @@ nouveau_display_destroy(struct drm_device *dev) nouveau_backlight_exit(dev); drm_vblank_cleanup(dev); - disp->dtor(dev); + if (disp->dtor) + disp->dtor(dev); drm_kms_helper_poll_fini(dev); drm_mode_config_cleanup(dev); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index ccae8c26ae2b..9cc83f18f9dc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -63,8 +63,9 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration"); static int nouveau_noaccel = 0; module_param_named(noaccel, nouveau_noaccel, int, 0400); -MODULE_PARM_DESC(modeset, "enable driver"); -static int nouveau_modeset = -1; +MODULE_PARM_DESC(modeset, "enable driver (default: auto, " + "0 = disabled, 1 = enabled, 2 = headless)"); +int nouveau_modeset = -1; module_param_named(modeset, nouveau_modeset, int, 0400); static struct drm_driver driver; @@ -363,7 +364,8 @@ nouveau_drm_unload(struct drm_device *dev) nouveau_pm_fini(dev); - nouveau_display_fini(dev); + if (dev->mode_config.num_crtc) + nouveau_display_fini(dev); nouveau_display_destroy(dev); nouveau_irq_fini(dev); @@ -403,13 +405,15 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state) pm_state.event == PM_EVENT_PRETHAW) return 0; - NV_INFO(drm, "suspending fbcon...\n"); - nouveau_fbcon_set_suspend(dev, 1); + if (dev->mode_config.num_crtc) { + NV_INFO(drm, "suspending fbcon...\n"); + nouveau_fbcon_set_suspend(dev, 1); - NV_INFO(drm, "suspending display...\n"); - ret = nouveau_display_suspend(dev); - if (ret) - return ret; + NV_INFO(drm, "suspending display...\n"); + ret = nouveau_display_suspend(dev); + if (ret) + return ret; + } NV_INFO(drm, "evicting buffers...\n"); ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM); @@ -445,8 +449,10 @@ fail_client: nouveau_client_init(&cli->base); } - NV_INFO(drm, "resuming display...\n"); - nouveau_display_resume(dev); + if (dev->mode_config.num_crtc) { + NV_INFO(drm, "resuming display...\n"); + nouveau_display_resume(dev); + } return ret; } @@ -486,8 +492,10 @@ nouveau_drm_resume(struct pci_dev *pdev) nouveau_irq_postinstall(dev); nouveau_pm_resume(dev); - NV_INFO(drm, "resuming display...\n"); - nouveau_display_resume(dev); + if (dev->mode_config.num_crtc) { + NV_INFO(drm, "resuming display...\n"); + nouveau_display_resume(dev); + } return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h index 819471217546..a10169927086 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/drivers/gpu/drm/nouveau/nouveau_drm.h @@ -141,4 +141,6 @@ int nouveau_drm_resume(struct pci_dev *); nv_info((cli), fmt, ##args); \ } while (0) +extern int nouveau_modeset; + #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 9ca8afdb5549..1d8cb506a28a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c @@ -61,13 +61,15 @@ nouveau_irq_handler(DRM_IRQ_ARGS) nv_subdev(pmc)->intr(nv_subdev(pmc)); - if (device->card_type >= NV_D0) { - if (nv_rd32(device, 0x000100) & 0x04000000) - nvd0_display_intr(dev); - } else - if (device->card_type >= NV_50) { - if (nv_rd32(device, 0x000100) & 0x04000000) - nv50_display_intr(dev); + if (dev->mode_config.num_crtc) { + if (device->card_type >= NV_D0) { + if (nv_rd32(device, 0x000100) & 0x04000000) + nvd0_display_intr(dev); + } else + if (device->card_type >= NV_50) { + if (nv_rd32(device, 0x000100) & 0x04000000) + nv50_display_intr(dev); + } } return IRQ_HANDLED; -- cgit v1.2.3-55-g7522 From e412e95a268fa8544858ebfe066826b290430d51 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 31 Oct 2012 12:16:06 +1000 Subject: drm/nouveau: headless mode by default if pci class != vga display This is to prevent nouveau from taking over the console on headless boards such as Tesla. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_display.c | 4 +++- drivers/gpu/drm/nouveau/nouveau_drm.c | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 0185837d9862..86124b131f4f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -290,6 +290,7 @@ nouveau_display_create(struct drm_device *dev) struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_disp *pdisp = nouveau_disp(drm->device); struct nouveau_display *disp; + u32 pclass = dev->pdev->class >> 8; int ret, gen; disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL); @@ -360,7 +361,8 @@ nouveau_display_create(struct drm_device *dev) drm_kms_helper_poll_init(dev); drm_kms_helper_poll_disable(dev); - if (nouveau_modeset == 1) { + if (nouveau_modeset == 1 || + (nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) { if (nv_device(drm->device)->card_type < NV_50) ret = nv04_display_create(dev); else diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 9cc83f18f9dc..0910125cbbc3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -670,9 +670,7 @@ nouveau_drm_init(void) #ifdef CONFIG_VGA_CONSOLE if (vgacon_text_force()) nouveau_modeset = 0; - else #endif - nouveau_modeset = 1; } if (!nouveau_modeset) -- cgit v1.2.3-55-g7522 From 32ed1911fc79908d704023317d4ddeb3883fd07e Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Tue, 30 Oct 2012 23:39:10 -0700 Subject: Input: tsc40 - remove wrong announcement of pressure support The tsc40 driver announces it supports the pressure event, but will never send one. The announcement will cause tslib to wait for such events and sending all touch events with a pressure of 0. Removing the announcement will make tslib fall back to emulating the pressure on touch events so everything works as expected. Signed-off-by: Rolf Eike Beer Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc40.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c index 63209aaa55f0..eb96f168fb9d 100644 --- a/drivers/input/touchscreen/tsc40.c +++ b/drivers/input/touchscreen/tsc40.c @@ -107,7 +107,6 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv) __set_bit(BTN_TOUCH, input_dev->keybit); input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0); input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0); - input_set_abs_params(ptsc->dev, ABS_PRESSURE, 0, 0, 0, 0); serio_set_drvdata(serio, ptsc); -- cgit v1.2.3-55-g7522 From 3ccc60f9d8c39180c205dba1a020735bda1b2491 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 19 Oct 2012 13:28:46 +0200 Subject: HID: microsoft: fix invalid rdesc for 3k kbd Microsoft Digital Media Keyboard 3000 has two interfaces, and the second one has a report descriptor with a bug. The second collection says: 05 01 -- global; usage page -- 01 -- Generic Desktop Controls 09 80 -- local; usage -- 80 -- System Control a1 01 -- main; collection -- 01 -- application 85 03 -- global; report ID -- 03 19 00 -- local; Usage Minimum -- 00 29 ff -- local; Usage Maximum -- ff 15 00 -- global; Logical Minimum -- 0 26 ff 00 -- global; Logical Maximum -- ff 81 00 -- main; input c0 -- main; End Collection I.e. it makes us think that there are all kinds of usages of system control. That the keyboard is a not only a keyboard, but also a joystick, mouse, gamepad, keypad, etc. The same as for the Wireless Desktop Receiver, this should be Physical Min/Max. So fix that appropriately. References: https://bugzilla.novell.com/show_bug.cgi?id=776834 Cc: Signed-off-by: Jiri Slaby Signed-off-by: Jiri Kosina --- drivers/hid/hid-microsoft.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 3acdcfcc17df..f676c01bb471 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -28,22 +28,30 @@ #define MS_RDESC 0x08 #define MS_NOGET 0x10 #define MS_DUPLICATE_USAGES 0x20 +#define MS_RDESC_3K 0x40 -/* - * Microsoft Wireless Desktop Receiver (Model 1028) has - * 'Usage Min/Max' where it ought to have 'Physical Min/Max' - */ static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); + /* + * Microsoft Wireless Desktop Receiver (Model 1028) has + * 'Usage Min/Max' where it ought to have 'Physical Min/Max' + */ if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 && rdesc[559] == 0x29) { hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n"); rdesc[557] = 0x35; rdesc[559] = 0x45; } + /* the same as above (s/usage/physical/) */ + if ((quirks & MS_RDESC_3K) && *rsize == 106 && + !memcmp((char []){ 0x19, 0x00, 0x29, 0xff }, + &rdesc[94], 4)) { + rdesc[94] = 0x35; + rdesc[96] = 0x45; + } return rdesc; } @@ -192,7 +200,7 @@ static const struct hid_device_id ms_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB), .driver_data = MS_PRESENTER }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K), - .driver_data = MS_ERGONOMY }, + .driver_data = MS_ERGONOMY | MS_RDESC_3K }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0), .driver_data = MS_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), -- cgit v1.2.3-55-g7522 From 65b258e9b57980c8241342928d5cd717ee11a68b Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 25 Oct 2012 15:35:25 +0100 Subject: HID: multitouch: put the case in the right switch statement Signed-off-by: Alan Cox Acked-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 3eb02b94fc87..c97011cdf852 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -421,11 +421,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, * contact max are global to the report */ td->last_field_index = field->index; return -1; - } case HID_DG_TOUCH: /* Legacy devices use TIPSWITCH and not TOUCH. * Let's just ignore this field. */ return -1; + } /* let hid-input decide for the others */ return 0; -- cgit v1.2.3-55-g7522 From 58ad34bf62b9fc52c04e6aabe3ad5a47e4a00dc1 Mon Sep 17 00:00:00 2001 From: Xianhan Yu Date: Mon, 29 Oct 2012 23:04:37 +0800 Subject: HID: multitouch: fix maxcontacts problem on GeneralTouch Fix maxcontacts problem for PWT GeneralTouch multi-touchscreen. Our device didn't contain HID_DG_CONTACTMAX usage. This usage use to describe touchscreen's maxcontacts for hid-multitouch.c to get maxcontacts automatic. We fix the device that driver can get maxcontact from our device, hence it doesn't need .maxcontact=10. Now there is just one device class can fix all our PWT touchscreen. Signed-off-by: Xianhan Yu Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index c97011cdf852..7867d69f0efe 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -210,8 +210,7 @@ static struct mt_class mt_classes[] = { }, { .name = MT_CLS_GENERALTOUCH_PWT_TENFINGERS, .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | - MT_QUIRK_SLOT_IS_CONTACTNUMBER, - .maxcontacts = 10 + MT_QUIRK_SLOT_IS_CONTACTNUMBER }, { .name = MT_CLS_FLATFROG, -- cgit v1.2.3-55-g7522 From 8d80da90f53d37cf6caefc61353e1cc3a145b9e0 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Tue, 30 Oct 2012 11:11:48 -0700 Subject: HID: Add support for the MacBook Pro 10,2 keyboard / touchpad This enables the existing drivers for keyboard and touchpad with the new USB IDs found on the MBP 13" Reasonable Resolution (also known as the Retina Display). Added entries to both keyboard and mouse ignore lists. Signed-off-by: Dirk Hohndel Signed-off-by: Jiri Kosina --- drivers/hid/hid-apple.c | 6 ++++++ drivers/hid/hid-core.c | 6 ++++++ drivers/hid/hid-ids.h | 3 +++ drivers/input/mouse/bcm5974.c | 21 +++++++++++++++++++++ 4 files changed, 36 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 06ebdbb6ea02..fd7722aecf77 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -522,6 +522,12 @@ static const struct hid_device_id apple_devices[] = { .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS), .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI), + .driver_data = APPLE_HAS_FN }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO), + .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS), + .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index bd3971bf31bf..f4109fd657ff 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1532,6 +1532,9 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, @@ -2139,6 +2142,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { } diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 269b50912a4a..9d7a42857ea1 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -118,6 +118,9 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI 0x0252 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO 0x0253 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS 0x0254 +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI 0x0259 +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO 0x025a +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS 0x025b #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI 0x0249 #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a #define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 3a78f235fa3e..2baff1b79a55 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -84,6 +84,10 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI 0x0262 #define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO 0x0263 #define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS 0x0264 +/* MacbookPro10,2 (unibody, October 2012) */ +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI 0x0259 +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO 0x025a +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS 0x025b #define BCM5974_DEVICE(prod) { \ .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ @@ -137,6 +141,10 @@ static const struct usb_device_id bcm5974_table[] = { BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ISO), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_JIS), + /* MacbookPro10,2 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS), /* Terminating entry */ {} }; @@ -379,6 +387,19 @@ static const struct bcm5974_config bcm5974_config_table[] = { { SN_COORD, -150, 6730 }, { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } }, + { + USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI, + USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO, + USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS, + HAS_INTEGRATED_BUTTON, + 0x84, sizeof(struct bt_data), + 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, + { SN_PRESSURE, 0, 300 }, + { SN_WIDTH, 0, 2048 }, + { SN_COORD, -4750, 5280 }, + { SN_COORD, -150, 6730 }, + { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + }, {} }; -- cgit v1.2.3-55-g7522 From 44c91697fb1add76f9f8c28c0d21b82b05b5d4cb Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Thu, 18 Oct 2012 18:59:55 +0900 Subject: drm/exynos: fix display on issue When crtc_funcs->dpms callback is called, exynos_crtc->dpms and exynos_encoder->dpms are changed to new mode. But if user requests dpms mode operation, OFF -> ON, when crtc's dpms callback is called, exynos_encoder->dpms is also changed to ON. This makes encoder's dpms callback call be ignored so display power couldn't become on again. This patch removes exynos_encoder->dpms changing and adds 'updated' variable to exynos_drm_encoder structure to avoid duplicated overlay updating. Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_connector.c | 1 + drivers/gpu/drm/exynos/exynos_drm_encoder.c | 33 ++++++++++++++------------- 2 files changed, 18 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index 18c271862ca8..0f68a2872673 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c @@ -374,6 +374,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev, exynos_connector->encoder_id = encoder->base.id; exynos_connector->manager = manager; exynos_connector->dpms = DRM_MODE_DPMS_OFF; + connector->dpms = DRM_MODE_DPMS_OFF; connector->encoder = encoder; err = drm_mode_connector_attach_encoder(connector, encoder); diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index e51503fbaf2b..241ad1eeec64 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -43,12 +43,14 @@ * @manager: specific encoder has its own manager to control a hardware * appropriately and we can access a hardware drawing on this manager. * @dpms: store the encoder dpms value. + * @updated: indicate whether overlay data updating is needed or not. */ struct exynos_drm_encoder { struct drm_crtc *old_crtc; struct drm_encoder drm_encoder; struct exynos_drm_manager *manager; - int dpms; + int dpms; + bool updated; }; static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode) @@ -85,7 +87,9 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) switch (mode) { case DRM_MODE_DPMS_ON: if (manager_ops && manager_ops->apply) - manager_ops->apply(manager->dev); + if (!exynos_encoder->updated) + manager_ops->apply(manager->dev); + exynos_drm_connector_power(encoder, mode); exynos_encoder->dpms = mode; break; @@ -94,6 +98,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) case DRM_MODE_DPMS_OFF: exynos_drm_connector_power(encoder, mode); exynos_encoder->dpms = mode; + exynos_encoder->updated = false; break; default: DRM_ERROR("unspecified mode %d\n", mode); @@ -205,13 +210,22 @@ static void exynos_drm_encoder_prepare(struct drm_encoder *encoder) static void exynos_drm_encoder_commit(struct drm_encoder *encoder) { - struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); + struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); + struct exynos_drm_manager *manager = exynos_encoder->manager; struct exynos_drm_manager_ops *manager_ops = manager->ops; DRM_DEBUG_KMS("%s\n", __FILE__); if (manager_ops && manager_ops->commit) manager_ops->commit(manager->dev); + + /* + * this will avoid one issue that overlay data is updated to + * real hardware two times. + * And this variable will be used to check if the data was + * already updated or not by exynos_drm_encoder_dpms function. + */ + exynos_encoder->updated = true; } static void exynos_drm_encoder_disable(struct drm_encoder *encoder) @@ -400,19 +414,6 @@ void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data) if (manager_ops && manager_ops->dpms) manager_ops->dpms(manager->dev, mode); - /* - * set current mode to new one so that data aren't updated into - * registers by drm_helper_connector_dpms two times. - * - * in case that drm_crtc_helper_set_mode() is called, - * overlay_ops->commit() and manager_ops->commit() callbacks - * can be called two times, first at drm_crtc_helper_set_mode() - * and second at drm_helper_connector_dpms(). - * so with this setting, when drm_helper_connector_dpms() is called - * encoder->funcs->dpms() will be ignored. - */ - exynos_encoder->dpms = mode; - /* * if this condition is ok then it means that the crtc is already * detached from encoder and last function for detaching is properly -- cgit v1.2.3-55-g7522 From 9eb3e9e6f3cface0d2ffa8d889f44af27dcbce7b Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 29 Oct 2012 09:31:13 +0100 Subject: drm/exynos: add support for ARCH_MULTIPLATFORM Exynos does not seem to have any dependency on anything from platform headers so just needs Kconfig updated to build in ARCH_MULTIPLATFORM builds. Signed-off-by: Rob Clark Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 59a26e577b57..fc345d4ebb03 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -1,6 +1,6 @@ config DRM_EXYNOS tristate "DRM Support for Samsung SoC EXYNOS Series" - depends on DRM && PLAT_SAMSUNG + depends on DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM) select DRM_KMS_HELPER select FB_CFB_FILLRECT select FB_CFB_COPYAREA -- cgit v1.2.3-55-g7522 From 2cdc53b355873ab54b6a348ee5bf022967fb4159 Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Wed, 31 Oct 2012 09:36:26 +0530 Subject: drm: exynos: removed warning due to missing typecast for mixer driver data Removing the warning by adding proper type casting where local pointer variable of type mixer driver data is assigned with void pointer. Signed-off-by: Rahul Sharma Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_mixer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 614b2e9ac462..e7fbb823fd8e 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -1142,7 +1142,7 @@ static int __devinit mixer_probe(struct platform_device *pdev) const struct of_device_id *match; match = of_match_node(of_match_ptr(mixer_match_types), pdev->dev.of_node); - drv = match->data; + drv = (struct mixer_drv_data *)match->data; } else { drv = (struct mixer_drv_data *) platform_get_device_id(pdev)->driver_data; -- cgit v1.2.3-55-g7522 From 3c172868cbbe3eb138fd57bb346c77dffb22b182 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Fri, 26 Oct 2012 06:24:34 +0000 Subject: vxlan: don't expire permanent entries VXLAN confused flag versus bitmap on state. Based on part of a earlier patch by David Stevens. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 607976c00162..7b4adde93c01 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -816,7 +816,7 @@ static void vxlan_cleanup(unsigned long arg) = container_of(p, struct vxlan_fdb, hlist); unsigned long timeout; - if (f->state == NUD_PERMANENT) + if (f->state & NUD_PERMANENT) continue; timeout = f->used + vxlan->age_interval * HZ; -- cgit v1.2.3-55-g7522 From 29c4bcddaa62e2b9fd2ba85668f6718b0b43f0e3 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Wed, 31 Oct 2012 00:30:38 +0100 Subject: cpufreq / powernow-k8: Change maintainer's email address Change the Andreas' email address in drivers/cpufreq/powernow-k8.c. Signed-off-by: Andreas Herrmann Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/powernow-k8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index c16a3a593ba4..e3ebb4fa2c3e 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -5,7 +5,7 @@ * http://www.gnu.org/licenses/gpl.html * * Maintainer: - * Andreas Herrmann + * Andreas Herrmann * * Based on the powernow-k7.c module written by Dave Jones. * (C) 2003 Dave Jones on behalf of SuSE Labs -- cgit v1.2.3-55-g7522 From dea5f0998aa82bdeca260b87c653db11e91329b2 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 31 Oct 2012 22:04:26 -0700 Subject: target: Re-add explict zeroing of INQUIRY bounce buffer memory This patch fixes a regression in spc_emulate_inquiry() code where the local scope bounce buffer was no longer getting it's memory zeroed, causing various problems with SCSI initiators that depend upon areas of INQUIRY EVPD=0x83 payload having been zeroed. This bug was introduced with the following v3.7-rc1 patch + CC'ed stable commit: commit ffe7b0e9326d9c68f5688bef691dd49f1e0d3651 Author: Paolo Bonzini Date: Fri Sep 7 17:30:38 2012 +0200 target: support zero allocation length in INQUIRY Go ahead and re-add the missing memset of bounce buffer memory to be copied into the outgoing se_cmd descriptor kmapped SGL payload. Reported-by: Kelsey Prantis Cc: Kelsey Prantis Cc: Paolo Bonzini Cc: Andy Grover Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_spc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 9229bd9ad61b..6fd434d3d7e4 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -605,6 +605,8 @@ static int spc_emulate_inquiry(struct se_cmd *cmd) unsigned char buf[SE_INQUIRY_BUF]; int p, ret; + memset(buf, 0, SE_INQUIRY_BUF); + if (dev == tpg->tpg_virt_lun0.lun_se_dev) buf[0] = 0x3f; /* Not connected */ else -- cgit v1.2.3-55-g7522 From 0d0f9dfb31e0a6c92063e235417b42df185b3275 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 31 Oct 2012 09:16:44 -0700 Subject: target: Don't return success from module_init() if setup fails If the call to core_dev_release_virtual_lun0() fails, then nothing sets ret to anything other than 0, so even though everything is torn down and freed, target_core_init_configfs() will seem to succeed and the module will be loaded. Fix this by passing the return value on up the chain. Signed-off-by: Roland Dreier Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_configfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 015f5be27bf6..c123327499a3 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -3206,7 +3206,8 @@ static int __init target_core_init_configfs(void) if (ret < 0) goto out; - if (core_dev_setup_virtual_lun0() < 0) + ret = core_dev_setup_virtual_lun0(); + if (ret < 0) goto out; return 0; -- cgit v1.2.3-55-g7522 From 3e03989b5868acf69a391a424dc71fcd6cc48167 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 31 Oct 2012 09:16:45 -0700 Subject: target: Avoid integer overflow in se_dev_align_max_sectors() The expression (max_sectors * block_size) might overflow a u32 (indeed, since iblock sets max_hw_sectors to UINT_MAX, it is guaranteed to overflow and end up with a much-too-small result in many common cases). Fix this by doing an equivalent calculation that doesn't require multiplication. While we're touching this code, avoid splitting a printk format across two lines and use pr_info(...) instead of printk(KERN_INFO ...). Signed-off-by: Roland Dreier Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 8d774da16320..9abef9f8eb76 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -850,20 +850,20 @@ int se_dev_check_shutdown(struct se_device *dev) static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size) { - u32 tmp, aligned_max_sectors; + u32 aligned_max_sectors; + u32 alignment; /* * Limit max_sectors to a PAGE_SIZE aligned value for modern * transport_allocate_data_tasks() operation. */ - tmp = rounddown((max_sectors * block_size), PAGE_SIZE); - aligned_max_sectors = (tmp / block_size); - if (max_sectors != aligned_max_sectors) { - printk(KERN_INFO "Rounding down aligned max_sectors from %u" - " to %u\n", max_sectors, aligned_max_sectors); - return aligned_max_sectors; - } + alignment = max(1ul, PAGE_SIZE / block_size); + aligned_max_sectors = rounddown(max_sectors, alignment); + + if (max_sectors != aligned_max_sectors) + pr_info("Rounding down aligned max_sectors from %u to %u\n", + max_sectors, aligned_max_sectors); - return max_sectors; + return aligned_max_sectors; } void se_dev_set_default_attribs( -- cgit v1.2.3-55-g7522 From d5627acba9ae584cf4928af19f7ddf5f6837de32 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 31 Oct 2012 09:16:46 -0700 Subject: iscsi-target: Fix missed wakeup race in TX thread The sleeping code in iscsi_target_tx_thread() is susceptible to the classic missed wakeup race: - TX thread finishes handle_immediate_queue() and handle_response_queue(), thinks both queues are empty. - Another thread adds a queue entry and does wake_up_process(), which does nothing because the TX thread is still awake. - TX thread does schedule_timeout() and sleeps forever. In practice this can kill an iSCSI connection if for example an initiator does single-threaded writes and the target misses the wakeup window when queueing an R2T; in this case the connection will be stuck until the initiator loses patience and does some task management operation (or kills the connection entirely). Fix this by converting to wait_event_interruptible(), which does not suffer from this sort of race. Signed-off-by: Roland Dreier Cc: Andy Grover Cc: Hannes Reinecke Cc: Christoph Hellwig Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 4 +++- drivers/target/iscsi/iscsi_target_core.h | 1 + drivers/target/iscsi/iscsi_target_login.c | 1 + drivers/target/iscsi/iscsi_target_util.c | 22 ++++++++++++++++++++-- drivers/target/iscsi/iscsi_target_util.h | 1 + 5 files changed, 26 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index d6ce2182e672..035c2c762537 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3719,7 +3719,9 @@ restart: */ iscsit_thread_check_cpumask(conn, current, 1); - schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT); + wait_event_interruptible(conn->queues_wq, + !iscsit_conn_all_queues_empty(conn) || + ts->status == ISCSI_THREAD_SET_RESET); if ((ts->status == ISCSI_THREAD_SET_RESET) || signal_pending(current)) diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 2ba9f9b9435c..21048dbf7d13 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -486,6 +486,7 @@ struct iscsi_tmr_req { }; struct iscsi_conn { + wait_queue_head_t queues_wq; /* Authentication Successful for this connection */ u8 auth_complete; /* State connection is currently in */ diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index cdc8a10939c3..f8dbec05d5e5 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -41,6 +41,7 @@ static int iscsi_login_init_conn(struct iscsi_conn *conn) { + init_waitqueue_head(&conn->queues_wq); INIT_LIST_HEAD(&conn->conn_list); INIT_LIST_HEAD(&conn->conn_cmd_list); INIT_LIST_HEAD(&conn->immed_queue_list); diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index afd98ccd40ae..1a91195ab619 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -488,7 +488,7 @@ void iscsit_add_cmd_to_immediate_queue( atomic_set(&conn->check_immediate_queue, 1); spin_unlock_bh(&conn->immed_queue_lock); - wake_up_process(conn->thread_set->tx_thread); + wake_up(&conn->queues_wq); } struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *conn) @@ -562,7 +562,7 @@ void iscsit_add_cmd_to_response_queue( atomic_inc(&cmd->response_queue_count); spin_unlock_bh(&conn->response_queue_lock); - wake_up_process(conn->thread_set->tx_thread); + wake_up(&conn->queues_wq); } struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *conn) @@ -616,6 +616,24 @@ static void iscsit_remove_cmd_from_response_queue( } } +bool iscsit_conn_all_queues_empty(struct iscsi_conn *conn) +{ + bool empty; + + spin_lock_bh(&conn->immed_queue_lock); + empty = list_empty(&conn->immed_queue_list); + spin_unlock_bh(&conn->immed_queue_lock); + + if (!empty) + return empty; + + spin_lock_bh(&conn->response_queue_lock); + empty = list_empty(&conn->response_queue_list); + spin_unlock_bh(&conn->response_queue_lock); + + return empty; +} + void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn) { struct iscsi_queue_req *qr, *qr_tmp; diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h index 44054bd35437..894d0f837924 100644 --- a/drivers/target/iscsi/iscsi_target_util.h +++ b/drivers/target/iscsi/iscsi_target_util.h @@ -25,6 +25,7 @@ extern struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_ extern void iscsit_add_cmd_to_response_queue(struct iscsi_cmd *, struct iscsi_conn *, u8); extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *); extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_conn *); +extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *); extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *); extern void iscsit_release_cmd(struct iscsi_cmd *); extern void iscsit_free_cmd(struct iscsi_cmd *); -- cgit v1.2.3-55-g7522 From ab74b3d62f05192bf8fb8f169e7999d1183b2e08 Mon Sep 17 00:00:00 2001 From: Steve Hodgson Date: Wed, 31 Oct 2012 10:24:02 -0700 Subject: target: Fix incorrect usage of nested IRQ spinlocks in ABORT_TASK path This patch changes core_tmr_abort_task() to use spin_lock -> spin_unlock around se_cmd->t_state_lock while spin_lock_irqsave is held via se_sess->sess_cmd_lock. Signed-off-by: Steve Hodgson Signed-off-by: Roland Dreier Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_tmr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 1c59a3c23b2c..be75c4331a92 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -140,15 +140,15 @@ void core_tmr_abort_task( printk("ABORT_TASK: Found referenced %s task_tag: %u\n", se_cmd->se_tfo->get_fabric_name(), ref_tag); - spin_lock_irq(&se_cmd->t_state_lock); + spin_lock(&se_cmd->t_state_lock); if (se_cmd->transport_state & CMD_T_COMPLETE) { printk("ABORT_TASK: ref_tag: %u already complete, skipping\n", ref_tag); - spin_unlock_irq(&se_cmd->t_state_lock); + spin_unlock(&se_cmd->t_state_lock); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); goto out; } se_cmd->transport_state |= CMD_T_ABORTED; - spin_unlock_irq(&se_cmd->t_state_lock); + spin_unlock(&se_cmd->t_state_lock); list_del_init(&se_cmd->se_cmd_list); kref_get(&se_cmd->cmd_kref); -- cgit v1.2.3-55-g7522 From 83325d072185899b706de2956170b246585aaec9 Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Wed, 24 Oct 2012 18:29:49 +0200 Subject: DRM/Radeon: Fix Load Detection on legacy primary DAC. An uninitialized variable led to broken load detection. Signed-off-by: Egbert Eich Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 0063df9d166d..f278f20ea12a 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -671,6 +671,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN; WREG32(RADEON_DAC_CNTL, tmp); + tmp = dac_macro_cntl; tmp &= ~(RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | RADEON_DAC_PDWN_B); -- cgit v1.2.3-55-g7522 From 9c50b1d937cc9656100ba10d9f57484c6d173936 Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Wed, 24 Oct 2012 18:31:19 +0200 Subject: DRM/Radeon: Fix primary DAC Load Detection for RV100 chips. For Radeon 7500 ATI recommends a DAC_FORCE value of 0x1ac. This value works better on ES1000 (RV100) chips, too, as it doesn't produce any false positives on any cards I have tested. Therefore let's assume that this value is good for all RV100 and RV200 chipset generations. Signed-off-by: Egbert Eich Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index f278f20ea12a..5fdc67bd25d9 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -662,6 +662,8 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc if (ASIC_IS_R300(rdev)) tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); + else if (ASIC_IS_RV100(rdev)) + tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT); else tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); -- cgit v1.2.3-55-g7522 From fc87f13b8dc73706ae06caf229a336965e9b44a6 Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Wed, 24 Oct 2012 18:32:52 +0200 Subject: DRM/Radeon: On DVI-I use Load Detection when EDID is bogus. The Radeon driver uses the analog/digital flag to determine if the DAC or the TMDS encoder should be enabled on a DVI-I connector. If the EDID is bogus this flag is no longer reliable. This fix adds a fallback to DAC load detection to determine if anything is connected to the DAC. If not and a (bogus) EDID is found it assumes a digital display is connected. This works around problems with some crappy IPMI devices using Radeon ES1000. Signed-off-by: Egbert Eich Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_connectors.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 67cfc1795ecd..b884c362a8c2 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -941,7 +941,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) struct drm_mode_object *obj; int i; enum drm_connector_status ret = connector_status_disconnected; - bool dret = false; + bool dret = false, broken_edid = false; if (!force && radeon_check_hpd_status_unchanged(connector)) return connector->status; @@ -965,6 +965,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) ret = connector_status_disconnected; DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector)); radeon_connector->ddc_bus = NULL; + } else { + ret = connector_status_connected; + broken_edid = true; /* defer use_digital to later */ } } else { radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); @@ -1047,13 +1050,24 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) encoder_funcs = encoder->helper_private; if (encoder_funcs->detect) { - if (ret != connector_status_connected) { - ret = encoder_funcs->detect(encoder, connector); - if (ret == connector_status_connected) { - radeon_connector->use_digital = false; + if (!broken_edid) { + if (ret != connector_status_connected) { + /* deal with analog monitors without DDC */ + ret = encoder_funcs->detect(encoder, connector); + if (ret == connector_status_connected) { + radeon_connector->use_digital = false; + } + if (ret != connector_status_disconnected) + radeon_connector->detected_by_load = true; } - if (ret != connector_status_disconnected) - radeon_connector->detected_by_load = true; + } else { + enum drm_connector_status lret; + /* assume digital unless load detected otherwise */ + radeon_connector->use_digital = true; + lret = encoder_funcs->detect(encoder, connector); + DRM_DEBUG_KMS("load_detect %x returned: %x\n",encoder->encoder_type,lret); + if (lret == connector_status_connected) + radeon_connector->use_digital = false; } break; } -- cgit v1.2.3-55-g7522 From 74e4ca32a406a15efb24a6a6ecf84b4cdabfd4e7 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Wed, 24 Oct 2012 16:42:26 +0200 Subject: drivers/gpu/drm/radeon/evergreen_cs.c: Remove unnecessary semicolon A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r1@ statement S; position p,p1; @@ S@p1;@p @script:python r2@ p << r1.p; p1 << r1.p1; @@ if p[0].line != p1[0].line_end: cocci.include_match(False) @@ position r1.p; @@ -;@p // Signed-off-by: Peter Senna Tschudin Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/evergreen_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 30271b641913..95e6318b6268 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -264,7 +264,7 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p, /* macro tile width & height */ palign = (8 * surf->bankw * track->npipes) * surf->mtilea; halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea; - mtileb = (palign / 8) * (halign / 8) * tileb;; + mtileb = (palign / 8) * (halign / 8) * tileb; mtile_pr = surf->nbx / palign; mtile_ps = (mtile_pr * surf->nby) / halign; surf->layer_size = mtile_ps * mtileb * slice_pt; -- cgit v1.2.3-55-g7522 From dfdcbebc548ff14fd1a7029c95d060e0dd466469 Mon Sep 17 00:00:00 2001 From: Igor Murzov Date: Thu, 25 Oct 2012 17:09:00 +0400 Subject: drm/radeon: fix ATPX function documentation Fix a copy&pasted documentation. Signed-off-by: Igor Murzov Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_atpx_handler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 37f6a907aea4..15f5ded65e0c 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -352,9 +352,9 @@ static int radeon_atpx_switchto(enum vga_switcheroo_client_id id) } /** - * radeon_atpx_switchto - switch to the requested GPU + * radeon_atpx_power_state - power down/up the requested GPU * - * @id: GPU to switch to + * @id: GPU to power down/up * @state: requested power state (0 = off, 1 = on) * * Execute the necessary ATPX function to power down/up the discrete GPU -- cgit v1.2.3-55-g7522 From d038db86984977646815fff54c1be11bff6b9f5b Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Tue, 30 Oct 2012 17:42:26 +0100 Subject: DRM/Radeon: Clean up code in TV DAC load detection. Signed-off-by: Egbert Eich Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 5fdc67bd25d9..85a7307e05f8 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -1425,7 +1425,8 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl; - uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp; + uint32_t gpiopad_a = 0, pixclks_cntl, tmp; + uint32_t disp_output_cntl = 0, disp_hw_debug = 0; enum drm_connector_status found = connector_status_disconnected; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; @@ -1464,9 +1465,12 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder /* save the regs we need */ pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); - gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0; - disp_output_cntl = ASIC_IS_R300(rdev) ? RREG32(RADEON_DISP_OUTPUT_CNTL) : 0; - disp_hw_debug = ASIC_IS_R300(rdev) ? 0 : RREG32(RADEON_DISP_HW_DEBUG); + if (ASIC_IS_R300(rdev)) { + gpiopad_a = RREG32(RADEON_GPIOPAD_A); + disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); + } else { + disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); + } crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL); @@ -1476,16 +1480,13 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder | RADEON_PIX2CLK_DAC_ALWAYS_ONb); WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); - if (ASIC_IS_R300(rdev)) - WREG32_P(RADEON_GPIOPAD_A, 1, ~1); - tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; tmp |= RADEON_CRTC2_CRT2_ON | (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); - WREG32(RADEON_CRTC2_GEN_CNTL, tmp); if (ASIC_IS_R300(rdev)) { + WREG32_P(RADEON_GPIOPAD_A, 1, ~1); tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); @@ -1541,6 +1542,7 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder } else { WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); } + WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); return found; -- cgit v1.2.3-55-g7522 From 701337dc2711096e5288430599dcf07aac5876ab Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Tue, 30 Oct 2012 17:42:27 +0100 Subject: DRM/Radeon: Fix TV DAC Load Detection for single CRTC chips. The RN50 has a TV DAC but only a single CRTC. For load detection this DAC is controlled by the primary CRTC. Signed-off-by: Egbert Eich Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 62 +++++++++++++++---------- 1 file changed, 38 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 85a7307e05f8..3afed70306df 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -1424,9 +1424,9 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; - uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl; + uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl; uint32_t gpiopad_a = 0, pixclks_cntl, tmp; - uint32_t disp_output_cntl = 0, disp_hw_debug = 0; + uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0; enum drm_connector_status found = connector_status_disconnected; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; @@ -1465,13 +1465,18 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder /* save the regs we need */ pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); - if (ASIC_IS_R300(rdev)) { - gpiopad_a = RREG32(RADEON_GPIOPAD_A); - disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); + + if (rdev->flags & RADEON_SINGLE_CRTC) { + crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); } else { - disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); + if (ASIC_IS_R300(rdev)) { + gpiopad_a = RREG32(RADEON_GPIOPAD_A); + disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); + } else { + disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); + } + crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); } - crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL); dac_cntl2 = RREG32(RADEON_DAC_CNTL2); @@ -1480,19 +1485,24 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder | RADEON_PIX2CLK_DAC_ALWAYS_ONb); WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); - tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; - tmp |= RADEON_CRTC2_CRT2_ON | - (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); - WREG32(RADEON_CRTC2_GEN_CNTL, tmp); - - if (ASIC_IS_R300(rdev)) { - WREG32_P(RADEON_GPIOPAD_A, 1, ~1); - tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; - tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; - WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); + if (rdev->flags & RADEON_SINGLE_CRTC) { + tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON; + WREG32(RADEON_CRTC_EXT_CNTL, tmp); } else { - tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; - WREG32(RADEON_DISP_HW_DEBUG, tmp); + tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; + tmp |= RADEON_CRTC2_CRT2_ON | + (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); + WREG32(RADEON_CRTC2_GEN_CNTL, tmp); + + if (ASIC_IS_R300(rdev)) { + WREG32_P(RADEON_GPIOPAD_A, 1, ~1); + tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; + tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; + WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); + } else { + tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; + WREG32(RADEON_DISP_HW_DEBUG, tmp); + } } tmp = RADEON_TV_DAC_NBLANK | @@ -1534,13 +1544,17 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder WREG32(RADEON_DAC_CNTL2, dac_cntl2); WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl); WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); - WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); - if (ASIC_IS_R300(rdev)) { - WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); - WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); + if (rdev->flags & RADEON_SINGLE_CRTC) { + WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); } else { - WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); + WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + if (ASIC_IS_R300(rdev)) { + WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); + } else { + WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); + } } WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); -- cgit v1.2.3-55-g7522 From f8c4d701ae3477f41fdc95592caa476617988a53 Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Mon, 29 Oct 2012 13:46:48 +0100 Subject: DRM/radeon: For single CRTC GPUs move handling of CRTC_CRT_ON to crtc_dpms(). On all dual CRTC GPUs the CRTC_CRT_ON in the RADEON_CRTC_EXT_CNTL register controls the CRTC of the primary DAC. Therefore it is set in the DAC DMPS function. This is different for GPU's with a single CRTC but a primary and a TV DAC: here it controls the single CRTC no matter where it is routed. Therefore we set it here. This avoids an elaborate on/off state tracking since both primary_dac_dpms() and tv_dac_dpms() functions would have to touch this bit. On single CRTC GPUs with just one DAC it's irrelevant where this bit is handled. agd5f: fix warning Signed-off-by: Egbert Eich Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 15 +++++++++++++-- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 7 +++++-- 2 files changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 5677a424b585..6857cb4efb76 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -295,6 +295,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; + uint32_t crtc_ext_cntl = 0; uint32_t mask; if (radeon_crtc->crtc_id) @@ -307,6 +308,16 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) RADEON_CRTC_VSYNC_DIS | RADEON_CRTC_HSYNC_DIS); + /* + * On all dual CRTC GPUs this bit controls the CRTC of the primary DAC. + * Therefore it is set in the DAC DMPS function. + * This is different for GPU's with a single CRTC but a primary and a + * TV DAC: here it controls the single CRTC no matter where it is + * routed. Therefore we set it here. + */ + if (rdev->flags & RADEON_SINGLE_CRTC) + crtc_ext_cntl = RADEON_CRTC_CRT_ON; + switch (mode) { case DRM_MODE_DPMS_ON: radeon_crtc->enabled = true; @@ -317,7 +328,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) else { WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN | RADEON_CRTC_DISP_REQ_EN_B)); - WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask); + WREG32_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, ~(mask | crtc_ext_cntl)); } drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); radeon_crtc_load_lut(crtc); @@ -331,7 +342,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) else { WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN | RADEON_CRTC_DISP_REQ_EN_B)); - WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask); + WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~(mask | crtc_ext_cntl)); } radeon_crtc->enabled = false; /* adjust pm to dpms changes AFTER disabling crtcs */ diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 3afed70306df..817392fc2d04 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -537,7 +537,9 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode break; } - WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); + /* handled in radeon_crtc_dpms() */ + if (!(rdev->flags & RADEON_SINGLE_CRTC)) + WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); WREG32(RADEON_DAC_CNTL, dac_cntl); WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); @@ -1095,7 +1097,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode) } else { if (is_tv) WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); - else + /* handled in radeon_crtc_dpms() */ + else if (!(rdev->flags & RADEON_SINGLE_CRTC)) WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); } -- cgit v1.2.3-55-g7522 From 6d9cdfc27115b5d4a32906b25a6b2f89920b0366 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 31 Oct 2012 11:51:03 -0400 Subject: drm/radeon: add load detection support for ext DAC on R200 (v2) The R200 asics use an external DAC for the secondary DAC. The current KMS code tries to use code for the integrated TV DAC for R200 which leads to unpredictable results since R200 does not have an integrated TV DAC. This patch ports the external DAC load detection support from the UMS driver to KMS. v2: fix typo in loop break logic Signed-off-by: Alex Deucher Reviewed-by: Egbert Eich --- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 97 +++++++++++++++++++++++++ 1 file changed, 97 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 817392fc2d04..f5ba2241dacc 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -1422,6 +1422,96 @@ static bool radeon_legacy_tv_detect(struct drm_encoder *encoder, return found; } +static bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl; + uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c; + uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f; + uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp; + uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid; + bool found = false; + int i; + + /* save the regs we need */ + gpio_monid = RREG32(RADEON_GPIO_MONID); + fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); + disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); + crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); + disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A); + disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B); + disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C); + disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D); + disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E); + disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F); + crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP); + crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP); + crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID); + crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID); + + tmp = RREG32(RADEON_GPIO_MONID); + tmp &= ~RADEON_GPIO_A_0; + WREG32(RADEON_GPIO_MONID, tmp); + + WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON | + RADEON_FP2_PANEL_FORMAT | + R200_FP2_SOURCE_SEL_TRANS_UNIT | + RADEON_FP2_DVO_EN | + R200_FP2_DVO_RATE_SEL_SDR)); + + WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX | + RADEON_DISP_TRANS_MATRIX_GRAPHICS)); + + WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN | + RADEON_CRTC2_DISP_REQ_EN_B)); + + WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); + + WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); + WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); + WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); + WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); + + for (i = 0; i < 200; i++) { + tmp = RREG32(RADEON_GPIO_MONID); + if (tmp & RADEON_GPIO_Y_0) + found = true; + + if (found) + break; + + if (!drm_can_sleep()) + mdelay(1); + else + msleep(1); + } + + /* restore the regs we used */ + WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f); + WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp); + WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp); + WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid); + WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid); + WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + WREG32(RADEON_GPIO_MONID, gpio_monid); + + return found; +} + static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) { @@ -1466,6 +1556,13 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder return connector_status_disconnected; } + /* R200 uses an external DAC for secondary DAC */ + if (rdev->family == CHIP_R200) { + if (radeon_legacy_ext_dac_detect(encoder, connector)) + found = connector_status_connected; + return found; + } + /* save the regs we need */ pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); -- cgit v1.2.3-55-g7522 From 50f8d35de8ba4af311ea1176c534e8b73bb198e5 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 31 Oct 2012 22:30:54 +0000 Subject: ixgbe: PTP get_ts_info missing software support This patch corrects the ethtool get_ts_info functon which did not state that software timestamping was supported, even though it is. Signed-off-by: Jacob Keller CC: Stable [3.5] Tested-by: Stephen Ko Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index 56b20d17d0e4..116f0e901bee 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -2673,6 +2673,9 @@ static int ixgbe_get_ts_info(struct net_device *dev, case ixgbe_mac_X540: case ixgbe_mac_82599EB: info->so_timestamping = + SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; -- cgit v1.2.3-55-g7522 From b457bcb97212c38154d941d88c13f5f63f3620d0 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 31 Oct 2012 05:46:52 +0000 Subject: bnx2x: Fix 57810 1G-KR link against certain switches. Fix 1G KR link by restoring CL72 misc control register to default value rather than 0. Signed-off-by: Yaniv Rosner Signed-off-by: Barak Witkowski Signed-off-by: Dmitry Kravkov Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index e2e45ee5df33..290e12a8d024 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -3545,12 +3545,11 @@ static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy, static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, struct link_params *params, struct link_vars *vars) { - u16 val16 = 0, lane, i; + u16 val16 = 0, lane, i, cl72_ctrl; struct bnx2x *bp = params->bp; static struct bnx2x_reg_set reg_set[] = { {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7}, {MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0}, - {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0}, {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0xff}, {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0x5555}, {MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0x0}, @@ -3565,6 +3564,13 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg, reg_set[i].val); + bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl); + cl72_ctrl &= 0xf8ff; + cl72_ctrl |= 0x3800; + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl); + /* Check adding advertisement for 1G KX */ if (((vars->line_speed == SPEED_AUTO_NEG) && (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) || -- cgit v1.2.3-55-g7522 From a75bb0010026f39910cd01d33a5baa47191539a0 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 31 Oct 2012 05:46:53 +0000 Subject: bnx2x: Fix link down in 57712 following LFA In case of link flap avoidance between PXE boot and bnx2x, set the appropriate PHY DEVAD even if LFA kicks in. Signed-off-by: Yaniv Rosner Signed-off-by: Barak Witkowski Signed-off-by: Dmitry Kravkov Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 290e12a8d024..f2436ea641a6 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -3295,6 +3295,21 @@ static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port) DEFAULT_PHY_DEV_ADDR); } +static void bnx2x_xgxs_specific_func(struct bnx2x_phy *phy, + struct link_params *params, + u32 action) +{ + struct bnx2x *bp = params->bp; + switch (action) { + case PHY_INIT: + /* Set correct devad */ + REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + params->port*0x18, 0); + REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18, + phy->def_md_devad); + break; + } +} + static void bnx2x_xgxs_deassert(struct link_params *params) { struct bnx2x *bp = params->bp; @@ -3309,10 +3324,8 @@ static void bnx2x_xgxs_deassert(struct link_params *params) REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val); udelay(500); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val); - - REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 0); - REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, - params->phy[INT_PHY].def_md_devad); + bnx2x_xgxs_specific_func(¶ms->phy[INT_PHY], params, + PHY_INIT); } static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy, @@ -10999,7 +11012,7 @@ static struct bnx2x_phy phy_xgxs = { .format_fw_ver = (format_fw_ver_t)NULL, .hw_reset = (hw_reset_t)NULL, .set_link_led = (set_link_led_t)NULL, - .phy_specific_func = (phy_specific_func_t)NULL + .phy_specific_func = (phy_specific_func_t)bnx2x_xgxs_specific_func }; static struct bnx2x_phy phy_warpcore = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT, -- cgit v1.2.3-55-g7522 From cd1a26a3bbc797100c55594bac0546204ccb1107 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 31 Oct 2012 05:46:54 +0000 Subject: bnx2x: Restore global registers back to default. Several KR registers were not set correctly back to default after loopback test, so set those global registers over the global WC lane (zero) rather than the current lane. Signed-off-by: Yaniv Rosner Signed-off-by: Barak Witkowski Signed-off-by: Dmitry Kravkov Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 78 +++++++++++++++++------- 1 file changed, 56 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index f2436ea641a6..5e8f7b7a8f65 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -3558,13 +3558,11 @@ static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy, static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, struct link_params *params, struct link_vars *vars) { - u16 val16 = 0, lane, i, cl72_ctrl; + u16 lane, i, cl72_ctrl, an_adv = 0; + u16 ucode_ver; struct bnx2x *bp = params->bp; static struct bnx2x_reg_set reg_set[] = { {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7}, - {MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0}, - {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0xff}, - {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0x5555}, {MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0x0}, {MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415}, {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190}, @@ -3589,7 +3587,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) || (vars->line_speed == SPEED_1000)) { u32 addr = MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2; - val16 |= (1<<5); + an_adv |= (1<<5); /* Enable CL37 1G Parallel Detect */ bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, addr, 0x1); @@ -3599,11 +3597,14 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) || (vars->line_speed == SPEED_10000)) { /* Check adding advertisement for 10G KR */ - val16 |= (1<<7); + an_adv |= (1<<7); /* Enable 10G Parallel Detect */ + CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, + MDIO_AER_BLOCK_AER_REG, 0); + bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 1); - + bnx2x_set_aer_mmd(params, phy); DP(NETIF_MSG_LINK, "Advertize 10G\n"); } @@ -3623,7 +3624,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, /* Advertised speeds */ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, - MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16); + MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, an_adv); /* Advertised and set FEC (Forward Error Correction) */ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, @@ -3647,9 +3648,10 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, /* Set KR Autoneg Work-Around flag for Warpcore version older than D108 */ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_UC_INFO_B1_VERSION, &val16); - if (val16 < 0xd108) { - DP(NETIF_MSG_LINK, "Enable AN KR work-around\n"); + MDIO_WC_REG_UC_INFO_B1_VERSION, &ucode_ver); + if (ucode_ver < 0xd108) { + DP(NETIF_MSG_LINK, "Enable AN KR work-around. WC ver:0x%x\n", + ucode_ver); vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY; } bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, @@ -3670,21 +3672,16 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy, struct link_vars *vars) { struct bnx2x *bp = params->bp; - u16 i; + u16 val16, i, lane; static struct bnx2x_reg_set reg_set[] = { /* Disable Autoneg */ {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7}, - {MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0x3f00}, {MDIO_AN_DEVAD, MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0}, {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0}, {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1}, {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0xa}, - /* Disable CL36 PCS Tx */ - {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0x0}, - /* Double Wide Single Data Rate @ pll rate */ - {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0xFFFF}, /* Leave cl72 training enable, needed for KR */ {MDIO_PMA_DEVAD, MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150, @@ -3695,11 +3692,24 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy, bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg, reg_set[i].val); - /* Leave CL72 enabled */ - bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, - 0x3800); + lane = bnx2x_get_warpcore_lane(phy, params); + /* Global registers */ + CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, + MDIO_AER_BLOCK_AER_REG, 0); + /* Disable CL36 PCS Tx */ + bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16); + val16 &= ~(0x0011 << lane); + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16); + bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16); + val16 |= (0x0303 << (lane << 1)); + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16); + /* Restore AER */ + bnx2x_set_aer_mmd(params, phy); /* Set speed via PMA/PMD register */ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040); @@ -4322,7 +4332,7 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy, struct link_params *params) { struct bnx2x *bp = params->bp; - u16 val16; + u16 val16, lane; bnx2x_sfp_e3_set_transmitter(params, phy, 0); bnx2x_set_mdio_clk(bp, params->chip_id, params->port); bnx2x_set_aer_mmd(params, phy); @@ -4359,6 +4369,30 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy, MDIO_WC_REG_XGXSBLK1_LANECTRL2, val16 & 0xff00); + lane = bnx2x_get_warpcore_lane(phy, params); + /* Disable CL36 PCS Tx */ + bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16); + val16 |= (0x11 << lane); + if (phy->flags & FLAGS_WC_DUAL_MODE) + val16 |= (0x22 << lane); + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16); + + bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16); + val16 &= ~(0x0303 << (lane << 1)); + val16 |= (0x0101 << (lane << 1)); + if (phy->flags & FLAGS_WC_DUAL_MODE) { + val16 &= ~(0x0c0c << (lane << 1)); + val16 |= (0x0404 << (lane << 1)); + } + + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16); + /* Restore AER */ + bnx2x_set_aer_mmd(params, phy); + } static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy, -- cgit v1.2.3-55-g7522 From 4978140c38958b15b3b95a49bda688723fa014eb Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 31 Oct 2012 05:46:55 +0000 Subject: bnx2x: Fix potential incorrect link speed provision Fix possible incorrect link speed provision following rapid link speed change. Clear link speed mask after each link change, and not only after link down. Signed-off-by: Yaniv Rosner Signed-off-by: Barak Witkowski Signed-off-by: Dmitry Kravkov Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 5e8f7b7a8f65..308ba42dfd56 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -137,7 +137,16 @@ #define LINK_20GTFD LINK_STATUS_SPEED_AND_DUPLEX_20GTFD #define LINK_20GXFD LINK_STATUS_SPEED_AND_DUPLEX_20GXFD - +#define LINK_UPDATE_MASK \ + (LINK_STATUS_SPEED_AND_DUPLEX_MASK | \ + LINK_STATUS_LINK_UP | \ + LINK_STATUS_PHYSICAL_LINK_FLAG | \ + LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | \ + LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | \ + LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | \ + LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK | \ + LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE | \ + LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE) #define SFP_EEPROM_CON_TYPE_ADDR 0x2 #define SFP_EEPROM_CON_TYPE_VAL_LC 0x7 @@ -6349,15 +6358,7 @@ static int bnx2x_update_link_down(struct link_params *params, vars->mac_type = MAC_TYPE_NONE; /* Update shared memory */ - vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK | - LINK_STATUS_LINK_UP | - LINK_STATUS_PHYSICAL_LINK_FLAG | - LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | - LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | - LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | - LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK | - LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE | - LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE); + vars->link_status &= ~LINK_UPDATE_MASK; vars->line_speed = 0; bnx2x_update_mng(params, vars->link_status); @@ -6505,6 +6506,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars) u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed; u8 active_external_phy = INT_PHY; vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG; + vars->link_status &= ~LINK_UPDATE_MASK; for (phy_index = INT_PHY; phy_index < params->num_phys; phy_index++) { phy_vars[phy_index].flow_ctrl = 0; -- cgit v1.2.3-55-g7522 From e82041df5d0a85457880fbbe00da057443b3fcc0 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 31 Oct 2012 05:46:56 +0000 Subject: bnx2x: Fix unrecognized SFP+ module after driver is loaded When SFP+ module is plugged in after driver is already loaded, it may not be recognized, so set SFP module recognition time up to 300ms, without resetting the module power in the middle. Signed-off-by: Yaniv Rosner Signed-off-by: Barak Witkowski Signed-off-by: Dmitry Kravkov Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 308ba42dfd56..679d45e09805 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -7634,7 +7634,7 @@ static void bnx2x_warpcore_power_module(struct link_params *params, static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy, struct link_params *params, u16 addr, u8 byte_cnt, - u8 *o_buf) + u8 *o_buf, u8 is_init) { int rc = 0; u8 i, j = 0, cnt = 0; @@ -7651,10 +7651,10 @@ static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy, /* 4 byte aligned address */ addr32 = addr & (~0x3); do { - if (cnt == I2C_WA_PWR_ITER) { + if ((!is_init) && (cnt == I2C_WA_PWR_ITER)) { bnx2x_warpcore_power_module(params, phy, 0); /* Note that 100us are not enough here */ - usleep_range(1000,1000); + usleep_range(1000, 2000); bnx2x_warpcore_power_module(params, phy, 1); } rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt, @@ -7774,7 +7774,7 @@ int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy, break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr, - byte_cnt, o_buf); + byte_cnt, o_buf, 0); break; } return rc; @@ -7978,6 +7978,7 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy, { u8 val; + int rc; struct bnx2x *bp = params->bp; u16 timeout; /* Initialization time after hot-plug may take up to 300ms for @@ -7985,8 +7986,14 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy, */ for (timeout = 0; timeout < 60; timeout++) { - if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val) - == 0) { + if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) + rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, + params, 1, + 1, &val, 1); + else + rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, + &val); + if (rc == 0) { DP(NETIF_MSG_LINK, "SFP+ module initialization took %d ms\n", timeout * 5); @@ -7994,7 +8001,8 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy, } usleep_range(5000, 10000); } - return -EINVAL; + rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val); + return rc; } static void bnx2x_8727_power_module(struct bnx2x *bp, -- cgit v1.2.3-55-g7522 From 03c31488a084b344cd04bb853db97706143327b9 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 31 Oct 2012 05:46:57 +0000 Subject: bnx2x: Fix no link on 577xx 10G-baseT Since the Warpcore supports various link types, need to set only the correct supported modes for XFI which is the serdes interface for the 10G-baseT PHY. Signed-off-by: Yaniv Rosner Signed-off-by: Barak Witkowski Signed-off-by: Dmitry Kravkov Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 679d45e09805..6dd0dd076cc5 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -11528,6 +11528,11 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port, phy->media_type = ETH_PHY_BASE_T; break; case PORT_HW_CFG_NET_SERDES_IF_XFI: + phy->supported &= (SUPPORTED_1000baseT_Full | + SUPPORTED_10000baseT_Full | + SUPPORTED_FIBRE | + SUPPORTED_Pause | + SUPPORTED_Asym_Pause); phy->media_type = ETH_PHY_XFP_FIBER; break; case PORT_HW_CFG_NET_SERDES_IF_SFI: -- cgit v1.2.3-55-g7522 From 477864ddd36510e9802c2adb6d9445c2d7783fe5 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Wed, 31 Oct 2012 05:46:58 +0000 Subject: bnx2x: Disable FCoE for 57840 since not yet supported by FW Signed-off-by: Dmitry Kravkov Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index d5648fc666bd..f23e8c022954 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -11902,7 +11902,15 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, /* disable FCOE L2 queue for E1x */ if (CHIP_IS_E1x(bp)) bp->flags |= NO_FCOE_FLAG; - + /* disable FCOE for 57840 device, until FW supports it */ + switch (ent->driver_data) { + case BCM57840_O: + case BCM57840_4_10: + case BCM57840_2_20: + case BCM57840_MFO: + case BCM57840_MF: + bp->flags |= NO_FCOE_FLAG; + } #endif -- cgit v1.2.3-55-g7522 From eb6e98a1b25fb0f347fece9814257a9e1cb537c8 Mon Sep 17 00:00:00 2001 From: nikolay@redhat.com Date: Wed, 31 Oct 2012 04:42:51 +0000 Subject: bonding: fix off-by-one error Fix off-by-one error because IFNAMSIZ == 16 and when this code gets executed we stick a NULL byte where we should not. How to reproduce: with CONFIG_CC_STACKPROTECTOR=y (otherwise it may pass by silently) modprobe bonding; echo 1 > /sys/class/net/bond0/bonding/mode; echo "AAAAAAAAAAAAAAAA" > /sys/class/net/bond0/bonding/primary; Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/bonding/bond_sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index dc15d248443f..238d9b3e2252 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -1060,7 +1060,7 @@ static ssize_t bonding_store_primary(struct device *d, goto out; } - sscanf(buf, "%16s", ifname); /* IFNAMSIZ */ + sscanf(buf, "%15s", ifname); /* IFNAMSIZ */ /* check to see if we are clearing primary */ if (!strlen(ifname) || buf[0] == '\n') { -- cgit v1.2.3-55-g7522 From c84e1590d149cfc885062e938944941f33e69f38 Mon Sep 17 00:00:00 2001 From: nikolay@redhat.com Date: Wed, 31 Oct 2012 06:03:52 +0000 Subject: bonding: fix second off-by-one error Fix off-by-one error because IFNAMSIZ == 16 and when this code gets executed we stick a NULL byte where we should not. How to reproduce: with CONFIG_CC_STACKPROTECTOR=y (otherwise it may pass by silently) modprobe bonding; echo 1 > /sys/class/net/bond0/bonding/mode; echo "AAAAAAAAAAAAAAAA" > /sys/class/net/bond0/bonding/active_slave; Signed-off-by: Nikolay Aleksandrov Note: Sorry for the second patch but I missed this one while checking the file. You can squash them into one patch. Signed-off-by: David S. Miller --- drivers/net/bonding/bond_sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 238d9b3e2252..ef8d2a080d17 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -1237,7 +1237,7 @@ static ssize_t bonding_store_active_slave(struct device *d, goto out; } - sscanf(buf, "%16s", ifname); /* IFNAMSIZ */ + sscanf(buf, "%15s", ifname); /* IFNAMSIZ */ /* check to see if we are clearing active */ if (!strlen(ifname) || buf[0] == '\n') { -- cgit v1.2.3-55-g7522 From eaa7cc60f7dff5e74ef387ace8228235fab8241b Mon Sep 17 00:00:00 2001 From: Jamie Lentin Date: Thu, 1 Nov 2012 23:55:43 +0000 Subject: hwmon: Only include of_match_table with CONFIG_OF_GPIO The following fixes build errors on sparc. Without any DT support, of_match_ptr is NULL and the below is a no-op. However, if just CONFIG_OF is defined then so is of_match_ptr. All useful parts of the gpio-fan DT support rely on CONFIG_OF_GPIO anyway, so of_match_table should too. Signed-off-by: Jamie Lentin Signed-off-by: Guenter Roeck --- drivers/hwmon/gpio-fan.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c index 36509ae32083..1381a2e3bbd4 100644 --- a/drivers/hwmon/gpio-fan.c +++ b/drivers/hwmon/gpio-fan.c @@ -630,7 +630,9 @@ static struct platform_driver gpio_fan_driver = { .driver = { .name = "gpio-fan", .pm = GPIO_FAN_PM, +#ifdef CONFIG_OF_GPIO .of_match_table = of_match_ptr(of_gpio_fan_match), +#endif }, }; -- cgit v1.2.3-55-g7522 From 3916e1d71b62b120888aa50bcc8d9a6200fc19a7 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 1 Nov 2012 13:47:09 +1000 Subject: drm/udl: fix stride issues scanning out stride != width*bpp When buffer sharing with the i915 and using a 1680x1050 monitor, the i915 gives is a 6912 buffer for the 6720 width, the code doesn't render this properly as it uses one value to set the base address for reading from the vmap and for where to start on the device. This fixes it by calculating the values correctly for the device and for the pixmap. No idea how I haven't seen this before now. Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/udl/udl_drv.h | 2 +- drivers/gpu/drm/udl/udl_fb.c | 12 +++++++----- drivers/gpu/drm/udl/udl_transfer.c | 5 +++-- 3 files changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index fccd361f7b50..87aa5f5d3c88 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -104,7 +104,7 @@ udl_fb_user_fb_create(struct drm_device *dev, int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, const char *front, char **urb_buf_ptr, - u32 byte_offset, u32 byte_width, + u32 byte_offset, u32 device_byte_offset, u32 byte_width, int *ident_ptr, int *sent_ptr); int udl_dumb_create(struct drm_file *file_priv, diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index 69a2b16f42a6..d4ab3beaada0 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -114,9 +114,10 @@ static void udlfb_dpy_deferred_io(struct fb_info *info, list_for_each_entry(cur, &fbdefio->pagelist, lru) { if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8), - &urb, (char *) info->fix.smem_start, - &cmd, cur->index << PAGE_SHIFT, - PAGE_SIZE, &bytes_identical, &bytes_sent)) + &urb, (char *) info->fix.smem_start, + &cmd, cur->index << PAGE_SHIFT, + cur->index << PAGE_SHIFT, + PAGE_SIZE, &bytes_identical, &bytes_sent)) goto error; bytes_rendered += PAGE_SIZE; } @@ -187,10 +188,11 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, for (i = y; i < y + height ; i++) { const int line_offset = fb->base.pitches[0] * i; const int byte_offset = line_offset + (x * bpp); - + const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp); if (udl_render_hline(dev, bpp, &urb, (char *) fb->obj->vmapping, - &cmd, byte_offset, width * bpp, + &cmd, byte_offset, dev_byte_offset, + width * bpp, &bytes_identical, &bytes_sent)) goto error; } diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c index dc095526ffb7..142fee5f983f 100644 --- a/drivers/gpu/drm/udl/udl_transfer.c +++ b/drivers/gpu/drm/udl/udl_transfer.c @@ -213,11 +213,12 @@ static void udl_compress_hline16( */ int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, const char *front, char **urb_buf_ptr, - u32 byte_offset, u32 byte_width, + u32 byte_offset, u32 device_byte_offset, + u32 byte_width, int *ident_ptr, int *sent_ptr) { const u8 *line_start, *line_end, *next_pixel; - u32 base16 = 0 + (byte_offset / bpp) * 2; + u32 base16 = 0 + (device_byte_offset / bpp) * 2; struct urb *urb = *urb_ptr; u8 *cmd = *urb_buf_ptr; u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; -- cgit v1.2.3-55-g7522 From 82fa63bd6b87969dfde0139dbede243380b087d6 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 12 Oct 2012 11:55:16 +0100 Subject: i2c: mxs: remove broken PIOQUEUE support This I2C master can do DMA and PIOQUEUE (PIO with FIFO). Originally, only PIOQUEUE was supported and it had issues, then DMA support was added this cycle. The original intention was to keep PIOQUEUE since it has less overhead what is nice for small transfers. However, runtime switching between PIOQEUE and DMA depending on the transfer size never worked despite a lot of trying. Since PIOQUEUE mode itself was flaky (polling at places where interrupts failed to work) and the implementation also imposed a size limit for transfers, it is best to remove the support, so users don't fall over its limitations. It also makes the driver a lot cleaner and more robust. If somebody really wants less overhead, plain PIO mode could still be implemented with the addidtional advantage that this mode is also available on MX23, too. Signed-off-by: Wolfram Sang Reviewed-by: Marek Vasut --- drivers/i2c/busses/i2c-mxs.c | 186 ++++--------------------------------------- 1 file changed, 14 insertions(+), 172 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 1f58197062cf..286ca1917820 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -1,7 +1,7 @@ /* * Freescale MXS I2C bus driver * - * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K. + * Copyright (C) 2011-2012 Wolfram Sang, Pengutronix e.K. * * based on a (non-working) driver which was: * @@ -35,10 +35,6 @@ #define DRIVER_NAME "mxs-i2c" -static bool use_pioqueue; -module_param(use_pioqueue, bool, 0); -MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA"); - #define MXS_I2C_CTRL0 (0x00) #define MXS_I2C_CTRL0_SET (0x04) @@ -75,23 +71,6 @@ MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA"); MXS_I2C_CTRL1_SLAVE_STOP_IRQ | \ MXS_I2C_CTRL1_SLAVE_IRQ) -#define MXS_I2C_QUEUECTRL (0x60) -#define MXS_I2C_QUEUECTRL_SET (0x64) -#define MXS_I2C_QUEUECTRL_CLR (0x68) - -#define MXS_I2C_QUEUECTRL_QUEUE_RUN 0x20 -#define MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE 0x04 - -#define MXS_I2C_QUEUESTAT (0x70) -#define MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY 0x00002000 -#define MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK 0x0000001F - -#define MXS_I2C_QUEUECMD (0x80) - -#define MXS_I2C_QUEUEDATA (0x90) - -#define MXS_I2C_DATA (0xa0) - #define MXS_CMD_I2C_SELECT (MXS_I2C_CTRL0_RETAIN_CLOCK | \ MXS_I2C_CTRL0_PRE_SEND_START | \ @@ -153,7 +132,6 @@ struct mxs_i2c_dev { const struct mxs_i2c_speed_config *speed; /* DMA support components */ - bool dma_mode; int dma_channel; struct dma_chan *dmach; struct mxs_dma_data dma_data; @@ -172,99 +150,6 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c) writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2); writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET); - if (i2c->dma_mode) - writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE, - i2c->regs + MXS_I2C_QUEUECTRL_CLR); - else - writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE, - i2c->regs + MXS_I2C_QUEUECTRL_SET); -} - -static void mxs_i2c_pioq_setup_read(struct mxs_i2c_dev *i2c, u8 addr, int len, - int flags) -{ - u32 data; - - writel(MXS_CMD_I2C_SELECT, i2c->regs + MXS_I2C_QUEUECMD); - - data = (addr << 1) | I2C_SMBUS_READ; - writel(data, i2c->regs + MXS_I2C_DATA); - - data = MXS_CMD_I2C_READ | MXS_I2C_CTRL0_XFER_COUNT(len) | flags; - writel(data, i2c->regs + MXS_I2C_QUEUECMD); -} - -static void mxs_i2c_pioq_setup_write(struct mxs_i2c_dev *i2c, - u8 addr, u8 *buf, int len, int flags) -{ - u32 data; - int i, shifts_left; - - data = MXS_CMD_I2C_WRITE | MXS_I2C_CTRL0_XFER_COUNT(len + 1) | flags; - writel(data, i2c->regs + MXS_I2C_QUEUECMD); - - /* - * We have to copy the slave address (u8) and buffer (arbitrary number - * of u8) into the data register (u32). To achieve that, the u8 are put - * into the MSBs of 'data' which is then shifted for the next u8. When - * appropriate, 'data' is written to MXS_I2C_DATA. So, the first u32 - * looks like this: - * - * 3 2 1 0 - * 10987654|32109876|54321098|76543210 - * --------+--------+--------+-------- - * buffer+2|buffer+1|buffer+0|slave_addr - */ - - data = ((addr << 1) | I2C_SMBUS_WRITE) << 24; - - for (i = 0; i < len; i++) { - data >>= 8; - data |= buf[i] << 24; - if ((i & 3) == 2) - writel(data, i2c->regs + MXS_I2C_DATA); - } - - /* Write out the remaining bytes if any */ - shifts_left = 24 - (i & 3) * 8; - if (shifts_left) - writel(data >> shifts_left, i2c->regs + MXS_I2C_DATA); -} - -/* - * TODO: should be replaceable with a waitqueue and RD_QUEUE_IRQ (setting the - * rd_threshold to 1). Couldn't get this to work, though. - */ -static int mxs_i2c_wait_for_data(struct mxs_i2c_dev *i2c) -{ - unsigned long timeout = jiffies + msecs_to_jiffies(1000); - - while (readl(i2c->regs + MXS_I2C_QUEUESTAT) - & MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY) { - if (time_after(jiffies, timeout)) - return -ETIMEDOUT; - cond_resched(); - } - - return 0; -} - -static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len) -{ - u32 uninitialized_var(data); - int i; - - for (i = 0; i < len; i++) { - if ((i & 3) == 0) { - if (mxs_i2c_wait_for_data(i2c)) - return -ETIMEDOUT; - data = readl(i2c->regs + MXS_I2C_QUEUEDATA); - } - buf[i] = data & 0xff; - data >>= 8; - } - - return 0; } static void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c) @@ -432,39 +317,17 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, init_completion(&i2c->cmd_complete); i2c->cmd_err = 0; - if (i2c->dma_mode) { - ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); - if (ret) - return ret; - } else { - if (msg->flags & I2C_M_RD) { - mxs_i2c_pioq_setup_read(i2c, msg->addr, - msg->len, flags); - } else { - mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf, - msg->len, flags); - } - - writel(MXS_I2C_QUEUECTRL_QUEUE_RUN, - i2c->regs + MXS_I2C_QUEUECTRL_SET); - } + ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); + if (ret) + return ret; ret = wait_for_completion_timeout(&i2c->cmd_complete, msecs_to_jiffies(1000)); if (ret == 0) goto timeout; - if (!i2c->dma_mode && !i2c->cmd_err && (msg->flags & I2C_M_RD)) { - ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len); - if (ret) - goto timeout; - } - if (i2c->cmd_err == -ENXIO) mxs_i2c_reset(i2c); - else - writel(MXS_I2C_QUEUECTRL_QUEUE_RUN, - i2c->regs + MXS_I2C_QUEUECTRL_CLR); dev_dbg(i2c->dev, "Done with err=%d\n", i2c->cmd_err); @@ -472,8 +335,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, timeout: dev_dbg(i2c->dev, "Timeout!\n"); - if (i2c->dma_mode) - mxs_i2c_dma_finish(i2c); + mxs_i2c_dma_finish(i2c); mxs_i2c_reset(i2c); return -ETIMEDOUT; } @@ -502,7 +364,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id) { struct mxs_i2c_dev *i2c = dev_id; u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK; - bool is_last_cmd; if (!stat) return IRQ_NONE; @@ -515,14 +376,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id) /* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */ i2c->cmd_err = -EIO; - if (!i2c->dma_mode) { - is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) & - MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0; - - if (is_last_cmd || i2c->cmd_err) - complete(&i2c->cmd_complete); - } - writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR); return IRQ_HANDLED; @@ -555,15 +408,6 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c) struct device_node *node = dev->of_node; int ret; - /* - * The MXS I2C DMA mode is prefered and enabled by default. - * The PIO mode is still supported, but should be used only - * for debuging purposes etc. - */ - i2c->dma_mode = !use_pioqueue; - if (!i2c->dma_mode) - dev_info(dev, "Using PIOQUEUE mode for I2C transfers!\n"); - /* * TODO: This is a temporary solution and should be changed * to use generic DMA binding later when the helpers get in. @@ -571,8 +415,8 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c) ret = of_property_read_u32(node, "fsl,i2c-dma-channel", &i2c->dma_channel); if (ret) { - dev_warn(dev, "Failed to get DMA channel, using PIOQUEUE!\n"); - i2c->dma_mode = 0; + dev_err(dev, "Failed to get DMA channel!\n"); + return -ENODEV; } ret = of_property_read_u32(node, "clock-frequency", &speed); @@ -634,15 +478,13 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev) } /* Setup the DMA */ - if (i2c->dma_mode) { - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - i2c->dma_data.chan_irq = dmairq; - i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c); - if (!i2c->dmach) { - dev_err(dev, "Failed to request dma\n"); - return -ENODEV; - } + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + i2c->dma_data.chan_irq = dmairq; + i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c); + if (!i2c->dmach) { + dev_err(dev, "Failed to request dma\n"); + return -ENODEV; } platform_set_drvdata(pdev, i2c); -- cgit v1.2.3-55-g7522 From 817315f57408b1a9c78cbc7ff2bf186da45ddcc1 Mon Sep 17 00:00:00 2001 From: Philippe Begnic Date: Wed, 10 Oct 2012 13:02:26 +0200 Subject: i2c-nomadik: Fixup clock handling Make sure to clk_prepare as well as clk_enable. Signed-off-by: Philippe Begnic Signed-off-by: Ulf Hansson Signed-off-by: Linus Walleij Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-nomadik.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 698d7acb0f08..02c3115a2dfa 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -644,7 +644,11 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, pm_runtime_get_sync(&dev->adev->dev); - clk_enable(dev->clk); + status = clk_prepare_enable(dev->clk); + if (status) { + dev_err(&dev->adev->dev, "can't prepare_enable clock\n"); + goto out_clk; + } status = init_hw(dev); if (status) @@ -671,7 +675,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, } out: - clk_disable(dev->clk); + clk_disable_unprepare(dev->clk); +out_clk: pm_runtime_put_sync(&dev->adev->dev); dev->busy = false; -- cgit v1.2.3-55-g7522 From 91b370a0dbda5de92c2cf4c3bc0d18d6bf08f05f Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 1 Nov 2012 22:08:14 +0530 Subject: i2c: tegra: set irq name as device name When watching the irqs name of tegra i2c, all instances irq name shows as tegra_i2c. Passing the device name properly to have the irq names with instance like tegra-i2c.0, tegra-i2c.1 etc. Signed-off-by: Laxman Dewangan Acked-by: Jean Delvare Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index f981ac4e6783..dcea77bf6f50 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -742,7 +742,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) } ret = devm_request_irq(&pdev->dev, i2c_dev->irq, - tegra_i2c_isr, 0, pdev->name, i2c_dev); + tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev); if (ret) { dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq); return ret; -- cgit v1.2.3-55-g7522 From 2b674047bef23d49a7ca8ec32f4b9e4e12588621 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Sun, 28 Oct 2012 21:59:04 +0000 Subject: bnx2x: fix HW initialization using fw 7.8.x Since commit 96bed4b9 (use FW 7.8.2) BRB HW block needs to be initialized using fw values for all devices. Otherwise ETS on 57712/578xx will not work. Signed-off-by: Dmitry Kravkov Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index f23e8c022954..bd1fd3d87c24 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -6794,8 +6794,9 @@ static int bnx2x_init_hw_port(struct bnx2x *bp) bnx2x_init_block(bp, BLOCK_DORQ, init_phase); + bnx2x_init_block(bp, BLOCK_BRB1, init_phase); + if (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) { - bnx2x_init_block(bp, BLOCK_BRB1, init_phase); if (IS_MF(bp)) low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246); -- cgit v1.2.3-55-g7522 From 57c10b61c84bfed68b1b317d6f507a392724b9c4 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Sun, 28 Oct 2012 06:12:00 +0000 Subject: drivers/net/ethernet/nxp/lpc_eth.c: Call mdiobus_unregister before mdiobus_free Based on commit b27393aecf66199f5ddad37c302d3e0cfadbe6c0 Calling mdiobus_free without calling mdiobus_unregister causes BUG_ON(). This patch fixes the issue. The semantic patch that found this issue(http://coccinelle.lip6.fr/): // @@ expression E; @@ ... when != mdiobus_unregister(E); + mdiobus_unregister(E); mdiobus_free(E); // Signed-off-by: Peter Senna Tschudin Tested-by: Roland Stigge Tested-by: Alexandre Pereira da Silva Signed-off-by: David S. Miller --- drivers/net/ethernet/nxp/lpc_eth.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 53743f7a2ca9..af8b4142088c 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -1524,6 +1524,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev) pldat->dma_buff_base_p); free_irq(ndev->irq, ndev); iounmap(pldat->net_base); + mdiobus_unregister(pldat->mii_bus); mdiobus_free(pldat->mii_bus); clk_disable(pldat->clk); clk_put(pldat->clk); -- cgit v1.2.3-55-g7522 From aa731872f7d33dcb8b54dad0cfb82d4e4d195d7e Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Sun, 28 Oct 2012 06:12:01 +0000 Subject: drivers/net/phy/mdio-bitbang.c: Call mdiobus_unregister before mdiobus_free Based on commit b27393aecf66199f5ddad37c302d3e0cfadbe6c0 Calling mdiobus_free without calling mdiobus_unregister causes BUG_ON(). This patch fixes the issue. The semantic patch that found this issue(http://coccinelle.lip6.fr/): // @@ expression E; @@ ... when != mdiobus_unregister(E); + mdiobus_unregister(E); mdiobus_free(E); // Signed-off-by: Peter Senna Tschudin Signed-off-by: David S. Miller --- drivers/net/phy/mdio-bitbang.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c index daec9b05d168..6428fcbbdd4b 100644 --- a/drivers/net/phy/mdio-bitbang.c +++ b/drivers/net/phy/mdio-bitbang.c @@ -234,6 +234,7 @@ void free_mdio_bitbang(struct mii_bus *bus) struct mdiobb_ctrl *ctrl = bus->priv; module_put(ctrl->ops->owner); + mdiobus_unregister(bus); mdiobus_free(bus); } EXPORT_SYMBOL(free_mdio_bitbang); -- cgit v1.2.3-55-g7522 From e3c98512780ae2cfb90be2152ab35294439bb7bb Mon Sep 17 00:00:00 2001 From: Vipul Pandya Date: Mon, 29 Oct 2012 02:02:36 +0000 Subject: cxgb4: Fix unable to get UP event from the LLD If T4 configuration file gets loaded from the /lib/firmware/cxgb4/ directory then offload capabilities of the cards were getting disabled during initialization. Hence ULDs do not get an UP event from the LLD. Signed-off-by: Jay Hernandez Signed-off-by: Vipul Pandya Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index c1cde11b0c6d..0df1284df497 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -3415,16 +3415,6 @@ static int adap_init0_config(struct adapter *adapter, int reset) "mismatch: [fini] csum=%#x, computed csum=%#x\n", finicsum, cfcsum); - /* - * If we're a pure NIC driver then disable all offloading facilities. - * This will allow the firmware to optimize aspects of the hardware - * configuration which will result in improved performance. - */ - caps_cmd.ofldcaps = 0; - caps_cmd.iscsicaps = 0; - caps_cmd.rdmacaps = 0; - caps_cmd.fcoecaps = 0; - /* * And now tell the firmware to use the configuration we just loaded. */ -- cgit v1.2.3-55-g7522 From 608f62b996c6e140ff7515abe75305aed4726b33 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Wed, 31 Oct 2012 17:46:10 +0900 Subject: thermal: solve compilation errors in rcar_thermal following were the errors reported drivers/thermal/rcar_thermal.c: In function ‘rcar_thermal_probe’: drivers/thermal/rcar_thermal.c:214:10: warning: passing argument 3 of ‘thermal_zone_device_register’ makes integer from pointer without a cast [enabled by default] include/linux/thermal.h:166:29: note: expected ‘int’ but argument is of type ‘struct rcar_thermal_priv *’ drivers/thermal/rcar_thermal.c:214:10: error: too few arguments to function ‘thermal_zone_device_register’ include/linux/thermal.h:166:29: note: declared here make[1]: *** [drivers/thermal/rcar_thermal.o] Error 1 make: *** [drivers/thermal/rcar_thermal.o] Error 2 with gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) Signed-off-by: Devendra Naga Signed-off-by: Kuninori Morimoto Signed-off-by: Zhang Rui --- drivers/thermal/rcar_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index d4452716aaab..f7a1b574a304 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -210,7 +210,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) goto error_free_priv; } - zone = thermal_zone_device_register("rcar_thermal", 0, priv, + zone = thermal_zone_device_register("rcar_thermal", 0, 0, priv, &rcar_thermal_zone_ops, 0, 0); if (IS_ERR(zone)) { dev_err(&pdev->dev, "thermal zone device is NULL\n"); -- cgit v1.2.3-55-g7522 From fba4e087361605d1eed63343bb08811f097c83ee Mon Sep 17 00:00:00 2001 From: Igor Murzov Date: Sat, 13 Oct 2012 04:41:25 +0400 Subject: ACPI video: Ignore errors after _DOD evaluation. There are systems where video module known to work fine regardless of broken _DOD and ignoring returned value here doesn't cause any issues later. This should fix brightness controls on some laptops. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=47861 Signed-off-by: Igor Murzov Reviewed-by: Sergey V Signed-off-by: Zhang Rui --- drivers/acpi/video.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index f94d4c818fc7..0230cb6cbb3a 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1345,12 +1345,15 @@ static int acpi_video_bus_get_devices(struct acpi_video_bus *video, struct acpi_device *device) { - int status; + int status = 0; struct acpi_device *dev; - status = acpi_video_device_enumerate(video); - if (status) - return status; + /* + * There are systems where video module known to work fine regardless + * of broken _DOD and ignoring returned value here doesn't cause + * any issues later. + */ + acpi_video_device_enumerate(video); list_for_each_entry(dev, &device->children, node) { -- cgit v1.2.3-55-g7522 From 3ae53b1e13e1ca7928a3dd2d51ea5417b618560c Mon Sep 17 00:00:00 2001 From: Jonghwan Choi Date: Tue, 23 Oct 2012 14:54:42 +0800 Subject: exynos4_tmu_driver_ids should be exynos_tmu_driver_ids. Signed-off-by: Jonghwan Choi Reviewed-by: Amit Daniel Kachhap Signed-off-by: Zhang Rui --- drivers/thermal/exynos_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/exynos_thermal.c index fd03e8581afc..6dd29e4ce36b 100644 --- a/drivers/thermal/exynos_thermal.c +++ b/drivers/thermal/exynos_thermal.c @@ -815,7 +815,7 @@ static struct platform_device_id exynos_tmu_driver_ids[] = { }, { }, }; -MODULE_DEVICE_TABLE(platform, exynos4_tmu_driver_ids); +MODULE_DEVICE_TABLE(platform, exynos_tmu_driver_ids); static inline struct exynos_tmu_platform_data *exynos_get_driver_data( struct platform_device *pdev) -- cgit v1.2.3-55-g7522 From a4d7e485bca65bd516fced77b03f92419308df72 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 29 Oct 2012 07:30:49 +0000 Subject: vmxnet3: must split too big fragments vmxnet3 has a 16Kbytes limit per tx descriptor, that happened to work as long as we provided PAGE_SIZE fragments. Our stack can now build larger fragments, so we need to split them to the 16kbytes boundary. Signed-off-by: Eric Dumazet Reported-by: jongman heo Tested-by: jongman heo Cc: Shreyas Bhatewara Reviewed-by: Bhavesh Davda Signed-off-by: Shreyas Bhatewara Signed-off-by: David S. Miller --- drivers/net/vmxnet3/vmxnet3_drv.c | 65 +++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index ce9d4f2c9776..0ae1bcc6da73 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -744,28 +744,43 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; + u32 buf_size; - tbi = tq->buf_info + tq->tx_ring.next2fill; - tbi->map_type = VMXNET3_MAP_PAGE; - tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag, - 0, skb_frag_size(frag), - DMA_TO_DEVICE); + buf_offset = 0; + len = skb_frag_size(frag); + while (len) { + tbi = tq->buf_info + tq->tx_ring.next2fill; + if (len < VMXNET3_MAX_TX_BUF_SIZE) { + buf_size = len; + dw2 |= len; + } else { + buf_size = VMXNET3_MAX_TX_BUF_SIZE; + /* spec says that for TxDesc.len, 0 == 2^14 */ + } + tbi->map_type = VMXNET3_MAP_PAGE; + tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag, + buf_offset, buf_size, + DMA_TO_DEVICE); - tbi->len = skb_frag_size(frag); + tbi->len = buf_size; - gdesc = tq->tx_ring.base + tq->tx_ring.next2fill; - BUG_ON(gdesc->txd.gen == tq->tx_ring.gen); + gdesc = tq->tx_ring.base + tq->tx_ring.next2fill; + BUG_ON(gdesc->txd.gen == tq->tx_ring.gen); - gdesc->txd.addr = cpu_to_le64(tbi->dma_addr); - gdesc->dword[2] = cpu_to_le32(dw2 | skb_frag_size(frag)); - gdesc->dword[3] = 0; + gdesc->txd.addr = cpu_to_le64(tbi->dma_addr); + gdesc->dword[2] = cpu_to_le32(dw2); + gdesc->dword[3] = 0; - dev_dbg(&adapter->netdev->dev, - "txd[%u]: 0x%llu %u %u\n", - tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr), - le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]); - vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring); - dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT; + dev_dbg(&adapter->netdev->dev, + "txd[%u]: 0x%llu %u %u\n", + tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr), + le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]); + vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring); + dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT; + + len -= buf_size; + buf_offset += buf_size; + } } ctx->eop_txd = gdesc; @@ -886,6 +901,18 @@ vmxnet3_prepare_tso(struct sk_buff *skb, } } +static int txd_estimate(const struct sk_buff *skb) +{ + int count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + 1; + int i; + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; + + count += VMXNET3_TXD_NEEDED(skb_frag_size(frag)); + } + return count; +} /* * Transmits a pkt thru a given tq @@ -914,9 +941,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq, union Vmxnet3_GenericDesc tempTxDesc; #endif - /* conservatively estimate # of descriptors to use */ - count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + - skb_shinfo(skb)->nr_frags + 1; + count = txd_estimate(skb); ctx.ipv4 = (vlan_get_protocol(skb) == cpu_to_be16(ETH_P_IP)); -- cgit v1.2.3-55-g7522