mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-13 05:54:23 +08:00
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.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
commit
92d685a96b
@ -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 @@ done:
|
||||
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,9 +1899,22 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
|
||||
return 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;
|
||||
|
||||
qla_put_fw_resources(sp->qpair, &sp->iores);
|
||||
return sp;
|
||||
}
|
||||
|
||||
@ -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 @@ out:
|
||||
|
||||
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 @@ process_err:
|
||||
(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 @@ qc24_fail_command:
|
||||
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,12 +1344,17 @@ __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;
|
||||
|
||||
while (wait_iter--) {
|
||||
found = false;
|
||||
|
||||
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
|
||||
for (cnt = 1; status == QLA_SUCCESS &&
|
||||
cnt < req->num_outstanding_cmds; cnt++) {
|
||||
for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
|
||||
sp = req->outstanding_cmds[cnt];
|
||||
if (!sp)
|
||||
continue;
|
||||
@ -1398,22 +1369,49 @@ __qla2x00_eh_wait_for_pending_commands(struct qla_qpair *qpair, unsigned int t,
|
||||
match = 1;
|
||||
break;
|
||||
case WAIT_TARGET:
|
||||
match = cmd->device->id == t;
|
||||
if (sp->fcport)
|
||||
match = sp->fcport->d_id.b24 == t;
|
||||
else
|
||||
match = 0;
|
||||
break;
|
||||
case WAIT_LUN:
|
||||
match = (cmd->device->id == t &&
|
||||
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);
|
||||
status = qla2x00_eh_wait_on_command(cmd);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user