Commit 44d01857 authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen

scsi: qla2xxx: edif: Add encryption to I/O path

Some FC adapters from Marvell offer the ability to encrypt data in flight
(EDIF). This feature requires an application to act as an authenticator.

After the completion of PLOGI, both sides have authenticated and PRLI
completed, encrypted I/Os are allowed to proceed.

 - Use new firmware API to encrypt traffic on the wire

 - Add driver parameter to enable|disable EDIF feature

   # modprobe qla2xxx ql2xsecenable=1

Link: https://lore.kernel.org/r/20210624052606.21613-10-njavali@marvell.comReviewed-by: default avatarHannes Reinecke <hare@suse.de>
Reviewed-by: default avatarHimanshu Madhani <himanshu.madhani@oracle.com>
Co-developed-by: default avatarLarry Wisneski <Larry.Wisneski@marvell.com>
Signed-off-by: default avatarLarry Wisneski <Larry.Wisneski@marvell.com>
Co-developed-by: default avatarDuane Grigsby <duane.grigsby@marvell.com>
Signed-off-by: default avatarDuane Grigsby <duane.grigsby@marvell.com>
Co-developed-by: default avatarRick Hicksted Jr <rhicksted@marvell.com>
Signed-off-by: default avatarRick Hicksted Jr <rhicksted@marvell.com>
Signed-off-by: default avatarQuinn Tran <qutran@marvell.com>
Signed-off-by: default avatarNilesh Javali <njavali@marvell.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 7a09e8d9
This diff is collapsed.
......@@ -490,6 +490,9 @@ struct cmd_type_6 {
struct scsi_lun lun; /* FCP LUN (BE). */
__le16 control_flags; /* Control flags. */
#define CF_NEW_SA BIT_12
#define CF_EN_EDIF BIT_9
#define CF_ADDITIONAL_PARAM_BLK BIT_8
#define CF_DIF_SEG_DESCR_ENABLE BIT_3
#define CF_DATA_SEG_DESCR_ENABLE BIT_2
#define CF_READ_DATA BIT_1
......
......@@ -188,6 +188,7 @@ extern int ql2xenablemsix;
extern int qla2xuseresexchforels;
extern int ql2xdifbundlinginternalbuffers;
extern int ql2xfulldump_on_mpifail;
extern int ql2xsecenable;
extern int ql2xenforce_iocb_limit;
extern int ql2xabts_wait_nvme;
......@@ -297,6 +298,8 @@ extern int qla2x00_vp_abort_isp(scsi_qla_host_t *);
*/
void qla_els_pt_iocb(struct scsi_qla_host *vha,
struct els_entry_24xx *pkt, struct qla_els_pt_arg *a);
cont_a64_entry_t *qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha,
struct req_que *que);
extern uint16_t qla2x00_calc_iocbs_32(uint16_t);
extern uint16_t qla2x00_calc_iocbs_64(uint16_t);
extern void qla2x00_build_scsi_iocbs_32(srb_t *, cmd_entry_t *, uint16_t);
......@@ -987,6 +990,7 @@ void qla_enode_init(scsi_qla_host_t *vha);
void qla_enode_stop(scsi_qla_host_t *vha);
void qla_edif_flush_sa_ctl_lists(fc_port_t *fcport);
void qla_edb_init(scsi_qla_host_t *vha);
int qla28xx_start_scsi_edif(srb_t *sp);
void qla24xx_sa_update_iocb(srb_t *sp, struct sa_update_28xx *sa_update_iocb);
void qla24xx_sa_replace_iocb(srb_t *sp, struct sa_update_28xx *sa_update_iocb);
void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp);
......
......@@ -632,7 +632,7 @@ static int qla_async_rftid(scsi_qla_host_t *vha, port_id_t *d_id)
ct_req->req.rft_id.port_id = port_id_to_be_id(vha->d_id);
ct_req->req.rft_id.fc4_types[2] = 0x01; /* FCP-3 */
if (vha->flags.nvme_enabled)
if (vha->flags.nvme_enabled && qla_ini_mode_enabled(vha))
ct_req->req.rft_id.fc4_types[6] = 1; /* NVMe type 28h */
sp->u.iocb_cmd.u.ctarg.req_size = RFT_ID_REQ_SIZE;
......
......@@ -345,15 +345,13 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
if (N2N_TOPO(fcport->vha->hw) && fcport_is_bigger(fcport)) {
lio->u.logio.flags |= SRB_LOGIN_PRLI_ONLY;
} else {
if (vha->hw->flags.edif_enabled) {
if (fcport->edif.non_secured_login == 0) {
if (vha->hw->flags.edif_enabled &&
vha->e_dbell.db_flags & EDB_ACTIVE) {
lio->u.logio.flags |=
(SRB_LOGIN_FCSP | SRB_LOGIN_SKIP_PRLI);
ql_dbg(ql_dbg_disc, vha, 0x2072,
"Async-login: w/ FCSP %8phC hdl=%x, loopid=%x portid=%06x\n",
fcport->port_name, sp->handle, fcport->loop_id,
fcport->d_id.b24);
}
fcport->port_name, sp->handle, fcport->loop_id, fcport->d_id.b24);
} else {
lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI;
}
......@@ -363,10 +361,9 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
lio->u.logio.flags |= SRB_LOGIN_SKIP_PRLI;
ql_log(ql_log_warn, vha, 0x2072,
"Async-login - %8phC hdl=%x, loopid=%x portid=%02x%02x%02x retries=%d.\n",
"Async-login - %8phC hdl=%x, loopid=%x portid=%06x retries=%d.\n",
fcport->port_name, sp->handle, fcport->loop_id,
fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
fcport->login_retry);
fcport->d_id.b24, fcport->login_retry);
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
......@@ -3964,7 +3961,8 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
}
/* Enable PUREX PASSTHRU */
if (ql2xrdpenable || ha->flags.scm_supported_f)
if (ql2xrdpenable || ha->flags.scm_supported_f ||
ha->flags.edif_enabled)
qla25xx_set_els_cmds_supported(vha);
} else
goto failed;
......@@ -4149,7 +4147,7 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha)
}
/* Move PUREX, ABTS RX & RIDA to ATIOQ */
if (ql2xmvasynctoatio &&
if (ql2xmvasynctoatio && !ha->flags.edif_enabled &&
(IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))) {
if (qla_tgt_mode_enabled(vha) ||
qla_dual_mode_enabled(vha))
......@@ -4177,7 +4175,8 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha)
ha->fw_options[2] &= ~BIT_8;
}
if (ql2xrdpenable || ha->flags.scm_supported_f)
if (ql2xrdpenable || ha->flags.scm_supported_f ||
ha->flags.edif_enabled)
ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB;
/* Enable Async 8130/8131 events -- transceiver insertion/removal */
......
......@@ -118,7 +118,7 @@ qla2x00_prep_cont_type0_iocb(struct scsi_qla_host *vha)
*
* Returns a pointer to the continuation type 1 IOCB packet.
*/
static inline cont_a64_entry_t *
cont_a64_entry_t *
qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha, struct req_que *req)
{
cont_a64_entry_t *cont_pkt;
......@@ -1910,6 +1910,9 @@ qla2xxx_start_scsi_mq(srb_t *sp)
struct qla_hw_data *ha = vha->hw;
struct qla_qpair *qpair = sp->qpair;
if (sp->fcport->edif.enable)
return qla28xx_start_scsi_edif(sp);
/* Acquire qpair specific lock */
spin_lock_irqsave(&qpair->qp_lock, flags);
......
......@@ -739,7 +739,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
mcp->mb[11] |= EXE_FW_FORCE_SEMAPHORE;
mcp->out_mb |= MBX_4 | MBX_3 | MBX_2 | MBX_1 | MBX_11;
mcp->in_mb |= MBX_3 | MBX_2 | MBX_1;
mcp->in_mb |= MBX_5 | MBX_3 | MBX_2 | MBX_1;
} else {
mcp->mb[1] = LSW(risc_addr);
mcp->out_mb |= MBX_1;
......@@ -795,6 +795,12 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
}
}
if (IS_QLA28XX(ha) && (mcp->mb[5] & BIT_10) && ql2xsecenable) {
ha->flags.edif_enabled = 1;
ql_log(ql_log_info, vha, 0xffff,
"%s: edif is enabled\n", __func__);
}
done:
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1028,
"Done %s.\n", __func__);
......@@ -4946,7 +4952,7 @@ qla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma,
return rval;
}
#define PUREX_CMD_COUNT 2
#define PUREX_CMD_COUNT 4
int
qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha)
{
......@@ -4954,6 +4960,7 @@ qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
uint8_t *els_cmd_map;
uint8_t active_cnt = 0;
dma_addr_t els_cmd_map_dma;
uint8_t cmd_opcode[PUREX_CMD_COUNT];
uint8_t i, index, purex_bit;
......@@ -4975,10 +4982,20 @@ qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha)
}
/* List of Purex ELS */
cmd_opcode[0] = ELS_FPIN;
cmd_opcode[1] = ELS_RDP;
if (ql2xrdpenable) {
cmd_opcode[active_cnt] = ELS_RDP;
active_cnt++;
}
if (ha->flags.scm_supported_f) {
cmd_opcode[active_cnt] = ELS_FPIN;
active_cnt++;
}
if (ha->flags.edif_enabled) {
cmd_opcode[active_cnt] = ELS_AUTH_ELS;
active_cnt++;
}
for (i = 0; i < PUREX_CMD_COUNT; i++) {
for (i = 0; i < active_cnt; i++) {
index = cmd_opcode[i] / 8;
purex_bit = cmd_opcode[i] % 8;
els_cmd_map[index] |= 1 << purex_bit;
......
......@@ -463,6 +463,10 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp)
} else if (fd->io_dir == 0) {
cmd_pkt->control_flags = 0;
}
if (sp->fcport->edif.enable && fd->io_dir != 0)
cmd_pkt->control_flags |= cpu_to_le16(CF_EN_EDIF);
/* Set BIT_13 of control flags for Async event */
if (vha->flags.nvme2_enabled &&
cmd->sqe.common.opcode == nvme_admin_async_event) {
......
......@@ -53,6 +53,11 @@ static struct kmem_cache *ctx_cachep;
*/
uint ql_errlev = 0x8001;
int ql2xsecenable;
module_param(ql2xsecenable, int, S_IRUGO);
MODULE_PARM_DESC(ql2xsecenable,
"Enable/disable security. 0(Default) - Security disabled. 1 - Security enabled.");
static int ql2xenableclass2;
module_param(ql2xenableclass2, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xenableclass2,
......@@ -4030,7 +4035,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
if (!ha->srb_mempool)
goto fail_free_gid_list;
if (IS_P3P_TYPE(ha)) {
if (IS_P3P_TYPE(ha) || IS_QLA27XX(ha) || (ql2xsecenable && IS_QLA28XX(ha))) {
/* Allocate cache for CT6 Ctx. */
if (!ctx_cachep) {
ctx_cachep = kmem_cache_create("qla2xxx_ctx",
......@@ -4064,7 +4069,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
"init_cb=%p gid_list=%p, srb_mempool=%p s_dma_pool=%p.\n",
ha->init_cb, ha->gid_list, ha->srb_mempool, ha->s_dma_pool);
if (IS_P3P_TYPE(ha) || ql2xenabledif) {
if (IS_P3P_TYPE(ha) || ql2xenabledif || (IS_QLA28XX(ha) && ql2xsecenable)) {
ha->dl_dma_pool = dma_pool_create(name, &ha->pdev->dev,
DSD_LIST_DMA_POOL_SIZE, 8, 0);
if (!ha->dl_dma_pool) {
......
......@@ -1313,8 +1313,8 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess)
qla24xx_chk_fcp_state(sess);
ql_dbg(ql_log_warn, sess->vha, 0xe001,
"Scheduling sess %p for deletion %8phC\n",
sess, sess->port_name);
"Scheduling sess %p for deletion %8phC fc4_type %x\n",
sess, sess->port_name, sess->fc4_type);
WARN_ON(!queue_work(sess->vha->hw->wq, &sess->del_work));
}
......@@ -2612,6 +2612,7 @@ static int qlt_24xx_build_ctio_pkt(struct qla_qpair *qpair,
struct ctio7_to_24xx *pkt;
struct atio_from_isp *atio = &prm->cmd->atio;
uint16_t temp;
struct qla_tgt_cmd *cmd = prm->cmd;
pkt = (struct ctio7_to_24xx *)qpair->req->ring_ptr;
prm->pkt = pkt;
......@@ -2644,6 +2645,15 @@ static int qlt_24xx_build_ctio_pkt(struct qla_qpair *qpair,
pkt->u.status0.ox_id = cpu_to_le16(temp);
pkt->u.status0.relative_offset = cpu_to_le32(prm->cmd->offset);
if (cmd->edif) {
if (cmd->dma_data_direction == DMA_TO_DEVICE)
prm->cmd->sess->edif.rx_bytes += cmd->bufflen;
if (cmd->dma_data_direction == DMA_FROM_DEVICE)
prm->cmd->sess->edif.tx_bytes += cmd->bufflen;
pkt->u.status0.edif_flags |= EF_EN_EDIF;
}
return 0;
}
......@@ -3334,8 +3344,10 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
if (xmit_type & QLA_TGT_XMIT_STATUS) {
pkt->u.status0.scsi_status =
cpu_to_le16(prm.rq_result);
if (!cmd->edif)
pkt->u.status0.residual =
cpu_to_le32(prm.residual);
pkt->u.status0.flags |= cpu_to_le16(
CTIO7_FLAGS_SEND_STATUS);
if (qlt_need_explicit_conf(cmd, 0)) {
......@@ -3982,6 +3994,12 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha,
if (cmd == NULL)
return;
if ((le16_to_cpu(((struct ctio7_from_24xx *)ctio)->flags) & CTIO7_FLAGS_DATA_OUT) &&
cmd->sess) {
qlt_chk_edif_rx_sa_delete_pending(vha, cmd->sess,
(struct ctio7_from_24xx *)ctio);
}
se_cmd = &cmd->se_cmd;
cmd->cmd_sent_to_fw = 0;
......@@ -4052,6 +4070,16 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha,
qlt_handle_dif_error(qpair, cmd, ctio);
return;
}
case CTIO_FAST_AUTH_ERR:
case CTIO_FAST_INCOMP_PAD_LEN:
case CTIO_FAST_INVALID_REQ:
case CTIO_FAST_SPI_ERR:
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05b,
"qla_target(%d): CTIO with EDIF error status 0x%x received (state %x, se_cmd %p\n",
vha->vp_idx, status, cmd->state, se_cmd);
break;
default:
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05b,
"qla_target(%d): CTIO with error status 0x%x received (state %x, se_cmd %p\n",
......@@ -4353,6 +4381,7 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha,
qlt_assign_qpair(vha, cmd);
cmd->reset_count = vha->hw->base_qpair->chip_reset;
cmd->vp_idx = vha->vp_idx;
cmd->edif = sess->edif.enable;
return cmd;
}
......@@ -4769,7 +4798,9 @@ static int qlt_handle_login(struct scsi_qla_host *vha,
}
if (vha->hw->flags.edif_enabled &&
vha->e_dbell.db_flags != EDB_ACTIVE) {
!(vha->e_dbell.db_flags & EDB_ACTIVE) &&
iocb->u.isp24.status_subcode == ELS_PLOGI &&
!(le16_to_cpu(iocb->u.isp24.flags) & NOTIFY24XX_FLAGS_FCSP)) {
ql_dbg(ql_dbg_disc, vha, 0xffff,
"%s %d Term INOT due to app not available lid=%d, NportID %06X ",
__func__, __LINE__, loop_id, port_id.b24);
......
......@@ -239,6 +239,10 @@ struct ctio_to_2xxx {
#define CTIO_PORT_LOGGED_OUT 0x29
#define CTIO_PORT_CONF_CHANGED 0x2A
#define CTIO_SRR_RECEIVED 0x45
#define CTIO_FAST_AUTH_ERR 0x63
#define CTIO_FAST_INCOMP_PAD_LEN 0x65
#define CTIO_FAST_INVALID_REQ 0x66
#define CTIO_FAST_SPI_ERR 0x67
#endif
#ifndef CTIO_RET_TYPE
......@@ -409,7 +413,16 @@ struct ctio7_to_24xx {
struct {
__le16 reserved1;
__le16 flags;
union {
__le32 residual;
struct {
uint8_t rsvd1;
uint8_t edif_flags;
#define EF_EN_EDIF BIT_0
#define EF_NEW_SA BIT_1
uint16_t rsvd2;
};
};
__le16 ox_id;
__le16 scsi_status;
__le32 relative_offset;
......@@ -876,6 +889,7 @@ struct qla_tgt_cmd {
unsigned int term_exchg:1;
unsigned int cmd_sent_to_fw:1;
unsigned int cmd_in_wq:1;
unsigned int edif:1;
/*
* This variable may be set from outside the LIO and I/O completion
......
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