speedtch usbatm.h,1.4,1.5 usbatm2.c,1.13,1.14

Roman Kagan rkagan at mail.ru
Mon Feb 7 04:21:21 EST 2005


> I'll be sending a complete async patch vs current CVS in a minute.

Here you are:

Index: usbatm.h
===================================================================
RCS file: /home/cvs/usbatm/usbatm.h,v
retrieving revision 1.8
diff -u -r1.8 usbatm.h
--- usbatm.h	1 Feb 2005 23:20:49 -0000	1.8
+++ usbatm.h	7 Feb 2005 02:54:25 -0000
@@ -74,9 +74,12 @@
 	/* additional device initialization that is too slow to be done in probe() */
         int (*heavy_init) (struct usbatm_data *, struct usb_interface *);
 
-	/* cleanup device ... can sleep, but can't fail */
+	/* disconnect device ... can sleep, but can't fail */
         void (*unbind) (struct usbatm_data *, struct usb_interface *);
 
+	/* release the resources allocated to the device */
+	void (*cleanup) (struct usbatm_data *);
+
 	/* init ATM device ... can sleep, or cause ATM initialization failure */
 	int (*atm_start) (struct usbatm_data *, struct atm_dev *);
 
@@ -148,17 +151,13 @@
 
 struct usbatm_data {
 	struct kref refcount;
+	struct kref sub_refcount;
 	struct semaphore serialize;
 
 	/* mini driver part */
 	struct usbatm_driver *driver;
 	void *driver_data;
 
-	/* heavy init part */
-	int thread_pid;
-	struct completion thread_started;
-	struct completion thread_exited;
-
 	/* USB device part */
 	struct usb_device *usb_dev;
 	struct usb_interface *usb_intf;
Index: usbatm.c
===================================================================
RCS file: /home/cvs/usbatm/usbatm.c,v
retrieving revision 1.4
diff -u -r1.4 usbatm.c
--- usbatm.c	1 Feb 2005 23:20:49 -0000	1.4
+++ usbatm.c	7 Feb 2005 02:54:25 -0000
@@ -763,6 +763,23 @@
 	kref_put(&instance->refcount, usbatm_destroy_instance);
 }
 
+static void usbatm_destroy_sub_instance(struct kref *kref)
+{
+	struct usbatm_data *instance = container_of(kref, struct usbatm_data, sub_refcount);
+
+	if (instance->driver->cleanup)
+		instance->driver->cleanup(instance);
+}
+
+void usbatm_get_sub_instance(struct usbatm_data *instance)
+{
+	kref_get(&instance->sub_refcount);
+}
+
+void usbatm_put_sub_instance(struct usbatm_data *instance)
+{
+	kref_put(&instance->sub_refcount, usbatm_destroy_sub_instance);
+}
 
 /**********
 **  ATM  **
@@ -994,38 +1011,39 @@
 	int ret;
 
 	daemonize("%s/%s", usbatm_driver_name, instance->driver->driver_name);
-	allow_signal(SIGTERM);
-
-	complete(&instance->thread_started);
 
 	ret = instance->driver->heavy_init(instance, instance->usb_intf);
 
 	if (!ret)
 		ret = usbatm_atm_init(instance);
 
-	down(&instance->serialize);
-	instance->thread_pid = -1;
-	up(&instance->serialize);
+	usbatm_put_sub_instance(instance);
+	module_put(instance->driver->owner);
+	usbatm_put_instance(instance);
 
-	complete_and_exit(&instance->thread_exited, ret);
+	return ret;
 }
 
 static int usbatm_heavy_init(struct usbatm_data *instance)
 {
-	int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_KERNEL);
-
-	if (ret < 0) {
-		dbg("usbatm_heavy_init: failed to create kernel_thread (%d)!", ret);
-		return ret;
-	}
-
-	down(&instance->serialize);
-	instance->thread_pid = ret;
-	up(&instance->serialize);
+	int ret;
 
-	wait_for_completion(&instance->thread_started);
+	usbatm_get_instance(instance);
+	try_module_get(instance->driver->owner);
+	usbatm_get_sub_instance(instance);
+	
+	ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_KERNEL);
+
+	if (ret >= 0)
+		return 0;	/* OK */
+
+	dbg("usbatm_heavy_init: failed to create kernel_thread (%d)!", ret);
+
+	usbatm_put_sub_instance(instance);
+	module_put(instance->driver->owner);
+	usbatm_put_instance(instance);
 
-	return 0;
+	return ret;
 }
 
 int usbatm_usb_probe (struct usb_interface *intf, const struct usb_device_id *id,
@@ -1035,11 +1053,12 @@
 	struct usbatm_data *instance;
 	char *buf;
 	int error = -ENOMEM;
-	int ifnum = intf->altsetting->desc.bInterfaceNumber;
 	int i, length;
 	int need_heavy;
 
-	dev_dbg(&intf->dev, "trying device with vendor=0x%x, product=0x%x, ifnum %d\n", dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum);
+	dev_dbg(&intf->dev, "trying device with vendor=0x%x, product=0x%x, ifnum %d\n",
+			dev->descriptor.idVendor, dev->descriptor.idProduct,
+			intf->altsetting->desc.bInterfaceNumber);
 
 	/* instance init */
 	if (!(instance = kmalloc(sizeof(*instance), GFP_KERNEL))) {
@@ -1049,16 +1068,12 @@
 
 	memset(instance, 0, sizeof(*instance));
 
-	kref_init(&instance->refcount);	/* one for USB */
+	kref_init(&instance->refcount);	/* dropped in usbatm_usb_disconnect */
 
 	init_MUTEX(&instance->serialize);
 
 	instance->driver = driver;
 
-	instance->thread_pid = -1;
-	init_completion(&instance->thread_started);
-	init_completion(&instance->thread_exited);
-
 	instance->usb_dev = dev;
 	instance->usb_intf = intf;
 	instance->tx_endpoint = usb_sndbulkpipe(dev, driver->out);
@@ -1164,20 +1179,24 @@
  bind:
 	need_heavy = 1;
 	if (driver->bind && (error = driver->bind(instance, intf, &need_heavy)) < 0)
-			goto fail;
+		goto fail;
+
+	kref_init(&instance->sub_refcount);	/* dropped in usbatm_usb_disconnect after ->unbind */
 
 	if (need_heavy && driver->heavy_init)
 		error = usbatm_heavy_init(instance);
-	else {
-		complete(&instance->thread_exited);	/* pretend that heavy_init was run */
+	else
 		error = usbatm_atm_init(instance);
-	}
 
-	if (error)
+	if (error) {
+		if (instance->driver->unbind)
+			instance->driver->unbind(instance, intf);
+
+		usbatm_put_sub_instance(instance);
 		goto fail;
+	}
 
 	usb_get_dev(dev);
-	usbatm_get_instance(instance);	/* dropped in usbatm_usb_disconnect */
 	usb_set_intfdata(intf, instance);
 
 	return 0;
@@ -1215,19 +1234,14 @@
 
 	usb_set_intfdata(intf, NULL);
 
-	down(&instance->serialize);
-	if (instance->thread_pid >= 0)
-		kill_proc(instance->thread_pid, SIGTERM, 1);
-	up(&instance->serialize);
-
-	wait_for_completion(&instance->thread_exited);
-
 	if (instance->atm_dev && instance->driver->atm_stop)
 		instance->driver->atm_stop(instance, instance->atm_dev);
 
 	if (instance->driver->unbind)
 		instance->driver->unbind(instance, intf);
 
+	usbatm_put_sub_instance(instance);
+
 	/* receive finalize */
 	tasklet_disable(&instance->receive_tasklet);
 
Index: cxacru.c
===================================================================
RCS file: /home/cvs/usbatm/cxacru.c,v
retrieving revision 1.8
diff -u -r1.8 cxacru.c
--- cxacru.c	1 Feb 2005 23:20:49 -0000	1.8
+++ cxacru.c	7 Feb 2005 02:54:25 -0000
@@ -763,6 +763,18 @@
 	del_timer_sync(&instance->poll_timer);
 	wmb();
 	flush_scheduled_work();
+}
+
+static void cxacru_cleanup(struct usbatm_data *usbatm_instance)
+{
+	struct cxacru_data *instance = usbatm_instance->driver_data;
+
+	dbg("cxacru_cleanup entered");
+
+	if (!instance) {
+		dbg("cxacru_cleanup: NULL instance!");
+		return;
+	}
 
 	usb_kill_urb(instance->snd_urb);
 	usb_kill_urb(instance->rcv_urb);
@@ -828,6 +840,7 @@
 	.bind		= cxacru_bind,
 	.heavy_init	= cxacru_heavy_init,
 	.unbind		= cxacru_unbind,
+	.cleanup	= cxacru_cleanup,
 	.atm_start	= cxacru_atm_start,
 	.in		= CXACRU_EP_DATA,
 	.out		= CXACRU_EP_DATA,
@@ -853,13 +866,13 @@
 	return usb_register(&cxacru_usb_driver);
 }
 
-static void __exit cxacru_cleanup(void)
+static void __exit cxacru_exit(void)
 {
 	usb_deregister(&cxacru_usb_driver);
 }
 
 module_init(cxacru_init);
-module_exit(cxacru_cleanup);
+module_exit(cxacru_exit);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);



More information about the Usbatm mailing list