Commit b2196401 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-misc-fixes-2022-10-27' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes

drm-misc-fixes for v6.1-rc3:
- Fix HPD on bridge/ps8640.
- Stop leaking fences when killing a sched entity.
- Avoid uninitialized read in aperture_remove_conflicting_pci_device()
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/ed24cbd2-2bcb-d2c2-46ed-9d8ea9615879@linux.intel.com
parents 9520b1d0 e0ba1a39
...@@ -105,6 +105,7 @@ struct ps8640 { ...@@ -105,6 +105,7 @@ struct ps8640 {
struct gpio_desc *gpio_powerdown; struct gpio_desc *gpio_powerdown;
struct device_link *link; struct device_link *link;
bool pre_enabled; bool pre_enabled;
bool need_post_hpd_delay;
}; };
static const struct regmap_config ps8640_regmap_config[] = { static const struct regmap_config ps8640_regmap_config[] = {
...@@ -173,14 +174,31 @@ static int _ps8640_wait_hpd_asserted(struct ps8640 *ps_bridge, unsigned long wai ...@@ -173,14 +174,31 @@ static int _ps8640_wait_hpd_asserted(struct ps8640 *ps_bridge, unsigned long wai
{ {
struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL]; struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL];
int status; int status;
int ret;
/* /*
* Apparently something about the firmware in the chip signals that * Apparently something about the firmware in the chip signals that
* HPD goes high by reporting GPIO9 as high (even though HPD isn't * HPD goes high by reporting GPIO9 as high (even though HPD isn't
* actually connected to GPIO9). * actually connected to GPIO9).
*/ */
return regmap_read_poll_timeout(map, PAGE2_GPIO_H, status, ret = regmap_read_poll_timeout(map, PAGE2_GPIO_H, status,
status & PS_GPIO9, wait_us / 10, wait_us); status & PS_GPIO9, wait_us / 10, wait_us);
/*
* The first time we see HPD go high after a reset we delay an extra
* 50 ms. The best guess is that the MCU is doing "stuff" during this
* time (maybe talking to the panel) and we don't want to interrupt it.
*
* No locking is done around "need_post_hpd_delay". If we're here we
* know we're holding a PM Runtime reference and the only other place
* that touches this is PM Runtime resume.
*/
if (!ret && ps_bridge->need_post_hpd_delay) {
ps_bridge->need_post_hpd_delay = false;
msleep(50);
}
return ret;
} }
static int ps8640_wait_hpd_asserted(struct drm_dp_aux *aux, unsigned long wait_us) static int ps8640_wait_hpd_asserted(struct drm_dp_aux *aux, unsigned long wait_us)
...@@ -381,6 +399,9 @@ static int __maybe_unused ps8640_resume(struct device *dev) ...@@ -381,6 +399,9 @@ static int __maybe_unused ps8640_resume(struct device *dev)
msleep(50); msleep(50);
gpiod_set_value(ps_bridge->gpio_reset, 0); gpiod_set_value(ps_bridge->gpio_reset, 0);
/* We just reset things, so we need a delay after the first HPD */
ps_bridge->need_post_hpd_delay = true;
/* /*
* Mystery 200 ms delay for the "MCU to be ready". It's unclear if * Mystery 200 ms delay for the "MCU to be ready". It's unclear if
* this is truly necessary since the MCU will already signal that * this is truly necessary since the MCU will already signal that
......
...@@ -207,6 +207,7 @@ static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f, ...@@ -207,6 +207,7 @@ static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f,
struct drm_sched_job *job = container_of(cb, struct drm_sched_job, struct drm_sched_job *job = container_of(cb, struct drm_sched_job,
finish_cb); finish_cb);
dma_fence_put(f);
INIT_WORK(&job->work, drm_sched_entity_kill_jobs_work); INIT_WORK(&job->work, drm_sched_entity_kill_jobs_work);
schedule_work(&job->work); schedule_work(&job->work);
} }
...@@ -234,8 +235,10 @@ static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity) ...@@ -234,8 +235,10 @@ static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity)
struct drm_sched_fence *s_fence = job->s_fence; struct drm_sched_fence *s_fence = job->s_fence;
/* Wait for all dependencies to avoid data corruptions */ /* Wait for all dependencies to avoid data corruptions */
while ((f = drm_sched_job_dependency(job, entity))) while ((f = drm_sched_job_dependency(job, entity))) {
dma_fence_wait(f, false); dma_fence_wait(f, false);
dma_fence_put(f);
}
drm_sched_fence_scheduled(s_fence); drm_sched_fence_scheduled(s_fence);
dma_fence_set_error(&s_fence->finished, -ESRCH); dma_fence_set_error(&s_fence->finished, -ESRCH);
...@@ -250,6 +253,7 @@ static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity) ...@@ -250,6 +253,7 @@ static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity)
continue; continue;
} }
dma_fence_get(entity->last_scheduled);
r = dma_fence_add_callback(entity->last_scheduled, r = dma_fence_add_callback(entity->last_scheduled,
&job->finish_cb, &job->finish_cb,
drm_sched_entity_kill_jobs_cb); drm_sched_entity_kill_jobs_cb);
......
...@@ -340,12 +340,9 @@ int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *na ...@@ -340,12 +340,9 @@ int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *na
size = pci_resource_len(pdev, bar); size = pci_resource_len(pdev, bar);
ret = aperture_remove_conflicting_devices(base, size, primary, name); ret = aperture_remove_conflicting_devices(base, size, primary, name);
if (ret) if (ret)
break; return ret;
} }
if (ret)
return ret;
/* /*
* WARNING: Apparently we must kick fbdev drivers before vgacon, * WARNING: Apparently we must kick fbdev drivers before vgacon,
* otherwise the vga fbdev driver falls over. * otherwise the vga fbdev driver falls over.
......
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