Add to_intel_uncore() function to avoid the inclusion of i915_drv.h from
intel_de.h. This reveals a number of implicit dependencies on i915_drv.h
that need to be added.
For now, to_intel_uncore() can be an inline function, with all the
includes in compat intel_uncore.h, as long as i915_drv.h isn't
included. The implicit dependencies on i915_drv.h is a problem in
display code, but the same is not true for xe_device.h etc.
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/377e2b400d126776224fc49874ed9cb03ac3123c.1732104170.git.jani.nikula@intel.com
We will need to flush the release work from outside in an upcoming
change. Let's put that into a public interface and call it
intel_dmc_wl_flush_release_work().
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241129164010.29887-2-gustavo.sousa@intel.com
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Although Bspec doesn't explicitly mentions that, as of Xe3_LPD, using
DMC wakelock is the officially recommended way of accessing registers
that would be off during DC5/DC6 and the legacy method (where the DMC
intercepts MMIO to wake up the hardware) is to be avoided.
As such, update the driver to use the DMC wakelock by default starting
with Xe3_LPD. Since the feature is somewhat new to the driver, also
allow disabling it via a module parameter for debugging purposes.
For that, make the existing parameter allow values -1 (per-chip
default), 0 (disabled) and 1 (enabled), similarly to what is done for
other parameters.
v2:
- Describe -1 in the same area where 0 and 1 are described. (Luca)
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241108130218.24125-16-gustavo.sousa@intel.com
Instead of checking for HAS_DMC_WAKELOCK() multiple times, let's use it
to sanitize the enable_dmc_wl parameter and use that variable when
necessary.
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241108130218.24125-15-gustavo.sousa@intel.com
A HAS_DMC_WAKELOCK() macro gives more semantic than openly checking the
display version. Define it and use it where appropriate.
v2:
- Make this patch contain only the non-functional refactor. Functional
changes related to including HAS_DMC() in the macro are done in
upcoming changes. (Jani)
Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241108130218.24125-14-gustavo.sousa@intel.com
Enabling and disabling the DMC wakelock should be done as part of
enabling and disabling of dynamic DC states, respectively. We should not
enable or disable DMC wakelock independently of DC states, otherwise we
would risk ending up with an inconsistent state where dynamic DC states
are enabled and the DMC wakelock is disabled, going against current
recommendations and making MMIO transactions potentially slower. In
future display IPs that could have a worse outcome if DMC trap
implementation is completely removed.
So, let's make things safer by tying stuff together, removing the
independent calls, and also put warnings in place to detect inconsistent
calls.
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241108130218.24125-13-gustavo.sousa@intel.com
It is possible that there are active wakelock references at the time we
are disabling the DMC wakelock mechanism. We need to deal with that in
two ways:
(A) Implement the missing step from Bspec:
The Bspec instructs us to clear any existing wakelock request bit
after disabling the mechanism. That gives a clue that it is okay to
disable while there are locks held and we do not need to wait for
them. However, since the spec is not explicit about it, we need
still to get confirmation with the hardware team. Let's thus
implement the spec and add a TODO note.
(B) Ensure a consistent driver state:
The enable/disable logic would be problematic if the following
sequence of events would happen:
1. Function A calls intel_dmc_wl_get();
2. Some function calls intel_dmc_wl_disable();
3. Some function calls intel_dmc_wl_enable();
4. Function A is done and calls intel_dmc_wl_put().
At (2), the refcount becomes zero and then (4) causes an invalid
decrement to the refcount. That would cause some issues:
- At the time between (3) and (4), function A would think that
the hardware lock is held but it could not be really held
until intel_dmc_wl_get() is called by something else.
- The call made to (4) could cause the refcount to become zero
and consequently the hardware lock to be released while there
could be innocent paths trusting they still have the lock.
To fix that, we need to keep the refcount correctly in sync with
intel_dmc_wl_{get,put}() calls and retake the hardware lock when
enabling the DMC wakelock with a non-zero refcount.
One missing piece left to be handled here is the following scenario:
1. Function A calls intel_dmc_wl_get();
2. Some function calls intel_dmc_wl_disable();
3. Some function calls intel_dmc_wl_enable();
4. Concurrently with (3), function A performs the MMIO in between
setting DMC_WAKELOCK_CFG_ENABLE and asserting the lock with
__intel_dmc_wl_take().
I'm mostly sure this would cause issues future display IPs if DMC
trap implementation was completely removed. We need to check with
the hardware team whether it would be safe to assert the hardware
lock before setting DMC_WAKELOCK_CFG_ENABLE to avoid this scenario.
If not, then we would have to deal with that via software
synchronization.
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241108130218.24125-12-gustavo.sousa@intel.com
Allow simpler syntax for defining entries for single registers in range
tables. That makes them easier to type as well as to read, allowing one
to quickly tell whether a range actually refers to a single register or
a "true range".
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241108130218.24125-11-gustavo.sousa@intel.com
There are extra registers that require the DMC wakelock when specific
dynamic DC states are in place. Those are registers that are touched by
the DMC and require DC exit for proper access. Add the range tables for
them and use the correct one depending on the enabled DC state.
v2:
- Do not look into power domains guts (i.e.
display->power.domains.dc_state). (Jani)
- Come up with better names for variables containing register ranges.
(Luca)
- Keep a copy of dc_state in struct intel_dmc_wl.
- Update commit message for a clearer explanation for the need of
these new tables.
Bspec: 71583
Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241108130218.24125-10-gustavo.sousa@intel.com
In an upcoming change, we will add extra range tables for registers that
are touched by the DMC during DC states. The range table that we are
currently using is meant for registers that are powered off during DC
states. As such, let's rename the table to powered_off_ranges and also
add a comment regarding its purpose in the function that uses it.
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241108130218.24125-9-gustavo.sousa@intel.com
We will be using more than one range table in
intel_dmc_wl_check_range(). As such, move the logic to a new function
and name it intel_dmc_wl_reg_in_range().
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241108130218.24125-8-gustavo.sousa@intel.com
We are currently using ARRAY_SIZE() to iterate address ranges in
intel_dmc_wl_check_range(). In upcoming changes, we will be using more
than a single table and will extract the range checking logic into a
dedicated function that takes a range table as argument. As we will not
able to use ARRAY_SIZE() then, let's make range tables contain a
sentinel item at the end and use that instead of having to pass the size
as parameter in this future function.
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241108130218.24125-7-gustavo.sousa@intel.com
Bspec says that disabling dynamic DC states require taking the DMC
wakelock to cause an DC exit before writing to DC_STATE_EN. Implement
that.
In fact, testing on PTL revealed we end up failing to exit DC5/6 without
this step.
Bspec: 71583
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241108130218.24125-6-gustavo.sousa@intel.com
When the DMC wakelock refcount reaches zero, we know that there are no
users and that we can do the actual release operation on the hardware,
which is queued with a delayed work. The idea of the delayed work is to
avoid performing the release if a new lock user appears (i.e. refcount
gets incremented) in a very short period of time.
Based on the above, the release work should bail out if refcount is
non-zero (meaning new lock users appeared in the meantime), but our
current code actually does the opposite: it bails when refcount is zero.
That means that the wakelock is not released when it should be; and
that, when the work is not canceled in time, it ends up being releasing
when it should not.
Fix that by inverting the condition.
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241108130218.24125-5-gustavo.sousa@intel.com
Some display MMIO transactions for offsets in the range that requires
the DMC wakelock happen in atomic context (this has been confirmed
during tests on PTL). That means that we need to use a non-sleeping
variant of MMIO waiting function.
Implement __intel_de_wait_for_register_atomic_nowl() and use it when
waiting for acknowledgment of acquire/release.
v2:
- No __intel_de_wait_for_register_atomic_nowl() wrapper to convert
i915 to display. (Jani)
- Add a quick explanation why DMC_WAKELOCK_CTL_TIMEOUT_US is defined
in microseconds. (Luca)
Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241108130218.24125-4-gustavo.sousa@intel.com
The macro i915_mmio_reg_offset() is the proper interface to get a
register's offset. Use that instead of looking directly at reg.reg.
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241108130218.24125-2-gustavo.sousa@intel.com
This feature should be disabled by default until properly tested and
mature. Add a module parameter to enable the feature for testing,
while keeping it disabled by default for now.
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240412094148.808179-4-luciano.coelho@intel.com
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Only allow running DMC wakelock code if the display version is 20 or
greater. Also check if DMC is loaded before enabling.
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240412094148.808179-3-luciano.coelho@intel.com
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
In order to reduce the DC5->DC2 restore time, wakelocks have been
introduced in DMC so the driver can tell it when registers and other
memory areas are going to be accessed and keep their respective blocks
awake.
Implement this in the driver by adding the concept of DMC wakelocks.
When the driver needs to access memory which lies inside pre-defined
ranges, it will tell DMC to set the wakelock, access the memory, then
wait for a while and clear the wakelock.
The wakelock state is protected in the driver with spinlocks to
prevent concurrency issues.
BSpec: 71583
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240412094148.808179-2-luciano.coelho@intel.com
Signed-off-by: Jani Nikula <jani.nikula@intel.com>