patch-2.4.21 linux-2.4.21/drivers/usb/storage/scsiglue.c

Next file: linux-2.4.21/drivers/usb/storage/sddr09.c
Previous file: linux-2.4.21/drivers/usb/storage/jumpshot.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.20/drivers/usb/storage/scsiglue.c linux-2.4.21/drivers/usb/storage/scsiglue.c
@@ -75,15 +75,15 @@
 {
 	struct us_data *us;
 	char local_name[32];
-
+	/* Note: this function gets called with io_request_lock spinlock helt! */
 	/* This is not nice at all, but how else are we to get the
 	 * data here? */
 	us = (struct us_data *)sht->proc_dir;
 
 	/* set up the name of our subdirectory under /proc/scsi/ */
 	sprintf(local_name, "usb-storage-%d", us->host_number);
-	sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_KERNEL);
-	if (!sht->proc_name)
+	sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_ATOMIC);
+	if (!sht->proc_name) 
 		return 0;
 	strcpy(sht->proc_name, local_name);
 
@@ -145,12 +145,13 @@
 static int queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *))
 {
 	struct us_data *us = (struct us_data *)srb->host->hostdata[0];
+	unsigned long flags;
 
 	US_DEBUGP("queuecommand() called\n");
 	srb->host_scribble = (unsigned char *)us;
 
 	/* get exclusive access to the structures we want */
-	down(&(us->queue_exclusion));
+	spin_lock_irqsave(&(us->queue_exclusion), flags);
 
 	/* enqueue the command */
 	us->queue_srb = srb;
@@ -158,7 +159,7 @@
 	us->action = US_ACT_COMMAND;
 
 	/* release the lock on the structure */
-	up(&(us->queue_exclusion));
+	spin_unlock_irqrestore(&(us->queue_exclusion), flags);
 
 	/* wake up the process task */
 	up(&(us->sema));
@@ -191,11 +192,15 @@
 
 	/* if we have an urb pending, let's wake the control thread up */
 	if (!us->current_done.done) {
+		atomic_inc(&us->abortcnt);
+		spin_unlock_irq(&io_request_lock);
 		/* cancel the URB -- this will automatically wake the thread */
 		usb_unlink_urb(us->current_urb);
 
 		/* wait for us to be done */
 		wait_for_completion(&(us->notify));
+		spin_lock_irq(&io_request_lock);
+		atomic_dec(&us->abortcnt);
 		return SUCCESS;
 	}
 
@@ -231,6 +236,8 @@
 		return SUCCESS;
 	}
 
+	spin_unlock_irq(&io_request_lock);
+
 	/* release the IRQ, if we have one */
 	down(&(us->irq_urb_sem));
 	if (us->irq_urb) {
@@ -241,8 +248,10 @@
 	up(&(us->irq_urb_sem));
 
 	/* attempt to reset the port */
-	if (usb_reset_device(us->pusb_dev) < 0)
+	if (usb_reset_device(us->pusb_dev) < 0) {
+		spin_lock_irq(&io_request_lock);
 		return FAILED;
+	}
 
 	/* FIXME: This needs to lock out driver probing while it's working
 	 * or we can have race conditions */
@@ -282,6 +291,8 @@
 		US_DEBUGP("usb_submit_urb() returns %d\n", result);
 		up(&(us->irq_urb_sem));
 	}
+	
+	spin_lock_irq(&io_request_lock);
 
 	US_DEBUGP("bus_reset() complete\n");
 	return SUCCESS;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)