summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_fops.c
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2012-11-16 16:59:17 +0100
committerArnd Bergmann <arnd@arndb.de>2012-11-16 16:59:17 +0100
commitdb2f95de7e6ab3d5cd7cc047bb09eb9ada07e3ba (patch)
tree46543712dbbb15075f7532621b0311f1de653e57 /drivers/gpu/drm/drm_fops.c
parent1bf0bc1e050fc425cc776b10d3ce8754389aabbe (diff)
parentd6aef84a48fa54ac606ae719fcd125199939f43d (diff)
Merge tag 'imx-soc' of git://git.pengutronix.de/git/imx/linux-2.6 into next/soc
From Sascha Hauer <s.hauer@pengutronix.de>: ARM i.MX SoC updates based on imx-multiplatform branch. * tag 'imx-soc' of git://git.pengutronix.de/git/imx/linux-2.6: ARM i.MX51 babbage: Add display support ARM i.MX6: Add IPU support ARM i.MX51: Add IPU support ARM i.MX53: Add IPU support ARM i.MX5: switch IPU clk support to devicetree bindings ARM i.MX6: fix ldb_di_sel mux ARM i.MX51: setup MIPI during startup mx2_camera: Fix regression caused by clock conversion ARM: clk-imx27: Add missing clock for mx2-camera ARM i.MX27: Fix low reference clock path ARM: dts: imx27-3ds: Remove local watchdog inclusion watchdog: Support imx watchdog on SOC_IMX53 ARM: mach-imx: Support for DryIce RTC in i.MX53 ARM : i.MX27 : split code for allocation of ressources of camera and eMMA Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers/gpu/drm/drm_fops.c')
-rw-r--r--drivers/gpu/drm/drm_fops.c44
1 files changed, 30 insertions, 14 deletions
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 7ef1b673e1b..133b4132983 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -121,6 +121,8 @@ int drm_open(struct inode *inode, struct file *filp)
int minor_id = iminor(inode);
struct drm_minor *minor;
int retcode = 0;
+ int need_setup = 0;
+ struct address_space *old_mapping;
minor = idr_find(&drm_minors_idr, minor_id);
if (!minor)
@@ -132,23 +134,37 @@ int drm_open(struct inode *inode, struct file *filp)
if (drm_device_is_unplugged(dev))
return -ENODEV;
+ if (!dev->open_count++)
+ need_setup = 1;
+ mutex_lock(&dev->struct_mutex);
+ old_mapping = dev->dev_mapping;
+ if (old_mapping == NULL)
+ dev->dev_mapping = &inode->i_data;
+ /* ihold ensures nobody can remove inode with our i_data */
+ ihold(container_of(dev->dev_mapping, struct inode, i_data));
+ inode->i_mapping = dev->dev_mapping;
+ filp->f_mapping = dev->dev_mapping;
+ mutex_unlock(&dev->struct_mutex);
+
retcode = drm_open_helper(inode, filp, dev);
- if (!retcode) {
- atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
- if (!dev->open_count++)
- retcode = drm_setup(dev);
- }
- if (!retcode) {
- mutex_lock(&dev->struct_mutex);
- if (dev->dev_mapping == NULL)
- dev->dev_mapping = &inode->i_data;
- /* ihold ensures nobody can remove inode with our i_data */
- ihold(container_of(dev->dev_mapping, struct inode, i_data));
- inode->i_mapping = dev->dev_mapping;
- filp->f_mapping = dev->dev_mapping;
- mutex_unlock(&dev->struct_mutex);
+ if (retcode)
+ goto err_undo;
+ atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
+ if (need_setup) {
+ retcode = drm_setup(dev);
+ if (retcode)
+ goto err_undo;
}
+ return 0;
+err_undo:
+ mutex_lock(&dev->struct_mutex);
+ filp->f_mapping = old_mapping;
+ inode->i_mapping = old_mapping;
+ iput(container_of(dev->dev_mapping, struct inode, i_data));
+ dev->dev_mapping = old_mapping;
+ mutex_unlock(&dev->struct_mutex);
+ dev->open_count--;
return retcode;
}
EXPORT_SYMBOL(drm_open);