aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-03-25 17:49:00 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-03-25 17:49:00 -0400
commita3ac7917b73070010c05b4485b8582a6c9cd69b6 (patch)
treeb53427da682c9004dce08e67d52a7984aaef5477
parent8c2ffd9174779014c3fe1f96d9dc3641d9175f00 (diff)
Revert "parport: daisy: use new parport device model"
This reverts commit 1aec4211204d9463d1fd209eb50453de16254599. Steven Rostedt reports that it causes a hang at bootup and bisected it to this commit. The troigger is apparently a module alias for "parport_lowlevel" that points to "parport_pc", which causes a hang with modprobe -q -- parport_lowlevel blocking forever with a backtrace like this: wait_for_completion_killable+0x1c/0x28 call_usermodehelper_exec+0xa7/0x108 __request_module+0x351/0x3d8 get_lowlevel_driver+0x28/0x41 [parport] __parport_register_driver+0x39/0x1f4 [parport] daisy_drv_init+0x31/0x4f [parport] parport_bus_init+0x5d/0x7b [parport] parport_default_proc_register+0x26/0x1000 [parport] do_one_initcall+0xc2/0x1e0 do_init_module+0x50/0x1d4 load_module+0x1c2e/0x21b3 sys_init_module+0xef/0x117 Supid says: "Due to the new device model daisy driver will now try to find the parallel ports while trying to register its driver so that it can bind with them. Now, since daisy driver is loaded while parport bus is initialising the list of parport is still empty and it tries to load the lowlevel driver, which has an alias set to parport_pc, now causes a deadlock" But I don't think the daisy driver should be loaded by the parport initialization in the first place, so let's revert the whole change. If the daisy driver can just initialize separately on its own (like a driver should), instead of hooking into the parport init sequence directly, this issue probably would go away. Reported-and-bisected-by: Steven Rostedt (VMware) <rostedt@goodmis.org> Reported-by: Michal Kubecek <mkubecek@suse.cz> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/parport/daisy.c32
-rw-r--r--drivers/parport/probe.c2
-rw-r--r--drivers/parport/share.c10
-rw-r--r--include/linux/parport.h13
4 files changed, 3 insertions, 54 deletions
diff --git a/drivers/parport/daisy.c b/drivers/parport/daisy.c
index 56dd83a45e55..5484a46dafda 100644
--- a/drivers/parport/daisy.c
+++ b/drivers/parport/daisy.c
@@ -213,12 +213,10 @@ void parport_daisy_fini(struct parport *port)
213struct pardevice *parport_open(int devnum, const char *name) 213struct pardevice *parport_open(int devnum, const char *name)
214{ 214{
215 struct daisydev *p = topology; 215 struct daisydev *p = topology;
216 struct pardev_cb par_cb;
217 struct parport *port; 216 struct parport *port;
218 struct pardevice *dev; 217 struct pardevice *dev;
219 int daisy; 218 int daisy;
220 219
221 memset(&par_cb, 0, sizeof(par_cb));
222 spin_lock(&topology_lock); 220 spin_lock(&topology_lock);
223 while (p && p->devnum != devnum) 221 while (p && p->devnum != devnum)
224 p = p->next; 222 p = p->next;
@@ -232,7 +230,7 @@ struct pardevice *parport_open(int devnum, const char *name)
232 port = parport_get_port(p->port); 230 port = parport_get_port(p->port);
233 spin_unlock(&topology_lock); 231 spin_unlock(&topology_lock);
234 232
235 dev = parport_register_dev_model(port, name, &par_cb, devnum); 233 dev = parport_register_device(port, name, NULL, NULL, NULL, 0, NULL);
236 parport_put_port(port); 234 parport_put_port(port);
237 if (!dev) 235 if (!dev)
238 return NULL; 236 return NULL;
@@ -482,31 +480,3 @@ static int assign_addrs(struct parport *port)
482 kfree(deviceid); 480 kfree(deviceid);
483 return detected; 481 return detected;
484} 482}
485
486static int daisy_drv_probe(struct pardevice *par_dev)
487{
488 struct device_driver *drv = par_dev->dev.driver;
489
490 if (strcmp(drv->name, "daisy_drv"))
491 return -ENODEV;
492 if (strcmp(par_dev->name, daisy_dev_name))
493 return -ENODEV;
494
495 return 0;
496}
497
498static struct parport_driver daisy_driver = {
499 .name = "daisy_drv",
500 .probe = daisy_drv_probe,
501 .devmodel = true,
502};
503
504int daisy_drv_init(void)
505{
506 return parport_register_driver(&daisy_driver);
507}
508
509void daisy_drv_exit(void)
510{
511 parport_unregister_driver(&daisy_driver);
512}
diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c
index e5e6a463a941..e035174ba205 100644
--- a/drivers/parport/probe.c
+++ b/drivers/parport/probe.c
@@ -257,7 +257,7 @@ static ssize_t parport_read_device_id (struct parport *port, char *buffer,
257ssize_t parport_device_id (int devnum, char *buffer, size_t count) 257ssize_t parport_device_id (int devnum, char *buffer, size_t count)
258{ 258{
259 ssize_t retval = -ENXIO; 259 ssize_t retval = -ENXIO;
260 struct pardevice *dev = parport_open(devnum, daisy_dev_name); 260 struct pardevice *dev = parport_open (devnum, "Device ID probe");
261 if (!dev) 261 if (!dev)
262 return -ENXIO; 262 return -ENXIO;
263 263
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index 0171b8dbcdcd..5dc53d420ca8 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -137,19 +137,11 @@ static struct bus_type parport_bus_type = {
137 137
138int parport_bus_init(void) 138int parport_bus_init(void)
139{ 139{
140 int retval; 140 return bus_register(&parport_bus_type);
141
142 retval = bus_register(&parport_bus_type);
143 if (retval)
144 return retval;
145 daisy_drv_init();
146
147 return 0;
148} 141}
149 142
150void parport_bus_exit(void) 143void parport_bus_exit(void)
151{ 144{
152 daisy_drv_exit();
153 bus_unregister(&parport_bus_type); 145 bus_unregister(&parport_bus_type);
154} 146}
155 147
diff --git a/include/linux/parport.h b/include/linux/parport.h
index f41f1d041e2c..397607a0c0eb 100644
--- a/include/linux/parport.h
+++ b/include/linux/parport.h
@@ -460,7 +460,6 @@ extern size_t parport_ieee1284_epp_read_addr (struct parport *,
460 void *, size_t, int); 460 void *, size_t, int);
461 461
462/* IEEE1284.3 functions */ 462/* IEEE1284.3 functions */
463#define daisy_dev_name "Device ID probe"
464extern int parport_daisy_init (struct parport *port); 463extern int parport_daisy_init (struct parport *port);
465extern void parport_daisy_fini (struct parport *port); 464extern void parport_daisy_fini (struct parport *port);
466extern struct pardevice *parport_open (int devnum, const char *name); 465extern struct pardevice *parport_open (int devnum, const char *name);
@@ -469,18 +468,6 @@ extern ssize_t parport_device_id (int devnum, char *buffer, size_t len);
469extern void parport_daisy_deselect_all (struct parport *port); 468extern void parport_daisy_deselect_all (struct parport *port);
470extern int parport_daisy_select (struct parport *port, int daisy, int mode); 469extern int parport_daisy_select (struct parport *port, int daisy, int mode);
471 470
472#ifdef CONFIG_PARPORT_1284
473extern int daisy_drv_init(void);
474extern void daisy_drv_exit(void);
475#else
476static inline int daisy_drv_init(void)
477{
478 return 0;
479}
480
481static inline void daisy_drv_exit(void) {}
482#endif
483
484/* Lowlevel drivers _can_ call this support function to handle irqs. */ 471/* Lowlevel drivers _can_ call this support function to handle irqs. */
485static inline void parport_generic_irq(struct parport *port) 472static inline void parport_generic_irq(struct parport *port)
486{ 473{