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

Commit 7343eb65 authored by bo yang's avatar bo yang Committed by James Bottomley
Browse files

[SCSI] megaraid_sas: call cmd completion from reset



Driver will call cmd completion routine from Reset path without waiting for cmd completion from isr context.

Signed-off-by: default avatarBo Yang <bo.yang@lsi.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent b10c36a5
Loading
Loading
Loading
Loading
+68 −54
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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);
@@ -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
@@ -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);
+2 −0
Original line number Diff line number Diff line
@@ -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;