Fixes for 4.16. I contains fixes for deadlock on runtime suspend on few
drivers, a memory leak on non-blocking commits, a crash on color-eviction. The is also meson and edid fixes, plus a fix for a doc warning. -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJajY3SAAoJEEN0HIUfOBk0/5IP/jTa0VKe7UurEzj9Vzgt4USu tVre4MGN42peY2PbVSsBmvHAOeyII7la1/NkiFi8wZKQ2MXw43NenKOcRLDW0r9b 6U8Tlq3sU//NdUDAiLLx9hKb+i31ag+wodvULt0PKtEWDsxWDSRZUo792as2YUkC VxHuIQywNABohn2Ya8Og1dON25GD7zRzNzH7O+g+fds/Qvav0504u2v10jBKJC0D IB2oc3ZtJR8n0dFpzhnEB7YkxyvkrsWZQ1LtutGFgrr54F0KVHvAm/VMZ5qzyCRi kvJN81OFo0xpdE7ZMSQ5YAvcPsEC5ifSNaaxpawsM904H7fS6FNhHMg7cGGi1f7R B8YbLrdy+mBnQPNNbPcDPQA+YN/tRv4rRmmdLdkDbdY1GM/JJ4C7PTuLL6mX1iWU DuHiaFS0KZGoS0XCVbvhLkPt5fsmvp+QxBpeNAtxgOdn2pRquDmGZ1jTVEG2mw5U rqoPURa3urqdSwj8ba0jbJo6WBAmb1uWeyJ7xpyUVhR9SR30+URYVWwJEPDOgTnQ PaEzjobntgDLaq5NbhpEvmYmylv1SPkucGtkCtwPxIrrh5Z84pZTJ1th2ogfn3Ti VL25dTlzFpsjEMgC72wCi0eiP7qLVTX9vHYZBzkeIjIWDH0rCnCFxvjwmD/aVUbz Ex1/fGNEVkFupcYLu7m4 =555h -----END PGP SIGNATURE----- Merge tag 'drm-misc-fixes-2018-02-21' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes Fixes for 4.16. I contains fixes for deadlock on runtime suspend on few drivers, a memory leak on non-blocking commits, a crash on color-eviction. The is also meson and edid fixes, plus a fix for a doc warning. * tag 'drm-misc-fixes-2018-02-21' of git://anongit.freedesktop.org/drm/drm-misc: drm/tve200: fix kernel-doc documentation comment include drm/meson: fix vsync buffer update drm: Handle unexpected holes in color-eviction drm/edid: Add 6 bpc quirk for CPT panel in Asus UX303LA drm/amdgpu: Fix deadlock on runtime suspend drm/radeon: Fix deadlock on runtime suspend drm/nouveau: Fix deadlock on runtime suspend drm: Allow determining if current task is output poll worker workqueue: Allow retrieval of current task's work struct drm/atomic: Fix memleak on ERESTARTSYS during non-blocking commits
This commit is contained in:
commit
dfe8db2237
|
@ -3,4 +3,4 @@
|
|||
==================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/tve200/tve200_drv.c
|
||||
:doc: Faraday TV Encoder 200
|
||||
:doc: Faraday TV Encoder TVE200 DRM Driver
|
||||
|
|
|
@ -736,9 +736,11 @@ amdgpu_connector_lvds_detect(struct drm_connector *connector, bool force)
|
|||
enum drm_connector_status ret = connector_status_disconnected;
|
||||
int r;
|
||||
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
return connector_status_disconnected;
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
if (encoder) {
|
||||
struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
|
||||
|
@ -757,8 +759,12 @@ amdgpu_connector_lvds_detect(struct drm_connector *connector, bool force)
|
|||
/* check acpi lid status ??? */
|
||||
|
||||
amdgpu_connector_update_scratch_regs(connector, ret);
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -868,9 +874,11 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)
|
|||
enum drm_connector_status ret = connector_status_disconnected;
|
||||
int r;
|
||||
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
return connector_status_disconnected;
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
encoder = amdgpu_connector_best_single_encoder(connector);
|
||||
if (!encoder)
|
||||
|
@ -924,8 +932,10 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)
|
|||
amdgpu_connector_update_scratch_regs(connector, ret);
|
||||
|
||||
out:
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -988,9 +998,11 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
|
|||
enum drm_connector_status ret = connector_status_disconnected;
|
||||
bool dret = false, broken_edid = false;
|
||||
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
return connector_status_disconnected;
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) {
|
||||
ret = connector->status;
|
||||
|
@ -1115,8 +1127,10 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
|
|||
amdgpu_connector_update_scratch_regs(connector, ret);
|
||||
|
||||
exit:
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1359,9 +1373,11 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force)
|
|||
struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
|
||||
int r;
|
||||
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
return connector_status_disconnected;
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) {
|
||||
ret = connector->status;
|
||||
|
@ -1429,8 +1445,10 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force)
|
|||
|
||||
amdgpu_connector_update_scratch_regs(connector, ret);
|
||||
out:
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1878,6 +1878,8 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
|
|||
new_crtc_state->event->base.completion = &commit->flip_done;
|
||||
new_crtc_state->event->base.completion_release = release_crtc_commit;
|
||||
drm_crtc_commit_get(commit);
|
||||
|
||||
commit->abort_completion = true;
|
||||
}
|
||||
|
||||
for_each_oldnew_connector_in_state(state, conn, old_conn_state, new_conn_state, i) {
|
||||
|
@ -3421,8 +3423,21 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
|
|||
void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state)
|
||||
{
|
||||
if (state->commit) {
|
||||
/*
|
||||
* In the event that a non-blocking commit returns
|
||||
* -ERESTARTSYS before the commit_tail work is queued, we will
|
||||
* have an extra reference to the commit object. Release it, if
|
||||
* the event has not been consumed by the worker.
|
||||
*
|
||||
* state->event may be freed, so we can't directly look at
|
||||
* state->event->base.completion.
|
||||
*/
|
||||
if (state->event && state->commit->abort_completion)
|
||||
drm_crtc_commit_put(state->commit);
|
||||
|
||||
kfree(state->commit->event);
|
||||
state->commit->event = NULL;
|
||||
|
||||
drm_crtc_commit_put(state->commit);
|
||||
}
|
||||
|
||||
|
|
|
@ -113,6 +113,9 @@ static const struct edid_quirk {
|
|||
/* AEO model 0 reports 8 bpc, but is a 6 bpc panel */
|
||||
{ "AEO", 0, EDID_QUIRK_FORCE_6BPC },
|
||||
|
||||
/* CPT panel of Asus UX303LA reports 8 bpc, but is a 6 bpc panel */
|
||||
{ "CPT", 0x17df, EDID_QUIRK_FORCE_6BPC },
|
||||
|
||||
/* Belinea 10 15 55 */
|
||||
{ "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 },
|
||||
{ "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 },
|
||||
|
|
|
@ -836,9 +836,24 @@ struct drm_mm_node *drm_mm_scan_color_evict(struct drm_mm_scan *scan)
|
|||
if (!mm->color_adjust)
|
||||
return NULL;
|
||||
|
||||
hole = list_first_entry(&mm->hole_stack, typeof(*hole), hole_stack);
|
||||
hole_start = __drm_mm_hole_node_start(hole);
|
||||
hole_end = hole_start + hole->hole_size;
|
||||
/*
|
||||
* The hole found during scanning should ideally be the first element
|
||||
* in the hole_stack list, but due to side-effects in the driver it
|
||||
* may not be.
|
||||
*/
|
||||
list_for_each_entry(hole, &mm->hole_stack, hole_stack) {
|
||||
hole_start = __drm_mm_hole_node_start(hole);
|
||||
hole_end = hole_start + hole->hole_size;
|
||||
|
||||
if (hole_start <= scan->hit_start &&
|
||||
hole_end >= scan->hit_end)
|
||||
break;
|
||||
}
|
||||
|
||||
/* We should only be called after we found the hole previously */
|
||||
DRM_MM_BUG_ON(&hole->hole_stack == &mm->hole_stack);
|
||||
if (unlikely(&hole->hole_stack == &mm->hole_stack))
|
||||
return NULL;
|
||||
|
||||
DRM_MM_BUG_ON(hole_start > scan->hit_start);
|
||||
DRM_MM_BUG_ON(hole_end < scan->hit_end);
|
||||
|
|
|
@ -653,6 +653,26 @@ static void output_poll_execute(struct work_struct *work)
|
|||
schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_kms_helper_is_poll_worker - is %current task an output poll worker?
|
||||
*
|
||||
* Determine if %current task is an output poll worker. This can be used
|
||||
* to select distinct code paths for output polling versus other contexts.
|
||||
*
|
||||
* One use case is to avoid a deadlock between the output poll worker and
|
||||
* the autosuspend worker wherein the latter waits for polling to finish
|
||||
* upon calling drm_kms_helper_poll_disable(), while the former waits for
|
||||
* runtime suspend to finish upon calling pm_runtime_get_sync() in a
|
||||
* connector ->detect hook.
|
||||
*/
|
||||
bool drm_kms_helper_is_poll_worker(void)
|
||||
{
|
||||
struct work_struct *work = current_work();
|
||||
|
||||
return work && work->func == output_poll_execute;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_kms_helper_is_poll_worker);
|
||||
|
||||
/**
|
||||
* drm_kms_helper_poll_disable - disable output polling
|
||||
* @dev: drm_device
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "meson_venc.h"
|
||||
#include "meson_vpp.h"
|
||||
#include "meson_viu.h"
|
||||
#include "meson_canvas.h"
|
||||
#include "meson_registers.h"
|
||||
|
||||
/* CRTC definition */
|
||||
|
@ -192,6 +193,11 @@ void meson_crtc_irq(struct meson_drm *priv)
|
|||
} else
|
||||
meson_vpp_disable_interlace_vscaler_osd1(priv);
|
||||
|
||||
meson_canvas_setup(priv, MESON_CANVAS_ID_OSD1,
|
||||
priv->viu.osd1_addr, priv->viu.osd1_stride,
|
||||
priv->viu.osd1_height, MESON_CANVAS_WRAP_NONE,
|
||||
MESON_CANVAS_BLKMODE_LINEAR);
|
||||
|
||||
/* Enable OSD1 */
|
||||
writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
|
||||
priv->io_base + _REG(VPP_MISC));
|
||||
|
|
|
@ -43,6 +43,9 @@ struct meson_drm {
|
|||
bool osd1_commit;
|
||||
uint32_t osd1_ctrl_stat;
|
||||
uint32_t osd1_blk0_cfg[5];
|
||||
uint32_t osd1_addr;
|
||||
uint32_t osd1_stride;
|
||||
uint32_t osd1_height;
|
||||
} viu;
|
||||
|
||||
struct {
|
||||
|
|
|
@ -164,10 +164,9 @@ static void meson_plane_atomic_update(struct drm_plane *plane,
|
|||
/* Update Canvas with buffer address */
|
||||
gem = drm_fb_cma_get_gem_obj(fb, 0);
|
||||
|
||||
meson_canvas_setup(priv, MESON_CANVAS_ID_OSD1,
|
||||
gem->paddr, fb->pitches[0],
|
||||
fb->height, MESON_CANVAS_WRAP_NONE,
|
||||
MESON_CANVAS_BLKMODE_LINEAR);
|
||||
priv->viu.osd1_addr = gem->paddr;
|
||||
priv->viu.osd1_stride = fb->pitches[0];
|
||||
priv->viu.osd1_height = fb->height;
|
||||
|
||||
spin_unlock_irqrestore(&priv->drm->event_lock, flags);
|
||||
}
|
||||
|
|
|
@ -570,9 +570,15 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
|
|||
nv_connector->edid = NULL;
|
||||
}
|
||||
|
||||
ret = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (ret < 0 && ret != -EACCES)
|
||||
return conn_status;
|
||||
/* Outputs are only polled while runtime active, so acquiring a
|
||||
* runtime PM ref here is unnecessary (and would deadlock upon
|
||||
* runtime suspend because it waits for polling to finish).
|
||||
*/
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
ret = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (ret < 0 && ret != -EACCES)
|
||||
return conn_status;
|
||||
}
|
||||
|
||||
nv_encoder = nouveau_connector_ddc_detect(connector);
|
||||
if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) {
|
||||
|
@ -647,8 +653,10 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
|
|||
|
||||
out:
|
||||
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
}
|
||||
|
||||
return conn_status;
|
||||
}
|
||||
|
|
|
@ -899,9 +899,11 @@ radeon_lvds_detect(struct drm_connector *connector, bool force)
|
|||
enum drm_connector_status ret = connector_status_disconnected;
|
||||
int r;
|
||||
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
return connector_status_disconnected;
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
if (encoder) {
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
|
@ -924,8 +926,12 @@ radeon_lvds_detect(struct drm_connector *connector, bool force)
|
|||
/* check acpi lid status ??? */
|
||||
|
||||
radeon_connector_update_scratch_regs(connector, ret);
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1039,9 +1045,11 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
|
|||
enum drm_connector_status ret = connector_status_disconnected;
|
||||
int r;
|
||||
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
return connector_status_disconnected;
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
encoder = radeon_best_single_encoder(connector);
|
||||
if (!encoder)
|
||||
|
@ -1108,8 +1116,10 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
|
|||
radeon_connector_update_scratch_regs(connector, ret);
|
||||
|
||||
out:
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1173,9 +1183,11 @@ radeon_tv_detect(struct drm_connector *connector, bool force)
|
|||
if (!radeon_connector->dac_load_detect)
|
||||
return ret;
|
||||
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
return connector_status_disconnected;
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
encoder = radeon_best_single_encoder(connector);
|
||||
if (!encoder)
|
||||
|
@ -1187,8 +1199,12 @@ radeon_tv_detect(struct drm_connector *connector, bool force)
|
|||
if (ret == connector_status_connected)
|
||||
ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, false);
|
||||
radeon_connector_update_scratch_regs(connector, ret);
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1251,9 +1267,11 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
|
|||
enum drm_connector_status ret = connector_status_disconnected;
|
||||
bool dret = false, broken_edid = false;
|
||||
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
return connector_status_disconnected;
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
if (radeon_connector->detected_hpd_without_ddc) {
|
||||
force = true;
|
||||
|
@ -1436,8 +1454,10 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
|
|||
}
|
||||
|
||||
exit:
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1688,9 +1708,11 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
|
|||
if (radeon_dig_connector->is_mst)
|
||||
return connector_status_disconnected;
|
||||
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
return connector_status_disconnected;
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
if (!force && radeon_check_hpd_status_unchanged(connector)) {
|
||||
ret = connector->status;
|
||||
|
@ -1777,8 +1799,10 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
|
|||
}
|
||||
|
||||
out:
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
pm_runtime_mark_last_busy(connector->dev->dev);
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -134,6 +134,15 @@ struct drm_crtc_commit {
|
|||
* &drm_pending_vblank_event pointer to clean up private events.
|
||||
*/
|
||||
struct drm_pending_vblank_event *event;
|
||||
|
||||
/**
|
||||
* @abort_completion:
|
||||
*
|
||||
* A flag that's set after drm_atomic_helper_setup_commit takes a second
|
||||
* reference for the completion of $drm_crtc_state.event. It's used by
|
||||
* the free code to remove the second reference if commit fails.
|
||||
*/
|
||||
bool abort_completion;
|
||||
};
|
||||
|
||||
struct __drm_planes_state {
|
||||
|
|
|
@ -77,5 +77,6 @@ void drm_kms_helper_hotplug_event(struct drm_device *dev);
|
|||
|
||||
void drm_kms_helper_poll_disable(struct drm_device *dev);
|
||||
void drm_kms_helper_poll_enable(struct drm_device *dev);
|
||||
bool drm_kms_helper_is_poll_worker(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -465,6 +465,7 @@ extern bool cancel_delayed_work_sync(struct delayed_work *dwork);
|
|||
|
||||
extern void workqueue_set_max_active(struct workqueue_struct *wq,
|
||||
int max_active);
|
||||
extern struct work_struct *current_work(void);
|
||||
extern bool current_is_workqueue_rescuer(void);
|
||||
extern bool workqueue_congested(int cpu, struct workqueue_struct *wq);
|
||||
extern unsigned int work_busy(struct work_struct *work);
|
||||
|
|
|
@ -4179,6 +4179,22 @@ void workqueue_set_max_active(struct workqueue_struct *wq, int max_active)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(workqueue_set_max_active);
|
||||
|
||||
/**
|
||||
* current_work - retrieve %current task's work struct
|
||||
*
|
||||
* Determine if %current task is a workqueue worker and what it's working on.
|
||||
* Useful to find out the context that the %current task is running in.
|
||||
*
|
||||
* Return: work struct if %current task is a workqueue worker, %NULL otherwise.
|
||||
*/
|
||||
struct work_struct *current_work(void)
|
||||
{
|
||||
struct worker *worker = current_wq_worker();
|
||||
|
||||
return worker ? worker->current_work : NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(current_work);
|
||||
|
||||
/**
|
||||
* current_is_workqueue_rescuer - is %current workqueue rescuer?
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue