Skip to content

Commit

Permalink
[SCSI] megaraid_sas: call cmd completion from reset
Browse files Browse the repository at this point in the history
Driver will call cmd completion routine from Reset path without waiting for cmd completion from isr context.

Signed-off-by: Bo Yang <bo.yang@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
  • Loading branch information
bo yang authored and James Bottomley committed Jan 12, 2008
1 parent b10c36a commit 7343eb6
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 54 deletions.
122 changes: 68 additions & 54 deletions drivers/scsi/megaraid/megaraid_sas.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ static DEFINE_MUTEX(megasas_async_queue_mutex);

static u32 megasas_dbg_lvl;

static void
megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
u8 alt_status);

/**
* megasas_get_cmd - Get a command from the free pool
* @instance: Adapter soft state
Expand Down Expand Up @@ -886,6 +890,64 @@ static int megasas_slave_configure(struct scsi_device *sdev)
return 0;
}

/**
* megasas_complete_cmd_dpc - Returns FW's controller structure
* @instance_addr: Address of adapter soft state
*
* Tasklet to complete cmds
*/
static void megasas_complete_cmd_dpc(unsigned long instance_addr)
{
u32 producer;
u32 consumer;
u32 context;
struct megasas_cmd *cmd;
struct megasas_instance *instance =
(struct megasas_instance *)instance_addr;
unsigned long flags;

/* If we have already declared adapter dead, donot complete cmds */
if (instance->hw_crit_error)
return;

spin_lock_irqsave(&instance->completion_lock, flags);

producer = *instance->producer;
consumer = *instance->consumer;

while (consumer != producer) {
context = instance->reply_queue[consumer];

cmd = instance->cmd_list[context];

megasas_complete_cmd(instance, cmd, DID_OK);

consumer++;
if (consumer == (instance->max_fw_cmds + 1)) {
consumer = 0;
}
}

*instance->consumer = producer;

spin_unlock_irqrestore(&instance->completion_lock, flags);

/*
* Check if we can restore can_queue
*/
if (instance->flag & MEGASAS_FW_BUSY
&& time_after(jiffies, instance->last_time + 5 * HZ)
&& atomic_read(&instance->fw_outstanding) < 17) {

spin_lock_irqsave(instance->host->host_lock, flags);
instance->flag &= ~MEGASAS_FW_BUSY;
instance->host->can_queue =
instance->max_fw_cmds - MEGASAS_INT_CMDS;

spin_unlock_irqrestore(instance->host->host_lock, flags);
}
}

/**
* megasas_wait_for_outstanding - Wait for all outstanding cmds
* @instance: Adapter soft state
Expand All @@ -909,6 +971,11 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance)
if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
printk(KERN_NOTICE "megasas: [%2d]waiting for %d "
"commands to complete\n",i,outstanding);
/*
* Call cmd completion routine. Cmd to be
* be completed directly without depending on isr.
*/
megasas_complete_cmd_dpc((unsigned long)instance);
}

msleep(1000);
Expand Down Expand Up @@ -1749,60 +1816,6 @@ megasas_get_ctrl_info(struct megasas_instance *instance,
return ret;
}

/**
* megasas_complete_cmd_dpc - Returns FW's controller structure
* @instance_addr: Address of adapter soft state
*
* Tasklet to complete cmds
*/
static void megasas_complete_cmd_dpc(unsigned long instance_addr)
{
u32 producer;
u32 consumer;
u32 context;
struct megasas_cmd *cmd;
struct megasas_instance *instance = (struct megasas_instance *)instance_addr;
unsigned long flags;

/* If we have already declared adapter dead, donot complete cmds */
if (instance->hw_crit_error)
return;

producer = *instance->producer;
consumer = *instance->consumer;

while (consumer != producer) {
context = instance->reply_queue[consumer];

cmd = instance->cmd_list[context];

megasas_complete_cmd(instance, cmd, DID_OK);

consumer++;
if (consumer == (instance->max_fw_cmds + 1)) {
consumer = 0;
}
}

*instance->consumer = producer;

/*
* Check if we can restore can_queue
*/
if (instance->flag & MEGASAS_FW_BUSY
&& time_after(jiffies, instance->last_time + 5 * HZ)
&& atomic_read(&instance->fw_outstanding) < 17) {

spin_lock_irqsave(instance->host->host_lock, flags);
instance->flag &= ~MEGASAS_FW_BUSY;
instance->host->can_queue =
instance->max_fw_cmds - MEGASAS_INT_CMDS;

spin_unlock_irqrestore(instance->host->host_lock, flags);
}

}

/**
* megasas_issue_init_mfi - Initializes the FW
* @instance: Adapter soft state
Expand Down Expand Up @@ -2395,6 +2408,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
init_waitqueue_head(&instance->abort_cmd_wait_q);

spin_lock_init(&instance->cmd_pool_lock);
spin_lock_init(&instance->completion_lock);

mutex_init(&instance->aen_mutex);
sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);
Expand Down
2 changes: 2 additions & 0 deletions drivers/scsi/megaraid/megaraid_sas.h
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,8 @@ struct megasas_instance {
struct megasas_cmd **cmd_list;
struct list_head cmd_pool;
spinlock_t cmd_pool_lock;
/* used to synch producer, consumer ptrs in dpc */
spinlock_t completion_lock;
struct dma_pool *frame_dma_pool;
struct dma_pool *sense_dma_pool;

Expand Down

0 comments on commit 7343eb6

Please sign in to comment.