From 36711f9ba818beeee2e5b168cfa8481faf67fcb5 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 13 Jun 2016 07:40:54 -0400 Subject: CVE-2016-1583 stack overflow via ecryptfs and /proc (rhbz 1344721 1344722) --- ...forbid-opening-files-without-mmap-handler.patch | 59 ++++++++++++++++++++++ kernel.spec | 8 +++ proc-prevent-stacking-filesystems-on-top.patch | 41 +++++++++++++++ sched-panic-on-corrupted-stack-end.patch | 36 +++++++++++++ 4 files changed, 144 insertions(+) create mode 100644 ecryptfs-forbid-opening-files-without-mmap-handler.patch create mode 100644 proc-prevent-stacking-filesystems-on-top.patch create mode 100644 sched-panic-on-corrupted-stack-end.patch diff --git a/ecryptfs-forbid-opening-files-without-mmap-handler.patch b/ecryptfs-forbid-opening-files-without-mmap-handler.patch new file mode 100644 index 000000000..2d40e68ed --- /dev/null +++ b/ecryptfs-forbid-opening-files-without-mmap-handler.patch @@ -0,0 +1,59 @@ +From 2f36db71009304b3f0b95afacd8eba1f9f046b87 Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Wed, 1 Jun 2016 11:55:06 +0200 +Subject: [PATCH] ecryptfs: forbid opening files without mmap handler + +This prevents users from triggering a stack overflow through a recursive +invocation of pagefault handling that involves mapping procfs files into +virtual memory. + +Signed-off-by: Jann Horn +Acked-by: Tyler Hicks +Cc: stable@vger.kernel.org +Signed-off-by: Linus Torvalds +--- + fs/ecryptfs/kthread.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c +index 866bb18efefe..e818f5ac7a26 100644 +--- a/fs/ecryptfs/kthread.c ++++ b/fs/ecryptfs/kthread.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include "ecryptfs_kernel.h" + + struct ecryptfs_open_req { +@@ -147,7 +148,7 @@ int ecryptfs_privileged_open(struct file **lower_file, + flags |= IS_RDONLY(d_inode(lower_dentry)) ? O_RDONLY : O_RDWR; + (*lower_file) = dentry_open(&req.path, flags, cred); + if (!IS_ERR(*lower_file)) +- goto out; ++ goto have_file; + if ((flags & O_ACCMODE) == O_RDONLY) { + rc = PTR_ERR((*lower_file)); + goto out; +@@ -165,8 +166,16 @@ int ecryptfs_privileged_open(struct file **lower_file, + mutex_unlock(&ecryptfs_kthread_ctl.mux); + wake_up(&ecryptfs_kthread_ctl.wait); + wait_for_completion(&req.done); +- if (IS_ERR(*lower_file)) ++ if (IS_ERR(*lower_file)) { + rc = PTR_ERR(*lower_file); ++ goto out; ++ } ++have_file: ++ if ((*lower_file)->f_op->mmap == NULL) { ++ fput(*lower_file); ++ *lower_file = NULL; ++ rc = -EMEDIUMTYPE; ++ } + out: + return rc; + } +-- +2.5.5 + diff --git a/kernel.spec b/kernel.spec index 4e53f2412..688001131 100644 --- a/kernel.spec +++ b/kernel.spec @@ -628,6 +628,11 @@ Patch721: tipc-fix-an-infoleak-in-tipc_nl_compat_link_dump.patch #CVE-2016-5244 rhbz 1343338 1343337 Patch722: rds-fix-an-infoleak-in-rds_inc_info_copy.txt +#CVE-2016-1583 rhbz 1344721 1344722 +Patch723: proc-prevent-stacking-filesystems-on-top.patch +Patch725: ecryptfs-forbid-opening-files-without-mmap-handler.patch +Patch726: sched-panic-on-corrupted-stack-end.patch + # END OF PATCH DEFINITIONS %endif @@ -2153,6 +2158,9 @@ fi # # %changelog +* Mon Jun 13 2016 Josh Boyer +- CVE-2016-1583 stack overflow via ecryptfs and /proc (rhbz 1344721 1344722) + * Wed Jun 08 2016 Josh Boyer - Linux v4.6.2 diff --git a/proc-prevent-stacking-filesystems-on-top.patch b/proc-prevent-stacking-filesystems-on-top.patch new file mode 100644 index 000000000..178aa3ba6 --- /dev/null +++ b/proc-prevent-stacking-filesystems-on-top.patch @@ -0,0 +1,41 @@ +From e54ad7f1ee263ffa5a2de9c609d58dfa27b21cd9 Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Wed, 1 Jun 2016 11:55:05 +0200 +Subject: [PATCH] proc: prevent stacking filesystems on top + +This prevents stacking filesystems (ecryptfs and overlayfs) from using +procfs as lower filesystem. There is too much magic going on inside +procfs, and there is no good reason to stack stuff on top of procfs. + +(For example, procfs does access checks in VFS open handlers, and +ecryptfs by design calls open handlers from a kernel thread that doesn't +drop privileges or so.) + +Signed-off-by: Jann Horn +Cc: stable@vger.kernel.org +Signed-off-by: Linus Torvalds +--- + fs/proc/root.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/fs/proc/root.c b/fs/proc/root.c +index 361ab4ee42fc..ec649c92d270 100644 +--- a/fs/proc/root.c ++++ b/fs/proc/root.c +@@ -121,6 +121,13 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, + if (IS_ERR(sb)) + return ERR_CAST(sb); + ++ /* ++ * procfs isn't actually a stacking filesystem; however, there is ++ * too much magic going on inside it to permit stacking things on ++ * top of it ++ */ ++ sb->s_stack_depth = FILESYSTEM_MAX_STACK_DEPTH; ++ + if (!proc_parse_options(options, ns)) { + deactivate_locked_super(sb); + return ERR_PTR(-EINVAL); +-- +2.5.5 + diff --git a/sched-panic-on-corrupted-stack-end.patch b/sched-panic-on-corrupted-stack-end.patch new file mode 100644 index 000000000..1d6bbaf3d --- /dev/null +++ b/sched-panic-on-corrupted-stack-end.patch @@ -0,0 +1,36 @@ +From 29d6455178a09e1dc340380c582b13356227e8df Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Wed, 1 Jun 2016 11:55:07 +0200 +Subject: [PATCH] sched: panic on corrupted stack end + +Until now, hitting this BUG_ON caused a recursive oops (because oops +handling involves do_exit(), which calls into the scheduler, which in +turn raises an oops), which caused stuff below the stack to be +overwritten until a panic happened (e.g. via an oops in interrupt +context, caused by the overwritten CPU index in the thread_info). + +Just panic directly. + +Signed-off-by: Jann Horn +Signed-off-by: Linus Torvalds +--- + kernel/sched/core.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index d1f7149f8704..11546a6ed5df 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -3047,7 +3047,8 @@ static noinline void __schedule_bug(struct task_struct *prev) + static inline void schedule_debug(struct task_struct *prev) + { + #ifdef CONFIG_SCHED_STACK_END_CHECK +- BUG_ON(task_stack_end_corrupted(prev)); ++ if (task_stack_end_corrupted(prev)) ++ panic("corrupted stack end detected inside scheduler\n"); + #endif + + if (unlikely(in_atomic_preempt_off())) { +-- +2.5.5 + -- cgit From 6a80877ca93ede833c44c79981e622255bed2107 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Tue, 14 Jun 2016 11:47:49 +0100 Subject: Enable Infiniband on ARM now we have HW --- config-arm-generic | 3 --- filter-aarch64.sh | 2 +- filter-armv7hl.sh | 2 +- kernel.spec | 3 +++ 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/config-arm-generic b/config-arm-generic index 91d27ad92..9ea02cf1d 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -498,7 +498,6 @@ CONFIG_COMMON_CLK_SCPI=m # core -# CONFIG_INFINIBAND is not set # CONFIG_ISDN is not set # CONFIG_PCMCIA is not set # CONFIG_PARPORT is not set @@ -533,8 +532,6 @@ CONFIG_NET_VENDOR_MELLANOX=y # CONFIG_SCSI_3W_SAS is not set # CONFIG_SCSI_PM8001 is not set # CONFIG_SCSI_IPS is not set -# CONFIG_SCSI_CXGB3_ISCSI is not set -# CONFIG_SCSI_CXGB4_ISCSI is not set # CONFIG_SCSI_BFA_FC is not set # CONFIG_FUSION is not set # CONFIG_SCSI_3W_9XXX is not set diff --git a/filter-aarch64.sh b/filter-aarch64.sh index 139d1791d..cc560ca97 100644 --- a/filter-aarch64.sh +++ b/filter-aarch64.sh @@ -13,4 +13,4 @@ driverdirs="atm auxdisplay bcma bluetooth firewire fmc infiniband isdn leds medi ethdrvs="3com adaptec arc alteon atheros broadcom cadence calxeda chelsio cisco dec dlink emulex icplus marvell micrel myricom neterion nvidia oki-semi packetengines qlogic rdc renesas sfc silan sis smsc stmicro sun tehuti ti via wiznet xircom" -singlemods="ntb_netdev iscsi_ibft iscsi_boot_sysfs megaraid pmcraid qla1280 9pnet_rdma rpcrdma hid-picolcd hid-prodikeys hwa-hc hwpoison-inject target_core_user sbp_target" +singlemods="ntb_netdev iscsi_ibft iscsi_boot_sysfs megaraid pmcraid qla1280 9pnet_rdma rpcrdma hid-picolcd hid-prodikeys hwa-hc hwpoison-inject target_core_user sbp_target cxgbit iw_cxgb3 iw_cxgb4 cxgb3i cxgb3i cxgb3i_ddp cxgb4i" diff --git a/filter-armv7hl.sh b/filter-armv7hl.sh index 6de77659a..0ae6d925b 100644 --- a/filter-armv7hl.sh +++ b/filter-armv7hl.sh @@ -15,4 +15,4 @@ ethdrvs="3com adaptec alteon altera amd atheros broadcom cadence chelsio cisco d drmdrvs="amd armada bridge ast exynos i2c imx mgag200 msm omapdrm panel nouveau radeon rockchip tegra tilcdc via" -singlemods="ntb_netdev iscsi_ibft iscsi_boot_sysfs megaraid pmcraid qla1280 9pnet_rdma rpcrdma hid-picolcd hid-prodikeys hwa-hc hwpoison-inject target_core_user sbp_target" +singlemods="ntb_netdev iscsi_ibft iscsi_boot_sysfs megaraid pmcraid qla1280 9pnet_rdma rpcrdma hid-picolcd hid-prodikeys hwa-hc hwpoison-inject target_core_user sbp_target cxgbit iw_cxgb3 iw_cxgb4 cxgb3i cxgb3i cxgb3i_ddp cxgb4i" diff --git a/kernel.spec b/kernel.spec index 688001131..71d7bfa82 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2158,6 +2158,9 @@ fi # # %changelog +* Tue Jun 14 2016 Peter Robinson +- Enable Infiniband on ARM now we have HW + * Mon Jun 13 2016 Josh Boyer - CVE-2016-1583 stack overflow via ecryptfs and /proc (rhbz 1344721 1344722) -- cgit From 0f872cd4568b47572a581f73a1661029d1db7987 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 15 Jun 2016 09:37:42 -0400 Subject: CVE-2016-4470 keys: uninitialized variable crash (rhbz 1341716 1346626) --- KEYS-potential-uninitialized-variable.patch | 30 +++++++++++++++++++++++++++++ kernel.spec | 6 ++++++ 2 files changed, 36 insertions(+) create mode 100644 KEYS-potential-uninitialized-variable.patch diff --git a/KEYS-potential-uninitialized-variable.patch b/KEYS-potential-uninitialized-variable.patch new file mode 100644 index 000000000..23cabbb2e --- /dev/null +++ b/KEYS-potential-uninitialized-variable.patch @@ -0,0 +1,30 @@ +From 82a50018782f84e733e718d4b24e1653d19333be Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Wed, 15 Jun 2016 09:31:45 -0400 +Subject: [PATCH] KEYS: potential uninitialized variable + +If __key_link_begin() failed then "edit" would be uninitialized. I've +added a check to fix that. + +Fixes: f70e2e06196a ('KEYS: Do preallocation for __key_link()') +Signed-off-by: Dan Carpenter +--- + security/keys/key.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/security/keys/key.c b/security/keys/key.c +index bd5a272f28a6..346fbf201c22 100644 +--- a/security/keys/key.c ++++ b/security/keys/key.c +@@ -597,7 +597,7 @@ int key_reject_and_link(struct key *key, + + mutex_unlock(&key_construction_mutex); + +- if (keyring) ++ if (keyring && link_ret == 0) + __key_link_end(keyring, &key->index_key, edit); + + /* wake up anyone waiting for a key to be constructed */ +-- +2.5.5 + diff --git a/kernel.spec b/kernel.spec index 71d7bfa82..b825cdd6d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -633,6 +633,9 @@ Patch723: proc-prevent-stacking-filesystems-on-top.patch Patch725: ecryptfs-forbid-opening-files-without-mmap-handler.patch Patch726: sched-panic-on-corrupted-stack-end.patch +#CVE-2016-4470 rhbz 1341716 1346626 +Patch727: KEYS-potential-uninitialized-variable.patch + # END OF PATCH DEFINITIONS %endif @@ -2158,6 +2161,9 @@ fi # # %changelog +* Wed Jun 15 2016 Josh Boyer +- CVE-2016-4470 keys: uninitialized variable crash (rhbz 1341716 1346626) + * Tue Jun 14 2016 Peter Robinson - Enable Infiniband on ARM now we have HW -- cgit From c24ec7cb4a43635a1aec1df73f0e89e61994c15f Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Wed, 15 Jun 2016 14:11:15 -0700 Subject: hp-wmi: fix wifi cannot be hard-unblock (rhbz 1338025) --- hp-wmi-fix-wifi-cannot-be-hard-unblock.patch | 44 ++++++++++++++++++++++++++++ kernel.spec | 6 ++++ 2 files changed, 50 insertions(+) create mode 100644 hp-wmi-fix-wifi-cannot-be-hard-unblock.patch diff --git a/hp-wmi-fix-wifi-cannot-be-hard-unblock.patch b/hp-wmi-fix-wifi-cannot-be-hard-unblock.patch new file mode 100644 index 000000000..51ccc8c48 --- /dev/null +++ b/hp-wmi-fix-wifi-cannot-be-hard-unblock.patch @@ -0,0 +1,44 @@ +From 97345b0e9b02d6d794fc772e366efe6e44b9340a Mon Sep 17 00:00:00 2001 +From: Alex Hung +Date: Mon, 13 Jun 2016 19:44:00 +0800 +Subject: [PATCH] hp-wmi: fix wifi cannot be hard-unblock + +Several users reported wifi cannot be unblocked as discussed in [1]. +This patch removes the useof 2009 flag by BIOS but uses the actual WMI +function calls - it will be skipped if WMI reports unsupported + +[1] https://bugzilla.kernel.org/show_bug.cgi?id=69131 + +Signed-off-by: Alex Hung +--- + drivers/platform/x86/hp-wmi.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c +index fb4dd7b..af2046c 100644 +--- a/drivers/platform/x86/hp-wmi.c ++++ b/drivers/platform/x86/hp-wmi.c +@@ -723,6 +723,11 @@ static int __init hp_wmi_rfkill_setup(struct platform_device *device) + if (err) + return err; + ++ err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, &wireless, ++ sizeof(wireless), 0); ++ if (err) ++ return err; ++ + if (wireless & 0x1) { + wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev, + RFKILL_TYPE_WLAN, +@@ -910,7 +915,7 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) + gps_rfkill = NULL; + rfkill2_count = 0; + +- if (hp_wmi_bios_2009_later() || hp_wmi_rfkill_setup(device)) ++ if (hp_wmi_rfkill_setup(device)) + hp_wmi_rfkill2_setup(device); + + err = device_create_file(&device->dev, &dev_attr_display); +-- +2.5.5 + diff --git a/kernel.spec b/kernel.spec index b825cdd6d..637780ff3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -636,6 +636,9 @@ Patch726: sched-panic-on-corrupted-stack-end.patch #CVE-2016-4470 rhbz 1341716 1346626 Patch727: KEYS-potential-uninitialized-variable.patch +#rhbz 1338025 +Patch728: hp-wmi-fix-wifi-cannot-be-hard-unblock.patch + # END OF PATCH DEFINITIONS %endif @@ -2161,6 +2164,9 @@ fi # # %changelog +* Wed Jun 15 2016 Laura Abbott +- hp-wmi: fix wifi cannot be hard-unblock (rhbz 1338025) + * Wed Jun 15 2016 Josh Boyer - CVE-2016-4470 keys: uninitialized variable crash (rhbz 1341716 1346626) -- cgit From b983da8fef8cbe53af0ecb4271910055fa456498 Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Wed, 15 Jun 2016 16:03:36 -0700 Subject: Use the not rebased version of the patch --- hp-wmi-fix-wifi-cannot-be-hard-unblock.patch | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/hp-wmi-fix-wifi-cannot-be-hard-unblock.patch b/hp-wmi-fix-wifi-cannot-be-hard-unblock.patch index 51ccc8c48..27744a0c3 100644 --- a/hp-wmi-fix-wifi-cannot-be-hard-unblock.patch +++ b/hp-wmi-fix-wifi-cannot-be-hard-unblock.patch @@ -1,7 +1,14 @@ -From 97345b0e9b02d6d794fc772e366efe6e44b9340a Mon Sep 17 00:00:00 2001 +From patchwork Mon Jun 13 11:44:00 2016 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: hp-wmi: fix wifi cannot be hard-unblock From: Alex Hung +X-Patchwork-Id: 9172765 +Message-Id: <1465818240-11994-1-git-send-email-alex.hung@canonical.com> +To: dvhart@infradead.org, platform-driver-x86@vger.kernel.org, + alex.hung@canonical.com, david.ward@ll.mit.edu Date: Mon, 13 Jun 2016 19:44:00 +0800 -Subject: [PATCH] hp-wmi: fix wifi cannot be hard-unblock Several users reported wifi cannot be unblocked as discussed in [1]. This patch removes the useof 2009 flag by BIOS but uses the actual WMI @@ -15,10 +22,10 @@ Signed-off-by: Alex Hung 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c -index fb4dd7b..af2046c 100644 +index 6f145f2..96ffda4 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c -@@ -723,6 +723,11 @@ static int __init hp_wmi_rfkill_setup(struct platform_device *device) +@@ -718,6 +718,11 @@ static int __init hp_wmi_rfkill_setup(struct platform_device *device) if (err) return err; @@ -30,8 +37,8 @@ index fb4dd7b..af2046c 100644 if (wireless & 0x1) { wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev, RFKILL_TYPE_WLAN, -@@ -910,7 +915,7 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) - gps_rfkill = NULL; +@@ -882,7 +887,7 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) + wwan_rfkill = NULL; rfkill2_count = 0; - if (hp_wmi_bios_2009_later() || hp_wmi_rfkill_setup(device)) @@ -39,6 +46,3 @@ index fb4dd7b..af2046c 100644 hp_wmi_rfkill2_setup(device); err = device_create_file(&device->dev, &dev_attr_display); --- -2.5.5 - -- cgit From 93f8d223fc495badc84a98bb11d826c0c1b3f9cb Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 20 Jun 2016 21:00:31 +0200 Subject: Bring in patch-series from drm-next to fix skl_update_other_pipe_wm issues (rhbz 1305038) - Cherry pick some other drm / kms fixes from upstream --- ...eorganize-WM-structs-unions-in-CRTC-state.patch | 198 +++++++++++ ...-mgag200-Black-screen-fix-for-G200e-rev-4.patch | 58 +++ ...name-s-skl_compute_pipe_wm-skl_build_pipe.patch | 60 ++++ ...u-fbcon-fix-out-of-bounds-memory-accesses.patch | 138 ++++++++ ...gen9-Cache-plane-data-rates-in-CRTC-state.patch | 214 ++++++++++++ ...-disp-sor-gf119-both-links-use-the-same-t.patch | 46 +++ ...n9-Allow-calculation-of-data-rate-for-in-.patch | 141 ++++++++ ...-disp-sor-gm107-training-pattern-register.patch | 195 +++++++++++ ...n9-Store-plane-minimum-blocks-in-CRTC-wm-.patch | 67 ++++ ...915-fbc-Disable-on-HSW-by-default-for-now.patch | 55 +++ ...re-Do-not-preserve-framebuffer-on-rmfb-v4.patch | 145 ++++++++ ...ack-whether-an-atomic-transaction-changes.patch | 68 ++++ ...n9-Allow-skl_allocate_pipe_ddb-to-operate.patch | 352 +++++++++++++++++++ ...-Add-distrust_bios_wm-flag-to-dev_priv-v2.patch | 94 +++++ ...n9-Compute-DDB-allocation-at-atomic-check.patch | 254 ++++++++++++++ ...n9-Drop-re-allocation-of-DDB-at-atomic-co.patch | 389 +++++++++++++++++++++ ...i915-gen9-Calculate-plane-WM-s-from-state.patch | 91 +++++ ...n9-Allow-watermark-calculation-on-in-flig.patch | 156 +++++++++ ...n9-Use-a-bitmask-to-track-dirty-pipe-wate.patch | 91 +++++ ...n9-Propagate-watermark-calculation-failur.patch | 254 ++++++++++++++ ...n9-Calculate-watermarks-during-atomic-che.patch | 321 +++++++++++++++++ ...n9-Reject-display-updates-that-exceed-wm-.patch | 63 ++++ ...move-wm_config-from-dev_priv-intel_atomic.patch | 115 ++++++ kernel.spec | 32 ++ 24 files changed, 3597 insertions(+) create mode 100644 0001-drm-i915-Reorganize-WM-structs-unions-in-CRTC-state.patch create mode 100644 0001-drm-mgag200-Black-screen-fix-for-G200e-rev-4.patch create mode 100644 0002-drm-i915-Rename-s-skl_compute_pipe_wm-skl_build_pipe.patch create mode 100644 0002-drm-nouveau-fbcon-fix-out-of-bounds-memory-accesses.patch create mode 100644 0003-drm-i915-gen9-Cache-plane-data-rates-in-CRTC-state.patch create mode 100644 0003-drm-nouveau-disp-sor-gf119-both-links-use-the-same-t.patch create mode 100644 0004-drm-i915-gen9-Allow-calculation-of-data-rate-for-in-.patch create mode 100644 0004-drm-nouveau-disp-sor-gm107-training-pattern-register.patch create mode 100644 0005-drm-i915-gen9-Store-plane-minimum-blocks-in-CRTC-wm-.patch create mode 100644 0005-i915-fbc-Disable-on-HSW-by-default-for-now.patch create mode 100644 0006-drm-core-Do-not-preserve-framebuffer-on-rmfb-v4.patch create mode 100644 0006-drm-i915-Track-whether-an-atomic-transaction-changes.patch create mode 100644 0007-drm-i915-gen9-Allow-skl_allocate_pipe_ddb-to-operate.patch create mode 100644 0008-drm-i915-Add-distrust_bios_wm-flag-to-dev_priv-v2.patch create mode 100644 0009-drm-i915-gen9-Compute-DDB-allocation-at-atomic-check.patch create mode 100644 0010-drm-i915-gen9-Drop-re-allocation-of-DDB-at-atomic-co.patch create mode 100644 0011-drm-i915-gen9-Calculate-plane-WM-s-from-state.patch create mode 100644 0012-drm-i915-gen9-Allow-watermark-calculation-on-in-flig.patch create mode 100644 0013-drm-i915-gen9-Use-a-bitmask-to-track-dirty-pipe-wate.patch create mode 100644 0014-drm-i915-gen9-Propagate-watermark-calculation-failur.patch create mode 100644 0015-drm-i915-gen9-Calculate-watermarks-during-atomic-che.patch create mode 100644 0016-drm-i915-gen9-Reject-display-updates-that-exceed-wm-.patch create mode 100644 0017-drm-i915-Remove-wm_config-from-dev_priv-intel_atomic.patch diff --git a/0001-drm-i915-Reorganize-WM-structs-unions-in-CRTC-state.patch b/0001-drm-i915-Reorganize-WM-structs-unions-in-CRTC-state.patch new file mode 100644 index 000000000..dc6e2e086 --- /dev/null +++ b/0001-drm-i915-Reorganize-WM-structs-unions-in-CRTC-state.patch @@ -0,0 +1,198 @@ +From 2a6f0971d09e2bb88d2ae40d91ceb2776090497d Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 11:11:50 +0200 +Subject: [PATCH 01/17] drm/i915: Reorganize WM structs/unions in CRTC state + +Upstream: since drm-intel-next-2016-05-22 +commit e8f1f02e7125220b99af8047703b63c11a7081d6 + +Author: Matt Roper +AuthorDate: Thu May 12 07:05:55 2016 -0700 +Commit: Matt Roper +CommitDate: Fri May 13 07:32:11 2016 -0700 + + drm/i915: Reorganize WM structs/unions in CRTC state + + Reorganize the nested structures and unions we have for pipe watermark + data in intel_crtc_state so that platform-specific data can be added in + a more sensible manner (and save a bit of memory at the same time). + + The change basically changes the organization from: + + union { + struct intel_pipe_wm ilk; + struct intel_pipe_wm skl; + } optimal; + + struct intel_pipe_wm intermediate /* ILK-only */ + + to + + union { + struct { + struct intel_pipe_wm intermediate; + struct intel_pipe_wm optimal; + } ilk; + + struct { + struct intel_pipe_wm optimal; + } skl; + } + + There should be no functional change here, but it will allow us to add + more platform-specific fields going forward (and more easily extend to + other platform types like VLV). + + While we're at it, let's move the entire watermark substructure out to + its own structure definition to make the code slightly more readable. + + Signed-off-by: Matt Roper + Reviewed-by: Maarten Lankhorst + Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-2-git-send-email-matthew.d.roper@intel.com +--- + drivers/gpu/drm/i915/intel_drv.h | 48 +++++++++++++++++++++++++++++++--------- + drivers/gpu/drm/i915/intel_pm.c | 16 +++++++------- + 2 files changed, 46 insertions(+), 18 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h +index 3a30b37..7d19baf 100644 +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -363,6 +363,40 @@ struct skl_pipe_wm { + uint32_t linetime; + }; + ++struct intel_crtc_wm_state { ++ union { ++ struct { ++ /* ++ * Intermediate watermarks; these can be ++ * programmed immediately since they satisfy ++ * both the current configuration we're ++ * switching away from and the new ++ * configuration we're switching to. ++ */ ++ struct intel_pipe_wm intermediate; ++ ++ /* ++ * Optimal watermarks, programmed post-vblank ++ * when this state is committed. ++ */ ++ struct intel_pipe_wm optimal; ++ } ilk; ++ ++ struct { ++ /* gen9+ only needs 1-step wm programming */ ++ struct skl_pipe_wm optimal; ++ } skl; ++ }; ++ ++ /* ++ * Platforms with two-step watermark programming will need to ++ * update watermark programming post-vblank to switch from the ++ * safe intermediate watermarks to the optimal final ++ * watermarks. ++ */ ++ bool need_postvbl_update; ++}; ++ + struct intel_crtc_state { + struct drm_crtc_state base; + +@@ -509,16 +543,10 @@ struct intel_crtc_state { + /* IVB sprite scaling w/a (WaCxSRDisabledForSpriteScaling:ivb) */ + bool disable_lp_wm; + +- struct { +- /* +- * optimal watermarks, programmed post-vblank when this state +- * is committed +- */ +- union { +- struct intel_pipe_wm ilk; +- struct skl_pipe_wm skl; +- } optimal; +- } wm; ++ struct intel_crtc_wm_state wm; ++ ++ /* Gamma mode programmed on the pipe */ ++ uint32_t gamma_mode; + }; + + struct vlv_wm_state { +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index 54ab023..0da1d60 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -2302,7 +2302,7 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, + if (IS_ERR(cstate)) + return PTR_ERR(cstate); + +- pipe_wm = &cstate->wm.optimal.ilk; ++ pipe_wm = &cstate->wm.ilk.optimal; + memset(pipe_wm, 0, sizeof(*pipe_wm)); + + for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { +@@ -2385,7 +2385,7 @@ static void ilk_merge_wm_level(struct drm_device *dev, + for_each_intel_crtc(dev, intel_crtc) { + const struct intel_crtc_state *cstate = + to_intel_crtc_state(intel_crtc->base.state); +- const struct intel_pipe_wm *active = &cstate->wm.optimal.ilk; ++ const struct intel_pipe_wm *active = &cstate->wm.ilk.optimal; + const struct intel_wm_level *wm = &active->wm[level]; + + if (!active->pipe_enabled) +@@ -2536,12 +2536,12 @@ static void ilk_compute_wm_results(struct drm_device *dev, + const struct intel_crtc_state *cstate = + to_intel_crtc_state(intel_crtc->base.state); + enum pipe pipe = intel_crtc->pipe; +- const struct intel_wm_level *r = &cstate->wm.optimal.ilk.wm[0]; ++ const struct intel_wm_level *r = &cstate->wm.ilk.optimal.wm[0]; + + if (WARN_ON(!r->enable)) + continue; + +- results->wm_linetime[pipe] = cstate->wm.optimal.ilk.linetime; ++ results->wm_linetime[pipe] = cstate->wm.ilk.optimal.linetime; + + results->wm_pipe[pipe] = + (r->pri_val << WM0_PIPE_PLANE_SHIFT) | +@@ -3617,7 +3617,7 @@ static void skl_update_wm(struct drm_crtc *crtc) + struct drm_i915_private *dev_priv = dev->dev_private; + struct skl_wm_values *results = &dev_priv->wm.skl_results; + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); +- struct skl_pipe_wm *pipe_wm = &cstate->wm.optimal.skl; ++ struct skl_pipe_wm *pipe_wm = &cstate->wm.skl.optimal; + + + /* Clear all dirty flags */ +@@ -3711,7 +3711,7 @@ static void ilk_update_wm(struct drm_crtc *crtc) + intel_wait_for_vblank(crtc->dev, intel_crtc->pipe); + } + +- intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk; ++ intel_crtc->wm.active.ilk = cstate->wm.ilk.optimal; + + ilk_program_watermarks(cstate); + } +@@ -3767,7 +3767,7 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc) + struct skl_wm_values *hw = &dev_priv->wm.skl_hw; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); +- struct skl_pipe_wm *active = &cstate->wm.optimal.skl; ++ struct skl_pipe_wm *active = &cstate->wm.skl.optimal; + enum pipe pipe = intel_crtc->pipe; + int level, i, max_level; + uint32_t temp; +@@ -3833,7 +3833,7 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc) + struct ilk_wm_values *hw = &dev_priv->wm.hw; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); +- struct intel_pipe_wm *active = &cstate->wm.optimal.ilk; ++ struct intel_pipe_wm *active = &cstate->wm.ilk.optimal; + enum pipe pipe = intel_crtc->pipe; + static const i915_reg_t wm0_pipe_reg[] = { + [PIPE_A] = WM0_PIPEA_ILK, +-- +2.7.4 + diff --git a/0001-drm-mgag200-Black-screen-fix-for-G200e-rev-4.patch b/0001-drm-mgag200-Black-screen-fix-for-G200e-rev-4.patch new file mode 100644 index 000000000..e583d09e8 --- /dev/null +++ b/0001-drm-mgag200-Black-screen-fix-for-G200e-rev-4.patch @@ -0,0 +1,58 @@ +From 1e5895f2c6068fb9ae5356e3a751a29a22af5f01 Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 14:53:03 +0200 +Subject: [PATCH 1/6] drm/mgag200: Black screen fix for G200e rev 4 + +Upstream: since drm-fixes-for-v4.7 +commit d3922b69617b62bb2509936b68301f837229d9f0 + +Author: Mathieu Larouche +AuthorDate: Fri May 27 15:12:50 2016 -0400 +Commit: Dave Airlie +CommitDate: Wed Jun 1 15:25:04 2016 +1000 + + drm/mgag200: Black screen fix for G200e rev 4 + + - Fixed black screen for some resolutions of G200e rev4 + - Fixed testm & testn which had predetermined value. + + Reported-by: Jan Beulich + + Signed-off-by: Mathieu Larouche + Cc: stable@vger.kernel.org + Signed-off-by: Dave Airlie +--- + drivers/gpu/drm/mgag200/mgag200_mode.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c +index 14e64e0..d347dca 100644 +--- a/drivers/gpu/drm/mgag200/mgag200_mode.c ++++ b/drivers/gpu/drm/mgag200/mgag200_mode.c +@@ -182,7 +182,7 @@ static int mga_g200se_set_plls(struct mga_device *mdev, long clock) + } + } + +- fvv = pllreffreq * testn / testm; ++ fvv = pllreffreq * (n + 1) / (m + 1); + fvv = (fvv - 800000) / 50000; + + if (fvv > 15) +@@ -202,6 +202,14 @@ static int mga_g200se_set_plls(struct mga_device *mdev, long clock) + WREG_DAC(MGA1064_PIX_PLLC_M, m); + WREG_DAC(MGA1064_PIX_PLLC_N, n); + WREG_DAC(MGA1064_PIX_PLLC_P, p); ++ ++ if (mdev->unique_rev_id >= 0x04) { ++ WREG_DAC(0x1a, 0x09); ++ msleep(20); ++ WREG_DAC(0x1a, 0x01); ++ ++ } ++ + return 0; + } + +-- +2.7.4 + diff --git a/0002-drm-i915-Rename-s-skl_compute_pipe_wm-skl_build_pipe.patch b/0002-drm-i915-Rename-s-skl_compute_pipe_wm-skl_build_pipe.patch new file mode 100644 index 000000000..f9eecb97a --- /dev/null +++ b/0002-drm-i915-Rename-s-skl_compute_pipe_wm-skl_build_pipe.patch @@ -0,0 +1,60 @@ +From 4d428f0fd6aaaa75382885d897900f619b2dad35 Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 11:12:56 +0200 +Subject: [PATCH 02/17] drm/i915: Rename + s/skl_compute_pipe_wm/skl_build_pipe_wm/ + +Upstream: since drm-intel-next-2016-05-22 +commit e7649b54777ba6491204acbe1f1a34fce78637d5 + +Author: Matt Roper +AuthorDate: Thu May 12 07:05:56 2016 -0700 +Commit: Matt Roper +CommitDate: Fri May 13 07:32:27 2016 -0700 + + drm/i915: Rename s/skl_compute_pipe_wm/skl_build_pipe_wm/ + + When we added atomic watermarks, we added a new display vfunc + 'compute_pipe_wm' that is used to compute any pipe-specific watermark + information that we can at atomic check time. This was a somewhat poor + naming choice since we already had a 'skl_compute_pipe_wm' function that + doesn't quite fit this model --- the existing SKL function is something + that gets used at atomic commit time, after the DDB allocation has been + determined. Let's rename the existing SKL function to avoid confusion. + + Signed-off-by: Matt Roper + Reviewed-by: Maarten Lankhorst + Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-3-git-send-email-matthew.d.roper@intel.com +--- + drivers/gpu/drm/i915/intel_pm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index 0da1d60..8f081b2 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -3266,9 +3266,9 @@ static void skl_compute_transition_wm(struct intel_crtc_state *cstate, + } + } + +-static void skl_compute_pipe_wm(struct intel_crtc_state *cstate, +- struct skl_ddb_allocation *ddb, +- struct skl_pipe_wm *pipe_wm) ++static void skl_build_pipe_wm(struct intel_crtc_state *cstate, ++ struct skl_ddb_allocation *ddb, ++ struct skl_pipe_wm *pipe_wm) + { + struct drm_device *dev = cstate->base.crtc->dev; + const struct drm_i915_private *dev_priv = dev->dev_private; +@@ -3535,7 +3535,7 @@ static bool skl_update_pipe_wm(struct drm_crtc *crtc, + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); + + skl_allocate_pipe_ddb(cstate, ddb); +- skl_compute_pipe_wm(cstate, ddb, pipe_wm); ++ skl_build_pipe_wm(cstate, ddb, pipe_wm); + + if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm))) + return false; +-- +2.7.4 + diff --git a/0002-drm-nouveau-fbcon-fix-out-of-bounds-memory-accesses.patch b/0002-drm-nouveau-fbcon-fix-out-of-bounds-memory-accesses.patch new file mode 100644 index 000000000..d1c32b439 --- /dev/null +++ b/0002-drm-nouveau-fbcon-fix-out-of-bounds-memory-accesses.patch @@ -0,0 +1,138 @@ +From 02510a8805db2c3f8ca2926f90c4b3793934404a Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 14:51:45 +0200 +Subject: [PATCH 2/6] drm/nouveau/fbcon: fix out-of-bounds memory accesses + +Upstream: drm-fixes for 4.7 (and cc'd 4.6-stable) +commit f045f459d925138fe7d6193a8c86406bda7e49da + +Author: Ben Skeggs +AuthorDate: Thu Jun 2 12:23:31 2016 +1000 +Commit: Ben Skeggs +CommitDate: Thu Jun 2 13:53:44 2016 +1000 + + drm/nouveau/fbcon: fix out-of-bounds memory accesses + + Reported by KASAN. + + Signed-off-by: Ben Skeggs + Cc: stable@vger.kernel.org +--- + drivers/gpu/drm/nouveau/nouveau_fbcon.c | 1 + + drivers/gpu/drm/nouveau/nv04_fbcon.c | 7 ++----- + drivers/gpu/drm/nouveau/nv50_fbcon.c | 6 ++---- + drivers/gpu/drm/nouveau/nvc0_fbcon.c | 6 ++---- + 4 files changed, 7 insertions(+), 13 deletions(-) + +diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c +index 59f27e7..bd89c86 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c ++++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c +@@ -557,6 +557,7 @@ nouveau_fbcon_init(struct drm_device *dev) + if (ret) + goto fini; + ++ fbcon->helper.fbdev->pixmap.buf_align = 4; + return 0; + + fini: +diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c +index 789dc29..8f715fe 100644 +--- a/drivers/gpu/drm/nouveau/nv04_fbcon.c ++++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c +@@ -82,7 +82,6 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) + uint32_t fg; + uint32_t bg; + uint32_t dsize; +- uint32_t width; + uint32_t *data = (uint32_t *)image->data; + int ret; + +@@ -93,9 +92,6 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) + if (ret) + return ret; + +- width = ALIGN(image->width, 8); +- dsize = ALIGN(width * image->height, 32) >> 5; +- + if (info->fix.visual == FB_VISUAL_TRUECOLOR || + info->fix.visual == FB_VISUAL_DIRECTCOLOR) { + fg = ((uint32_t *) info->pseudo_palette)[image->fg_color]; +@@ -111,10 +107,11 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) + ((image->dx + image->width) & 0xffff)); + OUT_RING(chan, bg); + OUT_RING(chan, fg); +- OUT_RING(chan, (image->height << 16) | width); ++ OUT_RING(chan, (image->height << 16) | image->width); + OUT_RING(chan, (image->height << 16) | image->width); + OUT_RING(chan, (image->dy << 16) | (image->dx & 0xffff)); + ++ dsize = ALIGN(image->width * image->height, 32) >> 5; + while (dsize) { + int iter_len = dsize > 128 ? 128 : dsize; + +diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c +index e05499d..a4e259a 100644 +--- a/drivers/gpu/drm/nouveau/nv50_fbcon.c ++++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c +@@ -95,7 +95,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) + struct nouveau_fbdev *nfbdev = info->par; + struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); + struct nouveau_channel *chan = drm->channel; +- uint32_t width, dwords, *data = (uint32_t *)image->data; ++ uint32_t dwords, *data = (uint32_t *)image->data; + uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel)); + uint32_t *palette = info->pseudo_palette; + int ret; +@@ -107,9 +107,6 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) + if (ret) + return ret; + +- width = ALIGN(image->width, 32); +- dwords = (width * image->height) >> 5; +- + BEGIN_NV04(chan, NvSub2D, 0x0814, 2); + if (info->fix.visual == FB_VISUAL_TRUECOLOR || + info->fix.visual == FB_VISUAL_DIRECTCOLOR) { +@@ -128,6 +125,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) + OUT_RING(chan, 0); + OUT_RING(chan, image->dy); + ++ dwords = ALIGN(image->width * image->height, 32) >> 5; + while (dwords) { + int push = dwords > 2047 ? 2047 : dwords; + +diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c +index c97395b..f28315e 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c ++++ b/drivers/gpu/drm/nouveau/nvc0_fbcon.c +@@ -95,7 +95,7 @@ nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) + struct nouveau_fbdev *nfbdev = info->par; + struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); + struct nouveau_channel *chan = drm->channel; +- uint32_t width, dwords, *data = (uint32_t *)image->data; ++ uint32_t dwords, *data = (uint32_t *)image->data; + uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel)); + uint32_t *palette = info->pseudo_palette; + int ret; +@@ -107,9 +107,6 @@ nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) + if (ret) + return ret; + +- width = ALIGN(image->width, 32); +- dwords = (width * image->height) >> 5; +- + BEGIN_NVC0(chan, NvSub2D, 0x0814, 2); + if (info->fix.visual == FB_VISUAL_TRUECOLOR || + info->fix.visual == FB_VISUAL_DIRECTCOLOR) { +@@ -128,6 +125,7 @@ nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) + OUT_RING (chan, 0); + OUT_RING (chan, image->dy); + ++ dwords = ALIGN(image->width * image->height, 32) >> 5; + while (dwords) { + int push = dwords > 2047 ? 2047 : dwords; + +-- +2.7.4 + diff --git a/0003-drm-i915-gen9-Cache-plane-data-rates-in-CRTC-state.patch b/0003-drm-i915-gen9-Cache-plane-data-rates-in-CRTC-state.patch new file mode 100644 index 000000000..9a9366c1c --- /dev/null +++ b/0003-drm-i915-gen9-Cache-plane-data-rates-in-CRTC-state.patch @@ -0,0 +1,214 @@ +From 0206aec944641c69815562407b73b6f9df22f041 Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 11:13:09 +0200 +Subject: [PATCH 03/17] drm/i915/gen9: Cache plane data rates in CRTC state + +Upstream: since drm-intel-next-2016-05-22 +commit a1de91e5f3039dfc32ac2b77ffb280a68646cbc7 + +Author: Matt Roper +AuthorDate: Thu May 12 07:05:57 2016 -0700 +Commit: Matt Roper +CommitDate: Fri May 13 07:32:35 2016 -0700 + + drm/i915/gen9: Cache plane data rates in CRTC state + + This will be important when we start calculating CRTC data rates for + in-flight CRTC states since it will allow us to calculate the total data + rate without needing to grab the plane state for any planes that aren't + updated by the transaction. + + Signed-off-by: Matt Roper + Reviewed-by: Maarten Lankhorst + Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-4-git-send-email-matthew.d.roper@intel.com +--- + drivers/gpu/drm/i915/intel_drv.h | 4 ++ + drivers/gpu/drm/i915/intel_pm.c | 92 ++++++++++++++++++++++++++-------------- + 2 files changed, 63 insertions(+), 33 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h +index 7d19baf..7c00ab6 100644 +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -385,6 +385,10 @@ struct intel_crtc_wm_state { + struct { + /* gen9+ only needs 1-step wm programming */ + struct skl_pipe_wm optimal; ++ ++ /* cached plane data rate */ ++ unsigned plane_data_rate[I915_MAX_PLANES]; ++ unsigned plane_y_data_rate[I915_MAX_PLANES]; + } skl; + }; + +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index 8f081b2..854f0a4 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -2879,6 +2879,14 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, + struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate); + struct drm_framebuffer *fb = pstate->fb; + uint32_t width = 0, height = 0; ++ unsigned format = fb ? fb->pixel_format : DRM_FORMAT_XRGB8888; ++ ++ if (!intel_pstate->visible) ++ return 0; ++ if (pstate->plane->type == DRM_PLANE_TYPE_CURSOR) ++ return 0; ++ if (y && format != DRM_FORMAT_NV12) ++ return 0; + + width = drm_rect_width(&intel_pstate->src) >> 16; + height = drm_rect_height(&intel_pstate->src) >> 16; +@@ -2887,17 +2895,17 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, + swap(width, height); + + /* for planar format */ +- if (fb->pixel_format == DRM_FORMAT_NV12) { ++ if (format == DRM_FORMAT_NV12) { + if (y) /* y-plane data rate */ + return width * height * +- drm_format_plane_cpp(fb->pixel_format, 0); ++ drm_format_plane_cpp(format, 0); + else /* uv-plane data rate */ + return (width / 2) * (height / 2) * +- drm_format_plane_cpp(fb->pixel_format, 1); ++ drm_format_plane_cpp(format, 1); + } + + /* for packed formats */ +- return width * height * drm_format_plane_cpp(fb->pixel_format, 0); ++ return width * height * drm_format_plane_cpp(format, 0); + } + + /* +@@ -2906,32 +2914,34 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, + * 3 * 4096 * 8192 * 4 < 2^32 + */ + static unsigned int +-skl_get_total_relative_data_rate(const struct intel_crtc_state *cstate) ++skl_get_total_relative_data_rate(struct intel_crtc_state *cstate) + { + struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); + struct drm_device *dev = intel_crtc->base.dev; + const struct intel_plane *intel_plane; +- unsigned int total_data_rate = 0; ++ unsigned int rate, total_data_rate = 0; + ++ /* Calculate and cache data rate for each plane */ + for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { + const struct drm_plane_state *pstate = intel_plane->base.state; ++ int id = skl_wm_plane_id(intel_plane); + +- if (pstate->fb == NULL) +- continue; ++ /* packed/uv */ ++ rate = skl_plane_relative_data_rate(cstate, pstate, 0); ++ cstate->wm.skl.plane_data_rate[id] = rate; + +- if (intel_plane->base.type == DRM_PLANE_TYPE_CURSOR) +- continue; ++ /* y-plane */ ++ rate = skl_plane_relative_data_rate(cstate, pstate, 1); ++ cstate->wm.skl.plane_y_data_rate[id] = rate; ++ } + +- /* packed/uv */ +- total_data_rate += skl_plane_relative_data_rate(cstate, +- pstate, +- 0); ++ /* Calculate CRTC's total data rate from cached values */ ++ for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { ++ int id = skl_wm_plane_id(intel_plane); + +- if (pstate->fb->pixel_format == DRM_FORMAT_NV12) +- /* y-plane */ +- total_data_rate += skl_plane_relative_data_rate(cstate, +- pstate, +- 1); ++ /* packed/uv */ ++ total_data_rate += cstate->wm.skl.plane_data_rate[id]; ++ total_data_rate += cstate->wm.skl.plane_y_data_rate[id]; + } + + return total_data_rate; +@@ -2995,6 +3005,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, + * FIXME: we may not allocate every single block here. + */ + total_data_rate = skl_get_total_relative_data_rate(cstate); ++ if (total_data_rate == 0) ++ return; + + start = alloc->start; + for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { +@@ -3009,7 +3021,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, + if (plane->type == DRM_PLANE_TYPE_CURSOR) + continue; + +- data_rate = skl_plane_relative_data_rate(cstate, pstate, 0); ++ data_rate = cstate->wm.skl.plane_data_rate[id]; + + /* + * allocation for (packed formats) or (uv-plane part of planar format): +@@ -3028,20 +3040,16 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, + /* + * allocation for y_plane part of planar format: + */ +- if (pstate->fb->pixel_format == DRM_FORMAT_NV12) { +- y_data_rate = skl_plane_relative_data_rate(cstate, +- pstate, +- 1); +- y_plane_blocks = y_minimum[id]; +- y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate, +- total_data_rate); +- +- ddb->y_plane[pipe][id].start = start; +- ddb->y_plane[pipe][id].end = start + y_plane_blocks; +- +- start += y_plane_blocks; +- } ++ y_data_rate = cstate->wm.skl.plane_y_data_rate[id]; ++ ++ y_plane_blocks = y_minimum[id]; ++ y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate, ++ total_data_rate); + ++ ddb->y_plane[pipe][id].start = start; ++ ddb->y_plane[pipe][id].end = start + y_plane_blocks; ++ ++ start += y_plane_blocks; + } + + } +@@ -3820,10 +3828,28 @@ void skl_wm_get_hw_state(struct drm_device *dev) + struct drm_i915_private *dev_priv = dev->dev_private; + struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb; + struct drm_crtc *crtc; ++ struct intel_crtc *intel_crtc; + + skl_ddb_get_hw_state(dev_priv, ddb); + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + skl_pipe_wm_get_hw_state(crtc); ++ ++ /* Calculate plane data rates */ ++ for_each_intel_crtc(dev, intel_crtc) { ++ struct intel_crtc_state *cstate = intel_crtc->config; ++ struct intel_plane *intel_plane; ++ ++ for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { ++ const struct drm_plane_state *pstate = ++ intel_plane->base.state; ++ int id = skl_wm_plane_id(intel_plane); ++ ++ cstate->wm.skl.plane_data_rate[id] = ++ skl_plane_relative_data_rate(cstate, pstate, 0); ++ cstate->wm.skl.plane_y_data_rate[id] = ++ skl_plane_relative_data_rate(cstate, pstate, 1); ++ } ++ } + } + + static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc) +-- +2.7.4 + diff --git a/0003-drm-nouveau-disp-sor-gf119-both-links-use-the-same-t.patch b/0003-drm-nouveau-disp-sor-gf119-both-links-use-the-same-t.patch new file mode 100644 index 000000000..b93bdff17 --- /dev/null +++ b/0003-drm-nouveau-disp-sor-gf119-both-links-use-the-same-t.patch @@ -0,0 +1,46 @@ +From de35f524e89daf8862d49724b9045f9254bfdfea Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 14:52:01 +0200 +Subject: [PATCH 3/6] drm/nouveau/disp/sor/gf119: both links use the same + training register + +Upstream: drm-fixes for 4.7 (and cc'd 4.6-stable) +commit a8953c52b95167b5d21a66f0859751570271d834 + +Author: Ben Skeggs +AuthorDate: Fri Jun 3 14:37:40 2016 +1000 +Commit: Ben Skeggs +CommitDate: Tue Jun 7 08:11:14 2016 +1000 + + drm/nouveau/disp/sor/gf119: both links use the same training register + + It appears that, for whatever reason, both link A and B use the same + register to control the training pattern. It's a little odd, as the + GPUs before this (Tesla/Fermi1) have per-link registers, as do newer + GPUs (Maxwell). + + Fixes the third DP output on NVS 510 (GK107). + + Signed-off-by: Ben Skeggs + Cc: stable@vger.kernel.org +--- + drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c +index b4b41b1..5111560 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c +@@ -40,8 +40,7 @@ static int + gf119_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern) + { + struct nvkm_device *device = outp->base.disp->engine.subdev.device; +- const u32 loff = gf119_sor_loff(outp); +- nvkm_mask(device, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern); ++ nvkm_mask(device, 0x61c110, 0x0f0f0f0f, 0x01010101 * pattern); + return 0; + } + +-- +2.7.4 + diff --git a/0004-drm-i915-gen9-Allow-calculation-of-data-rate-for-in-.patch b/0004-drm-i915-gen9-Allow-calculation-of-data-rate-for-in-.patch new file mode 100644 index 000000000..3a2b0aa1c --- /dev/null +++ b/0004-drm-i915-gen9-Allow-calculation-of-data-rate-for-in-.patch @@ -0,0 +1,141 @@ +From a75a3c793e2cd3e7648597f2c77d87453f520f31 Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 11:13:23 +0200 +Subject: [PATCH 04/17] drm/i915/gen9: Allow calculation of data rate for + in-flight state (v2) + +Upstream: since drm-intel-next-2016-05-22 +commit 9c74d82621c553f0da1f41bd5d90f5eab5659fdb + +Author: Matt Roper +AuthorDate: Thu May 12 07:05:58 2016 -0700 +Commit: Matt Roper +CommitDate: Fri May 13 07:32:49 2016 -0700 + + drm/i915/gen9: Allow calculation of data rate for in-flight state (v2) + + Our skl_get_total_relative_data_rate() function gets passed a crtc state + object to calculate the data rate for, but it currently always looks + up the committed plane states that correspond to that CRTC. Let's + check whether the CRTC state is an in-flight state (meaning + cstate->state is non-NULL) and if so, use the corresponding in-flight + plane states. + + We'll soon be using this function exclusively for in-flight states; at + that time we'll be able to simplify the function a bit, but for now we + allow it to be used in either mode. + + v2: + - Rebase on top of changes to cache plane data rates. + + Signed-off-by: Matt Roper + Reviewed-by: Maarten Lankhorst + Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-5-git-send-email-matthew.d.roper@intel.com +--- + drivers/gpu/drm/i915/intel_pm.c | 74 +++++++++++++++++++++++++++++++++-------- + 1 file changed, 60 insertions(+), 14 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index 854f0a4..b863bfc 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -2914,25 +2914,69 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, + * 3 * 4096 * 8192 * 4 < 2^32 + */ + static unsigned int +-skl_get_total_relative_data_rate(struct intel_crtc_state *cstate) ++skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate) + { +- struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); +- struct drm_device *dev = intel_crtc->base.dev; ++ struct drm_crtc_state *cstate = &intel_cstate->base; ++ struct drm_atomic_state *state = cstate->state; ++ struct drm_crtc *crtc = cstate->crtc; ++ struct drm_device *dev = crtc->dev; ++ struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + const struct intel_plane *intel_plane; + unsigned int rate, total_data_rate = 0; ++ int id; + + /* Calculate and cache data rate for each plane */ +- for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { +- const struct drm_plane_state *pstate = intel_plane->base.state; +- int id = skl_wm_plane_id(intel_plane); ++ /* ++ * FIXME: At the moment this function can be called on either an ++ * in-flight or a committed state object. If it's in-flight then we ++ * only want to re-calculate the plane data rate for planes that are ++ * part of the transaction (i.e., we don't want to grab any additional ++ * plane states if we don't have to). If we're operating on committed ++ * state, we'll just go ahead and recalculate the plane data rate for ++ * all planes. ++ * ++ * Once we finish moving our DDB allocation to the atomic check phase, ++ * we'll only be calling this function on in-flight state objects, so ++ * the 'else' branch here will go away. ++ */ ++ if (state) { ++ struct drm_plane *plane; ++ struct drm_plane_state *pstate; ++ int i; ++ ++ for_each_plane_in_state(state, plane, pstate, i) { ++ intel_plane = to_intel_plane(plane); ++ id = skl_wm_plane_id(intel_plane); ++ ++ if (intel_plane->pipe != intel_crtc->pipe) ++ continue; ++ ++ /* packed/uv */ ++ rate = skl_plane_relative_data_rate(intel_cstate, ++ pstate, 0); ++ intel_cstate->wm.skl.plane_data_rate[id] = rate; ++ ++ /* y-plane */ ++ rate = skl_plane_relative_data_rate(intel_cstate, ++ pstate, 1); ++ intel_cstate->wm.skl.plane_y_data_rate[id] = rate; ++ } ++ } else { ++ for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { ++ const struct drm_plane_state *pstate = ++ intel_plane->base.state; ++ int id = skl_wm_plane_id(intel_plane); + +- /* packed/uv */ +- rate = skl_plane_relative_data_rate(cstate, pstate, 0); +- cstate->wm.skl.plane_data_rate[id] = rate; ++ /* packed/uv */ ++ rate = skl_plane_relative_data_rate(intel_cstate, ++ pstate, 0); ++ intel_cstate->wm.skl.plane_data_rate[id] = rate; + +- /* y-plane */ +- rate = skl_plane_relative_data_rate(cstate, pstate, 1); +- cstate->wm.skl.plane_y_data_rate[id] = rate; ++ /* y-plane */ ++ rate = skl_plane_relative_data_rate(intel_cstate, ++ pstate, 1); ++ intel_cstate->wm.skl.plane_y_data_rate[id] = rate; ++ } + } + + /* Calculate CRTC's total data rate from cached values */ +@@ -2940,10 +2984,12 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *cstate) + int id = skl_wm_plane_id(intel_plane); + + /* packed/uv */ +- total_data_rate += cstate->wm.skl.plane_data_rate[id]; +- total_data_rate += cstate->wm.skl.plane_y_data_rate[id]; ++ total_data_rate += intel_cstate->wm.skl.plane_data_rate[id]; ++ total_data_rate += intel_cstate->wm.skl.plane_y_data_rate[id]; + } + ++ WARN_ON(cstate->plane_mask && total_data_rate == 0); ++ + return total_data_rate; + } + +-- +2.7.4 + diff --git a/0004-drm-nouveau-disp-sor-gm107-training-pattern-register.patch b/0004-drm-nouveau-disp-sor-gm107-training-pattern-register.patch new file mode 100644 index 000000000..a0b6171d8 --- /dev/null +++ b/0004-drm-nouveau-disp-sor-gm107-training-pattern-register.patch @@ -0,0 +1,195 @@ +From eb4668302adce316f53896b0fd8144ffe380a3ad Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 14:52:06 +0200 +Subject: [PATCH 4/6] drm/nouveau/disp/sor/gm107: training pattern registers + are like gm200 + +Upstream: drm-fixes for 4.7 (and cc'd 4.6-stable) +commit 4691409b3e2250ed66aa8dcefa23fe765daf7add + +Author: Ben Skeggs +AuthorDate: Fri Jun 3 15:05:52 2016 +1000 +Commit: Ben Skeggs +CommitDate: Tue Jun 7 08:11:25 2016 +1000 + + drm/nouveau/disp/sor/gm107: training pattern registers are like gm200 + + Signed-off-by: Ben Skeggs + Cc: stable@vger.kernel.org +--- + drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild | 1 + + drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c | 2 +- + drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h | 9 +++- + .../gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c | 2 +- + .../nvkm/engine/disp/{gm107.c => sorgm107.c} | 50 +++++++++++----------- + .../gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c | 15 +------ + 6 files changed, 36 insertions(+), 43 deletions(-) + copy drivers/gpu/drm/nouveau/nvkm/engine/disp/{gm107.c => sorgm107.c} (55%) + +diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild +index a74c5dd..e2a64ed 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild +@@ -18,6 +18,7 @@ nvkm-y += nvkm/engine/disp/piornv50.o + nvkm-y += nvkm/engine/disp/sornv50.o + nvkm-y += nvkm/engine/disp/sorg94.o + nvkm-y += nvkm/engine/disp/sorgf119.o ++nvkm-y += nvkm/engine/disp/sorgm107.o + nvkm-y += nvkm/engine/disp/sorgm200.o + nvkm-y += nvkm/engine/disp/dport.o + +diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c +index b694414..f4b9cf8 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c +@@ -36,7 +36,7 @@ gm107_disp = { + .outp.internal.crt = nv50_dac_output_new, + .outp.internal.tmds = nv50_sor_output_new, + .outp.internal.lvds = nv50_sor_output_new, +- .outp.internal.dp = gf119_sor_dp_new, ++ .outp.internal.dp = gm107_sor_dp_new, + .dac.nr = 3, + .dac.power = nv50_dac_power, + .dac.sense = nv50_dac_sense, +diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h +index e9067ba..4e983f6 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h +@@ -62,7 +62,12 @@ int g94_sor_dp_lnk_pwr(struct nvkm_output_dp *, int); + int gf119_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *, + struct nvkm_output **); + int gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *, int, int, bool); ++int gf119_sor_dp_drv_ctl(struct nvkm_output_dp *, int, int, int, int); + +-int gm200_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *, +- struct nvkm_output **); ++int gm107_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *, ++ struct nvkm_output **); ++int gm107_sor_dp_pattern(struct nvkm_output_dp *, int); ++ ++int gm200_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *, ++ struct nvkm_output **); + #endif +diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c +index 5111560..22706c0 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c +@@ -63,7 +63,7 @@ gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef) + return 0; + } + +-static int ++int + gf119_sor_dp_drv_ctl(struct nvkm_output_dp *outp, + int ln, int vs, int pe, int pc) + { +diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c +similarity index 55% +copy from drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c +copy to drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c +index b694414..37790b2 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c +@@ -1,5 +1,5 @@ + /* +- * Copyright 2012 Red Hat Inc. ++ * Copyright 2016 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), +@@ -19,35 +19,35 @@ + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * +- * Authors: Ben Skeggs ++ * Authors: Ben Skeggs + */ + #include "nv50.h" +-#include "rootnv50.h" ++#include "outpdp.h" + +-static const struct nv50_disp_func +-gm107_disp = { +- .intr = gf119_disp_intr, +- .uevent = &gf119_disp_chan_uevent, +- .super = gf119_disp_intr_supervisor, +- .root = &gm107_disp_root_oclass, +- .head.vblank_init = gf119_disp_vblank_init, +- .head.vblank_fini = gf119_disp_vblank_fini, +- .head.scanoutpos = gf119_disp_root_scanoutpos, +- .outp.internal.crt = nv50_dac_output_new, +- .outp.internal.tmds = nv50_sor_output_new, +- .outp.internal.lvds = nv50_sor_output_new, +- .outp.internal.dp = gf119_sor_dp_new, +- .dac.nr = 3, +- .dac.power = nv50_dac_power, +- .dac.sense = nv50_dac_sense, +- .sor.nr = 4, +- .sor.power = nv50_sor_power, +- .sor.hda_eld = gf119_hda_eld, +- .sor.hdmi = gk104_hdmi_ctrl, ++int ++gm107_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern) ++{ ++ struct nvkm_device *device = outp->base.disp->engine.subdev.device; ++ const u32 soff = outp->base.or * 0x800; ++ const u32 data = 0x01010101 * pattern; ++ if (outp->base.info.sorconf.link & 1) ++ nvkm_mask(device, 0x61c110 + soff, 0x0f0f0f0f, data); ++ else ++ nvkm_mask(device, 0x61c12c + soff, 0x0f0f0f0f, data); ++ return 0; ++} ++ ++static const struct nvkm_output_dp_func ++gm107_sor_dp_func = { ++ .pattern = gm107_sor_dp_pattern, ++ .lnk_pwr = g94_sor_dp_lnk_pwr, ++ .lnk_ctl = gf119_sor_dp_lnk_ctl, ++ .drv_ctl = gf119_sor_dp_drv_ctl, + }; + + int +-gm107_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) ++gm107_sor_dp_new(struct nvkm_disp *disp, int index, ++ struct dcb_output *dcbE, struct nvkm_output **poutp) + { +- return gf119_disp_new_(&gm107_disp, device, index, pdisp); ++ return nvkm_output_dp_new_(&gm107_sor_dp_func, disp, index, dcbE, poutp); + } +diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c +index 2cfbef9..c44fa7e 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c +@@ -57,19 +57,6 @@ gm200_sor_dp_lane_map(struct nvkm_device *device, u8 lane) + } + + static int +-gm200_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern) +-{ +- struct nvkm_device *device = outp->base.disp->engine.subdev.device; +- const u32 soff = gm200_sor_soff(outp); +- const u32 data = 0x01010101 * pattern; +- if (outp->base.info.sorconf.link & 1) +- nvkm_mask(device, 0x61c110 + soff, 0x0f0f0f0f, data); +- else +- nvkm_mask(device, 0x61c12c + soff, 0x0f0f0f0f, data); +- return 0; +-} +- +-static int + gm200_sor_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr) + { + struct nvkm_device *device = outp->base.disp->engine.subdev.device; +@@ -129,7 +116,7 @@ gm200_sor_dp_drv_ctl(struct nvkm_output_dp *outp, + + static const struct nvkm_output_dp_func + gm200_sor_dp_func = { +- .pattern = gm200_sor_dp_pattern, ++ .pattern = gm107_sor_dp_pattern, + .lnk_pwr = gm200_sor_dp_lnk_pwr, + .lnk_ctl = gf119_sor_dp_lnk_ctl, + .drv_ctl = gm200_sor_dp_drv_ctl, +-- +2.7.4 + diff --git a/0005-drm-i915-gen9-Store-plane-minimum-blocks-in-CRTC-wm-.patch b/0005-drm-i915-gen9-Store-plane-minimum-blocks-in-CRTC-wm-.patch new file mode 100644 index 000000000..7b1fcb144 --- /dev/null +++ b/0005-drm-i915-gen9-Store-plane-minimum-blocks-in-CRTC-wm-.patch @@ -0,0 +1,67 @@ +From cd21ce996b94fd149b3487398e5250e9f0cc8811 Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 12:39:24 +0200 +Subject: [PATCH 05/17] drm/i915/gen9: Store plane minimum blocks in CRTC wm + state (v2) + +Upstream: since drm-intel-next-2016-05-22 +commit 86a2100a8b96594902bb59b90614377df4f64ce0 + +Author: Matt Roper +AuthorDate: Thu May 12 07:05:59 2016 -0700 +Commit: Matt Roper +CommitDate: Fri May 13 07:32:56 2016 -0700 + + drm/i915/gen9: Store plane minimum blocks in CRTC wm state (v2) + + This will eventually allow us to re-use old values without + re-calculating them for unchanged planes (which also helps us avoid + re-grabbing extra plane states). + + v2: + - Drop unnecessary memset's; they were meant for a later patch (which + got reworked anyway to not need them, but were mis-rebased into this + one. (Maarten) + + Cc: Maarten Lankhorst + Signed-off-by: Matt Roper + Reviewed-by: Maarten Lankhorst + Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-6-git-send-email-matthew.d.roper@intel.com +--- + drivers/gpu/drm/i915/intel_drv.h | 4 ++++ + drivers/gpu/drm/i915/intel_pm.c | 4 ++-- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h +index 7c00ab6..d246308 100644 +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -389,6 +389,10 @@ struct intel_crtc_wm_state { + /* cached plane data rate */ + unsigned plane_data_rate[I915_MAX_PLANES]; + unsigned plane_y_data_rate[I915_MAX_PLANES]; ++ ++ /* minimum block allocation */ ++ uint16_t minimum_blocks[I915_MAX_PLANES]; ++ uint16_t minimum_y_blocks[I915_MAX_PLANES]; + } skl; + }; + +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index b863bfc..00db6e9 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -3006,8 +3006,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, + enum pipe pipe = intel_crtc->pipe; + struct skl_ddb_entry *alloc = &ddb->pipe[pipe]; + uint16_t alloc_size, start, cursor_blocks; +- uint16_t minimum[I915_MAX_PLANES]; +- uint16_t y_minimum[I915_MAX_PLANES]; ++ uint16_t *minimum = cstate->wm.skl.minimum_blocks; ++ uint16_t *y_minimum = cstate->wm.skl.minimum_y_blocks; + unsigned int total_data_rate; + + skl_ddb_get_pipe_allocation_limits(dev, cstate, config, alloc); +-- +2.7.4 + diff --git a/0005-i915-fbc-Disable-on-HSW-by-default-for-now.patch b/0005-i915-fbc-Disable-on-HSW-by-default-for-now.patch new file mode 100644 index 000000000..d95f2f4d0 --- /dev/null +++ b/0005-i915-fbc-Disable-on-HSW-by-default-for-now.patch @@ -0,0 +1,55 @@ +From 28d0147bded959b2c4d3eb1aa957452d5dbb0cc9 Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 14:52:10 +0200 +Subject: [PATCH 5/6] i915/fbc: Disable on HSW by default for now + +Upstream: posted on dri-devel (and r-b'd) + +Author: cpaul@redhat.com +AuthorDate: Thu Jun 9 11:58:15 2016 -0400 +Commit: Rob Clark +CommitDate: Thu Jun 9 15:43:07 2016 -0400 + + i915/fbc: Disable on HSW by default for now + + >From https://bugs.freedesktop.org/show_bug.cgi?id=96461 : + + This was kind of a difficult bug to track down. If you're using a + Haswell system running GNOME and you have fbc completely enabled and + working, playing videos can result in video artifacts. Steps to + reproduce: + + - Run GNOME + - Ensure FBC is enabled and active + - Download a movie, I used the ogg version of Big Buck Bunny for this + - Run `gst-launch-1.0 filesrc location='some_movie.ogg' ! decodebin ! + glimagesink` in a terminal + - Watch for about over a minute, you'll see small horizontal lines go + down the screen. + + For the time being, disable FBC for Haswell by default. + + Signed-off-by: Lyude + Reviewed-by: Paulo Zanoni + Cc: stable@vger.kernel.org +--- + drivers/gpu/drm/i915/intel_fbc.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c +index 0f0492f..28f4407 100644 +--- a/drivers/gpu/drm/i915/intel_fbc.c ++++ b/drivers/gpu/drm/i915/intel_fbc.c +@@ -823,8 +823,7 @@ static bool intel_fbc_can_choose(struct intel_crtc *crtc) + { + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct intel_fbc *fbc = &dev_priv->fbc; +- bool enable_by_default = IS_HASWELL(dev_priv) || +- IS_BROADWELL(dev_priv); ++ bool enable_by_default = IS_BROADWELL(dev_priv); + + if (intel_vgpu_active(dev_priv->dev)) { + fbc->no_fbc_reason = "VGPU is active"; +-- +2.7.4 + diff --git a/0006-drm-core-Do-not-preserve-framebuffer-on-rmfb-v4.patch b/0006-drm-core-Do-not-preserve-framebuffer-on-rmfb-v4.patch new file mode 100644 index 000000000..81936aca1 --- /dev/null +++ b/0006-drm-core-Do-not-preserve-framebuffer-on-rmfb-v4.patch @@ -0,0 +1,145 @@ +From b87459ac92803eafc8dd9f8a8ccc36190fe427f1 Mon Sep 17 00:00:00 2001 +From: Maarten Lankhorst +Date: Wed, 4 May 2016 14:38:26 +0200 +Subject: [PATCH 6/6] drm/core: Do not preserve framebuffer on rmfb, v4. + +Upstream since: 4.7-rc1 +commit f2d580b9a8149735cbc4b59c4a8df60173658140 + +It turns out that preserving framebuffers after the rmfb call breaks +vmwgfx userspace. This was originally introduced because it was thought +nobody relied on the behavior, but unfortunately it seems there are +exceptions. + +drm_framebuffer_remove may fail with -EINTR now, so a straight revert +is impossible. There is no way to remove the framebuffer from the lists +and active planes without introducing a race because of the different +locking requirements. Instead call drm_framebuffer_remove from a +workqueue, which is unaffected by signals. + +Changes since v1: +- Add comment. +Changes since v2: +- Add fastpath for refcount = 1. (danvet) +Changes since v3: +- Rebased. +- Restore lastclose framebuffer removal too. + +Cc: stable@vger.kernel.org #v4.4+ +Fixes: 13803132818c ("drm/core: Preserve the framebuffer after removing it.") +Testcase: kms_rmfb_basic +References: https://lists.freedesktop.org/archives/dri-devel/2016-March/102876.html +Cc: Thomas Hellstrom +Cc: David Herrmann +Reviewed-by: Daniel Vetter +Tested-by: Thomas Hellstrom #v3 +Tested-by: Tvrtko Ursulin +Signed-off-by: Daniel Vetter +Link: http://patchwork.freedesktop.org/patch/msgid/6c63ca37-0e7e-ac7f-a6d2-c7822e3d611f@linux.intel.com +--- + drivers/gpu/drm/drm_crtc.c | 60 ++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 55 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c +index e08f962..f30de80 100644 +--- a/drivers/gpu/drm/drm_crtc.c ++++ b/drivers/gpu/drm/drm_crtc.c +@@ -3434,6 +3434,24 @@ int drm_mode_addfb2(struct drm_device *dev, + return 0; + } + ++struct drm_mode_rmfb_work { ++ struct work_struct work; ++ struct list_head fbs; ++}; ++ ++static void drm_mode_rmfb_work_fn(struct work_struct *w) ++{ ++ struct drm_mode_rmfb_work *arg = container_of(w, typeof(*arg), work); ++ ++ while (!list_empty(&arg->fbs)) { ++ struct drm_framebuffer *fb = ++ list_first_entry(&arg->fbs, typeof(*fb), filp_head); ++ ++ list_del_init(&fb->filp_head); ++ drm_framebuffer_remove(fb); ++ } ++} ++ + /** + * drm_mode_rmfb - remove an FB from the configuration + * @dev: drm device for the ioctl +@@ -3474,7 +3492,25 @@ int drm_mode_rmfb(struct drm_device *dev, + mutex_unlock(&dev->mode_config.fb_lock); + mutex_unlock(&file_priv->fbs_lock); + +- drm_framebuffer_unreference(fb); ++ /* ++ * we now own the reference that was stored in the fbs list ++ * ++ * drm_framebuffer_remove may fail with -EINTR on pending signals, ++ * so run this in a separate stack as there's no way to correctly ++ * handle this after the fb is already removed from the lookup table. ++ */ ++ if (atomic_read(&fb->refcount.refcount) > 1) { ++ struct drm_mode_rmfb_work arg; ++ ++ INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn); ++ INIT_LIST_HEAD(&arg.fbs); ++ list_add_tail(&fb->filp_head, &arg.fbs); ++ ++ schedule_work(&arg.work); ++ flush_work(&arg.work); ++ destroy_work_on_stack(&arg.work); ++ } else ++ drm_framebuffer_unreference(fb); + + return 0; + +@@ -3627,7 +3663,6 @@ out_err1: + return ret; + } + +- + /** + * drm_fb_release - remove and free the FBs on this file + * @priv: drm file for the ioctl +@@ -3642,6 +3677,9 @@ out_err1: + void drm_fb_release(struct drm_file *priv) + { + struct drm_framebuffer *fb, *tfb; ++ struct drm_mode_rmfb_work arg; ++ ++ INIT_LIST_HEAD(&arg.fbs); + + /* + * When the file gets released that means no one else can access the fb +@@ -3654,10 +3692,22 @@ void drm_fb_release(struct drm_file *priv) + * at it any more. + */ + list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { +- list_del_init(&fb->filp_head); ++ if (atomic_read(&fb->refcount.refcount) > 1) { ++ list_move_tail(&fb->filp_head, &arg.fbs); ++ } else { ++ list_del_init(&fb->filp_head); + +- /* This drops the fpriv->fbs reference. */ +- drm_framebuffer_unreference(fb); ++ /* This drops the fpriv->fbs reference. */ ++ drm_framebuffer_unreference(fb); ++ } ++ } ++ ++ if (!list_empty(&arg.fbs)) { ++ INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn); ++ ++ schedule_work(&arg.work); ++ flush_work(&arg.work); ++ destroy_work_on_stack(&arg.work); + } + } + +-- +2.7.4 + diff --git a/0006-drm-i915-Track-whether-an-atomic-transaction-changes.patch b/0006-drm-i915-Track-whether-an-atomic-transaction-changes.patch new file mode 100644 index 000000000..7320abf6d --- /dev/null +++ b/0006-drm-i915-Track-whether-an-atomic-transaction-changes.patch @@ -0,0 +1,68 @@ +From 00edb23bcefa3ad6931f2a2855fe0801a55523f7 Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 12:39:40 +0200 +Subject: [PATCH 06/17] drm/i915: Track whether an atomic transaction changes + the active CRTC's + +Upstream: since drm-intel-next-2016-05-22 +commit 8b4a7d0597cd9910d7127ffae6ae91d21853a8a2 + +Author: Matt Roper +AuthorDate: Thu May 12 07:06:00 2016 -0700 +Commit: Matt Roper +CommitDate: Fri May 13 07:33:10 2016 -0700 + + drm/i915: Track whether an atomic transaction changes the active CRTC's + + For the purposes of DDB re-allocation we need to know whether a + transaction changes the list of CRTC's that are active. While + state->modeset could be used for this purpose, that would be slightly + too aggressive since it would lead us to re-allocate the DDB when a + CRTC's mode changes, but not its final active state. + + Signed-off-by: Matt Roper + Reviewed-by: Maarten Lankhorst + Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-7-git-send-email-matthew.d.roper@intel.com +--- + drivers/gpu/drm/i915/intel_display.c | 3 +++ + drivers/gpu/drm/i915/intel_drv.h | 10 ++++++++++ + 2 files changed, 13 insertions(+) + +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index 7d855ba..f53df81 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -13183,6 +13183,9 @@ static int intel_modeset_checks(struct drm_atomic_state *state) + intel_state->active_crtcs |= 1 << i; + else + intel_state->active_crtcs &= ~(1 << i); ++ ++ if (crtc_state->active != crtc->state->active) ++ intel_state->active_pipe_changes |= drm_crtc_mask(crtc); + } + + /* +diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h +index d246308..672ca56 100644 +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -256,6 +256,16 @@ struct intel_atomic_state { + + bool dpll_set, modeset; + ++ /* ++ * Does this transaction change the pipes that are active? This mask ++ * tracks which CRTC's have changed their active state at the end of ++ * the transaction (not counting the temporary disable during modesets). ++ * This mask should only be non-zero when intel_state->modeset is true, ++ * but the converse is not necessarily true; simply changing a mode may ++ * not flip the final active status of any CRTC's ++ */ ++ unsigned int active_pipe_changes; ++ + unsigned int active_crtcs; + unsigned int min_pixclk[I915_MAX_PIPES]; + +-- +2.7.4 + diff --git a/0007-drm-i915-gen9-Allow-skl_allocate_pipe_ddb-to-operate.patch b/0007-drm-i915-gen9-Allow-skl_allocate_pipe_ddb-to-operate.patch new file mode 100644 index 000000000..deb90fb01 --- /dev/null +++ b/0007-drm-i915-gen9-Allow-skl_allocate_pipe_ddb-to-operate.patch @@ -0,0 +1,352 @@ +From 99dd9c3733696d4a2536b21988c9b1b8f5195c5b Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 12:40:00 +0200 +Subject: [PATCH 07/17] drm/i915/gen9: Allow skl_allocate_pipe_ddb() to operate + on in-flight state (v3) + +Upstream: since drm-intel-next-2016-05-22 +commit c107acfeb03187873657ccc8af4fc5c704b3626b + +Author: Matt Roper +AuthorDate: Thu May 12 07:06:01 2016 -0700 +Commit: Matt Roper +CommitDate: Fri May 13 07:33:16 2016 -0700 + + drm/i915/gen9: Allow skl_allocate_pipe_ddb() to operate on in-flight state (v3) + + We eventually want to calculate watermark values at atomic 'check' time + instead of atomic 'commit' time so that any requested configurations + that result in impossible watermark requirements are properly rejected. + The first step along this path is to allocate the DDB at atomic 'check' + time. As we perform this transition, allow the main allocation function + to operate successfully on either an in-flight state or an + already-commited state. Once we complete the transition in a future + patch, we'll come back and remove the unnecessary logic for the + already-committed case. + + v2: Rebase/refactor; we should no longer need to grab extra plane states + while allocating the DDB since we can pull cached data rates and + minimum block counts from the CRTC state for any planes that aren't + being modified by this transaction. + + v3: + - Simplify memsets to clear DDB plane entries. (Maarten) + - Drop a redundant memset of plane[pipe][PLANE_CURSOR] that was added + by an earlier Coccinelle patch. (Maarten) + - Assign *num_active at the top of skl_ddb_get_pipe_allocation_limits() + so that no code paths return without setting it. (kbuild robot) + + Cc: Maarten Lankhorst + Signed-off-by: Matt Roper + Reviewed-by: Maarten Lankhorst + Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-8-git-send-email-matthew.d.roper@intel.com +--- + drivers/gpu/drm/i915/i915_drv.h | 6 ++ + drivers/gpu/drm/i915/intel_pm.c | 179 +++++++++++++++++++++++++++++----------- + 2 files changed, 139 insertions(+), 46 deletions(-) + +diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h +index daba7eb..804af6f 100644 +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -281,6 +281,12 @@ struct i915_hotplug { + &dev->mode_config.plane_list, \ + base.head) + ++#define for_each_intel_plane_mask(dev, intel_plane, plane_mask) \ ++ list_for_each_entry(intel_plane, &dev->mode_config.plane_list, \ ++ base.head) \ ++ for_each_if ((plane_mask) & \ ++ (1 << drm_plane_index(&intel_plane->base))) ++ + #define for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) \ + list_for_each_entry(intel_plane, \ + &(dev)->mode_config.plane_list, \ +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index 00db6e9..ee82b1f 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -2788,13 +2788,25 @@ skl_wm_plane_id(const struct intel_plane *plane) + static void + skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, + const struct intel_crtc_state *cstate, +- const struct intel_wm_config *config, +- struct skl_ddb_entry *alloc /* out */) ++ struct intel_wm_config *config, ++ struct skl_ddb_entry *alloc, /* out */ ++ int *num_active /* out */) + { ++ struct drm_atomic_state *state = cstate->base.state; ++ struct intel_atomic_state *intel_state = to_intel_atomic_state(state); ++ struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_crtc *for_crtc = cstate->base.crtc; + struct drm_crtc *crtc; + unsigned int pipe_size, ddb_size; + int nth_active_pipe; ++ int pipe = to_intel_crtc(for_crtc)->pipe; ++ ++ if (intel_state && intel_state->active_pipe_changes) ++ *num_active = hweight32(intel_state->active_crtcs); ++ else if (intel_state) ++ *num_active = hweight32(dev_priv->active_crtcs); ++ else ++ *num_active = config->num_pipes_active; + + if (!cstate->base.active) { + alloc->start = 0; +@@ -2809,25 +2821,56 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, + + ddb_size -= 4; /* 4 blocks for bypass path allocation */ + +- nth_active_pipe = 0; +- for_each_crtc(dev, crtc) { +- if (!to_intel_crtc(crtc)->active) +- continue; ++ /* ++ * FIXME: At the moment we may be called on either in-flight or fully ++ * committed cstate's. Once we fully move DDB allocation in the check ++ * phase, we'll only be called on in-flight states and the 'else' ++ * branch here will go away. ++ * ++ * The 'else' branch is slightly racy here, but it was racy to begin ++ * with; since it's going away soon, no effort is made to address that. ++ */ ++ if (state) { ++ /* ++ * If the state doesn't change the active CRTC's, then there's ++ * no need to recalculate; the existing pipe allocation limits ++ * should remain unchanged. Note that we're safe from racing ++ * commits since any racing commit that changes the active CRTC ++ * list would need to grab _all_ crtc locks, including the one ++ * we currently hold. ++ */ ++ if (!intel_state->active_pipe_changes) { ++ *alloc = dev_priv->wm.skl_hw.ddb.pipe[pipe]; ++ return; ++ } + +- if (crtc == for_crtc) +- break; ++ nth_active_pipe = hweight32(intel_state->active_crtcs & ++ (drm_crtc_mask(for_crtc) - 1)); ++ pipe_size = ddb_size / hweight32(intel_state->active_crtcs); ++ alloc->start = nth_active_pipe * ddb_size / *num_active; ++ alloc->end = alloc->start + pipe_size; ++ } else { ++ nth_active_pipe = 0; ++ for_each_crtc(dev, crtc) { ++ if (!to_intel_crtc(crtc)->active) ++ continue; + +- nth_active_pipe++; +- } ++ if (crtc == for_crtc) ++ break; ++ ++ nth_active_pipe++; ++ } + +- pipe_size = ddb_size / config->num_pipes_active; +- alloc->start = nth_active_pipe * ddb_size / config->num_pipes_active; +- alloc->end = alloc->start + pipe_size; ++ pipe_size = ddb_size / config->num_pipes_active; ++ alloc->start = nth_active_pipe * ddb_size / ++ config->num_pipes_active; ++ alloc->end = alloc->start + pipe_size; ++ } + } + +-static unsigned int skl_cursor_allocation(const struct intel_wm_config *config) ++static unsigned int skl_cursor_allocation(int num_active) + { +- if (config->num_pipes_active == 1) ++ if (num_active == 1) + return 32; + + return 8; +@@ -2993,33 +3036,44 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate) + return total_data_rate; + } + +-static void ++static int + skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, + struct skl_ddb_allocation *ddb /* out */) + { ++ struct drm_atomic_state *state = cstate->base.state; + struct drm_crtc *crtc = cstate->base.crtc; + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_wm_config *config = &dev_priv->wm.config; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_plane *intel_plane; ++ struct drm_plane *plane; ++ struct drm_plane_state *pstate; + enum pipe pipe = intel_crtc->pipe; + struct skl_ddb_entry *alloc = &ddb->pipe[pipe]; + uint16_t alloc_size, start, cursor_blocks; + uint16_t *minimum = cstate->wm.skl.minimum_blocks; + uint16_t *y_minimum = cstate->wm.skl.minimum_y_blocks; + unsigned int total_data_rate; ++ int num_active; ++ int id, i; ++ ++ if (!cstate->base.active) { ++ ddb->pipe[pipe].start = ddb->pipe[pipe].end = 0; ++ memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe])); ++ memset(ddb->y_plane[pipe], 0, sizeof(ddb->y_plane[pipe])); ++ return 0; ++ } + +- skl_ddb_get_pipe_allocation_limits(dev, cstate, config, alloc); ++ skl_ddb_get_pipe_allocation_limits(dev, cstate, config, alloc, ++ &num_active); + alloc_size = skl_ddb_entry_size(alloc); + if (alloc_size == 0) { + memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe])); +- memset(&ddb->plane[pipe][PLANE_CURSOR], 0, +- sizeof(ddb->plane[pipe][PLANE_CURSOR])); +- return; ++ return 0; + } + +- cursor_blocks = skl_cursor_allocation(config); ++ cursor_blocks = skl_cursor_allocation(num_active); + ddb->plane[pipe][PLANE_CURSOR].start = alloc->end - cursor_blocks; + ddb->plane[pipe][PLANE_CURSOR].end = alloc->end; + +@@ -3027,21 +3081,55 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, + alloc->end -= cursor_blocks; + + /* 1. Allocate the mininum required blocks for each active plane */ +- for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { +- struct drm_plane *plane = &intel_plane->base; +- struct drm_framebuffer *fb = plane->state->fb; +- int id = skl_wm_plane_id(intel_plane); ++ /* ++ * TODO: Remove support for already-committed state once we ++ * only allocate DDB on in-flight states. ++ */ ++ if (state) { ++ for_each_plane_in_state(state, plane, pstate, i) { ++ intel_plane = to_intel_plane(plane); ++ id = skl_wm_plane_id(intel_plane); + +- if (!to_intel_plane_state(plane->state)->visible) +- continue; ++ if (intel_plane->pipe != pipe) ++ continue; + +- if (plane->type == DRM_PLANE_TYPE_CURSOR) +- continue; ++ if (!to_intel_plane_state(pstate)->visible) { ++ minimum[id] = 0; ++ y_minimum[id] = 0; ++ continue; ++ } ++ if (plane->type == DRM_PLANE_TYPE_CURSOR) { ++ minimum[id] = 0; ++ y_minimum[id] = 0; ++ continue; ++ } + +- minimum[id] = 8; +- alloc_size -= minimum[id]; +- y_minimum[id] = (fb->pixel_format == DRM_FORMAT_NV12) ? 8 : 0; +- alloc_size -= y_minimum[id]; ++ minimum[id] = 8; ++ if (pstate->fb->pixel_format == DRM_FORMAT_NV12) ++ y_minimum[id] = 8; ++ else ++ y_minimum[id] = 0; ++ } ++ } else { ++ for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { ++ struct drm_plane *plane = &intel_plane->base; ++ struct drm_framebuffer *fb = plane->state->fb; ++ int id = skl_wm_plane_id(intel_plane); ++ ++ if (!to_intel_plane_state(plane->state)->visible) ++ continue; ++ ++ if (plane->type == DRM_PLANE_TYPE_CURSOR) ++ continue; ++ ++ minimum[id] = 8; ++ y_minimum[id] = (fb->pixel_format == DRM_FORMAT_NV12) ? 8 : 0; ++ } ++ } ++ ++ for (i = 0; i < PLANE_CURSOR; i++) { ++ alloc_size -= minimum[i]; ++ alloc_size -= y_minimum[i]; + } + + /* +@@ -3052,21 +3140,14 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, + */ + total_data_rate = skl_get_total_relative_data_rate(cstate); + if (total_data_rate == 0) +- return; ++ return 0; + + start = alloc->start; + for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { +- struct drm_plane *plane = &intel_plane->base; +- struct drm_plane_state *pstate = intel_plane->base.state; + unsigned int data_rate, y_data_rate; + uint16_t plane_blocks, y_plane_blocks = 0; + int id = skl_wm_plane_id(intel_plane); + +- if (!to_intel_plane_state(pstate)->visible) +- continue; +- if (plane->type == DRM_PLANE_TYPE_CURSOR) +- continue; +- + data_rate = cstate->wm.skl.plane_data_rate[id]; + + /* +@@ -3078,8 +3159,11 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, + plane_blocks += div_u64((uint64_t)alloc_size * data_rate, + total_data_rate); + +- ddb->plane[pipe][id].start = start; +- ddb->plane[pipe][id].end = start + plane_blocks; ++ /* Leave disabled planes at (0,0) */ ++ if (data_rate) { ++ ddb->plane[pipe][id].start = start; ++ ddb->plane[pipe][id].end = start + plane_blocks; ++ } + + start += plane_blocks; + +@@ -3092,12 +3176,15 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, + y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate, + total_data_rate); + +- ddb->y_plane[pipe][id].start = start; +- ddb->y_plane[pipe][id].end = start + y_plane_blocks; ++ if (y_data_rate) { ++ ddb->y_plane[pipe][id].start = start; ++ ddb->y_plane[pipe][id].end = start + y_plane_blocks; ++ } + + start += y_plane_blocks; + } + ++ return 0; + } + + static uint32_t skl_pipe_pixel_rate(const struct intel_crtc_state *config) +@@ -3588,7 +3675,7 @@ static bool skl_update_pipe_wm(struct drm_crtc *crtc, + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); + +- skl_allocate_pipe_ddb(cstate, ddb); ++ WARN_ON(skl_allocate_pipe_ddb(cstate, ddb) != 0); + skl_build_pipe_wm(cstate, ddb, pipe_wm); + + if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm))) +-- +2.7.4 + diff --git a/0008-drm-i915-Add-distrust_bios_wm-flag-to-dev_priv-v2.patch b/0008-drm-i915-Add-distrust_bios_wm-flag-to-dev_priv-v2.patch new file mode 100644 index 000000000..7a45a28a4 --- /dev/null +++ b/0008-drm-i915-Add-distrust_bios_wm-flag-to-dev_priv-v2.patch @@ -0,0 +1,94 @@ +From 0126336af286ea85c1137ad13882f8c93d74c6c3 Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 12:40:13 +0200 +Subject: [PATCH 08/17] drm/i915: Add distrust_bios_wm flag to dev_priv (v2) + +Upstream: since drm-intel-next-2016-05-22 +commit 279e99d76e6097ee7b531114777fa9b030496d81 + +Author: Matt Roper +AuthorDate: Thu May 12 07:06:02 2016 -0700 +Commit: Matt Roper +CommitDate: Fri May 13 07:33:54 2016 -0700 + + drm/i915: Add distrust_bios_wm flag to dev_priv (v2) + + SKL-style platforms can't fully trust the watermark/DDB settings + programmed by the BIOS and need to do extra sanitization on their first + atomic update. Add a flag to dev_priv that is set during hardware + readout and cleared at the end of the first commit. + + Note that for the somewhat common case where everything is turned off + when the driver starts up, we don't need to bother with a recompute...we + know exactly what the DDB should be (all zero's) so just setup the DDB + directly in that case. + + v2: + - Move clearing of distrust_bios_wm up below the swap_state call since + it's a more natural / self-explanatory location. (Maarten) + - Use dev_priv->active_crtcs to test whether any CRTC's are turned on + during HW WM readout rather than trying to count the active CRTC's + again ourselves. (Maarten) + + Cc: Maarten Lankhorst + Signed-off-by: Matt Roper + Reviewed-by: Maarten Lankhorst + Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-9-git-send-email-matthew.d.roper@intel.com +--- + drivers/gpu/drm/i915/i915_drv.h | 7 +++++++ + drivers/gpu/drm/i915/intel_display.c | 1 + + drivers/gpu/drm/i915/intel_pm.c | 8 ++++++++ + 3 files changed, 16 insertions(+) + +diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h +index 804af6f..ae7932a 100644 +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -1986,6 +1986,13 @@ struct drm_i915_private { + }; + + uint8_t max_level; ++ ++ /* ++ * Set during HW readout of watermarks/DDB. Some platforms ++ * need to know when we're still using BIOS-provided values ++ * (which we don't fully trust). ++ */ ++ bool distrust_bios_wm; + } wm; + + struct i915_runtime_pm pm; +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index f53df81..786f3d9 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -13516,6 +13516,7 @@ static int intel_atomic_commit(struct drm_device *dev, + + drm_atomic_helper_swap_state(dev, state); + dev_priv->wm.config = to_intel_atomic_state(state)->wm_config; ++ dev_priv->wm.distrust_bios_wm = false; + + if (intel_state->modeset) { + memcpy(dev_priv->min_pixclk, intel_state->min_pixclk, +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index ee82b1f..6a09d7a 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -3967,6 +3967,14 @@ void skl_wm_get_hw_state(struct drm_device *dev) + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + skl_pipe_wm_get_hw_state(crtc); + ++ if (dev_priv->active_crtcs) { ++ /* Fully recompute DDB on first atomic commit */ ++ dev_priv->wm.distrust_bios_wm = true; ++ } else { ++ /* Easy/common case; just sanitize DDB now if everything off */ ++ memset(ddb, 0, sizeof(*ddb)); ++ } ++ + /* Calculate plane data rates */ + for_each_intel_crtc(dev, intel_crtc) { + struct intel_crtc_state *cstate = intel_crtc->config; +-- +2.7.4 + diff --git a/0009-drm-i915-gen9-Compute-DDB-allocation-at-atomic-check.patch b/0009-drm-i915-gen9-Compute-DDB-allocation-at-atomic-check.patch new file mode 100644 index 000000000..53fb0cd7a --- /dev/null +++ b/0009-drm-i915-gen9-Compute-DDB-allocation-at-atomic-check.patch @@ -0,0 +1,254 @@ +From 0e9cf00438e4df1d97af44d3c52cc1cacc4dd2c9 Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 12:40:26 +0200 +Subject: [PATCH 09/17] drm/i915/gen9: Compute DDB allocation at atomic check + time (v4) + +Upstream: since drm-intel-next-2016-05-22 +commit 98d39494d3759f84ce50e505059bc80f54c1c47b + +Author: Matt Roper +AuthorDate: Thu May 12 07:06:03 2016 -0700 +Commit: Matt Roper +CommitDate: Fri May 13 07:34:00 2016 -0700 + + drm/i915/gen9: Compute DDB allocation at atomic check time (v4) + + Calculate the DDB blocks needed to satisfy the current atomic + transaction at atomic check time. This is a prerequisite to calculating + SKL watermarks during the 'check' phase and rejecting any configurations + that we can't find valid watermarks for. + + Due to the nature of DDB allocation, it's possible for the addition of a + new CRTC to make the watermark configuration already in use on another, + unchanged CRTC become invalid. A change in which CRTC's are active + triggers a recompute of the entire DDB, which unfortunately means we + need to disallow any other atomic commits from racing with such an + update. If the active CRTC's change, we need to grab the lock on all + CRTC's and run all CRTC's through their 'check' handler to recompute and + re-check their per-CRTC DDB allocations. + + Note that with this patch we only compute the DDB allocation but we + don't actually use the computed values during watermark programming yet. + For ease of review/testing/bisecting, we still recompute the DDB at + watermark programming time and just WARN() if it doesn't match the + precomputed values. A future patch will switch over to using the + precomputed values once we're sure they're being properly computed. + + Another clarifying note: DDB allocation itself shouldn't ever fail with + the algorithm we use today (i.e., we have enough DDB blocks on BXT to + support the minimum needs of the worst-case scenario of every pipe/plane + enabled at full size). However the watermarks calculations based on the + DDB may fail and we'll be moving those to the atomic check as well in + future patches. + + v2: + - Skip DDB calculations in the rare case where our transaction doesn't + actually touch any CRTC's at all. Assuming at least one CRTC state + is present in our transaction, then it means we can't race with any + transactions that would update dev_priv->active_crtcs (which requires + _all_ CRTC locks). + + v3: + - Also calculate DDB during initial hw readout, to prevent using + incorrect bios values. (Maarten) + + v4: + - Use new distrust_bios_wm flag instead of skip_initial_wm (which was + never actually set). + - Set intel_state->active_pipe_changes instead of just realloc_pipes + + Cc: Maarten Lankhorst + Cc: Lyude Paul + Cc: Radhakrishna Sripada + Signed-off-by: Matt Roper + Signed-off-by: Maarten Lankhorst + Reviewed-by: Maarten Lankhorst + Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-10-git-send-email-matthew.d.roper@intel.com +--- + drivers/gpu/drm/i915/i915_drv.h | 5 +++ + drivers/gpu/drm/i915/intel_display.c | 18 ++++++++ + drivers/gpu/drm/i915/intel_drv.h | 3 ++ + drivers/gpu/drm/i915/intel_pm.c | 79 ++++++++++++++++++++++++++++++++++++ + 4 files changed, 105 insertions(+) + +diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h +index ae7932a..237df9f 100644 +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -296,6 +296,10 @@ struct i915_hotplug { + #define for_each_intel_crtc(dev, intel_crtc) \ + list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) + ++#define for_each_intel_crtc_mask(dev, intel_crtc, crtc_mask) \ ++ list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) \ ++ for_each_if ((crtc_mask) & (1 << drm_crtc_index(&intel_crtc->base))) ++ + #define for_each_intel_encoder(dev, intel_encoder) \ + list_for_each_entry(intel_encoder, \ + &(dev)->mode_config.encoder_list, \ +@@ -638,6 +642,7 @@ struct drm_i915_display_funcs { + int (*compute_pipe_wm)(struct intel_crtc *crtc, + struct drm_atomic_state *state); + void (*program_watermarks)(struct intel_crtc_state *cstate); ++ int (*compute_global_watermarks)(struct drm_atomic_state *state); + void (*update_wm)(struct drm_crtc *crtc); + int (*modeset_calc_cdclk)(struct drm_atomic_state *state); + void (*modeset_commit_cdclk)(struct drm_atomic_state *state); +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index 786f3d9..03e2635 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -13225,6 +13225,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state) + static void calc_watermark_data(struct drm_atomic_state *state) + { + struct drm_device *dev = state->dev; ++ struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); + struct drm_crtc *crtc; + struct drm_crtc_state *cstate; +@@ -13254,6 +13255,10 @@ static void calc_watermark_data(struct drm_atomic_state *state) + pstate->crtc_h != pstate->src_h >> 16) + intel_state->wm_config.sprites_scaled = true; + } ++ ++ /* Is there platform-specific watermark information to calculate? */ ++ if (dev_priv->display.compute_global_watermarks) ++ dev_priv->display.compute_global_watermarks(state); + } + + /** +@@ -13616,6 +13621,19 @@ static int intel_atomic_commit(struct drm_device *dev, + modeset_put_power_domains(dev_priv, put_domains[i]); + } + ++ /* ++ * Temporary sanity check: make sure our pre-computed DDB matches the ++ * one we actually wind up programming. ++ * ++ * Not a great place to put this, but the easiest place we have access ++ * to both the pre-computed and final DDB's; we'll be removing this ++ * check in the next patch anyway. ++ */ ++ WARN(IS_GEN9(dev) && ++ memcmp(&intel_state->ddb, &dev_priv->wm.skl_results.ddb, ++ sizeof(intel_state->ddb)), ++ "Pre-computed DDB does not match final DDB!\n"); ++ + if (intel_state->modeset) + intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET); + +diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h +index 672ca56..4d6336a 100644 +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -271,6 +271,9 @@ struct intel_atomic_state { + + struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS]; + struct intel_wm_config wm_config; ++ ++ /* Gen9+ only */ ++ struct skl_ddb_allocation ddb; + }; + + struct intel_plane_state { +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index 6a09d7a..f60519d 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -3751,6 +3751,84 @@ static void skl_clear_wm(struct skl_wm_values *watermarks, enum pipe pipe) + + } + ++static int ++skl_compute_ddb(struct drm_atomic_state *state) ++{ ++ struct drm_device *dev = state->dev; ++ struct drm_i915_private *dev_priv = to_i915(dev); ++ struct intel_atomic_state *intel_state = to_intel_atomic_state(state); ++ struct intel_crtc *intel_crtc; ++ unsigned realloc_pipes = dev_priv->active_crtcs; ++ int ret; ++ ++ /* ++ * If this is our first atomic update following hardware readout, ++ * we can't trust the DDB that the BIOS programmed for us. Let's ++ * pretend that all pipes switched active status so that we'll ++ * ensure a full DDB recompute. ++ */ ++ if (dev_priv->wm.distrust_bios_wm) ++ intel_state->active_pipe_changes = ~0; ++ ++ /* ++ * If the modeset changes which CRTC's are active, we need to ++ * recompute the DDB allocation for *all* active pipes, even ++ * those that weren't otherwise being modified in any way by this ++ * atomic commit. Due to the shrinking of the per-pipe allocations ++ * when new active CRTC's are added, it's possible for a pipe that ++ * we were already using and aren't changing at all here to suddenly ++ * become invalid if its DDB needs exceeds its new allocation. ++ * ++ * Note that if we wind up doing a full DDB recompute, we can't let ++ * any other display updates race with this transaction, so we need ++ * to grab the lock on *all* CRTC's. ++ */ ++ if (intel_state->active_pipe_changes) ++ realloc_pipes = ~0; ++ ++ for_each_intel_crtc_mask(dev, intel_crtc, realloc_pipes) { ++ struct intel_crtc_state *cstate; ++ ++ cstate = intel_atomic_get_crtc_state(state, intel_crtc); ++ if (IS_ERR(cstate)) ++ return PTR_ERR(cstate); ++ ++ ret = skl_allocate_pipe_ddb(cstate, &intel_state->ddb); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int ++skl_compute_wm(struct drm_atomic_state *state) ++{ ++ struct drm_crtc *crtc; ++ struct drm_crtc_state *cstate; ++ int ret, i; ++ bool changed = false; ++ ++ /* ++ * If this transaction isn't actually touching any CRTC's, don't ++ * bother with watermark calculation. Note that if we pass this ++ * test, we're guaranteed to hold at least one CRTC state mutex, ++ * which means we can safely use values like dev_priv->active_crtcs ++ * since any racing commits that want to update them would need to ++ * hold _all_ CRTC state mutexes. ++ */ ++ for_each_crtc_in_state(state, crtc, cstate, i) ++ changed = true; ++ if (!changed) ++ return 0; ++ ++ ret = skl_compute_ddb(state); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ + static void skl_update_wm(struct drm_crtc *crtc) + { + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); +@@ -7258,6 +7336,7 @@ void intel_init_pm(struct drm_device *dev) + dev_priv->display.init_clock_gating = + bxt_init_clock_gating; + dev_priv->display.update_wm = skl_update_wm; ++ dev_priv->display.compute_global_watermarks = skl_compute_wm; + } else if (HAS_PCH_SPLIT(dev)) { + ilk_setup_wm_latency(dev); + +-- +2.7.4 + diff --git a/0010-drm-i915-gen9-Drop-re-allocation-of-DDB-at-atomic-co.patch b/0010-drm-i915-gen9-Drop-re-allocation-of-DDB-at-atomic-co.patch new file mode 100644 index 000000000..4d40a4e93 --- /dev/null +++ b/0010-drm-i915-gen9-Drop-re-allocation-of-DDB-at-atomic-co.patch @@ -0,0 +1,389 @@ +From 6a86f1d01bb25a687c59dd6b3e6deea362cf0ee1 Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 12:40:40 +0200 +Subject: [PATCH 10/17] drm/i915/gen9: Drop re-allocation of DDB at atomic + commit (v2) + +Upstream: since drm-intel-next-2016-05-22 +commit a6d3460e62d17098a815a53f23e44d814cb347e0 + +Author: Matt Roper +AuthorDate: Thu May 12 07:06:04 2016 -0700 +Commit: Matt Roper +CommitDate: Fri May 13 07:34:06 2016 -0700 + + drm/i915/gen9: Drop re-allocation of DDB at atomic commit (v2) + + Now that we're properly pre-allocating the DDB during the atomic check + phase and we trust that the allocation is appropriate, let's actually + use the allocation computed and not duplicate that work during the + commit phase. + + v2: + - Significant rebasing now that we can use cached data rates and + minimum block allocations to avoid grabbing additional plane states. + + Signed-off-by: Matt Roper + Reviewed-by: Maarten Lankhorst + Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-11-git-send-email-matthew.d.roper@intel.com +--- + drivers/gpu/drm/i915/intel_display.c | 14 +-- + drivers/gpu/drm/i915/intel_pm.c | 224 +++++++++++------------------------ + 2 files changed, 67 insertions(+), 171 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index 03e2635..b484fda 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -13522,6 +13522,7 @@ static int intel_atomic_commit(struct drm_device *dev, + drm_atomic_helper_swap_state(dev, state); + dev_priv->wm.config = to_intel_atomic_state(state)->wm_config; + dev_priv->wm.distrust_bios_wm = false; ++ dev_priv->wm.skl_results.ddb = intel_state->ddb; + + if (intel_state->modeset) { + memcpy(dev_priv->min_pixclk, intel_state->min_pixclk, +@@ -13621,19 +13622,6 @@ static int intel_atomic_commit(struct drm_device *dev, + modeset_put_power_domains(dev_priv, put_domains[i]); + } + +- /* +- * Temporary sanity check: make sure our pre-computed DDB matches the +- * one we actually wind up programming. +- * +- * Not a great place to put this, but the easiest place we have access +- * to both the pre-computed and final DDB's; we'll be removing this +- * check in the next patch anyway. +- */ +- WARN(IS_GEN9(dev) && +- memcmp(&intel_state->ddb, &dev_priv->wm.skl_results.ddb, +- sizeof(intel_state->ddb)), +- "Pre-computed DDB does not match final DDB!\n"); +- + if (intel_state->modeset) + intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET); + +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index f60519d..80f9f18 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -2788,7 +2788,6 @@ skl_wm_plane_id(const struct intel_plane *plane) + static void + skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, + const struct intel_crtc_state *cstate, +- struct intel_wm_config *config, + struct skl_ddb_entry *alloc, /* out */ + int *num_active /* out */) + { +@@ -2796,24 +2795,22 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); + struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_crtc *for_crtc = cstate->base.crtc; +- struct drm_crtc *crtc; + unsigned int pipe_size, ddb_size; + int nth_active_pipe; + int pipe = to_intel_crtc(for_crtc)->pipe; + +- if (intel_state && intel_state->active_pipe_changes) +- *num_active = hweight32(intel_state->active_crtcs); +- else if (intel_state) +- *num_active = hweight32(dev_priv->active_crtcs); +- else +- *num_active = config->num_pipes_active; +- +- if (!cstate->base.active) { ++ if (WARN_ON(!state) || !cstate->base.active) { + alloc->start = 0; + alloc->end = 0; ++ *num_active = hweight32(dev_priv->active_crtcs); + return; + } + ++ if (intel_state->active_pipe_changes) ++ *num_active = hweight32(intel_state->active_crtcs); ++ else ++ *num_active = hweight32(dev_priv->active_crtcs); ++ + if (IS_BROXTON(dev)) + ddb_size = BXT_DDB_SIZE; + else +@@ -2822,50 +2819,23 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, + ddb_size -= 4; /* 4 blocks for bypass path allocation */ + + /* +- * FIXME: At the moment we may be called on either in-flight or fully +- * committed cstate's. Once we fully move DDB allocation in the check +- * phase, we'll only be called on in-flight states and the 'else' +- * branch here will go away. +- * +- * The 'else' branch is slightly racy here, but it was racy to begin +- * with; since it's going away soon, no effort is made to address that. ++ * If the state doesn't change the active CRTC's, then there's ++ * no need to recalculate; the existing pipe allocation limits ++ * should remain unchanged. Note that we're safe from racing ++ * commits since any racing commit that changes the active CRTC ++ * list would need to grab _all_ crtc locks, including the one ++ * we currently hold. + */ +- if (state) { +- /* +- * If the state doesn't change the active CRTC's, then there's +- * no need to recalculate; the existing pipe allocation limits +- * should remain unchanged. Note that we're safe from racing +- * commits since any racing commit that changes the active CRTC +- * list would need to grab _all_ crtc locks, including the one +- * we currently hold. +- */ +- if (!intel_state->active_pipe_changes) { +- *alloc = dev_priv->wm.skl_hw.ddb.pipe[pipe]; +- return; +- } +- +- nth_active_pipe = hweight32(intel_state->active_crtcs & +- (drm_crtc_mask(for_crtc) - 1)); +- pipe_size = ddb_size / hweight32(intel_state->active_crtcs); +- alloc->start = nth_active_pipe * ddb_size / *num_active; +- alloc->end = alloc->start + pipe_size; +- } else { +- nth_active_pipe = 0; +- for_each_crtc(dev, crtc) { +- if (!to_intel_crtc(crtc)->active) +- continue; +- +- if (crtc == for_crtc) +- break; +- +- nth_active_pipe++; +- } +- +- pipe_size = ddb_size / config->num_pipes_active; +- alloc->start = nth_active_pipe * ddb_size / +- config->num_pipes_active; +- alloc->end = alloc->start + pipe_size; ++ if (!intel_state->active_pipe_changes) { ++ *alloc = dev_priv->wm.skl_hw.ddb.pipe[pipe]; ++ return; + } ++ ++ nth_active_pipe = hweight32(intel_state->active_crtcs & ++ (drm_crtc_mask(for_crtc) - 1)); ++ pipe_size = ddb_size / hweight32(intel_state->active_crtcs); ++ alloc->start = nth_active_pipe * ddb_size / *num_active; ++ alloc->end = alloc->start + pipe_size; + } + + static unsigned int skl_cursor_allocation(int num_active) +@@ -2964,62 +2934,33 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate) + struct drm_crtc *crtc = cstate->crtc; + struct drm_device *dev = crtc->dev; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); ++ const struct drm_plane *plane; + const struct intel_plane *intel_plane; ++ struct drm_plane_state *pstate; + unsigned int rate, total_data_rate = 0; + int id; ++ int i; ++ ++ if (WARN_ON(!state)) ++ return 0; + + /* Calculate and cache data rate for each plane */ +- /* +- * FIXME: At the moment this function can be called on either an +- * in-flight or a committed state object. If it's in-flight then we +- * only want to re-calculate the plane data rate for planes that are +- * part of the transaction (i.e., we don't want to grab any additional +- * plane states if we don't have to). If we're operating on committed +- * state, we'll just go ahead and recalculate the plane data rate for +- * all planes. +- * +- * Once we finish moving our DDB allocation to the atomic check phase, +- * we'll only be calling this function on in-flight state objects, so +- * the 'else' branch here will go away. +- */ +- if (state) { +- struct drm_plane *plane; +- struct drm_plane_state *pstate; +- int i; +- +- for_each_plane_in_state(state, plane, pstate, i) { +- intel_plane = to_intel_plane(plane); +- id = skl_wm_plane_id(intel_plane); +- +- if (intel_plane->pipe != intel_crtc->pipe) +- continue; +- +- /* packed/uv */ +- rate = skl_plane_relative_data_rate(intel_cstate, +- pstate, 0); +- intel_cstate->wm.skl.plane_data_rate[id] = rate; +- +- /* y-plane */ +- rate = skl_plane_relative_data_rate(intel_cstate, +- pstate, 1); +- intel_cstate->wm.skl.plane_y_data_rate[id] = rate; +- } +- } else { +- for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { +- const struct drm_plane_state *pstate = +- intel_plane->base.state; +- int id = skl_wm_plane_id(intel_plane); ++ for_each_plane_in_state(state, plane, pstate, i) { ++ id = skl_wm_plane_id(to_intel_plane(plane)); ++ intel_plane = to_intel_plane(plane); + +- /* packed/uv */ +- rate = skl_plane_relative_data_rate(intel_cstate, +- pstate, 0); +- intel_cstate->wm.skl.plane_data_rate[id] = rate; ++ if (intel_plane->pipe != intel_crtc->pipe) ++ continue; + +- /* y-plane */ +- rate = skl_plane_relative_data_rate(intel_cstate, +- pstate, 1); +- intel_cstate->wm.skl.plane_y_data_rate[id] = rate; +- } ++ /* packed/uv */ ++ rate = skl_plane_relative_data_rate(intel_cstate, ++ pstate, 0); ++ intel_cstate->wm.skl.plane_data_rate[id] = rate; ++ ++ /* y-plane */ ++ rate = skl_plane_relative_data_rate(intel_cstate, ++ pstate, 1); ++ intel_cstate->wm.skl.plane_y_data_rate[id] = rate; + } + + /* Calculate CRTC's total data rate from cached values */ +@@ -3043,8 +2984,6 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, + struct drm_atomic_state *state = cstate->base.state; + struct drm_crtc *crtc = cstate->base.crtc; + struct drm_device *dev = crtc->dev; +- struct drm_i915_private *dev_priv = to_i915(dev); +- struct intel_wm_config *config = &dev_priv->wm.config; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_plane *intel_plane; + struct drm_plane *plane; +@@ -3058,6 +2997,9 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, + int num_active; + int id, i; + ++ if (WARN_ON(!state)) ++ return 0; ++ + if (!cstate->base.active) { + ddb->pipe[pipe].start = ddb->pipe[pipe].end = 0; + memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe])); +@@ -3065,8 +3007,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, + return 0; + } + +- skl_ddb_get_pipe_allocation_limits(dev, cstate, config, alloc, +- &num_active); ++ skl_ddb_get_pipe_allocation_limits(dev, cstate, alloc, &num_active); + alloc_size = skl_ddb_entry_size(alloc); + if (alloc_size == 0) { + memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe])); +@@ -3078,53 +3019,31 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, + ddb->plane[pipe][PLANE_CURSOR].end = alloc->end; + + alloc_size -= cursor_blocks; +- alloc->end -= cursor_blocks; + + /* 1. Allocate the mininum required blocks for each active plane */ +- /* +- * TODO: Remove support for already-committed state once we +- * only allocate DDB on in-flight states. +- */ +- if (state) { +- for_each_plane_in_state(state, plane, pstate, i) { +- intel_plane = to_intel_plane(plane); +- id = skl_wm_plane_id(intel_plane); +- +- if (intel_plane->pipe != pipe) +- continue; +- +- if (!to_intel_plane_state(pstate)->visible) { +- minimum[id] = 0; +- y_minimum[id] = 0; +- continue; +- } +- if (plane->type == DRM_PLANE_TYPE_CURSOR) { +- minimum[id] = 0; +- y_minimum[id] = 0; +- continue; +- } +- +- minimum[id] = 8; +- if (pstate->fb->pixel_format == DRM_FORMAT_NV12) +- y_minimum[id] = 8; +- else +- y_minimum[id] = 0; +- } +- } else { +- for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { +- struct drm_plane *plane = &intel_plane->base; +- struct drm_framebuffer *fb = plane->state->fb; +- int id = skl_wm_plane_id(intel_plane); +- +- if (!to_intel_plane_state(plane->state)->visible) +- continue; ++ for_each_plane_in_state(state, plane, pstate, i) { ++ intel_plane = to_intel_plane(plane); ++ id = skl_wm_plane_id(intel_plane); + +- if (plane->type == DRM_PLANE_TYPE_CURSOR) +- continue; ++ if (intel_plane->pipe != pipe) ++ continue; + +- minimum[id] = 8; +- y_minimum[id] = (fb->pixel_format == DRM_FORMAT_NV12) ? 8 : 0; ++ if (!to_intel_plane_state(pstate)->visible) { ++ minimum[id] = 0; ++ y_minimum[id] = 0; ++ continue; ++ } ++ if (plane->type == DRM_PLANE_TYPE_CURSOR) { ++ minimum[id] = 0; ++ y_minimum[id] = 0; ++ continue; + } ++ ++ minimum[id] = 8; ++ if (pstate->fb->pixel_format == DRM_FORMAT_NV12) ++ y_minimum[id] = 8; ++ else ++ y_minimum[id] = 0; + } + + for (i = 0; i < PLANE_CURSOR; i++) { +@@ -3675,7 +3594,6 @@ static bool skl_update_pipe_wm(struct drm_crtc *crtc, + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); + +- WARN_ON(skl_allocate_pipe_ddb(cstate, ddb) != 0); + skl_build_pipe_wm(cstate, ddb, pipe_wm); + + if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm))) +@@ -3739,16 +3657,6 @@ static void skl_clear_wm(struct skl_wm_values *watermarks, enum pipe pipe) + memset(watermarks->plane_trans[pipe], + 0, sizeof(uint32_t) * I915_MAX_PLANES); + watermarks->plane_trans[pipe][PLANE_CURSOR] = 0; +- +- /* Clear ddb entries for pipe */ +- memset(&watermarks->ddb.pipe[pipe], 0, sizeof(struct skl_ddb_entry)); +- memset(&watermarks->ddb.plane[pipe], 0, +- sizeof(struct skl_ddb_entry) * I915_MAX_PLANES); +- memset(&watermarks->ddb.y_plane[pipe], 0, +- sizeof(struct skl_ddb_entry) * I915_MAX_PLANES); +- memset(&watermarks->ddb.plane[pipe][PLANE_CURSOR], 0, +- sizeof(struct skl_ddb_entry)); +- + } + + static int +-- +2.7.4 + diff --git a/0011-drm-i915-gen9-Calculate-plane-WM-s-from-state.patch b/0011-drm-i915-gen9-Calculate-plane-WM-s-from-state.patch new file mode 100644 index 000000000..9f839dfa2 --- /dev/null +++ b/0011-drm-i915-gen9-Calculate-plane-WM-s-from-state.patch @@ -0,0 +1,91 @@ +From eacd0ecb98a93e3ff83a4479eadeb9cda05d3579 Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 12:41:01 +0200 +Subject: [PATCH 11/17] drm/i915/gen9: Calculate plane WM's from state + +Upstream: since drm-intel-next-2016-05-22 +commit 33815fa55b31a5de4b197c09926ecab3dfb79732 + +Author: Matt Roper +AuthorDate: Thu May 12 07:06:05 2016 -0700 +Commit: Matt Roper +CommitDate: Fri May 13 07:34:12 2016 -0700 + + drm/i915/gen9: Calculate plane WM's from state + + In a future patch we'll want to calculate plane watermarks for in-flight + atomic state rather than the already-committed state. + + Signed-off-by: Matt Roper + Reviewed-by: Maarten Lankhorst + Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-12-git-send-email-matthew.d.roper@intel.com +--- + drivers/gpu/drm/i915/intel_pm.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index 80f9f18..3164f30 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -3179,16 +3179,14 @@ static bool skl_ddb_allocation_changed(const struct skl_ddb_allocation *new_ddb, + + static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, + struct intel_crtc_state *cstate, +- struct intel_plane *intel_plane, ++ struct intel_plane_state *intel_pstate, + uint16_t ddb_allocation, + int level, + uint16_t *out_blocks, /* out */ + uint8_t *out_lines /* out */) + { +- struct drm_plane *plane = &intel_plane->base; +- struct drm_framebuffer *fb = plane->state->fb; +- struct intel_plane_state *intel_pstate = +- to_intel_plane_state(plane->state); ++ struct drm_plane_state *pstate = &intel_pstate->base; ++ struct drm_framebuffer *fb = pstate->fb; + uint32_t latency = dev_priv->wm.skl_latency[level]; + uint32_t method1, method2; + uint32_t plane_bytes_per_line, plane_blocks_per_line; +@@ -3203,7 +3201,7 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, + width = drm_rect_width(&intel_pstate->src) >> 16; + height = drm_rect_height(&intel_pstate->src) >> 16; + +- if (intel_rotation_90_or_270(plane->state->rotation)) ++ if (intel_rotation_90_or_270(pstate->rotation)) + swap(width, height); + + cpp = drm_format_plane_cpp(fb->pixel_format, 0); +@@ -3223,7 +3221,7 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, + fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { + uint32_t min_scanlines = 4; + uint32_t y_tile_minimum; +- if (intel_rotation_90_or_270(plane->state->rotation)) { ++ if (intel_rotation_90_or_270(pstate->rotation)) { + int cpp = (fb->pixel_format == DRM_FORMAT_NV12) ? + drm_format_plane_cpp(fb->pixel_format, 1) : + drm_format_plane_cpp(fb->pixel_format, 0); +@@ -3277,17 +3275,19 @@ static void skl_compute_wm_level(const struct drm_i915_private *dev_priv, + struct drm_device *dev = dev_priv->dev; + struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); + struct intel_plane *intel_plane; ++ struct intel_plane_state *intel_pstate; + uint16_t ddb_blocks; + enum pipe pipe = intel_crtc->pipe; + + for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { + int i = skl_wm_plane_id(intel_plane); + ++ intel_pstate = to_intel_plane_state(intel_plane->base.state); + ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]); + + result->plane_en[i] = skl_compute_plane_wm(dev_priv, + cstate, +- intel_plane, ++ intel_pstate, + ddb_blocks, + level, + &result->plane_res_b[i], +-- +2.7.4 + diff --git a/0012-drm-i915-gen9-Allow-watermark-calculation-on-in-flig.patch b/0012-drm-i915-gen9-Allow-watermark-calculation-on-in-flig.patch new file mode 100644 index 000000000..d0cb50bac --- /dev/null +++ b/0012-drm-i915-gen9-Allow-watermark-calculation-on-in-flig.patch @@ -0,0 +1,156 @@ +From c3d2591095045a8230361d55fadf15ce5dc9127d Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 12:41:12 +0200 +Subject: [PATCH 12/17] drm/i915/gen9: Allow watermark calculation on in-flight + atomic state (v3) + +Upstream: since drm-intel-next-2016-05-22 +commit f4a967523ec7215a3ec867b7ed2e916bd34840e1 + +Author: Matt Roper +AuthorDate: Thu May 12 07:06:06 2016 -0700 +Commit: Matt Roper +CommitDate: Fri May 13 07:34:23 2016 -0700 + + drm/i915/gen9: Allow watermark calculation on in-flight atomic state (v3) + + In an upcoming patch we'll move this calculation to the atomic 'check' + phase so that the display update can be rejected early if no valid + watermark programming is possible. + + v2: + - Drop intel_pstate_for_cstate_plane() helper and add note about how + the code needs to evolve in the future if we start allowing more than + one pending commit against a CRTC. (Maarten) + + v3: + - Only have skl_compute_wm_level calculate watermarks for enabled + planes; we can just set the other planes on a CRTC to disabled + without having to look at the plane state. This is important because + despite our CRTC lock we can still have racing commits that modify + a disabled plane's property without turning it on. (Maarten) + + Signed-off-by: Matt Roper + Reviewed-by: Maarten Lankhorst + Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-13-git-send-email-matthew.d.roper@intel.com +--- + drivers/gpu/drm/i915/intel_pm.c | 61 ++++++++++++++++++++++++++++++++--------- + 1 file changed, 48 insertions(+), 13 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index 3164f30..cd29ab6 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -3266,23 +3266,56 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, + return true; + } + +-static void skl_compute_wm_level(const struct drm_i915_private *dev_priv, +- struct skl_ddb_allocation *ddb, +- struct intel_crtc_state *cstate, +- int level, +- struct skl_wm_level *result) ++static int ++skl_compute_wm_level(const struct drm_i915_private *dev_priv, ++ struct skl_ddb_allocation *ddb, ++ struct intel_crtc_state *cstate, ++ int level, ++ struct skl_wm_level *result) + { + struct drm_device *dev = dev_priv->dev; ++ struct drm_atomic_state *state = cstate->base.state; + struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); ++ struct drm_plane *plane; + struct intel_plane *intel_plane; + struct intel_plane_state *intel_pstate; + uint16_t ddb_blocks; + enum pipe pipe = intel_crtc->pipe; + +- for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { ++ /* ++ * We'll only calculate watermarks for planes that are actually ++ * enabled, so make sure all other planes are set as disabled. ++ */ ++ memset(result, 0, sizeof(*result)); ++ ++ for_each_intel_plane_mask(dev, intel_plane, cstate->base.plane_mask) { + int i = skl_wm_plane_id(intel_plane); + +- intel_pstate = to_intel_plane_state(intel_plane->base.state); ++ plane = &intel_plane->base; ++ intel_pstate = NULL; ++ if (state) ++ intel_pstate = ++ intel_atomic_get_existing_plane_state(state, ++ intel_plane); ++ ++ /* ++ * Note: If we start supporting multiple pending atomic commits ++ * against the same planes/CRTC's in the future, plane->state ++ * will no longer be the correct pre-state to use for the ++ * calculations here and we'll need to change where we get the ++ * 'unchanged' plane data from. ++ * ++ * For now this is fine because we only allow one queued commit ++ * against a CRTC. Even if the plane isn't modified by this ++ * transaction and we don't have a plane lock, we still have ++ * the CRTC's lock, so we know that no other transactions are ++ * racing with us to update it. ++ */ ++ if (!intel_pstate) ++ intel_pstate = to_intel_plane_state(plane->state); ++ ++ WARN_ON(!intel_pstate->base.fb); ++ + ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]); + + result->plane_en[i] = skl_compute_plane_wm(dev_priv, +@@ -3293,6 +3326,8 @@ static void skl_compute_wm_level(const struct drm_i915_private *dev_priv, + &result->plane_res_b[i], + &result->plane_res_l[i]); + } ++ ++ return 0; + } + + static uint32_t +@@ -3587,14 +3622,14 @@ static void skl_flush_wm_values(struct drm_i915_private *dev_priv, + } + } + +-static bool skl_update_pipe_wm(struct drm_crtc *crtc, ++static bool skl_update_pipe_wm(struct drm_crtc_state *cstate, + struct skl_ddb_allocation *ddb, /* out */ + struct skl_pipe_wm *pipe_wm /* out */) + { +- struct intel_crtc *intel_crtc = to_intel_crtc(crtc); +- struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); ++ struct intel_crtc *intel_crtc = to_intel_crtc(cstate->crtc); ++ struct intel_crtc_state *intel_cstate = to_intel_crtc_state(cstate); + +- skl_build_pipe_wm(cstate, ddb, pipe_wm); ++ skl_build_pipe_wm(intel_cstate, ddb, pipe_wm); + + if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm))) + return false; +@@ -3634,7 +3669,7 @@ static void skl_update_other_pipe_wm(struct drm_device *dev, + if (!intel_crtc->active) + continue; + +- wm_changed = skl_update_pipe_wm(&intel_crtc->base, ++ wm_changed = skl_update_pipe_wm(intel_crtc->base.state, + &r->ddb, &pipe_wm); + + /* +@@ -3752,7 +3787,7 @@ static void skl_update_wm(struct drm_crtc *crtc) + + skl_clear_wm(results, intel_crtc->pipe); + +- if (!skl_update_pipe_wm(crtc, &results->ddb, pipe_wm)) ++ if (!skl_update_pipe_wm(crtc->state, &results->ddb, pipe_wm)) + return; + + skl_compute_wm_results(dev, pipe_wm, results, intel_crtc); +-- +2.7.4 + diff --git a/0013-drm-i915-gen9-Use-a-bitmask-to-track-dirty-pipe-wate.patch b/0013-drm-i915-gen9-Use-a-bitmask-to-track-dirty-pipe-wate.patch new file mode 100644 index 000000000..959860f95 --- /dev/null +++ b/0013-drm-i915-gen9-Use-a-bitmask-to-track-dirty-pipe-wate.patch @@ -0,0 +1,91 @@ +From b43247a865f73fa3b73a878236b5055bfb864169 Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 12:41:23 +0200 +Subject: [PATCH 13/17] drm/i915/gen9: Use a bitmask to track dirty pipe + watermarks + +Upstream: since drm-intel-next-2016-05-22 +commit 2b4b9f35d94b1b533bc23110b040b04316480b28 + +Author: Matt Roper +AuthorDate: Thu May 12 07:06:07 2016 -0700 +Commit: Matt Roper +CommitDate: Fri May 13 07:34:40 2016 -0700 + + drm/i915/gen9: Use a bitmask to track dirty pipe watermarks + + Slightly easier to work with than an array of bools. + + Signed-off-by: Matt Roper + Reviewed-by: Maarten Lankhorst + Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-14-git-send-email-matthew.d.roper@intel.com +--- + drivers/gpu/drm/i915/i915_drv.h | 2 +- + drivers/gpu/drm/i915/intel_pm.c | 10 +++++----- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h +index 237df9f..67c76b6 100644 +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -1615,7 +1615,7 @@ struct skl_ddb_allocation { + }; + + struct skl_wm_values { +- bool dirty[I915_MAX_PIPES]; ++ unsigned dirty_pipes; + struct skl_ddb_allocation ddb; + uint32_t wm_linetime[I915_MAX_PIPES]; + uint32_t plane[I915_MAX_PIPES][I915_MAX_PLANES][8]; +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index cd29ab6..611c5a1 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -3455,7 +3455,7 @@ static void skl_write_wm_values(struct drm_i915_private *dev_priv, + int i, level, max_level = ilk_wm_max_level(dev); + enum pipe pipe = crtc->pipe; + +- if (!new->dirty[pipe]) ++ if ((new->dirty_pipes & drm_crtc_mask(&crtc->base)) == 0) + continue; + + I915_WRITE(PIPE_WM_LINETIME(pipe), new->wm_linetime[pipe]); +@@ -3680,7 +3680,7 @@ static void skl_update_other_pipe_wm(struct drm_device *dev, + WARN_ON(!wm_changed); + + skl_compute_wm_results(dev, &pipe_wm, r, intel_crtc); +- r->dirty[intel_crtc->pipe] = true; ++ r->dirty_pipes |= drm_crtc_mask(&intel_crtc->base); + } + } + +@@ -3783,7 +3783,7 @@ static void skl_update_wm(struct drm_crtc *crtc) + + + /* Clear all dirty flags */ +- memset(results->dirty, 0, sizeof(bool) * I915_MAX_PIPES); ++ results->dirty_pipes = 0; + + skl_clear_wm(results, intel_crtc->pipe); + +@@ -3791,7 +3791,7 @@ static void skl_update_wm(struct drm_crtc *crtc) + return; + + skl_compute_wm_results(dev, pipe_wm, results, intel_crtc); +- results->dirty[intel_crtc->pipe] = true; ++ results->dirty_pipes |= drm_crtc_mask(&intel_crtc->base); + + skl_update_other_pipe_wm(dev, crtc, results); + skl_write_wm_values(dev_priv, results); +@@ -3952,7 +3952,7 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc) + if (!intel_crtc->active) + return; + +- hw->dirty[pipe] = true; ++ hw->dirty_pipes |= drm_crtc_mask(crtc); + + active->linetime = hw->wm_linetime[pipe]; + +-- +2.7.4 + diff --git a/0014-drm-i915-gen9-Propagate-watermark-calculation-failur.patch b/0014-drm-i915-gen9-Propagate-watermark-calculation-failur.patch new file mode 100644 index 000000000..a868ebd1f --- /dev/null +++ b/0014-drm-i915-gen9-Propagate-watermark-calculation-failur.patch @@ -0,0 +1,254 @@ +From 2dda82bdd570042820241e71c02ea36081835f67 Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 12:41:35 +0200 +Subject: [PATCH 14/17] drm/i915/gen9: Propagate watermark calculation failures + up the call chain + +Upstream: since drm-intel-next-2016-05-22 +commit 55994c2c38a1101f84cdf277b228f830af8a9c1b + +Author: Matt Roper +AuthorDate: Thu May 12 07:06:08 2016 -0700 +Commit: Matt Roper +CommitDate: Fri May 13 07:34:48 2016 -0700 + + drm/i915/gen9: Propagate watermark calculation failures up the call chain + + Once we move watermark calculation to the atomic check phase, we'll want + to start rejecting display configurations that exceed out watermark + limits. At the moment we just assume that there's always a valid set of + watermarks, even though this may not actually be true. Let's prepare by + passing return codes up through the call stack in preparation. + + Signed-off-by: Matt Roper + Reviewed-by: Maarten Lankhorst + Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-15-git-send-email-matthew.d.roper@intel.com +--- + drivers/gpu/drm/i915/intel_display.c | 10 ++-- + drivers/gpu/drm/i915/intel_pm.c | 90 ++++++++++++++++++++++-------------- + 2 files changed, 61 insertions(+), 39 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index b484fda..9ac2346 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -13222,7 +13222,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state) + * phase. The code here should be run after the per-crtc and per-plane 'check' + * handlers to ensure that all derived state has been updated. + */ +-static void calc_watermark_data(struct drm_atomic_state *state) ++static int calc_watermark_data(struct drm_atomic_state *state) + { + struct drm_device *dev = state->dev; + struct drm_i915_private *dev_priv = to_i915(dev); +@@ -13258,7 +13258,9 @@ static void calc_watermark_data(struct drm_atomic_state *state) + + /* Is there platform-specific watermark information to calculate? */ + if (dev_priv->display.compute_global_watermarks) +- dev_priv->display.compute_global_watermarks(state); ++ return dev_priv->display.compute_global_watermarks(state); ++ ++ return 0; + } + + /** +@@ -13345,9 +13347,7 @@ static int intel_atomic_check(struct drm_device *dev, + return ret; + + intel_fbc_choose_crtc(dev_priv, state); +- calc_watermark_data(state); +- +- return 0; ++ return calc_watermark_data(state); + } + + static int intel_atomic_prepare_commit(struct drm_device *dev, +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index 611c5a1..ec22d93 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -3177,13 +3177,14 @@ static bool skl_ddb_allocation_changed(const struct skl_ddb_allocation *new_ddb, + return false; + } + +-static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, +- struct intel_crtc_state *cstate, +- struct intel_plane_state *intel_pstate, +- uint16_t ddb_allocation, +- int level, +- uint16_t *out_blocks, /* out */ +- uint8_t *out_lines /* out */) ++static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, ++ struct intel_crtc_state *cstate, ++ struct intel_plane_state *intel_pstate, ++ uint16_t ddb_allocation, ++ int level, ++ uint16_t *out_blocks, /* out */ ++ uint8_t *out_lines, /* out */ ++ bool *enabled /* out */) + { + struct drm_plane_state *pstate = &intel_pstate->base; + struct drm_framebuffer *fb = pstate->fb; +@@ -3195,8 +3196,10 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, + uint8_t cpp; + uint32_t width = 0, height = 0; + +- if (latency == 0 || !cstate->base.active || !intel_pstate->visible) +- return false; ++ if (latency == 0 || !cstate->base.active || !intel_pstate->visible) { ++ *enabled = false; ++ return 0; ++ } + + width = drm_rect_width(&intel_pstate->src) >> 16; + height = drm_rect_height(&intel_pstate->src) >> 16; +@@ -3257,13 +3260,16 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, + res_blocks++; + } + +- if (res_blocks >= ddb_allocation || res_lines > 31) +- return false; ++ if (res_blocks >= ddb_allocation || res_lines > 31) { ++ *enabled = false; ++ return 0; ++ } + + *out_blocks = res_blocks; + *out_lines = res_lines; ++ *enabled = true; + +- return true; ++ return 0; + } + + static int +@@ -3281,6 +3287,7 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv, + struct intel_plane_state *intel_pstate; + uint16_t ddb_blocks; + enum pipe pipe = intel_crtc->pipe; ++ int ret; + + /* + * We'll only calculate watermarks for planes that are actually +@@ -3318,13 +3325,16 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv, + + ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]); + +- result->plane_en[i] = skl_compute_plane_wm(dev_priv, +- cstate, +- intel_pstate, +- ddb_blocks, +- level, +- &result->plane_res_b[i], +- &result->plane_res_l[i]); ++ ret = skl_compute_plane_wm(dev_priv, ++ cstate, ++ intel_pstate, ++ ddb_blocks, ++ level, ++ &result->plane_res_b[i], ++ &result->plane_res_l[i], ++ &result->plane_en[i]); ++ if (ret) ++ return ret; + } + + return 0; +@@ -3361,21 +3371,26 @@ static void skl_compute_transition_wm(struct intel_crtc_state *cstate, + } + } + +-static void skl_build_pipe_wm(struct intel_crtc_state *cstate, +- struct skl_ddb_allocation *ddb, +- struct skl_pipe_wm *pipe_wm) ++static int skl_build_pipe_wm(struct intel_crtc_state *cstate, ++ struct skl_ddb_allocation *ddb, ++ struct skl_pipe_wm *pipe_wm) + { + struct drm_device *dev = cstate->base.crtc->dev; + const struct drm_i915_private *dev_priv = dev->dev_private; + int level, max_level = ilk_wm_max_level(dev); ++ int ret; + + for (level = 0; level <= max_level; level++) { +- skl_compute_wm_level(dev_priv, ddb, cstate, +- level, &pipe_wm->wm[level]); ++ ret = skl_compute_wm_level(dev_priv, ddb, cstate, ++ level, &pipe_wm->wm[level]); ++ if (ret) ++ return ret; + } + pipe_wm->linetime = skl_compute_linetime_wm(cstate); + + skl_compute_transition_wm(cstate, &pipe_wm->trans_wm); ++ ++ return 0; + } + + static void skl_compute_wm_results(struct drm_device *dev, +@@ -3622,21 +3637,27 @@ static void skl_flush_wm_values(struct drm_i915_private *dev_priv, + } + } + +-static bool skl_update_pipe_wm(struct drm_crtc_state *cstate, +- struct skl_ddb_allocation *ddb, /* out */ +- struct skl_pipe_wm *pipe_wm /* out */) ++static int skl_update_pipe_wm(struct drm_crtc_state *cstate, ++ struct skl_ddb_allocation *ddb, /* out */ ++ struct skl_pipe_wm *pipe_wm, /* out */ ++ bool *changed /* out */) + { + struct intel_crtc *intel_crtc = to_intel_crtc(cstate->crtc); + struct intel_crtc_state *intel_cstate = to_intel_crtc_state(cstate); ++ int ret; + +- skl_build_pipe_wm(intel_cstate, ddb, pipe_wm); ++ ret = skl_build_pipe_wm(intel_cstate, ddb, pipe_wm); ++ if (ret) ++ return ret; + + if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm))) +- return false; ++ *changed = false; ++ else ++ *changed = true; + + intel_crtc->wm.active.skl = *pipe_wm; + +- return true; ++ return 0; + } + + static void skl_update_other_pipe_wm(struct drm_device *dev, +@@ -3669,8 +3690,8 @@ static void skl_update_other_pipe_wm(struct drm_device *dev, + if (!intel_crtc->active) + continue; + +- wm_changed = skl_update_pipe_wm(intel_crtc->base.state, +- &r->ddb, &pipe_wm); ++ skl_update_pipe_wm(intel_crtc->base.state, ++ &r->ddb, &pipe_wm, &wm_changed); + + /* + * If we end up re-computing the other pipe WM values, it's +@@ -3780,14 +3801,15 @@ static void skl_update_wm(struct drm_crtc *crtc) + struct skl_wm_values *results = &dev_priv->wm.skl_results; + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); + struct skl_pipe_wm *pipe_wm = &cstate->wm.skl.optimal; +- ++ bool wm_changed; + + /* Clear all dirty flags */ + results->dirty_pipes = 0; + + skl_clear_wm(results, intel_crtc->pipe); + +- if (!skl_update_pipe_wm(crtc->state, &results->ddb, pipe_wm)) ++ skl_update_pipe_wm(crtc->state, &results->ddb, pipe_wm, &wm_changed); ++ if (!wm_changed) + return; + + skl_compute_wm_results(dev, pipe_wm, results, intel_crtc); +-- +2.7.4 + diff --git a/0015-drm-i915-gen9-Calculate-watermarks-during-atomic-che.patch b/0015-drm-i915-gen9-Calculate-watermarks-during-atomic-che.patch new file mode 100644 index 000000000..b8f602e0e --- /dev/null +++ b/0015-drm-i915-gen9-Calculate-watermarks-during-atomic-che.patch @@ -0,0 +1,321 @@ +From 71136125cc79dab464a0139dbf0c02891aa9ce6e Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 12:41:46 +0200 +Subject: [PATCH 15/17] drm/i915/gen9: Calculate watermarks during atomic + 'check' (v2) + +Upstream: since drm-intel-next-2016-05-22 +commit 734fa01f3a17ac80d2d53cee0b05b246c03df0e4 + +Author: Matt Roper +AuthorDate: Thu May 12 15:11:40 2016 -0700 +Commit: Matt Roper +CommitDate: Fri May 13 07:35:48 2016 -0700 + + drm/i915/gen9: Calculate watermarks during atomic 'check' (v2) + + Moving watermark calculation into the check phase will allow us to to + reject display configurations for which there are no valid watermark + values before we start trying to program the hardware (although those + tests will come in a subsequent patch). + + Another advantage of moving this calculation to the check phase is that + we can calculate the watermarks in a single shot as part of the atomic + transaction. The watermark interfaces we inherited from our legacy + modesetting days are a bit broken in the atomic design because they use + per-crtc entry points but actually re-calculate and re-program something + that is really more of a global state. That worked okay in the legacy + modesetting world because operations only ever updated a single CRTC at + a time. However in the atomic world, a transaction can involve multiple + CRTC's, which means we wind up computing and programming the watermarks + NxN times (where N is the number of CRTC's involved). With this patch + we eliminate the redundant re-calculation of watermark data for atomic + states (which was the cause of the WARN_ON(!wm_changed) problems that + have plagued us for a while). + + We still need to work on the 'commit' side of watermark handling so that + we aren't doing redundant NxN programming of watermarks, but that's + content for future patches. + + v2: + - Bail out of skl_write_wm_values() if the CRTC isn't active. Now that + we set dirty_pipes to ~0 if the active pipes change (because + we need to deal with DDB changes), we can now wind up here for + disabled pipes, whereas we couldn't before. + + Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=89055 + Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92181 + Cc: Maarten Lankhorst + Signed-off-by: Matt Roper + Tested-by: Daniel Stone + Reviewed-by: Maarten Lankhorst + Link: http://patchwork.freedesktop.org/patch/msgid/1463091100-13747-1-git-send-email-matthew.d.roper@intel.com +--- + drivers/gpu/drm/i915/intel_display.c | 2 +- + drivers/gpu/drm/i915/intel_drv.h | 14 +++- + drivers/gpu/drm/i915/intel_pm.c | 135 ++++++++++++----------------------- + 3 files changed, 61 insertions(+), 90 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index 9ac2346..1726ea4 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -13522,7 +13522,7 @@ static int intel_atomic_commit(struct drm_device *dev, + drm_atomic_helper_swap_state(dev, state); + dev_priv->wm.config = to_intel_atomic_state(state)->wm_config; + dev_priv->wm.distrust_bios_wm = false; +- dev_priv->wm.skl_results.ddb = intel_state->ddb; ++ dev_priv->wm.skl_results = intel_state->wm_results; + + if (intel_state->modeset) { + memcpy(dev_priv->min_pixclk, intel_state->min_pixclk, +diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h +index 4d6336a..e5543b8 100644 +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -273,7 +273,7 @@ struct intel_atomic_state { + struct intel_wm_config wm_config; + + /* Gen9+ only */ +- struct skl_ddb_allocation ddb; ++ struct skl_wm_values wm_results; + }; + + struct intel_plane_state { +@@ -1661,6 +1661,18 @@ intel_atomic_get_crtc_state(struct drm_atomic_state *state, + + return to_intel_crtc_state(crtc_state); + } ++ ++static inline struct intel_plane_state * ++intel_atomic_get_existing_plane_state(struct drm_atomic_state *state, ++ struct intel_plane *plane) ++{ ++ struct drm_plane_state *plane_state; ++ ++ plane_state = drm_atomic_get_existing_plane_state(state, &plane->base); ++ ++ return to_intel_plane_state(plane_state); ++} ++ + int intel_atomic_setup_scalers(struct drm_device *dev, + struct intel_crtc *intel_crtc, + struct intel_crtc_state *crtc_state); +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index ec22d93..73e5242 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -3160,23 +3160,6 @@ static uint32_t skl_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal, + return ret; + } + +-static bool skl_ddb_allocation_changed(const struct skl_ddb_allocation *new_ddb, +- const struct intel_crtc *intel_crtc) +-{ +- struct drm_device *dev = intel_crtc->base.dev; +- struct drm_i915_private *dev_priv = dev->dev_private; +- const struct skl_ddb_allocation *cur_ddb = &dev_priv->wm.skl_hw.ddb; +- +- /* +- * If ddb allocation of pipes changed, it may require recalculation of +- * watermarks +- */ +- if (memcmp(new_ddb->pipe, cur_ddb->pipe, sizeof(new_ddb->pipe))) +- return true; +- +- return false; +-} +- + static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, + struct intel_crtc_state *cstate, + struct intel_plane_state *intel_pstate, +@@ -3472,6 +3455,8 @@ static void skl_write_wm_values(struct drm_i915_private *dev_priv, + + if ((new->dirty_pipes & drm_crtc_mask(&crtc->base)) == 0) + continue; ++ if (!crtc->active) ++ continue; + + I915_WRITE(PIPE_WM_LINETIME(pipe), new->wm_linetime[pipe]); + +@@ -3655,66 +3640,9 @@ static int skl_update_pipe_wm(struct drm_crtc_state *cstate, + else + *changed = true; + +- intel_crtc->wm.active.skl = *pipe_wm; +- + return 0; + } + +-static void skl_update_other_pipe_wm(struct drm_device *dev, +- struct drm_crtc *crtc, +- struct skl_wm_values *r) +-{ +- struct intel_crtc *intel_crtc; +- struct intel_crtc *this_crtc = to_intel_crtc(crtc); +- +- /* +- * If the WM update hasn't changed the allocation for this_crtc (the +- * crtc we are currently computing the new WM values for), other +- * enabled crtcs will keep the same allocation and we don't need to +- * recompute anything for them. +- */ +- if (!skl_ddb_allocation_changed(&r->ddb, this_crtc)) +- return; +- +- /* +- * Otherwise, because of this_crtc being freshly enabled/disabled, the +- * other active pipes need new DDB allocation and WM values. +- */ +- for_each_intel_crtc(dev, intel_crtc) { +- struct skl_pipe_wm pipe_wm = {}; +- bool wm_changed; +- +- if (this_crtc->pipe == intel_crtc->pipe) +- continue; +- +- if (!intel_crtc->active) +- continue; +- +- skl_update_pipe_wm(intel_crtc->base.state, +- &r->ddb, &pipe_wm, &wm_changed); +- +- /* +- * If we end up re-computing the other pipe WM values, it's +- * because it was really needed, so we expect the WM values to +- * be different. +- */ +- WARN_ON(!wm_changed); +- +- skl_compute_wm_results(dev, &pipe_wm, r, intel_crtc); +- r->dirty_pipes |= drm_crtc_mask(&intel_crtc->base); +- } +-} +- +-static void skl_clear_wm(struct skl_wm_values *watermarks, enum pipe pipe) +-{ +- watermarks->wm_linetime[pipe] = 0; +- memset(watermarks->plane[pipe], 0, +- sizeof(uint32_t) * 8 * I915_MAX_PLANES); +- memset(watermarks->plane_trans[pipe], +- 0, sizeof(uint32_t) * I915_MAX_PLANES); +- watermarks->plane_trans[pipe][PLANE_CURSOR] = 0; +-} +- + static int + skl_compute_ddb(struct drm_atomic_state *state) + { +@@ -3722,6 +3650,7 @@ skl_compute_ddb(struct drm_atomic_state *state) + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); + struct intel_crtc *intel_crtc; ++ struct skl_ddb_allocation *ddb = &intel_state->wm_results.ddb; + unsigned realloc_pipes = dev_priv->active_crtcs; + int ret; + +@@ -3747,8 +3676,10 @@ skl_compute_ddb(struct drm_atomic_state *state) + * any other display updates race with this transaction, so we need + * to grab the lock on *all* CRTC's. + */ +- if (intel_state->active_pipe_changes) ++ if (intel_state->active_pipe_changes) { + realloc_pipes = ~0; ++ intel_state->wm_results.dirty_pipes = ~0; ++ } + + for_each_intel_crtc_mask(dev, intel_crtc, realloc_pipes) { + struct intel_crtc_state *cstate; +@@ -3757,7 +3688,7 @@ skl_compute_ddb(struct drm_atomic_state *state) + if (IS_ERR(cstate)) + return PTR_ERR(cstate); + +- ret = skl_allocate_pipe_ddb(cstate, &intel_state->ddb); ++ ret = skl_allocate_pipe_ddb(cstate, ddb); + if (ret) + return ret; + } +@@ -3770,8 +3701,11 @@ skl_compute_wm(struct drm_atomic_state *state) + { + struct drm_crtc *crtc; + struct drm_crtc_state *cstate; +- int ret, i; ++ struct intel_atomic_state *intel_state = to_intel_atomic_state(state); ++ struct skl_wm_values *results = &intel_state->wm_results; ++ struct skl_pipe_wm *pipe_wm; + bool changed = false; ++ int ret, i; + + /* + * If this transaction isn't actually touching any CRTC's, don't +@@ -3786,10 +3720,44 @@ skl_compute_wm(struct drm_atomic_state *state) + if (!changed) + return 0; + ++ /* Clear all dirty flags */ ++ results->dirty_pipes = 0; ++ + ret = skl_compute_ddb(state); + if (ret) + return ret; + ++ /* ++ * Calculate WM's for all pipes that are part of this transaction. ++ * Note that the DDB allocation above may have added more CRTC's that ++ * weren't otherwise being modified (and set bits in dirty_pipes) if ++ * pipe allocations had to change. ++ * ++ * FIXME: Now that we're doing this in the atomic check phase, we ++ * should allow skl_update_pipe_wm() to return failure in cases where ++ * no suitable watermark values can be found. ++ */ ++ for_each_crtc_in_state(state, crtc, cstate, i) { ++ struct intel_crtc *intel_crtc = to_intel_crtc(crtc); ++ struct intel_crtc_state *intel_cstate = ++ to_intel_crtc_state(cstate); ++ ++ pipe_wm = &intel_cstate->wm.skl.optimal; ++ ret = skl_update_pipe_wm(cstate, &results->ddb, pipe_wm, ++ &changed); ++ if (ret) ++ return ret; ++ ++ if (changed) ++ results->dirty_pipes |= drm_crtc_mask(crtc); ++ ++ if ((results->dirty_pipes & drm_crtc_mask(crtc)) == 0) ++ /* This pipe's WM's did not change */ ++ continue; ++ ++ skl_compute_wm_results(crtc->dev, pipe_wm, results, intel_crtc); ++ } ++ + return 0; + } + +@@ -3801,21 +3769,12 @@ static void skl_update_wm(struct drm_crtc *crtc) + struct skl_wm_values *results = &dev_priv->wm.skl_results; + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); + struct skl_pipe_wm *pipe_wm = &cstate->wm.skl.optimal; +- bool wm_changed; + +- /* Clear all dirty flags */ +- results->dirty_pipes = 0; +- +- skl_clear_wm(results, intel_crtc->pipe); +- +- skl_update_pipe_wm(crtc->state, &results->ddb, pipe_wm, &wm_changed); +- if (!wm_changed) ++ if ((results->dirty_pipes & drm_crtc_mask(crtc)) == 0) + return; + +- skl_compute_wm_results(dev, pipe_wm, results, intel_crtc); +- results->dirty_pipes |= drm_crtc_mask(&intel_crtc->base); ++ intel_crtc->wm.active.skl = *pipe_wm; + +- skl_update_other_pipe_wm(dev, crtc, results); + skl_write_wm_values(dev_priv, results); + skl_flush_wm_values(dev_priv, results); + +-- +2.7.4 + diff --git a/0016-drm-i915-gen9-Reject-display-updates-that-exceed-wm-.patch b/0016-drm-i915-gen9-Reject-display-updates-that-exceed-wm-.patch new file mode 100644 index 000000000..fb59572bd --- /dev/null +++ b/0016-drm-i915-gen9-Reject-display-updates-that-exceed-wm-.patch @@ -0,0 +1,63 @@ +From 7731c187f1f77501b7dddf419a06c1b42b0f1388 Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 12:42:00 +0200 +Subject: [PATCH 16/17] drm/i915/gen9: Reject display updates that exceed wm + limitations (v2) + +Upstream: since drm-intel-next-2016-05-22 +commit 6b6bada7d476b586d85b1f9df43125804877e09f + +Author: Matt Roper +AuthorDate: Thu May 12 07:06:10 2016 -0700 +Commit: Matt Roper +CommitDate: Fri May 13 07:36:04 2016 -0700 + + drm/i915/gen9: Reject display updates that exceed wm limitations (v2) + + If we can't find any valid level 0 watermark values for the requested + atomic transaction, reject the configuration before we try to start + programming the hardware. + + v2: + - Add extra debugging output when we reject level 0 watermarks so that + we can more easily debug how/why they were rejected. + + Cc: Lyude Paul + Signed-off-by: Matt Roper + Reviewed-by: Maarten Lankhorst + Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-17-git-send-email-matthew.d.roper@intel.com +--- + drivers/gpu/drm/i915/intel_pm.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index 73e5242..70dcd2e 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -3245,7 +3245,22 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, + + if (res_blocks >= ddb_allocation || res_lines > 31) { + *enabled = false; +- return 0; ++ ++ /* ++ * If there are no valid level 0 watermarks, then we can't ++ * support this display configuration. ++ */ ++ if (level) { ++ return 0; ++ } else { ++ DRM_DEBUG_KMS("Requested display configuration exceeds system watermark limitations\n"); ++ DRM_DEBUG_KMS("Plane %d.%d: blocks required = %u/%u, lines required = %u/31\n", ++ to_intel_crtc(cstate->base.crtc)->pipe, ++ skl_wm_plane_id(to_intel_plane(pstate->plane)), ++ res_blocks, ddb_allocation, res_lines); ++ ++ return -EINVAL; ++ } + } + + *out_blocks = res_blocks; +-- +2.7.4 + diff --git a/0017-drm-i915-Remove-wm_config-from-dev_priv-intel_atomic.patch b/0017-drm-i915-Remove-wm_config-from-dev_priv-intel_atomic.patch new file mode 100644 index 000000000..e47725c25 --- /dev/null +++ b/0017-drm-i915-Remove-wm_config-from-dev_priv-intel_atomic.patch @@ -0,0 +1,115 @@ +From ebe515b1696401259781bc183e211a81287242f6 Mon Sep 17 00:00:00 2001 +From: Fedora Kernel Team +Date: Mon, 20 Jun 2016 12:42:13 +0200 +Subject: [PATCH 17/17] drm/i915: Remove wm_config from + dev_priv/intel_atomic_state + +Upstream: since drm-intel-next-2016-05-22 +commit 5b483747a92570176259bb896dcf2468291f3e42 + +Author: Matt Roper +AuthorDate: Thu May 12 07:06:11 2016 -0700 +Commit: Matt Roper +CommitDate: Fri May 13 07:36:05 2016 -0700 + + drm/i915: Remove wm_config from dev_priv/intel_atomic_state + + We calculate the watermark config into intel_atomic_state and then save + it into dev_priv, but never actually use it from there. This is + left-over from some early ILK-style watermark programming designs that + got changed over time. + + Signed-off-by: Matt Roper + Reviewed-by: Maarten Lankhorst + Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-18-git-send-email-matthew.d.roper@intel.com +--- + drivers/gpu/drm/i915/i915_drv.h | 3 --- + drivers/gpu/drm/i915/intel_display.c | 31 ------------------------------- + drivers/gpu/drm/i915/intel_drv.h | 1 - + 3 files changed, 35 deletions(-) + +diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h +index 67c76b6..59092cb 100644 +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -1973,9 +1973,6 @@ struct drm_i915_private { + */ + uint16_t skl_latency[8]; + +- /* Committed wm config */ +- struct intel_wm_config config; +- + /* + * The skl_wm_values structure is a bit too big for stack + * allocation, so we keep the staging struct where we store +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index 1726ea4..f5eefb1 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -13226,35 +13226,6 @@ static int calc_watermark_data(struct drm_atomic_state *state) + { + struct drm_device *dev = state->dev; + struct drm_i915_private *dev_priv = to_i915(dev); +- struct intel_atomic_state *intel_state = to_intel_atomic_state(state); +- struct drm_crtc *crtc; +- struct drm_crtc_state *cstate; +- struct drm_plane *plane; +- struct drm_plane_state *pstate; +- +- /* +- * Calculate watermark configuration details now that derived +- * plane/crtc state is all properly updated. +- */ +- drm_for_each_crtc(crtc, dev) { +- cstate = drm_atomic_get_existing_crtc_state(state, crtc) ?: +- crtc->state; +- +- if (cstate->active) +- intel_state->wm_config.num_pipes_active++; +- } +- drm_for_each_legacy_plane(plane, dev) { +- pstate = drm_atomic_get_existing_plane_state(state, plane) ?: +- plane->state; +- +- if (!to_intel_plane_state(pstate)->visible) +- continue; +- +- intel_state->wm_config.sprites_enabled = true; +- if (pstate->crtc_w != pstate->src_w >> 16 || +- pstate->crtc_h != pstate->src_h >> 16) +- intel_state->wm_config.sprites_scaled = true; +- } + + /* Is there platform-specific watermark information to calculate? */ + if (dev_priv->display.compute_global_watermarks) +@@ -13520,7 +13491,6 @@ static int intel_atomic_commit(struct drm_device *dev, + } + + drm_atomic_helper_swap_state(dev, state); +- dev_priv->wm.config = to_intel_atomic_state(state)->wm_config; + dev_priv->wm.distrust_bios_wm = false; + dev_priv->wm.skl_results = intel_state->wm_results; + +@@ -15334,7 +15304,6 @@ retry: + } + + /* Write calculated watermark values back */ +- to_i915(dev)->wm.config = to_intel_atomic_state(state)->wm_config; + for_each_crtc_in_state(state, crtc, cstate, i) { + struct intel_crtc_state *cs = to_intel_crtc_state(cstate); + +diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h +index e5543b8..148f79d 100644 +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -270,7 +270,6 @@ struct intel_atomic_state { + unsigned int min_pixclk[I915_MAX_PIPES]; + + struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS]; +- struct intel_wm_config wm_config; + + /* Gen9+ only */ + struct skl_wm_values wm_results; +-- +2.7.4 + diff --git a/kernel.spec b/kernel.spec index 637780ff3..9f2d141ea 100644 --- a/kernel.spec +++ b/kernel.spec @@ -639,6 +639,33 @@ Patch727: KEYS-potential-uninitialized-variable.patch #rhbz 1338025 Patch728: hp-wmi-fix-wifi-cannot-be-hard-unblock.patch +#skl_update_other_pipe_wm issue patch-series from drm-next, rhbz 1305038 +Patch801: 0001-drm-i915-Reorganize-WM-structs-unions-in-CRTC-state.patch +Patch802: 0002-drm-i915-Rename-s-skl_compute_pipe_wm-skl_build_pipe.patch +Patch803: 0003-drm-i915-gen9-Cache-plane-data-rates-in-CRTC-state.patch +Patch804: 0004-drm-i915-gen9-Allow-calculation-of-data-rate-for-in-.patch +Patch805: 0005-drm-i915-gen9-Store-plane-minimum-blocks-in-CRTC-wm-.patch +Patch806: 0006-drm-i915-Track-whether-an-atomic-transaction-changes.patch +Patch807: 0007-drm-i915-gen9-Allow-skl_allocate_pipe_ddb-to-operate.patch +Patch808: 0008-drm-i915-Add-distrust_bios_wm-flag-to-dev_priv-v2.patch +Patch809: 0009-drm-i915-gen9-Compute-DDB-allocation-at-atomic-check.patch +Patch810: 0010-drm-i915-gen9-Drop-re-allocation-of-DDB-at-atomic-co.patch +Patch811: 0011-drm-i915-gen9-Calculate-plane-WM-s-from-state.patch +Patch812: 0012-drm-i915-gen9-Allow-watermark-calculation-on-in-flig.patch +Patch813: 0013-drm-i915-gen9-Use-a-bitmask-to-track-dirty-pipe-wate.patch +Patch814: 0014-drm-i915-gen9-Propagate-watermark-calculation-failur.patch +Patch815: 0015-drm-i915-gen9-Calculate-watermarks-during-atomic-che.patch +Patch816: 0016-drm-i915-gen9-Reject-display-updates-that-exceed-wm-.patch +Patch817: 0017-drm-i915-Remove-wm_config-from-dev_priv-intel_atomic.patch + +#other drm/kms fixes (most Cc-ed stable) +Patch821: 0001-drm-mgag200-Black-screen-fix-for-G200e-rev-4.patch +Patch822: 0002-drm-nouveau-fbcon-fix-out-of-bounds-memory-accesses.patch +Patch823: 0003-drm-nouveau-disp-sor-gf119-both-links-use-the-same-t.patch +Patch824: 0004-drm-nouveau-disp-sor-gm107-training-pattern-register.patch +Patch825: 0005-i915-fbc-Disable-on-HSW-by-default-for-now.patch +Patch826: 0006-drm-core-Do-not-preserve-framebuffer-on-rmfb-v4.patch + # END OF PATCH DEFINITIONS %endif @@ -2164,6 +2191,11 @@ fi # # %changelog +* Mon Jun 20 2016 Hans de Goede +- Bring in patch-series from drm-next to fix skl_update_other_pipe_wm issues + (rhbz 1305038) +- Cherry pick some other drm / kms fixes from upstream + * Wed Jun 15 2016 Laura Abbott - hp-wmi: fix wifi cannot be hard-unblock (rhbz 1338025) -- cgit From 37f3e02e10d06753c3ef2981ed1c36c0bcdcd3d6 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Tue, 21 Jun 2016 19:22:18 +0100 Subject: Update patch from 4.5 with missing bits for bcm238x support --- bcm283x-upstream-fixes.patch | 400 +++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 6 +- 2 files changed, 404 insertions(+), 2 deletions(-) create mode 100644 bcm283x-upstream-fixes.patch diff --git a/bcm283x-upstream-fixes.patch b/bcm283x-upstream-fixes.patch new file mode 100644 index 000000000..d8bb87ca0 --- /dev/null +++ b/bcm283x-upstream-fixes.patch @@ -0,0 +1,400 @@ +From 41135d2ce60509e53306e5b76afab98ddc15951b Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Mon, 2 Mar 2015 14:36:16 -0800 +Subject: [PATCH 26/36] ARM: bcm2835: Add VC4 to the device tree. + +VC4 is the GPU (display and 3D) present on the 283x. + +v2: Sort by register address, mark HDMI as disabled by default in the + SoC file and enable it from -rpi. +v3: Add references to the pixel/HSM clocks for HDMI. Rename + compatibility strings and clean up node names. +v4: Fix comment marking pv0's interrupt as pwa2 instead of pwa0. + Rename hpd-gpio to hpd-gpios. +v5: Rebase on bcm283x.dtsi change, add v3d. +v6: Make HDMI reference the power domain. +v7: Fix the HDMI HPD gpios active value and HDMI enable for each RPI + board. Change V3D compatible string to 2835. + +Signed-off-by: Eric Anholt +--- + arch/arm/boot/dts/bcm2835-rpi-a-plus.dts | 4 +++ + arch/arm/boot/dts/bcm2835-rpi-a.dts | 4 +++ + arch/arm/boot/dts/bcm2835-rpi-b-plus.dts | 4 +++ + arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts | 4 +++ + arch/arm/boot/dts/bcm2835-rpi-b.dts | 4 +++ + arch/arm/boot/dts/bcm2835-rpi.dtsi | 9 ++++++ + arch/arm/boot/dts/bcm2836-rpi-2-b.dts | 4 +++ + arch/arm/boot/dts/bcm283x.dtsi | 47 ++++++++++++++++++++++++++++++++ + 8 files changed, 80 insertions(+) + +diff --git a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts +index 228614f..35ff4e7a 100644 +--- a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts ++++ b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts +@@ -29,3 +29,7 @@ + brcm,function = ; + }; + }; ++ ++&hdmi { ++ hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; ++}; +diff --git a/arch/arm/boot/dts/bcm2835-rpi-a.dts b/arch/arm/boot/dts/bcm2835-rpi-a.dts +index ddbbbbd..306a84e 100644 +--- a/arch/arm/boot/dts/bcm2835-rpi-a.dts ++++ b/arch/arm/boot/dts/bcm2835-rpi-a.dts +@@ -22,3 +22,7 @@ + brcm,function = ; + }; + }; ++ ++&hdmi { ++ hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; ++}; +diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts +index ef54050..57d313b 100644 +--- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts ++++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts +@@ -29,3 +29,7 @@ + brcm,function = ; + }; + }; ++ ++&hdmi { ++ hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; ++}; +diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts +index 86f1f2f..cf2774e 100644 +--- a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts ++++ b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts +@@ -22,3 +22,7 @@ + brcm,function = ; + }; + }; ++ ++&hdmi { ++ hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; ++}; +diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts +index 4859e9d..8b15f9c 100644 +--- a/arch/arm/boot/dts/bcm2835-rpi-b.dts ++++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts +@@ -16,3 +16,7 @@ + &gpio { + pinctrl-0 = <&gpioout &alt0 &alt3>; + }; ++ ++&hdmi { ++ hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; ++}; +diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi +index 76bdbca..caf2707 100644 +--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi ++++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi +@@ -74,3 +74,12 @@ + &usb { + power-domains = <&power RPI_POWER_DOMAIN_USB>; + }; ++ ++&v3d { ++ power-domains = <&power RPI_POWER_DOMAIN_V3D>; ++}; ++ ++&hdmi { ++ power-domains = <&power RPI_POWER_DOMAIN_HDMI>; ++ status = "okay"; ++}; +diff --git a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts +index ff94666..c4743f4 100644 +--- a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts ++++ b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts +@@ -33,3 +33,7 @@ + brcm,function = ; + }; + }; ++ ++&hdmi { ++ hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; ++}; +diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi +index fc67964..bbe4eab 100644 +--- a/arch/arm/boot/dts/bcm283x.dtsi ++++ b/arch/arm/boot/dts/bcm283x.dtsi +@@ -1,6 +1,7 @@ + #include + #include + #include ++#include + #include "skeleton.dtsi" + + /* This include file covers the common peripherals and configuration between +@@ -153,6 +154,18 @@ + status = "disabled"; + }; + ++ pixelvalve@7e206000 { ++ compatible = "brcm,bcm2835-pixelvalve0"; ++ reg = <0x7e206000 0x100>; ++ interrupts = <2 13>; /* pwa0 */ ++ }; ++ ++ pixelvalve@7e207000 { ++ compatible = "brcm,bcm2835-pixelvalve1"; ++ reg = <0x7e207000 0x100>; ++ interrupts = <2 14>; /* pwa1 */ ++ }; ++ + aux: aux@0x7e215000 { + compatible = "brcm,bcm2835-aux"; + #clock-cells = <1>; +@@ -206,6 +219,12 @@ + status = "disabled"; + }; + ++ hvs@7e400000 { ++ compatible = "brcm,bcm2835-hvs"; ++ reg = <0x7e400000 0x6000>; ++ interrupts = <2 1>; ++ }; ++ + i2c1: i2c@7e804000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e804000 0x1000>; +@@ -226,11 +245,39 @@ + status = "disabled"; + }; + ++ pixelvalve@7e807000 { ++ compatible = "brcm,bcm2835-pixelvalve2"; ++ reg = <0x7e807000 0x100>; ++ interrupts = <2 10>; /* pixelvalve */ ++ }; ++ ++ hdmi: hdmi@7e902000 { ++ compatible = "brcm,bcm2835-hdmi"; ++ reg = <0x7e902000 0x600>, ++ <0x7e808000 0x100>; ++ interrupts = <2 8>, <2 9>; ++ ddc = <&i2c2>; ++ clocks = <&clocks BCM2835_PLLH_PIX>, ++ <&clocks BCM2835_CLOCK_HSM>; ++ clock-names = "pixel", "hdmi"; ++ status = "disabled"; ++ }; ++ + usb: usb@7e980000 { + compatible = "brcm,bcm2835-usb"; + reg = <0x7e980000 0x10000>; + interrupts = <1 9>; + }; ++ ++ v3d: v3d@7ec00000 { ++ compatible = "brcm,bcm2835-v3d"; ++ reg = <0x7ec00000 0x1000>; ++ interrupts = <1 10>; ++ }; ++ ++ vc4: gpu { ++ compatible = "brcm,bcm2835-vc4"; ++ }; + }; + + clocks { +-- +2.7.3 + +From da77f737f9f5a487f3a1f80f8546585ee18cd7b9 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Fri, 4 Mar 2016 10:39:28 -0800 +Subject: [PATCH 27/36] dt-bindings: Add root properties for Raspberry Pi 3 + +Signed-off-by: Eric Anholt +Acked-by: Rob Herring +--- + Documentation/devicetree/bindings/arm/bcm/brcm,bcm2835.txt | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm2835.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm2835.txt +index 11d3056..6ffe087 100644 +--- a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm2835.txt ++++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm2835.txt +@@ -30,6 +30,10 @@ Raspberry Pi 2 Model B + Required root node properties: + compatible = "raspberrypi,2-model-b", "brcm,bcm2836"; + ++Raspberry Pi 3 Model B ++Required root node properties: ++compatible = "raspberrypi,3-model-b", "brcm,bcm2837"; ++ + Raspberry Pi Compute Module + Required root node properties: + compatible = "raspberrypi,compute-module", "brcm,bcm2835"; +-- +2.7.3 + +From b76b1cdf2e569cceab41dcf3b3f6a90965d0a02c Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Fri, 4 Mar 2016 10:39:29 -0800 +Subject: [PATCH 28/36] ARM: bcm2835: Add devicetree for the Raspberry Pi 3. + +For now this doesn't support the new hardware present on the Pi 3 (BT, +wifi, GPIO expander). Since the GPIO expander isn't supported, we +also don't have the LEDs like the other board files do. + +Signed-off-by: Eric Anholt +Acked-by: Stephen Warren +--- + arch/arm/boot/dts/Makefile | 3 +- + arch/arm/boot/dts/bcm2837-rpi-3-b.dts | 22 ++++++++++++ + arch/arm/boot/dts/bcm2837.dtsi | 68 +++++++++++++++++++++++++++++++++++ + 3 files changed, 92 insertions(+), 1 deletion(-) + create mode 100644 arch/arm/boot/dts/bcm2837-rpi-3-b.dts + create mode 100644 arch/arm/boot/dts/bcm2837.dtsi + +diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index d000814..a8a0767 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -64,7 +64,8 @@ dtb-$(CONFIG_ARCH_BCM2835) += \ + bcm2835-rpi-b-rev2.dtb \ + bcm2835-rpi-b-plus.dtb \ + bcm2835-rpi-a-plus.dtb \ +- bcm2836-rpi-2-b.dtb ++ bcm2836-rpi-2-b.dtb \ ++ bcm2837-rpi-3-b.dtb + dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm4708-asus-rt-ac56u.dtb \ + bcm4708-asus-rt-ac68u.dtb \ +diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts +new file mode 100644 +index 0000000..5e8eafd +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts +@@ -0,0 +1,22 @@ ++/dts-v1/; ++#include "bcm2837.dtsi" ++#include "bcm2835-rpi.dtsi" ++ ++/ { ++ compatible = "raspberrypi,3-model-b", "brcm,bcm2837"; ++ model = "Raspberry Pi 3 Model B"; ++ ++ memory { ++ reg = <0 0x40000000>; ++ }; ++}; ++ ++&gpio { ++ pinctrl-0 = <&gpioout &alt0 &i2s_alt0 &alt3>; ++ ++ /* I2S interface */ ++ i2s_alt0: i2s_alt0 { ++ brcm,pins = <28 29 30 31>; ++ brcm,function = ; ++ }; ++}; +diff --git a/arch/arm/boot/dts/bcm2837.dtsi b/arch/arm/boot/dts/bcm2837.dtsi +new file mode 100644 +index 0000000..2f36722 +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2837.dtsi +@@ -0,0 +1,68 @@ ++#include "bcm283x.dtsi" ++ ++/ { ++ compatible = "brcm,bcm2836"; ++ ++ soc { ++ ranges = <0x7e000000 0x3f000000 0x1000000>, ++ <0x40000000 0x40000000 0x00001000>; ++ dma-ranges = <0xc0000000 0x00000000 0x3f000000>; ++ ++ local_intc: local_intc { ++ compatible = "brcm,bcm2836-l1-intc"; ++ reg = <0x40000000 0x100>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ interrupt-parent = <&local_intc>; ++ }; ++ }; ++ ++ timer { ++ compatible = "arm,armv7-timer"; ++ interrupt-parent = <&local_intc>; ++ interrupts = <0>, // PHYS_SECURE_PPI ++ <1>, // PHYS_NONSECURE_PPI ++ <3>, // VIRT_PPI ++ <2>; // HYP_PPI ++ always-on; ++ }; ++ ++ cpus: cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu0: cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <0>; ++ }; ++ ++ cpu1: cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <1>; ++ }; ++ ++ cpu2: cpu@2 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <2>; ++ }; ++ ++ cpu3: cpu@3 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <3>; ++ }; ++ }; ++}; ++ ++/* Make the BCM2835-style global interrupt controller be a child of the ++ * CPU-local interrupt controller. ++ */ ++&intc { ++ compatible = "brcm,bcm2836-armctrl-ic"; ++ reg = <0x7e00b200 0x200>; ++ interrupt-parent = <&local_intc>; ++ interrupts = <8>; ++}; +-- +2.7.3 + +From 528285e99c25249456023d28f521689bf9e9eb8b Mon Sep 17 00:00:00 2001 +From: Peter Robinson +Date: Wed, 30 Mar 2016 09:35:13 +0100 +Subject: [PATCH 32/36] drop usb power domain support for the moment, kills usb + +--- + arch/arm/boot/dts/bcm2835-rpi.dtsi | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi +index caf2707..b1e8145 100644 +--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi ++++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi +@@ -71,10 +71,6 @@ + status = "okay"; + }; + +-&usb { +- power-domains = <&power RPI_POWER_DOMAIN_USB>; +-}; +- + &v3d { + power-domains = <&power RPI_POWER_DOMAIN_V3D>; + }; +-- +2.7.3 + diff --git a/kernel.spec b/kernel.spec index 9f2d141ea..20d3ee049 100644 --- a/kernel.spec +++ b/kernel.spec @@ -518,8 +518,7 @@ Patch431: Fix-tegra-to-use-stdout-path-for-serial-console.patch Patch432: arm-i.MX6-Utilite-device-dtb.patch -# mvebu DSA switch fixes -# http://www.spinics.net/lists/netdev/msg370841.html http://www.spinics.net/lists/netdev/msg370842.html +Patch433: bcm283x-upstream-fixes.patch Patch460: lib-cpumask-Make-CPUMASK_OFFSTACK-usable-without-deb.patch @@ -2191,6 +2190,9 @@ fi # # %changelog +* Tue Jun 21 2016 Peter Robinson +- Update patch from 4.5 with missing bits for bcm238x support + * Mon Jun 20 2016 Hans de Goede - Bring in patch-series from drm-next to fix skl_update_other_pipe_wm issues (rhbz 1305038) -- cgit From bf1d35cfe8b31cbac09a036ab36cd742b63031f1 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 24 Jun 2016 14:01:12 -0400 Subject: Linux v4.6.3 --- ...re-Do-not-preserve-framebuffer-on-rmfb-v4.patch | 145 -------------------- ...forbid-opening-files-without-mmap-handler.patch | 59 -------- kernel.spec | 17 +-- ..._tables-deal-with-bogus-nextoffset-values.patch | 150 --------------------- proc-prevent-stacking-filesystems-on-top.patch | 41 ------ sched-panic-on-corrupted-stack-end.patch | 36 ----- sources | 2 +- ...-nl-sock-before-parsing-nested-attributes.patch | 36 ----- 8 files changed, 5 insertions(+), 481 deletions(-) delete mode 100644 0006-drm-core-Do-not-preserve-framebuffer-on-rmfb-v4.patch delete mode 100644 ecryptfs-forbid-opening-files-without-mmap-handler.patch delete mode 100644 netfilter-x_tables-deal-with-bogus-nextoffset-values.patch delete mode 100644 proc-prevent-stacking-filesystems-on-top.patch delete mode 100644 sched-panic-on-corrupted-stack-end.patch delete mode 100644 tipc-check-nl-sock-before-parsing-nested-attributes.patch diff --git a/0006-drm-core-Do-not-preserve-framebuffer-on-rmfb-v4.patch b/0006-drm-core-Do-not-preserve-framebuffer-on-rmfb-v4.patch deleted file mode 100644 index 81936aca1..000000000 --- a/0006-drm-core-Do-not-preserve-framebuffer-on-rmfb-v4.patch +++ /dev/null @@ -1,145 +0,0 @@ -From b87459ac92803eafc8dd9f8a8ccc36190fe427f1 Mon Sep 17 00:00:00 2001 -From: Maarten Lankhorst -Date: Wed, 4 May 2016 14:38:26 +0200 -Subject: [PATCH 6/6] drm/core: Do not preserve framebuffer on rmfb, v4. - -Upstream since: 4.7-rc1 -commit f2d580b9a8149735cbc4b59c4a8df60173658140 - -It turns out that preserving framebuffers after the rmfb call breaks -vmwgfx userspace. This was originally introduced because it was thought -nobody relied on the behavior, but unfortunately it seems there are -exceptions. - -drm_framebuffer_remove may fail with -EINTR now, so a straight revert -is impossible. There is no way to remove the framebuffer from the lists -and active planes without introducing a race because of the different -locking requirements. Instead call drm_framebuffer_remove from a -workqueue, which is unaffected by signals. - -Changes since v1: -- Add comment. -Changes since v2: -- Add fastpath for refcount = 1. (danvet) -Changes since v3: -- Rebased. -- Restore lastclose framebuffer removal too. - -Cc: stable@vger.kernel.org #v4.4+ -Fixes: 13803132818c ("drm/core: Preserve the framebuffer after removing it.") -Testcase: kms_rmfb_basic -References: https://lists.freedesktop.org/archives/dri-devel/2016-March/102876.html -Cc: Thomas Hellstrom -Cc: David Herrmann -Reviewed-by: Daniel Vetter -Tested-by: Thomas Hellstrom #v3 -Tested-by: Tvrtko Ursulin -Signed-off-by: Daniel Vetter -Link: http://patchwork.freedesktop.org/patch/msgid/6c63ca37-0e7e-ac7f-a6d2-c7822e3d611f@linux.intel.com ---- - drivers/gpu/drm/drm_crtc.c | 60 ++++++++++++++++++++++++++++++++++++++++++---- - 1 file changed, 55 insertions(+), 5 deletions(-) - -diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c -index e08f962..f30de80 100644 ---- a/drivers/gpu/drm/drm_crtc.c -+++ b/drivers/gpu/drm/drm_crtc.c -@@ -3434,6 +3434,24 @@ int drm_mode_addfb2(struct drm_device *dev, - return 0; - } - -+struct drm_mode_rmfb_work { -+ struct work_struct work; -+ struct list_head fbs; -+}; -+ -+static void drm_mode_rmfb_work_fn(struct work_struct *w) -+{ -+ struct drm_mode_rmfb_work *arg = container_of(w, typeof(*arg), work); -+ -+ while (!list_empty(&arg->fbs)) { -+ struct drm_framebuffer *fb = -+ list_first_entry(&arg->fbs, typeof(*fb), filp_head); -+ -+ list_del_init(&fb->filp_head); -+ drm_framebuffer_remove(fb); -+ } -+} -+ - /** - * drm_mode_rmfb - remove an FB from the configuration - * @dev: drm device for the ioctl -@@ -3474,7 +3492,25 @@ int drm_mode_rmfb(struct drm_device *dev, - mutex_unlock(&dev->mode_config.fb_lock); - mutex_unlock(&file_priv->fbs_lock); - -- drm_framebuffer_unreference(fb); -+ /* -+ * we now own the reference that was stored in the fbs list -+ * -+ * drm_framebuffer_remove may fail with -EINTR on pending signals, -+ * so run this in a separate stack as there's no way to correctly -+ * handle this after the fb is already removed from the lookup table. -+ */ -+ if (atomic_read(&fb->refcount.refcount) > 1) { -+ struct drm_mode_rmfb_work arg; -+ -+ INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn); -+ INIT_LIST_HEAD(&arg.fbs); -+ list_add_tail(&fb->filp_head, &arg.fbs); -+ -+ schedule_work(&arg.work); -+ flush_work(&arg.work); -+ destroy_work_on_stack(&arg.work); -+ } else -+ drm_framebuffer_unreference(fb); - - return 0; - -@@ -3627,7 +3663,6 @@ out_err1: - return ret; - } - -- - /** - * drm_fb_release - remove and free the FBs on this file - * @priv: drm file for the ioctl -@@ -3642,6 +3677,9 @@ out_err1: - void drm_fb_release(struct drm_file *priv) - { - struct drm_framebuffer *fb, *tfb; -+ struct drm_mode_rmfb_work arg; -+ -+ INIT_LIST_HEAD(&arg.fbs); - - /* - * When the file gets released that means no one else can access the fb -@@ -3654,10 +3692,22 @@ void drm_fb_release(struct drm_file *priv) - * at it any more. - */ - list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { -- list_del_init(&fb->filp_head); -+ if (atomic_read(&fb->refcount.refcount) > 1) { -+ list_move_tail(&fb->filp_head, &arg.fbs); -+ } else { -+ list_del_init(&fb->filp_head); - -- /* This drops the fpriv->fbs reference. */ -- drm_framebuffer_unreference(fb); -+ /* This drops the fpriv->fbs reference. */ -+ drm_framebuffer_unreference(fb); -+ } -+ } -+ -+ if (!list_empty(&arg.fbs)) { -+ INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn); -+ -+ schedule_work(&arg.work); -+ flush_work(&arg.work); -+ destroy_work_on_stack(&arg.work); - } - } - --- -2.7.4 - diff --git a/ecryptfs-forbid-opening-files-without-mmap-handler.patch b/ecryptfs-forbid-opening-files-without-mmap-handler.patch deleted file mode 100644 index 2d40e68ed..000000000 --- a/ecryptfs-forbid-opening-files-without-mmap-handler.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 2f36db71009304b3f0b95afacd8eba1f9f046b87 Mon Sep 17 00:00:00 2001 -From: Jann Horn -Date: Wed, 1 Jun 2016 11:55:06 +0200 -Subject: [PATCH] ecryptfs: forbid opening files without mmap handler - -This prevents users from triggering a stack overflow through a recursive -invocation of pagefault handling that involves mapping procfs files into -virtual memory. - -Signed-off-by: Jann Horn -Acked-by: Tyler Hicks -Cc: stable@vger.kernel.org -Signed-off-by: Linus Torvalds ---- - fs/ecryptfs/kthread.c | 13 +++++++++++-- - 1 file changed, 11 insertions(+), 2 deletions(-) - -diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c -index 866bb18efefe..e818f5ac7a26 100644 ---- a/fs/ecryptfs/kthread.c -+++ b/fs/ecryptfs/kthread.c -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - #include "ecryptfs_kernel.h" - - struct ecryptfs_open_req { -@@ -147,7 +148,7 @@ int ecryptfs_privileged_open(struct file **lower_file, - flags |= IS_RDONLY(d_inode(lower_dentry)) ? O_RDONLY : O_RDWR; - (*lower_file) = dentry_open(&req.path, flags, cred); - if (!IS_ERR(*lower_file)) -- goto out; -+ goto have_file; - if ((flags & O_ACCMODE) == O_RDONLY) { - rc = PTR_ERR((*lower_file)); - goto out; -@@ -165,8 +166,16 @@ int ecryptfs_privileged_open(struct file **lower_file, - mutex_unlock(&ecryptfs_kthread_ctl.mux); - wake_up(&ecryptfs_kthread_ctl.wait); - wait_for_completion(&req.done); -- if (IS_ERR(*lower_file)) -+ if (IS_ERR(*lower_file)) { - rc = PTR_ERR(*lower_file); -+ goto out; -+ } -+have_file: -+ if ((*lower_file)->f_op->mmap == NULL) { -+ fput(*lower_file); -+ *lower_file = NULL; -+ rc = -EMEDIUMTYPE; -+ } - out: - return rc; - } --- -2.5.5 - diff --git a/kernel.spec b/kernel.spec index 20d3ee049..3525f7180 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 2 +%define stable_update 3 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev %{stable_update} @@ -604,9 +604,6 @@ Patch571: ideapad-laptop-Add-Lenovo-ideapad-Y700-17ISK-to-no_h.patch #Required for some persistent memory options Patch641: disable-CONFIG_EXPERT-for-ZONE_DMA.patch -#CVE-2016-3134 rhbz 1317383 1317384 -Patch665: netfilter-x_tables-deal-with-bogus-nextoffset-values.patch - #CVE-2016-4482 rhbz 1332931 1332932 Patch706: USB-usbfs-fix-potential-infoleak-in-devio.patch @@ -618,20 +615,12 @@ Patch716: ALSA-timer-Fix-leak-in-events-via-snd_timer_user_tin.patch #CVE-2016-4440 rhbz 1337806 1337807 Patch719: kvm-vmx-more-complete-state-update-on-APICv-on-off.patch -#CVE-2016-4951 rhbz 1338625 1338626 -Patch720: tipc-check-nl-sock-before-parsing-nested-attributes.patch - #CVE-2016-5243 rhbz 1343338 1343335 Patch721: tipc-fix-an-infoleak-in-tipc_nl_compat_link_dump.patch #CVE-2016-5244 rhbz 1343338 1343337 Patch722: rds-fix-an-infoleak-in-rds_inc_info_copy.txt -#CVE-2016-1583 rhbz 1344721 1344722 -Patch723: proc-prevent-stacking-filesystems-on-top.patch -Patch725: ecryptfs-forbid-opening-files-without-mmap-handler.patch -Patch726: sched-panic-on-corrupted-stack-end.patch - #CVE-2016-4470 rhbz 1341716 1346626 Patch727: KEYS-potential-uninitialized-variable.patch @@ -663,7 +652,6 @@ Patch822: 0002-drm-nouveau-fbcon-fix-out-of-bounds-memory-accesses.patch Patch823: 0003-drm-nouveau-disp-sor-gf119-both-links-use-the-same-t.patch Patch824: 0004-drm-nouveau-disp-sor-gm107-training-pattern-register.patch Patch825: 0005-i915-fbc-Disable-on-HSW-by-default-for-now.patch -Patch826: 0006-drm-core-Do-not-preserve-framebuffer-on-rmfb-v4.patch # END OF PATCH DEFINITIONS @@ -2190,6 +2178,9 @@ fi # # %changelog +* Fri Jun 24 2016 Josh Boyer +- Linux v4.6.3 + * Tue Jun 21 2016 Peter Robinson - Update patch from 4.5 with missing bits for bcm238x support diff --git a/netfilter-x_tables-deal-with-bogus-nextoffset-values.patch b/netfilter-x_tables-deal-with-bogus-nextoffset-values.patch deleted file mode 100644 index ebfe1716f..000000000 --- a/netfilter-x_tables-deal-with-bogus-nextoffset-values.patch +++ /dev/null @@ -1,150 +0,0 @@ -Subject: [PATCH nf] netfilter: x_tables: deal with bogus nextoffset values -From: Florian Westphal -Date: 2016-03-10 0:56:02 - -Ben Hawkes says: - - In the mark_source_chains function (net/ipv4/netfilter/ip_tables.c) it - is possible for a user-supplied ipt_entry structure to have a large - next_offset field. This field is not bounds checked prior to writing a - counter value at the supplied offset. - -Problem is that xt_entry_foreach() macro stops iterating once e->next_offset -is out of bounds, assuming this is the last entry. - -With malformed data thats not necessarily the case so we can -write outside of allocated area later as we might not have walked the -entire blob. - -Fix this by simplifying mark_source_chains -- it already has to check -if nextoff is in range to catch invalid jumps, so just do the check -when we move to a next entry as well. - -Signed-off-by: Florian Westphal ---- - net/ipv4/netfilter/arp_tables.c | 16 ++++++++-------- - net/ipv4/netfilter/ip_tables.c | 15 ++++++++------- - net/ipv6/netfilter/ip6_tables.c | 13 ++++++------- - 3 files changed, 22 insertions(+), 22 deletions(-) - -diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c -index b488cac..5a0b591 100644 ---- a/net/ipv4/netfilter/arp_tables.c -+++ b/net/ipv4/netfilter/arp_tables.c -@@ -437,6 +437,10 @@ static int mark_source_chains(const struct xt_table_info *newinfo, - - /* Move along one */ - size = e->next_offset; -+ -+ if (pos + size > newinfo->size - sizeof(*e)) -+ return 0; -+ - e = (struct arpt_entry *) - (entry0 + pos + size); - e->counters.pcnt = pos; -@@ -447,14 +451,6 @@ static int mark_source_chains(const struct xt_table_info *newinfo, - if (strcmp(t->target.u.user.name, - XT_STANDARD_TARGET) == 0 && - newpos >= 0) { -- if (newpos > newinfo->size - -- sizeof(struct arpt_entry)) { -- duprintf("mark_source_chains: " -- "bad verdict (%i)\n", -- newpos); -- return 0; -- } -- - /* This a jump; chase it. */ - duprintf("Jump rule %u -> %u\n", - pos, newpos); -@@ -462,6 +458,10 @@ static int mark_source_chains(const struct xt_table_info *newinfo, - /* ... this is a fallthru */ - newpos = pos + e->next_offset; - } -+ -+ if (newpos > newinfo->size - sizeof(*e)) -+ return 0; -+ - e = (struct arpt_entry *) - (entry0 + newpos); - e->counters.pcnt = pos; -diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c -index b99affa..ceb995f 100644 ---- a/net/ipv4/netfilter/ip_tables.c -+++ b/net/ipv4/netfilter/ip_tables.c -@@ -519,6 +519,10 @@ mark_source_chains(const struct xt_table_info *newinfo, - - /* Move along one */ - size = e->next_offset; -+ -+ if (pos + size > newinfo->size - sizeof(*e)) -+ return 0; -+ - e = (struct ipt_entry *) - (entry0 + pos + size); - e->counters.pcnt = pos; -@@ -529,13 +533,6 @@ mark_source_chains(const struct xt_table_info *newinfo, - if (strcmp(t->target.u.user.name, - XT_STANDARD_TARGET) == 0 && - newpos >= 0) { -- if (newpos > newinfo->size - -- sizeof(struct ipt_entry)) { -- duprintf("mark_source_chains: " -- "bad verdict (%i)\n", -- newpos); -- return 0; -- } - /* This a jump; chase it. */ - duprintf("Jump rule %u -> %u\n", - pos, newpos); -@@ -543,6 +540,10 @@ mark_source_chains(const struct xt_table_info *newinfo, - /* ... this is a fallthru */ - newpos = pos + e->next_offset; - } -+ -+ if (newpos > newinfo->size - sizeof(*e)) -+ return 0; -+ - e = (struct ipt_entry *) - (entry0 + newpos); - e->counters.pcnt = pos; -diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c -index 99425cf..d88a794 100644 ---- a/net/ipv6/netfilter/ip6_tables.c -+++ b/net/ipv6/netfilter/ip6_tables.c -@@ -531,6 +531,8 @@ mark_source_chains(const struct xt_table_info *newinfo, - - /* Move along one */ - size = e->next_offset; -+ if (pos + size > newinfo->size - sizeof(*e)) -+ return 0; - e = (struct ip6t_entry *) - (entry0 + pos + size); - e->counters.pcnt = pos; -@@ -541,13 +543,6 @@ mark_source_chains(const struct xt_table_info *newinfo, - if (strcmp(t->target.u.user.name, - XT_STANDARD_TARGET) == 0 && - newpos >= 0) { -- if (newpos > newinfo->size - -- sizeof(struct ip6t_entry)) { -- duprintf("mark_source_chains: " -- "bad verdict (%i)\n", -- newpos); -- return 0; -- } - /* This a jump; chase it. */ - duprintf("Jump rule %u -> %u\n", - pos, newpos); -@@ -555,6 +550,10 @@ mark_source_chains(const struct xt_table_info *newinfo, - /* ... this is a fallthru */ - newpos = pos + e->next_offset; - } -+ -+ if (newpos > newinfo->size - sizeof(*e)) -+ return 0; -+ - e = (struct ip6t_entry *) - (entry0 + newpos); - e->counters.pcnt = pos; --- -2.4.10 diff --git a/proc-prevent-stacking-filesystems-on-top.patch b/proc-prevent-stacking-filesystems-on-top.patch deleted file mode 100644 index 178aa3ba6..000000000 --- a/proc-prevent-stacking-filesystems-on-top.patch +++ /dev/null @@ -1,41 +0,0 @@ -From e54ad7f1ee263ffa5a2de9c609d58dfa27b21cd9 Mon Sep 17 00:00:00 2001 -From: Jann Horn -Date: Wed, 1 Jun 2016 11:55:05 +0200 -Subject: [PATCH] proc: prevent stacking filesystems on top - -This prevents stacking filesystems (ecryptfs and overlayfs) from using -procfs as lower filesystem. There is too much magic going on inside -procfs, and there is no good reason to stack stuff on top of procfs. - -(For example, procfs does access checks in VFS open handlers, and -ecryptfs by design calls open handlers from a kernel thread that doesn't -drop privileges or so.) - -Signed-off-by: Jann Horn -Cc: stable@vger.kernel.org -Signed-off-by: Linus Torvalds ---- - fs/proc/root.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/fs/proc/root.c b/fs/proc/root.c -index 361ab4ee42fc..ec649c92d270 100644 ---- a/fs/proc/root.c -+++ b/fs/proc/root.c -@@ -121,6 +121,13 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, - if (IS_ERR(sb)) - return ERR_CAST(sb); - -+ /* -+ * procfs isn't actually a stacking filesystem; however, there is -+ * too much magic going on inside it to permit stacking things on -+ * top of it -+ */ -+ sb->s_stack_depth = FILESYSTEM_MAX_STACK_DEPTH; -+ - if (!proc_parse_options(options, ns)) { - deactivate_locked_super(sb); - return ERR_PTR(-EINVAL); --- -2.5.5 - diff --git a/sched-panic-on-corrupted-stack-end.patch b/sched-panic-on-corrupted-stack-end.patch deleted file mode 100644 index 1d6bbaf3d..000000000 --- a/sched-panic-on-corrupted-stack-end.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 29d6455178a09e1dc340380c582b13356227e8df Mon Sep 17 00:00:00 2001 -From: Jann Horn -Date: Wed, 1 Jun 2016 11:55:07 +0200 -Subject: [PATCH] sched: panic on corrupted stack end - -Until now, hitting this BUG_ON caused a recursive oops (because oops -handling involves do_exit(), which calls into the scheduler, which in -turn raises an oops), which caused stuff below the stack to be -overwritten until a panic happened (e.g. via an oops in interrupt -context, caused by the overwritten CPU index in the thread_info). - -Just panic directly. - -Signed-off-by: Jann Horn -Signed-off-by: Linus Torvalds ---- - kernel/sched/core.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/kernel/sched/core.c b/kernel/sched/core.c -index d1f7149f8704..11546a6ed5df 100644 ---- a/kernel/sched/core.c -+++ b/kernel/sched/core.c -@@ -3047,7 +3047,8 @@ static noinline void __schedule_bug(struct task_struct *prev) - static inline void schedule_debug(struct task_struct *prev) - { - #ifdef CONFIG_SCHED_STACK_END_CHECK -- BUG_ON(task_stack_end_corrupted(prev)); -+ if (task_stack_end_corrupted(prev)) -+ panic("corrupted stack end detected inside scheduler\n"); - #endif - - if (unlikely(in_atomic_preempt_off())) { --- -2.5.5 - diff --git a/sources b/sources index 97a63ff63..8debc8e12 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ d2927020e24a76da4ab482a8bc3e9ef3 linux-4.6.tar.xz fd23b14b9d474c3dfacb6e8ee82d3a51 perf-man-4.6.tar.gz -c064bbe8108b8e5304f3db2130a96845 patch-4.6.2.xz +0d59cb81eb7c0daf0f5019deda65af90 patch-4.6.3.xz diff --git a/tipc-check-nl-sock-before-parsing-nested-attributes.patch b/tipc-check-nl-sock-before-parsing-nested-attributes.patch deleted file mode 100644 index 09bfe1485..000000000 --- a/tipc-check-nl-sock-before-parsing-nested-attributes.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 45e093ae2830cd1264677d47ff9a95a71f5d9f9c Mon Sep 17 00:00:00 2001 -From: Richard Alpe -Date: Mon, 16 May 2016 11:14:54 +0200 -Subject: [PATCH] tipc: check nl sock before parsing nested attributes - -Make sure the socket for which the user is listing publication exists -before parsing the socket netlink attributes. - -Prior to this patch a call without any socket caused a NULL pointer -dereference in tipc_nl_publ_dump(). - -Tested-and-reported-by: Baozeng Ding -Signed-off-by: Richard Alpe -Acked-by: Jon Maloy -Signed-off-by: David S. Miller ---- - net/tipc/socket.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/net/tipc/socket.c b/net/tipc/socket.c -index 12628890c219..3b7a79991d55 100644 ---- a/net/tipc/socket.c -+++ b/net/tipc/socket.c -@@ -2853,6 +2853,9 @@ int tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb) - if (err) - return err; - -+ if (!attrs[TIPC_NLA_SOCK]) -+ return -EINVAL; -+ - err = nla_parse_nested(sock, TIPC_NLA_SOCK_MAX, - attrs[TIPC_NLA_SOCK], - tipc_nl_sock_policy); --- -2.5.5 - -- cgit