diff options
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-ioctl.c | 45 | ||||
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-sysfs.c | 2 | ||||
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb.h | 2 |
3 files changed, 36 insertions, 13 deletions
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index 3a10146dc120..7975a99c33f9 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c | |||
@@ -55,7 +55,7 @@ static struct omapfb2_mem_region *get_mem_region(struct omapfb_info *ofbi, | |||
55 | if (mem_idx >= fbdev->num_fbs) | 55 | if (mem_idx >= fbdev->num_fbs) |
56 | return NULL; | 56 | return NULL; |
57 | 57 | ||
58 | return omapfb_get_mem_region(&fbdev->regions[mem_idx]); | 58 | return &fbdev->regions[mem_idx]; |
59 | } | 59 | } |
60 | 60 | ||
61 | static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) | 61 | static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) |
@@ -77,20 +77,30 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) | |||
77 | /* XXX uses only the first overlay */ | 77 | /* XXX uses only the first overlay */ |
78 | ovl = ofbi->overlays[0]; | 78 | ovl = ofbi->overlays[0]; |
79 | 79 | ||
80 | old_rg = omapfb_get_mem_region(ofbi->region); | 80 | old_rg = ofbi->region; |
81 | new_rg = get_mem_region(ofbi, pi->mem_idx); | 81 | new_rg = get_mem_region(ofbi, pi->mem_idx); |
82 | if (!new_rg) { | 82 | if (!new_rg) { |
83 | r = -EINVAL; | 83 | r = -EINVAL; |
84 | goto put_old; | 84 | goto out; |
85 | } | 85 | } |
86 | 86 | ||
87 | /* Take the locks in a specific order to keep lockdep happy */ | ||
88 | if (old_rg->id < new_rg->id) { | ||
89 | omapfb_get_mem_region(old_rg); | ||
90 | omapfb_get_mem_region(new_rg); | ||
91 | } else if (new_rg->id < old_rg->id) { | ||
92 | omapfb_get_mem_region(new_rg); | ||
93 | omapfb_get_mem_region(old_rg); | ||
94 | } else | ||
95 | omapfb_get_mem_region(old_rg); | ||
96 | |||
87 | if (pi->enabled && !new_rg->size) { | 97 | if (pi->enabled && !new_rg->size) { |
88 | /* | 98 | /* |
89 | * This plane's memory was freed, can't enable it | 99 | * This plane's memory was freed, can't enable it |
90 | * until it's reallocated. | 100 | * until it's reallocated. |
91 | */ | 101 | */ |
92 | r = -EINVAL; | 102 | r = -EINVAL; |
93 | goto put_new; | 103 | goto put_mem; |
94 | } | 104 | } |
95 | 105 | ||
96 | ovl->get_overlay_info(ovl, &old_info); | 106 | ovl->get_overlay_info(ovl, &old_info); |
@@ -135,8 +145,15 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) | |||
135 | if (ovl->manager) | 145 | if (ovl->manager) |
136 | ovl->manager->apply(ovl->manager); | 146 | ovl->manager->apply(ovl->manager); |
137 | 147 | ||
138 | omapfb_put_mem_region(new_rg); | 148 | /* Release the locks in a specific order to keep lockdep happy */ |
139 | omapfb_put_mem_region(old_rg); | 149 | if (old_rg->id > new_rg->id) { |
150 | omapfb_put_mem_region(old_rg); | ||
151 | omapfb_put_mem_region(new_rg); | ||
152 | } else if (new_rg->id > old_rg->id) { | ||
153 | omapfb_put_mem_region(new_rg); | ||
154 | omapfb_put_mem_region(old_rg); | ||
155 | } else | ||
156 | omapfb_put_mem_region(old_rg); | ||
140 | 157 | ||
141 | return 0; | 158 | return 0; |
142 | 159 | ||
@@ -147,10 +164,16 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) | |||
147 | } | 164 | } |
148 | 165 | ||
149 | ovl->set_overlay_info(ovl, &old_info); | 166 | ovl->set_overlay_info(ovl, &old_info); |
150 | put_new: | 167 | put_mem: |
151 | omapfb_put_mem_region(new_rg); | 168 | /* Release the locks in a specific order to keep lockdep happy */ |
152 | put_old: | 169 | if (old_rg->id > new_rg->id) { |
153 | omapfb_put_mem_region(old_rg); | 170 | omapfb_put_mem_region(old_rg); |
171 | omapfb_put_mem_region(new_rg); | ||
172 | } else if (new_rg->id > old_rg->id) { | ||
173 | omapfb_put_mem_region(new_rg); | ||
174 | omapfb_put_mem_region(old_rg); | ||
175 | } else | ||
176 | omapfb_put_mem_region(old_rg); | ||
154 | out: | 177 | out: |
155 | dev_err(fbdev->dev, "setup_plane failed\n"); | 178 | dev_err(fbdev->dev, "setup_plane failed\n"); |
156 | 179 | ||
@@ -198,7 +221,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) | |||
198 | 221 | ||
199 | rg = ofbi->region; | 222 | rg = ofbi->region; |
200 | 223 | ||
201 | down_write(&rg->lock); | 224 | down_write_nested(&rg->lock, rg->id); |
202 | 225 | ||
203 | if (atomic_read(&rg->map_count)) { | 226 | if (atomic_read(&rg->map_count)) { |
204 | r = -EBUSY; | 227 | r = -EBUSY; |
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c index 724b760404f2..1e714bb48d39 100644 --- a/drivers/video/omap2/omapfb/omapfb-sysfs.c +++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c | |||
@@ -452,7 +452,7 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr, | |||
452 | 452 | ||
453 | rg = ofbi->region; | 453 | rg = ofbi->region; |
454 | 454 | ||
455 | down_write(&rg->lock); | 455 | down_write_nested(&rg->lock, rg->id); |
456 | 456 | ||
457 | if (atomic_read(&rg->map_count)) { | 457 | if (atomic_read(&rg->map_count)) { |
458 | r = -EBUSY; | 458 | r = -EBUSY; |
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h index 195a760eef54..676b55d98941 100644 --- a/drivers/video/omap2/omapfb/omapfb.h +++ b/drivers/video/omap2/omapfb/omapfb.h | |||
@@ -165,7 +165,7 @@ static inline int omapfb_overlay_enable(struct omap_overlay *ovl, | |||
165 | static inline struct omapfb2_mem_region * | 165 | static inline struct omapfb2_mem_region * |
166 | omapfb_get_mem_region(struct omapfb2_mem_region *rg) | 166 | omapfb_get_mem_region(struct omapfb2_mem_region *rg) |
167 | { | 167 | { |
168 | down_read(&rg->lock); | 168 | down_read_nested(&rg->lock, rg->id); |
169 | return rg; | 169 | return rg; |
170 | } | 170 | } |
171 | 171 | ||