aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/bw2.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-07-28 01:31:46 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-07-30 03:27:33 -0400
commitc7f439b99efbea74c70a5531f92566db5a6731f2 (patch)
tree7053ceffa23d54670862e14d0bc2eec9d5d42427 /drivers/video/bw2.c
parenta0afaa6ab12cf696d170c22a8fdfd88c3e33555c (diff)
[VIDEO]: Fix OOPS in all SBUS framebuffer drivers.
All of these drivers use a silly: struct all_info { struct fb_info info; struct foo_par par; }; struct all_info *all = kzalloc(sizeof(*all), GFP_KERNEL); all->info.par = &all->par; etc. etc. code sequence, basically replicating the provided framebuffer_alloc()/framebuffer_release(), and doing it badly. Not only is this massive code duplication, it also caused a bug in that we weren't setting the fb_info->device pointer which results in an OOPS when fb_is_primary_device() runs. Fix all of this by using framebuffer_{alloc,release}() and passing in "&of_device->dev" as the device pointer. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/video/bw2.c')
-rw-r--r--drivers/video/bw2.c105
1 files changed, 53 insertions, 52 deletions
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index b0b2e40bbd9f..718b9f83736e 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -279,90 +279,91 @@ static void __devinit bw2_do_default_mode(struct bw2_par *par,
279 } 279 }
280} 280}
281 281
282struct all_info { 282static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *match)
283 struct fb_info info;
284 struct bw2_par par;
285};
286
287static int __devinit bw2_init_one(struct of_device *op)
288{ 283{
289 struct device_node *dp = op->node; 284 struct device_node *dp = op->node;
290 struct all_info *all; 285 struct fb_info *info;
286 struct bw2_par *par;
291 int linebytes, err; 287 int linebytes, err;
292 288
293 all = kzalloc(sizeof(*all), GFP_KERNEL); 289 info = framebuffer_alloc(sizeof(struct bw2_par), &op->dev);
294 if (!all)
295 return -ENOMEM;
296 290
297 spin_lock_init(&all->par.lock); 291 err = -ENOMEM;
292 if (!info)
293 goto out_err;
294 par = info->par;
298 295
299 all->par.physbase = op->resource[0].start; 296 spin_lock_init(&par->lock);
300 all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
301 297
302 sbusfb_fill_var(&all->info.var, dp->node, 1); 298 par->physbase = op->resource[0].start;
299 par->which_io = op->resource[0].flags & IORESOURCE_BITS;
300
301 sbusfb_fill_var(&info->var, dp->node, 1);
303 linebytes = of_getintprop_default(dp, "linebytes", 302 linebytes = of_getintprop_default(dp, "linebytes",
304 all->info.var.xres); 303 info->var.xres);
305 304
306 all->info.var.red.length = all->info.var.green.length = 305 info->var.red.length = info->var.green.length =
307 all->info.var.blue.length = all->info.var.bits_per_pixel; 306 info->var.blue.length = info->var.bits_per_pixel;
308 all->info.var.red.offset = all->info.var.green.offset = 307 info->var.red.offset = info->var.green.offset =
309 all->info.var.blue.offset = 0; 308 info->var.blue.offset = 0;
310 309
311 all->par.regs = of_ioremap(&op->resource[0], BWTWO_REGISTER_OFFSET, 310 par->regs = of_ioremap(&op->resource[0], BWTWO_REGISTER_OFFSET,
312 sizeof(struct bw2_regs), "bw2 regs"); 311 sizeof(struct bw2_regs), "bw2 regs");
312 if (!par->regs)
313 goto out_release_fb;
313 314
314 if (!of_find_property(dp, "width", NULL)) 315 if (!of_find_property(dp, "width", NULL))
315 bw2_do_default_mode(&all->par, &all->info, &linebytes); 316 bw2_do_default_mode(par, info, &linebytes);
316 317
317 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); 318 par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
318 319
319 all->info.flags = FBINFO_DEFAULT; 320 info->flags = FBINFO_DEFAULT;
320 all->info.fbops = &bw2_ops; 321 info->fbops = &bw2_ops;
321 322
322 all->info.screen_base = 323 info->screen_base = of_ioremap(&op->resource[0], 0,
323 of_ioremap(&op->resource[0], 0, all->par.fbsize, "bw2 ram"); 324 par->fbsize, "bw2 ram");
324 all->info.par = &all->par; 325 if (!info->screen_base)
326 goto out_unmap_regs;
325 327
326 bw2_blank(0, &all->info); 328 bw2_blank(0, info);
327 329
328 bw2_init_fix(&all->info, linebytes); 330 bw2_init_fix(info, linebytes);
329 331
330 err= register_framebuffer(&all->info); 332 err = register_framebuffer(info);
331 if (err < 0) { 333 if (err < 0)
332 of_iounmap(&op->resource[0], 334 goto out_unmap_screen;
333 all->par.regs, sizeof(struct bw2_regs));
334 of_iounmap(&op->resource[0],
335 all->info.screen_base, all->par.fbsize);
336 kfree(all);
337 return err;
338 }
339 335
340 dev_set_drvdata(&op->dev, all); 336 dev_set_drvdata(&op->dev, info);
341 337
342 printk("%s: bwtwo at %lx:%lx\n", 338 printk("%s: bwtwo at %lx:%lx\n",
343 dp->full_name, 339 dp->full_name, par->which_io, par->physbase);
344 all->par.which_io, all->par.physbase);
345 340
346 return 0; 341 return 0;
347}
348 342
349static int __devinit bw2_probe(struct of_device *dev, const struct of_device_id *match) 343out_unmap_screen:
350{ 344 of_iounmap(&op->resource[0], info->screen_base, par->fbsize);
351 struct of_device *op = to_of_device(&dev->dev); 345
346out_unmap_regs:
347 of_iounmap(&op->resource[0], par->regs, sizeof(struct bw2_regs));
348
349out_release_fb:
350 framebuffer_release(info);
352 351
353 return bw2_init_one(op); 352out_err:
353 return err;
354} 354}
355 355
356static int __devexit bw2_remove(struct of_device *op) 356static int __devexit bw2_remove(struct of_device *op)
357{ 357{
358 struct all_info *all = dev_get_drvdata(&op->dev); 358 struct fb_info *info = dev_get_drvdata(&op->dev);
359 struct bw2_par *par = info->par;
359 360
360 unregister_framebuffer(&all->info); 361 unregister_framebuffer(info);
361 362
362 of_iounmap(&op->resource[0], all->par.regs, sizeof(struct bw2_regs)); 363 of_iounmap(&op->resource[0], par->regs, sizeof(struct bw2_regs));
363 of_iounmap(&op->resource[0], all->info.screen_base, all->par.fbsize); 364 of_iounmap(&op->resource[0], info->screen_base, par->fbsize);
364 365
365 kfree(all); 366 framebuffer_release(info);
366 367
367 dev_set_drvdata(&op->dev, NULL); 368 dev_set_drvdata(&op->dev, NULL);
368 369