mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-16 01:04:08 +08:00
Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
Pull drm fixes from Dave Airlie: "Nothing too crazy in here: a bunch of AMD fixes/quirks, two msm fixes, some rockchip fixes, and a udl warning fix, along with one locking fix for displayport that seems to fix some dodgy monitors" * 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: drm/udl: Use unlocked gem unreferencing drm/dp: move hw_mutex up the call stack drm/amdgpu: Don't move pinned BOs drm/radeon: Don't move pinned BOs drm/radeon: add a dpm quirk for all R7 370 parts drm/radeon: add another R7 370 quirk drm/rockchip: dw_hdmi: Don't call platform_set_drvdata() drm/rockchip: vop: Fix vop crtc cleanup drm/rockchip: dw_hdmi: Call drm_encoder_cleanup() in error path drm/rockchip: vop: Disable planes when disabling CRTC drm/rockchip: vop: Don't reject empty modesets drm/rockchip: cancel pending vblanks on close drm/rockchip: vop: fix crtc size in plane check drm/radeon: add a dpm quirk for sapphire Dual-X R7 370 2G D5 drm/amd: Beef up ACP Kconfig menu text drm/msm: fix typo in the !COMMON_CLK case drm/msm: fix bug after preclose removal
This commit is contained in:
commit
6ddf37da05
@ -1,10 +1,14 @@
|
||||
menu "ACP Configuration"
|
||||
menu "ACP (Audio CoProcessor) Configuration"
|
||||
|
||||
config DRM_AMD_ACP
|
||||
bool "Enable ACP IP support"
|
||||
bool "Enable AMD Audio CoProcessor IP support"
|
||||
select MFD_CORE
|
||||
select PM_GENERIC_DOMAINS if PM
|
||||
help
|
||||
Choose this option to enable ACP IP support for AMD SOCs.
|
||||
This adds the ACP (Audio CoProcessor) IP driver and wires
|
||||
it up into the amdgpu driver. The ACP block provides the DMA
|
||||
engine for the i2s-based ALSA driver. It is required for audio
|
||||
on APUs which utilize an i2s codec.
|
||||
|
||||
endmenu
|
||||
|
@ -608,6 +608,10 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
|
||||
if ((offset + size) <= adev->mc.visible_vram_size)
|
||||
return 0;
|
||||
|
||||
/* Can't move a pinned BO to visible VRAM */
|
||||
if (abo->pin_count > 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* hurrah the memory is not visible ! */
|
||||
amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_VRAM);
|
||||
lpfn = adev->mc.visible_vram_size >> PAGE_SHIFT;
|
||||
|
@ -384,9 +384,15 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo,
|
||||
struct ttm_mem_reg *new_mem)
|
||||
{
|
||||
struct amdgpu_device *adev;
|
||||
struct amdgpu_bo *abo;
|
||||
struct ttm_mem_reg *old_mem = &bo->mem;
|
||||
int r;
|
||||
|
||||
/* Can't move a pinned BO */
|
||||
abo = container_of(bo, struct amdgpu_bo, tbo);
|
||||
if (WARN_ON_ONCE(abo->pin_count > 0))
|
||||
return -EINVAL;
|
||||
|
||||
adev = amdgpu_get_adev(bo->bdev);
|
||||
if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) {
|
||||
amdgpu_move_null(bo, new_mem);
|
||||
|
@ -179,7 +179,7 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
|
||||
{
|
||||
struct drm_dp_aux_msg msg;
|
||||
unsigned int retry;
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.address = offset;
|
||||
@ -187,6 +187,8 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
|
||||
msg.buffer = buffer;
|
||||
msg.size = size;
|
||||
|
||||
mutex_lock(&aux->hw_mutex);
|
||||
|
||||
/*
|
||||
* The specification doesn't give any recommendation on how often to
|
||||
* retry native transactions. We used to retry 7 times like for
|
||||
@ -195,25 +197,24 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
|
||||
*/
|
||||
for (retry = 0; retry < 32; retry++) {
|
||||
|
||||
mutex_lock(&aux->hw_mutex);
|
||||
err = aux->transfer(aux, &msg);
|
||||
mutex_unlock(&aux->hw_mutex);
|
||||
if (err < 0) {
|
||||
if (err == -EBUSY)
|
||||
continue;
|
||||
|
||||
return err;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
|
||||
switch (msg.reply & DP_AUX_NATIVE_REPLY_MASK) {
|
||||
case DP_AUX_NATIVE_REPLY_ACK:
|
||||
if (err < size)
|
||||
return -EPROTO;
|
||||
return err;
|
||||
err = -EPROTO;
|
||||
goto unlock;
|
||||
|
||||
case DP_AUX_NATIVE_REPLY_NACK:
|
||||
return -EIO;
|
||||
err = -EIO;
|
||||
goto unlock;
|
||||
|
||||
case DP_AUX_NATIVE_REPLY_DEFER:
|
||||
usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100);
|
||||
@ -222,7 +223,11 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("too many retries, giving up\n");
|
||||
return -EIO;
|
||||
err = -EIO;
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&aux->hw_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -544,9 +549,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
|
||||
int max_retries = max(7, drm_dp_i2c_retry_count(msg, dp_aux_i2c_speed_khz));
|
||||
|
||||
for (retry = 0, defer_i2c = 0; retry < (max_retries + defer_i2c); retry++) {
|
||||
mutex_lock(&aux->hw_mutex);
|
||||
ret = aux->transfer(aux, msg);
|
||||
mutex_unlock(&aux->hw_mutex);
|
||||
if (ret < 0) {
|
||||
if (ret == -EBUSY)
|
||||
continue;
|
||||
@ -685,6 +688,8 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
||||
mutex_lock(&aux->hw_mutex);
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
msg.address = msgs[i].addr;
|
||||
drm_dp_i2c_msg_set_request(&msg, &msgs[i]);
|
||||
@ -739,6 +744,8 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
|
||||
msg.size = 0;
|
||||
(void)drm_dp_i2c_do_msg(aux, &msg);
|
||||
|
||||
mutex_unlock(&aux->hw_mutex);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -196,7 +196,7 @@ void __exit msm_hdmi_phy_driver_unregister(void);
|
||||
int msm_hdmi_pll_8960_init(struct platform_device *pdev);
|
||||
int msm_hdmi_pll_8996_init(struct platform_device *pdev);
|
||||
#else
|
||||
static inline int msm_hdmi_pll_8960_init(struct platform_device *pdev);
|
||||
static inline int msm_hdmi_pll_8960_init(struct platform_device *pdev)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -467,9 +467,6 @@ static void msm_preclose(struct drm_device *dev, struct drm_file *file)
|
||||
struct msm_file_private *ctx = file->driver_priv;
|
||||
struct msm_kms *kms = priv->kms;
|
||||
|
||||
if (kms)
|
||||
kms->funcs->preclose(kms, file);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
if (ctx == priv->lastctx)
|
||||
priv->lastctx = NULL;
|
||||
|
@ -55,7 +55,6 @@ struct msm_kms_funcs {
|
||||
struct drm_encoder *slave_encoder,
|
||||
bool is_cmd_mode);
|
||||
/* cleanup: */
|
||||
void (*preclose)(struct msm_kms *kms, struct drm_file *file);
|
||||
void (*destroy)(struct msm_kms *kms);
|
||||
};
|
||||
|
||||
|
@ -799,6 +799,10 @@ int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
|
||||
if ((offset + size) <= rdev->mc.visible_vram_size)
|
||||
return 0;
|
||||
|
||||
/* Can't move a pinned BO to visible VRAM */
|
||||
if (rbo->pin_count > 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* hurrah the memory is not visible ! */
|
||||
radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM);
|
||||
lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT;
|
||||
|
@ -397,9 +397,15 @@ static int radeon_bo_move(struct ttm_buffer_object *bo,
|
||||
struct ttm_mem_reg *new_mem)
|
||||
{
|
||||
struct radeon_device *rdev;
|
||||
struct radeon_bo *rbo;
|
||||
struct ttm_mem_reg *old_mem = &bo->mem;
|
||||
int r;
|
||||
|
||||
/* Can't move a pinned BO */
|
||||
rbo = container_of(bo, struct radeon_bo, tbo);
|
||||
if (WARN_ON_ONCE(rbo->pin_count > 0))
|
||||
return -EINVAL;
|
||||
|
||||
rdev = radeon_get_rdev(bo->bdev);
|
||||
if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) {
|
||||
radeon_move_null(bo, new_mem);
|
||||
|
@ -2926,9 +2926,11 @@ static struct si_dpm_quirk si_dpm_quirk_list[] = {
|
||||
/* PITCAIRN - https://bugs.freedesktop.org/show_bug.cgi?id=76490 */
|
||||
{ PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 },
|
||||
{ PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 },
|
||||
{ PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0x2015, 0, 120000 },
|
||||
{ PCI_VENDOR_ID_ATI, 0x6810, 0x174b, 0xe271, 85000, 90000 },
|
||||
{ PCI_VENDOR_ID_ATI, 0x6811, 0x1462, 0x2015, 0, 120000 },
|
||||
{ PCI_VENDOR_ID_ATI, 0x6811, 0x1043, 0x2015, 0, 120000 },
|
||||
{ PCI_VENDOR_ID_ATI, 0x6811, 0x148c, 0x2015, 0, 120000 },
|
||||
{ 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
@ -3008,6 +3010,10 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
|
||||
}
|
||||
++p;
|
||||
}
|
||||
/* limit mclk on all R7 370 parts for stability */
|
||||
if (rdev->pdev->device == 0x6811 &&
|
||||
rdev->pdev->revision == 0x81)
|
||||
max_mclk = 120000;
|
||||
|
||||
if (rps->vce_active) {
|
||||
rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
|
||||
|
@ -271,8 +271,6 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
|
||||
if (!iores)
|
||||
return -ENXIO;
|
||||
|
||||
platform_set_drvdata(pdev, hdmi);
|
||||
|
||||
encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
|
||||
/*
|
||||
* If we failed to find the CRTC(s) which this encoder is
|
||||
@ -293,7 +291,16 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
|
||||
drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL);
|
||||
|
||||
return dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data);
|
||||
ret = dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data);
|
||||
|
||||
/*
|
||||
* If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
|
||||
* which would have called the encoder cleanup. Do it manually.
|
||||
*/
|
||||
if (ret)
|
||||
drm_encoder_cleanup(encoder);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
|
||||
|
@ -251,6 +251,27 @@ static int rockchip_drm_unload(struct drm_device *drm_dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rockchip_drm_crtc_cancel_pending_vblank(struct drm_crtc *crtc,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct rockchip_drm_private *priv = crtc->dev->dev_private;
|
||||
int pipe = drm_crtc_index(crtc);
|
||||
|
||||
if (pipe < ROCKCHIP_MAX_CRTC &&
|
||||
priv->crtc_funcs[pipe] &&
|
||||
priv->crtc_funcs[pipe]->cancel_pending_vblank)
|
||||
priv->crtc_funcs[pipe]->cancel_pending_vblank(crtc, file_priv);
|
||||
}
|
||||
|
||||
static void rockchip_drm_preclose(struct drm_device *dev,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
|
||||
rockchip_drm_crtc_cancel_pending_vblank(crtc, file_priv);
|
||||
}
|
||||
|
||||
void rockchip_drm_lastclose(struct drm_device *dev)
|
||||
{
|
||||
struct rockchip_drm_private *priv = dev->dev_private;
|
||||
@ -281,6 +302,7 @@ static struct drm_driver rockchip_drm_driver = {
|
||||
DRIVER_PRIME | DRIVER_ATOMIC,
|
||||
.load = rockchip_drm_load,
|
||||
.unload = rockchip_drm_unload,
|
||||
.preclose = rockchip_drm_preclose,
|
||||
.lastclose = rockchip_drm_lastclose,
|
||||
.get_vblank_counter = drm_vblank_no_hw_counter,
|
||||
.enable_vblank = rockchip_drm_crtc_enable_vblank,
|
||||
|
@ -40,6 +40,7 @@ struct rockchip_crtc_funcs {
|
||||
int (*enable_vblank)(struct drm_crtc *crtc);
|
||||
void (*disable_vblank)(struct drm_crtc *crtc);
|
||||
void (*wait_for_update)(struct drm_crtc *crtc);
|
||||
void (*cancel_pending_vblank)(struct drm_crtc *crtc, struct drm_file *file_priv);
|
||||
};
|
||||
|
||||
struct rockchip_atomic_commit {
|
||||
|
@ -499,10 +499,25 @@ err_disable_hclk:
|
||||
static void vop_crtc_disable(struct drm_crtc *crtc)
|
||||
{
|
||||
struct vop *vop = to_vop(crtc);
|
||||
int i;
|
||||
|
||||
if (!vop->is_enabled)
|
||||
return;
|
||||
|
||||
/*
|
||||
* We need to make sure that all windows are disabled before we
|
||||
* disable that crtc. Otherwise we might try to scan from a destroyed
|
||||
* buffer later.
|
||||
*/
|
||||
for (i = 0; i < vop->data->win_size; i++) {
|
||||
struct vop_win *vop_win = &vop->win[i];
|
||||
const struct vop_win_data *win = vop_win->data;
|
||||
|
||||
spin_lock(&vop->reg_lock);
|
||||
VOP_WIN_SET(vop, win, enable, 0);
|
||||
spin_unlock(&vop->reg_lock);
|
||||
}
|
||||
|
||||
drm_crtc_vblank_off(crtc);
|
||||
|
||||
/*
|
||||
@ -549,6 +564,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
struct drm_crtc *crtc = state->crtc;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_framebuffer *fb = state->fb;
|
||||
struct vop_win *vop_win = to_vop_win(plane);
|
||||
struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
|
||||
@ -563,12 +579,13 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
|
||||
int max_scale = win->phy->scl ? FRAC_16_16(8, 1) :
|
||||
DRM_PLANE_HELPER_NO_SCALING;
|
||||
|
||||
crtc = crtc ? crtc : plane->state->crtc;
|
||||
/*
|
||||
* Both crtc or plane->state->crtc can be null.
|
||||
*/
|
||||
if (!crtc || !fb)
|
||||
goto out_disable;
|
||||
|
||||
crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
|
||||
if (WARN_ON(!crtc_state))
|
||||
return -EINVAL;
|
||||
|
||||
src->x1 = state->src_x;
|
||||
src->y1 = state->src_y;
|
||||
src->x2 = state->src_x + state->src_w;
|
||||
@ -580,8 +597,8 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
|
||||
|
||||
clip.x1 = 0;
|
||||
clip.y1 = 0;
|
||||
clip.x2 = crtc->mode.hdisplay;
|
||||
clip.y2 = crtc->mode.vdisplay;
|
||||
clip.x2 = crtc_state->adjusted_mode.hdisplay;
|
||||
clip.y2 = crtc_state->adjusted_mode.vdisplay;
|
||||
|
||||
ret = drm_plane_helper_check_update(plane, crtc, state->fb,
|
||||
src, dest, &clip,
|
||||
@ -873,10 +890,30 @@ static void vop_crtc_wait_for_update(struct drm_crtc *crtc)
|
||||
WARN_ON(!wait_for_completion_timeout(&vop->wait_update_complete, 100));
|
||||
}
|
||||
|
||||
static void vop_crtc_cancel_pending_vblank(struct drm_crtc *crtc,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_device *drm = crtc->dev;
|
||||
struct vop *vop = to_vop(crtc);
|
||||
struct drm_pending_vblank_event *e;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&drm->event_lock, flags);
|
||||
e = vop->event;
|
||||
if (e && e->base.file_priv == file_priv) {
|
||||
vop->event = NULL;
|
||||
|
||||
e->base.destroy(&e->base);
|
||||
file_priv->event_space += sizeof(e->event);
|
||||
}
|
||||
spin_unlock_irqrestore(&drm->event_lock, flags);
|
||||
}
|
||||
|
||||
static const struct rockchip_crtc_funcs private_crtc_funcs = {
|
||||
.enable_vblank = vop_crtc_enable_vblank,
|
||||
.disable_vblank = vop_crtc_disable_vblank,
|
||||
.wait_for_update = vop_crtc_wait_for_update,
|
||||
.cancel_pending_vblank = vop_crtc_cancel_pending_vblank,
|
||||
};
|
||||
|
||||
static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
@ -885,9 +922,6 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
{
|
||||
struct vop *vop = to_vop(crtc);
|
||||
|
||||
if (adjusted_mode->htotal == 0 || adjusted_mode->vtotal == 0)
|
||||
return false;
|
||||
|
||||
adjusted_mode->clock =
|
||||
clk_round_rate(vop->dclk, mode->clock * 1000) / 1000;
|
||||
|
||||
@ -1108,7 +1142,7 @@ static int vop_create_crtc(struct vop *vop)
|
||||
const struct vop_data *vop_data = vop->data;
|
||||
struct device *dev = vop->dev;
|
||||
struct drm_device *drm_dev = vop->drm_dev;
|
||||
struct drm_plane *primary = NULL, *cursor = NULL, *plane;
|
||||
struct drm_plane *primary = NULL, *cursor = NULL, *plane, *tmp;
|
||||
struct drm_crtc *crtc = &vop->crtc;
|
||||
struct device_node *port;
|
||||
int ret;
|
||||
@ -1148,7 +1182,7 @@ static int vop_create_crtc(struct vop *vop)
|
||||
ret = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor,
|
||||
&vop_crtc_funcs, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_cleanup_planes;
|
||||
|
||||
drm_crtc_helper_add(crtc, &vop_crtc_helper_funcs);
|
||||
|
||||
@ -1181,6 +1215,7 @@ static int vop_create_crtc(struct vop *vop)
|
||||
if (!port) {
|
||||
DRM_ERROR("no port node found in %s\n",
|
||||
dev->of_node->full_name);
|
||||
ret = -ENOENT;
|
||||
goto err_cleanup_crtc;
|
||||
}
|
||||
|
||||
@ -1194,7 +1229,8 @@ static int vop_create_crtc(struct vop *vop)
|
||||
err_cleanup_crtc:
|
||||
drm_crtc_cleanup(crtc);
|
||||
err_cleanup_planes:
|
||||
list_for_each_entry(plane, &drm_dev->mode_config.plane_list, head)
|
||||
list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list,
|
||||
head)
|
||||
drm_plane_cleanup(plane);
|
||||
return ret;
|
||||
}
|
||||
@ -1202,9 +1238,28 @@ err_cleanup_planes:
|
||||
static void vop_destroy_crtc(struct vop *vop)
|
||||
{
|
||||
struct drm_crtc *crtc = &vop->crtc;
|
||||
struct drm_device *drm_dev = vop->drm_dev;
|
||||
struct drm_plane *plane, *tmp;
|
||||
|
||||
rockchip_unregister_crtc_funcs(crtc);
|
||||
of_node_put(crtc->port);
|
||||
|
||||
/*
|
||||
* We need to cleanup the planes now. Why?
|
||||
*
|
||||
* The planes are "&vop->win[i].base". That means the memory is
|
||||
* all part of the big "struct vop" chunk of memory. That memory
|
||||
* was devm allocated and associated with this component. We need to
|
||||
* free it ourselves before vop_unbind() finishes.
|
||||
*/
|
||||
list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list,
|
||||
head)
|
||||
vop_plane_destroy(plane);
|
||||
|
||||
/*
|
||||
* Destroy CRTC after vop_plane_destroy() since vop_disable_plane()
|
||||
* references the CRTC.
|
||||
*/
|
||||
drm_crtc_cleanup(crtc);
|
||||
}
|
||||
|
||||
|
@ -536,7 +536,7 @@ static int udlfb_create(struct drm_fb_helper *helper,
|
||||
out_destroy_fbi:
|
||||
drm_fb_helper_release_fbi(helper);
|
||||
out_gfree:
|
||||
drm_gem_object_unreference(&ufbdev->ufb.obj->base);
|
||||
drm_gem_object_unreference_unlocked(&ufbdev->ufb.obj->base);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ udl_gem_create(struct drm_file *file,
|
||||
return ret;
|
||||
}
|
||||
|
||||
drm_gem_object_unreference(&obj->base);
|
||||
drm_gem_object_unreference_unlocked(&obj->base);
|
||||
*handle_p = handle;
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user