]>
Commit | Line | Data |
---|---|---|
f660c16b GKH |
1 | From fdb40a08ef7bc970899c3a1f471165f9c22763a1 Mon Sep 17 00:00:00 2001 |
2 | From: Ilija Hadzic <ilijahadzic@gmail.com> | |
3 | Date: Mon, 29 Oct 2012 17:35:01 +0000 | |
4 | Subject: drm: set dev_mapping before calling drm_open_helper | |
5 | ||
6 | From: Ilija Hadzic <ilijahadzic@gmail.com> | |
7 | ||
8 | commit fdb40a08ef7bc970899c3a1f471165f9c22763a1 upstream. | |
9 | ||
10 | Some drivers (specifically vmwgfx) look at dev_mapping | |
11 | in their open hook, so we have to set dev->dev_mapping | |
12 | earlier in the process. | |
13 | ||
14 | Reference: | |
15 | http://lists.freedesktop.org/archives/dri-devel/2012-October/029420.html | |
16 | ||
17 | Signed-off-by: Ilija Hadzic <ihadzic@research.bell-labs.com> | |
18 | Reported-by: Thomas Hellstrom <thellstrom@vmware.com> | |
19 | Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com> | |
20 | Signed-off-by: Dave Airlie <airlied@redhat.com> | |
21 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
22 | ||
23 | --- | |
24 | drivers/gpu/drm/drm_fops.c | 47 ++++++++++++++++++++++++++++----------------- | |
25 | 1 file changed, 30 insertions(+), 17 deletions(-) | |
26 | ||
27 | --- a/drivers/gpu/drm/drm_fops.c | |
28 | +++ b/drivers/gpu/drm/drm_fops.c | |
29 | @@ -121,6 +121,8 @@ int drm_open(struct inode *inode, struct | |
30 | int minor_id = iminor(inode); | |
31 | struct drm_minor *minor; | |
32 | int retcode = 0; | |
33 | + int need_setup = 0; | |
34 | + struct address_space *old_mapping; | |
35 | ||
36 | minor = idr_find(&drm_minors_idr, minor_id); | |
37 | if (!minor) | |
38 | @@ -132,26 +134,37 @@ int drm_open(struct inode *inode, struct | |
39 | if (drm_device_is_unplugged(dev)) | |
40 | return -ENODEV; | |
41 | ||
42 | + if (!dev->open_count++) | |
43 | + need_setup = 1; | |
44 | + mutex_lock(&dev->struct_mutex); | |
45 | + old_mapping = dev->dev_mapping; | |
46 | + if (old_mapping == NULL) | |
47 | + dev->dev_mapping = &inode->i_data; | |
48 | + /* ihold ensures nobody can remove inode with our i_data */ | |
49 | + ihold(container_of(dev->dev_mapping, struct inode, i_data)); | |
50 | + inode->i_mapping = dev->dev_mapping; | |
51 | + filp->f_mapping = dev->dev_mapping; | |
52 | + mutex_unlock(&dev->struct_mutex); | |
53 | + | |
54 | retcode = drm_open_helper(inode, filp, dev); | |
55 | - if (!retcode) { | |
56 | - atomic_inc(&dev->counts[_DRM_STAT_OPENS]); | |
57 | - if (!dev->open_count++) { | |
58 | - retcode = drm_setup(dev); | |
59 | - if (retcode) | |
60 | - dev->open_count--; | |
61 | - } | |
62 | - } | |
63 | - if (!retcode) { | |
64 | - mutex_lock(&dev->struct_mutex); | |
65 | - if (dev->dev_mapping == NULL) | |
66 | - dev->dev_mapping = &inode->i_data; | |
67 | - /* ihold ensures nobody can remove inode with our i_data */ | |
68 | - ihold(container_of(dev->dev_mapping, struct inode, i_data)); | |
69 | - inode->i_mapping = dev->dev_mapping; | |
70 | - filp->f_mapping = dev->dev_mapping; | |
71 | - mutex_unlock(&dev->struct_mutex); | |
72 | + if (retcode) | |
73 | + goto err_undo; | |
74 | + atomic_inc(&dev->counts[_DRM_STAT_OPENS]); | |
75 | + if (need_setup) { | |
76 | + retcode = drm_setup(dev); | |
77 | + if (retcode) | |
78 | + goto err_undo; | |
79 | } | |
80 | + return 0; | |
81 | ||
82 | +err_undo: | |
83 | + mutex_lock(&dev->struct_mutex); | |
84 | + filp->f_mapping = old_mapping; | |
85 | + inode->i_mapping = old_mapping; | |
86 | + iput(container_of(dev->dev_mapping, struct inode, i_data)); | |
87 | + dev->dev_mapping = old_mapping; | |
88 | + mutex_unlock(&dev->struct_mutex); | |
89 | + dev->open_count--; | |
90 | return retcode; | |
91 | } | |
92 | EXPORT_SYMBOL(drm_open); |