Skip to content

Commit

Permalink
[SCSI] ipr: Reduce interrupt lock time
Browse files Browse the repository at this point in the history
Reduce the amount of time the host lock is held in the interrupt handler
for improved performance.

[jejb: fix up checkpatch noise]
Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
  • Loading branch information
Brian King authored and James Bottomley committed Aug 24, 2012
1 parent 00bfef2 commit 172cd6e
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 14 deletions.
60 changes: 46 additions & 14 deletions drivers/scsi/ipr.c
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,23 @@ static void ipr_trc_hook(struct ipr_cmnd *ipr_cmd,
#define ipr_trc_hook(ipr_cmd, type, add_data) do { } while(0)
#endif

/**
* ipr_lock_and_done - Acquire lock and complete command
* @ipr_cmd: ipr command struct
*
* Return value:
* none
**/
static void ipr_lock_and_done(struct ipr_cmnd *ipr_cmd)
{
unsigned long lock_flags;
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;

spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
ipr_cmd->done(ipr_cmd);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
}

/**
* ipr_reinit_ipr_cmnd - Re-initialize an IPR Cmnd block for reuse
* @ipr_cmd: ipr command struct
Expand Down Expand Up @@ -611,11 +628,13 @@ static void ipr_reinit_ipr_cmnd(struct ipr_cmnd *ipr_cmd)
* Return value:
* none
**/
static void ipr_init_ipr_cmnd(struct ipr_cmnd *ipr_cmd)
static void ipr_init_ipr_cmnd(struct ipr_cmnd *ipr_cmd,
void (*fast_done) (struct ipr_cmnd *))
{
ipr_reinit_ipr_cmnd(ipr_cmd);
ipr_cmd->u.scratch = 0;
ipr_cmd->sibling = NULL;
ipr_cmd->fast_done = fast_done;
init_timer(&ipr_cmd->timer);
}

Expand Down Expand Up @@ -648,7 +667,7 @@ static
struct ipr_cmnd *ipr_get_free_ipr_cmnd(struct ipr_ioa_cfg *ioa_cfg)
{
struct ipr_cmnd *ipr_cmd = __ipr_get_free_ipr_cmnd(ioa_cfg);
ipr_init_ipr_cmnd(ipr_cmd);
ipr_init_ipr_cmnd(ipr_cmd, ipr_lock_and_done);
return ipr_cmd;
}

Expand Down Expand Up @@ -5130,8 +5149,9 @@ static irqreturn_t ipr_isr(int irq, void *devp)
u16 cmd_index;
int num_hrrq = 0;
int irq_none = 0;
struct ipr_cmnd *ipr_cmd;
struct ipr_cmnd *ipr_cmd, *temp;
irqreturn_t rc = IRQ_NONE;
LIST_HEAD(doneq);

spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);

Expand All @@ -5152,8 +5172,8 @@ static irqreturn_t ipr_isr(int irq, void *devp)

if (unlikely(cmd_index >= IPR_NUM_CMD_BLKS)) {
ipr_isr_eh(ioa_cfg, "Invalid response handle from IOA");
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
return IRQ_HANDLED;
rc = IRQ_HANDLED;
goto unlock_out;
}

ipr_cmd = ioa_cfg->ipr_cmnd_list[cmd_index];
Expand All @@ -5162,9 +5182,7 @@ static irqreturn_t ipr_isr(int irq, void *devp)

ipr_trc_hook(ipr_cmd, IPR_TRACE_FINISH, ioasc);

list_del(&ipr_cmd->queue);
del_timer(&ipr_cmd->timer);
ipr_cmd->done(ipr_cmd);
list_move_tail(&ipr_cmd->queue, &doneq);

rc = IRQ_HANDLED;

Expand Down Expand Up @@ -5194,16 +5212,23 @@ static irqreturn_t ipr_isr(int irq, void *devp)
} else if (num_hrrq == IPR_MAX_HRRQ_RETRIES &&
int_reg & IPR_PCII_HRRQ_UPDATED) {
ipr_isr_eh(ioa_cfg, "Error clearing HRRQ");
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
return IRQ_HANDLED;
rc = IRQ_HANDLED;
goto unlock_out;
} else
break;
}

if (unlikely(rc == IRQ_NONE))
rc = ipr_handle_other_interrupt(ioa_cfg, int_reg);

unlock_out:
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
list_for_each_entry_safe(ipr_cmd, temp, &doneq, queue) {
list_del(&ipr_cmd->queue);
del_timer(&ipr_cmd->timer);
ipr_cmd->fast_done(ipr_cmd);
}

return rc;
}

Expand Down Expand Up @@ -5784,15 +5809,22 @@ static void ipr_scsi_done(struct ipr_cmnd *ipr_cmd)
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
unsigned long lock_flags;

scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->s.ioasa.hdr.residual_data_len));

if (likely(IPR_IOASC_SENSE_KEY(ioasc) == 0)) {
scsi_dma_unmap(ipr_cmd->scsi_cmd);
scsi_dma_unmap(scsi_cmd);

spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
scsi_cmd->scsi_done(scsi_cmd);
} else
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
} else {
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
ipr_erp_start(ioa_cfg, ipr_cmd);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
}
}

/**
Expand Down Expand Up @@ -5848,12 +5880,12 @@ static int ipr_queuecommand(struct Scsi_Host *shost,
ipr_cmd = __ipr_get_free_ipr_cmnd(ioa_cfg);
spin_unlock_irqrestore(shost->host_lock, lock_flags);

ipr_init_ipr_cmnd(ipr_cmd);
ipr_init_ipr_cmnd(ipr_cmd, ipr_scsi_done);
ioarcb = &ipr_cmd->ioarcb;

memcpy(ioarcb->cmd_pkt.cdb, scsi_cmd->cmnd, scsi_cmd->cmd_len);
ipr_cmd->scsi_cmd = scsi_cmd;
ipr_cmd->done = ipr_scsi_done;
ipr_cmd->done = ipr_scsi_eh_done;

if (ipr_is_gscsi(res) || ipr_is_vset_device(res)) {
if (scsi_cmd->underflow == 0)
Expand Down
1 change: 1 addition & 0 deletions drivers/scsi/ipr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1525,6 +1525,7 @@ struct ipr_cmnd {
struct ata_queued_cmd *qc;
struct completion completion;
struct timer_list timer;
void (*fast_done) (struct ipr_cmnd *);
void (*done) (struct ipr_cmnd *);
int (*job_step) (struct ipr_cmnd *);
int (*job_step_failed) (struct ipr_cmnd *);
Expand Down

0 comments on commit 172cd6e

Please sign in to comment.