patch-2.3.43 linux/drivers/scsi/scsi.c

Next file: linux/drivers/scsi/scsi.h
Previous file: linux/drivers/scsi/qlogicisp.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
@@ -147,7 +147,7 @@
 
 
 /*
- * Function:    scsi_get_request_handler()
+ * Function:    scsi_initialize_queue()
  *
  * Purpose:     Selects queue handler function for a device.
  *
@@ -165,20 +165,17 @@
  *              For this case, we have a special handler function, which
  *              does some checks and ultimately calls scsi_request_fn.
  *
- *              As a future enhancement, it might be worthwhile to add support
- *              for stacked handlers - there might get to be too many permutations
- *              otherwise.  Then again, we might just have one handler that does
- *              all of the special cases (a little bit slower), and those devices
- *              that don't need the special case code would directly call 
- *              scsi_request_fn.
- *
- *              As it stands, I can think of a number of special cases that
- *              we might need to handle.  This would not only include the blocked
- *              case, but single_lun (for changers), and any special handling
- *              we might need for a spun-down disk to spin it back up again.
+ *              The single_lun feature is a similar special case.
+ *
+ *              We handle these things by stacking the handlers.  The
+ *              special case handlers simply check a few conditions,
+ *              and return if they are not supposed to do anything.
+ *              In the event that things are OK, then they call the next
+ *              handler in the list - ultimately they call scsi_request_fn
+ *              to do the dirty deed.
  */
-request_fn_proc * scsi_get_request_handler(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt) {
-        return scsi_request_fn;
+void  scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt) {
+	blk_init_queue(&SDpnt->request_queue, scsi_request_fn);
 }
 
 #ifdef MODULE
@@ -530,7 +527,7 @@
 #endif
 	struct Scsi_Host *host;
 	int rtn = 0;
-	unsigned long flags;
+	unsigned long flags = 0;
 	unsigned long timeout;
 
 	ASSERT_LOCK(&io_request_lock, 0);
@@ -1075,45 +1072,46 @@
 
 int scsi_loadable_module_flag;	/* Set after we scan builtin drivers */
 
-void *scsi_init_malloc(unsigned int size, int gfp_mask)
-{
-	void *retval;
-
-	/*
-	 * For buffers used by the DMA pool, we assume page aligned 
-	 * structures.
-	 */
-	if ((size % PAGE_SIZE) == 0) {
-		int order, a_size;
-		for (order = 0, a_size = PAGE_SIZE;
-		     a_size < size; order++, a_size <<= 1);
-		retval = (void *) __get_free_pages(gfp_mask | GFP_DMA, order);
-	} else
-		retval = kmalloc(size, gfp_mask);
-
-	if (retval)
-		memset(retval, 0, size);
-	return retval;
-}
-
-
-void scsi_init_free(char *ptr, unsigned int size)
+/*
+ * Function:    scsi_release_commandblocks()
+ *
+ * Purpose:     Release command blocks associated with a device.
+ *
+ * Arguments:   SDpnt   - device
+ *
+ * Returns:     Nothing
+ *
+ * Lock status: No locking assumed or required.
+ *
+ * Notes:
+ */
+void scsi_release_commandblocks(Scsi_Device * SDpnt)
 {
-	/*
-	 * We need this special code here because the DMA pool assumes
-	 * page aligned data.  Besides, it is wasteful to allocate
-	 * page sized chunks with kmalloc.
-	 */
-	if ((size % PAGE_SIZE) == 0) {
-		int order, a_size;
+	Scsi_Cmnd *SCpnt;
+	unsigned long flags;
 
-		for (order = 0, a_size = PAGE_SIZE;
-		     a_size < size; order++, a_size <<= 1);
-		free_pages((unsigned long) ptr, order);
-	} else
-		kfree(ptr);
+	spin_lock_irqsave(&device_request_lock, flags);
+	for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
+		SDpnt->device_queue = SCpnt->next;
+		kfree((char *) SCpnt);
+	}
+	SDpnt->has_cmdblocks = 0;
+	spin_unlock_irqrestore(&device_request_lock, flags);
 }
 
+/*
+ * Function:    scsi_build_commandblocks()
+ *
+ * Purpose:     Allocate command blocks associated with a device.
+ *
+ * Arguments:   SDpnt   - device
+ *
+ * Returns:     Nothing
+ *
+ * Lock status: No locking assumed or required.
+ *
+ * Notes:
+ */
 void scsi_build_commandblocks(Scsi_Device * SDpnt)
 {
 	unsigned long flags;
@@ -1129,9 +1127,10 @@
 
 	for (j = 0; j < SDpnt->queue_depth; j++) {
 		SCpnt = (Scsi_Cmnd *)
-		    scsi_init_malloc(sizeof(Scsi_Cmnd),
+		    kmalloc(sizeof(Scsi_Cmnd),
 				     GFP_ATOMIC |
 				(host->unchecked_isa_dma ? GFP_DMA : 0));
+		memset(SCpnt, 0, sizeof(Scsi_Cmnd));
 		if (NULL == SCpnt)
 			break;	/* If not, the next line will oops ... */
 		memset(&SCpnt->eh_timeout, 0, sizeof(SCpnt->eh_timeout));
@@ -1323,7 +1322,6 @@
 static int proc_scsi_gen_write(struct file * file, const char * buf,
                               unsigned long length, void *data)
 {
-	Scsi_Cmnd *SCpnt;
 	struct Scsi_Device_Template *SDTpnt;
 	Scsi_Device *scd;
 	struct Scsi_Host *HBA_ptr;
@@ -1537,10 +1535,8 @@
 			 * Nobody is using this device any more.
 			 * Free all of the command structures.
 			 */
-			for (SCpnt = scd->device_queue; SCpnt; SCpnt = SCpnt->next) {
-				scd->device_queue = SCpnt->next;
-				scsi_init_free((char *) SCpnt, sizeof(*SCpnt));
-			}
+			scsi_release_commandblocks(scd);
+
 			/* Now we can remove the device structure */
 			if (scd->next != NULL)
 				scd->next->prev = scd->prev;
@@ -1552,7 +1548,7 @@
 				HBA_ptr->host_queue = scd->next;
 			}
 			blk_cleanup_queue(&scd->request_queue);
-			scsi_init_free((char *) scd, sizeof(Scsi_Device));
+			kfree((char *) scd);
 		} else {
 			goto out;
 		}
@@ -1865,17 +1861,12 @@
 		}
 		for (SDpnt = shpnt->host_queue; SDpnt;
 		     SDpnt = shpnt->host_queue) {
-			while (SDpnt->device_queue) {
-				SCpnt = SDpnt->device_queue->next;
-				scsi_init_free((char *) SDpnt->device_queue, sizeof(Scsi_Cmnd));
-				SDpnt->device_queue = SCpnt;
-			}
-			SDpnt->has_cmdblocks = 0;
+			scsi_release_commandblocks(SDpnt);
 
 			blk_cleanup_queue(&SDpnt->request_queue);
 			/* Next free up the Scsi_Device structures for this host */
 			shpnt->host_queue = SDpnt->next;
-			scsi_init_free((char *) SDpnt, sizeof(Scsi_Device));
+			kfree((char *) SDpnt);
 
 		}
 	}
@@ -2023,7 +2014,6 @@
 static int scsi_unregister_device(struct Scsi_Device_Template *tpnt)
 {
 	Scsi_Device *SDpnt;
-	Scsi_Cmnd *SCpnt;
 	struct Scsi_Host *shpnt;
 	struct Scsi_Device_Template *spnt;
 	struct Scsi_Device_Template *prev_spnt;
@@ -2050,13 +2040,7 @@
 				 * Nobody is using this device any more.  Free all of the
 				 * command structures.
 				 */
-				for (SCpnt = SDpnt->device_queue; SCpnt;
-				     SCpnt = SCpnt->next) {
-					if (SCpnt == SDpnt->device_queue)
-						SDpnt->device_queue = SCpnt->next;
-					scsi_init_free((char *) SCpnt, sizeof(*SCpnt));
-				}
-				SDpnt->has_cmdblocks = 0;
+				scsi_release_commandblocks(SDpnt);
 			}
 		}
 	}
@@ -2309,7 +2293,7 @@
 Scsi_Device * scsi_get_host_dev(struct Scsi_Host * SHpnt)
 {
         Scsi_Device * SDpnt;
-        Scsi_Cmnd   * SCpnt;
+
         /*
          * Attach a single Scsi_Device to the Scsi_Host - this should
          * be made to look like a "pseudo-device" that points to the
@@ -2330,18 +2314,9 @@
         SDpnt->type = -1;
         SDpnt->queue_depth = 1;
         
-        SCpnt = kmalloc(sizeof(Scsi_Cmnd), GFP_ATOMIC);
-        memset(SCpnt, 0, sizeof(Scsi_Cmnd));
-        SCpnt->host = SHpnt;
-        SCpnt->device = SDpnt;
-        SCpnt->target = SDpnt->id;
-        SCpnt->state = SCSI_STATE_UNUSED;
-        SCpnt->owner = SCSI_OWNER_NOBODY;
-        SCpnt->request.rq_status = RQ_INACTIVE;
-
-        SDpnt->device_queue = SCpnt;
+	scsi_build_commandblocks(SDpnt);
 
-        blk_init_queue(&SDpnt->request_queue, scsi_get_request_handler(SDpnt, SDpnt->host));
+	scsi_initialize_queue(SDpnt, SHpnt);
         blk_queue_headactive(&SDpnt->request_queue, 0);
         SDpnt->request_queue.queuedata = (void *) SDpnt;
 
@@ -2380,7 +2355,7 @@
          * We only have a single SCpnt attached to this device.  Free
          * it now.
          */
-        kfree(SDpnt->device_queue);
+	scsi_release_commandblocks(SDpnt);
         kfree(SDpnt);
 }
 

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