4.4.4-stable review
Subsystems (5)
Greg Kroah-Hartman
maintainerPATCH 163/342 clk: exynos: use irqsave version of spin_lock to avoid deadlock with irqs
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marek Szyprowski <[email protected]>
commit 6b4feaea251a97bf08c7d41eabdec07f63a11073 upstream.
It is allowed to enable/disable clocks from interrupts, so common Exynos ARM clock management code for CPUfreq should use 'irqsave' version of spin_lock calls to avoid potential deadlock caused by spin_lock recursion. The same spin_lock is used by gate/mux clocks during enable/disable calls.
This deadlock, can be reproduced by enabling CPUfreq (ondemand or userspace) and decoding video with s5p-mfc driver.
Relevant stack trace:
[ 5928.061534] BUG: spinlock recursion on CPU#0, bash/1252 [ 5928.061609] lock: 0xee80454c, .magic: dead4ead, .owner: bash/1252, .owner_cpu: 0 [ 5928.068586] CPU: 0 PID: 1252 Comm: bash Tainted: G W 4.4.0-rc4-00001-g447a7fd #678 [ 5928.077260] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree) [ 5928.083359] [<c00153dc>] (unwind_backtrace) from [<c00121b4>] (show_stack+0x10/0x14) [ 5928.091072] [<c00121b4>] (show_stack) from [<c0213e28>] (dump_stack+0x68/0xb8) [ 5928.098275] [<c0213e28>] (dump_stack) from [<c005c1ec>] (do_raw_spin_lock+0x184/0x1ac) [ 5928.106177] [<c005c1ec>] (do_raw_spin_lock) from [<c05cfa98>] (_raw_spin_lock_irqsave+0x20/0x28) [ 5928.114943] [<c05cfa98>] (_raw_spin_lock_irqsave) from [<c0468698>] (clk_gate_endisable+0x24/0x98) [ 5928.123882] [<c0468698>] (clk_gate_endisable) from [<c0464d40>] (clk_core_disable+0x60/0x84) [ 5928.132299] [<c0464d40>] (clk_core_disable) from [<c0465e00>] (clk_disable+0x24/0x30) [ 5928.140117] [<c0465e00>] (clk_disable) from [<c03f3b80>] (s5p_mfc_handle_frame+0x254/0x860) [ 5928.148445] [<c03f3b80>] (s5p_mfc_handle_frame) from [<c03f4b34>] (s5p_mfc_irq+0x890/0xa24) [ 5928.156778] [<c03f4b34>] (s5p_mfc_irq) from [<c00627bc>] (handle_irq_event_percpu+0x50/0x14c) [ 5928.165283] [<c00627bc>] (handle_irq_event_percpu) from [<c00628f0>] (handle_irq_event+0x38/0x5c) [ 5928.174143] [<c00628f0>] (handle_irq_event) from [<c0065864>] (handle_fasteoi_irq+0xdc/0x1a4) [ 5928.182645] [<c0065864>] (handle_fasteoi_irq) from [<c0062090>] (generic_handle_irq+0x18/0x28) [ 5928.191236] [<c0062090>] (generic_handle_irq) from [<c00621a4>] (__handle_domain_irq+0x6c/0xdc) [ 5928.199917] [<c00621a4>] (__handle_domain_irq) from [<c0009470>] (gic_handle_irq+0x4c/0x98) [ 5928.208249] [<c0009470>] (gic_handle_irq) from [<c0012c54>] (__irq_svc+0x54/0x90) [ 5928.215709] Exception stack(0xeddb5cb8 to 0xeddb5d00) [ 5928.220745] 5ca0: ee80454c faddfadc [ 5928.228906] 5cc0: 00000000 01000001 ee831ce0 f8114200 ee807c00 01130520 00000403 eddb5d84 [ 5928.237063] 5ce0: ee807c48 2faf0800 ee807c0c eddb5d08 c046b618 c046b634 20000053 ffffffff [ 5928.245225] [<c0012c54>] (__irq_svc) from [<c046b634>] (exynos_cpuclk_notifier_cb+0x170/0x270) [ 5928.253823] [<c046b634>] (exynos_cpuclk_notifier_cb) from [<c003cb58>] (notifier_call_chain+0x44/0x84) [ 5928.263106] [<c003cb58>] (notifier_call_chain) from [<c003ccd4>] (__srcu_notifier_call_chain+0x6c/0x9c) [ 5928.272480] [<c003ccd4>] (__srcu_notifier_call_chain) from [<c003cd1c>] (srcu_notifier_call_chain+0x18/0x20) [ 5928.282288] [<c003cd1c>] (srcu_notifier_call_chain) from [<c0464ed0>] (__clk_notify+0x6c/0x74) [ 5928.290881] [<c0464ed0>] (__clk_notify) from [<c0465388>] (clk_propagate_rate_change+0xa0/0xac) [ 5928.299561] [<c0465388>] (clk_propagate_rate_change) from [<c0465378>] (clk_propagate_rate_change+0x90/0xac) [ 5928.309370] [<c0465378>] (clk_propagate_rate_change) from [<c04666fc>] (clk_core_set_rate_nolock+0x64/0xa8) [ 5928.319091] [<c04666fc>] (clk_core_set_rate_nolock) from [<c0466760>] (clk_set_rate+0x20/0x30) [ 5928.327686] [<c0466760>] (clk_set_rate) from [<c0428c70>] (set_target+0xe8/0x23c) [ 5928.335152] [<c0428c70>] (set_target) from [<c04244d0>] (__cpufreq_driver_target+0x184/0x29c) [ 5928.343655] [<c04244d0>] (__cpufreq_driver_target) from [<c0427128>] (cpufreq_set+0x44/0x64) [ 5928.352074] [<c0427128>] (cpufreq_set) from [<c0423948>] (store_scaling_setspeed+0x5c/0x74) [ 5928.360407] [<c0423948>] (store_scaling_setspeed) from [<c04238d0>] (store+0x7c/0x98) [ 5928.368221] [<c04238d0>] (store) from [<c0132540>] (sysfs_kf_write+0x44/0x48) [ 5928.375338] [<c0132540>] (sysfs_kf_write) from [<c0131b9c>] (kernfs_fop_write+0xb8/0x1bc) [ 5928.383496] [<c0131b9c>] (kernfs_fop_write) from [<c00d71f8>] (__vfs_write+0x2c/0xd4) [ 5928.391308] [<c00d71f8>] (__vfs_write) from [<c00d7de8>] (vfs_write+0xa0/0x144) [ 5928.398598] [<c00d7de8>] (vfs_write) from [<c00d8048>] (SyS_write+0x44/0x84) [ 5928.405631] [<c00d8048>] (SyS_write) from [<c000f540>] (ret_fast_syscall+0x0/0x3c)
--- drivers/clk/samsung/clk-cpu.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/clk/samsung/clk-cpu.c +6 -4
@@ -148,6 +148,7 @@ static int exynos_cpuclk_pre_rate_changeunsigned long alt_prate =clk_get_rate (cpuclk->alt_parent);unsigned long alt_div =0 , alt_div_mask =DIV_MASK ;unsigned long div0, div1 =0 , mux_reg; +unsigned long flags;/* find out the divider values to use for clock data */ while ((cfg_data->prate *1000 ) != ndata->new_rate) {
@@ -156,7 +157,7 @@ static int exynos_cpuclk_pre_rate_change cfg_data++; } -spin_lock (cpuclk->lock); +spin_lock_irqsave (cpuclk->lock, flags);/* * For the selected PLL clock frequency, get the pre-defined divider
@@ -212,7 +213,7 @@ static int exynos_cpuclk_pre_rate_change DIV_MASK_ALL); } -spin_unlock (cpuclk->lock); +spin_unlock_irqrestore (cpuclk->lock, flags);return 0 ; }
@@ -223,6 +224,7 @@ static int exynos_cpuclk_post_rate_changconst struct exynos_cpuclk_cfg_data *cfg_data = cpuclk->cfg;unsigned long div =0 , div_mask =DIV_MASK ;unsigned long mux_reg; +unsigned long flags;/* find out the divider values to use for clock data */ if (cpuclk->flags &CLK_CPU_NEEDS_DEBUG_ALT_DIV ) {
@@ -233,7 +235,7 @@ static int exynos_cpuclk_post_rate_chang } } -spin_lock (cpuclk->lock); +spin_lock_irqsave (cpuclk->lock, flags);/* select mout_apll as the alternate parent */ mux_reg =readl (base +E4210_SRC_CPU );
@@ -246,7 +248,7 @@ static int exynos_cpuclk_post_rate_chang }exynos_set_safe_div (base, div, div_mask); -spin_unlock (cpuclk->lock); +spin_unlock_irqrestore (cpuclk->lock, flags);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 164/342 regulator: axp20x: Fix GPIO LDO enable value for AXP22x
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen-Yu Tsai <[email protected]>
commit 3cb99e2ea99a454c8837a55aac88753ef05fc1eb upstream.
The enable/disable values for GPIO LDOs are reversed. It seems no one noticed as AXP22x support was introduced recently, and no one was using the GPIO LDOs, either because no designs actually use them or board support hasn't caught up.
--- drivers/regulator/axp20x-regulator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/regulator/axp20x-regulator.c +2 -2
@@ -27,8 +27,8 @@#define AXP20X_IO_ENABLED 0x03#define AXP20X_IO_DISABLED 0x07 -#define AXP22X_IO_ENABLED 0x04 -#define AXP22X_IO_DISABLED 0x03 +#define AXP22X_IO_ENABLED 0x03 +#define AXP22X_IO_DISABLED 0x04#define AXP20X_WORKMODE_DCDC2_MASK BIT(2)#define AXP20X_WORKMODE_DCDC3_MASK BIT(1)
Greg Kroah-Hartman
maintainerPATCH 165/342 regulator: mt6311: MT6311_REGULATOR needs to select REGMAP_I2C
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Henry Chen <[email protected]>
commit aab3c3f34cc2dd8230052770712606d65de6538f upstream.
This patch fix the below build error:drivers/regulator/mt6311-regulator.c:111: undefined reference to `__devm_regmap_init_i2c'
--- drivers/regulator/Kconfig | 1 + 1 file changed, 1 insertion(+)
drivers/regulator/Kconfig +1 -0
@@ -446,6 +446,7 @@ config REGULATOR_MC13892 config REGULATOR_MT6311 tristate "MediaTek MT6311 PMIC" depends on I2C + select REGMAP_I2C help Say y here to select this option to enable the power regulator of MediaTek MT6311 PMIC.
Greg Kroah-Hartman
maintainerPATCH 166/342 virtio_balloon: fix race by fill and leak
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Minchan Kim <[email protected]>
commit f68b992bbb474641881932c61c92dcfa6f5b3689 upstream.
During my compaction-related stuff, I encountered a bug with ballooning.
With repeated inflating and deflating cycle, guest memory( ie, cat /proc/meminfo | grep MemTotal) is decreased and couldn't be recovered.
The reason is balloon_lock doesn't cover release_pages_balloon so struct virtio_balloon fields could be overwritten by race of fill_balloon(e,g, vb->*pfns could be critical).
This patch fixes it in my test.
--- drivers/virtio/virtio_balloon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/virtio/virtio_balloon.c +1 -1
@@ -209,8 +209,8 @@ static unsigned leak_balloon(struct virt*/ if (vb->num_pfns !=0 )tell_host (vb, vb->deflate_vq); -mutex_unlock (&vb->balloon_lock);release_pages_balloon (vb); +mutex_unlock (&vb->balloon_lock);return num_freed_pages; }
Greg Kroah-Hartman
maintainerPATCH 167/342 virtio_balloon: fix race between migration and ballooning
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Minchan Kim <[email protected]>
commit 21ea9fb69e7c4b1b1559c3e410943d3ff248ffcb upstream.
In balloon_page_dequeue, pages_lock should cover the loop (ie, list_for_each_entry_safe). Otherwise, the cursor page could be isolated by compaction and then list_del by isolation could poison the page->lru.{prev,next} so the loop finally could access wrong address like this. This patch fixes the bug.
general protection fault: 0000 [#1] SMP Dumping ftrace buffer: (ftrace buffer empty) Modules linked in: CPU: 2 PID: 82 Comm: vballoon Not tainted 4.4.0-rc5-mm1-access_bit+ #1906 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 task: ffff8800a7ff0000 ti: ffff8800a7fec000 task.ti: ffff8800a7fec000 RIP: 0010:[<ffffffff8115e754>] [<ffffffff8115e754>] balloon_page_dequeue+0x54/0x130 RSP: 0018:ffff8800a7fefdc0 EFLAGS: 00010246 RAX: ffff88013fff9a70 RBX: ffffea000056fe00 RCX: 0000000000002b7d RDX: ffff88013fff9a70 RSI: ffffea000056fe00 RDI: ffff88013fff9a68 RBP: ffff8800a7fefde8 R08: ffffea000056fda0 R09: 0000000000000000 R10: ffff8800a7fefd90 R11: 0000000000000001 R12: dead0000000000e0 R13: ffffea000056fe20 R14: ffff880138809070 R15: ffff880138809060 FS: 0000000000000000(0000) GS:ffff88013fc40000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 00007f229c10e000 CR3: 00000000b8b53000 CR4: 00000000000006a0 Stack: 0000000000000100 ffff880138809088 ffff880138809000 ffff880138809060 0000000000000046 ffff8800a7fefe28 ffffffff812c86d3 ffff880138809020 ffff880138809000 fffffffffff91900 0000000000000100 ffff880138809060 Call Trace: [<ffffffff812c86d3>] leak_balloon+0x93/0x1a0 [<ffffffff812c8bc7>] balloon+0x217/0x2a0 [<ffffffff8143739e>] ? __schedule+0x31e/0x8b0 [<ffffffff81078160>] ? abort_exclusive_wait+0xb0/0xb0 [<ffffffff812c89b0>] ? update_balloon_stats+0xf0/0xf0 [<ffffffff8105b6e9>] kthread+0xc9/0xe0 [<ffffffff8105b620>] ? kthread_park+0x60/0x60 [<ffffffff8143b4af>] ret_from_fork+0x3f/0x70 [<ffffffff8105b620>] ? kthread_park+0x60/0x60 Code: 8d 60 e0 0f 84 af 00 00 00 48 8b 43 20 a8 01 75 3b 48 89 d8 f0 0f ba 28 00 72 10 48 8b 03 f6 c4 08 75 2f 48 89 df e8 8c 83 f9 ff <49> 8b 44 24 20 4d 8d 6c 24 20 48 83 e8 20 4d 39 f5 74 7a 4c 89 RIP [<ffffffff8115e754>] balloon_page_dequeue+0x54/0x130 RSP <ffff8800a7fefdc0> ---[ end trace 43cf28060d708d5f ]--- Kernel panic - not syncing: Fatal exception
Dumping ftrace buffer:
(ftrace buffer empty)
Kernel Offset: disabled
--- mm/balloon_compaction.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
mm/balloon_compaction.c +2 -2
@@ -61,6 +61,7 @@ struct page *balloon_page_dequeue(structbool dequeued_page; dequeued_page = false; +spin_lock_irqsave (&b_dev_info->pages_lock, flags);list_for_each_entry_safe (page, tmp, &b_dev_info->pages, lru) {/* * Block others from accessing the 'page' while we get around
@@ -75,15 +76,14 @@ struct page *balloon_page_dequeue(struct continue; }#endif -spin_lock_irqsave (&b_dev_info->pages_lock, flags);balloon_page_delete (page);__count_vm_event (BALLOON_DEFLATE ); -spin_unlock_irqrestore (&b_dev_info->pages_lock, flags);unlock_page (page); dequeued_page = true;break ; } } +spin_unlock_irqrestore (&b_dev_info->pages_lock, flags);if (!dequeued_page) {/*
Greg Kroah-Hartman
maintainerPATCH 168/342 virtio_pci: fix use after free on release
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael S. Tsirkin <[email protected]>
commit 2989be09a8a9d62a785137586ad941f916e08f83 upstream.
KASan detected a use-after-free error in virtio-pci remove code. In virtio_pci_remove(), vp_dev is still used after being freed in unregister_virtio_device() (in virtio_pci_release_dev() more precisely).
To fix, keep a reference until cleanup is done.
--- drivers/virtio/virtio_pci_common.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/virtio/virtio_pci_common.c +2 -0
@@ -545,6 +545,7 @@ err_enable_device:static void virtio_pci_remove (struct pci_dev *pci_dev) {struct virtio_pci_device *vp_dev =pci_get_drvdata (pci_dev); +struct device *dev =get_device (&vp_dev->vdev.dev);unregister_virtio_device (&vp_dev->vdev);
@@ -554,6 +555,7 @@ static void virtio_pci_remove(struct pcivirtio_pci_modern_remove (vp_dev);pci_disable_device (pci_dev); +put_device (dev); }static struct pci_driver virtio_pci_driver = {
Greg Kroah-Hartman
maintainerPATCH 169/342 drm/vmwgfx: Fix an incorrect lock check
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Hellstrom <[email protected]>
commit fb89ac5102ae2875d685c847e6b5dbc141622d43 upstream.
With CONFIG_SMP=n and CONFIG_DEBUG_SPINLOCK=y the vmwgfx kernel module would unconditionally throw a bug when checking for a held spinlock in the command buffer code. Fix this by using a lockdep check.
--- drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c +1 -1
@@ -247,7 +247,7 @@ static void __vmw_cmdbuf_header_free(str {struct vmw_cmdbuf_man *man = header->man; -BUG_ON (!spin_is_locked (&man->lock)); +lockdep_assert_held_once (&man->lock);if (header->inline_space) {vmw_cmdbuf_header_inline_free (header);
Greg Kroah-Hartman
maintainerPATCH 170/342 drm/vmwgfx: Fix a width / pitch mismatch on framebuffer updates
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Hellstrom <[email protected]>
commit a50e2bf5a0f674d62b69f51f6935a30e82bd015c upstream.
When the framebuffer is a vmwgfx dma buffer and a proxy surface is created, the vmw_kms_update_proxy() function requires that the proxy surface width and the framebuffer pitch are compatible, otherwise display corruption occurs as seen in gnome-shell/native with software 3D. Since the framebuffer pitch is determined by user-space, allocate a proxy surface the width of which is based on the framebuffer pitch rather than on the framebuffer width.
--- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +5 -1
@@ -763,21 +763,25 @@ static int vmw_create_dmabuf_proxy(strucuint32_t format;struct drm_vmw_size content_base_size;struct vmw_resource *res; +unsigned int bytes_pp;int ret;switch (mode_cmd->depth) {case 32 :case 24 : format =SVGA3D_X8R8G8B8 ; + bytes_pp =4 ;break ;case 16 :case 15 : format =SVGA3D_R5G6B5 ; + bytes_pp =2 ;break ;case 8 : format =SVGA3D_P8 ; + bytes_pp =1 ;break ;default :
@@ -785,7 +789,7 @@ static int vmw_create_dmabuf_proxy(strucreturn -EINVAL ; } - content_base_size.width = mode_cmd->width; + content_base_size.width = mode_cmd->pitch / bytes_pp; content_base_size.height = mode_cmd->height; content_base_size.depth =1 ;
Greg Kroah-Hartman
maintainerPATCH 171/342 drm/vmwgfx: respect nomodeset
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rob Clark <[email protected]>
commit 96c5d076f0a5e2023ecdb44d8261f87641ee71e0 upstream.
--- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +7 -0
@@ -25,6 +25,7 @@* **************************************************************************/ #include <linux/module.h> +#include <linux/console.h> #include <drm/drmP.h> #include "vmwgfx_drv.h"
@@ -1538,6 +1539,12 @@ static int vmw_probe(struct pci_dev *pdestatic int __init vmwgfx_init (void ) {int ret; + +#ifdef CONFIG_VGA_CONSOLE +if (vgacon_text_force ()) +return -EINVAL ; +#endif + ret =drm_pci_init (&driver, &vmw_pci_driver);if (ret)DRM_ERROR ("Failed initializing DRM.\n" );
Greg Kroah-Hartman
maintainerPATCH 172/342 drm/amdgpu: Fix off-by-one errors in amdgpu_vm_bo_map
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Kuehling <[email protected]>
commit 005ae95e6ec119c64e2d16eb65a94c49e1dcf9f0 upstream.
eaddr is sometimes treated as the last address inside the address range, and sometimes as the first address outside the range. This was resulting in errors when a test filled up the entire address space. Make it consistent to always be the last address within the range.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +5 -5
@@ -1010,13 +1010,13 @@ int amdgpu_vm_bo_map(struct amdgpu_devicreturn -EINVAL ;/* make sure object fit at this offset */ - eaddr = saddr + size; + eaddr = saddr + size -1 ;if ((saddr >= eaddr) || (offset + size >amdgpu_bo_size (bo_va->bo)))return -EINVAL ; last_pfn = eaddr /AMDGPU_GPU_PAGE_SIZE ; -if (last_pfn > adev->vm_manager.max_pfn) { -dev_err (adev->dev,"va above limit (0x%08X > 0x%08X)\n" , +if (last_pfn >= adev->vm_manager.max_pfn) { +dev_err (adev->dev,"va above limit (0x%08X >= 0x%08X)\n" , last_pfn, adev->vm_manager.max_pfn);return -EINVAL ; }
@@ -1025,7 +1025,7 @@ int amdgpu_vm_bo_map(struct amdgpu_devic eaddr /=AMDGPU_GPU_PAGE_SIZE ;spin_lock (&vm->it_lock); - it =interval_tree_iter_first (&vm->va, saddr, eaddr -1 ); + it =interval_tree_iter_first (&vm->va, saddr, eaddr);spin_unlock (&vm->it_lock);if (it) {struct amdgpu_bo_va_mapping *tmp;
@@ -1046,7 +1046,7 @@ int amdgpu_vm_bo_map(struct amdgpu_devicINIT_LIST_HEAD (&mapping->list); mapping->it.start = saddr; - mapping->it.last = eaddr -1 ; + mapping->it.last = eaddr; mapping->offset = offset; mapping->flags = flags;
Greg Kroah-Hartman
maintainerPATCH 173/342 drm/amdgpu: call hpd_irq_event on resume
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
commit 54fb2a5cd0baf8e97d743de411e2f832d1afa68d upstream.
Need to call this on resume if displays changes during suspend in order to properly be notified of changes.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +1 -0
@@ -1788,6 +1788,7 @@ int amdgpu_resume_kms(struct drm_device }drm_kms_helper_poll_enable (dev); +drm_helper_hpd_irq_event (dev);if (fbcon) {amdgpu_fbdev_set_suspend (adev,0 );
Greg Kroah-Hartman
maintainerPATCH 174/342 drm/amdgpu: fix lost sync_to if scheduler is enabled.
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chunming Zhou <[email protected]>
commit 888c9e33e4c5a503285921046c621f7c73199d2f upstream.
when scheduler is enabled, the semaphore isn't used at all.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c +3 -2
@@ -293,7 +293,8 @@ int amdgpu_sync_rings(struct amdgpu_sync fence =to_amdgpu_fence (sync->sync_to[i]);/* check if we really need to sync */ -if (!amdgpu_fence_need_sync (fence, ring)) +if (!amdgpu_enable_scheduler && + !amdgpu_fence_need_sync (fence, ring))continue ;/* prevent GPU deadlocks */
@@ -303,7 +304,7 @@ int amdgpu_sync_rings(struct amdgpu_sync }if (amdgpu_enable_scheduler || !amdgpu_enable_semaphores) { - r =fence_wait (&fence->base, true); + r =fence_wait (sync->sync_to[i], true);if (r)return r;continue ;
Greg Kroah-Hartman
maintainerPATCH 175/342 drm/amdgpu: fix tonga smu resume
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
commit e160e4db833c7e8587ec3c88efaed0d84f1bcf42 upstream.
Need to make sure smu buffers are pinned on resume. This matches what Fiji does.
--- drivers/gpu/drm/amd/amdgpu/tonga_dpm.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-)
drivers/gpu/drm/amd/amdgpu/tonga_dpm.c +2 -15
@@ -122,25 +122,12 @@ static int tonga_dpm_hw_fini(void *handlstatic int tonga_dpm_suspend (void *handle) { -return 0 ; +return tonga_dpm_hw_fini (handle); }static int tonga_dpm_resume (void *handle) { -int ret; -struct amdgpu_device *adev = (struct amdgpu_device *)handle; - -mutex_lock (&adev->pm.mutex); - - ret =tonga_smu_start (adev); -if (ret) { -DRM_ERROR ("SMU start failed\n" ); - goto fail; - } - -fail: -mutex_unlock (&adev->pm.mutex); -return ret; +return tonga_dpm_hw_init (handle); } static int tonga_dpm_set_clockgating_state(void *handle,
Greg Kroah-Hartman
maintainerPATCH 176/342 drm/amdgpu: fix amdgpu_bo_pin_restricted VRAM placing v2
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian König <[email protected]>
commit 78d0e182b6c1f5336f6e8cbb197f403276dabc7f upstream.
We could pin BOs into invisible VRAM otherwise.
v2: make logic more readable as suggested by Michel
--- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +2 -1
@@ -399,7 +399,8 @@ int amdgpu_bo_pin_restricted(struct amdg }if (fpfn > bo->placements[i].fpfn) bo->placements[i].fpfn = fpfn; -if (lpfn && lpfn < bo->placements[i].lpfn) +if (!bo->placements[i].lpfn || + (lpfn && lpfn < bo->placements[i].lpfn)) bo->placements[i].lpfn = lpfn; bo->placements[i].flags |=TTM_PL_FLAG_NO_EVICT ; }
Greg Kroah-Hartman
maintainerPATCH 177/342 drm/amdgpu: no need to load MC firmware on fiji
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
commit ad32152eb26043d165eed9406cb9e2f7011f6b10 upstream.
Vbios does this for us on asic_init.
--- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +2 -4
@@ -44,7 +44,6 @@ static void gmc_v8_0_set_irq_funcs(strucMODULE_FIRMWARE ("amdgpu/topaz_mc.bin" );MODULE_FIRMWARE ("amdgpu/tonga_mc.bin" ); -MODULE_FIRMWARE ("amdgpu/fiji_mc.bin" );static const u32 golden_settings_tonga_a11[] = {
@@ -236,8 +235,6 @@ static int gmc_v8_0_init_microcode(struc chip_name ="tonga" ;break ;case CHIP_FIJI : - chip_name ="fiji" ; -break ;case CHIP_CARRIZO :case CHIP_STONEY :return 0 ;
@@ -1003,7 +1000,8 @@ static int gmc_v8_0_hw_init(void *handlegmc_v8_0_mc_program (adev); -if (!(adev->flags &AMD_IS_APU )) { +if ((adev->asic_type ==CHIP_TOPAZ ) || + (adev->asic_type ==CHIP_TONGA )) { r =gmc_v8_0_mc_load_microcode (adev);if (r) {DRM_ERROR ("Failed to load MC firmware!\n" );
Greg Kroah-Hartman
maintainerPATCH 178/342 drm/amdgpu: move gmc7 support out of CIK dependency
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
commit e42d85261680edfc350a6c2a86b7fbb44a85014b upstream.
It's used by iceland which is VI.
--- drivers/gpu/drm/amd/amdgpu/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/Makefile +2 -1
@@ -22,7 +22,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o # add asic specific block -amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o gmc_v7_0.o cik_ih.o kv_smc.o kv_dpm.o \ +amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \ ci_smc.o ci_dpm.o dce_v8_0.o gfx_v7_0.o cik_sdma.o uvd_v4_2.o vce_v2_0.o \ amdgpu_amdkfd_gfx_v7.o
@@ -31,6 +31,7 @@ amdgpu-y += \ # add GMC block amdgpu-y += \ + gmc_v7_0.o \ gmc_v8_0.o # add IH block
Greg Kroah-Hartman
maintainerPATCH 179/342 drm/amdgpu: iceland use CI based MC IP
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ken Wang <[email protected]>
commit 429c45deae6e57f1bb91bfb05b671063fb0cef60 upstream.
--- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 10 +++++++++- drivers/gpu/drm/amd/amdgpu/vi.c | 7 ++++--- 2 files changed, 13 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +9 -1
@@ -42,6 +42,7 @@ static void gmc_v7_0_set_irq_funcs(strucMODULE_FIRMWARE ("radeon/bonaire_mc.bin" );MODULE_FIRMWARE ("radeon/hawaii_mc.bin" ); +MODULE_FIRMWARE ("amdgpu/topaz_mc.bin" );/** * gmc8_mc_wait_for_idle - wait for MC idle callback.
@@ -132,13 +133,20 @@ static int gmc_v7_0_init_microcode(struccase CHIP_HAWAII : chip_name ="hawaii" ;break ; +case CHIP_TOPAZ : + chip_name ="topaz" ; +break ;case CHIP_KAVERI :case CHIP_KABINI :return 0 ;default :BUG (); } -snprintf (fw_name,sizeof (fw_name),"radeon/%s_mc.bin" , chip_name); +if (adev->asic_type ==CHIP_TOPAZ ) +snprintf (fw_name,sizeof (fw_name),"amdgpu/%s_mc.bin" , chip_name); +else +snprintf (fw_name,sizeof (fw_name),"radeon/%s_mc.bin" , chip_name); + err =request_firmware (&adev->mc.fw, fw_name, adev->dev);if (err) goto out;
drivers/gpu/drm/amd/amdgpu/vi.c +4 -3
@@ -60,6 +60,7 @@#include "vi.h" #include "vi_dpm.h" #include "gmc_v8_0.h" +#include "gmc_v7_0.h" #include "gfx_v8_0.h" #include "sdma_v2_4.h" #include "sdma_v3_0.h"
@@ -1128,10 +1129,10 @@ static const struct amdgpu_ip_block_vers }, { .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 8, - .minor = 0, + .major = 7, + .minor = 4, .rev = 0, - .funcs = &gmc_v8_0_ip_funcs, + .funcs = &gmc_v7_0_ip_funcs, }, { .type = AMD_IP_BLOCK_TYPE_IH,
Greg Kroah-Hartman
maintainerPATCH 180/342 drm/amdgpu: The VI specific EXE bit should only apply to GMC v8.0 above
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ken Wang <[email protected]>
commit 8f3c162961fc2d92ec73a66496aab69eb2e19c36 upstream.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +1 -1
@@ -808,7 +808,7 @@ uint32_t amdgpu_ttm_tt_pte_flags(struct flags |=AMDGPU_PTE_SNOOPED ; } -if (adev->asic_type >=CHIP_TOPAZ ) +if (adev->asic_type >=CHIP_TONGA ) flags |=AMDGPU_PTE_EXECUTABLE ; flags |=AMDGPU_PTE_READABLE ;
Greg Kroah-Hartman
maintainerPATCH 181/342 drm/amdgpu: pull topaz gmc bits into gmc_v7
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
commit 72b459c8f716ef03a8a0c78078547ce64d8d29a2 upstream.
Add the topaz golden settings into the gmc7 module.
--- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 35 ++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +33 -2
@@ -44,8 +44,37 @@ MODULE_FIRMWARE("radeon/bonaire_mc.bin")MODULE_FIRMWARE ("radeon/hawaii_mc.bin" );MODULE_FIRMWARE ("amdgpu/topaz_mc.bin" ); +static const u32 golden_settings_iceland_a11[] = +{ + mmVM_PRT_APERTURE0_LOW_ADDR,0x0fffffff ,0x0fffffff , + mmVM_PRT_APERTURE1_LOW_ADDR,0x0fffffff ,0x0fffffff , + mmVM_PRT_APERTURE2_LOW_ADDR,0x0fffffff ,0x0fffffff , + mmVM_PRT_APERTURE3_LOW_ADDR,0x0fffffff ,0x0fffffff +}; + +static const u32 iceland_mgcg_cgcg_init[] = +{ + mmMC_MEM_POWER_LS,0xffffffff ,0x00000104 +}; + +static void gmc_v7_0_init_golden_registers (struct amdgpu_device *adev) +{ +switch (adev->asic_type) { +case CHIP_TOPAZ : +amdgpu_program_register_sequence (adev, + iceland_mgcg_cgcg_init, + (const u32 )ARRAY_SIZE (iceland_mgcg_cgcg_init)); +amdgpu_program_register_sequence (adev, + golden_settings_iceland_a11, + (const u32 )ARRAY_SIZE (golden_settings_iceland_a11)); +break ; +default : +break ; + } +} +/** -* gmc8_mc_wait_for_idle - wait for MC idle callback. +* gmc7_mc_wait_for_idle - wait for MC idle callback. * * @adev: amdgpu_device pointer *
@@ -142,7 +171,7 @@ static int gmc_v7_0_init_microcode(strucdefault :BUG (); } -if (adev->asic_type ==CHIP_TOPAZ ) +if (adev->asic_type ==CHIP_TOPAZ )snprintf (fw_name,sizeof (fw_name),"amdgpu/%s_mc.bin" , chip_name);else snprintf (fw_name,sizeof (fw_name),"radeon/%s_mc.bin" , chip_name);
@@ -988,6 +1017,8 @@ static int gmc_v7_0_hw_init(void *handleint r;struct amdgpu_device *adev = (struct amdgpu_device *)handle; +gmc_v7_0_init_golden_registers (adev); +gmc_v7_0_mc_program (adev);if (!(adev->flags &AMD_IS_APU )) {
Greg Kroah-Hartman
maintainerPATCH 182/342 drm/amdgpu: drop topaz support from gmc8 module
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
commit 8878d8548ac7fae43cd6d82579f966eb8825e282 upstream.
topaz is actually gmc7.
--- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-)
drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +1 -27
@@ -42,7 +42,6 @@static void gmc_v8_0_set_gart_funcs (struct amdgpu_device *adev);static void gmc_v8_0_set_irq_funcs (struct amdgpu_device *adev); -MODULE_FIRMWARE ("amdgpu/topaz_mc.bin" );MODULE_FIRMWARE ("amdgpu/tonga_mc.bin" ); static const u32 golden_settings_tonga_a11[] =
@@ -74,19 +73,6 @@ static const u32 fiji_mgcg_cgcg_init[] = mmMC_MEM_POWER_LS,0xffffffff ,0x00000104 }; -static const u32 golden_settings_iceland_a11[] = -{ - mmVM_PRT_APERTURE0_LOW_ADDR,0x0fffffff ,0x0fffffff , - mmVM_PRT_APERTURE1_LOW_ADDR,0x0fffffff ,0x0fffffff , - mmVM_PRT_APERTURE2_LOW_ADDR,0x0fffffff ,0x0fffffff , - mmVM_PRT_APERTURE3_LOW_ADDR,0x0fffffff ,0x0fffffff -}; - -static const u32 iceland_mgcg_cgcg_init[] = -{ - mmMC_MEM_POWER_LS,0xffffffff ,0x00000104 -}; -static const u32 cz_mgcg_cgcg_init[] = { mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104
@@ -101,14 +87,6 @@ static const u32 stoney_mgcg_cgcg_init[]static void gmc_v8_0_init_golden_registers (struct amdgpu_device *adev) {switch (adev->asic_type) { -case CHIP_TOPAZ : -amdgpu_program_register_sequence (adev, - iceland_mgcg_cgcg_init, - (const u32 )ARRAY_SIZE (iceland_mgcg_cgcg_init)); -amdgpu_program_register_sequence (adev, - golden_settings_iceland_a11, - (const u32 )ARRAY_SIZE (golden_settings_iceland_a11)); -break ;case CHIP_FIJI : amdgpu_program_register_sequence(adev, fiji_mgcg_cgcg_init,
@@ -228,9 +206,6 @@ static int gmc_v8_0_init_microcode(strucDRM_DEBUG ("\n" );switch (adev->asic_type) { -case CHIP_TOPAZ : - chip_name ="topaz" ; -break ;case CHIP_TONGA : chip_name ="tonga" ;break ;
@@ -1000,8 +975,7 @@ static int gmc_v8_0_hw_init(void *handlegmc_v8_0_mc_program (adev); -if ((adev->asic_type ==CHIP_TOPAZ ) || - (adev->asic_type ==CHIP_TONGA )) { +if (adev->asic_type ==CHIP_TONGA ) { r =gmc_v8_0_mc_load_microcode (adev);if (r) {DRM_ERROR ("Failed to load MC firmware!\n" );
Greg Kroah-Hartman
maintainerPATCH 183/342 drm/amdgpu: dont load MEC2 on topaz
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
commit 97dde76a30c2e67fa5fb9cb6a4072c0178c9df26 upstream.
Not validated.
--- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/iceland_smc.c | 12 +++--------- 2 files changed, 5 insertions(+), 11 deletions(-)
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +2 -2
@@ -90,7 +90,6 @@ MODULE_FIRMWARE("amdgpu/topaz_ce.bin");MODULE_FIRMWARE ("amdgpu/topaz_pfp.bin" );MODULE_FIRMWARE ("amdgpu/topaz_me.bin" );MODULE_FIRMWARE ("amdgpu/topaz_mec.bin" ); -MODULE_FIRMWARE ("amdgpu/topaz_mec2.bin" );MODULE_FIRMWARE ("amdgpu/topaz_rlc.bin" );MODULE_FIRMWARE ("amdgpu/fiji_ce.bin" );
@@ -807,7 +806,8 @@ static int gfx_v8_0_init_microcode(struc adev->gfx.mec_fw_version =le32_to_cpu (cp_hdr->header.ucode_version); adev->gfx.mec_feature_version =le32_to_cpu (cp_hdr->ucode_feature_version); -if (adev->asic_type !=CHIP_STONEY ) { +if ((adev->asic_type !=CHIP_STONEY ) && + (adev->asic_type !=CHIP_TOPAZ )) {snprintf (fw_name,sizeof (fw_name),"amdgpu/%s_mec2.bin" , chip_name); err =request_firmware (&adev->gfx.mec2_fw, fw_name, adev->dev);if (!err) {
drivers/gpu/drm/amd/amdgpu/iceland_smc.c +3 -9
@@ -432,7 +432,7 @@ static uint32_t iceland_smu_get_mask_forcase AMDGPU_UCODE_ID_CP_ME :return UCODE_ID_CP_ME_MASK ;case AMDGPU_UCODE_ID_CP_MEC1 : -return UCODE_ID_CP_MEC_MASK |UCODE_ID_CP_MEC_JT1_MASK |UCODE_ID_CP_MEC_JT2_MASK ; +return UCODE_ID_CP_MEC_MASK |UCODE_ID_CP_MEC_JT1_MASK ;case AMDGPU_UCODE_ID_CP_MEC2 :return UCODE_ID_CP_MEC_MASK ;case AMDGPU_UCODE_ID_RLC_G :
@@ -522,12 +522,6 @@ static int iceland_smu_request_load_fw(sreturn -EINVAL ; } -if (iceland_smu_populate_single_firmware_entry (adev,UCODE_ID_CP_MEC_JT2 , - &toc->entry[toc->num_entries++])) { -DRM_ERROR ("Failed to get firmware entry for MEC_JT2\n" ); -return -EINVAL ; - } -if (iceland_smu_populate_single_firmware_entry (adev,UCODE_ID_SDMA0 , &toc->entry[toc->num_entries++])) {DRM_ERROR ("Failed to get firmware entry for SDMA0\n" );
@@ -550,8 +544,8 @@ static int iceland_smu_request_load_fw(sUCODE_ID_CP_ME_MASK |UCODE_ID_CP_PFP_MASK |UCODE_ID_CP_MEC_MASK | -UCODE_ID_CP_MEC_JT1_MASK | -UCODE_ID_CP_MEC_JT2_MASK ; +UCODE_ID_CP_MEC_JT1_MASK ; +if (iceland_send_msg_to_smc_with_parameter_without_waiting (adev, PPSMC_MSG_LoadUcodes, fw_to_load)) {DRM_ERROR ("Fail to request SMU load ucode\n" );
Greg Kroah-Hartman
maintainerPATCH 184/342 drm/amdgpu: remove exp hardware support from iceland
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
commit dba280b20bfd1c2bed8a07ce3f75a6da8ba7d247 upstream.
It's working now.
bug:
https://bugs.freedesktop.org/show_bug.cgi?id=92270
--- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +5 -5
@@ -250,11 +250,11 @@ static struct pci_device_id pciidlist[] {0x1002, 0x985F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU}, #endif /* topaz */ - {0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6902, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6907, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT}, + {0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, + {0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, + {0x1002, 0x6902, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, + {0x1002, 0x6903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, + {0x1002, 0x6907, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, /* tonga */ {0x1002, 0x6920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA}, {0x1002, 0x6921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
Greg Kroah-Hartman
maintainerPATCH 185/342 drm/amdgpu: fix s4 resume
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Flora Cui <[email protected]>
commit ca19852884c8937eed89560f924f5a34cfcc22af upstream.
No need to re-init asic if it's already been initialized. Skip IB tests since kernel processes are frozen in thaw.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +9 -4
@@ -1744,15 +1744,20 @@ int amdgpu_resume_kms(struct drm_device }/* post card */ -amdgpu_atom_asic_init (adev->mode_info.atom_context); +if (!amdgpu_card_posted (adev)) +amdgpu_atom_asic_init (adev->mode_info.atom_context); r =amdgpu_resume (adev); +if (r) +DRM_ERROR ("amdgpu_resume failed (%d).\n" , r);amdgpu_fence_driver_resume (adev); - r =amdgpu_ib_ring_tests (adev); -if (r) -DRM_ERROR ("ib ring test failed (%d).\n" , r); +if (resume) { + r =amdgpu_ib_ring_tests (adev); +if (r) +DRM_ERROR ("ib ring test failed (%d).\n" , r); + } r =amdgpu_late_init (adev);if (r)
Greg Kroah-Hartman
maintainerPATCH 186/342 drm/amdgpu: remove unnecessary forward declaration
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolai Hähnle <[email protected]>
commit b19763d0d867eb863953500a5c87f2fd663863b8 upstream.
--- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 -- 1 file changed, 2 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu.h +0 -2
@@ -604,8 +604,6 @@ struct amdgpu_sa_manager {uint32_t align; }; -struct amdgpu_sa_bo ; -/* sub-allocation buffer */ struct amdgpu_sa_bo {struct list_head olist;
Greg Kroah-Hartman
maintainerPATCH 187/342 drm/amdgpu: hold reference to fences in amdgpu_sa_bo_new (v2)
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolai Hähnle <[email protected]>
commit a8d81b36267366603771431747438d18f32ae2d5 upstream.
An arbitrary amount of time can pass between spin_unlock and fence_wait_any_timeout, so we need to ensure that nobody frees the fences from under us.
A stress test (rapidly starting and killing hundreds of glxgears instances) ran into a deadlock in fence_wait_any_timeout after about an hour, and this race condition appears to be a plausible cause.
v2: agd: rebase on upstream
--- drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c +4 -1
@@ -354,12 +354,15 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_mafor (i =0 , count =0 ; i <AMDGPU_MAX_RINGS ; ++i)if (fences[i]) - fences[count++] = fences[i]; + fences[count++] =fence_get (fences[i]);if (count) {spin_unlock (&sa_manager->wq.lock); t =fence_wait_any_timeout (fences, count, false,MAX_SCHEDULE_TIMEOUT ); +for (i =0 ; i < count; ++i) +fence_put (fences[i]); + r = (t >0 ) ?0 : t;spin_lock (&sa_manager->wq.lock); }else {
Greg Kroah-Hartman
maintainerPATCH 188/342 drm/amdgpu: fix issue with overlapping userptrs
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian König <[email protected]>
commit cc1de6e800c253172334f8774c419dc64401cd2e upstream.
Otherwise we could try to evict overlapping userptr BOs in get_user_pages(), leading to a possible circular locking dependency.
--- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c | 3 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 19 +++++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu.h +2 -0
@@ -2312,6 +2312,8 @@ bool amdgpu_ttm_bo_is_amdgpu_bo(struct tint amdgpu_ttm_tt_set_userptr (struct ttm_tt *ttm,uint64_t addr,uint32_t flags);bool amdgpu_ttm_tt_has_userptr (struct ttm_tt *ttm); +bool amdgpu_ttm_tt_affect_userptr (struct ttm_tt *ttm,unsigned long start, +unsigned long end);bool amdgpu_ttm_tt_is_readonly (struct ttm_tt *ttm);uint32_t amdgpu_ttm_tt_pte_flags (struct amdgpu_device *adev,struct ttm_tt *ttm,struct ttm_mem_reg *mem);
drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c +2 -1
@@ -142,7 +142,8 @@ static void amdgpu_mn_invalidate_range_slist_for_each_entry (bo, &node->bos, mn_list) { -if (!bo->tbo.ttm || bo->tbo.ttm->state != tt_bound) +if (!amdgpu_ttm_tt_affect_userptr (bo->tbo.ttm, start, + end))continue ; r =amdgpu_bo_reserve (bo, true);
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +19 -0
@@ -783,6 +783,25 @@ bool amdgpu_ttm_tt_has_userptr(struct ttreturn !!gtt->userptr; } +bool amdgpu_ttm_tt_affect_userptr (struct ttm_tt *ttm,unsigned long start, +unsigned long end) +{ +struct amdgpu_ttm_tt *gtt = (void *)ttm; +unsigned long size; + +if (gtt ==NULL ) +return false; + +if (gtt->ttm.ttm.state != tt_bound || !gtt->userptr) +return false; + + size = (unsigned long )gtt->ttm.ttm.num_pages *PAGE_SIZE ; +if (gtt->userptr > end || gtt->userptr + size <= start) +return false; + +return true; +} +bool amdgpu_ttm_tt_is_readonly (struct ttm_tt *ttm) {struct amdgpu_ttm_tt *gtt = (void *)ttm;
Greg Kroah-Hartman
maintainerPATCH 189/342 drm/amdgpu: use post-decrement in error handling
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rasmus Villemoes <[email protected]>
commit 09ccbb74b6718ad4d1290de3f5669212c0ac7d4b upstream.
We need to use post-decrement to get the pci_map_page undone also for i==0, and to avoid some very unpleasant behaviour if pci_map_page failed already at i==0.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +1 -1
@@ -712,7 +712,7 @@ static int amdgpu_ttm_tt_populate(struct0 ,PAGE_SIZE , PCI_DMA_BIDIRECTIONAL);if (pci_dma_mapping_error (adev->pdev, gtt->ttm.dma_address[i])) { -while (--i) { +while (i--) {pci_unmap_page (adev->pdev, gtt->ttm.dma_address[i],PAGE_SIZE ,PCI_DMA_BIDIRECTIONAL ); gtt->ttm.dma_address[i] =0 ;
Greg Kroah-Hartman
maintainerPATCH 190/342 drm/amdgpu: Dont hang in amdgpu_flip_work_func on disabled crtc.
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Kleiner <[email protected]>
commit e1d09dc0ccc6c91e3916476f636edb76da1f65bb upstream.
This fixes a regression introduced in Linux 4.4.
This is a port of the same fix for radeon-kms in the patch "drm/radeon: Don't hang in radeon_flip_work_func on disabled crtc. (v2)"
Limit the amount of time amdgpu_flip_work_func can delay programming a page flip, by both limiting the maximum amount of time per wait cycle and the maximum number of wait cycles. Continue the flip if the limit is exceeded, even if that may result in a visual or timing glitch.
This is to prevent a hang of page flips, as reported in fdo bug #93746: Disconnecting a DisplayPort display in parallel to a kms pageflip getting queued can cause the following hang of page flips and thereby an unusable desktop:
1. kms pageflip ioctl() queues pageflip -> queues execution of amdgpu_flip_work_func.
2. Hotunplug of display causes the driver to DPMS OFF the unplugged display. Display engine shuts down, scanout no longer moves, but stays at its resting position at start line of vblank.
3. amdgpu_flip_work_func executes while crtc is off, and due to the non-moving scanout position, the new flip delay code introduced into Linux 4.4 by
commit 8e36f9d33c13 ("drm/amdgpu: Fixup hw vblank counter/ts..") enters an infinite wait loop.
4. After reconnecting the display, the pageflip continues to hang in 3. and the display doesn't update its view of the desktop.
This patch fixes the Linux 4.4 regression from fdo bug #93746
<https://bugs.freedesktop.org/show_bug.cgi?id=93746>
--- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +15 -3
@@ -72,8 +72,8 @@ static void amdgpu_flip_work_func(structstruct drm_crtc *crtc = &amdgpuCrtc->base;unsigned long flags; -unsigned i; -int vpos, hpos, stat, min_udelay; +unsigned i, repcnt =4 ; +int vpos, hpos, stat, min_udelay =0 ;struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];amdgpu_flip_wait_fence (adev, &work->excl);
@@ -96,7 +96,7 @@ static void amdgpu_flip_work_func(struct* In practice this won't execute very often unless on very fast * machines because the time window for this to happen is very small. */ -for (;;) { +while (amdgpuCrtc->enabled && repcnt--) {/* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank * start in hpos, and to the "fudged earlier" vblank start in * vpos.
@@ -114,10 +114,22 @@ static void amdgpu_flip_work_func(struct/* Sleep at least until estimated real start of hw vblank */ spin_unlock_irqrestore (&crtc->dev->event_lock, flags); min_udelay = (-hpos +1 ) *max (vblank->linedur_ns /1000 ,5 ); +if (min_udelay > vblank->framedur_ns /2000 ) { +/* Don't wait ridiculously long - something is wrong */ + repcnt =0 ; +break ; + }usleep_range (min_udelay,2 * min_udelay);spin_lock_irqsave (&crtc->dev->event_lock, flags); }; +if (!repcnt) +DRM_DEBUG_DRIVER ("Delay problem on crtc %d: min_udelay %d, " +"framedur %d, linedur %d, stat %d, vpos %d, " +"hpos %d\n" , work->crtc_id, min_udelay, + vblank->framedur_ns /1000 , + vblank->linedur_ns /1000 , stat, vpos, hpos); +/* do the flip (mmio) */ adev->mode_info.funcs->page_flip (adev, work->crtc_id, work->base);/* set the flip status */
Greg Kroah-Hartman
maintainerPATCH 191/342 drm/amdgpu/pm: adjust display configuration after powerstate
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
commit 8e7cedc6f7fe762ffe6e348502be34b11fa79298 upstream.
set_power_state defaults to no displays, so we need to update the display configuration after setting up the powerstate on the first call. In most cases this is not an issue since ends up getting called multiple times at any given modeset and the proper order is achieved in the display changed handling at the top of the function.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +3 -2
@@ -595,8 +595,6 @@ force:/* update display watermarks based on new power state */ amdgpu_display_bandwidth_update (adev); -/* update displays */ -amdgpu_dpm_display_configuration_changed (adev); adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
@@ -616,6 +614,9 @@ force:amdgpu_dpm_post_set_power_state (adev); +/* update displays */ +amdgpu_dpm_display_configuration_changed (adev); +if (adev->pm.funcs->force_performance_level) {if (adev->pm.dpm.thermal_active) {enum amdgpu_dpm_forced_level level = adev->pm.dpm.forced_level;
Greg Kroah-Hartman
maintainerPATCH 192/342 drm/nouveau/kms: take mode_config mutex in connector hotplug path
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ben Skeggs <[email protected]>
commit 0a882cadbc63fd2da3994af7115b4ada2fcbd638 upstream.
fdo#93634
--- drivers/gpu/drm/nouveau/nouveau_connector.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/gpu/drm/nouveau/nouveau_connector.c +3 -0
@@ -969,10 +969,13 @@ nouveau_connector_hotplug(struct nvif_noNV_DEBUG (drm,"%splugged %s\n" , plugged ?"" :"un" , name); +mutex_lock (&drm->dev->mode_config.mutex);if (plugged)drm_helper_connector_dpms (connector,DRM_MODE_DPMS_ON );else drm_helper_connector_dpms (connector,DRM_MODE_DPMS_OFF ); +mutex_unlock (&drm->dev->mode_config.mutex); +drm_helper_hpd_irq_event (connector->dev); }
Greg Kroah-Hartman
maintainerPATCH 193/342 drm/nouveau/display: Enable vblank irqs after display engine is on again.
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Kleiner <[email protected]>
commit ff683df7bf34f90766a50c7e7454e219aef2710e upstream.
In the display resume path, move the calls to drm_vblank_on() after the point when the display engine is running again.
Since changes were made to drm_update_vblank_count() in Linux 4.4+ to emulate hw vblank counters via vblank timestamping, the function drm_vblank_on() now needs working high precision vblank timestamping and therefore working scanout position queries at time of call. These don't work before the display engine gets restarted, causing miscalculation of vblank counter increments and thereby large forward jumps in vblank count at display resume. These jumps can cause client hangs on resume, or desktop hangs in the case of composited desktops.
Fix this Linux 4.4 regression by reordering calls accordingly.
--- drivers/gpu/drm/nouveau/nouveau_display.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/gpu/drm/nouveau/nouveau_display.c +4 -4
@@ -634,10 +634,6 @@ nouveau_display_resume(struct drm_device nv_crtc->lut.depth =0 ; } -/* Make sure that drm and hw vblank irqs get resumed if needed. */ -for (head =0 ; head < dev->mode_config.num_crtc; head++) -drm_vblank_on (dev, head); -/* This should ensure we don't hit a locking problem when someone * wakes us up via a connector. We should never go into suspend * while the display is on anyways.
@@ -647,6 +643,10 @@ nouveau_display_resume(struct drm_devicedrm_helper_resume_force_mode (dev); +/* Make sure that drm and hw vblank irqs get resumed if needed. */ +for (head =0 ; head < dev->mode_config.num_crtc; head++) +drm_vblank_on (dev, head); +list_for_each_entry (crtc, &dev->mode_config.crtc_list, head) {struct nouveau_crtc *nv_crtc =nouveau_crtc (crtc);
Greg Kroah-Hartman
maintainerPATCH 194/342 drm/nouveau/disp/dp: ensure sink is powered up before attempting link training
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ben Skeggs <[email protected]>
commit 95664e66fad964c3dd7945d6edfb1d0931844664 upstream.
This can happen under some annoying circumstances, and is a quick fix until more substantial changes can be made.
Fixed eDP mode changes on (at least) the Lenovo P50.
--- drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c | 10 ++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h | 6 ++++++ 2 files changed, 16 insertions(+)
drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c +10 -0
@@ -328,6 +328,7 @@ nvkm_dp_train(struct work_struct *w) .outp = outp, }, *dp = &_dp;u32 datarate =0 ; +u8 pwr;int ret;if (!outp->base.info.location && disp->func->sor.magic)
@@ -355,6 +356,15 @@ nvkm_dp_train(struct work_struct *w)/* disable link interrupt handling during link training */ nvkm_notify_put (&outp->irq); +/* ensure sink is not in a low-power state */ +if (!nvkm_rdaux (outp->aux,DPCD_SC00 , &pwr,1 )) { +if ((pwr &DPCD_SC00_SET_POWER ) !=DPCD_SC00_SET_POWER_D0 ) { + pwr &= ~DPCD_SC00_SET_POWER ; + pwr |=DPCD_SC00_SET_POWER_D0 ; +nvkm_wraux (outp->aux,DPCD_SC00 , &pwr,1 ); + } + } +/* enable down-spreading and execute pre-train script from vbios */ dp_link_train_init (dp, outp->dpcd[3 ] &0x01 );
drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h +6 -0
@@ -71,5 +71,11 @@#define DPCD_LS0C_LANE1_POST_CURSOR2 0x0c#define DPCD_LS0C_LANE0_POST_CURSOR2 0x03 +/* DPCD Sink Control */ +#define DPCD_SC00 0x00600 +#define DPCD_SC00_SET_POWER 0x03 +#define DPCD_SC00_SET_POWER_D0 0x01 +#define DPCD_SC00_SET_POWER_D3 0x03 +void nvkm_dp_train (struct work_struct *);#endif
Greg Kroah-Hartman
maintainerPATCH 195/342 drm/nouveau: platform: Fix deferred probe
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thierry Reding <[email protected]>
commit 870571a5698b2e9d0f4d2e5c6245967b582aab45 upstream.
The error cleanup paths aren't quite correct and will crash upon deferred probe.
--- drivers/gpu/drm/nouveau/nouveau_platform.c | 2 - drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c | 40 +++++++++++++++------ 2 files changed, 30 insertions(+), 12 deletions(-)
drivers/gpu/drm/nouveau/nouveau_platform.c +1 -1
@@ -24,7 +24,7 @@static int nouveau_platform_probe (struct platform_device *pdev) {const struct nvkm_device_tegra_func *func; -struct nvkm_device *device; +struct nvkm_device *device =NULL ;struct drm_device *drm;int ret;
drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c +29 -11
@@ -252,32 +252,40 @@ nvkm_device_tegra_new(const struct nvkm_if (!(tdev =kzalloc (sizeof (*tdev),GFP_KERNEL )))return -ENOMEM ; - *pdevice = &tdev->device; + tdev->func = func; tdev->pdev = pdev; tdev->irq =-1 ; tdev->vdd =devm_regulator_get (&pdev->dev,"vdd" ); -if (IS_ERR (tdev->vdd)) -return PTR_ERR (tdev->vdd); +if (IS_ERR (tdev->vdd)) { + ret =PTR_ERR (tdev->vdd); + goto free; + } tdev->rst =devm_reset_control_get (&pdev->dev,"gpu" ); -if (IS_ERR (tdev->rst)) -return PTR_ERR (tdev->rst); +if (IS_ERR (tdev->rst)) { + ret =PTR_ERR (tdev->rst); + goto free; + } tdev->clk =devm_clk_get (&pdev->dev,"gpu" ); -if (IS_ERR (tdev->clk)) -return PTR_ERR (tdev->clk); +if (IS_ERR (tdev->clk)) { + ret =PTR_ERR (tdev->clk); + goto free; + } tdev->clk_pwr =devm_clk_get (&pdev->dev,"pwr" ); -if (IS_ERR (tdev->clk_pwr)) -return PTR_ERR (tdev->clk_pwr); +if (IS_ERR (tdev->clk_pwr)) { + ret =PTR_ERR (tdev->clk_pwr); + goto free; + }nvkm_device_tegra_probe_iommu (tdev); ret =nvkm_device_tegra_power_up (tdev);if (ret) -return ret; + goto remove; tdev->gpu_speedo = tegra_sku_info.gpu_speedo_value; ret = nvkm_device_ctor(&nvkm_device_tegra_func, NULL, &pdev->dev,
@@ -285,9 +293,19 @@ nvkm_device_tegra_new(const struct nvkm_ cfg, dbg, detect, mmio, subdev_mask, &tdev->device);if (ret) -return ret; + goto powerdown; + + *pdevice = &tdev->device;return 0 ; + +powerdown: +nvkm_device_tegra_power_down (tdev); +remove: +nvkm_device_tegra_remove_iommu (tdev); +free: +kfree (tdev); + return ret; }#else int
Greg Kroah-Hartman
maintainerPATCH 196/342 drm/dp/mst: process broadcast messages correctly
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mykola Lysenko <[email protected]>
commit bd9343208704fcc70a5b919f228a7d26ae472727 upstream.
In case broadcast message received in UP request, RAD cannot be used to identify message originator. Message should be parsed, originator should be found by GUID from parsed message.
Also reply with broadcast in case broadcast message received (for now it is always broadcast)
--- drivers/gpu/drm/drm_dp_mst_topology.c | 95 ++++++++++++++++++++++++++++++---- 1 file changed, 84 insertions(+), 11 deletions(-)
drivers/gpu/drm/drm_dp_mst_topology.c +84 -11
@@ -1210,6 +1210,50 @@ out:return mstb; } +static struct drm_dp_mst_branch *get_mst_branch_device_by_guid_helper ( +struct drm_dp_mst_branch *mstb, +uint8_t *guid) +{ +struct drm_dp_mst_branch *found_mstb; +struct drm_dp_mst_port *port; + +list_for_each_entry (port, &mstb->ports, next) { +if (!port->mstb) +continue ; + +if (port->guid_valid &&memcmp (port->guid, guid,16 ) ==0 ) +return port->mstb; + + found_mstb =get_mst_branch_device_by_guid_helper (port->mstb, guid); + +if (found_mstb) +return found_mstb; + } + +return NULL ; +} + +static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device_by_guid ( +struct drm_dp_mst_topology_mgr *mgr, +uint8_t *guid) +{ +struct drm_dp_mst_branch *mstb; + +/* find the port by iterating down */ +mutex_lock (&mgr->lock); + +if (mgr->guid_valid &&memcmp (mgr->guid, guid,16 ) ==0 ) + mstb = mgr->mst_primary; +else + mstb =get_mst_branch_device_by_guid_helper (mgr->mst_primary, guid); + +if (mstb) +kref_get (&mstb->kref); + +mutex_unlock (&mgr->lock); +return mstb; +} +static void drm_dp_check_and_send_link_address (struct drm_dp_mst_topology_mgr *mgr,struct drm_dp_mst_branch *mstb) {
@@ -1320,6 +1364,7 @@ static int set_hdr_from_dst_qlock(struct struct drm_dp_sideband_msg_tx *txmsg) {struct drm_dp_mst_branch *mstb = txmsg->dst; +u8 req_type;/* both msg slots are full */ if (txmsg->seqno ==-1 ) {
@@ -1336,7 +1381,13 @@ static int set_hdr_from_dst_qlock(struct txmsg->seqno =1 ; mstb->tx_slots[txmsg->seqno] = txmsg; } - hdr->broadcast =0 ; + + req_type = txmsg->msg[0 ] &0x7f ; +if (req_type ==DP_CONNECTION_STATUS_NOTIFY || + req_type ==DP_RESOURCE_STATUS_NOTIFY ) + hdr->broadcast =1 ; +else + hdr->broadcast =0 ; hdr->path_msg = txmsg->path_msg; hdr->lct = mstb->lct; hdr->lcr = mstb->lct -1 ;
@@ -2145,28 +2196,50 @@ static int drm_dp_mst_handle_up_req(struif (mgr->up_req_recv.have_eomt) {struct drm_dp_sideband_msg_req_body msg; -struct drm_dp_mst_branch *mstb; +struct drm_dp_mst_branch *mstb =NULL ;bool seqno; - mstb =drm_dp_get_mst_branch_device (mgr, - mgr->up_req_recv.initial_hdr.lct, - mgr->up_req_recv.initial_hdr.rad); -if (!mstb) { -DRM_DEBUG_KMS ("Got MST reply from unknown device %d\n" , mgr->up_req_recv.initial_hdr.lct); -memset (&mgr->up_req_recv,0 ,sizeof (struct drm_dp_sideband_msg_rx )); -return 0 ; + +if (!mgr->up_req_recv.initial_hdr.broadcast) { + mstb =drm_dp_get_mst_branch_device (mgr, + mgr->up_req_recv.initial_hdr.lct, + mgr->up_req_recv.initial_hdr.rad); +if (!mstb) { +DRM_DEBUG_KMS ("Got MST reply from unknown device %d\n" , mgr->up_req_recv.initial_hdr.lct); +memset (&mgr->up_req_recv,0 ,sizeof (struct drm_dp_sideband_msg_rx )); +return 0 ; + } } seqno = mgr->up_req_recv.initial_hdr.seqno;drm_dp_sideband_parse_req (&mgr->up_req_recv, &msg);if (msg.req_type ==DP_CONNECTION_STATUS_NOTIFY ) { -drm_dp_send_up_ack_reply (mgr, mstb, msg.req_type, seqno, false); +drm_dp_send_up_ack_reply (mgr, mgr->mst_primary, msg.req_type, seqno, false); + +if (!mstb) + mstb =drm_dp_get_mst_branch_device_by_guid (mgr, msg.u.conn_stat.guid); + +if (!mstb) { +DRM_DEBUG_KMS ("Got MST reply from unknown device %d\n" , mgr->up_req_recv.initial_hdr.lct); +memset (&mgr->up_req_recv,0 ,sizeof (struct drm_dp_sideband_msg_rx )); +return 0 ; + } +drm_dp_update_port (mstb, &msg.u.conn_stat);DRM_DEBUG_KMS ("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n" , msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type); (*mgr->cbs->hotplug)(mgr); }else if (msg.req_type ==DP_RESOURCE_STATUS_NOTIFY ) { -drm_dp_send_up_ack_reply (mgr, mstb, msg.req_type, seqno, false); +drm_dp_send_up_ack_reply (mgr, mgr->mst_primary, msg.req_type, seqno, false); +if (!mstb) + mstb =drm_dp_get_mst_branch_device_by_guid (mgr, msg.u.resource_stat.guid); + +if (!mstb) { +DRM_DEBUG_KMS ("Got MST reply from unknown device %d\n" , mgr->up_req_recv.initial_hdr.lct); +memset (&mgr->up_req_recv,0 ,sizeof (struct drm_dp_sideband_msg_rx )); +return 0 ; + } +DRM_DEBUG_KMS ("Got RSN: pn: %d avail_pbn %d\n" , msg.u.resource_stat.port_number, msg.u.resource_stat.available_pbn); }
Greg Kroah-Hartman
maintainerPATCH 197/342 drm/dp/mst: always send reply for UP request
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mykola Lysenko <[email protected]>
commit 1f16ee7fa13649f4e55aa48ad31c3eb0722a62d3 upstream.
We should always send reply for UP request in order to make downstream device clean-up resources appropriately.
Issue was that reply for UP request was sent only once.
--- drivers/gpu/drm/drm_dp_mst_topology.c | 30 +++++++++++------------------- include/drm/drm_dp_mst_helper.h | 2 -- 2 files changed, 11 insertions(+), 21 deletions(-)
drivers/gpu/drm/drm_dp_mst_topology.c +11 -19
@@ -1489,26 +1489,18 @@ static void process_single_down_tx_qlock }/* called holding qlock */ -static void process_single_up_tx_qlock (struct drm_dp_mst_topology_mgr *mgr) +static void process_single_up_tx_qlock (struct drm_dp_mst_topology_mgr *mgr, +struct drm_dp_sideband_msg_tx *txmsg) { -struct drm_dp_sideband_msg_tx *txmsg;int ret;/* construct a chunk from the first msg in the tx_msg queue */ -if (list_empty (&mgr->tx_msg_upq)) { - mgr->tx_up_in_progress = false; -return ; - } - - txmsg = list_first_entry(&mgr->tx_msg_upq, struct drm_dp_sideband_msg_tx, next); ret =process_single_tx_qlock (mgr, txmsg, true); -if (ret ==1 ) { -/* up txmsgs aren't put in slots - so free after we send it */ -list_del (&txmsg->next); -kfree (txmsg); - }else if (ret) + +if (ret !=1 )DRM_DEBUG_KMS ("failed to send msg in q %d\n" , ret); - mgr->tx_up_in_progress = true; + + txmsg->dst->tx_slots[txmsg->seqno] =NULL ; } static void drm_dp_queue_down_tx(struct drm_dp_mst_topology_mgr *mgr,
@@ -1895,11 +1887,12 @@ static int drm_dp_send_up_ack_reply(strudrm_dp_encode_up_ack_reply (txmsg, req_type);mutex_lock (&mgr->qlock); -list_add_tail (&txmsg->next, &mgr->tx_msg_upq); -if (!mgr->tx_up_in_progress) { -process_single_up_tx_qlock (mgr); - } + +process_single_up_tx_qlock (mgr, txmsg); +mutex_unlock (&mgr->qlock); + +kfree (txmsg);return 0 ; }
@@ -2809,7 +2802,6 @@ int drm_dp_mst_topology_mgr_init(structmutex_init (&mgr->qlock);mutex_init (&mgr->payload_lock);mutex_init (&mgr->destroy_connector_lock); -INIT_LIST_HEAD (&mgr->tx_msg_upq);INIT_LIST_HEAD (&mgr->tx_msg_downq);INIT_LIST_HEAD (&mgr->destroy_connector_list);INIT_WORK (&mgr->work, drm_dp_mst_link_probe_work);
include/drm/drm_dp_mst_helper.h +0 -2
@@ -450,9 +450,7 @@ struct drm_dp_mst_topology_mgr {the mstb tx_slots and txmsg->state once they are queued */ struct mutex qlock;struct list_head tx_msg_downq; -struct list_head tx_msg_upq;bool tx_down_in_progress; -bool tx_up_in_progress;/* payload info + lock for it */ struct mutex payload_lock;
Greg Kroah-Hartman
maintainerPATCH 198/342 drm/dp/mst: fix in MSTB RAD initialization
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mykola Lysenko <[email protected]>
commit 75af4c8c4c0f60d7ad135419805798f144e9baf9 upstream.
This fix is needed to support more then two branch displays, so RAD address consist at least of 2 elements
--- drivers/gpu/drm/drm_dp_mst_topology.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/gpu/drm/drm_dp_mst_topology.c +6 -6
@@ -973,17 +973,17 @@ static struct drm_dp_mst_port *drm_dp_gestatic u8 drm_dp_calculate_rad (struct drm_dp_mst_port *port,u8 *rad) { -int lct = port->parent->lct; +int parent_lct = port->parent->lct;int shift =4 ; -int idx = lct /2 ; -if (lct >1 ) { -memcpy (rad, port->parent->rad, idx); - shift = (lct %2 ) ?4 :0 ; +int idx = (parent_lct -1 ) /2 ; +if (parent_lct >1 ) { +memcpy (rad, port->parent->rad, idx +1 ); + shift = (parent_lct %2 ) ?4 :0 ; }else rad[0 ] =0 ; rad[idx] |= port->port_num << shift; -return lct +1 ; +return parent_lct +1 ; }/*
Greg Kroah-Hartman
maintainerPATCH 199/342 drm/dp/mst: fix in RAD element access
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mykola Lysenko <[email protected]>
commit 7a11a334aa6af4c65c6a0d81b60c97fc18673532 upstream.
This is needed to receive correct port
number from RAD, so MSTB could be found
--- drivers/gpu/drm/drm_dp_mst_topology.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/drm_dp_mst_topology.c +2 -2
@@ -1039,7 +1039,7 @@ static void build_mst_prop_path(const stsnprintf (proppath, proppath_size,"mst:%d" , mstb->mgr->conn_base_id);for (i =0 ; i < (mstb->lct -1 ); i++) {int shift = (i %2 ) ?0 :4 ; -int port_num = mstb->rad[i /2 ] >> shift; +int port_num = (mstb->rad[i /2 ] >> shift) &0xf ;snprintf (temp,sizeof (temp),"-%d" , port_num);strlcat (proppath, temp, proppath_size); }
@@ -1190,7 +1190,7 @@ static struct drm_dp_mst_branch *drm_dp_for (i =0 ; i < lct -1 ; i++) {int shift = (i %2 ) ?0 :4 ; -int port_num = rad[i /2 ] >> shift; +int port_num = (rad[i /2 ] >> shift) &0xf ;list_for_each_entry (port, &mstb->ports, next) {if (port->port_num == port_num) {
Greg Kroah-Hartman
maintainerPATCH 200/342 drm: Add drm_fixp_from_fraction and drm_fixp2int_ceil
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harry Wentland <[email protected]>
commit 64566b5e767f9bc3161055ca1b443a51afb52aad upstream.
drm_fixp_from_fraction allows us to create a fixed point directly from a fraction, rather than creating fixed point values and dividing later. This avoids overflow of our 64 bit value for large numbers.
drm_fixp2int_ceil allows us to return the ceiling of our fixed point value.
[airlied: squash Jordan's fix] 32-bit-build-fix: Jordan Lazare <[email protected]>
--- include/drm/drm_fixed.h | 53 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-)
include/drm/drm_fixed.h +51 -2
@@ -73,18 +73,28 @@ static inline u32 dfixed_div(fixed20_12#define DRM_FIXED_ONE (1ULL << DRM_FIXED_POINT)#define DRM_FIXED_DECIMAL_MASK (DRM_FIXED_ONE - 1)#define DRM_FIXED_DIGITS_MASK (~DRM_FIXED_DECIMAL_MASK) +#define DRM_FIXED_EPSILON 1LL +#define DRM_FIXED_ALMOST_ONE (DRM_FIXED_ONE - DRM_FIXED_EPSILON)static inline s64 drm_int2fixp (int a) {return ((s64 )a) <<DRM_FIXED_POINT ; } -static inline int drm_fixp2int (int64_t a) +static inline int drm_fixp2int (s64 a) {return ((s64 )a) >>DRM_FIXED_POINT ; } -static inline unsigned drm_fixp_msbset (int64_t a) +static inline int drm_fixp2int_ceil (s64 a) +{ +if (a >0 ) +return drm_fixp2int (a +DRM_FIXED_ALMOST_ONE ); +else +return drm_fixp2int (a -DRM_FIXED_ALMOST_ONE ); +} + +static inline unsigned drm_fixp_msbset (s64 a) {unsigned shift, sign = (a >>63 ) &1 ;
@@ -136,6 +146,45 @@ static inline s64 drm_fixp_div(s64 a, s6return result; } +static inline s64 drm_fixp_from_fraction (s64 a,s64 b) +{ +s64 res; +bool a_neg = a <0 ; +bool b_neg = b <0 ; +u64 a_abs = a_neg ? -a : a; +u64 b_abs = b_neg ? -b : b; +u64 rem; + +/* determine integer part */ +u64 res_abs =div64_u64_rem (a_abs, b_abs, &rem); + +/* determine fractional part */ + { +u32 i =DRM_FIXED_POINT ; + +do { + rem <<=1 ; + res_abs <<=1 ; +if (rem >= b_abs) { + res_abs |=1 ; + rem -= b_abs; + } + }while (--i !=0 ); + } + +/* round up LSB */ + { +u64 summand = (rem <<1 ) >= b_abs; + + res_abs += summand; + } + + res = (s64 ) res_abs; +if (a_neg ^ b_neg) + res = -res; +return res; +} +static inline s64 drm_fixp_exp (s64 x) {s64 tolerance =div64_s64 (DRM_FIXED_ONE ,1000000 );
Greg Kroah-Hartman
maintainerPATCH 201/342 drm/dp/mst: Calculate MST PBN with 31.32 fixed point
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harry Wentland <[email protected]>
commit a9ebb3e46c7ef6112c0da466ef0954673ad36832 upstream.
Our PBN value overflows the 20 bits integer part of the 20.12 fixed point. We need to use 31.32 fixed point to avoid this.
This happens with display clocks larger than 293122 (at 24 bpp), which we see with the Sharp (and similar) 4k tiled displays.
--- drivers/gpu/drm/drm_dp_mst_topology.c | 67 +++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 28 deletions(-)
drivers/gpu/drm/drm_dp_mst_topology.c +39 -28
@@ -2571,32 +2571,31 @@ EXPORT_SYMBOL(drm_dp_check_act_status);*/ int drm_dp_calc_pbn_mode (int clock,int bpp) { -fixed20_12 pix_bw; -fixed20_12 fbpp; -fixed20_12 result; -fixed20_12 margin, tmp; -u32 res; - - pix_bw.full =dfixed_const (clock); - fbpp.full =dfixed_const (bpp); - tmp.full =dfixed_const (8 ); - fbpp.full =dfixed_div (fbpp, tmp); - - result.full =dfixed_mul (pix_bw, fbpp); - margin.full =dfixed_const (54 ); - tmp.full =dfixed_const (64 ); - margin.full =dfixed_div (margin, tmp); - result.full =dfixed_div (result, margin); - - margin.full =dfixed_const (1006 ); - tmp.full =dfixed_const (1000 ); - margin.full =dfixed_div (margin, tmp); - result.full =dfixed_mul (result, margin); - - result.full =dfixed_div (result, tmp); - result.full =dfixed_ceil (result); - res =dfixed_trunc (result); -return res; +u64 kbps; +s64 peak_kbps; +u32 numerator; +u32 denominator; + + kbps = clock * bpp; + +/* +* margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006 +* The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on +* common multiplier to render an integer PBN for all link rate/lane +* counts combinations +* calculate +* peak_kbps *= (1006/1000) +* peak_kbps *= (64/54) +* peak_kbps *= 8 convert to bytes +*/ + + numerator =64 *1006 ; + denominator =54 *8 *1000 *1000 ; + + kbps *= numerator; + peak_kbps =drm_fixp_from_fraction (kbps, denominator); + +return drm_fixp2int_ceil (peak_kbps); }EXPORT_SYMBOL (drm_dp_calc_pbn_mode);
@@ -2604,11 +2603,23 @@ static int test_calc_pbn_mode(void) {int ret; ret =drm_dp_calc_pbn_mode (154000 ,30 ); -if (ret !=689 ) +if (ret !=689 ) { +DRM_ERROR ("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n" , +154000 ,30 ,689 , ret);return -EINVAL ; + } ret =drm_dp_calc_pbn_mode (234000 ,30 ); -if (ret !=1047 ) +if (ret !=1047 ) { +DRM_ERROR ("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n" , +234000 ,30 ,1047 , ret); +return -EINVAL ; + } + ret =drm_dp_calc_pbn_mode (297000 ,24 ); +if (ret !=1063 ) { +DRM_ERROR ("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n" , +297000 ,24 ,1063 , ret);return -EINVAL ; + }return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 202/342 drm/dp/mst: move GUID storage from mgr, port to only mst branch
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hersen Wu <[email protected]>
commit 5e93b8208d3c419b515fb75e2601931c027e12ab upstream.
Previous implementation does not handle case below: boot up one MST branch to DP connector of ASIC. After boot up, hot plug 2nd MST branch to DP output of 1st MST, GUID is not created for 2nd MST branch. When downstream port of 2nd MST branch send upstream request, it fails because 2nd MST branch GUID is not available.
New Implementation: only create GUID for MST branch and save it within Branch.
--- drivers/gpu/drm/drm_dp_mst_topology.c | 64 ++++++++++++++-------------------- include/drm/drm_dp_mst_helper.h | 25 +++++-------- 2 files changed, 38 insertions(+), 51 deletions(-)
drivers/gpu/drm/drm_dp_mst_topology.c +28 -36
@@ -1013,18 +1013,27 @@ static bool drm_dp_port_setup_pdt(structreturn send_link; } -static void drm_dp_check_port_guid (struct drm_dp_mst_branch *mstb, -struct drm_dp_mst_port *port) +static void drm_dp_check_mstb_guid (struct drm_dp_mst_branch *mstb,u8 *guid) {int ret; -if (port->dpcd_rev >=0x12 ) { - port->guid_valid =drm_dp_validate_guid (mstb->mgr, port->guid); -if (!port->guid_valid) { - ret =drm_dp_send_dpcd_write (mstb->mgr, - port, -DP_GUID , -16 , port->guid); - port->guid_valid = true; + +memcpy (mstb->guid, guid,16 ); + +if (!drm_dp_validate_guid (mstb->mgr, mstb->guid)) { +if (mstb->port_parent) { + ret =drm_dp_send_dpcd_write ( + mstb->mgr, + mstb->port_parent, +DP_GUID , +16 , + mstb->guid); + }else { + + ret =drm_dp_dpcd_write ( + mstb->mgr->aux, +DP_GUID , + mstb->guid, +16 ); } } }
@@ -1081,7 +1090,6 @@ static void drm_dp_add_port(struct drm_d port->dpcd_rev = port_msg->dpcd_revision; port->num_sdp_streams = port_msg->num_sdp_streams; port->num_sdp_stream_sinks = port_msg->num_sdp_stream_sinks; -memcpy (port->guid, port_msg->peer_guid,16 );/* manage mstb port lists with mgr lock - take a reference for this list */
@@ -1094,11 +1102,9 @@ static void drm_dp_add_port(struct drm_dif (old_ddps != port->ddps) {if (port->ddps) { -drm_dp_check_port_guid (mstb, port);if (!port->input)drm_dp_send_enum_path_resources (mstb->mgr, mstb, port); }else { - port->guid_valid = false; port->available_pbn =0 ; } }
@@ -1157,10 +1163,8 @@ static void drm_dp_update_port(struct drif (old_ddps != port->ddps) {if (port->ddps) { -drm_dp_check_port_guid (mstb, port); dowork = true; }else { - port->guid_valid = false; port->available_pbn =0 ; } }
@@ -1217,13 +1221,14 @@ static struct drm_dp_mst_branch *get_mststruct drm_dp_mst_branch *found_mstb;struct drm_dp_mst_port *port; +if (memcmp (mstb->guid, guid,16 ) ==0 ) +return mstb; + +list_for_each_entry (port, &mstb->ports, next) {if (!port->mstb)continue ; -if (port->guid_valid &&memcmp (port->guid, guid,16 ) ==0 ) -return port->mstb; - found_mstb =get_mst_branch_device_by_guid_helper (port->mstb, guid);if (found_mstb)
@@ -1242,10 +1247,7 @@ static struct drm_dp_mst_branch *drm_dp_/* find the port by iterating down */ mutex_lock (&mgr->lock); -if (mgr->guid_valid &&memcmp (mgr->guid, guid,16 ) ==0 ) - mstb = mgr->mst_primary; -else - mstb =get_mst_branch_device_by_guid_helper (mgr->mst_primary, guid); + mstb =get_mst_branch_device_by_guid_helper (mgr->mst_primary, guid);if (mstb)kref_get (&mstb->kref);
@@ -1550,6 +1552,9 @@ static void drm_dp_send_link_address(str txmsg->reply.u.link_addr.ports[i].num_sdp_streams, txmsg->reply.u.link_addr.ports[i].num_sdp_stream_sinks); } + +drm_dp_check_mstb_guid (mstb, txmsg->reply.u.link_addr.guid); +for (i =0 ; i < txmsg->reply.u.link_addr.nports; i++) {drm_dp_add_port (mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]); }
@@ -1984,20 +1989,6 @@ int drm_dp_mst_topology_mgr_set_mst(stru goto out_unlock; } - -/* sort out guid */ - ret =drm_dp_dpcd_read (mgr->aux,DP_GUID , mgr->guid,16 ); -if (ret !=16 ) { -DRM_DEBUG_KMS ("failed to read DP GUID %d\n" , ret); - goto out_unlock; - } - - mgr->guid_valid =drm_dp_validate_guid (mgr, mgr->guid); -if (!mgr->guid_valid) { - ret =drm_dp_dpcd_write (mgr->aux,DP_GUID , mgr->guid,16 ); - mgr->guid_valid = true; - } -queue_work (system_long_wq, &mgr->work); ret =0 ;
@@ -2219,6 +2210,7 @@ static int drm_dp_mst_handle_up_req(stru }drm_dp_update_port (mstb, &msg.u.conn_stat); +DRM_DEBUG_KMS ("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n" , msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type); (*mgr->cbs->hotplug)(mgr);
include/drm/drm_dp_mst_helper.h +10 -15
@@ -44,8 +44,6 @@ struct drm_dp_vcpi {/** * struct drm_dp_mst_port - MST port * @kref: reference count for this port. -* @guid_valid: for DP 1.2 devices if we have validated the GUID. -* @guid: guid for DP 1.2 device on this port. * @port_num: port number * @input: if this port is an input port. * @mcs: message capability status - DP 1.2 spec.
@@ -70,10 +68,6 @@ struct drm_dp_vcpi {struct drm_dp_mst_port {struct kref kref; -/* if dpcd 1.2 device is on this port - its GUID info */ -bool guid_valid; -u8 guid[16 ]; -u8 port_num;bool input;bool mcs;
@@ -109,10 +103,12 @@ struct drm_dp_mst_port {* @tx_slots: transmission slots for this device. * @last_seqno: last sequence number used to talk to this. * @link_address_sent: if a link address message has been sent to this device yet. +* @guid: guid for DP 1.2 branch device. port under this branch can be +* identified by port #. * * This structure represents an MST branch device, there is one -* primary branch device at the root, along with any others connected -* to downstream ports +* primary branch device at the root, along with any other branches connected +* to downstream port of parent branches. */ struct drm_dp_mst_branch {struct kref kref;
@@ -131,6 +127,9 @@ struct drm_dp_mst_branch {struct drm_dp_sideband_msg_tx *tx_slots[2 ];int last_seqno;bool link_address_sent; + +/* global unique identifier to identify branch devices */ +u8 guid[16 ]; };
@@ -405,11 +404,9 @@ struct drm_dp_payload {* @conn_base_id: DRM connector ID this mgr is connected to. * @down_rep_recv: msg receiver state for down replies. * @up_req_recv: msg receiver state for up requests. -* @lock: protects mst state, primary, guid, dpcd. +* @lock: protects mst state, primary, dpcd. * @mst_state: if this manager is enabled for an MST capable port. * @mst_primary: pointer to the primary branch device. -* @guid_valid: GUID valid for the primary branch device. -* @guid: GUID for primary port. * @dpcd: cache of DPCD for primary port. * @pbn_div: PBN to slots divisor. *
@@ -431,13 +428,11 @@ struct drm_dp_mst_topology_mgr {struct drm_dp_sideband_msg_rx up_req_recv;/* pointer to info about the initial MST device */ -struct mutex lock;/* protects mst_state + primary + guid + dpcd */ +struct mutex lock;/* protects mst_state + primary + dpcd */ bool mst_state;struct drm_dp_mst_branch *mst_primary; -/* primary MST device GUID */ -bool guid_valid; -u8 guid[16 ]; +u8 dpcd[DP_RECEIVER_CAP_SIZE ];u8 sink_count;int pbn_div;
Greg Kroah-Hartman
maintainerPATCH 203/342 drm/dp/mst: Reverse order of MST enable and clearing VC payload table.
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrey Grodzovsky <[email protected]>
commit c175cd16df272119534058f28cbd5eeac6ff2d24 upstream.
On DELL U3014 if you clear the table before enabling MST it sometimes hangs the receiver.
--- drivers/gpu/drm/drm_dp_mst_topology.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/gpu/drm/drm_dp_mst_topology.c +6 -6
@@ -1976,6 +1976,12 @@ int drm_dp_mst_topology_mgr_set_mst(stru mgr->mst_primary = mstb;kref_get (&mgr->mst_primary->kref); + ret =drm_dp_dpcd_writeb (mgr->aux,DP_MSTM_CTRL , +DP_MST_EN |DP_UP_REQ_EN |DP_UPSTREAM_IS_SRC ); +if (ret <0 ) { + goto out_unlock; + } + {struct drm_dp_payload reset_pay; reset_pay.start_slot =0 ;
@@ -1983,12 +1989,6 @@ int drm_dp_mst_topology_mgr_set_mst(strudrm_dp_dpcd_write_payload (mgr,0 , &reset_pay); } - ret =drm_dp_dpcd_writeb (mgr->aux,DP_MSTM_CTRL , -DP_MST_EN |DP_UP_REQ_EN |DP_UPSTREAM_IS_SRC ); -if (ret <0 ) { - goto out_unlock; - } -queue_work (system_long_wq, &mgr->work); ret =0 ;
Greg Kroah-Hartman
maintainerPATCH 204/342 drm/dp/mst: deallocate payload on port destruction
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mykola Lysenko <[email protected]>
commit 91a25e463130c8e19bdb42f2d827836c7937992e upstream.
This is needed to properly deallocate port payload after downstream branch get unplugged.
In order to do this unplugged MST topology should be preserved, to find first alive port on path to unplugged MST topology, and send payload deallocation request to branch device of found port.
For this mstb and port kref's are used in reversed order to track when port and branch memory could be freed.
Added additional functions to find appropriate mstb as described above.
--- drivers/gpu/drm/drm_dp_mst_topology.c | 91 +++++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 8 deletions(-)
drivers/gpu/drm/drm_dp_mst_topology.c +83 -8
@@ -798,6 +798,18 @@ static struct drm_dp_mst_branch *drm_dp_return mstb; } +static void drm_dp_free_mst_port (struct kref *kref); + +static void drm_dp_free_mst_branch_device (struct kref *kref) +{ + struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref); +if (mstb->port_parent) { +if (list_empty (&mstb->port_parent->next)) +kref_put (&mstb->port_parent->kref, drm_dp_free_mst_port); + } +kfree (mstb); +} +static void drm_dp_destroy_mst_branch_device (struct kref *kref) { struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref);
@@ -805,6 +817,15 @@ static void drm_dp_destroy_mst_branch_debool wake_tx = false;/* +* init kref again to be used by ports to remove mst branch when it is +* not needed anymore +*/ +kref_init (kref); + +if (mstb->port_parent &&list_empty (&mstb->port_parent->next)) +kref_get (&mstb->port_parent->kref); + +/* * destroy all ports - don't need lock * as there are no more references to the mst branch * device at this point.
@@ -830,7 +851,8 @@ static void drm_dp_destroy_mst_branch_deif (wake_tx)wake_up (&mstb->mgr->tx_waitq); -kfree (mstb); + +kref_put (kref, drm_dp_free_mst_branch_device); }static void drm_dp_put_mst_branch_device (struct drm_dp_mst_branch *mstb)
@@ -878,6 +900,7 @@ static void drm_dp_destroy_port(struct k* from an EDID retrieval */ mutex_lock (&mgr->destroy_connector_lock); +kref_get (&port->parent->kref);list_add (&port->next, &mgr->destroy_connector_list);mutex_unlock (&mgr->destroy_connector_lock);schedule_work (&mgr->destroy_connector_work);
@@ -1602,6 +1625,37 @@ static int drm_dp_send_enum_path_resourcreturn 0 ; } +static struct drm_dp_mst_port *drm_dp_get_last_connected_port_to_mstb (struct drm_dp_mst_branch *mstb) +{ +if (!mstb->port_parent) +return NULL ; + +if (mstb->port_parent->mstb != mstb) +return mstb->port_parent; + +return drm_dp_get_last_connected_port_to_mstb (mstb->port_parent->parent); +} + +static struct drm_dp_mst_branch *drm_dp_get_last_connected_port_and_mstb (struct drm_dp_mst_topology_mgr *mgr, +struct drm_dp_mst_branch *mstb, +int *port_num) +{ +struct drm_dp_mst_branch *rmstb =NULL ; +struct drm_dp_mst_port *found_port; +mutex_lock (&mgr->lock); +if (mgr->mst_primary) { + found_port =drm_dp_get_last_connected_port_to_mstb (mstb); + +if (found_port) { + rmstb = found_port->parent; +kref_get (&rmstb->kref); + *port_num = found_port->port_num; + } + } +mutex_unlock (&mgr->lock); +return rmstb; +} + static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, int id,
@@ -1609,11 +1663,16 @@ static int drm_dp_payload_send_msg(struc {struct drm_dp_sideband_msg_tx *txmsg;struct drm_dp_mst_branch *mstb; -int len, ret; +int len, ret, port_num; + port_num = port->port_num; mstb =drm_dp_get_validated_mstb_ref (mgr, port->parent); -if (!mstb) -return -EINVAL ; +if (!mstb) { + mstb =drm_dp_get_last_connected_port_and_mstb (mgr, port->parent, &port_num); + +if (!mstb) +return -EINVAL ; + } txmsg =kzalloc (sizeof (*txmsg),GFP_KERNEL );if (!txmsg) {
@@ -1622,7 +1681,7 @@ static int drm_dp_payload_send_msg(struc } txmsg->dst = mstb; - len =build_allocate_payload (txmsg, port->port_num, + len =build_allocate_payload (txmsg, port_num, id, pbn);
@@ -2752,6 +2811,13 @@ static void drm_dp_tx_work(struct work_smutex_unlock (&mgr->qlock); } +static void drm_dp_free_mst_port (struct kref *kref) +{ + struct drm_dp_mst_port *port = container_of(kref, struct drm_dp_mst_port, kref); +kref_put (&port->parent->kref, drm_dp_free_mst_branch_device); +kfree (port); +} +static void drm_dp_destroy_connector_work (struct work_struct *work) { struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work);
@@ -2772,13 +2838,22 @@ static void drm_dp_destroy_connector_worlist_del (&port->next);mutex_unlock (&mgr->destroy_connector_lock); +kref_init (&port->kref); +INIT_LIST_HEAD (&port->next); + mgr->cbs->destroy_connector (mgr, port->connector);drm_dp_port_teardown_pdt (port, port->pdt); -if (!port->input && port->vcpi.vcpi >0 ) -drm_dp_mst_put_payload_id (mgr, port->vcpi.vcpi); -kfree (port); +if (!port->input && port->vcpi.vcpi >0 ) { +if (mgr->mst_state) { +drm_dp_mst_reset_vcpi_slots (mgr, port); +drm_dp_update_payload_part1 (mgr); +drm_dp_mst_put_payload_id (mgr, port->vcpi.vcpi); + } + } + +kref_put (&port->kref, drm_dp_free_mst_port); send_hotplug = true; }if (send_hotplug)
Greg Kroah-Hartman
maintainerPATCH 205/342 drm/radeon: Fix off-by-one errors in radeon_vm_bo_set_addr
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Kuehling <[email protected]>
commit 42ef344c0994cc453477afdc7a8eadc578ed0257 upstream.
eoffset is sometimes treated as the last address inside the address range, and sometimes as the first address outside the range. This was resulting in errors when a test filled up the entire address space. Make it consistent to always be the last address within the range. Also fixed related errors when checking the VA limit and in radeon_vm_fence_pts.
--- drivers/gpu/drm/radeon/radeon_vm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/gpu/drm/radeon/radeon_vm.c +6 -6
@@ -455,15 +455,15 @@ int radeon_vm_bo_set_addr(struct radeon_if (soffset) {/* make sure object fit at this offset */ - eoffset = soffset + size; + eoffset = soffset + size -1 ;if (soffset >= eoffset) { r = -EINVAL ; goto error_unreserve; } last_pfn = eoffset /RADEON_GPU_PAGE_SIZE ; -if (last_pfn > rdev->vm_manager.max_pfn) { -dev_err (rdev->dev,"va above limit (0x%08X > 0x%08X)\n" , +if (last_pfn >= rdev->vm_manager.max_pfn) { +dev_err (rdev->dev,"va above limit (0x%08X >= 0x%08X)\n" , last_pfn, rdev->vm_manager.max_pfn); r = -EINVAL ; goto error_unreserve;
@@ -478,7 +478,7 @@ int radeon_vm_bo_set_addr(struct radeon_ eoffset /=RADEON_GPU_PAGE_SIZE ;if (soffset || eoffset) {struct interval_tree_node *it; - it =interval_tree_iter_first (&vm->va, soffset, eoffset -1 ); + it =interval_tree_iter_first (&vm->va, soffset, eoffset);if (it && it != &bo_va->it) {struct radeon_bo_va *tmp; tmp = container_of(it, struct radeon_bo_va, it);
@@ -518,7 +518,7 @@ int radeon_vm_bo_set_addr(struct radeon_if (soffset || eoffset) {spin_lock (&vm->status_lock); bo_va->it.start = soffset; - bo_va->it.last = eoffset -1 ; + bo_va->it.last = eoffset;list_add (&bo_va->vm_status, &vm->cleared);spin_unlock (&vm->status_lock);interval_tree_insert (&bo_va->it, &vm->va);
@@ -888,7 +888,7 @@ static void radeon_vm_fence_pts(struct runsigned i; start >>= radeon_vm_block_size; - end >>= radeon_vm_block_size; + end = (end -1 ) >> radeon_vm_block_size;for (i = start; i <= end; ++i)radeon_bo_fence (vm->page_tables[i].bo, fence, true);
Greg Kroah-Hartman
maintainerPATCH 206/342 drm/radeon: call hpd_irq_event on resume
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
commit dbb17a21c131eca94eb31136eee9a7fe5aff00d9 upstream.
Need to call this on resume if displays changes during suspend in order to properly be notified of changes.
--- drivers/gpu/drm/radeon/radeon_device.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/radeon/radeon_device.c +1 -0
@@ -1744,6 +1744,7 @@ int radeon_resume_kms(struct drm_device }drm_kms_helper_poll_enable (dev); +drm_helper_hpd_irq_event (dev);/* set the power state here in case we are a PX system or headless */ if ((rdev->pm.pm_method ==PM_METHOD_DPM ) && rdev->pm.dpm_enabled)
Greg Kroah-Hartman
maintainerPATCH 207/342 drm/radeon: Fix "slow" audio over DP on DCE8+
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Slava Grigorev <[email protected]>
commit ac4a9350abddc51ccb897abf0d9f3fd592b97e0b upstream.
DP audio is derived from the dfs clock.
--- drivers/gpu/drm/radeon/dce6_afmt.c | 16 ++++++++++++++++ drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_atombios.c | 7 +++++++ drivers/gpu/drm/radeon/sid.h | 5 +++++ 4 files changed, 29 insertions(+)
drivers/gpu/drm/radeon/dce6_afmt.c +16 -0
@@ -301,6 +301,22 @@ void dce6_dp_audio_set_dto(struct radeon* is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator */ if (ASIC_IS_DCE8 (rdev)) { +unsigned int div = (RREG32 (DENTIST_DISPCLK_CNTL ) & +DENTIST_DPREFCLK_WDIVIDER_MASK ) >> +DENTIST_DPREFCLK_WDIVIDER_SHIFT ; + +if (div <128 && div >=96 ) + div -=64 ; +else if (div >=64 ) + div = div /2 -16 ; +else if (div >=8 ) + div /=4 ; +else + div =0 ; + +if (div) + clock = rdev->clock.gpupll_outputfreq *10 / div; +WREG32 (DCE8_DCCG_AUDIO_DTO1_PHASE ,24000 );WREG32 (DCE8_DCCG_AUDIO_DTO1_MODULE , clock); }else {
drivers/gpu/drm/radeon/radeon.h +1 -0
@@ -268,6 +268,7 @@ struct radeon_clock {uint32_t current_dispclk;uint32_t dp_extclk;uint32_t max_pixel_clock; +uint32_t gpupll_outputfreq; };/*
drivers/gpu/drm/radeon/radeon_atombios.c +7 -0
@@ -1263,6 +1263,13 @@ bool radeon_atom_get_clock_info(struct d rdev->mode_info.firmware_flags =le16_to_cpu (firmware_info->info.usFirmwareCapability.susAccess); +if (ASIC_IS_DCE8 (rdev)) { + rdev->clock.gpupll_outputfreq = +le32_to_cpu (firmware_info->info_22.ulGPUPLL_OutputFreq); +if (rdev->clock.gpupll_outputfreq ==0 ) + rdev->clock.gpupll_outputfreq =360000 ;/* 3.6 GHz */ + } +return true; }
drivers/gpu/drm/radeon/sid.h +5 -0
@@ -915,6 +915,11 @@#define DCCG_AUDIO_DTO1_PHASE 0x05c0#define DCCG_AUDIO_DTO1_MODULE 0x05c4 +#define DENTIST_DISPCLK_CNTL 0x0490 +# define DENTIST_DPREFCLK_WDIVIDER (x) (((x) & 0x7f) << 24) +# define DENTIST_DPREFCLK_WDIVIDER_MASK (0x7f << 24) +# define DENTIST_DPREFCLK_WDIVIDER_SHIFT 24 +#define AFMT_AUDIO_SRC_CONTROL 0x713c#define AFMT_AUDIO_SRC_SELECT (x) (((x) & 7) << 0)/* AFMT_AUDIO_SRC_SELECT
Greg Kroah-Hartman
maintainerPATCH 208/342 drm/radeon: clean up fujitsu quirks
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
commit 0eb1c3d4084eeb6fb3a703f88d6ce1521f8fcdd1 upstream.
Combine the two quirks.
bug:
https://bugzilla.kernel.org/show_bug.cgi?id=109481
--- drivers/gpu/drm/radeon/radeon_atombios.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-)
drivers/gpu/drm/radeon/radeon_atombios.c +3 -9
@@ -437,7 +437,9 @@ static bool radeon_atom_apply_quirks(str }/* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */ -if (((dev->pdev->device ==0x9802 ) || (dev->pdev->device ==0x9806 )) && +if (((dev->pdev->device ==0x9802 ) || + (dev->pdev->device ==0x9805 ) || + (dev->pdev->device ==0x9806 )) && (dev->pdev->subsystem_vendor ==0x1734 ) && (dev->pdev->subsystem_device ==0x11bd )) {if (*connector_type ==DRM_MODE_CONNECTOR_VGA ) {
@@ -448,14 +450,6 @@ static bool radeon_atom_apply_quirks(str } } -/* Fujitsu D3003-S2 board lists DVI-I as DVI-I and VGA */ -if ((dev->pdev->device ==0x9805 ) && - (dev->pdev->subsystem_vendor ==0x1734 ) && - (dev->pdev->subsystem_device ==0x11bd )) { -if (*connector_type ==DRM_MODE_CONNECTOR_VGA ) -return false; - } -return true; }
Greg Kroah-Hartman
maintainerPATCH 209/342 drm/radeon: properly byte swap vce firmware setup
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
commit cc78eb22885bba64445cde438ba098de0104920f upstream.
Firmware is LE. Need to properly byteswap some of the fields so they are interpreted correctly by the driver on BE systems.
--- drivers/gpu/drm/radeon/vce_v1_0.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/gpu/drm/radeon/vce_v1_0.c +6 -6
@@ -178,12 +178,12 @@ int vce_v1_0_load_fw(struct radeon_devicreturn -EINVAL ; } -for (i =0 ; i < sign->num; ++i) { -if (sign->val[i].chip_id == chip_id) +for (i =0 ; i <le32_to_cpu (sign->num); ++i) { +if (le32_to_cpu (sign->val[i].chip_id) == chip_id)break ; } -if (i == sign->num) +if (i ==le32_to_cpu (sign->num))return -EINVAL ; data += (256 -64 ) /4 ;
@@ -191,18 +191,18 @@ int vce_v1_0_load_fw(struct radeon_devic data[1 ] = sign->val[i].nonce[1 ]; data[2 ] = sign->val[i].nonce[2 ]; data[3 ] = sign->val[i].nonce[3 ]; - data[4 ] = sign->len +64 ; + data[4 ] =cpu_to_le32 (le32_to_cpu (sign->len) +64 );memset (&data[5 ],0 ,44 );memcpy (&data[16 ], &sign[1 ], rdev->vce_fw->size -sizeof (*sign)); - data += data[4 ] /4 ; + data +=le32_to_cpu (data[4 ]) /4 ; data[0 ] = sign->val[i].sigval[0 ]; data[1 ] = sign->val[i].sigval[1 ]; data[2 ] = sign->val[i].sigval[2 ]; data[3 ] = sign->val[i].sigval[3 ]; - rdev->vce.keyselect = sign->val[i].keyselect; + rdev->vce.keyselect =le32_to_cpu (sign->val[i].keyselect);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 210/342 drm/radeon: cleaned up VCO output settings for DP audio
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Slava Grigorev <[email protected]>
commit c9a392eac18409f51a071520cf508c0b4ad990e2 upstream.
This is preparation for the fixes in the following patches.
--- drivers/gpu/drm/radeon/dce6_afmt.c | 2 +- drivers/gpu/drm/radeon/radeon.h | 2 +- drivers/gpu/drm/radeon/radeon_atombios.c | 12 +++++++----- drivers/gpu/drm/radeon/radeon_audio.c | 8 +------- 4 files changed, 10 insertions(+), 14 deletions(-)
drivers/gpu/drm/radeon/dce6_afmt.c +1 -1
@@ -315,7 +315,7 @@ void dce6_dp_audio_set_dto(struct radeon div =0 ;if (div) - clock = rdev->clock.gpupll_outputfreq *10 / div; + clock /= div;WREG32 (DCE8_DCCG_AUDIO_DTO1_PHASE ,24000 );WREG32 (DCE8_DCCG_AUDIO_DTO1_MODULE , clock);
drivers/gpu/drm/radeon/radeon.h +1 -1
@@ -268,7 +268,7 @@ struct radeon_clock {uint32_t current_dispclk;uint32_t dp_extclk;uint32_t max_pixel_clock; -uint32_t gpupll_outputfreq; +uint32_t vco_freq; };/*
drivers/gpu/drm/radeon/radeon_atombios.c +7 -5
@@ -1257,12 +1257,14 @@ bool radeon_atom_get_clock_info(struct d rdev->mode_info.firmware_flags =le16_to_cpu (firmware_info->info.usFirmwareCapability.susAccess); -if (ASIC_IS_DCE8 (rdev)) { - rdev->clock.gpupll_outputfreq = +if (ASIC_IS_DCE8 (rdev)) + rdev->clock.vco_freq =le32_to_cpu (firmware_info->info_22.ulGPUPLL_OutputFreq); -if (rdev->clock.gpupll_outputfreq ==0 ) - rdev->clock.gpupll_outputfreq =360000 ;/* 3.6 GHz */ - } +else + rdev->clock.vco_freq = rdev->clock.current_dispclk; + +if (rdev->clock.vco_freq ==0 ) + rdev->clock.vco_freq =360000 ;/* 3.6 GHz */ return true; }
drivers/gpu/drm/radeon/radeon_audio.c +1 -7
@@ -739,9 +739,6 @@ static void radeon_audio_dp_mode_set(strstruct radeon_encoder *radeon_encoder =to_radeon_encoder (encoder);struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;struct drm_connector *connector =radeon_get_connector_for_encoder (encoder); -struct radeon_connector *radeon_connector =to_radeon_connector (connector); -struct radeon_connector_atom_dig *dig_connector = - radeon_connector->con_priv;if (!dig || !dig->afmt)return ;
@@ -753,10 +750,7 @@ static void radeon_audio_dp_mode_set(strradeon_audio_write_speaker_allocation (encoder);radeon_audio_write_sad_regs (encoder);radeon_audio_write_latency_fields (encoder, mode); -if (rdev->clock.dp_extclk ||ASIC_IS_DCE5 (rdev)) -radeon_audio_set_dto (encoder, rdev->clock.default_dispclk *10 ); -else -radeon_audio_set_dto (encoder, dig_connector->dp_clock); +radeon_audio_set_dto (encoder, rdev->clock.vco_freq *10 );radeon_audio_set_audio_packet (encoder);radeon_audio_select_pin (encoder);
Greg Kroah-Hartman
maintainerPATCH 211/342 drm/radeon: Add a common function for DFS handling
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Slava Grigorev <[email protected]>
commit a64c9dab1c4d05c87ec8a1cb9b48915816462143 upstream.
Move encoding of DFS (digital frequency synthesizer) divider into a separate function and improve calculation precision.
--- drivers/gpu/drm/radeon/dce6_afmt.c | 12 ++---------- drivers/gpu/drm/radeon/radeon_audio.c | 12 ++++++++++++ drivers/gpu/drm/radeon/radeon_audio.h | 1 + 3 files changed, 15 insertions(+), 10 deletions(-)
drivers/gpu/drm/radeon/dce6_afmt.c +2 -10
@@ -304,18 +304,10 @@ void dce6_dp_audio_set_dto(struct radeonunsigned int div = (RREG32 (DENTIST_DISPCLK_CNTL ) &DENTIST_DPREFCLK_WDIVIDER_MASK ) >>DENTIST_DPREFCLK_WDIVIDER_SHIFT ; - -if (div <128 && div >=96 ) - div -=64 ; -else if (div >=64 ) - div = div /2 -16 ; -else if (div >=8 ) - div /=4 ; -else - div =0 ; + div =radeon_audio_decode_dfs_div (div);if (div) - clock /= div; + clock = clock *100 / div;WREG32 (DCE8_DCCG_AUDIO_DTO1_PHASE ,24000 );WREG32 (DCE8_DCCG_AUDIO_DTO1_MODULE , clock);
drivers/gpu/drm/radeon/radeon_audio.c +12 -0
@@ -775,3 +775,15 @@ void radeon_audio_dpms(struct drm_encodeif (radeon_encoder->audio && radeon_encoder->audio->dpms) radeon_encoder->audio->dpms (encoder, mode ==DRM_MODE_DPMS_ON ); } + +unsigned int radeon_audio_decode_dfs_div (unsigned int div) +{ +if (div >=8 && div <64 ) +return (div -8 ) *25 +200 ; +else if (div >=64 && div <96 ) +return (div -64 ) *50 +1600 ; +else if (div >=96 && div <128 ) +return (div -96 ) *100 +3200 ; +else +return 0 ; +}
drivers/gpu/drm/radeon/radeon_audio.h +1 -0
@@ -79,5 +79,6 @@ void radeon_audio_fini(struct radeon_devvoid radeon_audio_mode_set (struct drm_encoder *encoder,struct drm_display_mode *mode);void radeon_audio_dpms (struct drm_encoder *encoder,int mode); +unsigned int radeon_audio_decode_dfs_div (unsigned int div);#endif
Greg Kroah-Hartman
maintainerPATCH 212/342 drm/radeon: fix DP audio support for APU with DCE4.1 display engine
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Slava Grigorev <[email protected]>
commit fe6fc1f132b4300c1f6defd43a5d673eb60a820d upstream.
Properly setup the DFS divider for DP audio for DCE4.1.
--- drivers/gpu/drm/radeon/evergreen_hdmi.c | 10 ++++++++ drivers/gpu/drm/radeon/evergreend.h | 5 ++++ drivers/gpu/drm/radeon/radeon_atombios.c | 37 ++++++++++++++++++++++++------- 3 files changed, 44 insertions(+), 8 deletions(-)
drivers/gpu/drm/radeon/evergreen_hdmi.c +10 -0
@@ -289,6 +289,16 @@ void dce4_dp_audio_set_dto(struct radeon* number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator */ +if (ASIC_IS_DCE41 (rdev)) { +unsigned int div = (RREG32 (DCE41_DENTIST_DISPCLK_CNTL ) & +DENTIST_DPREFCLK_WDIVIDER_MASK ) >> +DENTIST_DPREFCLK_WDIVIDER_SHIFT ; + div =radeon_audio_decode_dfs_div (div); + +if (div) + clock =100 * clock / div; + } +WREG32 (DCCG_AUDIO_DTO1_PHASE ,24000 );WREG32 (DCCG_AUDIO_DTO1_MODULE , clock); }
drivers/gpu/drm/radeon/evergreend.h +5 -0
@@ -511,6 +511,11 @@#define DCCG_AUDIO_DTO1_CNTL 0x05cc# define DCCG_AUDIO_DTO1_USE_512FBR_DTO (1 << 3) +#define DCE41_DENTIST_DISPCLK_CNTL 0x049c +# define DENTIST_DPREFCLK_WDIVIDER (x) (((x) & 0x7f) << 24) +# define DENTIST_DPREFCLK_WDIVIDER_MASK (0x7f << 24) +# define DENTIST_DPREFCLK_WDIVIDER_SHIFT 24 +/* DCE 4.0 AFMT */ #define HDMI_CONTROL 0x7030# define HDMI_KEEPOUT_MODE (1 << 0)
drivers/gpu/drm/radeon/radeon_atombios.c +29 -8
@@ -1106,6 +1106,31 @@ union firmware_info {ATOM_FIRMWARE_INFO_V2_2 info_22; }; +union igp_info { +struct _ATOM_INTEGRATED_SYSTEM_INFO info; +struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; +struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6; +struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7; +struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_8 info_8; +}; + +static void radeon_atombios_get_dentist_vco_freq (struct radeon_device *rdev) +{ +struct radeon_mode_info *mode_info = &rdev->mode_info; +int index =GetIndexIntoMasterTable (DATA , IntegratedSystemInfo); +union igp_info *igp_info; +u8 frev, crev; +u16 data_offset; + +if (atom_parse_data_header (mode_info->atom_context, index,NULL , + &frev, &crev, &data_offset)) { + igp_info = (union igp_info *)(mode_info->atom_context->bios + + data_offset); + rdev->clock.vco_freq = +le32_to_cpu (igp_info->info_6.ulDentistVCOFreq); + } +} +bool radeon_atom_get_clock_info (struct drm_device *dev) {struct radeon_device *rdev = dev->dev_private;
@@ -1260,6 +1285,10 @@ bool radeon_atom_get_clock_info(struct dif (ASIC_IS_DCE8 (rdev)) rdev->clock.vco_freq =le32_to_cpu (firmware_info->info_22.ulGPUPLL_OutputFreq); +else if (ASIC_IS_DCE5 (rdev)) + rdev->clock.vco_freq = rdev->clock.current_dispclk; +else if (ASIC_IS_DCE41 (rdev)) +radeon_atombios_get_dentist_vco_freq (rdev);else rdev->clock.vco_freq = rdev->clock.current_dispclk;
@@ -1272,14 +1301,6 @@ bool radeon_atom_get_clock_info(struct dreturn false; } -union igp_info { -struct _ATOM_INTEGRATED_SYSTEM_INFO info; -struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; -struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6; -struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7; -struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_8 info_8; -}; -bool radeon_atombios_sideport_present (struct radeon_device *rdev) {struct radeon_mode_info *mode_info = &rdev->mode_info;
Greg Kroah-Hartman
maintainerPATCH 213/342 drm: add helper to check for wc memory support
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Airlie <[email protected]>
commit 4b0e4e4af6c6dc8354dcb72182d52c1bc55f12fc upstream.
include/drm/drm_cache.h +9 -0
@@ -35,4 +35,13 @@void drm_clflush_pages (struct page *pages[],unsigned long num_pages); +static inline bool drm_arch_can_wc_memory (void ) +{ +#if defined(CONFIG_PPC ) && !defined(CONFIG_NOT_COHERENT_CACHE ) +return false; +#else +return true; +#endif +} +#endif
Greg Kroah-Hartman
maintainerPATCH 214/342 drm/radeon: mask out WC from BO on unsupported arches
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oded Gabbay <[email protected]>
commit c5244987394648913ae1a03879c58058a2fc2cee upstream.
--- drivers/gpu/drm/radeon/radeon_object.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/gpu/drm/radeon/radeon_object.c +7 -0
@@ -33,6 +33,7 @@#include <linux/slab.h> #include <drm/drmP.h> #include <drm/radeon_drm.h> +#include <drm/drm_cache.h> #include "radeon.h" #include "radeon_trace.h"
@@ -245,6 +246,12 @@ int radeon_bo_create(struct radeon_devicDRM_INFO_ONCE ("Please enable CONFIG_MTRR and CONFIG_X86_PAT for " "better performance thanks to write-combining\n" ); bo->flags &= ~(RADEON_GEM_GTT_WC |RADEON_GEM_GTT_UC ); +#else +/* For architectures that don't support WC memory, +* mask out the WC flag from the BO +*/ +if (!drm_arch_can_wc_memory ()) + bo->flags &= ~RADEON_GEM_GTT_WC ;#endif radeon_ttm_placement_from_domain (bo, domain);
Greg Kroah-Hartman
maintainerPATCH 215/342 drm/radeon: hold reference to fences in radeon_sa_bo_new
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolai Hähnle <[email protected]>
commit f6ff4f67cdf8455d0a4226eeeaf5af17c37d05eb upstream.
An arbitrary amount of time can pass between spin_unlock and radeon_fence_wait_any, so we need to ensure that nobody frees the fences from under us.
Based on the analogous fix for amdgpu.
--- drivers/gpu/drm/radeon/radeon_sa.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/gpu/drm/radeon/radeon_sa.c +5 -0
@@ -349,8 +349,13 @@ int radeon_sa_bo_new(struct radeon_devic/* see if we can skip over some allocations */ }while (radeon_sa_bo_next_hole (sa_manager, fences, tries)); +for (i =0 ; i <RADEON_NUM_RINGS ; ++i) +radeon_fence_ref (fences[i]); +spin_unlock (&sa_manager->wq.lock); r =radeon_fence_wait_any (rdev, fences, false); +for (i =0 ; i <RADEON_NUM_RINGS ; ++i) +radeon_fence_unref (&fences[i]);spin_lock (&sa_manager->wq.lock);/* if we have nothing to wait for block */ if (r == -ENOENT ) {
Greg Kroah-Hartman
maintainerPATCH 216/342 drm: fix missing reference counting decrease
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Insu Yun <[email protected]>
commit dabe19540af9e563d526113bb102e1b9b9fa73f9 upstream.
In drm_dp_mst_allocate_vcpi, it returns true in two paths, but in one path, there is no reference couting decrease.
--- drivers/gpu/drm/drm_dp_mst_topology.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/drm_dp_mst_topology.c +1 -0
@@ -2463,6 +2463,7 @@ bool drm_dp_mst_allocate_vcpi(struct drmDRM_DEBUG_KMS ("payload: vcpi %d already allocated for pbn %d - requested pbn %d\n" , port->vcpi.vcpi, port->vcpi.pbn, pbn);if (pbn == port->vcpi.pbn) { *slots = port->vcpi.num_slots; +drm_dp_put_port (port);return true; } }
Greg Kroah-Hartman
maintainerPATCH 217/342 drm/i915: Restore inhibiting the load of the default context
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chris Wilson <[email protected]>
commit 06ef83a705a98da63797a5a570220b6ca36febd4 upstream.
Following a GPU reset, we may leave the context in a poorly defined state, and reloading from that context will leave the GPU flummoxed. For secondary contexts, this will lead to that context being banned - but currently it is also causing the default context to become banned, leading to turmoil in the shared state.
This is a regression from
commit 6702cf16e0ba8b0129f5aa1b6609d4e9c70bc13b [v4.1]
Author: Ben Widawsky <[email protected]> Date: Mon Mar 16 16:00:58 2015 +0000
drm/i915: Initialize all contexts
which quietly introduced the removal of the MI_RESTORE_INHIBIT on the default context.
v2: Mark the global default context as uninitialized on GPU reset so that the context-local workarounds are reloaded upon re-enabling.
[danvet: This seems to fix a gpu hand on after the first resume, resulting in any future suspend operation failing with -EIO because the gpu seems to be in a funky state. Somehow this patch fixes that.]
--- drivers/gpu/drm/i915/i915_gem_context.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/i915_gem_context.c +5 -1
@@ -340,6 +340,10 @@ void i915_gem_context_reset(struct drm_di915_gem_context_unreference (lctx); ring->last_context =NULL ; } + +/* Force the GPU state to be reinitialised on enabling */ +if (ring->default_context) + ring->default_context->legacy_hw_ctx.initialized = false; } }
@@ -708,7 +712,7 @@ static int do_switch(struct drm_i915_gemif (ret) goto unpin_out; -if (!to->legacy_hw_ctx.initialized) { +if (!to->legacy_hw_ctx.initialized ||i915_gem_context_is_default (to)) { hw_flags |=MI_RESTORE_INHIBIT ;/* NB: If we inhibit the restore, the context is not allowed to * die because future work may end up depending on valid address
Greg Kroah-Hartman
maintainerPATCH 218/342 drm/i915: intel_hpd_init(): Fix suspend/resume reprobing
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lyude <[email protected]>
commit 2dc2f761dea65069485110d24eaa5b0d5d808b07 upstream.
This fixes reprobing of display connectors on resume. After some talking with danvet on IRC, I learned that calling drm_helper_hpd_irq_event() does actually trigger a full reprobe of each connector's status. It turns out this is the actual reason reprobing on resume hasn't been working (this was observed on a T440s):
- We call hpd_init()
- We check each connector for a couple of things before marking connector->polled with DRM_CONNECTOR_POLL_HPD, one of which is an active encoder. Of course, a disconnected port won't have an active encoder, so we don't add the flag to any of the connectors.
- We call drm_helper_hpd_irq_event()
- drm_helper_irq_event() checks each connector for the DRM_CONNECTOR_POLL_HPD flag. The only one that has it is eDP-1, so we skip reprobing each connector except that one.
In addition, we also now avoid setting connector->polled to DRM_CONNECTOR_POLL_HPD for MST connectors, since their reprobing is handled by the mst helpers. This is probably what was originally intended to happen here.
Changes since V1:
* Use the explanation of the issue as the commit message instead
* Change the title of the commit, since this does more then just stop a check for an encoder now
* Add "Fixes" line for the patch that introduced this regression
* Don't enable DRM_CONNECTOR_POLL_HPD for mst connectors
Changes since V2:
* Put patch changelog above Signed-off-by
* Follow Daniel Vetter's suggestion for making the code here a bit more legible
--- drivers/gpu/drm/i915/intel_hotplug.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/intel_hotplug.c +7 -2
@@ -468,9 +468,14 @@ void intel_hpd_init(struct drm_i915_privlist_for_each_entry (connector, &mode_config->connector_list, head) {struct intel_connector *intel_connector =to_intel_connector (connector); connector->polled = intel_connector->polled; -if (connector->encoder && !connector->polled &&I915_HAS_HOTPLUG (dev) && intel_connector->encoder->hpd_pin >HPD_NONE ) - connector->polled =DRM_CONNECTOR_POLL_HPD ; + +/* MST has a dynamic intel_connector->encoder and it's reprobing +* is all handled by the MST helpers. */ if (intel_connector->mst_port) +continue ; + +if (!connector->polled &&I915_HAS_HOTPLUG (dev) && + intel_connector->encoder->hpd_pin >HPD_NONE ) connector->polled =DRM_CONNECTOR_POLL_HPD ; }
Greg Kroah-Hartman
maintainerPATCH 219/342 drm/i915: Init power domains early in driver load
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Vetter <[email protected]>
commit f5949141a21ee16edf1beaf95cbae7e419171ab5 upstream.
Since
commit ac9b8236551d1177fd07b56aef9b565d1864420d
Author: Ville Syrjälä <[email protected]> Date: Fri Nov 27 18:55:26 2015 +0200
drm/i915: Introduce a gmbus power domain
gmbus also needs the power domain infrastructure right from the start, since as soon as we register the i2c controllers someone can use them.
v2: Adjust cleanup paths too (Chris).
v3: Rebase onto -nightly (totally bogus tree I had lying around) and also move dpio init head (Ville).
v4: Ville instead suggested to move gmbus setup later in the sequence, since it's only needed by the modeset code.
v5: Move even close to the actual user, right next to the comment that states where we really need gmbus (and interrupts!).
References: http://www.spinics.net/lists/intel-gfx/msg83075.html
--- drivers/gpu/drm/i915/i915_dma.c | 6 +++--- drivers/gpu/drm/i915/intel_display.c | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-)
drivers/gpu/drm/i915/i915_dma.c +3 -3
@@ -402,6 +402,8 @@ static int i915_load_modeset_init(structif (ret) goto cleanup_gem_stolen; +intel_setup_gmbus (dev); +/* Important: The output setup functions called by modeset_init need * working irqs for e.g. gmbus and dp aux transfers. */ intel_modeset_init (dev);
@@ -451,6 +453,7 @@ cleanup_gem: cleanup_irq:intel_guc_ucode_fini (dev);drm_irq_uninstall (dev); +intel_teardown_gmbus (dev); cleanup_gem_stolen:i915_gem_cleanup_stolen (dev); cleanup_vga_switcheroo:
@@ -1028,7 +1031,6 @@ int i915_driver_load(struct drm_device */* Try to make sure MCHBAR is enabled before poking at it */ intel_setup_mchbar (dev); -intel_setup_gmbus (dev);intel_opregion_setup (dev);i915_gem_load (dev);
@@ -1099,7 +1101,6 @@ out_gem_unload:if (dev->pdev->msi_enabled)pci_disable_msi (dev->pdev); -intel_teardown_gmbus (dev);intel_teardown_mchbar (dev);pm_qos_remove_request (&dev_priv->pm_qos);destroy_workqueue (dev_priv->gpu_error.hangcheck_wq);
@@ -1198,7 +1199,6 @@ int i915_driver_unload(struct drm_deviceintel_csr_ucode_fini (dev); -intel_teardown_gmbus (dev);intel_teardown_mchbar (dev);destroy_workqueue (dev_priv->hotplug.dp_wq);
drivers/gpu/drm/i915/intel_display.c +2 -0
@@ -15565,6 +15565,8 @@ void intel_modeset_cleanup(struct drm_demutex_lock (&dev->struct_mutex);intel_cleanup_gt_powersave (dev);mutex_unlock (&dev->struct_mutex); + +intel_teardown_gmbus (dev); }/*
Greg Kroah-Hartman
maintainerPATCH 220/342 drm/i915: Make sure DC writes are coherent on flush.
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Francisco Jerez <[email protected]>
commit 935a0ff0e1ea62a116848c0a187b13838f7b9cee upstream.
We need to set the DC FLUSH PIPE_CONTROL bit on Gen7+ to guarantee that writes performed via the HDC are visible in memory. Fixes an intermittent failure in a Piglit test that writes to a BO from a shader using GL atomic counters (implemented as HDC untyped atomics) and then expects the memory to read back the same value after mapping it on the CPU.
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=91298
--- drivers/gpu/drm/i915/intel_lrc.c | 1 + drivers/gpu/drm/i915/intel_ringbuffer.c | 2 ++ 2 files changed, 3 insertions(+)
drivers/gpu/drm/i915/intel_lrc.c +1 -0
@@ -1706,6 +1706,7 @@ static int gen8_emit_flush_render(structif (flush_domains) { flags |=PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH ; flags |=PIPE_CONTROL_DEPTH_CACHE_FLUSH ; + flags |=PIPE_CONTROL_DC_FLUSH_ENABLE ; flags |=PIPE_CONTROL_FLUSH_ENABLE ; }
drivers/gpu/drm/i915/intel_ringbuffer.c +2 -0
@@ -347,6 +347,7 @@ gen7_render_ring_flush(struct drm_i915_gif (flush_domains) { flags |=PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH ; flags |=PIPE_CONTROL_DEPTH_CACHE_FLUSH ; + flags |=PIPE_CONTROL_DC_FLUSH_ENABLE ; flags |=PIPE_CONTROL_FLUSH_ENABLE ; }if (invalidate_domains) {
@@ -419,6 +420,7 @@ gen8_render_ring_flush(struct drm_i915_gif (flush_domains) { flags |=PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH ; flags |=PIPE_CONTROL_DEPTH_CACHE_FLUSH ; + flags |=PIPE_CONTROL_DC_FLUSH_ENABLE ; flags |=PIPE_CONTROL_FLUSH_ENABLE ; }if (invalidate_domains) {
Greg Kroah-Hartman
maintainerPATCH 221/342 drm/i915/dp: fall back to 18 bpp when sink capability is unknown
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jani Nikula <[email protected]>
commit 5efd407674068dede403551bea3b0b134c32513a upstream.
Per DP spec, the source device should fall back to 18 bpp, VESA range RGB when the sink capability is unknown. Fix the color depth clamping. 18 bpp color depth should ensure full color range in automatic mode.
The clamping has been HDMI specific since its introduction in
commit 996a2239f93b03c5972923f04b097f65565c5bed
Author: Daniel Vetter <[email protected]> Date: Fri Apr 19 11:24:34 2013 +0200
drm/i915: Disable high-bpc on pre-1.4 EDID screens
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=105331
--- drivers/gpu/drm/i915/intel_display.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-)
drivers/gpu/drm/i915/intel_display.c +15 -5
@@ -11930,11 +11930,21 @@ connected_sink_compute_bpp(struct intel_ pipe_config->pipe_bpp = connector->base.display_info.bpc*3 ; } -/* Clamp bpp to 8 on screens without EDID 1.4 */ -if (connector->base.display_info.bpc ==0 && bpp >24 ) { -DRM_DEBUG_KMS ("clamping display bpp (was %d) to default limit of 24\n" , - bpp); - pipe_config->pipe_bpp =24 ; +/* Clamp bpp to default limit on screens without EDID 1.4 */ +if (connector->base.display_info.bpc ==0 ) { +int type = connector->base.connector_type; +int clamp_bpp =24 ; + +/* Fall back to 18 bpp when DP sink capability is unknown. */ +if (type == DRM_MODE_CONNECTOR_DisplayPort || + type == DRM_MODE_CONNECTOR_eDP) + clamp_bpp =18 ; + +if (bpp > clamp_bpp) { +DRM_DEBUG_KMS ("clamping display bpp (was %d) to default limit of %d\n" , + bpp, clamp_bpp); + pipe_config->pipe_bpp = clamp_bpp; + } } }
Greg Kroah-Hartman
maintainerPATCH 222/342 drm/i915: Dont reject primary plane windowing with color keying enabled on SKL+
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ville Syrjälä <[email protected]>
commit 6f94b6dd006909a5ef6435cc0af557e945240f48 upstream.
On SKL+ plane scaling is mutually exclusive with color keying. The code check for this, but during some refactoring the code got changed to also reject primary plane windowing when color keying is used. There is no such restriction in the hardware, so restore the original logic.
--- drivers/gpu/drm/i915/intel_display.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
drivers/gpu/drm/i915/intel_display.c +6 -5
@@ -13547,11 +13547,12 @@ intel_check_primary_plane(struct drm_plaint max_scale =DRM_PLANE_HELPER_NO_SCALING ;bool can_position = false; -/* use scaler when colorkey is not required */ -if (INTEL_INFO (plane->dev)->gen >=9 && - state->ckey.flags ==I915_SET_COLORKEY_NONE ) { - min_scale =1 ; - max_scale =skl_max_scale (to_intel_crtc (crtc), crtc_state); +if (INTEL_INFO (plane->dev)->gen >=9 ) { +/* use scaler when colorkey is not required */ +if (state->ckey.flags ==I915_SET_COLORKEY_NONE ) { + min_scale =1 ; + max_scale =skl_max_scale (to_intel_crtc (crtc), crtc_state); + } can_position = true; }
Greg Kroah-Hartman
maintainerPATCH 223/342 drm/i915/skl: Dont skip mst encoders in skl_ddi_pll_select()
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lyude <[email protected]>
commit 3d849b02336be103d312c1574d6f7314d5c0bc9f upstream.
We don't actually check for INTEL_OUTPUT_DP_MST at all in here, as a result we skip assigning a DPLL to any DP MST ports, which makes link training fail:
[ 1442.933896] [drm:intel_power_well_enable] enabling DDI D power well [ 1442.933905] [drm:skl_set_power_well] Enabling DDI D power well [ 1442.933957] [drm:intel_mst_pre_enable_dp] 0 [ 1442.935474] [drm:intel_dp_set_signal_levels] Using signal levels 00000000 [ 1442.935477] [drm:intel_dp_set_signal_levels] Using vswing level 0 [ 1442.935480] [drm:intel_dp_set_signal_levels] Using pre-emphasis level 0 [ 1442.936190] [drm:intel_dp_set_signal_levels] Using signal levels 05000000 [ 1442.936193] [drm:intel_dp_set_signal_levels] Using vswing level 1 [ 1442.936195] [drm:intel_dp_set_signal_levels] Using pre-emphasis level 1 [ 1442.936858] [drm:intel_dp_set_signal_levels] Using signal levels 08000000 [ 1442.936862] [drm:intel_dp_set_signal_levels] Using vswing level 2 … [ 1442.998253] [drm:intel_dp_link_training_clock_recovery [i915]] *ERROR* too many full retries, give up [ 1442.998512] [drm:intel_dp_start_link_train [i915]] *ERROR* failed to train DP, aborting
After which the pipe state goes completely out of sync:
[ 70.075596] [drm:check_crtc_state] [CRTC:25] [ 70.075696] [drm:intel_pipe_config_compare [i915]] *ERROR* mismatch in ddi_pll_sel (expected 0x00000000, found 0x00000001) [ 70.075747] [drm:intel_pipe_config_compare [i915]] *ERROR* mismatch in shared_dpll (expected -1, found 0) [ 70.075798] [drm:intel_pipe_config_compare [i915]] *ERROR* mismatch in dpll_hw_state.ctrl1 (expected 0x00000000, found 0x00000021) [ 70.075840] [drm:intel_pipe_config_compare [i915]] *ERROR* mismatch in dpll_hw_state.cfgcr1 (expected 0x00000000, found 0x80400173) [ 70.075884] [drm:intel_pipe_config_compare [i915]] *ERROR* mismatch in dpll_hw_state.cfgcr2 (expected 0x00000000, found 0x000003a5) [ 70.075954] [drm:intel_pipe_config_compare [i915]] *ERROR* mismatch in base.adjusted_mode.crtc_clock (expected 262750, found 72256) [ 70.075999] [drm:intel_pipe_config_compare [i915]] *ERROR* mismatch in port_clock (expected 540000, found 148500)
And if you're especially lucky, it keeps going downhill:
[ 83.309256] Kernel panic - not syncing: Timeout: Not all CPUs entered broadcast exception handler
[ 83.309265]
[ 83.309265] =================================
[ 83.309266] [ INFO: inconsistent lock state ]
[ 83.309267] 4.5.0-rc1Lyude-Test #265 Not tainted
[ 83.309267] ---------------------------------
[ 83.309268] inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage.
[ 83.309270] Xorg/1194 [HC0[1]:SC0[0]:HE1:SE1] takes:
[ 83.309293] (&(&dev_priv->uncore.lock)->rlock){?.-...}, at: [<ffffffffa02a6073>] gen9_write32+0x63/0x400 [i915]
[ 83.309293] {IN-HARDIRQ-W} state was registered at:
[ 83.309297] [<ffffffff810e84f4>] __lock_acquire+0x9c4/0x1d00
[ 83.309299] [<ffffffff810ea1be>] lock_acquire+0xce/0x1c0
[ 83.309302] [<ffffffff8177d936>] _raw_spin_lock_irqsave+0x56/0x90
[ 83.309321] [<ffffffffa02a5492>] gen9_read32+0x52/0x3d0 [i915]
[ 83.309332] [<ffffffffa024beea>] gen8_irq_handler+0x27a/0x6a0 [i915]
[ 83.309337] [<ffffffff810fdbc1>] handle_irq_event_percpu+0x41/0x300
[ 83.309339] [<ffffffff810fdeb9>] handle_irq_event+0x39/0x60
[ 83.309341] [<ffffffff811010b4>] handle_edge_irq+0x74/0x130
[ 83.309344] [<ffffffff81009073>] handle_irq+0x73/0x120
[ 83.309346] [<ffffffff817805f1>] do_IRQ+0x61/0x120
[ 83.309348] [<ffffffff8177e6d6>] ret_from_intr+0x0/0x20
[ 83.309351] [<ffffffff815f5105>] cpuidle_enter_state+0x105/0x330
[ 83.309353] [<ffffffff815f5367>] cpuidle_enter+0x17/0x20
[ 83.309356] [<ffffffff810dbe1a>] call_cpuidle+0x2a/0x50
[ 83.309358] [<ffffffff810dc1dd>] cpu_startup_entry+0x26d/0x3a0
[ 83.309360] [<ffffffff817701da>] rest_init+0x13a/0x140
[ 83.309363] [<ffffffff81f2af8e>] start_kernel+0x475/0x482
[ 83.309365] [<ffffffff81f2a315>] x86_64_start_reservations+0x2a/0x2c
[ 83.309367] [<ffffffff81f2a452>] x86_64_start_kernel+0x13b/0x14a--- drivers/gpu/drm/i915/intel_ddi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/intel_ddi.c +2 -1
@@ -1582,7 +1582,8 @@ skl_ddi_pll_select(struct intel_crtc *inDPLL_CFGCR2_KDIV (wrpll_params.kdiv) |DPLL_CFGCR2_PDIV (wrpll_params.pdiv) | wrpll_params.central_freq; - }else if (intel_encoder->type ==INTEL_OUTPUT_DISPLAYPORT ) { + }else if (intel_encoder->type ==INTEL_OUTPUT_DISPLAYPORT || + intel_encoder->type ==INTEL_OUTPUT_DP_MST ) {switch (crtc_state->port_clock /2 ) {case 81000 : ctrl1 |=DPLL_CTRL1_LINK_RATE (DPLL_CTRL1_LINK_RATE_810 ,0 );
Greg Kroah-Hartman
maintainerPATCH 224/342 drm/i915/dsi: defend gpio table against out of bounds access
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jani Nikula <[email protected]>
commit 4db3a2448ec8902310acb78de39b6227a9a56ac8 upstream.
Do not blindly trust the VBT data used for indexing.
--- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +6 -0
@@ -209,6 +209,11 @@ static const u8 *mipi_exec_gpio(struct i/* pull up/down */ action = *data++; +if (gpio >=ARRAY_SIZE (gtable)) { +DRM_DEBUG_KMS ("unknown gpio %u\n" , gpio); + goto out; + } + function = gtable[gpio].function_reg; pad = gtable[gpio].pad_reg;
@@ -226,6 +231,7 @@ static const u8 *mipi_exec_gpio(struct ivlv_gpio_nc_write (dev_priv, pad, val);mutex_unlock (&dev_priv->sb_lock); +out:return data; }
Greg Kroah-Hartman
maintainerPATCH 225/342 drm/i915/dsi: dont pass arbitrary data to sideband
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jani Nikula <[email protected]>
commit 26f6f2d301c1fb46acb1138ee155125815239b0d upstream.
Since sequence block v2 the second byte contains flags other than just pull up/down. Don't pass arbitrary data to the sideband interface.
The rest may or may not work for sequence block v2, but there should be no harm done.
--- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +1 -1
@@ -207,7 +207,7 @@ static const u8 *mipi_exec_gpio(struct i gpio = *data++;/* pull up/down */ - action = *data++; + action = *data++ &1 ;if (gpio >=ARRAY_SIZE (gtable)) {DRM_DEBUG_KMS ("unknown gpio %u\n" , gpio);
Greg Kroah-Hartman
maintainerPATCH 226/342 drm/i915: fix error path in intel_setup_gmbus()
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rasmus Villemoes <[email protected]>
commit ed3f9fd1e865975ceefdb2a43b453e090b1fd787 upstream.
This fails to undo the setup for pin==0; moreover, something interesting happens if the setup failed already at pin==0.
--- drivers/gpu/drm/i915/intel_i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/i915/intel_i2c.c +1 -1
@@ -675,7 +675,7 @@ int intel_setup_gmbus(struct drm_devicereturn 0 ; err: -while (--pin) { +while (pin--) {if (!intel_gmbus_is_valid_pin (dev_priv, pin))continue ;
Greg Kroah-Hartman
maintainerPATCH 227/342 drm/qxl: use kmalloc_array to alloc reloc_info in qxl_process_single_command
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gerd Hoffmann <[email protected]>
commit 34855706c30d52b0a744da44348b5d1cc39fbe51 upstream.
This avoids integer overflows on 32bit machines when calculating reloc_info size, as reported by Alan Cox.
--- drivers/gpu/drm/qxl/qxl_ioctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/qxl/qxl_ioctl.c +2 -1
@@ -168,7 +168,8 @@ static int qxl_process_single_command(st cmd->command_size))return -EFAULT ; - reloc_info =kmalloc (sizeof (struct qxl_reloc_info ) * cmd->relocs_num,GFP_KERNEL ); + reloc_info =kmalloc_array (cmd->relocs_num, +sizeof (struct qxl_reloc_info ),GFP_KERNEL );if (!reloc_info)return -ENOMEM ;
Greg Kroah-Hartman
maintainerPATCH 228/342 drm/radeon: use post-decrement in error handling
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rasmus Villemoes <[email protected]>
commit bc3f5d8c4ca01555820617eb3b6c0857e4df710d upstream.
We need to use post-decrement to get the pci_map_page undone also for i==0, and to avoid some very unpleasant behaviour if pci_map_page failed already at i==0.
--- drivers/gpu/drm/radeon/radeon_ttm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/radeon/radeon_ttm.c +1 -1
@@ -758,7 +758,7 @@ static int radeon_ttm_tt_populate(struct0 ,PAGE_SIZE , PCI_DMA_BIDIRECTIONAL);if (pci_dma_mapping_error (rdev->pdev, gtt->ttm.dma_address[i])) { -while (--i) { +while (i--) {pci_unmap_page (rdev->pdev, gtt->ttm.dma_address[i],PAGE_SIZE ,PCI_DMA_BIDIRECTIONAL ); gtt->ttm.dma_address[i] =0 ;
Greg Kroah-Hartman
maintainerPATCH 229/342 drm: No-Op redundant calls to drm_vblank_off() (v2)
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Kleiner <[email protected]>
commit e8235891b33799d597ff4ab5e45afe173a65da30 upstream.
Otherwise if a kms driver calls into drm_vblank_off() more than once before calling drm_vblank_on() again, the redundant calls to vblank_disable_and_save() will call drm_update_vblank_count() while hw vblank counters and vblank timestamping are in a undefined state during modesets, dpms off etc.
At least with the legacy drm helpers it is not unusual to get multiple calls to drm_vblank_off and drm_vblank_on, e.g., half a dozen calls to drm_vblank_off and two calls to drm_vblank_on were observed on radeon-kms during dpms-off -> dpms-on transition.
We don't no-op calls from atomic modesetting drivers, as they should do a proper job of tracking hw state.
Fixes large jumps of the software maintained vblank counter due to the hardware vblank counter resetting to zero during dpms off or modeset, e.g., if radeon-kms is modified to use drm_vblank_off/on instead of drm_vblank_pre/post_modeset().
This fixes a regression caused by the changes made to drm_update_vblank_count() in Linux 4.4.
v2: Don't no-op on atomic modesetting drivers, per suggestion
of Daniel Vetter.
--- drivers/gpu/drm/drm_irq.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/gpu/drm/drm_irq.c +10 -1
@@ -1313,7 +1313,13 @@ void drm_vblank_off(struct drm_device *dspin_lock_irqsave (&dev->event_lock, irqflags);spin_lock (&dev->vbl_lock); -vblank_disable_and_save (dev, pipe); +DRM_DEBUG_VBL ("crtc %d, vblank enabled %d, inmodeset %d\n" , + pipe, vblank->enabled, vblank->inmodeset); + +/* Avoid redundant vblank disables without previous drm_vblank_on(). */ +if (drm_core_check_feature (dev,DRIVER_ATOMIC ) || !vblank->inmodeset) +vblank_disable_and_save (dev, pipe); +wake_up (&vblank->queue);/*
@@ -1415,6 +1421,9 @@ void drm_vblank_on(struct drm_device *dereturn ;spin_lock_irqsave (&dev->vbl_lock, irqflags); +DRM_DEBUG_VBL ("crtc %d, vblank enabled %d, inmodeset %d\n" , + pipe, vblank->enabled, vblank->inmodeset); +/* Drop our private "prevent drm_vblank_get" refcount */ if (vblank->inmodeset) {atomic_dec (&vblank->refcount);
Greg Kroah-Hartman
maintainerPATCH 230/342 drm: Prevent vblank counter bumps > 1 with active vblank clients. (v2)
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Kleiner <[email protected]>
commit 99b8e71597fadd6b2ac85e6e10f221f79dd9c1c1 upstream.
This fixes a regression introduced by the new drm_update_vblank_count() implementation in Linux 4.4:
Restrict the bump of the software vblank counter in drm_update_vblank_count() to a safe maximum value of +1 whenever there is the possibility that concurrent readers of vblank timestamps could be active at the moment, as the current implementation of the timestamp caching and updating is not safe against concurrent readers for calls to store_vblank() with a bump of anything but +1. A bump != 1 would very likely return corrupted timestamps to userspace, because the same slot in the cache could be concurrently written by store_vblank() and read by one of those readers in a non-atomic fashion and without the read-retry logic detecting this collision.
Concurrent readers can exist while drm_update_vblank_count() is called from the drm_vblank_off() or drm_vblank_on() functions or other non-vblank- irq callers. However, all those calls are happening with the vbl_lock locked thereby preventing a drm_vblank_get(), so the vblank refcount can't increase while drm_update_vblank_count() is executing. Therefore a zero vblank refcount during execution of that function signals that is safe for arbitrary counter bumps if called from outside vblank irq, whereas a non-zero count is not safe.
Whenever the function is called from vblank irq, we have to assume concurrent readers could show up any time during its execution, even if the refcount is currently zero, as vblank irqs are usually only enabled due to the presence of readers, and because when it is called from vblank irq it can't hold the vbl_lock to protect it from sudden bumps in vblank refcount. Therefore also restrict bumps to +1 when the function is called from vblank irq.
Such bumps of more than +1 can happen at other times than reenabling vblank irqs, e.g., when regular vblank interrupts get delayed by more than 1 frame due to long held locks, long irq off periods, realtime preemption on RT kernels, or system management interrupts.
A better solution would be to rewrite the timestamp caching to use full seqlocks to allow concurrent writes and reads for arbitrary vblank counter increments.
v2: Add code comment that this is essentially a hack and should
be replaced by a full seqlock implementation for caching of timestamps.
--- drivers/gpu/drm/drm_irq.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
drivers/gpu/drm/drm_irq.c +43 -0
@@ -221,6 +221,49 @@ static void drm_update_vblank_count(stru diff = (flags &DRM_CALLED_FROM_VBLIRQ ) !=0 ; } +/* +* FIMXE: Need to replace this hack with proper seqlocks. +* +* Restrict the bump of the software vblank counter to a safe maximum +* value of +1 whenever there is the possibility that concurrent readers +* of vblank timestamps could be active at the moment, as the current +* implementation of the timestamp caching and updating is not safe +* against concurrent readers for calls to store_vblank() with a bump +* of anything but +1. A bump != 1 would very likely return corrupted +* timestamps to userspace, because the same slot in the cache could +* be concurrently written by store_vblank() and read by one of those +* readers without the read-retry logic detecting the collision. +* +* Concurrent readers can exist when we are called from the +* drm_vblank_off() or drm_vblank_on() functions and other non-vblank- +* irq callers. However, all those calls to us are happening with the +* vbl_lock locked to prevent drm_vblank_get(), so the vblank refcount +* can't increase while we are executing. Therefore a zero refcount at +* this point is safe for arbitrary counter bumps if we are called +* outside vblank irq, a non-zero count is not 100% safe. Unfortunately +* we must also accept a refcount of 1, as whenever we are called from +* drm_vblank_get() -> drm_vblank_enable() the refcount will be 1 and +* we must let that one pass through in order to not lose vblank counts +* during vblank irq off - which would completely defeat the whole +* point of this routine. +* +* Whenever we are called from vblank irq, we have to assume concurrent +* readers exist or can show up any time during our execution, even if +* the refcount is currently zero, as vblank irqs are usually only +* enabled due to the presence of readers, and because when we are called +* from vblank irq we can't hold the vbl_lock to protect us from sudden +* bumps in vblank refcount. Therefore also restrict bumps to +1 when +* called from vblank irq. +*/ +if ((diff >1 ) && (atomic_read (&vblank->refcount) >1 || + (flags &DRM_CALLED_FROM_VBLIRQ ))) { +DRM_DEBUG_VBL ("clamping vblank bump to 1 on crtc %u: diffr=%u " +"refcount %u, vblirq %u\n" , pipe, diff, +atomic_read (&vblank->refcount), + (flags &DRM_CALLED_FROM_VBLIRQ ) !=0 ); + diff =1 ; + } +DRM_DEBUG_VBL ("updating vblank count on crtc %u:" " current=%u, diff=%u, hw=%u hw_last=%u\n" , pipe, vblank->count, diff, cur_vblank, vblank->last);
Greg Kroah-Hartman
maintainerPATCH 231/342 drm: Fix drm_vblank_pre/post_modeset regression from Linux 4.4
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Kleiner <[email protected]>
commit c61934ed9a0e3911a9935df26858726a7ec35ec0 upstream.
Changes to drm_update_vblank_count() in Linux 4.4 broke the behaviour of the pre/post modeset functions as the new update code doesn't deal with hw vblank counter resets inbetween calls to drm_vblank_pre_modeset an drm_vblank_post_modeset, as it should.
This causes mistreatment of such hw counter resets as counter wraparound, and thereby large forward jumps of the software vblank counter which in turn cause vblank event dispatching and vblank waits to fail/hang --> userspace clients hang.
This symptom was reported on radeon-kms to cause a infinite hang of KDE Plasma 5 shell's login procedure, preventing users from logging in.
Fix this by detecting when drm_update_vblank_count() is called inside a pre->post modeset interval. If so, clamp valid vblank increments to the safe values 0 and 1, pretty much restoring the update behavior of the old update code of Linux 4.3 and earlier. Also reset the last recorded hw vblank count at call to drm_vblank_post_modeset() to be safe against hw that after modesetting, dpms on etc. only fires its first vblank irq after drm_vblank_post_modeset() was already called.
--- drivers/gpu/drm/drm_irq.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
drivers/gpu/drm/drm_irq.c +16 -0
@@ -222,6 +222,21 @@ static void drm_update_vblank_count(stru }/* +* Within a drm_vblank_pre_modeset - drm_vblank_post_modeset +* interval? If so then vblank irqs keep running and it will likely +* happen that the hardware vblank counter is not trustworthy as it +* might reset at some point in that interval and vblank timestamps +* are not trustworthy either in that interval. Iow. this can result +* in a bogus diff >> 1 which must be avoided as it would cause +* random large forward jumps of the software vblank counter. +*/ +if (diff >1 && (vblank->inmodeset &0x2 )) { +DRM_DEBUG_VBL ("clamping vblank bump to 1 on crtc %u: diffr=%u" +" due to pre-modeset.\n" , pipe, diff); + diff =1 ; + } + +/* * FIMXE: Need to replace this hack with proper seqlocks. * * Restrict the bump of the software vblank counter to a safe maximum
@@ -1575,6 +1590,7 @@ void drm_vblank_post_modeset(struct drm_if (vblank->inmodeset) {spin_lock_irqsave (&dev->vbl_lock, irqflags); dev->vblank_disable_allowed = true; +drm_reset_vblank_timestamp (dev, pipe);spin_unlock_irqrestore (&dev->vbl_lock, irqflags);if (vblank->inmodeset &0x2 )
Greg Kroah-Hartman
maintainerPATCH 232/342 drm: Fix treatment of drm_vblank_offdelay in drm_vblank_on() (v2)
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Kleiner <[email protected]>
commit bb74fc1bf3072bd3ab4ed5f43afd287a63baf2d7 upstream.
drm_vblank_offdelay can have three different types of values:
< 0 is to be always treated the same as dev->vblank_disable_immediate = 0 is to be treated as "never disable vblanks"
Quoted 1 line
0 is to be treated as disable immediate if kms driver wants it
that way via dev->vblank_disable_immediate. Otherwise it is a disable timeout in msecs.
This got broken in Linux 3.18+ for the implementation of drm_vblank_on. If the user specified a value of zero which should always reenable vblank irqs in this function, a kms driver could override the users choice by setting vblank_disable_immediate to true. This patch fixes the regression and keeps the user in control.
v2: Only reenable vblank if there are clients left or the user
requested to "never disable vblanks" via offdelay 0. Enabling vblanks even in the "delayed disable" case (offdelay > 0) was specifically added by Ville in commit cd19e52aee922 ("drm: Kick start vblank interrupts at drm_vblank_on()"), but after discussion it turns out that this was done by accident.
Citing Ville: "I think it just ended up as a mess due to changing some of the semantics of offdelay<0 vs. offdelay==0 vs. disable_immediate during the review of the series. So yeah, given how drm_vblank_put() works now, I'd just make this check for offdelay==0."
--- drivers/gpu/drm/drm_irq.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/gpu/drm/drm_irq.c +1 -2
@@ -1494,8 +1494,7 @@ void drm_vblank_on(struct drm_device *de* re-enable interrupts if there are users left, or the * user wishes vblank interrupts to be enabled all the time. */ -if (atomic_read (&vblank->refcount) !=0 || - (!dev->vblank_disable_immediate && drm_vblank_offdelay ==0 )) +if (atomic_read (&vblank->refcount) !=0 || drm_vblank_offdelay ==0 )WARN_ON (drm_vblank_enable (dev, pipe));spin_unlock_irqrestore (&dev->vbl_lock, irqflags); }
Greg Kroah-Hartman
maintainerPATCH 233/342 drm/radeon: Dont hang in radeon_flip_work_func on disabled crtc. (v2)
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Kleiner <[email protected]>
commit 2b8341b3f917c108b47f6a8a771a40d226c57883 upstream.
This fixes a regression introduced in Linux 4.4.
Limit the amount of time radeon_flip_work_func can delay programming a page flip, by both limiting the maximum amount of time per wait cycle and the maximum number of wait cycles. Continue the flip if the limit is exceeded, even if that may result in a visual or timing glitch.
This is to prevent a hang of page flips, as reported in fdo bug #93746: Disconnecting a DisplayPort display in parallel to a kms pageflip getting queued can cause the following hang of page flips and thereby an unusable desktop:
1. kms pageflip ioctl() queues pageflip -> queues execution of radeon_flip_work_func.
2. Hotunplug of display causes the driver to DPMS OFF the unplugged display. Display engine shuts down, scanout no longer moves, but stays at its resting position at start line of vblank.
3. radeon_flip_work_func executes while crtc is off, and due to the non-moving scanout position, the new flip delay code introduced into Linux 4.4 by
commit 5b5561b3660d ("drm/radeon: Fixup hw vblank counter/ts..") enters an infinite wait loop.
4. After reconnecting the display, the pageflip continues to hang in 3. and the display doesn't update its view of the desktop.
This patch fixes the Linux 4.4 regression from fdo bug #93746
<https://bugs.freedesktop.org/show_bug.cgi?id=93746>
v2: Skip wait immediately if !radeon_crtc->enabled, as
suggested by Michel.
--- drivers/gpu/drm/radeon/radeon_display.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
drivers/gpu/drm/radeon/radeon_display.c +15 -2
@@ -403,7 +403,8 @@ static void radeon_flip_work_func(structstruct drm_crtc *crtc = &radeon_crtc->base;unsigned long flags;int r; -int vpos, hpos, stat, min_udelay; +int vpos, hpos, stat, min_udelay =0 ; +unsigned repcnt =4 ;struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];down_read (&rdev->exclusive_lock);
@@ -454,7 +455,7 @@ static void radeon_flip_work_func(struct* In practice this won't execute very often unless on very fast * machines because the time window for this to happen is very small. */ -for (;;) { +while (radeon_crtc->enabled && repcnt--) {/* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank * start in hpos, and to the "fudged earlier" vblank start in * vpos.
@@ -472,10 +473,22 @@ static void radeon_flip_work_func(struct/* Sleep at least until estimated real start of hw vblank */ spin_unlock_irqrestore (&crtc->dev->event_lock, flags); min_udelay = (-hpos +1 ) *max (vblank->linedur_ns /1000 ,5 ); +if (min_udelay > vblank->framedur_ns /2000 ) { +/* Don't wait ridiculously long - something is wrong */ + repcnt =0 ; +break ; + }usleep_range (min_udelay,2 * min_udelay);spin_lock_irqsave (&crtc->dev->event_lock, flags); }; +if (!repcnt) +DRM_DEBUG_DRIVER ("Delay problem on crtc %d: min_udelay %d, " +"framedur %d, linedur %d, stat %d, vpos %d, " +"hpos %d\n" , work->crtc_id, min_udelay, + vblank->framedur_ns /1000 , + vblank->linedur_ns /1000 , stat, vpos, hpos); +/* do the flip (mmio) */ radeon_page_flip (rdev, radeon_crtc->crtc_id, work->base);
Greg Kroah-Hartman
maintainerPATCH 234/342 drm/radeon/pm: adjust display configuration after powerstate
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
commit 39d4275058baf53e89203407bf3841ff2c74fa32 upstream.
set_power_state defaults to no displays, so we need to update the display configuration after setting up the powerstate on the first call. In most cases this is not an issue since ends up getting called multiple times at any given modeset and the proper order is achieved in the display changed handling at the top of the function.
--- drivers/gpu/drm/radeon/radeon_pm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/gpu/drm/radeon/radeon_pm.c +3 -2
@@ -1075,8 +1075,6 @@ force:/* update display watermarks based on new power state */ radeon_bandwidth_update (rdev); -/* update displays */ -radeon_dpm_display_configuration_changed (rdev); rdev->pm.dpm.current_active_crtcs = rdev->pm.dpm.new_active_crtcs; rdev->pm.dpm.current_active_crtc_count = rdev->pm.dpm.new_active_crtc_count;
@@ -1097,6 +1095,9 @@ force:radeon_dpm_post_set_power_state (rdev); +/* update displays */ +radeon_dpm_display_configuration_changed (rdev); +if (rdev->asic->dpm.force_performance_level) {if (rdev->pm.dpm.thermal_active) {enum radeon_dpm_forced_level level = rdev->pm.dpm.forced_level;
Greg Kroah-Hartman
maintainerPATCH 235/342 make sure that freeing shmem fast symlinks is RCU-delayed
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
commit 3ed47db34f480df7caf44436e3e63e555351ae9a upstream.
--- include/linux/shmem_fs.h | 5 +---- mm/shmem.c | 9 ++++----- 2 files changed, 5 insertions(+), 9 deletions(-)
include/linux/shmem_fs.h +1 -4
@@ -15,10 +15,7 @@ struct shmem_inode_info {unsigned int seals;/* shmem seals */ unsigned long flags;unsigned long alloced;/* data pages alloced to file */ -union { -unsigned long swapped;/* subtotal assigned to swap */ -char *symlink;/* unswappable short symlink */ - }; +unsigned long swapped;/* subtotal assigned to swap */ struct shared_policy policy;/* NUMA memory alloc policy */ struct list_head swaplist;/* chain of maybes on swap */ struct simple_xattrs xattrs;/* list of xattrs */
mm/shmem.c +4 -5
@@ -620,8 +620,7 @@ static void shmem_evict_inode(struct inolist_del_init (&info->swaplist);mutex_unlock (&shmem_swaplist_mutex); } - }else -kfree (info->symlink); + }simple_xattrs_free (&info->xattrs);WARN_ON (inode->i_blocks);
@@ -2462,13 +2461,12 @@ static int shmem_symlink(struct inode *d info =SHMEM_I (inode); inode->i_size = len-1 ;if (len <=SHORT_SYMLINK_LEN ) { - info->symlink =kmemdup (symname, len,GFP_KERNEL ); -if (!info->symlink) { + inode->i_link =kmemdup (symname, len,GFP_KERNEL ); +if (!inode->i_link) {iput (inode);return -ENOMEM ; } inode->i_op = &shmem_short_symlink_operations; - inode->i_link = info->symlink; }else { error =shmem_getpage (inode,0 , &page,SGP_WRITE ,NULL );if (error) {
@@ -3083,6 +3081,7 @@ static struct inode *shmem_alloc_inode(sstatic void shmem_destroy_callback (struct rcu_head *head) { struct inode *inode = container_of(head, struct inode, i_rcu); +kfree (inode->i_link);kmem_cache_free (shmem_inode_cachep,SHMEM_I (inode)); }
Greg Kroah-Hartman
maintainerPATCH 236/342 toshiba_acpi: Fix blank screen at boot if transflective backlight is supported
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Azael Avalos <[email protected]>
commit bae5336f0aaedffa115dab9cb3d8a4e4aed3a26a upstream.
If transflective backlight is supported and the brightness is zero (lowest brightness level), the set_lcd_brightness function will activate the transflective backlight, making the LCD appear to be turned off.
This patch fixes the issue by incrementing the brightness level, and by doing so, avoiding the activation of the tranflective backlight.
--- drivers/platform/x86/toshiba_acpi.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/platform/x86/toshiba_acpi.c +8 -0
@@ -2484,6 +2484,14 @@ static int toshiba_acpi_setup_backlight( brightness =__get_lcd_brightness (dev);if (brightness <0 )return 0 ; +/* +* If transflective backlight is supported and the brightness is zero +* (lowest brightness level), the set_lcd_brightness function will +* activate the transflective backlight, making the LCD appear to be +* turned off, simply increment the brightness level to avoid that. +*/ +if (dev->tr_backlight_supported && brightness ==0 ) + brightness++; ret =set_lcd_brightness (dev, brightness);if (ret) {pr_debug ("Backlight method is read-only, disabling backlight support\n" );
Greg Kroah-Hartman
maintainerPATCH 237/342 ideapad-laptop: Add Lenovo ideapad Y700-17ISK to no_hw_rfkill dmi list
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Josh Boyer <[email protected]>
commit edde316acb5f07c04abf09a92f59db5d2efd14e2 upstream.
One of the newest ideapad models also lacks a physical hw rfkill switch, and trying to read the hw rfkill switch through the ideapad module causes it to always reported blocking breaking wifi.
Fix it by adding this model to the DMI list.
--- drivers/platform/x86/ideapad-laptop.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/platform/x86/ideapad-laptop.c +7 -0
@@ -865,6 +865,13 @@ static const struct dmi_system_id no_hw_ }, }, { + .ident = "Lenovo ideapad Y700-17ISK", + .matches = { +DMI_MATCH (DMI_SYS_VENDOR ,"LENOVO" ), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-17ISK"), + }, + }, + { .ident ="Lenovo Yoga 2 11 / 13 / Pro" , .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
Greg Kroah-Hartman
maintainerPATCH 238/342 ideapad-laptop: Add Lenovo Yoga 700 to no_hw_rfkill dmi list
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Josh Boyer <[email protected]>
commit 6b31de3e698582fe0b8f7f4bab15831b73204800 upstream.
Like the Yoga 900 models the Lenovo Yoga 700 does not have a hw rfkill switch, and trying to read the hw rfkill switch through the ideapad module causes it to always reported blocking breaking wifi.
This commit adds the Lenovo Yoga 700 to the no_hw_rfkill dmi list, fixing the wifi breakage.
--- drivers/platform/x86/ideapad-laptop.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/platform/x86/ideapad-laptop.c +7 -0
@@ -900,6 +900,13 @@ static const struct dmi_system_id no_hw_ }, }, { + .ident = "Lenovo Yoga 700", + .matches = { +DMI_MATCH (DMI_SYS_VENDOR ,"LENOVO" ), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 700"), + }, + }, + { .ident ="Lenovo Yoga 900" , .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
Greg Kroah-Hartman
maintainerPATCH 239/342 uapi: update install list after nvme.h rename
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Frysinger <[email protected]>
commit a9cf8284b45110a4d98aea180a89c857e53bf850 upstream.
Commit 9d99a8dda154 ("nvme: move hardware structures out of the uapi version of nvme.h") renamed nvme.h to nvme_ioctl.h, but the uapi list still refers to nvme.h. People trying to install the headers hit a failure as the header no longer exists.
--- include/uapi/linux/Kbuild | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/uapi/linux/Kbuild +1 -1
@@ -307,7 +307,7 @@ header-y += nfs_mount.h header-y += nl80211.h header-y += n_r3964.h header-y += nubus.h -header-y += nvme.h +header-y += nvme_ioctl.h header-y += nvram.h header-y += omap3isp.h header-y += omapfb.h
Greg Kroah-Hartman
maintainerPATCH 240/342 lib: sw842: select crc32
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnd Bergmann <[email protected]>
commit 5b57167749274961baf15ed1f05a4996b3ab0487 upstream.
The sw842 library code was merged in linux-4.1 and causes a very rare randconfig failure when CONFIG_CRC32 is not set:
lib/built-in.o: In function `sw842_compress':
oid_registry.c:(.text+0x12ddc): undefined reference to crc32_be' lib/built-in.o: In function sw842_decompress':
oid_registry.c:(.text+0x137e4): undefined reference to `crc32_be'
This adds an explict 'select CRC32' statement, similar to what the other users of the crc32 code have. In practice, CRC32 is always enabled anyway because over 100 other symbols select it.
--- lib/Kconfig | 2 ++ 1 file changed, 2 insertions(+)
lib/Kconfig +2 -0
@@ -210,9 +210,11 @@ config RANDOM32_SELFTEST # compression support is select'ed if needed # config 842_COMPRESS + select CRC32 tristate config 842_DECOMPRESS + select CRC32 tristate config ZLIB_INFLATE
Greg Kroah-Hartman
maintainerPATCH 241/342 ACPI / video: Add disable_backlight_sysfs_if quirk for the Toshiba Portege R700
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hans de Goede <[email protected]>
commit de588b8ff057d4de0751f337b930f90ca522bab2 upstream.
The Toshiba Portege R700 needs disable_backlight_sysfs_if=1, just like the Toshiba Portege R830. Add a quirk for this.
--- drivers/acpi/acpi_video.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/acpi/acpi_video.c +9 -0
@@ -465,6 +465,15 @@ static struct dmi_system_id video_dmi_ta* as brightness control does not work. */ { +/* https://bugzilla.kernel.org/show_bug.cgi?id=21012 */ + .callback = video_disable_backlight_sysfs_if, + .ident = "Toshiba Portege R700", + .matches = { +DMI_MATCH (DMI_SYS_VENDOR ,"TOSHIBA" ), + DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R700"), + }, + }, + {/* https://bugs.freedesktop.org/show_bug.cgi?id=82634 */ .callback = video_disable_backlight_sysfs_if, .ident = "Toshiba Portege R830",
Greg Kroah-Hartman
maintainerPATCH 242/342 ACPI / video: Add disable_backlight_sysfs_if quirk for the Toshiba Satellite R830
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hans de Goede <[email protected]>
commit b21f2e81bd3fd8ed260590e72901254bca2193cd upstream.
The Toshiba Satellite R830 needs disable_backlight_sysfs_if=1, just like the Toshiba Portege R830. Add a quirk for this.
--- drivers/acpi/acpi_video.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/acpi/acpi_video.c +9 -0
@@ -482,6 +482,15 @@ static struct dmi_system_id video_dmi_ta DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R830"), }, }, + { + /* https://bugzilla.kernel.org/show_bug.cgi?id=21012 */ + .callback = video_disable_backlight_sysfs_if, + .ident = "Toshiba Satellite R830", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE R830"), + }, + },/* * Some machine's _DOD IDs don't have bit 31(Device ID Scheme) set * but the IDs actually follow the Device ID Scheme.
Greg Kroah-Hartman
maintainerPATCH 243/342 ACPI: Revert "ACPI / video: Add Dell Inspiron 5737 to the blacklist"
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hans de Goede <[email protected]>
commit b186b4dcb79b1914c3dadb27ac72dafaa4267998 upstream.
The quirk to get "acpi_backlight=vendor" behavior by default on the Dell Inspiron 5737 was added before we started doing "acpi_backlight=native" by default on Win8 ready machines.
Since we now avoid using acpi-video as backlight driver on these machines by default (using the native driver instead) we no longer need this quirk.
Moreover the vendor driver does not work after a suspend/resume where as the native driver does.
This reverts commit 08a56226d847 (ACPI / video: Add Dell Inspiron 5737 to the blacklist).
--- drivers/acpi/video_detect.c | 8 -------- 1 file changed, 8 deletions(-)
drivers/acpi/video_detect.c +0 -8
@@ -135,14 +135,6 @@ static const struct dmi_system_id video_ DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"), }, }, - { - .callback = video_detect_force_vendor, - .ident = "Dell Inspiron 5737", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5737"), - }, - },/* * These models have a working acpi_video backlight control, and using
Greg Kroah-Hartman
maintainerPATCH 244/342 ACPI / PCI / hotplug: unlock in error path in acpiphp_enable_slot()
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Insu Yun <[email protected]>
commit 2c3033a0664dfae91e1dee7fabac10f24354b958 upstream.
In acpiphp_enable_slot(), there is a missing unlock path when error occurred. It needs to be unlocked before returning an error.
--- drivers/pci/hotplug/acpiphp_glue.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/pci/hotplug/acpiphp_glue.c +3 -1
@@ -953,8 +953,10 @@ int acpiphp_enable_slot(struct acpiphp_s {pci_lock_rescan_remove (); -if (slot->flags &SLOT_IS_GOING_AWAY ) +if (slot->flags &SLOT_IS_GOING_AWAY ) { +pci_unlock_rescan_remove ();return -ENODEV ; + }/* configure all functions */ if (!(slot->flags &SLOT_ENABLED ))
Greg Kroah-Hartman
maintainerPATCH 245/342 nfit: fix multi-interface dimm handling, acpi6.1 compatibility
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Williams <[email protected]>
commit 6697b2cf69d4363266ca47eaebc49ef13dabc1c9 upstream.
ACPI 6.1 clarified that multi-interface dimms require multiple control region entries (DCRs) per dimm. Previously we were assuming that a control region is only present when block-data-windows are present. This implementation was done with an eye to be compatibility with the looser ACPI 6.0 interpretation of this table.
1/ When coalescing the memory device (MEMDEV) tables for a single dimm, coalesce on device_handle rather than control region index.
2/ Whenever we disocver a control region with non-zero block windows re-scan for block-data-window (BDW) entries.
We may need to revisit this if a DIMM ever implements a format interface outside of blk or pmem, but that is not on the foreseeable horizon.
--- drivers/acpi/nfit.c | 71 +++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 36 deletions(-)
drivers/acpi/nfit.c +35 -36
@@ -468,37 +468,16 @@ static void nfit_mem_find_spa_bdw(struct nfit_mem->bdw =NULL ; } -static int nfit_mem_add (struct acpi_nfit_desc *acpi_desc, +static void nfit_mem_init_bdw (struct acpi_nfit_desc *acpi_desc,struct nfit_mem *nfit_mem,struct acpi_nfit_system_address *spa) {u16 dcr =__to_nfit_memdev (nfit_mem)->region_index;struct nfit_memdev *nfit_memdev;struct nfit_flush *nfit_flush; -struct nfit_dcr *nfit_dcr;struct nfit_bdw *nfit_bdw;struct nfit_idt *nfit_idt;u16 idt_idx, range_index; -list_for_each_entry (nfit_dcr, &acpi_desc->dcrs, list) { -if (nfit_dcr->dcr->region_index != dcr) -continue ; - nfit_mem->dcr = nfit_dcr->dcr; -break ; - } - -if (!nfit_mem->dcr) { -dev_dbg (acpi_desc->dev,"SPA %d missing:%s%s\n" , - spa->range_index,__to_nfit_memdev (nfit_mem) - ?"" :" MEMDEV" , nfit_mem->dcr ?"" :" DCR" ); -return -ENODEV ; - } - -/* -* We've found enough to create an nvdimm, optionally -* find an associated BDW -*/ -list_add (&nfit_mem->list, &acpi_desc->dimms); -list_for_each_entry (nfit_bdw, &acpi_desc->bdws, list) {if (nfit_bdw->bdw->region_index != dcr)continue ;
@@ -507,12 +486,12 @@ static int nfit_mem_add(struct acpi_nfit }if (!nfit_mem->bdw) -return 0 ; +return ;nfit_mem_find_spa_bdw (acpi_desc, nfit_mem);if (!nfit_mem->spa_bdw) -return 0 ; +return ; range_index = nfit_mem->spa_bdw->range_index;list_for_each_entry (nfit_memdev, &acpi_desc->memdevs, list) {
@@ -537,8 +516,6 @@ static int nfit_mem_add(struct acpi_nfit }break ; } - -return 0 ; } static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
@@ -547,7 +524,6 @@ static int nfit_mem_dcr_init(struct acpistruct nfit_mem *nfit_mem, *found;struct nfit_memdev *nfit_memdev;int type =nfit_spa_type (spa); -u16 dcr;switch (type) {case NFIT_SPA_DCR :
@@ -558,14 +534,18 @@ static int nfit_mem_dcr_init(struct acpi }list_for_each_entry (nfit_memdev, &acpi_desc->memdevs, list) { -int rc; +struct nfit_dcr *nfit_dcr; +u32 device_handle; +u16 dcr;if (nfit_memdev->memdev->range_index != spa->range_index)continue ; found =NULL ; dcr = nfit_memdev->memdev->region_index; + device_handle = nfit_memdev->memdev->device_handle;list_for_each_entry (nfit_mem, &acpi_desc->dimms, list) -if (__to_nfit_memdev (nfit_mem)->region_index == dcr) { +if (__to_nfit_memdev (nfit_mem)->device_handle + == device_handle) { found = nfit_mem;break ; }
@@ -578,6 +558,31 @@ static int nfit_mem_dcr_init(struct acpiif (!nfit_mem)return -ENOMEM ;INIT_LIST_HEAD (&nfit_mem->list); +list_add (&nfit_mem->list, &acpi_desc->dimms); + } + +list_for_each_entry (nfit_dcr, &acpi_desc->dcrs, list) { +if (nfit_dcr->dcr->region_index != dcr) +continue ; +/* +* Record the control region for the dimm. For +* the ACPI 6.1 case, where there are separate +* control regions for the pmem vs blk +* interfaces, be sure to record the extended +* blk details. +*/ +if (!nfit_mem->dcr) + nfit_mem->dcr = nfit_dcr->dcr; +else if (nfit_mem->dcr->windows ==0 + && nfit_dcr->dcr->windows) + nfit_mem->dcr = nfit_dcr->dcr; +break ; + } + +if (dcr && !nfit_mem->dcr) { +dev_err (acpi_desc->dev,"SPA %d missing DCR %d\n" , + spa->range_index, dcr); +return -ENODEV ; }if (type ==NFIT_SPA_DCR ) {
@@ -594,6 +599,7 @@ static int nfit_mem_dcr_init(struct acpi nfit_mem->idt_dcr = nfit_idt->idt;break ; } +nfit_mem_init_bdw (acpi_desc, nfit_mem, spa); }else {/* * A single dimm may belong to multiple SPA-PM
@@ -602,13 +608,6 @@ static int nfit_mem_dcr_init(struct acpi*/ nfit_mem->memdev_pmem = nfit_memdev->memdev; } - -if (found) -continue ; - - rc =nfit_mem_add (acpi_desc, nfit_mem, spa); -if (rc) -return rc; }return 0 ;
Greg Kroah-Hartman
maintainerPATCH 246/342 dmaengine: dw: fix cyclic transfer setup
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mans Rullgard <[email protected]>
commit df3bb8a0e619d501cd13334c3e0586edcdcbc716 upstream.
Commit 61e183f83069 ("dmaengine/dw_dmac: Reconfigure interrupt and chan_cfg register on resume") moved some channel initialisation to a new function which must be called before starting a transfer.
This updates dw_dma_cyclic_start() to use dwc_dostart() like the other modes, thus ensuring dwc_initialize() gets called and removing some code duplication.
--- drivers/dma/dw/core.c | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-)
drivers/dma/dw/core.c +1 -22
@@ -1245,7 +1245,6 @@ static void dwc_free_chan_resources(struint dw_dma_cyclic_start (struct dma_chan *chan) {struct dw_dma_chan *dwc =to_dw_dma_chan (chan); -struct dw_dma *dw =to_dw_dma (dwc->chan.device);unsigned long flags;if (!test_bit (DW_DMA_IS_CYCLIC , &dwc->flags)) {
@@ -1254,27 +1253,7 @@ int dw_dma_cyclic_start(struct dma_chan }spin_lock_irqsave (&dwc->lock, flags); - -/* Assert channel is idle */ -if (dma_readl (dw,CH_EN ) & dwc->mask) { -dev_err (chan2dev (&dwc->chan), -"%s: BUG: Attempted to start non-idle channel\n" , - __func__); -dwc_dump_chan_regs (dwc); -spin_unlock_irqrestore (&dwc->lock, flags); -return -EBUSY ; - } - -dma_writel (dw,CLEAR .ERROR, dwc->mask); -dma_writel (dw,CLEAR .XFER, dwc->mask); - -/* Setup DMAC channel registers */ -channel_writel (dwc,LLP , dwc->cdesc->desc[0 ]->txd.phys); -channel_writel (dwc,CTL_LO ,DWC_CTLL_LLP_D_EN |DWC_CTLL_LLP_S_EN ); -channel_writel (dwc,CTL_HI ,0 ); - -channel_set_bit (dw,CH_EN , dwc->mask); - +dwc_dostart (dwc, dwc->cdesc->desc[0 ]);spin_unlock_irqrestore (&dwc->lock, flags);return 0 ;
Greg Kroah-Hartman
maintainerPATCH 247/342 dmaengine: dw: fix cyclic transfer callbacks
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mans Rullgard <[email protected]>
commit 2895b2cad6e7a95104cf396e5330054453382ae1 upstream.
Cyclic transfer callbacks rely on block completion interrupts which were disabled in commit ff7b05f29fd4 ("dmaengine/dw_dmac: Don't handle block interrupts"). This re-enables block interrupts so the cyclic callbacks can work. Other transfer types are not affected as they set the INT_EN bit only on the last block.
--- drivers/dma/dw/core.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-)
drivers/dma/dw/core.c +15 -6
@@ -156,6 +156,7 @@ static void dwc_initialize(struct dw_dma/* Enable interrupts */ channel_set_bit (dw,MASK .XFER, dwc->mask); +channel_set_bit (dw,MASK .BLOCK, dwc->mask);channel_set_bit (dw,MASK .ERROR, dwc->mask); dwc->initialized = true;
@@ -536,16 +537,17 @@ EXPORT_SYMBOL(dw_dma_get_dst_addr);/* Called with dwc->lock held and all DMAC interrupts disabled */ static void dwc_handle_cyclic (struct dw_dma *dw,struct dw_dma_chan *dwc, -u32 status_err,u32 status_xfer) +u32 status_block,u32 status_err,u32 status_xfer) {unsigned long flags; -if (dwc->mask) { +if (status_block & dwc->mask) {void (*callback)(void *param);void *callback_param;dev_vdbg (chan2dev (&dwc->chan),"new cyclic period llp 0x%08x\n" ,channel_readl (dwc,LLP )); +dma_writel (dw,CLEAR .BLOCK, dwc->mask); callback = dwc->cdesc->period_callback; callback_param = dwc->cdesc->period_callback_param;
@@ -577,6 +579,7 @@ static void dwc_handle_cyclic(struct dw_channel_writel (dwc,CTL_LO ,0 );channel_writel (dwc,CTL_HI ,0 ); +dma_writel (dw,CLEAR .BLOCK, dwc->mask);dma_writel (dw,CLEAR .ERROR, dwc->mask);dma_writel (dw,CLEAR .XFER, dwc->mask);
@@ -593,10 +596,12 @@ static void dw_dma_tasklet(unsigned long {struct dw_dma *dw = (struct dw_dma *)data;struct dw_dma_chan *dwc; +u32 status_block;u32 status_xfer;u32 status_err;int i; + status_block =dma_readl (dw,RAW .BLOCK); status_xfer =dma_readl (dw,RAW .XFER); status_err =dma_readl (dw,RAW .ERROR);
@@ -605,7 +610,8 @@ static void dw_dma_tasklet(unsigned longfor (i =0 ; i < dw->dma.chancnt; i++) { dwc = &dw->chan[i];if (test_bit (DW_DMA_IS_CYCLIC , &dwc->flags)) -dwc_handle_cyclic (dw, dwc, status_err, status_xfer); +dwc_handle_cyclic (dw, dwc, status_block, status_err, + status_xfer);else if (status_err & (1 << i))dwc_handle_error (dw, dwc);else if (status_xfer & (1 << i))
@@ -616,6 +622,7 @@ static void dw_dma_tasklet(unsigned long* Re-enable interrupts. */ channel_set_bit (dw,MASK .XFER, dw->all_chan_mask); +channel_set_bit (dw,MASK .BLOCK, dw->all_chan_mask);channel_set_bit (dw,MASK .ERROR, dw->all_chan_mask); }
@@ -635,6 +642,7 @@ static irqreturn_t dw_dma_interrupt(int* softirq handler. */ channel_clear_bit (dw,MASK .XFER, dw->all_chan_mask); +channel_clear_bit (dw,MASK .BLOCK, dw->all_chan_mask);channel_clear_bit (dw,MASK .ERROR, dw->all_chan_mask); status =dma_readl (dw,STATUS_INT );
@@ -645,6 +653,7 @@ static irqreturn_t dw_dma_interrupt(int/* Try to recover */ channel_clear_bit (dw,MASK .XFER, (1 <<8 ) -1 ); +channel_clear_bit (dw,MASK .BLOCK, (1 <<8 ) -1 );channel_clear_bit (dw,MASK .SRC_TRAN, (1 <<8 ) -1 );channel_clear_bit (dw,MASK .DST_TRAN, (1 <<8 ) -1 );channel_clear_bit (dw,MASK .ERROR, (1 <<8 ) -1 );
@@ -1111,6 +1120,7 @@ static void dw_dma_off(struct dw_dma *dwdma_writel (dw,CFG ,0 );channel_clear_bit (dw,MASK .XFER, dw->all_chan_mask); +channel_clear_bit (dw,MASK .BLOCK, dw->all_chan_mask);channel_clear_bit (dw,MASK .SRC_TRAN, dw->all_chan_mask);channel_clear_bit (dw,MASK .DST_TRAN, dw->all_chan_mask);channel_clear_bit (dw,MASK .ERROR, dw->all_chan_mask);
@@ -1216,6 +1226,7 @@ static void dwc_free_chan_resources(stru/* Disable interrupts */ channel_clear_bit (dw,MASK .XFER, dwc->mask); +channel_clear_bit (dw,MASK .BLOCK, dwc->mask);channel_clear_bit (dw,MASK .ERROR, dwc->mask);spin_unlock_irqrestore (&dwc->lock, flags);
@@ -1458,6 +1469,7 @@ void dw_dma_cyclic_free(struct dma_chandwc_chan_disable (dw, dwc); +dma_writel (dw,CLEAR .BLOCK, dwc->mask);dma_writel (dw,CLEAR .ERROR, dwc->mask);dma_writel (dw,CLEAR .XFER, dwc->mask);
@@ -1546,9 +1558,6 @@ int dw_dma_probe(struct dw_dma_chip *chi/* Force dma off, just in case */ dw_dma_off (dw); -/* Disable BLOCK interrupts as well */ -channel_clear_bit (dw,MASK .BLOCK, dw->all_chan_mask); -/* Create a pool of consistent memory blocks for hardware descriptors */ dw->desc_pool =dmam_pool_create ("dw_dmac_desc_pool" , chip->dev,sizeof (struct dw_desc ),4 ,0 );
Greg Kroah-Hartman
maintainerPATCH 248/342 dmaengine: at_xdmac: fix resume for cyclic transfers
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Songjun Wu <[email protected]>
commit 611dcadb01c89d1d3521450c05a4ded332e5a32d upstream.
When having cyclic transfers, the channel was paused when performing suspend but was not correctly resumed.
--- drivers/dma/at_xdmac.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/dma/at_xdmac.c +3 -0
@@ -1688,6 +1688,7 @@ static int at_xdmac_device_terminate_alllist_for_each_entry_safe (desc, _desc, &atchan->xfers_list, xfer_node)at_xdmac_remove_xfer (atchan, desc); +clear_bit (AT_XDMAC_CHAN_IS_PAUSED , &atchan->status);clear_bit (AT_XDMAC_CHAN_IS_CYCLIC , &atchan->status);spin_unlock_irqrestore (&atchan->lock, flags);
@@ -1820,6 +1821,8 @@ static int atmel_xdmac_resume(struct dev atchan =to_at_xdmac_chan (chan);at_xdmac_chan_write (atchan,AT_XDMAC_CC , atchan->save_cc);if (at_xdmac_chan_is_cyclic (atchan)) { +if (at_xdmac_chan_is_paused (atchan)) +at_xdmac_device_resume (chan);at_xdmac_chan_write (atchan,AT_XDMAC_CNDA , atchan->save_cnda);at_xdmac_chan_write (atchan,AT_XDMAC_CNDC , atchan->save_cndc);at_xdmac_chan_write (atchan,AT_XDMAC_CIE , atchan->save_cim);
Greg Kroah-Hartman
maintainerPATCH 249/342 dmaengine: dw: disable BLOCK IRQs for non-cyclic xfer
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <[email protected]>
commit ee1cdcdae59563535485a5f56ee72c894ab7d7ad upstream.
The commit 2895b2cad6e7 ("dmaengine: dw: fix cyclic transfer callbacks") re-enabled BLOCK interrupts with regard to make cyclic transfers work. However, this change becomes a regression for non-cyclic transfers as interrupt counters under stress test had been grown enormously (approximately per 4-5 bytes in the UART loop back test).
Taking into consideration above enable BLOCK interrupts if and only if channel is programmed to perform cyclic transfer.
--- drivers/dma/dw/core.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
drivers/dma/dw/core.c +10 -5
@@ -156,7 +156,6 @@ static void dwc_initialize(struct dw_dma/* Enable interrupts */ channel_set_bit (dw,MASK .XFER, dwc->mask); -channel_set_bit (dw,MASK .BLOCK, dwc->mask);channel_set_bit (dw,MASK .ERROR, dwc->mask); dwc->initialized = true;
@@ -588,6 +587,9 @@ static void dwc_handle_cyclic(struct dw_spin_unlock_irqrestore (&dwc->lock, flags); } + +/* Re-enable interrupts */ +channel_set_bit (dw,MASK .BLOCK, dwc->mask); }/* ------------------------------------------------------------------------- */
@@ -618,11 +620,8 @@ static void dw_dma_tasklet(unsigned longdwc_scan_descriptors (dw, dwc); } -/* -* Re-enable interrupts. -*/ +/* Re-enable interrupts */ channel_set_bit (dw,MASK .XFER, dw->all_chan_mask); -channel_set_bit (dw,MASK .BLOCK, dw->all_chan_mask);channel_set_bit (dw,MASK .ERROR, dw->all_chan_mask); }
@@ -1256,6 +1255,7 @@ static void dwc_free_chan_resources(struint dw_dma_cyclic_start (struct dma_chan *chan) {struct dw_dma_chan *dwc =to_dw_dma_chan (chan); +struct dw_dma *dw =to_dw_dma (chan->device);unsigned long flags;if (!test_bit (DW_DMA_IS_CYCLIC , &dwc->flags)) {
@@ -1264,7 +1264,12 @@ int dw_dma_cyclic_start(struct dma_chan }spin_lock_irqsave (&dwc->lock, flags); + +/* Enable interrupts to perform cyclic transfer */ +channel_set_bit (dw,MASK .BLOCK, dwc->mask); +dwc_dostart (dwc, dwc->cdesc->desc[0 ]); +spin_unlock_irqrestore (&dwc->lock, flags);return 0 ;
Greg Kroah-Hartman
maintainerPATCH 250/342 IB/cm: Fix a recently introduced deadlock
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bart Van Assche <[email protected]>
commit 4bfdf635c668869c69fd18ece37ec66fb6f38fcf upstream.
ib_send_cm_drep() calls cm_enter_timewait() while holding a spinlock that can be locked from inside an interrupt handler. Hence do not enable interrupts inside cm_enter_timewait() if called with interrupts disabled.
This patch fixes e.g. the following deadlock:
=================================
[ INFO: inconsistent lock state ]
4.4.0-rc7+ #1 Tainted: G E
---------------------------------
inconsistent {HARDIRQ-ON-W} -> {IN-HARDIRQ-W} usage.
swapper/8/0 [HC1[1]:SC0[0]:HE0:SE1] takes:
(&(&cm_id_priv->lock)->rlock){?.+...}, at: [<ffffffffa036eec4>] cm_establish+0x 74/0x1b0 [ib_cm]
{HARDIRQ-ON-W} state was registered at:
[<ffffffff810a3c11>] mark_held_locks+0x71/0x90 [<ffffffff810a3e87>] trace_hardirqs_on_caller+0xa7/0x1c0 [<ffffffff810a3fad>] trace_hardirqs_on+0xd/0x10 [<ffffffff8151c40b>] _raw_spin_unlock_irq+0x2b/0x40 [<ffffffffa036ea8e>] cm_enter_timewait+0xae/0x100 [ib_cm] [<ffffffffa036ff76>] ib_send_cm_drep+0xb6/0x190 [ib_cm] [<ffffffffa052ed08>] srp_cm_handler+0x128/0x1a0 [ib_srp] [<ffffffffa0370340>] cm_process_work+0x20/0xf0 [ib_cm] [<ffffffffa0371335>] cm_dreq_handler+0x135/0x2c0 [ib_cm] [<ffffffffa03733c5>] cm_work_handler+0x75/0xd0 [ib_cm] [<ffffffff8107184d>] process_one_work+0x1bd/0x460 [<ffffffff81073148>] worker_thread+0x118/0x420 [<ffffffff81078454>] kthread+0xe4/0x100 [<ffffffff8151cbbf>] ret_from_fork+0x3f/0x70 irq event stamp: 1672286 hardirqs last enabled at (1672283): [<ffffffff81408ec0>] poll_idle+0x10/0x80 hardirqs last disabled at (1672284): [<ffffffff8151d304>] common_interrupt+0x84/0x89 softirqs last enabled at (1672286): [<ffffffff8105b4dc>] _local_bh_enable+0x1c/0x50 softirqs last disabled at (1672285): [<ffffffff8105b697>] irq_enter+0x47/0x70
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0
----
lock(&(&cm_id_priv->lock)->rlock);
<Interrupt>
lock(&(&cm_id_priv->lock)->rlock);*** DEADLOCK ***
no locks held by swapper/8/0.
stack backtrace: CPU: 8 PID: 0 Comm: swapper/8 Tainted: G E 4.4.0-rc7+ #1 Hardware name: Dell Inc. PowerEdge R430/03XKDV, BIOS 1.0.2 11/17/2014 ffff88045af5e950 ffff88046e503a88 ffffffff81251c1b 0000000000000007 0000000000000006 0000000000000003 ffff88045af5ddc0 ffff88046e503ad8 ffffffff810a32f4 0000000000000000 0000000000000000 0000000000000001 Call Trace: <IRQ> [<ffffffff81251c1b>] dump_stack+0x4f/0x74 [<ffffffff810a32f4>] print_usage_bug+0x184/0x190 [<ffffffff810a36e2>] mark_lock_irq+0xf2/0x290 [<ffffffff810a3995>] mark_lock+0x115/0x1b0 [<ffffffff810a3b8c>] mark_irqflags+0x15c/0x170 [<ffffffff810a4fef>] __lock_acquire+0x1ef/0x560 [<ffffffff810a53c2>] lock_acquire+0x62/0x80 [<ffffffff8151bd33>] _raw_spin_lock_irqsave+0x43/0x60 [<ffffffffa036eec4>] cm_establish+0x74/0x1b0 [ib_cm] [<ffffffffa036f031>] ib_cm_notify+0x31/0x100 [ib_cm] [<ffffffffa0637f24>] srpt_qp_event+0x54/0xd0 [ib_srpt] [<ffffffffa0196052>] mlx4_ib_qp_event+0x72/0xc0 [mlx4_ib] [<ffffffffa00775b9>] mlx4_qp_event+0x69/0xd0 [mlx4_core] [<ffffffffa006000e>] mlx4_eq_int+0x51e/0xd50 [mlx4_core] [<ffffffffa006084f>] mlx4_msi_x_interrupt+0xf/0x20 [mlx4_core] [<ffffffff810b67b0>] handle_irq_event_percpu+0x40/0x110 [<ffffffff810b68bf>] handle_irq_event+0x3f/0x70 [<ffffffff810ba7f9>] handle_edge_irq+0x79/0x120 [<ffffffff81007f3d>] handle_irq+0x5d/0x130 [<ffffffff810071fd>] do_IRQ+0x6d/0x130 [<ffffffff8151d309>] common_interrupt+0x89/0x89 <EOI> [<ffffffff8140895f>] cpuidle_enter_state+0xcf/0x200 [<ffffffff81408aa2>] cpuidle_enter+0x12/0x20 [<ffffffff810990d6>] call_cpuidle+0x36/0x60 [<ffffffff81099163>] cpuidle_idle_call+0x63/0x110 [<ffffffff8109930a>] cpu_idle_loop+0xfa/0x130 [<ffffffff8109934e>] cpu_startup_entry+0xe/0x10 [<ffffffff8103c443>] start_secondary+0x83/0x90
--- drivers/infiniband/core/cm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/infiniband/core/cm.c +2 -2
@@ -782,11 +782,11 @@ static void cm_enter_timewait(struct cm_ wait_time =cm_convert_to_ms (cm_id_priv->av.timeout);/* Check if the device started its remove_one */ -spin_lock_irq (&cm.lock); +spin_lock_irqsave (&cm.lock, flags);if (!cm_dev->going_down)queue_delayed_work (cm.wq, &cm_id_priv->timewait_info->work.work,msecs_to_jiffies (wait_time)); -spin_unlock_irq (&cm.lock); +spin_unlock_irqrestore (&cm.lock, flags); cm_id_priv->timewait_info =NULL ; }
Greg Kroah-Hartman
maintainerPATCH 251/342 IB/qib: fix mcast detach when qp not attached
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Marciniszyn <[email protected]>
commit 09dc9cd6528f5b52bcbd3292a6312e762c85260f upstream.
The code produces the following trace:
[1750924.419007] general protection fault: 0000 [#3] SMP [1750924.420364] Modules linked in: nfnetlink autofs4 rpcsec_gss_krb5 nfsv4
dcdbas rfcomm bnep bluetooth nfsd auth_rpcgss nfs_acl dm_multipath nfs lockd scsi_dh sunrpc fscache radeon ttm drm_kms_helper drm serio_raw parport_pc ppdev i2c_algo_bit lpc_ich ipmi_si ib_mthca ib_qib dca lp parport ib_ipoib mac_hid ib_cm i3000_edac ib_sa ib_uverbs edac_core ib_umad ib_mad ib_core ib_addr tg3 ptp dm_mirror dm_region_hash dm_log psmouse pps_core
[1750924.420364] CPU: 1 PID: 8401 Comm: python Tainted: G D 3.13.0-39-generic #66-Ubuntu [1750924.420364] Hardware name: Dell Computer Corporation PowerEdge 860/0XM089, BIOS A04 07/24/2007 [1750924.420364] task: ffff8800366a9800 ti: ffff88007af1c000 task.ti: ffff88007af1c000 [1750924.420364] RIP: 0010:[<ffffffffa0131d51>] [<ffffffffa0131d51>] qib_mcast_qp_free+0x11/0x50 [ib_qib] [1750924.420364] RSP: 0018:ffff88007af1dd70 EFLAGS: 00010246 [1750924.420364] RAX: 0000000000000001 RBX: ffff88007b822688 RCX: 000000000000000f [1750924.420364] RDX: ffff88007b822688 RSI: ffff8800366c15a0 RDI: 6764697200000000 [1750924.420364] RBP: ffff88007af1dd78 R08: 0000000000000001 R09: 0000000000000000 [1750924.420364] R10: 0000000000000011 R11: 0000000000000246 R12: ffff88007baa1d98 [1750924.420364] R13: ffff88003ecab000 R14: ffff88007b822660 R15: 0000000000000000 [1750924.420364] FS: 00007ffff7fd8740(0000) GS:ffff88007fc80000(0000) knlGS:0000000000000000 [1750924.420364] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [1750924.420364] CR2: 00007ffff597c750 CR3: 000000006860b000 CR4: 00000000000007e0 [1750924.420364] Stack: [1750924.420364] ffff88007b822688 ffff88007af1ddf0 ffffffffa0132429 000000007af1de20 [1750924.420364] ffff88007baa1dc8 ffff88007baa0000 ffff88007af1de70 ffffffffa00cb313 [1750924.420364] 00007fffffffde88 0000000000000000 0000000000000008 ffff88003ecab000 [1750924.420364] Call Trace: [1750924.420364] [<ffffffffa0132429>] qib_multicast_detach+0x1e9/0x350 [ib_qib] [1750924.568035] [<ffffffffa00cb313>] ? ib_uverbs_modify_qp+0x323/0x3d0 [ib_uverbs] [1750924.568035] [<ffffffffa0092d61>] ib_detach_mcast+0x31/0x50 [ib_core] [1750924.568035] [<ffffffffa00cc213>] ib_uverbs_detach_mcast+0x93/0x170 [ib_uverbs] [1750924.568035] [<ffffffffa00c61f6>] ib_uverbs_write+0xc6/0x2c0 [ib_uverbs] [1750924.568035] [<ffffffff81312e68>] ? apparmor_file_permission+0x18/0x20 [1750924.568035] [<ffffffff812d4cd3>] ? security_file_permission+0x23/0xa0 [1750924.568035] [<ffffffff811bd214>] vfs_write+0xb4/0x1f0 [1750924.568035] [<ffffffff811bdc49>] SyS_write+0x49/0xa0 [1750924.568035] [<ffffffff8172f7ed>] system_call_fastpath+0x1a/0x1f [1750924.568035] Code: 66 2e 0f 1f 84 00 00 00 00 00 31 c0 5d c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 0f 1f 44 00 00 55 48 89 e5 53 48 89 fb 48 8b 7f 10 <f0> ff 8f 40 01 00 00 74 0e 48 89 df e8 8e f8 06 e1 5b 5d c3 0f [1750924.568035] RIP [<ffffffffa0131d51>] qib_mcast_qp_free+0x11/0x50 [ib_qib] [1750924.568035] RSP <ffff88007af1dd70> [1750924.650439] ---[ end trace 73d5d4b3f8ad4851 ]
The fix is to note the qib_mcast_qp that was found. If none is found, then
return EINVAL indicating the error.
--- drivers/infiniband/hw/qib/qib_verbs_mcast.c | 35 ++++++++++++---------------- 1 file changed, 15 insertions(+), 20 deletions(-)
drivers/infiniband/hw/qib/qib_verbs_mcast.c +15 -20
@@ -286,15 +286,13 @@ int qib_multicast_detach(struct ib_qp *istruct qib_ibdev *dev =to_idev (ibqp->device);struct qib_ibport *ibp =to_iport (ibqp->device, qp->port_num);struct qib_mcast *mcast =NULL ; -struct qib_mcast_qp *p, *tmp; +struct qib_mcast_qp *p, *tmp, *delp =NULL ;struct rb_node *n;int last =0 ;int ret; -if (ibqp->qp_num <=1 || qp->state ==IB_QPS_RESET ) { - ret = -EINVAL ; - goto bail; - } +if (ibqp->qp_num <=1 || qp->state ==IB_QPS_RESET ) +return -EINVAL ;spin_lock_irq (&ibp->lock);
@@ -303,8 +301,7 @@ int qib_multicast_detach(struct ib_qp *iwhile (1 ) {if (n ==NULL ) {spin_unlock_irq (&ibp->lock); - ret = -EINVAL ; - goto bail; +return -EINVAL ; } mcast = rb_entry(n, struct qib_mcast, rb_node);
@@ -328,6 +325,7 @@ int qib_multicast_detach(struct ib_qp *i*/ list_del_rcu (&p->list); mcast->n_attached--; + delp = p;/* If this was the last attached QP, remove the GID too. */ if (list_empty (&mcast->qp_list)) {
@@ -338,15 +336,16 @@ int qib_multicast_detach(struct ib_qp *i }spin_unlock_irq (&ibp->lock); +/* QP not attached */ +if (!delp) +return -EINVAL ; +/* +* Wait for any list walkers to finish before freeing the +* list element. +*/ +wait_event (mcast->wait,atomic_read (&mcast->refcount) <=1 ); +qib_mcast_qp_free (delp); -if (p) { -/* -* Wait for any list walkers to finish before freeing the -* list element. -*/ -wait_event (mcast->wait,atomic_read (&mcast->refcount) <=1 ); -qib_mcast_qp_free (p); - }if (last) {atomic_dec (&mcast->refcount);wait_event (mcast->wait, !atomic_read (&mcast->refcount));
@@ -355,11 +354,7 @@ int qib_multicast_detach(struct ib_qp *i dev->n_mcast_grps_allocated--;spin_unlock_irq (&dev->n_mcast_grps_lock); } - - ret =0 ; - -bail: -return ret; +return 0 ; }int qib_mcast_tree_empty (struct qib_ibport *ibp)
Greg Kroah-Hartman
maintainerPATCH 252/342 IB/qib: Support creating qps with GFP_NOIO flag
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vinit Agnihotri <[email protected]>
commit fbbeb8632bf0b46ab44cfcedc4654cd7831b7161 upstream.
The current code is problematic when the QP creation and ipoib is used to support NFS and NFS desires to do IO for paging purposes. In that case, the GFP_KERNEL allocation in qib_qp.c causes a deadlock in tight memory situations.
This fix adds support to create queue pair with GFP_NOIO flag for connected mode only to cleanly fail the create queue pair in those situations.
--- drivers/infiniband/hw/qib/qib_qp.c | 46 +++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 14 deletions(-)
drivers/infiniband/hw/qib/qib_qp.c +32 -14
@@ -100,9 +100,10 @@ static u32 credit_table[31] = { 32768 /* 1E */ }; -static void get_map_page (struct qib_qpn_table *qpt,struct qpn_map *map) +static void get_map_page (struct qib_qpn_table *qpt,struct qpn_map *map, +gfp_t gfp) { -unsigned long page =get_zeroed_page (GFP_KERNEL ); +unsigned long page =get_zeroed_page (gfp);/* * Free the page if someone raced with us installing it.
@@ -121,7 +122,7 @@ static void get_map_page(struct qib_qpn_* zero/one for QP type IB_QPT_SMI/IB_QPT_GSI. */ static int alloc_qpn (struct qib_devdata *dd,struct qib_qpn_table *qpt, -enum ib_qp_type type,u8 port) +enum ib_qp_type type,u8 port,gfp_t gfp) {u32 i, offset, max_scan, qpn;struct qpn_map *map;
@@ -151,7 +152,7 @@ static int alloc_qpn(struct qib_devdata max_scan = qpt->nmaps - !offset;for (i =0 ;;) {if (unlikely (!map->page)) { -get_map_page (qpt, map); +get_map_page (qpt, map, gfp);if (unlikely (!map->page))break ; }
@@ -983,13 +984,21 @@ struct ib_qp *qib_create_qp(struct ib_pdsize_t sz;size_t sg_list_sz;struct ib_qp *ret; +gfp_t gfp; +if (init_attr->cap.max_send_sge > ib_qib_max_sges || init_attr->cap.max_send_wr > ib_qib_max_qp_wrs || - init_attr->create_flags) { - ret =ERR_PTR (-EINVAL ); - goto bail; - } + init_attr->create_flags & ~(IB_QP_CREATE_USE_GFP_NOIO )) +return ERR_PTR (-EINVAL ); + +/* GFP_NOIO is applicable in RC QPs only */ +if (init_attr->create_flags &IB_QP_CREATE_USE_GFP_NOIO && + init_attr->qp_type !=IB_QPT_RC ) +return ERR_PTR (-EINVAL ); + + gfp = init_attr->create_flags &IB_QP_CREATE_USE_GFP_NOIO ? +GFP_NOIO :GFP_KERNEL ;/* Check receive queue parameters if no SRQ is specified. */ if (!init_attr->srq) {
@@ -1021,7 +1030,8 @@ struct ib_qp *qib_create_qp(struct ib_pd sz =sizeof (struct qib_sge ) * init_attr->cap.max_send_sge +sizeof (struct qib_swqe ); - swq =vmalloc ((init_attr->cap.max_send_wr +1 ) * sz); + swq =__vmalloc ((init_attr->cap.max_send_wr +1 ) * sz, + gfp,PAGE_KERNEL );if (swq ==NULL ) { ret =ERR_PTR (-ENOMEM ); goto bail;
@@ -1037,13 +1047,13 @@ struct ib_qp *qib_create_qp(struct ib_pd }else if (init_attr->cap.max_recv_sge >1 ) sg_list_sz =sizeof (*qp->r_sg_list) * (init_attr->cap.max_recv_sge -1 ); - qp =kzalloc (sz + sg_list_sz,GFP_KERNEL ); + qp =kzalloc (sz + sg_list_sz, gfp);if (!qp) { ret =ERR_PTR (-ENOMEM ); goto bail_swq; }RCU_INIT_POINTER (qp->next,NULL ); - qp->s_hdr =kzalloc (sizeof (*qp->s_hdr),GFP_KERNEL ); + qp->s_hdr =kzalloc (sizeof (*qp->s_hdr), gfp);if (!qp->s_hdr) { ret =ERR_PTR (-ENOMEM ); goto bail_qp;
@@ -1058,8 +1068,16 @@ struct ib_qp *qib_create_qp(struct ib_pd qp->r_rq.max_sge = init_attr->cap.max_recv_sge; sz = (sizeof (struct ib_sge ) * qp->r_rq.max_sge) +sizeof (struct qib_rwqe ); - qp->r_rq.wq =vmalloc_user (sizeof (struct qib_rwq ) + - qp->r_rq.size * sz); +if (gfp !=GFP_NOIO ) + qp->r_rq.wq =vmalloc_user ( +sizeof (struct qib_rwq ) + + qp->r_rq.size * sz); +else + qp->r_rq.wq =__vmalloc ( +sizeof (struct qib_rwq ) + + qp->r_rq.size * sz, + gfp,PAGE_KERNEL ); +if (!qp->r_rq.wq) { ret =ERR_PTR (-ENOMEM ); goto bail_qp;
@@ -1090,7 +1108,7 @@ struct ib_qp *qib_create_qp(struct ib_pd dev =to_idev (ibpd->device); dd =dd_from_dev (dev); err =alloc_qpn (dd, &dev->qpn_table, init_attr->qp_type, - init_attr->port_num); + init_attr->port_num, gfp);if (err <0 ) { ret =ERR_PTR (err);vfree (qp->r_rq.wq);
Greg Kroah-Hartman
maintainerPATCH 253/342 IB/mlx5: Expose correct maximum number of CQE capacity
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
commit 9f17768611ebf81dfac69948dd12622b6f2e45fc upstream.
Maximum number of EQE capacity per CQ was mistakenly exposed as CQE. Fix that.
--- drivers/infiniband/hw/mlx5/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/hw/mlx5/main.c +1 -1
@@ -275,7 +275,7 @@ static int mlx5_ib_query_device(struct i props->max_sge =min (max_rq_sg, max_sq_sg); props->max_sge_rd = props->max_sge; props->max_cq =1 <<MLX5_CAP_GEN (mdev, log_max_cq); - props->max_cqe = (1 <<MLX5_CAP_GEN (mdev, log_max_eq_sz)) -1 ; + props->max_cqe = (1 <<MLX5_CAP_GEN (mdev, log_max_cq_sz)) -1 ; props->max_mr =1 <<MLX5_CAP_GEN (mdev, log_max_mkey); props->max_pd =1 <<MLX5_CAP_GEN (mdev, log_max_pd); props->max_qp_rd_atom =1 <<MLX5_CAP_GEN (mdev, log_max_ra_req_qp);
Greg Kroah-Hartman
maintainerPATCH 254/342 Thermal: initialize thermal zone device correctly
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Rui <[email protected]>
commit bb431ba26c5cd0a17c941ca6c3a195a3a6d5d461 upstream.
After thermal zone device registered, as we have not read any temperature before, thus tz->temperature should not be 0, which actually means 0C, and thermal trend is not available. In this case, we need specially handling for the first thermal_zone_device_update().
Both thermal core framework and step_wise governor is enhanced to handle this. And since the step_wise governor is the only one that uses trends, so it's the only thermal governor that needs to be updated.
--- drivers/thermal/step_wise.c | 17 +++++++++++++++-- drivers/thermal/thermal_core.c | 19 +++++++++++++++++-- drivers/thermal/thermal_core.h | 1 + include/linux/thermal.h | 3 +++ 4 files changed, 36 insertions(+), 4 deletions(-)
drivers/thermal/step_wise.c +15 -2
@@ -63,6 +63,19 @@ static unsigned long get_target_state(st next_target = instance->target;dev_dbg (&cdev->device,"cur_state=%ld\n" , cur_state); +if (!instance->initialized) { +if (throttle) { + next_target = (cur_state +1 ) >= instance->upper ? + instance->upper : + ((cur_state +1 ) < instance->lower ? + instance->lower : (cur_state +1 )); + }else { + next_target =THERMAL_NO_TARGET ; + } + +return next_target; + } +switch (trend) {case THERMAL_TREND_RAISING :if (throttle) {
@@ -149,7 +162,7 @@ static void thermal_zone_trip_update(strdev_dbg (&instance->cdev->device,"old_target=%d, target=%d\n" , old_target, (int )instance->target); -if (old_target == instance->target) +if (instance->initialized && old_target == instance->target)continue ;/* Activate a passive thermal instance */
@@ -161,7 +174,7 @@ static void thermal_zone_trip_update(str instance->target == THERMAL_NO_TARGET)update_passive_instance (tz, trip_type,-1 ); - + instance->initialized = true; instance->cdev->updated = false;/* cdev needs update */ }
drivers/thermal/thermal_core.c +17 -2
@@ -532,8 +532,22 @@ static void update_temperature(struct thmutex_unlock (&tz->lock);trace_thermal_temperature (tz); -dev_dbg (&tz->device,"last_temperature=%d, current_temperature=%d\n" , - tz->last_temperature, tz->temperature); +if (tz->last_temperature ==THERMAL_TEMP_INVALID ) +dev_dbg (&tz->device,"last_temperature N/A, current_temperature=%d\n" , + tz->temperature); +else +dev_dbg (&tz->device,"last_temperature=%d, current_temperature=%d\n" , + tz->last_temperature, tz->temperature); +} + +static void thermal_zone_device_reset (struct thermal_zone_device *tz) +{ +struct thermal_instance *pos; + + tz->temperature =THERMAL_TEMP_INVALID ; + tz->passive =0 ; +list_for_each_entry (pos, &tz->thermal_instances, tz_node) + pos->initialized = false; }void thermal_zone_device_update (struct thermal_zone_device *tz)
@@ -1900,6 +1914,7 @@ struct thermal_zone_device *thermal_zoneINIT_DELAYED_WORK (&(tz->poll_queue), thermal_zone_device_check); +thermal_zone_device_reset (tz);thermal_zone_device_update (tz);return tz;
drivers/thermal/thermal_core.h +1 -0
@@ -41,6 +41,7 @@ struct thermal_instance {struct thermal_zone_device *tz;struct thermal_cooling_device *cdev;int trip; +bool initialized;unsigned long upper;/* Highest cooling state for this trip point */ unsigned long lower;/* Lowest cooling state for this trip point */ unsigned long target;/* expected cooling state */
include/linux/thermal.h +3 -0
@@ -43,6 +43,9 @@/* Default weight of a bound cooling device */ #define THERMAL_WEIGHT_DEFAULT 0 +/* use value, which < 0K, to indicate an invalid/uninitialized temperature */ +#define THERMAL_TEMP_INVALID -274000 +/* Unit conversion macros */ #define DECI_KELVIN_TO_CELSIUS (t) ({ \ long _t = (t); \
Greg Kroah-Hartman
maintainerPATCH 255/342 Thermal: handle thermal zone device properly during system sleep
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Rui <[email protected]>
commit ff140fea847e1c2002a220571ab106c2456ed252 upstream.
Current thermal code does not handle system sleep well because
1. the cooling device cooling state may be changed during suspend
2. the previous temperature reading becomes invalid after resumed because it is got before system sleep
3. updating thermal zone device during suspending/resuming
is wrong because some devices may have already been suspended or may have not been resumed.
Thus, the proper way to do this is to cancel all thermal zone device update requirements during suspend/resume, and after all the devices have been resumed, reset and update every registered thermal zone devices.
This also fixes a regression introduced by:
Commit 19593a1fb1f6 ("ACPI / fan: convert to platform driver") Because, with above commit applied, all the fan devices are attached to the acpi_general_pm_domain, and they are turned on by the pm_domain automatically after resume, without the awareness of thermal core.
Reference: https://bugzilla.kernel.org/show_bug.cgi?id=78201
Reference: https://bugzilla.kernel.org/show_bug.cgi?id=91411
--- drivers/thermal/thermal_core.c | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+)
drivers/thermal/thermal_core.c +42 -0
@@ -37,6 +37,7 @@#include <linux/of.h> #include <net/netlink.h> #include <net/genetlink.h> +#include <linux/suspend.h> #define CREATE_TRACE_POINTS #include <trace/events/thermal.h>
@@ -59,6 +60,8 @@ static LIST_HEAD(thermal_governor_list);static DEFINE_MUTEX (thermal_list_lock);static DEFINE_MUTEX (thermal_governor_lock); +static atomic_t in_suspend; +static struct thermal_governor *def_governor;static struct thermal_governor *__find_governor (const char *name)
@@ -554,6 +557,9 @@ void thermal_zone_device_update(struct t {int count; +if (atomic_read (&in_suspend)) +return ; +if (!tz->ops->get_temp)return ;
@@ -2155,6 +2161,36 @@ static void thermal_unregister_governorsthermal_gov_power_allocator_unregister (); } +static int thermal_pm_notify (struct notifier_block *nb, +unsigned long mode,void *_unused) +{ +struct thermal_zone_device *tz; + +switch (mode) { +case PM_HIBERNATION_PREPARE : +case PM_RESTORE_PREPARE : +case PM_SUSPEND_PREPARE : +atomic_set (&in_suspend,1 ); +break ; +case PM_POST_HIBERNATION : +case PM_POST_RESTORE : +case PM_POST_SUSPEND : +atomic_set (&in_suspend,0 ); +list_for_each_entry (tz, &thermal_tz_list, node) { +thermal_zone_device_reset (tz); +thermal_zone_device_update (tz); + } +break ; +default : +break ; + } +return 0 ; +} + +static struct notifier_block thermal_pm_nb = { + .notifier_call = thermal_pm_notify, +}; +static int __init thermal_init (void ) {int result;
@@ -2175,6 +2211,11 @@ static int __init thermal_init(void)if (result) goto exit_netlink; + result =register_pm_notifier (&thermal_pm_nb); +if (result) +pr_warn ("Thermal: Can not register suspend notifier, return %d\n" , + result); +return 0 ; exit_netlink:
@@ -2194,6 +2235,7 @@ error: static void __exit thermal_exit(void) { +unregister_pm_notifier (&thermal_pm_nb);of_thermal_destroy_zones ();genetlink_exit ();class_unregister (&thermal_class);
Greg Kroah-Hartman
maintainerPATCH 256/342 Thermal: do thermal zone update after a cooling device registered
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen Yu <[email protected]>
commit 4511f7166a2deb5f7a578cf87fd2fe1ae83527e3 upstream.
When a new cooling device is registered, we need to update the thermal zone to set the new registered cooling device to a proper state.
This fixes a problem that the system is cool, while the fan devices are left running on full speed after boot, if fan device is registered after thermal zone device.
Here is the history of why current patch looks like this:
https://patchwork.kernel.org/patch/7273041/
Reference:https://bugzilla.kernel.org/show_bug.cgi?id=92431
--- drivers/thermal/thermal_core.c | 14 +++++++++++++- include/linux/thermal.h | 2 ++ 2 files changed, 15 insertions(+), 1 deletion(-)
drivers/thermal/thermal_core.c +13 -1
@@ -1341,6 +1341,7 @@ int thermal_zone_bind_cooling_device(strif (!result) {list_add_tail (&dev->tz_node, &tz->thermal_instances);list_add_tail (&dev->cdev_node, &cdev->thermal_instances); +atomic_set (&tz->need_update,1 ); }mutex_unlock (&cdev->lock);mutex_unlock (&tz->lock);
@@ -1450,6 +1451,7 @@ __thermal_cooling_device_register(struct const struct thermal_cooling_device_ops *ops) {struct thermal_cooling_device *cdev; +struct thermal_zone_device *pos =NULL ;int result;if (type &&strlen (type) >=THERMAL_NAME_LENGTH )
@@ -1494,6 +1496,12 @@ __thermal_cooling_device_register(struct/* Update binding information for 'this' new cdev */ bind_cdev (cdev); +mutex_lock (&thermal_list_lock); +list_for_each_entry (pos, &thermal_tz_list, node) +if (atomic_cmpxchg (&pos->need_update,1 ,0 )) +thermal_zone_device_update (pos); +mutex_unlock (&thermal_list_lock); +return cdev; }
@@ -1826,6 +1834,8 @@ struct thermal_zone_device *thermal_zone tz->trips = trips; tz->passive_delay = passive_delay; tz->polling_delay = polling_delay; +/* A new thermal zone needs to be updated anyway. */ +atomic_set (&tz->need_update,1 );dev_set_name (&tz->device,"thermal_zone%d" , tz->id); result =device_register (&tz->device);
@@ -1921,7 +1931,9 @@ struct thermal_zone_device *thermal_zoneINIT_DELAYED_WORK (&(tz->poll_queue), thermal_zone_device_check);thermal_zone_device_reset (tz); -thermal_zone_device_update (tz); +/* Update the new thermal zone and mark it as already updated. */ +if (atomic_cmpxchg (&tz->need_update,1 ,0 )) +thermal_zone_device_update (tz);return tz;
include/linux/thermal.h +2 -0
@@ -170,6 +170,7 @@ struct thermal_attr {* @forced_passive: If > 0, temperature at which to switch on all ACPI * processor cooling devices. Currently only used by the * step-wise governor. +* @need_update: if equals 1, thermal_zone_device_update needs to be invoked. * @ops: operations this &thermal_zone_device supports * @tzp: thermal zone parameters * @governor: pointer to the governor for this thermal zone
@@ -197,6 +198,7 @@ struct thermal_zone_device {int emul_temperature;int passive;unsigned int forced_passive; +atomic_t need_update;struct thermal_zone_device_ops *ops;struct thermal_zone_params *tzp;struct thermal_governor *governor;
Greg Kroah-Hartman
maintainerPATCH 257/342 hwmon: (dell-smm) Blacklist Dell Studio XPS 8000
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Leemhuis <[email protected]>
commit 6220f4ebd7b4db499238c2dc91268a9c473fd01c upstream.
Since Linux 4.0 the CPU fan speed is going up and down on Dell Studio XPS 8000 and 8100 for unknown reasons. The 8100 was already blacklisted in commit a4b45b25f18d ("hwmon: (dell-smm) Blacklist Dell Studio XPS 8100"). This patch blacklists the XPS 8000.
Without further debugging on the affected machine, it is not possible to find the problem. For more details see
https://bugzilla.kernel.org/show_bug.cgi?id=100121
--- drivers/hwmon/dell-smm-hwmon.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
drivers/hwmon/dell-smm-hwmon.c +11 -0
@@ -932,6 +932,17 @@ MODULE_DEVICE_TABLE(dmi, i8k_dmi_table);static struct dmi_system_id i8k_blacklist_dmi_table[]__initdata = { {/* +* CPU fan speed going up and down on Dell Studio XPS 8000 +* for unknown reasons. +*/ + .ident ="Dell Studio XPS 8000" , + .matches = { +DMI_EXACT_MATCH (DMI_SYS_VENDOR ,"Dell Inc." ), +DMI_EXACT_MATCH (DMI_PRODUCT_NAME ,"Studio XPS 8000" ), + }, + }, + { +/* * CPU fan speed going up and down on Dell Studio XPS 8100 * for unknown reasons. */
Greg Kroah-Hartman
maintainerPATCH 258/342 hwmon: (gpio-fan) Remove un-necessary speed_index lookup for thermal hook
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nishanth Menon <[email protected]>
commit 000e0949148382c4962489593a2f05504c2a6771 upstream.
Thermal hook gpio_fan_get_cur_state is only interested in knowing the current speed index that was setup in the system, this is already available as part of fan_data->speed_index which is always set by set_fan_speed. Using get_fan_speed_index is useful when we have no idea about the fan speed configuration (for example during fan_ctrl_init).
When thermal framework invokes gpio_fan_get_cur_state=>get_fan_speed_index via gpio_fan_get_cur_state especially in a polled configuration for thermal governor, we basically hog the i2c interface to the extent that other functions fail to get any traffic out :(.
Instead, just provide the last state set in the driver - since the gpio fan driver is responsible for the fan state immaterial of override, the fan_data->speed_index should accurately reflect the state.
--- drivers/hwmon/gpio-fan.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
drivers/hwmon/gpio-fan.c +1 -6
@@ -406,16 +406,11 @@ static int gpio_fan_get_cur_state(struct unsigned long *state) {struct gpio_fan_data *fan_data = cdev->devdata; -int r;if (!fan_data)return -EINVAL ; - r =get_fan_speed_index (fan_data); -if (r <0 ) -return r; - - *state = r; + *state = fan_data->speed_index;return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 259/342 hwmon: (ads1015) Handle negative conversion values correctly
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Rosin <[email protected]>
commit acc146943957d7418a6846f06e029b2c5e87e0d5 upstream.
Make the divisor signed as DIV_ROUND_CLOSEST is undefined for negative dividends when the divisor is unsigned.
--- drivers/hwmon/ads1015.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hwmon/ads1015.c +1 -1
@@ -126,7 +126,7 @@ static int ads1015_reg_to_mv(struct i2c_struct ads1015_data *data =i2c_get_clientdata (client);unsigned int pga = data->channel_data[channel].pga;int fullscale = fullscale_table[pga]; -const unsigned mask = data->id == ads1115 ?0x7fff :0x7ff0 ; +const int mask = data->id == ads1115 ?0x7fff :0x7ff0 ;return DIV_ROUND_CLOSEST (reg * fullscale, mask); }
Greg Kroah-Hartman
maintainerPATCH 260/342 cpufreq: pxa2xx: fix pxa_cpufreq_change_voltage prototype
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnd Bergmann <[email protected]>
commit fb2a24a1c6457d21df9fae0dd66b20c63ba56077 upstream.
There are two definitions of pxa_cpufreq_change_voltage, with slightly different prototypes after one of them had its argument marked 'const'. Now the other one (for !CONFIG_REGULATOR) produces a harmless warning:
drivers/cpufreq/pxa2xx-cpufreq.c: In function 'pxa_set_target':drivers/cpufreq/pxa2xx-cpufreq.c:291:36: warning: passing argument 1 of 'pxa_cpufreq_change_voltage' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]);
^
drivers/cpufreq/pxa2xx-cpufreq.c:205:12: note: expected 'struct pxa_freqs *' but argument is of type 'const struct pxa_freqs *'
static int pxa_cpufreq_change_voltage(struct pxa_freqs *pxa_freq)
^This changes the prototype in the same way as the other, which avoids the warning.
--- drivers/cpufreq/pxa2xx-cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/cpufreq/pxa2xx-cpufreq.c +1 -1
@@ -202,7 +202,7 @@ static void __init pxa_cpufreq_init_volt } }#else -static int pxa_cpufreq_change_voltage (struct pxa_freqs *pxa_freq) +static int pxa_cpufreq_change_voltage (const struct pxa_freqs *pxa_freq) {return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 261/342 cpufreq: Fix NULL reference crash while accessing policy->governor_data
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Viresh Kumar <[email protected]>
commit e4b133cc4b30b48d488e4e4fffb132f173ce4358 upstream.
There is a race discovered by Juri, where we are able to:
- create and read a sysfs file before policy->governor_data is being set to a non NULL value.
OR
- set policy->governor_data to NULL, and reading a file before being destroyed.
And so such a crash is reported:
Unable to handle kernel NULL pointer dereference at virtual address 0000000c pgd = edfc8000 [0000000c] *pgd=bfc8c835 Internal error: Oops: 17 [#1] SMP ARM Modules linked in: CPU: 4 PID: 1730 Comm: cat Not tainted 4.5.0-rc1+ #463 Hardware name: ARM-Versatile Express task: ee8e8480 ti: ee930000 task.ti: ee930000 PC is at show_ignore_nice_load_gov_pol+0x24/0x34 LR is at show+0x4c/0x60 pc : [<c058f1bc>] lr : [<c058ae88>] psr: a0070013
sp : ee931dd0 ip : ee931de0 fp : ee931ddc
r10: ee4bc290 r9 : 00001000 r8 : ef2cb000
r7 : ee4bc200 r6 : ef2cb000 r5 : c0af57b0 r4 : ee4bc2e0 r3 : 00000000 r2 : 00000000 r1 : c0928df4 r0 : ef2cb000
Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none
Control: 10c5387d Table: adfc806a DAC: 00000051 Process cat (pid: 1730, stack limit = 0xee930210)
Stack: (0xee931dd0 to 0xee932000)
1dc0: ee931dfc ee931de0 c058ae88 c058f1a4
1de0: edce3bc0 c07bfca4 edce3ac0 00001000 ee931e24 ee931e00 c01fcb90 c058ae48 1e00: 00000001 edce3bc0 00000000 00000001 ee931e50 ee8ff480 ee931e34 ee931e28 1e20: c01fb33c c01fcb0c ee931e8c ee931e38 c01a5210 c01fb314 ee931e9c ee931e48 1e40: 00000000 edce3bf0 befe4a00 ee931f78 00000000 00000000 000001e4 00000000 1e60: c00545a8 edce3ac0 00001000 00001000 befe4a00 ee931f78 00000000 00001000 1e80: ee931ed4 ee931e90 c01fbed8 c01a5038 ed085a58 00020000 00000000 00000000 1ea0: c0ad72e4 ee931f78 ee8ff488 ee8ff480 c077f3fc 00001000 befe4a00 ee931f78 1ec0: 00000000 00001000 ee931f44 ee931ed8 c017c328 c01fbdc4 00001000 00000000 1ee0: ee8ff480 00001000 ee931f44 ee931ef8 c017c65c c03deb10 ee931fac ee931f08 1f00: c0009270 c001f290 c0a8d968 ef2cb000 ef2cb000 ee8ff480 00000020 ee8ff480 1f20: ee8ff480 befe4a00 00001000 ee931f78 00000000 00000000 ee931f74 ee931f48 1f40: c017d1ec c017c2f8 c019c724 c019c684 ee8ff480 ee8ff480 00001000 befe4a00 1f60: 00000000 00000000 ee931fa4 ee931f78 c017d2a8 c017d160 00000000 00000000 1f80: 000a9f20 00001000 befe4a00 00000003 c000ffe4 ee930000 00000000 ee931fa8 1fa0: c000fe40 c017d264 000a9f20 00001000 00000003 befe4a00 00001000 00000000
Unable to handle kernel NULL pointer dereference at virtual address 0000000c
1fc0: 000a9f20 00001000 befe4a00 00000003 00000000 00000000 00000003 00000001 pgd = edfc4000
[0000000c] *pgd=bfcac835
1fe0: 00000000 befe49dc 000197f8 b6e35dfc 60070010 00000003 3065b49d 134ac2c9
[<c058f1bc>] (show_ignore_nice_load_gov_pol) from [<c058ae88>] (show+0x4c/0x60) [<c058ae88>] (show) from [<c01fcb90>] (sysfs_kf_seq_show+0x90/0xfc) [<c01fcb90>] (sysfs_kf_seq_show) from [<c01fb33c>] (kernfs_seq_show+0x34/0x38) [<c01fb33c>] (kernfs_seq_show) from [<c01a5210>] (seq_read+0x1e4/0x4e4) [<c01a5210>] (seq_read) from [<c01fbed8>] (kernfs_fop_read+0x120/0x1a0) [<c01fbed8>] (kernfs_fop_read) from [<c017c328>] (__vfs_read+0x3c/0xe0) [<c017c328>] (__vfs_read) from [<c017d1ec>] (vfs_read+0x98/0x104) [<c017d1ec>] (vfs_read) from [<c017d2a8>] (SyS_read+0x50/0x90) [<c017d2a8>] (SyS_read) from [<c000fe40>] (ret_fast_syscall+0x0/0x1c)
Code: e5903044 e1a00001 e3081df4 e34c1092 (e593300c) ---[ end trace 5994b9a5111f35ee ]---
Fix that by making sure, policy->governor_data is updated at the right places only.
--- drivers/cpufreq/cpufreq_governor.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
drivers/cpufreq/cpufreq_governor.c +8 -3
@@ -356,16 +356,18 @@ static int cpufreq_governor_init(structif (!have_governor_per_policy ()) cdata->gdbs_data = dbs_data; + policy->governor_data = dbs_data; + ret =sysfs_create_group (get_governor_parent_kobj (policy),get_sysfs_attr (dbs_data));if (ret) goto reset_gdbs_data; - policy->governor_data = dbs_data; -return 0 ; reset_gdbs_data: + policy->governor_data =NULL ; +if (!have_governor_per_policy ()) cdata->gdbs_data =NULL ; cdata->exit (dbs_data, !policy->governor->initialized);
@@ -386,16 +388,19 @@ static int cpufreq_governor_exit(structif (!cdbs->shared || cdbs->shared->policy)return -EBUSY ; - policy->governor_data =NULL ;if (!--dbs_data->usage_count) {sysfs_remove_group (get_governor_parent_kobj (policy),get_sysfs_attr (dbs_data)); + policy->governor_data =NULL ; +if (!have_governor_per_policy ()) cdata->gdbs_data =NULL ; cdata->exit (dbs_data, policy->governor->initialized ==1 );kfree (dbs_data); + }else { + policy->governor_data =NULL ; }free_common_dbs_info (policy, cdata);
Greg Kroah-Hartman
maintainerPATCH 262/342 seccomp: always propagate NO_NEW_PRIVS on tsync
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jann Horn <[email protected]>
commit 103502a35cfce0710909da874f092cb44823ca03 upstream.
Before this patch, a process with some permissive seccomp filter that was applied by root without NO_NEW_PRIVS was able to add more filters to itself without setting NO_NEW_PRIVS by setting the new filter from a throwaway thread with NO_NEW_PRIVS.
--- kernel/seccomp.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
kernel/seccomp.c +11 -11
@@ -316,24 +316,24 @@ static inline void seccomp_sync_threads(put_seccomp_filter (thread);smp_store_release (&thread->seccomp.filter, caller->seccomp.filter); + +/* +* Don't let an unprivileged task work around +* the no_new_privs restriction by creating +* a thread that sets it up, enters seccomp, +* then dies. +*/ +if (task_no_new_privs (caller)) +task_set_no_new_privs (thread); +/* * Opt the other thread into seccomp if needed. * As threads are considered to be trust-realm * equivalent (see ptrace_may_access), it is safe to * allow one thread to transition the other. */ -if (thread->seccomp.mode ==SECCOMP_MODE_DISABLED ) { -/* -* Don't let an unprivileged task work around -* the no_new_privs restriction by creating -* a thread that sets it up, enters seccomp, -* then dies. -*/ -if (task_no_new_privs (caller)) -task_set_no_new_privs (thread); - +if (thread->seccomp.mode ==SECCOMP_MODE_DISABLED )seccomp_assign_mode (thread,SECCOMP_MODE_FILTER ); - } } }
Greg Kroah-Hartman
maintainerPATCH 263/342 libceph: fix ceph_msg_revoke()
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ilya Dryomov <[email protected]>
commit 67645d7619738e51c668ca69f097cb90b5470422 upstream.
There are a number of problems with revoking a "was sending" message:
(1) We never make any attempt to revoke data - only kvecs contibute to con->out_skip. However, once the header (envelope) is written to the socket, our peer learns data_len and sets itself to expect at least data_len bytes to follow front or front+middle. If ceph_msg_revoke() is called while the messenger is sending message's data portion, anything we send after that call is counted by the OSD towards the now revoked message's data portion. The effects vary, the most common one is the eventual hang - higher layers get stuck waiting for the reply to the message that was sent out after ceph_msg_revoke() returned and treated by the OSD as a bunch of data bytes. This is what Matt ran into.
(2) Flat out zeroing con->out_kvec_bytes worth of bytes to handle kvecs is wrong. If ceph_msg_revoke() is called before the tag is sent out or while the messenger is sending the header, we will get a connection reset, either due to a bad tag (0 is not a valid tag) or a bad header CRC, which kind of defeats the purpose of revoke. Currently the kernel client refuses to work with header CRCs disabled, but that will likely change in the future, making this even worse.
(3) con->out_skip is not reset on connection reset, leading to one or more spurious connection resets if we happen to get a real one between con->out_skip is set in ceph_msg_revoke() and before it's cleared in write_partial_skip().
Fixing (1) and (3) is trivial. The idea behind fixing (2) is to never zero the tag or the header, i.e. send out tag+header regardless of when ceph_msg_revoke() is called. That way the header is always correct, no unnecessary resets are induced and revoke stands ready for disabled CRCs. Since ceph_msg_revoke() rips out con->out_msg, introduce a new "message out temp" and copy the header into it before sending.
--- include/linux/ceph/messenger.h | 2 - net/ceph/messenger.c | 78 +++++++++++++++++++++++++++++++---------- 2 files changed, 60 insertions(+), 20 deletions(-)
include/linux/ceph/messenger.h +1 -1
@@ -220,6 +220,7 @@ struct ceph_connection {struct ceph_entity_addr actual_peer_addr;/* message out temps */ +struct ceph_msg_header out_hdr;struct ceph_msg *out_msg;/* sending message (== tail of out_sent) */ bool out_msg_done;
@@ -229,7 +230,6 @@ struct ceph_connection {int out_kvec_left;/* kvec's left in out_kvec */ int out_skip;/* skip this many bytes */ int out_kvec_bytes;/* total bytes left */ -bool out_kvec_is_msg;/* kvec refers to out_msg */ int out_more;/* there is more data after the kvecs */ __le64 out_temp_ack;/* for writing an ack */ struct ceph_timespec out_temp_keepalive2;/* for writing keepalive2
net/ceph/messenger.c +59 -19
165 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 264/342 libceph: dont bail early from try_read() when skipping a message
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ilya Dryomov <[email protected]>
commit e7a88e82fe380459b864e05b372638aeacb0f52d upstream.
The contract between try_read() and try_write() is that when called each processes as much data as possible. When instructed by osd_client to skip a message, try_read() is violating this contract by returning after receiving and discarding a single message instead of checking for more. try_write() then gets a chance to write out more requests, generating more replies/skips for try_read() to handle, forcing the messenger into a starvation loop.
--- net/ceph/messenger.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/ceph/messenger.c +2 -2
@@ -2340,7 +2340,7 @@ static int read_partial_message(struct c con->in_base_pos = -front_len - middle_len - data_len -sizeof (m->footer); con->in_tag =CEPH_MSGR_TAG_READY ; -return 0 ; +return 1 ; }else if ((s64 )seq - (s64 )con->in_seq >1 ) {pr_err ("read_partial_message bad seq %lld expected %lld\n" , seq, con->in_seq +1 );
@@ -2366,7 +2366,7 @@ static int read_partial_message(struct csizeof (m->footer); con->in_tag =CEPH_MSGR_TAG_READY ; con->in_seq++; -return 0 ; +return 1 ; }BUG_ON (!con->in_msg);
Greg Kroah-Hartman
maintainerPATCH 265/342 libceph: use the right footer size when skipping a message
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ilya Dryomov <[email protected]>
commit dbc0d3caff5b7591e0cf8e34ca686ca6f4479ee1 upstream.
ceph_msg_footer is 21 bytes long, while ceph_msg_footer_old is only 13. Don't skip too much when CEPH_FEATURE_MSG_AUTH isn't negotiated.
--- net/ceph/messenger.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
net/ceph/messenger.c +9 -2
@@ -1200,6 +1200,13 @@ static bool ceph_msg_data_advance(structreturn new_piece; } +static size_t sizeof_footer (struct ceph_connection *con) +{ +return (con->peer_features &CEPH_FEATURE_MSG_AUTH ) ? +sizeof (struct ceph_msg_footer ) : +sizeof (struct ceph_msg_footer_old ); +} +static void prepare_message_data (struct ceph_msg *msg,u32 data_len) {BUG_ON (!msg);
@@ -2338,7 +2345,7 @@ static int read_partial_message(struct cceph_pr_addr (&con->peer_addr.in_addr), seq, con->in_seq + 1); con->in_base_pos = -front_len - middle_len - data_len - -sizeof (m->footer); +sizeof_footer (con); con->in_tag =CEPH_MSGR_TAG_READY ;return 1 ; }else if ((s64 )seq - (s64 )con->in_seq >1 ) {
@@ -2363,7 +2370,7 @@ static int read_partial_message(struct c/* skip this message */ dout ("alloc_msg said skip message\n" ); con->in_base_pos = -front_len - middle_len - data_len - -sizeof (m->footer); +sizeof_footer (con); con->in_tag =CEPH_MSGR_TAG_READY ; con->in_seq++;return 1 ;
Greg Kroah-Hartman
maintainerPATCH 266/342 libceph: dont spam dmesg with stray reply warnings
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ilya Dryomov <[email protected]>
commit cd8140c673d9ba9be3591220e1b2226d9e1e40d3 upstream.
Commit d15f9d694b77 ("libceph: check data_len in ->alloc_msg()") mistakenly bumped the log level on the "tid %llu unknown, skipping" message. Turn it back into a dout() - stray replies are perfectly normal when OSDs flap, crash, get killed for testing purposes, etc.
--- net/ceph/osd_client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/ceph/osd_client.c +2 -2
@@ -2843,8 +2843,8 @@ static struct ceph_msg *get_reply(structmutex_lock (&osdc->request_mutex); req =__lookup_request (osdc, tid);if (!req) { -pr_warn ("%s osd%d tid %llu unknown, skipping\n" , - __func__, osd->o_osd, tid); +dout ("%s osd%d tid %llu unknown, skipping\n" , __func__, + osd->o_osd, tid); m =NULL ; *skip =1 ; goto out;
Greg Kroah-Hartman
maintainerPATCH 267/342 sd: Optimal I/O size is in bytes, not sectors
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Martin K. Petersen <[email protected]>
commit d0eb20a863ba7dc1d3f4b841639671f134560be2 upstream.
Commit ca369d51b3e1 ("block/sd: Fix device-imposed transfer length limits") accidentally switched optimal I/O size reporting from bytes to block layer sectors.
--- drivers/scsi/sd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/sd.c +1 -1
@@ -2893,7 +2893,7 @@ static int sd_revalidate_disk(struct gen sdkp->opt_xfer_blocks <= SD_DEF_XFER_BLOCKS && sdkp->opt_xfer_blocks * sdp->sector_size >= PAGE_CACHE_SIZE) rw_max = q->limits.io_opt = -logical_to_sectors (sdp, sdkp->opt_xfer_blocks); + sdkp->opt_xfer_blocks * sdp->sector_size; else rw_max =BLK_DEF_MAX_SECTORS ;
Greg Kroah-Hartman
maintainerPATCH 268/342 Staging: speakup: Fix getting port information
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Samuel Thibault <[email protected]>
commit 327b882d3bcc1fba82dbd39b5cf5a838c81218e2 upstream.
Commit f79b0d9c223c ("staging: speakup: Fixed warning <linux/serial.h> instead of <asm/serial.h>") broke the port information in the speakup
driver: SERIAL_PORT_DFNS only gets defined if asm/serial.h is included, and no other header includes asm/serial.h.
We here make sure serialio.c does get the arch-specific definition of SERIAL_PORT_DFNS from asm/serial.h, if any.
Along the way, this makes sure that we do have information for the requested serial port number (index)
--- drivers/staging/speakup/serialio.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
drivers/staging/speakup/serialio.c +12 -1
@@ -6,6 +6,11 @@#include "spk_priv.h" #include "serialio.h" +#include <linux/serial_core.h> +/* WARNING: Do not change this to <linux/serial.h> without testing that +* SERIAL_PORT_DFNS does get defined to the appropriate value. */ +#include <asm/serial.h> +#ifndef SERIAL_PORT_DFNS #define SERIAL_PORT_DFNS #endif
@@ -23,9 +28,15 @@ const struct old_serial_port *spk_serialint baud =9600 , quot =0 ;unsigned int cval =0 ;int cflag =CREAD |HUPCL |CLOCAL |B9600 |CS8 ; -const struct old_serial_port *ser = rs_table + index; +const struct old_serial_port *ser;int err; +if (index >=ARRAY_SIZE (rs_table)) { +pr_info ("no port info for ttyS%d\n" , index); +return NULL ; + } + ser = rs_table + index; +/* Divisor, bytesize and parity */ quot = ser->baud_base / baud; cval = cflag & (CSIZE |CSTOPB );
Greg Kroah-Hartman
maintainerPATCH 269/342 Revert "Staging: panel: usleep_range is preferred over udelay"
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sudip Mukherjee <[email protected]>
commit b64a1cbef6df47c986ad622b5b2e4d3d1940070c upstream.
This reverts commit ebd43516d3879f882a403836bba8bc5791f26a28.
We should not be sleeping inside spin_lock.
drivers/staging/panel/panel.c +15 -19
@@ -825,8 +825,7 @@ static void lcd_write_cmd_s(int cmd)lcd_send_serial (0x1F );/* R/W=W, RS=0 */ lcd_send_serial (cmd &0x0F );lcd_send_serial ((cmd >>4 ) &0x0F ); -/* the shortest command takes at least 40 us */ -usleep_range (40 ,100 ); +udelay (40 );/* the shortest command takes at least 40 us */ spin_unlock_irq (&pprt_lock); }
@@ -837,8 +836,7 @@ static void lcd_write_data_s(int data)lcd_send_serial (0x5F );/* R/W=W, RS=1 */ lcd_send_serial (data &0x0F );lcd_send_serial ((data >>4 ) &0x0F ); -/* the shortest data takes at least 40 us */ -usleep_range (40 ,100 ); +udelay (40 );/* the shortest data takes at least 40 us */ spin_unlock_irq (&pprt_lock); }
@@ -848,20 +846,19 @@ static void lcd_write_cmd_p8(int cmd)spin_lock_irq (&pprt_lock);/* present the data to the data port */ w_dtr (pprt, cmd); -/* maintain the data during 20 us before the strobe */ -usleep_range (20 ,100 ); +udelay (20 );/* maintain the data during 20 us before the strobe */ bits.e =BIT_SET ; bits.rs =BIT_CLR ; bits.rw =BIT_CLR ;set_ctrl_bits (); -usleep_range (40 ,100 );/* maintain the strobe during 40 us */ +udelay (40 );/* maintain the strobe during 40 us */ bits.e =BIT_CLR ;set_ctrl_bits (); -usleep_range (120 ,500 );/* the shortest command takes at least 120 us */ +udelay (120 );/* the shortest command takes at least 120 us */ spin_unlock_irq (&pprt_lock); }
@@ -871,20 +868,19 @@ static void lcd_write_data_p8(int data)spin_lock_irq (&pprt_lock);/* present the data to the data port */ w_dtr (pprt, data); -/* maintain the data during 20 us before the strobe */ -usleep_range (20 ,100 ); +udelay (20 );/* maintain the data during 20 us before the strobe */ bits.e =BIT_SET ; bits.rs =BIT_SET ; bits.rw =BIT_CLR ;set_ctrl_bits (); -usleep_range (40 ,100 );/* maintain the strobe during 40 us */ +udelay (40 );/* maintain the strobe during 40 us */ bits.e =BIT_CLR ;set_ctrl_bits (); -usleep_range (45 ,100 );/* the shortest data takes at least 45 us */ +udelay (45 );/* the shortest data takes at least 45 us */ spin_unlock_irq (&pprt_lock); }
@@ -894,7 +890,7 @@ static void lcd_write_cmd_tilcd(int cmd)spin_lock_irq (&pprt_lock);/* present the data to the control port */ w_ctr (pprt, cmd); -usleep_range (60 ,120 ); +udelay (60 );spin_unlock_irq (&pprt_lock); }
@@ -904,7 +900,7 @@ static void lcd_write_data_tilcd(int data)spin_lock_irq (&pprt_lock);/* present the data to the data port */ w_dtr (pprt, data); -usleep_range (60 ,120 ); +udelay (60 );spin_unlock_irq (&pprt_lock); }
@@ -947,7 +943,7 @@ static void lcd_clear_fast_s(void)lcd_send_serial (0x5F );/* R/W=W, RS=1 */ lcd_send_serial (' ' &0x0F );lcd_send_serial ((' ' >>4 ) &0x0F ); -usleep_range (40 ,100 );/* the shortest data takes at least 40 us */ +udelay (40 );/* the shortest data takes at least 40 us */ }spin_unlock_irq (&pprt_lock);
@@ -971,7 +967,7 @@ static void lcd_clear_fast_p8(void)w_dtr (pprt,' ' );/* maintain the data during 20 us before the strobe */ -usleep_range (20 ,100 ); +udelay (20 ); bits.e =BIT_SET ; bits.rs =BIT_SET ;
@@ -979,13 +975,13 @@ static void lcd_clear_fast_p8(void)set_ctrl_bits ();/* maintain the strobe during 40 us */ -usleep_range (40 ,100 ); +udelay (40 ); bits.e =BIT_CLR ;set_ctrl_bits ();/* the shortest data takes at least 45 us */ -usleep_range (45 ,100 ); +udelay (45 ); }spin_unlock_irq (&pprt_lock);
@@ -1007,7 +1003,7 @@ static void lcd_clear_fast_tilcd(void)for (pos =0 ; pos < lcd.height * lcd.hwidth; pos++) {/* present the data to the data port */ w_dtr (pprt,' ' ); -usleep_range (60 ,120 ); +udelay (60 ); }spin_unlock_irq (&pprt_lock);
Greg Kroah-Hartman
maintainerPATCH 270/342 cdc-acm:exclude Samsung phone 04e8:685d
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Neukum <[email protected]>
commit e912e685f372ab62a2405a1acd923597f524e94a upstream.
This phone needs to be handled by a specialised firmware tool and is reported to crash irrevocably if cdc-acm takes it.
--- drivers/usb/class/cdc-acm.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/usb/class/cdc-acm.c +5 -0
@@ -1841,6 +1841,11 @@ static const struct usb_device_id acm_id },#endif +/*Samsung phone in firmware update mode */ + { USB_DEVICE(0x04e8, 0x685d), + .driver_info =IGNORE_DEVICE , + }, + /* Exclude Infineon Flash Loader utility */ { USB_DEVICE(0x058b, 0x0041), .driver_info = IGNORE_DEVICE,
Greg Kroah-Hartman
maintainerPATCH 271/342 perf stat: Do not clean events private stats
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiri Olsa <[email protected]>
commit 3f416f22d1e21709a631189ba169f76fd267b374 upstream.
Mel reported stddev reporting was broken due to following commit:
106a94a0f8c2 ("perf stat: Introduce read_counters function")
This commit merged interval and overall counters reading into single read_counters function.
The old interval code cleaned the stddev data for some reason (it's never displayed in interval mode) and the mentioned commit kept on cleaning the stddev data in merged function, which resulted in the stddev not being displayed.
Removing the wrong stddev data cleanup init_stats call.
--- tools/perf/util/stat.c | 1 - 1 file changed, 1 deletion(-)
tools/perf/util/stat.c +0 -1
@@ -310,7 +310,6 @@ int perf_stat_process_counter(struct perint i, ret; aggr->val = aggr->ena = aggr->run =0 ; -init_stats (ps->res_stats);if (counter->per_pkg)zero_per_pkg (counter);
Greg Kroah-Hartman
maintainerPATCH 272/342 tick/nohz: Set the correct expiry when switching to nohz/lowres mode
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wanpeng Li <[email protected]>
commit 1ca8ec532fc2d986f1f4a319857bb18e0c9739b4 upstream.
commit 0ff53d096422 sets the next tick interrupt to the last jiffies update, i.e. in the past, because the forward operation is invoked before the set operation. There is no resulting damage (yet), but we get an extra pointless tick interrupt.
Revert the order so we get the next tick interrupt in the future.
--- kernel/time/tick-sched.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/time/tick-sched.c +2 -2
@@ -977,9 +977,9 @@ static void tick_nohz_switch_to_nohz(voi/* Get the next period */ next =tick_init_jiffy_update (); -hrtimer_forward_now (&ts->sched_timer, tick_period);hrtimer_set_expires (&ts->sched_timer, next); -tick_program_event (next,1 ); +hrtimer_forward_now (&ts->sched_timer, tick_period); +tick_program_event (hrtimer_get_expires (&ts->sched_timer),1 );tick_nohz_activate (ts,NOHZ_MODE_LOWRES ); }
Greg Kroah-Hartman
maintainerPATCH 273/342 rfkill: fix rfkill_fop_read wait_event usage
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
commit 6736fde9672ff6717ac576e9bba2fd5f3dfec822 upstream.
The code within wait_event_interruptible() is called with !TASK_RUNNING, so mustn't call any functions that can sleep, like mutex_lock().
Since we re-check the list_empty() in a loop after the wait, it's safe to simply use list_empty() without locking.
This bug has existed forever, but was only discovered now because all userspace implementations, including the default 'rfkill' tool, use poll() or select() to get a readable fd before attempting to read.
--- net/rfkill/core.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-)
net/rfkill/core.c +4 -12
@@ -1095,17 +1095,6 @@ static unsigned int rfkill_fop_poll(strureturn res; } -static bool rfkill_readable (struct rfkill_data *data) -{ -bool r; - -mutex_lock (&data->mtx); - r = !list_empty (&data->events); -mutex_unlock (&data->mtx); - -return r; -} -static ssize_t rfkill_fop_read (struct file *file,char __user *buf,size_t count,loff_t *pos) {
@@ -1122,8 +1111,11 @@ static ssize_t rfkill_fop_read(struct fi goto out; }mutex_unlock (&data->mtx); +/* since we re-check and it just compares pointers, +* using !list_empty() without locking isn't a problem +*/ ret =wait_event_interruptible (data->read_wait, -rfkill_readable (data)); + !list_empty (&data->events));mutex_lock (&data->mtx);if (ret)
Greg Kroah-Hartman
maintainerPATCH 274/342 mac80211: Requeue work after scan complete for all VIF types.
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sachin Kulkarni <[email protected]>
commit 4fa11ec726a32ea6dd768dbb2e2af3453a98ec0a upstream.
During a sw scan ieee80211_iface_work ignores work items for all vifs. However after the scan complete work is requeued only for STA, ADHOC and MESH iftypes.
This occasionally results in event processing getting delayed/not processed for iftype AP when it coexists with a STA. This can result in data halt and eventually disconnection on the AP interface.
--- net/mac80211/ibss.c | 1 - net/mac80211/mesh.c | 11 ----------- net/mac80211/mesh.h | 4 ---- net/mac80211/mlme.c | 2 -- net/mac80211/scan.c | 12 +++++++++++- 5 files changed, 11 insertions(+), 19 deletions(-)
net/mac80211/ibss.c +0 -1
@@ -1732,7 +1732,6 @@ void ieee80211_ibss_notify_scan_completeif (sdata->vif.type !=NL80211_IFTYPE_ADHOC )continue ; sdata->u.ibss.last_scan_completed = jiffies; -ieee80211_queue_work (&local->hw, &sdata->work); }mutex_unlock (&local->iflist_mtx); }
net/mac80211/mesh.c +0 -11
@@ -1370,17 +1370,6 @@ out:sdata_unlock (sdata); } -void ieee80211_mesh_notify_scan_completed (struct ieee80211_local *local) -{ -struct ieee80211_sub_if_data *sdata; - -rcu_read_lock (); -list_for_each_entry_rcu (sdata, &local->interfaces, list) -if (ieee80211_vif_is_mesh (&sdata->vif) && -ieee80211_sdata_running (sdata)) -ieee80211_queue_work (&local->hw, &sdata->work); -rcu_read_unlock (); -}void ieee80211_mesh_init_sdata (struct ieee80211_sub_if_data *sdata) {
net/mac80211/mesh.h +0 -4
@@ -362,14 +362,10 @@ static inline bool mesh_path_sel_is_hwmp return sdata->u.mesh.mesh_pp_id == IEEE80211_PATH_PROTOCOL_HWMP; } -void ieee80211_mesh_notify_scan_completed (struct ieee80211_local *local); -void mesh_path_flush_by_iface (struct ieee80211_sub_if_data *sdata);void mesh_sync_adjust_tbtt (struct ieee80211_sub_if_data *sdata);void ieee80211s_stop (void );#else -static inline void -ieee80211_mesh_notify_scan_completed (struct ieee80211_local *local) {}static inline bool mesh_path_sel_is_hwmp (struct ieee80211_sub_if_data *sdata) {return false; }static inline void mesh_path_flush_by_iface (struct ieee80211_sub_if_data *sdata)
net/mac80211/mlme.c +0 -2
@@ -4003,8 +4003,6 @@ static void ieee80211_restart_sta_timer(if (!ieee80211_hw_check (&sdata->local->hw,CONNECTION_MONITOR ))ieee80211_queue_work (&sdata->local->hw, &sdata->u.mgd.monitor_work); -/* and do all the other regular work too */ -ieee80211_queue_work (&sdata->local->hw, &sdata->work); } }
net/mac80211/scan.c +11 -1
@@ -314,6 +314,7 @@ static void __ieee80211_scan_completed(sbool was_scanning = local->scanning;struct cfg80211_scan_request *scan_req;struct ieee80211_sub_if_data *scan_sdata; +struct ieee80211_sub_if_data *sdata;lockdep_assert_held (&local->mtx);
@@ -373,7 +374,16 @@ static void __ieee80211_scan_completed(sieee80211_mlme_notify_scan_completed (local);ieee80211_ibss_notify_scan_completed (local); -ieee80211_mesh_notify_scan_completed (local); + +/* Requeue all the work that might have been ignored while +* the scan was in progress; if there was none this will +* just be a no-op for the particular interface. +*/ +list_for_each_entry_rcu (sdata, &local->interfaces, list) { +if (ieee80211_sdata_running (sdata)) +ieee80211_queue_work (&sdata->local->hw, &sdata->work); + } +if (was_scanning)ieee80211_start_next_roc (local); }
Greg Kroah-Hartman
maintainerPATCH 275/342 workqueue: handle NUMA_NO_NODE for unbound pool_workqueue lookup
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <[email protected]>
commit d6e022f1d207a161cd88e08ef0371554680ffc46 upstream.
When looking up the pool_workqueue to use for an unbound workqueue, workqueue assumes that the target CPU is always bound to a valid NUMA node. However, currently, when a CPU goes offline, the mapping is destroyed and cpu_to_node() returns NUMA_NO_NODE.
This has always been broken but hasn't triggered often enough before 874bbfe600a6 ("workqueue: make sure delayed work run in local cpu"). After the commit, workqueue forcifully assigns the local CPU for delayed work items without explicit target CPU to fix a different issue. This widens the window where CPU can go offline while a delayed work item is pending causing delayed work items dispatched with target CPU set to an already offlined CPU. The resulting NUMA_NO_NODE mapping makes workqueue try to queue the work item on a NULL pool_workqueue and thus crash.
While 874bbfe600a6 has been reverted for a different reason making the bug less visible again, it can still happen. Fix it by mapping NUMA_NO_NODE to the default pool_workqueue from unbound_pwq_by_node(). This is a temporary workaround. The long term solution is keeping CPU -> NODE mapping stable across CPU off/online cycles which is being worked on.
--- kernel/workqueue.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
kernel/workqueue.c +10 -0
@@ -568,6 +568,16 @@ static struct pool_workqueue *unbound_pw int node) {assert_rcu_or_wq_mutex_or_pool_mutex (wq); + +/* +* XXX: @node can be NUMA_NO_NODE if CPU goes offline while a +* delayed item is pending. The plan is to keep CPU -> NODE +* mapping valid and stable across CPU on/offlines. Once that +* happens, this workaround can be removed. +*/ +if (unlikely (node ==NUMA_NO_NODE )) +return wq->dfl_pwq; +return rcu_dereference_raw (wq->numa_pwq_tbl[node]); }
Greg Kroah-Hartman
maintainerPATCH 276/342 Revert "workqueue: make sure delayed work run in local cpu"
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <[email protected]>
commit 041bd12e272c53a35c54c13875839bcb98c999ce upstream.
This reverts commit 874bbfe600a660cba9c776b3957b1ce393151b76.
Workqueue used to implicity guarantee that work items queued without explicit CPU specified are put on the local CPU. Recent changes in timer broke the guarantee and led to vmstat breakage which was fixed by 176bed1de5bf ("vmstat: explicitly schedule per-cpu work on the CPU we need it to run on").
vmstat is the most likely to expose the issue and it's quite possible that there are other similar problems which are a lot more difficult to trigger. As a preventive measure, 874bbfe600a6 ("workqueue: make sure delayed work run in local cpu") was applied to restore the local CPU guarnatee. Unfortunately, the change exposed a bug in timer code which got fixed by 22b886dd1018 ("timers: Use proper base migration in add_timer_on()"). Due to code restructuring, the commit couldn't be backported beyond certain point and stable kernels which only had 874bbfe600a6 started crashing.
The local CPU guarantee was accidental more than anything else and we want to get rid of it anyway. As, with the vmstat case fixed, 874bbfe600a6 is causing more problems than it's fixing, it has been decided to take the chance and officially break the guarantee by reverting the commit. A debug feature will be added to force foreign CPU assignment to expose cases relying on the guarantee and fixes for the individual cases will be backported to stable as necessary.
--- kernel/workqueue.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
kernel/workqueue.c +4 -4
@@ -1468,13 +1468,13 @@ static void __queue_delayed_work(int cputimer_stats_timer_set_start_info (&dwork->timer); dwork->wq = wq; -/* timer isn't guaranteed to run in this cpu, record earlier */ -if (cpu ==WORK_CPU_UNBOUND ) - cpu =raw_smp_processor_id (); dwork->cpu = cpu; timer->expires = jiffies + delay; -add_timer_on (timer, cpu); +if (unlikely (cpu !=WORK_CPU_UNBOUND )) +add_timer_on (timer, cpu); +else +add_timer (timer); }/**
Greg Kroah-Hartman
maintainerPATCH 277/342 ALSA: hda - Apply clock gate workaround to Skylake, too
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
commit 7e31a0159461818a1bda49662921b98a29c1187b upstream.
Some Skylake machines show the codec probe errors in certain
situations, e.g. HP Z240 desktop fails to probe the onboard Realtek
codec at reloading the snd-hda-intel module like:
snd_hda_intel 0000:00:1f.3: spurious response 0x200:0x2, last cmd=0x000000 snd_hda_intel 0000:00:1f.3: azx_get_response timeout, switching to polling mode: lastcmd=0x000f0000 snd_hda_intel 0000:00:1f.3: No response from codec, disabling MSI: last cmd=0x000f0000 snd_hda_intel 0000:00:1f.3: Codec #0 probe error; disabling it...
hdaudio hdaudioC0D2: no AFG or MFG node found
snd_hda_intel 0000:00:1f.3: no codecs initialized
Also, HP G470 G3 suffers from the similar problem, as reported in bugzilla below. On this machine, the codec probe error appears even at a fresh boot.
As Libin suggested, the same workaround used for Broxton in the commit [6639484ddaf6: ALSA: hda - disable dynamic clock gating on Broxton
before reset] can be applied for Skylake in order to fix this problem.
The Intel HW team also confirmed that this is needed for SKL.
This patch makes the workaround applied to both SKL and BXT platforms. The referred macros are moved and one superfluous macro (IS_BROXTON()) is another one (IS_BXT()) as well.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=112731
--- sound/pci/hda/hda_intel.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
sound/pci/hda/hda_intel.c +7 -9
@@ -357,7 +357,10 @@ enum { ((pci)->device == 0x0d0c) || \ ((pci)->device == 0x160c)) -#define IS_BROXTON (pci) ((pci)->device == 0x5a98) +#define IS_SKL (pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170) +#define IS_SKL_LP (pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70) +#define IS_BXT (pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) +#define IS_SKL_PLUS (pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci))static char *driver_short_names[] = { [AZX_DRIVER_ICH ] ="HDA Intel" ,
@@ -534,13 +537,13 @@ static void hda_intel_init_chip(struct aif (chip->driver_caps &AZX_DCAPS_I915_POWERWELL )snd_hdac_set_codec_wakeup (bus, true); -if (IS_BROXTON (pci)) { +if (IS_SKL_PLUS (pci)) {pci_read_config_dword (pci,INTEL_HDA_CGCTL , &val); val = val & ~INTEL_HDA_CGCTL_MISCBDCGE ;pci_write_config_dword (pci,INTEL_HDA_CGCTL , val); }azx_init_chip (chip, full_reset); -if (IS_BROXTON (pci)) { +if (IS_SKL_PLUS (pci)) {pci_read_config_dword (pci,INTEL_HDA_CGCTL , &val); val = val |INTEL_HDA_CGCTL_MISCBDCGE ;pci_write_config_dword (pci,INTEL_HDA_CGCTL , val);
@@ -549,7 +552,7 @@ static void hda_intel_init_chip(struct asnd_hdac_set_codec_wakeup (bus, false);/* reduce dma latency to avoid noise */ -if (IS_BROXTON (pci)) +if (IS_BXT (pci))bxt_reduce_dma_latency (chip); }
@@ -971,11 +974,6 @@ static int azx_resume(struct device *dev/* put codec down to D3 at hibernation for Intel SKL+; * otherwise BIOS may still access the codec and screw up the driver */ -#define IS_SKL (pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170) -#define IS_SKL_LP (pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70) -#define IS_BXT (pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) -#define IS_SKL_PLUS (pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci)) -static int azx_freeze_noirq (struct device *dev) {struct pci_dev *pci =to_pci_dev (dev);
Greg Kroah-Hartman
maintainerPATCH 278/342 ALSA: hda - Fixing background noise on Dell Inspiron 3162
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kai-Heng Feng <[email protected]>
commit 3b43b71f05d3ecd01c4116254666d9492301697d upstream.
After login to the desktop on Dell Inspiron 3162,
there's a very loud background noise comes from the builtin speaker. The noise does not go away even if the speaker is muted.
The noise disappears after using the aamix fixup.
Codec: Realtek ALC3234
Address: 0
AFG Function Id: 0x1 (unsol 1)
Vendor Id: 0x10ec0255
Subsystem Id: 0x10280725
Revision Id: 0x100002
No Modem Function Group found--- sound/pci/hda/patch_realtek.c | 8 ++++++++ 1 file changed, 8 insertions(+)
sound/pci/hda/patch_realtek.c +8 -0
@@ -4749,6 +4749,7 @@ enum {ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE ,ALC293_FIXUP_LENOVO_SPK_NOISE ,ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY , + ALC255_FIXUP_DELL_SPK_NOISE, }; static const struct hda_fixup alc269_fixups[] = {
@@ -5368,6 +5369,12 @@ static const struct hda_fixup alc269_fix .type = HDA_FIXUP_FUNC, .v.func = alc233_fixup_lenovo_line2_mic_hotkey, }, + [ALC255_FIXUP_DELL_SPK_NOISE] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_disable_aamix, + .chained = true, + .chain_id =ALC255_FIXUP_DELL1_MIC_NO_PRESENCE + }, };static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -5410,6 +5417,7 @@ static const struct snd_pci_quirk alc269SND_PCI_QUIRK (0x1028 ,0x06df ,"Dell" ,ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK ),SND_PCI_QUIRK (0x1028 ,0x06e0 ,"Dell" ,ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK ),SND_PCI_QUIRK (0x1028 ,0x0704 ,"Dell XPS 13" ,ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE ), +SND_PCI_QUIRK (0x1028 ,0x0725 ,"Dell Inspiron 3162" ,ALC255_FIXUP_DELL_SPK_NOISE ),SND_PCI_QUIRK (0x1028 ,0x164a ,"Dell" ,ALC293_FIXUP_DELL1_MIC_NO_PRESENCE ),SND_PCI_QUIRK (0x1028 ,0x164b ,"Dell" ,ALC293_FIXUP_DELL1_MIC_NO_PRESENCE ), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
Greg Kroah-Hartman
maintainerPATCH 279/342 target: Fix LUN_RESET active I/O handling for ACK_KREF
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicholas Bellinger <[email protected]>
commit febe562c20dfa8f33bee7d419c6b517986a5aa33 upstream.
This patch fixes a NULL pointer se_cmd->cmd_kref < 0 refcount bug during TMR LUN_RESET with active se_cmd I/O, that can be triggered during se_cmd descriptor shutdown + release via core_tmr_drain_state_list() code.
To address this bug, add common __target_check_io_state() helper for ABORT_TASK + LUN_RESET w/ CMD_T_COMPLETE checking, and set CMD_T_ABORTED + obtain ->cmd_kref for both cases ahead of last target_put_sess_cmd() after TFO->aborted_task() -> transport_cmd_finish_abort() callback has completed.
It also introduces SCF_ACK_KREF to determine when transport_cmd_finish_abort() needs to drop the second extra reference, ahead of calling target_put_sess_cmd() for the final kref_put(&se_cmd->cmd_kref).
It also updates transport_cmd_check_stop() to avoid holding se_cmd->t_state_lock while dropping se_cmd device state via target_remove_from_state_list(), now that core_tmr_drain_state_list() is holding the se_device lock while checking se_cmd state from within TMR logic.
Finally, move transport_put_cmd() release of SGL + TMR + extended CDB memory into target_free_cmd_mem() in order to avoid potential resource leaks in TMR ABORT_TASK + LUN_RESET code-paths. Also update target_release_cmd_kref() accordingly.
--- drivers/target/target_core_tmr.c | 69 ++++++++++++++++++++++----------- drivers/target/target_core_transport.c | 67 +++++++++++++------------------- include/target/target_core_base.h | 1 3 files changed, 76 insertions(+), 61 deletions(-)
drivers/target/target_core_tmr.c +46 -23
@@ -107,6 +107,34 @@ static int target_check_cdb_and_preempt(return 1 ; } +static bool __target_check_io_state (struct se_cmd *se_cmd) +{ +struct se_session *sess = se_cmd->se_sess; + +assert_spin_locked (&sess->sess_cmd_lock); +WARN_ON_ONCE (!irqs_disabled ()); +/* +* If command already reached CMD_T_COMPLETE state within +* target_complete_cmd(), this se_cmd has been passed to +* fabric driver and will not be aborted. +* +* Otherwise, obtain a local se_cmd->cmd_kref now for TMR +* ABORT_TASK + LUN_RESET for CMD_T_ABORTED processing as +* long as se_cmd->cmd_kref is still active unless zero. +*/ +spin_lock (&se_cmd->t_state_lock); +if (se_cmd->transport_state &CMD_T_COMPLETE ) { +pr_debug ("Attempted to abort io tag: %llu already complete," +" skipping\n" , se_cmd->tag); +spin_unlock (&se_cmd->t_state_lock); +return false; + } + se_cmd->transport_state |=CMD_T_ABORTED ; +spin_unlock (&se_cmd->t_state_lock); + +return kref_get_unless_zero (&se_cmd->cmd_kref); +} + void core_tmr_abort_task( struct se_device *dev, struct se_tmr_req *tmr,
@@ -130,34 +158,22 @@ void core_tmr_abort_task(if (tmr->ref_task_tag != ref_tag)continue ; -if (!kref_get_unless_zero (&se_cmd->cmd_kref)) -continue ; -printk ("ABORT_TASK: Found referenced %s task_tag: %llu\n" , se_cmd->se_tfo->get_fabric_name (), ref_tag); -spin_lock (&se_cmd->t_state_lock); -if (se_cmd->transport_state &CMD_T_COMPLETE ) { -printk ("ABORT_TASK: ref_tag: %llu already complete," -" skipping\n" , ref_tag); -spin_unlock (&se_cmd->t_state_lock); +if (!__target_check_io_state (se_cmd)) {spin_unlock_irqrestore (&se_sess->sess_cmd_lock, flags); -target_put_sess_cmd (se_cmd); - goto out; } - se_cmd->transport_state |=CMD_T_ABORTED ; -spin_unlock (&se_cmd->t_state_lock); -list_del_init (&se_cmd->se_cmd_list);spin_unlock_irqrestore (&se_sess->sess_cmd_lock, flags);cancel_work_sync (&se_cmd->work);transport_wait_for_tasks (se_cmd); -target_put_sess_cmd (se_cmd);transport_cmd_finish_abort (se_cmd, true); +target_put_sess_cmd (se_cmd);printk ("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for" " ref_tag: %llu\n" , ref_tag);
@@ -242,8 +258,10 @@ static void core_tmr_drain_state_list( struct list_head *preempt_and_abort_list) {LIST_HEAD (drain_task_list); +struct se_session *sess;struct se_cmd *cmd, *next;unsigned long flags; +int rc;/* * Complete outstanding commands with TASK_ABORTED SAM status.
@@ -282,6 +300,16 @@ static void core_tmr_drain_state_list(if (prout_cmd == cmd)continue ; + sess = cmd->se_sess; +if (WARN_ON_ONCE (!sess)) +continue ; + +spin_lock (&sess->sess_cmd_lock); + rc =__target_check_io_state (cmd); +spin_unlock (&sess->sess_cmd_lock); +if (!rc) +continue ; +list_move_tail (&cmd->state_list, &drain_task_list); cmd->state_active = false; }
@@ -289,7 +317,7 @@ static void core_tmr_drain_state_list(while (!list_empty (&drain_task_list)) { cmd = list_entry(drain_task_list.next, struct se_cmd, state_list); -list_del (&cmd->state_list); +list_del_init (&cmd->state_list);pr_debug ("LUN_RESET: %s cmd: %p" " ITT/CmdSN: 0x%08llx/0x%08x, i_state: %d, t_state: %d"
@@ -313,16 +341,11 @@ static void core_tmr_drain_state_list(* loop above, but we do it down here given that * cancel_work_sync may block. */ -if (cmd->t_state ==TRANSPORT_COMPLETE ) -cancel_work_sync (&cmd->work); - -spin_lock_irqsave (&cmd->t_state_lock, flags); -target_stop_cmd (cmd, &flags); - - cmd->transport_state |=CMD_T_ABORTED ; -spin_unlock_irqrestore (&cmd->t_state_lock, flags); +cancel_work_sync (&cmd->work); +transport_wait_for_tasks (cmd);core_tmr_handle_tas_abort (tmr_nacl, cmd, tas); +target_put_sess_cmd (cmd); } }
drivers/target/target_core_transport.c +29 -38
166 lines not on this page · raw message
include/target/target_core_base.h +1 -0
@@ -138,6 +138,7 @@ enum se_cmd_flags_table {SCF_COMPARE_AND_WRITE =0x00080000 ,SCF_COMPARE_AND_WRITE_POST =0x00100000 ,SCF_PASSTHROUGH_PROT_SG_TO_MEM_NOALLOC =0x00200000 , + SCF_ACK_KREF = 0x00400000, };/* struct se_dev_entry->lun_flags and struct se_lun->lun_access */
Greg Kroah-Hartman
maintainerPATCH 280/342 target: Fix LUN_RESET active TMR descriptor handling
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicholas Bellinger <[email protected]>
commit a6d9bb1c9605cd4f44e2d8290dc4d0e88f20292d upstream.
This patch fixes a NULL pointer se_cmd->cmd_kref < 0 refcount bug during TMR LUN_RESET with active TMRs, triggered during se_cmd + se_tmr_req descriptor shutdown + release via core_tmr_drain_tmr_list().
To address this bug, go ahead and obtain a local kref_get_unless_zero(&se_cmd->cmd_kref) for active I/O to set CMD_T_ABORTED, and transport_wait_for_tasks() followed by the final target_put_sess_cmd() to drop the local ->cmd_kref.
Also add two new checks within target_tmr_work() to avoid CMD_T_ABORTED -> TFO->queue_tm_rsp() callbacks ahead of invoking the backend -> fabric put in transport_cmd_check_stop_to_fabric().
For good measure, also change core_tmr_release_req() to use list_del_init() ahead of se_tmr_req memory free.
--- drivers/target/target_core_tmr.c | 22 +++++++++++++++++++++- drivers/target/target_core_transport.c | 17 +++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-)
drivers/target/target_core_tmr.c +21 -1
@@ -68,7 +68,7 @@ void core_tmr_release_req(struct se_tmr_if (dev) {spin_lock_irqsave (&dev->se_tmr_lock, flags); -list_del (&tmr->tmr_list); +list_del_init (&tmr->tmr_list);spin_unlock_irqrestore (&dev->se_tmr_lock, flags); }
@@ -194,9 +194,11 @@ static void core_tmr_drain_tmr_list( struct list_head *preempt_and_abort_list) {LIST_HEAD (drain_tmr_list); +struct se_session *sess;struct se_tmr_req *tmr_p, *tmr_pp;struct se_cmd *cmd;unsigned long flags; +bool rc;/* * Release all pending and outgoing TMRs aside from the received * LUN_RESET tmr..
@@ -222,17 +224,31 @@ static void core_tmr_drain_tmr_list(if (target_check_cdb_and_preempt (preempt_and_abort_list, cmd))continue ; + sess = cmd->se_sess; +if (WARN_ON_ONCE (!sess)) +continue ; + +spin_lock (&sess->sess_cmd_lock);spin_lock (&cmd->t_state_lock);if (!(cmd->transport_state &CMD_T_ACTIVE )) {spin_unlock (&cmd->t_state_lock); +spin_unlock (&sess->sess_cmd_lock);continue ; }if (cmd->t_state ==TRANSPORT_ISTATE_PROCESSING ) {spin_unlock (&cmd->t_state_lock); +spin_unlock (&sess->sess_cmd_lock);continue ; } + cmd->transport_state |=CMD_T_ABORTED ;spin_unlock (&cmd->t_state_lock); + rc =kref_get_unless_zero (&cmd->cmd_kref); +spin_unlock (&sess->sess_cmd_lock); +if (!rc) { +printk ("LUN_RESET TMR: non-zero kref_get_unless_zero\n" ); +continue ; + }list_move_tail (&tmr_p->tmr_list, &drain_tmr_list); }spin_unlock_irqrestore (&dev->se_tmr_lock, flags);
@@ -246,7 +262,11 @@ static void core_tmr_drain_tmr_list( (preempt_and_abort_list) ?"Preempt" :"" , tmr_p, tmr_p->function, tmr_p->response, cmd->t_state); +cancel_work_sync (&cmd->work); +transport_wait_for_tasks (cmd); +transport_cmd_finish_abort (cmd,1 ); +target_put_sess_cmd (cmd); } }
drivers/target/target_core_transport.c +17 -0
@@ -2891,8 +2891,17 @@ static void target_tmr_work(struct work_ struct se_cmd *cmd = container_of(work, struct se_cmd, work);struct se_device *dev = cmd->se_dev;struct se_tmr_req *tmr = cmd->se_tmr_req; +unsigned long flags;int ret; +spin_lock_irqsave (&cmd->t_state_lock, flags); +if (cmd->transport_state &CMD_T_ABORTED ) { + tmr->response =TMR_FUNCTION_REJECTED ; +spin_unlock_irqrestore (&cmd->t_state_lock, flags); + goto check_stop; + } +spin_unlock_irqrestore (&cmd->t_state_lock, flags); +switch (tmr->function) {case TMR_ABORT_TASK :core_tmr_abort_task (dev, tmr, cmd->se_sess);
@@ -2925,9 +2934,17 @@ static void target_tmr_work(struct work_break ; } +spin_lock_irqsave (&cmd->t_state_lock, flags); +if (cmd->transport_state &CMD_T_ABORTED ) { +spin_unlock_irqrestore (&cmd->t_state_lock, flags); + goto check_stop; + } cmd->t_state =TRANSPORT_ISTATE_PROCESSING ; +spin_unlock_irqrestore (&cmd->t_state_lock, flags); + cmd->se_tfo->queue_tm_rsp (cmd); +check_stop:transport_cmd_check_stop_to_fabric (cmd); }
Greg Kroah-Hartman
maintainerPATCH 281/342 target: Fix TAS handling for multi-session se_node_acls
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicholas Bellinger <[email protected]>
commit ebde1ca5a908b10312db4ecd7553e3ba039319ab upstream.
This patch fixes a bug in TMR task aborted status (TAS) handling when multiple sessions are connected to the same target WWPN endpoint and se_node_acl descriptor, resulting in TASK_ABORTED status to not be generated for aborted se_cmds on the remote port.
This is due to core_tmr_handle_tas_abort() incorrectly comparing se_node_acl instead of se_session, for which the multi-session case is expected to be sharing the same se_node_acl.
Instead, go ahead and update core_tmr_handle_tas_abort() to compare tmr_sess + cmd->se_sess in order to determine if the LUN_RESET was received on a different I_T nexus, and TASK_ABORTED status response needs to be generated.
--- drivers/target/target_core_tmr.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
drivers/target/target_core_tmr.c +9 -7
@@ -76,7 +76,7 @@ void core_tmr_release_req(struct se_tmr_ }static void core_tmr_handle_tas_abort ( -struct se_node_acl *tmr_nacl, +struct se_session *tmr_sess,struct se_cmd *cmd,int tas) {
@@ -84,7 +84,7 @@ static void core_tmr_handle_tas_abort(/* * TASK ABORTED status (TAS) bit support */ -if ((tmr_nacl && (tmr_nacl != cmd->se_sess->se_node_acl)) && tas) { +if (tmr_sess && tmr_sess != cmd->se_sess && tas) { remove = false;transport_send_task_abort (cmd); }
@@ -273,7 +273,7 @@ static void core_tmr_drain_tmr_list(static void core_tmr_drain_state_list (struct se_device *dev,struct se_cmd *prout_cmd, -struct se_node_acl *tmr_nacl, +struct se_session *tmr_sess,int tas,struct list_head *preempt_and_abort_list) {
@@ -364,7 +364,7 @@ static void core_tmr_drain_state_list(cancel_work_sync (&cmd->work);transport_wait_for_tasks (cmd); -core_tmr_handle_tas_abort (tmr_nacl, cmd, tas); +core_tmr_handle_tas_abort (tmr_sess, cmd, tas);target_put_sess_cmd (cmd); } }
@@ -377,6 +377,7 @@ int core_tmr_lun_reset( {struct se_node_acl *tmr_nacl =NULL ;struct se_portal_group *tmr_tpg =NULL ; +struct se_session *tmr_sess =NULL ;int tas;/* * TASK_ABORTED status bit, this is configurable via ConfigFS
@@ -395,8 +396,9 @@ int core_tmr_lun_reset(* or struct se_device passthrough.. */ if (tmr && tmr->task_cmd && tmr->task_cmd->se_sess) { - tmr_nacl = tmr->task_cmd->se_sess->se_node_acl; - tmr_tpg = tmr->task_cmd->se_sess->se_tpg; + tmr_sess = tmr->task_cmd->se_sess; + tmr_nacl = tmr_sess->se_node_acl; + tmr_tpg = tmr_sess->se_tpg;if (tmr_nacl && tmr_tpg) { pr_debug("LUN_RESET: TMR caller fabric: %s" " initiator port %s\n",
@@ -409,7 +411,7 @@ int core_tmr_lun_reset( dev->transport->name, tas);core_tmr_drain_tmr_list (dev, tmr, preempt_and_abort_list); -core_tmr_drain_state_list (dev, prout_cmd, tmr_nacl, tas, +core_tmr_drain_state_list (dev, prout_cmd, tmr_sess, tas, preempt_and_abort_list);/*
Greg Kroah-Hartman
maintainerPATCH 282/342 target: Fix remote-port TMR ABORT + se_cmd fabric stop
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicholas Bellinger <[email protected]>
commit 0f4a943168f31d29a1701908931acaba518b131a upstream.
To address the bug where fabric driver level shutdown of se_cmd occurs at the same time when TMR CMD_T_ABORTED is happening resulting in a -1 ->cmd_kref, this patch adds a CMD_T_FABRIC_STOP bit that is used to determine when TMR + driver I_T nexus shutdown is happening concurrently.
It changes target_sess_cmd_list_set_waiting() to obtain se_cmd->cmd_kref + set CMD_T_FABRIC_STOP, and drop local reference in target_wait_for_sess_cmds() and invoke extra target_put_sess_cmd() during Task Aborted Status (TAS) when necessary.
Also, it adds a new target_wait_free_cmd() wrapper around transport_wait_for_tasks() for the special case within transport_generic_free_cmd() to set CMD_T_FABRIC_STOP, and is now aware of CMD_T_ABORTED + CMD_T_TAS status bits to know when an extra transport_put_cmd() during TAS is required.
Note transport_generic_free_cmd() is expected to block on cmd->cmd_wait_comp in order to follow what iscsi-target expects during iscsi_conn context se_cmd shutdown.
--- drivers/target/target_core_tmr.c | 54 ++++++++---- drivers/target/target_core_transport.c | 145 +++++++++++++++++++++++++-------- include/target/target_core_base.h | 2 3 files changed, 150 insertions(+), 51 deletions(-)
drivers/target/target_core_tmr.c +38 -16
@@ -75,16 +75,18 @@ void core_tmr_release_req(struct se_tmr_kfree (tmr); } -static void core_tmr_handle_tas_abort ( -struct se_session *tmr_sess, -struct se_cmd *cmd, -int tas) +static void core_tmr_handle_tas_abort (struct se_cmd *cmd,int tas) { -bool remove = true; +unsigned long flags; +bool remove = true, send_tas;/* * TASK ABORTED status (TAS) bit support */ -if (tmr_sess && tmr_sess != cmd->se_sess && tas) { +spin_lock_irqsave (&cmd->t_state_lock, flags); + send_tas = (cmd->transport_state &CMD_T_TAS ); +spin_unlock_irqrestore (&cmd->t_state_lock, flags); + +if (send_tas) { remove = false;transport_send_task_abort (cmd); }
@@ -107,7 +109,8 @@ static int target_check_cdb_and_preempt(return 1 ; } -static bool __target_check_io_state (struct se_cmd *se_cmd) +static bool __target_check_io_state (struct se_cmd *se_cmd, +struct se_session *tmr_sess,int tas) {struct se_session *sess = se_cmd->se_sess;
@@ -115,21 +118,32 @@ static bool __target_check_io_state(struWARN_ON_ONCE (!irqs_disabled ());/* * If command already reached CMD_T_COMPLETE state within -* target_complete_cmd(), this se_cmd has been passed to -* fabric driver and will not be aborted. +* target_complete_cmd() or CMD_T_FABRIC_STOP due to shutdown, +* this se_cmd has been passed to fabric driver and will +* not be aborted. * * Otherwise, obtain a local se_cmd->cmd_kref now for TMR * ABORT_TASK + LUN_RESET for CMD_T_ABORTED processing as * long as se_cmd->cmd_kref is still active unless zero. */ spin_lock (&se_cmd->t_state_lock); -if (se_cmd->transport_state &CMD_T_COMPLETE ) { -pr_debug ("Attempted to abort io tag: %llu already complete," +if (se_cmd->transport_state & (CMD_T_COMPLETE |CMD_T_FABRIC_STOP )) { +pr_debug ("Attempted to abort io tag: %llu already complete or" +" fabric stop, skipping\n" , se_cmd->tag); +spin_unlock (&se_cmd->t_state_lock); +return false; + } +if (sess->sess_tearing_down || se_cmd->cmd_wait_set) { +pr_debug ("Attempted to abort io tag: %llu already shutdown," " skipping\n" , se_cmd->tag);spin_unlock (&se_cmd->t_state_lock);return false; } se_cmd->transport_state |=CMD_T_ABORTED ; + +if ((tmr_sess != se_cmd->se_sess) && tas) + se_cmd->transport_state |=CMD_T_TAS ; +spin_unlock (&se_cmd->t_state_lock);return kref_get_unless_zero (&se_cmd->cmd_kref);
@@ -161,7 +175,7 @@ void core_tmr_abort_task(printk ("ABORT_TASK: Found referenced %s task_tag: %llu\n" , se_cmd->se_tfo->get_fabric_name (), ref_tag); -if (!__target_check_io_state (se_cmd)) { +if (!__target_check_io_state (se_cmd, se_sess,0 )) {spin_unlock_irqrestore (&se_sess->sess_cmd_lock, flags);target_put_sess_cmd (se_cmd); goto out;
@@ -230,7 +244,8 @@ static void core_tmr_drain_tmr_list(spin_lock (&sess->sess_cmd_lock);spin_lock (&cmd->t_state_lock); -if (!(cmd->transport_state &CMD_T_ACTIVE )) { +if (!(cmd->transport_state &CMD_T_ACTIVE ) || + (cmd->transport_state &CMD_T_FABRIC_STOP )) {spin_unlock (&cmd->t_state_lock);spin_unlock (&sess->sess_cmd_lock);continue ;
@@ -240,15 +255,22 @@ static void core_tmr_drain_tmr_list(spin_unlock (&sess->sess_cmd_lock);continue ; } +if (sess->sess_tearing_down || cmd->cmd_wait_set) { +spin_unlock (&cmd->t_state_lock); +spin_unlock (&sess->sess_cmd_lock); +continue ; + } cmd->transport_state |=CMD_T_ABORTED ;spin_unlock (&cmd->t_state_lock); rc =kref_get_unless_zero (&cmd->cmd_kref); -spin_unlock (&sess->sess_cmd_lock);if (!rc) {printk ("LUN_RESET TMR: non-zero kref_get_unless_zero\n" ); +spin_unlock (&sess->sess_cmd_lock);continue ; } +spin_unlock (&sess->sess_cmd_lock); +list_move_tail (&tmr_p->tmr_list, &drain_tmr_list); }spin_unlock_irqrestore (&dev->se_tmr_lock, flags);
@@ -325,7 +347,7 @@ static void core_tmr_drain_state_list(continue ;spin_lock (&sess->sess_cmd_lock); - rc =__target_check_io_state (cmd); + rc =__target_check_io_state (cmd, tmr_sess, tas);spin_unlock (&sess->sess_cmd_lock);if (!rc)continue ;
@@ -364,7 +386,7 @@ static void core_tmr_drain_state_list(cancel_work_sync (&cmd->work);transport_wait_for_tasks (cmd); -core_tmr_handle_tas_abort (tmr_sess, cmd, tas); +core_tmr_handle_tas_abort (cmd, tas);target_put_sess_cmd (cmd); } }
drivers/target/target_core_transport.c +110 -35
236 lines not on this page · raw message
include/target/target_core_base.h +2 -0
@@ -491,6 +491,8 @@ struct se_cmd {#define CMD_T_DEV_ACTIVE (1 << 7)#define CMD_T_REQUEST_STOP (1 << 8)#define CMD_T_BUSY (1 << 9) +#define CMD_T_TAS (1 << 10) +#define CMD_T_FABRIC_STOP (1 << 11)spinlock_t t_state_lock;struct kref cmd_kref;struct completion t_transport_stop_comp;
Greg Kroah-Hartman
maintainerPATCH 283/342 target: Fix race with SCF_SEND_DELAYED_TAS handling
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicholas Bellinger <[email protected]>
commit 310d3d314be7f0a84011ebdc4bdccbcae9755a87 upstream.
This patch fixes a race between setting of SCF_SEND_DELAYED_TAS in transport_send_task_abort(), and check of the same bit in transport_check_aborted_status().
It adds a __transport_check_aborted_status() version that is used by target_execute_cmd() when se_cmd->t_state_lock is held, and a transport_check_aborted_status() wrapper for all other existing callers.
Also, it handles the case where the check happens before transport_send_task_abort() gets called. For this, go ahead and set SCF_SEND_DELAYED_TAS early when necessary, and have transport_send_task_abort() send the abort.
--- drivers/target/target_core_transport.c | 53 +++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 12 deletions(-)
drivers/target/target_core_transport.c +41 -12
@@ -1849,19 +1849,21 @@ static bool target_handle_task_attr(strureturn true; } +static int __transport_check_aborted_status (struct se_cmd *,int ); +void target_execute_cmd (struct se_cmd *cmd) {/* -* If the received CDB has aleady been aborted stop processing it here. -*/ -if (transport_check_aborted_status (cmd,1 )) -return ; - -/* * Determine if frontend context caller is requesting the stopping of * this command for frontend exceptions. +* +* If the received CDB has aleady been aborted stop processing it here. */ spin_lock_irq (&cmd->t_state_lock); +if (__transport_check_aborted_status (cmd,1 )) { +spin_unlock_irq (&cmd->t_state_lock); +return ; + }if (cmd->transport_state &CMD_T_STOP ) {pr_debug ("%s:%d CMD_T_STOP for ITT: 0x%08llx\n" , __func__, __LINE__, cmd->tag);
@@ -2902,28 +2904,49 @@ transport_send_check_condition_and_sense }EXPORT_SYMBOL (transport_send_check_condition_and_sense); -int transport_check_aborted_status (struct se_cmd *cmd,int send_status) +static int __transport_check_aborted_status (struct se_cmd *cmd,int send_status) + __releases(&cmd->t_state_lock) + __acquires(&cmd->t_state_lock) { +assert_spin_locked (&cmd->t_state_lock); +WARN_ON_ONCE (!irqs_disabled ()); +if (!(cmd->transport_state &CMD_T_ABORTED ))return 0 ; -/* * If cmd has been aborted but either no status is to be sent or it has * already been sent, just return */ -if (!send_status || !(cmd->se_cmd_flags &SCF_SEND_DELAYED_TAS )) +if (!send_status || !(cmd->se_cmd_flags &SCF_SEND_DELAYED_TAS )) { +if (send_status) + cmd->se_cmd_flags |=SCF_SEND_DELAYED_TAS ;return 1 ; + } -pr_debug ("Sending delayed SAM_STAT_TASK_ABORTED status for CDB: 0x%02x ITT: 0x%08llx\n" , - cmd->t_task_cdb[0 ], cmd->tag); +pr_debug ("Sending delayed SAM_STAT_TASK_ABORTED status for CDB:" +" 0x%02x ITT: 0x%08llx\n" , cmd->t_task_cdb[0 ], cmd->tag); cmd->se_cmd_flags &= ~SCF_SEND_DELAYED_TAS ; cmd->scsi_status =SAM_STAT_TASK_ABORTED ;trace_target_cmd_complete (cmd); + +spin_unlock_irq (&cmd->t_state_lock); cmd->se_tfo->queue_status (cmd); +spin_lock_irq (&cmd->t_state_lock);return 1 ; } + +int transport_check_aborted_status (struct se_cmd *cmd,int send_status) +{ +int ret; + +spin_lock_irq (&cmd->t_state_lock); + ret =__transport_check_aborted_status (cmd, send_status); +spin_unlock_irq (&cmd->t_state_lock); + +return ret; +}EXPORT_SYMBOL (transport_check_aborted_status);void transport_send_task_abort (struct se_cmd *cmd)
@@ -2945,11 +2968,17 @@ void transport_send_task_abort(struct se*/ if (cmd->data_direction ==DMA_TO_DEVICE ) {if (cmd->se_tfo->write_pending_status (cmd) !=0 ) { - cmd->transport_state |=CMD_T_ABORTED ; +spin_lock_irqsave (&cmd->t_state_lock, flags); +if (cmd->se_cmd_flags &SCF_SEND_DELAYED_TAS ) { +spin_unlock_irqrestore (&cmd->t_state_lock, flags); + goto send_abort; + } cmd->se_cmd_flags |=SCF_SEND_DELAYED_TAS ; +spin_unlock_irqrestore (&cmd->t_state_lock, flags);return ; } } +send_abort: cmd->scsi_status =SAM_STAT_TASK_ABORTED ;transport_lun_remove_cmd (cmd);
Greg Kroah-Hartman
maintainerPATCH 284/342 spi: atmel: fix gpio chip-select in case of non-DT platform
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cyrille Pitchen <[email protected]>
commit 70f340df24518d36eeaefb6652d492f250115c19 upstream.
The non-DT platform that uses this driver (actually the AVR32) was taking a bad branch for determining if the IP would use gpio for CS.
Adding the presence of DT as a condition fixes this issue.
--- drivers/spi/spi-atmel.c | 1 + 1 file changed, 1 insertion(+)
drivers/spi/spi-atmel.c +1 -0
@@ -1571,6 +1571,7 @@ static int atmel_spi_probe(struct platfo as->use_cs_gpios = true;if (atmel_spi_is_v2 (as) && + pdev->dev.of_node && !of_get_property (pdev->dev.of_node,"cs-gpios" ,NULL )) { as->use_cs_gpios = false; master->num_chipselect =4 ;
Greg Kroah-Hartman
maintainerPATCH 285/342 qla2xxx: Fix stale pointer access.
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Quinn Tran <[email protected]>
commit cb43285ff7039fe3c4b0bc476e6d6569c31104f3 upstream.
[ Upstream Commit 84e32a06f4f8756ce9ec3c8dc7e97896575f0771 ]
Commit 84e32a0 ("qla2xxx: Use pci_enable_msix_range() instead of pci_enable_msix()") introduced a regression when target mode is enabled. In qla24xx_enable_msix(), ha->max_rsp_queues was incorrectly set to a value higher than the number of response queues allocated causing an invalid dereference. Specifically here in qla2x00_init_rings():
*rsp->in_ptr = 0;
Add additional check to make sure the pointer is valid. following call stack will be seen
---- 8< ----
RIP: 0010:[<ffffffffa02ccadc>] [<ffffffffa02ccadc>] qla2x00_init_rings+0xdc/0x320 [qla2xxx] RSP: 0018:ffff880429447dd8 EFLAGS: 00010082 .... Call Trace: [<ffffffffa02ceb40>] qla2x00_abort_isp+0x170/0x6b0 [qla2xxx] [<ffffffffa02c6f77>] qla2x00_do_dpc+0x357/0x7f0 [qla2xxx] [<ffffffffa02c6c20>] ? qla2x00_relogin+0x260/0x260 [qla2xxx] [<ffffffff8107d2c9>] kthread+0xc9/0xe0 [<ffffffff8107d200>] ? flush_kthread_worker+0x90/0x90 [<ffffffff8172cc6f>] ret_from_fork+0x3f/0x70 [<ffffffff8107d200>] ? flush_kthread_worker+0x90/0x90
---- 8< ----
--- drivers/scsi/qla2xxx/qla_init.c | 10 +++++----- drivers/scsi/qla2xxx/qla_isr.c | 4 ++-- drivers/scsi/qla2xxx/qla_mid.c | 4 ++-- drivers/scsi/qla2xxx/qla_os.c | 6 ++++++ drivers/scsi/qla2xxx/qla_tmpl.c | 16 ++++++++++++++++ 5 files changed, 31 insertions(+), 9 deletions(-)
drivers/scsi/qla2xxx/qla_init.c +5 -5
@@ -2192,7 +2192,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha)/* Clear outstanding commands array. */ for (que =0 ; que < ha->max_req_queues; que++) { req = ha->req_q_map[que]; -if (!req) +if (!req || !test_bit (que, ha->req_qid_map))continue ; req->out_ptr = (void *)(req->ring + req->length); *req->out_ptr =0 ;
@@ -2209,7 +2209,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha)for (que =0 ; que < ha->max_rsp_queues; que++) { rsp = ha->rsp_q_map[que]; -if (!rsp) +if (!rsp || !test_bit (que, ha->rsp_qid_map))continue ; rsp->in_ptr = (void *)(rsp->ring + rsp->length); *rsp->in_ptr =0 ;
@@ -4961,7 +4961,7 @@ qla25xx_init_queues(struct qla_hw_data *for (i =1 ; i < ha->max_rsp_queues; i++) { rsp = ha->rsp_q_map[i]; -if (rsp) { +if (rsp &&test_bit (i, ha->rsp_qid_map)) { rsp->options &= ~BIT_0 ; ret =qla25xx_init_rsp_que (base_vha, rsp);if (ret !=QLA_SUCCESS )
@@ -4976,8 +4976,8 @@ qla25xx_init_queues(struct qla_hw_data * }for (i =1 ; i < ha->max_req_queues; i++) { req = ha->req_q_map[i]; -if (req) { -/* Clear outstanding commands array. */ +if (req &&test_bit (i, ha->req_qid_map)) { +/* Clear outstanding commands array. */ req->options &= ~BIT_0 ; ret =qla25xx_init_req_que (base_vha, req);if (ret !=QLA_SUCCESS )
drivers/scsi/qla2xxx/qla_isr.c +2 -2
@@ -3018,9 +3018,9 @@ qla24xx_enable_msix(struct qla_hw_data *"MSI-X: Failed to enable support " "-- %d/%d\n Retry with %d vectors.\n" , ha->msix_count, ret, ret); + ha->msix_count = ret; + ha->max_rsp_queues = ha->msix_count -1 ; } - ha->msix_count = ret; - ha->max_rsp_queues = ha->msix_count -1 ; ha->msix_entries =kzalloc (sizeof (struct qla_msix_entry ) * ha->msix_count,GFP_KERNEL );if (!ha->msix_entries) {
drivers/scsi/qla2xxx/qla_mid.c +2 -2
@@ -600,7 +600,7 @@ qla25xx_delete_queues(struct scsi_qla_ho/* Delete request queues */ for (cnt =1 ; cnt < ha->max_req_queues; cnt++) { req = ha->req_q_map[cnt]; -if (req) { +if (req &&test_bit (cnt, ha->req_qid_map)) { ret =qla25xx_delete_req_que (vha, req);if (ret !=QLA_SUCCESS ) { ql_log(ql_log_warn, vha, 0x00ea,
@@ -614,7 +614,7 @@ qla25xx_delete_queues(struct scsi_qla_ho/* Delete response queues */ for (cnt =1 ; cnt < ha->max_rsp_queues; cnt++) { rsp = ha->rsp_q_map[cnt]; -if (rsp) { +if (rsp &&test_bit (cnt, ha->rsp_qid_map)) { ret =qla25xx_delete_rsp_que (vha, rsp);if (ret !=QLA_SUCCESS ) { ql_log(ql_log_warn, vha, 0x00eb,
drivers/scsi/qla2xxx/qla_os.c +6 -0
@@ -397,6 +397,9 @@ static void qla2x00_free_queues(struct qint cnt;for (cnt =0 ; cnt < ha->max_req_queues; cnt++) { +if (!test_bit (cnt, ha->req_qid_map)) +continue ; + req = ha->req_q_map[cnt];qla2x00_free_req_que (ha, req); }
@@ -404,6 +407,9 @@ static void qla2x00_free_queues(struct q ha->req_q_map =NULL ;for (cnt =0 ; cnt < ha->max_rsp_queues; cnt++) { +if (!test_bit (cnt, ha->rsp_qid_map)) +continue ; + rsp = ha->rsp_q_map[cnt];qla2x00_free_rsp_que (ha, rsp); }
drivers/scsi/qla2xxx/qla_tmpl.c +16 -0
@@ -395,6 +395,10 @@ qla27xx_fwdt_entry_t263(struct scsi_qla_if (ent->t263.queue_type ==T263_QUEUE_TYPE_REQ ) {for (i =0 ; i < vha->hw->max_req_queues; i++) {struct req_que *req = vha->hw->req_q_map[i]; + +if (!test_bit (i, vha->hw->req_qid_map)) +continue ; +if (req || !buf) { length = req ? req->length :REQUEST_ENTRY_CNT_24XX ;
@@ -408,6 +412,10 @@ qla27xx_fwdt_entry_t263(struct scsi_qla_ }else if (ent->t263.queue_type ==T263_QUEUE_TYPE_RSP ) {for (i =0 ; i < vha->hw->max_rsp_queues; i++) {struct rsp_que *rsp = vha->hw->rsp_q_map[i]; + +if (!test_bit (i, vha->hw->rsp_qid_map)) +continue ; +if (rsp || !buf) { length = rsp ? rsp->length :RESPONSE_ENTRY_CNT_MQ ;
@@ -634,6 +642,10 @@ qla27xx_fwdt_entry_t274(struct scsi_qla_if (ent->t274.queue_type ==T274_QUEUE_TYPE_REQ_SHAD ) {for (i =0 ; i < vha->hw->max_req_queues; i++) {struct req_que *req = vha->hw->req_q_map[i]; + +if (!test_bit (i, vha->hw->req_qid_map)) +continue ; +if (req || !buf) {qla27xx_insert16 (i, buf, len);qla27xx_insert16 (1 , buf, len);
@@ -645,6 +657,10 @@ qla27xx_fwdt_entry_t274(struct scsi_qla_ }else if (ent->t274.queue_type ==T274_QUEUE_TYPE_RSP_SHAD ) {for (i =0 ; i < vha->hw->max_rsp_queues; i++) {struct rsp_que *rsp = vha->hw->rsp_q_map[i]; + +if (!test_bit (i, vha->hw->rsp_qid_map)) +continue ; +if (rsp || !buf) {qla27xx_insert16 (i, buf, len);qla27xx_insert16 (1 , buf, len);
Greg Kroah-Hartman
maintainerPATCH 286/342 libata: fix sff host state machine locking while polling
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <[email protected]>
commit 8eee1d3ed5b6fc8e14389567c9a6f53f82bb7224 upstream.
The bulk of ATA host state machine is implemented by ata_sff_hsm_move(). The function is called from either the interrupt handler or, if polling, a work item. Unlike from the interrupt path, the polling path calls the function without holding the host lock and ata_sff_hsm_move() selectively grabs the lock.
This is completely broken. If an IRQ triggers while polling is in progress, the two can easily race and end up accessing the hardware and updating state machine state at the same time. This can put the state machine in an illegal state and lead to a crash like the following.
kernel BUG at drivers/ata/libata-sff.c:1302! invalid opcode: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN
Modules linked in: CPU: 1 PID: 10679 Comm: syz-executor Not tainted 4.5.0-rc1+ #300 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 task: ffff88002bd00000 ti: ffff88002e048000 task.ti: ffff88002e048000 RIP: 0010:[<ffffffff83a83409>] [<ffffffff83a83409>] ata_sff_hsm_move+0x619/0x1c60 ... Call Trace: <IRQ> [<ffffffff83a84c31>] __ata_sff_port_intr+0x1e1/0x3a0 drivers/ata/libata-sff.c:1584 [<ffffffff83a85611>] ata_bmdma_port_intr+0x71/0x400 drivers/ata/libata-sff.c:2877 [< inline >] __ata_sff_interrupt drivers/ata/libata-sff.c:1629 [<ffffffff83a85bf3>] ata_bmdma_interrupt+0x253/0x580 drivers/ata/libata-sff.c:2902 [<ffffffff81479f98>] handle_irq_event_percpu+0x108/0x7e0 kernel/irq/handle.c:157 [<ffffffff8147a717>] handle_irq_event+0xa7/0x140 kernel/irq/handle.c:205 [<ffffffff81484573>] handle_edge_irq+0x1e3/0x8d0 kernel/irq/chip.c:623 [< inline >] generic_handle_irq_desc include/linux/irqdesc.h:146 [<ffffffff811a92bc>] handle_irq+0x10c/0x2a0 arch/x86/kernel/irq_64.c:78 [<ffffffff811a7e4d>] do_IRQ+0x7d/0x1a0 arch/x86/kernel/irq.c:240 [<ffffffff86653d4c>] common_interrupt+0x8c/0x8c arch/x86/entry/entry_64.S:520 <EOI> [< inline >] rcu_lock_acquire include/linux/rcupdate.h:490 [< inline >] rcu_read_lock include/linux/rcupdate.h:874 [<ffffffff8164b4a1>] filemap_map_pages+0x131/0xba0 mm/filemap.c:2145 [< inline >] do_fault_around mm/memory.c:2943 [< inline >] do_read_fault mm/memory.c:2962 [< inline >] do_fault mm/memory.c:3133 [< inline >] handle_pte_fault mm/memory.c:3308 [< inline >] __handle_mm_fault mm/memory.c:3418 [<ffffffff816efb16>] handle_mm_fault+0x2516/0x49a0 mm/memory.c:3447 [<ffffffff8127dc16>] __do_page_fault+0x376/0x960 arch/x86/mm/fault.c:1238 [<ffffffff8127e358>] trace_do_page_fault+0xe8/0x420 arch/x86/mm/fault.c:1331 [<ffffffff8126f514>] do_async_page_fault+0x14/0xd0 arch/x86/kernel/kvm.c:264 [<ffffffff86655578>] async_page_fault+0x28/0x30 arch/x86/entry/entry_64.S:986
Fix it by ensuring that the polling path is holding the host lock before entering ata_sff_hsm_move() so that all hardware accesses and state updates are performed under the host lock.
--- drivers/ata/libata-sff.c | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-)
drivers/ata/libata-sff.c +11 -21
@@ -997,12 +997,9 @@ static inline int ata_hsm_ok_in_wq(strucstatic void ata_hsm_qc_complete (struct ata_queued_cmd *qc,int in_wq) {struct ata_port *ap = qc->ap; -unsigned long flags;if (ap->ops->error_handler) {if (in_wq) { -spin_lock_irqsave (ap->lock, flags); -/* EH might have kicked in while host lock is * released. */
@@ -1014,8 +1011,6 @@ static void ata_hsm_qc_complete(struct a }else ata_port_freeze (ap); } - -spin_unlock_irqrestore (ap->lock, flags); }else {if (likely (!(qc->err_mask &AC_ERR_HSM )))ata_qc_complete (qc);
@@ -1024,10 +1019,8 @@ static void ata_hsm_qc_complete(struct a } }else {if (in_wq) { -spin_lock_irqsave (ap->lock, flags);ata_sff_irq_on (ap);ata_qc_complete (qc); -spin_unlock_irqrestore (ap->lock, flags); }else ata_qc_complete (qc); }
@@ -1048,9 +1041,10 @@ int ata_sff_hsm_move(struct ata_port *ap {struct ata_link *link = qc->dev->link;struct ata_eh_info *ehi = &link->eh_info; -unsigned long flags =0 ;int poll_next; +lockdep_assert_held (ap->lock); +WARN_ON_ONCE ((qc->flags &ATA_QCFLAG_ACTIVE ) ==0 );/* Make sure ata_sff_qc_issue() does not throw things
@@ -1112,14 +1106,6 @@ fsm_start: } } -/* Send the CDB (atapi) or the first data block (ata pio out). -* During the state transition, interrupt handler shouldn't -* be invoked before the data transfer is complete and -* hsm_task_state is changed. Hence, the following locking. -*/ -if (in_wq) -spin_lock_irqsave (ap->lock, flags); -if (qc->tf.protocol ==ATA_PROT_PIO ) {/* PIO data out protocol. * send first data block.
@@ -1135,9 +1121,6 @@ fsm_start:/* send CDB */ atapi_send_cdb (ap, qc); -if (in_wq) -spin_unlock_irqrestore (ap->lock, flags); -/* if polling, ata_sff_pio_task() handles the rest. * otherwise, interrupt handler takes over from here. */
@@ -1361,12 +1344,14 @@ static void ata_sff_pio_task(struct worku8 status;int poll_next; +spin_lock_irq (ap->lock); +BUG_ON (ap->sff_pio_task_link ==NULL );/* qc can be NULL if timeout occurred */ qc =ata_qc_from_tag (ap, link->active_tag);if (!qc) { ap->sff_pio_task_link =NULL ; -return ; + goto out_unlock; } fsm_start:
@@ -1381,11 +1366,14 @@ fsm_start:*/ status =ata_sff_busy_wait (ap,ATA_BUSY ,5 );if (status &ATA_BUSY ) { +spin_unlock_irq (ap->lock);ata_msleep (ap,2 ); +spin_lock_irq (ap->lock); + status =ata_sff_busy_wait (ap,ATA_BUSY ,10 );if (status &ATA_BUSY ) {ata_sff_queue_pio_task (link,ATA_SHORT_PAUSE ); -return ; + goto out_unlock; } }
@@ -1402,6 +1390,8 @@ fsm_start:*/ if (poll_next) goto fsm_start; +out_unlock: +spin_unlock_irq (ap->lock); }/**
Greg Kroah-Hartman
maintainerPATCH 287/342 ARCv2: STAR 9000950267: Handle return from intr to Delay Slot #2
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vineet Gupta <[email protected]>
commit cbfe74a753e877b49dc54e9b04d5d42230ca0aed upstream.
Returning to delay slot, riding an interrupti, had one loose end. AUX_USER_SP used for restoring user mode SP upon RTIE was not being setup from orig task's saved value, causing task to use wrong SP, leading to ProtV errors.
The reason being:
- INTERRUPT_EPILOGUE returns to a kernel trampoline, thus not expected to restore it
- EXCEPTION_EPILOGUE is not used at all
Fix that by restoring AUX_USER_SP explicitly in the trampoline.
This was broken in the original workaround, but the error scenarios got reduced considerably since v3.14 due to following:
1. The Linuxthreads.old based userspace at the time caused many more exceptions in delay slot than the current NPTL based one. Infact with current userspace the error doesn't happen at all.
2. Return from interrupt (delay slot or otherwise) doesn't get exercised much after commit 4de0e52867d8 ("Really Re-enable interrupts to avoid deadlocks") since IRQ_ACTIVE.active being clear means most returns are as if from pure kernel (even for active interrupts)
Infact the issue only happened in an experimental branch where I was tinkering with reverted 4de0e52867d8
--- arch/arc/kernel/entry-arcv2.S | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-)
arch/arc/kernel/entry-arcv2.S +18 -1
@@ -211,7 +211,11 @@ debug_marker_syscall: ; (since IRQ NOT allowed in DS in ARCv2, this can only happen if orig ; entry was via Exception in DS which got preempted in kernel). ; -; IRQ RTIE won't reliably restore DE bit and/or BTA, needs handling +; IRQ RTIE won't reliably restore DE bit and/or BTA, needs workaround +; +; Solution is return from Intr w/o any delay slot quirks into a kernel trampoline +; and from pure kernel mode return to delay slot which handles DS bit/BTA correctly + .Lintr_ret_to_delay_slot: debug_marker_ds:
@@ -222,18 +226,23 @@ debug_marker_ds: ld r2, [sp, PT_ret] ld r3, [sp, PT_status32] + ; STAT32 for Int return created from scratch + ; (No delay dlot, disable Further intr in trampoline) + bic r0, r3, STATUS_U_MASK|STATUS_DE_MASK|STATUS_IE_MASK|STATUS_L_MASK st r0, [sp, PT_status32] mov r1, .Lintr_ret_to_delay_slot_2 st r1, [sp, PT_ret] + ; Orig exception PC/STAT32 safekept @orig_r0 and @event stack slots st r2, [sp, 0] st r3, [sp, 4] b .Lisr_ret_fast_path .Lintr_ret_to_delay_slot_2: + ; Trampoline to restore orig exception PC/STAT32/BTA/AUX_USER_SP sub sp, sp, SZ_PT_REGS st r9, [sp, -4]
@@ -243,11 +252,19 @@ debug_marker_ds: ld r9, [sp, 4] sr r9, [erstatus] + ; restore AUX_USER_SP if returning to U mode + bbit0 r9, STATUS_U_BIT, 1f + ld r9, [sp, PT_sp] + sr r9, [AUX_USER_SP] + +1: ld r9, [sp, 8] sr r9, [erbta] ld r9, [sp, -4] add sp, sp, SZ_PT_REGS + + ; return from pure kernel mode to delay slot rtie END(ret_from_exception)
Greg Kroah-Hartman
maintainerPATCH 288/342 ARCv2: SMP: Emulate IPI to self using software triggered interrupt
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vineet Gupta <[email protected]>
commit bb143f814ea488769ca2e79e0b376139cb5f134b upstream.
ARConnect/MCIP Inter-Core-Interrupt module can't send interrupt to local core. So use core intc capability to trigger software interrupt to self, using an unsued IRQ #21.
This showed up as csd deadlock with LTP trace_sched on a dual core system. This test acts as scheduler fuzzer, triggering all sorts of schedulting activity. Trouble starts with IPI to self, which doesn't get delivered (effectively lost due to H/w capability), but the msg intended to be sent remain enqueued in per-cpu @ipi_data.
All subsequent IPIs to this core from other cores get elided due to the IPI coalescing optimization in ipi_send_msg_one() where a pending msg implies an IPI already sent and assumes other core is yet to ack it. After the elided IPI, other core simply goes into csd_lock_wait() but never comes out as this core never sees the interrupt.
Fixes STAR 9001008624
--- arch/arc/include/asm/irqflags-arcv2.h | 11 +++++++++++ arch/arc/kernel/entry-arcv2.S | 11 ++++++----- arch/arc/kernel/mcip.c | 15 +++++++++++++++ 3 files changed, 32 insertions(+), 5 deletions(-)
arch/arc/include/asm/irqflags-arcv2.h +11 -0
@@ -22,6 +22,7 @@#define AUX_IRQ_CTRL 0x00E#define AUX_IRQ_ACT 0x043/* Active Intr across all levels */ #define AUX_IRQ_LVL_PEND 0x200/* Pending Intr across all levels */ +#define AUX_IRQ_HINT 0x201/* For generating Soft Interrupts */ #define AUX_IRQ_PRIORITY 0x206#define ICAUSE 0x40a#define AUX_IRQ_SELECT 0x40b
@@ -112,6 +113,16 @@ static inline int arch_irqs_disabled(voi return arch_irqs_disabled_flags(arch_local_save_flags()); } +static inline void arc_softirq_trigger (int irq) +{ +write_aux_reg (AUX_IRQ_HINT , irq); +} + +static inline void arc_softirq_clear (int irq) +{ +write_aux_reg (AUX_IRQ_HINT ,0 ); +} +#else .macro IRQ_DISABLE scratch
arch/arc/kernel/entry-arcv2.S +6 -5
@@ -45,11 +45,12 @@ VECTOR reserved ; Reserved slots VECTOR handle_interrupt ; (16) Timer0 VECTOR handle_interrupt ; unused (Timer1) VECTOR handle_interrupt ; unused (WDT) -VECTOR handle_interrupt ; (19) ICI (inter core interrupt) -VECTOR handle_interrupt -VECTOR handle_interrupt -VECTOR handle_interrupt -VECTOR handle_interrupt ; (23) End of fixed IRQs +VECTOR handle_interrupt ; (19) Inter core Interrupt (IPI) +VECTOR handle_interrupt ; (20) perf Interrupt +VECTOR handle_interrupt ; (21) Software Triggered Intr (Self IPI) +VECTOR handle_interrupt ; unused +VECTOR handle_interrupt ; (23) unused +# End of fixed IRQs .rept CONFIG_ARC_NUMBER_OF_INTERRUPTS - 8 VECTOR handle_interrupt
arch/arc/kernel/mcip.c +15 -0
@@ -11,9 +11,12 @@#include <linux/smp.h> #include <linux/irq.h> #include <linux/spinlock.h> +#include <asm/irqflags-arcv2.h> #include <asm/mcip.h> #include <asm/setup.h> +#define SOFTIRQ_IRQ 21 +static char smp_cpuinfo_buf[128 ];static int idu_detected;
@@ -22,6 +25,7 @@ static DEFINE_RAW_SPINLOCK(mcip_lock);static void mcip_setup_per_cpu (int cpu) {smp_ipi_irq_setup (cpu,IPI_IRQ ); +smp_ipi_irq_setup (cpu,SOFTIRQ_IRQ ); }static void mcip_ipi_send (int cpu)
@@ -29,6 +33,12 @@ static void mcip_ipi_send(int cpu)unsigned long flags;int ipi_was_pending; +/* ARConnect can only send IPI to others */ +if (unlikely (cpu ==raw_smp_processor_id ())) { +arc_softirq_trigger (SOFTIRQ_IRQ ); +return ; + } +/* * NOTE: We must spin here if the other cpu hasn't yet * serviced a previous message. This can burn lots
@@ -63,6 +73,11 @@ static void mcip_ipi_clear(int irq)unsigned long flags;unsigned int __maybe_unused copy; +if (unlikely (irq ==SOFTIRQ_IRQ )) { +arc_softirq_clear (irq); +return ; + } +raw_spin_lock_irqsave (&mcip_lock, flags);/* Who sent the IPI */
Greg Kroah-Hartman
maintainerPATCH 289/342 PCI/AER: Flush workqueue on device remove to avoid use-after-free
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sebastian Andrzej Siewior <[email protected]>
commit 4ae2182b1e3407de369f8c5d799543b7db74221b upstream.
A Root Port's AER structure (rpc) contains a queue of events. aer_irq() enqueues AER status information and schedules aer_isr() to dequeue and process it. When we remove a device, aer_remove() waits for the queue to be empty, then frees the rpc struct.
But aer_isr() references the rpc struct after dequeueing and possibly emptying the queue, which can cause a use-after-free error as in the following scenario with two threads, aer_isr() on the left and a concurrent aer_remove() on the right:
Thread A Thread B
-------- --------
aer_irq():
rpc->prod_idx++
aer_remove():
wait_event(rpc->prod_idx == rpc->cons_idx)
# now blocked until queue becomes empty
aer_isr(): # ...
rpc->cons_idx++ # unblocked because queue is now empty
... kfree(rpc)
mutex_unlock(&rpc->rpc_mutex)To prevent this problem, use flush_work() to wait until the last scheduled instance of aer_isr() has completed before freeing the rpc struct in aer_remove().
I reproduced this use-after-free by flashing a device FPGA and re-enumerating the bus to find the new device. With SLUB debug, this crashes with 0x6b bytes (POISON_FREE, the use-after-free magic number) in GPR25:
pcieport 0000:00:00.0: AER: Multiple Corrected error received: id=0000
Unable to handle kernel paging request for data at address 0x27ef9e3e Workqueue: events aer_isr GPR24: dd6aa000 6b6b6b6b 605f8378 605f8360 d99b12c0 604fc674 606b1704 d99b12c0 NIP [602f5328] pci_walk_bus+0xd4/0x104
--- drivers/pci/pcie/aer/aerdrv.c | 4 +--- drivers/pci/pcie/aer/aerdrv.h | 1 - drivers/pci/pcie/aer/aerdrv_core.c | 2 -- 3 files changed, 1 insertion(+), 6 deletions(-)
drivers/pci/pcie/aer/aerdrv.c +1 -3
@@ -262,7 +262,6 @@ static struct aer_rpc *aer_alloc_rpc(str rpc->rpd = dev;INIT_WORK (&rpc->dpc_handler, aer_isr);mutex_init (&rpc->rpc_mutex); -init_waitqueue_head (&rpc->wait_release);/* Use PCIe bus function to store rpc into PCIe device */ set_service_data (dev, rpc);
@@ -285,8 +284,7 @@ static void aer_remove(struct pcie_devicif (rpc->isr)free_irq (dev->irq, dev); -wait_event (rpc->wait_release, rpc->prod_idx == rpc->cons_idx); - +flush_work (&rpc->dpc_handler);aer_disable_rootport (rpc);kfree (rpc);set_service_data (dev,NULL );
drivers/pci/pcie/aer/aerdrv.h +0 -1
@@ -72,7 +72,6 @@ struct aer_rpc {* recovery on the same * root port hierarchy */ -wait_queue_head_t wait_release; };struct aer_broadcast_data {
drivers/pci/pcie/aer/aerdrv_core.c +0 -2
@@ -811,8 +811,6 @@ void aer_isr(struct work_struct *work)while (get_e_source (rpc, &e_src))aer_isr_one_error (p_device, &e_src);mutex_unlock (&rpc->rpc_mutex); - -wake_up (&rpc->wait_release); }/**
Greg Kroah-Hartman
maintainerPATCH 290/342 cpuset: make mm migration asynchronous
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <[email protected]>
commit e93ad19d05648397ef3bcb838d26aec06c245dc0 upstream.
If "cpuset.memory_migrate" is set, when a process is moved from one cpuset to another with a different memory node mask, pages in used by the process are migrated to the new set of nodes. This was performed synchronously in the ->attach() callback, which is synchronized against process management. Recently, the synchronization was changed from per-process rwsem to global percpu rwsem for simplicity and optimization.
Combined with the synchronous mm migration, this led to deadlocks because mm migration could schedule a work item which may in turn try to create a new worker blocking on the process management lock held from cgroup process migration path.
This heavy an operation shouldn't be performed synchronously from that deep inside cgroup migration in the first place. This patch punts the actual migration to an ordered workqueue and updates cgroup process migration and cpuset config update paths to flush the workqueue after all locks are released. This way, the operations still seem synchronous to userland without entangling mm migration with process management synchronization. CPU hotplug can also invoke mm migration but there's no reason for it to wait for mm migrations and thus doesn't synchronize against their completions.
--- include/linux/cpuset.h | 6 ++++ kernel/cgroup.c | 3 +- kernel/cpuset.c | 71 +++++++++++++++++++++++++++++++++---------------- 3 files changed, 57 insertions(+), 23 deletions(-)
include/linux/cpuset.h +6 -0
@@ -137,6 +137,8 @@ static inline void set_mems_allowed(node task_unlock(current); } +extern void cpuset_post_attach_flush (void ); +#else /* !CONFIG_CPUSETS */ static inline bool cpusets_enabled (void ) {return false; }
@@ -243,6 +245,10 @@ static inline bool read_mems_allowed_retreturn false; } +static inline void cpuset_post_attach_flush (void ) +{ +} +#endif /* !CONFIG_CPUSETS */ #endif /* _LINUX_CPUSET_H */
kernel/cgroup.c +2 -1
@@ -57,7 +57,7 @@#include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */ #include <linux/kthread.h> #include <linux/delay.h> - +#include <linux/cpuset.h> #include <linux/atomic.h> /*
@@ -2764,6 +2764,7 @@ out_unlock_rcu: out_unlock_threadgroup:percpu_up_write (&cgroup_threadgroup_rwsem);cgroup_kn_unlock (of->kn); +cpuset_post_attach_flush ();return ret ?: nbytes; }
kernel/cpuset.c +49 -22
116 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 291/342 cgroup: make sure a parent css isnt offlined before its children
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <[email protected]>
commit aa226ff4a1ce79f229c6b7a4c0a14e17fececd01 upstream.
There are three subsystem callbacks in css shutdown path - css_offline(), css_released() and css_free(). Except for css_released(), cgroup core didn't guarantee the order of invocation. css_offline() or css_free() could be called on a parent css before its children. This behavior is unexpected and led to bugs in cpu and memory controller.
This patch updates offline path so that a parent css is never offlined before its children. Each css keeps online_cnt which reaches zero iff itself and all its children are offline and offline_css() is invoked only after online_cnt reaches zero.
This fixes the memory controller bug and allows the fix for cpu controller.
--- include/linux/cgroup-defs.h | 6 ++++++ kernel/cgroup.c | 22 +++++++++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-)
include/linux/cgroup-defs.h +6 -0
@@ -133,6 +133,12 @@ struct cgroup_subsys_state {*/ u64 serial_nr; +/* +* Incremented by online self and children. Used to guarantee that +* parents are not offlined before their children. +*/ +atomic_t online_cnt; +/* percpu_ref killing and RCU release */ struct rcu_head rcu_head;struct work_struct destroy_work;
kernel/cgroup.c +17 -5
@@ -4784,6 +4784,7 @@ static void init_and_link_css(struct cgrINIT_LIST_HEAD (&css->sibling);INIT_LIST_HEAD (&css->children); css->serial_nr = css_serial_nr_next++; +atomic_set (&css->online_cnt,0 );if (cgroup_parent (cgrp)) { css->parent =cgroup_css (cgroup_parent (cgrp), ss);
@@ -4806,6 +4807,10 @@ static int online_css(struct cgroup_subsif (!ret) { css->flags |=CSS_ONLINE ;rcu_assign_pointer (css->cgroup->subsys[ss->id], css); + +atomic_inc (&css->online_cnt); +if (css->parent) +atomic_inc (&css->parent->online_cnt); }return ret; }
@@ -5037,10 +5042,15 @@ static void css_killed_work_fn(struct wo container_of(work, struct cgroup_subsys_state, destroy_work);mutex_lock (&cgroup_mutex); -offline_css (css); -mutex_unlock (&cgroup_mutex); -css_put (css); +do { +offline_css (css); +css_put (css); +/* @css can't go away while we're holding cgroup_mutex */ + css = css->parent; + }while (css &&atomic_dec_and_test (&css->online_cnt)); + +mutex_unlock (&cgroup_mutex); }/* css kill confirmation processing requires process context, bounce */
@@ -5049,8 +5059,10 @@ static void css_killed_ref_fn(struct perstruct cgroup_subsys_state *css = container_of(ref, struct cgroup_subsys_state, refcnt); -INIT_WORK (&css->destroy_work, css_killed_work_fn); -queue_work (cgroup_destroy_wq, &css->destroy_work); +if (atomic_dec_and_test (&css->online_cnt)) { +INIT_WORK (&css->destroy_work, css_killed_work_fn); +queue_work (cgroup_destroy_wq, &css->destroy_work); + } }/**
Greg Kroah-Hartman
maintainerPATCH 292/342 writeback: keep superblock pinned during cgroup writeback association switches
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <[email protected]>
commit 5ff8eaac1636bf6deae86491f4818c4c69d1a9ac upstream.
If cgroup writeback is in use, an inode is associated with a cgroup for writeback. If the inode's main dirtier changes to another cgroup, the association gets updated asynchronously. Nothing was pinning the superblock while such switches are in progress and superblock could go away while async switching is pending or in progress leading to crashes like the following.
kernel BUG at fs/jbd2/transaction.c:319!
invalid opcode: 0000 [#1] SMP DEBUG_PAGEALLOC
CPU: 1 PID: 29158 Comm: kworker/1:10 Not tainted 4.5.0-rc3 #51 Hardware name: Google Google, BIOS Google 01/01/2011 Workqueue: events inode_switch_wbs_work_fn task: ffff880213dbbd40 ti: ffff880209264000 task.ti: ffff880209264000 RIP: 0010:[<ffffffff803e6922>] [<ffffffff803e6922>] start_this_handle+0x382/0x3e0 RSP: 0018:ffff880209267c30 EFLAGS: 00010202 ... Call Trace: [<ffffffff803e6be4>] jbd2__journal_start+0xf4/0x190 [<ffffffff803cfc7e>] __ext4_journal_start_sb+0x4e/0x70 [<ffffffff803b31ec>] ext4_evict_inode+0x12c/0x3d0 [<ffffffff8035338b>] evict+0xbb/0x190 [<ffffffff80354190>] iput+0x130/0x190 [<ffffffff80360223>] inode_switch_wbs_work_fn+0x343/0x4c0 [<ffffffff80279819>] process_one_work+0x129/0x300 [<ffffffff80279b16>] worker_thread+0x126/0x480 [<ffffffff8027ed14>] kthread+0xc4/0xe0 [<ffffffff809771df>] ret_from_fork+0x3f/0x70
Fix it by bumping s_active while cgroup association switching is in flight.
fs/fs-writeback.c +11 -4
@@ -317,6 +317,7 @@ static void inode_switch_wbs_work_fn(struct work_struct *work)struct inode_switch_wbs_context *isw = container_of(work, struct inode_switch_wbs_context, work);struct inode *inode = isw->inode; +struct super_block *sb = inode->i_sb;struct address_space *mapping = inode->i_mapping;struct bdi_writeback *old_wb = inode->i_wb;struct bdi_writeback *new_wb = isw->new_wb;
@@ -423,6 +424,7 @@ skip_switch:wb_put (new_wb);iput (inode); +deactivate_super (sb);kfree (isw); }
@@ -469,11 +471,14 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)/* while holding I_WB_SWITCH, no one else can update the association */ spin_lock (&inode->i_lock); +if (inode->i_state & (I_WB_SWITCH |I_FREEING ) || -inode_to_wb (inode) == isw->new_wb) { -spin_unlock (&inode->i_lock); - goto out_free; - } +inode_to_wb (inode) == isw->new_wb) + goto out_unlock; + +if (!atomic_inc_not_zero (&inode->i_sb->s_active)) + goto out_unlock; + inode->i_state |=I_WB_SWITCH ;spin_unlock (&inode->i_lock);
@@ -489,6 +494,8 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)call_rcu (&isw->rcu_head, inode_switch_wbs_rcu_fn);return ; +out_unlock: +spin_unlock (&inode->i_lock); out_free:if (isw->new_wb)wb_put (isw->new_wb);
Greg Kroah-Hartman
maintainerPATCH 293/342 phy: core: fix wrong err handle for phy_power_on
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shawn Lin <[email protected]>
commit b82fcabe212a11698fd4b3e604d2f81d929d22f6 upstream.
If phy_pm_runtime_get_sync failed but we already enable regulator, current code return directly without doing regulator_disable. This patch fix this problem and cleanup err handle of phy_power_on to be more readable.
--- drivers/phy/phy-core.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
drivers/phy/phy-core.c +9 -7
@@ -275,20 +275,21 @@ EXPORT_SYMBOL_GPL(phy_exit);int phy_power_on (struct phy *phy) { -int ret; +int ret =0 ;if (!phy) -return 0 ; + goto out;if (phy->pwr) { ret =regulator_enable (phy->pwr);if (ret) -return ret; + goto out; } ret =phy_pm_runtime_get_sync (phy);if (ret <0 && ret != -ENOTSUPP ) -return ret; + goto err_pm_sync; + ret =0 ;/* Override possible ret == -ENOTSUPP */ mutex_lock (&phy->mutex);
@@ -296,19 +297,20 @@ int phy_power_on(struct phy *phy) ret = phy->ops->power_on (phy);if (ret <0 ) {dev_err (&phy->dev,"phy poweron failed --> %d\n" , ret); - goto out; + goto err_pwr_on; } } ++phy->power_count;mutex_unlock (&phy->mutex);return 0 ; -out: +err_pwr_on:mutex_unlock (&phy->mutex);phy_pm_runtime_put_sync (phy); +err_pm_sync:if (phy->pwr)regulator_disable (phy->pwr); - +out:return ret; }EXPORT_SYMBOL_GPL (phy_power_on);
Greg Kroah-Hartman
maintainerPATCH 294/342 i2c: i801: Adding Intel Lewisburg support for iTCO
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexandra Yates <[email protected]>
commit 1a1503c5396eb7f2edf4b8ef6067853014478c0c upstream.
Starting from Intel Sunrisepoint (Skylake PCH) the iTCO watchdog resources have been moved to reside under the i801 SMBus host controller whereas previously they were under the LPC device.
This patch adds Intel lewisburg SMBus support for iTCO device. It allows to load watchdog dynamically when the hardware is present.
--- drivers/i2c/busses/i2c-i801.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/i2c/busses/i2c-i801.c +2 -0
@@ -1271,6 +1271,8 @@ static int i801_probe(struct pci_dev *deswitch (dev->device) {case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS :case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS : +case PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS : +case PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS :case PCI_DEVICE_ID_INTEL_DNV_SMBUS : priv->features |=FEATURE_I2C_BLOCK_READ ; priv->features |=FEATURE_IRQ ;
Greg Kroah-Hartman
maintainerPATCH 295/342 bio: return EINTR if copying to user space got interrupted
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hannes Reinecke <[email protected]>
commit 2d99b55d378c996b9692a0c93dd25f4ed5d58934 upstream.
Commit 35dc248383bbab0a7203fca4d722875bc81ef091 introduced a check for current->mm to see if we have a user space context and only copies data if we do. Now if an IO gets interrupted by a signal data isn't copied into user space any more (as we don't have a user space context) but user space isn't notified about it.
This patch modifies the behaviour to return -EINTR from bio_uncopy_user() to notify userland that a signal has interrupted the syscall, otherwise it could lead to a situation where the caller may get a buffer with no data returned.
This can be reproduced by issuing SG_IO ioctl()s in one thread while constantly sending signals to it.
--- block/bio.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
block/bio.c +5 -2
@@ -1090,9 +1090,12 @@ int bio_uncopy_user(struct bio *bio)if (!bio_flagged (bio,BIO_NULL_MAPPED )) {/* * if we're in a workqueue, the request is orphaned, so -* don't copy into a random user address space, just free. +* don't copy into a random user address space, just free +* and return -EINTR so user space doesn't expect any data. */ -if (current->mm &&bio_data_dir (bio) ==READ ) +if (!current->mm) + ret = -EINTR ; +else if (bio_data_dir (bio) ==READ ) ret =bio_copy_to_iter (bio, bmd->iter);if (bmd->is_our_pages)bio_free_pages (bio);
Greg Kroah-Hartman
maintainerPATCH 296/342 block: fix use-after-free in dio_bio_complete
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Krinkin <[email protected]>
commit 7ddc971f86aa0a4cee9f6886c356a052461957ae upstream.
kasan reported the following error when i ran xfstest:
[ 701.826854] ================================================================== [ 701.826864] BUG: KASAN: use-after-free in dio_bio_complete+0x41a/0x600 at addr ffff880080b95f94 [ 701.826870] Read of size 4 by task loop2/3874 [ 701.826879] page:ffffea000202e540 count:0 mapcount:0 mapping: (null) index:0x0 [ 701.826890] flags: 0x100000000000000() [ 701.826895] page dumped because: kasan: bad access detected [ 701.826904] CPU: 3 PID: 3874 Comm: loop2 Tainted: G B W L 4.5.0-rc1-next-20160129 #83 [ 701.826910] Hardware name: LENOVO 23205NG/23205NG, BIOS G2ET95WW (2.55 ) 07/09/2013 [ 701.826917] ffff88008fadf800 ffff88008fadf758 ffffffff81ca67bb 0000000041b58ab3 [ 701.826941] ffffffff830d1e74 ffffffff81ca6724 ffff88008fadf748 ffffffff8161c05c [ 701.826963] 0000000000000282 ffff88008fadf800 ffffed0010172bf2 ffffea000202e540 [ 701.826987] Call Trace: [ 701.826997] [<ffffffff81ca67bb>] dump_stack+0x97/0xdc [ 701.827005] [<ffffffff81ca6724>] ? _atomic_dec_and_lock+0xc4/0xc4 [ 701.827014] [<ffffffff8161c05c>] ? __dump_page+0x32c/0x490 [ 701.827023] [<ffffffff816b0d03>] kasan_report_error+0x5f3/0x8b0 [ 701.827033] [<ffffffff817c302a>] ? dio_bio_complete+0x41a/0x600 [ 701.827040] [<ffffffff816b1119>] __asan_report_load4_noabort+0x59/0x80 [ 701.827048] [<ffffffff817c302a>] ? dio_bio_complete+0x41a/0x600 [ 701.827053] [<ffffffff817c302a>] dio_bio_complete+0x41a/0x600 [ 701.827057] [<ffffffff81bd19c8>] ? blk_queue_exit+0x108/0x270 [ 701.827060] [<ffffffff817c32b0>] dio_bio_end_aio+0xa0/0x4d0 [ 701.827063] [<ffffffff817c3210>] ? dio_bio_complete+0x600/0x600 [ 701.827067] [<ffffffff81bd2806>] ? blk_account_io_completion+0x316/0x5d0 [ 701.827070] [<ffffffff81bafe89>] bio_endio+0x79/0x200 [ 701.827074] [<ffffffff81bd2c9f>] blk_update_request+0x1df/0xc50 [ 701.827078] [<ffffffff81c02c27>] blk_mq_end_request+0x57/0x120 [ 701.827081] [<ffffffff81c03670>] __blk_mq_complete_request+0x310/0x590 [ 701.827084] [<ffffffff812348d8>] ? set_next_entity+0x2f8/0x2ed0 [ 701.827088] [<ffffffff8124b34d>] ? put_prev_entity+0x22d/0x2a70 [ 701.827091] [<ffffffff81c0394b>] blk_mq_complete_request+0x5b/0x80 [ 701.827094] [<ffffffff821e2a33>] loop_queue_work+0x273/0x19d0 [ 701.827098] [<ffffffff811f6578>] ? finish_task_switch+0x1c8/0x8e0 [ 701.827101] [<ffffffff8129d058>] ? trace_hardirqs_on_caller+0x18/0x6c0 [ 701.827104] [<ffffffff821e27c0>] ? lo_read_simple+0x890/0x890 [ 701.827108] [<ffffffff8129dd60>] ? debug_check_no_locks_freed+0x350/0x350 [ 701.827111] [<ffffffff811f63b0>] ? __hrtick_start+0x130/0x130 [ 701.827115] [<ffffffff82a0c8f6>] ? __schedule+0x936/0x20b0 [ 701.827118] [<ffffffff811dd6bd>] ? kthread_worker_fn+0x3ed/0x8d0 [ 701.827121] [<ffffffff811dd4ed>] ? kthread_worker_fn+0x21d/0x8d0 [ 701.827125] [<ffffffff8129d058>] ? trace_hardirqs_on_caller+0x18/0x6c0 [ 701.827128] [<ffffffff811dd57f>] kthread_worker_fn+0x2af/0x8d0 [ 701.827132] [<ffffffff811dd2d0>] ? __init_kthread_worker+0x170/0x170 [ 701.827135] [<ffffffff82a1ea46>] ? _raw_spin_unlock_irqrestore+0x36/0x60 [ 701.827138] [<ffffffff811dd2d0>] ? __init_kthread_worker+0x170/0x170 [ 701.827141] [<ffffffff811dd2d0>] ? __init_kthread_worker+0x170/0x170 [ 701.827144] [<ffffffff811dd00b>] kthread+0x24b/0x3a0 [ 701.827148] [<ffffffff811dcdc0>] ? kthread_create_on_node+0x4c0/0x4c0 [ 701.827151] [<ffffffff8129d70d>] ? trace_hardirqs_on+0xd/0x10 [ 701.827155] [<ffffffff8116d41d>] ? do_group_exit+0xdd/0x350 [ 701.827158] [<ffffffff811dcdc0>] ? kthread_create_on_node+0x4c0/0x4c0 [ 701.827161] [<ffffffff82a1f52f>] ret_from_fork+0x3f/0x70 [ 701.827165] [<ffffffff811dcdc0>] ? kthread_create_on_node+0x4c0/0x4c0 [ 701.827167] Memory state around the buggy address: [ 701.827170] ffff880080b95e80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 701.827172] ffff880080b95f00: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 701.827175] >ffff880080b95f80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 701.827177] ^ [ 701.827179] ffff880080b96000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 701.827182] ffff880080b96080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 701.827183] ==================================================================
The problem is that bio_check_pages_dirty calls bio_put, so we must not access bio fields after bio_check_pages_dirty.
fs/direct-io.c +1 -1
@@ -472,8 +472,8 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio) dio->io_error = -EIO ;if (dio->is_async && dio->rw ==READ && dio->should_dirty) { -bio_check_pages_dirty (bio);/* transfers ownership */ err = bio->bi_error; +bio_check_pages_dirty (bio);/* transfers ownership */ }else {bio_for_each_segment_all (bvec, bio, i) {struct page *page = bvec->bv_page;
Greg Kroah-Hartman
maintainerPATCH 297/342 nfs: fix nfs_size_to_loff_t
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig <[email protected]>
commit 50ab8ec74a153eb30db26529088bc57dd700b24c upstream.
See http: //www.infradead.org/rpr.html
X-Evolution-Source: [email protected]
Content-Transfer-Encoding: 8bit
Mime-Version: 1.0
We support OFFSET_MAX just fine, so don't round down below it. Also switch to using min_t to make the helper more readable.
--- include/linux/nfs_fs.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
include/linux/nfs_fs.h +1 -3
@@ -544,9 +544,7 @@ extern int nfs_readpage_async(struct nfstatic inline loff_t nfs_size_to_loff_t (__u64 size) { -if (size > (__u64 )OFFSET_MAX -1 ) -return OFFSET_MAX -1 ; -return (loff_t ) size; +return min_t (u64, size,OFFSET_MAX ); } static inline ino_t
Greg Kroah-Hartman
maintainerPATCH 298/342 NFSv4: Fix a dentry leak on alias use
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Coddington <[email protected]>
commit d9dfd8d741683347ee159d25f5b50c346a0df557 upstream.
In the case where d_add_unique() finds an appropriate alias to use it will have already incremented the reference count. An additional dget() to swap the open context's dentry is unnecessary and will leak a reference.
--- fs/nfs/nfs4proc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/nfs/nfs4proc.c +2 -2
@@ -2461,9 +2461,9 @@ static int _nfs4_open_and_get_state(stru dentry =d_add_unique (dentry,igrab (state->inode));if (dentry ==NULL ) { dentry = opendata->dentry; - }else if (dentry != ctx->dentry) { + }else {dput (ctx->dentry); - ctx->dentry =dget (dentry); + ctx->dentry = dentry; }nfs_set_verifier (dentry,nfs_save_change_attribute (d_inode (opendata->dir)));
Greg Kroah-Hartman
maintainerPATCH 299/342 of/irq: Fix msi-map calculation for nonzero rid-base
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Robin Murphy <[email protected]>
commit 5d589d81acf974d23af98044aac56c6339d659f8 upstream.
The existing msi-map code is fine for shifting the entire RID space upwards, but attempting finer-grained remapping reveals a bug. It turns out that we are mistakenly treating the msi-base part as an offset, not as a new base to remap onto, so things get squiffy when rid-base is nonzero. Fix this, and at the same time add a sanity check against having msi-map-mask clash with a nonzero rid-base, as that's another thing one can easily get wrong.
--- drivers/of/irq.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/of/irq.c +8 -1
@@ -636,6 +636,13 @@ static u32 __of_msi_map_rid(struct devic msi_base =be32_to_cpup (msi_map +2 ); rid_len =be32_to_cpup (msi_map +3 ); +if (rid_base & ~map_mask) { +dev_err (parent_dev, +"Invalid msi-map translation - msi-map-mask (0x%x) ignores rid-base (0x%x)\n" , + map_mask, rid_base); +return rid_out; + } + msi_controller_node =of_find_node_by_phandle (phandle); matched = (masked_rid >= rid_base &&
@@ -655,7 +662,7 @@ static u32 __of_msi_map_rid(struct devicif (!matched)return rid_out; - rid_out = masked_rid + msi_base; + rid_out = masked_rid - rid_base + msi_base; dev_dbg(dev, "msi-map at: %s, using mask %08x, rid-base: %08x, msi-base: %08x, length: %08x, rid: %08x -> %08x\n", dev_name(parent_dev), map_mask, rid_base, msi_base,
Greg Kroah-Hartman
maintainerPATCH 300/342 KVM: async_pf: do not warn on page allocation failures
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Borntraeger <[email protected]>
commit d7444794a02ff655eda87e3cc54e86b940e7736f upstream.
In async_pf we try to allocate with NOWAIT to get an element quickly or fail. This code also handle failures gracefully. Lets silence potential page allocation failures under load.
qemu-system-s39: page allocation failure: order:0,mode:0x2200000 [...]
Call Trace: ([<00000000001146b8>] show_trace+0xf8/0x148) [<000000000011476a>] show_stack+0x62/0xe8 [<00000000004a36b8>] dump_stack+0x70/0x98 [<0000000000272c3a>] warn_alloc_failed+0xd2/0x148 [<000000000027709e>] __alloc_pages_nodemask+0x94e/0xb38 [<00000000002cd36a>] new_slab+0x382/0x400 [<00000000002cf7ac>] ___slab_alloc.constprop.30+0x2dc/0x378 [<00000000002d03d0>] kmem_cache_alloc+0x160/0x1d0 [<0000000000133db4>] kvm_setup_async_pf+0x6c/0x198 [<000000000013dee8>] kvm_arch_vcpu_ioctl_run+0xd48/0xd58 [<000000000012fcaa>] kvm_vcpu_ioctl+0x372/0x690 [<00000000002f66f6>] do_vfs_ioctl+0x3be/0x510 [<00000000002f68ec>] SyS_ioctl+0xa4/0xb8 [<0000000000781c5e>] system_call+0xd6/0x264
[<000003ffa24fa06a>] 0x3ffa24fa06a
--- virt/kvm/async_pf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
virt/kvm/async_pf.c +1 -1
@@ -173,7 +173,7 @@ int kvm_setup_async_pf(struct kvm_vcpu ** do alloc nowait since if we are going to sleep anyway we * may as well sleep faulting in page */ - work =kmem_cache_zalloc (async_pf_cache,GFP_NOWAIT ); + work =kmem_cache_zalloc (async_pf_cache,GFP_NOWAIT | __GFP_NOWARN);if (!work)return 0 ;
Greg Kroah-Hartman
maintainerPATCH 301/342 KVM: arm/arm64: vgic: Ensure bitmaps are long enough
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mark Rutland <[email protected]>
commit 236cf17c2502007a9d2dda3c39fb0d9a6bd03cc2 upstream.
When we allocate bitmaps in vgic_vcpu_init_maps, we divide the number of bits we need by 8 to figure out how many bytes to allocate. However, bitmap elements are always accessed as unsigned longs, and if we didn't happen to allocate a size such that size % sizeof(unsigned long) == 0, bitmap accesses may go past the end of the allocation.
When using KASAN (which does byte-granular access checks), this results in a continuous stream of BUGs whenever these bitmaps are accessed:
=============================================================================
BUG kmalloc-128 (Tainted: G B ): kasan: bad access detected
-----------------------------------------------------------------------------
INFO: Allocated in vgic_init.part.25+0x55c/0x990 age=7493 cpu=3 pid=1730
INFO: Slab 0xffffffbde6d5da40 objects=16 used=15 fp=0xffffffc935769700 flags=0x4000000000000080
INFO: Object 0xffffffc935769500 @offset=1280 fp=0x (null)
Bytes b4 ffffffc9357694f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ Object ffffffc935769500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ Object ffffffc935769510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ Object ffffffc935769520: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ Object ffffffc935769530: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ Object ffffffc935769540: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ Object ffffffc935769550: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ Object ffffffc935769560: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ Object ffffffc935769570: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ Padding ffffffc9357695b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ Padding ffffffc9357695c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ Padding ffffffc9357695d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ Padding ffffffc9357695e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ Padding ffffffc9357695f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
CPU: 3 PID: 1740 Comm: kvm-vcpu-0 Tainted: G B 4.4.0+ #17
Hardware name: ARM Juno development board (r1) (DT)
Call trace:
[<ffffffc00008e770>] dump_backtrace+0x0/0x280
[<ffffffc00008ea04>] show_stack+0x14/0x20
[<ffffffc000726360>] dump_stack+0x100/0x188
[<ffffffc00030d324>] print_trailer+0xfc/0x168
[<ffffffc000312294>] object_err+0x3c/0x50
[<ffffffc0003140fc>] kasan_report_error+0x244/0x558
[<ffffffc000314548>] __asan_report_load8_noabort+0x48/0x50
[<ffffffc000745688>] __bitmap_or+0xc0/0xc8
[<ffffffc0000d9e44>] kvm_vgic_flush_hwstate+0x1bc/0x650
[<ffffffc0000c514c>] kvm_arch_vcpu_ioctl_run+0x2ec/0xa60
[<ffffffc0000b9a6c>] kvm_vcpu_ioctl+0x474/0xa68
[<ffffffc00036b7b0>] do_vfs_ioctl+0x5b8/0xcb0
[<ffffffc00036bf34>] SyS_ioctl+0x8c/0xa0
[<ffffffc000086cb0>] el0_svc_naked+0x24/0x28
Memory state around the buggy address:
ffffffc935769400: 00 00 fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffffffc935769480: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffffffc935769500: 04 fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
^
ffffffc935769580: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffffffc935769600: 00 00 00 00 fc fc fc fc fc fc fc fc fc fc fc fc
==================================================================Fix the issue by always allocating a multiple of sizeof(unsigned long), as we do elsewhere in the vgic code.
--- virt/kvm/arm/vgic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
virt/kvm/arm/vgic.c +2 -2
@@ -1875,8 +1875,8 @@ void kvm_vgic_vcpu_destroy(struct kvm_vcstatic int vgic_vcpu_init_maps (struct kvm_vcpu *vcpu,int nr_irqs) {struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; - -int sz = (nr_irqs -VGIC_NR_PRIVATE_IRQS ) /8 ; +int nr_longs =BITS_TO_LONGS (nr_irqs -VGIC_NR_PRIVATE_IRQS ); +int sz = nr_longs *sizeof (unsigned long ); vgic_cpu->pending_shared =kzalloc (sz,GFP_KERNEL ); vgic_cpu->active_shared =kzalloc (sz,GFP_KERNEL ); vgic_cpu->pend_act_shared =kzalloc (sz,GFP_KERNEL );
Greg Kroah-Hartman
maintainerPATCH 302/342 KVM: x86: fix missed hardware breakpoints
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paolo Bonzini <[email protected]>
commit 172b2386ed16a9143d9a456aae5ec87275c61489 upstream.
Sometimes when setting a breakpoint a process doesn't stop on it. This is because the debug registers are not loaded correctly on VCPU load.
The following simple reproducer from Oleg Nesterov tries using debug registers in two threads. To see the bug, run a 2-VCPU guest with "taskset -c 0" and run "./bp 0 1" inside the guest.
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <asm/debugreg.h>
#include <assert.h>
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
unsigned long encode_dr7(int drnum, int enable, unsigned int type, unsigned int len)
{
unsigned long dr7;
dr7 = ((len | type) & 0xf)
<< (DR_CONTROL_SHIFT + drnum * DR_CONTROL_SIZE);
if (enable)
dr7 |= (DR_GLOBAL_ENABLE << (drnum * DR_ENABLE_SIZE));
return dr7;
}
int write_dr(int pid, int dr, unsigned long val)
{
return ptrace(PTRACE_POKEUSER, pid,
offsetof (struct user, u_debugreg[dr]),
val);
}
void set_bp(pid_t pid, void *addr)
{
unsigned long dr7;
assert(write_dr(pid, 0, (long)addr) == 0);
dr7 = encode_dr7(0, 1, DR_RW_EXECUTE, DR_LEN_1);
assert(write_dr(pid, 7, dr7) == 0);
}
void *get_rip(int pid)
{
return (void*)ptrace(PTRACE_PEEKUSER, pid,
offsetof(struct user, regs.rip), 0);
}
void test(int nr)
{
void *bp_addr = &&label + nr, *bp_hit;
int pid;
printf("test bp %d\n", nr);
assert(nr < 16); // see 16 asm nops below
pid = fork();
if (!pid) {
assert(ptrace(PTRACE_TRACEME, 0,0,0) == 0);
kill(getpid(), SIGSTOP);
for (;;) {
label: asm (
"nop; nop; nop; nop;"
"nop; nop; nop; nop;"
"nop; nop; nop; nop;"
"nop; nop; nop; nop;"
);
}
}
assert(pid == wait(NULL));
set_bp(pid, bp_addr);
for (;;) {
assert(ptrace(PTRACE_CONT, pid, 0, 0) == 0);
assert(pid == wait(NULL));
bp_hit = get_rip(pid);
if (bp_hit != bp_addr)
fprintf(stderr, "ERR!! hit wrong bp %ld != %d\n",
bp_hit - &&label, nr);
}
}
int main(int argc, const char *argv[])
{
while (--argc) {
int nr = atoi(*++argv);
if (!fork())
test(nr);
}
while (wait(NULL) > 0)
;
return 0;
}--- arch/x86/kvm/x86.c | 1 + 1 file changed, 1 insertion(+)
arch/x86/kvm/x86.c +1 -0
@@ -2736,6 +2736,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu }kvm_make_request (KVM_REQ_STEAL_UPDATE , vcpu); + vcpu->arch.switch_db_regs |=KVM_DEBUGREG_RELOAD ; }void kvm_arch_vcpu_put (struct kvm_vcpu *vcpu)
Greg Kroah-Hartman
maintainerPATCH 303/342 KVM: x86: fix conversion of addresses to linear in 32-bit protected mode
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paolo Bonzini <[email protected]>
commit 0c1d77f4ba5cc9c05a29adca3d6466cdf4969b70 upstream.
Commit e8dd2d2d641c ("Silence compiler warning in arch/x86/kvm/emulate.c", 2015-09-06) broke boot of the Hurd. The bug is that the "default:" case actually could modify "la", but after the patch this change is not reflected in *linear.
The bug is visible whenever a non-zero segment base causes the linear address to wrap around the 4GB mark.
--- arch/x86/kvm/emulate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/kvm/emulate.c +2 -2
@@ -650,10 +650,10 @@ static __always_inline int __linearize(su16 sel; la =seg_base (ctxt, addr.seg) + addr.ea; - *linear = la; *max_size =0 ;switch (mode) {case X86EMUL_MODE_PROT64 : + *linear = la;if (is_noncanonical_address (la)) goto bad;
@@ -662,6 +662,7 @@ static __always_inline int __linearize(s goto bad;break ;default : + *linear = la = (u32 )la; usable = ctxt->ops->get_segment (ctxt, &sel, &desc,NULL , addr.seg);if (!usable)
@@ -689,7 +690,6 @@ static __always_inline int __linearize(sif (size > *max_size) goto bad; } - la &= (u32)-1 ;break ; }if (insn_aligned (ctxt, size) && ((la & (size -1 )) !=0 ))
Greg Kroah-Hartman
maintainerPATCH 304/342 KVM: x86: MMU: fix ubsan index-out-of-range warning
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Krinkin <[email protected]>
commit 17e4bce0ae63c7e03f3c7fa8d80890e7af3d4971 upstream.
Ubsan reports the following warning due to a typo in update_accessed_dirty_bits template, the patch fixes the typo:
[ 168.791851] ================================================================================ [ 168.791862] UBSAN: Undefined behaviour in arch/x86/kvm/paging_tmpl.h:252:15 [ 168.791866] index 4 is out of range for type 'u64 [4]' [ 168.791871] CPU: 0 PID: 2950 Comm: qemu-system-x86 Tainted: G O L 4.5.0-rc5-next-20160222 #7 [ 168.791873] Hardware name: LENOVO 23205NG/23205NG, BIOS G2ET95WW (2.55 ) 07/09/2013 [ 168.791876] 0000000000000000 ffff8801cfcaf208 ffffffff81c9f780 0000000041b58ab3 [ 168.791882] ffffffff82eb2cc1 ffffffff81c9f6b4 ffff8801cfcaf230 ffff8801cfcaf1e0 [ 168.791886] 0000000000000004 0000000000000001 0000000000000000 ffffffffa1981600 [ 168.791891] Call Trace: [ 168.791899] [<ffffffff81c9f780>] dump_stack+0xcc/0x12c [ 168.791904] [<ffffffff81c9f6b4>] ? _atomic_dec_and_lock+0xc4/0xc4 [ 168.791910] [<ffffffff81da9e81>] ubsan_epilogue+0xd/0x8a [ 168.791914] [<ffffffff81daafa2>] __ubsan_handle_out_of_bounds+0x15c/0x1a3 [ 168.791918] [<ffffffff81daae46>] ? __ubsan_handle_shift_out_of_bounds+0x2bd/0x2bd [ 168.791922] [<ffffffff811287ef>] ? get_user_pages_fast+0x2bf/0x360 [ 168.791954] [<ffffffffa1794050>] ? kvm_largepages_enabled+0x30/0x30 [kvm] [ 168.791958] [<ffffffff81128530>] ? __get_user_pages_fast+0x360/0x360 [ 168.791987] [<ffffffffa181b818>] paging64_walk_addr_generic+0x1b28/0x2600 [kvm] [ 168.792014] [<ffffffffa1819cf0>] ? init_kvm_mmu+0x1100/0x1100 [kvm] [ 168.792019] [<ffffffff8129e350>] ? debug_check_no_locks_freed+0x350/0x350 [ 168.792044] [<ffffffffa1819cf0>] ? init_kvm_mmu+0x1100/0x1100 [kvm] [ 168.792076] [<ffffffffa181c36d>] paging64_gva_to_gpa+0x7d/0x110 [kvm] [ 168.792121] [<ffffffffa181c2f0>] ? paging64_walk_addr_generic+0x2600/0x2600 [kvm] [ 168.792130] [<ffffffff812e848b>] ? debug_lockdep_rcu_enabled+0x7b/0x90 [ 168.792178] [<ffffffffa17d9a4a>] emulator_read_write_onepage+0x27a/0x1150 [kvm] [ 168.792208] [<ffffffffa1794d44>] ? __kvm_read_guest_page+0x54/0x70 [kvm] [ 168.792234] [<ffffffffa17d97d0>] ? kvm_task_switch+0x160/0x160 [kvm] [ 168.792238] [<ffffffff812e848b>] ? debug_lockdep_rcu_enabled+0x7b/0x90 [ 168.792263] [<ffffffffa17daa07>] emulator_read_write+0xe7/0x6d0 [kvm] [ 168.792290] [<ffffffffa183b620>] ? em_cr_write+0x230/0x230 [kvm] [ 168.792314] [<ffffffffa17db005>] emulator_write_emulated+0x15/0x20 [kvm] [ 168.792340] [<ffffffffa18465f8>] segmented_write+0xf8/0x130 [kvm] [ 168.792367] [<ffffffffa1846500>] ? em_lgdt+0x20/0x20 [kvm] [ 168.792374] [<ffffffffa14db512>] ? vmx_read_guest_seg_ar+0x42/0x1e0 [kvm_intel] [ 168.792400] [<ffffffffa1846d82>] writeback+0x3f2/0x700 [kvm] [ 168.792424] [<ffffffffa1846990>] ? em_sidt+0xa0/0xa0 [kvm] [ 168.792449] [<ffffffffa185554d>] ? x86_decode_insn+0x1b3d/0x4f70 [kvm] [ 168.792474] [<ffffffffa1859032>] x86_emulate_insn+0x572/0x3010 [kvm] [ 168.792499] [<ffffffffa17e71dd>] x86_emulate_instruction+0x3bd/0x2110 [kvm] [ 168.792524] [<ffffffffa17e6e20>] ? reexecute_instruction.part.110+0x2e0/0x2e0 [kvm] [ 168.792532] [<ffffffffa14e9a81>] handle_ept_misconfig+0x61/0x460 [kvm_intel] [ 168.792539] [<ffffffffa14e9a20>] ? handle_pause+0x450/0x450 [kvm_intel] [ 168.792546] [<ffffffffa15130ea>] vmx_handle_exit+0xd6a/0x1ad0 [kvm_intel] [ 168.792572] [<ffffffffa17f6a6c>] ? kvm_arch_vcpu_ioctl_run+0xbdc/0x6090 [kvm] [ 168.792597] [<ffffffffa17f6bcd>] kvm_arch_vcpu_ioctl_run+0xd3d/0x6090 [kvm] [ 168.792621] [<ffffffffa17f6a6c>] ? kvm_arch_vcpu_ioctl_run+0xbdc/0x6090 [kvm] [ 168.792627] [<ffffffff8293b530>] ? __ww_mutex_lock_interruptible+0x1630/0x1630 [ 168.792651] [<ffffffffa17f5e90>] ? kvm_arch_vcpu_runnable+0x4f0/0x4f0 [kvm] [ 168.792656] [<ffffffff811eeb30>] ? preempt_notifier_unregister+0x190/0x190 [ 168.792681] [<ffffffffa17e0447>] ? kvm_arch_vcpu_load+0x127/0x650 [kvm] [ 168.792704] [<ffffffffa178e9a3>] kvm_vcpu_ioctl+0x553/0xda0 [kvm] [ 168.792727] [<ffffffffa178e450>] ? vcpu_put+0x40/0x40 [kvm] [ 168.792732] [<ffffffff8129e350>] ? debug_check_no_locks_freed+0x350/0x350 [ 168.792735] [<ffffffff82946087>] ? _raw_spin_unlock+0x27/0x40 [ 168.792740] [<ffffffff8163a943>] ? handle_mm_fault+0x1673/0x2e40 [ 168.792744] [<ffffffff8129daa8>] ? trace_hardirqs_on_caller+0x478/0x6c0 [ 168.792747] [<ffffffff8129dcfd>] ? trace_hardirqs_on+0xd/0x10 [ 168.792751] [<ffffffff812e848b>] ? debug_lockdep_rcu_enabled+0x7b/0x90 [ 168.792756] [<ffffffff81725a80>] do_vfs_ioctl+0x1b0/0x12b0 [ 168.792759] [<ffffffff817258d0>] ? ioctl_preallocate+0x210/0x210 [ 168.792763] [<ffffffff8174aef3>] ? __fget+0x273/0x4a0 [ 168.792766] [<ffffffff8174acd0>] ? __fget+0x50/0x4a0 [ 168.792770] [<ffffffff8174b1f6>] ? __fget_light+0x96/0x2b0 [ 168.792773] [<ffffffff81726bf9>] SyS_ioctl+0x79/0x90 [ 168.792777] [<ffffffff82946880>] entry_SYSCALL_64_fastpath+0x23/0xc1 [ 168.792780] ================================================================================
--- arch/x86/kvm/paging_tmpl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kvm/paging_tmpl.h +1 -1
@@ -249,7 +249,7 @@ static int FNAME(update_accessed_dirty_breturn ret;kvm_vcpu_mark_page_dirty (vcpu, table_gfn); - walker->ptes[level] = pte; + walker->ptes[level -1 ] = pte; }return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 305/342 powerpc/eeh: Fix partial hotplug criterion
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gavin Shan <[email protected]>
commit f6bf0fa14cf848ae770e0b7842c9b11ce2f01645 upstream.
During error recovery, the device could be removed as part of the partial hotplug. The criterion used to come with partial hotplug
is: if the device driver provides error_detected(), slot_reset() and resume() callbacks, it's immune from hotplug. Otherwise, it's going to experience partial hotplug during EEH recovery. But the criterion isn't correct enough: mlx4_core driver for Mellanox adapters provides error_detected(), slot_reset() callbacks, but resume() isn't there. Those Mellanox adapters won't be to involved in the partial hotplug.
This fixes the criterion to a practical one: adpater with driver that provides error_detected(), slot_reset() will be immune from partial hotplug. resume() isn't mandatory.
--- arch/powerpc/kernel/eeh_driver.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
arch/powerpc/kernel/eeh_driver.c +1 -2
@@ -418,8 +418,7 @@ static void *eeh_rmv_device(void *data,eeh_pcid_put (dev);if (driver->err_handler && driver->err_handler->error_detected && - driver->err_handler->slot_reset && - driver->err_handler->resume) + driver->err_handler->slot_reset)return NULL ; }
Greg Kroah-Hartman
maintainerPATCH 306/342 tracing: Fix showing function event in available_events
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steven Rostedt (Red Hat) <[email protected]>
commit d045437a169f899dfb0f6f7ede24cc042543ced9 upstream.
The ftrace:function event is only displayed for parsing the function tracer data. It is not used to enable function tracing, and does not include an "enable" file in its event directory.
Originally, this event was kept separate from other events because it did not have a ->reg parameter. But perf added a "reg" parameter for its use which caused issues, because it made the event available to functions where it was not compatible for.
Commit 9b63776fa3ca9 "tracing: Do not enable function event with enable" added a TRACE_EVENT_FL_IGNORE_ENABLE flag that prevented the function event from being enabled by normal trace events. But this commit missed keeping the function event from being displayed by the "available_events" directory, which is used to show what events can be enabled by set_event.
One documented way to enable all events is to:
cat available_events > set_event
But because the function event is displayed in the available_events, this now causes an INVALID error:
cat: write error: Invalid argument
--- kernel/trace/trace_events.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/trace/trace_events.c +2 -1
@@ -869,7 +869,8 @@ t_next(struct seq_file *m, void *v, loff* The ftrace subsystem is for showing formats only. * They can not be enabled or disabled via the event files. */ -if (call->class && call->class->reg) +if (call->class && call->class->reg && + !(call->flags &TRACE_EVENT_FL_IGNORE_ENABLE ))return file; }
Greg Kroah-Hartman
maintainerPATCH 307/342 sunrpc/cache: fix off-by-one in qword_get()
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Hajnoczi <[email protected]>
commit b7052cd7bcf3c1478796e93e3dff2b44c9e82943 upstream.
The qword_get() function NUL-terminates its output buffer. If the input string is in hex format \xXXXX... and the same length as the output buffer, there is an off-by-one:
int qword_get(char **bpp, char *dest, int bufsize)
{
...
while (len < bufsize) {
...
*dest++ = (h << 4) | l;
len++;
}
...
*dest = '\0';
return len;
}This patch ensures the NUL terminator doesn't fall outside the output buffer.
--- net/sunrpc/cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sunrpc/cache.c +1 -1
@@ -1225,7 +1225,7 @@ int qword_get(char **bpp, char *dest, inif (bp[0 ] =='\\' && bp[1 ] =='x' ) {/* HEX STRING */ bp +=2 ; -while (len < bufsize) { +while (len < bufsize -1 ) {int h, l; h =hex_to_bin (bp[0 ]);
Greg Kroah-Hartman
maintainerPATCH 308/342 kernel/resource.c: fix muxed resource handling in __request_region()
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Simon Guinot <[email protected]>
commit 59ceeaaf355fa0fb16558ef7c24413c804932ada upstream.
In __request_region, if a conflict with a BUSY and MUXED resource is detected, then the caller goes to sleep and waits for the resource to be released. A pointer on the conflicting resource is kept. At wake-up this pointer is used as a parent to retry to request the region.
A first problem is that this pointer might well be invalid (if for example the conflicting resource have already been freed). Another problem is that the next call to __request_region() fails to detect a remaining conflict. The previously conflicting resource is passed as a parameter and __request_region() will look for a conflict among the children of this resource and not at the resource itself. It is likely to succeed anyway, even if there is still a conflict.
Instead, the parent of the conflicting resource should be passed to __request_region().
As a fix, this patch doesn't update the parent resource pointer in the case we have to wait for a muxed region right after.
--- kernel/resource.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
kernel/resource.c +3 -2
@@ -1083,9 +1083,10 @@ struct resource * __request_region(strucif (!conflict)break ;if (conflict != parent) { - parent = conflict; -if (!(conflict->flags &IORESOURCE_BUSY )) +if (!(conflict->flags &IORESOURCE_BUSY )) { + parent = conflict;continue ; + } }if (conflict->flags & flags &IORESOURCE_MUXED ) {add_wait_queue (&muxed_resource_wait, &wait);
Greg Kroah-Hartman
maintainerPATCH 309/342 do_last(): dont let a bogus return value from ->open() et.al. to confuse us
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
commit c80567c82ae4814a41287618e315a60ecf513be6 upstream.
... into returning a positive to path_openat(), which would interpret that as "symlink had been encountered" and proceed to corrupt memory, etc. It can only happen due to a bug in some ->open() instance or in some LSM hook, etc., so we report any such event *and* make sure it doesn't trick us into further unpleasantness.
--- fs/namei.c | 4 ++++ 1 file changed, 4 insertions(+)
fs/namei.c +4 -0
@@ -3210,6 +3210,10 @@ opened: goto exit_fput; } out: +if (unlikely (error >0 )) { +WARN_ON (1 ); + error = -EINVAL ; + }if (got_write)mnt_drop_write (nd->path.mnt);path_put (&save_parent);
Greg Kroah-Hartman
maintainerPATCH 310/342 ARM: OMAP2+: Fix onenand initialization to avoid filesystem corruption
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ivaylo Dimitrov <[email protected]>
commit 3f315c5b850fa7aff73f50de8e316b98f611a32b upstream.
Commit e7b11dc7b77b ("ARM: OMAP2+: Fix onenand rate detection to avoid filesystem corruption") partially fixed onenand configuration when GPMC module is reset. Finish the job by also providing the correct values in ONENAND_REG_SYS_CFG1 register.
filesystem corruption")
--- arch/arm/mach-omap2/gpmc-onenand.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/arm/mach-omap2/gpmc-onenand.c +3 -3
@@ -101,10 +101,8 @@ static void omap2_onenand_set_async_modestatic void set_onenand_cfg (void __iomem *onenand_base) { -u32 reg; +u32 reg =ONENAND_SYS_CFG1_RDY |ONENAND_SYS_CFG1_INT ; - reg =readw (onenand_base +ONENAND_REG_SYS_CFG1 ); - reg &= ~((0x7 <<ONENAND_SYS_CFG1_BRL_SHIFT ) | (0x7 <<9 )); reg |= (latency <<ONENAND_SYS_CFG1_BRL_SHIFT ) |ONENAND_SYS_CFG1_BL_16 ;if (onenand_flags &ONENAND_FLAG_SYNCREAD )
@@ -123,6 +121,7 @@ static void set_onenand_cfg(void __iomem reg |=ONENAND_SYS_CFG1_VHF ; else reg &= ~ONENAND_SYS_CFG1_VHF; +writew (reg, onenand_base +ONENAND_REG_SYS_CFG1 ); }
@@ -289,6 +288,7 @@ static int omap2_onenand_setup_async(voi } } + onenand_async.sync_write = true;omap2_onenand_calc_async_timings (&t); ret =gpmc_cs_program_settings (gpmc_onenand_data->cs, &onenand_async);
Greg Kroah-Hartman
maintainerPATCH 311/342 ARM: at91/dt: fix typo in sama5d2 pinmux descriptions
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ludovic Desroches <[email protected]>
commit 5e45a2589d24573c564630990c88ac93659f8fe4 upstream.
PIN_PA15 macro has the same value as PIN_PA14 so we were overriding PA14 mux/configuration.
--- arch/arm/boot/dts/sama5d2-pinfunc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/boot/dts/sama5d2-pinfunc.h +1 -1
@@ -90,7 +90,7 @@#define PIN_PA14__I2SC1_MCK PINMUX_PIN(PIN_PA14, 4, 2)#define PIN_PA14__FLEXCOM3_IO2 PINMUX_PIN(PIN_PA14, 5, 1)#define PIN_PA14__D9 PINMUX_PIN(PIN_PA14, 6, 2) -#define PIN_PA15 14 +#define PIN_PA15 15#define PIN_PA15__GPIO PINMUX_PIN(PIN_PA15, 0, 0)#define PIN_PA15__SPI0_MOSI PINMUX_PIN(PIN_PA15, 1, 1)#define PIN_PA15__TF1 PINMUX_PIN(PIN_PA15, 2, 1)
Greg Kroah-Hartman
maintainerPATCH 312/342 xen/arm: correctly handle DMA mapping of compound pages
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Campbell <[email protected]>
commit 52ba0746b3b44c86aee121babf3b2fd9b8f84090 upstream.
Currently xen_dma_map_page concludes that DMA to anything other than the head page of a compound page must be foreign, since the PFN of the page is that of the head.
Fix the check to instead consider the whole of a compound page to be local if the PFN of the head passes the 1:1 check.
We can never see a compound page which is a mixture of foreign and local sub-pages.
The comment already correctly described the intention, but fixup the spelling and some grammar.
This fixes the various SSH protocol errors which we have been seeing on the cubietrucks in our automated test infrastructure.
This has been broken since commit 3567258d281b ("xen/arm: use hypercall to flush caches in map_page"), which was in v3.19-rc1.
NB arch/arm64/.../xen/page-coherent.h also includes this file.
arch/arm/include/asm/xen/page-coherent.h +14 -7
@@ -35,14 +35,21 @@ static inline void xen_dma_map_page(struct device *hwdev, struct page *page, dma_addr_t dev_addr, unsigned long offset, size_t size, enum dma_data_direction dir, struct dma_attrs *attrs) { - bool local = XEN_PFN_DOWN(dev_addr) == page_to_xen_pfn(page); + unsigned long page_pfn = page_to_xen_pfn(page); +unsigned long dev_pfn =XEN_PFN_DOWN (dev_addr); +unsigned long compound_pages = + (1 <<compound_order (page)) *XEN_PFN_PER_PAGE ; +bool local = (page_pfn <= dev_pfn) && + (dev_pfn - page_pfn < compound_pages); +/* -* Dom0 is mapped 1:1, while the Linux page can be spanned accross -* multiple Xen page, it's not possible to have a mix of local and -* foreign Xen page. So if the first xen_pfn == mfn the page is local -* otherwise it's a foreign page grant-mapped in dom0. If the page is -* local we can safely call the native dma_ops function, otherwise we -* call the xen specific function. +* Dom0 is mapped 1:1, while the Linux page can span across +* multiple Xen pages, it's not possible for it to contain a +* mix of local and foreign Xen pages. So if the first xen_pfn +* == mfn the page is local otherwise it's a foreign page +* grant-mapped in dom0. If the page is local we can safely +* call the native dma_ops function, otherwise we call the xen +* specific function. */ if (local)__generic_dma_ops (hwdev)->map_page (hwdev, page, offset, size, dir, attrs);
Greg Kroah-Hartman
maintainerPATCH 312/342 xen/arm: correctly handle DMA mapping of compound pages
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Campbell <[email protected]>
commit 52ba0746b3b44c86aee121babf3b2fd9b8f84090 upstream.
Currently xen_dma_map_page concludes that DMA to anything other than the head page of a compound page must be foreign, since the PFN of the page is that of the head.
Fix the check to instead consider the whole of a compound page to be local if the PFN of the head passes the 1:1 check.
We can never see a compound page which is a mixture of foreign and local sub-pages.
The comment already correctly described the intention, but fixup the spelling and some grammar.
This fixes the various SSH protocol errors which we have been seeing on the cubietrucks in our automated test infrastructure.
This has been broken since commit 3567258d281b ("xen/arm: use hypercall to flush caches in map_page"), which was in v3.19-rc1.
NB arch/arm64/.../xen/page-coherent.h also includes this file.
arch/arm/include/asm/xen/page-coherent.h +14 -7
@@ -35,14 +35,21 @@ static inline void xen_dma_map_page(struct device *hwdev, struct page *page, dma_addr_t dev_addr, unsigned long offset, size_t size, enum dma_data_direction dir, struct dma_attrs *attrs) { - bool local = XEN_PFN_DOWN(dev_addr) == page_to_xen_pfn(page); + unsigned long page_pfn = page_to_xen_pfn(page); +unsigned long dev_pfn =XEN_PFN_DOWN (dev_addr); +unsigned long compound_pages = + (1 <<compound_order (page)) *XEN_PFN_PER_PAGE ; +bool local = (page_pfn <= dev_pfn) && + (dev_pfn - page_pfn < compound_pages); +/* -* Dom0 is mapped 1:1, while the Linux page can be spanned accross -* multiple Xen page, it's not possible to have a mix of local and -* foreign Xen page. So if the first xen_pfn == mfn the page is local -* otherwise it's a foreign page grant-mapped in dom0. If the page is -* local we can safely call the native dma_ops function, otherwise we -* call the xen specific function. +* Dom0 is mapped 1:1, while the Linux page can span across +* multiple Xen pages, it's not possible for it to contain a +* mix of local and foreign Xen pages. So if the first xen_pfn +* == mfn the page is local otherwise it's a foreign page +* grant-mapped in dom0. If the page is local we can safely +* call the native dma_ops function, otherwise we call the xen +* specific function. */ if (local)__generic_dma_ops (hwdev)->map_page (hwdev, page, offset, size, dir, attrs);
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xen.org/xen-devel
Greg Kroah-Hartman
maintainerPATCH 313/342 xen/scsiback: correct frontend counting
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Juergen Gross <[email protected]>
commit f285aa8db7cc4432c1a03f8b55ff34fe96317c11 upstream.
When adding a new frontend to xen-scsiback don't decrement the number of active frontends in case of no error. Doing so results in a failure when trying to remove the xen-pvscsi nexus even if no domain is using it.
--- drivers/xen/xen-scsiback.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/xen/xen-scsiback.c +5 -5
@@ -939,12 +939,12 @@ out:spin_unlock_irqrestore (&info->v2p_lock, flags); out_free: -mutex_lock (&tpg->tv_tpg_mutex); - tpg->tv_tpg_fe_count--; -mutex_unlock (&tpg->tv_tpg_mutex); - -if (err) +if (err) { +mutex_lock (&tpg->tv_tpg_mutex); + tpg->tv_tpg_fe_count--; +mutex_unlock (&tpg->tv_tpg_mutex);kfree (new); + }return err; }
Greg Kroah-Hartman
maintainerPATCH 314/342 xen/pciback: Check PF instead of VF for PCI_COMMAND_MEMORY
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konrad Rzeszutek Wilk <[email protected]>
commit 8d47065f7d1980dde52abb874b301054f3013602 upstream.
Commit 408fb0e5aa7fda0059db282ff58c3b2a4278baa0 (xen/pciback: Don't allow MSI-X ops if PCI_COMMAND_MEMORY is not set) prevented enabling MSI-X on passed-through virtual functions, because it checked the VF for PCI_COMMAND_MEMORY but this is not a valid bit for VFs.
Instead, check the physical function for PCI_COMMAND_MEMORY.
--- drivers/xen/xen-pciback/pciback_ops.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/xen/xen-pciback/pciback_ops.c +2 -1
@@ -227,8 +227,9 @@ int xen_pcibk_enable_msix(struct xen_pci/* * PCI_COMMAND_MEMORY must be enabled, otherwise we may not be able * to access the BARs where the MSI-X entries reside. +* But VF devices are unique in which the PF needs to be checked. */ -pci_read_config_word (dev,PCI_COMMAND , &cmd); +pci_read_config_word (pci_physfn (dev),PCI_COMMAND , &cmd);if (dev->msi_enabled || !(cmd &PCI_COMMAND_MEMORY ))return -ENXIO ;
Greg Kroah-Hartman
maintainerPATCH 315/342 xen/pciback: Save the number of MSI-X entries to be copied later.
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konrad Rzeszutek Wilk <[email protected]>
commit d159457b84395927b5a52adb72f748dd089ad5e5 upstream.
Commit 8135cf8b092723dbfcc611fe6fdcb3a36c9951c5 (xen/pciback: Save xen_pci_op commands before processing it) broke enabling MSI-X because it would never copy the resulting vectors into the response. The number of vectors requested was being overwritten by the return value (typically zero for success).
Save the number of vectors before processing the op, so the correct number of vectors are copied afterwards.
--- drivers/xen/xen-pciback/pciback_ops.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/xen/xen-pciback/pciback_ops.c +5 -1
@@ -333,6 +333,9 @@ void xen_pcibk_do_op(struct work_structstruct xen_pcibk_dev_data *dev_data =NULL ;struct xen_pci_op *op = &pdev->op;int test_intx =0 ; +#ifdef CONFIG_PCI_MSI +unsigned int nr =0 ; +#endif *op = pdev->sh_info->op;barrier ();
@@ -361,6 +364,7 @@ void xen_pcibk_do_op(struct work_struct op->err =xen_pcibk_disable_msi (pdev, dev, op);break ;case XEN_PCI_OP_enable_msix: + nr = op->value; op->err =xen_pcibk_enable_msix (pdev, dev, op);break ;case XEN_PCI_OP_disable_msix:
@@ -383,7 +387,7 @@ void xen_pcibk_do_op(struct work_structif (op->cmd == XEN_PCI_OP_enable_msix && op->err ==0 ) {unsigned int i; -for (i =0 ; i < op->value; i++) +for (i =0 ; i < nr; i++) pdev->sh_info->op.msix_entries[i].vector = op->msix_entries[i].vector; }
Greg Kroah-Hartman
maintainerPATCH 316/342 xen/pcifront: Fix mysterious crashes when NUMA locality information was extracted.
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konrad Rzeszutek Wilk <[email protected]>
commit 4d8c8bd6f2062c9988817183a91fe2e623c8aa5e upstream.
Occasionaly PV guests would crash with:
pciback 0000:00:00.1: Xen PCI mapped GSI0 to IRQ16
BUG: unable to handle kernel paging request at 0000000d1a8c0be0 .. snip.. <ffffffff8139ce1b>] find_next_bit+0xb/0x10 [<ffffffff81387f22>] cpumask_next_and+0x22/0x40 [<ffffffff813c1ef8>] pci_device_probe+0xb8/0x120 [<ffffffff81529097>] ? driver_sysfs_add+0x77/0xa0 [<ffffffff815293e4>] driver_probe_device+0x1a4/0x2d0 [<ffffffff813c1ddd>] ? pci_match_device+0xdd/0x110 [<ffffffff81529657>] __device_attach_driver+0xa7/0xb0 [<ffffffff815295b0>] ? __driver_attach+0xa0/0xa0 [<ffffffff81527622>] bus_for_each_drv+0x62/0x90 [<ffffffff8152978d>] __device_attach+0xbd/0x110 [<ffffffff815297fb>] device_attach+0xb/0x10 [<ffffffff813b75ac>] pci_bus_add_device+0x3c/0x70 [<ffffffff813b7618>] pci_bus_add_devices+0x38/0x80 [<ffffffff813dc34e>] pcifront_scan_root+0x13e/0x1a0 [<ffffffff817a0692>] pcifront_backend_changed+0x262/0x60b [<ffffffff814644c6>] ? xenbus_gather+0xd6/0x160 [<ffffffff8120900f>] ? put_object+0x2f/0x50 [<ffffffff81465c1d>] xenbus_otherend_changed+0x9d/0xa0 [<ffffffff814678ee>] backend_changed+0xe/0x10 [<ffffffff81463a28>] xenwatch_thread+0xc8/0x190 [<ffffffff810f22f0>] ? woken_wake_function+0x10/0x10
which was the result of two things:
When we call pci_scan_root_bus we would pass in 'sd' (sysdata) pointer which was an 'pcifront_sd' structure. However in the pci_device_add it expects that the 'sd' is 'struct sysdata' and sets the dev->node to what is in sd->node (offset 4):
set_dev_node(&dev->dev, pcibus_to_node(bus));
__pcibus_to_node(const struct pci_bus *bus)
{
const struct pci_sysdata *sd = bus->sysdata;
return sd->node;
}However our structure was pcifront_sd which had nothing at that offset:
struct pcifront_sd {
int domain; /* 0 4 */
/* XXX 4 bytes hole, try to pack */
struct pcifront_device * pdev; /* 8 8 */
}
That is an hole - filled with garbage as we used kmalloc instead of kzalloc (the second problem).
This patch fixes the issue by:
1) Use kzalloc to initialize to a well known state.
2) Put 'struct pci_sysdata' at the start of 'pcifront_sd'. That way access to the 'node' will access the right offset.
--- drivers/pci/xen-pcifront.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/pci/xen-pcifront.c +6 -4
@@ -53,7 +53,7 @@ struct pcifront_device { };struct pcifront_sd { -int domain; +struct pci_sysdata sd;struct pcifront_device *pdev; };
@@ -67,7 +67,9 @@ static inline void pcifront_init_sd(stru unsigned int domain, unsigned int bus, struct pcifront_device *pdev) { - sd->domain = domain; +/* Because we do not expose that information via XenBus. */ + sd->sd.node = first_online_node; + sd->sd.domain = domain; sd->pdev = pdev; }
@@ -468,8 +470,8 @@ static int pcifront_scan_root(struct pcidev_info (&pdev->xdev->dev,"Creating PCI Frontend Bus %04x:%02x\n" , domain, bus); - bus_entry =kmalloc (sizeof (*bus_entry),GFP_KERNEL ); - sd =kmalloc (sizeof (*sd),GFP_KERNEL ); + bus_entry =kzalloc (sizeof (*bus_entry),GFP_KERNEL ); + sd =kzalloc (sizeof (*sd),GFP_KERNEL );if (!bus_entry || !sd) { err = -ENOMEM ; goto err_out;
Greg Kroah-Hartman
maintainerPATCH 317/342 should_follow_link(): validate ->d_seq after having decided to follow
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
commit a7f775428b8f5808815c0e3004020cedb94cbe3b upstream.
... otherwise d_is_symlink() above might have nothing to do with the inode value we've got.
--- fs/namei.c | 5 +++++ 1 file changed, 5 insertions(+)
fs/namei.c +5 -0
@@ -1711,6 +1711,11 @@ static inline int should_follow_link(strreturn 0 ;if (!follow)return 0 ; +/* make sure that d_is_symlink above matches inode */ +if (nd->flags &LOOKUP_RCU ) { +if (read_seqcount_retry (&link->dentry->d_seq, seq)) +return -ECHILD ; + }return pick_link (nd, link, inode, seq); }
Greg Kroah-Hartman
maintainerPATCH 318/342 do_last(): ELOOP failure exit should be done after leaving RCU mode
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
commit 5129fa482b16615fd4464d2f5d23acb1b7056c66 upstream.
... or we risk seeing a bogus value of d_is_symlink() there.
--- fs/namei.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
fs/namei.c +4 -5
@@ -3149,11 +3149,6 @@ finish_lookup:if (unlikely (error))return error; -if (unlikely (d_is_symlink (path.dentry)) && !(open_flag &O_PATH )) { -path_to_nameidata (&path, nd); -return -ELOOP ; - } -if ((nd->flags &LOOKUP_RCU ) || nd->path.mnt != path.mnt) {path_to_nameidata (&path, nd); }else {
@@ -3172,6 +3167,10 @@ finish_open:return error; }audit_inode (nd->name, nd->path.dentry,0 ); +if (unlikely (d_is_symlink (nd->path.dentry)) && !(open_flag &O_PATH )) { + error = -ELOOP ; + goto out; + } error = -EISDIR ;if ((open_flag &O_CREAT ) &&d_is_dir (nd->path.dentry)) goto out;