]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.7
authorSasha Levin <sashal@kernel.org>
Sun, 31 Mar 2024 13:26:24 +0000 (09:26 -0400)
committerSasha Levin <sashal@kernel.org>
Sun, 31 Mar 2024 13:26:24 +0000 (09:26 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-6.7/drm-amd-display-set-odm_combine_policy-based-on-cont.patch [new file with mode: 0644]
queue-6.7/drm-amdgpu-display-address-kdoc-for-is_psr_su-in-fil.patch [new file with mode: 0644]
queue-6.7/drm-amdgpu-make-damage-clips-support-configurable.patch [new file with mode: 0644]
queue-6.7/series
queue-6.7/vfio-pds-make-sure-migration-file-isn-t-accessed-aft.patch [new file with mode: 0644]

diff --git a/queue-6.7/drm-amd-display-set-odm_combine_policy-based-on-cont.patch b/queue-6.7/drm-amd-display-set-odm_combine_policy-based-on-cont.patch
new file mode 100644 (file)
index 0000000..2732249
--- /dev/null
@@ -0,0 +1,161 @@
+From 6af4debf6b17e843bdfa9a46c447cb66d1710ead Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 18 Jan 2024 18:12:15 -0500
+Subject: drm/amd/display: set odm_combine_policy based on context in dcn32
+ resource
+
+From: Wenjing Liu <wenjing.liu@amd.com>
+
+[ Upstream commit 0a5fd7811a17af708cefdaab93af86838353002d ]
+
+[why]
+When populating dml pipes, odm combine policy should be assigned based
+on the pipe topology of the context passed in. DML pipes could be
+repopulated multiple times during single validate bandwidth attempt. We
+need to make sure that whenever we repopulate the dml pipes it is always
+aligned with the updated context. There is a case where DML pipes get
+repopulated during FPO optimization after ODM combine policy is changed.
+Since in the current code we reinitlaize ODM combine policy, even though
+the current context has ODM combine enabled, we overwrite it despite the
+pipes are already split. This causes DML to think that MPC combine is
+used so we mistakenly enable MPC combine because we apply pipe split
+with ODM combine policy reset. This issue doesn't impact non windowed
+MPO with ODM case because the legacy policy has restricted use cases. We
+don't encounter the case where both ODM and FPO optimizations are
+enabled together. So we decide to leave it as is because it is about to
+be replaced anyway.
+
+Cc: stable@vger.kernel.org # 6.6+
+Reviewed-by: Chaitanya Dhere <chaitanya.dhere@amd.com>
+Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
+Acked-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Wenjing Liu <wenjing.liu@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../drm/amd/display/dc/dcn32/dcn32_resource.c | 16 ++++++++++++++-
+ .../drm/amd/display/dc/dml/dcn32/dcn32_fpu.c  | 15 ++++++++++----
+ drivers/gpu/drm/amd/display/dc/inc/resource.h | 20 ++++++++-----------
+ 3 files changed, 34 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
+index cc468bdcb3de2..f663de1cdcdca 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
+@@ -1925,7 +1925,21 @@ int dcn32_populate_dml_pipes_from_context(
+               dcn32_zero_pipe_dcc_fraction(pipes, pipe_cnt);
+               DC_FP_END();
+               pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch;
+-              pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal;
++              if (dc->config.enable_windowed_mpo_odm &&
++                              dc->debug.enable_single_display_2to1_odm_policy) {
++                      switch (resource_get_odm_slice_count(pipe)) {
++                      case 2:
++                              pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1;
++                              break;
++                      case 4:
++                              pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_4to1;
++                              break;
++                      default:
++                              pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal;
++                      }
++              } else {
++                      pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal;
++              }
+               pipes[pipe_cnt].pipe.src.gpuvm_min_page_size_kbytes = 256; // according to spreadsheet
+               pipes[pipe_cnt].pipe.src.unbounded_req_mode = false;
+               pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_19;
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+index 5b6d9643b02dc..b315ca6f1cee8 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+@@ -1265,7 +1265,7 @@ static bool update_pipes_with_split_flags(struct dc *dc, struct dc_state *contex
+       return updated;
+ }
+-static bool should_allow_odm_power_optimization(struct dc *dc,
++static bool should_apply_odm_power_optimization(struct dc *dc,
+               struct dc_state *context, struct vba_vars_st *v, int *split,
+               bool *merge)
+ {
+@@ -1369,9 +1369,12 @@ static void try_odm_power_optimization_and_revalidate(
+ {
+       int i;
+       unsigned int new_vlevel;
++      unsigned int cur_policy[MAX_PIPES];
+-      for (i = 0; i < pipe_cnt; i++)
++      for (i = 0; i < pipe_cnt; i++) {
++              cur_policy[i] = pipes[i].pipe.dest.odm_combine_policy;
+               pipes[i].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1;
++      }
+       new_vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
+@@ -1380,6 +1383,9 @@ static void try_odm_power_optimization_and_revalidate(
+               memset(merge, 0, MAX_PIPES * sizeof(bool));
+               *vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, new_vlevel, split, merge);
+               context->bw_ctx.dml.vba.VoltageLevel = *vlevel;
++      } else {
++              for (i = 0; i < pipe_cnt; i++)
++                      pipes[i].pipe.dest.odm_combine_policy = cur_policy[i];
+       }
+ }
+@@ -1550,7 +1556,7 @@ static void dcn32_full_validate_bw_helper(struct dc *dc,
+               }
+       }
+-      if (should_allow_odm_power_optimization(dc, context, vba, split, merge))
++      if (should_apply_odm_power_optimization(dc, context, vba, split, merge))
+               try_odm_power_optimization_and_revalidate(
+                               dc, context, pipes, split, merge, vlevel, *pipe_cnt);
+@@ -2178,7 +2184,8 @@ bool dcn32_internal_validate_bw(struct dc *dc,
+               int i;
+               pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate);
+-              dcn32_update_dml_pipes_odm_policy_based_on_context(dc, context, pipes);
++              if (!dc->config.enable_windowed_mpo_odm)
++                      dcn32_update_dml_pipes_odm_policy_based_on_context(dc, context, pipes);
+               /* repopulate_pipes = 1 means the pipes were either split or merged. In this case
+                * we have to re-calculate the DET allocation and run through DML once more to
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h
+index 06ca8bfb91e7d..3d7244393807a 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/resource.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h
+@@ -427,22 +427,18 @@ struct pipe_ctx *resource_get_primary_dpp_pipe(const struct pipe_ctx *dpp_pipe);
+ int resource_get_mpc_slice_index(const struct pipe_ctx *dpp_pipe);
+ /*
+- * Get number of MPC "cuts" of the plane associated with the pipe. MPC slice
+- * count is equal to MPC splits + 1. For example if a plane is cut 3 times, it
+- * will have 4 pieces of slice.
+- * return - 0 if pipe is not used for a plane with MPCC combine. otherwise
+- * the number of MPC "cuts" for the plane.
++ * Get the number of MPC slices associated with the pipe.
++ * The function returns 0 if the pipe is not associated with an MPC combine
++ * pipe topology.
+  */
+-int resource_get_mpc_slice_count(const struct pipe_ctx *opp_head);
++int resource_get_mpc_slice_count(const struct pipe_ctx *pipe);
+ /*
+- * Get number of ODM "cuts" of the timing associated with the pipe. ODM slice
+- * count is equal to ODM splits + 1. For example if a timing is cut 3 times, it
+- * will have 4 pieces of slice.
+- * return - 0 if pipe is not used for ODM combine. otherwise
+- * the number of ODM "cuts" for the timing.
++ * Get the number of ODM slices associated with the pipe.
++ * The function returns 0 if the pipe is not associated with an ODM combine
++ * pipe topology.
+  */
+-int resource_get_odm_slice_count(const struct pipe_ctx *otg_master);
++int resource_get_odm_slice_count(const struct pipe_ctx *pipe);
+ /* Get the ODM slice index counting from 0 from left most slice */
+ int resource_get_odm_slice_index(const struct pipe_ctx *opp_head);
+-- 
+2.43.0
+
diff --git a/queue-6.7/drm-amdgpu-display-address-kdoc-for-is_psr_su-in-fil.patch b/queue-6.7/drm-amdgpu-display-address-kdoc-for-is_psr_su-in-fil.patch
new file mode 100644 (file)
index 0000000..5967aa1
--- /dev/null
@@ -0,0 +1,51 @@
+From 336b347ab3f9209845f0d7aa6fdab8d27702ae8c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Feb 2024 18:25:40 +0530
+Subject: drm/amdgpu/display: Address kdoc for 'is_psr_su' in
+ 'fill_dc_dirty_rects'
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit 3651306ae4c7f3f54caa9feb826a93cc69ccebbf ]
+
+The is_psr_su parameter is a boolean flag indicating whether the Panel
+Self Refresh Selective Update (PSR SU) feature is enabled which is a
+power-saving feature that allows only the updated regions of the screen
+to be refreshed, reducing the amount of data that needs to be sent to
+the display.
+
+Fixes the below with gcc W=1:
+drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:5257: warning: Function parameter or member 'is_psr_su' not described in 'fill_dc_dirty_rects'
+
+Fixes: d16df040c8da ("drm/amdgpu: make damage clips support configurable")
+Cc: stable@vger.kernel.org
+Cc: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Cc: Mario Limonciello <mario.limonciello@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+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 342e41c78fb34..dafe9562a7370 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -5129,6 +5129,10 @@ static inline void fill_dc_dirty_rect(struct drm_plane *plane,
+  * @new_plane_state: New state of @plane
+  * @crtc_state: New state of CRTC connected to the @plane
+  * @flip_addrs: DC flip tracking struct, which also tracts dirty rects
++ * @is_psr_su: Flag indicating whether Panel Self Refresh Selective Update (PSR SU) is enabled.
++ *             If PSR SU is enabled and damage clips are available, only the regions of the screen
++ *             that have changed will be updated. If PSR SU is not enabled,
++ *             or if damage clips are not available, the entire screen will be updated.
+  * @dirty_regions_changed: dirty regions changed
+  *
+  * For PSR SU, DC informs the DMUB uController of dirty rectangle regions
+-- 
+2.43.0
+
diff --git a/queue-6.7/drm-amdgpu-make-damage-clips-support-configurable.patch b/queue-6.7/drm-amdgpu-make-damage-clips-support-configurable.patch
new file mode 100644 (file)
index 0000000..d066ff4
--- /dev/null
@@ -0,0 +1,103 @@
+From 6b7addaf573fcfd3711bcb41fbe33b23597274c9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Feb 2024 16:23:29 -0500
+Subject: drm/amdgpu: make damage clips support configurable
+
+From: Hamza Mahfooz <hamza.mahfooz@amd.com>
+
+[ Upstream commit fc184dbe9fd99ad2dfb197b6fe18768bae1774b1 ]
+
+We have observed that there are quite a number of PSR-SU panels on the
+market that are unable to keep up with what user space throws at them,
+resulting in hangs and random black screens. So, make damage clips
+support configurable and disable it by default for PSR-SU displays.
+
+Cc: stable@vger.kernel.org
+Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu.h               |  1 +
+ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c           | 13 +++++++++++++
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  7 +++++++
+ 3 files changed, 21 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+index 31d4b5a2c5e83..13c62a26aa19c 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+@@ -198,6 +198,7 @@ extern uint amdgpu_dc_debug_mask;
+ extern uint amdgpu_dc_visual_confirm;
+ extern uint amdgpu_dm_abm_level;
+ extern int amdgpu_backlight;
++extern int amdgpu_damage_clips;
+ extern struct amdgpu_mgpu_info mgpu_info;
+ extern int amdgpu_ras_enable;
+ extern uint amdgpu_ras_mask;
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+index 10c4a8cfa18a0..855ab596323c7 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+@@ -209,6 +209,7 @@ int amdgpu_umsch_mm;
+ int amdgpu_seamless = -1; /* auto */
+ uint amdgpu_debug_mask;
+ int amdgpu_agp = -1; /* auto */
++int amdgpu_damage_clips = -1; /* auto */
+ static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work);
+@@ -857,6 +858,18 @@ int amdgpu_backlight = -1;
+ MODULE_PARM_DESC(backlight, "Backlight control (0 = pwm, 1 = aux, -1 auto (default))");
+ module_param_named(backlight, amdgpu_backlight, bint, 0444);
++/**
++ * DOC: damageclips (int)
++ * Enable or disable damage clips support. If damage clips support is disabled,
++ * we will force full frame updates, irrespective of what user space sends to
++ * us.
++ *
++ * Defaults to -1 (where it is enabled unless a PSR-SU display is detected).
++ */
++MODULE_PARM_DESC(damageclips,
++               "Damage clips support (0 = disable, 1 = enable, -1 auto (default))");
++module_param_named(damageclips, amdgpu_damage_clips, int, 0444);
++
+ /**
+  * DOC: tmz (int)
+  * Trusted Memory Zone (TMZ) is a method to protect data being written
+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 f5dceb4eb99a3..342e41c78fb34 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -5147,6 +5147,7 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
+                               struct drm_plane_state *new_plane_state,
+                               struct drm_crtc_state *crtc_state,
+                               struct dc_flip_addrs *flip_addrs,
++                              bool is_psr_su,
+                               bool *dirty_regions_changed)
+ {
+       struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state);
+@@ -5171,6 +5172,10 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
+       num_clips = drm_plane_get_damage_clips_count(new_plane_state);
+       clips = drm_plane_get_damage_clips(new_plane_state);
++      if (num_clips && (!amdgpu_damage_clips || (amdgpu_damage_clips < 0 &&
++                                                 is_psr_su)))
++              goto ffu;
++
+       if (!dm_crtc_state->mpo_requested) {
+               if (!num_clips || num_clips > DC_MAX_DIRTY_RECTS)
+                       goto ffu;
+@@ -8216,6 +8221,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
+                       fill_dc_dirty_rects(plane, old_plane_state,
+                                           new_plane_state, new_crtc_state,
+                                           &bundle->flip_addrs[planes_count],
++                                          acrtc_state->stream->link->psr_settings.psr_version ==
++                                          DC_PSR_VERSION_SU_1,
+                                           &dirty_rects_changed);
+                       /*
+-- 
+2.43.0
+
index 11cd1af6a9c5c47924750778278a6e5eebf426d5..a2ec82fc3f4a5db311ee9c3c8ca586e4e3b070d8 100644 (file)
@@ -381,3 +381,7 @@ revert-usb-phy-generic-get-the-vbus-supply.patch
 usb-cdc-wdm-close-race-between-read-and-workqueue.patch
 usb-misc-ljca-fix-double-free-in-error-handling-path.patch
 usb-uas-return-enodev-when-submit-urbs-fail-with-device-not-attached.patch
+drm-amd-display-set-odm_combine_policy-based-on-cont.patch
+drm-amdgpu-make-damage-clips-support-configurable.patch
+drm-amdgpu-display-address-kdoc-for-is_psr_su-in-fil.patch
+vfio-pds-make-sure-migration-file-isn-t-accessed-aft.patch
diff --git a/queue-6.7/vfio-pds-make-sure-migration-file-isn-t-accessed-aft.patch b/queue-6.7/vfio-pds-make-sure-migration-file-isn-t-accessed-aft.patch
new file mode 100644 (file)
index 0000000..031d577
--- /dev/null
@@ -0,0 +1,110 @@
+From 8da00a760f7e25ef222ec07dc9030bb0fe7555b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Mar 2024 10:21:48 -0800
+Subject: vfio/pds: Make sure migration file isn't accessed after reset
+
+From: Brett Creeley <brett.creeley@amd.com>
+
+[ Upstream commit 457f7308254756b6e4b8fc3876cb770dcf0e7cc7 ]
+
+It's possible the migration file is accessed after reset when it has
+been cleaned up, especially when it's initiated by the device. This is
+because the driver doesn't rip out the filep when cleaning up it only
+frees the related page structures and sets its local struct
+pds_vfio_lm_file pointer to NULL. This can cause a NULL pointer
+dereference, which is shown in the example below during a restore after
+a device initiated reset:
+
+BUG: kernel NULL pointer dereference, address: 000000000000000c
+PF: supervisor read access in kernel mode
+PF: error_code(0x0000) - not-present page
+PGD 0 P4D 0
+Oops: 0000 [#1] PREEMPT SMP NOPTI
+RIP: 0010:pds_vfio_get_file_page+0x5d/0xf0 [pds_vfio_pci]
+[...]
+Call Trace:
+ <TASK>
+ pds_vfio_restore_write+0xf6/0x160 [pds_vfio_pci]
+ vfs_write+0xc9/0x3f0
+ ? __fget_light+0xc9/0x110
+ ksys_write+0xb5/0xf0
+ __x64_sys_write+0x1a/0x20
+ do_syscall_64+0x38/0x90
+ entry_SYSCALL_64_after_hwframe+0x63/0xcd
+[...]
+
+Add a disabled flag to the driver's struct pds_vfio_lm_file that gets
+set during cleanup. Then make sure to check the flag when the migration
+file is accessed via its file_operations. By default this flag will be
+false as the memory for struct pds_vfio_lm_file is kzalloc'd, which means
+the struct pds_vfio_lm_file is enabled and accessible. Also, since the
+file_operations and driver's migration file cleanup happen under the
+protection of the same pds_vfio_lm_file.lock, using this flag is thread
+safe.
+
+Fixes: 8512ed256334 ("vfio/pds: Always clear the save/restore FDs on reset")
+Reviewed-by: Shannon Nelson <shannon.nelson@amd.com>
+Signed-off-by: Brett Creeley <brett.creeley@amd.com>
+Link: https://lore.kernel.org/r/20240308182149.22036-2-brett.creeley@amd.com
+Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vfio/pci/pds/lm.c | 13 +++++++++++++
+ drivers/vfio/pci/pds/lm.h |  1 +
+ 2 files changed, 14 insertions(+)
+
+diff --git a/drivers/vfio/pci/pds/lm.c b/drivers/vfio/pci/pds/lm.c
+index 79fe2e66bb498..6b94cc0bf45b4 100644
+--- a/drivers/vfio/pci/pds/lm.c
++++ b/drivers/vfio/pci/pds/lm.c
+@@ -92,8 +92,10 @@ static void pds_vfio_put_lm_file(struct pds_vfio_lm_file *lm_file)
+ {
+       mutex_lock(&lm_file->lock);
++      lm_file->disabled = true;
+       lm_file->size = 0;
+       lm_file->alloc_size = 0;
++      lm_file->filep->f_pos = 0;
+       /* Free scatter list of file pages */
+       sg_free_table(&lm_file->sg_table);
+@@ -183,6 +185,12 @@ static ssize_t pds_vfio_save_read(struct file *filp, char __user *buf,
+       pos = &filp->f_pos;
+       mutex_lock(&lm_file->lock);
++
++      if (lm_file->disabled) {
++              done = -ENODEV;
++              goto out_unlock;
++      }
++
+       if (*pos > lm_file->size) {
+               done = -EINVAL;
+               goto out_unlock;
+@@ -283,6 +291,11 @@ static ssize_t pds_vfio_restore_write(struct file *filp, const char __user *buf,
+       mutex_lock(&lm_file->lock);
++      if (lm_file->disabled) {
++              done = -ENODEV;
++              goto out_unlock;
++      }
++
+       while (len) {
+               size_t page_offset;
+               struct page *page;
+diff --git a/drivers/vfio/pci/pds/lm.h b/drivers/vfio/pci/pds/lm.h
+index 13be893198b74..9511b1afc6a11 100644
+--- a/drivers/vfio/pci/pds/lm.h
++++ b/drivers/vfio/pci/pds/lm.h
+@@ -27,6 +27,7 @@ struct pds_vfio_lm_file {
+       struct scatterlist *last_offset_sg;     /* Iterator */
+       unsigned int sg_last_entry;
+       unsigned long last_offset;
++      bool disabled;
+ };
+ struct pds_vfio_pci_device;
+-- 
+2.43.0
+