summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorgraysky2023-01-26 08:05:12 -0500
committergraysky2023-01-26 08:05:12 -0500
commit3149fefa46f8290285eb5f6efc0215fd23509baa (patch)
tree6a237f80b6cc88acd5ba793a2bfec26f81f85c55
parent1f3a325b9232a59c3d4dd4c86c4f3caf12bef906 (diff)
downloadaur-3149fefa46f8290285eb5f6efc0215fd23509baa.tar.gz
Update to 6.1.8-1
-rw-r--r--.SRCINFO28
-rw-r--r--0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-C.patch4
-rw-r--r--0002-Revert-drm-display-dp_mst-Move-all-payload-info-into.patch2479
-rw-r--r--0002-Revert-drm-i915-improve-the-catch-all-evict-to-handl.patch231
-rw-r--r--0003-btrfs-fix-invalid-leaf-access-due-to-inline-extent-d.patch67
-rw-r--r--0003-drm-i915-improve-the-catch-all-evict-to-handle-lock-.patch260
-rw-r--r--0004-drm-amdgpu-display-mst-Fix-mst_state-pbn_div-and-slo.patch88
-rw-r--r--0004-wifi-mac80211-fix-initialization-of-rx-link-and-rx-l.patch459
-rw-r--r--0005-drm-amdgpu-display-mst-limit-payload-to-be-updated-o.patch105
-rw-r--r--0006-drm-amdgpu-display-mst-update-mst_mgr-relevant-varia.patch73
-rw-r--r--0007-drm-display-dp_mst-Correct-the-kref-of-port.patch44
-rw-r--r--PKGBUILD24
12 files changed, 835 insertions, 3027 deletions
diff --git a/.SRCINFO b/.SRCINFO
index cfb139e3361b..316ab49794db 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,5 +1,5 @@
pkgbase = linux-ck
- pkgver = 6.1.7
+ pkgver = 6.1.8
pkgrel = 1
url = https://wiki.archlinux.org/index.php/Linux-ck
arch = x86_64
@@ -12,26 +12,32 @@ pkgbase = linux-ck
makedepends = tar
makedepends = xz
options = !strip
- source = https://www.kernel.org/pub/linux/kernel/v6.x/linux-6.1.7.tar.xz
- source = https://www.kernel.org/pub/linux/kernel/v6.x/linux-6.1.7.tar.sign
+ source = https://www.kernel.org/pub/linux/kernel/v6.x/linux-6.1.8.tar.xz
+ source = https://www.kernel.org/pub/linux/kernel/v6.x/linux-6.1.8.tar.sign
source = config
source = more-uarches-20221217.tar.gz::https://github.com/graysky2/kernel_compiler_patch/archive/20221217.tar.gz
source = ck-hrtimer-fdbdf7e0ec56cd59e11d024c473e766429271a5c.tar.gz::https://github.com/graysky2/linux-patches/archive/fdbdf7e0ec56cd59e11d024c473e766429271a5c.tar.gz
source = 0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-C.patch
- source = 0002-Revert-drm-display-dp_mst-Move-all-payload-info-into.patch
- source = 0003-btrfs-fix-invalid-leaf-access-due-to-inline-extent-d.patch
- source = 0004-wifi-mac80211-fix-initialization-of-rx-link-and-rx-l.patch
+ source = 0002-Revert-drm-i915-improve-the-catch-all-evict-to-handl.patch
+ source = 0003-drm-i915-improve-the-catch-all-evict-to-handle-lock-.patch
+ source = 0004-drm-amdgpu-display-mst-Fix-mst_state-pbn_div-and-slo.patch
+ source = 0005-drm-amdgpu-display-mst-limit-payload-to-be-updated-o.patch
+ source = 0006-drm-amdgpu-display-mst-update-mst_mgr-relevant-varia.patch
+ source = 0007-drm-display-dp_mst-Correct-the-kref-of-port.patch
validpgpkeys = ABAF11C65A2970B130ABE3C479BE3E4300411886
validpgpkeys = 647F28654894E3BD457199BE38DBBDC86092693E
- sha256sums = 4ab048bad2e7380d3b827f1fad5ad2d2fc4f2e80e1c604d85d1f8781debe600f
+ sha256sums = b60bb53ab8ba370a270454b11e93d41af29126fc72bd6ede517673e2e57b816d
sha256sums = SKIP
sha256sums = 1efa33aea067fa920880ef7fef3ec82f8d4cde21213eda34ac6534ca6879fca0
sha256sums = f1d586e111932890ad5e0df15d092fb9b3f87bae4ea17812aae9b0ec98fe2db0
sha256sums = 6d3b9cb4639c1c5eb4e2697aed0dbffa5b4a37d63a0861dec8315dd052723e0e
- sha256sums = b28485e4b036abc85725f9c3ee036b83b31905f35567088f5c4b678371832c42
- sha256sums = de5af5d1bad793cf3959df743f50a07421156e3e5e7ec95999f78089c2df2b17
- sha256sums = 2ef9b1da56c0ccc615112713a516a2f6e275d3cde5d0aab2666c43a12d065443
- sha256sums = 68cc969cb5f4c5e1733260230cf13f64a1c59289b770058cd960f1550fe4d71f
+ sha256sums = dd0a155f8be7face604741716e5ea1ccd47c7988d4db4476f9736def57a6ae86
+ sha256sums = b734f0f038647618617226794298b1cc7f6928dd43d46f056486a7d664fff3e0
+ sha256sums = b725cde6ef68dcb2fe59a1e8646938d95d25a7292910dceef1adaeae229749e6
+ sha256sums = 1aaa3c58e4129804eb704fbb66e1fe9a18d37059516f4153bb375a406a3c373a
+ sha256sums = 6448060153217445d35f0f2191424acac53defe7a67f08cb7f7347c141bd535e
+ sha256sums = a3c9ed15a33b7e7f1f589e6b0b00482b78aa7a0044940e4e3f87ad542db9308e
+ sha256sums = 28d3e5daa705da23bdafc916695bc50cc8f65655c8965fb6d007d67dfa6cb52f
pkgname = linux-ck
pkgdesc = The Linux kernel and modules with ck's hrtimer patches
diff --git a/0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-C.patch b/0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-C.patch
index 80ecb83d2573..d42ab9ecebe1 100644
--- a/0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-C.patch
+++ b/0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-C.patch
@@ -1,7 +1,7 @@
-From 9bec448ab7f53d02d88aaf0dd5d3683fb163a54c Mon Sep 17 00:00:00 2001
+From 73febcbf40df1fb410fa3211ef7a8b539fe762a6 Mon Sep 17 00:00:00 2001
From: "Jan Alexander Steffens (heftig)" <jan.steffens@gmail.com>
Date: Mon, 16 Sep 2019 04:53:20 +0200
-Subject: [PATCH 1/5] ZEN: Add sysctl and CONFIG to disallow unprivileged
+Subject: [PATCH 1/8] ZEN: Add sysctl and CONFIG to disallow unprivileged
CLONE_NEWUSER
Our default behavior continues to match the vanilla kernel.
diff --git a/0002-Revert-drm-display-dp_mst-Move-all-payload-info-into.patch b/0002-Revert-drm-display-dp_mst-Move-all-payload-info-into.patch
deleted file mode 100644
index 19ab5655d2cd..000000000000
--- a/0002-Revert-drm-display-dp_mst-Move-all-payload-info-into.patch
+++ /dev/null
@@ -1,2479 +0,0 @@
-From 96c2a11329533bb221e884bc8b91c6fc2f305dd8 Mon Sep 17 00:00:00 2001
-From: Wayne Lin <Wayne.Lin@amd.com>
-Date: Thu, 12 Jan 2023 16:50:44 +0800
-Subject: [PATCH 2/5] Revert "drm/display/dp_mst: Move all payload info into
- the atomic state"
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This reverts commit 4d07b0bc403403438d9cf88450506240c5faf92f.
-
-[Why]
-Changes cause regression on amdgpu mst.
-E.g.
-In fill_dc_mst_payload_table_from_drm(), amdgpu expects to add/remove payload
-one by one and call fill_dc_mst_payload_table_from_drm() to update the HW
-maintained payload table. But previous change tries to go through all the
-payloads in mst_state and update amdpug hw maintained table in once everytime
-driver only tries to add/remove a specific payload stream only. The newly
-design idea conflicts with the implementation in amdgpu nowadays.
-
-[How]
-Revert this patch first. After addressing all regression problems caused by
-this previous patch, will add it back and adjust it.
-
-Signed-off-by: Wayne Lin <Wayne.Lin@amd.com>
-Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2171
-Cc: stable@vger.kernel.org # 6.1
-Cc: Lyude Paul <lyude@redhat.com>
-Cc: Harry Wentland <harry.wentland@amd.com>
-Cc: Mario Limonciello <mario.limonciello@amd.com>
-Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
-Cc: Ben Skeggs <bskeggs@redhat.com>
-Cc: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
-Cc: Fangzhi Zuo <Jerry.Zuo@amd.com>
-Cherry-picked-for: https://bugs.archlinux.org/task/76934
----
- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 53 +-
- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 104 ++-
- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 87 ++-
- .../amd/display/include/link_service_types.h | 3 -
- drivers/gpu/drm/display/drm_dp_mst_topology.c | 724 ++++++++++++------
- drivers/gpu/drm/i915/display/intel_dp_mst.c | 64 +-
- drivers/gpu/drm/i915/display/intel_hdcp.c | 24 +-
- drivers/gpu/drm/nouveau/dispnv50/disp.c | 169 ++--
- include/drm/display/drm_dp_mst_helper.h | 178 +++--
- 9 files changed, 876 insertions(+), 530 deletions(-)
-
-diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
-index dacad8b85963..40defd664b49 100644
---- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
-+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
-@@ -6460,7 +6460,6 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
- const struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
- struct drm_dp_mst_topology_mgr *mst_mgr;
- struct drm_dp_mst_port *mst_port;
-- struct drm_dp_mst_topology_state *mst_state;
- enum dc_color_depth color_depth;
- int clock, bpp = 0;
- bool is_y420 = false;
-@@ -6474,13 +6473,6 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
- if (!crtc_state->connectors_changed && !crtc_state->mode_changed)
- return 0;
-
-- mst_state = drm_atomic_get_mst_topology_state(state, mst_mgr);
-- if (IS_ERR(mst_state))
-- return PTR_ERR(mst_state);
--
-- if (!mst_state->pbn_div)
-- mst_state->pbn_div = dm_mst_get_pbn_divider(aconnector->mst_port->dc_link);
--
- if (!state->duplicated) {
- int max_bpc = conn_state->max_requested_bpc;
- is_y420 = drm_mode_is_420_also(&connector->display_info, adjusted_mode) &&
-@@ -6492,10 +6484,11 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
- clock = adjusted_mode->clock;
- dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp, false);
- }
--
-- dm_new_connector_state->vcpi_slots =
-- drm_dp_atomic_find_time_slots(state, mst_mgr, mst_port,
-- dm_new_connector_state->pbn);
-+ dm_new_connector_state->vcpi_slots = drm_dp_atomic_find_time_slots(state,
-+ mst_mgr,
-+ mst_port,
-+ dm_new_connector_state->pbn,
-+ dm_mst_get_pbn_divider(aconnector->dc_link));
- if (dm_new_connector_state->vcpi_slots < 0) {
- DRM_DEBUG_ATOMIC("failed finding vcpi slots: %d\n", (int)dm_new_connector_state->vcpi_slots);
- return dm_new_connector_state->vcpi_slots;
-@@ -6566,14 +6559,17 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
- dm_conn_state->vcpi_slots = slot_num;
-
- ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->port,
-- dm_conn_state->pbn, false);
-+ dm_conn_state->pbn, 0, false);
- if (ret < 0)
- return ret;
-
- continue;
- }
-
-- vcpi = drm_dp_mst_atomic_enable_dsc(state, aconnector->port, pbn, true);
-+ vcpi = drm_dp_mst_atomic_enable_dsc(state,
-+ aconnector->port,
-+ pbn, pbn_div,
-+ true);
- if (vcpi < 0)
- return vcpi;
-
-@@ -9407,6 +9403,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
- struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state;
- #if defined(CONFIG_DRM_AMD_DC_DCN)
- struct dsc_mst_fairness_vars vars[MAX_PIPES];
-+ struct drm_dp_mst_topology_state *mst_state;
-+ struct drm_dp_mst_topology_mgr *mgr;
- #endif
-
- trace_amdgpu_dm_atomic_check_begin(state);
-@@ -9654,6 +9652,33 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
- lock_and_validation_needed = true;
- }
-
-+#if defined(CONFIG_DRM_AMD_DC_DCN)
-+ /* set the slot info for each mst_state based on the link encoding format */
-+ for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) {
-+ struct amdgpu_dm_connector *aconnector;
-+ struct drm_connector *connector;
-+ struct drm_connector_list_iter iter;
-+ u8 link_coding_cap;
-+
-+ if (!mgr->mst_state )
-+ continue;
-+
-+ drm_connector_list_iter_begin(dev, &iter);
-+ drm_for_each_connector_iter(connector, &iter) {
-+ int id = connector->index;
-+
-+ if (id == mst_state->mgr->conn_base_id) {
-+ aconnector = to_amdgpu_dm_connector(connector);
-+ link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(aconnector->dc_link);
-+ drm_dp_mst_update_slots(mst_state, link_coding_cap);
-+
-+ break;
-+ }
-+ }
-+ drm_connector_list_iter_end(&iter);
-+
-+ }
-+#endif
- /**
- * Streams and planes are reset when there are changes that affect
- * bandwidth. Anything that affects bandwidth needs to go through
-diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
-index f72c013d3a5b..c8f9d10fde17 100644
---- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
-+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
-@@ -27,7 +27,6 @@
- #include <linux/acpi.h>
- #include <linux/i2c.h>
-
--#include <drm/drm_atomic.h>
- #include <drm/drm_probe_helper.h>
- #include <drm/amdgpu_drm.h>
- #include <drm/drm_edid.h>
-@@ -120,27 +119,40 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
- }
-
- static void
--fill_dc_mst_payload_table_from_drm(struct drm_dp_mst_topology_state *mst_state,
-- struct amdgpu_dm_connector *aconnector,
-- struct dc_dp_mst_stream_allocation_table *table)
-+fill_dc_mst_payload_table_from_drm(struct amdgpu_dm_connector *aconnector,
-+ struct dc_dp_mst_stream_allocation_table *proposed_table)
- {
-- struct dc_dp_mst_stream_allocation_table new_table = { 0 };
-- struct dc_dp_mst_stream_allocation *sa;
-- struct drm_dp_mst_atomic_payload *payload;
--
-- /* Fill payload info*/
-- list_for_each_entry(payload, &mst_state->payloads, next) {
-- if (payload->delete)
-- continue;
--
-- sa = &new_table.stream_allocations[new_table.stream_count];
-- sa->slot_count = payload->time_slots;
-- sa->vcp_id = payload->vcpi;
-- new_table.stream_count++;
-+ int i;
-+ struct drm_dp_mst_topology_mgr *mst_mgr =
-+ &aconnector->mst_port->mst_mgr;
-+
-+ mutex_lock(&mst_mgr->payload_lock);
-+
-+ proposed_table->stream_count = 0;
-+
-+ /* number of active streams */
-+ for (i = 0; i < mst_mgr->max_payloads; i++) {
-+ if (mst_mgr->payloads[i].num_slots == 0)
-+ break; /* end of vcp_id table */
-+
-+ ASSERT(mst_mgr->payloads[i].payload_state !=
-+ DP_PAYLOAD_DELETE_LOCAL);
-+
-+ if (mst_mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL ||
-+ mst_mgr->payloads[i].payload_state ==
-+ DP_PAYLOAD_REMOTE) {
-+
-+ struct dc_dp_mst_stream_allocation *sa =
-+ &proposed_table->stream_allocations[
-+ proposed_table->stream_count];
-+
-+ sa->slot_count = mst_mgr->payloads[i].num_slots;
-+ sa->vcp_id = mst_mgr->proposed_vcpis[i]->vcpi;
-+ proposed_table->stream_count++;
-+ }
- }
-
-- /* Overwrite the old table */
-- *table = new_table;
-+ mutex_unlock(&mst_mgr->payload_lock);
- }
-
- void dm_helpers_dp_update_branch_info(
-@@ -158,9 +170,11 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
- bool enable)
- {
- struct amdgpu_dm_connector *aconnector;
-- struct drm_dp_mst_topology_state *mst_state;
-- struct drm_dp_mst_atomic_payload *payload;
-+ struct dm_connector_state *dm_conn_state;
- struct drm_dp_mst_topology_mgr *mst_mgr;
-+ struct drm_dp_mst_port *mst_port;
-+ bool ret;
-+ u8 link_coding_cap = DP_8b_10b_ENCODING;
-
- aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
- /* Accessing the connector state is required for vcpi_slots allocation
-@@ -171,21 +185,40 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
- if (!aconnector || !aconnector->mst_port)
- return false;
-
-+ dm_conn_state = to_dm_connector_state(aconnector->base.state);
-+
- mst_mgr = &aconnector->mst_port->mst_mgr;
-- mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state);
-+
-+ if (!mst_mgr->mst_state)
-+ return false;
-+
-+ mst_port = aconnector->port;
-+
-+#if defined(CONFIG_DRM_AMD_DC_DCN)
-+ link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(aconnector->dc_link);
-+#endif
-+
-+ if (enable) {
-+
-+ ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port,
-+ dm_conn_state->pbn,
-+ dm_conn_state->vcpi_slots);
-+ if (!ret)
-+ return false;
-+
-+ } else {
-+ drm_dp_mst_reset_vcpi_slots(mst_mgr, mst_port);
-+ }
-
- /* It's OK for this to fail */
-- payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->port);
-- if (enable)
-- drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
-- else
-- drm_dp_remove_payload(mst_mgr, mst_state, payload);
-+ drm_dp_update_payload_part1(mst_mgr, (link_coding_cap == DP_CAP_ANSI_128B132B) ? 0:1);
-
- /* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
- * AUX message. The sequence is slot 1-63 allocated sequence for each
- * stream. AMD ASIC stream slot allocation should follow the same
- * sequence. copy DRM MST allocation to dc */
-- fill_dc_mst_payload_table_from_drm(mst_state, aconnector, proposed_table);
-+
-+ fill_dc_mst_payload_table_from_drm(aconnector, proposed_table);
-
- return true;
- }
-@@ -242,9 +275,8 @@ bool dm_helpers_dp_mst_send_payload_allocation(
- bool enable)
- {
- struct amdgpu_dm_connector *aconnector;
-- struct drm_dp_mst_topology_state *mst_state;
- struct drm_dp_mst_topology_mgr *mst_mgr;
-- struct drm_dp_mst_atomic_payload *payload;
-+ struct drm_dp_mst_port *mst_port;
- enum mst_progress_status set_flag = MST_ALLOCATE_NEW_PAYLOAD;
- enum mst_progress_status clr_flag = MST_CLEAR_ALLOCATED_PAYLOAD;
-
-@@ -253,16 +285,19 @@ bool dm_helpers_dp_mst_send_payload_allocation(
- if (!aconnector || !aconnector->mst_port)
- return false;
-
-+ mst_port = aconnector->port;
-+
- mst_mgr = &aconnector->mst_port->mst_mgr;
-- mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state);
-
-- payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->port);
-+ if (!mst_mgr->mst_state)
-+ return false;
-+
- if (!enable) {
- set_flag = MST_CLEAR_ALLOCATED_PAYLOAD;
- clr_flag = MST_ALLOCATE_NEW_PAYLOAD;
- }
-
-- if (enable && drm_dp_add_payload_part2(mst_mgr, mst_state->base.state, payload)) {
-+ if (drm_dp_update_payload_part2(mst_mgr)) {
- amdgpu_dm_set_mst_status(&aconnector->mst_status,
- set_flag, false);
- } else {
-@@ -272,6 +307,9 @@ bool dm_helpers_dp_mst_send_payload_allocation(
- clr_flag, false);
- }
-
-+ if (!enable)
-+ drm_dp_mst_deallocate_vcpi(mst_mgr, mst_port);
-+
- return true;
- }
-
-diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
-index 6483ba266893..d57f1528a295 100644
---- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
-+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
-@@ -598,8 +598,15 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
-
- dc_link_dp_get_max_link_enc_cap(aconnector->dc_link, &max_link_enc_cap);
- aconnector->mst_mgr.cbs = &dm_mst_cbs;
-- drm_dp_mst_topology_mgr_init(&aconnector->mst_mgr, adev_to_drm(dm->adev),
-- &aconnector->dm_dp_aux.aux, 16, 4, aconnector->connector_id);
-+ drm_dp_mst_topology_mgr_init(
-+ &aconnector->mst_mgr,
-+ adev_to_drm(dm->adev),
-+ &aconnector->dm_dp_aux.aux,
-+ 16,
-+ 4,
-+ max_link_enc_cap.lane_count,
-+ drm_dp_bw_code_to_link_rate(max_link_enc_cap.link_rate),
-+ aconnector->connector_id);
-
- drm_connector_attach_dp_subconnector_property(&aconnector->base);
- }
-@@ -703,13 +710,12 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn)
- return dsc_config.bits_per_pixel;
- }
-
--static int increase_dsc_bpp(struct drm_atomic_state *state,
-- struct drm_dp_mst_topology_state *mst_state,
-- struct dc_link *dc_link,
-- struct dsc_mst_fairness_params *params,
-- struct dsc_mst_fairness_vars *vars,
-- int count,
-- int k)
-+static bool increase_dsc_bpp(struct drm_atomic_state *state,
-+ struct dc_link *dc_link,
-+ struct dsc_mst_fairness_params *params,
-+ struct dsc_mst_fairness_vars *vars,
-+ int count,
-+ int k)
- {
- int i;
- bool bpp_increased[MAX_PIPES];
-@@ -717,10 +723,13 @@ static int increase_dsc_bpp(struct drm_atomic_state *state,
- int min_initial_slack;
- int next_index;
- int remaining_to_increase = 0;
-+ int pbn_per_timeslot;
- int link_timeslots_used;
- int fair_pbn_alloc;
- int ret = 0;
-
-+ pbn_per_timeslot = dm_mst_get_pbn_divider(dc_link);
-+
- for (i = 0; i < count; i++) {
- if (vars[i + k].dsc_enabled) {
- initial_slack[i] =
-@@ -751,17 +760,18 @@ static int increase_dsc_bpp(struct drm_atomic_state *state,
- link_timeslots_used = 0;
-
- for (i = 0; i < count; i++)
-- link_timeslots_used += DIV_ROUND_UP(vars[i + k].pbn, mst_state->pbn_div);
-+ link_timeslots_used += DIV_ROUND_UP(vars[i + k].pbn, pbn_per_timeslot);
-
-- fair_pbn_alloc =
-- (63 - link_timeslots_used) / remaining_to_increase * mst_state->pbn_div;
-+ fair_pbn_alloc = (63 - link_timeslots_used) / remaining_to_increase * pbn_per_timeslot;
-
- if (initial_slack[next_index] > fair_pbn_alloc) {
- vars[next_index].pbn += fair_pbn_alloc;
-+
- ret = drm_dp_atomic_find_time_slots(state,
- params[next_index].port->mgr,
- params[next_index].port,
-- vars[next_index].pbn);
-+ vars[next_index].pbn,
-+ pbn_per_timeslot);
- if (ret < 0)
- return ret;
-
-@@ -773,7 +783,8 @@ static int increase_dsc_bpp(struct drm_atomic_state *state,
- ret = drm_dp_atomic_find_time_slots(state,
- params[next_index].port->mgr,
- params[next_index].port,
-- vars[next_index].pbn);
-+ vars[next_index].pbn,
-+ pbn_per_timeslot);
- if (ret < 0)
- return ret;
- }
-@@ -782,7 +793,8 @@ static int increase_dsc_bpp(struct drm_atomic_state *state,
- ret = drm_dp_atomic_find_time_slots(state,
- params[next_index].port->mgr,
- params[next_index].port,
-- vars[next_index].pbn);
-+ vars[next_index].pbn,
-+ pbn_per_timeslot);
- if (ret < 0)
- return ret;
-
-@@ -794,7 +806,8 @@ static int increase_dsc_bpp(struct drm_atomic_state *state,
- ret = drm_dp_atomic_find_time_slots(state,
- params[next_index].port->mgr,
- params[next_index].port,
-- vars[next_index].pbn);
-+ vars[next_index].pbn,
-+ pbn_per_timeslot);
- if (ret < 0)
- return ret;
- }
-@@ -850,10 +863,12 @@ static int try_disable_dsc(struct drm_atomic_state *state,
- break;
-
- vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
-+
- ret = drm_dp_atomic_find_time_slots(state,
- params[next_index].port->mgr,
- params[next_index].port,
-- vars[next_index].pbn);
-+ vars[next_index].pbn,
-+ dm_mst_get_pbn_divider(dc_link));
- if (ret < 0)
- return ret;
-
-@@ -863,10 +878,12 @@ static int try_disable_dsc(struct drm_atomic_state *state,
- vars[next_index].bpp_x16 = 0;
- } else {
- vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
-+
- ret = drm_dp_atomic_find_time_slots(state,
- params[next_index].port->mgr,
- params[next_index].port,
-- vars[next_index].pbn);
-+ vars[next_index].pbn,
-+ dm_mst_get_pbn_divider(dc_link));
- if (ret < 0)
- return ret;
- }
-@@ -877,31 +894,21 @@ static int try_disable_dsc(struct drm_atomic_state *state,
- return 0;
- }
-
--static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
-- struct dc_state *dc_state,
-- struct dc_link *dc_link,
-- struct dsc_mst_fairness_vars *vars,
-- struct drm_dp_mst_topology_mgr *mgr,
-- int *link_vars_start_index)
-+static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
-+ struct dc_state *dc_state,
-+ struct dc_link *dc_link,
-+ struct dsc_mst_fairness_vars *vars,
-+ int *link_vars_start_index)
- {
-+ int i, k, ret;
- struct dc_stream_state *stream;
- struct dsc_mst_fairness_params params[MAX_PIPES];
- struct amdgpu_dm_connector *aconnector;
-- struct drm_dp_mst_topology_state *mst_state = drm_atomic_get_mst_topology_state(state, mgr);
- int count = 0;
-- int i, k, ret;
- bool debugfs_overwrite = false;
-
- memset(params, 0, sizeof(params));
-
-- if (IS_ERR(mst_state))
-- return PTR_ERR(mst_state);
--
-- mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);
--#if defined(CONFIG_DRM_AMD_DC_DCN)
-- drm_dp_mst_update_slots(mst_state, dc_link_dp_mst_decide_link_encoding_format(dc_link));
--#endif
--
- /* Set up params */
- for (i = 0; i < dc_state->stream_count; i++) {
- struct dc_dsc_policy dsc_policy = {0};
-@@ -961,7 +968,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
- vars[i + k].dsc_enabled = false;
- vars[i + k].bpp_x16 = 0;
- ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
-- vars[i + k].pbn);
-+ vars[i + k].pbn, dm_mst_get_pbn_divider(dc_link));
- if (ret < 0)
- return ret;
- }
-@@ -980,7 +987,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
- vars[i + k].dsc_enabled = true;
- vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16;
- ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
-- params[i].port, vars[i + k].pbn);
-+ params[i].port, vars[i + k].pbn, dm_mst_get_pbn_divider(dc_link));
- if (ret < 0)
- return ret;
- } else {
-@@ -988,7 +995,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
- vars[i + k].dsc_enabled = false;
- vars[i + k].bpp_x16 = 0;
- ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
-- params[i].port, vars[i + k].pbn);
-+ params[i].port, vars[i + k].pbn, dm_mst_get_pbn_divider(dc_link));
- if (ret < 0)
- return ret;
- }
-@@ -998,7 +1005,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
- return ret;
-
- /* Optimize degree of compression */
-- ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k);
-+ ret = increase_dsc_bpp(state, dc_link, params, vars, count, k);
- if (ret < 0)
- return ret;
-
-@@ -1148,7 +1155,7 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
- continue;
-
- mst_mgr = aconnector->port->mgr;
-- ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr,
-+ ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
- &link_vars_start_index);
- if (ret != 0)
- return ret;
-@@ -1206,7 +1213,7 @@ static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
- continue;
-
- mst_mgr = aconnector->port->mgr;
-- ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr,
-+ ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
- &link_vars_start_index);
- if (ret != 0)
- return ret;
-diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h
-index d1e91d31d151..0889c2a86733 100644
---- a/drivers/gpu/drm/amd/display/include/link_service_types.h
-+++ b/drivers/gpu/drm/amd/display/include/link_service_types.h
-@@ -252,9 +252,6 @@ union dpcd_training_lane_set {
- * _ONLY_ be filled out from DM and then passed to DC, do NOT use these for _any_ kind of atomic
- * state calculations in DM, or you will break something.
- */
--
--struct drm_dp_mst_port;
--
- /* DP MST stream allocation (payload bandwidth number) */
- struct dc_dp_mst_stream_allocation {
- uint8_t vcp_id;
-diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
-index 51a46689cda7..95ff57d20216 100644
---- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
-+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
-@@ -68,7 +68,8 @@ static bool dump_dp_payload_table(struct drm_dp_mst_topology_mgr *mgr,
- static void drm_dp_mst_topology_put_port(struct drm_dp_mst_port *port);
-
- static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr,
-- int id, u8 start_slot, u8 num_slots);
-+ int id,
-+ struct drm_dp_payload *payload);
-
- static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
- struct drm_dp_mst_port *port,
-@@ -1234,6 +1235,57 @@ build_query_stream_enc_status(struct drm_dp_sideband_msg_tx *msg, u8 stream_id,
- return 0;
- }
-
-+static int drm_dp_mst_assign_payload_id(struct drm_dp_mst_topology_mgr *mgr,
-+ struct drm_dp_vcpi *vcpi)
-+{
-+ int ret, vcpi_ret;
-+
-+ mutex_lock(&mgr->payload_lock);
-+ ret = find_first_zero_bit(&mgr->payload_mask, mgr->max_payloads + 1);
-+ if (ret > mgr->max_payloads) {
-+ ret = -EINVAL;
-+ drm_dbg_kms(mgr->dev, "out of payload ids %d\n", ret);
-+ goto out_unlock;
-+ }
-+
-+ vcpi_ret = find_first_zero_bit(&mgr->vcpi_mask, mgr->max_payloads + 1);
-+ if (vcpi_ret > mgr->max_payloads) {
-+ ret = -EINVAL;
-+ drm_dbg_kms(mgr->dev, "out of vcpi ids %d\n", ret);
-+ goto out_unlock;
-+ }
-+
-+ set_bit(ret, &mgr->payload_mask);
-+ set_bit(vcpi_ret, &mgr->vcpi_mask);
-+ vcpi->vcpi = vcpi_ret + 1;
-+ mgr->proposed_vcpis[ret - 1] = vcpi;
-+out_unlock:
-+ mutex_unlock(&mgr->payload_lock);
-+ return ret;
-+}
-+
-+static void drm_dp_mst_put_payload_id(struct drm_dp_mst_topology_mgr *mgr,
-+ int vcpi)
-+{
-+ int i;
-+
-+ if (vcpi == 0)
-+ return;
-+
-+ mutex_lock(&mgr->payload_lock);
-+ drm_dbg_kms(mgr->dev, "putting payload %d\n", vcpi);
-+ clear_bit(vcpi - 1, &mgr->vcpi_mask);
-+
-+ for (i = 0; i < mgr->max_payloads; i++) {
-+ if (mgr->proposed_vcpis[i] &&
-+ mgr->proposed_vcpis[i]->vcpi == vcpi) {
-+ mgr->proposed_vcpis[i] = NULL;
-+ clear_bit(i + 1, &mgr->payload_mask);
-+ }
-+ }
-+ mutex_unlock(&mgr->payload_lock);
-+}
-+
- static bool check_txmsg_state(struct drm_dp_mst_topology_mgr *mgr,
- struct drm_dp_sideband_msg_tx *txmsg)
- {
-@@ -1686,7 +1738,7 @@ drm_dp_mst_dump_port_topology_history(struct drm_dp_mst_port *port) {}
- #define save_port_topology_ref(port, type)
- #endif
-
--struct drm_dp_mst_atomic_payload *
-+static struct drm_dp_mst_atomic_payload *
- drm_atomic_get_mst_payload_state(struct drm_dp_mst_topology_state *state,
- struct drm_dp_mst_port *port)
- {
-@@ -1698,7 +1750,6 @@ drm_atomic_get_mst_payload_state(struct drm_dp_mst_topology_state *state,
-
- return NULL;
- }
--EXPORT_SYMBOL(drm_atomic_get_mst_payload_state);
-
- static void drm_dp_destroy_mst_branch_device(struct kref *kref)
- {
-@@ -3201,8 +3252,6 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
- struct drm_dp_mst_port *port,
- struct drm_dp_query_stream_enc_status_ack_reply *status)
- {
-- struct drm_dp_mst_topology_state *state;
-- struct drm_dp_mst_atomic_payload *payload;
- struct drm_dp_sideband_msg_tx *txmsg;
- u8 nonce[7];
- int ret;
-@@ -3219,10 +3268,6 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
-
- get_random_bytes(nonce, sizeof(nonce));
-
-- drm_modeset_lock(&mgr->base.lock, NULL);
-- state = to_drm_dp_mst_topology_state(mgr->base.state);
-- payload = drm_atomic_get_mst_payload_state(state, port);
--
- /*
- * "Source device targets the QUERY_STREAM_ENCRYPTION_STATUS message
- * transaction at the MST Branch device directly connected to the
-@@ -3230,7 +3275,7 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
- */
- txmsg->dst = mgr->mst_primary;
-
-- build_query_stream_enc_status(txmsg, payload->vcpi, nonce);
-+ build_query_stream_enc_status(txmsg, port->vcpi.vcpi, nonce);
-
- drm_dp_queue_down_tx(mgr, txmsg);
-
-@@ -3247,7 +3292,6 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
- memcpy(status, &txmsg->reply.u.enc_status, sizeof(*status));
-
- out:
-- drm_modeset_unlock(&mgr->base.lock);
- drm_dp_mst_topology_put_port(port);
- out_get_port:
- kfree(txmsg);
-@@ -3256,162 +3300,238 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
- EXPORT_SYMBOL(drm_dp_send_query_stream_enc_status);
-
- static int drm_dp_create_payload_step1(struct drm_dp_mst_topology_mgr *mgr,
-- struct drm_dp_mst_atomic_payload *payload)
-+ int id,
-+ struct drm_dp_payload *payload)
- {
-- return drm_dp_dpcd_write_payload(mgr, payload->vcpi, payload->vc_start_slot,
-- payload->time_slots);
-+ int ret;
-+
-+ ret = drm_dp_dpcd_write_payload(mgr, id, payload);
-+ if (ret < 0) {
-+ payload->payload_state = 0;
-+ return ret;
-+ }
-+ payload->payload_state = DP_PAYLOAD_LOCAL;
-+ return 0;
- }
-
- static int drm_dp_create_payload_step2(struct drm_dp_mst_topology_mgr *mgr,
-- struct drm_dp_mst_atomic_payload *payload)
-+ struct drm_dp_mst_port *port,
-+ int id,
-+ struct drm_dp_payload *payload)
- {
- int ret;
-- struct drm_dp_mst_port *port = drm_dp_mst_topology_get_port_validated(mgr, payload->port);
--
-- if (!port)
-- return -EIO;
-
-- ret = drm_dp_payload_send_msg(mgr, port, payload->vcpi, payload->pbn);
-- drm_dp_mst_topology_put_port(port);
-+ ret = drm_dp_payload_send_msg(mgr, port, id, port->vcpi.pbn);
-+ if (ret < 0)
-+ return ret;
-+ payload->payload_state = DP_PAYLOAD_REMOTE;
- return ret;
- }
-
- static int drm_dp_destroy_payload_step1(struct drm_dp_mst_topology_mgr *mgr,
-- struct drm_dp_mst_topology_state *mst_state,
-- struct drm_dp_mst_atomic_payload *payload)
-+ struct drm_dp_mst_port *port,
-+ int id,
-+ struct drm_dp_payload *payload)
- {
- drm_dbg_kms(mgr->dev, "\n");
--
- /* it's okay for these to fail */
-- drm_dp_payload_send_msg(mgr, payload->port, payload->vcpi, 0);
-- drm_dp_dpcd_write_payload(mgr, payload->vcpi, payload->vc_start_slot, 0);
-+ if (port) {
-+ drm_dp_payload_send_msg(mgr, port, id, 0);
-+ }
-
-+ drm_dp_dpcd_write_payload(mgr, id, payload);
-+ payload->payload_state = DP_PAYLOAD_DELETE_LOCAL;
-+ return 0;
-+}
-+
-+static int drm_dp_destroy_payload_step2(struct drm_dp_mst_topology_mgr *mgr,
-+ int id,
-+ struct drm_dp_payload *payload)
-+{
-+ payload->payload_state = 0;
- return 0;
- }
-
- /**
-- * drm_dp_add_payload_part1() - Execute payload update part 1
-- * @mgr: Manager to use.
-- * @mst_state: The MST atomic state
-- * @payload: The payload to write
-+ * drm_dp_update_payload_part1() - Execute payload update part 1
-+ * @mgr: manager to use.
-+ * @start_slot: this is the cur slot
-+ *
-+ * NOTE: start_slot is a temporary workaround for non-atomic drivers,
-+ * this will be removed when non-atomic mst helpers are moved out of the helper
- *
-- * Determines the starting time slot for the given payload, and programs the VCPI for this payload
-- * into hardware. After calling this, the driver should generate ACT and payload packets.
-+ * This iterates over all proposed virtual channels, and tries to
-+ * allocate space in the link for them. For 0->slots transitions,
-+ * this step just writes the VCPI to the MST device. For slots->0
-+ * transitions, this writes the updated VCPIs and removes the
-+ * remote VC payloads.
- *
-- * Returns: 0 on success, error code on failure. In the event that this fails,
-- * @payload.vc_start_slot will also be set to -1.
-+ * after calling this the driver should generate ACT and payload
-+ * packets.
- */
--int drm_dp_add_payload_part1(struct drm_dp_mst_topology_mgr *mgr,
-- struct drm_dp_mst_topology_state *mst_state,
-- struct drm_dp_mst_atomic_payload *payload)
-+int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr, int start_slot)
- {
-+ struct drm_dp_payload req_payload;
- struct drm_dp_mst_port *port;
-- int ret;
-+ int i, j;
-+ int cur_slots = start_slot;
-+ bool skip;
-
-- port = drm_dp_mst_topology_get_port_validated(mgr, payload->port);
-- if (!port)
-- return 0;
-+ mutex_lock(&mgr->payload_lock);
-+ for (i = 0; i < mgr->max_payloads; i++) {
-+ struct drm_dp_vcpi *vcpi = mgr->proposed_vcpis[i];
-+ struct drm_dp_payload *payload = &mgr->payloads[i];
-+ bool put_port = false;
-
-- if (mgr->payload_count == 0)
-- mgr->next_start_slot = mst_state->start_slot;
-+ /* solve the current payloads - compare to the hw ones
-+ - update the hw view */
-+ req_payload.start_slot = cur_slots;
-+ if (vcpi) {
-+ port = container_of(vcpi, struct drm_dp_mst_port,
-+ vcpi);
-
-- payload->vc_start_slot = mgr->next_start_slot;
-+ mutex_lock(&mgr->lock);
-+ skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary);
-+ mutex_unlock(&mgr->lock);
-
-- ret = drm_dp_create_payload_step1(mgr, payload);
-- drm_dp_mst_topology_put_port(port);
-- if (ret < 0) {
-- drm_warn(mgr->dev, "Failed to create MST payload for port %p: %d\n",
-- payload->port, ret);
-- payload->vc_start_slot = -1;
-- return ret;
-- }
-+ if (skip) {
-+ drm_dbg_kms(mgr->dev,
-+ "Virtual channel %d is not in current topology\n",
-+ i);
-+ continue;
-+ }
-+ /* Validated ports don't matter if we're releasing
-+ * VCPI
-+ */
-+ if (vcpi->num_slots) {
-+ port = drm_dp_mst_topology_get_port_validated(
-+ mgr, port);
-+ if (!port) {
-+ if (vcpi->num_slots == payload->num_slots) {
-+ cur_slots += vcpi->num_slots;
-+ payload->start_slot = req_payload.start_slot;
-+ continue;
-+ } else {
-+ drm_dbg_kms(mgr->dev,
-+ "Fail:set payload to invalid sink");
-+ mutex_unlock(&mgr->payload_lock);
-+ return -EINVAL;
-+ }
-+ }
-+ put_port = true;
-+ }
-
-- mgr->payload_count++;
-- mgr->next_start_slot += payload->time_slots;
-+ req_payload.num_slots = vcpi->num_slots;
-+ req_payload.vcpi = vcpi->vcpi;
-+ } else {
-+ port = NULL;
-+ req_payload.num_slots = 0;
-+ }
-
-- return 0;
--}
--EXPORT_SYMBOL(drm_dp_add_payload_part1);
-+ payload->start_slot = req_payload.start_slot;
-+ /* work out what is required to happen with this payload */
-+ if (payload->num_slots != req_payload.num_slots) {
-+
-+ /* need to push an update for this payload */
-+ if (req_payload.num_slots) {
-+ drm_dp_create_payload_step1(mgr, vcpi->vcpi,
-+ &req_payload);
-+ payload->num_slots = req_payload.num_slots;
-+ payload->vcpi = req_payload.vcpi;
-+
-+ } else if (payload->num_slots) {
-+ payload->num_slots = 0;
-+ drm_dp_destroy_payload_step1(mgr, port,
-+ payload->vcpi,
-+ payload);
-+ req_payload.payload_state =
-+ payload->payload_state;
-+ payload->start_slot = 0;
-+ }
-+ payload->payload_state = req_payload.payload_state;
-+ }
-+ cur_slots += req_payload.num_slots;
-
--/**
-- * drm_dp_remove_payload() - Remove an MST payload
-- * @mgr: Manager to use.
-- * @mst_state: The MST atomic state
-- * @payload: The payload to write
-- *
-- * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
-- * the starting time slots of all other payloads which would have been shifted towards the start of
-- * the VC table as a result. After calling this, the driver should generate ACT and payload packets.
-- */
--void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
-- struct drm_dp_mst_topology_state *mst_state,
-- struct drm_dp_mst_atomic_payload *payload)
--{
-- struct drm_dp_mst_atomic_payload *pos;
-- bool send_remove = false;
-+ if (put_port)
-+ drm_dp_mst_topology_put_port(port);
-+ }
-
-- /* We failed to make the payload, so nothing to do */
-- if (payload->vc_start_slot == -1)
-- return;
-+ for (i = 0; i < mgr->max_payloads; /* do nothing */) {
-+ if (mgr->payloads[i].payload_state != DP_PAYLOAD_DELETE_LOCAL) {
-+ i++;
-+ continue;
-+ }
-
-- mutex_lock(&mgr->lock);
-- send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
-- mutex_unlock(&mgr->lock);
-+ drm_dbg_kms(mgr->dev, "removing payload %d\n", i);
-+ for (j = i; j < mgr->max_payloads - 1; j++) {
-+ mgr->payloads[j] = mgr->payloads[j + 1];
-+ mgr->proposed_vcpis[j] = mgr->proposed_vcpis[j + 1];
-
-- if (send_remove)
-- drm_dp_destroy_payload_step1(mgr, mst_state, payload);
-- else
-- drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
-- payload->vcpi);
-+ if (mgr->proposed_vcpis[j] &&
-+ mgr->proposed_vcpis[j]->num_slots) {
-+ set_bit(j + 1, &mgr->payload_mask);
-+ } else {
-+ clear_bit(j + 1, &mgr->payload_mask);
-+ }
-+ }
-
-- list_for_each_entry(pos, &mst_state->payloads, next) {
-- if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
-- pos->vc_start_slot -= payload->time_slots;
-+ memset(&mgr->payloads[mgr->max_payloads - 1], 0,
-+ sizeof(struct drm_dp_payload));
-+ mgr->proposed_vcpis[mgr->max_payloads - 1] = NULL;
-+ clear_bit(mgr->max_payloads, &mgr->payload_mask);
- }
-- payload->vc_start_slot = -1;
-+ mutex_unlock(&mgr->payload_lock);
-
-- mgr->payload_count--;
-- mgr->next_start_slot -= payload->time_slots;
-+ return 0;
- }
--EXPORT_SYMBOL(drm_dp_remove_payload);
-+EXPORT_SYMBOL(drm_dp_update_payload_part1);
-
- /**
-- * drm_dp_add_payload_part2() - Execute payload update part 2
-- * @mgr: Manager to use.
-- * @state: The global atomic state
-- * @payload: The payload to update
-- *
-- * If @payload was successfully assigned a starting time slot by drm_dp_add_payload_part1(), this
-- * function will send the sideband messages to finish allocating this payload.
-+ * drm_dp_update_payload_part2() - Execute payload update part 2
-+ * @mgr: manager to use.
- *
-- * Returns: 0 on success, negative error code on failure.
-+ * This iterates over all proposed virtual channels, and tries to
-+ * allocate space in the link for them. For 0->slots transitions,
-+ * this step writes the remote VC payload commands. For slots->0
-+ * this just resets some internal state.
- */
--int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
-- struct drm_atomic_state *state,
-- struct drm_dp_mst_atomic_payload *payload)
-+int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr)
- {
-+ struct drm_dp_mst_port *port;
-+ int i;
- int ret = 0;
-+ bool skip;
-
-- /* Skip failed payloads */
-- if (payload->vc_start_slot == -1) {
-- drm_dbg_kms(state->dev, "Part 1 of payload creation for %s failed, skipping part 2\n",
-- payload->port->connector->name);
-- return -EIO;
-- }
-+ mutex_lock(&mgr->payload_lock);
-+ for (i = 0; i < mgr->max_payloads; i++) {
-
-- ret = drm_dp_create_payload_step2(mgr, payload);
-- if (ret < 0) {
-- if (!payload->delete)
-- drm_err(mgr->dev, "Step 2 of creating MST payload for %p failed: %d\n",
-- payload->port, ret);
-- else
-- drm_dbg_kms(mgr->dev, "Step 2 of removing MST payload for %p failed: %d\n",
-- payload->port, ret);
-- }
-+ if (!mgr->proposed_vcpis[i])
-+ continue;
-
-- return ret;
-+ port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi);
-+
-+ mutex_lock(&mgr->lock);
-+ skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary);
-+ mutex_unlock(&mgr->lock);
-+
-+ if (skip)
-+ continue;
-+
-+ drm_dbg_kms(mgr->dev, "payload %d %d\n", i, mgr->payloads[i].payload_state);
-+ if (mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL) {
-+ ret = drm_dp_create_payload_step2(mgr, port, mgr->proposed_vcpis[i]->vcpi, &mgr->payloads[i]);
-+ } else if (mgr->payloads[i].payload_state == DP_PAYLOAD_DELETE_LOCAL) {
-+ ret = drm_dp_destroy_payload_step2(mgr, mgr->proposed_vcpis[i]->vcpi, &mgr->payloads[i]);
-+ }
-+ if (ret) {
-+ mutex_unlock(&mgr->payload_lock);
-+ return ret;
-+ }
-+ }
-+ mutex_unlock(&mgr->payload_lock);
-+ return 0;
- }
--EXPORT_SYMBOL(drm_dp_add_payload_part2);
-+EXPORT_SYMBOL(drm_dp_update_payload_part2);
-
- static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
- struct drm_dp_mst_port *port,
-@@ -3591,6 +3711,7 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
- int ret = 0;
- struct drm_dp_mst_branch *mstb = NULL;
-
-+ mutex_lock(&mgr->payload_lock);
- mutex_lock(&mgr->lock);
- if (mst_state == mgr->mst_state)
- goto out_unlock;
-@@ -3598,6 +3719,10 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
- mgr->mst_state = mst_state;
- /* set the device into MST mode */
- if (mst_state) {
-+ struct drm_dp_payload reset_pay;
-+ int lane_count;
-+ int link_rate;
-+
- WARN_ON(mgr->mst_primary);
-
- /* get dpcd info */
-@@ -3608,6 +3733,16 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
- goto out_unlock;
- }
-
-+ lane_count = min_t(int, mgr->dpcd[2] & DP_MAX_LANE_COUNT_MASK, mgr->max_lane_count);
-+ link_rate = min_t(int, drm_dp_bw_code_to_link_rate(mgr->dpcd[1]), mgr->max_link_rate);
-+ mgr->pbn_div = drm_dp_get_vc_payload_bw(mgr,
-+ link_rate,
-+ lane_count);
-+ if (mgr->pbn_div == 0) {
-+ ret = -EINVAL;
-+ goto out_unlock;
-+ }
-+
- /* add initial branch device at LCT 1 */
- mstb = drm_dp_add_mst_branch_device(1, NULL);
- if (mstb == NULL) {
-@@ -3627,8 +3762,9 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
- if (ret < 0)
- goto out_unlock;
-
-- /* Write reset payload */
-- drm_dp_dpcd_write_payload(mgr, 0, 0, 0x3f);
-+ reset_pay.start_slot = 0;
-+ reset_pay.num_slots = 0x3f;
-+ drm_dp_dpcd_write_payload(mgr, 0, &reset_pay);
-
- queue_work(system_long_wq, &mgr->work);
-
-@@ -3640,11 +3776,19 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
- /* this can fail if the device is gone */
- drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL, 0);
- ret = 0;
-+ memset(mgr->payloads, 0,
-+ mgr->max_payloads * sizeof(mgr->payloads[0]));
-+ memset(mgr->proposed_vcpis, 0,
-+ mgr->max_payloads * sizeof(mgr->proposed_vcpis[0]));
-+ mgr->payload_mask = 0;
-+ set_bit(0, &mgr->payload_mask);
-+ mgr->vcpi_mask = 0;
- mgr->payload_id_table_cleared = false;
- }
-
- out_unlock:
- mutex_unlock(&mgr->lock);
-+ mutex_unlock(&mgr->payload_lock);
- if (mstb)
- drm_dp_mst_topology_put_mstb(mstb);
- return ret;
-@@ -4163,18 +4307,62 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
- }
- EXPORT_SYMBOL(drm_dp_mst_get_edid);
-
-+/**
-+ * drm_dp_find_vcpi_slots() - Find time slots for this PBN value
-+ * @mgr: manager to use
-+ * @pbn: payload bandwidth to convert into slots.
-+ *
-+ * Calculate the number of time slots that will be required for the given PBN
-+ * value. This function is deprecated, and should not be used in atomic
-+ * drivers.
-+ *
-+ * RETURNS:
-+ * The total slots required for this port, or error.
-+ */
-+int drm_dp_find_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr,
-+ int pbn)
-+{
-+ int num_slots;
-+
-+ num_slots = DIV_ROUND_UP(pbn, mgr->pbn_div);
-+
-+ /* max. time slots - one slot for MTP header */
-+ if (num_slots > 63)
-+ return -ENOSPC;
-+ return num_slots;
-+}
-+EXPORT_SYMBOL(drm_dp_find_vcpi_slots);
-+
-+static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr,
-+ struct drm_dp_vcpi *vcpi, int pbn, int slots)
-+{
-+ int ret;
-+
-+ vcpi->pbn = pbn;
-+ vcpi->aligned_pbn = slots * mgr->pbn_div;
-+ vcpi->num_slots = slots;
-+
-+ ret = drm_dp_mst_assign_payload_id(mgr, vcpi);
-+ if (ret < 0)
-+ return ret;
-+ return 0;
-+}
-+
- /**
- * drm_dp_atomic_find_time_slots() - Find and add time slots to the state
- * @state: global atomic state
- * @mgr: MST topology manager for the port
- * @port: port to find time slots for
- * @pbn: bandwidth required for the mode in PBN
-+ * @pbn_div: divider for DSC mode that takes FEC into account
- *
-- * Allocates time slots to @port, replacing any previous time slot allocations it may
-- * have had. Any atomic drivers which support MST must call this function in
-- * their &drm_encoder_helper_funcs.atomic_check() callback unconditionally to
-- * change the current time slot allocation for the new state, and ensure the MST
-- * atomic state is added whenever the state of payloads in the topology changes.
-+ * Allocates time slots to @port, replacing any previous timeslot allocations it
-+ * may have had. Any atomic drivers which support MST must call this function
-+ * in their &drm_encoder_helper_funcs.atomic_check() callback to change the
-+ * current timeslot allocation for the new state, but only when
-+ * &drm_crtc_state.mode_changed or &drm_crtc_state.connectors_changed is set
-+ * to ensure compatibility with userspace applications that still use the
-+ * legacy modesetting UAPI.
- *
- * Allocations set by this function are not checked against the bandwidth
- * restraints of @mgr until the driver calls drm_dp_mst_atomic_check().
-@@ -4193,7 +4381,8 @@ EXPORT_SYMBOL(drm_dp_mst_get_edid);
- */
- int drm_dp_atomic_find_time_slots(struct drm_atomic_state *state,
- struct drm_dp_mst_topology_mgr *mgr,
-- struct drm_dp_mst_port *port, int pbn)
-+ struct drm_dp_mst_port *port, int pbn,
-+ int pbn_div)
- {
- struct drm_dp_mst_topology_state *topology_state;
- struct drm_dp_mst_atomic_payload *payload = NULL;
-@@ -4226,7 +4415,10 @@ int drm_dp_atomic_find_time_slots(struct drm_atomic_state *state,
- }
- }
-
-- req_slots = DIV_ROUND_UP(pbn, topology_state->pbn_div);
-+ if (pbn_div <= 0)
-+ pbn_div = mgr->pbn_div;
-+
-+ req_slots = DIV_ROUND_UP(pbn, pbn_div);
-
- drm_dbg_atomic(mgr->dev, "[CONNECTOR:%d:%s] [MST PORT:%p] TU %d -> %d\n",
- port->connector->base.id, port->connector->name,
-@@ -4235,7 +4427,7 @@ int drm_dp_atomic_find_time_slots(struct drm_atomic_state *state,
- port->connector->base.id, port->connector->name,
- port, prev_bw, pbn);
-
-- /* Add the new allocation to the state, note the VCPI isn't assigned until the end */
-+ /* Add the new allocation to the state */
- if (!payload) {
- payload = kzalloc(sizeof(*payload), GFP_KERNEL);
- if (!payload)
-@@ -4243,7 +4435,6 @@ int drm_dp_atomic_find_time_slots(struct drm_atomic_state *state,
-
- drm_dp_mst_get_port_malloc(port);
- payload->port = port;
-- payload->vc_start_slot = -1;
- list_add(&payload->next, &topology_state->payloads);
- }
- payload->time_slots = req_slots;
-@@ -4260,12 +4451,10 @@ EXPORT_SYMBOL(drm_dp_atomic_find_time_slots);
- * @port: The port to release the time slots from
- *
- * Releases any time slots that have been allocated to a port in the atomic
-- * state. Any atomic drivers which support MST must call this function
-- * unconditionally in their &drm_connector_helper_funcs.atomic_check() callback.
-- * This helper will check whether time slots would be released by the new state and
-- * respond accordingly, along with ensuring the MST state is always added to the
-- * atomic state whenever a new state would modify the state of payloads on the
-- * topology.
-+ * state. Any atomic drivers which support MST must call this function in
-+ * their &drm_connector_helper_funcs.atomic_check() callback when the
-+ * connector will no longer have VCPI allocated (e.g. because its CRTC was
-+ * removed) when it had VCPI allocated in the previous atomic state.
- *
- * It is OK to call this even if @port has been removed from the system.
- * Additionally, it is OK to call this function multiple times on the same
-@@ -4330,7 +4519,6 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state,
- drm_dp_mst_put_port_malloc(port);
- payload->pbn = 0;
- payload->delete = true;
-- topology_state->payload_mask &= ~BIT(payload->vcpi - 1);
- }
-
- return 0;
-@@ -4381,8 +4569,7 @@ int drm_dp_mst_atomic_setup_commit(struct drm_atomic_state *state)
- EXPORT_SYMBOL(drm_dp_mst_atomic_setup_commit);
-
- /**
-- * drm_dp_mst_atomic_wait_for_dependencies() - Wait for all pending commits on MST topologies,
-- * prepare new MST state for commit
-+ * drm_dp_mst_atomic_wait_for_dependencies() - Wait for all pending commits on MST topologies
- * @state: global atomic state
- *
- * Goes through any MST topologies in this atomic state, and waits for any pending commits which
-@@ -4400,30 +4587,17 @@ EXPORT_SYMBOL(drm_dp_mst_atomic_setup_commit);
- */
- void drm_dp_mst_atomic_wait_for_dependencies(struct drm_atomic_state *state)
- {
-- struct drm_dp_mst_topology_state *old_mst_state, *new_mst_state;
-+ struct drm_dp_mst_topology_state *old_mst_state;
- struct drm_dp_mst_topology_mgr *mgr;
-- struct drm_dp_mst_atomic_payload *old_payload, *new_payload;
- int i, j, ret;
-
-- for_each_oldnew_mst_mgr_in_state(state, mgr, old_mst_state, new_mst_state, i) {
-+ for_each_old_mst_mgr_in_state(state, mgr, old_mst_state, i) {
- for (j = 0; j < old_mst_state->num_commit_deps; j++) {
- ret = drm_crtc_commit_wait(old_mst_state->commit_deps[j]);
- if (ret < 0)
- drm_err(state->dev, "Failed to wait for %s: %d\n",
- old_mst_state->commit_deps[j]->crtc->name, ret);
- }
--
-- /* Now that previous state is committed, it's safe to copy over the start slot
-- * assignments
-- */
-- list_for_each_entry(old_payload, &old_mst_state->payloads, next) {
-- if (old_payload->delete)
-- continue;
--
-- new_payload = drm_atomic_get_mst_payload_state(new_mst_state,
-- old_payload->port);
-- new_payload->vc_start_slot = old_payload->vc_start_slot;
-- }
- }
- }
- EXPORT_SYMBOL(drm_dp_mst_atomic_wait_for_dependencies);
-@@ -4508,8 +4682,119 @@ void drm_dp_mst_update_slots(struct drm_dp_mst_topology_state *mst_state, uint8_
- }
- EXPORT_SYMBOL(drm_dp_mst_update_slots);
-
-+/**
-+ * drm_dp_mst_allocate_vcpi() - Allocate a virtual channel
-+ * @mgr: manager for this port
-+ * @port: port to allocate a virtual channel for.
-+ * @pbn: payload bandwidth number to request
-+ * @slots: returned number of slots for this PBN.
-+ */
-+bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
-+ struct drm_dp_mst_port *port, int pbn, int slots)
-+{
-+ int ret;
-+
-+ if (slots < 0)
-+ return false;
-+
-+ port = drm_dp_mst_topology_get_port_validated(mgr, port);
-+ if (!port)
-+ return false;
-+
-+ if (port->vcpi.vcpi > 0) {
-+ drm_dbg_kms(mgr->dev,
-+ "payload: vcpi %d already allocated for pbn %d - requested pbn %d\n",
-+ port->vcpi.vcpi, port->vcpi.pbn, pbn);
-+ if (pbn == port->vcpi.pbn) {
-+ drm_dp_mst_topology_put_port(port);
-+ return true;
-+ }
-+ }
-+
-+ ret = drm_dp_init_vcpi(mgr, &port->vcpi, pbn, slots);
-+ if (ret) {
-+ drm_dbg_kms(mgr->dev, "failed to init time slots=%d ret=%d\n",
-+ DIV_ROUND_UP(pbn, mgr->pbn_div), ret);
-+ drm_dp_mst_topology_put_port(port);
-+ goto out;
-+ }
-+ drm_dbg_kms(mgr->dev, "initing vcpi for pbn=%d slots=%d\n", pbn, port->vcpi.num_slots);
-+
-+ /* Keep port allocated until its payload has been removed */
-+ drm_dp_mst_get_port_malloc(port);
-+ drm_dp_mst_topology_put_port(port);
-+ return true;
-+out:
-+ return false;
-+}
-+EXPORT_SYMBOL(drm_dp_mst_allocate_vcpi);
-+
-+int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
-+{
-+ int slots = 0;
-+
-+ port = drm_dp_mst_topology_get_port_validated(mgr, port);
-+ if (!port)
-+ return slots;
-+
-+ slots = port->vcpi.num_slots;
-+ drm_dp_mst_topology_put_port(port);
-+ return slots;
-+}
-+EXPORT_SYMBOL(drm_dp_mst_get_vcpi_slots);
-+
-+/**
-+ * drm_dp_mst_reset_vcpi_slots() - Reset number of slots to 0 for VCPI
-+ * @mgr: manager for this port
-+ * @port: unverified pointer to a port.
-+ *
-+ * This just resets the number of slots for the ports VCPI for later programming.
-+ */
-+void drm_dp_mst_reset_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
-+{
-+ /*
-+ * A port with VCPI will remain allocated until its VCPI is
-+ * released, no verified ref needed
-+ */
-+
-+ port->vcpi.num_slots = 0;
-+}
-+EXPORT_SYMBOL(drm_dp_mst_reset_vcpi_slots);
-+
-+/**
-+ * drm_dp_mst_deallocate_vcpi() - deallocate a VCPI
-+ * @mgr: manager for this port
-+ * @port: port to deallocate vcpi for
-+ *
-+ * This can be called unconditionally, regardless of whether
-+ * drm_dp_mst_allocate_vcpi() succeeded or not.
-+ */
-+void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
-+ struct drm_dp_mst_port *port)
-+{
-+ bool skip;
-+
-+ if (!port->vcpi.vcpi)
-+ return;
-+
-+ mutex_lock(&mgr->lock);
-+ skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary);
-+ mutex_unlock(&mgr->lock);
-+
-+ if (skip)
-+ return;
-+
-+ drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
-+ port->vcpi.num_slots = 0;
-+ port->vcpi.pbn = 0;
-+ port->vcpi.aligned_pbn = 0;
-+ port->vcpi.vcpi = 0;
-+ drm_dp_mst_put_port_malloc(port);
-+}
-+EXPORT_SYMBOL(drm_dp_mst_deallocate_vcpi);
-+
- static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr,
-- int id, u8 start_slot, u8 num_slots)
-+ int id, struct drm_dp_payload *payload)
- {
- u8 payload_alloc[3], status;
- int ret;
-@@ -4519,8 +4804,8 @@ static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr,
- DP_PAYLOAD_TABLE_UPDATED);
-
- payload_alloc[0] = id;
-- payload_alloc[1] = start_slot;
-- payload_alloc[2] = num_slots;
-+ payload_alloc[1] = payload->start_slot;
-+ payload_alloc[2] = payload->num_slots;
-
- ret = drm_dp_dpcd_write(mgr->aux, DP_PAYLOAD_ALLOCATE_SET, payload_alloc, 3);
- if (ret != 3) {
-@@ -4735,9 +5020,8 @@ static void fetch_monitor_name(struct drm_dp_mst_topology_mgr *mgr,
- void drm_dp_mst_dump_topology(struct seq_file *m,
- struct drm_dp_mst_topology_mgr *mgr)
- {
-- struct drm_dp_mst_topology_state *state;
-- struct drm_dp_mst_atomic_payload *payload;
-- int i, ret;
-+ int i;
-+ struct drm_dp_mst_port *port;
-
- mutex_lock(&mgr->lock);
- if (mgr->mst_primary)
-@@ -4746,35 +5030,36 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
- /* dump VCPIs */
- mutex_unlock(&mgr->lock);
-
-- ret = drm_modeset_lock_single_interruptible(&mgr->base.lock);
-- if (ret < 0)
-- return;
-+ mutex_lock(&mgr->payload_lock);
-+ seq_printf(m, "\n*** VCPI Info ***\n");
-+ seq_printf(m, "payload_mask: %lx, vcpi_mask: %lx, max_payloads: %d\n", mgr->payload_mask, mgr->vcpi_mask, mgr->max_payloads);
-
-- state = to_drm_dp_mst_topology_state(mgr->base.state);
-- seq_printf(m, "\n*** Atomic state info ***\n");
-- seq_printf(m, "payload_mask: %x, max_payloads: %d, start_slot: %u, pbn_div: %d\n",
-- state->payload_mask, mgr->max_payloads, state->start_slot, state->pbn_div);
--
-- seq_printf(m, "\n| idx | port | vcpi | slots | pbn | dsc | sink name |\n");
-+ seq_printf(m, "\n| idx | port # | vcp_id | # slots | sink name |\n");
- for (i = 0; i < mgr->max_payloads; i++) {
-- list_for_each_entry(payload, &state->payloads, next) {
-+ if (mgr->proposed_vcpis[i]) {
- char name[14];
-
-- if (payload->vcpi != i || payload->delete)
-- continue;
--
-- fetch_monitor_name(mgr, payload->port, name, sizeof(name));
-- seq_printf(m, " %5d %6d %6d %02d - %02d %5d %5s %19s\n",
-+ port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi);
-+ fetch_monitor_name(mgr, port, name, sizeof(name));
-+ seq_printf(m, "%10d%10d%10d%10d%20s\n",
- i,
-- payload->port->port_num,
-- payload->vcpi,
-- payload->vc_start_slot,
-- payload->vc_start_slot + payload->time_slots - 1,
-- payload->pbn,
-- payload->dsc_enabled ? "Y" : "N",
-+ port->port_num,
-+ port->vcpi.vcpi,
-+ port->vcpi.num_slots,
- (*name != 0) ? name : "Unknown");
-- }
-+ } else
-+ seq_printf(m, "%6d - Unused\n", i);
-+ }
-+ seq_printf(m, "\n*** Payload Info ***\n");
-+ seq_printf(m, "| idx | state | start slot | # slots |\n");
-+ for (i = 0; i < mgr->max_payloads; i++) {
-+ seq_printf(m, "%10d%10d%15d%10d\n",
-+ i,
-+ mgr->payloads[i].payload_state,
-+ mgr->payloads[i].start_slot,
-+ mgr->payloads[i].num_slots);
- }
-+ mutex_unlock(&mgr->payload_lock);
-
- seq_printf(m, "\n*** DPCD Info ***\n");
- mutex_lock(&mgr->lock);
-@@ -4820,7 +5105,7 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
-
- out:
- mutex_unlock(&mgr->lock);
-- drm_modeset_unlock(&mgr->base.lock);
-+
- }
- EXPORT_SYMBOL(drm_dp_mst_dump_topology);
-
-@@ -5141,22 +5426,9 @@ drm_dp_mst_atomic_check_payload_alloc_limits(struct drm_dp_mst_topology_mgr *mgr
- mgr, mst_state, mgr->max_payloads);
- return -EINVAL;
- }
--
-- /* Assign a VCPI */
-- if (!payload->vcpi) {
-- payload->vcpi = ffz(mst_state->payload_mask) + 1;
-- drm_dbg_atomic(mgr->dev, "[MST PORT:%p] assigned VCPI #%d\n",
-- payload->port, payload->vcpi);
-- mst_state->payload_mask |= BIT(payload->vcpi - 1);
-- }
- }
--
-- if (!payload_count)
-- mst_state->pbn_div = 0;
--
-- drm_dbg_atomic(mgr->dev, "[MST MGR:%p] mst state %p TU pbn_div=%d avail=%d used=%d\n",
-- mgr, mst_state, mst_state->pbn_div, avail_slots,
-- mst_state->total_avail_slots - avail_slots);
-+ drm_dbg_atomic(mgr->dev, "[MST MGR:%p] mst state %p TU avail=%d used=%d\n",
-+ mgr, mst_state, avail_slots, mst_state->total_avail_slots - avail_slots);
-
- return 0;
- }
-@@ -5227,6 +5499,7 @@ EXPORT_SYMBOL(drm_dp_mst_add_affected_dsc_crtcs);
- * @state: Pointer to the new drm_atomic_state
- * @port: Pointer to the affected MST Port
- * @pbn: Newly recalculated bw required for link with DSC enabled
-+ * @pbn_div: Divider to calculate correct number of pbn per slot
- * @enable: Boolean flag to enable or disable DSC on the port
- *
- * This function enables DSC on the given Port
-@@ -5237,7 +5510,8 @@ EXPORT_SYMBOL(drm_dp_mst_add_affected_dsc_crtcs);
- */
- int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state,
- struct drm_dp_mst_port *port,
-- int pbn, bool enable)
-+ int pbn, int pbn_div,
-+ bool enable)
- {
- struct drm_dp_mst_topology_state *mst_state;
- struct drm_dp_mst_atomic_payload *payload;
-@@ -5263,7 +5537,7 @@ int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state,
- }
-
- if (enable) {
-- time_slots = drm_dp_atomic_find_time_slots(state, port->mgr, port, pbn);
-+ time_slots = drm_dp_atomic_find_time_slots(state, port->mgr, port, pbn, pbn_div);
- drm_dbg_atomic(state->dev,
- "[MST PORT:%p] Enabling DSC flag, reallocating %d time slots on the port\n",
- port, time_slots);
-@@ -5276,7 +5550,6 @@ int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state,
- return time_slots;
- }
- EXPORT_SYMBOL(drm_dp_mst_atomic_enable_dsc);
--
- /**
- * drm_dp_mst_atomic_check - Check that the new state of an MST topology in an
- * atomic update is valid
-@@ -5334,6 +5607,7 @@ EXPORT_SYMBOL(drm_dp_mst_topology_state_funcs);
-
- /**
- * drm_atomic_get_mst_topology_state: get MST topology state
-+ *
- * @state: global atomic state
- * @mgr: MST topology manager, also the private object in this case
- *
-@@ -5352,31 +5626,6 @@ struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_a
- }
- EXPORT_SYMBOL(drm_atomic_get_mst_topology_state);
-
--/**
-- * drm_atomic_get_new_mst_topology_state: get new MST topology state in atomic state, if any
-- * @state: global atomic state
-- * @mgr: MST topology manager, also the private object in this case
-- *
-- * This function wraps drm_atomic_get_priv_obj_state() passing in the MST atomic
-- * state vtable so that the private object state returned is that of a MST
-- * topology object.
-- *
-- * Returns:
-- *
-- * The MST topology state, or NULL if there's no topology state for this MST mgr
-- * in the global atomic state
-- */
--struct drm_dp_mst_topology_state *
--drm_atomic_get_new_mst_topology_state(struct drm_atomic_state *state,
-- struct drm_dp_mst_topology_mgr *mgr)
--{
-- struct drm_private_state *priv_state =
-- drm_atomic_get_new_private_obj_state(state, &mgr->base);
--
-- return priv_state ? to_dp_mst_topology_state(priv_state) : NULL;
--}
--EXPORT_SYMBOL(drm_atomic_get_new_mst_topology_state);
--
- /**
- * drm_dp_mst_topology_mgr_init - initialise a topology manager
- * @mgr: manager struct to initialise
-@@ -5384,6 +5633,8 @@ EXPORT_SYMBOL(drm_atomic_get_new_mst_topology_state);
- * @aux: DP helper aux channel to talk to this device
- * @max_dpcd_transaction_bytes: hw specific DPCD transaction limit
- * @max_payloads: maximum number of payloads this GPU can source
-+ * @max_lane_count: maximum number of lanes this GPU supports
-+ * @max_link_rate: maximum link rate per lane this GPU supports in kHz
- * @conn_base_id: the connector object ID the MST device is connected to.
- *
- * Return 0 for success, or negative error code on failure
-@@ -5391,12 +5642,14 @@ EXPORT_SYMBOL(drm_atomic_get_new_mst_topology_state);
- int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
- struct drm_device *dev, struct drm_dp_aux *aux,
- int max_dpcd_transaction_bytes, int max_payloads,
-+ int max_lane_count, int max_link_rate,
- int conn_base_id)
- {
- struct drm_dp_mst_topology_state *mst_state;
-
- mutex_init(&mgr->lock);
- mutex_init(&mgr->qlock);
-+ mutex_init(&mgr->payload_lock);
- mutex_init(&mgr->delayed_destroy_lock);
- mutex_init(&mgr->up_req_lock);
- mutex_init(&mgr->probe_lock);
-@@ -5426,7 +5679,19 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
- mgr->aux = aux;
- mgr->max_dpcd_transaction_bytes = max_dpcd_transaction_bytes;
- mgr->max_payloads = max_payloads;
-+ mgr->max_lane_count = max_lane_count;
-+ mgr->max_link_rate = max_link_rate;
- mgr->conn_base_id = conn_base_id;
-+ if (max_payloads + 1 > sizeof(mgr->payload_mask) * 8 ||
-+ max_payloads + 1 > sizeof(mgr->vcpi_mask) * 8)
-+ return -EINVAL;
-+ mgr->payloads = kcalloc(max_payloads, sizeof(struct drm_dp_payload), GFP_KERNEL);
-+ if (!mgr->payloads)
-+ return -ENOMEM;
-+ mgr->proposed_vcpis = kcalloc(max_payloads, sizeof(struct drm_dp_vcpi *), GFP_KERNEL);
-+ if (!mgr->proposed_vcpis)
-+ return -ENOMEM;
-+ set_bit(0, &mgr->payload_mask);
-
- mst_state = kzalloc(sizeof(*mst_state), GFP_KERNEL);
- if (mst_state == NULL)
-@@ -5459,12 +5724,19 @@ void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr)
- destroy_workqueue(mgr->delayed_destroy_wq);
- mgr->delayed_destroy_wq = NULL;
- }
-+ mutex_lock(&mgr->payload_lock);
-+ kfree(mgr->payloads);
-+ mgr->payloads = NULL;
-+ kfree(mgr->proposed_vcpis);
-+ mgr->proposed_vcpis = NULL;
-+ mutex_unlock(&mgr->payload_lock);
- mgr->dev = NULL;
- mgr->aux = NULL;
- drm_atomic_private_obj_fini(&mgr->base);
- mgr->funcs = NULL;
-
- mutex_destroy(&mgr->delayed_destroy_lock);
-+ mutex_destroy(&mgr->payload_lock);
- mutex_destroy(&mgr->qlock);
- mutex_destroy(&mgr->lock);
- mutex_destroy(&mgr->up_req_lock);
-diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
-index 03604a37931c..e01a40f35284 100644
---- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
-+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
-@@ -52,7 +52,6 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
- struct drm_atomic_state *state = crtc_state->uapi.state;
- struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
- struct intel_dp *intel_dp = &intel_mst->primary->dp;
-- struct drm_dp_mst_topology_state *mst_state;
- struct intel_connector *connector =
- to_intel_connector(conn_state->connector);
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
-@@ -60,28 +59,22 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
- &crtc_state->hw.adjusted_mode;
- int bpp, slots = -EINVAL;
-
-- mst_state = drm_atomic_get_mst_topology_state(state, &intel_dp->mst_mgr);
-- if (IS_ERR(mst_state))
-- return PTR_ERR(mst_state);
--
- crtc_state->lane_count = limits->max_lane_count;
- crtc_state->port_clock = limits->max_rate;
-
-- // TODO: Handle pbn_div changes by adding a new MST helper
-- if (!mst_state->pbn_div) {
-- mst_state->pbn_div = drm_dp_get_vc_payload_bw(&intel_dp->mst_mgr,
-- limits->max_rate,
-- limits->max_lane_count);
-- }
--
- for (bpp = limits->max_bpp; bpp >= limits->min_bpp; bpp -= 2 * 3) {
-+
- crtc_state->pipe_bpp = bpp;
-
- crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
- crtc_state->pipe_bpp,
- false);
- slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr,
-- connector->port, crtc_state->pbn);
-+ connector->port,
-+ crtc_state->pbn,
-+ drm_dp_get_vc_payload_bw(&intel_dp->mst_mgr,
-+ crtc_state->port_clock,
-+ crtc_state->lane_count));
- if (slots == -EDEADLK)
- return slots;
- if (slots >= 0)
-@@ -364,17 +357,21 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
- struct intel_dp *intel_dp = &dig_port->dp;
- struct intel_connector *connector =
- to_intel_connector(old_conn_state->connector);
-- struct drm_dp_mst_topology_state *mst_state =
-- drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
-+ int start_slot = intel_dp_is_uhbr(old_crtc_state) ? 0 : 1;
-+ int ret;
-
- drm_dbg_kms(&i915->drm, "active links %d\n",
- intel_dp->active_mst_links);
-
- intel_hdcp_disable(intel_mst->connector);
-
-- drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
-- drm_atomic_get_mst_payload_state(mst_state, connector->port));
-+ drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, connector->port);
-+
-+ ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr, start_slot);
-+ if (ret) {
-+ drm_dbg_kms(&i915->drm, "failed to update payload %d\n", ret);
-+ }
-
- intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
- }
-@@ -402,6 +399,8 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
-
- intel_disable_transcoder(old_crtc_state);
-
-+ drm_dp_update_payload_part2(&intel_dp->mst_mgr);
-+
- clear_act_sent(encoder, old_crtc_state);
-
- intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(old_crtc_state->cpu_transcoder),
-@@ -409,6 +408,8 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
-
- wait_for_act_sent(encoder, old_crtc_state);
-
-+ drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, connector->port);
-+
- intel_ddi_disable_transcoder_func(old_crtc_state);
-
- if (DISPLAY_VER(dev_priv) >= 9)
-@@ -475,8 +476,7 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state,
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct intel_connector *connector =
- to_intel_connector(conn_state->connector);
-- struct drm_dp_mst_topology_state *mst_state =
-- drm_atomic_get_new_mst_topology_state(&state->base, &intel_dp->mst_mgr);
-+ int start_slot = intel_dp_is_uhbr(pipe_config) ? 0 : 1;
- int ret;
- bool first_mst_stream;
-
-@@ -502,13 +502,16 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state,
- dig_port->base.pre_enable(state, &dig_port->base,
- pipe_config, NULL);
-
-+ ret = drm_dp_mst_allocate_vcpi(&intel_dp->mst_mgr,
-+ connector->port,
-+ pipe_config->pbn,
-+ pipe_config->dp_m_n.tu);
-+ if (!ret)
-+ drm_err(&dev_priv->drm, "failed to allocate vcpi\n");
-+
- intel_dp->active_mst_links++;
-
-- ret = drm_dp_add_payload_part1(&intel_dp->mst_mgr, mst_state,
-- drm_atomic_get_mst_payload_state(mst_state, connector->port));
-- if (ret < 0)
-- drm_err(&dev_priv->drm, "Failed to create MST payload for %s: %d\n",
-- connector->base.name, ret);
-+ ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr, start_slot);
-
- /*
- * Before Gen 12 this is not done as part of
-@@ -531,10 +534,7 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
- struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
- struct intel_digital_port *dig_port = intel_mst->primary;
- struct intel_dp *intel_dp = &dig_port->dp;
-- struct intel_connector *connector = to_intel_connector(conn_state->connector);
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
-- struct drm_dp_mst_topology_state *mst_state =
-- drm_atomic_get_new_mst_topology_state(&state->base, &intel_dp->mst_mgr);
- enum transcoder trans = pipe_config->cpu_transcoder;
-
- drm_WARN_ON(&dev_priv->drm, pipe_config->has_pch_encoder);
-@@ -562,8 +562,7 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
-
- wait_for_act_sent(encoder, pipe_config);
-
-- drm_dp_add_payload_part2(&intel_dp->mst_mgr, &state->base,
-- drm_atomic_get_mst_payload_state(mst_state, connector->port));
-+ drm_dp_update_payload_part2(&intel_dp->mst_mgr);
-
- if (DISPLAY_VER(dev_priv) >= 14 && pipe_config->fec_enable)
- intel_de_rmw(dev_priv, MTL_CHICKEN_TRANS(trans), 0,
-@@ -950,6 +949,8 @@ intel_dp_mst_encoder_init(struct intel_digital_port *dig_port, int conn_base_id)
- struct intel_dp *intel_dp = &dig_port->dp;
- enum port port = dig_port->base.port;
- int ret;
-+ int max_source_rate =
-+ intel_dp->source_rates[intel_dp->num_source_rates - 1];
-
- if (!HAS_DP_MST(i915) || intel_dp_is_edp(intel_dp))
- return 0;
-@@ -965,7 +966,10 @@ intel_dp_mst_encoder_init(struct intel_digital_port *dig_port, int conn_base_id)
- /* create encoders */
- intel_dp_create_fake_mst_encoders(dig_port);
- ret = drm_dp_mst_topology_mgr_init(&intel_dp->mst_mgr, &i915->drm,
-- &intel_dp->aux, 16, 3, conn_base_id);
-+ &intel_dp->aux, 16, 3,
-+ dig_port->max_lanes,
-+ max_source_rate,
-+ conn_base_id);
- if (ret) {
- intel_dp->mst_mgr.cbs = NULL;
- return ret;
-diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c
-index 6406fd487ee5..987e02eea66a 100644
---- a/drivers/gpu/drm/i915/display/intel_hdcp.c
-+++ b/drivers/gpu/drm/i915/display/intel_hdcp.c
-@@ -31,30 +31,8 @@
-
- static int intel_conn_to_vcpi(struct intel_connector *connector)
- {
-- struct drm_dp_mst_topology_mgr *mgr;
-- struct drm_dp_mst_atomic_payload *payload;
-- struct drm_dp_mst_topology_state *mst_state;
-- int vcpi = 0;
--
- /* For HDMI this is forced to be 0x0. For DP SST also this is 0x0. */
-- if (!connector->port)
-- return 0;
-- mgr = connector->port->mgr;
--
-- drm_modeset_lock(&mgr->base.lock, NULL);
-- mst_state = to_drm_dp_mst_topology_state(mgr->base.state);
-- payload = drm_atomic_get_mst_payload_state(mst_state, connector->port);
-- if (drm_WARN_ON(mgr->dev, !payload))
-- goto out;
--
-- vcpi = payload->vcpi;
-- if (drm_WARN_ON(mgr->dev, vcpi < 0)) {
-- vcpi = 0;
-- goto out;
-- }
--out:
-- drm_modeset_unlock(&mgr->base.lock);
-- return vcpi;
-+ return connector->port ? connector->port->vcpi.vcpi : 0;
- }
-
- /*
-diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
-index 33c97d510999..8400a5d8ea6e 100644
---- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
-+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
-@@ -932,7 +932,6 @@ struct nv50_msto {
- struct nv50_head *head;
- struct nv50_mstc *mstc;
- bool disabled;
-- bool enabled;
- };
-
- struct nouveau_encoder *nv50_real_outp(struct drm_encoder *encoder)
-@@ -949,36 +948,58 @@ struct nouveau_encoder *nv50_real_outp(struct drm_encoder *encoder)
- }
-
- static void
--nv50_msto_cleanup(struct drm_atomic_state *state,
-- struct drm_dp_mst_topology_state *mst_state,
-- struct drm_dp_mst_topology_mgr *mgr,
-- struct nv50_msto *msto)
-+nv50_msto_cleanup(struct nv50_msto *msto)
- {
- struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev);
-- struct drm_dp_mst_atomic_payload *payload =
-- drm_atomic_get_mst_payload_state(mst_state, msto->mstc->port);
-+
-+ struct nv50_mstc *mstc = msto->mstc;
-+ struct nv50_mstm *mstm = mstc->mstm;
-+
-+ if (!msto->disabled)
-+ return;
-
- NV_ATOMIC(drm, "%s: msto cleanup\n", msto->encoder.name);
-
-- if (msto->disabled) {
-- msto->mstc = NULL;
-- msto->disabled = false;
-- } else if (msto->enabled) {
-- drm_dp_add_payload_part2(mgr, state, payload);
-- msto->enabled = false;
-+ drm_dp_mst_deallocate_vcpi(&mstm->mgr, mstc->port);
-+
-+ msto->mstc = NULL;
-+ msto->disabled = false;
-+}
-+
-+static struct drm_dp_payload *
-+nv50_msto_payload(struct nv50_msto *msto)
-+{
-+ struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev);
-+ struct nv50_mstc *mstc = msto->mstc;
-+ struct nv50_mstm *mstm = mstc->mstm;
-+ int vcpi = mstc->port->vcpi.vcpi, i;
-+
-+ WARN_ON(!mutex_is_locked(&mstm->mgr.payload_lock));
-+
-+ NV_ATOMIC(drm, "%s: vcpi %d\n", msto->encoder.name, vcpi);
-+ for (i = 0; i < mstm->mgr.max_payloads; i++) {
-+ struct drm_dp_payload *payload = &mstm->mgr.payloads[i];
-+ NV_ATOMIC(drm, "%s: %d: vcpi %d start 0x%02x slots 0x%02x\n",
-+ mstm->outp->base.base.name, i, payload->vcpi,
-+ payload->start_slot, payload->num_slots);
-+ }
-+
-+ for (i = 0; i < mstm->mgr.max_payloads; i++) {
-+ struct drm_dp_payload *payload = &mstm->mgr.payloads[i];
-+ if (payload->vcpi == vcpi)
-+ return payload;
- }
-+
-+ return NULL;
- }
-
- static void
--nv50_msto_prepare(struct drm_atomic_state *state,
-- struct drm_dp_mst_topology_state *mst_state,
-- struct drm_dp_mst_topology_mgr *mgr,
-- struct nv50_msto *msto)
-+nv50_msto_prepare(struct nv50_msto *msto)
- {
- struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev);
- struct nv50_mstc *mstc = msto->mstc;
- struct nv50_mstm *mstm = mstc->mstm;
-- struct drm_dp_mst_atomic_payload *payload;
-+ struct drm_dp_payload *payload = NULL;
- struct {
- struct nv50_disp_mthd_v1 base;
- struct nv50_disp_sor_dp_mst_vcpi_v0 vcpi;
-@@ -990,27 +1011,28 @@ nv50_msto_prepare(struct drm_atomic_state *state,
- (0x0100 << msto->head->base.index),
- };
-
-+ mutex_lock(&mstm->mgr.payload_lock);
-+
- NV_ATOMIC(drm, "%s: msto prepare\n", msto->encoder.name);
-
-- payload = drm_atomic_get_mst_payload_state(mst_state, mstc->port);
-+ if (mstc->port->vcpi.vcpi > 0)
-+ payload = nv50_msto_payload(msto);
-
-- // TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
-- if (msto->disabled) {
-- drm_dp_remove_payload(mgr, mst_state, payload);
-- } else {
-- if (msto->enabled)
-- drm_dp_add_payload_part1(mgr, mst_state, payload);
-+ if (payload) {
-+ NV_ATOMIC(drm, "%s: %s: %02x %02x %04x %04x\n",
-+ msto->encoder.name, msto->head->base.base.name,
-+ payload->start_slot, payload->num_slots,
-+ mstc->port->vcpi.pbn, mstc->port->vcpi.aligned_pbn);
-
-- args.vcpi.start_slot = payload->vc_start_slot;
-- args.vcpi.num_slots = payload->time_slots;
-+ args.vcpi.start_slot = payload->start_slot;
-+ args.vcpi.num_slots = payload->num_slots;
- args.vcpi.pbn = payload->pbn;
-- args.vcpi.aligned_pbn = payload->time_slots * mst_state->pbn_div;
-- }
-+ } else {
-+ NV_ATOMIC(drm, "%s: %s: %02x %02x %04x %04x\n",
-+ msto->encoder.name, msto->head->base.base.name, 0, 0, 0, 0);
-+ }
-
-- NV_ATOMIC(drm, "%s: %s: %02x %02x %04x %04x\n",
-- msto->encoder.name, msto->head->base.base.name,
-- args.vcpi.start_slot, args.vcpi.num_slots,
-- args.vcpi.pbn, args.vcpi.aligned_pbn);
-+ mutex_unlock(&mstm->mgr.payload_lock);
-
- nvif_mthd(&drm->display->disp.object, 0, &args, sizeof(args));
- }
-@@ -1022,7 +1044,6 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
- {
- struct drm_atomic_state *state = crtc_state->state;
- struct drm_connector *connector = conn_state->connector;
-- struct drm_dp_mst_topology_state *mst_state;
- struct nv50_mstc *mstc = nv50_mstc(connector);
- struct nv50_mstm *mstm = mstc->mstm;
- struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
-@@ -1050,18 +1071,8 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
- false);
- }
-
-- mst_state = drm_atomic_get_mst_topology_state(state, &mstm->mgr);
-- if (IS_ERR(mst_state))
-- return PTR_ERR(mst_state);
--
-- if (!mst_state->pbn_div) {
-- struct nouveau_encoder *outp = mstc->mstm->outp;
--
-- mst_state->pbn_div = drm_dp_get_vc_payload_bw(&mstm->mgr,
-- outp->dp.link_bw, outp->dp.link_nr);
-- }
--
-- slots = drm_dp_atomic_find_time_slots(state, &mstm->mgr, mstc->port, asyh->dp.pbn);
-+ slots = drm_dp_atomic_find_time_slots(state, &mstm->mgr, mstc->port,
-+ asyh->dp.pbn, 0);
- if (slots < 0)
- return slots;
-
-@@ -1093,6 +1104,7 @@ nv50_msto_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *st
- struct drm_connector *connector;
- struct drm_connector_list_iter conn_iter;
- u8 proto;
-+ bool r;
-
- drm_connector_list_iter_begin(encoder->dev, &conn_iter);
- drm_for_each_connector_iter(connector, &conn_iter) {
-@@ -1107,6 +1119,10 @@ nv50_msto_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *st
- if (WARN_ON(!mstc))
- return;
-
-+ r = drm_dp_mst_allocate_vcpi(&mstm->mgr, mstc->port, asyh->dp.pbn, asyh->dp.tu);
-+ if (!r)
-+ DRM_DEBUG_KMS("Failed to allocate VCPI\n");
-+
- if (!mstm->links++)
- nv50_outp_acquire(mstm->outp, false /*XXX: MST audio.*/);
-
-@@ -1119,7 +1135,6 @@ nv50_msto_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *st
- nv50_dp_bpc_to_depth(asyh->or.bpc));
-
- msto->mstc = mstc;
-- msto->enabled = true;
- mstm->modified = true;
- }
-
-@@ -1130,6 +1145,8 @@ nv50_msto_atomic_disable(struct drm_encoder *encoder, struct drm_atomic_state *s
- struct nv50_mstc *mstc = msto->mstc;
- struct nv50_mstm *mstm = mstc->mstm;
-
-+ drm_dp_mst_reset_vcpi_slots(&mstm->mgr, mstc->port);
-+
- mstm->outp->update(mstm->outp, msto->head->base.index, NULL, 0, 0);
- mstm->modified = true;
- if (!--mstm->links)
-@@ -1349,9 +1366,7 @@ nv50_mstc_new(struct nv50_mstm *mstm, struct drm_dp_mst_port *port,
- }
-
- static void
--nv50_mstm_cleanup(struct drm_atomic_state *state,
-- struct drm_dp_mst_topology_state *mst_state,
-- struct nv50_mstm *mstm)
-+nv50_mstm_cleanup(struct nv50_mstm *mstm)
- {
- struct nouveau_drm *drm = nouveau_drm(mstm->outp->base.base.dev);
- struct drm_encoder *encoder;
-@@ -1359,12 +1374,14 @@ nv50_mstm_cleanup(struct drm_atomic_state *state,
- NV_ATOMIC(drm, "%s: mstm cleanup\n", mstm->outp->base.base.name);
- drm_dp_check_act_status(&mstm->mgr);
-
-+ drm_dp_update_payload_part2(&mstm->mgr);
-+
- drm_for_each_encoder(encoder, mstm->outp->base.base.dev) {
- if (encoder->encoder_type == DRM_MODE_ENCODER_DPMST) {
- struct nv50_msto *msto = nv50_msto(encoder);
- struct nv50_mstc *mstc = msto->mstc;
- if (mstc && mstc->mstm == mstm)
-- nv50_msto_cleanup(state, mst_state, &mstm->mgr, msto);
-+ nv50_msto_cleanup(msto);
- }
- }
-
-@@ -1372,34 +1389,20 @@ nv50_mstm_cleanup(struct drm_atomic_state *state,
- }
-
- static void
--nv50_mstm_prepare(struct drm_atomic_state *state,
-- struct drm_dp_mst_topology_state *mst_state,
-- struct nv50_mstm *mstm)
-+nv50_mstm_prepare(struct nv50_mstm *mstm)
- {
- struct nouveau_drm *drm = nouveau_drm(mstm->outp->base.base.dev);
- struct drm_encoder *encoder;
-
- NV_ATOMIC(drm, "%s: mstm prepare\n", mstm->outp->base.base.name);
-+ drm_dp_update_payload_part1(&mstm->mgr, 1);
-
-- /* Disable payloads first */
-- drm_for_each_encoder(encoder, mstm->outp->base.base.dev) {
-- if (encoder->encoder_type == DRM_MODE_ENCODER_DPMST) {
-- struct nv50_msto *msto = nv50_msto(encoder);
-- struct nv50_mstc *mstc = msto->mstc;
-- if (mstc && mstc->mstm == mstm && msto->disabled)
-- nv50_msto_prepare(state, mst_state, &mstm->mgr, msto);
-- }
-- }
--
-- /* Add payloads for new heads, while also updating the start slots of any unmodified (but
-- * active) heads that may have had their VC slots shifted left after the previous step
-- */
- drm_for_each_encoder(encoder, mstm->outp->base.base.dev) {
- if (encoder->encoder_type == DRM_MODE_ENCODER_DPMST) {
- struct nv50_msto *msto = nv50_msto(encoder);
- struct nv50_mstc *mstc = msto->mstc;
-- if (mstc && mstc->mstm == mstm && !msto->disabled)
-- nv50_msto_prepare(state, mst_state, &mstm->mgr, msto);
-+ if (mstc && mstc->mstm == mstm)
-+ nv50_msto_prepare(msto);
- }
- }
-
-@@ -1596,7 +1599,9 @@ nv50_mstm_new(struct nouveau_encoder *outp, struct drm_dp_aux *aux, int aux_max,
- mstm->mgr.cbs = &nv50_mstm;
-
- ret = drm_dp_mst_topology_mgr_init(&mstm->mgr, dev, aux, aux_max,
-- max_payloads, conn_base_id);
-+ max_payloads, outp->dcb->dpconf.link_nr,
-+ drm_dp_bw_code_to_link_rate(outp->dcb->dpconf.link_bw),
-+ conn_base_id);
- if (ret)
- return ret;
-
-@@ -2048,20 +2053,20 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
- static void
- nv50_disp_atomic_commit_core(struct drm_atomic_state *state, u32 *interlock)
- {
-- struct drm_dp_mst_topology_mgr *mgr;
-- struct drm_dp_mst_topology_state *mst_state;
- struct nouveau_drm *drm = nouveau_drm(state->dev);
- struct nv50_disp *disp = nv50_disp(drm->dev);
- struct nv50_core *core = disp->core;
- struct nv50_mstm *mstm;
-- int i;
-+ struct drm_encoder *encoder;
-
- NV_ATOMIC(drm, "commit core %08x\n", interlock[NV50_DISP_INTERLOCK_BASE]);
-
-- for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) {
-- mstm = nv50_mstm(mgr);
-- if (mstm->modified)
-- nv50_mstm_prepare(state, mst_state, mstm);
-+ drm_for_each_encoder(encoder, drm->dev) {
-+ if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) {
-+ mstm = nouveau_encoder(encoder)->dp.mstm;
-+ if (mstm && mstm->modified)
-+ nv50_mstm_prepare(mstm);
-+ }
- }
-
- core->func->ntfy_init(disp->sync, NV50_DISP_CORE_NTFY);
-@@ -2070,10 +2075,12 @@ nv50_disp_atomic_commit_core(struct drm_atomic_state *state, u32 *interlock)
- disp->core->chan.base.device))
- NV_ERROR(drm, "core notifier timeout\n");
-
-- for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) {
-- mstm = nv50_mstm(mgr);
-- if (mstm->modified)
-- nv50_mstm_cleanup(state, mst_state, mstm);
-+ drm_for_each_encoder(encoder, drm->dev) {
-+ if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) {
-+ mstm = nouveau_encoder(encoder)->dp.mstm;
-+ if (mstm && mstm->modified)
-+ nv50_mstm_cleanup(mstm);
-+ }
- }
- }
-
-diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
-index 41fd8352ab65..1d2f77835de5 100644
---- a/include/drm/display/drm_dp_mst_helper.h
-+++ b/include/drm/display/drm_dp_mst_helper.h
-@@ -48,6 +48,20 @@ struct drm_dp_mst_topology_ref_history {
-
- struct drm_dp_mst_branch;
-
-+/**
-+ * struct drm_dp_vcpi - Virtual Channel Payload Identifier
-+ * @vcpi: Virtual channel ID.
-+ * @pbn: Payload Bandwidth Number for this channel
-+ * @aligned_pbn: PBN aligned with slot size
-+ * @num_slots: number of slots for this PBN
-+ */
-+struct drm_dp_vcpi {
-+ int vcpi;
-+ int pbn;
-+ int aligned_pbn;
-+ int num_slots;
-+};
-+
- /**
- * struct drm_dp_mst_port - MST port
- * @port_num: port number
-@@ -131,6 +145,7 @@ struct drm_dp_mst_port {
- struct drm_dp_aux *passthrough_aux;
- struct drm_dp_mst_branch *parent;
-
-+ struct drm_dp_vcpi vcpi;
- struct drm_connector *connector;
- struct drm_dp_mst_topology_mgr *mgr;
-
-@@ -515,6 +530,20 @@ struct drm_dp_mst_topology_cbs {
- void (*poll_hpd_irq)(struct drm_dp_mst_topology_mgr *mgr);
- };
-
-+#define DP_MAX_PAYLOAD (sizeof(unsigned long) * 8)
-+
-+#define DP_PAYLOAD_LOCAL 1
-+#define DP_PAYLOAD_REMOTE 2
-+#define DP_PAYLOAD_DELETE_LOCAL 3
-+
-+struct drm_dp_payload {
-+ int payload_state;
-+ int start_slot;
-+ int num_slots;
-+ int vcpi;
-+ int pbn;
-+};
-+
- #define to_dp_mst_topology_state(x) container_of(x, struct drm_dp_mst_topology_state, base)
-
- /**
-@@ -527,34 +556,6 @@ struct drm_dp_mst_atomic_payload {
- /** @port: The MST port assigned to this payload */
- struct drm_dp_mst_port *port;
-
-- /**
-- * @vc_start_slot: The time slot that this payload starts on. Because payload start slots
-- * can't be determined ahead of time, the contents of this value are UNDEFINED at atomic
-- * check time. This shouldn't usually matter, as the start slot should never be relevant for
-- * atomic state computations.
-- *
-- * Since this value is determined at commit time instead of check time, this value is
-- * protected by the MST helpers ensuring that async commits operating on the given topology
-- * never run in parallel. In the event that a driver does need to read this value (e.g. to
-- * inform hardware of the starting timeslot for a payload), the driver may either:
-- *
-- * * Read this field during the atomic commit after
-- * drm_dp_mst_atomic_wait_for_dependencies() has been called, which will ensure the
-- * previous MST states payload start slots have been copied over to the new state. Note
-- * that a new start slot won't be assigned/removed from this payload until
-- * drm_dp_add_payload_part1()/drm_dp_remove_payload() have been called.
-- * * Acquire the MST modesetting lock, and then wait for any pending MST-related commits to
-- * get committed to hardware by calling drm_crtc_commit_wait() on each of the
-- * &drm_crtc_commit structs in &drm_dp_mst_topology_state.commit_deps.
-- *
-- * If neither of the two above solutions suffice (e.g. the driver needs to read the start
-- * slot in the middle of an atomic commit without waiting for some reason), then drivers
-- * should cache this value themselves after changing payloads.
-- */
-- s8 vc_start_slot;
--
-- /** @vcpi: The Virtual Channel Payload Identifier */
-- u8 vcpi;
- /**
- * @time_slots:
- * The number of timeslots allocated to this payload from the source DP Tx to
-@@ -582,6 +583,8 @@ struct drm_dp_mst_topology_state {
- /** @base: Base private state for atomic */
- struct drm_private_state base;
-
-+ /** @payloads: The list of payloads being created/destroyed in this state */
-+ struct list_head payloads;
- /** @mgr: The topology manager */
- struct drm_dp_mst_topology_mgr *mgr;
-
-@@ -598,21 +601,10 @@ struct drm_dp_mst_topology_state {
- /** @num_commit_deps: The number of CRTC commits in @commit_deps */
- size_t num_commit_deps;
-
-- /** @payload_mask: A bitmask of allocated VCPIs, used for VCPI assignments */
-- u32 payload_mask;
-- /** @payloads: The list of payloads being created/destroyed in this state */
-- struct list_head payloads;
--
- /** @total_avail_slots: The total number of slots this topology can handle (63 or 64) */
- u8 total_avail_slots;
- /** @start_slot: The first usable time slot in this topology (1 or 0) */
- u8 start_slot;
--
-- /**
-- * @pbn_div: The current PBN divisor for this topology. The driver is expected to fill this
-- * out itself.
-- */
-- int pbn_div;
- };
-
- #define to_dp_mst_topology_mgr(x) container_of(x, struct drm_dp_mst_topology_mgr, base)
-@@ -652,6 +644,14 @@ struct drm_dp_mst_topology_mgr {
- * @max_payloads: maximum number of payloads the GPU can generate.
- */
- int max_payloads;
-+ /**
-+ * @max_lane_count: maximum number of lanes the GPU can drive.
-+ */
-+ int max_lane_count;
-+ /**
-+ * @max_link_rate: maximum link rate per lane GPU can output, in kHz.
-+ */
-+ int max_link_rate;
- /**
- * @conn_base_id: DRM connector ID this mgr is connected to. Only used
- * to build the MST connector path value.
-@@ -694,20 +694,6 @@ struct drm_dp_mst_topology_mgr {
- */
- bool payload_id_table_cleared : 1;
-
-- /**
-- * @payload_count: The number of currently active payloads in hardware. This value is only
-- * intended to be used internally by MST helpers for payload tracking, and is only safe to
-- * read/write from the atomic commit (not check) context.
-- */
-- u8 payload_count;
--
-- /**
-- * @next_start_slot: The starting timeslot to use for new VC payloads. This value is used
-- * internally by MST helpers for payload tracking, and is only safe to read/write from the
-- * atomic commit (not check) context.
-- */
-- u8 next_start_slot;
--
- /**
- * @mst_primary: Pointer to the primary/first branch device.
- */
-@@ -721,6 +707,10 @@ struct drm_dp_mst_topology_mgr {
- * @sink_count: Sink count from DEVICE_SERVICE_IRQ_VECTOR_ESI0.
- */
- u8 sink_count;
-+ /**
-+ * @pbn_div: PBN to slots divisor.
-+ */
-+ int pbn_div;
-
- /**
- * @funcs: Atomic helper callbacks
-@@ -737,6 +727,32 @@ struct drm_dp_mst_topology_mgr {
- */
- struct list_head tx_msg_downq;
-
-+ /**
-+ * @payload_lock: Protect payload information.
-+ */
-+ struct mutex payload_lock;
-+ /**
-+ * @proposed_vcpis: Array of pointers for the new VCPI allocation. The
-+ * VCPI structure itself is &drm_dp_mst_port.vcpi, and the size of
-+ * this array is determined by @max_payloads.
-+ */
-+ struct drm_dp_vcpi **proposed_vcpis;
-+ /**
-+ * @payloads: Array of payloads. The size of this array is determined
-+ * by @max_payloads.
-+ */
-+ struct drm_dp_payload *payloads;
-+ /**
-+ * @payload_mask: Elements of @payloads actually in use. Since
-+ * reallocation of active outputs isn't possible gaps can be created by
-+ * disabling outputs out of order compared to how they've been enabled.
-+ */
-+ unsigned long payload_mask;
-+ /**
-+ * @vcpi_mask: Similar to @payload_mask, but for @proposed_vcpis.
-+ */
-+ unsigned long vcpi_mask;
-+
- /**
- * @tx_waitq: Wait to queue stall for the tx worker.
- */
-@@ -808,7 +824,9 @@ struct drm_dp_mst_topology_mgr {
- int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
- struct drm_device *dev, struct drm_dp_aux *aux,
- int max_dpcd_transaction_bytes,
-- int max_payloads, int conn_base_id);
-+ int max_payloads,
-+ int max_lane_count, int max_link_rate,
-+ int conn_base_id);
-
- void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr);
-
-@@ -831,17 +849,28 @@ int drm_dp_get_vc_payload_bw(const struct drm_dp_mst_topology_mgr *mgr,
-
- int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc);
-
-+bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
-+ struct drm_dp_mst_port *port, int pbn, int slots);
-+
-+int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
-+
-+
-+void drm_dp_mst_reset_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
-+
- void drm_dp_mst_update_slots(struct drm_dp_mst_topology_state *mst_state, uint8_t link_encoding_cap);
-
--int drm_dp_add_payload_part1(struct drm_dp_mst_topology_mgr *mgr,
-- struct drm_dp_mst_topology_state *mst_state,
-- struct drm_dp_mst_atomic_payload *payload);
--int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
-- struct drm_atomic_state *state,
-- struct drm_dp_mst_atomic_payload *payload);
--void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
-- struct drm_dp_mst_topology_state *mst_state,
-- struct drm_dp_mst_atomic_payload *payload);
-+void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
-+ struct drm_dp_mst_port *port);
-+
-+
-+int drm_dp_find_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr,
-+ int pbn);
-+
-+
-+int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr, int start_slot);
-+
-+
-+int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr);
-
- int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
-
-@@ -863,22 +892,17 @@ int drm_dp_mst_connector_late_register(struct drm_connector *connector,
- void drm_dp_mst_connector_early_unregister(struct drm_connector *connector,
- struct drm_dp_mst_port *port);
-
--struct drm_dp_mst_topology_state *
--drm_atomic_get_mst_topology_state(struct drm_atomic_state *state,
-- struct drm_dp_mst_topology_mgr *mgr);
--struct drm_dp_mst_topology_state *
--drm_atomic_get_new_mst_topology_state(struct drm_atomic_state *state,
-- struct drm_dp_mst_topology_mgr *mgr);
--struct drm_dp_mst_atomic_payload *
--drm_atomic_get_mst_payload_state(struct drm_dp_mst_topology_state *state,
-- struct drm_dp_mst_port *port);
-+struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state,
-+ struct drm_dp_mst_topology_mgr *mgr);
- int __must_check
- drm_dp_atomic_find_time_slots(struct drm_atomic_state *state,
- struct drm_dp_mst_topology_mgr *mgr,
-- struct drm_dp_mst_port *port, int pbn);
-+ struct drm_dp_mst_port *port, int pbn,
-+ int pbn_div);
- int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state,
- struct drm_dp_mst_port *port,
-- int pbn, bool enable);
-+ int pbn, int pbn_div,
-+ bool enable);
- int __must_check
- drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state,
- struct drm_dp_mst_topology_mgr *mgr);
-@@ -902,12 +926,6 @@ void drm_dp_mst_put_port_malloc(struct drm_dp_mst_port *port);
-
- struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port);
-
--static inline struct drm_dp_mst_topology_state *
--to_drm_dp_mst_topology_state(struct drm_private_state *state)
--{
-- return container_of(state, struct drm_dp_mst_topology_state, base);
--}
--
- extern const struct drm_private_state_funcs drm_dp_mst_topology_state_funcs;
-
- /**
---
-2.39.1
-
diff --git a/0002-Revert-drm-i915-improve-the-catch-all-evict-to-handl.patch b/0002-Revert-drm-i915-improve-the-catch-all-evict-to-handl.patch
new file mode 100644
index 000000000000..43b24b62790f
--- /dev/null
+++ b/0002-Revert-drm-i915-improve-the-catch-all-evict-to-handl.patch
@@ -0,0 +1,231 @@
+From 1635d2bdd74f7ecea0a7cbbdd74f78b2f369a16e Mon Sep 17 00:00:00 2001
+From: "Jan Alexander Steffens (heftig)" <heftig@archlinux.org>
+Date: Wed, 4 Jan 2023 17:25:32 +0100
+Subject: [PATCH 2/8] Revert "drm/i915: improve the catch-all evict to handle
+ lock contention"
+
+Will be replaced with the revision from mainline, which only adds
+comment changes.
+
+This reverts commit 4b1f2367bcbd0cdb86c71ddbb5fc1041872b6766.
+---
+ .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 25 ++-----------
+ drivers/gpu/drm/i915/gem/i915_gem_mman.c | 2 +-
+ drivers/gpu/drm/i915/i915_gem_evict.c | 37 +++++--------------
+ drivers/gpu/drm/i915/i915_gem_evict.h | 4 +-
+ drivers/gpu/drm/i915/i915_vma.c | 2 +-
+ .../gpu/drm/i915/selftests/i915_gem_evict.c | 4 +-
+ 6 files changed, 18 insertions(+), 56 deletions(-)
+
+diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+index f461e34cc5f0..68f2c3e5065a 100644
+--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
++++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+@@ -759,44 +759,25 @@ static int eb_reserve(struct i915_execbuffer *eb)
+ * hopefully unbind (if still bound in the VM). Repeat until the VM is
+ * evicted. Finally we should be able bind everything.
+ */
+- for (pass = 0; pass <= 3; pass++) {
++ for (pass = 0; pass <= 2; pass++) {
+ int pin_flags = PIN_USER | PIN_VALIDATE;
+
+ if (pass == 0)
+ pin_flags |= PIN_NONBLOCK;
+
+ if (pass >= 1)
+- unpinned = eb_unbind(eb, pass >= 2);
++ unpinned = eb_unbind(eb, pass == 2);
+
+ if (pass == 2) {
+ err = mutex_lock_interruptible(&eb->context->vm->mutex);
+ if (!err) {
+- err = i915_gem_evict_vm(eb->context->vm, &eb->ww, NULL);
++ err = i915_gem_evict_vm(eb->context->vm, &eb->ww);
+ mutex_unlock(&eb->context->vm->mutex);
+ }
+ if (err)
+ return err;
+ }
+
+- if (pass == 3) {
+-retry:
+- err = mutex_lock_interruptible(&eb->context->vm->mutex);
+- if (!err) {
+- struct drm_i915_gem_object *busy_bo = NULL;
+-
+- err = i915_gem_evict_vm(eb->context->vm, &eb->ww, &busy_bo);
+- mutex_unlock(&eb->context->vm->mutex);
+- if (err && busy_bo) {
+- err = i915_gem_object_lock(busy_bo, &eb->ww);
+- i915_gem_object_put(busy_bo);
+- if (!err)
+- goto retry;
+- }
+- }
+- if (err)
+- return err;
+- }
+-
+ list_for_each_entry(ev, &eb->unbound, bind_link) {
+ err = eb_reserve_vma(eb, ev, pin_flags);
+ if (err)
+diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+index 354c1d6dab84..e63329bc8065 100644
+--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
++++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+@@ -369,7 +369,7 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf)
+ if (vma == ERR_PTR(-ENOSPC)) {
+ ret = mutex_lock_interruptible(&ggtt->vm.mutex);
+ if (!ret) {
+- ret = i915_gem_evict_vm(&ggtt->vm, &ww, NULL);
++ ret = i915_gem_evict_vm(&ggtt->vm, &ww);
+ mutex_unlock(&ggtt->vm.mutex);
+ }
+ if (ret)
+diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
+index a4b4d9b7d26c..f025ee4fa526 100644
+--- a/drivers/gpu/drm/i915/i915_gem_evict.c
++++ b/drivers/gpu/drm/i915/i915_gem_evict.c
+@@ -416,11 +416,6 @@ int i915_gem_evict_for_node(struct i915_address_space *vm,
+ * @vm: Address space to cleanse
+ * @ww: An optional struct i915_gem_ww_ctx. If not NULL, i915_gem_evict_vm
+ * will be able to evict vma's locked by the ww as well.
+- * @busy_bo: Optional pointer to struct drm_i915_gem_object. If not NULL, then
+- * in the event i915_gem_evict_vm() is unable to trylock an object for eviction,
+- * then @busy_bo will point to it. -EBUSY is also returned. The caller must drop
+- * the vm->mutex, before trying again to acquire the contended lock. The caller
+- * also owns a reference to the object.
+ *
+ * This function evicts all vmas from a vm.
+ *
+@@ -430,8 +425,7 @@ int i915_gem_evict_for_node(struct i915_address_space *vm,
+ * To clarify: This is for freeing up virtual address space, not for freeing
+ * memory in e.g. the shrinker.
+ */
+-int i915_gem_evict_vm(struct i915_address_space *vm, struct i915_gem_ww_ctx *ww,
+- struct drm_i915_gem_object **busy_bo)
++int i915_gem_evict_vm(struct i915_address_space *vm, struct i915_gem_ww_ctx *ww)
+ {
+ int ret = 0;
+
+@@ -463,22 +457,15 @@ int i915_gem_evict_vm(struct i915_address_space *vm, struct i915_gem_ww_ctx *ww,
+ * the resv is shared among multiple objects, we still
+ * need the object ref.
+ */
+- if (!i915_gem_object_get_rcu(vma->obj) ||
++ if (dying_vma(vma) ||
+ (ww && (dma_resv_locking_ctx(vma->obj->base.resv) == &ww->ctx))) {
+ __i915_vma_pin(vma);
+ list_add(&vma->evict_link, &locked_eviction_list);
+ continue;
+ }
+
+- if (!i915_gem_object_trylock(vma->obj, ww)) {
+- if (busy_bo) {
+- *busy_bo = vma->obj; /* holds ref */
+- ret = -EBUSY;
+- break;
+- }
+- i915_gem_object_put(vma->obj);
++ if (!i915_gem_object_trylock(vma->obj, ww))
+ continue;
+- }
+
+ __i915_vma_pin(vma);
+ list_add(&vma->evict_link, &eviction_list);
+@@ -486,29 +473,25 @@ int i915_gem_evict_vm(struct i915_address_space *vm, struct i915_gem_ww_ctx *ww,
+ if (list_empty(&eviction_list) && list_empty(&locked_eviction_list))
+ break;
+
++ ret = 0;
+ /* Unbind locked objects first, before unlocking the eviction_list */
+ list_for_each_entry_safe(vma, vn, &locked_eviction_list, evict_link) {
+ __i915_vma_unpin(vma);
+
+- if (ret == 0) {
++ if (ret == 0)
+ ret = __i915_vma_unbind(vma);
+- if (ret != -EINTR) /* "Get me out of here!" */
+- ret = 0;
+- }
+- if (!dying_vma(vma))
+- i915_gem_object_put(vma->obj);
++ if (ret != -EINTR) /* "Get me out of here!" */
++ ret = 0;
+ }
+
+ list_for_each_entry_safe(vma, vn, &eviction_list, evict_link) {
+ __i915_vma_unpin(vma);
+- if (ret == 0) {
++ if (ret == 0)
+ ret = __i915_vma_unbind(vma);
+- if (ret != -EINTR) /* "Get me out of here!" */
+- ret = 0;
+- }
++ if (ret != -EINTR) /* "Get me out of here!" */
++ ret = 0;
+
+ i915_gem_object_unlock(vma->obj);
+- i915_gem_object_put(vma->obj);
+ }
+ } while (ret == 0);
+
+diff --git a/drivers/gpu/drm/i915/i915_gem_evict.h b/drivers/gpu/drm/i915/i915_gem_evict.h
+index bf0ee0e4fe60..e593c530f9bd 100644
+--- a/drivers/gpu/drm/i915/i915_gem_evict.h
++++ b/drivers/gpu/drm/i915/i915_gem_evict.h
+@@ -11,7 +11,6 @@
+ struct drm_mm_node;
+ struct i915_address_space;
+ struct i915_gem_ww_ctx;
+-struct drm_i915_gem_object;
+
+ int __must_check i915_gem_evict_something(struct i915_address_space *vm,
+ struct i915_gem_ww_ctx *ww,
+@@ -24,7 +23,6 @@ int __must_check i915_gem_evict_for_node(struct i915_address_space *vm,
+ struct drm_mm_node *node,
+ unsigned int flags);
+ int i915_gem_evict_vm(struct i915_address_space *vm,
+- struct i915_gem_ww_ctx *ww,
+- struct drm_i915_gem_object **busy_bo);
++ struct i915_gem_ww_ctx *ww);
+
+ #endif /* __I915_GEM_EVICT_H__ */
+diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
+index c8ad8f37e5cf..0fd46ba89549 100644
+--- a/drivers/gpu/drm/i915/i915_vma.c
++++ b/drivers/gpu/drm/i915/i915_vma.c
+@@ -1569,7 +1569,7 @@ static int __i915_ggtt_pin(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
+ * locked objects when called from execbuf when pinning
+ * is removed. This would probably regress badly.
+ */
+- i915_gem_evict_vm(vm, NULL, NULL);
++ i915_gem_evict_vm(vm, NULL);
+ mutex_unlock(&vm->mutex);
+ }
+ } while (1);
+diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
+index 37068542aafe..8c6517d29b8e 100644
+--- a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
++++ b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
+@@ -344,7 +344,7 @@ static int igt_evict_vm(void *arg)
+
+ /* Everything is pinned, nothing should happen */
+ mutex_lock(&ggtt->vm.mutex);
+- err = i915_gem_evict_vm(&ggtt->vm, NULL, NULL);
++ err = i915_gem_evict_vm(&ggtt->vm, NULL);
+ mutex_unlock(&ggtt->vm.mutex);
+ if (err) {
+ pr_err("i915_gem_evict_vm on a full GGTT returned err=%d]\n",
+@@ -356,7 +356,7 @@ static int igt_evict_vm(void *arg)
+
+ for_i915_gem_ww(&ww, err, false) {
+ mutex_lock(&ggtt->vm.mutex);
+- err = i915_gem_evict_vm(&ggtt->vm, &ww, NULL);
++ err = i915_gem_evict_vm(&ggtt->vm, &ww);
+ mutex_unlock(&ggtt->vm.mutex);
+ }
+
+--
+2.39.1
+
diff --git a/0003-btrfs-fix-invalid-leaf-access-due-to-inline-extent-d.patch b/0003-btrfs-fix-invalid-leaf-access-due-to-inline-extent-d.patch
deleted file mode 100644
index d10a0724c9fa..000000000000
--- a/0003-btrfs-fix-invalid-leaf-access-due-to-inline-extent-d.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From 0a772f0e9788d760313382ec21b81dca83515966 Mon Sep 17 00:00:00 2001
-From: Filipe Manana <fdmanana@suse.com>
-Date: Thu, 12 Jan 2023 14:17:20 +0000
-Subject: [PATCH 3/5] btrfs: fix invalid leaf access due to inline extent
- during lseek
-
-During lseek, for SEEK_DATA and SEEK_HOLE modes, we access the disk_bytenr
-of anextent without checking its type. However inline extents have their
-data starting the offset of the disk_bytenr field, so accessing that field
-when we have an inline extent can result in either of the following:
-
-1) Interpret the inline extent's data as a disk_bytenr value;
-
-2) In case the inline data is less than 8 bytes, we access part of some
- other item in the leaf, or unused space in the leaf;
-
-3) In case the inline data is less than 8 bytes and the extent item is
- the first item in the leaf, we can access beyond the leaf's limit.
-
-So fix this by not accessing the disk_bytenr field if we have an inline
-extent.
-
-Fixes: b6e833567ea1 ("btrfs: make hole and data seeking a lot more efficient")
-Reported-by: Matthias Schoepfer <matthias.schoepfer@googlemail.com>
-Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=216908
-Link: https://lore.kernel.org/linux-btrfs/7f25442f-b121-2a3a-5a3d-22bcaae83cd4@leemhuis.info/
-Signed-off-by: Filipe Manana <fdmanana@suse.com>
-Cherry-picked-for: https://bugs.archlinux.org/task/77041
----
- fs/btrfs/file.c | 13 ++++++++++---
- 1 file changed, 10 insertions(+), 3 deletions(-)
-
-diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
-index 9bef8eaa074a..23056d9914d8 100644
---- a/fs/btrfs/file.c
-+++ b/fs/btrfs/file.c
-@@ -3838,6 +3838,7 @@ static loff_t find_desired_extent(struct btrfs_inode *inode, loff_t offset,
- struct extent_buffer *leaf = path->nodes[0];
- struct btrfs_file_extent_item *extent;
- u64 extent_end;
-+ u8 type;
-
- if (path->slots[0] >= btrfs_header_nritems(leaf)) {
- ret = btrfs_next_leaf(root, path);
-@@ -3892,10 +3893,16 @@ static loff_t find_desired_extent(struct btrfs_inode *inode, loff_t offset,
-
- extent = btrfs_item_ptr(leaf, path->slots[0],
- struct btrfs_file_extent_item);
-+ type = btrfs_file_extent_type(leaf, extent);
-
-- if (btrfs_file_extent_disk_bytenr(leaf, extent) == 0 ||
-- btrfs_file_extent_type(leaf, extent) ==
-- BTRFS_FILE_EXTENT_PREALLOC) {
-+ /*
-+ * Can't access the extent's disk_bytenr field if this is an
-+ * inline extent, since at that offset, it's where the extent
-+ * data starts.
-+ */
-+ if (type == BTRFS_FILE_EXTENT_PREALLOC ||
-+ (type == BTRFS_FILE_EXTENT_REG &&
-+ btrfs_file_extent_disk_bytenr(leaf, extent) == 0)) {
- /*
- * Explicit hole or prealloc extent, search for delalloc.
- * A prealloc extent is treated like a hole.
---
-2.39.1
-
diff --git a/0003-drm-i915-improve-the-catch-all-evict-to-handle-lock-.patch b/0003-drm-i915-improve-the-catch-all-evict-to-handle-lock-.patch
new file mode 100644
index 000000000000..6d7c4834a612
--- /dev/null
+++ b/0003-drm-i915-improve-the-catch-all-evict-to-handle-lock-.patch
@@ -0,0 +1,260 @@
+From ad3af346ebfb9b31d39ffeb57820617acf9902a8 Mon Sep 17 00:00:00 2001
+From: Matthew Auld <matthew.auld@intel.com>
+Date: Fri, 16 Dec 2022 11:34:56 +0000
+Subject: [PATCH 3/8] drm/i915: improve the catch-all evict to handle lock
+ contention
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The catch-all evict can fail due to object lock contention, since it
+only goes as far as trylocking the object, due to us already holding the
+vm->mutex. Doing a full object lock here can deadlock, since the
+vm->mutex is always our inner lock. Add another execbuf pass which drops
+the vm->mutex and then tries to grab the object will the full lock,
+before then retrying the eviction. This should be good enough for now to
+fix the immediate regression with userspace seeing -ENOSPC from execbuf
+due to contended object locks during GTT eviction.
+
+v2 (Mani)
+ - Also revamp the docs for the different passes.
+
+Testcase: igt@gem_ppgtt@shrink-vs-evict-*
+Fixes: 7e00897be8bf ("drm/i915: Add object locking to i915_gem_evict_for_node and i915_gem_evict_something, v2.")
+References: https://gitlab.freedesktop.org/drm/intel/-/issues/7627
+References: https://gitlab.freedesktop.org/drm/intel/-/issues/7570
+References: https://bugzilla.mozilla.org/show_bug.cgi?id=1779558
+Signed-off-by: Matthew Auld <matthew.auld@intel.com>
+Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
+Cc: Andrzej Hajda <andrzej.hajda@intel.com>
+Cc: Mani Milani <mani@chromium.org>
+Cc: <stable@vger.kernel.org> # v5.18+
+Reviewed-by: Mani Milani <mani@chromium.org>
+Tested-by: Mani Milani <mani@chromium.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20221216113456.414183-1-matthew.auld@intel.com
+(cherry picked from commit 801fa7a81f6da533cc5442fc40e32c72b76cd42a)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+(cherry picked from commit 3f882f2d4f689627c1566c2c92087bc3ff734953)
+---
+ .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 25 +++++++++++--
+ drivers/gpu/drm/i915/gem/i915_gem_mman.c | 2 +-
+ drivers/gpu/drm/i915/i915_gem_evict.c | 37 ++++++++++++++-----
+ drivers/gpu/drm/i915/i915_gem_evict.h | 4 +-
+ drivers/gpu/drm/i915/i915_vma.c | 2 +-
+ .../gpu/drm/i915/selftests/i915_gem_evict.c | 4 +-
+ 6 files changed, 56 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+index 68f2c3e5065a..f461e34cc5f0 100644
+--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
++++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+@@ -759,25 +759,44 @@ static int eb_reserve(struct i915_execbuffer *eb)
+ * hopefully unbind (if still bound in the VM). Repeat until the VM is
+ * evicted. Finally we should be able bind everything.
+ */
+- for (pass = 0; pass <= 2; pass++) {
++ for (pass = 0; pass <= 3; pass++) {
+ int pin_flags = PIN_USER | PIN_VALIDATE;
+
+ if (pass == 0)
+ pin_flags |= PIN_NONBLOCK;
+
+ if (pass >= 1)
+- unpinned = eb_unbind(eb, pass == 2);
++ unpinned = eb_unbind(eb, pass >= 2);
+
+ if (pass == 2) {
+ err = mutex_lock_interruptible(&eb->context->vm->mutex);
+ if (!err) {
+- err = i915_gem_evict_vm(eb->context->vm, &eb->ww);
++ err = i915_gem_evict_vm(eb->context->vm, &eb->ww, NULL);
+ mutex_unlock(&eb->context->vm->mutex);
+ }
+ if (err)
+ return err;
+ }
+
++ if (pass == 3) {
++retry:
++ err = mutex_lock_interruptible(&eb->context->vm->mutex);
++ if (!err) {
++ struct drm_i915_gem_object *busy_bo = NULL;
++
++ err = i915_gem_evict_vm(eb->context->vm, &eb->ww, &busy_bo);
++ mutex_unlock(&eb->context->vm->mutex);
++ if (err && busy_bo) {
++ err = i915_gem_object_lock(busy_bo, &eb->ww);
++ i915_gem_object_put(busy_bo);
++ if (!err)
++ goto retry;
++ }
++ }
++ if (err)
++ return err;
++ }
++
+ list_for_each_entry(ev, &eb->unbound, bind_link) {
+ err = eb_reserve_vma(eb, ev, pin_flags);
+ if (err)
+diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+index e63329bc8065..354c1d6dab84 100644
+--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
++++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+@@ -369,7 +369,7 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf)
+ if (vma == ERR_PTR(-ENOSPC)) {
+ ret = mutex_lock_interruptible(&ggtt->vm.mutex);
+ if (!ret) {
+- ret = i915_gem_evict_vm(&ggtt->vm, &ww);
++ ret = i915_gem_evict_vm(&ggtt->vm, &ww, NULL);
+ mutex_unlock(&ggtt->vm.mutex);
+ }
+ if (ret)
+diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
+index f025ee4fa526..a4b4d9b7d26c 100644
+--- a/drivers/gpu/drm/i915/i915_gem_evict.c
++++ b/drivers/gpu/drm/i915/i915_gem_evict.c
+@@ -416,6 +416,11 @@ int i915_gem_evict_for_node(struct i915_address_space *vm,
+ * @vm: Address space to cleanse
+ * @ww: An optional struct i915_gem_ww_ctx. If not NULL, i915_gem_evict_vm
+ * will be able to evict vma's locked by the ww as well.
++ * @busy_bo: Optional pointer to struct drm_i915_gem_object. If not NULL, then
++ * in the event i915_gem_evict_vm() is unable to trylock an object for eviction,
++ * then @busy_bo will point to it. -EBUSY is also returned. The caller must drop
++ * the vm->mutex, before trying again to acquire the contended lock. The caller
++ * also owns a reference to the object.
+ *
+ * This function evicts all vmas from a vm.
+ *
+@@ -425,7 +430,8 @@ int i915_gem_evict_for_node(struct i915_address_space *vm,
+ * To clarify: This is for freeing up virtual address space, not for freeing
+ * memory in e.g. the shrinker.
+ */
+-int i915_gem_evict_vm(struct i915_address_space *vm, struct i915_gem_ww_ctx *ww)
++int i915_gem_evict_vm(struct i915_address_space *vm, struct i915_gem_ww_ctx *ww,
++ struct drm_i915_gem_object **busy_bo)
+ {
+ int ret = 0;
+
+@@ -457,15 +463,22 @@ int i915_gem_evict_vm(struct i915_address_space *vm, struct i915_gem_ww_ctx *ww)
+ * the resv is shared among multiple objects, we still
+ * need the object ref.
+ */
+- if (dying_vma(vma) ||
++ if (!i915_gem_object_get_rcu(vma->obj) ||
+ (ww && (dma_resv_locking_ctx(vma->obj->base.resv) == &ww->ctx))) {
+ __i915_vma_pin(vma);
+ list_add(&vma->evict_link, &locked_eviction_list);
+ continue;
+ }
+
+- if (!i915_gem_object_trylock(vma->obj, ww))
++ if (!i915_gem_object_trylock(vma->obj, ww)) {
++ if (busy_bo) {
++ *busy_bo = vma->obj; /* holds ref */
++ ret = -EBUSY;
++ break;
++ }
++ i915_gem_object_put(vma->obj);
+ continue;
++ }
+
+ __i915_vma_pin(vma);
+ list_add(&vma->evict_link, &eviction_list);
+@@ -473,25 +486,29 @@ int i915_gem_evict_vm(struct i915_address_space *vm, struct i915_gem_ww_ctx *ww)
+ if (list_empty(&eviction_list) && list_empty(&locked_eviction_list))
+ break;
+
+- ret = 0;
+ /* Unbind locked objects first, before unlocking the eviction_list */
+ list_for_each_entry_safe(vma, vn, &locked_eviction_list, evict_link) {
+ __i915_vma_unpin(vma);
+
+- if (ret == 0)
++ if (ret == 0) {
+ ret = __i915_vma_unbind(vma);
+- if (ret != -EINTR) /* "Get me out of here!" */
+- ret = 0;
++ if (ret != -EINTR) /* "Get me out of here!" */
++ ret = 0;
++ }
++ if (!dying_vma(vma))
++ i915_gem_object_put(vma->obj);
+ }
+
+ list_for_each_entry_safe(vma, vn, &eviction_list, evict_link) {
+ __i915_vma_unpin(vma);
+- if (ret == 0)
++ if (ret == 0) {
+ ret = __i915_vma_unbind(vma);
+- if (ret != -EINTR) /* "Get me out of here!" */
+- ret = 0;
++ if (ret != -EINTR) /* "Get me out of here!" */
++ ret = 0;
++ }
+
+ i915_gem_object_unlock(vma->obj);
++ i915_gem_object_put(vma->obj);
+ }
+ } while (ret == 0);
+
+diff --git a/drivers/gpu/drm/i915/i915_gem_evict.h b/drivers/gpu/drm/i915/i915_gem_evict.h
+index e593c530f9bd..bf0ee0e4fe60 100644
+--- a/drivers/gpu/drm/i915/i915_gem_evict.h
++++ b/drivers/gpu/drm/i915/i915_gem_evict.h
+@@ -11,6 +11,7 @@
+ struct drm_mm_node;
+ struct i915_address_space;
+ struct i915_gem_ww_ctx;
++struct drm_i915_gem_object;
+
+ int __must_check i915_gem_evict_something(struct i915_address_space *vm,
+ struct i915_gem_ww_ctx *ww,
+@@ -23,6 +24,7 @@ int __must_check i915_gem_evict_for_node(struct i915_address_space *vm,
+ struct drm_mm_node *node,
+ unsigned int flags);
+ int i915_gem_evict_vm(struct i915_address_space *vm,
+- struct i915_gem_ww_ctx *ww);
++ struct i915_gem_ww_ctx *ww,
++ struct drm_i915_gem_object **busy_bo);
+
+ #endif /* __I915_GEM_EVICT_H__ */
+diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
+index 0fd46ba89549..c8ad8f37e5cf 100644
+--- a/drivers/gpu/drm/i915/i915_vma.c
++++ b/drivers/gpu/drm/i915/i915_vma.c
+@@ -1569,7 +1569,7 @@ static int __i915_ggtt_pin(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
+ * locked objects when called from execbuf when pinning
+ * is removed. This would probably regress badly.
+ */
+- i915_gem_evict_vm(vm, NULL);
++ i915_gem_evict_vm(vm, NULL, NULL);
+ mutex_unlock(&vm->mutex);
+ }
+ } while (1);
+diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
+index 8c6517d29b8e..37068542aafe 100644
+--- a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
++++ b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
+@@ -344,7 +344,7 @@ static int igt_evict_vm(void *arg)
+
+ /* Everything is pinned, nothing should happen */
+ mutex_lock(&ggtt->vm.mutex);
+- err = i915_gem_evict_vm(&ggtt->vm, NULL);
++ err = i915_gem_evict_vm(&ggtt->vm, NULL, NULL);
+ mutex_unlock(&ggtt->vm.mutex);
+ if (err) {
+ pr_err("i915_gem_evict_vm on a full GGTT returned err=%d]\n",
+@@ -356,7 +356,7 @@ static int igt_evict_vm(void *arg)
+
+ for_i915_gem_ww(&ww, err, false) {
+ mutex_lock(&ggtt->vm.mutex);
+- err = i915_gem_evict_vm(&ggtt->vm, &ww);
++ err = i915_gem_evict_vm(&ggtt->vm, &ww, NULL);
+ mutex_unlock(&ggtt->vm.mutex);
+ }
+
+--
+2.39.1
+
diff --git a/0004-drm-amdgpu-display-mst-Fix-mst_state-pbn_div-and-slo.patch b/0004-drm-amdgpu-display-mst-Fix-mst_state-pbn_div-and-slo.patch
new file mode 100644
index 000000000000..870cb3d99adb
--- /dev/null
+++ b/0004-drm-amdgpu-display-mst-Fix-mst_state-pbn_div-and-slo.patch
@@ -0,0 +1,88 @@
+From 688c752c92a868114d754da67a6d109dc1903e9a Mon Sep 17 00:00:00 2001
+From: Lyude Paul <lyude@redhat.com>
+Date: Wed, 23 Nov 2022 14:50:16 -0500
+Subject: [PATCH 4/8] drm/amdgpu/display/mst: Fix mst_state->pbn_div and slot
+ count assignments
+
+Looks like I made a pretty big mistake here without noticing: it seems when
+I moved the assignments of mst_state->pbn_div I completely missed the fact
+that the reason for us calling drm_dp_mst_update_slots() earlier was to
+account for the fact that we need to call this function using info from the
+root MST connector, instead of just trying to do this from each MST
+encoder's atomic check function. Otherwise, we end up filling out all of
+DC's link information with zeroes.
+
+So, let's restore that and hopefully fix this DSC regression.
+
+Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/2171
+Signed-off-by: Lyude Paul <lyude@redhat.com>
+Signed-off-by: Harry Wentland <harry.wentland@amd.com>
+Fixes: 4d07b0bc4034 ("drm/display/dp_mst: Move all payload info into the atomic state")
+Cc: stable@vger.kernel.org # 6.1
+Acked-by: Harry Wentland <harry.wentland@amd.com>
+---
+ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 24 +++++++++++++++++++
+ .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 5 ----
+ 2 files changed, 24 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index e10f1f15c9c4..e7ff09bdf533 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -9397,6 +9397,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
+ struct drm_connector_state *old_con_state, *new_con_state;
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *old_crtc_state, *new_crtc_state;
++ struct drm_dp_mst_topology_mgr *mgr;
++ struct drm_dp_mst_topology_state *mst_state;
+ struct drm_plane *plane;
+ struct drm_plane_state *old_plane_state, *new_plane_state;
+ enum dc_status status;
+@@ -9652,6 +9654,28 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
+ lock_and_validation_needed = true;
+ }
+
++#if defined(CONFIG_DRM_AMD_DC_DCN)
++ /* set the slot info for each mst_state based on the link encoding format */
++ for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) {
++ struct amdgpu_dm_connector *aconnector;
++ struct drm_connector *connector;
++ struct drm_connector_list_iter iter;
++ u8 link_coding_cap;
++
++ drm_connector_list_iter_begin(dev, &iter);
++ drm_for_each_connector_iter(connector, &iter) {
++ if (connector->index == mst_state->mgr->conn_base_id) {
++ aconnector = to_amdgpu_dm_connector(connector);
++ link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(aconnector->dc_link);
++ drm_dp_mst_update_slots(mst_state, link_coding_cap);
++
++ break;
++ }
++ }
++ drm_connector_list_iter_end(&iter);
++ }
++#endif
++
+ /**
+ * Streams and planes are reset when there are changes that affect
+ * bandwidth. Anything that affects bandwidth needs to go through
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+index 6483ba266893..4acd0b4afb48 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+@@ -897,11 +897,6 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
+ if (IS_ERR(mst_state))
+ return PTR_ERR(mst_state);
+
+- mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);
+-#if defined(CONFIG_DRM_AMD_DC_DCN)
+- drm_dp_mst_update_slots(mst_state, dc_link_dp_mst_decide_link_encoding_format(dc_link));
+-#endif
+-
+ /* Set up params */
+ for (i = 0; i < dc_state->stream_count; i++) {
+ struct dc_dsc_policy dsc_policy = {0};
+--
+2.39.1
+
diff --git a/0004-wifi-mac80211-fix-initialization-of-rx-link-and-rx-l.patch b/0004-wifi-mac80211-fix-initialization-of-rx-link-and-rx-l.patch
deleted file mode 100644
index 49c9bb437cd5..000000000000
--- a/0004-wifi-mac80211-fix-initialization-of-rx-link-and-rx-l.patch
+++ /dev/null
@@ -1,459 +0,0 @@
-From 93753514870b99ede0d3d94e176e3c35f55aab40 Mon Sep 17 00:00:00 2001
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 30 Dec 2022 21:07:47 +0100
-Subject: [PATCH 4/5] wifi: mac80211: fix initialization of rx->link and
- rx->link_sta
-
-There are some codepaths that do not initialize rx->link_sta properly. This
-causes a crash in places which assume that rx->link_sta is valid if rx->sta
-is valid.
-One known instance is triggered by __ieee80211_rx_h_amsdu being called from
-fast-rx. It results in a crash like this one:
-
- BUG: kernel NULL pointer dereference, address: 00000000000000a8
- #PF: supervisor write access in kernel mode
- #PF: error_code(0x0002) - not-present page PGD 0 P4D 0
- Oops: 0002 [#1] PREEMPT SMP PTI
- CPU: 1 PID: 506 Comm: mt76-usb-rx phy Tainted: G E 6.1.0-debian64x+1.7 #3
- Hardware name: ZOTAC ZBOX-ID92/ZBOX-IQ01/ZBOX-ID92/ZBOX-IQ01, BIOS B220P007 05/21/2014
- RIP: 0010:ieee80211_deliver_skb+0x62/0x1f0 [mac80211]
- Code: 00 48 89 04 24 e8 9e a7 c3 df 89 c0 48 03 1c c5 a0 ea 39 a1 4c 01 6b 08 48 ff 03 48
- 83 7d 28 00 74 11 48 8b 45 30 48 63 55 44 <48> 83 84 d0 a8 00 00 00 01 41 8b 86 c0
- 11 00 00 8d 50 fd 83 fa 01
- RSP: 0018:ffff999040803b10 EFLAGS: 00010286
- RAX: 0000000000000000 RBX: ffffb9903f496480 RCX: 0000000000000000
- RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
- RBP: ffff999040803ce0 R08: 0000000000000000 R09: 0000000000000000
- R10: 0000000000000000 R11: 0000000000000000 R12: ffff8d21828ac900
- R13: 000000000000004a R14: ffff8d2198ed89c0 R15: ffff8d2198ed8000
- FS: 0000000000000000(0000) GS:ffff8d24afe80000(0000) knlGS:0000000000000000
- CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
- CR2: 00000000000000a8 CR3: 0000000429810002 CR4: 00000000001706e0
- Call Trace:
- <TASK>
- __ieee80211_rx_h_amsdu+0x1b5/0x240 [mac80211]
- ? ieee80211_prepare_and_rx_handle+0xcdd/0x1320 [mac80211]
- ? __local_bh_enable_ip+0x3b/0xa0
- ieee80211_prepare_and_rx_handle+0xcdd/0x1320 [mac80211]
- ? prepare_transfer+0x109/0x1a0 [xhci_hcd]
- ieee80211_rx_list+0xa80/0xda0 [mac80211]
- mt76_rx_complete+0x207/0x2e0 [mt76]
- mt76_rx_poll_complete+0x357/0x5a0 [mt76]
- mt76u_rx_worker+0x4f5/0x600 [mt76_usb]
- ? mt76_get_min_avg_rssi+0x140/0x140 [mt76]
- __mt76_worker_fn+0x50/0x80 [mt76]
- kthread+0xed/0x120
- ? kthread_complete_and_exit+0x20/0x20
- ret_from_fork+0x22/0x30
-
-Since the initialization of rx->link and rx->link_sta is rather convoluted
-and duplicated in many places, clean it up by using a helper function to
-set it.
-
-Fixes: ccdde7c74ffd ("wifi: mac80211: properly implement MLO key handling")
-Fixes: b320d6c456ff ("wifi: mac80211: use correct rx link_sta instead of default")
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
-Link: https://lore.kernel.org/r/20221230200747.19040-1-nbd@nbd.name
-[remove unnecessary rx->sta->sta.mlo check]
-Cc: stable@vger.kernel.org
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-Cherry-picked-for: https://bugs.archlinux.org/task/76922
----
- net/mac80211/rx.c | 222 +++++++++++++++++++++-------------------------
- 1 file changed, 99 insertions(+), 123 deletions(-)
-
-diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
-index f99416d2e144..3262ebb24092 100644
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -4070,6 +4070,58 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)
- #undef CALL_RXH
- }
-
-+static bool
-+ieee80211_rx_is_valid_sta_link_id(struct ieee80211_sta *sta, u8 link_id)
-+{
-+ if (!sta->mlo)
-+ return false;
-+
-+ return !!(sta->valid_links & BIT(link_id));
-+}
-+
-+static bool ieee80211_rx_data_set_link(struct ieee80211_rx_data *rx,
-+ u8 link_id)
-+{
-+ rx->link_id = link_id;
-+ rx->link = rcu_dereference(rx->sdata->link[link_id]);
-+
-+ if (!rx->sta)
-+ return rx->link;
-+
-+ if (!ieee80211_rx_is_valid_sta_link_id(&rx->sta->sta, link_id))
-+ return false;
-+
-+ rx->link_sta = rcu_dereference(rx->sta->link[link_id]);
-+
-+ return rx->link && rx->link_sta;
-+}
-+
-+static bool ieee80211_rx_data_set_sta(struct ieee80211_rx_data *rx,
-+ struct ieee80211_sta *pubsta,
-+ int link_id)
-+{
-+ struct sta_info *sta;
-+
-+ sta = container_of(pubsta, struct sta_info, sta);
-+
-+ rx->link_id = link_id;
-+ rx->sta = sta;
-+
-+ if (sta) {
-+ rx->local = sta->sdata->local;
-+ if (!rx->sdata)
-+ rx->sdata = sta->sdata;
-+ rx->link_sta = &sta->deflink;
-+ }
-+
-+ if (link_id < 0)
-+ rx->link = &rx->sdata->deflink;
-+ else if (!ieee80211_rx_data_set_link(rx, link_id))
-+ return false;
-+
-+ return true;
-+}
-+
- /*
- * This function makes calls into the RX path, therefore
- * it has to be invoked under RCU read lock.
-@@ -4078,16 +4130,19 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
- {
- struct sk_buff_head frames;
- struct ieee80211_rx_data rx = {
-- .sta = sta,
-- .sdata = sta->sdata,
-- .local = sta->local,
- /* This is OK -- must be QoS data frame */
- .security_idx = tid,
- .seqno_idx = tid,
-- .link_id = -1,
- };
- struct tid_ampdu_rx *tid_agg_rx;
-- u8 link_id;
-+ int link_id = -1;
-+
-+ /* FIXME: statistics won't be right with this */
-+ if (sta->sta.valid_links)
-+ link_id = ffs(sta->sta.valid_links) - 1;
-+
-+ if (!ieee80211_rx_data_set_sta(&rx, &sta->sta, link_id))
-+ return;
-
- tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
- if (!tid_agg_rx)
-@@ -4107,10 +4162,6 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
- };
- drv_event_callback(rx.local, rx.sdata, &event);
- }
-- /* FIXME: statistics won't be right with this */
-- link_id = sta->sta.valid_links ? ffs(sta->sta.valid_links) - 1 : 0;
-- rx.link = rcu_dereference(sta->sdata->link[link_id]);
-- rx.link_sta = rcu_dereference(sta->link[link_id]);
-
- ieee80211_rx_handlers(&rx, &frames);
- }
-@@ -4126,7 +4177,6 @@ void ieee80211_mark_rx_ba_filtered_frames(struct ieee80211_sta *pubsta, u8 tid,
- /* This is OK -- must be QoS data frame */
- .security_idx = tid,
- .seqno_idx = tid,
-- .link_id = -1,
- };
- int i, diff;
-
-@@ -4137,10 +4187,8 @@ void ieee80211_mark_rx_ba_filtered_frames(struct ieee80211_sta *pubsta, u8 tid,
-
- sta = container_of(pubsta, struct sta_info, sta);
-
-- rx.sta = sta;
-- rx.sdata = sta->sdata;
-- rx.link = &rx.sdata->deflink;
-- rx.local = sta->local;
-+ if (!ieee80211_rx_data_set_sta(&rx, pubsta, -1))
-+ return;
-
- rcu_read_lock();
- tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
-@@ -4527,15 +4575,6 @@ void ieee80211_check_fast_rx_iface(struct ieee80211_sub_if_data *sdata)
- mutex_unlock(&local->sta_mtx);
- }
-
--static bool
--ieee80211_rx_is_valid_sta_link_id(struct ieee80211_sta *sta, u8 link_id)
--{
-- if (!sta->mlo)
-- return false;
--
-- return !!(sta->valid_links & BIT(link_id));
--}
--
- static void ieee80211_rx_8023(struct ieee80211_rx_data *rx,
- struct ieee80211_fast_rx *fast_rx,
- int orig_len)
-@@ -4646,7 +4685,6 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
- struct sk_buff *skb = rx->skb;
- struct ieee80211_hdr *hdr = (void *)skb->data;
- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-- struct sta_info *sta = rx->sta;
- int orig_len = skb->len;
- int hdrlen = ieee80211_hdrlen(hdr->frame_control);
- int snap_offs = hdrlen;
-@@ -4658,7 +4696,6 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
- u8 da[ETH_ALEN];
- u8 sa[ETH_ALEN];
- } addrs __aligned(2);
-- struct link_sta_info *link_sta;
- struct ieee80211_sta_rx_stats *stats;
-
- /* for parallel-rx, we need to have DUP_VALIDATED, otherwise we write
-@@ -4761,18 +4798,10 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
- drop:
- dev_kfree_skb(skb);
-
-- if (rx->link_id >= 0) {
-- link_sta = rcu_dereference(sta->link[rx->link_id]);
-- if (!link_sta)
-- return true;
-- } else {
-- link_sta = &sta->deflink;
-- }
--
- if (fast_rx->uses_rss)
-- stats = this_cpu_ptr(link_sta->pcpu_rx_stats);
-+ stats = this_cpu_ptr(rx->link_sta->pcpu_rx_stats);
- else
-- stats = &link_sta->rx_stats;
-+ stats = &rx->link_sta->rx_stats;
-
- stats->dropped++;
- return true;
-@@ -4790,8 +4819,8 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
- struct ieee80211_local *local = rx->local;
- struct ieee80211_sub_if_data *sdata = rx->sdata;
- struct ieee80211_hdr *hdr = (void *)skb->data;
-- struct link_sta_info *link_sta = NULL;
-- struct ieee80211_link_data *link;
-+ struct link_sta_info *link_sta = rx->link_sta;
-+ struct ieee80211_link_data *link = rx->link;
-
- rx->skb = skb;
-
-@@ -4813,35 +4842,6 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
- if (!ieee80211_accept_frame(rx))
- return false;
-
-- if (rx->link_id >= 0) {
-- link = rcu_dereference(rx->sdata->link[rx->link_id]);
--
-- /* we might race link removal */
-- if (!link)
-- return true;
-- rx->link = link;
--
-- if (rx->sta) {
-- rx->link_sta =
-- rcu_dereference(rx->sta->link[rx->link_id]);
-- if (!rx->link_sta)
-- return true;
-- }
-- } else {
-- if (rx->sta)
-- rx->link_sta = &rx->sta->deflink;
--
-- rx->link = &sdata->deflink;
-- }
--
-- if (unlikely(!is_multicast_ether_addr(hdr->addr1) &&
-- rx->link_id >= 0 && rx->sta && rx->sta->sta.mlo)) {
-- link_sta = rcu_dereference(rx->sta->link[rx->link_id]);
--
-- if (WARN_ON_ONCE(!link_sta))
-- return true;
-- }
--
- if (!consume) {
- struct skb_shared_hwtstamps *shwt;
-
-@@ -4861,7 +4861,7 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
- shwt->hwtstamp = skb_hwtstamps(skb)->hwtstamp;
- }
-
-- if (unlikely(link_sta)) {
-+ if (unlikely(rx->sta && rx->sta->sta.mlo)) {
- /* translate to MLD addresses */
- if (ether_addr_equal(link->conf->addr, hdr->addr1))
- ether_addr_copy(hdr->addr1, rx->sdata->vif.addr);
-@@ -4891,6 +4891,7 @@ static void __ieee80211_rx_handle_8023(struct ieee80211_hw *hw,
- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
- struct ieee80211_fast_rx *fast_rx;
- struct ieee80211_rx_data rx;
-+ int link_id = -1;
-
- memset(&rx, 0, sizeof(rx));
- rx.skb = skb;
-@@ -4907,12 +4908,8 @@ static void __ieee80211_rx_handle_8023(struct ieee80211_hw *hw,
- if (!pubsta)
- goto drop;
-
-- rx.sta = container_of(pubsta, struct sta_info, sta);
-- rx.sdata = rx.sta->sdata;
--
-- if (status->link_valid &&
-- !ieee80211_rx_is_valid_sta_link_id(pubsta, status->link_id))
-- goto drop;
-+ if (status->link_valid)
-+ link_id = status->link_id;
-
- /*
- * TODO: Should the frame be dropped if the right link_id is not
-@@ -4921,19 +4918,8 @@ static void __ieee80211_rx_handle_8023(struct ieee80211_hw *hw,
- * link_id is used only for stats purpose and updating the stats on
- * the deflink is fine?
- */
-- if (status->link_valid)
-- rx.link_id = status->link_id;
--
-- if (rx.link_id >= 0) {
-- struct ieee80211_link_data *link;
--
-- link = rcu_dereference(rx.sdata->link[rx.link_id]);
-- if (!link)
-- goto drop;
-- rx.link = link;
-- } else {
-- rx.link = &rx.sdata->deflink;
-- }
-+ if (!ieee80211_rx_data_set_sta(&rx, pubsta, link_id))
-+ goto drop;
-
- fast_rx = rcu_dereference(rx.sta->fast_rx);
- if (!fast_rx)
-@@ -4951,6 +4937,8 @@ static bool ieee80211_rx_for_interface(struct ieee80211_rx_data *rx,
- {
- struct link_sta_info *link_sta;
- struct ieee80211_hdr *hdr = (void *)skb->data;
-+ struct sta_info *sta;
-+ int link_id = -1;
-
- /*
- * Look up link station first, in case there's a
-@@ -4960,24 +4948,19 @@ static bool ieee80211_rx_for_interface(struct ieee80211_rx_data *rx,
- */
- link_sta = link_sta_info_get_bss(rx->sdata, hdr->addr2);
- if (link_sta) {
-- rx->sta = link_sta->sta;
-- rx->link_id = link_sta->link_id;
-+ sta = link_sta->sta;
-+ link_id = link_sta->link_id;
- } else {
- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-
-- rx->sta = sta_info_get_bss(rx->sdata, hdr->addr2);
-- if (rx->sta) {
-- if (status->link_valid &&
-- !ieee80211_rx_is_valid_sta_link_id(&rx->sta->sta,
-- status->link_id))
-- return false;
--
-- rx->link_id = status->link_valid ? status->link_id : -1;
-- } else {
-- rx->link_id = -1;
-- }
-+ sta = sta_info_get_bss(rx->sdata, hdr->addr2);
-+ if (status->link_valid)
-+ link_id = status->link_id;
- }
-
-+ if (!ieee80211_rx_data_set_sta(rx, &sta->sta, link_id))
-+ return false;
-+
- return ieee80211_prepare_and_rx_handle(rx, skb, consume);
- }
-
-@@ -5036,19 +5019,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
-
- if (ieee80211_is_data(fc)) {
- struct sta_info *sta, *prev_sta;
-- u8 link_id = status->link_id;
-+ int link_id = -1;
-
-- if (pubsta) {
-- rx.sta = container_of(pubsta, struct sta_info, sta);
-- rx.sdata = rx.sta->sdata;
-+ if (status->link_valid)
-+ link_id = status->link_id;
-
-- if (status->link_valid &&
-- !ieee80211_rx_is_valid_sta_link_id(pubsta, link_id))
-+ if (pubsta) {
-+ if (!ieee80211_rx_data_set_sta(&rx, pubsta, link_id))
- goto out;
-
-- if (status->link_valid)
-- rx.link_id = status->link_id;
--
- /*
- * In MLO connection, fetch the link_id using addr2
- * when the driver does not pass link_id in status.
-@@ -5066,7 +5045,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
- if (!link_sta)
- goto out;
-
-- rx.link_id = link_sta->link_id;
-+ ieee80211_rx_data_set_link(&rx, link_sta->link_id);
- }
-
- if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
-@@ -5082,30 +5061,27 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
- continue;
- }
-
-- if ((status->link_valid &&
-- !ieee80211_rx_is_valid_sta_link_id(&prev_sta->sta,
-- link_id)) ||
-- (!status->link_valid && prev_sta->sta.mlo))
-+ rx.sdata = prev_sta->sdata;
-+ if (!ieee80211_rx_data_set_sta(&rx, &prev_sta->sta,
-+ link_id))
-+ goto out;
-+
-+ if (!status->link_valid && prev_sta->sta.mlo)
- continue;
-
-- rx.link_id = status->link_valid ? link_id : -1;
-- rx.sta = prev_sta;
-- rx.sdata = prev_sta->sdata;
- ieee80211_prepare_and_rx_handle(&rx, skb, false);
-
- prev_sta = sta;
- }
-
- if (prev_sta) {
-- if ((status->link_valid &&
-- !ieee80211_rx_is_valid_sta_link_id(&prev_sta->sta,
-- link_id)) ||
-- (!status->link_valid && prev_sta->sta.mlo))
-+ rx.sdata = prev_sta->sdata;
-+ if (!ieee80211_rx_data_set_sta(&rx, &prev_sta->sta,
-+ link_id))
- goto out;
-
-- rx.link_id = status->link_valid ? link_id : -1;
-- rx.sta = prev_sta;
-- rx.sdata = prev_sta->sdata;
-+ if (!status->link_valid && prev_sta->sta.mlo)
-+ goto out;
-
- if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
- return;
---
-2.39.1
-
diff --git a/0005-drm-amdgpu-display-mst-limit-payload-to-be-updated-o.patch b/0005-drm-amdgpu-display-mst-limit-payload-to-be-updated-o.patch
new file mode 100644
index 000000000000..be1dfdf5f577
--- /dev/null
+++ b/0005-drm-amdgpu-display-mst-limit-payload-to-be-updated-o.patch
@@ -0,0 +1,105 @@
+From 50811dff5e09b96380a305d5e44de1f17d9cd7c0 Mon Sep 17 00:00:00 2001
+From: Wayne Lin <Wayne.Lin@amd.com>
+Date: Fri, 9 Dec 2022 19:05:33 +0800
+Subject: [PATCH 5/8] drm/amdgpu/display/mst: limit payload to be updated one
+ by one
+
+[Why]
+amdgpu expects to update payload table for one stream one time
+by calling dm_helpers_dp_mst_write_payload_allocation_table().
+Currently, it get modified to try to update HW payload table
+at once by referring mst_state.
+
+[How]
+This is just a quick workaround. Should find way to remove the
+temporary struct dc_dp_mst_stream_allocation_table later if set
+struct link_mst_stream_allocatio directly is possible.
+
+Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/2171
+Signed-off-by: Wayne Lin <Wayne.Lin@amd.com>
+Signed-off-by: Harry Wentland <harry.wentland@amd.com>
+Fixes: 4d07b0bc4034 ("drm/display/dp_mst: Move all payload info into the atomic state")
+Cc: stable@vger.kernel.org # 6.1
+Acked-by: Harry Wentland <harry.wentland@amd.com>
+---
+ .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 51 ++++++++++++++-----
+ 1 file changed, 39 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+index f72c013d3a5b..16623f73ddbe 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+@@ -120,23 +120,50 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
+ }
+
+ static void
+-fill_dc_mst_payload_table_from_drm(struct drm_dp_mst_topology_state *mst_state,
+- struct amdgpu_dm_connector *aconnector,
++fill_dc_mst_payload_table_from_drm(struct dc_link *link,
++ bool enable,
++ struct drm_dp_mst_atomic_payload *target_payload,
+ struct dc_dp_mst_stream_allocation_table *table)
+ {
+ struct dc_dp_mst_stream_allocation_table new_table = { 0 };
+ struct dc_dp_mst_stream_allocation *sa;
+- struct drm_dp_mst_atomic_payload *payload;
++ struct link_mst_stream_allocation_table copy_of_link_table =
++ link->mst_stream_alloc_table;
++
++ int i;
++ int current_hw_table_stream_cnt = copy_of_link_table.stream_count;
++ struct link_mst_stream_allocation *dc_alloc;
++
++ /* TODO: refactor to set link->mst_stream_alloc_table directly if possible.*/
++ if (enable) {
++ dc_alloc =
++ &copy_of_link_table.stream_allocations[current_hw_table_stream_cnt];
++ dc_alloc->vcp_id = target_payload->vcpi;
++ dc_alloc->slot_count = target_payload->time_slots;
++ } else {
++ for (i = 0; i < copy_of_link_table.stream_count; i++) {
++ dc_alloc =
++ &copy_of_link_table.stream_allocations[i];
++
++ if (dc_alloc->vcp_id == target_payload->vcpi) {
++ dc_alloc->vcp_id = 0;
++ dc_alloc->slot_count = 0;
++ break;
++ }
++ }
++ ASSERT(i != copy_of_link_table.stream_count);
++ }
+
+ /* Fill payload info*/
+- list_for_each_entry(payload, &mst_state->payloads, next) {
+- if (payload->delete)
+- continue;
+-
+- sa = &new_table.stream_allocations[new_table.stream_count];
+- sa->slot_count = payload->time_slots;
+- sa->vcp_id = payload->vcpi;
+- new_table.stream_count++;
++ for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
++ dc_alloc =
++ &copy_of_link_table.stream_allocations[i];
++ if (dc_alloc->vcp_id > 0 && dc_alloc->slot_count > 0) {
++ sa = &new_table.stream_allocations[new_table.stream_count];
++ sa->slot_count = dc_alloc->slot_count;
++ sa->vcp_id = dc_alloc->vcp_id;
++ new_table.stream_count++;
++ }
+ }
+
+ /* Overwrite the old table */
+@@ -185,7 +212,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
+ * AUX message. The sequence is slot 1-63 allocated sequence for each
+ * stream. AMD ASIC stream slot allocation should follow the same
+ * sequence. copy DRM MST allocation to dc */
+- fill_dc_mst_payload_table_from_drm(mst_state, aconnector, proposed_table);
++ fill_dc_mst_payload_table_from_drm(stream->link, enable, payload, proposed_table);
+
+ return true;
+ }
+--
+2.39.1
+
diff --git a/0006-drm-amdgpu-display-mst-update-mst_mgr-relevant-varia.patch b/0006-drm-amdgpu-display-mst-update-mst_mgr-relevant-varia.patch
new file mode 100644
index 000000000000..361cfa02308a
--- /dev/null
+++ b/0006-drm-amdgpu-display-mst-update-mst_mgr-relevant-varia.patch
@@ -0,0 +1,73 @@
+From 40b9d0489f5ab85733605a5112f4f6bb22ec7c9e Mon Sep 17 00:00:00 2001
+From: Wayne Lin <Wayne.Lin@amd.com>
+Date: Mon, 12 Dec 2022 15:41:18 +0800
+Subject: [PATCH 6/8] drm/amdgpu/display/mst: update mst_mgr relevant variable
+ when long HPD
+
+[Why & How]
+Now the vc_start_slot is controlled at drm side. When we
+service a long HPD, we still need to run
+dm_helpers_dp_mst_write_payload_allocation_table() to update
+drm mst_mgr's relevant variable. Otherwise, on the next plug-in,
+payload will get assigned with a wrong start slot.
+
+Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/2171
+Signed-off-by: Wayne Lin <Wayne.Lin@amd.com>
+Signed-off-by: Harry Wentland <harry.wentland@amd.com>
+Fixes: 4d07b0bc4034 ("drm/display/dp_mst: Move all payload info into the atomic state")
+Cc: stable@vger.kernel.org # 6.1
+Acked-by: Harry Wentland <harry.wentland@amd.com>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_link.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+index d7b1ace6328a..40b9d2ce08e6 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+@@ -3995,10 +3995,13 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
+ struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0);
+ int i;
+ bool mst_mode = (link->type == dc_connection_mst_branch);
++ /* adjust for drm changes*/
++ bool update_drm_mst_state = true;
+ const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
+ const struct dc_link_settings empty_link_settings = {0};
+ DC_LOGGER_INIT(link->ctx->logger);
+
++
+ /* deallocate_mst_payload is called before disable link. When mode or
+ * disable/enable monitor, new stream is created which is not in link
+ * stream[] yet. For this, payload is not allocated yet, so de-alloc
+@@ -4014,7 +4017,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
+ &empty_link_settings,
+ avg_time_slots_per_mtp);
+
+- if (mst_mode) {
++ if (mst_mode || update_drm_mst_state) {
+ /* when link is in mst mode, reply on mst manager to remove
+ * payload
+ */
+@@ -4077,11 +4080,18 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
+ stream->ctx,
+ stream);
+
++ if (!update_drm_mst_state)
++ dm_helpers_dp_mst_send_payload_allocation(
++ stream->ctx,
++ stream,
++ false);
++ }
++
++ if (update_drm_mst_state)
+ dm_helpers_dp_mst_send_payload_allocation(
+ stream->ctx,
+ stream,
+ false);
+- }
+
+ return DC_OK;
+ }
+--
+2.39.1
+
diff --git a/0007-drm-display-dp_mst-Correct-the-kref-of-port.patch b/0007-drm-display-dp_mst-Correct-the-kref-of-port.patch
new file mode 100644
index 000000000000..f41c78342a4e
--- /dev/null
+++ b/0007-drm-display-dp_mst-Correct-the-kref-of-port.patch
@@ -0,0 +1,44 @@
+From cb872cf86fe3ade981c51530cf0422472a1c55fe Mon Sep 17 00:00:00 2001
+From: Wayne Lin <Wayne.Lin@amd.com>
+Date: Wed, 28 Dec 2022 14:50:43 +0800
+Subject: [PATCH 7/8] drm/display/dp_mst: Correct the kref of port.
+
+[why & how]
+We still need to refer to port while removing payload at commit_tail.
+we should keep the kref till then to release.
+
+Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/2171
+Signed-off-by: Wayne Lin <Wayne.Lin@amd.com>
+Signed-off-by: Harry Wentland <harry.wentland@amd.com>
+Fixes: 4d07b0bc4034 ("drm/display/dp_mst: Move all payload info into the atomic state")
+Cc: stable@vger.kernel.org # 6.1
+Acked-by: Harry Wentland <harry.wentland@amd.com>
+---
+ drivers/gpu/drm/display/drm_dp_mst_topology.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
+index 51a46689cda7..4ca37261584a 100644
+--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
++++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
+@@ -3372,6 +3372,9 @@ void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
+
+ mgr->payload_count--;
+ mgr->next_start_slot -= payload->time_slots;
++
++ if (payload->delete)
++ drm_dp_mst_put_port_malloc(payload->port);
+ }
+ EXPORT_SYMBOL(drm_dp_remove_payload);
+
+@@ -4327,7 +4330,6 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state,
+
+ drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, payload->time_slots);
+ if (!payload->delete) {
+- drm_dp_mst_put_port_malloc(port);
+ payload->pbn = 0;
+ payload->delete = true;
+ topology_state->payload_mask &= ~BIT(payload->vcpi - 1);
+--
+2.39.1
+
diff --git a/PKGBUILD b/PKGBUILD
index 1eea35a4ae48..9721695007c1 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -68,7 +68,7 @@ _subarch=
### IMPORTANT: Do no edit below this line unless you know what you're doing
pkgbase=linux-ck
-pkgver=6.1.7
+pkgver=6.1.8
pkgrel=1
arch=(x86_64)
url="https://wiki.archlinux.org/index.php/Linux-ck"
@@ -91,23 +91,29 @@ source=(
"more-uarches-$_gcc_more_v.tar.gz::https://github.com/graysky2/kernel_compiler_patch/archive/$_gcc_more_v.tar.gz"
"ck-hrtimer-$_commit.tar.gz::https://github.com/graysky2/linux-patches/archive/$_commit.tar.gz"
0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-C.patch
- 0002-Revert-drm-display-dp_mst-Move-all-payload-info-into.patch
- 0003-btrfs-fix-invalid-leaf-access-due-to-inline-extent-d.patch
- 0004-wifi-mac80211-fix-initialization-of-rx-link-and-rx-l.patch
+ 0002-Revert-drm-i915-improve-the-catch-all-evict-to-handl.patch
+ 0003-drm-i915-improve-the-catch-all-evict-to-handle-lock-.patch
+ 0004-drm-amdgpu-display-mst-Fix-mst_state-pbn_div-and-slo.patch
+ 0005-drm-amdgpu-display-mst-limit-payload-to-be-updated-o.patch
+ 0006-drm-amdgpu-display-mst-update-mst_mgr-relevant-varia.patch
+ 0007-drm-display-dp_mst-Correct-the-kref-of-port.patch
)
validpgpkeys=(
'ABAF11C65A2970B130ABE3C479BE3E4300411886' # Linus Torvalds
'647F28654894E3BD457199BE38DBBDC86092693E' # Greg Kroah-Hartman
)
-sha256sums=('4ab048bad2e7380d3b827f1fad5ad2d2fc4f2e80e1c604d85d1f8781debe600f'
+sha256sums=('b60bb53ab8ba370a270454b11e93d41af29126fc72bd6ede517673e2e57b816d'
'SKIP'
'1efa33aea067fa920880ef7fef3ec82f8d4cde21213eda34ac6534ca6879fca0'
'f1d586e111932890ad5e0df15d092fb9b3f87bae4ea17812aae9b0ec98fe2db0'
'6d3b9cb4639c1c5eb4e2697aed0dbffa5b4a37d63a0861dec8315dd052723e0e'
- 'b28485e4b036abc85725f9c3ee036b83b31905f35567088f5c4b678371832c42'
- 'de5af5d1bad793cf3959df743f50a07421156e3e5e7ec95999f78089c2df2b17'
- '2ef9b1da56c0ccc615112713a516a2f6e275d3cde5d0aab2666c43a12d065443'
- '68cc969cb5f4c5e1733260230cf13f64a1c59289b770058cd960f1550fe4d71f')
+ 'dd0a155f8be7face604741716e5ea1ccd47c7988d4db4476f9736def57a6ae86'
+ 'b734f0f038647618617226794298b1cc7f6928dd43d46f056486a7d664fff3e0'
+ 'b725cde6ef68dcb2fe59a1e8646938d95d25a7292910dceef1adaeae229749e6'
+ '1aaa3c58e4129804eb704fbb66e1fe9a18d37059516f4153bb375a406a3c373a'
+ '6448060153217445d35f0f2191424acac53defe7a67f08cb7f7347c141bd535e'
+ 'a3c9ed15a33b7e7f1f589e6b0b00482b78aa7a0044940e4e3f87ad542db9308e'
+ '28d3e5daa705da23bdafc916695bc50cc8f65655c8965fb6d007d67dfa6cb52f')
prepare() {
cd linux-${pkgver}