Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0f2bb84d authored by Christoph Hellwig's avatar Christoph Hellwig Committed by James Bottomley
Browse files

[SCSI] megaraid: simplify internal command handling



We don't use the passed in scsi command for anything, so just add a adapter-
wide internal status to go along with the internal scb that is used unter
int_mtx to pass back the return value and get rid of all the complexities
and abuse of the scsi_cmnd structure.

This gets rid of the only user of scsi_allocate_command/scsi_free_command,
which can now be removed.

[jejb: checkpatch fixes]
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Acked-by: default avatarAdam Radford <aradford@gmail.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent c38c007a
Loading
Loading
Loading
Loading
+31 −89
Original line number Original line Diff line number Diff line
@@ -531,13 +531,6 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy)
	int	target = 0;
	int	target = 0;
	int	ldrv_num = 0;   /* logical drive number */
	int	ldrv_num = 0;   /* logical drive number */



	/*
	 * filter the internal and ioctl commands
	 */
	if((cmd->cmnd[0] == MEGA_INTERNAL_CMD))
		return (scb_t *)cmd->host_scribble;

	/*
	/*
	 * We know what channels our logical drives are on - mega_find_card()
	 * We know what channels our logical drives are on - mega_find_card()
	 */
	 */
@@ -1439,19 +1432,22 @@ mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status)


		cmdid = completed[i];
		cmdid = completed[i];


		if( cmdid == CMDID_INT_CMDS ) { /* internal command */
			scb = &adapter->int_scb;
			cmd = scb->cmd;
			mbox = (mbox_t *)scb->raw_mbox;

		/*
		/*
			 * Internal command interface do not fire the extended
		 * Only free SCBs for the commands coming down from the
			 * passthru or 64-bit passthru
		 * mid-layer, not for which were issued internally
		 *
		 * For internal command, restore the status returned by the
		 * firmware so that user can interpret it.
		 */
		 */
			pthru = scb->pthru;
		if (cmdid == CMDID_INT_CMDS) {
			scb = &adapter->int_scb;


		}
			list_del_init(&scb->list);
		else {
			scb->state = SCB_FREE;

			adapter->int_status = status;
			complete(&adapter->int_waitq);
		} else {
			scb = &adapter->scb_list[cmdid];
			scb = &adapter->scb_list[cmdid];


			/*
			/*
@@ -1640,25 +1636,7 @@ mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status)
				cmd->result |= (DID_BAD_TARGET << 16)|status;
				cmd->result |= (DID_BAD_TARGET << 16)|status;
		}
		}


		/*
		 * Only free SCBs for the commands coming down from the
		 * mid-layer, not for which were issued internally
		 *
		 * For internal command, restore the status returned by the
		 * firmware so that user can interpret it.
		 */
		if( cmdid == CMDID_INT_CMDS ) { /* internal command */
			cmd->result = status;

			/*
			 * Remove the internal command from the pending list
			 */
			list_del_init(&scb->list);
			scb->state = SCB_FREE;
		}
		else {
		mega_free_scb(adapter, scb);
		mega_free_scb(adapter, scb);
		}


		/* Add Scsi_Command to end of completed queue */
		/* Add Scsi_Command to end of completed queue */
		list_add_tail(SCSI_LIST(cmd), &adapter->completed_list);
		list_add_tail(SCSI_LIST(cmd), &adapter->completed_list);
@@ -4133,23 +4111,15 @@ mega_internal_dev_inquiry(adapter_t *adapter, u8 ch, u8 tgt,
 * The last argument is the address of the passthru structure if the command
 * The last argument is the address of the passthru structure if the command
 * to be fired is a passthru command
 * to be fired is a passthru command
 *
 *
 * lockscope specifies whether the caller has already acquired the lock. Of
 * course, the caller must know which lock we are talking about.
 *
 * Note: parameter 'pthru' is null for non-passthru commands.
 * Note: parameter 'pthru' is null for non-passthru commands.
 */
 */
static int
static int
mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru)
mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru)
{
{
	Scsi_Cmnd	*scmd;
	unsigned long flags;
	struct	scsi_device *sdev;
	scb_t	*scb;
	scb_t	*scb;
	int	rval;
	int	rval;


	scmd = scsi_allocate_command(GFP_KERNEL);
	if (!scmd)
		return -ENOMEM;

	/*
	/*
	 * The internal commands share one command id and hence are
	 * The internal commands share one command id and hence are
	 * serialized. This is so because we want to reserve maximum number of
	 * serialized. This is so because we want to reserve maximum number of
@@ -4160,73 +4130,45 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru)
	scb = &adapter->int_scb;
	scb = &adapter->int_scb;
	memset(scb, 0, sizeof(scb_t));
	memset(scb, 0, sizeof(scb_t));


	sdev = kzalloc(sizeof(struct scsi_device), GFP_KERNEL);
	scb->idx = CMDID_INT_CMDS;
	scmd->device = sdev;
	scb->state |= SCB_ACTIVE | SCB_PENDQ;

	memset(adapter->int_cdb, 0, sizeof(adapter->int_cdb));
	scmd->cmnd = adapter->int_cdb;
	scmd->device->host = adapter->host;
	scmd->host_scribble = (void *)scb;
	scmd->cmnd[0] = MEGA_INTERNAL_CMD;

	scb->state |= SCB_ACTIVE;
	scb->cmd = scmd;


	memcpy(scb->raw_mbox, mc, sizeof(megacmd_t));
	memcpy(scb->raw_mbox, mc, sizeof(megacmd_t));


	/*
	/*
	 * Is it a passthru command
	 * Is it a passthru command
	 */
	 */
	if( mc->cmd == MEGA_MBOXCMD_PASSTHRU ) {
	if (mc->cmd == MEGA_MBOXCMD_PASSTHRU)

		scb->pthru = pthru;
		scb->pthru = pthru;
	}

	scb->idx = CMDID_INT_CMDS;


	megaraid_queue_lck(scmd, mega_internal_done);
	spin_lock_irqsave(&adapter->lock, flags);
	list_add_tail(&scb->list, &adapter->pending_list);
	/*
	 * Check if the HBA is in quiescent state, e.g., during a
	 * delete logical drive opertion. If it is, don't run
	 * the pending_list.
	 */
	if (atomic_read(&adapter->quiescent) == 0)
		mega_runpendq(adapter);
	spin_unlock_irqrestore(&adapter->lock, flags);


	wait_for_completion(&adapter->int_waitq);
	wait_for_completion(&adapter->int_waitq);


	rval = scmd->result;
	mc->status = rval = adapter->int_status;
	mc->status = scmd->result;
	kfree(sdev);


	/*
	/*
	 * Print a debug message for all failed commands. Applications can use
	 * Print a debug message for all failed commands. Applications can use
	 * this information.
	 * this information.
	 */
	 */
	if( scmd->result && trace_level ) {
	if (rval && trace_level) {
		printk("megaraid: cmd [%x, %x, %x] status:[%x]\n",
		printk("megaraid: cmd [%x, %x, %x] status:[%x]\n",
			mc->cmd, mc->opcode, mc->subopcode, scmd->result);
			mc->cmd, mc->opcode, mc->subopcode, rval);
	}
	}


	mutex_unlock(&adapter->int_mtx);
	mutex_unlock(&adapter->int_mtx);

	scsi_free_command(GFP_KERNEL, scmd);

	return rval;
	return rval;
}
}



/**
 * mega_internal_done()
 * @scmd - internal scsi command
 *
 * Callback routine for internal commands.
 */
static void
mega_internal_done(Scsi_Cmnd *scmd)
{
	adapter_t	*adapter;

	adapter = (adapter_t *)scmd->device->host->hostdata;

	complete(&adapter->int_waitq);

}


static struct scsi_host_template megaraid_template = {
static struct scsi_host_template megaraid_template = {
	.module				= THIS_MODULE,
	.module				= THIS_MODULE,
	.name				= "MegaRAID",
	.name				= "MegaRAID",
+1 −2
Original line number Original line Diff line number Diff line
@@ -853,10 +853,10 @@ typedef struct {


	u8	sglen;	/* f/w supported scatter-gather list length */
	u8	sglen;	/* f/w supported scatter-gather list length */


	unsigned char int_cdb[MAX_COMMAND_SIZE];
	scb_t			int_scb;
	scb_t			int_scb;
	struct mutex		int_mtx;	/* To synchronize the internal
	struct mutex		int_mtx;	/* To synchronize the internal
						commands */
						commands */
	int			int_status;	/* status of internal cmd */
	struct completion	int_waitq;	/* wait queue for internal
	struct completion	int_waitq;	/* wait queue for internal
						 cmds */
						 cmds */


@@ -1004,7 +1004,6 @@ static int mega_del_logdrv(adapter_t *, int);
static int mega_do_del_logdrv(adapter_t *, int);
static int mega_do_del_logdrv(adapter_t *, int);
static void mega_get_max_sgl(adapter_t *);
static void mega_get_max_sgl(adapter_t *);
static int mega_internal_command(adapter_t *, megacmd_t *, mega_passthru *);
static int mega_internal_command(adapter_t *, megacmd_t *, mega_passthru *);
static void mega_internal_done(Scsi_Cmnd *);
static int mega_support_cluster(adapter_t *);
static int mega_support_cluster(adapter_t *);
#endif
#endif


+0 −56
Original line number Original line Diff line number Diff line
@@ -402,62 +402,6 @@ static void scsi_put_host_cmd_pool(gfp_t gfp_mask)
	mutex_unlock(&host_cmd_pool_mutex);
	mutex_unlock(&host_cmd_pool_mutex);
}
}


/**
 * scsi_allocate_command - get a fully allocated SCSI command
 * @gfp_mask:	allocation mask
 *
 * This function is for use outside of the normal host based pools.
 * It allocates the relevant command and takes an additional reference
 * on the pool it used.  This function *must* be paired with
 * scsi_free_command which also has the identical mask, otherwise the
 * free pool counts will eventually go wrong and you'll trigger a bug.
 *
 * This function should *only* be used by drivers that need a static
 * command allocation at start of day for internal functions.
 */
struct scsi_cmnd *scsi_allocate_command(gfp_t gfp_mask)
{
	struct scsi_host_cmd_pool *pool = scsi_get_host_cmd_pool(gfp_mask);

	if (!pool)
		return NULL;

	return scsi_pool_alloc_command(pool, gfp_mask);
}
EXPORT_SYMBOL(scsi_allocate_command);

/**
 * scsi_free_command - free a command allocated by scsi_allocate_command
 * @gfp_mask:	mask used in the original allocation
 * @cmd:	command to free
 *
 * Note: using the original allocation mask is vital because that's
 * what determines which command pool we use to free the command.  Any
 * mismatch will cause the system to BUG eventually.
 */
void scsi_free_command(gfp_t gfp_mask, struct scsi_cmnd *cmd)
{
	struct scsi_host_cmd_pool *pool = scsi_get_host_cmd_pool(gfp_mask);

	/*
	 * this could trigger if the mask to scsi_allocate_command
	 * doesn't match this mask.  Otherwise we're guaranteed that this
	 * succeeds because scsi_allocate_command must have taken a reference
	 * on the pool
	 */
	BUG_ON(!pool);

	scsi_pool_free_command(pool, cmd);
	/*
	 * scsi_put_host_cmd_pool is called twice; once to release the
	 * reference we took above, and once to release the reference
	 * originally taken by scsi_allocate_command
	 */
	scsi_put_host_cmd_pool(gfp_mask);
	scsi_put_host_cmd_pool(gfp_mask);
}
EXPORT_SYMBOL(scsi_free_command);

/**
/**
 * scsi_setup_command_freelist - Setup the command freelist for a scsi host.
 * scsi_setup_command_freelist - Setup the command freelist for a scsi host.
 * @shost: host to allocate the freelist for.
 * @shost: host to allocate the freelist for.
+0 −3
Original line number Original line Diff line number Diff line
@@ -155,9 +155,6 @@ extern void scsi_release_buffers(struct scsi_cmnd *cmd);
extern int scsi_dma_map(struct scsi_cmnd *cmd);
extern int scsi_dma_map(struct scsi_cmnd *cmd);
extern void scsi_dma_unmap(struct scsi_cmnd *cmd);
extern void scsi_dma_unmap(struct scsi_cmnd *cmd);


struct scsi_cmnd *scsi_allocate_command(gfp_t gfp_mask);
void scsi_free_command(gfp_t gfp_mask, struct scsi_cmnd *cmd);

static inline unsigned scsi_sg_count(struct scsi_cmnd *cmd)
static inline unsigned scsi_sg_count(struct scsi_cmnd *cmd)
{
{
	return cmd->sdb.table.nents;
	return cmd->sdb.table.nents;