diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-25 12:02:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-25 12:02:13 -0400 |
commit | 1701f680407c6cc05121566cef5293d33881fe71 (patch) | |
tree | bf9e537a9a36ba066f6f1b25e6bde58c35516706 /drivers/char | |
parent | 3b3b3bd97788e1f574c71f865d8465b00a6b8708 (diff) |
Revert "ppdev: use new parport device model"
This reverts commit e7223f18603374d235d8bb0398532323e5f318b9.
It causes problems when a ppdev tries to register before the parport
driver has been registered with the device model. That will trigger the
BUG_ON(!drv->bus->p);
at drivers/base/driver.c:153. The call chain is
kernel_init ->
kernel_init_freeable ->
do_one_initcall ->
ppdev_init ->
__parport_register_driver ->
driver_register *BOOM*
Reported-by: kernel test robot <fengguang.wu@intel.com>
Reported-by: Ross Zwisler <zwisler@gmail.com>
Reported-by: Petr Mladek <pmladek@suse.com>
Cc: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/ppdev.c | 25 |
1 files changed, 5 insertions, 20 deletions
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index d23368874710..f8a483c67b07 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c | |||
@@ -286,7 +286,7 @@ static int register_device(int minor, struct pp_struct *pp) | |||
286 | struct parport *port; | 286 | struct parport *port; |
287 | struct pardevice *pdev = NULL; | 287 | struct pardevice *pdev = NULL; |
288 | char *name; | 288 | char *name; |
289 | struct pardev_cb ppdev_cb; | 289 | int fl; |
290 | 290 | ||
291 | name = kasprintf(GFP_KERNEL, CHRDEV "%x", minor); | 291 | name = kasprintf(GFP_KERNEL, CHRDEV "%x", minor); |
292 | if (name == NULL) | 292 | if (name == NULL) |
@@ -299,11 +299,9 @@ static int register_device(int minor, struct pp_struct *pp) | |||
299 | return -ENXIO; | 299 | return -ENXIO; |
300 | } | 300 | } |
301 | 301 | ||
302 | memset(&ppdev_cb, 0, sizeof(ppdev_cb)); | 302 | fl = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0; |
303 | ppdev_cb.irq_func = pp_irq; | 303 | pdev = parport_register_device(port, name, NULL, |
304 | ppdev_cb.flags = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0; | 304 | NULL, pp_irq, fl, pp); |
305 | ppdev_cb.private = pp; | ||
306 | pdev = parport_register_dev_model(port, name, &ppdev_cb, minor); | ||
307 | parport_put_port(port); | 305 | parport_put_port(port); |
308 | 306 | ||
309 | if (!pdev) { | 307 | if (!pdev) { |
@@ -801,23 +799,10 @@ static void pp_detach(struct parport *port) | |||
801 | device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number)); | 799 | device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number)); |
802 | } | 800 | } |
803 | 801 | ||
804 | static int pp_probe(struct pardevice *par_dev) | ||
805 | { | ||
806 | struct device_driver *drv = par_dev->dev.driver; | ||
807 | int len = strlen(drv->name); | ||
808 | |||
809 | if (strncmp(par_dev->name, drv->name, len)) | ||
810 | return -ENODEV; | ||
811 | |||
812 | return 0; | ||
813 | } | ||
814 | |||
815 | static struct parport_driver pp_driver = { | 802 | static struct parport_driver pp_driver = { |
816 | .name = CHRDEV, | 803 | .name = CHRDEV, |
817 | .probe = pp_probe, | 804 | .attach = pp_attach, |
818 | .match_port = pp_attach, | ||
819 | .detach = pp_detach, | 805 | .detach = pp_detach, |
820 | .devmodel = true, | ||
821 | }; | 806 | }; |
822 | 807 | ||
823 | static int __init ppdev_init(void) | 808 | static int __init ppdev_init(void) |