All of lore.kernel.org
 help / color / mirror / Atom feed
From: Luben Tuikov <luben@splentec.com>
To: linux-scsi@vger.kernel.org
Subject: [PATCH] SCSI Core cmd allocation 3/3
Date: Mon, 06 Jan 2003 19:37:20 -0500	[thread overview]
Message-ID: <3E1A2140.3000408@splentec.com> (raw)

This patch introduces slab allocation of SCSI command structs
with (currently) one backup scsi command struct per host in
host->free_list.

New are:

struct scsi_cmnd * scsi_get_command(struct Scsi_Host *host, int alloc_flags);
void scsi_put_command(struct scsi_cmnd *cmd);
void scsi_setup_command(struct scsi_device *dev, struct scsi_cmnd *cmd);

static inline struct scsi_cmnd * scsi_getset_command(struct scsi_device *dev,
                                                     int flags);
For when the device is known (most of the cases).

Also:

int scsi_create_cmdcache(struct scsi_core_data *scsi_core);
int scsi_destroy_cmdcache(struct scsi_core_data *scsi_core);

struct scsi_core_data is a holder of all global SCSI Core data.

This is a joint work.

-- 
Luben

diff -Naur -X /usr/src/dontdiff linux-2.5.54-2/drivers/scsi/aic7xxx/aic79xx_osm.c linux-2.5.54-3/drivers/scsi/aic7xxx/aic79xx_osm.c
--- linux-2.5.54-2/drivers/scsi/aic7xxx/aic79xx_osm.c	2003-01-06 11:57:22.000000000 -0500
+++ linux-2.5.54-3/drivers/scsi/aic7xxx/aic79xx_osm.c	2003-01-06 17:16:13.000000000 -0500
@@ -971,7 +971,7 @@
  	struct	 ahd_linux_device *dev;
  	u_long	 flags;

-	ahd = *(struct ahd_softc **)cmd->host->hostdata;
+	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;

  	/*
  	 * Save the callback on completion function.
@@ -995,8 +995,8 @@
  		ahd_midlayer_entrypoint_unlock(ahd, &flags);
  		return (0);
  	}
-	dev = ahd_linux_get_device(ahd, cmd->channel, cmd->target,
-				   cmd->lun, /*alloc*/TRUE);
+	dev = ahd_linux_get_device(ahd, cmd->device->channel, cmd->device->id,
+				   cmd->device->lun, /*alloc*/TRUE);
  	if (dev == NULL) {
  		ahd_midlayer_entrypoint_unlock(ahd, &flags);
  		printf("aic79xx_linux_queue: Unable to allocate device!\n");
@@ -1217,7 +1217,7 @@
  	int    found;
  #endif

-	ahd = *(struct ahd_softc **)cmd->host->hostdata;
+	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
  #if NOTYET
  	int error;

@@ -1251,7 +1251,7 @@
  	int    found;
  #endif

-	ahd = *(struct ahd_softc **)cmd->host->hostdata;
+	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
  #ifdef AHD_DEBUG
  	if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
  		printf("%s: Dev reset called for cmd %p\n",
@@ -1283,14 +1283,14 @@
  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  	spin_unlock_irq(&io_request_lock);
  #endif
-	ahd = *(struct ahd_softc **)cmd->host->hostdata;
+	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
  #ifdef AHD_DEBUG
  	if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
  		printf("%s: Bus reset called for cmd %p\n",
  		       ahd_name(ahd), cmd);
  #endif
  	ahd_midlayer_entrypoint_lock(ahd, &s);
-	found = ahd_reset_channel(ahd, cmd->channel + 'A',
+	found = ahd_reset_channel(ahd, cmd->device->channel + 'A',
  				  /*initiate reset*/TRUE);
  	acmd = TAILQ_FIRST(&ahd->platform_data->completeq);
  	TAILQ_INIT(&ahd->platform_data->completeq);
@@ -1415,7 +1415,7 @@

  /******************************** Macros **************************************/
  #define BUILD_SCSIID(ahd, cmd)						\
-	((((cmd)->target << TID_SHIFT) & TID) | (ahd)->our_id)
+	((((cmd)->device->id << TID_SHIFT) & TID) | (ahd)->our_id)

  /******************************** Bus DMA *************************************/
  int
@@ -3668,7 +3668,7 @@
  	struct	scb *scb;
  	u_long	flags;

-	ahd = *((struct ahd_softc **)cmd->host->hostdata);
+	ahd = *((struct ahd_softc **)cmd->device->host->hostdata);
  	ahd_lock(ahd, &flags);

  #ifdef AHD_DEBUG
@@ -3696,7 +3696,7 @@
  		ahd_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
  	else
  		ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
-	ahd_reset_channel(ahd, cmd->channel + 'A', /*initiate*/TRUE);
+	ahd_reset_channel(ahd, cmd->device->channel + 'A', /*initiate*/TRUE);

  	/*
  	 * Add a minimal bus settle delay for devices that are slow to
@@ -3746,7 +3746,7 @@
  {
  	struct ahd_softc *ahd;

-	ahd = *((struct ahd_softc **)cmd->host->hostdata);
+	ahd = *((struct ahd_softc **)cmd->device->host->hostdata);

  	/* Delete the DV timer before it goes off! */
  	scsi_delete_timer(cmd);
@@ -3754,7 +3754,8 @@
  #ifdef AHD_DEBUG
  	if (ahd_debug & AHD_SHOW_DV)
  		printf("%s:%c:%d: Command completed, status= 0x%x\n",
-		       ahd_name(ahd), cmd->channel, cmd->target, cmd->result);
+		       ahd_name(ahd), cmd->device->channel,
+		       cmd->device->id, cmd->result);
  #endif

  	/* Wake up the state machine */
@@ -3948,12 +3949,13 @@
  		 * Get an scb to use.
  		 */
  		tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
-					    cmd->target, &tstate);
+					    cmd->device->id, &tstate);
  		if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) == 0
  		 || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
  			col_idx = AHD_NEVER_COL_IDX;
  		} else {
-			col_idx = AHD_BUILD_COL_IDX(cmd->target, cmd->lun);
+			col_idx = AHD_BUILD_COL_IDX(cmd->device->id,
+						    cmd->device->lun);
  		}
  		if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
  			TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq,
@@ -3973,7 +3975,7 @@
  		 */
  		hscb->control = 0;
  		hscb->scsiid = BUILD_SCSIID(ahd, cmd);
-		hscb->lun = cmd->lun;
+		hscb->lun = cmd->device->lun;
  		mask = SCB_GET_TARGET_MASK(ahd, scb);

  		if ((ahd->user_discenable & mask) != 0)
@@ -4641,8 +4643,9 @@
  			struct ahd_devinfo devinfo;
  			uint32_t action;

-			dev = ahd_linux_get_device(ahd, cmd->channel,
-						   cmd->target, cmd->lun,
+			dev = ahd_linux_get_device(ahd, cmd->device->channel,
+						   cmd->device->id,
+						   cmd->device->lun,
  						   /*alloc*/FALSE);

  			if (dev == NULL)
diff -Naur -X /usr/src/dontdiff linux-2.5.54-2/drivers/scsi/aic7xxx/aic7xxx_osm.c linux-2.5.54-3/drivers/scsi/aic7xxx/aic7xxx_osm.c
--- linux-2.5.54-2/drivers/scsi/aic7xxx/aic7xxx_osm.c	2003-01-06 11:57:22.000000000 -0500
+++ linux-2.5.54-3/drivers/scsi/aic7xxx/aic7xxx_osm.c	2003-01-06 17:27:20.000000000 -0500
@@ -975,7 +975,7 @@
  	struct	 ahc_linux_device *dev;
  	u_long	 flags;

-	ahc = *(struct ahc_softc **)cmd->host->hostdata;
+	ahc = *(struct ahc_softc **)cmd->device->host->hostdata;

  	/*
  	 * Save the callback on completion function.
@@ -999,8 +999,8 @@
  		ahc_midlayer_entrypoint_unlock(ahc, &flags);
  		return (0);
  	}
-	dev = ahc_linux_get_device(ahc, cmd->channel, cmd->target,
-				   cmd->lun, /*alloc*/TRUE);
+	dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id,
+				   cmd->device->lun, /*alloc*/TRUE);
  	if (dev == NULL) {
  		ahc_midlayer_entrypoint_unlock(ahc, &flags);
  		printf("aic7xxx_linux_queue: Unable to allocate device!\n");
@@ -1244,12 +1244,12 @@
  	u_long s;
  	int    found;

-	ahc = *(struct ahc_softc **)cmd->host->hostdata;
+	ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  	spin_unlock_irq(&io_request_lock);
  #endif
  	ahc_midlayer_entrypoint_lock(ahc, &s);
-	found = ahc_reset_channel(ahc, cmd->channel + 'A',
+	found = ahc_reset_channel(ahc, cmd->device->channel + 'A',
  				  /*initiate reset*/TRUE);
  	acmd = TAILQ_FIRST(&ahc->platform_data->completeq);
  	TAILQ_INIT(&ahc->platform_data->completeq);
@@ -1371,10 +1371,10 @@
  }

  /******************************** Macros **************************************/
-#define BUILD_SCSIID(ahc, cmd)						\
-	((((cmd)->target << TID_SHIFT) & TID)				\
-	| (((cmd)->channel == 0) ? (ahc)->our_id : (ahc)->our_id_b)	\
-	| (((cmd)->channel == 0) ? 0 : TWIN_CHNLB))
+#define BUILD_SCSIID(ahc, cmd)						   \
+	((((cmd)->device->id << TID_SHIFT) & TID)			   \
+	| (((cmd)->device->channel == 0) ? (ahc)->our_id : (ahc)->our_id_b)\
+	| (((cmd)->device->channel == 0) ? 0 : TWIN_CHNLB))

  /******************************** Bus DMA *************************************/
  int
@@ -3511,7 +3511,7 @@
  	struct	scb *scb;
  	u_long	flags;

-	ahc = *((struct ahc_softc **)cmd->host->hostdata);
+	ahc = *((struct ahc_softc **)cmd->device->host->hostdata);
  	ahc_lock(ahc, &flags);

  #ifdef AHC_DEBUG
@@ -3539,7 +3539,7 @@
  		ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
  	else
  		ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT);
-	ahc_reset_channel(ahc, cmd->channel + 'A', /*initiate*/TRUE);
+	ahc_reset_channel(ahc, cmd->device->channel + 'A', /*initiate*/TRUE);

  	/*
  	 * Add a minimal bus settle delay for devices that are slow to
@@ -3589,7 +3589,7 @@
  {
  	struct ahc_softc *ahc;

-	ahc = *((struct ahc_softc **)cmd->host->hostdata);
+	ahc = *((struct ahc_softc **)cmd->device->host->hostdata);

  	/* Delete the DV timer before it goes off! */
  	scsi_delete_timer(cmd);
@@ -3597,7 +3597,8 @@
  #ifdef AHC_DEBUG
  	if (ahc_debug & AHC_SHOW_DV)
  		printf("%s:%d:%d: Command completed, status= 0x%x\n",
-		       ahc_name(ahc), cmd->channel, cmd->target, cmd->result);
+		       ahc_name(ahc), cmd->device->channel, cmd->device->id,
+		       cmd->result);
  #endif

  	/* Wake up the state machine */
@@ -3813,7 +3814,7 @@
  		 */
  		hscb->control = 0;
  		hscb->scsiid = BUILD_SCSIID(ahc, cmd);
-		hscb->lun = cmd->lun;
+		hscb->lun = cmd->device->lun;
  		mask = SCB_GET_TARGET_MASK(ahc, scb);
  		tinfo = ahc_fetch_transinfo(ahc, SCB_GET_CHANNEL(ahc, scb),
  					    SCB_GET_OUR_ID(scb),
@@ -4838,11 +4839,12 @@
  	pending_scb = NULL;
  	paused = FALSE;
  	wait = FALSE;
-	ahc = *(struct ahc_softc **)cmd->host->hostdata;
+	ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
  	acmd = (struct ahc_cmd *)cmd;

  	printf("%s:%d:%d:%d: Attempting to queue a%s message\n",
-	       ahc_name(ahc), cmd->channel, cmd->target, cmd->lun,
+	       ahc_name(ahc), cmd->device->channel, cmd->device->id,
+	       cmd->device->lun,
  	       flag == SCB_ABORT ? "n ABORT" : " TARGET RESET");

  	/*
@@ -4871,8 +4873,8 @@
  	 * at all, and the system wanted us to just abort the
  	 * command return success.
  	 */
-	dev = ahc_linux_get_device(ahc, cmd->channel, cmd->target,
-				   cmd->lun, /*alloc*/FALSE);
+	dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id,
+				   cmd->device->lun, /*alloc*/FALSE);

  	if (dev == NULL) {
  		/*
@@ -4880,7 +4882,8 @@
  		 * so we must not still own the command.
  		 */
  		printf("%s:%d:%d:%d: Is not an active device\n",
-		       ahc_name(ahc), cmd->channel, cmd->target, cmd->lun);
+		       ahc_name(ahc), cmd->device->channel, cmd->device->id,
+		       cmd->device->lun);
  		retval = SUCCESS;
  		goto no_cmd;
  	}
@@ -4892,7 +4895,8 @@

  	if (list_acmd != NULL) {
  		printf("%s:%d:%d:%d: Command found on device queue\n",
-		       ahc_name(ahc), cmd->channel, cmd->target, cmd->lun);
+		       ahc_name(ahc), cmd->device->channel, cmd->device->id,
+		       cmd->device->lun);
  		if (flag == SCB_ABORT) {
  			TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe);
  			cmd->result = DID_ABORT << 16;
@@ -4903,11 +4907,13 @@
  	}

  	if ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED)) == 0
-	 && ahc_search_untagged_queues(ahc, cmd, cmd->target,
-				       cmd->channel + 'A', cmd->lun,
+	 && ahc_search_untagged_queues(ahc, cmd, cmd->device->id,
+				       cmd->device->channel + 'A',
+				       cmd->device->lun,
  				       CAM_REQ_ABORTED, SEARCH_COMPLETE) != 0) {
  		printf("%s:%d:%d:%d: Command found on untagged queue\n",
-		       ahc_name(ahc), cmd->channel, cmd->target, cmd->lun);
+		       ahc_name(ahc), cmd->device->channel, cmd->device->id,
+		       cmd->device->lun);
  		retval = SUCCESS;
  		goto done;
  	}
@@ -4924,8 +4930,9 @@

  		/* Any SCB for this device will do for a target reset */
  		LIST_FOREACH(pending_scb, &ahc->pending_scbs, pending_links) {
-		  	if (ahc_match_scb(ahc, pending_scb, cmd->target,
-					  cmd->channel + 'A', CAM_LUN_WILDCARD,
+		  	if (ahc_match_scb(ahc, pending_scb, cmd->device->id,
+					  cmd->device->channel + 'A',
+					  CAM_LUN_WILDCARD,
  					  SCB_LIST_NULL, ROLE_INITIATOR) == 0)
  				break;
  		}
@@ -4933,7 +4940,8 @@

  	if (pending_scb == NULL) {
  		printf("%s:%d:%d:%d: Command not found\n",
-		       ahc_name(ahc), cmd->channel, cmd->target, cmd->lun);
+		       ahc_name(ahc), cmd->device->channel, cmd->device->id,
+		       cmd->device->lun);
  		goto no_cmd;
  	}

@@ -4957,24 +4965,24 @@

  	if ((pending_scb->flags & SCB_ACTIVE) == 0) {
  		printf("%s:%d:%d:%d: Command already completed\n",
-		       ahc_name(ahc), cmd->channel, cmd->target, cmd->lun);
+		       ahc_name(ahc), cmd->device->channel, cmd->device->id, cmd->device->lun);
  		goto no_cmd;
  	}

  	disconnected = TRUE;
  	if (flag == SCB_ABORT) {
-		if (ahc_search_qinfifo(ahc, cmd->target, cmd->channel + 'A',
-				       cmd->lun, pending_scb->hscb->tag,
+		if (ahc_search_qinfifo(ahc, cmd->device->id, cmd->device->channel + 'A',
+				       cmd->device->lun, pending_scb->hscb->tag,
  				       ROLE_INITIATOR, CAM_REQ_ABORTED,
  				       SEARCH_COMPLETE) > 0) {
  			printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
-			       ahc_name(ahc), cmd->channel, cmd->target,
-					cmd->lun);
+			       ahc_name(ahc), cmd->device->channel, cmd->device->id,
+					cmd->device->lun);
  			retval = SUCCESS;
  			goto done;
  		}
-	} else if (ahc_search_qinfifo(ahc, cmd->target, cmd->channel + 'A',
-				      cmd->lun, pending_scb->hscb->tag,
+	} else if (ahc_search_qinfifo(ahc, cmd->device->id, cmd->device->channel + 'A',
+				      cmd->device->lun, pending_scb->hscb->tag,
  				      ROLE_INITIATOR, /*status*/0,
  				      SEARCH_COUNT) > 0) {
  		disconnected = FALSE;
@@ -5006,7 +5014,7 @@
  	if (last_phase != P_BUSFREE
  	 && (pending_scb->hscb->tag == active_scb_index
  	  || (flag == SCB_DEVICE_RESET
-	   && SCSIID_TARGET(ahc, ahc_inb(ahc, SAVED_SCSIID)) == cmd->target))) {
+	   && SCSIID_TARGET(ahc, ahc_inb(ahc, SAVED_SCSIID)) == cmd->device->id))) {

  		/*
  		 * We're active on the bus, so assert ATN
@@ -5017,7 +5025,7 @@
  		ahc_outb(ahc, MSG_OUT, HOST_MSG);
  		ahc_outb(ahc, SCSISIGO, last_phase|ATNO);
  		printf("%s:%d:%d:%d: Device is active, asserting ATN\n",
-		       ahc_name(ahc), cmd->channel, cmd->target, cmd->lun);
+		       ahc_name(ahc), cmd->device->channel, cmd->device->id, cmd->device->lun);
  		wait = TRUE;
  	} else if (disconnected) {

@@ -5047,8 +5055,8 @@
  		 * same element in the SCB, SCB_NEXT, for
  		 * both the qinfifo and the disconnected list.
  		 */
-		ahc_search_disc_list(ahc, cmd->target, cmd->channel + 'A',
-				     cmd->lun, pending_scb->hscb->tag,
+		ahc_search_disc_list(ahc, cmd->device->id, cmd->device->channel + 'A',
+				     cmd->device->lun, pending_scb->hscb->tag,
  				     /*stop_on_first*/TRUE,
  				     /*remove*/TRUE,
  				     /*save_state*/FALSE);
@@ -5071,19 +5079,19 @@
  		 * so we are the next SCB for this target
  		 * to run.
  		 */
-		ahc_search_qinfifo(ahc, cmd->target, cmd->channel + 'A',
-				   cmd->lun, SCB_LIST_NULL, ROLE_INITIATOR,
+		ahc_search_qinfifo(ahc, cmd->device->id, cmd->device->channel + 'A',
+				   cmd->device->lun, SCB_LIST_NULL, ROLE_INITIATOR,
  				   CAM_REQUEUE_REQ, SEARCH_COMPLETE);
  		ahc_print_path(ahc, pending_scb);
  		printf("Queuing a recovery SCB\n");
  		ahc_qinfifo_requeue_tail(ahc, pending_scb);
  		ahc_outb(ahc, SCBPTR, saved_scbptr);
  		printf("%s:%d:%d:%d: Device is disconnected, re-queuing SCB\n",
-		       ahc_name(ahc), cmd->channel, cmd->target, cmd->lun);
+		       ahc_name(ahc), cmd->device->channel, cmd->device->id, cmd->device->lun);
  		wait = TRUE;
  	} else {
  		printf("%s:%d:%d:%d: Unable to deliver message\n",
-		       ahc_name(ahc), cmd->channel, cmd->target, cmd->lun);
+		       ahc_name(ahc), cmd->device->channel, cmd->device->id, cmd->device->lun);
  		retval = FAILED;
  		goto done;
  	}
diff -Naur -X /usr/src/dontdiff linux-2.5.54-2/drivers/scsi/cpqfcTSinit.c linux-2.5.54-3/drivers/scsi/cpqfcTSinit.c
--- linux-2.5.54-2/drivers/scsi/cpqfcTSinit.c	2003-01-06 12:01:16.000000000 -0500
+++ linux-2.5.54-3/drivers/scsi/cpqfcTSinit.c	2003-01-06 16:29:51.000000000 -0500
@@ -1603,8 +1603,7 @@

    scsi_cdb[0] = RELEASE;

-  // allocate with wait = true, interruptible = false
-  SCpnt = scsi_allocate_device(ScsiDev, 1);
+  SCpnt = scsi_getset_command(ScsiDev, GFP_KERNEL);
    {
      CPQFC_DECLARE_COMPLETION(wait);

@@ -1653,7 +1652,7 @@
    result = SCpnt->result;

    SDpnt = SCpnt->device;
-  scsi_release_command(SCpnt);
+  scsi_put_command(SCpnt);
    SCpnt = NULL;

    // if (!SDpnt->was_reset && SDpnt->scsi_request_fn)
diff -Naur -X /usr/src/dontdiff linux-2.5.54-2/drivers/scsi/gdth.c linux-2.5.54-3/drivers/scsi/gdth.c
--- linux-2.5.54-2/drivers/scsi/gdth.c	2003-01-06 12:01:16.000000000 -0500
+++ linux-2.5.54-3/drivers/scsi/gdth.c	2003-01-06 16:31:52.000000000 -0500
@@ -4599,7 +4599,7 @@

  #if LINUX_VERSION_CODE >= 0x020322
      sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
-    scp  = scsi_allocate_device(sdev, 1);
+    scp  = scsi_getset_command(sdev, GFP_KERNEL);
      scp->cmd_len = 12;
      scp->use_sg = 0;
  #else
@@ -4627,7 +4627,7 @@
          }
      }
  #if LINUX_VERSION_CODE >= 0x020322
-    scsi_release_command(scp);
+    scsi_put_command(scp);
      scsi_free_host_dev(sdev);
  #endif
  }
@@ -4673,7 +4673,7 @@
          memset(cmnd, 0xff, MAX_COMMAND_SIZE);
  #if LINUX_VERSION_CODE >= 0x020322
          sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
-        scp  = scsi_allocate_device(sdev, 1);
+        scp  = scsi_getset_command(sdev, GFP_KERNEL);
          scp->cmd_len = 12;
          scp->use_sg = 0;
  #else
@@ -4690,7 +4690,7 @@
          TRACE2(("gdth_halt(): reset controller %d\n", hanum));
  #if LINUX_VERSION_CODE >= 0x020322
          gdth_do_cmd(scp, &gdtcmd, cmnd, 10);
-        scsi_release_command(scp);
+        scsi_put_command(scp);
          scsi_free_host_dev(sdev);
  #else
          gdth_do_cmd(&scp, &gdtcmd, cmnd, 10);
diff -Naur -X /usr/src/dontdiff linux-2.5.54-2/drivers/scsi/gdth_proc.c linux-2.5.54-3/drivers/scsi/gdth_proc.c
--- linux-2.5.54-2/drivers/scsi/gdth_proc.c	2003-01-06 12:01:16.000000000 -0500
+++ linux-2.5.54-3/drivers/scsi/gdth_proc.c	2003-01-06 16:35:02.000000000 -0500
@@ -48,7 +48,7 @@

  #if LINUX_VERSION_CODE >= 0x020322
      sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]);
-    scp  = scsi_allocate_device(sdev, 1);
+    scp  = scsi_getset_command(sdev, GFP_KERNEL);
      if (!scp)
          return -ENOMEM;
      scp->cmd_len = 12;
@@ -81,7 +81,7 @@
          ret_val = -EINVAL;
      }
  #if LINUX_VERSION_CODE >= 0x020322
-    scsi_release_command(scp);
+    scsi_put_command(scp);
      scsi_free_host_dev(sdev);
  #endif
      return ret_val;
@@ -712,7 +712,7 @@

  #if LINUX_VERSION_CODE >= 0x020322
      sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]);
-    scp  = scsi_allocate_device(sdev, 1);
+    scp  = scsi_getset_command(sdev, GFP_KERNEL);
      if (!scp)
          return -ENOMEM;
      scp->cmd_len = 12;
@@ -1234,7 +1234,7 @@

  stop_output:
  #if LINUX_VERSION_CODE >= 0x020322
-    scsi_release_command(scp);
+    scsi_put_command(scp);
      scsi_free_host_dev(sdev);
  #endif
      *start = buffer +(offset-begin);
diff -Naur -X /usr/src/dontdiff linux-2.5.54-2/drivers/scsi/hosts.c linux-2.5.54-3/drivers/scsi/hosts.c
--- linux-2.5.54-2/drivers/scsi/hosts.c	2003-01-06 12:00:18.000000000 -0500
+++ linux-2.5.54-3/drivers/scsi/hosts.c	2003-01-06 17:01:29.000000000 -0500
@@ -347,6 +347,13 @@
  	/* Cleanup proc */
  	scsi_proc_host_rm(shost);

+	while (!list_empty(&shost->free_list)) {
+		struct scsi_cmnd *cmd;
+		cmd = list_entry(shost->free_list.next,struct scsi_cmnd,list);
+		list_del_init(&cmd->list);
+		kmem_cache_free(scsi_core->scsi_cmd_cache, cmd);
+	}
+
  	kfree(shost);
  }

@@ -367,6 +374,7 @@
  struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes)
  {
  	struct Scsi_Host *shost, *shost_scr;
+	struct scsi_cmnd *cmd = NULL;
  	int gfp_mask;
  	DECLARE_MUTEX_LOCKED(sem);

@@ -456,6 +464,15 @@
  found:
  	spin_unlock(&scsi_host_list_lock);

+	INIT_LIST_HEAD(&shost->free_list);
+
+	/* Get one backup command for this host. */
+	cmd = scsi_get_command(shost, GFP_KERNEL);
+	if (cmd)
+		list_add(&cmd->list, &shost->free_list);		
+	else
+		printk(KERN_NOTICE "The system is running low in memory.\n");
+
  	scsi_proc_host_add(shost);

  	shost->eh_notify = &sem;
diff -Naur -X /usr/src/dontdiff linux-2.5.54-2/drivers/scsi/hosts.h linux-2.5.54-3/drivers/scsi/hosts.h
--- linux-2.5.54-2/drivers/scsi/hosts.h	2003-01-06 11:57:16.000000000 -0500
+++ linux-2.5.54-3/drivers/scsi/hosts.h	2003-01-06 12:37:43.000000000 -0500
@@ -375,6 +375,8 @@
      struct list_head      sh_list;
      struct list_head	  my_devices;

+    struct list_head      free_list;   /* backup store of cmd structs */
+
      spinlock_t		  default_lock;
      spinlock_t		  *host_lock;

diff -Naur -X /usr/src/dontdiff linux-2.5.54-2/drivers/scsi/scsi.c linux-2.5.54-3/drivers/scsi/scsi.c
--- linux-2.5.54-2/drivers/scsi/scsi.c	2003-01-06 12:01:16.000000000 -0500
+++ linux-2.5.54-3/drivers/scsi/scsi.c	2003-01-06 18:30:11.000000000 -0500
@@ -265,7 +265,7 @@
  {
  	if( req->sr_command != NULL )
  	{
-		scsi_release_command(req->sr_command);
+		scsi_put_command(req->sr_command);
  		req->sr_command = NULL;
  	}

@@ -768,7 +768,7 @@
  	SRpnt->sr_request->waiting = NULL;
  	if( SRpnt->sr_command != NULL )
  	{
-		scsi_release_command(SRpnt->sr_command);
+		scsi_put_command(SRpnt->sr_command);
  		SRpnt->sr_command = NULL;
  	}

@@ -834,7 +834,7 @@
  	 */
  	if( SRpnt->sr_command != NULL )
  	{
-		scsi_release_command(SRpnt->sr_command);
+		scsi_put_command(SRpnt->sr_command);
  		SRpnt->sr_command = NULL;
  	}

@@ -1506,6 +1506,12 @@
  			SDpnt->new_queue_depth = tags;
  			break;
  	}
+	/* TODO FIXME This is a hack and MUST go eventually.
+	   This fixes a problem in scsi_scan.c::scsi_alloc_sdev()
+	   else we cannot ever have ANY SCSI devices.
+	*/
+	SDpnt->current_queue_depth = 1;
+
  	spin_unlock_irqrestore(&device_request_lock, flags);
  }

@@ -2017,6 +2023,14 @@
  {
  	printk(KERN_INFO "SCSI subsystem driver " REVISION "\n");

+	scsi_core = kmalloc(sizeof(struct scsi_core_data), GFP_KERNEL);
+	if (!scsi_core)
+		goto out_no_mem;
+	memset(scsi_core, 0, sizeof(*scsi_core));
+	
+	if (scsi_create_cmdcache(scsi_core))
+		goto out_no_mem;
+
  	scsi_init_queue();
  	scsi_init_procfs();
  	devfs_mk_dir(NULL, "scsi", NULL);
@@ -2025,6 +2039,10 @@
  	scsi_sysfs_register();
  	open_softirq(SCSI_SOFTIRQ, scsi_softirq, NULL);
  	return 0;
+
+out_no_mem:
+	printk(KERN_CRIT "Couldn't load SCSI Core -- out of memory!\n");
+	return -ENOMEM;
  }

  static void __exit exit_scsi(void)
@@ -2034,6 +2052,12 @@
  	devfs_remove("scsi");
  	scsi_exit_procfs();
  	scsi_exit_queue();
+
+	scsi_destroy_cmdcache(scsi_core);
+
+	if (scsi_core)
+		kfree(scsi_core);
+	scsi_core = NULL;
  }

  subsys_initcall(init_scsi);
diff -Naur -X /usr/src/dontdiff linux-2.5.54-2/drivers/scsi/scsi.h linux-2.5.54-3/drivers/scsi/scsi.h
--- linux-2.5.54-2/drivers/scsi/scsi.h	2003-01-06 12:01:16.000000000 -0500
+++ linux-2.5.54-3/drivers/scsi/scsi.h	2003-01-06 16:29:22.000000000 -0500
@@ -734,7 +734,8 @@
  	Scsi_Request *sc_request;
  	struct scsi_cmnd *next;
  	struct scsi_cmnd *reset_chain;
-	struct list_head list_entry; /* Used to place us on the cmd lists */
+
+	struct list_head list;  /* scsi_cmnd participates in queue lists */

  	int eh_state;		/* Used for state tracking in error handlr */
  	int eh_eflags;		/* Used by error handlr */
@@ -994,4 +995,44 @@
  extern int scsi_sysfs_register(void);
  extern void scsi_sysfs_unregister(void);

+/* -------------------------------------------------- */
+/* data decl: */
+
+/* All the SCSI Core specific global data, etc,
+   should go in here.
+*/
+
+struct scsi_core_data {
+	kmem_cache_t   *scsi_cmd_cache;
+};
+
+extern struct scsi_core_data *scsi_core;
+
+/* -------------------------------------------------- */
+/* fn decl: */
+
+int scsi_create_cmdcache(struct scsi_core_data *scsi_core);
+int scsi_destroy_cmdcache(struct scsi_core_data *scsi_core);
+
+struct scsi_cmnd * scsi_get_command(struct Scsi_Host *host, int alloc_flags);
+void scsi_put_command(struct scsi_cmnd *cmd);
+void scsi_setup_command(struct scsi_device *dev, struct scsi_cmnd *cmd);
+
+/* -------------------------------------------------- */
+/* inline funcs: */
+
+/* scsi_getset_command: allocate, set and return a command struct,
+   when the device is known.
+*/
+static inline struct scsi_cmnd *scsi_getset_command(struct scsi_device *dev,
+						    int flags)
+{
+	struct scsi_cmnd *cmd;
+
+	if (!dev) return NULL;
+	if (!dev->host) return NULL;
+	scsi_setup_command(dev, (cmd = scsi_get_command(dev->host, flags)));
+	return cmd;
+}				
+
  #endif
diff -Naur -X /usr/src/dontdiff linux-2.5.54-2/drivers/scsi/scsi_error.c linux-2.5.54-3/drivers/scsi/scsi_error.c
--- linux-2.5.54-2/drivers/scsi/scsi_error.c	2003-01-06 12:01:16.000000000 -0500
+++ linux-2.5.54-3/drivers/scsi/scsi_error.c	2003-01-06 16:47:57.000000000 -0500
@@ -1384,7 +1384,7 @@
  	scmd->sc_request = NULL;
  	sreq->sr_command = NULL;

-	scsi_release_command(scmd);
+	scsi_put_command(scmd);
  	scsi_release_request(sreq);
  }

diff -Naur -X /usr/src/dontdiff linux-2.5.54-2/drivers/scsi/scsi_lib.c linux-2.5.54-3/drivers/scsi/scsi_lib.c
--- linux-2.5.54-2/drivers/scsi/scsi_lib.c	2003-01-06 12:01:16.000000000 -0500
+++ linux-2.5.54-3/drivers/scsi/scsi_lib.c	2003-01-06 16:49:18.000000000 -0500
@@ -33,7 +33,9 @@
  struct scsi_host_sg_pool scsi_sg_pools[SG_MEMPOOL_NR] = {
  	SP(8), SP(16), SP(32), SP(64), SP(MAX_PHYS_SEGMENTS)
  }; 	
-#undef SP 	
+#undef SP
+
+struct scsi_core_data *scsi_core;

  /*
   * Function:    scsi_insert_special_cmd()
@@ -357,7 +359,7 @@
  	 * This will goose the queue request function at the end, so we don't
  	 * need to worry about launching another command.
  	 */
-	__scsi_release_command(SCpnt);
+	scsi_put_command(SCpnt);
  	scsi_queue_next_request(q, NULL);
  	return NULL;
  }
@@ -802,7 +804,8 @@
  		SRpnt = (Scsi_Request *) req->special;
  		
  		if( SRpnt->sr_magic == SCSI_REQ_MAGIC ) {
-			SCpnt = scsi_allocate_device(SRpnt->sr_device, 0);
+			SCpnt = scsi_getset_command(SRpnt->sr_device,
+						    GFP_ATOMIC);
  			if (!SCpnt)
  				return BLKPREP_DEFER;
  			scsi_init_cmd_from_req(SCpnt, SRpnt);
@@ -815,7 +818,7 @@
  		if (req->special) {
  			SCpnt = (Scsi_Cmnd *) req->special;
  		} else {
-			SCpnt = scsi_allocate_device(SDpnt, 0);
+			SCpnt = scsi_getset_command(SDpnt, GFP_ATOMIC);
  		}
  		/*
  		 * if command allocation failure, wait a bit
@@ -1179,3 +1182,110 @@
  		kmem_cache_destroy(sgp->slab);
  	}
  }
+
+/* -------------------------------------------------- */
+
+int scsi_create_cmdcache(struct scsi_core_data *scsi_core)
+{
+	if (!scsi_core)
+		return -EFAULT;
+	scsi_core->scsi_cmd_cache
+		= kmem_cache_create("scsi_cmd_cache",
+				    sizeof(struct scsi_cmnd), 0,
+				    SLAB_NO_REAP|SLAB_HWCACHE_ALIGN,NULL,NULL);
+	if (!scsi_core->scsi_cmd_cache)
+		return -ENOMEM;
+	return 0;
+} /* end scsi_create_cmdcache() */
+
+/* -------------------------------------------------- */
+
+int scsi_destroy_cmdcache(struct scsi_core_data *scsi_core)
+{
+	if (!scsi_core)
+		return -EFAULT;
+	if (kmem_cache_destroy(scsi_core->scsi_cmd_cache)) {
+		printk(KERN_CRIT "Failed to free scsi command cache"
+		       " -- memory leak\n");
+		return -EFAULT;
+	} else {
+		scsi_core->scsi_cmd_cache = NULL;
+	}
+	return 0;
+} /* end scsi_destroy_cmdcache() */
+
+/* -------------------------------------------------- */
+
+struct scsi_cmnd * scsi_get_command(struct Scsi_Host *host, int alloc_flags)
+{
+	unsigned long flags;
+	struct scsi_cmnd *cmd = NULL;
+	
+	if (!host)
+		return NULL;
+
+	cmd = kmem_cache_alloc(scsi_core->scsi_cmd_cache, alloc_flags);
+
+	if (!cmd) {
+		spin_lock_irqsave(host->host_lock, flags);
+		if (!list_empty(&host->free_list)) {
+			cmd = list_entry(host->free_list.next,
+					 struct scsi_cmnd, list);
+			list_del_init(&cmd->list);
+		}
+		spin_unlock_irqrestore(host->host_lock, flags);
+	}
+
+	return cmd;
+} /* end scsi_get_command() */
+
+/* -------------------------------------------------- */
+/* scsi_put_command: free a scsi_cmnd struct.
+   Note: the command must not belong to any lists!
+*/
+void scsi_put_command(struct scsi_cmnd *cmd)
+{
+	unsigned long flags;
+	struct Scsi_Host *host;
+	
+	if (!cmd)
+		return;
+
+	if (!cmd->device || !cmd->device->host) {
+		printk(KERN_NOTICE "Trying to free a command which"
+		       " doesn't belong to scsi core?!\n");
+		 /* Memory leak, but let the system survive for now --
+		    they'll get it eventually! */
+		return;
+	}
+
+	host = cmd->device->host;
+
+	spin_lock_irqsave(host->host_lock, flags);
+	if (list_empty(&host->free_list)) {
+		list_add(&cmd->list, &host->free_list);
+		cmd = NULL;
+	}
+	spin_unlock_irqrestore(host->host_lock, flags);
+
+	if (cmd)
+		kmem_cache_free(scsi_core->scsi_cmd_cache, cmd);
+} /* end scsi_put_command() */
+
+/* -------------------------------------------------- */
+/* scsi_setup_command: This will do post-alloc init of the command.
+   We want to do as little as possible here.
+*/
+void scsi_setup_command(struct scsi_device *dev, struct scsi_cmnd *cmd)
+{
+	if (!cmd)
+		return;
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->device = dev;
+	cmd->state = SCSI_STATE_UNUSED;
+	cmd->owner = SCSI_OWNER_NOBODY;
+	init_timer(&cmd->eh_timeout);
+	INIT_LIST_HEAD(&cmd->list);
+} /* end scsi_setup_command() */
+
+/* -------------------------------------------------- */
diff -Naur -X /usr/src/dontdiff linux-2.5.54-2/drivers/scsi/scsi_scan.c linux-2.5.54-3/drivers/scsi/scsi_scan.c
--- linux-2.5.54-2/drivers/scsi/scsi_scan.c	2003-01-06 11:57:16.000000000 -0500
+++ linux-2.5.54-3/drivers/scsi/scsi_scan.c	2003-01-06 18:45:38.000000000 -0500
@@ -471,7 +471,6 @@

  		sdev->request_queue->queuedata = sdev;
  		scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
-		scsi_build_commandblocks(sdev);
  		if (sdev->current_queue_depth == 0) {
  			goto out_bail;
  		}
@@ -515,7 +514,6 @@
  	} else if (sdev->request_queue)
  		scsi_free_queue(sdev->request_queue);

-	scsi_release_commandblocks(sdev);
  	kfree(sdev);
  	return NULL;
  }
@@ -535,7 +533,6 @@

  	if (sdev->request_queue)
  		scsi_free_queue(sdev->request_queue);
-	scsi_release_commandblocks(sdev);
  	if (sdev->host->hostt->slave_destroy)
  		sdev->host->hostt->slave_destroy(sdev);
  	if (sdev->inquiry)
diff -Naur -X /usr/src/dontdiff linux-2.5.54-2/drivers/scsi/scsi_syms.c linux-2.5.54-3/drivers/scsi/scsi_syms.c
--- linux-2.5.54-2/drivers/scsi/scsi_syms.c	2003-01-06 11:57:16.000000000 -0500
+++ linux-2.5.54-3/drivers/scsi/scsi_syms.c	2003-01-06 16:51:09.000000000 -0500
@@ -39,7 +39,8 @@
  EXPORT_SYMBOL(scsicam_bios_param);
  EXPORT_SYMBOL(scsi_partsize);
  EXPORT_SYMBOL(scsi_bios_ptable);
-EXPORT_SYMBOL(scsi_allocate_device);
+/* Obsolete! Use scsi_get_command() or scsi_getset_command(). */
+/* EXPORT_SYMBOL(scsi_allocate_device); */
  EXPORT_SYMBOL(scsi_do_cmd);
  EXPORT_SYMBOL(scsi_ioctl);
  EXPORT_SYMBOL(print_command);
@@ -50,7 +51,8 @@
  EXPORT_SYMBOL(scsi_sense_key_string);
  EXPORT_SYMBOL(scsi_extd_sense_format);
  EXPORT_SYMBOL(kernel_scsi_ioctl);
-EXPORT_SYMBOL(scsi_release_command);
+/* Obsolete! Use scsi_put_command() instead. */
+/* EXPORT_SYMBOL(scsi_release_command); */
  EXPORT_SYMBOL(print_Scsi_Cmnd);
  EXPORT_SYMBOL(scsi_block_when_processing_errors);
  EXPORT_SYMBOL(scsi_ioctl_send_command);
@@ -114,3 +116,8 @@
   * sysfs support
   */
  EXPORT_SYMBOL(shost_devclass);
+
+EXPORT_SYMBOL(scsi_get_command);
+EXPORT_SYMBOL(scsi_put_command);
+EXPORT_SYMBOL(scsi_setup_command);
+


             reply	other threads:[~2003-01-07  0:37 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-01-07  0:37 Luben Tuikov [this message]
2003-01-11 18:03 ` [PATCH] SCSI Core cmd allocation 3/3 Christoph Hellwig
2003-01-13 17:12   ` Luben Tuikov
2003-01-13 17:59     ` Christoph Hellwig
2003-01-13 19:16       ` Luben Tuikov
2003-01-13 20:11         ` Patrick Mansfield
2003-01-13 20:40           ` Luben Tuikov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3E1A2140.3000408@splentec.com \
    --to=luben@splentec.com \
    --cc=linux-scsi@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.