forked from Minki/linux
SCSI fixes on 20150802
A set of three fixes for the ipr driver and one fairly major one for memory leaks in the mq path of SCSI. Signed-off-by: James Bottomley <JBottomley@Odin.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQEcBAABAgAGBQJVvkKdAAoJEDeqqVYsXL0McOkH/3JRKdIqfI1vOWG5kje0f2DJ qWwLZ68iG2t31Y8vdrSgT94/gfX3PH6rQ3yxuXDvr+oupTSoAyYR2D/R5zTOvusC pKvYZSE74yUD23J6Www5WlkTZpSzbSknm7Hj6UkIkHW0+Ihk53pWfQReLbAWpY7h MiMG7hqEnQEW2Wsp3SVD5jVy/tDyt2IeRZxcAqgBo5aU5xXzre0Kj8ya7hBZRCO0 cJaZjLPSJwapAzrqU2X7dOTCAojiMkDmHA4wGDmCtbdST6191JfOz8aiky7SJqnU ii4kZLf2wPDUxmRYIJJnY8IweN+VMu7vAvCo2GbeJebpIgu8ZsjHd/9X/6XF0v4= =oAZ+ -----END PGP SIGNATURE----- Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi Pull SCSI fixes from James Bottomley: "A set of three fixes for the ipr driver and one fairly major one for memory leaks in the mq path of SCSI" * tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: scsi: fix memory leak with scsi-mq ipr: Fix invalid array indexing for HRRQ ipr: Fix incorrect trace indexing ipr: Fix locking for unit attention handling
This commit is contained in:
commit
d4edea4038
@ -599,9 +599,10 @@ static void ipr_trc_hook(struct ipr_cmnd *ipr_cmd,
|
||||
{
|
||||
struct ipr_trace_entry *trace_entry;
|
||||
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
|
||||
unsigned int trace_index;
|
||||
|
||||
trace_entry = &ioa_cfg->trace[atomic_add_return
|
||||
(1, &ioa_cfg->trace_index)%IPR_NUM_TRACE_ENTRIES];
|
||||
trace_index = atomic_add_return(1, &ioa_cfg->trace_index) & IPR_TRACE_INDEX_MASK;
|
||||
trace_entry = &ioa_cfg->trace[trace_index];
|
||||
trace_entry->time = jiffies;
|
||||
trace_entry->op_code = ipr_cmd->ioarcb.cmd_pkt.cdb[0];
|
||||
trace_entry->type = type;
|
||||
@ -1051,10 +1052,15 @@ static void ipr_send_blocking_cmd(struct ipr_cmnd *ipr_cmd,
|
||||
|
||||
static int ipr_get_hrrq_index(struct ipr_ioa_cfg *ioa_cfg)
|
||||
{
|
||||
unsigned int hrrq;
|
||||
|
||||
if (ioa_cfg->hrrq_num == 1)
|
||||
return 0;
|
||||
else
|
||||
return (atomic_add_return(1, &ioa_cfg->hrrq_index) % (ioa_cfg->hrrq_num - 1)) + 1;
|
||||
hrrq = 0;
|
||||
else {
|
||||
hrrq = atomic_add_return(1, &ioa_cfg->hrrq_index);
|
||||
hrrq = (hrrq % (ioa_cfg->hrrq_num - 1)) + 1;
|
||||
}
|
||||
return hrrq;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -6263,21 +6269,23 @@ 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 hrrq_flags;
|
||||
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(scsi_cmd);
|
||||
|
||||
spin_lock_irqsave(ipr_cmd->hrrq->lock, hrrq_flags);
|
||||
spin_lock_irqsave(ipr_cmd->hrrq->lock, lock_flags);
|
||||
list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
|
||||
scsi_cmd->scsi_done(scsi_cmd);
|
||||
spin_unlock_irqrestore(ipr_cmd->hrrq->lock, hrrq_flags);
|
||||
spin_unlock_irqrestore(ipr_cmd->hrrq->lock, lock_flags);
|
||||
} else {
|
||||
spin_lock_irqsave(ipr_cmd->hrrq->lock, hrrq_flags);
|
||||
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
|
||||
spin_lock(&ipr_cmd->hrrq->_lock);
|
||||
ipr_erp_start(ioa_cfg, ipr_cmd);
|
||||
spin_unlock_irqrestore(ipr_cmd->hrrq->lock, hrrq_flags);
|
||||
spin_unlock(&ipr_cmd->hrrq->_lock);
|
||||
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1486,6 +1486,7 @@ struct ipr_ioa_cfg {
|
||||
|
||||
#define IPR_NUM_TRACE_INDEX_BITS 8
|
||||
#define IPR_NUM_TRACE_ENTRIES (1 << IPR_NUM_TRACE_INDEX_BITS)
|
||||
#define IPR_TRACE_INDEX_MASK (IPR_NUM_TRACE_ENTRIES - 1)
|
||||
#define IPR_TRACE_SIZE (sizeof(struct ipr_trace_entry) * IPR_NUM_TRACE_ENTRIES)
|
||||
char trace_start[8];
|
||||
#define IPR_TRACE_START_LABEL "trace"
|
||||
|
@ -944,7 +944,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
|
||||
scmd->sdb.length);
|
||||
scmd->sdb.table.sgl = &ses->sense_sgl;
|
||||
scmd->sc_data_direction = DMA_FROM_DEVICE;
|
||||
scmd->sdb.table.nents = 1;
|
||||
scmd->sdb.table.nents = scmd->sdb.table.orig_nents = 1;
|
||||
scmd->cmnd[0] = REQUEST_SENSE;
|
||||
scmd->cmnd[4] = scmd->sdb.length;
|
||||
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
|
||||
|
@ -583,7 +583,7 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask)
|
||||
|
||||
static void scsi_free_sgtable(struct scsi_data_buffer *sdb, bool mq)
|
||||
{
|
||||
if (mq && sdb->table.nents <= SCSI_MAX_SG_SEGMENTS)
|
||||
if (mq && sdb->table.orig_nents <= SCSI_MAX_SG_SEGMENTS)
|
||||
return;
|
||||
__sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free);
|
||||
}
|
||||
@ -597,8 +597,8 @@ static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, bool mq)
|
||||
|
||||
if (mq) {
|
||||
if (nents <= SCSI_MAX_SG_SEGMENTS) {
|
||||
sdb->table.nents = nents;
|
||||
sg_init_table(sdb->table.sgl, sdb->table.nents);
|
||||
sdb->table.nents = sdb->table.orig_nents = nents;
|
||||
sg_init_table(sdb->table.sgl, nents);
|
||||
return 0;
|
||||
}
|
||||
first_chunk = sdb->table.sgl;
|
||||
|
Loading…
Reference in New Issue
Block a user