<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">ChangeSet 1.1254.1.7, 2003/05/29 15:25:37-07:00, hch@lst.de

[PATCH] fix scsi_register_host abuse in usb scanner drivers

They should be using scsi_add_host directly.  I had to rewrite
half of the drivers, though to fix horrible braindamage like
leaving dangling scsi structures around after -&gt;disconnect.

Gettig rid of the remaining scsi_register_host callers is required
for the scsi stack to move forward so please try to forward this
to Linus in a timely mannor, thanks!


 drivers/usb/image/hpusbscsi.c |  223 ++++++++++----------------------
 drivers/usb/image/hpusbscsi.h |   22 ---
 drivers/usb/image/microtek.c  |  291 ++++++------------------------------------
 drivers/usb/image/microtek.h  |    3 
 4 files changed, 118 insertions(+), 421 deletions(-)


diff -Nru a/drivers/usb/image/hpusbscsi.c b/drivers/usb/image/hpusbscsi.c
--- a/drivers/usb/image/hpusbscsi.c	Fri May 30 11:35:21 2003
+++ b/drivers/usb/image/hpusbscsi.c	Fri May 30 11:35:21 2003
@@ -22,65 +22,56 @@
 
 #define TRACE_STATE printk(KERN_DEBUG"hpusbscsi-&gt;state = %s at line %d\n", states[hpusbscsi-&gt;state], __LINE__)
 
-/* global variables */
-
-struct list_head hpusbscsi_devices;
-//LIST_HEAD(hpusbscsi_devices);
-
-/* USB related parts */
+static Scsi_Host_Template hpusbscsi_scsi_host_template = {
+	.module			= THIS_MODULE,
+	.name			= "hpusbscsi",
+	.proc_name		= "hpusbscsi",
+	.queuecommand		= hpusbscsi_scsi_queuecommand,
+	.eh_abort_handler	= hpusbscsi_scsi_abort,
+	.eh_host_reset_handler	= hpusbscsi_scsi_host_reset,
+	.sg_tablesize		= SG_ALL,
+	.can_queue		= 1,
+	.this_id		= -1,
+	.cmd_per_lun		= 1,
+	.use_clustering		= 1,
+	.emulated		= 1,
+};
 
 static int
-hpusbscsi_usb_probe (struct usb_interface *intf,
-		     const struct usb_device_id *id)
+hpusbscsi_usb_probe(struct usb_interface *intf,
+		    const struct usb_device_id *id)
 {
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct usb_host_interface *altsetting =	intf-&gt;altsetting;
 	struct hpusbscsi *new;
-	struct usb_device *dev = interface_to_usbdev (intf);
-	struct usb_host_interface *altsetting =
-		&amp;(intf-&gt;altsetting[0]);
-
+	int error = -ENOMEM;
 	int i, result;
 
-	/* basic check */
-
 	if (altsetting-&gt;desc.bNumEndpoints != 3) {
 		printk (KERN_ERR "Wrong number of endpoints\n");
 		return -ENODEV;
 	}
 
-	/* descriptor allocation */
-
-	new =
-		(struct hpusbscsi *) kmalloc (sizeof (struct hpusbscsi),
-					      GFP_KERNEL);
-	if (new == NULL)
+	new = kmalloc(sizeof(struct hpusbscsi), GFP_KERNEL);
+	if (!new)
 		return -ENOMEM;
-	DEBUG ("Allocated memory\n");
-	memset (new, 0, sizeof (struct hpusbscsi));
+	memset(new, 0, sizeof(struct hpusbscsi));
 	new-&gt;dataurb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!new-&gt;dataurb) {
-		kfree (new);
-		return -ENOMEM;
-	}
+	if (!new-&gt;dataurb)
+		goto out_kfree;
 	new-&gt;controlurb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!new-&gt;controlurb) {
-		usb_free_urb (new-&gt;dataurb);
-		kfree (new);
-		return -ENOMEM;
-	}
-	new-&gt;dev = dev;
-	init_waitqueue_head (&amp;new-&gt;pending);
-	init_waitqueue_head (&amp;new-&gt;deathrow);
-	INIT_LIST_HEAD (&amp;new-&gt;lh);
-
+	if (!new-&gt;controlurb)
+		goto out_free_dataurb;
 
+	new-&gt;dev = dev;
+	init_waitqueue_head(&amp;new-&gt;pending);
+	init_waitqueue_head(&amp;new-&gt;deathrow);
 
-	/* finding endpoints */
-
+	error = -ENODEV;
 	for (i = 0; i &lt; altsetting-&gt;desc.bNumEndpoints; i++) {
-		if (
-		    (altsetting-&gt;endpoint[i].desc.
+		if ((altsetting-&gt;endpoint[i].desc.
 		     bmAttributes &amp; USB_ENDPOINT_XFERTYPE_MASK) ==
-		    USB_ENDPOINT_XFER_BULK) {
+				USB_ENDPOINT_XFER_BULK) {
 			if (altsetting-&gt;endpoint[i].desc.
 			    bEndpointAddress &amp; USB_DIR_IN) {
 				new-&gt;ep_in =
@@ -97,57 +88,71 @@
 			new-&gt;ep_int =
 				altsetting-&gt;endpoint[i].desc.
 				bEndpointAddress &amp; USB_ENDPOINT_NUMBER_MASK;
-			new-&gt;interrupt_interval= altsetting-&gt;endpoint[i].desc.bInterval;
+			new-&gt;interrupt_interval= altsetting-&gt;endpoint[i].desc.
+				bInterval;
 		}
 	}
 
 	/* USB initialisation magic for the simple case */
-
-	result = usb_set_interface (dev, altsetting-&gt;desc.bInterfaceNumber, 0);
-
+	result = usb_set_interface(dev, altsetting-&gt;desc.bInterfaceNumber, 0);
 	switch (result) {
 	case 0:		/* no error */
 		break;
 	default:
-		printk (KERN_ERR "unknown error %d from usb_set_interface\n",
+		printk(KERN_ERR "unknown error %d from usb_set_interface\n",
 			 result);
-		goto err_out;
+		goto out_free_controlurb;
 	}
 
-	/* making a template for the scsi layer to fake detection of a scsi device */
+	/* build and submit an interrupt URB for status byte handling */
+ 	usb_fill_int_urb(new-&gt;controlurb, new-&gt;dev,
+			usb_rcvintpipe(new-&gt;dev, new-&gt;ep_int),
+			&amp;new-&gt;scsi_state_byte, 1,
+			control_interrupt_callback,new,
+			new-&gt;interrupt_interval);
+
+	if (usb_submit_urb(new-&gt;controlurb, GFP_KERNEL) &lt; 0)
+		goto out_free_controlurb;
 
-	memcpy (&amp;(new-&gt;ctempl), &amp;hpusbscsi_scsi_host_template,
-		sizeof (hpusbscsi_scsi_host_template));
-	(struct hpusbscsi *) new-&gt;ctempl.proc_dir = new;
-	new-&gt;ctempl.module = THIS_MODULE;
+	/* In host-&gt;hostdata we store a pointer to desc */
+	new-&gt;host = scsi_register(&amp;hpusbscsi_scsi_host_template, sizeof(new));
+	if (!new-&gt;host)
+		goto out_unlink_controlurb;
 
-	if (scsi_register_host(&amp;new-&gt;ctempl))
-		goto err_out;
+	new-&gt;host-&gt;hostdata[0] = (unsigned long)new;
+	scsi_add_host(new-&gt;host, &amp;intf-&gt;dev);
 
 	new-&gt;sense_command[0] = REQUEST_SENSE;
 	new-&gt;sense_command[4] = HPUSBSCSI_SENSE_LENGTH;
 
-	/* adding to list for module unload */
-	list_add (&amp;hpusbscsi_devices, &amp;new-&gt;lh);
-
 	usb_set_intfdata(intf, new);
 	return 0;
 
-      err_out:
-	usb_free_urb (new-&gt;controlurb);
-	usb_free_urb (new-&gt;dataurb);
-	kfree (new);
-	return -ENODEV;
+ out_unlink_controlurb:
+	usb_unlink_urb(new-&gt;controlurb);
+ out_free_controlurb:
+	usb_free_urb(new-&gt;controlurb);
+ out_free_dataurb:
+	usb_free_urb(new-&gt;dataurb);
+ out_kfree:
+	kfree(new);
+	return error;
 }
 
 static void
-hpusbscsi_usb_disconnect (struct usb_interface *intf)
+hpusbscsi_usb_disconnect(struct usb_interface *intf)
 {
 	struct hpusbscsi *desc = usb_get_intfdata(intf);
 
 	usb_set_intfdata(intf, NULL);
-	if (desc)
-		usb_unlink_urb(desc-&gt;controlurb);
+
+	scsi_remove_host(desc-&gt;host);
+	usb_unlink_urb(desc-&gt;controlurb);
+	scsi_unregister(desc-&gt;host);
+
+	usb_free_urb(desc-&gt;controlurb);
+	usb_free_urb(desc-&gt;dataurb);
+	kfree(desc);
 }
 
 static struct usb_device_id hpusbscsi_usb_ids[] = {
@@ -177,100 +182,20 @@
 
 /* module initialisation */
 
-int __init
+static int __init
 hpusbscsi_init (void)
 {
-	int result;
-
-	INIT_LIST_HEAD (&amp;hpusbscsi_devices);
-	DEBUG ("Driver loaded\n");
-
-	if ((result = usb_register (&amp;hpusbscsi_usb_driver)) &lt; 0) {
-		printk (KERN_ERR "hpusbscsi: driver registration failed\n");
-		return -1;
-	} else {
-		return 0;
-	}
+	return usb_register(&amp;hpusbscsi_usb_driver);
 }
 
-void __exit
+static void __exit
 hpusbscsi_exit (void)
 {
-	struct list_head *tmp;
-	struct list_head *old;
-	struct hpusbscsi * o;
-
-	for (tmp = hpusbscsi_devices.next; tmp != &amp;hpusbscsi_devices;/*nothing */) {
-		old = tmp;
-		tmp = tmp-&gt;next;
-		o = (struct hpusbscsi *)old;
-		usb_unlink_urb(o-&gt;controlurb);
-		scsi_unregister_host(&amp;o-&gt;ctempl);
-		usb_free_urb(o-&gt;controlurb);
-		usb_free_urb(o-&gt;dataurb);
-		kfree(old);
-	}
-
-	usb_deregister (&amp;hpusbscsi_usb_driver);
+	usb_deregister(&amp;hpusbscsi_usb_driver);
 }
 
 module_init (hpusbscsi_init);
 module_exit (hpusbscsi_exit);
-
-/* interface to the scsi layer */
-
-static int
-hpusbscsi_scsi_detect (struct SHT *sht)
-{
-	/* Whole function stolen from usb-storage */
-
-	struct hpusbscsi *desc = (struct hpusbscsi *) sht-&gt;proc_dir;
-	/* What a hideous hack! */
-
-	char local_name[48];
-
-
-	/* set up the name of our subdirectory under /proc/scsi/ */
-	sprintf (local_name, "hpusbscsi-%d", desc-&gt;number);
-	sht-&gt;proc_name = kmalloc (strlen (local_name) + 1, GFP_KERNEL);
-	/* FIXME: where is this freed ? */
-
-	if (!sht-&gt;proc_name) {
-		return 0;
-	}
-
-	strcpy (sht-&gt;proc_name, local_name);
-
-	sht-&gt;proc_dir = NULL;
-
-	/* build and submit an interrupt URB for status byte handling */
- 	usb_fill_int_urb(desc-&gt;controlurb,
-			desc-&gt;dev,
-			usb_rcvintpipe(desc-&gt;dev,desc-&gt;ep_int),
-			&amp;desc-&gt;scsi_state_byte,
-			1,
-			control_interrupt_callback,
-			desc,
-			desc-&gt;interrupt_interval
-	);
-
-	if ( 0  &gt;  usb_submit_urb(desc-&gt;controlurb, GFP_KERNEL)) {
-		kfree(sht-&gt;proc_name);
-		return 0;
-	}
-
-	/* In host-&gt;hostdata we store a pointer to desc */
-	desc-&gt;host = scsi_register (sht, sizeof (desc));
-	if (desc-&gt;host == NULL) {
-		kfree (sht-&gt;proc_name);
-		usb_unlink_urb(desc-&gt;controlurb);
-		return 0;
-	}
-	desc-&gt;host-&gt;hostdata[0] = (unsigned long) desc;
-
-
-	return 1;
-}
 
 static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback)
 {
diff -Nru a/drivers/usb/image/hpusbscsi.h b/drivers/usb/image/hpusbscsi.h
--- a/drivers/usb/image/hpusbscsi.h	Fri May 30 11:35:21 2003
+++ b/drivers/usb/image/hpusbscsi.h	Fri May 30 11:35:21 2003
@@ -13,7 +13,6 @@
 
 struct hpusbscsi
 {
-        struct list_head lh;
         struct usb_device *dev; /* NULL indicates unplugged device */
         int ep_out;
         int ep_in;
@@ -36,7 +35,6 @@
 
         int state;
         int current_data_pipe;
-	Scsi_Host_Template ctempl;
 	u8 sense_command[SENSE_COMMAND_SIZE];
         u8 scsi_state_byte;
 };
@@ -52,7 +50,6 @@
 
 #define DIRECTION_IS_IN(x) ((scsi_command_direction[x&gt;&gt;3] &gt;&gt; (x &amp; 7)) &amp; 1)
 
-static int hpusbscsi_scsi_detect (struct SHT * sht);
 static void simple_command_callback(struct urb *u, struct pt_regs *regs);
 static void scatter_gather_callback(struct urb *u, struct pt_regs *regs);
 static void simple_payload_callback (struct urb *u, struct pt_regs *regs);
@@ -63,25 +60,6 @@
 static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb);
 static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb);
 static void issue_request_sense (struct hpusbscsi *hpusbscsi);
-
-static Scsi_Host_Template hpusbscsi_scsi_host_template = {
-	.name			= "hpusbscsi",
-	.detect			= hpusbscsi_scsi_detect,
-//	.release		= hpusbscsi_scsi_release,
-	.queuecommand		= hpusbscsi_scsi_queuecommand,
-
-	.eh_abort_handler	= hpusbscsi_scsi_abort,
-	.eh_host_reset_handler	= hpusbscsi_scsi_host_reset,
-
-	.sg_tablesize		= SG_ALL,
-	.can_queue		= 1,
-	.this_id		= -1,
-	.cmd_per_lun		= 1,
-	.present		= 0,
-	.unchecked_isa_dma	= FALSE,
-	.use_clustering		= TRUE,
-	.emulated		= TRUE
-};
 
 /* defines for internal driver state */
 #define HP_STATE_FREE                 0  /*ready for next request */
diff -Nru a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
--- a/drivers/usb/image/microtek.c	Fri May 30 11:35:21 2003
+++ b/drivers/usb/image/microtek.c	Fri May 30 11:35:21 2003
@@ -326,76 +326,6 @@
 	usb_unlink_urb( desc-&gt;urb );
 }
 
-static struct mts_desc * mts_list; /* list of active scanners */
-struct semaphore mts_list_semaphore;
-
-/* Internal list operations */
-
-static
-void mts_remove_nolock( struct mts_desc* to_remove )
-{
-	MTS_DEBUG( "removing 0x%x from list\n",
-		   (int)to_remove );
-
-	lock_kernel();
-	mts_urb_abort(to_remove);
-
-	MTS_DEBUG_GOT_HERE();
-
-	if ( to_remove != mts_list ) {
-		MTS_DEBUG_GOT_HERE();
-		if (to_remove-&gt;prev &amp;&amp; to_remove-&gt;next)
-			to_remove-&gt;prev-&gt;next = to_remove-&gt;next;
-	} else {
-		MTS_DEBUG_GOT_HERE();
-		mts_list = to_remove-&gt;next;
-		if (mts_list) {
-			MTS_DEBUG_GOT_HERE();
-			mts_list-&gt;prev = 0;
-		}
-	}
-
-	if ( to_remove-&gt;next ) {
-		MTS_DEBUG_GOT_HERE();
-		to_remove-&gt;next-&gt;prev = to_remove-&gt;prev;
-	}
-
-	MTS_DEBUG_GOT_HERE();
-	scsi_unregister_host(&amp;to_remove-&gt;ctempl);
-	unlock_kernel();
-
-	usb_free_urb(to_remove-&gt;urb);
-	kfree( to_remove );
-}
-
-static
-void mts_add_nolock( struct mts_desc* to_add )
-{
-	MTS_DEBUG( "adding 0x%x to list\n", (int)to_add );
-
-	to_add-&gt;prev = 0;
-	to_add-&gt;next = mts_list;
-	if ( mts_list ) {
-		mts_list-&gt;prev = to_add;
-	}
-
-	mts_list = to_add;
-}
-
-
-
-
-/* SCSI driver interface */
-
-/* scsi related functions - dummies for now mostly */
-
-static int mts_scsi_release(struct Scsi_Host *psh)
-{
-	MTS_DEBUG_GOT_HERE();
-
-	return 0;
-}
-
 static int mts_scsi_abort (Scsi_Cmnd *srb)
 {
 	struct mts_desc* desc = (struct mts_desc*)(srb-&gt;device-&gt;host-&gt;hostdata[0]);
@@ -418,54 +348,6 @@
 	return 0;  /* RANT why here 0 and not SUCCESS */
 }
 
-/* the core of the scsi part */
-
-/* faking a detection - which can't fail :-) */
-
-static int mts_scsi_detect (struct SHT * sht)
-{
-	/* Whole function stolen from usb-storage */
-
-	struct mts_desc * desc = (struct mts_desc *)sht-&gt;proc_dir;
-	/* What a hideous hack! */
-
-	char local_name[48];
-
-	MTS_DEBUG_GOT_HERE();
-
-	/* set up the name of our subdirectory under /proc/scsi/ */
-	sprintf(local_name, "microtek-%d", desc-&gt;host_number);
-	sht-&gt;proc_name = kmalloc (strlen(local_name) + 1, GFP_KERNEL);
-	/* FIXME: where is this freed ? */
-
-	if (!sht-&gt;proc_name) {
-		MTS_ERROR( "unable to allocate memory for proc interface!!\n" );
-		return 0;
-	}
-
-	strcpy(sht-&gt;proc_name, local_name);
-
- 	sht-&gt;proc_dir = NULL;
-
-	/* In host-&gt;hostdata we store a pointer to desc */
-	desc-&gt;host = scsi_register(sht, sizeof(desc));
-	if (desc-&gt;host == NULL) {
-		MTS_ERROR("Cannot register due to low memory");
-		kfree(sht-&gt;proc_name);
-		return 0;
-	}
-	desc-&gt;host-&gt;hostdata[0] = (unsigned long)desc;
-/* FIXME: what if sizeof(void*) != sizeof(unsigned long)? */
-
-	return 1;
-}
-
-
-
-/* Main entrypoint: SCSI commands are dispatched to here */
-
-
-
 static
 int mts_scsi_queuecommand (Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback );
 
@@ -743,52 +625,22 @@
 out:
 	return err;
 }
-/*
- * this defines our 'host'
- */
-
-/* NOTE: This is taken from usb-storage, should be right. */
-
 
 static Scsi_Host_Template mts_scsi_host_template = {
-	.name =         "microtekX6",
-	.detect =	mts_scsi_detect,
-	.release =	mts_scsi_release,
-	.queuecommand =	mts_scsi_queuecommand,
-
-	.eh_abort_handler =	mts_scsi_abort,
-	.eh_host_reset_handler =mts_scsi_host_reset,
-
+	.module			= THIS_MODULE,
+	.name			= "microtekX6",
+	.proc_name		= "microtekX6",
+	.queuecommand		= mts_scsi_queuecommand,
+	.eh_abort_handler	= mts_scsi_abort,
+	.eh_host_reset_handler	= mts_scsi_host_reset,
 	.sg_tablesize =		SG_ALL,
 	.can_queue =		1,
 	.this_id =		-1,
 	.cmd_per_lun =		1,
-	.present =		0,
-	.unchecked_isa_dma =	FALSE,
-	.use_clustering =	TRUE,
-	.emulated =		TRUE
+	.use_clustering =	1,
+	.emulated =		1,
 };
 
-
-/* USB layer driver interface implementation */
-
-static void mts_usb_disconnect (struct usb_interface *intf)
-{
-	struct mts_desc* to_remove = usb_get_intfdata(intf);
-
-	MTS_DEBUG_GOT_HERE();
-
-	usb_set_intfdata(intf, NULL);
-	if (to_remove) {
-		/* leave the list - lock it */
-		down(&amp;mts_list_semaphore);
-
-		mts_remove_nolock(to_remove);
-
-		up(&amp;mts_list_semaphore);
-	}
-}
-
 struct vendor_product
 {
 	char* name;
@@ -836,8 +688,8 @@
 MODULE_DEVICE_TABLE (usb, mts_usb_ids);
 
 
-static int mts_usb_probe (struct usb_interface *intf,
-			  const struct usb_device_id *id)
+static int mts_usb_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
 {
 	int i;
 	int result;
@@ -929,39 +781,23 @@
 	}
 	
 	
-	/* allocating a new descriptor */
-	new_desc = (struct mts_desc *)kmalloc(sizeof(struct mts_desc), GFP_KERNEL);
-	if (new_desc == NULL)
-	{
-		MTS_ERROR("couldn't allocate scanner desc, bailing out!\n");
-		return -ENOMEM;
-	}
+	new_desc = kmalloc(sizeof(struct mts_desc), GFP_KERNEL);
+	if (!new_desc)
+		goto out;
 
-	memset( new_desc, 0, sizeof(*new_desc) );
+	memset(new_desc, 0, sizeof(*new_desc));
 	new_desc-&gt;urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!new_desc-&gt;urb) {
-		kfree(new_desc);
-		return -ENOMEM;
-	}
-		
-	/* initialising that descriptor */
-	new_desc-&gt;usb_dev = dev;
+	if (!new_desc-&gt;urb)
+		goto out_kfree;
 
+	new_desc-&gt;usb_dev = dev;
 	init_MUTEX(&amp;new_desc-&gt;lock);
 
-	if(mts_list){
-		new_desc-&gt;host_number = mts_list-&gt;host_number+1;
-	} else {
-		new_desc-&gt;host_number = 0;
-	}
-	
 	/* endpoints */
-	
 	new_desc-&gt;ep_out = ep_out;
 	new_desc-&gt;ep_response = ep_in_set[0];
 	new_desc-&gt;ep_image = ep_in_set[1];
 
-
 	if ( new_desc-&gt;ep_out != MTS_EP_OUT )
 		MTS_WARNING( "will this work? Command EP is not usually %d\n",
 			     (int)new_desc-&gt;ep_out );
@@ -974,87 +810,48 @@
 		MTS_WARNING( "will this work? Image data EP is not usually %d\n",
 			     (int)new_desc-&gt;ep_image );
 
+	new_desc-&gt;host = scsi_register(&amp;mts_scsi_host_template,
+			sizeof(new_desc));
+	if (!new_desc-&gt;host)
+		goto out_free_urb;
 
-	/* Initialize the host template based on the default one */
-	memcpy(&amp;(new_desc-&gt;ctempl), &amp;mts_scsi_host_template, sizeof(mts_scsi_host_template));
-	/* HACK from usb-storage - this is needed for scsi detection */
-	(struct mts_desc *)new_desc-&gt;ctempl.proc_dir = new_desc; /* FIXME */
-
-	MTS_DEBUG("registering SCSI module\n");
-
-	new_desc-&gt;ctempl.module = THIS_MODULE;
-	result = scsi_register_host(&amp;new_desc-&gt;ctempl);
-	/* Will get hit back in microtek_detect by this func */
-	if ( result )
-	{
-		MTS_ERROR( "error %d from scsi_register_host! Help!\n",
-			   (int)result );
-
-		/* FIXME: need more cleanup? */
-		kfree( new_desc );
-		return -ENOMEM;
-	}
-	MTS_DEBUG_GOT_HERE();
-
-	/* FIXME: the bomb is armed, must the host be registered under lock ? */
-	/* join the list - lock it */
-	down(&amp;mts_list_semaphore);
-
-	mts_add_nolock( new_desc );
-
-	up(&amp;mts_list_semaphore);
-
-
-	MTS_DEBUG("completed probe and exiting happily\n");
+	new_desc-&gt;host-&gt;hostdata[0] = (unsigned long)new_desc;
+	scsi_add_host(new_desc-&gt;host, NULL);
 
 	usb_set_intfdata(intf, new_desc);
 	return 0;
-}
-
 
+ out_free_urb:
+	usb_free_urb(new_desc-&gt;urb);
+ out_kfree:
+	kfree(new_desc);
+ out:
+	return -ENOMEM;
+}
 
-/* get us noticed by the rest of the kernel */
-
-int __init microtek_drv_init(void)
+static void mts_usb_disconnect (struct usb_interface *intf)
 {
-	int result;
+	struct mts_desc *desc = usb_get_intfdata(intf);
 
-	MTS_DEBUG_GOT_HERE();
-	init_MUTEX(&amp;mts_list_semaphore);
-
-	if ((result = usb_register(&amp;mts_usb_driver)) &lt; 0) {
-		MTS_DEBUG("usb_register returned %d\n", result );
-		return -1;
-	} else {
-		MTS_DEBUG("driver registered.\n");
-	}
+	usb_set_intfdata(intf, NULL);
 
-	info(DRIVER_VERSION ":" DRIVER_DESC);
+	scsi_remove_host(desc-&gt;host);
+	usb_unlink_urb(desc-&gt;urb);
+	scsi_unregister(desc-&gt;host);
 
-	return 0;
+	usb_free_urb(desc-&gt;urb);
+	kfree(desc);
 }
 
-void __exit microtek_drv_exit(void)
-{
-	struct mts_desc* next;
 
-	MTS_DEBUG_GOT_HERE();
+static int __init microtek_drv_init(void)
+{
+	return usb_register(&amp;mts_usb_driver);
+}
 
+static void __exit microtek_drv_exit(void)
+{
 	usb_deregister(&amp;mts_usb_driver);
-
-	down(&amp;mts_list_semaphore);
-
-	while (mts_list) {
-		/* keep track of where the next one is */
-		next = mts_list-&gt;next;
-
-		mts_remove_nolock( mts_list );
-
-		/* advance the list pointer */
-		mts_list = next;
-	}
-
-	up(&amp;mts_list_semaphore);
 }
 
 module_init(microtek_drv_init);
diff -Nru a/drivers/usb/image/microtek.h b/drivers/usb/image/microtek.h
--- a/drivers/usb/image/microtek.h	Fri May 30 11:35:21 2003
+++ b/drivers/usb/image/microtek.h	Fri May 30 11:35:21 2003
@@ -38,9 +38,6 @@
 	u8 ep_image;
 
 	struct Scsi_Host * host;
-	Scsi_Host_Template ctempl;
-	int host_number;
-
 	struct semaphore lock;
 
 	struct urb *urb;
</pre></body></html>