Commit 5016bd24 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-fixes-2019-02-13' of...

Merge tag 'drm-intel-fixes-2019-02-13' of git://anongit.freedesktop.org/drm/drm-intel into drm-fixes

drm/i915 fixes for v5.0-rc7:
- combo phy programming fix
- opregion version check fix for VBT RVDA lookup
- gem mmap ioctl race fix
- fbdev hpd during suspend fix
- array size bounds check fix in pmu
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/877ee3504b.fsf@intel.com
parents d586d571 16eb0f34
...@@ -1824,6 +1824,16 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, ...@@ -1824,6 +1824,16 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
return 0; return 0;
} }
static inline bool
__vma_matches(struct vm_area_struct *vma, struct file *filp,
unsigned long addr, unsigned long size)
{
if (vma->vm_file != filp)
return false;
return vma->vm_start == addr && (vma->vm_end - vma->vm_start) == size;
}
/** /**
* i915_gem_mmap_ioctl - Maps the contents of an object, returning the address * i915_gem_mmap_ioctl - Maps the contents of an object, returning the address
* it is mapped to. * it is mapped to.
...@@ -1882,7 +1892,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, ...@@ -1882,7 +1892,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
return -EINTR; return -EINTR;
} }
vma = find_vma(mm, addr); vma = find_vma(mm, addr);
if (vma) if (vma && __vma_matches(vma, obj->base.filp, addr, args->size))
vma->vm_page_prot = vma->vm_page_prot =
pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
else else
......
...@@ -594,7 +594,8 @@ static void i915_pmu_enable(struct perf_event *event) ...@@ -594,7 +594,8 @@ static void i915_pmu_enable(struct perf_event *event)
* Update the bitmask of enabled events and increment * Update the bitmask of enabled events and increment
* the event reference counter. * the event reference counter.
*/ */
GEM_BUG_ON(bit >= I915_PMU_MASK_BITS); BUILD_BUG_ON(ARRAY_SIZE(i915->pmu.enable_count) != I915_PMU_MASK_BITS);
GEM_BUG_ON(bit >= ARRAY_SIZE(i915->pmu.enable_count));
GEM_BUG_ON(i915->pmu.enable_count[bit] == ~0); GEM_BUG_ON(i915->pmu.enable_count[bit] == ~0);
i915->pmu.enable |= BIT_ULL(bit); i915->pmu.enable |= BIT_ULL(bit);
i915->pmu.enable_count[bit]++; i915->pmu.enable_count[bit]++;
...@@ -615,11 +616,16 @@ static void i915_pmu_enable(struct perf_event *event) ...@@ -615,11 +616,16 @@ static void i915_pmu_enable(struct perf_event *event)
engine = intel_engine_lookup_user(i915, engine = intel_engine_lookup_user(i915,
engine_event_class(event), engine_event_class(event),
engine_event_instance(event)); engine_event_instance(event));
GEM_BUG_ON(!engine);
engine->pmu.enable |= BIT(sample);
GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS); BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.enable_count) !=
I915_ENGINE_SAMPLE_COUNT);
BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.sample) !=
I915_ENGINE_SAMPLE_COUNT);
GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count));
GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample));
GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0); GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0);
engine->pmu.enable |= BIT(sample);
engine->pmu.enable_count[sample]++; engine->pmu.enable_count[sample]++;
} }
...@@ -649,9 +655,11 @@ static void i915_pmu_disable(struct perf_event *event) ...@@ -649,9 +655,11 @@ static void i915_pmu_disable(struct perf_event *event)
engine = intel_engine_lookup_user(i915, engine = intel_engine_lookup_user(i915,
engine_event_class(event), engine_event_class(event),
engine_event_instance(event)); engine_event_instance(event));
GEM_BUG_ON(!engine);
GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS); GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count));
GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample));
GEM_BUG_ON(engine->pmu.enable_count[sample] == 0); GEM_BUG_ON(engine->pmu.enable_count[sample] == 0);
/* /*
* Decrement the reference count and clear the enabled * Decrement the reference count and clear the enabled
* bitmask when the last listener on an event goes away. * bitmask when the last listener on an event goes away.
...@@ -660,7 +668,7 @@ static void i915_pmu_disable(struct perf_event *event) ...@@ -660,7 +668,7 @@ static void i915_pmu_disable(struct perf_event *event)
engine->pmu.enable &= ~BIT(sample); engine->pmu.enable &= ~BIT(sample);
} }
GEM_BUG_ON(bit >= I915_PMU_MASK_BITS); GEM_BUG_ON(bit >= ARRAY_SIZE(i915->pmu.enable_count));
GEM_BUG_ON(i915->pmu.enable_count[bit] == 0); GEM_BUG_ON(i915->pmu.enable_count[bit] == 0);
/* /*
* Decrement the reference count and clear the enabled * Decrement the reference count and clear the enabled
......
...@@ -31,6 +31,8 @@ enum { ...@@ -31,6 +31,8 @@ enum {
((1 << I915_PMU_SAMPLE_BITS) + \ ((1 << I915_PMU_SAMPLE_BITS) + \
(I915_PMU_LAST + 1 - __I915_PMU_OTHER(0))) (I915_PMU_LAST + 1 - __I915_PMU_OTHER(0)))
#define I915_ENGINE_SAMPLE_COUNT (I915_SAMPLE_SEMA + 1)
struct i915_pmu_sample { struct i915_pmu_sample {
u64 cur; u64 cur;
}; };
......
...@@ -1790,7 +1790,7 @@ enum i915_power_well_id { ...@@ -1790,7 +1790,7 @@ enum i915_power_well_id {
#define _CNL_PORT_TX_C_LN0_OFFSET 0x162C40 #define _CNL_PORT_TX_C_LN0_OFFSET 0x162C40
#define _CNL_PORT_TX_D_LN0_OFFSET 0x162E40 #define _CNL_PORT_TX_D_LN0_OFFSET 0x162E40
#define _CNL_PORT_TX_F_LN0_OFFSET 0x162840 #define _CNL_PORT_TX_F_LN0_OFFSET 0x162840
#define _CNL_PORT_TX_DW_GRP(port, dw) (_PICK((port), \ #define _CNL_PORT_TX_DW_GRP(dw, port) (_PICK((port), \
_CNL_PORT_TX_AE_GRP_OFFSET, \ _CNL_PORT_TX_AE_GRP_OFFSET, \
_CNL_PORT_TX_B_GRP_OFFSET, \ _CNL_PORT_TX_B_GRP_OFFSET, \
_CNL_PORT_TX_B_GRP_OFFSET, \ _CNL_PORT_TX_B_GRP_OFFSET, \
...@@ -1798,7 +1798,7 @@ enum i915_power_well_id { ...@@ -1798,7 +1798,7 @@ enum i915_power_well_id {
_CNL_PORT_TX_AE_GRP_OFFSET, \ _CNL_PORT_TX_AE_GRP_OFFSET, \
_CNL_PORT_TX_F_GRP_OFFSET) + \ _CNL_PORT_TX_F_GRP_OFFSET) + \
4 * (dw)) 4 * (dw))
#define _CNL_PORT_TX_DW_LN0(port, dw) (_PICK((port), \ #define _CNL_PORT_TX_DW_LN0(dw, port) (_PICK((port), \
_CNL_PORT_TX_AE_LN0_OFFSET, \ _CNL_PORT_TX_AE_LN0_OFFSET, \
_CNL_PORT_TX_B_LN0_OFFSET, \ _CNL_PORT_TX_B_LN0_OFFSET, \
_CNL_PORT_TX_B_LN0_OFFSET, \ _CNL_PORT_TX_B_LN0_OFFSET, \
...@@ -1834,9 +1834,9 @@ enum i915_power_well_id { ...@@ -1834,9 +1834,9 @@ enum i915_power_well_id {
#define _CNL_PORT_TX_DW4_LN0_AE 0x162450 #define _CNL_PORT_TX_DW4_LN0_AE 0x162450
#define _CNL_PORT_TX_DW4_LN1_AE 0x1624D0 #define _CNL_PORT_TX_DW4_LN1_AE 0x1624D0
#define CNL_PORT_TX_DW4_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP((port), 4)) #define CNL_PORT_TX_DW4_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP(4, (port)))
#define CNL_PORT_TX_DW4_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0((port), 4)) #define CNL_PORT_TX_DW4_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0(4, (port)))
#define CNL_PORT_TX_DW4_LN(port, ln) _MMIO(_CNL_PORT_TX_DW_LN0((port), 4) + \ #define CNL_PORT_TX_DW4_LN(port, ln) _MMIO(_CNL_PORT_TX_DW_LN0(4, (port)) + \
((ln) * (_CNL_PORT_TX_DW4_LN1_AE - \ ((ln) * (_CNL_PORT_TX_DW4_LN1_AE - \
_CNL_PORT_TX_DW4_LN0_AE))) _CNL_PORT_TX_DW4_LN0_AE)))
#define ICL_PORT_TX_DW4_AUX(port) _MMIO(_ICL_PORT_TX_DW_AUX(4, port)) #define ICL_PORT_TX_DW4_AUX(port) _MMIO(_ICL_PORT_TX_DW_AUX(4, port))
...@@ -1864,8 +1864,12 @@ enum i915_power_well_id { ...@@ -1864,8 +1864,12 @@ enum i915_power_well_id {
#define RTERM_SELECT(x) ((x) << 3) #define RTERM_SELECT(x) ((x) << 3)
#define RTERM_SELECT_MASK (0x7 << 3) #define RTERM_SELECT_MASK (0x7 << 3)
#define CNL_PORT_TX_DW7_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP((port), 7)) #define CNL_PORT_TX_DW7_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP(7, (port)))
#define CNL_PORT_TX_DW7_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0((port), 7)) #define CNL_PORT_TX_DW7_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0(7, (port)))
#define ICL_PORT_TX_DW7_AUX(port) _MMIO(_ICL_PORT_TX_DW_AUX(7, port))
#define ICL_PORT_TX_DW7_GRP(port) _MMIO(_ICL_PORT_TX_DW_GRP(7, port))
#define ICL_PORT_TX_DW7_LN0(port) _MMIO(_ICL_PORT_TX_DW_LN(7, 0, port))
#define ICL_PORT_TX_DW7_LN(port, ln) _MMIO(_ICL_PORT_TX_DW_LN(7, ln, port))
#define N_SCALAR(x) ((x) << 24) #define N_SCALAR(x) ((x) << 24)
#define N_SCALAR_MASK (0x7F << 24) #define N_SCALAR_MASK (0x7F << 24)
......
This diff is collapsed.
...@@ -304,9 +304,11 @@ static int cnl_max_source_rate(struct intel_dp *intel_dp) ...@@ -304,9 +304,11 @@ static int cnl_max_source_rate(struct intel_dp *intel_dp)
static int icl_max_source_rate(struct intel_dp *intel_dp) static int icl_max_source_rate(struct intel_dp *intel_dp)
{ {
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
enum port port = dig_port->base.port; enum port port = dig_port->base.port;
if (port == PORT_B) if (intel_port_is_combophy(dev_priv, port) &&
!intel_dp_is_edp(intel_dp))
return 540000; return 540000;
return 810000; return 810000;
......
...@@ -209,6 +209,16 @@ struct intel_fbdev { ...@@ -209,6 +209,16 @@ struct intel_fbdev {
unsigned long vma_flags; unsigned long vma_flags;
async_cookie_t cookie; async_cookie_t cookie;
int preferred_bpp; int preferred_bpp;
/* Whether or not fbdev hpd processing is temporarily suspended */
bool hpd_suspended : 1;
/* Set when a hotplug was received while HPD processing was
* suspended
*/
bool hpd_waiting : 1;
/* Protects hpd_suspended */
struct mutex hpd_lock;
}; };
struct intel_encoder { struct intel_encoder {
......
...@@ -679,6 +679,7 @@ int intel_fbdev_init(struct drm_device *dev) ...@@ -679,6 +679,7 @@ int intel_fbdev_init(struct drm_device *dev)
if (ifbdev == NULL) if (ifbdev == NULL)
return -ENOMEM; return -ENOMEM;
mutex_init(&ifbdev->hpd_lock);
drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs); drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);
if (!intel_fbdev_init_bios(dev, ifbdev)) if (!intel_fbdev_init_bios(dev, ifbdev))
...@@ -752,6 +753,26 @@ void intel_fbdev_fini(struct drm_i915_private *dev_priv) ...@@ -752,6 +753,26 @@ void intel_fbdev_fini(struct drm_i915_private *dev_priv)
intel_fbdev_destroy(ifbdev); intel_fbdev_destroy(ifbdev);
} }
/* Suspends/resumes fbdev processing of incoming HPD events. When resuming HPD
* processing, fbdev will perform a full connector reprobe if a hotplug event
* was received while HPD was suspended.
*/
static void intel_fbdev_hpd_set_suspend(struct intel_fbdev *ifbdev, int state)
{
bool send_hpd = false;
mutex_lock(&ifbdev->hpd_lock);
ifbdev->hpd_suspended = state == FBINFO_STATE_SUSPENDED;
send_hpd = !ifbdev->hpd_suspended && ifbdev->hpd_waiting;
ifbdev->hpd_waiting = false;
mutex_unlock(&ifbdev->hpd_lock);
if (send_hpd) {
DRM_DEBUG_KMS("Handling delayed fbcon HPD event\n");
drm_fb_helper_hotplug_event(&ifbdev->helper);
}
}
void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous) void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous)
{ {
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
...@@ -773,6 +794,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous ...@@ -773,6 +794,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
*/ */
if (state != FBINFO_STATE_RUNNING) if (state != FBINFO_STATE_RUNNING)
flush_work(&dev_priv->fbdev_suspend_work); flush_work(&dev_priv->fbdev_suspend_work);
console_lock(); console_lock();
} else { } else {
/* /*
...@@ -800,17 +822,26 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous ...@@ -800,17 +822,26 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
drm_fb_helper_set_suspend(&ifbdev->helper, state); drm_fb_helper_set_suspend(&ifbdev->helper, state);
console_unlock(); console_unlock();
intel_fbdev_hpd_set_suspend(ifbdev, state);
} }
void intel_fbdev_output_poll_changed(struct drm_device *dev) void intel_fbdev_output_poll_changed(struct drm_device *dev)
{ {
struct intel_fbdev *ifbdev = to_i915(dev)->fbdev; struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
bool send_hpd;
if (!ifbdev) if (!ifbdev)
return; return;
intel_fbdev_sync(ifbdev); intel_fbdev_sync(ifbdev);
if (ifbdev->vma || ifbdev->helper.deferred_setup)
mutex_lock(&ifbdev->hpd_lock);
send_hpd = !ifbdev->hpd_suspended;
ifbdev->hpd_waiting = true;
mutex_unlock(&ifbdev->hpd_lock);
if (send_hpd && (ifbdev->vma || ifbdev->helper.deferred_setup))
drm_fb_helper_hotplug_event(&ifbdev->helper); drm_fb_helper_hotplug_event(&ifbdev->helper);
} }
......
...@@ -55,7 +55,12 @@ ...@@ -55,7 +55,12 @@
struct opregion_header { struct opregion_header {
u8 signature[16]; u8 signature[16];
u32 size; u32 size;
u32 opregion_ver; struct {
u8 rsvd;
u8 revision;
u8 minor;
u8 major;
} __packed over;
u8 bios_ver[32]; u8 bios_ver[32];
u8 vbios_ver[16]; u8 vbios_ver[16];
u8 driver_ver[16]; u8 driver_ver[16];
...@@ -119,7 +124,8 @@ struct opregion_asle { ...@@ -119,7 +124,8 @@ struct opregion_asle {
u64 fdss; u64 fdss;
u32 fdsp; u32 fdsp;
u32 stat; 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 */ u32 rvds; /* Size of raw vbt data */
u8 rsvd[58]; u8 rsvd[58];
} __packed; } __packed;
...@@ -925,6 +931,11 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv) ...@@ -925,6 +931,11 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
opregion->header = base; opregion->header = base;
opregion->lid_state = base + ACPI_CLID; opregion->lid_state = base + ACPI_CLID;
DRM_DEBUG_DRIVER("ACPI OpRegion version %u.%u.%u\n",
opregion->header->over.major,
opregion->header->over.minor,
opregion->header->over.revision);
mboxes = opregion->header->mboxes; mboxes = opregion->header->mboxes;
if (mboxes & MBOX_ACPI) { if (mboxes & MBOX_ACPI) {
DRM_DEBUG_DRIVER("Public ACPI methods supported\n"); DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
...@@ -953,11 +964,26 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv) ...@@ -953,11 +964,26 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
if (dmi_check_system(intel_no_opregion_vbt)) if (dmi_check_system(intel_no_opregion_vbt))
goto out; goto out;
if (opregion->header->opregion_ver >= 2 && opregion->asle && if (opregion->header->over.major >= 2 && opregion->asle &&
opregion->asle->rvda && opregion->asle->rvds) { opregion->asle->rvda && opregion->asle->rvds) {
opregion->rvda = memremap(opregion->asle->rvda, resource_size_t rvda = opregion->asle->rvda;
opregion->asle->rvds,
/*
* 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); MEMREMAP_WB);
vbt = opregion->rvda; vbt = opregion->rvda;
vbt_size = opregion->asle->rvds; vbt_size = opregion->asle->rvds;
if (intel_bios_is_valid_vbt(vbt, vbt_size)) { if (intel_bios_is_valid_vbt(vbt, vbt_size)) {
...@@ -967,6 +993,8 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv) ...@@ -967,6 +993,8 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
goto out; goto out;
} else { } else {
DRM_DEBUG_KMS("Invalid VBT in ACPI OpRegion (RVDA)\n"); DRM_DEBUG_KMS("Invalid VBT in ACPI OpRegion (RVDA)\n");
memunmap(opregion->rvda);
opregion->rvda = NULL;
} }
} }
......
...@@ -415,16 +415,17 @@ struct intel_engine_cs { ...@@ -415,16 +415,17 @@ struct intel_engine_cs {
/** /**
* @enable_count: Reference count for the enabled samplers. * @enable_count: Reference count for the enabled samplers.
* *
* Index number corresponds to the bit number from @enable. * Index number corresponds to @enum drm_i915_pmu_engine_sample.
*/ */
unsigned int enable_count[I915_PMU_SAMPLE_BITS]; unsigned int enable_count[I915_ENGINE_SAMPLE_COUNT];
/** /**
* @sample: Counter values for sampling events. * @sample: Counter values for sampling events.
* *
* Our internal timer stores the current counters in this field. * Our internal timer stores the current counters in this field.
*
* Index number corresponds to @enum drm_i915_pmu_engine_sample.
*/ */
#define I915_ENGINE_SAMPLE_MAX (I915_SAMPLE_SEMA + 1) struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_COUNT];
struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX];
} pmu; } pmu;
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment