Commit d058bea1 authored by Martin K. Petersen's avatar Martin K. Petersen

Merge patch series "Misc. qla2xxx driver bug fixes"

Nilesh Javali <njavali@marvell.com> says:

Please apply the miscellaneous qla2xxx driver bug fixes to the SCSI
tree at your earliest convenience.

Link: https://lore.kernel.org/r/20221219110748.7039-1-njavali@marvell.comSigned-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parents 3d2f12b4 f590c255
...@@ -278,8 +278,8 @@ qla2x00_process_els(struct bsg_job *bsg_job) ...@@ -278,8 +278,8 @@ qla2x00_process_els(struct bsg_job *bsg_job)
const char *type; const char *type;
int req_sg_cnt, rsp_sg_cnt; int req_sg_cnt, rsp_sg_cnt;
int rval = (DID_ERROR << 16); int rval = (DID_ERROR << 16);
uint16_t nextlid = 0;
uint32_t els_cmd = 0; uint32_t els_cmd = 0;
int qla_port_allocated = 0;
if (bsg_request->msgcode == FC_BSG_RPT_ELS) { if (bsg_request->msgcode == FC_BSG_RPT_ELS) {
rport = fc_bsg_to_rport(bsg_job); rport = fc_bsg_to_rport(bsg_job);
...@@ -329,9 +329,9 @@ qla2x00_process_els(struct bsg_job *bsg_job) ...@@ -329,9 +329,9 @@ qla2x00_process_els(struct bsg_job *bsg_job)
/* make sure the rport is logged in, /* make sure the rport is logged in,
* if not perform fabric login * if not perform fabric login
*/ */
if (qla2x00_fabric_login(vha, fcport, &nextlid)) { if (atomic_read(&fcport->state) != FCS_ONLINE) {
ql_dbg(ql_dbg_user, vha, 0x7003, ql_dbg(ql_dbg_user, vha, 0x7003,
"Failed to login port %06X for ELS passthru.\n", "Port %06X is not online for ELS passthru.\n",
fcport->d_id.b24); fcport->d_id.b24);
rval = -EIO; rval = -EIO;
goto done; goto done;
...@@ -348,6 +348,7 @@ qla2x00_process_els(struct bsg_job *bsg_job) ...@@ -348,6 +348,7 @@ qla2x00_process_els(struct bsg_job *bsg_job)
goto done; goto done;
} }
qla_port_allocated = 1;
/* Initialize all required fields of fcport */ /* Initialize all required fields of fcport */
fcport->vha = vha; fcport->vha = vha;
fcport->d_id.b.al_pa = fcport->d_id.b.al_pa =
...@@ -432,7 +433,7 @@ qla2x00_process_els(struct bsg_job *bsg_job) ...@@ -432,7 +433,7 @@ qla2x00_process_els(struct bsg_job *bsg_job)
goto done_free_fcport; goto done_free_fcport;
done_free_fcport: done_free_fcport:
if (bsg_request->msgcode != FC_BSG_RPT_ELS) if (qla_port_allocated)
qla2x00_free_fcport(fcport); qla2x00_free_fcport(fcport);
done: done:
return rval; return rval;
......
...@@ -660,7 +660,7 @@ enum { ...@@ -660,7 +660,7 @@ enum {
struct iocb_resource { struct iocb_resource {
u8 res_type; u8 res_type;
u8 pad; u8 exch_cnt;
u16 iocb_cnt; u16 iocb_cnt;
}; };
...@@ -3721,6 +3721,10 @@ struct qla_fw_resources { ...@@ -3721,6 +3721,10 @@ struct qla_fw_resources {
u16 iocbs_limit; u16 iocbs_limit;
u16 iocbs_qp_limit; u16 iocbs_qp_limit;
u16 iocbs_used; u16 iocbs_used;
u16 exch_total;
u16 exch_limit;
u16 exch_used;
u16 pad;
}; };
#define QLA_IOCB_PCT_LIMIT 95 #define QLA_IOCB_PCT_LIMIT 95
......
...@@ -235,7 +235,7 @@ qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused) ...@@ -235,7 +235,7 @@ qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused)
uint16_t mb[MAX_IOCB_MB_REG]; uint16_t mb[MAX_IOCB_MB_REG];
int rc; int rc;
struct qla_hw_data *ha = vha->hw; struct qla_hw_data *ha = vha->hw;
u16 iocbs_used, i; u16 iocbs_used, i, exch_used;
rc = qla24xx_res_count_wait(vha, mb, SIZEOF_IOCB_MB_REG); rc = qla24xx_res_count_wait(vha, mb, SIZEOF_IOCB_MB_REG);
if (rc != QLA_SUCCESS) { if (rc != QLA_SUCCESS) {
...@@ -263,13 +263,19 @@ qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused) ...@@ -263,13 +263,19 @@ qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused)
if (ql2xenforce_iocb_limit) { if (ql2xenforce_iocb_limit) {
/* lock is not require. It's an estimate. */ /* lock is not require. It's an estimate. */
iocbs_used = ha->base_qpair->fwres.iocbs_used; iocbs_used = ha->base_qpair->fwres.iocbs_used;
exch_used = ha->base_qpair->fwres.exch_used;
for (i = 0; i < ha->max_qpairs; i++) { for (i = 0; i < ha->max_qpairs; i++) {
if (ha->queue_pair_map[i]) if (ha->queue_pair_map[i]) {
iocbs_used += ha->queue_pair_map[i]->fwres.iocbs_used; iocbs_used += ha->queue_pair_map[i]->fwres.iocbs_used;
exch_used += ha->queue_pair_map[i]->fwres.exch_used;
}
} }
seq_printf(s, "Driver: estimate iocb used [%d] high water limit [%d]\n", seq_printf(s, "Driver: estimate iocb used [%d] high water limit [%d]\n",
iocbs_used, ha->base_qpair->fwres.iocbs_limit); iocbs_used, ha->base_qpair->fwres.iocbs_limit);
seq_printf(s, "estimate exchange used[%d] high water limit [%d] n",
exch_used, ha->base_qpair->fwres.exch_limit);
} }
return 0; return 0;
......
...@@ -2989,9 +2989,10 @@ qla28xx_start_scsi_edif(srb_t *sp) ...@@ -2989,9 +2989,10 @@ qla28xx_start_scsi_edif(srb_t *sp)
tot_dsds = nseg; tot_dsds = nseg;
req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
sp->iores.res_type = RESOURCE_INI; sp->iores.res_type = RESOURCE_IOCB | RESOURCE_EXCH;
sp->iores.exch_cnt = 1;
sp->iores.iocb_cnt = req_cnt; sp->iores.iocb_cnt = req_cnt;
if (qla_get_iocbs(sp->qpair, &sp->iores)) if (qla_get_fw_resources(sp->qpair, &sp->iores))
goto queuing_error; goto queuing_error;
if (req->cnt < (req_cnt + 2)) { if (req->cnt < (req_cnt + 2)) {
...@@ -3185,7 +3186,7 @@ qla28xx_start_scsi_edif(srb_t *sp) ...@@ -3185,7 +3186,7 @@ qla28xx_start_scsi_edif(srb_t *sp)
mempool_free(sp->u.scmd.ct6_ctx, ha->ctx_mempool); mempool_free(sp->u.scmd.ct6_ctx, ha->ctx_mempool);
sp->u.scmd.ct6_ctx = NULL; sp->u.scmd.ct6_ctx = NULL;
} }
qla_put_iocbs(sp->qpair, &sp->iores); qla_put_fw_resources(sp->qpair, &sp->iores);
spin_unlock_irqrestore(lock, flags); spin_unlock_irqrestore(lock, flags);
return QLA_FUNCTION_FAILED; return QLA_FUNCTION_FAILED;
......
...@@ -128,12 +128,14 @@ static void qla24xx_abort_iocb_timeout(void *data) ...@@ -128,12 +128,14 @@ static void qla24xx_abort_iocb_timeout(void *data)
sp->cmd_sp)) { sp->cmd_sp)) {
qpair->req->outstanding_cmds[handle] = NULL; qpair->req->outstanding_cmds[handle] = NULL;
cmdsp_found = 1; cmdsp_found = 1;
qla_put_fw_resources(qpair, &sp->cmd_sp->iores);
} }
/* removing the abort */ /* removing the abort */
if (qpair->req->outstanding_cmds[handle] == sp) { if (qpair->req->outstanding_cmds[handle] == sp) {
qpair->req->outstanding_cmds[handle] = NULL; qpair->req->outstanding_cmds[handle] = NULL;
sp_found = 1; sp_found = 1;
qla_put_fw_resources(qpair, &sp->iores);
break; break;
} }
} }
...@@ -388,6 +390,12 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, ...@@ -388,6 +390,12 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
fcport->flags &= ~FCF_ASYNC_SENT; fcport->flags &= ~FCF_ASYNC_SENT;
done: done:
fcport->flags &= ~FCF_ASYNC_ACTIVE; fcport->flags &= ~FCF_ASYNC_ACTIVE;
/*
* async login failed. Could be due to iocb/exchange resource
* being low. Set state DELETED for re-login process to start again.
*/
qla2x00_set_fcport_disc_state(fcport, DSC_DELETED);
return rval; return rval;
} }
...@@ -2000,6 +2008,7 @@ qla2x00_tmf_iocb_timeout(void *data) ...@@ -2000,6 +2008,7 @@ qla2x00_tmf_iocb_timeout(void *data)
for (h = 1; h < sp->qpair->req->num_outstanding_cmds; h++) { for (h = 1; h < sp->qpair->req->num_outstanding_cmds; h++) {
if (sp->qpair->req->outstanding_cmds[h] == sp) { if (sp->qpair->req->outstanding_cmds[h] == sp) {
sp->qpair->req->outstanding_cmds[h] = NULL; sp->qpair->req->outstanding_cmds[h] = NULL;
qla_put_fw_resources(sp->qpair, &sp->iores);
break; break;
} }
} }
...@@ -2073,7 +2082,6 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, ...@@ -2073,7 +2082,6 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
done_free_sp: done_free_sp:
/* ref: INIT */ /* ref: INIT */
kref_put(&sp->cmd_kref, qla2x00_sp_release); kref_put(&sp->cmd_kref, qla2x00_sp_release);
fcport->flags &= ~FCF_ASYNC_SENT;
done: done:
return rval; return rval;
} }
...@@ -3943,6 +3951,12 @@ void qla_init_iocb_limit(scsi_qla_host_t *vha) ...@@ -3943,6 +3951,12 @@ void qla_init_iocb_limit(scsi_qla_host_t *vha)
ha->base_qpair->fwres.iocbs_limit = limit; ha->base_qpair->fwres.iocbs_limit = limit;
ha->base_qpair->fwres.iocbs_qp_limit = limit / num_qps; ha->base_qpair->fwres.iocbs_qp_limit = limit / num_qps;
ha->base_qpair->fwres.iocbs_used = 0; ha->base_qpair->fwres.iocbs_used = 0;
ha->base_qpair->fwres.exch_total = ha->orig_fw_xcb_count;
ha->base_qpair->fwres.exch_limit = (ha->orig_fw_xcb_count *
QLA_IOCB_PCT_LIMIT) / 100;
ha->base_qpair->fwres.exch_used = 0;
for (i = 0; i < ha->max_qpairs; i++) { for (i = 0; i < ha->max_qpairs; i++) {
if (ha->queue_pair_map[i]) { if (ha->queue_pair_map[i]) {
ha->queue_pair_map[i]->fwres.iocbs_total = ha->queue_pair_map[i]->fwres.iocbs_total =
...@@ -3951,6 +3965,10 @@ void qla_init_iocb_limit(scsi_qla_host_t *vha) ...@@ -3951,6 +3965,10 @@ void qla_init_iocb_limit(scsi_qla_host_t *vha)
ha->queue_pair_map[i]->fwres.iocbs_qp_limit = ha->queue_pair_map[i]->fwres.iocbs_qp_limit =
limit / num_qps; limit / num_qps;
ha->queue_pair_map[i]->fwres.iocbs_used = 0; ha->queue_pair_map[i]->fwres.iocbs_used = 0;
ha->queue_pair_map[i]->fwres.exch_total = ha->orig_fw_xcb_count;
ha->queue_pair_map[i]->fwres.exch_limit =
(ha->orig_fw_xcb_count * QLA_IOCB_PCT_LIMIT) / 100;
ha->queue_pair_map[i]->fwres.exch_used = 0;
} }
} }
} }
......
...@@ -380,24 +380,26 @@ qla2xxx_get_fc4_priority(struct scsi_qla_host *vha) ...@@ -380,24 +380,26 @@ qla2xxx_get_fc4_priority(struct scsi_qla_host *vha)
enum { enum {
RESOURCE_NONE, RESOURCE_NONE,
RESOURCE_INI, RESOURCE_IOCB = BIT_0,
RESOURCE_EXCH = BIT_1, /* exchange */
RESOURCE_FORCE = BIT_2,
}; };
static inline int static inline int
qla_get_iocbs(struct qla_qpair *qp, struct iocb_resource *iores) qla_get_fw_resources(struct qla_qpair *qp, struct iocb_resource *iores)
{ {
u16 iocbs_used, i; u16 iocbs_used, i;
u16 exch_used;
struct qla_hw_data *ha = qp->vha->hw; struct qla_hw_data *ha = qp->vha->hw;
if (!ql2xenforce_iocb_limit) { if (!ql2xenforce_iocb_limit) {
iores->res_type = RESOURCE_NONE; iores->res_type = RESOURCE_NONE;
return 0; return 0;
} }
if (iores->res_type & RESOURCE_FORCE)
goto force;
if ((iores->iocb_cnt + qp->fwres.iocbs_used) < qp->fwres.iocbs_qp_limit) { if ((iores->iocb_cnt + qp->fwres.iocbs_used) >= qp->fwres.iocbs_qp_limit) {
qp->fwres.iocbs_used += iores->iocb_cnt;
return 0;
} else {
/* no need to acquire qpair lock. It's just rough calculation */ /* no need to acquire qpair lock. It's just rough calculation */
iocbs_used = ha->base_qpair->fwres.iocbs_used; iocbs_used = ha->base_qpair->fwres.iocbs_used;
for (i = 0; i < ha->max_qpairs; i++) { for (i = 0; i < ha->max_qpairs; i++) {
...@@ -405,30 +407,49 @@ qla_get_iocbs(struct qla_qpair *qp, struct iocb_resource *iores) ...@@ -405,30 +407,49 @@ qla_get_iocbs(struct qla_qpair *qp, struct iocb_resource *iores)
iocbs_used += ha->queue_pair_map[i]->fwres.iocbs_used; iocbs_used += ha->queue_pair_map[i]->fwres.iocbs_used;
} }
if ((iores->iocb_cnt + iocbs_used) < qp->fwres.iocbs_limit) { if ((iores->iocb_cnt + iocbs_used) >= qp->fwres.iocbs_limit) {
qp->fwres.iocbs_used += iores->iocb_cnt; iores->res_type = RESOURCE_NONE;
return 0; return -ENOSPC;
} else { }
}
if (iores->res_type & RESOURCE_EXCH) {
exch_used = ha->base_qpair->fwres.exch_used;
for (i = 0; i < ha->max_qpairs; i++) {
if (ha->queue_pair_map[i])
exch_used += ha->queue_pair_map[i]->fwres.exch_used;
}
if ((exch_used + iores->exch_cnt) >= qp->fwres.exch_limit) {
iores->res_type = RESOURCE_NONE; iores->res_type = RESOURCE_NONE;
return -ENOSPC; return -ENOSPC;
} }
} }
force:
qp->fwres.iocbs_used += iores->iocb_cnt;
qp->fwres.exch_used += iores->exch_cnt;
return 0;
} }
static inline void static inline void
qla_put_iocbs(struct qla_qpair *qp, struct iocb_resource *iores) qla_put_fw_resources(struct qla_qpair *qp, struct iocb_resource *iores)
{ {
switch (iores->res_type) { if (iores->res_type & RESOURCE_IOCB) {
case RESOURCE_NONE:
break;
default:
if (qp->fwres.iocbs_used >= iores->iocb_cnt) { if (qp->fwres.iocbs_used >= iores->iocb_cnt) {
qp->fwres.iocbs_used -= iores->iocb_cnt; qp->fwres.iocbs_used -= iores->iocb_cnt;
} else { } else {
// should not happen /* should not happen */
qp->fwres.iocbs_used = 0; qp->fwres.iocbs_used = 0;
} }
break; }
if (iores->res_type & RESOURCE_EXCH) {
if (qp->fwres.exch_used >= iores->exch_cnt) {
qp->fwres.exch_used -= iores->exch_cnt;
} else {
/* should not happen */
qp->fwres.exch_used = 0;
}
} }
iores->res_type = RESOURCE_NONE; iores->res_type = RESOURCE_NONE;
} }
......
...@@ -1589,9 +1589,10 @@ qla24xx_start_scsi(srb_t *sp) ...@@ -1589,9 +1589,10 @@ qla24xx_start_scsi(srb_t *sp)
tot_dsds = nseg; tot_dsds = nseg;
req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
sp->iores.res_type = RESOURCE_INI; sp->iores.res_type = RESOURCE_IOCB | RESOURCE_EXCH;
sp->iores.exch_cnt = 1;
sp->iores.iocb_cnt = req_cnt; sp->iores.iocb_cnt = req_cnt;
if (qla_get_iocbs(sp->qpair, &sp->iores)) if (qla_get_fw_resources(sp->qpair, &sp->iores))
goto queuing_error; goto queuing_error;
if (req->cnt < (req_cnt + 2)) { if (req->cnt < (req_cnt + 2)) {
...@@ -1678,7 +1679,7 @@ qla24xx_start_scsi(srb_t *sp) ...@@ -1678,7 +1679,7 @@ qla24xx_start_scsi(srb_t *sp)
if (tot_dsds) if (tot_dsds)
scsi_dma_unmap(cmd); scsi_dma_unmap(cmd);
qla_put_iocbs(sp->qpair, &sp->iores); qla_put_fw_resources(sp->qpair, &sp->iores);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->hardware_lock, flags);
return QLA_FUNCTION_FAILED; return QLA_FUNCTION_FAILED;
...@@ -1793,9 +1794,10 @@ qla24xx_dif_start_scsi(srb_t *sp) ...@@ -1793,9 +1794,10 @@ qla24xx_dif_start_scsi(srb_t *sp)
tot_prot_dsds = nseg; tot_prot_dsds = nseg;
tot_dsds += nseg; tot_dsds += nseg;
sp->iores.res_type = RESOURCE_INI; sp->iores.res_type = RESOURCE_IOCB | RESOURCE_EXCH;
sp->iores.exch_cnt = 1;
sp->iores.iocb_cnt = qla24xx_calc_iocbs(vha, tot_dsds); sp->iores.iocb_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
if (qla_get_iocbs(sp->qpair, &sp->iores)) if (qla_get_fw_resources(sp->qpair, &sp->iores))
goto queuing_error; goto queuing_error;
if (req->cnt < (req_cnt + 2)) { if (req->cnt < (req_cnt + 2)) {
...@@ -1883,7 +1885,7 @@ qla24xx_dif_start_scsi(srb_t *sp) ...@@ -1883,7 +1885,7 @@ qla24xx_dif_start_scsi(srb_t *sp)
} }
/* Cleanup will be performed by the caller (queuecommand) */ /* Cleanup will be performed by the caller (queuecommand) */
qla_put_iocbs(sp->qpair, &sp->iores); qla_put_fw_resources(sp->qpair, &sp->iores);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->hardware_lock, flags);
return QLA_FUNCTION_FAILED; return QLA_FUNCTION_FAILED;
...@@ -1952,9 +1954,10 @@ qla2xxx_start_scsi_mq(srb_t *sp) ...@@ -1952,9 +1954,10 @@ qla2xxx_start_scsi_mq(srb_t *sp)
tot_dsds = nseg; tot_dsds = nseg;
req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
sp->iores.res_type = RESOURCE_INI; sp->iores.res_type = RESOURCE_IOCB | RESOURCE_EXCH;
sp->iores.exch_cnt = 1;
sp->iores.iocb_cnt = req_cnt; sp->iores.iocb_cnt = req_cnt;
if (qla_get_iocbs(sp->qpair, &sp->iores)) if (qla_get_fw_resources(sp->qpair, &sp->iores))
goto queuing_error; goto queuing_error;
if (req->cnt < (req_cnt + 2)) { if (req->cnt < (req_cnt + 2)) {
...@@ -2041,7 +2044,7 @@ qla2xxx_start_scsi_mq(srb_t *sp) ...@@ -2041,7 +2044,7 @@ qla2xxx_start_scsi_mq(srb_t *sp)
if (tot_dsds) if (tot_dsds)
scsi_dma_unmap(cmd); scsi_dma_unmap(cmd);
qla_put_iocbs(sp->qpair, &sp->iores); qla_put_fw_resources(sp->qpair, &sp->iores);
spin_unlock_irqrestore(&qpair->qp_lock, flags); spin_unlock_irqrestore(&qpair->qp_lock, flags);
return QLA_FUNCTION_FAILED; return QLA_FUNCTION_FAILED;
...@@ -2171,9 +2174,10 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp) ...@@ -2171,9 +2174,10 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp)
tot_prot_dsds = nseg; tot_prot_dsds = nseg;
tot_dsds += nseg; tot_dsds += nseg;
sp->iores.res_type = RESOURCE_INI; sp->iores.res_type = RESOURCE_IOCB | RESOURCE_EXCH;
sp->iores.exch_cnt = 1;
sp->iores.iocb_cnt = qla24xx_calc_iocbs(vha, tot_dsds); sp->iores.iocb_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
if (qla_get_iocbs(sp->qpair, &sp->iores)) if (qla_get_fw_resources(sp->qpair, &sp->iores))
goto queuing_error; goto queuing_error;
if (req->cnt < (req_cnt + 2)) { if (req->cnt < (req_cnt + 2)) {
...@@ -2260,7 +2264,7 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp) ...@@ -2260,7 +2264,7 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp)
} }
/* Cleanup will be performed by the caller (queuecommand) */ /* Cleanup will be performed by the caller (queuecommand) */
qla_put_iocbs(sp->qpair, &sp->iores); qla_put_fw_resources(sp->qpair, &sp->iores);
spin_unlock_irqrestore(&qpair->qp_lock, flags); spin_unlock_irqrestore(&qpair->qp_lock, flags);
return QLA_FUNCTION_FAILED; return QLA_FUNCTION_FAILED;
...@@ -3813,6 +3817,65 @@ qla24xx_prlo_iocb(srb_t *sp, struct logio_entry_24xx *logio) ...@@ -3813,6 +3817,65 @@ qla24xx_prlo_iocb(srb_t *sp, struct logio_entry_24xx *logio)
logio->vp_index = sp->fcport->vha->vp_idx; logio->vp_index = sp->fcport->vha->vp_idx;
} }
static int qla_get_iocbs_resource(struct srb *sp)
{
bool get_exch;
bool push_it_through = false;
if (!ql2xenforce_iocb_limit) {
sp->iores.res_type = RESOURCE_NONE;
return 0;
}
sp->iores.res_type = RESOURCE_NONE;
switch (sp->type) {
case SRB_TM_CMD:
case SRB_PRLI_CMD:
case SRB_ADISC_CMD:
push_it_through = true;
fallthrough;
case SRB_LOGIN_CMD:
case SRB_ELS_CMD_RPT:
case SRB_ELS_CMD_HST:
case SRB_ELS_CMD_HST_NOLOGIN:
case SRB_CT_CMD:
case SRB_NVME_LS:
case SRB_ELS_DCMD:
get_exch = true;
break;
case SRB_FXIOCB_DCMD:
case SRB_FXIOCB_BCMD:
sp->iores.res_type = RESOURCE_NONE;
return 0;
case SRB_SA_UPDATE:
case SRB_SA_REPLACE:
case SRB_MB_IOCB:
case SRB_ABT_CMD:
case SRB_NACK_PLOGI:
case SRB_NACK_PRLI:
case SRB_NACK_LOGO:
case SRB_LOGOUT_CMD:
case SRB_CTRL_VP:
push_it_through = true;
fallthrough;
default:
get_exch = false;
}
sp->iores.res_type |= RESOURCE_IOCB;
sp->iores.iocb_cnt = 1;
if (get_exch) {
sp->iores.res_type |= RESOURCE_EXCH;
sp->iores.exch_cnt = 1;
}
if (push_it_through)
sp->iores.res_type |= RESOURCE_FORCE;
return qla_get_fw_resources(sp->qpair, &sp->iores);
}
int int
qla2x00_start_sp(srb_t *sp) qla2x00_start_sp(srb_t *sp)
{ {
...@@ -3827,6 +3890,12 @@ qla2x00_start_sp(srb_t *sp) ...@@ -3827,6 +3890,12 @@ qla2x00_start_sp(srb_t *sp)
return -EIO; return -EIO;
spin_lock_irqsave(qp->qp_lock_ptr, flags); spin_lock_irqsave(qp->qp_lock_ptr, flags);
rval = qla_get_iocbs_resource(sp);
if (rval) {
spin_unlock_irqrestore(qp->qp_lock_ptr, flags);
return -EAGAIN;
}
pkt = __qla2x00_alloc_iocbs(sp->qpair, sp); pkt = __qla2x00_alloc_iocbs(sp->qpair, sp);
if (!pkt) { if (!pkt) {
rval = EAGAIN; rval = EAGAIN;
...@@ -3927,6 +3996,8 @@ qla2x00_start_sp(srb_t *sp) ...@@ -3927,6 +3996,8 @@ qla2x00_start_sp(srb_t *sp)
wmb(); wmb();
qla2x00_start_iocbs(vha, qp->req); qla2x00_start_iocbs(vha, qp->req);
done: done:
if (rval)
qla_put_fw_resources(sp->qpair, &sp->iores);
spin_unlock_irqrestore(qp->qp_lock_ptr, flags); spin_unlock_irqrestore(qp->qp_lock_ptr, flags);
return rval; return rval;
} }
......
...@@ -3112,6 +3112,7 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt, ...@@ -3112,6 +3112,7 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt,
} }
bsg_reply->reply_payload_rcv_len = 0; bsg_reply->reply_payload_rcv_len = 0;
qla_put_fw_resources(sp->qpair, &sp->iores);
done: done:
/* Return the vendor specific reply to API */ /* Return the vendor specific reply to API */
bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval; bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval;
...@@ -3197,7 +3198,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) ...@@ -3197,7 +3198,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
} }
return; return;
} }
qla_put_iocbs(sp->qpair, &sp->iores); qla_put_fw_resources(sp->qpair, &sp->iores);
if (sp->cmd_type != TYPE_SRB) { if (sp->cmd_type != TYPE_SRB) {
req->outstanding_cmds[handle] = NULL; req->outstanding_cmds[handle] = NULL;
...@@ -3362,8 +3363,6 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) ...@@ -3362,8 +3363,6 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
"Dropped frame(s) detected (0x%x of 0x%x bytes).\n", "Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
resid, scsi_bufflen(cp)); resid, scsi_bufflen(cp));
vha->interface_err_cnt++;
res = DID_ERROR << 16 | lscsi_status; res = DID_ERROR << 16 | lscsi_status;
goto check_scsi_status; goto check_scsi_status;
} }
...@@ -3618,7 +3617,6 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt) ...@@ -3618,7 +3617,6 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
default: default:
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
if (sp) { if (sp) {
qla_put_iocbs(sp->qpair, &sp->iores);
sp->done(sp, res); sp->done(sp, res);
return 0; return 0;
} }
......
...@@ -170,18 +170,6 @@ static void qla_nvme_release_fcp_cmd_kref(struct kref *kref) ...@@ -170,18 +170,6 @@ static void qla_nvme_release_fcp_cmd_kref(struct kref *kref)
qla2xxx_rel_qpair_sp(sp->qpair, sp); qla2xxx_rel_qpair_sp(sp->qpair, sp);
} }
static void qla_nvme_ls_unmap(struct srb *sp, struct nvmefc_ls_req *fd)
{
if (sp->flags & SRB_DMA_VALID) {
struct srb_iocb *nvme = &sp->u.iocb_cmd;
struct qla_hw_data *ha = sp->fcport->vha->hw;
dma_unmap_single(&ha->pdev->dev, nvme->u.nvme.cmd_dma,
fd->rqstlen, DMA_TO_DEVICE);
sp->flags &= ~SRB_DMA_VALID;
}
}
static void qla_nvme_release_ls_cmd_kref(struct kref *kref) static void qla_nvme_release_ls_cmd_kref(struct kref *kref)
{ {
struct srb *sp = container_of(kref, struct srb, cmd_kref); struct srb *sp = container_of(kref, struct srb, cmd_kref);
...@@ -199,7 +187,6 @@ static void qla_nvme_release_ls_cmd_kref(struct kref *kref) ...@@ -199,7 +187,6 @@ static void qla_nvme_release_ls_cmd_kref(struct kref *kref)
fd = priv->fd; fd = priv->fd;
qla_nvme_ls_unmap(sp, fd);
fd->done(fd, priv->comp_status); fd->done(fd, priv->comp_status);
out: out:
qla2x00_rel_sp(sp); qla2x00_rel_sp(sp);
...@@ -365,13 +352,10 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport, ...@@ -365,13 +352,10 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport,
nvme->u.nvme.rsp_len = fd->rsplen; nvme->u.nvme.rsp_len = fd->rsplen;
nvme->u.nvme.rsp_dma = fd->rspdma; nvme->u.nvme.rsp_dma = fd->rspdma;
nvme->u.nvme.timeout_sec = fd->timeout; nvme->u.nvme.timeout_sec = fd->timeout;
nvme->u.nvme.cmd_dma = dma_map_single(&ha->pdev->dev, fd->rqstaddr, nvme->u.nvme.cmd_dma = fd->rqstdma;
fd->rqstlen, DMA_TO_DEVICE);
dma_sync_single_for_device(&ha->pdev->dev, nvme->u.nvme.cmd_dma, dma_sync_single_for_device(&ha->pdev->dev, nvme->u.nvme.cmd_dma,
fd->rqstlen, DMA_TO_DEVICE); fd->rqstlen, DMA_TO_DEVICE);
sp->flags |= SRB_DMA_VALID;
rval = qla2x00_start_sp(sp); rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) { if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x700e, ql_log(ql_log_warn, vha, 0x700e,
...@@ -379,7 +363,6 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport, ...@@ -379,7 +363,6 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport,
wake_up(&sp->nvme_ls_waitq); wake_up(&sp->nvme_ls_waitq);
sp->priv = NULL; sp->priv = NULL;
priv->sp = NULL; priv->sp = NULL;
qla_nvme_ls_unmap(sp, fd);
qla2x00_rel_sp(sp); qla2x00_rel_sp(sp);
return rval; return rval;
} }
...@@ -445,13 +428,24 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp) ...@@ -445,13 +428,24 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp)
goto queuing_error; goto queuing_error;
} }
req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
sp->iores.res_type = RESOURCE_IOCB | RESOURCE_EXCH;
sp->iores.exch_cnt = 1;
sp->iores.iocb_cnt = req_cnt;
if (qla_get_fw_resources(sp->qpair, &sp->iores)) {
rval = -EBUSY;
goto queuing_error;
}
if (req->cnt < (req_cnt + 2)) { if (req->cnt < (req_cnt + 2)) {
if (IS_SHADOW_REG_CAPABLE(ha)) { if (IS_SHADOW_REG_CAPABLE(ha)) {
cnt = *req->out_ptr; cnt = *req->out_ptr;
} else { } else {
cnt = rd_reg_dword_relaxed(req->req_q_out); cnt = rd_reg_dword_relaxed(req->req_q_out);
if (qla2x00_check_reg16_for_disconnect(vha, cnt)) if (qla2x00_check_reg16_for_disconnect(vha, cnt)) {
rval = -EBUSY;
goto queuing_error; goto queuing_error;
}
} }
if (req->ring_index < cnt) if (req->ring_index < cnt)
...@@ -600,6 +594,8 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp) ...@@ -600,6 +594,8 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp)
qla24xx_process_response_queue(vha, rsp); qla24xx_process_response_queue(vha, rsp);
queuing_error: queuing_error:
if (rval)
qla_put_fw_resources(sp->qpair, &sp->iores);
spin_unlock_irqrestore(&qpair->qp_lock, flags); spin_unlock_irqrestore(&qpair->qp_lock, flags);
return rval; return rval;
......
...@@ -7094,9 +7094,12 @@ qla2x00_do_dpc(void *data) ...@@ -7094,9 +7094,12 @@ qla2x00_do_dpc(void *data)
} }
} }
loop_resync_check: loop_resync_check:
if (test_and_clear_bit(LOOP_RESYNC_NEEDED, if (!qla2x00_reset_active(base_vha) &&
test_and_clear_bit(LOOP_RESYNC_NEEDED,
&base_vha->dpc_flags)) { &base_vha->dpc_flags)) {
/*
* Allow abort_isp to complete before moving on to scanning.
*/
ql_dbg(ql_dbg_dpc, base_vha, 0x400f, ql_dbg(ql_dbg_dpc, base_vha, 0x400f,
"Loop resync scheduled.\n"); "Loop resync scheduled.\n");
...@@ -7447,7 +7450,7 @@ qla2x00_timer(struct timer_list *t) ...@@ -7447,7 +7450,7 @@ qla2x00_timer(struct timer_list *t)
/* if the loop has been down for 4 minutes, reinit adapter */ /* if the loop has been down for 4 minutes, reinit adapter */
if (atomic_dec_and_test(&vha->loop_down_timer) != 0) { if (atomic_dec_and_test(&vha->loop_down_timer) != 0) {
if (!(vha->device_flags & DFLG_NO_CABLE)) { if (!(vha->device_flags & DFLG_NO_CABLE) && !vha->vp_idx) {
ql_log(ql_log_warn, vha, 0x6009, ql_log(ql_log_warn, vha, 0x6009,
"Loop down - aborting ISP.\n"); "Loop down - aborting ISP.\n");
......
...@@ -6,9 +6,9 @@ ...@@ -6,9 +6,9 @@
/* /*
* Driver version * Driver version
*/ */
#define QLA2XXX_VERSION "10.02.07.900-k" #define QLA2XXX_VERSION "10.02.08.100-k"
#define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MAJOR_VER 10
#define QLA_DRIVER_MINOR_VER 2 #define QLA_DRIVER_MINOR_VER 2
#define QLA_DRIVER_PATCH_VER 7 #define QLA_DRIVER_PATCH_VER 8
#define QLA_DRIVER_BETA_VER 900 #define QLA_DRIVER_BETA_VER 100
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