Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
Pull DRM fixes from Dave Airlie: "Two core fixes, both regressions, along with some intel and some nouveau fixes for regressions and oopses" * 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: drm: correctly restore mappings if drm_open fails drm/nouveau: fix NULL ptr dereference from nv50_disp_intr() drm/nouveau: fix handling empty channel list in ioctl's drm: don't unlock in the addfb error paths drm/i915: Fix build failure drm/i915: Be sure to turn hsync/vsync back on at crt enable (v2) drm/i915: duct-tape locking when eDP init fails
This commit is contained in:
Коммит
bd709bd027
|
@ -2326,7 +2326,6 @@ int drm_mode_addfb(struct drm_device *dev,
|
|||
fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r);
|
||||
if (IS_ERR(fb)) {
|
||||
DRM_DEBUG_KMS("could not create framebuffer\n");
|
||||
drm_modeset_unlock_all(dev);
|
||||
return PTR_ERR(fb);
|
||||
}
|
||||
|
||||
|
@ -2506,7 +2505,6 @@ int drm_mode_addfb2(struct drm_device *dev,
|
|||
fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
|
||||
if (IS_ERR(fb)) {
|
||||
DRM_DEBUG_KMS("could not create framebuffer\n");
|
||||
drm_modeset_unlock_all(dev);
|
||||
return PTR_ERR(fb);
|
||||
}
|
||||
|
||||
|
|
|
@ -123,6 +123,7 @@ int drm_open(struct inode *inode, struct file *filp)
|
|||
int retcode = 0;
|
||||
int need_setup = 0;
|
||||
struct address_space *old_mapping;
|
||||
struct address_space *old_imapping;
|
||||
|
||||
minor = idr_find(&drm_minors_idr, minor_id);
|
||||
if (!minor)
|
||||
|
@ -137,6 +138,7 @@ int drm_open(struct inode *inode, struct file *filp)
|
|||
if (!dev->open_count++)
|
||||
need_setup = 1;
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
old_imapping = inode->i_mapping;
|
||||
old_mapping = dev->dev_mapping;
|
||||
if (old_mapping == NULL)
|
||||
dev->dev_mapping = &inode->i_data;
|
||||
|
@ -159,8 +161,8 @@ int drm_open(struct inode *inode, struct file *filp)
|
|||
|
||||
err_undo:
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
filp->f_mapping = old_mapping;
|
||||
inode->i_mapping = old_mapping;
|
||||
filp->f_mapping = old_imapping;
|
||||
inode->i_mapping = old_imapping;
|
||||
iput(container_of(dev->dev_mapping, struct inode, i_data));
|
||||
dev->dev_mapping = old_mapping;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
|
|
@ -57,7 +57,7 @@ eb_create(struct drm_i915_gem_execbuffer2 *args)
|
|||
if (eb == NULL) {
|
||||
int size = args->buffer_count;
|
||||
int count = PAGE_SIZE / sizeof(struct hlist_head) / 2;
|
||||
BUILD_BUG_ON(!is_power_of_2(PAGE_SIZE / sizeof(struct hlist_head)));
|
||||
BUILD_BUG_ON_NOT_POWER_OF_2(PAGE_SIZE / sizeof(struct hlist_head));
|
||||
while (count > 2*size)
|
||||
count >>= 1;
|
||||
eb = kzalloc(count*sizeof(struct hlist_head) +
|
||||
|
|
|
@ -45,6 +45,9 @@
|
|||
|
||||
struct intel_crt {
|
||||
struct intel_encoder base;
|
||||
/* DPMS state is stored in the connector, which we need in the
|
||||
* encoder's enable/disable callbacks */
|
||||
struct intel_connector *connector;
|
||||
bool force_hotplug_required;
|
||||
u32 adpa_reg;
|
||||
};
|
||||
|
@ -81,29 +84,6 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
|
|||
return true;
|
||||
}
|
||||
|
||||
static void intel_disable_crt(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
|
||||
struct intel_crt *crt = intel_encoder_to_crt(encoder);
|
||||
u32 temp;
|
||||
|
||||
temp = I915_READ(crt->adpa_reg);
|
||||
temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
|
||||
temp &= ~ADPA_DAC_ENABLE;
|
||||
I915_WRITE(crt->adpa_reg, temp);
|
||||
}
|
||||
|
||||
static void intel_enable_crt(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
|
||||
struct intel_crt *crt = intel_encoder_to_crt(encoder);
|
||||
u32 temp;
|
||||
|
||||
temp = I915_READ(crt->adpa_reg);
|
||||
temp |= ADPA_DAC_ENABLE;
|
||||
I915_WRITE(crt->adpa_reg, temp);
|
||||
}
|
||||
|
||||
/* Note: The caller is required to filter out dpms modes not supported by the
|
||||
* platform. */
|
||||
static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
|
||||
|
@ -135,6 +115,19 @@ static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
|
|||
I915_WRITE(crt->adpa_reg, temp);
|
||||
}
|
||||
|
||||
static void intel_disable_crt(struct intel_encoder *encoder)
|
||||
{
|
||||
intel_crt_set_dpms(encoder, DRM_MODE_DPMS_OFF);
|
||||
}
|
||||
|
||||
static void intel_enable_crt(struct intel_encoder *encoder)
|
||||
{
|
||||
struct intel_crt *crt = intel_encoder_to_crt(encoder);
|
||||
|
||||
intel_crt_set_dpms(encoder, crt->connector->base.dpms);
|
||||
}
|
||||
|
||||
|
||||
static void intel_crt_dpms(struct drm_connector *connector, int mode)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
|
@ -746,6 +739,7 @@ void intel_crt_init(struct drm_device *dev)
|
|||
}
|
||||
|
||||
connector = &intel_connector->base;
|
||||
crt->connector = intel_connector;
|
||||
drm_connector_init(dev, &intel_connector->base,
|
||||
&intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
|
||||
|
||||
|
|
|
@ -2559,12 +2559,15 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
|
|||
{
|
||||
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
|
||||
struct intel_dp *intel_dp = &intel_dig_port->dp;
|
||||
struct drm_device *dev = intel_dp_to_dev(intel_dp);
|
||||
|
||||
i2c_del_adapter(&intel_dp->adapter);
|
||||
drm_encoder_cleanup(encoder);
|
||||
if (is_edp(intel_dp)) {
|
||||
cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
ironlake_panel_vdd_off_sync(intel_dp);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
}
|
||||
kfree(intel_dig_port);
|
||||
}
|
||||
|
|
|
@ -391,7 +391,7 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
|
|||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct nouveau_device *device = nv_device(drm->device);
|
||||
struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
|
||||
struct nouveau_abi16_chan *chan, *temp;
|
||||
struct nouveau_abi16_chan *chan = NULL, *temp;
|
||||
struct nouveau_abi16_ntfy *ntfy;
|
||||
struct nouveau_object *object;
|
||||
struct nv_dma_class args = {};
|
||||
|
@ -404,10 +404,11 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
|
|||
if (unlikely(nv_device(abi16->device)->card_type >= NV_C0))
|
||||
return nouveau_abi16_put(abi16, -EINVAL);
|
||||
|
||||
list_for_each_entry_safe(chan, temp, &abi16->channels, head) {
|
||||
if (chan->chan->handle == (NVDRM_CHAN | info->channel))
|
||||
list_for_each_entry(temp, &abi16->channels, head) {
|
||||
if (temp->chan->handle == (NVDRM_CHAN | info->channel)) {
|
||||
chan = temp;
|
||||
break;
|
||||
chan = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!chan)
|
||||
|
@ -459,17 +460,18 @@ nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS)
|
|||
{
|
||||
struct drm_nouveau_gpuobj_free *fini = data;
|
||||
struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
|
||||
struct nouveau_abi16_chan *chan, *temp;
|
||||
struct nouveau_abi16_chan *chan = NULL, *temp;
|
||||
struct nouveau_abi16_ntfy *ntfy;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!abi16))
|
||||
return -ENOMEM;
|
||||
|
||||
list_for_each_entry_safe(chan, temp, &abi16->channels, head) {
|
||||
if (chan->chan->handle == (NVDRM_CHAN | fini->channel))
|
||||
list_for_each_entry(temp, &abi16->channels, head) {
|
||||
if (temp->chan->handle == (NVDRM_CHAN | fini->channel)) {
|
||||
chan = temp;
|
||||
break;
|
||||
chan = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!chan)
|
||||
|
|
|
@ -71,12 +71,26 @@ module_param_named(modeset, nouveau_modeset, int, 0400);
|
|||
|
||||
static struct drm_driver driver;
|
||||
|
||||
static int
|
||||
nouveau_drm_vblank_handler(struct nouveau_eventh *event, int head)
|
||||
{
|
||||
struct nouveau_drm *drm =
|
||||
container_of(event, struct nouveau_drm, vblank[head]);
|
||||
drm_handle_vblank(drm->dev, head);
|
||||
return NVKM_EVENT_KEEP;
|
||||
}
|
||||
|
||||
static int
|
||||
nouveau_drm_vblank_enable(struct drm_device *dev, int head)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct nouveau_disp *pdisp = nouveau_disp(drm->device);
|
||||
nouveau_event_get(pdisp->vblank, head, &drm->vblank);
|
||||
|
||||
if (WARN_ON_ONCE(head > ARRAY_SIZE(drm->vblank)))
|
||||
return -EIO;
|
||||
WARN_ON_ONCE(drm->vblank[head].func);
|
||||
drm->vblank[head].func = nouveau_drm_vblank_handler;
|
||||
nouveau_event_get(pdisp->vblank, head, &drm->vblank[head]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -85,16 +99,11 @@ nouveau_drm_vblank_disable(struct drm_device *dev, int head)
|
|||
{
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct nouveau_disp *pdisp = nouveau_disp(drm->device);
|
||||
nouveau_event_put(pdisp->vblank, head, &drm->vblank);
|
||||
}
|
||||
|
||||
static int
|
||||
nouveau_drm_vblank_handler(struct nouveau_eventh *event, int head)
|
||||
{
|
||||
struct nouveau_drm *drm =
|
||||
container_of(event, struct nouveau_drm, vblank);
|
||||
drm_handle_vblank(drm->dev, head);
|
||||
return NVKM_EVENT_KEEP;
|
||||
if (drm->vblank[head].func)
|
||||
nouveau_event_put(pdisp->vblank, head, &drm->vblank[head]);
|
||||
else
|
||||
WARN_ON_ONCE(1);
|
||||
drm->vblank[head].func = NULL;
|
||||
}
|
||||
|
||||
static u64
|
||||
|
@ -292,7 +301,6 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
|
|||
|
||||
dev->dev_private = drm;
|
||||
drm->dev = dev;
|
||||
drm->vblank.func = nouveau_drm_vblank_handler;
|
||||
|
||||
INIT_LIST_HEAD(&drm->clients);
|
||||
spin_lock_init(&drm->tile.lock);
|
||||
|
|
|
@ -113,7 +113,7 @@ struct nouveau_drm {
|
|||
struct nvbios vbios;
|
||||
struct nouveau_display *display;
|
||||
struct backlight_device *backlight;
|
||||
struct nouveau_eventh vblank;
|
||||
struct nouveau_eventh vblank[4];
|
||||
|
||||
/* power management */
|
||||
struct nouveau_pm *pm;
|
||||
|
|
Загрузка…
Ссылка в новой задаче