patch

Roman Kagan rkagan at mail.ru
Fri Jan 28 05:00:32 EST 2005


Damn, I believe you've appreciated my search&replace abilities:

On Fri, Jan 28, 2005 at 12:04:46PM +0300, Roman Kagan wrote:
> +	up(&usbatm_driver_list_sem);
> +	list_del(&driver->driver_list);
> +	down(&usbatm_driver_list_sem);

Corrected one below.

Roman.


Index: usbatm.h
===================================================================
RCS file: /home/cvs/usbatm/usbatm.h,v
retrieving revision 1.3
diff -u -r1.3 usbatm.h
--- usbatm.h	25 Jan 2005 08:18:09 -0000	1.3
+++ usbatm.h	28 Jan 2005 09:59:24 -0000
@@ -26,6 +26,7 @@
 
 #include <linux/config.h>
 #include <linux/list.h>
+#include <linux/completion.h>
 #include <linux/kref.h>
 #include <linux/atm.h>
 #include <linux/atmdev.h>
@@ -91,6 +92,7 @@
 
 	/* private */
 	struct usb_driver usb;
+	struct list_head driver_list;
 };
 
 int usbatm_register (struct usbatm_driver *driver);
@@ -157,7 +159,7 @@
 	void *driver_data;
 
 	/* heavy thread part */
-	struct task_struct *kthread;
+	struct completion heavy_init_completion;
 
 	/* USB device part */
 	struct usb_device *usb_dev;
Index: usbatm2.c
===================================================================
RCS file: /home/cvs/usbatm/usbatm2.c,v
retrieving revision 1.11
diff -u -r1.11 usbatm2.c
--- usbatm2.c	25 Jan 2005 08:18:09 -0000	1.11
+++ usbatm2.c	28 Jan 2005 09:59:25 -0000
@@ -1020,36 +1020,39 @@
 	struct usbatm_data *instance = arg;
 	int ret;
 
+	daemonize("%s/%s", usbatm_driver_name, instance->driver->driver_name);
+
 	ret = instance->driver->heavy_init(instance, instance->usb_intf);
 
 	if (!ret)
 		ret = usbatm_atm_init(instance);
 
+	complete(&instance->heavy_init_completion);
+
 	return ret;
 }
 
-static long usbatm_heavy_init(struct usbatm_data *instance)
+static int usbatm_heavy_init(struct usbatm_data *instance)
 {
-	struct task_struct *kthread;
+	int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_FS | CLONE_FILES);
 
-	kthread = kthread_create(usbatm_do_heavy_init, instance, "%s/%s", usbatm_driver_name, instance->driver->driver_name);
+	if (ret >= 0)
+		return 0;
 
-	if (IS_ERR(kthread)) {
-		dbg("usbatm_heavy_init: kernel_thread failed (%ld)!", PTR_ERR(kthread));
-		return PTR_ERR(kthread);
-	}
+	dbg("usbatm_heavy_init: kernel_thread failed (%d)!", ret);
 
-	instance->kthread = kthread;
-	mb();
-	wake_up_process(kthread);
+	complete(&instance->heavy_init_completion);
 
-	return 0;
+	return ret;
 }
 
+static DECLARE_MUTEX(usbatm_driver_list_sem);
+static LIST_HEAD(usbatm_driver_list);
+
 static int usbatm_usb_probe (struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
-	struct usbatm_driver *driver = (struct usbatm_driver *) id->driver_info;
+	struct usbatm_driver *driver;
 	struct usbatm_data *instance;
 	char *buf;
 	int error = -ENOMEM;
@@ -1059,6 +1062,13 @@
 
 	dev_dbg(&intf->dev, "trying device with vendor=0x%x, product=0x%x, ifnum %d\n", dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum);
 
+	/* USB core guarantees the right driver is on the list */
+	down(&usbatm_driver_list_sem);
+	list_for_each_entry(driver, &usbatm_driver_list, driver_list)
+		if (usb_match_id(intf, driver->id_table))
+			break;
+	up(&usbatm_driver_list_sem);
+
 	if (!driver) {
 		dev_dbg(&intf->dev, "blacklisted by %s\n", usbatm_driver_name);
 		return -ENODEV;
@@ -1074,6 +1084,8 @@
 
 	kref_init(&instance->refcount);	/* one for USB */
 
+	init_completion(&instance->heavy_init_completion);
+
 	init_MUTEX(&instance->serialize);
 
 	instance->driver = driver;
@@ -1190,8 +1202,11 @@
 
 	if (need_heavy && driver->heavy_init)
 		error = usbatm_heavy_init(instance);
-	else
+	else {
+		/* pretend that heavy_init was run */
+		complete(&instance->heavy_init_completion);
 		error = usbatm_atm_init(instance);
+	}
 
 	if (error)
 		goto fail;
@@ -1241,8 +1256,8 @@
 	if (instance->atm_dev && instance->driver->atm_stop)
 		instance->driver->atm_stop(instance, instance->atm_dev);
 
-	if (instance->kthread)
-		kthread_stop(instance->kthread);
+	/* hope heavy_init has already exited or will do so real soon */
+	wait_for_completion(&instance->heavy_init_completion);
 
 	if (instance->driver->unbind)
 		instance->driver->unbind(instance, intf);
@@ -1306,12 +1321,20 @@
         usb_driver->disconnect	= usbatm_disconnect;
         usb_driver->id_table	= driver->id_table;
 
+	down(&usbatm_driver_list_sem);
+	list_add(&driver->driver_list, &usbatm_driver_list);
+	up(&usbatm_driver_list_sem);
+
 	return usb_register(usb_driver);
 }
 EXPORT_SYMBOL_GPL(usbatm_register);
 
 void usbatm_deregister (struct usbatm_driver *driver)
 {
+	down(&usbatm_driver_list_sem);
+	list_del(&driver->driver_list);
+	up(&usbatm_driver_list_sem);
+
 	usb_deregister(&driver->usb);
 }
 EXPORT_SYMBOL_GPL(usbatm_deregister);
@@ -1337,6 +1360,11 @@
 }
 module_init(udsl_usb_init);
 
+static void __exit udsl_usb_exit(void)
+{
+}
+module_exit(udsl_usb_exit);
+
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");



More information about the Usbatm mailing list