mirror of https://gitee.com/openkylin/linux.git
drm/i915/opregion: rvda is relative from opregion base in opregion 2.1+
Starting from opregion version 2.1 (roughly corresponding to ICL+) the
RVDA field is relative from the beginning of opregion, not absolute
address.
Fix the error path while at it.
v2: Make relative vs. absolute conditional on the opregion version,
bumped for the purpose. Turned out there are machines relying on
absolute RVDA in the wild.
v3: Fix the version checks
Fixes: 04ebaadb9f
("drm/i915/opregion: handle VBT sizes bigger than 6 KB")
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Imre Deak <imre.deak@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190208184254.24123-2-jani.nikula@intel.com
This commit is contained in:
parent
98fdaaca95
commit
a0f52c3d35
|
@ -123,7 +123,8 @@ struct opregion_asle {
|
|||
u64 fdss;
|
||||
u32 fdsp;
|
||||
u32 stat;
|
||||
u64 rvda; /* Physical address of raw vbt data */
|
||||
u64 rvda; /* Physical (2.0) or relative from opregion (2.1+)
|
||||
* address of raw VBT data. */
|
||||
u32 rvds; /* Size of raw vbt data */
|
||||
u8 rsvd[58];
|
||||
} __packed;
|
||||
|
@ -964,9 +965,24 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
|
|||
|
||||
if (opregion->header->over.major >= 2 && opregion->asle &&
|
||||
opregion->asle->rvda && opregion->asle->rvds) {
|
||||
opregion->rvda = memremap(opregion->asle->rvda,
|
||||
opregion->asle->rvds,
|
||||
resource_size_t rvda = opregion->asle->rvda;
|
||||
|
||||
/*
|
||||
* opregion 2.0: rvda is the physical VBT address.
|
||||
*
|
||||
* opregion 2.1+: rvda is unsigned, relative offset from
|
||||
* opregion base, and should never point within opregion.
|
||||
*/
|
||||
if (opregion->header->over.major > 2 ||
|
||||
opregion->header->over.minor >= 1) {
|
||||
WARN_ON(rvda < OPREGION_SIZE);
|
||||
|
||||
rvda += asls;
|
||||
}
|
||||
|
||||
opregion->rvda = memremap(rvda, opregion->asle->rvds,
|
||||
MEMREMAP_WB);
|
||||
|
||||
vbt = opregion->rvda;
|
||||
vbt_size = opregion->asle->rvds;
|
||||
if (intel_bios_is_valid_vbt(vbt, vbt_size)) {
|
||||
|
@ -976,6 +992,8 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
|
|||
goto out;
|
||||
} else {
|
||||
DRM_DEBUG_KMS("Invalid VBT in ACPI OpRegion (RVDA)\n");
|
||||
memunmap(opregion->rvda);
|
||||
opregion->rvda = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue