Merge branch 'svn-trunk'

This commit is contained in:
Bart Van Assche
2021-05-15 16:00:14 -07:00
19 changed files with 442 additions and 192 deletions
+6 -1
View File
@@ -50,10 +50,11 @@ void qla2x00_bsg_job_done(srb_t *sp, int res)
#endif
struct fc_bsg_reply *bsg_reply = bsg_job->reply;
sp->free(sp);
bsg_reply->result = res;
bsg_job_done(bsg_job, bsg_reply->result,
bsg_reply->reply_payload_rcv_len);
sp->free(sp);
}
void qla2x00_bsg_sp_free(srb_t *sp)
@@ -2725,6 +2726,10 @@ qla2x00_get_host_stats(struct bsg_job *bsg_job)
}
data = kzalloc(response_len, GFP_KERNEL);
if (!data) {
ret = -ENOMEM;
goto host_stat_out;
}
ret = qla2xxx_get_ini_stats(fc_bsg_to_shost(bsg_job), req_data->stat_type,
data, response_len);
+15 -1
View File
@@ -113,8 +113,13 @@ qla27xx_dump_mpi_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram,
uint32_t stat;
ulong i, j, timer = 6000000;
int rval = QLA_FUNCTION_FAILED;
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
if (qla_pci_disconnected(vha, reg))
return rval;
for (i = 0; i < ram_dwords; i += dwords, addr += dwords) {
if (i + dwords > ram_dwords)
dwords = ram_dwords - i;
@@ -138,6 +143,9 @@ qla27xx_dump_mpi_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram,
while (timer--) {
udelay(5);
if (qla_pci_disconnected(vha, reg))
return rval;
stat = rd_reg_dword(&reg->host_status);
/* Check for pending interrupts. */
if (!(stat & HSRX_RISC_INT))
@@ -192,9 +200,13 @@ qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, __be32 *ram,
uint32_t dwords = qla2x00_gid_list_size(ha) / 4;
uint32_t stat;
ulong i, j, timer = 6000000;
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
if (qla_pci_disconnected(vha, reg))
return rval;
for (i = 0; i < ram_dwords; i += dwords, addr += dwords) {
if (i + dwords > ram_dwords)
dwords = ram_dwords - i;
@@ -216,8 +228,10 @@ qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, __be32 *ram,
ha->flags.mbox_int = 0;
while (timer--) {
udelay(5);
stat = rd_reg_dword(&reg->host_status);
if (qla_pci_disconnected(vha, reg))
return rval;
stat = rd_reg_dword(&reg->host_status);
/* Check for pending interrupts. */
if (!(stat & HSRX_RISC_INT))
continue;
+1 -1
View File
@@ -308,7 +308,7 @@ struct qla2xxx_fw_dump {
};
#define QL_MSGHDR "qla2xxx"
#define QL_DBG_DEFAULT1_MASK 0x1e400000
#define QL_DBG_DEFAULT1_MASK 0x1e600000
#define ql_log_fatal 0 /* display fatal errors */
#define ql_log_warn 1 /* display critical errors */
+12 -3
View File
@@ -418,6 +418,7 @@ typedef union {
} b;
} port_id_t;
#define INVALID_PORT_ID 0xFFFFFF
#define ISP_REG16_DISCONNECT 0xFFFF
static inline le_id_t be_id_to_le(be_id_t id)
{
@@ -1553,7 +1554,7 @@ struct init_sf_cb {
* BIT_12 = Remote Write Optimization (1 - Enabled, 0 - Disabled)
* BIT 11-0 = Reserved
*/
uint16_t flags;
__le16 flags;
uint8_t reserved1[32];
uint16_t discard_OHRB_timeout_value;
uint16_t remote_write_opt_queue_num;
@@ -3842,7 +3843,7 @@ struct qlt_hw_data {
__le32 __iomem *atio_q_in;
__le32 __iomem *atio_q_out;
struct qla_tgt_func_tmpl *tgt_ops;
const struct qla_tgt_func_tmpl *tgt_ops;
struct qla_tgt_vp_map *tgt_vp_map;
int saved_set;
@@ -3884,6 +3885,13 @@ struct qla_hw_data_stat {
u32 num_mpi_reset;
};
/* refer to pcie_do_recovery reference */
typedef enum {
QLA_PCI_RESUME,
QLA_PCI_ERR_DETECTED,
QLA_PCI_MMIO_ENABLED,
QLA_PCI_SLOT_RESET,
} pci_error_state_t;
/*
* Qlogic host adapter specific data structure.
*/
@@ -4634,6 +4642,7 @@ struct qla_hw_data {
#define DEFAULT_ZIO_THRESHOLD 5
struct qla_hw_data_stat stat;
pci_error_state_t pci_error_state;
};
struct active_regions {
@@ -4754,7 +4763,7 @@ typedef struct scsi_qla_host {
#define FX00_CRITEMP_RECOVERY 25
#define FX00_HOST_INFO_RESEND 26
#define QPAIR_ONLINE_CHECK_NEEDED 27
#define SET_NVME_ZIO_THRESHOLD_NEEDED 28
#define DO_EEH_RECOVERY 28
#define DETECT_SFP_CHANGE 29
#define N2N_LOGIN_NEEDED 30
#define IOCB_WORK_ACTIVE 31
+3
View File
@@ -228,6 +228,7 @@ extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32);
extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32);
extern void qla2x00_disable_board_on_pci_error(struct work_struct *);
extern void qla_eeh_work(struct work_struct *);
extern void qla2x00_sp_compl(srb_t *sp, int);
extern void qla2xxx_qpair_sp_free_dma(srb_t *sp);
extern void qla2xxx_qpair_sp_compl(srb_t *sp, int);
@@ -239,6 +240,8 @@ int qla24xx_post_relogin_work(struct scsi_qla_host *vha);
void qla2x00_wait_for_sess_deletion(scsi_qla_host_t *);
void qla24xx_process_purex_rdp(struct scsi_qla_host *vha,
struct purex_item *pkt);
void qla_pci_set_eeh_busy(struct scsi_qla_host *);
void qla_schedule_eeh_work(struct scsi_qla_host *);
/*
* Global Functions in qla_mid.c source file.
+9 -5
View File
@@ -1247,7 +1247,7 @@ qla2x00_sns_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
}
/**
* qla2x00_snd_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
* qla2x00_sns_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
* @vha: HA context
*
* This command uses the old Exectute SNS Command mailbox routine.
@@ -1479,7 +1479,7 @@ qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size)
}
/**
* qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
* qla2x00_prep_ct_fdmi_req() - Prepare common CT request fields for SNS query.
* @p: CT request buffer
* @cmd: GS command
* @rsp_size: response size in bytes
@@ -1582,7 +1582,7 @@ qla25xx_fdmi_port_speed_currently(struct qla_hw_data *ha)
}
/**
* qla2x00_hba_attributes() perform HBA attributes registration
* qla2x00_hba_attributes() - perform HBA attributes registration
* @vha: HA context
* @entries: number of entries to use
* @callopt: Option to issue extended or standard FDMI
@@ -1837,7 +1837,7 @@ done:
}
/**
* qla2x00_port_attributes() perform Port attributes registration
* qla2x00_port_attributes() - perform Port attributes registration
* @vha: HA context
* @entries: number of entries to use
* @callopt: Option to issue extended or standard FDMI
@@ -2272,7 +2272,7 @@ qla2x00_fdmi_dhba(scsi_qla_host_t *vha)
}
/**
* qla2x00_fdmi_rprt() perform RPRT registration
* qla2x00_fdmi_rprt() - perform RPRT registration
* @vha: HA context
* @callopt: Option to issue extended or standard FDMI
* command parameter
@@ -3443,6 +3443,10 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
list_for_each_entry(fcport, &vha->vp_fcports, list) {
if ((fcport->flags & FCF_FABRIC_DEVICE) != 0) {
fcport->scan_state = QLA_FCPORT_SCAN;
if (fcport->loop_id == FC_NO_LOOP_ID)
fcport->logout_on_delete = 0;
else
fcport->logout_on_delete = 1;
}
}
goto login_logout;
+94 -24
View File
@@ -718,6 +718,7 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
ql_dbg(ql_dbg_disc, vha, 0x20e0,
"%s %8phC login gen changed\n",
__func__, fcport->port_name);
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
return;
}
@@ -1194,6 +1195,9 @@ static int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport)
{
struct qla_work_evt *e;
if (vha->host->active_mode == MODE_TARGET)
return QLA_FUNCTION_FAILED;
e = qla2x00_alloc_work(vha, QLA_EVT_PRLI);
if (!e)
return QLA_FUNCTION_FAILED;
@@ -2766,6 +2770,49 @@ qla81xx_reset_mpi(scsi_qla_host_t *vha)
return qla81xx_write_mpi_register(vha, mb);
}
static int
qla_chk_risc_recovery(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
__le16 __iomem *mbptr = &reg->mailbox0;
int i;
u16 mb[32];
int rc = QLA_SUCCESS;
if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
return rc;
/* this check is only valid after RISC reset */
mb[0] = rd_reg_word(mbptr);
mbptr++;
if (mb[0] == 0xf) {
rc = QLA_FUNCTION_FAILED;
for (i = 1; i < 32; i++) {
mb[i] = rd_reg_word(mbptr);
mbptr++;
}
ql_log(ql_log_warn, vha, 0x1015,
"RISC reset failed. mb[0-7] %04xh %04xh %04xh %04xh %04xh %04xh %04xh %04xh\n",
mb[0], mb[1], mb[2], mb[3], mb[4], mb[5], mb[6], mb[7]);
ql_log(ql_log_warn, vha, 0x1015,
"RISC reset failed. mb[8-15] %04xh %04xh %04xh %04xh %04xh %04xh %04xh %04xh\n",
mb[8], mb[9], mb[10], mb[11], mb[12], mb[13], mb[14],
mb[15]);
ql_log(ql_log_warn, vha, 0x1015,
"RISC reset failed. mb[16-23] %04xh %04xh %04xh %04xh %04xh %04xh %04xh %04xh\n",
mb[16], mb[17], mb[18], mb[19], mb[20], mb[21], mb[22],
mb[23]);
ql_log(ql_log_warn, vha, 0x1015,
"RISC reset failed. mb[24-31] %04xh %04xh %04xh %04xh %04xh %04xh %04xh %04xh\n",
mb[24], mb[25], mb[26], mb[27], mb[28], mb[29], mb[30],
mb[31]);
}
return rc;
}
/**
* qla24xx_reset_risc() - Perform full reset of ISP24xx RISC.
* @vha: HA context
@@ -2782,6 +2829,7 @@ qla24xx_reset_risc(scsi_qla_host_t *vha)
uint16_t wd;
static int abts_cnt; /* ISP abort retry counts */
int rval = QLA_SUCCESS;
int print = 1;
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -2870,17 +2918,26 @@ qla24xx_reset_risc(scsi_qla_host_t *vha)
rd_reg_dword(&reg->hccr);
wrt_reg_dword(&reg->hccr, HCCRX_CLR_RISC_RESET);
mdelay(10);
rd_reg_dword(&reg->hccr);
rd_reg_word(&reg->mailbox0);
for (cnt = 60; rd_reg_word(&reg->mailbox0) != 0 &&
rval == QLA_SUCCESS; cnt--) {
wd = rd_reg_word(&reg->mailbox0);
for (cnt = 300; wd != 0 && rval == QLA_SUCCESS; cnt--) {
barrier();
if (cnt)
udelay(5);
else
if (cnt) {
mdelay(1);
if (print && qla_chk_risc_recovery(vha))
print = 0;
wd = rd_reg_word(&reg->mailbox0);
} else {
rval = QLA_FUNCTION_TIMEOUT;
ql_log(ql_log_warn, vha, 0x015e,
"RISC reset timeout\n");
}
}
if (rval == QLA_SUCCESS)
set_bit(RISC_RDY_AFT_RESET, &ha->fw_dump_cap_flags);
@@ -5512,13 +5569,14 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
if (fcport->port_type & FCT_NVME_DISCOVERY)
rport_ids.roles |= FC_PORT_ROLE_NVME_DISCOVERY;
fc_remote_port_rolechg(rport, rport_ids.roles);
ql_dbg(ql_dbg_disc, vha, 0x20ee,
"%s %8phN. rport %p is %s mode\n",
__func__, fcport->port_name, rport,
"%s: %8phN. rport %ld:0:%d (%p) is %s mode\n",
__func__, fcport->port_name, vha->host_no,
rport->scsi_target_id, rport,
(fcport->port_type == FCT_TARGET) ? "tgt" :
((fcport->port_type & FCT_NVME) ? "nvme" : "ini"));
fc_remote_port_rolechg(rport, rport_ids.roles);
}
/*
@@ -6877,22 +6935,18 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
}
spin_unlock_irqrestore(&ha->vport_slock, flags);
if (!ha->flags.eeh_busy) {
/* Make sure for ISP 82XX IO DMA is complete */
if (IS_P3P_TYPE(ha)) {
qla82xx_chip_reset_cleanup(vha);
ql_log(ql_log_info, vha, 0x00b4,
"Done chip reset cleanup.\n");
/* Make sure for ISP 82XX IO DMA is complete */
if (IS_P3P_TYPE(ha)) {
qla82xx_chip_reset_cleanup(vha);
ql_log(ql_log_info, vha, 0x00b4,
"Done chip reset cleanup.\n");
/* Done waiting for pending commands.
* Reset the online flag.
*/
vha->flags.online = 0;
}
/* Requeue all commands in outstanding command list. */
qla2x00_abort_all_cmds(vha, DID_RESET << 16);
/* Done waiting for pending commands. Reset online flag */
vha->flags.online = 0;
}
/* Requeue all commands in outstanding command list. */
qla2x00_abort_all_cmds(vha, DID_RESET << 16);
/* memory barrier */
wmb();
}
@@ -6923,6 +6977,12 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
if (vha->hw->flags.port_isolated)
return status;
if (qla2x00_isp_reg_stat(ha)) {
ql_log(ql_log_info, vha, 0x803f,
"ISP Abort - ISP reg disconnect, exiting.\n");
return status;
}
if (test_and_clear_bit(ISP_ABORT_TO_ROM, &vha->dpc_flags)) {
ha->flags.chip_reset_done = 1;
vha->flags.online = 1;
@@ -6962,8 +7022,18 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
ha->isp_ops->get_flash_version(vha, req->ring);
if (qla2x00_isp_reg_stat(ha)) {
ql_log(ql_log_info, vha, 0x803f,
"ISP Abort - ISP reg disconnect pre nvram config, exiting.\n");
return status;
}
ha->isp_ops->nvram_config(vha);
if (qla2x00_isp_reg_stat(ha)) {
ql_log(ql_log_info, vha, 0x803f,
"ISP Abort - ISP reg disconnect post nvmram config, exiting.\n");
return status;
}
if (!qla2x00_restart_isp(vha)) {
clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
+46
View File
@@ -440,3 +440,49 @@ qla_put_iocbs(struct qla_qpair *qp, struct iocb_resource *iores)
}
iores->res_type = RESOURCE_NONE;
}
#define ISP_REG_DISCONNECT 0xffffffffU
/**************************************************************************
* qla2x00_isp_reg_stat
*
* Description:
* Read the host status register of ISP before aborting the command.
*
* Input:
* ha = pointer to host adapter structure.
*
*
* Returns:
* Either true or false.
*
* Note: Return true if there is register disconnect.
**************************************************************************/
static inline
uint32_t qla2x00_isp_reg_stat(struct qla_hw_data *ha)
{
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82;
if (IS_P3P_TYPE(ha))
return ((rd_reg_dword(&reg82->host_int)) == ISP_REG_DISCONNECT);
else
return ((rd_reg_dword(&reg->host_status)) ==
ISP_REG_DISCONNECT);
}
static inline
bool qla_pci_disconnected(struct scsi_qla_host *vha,
struct device_reg_24xx __iomem *reg)
{
uint32_t stat;
bool ret = false;
stat = rd_reg_dword(&reg->host_status);
if (stat == 0xffffffff) {
ql_log(ql_log_info, vha, 0x8041,
"detected PCI disconnect.\n");
qla_schedule_eeh_work(vha);
ret = true;
}
return ret;
}
+72 -12
View File
@@ -491,7 +491,7 @@ qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req)
}
/**
* qla2x00_marker() - Send a marker IOCB to the firmware.
* __qla2x00_marker() - Send a marker IOCB to the firmware.
* @vha: HA context
* @qpair: queue pair pointer
* @loop_id: loop ID
@@ -1606,12 +1606,14 @@ qla24xx_start_scsi(srb_t *sp)
uint16_t req_cnt;
uint16_t tot_dsds;
struct req_que *req = NULL;
struct rsp_que *rsp;
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
struct scsi_qla_host *vha = sp->vha;
struct qla_hw_data *ha = vha->hw;
/* Setup device pointers. */
req = vha->req;
rsp = req->rsp;
/* So we know we haven't pci_map'ed anything yet */
tot_dsds = 0;
@@ -1649,8 +1651,14 @@ qla24xx_start_scsi(srb_t *sp)
goto queuing_error;
if (req->cnt < (req_cnt + 2)) {
cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
rd_reg_dword_relaxed(req->req_q_out);
if (IS_SHADOW_REG_CAPABLE(ha)) {
cnt = *req->out_ptr;
} else {
cnt = rd_reg_dword_relaxed(req->req_q_out);
if (qla2x00_check_reg16_for_disconnect(vha, cnt))
goto queuing_error;
}
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
else
@@ -1713,6 +1721,11 @@ qla24xx_start_scsi(srb_t *sp)
/* Set chip new ring index. */
wrt_reg_dword(req->req_q_in, req->ring_index);
/* Manage unprocessed RIO/ZIO commands in response queue. */
if (vha->flags.process_response_queue &&
rsp->ring_ptr->signature != RESPONSE_PROCESSED)
qla24xx_process_response_queue(vha, rsp);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return QLA_SUCCESS;
@@ -1841,8 +1854,13 @@ qla24xx_dif_start_scsi(srb_t *sp)
goto queuing_error;
if (req->cnt < (req_cnt + 2)) {
cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
rd_reg_dword_relaxed(req->req_q_out);
if (IS_SHADOW_REG_CAPABLE(ha)) {
cnt = *req->out_ptr;
} else {
cnt = rd_reg_dword_relaxed(req->req_q_out);
if (qla2x00_check_reg16_for_disconnect(vha, cnt))
goto queuing_error;
}
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
else
@@ -1903,6 +1921,11 @@ qla24xx_dif_start_scsi(srb_t *sp)
/* Set chip new ring index. */
wrt_reg_dword(req->req_q_in, req->ring_index);
/* Manage unprocessed RIO/ZIO commands in response queue. */
if (vha->flags.process_response_queue &&
rsp->ring_ptr->signature != RESPONSE_PROCESSED)
qla24xx_process_response_queue(vha, rsp);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return QLA_SUCCESS;
@@ -1916,6 +1939,7 @@ queuing_error:
qla_put_iocbs(sp->qpair, &sp->iores);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return QLA_FUNCTION_FAILED;
}
@@ -1937,6 +1961,7 @@ qla2xxx_start_scsi_mq(srb_t *sp)
uint16_t req_cnt;
uint16_t tot_dsds;
struct req_que *req = NULL;
struct rsp_que *rsp;
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
struct scsi_qla_host *vha = sp->fcport->vha;
struct qla_hw_data *ha = vha->hw;
@@ -1947,6 +1972,7 @@ qla2xxx_start_scsi_mq(srb_t *sp)
/* Setup qpair pointers */
req = qpair->req;
rsp = qpair->rsp;
/* So we know we haven't pci_map'ed anything yet */
tot_dsds = 0;
@@ -1983,8 +2009,14 @@ qla2xxx_start_scsi_mq(srb_t *sp)
goto queuing_error;
if (req->cnt < (req_cnt + 2)) {
cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
rd_reg_dword_relaxed(req->req_q_out);
if (IS_SHADOW_REG_CAPABLE(ha)) {
cnt = *req->out_ptr;
} else {
cnt = rd_reg_dword_relaxed(req->req_q_out);
if (qla2x00_check_reg16_for_disconnect(vha, cnt))
goto queuing_error;
}
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
else
@@ -2047,6 +2079,11 @@ qla2xxx_start_scsi_mq(srb_t *sp)
/* Set chip new ring index. */
wrt_reg_dword(req->req_q_in, req->ring_index);
/* Manage unprocessed RIO/ZIO commands in response queue. */
if (vha->flags.process_response_queue &&
rsp->ring_ptr->signature != RESPONSE_PROCESSED)
qla24xx_process_response_queue(vha, rsp);
spin_unlock_irqrestore(&qpair->qp_lock, flags);
return QLA_SUCCESS;
@@ -2190,8 +2227,14 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp)
goto queuing_error;
if (req->cnt < (req_cnt + 2)) {
cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
rd_reg_dword_relaxed(req->req_q_out);
if (IS_SHADOW_REG_CAPABLE(ha)) {
cnt = *req->out_ptr;
} else {
cnt = rd_reg_dword_relaxed(req->req_q_out);
if (qla2x00_check_reg16_for_disconnect(vha, cnt))
goto queuing_error;
}
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
else
@@ -2268,6 +2311,7 @@ queuing_error:
qla_put_iocbs(sp->qpair, &sp->iores);
spin_unlock_irqrestore(&qpair->qp_lock, flags);
return QLA_FUNCTION_FAILED;
}
@@ -2312,6 +2356,11 @@ __qla2x00_alloc_iocbs(struct qla_qpair *qpair, srb_t *sp)
cnt = qla2x00_debounce_register(
ISP_REQ_Q_OUT(ha, &reg->isp));
if (!qpair->use_shadow_reg && cnt == ISP_REG16_DISCONNECT) {
qla_schedule_eeh_work(vha);
return NULL;
}
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
else
@@ -2385,7 +2434,8 @@ qla24xx_prli_iocb(srb_t *sp, struct logio_entry_24xx *logio)
cpu_to_le32(NVME_PRLI_SP_FIRST_BURST);
if (sp->vha->flags.nvme2_enabled) {
/* Set service parameter BIT_7 for NVME CONF support */
logio->io_parameter[0] |= NVME_PRLI_SP_CONF;
logio->io_parameter[0] |=
cpu_to_le32(NVME_PRLI_SP_CONF);
/* Set service parameter BIT_8 for SLER support */
logio->io_parameter[0] |=
cpu_to_le32(NVME_PRLI_SP_SLER);
@@ -3738,6 +3788,9 @@ qla2x00_start_sp(srb_t *sp)
void *pkt;
unsigned long flags;
if (vha->hw->flags.eeh_busy)
return -EIO;
spin_lock_irqsave(qp->qp_lock_ptr, flags);
pkt = __qla2x00_alloc_iocbs(sp->qpair, sp);
if (!pkt) {
@@ -3959,8 +4012,14 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds)
/* Check for room on request queue. */
if (req->cnt < req_cnt + 2) {
cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
rd_reg_dword_relaxed(req->req_q_out);
if (IS_SHADOW_REG_CAPABLE(ha)) {
cnt = *req->out_ptr;
} else {
cnt = rd_reg_dword_relaxed(req->req_q_out);
if (qla2x00_check_reg16_for_disconnect(vha, cnt))
goto queuing_error;
}
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
else
@@ -3999,5 +4058,6 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds)
qla2x00_start_iocbs(vha, req);
queuing_error:
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return rval;
}
+4 -11
View File
@@ -282,12 +282,7 @@ qla2x00_check_reg32_for_disconnect(scsi_qla_host_t *vha, uint32_t reg)
if (!test_and_set_bit(PFLG_DISCONNECTED, &vha->pci_flags) &&
!test_bit(PFLG_DRIVER_REMOVING, &vha->pci_flags) &&
!test_bit(PFLG_DRIVER_PROBING, &vha->pci_flags)) {
/*
* Schedule this (only once) on the default system
* workqueue so that all the adapter workqueues and the
* DPC thread can be shutdown cleanly.
*/
schedule_work(&vha->hw->board_disable);
qla_schedule_eeh_work(vha);
}
return true;
} else
@@ -1669,8 +1664,6 @@ global_port_update:
case MBA_TEMPERATURE_ALERT:
ql_dbg(ql_dbg_async, vha, 0x505e,
"TEMPERATURE ALERT: %04x %04x %04x\n", mb[1], mb[2], mb[3]);
if (mb[1] == 0x12)
schedule_work(&ha->board_disable);
break;
case MBA_TRANS_INSERT:
@@ -3475,7 +3468,7 @@ qla24xx_abort_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
return;
abt = &sp->u.iocb_cmd;
abt->u.abt.comp_status = le16_to_cpu(pkt->comp_status);
abt->u.abt.comp_status = pkt->comp_status;
orig_sp = sp->cmd_sp;
/* Need to pass original sp */
if (orig_sp)
@@ -4109,11 +4102,11 @@ msix_failed:
if (USER_CTRL_IRQ(ha) || !ha->mqiobase) {
/* user wants to control IRQ setting for target mode */
ret = pci_alloc_irq_vectors(ha->pdev, min_vecs,
min((u16)ha->msix_count, (u16)num_online_cpus()),
min((u16)ha->msix_count, (u16)(num_online_cpus() + min_vecs)),
PCI_IRQ_MSIX);
} else
ret = pci_alloc_irq_vectors_affinity(ha->pdev, min_vecs,
min((u16)ha->msix_count, (u16)num_online_cpus()),
min((u16)ha->msix_count, (u16)(num_online_cpus() + min_vecs)),
PCI_IRQ_MSIX | PCI_IRQ_AFFINITY,
&desc);
#endif
+30 -8
View File
@@ -102,7 +102,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
int rval, i;
unsigned long flags = 0;
device_reg_t *reg;
uint8_t abort_active;
uint8_t abort_active, eeh_delay;
uint8_t io_lock_on;
uint16_t command = 0;
uint16_t *iptr;
@@ -136,7 +136,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
"PCI error, exiting.\n");
return QLA_FUNCTION_TIMEOUT;
}
eeh_delay = 0;
reg = ha->iobase;
io_lock_on = base_vha->flags.init_done;
@@ -159,10 +159,10 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
}
/* check if ISP abort is active and return cmd with timeout */
if ((test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) &&
!is_rom_cmd(mcp->mb[0])) {
if (((test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) &&
!is_rom_cmd(mcp->mb[0])) || ha->flags.eeh_busy) {
ql_log(ql_log_info, vha, 0x1005,
"Cmd 0x%x aborted with timeout since ISP Abort is pending\n",
mcp->mb[0]);
@@ -185,7 +185,11 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
return QLA_FUNCTION_TIMEOUT;
}
atomic_dec(&ha->num_pend_mbx_stage1);
if (ha->flags.purge_mbox || chip_reset != ha->chip_reset) {
if (ha->flags.purge_mbox || chip_reset != ha->chip_reset ||
ha->flags.eeh_busy) {
ql_log(ql_log_warn, vha, 0xd035,
"Error detected: purge[%d] eeh[%d] cmd=0x%x, Exiting.\n",
ha->flags.purge_mbox, ha->flags.eeh_busy, mcp->mb[0]);
rval = QLA_ABORTED;
goto premature_exit;
}
@@ -265,6 +269,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
if (!wait_for_completion_timeout(&ha->mbx_intr_comp,
mcp->tov * HZ)) {
if (chip_reset != ha->chip_reset) {
eeh_delay = ha->flags.eeh_busy ? 1 : 0;
spin_lock_irqsave(&ha->hardware_lock, flags);
ha->flags.mbox_busy = 0;
spin_unlock_irqrestore(&ha->hardware_lock,
@@ -282,6 +288,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
} else if (ha->flags.purge_mbox ||
chip_reset != ha->chip_reset) {
eeh_delay = ha->flags.eeh_busy ? 1 : 0;
spin_lock_irqsave(&ha->hardware_lock, flags);
ha->flags.mbox_busy = 0;
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -323,6 +331,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
while (!ha->flags.mbox_int) {
if (ha->flags.purge_mbox ||
chip_reset != ha->chip_reset) {
eeh_delay = ha->flags.eeh_busy ? 1 : 0;
spin_lock_irqsave(&ha->hardware_lock, flags);
ha->flags.mbox_busy = 0;
spin_unlock_irqrestore(&ha->hardware_lock,
@@ -531,7 +541,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
/* Allow next mbx cmd to come in. */
complete(&ha->mbx_cmd_comp);
if (ha->isp_ops->abort_isp(vha)) {
if (ha->isp_ops->abort_isp(vha) &&
!ha->flags.eeh_busy) {
/* Failed. retry later. */
set_bit(ISP_ABORT_NEEDED,
&vha->dpc_flags);
@@ -584,6 +595,17 @@ mbx_done:
ql_dbg(ql_dbg_mbx, base_vha, 0x1021, "Done %s.\n", __func__);
}
i = 500;
while (i && eeh_delay && (ha->pci_error_state < QLA_PCI_SLOT_RESET)) {
/*
* The caller of this mailbox encounter pci error.
* Hold the thread until PCIE link reset complete to make
* sure caller does not unmap dma while recovery is
* in progress.
*/
msleep(1);
i--;
}
return rval;
}
+2 -2
View File
@@ -516,7 +516,7 @@ qlafx00_pci_config(scsi_qla_host_t *vha)
}
/**
* qlafx00_warm_reset() - Perform warm reset of iSA(CPUs being reset on SOC).
* qlafx00_soc_cpu_reset() - Perform warm reset of iSA(CPUs being reset on SOC).
* @vha: HA context
*
*/
@@ -2875,7 +2875,7 @@ qlafx00_async_event(scsi_qla_host_t *vha)
}
/**
* qlafx00x_mbx_completion() - Process mailbox command completions.
* qlafx00_mbx_completion() - Process mailbox command completions.
* @vha: SCSI driver HA context
* @mb0: value to be written into mailbox register 0
*/
+8 -2
View File
@@ -411,8 +411,13 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp)
}
req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
if (req->cnt < (req_cnt + 2)) {
cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
rd_reg_dword_relaxed(req->req_q_out);
if (IS_SHADOW_REG_CAPABLE(ha)) {
cnt = *req->out_ptr;
} else {
cnt = rd_reg_dword_relaxed(req->req_q_out);
if (qla2x00_check_reg16_for_disconnect(vha, cnt))
goto queuing_error;
}
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
@@ -549,6 +554,7 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp)
queuing_error:
spin_unlock_irqrestore(&qpair->qp_lock, flags);
return rval;
}
+1 -9
View File
@@ -2028,7 +2028,7 @@ exit_error:
}
/**
* qla4_8xxx_check_temp - Check the ISP82XX temperature.
* qla8044_check_temp - Check the ISP82XX temperature.
* @vha: adapter block pointer.
*
* Note: The caller should not hold the idc lock.
@@ -2226,19 +2226,16 @@ qla8044_minidump_process_control(struct scsi_qla_host *vha,
if (opcode & QLA82XX_DBG_OPCODE_WR) {
qla8044_wr_reg_indirect(vha, crb_addr,
crb_entry->value_1);
opcode &= ~QLA82XX_DBG_OPCODE_WR;
}
if (opcode & QLA82XX_DBG_OPCODE_RW) {
qla8044_rd_reg_indirect(vha, crb_addr, &read_value);
qla8044_wr_reg_indirect(vha, crb_addr, read_value);
opcode &= ~QLA82XX_DBG_OPCODE_RW;
}
if (opcode & QLA82XX_DBG_OPCODE_AND) {
qla8044_rd_reg_indirect(vha, crb_addr, &read_value);
read_value &= crb_entry->value_2;
opcode &= ~QLA82XX_DBG_OPCODE_AND;
if (opcode & QLA82XX_DBG_OPCODE_OR) {
read_value |= crb_entry->value_3;
opcode &= ~QLA82XX_DBG_OPCODE_OR;
@@ -2249,7 +2246,6 @@ qla8044_minidump_process_control(struct scsi_qla_host *vha,
qla8044_rd_reg_indirect(vha, crb_addr, &read_value);
read_value |= crb_entry->value_3;
qla8044_wr_reg_indirect(vha, crb_addr, read_value);
opcode &= ~QLA82XX_DBG_OPCODE_OR;
}
if (opcode & QLA82XX_DBG_OPCODE_POLL) {
poll_time = crb_entry->crb_strd.poll_timeout;
@@ -2269,7 +2265,6 @@ qla8044_minidump_process_control(struct scsi_qla_host *vha,
crb_addr, &read_value);
}
} while (1);
opcode &= ~QLA82XX_DBG_OPCODE_POLL;
}
if (opcode & QLA82XX_DBG_OPCODE_RDSTATE) {
@@ -2283,7 +2278,6 @@ qla8044_minidump_process_control(struct scsi_qla_host *vha,
qla8044_rd_reg_indirect(vha, addr, &read_value);
index = crb_entry->crb_ctrl.state_index_v;
tmplt_hdr->saved_state_array[index] = read_value;
opcode &= ~QLA82XX_DBG_OPCODE_RDSTATE;
}
if (opcode & QLA82XX_DBG_OPCODE_WRSTATE) {
@@ -2303,7 +2297,6 @@ qla8044_minidump_process_control(struct scsi_qla_host *vha,
}
qla8044_wr_reg_indirect(vha, addr, read_value);
opcode &= ~QLA82XX_DBG_OPCODE_WRSTATE;
}
if (opcode & QLA82XX_DBG_OPCODE_MDSTATE) {
@@ -2316,7 +2309,6 @@ qla8044_minidump_process_control(struct scsi_qla_host *vha,
read_value |= crb_entry->value_3;
read_value += crb_entry->value_1;
tmplt_hdr->saved_state_array[index] = read_value;
opcode &= ~QLA82XX_DBG_OPCODE_MDSTATE;
}
crb_addr += crb_entry->crb_strd.addr_stride;
}
+123 -103
View File
@@ -1008,6 +1008,13 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
goto qc24_fail_command;
}
if (!qpair->online) {
ql_dbg(ql_dbg_io, vha, 0x3077,
"qpair not online. eeh_busy=%d.\n", ha->flags.eeh_busy);
cmd->result = DID_NO_CONNECT << 16;
goto qc24_fail_command;
}
if (!fcport || fcport->deleted) {
cmd->result = DID_IMM_RETRY << 16;
goto qc24_fail_command;
@@ -1050,8 +1057,6 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x3078,
"Start scsi failed rval=%d for cmd=%p.\n", rval, cmd);
if (rval == QLA_INTERFACE_ERROR)
goto qc24_free_sp_fail_command;
goto qc24_host_busy_free_sp;
}
@@ -1063,11 +1068,6 @@ qc24_host_busy_free_sp:
qc24_target_busy:
return SCSI_MLQUEUE_TARGET_BUSY;
qc24_free_sp_fail_command:
sp->free(sp);
CMD_SP(cmd) = NULL;
qla2xxx_rel_qpair_sp(sp->qpair, sp);
qc24_fail_command:
cmd->scsi_done(cmd);
@@ -1244,35 +1244,6 @@ qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha)
return return_status;
}
#define ISP_REG_DISCONNECT 0xffffffffU
/**************************************************************************
* qla2x00_isp_reg_stat
*
* Description:
* Read the host status register of ISP before aborting the command.
*
* Input:
* ha = pointer to host adapter structure.
*
*
* Returns:
* Either true or false.
*
* Note: Return true if there is register disconnect.
**************************************************************************/
static inline
uint32_t qla2x00_isp_reg_stat(struct qla_hw_data *ha)
{
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82;
if (IS_P3P_TYPE(ha))
return ((rd_reg_dword(&reg82->host_int)) == ISP_REG_DISCONNECT);
else
return ((rd_reg_dword(&reg->host_status)) ==
ISP_REG_DISCONNECT);
}
/**************************************************************************
* qla2xxx_eh_abort
*
@@ -1306,6 +1277,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
if (qla2x00_isp_reg_stat(ha)) {
ql_log(ql_log_info, vha, 0x8042,
"PCI/Register disconnect, exiting.\n");
qla_pci_set_eeh_busy(vha);
return FAILED;
}
@@ -1499,6 +1471,7 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
if (qla2x00_isp_reg_stat(ha)) {
ql_log(ql_log_info, vha, 0x803e,
"PCI/Register disconnect, exiting.\n");
qla_pci_set_eeh_busy(vha);
return FAILED;
}
@@ -1515,6 +1488,7 @@ qla2xxx_eh_target_reset(struct scsi_cmnd *cmd)
if (qla2x00_isp_reg_stat(ha)) {
ql_log(ql_log_info, vha, 0x803f,
"PCI/Register disconnect, exiting.\n");
qla_pci_set_eeh_busy(vha);
return FAILED;
}
@@ -1550,6 +1524,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
if (qla2x00_isp_reg_stat(ha)) {
ql_log(ql_log_info, vha, 0x8040,
"PCI/Register disconnect, exiting.\n");
qla_pci_set_eeh_busy(vha);
return FAILED;
}
@@ -1627,7 +1602,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
if (qla2x00_isp_reg_stat(ha)) {
ql_log(ql_log_info, vha, 0x8041,
"PCI/Register disconnect, exiting.\n");
schedule_work(&ha->board_disable);
qla_pci_set_eeh_busy(vha);
return SUCCESS;
}
@@ -4286,11 +4261,10 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
/* Get consistent memory allocated for Special Features-CB. */
if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
ha->sf_init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
ha->sf_init_cb = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL,
&ha->sf_init_cb_dma);
if (!ha->sf_init_cb)
goto fail_sf_init_cb;
memset(ha->sf_init_cb, 0, sizeof(struct init_sf_cb));
ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0199,
"sf_init_cb=%p.\n", ha->sf_init_cb);
}
@@ -4692,8 +4666,7 @@ qla2x00_free_fw_dump(struct qla_hw_data *ha)
dma_free_coherent(&ha->pdev->dev,
EFT_SIZE, ha->eft, ha->eft_dma);
if (ha->fw_dump)
vfree(ha->fw_dump);
vfree(ha->fw_dump);
ha->fce = NULL;
ha->fce_dma = 0;
@@ -4707,8 +4680,7 @@ qla2x00_free_fw_dump(struct qla_hw_data *ha)
ha->fw_dump_len = 0;
for (j = 0; j < 2; j++, fwdt++) {
if (fwdt->template)
vfree(fwdt->template);
vfree(fwdt->template);
fwdt->template = NULL;
fwdt->length = 0;
}
@@ -6728,6 +6700,9 @@ qla2x00_do_dpc(void *data)
schedule();
if (test_and_clear_bit(DO_EEH_RECOVERY, &base_vha->dpc_flags))
qla_pci_set_eeh_busy(base_vha);
if (!base_vha->flags.init_done || ha->flags.mbox_busy)
goto end_loop;
@@ -7021,26 +6996,21 @@ intr_on_check:
mutex_unlock(&ha->mq_lock);
}
if (test_and_clear_bit(SET_NVME_ZIO_THRESHOLD_NEEDED,
&base_vha->dpc_flags)) {
ql_log(ql_log_info, base_vha, 0xffffff,
"nvme: SET ZIO Activity exchange threshold to %d.\n",
ha->nvme_last_rptd_aen);
if (qla27xx_set_zio_threshold(base_vha,
ha->nvme_last_rptd_aen)) {
ql_log(ql_log_info, base_vha, 0xffffff,
"nvme: Unable to SET ZIO Activity exchange threshold to %d.\n",
ha->nvme_last_rptd_aen);
}
}
if (test_and_clear_bit(SET_ZIO_THRESHOLD_NEEDED,
&base_vha->dpc_flags)) {
&base_vha->dpc_flags)) {
u16 threshold = ha->nvme_last_rptd_aen + ha->last_zio_threshold;
if (threshold > ha->orig_fw_xcb_count)
threshold = ha->orig_fw_xcb_count;
ql_log(ql_log_info, base_vha, 0xffffff,
"SET ZIO Activity exchange threshold to %d.\n",
ha->last_zio_threshold);
qla27xx_set_zio_threshold(base_vha,
ha->last_zio_threshold);
"SET ZIO Activity exchange threshold to %d.\n",
threshold);
if (qla27xx_set_zio_threshold(base_vha, threshold)) {
ql_log(ql_log_info, base_vha, 0xffffff,
"Unable to SET ZIO Activity exchange threshold to %d.\n",
threshold);
}
}
if (!IS_QLAFX00(ha))
@@ -7270,14 +7240,13 @@ qla2x00_timer(struct timer_list *t)
index = atomic_read(&ha->nvme_active_aen_cnt);
if (!vha->vp_idx &&
(index != ha->nvme_last_rptd_aen) &&
(index >= DEFAULT_ZIO_THRESHOLD) &&
ha->zio_mode == QLA_ZIO_MODE_6 &&
!ha->flags.host_shutting_down) {
ha->nvme_last_rptd_aen = atomic_read(&ha->nvme_active_aen_cnt);
ql_log(ql_log_info, vha, 0x3002,
"nvme: Sched: Set ZIO exchange threshold to %d.\n",
ha->nvme_last_rptd_aen);
ha->nvme_last_rptd_aen = atomic_read(&ha->nvme_active_aen_cnt);
set_bit(SET_NVME_ZIO_THRESHOLD_NEEDED, &vha->dpc_flags);
set_bit(SET_ZIO_THRESHOLD_NEEDED, &vha->dpc_flags);
start_dpc++;
}
@@ -7450,6 +7419,8 @@ static void qla_pci_error_cleanup(scsi_qla_host_t *vha)
int i;
unsigned long flags;
ql_dbg(ql_dbg_aer, vha, 0x9000,
"%s\n", __func__);
ha->chip_reset++;
ha->base_qpair->chip_reset = ha->chip_reset;
@@ -7459,28 +7430,16 @@ static void qla_pci_error_cleanup(scsi_qla_host_t *vha)
ha->base_qpair->chip_reset;
}
/* purge MBox commands */
if (atomic_read(&ha->num_pend_mbx_stage3)) {
clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
complete(&ha->mbx_intr_comp);
}
i = 0;
while (atomic_read(&ha->num_pend_mbx_stage3) ||
atomic_read(&ha->num_pend_mbx_stage2) ||
atomic_read(&ha->num_pend_mbx_stage1)) {
msleep(20);
i++;
if (i > 50)
break;
}
ha->flags.purge_mbox = 0;
/*
* purge mailbox might take a while. Slot Reset/chip reset
* will take care of the purge
*/
mutex_lock(&ha->mq_lock);
ha->base_qpair->online = 0;
list_for_each_entry(qpair, &base_vha->qp_list, qp_list_elem)
qpair->online = 0;
wmb();
mutex_unlock(&ha->mq_lock);
qla2x00_mark_all_devices_lost(vha);
@@ -7517,14 +7476,17 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
{
scsi_qla_host_t *vha = pci_get_drvdata(pdev);
struct qla_hw_data *ha = vha->hw;
pci_ers_result_t ret = PCI_ERS_RESULT_NEED_RESET;
ql_dbg(ql_dbg_aer, vha, 0x9000,
"PCI error detected, state %x.\n", state);
ql_log(ql_log_warn, vha, 0x9000,
"PCI error detected, state %x.\n", state);
ha->pci_error_state = QLA_PCI_ERR_DETECTED;
if (!atomic_read(&pdev->enable_cnt)) {
ql_log(ql_log_info, vha, 0xffff,
"PCI device is disabled,state %x\n", state);
return PCI_ERS_RESULT_NEED_RESET;
ret = PCI_ERS_RESULT_NEED_RESET;
goto out;
}
switch (state) {
@@ -7534,11 +7496,12 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
set_bit(QPAIR_ONLINE_CHECK_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
}
return PCI_ERS_RESULT_CAN_RECOVER;
ret = PCI_ERS_RESULT_CAN_RECOVER;
break;
case pci_channel_io_frozen:
ha->flags.eeh_busy = 1;
qla_pci_error_cleanup(vha);
return PCI_ERS_RESULT_NEED_RESET;
qla_pci_set_eeh_busy(vha);
ret = PCI_ERS_RESULT_NEED_RESET;
break;
case pci_channel_io_perm_failure:
ha->flags.pci_channel_io_perm_failure = 1;
qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16);
@@ -7546,9 +7509,12 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
set_bit(QPAIR_ONLINE_CHECK_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
}
return PCI_ERS_RESULT_DISCONNECT;
ret = PCI_ERS_RESULT_DISCONNECT;
}
return PCI_ERS_RESULT_NEED_RESET;
out:
ql_dbg(ql_dbg_aer, vha, 0x600d,
"PCI error detected returning [%x].\n", ret);
return ret;
}
static pci_ers_result_t
@@ -7562,6 +7528,10 @@ qla2xxx_pci_mmio_enabled(struct pci_dev *pdev)
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;
ql_log(ql_log_warn, base_vha, 0x9000,
"mmio enabled\n");
ha->pci_error_state = QLA_PCI_MMIO_ENABLED;
if (IS_QLA82XX(ha))
return PCI_ERS_RESULT_RECOVERED;
@@ -7585,10 +7555,11 @@ qla2xxx_pci_mmio_enabled(struct pci_dev *pdev)
ql_log(ql_log_info, base_vha, 0x9003,
"RISC paused -- mmio_enabled, Dumping firmware.\n");
qla2xxx_dump_fw(base_vha);
return PCI_ERS_RESULT_NEED_RESET;
} else
return PCI_ERS_RESULT_RECOVERED;
}
/* set PCI_ERS_RESULT_NEED_RESET to trigger call to qla2xxx_pci_slot_reset */
ql_dbg(ql_dbg_aer, base_vha, 0x600d,
"mmio enabled returning.\n");
return PCI_ERS_RESULT_NEED_RESET;
}
static pci_ers_result_t
@@ -7600,9 +7571,10 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
int rc;
struct qla_qpair *qpair = NULL;
ql_dbg(ql_dbg_aer, base_vha, 0x9004,
"Slot Reset.\n");
ql_log(ql_log_warn, base_vha, 0x9004,
"Slot Reset.\n");
ha->pci_error_state = QLA_PCI_SLOT_RESET;
/* Workaround: qla2xxx driver which access hardware earlier
* needs error state to be pci_channel_io_online.
* Otherwise mailbox command timesout.
@@ -7636,16 +7608,24 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
qpair->online = 1;
mutex_unlock(&ha->mq_lock);
ha->flags.eeh_busy = 0;
base_vha->flags.online = 1;
set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
if (ha->isp_ops->abort_isp(base_vha) == QLA_SUCCESS)
ret = PCI_ERS_RESULT_RECOVERED;
ha->isp_ops->abort_isp(base_vha);
clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
if (qla2x00_isp_reg_stat(ha)) {
ha->flags.eeh_busy = 1;
qla_pci_error_cleanup(base_vha);
ql_log(ql_log_warn, base_vha, 0x9005,
"Device unable to recover from PCI error.\n");
} else {
ret = PCI_ERS_RESULT_RECOVERED;
}
exit_slot_reset:
ql_dbg(ql_dbg_aer, base_vha, 0x900e,
"slot_reset return %x.\n", ret);
"Slot Reset returning %x.\n", ret);
return ret;
}
@@ -7657,16 +7637,55 @@ qla2xxx_pci_resume(struct pci_dev *pdev)
struct qla_hw_data *ha = base_vha->hw;
int ret;
ql_dbg(ql_dbg_aer, base_vha, 0x900f,
"pci_resume.\n");
ql_log(ql_log_warn, base_vha, 0x900f,
"Pci Resume.\n");
ha->flags.eeh_busy = 0;
ret = qla2x00_wait_for_hba_online(base_vha);
if (ret != QLA_SUCCESS) {
ql_log(ql_log_fatal, base_vha, 0x9002,
"The device failed to resume I/O from slot/link_reset.\n");
}
ha->pci_error_state = QLA_PCI_RESUME;
ql_dbg(ql_dbg_aer, base_vha, 0x600d,
"Pci Resume returning.\n");
}
void qla_pci_set_eeh_busy(struct scsi_qla_host *vha)
{
struct qla_hw_data *ha = vha->hw;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
bool do_cleanup = false;
unsigned long flags;
if (ha->flags.eeh_busy)
return;
spin_lock_irqsave(&base_vha->work_lock, flags);
if (!ha->flags.eeh_busy) {
ha->flags.eeh_busy = 1;
do_cleanup = true;
}
spin_unlock_irqrestore(&base_vha->work_lock, flags);
if (do_cleanup)
qla_pci_error_cleanup(base_vha);
}
/*
* this routine will schedule a task to pause IO from interrupt context
* if caller sees a PCIE error event (register read = 0xf's)
*/
void qla_schedule_eeh_work(struct scsi_qla_host *vha)
{
struct qla_hw_data *ha = vha->hw;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
if (ha->flags.eeh_busy)
return;
set_bit(DO_EEH_RECOVERY, &base_vha->dpc_flags);
qla2xxx_wake_dpc(base_vha);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
@@ -7774,6 +7793,7 @@ struct scsi_host_template qla2xxx_driver_template = {
.eh_timed_out = fc_eh_timed_out,
#endif
.eh_abort_handler = qla2xxx_eh_abort,
.eh_should_retry_cmd = fc_eh_should_retry_cmd,
.eh_device_reset_handler = qla2xxx_eh_device_reset,
.eh_target_reset_handler = qla2xxx_eh_target_reset,
.eh_bus_reset_handler = qla2xxx_eh_bus_reset,
+5 -4
View File
@@ -2621,10 +2621,11 @@ qla24xx_read_optrom_data(struct scsi_qla_host *vha, void *buf,
}
static int
qla28xx_extract_sfub_and_verify(struct scsi_qla_host *vha, uint32_t *buf,
qla28xx_extract_sfub_and_verify(struct scsi_qla_host *vha, __le32 *buf,
uint32_t len, uint32_t buf_size_without_sfub, uint8_t *sfub_buf)
{
uint32_t *p, check_sum = 0;
uint32_t check_sum = 0;
__le32 *p;
int i;
p = buf + buf_size_without_sfub;
@@ -2790,8 +2791,8 @@ qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
goto done;
}
rval = qla28xx_extract_sfub_and_verify(vha, dwptr, dwords,
buf_size_without_sfub, (uint8_t *)sfub);
rval = qla28xx_extract_sfub_and_verify(vha, (__le32 *)dwptr,
dwords, buf_size_without_sfub, (uint8_t *)sfub);
if (rval != QLA_SUCCESS)
goto done;
+8 -3
View File
@@ -1044,7 +1044,12 @@ void qlt_free_session_done(struct work_struct *work)
}
msleep(100);
cnt++;
if (cnt > 200)
/*
* Driver timeout is set to 22 Sec, update count value to loop
* long enough for log-out to complete before advancing. Otherwise,
* straddling logout can interfere with re-login attempt.
*/
if (cnt > 230)
break;
}
@@ -6527,7 +6532,7 @@ static void qlt_lport_dump(struct scsi_qla_host *vha, u64 wwpn,
}
/**
* qla_tgt_lport_register - register lport with external module
* qlt_lport_register - register lport with external module
*
* @target_lport_ptr: pointer for tcm_qla2xxx specific lport data
* @phys_wwpn: physical port WWPN
@@ -6603,7 +6608,7 @@ int qlt_lport_register(void *target_lport_ptr, u64 phys_wwpn,
EXPORT_SYMBOL(qlt_lport_register);
/**
* qla_tgt_lport_deregister - Degister lport
* qlt_lport_deregister - Degister lport
*
* @vha: Registered scsi_qla_host pointer
*/
+1 -1
View File
@@ -143,7 +143,6 @@
(min(1270, ((ql) > 0) ? (QLA_TGT_DATASEGS_PER_CMD_24XX + \
QLA_TGT_DATASEGS_PER_CONT_24XX*((ql) - 1)) : 0))
#endif
#endif
#define GET_TARGET_ID(ha, iocb) ((HAS_EXTENDED_IDS(ha)) \
? le16_to_cpu((iocb)->u.isp2x.target.extended) \
@@ -271,6 +270,7 @@ struct ctio_to_2xxx {
#ifndef CTIO_RET_TYPE
#define CTIO_RET_TYPE 0x17 /* CTIO return entry */
#define ATIO_TYPE7 0x06 /* Accept target I/O entry for 24xx */
#endif
struct fcp_hdr {
uint8_t r_ctl;
+2 -2
View File
@@ -6,9 +6,9 @@
/*
* Driver version
*/
#define QLA2XXX_VERSION "10.02.00.105-k"
#define QLA2XXX_VERSION "10.02.00.106-k"
#define QLA_DRIVER_MAJOR_VER 10
#define QLA_DRIVER_MINOR_VER 2
#define QLA_DRIVER_PATCH_VER 0
#define QLA_DRIVER_BETA_VER 105
#define QLA_DRIVER_BETA_VER 106