Commit 9ba56b95 authored by Giridhar Malavali's avatar Giridhar Malavali Committed by James Bottomley

[SCSI] qla2xxx: Consolidation of SRB processing.

Rework the structures related to SRB processing to minimize the memory
allocations per I/O and manage resources associated with and completions
from common routines.
Signed-off-by: default avatarGiridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: default avatarChad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 69e5f1ea
...@@ -11,29 +11,36 @@ ...@@ -11,29 +11,36 @@
#include <linux/delay.h> #include <linux/delay.h>
/* BSG support for ELS/CT pass through */ /* BSG support for ELS/CT pass through */
inline srb_t * void
qla2x00_get_ctx_bsg_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size) qla2x00_bsg_job_done(void *data, void *ptr, int res)
{ {
srb_t *sp; srb_t *sp = (srb_t *)ptr;
struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
struct fc_bsg_job *bsg_job = sp->u.bsg_job;
bsg_job->reply->result = res;
bsg_job->job_done(bsg_job);
sp->free(vha, sp);
}
void
qla2x00_bsg_sp_free(void *data, void *ptr)
{
srb_t *sp = (srb_t *)ptr;
struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
struct fc_bsg_job *bsg_job = sp->u.bsg_job;
struct qla_hw_data *ha = vha->hw; struct qla_hw_data *ha = vha->hw;
struct srb_ctx *ctx;
sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL); dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
if (!sp) bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
goto done;
ctx = kzalloc(size, GFP_KERNEL);
if (!ctx) {
mempool_free(sp, ha->srb_mempool);
sp = NULL;
goto done;
}
memset(sp, 0, sizeof(*sp)); dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
sp->fcport = fcport; bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
sp->ctx = ctx;
ctx->iocbs = 1; if (sp->type == SRB_CT_CMD ||
done: sp->type == SRB_ELS_CMD_HST)
return sp; kfree(sp->fcport);
mempool_free(sp, vha->hw->srb_mempool);
} }
int int
...@@ -217,6 +224,7 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job) ...@@ -217,6 +224,7 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
bsg_job->job_done(bsg_job); bsg_job->job_done(bsg_job);
return ret; return ret;
} }
static int static int
qla2x00_process_els(struct fc_bsg_job *bsg_job) qla2x00_process_els(struct fc_bsg_job *bsg_job)
{ {
...@@ -230,7 +238,6 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) ...@@ -230,7 +238,6 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
int req_sg_cnt, rsp_sg_cnt; int req_sg_cnt, rsp_sg_cnt;
int rval = (DRIVER_ERROR << 16); int rval = (DRIVER_ERROR << 16);
uint16_t nextlid = 0; uint16_t nextlid = 0;
struct srb_ctx *els;
if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) { if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) {
rport = bsg_job->rport; rport = bsg_job->rport;
...@@ -337,20 +344,21 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) ...@@ -337,20 +344,21 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
} }
/* Alloc SRB structure */ /* Alloc SRB structure */
sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_ctx)); sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp) { if (!sp) {
rval = -ENOMEM; rval = -ENOMEM;
goto done_unmap_sg; goto done_unmap_sg;
} }
els = sp->ctx; sp->type =
els->type =
(bsg_job->request->msgcode == FC_BSG_RPT_ELS ? (bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST); SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST);
els->name = sp->name =
(bsg_job->request->msgcode == FC_BSG_RPT_ELS ? (bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
"bsg_els_rpt" : "bsg_els_hst"); "bsg_els_rpt" : "bsg_els_hst");
els->u.bsg_job = bsg_job; sp->u.bsg_job = bsg_job;
sp->free = qla2x00_bsg_sp_free;
sp->done = qla2x00_bsg_job_done;
ql_dbg(ql_dbg_user, vha, 0x700a, ql_dbg(ql_dbg_user, vha, 0x700a,
"bsg rqst type: %s els type: %x - loop-id=%x " "bsg rqst type: %s els type: %x - loop-id=%x "
...@@ -362,7 +370,6 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) ...@@ -362,7 +370,6 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
if (rval != QLA_SUCCESS) { if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x700e, ql_log(ql_log_warn, vha, 0x700e,
"qla2x00_start_sp failed = %d\n", rval); "qla2x00_start_sp failed = %d\n", rval);
kfree(sp->ctx);
mempool_free(sp, ha->srb_mempool); mempool_free(sp, ha->srb_mempool);
rval = -EIO; rval = -EIO;
goto done_unmap_sg; goto done_unmap_sg;
...@@ -409,7 +416,6 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job) ...@@ -409,7 +416,6 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
uint16_t loop_id; uint16_t loop_id;
struct fc_port *fcport; struct fc_port *fcport;
char *type = "FC_BSG_HST_CT"; char *type = "FC_BSG_HST_CT";
struct srb_ctx *ct;
req_sg_cnt = req_sg_cnt =
dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
...@@ -486,19 +492,20 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job) ...@@ -486,19 +492,20 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
fcport->loop_id = loop_id; fcport->loop_id = loop_id;
/* Alloc SRB structure */ /* Alloc SRB structure */
sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_ctx)); sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp) { if (!sp) {
ql_log(ql_log_warn, vha, 0x7015, ql_log(ql_log_warn, vha, 0x7015,
"qla2x00_get_ctx_bsg_sp failed.\n"); "qla2x00_get_sp failed.\n");
rval = -ENOMEM; rval = -ENOMEM;
goto done_free_fcport; goto done_free_fcport;
} }
ct = sp->ctx; sp->type = SRB_CT_CMD;
ct->type = SRB_CT_CMD; sp->name = "bsg_ct";
ct->name = "bsg_ct"; sp->iocbs = qla24xx_calc_ct_iocbs(req_sg_cnt + rsp_sg_cnt);
ct->iocbs = qla24xx_calc_ct_iocbs(req_sg_cnt + rsp_sg_cnt); sp->u.bsg_job = bsg_job;
ct->u.bsg_job = bsg_job; sp->free = qla2x00_bsg_sp_free;
sp->done = qla2x00_bsg_job_done;
ql_dbg(ql_dbg_user, vha, 0x7016, ql_dbg(ql_dbg_user, vha, 0x7016,
"bsg rqst type: %s else type: %x - " "bsg rqst type: %s else type: %x - "
...@@ -511,7 +518,6 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job) ...@@ -511,7 +518,6 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
if (rval != QLA_SUCCESS) { if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x7017, ql_log(ql_log_warn, vha, 0x7017,
"qla2x00_start_sp failed=%d.\n", rval); "qla2x00_start_sp failed=%d.\n", rval);
kfree(sp->ctx);
mempool_free(sp, ha->srb_mempool); mempool_free(sp, ha->srb_mempool);
rval = -EIO; rval = -EIO;
goto done_free_fcport; goto done_free_fcport;
...@@ -1669,7 +1675,6 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job) ...@@ -1669,7 +1675,6 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
int cnt, que; int cnt, que;
unsigned long flags; unsigned long flags;
struct req_que *req; struct req_que *req;
struct srb_ctx *sp_bsg;
/* find the bsg job from the active list of commands */ /* find the bsg job from the active list of commands */
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
...@@ -1681,11 +1686,9 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job) ...@@ -1681,11 +1686,9 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
sp = req->outstanding_cmds[cnt]; sp = req->outstanding_cmds[cnt];
if (sp) { if (sp) {
sp_bsg = sp->ctx; if (((sp->type == SRB_CT_CMD) ||
(sp->type == SRB_ELS_CMD_HST))
if (((sp_bsg->type == SRB_CT_CMD) || && (sp->u.bsg_job == bsg_job)) {
(sp_bsg->type == SRB_ELS_CMD_HST))
&& (sp_bsg->u.bsg_job == bsg_job)) {
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (ha->isp_ops->abort_command(sp)) { if (ha->isp_ops->abort_command(sp)) {
ql_log(ql_log_warn, vha, 0x7089, ql_log(ql_log_warn, vha, 0x7089,
...@@ -1715,7 +1718,6 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job) ...@@ -1715,7 +1718,6 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (bsg_job->request->msgcode == FC_BSG_HST_CT) if (bsg_job->request->msgcode == FC_BSG_HST_CT)
kfree(sp->fcport); kfree(sp->fcport);
kfree(sp->ctx);
mempool_free(sp, ha->srb_mempool); mempool_free(sp, ha->srb_mempool);
return 0; return 0;
} }
...@@ -14,10 +14,11 @@ ...@@ -14,10 +14,11 @@
* | Module Init and Probe | 0x011f | 0x4b,0xfa | * | Module Init and Probe | 0x011f | 0x4b,0xfa |
* | Mailbox commands | 0x1139 | 0x112c-0x112e | * | Mailbox commands | 0x1139 | 0x112c-0x112e |
* | Device Discovery | 0x2084 | | * | Device Discovery | 0x2084 | |
* | Queue Command and IO tracing | 0x302f | 0x3008 | * | Queue Command and IO tracing | 0x302f | 0x3006,0x3008 |
* | | | 0x302d-0x302e | * | | | 0x302d-0x302e |
* | DPC Thread | 0x401c | | * | DPC Thread | 0x401c | |
* | Async Events | 0x5057 | 0x5052 | * | Async Events | 0x5057 | 0x502b-0x502f |
* | | | 0x5047,0x5052 |
* | Timer Routines | 0x6011 | 0x600e-0x600f | * | Timer Routines | 0x6011 | 0x600e-0x600f |
* | User Space Interactions | 0x709e | 0x7018,0x702e | * | User Space Interactions | 0x709e | 0x7018,0x702e |
* | | | 0x7039,0x7045 | * | | | 0x7039,0x7045 |
......
...@@ -202,20 +202,12 @@ struct sd_dif_tuple { ...@@ -202,20 +202,12 @@ struct sd_dif_tuple {
/* /*
* SCSI Request Block * SCSI Request Block
*/ */
typedef struct srb { struct srb_cmd {
atomic_t ref_count;
struct fc_port *fcport;
uint32_t handle;
struct scsi_cmnd *cmd; /* Linux SCSI command pkt */ struct scsi_cmnd *cmd; /* Linux SCSI command pkt */
uint16_t flags;
uint32_t request_sense_length; uint32_t request_sense_length;
uint8_t *request_sense_ptr; uint8_t *request_sense_ptr;
void *ctx; void *ctx;
} srb_t; };
/* /*
* SRB flag definitions * SRB flag definitions
...@@ -254,10 +246,7 @@ struct srb_iocb { ...@@ -254,10 +246,7 @@ struct srb_iocb {
} u; } u;
struct timer_list timer; struct timer_list timer;
void (*timeout)(void *);
void (*done)(srb_t *);
void (*free)(srb_t *);
void (*timeout)(srb_t *);
}; };
/* Values for srb_ctx type */ /* Values for srb_ctx type */
...@@ -268,16 +257,37 @@ struct srb_iocb { ...@@ -268,16 +257,37 @@ struct srb_iocb {
#define SRB_CT_CMD 5 #define SRB_CT_CMD 5
#define SRB_ADISC_CMD 6 #define SRB_ADISC_CMD 6
#define SRB_TM_CMD 7 #define SRB_TM_CMD 7
#define SRB_SCSI_CMD 8
struct srb_ctx { typedef struct srb {
atomic_t ref_count;
struct fc_port *fcport;
uint32_t handle;
uint16_t flags;
uint16_t type; uint16_t type;
char *name; char *name;
int iocbs; int iocbs;
union { union {
struct srb_iocb *iocb_cmd; struct srb_iocb iocb_cmd;
struct fc_bsg_job *bsg_job; struct fc_bsg_job *bsg_job;
struct srb_cmd scmd;
} u; } u;
}; void (*done)(void *, void *, int);
void (*free)(void *, void *);
} srb_t;
#define GET_CMD_SP(sp) (sp->u.scmd.cmd)
#define SET_CMD_SP(sp, cmd) (sp->u.scmd.cmd = cmd)
#define GET_CMD_CTX_SP(sp) (sp->u.scmd.ctx)
#define GET_CMD_SENSE_LEN(sp) \
(sp->u.scmd.request_sense_length)
#define SET_CMD_SENSE_LEN(sp, len) \
(sp->u.scmd.request_sense_length = len)
#define GET_CMD_SENSE_PTR(sp) \
(sp->u.scmd.request_sense_ptr)
#define SET_CMD_SENSE_PTR(sp, ptr) \
(sp->u.scmd.request_sense_ptr = ptr)
struct msg_echo_lb { struct msg_echo_lb {
dma_addr_t send_dma; dma_addr_t send_dma;
......
...@@ -71,8 +71,6 @@ extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *, ...@@ -71,8 +71,6 @@ extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
uint16_t *); uint16_t *);
extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *, extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
uint16_t *); uint16_t *);
extern void qla2x00_async_tm_cmd_done(struct scsi_qla_host *, fc_port_t *,
struct srb_iocb *);
extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *); extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *);
extern int qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *, fc_port_t *); extern int qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *, fc_port_t *);
...@@ -156,8 +154,7 @@ extern void qla2x00_do_dpc_all_vps(scsi_qla_host_t *); ...@@ -156,8 +154,7 @@ extern void qla2x00_do_dpc_all_vps(scsi_qla_host_t *);
extern int qla24xx_vport_create_req_sanity_check(struct fc_vport *); extern int qla24xx_vport_create_req_sanity_check(struct fc_vport *);
extern scsi_qla_host_t * qla24xx_create_vhost(struct fc_vport *); extern scsi_qla_host_t * qla24xx_create_vhost(struct fc_vport *);
extern void qla2x00_sp_compl(struct qla_hw_data *, srb_t *); extern void qla2x00_sp_free_dma(void *, void *);
extern char *qla2x00_get_fw_version_str(struct scsi_qla_host *, char *); extern char *qla2x00_get_fw_version_str(struct scsi_qla_host *, char *);
extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int); extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int);
...@@ -542,6 +539,10 @@ extern int qla82xx_restart_isp(scsi_qla_host_t *); ...@@ -542,6 +539,10 @@ extern int qla82xx_restart_isp(scsi_qla_host_t *);
/* IOCB related functions */ /* IOCB related functions */
extern int qla82xx_start_scsi(srb_t *); extern int qla82xx_start_scsi(srb_t *);
extern void qla2x00_sp_free(void *, void *);
extern void qla2x00_sp_timeout(unsigned long);
extern void qla2x00_bsg_job_done(void *, void *, int);
extern void qla2x00_bsg_sp_free(void *, void *);
/* Interrupt related */ /* Interrupt related */
extern irqreturn_t qla82xx_intr_handler(int, void *); extern irqreturn_t qla82xx_intr_handler(int, void *);
......
This diff is collapsed.
...@@ -72,16 +72,19 @@ static inline void ...@@ -72,16 +72,19 @@ static inline void
qla2x00_clean_dsd_pool(struct qla_hw_data *ha, srb_t *sp) qla2x00_clean_dsd_pool(struct qla_hw_data *ha, srb_t *sp)
{ {
struct dsd_dma *dsd_ptr, *tdsd_ptr; struct dsd_dma *dsd_ptr, *tdsd_ptr;
struct crc_context *ctx;
ctx = (struct crc_context *)GET_CMD_CTX_SP(sp);
/* clean up allocated prev pool */ /* clean up allocated prev pool */
list_for_each_entry_safe(dsd_ptr, tdsd_ptr, list_for_each_entry_safe(dsd_ptr, tdsd_ptr,
&((struct crc_context *)sp->ctx)->dsd_list, list) { &ctx->dsd_list, list) {
dma_pool_free(ha->dl_dma_pool, dsd_ptr->dsd_addr, dma_pool_free(ha->dl_dma_pool, dsd_ptr->dsd_addr,
dsd_ptr->dsd_list_dma); dsd_ptr->dsd_list_dma);
list_del(&dsd_ptr->list); list_del(&dsd_ptr->list);
kfree(dsd_ptr); kfree(dsd_ptr);
} }
INIT_LIST_HEAD(&((struct crc_context *)sp->ctx)->dsd_list); INIT_LIST_HEAD(&ctx->dsd_list);
} }
static inline void static inline void
...@@ -113,8 +116,7 @@ qla2x00_hba_err_chk_enabled(srb_t *sp) ...@@ -113,8 +116,7 @@ qla2x00_hba_err_chk_enabled(srb_t *sp)
return 0; return 0;
* *
*/ */
switch (scsi_get_prot_op(GET_CMD_SP(sp))) {
switch (scsi_get_prot_op(sp->cmd)) {
case SCSI_PROT_READ_STRIP: case SCSI_PROT_READ_STRIP:
case SCSI_PROT_WRITE_INSERT: case SCSI_PROT_WRITE_INSERT:
if (ql2xenablehba_err_chk >= 1) if (ql2xenablehba_err_chk >= 1)
...@@ -144,3 +146,38 @@ qla2x00_reset_active(scsi_qla_host_t *vha) ...@@ -144,3 +146,38 @@ qla2x00_reset_active(scsi_qla_host_t *vha)
test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) || test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags); test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
} }
static inline srb_t *
qla2x00_get_sp(scsi_qla_host_t *vha, fc_port_t *fcport, gfp_t flag)
{
srb_t *sp = NULL;
struct qla_hw_data *ha = vha->hw;
uint8_t bail;
QLA_VHA_MARK_BUSY(vha, bail);
if (unlikely(bail))
return NULL;
sp = mempool_alloc(ha->srb_mempool, flag);
if (!sp)
goto done;
memset(sp, 0, sizeof(*sp));
sp->fcport = fcport;
sp->iocbs = 1;
done:
if (!sp)
QLA_VHA_MARK_NOT_BUSY(vha);
return sp;
}
static inline void
qla2x00_init_timer(srb_t *sp, unsigned long tmo)
{
init_timer(&sp->u.iocb_cmd.timer);
sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ;
sp->u.iocb_cmd.timer.data = (unsigned long)sp;
sp->u.iocb_cmd.timer.function = qla2x00_sp_timeout;
add_timer(&sp->u.iocb_cmd.timer);
sp->free = qla2x00_sp_free;
}
This diff is collapsed.
This diff is collapsed.
...@@ -874,6 +874,7 @@ qla2x00_abort_command(srb_t *sp) ...@@ -874,6 +874,7 @@ qla2x00_abort_command(srb_t *sp)
scsi_qla_host_t *vha = fcport->vha; scsi_qla_host_t *vha = fcport->vha;
struct qla_hw_data *ha = vha->hw; struct qla_hw_data *ha = vha->hw;
struct req_que *req = vha->req; struct req_que *req = vha->req;
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
ql_dbg(ql_dbg_mbx, vha, 0x103b, "Entered %s.\n", __func__); ql_dbg(ql_dbg_mbx, vha, 0x103b, "Entered %s.\n", __func__);
...@@ -896,7 +897,7 @@ qla2x00_abort_command(srb_t *sp) ...@@ -896,7 +897,7 @@ qla2x00_abort_command(srb_t *sp)
mcp->mb[1] = fcport->loop_id << 8; mcp->mb[1] = fcport->loop_id << 8;
mcp->mb[2] = (uint16_t)handle; mcp->mb[2] = (uint16_t)handle;
mcp->mb[3] = (uint16_t)(handle >> 16); mcp->mb[3] = (uint16_t)(handle >> 16);
mcp->mb[6] = (uint16_t)sp->cmd->device->lun; mcp->mb[6] = (uint16_t)cmd->device->lun;
mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_0; mcp->in_mb = MBX_0;
mcp->tov = MBX_TOV_SECONDS; mcp->tov = MBX_TOV_SECONDS;
......
...@@ -3608,7 +3608,7 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha) ...@@ -3608,7 +3608,7 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha)
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
sp = req->outstanding_cmds[cnt]; sp = req->outstanding_cmds[cnt];
if (sp) { if (sp) {
if (!sp->ctx || if (!sp->u.scmd.ctx ||
(sp->flags & SRB_FCP_CMND_DMA_VALID)) { (sp->flags & SRB_FCP_CMND_DMA_VALID)) {
spin_unlock_irqrestore( spin_unlock_irqrestore(
&ha->hardware_lock, flags); &ha->hardware_lock, flags);
......
...@@ -304,7 +304,6 @@ static int qla2x00_mem_alloc(struct qla_hw_data *, uint16_t, uint16_t, ...@@ -304,7 +304,6 @@ static int qla2x00_mem_alloc(struct qla_hw_data *, uint16_t, uint16_t,
struct req_que **, struct rsp_que **); struct req_que **, struct rsp_que **);
static void qla2x00_free_fw_dump(struct qla_hw_data *); static void qla2x00_free_fw_dump(struct qla_hw_data *);
static void qla2x00_mem_free(struct qla_hw_data *); static void qla2x00_mem_free(struct qla_hw_data *);
static void qla2x00_sp_free_dma(srb_t *);
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
static int qla2x00_alloc_queues(struct qla_hw_data *ha) static int qla2x00_alloc_queues(struct qla_hw_data *ha)
...@@ -559,28 +558,75 @@ qla24xx_fw_version_str(struct scsi_qla_host *vha, char *str) ...@@ -559,28 +558,75 @@ qla24xx_fw_version_str(struct scsi_qla_host *vha, char *str)
return str; return str;
} }
static inline srb_t * void
qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport, qla2x00_sp_free_dma(void *vha, void *ptr)
struct scsi_cmnd *cmd)
{ {
srb_t *sp; srb_t *sp = (srb_t *)ptr;
struct qla_hw_data *ha = vha->hw; struct scsi_cmnd *cmd = GET_CMD_SP(sp);
struct qla_hw_data *ha = sp->fcport->vha->hw;
void *ctx = GET_CMD_CTX_SP(sp);
sp = mempool_alloc(ha->srb_mempool, GFP_ATOMIC); if (sp->flags & SRB_DMA_VALID) {
if (!sp) { scsi_dma_unmap(cmd);
ql_log(ql_log_warn, vha, 0x3006, sp->flags &= ~SRB_DMA_VALID;
"Memory allocation failed for sp.\n");
return sp;
} }
atomic_set(&sp->ref_count, 1); if (sp->flags & SRB_CRC_PROT_DMA_VALID) {
sp->fcport = fcport; dma_unmap_sg(&ha->pdev->dev, scsi_prot_sglist(cmd),
sp->cmd = cmd; scsi_prot_sg_count(cmd), cmd->sc_data_direction);
sp->flags = 0; sp->flags &= ~SRB_CRC_PROT_DMA_VALID;
CMD_SP(cmd) = (void *)sp; }
sp->ctx = NULL;
if (sp->flags & SRB_CRC_CTX_DSD_VALID) {
/* List assured to be having elements */
qla2x00_clean_dsd_pool(ha, sp);
sp->flags &= ~SRB_CRC_CTX_DSD_VALID;
}
if (sp->flags & SRB_CRC_CTX_DMA_VALID) {
dma_pool_free(ha->dl_dma_pool, ctx,
((struct crc_context *)ctx)->crc_ctx_dma);
sp->flags &= ~SRB_CRC_CTX_DMA_VALID;
}
if (sp->flags & SRB_FCP_CMND_DMA_VALID) {
struct ct6_dsd *ctx1 = (struct ct6_dsd *)ctx;
dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd,
ctx1->fcp_cmnd_dma);
list_splice(&ctx1->dsd_list, &ha->gbl_dsd_list);
ha->gbl_dsd_inuse -= ctx1->dsd_use_cnt;
ha->gbl_dsd_avail += ctx1->dsd_use_cnt;
mempool_free(ctx1, ha->ctx_mempool);
ctx1 = NULL;
}
CMD_SP(cmd) = NULL;
mempool_free(sp, ha->srb_mempool);
}
static void
qla2x00_sp_compl(void *data, void *ptr, int res)
{
struct qla_hw_data *ha = (struct qla_hw_data *)data;
srb_t *sp = (srb_t *)ptr;
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
cmd->result = res;
if (atomic_read(&sp->ref_count) == 0) {
ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3015,
"SP reference-count to ZERO -- sp=%p cmd=%p.\n",
sp, GET_CMD_SP(sp));
if (ql2xextended_error_logging & ql_dbg_io)
BUG();
return;
}
if (!atomic_dec_and_test(&sp->ref_count))
return;
return sp; qla2x00_sp_free_dma(ha, sp);
cmd->scsi_done(cmd);
} }
static int static int
...@@ -644,10 +690,17 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) ...@@ -644,10 +690,17 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
goto qc24_target_busy; goto qc24_target_busy;
} }
sp = qla2x00_get_new_sp(base_vha, fcport, cmd); sp = qla2x00_get_sp(base_vha, fcport, GFP_ATOMIC);
if (!sp) if (!sp)
goto qc24_host_busy; goto qc24_host_busy;
sp->u.scmd.cmd = cmd;
sp->type = SRB_SCSI_CMD;
atomic_set(&sp->ref_count, 1);
CMD_SP(cmd) = (void *)sp;
sp->free = qla2x00_sp_free_dma;
sp->done = qla2x00_sp_compl;
rval = ha->isp_ops->start_scsi(sp); rval = ha->isp_ops->start_scsi(sp);
if (rval != QLA_SUCCESS) { if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_io, vha, 0x3013, ql_dbg(ql_dbg_io, vha, 0x3013,
...@@ -658,8 +711,7 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) ...@@ -658,8 +711,7 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
return 0; return 0;
qc24_host_busy_free_sp: qc24_host_busy_free_sp:
qla2x00_sp_free_dma(sp); qla2x00_sp_free_dma(ha, sp);
mempool_free(sp, ha->srb_mempool);
qc24_host_busy: qc24_host_busy:
return SCSI_MLQUEUE_HOST_BUSY; return SCSI_MLQUEUE_HOST_BUSY;
...@@ -893,7 +945,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) ...@@ -893,7 +945,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
} }
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
qla2x00_sp_compl(ha, sp); sp->done(ha, sp, 0);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->hardware_lock, flags);
/* Did the command return during mailbox execution? */ /* Did the command return during mailbox execution? */
...@@ -925,6 +977,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t, ...@@ -925,6 +977,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
struct qla_hw_data *ha = vha->hw; struct qla_hw_data *ha = vha->hw;
struct req_que *req; struct req_que *req;
srb_t *sp; srb_t *sp;
struct scsi_cmnd *cmd;
status = QLA_SUCCESS; status = QLA_SUCCESS;
...@@ -935,28 +988,29 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t, ...@@ -935,28 +988,29 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
sp = req->outstanding_cmds[cnt]; sp = req->outstanding_cmds[cnt];
if (!sp) if (!sp)
continue; continue;
if ((sp->ctx) && !IS_PROT_IO(sp)) if (sp->type != SRB_SCSI_CMD)
continue; continue;
if (vha->vp_idx != sp->fcport->vha->vp_idx) if (vha->vp_idx != sp->fcport->vha->vp_idx)
continue; continue;
match = 0; match = 0;
cmd = GET_CMD_SP(sp);
switch (type) { switch (type) {
case WAIT_HOST: case WAIT_HOST:
match = 1; match = 1;
break; break;
case WAIT_TARGET: case WAIT_TARGET:
match = sp->cmd->device->id == t; match = cmd->device->id == t;
break; break;
case WAIT_LUN: case WAIT_LUN:
match = (sp->cmd->device->id == t && match = (cmd->device->id == t &&
sp->cmd->device->lun == l); cmd->device->lun == l);
break; break;
} }
if (!match) if (!match)
continue; continue;
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->hardware_lock, flags);
status = qla2x00_eh_wait_on_command(sp->cmd); status = qla2x00_eh_wait_on_command(cmd);
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
} }
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->hardware_lock, flags);
...@@ -1249,7 +1303,6 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) ...@@ -1249,7 +1303,6 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
int que, cnt; int que, cnt;
unsigned long flags; unsigned long flags;
srb_t *sp; srb_t *sp;
struct srb_ctx *ctx;
struct qla_hw_data *ha = vha->hw; struct qla_hw_data *ha = vha->hw;
struct req_que *req; struct req_que *req;
...@@ -1262,31 +1315,7 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) ...@@ -1262,31 +1315,7 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
sp = req->outstanding_cmds[cnt]; sp = req->outstanding_cmds[cnt];
if (sp) { if (sp) {
req->outstanding_cmds[cnt] = NULL; req->outstanding_cmds[cnt] = NULL;
if (!sp->ctx || sp->done(vha, sp, res);
(sp->flags & SRB_FCP_CMND_DMA_VALID) ||
IS_PROT_IO(sp)) {
sp->cmd->result = res;
qla2x00_sp_compl(ha, sp);
} else {
ctx = sp->ctx;
if (ctx->type == SRB_ELS_CMD_RPT ||
ctx->type == SRB_ELS_CMD_HST ||
ctx->type == SRB_CT_CMD) {
struct fc_bsg_job *bsg_job =
ctx->u.bsg_job;
if (bsg_job->request->msgcode
== FC_BSG_HST_CT)
kfree(sp->fcport);
bsg_job->req->errors = 0;
bsg_job->reply->result = res;
bsg_job->job_done(bsg_job);
kfree(sp->ctx);
mempool_free(sp,
ha->srb_mempool);
} else {
ctx->u.iocb_cmd->free(sp);
}
}
} }
} }
} }
...@@ -3820,75 +3849,6 @@ qla2x00_rst_aen(scsi_qla_host_t *vha) ...@@ -3820,75 +3849,6 @@ qla2x00_rst_aen(scsi_qla_host_t *vha)
} }
} }
static void
qla2x00_sp_free_dma(srb_t *sp)
{
struct scsi_cmnd *cmd = sp->cmd;
struct qla_hw_data *ha = sp->fcport->vha->hw;
if (sp->flags & SRB_DMA_VALID) {
scsi_dma_unmap(cmd);
sp->flags &= ~SRB_DMA_VALID;
}
if (sp->flags & SRB_CRC_PROT_DMA_VALID) {
dma_unmap_sg(&ha->pdev->dev, scsi_prot_sglist(cmd),
scsi_prot_sg_count(cmd), cmd->sc_data_direction);
sp->flags &= ~SRB_CRC_PROT_DMA_VALID;
}
if (sp->flags & SRB_CRC_CTX_DSD_VALID) {
/* List assured to be having elements */
qla2x00_clean_dsd_pool(ha, sp);
sp->flags &= ~SRB_CRC_CTX_DSD_VALID;
}
if (sp->flags & SRB_CRC_CTX_DMA_VALID) {
dma_pool_free(ha->dl_dma_pool, sp->ctx,
((struct crc_context *)sp->ctx)->crc_ctx_dma);
sp->flags &= ~SRB_CRC_CTX_DMA_VALID;
}
if (sp->flags & SRB_FCP_CMND_DMA_VALID) {
struct ct6_dsd *ctx = sp->ctx;
dma_pool_free(ha->fcp_cmnd_dma_pool, ctx->fcp_cmnd,
ctx->fcp_cmnd_dma);
list_splice(&ctx->dsd_list, &ha->gbl_dsd_list);
ha->gbl_dsd_inuse -= ctx->dsd_use_cnt;
ha->gbl_dsd_avail += ctx->dsd_use_cnt;
mempool_free(sp->ctx, ha->ctx_mempool);
sp->ctx = NULL;
}
CMD_SP(cmd) = NULL;
}
static void
qla2x00_sp_final_compl(struct qla_hw_data *ha, srb_t *sp)
{
struct scsi_cmnd *cmd = sp->cmd;
qla2x00_sp_free_dma(sp);
mempool_free(sp, ha->srb_mempool);
cmd->scsi_done(cmd);
}
void
qla2x00_sp_compl(struct qla_hw_data *ha, srb_t *sp)
{
if (atomic_read(&sp->ref_count) == 0) {
ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3015,
"SP reference-count to ZERO -- sp=%p cmd=%p.\n",
sp, sp->cmd);
if (ql2xextended_error_logging & ql_dbg_io)
BUG();
return;
}
if (!atomic_dec_and_test(&sp->ref_count))
return;
qla2x00_sp_final_compl(ha, sp);
}
/************************************************************************** /**************************************************************************
* qla2x00_timer * qla2x00_timer
* *
...@@ -3959,7 +3919,7 @@ qla2x00_timer(scsi_qla_host_t *vha) ...@@ -3959,7 +3919,7 @@ qla2x00_timer(scsi_qla_host_t *vha)
sp = req->outstanding_cmds[index]; sp = req->outstanding_cmds[index];
if (!sp) if (!sp)
continue; continue;
if (sp->ctx && !IS_PROT_IO(sp)) if (sp->type != SRB_SCSI_CMD)
continue; continue;
sfcp = sp->fcport; sfcp = sp->fcport;
if (!(sfcp->flags & FCF_FCP2_DEVICE)) if (!(sfcp->flags & FCF_FCP2_DEVICE))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment