소스 검색

staging: dgnc: cleanup properly

dgnc_cleanup_module() was called when the module unloaded to do a total
cleanup and it was also called if pci_register_driver() fails. But
dgnc_cleanup_module() will try dgnc_remove_driver_sysfiles() but the
sysfiles will be created only if pci_register_driver() succeeds.
So if pci_register_driver() fails and we try dgnc_cleanup_module() then we
were getting:

[  942.001479] BUG: unable to handle kernel NULL pointer dereference at 00000018
[  942.001482] IP: [<c122c7a8>] sysfs_remove_file_ns+0x8/0x20

with part of the call trace as:

[  942.001544] Call Trace:
[  942.001555]  [<c149acc6>] driver_remove_file+0x16/0x20
[  942.001571]  [<f864a708>] dgnc_remove_driver_sysfiles+0x18/0x40 [dgnc]
[  942.001575]  [<f8643ac7>] dgnc_cleanup_module+0x47/0x260 [dgnc]
[  942.001577]  [<f86cb000>] ? 0xf86cb000
[  942.001580]  [<f86cb1e6>] dgnc_init_module+0x1e6/0x1000 [dgnc]

Lets have a separate cleanup function which will execute
dgnc_remove_driver_sysfiles() depending on the argument passed to it.

Reported-by: Navy Cheng <navych@126.com>
Signed-off-by: Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Sudip Mukherjee 9 년 전
부모
커밋
18f038e6bf
1개의 변경된 파일13개의 추가작업 그리고 8개의 파일을 삭제
  1. 13 8
      drivers/staging/dgnc/dgnc_driver.c

+ 13 - 8
drivers/staging/dgnc/dgnc_driver.c

@@ -125,12 +125,7 @@ static struct pci_driver dgnc_driver = {
  *
  *
  ************************************************************************/
  ************************************************************************/
 
 
-/*
- * dgnc_cleanup_module()
- *
- * Module unload.  This is where it all ends.
- */
-static void dgnc_cleanup_module(void)
+static void cleanup(bool sysfiles)
 {
 {
 	int i;
 	int i;
 	unsigned long flags;
 	unsigned long flags;
@@ -142,7 +137,8 @@ static void dgnc_cleanup_module(void)
 	/* Turn off poller right away. */
 	/* Turn off poller right away. */
 	del_timer_sync(&dgnc_poll_timer);
 	del_timer_sync(&dgnc_poll_timer);
 
 
-	dgnc_remove_driver_sysfiles(&dgnc_driver);
+	if (sysfiles)
+		dgnc_remove_driver_sysfiles(&dgnc_driver);
 
 
 	device_destroy(dgnc_class, MKDEV(dgnc_Major, 0));
 	device_destroy(dgnc_class, MKDEV(dgnc_Major, 0));
 	class_destroy(dgnc_class);
 	class_destroy(dgnc_class);
@@ -155,7 +151,16 @@ static void dgnc_cleanup_module(void)
 	}
 	}
 
 
 	dgnc_tty_post_uninit();
 	dgnc_tty_post_uninit();
+}
 
 
+/*
+ * dgnc_cleanup_module()
+ *
+ * Module unload.  This is where it all ends.
+ */
+static void dgnc_cleanup_module(void)
+{
+	cleanup(true);
 	pci_unregister_driver(&dgnc_driver);
 	pci_unregister_driver(&dgnc_driver);
 }
 }
 
 
@@ -182,7 +187,7 @@ static int __init dgnc_init_module(void)
 	rc = pci_register_driver(&dgnc_driver);
 	rc = pci_register_driver(&dgnc_driver);
 	if (rc) {
 	if (rc) {
 		pr_warn("WARNING: dgnc driver load failed.  No Digi Neo or Classic boards found.\n");
 		pr_warn("WARNING: dgnc driver load failed.  No Digi Neo or Classic boards found.\n");
-		dgnc_cleanup_module();
+		cleanup(false);
 		return rc;
 		return rc;
 	}
 	}
 	dgnc_create_driver_sysfiles(&dgnc_driver);
 	dgnc_create_driver_sysfiles(&dgnc_driver);