Commit 92d685a9 authored by Martin K. Petersen's avatar Martin K. Petersen

Merge patch series "qla2xxx driver update"

Nilesh Javali <njavali@marvell.com> says:

Please apply the qla2xxx driver enhancement and bug fixes to the scsi tree
at your earliest convenience.

Link: https://lore.kernel.org/r/20230428075339.32551-1-njavali@marvell.comSigned-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parents 808e87a5 eb91eb80
......@@ -2750,6 +2750,7 @@ static void
qla2x00_terminate_rport_io(struct fc_rport *rport)
{
fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
scsi_qla_host_t *vha;
if (!fcport)
return;
......@@ -2759,9 +2760,12 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags))
return;
vha = fcport->vha;
if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) {
qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24,
0, WAIT_TARGET);
return;
}
/*
......@@ -2786,6 +2790,15 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
qla2x00_port_logout(fcport->vha, fcport);
}
}
/* check for any straggling io left behind */
if (qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24, 0, WAIT_TARGET)) {
ql_log(ql_log_warn, vha, 0x300b,
"IO not return. Resetting. \n");
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
qla2x00_wait_for_chip_reset(vha);
}
}
static int
......
......@@ -465,6 +465,15 @@ static inline be_id_t port_id_to_be_id(port_id_t port_id)
return res;
}
struct tmf_arg {
struct qla_qpair *qpair;
struct fc_port *fcport;
struct scsi_qla_host *vha;
u64 lun;
u32 flags;
uint8_t modifier;
};
struct els_logo_payload {
uint8_t opcode;
uint8_t rsvd[3];
......@@ -544,6 +553,10 @@ struct srb_iocb {
uint32_t data;
struct completion comp;
__le16 comp_status;
uint8_t modifier;
uint8_t vp_index;
uint16_t loop_id;
} tmf;
struct {
#define SRB_FXDISC_REQ_DMA_VALID BIT_0
......@@ -647,6 +660,7 @@ struct srb_iocb {
#define SRB_SA_UPDATE 25
#define SRB_ELS_CMD_HST_NOLOGIN 26
#define SRB_SA_REPLACE 27
#define SRB_MARKER 28
struct qla_els_pt_arg {
u8 els_opcode;
......@@ -2528,6 +2542,7 @@ enum rscn_addr_format {
typedef struct fc_port {
struct list_head list;
struct scsi_qla_host *vha;
struct list_head tmf_pending;
unsigned int conf_compl_supported:1;
unsigned int deleted:2;
......@@ -2548,6 +2563,8 @@ typedef struct fc_port {
unsigned int do_prli_nvme:1;
uint8_t nvme_flag;
uint8_t active_tmf;
#define MAX_ACTIVE_TMF 8
uint8_t node_name[WWN_SIZE];
uint8_t port_name[WWN_SIZE];
......@@ -5498,4 +5515,8 @@ struct ql_vnd_tgt_stats_resp {
_fp->disc_state, _fp->scan_state, _fp->loop_id, _fp->deleted, \
_fp->flags
#define TMF_NOT_READY(_fcport) \
(!_fcport || IS_SESSION_DELETED(_fcport) || atomic_read(&_fcport->state) != FCS_ONLINE || \
!_fcport->vha->hw->flags.fw_started)
#endif
......@@ -69,7 +69,7 @@ extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *);
extern int qla2x00_async_prlo(struct scsi_qla_host *, fc_port_t *);
extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t);
extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint64_t, uint32_t);
struct qla_work_evt *qla2x00_alloc_work(struct scsi_qla_host *,
enum qla_work_type);
extern int qla24xx_async_gnl(struct scsi_qla_host *, fc_port_t *);
......
......@@ -1996,6 +1996,11 @@ qla2x00_tmf_iocb_timeout(void *data)
int rc, h;
unsigned long flags;
if (sp->type == SRB_MARKER) {
complete(&tmf->u.tmf.comp);
return;
}
rc = qla24xx_async_abort_cmd(sp, false);
if (rc) {
spin_lock_irqsave(sp->qpair->qp_lock_ptr, flags);
......@@ -2013,24 +2018,131 @@ qla2x00_tmf_iocb_timeout(void *data)
}
}
static void qla_marker_sp_done(srb_t *sp, int res)
{
struct srb_iocb *tmf = &sp->u.iocb_cmd;
if (res != QLA_SUCCESS)
ql_dbg(ql_dbg_taskm, sp->vha, 0x8004,
"Async-marker fail hdl=%x portid=%06x ctrl=%x lun=%lld qp=%d.\n",
sp->handle, sp->fcport->d_id.b24, sp->u.iocb_cmd.u.tmf.flags,
sp->u.iocb_cmd.u.tmf.lun, sp->qpair->id);
sp->u.iocb_cmd.u.tmf.data = res;
complete(&tmf->u.tmf.comp);
}
#define START_SP_W_RETRIES(_sp, _rval) \
{\
int cnt = 5; \
do { \
_rval = qla2x00_start_sp(_sp); \
if (_rval == EAGAIN) \
msleep(1); \
else \
break; \
cnt--; \
} while (cnt); \
}
/**
* qla26xx_marker: send marker IOCB and wait for the completion of it.
* @arg: pointer to argument list.
* It is assume caller will provide an fcport pointer and modifier
*/
static int
qla26xx_marker(struct tmf_arg *arg)
{
struct scsi_qla_host *vha = arg->vha;
struct srb_iocb *tm_iocb;
srb_t *sp;
int rval = QLA_FUNCTION_FAILED;
fc_port_t *fcport = arg->fcport;
if (TMF_NOT_READY(arg->fcport)) {
ql_dbg(ql_dbg_taskm, vha, 0x8039,
"FC port not ready for marker loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d.\n",
fcport->loop_id, fcport->d_id.b24,
arg->modifier, arg->lun, arg->qpair->id);
return QLA_SUSPENDED;
}
/* ref: INIT */
sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL);
if (!sp)
goto done;
sp->type = SRB_MARKER;
sp->name = "marker";
qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha), qla_marker_sp_done);
sp->u.iocb_cmd.timeout = qla2x00_tmf_iocb_timeout;
tm_iocb = &sp->u.iocb_cmd;
init_completion(&tm_iocb->u.tmf.comp);
tm_iocb->u.tmf.modifier = arg->modifier;
tm_iocb->u.tmf.lun = arg->lun;
tm_iocb->u.tmf.loop_id = fcport->loop_id;
tm_iocb->u.tmf.vp_index = vha->vp_idx;
START_SP_W_RETRIES(sp, rval);
ql_dbg(ql_dbg_taskm, vha, 0x8006,
"Async-marker hdl=%x loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d rval %d.\n",
sp->handle, fcport->loop_id, fcport->d_id.b24,
arg->modifier, arg->lun, sp->qpair->id, rval);
if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x8031,
"Marker IOCB send failure (%x).\n", rval);
goto done_free_sp;
}
wait_for_completion(&tm_iocb->u.tmf.comp);
rval = tm_iocb->u.tmf.data;
if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x8019,
"Marker failed hdl=%x loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d rval %d.\n",
sp->handle, fcport->loop_id, fcport->d_id.b24,
arg->modifier, arg->lun, sp->qpair->id, rval);
}
done_free_sp:
/* ref: INIT */
kref_put(&sp->cmd_kref, qla2x00_sp_release);
done:
return rval;
}
static void qla2x00_tmf_sp_done(srb_t *sp, int res)
{
struct srb_iocb *tmf = &sp->u.iocb_cmd;
if (res)
tmf->u.tmf.data = res;
complete(&tmf->u.tmf.comp);
}
int
qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
uint32_t tag)
static int
__qla2x00_async_tm_cmd(struct tmf_arg *arg)
{
struct scsi_qla_host *vha = fcport->vha;
struct scsi_qla_host *vha = arg->vha;
struct srb_iocb *tm_iocb;
srb_t *sp;
int rval = QLA_FUNCTION_FAILED;
fc_port_t *fcport = arg->fcport;
if (TMF_NOT_READY(arg->fcport)) {
ql_dbg(ql_dbg_taskm, vha, 0x8032,
"FC port not ready for TM command loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d.\n",
fcport->loop_id, fcport->d_id.b24,
arg->modifier, arg->lun, arg->qpair->id);
return QLA_SUSPENDED;
}
/* ref: INIT */
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL);
if (!sp)
goto done;
......@@ -2043,15 +2155,16 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
tm_iocb = &sp->u.iocb_cmd;
init_completion(&tm_iocb->u.tmf.comp);
tm_iocb->u.tmf.flags = flags;
tm_iocb->u.tmf.lun = lun;
tm_iocb->u.tmf.flags = arg->flags;
tm_iocb->u.tmf.lun = arg->lun;
START_SP_W_RETRIES(sp, rval);
ql_dbg(ql_dbg_taskm, vha, 0x802f,
"Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
sp->handle, fcport->loop_id, fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa);
"Async-tmf hdl=%x loop-id=%x portid=%06x ctrl=%x lun=%lld qp=%d rval=%x.\n",
sp->handle, fcport->loop_id, fcport->d_id.b24,
arg->flags, arg->lun, sp->qpair->id, rval);
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS)
goto done_free_sp;
wait_for_completion(&tm_iocb->u.tmf.comp);
......@@ -2063,15 +2176,8 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
"TM IOCB failed (%x).\n", rval);
}
if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) {
flags = tm_iocb->u.tmf.flags;
lun = (uint16_t)tm_iocb->u.tmf.lun;
/* Issue Marker IOCB */
qla2x00_marker(vha, vha->hw->base_qpair,
fcport->loop_id, lun,
flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
}
if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw))
rval = qla26xx_marker(arg);
done_free_sp:
/* ref: INIT */
......@@ -2080,6 +2186,115 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
return rval;
}
static void qla_put_tmf(fc_port_t *fcport)
{
struct scsi_qla_host *vha = fcport->vha;
struct qla_hw_data *ha = vha->hw;
unsigned long flags;
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
fcport->active_tmf--;
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
}
static
int qla_get_tmf(fc_port_t *fcport)
{
struct scsi_qla_host *vha = fcport->vha;
struct qla_hw_data *ha = vha->hw;
unsigned long flags;
int rc = 0;
LIST_HEAD(tmf_elem);
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
list_add_tail(&tmf_elem, &fcport->tmf_pending);
while (fcport->active_tmf >= MAX_ACTIVE_TMF) {
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
msleep(1);
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
if (TMF_NOT_READY(fcport)) {
ql_log(ql_log_warn, vha, 0x802c,
"Unable to acquire TM resource due to disruption.\n");
rc = EIO;
break;
}
if (fcport->active_tmf < MAX_ACTIVE_TMF &&
list_is_first(&tmf_elem, &fcport->tmf_pending))
break;
}
list_del(&tmf_elem);
if (!rc)
fcport->active_tmf++;
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
return rc;
}
int
qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
uint32_t tag)
{
struct scsi_qla_host *vha = fcport->vha;
struct qla_qpair *qpair;
struct tmf_arg a;
int i, rval = QLA_SUCCESS;
if (TMF_NOT_READY(fcport))
return QLA_SUSPENDED;
a.vha = fcport->vha;
a.fcport = fcport;
a.lun = lun;
if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) {
a.modifier = MK_SYNC_ID_LUN;
if (qla_get_tmf(fcport))
return QLA_FUNCTION_FAILED;
} else {
a.modifier = MK_SYNC_ID;
}
if (vha->hw->mqenable) {
for (i = 0; i < vha->hw->num_qpairs; i++) {
qpair = vha->hw->queue_pair_map[i];
if (!qpair)
continue;
if (TMF_NOT_READY(fcport)) {
ql_log(ql_log_warn, vha, 0x8026,
"Unable to send TM due to disruption.\n");
rval = QLA_SUSPENDED;
break;
}
a.qpair = qpair;
a.flags = flags|TCF_NOTMCMD_TO_TARGET;
rval = __qla2x00_async_tm_cmd(&a);
if (rval)
break;
}
}
if (rval)
goto bailout;
a.qpair = vha->hw->base_qpair;
a.flags = flags;
rval = __qla2x00_async_tm_cmd(&a);
bailout:
if (a.modifier == MK_SYNC_ID_LUN)
qla_put_tmf(fcport);
return rval;
}
int
qla24xx_async_abort_command(srb_t *sp)
{
......@@ -5291,6 +5506,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
INIT_WORK(&fcport->reg_work, qla_register_fcport_fn);
INIT_LIST_HEAD(&fcport->gnl_entry);
INIT_LIST_HEAD(&fcport->list);
INIT_LIST_HEAD(&fcport->tmf_pending);
INIT_LIST_HEAD(&fcport->sess_cmd_list);
spin_lock_init(&fcport->sess_cmd_lock);
......
......@@ -522,21 +522,25 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct qla_qpair *qpair,
return (QLA_FUNCTION_FAILED);
}
mrk24 = (struct mrk_entry_24xx *)mrk;
mrk->entry_type = MARKER_TYPE;
mrk->modifier = type;
if (type != MK_SYNC_ALL) {
if (IS_FWI2_CAPABLE(ha)) {
mrk24 = (struct mrk_entry_24xx *) mrk;
mrk24->nport_handle = cpu_to_le16(loop_id);
int_to_scsilun(lun, (struct scsi_lun *)&mrk24->lun);
host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun));
mrk24->vp_index = vha->vp_idx;
mrk24->handle = make_handle(req->id, mrk24->handle);
} else {
SET_TARGET_ID(ha, mrk->target, loop_id);
mrk->lun = cpu_to_le16((uint16_t)lun);
}
}
if (IS_FWI2_CAPABLE(ha))
mrk24->handle = QLA_SKIP_HANDLE;
wmb();
qla2x00_start_iocbs(vha, req);
......@@ -2541,7 +2545,7 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
scsi_qla_host_t *vha = fcport->vha;
struct qla_hw_data *ha = vha->hw;
struct srb_iocb *iocb = &sp->u.iocb_cmd;
struct req_que *req = vha->req;
struct req_que *req = sp->qpair->req;
flags = iocb->u.tmf.flags;
lun = iocb->u.tmf.lun;
......@@ -2557,7 +2561,8 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
tsk->port_id[2] = fcport->d_id.b.domain;
tsk->vp_index = fcport->vha->vp_idx;
if (flags == TCF_LUN_RESET) {
if (flags & (TCF_LUN_RESET | TCF_ABORT_TASK_SET|
TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) {
int_to_scsilun(lun, &tsk->lun);
host_to_fcp_swap((uint8_t *)&tsk->lun,
sizeof(tsk->lun));
......@@ -3852,9 +3857,9 @@ static int qla_get_iocbs_resource(struct srb *sp)
case SRB_NACK_LOGO:
case SRB_LOGOUT_CMD:
case SRB_CTRL_VP:
push_it_through = true;
fallthrough;
case SRB_MARKER:
default:
push_it_through = true;
get_exch = false;
}
......@@ -3870,6 +3875,19 @@ static int qla_get_iocbs_resource(struct srb *sp)
return qla_get_fw_resources(sp->qpair, &sp->iores);
}
static void
qla_marker_iocb(srb_t *sp, struct mrk_entry_24xx *mrk)
{
mrk->entry_type = MARKER_TYPE;
mrk->modifier = sp->u.iocb_cmd.u.tmf.modifier;
if (sp->u.iocb_cmd.u.tmf.modifier != MK_SYNC_ALL) {
mrk->nport_handle = cpu_to_le16(sp->u.iocb_cmd.u.tmf.loop_id);
int_to_scsilun(sp->u.iocb_cmd.u.tmf.lun, (struct scsi_lun *)&mrk->lun);
host_to_fcp_swap(mrk->lun, sizeof(mrk->lun));
mrk->vp_index = sp->u.iocb_cmd.u.tmf.vp_index;
}
}
int
qla2x00_start_sp(srb_t *sp)
{
......@@ -3973,6 +3991,9 @@ qla2x00_start_sp(srb_t *sp)
case SRB_SA_REPLACE:
qla24xx_sa_replace_iocb(sp, pkt);
break;
case SRB_MARKER:
qla_marker_iocb(sp, pkt);
break;
default:
break;
}
......
......@@ -1862,9 +1862,9 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha,
}
}
srb_t *
qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
struct req_que *req, void *iocb)
static srb_t *
qla_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
struct req_que *req, void *iocb, u16 *ret_index)
{
struct qla_hw_data *ha = vha->hw;
sts_entry_t *pkt = iocb;
......@@ -1899,12 +1899,25 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
return NULL;
}
req->outstanding_cmds[index] = NULL;
*ret_index = index;
qla_put_fw_resources(sp->qpair, &sp->iores);
return sp;
}
srb_t *
qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
struct req_que *req, void *iocb)
{
uint16_t index;
srb_t *sp;
sp = qla_get_sp_from_handle(vha, func, req, iocb, &index);
if (sp)
req->outstanding_cmds[index] = NULL;
return sp;
}
static void
qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
struct mbx_entry *mbx)
......@@ -3237,13 +3250,13 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
return;
}
req->outstanding_cmds[handle] = NULL;
cp = GET_CMD_SP(sp);
if (cp == NULL) {
ql_dbg(ql_dbg_io, vha, 0x3018,
"Command already returned (0x%x/%p).\n",
sts->handle, sp);
req->outstanding_cmds[handle] = NULL;
return;
}
......@@ -3514,6 +3527,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
if (rsp->status_srb == NULL)
sp->done(sp, res);
/* for io's, clearing of outstanding_cmds[handle] means scsi_done was called */
req->outstanding_cmds[handle] = NULL;
}
/**
......@@ -3590,6 +3606,7 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
uint16_t que = MSW(pkt->handle);
struct req_que *req = NULL;
int res = DID_ERROR << 16;
u16 index;
ql_dbg(ql_dbg_async, vha, 0x502a,
"iocb type %xh with error status %xh, handle %xh, rspq id %d\n",
......@@ -3608,7 +3625,6 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
switch (pkt->entry_type) {
case NOTIFY_ACK_TYPE:
case STATUS_TYPE:
case STATUS_CONT_TYPE:
case LOGINOUT_PORT_IOCB_TYPE:
case CT_IOCB_TYPE:
......@@ -3628,6 +3644,14 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
case CTIO_TYPE7:
case CTIO_CRC2:
return 1;
case STATUS_TYPE:
sp = qla_get_sp_from_handle(vha, func, req, pkt, &index);
if (sp) {
sp->done(sp, res);
req->outstanding_cmds[index] = NULL;
return 0;
}
break;
}
fatal:
ql_log(ql_log_warn, vha, 0x5030,
......@@ -3750,6 +3774,28 @@ static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha,
return rc;
}
static void qla_marker_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
struct mrk_entry_24xx *pkt)
{
const char func[] = "MRK-IOCB";
srb_t *sp;
int res = QLA_SUCCESS;
if (!IS_FWI2_CAPABLE(vha->hw))
return;
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
if (!sp)
return;
if (pkt->entry_status) {
ql_dbg(ql_dbg_taskm, vha, 0x8025, "marker failure.\n");
res = QLA_COMMAND_ERROR;
}
sp->u.iocb_cmd.u.tmf.data = res;
sp->done(sp, res);
}
/**
* qla24xx_process_response_queue() - Process response queue entries.
* @vha: SCSI driver HA context
......@@ -3863,9 +3909,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
(struct nack_to_isp *)pkt);
break;
case MARKER_TYPE:
/* Do nothing in this case, this check is to prevent it
* from falling into default case
*/
qla_marker_iocb_entry(vha, rsp->req, (struct mrk_entry_24xx *)pkt);
break;
case ABORT_IOCB_TYPE:
qla24xx_abort_iocb_entry(vha, rsp->req,
......
......@@ -1078,43 +1078,6 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
return 0;
}
/*
* qla2x00_eh_wait_on_command
* Waits for the command to be returned by the Firmware for some
* max time.
*
* Input:
* cmd = Scsi Command to wait on.
*
* Return:
* Completed in time : QLA_SUCCESS
* Did not complete in time : QLA_FUNCTION_FAILED
*/
static int
qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd)
{
#define ABORT_POLLING_PERIOD 1000
#define ABORT_WAIT_ITER ((2 * 1000) / (ABORT_POLLING_PERIOD))
unsigned long wait_iter = ABORT_WAIT_ITER;
scsi_qla_host_t *vha = shost_priv(cmd->device->host);
struct qla_hw_data *ha = vha->hw;
srb_t *sp = scsi_cmd_priv(cmd);
int ret = QLA_SUCCESS;
if (unlikely(pci_channel_offline(ha->pdev)) || ha->flags.eeh_busy) {
ql_dbg(ql_dbg_taskm, vha, 0x8005,
"Return:eh_wait.\n");
return ret;
}
while (sp->type && wait_iter--)
msleep(ABORT_POLLING_PERIOD);
if (sp->type)
ret = QLA_FUNCTION_FAILED;
return ret;
}
/*
* qla2x00_wait_for_hba_online
* Wait till the HBA is online after going through
......@@ -1365,6 +1328,9 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
return ret;
}
#define ABORT_POLLING_PERIOD 1000
#define ABORT_WAIT_ITER ((2 * 1000) / (ABORT_POLLING_PERIOD))
/*
* Returns: QLA_SUCCESS or QLA_FUNCTION_FAILED.
*/
......@@ -1378,41 +1344,73 @@ __qla2x00_eh_wait_for_pending_commands(struct qla_qpair *qpair, unsigned int t,
struct req_que *req = qpair->req;
srb_t *sp;
struct scsi_cmnd *cmd;
unsigned long wait_iter = ABORT_WAIT_ITER;
bool found;
struct qla_hw_data *ha = vha->hw;
status = QLA_SUCCESS;
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
for (cnt = 1; status == QLA_SUCCESS &&
cnt < req->num_outstanding_cmds; cnt++) {
sp = req->outstanding_cmds[cnt];
if (!sp)
continue;
if (sp->type != SRB_SCSI_CMD)
continue;
if (vha->vp_idx != sp->vha->vp_idx)
continue;
match = 0;
cmd = GET_CMD_SP(sp);
switch (type) {
case WAIT_HOST:
match = 1;
break;
case WAIT_TARGET:
match = cmd->device->id == t;
break;
case WAIT_LUN:
match = (cmd->device->id == t &&
cmd->device->lun == l);
break;
}
if (!match)
continue;
while (wait_iter--) {
found = false;
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
status = qla2x00_eh_wait_on_command(cmd);
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
sp = req->outstanding_cmds[cnt];
if (!sp)
continue;
if (sp->type != SRB_SCSI_CMD)
continue;
if (vha->vp_idx != sp->vha->vp_idx)
continue;
match = 0;
cmd = GET_CMD_SP(sp);
switch (type) {
case WAIT_HOST:
match = 1;
break;
case WAIT_TARGET:
if (sp->fcport)
match = sp->fcport->d_id.b24 == t;
else
match = 0;
break;
case WAIT_LUN:
if (sp->fcport)
match = (sp->fcport->d_id.b24 == t &&
cmd->device->lun == l);
else
match = 0;
break;
}
if (!match)
continue;
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
if (unlikely(pci_channel_offline(ha->pdev)) ||
ha->flags.eeh_busy) {
ql_dbg(ql_dbg_taskm, vha, 0x8005,
"Return:eh_wait.\n");
return status;
}
/*
* SRB_SCSI_CMD is still in the outstanding_cmds array.
* it means scsi_done has not called. Wait for it to
* clear from outstanding_cmds.
*/
msleep(ABORT_POLLING_PERIOD);
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
found = true;
}
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
if (!found)
break;
}
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
if (!wait_iter && found)
status = QLA_FUNCTION_FAILED;
return status;
}
......
......@@ -6,9 +6,9 @@
/*
* Driver version
*/
#define QLA2XXX_VERSION "10.02.08.200-k"
#define QLA2XXX_VERSION "10.02.08.300-k"
#define QLA_DRIVER_MAJOR_VER 10
#define QLA_DRIVER_MINOR_VER 2
#define QLA_DRIVER_PATCH_VER 8
#define QLA_DRIVER_BETA_VER 200
#define QLA_DRIVER_BETA_VER 300
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