|
@@ -531,13 +531,6 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy)
|
|
|
int target = 0;
|
|
|
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()
|
|
|
*/
|
|
@@ -1439,19 +1432,22 @@ mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status)
|
|
|
|
|
|
cmdid = completed[i];
|
|
|
|
|
|
- if( cmdid == CMDID_INT_CMDS ) { /* internal command */
|
|
|
+ /*
|
|
|
+ * 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) {
|
|
|
scb = &adapter->int_scb;
|
|
|
- cmd = scb->cmd;
|
|
|
- mbox = (mbox_t *)scb->raw_mbox;
|
|
|
|
|
|
- /*
|
|
|
- * Internal command interface do not fire the extended
|
|
|
- * passthru or 64-bit passthru
|
|
|
- */
|
|
|
- pthru = scb->pthru;
|
|
|
+ list_del_init(&scb->list);
|
|
|
+ scb->state = SCB_FREE;
|
|
|
|
|
|
- }
|
|
|
- else {
|
|
|
+ adapter->int_status = status;
|
|
|
+ complete(&adapter->int_waitq);
|
|
|
+ } else {
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * 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 */
|
|
|
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
|
|
|
* 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.
|
|
|
*/
|
|
|
static int
|
|
|
mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru)
|
|
|
{
|
|
|
- Scsi_Cmnd *scmd;
|
|
|
- struct scsi_device *sdev;
|
|
|
+ unsigned long flags;
|
|
|
scb_t *scb;
|
|
|
int rval;
|
|
|
|
|
|
- scmd = scsi_allocate_command(GFP_KERNEL);
|
|
|
- if (!scmd)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
/*
|
|
|
* The internal commands share one command id and hence are
|
|
|
* 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;
|
|
|
memset(scb, 0, sizeof(scb_t));
|
|
|
|
|
|
- sdev = kzalloc(sizeof(struct scsi_device), GFP_KERNEL);
|
|
|
- scmd->device = sdev;
|
|
|
-
|
|
|
- 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;
|
|
|
+ scb->idx = CMDID_INT_CMDS;
|
|
|
+ scb->state |= SCB_ACTIVE | SCB_PENDQ;
|
|
|
|
|
|
memcpy(scb->raw_mbox, mc, sizeof(megacmd_t));
|
|
|
|
|
|
/*
|
|
|
* Is it a passthru command
|
|
|
*/
|
|
|
- if( mc->cmd == MEGA_MBOXCMD_PASSTHRU ) {
|
|
|
-
|
|
|
+ if (mc->cmd == MEGA_MBOXCMD_PASSTHRU)
|
|
|
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);
|
|
|
|
|
|
- rval = scmd->result;
|
|
|
- mc->status = scmd->result;
|
|
|
- kfree(sdev);
|
|
|
+ mc->status = rval = adapter->int_status;
|
|
|
|
|
|
/*
|
|
|
* Print a debug message for all failed commands. Applications can use
|
|
|
* this information.
|
|
|
*/
|
|
|
- if( scmd->result && trace_level ) {
|
|
|
+ if (rval && trace_level) {
|
|
|
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);
|
|
|
-
|
|
|
- scsi_free_command(GFP_KERNEL, scmd);
|
|
|
-
|
|
|
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 = {
|
|
|
.module = THIS_MODULE,
|
|
|
.name = "MegaRAID",
|