Merge patch series "qla2xxx target mode improvements"
Tony Battersby <tonyb@cybernetics.com> says: This patch series improves the qla2xxx FC driver in target mode. I developed these patches using the out-of-tree SCST target-mode subsystem (https://scst.sourceforge.net/), although most of the improvements will also apply to the other target-mode subsystems such as the in-tree LIO. Unfortunately qla2xxx+LIO does not pass all of my tests, but my patches do not make it any worse (results below). These patches have been well-tested at my employer with qla2xxx+SCST in both initiator mode and target mode and with a variety of FC HBAs and initiators. Since SCST is out-of-tree, some of the patches have parts that apply in-tree and other parts that apply out-of-tree to SCST. The SCST patches can be found in the v2 posting linked above. All patches apply to linux 6.17 and SCST 3.10 master branch. Summary of patches: - bugfixes - cleanups - improve handling of aborts and task management requests - improve log message - add back SLER / SRR support (removed in 2017) Some of these patches improve handling of aborts and task management requests. This is some of the testing that I did: Test 1: Use /dev/sg to queue random disk I/O with short timeouts; make sure cmds are aborted successfully. Test 2: Queue lots of disk I/O, then use "sg_reset -N -d /dev/sg" on initiator to reset logical unit. Test 3: Queue lots of disk I/O, then use "sg_reset -N -t /dev/sg" on initiator to reset target. Test 4: Queue lots of disk I/O, then use "sg_reset -N -b /dev/sg" on initiator to reset bus. Test 5: Queue lots of disk I/O, then use "sg_reset -N -H /dev/sg" on initiator to reset host. Test 6: Use fiber channel attenuator to trigger SRR during write/read/compare test; check data integrity. With my patches, SCST passes all of these tests. Results with in-tree LIO target-mode subsystem: Test 1: Seems to abort the same cmd multiple times (both qlt_24xx_retry_term_exchange() and __qlt_send_term_exchange()). But cmds get aborted, so give it a pass? Test 2: Seems to work; cmds are aborted. Test 3: Target reset doesn't seem to abort cmds, instead, a few seconds later: qla2xxx [0000:04:00.0]-f058:9: qla_target(0): tag 1314312, op 2a: CTIO with TIMEOUT status 0xb received (state 1, port 51:40:2e:c0:18:1d:9f:cc, LUN 0) Tests 4 and 5: The initiator is unable to log back in to the target; the following messages are repeated over and over on the target: qla2xxx [0000:04:00.0]-e01c:9: Sending TERM ELS CTIO (ha=00000000f8811390) qla2xxx [0000:04:00.0]-f097:9: Linking sess 000000008df5aba8 [0] wwn 51:40:2e:c0:18:1d:9f:cc with PLOGI ACK to wwn 51:40:2e:c0:18:1d:9f:cc s_id 00:00:01, ref=2 pla 00000000835a9271 link 0 Test 6: passes with my patches; SRR not supported previously. So qla2xxx+LIO seems a bit flaky when handling exceptions, but my patches do not make it any worse. Perhaps someone who is more familiar with LIO can look at the difference between LIO and SCST and figure out how to improve it. Tony Battersby https://www.cybernetics.com/ v1: https://lore.kernel.org/r/f8977250-638c-4d7d-ac0c-65f742b8d535@cybernetics.com/ v2: https://lore.kernel.org/linux-scsi/e95ee7d0-3580-4124-b854-7f73ca3a3a84@cybernetics.com/ Link: https://patch.msgid.link/aaea0ab0-da8b-4153-9369-60db7507ff7a@cybernetics.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
@@ -54,10 +54,11 @@
|
|||||||
* | Misc | 0xd303 | 0xd031-0xd0ff |
|
* | Misc | 0xd303 | 0xd031-0xd0ff |
|
||||||
* | | | 0xd101-0xd1fe |
|
* | | | 0xd101-0xd1fe |
|
||||||
* | | | 0xd214-0xd2fe |
|
* | | | 0xd214-0xd2fe |
|
||||||
* | Target Mode | 0xe081 | |
|
* | Target Mode | 0xe089 | |
|
||||||
* | Target Mode Management | 0xf09b | 0xf002 |
|
* | Target Mode Management | 0xf09b | 0xf002 |
|
||||||
* | | | 0xf046-0xf049 |
|
* | | | 0xf046-0xf049 |
|
||||||
* | Target Mode Task Management | 0x1000d | |
|
* | Target Mode Task Management | 0x1000d | |
|
||||||
|
* | Target Mode SRR | 0x11038 | |
|
||||||
* ----------------------------------------------------------------------
|
* ----------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -3503,7 +3503,6 @@ struct isp_operations {
|
|||||||
#define QLA_MSIX_RSP_Q 0x01
|
#define QLA_MSIX_RSP_Q 0x01
|
||||||
#define QLA_ATIO_VECTOR 0x02
|
#define QLA_ATIO_VECTOR 0x02
|
||||||
#define QLA_MSIX_QPAIR_MULTIQ_RSP_Q 0x03
|
#define QLA_MSIX_QPAIR_MULTIQ_RSP_Q 0x03
|
||||||
#define QLA_MSIX_QPAIR_MULTIQ_RSP_Q_HS 0x04
|
|
||||||
|
|
||||||
#define QLA_MIDX_DEFAULT 0
|
#define QLA_MIDX_DEFAULT 0
|
||||||
#define QLA_MIDX_RSP_Q 1
|
#define QLA_MIDX_RSP_Q 1
|
||||||
|
|||||||
@@ -766,7 +766,7 @@ extern int qla2x00_dfs_remove(scsi_qla_host_t *);
|
|||||||
|
|
||||||
/* Globa function prototypes for multi-q */
|
/* Globa function prototypes for multi-q */
|
||||||
extern int qla25xx_request_irq(struct qla_hw_data *, struct qla_qpair *,
|
extern int qla25xx_request_irq(struct qla_hw_data *, struct qla_qpair *,
|
||||||
struct qla_msix_entry *, int);
|
struct qla_msix_entry *);
|
||||||
extern int qla25xx_init_req_que(struct scsi_qla_host *, struct req_que *);
|
extern int qla25xx_init_req_que(struct scsi_qla_host *, struct req_que *);
|
||||||
extern int qla25xx_init_rsp_que(struct scsi_qla_host *, struct rsp_que *);
|
extern int qla25xx_init_rsp_que(struct scsi_qla_host *, struct rsp_que *);
|
||||||
extern int qla25xx_create_req_que(struct qla_hw_data *, uint16_t, uint8_t,
|
extern int qla25xx_create_req_que(struct qla_hw_data *, uint16_t, uint8_t,
|
||||||
|
|||||||
@@ -4369,6 +4369,7 @@ enable_82xx_npiv:
|
|||||||
ha->max_npiv_vports =
|
ha->max_npiv_vports =
|
||||||
MIN_MULTI_ID_FABRIC - 1;
|
MIN_MULTI_ID_FABRIC - 1;
|
||||||
}
|
}
|
||||||
|
qlt_config_nvram_with_fw_version(vha);
|
||||||
qla2x00_get_resource_cnts(vha);
|
qla2x00_get_resource_cnts(vha);
|
||||||
qla_init_iocb_limit(vha);
|
qla_init_iocb_limit(vha);
|
||||||
|
|
||||||
|
|||||||
@@ -4467,32 +4467,6 @@ qla2xxx_msix_rsp_q(int irq, void *dev_id)
|
|||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
irqreturn_t
|
|
||||||
qla2xxx_msix_rsp_q_hs(int irq, void *dev_id)
|
|
||||||
{
|
|
||||||
struct qla_hw_data *ha;
|
|
||||||
struct qla_qpair *qpair;
|
|
||||||
struct device_reg_24xx __iomem *reg;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
qpair = dev_id;
|
|
||||||
if (!qpair) {
|
|
||||||
ql_log(ql_log_info, NULL, 0x505b,
|
|
||||||
"%s: NULL response queue pointer.\n", __func__);
|
|
||||||
return IRQ_NONE;
|
|
||||||
}
|
|
||||||
ha = qpair->hw;
|
|
||||||
|
|
||||||
reg = &ha->iobase->isp24;
|
|
||||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
|
||||||
wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_INT);
|
|
||||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
|
||||||
|
|
||||||
queue_work(ha->wq, &qpair->q_work);
|
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Interrupt handling helpers. */
|
/* Interrupt handling helpers. */
|
||||||
|
|
||||||
struct qla_init_msix_entry {
|
struct qla_init_msix_entry {
|
||||||
@@ -4505,7 +4479,6 @@ static const struct qla_init_msix_entry msix_entries[] = {
|
|||||||
{ "rsp_q", qla24xx_msix_rsp_q },
|
{ "rsp_q", qla24xx_msix_rsp_q },
|
||||||
{ "atio_q", qla83xx_msix_atio_q },
|
{ "atio_q", qla83xx_msix_atio_q },
|
||||||
{ "qpair_multiq", qla2xxx_msix_rsp_q },
|
{ "qpair_multiq", qla2xxx_msix_rsp_q },
|
||||||
{ "qpair_multiq_hs", qla2xxx_msix_rsp_q_hs },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct qla_init_msix_entry qla82xx_msix_entries[] = {
|
static const struct qla_init_msix_entry qla82xx_msix_entries[] = {
|
||||||
@@ -4792,9 +4765,10 @@ free_irqs:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int qla25xx_request_irq(struct qla_hw_data *ha, struct qla_qpair *qpair,
|
int qla25xx_request_irq(struct qla_hw_data *ha, struct qla_qpair *qpair,
|
||||||
struct qla_msix_entry *msix, int vector_type)
|
struct qla_msix_entry *msix)
|
||||||
{
|
{
|
||||||
const struct qla_init_msix_entry *intr = &msix_entries[vector_type];
|
const struct qla_init_msix_entry *intr =
|
||||||
|
&msix_entries[QLA_MSIX_QPAIR_MULTIQ_RSP_Q];
|
||||||
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
|
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
|||||||
@@ -253,6 +253,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
|
|||||||
/* Issue set host interrupt command to send cmd out. */
|
/* Issue set host interrupt command to send cmd out. */
|
||||||
ha->flags.mbox_int = 0;
|
ha->flags.mbox_int = 0;
|
||||||
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
|
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
|
||||||
|
reinit_completion(&ha->mbx_intr_comp);
|
||||||
|
|
||||||
/* Unlock mbx registers and wait for interrupt */
|
/* Unlock mbx registers and wait for interrupt */
|
||||||
ql_dbg(ql_dbg_mbx, vha, 0x100f,
|
ql_dbg(ql_dbg_mbx, vha, 0x100f,
|
||||||
@@ -279,6 +280,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
|
|||||||
"cmd=%x Timeout.\n", command);
|
"cmd=%x Timeout.\n", command);
|
||||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||||
clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
|
clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
|
||||||
|
reinit_completion(&ha->mbx_intr_comp);
|
||||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||||
|
|
||||||
if (chip_reset != ha->chip_reset) {
|
if (chip_reset != ha->chip_reset) {
|
||||||
|
|||||||
@@ -899,9 +899,7 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
|
|||||||
rsp->options, rsp->id, rsp->rsp_q_in,
|
rsp->options, rsp->id, rsp->rsp_q_in,
|
||||||
rsp->rsp_q_out);
|
rsp->rsp_q_out);
|
||||||
|
|
||||||
ret = qla25xx_request_irq(ha, qpair, qpair->msix,
|
ret = qla25xx_request_irq(ha, qpair, qpair->msix);
|
||||||
ha->flags.disable_msix_handshake ?
|
|
||||||
QLA_MSIX_QPAIR_MULTIQ_RSP_Q : QLA_MSIX_QPAIR_MULTIQ_RSP_Q_HS);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
goto que_failed;
|
goto que_failed;
|
||||||
|
|
||||||
|
|||||||
@@ -1862,12 +1862,6 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)
|
|||||||
for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
|
for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
|
||||||
sp = req->outstanding_cmds[cnt];
|
sp = req->outstanding_cmds[cnt];
|
||||||
if (sp) {
|
if (sp) {
|
||||||
if (qla2x00_chip_is_down(vha)) {
|
|
||||||
req->outstanding_cmds[cnt] = NULL;
|
|
||||||
sp->done(sp, res);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (sp->cmd_type) {
|
switch (sp->cmd_type) {
|
||||||
case TYPE_SRB:
|
case TYPE_SRB:
|
||||||
qla2x00_abort_srb(qp, sp, res, &flags);
|
qla2x00_abort_srb(qp, sp, res, &flags);
|
||||||
@@ -1881,10 +1875,26 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
cmd = (struct qla_tgt_cmd *)sp;
|
cmd = (struct qla_tgt_cmd *)sp;
|
||||||
cmd->aborted = 1;
|
|
||||||
|
if (cmd->sg_mapped)
|
||||||
|
qlt_unmap_sg(vha, cmd);
|
||||||
|
|
||||||
|
if (cmd->state == QLA_TGT_STATE_NEED_DATA) {
|
||||||
|
cmd->aborted = 1;
|
||||||
|
cmd->write_data_transferred = 0;
|
||||||
|
cmd->state = QLA_TGT_STATE_DATA_IN;
|
||||||
|
ha->tgt.tgt_ops->handle_data(cmd);
|
||||||
|
} else {
|
||||||
|
ha->tgt.tgt_ops->free_cmd(cmd);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TYPE_TGT_TMCMD:
|
case TYPE_TGT_TMCMD:
|
||||||
/* Skip task management functions. */
|
/*
|
||||||
|
* Currently, only ABTS response gets on the
|
||||||
|
* outstanding_cmds[]
|
||||||
|
*/
|
||||||
|
qlt_free_ul_mcmd(ha,
|
||||||
|
(struct qla_tgt_mgmt_cmd *) sp);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -3444,13 +3454,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||||||
ha->mqenable = 0;
|
ha->mqenable = 0;
|
||||||
|
|
||||||
if (ha->mqenable) {
|
if (ha->mqenable) {
|
||||||
bool startit = false;
|
bool startit = !!(host->active_mode & MODE_INITIATOR);
|
||||||
|
|
||||||
if (QLA_TGT_MODE_ENABLED())
|
|
||||||
startit = false;
|
|
||||||
|
|
||||||
if (ql2x_ini_mode == QLA2XXX_INI_MODE_ENABLED)
|
|
||||||
startit = true;
|
|
||||||
|
|
||||||
/* Create start of day qpairs for Block MQ */
|
/* Create start of day qpairs for Block MQ */
|
||||||
for (i = 0; i < ha->max_qpairs; i++)
|
for (i = 0; i < ha->max_qpairs; i++)
|
||||||
@@ -7244,6 +7248,7 @@ qla2xxx_wake_dpc(struct scsi_qla_host *vha)
|
|||||||
if (!test_bit(UNLOADING, &vha->dpc_flags) && t)
|
if (!test_bit(UNLOADING, &vha->dpc_flags) && t)
|
||||||
wake_up_process(t);
|
wake_up_process(t);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(qla2xxx_wake_dpc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* qla2x00_rst_aen
|
* qla2x00_rst_aen
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -184,6 +184,7 @@ struct nack_to_isp {
|
|||||||
#define NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM 0x9
|
#define NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM 0x9
|
||||||
|
|
||||||
#define NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL 0
|
#define NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL 0
|
||||||
|
#define NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_INVALID_OX_ID_RX_ID 0x17
|
||||||
#define NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_UNABLE_TO_SUPPLY_DATA 0x2a
|
#define NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_UNABLE_TO_SUPPLY_DATA 0x2a
|
||||||
|
|
||||||
#define NOTIFY_ACK_SUCCESS 0x01
|
#define NOTIFY_ACK_SUCCESS 0x01
|
||||||
@@ -686,6 +687,8 @@ struct qla_tgt_func_tmpl {
|
|||||||
int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, u64, uint16_t,
|
int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, u64, uint16_t,
|
||||||
uint32_t);
|
uint32_t);
|
||||||
struct qla_tgt_cmd *(*get_cmd)(struct fc_port *);
|
struct qla_tgt_cmd *(*get_cmd)(struct fc_port *);
|
||||||
|
int (*get_cmd_ref)(struct qla_tgt_cmd *cmd);
|
||||||
|
void (*put_cmd_ref)(struct qla_tgt_cmd *cmd);
|
||||||
void (*rel_cmd)(struct qla_tgt_cmd *);
|
void (*rel_cmd)(struct qla_tgt_cmd *);
|
||||||
void (*free_cmd)(struct qla_tgt_cmd *);
|
void (*free_cmd)(struct qla_tgt_cmd *);
|
||||||
void (*free_mcmd)(struct qla_tgt_mgmt_cmd *);
|
void (*free_mcmd)(struct qla_tgt_mgmt_cmd *);
|
||||||
@@ -754,6 +757,7 @@ int qla2x00_wait_for_hba_online(struct scsi_qla_host *);
|
|||||||
#define QLA_TGT_STATE_NEED_DATA 1 /* target needs data to continue */
|
#define QLA_TGT_STATE_NEED_DATA 1 /* target needs data to continue */
|
||||||
#define QLA_TGT_STATE_DATA_IN 2 /* Data arrived + target processing */
|
#define QLA_TGT_STATE_DATA_IN 2 /* Data arrived + target processing */
|
||||||
#define QLA_TGT_STATE_PROCESSED 3 /* target done processing */
|
#define QLA_TGT_STATE_PROCESSED 3 /* target done processing */
|
||||||
|
#define QLA_TGT_STATE_DONE 4 /* cmd being freed */
|
||||||
|
|
||||||
/* ATIO task_codes field */
|
/* ATIO task_codes field */
|
||||||
#define ATIO_SIMPLE_QUEUE 0
|
#define ATIO_SIMPLE_QUEUE 0
|
||||||
@@ -822,18 +826,26 @@ struct qla_tgt {
|
|||||||
int notify_ack_expected;
|
int notify_ack_expected;
|
||||||
int abts_resp_expected;
|
int abts_resp_expected;
|
||||||
int modify_lun_expected;
|
int modify_lun_expected;
|
||||||
|
|
||||||
|
spinlock_t srr_lock;
|
||||||
|
struct list_head srr_list;
|
||||||
|
struct work_struct srr_work;
|
||||||
|
|
||||||
atomic_t tgt_global_resets_count;
|
atomic_t tgt_global_resets_count;
|
||||||
|
|
||||||
struct list_head tgt_list_entry;
|
struct list_head tgt_list_entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct qla_tgt_sess_op {
|
struct qla_tgt_sess_op {
|
||||||
struct scsi_qla_host *vha;
|
struct scsi_qla_host *vha;
|
||||||
uint32_t chip_reset;
|
uint32_t chip_reset;
|
||||||
struct atio_from_isp atio;
|
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
struct list_head cmd_list;
|
struct list_head cmd_list;
|
||||||
bool aborted;
|
bool aborted;
|
||||||
struct rsp_que *rsp;
|
struct rsp_que *rsp;
|
||||||
|
|
||||||
|
struct atio_from_isp atio;
|
||||||
|
/* DO NOT ADD ANYTHING ELSE HERE - atio must be last member */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum trace_flags {
|
enum trace_flags {
|
||||||
@@ -858,6 +870,7 @@ enum trace_flags {
|
|||||||
TRC_DATA_IN = BIT_18,
|
TRC_DATA_IN = BIT_18,
|
||||||
TRC_ABORT = BIT_19,
|
TRC_ABORT = BIT_19,
|
||||||
TRC_DIF_ERR = BIT_20,
|
TRC_DIF_ERR = BIT_20,
|
||||||
|
TRC_SRR_IMM = BIT_21,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct qla_tgt_cmd {
|
struct qla_tgt_cmd {
|
||||||
@@ -876,25 +889,36 @@ struct qla_tgt_cmd {
|
|||||||
/* Sense buffer that will be mapped into outgoing status */
|
/* Sense buffer that will be mapped into outgoing status */
|
||||||
unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER];
|
unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER];
|
||||||
|
|
||||||
spinlock_t cmd_lock;
|
|
||||||
/* to save extra sess dereferences */
|
|
||||||
unsigned int conf_compl_supported:1;
|
unsigned int conf_compl_supported:1;
|
||||||
unsigned int sg_mapped:1;
|
unsigned int sg_mapped:1;
|
||||||
|
|
||||||
|
/* Call qlt_free_sg() if set. */
|
||||||
|
unsigned int free_sg:1;
|
||||||
|
|
||||||
unsigned int write_data_transferred:1;
|
unsigned int write_data_transferred:1;
|
||||||
|
|
||||||
|
/* Set if the SCSI status was sent successfully. */
|
||||||
|
unsigned int rsp_sent:1;
|
||||||
|
|
||||||
unsigned int q_full:1;
|
unsigned int q_full:1;
|
||||||
unsigned int term_exchg:1;
|
unsigned int term_exchg:1;
|
||||||
unsigned int cmd_sent_to_fw:1;
|
unsigned int cmd_sent_to_fw:1;
|
||||||
unsigned int cmd_in_wq:1;
|
unsigned int cmd_in_wq:1;
|
||||||
unsigned int edif:1;
|
unsigned int edif:1;
|
||||||
|
|
||||||
/*
|
/* Set if a SRR was rejected. */
|
||||||
* This variable may be set from outside the LIO and I/O completion
|
unsigned int srr_failed:1;
|
||||||
* callback functions. Do not declare this member variable as a
|
|
||||||
* bitfield to avoid a read-modify-write operation when this variable
|
|
||||||
* is set.
|
|
||||||
*/
|
|
||||||
unsigned int aborted;
|
|
||||||
|
|
||||||
|
/* Set if the exchange has been terminated. */
|
||||||
|
unsigned int sent_term_exchg:1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set if sent_term_exchg is set, or if the cmd was aborted by a TMR,
|
||||||
|
* or if some other error prevents normal processing of the command.
|
||||||
|
*/
|
||||||
|
unsigned int aborted:1;
|
||||||
|
|
||||||
|
struct qla_tgt_srr *srr;
|
||||||
struct scatterlist *sg; /* cmd data buffer SG vector */
|
struct scatterlist *sg; /* cmd data buffer SG vector */
|
||||||
int sg_cnt; /* SG segments count */
|
int sg_cnt; /* SG segments count */
|
||||||
int bufflen; /* cmd buffer length */
|
int bufflen; /* cmd buffer length */
|
||||||
@@ -925,13 +949,23 @@ struct qla_tgt_cmd {
|
|||||||
uint8_t scsi_status, sense_key, asc, ascq;
|
uint8_t scsi_status, sense_key, asc, ascq;
|
||||||
|
|
||||||
struct crc_context *ctx;
|
struct crc_context *ctx;
|
||||||
const uint8_t *cdb;
|
uint8_t *cdb;
|
||||||
uint64_t lba;
|
uint64_t lba;
|
||||||
|
int cdb_len;
|
||||||
uint16_t a_guard, e_guard, a_app_tag, e_app_tag;
|
uint16_t a_guard, e_guard, a_app_tag, e_app_tag;
|
||||||
uint32_t a_ref_tag, e_ref_tag;
|
uint32_t a_ref_tag, e_ref_tag;
|
||||||
#define DIF_BUNDL_DMA_VALID 1
|
#define DIF_BUNDL_DMA_VALID 1
|
||||||
uint16_t prot_flags;
|
uint16_t prot_flags;
|
||||||
|
|
||||||
|
unsigned long jiffies_at_term_exchg;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* jiffies64 when qlt_rdy_to_xfer() or qlt_xmit_response() first
|
||||||
|
* called, or 0 when not in those states. Used to limit the number of
|
||||||
|
* SRR retries.
|
||||||
|
*/
|
||||||
|
uint64_t jiffies_at_hw_st_entry;
|
||||||
|
|
||||||
uint64_t jiffies_at_alloc;
|
uint64_t jiffies_at_alloc;
|
||||||
uint64_t jiffies_at_free;
|
uint64_t jiffies_at_free;
|
||||||
|
|
||||||
@@ -965,6 +999,7 @@ struct qla_tgt_mgmt_cmd {
|
|||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
#define QLA24XX_MGMT_SEND_NACK BIT_0
|
#define QLA24XX_MGMT_SEND_NACK BIT_0
|
||||||
#define QLA24XX_MGMT_ABORT_IO_ATTR_VALID BIT_1
|
#define QLA24XX_MGMT_ABORT_IO_ATTR_VALID BIT_1
|
||||||
|
#define QLA24XX_MGMT_LLD_OWNED BIT_2
|
||||||
uint32_t reset_count;
|
uint32_t reset_count;
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
uint64_t unpacked_lun;
|
uint64_t unpacked_lun;
|
||||||
@@ -993,6 +1028,45 @@ struct qla_tgt_prm {
|
|||||||
uint16_t tot_dsds;
|
uint16_t tot_dsds;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SRR (Sequence Retransmission Request) - resend or re-receive some or all
|
||||||
|
* data or status to recover from a transient I/O error.
|
||||||
|
*/
|
||||||
|
struct qla_tgt_srr {
|
||||||
|
/*
|
||||||
|
* Copy of immediate notify SRR message received from hw; valid only if
|
||||||
|
* imm_ntfy_recvd is true.
|
||||||
|
*/
|
||||||
|
struct imm_ntfy_from_isp imm_ntfy;
|
||||||
|
|
||||||
|
struct list_head srr_list_entry;
|
||||||
|
|
||||||
|
/* The command affected by this SRR, or NULL if not yet determined. */
|
||||||
|
struct qla_tgt_cmd *cmd;
|
||||||
|
|
||||||
|
/* Used to detect if the HBA has been reset since receiving the SRR. */
|
||||||
|
uint32_t reset_count;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The hardware sends two messages for each SRR - an immediate notify
|
||||||
|
* and a CTIO with CTIO_SRR_RECEIVED status. These keep track of which
|
||||||
|
* messages have been received. The SRR can be processed once both of
|
||||||
|
* these are true.
|
||||||
|
*/
|
||||||
|
bool imm_ntfy_recvd;
|
||||||
|
bool ctio_recvd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is set to true if the affected command was aborted (cmd may be
|
||||||
|
* set to NULL), in which case the immediate notify exchange also needs
|
||||||
|
* to be aborted.
|
||||||
|
*/
|
||||||
|
bool aborted;
|
||||||
|
|
||||||
|
/* This is set to true to force the SRR to be rejected. */
|
||||||
|
bool reject;
|
||||||
|
};
|
||||||
|
|
||||||
/* Check for Switch reserved address */
|
/* Check for Switch reserved address */
|
||||||
#define IS_SW_RESV_ADDR(_s_id) \
|
#define IS_SW_RESV_ADDR(_s_id) \
|
||||||
((_s_id.b.domain == 0xff) && ((_s_id.b.area & 0xf0) == 0xf0))
|
((_s_id.b.domain == 0xff) && ((_s_id.b.area & 0xf0) == 0xf0))
|
||||||
@@ -1047,6 +1121,20 @@ static inline uint32_t sid_to_key(const be_id_t s_id)
|
|||||||
s_id.al_pa;
|
s_id.al_pa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free the scatterlist allocated by qlt_set_data_offset(). Call this only if
|
||||||
|
* cmd->free_sg is set.
|
||||||
|
*/
|
||||||
|
static inline void qlt_free_sg(struct qla_tgt_cmd *cmd)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The scatterlist may be chained to the original scatterlist, but we
|
||||||
|
* only need to free the first segment here since that is the only part
|
||||||
|
* allocated by qlt_set_data_offset().
|
||||||
|
*/
|
||||||
|
kfree(cmd->sg);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exported symbols from qla_target.c LLD logic used by qla2xxx code..
|
* Exported symbols from qla_target.c LLD logic used by qla2xxx code..
|
||||||
*/
|
*/
|
||||||
@@ -1055,9 +1143,14 @@ extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, struct rsp_que *,
|
|||||||
extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *);
|
extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *);
|
||||||
extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t);
|
extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t);
|
||||||
extern int qlt_abort_cmd(struct qla_tgt_cmd *);
|
extern int qlt_abort_cmd(struct qla_tgt_cmd *);
|
||||||
|
void qlt_srr_abort(struct qla_tgt_cmd *cmd, bool reject);
|
||||||
|
void qlt_send_term_exchange(struct qla_qpair *qpair,
|
||||||
|
struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked);
|
||||||
extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *);
|
extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *);
|
||||||
|
void qlt_free_ul_mcmd(struct qla_hw_data *ha, struct qla_tgt_mgmt_cmd *mcmd);
|
||||||
extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *);
|
extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *);
|
||||||
extern void qlt_free_cmd(struct qla_tgt_cmd *cmd);
|
extern void qlt_free_cmd(struct qla_tgt_cmd *cmd);
|
||||||
|
extern void qlt_unmap_sg(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd);
|
||||||
extern void qlt_async_event(uint16_t, struct scsi_qla_host *, uint16_t *);
|
extern void qlt_async_event(uint16_t, struct scsi_qla_host *, uint16_t *);
|
||||||
extern void qlt_enable_vha(struct scsi_qla_host *);
|
extern void qlt_enable_vha(struct scsi_qla_host *);
|
||||||
extern void qlt_vport_create(struct scsi_qla_host *, struct qla_hw_data *);
|
extern void qlt_vport_create(struct scsi_qla_host *, struct qla_hw_data *);
|
||||||
@@ -1073,6 +1166,7 @@ extern void qlt_81xx_config_nvram_stage2(struct scsi_qla_host *,
|
|||||||
struct init_cb_81xx *);
|
struct init_cb_81xx *);
|
||||||
extern void qlt_81xx_config_nvram_stage1(struct scsi_qla_host *,
|
extern void qlt_81xx_config_nvram_stage1(struct scsi_qla_host *,
|
||||||
struct nvram_81xx *);
|
struct nvram_81xx *);
|
||||||
|
void qlt_config_nvram_with_fw_version(struct scsi_qla_host *vha);
|
||||||
extern void qlt_modify_vp_config(struct scsi_qla_host *,
|
extern void qlt_modify_vp_config(struct scsi_qla_host *,
|
||||||
struct vp_config_entry_24xx *);
|
struct vp_config_entry_24xx *);
|
||||||
extern void qlt_probe_one_stage1(struct scsi_qla_host *, struct qla_hw_data *);
|
extern void qlt_probe_one_stage1(struct scsi_qla_host *, struct qla_hw_data *);
|
||||||
|
|||||||
@@ -291,6 +291,16 @@ static struct qla_tgt_cmd *tcm_qla2xxx_get_cmd(struct fc_port *sess)
|
|||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int tcm_qla2xxx_get_cmd_ref(struct qla_tgt_cmd *cmd)
|
||||||
|
{
|
||||||
|
return target_get_sess_cmd(&cmd->se_cmd, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcm_qla2xxx_put_cmd_ref(struct qla_tgt_cmd *cmd)
|
||||||
|
{
|
||||||
|
target_put_sess_cmd(&cmd->se_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
static void tcm_qla2xxx_rel_cmd(struct qla_tgt_cmd *cmd)
|
static void tcm_qla2xxx_rel_cmd(struct qla_tgt_cmd *cmd)
|
||||||
{
|
{
|
||||||
target_free_tag(cmd->sess->se_sess, &cmd->se_cmd);
|
target_free_tag(cmd->sess->se_sess, &cmd->se_cmd);
|
||||||
@@ -303,6 +313,8 @@ static void tcm_qla2xxx_rel_cmd(struct qla_tgt_cmd *cmd)
|
|||||||
*/
|
*/
|
||||||
static void tcm_qla2xxx_free_cmd(struct qla_tgt_cmd *cmd)
|
static void tcm_qla2xxx_free_cmd(struct qla_tgt_cmd *cmd)
|
||||||
{
|
{
|
||||||
|
cmd->state = QLA_TGT_STATE_DONE;
|
||||||
|
|
||||||
cmd->qpair->tgt_counters.core_qla_free_cmd++;
|
cmd->qpair->tgt_counters.core_qla_free_cmd++;
|
||||||
cmd->cmd_in_wq = 1;
|
cmd->cmd_in_wq = 1;
|
||||||
|
|
||||||
@@ -529,6 +541,9 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
|
|||||||
if (cmd->se_cmd.pi_err)
|
if (cmd->se_cmd.pi_err)
|
||||||
transport_generic_request_failure(&cmd->se_cmd,
|
transport_generic_request_failure(&cmd->se_cmd,
|
||||||
cmd->se_cmd.pi_err);
|
cmd->se_cmd.pi_err);
|
||||||
|
else if (cmd->srr_failed)
|
||||||
|
transport_generic_request_failure(&cmd->se_cmd,
|
||||||
|
TCM_SNACK_REJECTED);
|
||||||
else
|
else
|
||||||
transport_generic_request_failure(&cmd->se_cmd,
|
transport_generic_request_failure(&cmd->se_cmd,
|
||||||
TCM_CHECK_CONDITION_ABORT_CMD);
|
TCM_CHECK_CONDITION_ABORT_CMD);
|
||||||
@@ -1524,6 +1539,8 @@ static const struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
|
|||||||
.handle_data = tcm_qla2xxx_handle_data,
|
.handle_data = tcm_qla2xxx_handle_data,
|
||||||
.handle_tmr = tcm_qla2xxx_handle_tmr,
|
.handle_tmr = tcm_qla2xxx_handle_tmr,
|
||||||
.get_cmd = tcm_qla2xxx_get_cmd,
|
.get_cmd = tcm_qla2xxx_get_cmd,
|
||||||
|
.get_cmd_ref = tcm_qla2xxx_get_cmd_ref,
|
||||||
|
.put_cmd_ref = tcm_qla2xxx_put_cmd_ref,
|
||||||
.rel_cmd = tcm_qla2xxx_rel_cmd,
|
.rel_cmd = tcm_qla2xxx_rel_cmd,
|
||||||
.free_cmd = tcm_qla2xxx_free_cmd,
|
.free_cmd = tcm_qla2xxx_free_cmd,
|
||||||
.free_mcmd = tcm_qla2xxx_free_mcmd,
|
.free_mcmd = tcm_qla2xxx_free_mcmd,
|
||||||
|
|||||||
Reference in New Issue
Block a user