Commit be25152c authored by Quinn Tran's avatar Quinn Tran Committed by Nicholas Bellinger

qla2xxx: Improve T10-DIF/PI handling in driver.

Add routines to support T10 DIF tag.
Signed-off-by: default avatarQuinn Tran <quinn.tran@cavium.com>
Signed-off-by: default avatarAnil Gurumurthy <anil.gurumurthy@cavium.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 5b33469a
......@@ -348,6 +348,7 @@ ql_log_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...);
#define ql_dbg_tgt 0x00004000 /* Target mode */
#define ql_dbg_tgt_mgt 0x00002000 /* Target mode management */
#define ql_dbg_tgt_tmr 0x00001000 /* Target mode task management */
#define ql_dbg_tgt_dif 0x00000800 /* Target mode dif */
extern int qla27xx_dump_mpi_ram(struct qla_hw_data *, uint32_t, uint32_t *,
uint32_t, void **);
......
......@@ -3127,6 +3127,16 @@ struct bidi_statistics {
unsigned long long transfer_bytes;
};
struct qla_tc_param {
struct scsi_qla_host *vha;
uint32_t blk_sz;
uint32_t bufflen;
struct scatterlist *sg;
struct scatterlist *prot_sg;
struct crc_context *ctx;
uint8_t *ctx_dsd_alloced;
};
/* Multi queue support */
#define MBC_INITIALIZE_MULTIQ 0x1f
#define QLA_QUE_PAGE 0X1000
......
......@@ -256,11 +256,11 @@ extern unsigned long qla2x00_get_async_timeout(struct scsi_qla_host *);
extern void *qla2x00_alloc_iocbs(scsi_qla_host_t *, srb_t *);
extern int qla2x00_issue_marker(scsi_qla_host_t *, int);
extern int qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *, srb_t *,
uint32_t *, uint16_t, struct qla_tgt_cmd *);
uint32_t *, uint16_t, struct qla_tc_param *);
extern int qla24xx_walk_and_build_sglist(struct qla_hw_data *, srb_t *,
uint32_t *, uint16_t, struct qla_tgt_cmd *);
uint32_t *, uint16_t, struct qla_tc_param *);
extern int qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *, srb_t *,
uint32_t *, uint16_t, struct qla_tgt_cmd *);
uint32_t *, uint16_t, struct qla_tc_param *);
extern int qla24xx_get_one_block_sg(uint32_t, struct qla2_sgx *, uint32_t *);
extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *);
extern int qla24xx_build_scsi_crc_2_iocbs(srb_t *,
......
......@@ -889,7 +889,7 @@ qla24xx_get_one_block_sg(uint32_t blk_sz, struct qla2_sgx *sgx,
int
qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp,
uint32_t *dsd, uint16_t tot_dsds, struct qla_tgt_cmd *tc)
uint32_t *dsd, uint16_t tot_dsds, struct qla_tc_param *tc)
{
void *next_dsd;
uint8_t avail_dsds = 0;
......@@ -898,7 +898,6 @@ qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp,
struct scatterlist *sg_prot;
uint32_t *cur_dsd = dsd;
uint16_t used_dsds = tot_dsds;
uint32_t prot_int; /* protection interval */
uint32_t partial;
struct qla2_sgx sgx;
......@@ -966,7 +965,7 @@ qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp,
} else {
list_add_tail(&dsd_ptr->list,
&(tc->ctx->dsd_list));
tc->ctx_dsd_alloced = 1;
*tc->ctx_dsd_alloced = 1;
}
......@@ -1005,7 +1004,7 @@ qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp,
int
qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
uint16_t tot_dsds, struct qla_tgt_cmd *tc)
uint16_t tot_dsds, struct qla_tc_param *tc)
{
void *next_dsd;
uint8_t avail_dsds = 0;
......@@ -1066,7 +1065,7 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
} else {
list_add_tail(&dsd_ptr->list,
&(tc->ctx->dsd_list));
tc->ctx_dsd_alloced = 1;
*tc->ctx_dsd_alloced = 1;
}
/* add new list to cmd iocb or last list */
......@@ -1092,7 +1091,7 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
int
qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
uint32_t *dsd, uint16_t tot_dsds, struct qla_tgt_cmd *tc)
uint32_t *dsd, uint16_t tot_dsds, struct qla_tc_param *tc)
{
void *next_dsd;
uint8_t avail_dsds = 0;
......@@ -1158,7 +1157,7 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
} else {
list_add_tail(&dsd_ptr->list,
&(tc->ctx->dsd_list));
tc->ctx_dsd_alloced = 1;
*tc->ctx_dsd_alloced = 1;
}
/* add new list to cmd iocb or last list */
......
This diff is collapsed.
......@@ -378,6 +378,14 @@ static inline void adjust_corrupted_atio(struct atio_from_isp *atio)
atio->u.isp24.fcp_cmnd.add_cdb_len = 0;
}
static inline int get_datalen_for_atio(struct atio_from_isp *atio)
{
int len = atio->u.isp24.fcp_cmnd.add_cdb_len;
return (be32_to_cpu(get_unaligned((uint32_t *)
&atio->u.isp24.fcp_cmnd.add_cdb[len * 4])));
}
#define CTIO_TYPE7 0x12 /* Continue target I/O entry (for 24xx) */
/*
......@@ -667,7 +675,6 @@ struct qla_tgt_func_tmpl {
int (*handle_cmd)(struct scsi_qla_host *, struct qla_tgt_cmd *,
unsigned char *, uint32_t, int, int, int);
void (*handle_data)(struct qla_tgt_cmd *);
void (*handle_dif_err)(struct qla_tgt_cmd *);
int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, uint32_t, uint16_t,
uint32_t);
void (*free_cmd)(struct qla_tgt_cmd *);
......@@ -684,6 +691,8 @@ struct qla_tgt_func_tmpl {
void (*clear_nacl_from_fcport_map)(struct fc_port *);
void (*put_sess)(struct fc_port *);
void (*shutdown_sess)(struct fc_port *);
int (*get_dif_tags)(struct qla_tgt_cmd *cmd, uint16_t *pfw_prot_opts);
int (*chk_dif_tags)(uint32_t tag);
};
int qla2x00_wait_for_hba_online(struct scsi_qla_host *);
......@@ -845,6 +854,7 @@ enum trace_flags {
TRC_CMD_FREE = BIT_17,
TRC_DATA_IN = BIT_18,
TRC_ABORT = BIT_19,
TRC_DIF_ERR = BIT_20,
};
struct qla_tgt_cmd {
......@@ -862,7 +872,6 @@ struct qla_tgt_cmd {
unsigned int sg_mapped:1;
unsigned int free_sg:1;
unsigned int write_data_transferred:1;
unsigned int ctx_dsd_alloced:1;
unsigned int q_full:1;
unsigned int term_exchg:1;
unsigned int cmd_sent_to_fw:1;
......@@ -885,11 +894,25 @@ struct qla_tgt_cmd {
struct list_head cmd_list;
struct atio_from_isp atio;
/* t10dif */
uint8_t ctx_dsd_alloced;
/* T10-DIF */
#define DIF_ERR_NONE 0
#define DIF_ERR_GRD 1
#define DIF_ERR_REF 2
#define DIF_ERR_APP 3
int8_t dif_err_code;
struct scatterlist *prot_sg;
uint32_t prot_sg_cnt;
uint32_t blk_sz;
uint32_t blk_sz, num_blks;
uint8_t scsi_status, sense_key, asc, ascq;
struct crc_context *ctx;
uint8_t *cdb;
uint64_t lba;
uint16_t a_guard, e_guard, a_app_tag, e_app_tag;
uint32_t a_ref_tag, e_ref_tag;
uint64_t jiffies_at_alloc;
uint64_t jiffies_at_free;
......@@ -1053,4 +1076,7 @@ extern int qlt_free_qfull_cmds(struct scsi_qla_host *);
extern void qlt_logo_completion_handler(fc_port_t *, int);
extern void qlt_do_generation_tick(struct scsi_qla_host *, int *);
void qlt_send_resp_ctio(scsi_qla_host_t *, struct qla_tgt_cmd *, uint8_t,
uint8_t, uint8_t, uint8_t);
#endif /* __QLA_TARGET_H */
......@@ -531,6 +531,24 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
return;
}
switch (cmd->dif_err_code) {
case DIF_ERR_GRD:
cmd->se_cmd.pi_err =
TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED;
break;
case DIF_ERR_REF:
cmd->se_cmd.pi_err =
TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED;
break;
case DIF_ERR_APP:
cmd->se_cmd.pi_err =
TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED;
break;
case DIF_ERR_NONE:
default:
break;
}
if (cmd->se_cmd.pi_err)
transport_generic_request_failure(&cmd->se_cmd,
cmd->se_cmd.pi_err);
......@@ -555,25 +573,23 @@ static void tcm_qla2xxx_handle_data(struct qla_tgt_cmd *cmd)
queue_work_on(smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work);
}
static void tcm_qla2xxx_handle_dif_work(struct work_struct *work)
static int tcm_qla2xxx_chk_dif_tags(uint32_t tag)
{
struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work);
/* take an extra kref to prevent cmd free too early.
* need to wait for SCSI status/check condition to
* finish responding generate by transport_generic_request_failure.
*/
kref_get(&cmd->se_cmd.cmd_kref);
transport_generic_request_failure(&cmd->se_cmd, cmd->se_cmd.pi_err);
return 0;
}
/*
* Called from qla_target.c:qlt_do_ctio_completion()
*/
static void tcm_qla2xxx_handle_dif_err(struct qla_tgt_cmd *cmd)
static int tcm_qla2xxx_dif_tags(struct qla_tgt_cmd *cmd,
uint16_t *pfw_prot_opts)
{
INIT_WORK(&cmd->work, tcm_qla2xxx_handle_dif_work);
queue_work(tcm_qla2xxx_free_wq, &cmd->work);
struct se_cmd *se_cmd = &cmd->se_cmd;
if (!(se_cmd->prot_checks & TARGET_DIF_CHECK_GUARD))
*pfw_prot_opts |= PO_DISABLE_GUARD_CHECK;
if (!(se_cmd->prot_checks & TARGET_DIF_CHECK_APPTAG))
*pfw_prot_opts |= PO_DIS_APP_TAG_VALD;
return 0;
}
/*
......@@ -1610,7 +1626,6 @@ static void tcm_qla2xxx_update_sess(struct fc_port *sess, port_id_t s_id,
static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
.handle_cmd = tcm_qla2xxx_handle_cmd,
.handle_data = tcm_qla2xxx_handle_data,
.handle_dif_err = tcm_qla2xxx_handle_dif_err,
.handle_tmr = tcm_qla2xxx_handle_tmr,
.free_cmd = tcm_qla2xxx_free_cmd,
.free_mcmd = tcm_qla2xxx_free_mcmd,
......@@ -1622,6 +1637,8 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
.clear_nacl_from_fcport_map = tcm_qla2xxx_clear_nacl_from_fcport_map,
.put_sess = tcm_qla2xxx_put_sess,
.shutdown_sess = tcm_qla2xxx_shutdown_sess,
.get_dif_tags = tcm_qla2xxx_dif_tags,
.chk_dif_tags = tcm_qla2xxx_chk_dif_tags,
};
static int tcm_qla2xxx_init_lport(struct tcm_qla2xxx_lport *lport)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment