summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThorsten Leemhuis <fedora@leemhuis.info>2016-11-08 07:44:09 +0100
committerThorsten Leemhuis <fedora@leemhuis.info>2016-11-08 07:44:09 +0100
commitaa0b45ebce64eeb2b8cf30ddf3d4ef5b971a875b (patch)
tree1df88487da2ba4a730e9312179132e8a7a1ceeae
parent6ef1f900ea30dc8e92ee3ae82be1594e4e010490 (diff)
parent81637157067b36fc2d01fd3aa596beaefc424ae8 (diff)
downloadkernel-aa0b45ebce64eeb2b8cf30ddf3d4ef5b971a875b.tar.gz
kernel-aa0b45ebce64eeb2b8cf30ddf3d4ef5b971a875b.tar.xz
kernel-aa0b45ebce64eeb2b8cf30ddf3d4ef5b971a875b.zip
Merge remote-tracking branch 'origin/f23' into f23-user-thl-vanilla-fedorakernel-4.8.6-100.vanilla.knurd.1.fc23
-rw-r--r--0001-HID-input-ignore-System-Control-application-usages-i.patch75
-rw-r--r--0001-dm-raid-fix-compat_features-validation.patch39
-rw-r--r--0001-drm-i915-Reorganize-WM-structs-unions-in-CRTC-state.patch227
-rw-r--r--0001-selinux-Only-apply-bounds-checking-to-source-types.patch203
-rw-r--r--0002-drm-i915-Rename-s-skl_compute_pipe_wm-skl_build_pipe.patch60
-rw-r--r--0003-drm-i915-gen9-Cache-plane-data-rates-in-CRTC-state.patch214
-rw-r--r--0004-drm-i915-gen9-Allow-calculation-of-data-rate-for-in-.patch141
-rw-r--r--0005-drm-i915-gen9-Store-plane-minimum-blocks-in-CRTC-wm-.patch67
-rw-r--r--0006-drm-i915-Track-whether-an-atomic-transaction-changes.patch68
-rw-r--r--0007-drm-i915-gen9-Allow-skl_allocate_pipe_ddb-to-operate.patch352
-rw-r--r--0008-drm-i915-Add-distrust_bios_wm-flag-to-dev_priv-v2.patch84
-rw-r--r--0009-drm-i915-gen9-Compute-DDB-allocation-at-atomic-check.patch244
-rw-r--r--0010-drm-i915-gen9-Drop-re-allocation-of-DDB-at-atomic-co.patch379
-rw-r--r--0011-drm-i915-gen9-Calculate-plane-WM-s-from-state.patch91
-rw-r--r--0012-drm-i915-gen9-Allow-watermark-calculation-on-in-flig.patch156
-rw-r--r--0013-drm-i915-gen9-Use-a-bitmask-to-track-dirty-pipe-wate.patch91
-rw-r--r--0014-drm-i915-gen9-Propagate-watermark-calculation-failur.patch254
-rw-r--r--0015-drm-i915-gen9-Calculate-watermarks-during-atomic-che.patch302
-rw-r--r--0016-drm-i915-gen9-Reject-display-updates-that-exceed-wm-.patch63
-rw-r--r--0017-drm-i915-Remove-wm_config-from-dev_priv-intel_atomic.patch105
-rw-r--r--ARM-OMAP4-Fix-crashes.patch97
-rw-r--r--Add-EFI-signature-data-types.patch13
-rw-r--r--Add-secure_modules-call.patch18
-rw-r--r--AllWinner-net-emac.patch2700
-rw-r--r--HID-microsoft-Add-Surface-4-type-cover-pro-4-JP.patch76
-rw-r--r--PCI-Lock-down-BAR-access-when-module-security-is-ena.patch21
-rw-r--r--arm-i.MX6-Utilite-device-dtb.patch354
-rw-r--r--arm-revert-mmc-omap_hsmmc-Use-dma_request_chan-for-reque.patch100
-rw-r--r--arm64-ACPI-parse-SPCR-table.patch596
-rw-r--r--arm64-pcie-acpi.patch1247
-rw-r--r--arm64-pcie-quirks-xgene.patch508
-rw-r--r--arm64-pcie-quirks.patch977
-rw-r--r--bcm2837-initial-support.patch (renamed from bcm283x-upstream-fixes.patch)95
-rw-r--r--bcm283x-vc4-fixes.patch682
-rw-r--r--config-arm-generic82
-rw-r--r--config-arm6454
-rw-r--r--config-armv743
-rw-r--r--config-armv7-generic90
-rw-r--r--config-armv7-lpae18
-rw-r--r--config-generic110
-rw-r--r--config-powerpc64-generic11
-rw-r--r--config-s390x3
-rw-r--r--config-x86-generic18
-rw-r--r--config-x86_64-generic10
-rw-r--r--crash-driver.patch131
-rw-r--r--disable-CONFIG_EXPERT-for-ZONE_DMA.patch43
-rw-r--r--drm-i915-turn-off-wc-mmaps.patch8
-rw-r--r--kbuild-AFTER_LINK.patch12
-rw-r--r--kernel-panic-TPROXY-vanilla-4.7.1.patch85
-rw-r--r--kernel.spec87
-rw-r--r--qcom-QDF2432-tmp-errata.patch59
-rw-r--r--qxl-reapply-cursor-after-SetCrtc-calls.patch439
-rw-r--r--security-selinux-overlayfs-support.patch931
-rw-r--r--sources6
-rw-r--r--tip-x86-boot-x86-KASLR-x86-power-Remove-x86-hibernation-restrictions.patch131
-rw-r--r--v3-vfio-pci-Fix-integer-overflows-bitmask-check.patch102
56 files changed, 7397 insertions, 5775 deletions
diff --git a/0001-HID-input-ignore-System-Control-application-usages-i.patch b/0001-HID-input-ignore-System-Control-application-usages-i.patch
new file mode 100644
index 000000000..9920598c2
--- /dev/null
+++ b/0001-HID-input-ignore-System-Control-application-usages-i.patch
@@ -0,0 +1,75 @@
+From 1989dada7ce07848196991c9ebf25ff9c5f14d4e Mon Sep 17 00:00:00 2001
+From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Date: Tue, 13 Sep 2016 11:52:37 +0200
+Subject: [PATCH] HID: input: ignore System Control application usages if not
+ System Controls
+
+Microsoft is reusing its report descriptor again and again, and part of it
+looks like this:
+
+0x05, 0x01, // Usage Page (Generic Desktop) 299
+0x09, 0x80, // Usage (System Control) 301
+0xa1, 0x01, // Collection (Application) 303
+0x85, 0x03, // Report ID (3) 305
+0x19, 0x00, // Usage Minimum (0) 307
+0x29, 0xff, // Usage Maximum (255) 309
+0x15, 0x00, // Logical Minimum (0) 311
+0x26, 0xff, 0x00, // Logical Maximum (255) 313
+0x81, 0x00, // Input (Data,Arr,Abs) 316
+0xc0, // End Collection 318
+
+While there is nothing wrong in term of processing, we do however blindly
+map the full usage range (it's an array) from 0x00 to 0xff, which creates
+some interesting axis, like ABS_X|Y, and a bunch of ABS_MISC + n.
+
+While libinput and other stacks don't care that much (we can detect them),
+joydev is very happy and attaches itself to the mouse or keyboard.
+
+The problem is that joydev now handles the device as a joystick, but given
+that we have a HID array, it sets all the ABS_* values to 0. And in its
+world, 0 means -32767 (minimum value), which sends spurious events to games
+(think Steam).
+
+It looks like hid-microsoft tries to tackle the very same problem with its
+.report_fixup callback. But fixing the report descriptor is an endless task
+and is quite obfuscated.
+
+So take the hammer, and decide that if the application is meant to be
+System Control, any other usage not in the System Control range should
+be ignored.
+
+Link: https://bugzilla.redhat.com/show_bug.cgi?id=1325354
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=28912
+Link: https://github.com/ValveSoftware/steam-for-linux/issues/3384
+Link: https://bugzilla.redhat.com/show_bug.cgi?id=1325354
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=37982
+
+Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+---
+ drivers/hid/hid-input.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
+index bcfaf32..058919d 100644
+--- a/drivers/hid/hid-input.c
++++ b/drivers/hid/hid-input.c
+@@ -604,6 +604,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
+ break;
+ }
+
++ /*
++ * Some lazy vendors declare 255 usages for System Control,
++ * leading to the creation of ABS_X|Y axis and too many others.
++ * It wouldn't be a problem if joydev doesn't consider the
++ * device as a joystick then.
++ */
++ if (field->application == HID_GD_SYSTEM_CONTROL)
++ goto ignore;
++
+ if ((usage->hid & 0xf0) == 0x90) { /* D-pad */
+ switch (usage->hid) {
+ case HID_GD_UP: usage->hat_dir = 1; break;
+--
+2.7.4
+
diff --git a/0001-dm-raid-fix-compat_features-validation.patch b/0001-dm-raid-fix-compat_features-validation.patch
new file mode 100644
index 000000000..c418f2632
--- /dev/null
+++ b/0001-dm-raid-fix-compat_features-validation.patch
@@ -0,0 +1,39 @@
+From 5c33677c87cbe44ae04df69c4a29c1750a9ec4e5 Mon Sep 17 00:00:00 2001
+From: Andy Whitcroft <apw@canonical.com>
+Date: Tue, 11 Oct 2016 15:16:57 +0100
+Subject: [PATCH] dm raid: fix compat_features validation
+
+In ecbfb9f118bce4 ("dm raid: add raid level takeover support") a new
+compatible feature flag was added. Validation for these compat_features
+was added but this only passes for new raid mappings with this feature
+flag. This causes previously created raid mappings to be failed at
+import.
+
+Check compat_features for the only valid combination.
+
+Fixes: ecbfb9f118bce4 ("dm raid: add raid level takeover support")
+Cc: stable@vger.kernel.org # v4.8
+Signed-off-by: Andy Whitcroft <apw@canonical.com>
+Signed-off-by: Heinz Mauelshagen <heinzm@redhat.com>
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+---
+ drivers/md/dm-raid.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
+index 8abde6b..2a39700 100644
+--- a/drivers/md/dm-raid.c
++++ b/drivers/md/dm-raid.c
+@@ -2258,7 +2258,8 @@ static int super_validate(struct raid_set *rs, struct md_rdev *rdev)
+ if (!mddev->events && super_init_validation(rs, rdev))
+ return -EINVAL;
+
+- if (le32_to_cpu(sb->compat_features) != FEATURE_FLAG_SUPPORTS_V190) {
++ if (le32_to_cpu(sb->compat_features) &&
++ le32_to_cpu(sb->compat_features) != FEATURE_FLAG_SUPPORTS_V190) {
+ rs->ti->error = "Unable to assemble array: Unknown flag(s) in compatible feature flags";
+ return -EINVAL;
+ }
+--
+2.7.4
+
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
deleted file mode 100644
index f30e32dc4..000000000
--- a/0001-drm-i915-Reorganize-WM-structs-unions-in-CRTC-state.patch
+++ /dev/null
@@ -1,227 +0,0 @@
-From 0042e1e7a03a2fb5d6c464c03ce84d55b31add11 Mon Sep 17 00:00:00 2001
-From: Matt Roper <matthew.d.roper@intel.com>
-Date: Thu, 12 May 2016 07:05:55 -0700
-Subject: [PATCH 01/17] 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 <matthew.d.roper@intel.com>
-Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
-Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-2-git-send-email-matthew.d.roper@intel.com
----
- drivers/gpu/drm/i915/intel_display.c | 2 +-
- drivers/gpu/drm/i915/intel_drv.h | 61 +++++++++++++++++++++---------------
- drivers/gpu/drm/i915/intel_pm.c | 18 +++++------
- 3 files changed, 45 insertions(+), 36 deletions(-)
-
-diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
-index d19b392..4633aec 100644
---- a/drivers/gpu/drm/i915/intel_display.c
-+++ b/drivers/gpu/drm/i915/intel_display.c
-@@ -12027,7 +12027,7 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
- }
- } else if (dev_priv->display.compute_intermediate_wm) {
- if (HAS_PCH_SPLIT(dev_priv) && INTEL_GEN(dev_priv) < 9)
-- pipe_config->wm.intermediate = pipe_config->wm.optimal.ilk;
-+ pipe_config->wm.ilk.intermediate = pipe_config->wm.ilk.optimal;
- }
-
- if (INTEL_INFO(dev)->gen >= 9) {
-diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
-index 4a24b00..5a186bf 100644
---- a/drivers/gpu/drm/i915/intel_drv.h
-+++ b/drivers/gpu/drm/i915/intel_drv.h
-@@ -405,6 +405,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;
-
-@@ -558,32 +592,7 @@ 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;
--
-- /*
-- * 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;
--
-- /*
-- * 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;
-- } wm;
-+ struct intel_crtc_wm_state wm;
-
- /* Gamma mode programmed on the pipe */
- uint32_t gamma_mode;
-diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
-index a7ef45d..4353fec 100644
---- a/drivers/gpu/drm/i915/intel_pm.c
-+++ b/drivers/gpu/drm/i915/intel_pm.c
-@@ -2309,7 +2309,7 @@ static int ilk_compute_pipe_wm(struct intel_crtc_state *cstate)
- int level, max_level = ilk_wm_max_level(dev), usable_level;
- struct ilk_wm_maximums max;
-
-- pipe_wm = &cstate->wm.optimal.ilk;
-+ pipe_wm = &cstate->wm.ilk.optimal;
-
- for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
- struct intel_plane_state *ps;
-@@ -2391,7 +2391,7 @@ static int ilk_compute_intermediate_wm(struct drm_device *dev,
- struct intel_crtc *intel_crtc,
- struct intel_crtc_state *newstate)
- {
-- struct intel_pipe_wm *a = &newstate->wm.intermediate;
-+ struct intel_pipe_wm *a = &newstate->wm.ilk.intermediate;
- struct intel_pipe_wm *b = &intel_crtc->wm.active.ilk;
- int level, max_level = ilk_wm_max_level(dev);
-
-@@ -2400,7 +2400,7 @@ static int ilk_compute_intermediate_wm(struct drm_device *dev,
- * currently active watermarks to get values that are safe both before
- * and after the vblank.
- */
-- *a = newstate->wm.optimal.ilk;
-+ *a = newstate->wm.ilk.optimal;
- a->pipe_enabled |= b->pipe_enabled;
- a->sprites_enabled |= b->sprites_enabled;
- a->sprites_scaled |= b->sprites_scaled;
-@@ -2429,7 +2429,7 @@ static int ilk_compute_intermediate_wm(struct drm_device *dev,
- * If our intermediate WM are identical to the final WM, then we can
- * omit the post-vblank programming; only update if it's different.
- */
-- if (memcmp(a, &newstate->wm.optimal.ilk, sizeof(*a)) == 0)
-+ if (memcmp(a, &newstate->wm.ilk.optimal, sizeof(*a)) == 0)
- newstate->wm.need_postvbl_update = false;
-
- return 0;
-@@ -3678,7 +3678,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 */
-@@ -3757,7 +3757,7 @@ static void ilk_initial_watermarks(struct intel_crtc_state *cstate)
- struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
-
- mutex_lock(&dev_priv->wm.wm_mutex);
-- intel_crtc->wm.active.ilk = cstate->wm.intermediate;
-+ intel_crtc->wm.active.ilk = cstate->wm.ilk.intermediate;
- ilk_program_watermarks(dev_priv);
- mutex_unlock(&dev_priv->wm.wm_mutex);
- }
-@@ -3769,7 +3769,7 @@ static void ilk_optimize_watermarks(struct intel_crtc_state *cstate)
-
- mutex_lock(&dev_priv->wm.wm_mutex);
- if (cstate->wm.need_postvbl_update) {
-- intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk;
-+ intel_crtc->wm.active.ilk = cstate->wm.ilk.optimal;
- ilk_program_watermarks(dev_priv);
- }
- mutex_unlock(&dev_priv->wm.wm_mutex);
-@@ -3826,7 +3826,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;
-@@ -3892,7 +3892,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-selinux-Only-apply-bounds-checking-to-source-types.patch b/0001-selinux-Only-apply-bounds-checking-to-source-types.patch
deleted file mode 100644
index dcc9e6b2b..000000000
--- a/0001-selinux-Only-apply-bounds-checking-to-source-types.patch
+++ /dev/null
@@ -1,203 +0,0 @@
-From 7ea59202db8d20806d9ae552acd1875c3a978bcc Mon Sep 17 00:00:00 2001
-From: Stephen Smalley <sds@tycho.nsa.gov>
-Date: Mon, 23 May 2016 10:54:11 -0400
-Subject: [PATCH] selinux: Only apply bounds checking to source types
-
-The current bounds checking of both source and target types
-requires allowing any domain that has access to the child
-domain to also have the same permissions to the parent, which
-is undesirable. Drop the target bounds checking.
-
-KaiGai Kohei originally removed all use of target bounds in
-commit 7d52a155e38d ("selinux: remove dead code in
-type_attribute_bounds_av()") but this was reverted in
-commit 2ae3ba39389b ("selinux: libsepol: remove dead code in
-check_avtab_hierarchy_callback()") because it would have
-required explicitly allowing the parent any permissions
-to the child that the child is allowed to itself.
-
-This change in contrast retains the logic for the case where both
-source and target types are bounded, thereby allowing access
-if the parent of the source is allowed the corresponding
-permissions to the parent of the target. Further, this change
-reworks the logic such that we only perform a single computation
-for each case and there is no ambiguity as to how to resolve
-a bounds violation.
-
-Under the new logic, if the source type and target types are both
-bounded, then the parent of the source type must be allowed the same
-permissions to the parent of the target type. If only the source
-type is bounded, then the parent of the source type must be allowed
-the same permissions to the target type.
-
-Examples of the new logic and comparisons with the old logic:
-1. If we have:
- typebounds A B;
-then:
- allow B self:process <permissions>;
-will satisfy the bounds constraint iff:
- allow A self:process <permissions>;
-is also allowed in policy.
-
-Under the old logic, the allow rule on B satisfies the
-bounds constraint if any of the following three are allowed:
- allow A B:process <permissions>; or
- allow B A:process <permissions>; or
- allow A self:process <permissions>;
-However, either of the first two ultimately require the third to
-satisfy the bounds constraint under the old logic, and therefore
-this degenerates to the same result (but is more efficient - we only
-need to perform one compute_av call).
-
-2. If we have:
- typebounds A B;
- typebounds A_exec B_exec;
-then:
- allow B B_exec:file <permissions>;
-will satisfy the bounds constraint iff:
- allow A A_exec:file <permissions>;
-is also allowed in policy.
-
-This is essentially the same as #1; it is merely included as
-an example of dealing with object types related to a bounded domain
-in a manner that satisfies the bounds relationship. Note that
-this approach is preferable to leaving B_exec unbounded and having:
- allow A B_exec:file <permissions>;
-in policy because that would allow B's entrypoints to be used to
-enter A. Similarly for _tmp or other related types.
-
-3. If we have:
- typebounds A B;
-and an unbounded type T, then:
- allow B T:file <permissions>;
-will satisfy the bounds constraint iff:
- allow A T:file <permissions>;
-is allowed in policy.
-
-The old logic would have been identical for this example.
-
-4. If we have:
- typebounds A B;
-and an unbounded domain D, then:
- allow D B:unix_stream_socket <permissions>;
-is not subject to any bounds constraints under the new logic
-because D is not bounded. This is desirable so that we can
-allow a domain to e.g. connectto a child domain without having
-to allow it to do the same to its parent.
-
-The old logic would have required:
- allow D A:unix_stream_socket <permissions>;
-to also be allowed in policy.
-
-Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
-[PM: re-wrapped description to appease checkpatch.pl]
-Signed-off-by: Paul Moore <paul@paul-moore.com>
----
- security/selinux/ss/services.c | 70 +++++++++++++-----------------------------
- 1 file changed, 22 insertions(+), 48 deletions(-)
-
-diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
-index 89df646..082b20c 100644
---- a/security/selinux/ss/services.c
-+++ b/security/selinux/ss/services.c
-@@ -543,7 +543,7 @@ static void type_attribute_bounds_av(struct context *scontext,
- struct av_decision *avd)
- {
- struct context lo_scontext;
-- struct context lo_tcontext;
-+ struct context lo_tcontext, *tcontextp = tcontext;
- struct av_decision lo_avd;
- struct type_datum *source;
- struct type_datum *target;
-@@ -553,67 +553,41 @@ static void type_attribute_bounds_av(struct context *scontext,
- scontext->type - 1);
- BUG_ON(!source);
-
-+ if (!source->bounds)
-+ return;
-+
- target = flex_array_get_ptr(policydb.type_val_to_struct_array,
- tcontext->type - 1);
- BUG_ON(!target);
-
-- if (source->bounds) {
-- memset(&lo_avd, 0, sizeof(lo_avd));
--
-- memcpy(&lo_scontext, scontext, sizeof(lo_scontext));
-- lo_scontext.type = source->bounds;
-+ memset(&lo_avd, 0, sizeof(lo_avd));
-
-- context_struct_compute_av(&lo_scontext,
-- tcontext,
-- tclass,
-- &lo_avd,
-- NULL);
-- if ((lo_avd.allowed & avd->allowed) == avd->allowed)
-- return; /* no masked permission */
-- masked = ~lo_avd.allowed & avd->allowed;
-- }
-+ memcpy(&lo_scontext, scontext, sizeof(lo_scontext));
-+ lo_scontext.type = source->bounds;
-
- if (target->bounds) {
-- memset(&lo_avd, 0, sizeof(lo_avd));
--
- memcpy(&lo_tcontext, tcontext, sizeof(lo_tcontext));
- lo_tcontext.type = target->bounds;
--
-- context_struct_compute_av(scontext,
-- &lo_tcontext,
-- tclass,
-- &lo_avd,
-- NULL);
-- if ((lo_avd.allowed & avd->allowed) == avd->allowed)
-- return; /* no masked permission */
-- masked = ~lo_avd.allowed & avd->allowed;
-+ tcontextp = &lo_tcontext;
- }
-
-- if (source->bounds && target->bounds) {
-- memset(&lo_avd, 0, sizeof(lo_avd));
-- /*
-- * lo_scontext and lo_tcontext are already
-- * set up.
-- */
-+ context_struct_compute_av(&lo_scontext,
-+ tcontextp,
-+ tclass,
-+ &lo_avd,
-+ NULL);
-
-- context_struct_compute_av(&lo_scontext,
-- &lo_tcontext,
-- tclass,
-- &lo_avd,
-- NULL);
-- if ((lo_avd.allowed & avd->allowed) == avd->allowed)
-- return; /* no masked permission */
-- masked = ~lo_avd.allowed & avd->allowed;
-- }
-+ masked = ~lo_avd.allowed & avd->allowed;
-
-- if (masked) {
-- /* mask violated permissions */
-- avd->allowed &= ~masked;
-+ if (likely(!masked))
-+ return; /* no masked permission */
-
-- /* audit masked permissions */
-- security_dump_masked_av(scontext, tcontext,
-- tclass, masked, "bounds");
-- }
-+ /* mask violated permissions */
-+ avd->allowed &= ~masked;
-+
-+ /* audit masked permissions */
-+ security_dump_masked_av(scontext, tcontext,
-+ tclass, masked, "bounds");
- }
-
- /*
---
-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
deleted file mode 100644
index f9eecb97a..000000000
--- a/0002-drm-i915-Rename-s-skl_compute_pipe_wm-skl_build_pipe.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-From 4d428f0fd6aaaa75382885d897900f619b2dad35 Mon Sep 17 00:00:00 2001
-From: Fedora Kernel Team <kernel-team@fedoraproject.org>
-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 <matthew.d.roper@intel.com>
-AuthorDate: Thu May 12 07:05:56 2016 -0700
-Commit: Matt Roper <matthew.d.roper@intel.com>
-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 <matthew.d.roper@intel.com>
- Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
- 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/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
deleted file mode 100644
index 9a9366c1c..000000000
--- a/0003-drm-i915-gen9-Cache-plane-data-rates-in-CRTC-state.patch
+++ /dev/null
@@ -1,214 +0,0 @@
-From 0206aec944641c69815562407b73b6f9df22f041 Mon Sep 17 00:00:00 2001
-From: Fedora Kernel Team <kernel-team@fedoraproject.org>
-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 <matthew.d.roper@intel.com>
-AuthorDate: Thu May 12 07:05:57 2016 -0700
-Commit: Matt Roper <matthew.d.roper@intel.com>
-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 <matthew.d.roper@intel.com>
- Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
- 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/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
deleted file mode 100644
index 3a2b0aa1c..000000000
--- a/0004-drm-i915-gen9-Allow-calculation-of-data-rate-for-in-.patch
+++ /dev/null
@@ -1,141 +0,0 @@
-From a75a3c793e2cd3e7648597f2c77d87453f520f31 Mon Sep 17 00:00:00 2001
-From: Fedora Kernel Team <kernel-team@fedoraproject.org>
-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 <matthew.d.roper@intel.com>
-AuthorDate: Thu May 12 07:05:58 2016 -0700
-Commit: Matt Roper <matthew.d.roper@intel.com>
-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 <matthew.d.roper@intel.com>
- Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
- 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/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
deleted file mode 100644
index 7b1fcb144..000000000
--- a/0005-drm-i915-gen9-Store-plane-minimum-blocks-in-CRTC-wm-.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From cd21ce996b94fd149b3487398e5250e9f0cc8811 Mon Sep 17 00:00:00 2001
-From: Fedora Kernel Team <kernel-team@fedoraproject.org>
-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 <matthew.d.roper@intel.com>
-AuthorDate: Thu May 12 07:05:59 2016 -0700
-Commit: Matt Roper <matthew.d.roper@intel.com>
-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 <maarten.lankhorst@linux.intel.com>
- Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
- Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
- 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/0006-drm-i915-Track-whether-an-atomic-transaction-changes.patch b/0006-drm-i915-Track-whether-an-atomic-transaction-changes.patch
deleted file mode 100644
index 7320abf6d..000000000
--- a/0006-drm-i915-Track-whether-an-atomic-transaction-changes.patch
+++ /dev/null
@@ -1,68 +0,0 @@
-From 00edb23bcefa3ad6931f2a2855fe0801a55523f7 Mon Sep 17 00:00:00 2001
-From: Fedora Kernel Team <kernel-team@fedoraproject.org>
-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 <matthew.d.roper@intel.com>
-AuthorDate: Thu May 12 07:06:00 2016 -0700
-Commit: Matt Roper <matthew.d.roper@intel.com>
-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 <matthew.d.roper@intel.com>
- Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
- 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
deleted file mode 100644
index deb90fb01..000000000
--- a/0007-drm-i915-gen9-Allow-skl_allocate_pipe_ddb-to-operate.patch
+++ /dev/null
@@ -1,352 +0,0 @@
-From 99dd9c3733696d4a2536b21988c9b1b8f5195c5b Mon Sep 17 00:00:00 2001
-From: Fedora Kernel Team <kernel-team@fedoraproject.org>
-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 <matthew.d.roper@intel.com>
-AuthorDate: Thu May 12 07:06:01 2016 -0700
-Commit: Matt Roper <matthew.d.roper@intel.com>
-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 <maarten.lankhorst@linux.intel.com>
- Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
- Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
- 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
deleted file mode 100644
index 9131a60da..000000000
--- a/0008-drm-i915-Add-distrust_bios_wm-flag-to-dev_priv-v2.patch
+++ /dev/null
@@ -1,84 +0,0 @@
-From 7207eecfcb3095442bce30227b551003edc7b908 Mon Sep 17 00:00:00 2001
-From: Matt Roper <matthew.d.roper@intel.com>
-Date: Thu, 12 May 2016 07:06:02 -0700
-Subject: [PATCH 08/17] 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 <maarten.lankhorst@linux.intel.com>
-Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
-Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
-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 611c128..e21960d 100644
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -1981,6 +1981,13 @@ struct drm_i915_private {
- * cstate->wm.need_postvbl_update.
- */
- struct mutex wm_mutex;
-+
-+ /*
-+ * 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 f26d1c5..a9d2e30 100644
---- a/drivers/gpu/drm/i915/intel_display.c
-+++ b/drivers/gpu/drm/i915/intel_display.c
-@@ -13621,6 +13621,7 @@ static int intel_atomic_commit(struct drm_device *dev,
-
- drm_atomic_helper_swap_state(dev, state);
- dev_priv->wm.config = intel_state->wm_config;
-+ dev_priv->wm.distrust_bios_wm = false;
- intel_shared_dpll_commit(state);
-
- if (intel_state->modeset) {
-diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
-index f009d43..a49faa7 100644
---- a/drivers/gpu/drm/i915/intel_pm.c
-+++ b/drivers/gpu/drm/i915/intel_pm.c
-@@ -4026,6 +4026,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
deleted file mode 100644
index 80cdacf9a..000000000
--- a/0009-drm-i915-gen9-Compute-DDB-allocation-at-atomic-check.patch
+++ /dev/null
@@ -1,244 +0,0 @@
-From fbf53d8f1b7d1bcea1411f1f2cd0df6a6cc95332 Mon Sep 17 00:00:00 2001
-From: Matt Roper <matthew.d.roper@intel.com>
-Date: Thu, 12 May 2016 07:06:03 -0700
-Subject: [PATCH 09/17] 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 <maarten.lankhorst@linux.intel.com>
-Cc: Lyude Paul <cpaul@redhat.com>
-Cc: Radhakrishna Sripada <radhakrishna.sripada@intel.com>
-Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
-Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
-Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
-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 e21960d..b908a41 100644
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -339,6 +339,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, \
-@@ -594,6 +598,7 @@ struct drm_i915_display_funcs {
- struct intel_crtc_state *newstate);
- void (*initial_watermarks)(struct intel_crtc_state *cstate);
- void (*optimize_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 a9d2e30..ecad0ef 100644
---- a/drivers/gpu/drm/i915/intel_display.c
-+++ b/drivers/gpu/drm/i915/intel_display.c
-@@ -13342,6 +13342,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;
-@@ -13371,6 +13372,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);
- }
-
- /**
-@@ -13739,6 +13744,19 @@ static int intel_atomic_commit(struct drm_device *dev,
- intel_modeset_verify_crtc(crtc, old_crtc_state, crtc->state);
- }
-
-+ /*
-+ * 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 d19e83e..2218290 100644
---- a/drivers/gpu/drm/i915/intel_drv.h
-+++ b/drivers/gpu/drm/i915/intel_drv.h
-@@ -312,6 +312,9 @@ struct intel_atomic_state {
- * don't bother calculating intermediate watermarks.
- */
- bool skip_intermediate_wm;
-+
-+ /* 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 a49faa7..cfa4f80 100644
---- a/drivers/gpu/drm/i915/intel_pm.c
-+++ b/drivers/gpu/drm/i915/intel_pm.c
-@@ -3812,6 +3812,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);
-@@ -7384,6 +7462,7 @@ void intel_init_pm(struct drm_device *dev)
- if (INTEL_INFO(dev)->gen >= 9) {
- skl_setup_wm_latency(dev);
- 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
deleted file mode 100644
index 26f7e750c..000000000
--- a/0010-drm-i915-gen9-Drop-re-allocation-of-DDB-at-atomic-co.patch
+++ /dev/null
@@ -1,379 +0,0 @@
-From a9abdc6767855e1668301a1dcc4b5fa8bed1ddfa Mon Sep 17 00:00:00 2001
-From: Matt Roper <matthew.d.roper@intel.com>
-Date: Thu, 12 May 2016 07:06:04 -0700
-Subject: [PATCH 10/17] 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 <matthew.d.roper@intel.com>
-Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
-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 ecad0ef..4db10d7 100644
---- a/drivers/gpu/drm/i915/intel_display.c
-+++ b/drivers/gpu/drm/i915/intel_display.c
-@@ -13627,6 +13627,7 @@ static int intel_atomic_commit(struct drm_device *dev,
- drm_atomic_helper_swap_state(dev, state);
- dev_priv->wm.config = intel_state->wm_config;
- dev_priv->wm.distrust_bios_wm = false;
-+ dev_priv->wm.skl_results.ddb = intel_state->ddb;
- intel_shared_dpll_commit(state);
-
- if (intel_state->modeset) {
-@@ -13744,19 +13745,6 @@ static int intel_atomic_commit(struct drm_device *dev,
- intel_modeset_verify_crtc(crtc, old_crtc_state, crtc->state);
- }
-
-- /*
-- * 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 cfa4f80..0f0d4e1 100644
---- a/drivers/gpu/drm/i915/intel_pm.c
-+++ b/drivers/gpu/drm/i915/intel_pm.c
-@@ -2849,7 +2849,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 */)
- {
-@@ -2857,24 +2856,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
-@@ -2883,50 +2880,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)
-@@ -3025,62 +2995,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 */
-@@ -3104,8 +3045,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;
-@@ -3119,6 +3058,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]));
-@@ -3126,8 +3068,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]));
-@@ -3139,53 +3080,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++) {
-@@ -3736,7 +3655,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)))
-@@ -3800,16 +3718,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
deleted file mode 100644
index 9f839dfa2..000000000
--- a/0011-drm-i915-gen9-Calculate-plane-WM-s-from-state.patch
+++ /dev/null
@@ -1,91 +0,0 @@
-From eacd0ecb98a93e3ff83a4479eadeb9cda05d3579 Mon Sep 17 00:00:00 2001
-From: Fedora Kernel Team <kernel-team@fedoraproject.org>
-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 <matthew.d.roper@intel.com>
-AuthorDate: Thu May 12 07:06:05 2016 -0700
-Commit: Matt Roper <matthew.d.roper@intel.com>
-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 <matthew.d.roper@intel.com>
- Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
- 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
deleted file mode 100644
index d0cb50bac..000000000
--- a/0012-drm-i915-gen9-Allow-watermark-calculation-on-in-flig.patch
+++ /dev/null
@@ -1,156 +0,0 @@
-From c3d2591095045a8230361d55fadf15ce5dc9127d Mon Sep 17 00:00:00 2001
-From: Fedora Kernel Team <kernel-team@fedoraproject.org>
-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 <matthew.d.roper@intel.com>
-AuthorDate: Thu May 12 07:06:06 2016 -0700
-Commit: Matt Roper <matthew.d.roper@intel.com>
-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 <matthew.d.roper@intel.com>
- Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
- 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
deleted file mode 100644
index 959860f95..000000000
--- a/0013-drm-i915-gen9-Use-a-bitmask-to-track-dirty-pipe-wate.patch
+++ /dev/null
@@ -1,91 +0,0 @@
-From b43247a865f73fa3b73a878236b5055bfb864169 Mon Sep 17 00:00:00 2001
-From: Fedora Kernel Team <kernel-team@fedoraproject.org>
-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 <matthew.d.roper@intel.com>
-AuthorDate: Thu May 12 07:06:07 2016 -0700
-Commit: Matt Roper <matthew.d.roper@intel.com>
-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 <matthew.d.roper@intel.com>
- Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
- 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
deleted file mode 100644
index a868ebd1f..000000000
--- a/0014-drm-i915-gen9-Propagate-watermark-calculation-failur.patch
+++ /dev/null
@@ -1,254 +0,0 @@
-From 2dda82bdd570042820241e71c02ea36081835f67 Mon Sep 17 00:00:00 2001
-From: Fedora Kernel Team <kernel-team@fedoraproject.org>
-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 <matthew.d.roper@intel.com>
-AuthorDate: Thu May 12 07:06:08 2016 -0700
-Commit: Matt Roper <matthew.d.roper@intel.com>
-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 <matthew.d.roper@intel.com>
- Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
- 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
deleted file mode 100644
index 691b6b985..000000000
--- a/0015-drm-i915-gen9-Calculate-watermarks-during-atomic-che.patch
+++ /dev/null
@@ -1,302 +0,0 @@
-From 664f87c5bfcc7798bd5b16e14792f1e9ba2956ea Mon Sep 17 00:00:00 2001
-From: Matt Roper <matthew.d.roper@intel.com>
-Date: Thu, 12 May 2016 15:11:40 -0700
-Subject: [PATCH 15/17] 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 <maarten.lankhorst@linux.intel.com>
-Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
-Tested-by: Daniel Stone <daniels@collabora.com>
-Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
-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 | 2 +-
- drivers/gpu/drm/i915/intel_pm.c | 140 +++++++++++++----------------------
- 3 files changed, 54 insertions(+), 90 deletions(-)
-
-diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
-index 2190bac..a75daac 100644
---- a/drivers/gpu/drm/i915/intel_display.c
-+++ b/drivers/gpu/drm/i915/intel_display.c
-@@ -13627,7 +13627,7 @@ static int intel_atomic_commit(struct drm_device *dev,
- drm_atomic_helper_swap_state(dev, state);
- dev_priv->wm.config = intel_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;
- intel_shared_dpll_commit(state);
-
- if (intel_state->modeset) {
-diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
-index 2218290..ab0be7a 100644
---- a/drivers/gpu/drm/i915/intel_drv.h
-+++ b/drivers/gpu/drm/i915/intel_drv.h
-@@ -314,7 +314,7 @@ struct intel_atomic_state {
- bool skip_intermediate_wm;
-
- /* Gen9+ only */
-- struct skl_ddb_allocation ddb;
-+ struct skl_wm_values wm_results;
- };
-
- struct intel_plane_state {
-diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
-index 342aa66..b072417 100644
---- a/drivers/gpu/drm/i915/intel_pm.c
-+++ b/drivers/gpu/drm/i915/intel_pm.c
-@@ -3221,23 +3221,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,
-@@ -3533,6 +3516,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]);
-
-@@ -3716,66 +3701,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)
- {
-@@ -3783,6 +3711,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;
-
-@@ -3808,8 +3737,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;
-@@ -3818,7 +3749,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;
- }
-@@ -3831,8 +3762,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
-@@ -3847,10 +3781,45 @@ 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;
-+
-+ intel_cstate->update_wm_pre = true;
-+ skl_compute_wm_results(crtc->dev, pipe_wm, results, intel_crtc);
-+ }
-+
- return 0;
- }
-
-@@ -3862,26 +3831,21 @@ 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;
-+
-+ mutex_lock(&dev_priv->wm.wm_mutex);
-
-- skl_update_other_pipe_wm(dev, crtc, results);
- skl_write_wm_values(dev_priv, results);
- skl_flush_wm_values(dev_priv, results);
-
- /* store the new configuration */
- dev_priv->wm.skl_hw = *results;
-+
-+ mutex_unlock(&dev_priv->wm.wm_mutex);
- }
-
- static void ilk_compute_wm_config(struct drm_device *dev,
---
-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
deleted file mode 100644
index fb59572bd..000000000
--- a/0016-drm-i915-gen9-Reject-display-updates-that-exceed-wm-.patch
+++ /dev/null
@@ -1,63 +0,0 @@
-From 7731c187f1f77501b7dddf419a06c1b42b0f1388 Mon Sep 17 00:00:00 2001
-From: Fedora Kernel Team <kernel-team@fedoraproject.org>
-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 <matthew.d.roper@intel.com>
-AuthorDate: Thu May 12 07:06:10 2016 -0700
-Commit: Matt Roper <matthew.d.roper@intel.com>
-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 <cpaul@redhat.com>
- Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
- Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
- 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
deleted file mode 100644
index 73a6dacc6..000000000
--- a/0017-drm-i915-Remove-wm_config-from-dev_priv-intel_atomic.patch
+++ /dev/null
@@ -1,105 +0,0 @@
-From 73a35468564f4e47deade0a4a5eb7ec289611ebc Mon Sep 17 00:00:00 2001
-From: Matt Roper <matthew.d.roper@intel.com>
-Date: Thu, 12 May 2016 07:06:11 -0700
-Subject: [PATCH 17/17] 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 <matthew.d.roper@intel.com>
-Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
-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 e7bde72..608f8e4 100644
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -1961,9 +1961,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 a75daac..9c109c6 100644
---- a/drivers/gpu/drm/i915/intel_display.c
-+++ b/drivers/gpu/drm/i915/intel_display.c
-@@ -13343,35 +13343,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)
-@@ -13625,7 +13596,6 @@ static int intel_atomic_commit(struct drm_device *dev,
- }
-
- drm_atomic_helper_swap_state(dev, state);
-- dev_priv->wm.config = intel_state->wm_config;
- dev_priv->wm.distrust_bios_wm = false;
- dev_priv->wm.skl_results = intel_state->wm_results;
- intel_shared_dpll_commit(state);
-@@ -15405,7 +15375,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 ab0be7a..8d73c20 100644
---- a/drivers/gpu/drm/i915/intel_drv.h
-+++ b/drivers/gpu/drm/i915/intel_drv.h
-@@ -305,7 +305,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;
-
- /*
- * Current watermarks can't be trusted during hardware readout, so
---
-2.7.4
-
diff --git a/ARM-OMAP4-Fix-crashes.patch b/ARM-OMAP4-Fix-crashes.patch
new file mode 100644
index 000000000..57e56e507
--- /dev/null
+++ b/ARM-OMAP4-Fix-crashes.patch
@@ -0,0 +1,97 @@
+From patchwork Wed Oct 26 15:17:01 2016
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [3/5] ARM: OMAP4+: Fix bad fallthrough for cpuidle
+From: Tony Lindgren <tony@atomide.com>
+X-Patchwork-Id: 9397501
+Message-Id: <20161026151703.24730-4-tony@atomide.com>
+To: linux-omap@vger.kernel.org
+Cc: Nishanth Menon <nm@ti.com>, Dmitry Lifshitz <lifshitz@compulab.co.il>,
+ Dave Gerlach <d-gerlach@ti.com>,
+ Enric Balletbo Serra <eballetbo@gmail.com>,
+ "Dr . H . Nikolaus Schaller" <hns@goldelico.com>,
+ Pau Pajuel <ppajuel@gmail.com>, Grazvydas Ignotas <notasas@gmail.com>,
+ Benoit Cousson <bcousson@baylibre.com>,
+ Santosh Shilimkar <ssantosh@kernel.org>,
+ Javier Martinez Canillas <javier@dowhile0.org>,
+ Robert Nelson <robertcnelson@gmail.com>,
+ Marek Belisko <marek@goldelico.com>, linux-arm-kernel@lists.infradead.org
+Date: Wed, 26 Oct 2016 08:17:01 -0700
+
+We don't want to fall through to a bunch of errors for retention
+if PM_OMAP4_CPU_OSWR_DISABLE is not configured for a SoC.
+
+Fixes: 6099dd37c669 ("ARM: OMAP5 / DRA7: Enable CPU RET on suspend")
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+---
+ arch/arm/mach-omap2/omap-mpuss-lowpower.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
++++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+@@ -244,10 +244,9 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
+ save_state = 1;
+ break;
+ case PWRDM_POWER_RET:
+- if (IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE)) {
++ if (IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE))
+ save_state = 0;
+- break;
+- }
++ break;
+ default:
+ /*
+ * CPUx CSWR is invalid hardware state. Also CPUx OSWR
+From 5a78ff7bf7e25191144b550961001bbf6c734da4 Mon Sep 17 00:00:00 2001
+From: Peter Chen <peter.chen@nxp.com>
+Date: Thu, 11 Aug 2016 17:44:54 +0800
+Subject: [PATCH 04152/16809] Revert "gpu: drm: omapdrm: dss-of: add missing
+ of_node_put after calling of_parse_phandle"
+
+This reverts
+commit 2ab9f5879162499e1c4e48613287e3f59e593c4f
+Author: Peter Chen <peter.chen@nxp.com>
+Date: Fri Jul 15 11:17:03 2016 +0800
+ gpu: drm: omapdrm: dss-of: add missing of_node_put after calling of_parse_phandle
+
+The of_get_next_parent will drop refcount on the passed node, so the reverted
+patch is wrong, thanks for Tomi Valkeinen points it.
+
+Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
+Signed-off-by: Peter Chen <peter.chen@nxp.com>
+Acked-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
+Signed-off-by: Sean Paul <seanpaul@chromium.org>
+Link: http://patchwork.freedesktop.org/patch/msgid/1470908694-16362-1-git-send-email-peter.chen@nxp.com
+---
+ drivers/gpu/drm/omapdrm/dss/dss-of.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/omapdrm/dss/dss-of.c b/drivers/gpu/drm/omapdrm/dss/dss-of.c
+index e256d87..dfd4e96 100644
+--- a/drivers/gpu/drm/omapdrm/dss/dss-of.c
++++ b/drivers/gpu/drm/omapdrm/dss/dss-of.c
+@@ -125,16 +125,15 @@ u32 dss_of_port_get_port_number(struct device_node *port)
+
+ static struct device_node *omapdss_of_get_remote_port(const struct device_node *node)
+ {
+- struct device_node *np, *np_parent;
++ struct device_node *np;
+
+ np = of_parse_phandle(node, "remote-endpoint", 0);
+ if (!np)
+ return NULL;
+
+- np_parent = of_get_next_parent(np);
+- of_node_put(np);
++ np = of_get_next_parent(np);
+
+- return np_parent;
++ return np;
+ }
+
+ struct device_node *
+--
+2.9.3
+
diff --git a/Add-EFI-signature-data-types.patch b/Add-EFI-signature-data-types.patch
index 094c5a34c..23402354e 100644
--- a/Add-EFI-signature-data-types.patch
+++ b/Add-EFI-signature-data-types.patch
@@ -18,15 +18,12 @@ diff --git a/include/linux/efi.h b/include/linux/efi.h
index 8cb38cfcba74..8c274b4ea8e6 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
-@@ -647,6 +647,12 @@ void efi_native_runtime_setup(void);
- EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, \
- 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f)
+@@ -647,6 +647,9 @@ void efi_native_runtime_setup(void);
+ #define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95)
+ #define LINUX_EFI_LOADER_ENTRY_GUID EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f)
-+#define EFI_CERT_SHA256_GUID \
-+ EFI_GUID( 0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 )
-+
-+#define EFI_CERT_X509_GUID \
-+ EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 )
++#define EFI_CERT_SHA256_GUID EFI_GUID(0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28)
++#define EFI_CERT_X509_GUID EFI_GUID(0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72)
+
typedef struct {
efi_guid_t guid;
diff --git a/Add-secure_modules-call.patch b/Add-secure_modules-call.patch
index 5c272a983..1cbf3afd9 100644
--- a/Add-secure_modules-call.patch
+++ b/Add-secure_modules-call.patch
@@ -1,7 +1,7 @@
-From 0f6eec5ca124baf1372fb4edeacd11a002378f5e Mon Sep 17 00:00:00 2001
+From 3213f1513a744fb21b6b9e4d4f2650a204855b3e Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Fri, 9 Aug 2013 17:58:15 -0400
-Subject: [PATCH 01/20] Add secure_modules() call
+Subject: [PATCH] Add secure_modules() call
Provide a single call to allow kernel code to determine whether the system
has been configured to either disable module loading entirely or to load
@@ -17,10 +17,10 @@ Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
2 files changed, 16 insertions(+)
diff --git a/include/linux/module.h b/include/linux/module.h
-index 3daf2b3..082298a 100644
+index 0c3207d..05bd6c9 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
-@@ -655,6 +655,8 @@ static inline bool is_livepatch_module(struct module *mod)
+@@ -641,6 +641,8 @@ static inline bool is_livepatch_module(struct module *mod)
}
#endif /* CONFIG_LIVEPATCH */
@@ -28,8 +28,8 @@ index 3daf2b3..082298a 100644
+
#else /* !CONFIG_MODULES... */
- /* Given an address, look for it in the exception tables. */
-@@ -771,6 +773,10 @@ static inline bool module_requested_async_probing(struct module *module)
+ static inline struct module *__module_address(unsigned long addr)
+@@ -750,6 +752,10 @@ static inline bool module_requested_async_probing(struct module *module)
return false;
}
@@ -41,10 +41,10 @@ index 3daf2b3..082298a 100644
#ifdef CONFIG_SYSFS
diff --git a/kernel/module.c b/kernel/module.c
-index 5f71aa6..3c38496 100644
+index 529efae..0332fdd 100644
--- a/kernel/module.c
+++ b/kernel/module.c
-@@ -4199,3 +4199,13 @@ void module_layout(struct module *mod,
+@@ -4279,3 +4279,13 @@ void module_layout(struct module *mod,
}
EXPORT_SYMBOL(module_layout);
#endif
@@ -59,5 +59,5 @@ index 5f71aa6..3c38496 100644
+}
+EXPORT_SYMBOL(secure_modules);
--
-2.5.5
+2.9.2
diff --git a/AllWinner-net-emac.patch b/AllWinner-net-emac.patch
new file mode 100644
index 000000000..7bcaecf4a
--- /dev/null
+++ b/AllWinner-net-emac.patch
@@ -0,0 +1,2700 @@
+From e90ba04ee5efbed6fc17dfa7f62702f268fc1bc4 Mon Sep 17 00:00:00 2001
+From: Corentin LABBE <clabbe.montjoie@gmail.com>
+Date: Fri, 7 Oct 2016 10:25:48 +0200
+Subject: [PATCH 1/9] ethernet: add sun8i-emac driver
+
+This patch add support for sun8i-emac ethernet MAC hardware.
+It could be found in Allwinner H3/A83T/A64 SoCs.
+
+It supports 10/100/1000 Mbit/s speed with half/full duplex.
+It can use an internal PHY (MII 10/100) or an external PHY
+via RGMII/RMII.
+
+Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
+---
+ drivers/net/ethernet/allwinner/Kconfig | 13 +
+ drivers/net/ethernet/allwinner/Makefile | 1 +
+ drivers/net/ethernet/allwinner/sun8i-emac.c | 2266 +++++++++++++++++++++++++++
+ 3 files changed, 2280 insertions(+)
+ create mode 100644 drivers/net/ethernet/allwinner/sun8i-emac.c
+
+diff --git a/drivers/net/ethernet/allwinner/Kconfig b/drivers/net/ethernet/allwinner/Kconfig
+index 47da7e7..060569c 100644
+--- a/drivers/net/ethernet/allwinner/Kconfig
++++ b/drivers/net/ethernet/allwinner/Kconfig
+@@ -33,4 +33,17 @@ config SUN4I_EMAC
+ To compile this driver as a module, choose M here. The module
+ will be called sun4i-emac.
+
++config SUN8I_EMAC
++ tristate "Allwinner sun8i EMAC support"
++ depends on ARCH_SUNXI || COMPILE_TEST
++ depends on OF
++ select MII
++ select PHYLIB
++ ---help---
++ This driver support the sun8i EMAC ethernet driver present on
++ H3/A83T/A64 Allwinner SoCs.
++
++ To compile this driver as a module, choose M here. The module
++ will be called sun8i-emac.
++
+ endif # NET_VENDOR_ALLWINNER
+diff --git a/drivers/net/ethernet/allwinner/Makefile b/drivers/net/ethernet/allwinner/Makefile
+index 03129f7..8bd1693c 100644
+--- a/drivers/net/ethernet/allwinner/Makefile
++++ b/drivers/net/ethernet/allwinner/Makefile
+@@ -3,3 +3,4 @@
+ #
+
+ obj-$(CONFIG_SUN4I_EMAC) += sun4i-emac.o
++obj-$(CONFIG_SUN8I_EMAC) += sun8i-emac.o
+diff --git a/drivers/net/ethernet/allwinner/sun8i-emac.c b/drivers/net/ethernet/allwinner/sun8i-emac.c
+new file mode 100644
+index 0000000..bc74467
+--- /dev/null
++++ b/drivers/net/ethernet/allwinner/sun8i-emac.c
+@@ -0,0 +1,2266 @@
++/*
++ * sun8i-emac driver
++ *
++ * Copyright (C) 2015-2016 Corentin LABBE <clabbe.montjoie@gmail.com>
++ *
++ * This is the driver for Allwinner Ethernet MAC found in H3/A83T/A64 SoC
++ *
++ * TODO:
++ * - MAC filtering
++ * - Jumbo frame
++ * - features rx-all (NETIF_F_RXALL_BIT)
++ * - PM runtime
++ */
++#include <linux/bitops.h>
++#include <linux/clk.h>
++#include <linux/dma-mapping.h>
++#include <linux/etherdevice.h>
++#include <linux/interrupt.h>
++#include <linux/iopoll.h>
++#include <linux/mii.h>
++#include <linux/module.h>
++#include <linux/netdevice.h>
++#include <linux/of_device.h>
++#include <linux/of_mdio.h>
++#include <linux/of_net.h>
++#include <linux/phy.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/platform_device.h>
++#include <linux/reset.h>
++#include <linux/scatterlist.h>
++#include <linux/skbuff.h>
++#include <linux/mfd/syscon.h>
++#include <linux/regmap.h>
++
++#define EMAC_BASIC_CTL0 0x00
++#define EMAC_BASIC_CTL1 0x04
++#define EMAC_INT_STA 0x08
++#define EMAC_INT_EN 0x0C
++#define EMAC_TX_CTL0 0x10
++#define EMAC_TX_CTL1 0x14
++#define EMAC_TX_FLOW_CTL 0x1C
++#define EMAC_RX_CTL0 0x24
++#define EMAC_RX_CTL1 0x28
++#define EMAC_RX_FRM_FLT 0x38
++#define EMAC_MDIO_CMD 0x48
++#define EMAC_MDIO_DATA 0x4C
++#define EMAC_TX_DMA_STA 0xB0
++#define EMAC_TX_CUR_DESC 0xB4
++#define EMAC_TX_CUR_BUF 0xB8
++#define EMAC_RX_DMA_STA 0xC0
++
++#define MDIO_CMD_MII_BUSY BIT(0)
++#define MDIO_CMD_MII_WRITE BIT(1)
++#define MDIO_CMD_MII_PHY_REG_ADDR_MASK GENMASK(8, 4)
++#define MDIO_CMD_MII_PHY_REG_ADDR_SHIFT 4
++#define MDIO_CMD_MII_PHY_ADDR_MASK GENMASK(16, 12)
++#define MDIO_CMD_MII_PHY_ADDR_SHIFT 12
++
++#define EMAC_MACADDR_HI 0x50
++#define EMAC_MACADDR_LO 0x54
++
++#define EMAC_RX_DESC_LIST 0x34
++#define EMAC_TX_DESC_LIST 0x20
++
++#define EMAC_RX_DO_CRC BIT(27)
++#define EMAC_RX_STRIP_FCS BIT(28)
++
++#define LE32_BIT(x) (cpu_to_le32(BIT(x)))
++
++#define EMAC_COULD_BE_USED_BY_DMA LE32_BIT(31)
++
++/* Used in RX_CTL1*/
++#define EMAC_RX_DMA_EN BIT(30)
++#define EMAC_RX_DMA_START BIT(31)
++/* Used in TX_CTL1*/
++#define EMAC_TX_DMA_EN BIT(30)
++#define EMAC_TX_DMA_START BIT(31)
++
++/* Used in RX_CTL0 */
++#define EMAC_RX_RECEIVER_EN BIT(31)
++/* Used in TX_CTL0 */
++#define EMAC_TX_TRANSMITTER_EN BIT(31)
++
++/* Basic CTL0 */
++#define EMAC_BCTL0_FD BIT(0)
++#define EMAC_BCTL0_SPEED_10 2
++#define EMAC_BCTL0_SPEED_100 3
++#define EMAC_BCTL0_SPEED_MASK GENMASK(3, 2)
++#define EMAC_BCTL0_SPEED_SHIFT 2
++
++#define EMAC_FLOW_RX 1
++#define EMAC_FLOW_TX 2
++
++#define EMAC_TX_INT BIT(0)
++#define EMAC_TX_DMA_STOP_INT BIT(1)
++#define EMAC_TX_BUF_UA_INT BIT(2)
++#define EMAC_TX_TIMEOUT_INT BIT(3)
++#define EMAC_TX_UNDERFLOW_INT BIT(4)
++#define EMAC_TX_EARLY_INT BIT(5)
++#define EMAC_RX_INT BIT(8)
++#define EMAC_RX_BUF_UA_INT BIT(9)
++#define EMAC_RX_DMA_STOP_INT BIT(10)
++#define EMAC_RX_TIMEOUT_INT BIT(11)
++#define EMAC_RX_OVERFLOW_INT BIT(12)
++#define EMAC_RX_EARLY_INT BIT(13)
++#define EMAC_RGMII_STA_INT BIT(16)
++
++/* Bits used in frame RX status */
++#define EMAC_DSC_RX_FIRST BIT(9)
++#define EMAC_DSC_RX_LAST BIT(8)
++
++/* Bits used in frame TX ctl */
++#define EMAC_MAGIC_TX_BIT LE32_BIT(24)
++#define EMAC_TX_DO_CRC (LE32_BIT(27) | LE32_BIT(28))
++#define EMAC_DSC_TX_FIRST LE32_BIT(29)
++#define EMAC_DSC_TX_LAST LE32_BIT(30)
++#define EMAC_WANT_INT LE32_BIT(31)
++
++/* struct emac_variant - Describe an emac variant of sun8i-emac
++ * @default_syscon_value: Default value of the syscon EMAC register
++ * The default_syscon_value is also used for powering down the PHY
++ * @internal_phy: which PHY type is internal
++ * @support_mii: Does the SoC support MII
++ * @support_rmii: Does the SoC support RMII
++ * @support_rgmii: Does the SoC support RGMII
++ */
++struct emac_variant {
++ u32 default_syscon_value;
++ int internal_phy;
++ bool support_mii;
++ bool support_rmii;
++ bool support_rgmii;
++};
++
++static const struct emac_variant emac_variant_h3 = {
++ .default_syscon_value = 0x58000,
++ .internal_phy = PHY_INTERFACE_MODE_MII,
++ .support_mii = true,
++ .support_rmii = true,
++ .support_rgmii = true
++};
++
++static const struct emac_variant emac_variant_a83t = {
++ .default_syscon_value = 0,
++ .internal_phy = 0,
++ .support_mii = true,
++ .support_rgmii = true
++};
++
++static const struct emac_variant emac_variant_a64 = {
++ .default_syscon_value = 0,
++ .internal_phy = 0,
++ .support_mii = true,
++ .support_rmii = true,
++ .support_rgmii = true
++};
++
++static const char const estats_str[][ETH_GSTRING_LEN] = {
++ /* errors */
++ "rx_payload_error",
++ "rx_CRC_error",
++ "rx_phy_error",
++ "rx_length_error",
++ "rx_col_error",
++ "rx_header_error",
++ "rx_overflow_error",
++ "rx_saf_error",
++ "rx_daf_error",
++ "rx_buf_error",
++ "rx_invalid_error",
++ "tx_timeout",
++ /* misc infos */
++ "tx_stop_queue",
++ "rx_dma_ua",
++ "rx_dma_stop",
++ "tx_dma_ua",
++ "tx_dma_stop",
++ "rx_hw_csum",
++ "tx_hw_csum",
++ /* interrupts */
++ "rx_int",
++ "tx_int",
++ "tx_early_int",
++ "tx_underflow_int",
++ "tx_timeout_int",
++ "rx_early_int",
++ "rx_overflow_int",
++ "rx_timeout_int",
++ "rgmii_state_int",
++ /* debug */
++ "tx_used_desc",
++ "napi_schedule",
++ "napi_underflow",
++};
++
++struct sun8i_emac_stats {
++ u64 rx_payload_error;
++ u64 rx_crc_error;
++ u64 rx_phy_error;
++ u64 rx_length_error;
++ u64 rx_col_error;
++ u64 rx_header_error;
++ u64 rx_overflow_error;
++ u64 rx_saf_fail;
++ u64 rx_daf_fail;
++ u64 rx_buf_error;
++ u64 rx_invalid_error;
++ u64 tx_timeout;
++
++ u64 tx_stop_queue;
++ u64 rx_dma_ua;
++ u64 rx_dma_stop;
++ u64 tx_dma_ua;
++ u64 tx_dma_stop;
++ u64 rx_hw_csum;
++ u64 tx_hw_csum;
++
++ u64 rx_int;
++ u64 tx_int;
++ u64 tx_early_int;
++ u64 tx_underflow_int;
++ u64 tx_timeout_int;
++ u64 rx_early_int;
++ u64 rx_overflow_int;
++ u64 rx_timeout_int;
++ u64 rgmii_state_int;
++
++ u64 tx_used_desc;
++ u64 napi_schedule;
++ u64 napi_underflow;
++};
++
++/* The datasheet said that each descriptor can transfers up to 4096bytes
++ * But latter, a register documentation reduce that value to 2048
++ * Anyway using 2048 cause strange behaviours and even BSP driver use 2047
++ */
++#define DESC_BUF_MAX 2044
++
++/* MAGIC value for knowing if a descriptor is available or not */
++#define DCLEAN cpu_to_le32(BIT(16) | BIT(14) | BIT(12) | BIT(10) | BIT(9))
++
++/* struct dma_desc - Structure of DMA descriptor used by the hardware
++ * @status: Status of the frame written by HW, so RO for the
++ * driver (except for BIT(31) which is R/W)
++ * @ctl: Information on the frame written by the driver (INT, len,...)
++ * @buf_addr: physical address of the frame data
++ * @next: physical address of next dma_desc
++ */
++struct dma_desc {
++ __le32 status;
++ __le32 ctl;
++ __le32 buf_addr;
++ __le32 next;
++};
++
++/* Describe how data from skb are DMA mapped (used in txinfo map member) */
++#define MAP_SINGLE 1
++#define MAP_PAGE 2
++
++/* Structure for storing information about data in TX ring buffer */
++struct txinfo {
++ struct sk_buff *skb;
++ int map;
++};
++
++struct sun8i_emac_priv {
++ void __iomem *base;
++ struct regmap *regmap;
++ int irq;
++ struct device *dev;
++ struct net_device *ndev;
++ struct mii_bus *mdio;
++ struct napi_struct napi;
++ spinlock_t tx_lock;/* control the access of transmit descriptors */
++ int duplex;
++ int speed;
++ int link;
++ int phy_interface;
++ const struct emac_variant *variant;
++ struct device_node *phy_node;
++ struct device_node *mdio_node;
++ struct clk *ahb_clk;
++ struct clk *ephy_clk;
++ bool use_internal_phy;
++
++ struct reset_control *rst_mac;
++ struct reset_control *rst_ephy;
++
++ struct dma_desc *dd_rx;
++ dma_addr_t dd_rx_phy;
++ struct dma_desc *dd_tx;
++ dma_addr_t dd_tx_phy;
++ struct sk_buff **rx_skb;
++ struct txinfo *txl;
++
++ int nbdesc_tx;
++ int nbdesc_rx;
++ int tx_slot;
++ int tx_dirty;
++ int rx_dirty;
++ struct sun8i_emac_stats estats;
++ u32 msg_enable;
++ int flow_ctrl;
++ int pause;
++};
++
++static irqreturn_t sun8i_emac_dma_interrupt(int irq, void *dev_id);
++
++static void rb_inc(int *p, const int max)
++{
++ (*p)++;
++ (*p) %= max;
++}
++
++/* Locking strategy:
++ * RX queue does not need any lock since only sun8i_emac_poll() access it.
++ * (All other RX modifiers (ringparam/ndo_stop) disable NAPI and so
++ * sun8i_emac_poll())
++ * TX queue is handled by sun8i_emac_xmit(), sun8i_emac_complete_xmit() and
++ * sun8i_emac_tx_timeout()
++ * (All other RX modifiers (ringparam/ndo_stop) disable NAPI and stop queue)
++ *
++ * sun8i_emac_xmit() could fire only once (netif_tx_lock)
++ * sun8i_emac_complete_xmit() could fire only once (called from NAPI)
++ * sun8i_emac_tx_timeout() could fire only once (netif_tx_lock) and could not
++ * race with sun8i_emac_xmit (due to netif_tx_lock) and with
++ * sun8i_emac_complete_xmit which disable NAPI.
++ *
++ * So only sun8i_emac_xmit and sun8i_emac_complete_xmit could fire at the same
++ * time.
++ * But they never could modify the same descriptors:
++ * - sun8i_emac_complete_xmit() will modify only descriptors with empty status
++ * - sun8i_emac_xmit() will modify only descriptors set to DCLEAN
++ * Proper memory barriers ensure that descriptor set to DCLEAN could not be
++ * modified latter by sun8i_emac_complete_xmit().
++ */
++
++/* Return the number of contiguous free descriptors
++ * starting from tx_slot
++ */
++static int rb_tx_numfreedesc(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++
++ if (priv->tx_slot < priv->tx_dirty)
++ return priv->tx_dirty - priv->tx_slot;
++
++ return (priv->nbdesc_tx - priv->tx_slot) + priv->tx_dirty;
++}
++
++/* sun8i_emac_rx_skb - Allocate a skb in a DMA descriptor
++ *
++ * @ndev: The net_device for this interface
++ * @i: index of slot to fill
++ *
++ * Refill a DMA descriptor with a fresh skb and map it for DMA.
++*/
++static int sun8i_emac_rx_skb(struct net_device *ndev, int i)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ struct dma_desc *ddesc;
++ struct sk_buff *skb;
++
++ ddesc = priv->dd_rx + i;
++
++ ddesc->ctl = 0;
++
++ skb = netdev_alloc_skb_ip_align(ndev, DESC_BUF_MAX);
++ if (!skb)
++ return -ENOMEM;
++
++ /* should not happen */
++ if (unlikely(priv->rx_skb[i]))
++ dev_warn(priv->dev, "BUG: Leaking a skbuff\n");
++
++ priv->rx_skb[i] = skb;
++
++ ddesc->buf_addr = dma_map_single(priv->dev, skb->data,
++ DESC_BUF_MAX, DMA_FROM_DEVICE);
++ if (dma_mapping_error(priv->dev, ddesc->buf_addr)) {
++ dev_err(priv->dev, "ERROR: Cannot map RX buffer for DMA\n");
++ dev_kfree_skb(skb);
++ return -EFAULT;
++ }
++ /* We cannot direcly use cpu_to_le32() after dma_map_single
++ * since dma_mapping_error use it
++ */
++ ddesc->buf_addr = cpu_to_le32(ddesc->buf_addr);
++ ddesc->ctl |= cpu_to_le32(DESC_BUF_MAX);
++ /* EMAC_COULD_BE_USED_BY_DMA must be the last value written */
++ wmb();
++ ddesc->status = EMAC_COULD_BE_USED_BY_DMA;
++
++ return 0;
++}
++
++static void sun8i_emac_stop_tx(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ u32 v;
++
++ netif_stop_queue(ndev);
++
++ v = readl(priv->base + EMAC_TX_CTL0);
++ /* Disable transmitter after current reception */
++ v &= ~EMAC_TX_TRANSMITTER_EN;
++ writel(v, priv->base + EMAC_TX_CTL0);
++
++ v = readl(priv->base + EMAC_TX_CTL1);
++ /* Stop TX DMA */
++ v &= ~EMAC_TX_DMA_EN;
++ writel(v, priv->base + EMAC_TX_CTL1);
++
++ /* We must be sure that all is stopped before leaving this function */
++ wmb();
++}
++
++static void sun8i_emac_stop_rx(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ u32 v;
++
++ v = readl(priv->base + EMAC_RX_CTL0);
++ /* Disable receiver after current reception */
++ v &= ~EMAC_RX_RECEIVER_EN;
++ writel(v, priv->base + EMAC_RX_CTL0);
++
++ v = readl(priv->base + EMAC_RX_CTL1);
++ /* Stop RX DMA */
++ v &= ~EMAC_RX_DMA_EN;
++ writel(v, priv->base + EMAC_RX_CTL1);
++
++ /* We must be sure that all is stopped before leaving this function */
++ wmb();
++}
++
++static void sun8i_emac_start_rx(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ u32 v;
++
++ v = readl(priv->base + EMAC_RX_CTL0);
++ /* Enable receiver */
++ v |= EMAC_RX_RECEIVER_EN;
++ writel(v, priv->base + EMAC_RX_CTL0);
++
++ v = readl(priv->base + EMAC_RX_CTL1);
++ v |= EMAC_RX_DMA_START;
++ v |= EMAC_RX_DMA_EN;
++ writel(v, priv->base + EMAC_RX_CTL1);
++}
++
++static void sun8i_emac_start_tx(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ u32 v;
++
++ v = readl(priv->base + EMAC_TX_CTL0);
++ v |= EMAC_TX_TRANSMITTER_EN;
++ writel(v, priv->base + EMAC_TX_CTL0);
++
++ v = readl(priv->base + EMAC_TX_CTL1);
++ v |= EMAC_TX_DMA_START;
++ v |= EMAC_TX_DMA_EN;
++ writel(v, priv->base + EMAC_TX_CTL1);
++}
++
++/* sun8i_emac_set_macaddr - Set MAC address for slot index
++ *
++ * @addr: the MAC address to set
++ * @index: The index of slot where to set address.
++ *
++ * The slot 0 is the main MAC address
++ */
++static void sun8i_emac_set_macaddr(struct sun8i_emac_priv *priv,
++ const u8 *addr, int index)
++{
++ u32 v;
++
++ dev_info(priv->dev, "device MAC address slot %d %pM", index, addr);
++
++ v = (addr[5] << 8) | addr[4];
++ writel(v, priv->base + EMAC_MACADDR_HI + index * 8);
++
++ v = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
++ writel(v, priv->base + EMAC_MACADDR_LO + index * 8);
++}
++
++static void sun8i_emac_set_link_mode(struct sun8i_emac_priv *priv)
++{
++ u32 v;
++
++ v = readl(priv->base + EMAC_BASIC_CTL0);
++
++ if (priv->duplex)
++ v |= EMAC_BCTL0_FD;
++ else
++ v &= ~EMAC_BCTL0_FD;
++
++ v &= ~EMAC_BCTL0_SPEED_MASK;
++
++ switch (priv->speed) {
++ case 1000:
++ break;
++ case 100:
++ v |= EMAC_BCTL0_SPEED_100 << EMAC_BCTL0_SPEED_SHIFT;
++ break;
++ case 10:
++ v |= EMAC_BCTL0_SPEED_10 << EMAC_BCTL0_SPEED_SHIFT;
++ break;
++ default:
++ dev_err(priv->dev, "Unsupported speed %d\n", priv->speed);
++ return;
++ }
++
++ writel(v, priv->base + EMAC_BASIC_CTL0);
++}
++
++static void sun8i_emac_flow_ctrl(struct sun8i_emac_priv *priv, int duplex,
++ int fc)
++{
++ u32 flow = 0;
++
++ flow = readl(priv->base + EMAC_RX_CTL0);
++ if (fc & EMAC_FLOW_RX)
++ flow |= BIT(16);
++ else
++ flow &= ~BIT(16);
++ writel(flow, priv->base + EMAC_RX_CTL0);
++
++ flow = readl(priv->base + EMAC_TX_FLOW_CTL);
++ if (fc & EMAC_FLOW_TX)
++ flow |= BIT(0);
++ else
++ flow &= ~BIT(0);
++ writel(flow, priv->base + EMAC_TX_FLOW_CTL);
++}
++
++/* Grab a frame into a skb from descriptor number i */
++static int sun8i_emac_rx_from_ddesc(struct net_device *ndev, int i)
++{
++ struct sk_buff *skb;
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ struct dma_desc *ddesc = priv->dd_rx + i;
++ int frame_len;
++ int rxcsum_done = 0;
++ u32 dstatus = le32_to_cpu(ddesc->status);
++
++ if (ndev->features & NETIF_F_RXCSUM)
++ rxcsum_done = 1;
++
++ /* bit0/bit7 work only on IPv4/IPv6 TCP traffic,
++ * (not on ARP for example) so we do not raise rx_errors/discard frame
++ */
++ /* the checksum or length of received frame's payload is wrong*/
++ if (dstatus & BIT(0)) {
++ priv->estats.rx_payload_error++;
++ rxcsum_done = 0;
++ }
++
++ /* RX_CRC_ERR */
++ if (dstatus & BIT(1)) {
++ priv->ndev->stats.rx_errors++;
++ priv->ndev->stats.rx_crc_errors++;
++ priv->estats.rx_crc_error++;
++ goto discard_frame;
++ }
++
++ /* RX_PHY_ERR */
++ if ((dstatus & BIT(3))) {
++ priv->ndev->stats.rx_errors++;
++ priv->estats.rx_phy_error++;
++ goto discard_frame;
++ }
++
++ /* RX_LENGTH_ERR */
++ if ((dstatus & BIT(4))) {
++ priv->ndev->stats.rx_errors++;
++ priv->ndev->stats.rx_length_errors++;
++ priv->estats.rx_length_error++;
++ goto discard_frame;
++ }
++
++ /* RX_COL_ERR */
++ if ((dstatus & BIT(6))) {
++ priv->ndev->stats.rx_errors++;
++ priv->estats.rx_col_error++;
++ goto discard_frame;
++ }
++
++ /* RX_HEADER_ERR */
++ if ((dstatus & BIT(7))) {
++ priv->estats.rx_header_error++;
++ rxcsum_done = 0;
++ }
++
++ /* RX_OVERFLOW_ERR */
++ if ((dstatus & BIT(11))) {
++ priv->ndev->stats.rx_over_errors++;
++ priv->estats.rx_overflow_error++;
++ goto discard_frame;
++ }
++
++ /* RX_NO_ENOUGTH_BUF_ERR */
++ if ((dstatus & BIT(14))) {
++ priv->ndev->stats.rx_errors++;
++ priv->estats.rx_buf_error++;
++ goto discard_frame;
++ }
++
++ /* BIT(9) is for the first frame, not having it is bad since we do not
++ * handle Jumbo frame
++ */
++ if ((dstatus & EMAC_DSC_RX_FIRST) == 0) {
++ priv->ndev->stats.rx_errors++;
++ priv->estats.rx_invalid_error++;
++ goto discard_frame;
++ }
++
++ /* this frame is not the last */
++ if ((dstatus & EMAC_DSC_RX_LAST) == 0) {
++ priv->ndev->stats.rx_errors++;
++ priv->estats.rx_invalid_error++;
++ goto discard_frame;
++ }
++
++ frame_len = (dstatus >> 16) & 0x3FFF;
++ if (!(ndev->features & NETIF_F_RXFCS))
++ frame_len -= ETH_FCS_LEN;
++
++ skb = priv->rx_skb[i];
++
++ netif_dbg(priv, rx_status, priv->ndev,
++ "%s from %02d %pad len=%d status=%x st=%x\n",
++ __func__, i, &ddesc, frame_len, dstatus,
++ cpu_to_le32(ddesc->ctl));
++
++ skb_put(skb, frame_len);
++
++ dma_unmap_single(priv->dev, le32_to_cpu(ddesc->buf_addr), DESC_BUF_MAX,
++ DMA_FROM_DEVICE);
++ skb->protocol = eth_type_trans(skb, priv->ndev);
++ if (rxcsum_done) {
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ priv->estats.rx_hw_csum++;
++ } else {
++ skb->ip_summed = CHECKSUM_PARTIAL;
++ }
++
++ priv->ndev->stats.rx_packets++;
++ priv->ndev->stats.rx_bytes += frame_len;
++ priv->rx_skb[i] = NULL;
++
++ sun8i_emac_rx_skb(ndev, i);
++ napi_gro_receive(&priv->napi, skb);
++
++ return 0;
++ /* If the frame need to be dropped, we simply reuse the buffer */
++discard_frame:
++ ddesc->ctl = cpu_to_le32(DESC_BUF_MAX);
++ /* EMAC_COULD_BE_USED_BY_DMA must be the last value written */
++ wmb();
++ ddesc->status = EMAC_COULD_BE_USED_BY_DMA;
++ return 0;
++}
++
++/* Iterate over dma_desc for finding completed xmit.
++ *
++ * The problem is: how to know that a descriptor is sent and not just in
++ * preparation.
++ * Need to have status=0 and st set but this is the state of first frame just
++ * before setting the own-by-DMA bit.
++ * The solution is to used the artificial value DCLEAN.
++ */
++static int sun8i_emac_complete_xmit(struct net_device *ndev, int budget)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ struct dma_desc *ddesc;
++ int frame_len;
++ int work = 0;
++ unsigned int bytes_compl = 0, pkts_compl = 0;
++ u32 dstatus;
++
++ do {
++ ddesc = priv->dd_tx + priv->tx_dirty;
++
++ if (ddesc->status & EMAC_COULD_BE_USED_BY_DMA)
++ goto xmit_end;
++
++ if (ddesc->status == DCLEAN)
++ goto xmit_end;
++
++ dstatus = cpu_to_le32(ddesc->status);
++
++ if (ddesc->status == 0 && !ddesc->ctl) {
++ dev_err(priv->dev, "BUG: reached the void %d %d\n",
++ priv->tx_dirty, priv->tx_slot);
++ goto xmit_end;
++ }
++
++ /* TX_UNDERFLOW_ERR */
++ if (dstatus & BIT(1))
++ priv->ndev->stats.tx_errors++;
++ /* TX_DEFER_ERR */
++ if (dstatus & BIT(2))
++ priv->ndev->stats.tx_errors++;
++ /* BIT 6:3 numbers of collisions */
++ if (dstatus & 0x78)
++ priv->ndev->stats.collisions +=
++ (dstatus & 0x78) >> 3;
++ /* TX_COL_ERR_1 */
++ if (dstatus & BIT(8))
++ priv->ndev->stats.tx_errors++;
++ /* TX_COL_ERR_0 */
++ if (dstatus & BIT(9))
++ priv->ndev->stats.tx_errors++;
++ /* TX_CRS_ERR */
++ if (dstatus & BIT(10))
++ priv->ndev->stats.tx_carrier_errors++;
++ /* TX_PAYLOAD_ERR */
++ if (dstatus & BIT(12))
++ priv->ndev->stats.tx_errors++;
++ /* TX_LENGTH_ERR */
++ if (dstatus & BIT(14))
++ priv->ndev->stats.tx_errors++;
++ /* TX_HEADER_ERR */
++ if (dstatus & BIT(16))
++ priv->ndev->stats.tx_errors++;
++
++ frame_len = le32_to_cpu(ddesc->ctl) & 0x3FFF;
++ bytes_compl += frame_len;
++
++ if (priv->txl[priv->tx_dirty].map == MAP_SINGLE)
++ dma_unmap_single(priv->dev,
++ le32_to_cpu(ddesc->buf_addr),
++ frame_len, DMA_TO_DEVICE);
++ else
++ dma_unmap_page(priv->dev,
++ le32_to_cpu(ddesc->buf_addr),
++ frame_len, DMA_TO_DEVICE);
++ /* we can free skb only on last frame */
++ if (priv->txl[priv->tx_dirty].skb &&
++ (ddesc->ctl & EMAC_DSC_TX_LAST)) {
++ dev_kfree_skb_irq(priv->txl[priv->tx_dirty].skb);
++ pkts_compl++;
++ }
++
++ priv->txl[priv->tx_dirty].skb = NULL;
++ priv->txl[priv->tx_dirty].map = 0;
++ ddesc->ctl = 0;
++ /* setting status to DCLEAN is the last value to be set */
++ wmb();
++ ddesc->status = DCLEAN;
++ work++;
++
++ rb_inc(&priv->tx_dirty, priv->nbdesc_tx);
++ ddesc = priv->dd_tx + priv->tx_dirty;
++ } while (ddesc->ctl &&
++ !(ddesc->status & EMAC_COULD_BE_USED_BY_DMA) &&
++ work < budget);
++
++xmit_end:
++ netdev_completed_queue(ndev, pkts_compl, bytes_compl);
++
++ /* if we don't have handled all packets */
++ if (work < budget)
++ work = 0;
++
++ if (netif_queue_stopped(ndev) &&
++ rb_tx_numfreedesc(ndev) > MAX_SKB_FRAGS + 1)
++ netif_wake_queue(ndev);
++ return work;
++}
++
++static int sun8i_emac_poll(struct napi_struct *napi, int budget)
++{
++ struct sun8i_emac_priv *priv =
++ container_of(napi, struct sun8i_emac_priv, napi);
++ struct net_device *ndev = priv->ndev;
++ int worked;
++ struct dma_desc *ddesc;
++
++ priv->estats.napi_schedule++;
++ worked = sun8i_emac_complete_xmit(ndev, budget);
++
++ ddesc = priv->dd_rx + priv->rx_dirty;
++ while (!(ddesc->status & EMAC_COULD_BE_USED_BY_DMA) &&
++ worked < budget) {
++ sun8i_emac_rx_from_ddesc(ndev, priv->rx_dirty);
++ worked++;
++ rb_inc(&priv->rx_dirty, priv->nbdesc_rx);
++ ddesc = priv->dd_rx + priv->rx_dirty;
++ };
++ if (worked < budget) {
++ priv->estats.napi_underflow++;
++ napi_complete(&priv->napi);
++ writel(EMAC_RX_INT | EMAC_TX_INT, priv->base + EMAC_INT_EN);
++ }
++ return worked;
++}
++
++static int sun8i_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg)
++{
++ struct net_device *ndev = bus->priv;
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ int err;
++ u32 reg;
++
++ err = readl_poll_timeout(priv->base + EMAC_MDIO_CMD, reg,
++ !(reg & MDIO_CMD_MII_BUSY), 100, 10000);
++ if (err) {
++ dev_err(priv->dev, "%s timeout %x\n", __func__, reg);
++ return err;
++ }
++
++ reg &= ~MDIO_CMD_MII_WRITE;
++ reg &= ~MDIO_CMD_MII_PHY_REG_ADDR_MASK;
++ reg |= (phy_reg << MDIO_CMD_MII_PHY_REG_ADDR_SHIFT) &
++ MDIO_CMD_MII_PHY_REG_ADDR_MASK;
++
++ reg &= ~MDIO_CMD_MII_PHY_ADDR_MASK;
++
++ reg |= (phy_addr << MDIO_CMD_MII_PHY_ADDR_SHIFT) &
++ MDIO_CMD_MII_PHY_ADDR_MASK;
++
++ reg |= MDIO_CMD_MII_BUSY;
++
++ writel(reg, priv->base + EMAC_MDIO_CMD);
++
++ err = readl_poll_timeout(priv->base + EMAC_MDIO_CMD, reg,
++ !(reg & MDIO_CMD_MII_BUSY), 100, 10000);
++
++ if (err) {
++ dev_err(priv->dev, "%s timeout %x\n", __func__, reg);
++ return err;
++ }
++
++ return readl(priv->base + EMAC_MDIO_DATA);
++}
++
++static int sun8i_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg,
++ u16 data)
++{
++ struct net_device *ndev = bus->priv;
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ u32 reg;
++ int err;
++
++ err = readl_poll_timeout(priv->base + EMAC_MDIO_CMD, reg,
++ !(reg & MDIO_CMD_MII_BUSY), 100, 10000);
++ if (err) {
++ dev_err(priv->dev, "%s timeout %x\n", __func__, reg);
++ return err;
++ }
++
++ reg &= ~MDIO_CMD_MII_PHY_REG_ADDR_MASK;
++ reg |= (phy_reg << MDIO_CMD_MII_PHY_REG_ADDR_SHIFT) &
++ MDIO_CMD_MII_PHY_REG_ADDR_MASK;
++
++ reg &= ~MDIO_CMD_MII_PHY_ADDR_MASK;
++ reg |= (phy_addr << MDIO_CMD_MII_PHY_ADDR_SHIFT) &
++ MDIO_CMD_MII_PHY_ADDR_MASK;
++
++ reg |= MDIO_CMD_MII_WRITE;
++ reg |= MDIO_CMD_MII_BUSY;
++
++ writel(reg, priv->base + EMAC_MDIO_CMD);
++ writel(data, priv->base + EMAC_MDIO_DATA);
++
++ err = readl_poll_timeout(priv->base + EMAC_MDIO_CMD, reg,
++ !(reg & MDIO_CMD_MII_BUSY), 100, 10000);
++ if (err) {
++ dev_err(priv->dev, "%s timeout %x\n", __func__, reg);
++ return err;
++ }
++
++ return 0;
++}
++
++static int sun8i_emac_mdio_register(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ struct mii_bus *bus;
++ int ret;
++
++ bus = mdiobus_alloc();
++ if (!bus) {
++ netdev_err(ndev, "Failed to allocate a new mdio bus\n");
++ return -ENOMEM;
++ }
++
++ bus->name = dev_name(priv->dev);
++ bus->read = &sun8i_mdio_read;
++ bus->write = &sun8i_mdio_write;
++ snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%x", bus->name, priv->dev->id);
++
++ bus->parent = priv->dev;
++ bus->priv = ndev;
++
++ ret = of_mdiobus_register(bus, priv->mdio_node);
++ if (ret) {
++ netdev_err(ndev, "Could not register a MDIO bus: %d\n", ret);
++ mdiobus_free(bus);
++ return ret;
++ }
++
++ priv->mdio = bus;
++
++ return 0;
++}
++
++static void sun8i_emac_mdio_unregister(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++
++ mdiobus_unregister(priv->mdio);
++ mdiobus_free(priv->mdio);
++}
++
++/* Run within phydev->lock */
++static void sun8i_emac_adjust_link(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ struct phy_device *phydev = ndev->phydev;
++ int new_state = 0;
++
++ netif_dbg(priv, link, priv->ndev,
++ "%s link=%x duplex=%x speed=%x\n", __func__,
++ phydev->link, phydev->duplex, phydev->speed);
++ if (!phydev)
++ return;
++
++ if (phydev->link) {
++ if (phydev->duplex != priv->duplex) {
++ new_state = 1;
++ priv->duplex = phydev->duplex;
++ }
++ if (phydev->pause)
++ sun8i_emac_flow_ctrl(priv, phydev->duplex,
++ priv->flow_ctrl);
++
++ if (phydev->speed != priv->speed) {
++ new_state = 1;
++ priv->speed = phydev->speed;
++ }
++
++ if (priv->link == 0) {
++ new_state = 1;
++ priv->link = phydev->link;
++ }
++
++ netif_dbg(priv, link, priv->ndev,
++ "%s new=%d link=%d pause=%d\n",
++ __func__, new_state, priv->link, phydev->pause);
++ if (new_state)
++ sun8i_emac_set_link_mode(priv);
++ } else if (priv->link != phydev->link) {
++ new_state = 1;
++ priv->link = 0;
++ priv->speed = 0;
++ priv->duplex = -1;
++ }
++
++ if (new_state)
++ phy_print_status(phydev);
++}
++
++/* H3 specific bits for EPHY */
++#define H3_EPHY_ADDR_SHIFT 20
++#define H3_EPHY_LED_POL BIT(17) /* 1: active low, 0: active high */
++#define H3_EPHY_SHUTDOWN BIT(16) /* 1: shutdown, 0: power up */
++#define H3_EPHY_SELECT BIT(15) /* 1: internal PHY, 0: external PHY */
++
++/* H3/A64 specific bits */
++#define SYSCON_RMII_EN BIT(13) /* 1: enable RMII (overrides EPIT) */
++
++/* Generic system control EMAC_CLK bits */
++#define SYSCON_ETXDC_MASK GENMASK(2, 0)
++#define SYSCON_ETXDC_SHIFT 10
++#define SYSCON_ERXDC_MASK GENMASK(4, 0)
++#define SYSCON_ERXDC_SHIFT 5
++/* EMAC PHY Interface Type */
++#define SYSCON_EPIT BIT(2) /* 1: RGMII, 0: MII */
++#define SYSCON_ETCS_MASK GENMASK(1, 0)
++#define SYSCON_ETCS_MII 0x0
++#define SYSCON_ETCS_EXT_GMII 0x1
++#define SYSCON_ETCS_INT_GMII 0x2
++#define SYSCON_EMAC_REG 0x30
++
++static int sun8i_emac_set_syscon(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ struct device_node *node = priv->dev->of_node;
++ int ret;
++ u32 reg, val;
++
++ reg = priv->variant->default_syscon_value;
++
++ if (priv->variant->internal_phy) {
++ if (!priv->use_internal_phy) {
++ /* switch to external PHY interface */
++ reg &= ~H3_EPHY_SELECT;
++ } else {
++ reg |= H3_EPHY_SELECT;
++ reg &= ~H3_EPHY_SHUTDOWN;
++
++ if (of_property_read_bool(priv->phy_node,
++ "allwinner,leds-active-low"))
++ reg |= H3_EPHY_LED_POL;
++
++ ret = of_mdio_parse_addr(priv->dev, priv->phy_node);
++ if (ret < 0) {
++ netdev_err(ndev, "Could not parse MDIO addr\n");
++ return ret;
++ }
++ /* of_mdio_parse_addr returns a valid (0 ~ 31) PHY
++ * address. No need to mask it again.
++ */
++ reg |= ret << H3_EPHY_ADDR_SHIFT;
++ }
++ }
++
++ if (!of_property_read_u32(node, "allwinner,tx-delay", &val)) {
++ if (val <= SYSCON_ETXDC_MASK) {
++ reg &= ~(SYSCON_ETXDC_MASK << SYSCON_ETXDC_SHIFT);
++ reg |= (val << SYSCON_ETXDC_SHIFT);
++ } else {
++ netdev_warn(ndev, "Invalid TX clock delay: %d\n", val);
++ }
++ }
++
++ if (!of_property_read_u32(node, "allwinner,rx-delay", &val)) {
++ if (val <= SYSCON_ERXDC_MASK) {
++ reg &= ~(SYSCON_ERXDC_MASK << SYSCON_ERXDC_SHIFT);
++ reg |= (val << SYSCON_ERXDC_SHIFT);
++ } else {
++ netdev_warn(ndev, "Invalid RX clock delay: %d\n", val);
++ }
++ }
++
++ /* Clear interface mode bits */
++ reg &= ~(SYSCON_ETCS_MASK | SYSCON_EPIT);
++ if (priv->variant->support_rmii)
++ reg &= ~SYSCON_RMII_EN;
++
++ switch (priv->phy_interface) {
++ case PHY_INTERFACE_MODE_MII:
++ /* default */
++ break;
++ case PHY_INTERFACE_MODE_RGMII:
++ reg |= SYSCON_EPIT | SYSCON_ETCS_INT_GMII;
++ break;
++ case PHY_INTERFACE_MODE_RMII:
++ reg |= SYSCON_RMII_EN | SYSCON_ETCS_EXT_GMII;
++ break;
++ default:
++ netdev_err(ndev, "Unsupported interface mode: %s",
++ phy_modes(priv->phy_interface));
++ return -EINVAL;
++ }
++
++ regmap_write(priv->regmap, SYSCON_EMAC_REG, reg);
++
++ return 0;
++}
++
++static void sun8i_emac_unset_syscon(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ u32 reg = priv->variant->default_syscon_value;
++
++ regmap_write(priv->regmap, SYSCON_EMAC_REG, reg);
++}
++
++/* Set Management Data Clock, must be call after device reset */
++static void sun8i_emac_set_mdc(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ unsigned long rate;
++ u32 reg;
++
++ rate = clk_get_rate(priv->ahb_clk);
++ if (rate > 160000000)
++ reg = 0x3 << 20; /* AHB / 128 */
++ else if (rate > 80000000)
++ reg = 0x2 << 20; /* AHB / 64 */
++ else if (rate > 40000000)
++ reg = 0x1 << 20; /* AHB / 32 */
++ else
++ reg = 0x0 << 20; /* AHB / 16 */
++ netif_dbg(priv, link, ndev, "MDC auto : %x\n", reg);
++ writel(reg, priv->base + EMAC_MDIO_CMD);
++}
++
++/* "power" the device, by enabling clk/reset/regulators */
++static int sun8i_emac_power(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ int ret;
++
++ ret = clk_prepare_enable(priv->ahb_clk);
++ if (ret) {
++ netdev_err(ndev, "Could not enable AHB clock\n");
++ return ret;
++ }
++
++ if (priv->rst_mac) {
++ ret = reset_control_deassert(priv->rst_mac);
++ if (ret) {
++ netdev_err(ndev, "Could not deassert reset\n");
++ goto err_reset;
++ }
++ }
++
++ if (priv->ephy_clk) {
++ ret = clk_prepare_enable(priv->ephy_clk);
++ if (ret) {
++ netdev_err(ndev, "Could not enable EPHY clock\n");
++ goto err_ephy_clk;
++ }
++ }
++
++ if (priv->rst_ephy) {
++ ret = reset_control_deassert(priv->rst_ephy);
++ if (ret) {
++ netdev_err(ndev, "Could not deassert EPHY reset\n");
++ goto err_ephy_reset;
++ }
++ }
++
++ return 0;
++
++err_ephy_reset:
++ if (priv->ephy_clk)
++ clk_disable_unprepare(priv->ephy_clk);
++err_ephy_clk:
++ if (priv->rst_mac)
++ reset_control_assert(priv->rst_mac);
++err_reset:
++ clk_disable_unprepare(priv->ahb_clk);
++ return ret;
++}
++
++/* "Unpower" the device, disabling clocks and regulators, asserting reset */
++static void sun8i_emac_unpower(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++
++ if (priv->rst_ephy)
++ reset_control_assert(priv->rst_ephy);
++
++ if (priv->ephy_clk)
++ clk_disable_unprepare(priv->ephy_clk);
++
++ if (priv->rst_mac)
++ reset_control_assert(priv->rst_mac);
++
++ clk_disable_unprepare(priv->ahb_clk);
++}
++
++static int sun8i_emac_init(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ struct device_node *node = priv->dev->of_node;
++ const u8 *addr;
++
++ /* Try to get MAC address from DT, or assign a random one */
++ addr = of_get_mac_address(node);
++ if (addr)
++ ether_addr_copy(ndev->dev_addr, addr);
++ else
++ eth_hw_addr_random(ndev);
++
++ return 0;
++}
++
++static int sun8i_emac_mdio_probe(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ struct phy_device *phydev = NULL;
++
++ phydev = of_phy_connect(ndev, priv->phy_node, &sun8i_emac_adjust_link,
++ 0, priv->phy_interface);
++
++ if (!phydev) {
++ netdev_err(ndev, "Could not attach to PHY\n");
++ return -ENODEV;
++ }
++
++ phy_attached_info(phydev);
++
++ /* mask with MAC supported features */
++ phydev->supported &= PHY_GBIT_FEATURES;
++ phydev->advertising = phydev->supported;
++
++ priv->link = 0;
++ priv->speed = 0;
++ priv->duplex = -1;
++
++ return 0;
++}
++
++/* Allocate both RX and TX ring buffer and init them
++ * This function also write the startbase of thoses ring in the device.
++ * All structures that help managing thoses rings are also handled
++ * by this functions (rx_skb/txl)
++ */
++static int sun8i_emac_alloc_rings(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ struct dma_desc *ddesc;
++ int err, i;
++
++ priv->rx_skb = kcalloc(priv->nbdesc_rx, sizeof(struct sk_buff *),
++ GFP_KERNEL);
++ if (!priv->rx_skb) {
++ err = -ENOMEM;
++ goto rx_skb_error;
++ }
++ priv->txl = kcalloc(priv->nbdesc_tx, sizeof(struct txinfo), GFP_KERNEL);
++ if (!priv->txl) {
++ err = -ENOMEM;
++ goto tx_error;
++ }
++
++ /* allocate/init RX ring */
++ priv->dd_rx = dma_zalloc_coherent(priv->dev,
++ priv->nbdesc_rx * sizeof(struct dma_desc),
++ &priv->dd_rx_phy, GFP_KERNEL);
++ if (!priv->dd_rx) {
++ dev_err(priv->dev, "ERROR: cannot allocate DMA RX buffer");
++ err = -ENOMEM;
++ goto dma_rx_error;
++ }
++ ddesc = priv->dd_rx;
++ for (i = 0; i < priv->nbdesc_rx; i++) {
++ sun8i_emac_rx_skb(ndev, i);
++ ddesc->next = cpu_to_le32(priv->dd_rx_phy + (i + 1)
++ * sizeof(struct dma_desc));
++ ddesc++;
++ }
++ /* last descriptor point back to first one */
++ ddesc--;
++ ddesc->next = cpu_to_le32(priv->dd_rx_phy);
++
++ /* allocate/init TX ring */
++ priv->dd_tx = dma_zalloc_coherent(priv->dev,
++ priv->nbdesc_tx * sizeof(struct dma_desc),
++ &priv->dd_tx_phy, GFP_KERNEL);
++ if (!priv->dd_tx) {
++ dev_err(priv->dev, "ERROR: cannot allocate DMA TX buffer");
++ err = -ENOMEM;
++ goto dma_tx_error;
++ }
++ ddesc = priv->dd_tx;
++ for (i = 0; i < priv->nbdesc_tx; i++) {
++ ddesc->status = DCLEAN;
++ ddesc->ctl = 0;
++ ddesc->next = cpu_to_le32(priv->dd_tx_phy + (i + 1)
++ * sizeof(struct dma_desc));
++ ddesc++;
++ }
++ /* last descriptor point back to first one */
++ ddesc--;
++ ddesc->next = cpu_to_le32(priv->dd_tx_phy);
++ i--;
++
++ priv->tx_slot = 0;
++ priv->tx_dirty = 0;
++ priv->rx_dirty = 0;
++
++ /* write start of RX ring descriptor */
++ writel(priv->dd_rx_phy, priv->base + EMAC_RX_DESC_LIST);
++ /* write start of TX ring descriptor */
++ writel(priv->dd_tx_phy, priv->base + EMAC_TX_DESC_LIST);
++
++ return 0;
++dma_tx_error:
++ dma_free_coherent(priv->dev, priv->nbdesc_rx * sizeof(struct dma_desc),
++ priv->dd_rx, priv->dd_rx_phy);
++dma_rx_error:
++ kfree(priv->txl);
++tx_error:
++ kfree(priv->rx_skb);
++rx_skb_error:
++ return err;
++}
++
++static int sun8i_emac_open(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ int err;
++ u32 v;
++
++ err = sun8i_emac_power(ndev);
++ if (err)
++ return err;
++
++ err = request_irq(priv->irq, sun8i_emac_dma_interrupt, 0,
++ dev_name(priv->dev), ndev);
++ if (err) {
++ dev_err(priv->dev, "Cannot request IRQ: %d\n", err);
++ goto err_power;
++ }
++
++ /* Set interface mode (and configure internal PHY on H3) */
++ err = sun8i_emac_set_syscon(ndev);
++ if (err)
++ goto err_irq;
++
++ /* Do SOFT RST */
++ v = readl(priv->base + EMAC_BASIC_CTL1);
++ writel(v | 0x01, priv->base + EMAC_BASIC_CTL1);
++
++ err = readl_poll_timeout(priv->base + EMAC_BASIC_CTL1, v,
++ !(v & 0x01), 100, 10000);
++ if (err) {
++ dev_err(priv->dev, "EMAC reset timeout\n");
++ err = -EFAULT;
++ goto err_syscon;
++ }
++
++ sun8i_emac_set_mdc(ndev);
++
++ err = sun8i_emac_mdio_register(ndev);
++ if (err)
++ goto err_syscon;
++
++ err = sun8i_emac_mdio_probe(ndev);
++ if (err)
++ goto err_syscon;
++
++ /* DMA */
++ v = (8 << 24);/* burst len */
++ writel(v, priv->base + EMAC_BASIC_CTL1);
++
++ writel(EMAC_RX_INT | EMAC_TX_INT, priv->base + EMAC_INT_EN);
++
++ v = readl(priv->base + EMAC_RX_CTL0);
++ /* CHECK_CRC */
++ if (ndev->features & NETIF_F_RXCSUM)
++ v |= EMAC_RX_DO_CRC;
++ else
++ v &= ~EMAC_RX_DO_CRC;
++ /* STRIP_FCS */
++ if (ndev->features & NETIF_F_RXFCS)
++ v &= ~EMAC_RX_STRIP_FCS;
++ else
++ v |= EMAC_RX_STRIP_FCS;
++ writel(v, priv->base + EMAC_RX_CTL0);
++
++ v = readl(priv->base + EMAC_TX_CTL1);
++ /* TX_MD Transmission starts after a full frame located in TX DMA FIFO*/
++ v |= BIT(1);
++ /* Undocumented bit (called TX_NEXT_FRM in BSP), the original comment is
++ * "Operating on second frame increase the performance
++ * especially when transmit store-and-forward is used."
++ */
++ v |= BIT(2);
++ writel(v, priv->base + EMAC_TX_CTL1);
++
++ v = readl(priv->base + EMAC_RX_CTL1);
++ /* RX_MD RX DMA reads data from RX DMA FIFO to host memory after a
++ * complete frame has been written to RX DMA FIFO
++ */
++ v |= BIT(1);
++ writel(v, priv->base + EMAC_RX_CTL1);
++
++ sun8i_emac_set_macaddr(priv, ndev->dev_addr, 0);
++
++ err = sun8i_emac_alloc_rings(ndev);
++ if (err) {
++ netdev_err(ndev, "Fail to allocate rings\n");
++ goto err_mdio;
++ }
++
++ phy_start(ndev->phydev);
++
++ sun8i_emac_start_rx(ndev);
++ sun8i_emac_start_tx(ndev);
++
++ netif_napi_add(ndev, &priv->napi, sun8i_emac_poll, 64);
++ napi_enable(&priv->napi);
++ netif_start_queue(ndev);
++
++ return 0;
++err_mdio:
++ phy_disconnect(ndev->phydev);
++err_syscon:
++ sun8i_emac_unset_syscon(ndev);
++err_irq:
++ free_irq(priv->irq, ndev);
++err_power:
++ sun8i_emac_unpower(ndev);
++ return err;
++}
++
++/* Clean the TX ring of any accepted skb for xmit */
++static void sun8i_emac_tx_clean(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ int i;
++ struct dma_desc *ddesc;
++ int frame_len;
++
++ for (i = 0; i < priv->nbdesc_tx; i++) {
++ if (priv->txl[i].skb) {
++ ddesc = priv->dd_tx + i;
++ frame_len = le32_to_cpu(ddesc->ctl) & 0x3FFF;
++ switch (priv->txl[i].map) {
++ case MAP_SINGLE:
++ dma_unmap_single(priv->dev,
++ le32_to_cpu(ddesc->buf_addr),
++ frame_len, DMA_TO_DEVICE);
++ break;
++ case MAP_PAGE:
++ dma_unmap_page(priv->dev,
++ le32_to_cpu(ddesc->buf_addr),
++ frame_len, DMA_TO_DEVICE);
++ break;
++ default:
++ dev_err(priv->dev, "Trying to free an empty slot\n");
++ continue;
++ }
++ dev_kfree_skb_any(priv->txl[i].skb);
++ priv->txl[i].skb = NULL;
++ ddesc->ctl = 0;
++ ddesc->status = DCLEAN;
++ }
++ }
++ priv->tx_slot = 0;
++ priv->tx_dirty = 0;
++}
++
++/* Clean the RX ring */
++static void sun8i_emac_rx_clean(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ int i;
++ struct dma_desc *ddesc;
++
++ /* clean RX ring */
++ for (i = 0; i < priv->nbdesc_rx; i++)
++ if (priv->rx_skb[i]) {
++ ddesc = priv->dd_rx + i;
++ dma_unmap_single(priv->dev,
++ le32_to_cpu(ddesc->buf_addr),
++ DESC_BUF_MAX, DMA_FROM_DEVICE);
++ dev_kfree_skb_any(priv->rx_skb[i]);
++ priv->rx_skb[i] = NULL;
++ }
++}
++
++static int sun8i_emac_stop(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++
++ napi_disable(&priv->napi);
++
++ sun8i_emac_stop_tx(ndev);
++ sun8i_emac_stop_rx(ndev);
++
++ phy_stop(ndev->phydev);
++ phy_disconnect(ndev->phydev);
++
++ sun8i_emac_mdio_unregister(ndev);
++
++ sun8i_emac_unset_syscon(ndev);
++
++ free_irq(priv->irq, ndev);
++
++ sun8i_emac_rx_clean(ndev);
++ sun8i_emac_tx_clean(ndev);
++
++ kfree(priv->rx_skb);
++ kfree(priv->txl);
++
++ dma_free_coherent(priv->dev, priv->nbdesc_rx * sizeof(struct dma_desc),
++ priv->dd_rx, priv->dd_rx_phy);
++ dma_free_coherent(priv->dev, priv->nbdesc_tx * sizeof(struct dma_desc),
++ priv->dd_tx, priv->dd_tx_phy);
++
++ sun8i_emac_unpower(ndev);
++
++ return 0;
++}
++
++static netdev_tx_t sun8i_emac_xmit(struct sk_buff *skb, struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ struct dma_desc *ddesc;
++ struct dma_desc *first;
++ int i = 0, rbd_first;
++ unsigned int len, fraglen, tlen;
++ u32 v;
++ int n;
++ int nf;
++ const skb_frag_t *frag;
++ int do_csum = 0;
++
++ if (skb_put_padto(skb, ETH_ZLEN))
++ return NETDEV_TX_OK;
++ len = skb_headlen(skb);
++
++ n = skb_shinfo(skb)->nr_frags;
++
++ if (skb->ip_summed == CHECKSUM_PARTIAL) {
++ do_csum = 1;
++ priv->estats.tx_hw_csum++;
++ }
++ netif_dbg(priv, tx_queued, ndev, "%s len=%u skblen=%u %x\n", __func__,
++ len, skb->len,
++ (skb->ip_summed == CHECKSUM_PARTIAL));
++
++ /* check for contigous space
++ * We need at least 1(skb->data) + n(numfrags) + 1(one clean slot)
++ */
++ if (rb_tx_numfreedesc(ndev) < n + 2) {
++ dev_err_ratelimited(priv->dev, "BUG!: TX is full %d %d\n",
++ priv->tx_dirty, priv->tx_slot);
++ netif_stop_queue(ndev);
++ return NETDEV_TX_BUSY;
++ }
++ i = priv->tx_slot;
++
++ ddesc = priv->dd_tx + i;
++ first = priv->dd_tx + i;
++ rbd_first = i;
++
++ ddesc->buf_addr = dma_map_single(priv->dev, skb->data, len,
++ DMA_TO_DEVICE);
++ if (dma_mapping_error(priv->dev, ddesc->buf_addr)) {
++ dev_err(priv->dev, "ERROR: Cannot map buffer for DMA\n");
++ goto xmit_error;
++ }
++ /* We cannot direcly use cpu_to_le32() after dma_map_single
++ * since dma_mapping_error use it
++ */
++ ddesc->buf_addr = cpu_to_le32(ddesc->buf_addr);
++ priv->txl[i].map = MAP_SINGLE;
++ priv->txl[i].skb = skb;
++
++ tlen = len;
++ ddesc->ctl = le32_to_cpu(len);
++ /* Undocumented bit that make it works
++ * Without it, packets never be sent on H3 SoC
++ */
++ ddesc->ctl |= EMAC_MAGIC_TX_BIT;
++ if (do_csum)
++ ddesc->ctl |= EMAC_TX_DO_CRC;
++
++ /* handle fragmented skb, one descriptor per fragment */
++ for (nf = 0; nf < n; nf++) {
++ frag = &skb_shinfo(skb)->frags[nf];
++ rb_inc(&i, priv->nbdesc_tx);
++ priv->txl[i].skb = skb;
++ ddesc = priv->dd_tx + i;
++ fraglen = skb_frag_size(frag);
++ ddesc->ctl = le32_to_cpu(fraglen);
++ tlen += fraglen,
++ ddesc->ctl |= EMAC_MAGIC_TX_BIT;
++ if (do_csum)
++ ddesc->ctl |= EMAC_TX_DO_CRC;
++
++ ddesc->buf_addr = skb_frag_dma_map(priv->dev, frag, 0,
++ fraglen, DMA_TO_DEVICE);
++ if (dma_mapping_error(priv->dev, ddesc->buf_addr)) {
++ dev_err(priv->dev, "Cannot map buffer for DMA\n");
++ goto xmit_error;
++ }
++ /* Cannot directly use cpu_to_le32() after skb_frag_dma_map
++ * since dma_mapping_error use it
++ */
++ ddesc->buf_addr = cpu_to_le32(ddesc->buf_addr);
++ priv->txl[i].map = MAP_PAGE;
++ ddesc->status = EMAC_COULD_BE_USED_BY_DMA;
++ }
++
++ /* frame end */
++ ddesc->ctl |= EMAC_DSC_TX_LAST;
++ /* We want an interrupt after transmission */
++ ddesc->ctl |= EMAC_WANT_INT;
++
++ rb_inc(&i, priv->nbdesc_tx);
++
++ /* This line was previously after DMA start, but with that we hit a
++ * small race with complete_xmit() where we complete more data than
++ * sent.
++ * The packet is sent just after EMAC_COULD_BE_USED_BY_DMA flag set and
++ * complete_xmit fire just after before netdev_sent_queue().
++ * This race could be observed only when overflowing a gigabit line.
++ */
++ netdev_sent_queue(ndev, skb->len);
++
++ /* frame begin */
++ first->ctl |= EMAC_DSC_TX_FIRST;
++ wmb();/* EMAC_COULD_BE_USED_BY_DMA must be the last value written */
++ first->status = EMAC_COULD_BE_USED_BY_DMA;
++ priv->tx_slot = i;
++
++ /* Trying to optimize this (recording DMA start/stop) seems
++ * to lead to errors. So we always start DMA.
++ */
++ v = readl(priv->base + EMAC_TX_CTL1);
++ v |= EMAC_TX_DMA_START;
++ v |= EMAC_TX_DMA_EN;
++ writel_relaxed(v, priv->base + EMAC_TX_CTL1);
++
++ if (rb_tx_numfreedesc(ndev) < MAX_SKB_FRAGS + 1) {
++ netif_stop_queue(ndev);
++ priv->estats.tx_stop_queue++;
++ }
++ priv->estats.tx_used_desc = rb_tx_numfreedesc(ndev);
++ priv->ndev->stats.tx_packets++;
++ priv->ndev->stats.tx_bytes += tlen;
++
++ return NETDEV_TX_OK;
++
++xmit_error:
++ /* destroy skb and return TX OK Documentation/DMA-API-HOWTO.txt */
++ /* clean descritors from rbd_first to i */
++ ddesc->ctl = 0;
++ /* setting status to DCLEAN is the last value to be set */
++ wmb();
++ ddesc->status = DCLEAN;
++ do {
++ ddesc = priv->dd_tx + rbd_first;
++ ddesc->ctl = 0;
++ /* setting status to DCLEAN is the last value to be set */
++ wmb();
++ ddesc->status = DCLEAN;
++ rb_inc(&rbd_first, priv->nbdesc_tx);
++ } while (rbd_first != i);
++ dev_kfree_skb_any(skb);
++ return NETDEV_TX_OK;
++}
++
++static int sun8i_emac_change_mtu(struct net_device *ndev, int new_mtu)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ int max_mtu;
++
++ dev_info(priv->dev, "%s set MTU to %d\n", __func__, new_mtu);
++
++ if (netif_running(ndev)) {
++ dev_err(priv->dev, "%s: must be stopped to change its MTU\n",
++ ndev->name);
++ return -EBUSY;
++ }
++
++ max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
++
++ if ((new_mtu < 68) || (new_mtu > max_mtu)) {
++ dev_err(priv->dev, "%s: invalid MTU, max MTU is: %d\n",
++ ndev->name, max_mtu);
++ return -EINVAL;
++ }
++
++ ndev->mtu = new_mtu;
++ netdev_update_features(ndev);
++ return 0;
++}
++
++static int sun8i_emac_set_features(struct net_device *ndev,
++ netdev_features_t features)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ u32 v;
++
++ v = readl(priv->base + EMAC_BASIC_CTL0);
++ if (features & NETIF_F_LOOPBACK && netif_running(ndev)) {
++ netif_info(priv, hw, ndev, "Set loopback features");
++ v |= BIT(1);
++ } else {
++ netif_info(priv, hw, ndev, "Unset loopback features");
++ v &= ~BIT(1);
++ }
++ writel(v, priv->base + EMAC_BASIC_CTL0);
++
++ v = readl(priv->base + EMAC_RX_CTL0);
++ if (features & NETIF_F_RXCSUM) {
++ v |= EMAC_RX_DO_CRC;
++ netif_info(priv, hw, ndev, "Doing RX CRC check by hardware");
++ } else {
++ v &= ~EMAC_RX_DO_CRC;
++ netif_info(priv, hw, ndev, "No RX CRC check by hardware");
++ }
++ if (features & NETIF_F_RXFCS) {
++ v &= ~EMAC_RX_STRIP_FCS;
++ netif_info(priv, hw, ndev, "Keep FCS");
++ } else {
++ v |= EMAC_RX_STRIP_FCS;
++ netif_info(priv, hw, ndev, "Strip FCS");
++ }
++ writel(v, priv->base + EMAC_RX_CTL0);
++
++ netif_dbg(priv, drv, ndev, "%s %llx %x\n", __func__, features, v);
++
++ return 0;
++}
++
++static void sun8i_emac_set_rx_mode(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ u32 v = 0;
++ int i = 0;
++ struct netdev_hw_addr *ha;
++
++ /* Receive all multicast frames */
++ v |= BIT(16);
++ /* Receive all control frames */
++ v |= BIT(13);
++ if (ndev->flags & IFF_PROMISC)
++ v |= BIT(1);
++ if (netdev_uc_count(ndev) > 7) {
++ v |= BIT(1);
++ } else {
++ netdev_for_each_uc_addr(ha, ndev) {
++ i++;
++ sun8i_emac_set_macaddr(priv, ha->addr, i);
++ }
++ }
++ writel(v, priv->base + EMAC_RX_FRM_FLT);
++}
++
++static void sun8i_emac_tx_timeout(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++
++ netdev_err(ndev, "%s\n", __func__);
++
++ sun8i_emac_stop_tx(ndev);
++
++ sun8i_emac_tx_clean(ndev);
++
++ /* write start of the new TX ring descriptor */
++ writel(priv->dd_tx_phy, priv->base + EMAC_TX_DESC_LIST);
++
++ sun8i_emac_start_tx(ndev);
++
++ netdev_reset_queue(ndev);
++
++ priv->estats.tx_timeout++;
++ ndev->stats.tx_errors++;
++ netif_wake_queue(ndev);
++}
++
++static int sun8i_emac_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
++{
++ struct phy_device *phydev = ndev->phydev;
++
++ if (!netif_running(ndev))
++ return -EINVAL;
++
++ if (!phydev)
++ return -ENODEV;
++
++ return phy_mii_ioctl(phydev, rq, cmd);
++}
++
++static int sun8i_emac_check_if_running(struct net_device *ndev)
++{
++ if (!netif_running(ndev))
++ return -EINVAL;
++ return 0;
++}
++
++static int sun8i_emac_get_sset_count(struct net_device *ndev, int sset)
++{
++ switch (sset) {
++ case ETH_SS_STATS:
++ return ARRAY_SIZE(estats_str);
++ }
++ return -EOPNOTSUPP;
++}
++
++static int sun8i_emac_ethtool_get_settings(struct net_device *ndev,
++ struct ethtool_cmd *cmd)
++{
++ struct phy_device *phy = ndev->phydev;
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++
++ if (!phy) {
++ netdev_err(ndev, "%s: %s: PHY is not registered\n",
++ __func__, ndev->name);
++ return -ENODEV;
++ }
++
++ if (!netif_running(ndev)) {
++ dev_err(priv->dev, "interface disabled: we cannot track link speed / duplex setting\n");
++ return -EBUSY;
++ }
++
++ return phy_ethtool_gset(phy, cmd);
++}
++
++static int sun8i_emac_ethtool_set_settings(struct net_device *ndev,
++ struct ethtool_cmd *cmd)
++{
++ struct phy_device *phy = ndev->phydev;
++
++ return phy_ethtool_sset(phy, cmd);
++}
++
++static void sun8i_emac_ethtool_getdrvinfo(struct net_device *ndev,
++ struct ethtool_drvinfo *info)
++{
++ strlcpy(info->driver, "sun8i_emac", sizeof(info->driver));
++ strcpy(info->version, "00");
++ info->fw_version[0] = '\0';
++}
++
++static void sun8i_emac_ethtool_stats(struct net_device *ndev,
++ struct ethtool_stats *dummy, u64 *data)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++
++ memcpy(data, &priv->estats,
++ sun8i_emac_get_sset_count(ndev, ETH_SS_STATS) * sizeof(u64));
++}
++
++static void sun8i_emac_ethtool_strings(struct net_device *dev, u32 stringset,
++ u8 *buffer)
++{
++ switch (stringset) {
++ case ETH_SS_STATS:
++ memcpy(buffer, &estats_str, sizeof(estats_str));
++ break;
++ }
++}
++
++static u32 sun8i_emac_ethtool_getmsglevel(struct net_device *ndev)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++
++ return priv->msg_enable;
++}
++
++static void sun8i_emac_ethtool_setmsglevel(struct net_device *ndev, u32 level)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++
++ priv->msg_enable = level;
++}
++
++static void sun8i_emac_get_pauseparam(struct net_device *ndev,
++ struct ethtool_pauseparam *pause)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++
++ pause->rx_pause = 0;
++ pause->tx_pause = 0;
++ pause->autoneg = ndev->phydev->autoneg;
++
++ if (priv->flow_ctrl & EMAC_FLOW_RX)
++ pause->rx_pause = 1;
++ if (priv->flow_ctrl & EMAC_FLOW_TX)
++ pause->tx_pause = 1;
++}
++
++static int sun8i_emac_set_pauseparam(struct net_device *ndev,
++ struct ethtool_pauseparam *pause)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ struct phy_device *phy = ndev->phydev;
++ int new_pause = 0;
++ int ret = 0;
++
++ if (pause->rx_pause)
++ new_pause |= EMAC_FLOW_RX;
++ if (pause->tx_pause)
++ new_pause |= EMAC_FLOW_TX;
++
++ priv->flow_ctrl = new_pause;
++ phy->autoneg = pause->autoneg;
++
++ if (phy->autoneg) {
++ if (netif_running(ndev))
++ ret = phy_start_aneg(phy);
++ } else {
++ sun8i_emac_flow_ctrl(priv, phy->duplex, priv->flow_ctrl);
++ }
++ return ret;
++}
++
++static void sun8i_emac_ethtool_get_ringparam(struct net_device *ndev,
++ struct ethtool_ringparam *ring)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++
++ ring->rx_pending = priv->nbdesc_rx;
++ ring->tx_pending = priv->nbdesc_tx;
++}
++
++static int sun8i_emac_ethtool_set_ringparam(struct net_device *ndev,
++ struct ethtool_ringparam *ring)
++{
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ int err;
++
++ if (ring->rx_max_pending || ring->rx_mini_max_pending ||
++ ring->rx_jumbo_max_pending || ring->rx_mini_pending ||
++ ring->rx_jumbo_pending || ring->tx_max_pending)
++ return -EINVAL;
++
++ if (ring->tx_pending < MAX_SKB_FRAGS + 1) {
++ netdev_err(ndev, "The number of TX descriptors is too low");
++ return -EINVAL;
++ }
++
++ sun8i_emac_stop_tx(ndev);
++ sun8i_emac_stop_rx(ndev);
++
++ sun8i_emac_rx_clean(ndev);
++ sun8i_emac_tx_clean(ndev);
++
++ kfree(priv->rx_skb);
++ kfree(priv->txl);
++
++ dma_free_coherent(priv->dev, priv->nbdesc_rx * sizeof(struct dma_desc),
++ priv->dd_rx, priv->dd_rx_phy);
++ dma_free_coherent(priv->dev, priv->nbdesc_tx * sizeof(struct dma_desc),
++ priv->dd_tx, priv->dd_tx_phy);
++
++ priv->nbdesc_rx = ring->rx_pending;
++ priv->nbdesc_tx = ring->tx_pending;
++ err = sun8i_emac_alloc_rings(ndev);
++ if (err) {
++ /* Fatal error, we cannot re start */
++ netdev_err(ndev, "Fail to allocate rings\n");
++ return -EFAULT;
++ }
++
++ sun8i_emac_start_rx(ndev);
++ sun8i_emac_start_tx(ndev);
++
++ netif_start_queue(ndev);
++
++ netdev_info(ndev, "Ring Param settings: rx: %d, tx %d\n",
++ ring->rx_pending, ring->tx_pending);
++ return 0;
++}
++
++static const struct ethtool_ops sun8i_emac_ethtool_ops = {
++ .begin = sun8i_emac_check_if_running,
++ .get_settings = sun8i_emac_ethtool_get_settings,
++ .set_settings = sun8i_emac_ethtool_set_settings,
++ .get_link = ethtool_op_get_link,
++ .get_pauseparam = sun8i_emac_get_pauseparam,
++ .set_pauseparam = sun8i_emac_set_pauseparam,
++ .get_ethtool_stats = sun8i_emac_ethtool_stats,
++ .get_strings = sun8i_emac_ethtool_strings,
++ .get_sset_count = sun8i_emac_get_sset_count,
++ .get_drvinfo = sun8i_emac_ethtool_getdrvinfo,
++ .get_msglevel = sun8i_emac_ethtool_getmsglevel,
++ .set_msglevel = sun8i_emac_ethtool_setmsglevel,
++ .get_ringparam = sun8i_emac_ethtool_get_ringparam,
++ .set_ringparam = sun8i_emac_ethtool_set_ringparam,
++};
++
++static const struct net_device_ops sun8i_emac_netdev_ops = {
++ .ndo_init = sun8i_emac_init,
++ .ndo_open = sun8i_emac_open,
++ .ndo_start_xmit = sun8i_emac_xmit,
++ .ndo_stop = sun8i_emac_stop,
++ .ndo_change_mtu = sun8i_emac_change_mtu,
++ .ndo_set_features = sun8i_emac_set_features,
++ .ndo_set_rx_mode = sun8i_emac_set_rx_mode,
++ .ndo_tx_timeout = sun8i_emac_tx_timeout,
++ .ndo_do_ioctl = sun8i_emac_ioctl,
++ .ndo_set_mac_address = eth_mac_addr,
++};
++
++/* No locking in this function since it is guaranteed to be run once and
++ * do actions only done here:
++ * - Scheduling NAPI
++ * - Stopping interrupts
++ * - Updating stats
++ *
++ * Even when not enabled via EMAC_INT_EN, some interrupt could fire, so we need
++ * to handle all of them.
++ * Interrupts know to fire when not enabled are:
++ * - EMAC_TX_DMA_STOP_INT
++ * - EMAC_TX_BUF_UA_INT
++ * - EMAC_TX_EARLY_INT
++ * - EMAC_RX_BUF_UA_INT
++ * - EMAC_RX_EARLY_INT
++ */
++static irqreturn_t sun8i_emac_dma_interrupt(int irq, void *dev_id)
++{
++ struct net_device *ndev = dev_id;
++ struct sun8i_emac_priv *priv = netdev_priv(ndev);
++ u32 v, u;
++
++ v = readl(priv->base + EMAC_INT_STA);
++
++ /* When this bit is asserted, a frame transmission is completed. */
++ if (v & EMAC_TX_INT) {
++ priv->estats.tx_int++;
++ writel(0, priv->base + EMAC_INT_EN);
++ napi_schedule(&priv->napi);
++ }
++
++ /* When this bit is asserted, the TX DMA FSM is stopped.
++ * For the moment only a call to tx_timeout cause this interrupt
++ * to fire.
++ */
++ if (v & EMAC_TX_DMA_STOP_INT)
++ priv->estats.tx_dma_stop++;
++
++ /* When this asserted, the TX DMA can not acquire next TX descriptor
++ * and TX DMA FSM is suspended.
++ */
++ if (v & EMAC_TX_BUF_UA_INT) {
++ priv->estats.tx_dma_ua++;
++ writel(0, priv->base + EMAC_INT_EN);
++ napi_schedule(&priv->napi);
++ }
++
++ if (v & EMAC_TX_TIMEOUT_INT)
++ priv->estats.tx_timeout_int++;
++
++ if (v & EMAC_TX_UNDERFLOW_INT)
++ priv->estats.tx_underflow_int++;
++
++ /* When this bit asserted , the frame is transmitted to FIFO totally. */
++ if (v & EMAC_TX_EARLY_INT)
++ priv->estats.tx_early_int++;
++
++ /* When this bit is asserted, a frame reception is completed */
++ if (v & EMAC_RX_INT) {
++ priv->estats.rx_int++;
++ writel(0, priv->base + EMAC_INT_EN);
++ napi_schedule(&priv->napi);
++ }
++
++ /* When this asserted, the RX DMA can not acquire next RX descriptor
++ * and RX DMA FSM is suspended.
++ */
++ if (v & EMAC_RX_BUF_UA_INT) {
++ u = readl(priv->base + EMAC_RX_CTL1);
++ writel(u | EMAC_RX_DMA_START, priv->base + EMAC_RX_CTL1);
++ priv->estats.rx_dma_ua++;
++ }
++
++ /* Same as TX DMA STOP, but never hit it */
++ if (v & EMAC_RX_DMA_STOP_INT)
++ priv->estats.rx_dma_stop++;
++
++ if (v & EMAC_RX_TIMEOUT_INT)
++ priv->estats.rx_timeout_int++;
++
++ if (v & EMAC_RX_OVERFLOW_INT)
++ priv->estats.rx_overflow_int++;
++
++ if (v & EMAC_RX_EARLY_INT)
++ priv->estats.rx_early_int++;
++
++ if (v & EMAC_RGMII_STA_INT)
++ priv->estats.rgmii_state_int++;
++
++ /* the datasheet state those register as read-only
++ * but nothing work(freeze) without writing to it
++ */
++ writel(v, priv->base + EMAC_INT_STA);
++
++ return IRQ_HANDLED;
++}
++
++static int sun8i_emac_probe(struct platform_device *pdev)
++{
++ struct device_node *node = pdev->dev.of_node;
++ struct sun8i_emac_priv *priv;
++ struct net_device *ndev;
++ struct resource *res;
++ int ret;
++
++ ndev = alloc_etherdev(sizeof(*priv));
++ if (!ndev)
++ return -ENOMEM;
++
++ SET_NETDEV_DEV(ndev, &pdev->dev);
++ priv = netdev_priv(ndev);
++ platform_set_drvdata(pdev, ndev);
++
++ priv->variant = of_device_get_match_data(&pdev->dev);
++ if (!priv->variant) {
++ dev_err(&pdev->dev, "Missing sun8i-emac variant\n");
++ return -EINVAL;
++ }
++
++ priv->mdio_node = of_get_child_by_name(node, "mdio");
++ if (!priv->mdio_node) {
++ netdev_err(ndev, "Could not find a MDIO node\n");
++ return -EINVAL;
++ }
++
++ priv->phy_node = of_parse_phandle(node, "phy-handle", 0);
++ if (!priv->phy_node) {
++ netdev_err(ndev, "No associated PHY\n");
++ return -EINVAL;
++ }
++
++ priv->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
++ "syscon");
++ if (IS_ERR(priv->regmap)) {
++ ret = PTR_ERR(priv->regmap);
++ dev_err(&pdev->dev, "unable to map SYSCON:%d\n", ret);
++ return ret;
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ priv->base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(priv->base)) {
++ ret = PTR_ERR(priv->base);
++ dev_err(&pdev->dev, "Cannot request MMIO: %d\n", ret);
++ return ret;
++ }
++
++ priv->ahb_clk = devm_clk_get(&pdev->dev, "ahb");
++ if (IS_ERR(priv->ahb_clk)) {
++ ret = PTR_ERR(priv->ahb_clk);
++ dev_err(&pdev->dev, "Cannot get AHB clock err=%d\n", ret);
++ goto probe_err;
++ }
++
++ priv->rst_mac = devm_reset_control_get_optional(&pdev->dev, "ahb");
++ if (IS_ERR(priv->rst_mac)) {
++ ret = PTR_ERR(priv->rst_mac);
++ if (ret == -EPROBE_DEFER)
++ return -EPROBE_DEFER;
++ dev_info(&pdev->dev, "No MAC reset control found %d\n", ret);
++ priv->rst_mac = NULL;
++ }
++
++ priv->phy_interface = of_get_phy_mode(node);
++ if (priv->phy_interface < 0) {
++ netdev_err(ndev, "PHY interface mode node unspecified\n");
++ return priv->phy_interface;
++ }
++
++ switch (priv->phy_interface) {
++ case PHY_INTERFACE_MODE_MII:
++ if (!priv->variant->support_mii)
++ return -EINVAL;
++ break;
++ case PHY_INTERFACE_MODE_RMII:
++ if (!priv->variant->support_rmii)
++ return -EINVAL;
++ break;
++ case PHY_INTERFACE_MODE_RGMII:
++ if (!priv->variant->support_rgmii)
++ return -EINVAL;
++ break;
++ default:
++ netdev_err(ndev, "Unsupported interface mode: %s",
++ phy_modes(priv->phy_interface));
++ return -EINVAL;
++ }
++
++ if (priv->phy_interface == priv->variant->internal_phy)
++ priv->use_internal_phy = true;
++
++ if (priv->use_internal_phy) {
++ priv->ephy_clk = of_clk_get(priv->phy_node, 0);
++ if (IS_ERR(priv->ephy_clk)) {
++ ret = PTR_ERR(priv->ephy_clk);
++ dev_err(&pdev->dev, "Cannot get EPHY clock err=%d\n",
++ ret);
++ goto probe_err;
++ }
++
++ priv->rst_ephy = of_reset_control_get(priv->phy_node, 0);
++ if (IS_ERR(priv->rst_ephy)) {
++ ret = PTR_ERR(priv->rst_ephy);
++ if (ret == -EPROBE_DEFER)
++ goto probe_err;
++ dev_info(&pdev->dev,
++ "No EPHY reset control found %d\n", ret);
++ priv->rst_ephy = NULL;
++ }
++ }
++
++ priv->irq = platform_get_irq(pdev, 0);
++ if (priv->irq < 0) {
++ ret = priv->irq;
++ dev_err(&pdev->dev, "Cannot claim IRQ: %d\n", ret);
++ goto probe_err;
++ }
++
++ spin_lock_init(&priv->tx_lock);
++
++ ndev->netdev_ops = &sun8i_emac_netdev_ops;
++ ndev->ethtool_ops = &sun8i_emac_ethtool_ops;
++
++ priv->ndev = ndev;
++ priv->dev = &pdev->dev;
++
++ ndev->hw_features = NETIF_F_SG | NETIF_F_HIGHDMA;
++ ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
++ NETIF_F_RXCSUM;
++ ndev->features |= ndev->hw_features;
++ ndev->hw_features |= NETIF_F_RXFCS;
++ ndev->hw_features |= NETIF_F_RXALL;
++ ndev->hw_features |= NETIF_F_LOOPBACK;
++ ndev->priv_flags |= IFF_UNICAST_FLT;
++
++ ndev->watchdog_timeo = msecs_to_jiffies(5000);
++ netif_carrier_off(ndev);
++
++ /* Benched on OPIPC with 100M, setting more than 256 does not give any
++ * perf boost
++ */
++ priv->nbdesc_rx = 128;
++ priv->nbdesc_tx = 256;
++
++ ret = register_netdev(ndev);
++ if (ret) {
++ dev_err(&pdev->dev, "ERROR: Register %s failed\n", ndev->name);
++ goto probe_err;
++ }
++
++ return 0;
++
++probe_err:
++ free_netdev(ndev);
++ return ret;
++}
++
++static int sun8i_emac_remove(struct platform_device *pdev)
++{
++ struct net_device *ndev = platform_get_drvdata(pdev);
++
++ unregister_netdev(ndev);
++ platform_set_drvdata(pdev, NULL);
++ free_netdev(ndev);
++
++ return 0;
++}
++
++static const struct of_device_id sun8i_emac_of_match_table[] = {
++ { .compatible = "allwinner,sun8i-a83t-emac",
++ .data = &emac_variant_a83t },
++ { .compatible = "allwinner,sun8i-h3-emac",
++ .data = &emac_variant_h3 },
++ { .compatible = "allwinner,sun50i-a64-emac",
++ .data = &emac_variant_a64 },
++ {}
++};
++MODULE_DEVICE_TABLE(of, sun8i_emac_of_match_table);
++
++static struct platform_driver sun8i_emac_driver = {
++ .probe = sun8i_emac_probe,
++ .remove = sun8i_emac_remove,
++ .driver = {
++ .name = "sun8i-emac",
++ .of_match_table = sun8i_emac_of_match_table,
++ },
++};
++
++module_platform_driver(sun8i_emac_driver);
++
++MODULE_DESCRIPTION("sun8i Ethernet driver");
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Corentin Labbe <clabbe.montjoie@gmail.com");
+--
+2.9.3
+
+From 7171a3584b7eb728d263f72876836dda933aa6a6 Mon Sep 17 00:00:00 2001
+From: Corentin LABBE <clabbe.montjoie@gmail.com>
+Date: Fri, 7 Oct 2016 10:25:49 +0200
+Subject: [PATCH 2/9] MAINTAINERS: Add myself as maintainer of sun8i-emac
+
+This patch add myself as maintainer of the sun8i-emac driver.
+
+Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
+---
+ MAINTAINERS | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index f593300..94dac86 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -582,6 +582,12 @@ S: Maintained
+ F: Documentation/i2c/busses/i2c-ali1563
+ F: drivers/i2c/busses/i2c-ali1563.c
+
++ALLWINNER SUN8I-EMAC ETHERNET DRIVER
++M: Corentin Labbe <clabbe.montjoie@gmail.com>
++L: netdev@vger.kernel.org
++S: Maintained
++F: drivers/net/ethernet/allwinner/sun8i-emac.c
++
+ ALLWINNER SECURITY SYSTEM
+ M: Corentin Labbe <clabbe.montjoie@gmail.com>
+ L: linux-crypto@vger.kernel.org
+--
+2.9.3
+
+From 0c21240a091e9553751845f2aa3be0b5a88d9ac7 Mon Sep 17 00:00:00 2001
+From: Corentin LABBE <clabbe.montjoie@gmail.com>
+Date: Fri, 7 Oct 2016 10:25:50 +0200
+Subject: [PATCH 3/9] ARM: sun8i: dt: Add DT bindings documentation for
+ Allwinner sun8i-emac
+
+This patch adds documentation for Device-Tree bindings for the
+Allwinner sun8i-emac driver.
+
+Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
+---
+ .../bindings/net/allwinner,sun8i-emac.txt | 70 ++++++++++++++++++++++
+ 1 file changed, 70 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/net/allwinner,sun8i-emac.txt
+
+diff --git a/Documentation/devicetree/bindings/net/allwinner,sun8i-emac.txt b/Documentation/devicetree/bindings/net/allwinner,sun8i-emac.txt
+new file mode 100644
+index 0000000..92e4ef3b
+--- /dev/null
++++ b/Documentation/devicetree/bindings/net/allwinner,sun8i-emac.txt
+@@ -0,0 +1,70 @@
++* Allwinner sun8i EMAC ethernet controller
++
++Required properties:
++- compatible: should be one of the following string:
++ "allwinner,sun8i-a83t-emac"
++ "allwinner,sun8i-h3-emac"
++ "allwinner,sun50i-a64-emac"
++- reg: address and length of the register for the device.
++- syscon: A phandle to the syscon of the SoC
++- interrupts: interrupt for the device
++- clocks: A phandle to the reference clock for this device
++- clock-names: should be "ahb"
++- resets: A phandle to the reset control for this device
++- reset-names: should be "ahb"
++- phy-mode: See ethernet.txt
++- phy-handle: See ethernet.txt
++- #address-cells: shall be 1
++- #size-cells: shall be 0
++
++Optional properties:
++- allwinner,tx-delay: TX clock delay chain value. Range value is 0-0x07. Default is 0)
++- allwinner,rx-delay: RX clock delay chain value. Range value is 0-0x1F. Default is 0)
++Both delay properties does not have units, there are arbitrary value.
++The TX/RX clock delay chain settings are board specific and could be found
++in vendor FEX files.
++
++Optional properties for "allwinner,sun8i-h3-emac":
++- allwinner,leds-active-low: EPHY LEDs are active low
++
++Required child node of emac:
++- mdio bus node: should be named mdio
++
++Required properties of the mdio node:
++- #address-cells: shall be 1
++- #size-cells: shall be 0
++
++The device node referenced by "phy" or "phy-handle" should be a child node
++of the mdio node. See phy.txt for the generic PHY bindings.
++
++Required properties of the phy node with "allwinner,sun8i-h3-emac":
++- clocks: an extra phandle to the reference clock for the EPHY
++- resets: an extra phandle to the reset control for the EPHY
++
++Example:
++
++emac: ethernet@01c0b000 {
++ compatible = "allwinner,sun8i-h3-emac";
++ syscon = <&syscon>;
++ reg = <0x01c0b000 0x104>;
++ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
++ resets = <&ccu RST_BUS_EMAC>;
++ reset-names = "ahb";
++ clocks = <&ccu CLK_BUS_EMAC>;
++ clock-names = "ahb";
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ phy = <&int_mii_phy>;
++ phy-mode = "mii";
++ allwinner,leds-active-low;
++ mdio: mdio {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ int_mii_phy: ethernet-phy@1 {
++ reg = <1>;
++ clocks = <&ccu CLK_BUS_EPHY>;
++ resets = <&ccu RST_BUS_EPHY>;
++ };
++ };
++};
+--
+2.9.3
+
+From 95d456fcdd33eb7c1512956050faba648550e06f Mon Sep 17 00:00:00 2001
+From: Corentin LABBE <clabbe.montjoie@gmail.com>
+Date: Fri, 7 Oct 2016 10:25:51 +0200
+Subject: [PATCH 4/9] ARM: dts: sun8i-h3: Add dt node for the syscon control
+ module
+
+This patch add the dt node for the syscon register present on the
+Allwinner H3.
+
+Only two register are present in this syscon and the only one useful is
+the one dedicated to EMAC clock.
+
+Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
+---
+ arch/arm/boot/dts/sun8i-h3.dtsi | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
+index fdf9fdb..d658a596 100644
+--- a/arch/arm/boot/dts/sun8i-h3.dtsi
++++ b/arch/arm/boot/dts/sun8i-h3.dtsi
+@@ -140,6 +140,11 @@
+ #size-cells = <1>;
+ ranges;
+
++ syscon: syscon@01c00000 {
++ compatible = "syscon";
++ reg = <0x01c00000 0x1000>;
++ };
++
+ dma: dma-controller@01c02000 {
+ compatible = "allwinner,sun8i-h3-dma";
+ reg = <0x01c02000 0x1000>;
+--
+2.9.3
+
+From 7837b66f2bce01da31ec4c005023c729ba3f17a7 Mon Sep 17 00:00:00 2001
+From: Corentin LABBE <clabbe.montjoie@gmail.com>
+Date: Fri, 7 Oct 2016 10:25:52 +0200
+Subject: [PATCH 5/9] ARM: dts: sun8i-h3: add sun8i-emac ethernet driver
+
+The sun8i-emac is an ethernet MAC hardware that support 10/100/1000
+speed.
+
+This patch enable the sun8i-emac on the Allwinner H3 SoC Device-tree.
+The SoC H3 have an internal PHY, so optionals syscon and ephy are set.
+
+Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
+---
+ arch/arm/boot/dts/sun8i-h3.dtsi | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
+index d658a596..54174cf 100644
+--- a/arch/arm/boot/dts/sun8i-h3.dtsi
++++ b/arch/arm/boot/dts/sun8i-h3.dtsi
+@@ -446,6 +446,30 @@
+ status = "disabled";
+ };
+
++ emac: ethernet@1c30000 {
++ compatible = "allwinner,sun8i-h3-emac";
++ syscon = <&syscon>;
++ reg = <0x01c30000 0x104>;
++ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
++ resets = <&ccu RST_BUS_EMAC>;
++ reset-names = "ahb";
++ clocks = <&ccu CLK_BUS_EMAC>;
++ clock-names = "ahb";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "disabled";
++
++ mdio: mdio {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ int_mii_phy: ethernet-phy@1 {
++ reg = <1>;
++ clocks = <&ccu CLK_BUS_EPHY>;
++ resets = <&ccu RST_BUS_EPHY>;
++ };
++ };
++ };
++
+ gic: interrupt-controller@01c81000 {
+ compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
+ reg = <0x01c81000 0x1000>,
+--
+2.9.3
+
+From e9687b752a1551ae420a94ff44254831ef464557 Mon Sep 17 00:00:00 2001
+From: Corentin LABBE <clabbe.montjoie@gmail.com>
+Date: Fri, 7 Oct 2016 10:25:53 +0200
+Subject: [PATCH 6/9] ARM: dts: sun8i: Enable sun8i-emac on the Orange PI PC
+
+The sun8i-emac hardware is present on the Orange PI PC.
+It uses the internal PHY.
+
+This patch create the needed emac node.
+
+Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
+---
+ arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
+index daf50b9a6..71717cc 100644
+--- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
++++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
+@@ -54,6 +54,7 @@
+
+ aliases {
+ serial0 = &uart0;
++ ethernet0 = &emac;
+ };
+
+ chosen {
+@@ -165,3 +166,10 @@
+ /* USB VBUS is always on */
+ status = "okay";
+ };
++
++&emac {
++ phy-handle = <&int_mii_phy>;
++ phy-mode = "mii";
++ allwinner,leds-active-low;
++ status = "okay";
++};
+--
+2.9.3
+
+From 7df9f84ca65a398b1bb692344fa26c67235f19d3 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Fri, 7 Oct 2016 10:25:54 +0200
+Subject: [PATCH 7/9] ARM: dts: sun8i: Enable sun8i-emac on the Orange PI One
+
+The sun8i-emac hardware is present on the Orange PI One.
+It uses the internal PHY.
+
+This patch create the needed emac node.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
+---
+ arch/arm/boot/dts/sun8i-h3-orangepi-one.dts | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
+index 0adf932..25f2455 100644
+--- a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
++++ b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
+@@ -54,6 +54,7 @@
+
+ aliases {
+ serial0 = &uart0;
++ ethernet0 = &emac;
+ };
+
+ chosen {
+@@ -94,6 +95,13 @@
+ status = "okay";
+ };
+
++&emac {
++ phy-handle = <&int_mii_phy>;
++ phy-mode = "mii";
++ allwinner,leds-active-low;
++ status = "okay";
++};
++
+ &mmc0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
+--
+2.9.3
+
+From dd8a48a9d7250d4bfc501dd5a4e8179ffac27d11 Mon Sep 17 00:00:00 2001
+From: Corentin LABBE <clabbe.montjoie@gmail.com>
+Date: Fri, 7 Oct 2016 10:25:55 +0200
+Subject: [PATCH 8/9] ARM: dts: sun8i: Enable sun8i-emac on the Orange Pi 2
+
+The sun8i-emac hardware is present on the Orange PI 2.
+It uses the internal PHY.
+
+This patch create the needed emac node.
+
+Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
+---
+ arch/arm/boot/dts/sun8i-h3-orangepi-2.dts | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
+index f93f5d1..5608eb4 100644
+--- a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
++++ b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
+@@ -54,6 +54,7 @@
+
+ aliases {
+ serial0 = &uart0;
++ ethernet0 = &emac;
+ };
+
+ chosen {
+@@ -184,3 +185,10 @@
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+ };
++
++&emac {
++ phy-handle = <&int_mii_phy>;
++ phy-mode = "mii";
++ allwinner,leds-active-low;
++ status = "okay";
++};
+--
+2.9.3
+
+From cc1f0d509ecebebe8b50c97b71c84fb082ce0e56 Mon Sep 17 00:00:00 2001
+From: Corentin LABBE <clabbe.montjoie@gmail.com>
+Date: Wed, 5 Oct 2016 11:48:24 +0200
+Subject: [PATCH 9/9] ARM: dt: sun8i-h3: Add sunxi-sid to dts for sun8i-h3
+
+This patch add support for the sunxi-sid driver to the device tree for sun8i-h3.
+
+Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
+---
+ arch/arm/boot/dts/sun8i-h3.dtsi | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
+index 54174cf..8628b38 100644
+--- a/arch/arm/boot/dts/sun8i-h3.dtsi
++++ b/arch/arm/boot/dts/sun8i-h3.dtsi
+@@ -211,6 +211,11 @@
+ #size-cells = <0>;
+ };
+
++ sid: eeprom@01c14200 {
++ compatible = "allwinner,sun7i-a20-sid";
++ reg = <0x01c14200 0x200>;
++ };
++
+ usbphy: phy@01c19400 {
+ compatible = "allwinner,sun8i-h3-usb-phy";
+ reg = <0x01c19400 0x2c>,
+--
+2.9.3
+
diff --git a/HID-microsoft-Add-Surface-4-type-cover-pro-4-JP.patch b/HID-microsoft-Add-Surface-4-type-cover-pro-4-JP.patch
new file mode 100644
index 000000000..f231aa10a
--- /dev/null
+++ b/HID-microsoft-Add-Surface-4-type-cover-pro-4-JP.patch
@@ -0,0 +1,76 @@
+From b490a8537df60d449199e162417da74ee9262515 Mon Sep 17 00:00:00 2001
+From: Yuta Kobayashi <alu.ula@outlook.com>
+Date: Fri, 12 Aug 2016 07:49:17 +0000
+Subject: [PATCH] HID: microsoft: Add Surface 4 type cover pro 4 (JP)
+
+Adding support for the Microsoft Surface 4 Type Cover Pro (JP).
+
+Signed-off-by: Yuta Kobayashi <alu.ula@outlook.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+---
+ drivers/hid/hid-core.c | 2 ++
+ drivers/hid/hid-ids.h | 1 +
+ drivers/hid/hid-microsoft.c | 2 ++
+ drivers/hid/usbhid/hid-quirks.c | 1 +
+ 4 files changed, 6 insertions(+)
+
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index ed10d4f..45400de 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -727,6 +727,7 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type)
+ (hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 ||
+ hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2 ||
+ hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP ||
++ hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP ||
+ hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 ||
+ hid->product == USB_DEVICE_ID_MS_POWER_COVER) &&
+ hid->group == HID_GROUP_MULTITOUCH)
+@@ -1982,6 +1983,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) },
++ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_7K) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_600) },
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index da1c58e..3466f0d 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -713,6 +713,7 @@
+ #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 0x07dc
+ #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2 0x07e2
+ #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP 0x07dd
++#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP 0x07e9
+ #define USB_DEVICE_ID_MS_TYPE_COVER_3 0x07de
+ #define USB_DEVICE_ID_MS_POWER_COVER 0x07da
+
+diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
+index e924d55..56c586f 100644
+--- a/drivers/hid/hid-microsoft.c
++++ b/drivers/hid/hid-microsoft.c
+@@ -288,6 +288,8 @@ static const struct hid_device_id ms_devices[] = {
+ .driver_data = MS_HIDINPUT },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP),
+ .driver_data = MS_HIDINPUT },
++ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP),
++ .driver_data = MS_HIDINPUT },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3),
+ .driver_data = MS_HIDINPUT },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER),
+diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
+index b4b8c6a..1fccffd 100644
+--- a/drivers/hid/usbhid/hid-quirks.c
++++ b/drivers/hid/usbhid/hid-quirks.c
+@@ -98,6 +98,7 @@ static const struct hid_blacklist {
+ { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3, HID_QUIRK_NO_INIT_REPORTS },
+ { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2, HID_QUIRK_NO_INIT_REPORTS },
+ { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP, HID_QUIRK_NO_INIT_REPORTS },
++ { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP, HID_QUIRK_NO_INIT_REPORTS },
+ { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS },
+ { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS },
+ { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
+--
+2.7.4
+
diff --git a/PCI-Lock-down-BAR-access-when-module-security-is-ena.patch b/PCI-Lock-down-BAR-access-when-module-security-is-ena.patch
index 23a514f3b..9500b96d2 100644
--- a/PCI-Lock-down-BAR-access-when-module-security-is-ena.patch
+++ b/PCI-Lock-down-BAR-access-when-module-security-is-ena.patch
@@ -1,8 +1,7 @@
-From 655fbf360e1481db4f06001f893d388c15ac307f Mon Sep 17 00:00:00 2001
+From 6f756b32a45b022428e33ce20181e874c73ca82e Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Thu, 8 Mar 2012 10:10:38 -0500
-Subject: [PATCH 02/20] PCI: Lock down BAR access when module security is
- enabled
+Subject: [PATCH] PCI: Lock down BAR access when module security is enabled
Any hardware that can potentially generate DMA has to be locked down from
userspace in order to avoid it being possible for an attacker to modify
@@ -18,7 +17,7 @@ Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
3 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
-index 312f23a8429c..93e6ac103dd0 100644
+index bcd10c7..a950301 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -30,6 +30,7 @@
@@ -29,7 +28,7 @@ index 312f23a8429c..93e6ac103dd0 100644
#include "pci.h"
static int sysfs_initialized; /* = 0 */
-@@ -710,6 +711,9 @@ static ssize_t pci_write_config(struct file *filp, struct kobject *kobj,
+@@ -716,6 +717,9 @@ static ssize_t pci_write_config(struct file *filp, struct kobject *kobj,
loff_t init_off = off;
u8 *data = (u8 *) buf;
@@ -39,7 +38,7 @@ index 312f23a8429c..93e6ac103dd0 100644
if (off > dev->cfg_size)
return 0;
if (off + count > dev->cfg_size) {
-@@ -1004,6 +1008,9 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
+@@ -1007,6 +1011,9 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
resource_size_t start, end;
int i;
@@ -49,7 +48,7 @@ index 312f23a8429c..93e6ac103dd0 100644
for (i = 0; i < PCI_ROM_RESOURCE; i++)
if (res == &pdev->resource[i])
break;
-@@ -1105,6 +1112,9 @@ static ssize_t pci_write_resource_io(struct file *filp, struct kobject *kobj,
+@@ -1106,6 +1113,9 @@ static ssize_t pci_write_resource_io(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
@@ -60,7 +59,7 @@ index 312f23a8429c..93e6ac103dd0 100644
}
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
-index 3f155e78513f..4265ea07e3b0 100644
+index 2408abe..59f321c 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -116,6 +116,9 @@ static ssize_t proc_bus_pci_write(struct file *file, const char __user *buf,
@@ -85,7 +84,7 @@ index 3f155e78513f..4265ea07e3b0 100644
ret = pci_domain_nr(dev->bus);
@@ -233,7 +239,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
struct pci_filp_private *fpriv = file->private_data;
- int i, ret;
+ int i, ret, write_combine;
- if (!capable(CAP_SYS_RAWIO))
+ if (!capable(CAP_SYS_RAWIO) || secure_modules())
@@ -93,7 +92,7 @@ index 3f155e78513f..4265ea07e3b0 100644
/* Make sure the caller is mapping a real resource for this device */
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c
-index b91c4da68365..98f5637304d1 100644
+index b91c4da..98f5637 100644
--- a/drivers/pci/syscall.c
+++ b/drivers/pci/syscall.c
@@ -10,6 +10,7 @@
@@ -114,5 +113,5 @@ index b91c4da68365..98f5637304d1 100644
dev = pci_get_bus_and_slot(bus, dfn);
--
-2.4.3
+2.9.2
diff --git a/arm-i.MX6-Utilite-device-dtb.patch b/arm-i.MX6-Utilite-device-dtb.patch
deleted file mode 100644
index efffd77bd..000000000
--- a/arm-i.MX6-Utilite-device-dtb.patch
+++ /dev/null
@@ -1,354 +0,0 @@
-From: Christopher Spinrath <christopher.spinrath@xxxxxxxxxxxxxx>
-
-The CompuLab Utilite Pro is a miniature fanless desktop pc based on
-the i.MX6 Quad powered cm-fx6 module. It features two serial ports,
-USB OTG, 4x USB, analog audio and S/PDIF, 2x Gb Ethernet, HDMI and
-DVI ports, an on-board 32GB SSD, a mmc slot, and on-board wifi/bt.
-
-Add initial support for it including USB, Ethernet (both ports), sata
-and HDMI support.
-
-Signed-off-by: Christopher Spinrath <christopher.spinrath@xxxxxxxxxxxxxx>
----
- arch/arm/boot/dts/Makefile | 1 +
- arch/arm/boot/dts/imx6q-utilite-pro.dts | 128 ++++++++++++++++++++++++++++++++
- 2 files changed, 129 insertions(+)
- create mode 100644 arch/arm/boot/dts/imx6q-utilite-pro.dts
-
-diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
-index 515a428..287044c 100644
---- a/arch/arm/boot/dts/Makefile
-+++ b/arch/arm/boot/dts/Makefile
-@@ -369,6 +369,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
- imx6q-tx6q-1110.dtb \
- imx6q-tx6q-11x0-mb7.dtb \
- imx6q-udoo.dtb \
-+ imx6q-utilite-pro.dtb \
- imx6q-wandboard.dtb \
- imx6q-wandboard-revb1.dtb \
- imx6qp-nitrogen6_max.dtb \
-diff --git a/arch/arm/boot/dts/imx6q-utilite-pro.dts b/arch/arm/boot/dts/imx6q-utilite-pro.dts
-new file mode 100644
-index 0000000..bcd8e0d
---- /dev/null
-+++ b/arch/arm/boot/dts/imx6q-utilite-pro.dts
-@@ -0,0 +1,128 @@
-+/*
-+ * Copyright 2016 Christopher Spinrath
-+ * Copyright 2013 CompuLab Ltd.
-+ *
-+ * Based on the GPLv2 licensed devicetree distributed with the vendor
-+ * kernel for the Utilite Pro:
-+ * Copyright 2013 CompuLab Ltd.
-+ * Author: Valentin Raevsky <valentin@xxxxxxxxxxxxxx>
-+ *
-+ * The code contained herein is licensed under the GNU General Public
-+ * License. You may obtain a copy of the GNU General Public License
-+ * Version 2 or later at the following locations:
-+ *
-+ * http://www.opensource.org/licenses/gpl-license.html
-+ * http://www.gnu.org/copyleft/gpl.html
-+ */
-+
-+#include "imx6q-cm-fx6.dts"
-+
-+/ {
-+ model = "CompuLab Utilite Pro";
-+ compatible = "compulab,utilite-pro", "compulab,cm-fx6", "fsl,imx6q";
-+
-+ aliases {
-+ ethernet1 = &eth1;
-+ rtc0 = &em3027;
-+ rtc1 = &snvs_rtc;
-+ };
-+
-+ gpio-keys {
-+ compatible = "gpio-keys";
-+ power {
-+ label = "Power Button";
-+ gpios = <&gpio1 29 1>;
-+ linux,code = <116>; /* KEY_POWER */
-+ gpio-key,wakeup;
-+ };
-+ };
-+};
-+
-+&hdmi {
-+ ddc-i2c-bus = <&i2c2>;
-+ status = "okay";
-+};
-+
-+&i2c1 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_i2c1>;
-+ status = "okay";
-+
-+ eeprom@50 {
-+ compatible = "at24,24c02";
-+ reg = <0x50>;
-+ pagesize = <16>;
-+ };
-+
-+ em3027: rtc@56 {
-+ compatible = "emmicro,em3027";
-+ reg = <0x56>;
-+ };
-+};
-+
-+&i2c2 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_i2c2>;
-+ status = "okay";
-+};
-+
-+&iomuxc {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_hog>;
-+
-+ hog {
-+ pinctrl_hog: hoggrp {
-+ fsl,pins = <
-+ /* power button */
-+ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
-+ >;
-+ };
-+ };
-+
-+ imx6q-utilite-pro {
-+ pinctrl_i2c1: i2c1grp {
-+ fsl,pins = <
-+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
-+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
-+ >;
-+ };
-+
-+ pinctrl_i2c2: i2c2grp {
-+ fsl,pins = <
-+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
-+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
-+ >;
-+ };
-+
-+ pinctrl_uart2: uart2grp {
-+ fsl,pins = <
-+ MX6QDL_PAD_GPIO_7__UART2_TX_DATA 0x1b0b1
-+ MX6QDL_PAD_GPIO_8__UART2_RX_DATA 0x1b0b1
-+ MX6QDL_PAD_SD4_DAT5__UART2_RTS_B 0x1b0b1
-+ MX6QDL_PAD_SD4_DAT6__UART2_CTS_B 0x1b0b1
-+ >;
-+ };
-+ };
-+};
-+
-+&pcie {
-+ pcie@0,0 {
-+ reg = <0x000000 0 0 0 0>;
-+ #address-cells = <3>;
-+ #size-cells = <2>;
-+
-+ /* non-removable i211 ethernet card */
-+ eth1: intel,i211@pcie0,0 {
-+ reg = <0x010000 0 0 0 0>;
-+ };
-+ };
-+};
-+
-+&uart2 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_uart2>;
-+ fsl,uart-has-rtscts;
-+ dma-names = "rx", "tx";
-+ dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
-+ status = "okay";
-+};
---
-2.8.2
-From: Christopher Spinrath <christopher.spinrath@xxxxxxxxxxxxxx>
-
-The cm-fx6 module has an on-board spi-flash chip for its firmware, an
-eeprom (containing e.g. the mac address of the on-board Ethernet),
-a sata port, a pcie controller, an USB hub, and an USB otg port.
-Enable support for them. In addition, enable syscon poweroff support.
-
-Signed-off-by: Christopher Spinrath <christopher.spinrath@xxxxxxxxxxxxxx>
----
- arch/arm/boot/dts/imx6q-cm-fx6.dts | 136 +++++++++++++++++++++++++++++++++++++
- 1 file changed, 136 insertions(+)
-
-diff --git a/arch/arm/boot/dts/imx6q-cm-fx6.dts b/arch/arm/boot/dts/imx6q-cm-fx6.dts
-index 99b46f8..f4fc22e 100644
---- a/arch/arm/boot/dts/imx6q-cm-fx6.dts
-+++ b/arch/arm/boot/dts/imx6q-cm-fx6.dts
-@@ -31,6 +31,61 @@
- linux,default-trigger = "heartbeat";
- };
- };
-+
-+ regulators {
-+ compatible = "simple-bus";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ reg_usb_otg_vbus: usb_otg_vbus {
-+ compatible = "regulator-fixed";
-+ regulator-name = "usb_otg_vbus";
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
-+ gpio = <&gpio3 22 0>;
-+ enable-active-high;
-+ };
-+
-+ reg_usb_h1_vbus: usb_h1_vbus {
-+ compatible = "regulator-fixed";
-+ regulator-name = "usb_h1_vbus";
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
-+ gpio = <&gpio7 8 0>;
-+ enable-active-high;
-+ };
-+ };
-+};
-+
-+&ecspi1 {
-+ fsl,spi-num-chipselects = <2>;
-+ cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_ecspi1>;
-+ status = "okay";
-+
-+ flash: m25p80@0 {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ compatible = "st,m25p", "jedec,spi-nor";
-+ spi-max-frequency = <20000000>;
-+ reg = <0>;
-+
-+ partition@0 {
-+ label = "uboot";
-+ reg = <0x0 0xc0000>;
-+ };
-+
-+ partition@c0000 {
-+ label = "uboot environment";
-+ reg = <0xc0000 0x40000>;
-+ };
-+
-+ partition@100000 {
-+ label = "reserved";
-+ reg = <0x100000 0x100000>;
-+ };
-+ };
- };
-
- &fec {
-@@ -46,8 +101,31 @@
- status = "okay";
- };
-
-+&i2c3 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_i2c3>;
-+ status = "okay";
-+ clock-frequency = <100000>;
-+
-+ eeprom@50 {
-+ compatible = "at24,24c02";
-+ reg = <0x50>;
-+ pagesize = <16>;
-+ };
-+};
-+
- &iomuxc {
- imx6q-cm-fx6 {
-+ pinctrl_ecspi1: ecspi1grp {
-+ fsl,pins = <
-+ MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
-+ MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
-+ MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
-+ MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x100b1
-+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x100b1
-+ >;
-+ };
-+
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
-@@ -91,17 +169,75 @@
- >;
- };
-
-+ pinctrl_i2c3: i2c3grp {
-+ fsl,pins = <
-+ MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
-+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
-+ >;
-+ };
-+
-+ pinctrl_pcie: pciegrp {
-+ fsl,pins = <
-+ MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000
-+ MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x80000000
-+ >;
-+ };
-+
- pinctrl_uart4: uart4grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
- MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
- >;
- };
-+
-+ pinctrl_usbh1: usbh1grp {
-+ fsl,pins = <
-+ MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x80000000
-+ >;
-+ };
-+
-+ pinctrl_usbotg: usbotggrp {
-+ fsl,pins = <
-+ MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
-+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000
-+ >;
-+ };
- };
- };
-
-+&pcie {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_pcie>;
-+ reset-gpio = <&gpio1 26 0>;
-+ power-on-gpio = <&gpio2 24 0>;
-+ status = "okay";
-+};
-+
-+&sata {
-+ status = "okay";
-+};
-+
-+&snvs_poweroff {
-+ status = "okay";
-+};
-+
- &uart4 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart4>;
- status = "okay";
- };
-+
-+&usbotg {
-+ vbus-supply = <&reg_usb_otg_vbus>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_usbotg>;
-+ dr_mode = "otg";
-+ status = "okay";
-+};
-+
-+&usbh1 {
-+ vbus-supply = <&reg_usb_h1_vbus>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_usbh1>;
-+ status = "okay";
-+};
---
-2.8.2
-
diff --git a/arm-revert-mmc-omap_hsmmc-Use-dma_request_chan-for-reque.patch b/arm-revert-mmc-omap_hsmmc-Use-dma_request_chan-for-reque.patch
new file mode 100644
index 000000000..b55dec0cb
--- /dev/null
+++ b/arm-revert-mmc-omap_hsmmc-Use-dma_request_chan-for-reque.patch
@@ -0,0 +1,100 @@
+From bb3e08008c0e48fd4f51a0f0957eecae61a24d69 Mon Sep 17 00:00:00 2001
+From: Peter Robinson <pbrobinson@gmail.com>
+Date: Tue, 1 Nov 2016 09:35:30 +0000
+Subject: [PATCH] Revert "mmc: omap_hsmmc: Use dma_request_chan() for
+ requesting DMA channel"
+
+This reverts commit 81eef6ca92014845d40e3f1310e42b7010303acc.
+---
+ drivers/mmc/host/omap_hsmmc.c | 50 ++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 40 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index 24ebc9a..3563321 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -32,6 +32,7 @@
+ #include <linux/of_irq.h>
+ #include <linux/of_gpio.h>
+ #include <linux/of_device.h>
++#include <linux/omap-dmaengine.h>
+ #include <linux/mmc/host.h>
+ #include <linux/mmc/core.h>
+ #include <linux/mmc/mmc.h>
+@@ -1992,6 +1993,8 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
+ struct resource *res;
+ int ret, irq;
+ const struct of_device_id *match;
++ dma_cap_mask_t mask;
++ unsigned tx_req, rx_req;
+ const struct omap_mmc_of_data *data;
+ void __iomem *base;
+
+@@ -2121,17 +2124,44 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
+
+ omap_hsmmc_conf_bus_power(host);
+
+- host->rx_chan = dma_request_chan(&pdev->dev, "rx");
+- if (IS_ERR(host->rx_chan)) {
+- dev_err(mmc_dev(host->mmc), "RX DMA channel request failed\n");
+- ret = PTR_ERR(host->rx_chan);
++ if (!pdev->dev.of_node) {
++ res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
++ if (!res) {
++ dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
++ ret = -ENXIO;
++ goto err_irq;
++ }
++ tx_req = res->start;
++
++ res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
++ if (!res) {
++ dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
++ ret = -ENXIO;
++ goto err_irq;
++ }
++ rx_req = res->start;
++ }
++
++ dma_cap_zero(mask);
++ dma_cap_set(DMA_SLAVE, mask);
++
++ host->rx_chan =
++ dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
++ &rx_req, &pdev->dev, "rx");
++
++ if (!host->rx_chan) {
++ dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel\n");
++ ret = -ENXIO;
+ goto err_irq;
+ }
+
+- host->tx_chan = dma_request_chan(&pdev->dev, "tx");
+- if (IS_ERR(host->tx_chan)) {
+- dev_err(mmc_dev(host->mmc), "TX DMA channel request failed\n");
+- ret = PTR_ERR(host->tx_chan);
++ host->tx_chan =
++ dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
++ &tx_req, &pdev->dev, "tx");
++
++ if (!host->tx_chan) {
++ dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel\n");
++ ret = -ENXIO;
+ goto err_irq;
+ }
+
+@@ -2189,9 +2219,9 @@ err_slot_name:
+ mmc_remove_host(mmc);
+ err_irq:
+ device_init_wakeup(&pdev->dev, false);
+- if (!IS_ERR_OR_NULL(host->tx_chan))
++ if (host->tx_chan)
+ dma_release_channel(host->tx_chan);
+- if (!IS_ERR_OR_NULL(host->rx_chan))
++ if (host->rx_chan)
+ dma_release_channel(host->rx_chan);
+ pm_runtime_dont_use_autosuspend(host->dev);
+ pm_runtime_put_sync(host->dev);
+--
+2.9.3
+
diff --git a/arm64-ACPI-parse-SPCR-table.patch b/arm64-ACPI-parse-SPCR-table.patch
new file mode 100644
index 000000000..ba8a70679
--- /dev/null
+++ b/arm64-ACPI-parse-SPCR-table.patch
@@ -0,0 +1,596 @@
+From patchwork Fri Aug 12 11:07:14 2016
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v9,1/4] of/serial: move earlycon early_param handling to serial
+From: Aleksey Makarov <aleksey.makarov@linaro.org>
+X-Patchwork-Id: 9276727
+Message-Id: <20160812110717.12351-1-aleksey.makarov@linaro.org>
+To: "Rafael J . Wysocki" <rjw@rjwysocki.net>,
+ Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: linux-serial@vger.kernel.org, linux-acpi@vger.kernel.org,
+ linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
+ Aleksey Makarov <aleksey.makarov@linaro.org>,
+ Russell King <linux@arm.linux.org.uk>, Len Brown <lenb@kernel.org>,
+ Leif Lindholm <leif.lindholm@linaro.org>,
+ Graeme Gregory <graeme.gregory@linaro.org>, Al Stone <ahs3@redhat.com>,
+ Christopher Covington <cov@codeaurora.org>,
+ Yury Norov <ynorov@caviumnetworks.com>,
+ Peter Hurley <peter@hurleysoftware.com>,
+ Andy Shevchenko <andy.shevchenko@gmail.com>,
+ "Zheng, Lv" <lv.zheng@intel.com>, Mark Salter <msalter@redhat.com>,
+ Kefeng Wang <wangkefeng.wang@huawei.com>,
+ Rob Herring <robh+dt@kernel.org>, Frank Rowand <frowand.list@gmail.com>,
+ Jiri Slaby <jslaby@suse.com>, devicetree@vger.kernel.org
+Date: Fri, 12 Aug 2016 14:07:14 +0300
+
+From: Leif Lindholm <leif.lindholm@linaro.org>
+
+We have multiple "earlycon" early_param handlers - merge the DT one into
+the main earlycon one. It's a cleanup that also will be useful
+to defer setting up DT console until ACPI/DT decision is made.
+
+Rename the exported function to avoid clashing with the function from
+arch/microblaze/kernel/prom.c
+
+Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
+Signed-off-by: Aleksey Makarov <aleksey.makarov@linaro.org>
+Acked-by: Rob Herring <robh@kernel.org>
+Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Reviewed-by: Peter Hurley <peter@hurleysoftware.com>
+Tested-by: Kefeng Wang <wangkefeng.wang@huawei.com>
+---
+ drivers/of/fdt.c | 11 +----------
+ drivers/tty/serial/earlycon.c | 2 +-
+ include/linux/of_fdt.h | 3 +++
+ 3 files changed, 5 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
+index 55f1b83..741cac53 100644
+--- a/drivers/of/fdt.c
++++ b/drivers/of/fdt.c
+@@ -924,7 +924,7 @@ static inline void early_init_dt_check_for_initrd(unsigned long node)
+
+ #ifdef CONFIG_SERIAL_EARLYCON
+
+-static int __init early_init_dt_scan_chosen_serial(void)
++int __init early_init_dt_scan_chosen_stdout(void)
+ {
+ int offset;
+ const char *p, *q, *options = NULL;
+@@ -968,15 +968,6 @@ static int __init early_init_dt_scan_chosen_serial(void)
+ }
+ return -ENODEV;
+ }
+-
+-static int __init setup_of_earlycon(char *buf)
+-{
+- if (buf)
+- return 0;
+-
+- return early_init_dt_scan_chosen_serial();
+-}
+-early_param("earlycon", setup_of_earlycon);
+ #endif
+
+ /**
+diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
+index 067783f..7aae655 100644
+--- a/drivers/tty/serial/earlycon.c
++++ b/drivers/tty/serial/earlycon.c
+@@ -209,7 +209,7 @@ static int __init param_setup_earlycon(char *buf)
+ * don't generate a warning from parse_early_params() in that case
+ */
+ if (!buf || !buf[0])
+- return 0;
++ return early_init_dt_scan_chosen_stdout();
+
+ err = setup_earlycon(buf);
+ if (err == -ENOENT || err == -EALREADY)
+diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
+index 26c3302..4341f32 100644
+--- a/include/linux/of_fdt.h
++++ b/include/linux/of_fdt.h
+@@ -14,6 +14,7 @@
+
+ #include <linux/types.h>
+ #include <linux/init.h>
++#include <linux/errno.h>
+
+ /* Definitions used by the flattened device tree */
+ #define OF_DT_HEADER 0xd00dfeed /* marker */
+@@ -66,6 +67,7 @@ extern int early_init_dt_scan_chosen(unsigned long node, const char *uname,
+ int depth, void *data);
+ extern int early_init_dt_scan_memory(unsigned long node, const char *uname,
+ int depth, void *data);
++extern int early_init_dt_scan_chosen_stdout(void);
+ extern void early_init_fdt_scan_reserved_mem(void);
+ extern void early_init_fdt_reserve_self(void);
+ extern void early_init_dt_add_memory_arch(u64 base, u64 size);
+@@ -94,6 +96,7 @@ extern void early_get_first_memblock_info(void *, phys_addr_t *);
+ extern u64 of_flat_dt_translate_address(unsigned long node);
+ extern void of_fdt_limit_memory(int limit);
+ #else /* CONFIG_OF_FLATTREE */
++static inline int early_init_dt_scan_chosen_stdout(void) { return -ENODEV; }
+ static inline void early_init_fdt_scan_reserved_mem(void) {}
+ static inline void early_init_fdt_reserve_self(void) {}
+ static inline const char *of_flat_dt_get_machine_name(void) { return NULL; }
+From patchwork Thu Aug 11 15:31:39 2016
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v9,2/4] ACPI: parse SPCR and enable matching console
+From: Aleksey Makarov <aleksey.makarov@linaro.org>
+X-Patchwork-Id: 9275443
+Message-Id: <20160811153152.755-3-aleksey.makarov@linaro.org>
+To: "Rafael J . Wysocki" <rjw@rjwysocki.net>,
+ Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: linux-serial@vger.kernel.org, linux-acpi@vger.kernel.org,
+ linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
+ Aleksey Makarov <aleksey.makarov@linaro.org>,
+ Russell King <linux@arm.linux.org.uk>, Len Brown <lenb@kernel.org>,
+ Leif Lindholm <leif.lindholm@linaro.org>,
+ Graeme Gregory <graeme.gregory@linaro.org>, Al Stone <ahs3@redhat.com>,
+ Christopher Covington <cov@codeaurora.org>,
+ Yury Norov <ynorov@caviumnetworks.com>,
+ Peter Hurley <peter@hurleysoftware.com>,
+ Andy Shevchenko <andy.shevchenko@gmail.com>,
+ "Zheng, Lv" <lv.zheng@intel.com>, Mark Salter <msalter@redhat.com>,
+ Kefeng Wang <wangkefeng.wang@huawei.com>, Jiri Slaby <jslaby@suse.com>
+Date: Thu, 11 Aug 2016 18:31:39 +0300
+
+'ARM Server Base Boot Requiremets' [1] mentions SPCR (Serial Port
+Console Redirection Table) [2] as a mandatory ACPI table that
+specifies the configuration of serial console.
+
+Defer initialization of DT earlycon until ACPI/DT decision is made.
+
+Parse the ACPI SPCR table, setup earlycon if required,
+enable specified console.
+
+Thanks to Peter Hurley for explaining how this should work.
+
+[1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0044a/index.html
+[2] https://msdn.microsoft.com/en-us/library/windows/hardware/dn639132(v=vs.85).aspx
+
+Signed-off-by: Aleksey Makarov <aleksey.makarov@linaro.org>
+Reviewed-by: Peter Hurley <peter@hurleysoftware.com>
+Tested-by: Kefeng Wang <wangkefeng.wang@huawei.com>
+Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+---
+ drivers/acpi/Kconfig | 3 ++
+ drivers/acpi/Makefile | 1 +
+ drivers/acpi/spcr.c | 111 ++++++++++++++++++++++++++++++++++++++++++
+ drivers/tty/serial/earlycon.c | 19 +++++++-
+ include/linux/acpi.h | 6 +++
+ include/linux/serial_core.h | 9 +++-
+ 6 files changed, 146 insertions(+), 3 deletions(-)
+ create mode 100644 drivers/acpi/spcr.c
+
+diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
+index 6cef2d1..4a269f9 100644
+--- a/drivers/acpi/Kconfig
++++ b/drivers/acpi/Kconfig
+@@ -77,6 +77,9 @@ config ACPI_DEBUGGER_USER
+
+ endif
+
++config ACPI_SPCR_TABLE
++ bool
++
+ config ACPI_SLEEP
+ bool
+ depends on SUSPEND || HIBERNATION
+diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
+index e5ada78..d799593 100644
+--- a/drivers/acpi/Makefile
++++ b/drivers/acpi/Makefile
+@@ -81,6 +81,7 @@ obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o
+ obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
+ obj-$(CONFIG_ACPI_BGRT) += bgrt.o
+ obj-$(CONFIG_ACPI_CPPC_LIB) += cppc_acpi.o
++obj-$(CONFIG_ACPI_SPCR_TABLE) += spcr.o
+ obj-$(CONFIG_ACPI_DEBUGGER_USER) += acpi_dbg.o
+
+ # processor has its own "processor." module_param namespace
+diff --git a/drivers/acpi/spcr.c b/drivers/acpi/spcr.c
+new file mode 100644
+index 0000000..e8d7bc7
+--- /dev/null
++++ b/drivers/acpi/spcr.c
+@@ -0,0 +1,111 @@
++/*
++ * Copyright (c) 2012, Intel Corporation
++ * Copyright (c) 2015, Red Hat, Inc.
++ * Copyright (c) 2015, 2016 Linaro Ltd.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#define pr_fmt(fmt) "ACPI: SPCR: " fmt
++
++#include <linux/acpi.h>
++#include <linux/console.h>
++#include <linux/kernel.h>
++#include <linux/serial_core.h>
++
++/**
++ * parse_spcr() - parse ACPI SPCR table and add preferred console
++ *
++ * @earlycon: set up earlycon for the console specified by the table
++ *
++ * For the architectures with support for ACPI, CONFIG_ACPI_SPCR_TABLE may be
++ * defined to parse ACPI SPCR table. As a result of the parsing preferred
++ * console is registered and if @earlycon is true, earlycon is set up.
++ *
++ * When CONFIG_ACPI_SPCR_TABLE is defined, this function should be called
++ * from arch inintialization code as soon as the DT/ACPI decision is made.
++ *
++ */
++int __init parse_spcr(bool earlycon)
++{
++ static char opts[64];
++ struct acpi_table_spcr *table;
++ acpi_size table_size;
++ acpi_status status;
++ char *uart;
++ char *iotype;
++ int baud_rate;
++ int err;
++
++ if (acpi_disabled)
++ return -ENODEV;
++
++ status = acpi_get_table_with_size(ACPI_SIG_SPCR, 0,
++ (struct acpi_table_header **)&table,
++ &table_size);
++
++ if (ACPI_FAILURE(status))
++ return -ENOENT;
++
++ if (table->header.revision < 2) {
++ err = -ENOENT;
++ pr_err("wrong table version\n");
++ goto done;
++ }
++
++ iotype = table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY ?
++ "mmio" : "io";
++
++ switch (table->interface_type) {
++ case ACPI_DBG2_ARM_SBSA_32BIT:
++ iotype = "mmio32";
++ /* fall through */
++ case ACPI_DBG2_ARM_PL011:
++ case ACPI_DBG2_ARM_SBSA_GENERIC:
++ case ACPI_DBG2_BCM2835:
++ uart = "pl011";
++ break;
++ case ACPI_DBG2_16550_COMPATIBLE:
++ case ACPI_DBG2_16550_SUBSET:
++ uart = "uart";
++ break;
++ default:
++ err = -ENOENT;
++ goto done;
++ }
++
++ switch (table->baud_rate) {
++ case 3:
++ baud_rate = 9600;
++ break;
++ case 4:
++ baud_rate = 19200;
++ break;
++ case 6:
++ baud_rate = 57600;
++ break;
++ case 7:
++ baud_rate = 115200;
++ break;
++ default:
++ err = -ENOENT;
++ goto done;
++ }
++
++ snprintf(opts, sizeof(opts), "%s,%s,0x%llx,%d", uart, iotype,
++ table->serial_port.address, baud_rate);
++
++ pr_info("console: %s\n", opts);
++
++ if (earlycon)
++ setup_earlycon(opts);
++
++ err = add_preferred_console(uart, 0, opts + strlen(uart) + 1);
++
++done:
++ early_acpi_os_unmap_memory((void __iomem *)table, table_size);
++ return err;
++}
+diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
+index 7aae655..ea00b9f 100644
+--- a/drivers/tty/serial/earlycon.c
++++ b/drivers/tty/serial/earlycon.c
+@@ -21,6 +21,7 @@
+ #include <linux/sizes.h>
+ #include <linux/of.h>
+ #include <linux/of_fdt.h>
++#include <linux/acpi.h>
+
+ #ifdef CONFIG_FIX_EARLYCON_MEM
+ #include <asm/fixmap.h>
+@@ -199,6 +200,14 @@ int __init setup_earlycon(char *buf)
+ return -ENOENT;
+ }
+
++/*
++ * When CONFIG_ACPI_SPCR_TABLE is defined, "earlycon" without parameters in
++ * command line does not start DT earlycon immediately, instead it defers
++ * starting it until DT/ACPI decision is made. At that time if ACPI is enabled
++ * call parse_spcr(), else call early_init_dt_scan_chosen_stdout()
++ */
++bool earlycon_init_is_deferred __initdata;
++
+ /* early_param wrapper for setup_earlycon() */
+ static int __init param_setup_earlycon(char *buf)
+ {
+@@ -208,8 +217,14 @@ static int __init param_setup_earlycon(char *buf)
+ * Just 'earlycon' is a valid param for devicetree earlycons;
+ * don't generate a warning from parse_early_params() in that case
+ */
+- if (!buf || !buf[0])
+- return early_init_dt_scan_chosen_stdout();
++ if (!buf || !buf[0]) {
++ if (IS_ENABLED(CONFIG_ACPI_SPCR_TABLE)) {
++ earlycon_init_is_deferred = true;
++ return 0;
++ } else {
++ return early_init_dt_scan_chosen_stdout();
++ }
++ }
+
+ err = setup_earlycon(buf);
+ if (err == -ENOENT || err == -EALREADY)
+diff --git a/include/linux/acpi.h b/include/linux/acpi.h
+index 4d8452c..32407e4 100644
+--- a/include/linux/acpi.h
++++ b/include/linux/acpi.h
+@@ -1074,4 +1074,10 @@ void acpi_table_upgrade(void);
+ static inline void acpi_table_upgrade(void) { }
+ #endif
+
++#ifdef CONFIG_ACPI_SPCR_TABLE
++int parse_spcr(bool earlycon);
++#else
++static inline int parse_spcr(bool earlycon) { return 0; }
++#endif
++
+ #endif /*_LINUX_ACPI_H*/
+diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
+index 2f44e20..04b8cfb 100644
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -367,11 +367,18 @@ extern const struct earlycon_id __earlycon_table_end[];
+
+ #define EARLYCON_DECLARE(_name, fn) OF_EARLYCON_DECLARE(_name, "", fn)
+
+-extern int setup_earlycon(char *buf);
+ extern int of_setup_earlycon(const struct earlycon_id *match,
+ unsigned long node,
+ const char *options);
+
++#ifdef CONFIG_SERIAL_EARLYCON
++extern bool earlycon_init_is_deferred __initdata;
++extern int setup_earlycon(char *buf);
++#else
++static const bool earlycon_init_is_deferred;
++static inline int setup_earlycon(char *buf) { return 0; }
++#endif
++
+ struct uart_port *uart_get_console(struct uart_port *ports, int nr,
+ struct console *c);
+ int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
+From patchwork Thu Aug 11 15:31:40 2016
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v9,3/4] ARM64: ACPI: enable ACPI_SPCR_TABLE
+From: Aleksey Makarov <aleksey.makarov@linaro.org>
+X-Patchwork-Id: 9275457
+Message-Id: <20160811153152.755-4-aleksey.makarov@linaro.org>
+To: "Rafael J . Wysocki" <rjw@rjwysocki.net>,
+ Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: linux-serial@vger.kernel.org, linux-acpi@vger.kernel.org,
+ linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
+ Aleksey Makarov <aleksey.makarov@linaro.org>,
+ Russell King <linux@arm.linux.org.uk>, Len Brown <lenb@kernel.org>,
+ Leif Lindholm <leif.lindholm@linaro.org>,
+ Graeme Gregory <graeme.gregory@linaro.org>, Al Stone <ahs3@redhat.com>,
+ Christopher Covington <cov@codeaurora.org>,
+ Yury Norov <ynorov@caviumnetworks.com>,
+ Peter Hurley <peter@hurleysoftware.com>,
+ Andy Shevchenko <andy.shevchenko@gmail.com>,
+ "Zheng, Lv" <lv.zheng@intel.com>, Mark Salter <msalter@redhat.com>,
+ Kefeng Wang <wangkefeng.wang@huawei.com>,
+ Catalin Marinas <catalin.marinas@arm.com>,
+ Will Deacon <will.deacon@arm.com>
+Date: Thu, 11 Aug 2016 18:31:40 +0300
+
+SBBR mentions SPCR as a mandatory ACPI table. So enable it for ARM64
+
+Earlycon should be set up as early as possible. ACPI boot tables are
+mapped in arch/arm64/kernel/acpi.c:acpi_boot_table_init() that
+is called from setup_arch() and that's where we parse SPCR.
+So it has to be opted-in per-arch.
+
+When ACPI_SPCR_TABLE is defined initialization of DT earlycon is
+deferred until the DT/ACPI decision is done. Initialize DT earlycon
+if ACPI is disabled.
+
+Signed-off-by: Aleksey Makarov <aleksey.makarov@linaro.org>
+Tested-by: Kefeng Wang <wangkefeng.wang@huawei.com>
+---
+ arch/arm64/Kconfig | 1 +
+ arch/arm64/kernel/acpi.c | 11 ++++++++++-
+ 2 files changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
+index 69c8787..a54dfc0 100644
+--- a/arch/arm64/Kconfig
++++ b/arch/arm64/Kconfig
+@@ -4,6 +4,7 @@ config ARM64
+ select ACPI_GENERIC_GSI if ACPI
+ select ACPI_REDUCED_HARDWARE_ONLY if ACPI
+ select ACPI_MCFG if ACPI
++ select ACPI_SPCR_TABLE if ACPI
+ select ARCH_HAS_DEVMEM_IS_ALLOWED
+ select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
+ select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
+diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
+index 3e4f1a4..252a6d9 100644
+--- a/arch/arm64/kernel/acpi.c
++++ b/arch/arm64/kernel/acpi.c
+@@ -24,6 +24,7 @@
+ #include <linux/memblock.h>
+ #include <linux/of_fdt.h>
+ #include <linux/smp.h>
++#include <linux/serial_core.h>
+
+ #include <asm/cputype.h>
+ #include <asm/cpu_ops.h>
+@@ -206,7 +207,7 @@ void __init acpi_boot_table_init(void)
+ if (param_acpi_off ||
+ (!param_acpi_on && !param_acpi_force &&
+ of_scan_flat_dt(dt_scan_depth1_nodes, NULL)))
+- return;
++ goto done;
+
+ /*
+ * ACPI is disabled at this point. Enable it in order to parse
+@@ -226,6 +227,14 @@ void __init acpi_boot_table_init(void)
+ if (!param_acpi_force)
+ disable_acpi();
+ }
++
++done:
++ if (acpi_disabled) {
++ if (earlycon_init_is_deferred)
++ early_init_dt_scan_chosen_stdout();
++ } else {
++ parse_spcr(earlycon_init_is_deferred);
++ }
+ }
+
+ #ifdef CONFIG_ACPI_APEI
+From patchwork Mon Aug 15 13:35:03 2016
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v9,4/4] serial: pl011: add console matching function
+From: Aleksey Makarov <aleksey.makarov@linaro.org>
+X-Patchwork-Id: 9280971
+Message-Id: <20160815133505.15294-1-aleksey.makarov@linaro.org>
+To: "Rafael J . Wysocki" <rjw@rjwysocki.net>,
+ Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: linux-serial@vger.kernel.org, linux-acpi@vger.kernel.org,
+ linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
+ Aleksey Makarov <aleksey.makarov@linaro.org>,
+ Russell King <linux@arm.linux.org.uk>, Len Brown <lenb@kernel.org>,
+ Leif Lindholm <leif.lindholm@linaro.org>,
+ Graeme Gregory <graeme.gregory@linaro.org>, Al Stone <ahs3@redhat.com>,
+ Christopher Covington <cov@codeaurora.org>,
+ Yury Norov <ynorov@caviumnetworks.com>,
+ Peter Hurley <peter@hurleysoftware.com>,
+ Andy Shevchenko <andy.shevchenko@gmail.com>,
+ "Zheng, Lv" <lv.zheng@intel.com>, Mark Salter <msalter@redhat.com>,
+ Kefeng Wang <wangkefeng.wang@huawei.com>,
+ Russell King <linux@armlinux.org.uk>, Jiri Slaby <jslaby@suse.com>
+Date: Mon, 15 Aug 2016 16:35:03 +0300
+
+This patch adds function pl011_console_match() that implements
+method match of struct console. It allows to match consoles against
+data specified in a string, for example taken from command line or
+compiled by ACPI SPCR table handler.
+
+Signed-off-by: Aleksey Makarov <aleksey.makarov@linaro.org>
+Reviewed-by: Peter Hurley <peter@hurleysoftware.com>
+Acked-by: Russell King <rmk+kernel@armlinux.org.uk>
+---
+ drivers/tty/serial/amba-pl011.c | 55 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 55 insertions(+)
+
+diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
+index 8a9e213..2f9af8a 100644
+--- a/drivers/tty/serial/amba-pl011.c
++++ b/drivers/tty/serial/amba-pl011.c
+@@ -2288,12 +2288,67 @@ static int __init pl011_console_setup(struct console *co, char *options)
+ return uart_set_options(&uap->port, co, baud, parity, bits, flow);
+ }
+
++/**
++ * pl011_console_match - non-standard console matching
++ * @co: registering console
++ * @name: name from console command line
++ * @idx: index from console command line
++ * @options: ptr to option string from console command line
++ *
++ * Only attempts to match console command lines of the form:
++ * console=pl011,mmio|mmio32,<addr>[,<options>]
++ * console=pl011,0x<addr>[,<options>]
++ * This form is used to register an initial earlycon boot console and
++ * replace it with the amba_console at pl011 driver init.
++ *
++ * Performs console setup for a match (as required by interface)
++ * If no <options> are specified, then assume the h/w is already setup.
++ *
++ * Returns 0 if console matches; otherwise non-zero to use default matching
++ */
++static int __init pl011_console_match(struct console *co, char *name, int idx,
++ char *options)
++{
++ unsigned char iotype;
++ unsigned long addr;
++ int i;
++
++ if (strcmp(name, "pl011") != 0)
++ return -ENODEV;
++
++ if (uart_parse_earlycon(options, &iotype, &addr, &options))
++ return -ENODEV;
++
++ if (iotype != UPIO_MEM && iotype != UPIO_MEM32)
++ return -ENODEV;
++
++ /* try to match the port specified on the command line */
++ for (i = 0; i < ARRAY_SIZE(amba_ports); i++) {
++ struct uart_port *port;
++
++ if (!amba_ports[i])
++ continue;
++
++ port = &amba_ports[i]->port;
++
++ if (port->mapbase != addr)
++ continue;
++
++ co->index = i;
++ port->cons = co;
++ return pl011_console_setup(co, options);
++ }
++
++ return -ENODEV;
++}
++
+ static struct uart_driver amba_reg;
+ static struct console amba_console = {
+ .name = "ttyAMA",
+ .write = pl011_console_write,
+ .device = uart_console_device,
+ .setup = pl011_console_setup,
++ .match = pl011_console_match,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &amba_reg,
diff --git a/arm64-pcie-acpi.patch b/arm64-pcie-acpi.patch
deleted file mode 100644
index e9a359db6..000000000
--- a/arm64-pcie-acpi.patch
+++ /dev/null
@@ -1,1247 +0,0 @@
-From 1fc02559de87cd88339a83ad05baa9c2b5bd1ac0 Mon Sep 17 00:00:00 2001
-From: Jayachandran C <jchandra@broadcom.com>
-Date: Fri, 10 Jun 2016 21:55:09 +0200
-Subject: [PATCH 01/11] PCI/ECAM: Move ecam.h to linux/include/pci-ecam.h
-
-This header will be used from arch/arm64 for ACPI PCI implementation
-so it needs to be moved out of drivers/pci.
-
-Update users of the header file to use the new name. No functional
-changes.
-
-Signed-off-by: Jayachandran C <jchandra@broadcom.com>
-Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- drivers/pci/ecam.c | 3 +-
- drivers/pci/ecam.h | 67 -------------------------------------
- drivers/pci/host/pci-host-common.c | 3 +-
- drivers/pci/host/pci-host-generic.c | 3 +-
- drivers/pci/host/pci-thunder-ecam.c | 3 +-
- drivers/pci/host/pci-thunder-pem.c | 3 +-
- include/linux/pci-ecam.h | 67 +++++++++++++++++++++++++++++++++++++
- 7 files changed, 72 insertions(+), 77 deletions(-)
- delete mode 100644 drivers/pci/ecam.h
- create mode 100644 include/linux/pci-ecam.h
-
-diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c
-index f9832ad..820e26b 100644
---- a/drivers/pci/ecam.c
-+++ b/drivers/pci/ecam.c
-@@ -19,10 +19,9 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
-+#include <linux/pci-ecam.h>
- #include <linux/slab.h>
-
--#include "ecam.h"
--
- /*
- * On 64-bit systems, we do a single ioremap for the whole config space
- * since we have enough virtual address range available. On 32-bit, we
-diff --git a/drivers/pci/ecam.h b/drivers/pci/ecam.h
-deleted file mode 100644
-index 9878beb..0000000
---- a/drivers/pci/ecam.h
-+++ /dev/null
-@@ -1,67 +0,0 @@
--/*
-- * Copyright 2016 Broadcom
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License, version 2, as
-- * published by the Free Software Foundation (the "GPL").
-- *
-- * This program is distributed in the hope that it will be useful, but
-- * WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- * General Public License version 2 (GPLv2) for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * version 2 (GPLv2) along with this source code.
-- */
--#ifndef DRIVERS_PCI_ECAM_H
--#define DRIVERS_PCI_ECAM_H
--
--#include <linux/kernel.h>
--#include <linux/platform_device.h>
--
--/*
-- * struct to hold pci ops and bus shift of the config window
-- * for a PCI controller.
-- */
--struct pci_config_window;
--struct pci_ecam_ops {
-- unsigned int bus_shift;
-- struct pci_ops pci_ops;
-- int (*init)(struct device *,
-- struct pci_config_window *);
--};
--
--/*
-- * struct to hold the mappings of a config space window. This
-- * is expected to be used as sysdata for PCI controllers that
-- * use ECAM.
-- */
--struct pci_config_window {
-- struct resource res;
-- struct resource busr;
-- void *priv;
-- struct pci_ecam_ops *ops;
-- union {
-- void __iomem *win; /* 64-bit single mapping */
-- void __iomem **winp; /* 32-bit per-bus mapping */
-- };
--};
--
--/* create and free pci_config_window */
--struct pci_config_window *pci_ecam_create(struct device *dev,
-- struct resource *cfgres, struct resource *busr,
-- struct pci_ecam_ops *ops);
--void pci_ecam_free(struct pci_config_window *cfg);
--
--/* map_bus when ->sysdata is an instance of pci_config_window */
--void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
-- int where);
--/* default ECAM ops */
--extern struct pci_ecam_ops pci_generic_ecam_ops;
--
--#ifdef CONFIG_PCI_HOST_GENERIC
--/* for DT-based PCI controllers that support ECAM */
--int pci_host_common_probe(struct platform_device *pdev,
-- struct pci_ecam_ops *ops);
--#endif
--#endif
-diff --git a/drivers/pci/host/pci-host-common.c b/drivers/pci/host/pci-host-common.c
-index 8cba7ab..c18b9e3 100644
---- a/drivers/pci/host/pci-host-common.c
-+++ b/drivers/pci/host/pci-host-common.c
-@@ -20,10 +20,9 @@
- #include <linux/module.h>
- #include <linux/of_address.h>
- #include <linux/of_pci.h>
-+#include <linux/pci-ecam.h>
- #include <linux/platform_device.h>
-
--#include "../ecam.h"
--
- static int gen_pci_parse_request_of_pci_ranges(struct device *dev,
- struct list_head *resources, struct resource **bus_range)
- {
-diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c
-index 6eaceab..f0ca6de 100644
---- a/drivers/pci/host/pci-host-generic.c
-+++ b/drivers/pci/host/pci-host-generic.c
-@@ -23,10 +23,9 @@
- #include <linux/module.h>
- #include <linux/of_address.h>
- #include <linux/of_pci.h>
-+#include <linux/pci-ecam.h>
- #include <linux/platform_device.h>
-
--#include "../ecam.h"
--
- static struct pci_ecam_ops gen_pci_cfg_cam_bus_ops = {
- .bus_shift = 16,
- .pci_ops = {
-diff --git a/drivers/pci/host/pci-thunder-ecam.c b/drivers/pci/host/pci-thunder-ecam.c
-index 540d030..a9fc1c9 100644
---- a/drivers/pci/host/pci-thunder-ecam.c
-+++ b/drivers/pci/host/pci-thunder-ecam.c
-@@ -11,10 +11,9 @@
- #include <linux/ioport.h>
- #include <linux/of_pci.h>
- #include <linux/of.h>
-+#include <linux/pci-ecam.h>
- #include <linux/platform_device.h>
-
--#include "../ecam.h"
--
- static void set_val(u32 v, int where, int size, u32 *val)
- {
- int shift = (where & 3) * 8;
-diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/host/pci-thunder-pem.c
-index 9b8ab94..5020d3d 100644
---- a/drivers/pci/host/pci-thunder-pem.c
-+++ b/drivers/pci/host/pci-thunder-pem.c
-@@ -18,10 +18,9 @@
- #include <linux/module.h>
- #include <linux/of_address.h>
- #include <linux/of_pci.h>
-+#include <linux/pci-ecam.h>
- #include <linux/platform_device.h>
-
--#include "../ecam.h"
--
- #define PEM_CFG_WR 0x28
- #define PEM_CFG_RD 0x30
-
-diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h
-new file mode 100644
-index 0000000..9878beb
---- /dev/null
-+++ b/include/linux/pci-ecam.h
-@@ -0,0 +1,67 @@
-+/*
-+ * Copyright 2016 Broadcom
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License, version 2, as
-+ * published by the Free Software Foundation (the "GPL").
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License version 2 (GPLv2) for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * version 2 (GPLv2) along with this source code.
-+ */
-+#ifndef DRIVERS_PCI_ECAM_H
-+#define DRIVERS_PCI_ECAM_H
-+
-+#include <linux/kernel.h>
-+#include <linux/platform_device.h>
-+
-+/*
-+ * struct to hold pci ops and bus shift of the config window
-+ * for a PCI controller.
-+ */
-+struct pci_config_window;
-+struct pci_ecam_ops {
-+ unsigned int bus_shift;
-+ struct pci_ops pci_ops;
-+ int (*init)(struct device *,
-+ struct pci_config_window *);
-+};
-+
-+/*
-+ * struct to hold the mappings of a config space window. This
-+ * is expected to be used as sysdata for PCI controllers that
-+ * use ECAM.
-+ */
-+struct pci_config_window {
-+ struct resource res;
-+ struct resource busr;
-+ void *priv;
-+ struct pci_ecam_ops *ops;
-+ union {
-+ void __iomem *win; /* 64-bit single mapping */
-+ void __iomem **winp; /* 32-bit per-bus mapping */
-+ };
-+};
-+
-+/* create and free pci_config_window */
-+struct pci_config_window *pci_ecam_create(struct device *dev,
-+ struct resource *cfgres, struct resource *busr,
-+ struct pci_ecam_ops *ops);
-+void pci_ecam_free(struct pci_config_window *cfg);
-+
-+/* map_bus when ->sysdata is an instance of pci_config_window */
-+void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
-+ int where);
-+/* default ECAM ops */
-+extern struct pci_ecam_ops pci_generic_ecam_ops;
-+
-+#ifdef CONFIG_PCI_HOST_GENERIC
-+/* for DT-based PCI controllers that support ECAM */
-+int pci_host_common_probe(struct platform_device *pdev,
-+ struct pci_ecam_ops *ops);
-+#endif
-+#endif
---
-2.7.4
-
-From 5eb9996fc097629854f359f9ad3d959fdacb7f8f Mon Sep 17 00:00:00 2001
-From: Jayachandran C <jchandra@broadcom.com>
-Date: Fri, 10 Jun 2016 21:55:10 +0200
-Subject: [PATCH 02/11] PCI/ECAM: Add parent device field to pci_config_window
-
-Add a parent device field to struct pci_config_window. The parent
-is not saved now, but will be useful to save it in some cases.
-Specifically in case of ACPI for ARM64, it can be used to setup
-ACPI companion and domain.
-
-Since the parent dev is in struct pci_config_window now, we need
-not pass it to the init function as a separate argument.
-
-Signed-off-by: Jayachandran C <jchandra@broadcom.com>
-Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- drivers/pci/ecam.c | 3 ++-
- drivers/pci/host/pci-thunder-pem.c | 3 ++-
- include/linux/pci-ecam.h | 4 ++--
- 3 files changed, 6 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c
-index 820e26b..66e0d71 100644
---- a/drivers/pci/ecam.c
-+++ b/drivers/pci/ecam.c
-@@ -51,6 +51,7 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
- if (!cfg)
- return ERR_PTR(-ENOMEM);
-
-+ cfg->parent = dev;
- cfg->ops = ops;
- cfg->busr.start = busr->start;
- cfg->busr.end = busr->end;
-@@ -94,7 +95,7 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
- }
-
- if (ops->init) {
-- err = ops->init(dev, cfg);
-+ err = ops->init(cfg);
- if (err)
- goto err_exit;
- }
-diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/host/pci-thunder-pem.c
-index 5020d3d..91f6fc6 100644
---- a/drivers/pci/host/pci-thunder-pem.c
-+++ b/drivers/pci/host/pci-thunder-pem.c
-@@ -284,8 +284,9 @@ static int thunder_pem_config_write(struct pci_bus *bus, unsigned int devfn,
- return pci_generic_config_write(bus, devfn, where, size, val);
- }
-
--static int thunder_pem_init(struct device *dev, struct pci_config_window *cfg)
-+static int thunder_pem_init(struct pci_config_window *cfg)
- {
-+ struct device *dev = cfg->parent;
- resource_size_t bar4_start;
- struct resource *res_pem;
- struct thunder_pem_pci *pem_pci;
-diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h
-index 9878beb..7adad20 100644
---- a/include/linux/pci-ecam.h
-+++ b/include/linux/pci-ecam.h
-@@ -27,8 +27,7 @@ struct pci_config_window;
- struct pci_ecam_ops {
- unsigned int bus_shift;
- struct pci_ops pci_ops;
-- int (*init)(struct device *,
-- struct pci_config_window *);
-+ int (*init)(struct pci_config_window *);
- };
-
- /*
-@@ -45,6 +44,7 @@ struct pci_config_window {
- void __iomem *win; /* 64-bit single mapping */
- void __iomem **winp; /* 32-bit per-bus mapping */
- };
-+ struct device *parent;/* ECAM res was from this dev */
- };
-
- /* create and free pci_config_window */
---
-2.7.4
-
-From 6ed6c1365df5c9201e9b275e8ed4eaa64ef2ec0d Mon Sep 17 00:00:00 2001
-From: Sinan Kaya <okaya@codeaurora.org>
-Date: Fri, 10 Jun 2016 21:55:11 +0200
-Subject: [PATCH 03/11] PCI: Add new function to unmap IO resources
-
-We need to release I/O resources so that the same I/O resources
-can be allocated again in pci_remap_iospace(), like in PCI hotplug removal
-scenario. Therefore implement new pci_unmap_iospace() call which
-unmaps I/O space as the symmetry to pci_remap_iospace().
-
-Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- drivers/pci/pci.c | 18 ++++++++++++++++++
- include/linux/pci.h | 1 +
- 2 files changed, 19 insertions(+)
-
-diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
-index c8b4dbd..eb431b5 100644
---- a/drivers/pci/pci.c
-+++ b/drivers/pci/pci.c
-@@ -25,6 +25,7 @@
- #include <linux/device.h>
- #include <linux/pm_runtime.h>
- #include <linux/pci_hotplug.h>
-+#include <linux/vmalloc.h>
- #include <asm/setup.h>
- #include <linux/aer.h>
- #include "pci.h"
-@@ -3165,6 +3166,23 @@ int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
- #endif
- }
-
-+/**
-+ * pci_unmap_iospace - Unmap the memory mapped I/O space
-+ * @res: resource to be unmapped
-+ *
-+ * Unmap the CPU virtual address @res from virtual address space.
-+ * Only architectures that have memory mapped IO functions defined
-+ * (and the PCI_IOBASE value defined) should call this function.
-+ */
-+void pci_unmap_iospace(struct resource *res)
-+{
-+#if defined(PCI_IOBASE) && defined(CONFIG_MMU)
-+ unsigned long vaddr = (unsigned long)PCI_IOBASE + res->start;
-+
-+ unmap_kernel_range(vaddr, resource_size(res));
-+#endif
-+}
-+
- static void __pci_set_master(struct pci_dev *dev, bool enable)
- {
- u16 old_cmd, cmd;
-diff --git a/include/linux/pci.h b/include/linux/pci.h
-index b67e4df..12349de 100644
---- a/include/linux/pci.h
-+++ b/include/linux/pci.h
-@@ -1167,6 +1167,7 @@ int pci_register_io_range(phys_addr_t addr, resource_size_t size);
- unsigned long pci_address_to_pio(phys_addr_t addr);
- phys_addr_t pci_pio_to_address(unsigned long pio);
- int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
-+void pci_unmap_iospace(struct resource *res);
-
- static inline pci_bus_addr_t pci_bus_address(struct pci_dev *pdev, int bar)
- {
---
-2.7.4
-
-From 62f4d54fc2d2882b9ebaa920189574f422e12207 Mon Sep 17 00:00:00 2001
-From: Jayachandran C <jchandra@broadcom.com>
-Date: Fri, 10 Jun 2016 21:55:12 +0200
-Subject: [PATCH 04/11] ACPI/PCI: Support IO resources when parsing PCI host
- bridge resources
-
-Platforms that have memory mapped IO port (such as ARM64) need special
-handling for PCI I/O resources. For host bridge's resource probing case
-these resources need to be fixed up with
-pci_register_io_range()/pci_remap_iospace() etc.
-
-The same I/O resources need to be released after hotplug
-removal so that it can be re-added back by the pci_remap_iospace()
-function during insertion. As a consequence unmap I/O resources
-with pci_unmap_iospace() when we release host bridge resources.
-
-Signed-off-by: Jayachandran C <jchandra@broadcom.com>
-Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
-[ Tomasz: merged in Sinan's patch to unmap IO resources properly, updated changelog]
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- drivers/acpi/pci_root.c | 39 +++++++++++++++++++++++++++++++++++++++
- 1 file changed, 39 insertions(+)
-
-diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
-index ae3fe4e..9a26dd1 100644
---- a/drivers/acpi/pci_root.c
-+++ b/drivers/acpi/pci_root.c
-@@ -720,6 +720,40 @@ next:
- }
- }
-
-+#ifdef PCI_IOBASE
-+static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
-+{
-+ struct resource *res = entry->res;
-+ resource_size_t cpu_addr = res->start;
-+ resource_size_t pci_addr = cpu_addr - entry->offset;
-+ resource_size_t length = resource_size(res);
-+ unsigned long port;
-+
-+ if (pci_register_io_range(cpu_addr, length))
-+ goto err;
-+
-+ port = pci_address_to_pio(cpu_addr);
-+ if (port == (unsigned long)-1)
-+ goto err;
-+
-+ res->start = port;
-+ res->end = port + length - 1;
-+ entry->offset = port - pci_addr;
-+
-+ if (pci_remap_iospace(res, cpu_addr) < 0)
-+ goto err;
-+
-+ pr_info("Remapped I/O %pa to %pR\n", &cpu_addr, res);
-+ return;
-+err:
-+ res->flags |= IORESOURCE_DISABLED;
-+}
-+#else
-+static inline void acpi_pci_root_remap_iospace(struct resource_entry *entry)
-+{
-+}
-+#endif
-+
- int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
- {
- int ret;
-@@ -740,6 +774,9 @@ int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
- "no IO and memory resources present in _CRS\n");
- else {
- resource_list_for_each_entry_safe(entry, tmp, list) {
-+ if (entry->res->flags & IORESOURCE_IO)
-+ acpi_pci_root_remap_iospace(entry);
-+
- if (entry->res->flags & IORESOURCE_DISABLED)
- resource_list_destroy_entry(entry);
- else
-@@ -811,6 +848,8 @@ static void acpi_pci_root_release_info(struct pci_host_bridge *bridge)
-
- resource_list_for_each_entry(entry, &bridge->windows) {
- res = entry->res;
-+ if (res->flags & IORESOURCE_IO)
-+ pci_unmap_iospace(res);
- if (res->parent &&
- (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
- release_resource(res);
---
-2.7.4
-
-From dd4f7822d702cca83baa1de7a5f69344ffb82af9 Mon Sep 17 00:00:00 2001
-From: Tomasz Nowicki <tn@semihalf.com>
-Date: Fri, 10 Jun 2016 21:55:13 +0200
-Subject: [PATCH 05/11] ACPI/PCI: Add generic MCFG table handling
-
-According to PCI firmware specifications, on systems booting with ACPI,
-PCI configuration for a host bridge must be set-up through the MCFG table
-regions for non-hotpluggable bridges and _CBA method for hotpluggable ones.
-
-Current MCFG table handling code, as implemented for x86, cannot be
-easily generalized owing to x86 specific quirks handling and related
-code, which makes it hard to reuse on other architectures.
-
-In order to implement MCFG PCI configuration handling for new platforms
-booting with ACPI (eg ARM64) this patch re-implements MCFG handling from
-scratch in a streamlined fashion and provides (through a generic
-interface available to all arches):
-
-- Simplified MCFG table parsing (executed through the pci_mmcfg_late_init()
- hook as in current x86)
-- MCFG regions look-up interface through domain:bus_start:bus_end tuple
-
-The new MCFG regions handling interface is added to generic ACPI code
-so that existing architectures (eg x86) can be moved over to it and
-architectures relying on MCFG for ACPI PCI config space can rely on it
-without having to resort to arch specific implementations.
-
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-Signed-off-by: Jayachandran C <jchandra@broadcom.com>
-Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- drivers/acpi/Kconfig | 3 ++
- drivers/acpi/Makefile | 1 +
- drivers/acpi/pci_mcfg.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++
- include/linux/pci-acpi.h | 2 ++
- include/linux/pci.h | 2 +-
- 5 files changed, 99 insertions(+), 1 deletion(-)
- create mode 100644 drivers/acpi/pci_mcfg.c
-
-diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
-index b7e2e77..f98c328 100644
---- a/drivers/acpi/Kconfig
-+++ b/drivers/acpi/Kconfig
-@@ -217,6 +217,9 @@ config ACPI_PROCESSOR_IDLE
- bool
- select CPU_IDLE
-
-+config ACPI_MCFG
-+ bool
-+
- config ACPI_CPPC_LIB
- bool
- depends on ACPI_PROCESSOR
-diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
-index 251ce85..632e81f 100644
---- a/drivers/acpi/Makefile
-+++ b/drivers/acpi/Makefile
-@@ -40,6 +40,7 @@ acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o
- acpi-y += ec.o
- acpi-$(CONFIG_ACPI_DOCK) += dock.o
- acpi-y += pci_root.o pci_link.o pci_irq.o
-+obj-$(CONFIG_ACPI_MCFG) += pci_mcfg.o
- acpi-y += acpi_lpss.o acpi_apd.o
- acpi-y += acpi_platform.o
- acpi-y += acpi_pnp.o
-diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
-new file mode 100644
-index 0000000..d3c3e85
---- /dev/null
-+++ b/drivers/acpi/pci_mcfg.c
-@@ -0,0 +1,92 @@
-+/*
-+ * Copyright (C) 2016 Broadcom
-+ * Author: Jayachandran C <jchandra@broadcom.com>
-+ * Copyright (C) 2016 Semihalf
-+ * Author: Tomasz Nowicki <tn@semihalf.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License, version 2, as
-+ * published by the Free Software Foundation (the "GPL").
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License version 2 (GPLv2) for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * version 2 (GPLv2) along with this source code.
-+ */
-+
-+#define pr_fmt(fmt) "ACPI: " fmt
-+
-+#include <linux/kernel.h>
-+#include <linux/pci.h>
-+#include <linux/pci-acpi.h>
-+
-+/* Structure to hold entries from the MCFG table */
-+struct mcfg_entry {
-+ struct list_head list;
-+ phys_addr_t addr;
-+ u16 segment;
-+ u8 bus_start;
-+ u8 bus_end;
-+};
-+
-+/* List to save mcfg entries */
-+static LIST_HEAD(pci_mcfg_list);
-+
-+phys_addr_t pci_mcfg_lookup(u16 seg, struct resource *bus_res)
-+{
-+ struct mcfg_entry *e;
-+
-+ /*
-+ * We expect exact match, unless MCFG entry end bus covers more than
-+ * specified by caller.
-+ */
-+ list_for_each_entry(e, &pci_mcfg_list, list) {
-+ if (e->segment == seg && e->bus_start == bus_res->start &&
-+ e->bus_end >= bus_res->end)
-+ return e->addr;
-+ }
-+
-+ return 0;
-+}
-+
-+static __init int pci_mcfg_parse(struct acpi_table_header *header)
-+{
-+ struct acpi_table_mcfg *mcfg;
-+ struct acpi_mcfg_allocation *mptr;
-+ struct mcfg_entry *e, *arr;
-+ int i, n;
-+
-+ if (header->length < sizeof(struct acpi_table_mcfg))
-+ return -EINVAL;
-+
-+ n = (header->length - sizeof(struct acpi_table_mcfg)) /
-+ sizeof(struct acpi_mcfg_allocation);
-+ mcfg = (struct acpi_table_mcfg *)header;
-+ mptr = (struct acpi_mcfg_allocation *) &mcfg[1];
-+
-+ arr = kcalloc(n, sizeof(*arr), GFP_KERNEL);
-+ if (!arr)
-+ return -ENOMEM;
-+
-+ for (i = 0, e = arr; i < n; i++, mptr++, e++) {
-+ e->segment = mptr->pci_segment;
-+ e->addr = mptr->address;
-+ e->bus_start = mptr->start_bus_number;
-+ e->bus_end = mptr->end_bus_number;
-+ list_add(&e->list, &pci_mcfg_list);
-+ }
-+
-+ pr_info("MCFG table detected, %d entries\n", n);
-+ return 0;
-+}
-+
-+/* Interface called by ACPI - parse and save MCFG table */
-+void __init pci_mmcfg_late_init(void)
-+{
-+ int err = acpi_table_parse(ACPI_SIG_MCFG, pci_mcfg_parse);
-+ if (err)
-+ pr_err("Failed to parse MCFG (%d)\n", err);
-+}
-diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
-index 89ab057..7d63a66 100644
---- a/include/linux/pci-acpi.h
-+++ b/include/linux/pci-acpi.h
-@@ -24,6 +24,8 @@ static inline acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
- }
- extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle);
-
-+extern phys_addr_t pci_mcfg_lookup(u16 domain, struct resource *bus_res);
-+
- static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
- {
- struct pci_bus *pbus = pdev->bus;
-diff --git a/include/linux/pci.h b/include/linux/pci.h
-index 12349de..ce03d65 100644
---- a/include/linux/pci.h
-+++ b/include/linux/pci.h
-@@ -1723,7 +1723,7 @@ void pcibios_free_irq(struct pci_dev *dev);
- extern struct dev_pm_ops pcibios_pm_ops;
- #endif
-
--#ifdef CONFIG_PCI_MMCONFIG
-+#if defined(CONFIG_PCI_MMCONFIG) || defined(CONFIG_ACPI_MCFG)
- void __init pci_mmcfg_early_init(void);
- void __init pci_mmcfg_late_init(void);
- #else
---
-2.7.4
-
-From fc1907f9c79f9a0a0c2f4d579896e678915fec48 Mon Sep 17 00:00:00 2001
-From: Tomasz Nowicki <tn@semihalf.com>
-Date: Fri, 10 Jun 2016 21:55:14 +0200
-Subject: [PATCH 06/11] PCI: Refactor generic bus domain assignment
-
-Change the way PCI bus domain number is assigned and improve function
-name to reflect what function does. No functional changes.
-
-Instead of assigning bus domain number inside of pci_bus_assign_domain_nr()
-simply return domain number and let pci_create_root_bus() do assignment.
-This way pci_create_root_bus() setups bus structure data in the consistent
-way. Since pci_bus_assign_domain_nr() now does not assign but retrieves
-domain number instead, rename it to pci_bus_find_domain_nr().
-
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- drivers/pci/pci.c | 4 ++--
- drivers/pci/probe.c | 4 +++-
- include/linux/pci.h | 7 +------
- 3 files changed, 6 insertions(+), 9 deletions(-)
-
-diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
-index eb431b5..b9a7833 100644
---- a/drivers/pci/pci.c
-+++ b/drivers/pci/pci.c
-@@ -4941,7 +4941,7 @@ int pci_get_new_domain_nr(void)
- }
-
- #ifdef CONFIG_PCI_DOMAINS_GENERIC
--void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
-+int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
- {
- static int use_dt_domains = -1;
- int domain = -1;
-@@ -4985,7 +4985,7 @@ void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
- domain = -1;
- }
-
-- bus->domain_nr = domain;
-+ return domain;
- }
- #endif
- #endif
-diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
-index 8e3ef72..380d46d 100644
---- a/drivers/pci/probe.c
-+++ b/drivers/pci/probe.c
-@@ -2127,7 +2127,9 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
- b->sysdata = sysdata;
- b->ops = ops;
- b->number = b->busn_res.start = bus;
-- pci_bus_assign_domain_nr(b, parent);
-+#ifdef CONFIG_PCI_DOMAINS_GENERIC
-+ b->domain_nr = pci_bus_find_domain_nr(b, parent);
-+#endif
- b2 = pci_find_bus(pci_domain_nr(b), bus);
- if (b2) {
- /* If we already got to this bus through a different bridge, ignore it */
-diff --git a/include/linux/pci.h b/include/linux/pci.h
-index ce03d65..48839e8 100644
---- a/include/linux/pci.h
-+++ b/include/linux/pci.h
-@@ -1390,12 +1390,7 @@ static inline int pci_domain_nr(struct pci_bus *bus)
- {
- return bus->domain_nr;
- }
--void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent);
--#else
--static inline void pci_bus_assign_domain_nr(struct pci_bus *bus,
-- struct device *parent)
--{
--}
-+int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent);
- #endif
-
- /* some architectures require additional setup to direct VGA traffic */
---
-2.7.4
-
-From d6d45ae1d58658111d5e838c41b9ed4729bbb81e Mon Sep 17 00:00:00 2001
-From: Tomasz Nowicki <tn@semihalf.com>
-Date: Fri, 10 Jun 2016 21:55:15 +0200
-Subject: [PATCH 07/11] PCI: Factor DT specific pci_bus_find_domain_nr() code
- out
-
-pci_bus_find_domain_nr() retrieves the host bridge domain number in a DT
-specific way. Factor our pci_bus_find_domain_nr() in a separate DT
-function (ie of_pci_bus_find_domain_nr()) so that DT code is self
-contained, paving the way for retrieving domain number in
-pci_bus_find_domain_nr() with additional firmware methods (ie ACPI).
-
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- drivers/pci/pci.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
-index b9a7833..97f7cd4 100644
---- a/drivers/pci/pci.c
-+++ b/drivers/pci/pci.c
-@@ -4941,7 +4941,7 @@ int pci_get_new_domain_nr(void)
- }
-
- #ifdef CONFIG_PCI_DOMAINS_GENERIC
--int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
-+static int of_pci_bus_find_domain_nr(struct device *parent)
- {
- static int use_dt_domains = -1;
- int domain = -1;
-@@ -4987,6 +4987,11 @@ int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
-
- return domain;
- }
-+
-+int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
-+{
-+ return of_pci_bus_find_domain_nr(parent);
-+}
- #endif
- #endif
-
---
-2.7.4
-
-From 92d59511fd365d3c0c31d074b5e96cf48c58f68b Mon Sep 17 00:00:00 2001
-From: Peter Robinson <pbrobinson@gmail.com>
-Date: Thu, 30 Jun 2016 16:56:24 +0100
-Subject: [PATCH 08/11] ARM64/PCI: Add ACPI hook to assign domain number
-
-PCI core code provides a config option (CONFIG_PCI_DOMAINS_GENERIC)
-that allows assigning the PCI bus domain number generically by
-relying on device tree bindings, and falling back to a simple counter
-when the respective DT properties (ie "linux,pci-domain") are not
-specified in the host bridge device tree node.
-
-In a similar way, when a system is booted through ACPI, architectures
-that are selecting CONFIG_PCI_DOMAINS_GENERIC (ie ARM64) require kernel
-hooks to retrieve the domain number so that the PCI bus domain number
-set-up can be handled seamlessly with DT and ACPI in generic core code
-when CONFIG_PCI_DOMAINS_GENERIC is selected.
-
-Since currently it is not possible to retrieve a pointer to the PCI
-host bridge ACPI device backing the host bridge from core PCI code
-(which would allow retrieving the domain number in an arch agnostic
-way through the ACPI _SEG method), an arch specific ACPI hook has to
-be declared and implemented by all arches that rely on
-CONFIG_PCI_DOMAINS_GENERIC to retrieve the domain number and set it
-up in core PCI code.
-
-For the aforementioned reasons, introduce acpi_pci_bus_find_domain_nr()
-hook to retrieve the domain number on a per-arch basis when the system
-boots through ACPI. ARM64 dummy implementation of the same is provided
-in first place in preparation for ARM64 ACPI based PCI host controller
-driver.
-
-acpi_pci_bus_find_domain_nr() is called from generic
-pci_bus_find_domain_nr() as an ACPI option to DT domain assignment.
-
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- arch/arm64/kernel/pci.c | 7 +++++++
- drivers/pci/pci.c | 4 +++-
- include/linux/pci.h | 7 +++++++
- 3 files changed, 17 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
-index 3c4e308..d5d3d26 100644
---- a/arch/arm64/kernel/pci.c
-+++ b/arch/arm64/kernel/pci.c
-@@ -17,6 +17,7 @@
- #include <linux/mm.h>
- #include <linux/of_pci.h>
- #include <linux/of_platform.h>
-+#include <linux/pci.h>
- #include <linux/slab.h>
-
- /*
-@@ -85,6 +86,12 @@ EXPORT_SYMBOL(pcibus_to_node);
- #endif
-
- #ifdef CONFIG_ACPI
-+
-+int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
-+{
-+ return 0;
-+}
-+
- /* Root bridge scanning */
- struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
- {
-diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
-index 97f7cd4..4834cee 100644
---- a/drivers/pci/pci.c
-+++ b/drivers/pci/pci.c
-@@ -7,6 +7,7 @@
- * Copyright 1997 -- 2000 Martin Mares <mj@ucw.cz>
- */
-
-+#include <linux/acpi.h>
- #include <linux/kernel.h>
- #include <linux/delay.h>
- #include <linux/init.h>
-@@ -4990,7 +4991,8 @@ static int of_pci_bus_find_domain_nr(struct device *parent)
-
- int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
- {
-- return of_pci_bus_find_domain_nr(parent);
-+ return acpi_disabled ? of_pci_bus_find_domain_nr(parent) :
-+ acpi_pci_bus_find_domain_nr(bus);
- }
- #endif
- #endif
-diff --git a/include/linux/pci.h b/include/linux/pci.h
-index 48839e8..49ba8af 100644
---- a/include/linux/pci.h
-+++ b/include/linux/pci.h
-@@ -1390,6 +1390,13 @@ static inline int pci_domain_nr(struct pci_bus *bus)
- {
- return bus->domain_nr;
- }
-+/* Arch specific ACPI hook to set-up domain number */
-+#ifdef CONFIG_ACPI
-+int acpi_pci_bus_find_domain_nr(struct pci_bus *bus);
-+#else
-+static inline int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
-+{ return 0; }
-+#endif
- int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent);
- #endif
-
---
-2.7.4
-
-From bb06753d2e163d8100a017f06a6d9dd195d68a76 Mon Sep 17 00:00:00 2001
-From: Tomasz Nowicki <tn@semihalf.com>
-Date: Fri, 10 Jun 2016 21:55:17 +0200
-Subject: [PATCH 09/11] ARM64/PCI: ACPI support for legacy IRQs parsing and
- consolidation with DT code
-
-To enable PCI legacy IRQs on platforms booting with ACPI, arch code
-should include ACPI specific callbacks that parse and set-up the
-device IRQ number, equivalent to the DT boot path. Owing to the current
-ACPI core scan handlers implementation, ACPI PCI legacy IRQs bindings
-cannot be parsed at device add time, since that would trigger ACPI scan
-handlers ordering issues depending on how the ACPI tables are defined.
-
-To solve this problem and consolidate FW PCI legacy IRQs parsing in
-one single pcibios callback (pending final removal), this patch moves
-DT PCI IRQ parsing to the pcibios_alloc_irq() callback (called by
-PCI core code at device probe time) and adds ACPI PCI legacy IRQs
-parsing to the same callback too, so that FW PCI legacy IRQs parsing
-is confined in one single arch callback that can be easily removed
-when code parsing PCI legacy IRQs is consolidated and moved to core
-PCI code.
-
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-Suggested-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- arch/arm64/kernel/pci.c | 11 ++++++++---
- 1 file changed, 8 insertions(+), 3 deletions(-)
-
-diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
-index d5d3d26..b3b8a2c 100644
---- a/arch/arm64/kernel/pci.c
-+++ b/arch/arm64/kernel/pci.c
-@@ -51,11 +51,16 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
- }
-
- /*
-- * Try to assign the IRQ number from DT when adding a new device
-+ * Try to assign the IRQ number when probing a new device
- */
--int pcibios_add_device(struct pci_dev *dev)
-+int pcibios_alloc_irq(struct pci_dev *dev)
- {
-- dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
-+ if (acpi_disabled)
-+ dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
-+#ifdef CONFIG_ACPI
-+ else
-+ return acpi_pci_irq_enable(dev);
-+#endif
-
- return 0;
- }
---
-2.7.4
-
-From b6e298840f532192a589f8ade128dec3fef3a4c6 Mon Sep 17 00:00:00 2001
-From: Tomasz Nowicki <tn@semihalf.com>
-Date: Fri, 10 Jun 2016 21:55:18 +0200
-Subject: [PATCH 10/11] ARM64/PCI: Implement ACPI low-level calls to access
- PCI_Config region from AML
-
-ACPI spec6.1 - chapter: 5.5.2.4 defines OperationRegion (Declare Operation
-Region). Following the spec: " [...] An Operation Region is a specific
-region of operation within an address space that is declared as a subset
-of the entire address space using a starting address (offset) and a length.
-Control methods must have exclusive access to any address accessed via
-fields declared in Operation Regions. [...]".
-
-OperationRegion allows to declare various of operation region address space
-identifiers including PCI_Config. PCI_Config is meant to access PCI
-configuration space from the ASL. So every time ASL opcode operates
-on PCI_Config space region, ASL interpreter dispatches accesses to OS
-low-level calls - raw_pci_write() and raw_pci_read() for Linux - so-called
-ACPI RAW accessors.
-
-In order to support PCI_Config operation region, implement mentioned
-raw_pci_write() and raw_pci_read() calls so they find associated bus
-and call read/write ops.
-
-Waiting for clarification in the ACPI specifications in relation
-to PCI_Config space handling before PCI bus enumeration is completed,
-current code does not support PCI_Config region accesses before PCI bus
-enumeration whilst providing full AML PCI_Config access availability
-when the PCI bus enumeration is completed by the kernel so that
-RAW accessors can look-up PCI operations through the struct pci_bus
-associated with a PCI bus.
-
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-Signed-off-by: Jayachandran C <jchandra@broadcom.com>
-Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- arch/arm64/kernel/pci.c | 12 ++++++++++--
- 1 file changed, 10 insertions(+), 2 deletions(-)
-
-diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
-index b3b8a2c..328f857 100644
---- a/arch/arm64/kernel/pci.c
-+++ b/arch/arm64/kernel/pci.c
-@@ -71,13 +71,21 @@ int pcibios_alloc_irq(struct pci_dev *dev)
- int raw_pci_read(unsigned int domain, unsigned int bus,
- unsigned int devfn, int reg, int len, u32 *val)
- {
-- return -ENXIO;
-+ struct pci_bus *b = pci_find_bus(domain, bus);
-+
-+ if (!b)
-+ return PCIBIOS_DEVICE_NOT_FOUND;
-+ return b->ops->read(b, devfn, reg, len, val);
- }
-
- int raw_pci_write(unsigned int domain, unsigned int bus,
- unsigned int devfn, int reg, int len, u32 val)
- {
-- return -ENXIO;
-+ struct pci_bus *b = pci_find_bus(domain, bus);
-+
-+ if (!b)
-+ return PCIBIOS_DEVICE_NOT_FOUND;
-+ return b->ops->write(b, devfn, reg, len, val);
- }
-
- #ifdef CONFIG_NUMA
---
-2.7.4
-
-From 3b8cff3fa89ba3ef6f1cf09a0667aa470b7fad0b Mon Sep 17 00:00:00 2001
-From: Tomasz Nowicki <tn@semihalf.com>
-Date: Fri, 10 Jun 2016 21:55:19 +0200
-Subject: [PATCH 11/11] ARM64/PCI: Support for ACPI based PCI host controller
-
-Implement pci_acpi_scan_root and other arch-specific call so that ARM64
-can start using ACPI to setup and enumerate PCI buses.
-
-Prior to buses enumeration the pci_acpi_scan_root() implementation looks
-for configuration space start address (obtained through ACPI _CBA method or
-MCFG interface). If succeed, it uses ECAM library to create new mapping.
-Then it attaches generic ECAM ops (pci_generic_ecam_ops) which are used
-for accessing configuration space later on.
-
-On ARM64, we need to use generic domains (CONFIG_PCI_DOMAINS_GENERIC).
-In order to achieve that for ACPI case implement
-acpi_pci_bus_find_domain_nr() body so that it retrieves pci_config_window
-structure from bus sysdata and eventually gets domain number from
-acpi_pci_root structure.
-
-ACPI requires to run acpi_pci_{add|remove}_bus while new PCI bus is created.
-This allows to do some ACPI-specific additional configuration, like
-PCI hotplug slot enumeration. In order to fulfill these requirements,
-we implement arch-specific pcibios_{add|remove}_bus calls
-and call acpi_pci_{add|remove}_bus from there.
-
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-Signed-off-by: Jayachandran C <jchandra@broadcom.com>
-Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- arch/arm64/Kconfig | 2 +
- arch/arm64/kernel/pci.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++--
- 2 files changed, 115 insertions(+), 3 deletions(-)
-
-diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
-index 5a0a691..4806cde 100644
---- a/arch/arm64/Kconfig
-+++ b/arch/arm64/Kconfig
-@@ -3,6 +3,7 @@ config ARM64
- select ACPI_CCA_REQUIRED if ACPI
- select ACPI_GENERIC_GSI if ACPI
- select ACPI_REDUCED_HARDWARE_ONLY if ACPI
-+ select ACPI_MCFG if ACPI
- select ARCH_HAS_DEVMEM_IS_ALLOWED
- select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
- select ARCH_HAS_ELF_RANDOMIZE
-@@ -96,6 +97,7 @@ config ARM64
- select OF_EARLY_FLATTREE
- select OF_NUMA if NUMA && OF
- select OF_RESERVED_MEM
-+ select PCI_ECAM if ACPI
- select PERF_USE_VMALLOC
- select POWER_RESET
- select POWER_SUPPLY
-diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
-index 328f857..94cd43c 100644
---- a/arch/arm64/kernel/pci.c
-+++ b/arch/arm64/kernel/pci.c
-@@ -18,6 +18,8 @@
- #include <linux/of_pci.h>
- #include <linux/of_platform.h>
- #include <linux/pci.h>
-+#include <linux/pci-acpi.h>
-+#include <linux/pci-ecam.h>
- #include <linux/slab.h>
-
- /*
-@@ -100,15 +102,123 @@ EXPORT_SYMBOL(pcibus_to_node);
-
- #ifdef CONFIG_ACPI
-
-+struct acpi_pci_generic_root_info {
-+ struct acpi_pci_root_info common;
-+ struct pci_config_window *cfg; /* config space mapping */
-+};
-+
- int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
- {
-+ struct pci_config_window *cfg = bus->sysdata;
-+ struct acpi_device *adev = to_acpi_device(cfg->parent);
-+ struct acpi_pci_root *root = acpi_driver_data(adev);
-+
-+ return root->segment;
-+}
-+
-+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
-+{
-+ if (!acpi_disabled) {
-+ struct pci_config_window *cfg = bridge->bus->sysdata;
-+ struct acpi_device *adev = to_acpi_device(cfg->parent);
-+ ACPI_COMPANION_SET(&bridge->dev, adev);
-+ }
-+
- return 0;
- }
-
--/* Root bridge scanning */
-+/*
-+ * Lookup the bus range for the domain in MCFG, and set up config space
-+ * mapping.
-+ */
-+static struct pci_config_window *
-+pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root)
-+{
-+ struct resource *bus_res = &root->secondary;
-+ u16 seg = root->segment;
-+ struct pci_config_window *cfg;
-+ struct resource cfgres;
-+ unsigned int bsz;
-+
-+ /* Use address from _CBA if present, otherwise lookup MCFG */
-+ if (!root->mcfg_addr)
-+ root->mcfg_addr = pci_mcfg_lookup(seg, bus_res);
-+
-+ if (!root->mcfg_addr) {
-+ dev_err(&root->device->dev, "%04x:%pR ECAM region not found\n",
-+ seg, bus_res);
-+ return NULL;
-+ }
-+
-+ bsz = 1 << pci_generic_ecam_ops.bus_shift;
-+ cfgres.start = root->mcfg_addr + bus_res->start * bsz;
-+ cfgres.end = cfgres.start + resource_size(bus_res) * bsz - 1;
-+ cfgres.flags = IORESOURCE_MEM;
-+ cfg = pci_ecam_create(&root->device->dev, &cfgres, bus_res,
-+ &pci_generic_ecam_ops);
-+ if (IS_ERR(cfg)) {
-+ dev_err(&root->device->dev, "%04x:%pR error %ld mapping ECAM\n",
-+ seg, bus_res, PTR_ERR(cfg));
-+ return NULL;
-+ }
-+
-+ return cfg;
-+}
-+
-+/* release_info: free resources allocated by init_info */
-+static void pci_acpi_generic_release_info(struct acpi_pci_root_info *ci)
-+{
-+ struct acpi_pci_generic_root_info *ri;
-+
-+ ri = container_of(ci, struct acpi_pci_generic_root_info, common);
-+ pci_ecam_free(ri->cfg);
-+ kfree(ri);
-+}
-+
-+static struct acpi_pci_root_ops acpi_pci_root_ops = {
-+ .release_info = pci_acpi_generic_release_info,
-+};
-+
-+/* Interface called from ACPI code to setup PCI host controller */
- struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
- {
-- /* TODO: Should be revisited when implementing PCI on ACPI */
-- return NULL;
-+ int node = acpi_get_node(root->device->handle);
-+ struct acpi_pci_generic_root_info *ri;
-+ struct pci_bus *bus, *child;
-+
-+ ri = kzalloc_node(sizeof(*ri), GFP_KERNEL, node);
-+ if (!ri)
-+ return NULL;
-+
-+ ri->cfg = pci_acpi_setup_ecam_mapping(root);
-+ if (!ri->cfg) {
-+ kfree(ri);
-+ return NULL;
-+ }
-+
-+ acpi_pci_root_ops.pci_ops = &ri->cfg->ops->pci_ops;
-+ bus = acpi_pci_root_create(root, &acpi_pci_root_ops, &ri->common,
-+ ri->cfg);
-+ if (!bus)
-+ return NULL;
-+
-+ pci_bus_size_bridges(bus);
-+ pci_bus_assign_resources(bus);
-+
-+ list_for_each_entry(child, &bus->children, node)
-+ pcie_bus_configure_settings(child);
-+
-+ return bus;
-+}
-+
-+void pcibios_add_bus(struct pci_bus *bus)
-+{
-+ acpi_pci_add_bus(bus);
- }
-+
-+void pcibios_remove_bus(struct pci_bus *bus)
-+{
-+ acpi_pci_remove_bus(bus);
-+}
-+
- #endif
---
-2.7.4
-
diff --git a/arm64-pcie-quirks-xgene.patch b/arm64-pcie-quirks-xgene.patch
deleted file mode 100644
index 8e6805df6..000000000
--- a/arm64-pcie-quirks-xgene.patch
+++ /dev/null
@@ -1,508 +0,0 @@
-From 767b70aa55d013f0c7589955f410d488fed5776a Mon Sep 17 00:00:00 2001
-From: Peter Robinson <pbrobinson@gmail.com>
-Date: Tue, 5 Jul 2016 23:49:39 +0100
-Subject: [PATCH 1/4] Some platforms may not be fully compliant with generic
- set of PCI config accessors. For these cases we implement the way to
- overwrite accessors set. Algorithm traverses available quirk list, matches
- against <oem_id, oem_table_id, domain, bus number> tuple and returns
- corresponding PCI config ops. oem_id and oem_table_id come from MCFG table
- standard header. All quirks can be defined using DECLARE_ACPI_MCFG_FIXUP()
- macro and kept self contained. Example:
-
-/* Custom PCI config ops */
-static struct pci_generic_ecam_ops foo_pci_ops = {
- .bus_shift = 24,
- .pci_ops = {
- .map_bus = pci_ecam_map_bus,
- .read = foo_ecam_config_read,
- .write = foo_ecam_config_write,
- }
-};
-
-DECLARE_ACPI_MCFG_FIXUP(&foo_pci_ops, <oem_id_str>, <oem_table_id>, <domain_nr>, <bus_nr>);
-
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-Signed-off-by: Dongdong Liu <liudongdong3@huawei.com>
----
- drivers/acpi/pci_mcfg.c | 41 ++++++++++++++++++++++++++++++++++++---
- include/asm-generic/vmlinux.lds.h | 7 +++++++
- include/linux/pci-acpi.h | 20 +++++++++++++++++++
- 3 files changed, 65 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
-index d3c3e85..deb0077 100644
---- a/drivers/acpi/pci_mcfg.c
-+++ b/drivers/acpi/pci_mcfg.c
-@@ -22,6 +22,10 @@
- #include <linux/kernel.h>
- #include <linux/pci.h>
- #include <linux/pci-acpi.h>
-+#include <linux/pci-ecam.h>
-+
-+/* Root pointer to the mapped MCFG table */
-+static struct acpi_table_mcfg *mcfg_table;
-
- /* Structure to hold entries from the MCFG table */
- struct mcfg_entry {
-@@ -35,6 +39,38 @@ struct mcfg_entry {
- /* List to save mcfg entries */
- static LIST_HEAD(pci_mcfg_list);
-
-+extern struct pci_cfg_fixup __start_acpi_mcfg_fixups[];
-+extern struct pci_cfg_fixup __end_acpi_mcfg_fixups[];
-+
-+struct pci_ecam_ops *pci_mcfg_get_ops(struct acpi_pci_root *root)
-+{
-+ int bus_num = root->secondary.start;
-+ int domain = root->segment;
-+ struct pci_cfg_fixup *f;
-+
-+ if (!mcfg_table)
-+ return &pci_generic_ecam_ops;
-+
-+ /*
-+ * Match against platform specific quirks and return corresponding
-+ * CAM ops.
-+ *
-+ * First match against PCI topology <domain:bus> then use OEM ID and
-+ * OEM revision from MCFG table standard header.
-+ */
-+ for (f = __start_acpi_mcfg_fixups; f < __end_acpi_mcfg_fixups; f++) {
-+ if ((f->domain == domain || f->domain == PCI_MCFG_DOMAIN_ANY) &&
-+ (f->bus_num == bus_num || f->bus_num == PCI_MCFG_BUS_ANY) &&
-+ (!strncmp(f->oem_id, mcfg_table->header.oem_id,
-+ ACPI_OEM_ID_SIZE)) &&
-+ (!strncmp(f->oem_table_id, mcfg_table->header.oem_table_id,
-+ ACPI_OEM_TABLE_ID_SIZE)))
-+ return f->ops;
-+ }
-+ /* No quirks, use ECAM */
-+ return &pci_generic_ecam_ops;
-+}
-+
- phys_addr_t pci_mcfg_lookup(u16 seg, struct resource *bus_res)
- {
- struct mcfg_entry *e;
-@@ -54,7 +90,6 @@ phys_addr_t pci_mcfg_lookup(u16 seg, struct resource *bus_res)
-
- static __init int pci_mcfg_parse(struct acpi_table_header *header)
- {
-- struct acpi_table_mcfg *mcfg;
- struct acpi_mcfg_allocation *mptr;
- struct mcfg_entry *e, *arr;
- int i, n;
-@@ -64,8 +99,8 @@ static __init int pci_mcfg_parse(struct acpi_table_header *header)
-
- n = (header->length - sizeof(struct acpi_table_mcfg)) /
- sizeof(struct acpi_mcfg_allocation);
-- mcfg = (struct acpi_table_mcfg *)header;
-- mptr = (struct acpi_mcfg_allocation *) &mcfg[1];
-+ mcfg_table = (struct acpi_table_mcfg *)header;
-+ mptr = (struct acpi_mcfg_allocation *) &mcfg_table[1];
-
- arr = kcalloc(n, sizeof(*arr), GFP_KERNEL);
- if (!arr)
-diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
-index 6a67ab9..43604fc 100644
---- a/include/asm-generic/vmlinux.lds.h
-+++ b/include/asm-generic/vmlinux.lds.h
-@@ -300,6 +300,13 @@
- VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .; \
- } \
- \
-+ /* ACPI MCFG quirks */ \
-+ .acpi_fixup : AT(ADDR(.acpi_fixup) - LOAD_OFFSET) { \
-+ VMLINUX_SYMBOL(__start_acpi_mcfg_fixups) = .; \
-+ *(.acpi_fixup_mcfg) \
-+ VMLINUX_SYMBOL(__end_acpi_mcfg_fixups) = .; \
-+ } \
-+ \
- /* Built-in firmware blobs */ \
- .builtin_fw : AT(ADDR(.builtin_fw) - LOAD_OFFSET) { \
- VMLINUX_SYMBOL(__start_builtin_fw) = .; \
-diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
-index 7d63a66..c8a6559 100644
---- a/include/linux/pci-acpi.h
-+++ b/include/linux/pci-acpi.h
-@@ -25,6 +25,7 @@ static inline acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
- extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle);
-
- extern phys_addr_t pci_mcfg_lookup(u16 domain, struct resource *bus_res);
-+extern struct pci_ecam_ops *pci_mcfg_get_ops(struct acpi_pci_root *root);
-
- static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
- {
-@@ -72,6 +73,25 @@ struct acpi_pci_root_ops {
- int (*prepare_resources)(struct acpi_pci_root_info *info);
- };
-
-+struct pci_cfg_fixup {
-+ struct pci_ecam_ops *ops;
-+ char *oem_id;
-+ char *oem_table_id;
-+ int domain;
-+ int bus_num;
-+};
-+
-+#define PCI_MCFG_DOMAIN_ANY -1
-+#define PCI_MCFG_BUS_ANY -1
-+
-+/* Designate a routine to fix up buggy MCFG */
-+#define DECLARE_ACPI_MCFG_FIXUP(ops, oem_id, oem_table_id, dom, bus) \
-+ static const struct pci_cfg_fixup \
-+ __mcfg_fixup_##oem_id##oem_table_id##dom##bus \
-+ __used __attribute__((__section__(".acpi_fixup_mcfg"), \
-+ aligned((sizeof(void *))))) = \
-+ { ops, oem_id, oem_table_id, dom, bus };
-+
- extern int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info);
- extern struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
- struct acpi_pci_root_ops *ops,
---
-2.7.4
-
-From 4f86a9b006b25dd7336043dab26058ed6fb2802d Mon Sep 17 00:00:00 2001
-From: Peter Robinson <pbrobinson@gmail.com>
-Date: Tue, 5 Jul 2016 23:52:46 +0100
-Subject: [PATCH 2/4] pci_generic_ecam_ops is used by default. Since there are
- platforms which have non-compliant ECAM space we need to overwrite these
- accessors prior to PCI buses enumeration. In order to do that we call
- pci_mcfg_get_ops to retrieve pci_ecam_ops structure so that we can use proper
- PCI config space accessors and bus_shift.
-
-pci_generic_ecam_ops is still used for platforms free from quirks.
-
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
----
- arch/arm64/kernel/pci.c | 7 ++++---
- 1 file changed, 4 insertions(+), 3 deletions(-)
-
-diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
-index 94cd43c..a891bda 100644
---- a/arch/arm64/kernel/pci.c
-+++ b/arch/arm64/kernel/pci.c
-@@ -139,6 +139,7 @@ pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root)
- struct pci_config_window *cfg;
- struct resource cfgres;
- unsigned int bsz;
-+ struct pci_ecam_ops *ops;
-
- /* Use address from _CBA if present, otherwise lookup MCFG */
- if (!root->mcfg_addr)
-@@ -150,12 +151,12 @@ pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root)
- return NULL;
- }
-
-- bsz = 1 << pci_generic_ecam_ops.bus_shift;
-+ ops = pci_mcfg_get_ops(root);
-+ bsz = 1 << ops->bus_shift;
- cfgres.start = root->mcfg_addr + bus_res->start * bsz;
- cfgres.end = cfgres.start + resource_size(bus_res) * bsz - 1;
- cfgres.flags = IORESOURCE_MEM;
-- cfg = pci_ecam_create(&root->device->dev, &cfgres, bus_res,
-- &pci_generic_ecam_ops);
-+ cfg = pci_ecam_create(&root->device->dev, &cfgres, bus_res, ops);
- if (IS_ERR(cfg)) {
- dev_err(&root->device->dev, "%04x:%pR error %ld mapping ECAM\n",
- seg, bus_res, PTR_ERR(cfg));
---
-2.7.4
-
-From cbdbd697bd6d716eb9d1705ee55445432e73eabb Mon Sep 17 00:00:00 2001
-From: Peter Robinson <pbrobinson@gmail.com>
-Date: Tue, 5 Jul 2016 23:53:59 +0100
-Subject: [PATCH 3/4] The ECAM quirk matching criteria per the discussion on
- https://lkml.org/lkml/2016/6/13/944 includes: OEM ID, OEM Table ID and OEM
- Revision. So this patch adds OEM Table ID into the check to match platform
- specific ECAM quirks as well.
-
-This patch also improve strncmp check using strlen and
-min_t to ignore the padding spaces in OEM ID and OEM
-Table ID.
-
-Signed-off-by: Duc Dang <dhdang@apm.com>
----
- drivers/acpi/pci_mcfg.c | 7 +++++--
- include/linux/pci-acpi.h | 7 ++++---
- 2 files changed, 9 insertions(+), 5 deletions(-)
-
-diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
-index deb0077..307ca9a 100644
---- a/drivers/acpi/pci_mcfg.c
-+++ b/drivers/acpi/pci_mcfg.c
-@@ -62,9 +62,12 @@ struct pci_ecam_ops *pci_mcfg_get_ops(struct acpi_pci_root *root)
- if ((f->domain == domain || f->domain == PCI_MCFG_DOMAIN_ANY) &&
- (f->bus_num == bus_num || f->bus_num == PCI_MCFG_BUS_ANY) &&
- (!strncmp(f->oem_id, mcfg_table->header.oem_id,
-- ACPI_OEM_ID_SIZE)) &&
-+ min_t(size_t, strlen(f->oem_id),
-+ ACPI_OEM_ID_SIZE))) &&
- (!strncmp(f->oem_table_id, mcfg_table->header.oem_table_id,
-- ACPI_OEM_TABLE_ID_SIZE)))
-+ min_t(size_t, strlen(f->oem_table_id),
-+ ACPI_OEM_TABLE_ID_SIZE))) &&
-+ (f->oem_revision == mcfg_table->header.oem_revision))
- return f->ops;
- }
- /* No quirks, use ECAM */
-diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
-index c8a6559..5148c8d 100644
---- a/include/linux/pci-acpi.h
-+++ b/include/linux/pci-acpi.h
-@@ -77,6 +77,7 @@ struct pci_cfg_fixup {
- struct pci_ecam_ops *ops;
- char *oem_id;
- char *oem_table_id;
-+ u32 oem_revision;
- int domain;
- int bus_num;
- };
-@@ -85,12 +86,12 @@ struct pci_cfg_fixup {
- #define PCI_MCFG_BUS_ANY -1
-
- /* Designate a routine to fix up buggy MCFG */
--#define DECLARE_ACPI_MCFG_FIXUP(ops, oem_id, oem_table_id, dom, bus) \
-+#define DECLARE_ACPI_MCFG_FIXUP(ops, oem_id, oem_table_id, rev, dom, bus) \
- static const struct pci_cfg_fixup \
-- __mcfg_fixup_##oem_id##oem_table_id##dom##bus \
-+ __mcfg_fixup_##oem_id##oem_table_id##rev##dom##bus \
- __used __attribute__((__section__(".acpi_fixup_mcfg"), \
- aligned((sizeof(void *))))) = \
-- { ops, oem_id, oem_table_id, dom, bus };
-+ { ops, oem_id, oem_table_id, rev, dom, bus };
-
- extern int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info);
- extern struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
---
-2.7.4
-
-From 78766cf255bc6aafac2f57372a0446f78322da19 Mon Sep 17 00:00:00 2001
-From: Peter Robinson <pbrobinson@gmail.com>
-Date: Tue, 5 Jul 2016 23:55:11 +0100
-Subject: [PATCH 4/4] X-Gene PCIe controller does not fully support ECAM. This
- patch adds required ECAM fixup to allow X-Gene PCIe controller to be
- functional in ACPI boot mode.
-
-Signed-off-by: Duc Dang <dhdang@apm.com>
----
- drivers/pci/host/Makefile | 2 +-
- drivers/pci/host/pci-xgene-ecam.c | 194 ++++++++++++++++++++++++++++++++++++++
- 2 files changed, 195 insertions(+), 1 deletion(-)
- create mode 100644 drivers/pci/host/pci-xgene-ecam.c
-
-diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
-index 9c8698e..3480696 100644
---- a/drivers/pci/host/Makefile
-+++ b/drivers/pci/host/Makefile
-@@ -14,7 +14,7 @@ obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
- obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
- obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
- obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o
--obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
-+obj-$(CONFIG_PCI_XGENE) += pci-xgene.o pci-xgene-ecam.o
- obj-$(CONFIG_PCI_XGENE_MSI) += pci-xgene-msi.o
- obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
- obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
-diff --git a/drivers/pci/host/pci-xgene-ecam.c b/drivers/pci/host/pci-xgene-ecam.c
-new file mode 100644
-index 0000000..1bea63f
---- /dev/null
-+++ b/drivers/pci/host/pci-xgene-ecam.c
-@@ -0,0 +1,194 @@
-+/*
-+ * APM X-Gene PCIe ECAM fixup driver
-+ *
-+ * Copyright (c) 2016, Applied Micro Circuits Corporation
-+ * Author:
-+ * Duc Dang <dhdang@apm.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of_address.h>
-+#include <linux/of_pci.h>
-+#include <linux/pci-acpi.h>
-+#include <linux/platform_device.h>
-+#include <linux/pci-ecam.h>
-+
-+#ifdef CONFIG_ACPI
-+#define RTDID 0x160
-+#define ROOT_CAP_AND_CTRL 0x5C
-+
-+/* PCIe IP version */
-+#define XGENE_PCIE_IP_VER_UNKN 0
-+#define XGENE_PCIE_IP_VER_1 1
-+
-+#define APM_OEM_ID "APM"
-+#define APM_XGENE_OEM_TABLE_ID "XGENE"
-+#define APM_XGENE_OEM_REV 0x00000002
-+
-+struct xgene_pcie_acpi_root {
-+ void __iomem *csr_base;
-+ u32 version;
-+};
-+
-+static acpi_status xgene_pcie_find_csr_base(struct acpi_resource *acpi_res,
-+ void *data)
-+{
-+ struct xgene_pcie_acpi_root *root = data;
-+ struct acpi_resource_fixed_memory32 *fixed32;
-+
-+ if (acpi_res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) {
-+ fixed32 = &acpi_res->data.fixed_memory32;
-+ root->csr_base = ioremap(fixed32->address,
-+ fixed32->address_length);
-+ return AE_CTRL_TERMINATE;
-+ }
-+
-+ return AE_OK;
-+}
-+
-+static int xgene_pcie_ecam_init(struct pci_config_window *cfg)
-+{
-+ struct xgene_pcie_acpi_root *xgene_root;
-+ struct device *dev = cfg->parent;
-+ struct acpi_device *adev = to_acpi_device(dev);
-+ acpi_handle handle = acpi_device_handle(adev);
-+
-+ xgene_root = devm_kzalloc(dev, sizeof(*xgene_root), GFP_KERNEL);
-+ if (!xgene_root)
-+ return -ENOMEM;
-+
-+ acpi_walk_resources(handle, METHOD_NAME__CRS,
-+ xgene_pcie_find_csr_base, xgene_root);
-+
-+ if (!xgene_root->csr_base) {
-+ kfree(xgene_root);
-+ return -ENODEV;
-+ }
-+
-+ xgene_root->version = XGENE_PCIE_IP_VER_1;
-+
-+ cfg->priv = xgene_root;
-+
-+ return 0;
-+}
-+
-+/*
-+ * For Configuration request, RTDID register is used as Bus Number,
-+ * Device Number and Function number of the header fields.
-+ */
-+static void xgene_pcie_set_rtdid_reg(struct pci_bus *bus, uint devfn)
-+{
-+ struct pci_config_window *cfg = bus->sysdata;
-+ struct xgene_pcie_acpi_root *port = cfg->priv;
-+ unsigned int b, d, f;
-+ u32 rtdid_val = 0;
-+
-+ b = bus->number;
-+ d = PCI_SLOT(devfn);
-+ f = PCI_FUNC(devfn);
-+
-+ if (!pci_is_root_bus(bus))
-+ rtdid_val = (b << 8) | (d << 3) | f;
-+
-+ writel(rtdid_val, port->csr_base + RTDID);
-+ /* read the register back to ensure flush */
-+ readl(port->csr_base + RTDID);
-+}
-+
-+/*
-+ * X-Gene PCIe port uses BAR0-BAR1 of RC's configuration space as
-+ * the translation from PCI bus to native BUS. Entire DDR region
-+ * is mapped into PCIe space using these registers, so it can be
-+ * reached by DMA from EP devices. The BAR0/1 of bridge should be
-+ * hidden during enumeration to avoid the sizing and resource allocation
-+ * by PCIe core.
-+ */
-+static bool xgene_pcie_hide_rc_bars(struct pci_bus *bus, int offset)
-+{
-+ if (pci_is_root_bus(bus) && ((offset == PCI_BASE_ADDRESS_0) ||
-+ (offset == PCI_BASE_ADDRESS_1)))
-+ return true;
-+
-+ return false;
-+}
-+
-+void __iomem *xgene_pcie_ecam_map_bus(struct pci_bus *bus,
-+ unsigned int devfn, int where)
-+{
-+ struct pci_config_window *cfg = bus->sysdata;
-+ unsigned int busn = bus->number;
-+ void __iomem *base;
-+
-+ if (busn < cfg->busr.start || busn > cfg->busr.end)
-+ return NULL;
-+
-+ if ((pci_is_root_bus(bus) && devfn != 0) ||
-+ xgene_pcie_hide_rc_bars(bus, where))
-+ return NULL;
-+
-+ xgene_pcie_set_rtdid_reg(bus, devfn);
-+
-+ if (busn > cfg->busr.start)
-+ base = cfg->win + (1 << cfg->ops->bus_shift);
-+ else
-+ base = cfg->win;
-+
-+ return base + where;
-+}
-+
-+static int xgene_pcie_config_read32(struct pci_bus *bus, unsigned int devfn,
-+ int where, int size, u32 *val)
-+{
-+ struct pci_config_window *cfg = bus->sysdata;
-+ struct xgene_pcie_acpi_root *port = cfg->priv;
-+
-+ if (pci_generic_config_read32(bus, devfn, where & ~0x3, 4, val) !=
-+ PCIBIOS_SUCCESSFUL)
-+ return PCIBIOS_DEVICE_NOT_FOUND;
-+
-+ /*
-+ * The v1 controller has a bug in its Configuration Request
-+ * Retry Status (CRS) logic: when CRS is enabled and we read the
-+ * Vendor and Device ID of a non-existent device, the controller
-+ * fabricates return data of 0xFFFF0001 ("device exists but is not
-+ * ready") instead of 0xFFFFFFFF ("device does not exist"). This
-+ * causes the PCI core to retry the read until it times out.
-+ * Avoid this by not claiming to support CRS.
-+ */
-+ if (pci_is_root_bus(bus) && (port->version == XGENE_PCIE_IP_VER_1) &&
-+ ((where & ~0x3) == ROOT_CAP_AND_CTRL))
-+ *val &= ~(PCI_EXP_RTCAP_CRSVIS << 16);
-+
-+ if (size <= 2)
-+ *val = (*val >> (8 * (where & 3))) & ((1 << (size * 8)) - 1);
-+
-+ return PCIBIOS_SUCCESSFUL;
-+}
-+
-+static struct pci_ecam_ops xgene_pcie_ecam_ops = {
-+ .bus_shift = 16,
-+ .init = xgene_pcie_ecam_init,
-+ .pci_ops = {
-+ .map_bus = xgene_pcie_ecam_map_bus,
-+ .read = xgene_pcie_config_read32,
-+ .write = pci_generic_config_write,
-+ }
-+};
-+
-+DECLARE_ACPI_MCFG_FIXUP(&xgene_pcie_ecam_ops, APM_OEM_ID,
-+ APM_XGENE_OEM_TABLE_ID, APM_XGENE_OEM_REV,
-+ PCI_MCFG_DOMAIN_ANY, PCI_MCFG_BUS_ANY);
-+#endif
---
-2.7.4
-
diff --git a/arm64-pcie-quirks.patch b/arm64-pcie-quirks.patch
new file mode 100644
index 000000000..36e8d3724
--- /dev/null
+++ b/arm64-pcie-quirks.patch
@@ -0,0 +1,977 @@
+From 5c4f8b5b68451e5d208a5aefb195fdd108629da4 Mon Sep 17 00:00:00 2001
+From: Tomasz Nowicki <tn@semihalf.com>
+Date: Fri, 9 Sep 2016 21:24:03 +0200
+Subject: [PATCH 1/6] PCI/ACPI: Extend pci_mcfg_lookup() responsibilities
+
+In preparation for adding MCFG platform specific quirk handling move
+CFG resource calculation and ECAM ops assignment to pci_mcfg_lookup().
+It becomes the gate for further ops and CFG resource manipulation
+in arch-agnostic code (drivers/acpi/pci_mcfg.c).
+
+No functionality changes in this patch.
+
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+---
+ arch/arm64/kernel/pci.c | 17 +++++------------
+ drivers/acpi/pci_mcfg.c | 28 +++++++++++++++++++++++++---
+ include/linux/pci-acpi.h | 4 +++-
+ 3 files changed, 33 insertions(+), 16 deletions(-)
+
+diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
+index acf3872..fb439c7 100644
+--- a/arch/arm64/kernel/pci.c
++++ b/arch/arm64/kernel/pci.c
+@@ -125,24 +125,17 @@ pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root)
+ u16 seg = root->segment;
+ struct pci_config_window *cfg;
+ struct resource cfgres;
+- unsigned int bsz;
++ struct pci_ecam_ops *ecam_ops;
++ int ret;
+
+- /* Use address from _CBA if present, otherwise lookup MCFG */
+- if (!root->mcfg_addr)
+- root->mcfg_addr = pci_mcfg_lookup(seg, bus_res);
+-
+- if (!root->mcfg_addr) {
++ ret = pci_mcfg_lookup(root, &cfgres, &ecam_ops);
++ if (ret) {
+ dev_err(&root->device->dev, "%04x:%pR ECAM region not found\n",
+ seg, bus_res);
+ return NULL;
+ }
+
+- bsz = 1 << pci_generic_ecam_ops.bus_shift;
+- cfgres.start = root->mcfg_addr + bus_res->start * bsz;
+- cfgres.end = cfgres.start + resource_size(bus_res) * bsz - 1;
+- cfgres.flags = IORESOURCE_MEM;
+- cfg = pci_ecam_create(&root->device->dev, &cfgres, bus_res,
+- &pci_generic_ecam_ops);
++ cfg = pci_ecam_create(&root->device->dev, &cfgres, bus_res, ecam_ops);
+ if (IS_ERR(cfg)) {
+ dev_err(&root->device->dev, "%04x:%pR error %ld mapping ECAM\n",
+ seg, bus_res, PTR_ERR(cfg));
+diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
+index b5b376e..ffcc651 100644
+--- a/drivers/acpi/pci_mcfg.c
++++ b/drivers/acpi/pci_mcfg.c
+@@ -22,6 +22,7 @@
+ #include <linux/kernel.h>
+ #include <linux/pci.h>
+ #include <linux/pci-acpi.h>
++#include <linux/pci-ecam.h>
+
+ /* Structure to hold entries from the MCFG table */
+ struct mcfg_entry {
+@@ -35,9 +36,18 @@ struct mcfg_entry {
+ /* List to save MCFG entries */
+ static LIST_HEAD(pci_mcfg_list);
+
+-phys_addr_t pci_mcfg_lookup(u16 seg, struct resource *bus_res)
++int pci_mcfg_lookup(struct acpi_pci_root *root, struct resource *cfgres,
++ struct pci_ecam_ops **ecam_ops)
+ {
++ struct pci_ecam_ops *ops = &pci_generic_ecam_ops;
++ struct resource *bus_res = &root->secondary;
++ u16 seg = root->segment;
+ struct mcfg_entry *e;
++ struct resource res;
++
++ /* Use address from _CBA if present, otherwise lookup MCFG */
++ if (root->mcfg_addr)
++ goto skip_lookup;
+
+ /*
+ * We expect exact match, unless MCFG entry end bus covers more than
+@@ -45,10 +55,22 @@ phys_addr_t pci_mcfg_lookup(u16 seg, struct resource *bus_res)
+ */
+ list_for_each_entry(e, &pci_mcfg_list, list) {
+ if (e->segment == seg && e->bus_start == bus_res->start &&
+- e->bus_end >= bus_res->end)
+- return e->addr;
++ e->bus_end >= bus_res->end) {
++ root->mcfg_addr = e->addr;
++ }
++
+ }
+
++ if (!root->mcfg_addr)
++ return -ENXIO;
++
++skip_lookup:
++ memset(&res, 0, sizeof(res));
++ res.start = root->mcfg_addr + (bus_res->start << 20);
++ res.end = res.start + (resource_size(bus_res) << 20) - 1;
++ res.flags = IORESOURCE_MEM;
++ *cfgres = res;
++ *ecam_ops = ops;
+ return 0;
+ }
+
+diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
+index 7d63a66..7a4e83a 100644
+--- a/include/linux/pci-acpi.h
++++ b/include/linux/pci-acpi.h
+@@ -24,7 +24,9 @@ static inline acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
+ }
+ extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle);
+
+-extern phys_addr_t pci_mcfg_lookup(u16 domain, struct resource *bus_res);
++struct pci_ecam_ops;
++extern int pci_mcfg_lookup(struct acpi_pci_root *root, struct resource *cfgres,
++ struct pci_ecam_ops **ecam_ops);
+
+ static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
+ {
+--
+2.9.3
+
+From 16c02d9cc0e67b48c343aecc4b5566e729a97683 Mon Sep 17 00:00:00 2001
+From: Tomasz Nowicki <tn@semihalf.com>
+Date: Fri, 9 Sep 2016 21:24:04 +0200
+Subject: [PATCH 2/6] PCI/ACPI: Check platform specific ECAM quirks
+
+Some platforms may not be fully compliant with generic set of PCI config
+accessors. For these cases we implement the way to overwrite CFG accessors
+set and configuration space range.
+
+In first place pci_mcfg_parse() saves machine's IDs and revision number
+(these come from MCFG header) in order to match against known quirk entries.
+Then the algorithm traverses available quirk list (static array),
+matches against <oem_id, oem_table_id, rev, domain, bus number range> and
+returns custom PCI config ops and/or CFG resource structure.
+
+When adding new quirk there are two possibilities:
+1. Override default pci_generic_ecam_ops ops but CFG resource comes from MCFG
+{ "OEM_ID", "OEM_TABLE_ID", <REV>, <DOMAIN>, <BUS_NR>, &foo_ops, MCFG_RES_EMPTY },
+2. Override default pci_generic_ecam_ops ops and CFG resource. For this case
+it is also allowed get CFG resource from quirk entry w/o having it in MCFG.
+{ "OEM_ID", "OEM_TABLE_ID", <REV>, <DOMAIN>, <BUS_NR>, &boo_ops,
+ DEFINE_RES_MEM(START, SIZE) },
+
+pci_generic_ecam_ops and MCFG entries will be used for platforms
+free from quirks.
+
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+Signed-off-by: Dongdong Liu <liudongdong3@huawei.com>
+Signed-off-by: Christopher Covington <cov@codeaurora.org>
+---
+ drivers/acpi/pci_mcfg.c | 80 +++++++++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 74 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
+index ffcc651..2b8acc7 100644
+--- a/drivers/acpi/pci_mcfg.c
++++ b/drivers/acpi/pci_mcfg.c
+@@ -32,6 +32,59 @@ struct mcfg_entry {
+ u8 bus_start;
+ u8 bus_end;
+ };
++struct mcfg_fixup {
++ char oem_id[ACPI_OEM_ID_SIZE + 1];
++ char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
++ u32 oem_revision;
++ u16 seg;
++ struct resource bus_range;
++ struct pci_ecam_ops *ops;
++ struct resource cfgres;
++};
++
++#define MCFG_DOM_ANY (-1)
++#define MCFG_BUS_RANGE(start, end) DEFINE_RES_NAMED((start), \
++ ((end) - (start) + 1), \
++ NULL, IORESOURCE_BUS)
++#define MCFG_BUS_ANY MCFG_BUS_RANGE(0x0, 0xff)
++#define MCFG_RES_EMPTY DEFINE_RES_NAMED(0, 0, NULL, 0)
++
++static struct mcfg_fixup mcfg_quirks[] = {
++/* { OEM_ID, OEM_TABLE_ID, REV, DOMAIN, BUS_RANGE, cfgres, ops }, */
++};
++
++static char mcfg_oem_id[ACPI_OEM_ID_SIZE];
++static char mcfg_oem_table_id[ACPI_OEM_TABLE_ID_SIZE];
++static u32 mcfg_oem_revision;
++
++static void pci_mcfg_match_quirks(struct acpi_pci_root *root,
++ struct resource *cfgres,
++ struct pci_ecam_ops **ecam_ops)
++{
++ struct mcfg_fixup *f;
++ int i;
++
++ /*
++ * First match against PCI topology <domain:bus> then use OEM ID, OEM
++ * table ID, and OEM revision from MCFG table standard header.
++ */
++ for (i = 0, f = mcfg_quirks; i < ARRAY_SIZE(mcfg_quirks); i++, f++) {
++ if (f->seg == root->segment &&
++ resource_contains(&f->bus_range, &root->secondary) &&
++ !memcmp(f->oem_id, mcfg_oem_id, ACPI_OEM_ID_SIZE) &&
++ !memcmp(f->oem_table_id, mcfg_oem_table_id,
++ ACPI_OEM_TABLE_ID_SIZE) &&
++ f->oem_revision == mcfg_oem_revision) {
++ if (f->cfgres.start)
++ *cfgres = f->cfgres;
++ if (f->ops)
++ *ecam_ops = f->ops;
++ dev_info(&root->device->dev, "Applying PCI MCFG quirks for %s %s rev: %d\n",
++ f->oem_id, f->oem_table_id, f->oem_revision);
++ return;
++ }
++ }
++}
+
+ /* List to save MCFG entries */
+ static LIST_HEAD(pci_mcfg_list);
+@@ -61,14 +114,24 @@ int pci_mcfg_lookup(struct acpi_pci_root *root, struct resource *cfgres,
+
+ }
+
+- if (!root->mcfg_addr)
+- return -ENXIO;
+-
+ skip_lookup:
+ memset(&res, 0, sizeof(res));
+- res.start = root->mcfg_addr + (bus_res->start << 20);
+- res.end = res.start + (resource_size(bus_res) << 20) - 1;
+- res.flags = IORESOURCE_MEM;
++ if (root->mcfg_addr) {
++ res.start = root->mcfg_addr + (bus_res->start << 20);
++ res.end = res.start + (resource_size(bus_res) << 20) - 1;
++ res.flags = IORESOURCE_MEM;
++ }
++
++ /*
++ * Let to override default ECAM ops and CFG resource range.
++ * Also, this might even retrieve CFG resource range in case MCFG
++ * does not have it. Invalid CFG start address means MCFG firmware bug
++ * or we need another quirk in array.
++ */
++ pci_mcfg_match_quirks(root, &res, &ops);
++ if (!res.start)
++ return -ENXIO;
++
+ *cfgres = res;
+ *ecam_ops = ops;
+ return 0;
+@@ -101,6 +164,11 @@ static __init int pci_mcfg_parse(struct acpi_table_header *header)
+ list_add(&e->list, &pci_mcfg_list);
+ }
+
++ /* Save MCFG IDs and revision for quirks matching */
++ memcpy(mcfg_oem_id, header->oem_id, ACPI_OEM_ID_SIZE);
++ memcpy(mcfg_oem_table_id, header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE);
++ mcfg_oem_revision = header->revision;
++
+ pr_info("MCFG table detected, %d entries\n", n);
+ return 0;
+ }
+--
+2.9.3
+
+From 2243ab64c12a873e47b72c8e636b40ed09c5f0d4 Mon Sep 17 00:00:00 2001
+From: Tomasz Nowicki <tn@semihalf.com>
+Date: Fri, 9 Sep 2016 21:24:05 +0200
+Subject: [PATCH 3/6] PCI: thunder-pem: Allow to probe PEM-specific register
+ range for ACPI case
+
+thunder-pem driver stands for being ACPI based PCI host controller.
+However, there is no standard way to describe its PEM-specific register
+ranges in ACPI tables. Thus we add thunder_pem_init() ACPI extension
+to obtain hardcoded addresses from static resource array.
+Although it is not pretty, it prevents from creating standard mechanism to
+handle similar cases in future.
+
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+---
+ drivers/pci/host/pci-thunder-pem.c | 61 ++++++++++++++++++++++++++++++--------
+ 1 file changed, 48 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/host/pci-thunder-pem.c
+index 6abaf80..b048761 100644
+--- a/drivers/pci/host/pci-thunder-pem.c
++++ b/drivers/pci/host/pci-thunder-pem.c
+@@ -18,6 +18,7 @@
+ #include <linux/init.h>
+ #include <linux/of_address.h>
+ #include <linux/of_pci.h>
++#include <linux/pci-acpi.h>
+ #include <linux/pci-ecam.h>
+ #include <linux/platform_device.h>
+
+@@ -284,6 +285,40 @@ static int thunder_pem_config_write(struct pci_bus *bus, unsigned int devfn,
+ return pci_generic_config_write(bus, devfn, where, size, val);
+ }
+
++#ifdef CONFIG_ACPI
++static struct resource thunder_pem_reg_res[] = {
++ [4] = DEFINE_RES_MEM(0x87e0c0000000UL, SZ_16M),
++ [5] = DEFINE_RES_MEM(0x87e0c1000000UL, SZ_16M),
++ [6] = DEFINE_RES_MEM(0x87e0c2000000UL, SZ_16M),
++ [7] = DEFINE_RES_MEM(0x87e0c3000000UL, SZ_16M),
++ [8] = DEFINE_RES_MEM(0x87e0c4000000UL, SZ_16M),
++ [9] = DEFINE_RES_MEM(0x87e0c5000000UL, SZ_16M),
++ [14] = DEFINE_RES_MEM(0x97e0c0000000UL, SZ_16M),
++ [15] = DEFINE_RES_MEM(0x97e0c1000000UL, SZ_16M),
++ [16] = DEFINE_RES_MEM(0x97e0c2000000UL, SZ_16M),
++ [17] = DEFINE_RES_MEM(0x97e0c3000000UL, SZ_16M),
++ [18] = DEFINE_RES_MEM(0x97e0c4000000UL, SZ_16M),
++ [19] = DEFINE_RES_MEM(0x97e0c5000000UL, SZ_16M),
++};
++
++static struct resource *thunder_pem_acpi_res(struct pci_config_window *cfg)
++{
++ struct acpi_device *adev = to_acpi_device(cfg->parent);
++ struct acpi_pci_root *root = acpi_driver_data(adev);
++
++ if ((root->segment >= 4 && root->segment <= 9) ||
++ (root->segment >= 14 && root->segment <= 19))
++ return &thunder_pem_reg_res[root->segment];
++
++ return NULL;
++}
++#else
++static struct resource *thunder_pem_acpi_res(struct pci_config_window *cfg)
++{
++ return NULL;
++}
++#endif
++
+ static int thunder_pem_init(struct pci_config_window *cfg)
+ {
+ struct device *dev = cfg->parent;
+@@ -292,24 +327,24 @@ static int thunder_pem_init(struct pci_config_window *cfg)
+ struct thunder_pem_pci *pem_pci;
+ struct platform_device *pdev;
+
+- /* Only OF support for now */
+- if (!dev->of_node)
+- return -EINVAL;
+-
+ pem_pci = devm_kzalloc(dev, sizeof(*pem_pci), GFP_KERNEL);
+ if (!pem_pci)
+ return -ENOMEM;
+
+- pdev = to_platform_device(dev);
+-
+- /*
+- * The second register range is the PEM bridge to the PCIe
+- * bus. It has a different config access method than those
+- * devices behind the bridge.
+- */
+- res_pem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++ if (acpi_disabled) {
++ pdev = to_platform_device(dev);
++
++ /*
++ * The second register range is the PEM bridge to the PCIe
++ * bus. It has a different config access method than those
++ * devices behind the bridge.
++ */
++ res_pem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++ } else {
++ res_pem = thunder_pem_acpi_res(cfg);
++ }
+ if (!res_pem) {
+- dev_err(dev, "missing \"reg[1]\"property\n");
++ dev_err(dev, "missing configuration region\n");
+ return -EINVAL;
+ }
+
+--
+2.9.3
+
+From 443d85d47ee00b3f0b6f39d470a11e7eb116817d Mon Sep 17 00:00:00 2001
+From: Tomasz Nowicki <tn@semihalf.com>
+Date: Fri, 9 Sep 2016 21:24:06 +0200
+Subject: [PATCH 4/6] PCI: thunder: Enable ACPI PCI controller for ThunderX
+ pass2.x silicon version
+
+ThunderX PCIe controller to off-chip devices (so-called PEM) is not fully
+compliant with ECAM standard. It uses non-standard configuration space
+accessors (see pci_thunder_pem_ops) and custom configuration space granulation
+(see bus_shift = 24). In order to access configuration space and
+probe PEM as ACPI based PCI host controller we need to add MCFG quirk
+infrastructure. This involves:
+1. Export PEM pci_thunder_pem_ops structure so it is visible to MCFG quirk
+ code.
+2. New quirk entries for each PEM segment. Each contains platform IDs,
+ mentioned pci_thunder_pem_ops and CFG resources.
+
+Quirk is considered for ThunderX silicon pass2.x only which is identified
+via MCFG revision 1.
+
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+---
+ drivers/acpi/pci_mcfg.c | 27 +++++++++++++++++++++++++++
+ drivers/pci/host/pci-thunder-pem.c | 2 +-
+ include/linux/pci-ecam.h | 4 ++++
+ 3 files changed, 32 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
+index 2b8acc7..1f73d7b 100644
+--- a/drivers/acpi/pci_mcfg.c
++++ b/drivers/acpi/pci_mcfg.c
+@@ -51,6 +51,33 @@ struct mcfg_fixup {
+
+ static struct mcfg_fixup mcfg_quirks[] = {
+ /* { OEM_ID, OEM_TABLE_ID, REV, DOMAIN, BUS_RANGE, cfgres, ops }, */
++#ifdef CONFIG_PCI_HOST_THUNDER_PEM
++ /* SoC pass2.x */
++ { "CAVIUM", "THUNDERX", 1, 4, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x88001f000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 1, 5, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x884057000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 1, 6, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x88808f000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 1, 7, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x89001f000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 1, 8, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x894057000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 1, 9, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x89808f000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 1, 14, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x98001f000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 1, 15, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x984057000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 1, 16, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x98808f000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 1, 17, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x99001f000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 1, 18, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x994057000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 1, 19, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x99808f000000UL, 0x39 * SZ_16M) },
++#endif
+ };
+
+ static char mcfg_oem_id[ACPI_OEM_ID_SIZE];
+diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/host/pci-thunder-pem.c
+index b048761..d7c10cc 100644
+--- a/drivers/pci/host/pci-thunder-pem.c
++++ b/drivers/pci/host/pci-thunder-pem.c
+@@ -367,7 +367,7 @@ static int thunder_pem_init(struct pci_config_window *cfg)
+ return 0;
+ }
+
+-static struct pci_ecam_ops pci_thunder_pem_ops = {
++struct pci_ecam_ops pci_thunder_pem_ops = {
+ .bus_shift = 24,
+ .init = thunder_pem_init,
+ .pci_ops = {
+diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h
+index 7adad20..65505ea 100644
+--- a/include/linux/pci-ecam.h
++++ b/include/linux/pci-ecam.h
+@@ -58,6 +58,10 @@ void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
+ int where);
+ /* default ECAM ops */
+ extern struct pci_ecam_ops pci_generic_ecam_ops;
++/* ECAM ops for known quirks */
++#ifdef CONFIG_PCI_HOST_THUNDER_PEM
++extern struct pci_ecam_ops pci_thunder_pem_ops;
++#endif
+
+ #ifdef CONFIG_PCI_HOST_GENERIC
+ /* for DT-based PCI controllers that support ECAM */
+--
+2.9.3
+
+From 6eca99cc392a11bb07b9ef88bca71a85f8bbe273 Mon Sep 17 00:00:00 2001
+From: Tomasz Nowicki <tn@semihalf.com>
+Date: Fri, 9 Sep 2016 21:24:07 +0200
+Subject: [PATCH 5/6] PCI: thunder: Enable ACPI PCI controller for ThunderX
+ pass1.x silicon version
+
+ThunderX pass1.x requires to emulate the EA headers for on-chip devices
+hence it has to use custom pci_thunder_ecam_ops for accessing PCI config
+space (pci-thuner-ecam.c). Add new entries to MCFG quirk array where they
+can be applied while probing ACPI based PCI host controller.
+
+ThunderX pass1.x is using the same way for accessing off-chip devices
+(so-called PEM) as silicon pass-2.x so we need to add PEM quirk
+entries too.
+
+Quirk is considered for ThunderX silicon pass1.x only which is identified
+via MCFG revision 2.
+
+Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
+---
+ drivers/acpi/pci_mcfg.c | 45 +++++++++++++++++++++++++++++++++++++
+ drivers/pci/host/pci-thunder-ecam.c | 2 +-
+ include/linux/pci-ecam.h | 3 +++
+ 3 files changed, 49 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
+index 1f73d7b..eb14f74 100644
+--- a/drivers/acpi/pci_mcfg.c
++++ b/drivers/acpi/pci_mcfg.c
+@@ -77,6 +77,51 @@ static struct mcfg_fixup mcfg_quirks[] = {
+ DEFINE_RES_MEM(0x994057000000UL, 0x39 * SZ_16M) },
+ { "CAVIUM", "THUNDERX", 1, 19, MCFG_BUS_ANY, &pci_thunder_pem_ops,
+ DEFINE_RES_MEM(0x99808f000000UL, 0x39 * SZ_16M) },
++
++ /* SoC pass1.x */
++ { "CAVIUM", "THUNDERX", 2, 4, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x88001f000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 2, 5, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x884057000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 2, 6, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x88808f000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 2, 7, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x89001f000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 2, 8, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x894057000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 2, 9, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x89808f000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 2, 14, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x98001f000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 2, 15, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x984057000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 2, 16, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x98808f000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 2, 17, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x99001f000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 2, 18, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x994057000000UL, 0x39 * SZ_16M) },
++ { "CAVIUM", "THUNDERX", 2, 19, MCFG_BUS_ANY, &pci_thunder_pem_ops,
++ DEFINE_RES_MEM(0x99808f000000UL, 0x39 * SZ_16M) },
++#endif
++#ifdef CONFIG_PCI_HOST_THUNDER_ECAM
++ /* SoC pass1.x */
++ { "CAVIUM", "THUNDERX", 2, 0, MCFG_BUS_ANY, &pci_thunder_ecam_ops,
++ MCFG_RES_EMPTY},
++ { "CAVIUM", "THUNDERX", 2, 1, MCFG_BUS_ANY, &pci_thunder_ecam_ops,
++ MCFG_RES_EMPTY},
++ { "CAVIUM", "THUNDERX", 2, 2, MCFG_BUS_ANY, &pci_thunder_ecam_ops,
++ MCFG_RES_EMPTY},
++ { "CAVIUM", "THUNDERX", 2, 3, MCFG_BUS_ANY, &pci_thunder_ecam_ops,
++ MCFG_RES_EMPTY},
++ { "CAVIUM", "THUNDERX", 2, 10, MCFG_BUS_ANY, &pci_thunder_ecam_ops,
++ MCFG_RES_EMPTY},
++ { "CAVIUM", "THUNDERX", 2, 11, MCFG_BUS_ANY, &pci_thunder_ecam_ops,
++ MCFG_RES_EMPTY},
++ { "CAVIUM", "THUNDERX", 2, 12, MCFG_BUS_ANY, &pci_thunder_ecam_ops,
++ MCFG_RES_EMPTY},
++ { "CAVIUM", "THUNDERX", 2, 13, MCFG_BUS_ANY, &pci_thunder_ecam_ops,
++ MCFG_RES_EMPTY},
+ #endif
+ };
+
+diff --git a/drivers/pci/host/pci-thunder-ecam.c b/drivers/pci/host/pci-thunder-ecam.c
+index d50a3dc..b6c17e2 100644
+--- a/drivers/pci/host/pci-thunder-ecam.c
++++ b/drivers/pci/host/pci-thunder-ecam.c
+@@ -346,7 +346,7 @@ static int thunder_ecam_config_write(struct pci_bus *bus, unsigned int devfn,
+ return pci_generic_config_write(bus, devfn, where, size, val);
+ }
+
+-static struct pci_ecam_ops pci_thunder_ecam_ops = {
++struct pci_ecam_ops pci_thunder_ecam_ops = {
+ .bus_shift = 20,
+ .pci_ops = {
+ .map_bus = pci_ecam_map_bus,
+diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h
+index 65505ea..35f0e81 100644
+--- a/include/linux/pci-ecam.h
++++ b/include/linux/pci-ecam.h
+@@ -62,6 +62,9 @@ extern struct pci_ecam_ops pci_generic_ecam_ops;
+ #ifdef CONFIG_PCI_HOST_THUNDER_PEM
+ extern struct pci_ecam_ops pci_thunder_pem_ops;
+ #endif
++#ifdef CONFIG_PCI_HOST_THUNDER_ECAM
++extern struct pci_ecam_ops pci_thunder_ecam_ops;
++#endif
+
+ #ifdef CONFIG_PCI_HOST_GENERIC
+ /* for DT-based PCI controllers that support ECAM */
+--
+2.9.3
+
+From 3080ac5bb527155ccdf8490ce221b1c6ad01f502 Mon Sep 17 00:00:00 2001
+From: Duc Dang <dhdang@apm.com>
+Date: Sat, 17 Sep 2016 07:24:38 -0700
+Subject: [PATCH 6/6] PCI/ACPI: xgene: Add ECAM quirk for X-Gene PCIe
+ controller
+
+PCIe controller in X-Gene SoCs is not ECAM compliant: software
+needs to configure additional concontroller register to address
+device at bus:dev:function.
+
+This patch depends on "ECAM quirks handling for ARM64 platforms"
+series (http://www.spinics.net/lists/arm-kernel/msg530692.html)
+to address the limitation above for X-Gene PCIe controller.
+
+The quirk will only be applied for X-Gene PCIe MCFG table with
+OEM revison 1, 2, 3 or 4 (PCIe controller v1 and v2 on X-Gene SoCs).
+
+Signed-off-by: Duc Dang <dhdang@apm.com>
+---
+ drivers/acpi/pci_mcfg.c | 32 +++++
+ drivers/pci/host/Makefile | 2 +-
+ drivers/pci/host/pci-xgene-ecam.c | 280 ++++++++++++++++++++++++++++++++++++++
+ include/linux/pci-ecam.h | 5 +
+ 4 files changed, 318 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/pci/host/pci-xgene-ecam.c
+
+diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
+index eb14f74..635ab24 100644
+--- a/drivers/acpi/pci_mcfg.c
++++ b/drivers/acpi/pci_mcfg.c
+@@ -123,6 +123,38 @@ static struct mcfg_fixup mcfg_quirks[] = {
+ { "CAVIUM", "THUNDERX", 2, 13, MCFG_BUS_ANY, &pci_thunder_ecam_ops,
+ MCFG_RES_EMPTY},
+ #endif
++#ifdef CONFIG_PCI_XGENE
++ {"APM ", "XGENE ", 1, 0, MCFG_BUS_ANY,
++ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
++ {"APM ", "XGENE ", 1, 1, MCFG_BUS_ANY,
++ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
++ {"APM ", "XGENE ", 1, 2, MCFG_BUS_ANY,
++ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
++ {"APM ", "XGENE ", 1, 3, MCFG_BUS_ANY,
++ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
++ {"APM ", "XGENE ", 1, 4, MCFG_BUS_ANY,
++ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
++ {"APM ", "XGENE ", 2, 0, MCFG_BUS_ANY,
++ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
++ {"APM ", "XGENE ", 2, 1, MCFG_BUS_ANY,
++ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
++ {"APM ", "XGENE ", 2, 2, MCFG_BUS_ANY,
++ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
++ {"APM ", "XGENE ", 2, 3, MCFG_BUS_ANY,
++ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
++ {"APM ", "XGENE ", 2, 4, MCFG_BUS_ANY,
++ &xgene_v1_pcie_ecam_ops, MCFG_RES_EMPTY},
++ {"APM ", "XGENE ", 3, 0, MCFG_BUS_ANY,
++ &xgene_v2_1_pcie_ecam_ops, MCFG_RES_EMPTY},
++ {"APM ", "XGENE ", 3, 1, MCFG_BUS_ANY,
++ &xgene_v2_1_pcie_ecam_ops, MCFG_RES_EMPTY},
++ {"APM ", "XGENE ", 4, 0, MCFG_BUS_ANY,
++ &xgene_v2_2_pcie_ecam_ops, MCFG_RES_EMPTY},
++ {"APM ", "XGENE ", 4, 1, MCFG_BUS_ANY,
++ &xgene_v2_2_pcie_ecam_ops, MCFG_RES_EMPTY},
++ {"APM ", "XGENE ", 4, 2, MCFG_BUS_ANY,
++ &xgene_v2_2_pcie_ecam_ops, MCFG_RES_EMPTY},
++#endif
+ };
+
+ static char mcfg_oem_id[ACPI_OEM_ID_SIZE];
+diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
+index 8843410..af4f505 100644
+--- a/drivers/pci/host/Makefile
++++ b/drivers/pci/host/Makefile
+@@ -15,7 +15,7 @@ obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
+ obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
+ obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
+ obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o
+-obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
++obj-$(CONFIG_PCI_XGENE) += pci-xgene.o pci-xgene-ecam.o
+ obj-$(CONFIG_PCI_XGENE_MSI) += pci-xgene-msi.o
+ obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
+ obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
+diff --git a/drivers/pci/host/pci-xgene-ecam.c b/drivers/pci/host/pci-xgene-ecam.c
+new file mode 100644
+index 0000000..b66a04f
+--- /dev/null
++++ b/drivers/pci/host/pci-xgene-ecam.c
+@@ -0,0 +1,280 @@
++/*
++ * APM X-Gene PCIe ECAM fixup driver
++ *
++ * Copyright (c) 2016, Applied Micro Circuits Corporation
++ * Author:
++ * Duc Dang <dhdang@apm.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of_address.h>
++#include <linux/of_pci.h>
++#include <linux/pci-acpi.h>
++#include <linux/platform_device.h>
++#include <linux/pci-ecam.h>
++
++#ifdef CONFIG_ACPI
++#define RTDID 0x160
++#define ROOT_CAP_AND_CTRL 0x5C
++
++/* PCIe IP version */
++#define XGENE_PCIE_IP_VER_UNKN 0
++#define XGENE_PCIE_IP_VER_1 1
++#define XGENE_PCIE_IP_VER_2 2
++
++#define XGENE_CSR_LENGTH 0x10000
++
++struct xgene_pcie_acpi_root {
++ void __iomem *csr_base;
++ u32 version;
++};
++
++static int xgene_v1_pcie_ecam_init(struct pci_config_window *cfg)
++{
++ struct xgene_pcie_acpi_root *xgene_root;
++ struct device *dev = cfg->parent;
++ u32 csr_base;
++
++ xgene_root = devm_kzalloc(dev, sizeof(*xgene_root), GFP_KERNEL);
++ if (!xgene_root)
++ return -ENOMEM;
++
++ switch (cfg->res.start) {
++ case 0xE0D0000000ULL:
++ csr_base = 0x1F2B0000;
++ break;
++ case 0xD0D0000000ULL:
++ csr_base = 0x1F2C0000;
++ break;
++ case 0x90D0000000ULL:
++ csr_base = 0x1F2D0000;
++ break;
++ case 0xA0D0000000ULL:
++ csr_base = 0x1F500000;
++ break;
++ case 0xC0D0000000ULL:
++ csr_base = 0x1F510000;
++ break;
++ default:
++ return -ENODEV;
++ }
++
++ xgene_root->csr_base = ioremap(csr_base, XGENE_CSR_LENGTH);
++ if (!xgene_root->csr_base) {
++ kfree(xgene_root);
++ return -ENODEV;
++ }
++
++ xgene_root->version = XGENE_PCIE_IP_VER_1;
++
++ cfg->priv = xgene_root;
++
++ return 0;
++}
++
++static int xgene_v2_1_pcie_ecam_init(struct pci_config_window *cfg)
++{
++ struct xgene_pcie_acpi_root *xgene_root;
++ struct device *dev = cfg->parent;
++ resource_size_t csr_base;
++
++ xgene_root = devm_kzalloc(dev, sizeof(*xgene_root), GFP_KERNEL);
++ if (!xgene_root)
++ return -ENOMEM;
++
++ switch (cfg->res.start) {
++ case 0xC0D0000000ULL:
++ csr_base = 0x1F2B0000;
++ break;
++ case 0xA0D0000000ULL:
++ csr_base = 0x1F2C0000;
++ break;
++ default:
++ return -ENODEV;
++ }
++
++ xgene_root->csr_base = ioremap(csr_base, XGENE_CSR_LENGTH);
++ if (!xgene_root->csr_base) {
++ kfree(xgene_root);
++ return -ENODEV;
++ }
++
++ xgene_root->version = XGENE_PCIE_IP_VER_2;
++
++ cfg->priv = xgene_root;
++
++ return 0;
++}
++
++static int xgene_v2_2_pcie_ecam_init(struct pci_config_window *cfg)
++{
++ struct xgene_pcie_acpi_root *xgene_root;
++ struct device *dev = cfg->parent;
++ resource_size_t csr_base;
++
++ xgene_root = devm_kzalloc(dev, sizeof(*xgene_root), GFP_KERNEL);
++ if (!xgene_root)
++ return -ENOMEM;
++
++ switch (cfg->res.start) {
++ case 0xE0D0000000ULL:
++ csr_base = 0x1F2B0000;
++ break;
++ case 0xA0D0000000ULL:
++ csr_base = 0x1F500000;
++ break;
++ case 0x90D0000000ULL:
++ csr_base = 0x1F2D0000;
++ break;
++ default:
++ return -ENODEV;
++ }
++
++ xgene_root->csr_base = ioremap(csr_base, XGENE_CSR_LENGTH);
++ if (!xgene_root->csr_base) {
++ kfree(xgene_root);
++ return -ENODEV;
++ }
++
++ xgene_root->version = XGENE_PCIE_IP_VER_2;
++
++ cfg->priv = xgene_root;
++
++ return 0;
++}
++/*
++ * For Configuration request, RTDID register is used as Bus Number,
++ * Device Number and Function number of the header fields.
++ */
++static void xgene_pcie_set_rtdid_reg(struct pci_bus *bus, uint devfn)
++{
++ struct pci_config_window *cfg = bus->sysdata;
++ struct xgene_pcie_acpi_root *port = cfg->priv;
++ unsigned int b, d, f;
++ u32 rtdid_val = 0;
++
++ b = bus->number;
++ d = PCI_SLOT(devfn);
++ f = PCI_FUNC(devfn);
++
++ if (!pci_is_root_bus(bus))
++ rtdid_val = (b << 8) | (d << 3) | f;
++
++ writel(rtdid_val, port->csr_base + RTDID);
++ /* read the register back to ensure flush */
++ readl(port->csr_base + RTDID);
++}
++
++/*
++ * X-Gene PCIe port uses BAR0-BAR1 of RC's configuration space as
++ * the translation from PCI bus to native BUS. Entire DDR region
++ * is mapped into PCIe space using these registers, so it can be
++ * reached by DMA from EP devices. The BAR0/1 of bridge should be
++ * hidden during enumeration to avoid the sizing and resource allocation
++ * by PCIe core.
++ */
++static bool xgene_pcie_hide_rc_bars(struct pci_bus *bus, int offset)
++{
++ if (pci_is_root_bus(bus) && ((offset == PCI_BASE_ADDRESS_0) ||
++ (offset == PCI_BASE_ADDRESS_1)))
++ return true;
++
++ return false;
++}
++
++void __iomem *xgene_pcie_ecam_map_bus(struct pci_bus *bus,
++ unsigned int devfn, int where)
++{
++ struct pci_config_window *cfg = bus->sysdata;
++ unsigned int busn = bus->number;
++ void __iomem *base;
++
++ if (busn < cfg->busr.start || busn > cfg->busr.end)
++ return NULL;
++
++ if ((pci_is_root_bus(bus) && devfn != 0) ||
++ xgene_pcie_hide_rc_bars(bus, where))
++ return NULL;
++
++ xgene_pcie_set_rtdid_reg(bus, devfn);
++
++ if (busn > cfg->busr.start)
++ base = cfg->win + (1 << cfg->ops->bus_shift);
++ else
++ base = cfg->win;
++
++ return base + where;
++}
++
++static int xgene_pcie_config_read32(struct pci_bus *bus, unsigned int devfn,
++ int where, int size, u32 *val)
++{
++ struct pci_config_window *cfg = bus->sysdata;
++ struct xgene_pcie_acpi_root *port = cfg->priv;
++
++ if (pci_generic_config_read32(bus, devfn, where & ~0x3, 4, val) !=
++ PCIBIOS_SUCCESSFUL)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ /*
++ * The v1 controller has a bug in its Configuration Request
++ * Retry Status (CRS) logic: when CRS is enabled and we read the
++ * Vendor and Device ID of a non-existent device, the controller
++ * fabricates return data of 0xFFFF0001 ("device exists but is not
++ * ready") instead of 0xFFFFFFFF ("device does not exist"). This
++ * causes the PCI core to retry the read until it times out.
++ * Avoid this by not claiming to support CRS.
++ */
++ if (pci_is_root_bus(bus) && (port->version == XGENE_PCIE_IP_VER_1) &&
++ ((where & ~0x3) == ROOT_CAP_AND_CTRL))
++ *val &= ~(PCI_EXP_RTCAP_CRSVIS << 16);
++
++ if (size <= 2)
++ *val = (*val >> (8 * (where & 3))) & ((1 << (size * 8)) - 1);
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++struct pci_ecam_ops xgene_v1_pcie_ecam_ops = {
++ .bus_shift = 16,
++ .init = xgene_v1_pcie_ecam_init,
++ .pci_ops = {
++ .map_bus = xgene_pcie_ecam_map_bus,
++ .read = xgene_pcie_config_read32,
++ .write = pci_generic_config_write,
++ }
++};
++
++struct pci_ecam_ops xgene_v2_1_pcie_ecam_ops = {
++ .bus_shift = 16,
++ .init = xgene_v2_1_pcie_ecam_init,
++ .pci_ops = {
++ .map_bus = xgene_pcie_ecam_map_bus,
++ .read = xgene_pcie_config_read32,
++ .write = pci_generic_config_write,
++ }
++};
++
++struct pci_ecam_ops xgene_v2_2_pcie_ecam_ops = {
++ .bus_shift = 16,
++ .init = xgene_v2_2_pcie_ecam_init,
++ .pci_ops = {
++ .map_bus = xgene_pcie_ecam_map_bus,
++ .read = xgene_pcie_config_read32,
++ .write = pci_generic_config_write,
++ }
++};
++#endif
+diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h
+index 35f0e81..40da3e7 100644
+--- a/include/linux/pci-ecam.h
++++ b/include/linux/pci-ecam.h
+@@ -65,6 +65,11 @@ extern struct pci_ecam_ops pci_thunder_pem_ops;
+ #ifdef CONFIG_PCI_HOST_THUNDER_ECAM
+ extern struct pci_ecam_ops pci_thunder_ecam_ops;
+ #endif
++#ifdef CONFIG_PCI_XGENE
++extern struct pci_ecam_ops xgene_v1_pcie_ecam_ops;
++extern struct pci_ecam_ops xgene_v2_1_pcie_ecam_ops;
++extern struct pci_ecam_ops xgene_v2_2_pcie_ecam_ops;
++#endif
+
+ #ifdef CONFIG_PCI_HOST_GENERIC
+ /* for DT-based PCI controllers that support ECAM */
+--
+2.9.3
+
diff --git a/bcm283x-upstream-fixes.patch b/bcm2837-initial-support.patch
index 82abd874b..0e641d693 100644
--- a/bcm283x-upstream-fixes.patch
+++ b/bcm2837-initial-support.patch
@@ -1,56 +1,27 @@
-From da77f737f9f5a487f3a1f80f8546585ee18cd7b9 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-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 <eric@anholt.net>
-Acked-by: Rob Herring <robh@kernel.org>
----
- 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 <eric@anholt.net>
-Date: Fri, 4 Mar 2016 10:39:29 -0800
-Subject: [PATCH 28/36] ARM: bcm2835: Add devicetree for the Raspberry Pi 3.
+From a2858804c7f5f4585b718543236b7ba3b3ec813a Mon Sep 17 00:00:00 2001
+From: Peter Robinson <pbrobinson@gmail.com>
+Date: Mon, 29 Aug 2016 09:14:15 +0100
+Subject: [PATCH] ARM: bcm283x: 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.
+wifi, GPIO expander).
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Acked-by: Stephen Warren <swarren@wwwdotorg.org>
+Rebased to the patch that went upstream for ARM64
+
+Signed-off-by: Peter Robinson <pbrobinson@gmail.com>
---
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(-)
+ arch/arm/boot/dts/bcm2837-rpi-3-b.dts | 30 ++++++++++++++
+ arch/arm/boot/dts/bcm2837.dtsi | 76 +++++++++++++++++++++++++++++++++++
+ 3 files changed, 108 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
+index faacd52..ec41888 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
-@@ -64,7 +64,8 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
+@@ -69,7 +69,8 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
bcm2835-rpi-b-rev2.dtb \
bcm2835-rpi-b-plus.dtb \
bcm2835-rpi-a-plus.dtb \
@@ -62,13 +33,14 @@ index d000814..a8a0767 100644
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
+index 0000000..7841b72
--- /dev/null
+++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
-@@ -0,0 +1,22 @@
+@@ -0,0 +1,30 @@
+/dts-v1/;
+#include "bcm2837.dtsi"
+#include "bcm2835-rpi.dtsi"
++#include "bcm283x-rpi-smsc9514.dtsi"
+
+/ {
+ compatible = "raspberrypi,3-model-b", "brcm,bcm2837";
@@ -77,23 +49,30 @@ index 0000000..5e8eafd
+ memory {
+ reg = <0 0x40000000>;
+ };
-+};
+
-+&gpio {
-+ pinctrl-0 = <&gpioout &alt0 &i2s_alt0 &alt3>;
++ leds {
++ act {
++ gpios = <&gpio 47 0>;
++ };
+
-+ /* I2S interface */
-+ i2s_alt0: i2s_alt0 {
-+ brcm,pins = <28 29 30 31>;
-+ brcm,function = <BCM2835_FSEL_ALT2>;
++ pwr {
++ label = "PWR";
++ gpios = <&gpio 35 0>;
++ default-state = "keep";
++ linux,default-trigger = "default-on";
++ };
+ };
+};
++
++&uart1 {
++ status = "okay";
++};
diff --git a/arch/arm/boot/dts/bcm2837.dtsi b/arch/arm/boot/dts/bcm2837.dtsi
new file mode 100644
-index 0000000..2f36722
+index 0000000..8216bbb
--- /dev/null
+++ b/arch/arm/boot/dts/bcm2837.dtsi
-@@ -0,0 +1,68 @@
+@@ -0,0 +1,76 @@
+#include "bcm283x.dtsi"
+
+/ {
@@ -131,24 +110,32 @@ index 0000000..2f36722
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0>;
++ enable-method = "spin-table";
++ cpu-release-addr = <0x0 0x000000d8>;
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <1>;
++ enable-method = "spin-table";
++ cpu-release-addr = <0x0 0x000000e0>;
+ };
+
+ cpu2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <2>;
++ enable-method = "spin-table";
++ cpu-release-addr = <0x0 0x000000e8>;
+ };
+
+ cpu3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <3>;
++ enable-method = "spin-table";
++ cpu-release-addr = <0x0 0x000000f0>;
+ };
+ };
+};
@@ -163,4 +150,4 @@ index 0000000..2f36722
+ interrupts = <8>;
+};
--
-2.7.3
+2.9.3
diff --git a/bcm283x-vc4-fixes.patch b/bcm283x-vc4-fixes.patch
new file mode 100644
index 000000000..3f77b7485
--- /dev/null
+++ b/bcm283x-vc4-fixes.patch
@@ -0,0 +1,682 @@
+From 9db79f3a51c97e0cfcde1b25299e8db9ee3d64ab Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 14 Sep 2016 19:21:29 +0100
+Subject: [PATCH 1/4] drm/vc4: Fall back to using an EDID probe in the absence
+ of a GPIO.
+
+On Pi0/1/2, we use an external GPIO line for hotplug detection, since
+the HDMI_HOTPLUG register isn't connected to anything. However, with
+the Pi3 the HPD GPIO line has moved off to a GPIO expander that will
+be tricky to get to (the firmware is constantly polling the expander
+using i2c0, so we'll need to coordinate with it).
+
+As a stop-gap, if we don't have a GPIO line, use an EDID probe to
+detect connection. Fixes HDMI display on the pi3.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
+index 4452f36..5adc0c7 100644
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -174,6 +174,9 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
+ return connector_status_disconnected;
+ }
+
++ if (drm_probe_ddc(vc4->hdmi->ddc))
++ return connector_status_connected;
++
+ if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
+ return connector_status_connected;
+ else
+--
+2.9.3
+
+From 7b4c39f34fbbdfe0cd0e626686ee01ab96601598 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 16 Sep 2016 10:59:45 +0100
+Subject: [PATCH 2/4] drm/vc4: Enable limited range RGB output on HDMI with CEA
+ modes.
+
+Fixes broken grayscale ramps on many HDMI monitors, where large areas
+at the ends of the ramp would all appear as black or white.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 31 +++++++++++++++++++++++++++++--
+ drivers/gpu/drm/vc4/vc4_regs.h | 9 ++++++++-
+ 2 files changed, 37 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
+index 5adc0c7..5df4e74 100644
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -276,6 +276,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *unadjusted_mode,
+ struct drm_display_mode *mode)
+ {
++ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
+ struct drm_device *dev = encoder->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ bool debug_dump_regs = false;
+@@ -291,6 +292,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
+ u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) |
+ VC4_SET_FIELD(mode->vtotal - mode->vsync_end,
+ VC4_HDMI_VERTB_VBP));
++ u32 csc_ctl;
+
+ if (debug_dump_regs) {
+ DRM_INFO("HDMI regs before:\n");
+@@ -329,9 +331,34 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
+ (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
+ (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
+
++ csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
++ VC4_HD_CSC_CTL_ORDER);
++
++ if (vc4_encoder->hdmi_monitor && drm_match_cea_mode(mode) > 1) {
++ /* CEA VICs other than #1 requre limited range RGB
++ * output. Apply a colorspace conversion to squash
++ * 0-255 down to 16-235. The matrix here is:
++ *
++ * [ 0 0 0.8594 16]
++ * [ 0 0.8594 0 16]
++ * [ 0.8594 0 0 16]
++ * [ 0 0 0 1]
++ */
++ csc_ctl |= VC4_HD_CSC_CTL_ENABLE;
++ csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC;
++ csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
++ VC4_HD_CSC_CTL_MODE);
++
++ HD_WRITE(VC4_HD_CSC_12_11, (0x000 << 16) | 0x000);
++ HD_WRITE(VC4_HD_CSC_14_13, (0x100 << 16) | 0x6e0);
++ HD_WRITE(VC4_HD_CSC_22_21, (0x6e0 << 16) | 0x000);
++ HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000);
++ HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0);
++ HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000);
++ }
++
+ /* The RGB order applies even when CSC is disabled. */
+- HD_WRITE(VC4_HD_CSC_CTL, VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
+- VC4_HD_CSC_CTL_ORDER));
++ HD_WRITE(VC4_HD_CSC_CTL, csc_ctl);
+
+ HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
+
+diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
+index 160942a..9ecd6ff 100644
+--- a/drivers/gpu/drm/vc4/vc4_regs.h
++++ b/drivers/gpu/drm/vc4/vc4_regs.h
+@@ -528,10 +528,17 @@
+ # define VC4_HD_CSC_CTL_MODE_SHIFT 2
+ # define VC4_HD_CSC_CTL_MODE_RGB_TO_SD_YPRPB 0
+ # define VC4_HD_CSC_CTL_MODE_RGB_TO_HD_YPRPB 1
+-# define VC4_HD_CSC_CTL_MODE_CUSTOM 2
++# define VC4_HD_CSC_CTL_MODE_CUSTOM 3
+ # define VC4_HD_CSC_CTL_RGB2YCC BIT(1)
+ # define VC4_HD_CSC_CTL_ENABLE BIT(0)
+
++#define VC4_HD_CSC_12_11 0x044
++#define VC4_HD_CSC_14_13 0x048
++#define VC4_HD_CSC_22_21 0x04c
++#define VC4_HD_CSC_24_23 0x050
++#define VC4_HD_CSC_32_31 0x054
++#define VC4_HD_CSC_34_33 0x058
++
+ #define VC4_HD_FRAME_COUNT 0x068
+
+ /* HVS display list information. */
+--
+2.9.3
+
+From f379f5432e4b74e3d1d894ce2fefbe1b8a3c24fd Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 28 Sep 2016 19:20:44 -0700
+Subject: [PATCH 4/4] drm/vc4: Increase timeout for HDMI_SCHEDULER_CONTROL
+ changes.
+
+Fixes occasional debug spew at boot when connected directly through
+HDMI, and probably confusing the HDMI state machine when we go trying
+to poke registers for the enable sequence too soon.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
+index 5df4e74..9a6883d 100644
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -399,7 +399,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
+ VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
+
+ ret = wait_for(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+- VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1);
++ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000);
+ WARN_ONCE(ret, "Timeout waiting for "
+ "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
+ } else {
+@@ -411,7 +411,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
+ ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
+
+ ret = wait_for(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+- VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1);
++ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000);
+ WARN_ONCE(ret, "Timeout waiting for "
+ "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
+ }
+--
+2.9.3
+
+From bd712d14886c37eb804036b2ac3036df79d33476 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 29 Sep 2016 15:34:43 -0700
+Subject: [PATCH] drm/vc4: Set up the AVI and SPD infoframes.
+
+Fixes a purple bar on the left side of the screen with my Dell
+2408WFP. It will also be required for supporting the double-clocked
+video modes.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 136 +++++++++++++++++++++++++++++++++++++++--
+ drivers/gpu/drm/vc4/vc4_regs.h | 5 ++
+ 2 files changed, 136 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
+index 9a6883d..f722334 100644
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -62,6 +62,8 @@ struct vc4_hdmi {
+ struct vc4_hdmi_encoder {
+ struct vc4_encoder base;
+ bool hdmi_monitor;
++ bool limited_rgb_range;
++ bool rgb_range_selectable;
+ };
+
+ static inline struct vc4_hdmi_encoder *
+@@ -205,6 +207,12 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
+ return -ENODEV;
+
+ vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
++
++ if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
++ vc4_encoder->rgb_range_selectable =
++ drm_rgb_quant_range_selectable(edid);
++ }
++
+ drm_mode_connector_update_edid_property(connector, edid);
+ ret = drm_add_edid_modes(connector, edid);
+
+@@ -272,6 +280,117 @@ static const struct drm_encoder_funcs vc4_hdmi_encoder_funcs = {
+ .destroy = vc4_hdmi_encoder_destroy,
+ };
+
++static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
++ enum hdmi_infoframe_type type)
++{
++ struct drm_device *dev = encoder->dev;
++ struct vc4_dev *vc4 = to_vc4_dev(dev);
++ u32 packet_id = type - 0x80;
++
++ HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
++ HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id));
++
++ return wait_for(!(HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
++ BIT(packet_id)), 100);
++}
++
++static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
++ union hdmi_infoframe *frame)
++{
++ struct drm_device *dev = encoder->dev;
++ struct vc4_dev *vc4 = to_vc4_dev(dev);
++ u32 packet_id = frame->any.type - 0x80;
++ u32 packet_reg = VC4_HDMI_GCP_0 + VC4_HDMI_PACKET_STRIDE * packet_id;
++ uint8_t buffer[VC4_HDMI_PACKET_STRIDE];
++ ssize_t len, i;
++ int ret;
++
++ WARN_ONCE(!(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
++ VC4_HDMI_RAM_PACKET_ENABLE),
++ "Packet RAM has to be on to store the packet.");
++
++ len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer));
++ if (len < 0)
++ return;
++
++ ret = vc4_hdmi_stop_packet(encoder, frame->any.type);
++ if (ret) {
++ DRM_ERROR("Failed to wait for infoframe to go idle: %d\n", ret);
++ return;
++ }
++
++ for (i = 0; i < len; i += 7) {
++ HDMI_WRITE(packet_reg,
++ buffer[i + 0] << 0 |
++ buffer[i + 1] << 8 |
++ buffer[i + 2] << 16);
++ packet_reg += 4;
++
++ HDMI_WRITE(packet_reg,
++ buffer[i + 3] << 0 |
++ buffer[i + 4] << 8 |
++ buffer[i + 5] << 16 |
++ buffer[i + 6] << 24);
++ packet_reg += 4;
++ }
++
++ HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
++ HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
++ ret = wait_for((HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
++ BIT(packet_id)), 100);
++ if (ret)
++ DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret);
++}
++
++static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
++{
++ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
++ struct drm_crtc *crtc = encoder->crtc;
++ const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
++ union hdmi_infoframe frame;
++ int ret;
++
++ ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
++ if (ret < 0) {
++ DRM_ERROR("couldn't fill AVI infoframe\n");
++ return;
++ }
++
++ if (vc4_encoder->rgb_range_selectable) {
++ if (vc4_encoder->limited_rgb_range) {
++ frame.avi.quantization_range =
++ HDMI_QUANTIZATION_RANGE_LIMITED;
++ } else {
++ frame.avi.quantization_range =
++ HDMI_QUANTIZATION_RANGE_FULL;
++ }
++ }
++
++ vc4_hdmi_write_infoframe(encoder, &frame);
++}
++
++static void vc4_hdmi_set_spd_infoframe(struct drm_encoder *encoder)
++{
++ union hdmi_infoframe frame;
++ int ret;
++
++ ret = hdmi_spd_infoframe_init(&frame.spd, "Broadcom", "Videocore");
++ if (ret < 0) {
++ DRM_ERROR("couldn't fill SPD infoframe\n");
++ return;
++ }
++
++ frame.spd.sdi = HDMI_SPD_SDI_PC;
++
++ vc4_hdmi_write_infoframe(encoder, &frame);
++}
++
++static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
++{
++ vc4_hdmi_set_avi_infoframe(encoder);
++ vc4_hdmi_set_spd_infoframe(encoder);
++}
++
+ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *unadjusted_mode,
+ struct drm_display_mode *mode)
+@@ -336,8 +455,9 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
+
+ if (vc4_encoder->hdmi_monitor && drm_match_cea_mode(mode) > 1) {
+ /* CEA VICs other than #1 requre limited range RGB
+- * output. Apply a colorspace conversion to squash
+- * 0-255 down to 16-235. The matrix here is:
++ * output unless overridden by an AVI infoframe.
++ * Apply a colorspace conversion to squash 0-255 down
++ * to 16-235. The matrix here is:
+ *
+ * [ 0 0 0.8594 16]
+ * [ 0 0.8594 0 16]
+@@ -355,6 +475,9 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
+ HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000);
+ HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0);
+ HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000);
++ vc4_encoder->limited_rgb_range = true;
++ } else {
++ vc4_encoder->limited_rgb_range = false;
+ }
+
+ /* The RGB order applies even when CSC is disabled. */
+@@ -373,6 +496,8 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
+ struct drm_device *dev = encoder->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+
++ HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0);
++
+ HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+ HD_WRITE(VC4_HD_VID_CTL,
+ HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
+@@ -425,9 +550,10 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
+ HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
+ VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT);
+
+- /* XXX: Set HDMI_RAM_PACKET_CONFIG (1 << 16) and set
+- * up the infoframe.
+- */
++ HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
++ VC4_HDMI_RAM_PACKET_ENABLE);
++
++ vc4_hdmi_set_infoframes(encoder);
+
+ drift = HDMI_READ(VC4_HDMI_FIFO_CTL);
+ drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
+diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
+index 9ecd6ff..a4b5370 100644
+--- a/drivers/gpu/drm/vc4/vc4_regs.h
++++ b/drivers/gpu/drm/vc4/vc4_regs.h
+@@ -438,6 +438,8 @@
+ #define VC4_HDMI_RAM_PACKET_CONFIG 0x0a0
+ # define VC4_HDMI_RAM_PACKET_ENABLE BIT(16)
+
++#define VC4_HDMI_RAM_PACKET_STATUS 0x0a4
++
+ #define VC4_HDMI_HORZA 0x0c4
+ # define VC4_HDMI_HORZA_VPOS BIT(14)
+ # define VC4_HDMI_HORZA_HPOS BIT(13)
+@@ -499,6 +501,9 @@
+
+ #define VC4_HDMI_TX_PHY_RESET_CTL 0x2c0
+
++#define VC4_HDMI_GCP_0 0x400
++#define VC4_HDMI_PACKET_STRIDE 0x24
++
+ #define VC4_HD_M_CTL 0x00c
+ # define VC4_HD_M_REGISTER_FILE_STANDBY (3 << 6)
+ # define VC4_HD_M_RAM_STANDBY (3 << 4)
+--
+2.9.3
+
+From c4e634ce412d97f0e61223b2a5b3f8f9600cd4dc Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 30 Sep 2016 10:07:27 -0700
+Subject: clk: bcm2835: Clamp the PLL's requested rate to the hardware limits.
+
+Fixes setting low-resolution video modes on HDMI. Now the PLLH_PIX
+divider adjusts itself until the PLLH is within bounds.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
+index b68bf57..8c7763f 100644
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -502,8 +502,12 @@ static long bcm2835_pll_rate_from_divisors(unsigned long parent_rate,
+ static long bcm2835_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+ {
++ struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
++ const struct bcm2835_pll_data *data = pll->data;
+ u32 ndiv, fdiv;
+
++ rate = clamp(rate, data->min_rate, data->max_rate);
++
+ bcm2835_pll_choose_ndiv_and_fdiv(rate, *parent_rate, &ndiv, &fdiv);
+
+ return bcm2835_pll_rate_from_divisors(*parent_rate, ndiv, fdiv, 1);
+@@ -608,13 +612,6 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw,
+ u32 ana[4];
+ int i;
+
+- if (rate < data->min_rate || rate > data->max_rate) {
+- dev_err(cprman->dev, "%s: rate out of spec: %lu vs (%lu, %lu)\n",
+- clk_hw_get_name(hw), rate,
+- data->min_rate, data->max_rate);
+- return -EINVAL;
+- }
+-
+ if (rate > data->max_fb_rate) {
+ use_fb_prediv = true;
+ rate /= 2;
+--
+cgit v0.12
+
+From e69fdcca836f0b81a2260b69429c8622a80ea891 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 1 Jun 2016 12:05:33 -0700
+Subject: clk: bcm2835: Mark the VPU clock as critical
+
+The VPU clock is also the clock for our AXI bus, so we really can't
+disable it. This might have happened during boot if, for example,
+uart1 (aux_uart clock) probed and was then disabled before the other
+consumers of the VPU clock had probed.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Acked-by: Martin Sperl <kernel@martin.sperl.org>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
+index 7a79708..d9db03c 100644
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -443,6 +443,8 @@ struct bcm2835_clock_data {
+ /* Number of fractional bits in the divider */
+ u32 frac_bits;
+
++ u32 flags;
++
+ bool is_vpu_clock;
+ bool is_mash_clock;
+ };
+@@ -1230,7 +1232,7 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
+ init.parent_names = parents;
+ init.num_parents = data->num_mux_parents;
+ init.name = data->name;
+- init.flags = CLK_IGNORE_UNUSED;
++ init.flags = data->flags | CLK_IGNORE_UNUSED;
+
+ if (data->is_vpu_clock) {
+ init.ops = &bcm2835_vpu_clock_clk_ops;
+@@ -1649,6 +1651,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
+ .div_reg = CM_VPUDIV,
+ .int_bits = 12,
+ .frac_bits = 8,
++ .flags = CLK_IS_CRITICAL,
+ .is_vpu_clock = true),
+
+ /* clocks with per parent mux */
+--
+cgit v0.12
+
+From eddcbe8398fc7103fccd22aa6df6917caf0123bf Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 1 Jun 2016 12:05:34 -0700
+Subject: clk: bcm2835: Mark GPIO clocks enabled at boot as critical
+
+These divide off of PLLD_PER and are used for the ethernet and wifi
+PHYs source PLLs. Neither of them is currently represented by a phy
+device that would grab the clock for us.
+
+This keeps other drivers from killing the networking PHYs when they
+disable their own clocks and trigger PLLD_PER's refcount going to 0.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Acked-by: Martin Sperl <kernel@martin.sperl.org>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
+index d9db03c..400615b 100644
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -1239,6 +1239,12 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
+ } else {
+ init.ops = &bcm2835_clock_clk_ops;
+ init.flags |= CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
++
++ /* If the clock wasn't actually enabled at boot, it's not
++ * critical.
++ */
++ if (!(cprman_read(cprman, data->ctl_reg) & CM_ENABLE))
++ init.flags &= ~CLK_IS_CRITICAL;
+ }
+
+ clock = devm_kzalloc(cprman->dev, sizeof(*clock), GFP_KERNEL);
+@@ -1708,13 +1714,15 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
+ .div_reg = CM_GP1DIV,
+ .int_bits = 12,
+ .frac_bits = 12,
++ .flags = CLK_IS_CRITICAL,
+ .is_mash_clock = true),
+ [BCM2835_CLOCK_GP2] = REGISTER_PER_CLK(
+ .name = "gp2",
+ .ctl_reg = CM_GP2CTL,
+ .div_reg = CM_GP2DIV,
+ .int_bits = 12,
+- .frac_bits = 12),
++ .frac_bits = 12,
++ .flags = CLK_IS_CRITICAL),
+
+ /* HDMI state machine */
+ [BCM2835_CLOCK_HSM] = REGISTER_PER_CLK(
+--
+cgit v0.12
+
+From 9e400c5cc5c105e35216ac59a346f20cdd7613be Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 1 Jun 2016 12:05:35 -0700
+Subject: clk: bcm2835: Mark the CM SDRAM clock's parent as critical
+
+While the SDRAM is being driven by its dedicated PLL most of the time,
+there is a little loop running in the firmware that periodically turns
+on the CM SDRAM clock (using its pre-initialized parent) and switches
+SDRAM to using the CM clock to do PVT recalibration.
+
+This avoids system hangs if we choose SDRAM's parent for some other
+clock, then disable that clock.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Acked-by: Martin Sperl <kernel@martin.sperl.org>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 25 +++++++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+
+diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
+index 400615b..c6420b3 100644
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -36,6 +36,7 @@
+
+ #include <linux/clk-provider.h>
+ #include <linux/clkdev.h>
++#include <linux/clk.h>
+ #include <linux/clk/bcm2835.h>
+ #include <linux/debugfs.h>
+ #include <linux/module.h>
+@@ -1801,6 +1802,25 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
+ .ctl_reg = CM_PERIICTL),
+ };
+
++/*
++ * Permanently take a reference on the parent of the SDRAM clock.
++ *
++ * While the SDRAM is being driven by its dedicated PLL most of the
++ * time, there is a little loop running in the firmware that
++ * periodically switches the SDRAM to using our CM clock to do PVT
++ * recalibration, with the assumption that the previously configured
++ * SDRAM parent is still enabled and running.
++ */
++static int bcm2835_mark_sdc_parent_critical(struct clk *sdc)
++{
++ struct clk *parent = clk_get_parent(sdc);
++
++ if (IS_ERR(parent))
++ return PTR_ERR(parent);
++
++ return clk_prepare_enable(parent);
++}
++
+ static int bcm2835_clk_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+@@ -1810,6 +1830,7 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
+ const struct bcm2835_clk_desc *desc;
+ const size_t asize = ARRAY_SIZE(clk_desc_array);
+ size_t i;
++ int ret;
+
+ cprman = devm_kzalloc(dev,
+ sizeof(*cprman) + asize * sizeof(*clks),
+@@ -1840,6 +1861,10 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
+ clks[i] = desc->clk_register(cprman, desc->data);
+ }
+
++ ret = bcm2835_mark_sdc_parent_critical(clks[BCM2835_CLOCK_SDRAM]);
++ if (ret)
++ return ret;
++
+ return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
+ &cprman->onecell);
+ }
+--
+cgit v0.12
+
+From 30772942cc1095c3129eecfa182e2c568e566b9d Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Thu, 13 Oct 2016 11:54:31 +0300
+Subject: [PATCH] drm/vc4: Fix a couple error codes in vc4_cl_lookup_bos()
+
+If the allocation fails the current code returns success. If
+copy_from_user() fails it returns the number of bytes remaining instead
+of -EFAULT.
+
+Fixes: d5b1a78a772f ("drm/vc4: Add support for drawing 3D frames.")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/vc4/vc4_gem.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c
+index ae1609e..4050540 100644
+--- a/drivers/gpu/drm/vc4/vc4_gem.c
++++ b/drivers/gpu/drm/vc4/vc4_gem.c
+@@ -548,14 +548,15 @@ vc4_cl_lookup_bos(struct drm_device *dev,
+
+ handles = drm_malloc_ab(exec->bo_count, sizeof(uint32_t));
+ if (!handles) {
++ ret = -ENOMEM;
+ DRM_ERROR("Failed to allocate incoming GEM handles\n");
+ goto fail;
+ }
+
+- ret = copy_from_user(handles,
+- (void __user *)(uintptr_t)args->bo_handles,
+- exec->bo_count * sizeof(uint32_t));
+- if (ret) {
++ if (copy_from_user(handles,
++ (void __user *)(uintptr_t)args->bo_handles,
++ exec->bo_count * sizeof(uint32_t))) {
++ ret = -EFAULT;
+ DRM_ERROR("Failed to copy in GEM handles\n");
+ goto fail;
+ }
+--
+2.9.3
+
diff --git a/config-arm-generic b/config-arm-generic
index f8d6052d6..7a88c2d02 100644
--- a/config-arm-generic
+++ b/config-arm-generic
@@ -19,8 +19,14 @@ CONFIG_CC_STACKPROTECTOR=y
# CONFIG_CPU_BIG_ENDIAN is not set
# CONFIG_BIG_LITTLE is not set
+# CONFIG_ARM_BIG_LITTLE_CPUIDLE is not set
# CONFIG_IWMMXT is not set
+# https://fedoraproject.org/wiki/Features/Checkpoint_Restore
+CONFIG_CHECKPOINT_RESTORE=y
+
+CONFIG_ARM_CPUIDLE=y
+
CONFIG_RESET_CONTROLLER=y
CONFIG_RESET_GPIO=y
@@ -31,7 +37,6 @@ CONFIG_INPUT_PWM_BEEPER=m
CONFIG_ARM_SP805_WATCHDOG=m
CONFIG_ARM_ARCH_TIMER=y
CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
-CONFIG_NR_CPUS=8
CONFIG_SWIOTLB=y
CONFIG_DMA_VIRTUAL_CHANNELS=y
@@ -70,6 +75,7 @@ CONFIG_GPIO_PL061=y
CONFIG_USB_ISP1760=m
CONFIG_ARM_PL172_MPMC=m
CONFIG_DRM_HDLCD=m
+CONFIG_DRM_MALI_DISPLAY=m
# CONFIG_DRM_HDLCD_SHOW_UNDERRUN is not set
# HW crypto and rng
@@ -112,6 +118,51 @@ CONFIG_CLKSRC_VERSATILE=y
CONFIG_POWER_RESET_VERSATILE=y
# CONFIG_ARM_CHARLCD is not set
+# Broadcom
+CONFIG_ARCH_BCM=y
+CONFIG_ARCH_BCM2835=y
+# CONFIG_ARCH_BCM_CYGNUS is not set
+# CONFIG_ARCH_BCM_NSP is not set
+# CONFIG_ARCH_BCM_5301X is not set
+# CONFIG_ARCH_BCM_281XX is not set
+# CONFIG_ARCH_BCM_21664 is not set
+# CONFIG_ARCH_BCM_63XX is not set
+# CONFIG_ARCH_BRCMSTB is not set
+# CONFIG_ARCH_BERLIN is not set
+# CONFIG_ARCH_BCM_CYGNUS is not set
+# CONFIG_ARCH_BCM_NSP is not set
+# CONFIG_ARCH_BCM_5301X is not set
+# CONFIG_ARCH_BCM_281XX is not set
+# CONFIG_ARCH_BCM_21664 is not set
+# CONFIG_ARCH_BCM_63XX is not set
+# CONFIG_ARCH_BCM_23550 is not set
+# CONFIG_ARCH_BRCMSTB is not set
+# CONFIG_ARCH_BERLIN is not set
+# BCM 283x
+CONFIG_SERIAL_8250_BCM2835AUX=y
+CONFIG_DMA_BCM2835=m
+CONFIG_MMC_SDHCI_IPROC=m
+CONFIG_MMC_BCM2835_SDHOST=m
+CONFIG_BCM2835_MBOX=y
+CONFIG_PWM_BCM2835=m
+CONFIG_HW_RANDOM_BCM2835=m
+CONFIG_I2C_BCM2835=m
+CONFIG_SPI_BCM2835=m
+CONFIG_SPI_BCM2835AUX=m
+CONFIG_BCM2835_WDT=m
+CONFIG_SND_BCM2835_SOC_I2S=m
+CONFIG_DRM_VC4=m
+CONFIG_RASPBERRYPI_FIRMWARE=y
+CONFIG_RASPBERRYPI_POWER=y
+# popular digital audio HATs
+CONFIG_SND_SOC_PCM512x=m
+CONFIG_SND_SOC_PCM512x_I2C=m
+CONFIG_SND_SOC_PCM512x_SPI=m
+CONFIG_SND_SOC_TPA6130A2=m
+CONFIG_SND_SOC_WM8804=m
+CONFIG_SND_SOC_WM8804_I2C=m
+CONFIG_SND_SOC_WM8804_SPI=m
+
# Marvell EBU
CONFIG_ARCH_MVEBU=y
CONFIG_SERIAL_MVEBU_UART=y
@@ -146,6 +197,7 @@ CONFIG_PHY_MVEBU_SATA=y
CONFIG_AHCI_MVEBU=m
# CONFIG_CACHE_FEROCEON_L2 is not set
# CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH is not set
+# CONFIG_PCI_AARDVARK is not set
# Rockchips
CONFIG_ARCH_ROCKCHIP=y
@@ -154,7 +206,7 @@ CONFIG_SPI_ROCKCHIP=m
CONFIG_PWM_ROCKCHIP=m
CONFIG_ROCKCHIP_SARADC=m
CONFIG_ROCKCHIP_IODOMAIN=m
-CONFIG_MMC_DW_ROCKCHIP=m
+CONFIG_MMC_DW_ROCKCHIP=y
CONFIG_EMAC_ROCKCHIP=m
CONFIG_MFD_RK808=m
CONFIG_COMMON_CLK_RK808=m
@@ -197,6 +249,7 @@ CONFIG_PCI_TEGRA=y
CONFIG_AHCI_TEGRA=m
CONFIG_MMC_SDHCI_TEGRA=m
CONFIG_TEGRA_WATCHDOG=m
+CONFIG_GPIO_TEGRA=y
CONFIG_I2C_TEGRA=m
CONFIG_SPI_TEGRA114=m
CONFIG_PWM_TEGRA=m
@@ -253,7 +306,6 @@ CONFIG_CLOCK_THERMAL=y
CONFIG_CPUFREQ_DT=m
CONFIG_CPUFREQ_DT_PLATDEV=y
CONFIG_DEVFREQ_THERMAL=y
-# CONFIG_ARM_CPUIDLE is not set
# CONFIG_ARM_DT_BL_CPUFREQ is not set
# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set
CONFIG_SPMI=m
@@ -278,7 +330,6 @@ CONFIG_OF_OVERLAY=y
CONFIG_OF_PCI_IRQ=m
CONFIG_OF_PCI=m
CONFIG_PCI_HOST_GENERIC=y
-# CONFIG_PCIE_IPROC is not set
CONFIG_OF_RESERVED_MEM=y
CONFIG_OF_RESOLVE=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
@@ -295,6 +346,7 @@ CONFIG_MAILBOX=y
CONFIG_ARM_MHU=m
# CONFIG_PL320_MBOX is not set
CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_POWER_DOMAIN=m
# NVMem
CONFIG_NVMEM=m
@@ -393,9 +445,9 @@ CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0=m
# Designware (used by numerous devices)
CONFIG_MMC_DW=m
-CONFIG_MMC_DW_PLTFM=m
-CONFIG_MMC_DW_K3=m
-CONFIG_MMC_DW_PCI=m
+CONFIG_MMC_DW_PLTFM=y
+CONFIG_MMC_DW_K3=y
+CONFIG_MMC_DW_PCI=y
CONFIG_SPI_DW_MMIO=m
CONFIG_SPI_DW_PCI=m
# CONFIG_SPI_DW_MID_DMA is not set
@@ -489,6 +541,12 @@ CONFIG_SPI_PL022=m
CONFIG_SENSORS_IIO_HWMON=m
CONFIG_IIO_SYSFS_TRIGGER=m
CONFIG_SENSORS_ARM_SCPI=m
+CONFIG_IIO_ST_PRESS=m
+CONFIG_IIO_ST_PRESS_I2C=m
+CONFIG_IIO_ST_PRESS_SPI=m
+CONFIG_TMP006=m
+CONFIG_BMP280=m
+CONFIG_TCS3472=m
# PHY framework
CONFIG_GENERIC_PHY=y
@@ -504,7 +562,7 @@ CONFIG_CMA=y
CONFIG_DMA_CMA=y
# CONFIG_CMA_DEBUG is not set
CONFIG_CMA_DEBUGFS=y
-CONFIG_CMA_SIZE_MBYTES=16
+CONFIG_CMA_SIZE_MBYTES=64
CONFIG_CMA_SIZE_SEL_MBYTES=y
# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set
# CONFIG_CMA_SIZE_SEL_MIN is not set
@@ -629,23 +687,19 @@ CONFIG_NET_VENDOR_MELLANOX=y
# drm
# CONFIG_DRM_VMWGFX is not set
# CONFIG_IMX_IPUV3_CORE is not set
+# CONFIG_FB_DA8XX is not set
-# CONFIG_DEBUG_SET_MODULE_RONX is not set
# CONFIG_CORESIGHT is not set
# CONFIG_LATTICE_ECP3_CONFIG is not set
-# CONFIG_BMP085_SPI is not set
# CONFIG_TI_DAC7512 is not set
-# https://fedoraproject.org/wiki/Features/Checkpoint_Restore
-CONFIG_CHECKPOINT_RESTORE=y
-
# Bad Intel shit we don't care about
# CONFIG_PINCTRL_BAYTRAIL is not set
# CONFIG_PINCTRL_CHERRYVIEW is not set
# CONFIG_PINCTRL_BROXTON is not set
# CONFIG_PINCTRL_SUNRISEPOINT is not set
+# CONFIG_XILINX_ZYNQMP_DMA is not set
-# CONFIG_HW_RANDOM_HISI is not set
# CONFIG_HISILICON_IRQ_MBIGEN is not set
# CONFIG_QRTR is not set
diff --git a/config-arm64 b/config-arm64
index a9a02f81f..0bc9b30bd 100644
--- a/config-arm64
+++ b/config-arm64
@@ -8,6 +8,7 @@ CONFIG_ARCH_SEATTLE=y
CONFIG_ARCH_SUNXI=y
CONFIG_ARCH_TEGRA=y
CONFIG_ARCH_XGENE=y
+CONFIG_ARCH_THUNDER=y
# CONFIG_ARCH_ALPINE is not set
# CONFIG_ARCH_BCM_IPROC is not set
# CONFIG_ARCH_BERLIN is not set
@@ -18,7 +19,6 @@ CONFIG_ARCH_XGENE=y
# CONFIG_ARCH_RENESAS is not set
# CONFIG_ARCH_SPRD is not set
# CONFIG_ARCH_STRATIX10 is not set
-# CONFIG_ARCH_THUNDER is not set
# CONFIG_ARCH_VULCAN is not set
# CONFIG_ARCH_ZYNQMP is not set
# CONFIG_ARCH_UNIPHIER is not set
@@ -33,6 +33,7 @@ CONFIG_ARM64_ERRATUM_832075=y
CONFIG_ARM64_ERRATUM_843419=y
CONFIG_ARM64_ERRATUM_834220=y
CONFIG_CAVIUM_ERRATUM_22375=y
+CONFIG_CAVIUM_ERRATUM_23144=y
CONFIG_CAVIUM_ERRATUM_23154=y
CONFIG_CAVIUM_ERRATUM_27456=y
@@ -41,6 +42,7 @@ CONFIG_CAVIUM_ERRATUM_27456=y
# CONFIG_SERIAL_AMBA_PL010 is not set
# CONFIG_AMBA_PL08X is not set
CONFIG_ARM_SMMU_V3=y
+CONFIG_NR_CPUS=256
CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
CONFIG_ARCH_REQUIRE_GPIOLIB=y
@@ -99,11 +101,23 @@ CONFIG_ACPI_CUSTOM_METHOD=m
CONFIG_ACPI_NFIT=m
# CONFIG_ACPI_NFIT_DEBUG is not set
CONFIG_PCC=y
-CONFIG_ACPI_CPPC_CPUFREQ=y
+# CONFIG_ACPI_CPPC_CPUFREQ is not set
CONFIG_ACPI_PROCESSOR=y
CONFIG_ACPI_THERMAL=y
CONFIG_I2C_SCMI=m
CONFIG_SENSORS_ACPI_POWER=m
+CONFIG_ACPI_TABLE_UPGRADE=y
+CONFIG_ACPI_CONFIGFS=m
+
+CONFIG_NUMA=y
+CONFIG_ACPI_NUMA=y
+CONFIG_NUMA_BALANCING=y
+CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y
+CONFIG_NODES_SHIFT=9
+
+CONFIG_DMI=y
+CONFIG_DMIID=y
+CONFIG_DMI_SYSFS=y
CONFIG_ARM64_CRYPTO=y
CONFIG_CRYPTO_SHA1_ARM64_CE=y
@@ -134,6 +148,7 @@ CONFIG_PCI_XGENE=y
CONFIG_PCI_XGENE_MSI=y
CONFIG_I2C_XGENE_SLIMPRO=m
CONFIG_XGENE_SLIMPRO_MBOX=m
+CONFIG_MDIO_XGENE=m
# AMD Seattle
CONFIG_NET_SB1000=y
@@ -148,6 +163,7 @@ CONFIG_COMMON_CLK_HI6220=y
CONFIG_PCI_HISI=y
CONFIG_POWER_RESET_HISI=y
CONFIG_HISI_THERMAL=m
+CONFIG_HW_RANDOM_HISI=m
CONFIG_STUB_CLK_HI6220=y
CONFIG_REGULATOR_HI655X=m
CONFIG_PHY_HI6220_USB=m
@@ -157,14 +173,18 @@ CONFIG_RESET_HISI=y
CONFIG_MFD_HI655X_PMIC=m
CONFIG_DRM_HISI_KIRIN=m
CONFIG_HISI_KIRIN_DW_DSI=m
+CONFIG_MDIO_HISI_FEMAC=m
+CONFIG_INPUT_HISI_POWERKEY=m
# Tegra
CONFIG_ARCH_TEGRA_132_SOC=y
CONFIG_ARCH_TEGRA_210_SOC=y
CONFIG_TEGRA210_ADMA=y
CONFIG_MFD_MAX77620=y
+CONFIG_PINCTRL_MAX77620=m
CONFIG_REGULATOR_MAX77620=m
-# CONFIG_GPIO_TEGRA is not set
+CONFIG_GPIO_MAX77620=m
+CONFIG_TEGRA_ACONNECT=y
# AllWinner
CONFIG_MACH_SUN50I=y
@@ -172,6 +192,7 @@ CONFIG_SUNXI_RSB=m
CONFIG_AHCI_SUNXI=m
CONFIG_NET_VENDOR_ALLWINNER=y
# CONFIG_SUN4I_EMAC is not set
+CONFIG_SUN8I_EMAC=m
# CONFIG_MDIO_SUN4I is not set
# CONFIG_KEYBOARD_SUN4I_LRADC is not set
# CONFIG_TOUCHSCREEN_SUN4I is not set
@@ -185,6 +206,8 @@ CONFIG_PWM_SUN4I=m
# CONFIG_PHY_SUN4I_USB is not set
# CONFIG_PHY_SUN9I_USB is not set
CONFIG_NVMEM_SUNXI_SID=m
+CONFIG_SUNXI_CCU=y
+# CONFIG_SUN8I_H3_CCU is not set
# qcom
# MSM8996 = SD-820, MSM8916 = SD-410
@@ -239,22 +262,28 @@ CONFIG_QCOM_COINCELL=m
# CONFIG_PINCTRL_APQ8084 is not set
# CONFIG_PINCTRL_MSM8660 is not set
# CONFIG_PINCTRL_MSM8960 is not set
+# CONFIG_PINCTRL_MDM9615 is not set
# CONFIG_PINCTRL_MSM8X74 is not set
# CONFIG_PINCTRL_QDF2XXX is not set
# CONFIG_INPUT_PM8941_PWRKEY is not set
# CONFIG_INPUT_REGULATOR_HAPTIC is not set
# CONFIG_CHARGER_MANAGER is not set
# CONFIG_SENSORS_LTC2978_REGULATOR is not set
+# CONFIG_QCOM_Q6V5_PIL is not set
+
+# mvebu
+# CONFIG_MV_XOR_V2 is not set
# ThunderX
# CONFIG_MDIO_OCTEON is not set
-# CONFIG_MDIO_THUNDER is not set
-# CONFIG_PCI_HOST_THUNDER_PEM is not set
-# CONFIG_PCI_HOST_THUNDER_ECAM is not set
-
-CONFIG_DMI=y
-CONFIG_DMIID=y
-CONFIG_DMI_SYSFS=y
+CONFIG_MDIO_THUNDER=m
+CONFIG_PCI_HOST_THUNDER_PEM=y
+CONFIG_PCI_HOST_THUNDER_ECAM=y
+CONFIG_NET_VENDOR_CAVIUM=y
+CONFIG_THUNDER_NIC_PF=m
+CONFIG_THUNDER_NIC_VF=m
+CONFIG_THUNDER_NIC_BGX=m
+# CONFIG_LIQUIDIO is not set
CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_SATA_AHCI_SEATTLE=m
@@ -286,7 +315,4 @@ CONFIG_DEBUG_SECTION_MISMATCH=y
# CONFIG_FUJITSU_ES is not set
# CONFIG_IMX_THERMAL is not set
# CONFIG_PNP_DEBUG_MESSAGES is not set
-
-# Will probably need to be changed later
-# CONFIG_NUMA is not set
-
+# CONFIG_BCM_PDC_MBOX is not set
diff --git a/config-armv7 b/config-armv7
index 44685c2fd..0207f9ab9 100644
--- a/config-armv7
+++ b/config-armv7
@@ -9,6 +9,7 @@ CONFIG_ARCH_OMAP4=y
CONFIG_ARCH_QCOM=y
CONFIG_ARCH_TEGRA=y
CONFIG_ARCH_ZYNQ=y
+# CONFIG_ARCH_MDM9615 is not set
# These are supported in the LPAE kernel
# CONFIG_ARM_LPAE is not set
@@ -142,9 +143,11 @@ CONFIG_PWM_TIEHRPWM=m
CONFIG_PWM_TWL=m
CONFIG_PWM_TWL_LED=m
CONFIG_PWM_OMAP_DMTIMER=m
+# CONFIG_PWM_STMPE is not set
CONFIG_CRYPTO_DEV_OMAP_SHAM=m
-CONFIG_CRYPTO_DEV_OMAP_AES=m
+# Disable for the moment, terribly broken upstream
+# CONFIG_CRYPTO_DEV_OMAP_AES is not set
CONFIG_CRYPTO_DEV_OMAP_DES=m
CONFIG_HW_RANDOM_OMAP=m
CONFIG_HW_RANDOM_OMAP3_ROM=m
@@ -152,8 +155,20 @@ CONFIG_HW_RANDOM_OMAP3_ROM=m
CONFIG_DRM_OMAP=m
CONFIG_DRM_OMAP_NUM_CRTCS=2
CONFIG_OMAP2_VRFB=y
-# CONFIG_FB_OMAP2 is not set
-# CONFIG_FB_DA8XX is not set
+CONFIG_DRM_OMAP_ENCODER_OPA362=m
+CONFIG_DRM_OMAP_ENCODER_TFP410=m
+CONFIG_DRM_OMAP_ENCODER_TPD12S015=m
+CONFIG_DRM_OMAP_CONNECTOR_DVI=m
+CONFIG_DRM_OMAP_CONNECTOR_HDMI=m
+CONFIG_DRM_OMAP_CONNECTOR_ANALOG_TV=m
+CONFIG_DRM_OMAP_PANEL_DPI=m
+CONFIG_DRM_OMAP_PANEL_DSI_CM=m
+CONFIG_DRM_OMAP_PANEL_SONY_ACX565AKM=m
+CONFIG_DRM_OMAP_PANEL_LGPHILIPS_LB035Q02=m
+CONFIG_DRM_OMAP_PANEL_SHARP_LS037V7DW01=m
+CONFIG_DRM_OMAP_PANEL_TPO_TD028TTEC1=m
+CONFIG_DRM_OMAP_PANEL_TPO_TD043MTEA1=m
+CONFIG_DRM_OMAP_PANEL_NEC_NL8048HL11=m
CONFIG_OMAP2_DSS=m
# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set
@@ -166,21 +181,6 @@ CONFIG_OMAP2_DSS_DSI=y
CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y
-CONFIG_DISPLAY_ENCODER_OPA362=m
-CONFIG_DISPLAY_ENCODER_TFP410=m
-CONFIG_DISPLAY_ENCODER_TPD12S015=m
-CONFIG_DISPLAY_CONNECTOR_DVI=m
-CONFIG_DISPLAY_CONNECTOR_HDMI=m
-CONFIG_DISPLAY_CONNECTOR_ANALOG_TV=m
-CONFIG_DISPLAY_PANEL_DPI=m
-CONFIG_DISPLAY_PANEL_DSI_CM=m
-CONFIG_DISPLAY_PANEL_SONY_ACX565AKM=m
-CONFIG_DISPLAY_PANEL_LGPHILIPS_LB035Q02=m
-CONFIG_DISPLAY_PANEL_SHARP_LS037V7DW01=m
-CONFIG_DISPLAY_PANEL_TPO_TD043MTEA1=m
-CONFIG_DISPLAY_PANEL_NEC_NL8048HL11=m
-CONFIG_DISPLAY_PANEL_TPO_TD028TTEC1=m
-
# Enable V4L2 drivers for OMAP2+
CONFIG_V4L_PLATFORM_DRIVERS=y
# CONFIG_VIDEO_OMAP2_VOUT is not set
@@ -207,12 +207,12 @@ CONFIG_SND_SOC_TLV320AIC23_I2C=m
CONFIG_SND_SOC_TLV320AIC23_SPI=m
CONFIG_SND_SOC_TLV320AIC3X=m
CONFIG_SND_SOC_TLV320AIC31XX=m
-CONFIG_SND_SOC_TPA6130A2=m
CONFIG_SND_SOC_TWL4030=m
CONFIG_SND_SOC_TWL6040=m
CONFIG_RADIO_WL128X=m
CONFIG_OMAP_REMOTEPROC=m
+CONFIG_TI_SYSCON_RESET=m
# CONFIG_OMAP2_DSS_DEBUGFS is not set
# CONFIG_OMAP_IOMMU_DEBUG is not set
@@ -349,6 +349,8 @@ CONFIG_QCOM_SMSM=y
CONFIG_QCOM_SMP2P=m
CONFIG_PCIE_QCOM=y
CONFIG_MTD_NAND_QCOM=m
+# CONFIG_QCOM_Q6V5_PIL is not set
+# CONFIG_MSM_IOMMU is not set
# i.MX
# CONFIG_MXC_DEBUG_BOARD is not set
@@ -412,6 +414,7 @@ CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_TIME_THLD=8192
CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API=m
CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API=m
CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API=m
+CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API=m
# CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG is not set
# CONFIG_CRYPTO_DEV_MXS_DCP is not set
# CONFIG_CRYPTO_DEV_MXC_SCC is not set
@@ -574,7 +577,7 @@ CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
CONFIG_COMMON_CLK_AXI_CLKGEN=m
CONFIG_COMMON_CLK_SI570=m
CONFIG_COMMON_CLK_XLNX_CLKWZRD=m
-# CONFIG_ARM_ZYNQ_CPUIDLE is not set
+CONFIG_ARM_ZYNQ_CPUIDLE=y
CONFIG_LATTICE_ECP3_CONFIG=m
CONFIG_NET_VENDOR_XILINX=y
CONFIG_XILINX_EMACLITE=m
diff --git a/config-armv7-generic b/config-armv7-generic
index ef8337abc..f36ed38b0 100644
--- a/config-armv7-generic
+++ b/config-armv7-generic
@@ -35,6 +35,7 @@ CONFIG_IRQ_CROSSBAR=y
CONFIG_IOMMU_IO_PGTABLE_LPAE=y
CONFIG_CPU_SW_DOMAIN_PAN=y
CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_NR_CPUS=32
# CONFIG_MCPM is not set
# CONFIG_OABI_COMPAT is not set
@@ -52,8 +53,6 @@ CONFIG_ARM_CPU_SUSPEND=y
# CONFIG_DEBUG_ALIGN_RODATA is not set
# Platforms enabled/disabled globally on ARMv7
-CONFIG_ARCH_BCM=y
-CONFIG_ARCH_BCM2835=y
CONFIG_ARCH_EXYNOS=y
CONFIG_ARCH_HIGHBANK=y
CONFIG_ARCH_SUNXI=y
@@ -61,22 +60,6 @@ CONFIG_ARCH_TEGRA=y
CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA=y
CONFIG_ARCH_VIRT=y
# CONFIG_ARCH_ARTPEC is not set
-# CONFIG_ARCH_BCM_CYGNUS is not set
-# CONFIG_ARCH_BCM_NSP is not set
-# CONFIG_ARCH_BCM_5301X is not set
-# CONFIG_ARCH_BCM_281XX is not set
-# CONFIG_ARCH_BCM_21664 is not set
-# CONFIG_ARCH_BCM_63XX is not set
-# CONFIG_ARCH_BRCMSTB is not set
-# CONFIG_ARCH_BERLIN is not set
-# CONFIG_ARCH_BCM_CYGNUS is not set
-# CONFIG_ARCH_BCM_NSP is not set
-# CONFIG_ARCH_BCM_5301X is not set
-# CONFIG_ARCH_BCM_281XX is not set
-# CONFIG_ARCH_BCM_21664 is not set
-# CONFIG_ARCH_BCM_63XX is not set
-# CONFIG_ARCH_BRCMSTB is not set
-# CONFIG_ARCH_BERLIN is not set
# CONFIG_ARCH_HI3xxx is not set
# CONFIG_ARCH_HISI is not set
# CONFIG_ARCH_MEDIATEK is not set
@@ -128,9 +111,14 @@ CONFIG_ARM_ERRATA_775420=y
CONFIG_PL310_ERRATA_753970=y
CONFIG_PL310_ERRATA_769419=y
CONFIG_PJ4B_ERRATA_4742=y
-# Cortex-A15
-# CONFIG_ARM_ERRATA_798181 is not set
-# CONFIG_ARM_ERRATA_773022 is not set
+# Cortex-A12/15/17
+CONFIG_ARM_ERRATA_798181=y
+CONFIG_ARM_ERRATA_773022=y
+CONFIG_ARM_ERRATA_818325_852422=y
+CONFIG_ARM_ERRATA_821420=y
+CONFIG_ARM_ERRATA_825619=y
+CONFIG_ARM_ERRATA_852421=y
+CONFIG_ARM_ERRATA_852423=y
# generic that deviates from or should be merged into config-generic
CONFIG_SMP_ON_UP=y
@@ -158,6 +146,17 @@ CONFIG_LSM_MMAP_MIN_ADDR=32768
CONFIG_LBDAF=y
+# Little.BIG
+CONFIG_BIG_LITTLE=y
+CONFIG_BL_SWITCHER=y
+CONFIG_ARM_BIG_LITTLE_CPUFREQ=m
+CONFIG_ARM_SCPI_CPUFREQ=m
+CONFIG_ARCH_VEXPRESS_DCSCB=y
+CONFIG_ARCH_VEXPRESS_TC2_PM=y
+CONFIG_ARM_VEXPRESS_SPC_CPUFREQ=m
+CONFIG_ARM_BIG_LITTLE_CPUIDLE=y
+# CONFIG_BL_SWITCHER_DUMMY_IF is not set
+
# GRR, needed for MFD_AS3722
CONFIG_I2C=y
@@ -190,8 +189,9 @@ CONFIG_VFIO_PLATFORM_CALXEDAXGMAC_RESET=m
CONFIG_MACH_SUN6I=y
CONFIG_MACH_SUN7I=y
CONFIG_MACH_SUN8I=y
-# CONFIG_MACH_SUN9I is not set
-# CONFIG_MACH_SUN50I is not set
+CONFIG_MACH_SUN9I=y
+CONFIG_SUNXI_CCU=y
+CONFIG_SUN8I_H3_CCU=y
CONFIG_SUNXI_SRAM=y
CONFIG_DMA_SUN4I=m
CONFIG_DMA_SUN6I=m
@@ -200,7 +200,7 @@ CONFIG_SUNXI_WATCHDOG=m
CONFIG_NET_VENDOR_ALLWINNER=y
CONFIG_RTC_DRV_SUNXI=m
CONFIG_PHY_SUN4I_USB=m
-# CONFIG_PHY_SUN9I_USB is not set
+CONFIG_PHY_SUN9I_USB=m
CONFIG_AHCI_SUNXI=m
CONFIG_SPI_SUN4I=m
CONFIG_SPI_SUN6I=m
@@ -223,6 +223,7 @@ CONFIG_IR_SUNXI=m
CONFIG_MDIO_SUN4I=m
CONFIG_DWMAC_SUNXI=m
CONFIG_SUN4I_EMAC=m
+CONFIG_SUN8I_EMAC=m
CONFIG_RTC_DRV_SUN6I=m
CONFIG_MTD_NAND_SUNXI=m
CONFIG_SERIO_SUN4I_PS2=m
@@ -233,28 +234,10 @@ CONFIG_USB_MUSB_SUNXI=m
CONFIG_CRYPTO_DEV_SUN4I_SS=m
CONFIG_SND_SUN4I_CODEC=m
CONFIG_SND_SUN4I_SPDIF=m
+CONFIG_SND_SUN4I_I2S=m
CONFIG_SUNXI_RSB=m
CONFIG_NVMEM_SUNXI_SID=m
-# BCM 283x
-CONFIG_SERIAL_AMBA_PL011=y
-CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-CONFIG_SERIAL_8250_BCM2835AUX=y
-CONFIG_DMA_BCM2835=m
-# CONFIG_MMC_SDHCI_BCM2835 is not set
-CONFIG_MMC_SDHCI_IPROC=m
-CONFIG_BCM2835_MBOX=y
-CONFIG_PWM_BCM2835=m
-CONFIG_HW_RANDOM_BCM2835=m
-CONFIG_I2C_BCM2835=m
-CONFIG_SPI_BCM2835=m
-CONFIG_SPI_BCM2835AUX=m
-CONFIG_BCM2835_WDT=m
-CONFIG_SND_BCM2835_SOC_I2S=m
-CONFIG_DRM_VC4=m
-CONFIG_RASPBERRYPI_FIRMWARE=y
-CONFIG_RASPBERRYPI_POWER=y
-
# Exynos
CONFIG_ARCH_EXYNOS3=y
# CONFIG_ARCH_EXYNOS4 is not set
@@ -269,7 +252,8 @@ CONFIG_SOC_EXYNOS5800=y
CONFIG_SERIAL_SAMSUNG=y
CONFIG_SERIAL_SAMSUNG_CONSOLE=y
CONFIG_ARM_EXYNOS5440_CPUFREQ=m
-# CONFIG_ARM_EXYNOS_CPUIDLE is not set
+CONFIG_ARM_EXYNOS_CPUIDLE=y
+CONFIG_EXYNOS5420_MCPM=y
CONFIG_ARM_EXYNOS5_BUS_DEVFREQ=m
# CONFIG_ARM_EXYNOS_BUS_DEVFREQ is not set
# CONFIG_EXYNOS5420_MCPM not set
@@ -283,7 +267,7 @@ CONFIG_EXYNOS_THERMAL=m
CONFIG_EXYNOS_ADC=m
CONFIG_MMC_SDHCI_S3C=m
CONFIG_MMC_SDHCI_S3C_DMA=y
-CONFIG_MMC_DW_EXYNOS=m
+CONFIG_MMC_DW_EXYNOS=y
# CONFIG_EXYNOS_IOMMU is not set
CONFIG_PCI_EXYNOS=y
CONFIG_PHY_EXYNOS5_USBDRD=m
@@ -347,6 +331,7 @@ CONFIG_SND_SOC_SAMSUNG_SMDK_WM8994=m
CONFIG_SND_SOC_SMDK_WM8994_PCM=m
CONFIG_SND_SOC_SNOW=m
CONFIG_SND_SOC_ODROIDX2=m
+CONFIG_EXYNOS_AUDSS_CLK_CON=m
# CONFIG_EXYNOS_IOMMU_DEBUG is not set
# CONFIG_SAMSUNG_PM_DEBUG is not set
# CONFIG_SAMSUNG_PM_CHECK is not set
@@ -379,7 +364,6 @@ CONFIG_SND_SOC_TEGRA_RT5677=m
CONFIG_AD525X_DPOT=m
CONFIG_AD525X_DPOT_I2C=m
CONFIG_AD525X_DPOT_SPI=m
-# CONFIG_GPIO_TEGRA is not set
# Jetson TK1
CONFIG_PINCTRL_AS3722=y
@@ -405,7 +389,7 @@ CONFIG_MACH_DOVE=y
CONFIG_CACHE_TAUROS2=y
CONFIG_PINCTRL_ARMADA_370=y
CONFIG_PINCTRL_ARMADA_XP=y
-# CONFIG_ARM_MVEBU_V7_CPUIDLE is not set
+CONFIG_ARM_MVEBU_V7_CPUIDLE=y
CONFIG_PINCTRL_DOVE=y
CONFIG_MMC_SDHCI_DOVE=m
CONFIG_DOVE_THERMAL=m
@@ -420,8 +404,6 @@ CONFIG_RTC_DRV_ARMADA38X=m
# CONFIG_CACHE_FEROCEON_L2 is not set
# CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH is not set
CONFIG_LEDS_NS2=m
-CONFIG_SERIAL_MVEBU_UART=y
-# CONFIG_SERIAL_MVEBU_CONSOLE is not set
# CONFIG_PCIE_ARMADA_8K is not set
# DRM panels
@@ -475,6 +457,7 @@ CONFIG_MFD_TPS65912_SPI=y
# CONFIG_PINCTRL_APQ8084 is not set
# CONFIG_PINCTRL_MSM8960 is not set
# CONFIG_PINCTRL_MSM8660 is not set
+# CONFIG_PINCTRL_MDM9615 is not set
# CONFIG_PINCTRL_MSM8996 is not set
# GPIO
@@ -528,6 +511,7 @@ CONFIG_MTD_NAND_PXA3xx=m
CONFIG_MTD_NAND_RICOH=m
CONFIG_MTD_NAND_TMIO=m
# CONFIG_MTD_NAND_BRCMNAND is not set
+# CONFIG_MTD_NAND_MTK is not set
# CONFIG_MTD_MT81xx_NOR is not set
CONFIG_MTD_SPI_NOR=m
# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
@@ -608,11 +592,6 @@ CONFIG_GENERIC_ADC_BATTERY=m
CONFIG_BATTERY_SBS=m
# Sensors
-CONFIG_TMP006=m
-CONFIG_BMP085=y
-CONFIG_BMP085_I2C=m
-CONFIG_BMP085_SPI=m
-CONFIG_BMP280=m
CONFIG_SENSORS_AD7314=m
CONFIG_SENSORS_ADCXX=m
CONFIG_SENSORS_ADS7871=m
@@ -704,6 +683,7 @@ CONFIG_I2C_CROS_EC_TUNNEL=m
CONFIG_SND_SOC_TS3A227E=m
CONFIG_CROS_EC_CHARDEV=m
CONFIG_CROS_EC_PROTO=y
+CONFIG_PWM_CROS_EC=m
# This newly introduced mess needs to be fixed upstream :-(
CONFIG_STMMAC_PLATFORM=m
@@ -721,6 +701,7 @@ CONFIG_R8188EU=m
# CONFIG_CAN_TI_HECC is not set
# CONFIG_CAN_FLEXCAN is not set
# CONFIG_CAN_RCAR is not set
+# CONFIG_CAN_RCAR_CANFD is not set
# Needs work/investigation
# CONFIG_ARM_KPROBES_TEST is not set
@@ -745,6 +726,7 @@ CONFIG_R8188EU=m
# CONFIG_DM9000 is not set
# CONFIG_MTD_AFS_PARTS is not set
# CONFIG_SPI_PXA2XX is not set
+# CONFIG_SPI_CADENCE_QUADSPI is not set
# CONFIG_DEPRECATED_PARAM_STRUCT is not set
# CONFIG_LATTICE_ECP3_CONFIG is not set
# CONFIG_SERIAL_8250_EM is not set
diff --git a/config-armv7-lpae b/config-armv7-lpae
index 178d36e8f..fb7177b85 100644
--- a/config-armv7-lpae
+++ b/config-armv7-lpae
@@ -18,24 +18,6 @@ CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
CONFIG_ARM_VIRT_EXT=y
CONFIG_ARM_DMA_IOMMU_ALIGNMENT=8
-CONFIG_CMA_SIZE_SEL_MBYTES=y
-CONFIG_CMA_SIZE_MBYTES=64
-
-# Cortex-A15
-CONFIG_ARM_ERRATA_798181=y
-CONFIG_ARM_ERRATA_773022=y
-
-# Little.BIG
-CONFIG_BIG_LITTLE=y
-CONFIG_BL_SWITCHER=y
-CONFIG_EXYNOS5420_MCPM=y
-CONFIG_ARCH_VEXPRESS_DCSCB=y
-CONFIG_ARCH_VEXPRESS_TC2_PM=y
-CONFIG_ARM_BIG_LITTLE_CPUFREQ=m
-CONFIG_ARM_SCPI_CPUFREQ=m
-CONFIG_ARM_VEXPRESS_SPC_CPUFREQ=m
-# CONFIG_BL_SWITCHER_DUMMY_IF is not set
-
CONFIG_KVM=y
CONFIG_KVM_ARM_HOST=y
CONFIG_KVM_NEW_VGIC=y
diff --git a/config-generic b/config-generic
index 82db0f623..744489577 100644
--- a/config-generic
+++ b/config-generic
@@ -9,6 +9,7 @@ CONFIG_HOTPLUG_CPU=y
CONFIG_LOCALVERSION=""
CONFIG_CROSS_COMPILE=""
CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_GCC_PLUGINS is not set
#
# Code maturity level options
@@ -33,6 +34,7 @@ CONFIG_KERNEL_GZIP=y
# CONFIG_KERNEL_LZMA is not set
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
# CONFIG_COMPILE_TEST is not set
@@ -74,6 +76,7 @@ CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
CONFIG_SLUB=y
+CONFIG_SLAB_FREELIST_RANDOM=y
CONFIG_SLUB_CPU_PARTIAL=y
# CONFIG_SLUB_STATS is not set
# CONFIG_SLUB_DEBUG_ON is not set
@@ -111,7 +114,7 @@ CONFIG_HOTPLUG_PCI=y
# CONFIG_HOTPLUG_PCI_SHPC is not set
CONFIG_HOTPLUG_PCI_PCIE=y
# CONFIG_PCIE_DW_PLAT is not set
-CONFIG_PCIE_DPC=m
+CONFIG_PCIE_DPC=y
# CONFIG_SGI_IOC4 is not set
@@ -196,6 +199,7 @@ CONFIG_INFINIBAND_OCRDMA=m
CONFIG_INFINIBAND_USNIC=m
CONFIG_INFINIBAND_RDMAVT=m
+CONFIG_RDMA_RXE=m
#
# Executable file formats
@@ -217,6 +221,7 @@ CONFIG_BINFMT_MISC=m
# CONFIG_COMMON_CLK_CDCE925 is not set
# CONFIG_COMMON_CLK_OXNAS is not set
# CONFIG_COMMON_CLK_HI3519 is not set
+# CONFIG_SUNXI_CCU is not set
#
# Generic Driver Options
@@ -228,7 +233,6 @@ CONFIG_EXTRA_FIRMWARE=""
CONFIG_FW_CFG_SYSFS=m
# CONFIG_FW_CFG_SYSFS_CMDLINE is not set
-
# Give this a try in rawhide for now
# CONFIG_FW_LOADER_USER_HELPER is not set
# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
@@ -426,11 +430,13 @@ CONFIG_VIRTIO_INPUT=m
CONFIG_VIRTIO_MMIO=m
# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set
CONFIG_VIRTIO_NET=m
+CONFIG_VIRTIO_VSOCKETS=m
CONFIG_HW_RANDOM_VIRTIO=m
CONFIG_VIRTIO_CONSOLE=m
CONFIG_VHOST_NET=m
CONFIG_VHOST_SCSI=m
# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set
+CONFIG_VHOST_VSOCK=m
#
# SCSI device support
@@ -524,6 +530,8 @@ CONFIG_SCSI_UFSHCD=m
CONFIG_SCSI_UFSHCD_PCI=m
# CONFIG_SCSI_UFSHCD_PLATFORM is not set
+# CONFIG_SCSI_UFS_DWC_TC_PCI is not set
+
CONFIG_SCSI_MVUMI=m
CONFIG_SCSI_OSD_INITIATOR=m
@@ -737,6 +745,14 @@ CONFIG_FUSION_SAS=m
CONFIG_FUSION_LOGGING=y
#
+# NVME support
+#
+CONFIG_NVME_RDMA=m
+CONFIG_NVME_TARGET=m
+CONFIG_NVME_TARGET_LOOP=m
+CONFIG_NVME_TARGET_RDMA=m
+
+#
# IEEE 1394 (FireWire) support (JUJU alternative stack)
#
CONFIG_FIREWIRE=m
@@ -778,6 +794,7 @@ CONFIG_TCP_CONG_CDG=m
CONFIG_TCP_CONG_LP=m
CONFIG_TCP_CONG_SCALABLE=m
CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_NV=m
CONFIG_TCP_CONG_VENO=m
CONFIG_TCP_CONG_WESTWOOD=m
CONFIG_TCP_CONG_YEAH=m
@@ -1250,6 +1267,7 @@ CONFIG_NET_CLS_FLOWER=m
CONFIG_NET_CLS_FLOW=m
CONFIG_NET_CLS_FW=m
CONFIG_NET_CLS_IND=y
+CONFIG_NET_CLS_MATCHALL=m
CONFIG_NET_CLS_ROUTE4=m
CONFIG_NET_CLS_ROUTE=y
CONFIG_NET_CLS_RSVP=m
@@ -1607,7 +1625,6 @@ CONFIG_NET_VENDOR_SIS=y
CONFIG_SIS900=m
CONFIG_SIS190=m
-
CONFIG_NET_VENDOR_SMSC=y
CONFIG_PCMCIA_SMC91C92=m
CONFIG_EPIC100=m
@@ -1664,6 +1681,8 @@ CONFIG_NATIONAL_PHY=m
CONFIG_ICPLUS_PHY=m
CONFIG_BCM63XX_PHY=m
CONFIG_BCM7XXX_PHY=m
+CONFIG_INTEL_XWAY_PHY=m
+# CONFIG_MDIO_HISI_FEMAC is not set
CONFIG_LSI_ET1011C_PHY=m
CONFIG_LXT_PHY=m
CONFIG_MARVELL_PHY=m
@@ -1708,7 +1727,6 @@ CONFIG_JME=m
# Ethernet (10000 Mbit)
# CONFIG_NET_VENDOR_AURORA is not set
-#
CONFIG_MLX4_CORE=m
CONFIG_MLX4_EN=m
CONFIG_MLX4_EN_DCB=y
@@ -1751,7 +1769,6 @@ CONFIG_SLIP_SMART=y
#
# Wireless LAN
#
-#
CONFIG_WLAN=y
# CONFIG_STRIP is not set
# CONFIG_PCMCIA_RAYCS is not set
@@ -2007,6 +2024,7 @@ CONFIG_MPLS_ROUTING=m
CONFIG_MPLS_IPTUNNEL=m
CONFIG_NET_SWITCHDEV=y
+CONFIG_NET_NCSI=y
CONFIG_6LOWPAN=m
CONFIG_6LOWPAN_NHC=m
@@ -2200,8 +2218,6 @@ CONFIG_BT_HIDP=m
# Bluetooth device drivers
#
CONFIG_BT_HCIBTUSB=m
-# Disable the BT_HCIUSB driver.
-# It sucks more power than BT_HCIBTUSB which has the same functionality.
CONFIG_BT_HCIBTUSB_BCM=y
CONFIG_BT_HCIBTUSB_RTL=y
CONFIG_BT_HCIUART=m
@@ -2241,20 +2257,19 @@ CONFIG_MISDN_SPEEDFAX=m
CONFIG_MISDN_INFINEON=m
CONFIG_MISDN_W6692=m
CONFIG_MISDN_NETJET=m
+CONFIG_MISDN_HFCUSB=m
+CONFIG_MISDN_HFCPCI=m
+CONFIG_MISDN_HFCMULTI=m
#
# mISDN hardware drivers
#
-CONFIG_MISDN_HFCPCI=m
-CONFIG_MISDN_HFCMULTI=m
CONFIG_ISDN_I4L=m
CONFIG_ISDN_DRV_AVMB1_B1PCI=m
CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
CONFIG_ISDN_DRV_AVMB1_T1PCI=m
CONFIG_ISDN_DRV_AVMB1_C4=m
-CONFIG_MISDN_HFCUSB=m
-
CONFIG_ISDN_PPP=y
CONFIG_ISDN_PPP_VJ=y
CONFIG_ISDN_MPP=y
@@ -2379,6 +2394,7 @@ CONFIG_TABLET_USB_AIPTEK=m
CONFIG_TABLET_USB_GTCO=m
CONFIG_TABLET_USB_HANWANG=m
CONFIG_TABLET_USB_KBTAB=m
+CONFIG_TABLET_USB_PEGASUS=m
CONFIG_TABLET_SERIAL_WACOM4=m
CONFIG_INPUT_POWERMATE=m
@@ -2387,6 +2403,7 @@ CONFIG_INPUT_CM109=m
CONFIG_INPUT_POLLDEV=m
CONFIG_INPUT_SPARSEKMAP=m
# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_ATMEL_CAPTOUCH is not set
# CONFIG_INPUT_BMA150 is not set
# CONFIG_INPUT_IMS_PCU is not set
CONFIG_INPUT_CMA3000=m
@@ -2536,7 +2553,11 @@ CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
# CONFIG_TOUCHSCREEN_WM97XX is not set
CONFIG_TOUCHSCREEN_W90X900=m
# CONFIG_TOUCHSCREEN_BU21013 is not set
+CONFIG_TOUCHSCREEN_RM_TS=m
+CONFIG_TOUCHSCREEN_SILEAD=m
+CONFIG_TOUCHSCREEN_SIS_I2C=m
CONFIG_TOUCHSCREEN_ST1232=m
+# CONFIG_TOUCHSCREEN_SURFACE3_SPI is not set
CONFIG_TOUCHSCREEN_ATMEL_MXT=m
# CONFIG_TOUCHSCREEN_MAX11801 is not set
CONFIG_TOUCHSCREEN_AUO_PIXCIR=m
@@ -2615,6 +2636,11 @@ CONFIG_TCG_ATMEL=m
# CONFIG_TCG_INFINEON is not set
# CONFIG_TCG_TIS_ST33ZP24 is not set
# CONFIG_TCG_XEN is not set
+# CONFIG_TCG_TIS_SPI is not set
+# CONFIG_TCG_VTPM_PROXY is not set
+# CONFIG_TCG_TIS_ST33ZP24_I2C is not set
+# CONFIG_TCG_TIS_ST33ZP24_SPI is not set
+
CONFIG_TELCLOCK=m
#
@@ -2786,6 +2812,7 @@ CONFIG_SENSORS_F71805F=m
CONFIG_SENSORS_F71882FG=m
CONFIG_SENSORS_F75375S=m
CONFIG_SENSORS_FSCHMD=m
+CONFIG_SENSORS_FTSTEUTATES=m
CONFIG_SENSORS_G760A=m
CONFIG_SENSORS_G762=m
CONFIG_SENSORS_GL518SM=m
@@ -2834,6 +2861,7 @@ CONFIG_SENSORS_PC87360=m
CONFIG_SENSORS_PC87427=m
CONFIG_SENSORS_PCF8591=m
CONFIG_SENSORS_SHT15=m
+CONFIG_SENSORS_SHT3x=m
CONFIG_SENSORS_SHTC1=m
CONFIG_SENSORS_SIS5595=m
CONFIG_CHARGER_SMB347=m
@@ -2871,6 +2899,7 @@ CONFIG_SENSORS_LM73=m
CONFIG_SENSORS_AMC6821=m
CONFIG_SENSORS_INA2XX=m
CONFIG_SENSORS_INA209=m
+CONFIG_SENSORS_INA3221=m
CONFIG_SENSORS_ADT7411=m
CONFIG_SENSORS_ASC7621=m
CONFIG_SENSORS_EMC1403=m
@@ -2932,8 +2961,10 @@ CONFIG_IIO_BUFFER_CB=y
CONFIG_IIO_TRIGGERED_BUFFER=m
CONFIG_IIO_TRIGGER=y
CONFIG_IIO_SW_TRIGGER=y
+CONFIG_IIO_SW_DEVICE=m
CONFIG_IIO_CONSUMERS_PER_TRIGGER=2
CONFIG_IIO_INTERRUPT_TRIGGER=m
+CONFIG_IIO_TIGHTLOOP_TRIGGER=m
CONFIG_HID_SENSOR_IIO_COMMON=m
CONFIG_HID_SENSOR_IIO_TRIGGER=m
CONFIG_IIO_CONFIGFS=m
@@ -2944,6 +2975,7 @@ CONFIG_IIO_CONFIGFS=m
# CONFIG_AD5380 is not set
# CONFIG_AD5064 is not set
# CONFIG_BMA180 is not set
+# CONFIG_BMA220 is not set
CONFIG_BMC150_ACCEL=m
# CONFIG_MAX1363 is not set
# CONFIG_MAX517 is not set
@@ -2975,9 +3007,14 @@ CONFIG_STK3310=m
# CONFIG_CC10001_ADC is not set
# CONFIG_INV_MPU6050_IIO is not set
CONFIG_IIO_ST_GYRO_3AXIS=m
+CONFIG_IIO_ST_GYRO_I2C_3AXIS=m
+CONFIG_IIO_ST_GYRO_SPI_3AXIS=m
CONFIG_IIO_ST_MAGN_3AXIS=m
# CONFIG_BMC150_MAGN is not set
+CONFIG_MMA7660=m
CONFIG_IIO_ST_ACCEL_3AXIS=m
+CONFIG_IIO_ST_ACCEL_I2C_3AXIS=m
+CONFIG_IIO_ST_ACCEL_SPI_3AXIS=m
CONFIG_HID_SENSOR_INCLINOMETER_3D=m
CONFIG_HID_SENSOR_DEVICE_ROTATION=m
CONFIG_ACPI_ALS=m
@@ -3088,6 +3125,7 @@ CONFIG_PA12203001=m
# CONFIG_BMC150_MAGN_I2C is not set
# CONFIG_BMC150_MAGN_SPI is not set
# CONFIG_DS1803 is not set
+# CONFIG_MAX5487 is not set
# CONFIG_MCP4131 is not set
# CONFIG_HP03 is not set
# CONFIG_HP206C is not set
@@ -3268,6 +3306,7 @@ CONFIG_RTC_DRV_M41T80=m
CONFIG_RTC_DRV_M41T80_WDT=y
CONFIG_RTC_DRV_M48T59=m
CONFIG_RTC_DRV_MAX6900=m
+CONFIG_RTC_DRV_MAX6916=m
# CONFIG_RTC_DRV_M48T86 is not set
CONFIG_RTC_DRV_PCF2127=m
CONFIG_RTC_DRV_PCF8563=m
@@ -3371,6 +3410,7 @@ CONFIG_DRM_MGAG200=m # do not enable on f17 or older
CONFIG_DRM_I915=m
# CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT is not set
CONFIG_DRM_I915_USERPTR=y
+CONFIG_DRM_I915_GVT=y
CONFIG_DRM_VIA=m
CONFIG_DRM_NOUVEAU=m
CONFIG_NOUVEAU_DEBUG=5
@@ -3392,6 +3432,11 @@ CONFIG_DRM_VIRTIO_GPU=m
# CONFIG_DRM_PANEL_SIMPLE is not set
# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set
CONFIG_DRM_VGEM=m
+# CONFIG_DRM_MALI_DISPLAY is not set
+# CONFIG_DRM_SII902X is not set
+# CONFIG_DRM_TOSHIBA_TC358767 is not set
+# CONFIG_DRM_I2C_ADV7533 is not set
+
#
# PCMCIA character devices
@@ -4092,6 +4137,7 @@ CONFIG_HID_GREENASIA=m
CONFIG_HID_SMARTJOYPLUS=m
CONFIG_HID_TOPSEED=m
CONFIG_HID_THINGM=m
+CONFIG_HID_LED=m
CONFIG_HID_THRUSTMASTER=m
CONFIG_HID_XINMO=m
CONFIG_HID_ZEROPLUS=m
@@ -4104,6 +4150,7 @@ CONFIG_HID_SENSOR_ALS=m
# CONFIG_HID_SENSOR_PROX is not set
CONFIG_HID_SENSOR_ACCEL_3D=m
# CONFIG_HID_SENSOR_CUSTOM_SENSOR is not set
+CONFIG_HID_ALPS=m
CONFIG_HID_EMS_FF=m
CONFIG_HID_ELECOM=m
CONFIG_HID_ELO=m
@@ -4700,6 +4747,8 @@ CONFIG_NFSD_PNFS=y
CONFIG_NFSD_BLOCKLAYOUT=y
CONFIG_NFSD_SCSILAYOUT=y
CONFIG_NFSD_V4_SECURITY_LABEL=y
+# This is labeled as 'bare minimum' and 'not for production'
+# CONFIG_NFSD_FLEXFILELAYOUT is not set
CONFIG_NFS_FSCACHE=y
# CONFIG_NFS_USE_LEGACY_DNS is not set
CONFIG_PNFS_OBJLAYOUT=m
@@ -5036,6 +5085,7 @@ CONFIG_CRYPTO_SEED=m
CONFIG_CRYPTO_SEQIV=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA3=m
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_TEA=m
@@ -5056,6 +5106,8 @@ CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y
CONFIG_CRYPTO_PCRYPT=m
CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_RSA=m
+CONFIG_CRYPTO_DH=m
+CONFIG_CRYPTO_ECDH=m
CONFIG_CRYPTO_CHACHA20POLY1305=m
CONFIG_CRYPTO_ECHAINIV=m
CONFIG_CRYPTO_POLY1305=m
@@ -5234,7 +5286,7 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
-CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_STAT_DETAILS=y
@@ -5274,22 +5326,27 @@ CONFIG_SND_INDIGODJX=m
CONFIG_SND_SOC=m
CONFIG_SND_SIMPLE_CARD=m
CONFIG_SND_DESIGNWARE_I2S=m
+CONFIG_SND_DESIGNWARE_PCM=m
CONFIG_SND_SOC_ALL_CODECS=m
CONFIG_SND_SOC_DMIC=m
CONFIG_SND_SOC_SPDIF=m
CONFIG_SND_DMAENGINE_PCM=m
CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y
# CONFIG_SND_SOC_ADAU1701 is not set
+# CONFIG_SND_SOC_ADAU7002 is not set
# CONFIG_SND_SOC_AK4104 is not set
# CONFIG_SND_SOC_AK4554 is not set
# CONFIG_SND_SOC_AK4642 is not set
# CONFIG_SND_SOC_AK5386 is not set
# CONFIG_SND_SOC_AK4613 is not set
+# CONFIG_SND_SOC_BT_SCO is not set
+# CONFIG_SND_SOC_CS35L33 is not set
# CONFIG_SND_SOC_CS42L52 is not set
# CONFIG_SND_SOC_CS42L73 is not set
# CONFIG_SND_SOC_CS4270 is not set
# CONFIG_SND_SOC_CS4271 is not set
# CONFIG_SND_SOC_CS42XX8_I2C is not set
+# CONFIG_SND_SOC_CS53L30 is not set
# CONFIG_SND_SOC_PCM1681 is not set
# CONFIG_SND_SOC_PCM179X is not set
# CONFIG_SND_SOC_PCM3168A_I2C is not set
@@ -5364,6 +5421,9 @@ CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y
CONFIG_SND_SOC_AMD_ACP=m
# CONFIG_SND_SOC_TAS5720 is not set
# CONFIG_SND_SOC_WM8960 is not set
+# CONFIG_SND_SOC_MAX98504 is not set
+# CONFIG_SND_SOC_MAX9860 is not set
+# CONFIG_SND_SOC_WM8985 is not set
CONFIG_BALLOON_COMPACTION=y
@@ -5413,9 +5473,11 @@ CONFIG_LEDS_LM3530=m
# CONFIG_LEDS_IS31FL32XX is not set
CONFIG_LEDS_BLINKM=m
CONFIG_LEDS_LP3944=m
+CONFIG_LEDS_LP3952=m
CONFIG_LEDS_LT3593=m
CONFIG_LEDS_REGULATOR=m
CONFIG_LEDS_TRIGGER_GPIO=m
+CONFIG_LEDS_TRIGGER_DISK=y
CONFIG_LEDS_WM8350=m
CONFIG_LEDS_WM831X_STATUS=m
# CONFIG_LEDS_DAC124S085 is not set
@@ -5427,8 +5489,8 @@ CONFIG_LEDS_WM831X_STATUS=m
CONFIG_DMADEVICES=y
CONFIG_DMA_ENGINE=y
-CONFIG_DW_DMAC_CORE=m
CONFIG_DW_DMAC=m
+CONFIG_DW_DMAC_CORE=m
CONFIG_DW_DMAC_PCI=m
# CONFIG_IDMA64 is not set
# CONFIG_DW_DMAC_BIG_ENDIAN_IO is not set
@@ -5439,7 +5501,7 @@ CONFIG_DW_DMAC_PCI=m
CONFIG_ASYNC_TX_DMA=y
# CONFIG_HSU_DMA is not set
# CONFIG_HSU_DMA_PCI is not set
-# CONFIG_XGENE_DMA is not set
+# CONFIG_XILINX_DMA is not set
# CONFIG_INTEL_IDMA64 is not set
# CONFIG_QCOM_HIDMA_MGMT is not set
# CONFIG_QCOM_HIDMA is not set
@@ -5536,6 +5598,8 @@ CONFIG_POWER_RESET=y
# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
# CONFIG_BATTERY_GAUGE_LTC2941 is not set
# CONFIG_POWER_RESET_RESTART is not set
+# CONFIG_SYSCON_REBOOT_MODE is not set
+# CONFIG_POWER_RESET_BRCMKONA is not set
# CONFIG_PDA_POWER is not set
@@ -5584,8 +5648,7 @@ CONFIG_INPUT_GP2A=m
# CONFIG_INTEL_MENLOW is not set
CONFIG_ENCLOSURE_SERVICES=m
-# Disable temporarily while I (pbr) work out why this filters properly when build with rpmbuild but not in koji
-# CONFIG_IPWIRELESS is not set
+CONFIG_IPWIRELESS=m
CONFIG_MEMSTICK=m
# CONFIG_MEMSTICK_DEBUG is not set
@@ -5622,6 +5685,12 @@ CONFIG_NET_DSA_MV88E6060=m
CONFIG_NET_DSA_MV88E6XXX=m
CONFIG_NET_DSA_BCM_SF2=m
+CONFIG_B53=m
+CONFIG_B53_SPI_DRIVER=m
+CONFIG_B53_MDIO_DRIVER=m
+CONFIG_B53_MMAP_DRIVER=m
+CONFIG_B53_SRAB_DRIVER=m
+
# Used by Maemo, we don't care.
# CONFIG_PHONET is not set
@@ -5654,6 +5723,7 @@ CONFIG_STAGING=y
# CONFIG_ANDROID is not set
# CONFIG_STAGING_BOARD is not set
CONFIG_STAGING_MEDIA=y
+# CONFIG_MEDIA_CEC is not set
# CONFIG_DVB_AS102 is not set
# CONFIG_SLICOSS is not set
# CONFIG_VIDEO_DT3155 is not set
@@ -5713,6 +5783,7 @@ CONFIG_USBIP_VUDC=m
# CONFIG_WILC1000_SDIO is not set
# CONFIG_WILC1000_SPI is not set
# CONFIG_LNET is not set
+# CONFIG_KS7010 is not set
# END OF STAGING
#
@@ -5733,6 +5804,7 @@ CONFIG_PWM=y
# CONFIG_PWM_PCA9685 is not set
CONFIG_LSM_MMAP_MIN_ADDR=65536
+CONFIG_HARDENED_USERCOPY=y
CONFIG_STRIP_ASM_SYMS=y
@@ -5925,7 +5997,7 @@ CONFIG_IOMMU_SUPPORT=y
# CONFIG_MAILBOX_TEST is not set
# CONFIG_RESET_CONTROLLER is not set
-
+# CONFIG_TI_SYSCON_RESET is not set
CONFIG_FMC=m
CONFIG_FMC_FAKEDEV=m
CONFIG_FMC_TRIVIAL=m
@@ -5940,7 +6012,8 @@ CONFIG_POWERCAP=y
# CONFIG_HSI is not set
-# CONFIG_CPU_IDLE is not set
+CONFIG_CPU_IDLE=y
+# CONFIG_CPU_IDLE_GOV_LADDER is not set
# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set
# CONFIG_ASM9260_TIMER is not set
@@ -5977,7 +6050,6 @@ CONFIG_SYSTEM_BLACKLIST_KEYRING=y
# CONFIG_MODULE_COMPRESS is not set
# CONFIG_RTC_DRV_EFI is not set
-# CONFIG_NET_XGENE is not set
# CONFIG_GLOB_SELFTEST is not set
diff --git a/config-powerpc64-generic b/config-powerpc64-generic
index ba71ccec1..fcd3a49a4 100644
--- a/config-powerpc64-generic
+++ b/config-powerpc64-generic
@@ -69,8 +69,6 @@ CONFIG_RCU_FANOUT_LEAF=16
CONFIG_FA_DUMP=y
CONFIG_RELOCATABLE=y
-CONFIG_CPU_IDLE=y
-# CONFIG_CPU_IDLE_GOV_LADDER is not set
CONFIG_POWERNV_CPUIDLE=y
CONFIG_PSERIES_CPUIDLE=y
@@ -121,6 +119,8 @@ CONFIG_IPMI_POWERNV=m
CONFIG_RTAS_FLASH=y
CONFIG_OPAL_PRD=m
CONFIG_MTD_POWERNV_FLASH=m
+# CONFIG_HOTPLUG_PCI_POWERNV is not set
+# CONFIG_POWERNV_OP_PANEL is not set
# Power 7 and later
CONFIG_PPC_TRANSACTIONAL_MEM=y
@@ -161,6 +161,7 @@ CONFIG_SCSI_IBMVSCSI=m
CONFIG_SCSI_IPR=m
CONFIG_SCSI_IPR_TRACE=y
CONFIG_SCSI_IPR_DUMP=y
+CONFIG_SCSI_IBMVSCSIS=m
CONFIG_SERIAL_ICOM=m
# CONFIG_SERIAL_8250 is not set
@@ -209,6 +210,7 @@ CONFIG_LEDS_TRIGGER_TIMER=m
CONFIG_LEDS_TRIGGER_HEARTBEAT=m
CONFIG_LEDS_TRIGGER_GPIO=m
CONFIG_LEDS_POWERNV=m
+CONFIG_ADB_PMU_LED_DISK=y
CONFIG_USB_EHCI_HCD_PPC_OF=y
CONFIG_USB_OHCI_HCD_PCI=y
@@ -374,3 +376,8 @@ CONFIG_POWER_RESET_GPIO_RESTART=y
CONFIG_FB_SSD1307=m
CONFIG_INPUT_PWM_BEEPER=m
CONFIG_BACKLIGHT_PWM=m
+
+CONFIG_CRYPT_CRC32C_VPMSUM=m
+
+# CONFIG_JUMP_LABEL_FEATURE_CHECKS is not set
+# CONFIG_JUMP_LABEL_FEATURE_CHECK_DEBUG is not set
diff --git a/config-s390x b/config-s390x
index d559c6570..e235e9e01 100644
--- a/config-s390x
+++ b/config-s390x
@@ -135,6 +135,7 @@ CONFIG_CRYPTO_GHASH_S390=m
CONFIG_CRYPTO_SHA1_S390=m
CONFIG_CRYPTO_SHA256_S390=m
CONFIG_CRYPTO_SHA512_S390=m
+CONFIG_CRYPTO_CRC32_S390=m
#
# Kernel hacking
@@ -158,6 +159,7 @@ CONFIG_MONREADER=m
CONFIG_STACK_GUARD=256
CONFIG_CMM_IUCV=y
+# CONFIG_CPU_IDLE is not set
CONFIG_S390_HYPFS_FS=y
@@ -178,6 +180,7 @@ CONFIG_QETH_L3=m
CONFIG_KVM=m
# CONFIG_KVM_S390_UCONTROL is not set
CONFIG_S390_GUEST=y
+CONFIG_S390_GUEST_OLD_TRANSPORT=y
CONFIG_VIRTIO_CONSOLE=y
diff --git a/config-x86-generic b/config-x86-generic
index bbbd71da1..a44190bd7 100644
--- a/config-x86-generic
+++ b/config-x86-generic
@@ -76,7 +76,7 @@ CONFIG_X86_MPPARSE=y
CONFIG_MMIOTRACE=y
# CONFIG_MMIOTRACE_TEST is not set
# CONFIG_DEBUG_PER_CPU_MAPS is not set
-# CONFIG_DEBUG_WX is not set
+CONFIG_DEBUG_WX=y
CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_ACPI=y
@@ -86,7 +86,6 @@ CONFIG_ACPI_BUTTON=y
CONFIG_ACPI_CONTAINER=y
CONFIG_ACPI_DOCK=y
CONFIG_ACPI_FAN=y
-CONFIG_ACPI_NUMA=y
CONFIG_ACPI_PROCESSOR=y
CONFIG_ACPI_PROCFS=y
CONFIG_ACPI_SBS=m
@@ -95,6 +94,7 @@ CONFIG_ACPI_THERMAL=y
CONFIG_ACPI_TOSHIBA=m
CONFIG_ACPI_VIDEO=m
CONFIG_ACPI_INITRD_TABLE_OVERRIDE=y
+CONFIG_ACPI_CONFIGFS=m
# FIXME: Next two are deprecated. Remove them when they disappear upstream
# CONFIG_ACPI_PROCFS_POWER is not set
CONFIG_PNPACPI=y
@@ -105,6 +105,7 @@ CONFIG_ACPI_APEI_PCIEAER=y
CONFIG_ACPI_APEI_GHES=y
CONFIG_ACPI_APEI_MEMORY_FAILURE=y
# CONFIG_ACPI_APEI_EINJ is not set
+CONFIG_DPTF_POWER=m
CONFIG_ACPI_IPMI=m
CONFIG_ACPI_CUSTOM_METHOD=m
CONFIG_ACPI_BGRT=y
@@ -116,10 +117,11 @@ CONFIG_INTEL_SOC_PMIC=y
CONFIG_PMIC_OPREGION=y
CONFIG_CRC_PMIC_OPREGION=y
CONFIG_XPOWER_PMIC_OPREGION=y
+CONFIG_BXT_WC_PMIC_OPREGION=y
CONFIG_GPIO_CRYSTAL_COVE=y
CONFIG_AXP288_ADC=y
CONFIG_AXP288_FUEL_GAUGE=y
-# CONFIG_PWM_CRC is not set
+CONFIG_PWM_CRC=y
CONFIG_X86_INTEL_PSTATE=y
@@ -243,6 +245,7 @@ CONFIG_FUJITSU_TABLET=m
CONFIG_FUJITSU_LAPTOP=m
# CONFIG_FUJITSU_LAPTOP_DEBUG is not set
CONFIG_IDEAPAD_LAPTOP=m
+CONFIG_INTEL_VBTN=m
CONFIG_INTEL_HID_EVENT=m
CONFIG_MSI_LAPTOP=m
CONFIG_PANASONIC_LAPTOP=m
@@ -274,6 +277,7 @@ CONFIG_PVPANIC=m
# CONFIG_TOUCHSCREEN_INTEL_MID is not set
CONFIG_TOUCHSCREEN_GOODIX=m
+CONFIG_TOUCHSCREEN_SURFACE3_SPI=m
# CONFIG_SMSC37B787_WDT is not set
CONFIG_VIA_WDT=m
@@ -341,11 +345,6 @@ CONFIG_SPI_PXA2XX=m
CONFIG_MTD_ESB2ROM=m
CONFIG_MTD_CK804XROM=m
-CONFIG_CPU_IDLE=y
-# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set
-# CONFIG_CPU_IDLE_GOV_LADDER is not set
-CONFIG_CPU_IDLE_GOV_MENU=y
-
CONFIG_THINKPAD_ACPI=m
# CONFIG_THINKPAD_ACPI_DEBUG is not set
# CONFIG_THINKPAD_ACPI_DEBUGFACILITIES is not set
@@ -461,7 +460,6 @@ CONFIG_INTEL_PMC_CORE=y
CONFIG_VIDEO_VIA_CAMERA=m
-CONFIG_IRQ_TIME_ACCOUNTING=y
CONFIG_X86_RESERVE_LOW=64
# CONFIG_IRQ_DOMAIN_DEBUG is not set
@@ -565,10 +563,12 @@ CONFIG_SND_SOC_INTEL_SKL_RT286_MACH=m
CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH=m
CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH=m
CONFIG_SND_SOC_INTEL_BXT_RT298_MACH=m
+CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH=m
CONFIG_SND_SOC_AC97_CODEC=m
# CONFIG_SND_SOC_TAS571X is not set
# CONFIG_SND_SUN4I_CODEC is not set
# CONFIG_SND_SUN4I_SPDIF is not set
+# CONFIG_SND_SUN4I_I2S is not set
CONFIG_INTEL_POWERCLAMP=m
CONFIG_X86_PKG_TEMP_THERMAL=m
diff --git a/config-x86_64-generic b/config-x86_64-generic
index d1e9105c5..704dc30bd 100644
--- a/config-x86_64-generic
+++ b/config-x86_64-generic
@@ -9,14 +9,15 @@ CONFIG_GENERIC_CPU=y
CONFIG_X86_UV=y
CONFIG_UV_MMTIMER=m
CONFIG_NUMA=y
+CONFIG_ACPI_NUMA=y
CONFIG_AMD_NUMA=y
CONFIG_X86_64_ACPI_NUMA=y
CONFIG_ACPI_NFIT=m
# CONFIG_ACPI_NFIT_DEBUG is not set
# CONFIG_NUMA_EMU is not set
CONFIG_X86_NUMACHIP=y
-CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y
CONFIG_NUMA_BALANCING=y
+CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y
# https://lists.fedoraproject.org/pipermail/kernel/2013-November/004601.html
CONFIG_NR_CPUS=1024
@@ -28,6 +29,7 @@ CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS=y
+CONFIG_RANDOMIZE_MEMORY=y
# enable the 32-bit entry point for Baytrail
CONFIG_EFI_MIXED=y
@@ -80,6 +82,8 @@ CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m
CONFIG_CRYPTO_SHA1_SSSE3=m
CONFIG_CRYPTO_SHA256_SSSE3=m
CONFIG_CRYPTO_SHA512_SSSE3=m
+CONFIG_CRYPTO_SHA256_MB=m
+CONFIG_CRYPTO_SHA512_MB=m
CONFIG_CRYPTO_BLOWFISH_X86_64=m
CONFIG_CRYPTO_TWOFISH_X86_64_3WAY=m
CONFIG_CRYPTO_CAMELLIA_X86_64=m
@@ -106,6 +110,7 @@ CONFIG_CRYPTO_CHACHA20_X86_64=m
CONFIG_EDAC_AMD64=m
# CONFIG_EDAC_AMD64_ERROR_INJECTION is not set
CONFIG_EDAC_SBRIDGE=m
+CONFIG_EDAC_SKX=m
# CONFIG_PC8736x_GPIO is not set
@@ -235,6 +240,3 @@ CONFIG_INFINIBAND_HFI1=m
# CONFIG_HFI1_DEBUG_SDMA_ORDER is not set
CONFIG_HFI1_VERBS_31BIT_PSN=y
# CONFIG_SDMA_VERBOSITY is not set
-#
-# Temporary workaround until SND_SOC_INTEL_HASWELL_MACH no longer requires builtin
-CONFIG_DW_DMAC=y
diff --git a/crash-driver.patch b/crash-driver.patch
index d88138440..2b05554b7 100644
--- a/crash-driver.patch
+++ b/crash-driver.patch
@@ -1,3 +1,4 @@
+From 3fbd61fbbbfa7ae15cd3f3e2ff7a97e106be2b43 Mon Sep 17 00:00:00 2001
From: Dave Anderson <anderson@redhat.com>
Date: Tue, 26 Nov 2013 12:42:46 -0500
Subject: [PATCH] crash-driver
@@ -29,7 +30,7 @@ Upstream-status: Fedora mustard
diff --git a/arch/arm/include/asm/crash-driver.h b/arch/arm/include/asm/crash-driver.h
new file mode 100644
-index 000000000000..06e7ae916601
+index 0000000..06e7ae9
--- /dev/null
+++ b/arch/arm/include/asm/crash-driver.h
@@ -0,0 +1,6 @@
@@ -41,7 +42,7 @@ index 000000000000..06e7ae916601
+#endif /* _ARM_CRASH_H */
diff --git a/arch/arm64/include/asm/crash-driver.h b/arch/arm64/include/asm/crash-driver.h
new file mode 100644
-index 000000000000..43b26da0c5d6
+index 0000000..43b26da
--- /dev/null
+++ b/arch/arm64/include/asm/crash-driver.h
@@ -0,0 +1,6 @@
@@ -53,7 +54,7 @@ index 000000000000..43b26da0c5d6
+#endif /* _ARM64_CRASH_H */
diff --git a/arch/ia64/include/asm/crash-driver.h b/arch/ia64/include/asm/crash-driver.h
new file mode 100644
-index 000000000000..404bcb93c112
+index 0000000..404bcb9
--- /dev/null
+++ b/arch/ia64/include/asm/crash-driver.h
@@ -0,0 +1,90 @@
@@ -148,7 +149,7 @@ index 000000000000..404bcb93c112
+
+#endif /* _ASM_IA64_CRASH_H */
diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
-index 096731049538..e88887827906 100644
+index 0967310..e888878 100644
--- a/arch/ia64/kernel/ia64_ksyms.c
+++ b/arch/ia64/kernel/ia64_ksyms.c
@@ -84,6 +84,9 @@ EXPORT_SYMBOL(ia64_save_scratch_fpregs);
@@ -163,7 +164,7 @@ index 096731049538..e88887827906 100644
EXPORT_SYMBOL_GPL(esi_call_phys);
diff --git a/arch/powerpc/include/asm/crash-driver.h b/arch/powerpc/include/asm/crash-driver.h
new file mode 100644
-index 000000000000..50092d965dc5
+index 0000000..50092d9
--- /dev/null
+++ b/arch/powerpc/include/asm/crash-driver.h
@@ -0,0 +1,6 @@
@@ -175,7 +176,7 @@ index 000000000000..50092d965dc5
+#endif /* _PPC64_CRASH_H */
diff --git a/arch/s390/include/asm/crash-driver.h b/arch/s390/include/asm/crash-driver.h
new file mode 100644
-index 000000000000..552be5e2c571
+index 0000000..552be5e
--- /dev/null
+++ b/arch/s390/include/asm/crash-driver.h
@@ -0,0 +1,60 @@
@@ -240,10 +241,10 @@ index 000000000000..552be5e2c571
+
+#endif /* _S390_CRASH_H */
diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c
-index 8a993a53fcd6..8f511795b52e 100644
+index 792f9c6..3197995 100644
--- a/arch/s390/mm/maccess.c
+++ b/arch/s390/mm/maccess.c
-@@ -197,6 +197,7 @@ void *xlate_dev_mem_ptr(phys_addr_t addr)
+@@ -201,6 +201,7 @@ void *xlate_dev_mem_ptr(phys_addr_t addr)
put_online_cpus();
return bounce;
}
@@ -251,14 +252,14 @@ index 8a993a53fcd6..8f511795b52e 100644
/*
* Free converted buffer for /dev/mem access (if necessary)
-@@ -206,3 +207,4 @@ void unxlate_dev_mem_ptr(phys_addr_t addr, void *buf)
+@@ -210,3 +211,4 @@ void unxlate_dev_mem_ptr(phys_addr_t addr, void *buf)
if ((void *) addr != buf)
free_page((unsigned long) buf);
}
+EXPORT_SYMBOL_GPL(unxlate_dev_mem_ptr);
diff --git a/arch/x86/include/asm/crash-driver.h b/arch/x86/include/asm/crash-driver.h
new file mode 100644
-index 000000000000..fd4736ec99f5
+index 0000000..fd4736e
--- /dev/null
+++ b/arch/x86/include/asm/crash-driver.h
@@ -0,0 +1,6 @@
@@ -269,7 +270,7 @@ index 000000000000..fd4736ec99f5
+
+#endif /* _X86_CRASH_H */
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
-index a043107da2af..b272397f306a 100644
+index fdb8f3e..7dd3a49 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -4,6 +4,9 @@
@@ -283,18 +284,18 @@ index a043107da2af..b272397f306a 100644
config DEVMEM
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
-index d8a7579300d2..31c83630f593 100644
+index 55d16bf..a40ace9 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
-@@ -60,3 +60,5 @@ js-rtc-y = rtc.o
-
+@@ -61,3 +61,5 @@ js-rtc-y = rtc.o
obj-$(CONFIG_TILE_SROM) += tile-srom.o
obj-$(CONFIG_XILLYBUS) += xillybus/
+ obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o
+
+obj-$(CONFIG_CRASH) += crash.o
diff --git a/drivers/char/crash.c b/drivers/char/crash.c
new file mode 100644
-index 000000000000..085378a1d539
+index 0000000..085378a
--- /dev/null
+++ b/drivers/char/crash.c
@@ -0,0 +1,128 @@
@@ -428,7 +429,7 @@ index 000000000000..085378a1d539
+MODULE_LICENSE("GPL");
diff --git a/include/asm-generic/crash-driver.h b/include/asm-generic/crash-driver.h
new file mode 100644
-index 000000000000..25ab9869d566
+index 0000000..25ab986
--- /dev/null
+++ b/include/asm-generic/crash-driver.h
@@ -0,0 +1,72 @@
@@ -504,3 +505,101 @@ index 000000000000..25ab9869d566
+#endif /* __KERNEL__ */
+
+#endif /* __CRASH_H__ */
+--
+2.9.2
+
+From 7523c19e1d22fbabeaeae9520c16a78202c0eefe Mon Sep 17 00:00:00 2001
+From: Fedora Kernel Team <kernel-team@fedoraproject.org>
+Date: Tue, 20 Sep 2016 19:39:46 +0200
+Subject: [PATCH] Update of crash driver to handle CONFIG_HARDENED_USERCOPY and
+ to restrict the supported architectures.
+
+---
+ drivers/char/Kconfig | 1 +
+ drivers/char/crash.c | 33 ++++++++++++++++++++++++++++++---
+ 2 files changed, 31 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
+index 99b99d5..be6a3ae 100644
+--- a/drivers/char/Kconfig
++++ b/drivers/char/Kconfig
+@@ -6,6 +6,7 @@ menu "Character devices"
+
+ config CRASH
+ tristate "Crash Utility memory driver"
++ depends on X86_32 || X86_64 || ARM || ARM64 || PPC64 || S390
+
+ source "drivers/tty/Kconfig"
+
+diff --git a/drivers/char/crash.c b/drivers/char/crash.c
+index 085378a..0258bf8 100644
+--- a/drivers/char/crash.c
++++ b/drivers/char/crash.c
+@@ -32,7 +32,7 @@
+ #include <asm/types.h>
+ #include <asm/crash-driver.h>
+
+-#define CRASH_VERSION "1.0"
++#define CRASH_VERSION "1.2"
+
+ /*
+ * These are the file operation functions that allow crash utility
+@@ -66,6 +66,7 @@ crash_read(struct file *file, char *buf, size_t count, loff_t *poff)
+ struct page *page;
+ u64 offset;
+ ssize_t read;
++ char *buffer = file->private_data;
+
+ offset = *poff;
+ if (offset >> PAGE_SHIFT != (offset+count-1) >> PAGE_SHIFT)
+@@ -74,8 +75,12 @@ crash_read(struct file *file, char *buf, size_t count, loff_t *poff)
+ vaddr = map_virtual(offset, &page);
+ if (!vaddr)
+ return -EFAULT;
+-
+- if (copy_to_user(buf, vaddr, count)) {
++ /*
++ * Use bounce buffer to bypass the CONFIG_HARDENED_USERCOPY
++ * kernel text restriction.
++ */
++ memcpy(buffer, (char *)vaddr, count);
++ if (copy_to_user(buf, buffer, count)) {
+ unmap_virtual(page);
+ return -EFAULT;
+ }
+@@ -86,10 +91,32 @@ crash_read(struct file *file, char *buf, size_t count, loff_t *poff)
+ return read;
+ }
+
++static int
++crash_open(struct inode * inode, struct file * filp)
++{
++ if (!capable(CAP_SYS_RAWIO))
++ return -EPERM;
++
++ filp->private_data = (void *)__get_free_page(GFP_KERNEL);
++ if (!filp->private_data)
++ return -ENOMEM;
++
++ return 0;
++}
++
++static int
++crash_release(struct inode *inode, struct file *filp)
++{
++ free_pages((unsigned long)filp->private_data, 0);
++ return 0;
++}
++
+ static struct file_operations crash_fops = {
+ .owner = THIS_MODULE,
+ .llseek = crash_llseek,
+ .read = crash_read,
++ .open = crash_open,
++ .release = crash_release,
+ };
+
+ static struct miscdevice crash_dev = {
+--
+2.9.3
+
diff --git a/disable-CONFIG_EXPERT-for-ZONE_DMA.patch b/disable-CONFIG_EXPERT-for-ZONE_DMA.patch
deleted file mode 100644
index 784cf2035..000000000
--- a/disable-CONFIG_EXPERT-for-ZONE_DMA.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From 78bd7226c92c8309d1c6c1378f1224dcd591b49f Mon Sep 17 00:00:00 2001
-From: Fedora Kernel Team <kernel-team@fedoraproject.org>
-Date: Fri, 22 Jan 2016 13:03:36 -0600
-Subject: [PATCH] Make ZONE_DMA not depend on CONFIG_EXPERT
-
-Disable the requirement on CONFIG_EXPERT for ZONE_DMA and ZONE_DEVICE so
-that we can enable NVDIMM_PFN and ND_PFN
-
-Signed-off-by: Justin Forbes <jforbes@fedoraproject.org>
----
- arch/x86/Kconfig | 2 +-
- mm/Kconfig | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index 3c74b549ea9a..8a5b7b8cc425 100644
---- a/arch/x86/Kconfig
-+++ b/arch/x86/Kconfig
-@@ -318,7 +318,7 @@ source "kernel/Kconfig.freezer"
- menu "Processor type and features"
-
- config ZONE_DMA
-- bool "DMA memory allocation support" if EXPERT
-+ bool "DMA memory allocation support"
- default y
- help
- DMA memory allocation support allows devices with less than 32-bit
-diff --git a/mm/Kconfig b/mm/Kconfig
-index 05efa6a5199e..c1a01e50c293 100644
---- a/mm/Kconfig
-+++ b/mm/Kconfig
-@@ -650,7 +650,7 @@ config IDLE_PAGE_TRACKING
- See Documentation/vm/idle_page_tracking.txt for more details.
-
- config ZONE_DEVICE
-- bool "Device memory (pmem, etc...) hotplug support" if EXPERT
-+ bool "Device memory (pmem, etc...) hotplug support"
- depends on MEMORY_HOTPLUG
- depends on MEMORY_HOTREMOVE
- depends on SPARSEMEM_VMEMMAP
---
-2.5.0
-
diff --git a/drm-i915-turn-off-wc-mmaps.patch b/drm-i915-turn-off-wc-mmaps.patch
index c81b89226..51df9c296 100644
--- a/drm-i915-turn-off-wc-mmaps.patch
+++ b/drm-i915-turn-off-wc-mmaps.patch
@@ -3,13 +3,13 @@ Date: Thu, 4 Jun 2015 07:12:20 -0400
Subject: [PATCH] drm: i915: turn off wc mmaps
---
- drivers/gpu/drm/i915/i915_dma.c | 2 +-
+ drivers/gpu/drm/i915/i915_drv.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
-diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
+diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index d2df321ba634..775a5b11a366 100644
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
+--- a/drivers/gpu/drm/i915/i915_drv.c
++++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -151,7 +151,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
value = 1;
break;
diff --git a/kbuild-AFTER_LINK.patch b/kbuild-AFTER_LINK.patch
index 6cbf7d643..d79a6186b 100644
--- a/kbuild-AFTER_LINK.patch
+++ b/kbuild-AFTER_LINK.patch
@@ -1,4 +1,4 @@
-From 3430f2441f7176d543a76aa73ae7315db355a5b0 Mon Sep 17 00:00:00 2001
+From a9488dbeccf188f0bd83b9d5704892f2c0f97fdc Mon Sep 17 00:00:00 2001
From: Roland McGrath <roland@redhat.com>
Date: Mon, 6 Oct 2008 23:03:03 -0700
Subject: [PATCH] kbuild: AFTER_LINK
@@ -42,8 +42,8 @@ index 6abffb7..7b103bb 100644
# actual build commands
quiet_cmd_vdso32ld = VDSO32L $@
-- cmd_vdso32ld = $(CROSS32CC) $(c_flags) -Wl,-T $^ -o $@
-+ cmd_vdso32ld = $(CROSS32CC) $(c_flags) -Wl,-T $^ -o $@ \
+- cmd_vdso32ld = $(CROSS32CC) $(c_flags) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^)
++ cmd_vdso32ld = $(CROSS32CC) $(c_flags) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^) \
+ $(if $(AFTER_LINK),; $(AFTER_LINK))
quiet_cmd_vdso32as = VDSO32A $@
cmd_vdso32as = $(CROSS32CC) $(a_flags) -c -o $@ $<
@@ -56,8 +56,8 @@ index 8c8f2ae..a743ebe 100644
# actual build commands
quiet_cmd_vdso64ld = VDSO64L $@
-- cmd_vdso64ld = $(CC) $(c_flags) -Wl,-T $^ -o $@
-+ cmd_vdso64ld = $(CC) $(c_flags) -Wl,-T $^ -o $@ \
+- cmd_vdso64ld = $(CC) $(c_flags) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^)
++ cmd_vdso64ld = $(CC) $(c_flags) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^) \
+ $(if $(AFTER_LINK),; $(AFTER_LINK))
quiet_cmd_vdso64as = VDSO64A $@
cmd_vdso64as = $(CC) $(a_flags) -c -o $@ $<
@@ -107,7 +107,7 @@ index 265c0ed..fd90c7d 100644
VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=both) \
$(call cc-ldoption, -Wl$(comma)--build-id) -Wl,-Bsymbolic $(LTO_CFLAGS)
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
-index ba6c34e..245501e 100755
+index dacf71a..72cbefd 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -65,6 +65,10 @@ vmlinux_link()
diff --git a/kernel-panic-TPROXY-vanilla-4.7.1.patch b/kernel-panic-TPROXY-vanilla-4.7.1.patch
deleted file mode 100644
index 9d045cabe..000000000
--- a/kernel-panic-TPROXY-vanilla-4.7.1.patch
+++ /dev/null
@@ -1,85 +0,0 @@
-From patchwork Wed Aug 17 16:04:31 2016
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: kernel panic TPROXY , vanilla 4.7.1
-From: Eric Dumazet <eric.dumazet@gmail.com>
-X-Patchwork-Id: 660174
-X-Patchwork-Delegate: davem@davemloft.net
-Message-Id: <1471449871.29842.3.camel@edumazet-glaptop3.roam.corp.google.com>
-To: Denys Fedoryshchenko <nuclearcat@nuclearcat.com>
-Cc: Linux Kernel Network Developers <netdev@vger.kernel.org>,
- netfilter-devel@vger.kernel.org
-Date: Wed, 17 Aug 2016 09:04:31 -0700
-
-On Wed, 2016-08-17 at 08:42 -0700, Eric Dumazet wrote:
-> On Wed, 2016-08-17 at 17:31 +0300, Denys Fedoryshchenko wrote:
-> > Hi!
-> >
-> > Tried to run squid on latest kernel, and hit a panic
-> > Sometimes it just shows warning in dmesg (but doesnt work properly)
-> > [ 75.701666] IPv4: Attempt to release TCP socket in state 10
-> > ffff88102d430780
-> > [ 83.866974] squid (2700) used greatest stack depth: 12912 bytes left
-> > [ 87.506644] IPv4: Attempt to release TCP socket in state 10
-> > ffff880078a48780
-> > [ 114.704295] IPv4: Attempt to release TCP socket in state 10
-> > ffff881029f8ad00
-> >
-> > I cannot catch yet oops/panic message, netconsole not working.
-> >
-> > After triggering warning message 3 times, i am unable to run squid
-> > anymore (without reboot), and in netstat it doesnt show port running.
-> >
-> > firewall is:
-> > *mangle
-> > -A PREROUTING -p tcp -m socket -j DIVERT
-> > -A PREROUTING -p tcp -m tcp --dport 80 -i eno1 -j TPROXY --on-port 3129
-> > --on-ip 0.0.0.0 --tproxy-mark 0x1/0x1
-> > -A DIVERT -j MARK --set-xmark 0x1/0xffffffff
-> > -A DIVERT -j ACCEPT
-> >
-> > routing
-> > ip rule add fwmark 1 lookup 100
-> > ip route add local default dev eno1 table 100
-> >
-> >
-> > squid config is default with tproxy option
-> > http_port 3129 tproxy
-> >
->
-> Hmppff... sorry for this, I will send a fix.
->
-> Thanks for the report !
->
-
-
-Could you try the following ?
-
-Thanks !
-
- net/netfilter/xt_TPROXY.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
-index 7f4414d26a66..663c4c3c9072 100644
---- a/net/netfilter/xt_TPROXY.c
-+++ b/net/netfilter/xt_TPROXY.c
-@@ -127,6 +127,8 @@ nf_tproxy_get_sock_v4(struct net *net, struct sk_buff *skb, void *hp,
- daddr, dport,
- in->ifindex);
-
-+ if (sk && !atomic_inc_not_zero(&sk->sk_refcnt))
-+ sk = NULL;
- /* NOTE: we return listeners even if bound to
- * 0.0.0.0, those are filtered out in
- * xt_socket, since xt_TPROXY needs 0 bound
-@@ -195,6 +197,8 @@ nf_tproxy_get_sock_v6(struct net *net, struct sk_buff *skb, int thoff, void *hp,
- daddr, ntohs(dport),
- in->ifindex);
-
-+ if (sk && !atomic_inc_not_zero(&sk->sk_refcnt))
-+ sk = NULL;
- /* NOTE: we return listeners even if bound to
- * 0.0.0.0, those are filtered out in
- * xt_socket, since xt_TPROXY needs 0 bound
diff --git a/kernel.spec b/kernel.spec
index 8c107da3f..77393ec78 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -50,7 +50,7 @@ Summary: The Linux kernel
# base_sublevel is the kernel version we're starting with and patching
# on top of -- for example, 3.1-rc7-git1 starts with a 3.0 base,
# which yields a base_sublevel of 0.
-%define base_sublevel 7
+%define base_sublevel 8
## If this is a released kernel ##
%if 0%{?released_kernel}
@@ -60,7 +60,7 @@ Summary: The Linux kernel
# Do we have a -stable update to apply?
-%define stable_update 10
+%define stable_update 6
# Set rpm version accordingly
%if 0%{?stable_update}
%define stablerev %{stable_update}
@@ -515,23 +515,34 @@ Source5005: kbuild-AFTER_LINK.patch
# Git trees.
# Standalone patches
-Patch420: arm64-avoid-needing-console-to-enable-serial-console.patch
+
+# http://www.spinics.net/lists/arm-kernel/msg523359.html
+Patch420: arm64-ACPI-parse-SPCR-table.patch
+
+# a tempory patch for QCOM hardware enablement. Will be gone by end of 2016/F-26 GA
+Patch421: qcom-QDF2432-tmp-errata.patch
# http://www.spinics.net/lists/arm-kernel/msg490981.html
Patch422: geekbox-v4-device-tree-support.patch
-Patch424: arm64-pcie-acpi.patch
-Patch425: arm64-pcie-quirks-xgene.patch
+# http://www.spinics.net/lists/linux-pci/msg53991.html
+# https://patchwork.kernel.org/patch/9337113/
+Patch425: arm64-pcie-quirks.patch
# http://www.spinics.net/lists/linux-tegra/msg26029.html
Patch426: usb-phy-tegra-Add-38.4MHz-clock-table-entry.patch
+Patch427: ARM-OMAP4-Fix-crashes.patch
+Patch428: arm-revert-mmc-omap_hsmmc-Use-dma_request_chan-for-reque.patch
+
# http://patchwork.ozlabs.org/patch/587554/
Patch430: ARM-tegra-usb-no-reset.patch
-Patch431: bcm283x-upstream-fixes.patch
+Patch431: bcm2837-initial-support.patch
+
+Patch432: bcm283x-vc4-fixes.patch
-Patch432: arm-i.MX6-Utilite-device-dtb.patch
+Patch433: AllWinner-net-emac.patch
Patch460: lib-cpumask-Make-CPUMASK_OFFSTACK-usable-without-deb.patch
@@ -594,7 +605,8 @@ Patch494: disable-i8042-check-on-apple-mac.patch
Patch495: lis3-improve-handling-of-null-rate.patch
-Patch496: watchdog-Disable-watchdog-on-virtual-machines.patch
+# In theory this has been fixed so should no longer be needed, it also causes problems with aarch64 DMI, so disable to see for sure if it's fixed
+# Patch496: watchdog-Disable-watchdog-on-virtual-machines.patch
Patch497: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch
@@ -612,48 +624,35 @@ Patch503: drm-i915-turn-off-wc-mmaps.patch
Patch508: kexec-uefi-copy-secure_boot-flag-in-boot-params.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
-#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
-
-#rhbz 1353558
-Patch844: 0001-selinux-Only-apply-bounds-checking-to-source-types.patch
-
-#rhbz 13700161
-Patch857: kernel-panic-TPROXY-vanilla-4.7.1.patch
+#rhbz 1200901 (There should be something better upstream at some point)
+Patch842: qxl-reapply-cursor-after-SetCrtc-calls.patch
-#rhbz 1360688
-Patch859: rc-core-fix-repeat-events.patch
+# From kernel list, currently in linux-next
+Patch845: HID-microsoft-Add-Surface-4-type-cover-pro-4-JP.patch
-#rhbz 1350174
-Patch862: tip-x86-boot-x86-KASLR-x86-power-Remove-x86-hibernation-restrictions.patch
+# SELinux OverlayFS support (queued for 4.9)
+Patch846: security-selinux-overlayfs-support.patch
+
+#rhbz 1360688
+Patch847: rc-core-fix-repeat-events.patch
#rhbz 1374212
-Patch863: 0001-cpupower-Correct-return-type-of-cpu_power_is_cpu_onl.patch
+Patch848: 0001-cpupower-Correct-return-type-of-cpu_power_is_cpu_onl.patch
#ongoing complaint, full discussion delayed until ksummit/plumbers
-Patch864: 0001-iio-Use-event-header-from-kernel-tree.patch
+Patch849: 0001-iio-Use-event-header-from-kernel-tree.patch
+
+# CVE-2016-9083 CVE-2016-9084 rhbz 1389258 1389259 1389285
+Patch850: v3-vfio-pci-Fix-integer-overflows-bitmask-check.patch
+
+#rhbz 1325354
+Patch852: 0001-HID-input-ignore-System-Control-application-usages-i.patch
+
+#rhbz 1391279
+Patch853: 0001-dm-raid-fix-compat_features-validation.patch
# END OF PATCH DEFINITIONS
@@ -2180,6 +2179,12 @@ fi
#
#
%changelog
+* Mon Nov 7 2016 Justin M. Forbes <jforbes@fedoraproject.org>
+- Linux v4.8.6
+
+* Thu Oct 27 2016 Justin M. Forbes <jforbes@fedoraproject.org>
+- CVE-2016-9083 CVE-2016-9084 vfio multiple flaws (rhbz 1389258 1389259 1389285)
+
* Wed Oct 26 2016 Laura Abbott <labbott@redhat.com> - 4.7.10-100
- Linux v4.7.10
diff --git a/qcom-QDF2432-tmp-errata.patch b/qcom-QDF2432-tmp-errata.patch
new file mode 100644
index 000000000..f7ace4787
--- /dev/null
+++ b/qcom-QDF2432-tmp-errata.patch
@@ -0,0 +1,59 @@
+From edc7986d4d405daebaf2f66269b353da579fce5f Mon Sep 17 00:00:00 2001
+From: Christopher Covington <cov@codeaurora.org>
+Date: Tue, 31 May 2016 16:19:02 -0400
+Subject: arm64: Workaround for QDF2432 ID_AA64 SR accesses
+
+The ARMv8.0 architecture reserves several system register encodings for
+future use. These encodings should behave as read-only and always return
+zero on a read. As described in Errata 94, the CPU cores in the QDF2432
+errantly cause an instruction abort if an AArch64 MRS instruction attempts
+to read any of the following system register encodings:
+
+ Op0, Op1, CRn, CRm, Op2
+ 3, 0, C0, [C4-C7], [2-3, 6-7]
+ 3, 0, C0, C3, [3-7]
+ 3, 0, C0, [C4,C6,C7], [4-5]
+ 3, 0, C0, C2, [6-7]
+
+Naively projecting ARMv8.0 names, this space includes:
+
+ ID_AA64PFR[2-7]_EL1
+ ID_AA64DFR[2-3]_EL1
+ ID_AA64AFR[2-3]_EL1
+ ID_AA64ISAR[2-7]_EL1
+ ID_AA64MMFR[2-7]_EL1
+
+As of v4.8-rc2, Linux only attempts to query one register in this space,
+ID_AA64MMFR2_EL1. As simple workaround, skip that access when the affected
+MIDR is detected.
+
+Signed-off-by: Christopher Covington <cov@codeaurora.org>
+---
+ arch/arm64/kernel/cpuinfo.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
+index ed1b84f..790de6b 100644
+--- a/arch/arm64/kernel/cpuinfo.c
++++ b/arch/arm64/kernel/cpuinfo.c
+@@ -325,6 +325,8 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
+
+ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
+ {
++ bool qdf2432_cpu = read_cpuid_id() == 0x510f2811;
++
+ info->reg_cntfrq = arch_timer_get_cntfrq();
+ info->reg_ctr = read_cpuid_cachetype();
+ info->reg_dczid = read_cpuid(DCZID_EL0);
+@@ -337,7 +339,7 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
+ info->reg_id_aa64isar1 = read_cpuid(ID_AA64ISAR1_EL1);
+ info->reg_id_aa64mmfr0 = read_cpuid(ID_AA64MMFR0_EL1);
+ info->reg_id_aa64mmfr1 = read_cpuid(ID_AA64MMFR1_EL1);
+- info->reg_id_aa64mmfr2 = read_cpuid(ID_AA64MMFR2_EL1);
++ info->reg_id_aa64mmfr2 = qdf2432_cpu ? 0 : read_cpuid(ID_AA64MMFR2_EL1);
+ info->reg_id_aa64pfr0 = read_cpuid(ID_AA64PFR0_EL1);
+ info->reg_id_aa64pfr1 = read_cpuid(ID_AA64PFR1_EL1);
+
+--
+cgit v0.12
+
diff --git a/qxl-reapply-cursor-after-SetCrtc-calls.patch b/qxl-reapply-cursor-after-SetCrtc-calls.patch
new file mode 100644
index 000000000..d70acc4eb
--- /dev/null
+++ b/qxl-reapply-cursor-after-SetCrtc-calls.patch
@@ -0,0 +1,439 @@
+From 92777b4dfc3920edb449d0be6ead65d8460653cc Mon Sep 17 00:00:00 2001
+From: Ray Strode <rstrode@redhat.com>
+Date: Tue, 12 May 2015 12:51:18 -0400
+Subject: [PATCH] drm/qxl: reapply cursor after SetCrtc calls
+
+The qxl driver currently destroys and recreates the
+qxl "primary" any time the first crtc is set.
+
+A side-effect of destroying the primary is mouse state
+associated with the crtc is lost, which leads to
+disappearing mouse cursors on wayland sessions.
+
+This commit changes the driver to reapply the cursor
+any time SetCrtc is called. It achieves this by keeping
+a copy of the cursor data on the qxl_crtc struct.
+
+Signed-off-by: Ray Strode <rstrode@redhat.com>
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1200901
+---
+ drivers/gpu/drm/qxl/qxl_display.c | 98 +++++++++++++++++++++++++++++++++++++++
+ drivers/gpu/drm/qxl/qxl_drv.h | 1 +
+ 2 files changed, 99 insertions(+)
+
+diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
+index 3aef127..34ab444 100644
+--- a/drivers/gpu/drm/qxl/qxl_display.c
++++ b/drivers/gpu/drm/qxl/qxl_display.c
+@@ -184,60 +184,61 @@ static struct mode_size {
+ {1440, 900},
+ {1400, 1050},
+ {1680, 1050},
+ {1600, 1200},
+ {1920, 1080},
+ {1920, 1200}
+ };
+
+ static int qxl_add_common_modes(struct drm_connector *connector,
+ unsigned pwidth,
+ unsigned pheight)
+ {
+ struct drm_device *dev = connector->dev;
+ struct drm_display_mode *mode = NULL;
+ int i;
+ for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
+ mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h,
+ 60, false, false, false);
+ if (common_modes[i].w == pwidth && common_modes[i].h == pheight)
+ mode->type |= DRM_MODE_TYPE_PREFERRED;
+ drm_mode_probed_add(connector, mode);
+ }
+ return i - 1;
+ }
+
+ static void qxl_crtc_destroy(struct drm_crtc *crtc)
+ {
+ struct qxl_crtc *qxl_crtc = to_qxl_crtc(crtc);
+
+ drm_crtc_cleanup(crtc);
++ kfree(qxl_crtc->cursor);
+ kfree(qxl_crtc);
+ }
+
+ static int qxl_crtc_page_flip(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct drm_pending_vblank_event *event,
+ uint32_t page_flip_flags)
+ {
+ struct drm_device *dev = crtc->dev;
+ struct qxl_device *qdev = dev->dev_private;
+ struct qxl_framebuffer *qfb_src = to_qxl_framebuffer(fb);
+ struct qxl_framebuffer *qfb_old = to_qxl_framebuffer(crtc->primary->fb);
+ struct qxl_bo *bo_old = gem_to_qxl_bo(qfb_old->obj);
+ struct qxl_bo *bo = gem_to_qxl_bo(qfb_src->obj);
+ unsigned long flags;
+ struct drm_clip_rect norect = {
+ .x1 = 0,
+ .y1 = 0,
+ .x2 = fb->width,
+ .y2 = fb->height
+ };
+ int inc = 1;
+ int one_clip_rect = 1;
+ int ret = 0;
+
+ crtc->primary->fb = fb;
+ bo_old->is_primary = false;
+ bo->is_primary = true;
+
+ ret = qxl_bo_reserve(bo, false);
+@@ -269,60 +270,145 @@ static int qxl_crtc_page_flip(struct drm_crtc *crtc,
+ return 0;
+ }
+
+ static int
+ qxl_hide_cursor(struct qxl_device *qdev)
+ {
+ struct qxl_release *release;
+ struct qxl_cursor_cmd *cmd;
+ int ret;
+
+ ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd), QXL_RELEASE_CURSOR_CMD,
+ &release, NULL);
+ if (ret)
+ return ret;
+
+ ret = qxl_release_reserve_list(release, true);
+ if (ret) {
+ qxl_release_free(qdev, release);
+ return ret;
+ }
+
+ cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
+ cmd->type = QXL_CURSOR_HIDE;
+ qxl_release_unmap(qdev, release, &cmd->release_info);
+
+ qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
+ qxl_release_fence_buffer_objects(release);
+ return 0;
+ }
+
++static int qxl_crtc_stash_cursor(struct drm_crtc *crtc,
++ struct qxl_cursor *cursor)
++{
++ struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
++ size_t cursor_size;
++
++ cursor_size = sizeof(struct qxl_cursor) + cursor->data_size;
++
++ if (!qcrtc->cursor || qcrtc->cursor->data_size != cursor->data_size) {
++ kfree(qcrtc->cursor);
++ qcrtc->cursor = kmalloc(cursor_size, GFP_KERNEL);
++
++ if (!qcrtc->cursor)
++ return -ENOMEM;
++ }
++
++ memcpy(qcrtc->cursor, cursor, cursor_size);
++
++ return 0;
++}
++
++static int qxl_crtc_apply_cursor(struct drm_crtc *crtc)
++{
++ struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
++ struct drm_device *dev = crtc->dev;
++ struct qxl_device *qdev = dev->dev_private;
++ struct qxl_cursor *cursor;
++ struct qxl_cursor_cmd *cmd;
++ struct qxl_bo *cursor_bo;
++ struct qxl_release *release;
++ size_t cursor_size;
++ int ret = 0;
++
++ if (!qcrtc->cursor)
++ return 0;
++
++ cursor_size = sizeof(*qcrtc->cursor) + qcrtc->cursor->data_size;
++
++ ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
++ QXL_RELEASE_CURSOR_CMD,
++ &release, NULL);
++ if (ret)
++ return ret;
++
++ ret = qxl_alloc_bo_reserved(qdev, release, cursor_size, &cursor_bo);
++ if (ret)
++ goto out_free_release;
++
++ ret = qxl_release_reserve_list(release, false);
++ if (ret)
++ goto out_free_bo;
++
++ ret = qxl_bo_kmap(cursor_bo, (void **)&cursor);
++ if (ret)
++ goto out_backoff;
++
++ memcpy(cursor, qcrtc->cursor, cursor_size);
++
++ qxl_bo_kunmap(cursor_bo);
++
++ cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
++ cmd->type = QXL_CURSOR_SET;
++ cmd->u.set.position.x = qcrtc->cur_x + qcrtc->hot_spot_x;
++ cmd->u.set.position.y = qcrtc->cur_y + qcrtc->hot_spot_y;
++
++ cmd->u.set.shape = qxl_bo_physical_address(qdev, cursor_bo, 0);
++
++ cmd->u.set.visible = 1;
++ qxl_release_unmap(qdev, release, &cmd->release_info);
++
++ qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
++ qxl_release_fence_buffer_objects(release);
++ qxl_bo_unref(&cursor_bo);
++
++ return ret;
++
++out_backoff:
++ qxl_release_backoff_reserve_list(release);
++out_free_bo:
++ qxl_bo_unref(&cursor_bo);
++out_free_release:
++ qxl_release_free(qdev, release);
++ return ret;
++}
++
+ static int qxl_crtc_cursor_set2(struct drm_crtc *crtc,
+ struct drm_file *file_priv,
+ uint32_t handle,
+ uint32_t width,
+ uint32_t height, int32_t hot_x, int32_t hot_y)
+ {
+ struct drm_device *dev = crtc->dev;
+ struct qxl_device *qdev = dev->dev_private;
+ struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
+ struct drm_gem_object *obj;
+ struct qxl_cursor *cursor;
+ struct qxl_cursor_cmd *cmd;
+ struct qxl_bo *cursor_bo, *user_bo;
+ struct qxl_release *release;
+ void *user_ptr;
+
+ int size = 64*64*4;
+ int ret = 0;
+ if (!handle)
+ return qxl_hide_cursor(qdev);
+
+ obj = drm_gem_object_lookup(file_priv, handle);
+ if (!obj) {
+ DRM_ERROR("cannot find cursor object\n");
+ return -ENOENT;
+ }
+
+ user_bo = gem_to_qxl_bo(obj);
+
+ ret = qxl_bo_reserve(user_bo, false);
+@@ -343,60 +429,66 @@ static int qxl_crtc_cursor_set2(struct drm_crtc *crtc,
+ &release, NULL);
+ if (ret)
+ goto out_kunmap;
+
+ ret = qxl_alloc_bo_reserved(qdev, release, sizeof(struct qxl_cursor) + size,
+ &cursor_bo);
+ if (ret)
+ goto out_free_release;
+
+ ret = qxl_release_reserve_list(release, false);
+ if (ret)
+ goto out_free_bo;
+
+ ret = qxl_bo_kmap(cursor_bo, (void **)&cursor);
+ if (ret)
+ goto out_backoff;
+
+ cursor->header.unique = 0;
+ cursor->header.type = SPICE_CURSOR_TYPE_ALPHA;
+ cursor->header.width = 64;
+ cursor->header.height = 64;
+ cursor->header.hot_spot_x = hot_x;
+ cursor->header.hot_spot_y = hot_y;
+ cursor->data_size = size;
+ cursor->chunk.next_chunk = 0;
+ cursor->chunk.prev_chunk = 0;
+ cursor->chunk.data_size = size;
+
+ memcpy(cursor->chunk.data, user_ptr, size);
+
++ ret = qxl_crtc_stash_cursor(crtc, cursor);
++ if (ret) {
++ DRM_ERROR("cannot save cursor, may be lost on next mode set\n");
++ ret = 0;
++ }
++
+ qxl_bo_kunmap(cursor_bo);
+
+ qxl_bo_kunmap(user_bo);
+
+ qcrtc->cur_x += qcrtc->hot_spot_x - hot_x;
+ qcrtc->cur_y += qcrtc->hot_spot_y - hot_y;
+ qcrtc->hot_spot_x = hot_x;
+ qcrtc->hot_spot_y = hot_y;
+
+ cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
+ cmd->type = QXL_CURSOR_SET;
+ cmd->u.set.position.x = qcrtc->cur_x + qcrtc->hot_spot_x;
+ cmd->u.set.position.y = qcrtc->cur_y + qcrtc->hot_spot_y;
+
+ cmd->u.set.shape = qxl_bo_physical_address(qdev, cursor_bo, 0);
+
+ cmd->u.set.visible = 1;
+ qxl_release_unmap(qdev, release, &cmd->release_info);
+
+ qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
+ qxl_release_fence_buffer_objects(release);
+
+ /* finish with the userspace bo */
+ ret = qxl_bo_reserve(user_bo, false);
+ if (!ret) {
+ qxl_bo_unpin(user_bo);
+ qxl_bo_unreserve(user_bo);
+ }
+ drm_gem_object_unreference_unlocked(obj);
+
+@@ -628,60 +720,66 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
+ x, y,
+ mode->hdisplay, mode->vdisplay,
+ adjusted_mode->hdisplay,
+ adjusted_mode->vdisplay);
+
+ if (bo->is_primary == false)
+ recreate_primary = true;
+
+ if (bo->surf.stride * bo->surf.height > qdev->vram_size) {
+ DRM_ERROR("Mode doesn't fit in vram size (vgamem)");
+ return -EINVAL;
+ }
+
+ ret = qxl_bo_reserve(bo, false);
+ if (ret != 0)
+ return ret;
+ ret = qxl_bo_pin(bo, bo->type, NULL);
+ if (ret != 0) {
+ qxl_bo_unreserve(bo);
+ return -EINVAL;
+ }
+ qxl_bo_unreserve(bo);
+ if (recreate_primary) {
+ qxl_io_destroy_primary(qdev);
+ qxl_io_log(qdev,
+ "recreate primary: %dx%d,%d,%d\n",
+ bo->surf.width, bo->surf.height,
+ bo->surf.stride, bo->surf.format);
+ qxl_io_create_primary(qdev, 0, bo);
+ bo->is_primary = true;
++
++ ret = qxl_crtc_apply_cursor(crtc);
++ if (ret) {
++ DRM_ERROR("could not set cursor after modeset");
++ ret = 0;
++ }
+ }
+
+ if (bo->is_primary) {
+ DRM_DEBUG_KMS("setting surface_id to 0 for primary surface %d on crtc %d\n", bo->surface_id, qcrtc->index);
+ surf_id = 0;
+ } else {
+ surf_id = bo->surface_id;
+ }
+
+ if (old_bo && old_bo != bo) {
+ old_bo->is_primary = false;
+ ret = qxl_bo_reserve(old_bo, false);
+ qxl_bo_unpin(old_bo);
+ qxl_bo_unreserve(old_bo);
+ }
+
+ qxl_monitors_config_set(qdev, qcrtc->index, x, y,
+ mode->hdisplay,
+ mode->vdisplay, surf_id);
+ return 0;
+ }
+
+ static void qxl_crtc_prepare(struct drm_crtc *crtc)
+ {
+ DRM_DEBUG("current: %dx%d+%d+%d (%d).\n",
+ crtc->mode.hdisplay, crtc->mode.vdisplay,
+ crtc->x, crtc->y, crtc->enabled);
+ }
+
+ static void qxl_crtc_commit(struct drm_crtc *crtc)
+diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
+index 8e633ca..6b63c54 100644
+--- a/drivers/gpu/drm/qxl/qxl_drv.h
++++ b/drivers/gpu/drm/qxl/qxl_drv.h
+@@ -110,60 +110,61 @@ struct qxl_bo {
+ void *kptr;
+ int type;
+
+ /* Constant after initialization */
+ struct drm_gem_object gem_base;
+ bool is_primary; /* is this now a primary surface */
+ bool hw_surf_alloc;
+ struct qxl_surface surf;
+ uint32_t surface_id;
+ struct qxl_release *surf_create;
+ };
+ #define gem_to_qxl_bo(gobj) container_of((gobj), struct qxl_bo, gem_base)
+ #define to_qxl_bo(tobj) container_of((tobj), struct qxl_bo, tbo)
+
+ struct qxl_gem {
+ struct mutex mutex;
+ struct list_head objects;
+ };
+
+ struct qxl_bo_list {
+ struct ttm_validate_buffer tv;
+ };
+
+ struct qxl_crtc {
+ struct drm_crtc base;
+ int index;
+ int cur_x;
+ int cur_y;
+ int hot_spot_x;
+ int hot_spot_y;
++ struct qxl_cursor *cursor;
+ };
+
+ struct qxl_output {
+ int index;
+ struct drm_connector base;
+ struct drm_encoder enc;
+ };
+
+ struct qxl_framebuffer {
+ struct drm_framebuffer base;
+ struct drm_gem_object *obj;
+ };
+
+ #define to_qxl_crtc(x) container_of(x, struct qxl_crtc, base)
+ #define drm_connector_to_qxl_output(x) container_of(x, struct qxl_output, base)
+ #define drm_encoder_to_qxl_output(x) container_of(x, struct qxl_output, enc)
+ #define to_qxl_framebuffer(x) container_of(x, struct qxl_framebuffer, base)
+
+ struct qxl_mman {
+ struct ttm_bo_global_ref bo_global_ref;
+ struct drm_global_reference mem_global_ref;
+ bool mem_global_referenced;
+ struct ttm_bo_device bdev;
+ };
+
+ struct qxl_mode_info {
+ int num_modes;
+ struct qxl_mode *modes;
+ bool mode_config_initialized;
+
+--
+2.7.4
+
diff --git a/security-selinux-overlayfs-support.patch b/security-selinux-overlayfs-support.patch
new file mode 100644
index 000000000..7149e4566
--- /dev/null
+++ b/security-selinux-overlayfs-support.patch
@@ -0,0 +1,931 @@
+From 1a93a6eac32a2853177f10e274b9b761b42356eb Mon Sep 17 00:00:00 2001
+From: Javier Martinez Canillas <javier@osg.samsung.com>
+Date: Mon, 8 Aug 2016 13:08:25 -0400
+Subject: [PATCH 01/10] security: Use IS_ENABLED() instead of checking for
+ built-in or module
+
+The IS_ENABLED() macro checks if a Kconfig symbol has been enabled
+either built-in or as a module, use that macro instead of open coding
+the same.
+
+Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
+Acked-by: Casey Schaufler <casey@schaufler-ca.com>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+---
+ security/lsm_audit.c | 2 +-
+ security/selinux/hooks.c | 12 ++++++------
+ security/smack/smack_netfilter.c | 4 ++--
+ 3 files changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/security/lsm_audit.c b/security/lsm_audit.c
+index cccbf30..5369036 100644
+--- a/security/lsm_audit.c
++++ b/security/lsm_audit.c
+@@ -99,7 +99,7 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
+ }
+ return ret;
+ }
+-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++#if IS_ENABLED(CONFIG_IPV6)
+ /**
+ * ipv6_skb_to_auditdata : fill auditdata from skb
+ * @skb : the skb
+diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
+index 13185a6..880f953 100644
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -3984,7 +3984,7 @@ out:
+ return ret;
+ }
+
+-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++#if IS_ENABLED(CONFIG_IPV6)
+
+ /* Returns error only if unable to parse addresses */
+ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
+@@ -4075,7 +4075,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
+ &ad->u.net->v4info.daddr);
+ goto okay;
+
+-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++#if IS_ENABLED(CONFIG_IPV6)
+ case PF_INET6:
+ ret = selinux_parse_skb_ipv6(skb, ad, proto);
+ if (ret)
+@@ -5029,7 +5029,7 @@ static unsigned int selinux_ipv4_forward(void *priv,
+ return selinux_ip_forward(skb, state->in, PF_INET);
+ }
+
+-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++#if IS_ENABLED(CONFIG_IPV6)
+ static unsigned int selinux_ipv6_forward(void *priv,
+ struct sk_buff *skb,
+ const struct nf_hook_state *state)
+@@ -5087,7 +5087,7 @@ static unsigned int selinux_ipv4_output(void *priv,
+ return selinux_ip_output(skb, PF_INET);
+ }
+
+-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++#if IS_ENABLED(CONFIG_IPV6)
+ static unsigned int selinux_ipv6_output(void *priv,
+ struct sk_buff *skb,
+ const struct nf_hook_state *state)
+@@ -5273,7 +5273,7 @@ static unsigned int selinux_ipv4_postroute(void *priv,
+ return selinux_ip_postroute(skb, state->out, PF_INET);
+ }
+
+-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++#if IS_ENABLED(CONFIG_IPV6)
+ static unsigned int selinux_ipv6_postroute(void *priv,
+ struct sk_buff *skb,
+ const struct nf_hook_state *state)
+@@ -6317,7 +6317,7 @@ static struct nf_hook_ops selinux_nf_ops[] = {
+ .hooknum = NF_INET_LOCAL_OUT,
+ .priority = NF_IP_PRI_SELINUX_FIRST,
+ },
+-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++#if IS_ENABLED(CONFIG_IPV6)
+ {
+ .hook = selinux_ipv6_postroute,
+ .pf = NFPROTO_IPV6,
+diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c
+index aa6bf1b..205b785 100644
+--- a/security/smack/smack_netfilter.c
++++ b/security/smack/smack_netfilter.c
+@@ -20,7 +20,7 @@
+ #include <net/inet_sock.h>
+ #include "smack.h"
+
+-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++#if IS_ENABLED(CONFIG_IPV6)
+
+ static unsigned int smack_ipv6_output(void *priv,
+ struct sk_buff *skb,
+@@ -64,7 +64,7 @@ static struct nf_hook_ops smack_nf_ops[] = {
+ .hooknum = NF_INET_LOCAL_OUT,
+ .priority = NF_IP_PRI_SELINUX_FIRST,
+ },
+-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++#if IS_ENABLED(CONFIG_IPV6)
+ {
+ .hook = smack_ipv6_output,
+ .pf = NFPROTO_IPV6,
+--
+2.7.4
+
+From 8b31f456c72e53ee97474a538bcd91bfb1b93fb7 Mon Sep 17 00:00:00 2001
+From: William Roberts <william.c.roberts@intel.com>
+Date: Mon, 8 Aug 2016 13:08:34 -0400
+Subject: [PATCH 02/10] selinux: print leading 0x on ioctlcmd audits
+
+ioctlcmd is currently printing hex numbers, but their is no leading
+0x. Thus things like ioctlcmd=1234 are misleading, as the base is
+not evident.
+
+Correct this by adding 0x as a prefix, so ioctlcmd=1234 becomes
+ioctlcmd=0x1234.
+
+Signed-off-by: William Roberts <william.c.roberts@intel.com>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+---
+ security/lsm_audit.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/security/lsm_audit.c b/security/lsm_audit.c
+index 5369036..9bf8518 100644
+--- a/security/lsm_audit.c
++++ b/security/lsm_audit.c
+@@ -257,7 +257,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
+ audit_log_format(ab, " ino=%lu", inode->i_ino);
+ }
+
+- audit_log_format(ab, " ioctlcmd=%hx", a->u.op->cmd);
++ audit_log_format(ab, " ioctlcmd=0x%hx", a->u.op->cmd);
+ break;
+ }
+ case LSM_AUDIT_DATA_DENTRY: {
+--
+2.7.4
+
+From d8ad8b49618410ddeafd78465b63a6cedd6c9484 Mon Sep 17 00:00:00 2001
+From: Vivek Goyal <vgoyal@redhat.com>
+Date: Wed, 13 Jul 2016 11:13:56 -0400
+Subject: [PATCH 03/10] security, overlayfs: provide copy up security hook for
+ unioned files
+
+Provide a security hook to label new file correctly when a file is copied
+up from lower layer to upper layer of a overlay/union mount.
+
+This hook can prepare a new set of creds which are suitable for new file
+creation during copy up. Caller will use new creds to create file and then
+revert back to old creds and release new creds.
+
+Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
+Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
+[PM: whitespace cleanup to appease checkpatch.pl]
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+---
+ fs/overlayfs/copy_up.c | 15 +++++++++++++++
+ include/linux/lsm_hooks.h | 11 +++++++++++
+ include/linux/security.h | 6 ++++++
+ security/security.c | 8 ++++++++
+ 4 files changed, 40 insertions(+)
+
+diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
+index 54e5d66..c297b1f 100644
+--- a/fs/overlayfs/copy_up.c
++++ b/fs/overlayfs/copy_up.c
+@@ -246,6 +246,8 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
+ struct dentry *upper = NULL;
+ umode_t mode = stat->mode;
+ int err;
++ const struct cred *old_creds = NULL;
++ struct cred *new_creds = NULL;
+
+ newdentry = ovl_lookup_temp(workdir, dentry);
+ err = PTR_ERR(newdentry);
+@@ -258,10 +260,23 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
+ if (IS_ERR(upper))
+ goto out1;
+
++ err = security_inode_copy_up(dentry, &new_creds);
++ if (err < 0)
++ goto out2;
++
++ if (new_creds)
++ old_creds = override_creds(new_creds);
++
+ /* Can't properly set mode on creation because of the umask */
+ stat->mode &= S_IFMT;
+ err = ovl_create_real(wdir, newdentry, stat, link, NULL, true);
+ stat->mode = mode;
++
++ if (new_creds) {
++ revert_creds(old_creds);
++ put_cred(new_creds);
++ }
++
+ if (err)
+ goto out2;
+
+diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
+index 101bf19..cb69fc8 100644
+--- a/include/linux/lsm_hooks.h
++++ b/include/linux/lsm_hooks.h
+@@ -401,6 +401,15 @@
+ * @inode contains a pointer to the inode.
+ * @secid contains a pointer to the location where result will be saved.
+ * In case of failure, @secid will be set to zero.
++ * @inode_copy_up:
++ * A file is about to be copied up from lower layer to upper layer of
++ * overlay filesystem. Security module can prepare a set of new creds
++ * and modify as need be and return new creds. Caller will switch to
++ * new creds temporarily to create new file and release newly allocated
++ * creds.
++ * @src indicates the union dentry of file that is being copied up.
++ * @new pointer to pointer to return newly allocated creds.
++ * Returns 0 on success or a negative error code on error.
+ *
+ * Security hooks for file operations
+ *
+@@ -1425,6 +1434,7 @@ union security_list_options {
+ int (*inode_listsecurity)(struct inode *inode, char *buffer,
+ size_t buffer_size);
+ void (*inode_getsecid)(struct inode *inode, u32 *secid);
++ int (*inode_copy_up)(struct dentry *src, struct cred **new);
+
+ int (*file_permission)(struct file *file, int mask);
+ int (*file_alloc_security)(struct file *file);
+@@ -1696,6 +1706,7 @@ struct security_hook_heads {
+ struct list_head inode_setsecurity;
+ struct list_head inode_listsecurity;
+ struct list_head inode_getsecid;
++ struct list_head inode_copy_up;
+ struct list_head file_permission;
+ struct list_head file_alloc_security;
+ struct list_head file_free_security;
+diff --git a/include/linux/security.h b/include/linux/security.h
+index 7831cd5..c5b0ccd 100644
+--- a/include/linux/security.h
++++ b/include/linux/security.h
+@@ -282,6 +282,7 @@ int security_inode_getsecurity(struct inode *inode, const char *name, void **buf
+ int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
+ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
+ void security_inode_getsecid(struct inode *inode, u32 *secid);
++int security_inode_copy_up(struct dentry *src, struct cred **new);
+ int security_file_permission(struct file *file, int mask);
+ int security_file_alloc(struct file *file);
+ void security_file_free(struct file *file);
+@@ -758,6 +759,11 @@ static inline void security_inode_getsecid(struct inode *inode, u32 *secid)
+ *secid = 0;
+ }
+
++static inline int security_inode_copy_up(struct dentry *src, struct cred **new)
++{
++ return 0;
++}
++
+ static inline int security_file_permission(struct file *file, int mask)
+ {
+ return 0;
+diff --git a/security/security.c b/security/security.c
+index 4838e7f..f2a7f27 100644
+--- a/security/security.c
++++ b/security/security.c
+@@ -748,6 +748,12 @@ void security_inode_getsecid(struct inode *inode, u32 *secid)
+ call_void_hook(inode_getsecid, inode, secid);
+ }
+
++int security_inode_copy_up(struct dentry *src, struct cred **new)
++{
++ return call_int_hook(inode_copy_up, 0, src, new);
++}
++EXPORT_SYMBOL(security_inode_copy_up);
++
+ int security_file_permission(struct file *file, int mask)
+ {
+ int ret;
+@@ -1684,6 +1690,8 @@ struct security_hook_heads security_hook_heads = {
+ LIST_HEAD_INIT(security_hook_heads.inode_listsecurity),
+ .inode_getsecid =
+ LIST_HEAD_INIT(security_hook_heads.inode_getsecid),
++ .inode_copy_up =
++ LIST_HEAD_INIT(security_hook_heads.inode_copy_up),
+ .file_permission =
+ LIST_HEAD_INIT(security_hook_heads.file_permission),
+ .file_alloc_security =
+--
+2.7.4
+
+From 56909eb3f559103196ecbf2c08c923e0804980fb Mon Sep 17 00:00:00 2001
+From: Vivek Goyal <vgoyal@redhat.com>
+Date: Wed, 13 Jul 2016 10:44:48 -0400
+Subject: [PATCH 04/10] selinux: Implementation for inode_copy_up() hook
+
+A file is being copied up for overlay file system. Prepare a new set of
+creds and set create_sid appropriately so that new file is created with
+appropriate label.
+
+Overlay inode has right label for both context and non-context mount
+cases. In case of non-context mount, overlay inode will have the label
+of lower file and in case of context mount, overlay inode will have
+the label from context= mount option.
+
+Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
+Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+---
+ security/selinux/hooks.c | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
+index 880f953..40597ed 100644
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -3293,6 +3293,26 @@ static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
+ *secid = isec->sid;
+ }
+
++static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
++{
++ u32 sid;
++ struct task_security_struct *tsec;
++ struct cred *new_creds = *new;
++
++ if (new_creds == NULL) {
++ new_creds = prepare_creds();
++ if (!new_creds)
++ return -ENOMEM;
++ }
++
++ tsec = new_creds->security;
++ /* Get label from overlay inode and set it in create_sid */
++ selinux_inode_getsecid(d_inode(src), &sid);
++ tsec->create_sid = sid;
++ *new = new_creds;
++ return 0;
++}
++
+ /* file security operations */
+
+ static int selinux_revalidate_file_permission(struct file *file, int mask)
+@@ -6088,6 +6108,7 @@ static struct security_hook_list selinux_hooks[] = {
+ LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
+ LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
+ LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
++ LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),
+
+ LSM_HOOK_INIT(file_permission, selinux_file_permission),
+ LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
+--
+2.7.4
+
+From 121ab822ef21914adac2fa3730efeeb8fd762473 Mon Sep 17 00:00:00 2001
+From: Vivek Goyal <vgoyal@redhat.com>
+Date: Wed, 13 Jul 2016 10:44:49 -0400
+Subject: [PATCH 05/10] security,overlayfs: Provide security hook for copy up
+ of xattrs for overlay file
+
+Provide a security hook which is called when xattrs of a file are being
+copied up. This hook is called once for each xattr and LSM can return
+0 if the security module wants the xattr to be copied up, 1 if the
+security module wants the xattr to be discarded on the copy, -EOPNOTSUPP
+if the security module does not handle/manage the xattr, or a -errno
+upon an error.
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
+Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
+[PM: whitespace cleanup for checkpatch.pl]
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+---
+ fs/overlayfs/copy_up.c | 7 +++++++
+ include/linux/lsm_hooks.h | 10 ++++++++++
+ include/linux/security.h | 6 ++++++
+ security/security.c | 8 ++++++++
+ 4 files changed, 31 insertions(+)
+
+diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
+index c297b1f..cd65f12 100644
+--- a/fs/overlayfs/copy_up.c
++++ b/fs/overlayfs/copy_up.c
+@@ -103,6 +103,13 @@ retry:
+ goto retry;
+ }
+
++ error = security_inode_copy_up_xattr(name);
++ if (error < 0 && error != -EOPNOTSUPP)
++ break;
++ if (error == 1) {
++ error = 0;
++ continue; /* Discard */
++ }
+ error = vfs_setxattr(new, name, value, size, 0);
+ if (error)
+ break;
+diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
+index cb69fc8..5797122 100644
+--- a/include/linux/lsm_hooks.h
++++ b/include/linux/lsm_hooks.h
+@@ -410,6 +410,14 @@
+ * @src indicates the union dentry of file that is being copied up.
+ * @new pointer to pointer to return newly allocated creds.
+ * Returns 0 on success or a negative error code on error.
++ * @inode_copy_up_xattr:
++ * Filter the xattrs being copied up when a unioned file is copied
++ * up from a lower layer to the union/overlay layer.
++ * @name indicates the name of the xattr.
++ * Returns 0 to accept the xattr, 1 to discard the xattr, -EOPNOTSUPP if
++ * security module does not know about attribute or a negative error code
++ * to abort the copy up. Note that the caller is responsible for reading
++ * and writing the xattrs as this hook is merely a filter.
+ *
+ * Security hooks for file operations
+ *
+@@ -1435,6 +1443,7 @@ union security_list_options {
+ size_t buffer_size);
+ void (*inode_getsecid)(struct inode *inode, u32 *secid);
+ int (*inode_copy_up)(struct dentry *src, struct cred **new);
++ int (*inode_copy_up_xattr)(const char *name);
+
+ int (*file_permission)(struct file *file, int mask);
+ int (*file_alloc_security)(struct file *file);
+@@ -1707,6 +1716,7 @@ struct security_hook_heads {
+ struct list_head inode_listsecurity;
+ struct list_head inode_getsecid;
+ struct list_head inode_copy_up;
++ struct list_head inode_copy_up_xattr;
+ struct list_head file_permission;
+ struct list_head file_alloc_security;
+ struct list_head file_free_security;
+diff --git a/include/linux/security.h b/include/linux/security.h
+index c5b0ccd..536fafd 100644
+--- a/include/linux/security.h
++++ b/include/linux/security.h
+@@ -283,6 +283,7 @@ int security_inode_setsecurity(struct inode *inode, const char *name, const void
+ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
+ void security_inode_getsecid(struct inode *inode, u32 *secid);
+ int security_inode_copy_up(struct dentry *src, struct cred **new);
++int security_inode_copy_up_xattr(const char *name);
+ int security_file_permission(struct file *file, int mask);
+ int security_file_alloc(struct file *file);
+ void security_file_free(struct file *file);
+@@ -764,6 +765,11 @@ static inline int security_inode_copy_up(struct dentry *src, struct cred **new)
+ return 0;
+ }
+
++static inline int security_inode_copy_up_xattr(const char *name)
++{
++ return -EOPNOTSUPP;
++}
++
+ static inline int security_file_permission(struct file *file, int mask)
+ {
+ return 0;
+diff --git a/security/security.c b/security/security.c
+index f2a7f27..a9e2bb9 100644
+--- a/security/security.c
++++ b/security/security.c
+@@ -754,6 +754,12 @@ int security_inode_copy_up(struct dentry *src, struct cred **new)
+ }
+ EXPORT_SYMBOL(security_inode_copy_up);
+
++int security_inode_copy_up_xattr(const char *name)
++{
++ return call_int_hook(inode_copy_up_xattr, -EOPNOTSUPP, name);
++}
++EXPORT_SYMBOL(security_inode_copy_up_xattr);
++
+ int security_file_permission(struct file *file, int mask)
+ {
+ int ret;
+@@ -1692,6 +1698,8 @@ struct security_hook_heads security_hook_heads = {
+ LIST_HEAD_INIT(security_hook_heads.inode_getsecid),
+ .inode_copy_up =
+ LIST_HEAD_INIT(security_hook_heads.inode_copy_up),
++ .inode_copy_up_xattr =
++ LIST_HEAD_INIT(security_hook_heads.inode_copy_up_xattr),
+ .file_permission =
+ LIST_HEAD_INIT(security_hook_heads.file_permission),
+ .file_alloc_security =
+--
+2.7.4
+
+From 19472b69d639d58415866bf127d5f9005038c105 Mon Sep 17 00:00:00 2001
+From: Vivek Goyal <vgoyal@redhat.com>
+Date: Wed, 13 Jul 2016 10:44:50 -0400
+Subject: [PATCH 06/10] selinux: Implementation for inode_copy_up_xattr() hook
+
+When a file is copied up in overlay, we have already created file on
+upper/ with right label and there is no need to copy up selinux
+label/xattr from lower file to upper file. In fact in case of context
+mount, we don't want to copy up label as newly created file got its label
+from context= option.
+
+Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
+Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+---
+ security/selinux/hooks.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
+index 40597ed..a2d5108 100644
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -3313,6 +3313,21 @@ static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
+ return 0;
+ }
+
++static int selinux_inode_copy_up_xattr(const char *name)
++{
++ /* The copy_up hook above sets the initial context on an inode, but we
++ * don't then want to overwrite it by blindly copying all the lower
++ * xattrs up. Instead, we have to filter out SELinux-related xattrs.
++ */
++ if (strcmp(name, XATTR_NAME_SELINUX) == 0)
++ return 1; /* Discard */
++ /*
++ * Any other attribute apart from SELINUX is not claimed, supported
++ * by selinux.
++ */
++ return -EOPNOTSUPP;
++}
++
+ /* file security operations */
+
+ static int selinux_revalidate_file_permission(struct file *file, int mask)
+@@ -6109,6 +6124,7 @@ static struct security_hook_list selinux_hooks[] = {
+ LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
+ LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
+ LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),
++ LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr),
+
+ LSM_HOOK_INIT(file_permission, selinux_file_permission),
+ LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
+--
+2.7.4
+
+From c957f6df52c509ccfbb96659fd1a0f7812de333f Mon Sep 17 00:00:00 2001
+From: Vivek Goyal <vgoyal@redhat.com>
+Date: Wed, 13 Jul 2016 10:44:51 -0400
+Subject: [PATCH 07/10] selinux: Pass security pointer to
+ determine_inode_label()
+
+Right now selinux_determine_inode_label() works on security pointer of
+current task. Soon I need this to work on a security pointer retrieved
+from a set of creds. So start passing in a pointer and caller can
+decide where to fetch security pointer from.
+
+Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
+Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+---
+ security/selinux/hooks.c | 19 ++++++++++---------
+ 1 file changed, 10 insertions(+), 9 deletions(-)
+
+diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
+index a2d5108..f9d398b 100644
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -1808,13 +1808,13 @@ out:
+ /*
+ * Determine the label for an inode that might be unioned.
+ */
+-static int selinux_determine_inode_label(struct inode *dir,
+- const struct qstr *name,
+- u16 tclass,
+- u32 *_new_isid)
++static int
++selinux_determine_inode_label(const struct task_security_struct *tsec,
++ struct inode *dir,
++ const struct qstr *name, u16 tclass,
++ u32 *_new_isid)
+ {
+ const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
+- const struct task_security_struct *tsec = current_security();
+
+ if ((sbsec->flags & SE_SBINITIALIZED) &&
+ (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
+@@ -1857,8 +1857,8 @@ static int may_create(struct inode *dir,
+ if (rc)
+ return rc;
+
+- rc = selinux_determine_inode_label(dir, &dentry->d_name, tclass,
+- &newsid);
++ rc = selinux_determine_inode_label(current_security(), dir,
++ &dentry->d_name, tclass, &newsid);
+ if (rc)
+ return rc;
+
+@@ -2838,7 +2838,8 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
+ u32 newsid;
+ int rc;
+
+- rc = selinux_determine_inode_label(d_inode(dentry->d_parent), name,
++ rc = selinux_determine_inode_label(current_security(),
++ d_inode(dentry->d_parent), name,
+ inode_mode_to_security_class(mode),
+ &newsid);
+ if (rc)
+@@ -2863,7 +2864,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
+ sid = tsec->sid;
+ newsid = tsec->create_sid;
+
+- rc = selinux_determine_inode_label(
++ rc = selinux_determine_inode_label(current_security(),
+ dir, qstr,
+ inode_mode_to_security_class(inode->i_mode),
+ &newsid);
+--
+2.7.4
+
+From 2602625b7e46576b00db619ac788c508ba3bcb2c Mon Sep 17 00:00:00 2001
+From: Vivek Goyal <vgoyal@redhat.com>
+Date: Wed, 13 Jul 2016 10:44:52 -0400
+Subject: [PATCH 08/10] security, overlayfs: Provide hook to correctly label
+ newly created files
+
+During a new file creation we need to make sure new file is created with the
+right label. New file is created in upper/ so effectively file should get
+label as if task had created file in upper/.
+
+We switched to mounter's creds for actual file creation. Also if there is a
+whiteout present, then file will be created in work/ dir first and then
+renamed in upper. In none of the cases file will be labeled as we want it to
+be.
+
+This patch introduces a new hook dentry_create_files_as(), which determines
+the label/context dentry will get if it had been created by task in upper
+and modify passed set of creds appropriately. Caller makes use of these new
+creds for file creation.
+
+Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
+Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
+[PM: fix whitespace issues found with checkpatch.pl]
+[PM: changes to use stat->mode in ovl_create_or_link()]
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+---
+ fs/overlayfs/dir.c | 10 ++++++++++
+ include/linux/lsm_hooks.h | 15 +++++++++++++++
+ include/linux/security.h | 12 ++++++++++++
+ security/security.c | 11 +++++++++++
+ 4 files changed, 48 insertions(+)
+
+diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
+index 12bcd07..a155e52 100644
+--- a/fs/overlayfs/dir.c
++++ b/fs/overlayfs/dir.c
+@@ -435,6 +435,15 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
+ if (override_cred) {
+ override_cred->fsuid = inode->i_uid;
+ override_cred->fsgid = inode->i_gid;
++ if (!hardlink) {
++ err = security_dentry_create_files_as(dentry,
++ stat->mode, &dentry->d_name, old_cred,
++ override_cred);
++ if (err) {
++ put_cred(override_cred);
++ goto out_revert_creds;
++ }
++ }
+ put_cred(override_creds(override_cred));
+ put_cred(override_cred);
+
+@@ -445,6 +454,7 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
+ err = ovl_create_over_whiteout(dentry, inode, stat,
+ link, hardlink);
+ }
++out_revert_creds:
+ revert_creds(old_cred);
+ if (!err) {
+ struct inode *realinode = d_inode(ovl_dentry_upper(dentry));
+diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
+index 5797122..f2af2af 100644
+--- a/include/linux/lsm_hooks.h
++++ b/include/linux/lsm_hooks.h
+@@ -151,6 +151,16 @@
+ * @name name of the last path component used to create file
+ * @ctx pointer to place the pointer to the resulting context in.
+ * @ctxlen point to place the length of the resulting context.
++ * @dentry_create_files_as:
++ * Compute a context for a dentry as the inode is not yet available
++ * and set that context in passed in creds so that new files are
++ * created using that context. Context is calculated using the
++ * passed in creds and not the creds of the caller.
++ * @dentry dentry to use in calculating the context.
++ * @mode mode used to determine resource type.
++ * @name name of the last path component used to create file
++ * @old creds which should be used for context calculation
++ * @new creds to modify
+ *
+ *
+ * Security hooks for inode operations.
+@@ -1375,6 +1385,10 @@ union security_list_options {
+ int (*dentry_init_security)(struct dentry *dentry, int mode,
+ const struct qstr *name, void **ctx,
+ u32 *ctxlen);
++ int (*dentry_create_files_as)(struct dentry *dentry, int mode,
++ struct qstr *name,
++ const struct cred *old,
++ struct cred *new);
+
+
+ #ifdef CONFIG_SECURITY_PATH
+@@ -1675,6 +1689,7 @@ struct security_hook_heads {
+ struct list_head sb_clone_mnt_opts;
+ struct list_head sb_parse_opts_str;
+ struct list_head dentry_init_security;
++ struct list_head dentry_create_files_as;
+ #ifdef CONFIG_SECURITY_PATH
+ struct list_head path_unlink;
+ struct list_head path_mkdir;
+diff --git a/include/linux/security.h b/include/linux/security.h
+index 536fafd..a6c6d5d 100644
+--- a/include/linux/security.h
++++ b/include/linux/security.h
+@@ -242,6 +242,10 @@ int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);
+ int security_dentry_init_security(struct dentry *dentry, int mode,
+ const struct qstr *name, void **ctx,
+ u32 *ctxlen);
++int security_dentry_create_files_as(struct dentry *dentry, int mode,
++ struct qstr *name,
++ const struct cred *old,
++ struct cred *new);
+
+ int security_inode_alloc(struct inode *inode);
+ void security_inode_free(struct inode *inode);
+@@ -600,6 +604,14 @@ static inline int security_dentry_init_security(struct dentry *dentry,
+ return -EOPNOTSUPP;
+ }
+
++static inline int security_dentry_create_files_as(struct dentry *dentry,
++ int mode, struct qstr *name,
++ const struct cred *old,
++ struct cred *new)
++{
++ return 0;
++}
++
+
+ static inline int security_inode_init_security(struct inode *inode,
+ struct inode *dir,
+diff --git a/security/security.c b/security/security.c
+index a9e2bb9..f825304 100644
+--- a/security/security.c
++++ b/security/security.c
+@@ -364,6 +364,15 @@ int security_dentry_init_security(struct dentry *dentry, int mode,
+ }
+ EXPORT_SYMBOL(security_dentry_init_security);
+
++int security_dentry_create_files_as(struct dentry *dentry, int mode,
++ struct qstr *name,
++ const struct cred *old, struct cred *new)
++{
++ return call_int_hook(dentry_create_files_as, 0, dentry, mode,
++ name, old, new);
++}
++EXPORT_SYMBOL(security_dentry_create_files_as);
++
+ int security_inode_init_security(struct inode *inode, struct inode *dir,
+ const struct qstr *qstr,
+ const initxattrs initxattrs, void *fs_data)
+@@ -1635,6 +1644,8 @@ struct security_hook_heads security_hook_heads = {
+ LIST_HEAD_INIT(security_hook_heads.sb_parse_opts_str),
+ .dentry_init_security =
+ LIST_HEAD_INIT(security_hook_heads.dentry_init_security),
++ .dentry_create_files_as =
++ LIST_HEAD_INIT(security_hook_heads.dentry_create_files_as),
+ #ifdef CONFIG_SECURITY_PATH
+ .path_unlink = LIST_HEAD_INIT(security_hook_heads.path_unlink),
+ .path_mkdir = LIST_HEAD_INIT(security_hook_heads.path_mkdir),
+--
+2.7.4
+
+From a518b0a5b0d7f3397e065acb956bca9635aa892d Mon Sep 17 00:00:00 2001
+From: Vivek Goyal <vgoyal@redhat.com>
+Date: Wed, 13 Jul 2016 10:44:53 -0400
+Subject: [PATCH 09/10] selinux: Implement dentry_create_files_as() hook
+
+Calculate what would be the label of newly created file and set that
+secid in the passed creds.
+
+Context of the task which is actually creating file is retrieved from
+set of creds passed in. (old->security).
+
+Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
+Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+---
+ security/selinux/hooks.c | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
+index f9d398b..e15e560 100644
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -2848,6 +2848,27 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
+ return security_sid_to_context(newsid, (char **)ctx, ctxlen);
+ }
+
++static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
++ struct qstr *name,
++ const struct cred *old,
++ struct cred *new)
++{
++ u32 newsid;
++ int rc;
++ struct task_security_struct *tsec;
++
++ rc = selinux_determine_inode_label(old->security,
++ d_inode(dentry->d_parent), name,
++ inode_mode_to_security_class(mode),
++ &newsid);
++ if (rc)
++ return rc;
++
++ tsec = new->security;
++ tsec->create_sid = newsid;
++ return 0;
++}
++
+ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
+ const struct qstr *qstr,
+ const char **name,
+@@ -6098,6 +6119,7 @@ static struct security_hook_list selinux_hooks[] = {
+ LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str),
+
+ LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
++ LSM_HOOK_INIT(dentry_create_files_as, selinux_dentry_create_files_as),
+
+ LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
+ LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
+--
+2.7.4
+
+From 348a0db9e69e4c214bf5d7677f17cb99cdc47db0 Mon Sep 17 00:00:00 2001
+From: William Roberts <william.c.roberts@intel.com>
+Date: Mon, 15 Aug 2016 12:42:12 -0700
+Subject: [PATCH 10/10] selinux: drop SECURITY_SELINUX_POLICYDB_VERSION_MAX
+
+Remove the SECURITY_SELINUX_POLICYDB_VERSION_MAX Kconfig option
+
+Per: https://github.com/SELinuxProject/selinux/wiki/Kernel-Todo
+
+This was only needed on Fedora 3 and 4 and just causes issues now,
+so drop it.
+
+The MAX and MIN should just be whatever the kernel can support.
+
+Signed-off-by: William Roberts <william.c.roberts@intel.com>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+---
+ security/selinux/Kconfig | 38 -------------------------------------
+ security/selinux/include/security.h | 4 ----
+ 2 files changed, 42 deletions(-)
+
+diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
+index 8691e92..ea7e3ef 100644
+--- a/security/selinux/Kconfig
++++ b/security/selinux/Kconfig
+@@ -93,41 +93,3 @@ config SECURITY_SELINUX_CHECKREQPROT_VALUE
+ via /selinux/checkreqprot if authorized by policy.
+
+ If you are unsure how to answer this question, answer 0.
+-
+-config SECURITY_SELINUX_POLICYDB_VERSION_MAX
+- bool "NSA SELinux maximum supported policy format version"
+- depends on SECURITY_SELINUX
+- default n
+- help
+- This option enables the maximum policy format version supported
+- by SELinux to be set to a particular value. This value is reported
+- to userspace via /selinux/policyvers and used at policy load time.
+- It can be adjusted downward to support legacy userland (init) that
+- does not correctly handle kernels that support newer policy versions.
+-
+- Examples:
+- For the Fedora Core 3 or 4 Linux distributions, enable this option
+- and set the value via the next option. For Fedora Core 5 and later,
+- do not enable this option.
+-
+- If you are unsure how to answer this question, answer N.
+-
+-config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
+- int "NSA SELinux maximum supported policy format version value"
+- depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX
+- range 15 23
+- default 19
+- help
+- This option sets the value for the maximum policy format version
+- supported by SELinux.
+-
+- Examples:
+- For Fedora Core 3, use 18.
+- For Fedora Core 4, use 19.
+-
+- If you are unsure how to answer this question, look for the
+- policy format version supported by your policy toolchain, by
+- running 'checkpolicy -V'. Or look at what policy you have
+- installed under /etc/selinux/$SELINUXTYPE/policy, where
+- SELINUXTYPE is defined in your /etc/selinux/config.
+-
+diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
+index 38feb55..308a286 100644
+--- a/security/selinux/include/security.h
++++ b/security/selinux/include/security.h
+@@ -39,11 +39,7 @@
+
+ /* Range of policy versions we understand*/
+ #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
+-#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
+-#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
+-#else
+ #define POLICYDB_VERSION_MAX POLICYDB_VERSION_XPERMS_IOCTL
+-#endif
+
+ /* Mask for just the mount related flags */
+ #define SE_MNTMASK 0x0f
+--
+2.7.4
+
diff --git a/sources b/sources
index 1c5ba6130..07d525ab6 100644
--- a/sources
+++ b/sources
@@ -1,3 +1,3 @@
-5276563eb1f39a048e4a8a887408c031 linux-4.7.tar.xz
-fe259c02c75eec61d1aa4b1211f3c853 perf-man-4.7.tar.gz
-b9fd64120635788b6219f82392cedcb9 patch-4.7.10.xz
+c1af0afbd3df35c1ccdc7a5118cd2d07 linux-4.8.tar.xz
+0dad03f586e835d538d3e0d2cbdb9a28 perf-man-4.8.tar.gz
+666753363fd69ac2c1a94f4349a7197e patch-4.8.6.xz
diff --git a/tip-x86-boot-x86-KASLR-x86-power-Remove-x86-hibernation-restrictions.patch b/tip-x86-boot-x86-KASLR-x86-power-Remove-x86-hibernation-restrictions.patch
deleted file mode 100644
index 7d79fbcef..000000000
--- a/tip-x86-boot-x86-KASLR-x86-power-Remove-x86-hibernation-restrictions.patch
+++ /dev/null
@@ -1,131 +0,0 @@
-From patchwork Sun Jun 26 11:01:18 2016
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [tip:x86/boot] x86/KASLR,
- x86/power: Remove x86 hibernation restrictions
-From: tip-bot for Jacob Shin <tipbot@zytor.com>
-X-Patchwork-Id: 9199367
-Message-Id: <tip-65fe935dd2387a4faf15314c73f5e6d31ef0217e@git.kernel.org>
-To: linux-tip-commits@vger.kernel.org
-Cc: pavel@ucw.cz, linux-pm@vger.kernel.org, yinghai@kernel.org,
- mingo@kernel.org, linux-kernel@vger.kernel.org, tglx@linutronix.de,
- corbet@lwn.net, dvlasenk@redhat.com, sds@tycho.nsa.gov,
- peterz@infradead.org, logang@deltatee.com, bhe@redhat.com,
- torvalds@linux-foundation.org, bp@alien8.de, luto@kernel.org,
- keescook@chromium.org, hpa@zytor.com, brgerst@gmail.com,
- len.brown@intel.com
-Date: Sun, 26 Jun 2016 04:01:18 -0700
-
-Commit-ID: 65fe935dd2387a4faf15314c73f5e6d31ef0217e
-Gitweb: http://git.kernel.org/tip/65fe935dd2387a4faf15314c73f5e6d31ef0217e
-Author: Kees Cook <keescook@chromium.org>
-AuthorDate: Mon, 13 Jun 2016 15:10:02 -0700
-Committer: Ingo Molnar <mingo@kernel.org>
-CommitDate: Sun, 26 Jun 2016 12:32:03 +0200
-
-x86/KASLR, x86/power: Remove x86 hibernation restrictions
-
-With the following fix:
-
- 70595b479ce1 ("x86/power/64: Fix crash whan the hibernation code passes control to the image kernel")
-
-... there is no longer a problem with hibernation resuming a
-KASLR-booted kernel image, so remove the restriction.
-
-Signed-off-by: Kees Cook <keescook@chromium.org>
-Cc: Andy Lutomirski <luto@kernel.org>
-Cc: Baoquan He <bhe@redhat.com>
-Cc: Borislav Petkov <bp@alien8.de>
-Cc: Brian Gerst <brgerst@gmail.com>
-Cc: Denys Vlasenko <dvlasenk@redhat.com>
-Cc: H. Peter Anvin <hpa@zytor.com>
-Cc: Jonathan Corbet <corbet@lwn.net>
-Cc: Len Brown <len.brown@intel.com>
-Cc: Linus Torvalds <torvalds@linux-foundation.org>
-Cc: Linux PM list <linux-pm@vger.kernel.org>
-Cc: Logan Gunthorpe <logang@deltatee.com>
-Cc: Pavel Machek <pavel@ucw.cz>
-Cc: Peter Zijlstra <peterz@infradead.org>
-Cc: Stephen Smalley <sds@tycho.nsa.gov>
-Cc: Thomas Gleixner <tglx@linutronix.de>
-Cc: Yinghai Lu <yinghai@kernel.org>
-Cc: linux-doc@vger.kernel.org
-Link: http://lkml.kernel.org/r/20160613221002.GA29719@www.outflux.net
-Signed-off-by: Ingo Molnar <mingo@kernel.org>
----
- Documentation/kernel-parameters.txt | 10 ++++------
- arch/x86/boot/compressed/kaslr.c | 7 -------
- kernel/power/hibernate.c | 6 ------
- 3 files changed, 4 insertions(+), 19 deletions(-)
-
---
-To unsubscribe from this list: send the line "unsubscribe linux-pm" in
-the body of a message to majordomo@vger.kernel.org
-More majordomo info at http://vger.kernel.org/majordomo-info.html
-
-diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
-index 82b42c9..fa8c6d4 100644
---- a/Documentation/kernel-parameters.txt
-+++ b/Documentation/kernel-parameters.txt
-@@ -1803,12 +1803,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
- js= [HW,JOY] Analog joystick
- See Documentation/input/joystick.txt.
-
-- kaslr/nokaslr [X86]
-- Enable/disable kernel and module base offset ASLR
-- (Address Space Layout Randomization) if built into
-- the kernel. When CONFIG_HIBERNATION is selected,
-- kASLR is disabled by default. When kASLR is enabled,
-- hibernation will be disabled.
-+ nokaslr [KNL]
-+ When CONFIG_RANDOMIZE_BASE is set, this disables
-+ kernel and module base offset ASLR (Address Space
-+ Layout Randomization).
-
- keepinitrd [HW,ARM]
-
-diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
-index cfeb025..dff4217 100644
---- a/arch/x86/boot/compressed/kaslr.c
-+++ b/arch/x86/boot/compressed/kaslr.c
-@@ -471,17 +471,10 @@ unsigned char *choose_random_location(unsigned long input,
- unsigned long choice = output;
- unsigned long random_addr;
-
--#ifdef CONFIG_HIBERNATION
-- if (!cmdline_find_option_bool("kaslr")) {
-- warn("KASLR disabled: 'kaslr' not on cmdline (hibernation selected).");
-- goto out;
-- }
--#else
- if (cmdline_find_option_bool("nokaslr")) {
- warn("KASLR disabled: 'nokaslr' on cmdline.");
- goto out;
- }
--#endif
-
- boot_params->hdr.loadflags |= KASLR_FLAG;
-
-diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
-index fca9254..9021387 100644
---- a/kernel/power/hibernate.c
-+++ b/kernel/power/hibernate.c
-@@ -1154,11 +1154,6 @@ static int __init nohibernate_setup(char *str)
- return 1;
- }
-
--static int __init kaslr_nohibernate_setup(char *str)
--{
-- return nohibernate_setup(str);
--}
--
- static int __init page_poison_nohibernate_setup(char *str)
- {
- #ifdef CONFIG_PAGE_POISONING_ZERO
-@@ -1182,5 +1177,4 @@ __setup("hibernate=", hibernate_setup);
- __setup("resumewait", resumewait_setup);
- __setup("resumedelay=", resumedelay_setup);
- __setup("nohibernate", nohibernate_setup);
--__setup("kaslr", kaslr_nohibernate_setup);
- __setup("page_poison=", page_poison_nohibernate_setup);
diff --git a/v3-vfio-pci-Fix-integer-overflows-bitmask-check.patch b/v3-vfio-pci-Fix-integer-overflows-bitmask-check.patch
new file mode 100644
index 000000000..5278d4486
--- /dev/null
+++ b/v3-vfio-pci-Fix-integer-overflows-bitmask-check.patch
@@ -0,0 +1,102 @@
+From patchwork Wed Oct 12 16:51:24 2016
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v3] vfio/pci: Fix integer overflows, bitmask check
+From: Vlad Tsyrklevich <vlad@tsyrklevich.net>
+X-Patchwork-Id: 9373631
+Message-Id: <1476291084-50737-1-git-send-email-vlad@tsyrklevich.net>
+To: kvm@vger.kernel.org
+Cc: alex.williamson@redhat.com, Vlad Tsyrklevich <vlad@tsyrklevich.net>
+Date: Wed, 12 Oct 2016 18:51:24 +0200
+
+The VFIO_DEVICE_SET_IRQS ioctl did not sufficiently sanitize
+user-supplied integers, potentially allowing memory corruption. This
+patch adds appropriate integer overflow checks, checks the range bounds
+for VFIO_IRQ_SET_DATA_NONE, and also verifies that only single element
+in the VFIO_IRQ_SET_DATA_TYPE_MASK bitmask is set.
+VFIO_IRQ_SET_ACTION_TYPE_MASK is already correctly checked later in
+vfio_pci_set_irqs_ioctl().
+
+Furthermore, a kzalloc is changed to a kcalloc because the use of a
+kzalloc with an integer multiplication allowed an integer overflow
+condition to be reached without this patch. kcalloc checks for overflow
+and should prevent a similar occurrence.
+
+Signed-off-by: Vlad Tsyrklevich <vlad@tsyrklevich.net>
+---
+ drivers/vfio/pci/vfio_pci.c | 33 +++++++++++++++++++++------------
+ drivers/vfio/pci/vfio_pci_intrs.c | 2 +-
+ 2 files changed, 22 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
+index d624a52..031bc08 100644
+--- a/drivers/vfio/pci/vfio_pci.c
++++ b/drivers/vfio/pci/vfio_pci.c
+@@ -829,8 +829,9 @@ static long vfio_pci_ioctl(void *device_data,
+
+ } else if (cmd == VFIO_DEVICE_SET_IRQS) {
+ struct vfio_irq_set hdr;
++ size_t size;
+ u8 *data = NULL;
+- int ret = 0;
++ int max, ret = 0;
+
+ minsz = offsetofend(struct vfio_irq_set, count);
+
+@@ -838,23 +839,31 @@ static long vfio_pci_ioctl(void *device_data,
+ return -EFAULT;
+
+ if (hdr.argsz < minsz || hdr.index >= VFIO_PCI_NUM_IRQS ||
++ hdr.count >= (U32_MAX - hdr.start) ||
+ hdr.flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK |
+ VFIO_IRQ_SET_ACTION_TYPE_MASK))
+ return -EINVAL;
+
+- if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) {
+- size_t size;
+- int max = vfio_pci_get_irq_count(vdev, hdr.index);
++ max = vfio_pci_get_irq_count(vdev, hdr.index);
++ if (hdr.start >= max || hdr.start + hdr.count > max)
++ return -EINVAL;
+
+- if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL)
+- size = sizeof(uint8_t);
+- else if (hdr.flags & VFIO_IRQ_SET_DATA_EVENTFD)
+- size = sizeof(int32_t);
+- else
+- return -EINVAL;
++ switch (hdr.flags & VFIO_IRQ_SET_DATA_TYPE_MASK) {
++ case VFIO_IRQ_SET_DATA_NONE:
++ size = 0;
++ break;
++ case VFIO_IRQ_SET_DATA_BOOL:
++ size = sizeof(uint8_t);
++ break;
++ case VFIO_IRQ_SET_DATA_EVENTFD:
++ size = sizeof(int32_t);
++ break;
++ default:
++ return -EINVAL;
++ }
+
+- if (hdr.argsz - minsz < hdr.count * size ||
+- hdr.start >= max || hdr.start + hdr.count > max)
++ if (size) {
++ if (hdr.argsz - minsz < hdr.count * size)
+ return -EINVAL;
+
+ data = memdup_user((void __user *)(arg + minsz),
+diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
+index c2e6089..1c46045 100644
+--- a/drivers/vfio/pci/vfio_pci_intrs.c
++++ b/drivers/vfio/pci/vfio_pci_intrs.c
+@@ -256,7 +256,7 @@ static int vfio_msi_enable(struct vfio_pci_device *vdev, int nvec, bool msix)
+ if (!is_irq_none(vdev))
+ return -EINVAL;
+
+- vdev->ctx = kzalloc(nvec * sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL);
++ vdev->ctx = kcalloc(nvec, sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL);
+ if (!vdev->ctx)
+ return -ENOMEM;
+