scsi: mpi3mr: Add EEDP DIF DIX support
Link: https://lore.kernel.org/r/20210520152545.2710479-24-kashyap.desai@broadcom.com Cc: sathya.prakash@broadcom.com Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Tomas Henzl <thenzl@redhat.com> Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
28cbe2f420
commit
74e1f30a28
@ -123,6 +123,7 @@ extern struct list_head mrioc_list;
|
|||||||
#define MPI3MR_SENSEBUF_SZ 256
|
#define MPI3MR_SENSEBUF_SZ 256
|
||||||
#define MPI3MR_SENSEBUF_FACTOR 3
|
#define MPI3MR_SENSEBUF_FACTOR 3
|
||||||
#define MPI3MR_CHAINBUF_FACTOR 3
|
#define MPI3MR_CHAINBUF_FACTOR 3
|
||||||
|
#define MPI3MR_CHAINBUFDIX_FACTOR 2
|
||||||
|
|
||||||
/* Invalid target device handle */
|
/* Invalid target device handle */
|
||||||
#define MPI3MR_INVALID_DEV_HANDLE 0xFFFF
|
#define MPI3MR_INVALID_DEV_HANDLE 0xFFFF
|
||||||
@ -562,17 +563,21 @@ struct chain_element {
|
|||||||
*
|
*
|
||||||
* @host_tag: Host tag specific to operational queue
|
* @host_tag: Host tag specific to operational queue
|
||||||
* @in_lld_scope: Command in LLD scope or not
|
* @in_lld_scope: Command in LLD scope or not
|
||||||
|
* @meta_sg_valid: DIX command with meta data SGL or not
|
||||||
* @scmd: SCSI Command pointer
|
* @scmd: SCSI Command pointer
|
||||||
* @req_q_idx: Operational request queue index
|
* @req_q_idx: Operational request queue index
|
||||||
* @chain_idx: Chain frame index
|
* @chain_idx: Chain frame index
|
||||||
|
* @meta_chain_idx: Chain frame index of meta data SGL
|
||||||
* @mpi3mr_scsiio_req: MPI SCSI IO request
|
* @mpi3mr_scsiio_req: MPI SCSI IO request
|
||||||
*/
|
*/
|
||||||
struct scmd_priv {
|
struct scmd_priv {
|
||||||
u16 host_tag;
|
u16 host_tag;
|
||||||
u8 in_lld_scope;
|
u8 in_lld_scope;
|
||||||
|
u8 meta_sg_valid;
|
||||||
struct scsi_cmnd *scmd;
|
struct scsi_cmnd *scmd;
|
||||||
u16 req_q_idx;
|
u16 req_q_idx;
|
||||||
int chain_idx;
|
int chain_idx;
|
||||||
|
int meta_chain_idx;
|
||||||
u8 mpi3mr_scsiio_req[MPI3MR_ADMIN_REQ_FRAME_SZ];
|
u8 mpi3mr_scsiio_req[MPI3MR_ADMIN_REQ_FRAME_SZ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "mpi3mr.h"
|
#include "mpi3mr.h"
|
||||||
#include <linux/io-64-nonatomic-lo-hi.h>
|
#include <linux/io-64-nonatomic-lo-hi.h>
|
||||||
|
extern int prot_mask;
|
||||||
|
|
||||||
#if defined(writeq) && defined(CONFIG_64BIT)
|
#if defined(writeq) && defined(CONFIG_64BIT)
|
||||||
static inline void mpi3mr_writeq(__u64 b, volatile void __iomem *addr)
|
static inline void mpi3mr_writeq(__u64 b, volatile void __iomem *addr)
|
||||||
@ -2749,6 +2750,12 @@ static int mpi3mr_alloc_chain_bufs(struct mpi3mr_ioc *mrioc)
|
|||||||
|
|
||||||
num_chains = mrioc->max_host_ios / MPI3MR_CHAINBUF_FACTOR;
|
num_chains = mrioc->max_host_ios / MPI3MR_CHAINBUF_FACTOR;
|
||||||
|
|
||||||
|
if (prot_mask & (SHOST_DIX_TYPE0_PROTECTION
|
||||||
|
| SHOST_DIX_TYPE1_PROTECTION
|
||||||
|
| SHOST_DIX_TYPE2_PROTECTION
|
||||||
|
| SHOST_DIX_TYPE3_PROTECTION))
|
||||||
|
num_chains += (num_chains / MPI3MR_CHAINBUFDIX_FACTOR);
|
||||||
|
|
||||||
mrioc->chain_buf_count = num_chains;
|
mrioc->chain_buf_count = num_chains;
|
||||||
sz = sizeof(struct chain_element) * num_chains;
|
sz = sizeof(struct chain_element) * num_chains;
|
||||||
mrioc->chain_sgl_list = kzalloc(sz, GFP_KERNEL);
|
mrioc->chain_sgl_list = kzalloc(sz, GFP_KERNEL);
|
||||||
|
@ -21,6 +21,13 @@ MODULE_LICENSE(MPI3MR_DRIVER_LICENSE);
|
|||||||
MODULE_VERSION(MPI3MR_DRIVER_VERSION);
|
MODULE_VERSION(MPI3MR_DRIVER_VERSION);
|
||||||
|
|
||||||
/* Module parameters*/
|
/* Module parameters*/
|
||||||
|
int prot_mask = -1;
|
||||||
|
module_param(prot_mask, int, 0);
|
||||||
|
MODULE_PARM_DESC(prot_mask, "Host protection capabilities mask, def=0x07");
|
||||||
|
|
||||||
|
int prot_guard_mask = 3;
|
||||||
|
module_param(prot_guard_mask, int, 0);
|
||||||
|
MODULE_PARM_DESC(prot_guard_mask, " Host protection guard mask, def=3");
|
||||||
int logging_level;
|
int logging_level;
|
||||||
module_param(logging_level, int, 0);
|
module_param(logging_level, int, 0);
|
||||||
MODULE_PARM_DESC(logging_level,
|
MODULE_PARM_DESC(logging_level,
|
||||||
@ -59,7 +66,9 @@ static u16 mpi3mr_host_tag_for_scmd(struct mpi3mr_ioc *mrioc,
|
|||||||
priv->scmd = scmd;
|
priv->scmd = scmd;
|
||||||
priv->in_lld_scope = 1;
|
priv->in_lld_scope = 1;
|
||||||
priv->req_q_idx = hw_queue;
|
priv->req_q_idx = hw_queue;
|
||||||
|
priv->meta_chain_idx = -1;
|
||||||
priv->chain_idx = -1;
|
priv->chain_idx = -1;
|
||||||
|
priv->meta_sg_valid = 0;
|
||||||
return priv->host_tag;
|
return priv->host_tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,10 +128,15 @@ static void mpi3mr_clear_scmd_priv(struct mpi3mr_ioc *mrioc,
|
|||||||
priv->req_q_idx = 0xFFFF;
|
priv->req_q_idx = 0xFFFF;
|
||||||
priv->scmd = NULL;
|
priv->scmd = NULL;
|
||||||
priv->in_lld_scope = 0;
|
priv->in_lld_scope = 0;
|
||||||
|
priv->meta_sg_valid = 0;
|
||||||
if (priv->chain_idx >= 0) {
|
if (priv->chain_idx >= 0) {
|
||||||
clear_bit(priv->chain_idx, mrioc->chain_bitmap);
|
clear_bit(priv->chain_idx, mrioc->chain_bitmap);
|
||||||
priv->chain_idx = -1;
|
priv->chain_idx = -1;
|
||||||
}
|
}
|
||||||
|
if (priv->meta_chain_idx >= 0) {
|
||||||
|
clear_bit(priv->meta_chain_idx, mrioc->chain_bitmap);
|
||||||
|
priv->meta_chain_idx = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mpi3mr_dev_rmhs_send_tm(struct mpi3mr_ioc *mrioc, u16 handle,
|
static void mpi3mr_dev_rmhs_send_tm(struct mpi3mr_ioc *mrioc, u16 handle,
|
||||||
@ -388,6 +402,9 @@ static bool mpi3mr_flush_scmd(struct request *rq,
|
|||||||
if (!priv->in_lld_scope)
|
if (!priv->in_lld_scope)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
if (priv->meta_sg_valid)
|
||||||
|
dma_unmap_sg(&mrioc->pdev->dev, scsi_prot_sglist(scmd),
|
||||||
|
scsi_prot_sg_count(scmd), scmd->sc_data_direction);
|
||||||
mpi3mr_clear_scmd_priv(mrioc, scmd);
|
mpi3mr_clear_scmd_priv(mrioc, scmd);
|
||||||
scsi_dma_unmap(scmd);
|
scsi_dma_unmap(scmd);
|
||||||
scmd->result = DID_RESET << 16;
|
scmd->result = DID_RESET << 16;
|
||||||
@ -785,6 +802,7 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc,
|
|||||||
{
|
{
|
||||||
u16 flags = 0;
|
u16 flags = 0;
|
||||||
struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data;
|
struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data;
|
||||||
|
u8 prot_mask = 0;
|
||||||
|
|
||||||
tgtdev->perst_id = le16_to_cpu(dev_pg0->persistent_id);
|
tgtdev->perst_id = le16_to_cpu(dev_pg0->persistent_id);
|
||||||
tgtdev->dev_handle = le16_to_cpu(dev_pg0->dev_handle);
|
tgtdev->dev_handle = le16_to_cpu(dev_pg0->dev_handle);
|
||||||
@ -849,6 +867,15 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc,
|
|||||||
if ((dev_info & MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK) !=
|
if ((dev_info & MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK) !=
|
||||||
MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_NVME_DEVICE)
|
MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_NVME_DEVICE)
|
||||||
tgtdev->is_hidden = 1;
|
tgtdev->is_hidden = 1;
|
||||||
|
if (mrioc->shost)
|
||||||
|
prot_mask = scsi_host_get_prot(mrioc->shost);
|
||||||
|
if (prot_mask & SHOST_DIX_TYPE0_PROTECTION) {
|
||||||
|
scsi_host_set_prot(mrioc->shost, prot_mask & 0x77);
|
||||||
|
ioc_info(mrioc,
|
||||||
|
"%s : Disabling DIX0 prot capability\n", __func__);
|
||||||
|
ioc_info(mrioc,
|
||||||
|
"because HBA does not support DIX0 operation on NVME drives\n");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MPI3_DEVICE_DEVFORM_VD:
|
case MPI3_DEVICE_DEVFORM_VD:
|
||||||
@ -1752,6 +1779,194 @@ void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mpi3mr_setup_eedp - Setup EEDP information in MPI3 SCSI IO
|
||||||
|
* @mrioc: Adapter instance reference
|
||||||
|
* @scmd: SCSI command reference
|
||||||
|
* @scsiio_req: MPI3 SCSI IO request
|
||||||
|
*
|
||||||
|
* Identifies the protection information flags from the SCSI
|
||||||
|
* command and set appropriate flags in the MPI3 SCSI IO
|
||||||
|
* request.
|
||||||
|
*
|
||||||
|
* Return: Nothing
|
||||||
|
*/
|
||||||
|
static void mpi3mr_setup_eedp(struct mpi3mr_ioc *mrioc,
|
||||||
|
struct scsi_cmnd *scmd, struct mpi3_scsi_io_request *scsiio_req)
|
||||||
|
{
|
||||||
|
u16 eedp_flags = 0;
|
||||||
|
unsigned char prot_op = scsi_get_prot_op(scmd);
|
||||||
|
unsigned char prot_type = scsi_get_prot_type(scmd);
|
||||||
|
|
||||||
|
switch (prot_op) {
|
||||||
|
case SCSI_PROT_NORMAL:
|
||||||
|
return;
|
||||||
|
case SCSI_PROT_READ_STRIP:
|
||||||
|
eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_CHECK_REMOVE;
|
||||||
|
break;
|
||||||
|
case SCSI_PROT_WRITE_INSERT:
|
||||||
|
eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_INSERT;
|
||||||
|
break;
|
||||||
|
case SCSI_PROT_READ_INSERT:
|
||||||
|
eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_INSERT;
|
||||||
|
scsiio_req->msg_flags |= MPI3_SCSIIO_MSGFLAGS_METASGL_VALID;
|
||||||
|
break;
|
||||||
|
case SCSI_PROT_WRITE_STRIP:
|
||||||
|
eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_CHECK_REMOVE;
|
||||||
|
scsiio_req->msg_flags |= MPI3_SCSIIO_MSGFLAGS_METASGL_VALID;
|
||||||
|
break;
|
||||||
|
case SCSI_PROT_READ_PASS:
|
||||||
|
eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_CHECK |
|
||||||
|
MPI3_EEDPFLAGS_CHK_REF_TAG | MPI3_EEDPFLAGS_CHK_APP_TAG |
|
||||||
|
MPI3_EEDPFLAGS_CHK_GUARD;
|
||||||
|
scsiio_req->msg_flags |= MPI3_SCSIIO_MSGFLAGS_METASGL_VALID;
|
||||||
|
break;
|
||||||
|
case SCSI_PROT_WRITE_PASS:
|
||||||
|
if (scsi_host_get_guard(scmd->device->host)
|
||||||
|
& SHOST_DIX_GUARD_IP) {
|
||||||
|
eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_CHECK_REGEN |
|
||||||
|
MPI3_EEDPFLAGS_CHK_APP_TAG |
|
||||||
|
MPI3_EEDPFLAGS_CHK_GUARD |
|
||||||
|
MPI3_EEDPFLAGS_INCR_PRI_REF_TAG;
|
||||||
|
scsiio_req->sgl[0].eedp.application_tag_translation_mask =
|
||||||
|
0xffff;
|
||||||
|
} else {
|
||||||
|
eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_CHECK |
|
||||||
|
MPI3_EEDPFLAGS_CHK_REF_TAG |
|
||||||
|
MPI3_EEDPFLAGS_CHK_APP_TAG |
|
||||||
|
MPI3_EEDPFLAGS_CHK_GUARD;
|
||||||
|
}
|
||||||
|
scsiio_req->msg_flags |= MPI3_SCSIIO_MSGFLAGS_METASGL_VALID;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scsi_host_get_guard(scmd->device->host) & SHOST_DIX_GUARD_IP)
|
||||||
|
eedp_flags |= MPI3_EEDPFLAGS_HOST_GUARD_IP_CHKSUM;
|
||||||
|
|
||||||
|
switch (prot_type) {
|
||||||
|
case SCSI_PROT_DIF_TYPE0:
|
||||||
|
eedp_flags |= MPI3_EEDPFLAGS_INCR_PRI_REF_TAG;
|
||||||
|
scsiio_req->cdb.eedp32.primary_reference_tag =
|
||||||
|
cpu_to_be32(t10_pi_ref_tag(scmd->request));
|
||||||
|
break;
|
||||||
|
case SCSI_PROT_DIF_TYPE1:
|
||||||
|
case SCSI_PROT_DIF_TYPE2:
|
||||||
|
eedp_flags |= MPI3_EEDPFLAGS_INCR_PRI_REF_TAG |
|
||||||
|
MPI3_EEDPFLAGS_ESC_MODE_APPTAG_DISABLE |
|
||||||
|
MPI3_EEDPFLAGS_CHK_GUARD;
|
||||||
|
scsiio_req->cdb.eedp32.primary_reference_tag =
|
||||||
|
cpu_to_be32(t10_pi_ref_tag(scmd->request));
|
||||||
|
break;
|
||||||
|
case SCSI_PROT_DIF_TYPE3:
|
||||||
|
eedp_flags |= MPI3_EEDPFLAGS_CHK_GUARD |
|
||||||
|
MPI3_EEDPFLAGS_ESC_MODE_APPTAG_DISABLE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
scsiio_req->msg_flags &= ~(MPI3_SCSIIO_MSGFLAGS_METASGL_VALID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (scmd->device->sector_size) {
|
||||||
|
case 512:
|
||||||
|
scsiio_req->sgl[0].eedp.user_data_size = MPI3_EEDP_UDS_512;
|
||||||
|
break;
|
||||||
|
case 520:
|
||||||
|
scsiio_req->sgl[0].eedp.user_data_size = MPI3_EEDP_UDS_520;
|
||||||
|
break;
|
||||||
|
case 4080:
|
||||||
|
scsiio_req->sgl[0].eedp.user_data_size = MPI3_EEDP_UDS_4080;
|
||||||
|
break;
|
||||||
|
case 4088:
|
||||||
|
scsiio_req->sgl[0].eedp.user_data_size = MPI3_EEDP_UDS_4088;
|
||||||
|
break;
|
||||||
|
case 4096:
|
||||||
|
scsiio_req->sgl[0].eedp.user_data_size = MPI3_EEDP_UDS_4096;
|
||||||
|
break;
|
||||||
|
case 4104:
|
||||||
|
scsiio_req->sgl[0].eedp.user_data_size = MPI3_EEDP_UDS_4104;
|
||||||
|
break;
|
||||||
|
case 4160:
|
||||||
|
scsiio_req->sgl[0].eedp.user_data_size = MPI3_EEDP_UDS_4160;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
scsiio_req->sgl[0].eedp.eedp_flags = cpu_to_le16(eedp_flags);
|
||||||
|
scsiio_req->sgl[0].eedp.flags = MPI3_SGE_FLAGS_ELEMENT_TYPE_EXTENDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mpi3mr_build_sense_buffer - Map sense information
|
||||||
|
* @desc: Sense type
|
||||||
|
* @buf: Sense buffer to populate
|
||||||
|
* @key: Sense key
|
||||||
|
* @asc: Additional sense code
|
||||||
|
* @ascq: Additional sense code qualifier
|
||||||
|
*
|
||||||
|
* Maps the given sense information into either descriptor or
|
||||||
|
* fixed format sense data.
|
||||||
|
*
|
||||||
|
* Return: Nothing
|
||||||
|
*/
|
||||||
|
static inline void mpi3mr_build_sense_buffer(int desc, u8 *buf, u8 key,
|
||||||
|
u8 asc, u8 ascq)
|
||||||
|
{
|
||||||
|
if (desc) {
|
||||||
|
buf[0] = 0x72; /* descriptor, current */
|
||||||
|
buf[1] = key;
|
||||||
|
buf[2] = asc;
|
||||||
|
buf[3] = ascq;
|
||||||
|
buf[7] = 0;
|
||||||
|
} else {
|
||||||
|
buf[0] = 0x70; /* fixed, current */
|
||||||
|
buf[2] = key;
|
||||||
|
buf[7] = 0xa;
|
||||||
|
buf[12] = asc;
|
||||||
|
buf[13] = ascq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mpi3mr_map_eedp_error - Map EEDP errors from IOC status
|
||||||
|
* @scmd: SCSI command reference
|
||||||
|
* @ioc_status: status of MPI3 request
|
||||||
|
*
|
||||||
|
* Maps the EEDP error status of the SCSI IO request to sense
|
||||||
|
* data.
|
||||||
|
*
|
||||||
|
* Return: Nothing
|
||||||
|
*/
|
||||||
|
static void mpi3mr_map_eedp_error(struct scsi_cmnd *scmd,
|
||||||
|
u16 ioc_status)
|
||||||
|
{
|
||||||
|
u8 ascq = 0;
|
||||||
|
|
||||||
|
switch (ioc_status) {
|
||||||
|
case MPI3_IOCSTATUS_EEDP_GUARD_ERROR:
|
||||||
|
ascq = 0x01;
|
||||||
|
break;
|
||||||
|
case MPI3_IOCSTATUS_EEDP_APP_TAG_ERROR:
|
||||||
|
ascq = 0x02;
|
||||||
|
break;
|
||||||
|
case MPI3_IOCSTATUS_EEDP_REF_TAG_ERROR:
|
||||||
|
ascq = 0x03;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ascq = 0x00;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mpi3mr_build_sense_buffer(0, scmd->sense_buffer, ILLEGAL_REQUEST,
|
||||||
|
0x10, ascq);
|
||||||
|
scmd->result = DRIVER_SENSE << 24 | (DID_ABORT << 16) |
|
||||||
|
SAM_STAT_CHECK_CONDITION;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mpi3mr_process_op_reply_desc - reply descriptor handler
|
* mpi3mr_process_op_reply_desc - reply descriptor handler
|
||||||
* @mrioc: Adapter instance reference
|
* @mrioc: Adapter instance reference
|
||||||
@ -1905,6 +2120,11 @@ void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc,
|
|||||||
else if (scsi_state & MPI3_SCSI_STATE_TERMINATED)
|
else if (scsi_state & MPI3_SCSI_STATE_TERMINATED)
|
||||||
scmd->result = DID_RESET << 16;
|
scmd->result = DID_RESET << 16;
|
||||||
break;
|
break;
|
||||||
|
case MPI3_IOCSTATUS_EEDP_GUARD_ERROR:
|
||||||
|
case MPI3_IOCSTATUS_EEDP_REF_TAG_ERROR:
|
||||||
|
case MPI3_IOCSTATUS_EEDP_APP_TAG_ERROR:
|
||||||
|
mpi3mr_map_eedp_error(scmd, ioc_status);
|
||||||
|
break;
|
||||||
case MPI3_IOCSTATUS_SCSI_PROTOCOL_ERROR:
|
case MPI3_IOCSTATUS_SCSI_PROTOCOL_ERROR:
|
||||||
case MPI3_IOCSTATUS_INVALID_FUNCTION:
|
case MPI3_IOCSTATUS_INVALID_FUNCTION:
|
||||||
case MPI3_IOCSTATUS_INVALID_SGL:
|
case MPI3_IOCSTATUS_INVALID_SGL:
|
||||||
@ -1940,6 +2160,10 @@ void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
out_success:
|
out_success:
|
||||||
|
if (priv->meta_sg_valid) {
|
||||||
|
dma_unmap_sg(&mrioc->pdev->dev, scsi_prot_sglist(scmd),
|
||||||
|
scsi_prot_sg_count(scmd), scmd->sc_data_direction);
|
||||||
|
}
|
||||||
mpi3mr_clear_scmd_priv(mrioc, scmd);
|
mpi3mr_clear_scmd_priv(mrioc, scmd);
|
||||||
scsi_dma_unmap(scmd);
|
scsi_dma_unmap(scmd);
|
||||||
scmd->scsi_done(scmd);
|
scmd->scsi_done(scmd);
|
||||||
@ -2003,6 +2227,8 @@ static int mpi3mr_prepare_sg_scmd(struct mpi3mr_ioc *mrioc,
|
|||||||
u8 last_chain_sgl_flags;
|
u8 last_chain_sgl_flags;
|
||||||
struct chain_element *chain_req;
|
struct chain_element *chain_req;
|
||||||
struct scmd_priv *priv = NULL;
|
struct scmd_priv *priv = NULL;
|
||||||
|
u32 meta_sg = le32_to_cpu(scsiio_req->flags) &
|
||||||
|
MPI3_SCSIIO_FLAGS_DMAOPERATION_HOST_PI;
|
||||||
|
|
||||||
priv = scsi_cmd_priv(scmd);
|
priv = scsi_cmd_priv(scmd);
|
||||||
|
|
||||||
@ -2013,15 +2239,27 @@ static int mpi3mr_prepare_sg_scmd(struct mpi3mr_ioc *mrioc,
|
|||||||
last_chain_sgl_flags = MPI3_SGE_FLAGS_ELEMENT_TYPE_LAST_CHAIN |
|
last_chain_sgl_flags = MPI3_SGE_FLAGS_ELEMENT_TYPE_LAST_CHAIN |
|
||||||
MPI3_SGE_FLAGS_DLAS_SYSTEM;
|
MPI3_SGE_FLAGS_DLAS_SYSTEM;
|
||||||
|
|
||||||
sg_local = &scsiio_req->sgl;
|
if (meta_sg)
|
||||||
|
sg_local = &scsiio_req->sgl[MPI3_SCSIIO_METASGL_INDEX];
|
||||||
|
else
|
||||||
|
sg_local = &scsiio_req->sgl;
|
||||||
|
|
||||||
if (!scsiio_req->data_length) {
|
if (!scsiio_req->data_length && !meta_sg) {
|
||||||
mpi3mr_build_zero_len_sge(sg_local);
|
mpi3mr_build_zero_len_sge(sg_local);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
sg_scmd = scsi_sglist(scmd);
|
if (meta_sg) {
|
||||||
sges_left = scsi_dma_map(scmd);
|
sg_scmd = scsi_prot_sglist(scmd);
|
||||||
|
sges_left = dma_map_sg(&mrioc->pdev->dev,
|
||||||
|
scsi_prot_sglist(scmd),
|
||||||
|
scsi_prot_sg_count(scmd),
|
||||||
|
scmd->sc_data_direction);
|
||||||
|
priv->meta_sg_valid = 1; /* To unmap meta sg DMA */
|
||||||
|
} else {
|
||||||
|
sg_scmd = scsi_sglist(scmd);
|
||||||
|
sges_left = scsi_dma_map(scmd);
|
||||||
|
}
|
||||||
|
|
||||||
if (sges_left < 0) {
|
if (sges_left < 0) {
|
||||||
sdev_printk(KERN_ERR, scmd->device,
|
sdev_printk(KERN_ERR, scmd->device,
|
||||||
@ -2039,6 +2277,22 @@ static int mpi3mr_prepare_sg_scmd(struct mpi3mr_ioc *mrioc,
|
|||||||
sges_in_segment = (mrioc->facts.op_req_sz -
|
sges_in_segment = (mrioc->facts.op_req_sz -
|
||||||
offsetof(struct mpi3_scsi_io_request, sgl)) / sizeof(struct mpi3_sge_common);
|
offsetof(struct mpi3_scsi_io_request, sgl)) / sizeof(struct mpi3_sge_common);
|
||||||
|
|
||||||
|
if (scsiio_req->sgl[0].eedp.flags ==
|
||||||
|
MPI3_SGE_FLAGS_ELEMENT_TYPE_EXTENDED && !meta_sg) {
|
||||||
|
sg_local += sizeof(struct mpi3_sge_common);
|
||||||
|
sges_in_segment--;
|
||||||
|
/* Reserve 1st segment (scsiio_req->sgl[0]) for eedp */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scsiio_req->msg_flags ==
|
||||||
|
MPI3_SCSIIO_MSGFLAGS_METASGL_VALID && !meta_sg) {
|
||||||
|
sges_in_segment--;
|
||||||
|
/* Reserve last segment (scsiio_req->sgl[3]) for meta sg */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meta_sg)
|
||||||
|
sges_in_segment = 1;
|
||||||
|
|
||||||
if (sges_left <= sges_in_segment)
|
if (sges_left <= sges_in_segment)
|
||||||
goto fill_in_last_segment;
|
goto fill_in_last_segment;
|
||||||
|
|
||||||
@ -2056,7 +2310,10 @@ static int mpi3mr_prepare_sg_scmd(struct mpi3mr_ioc *mrioc,
|
|||||||
if (chain_idx < 0)
|
if (chain_idx < 0)
|
||||||
return -1;
|
return -1;
|
||||||
chain_req = &mrioc->chain_sgl_list[chain_idx];
|
chain_req = &mrioc->chain_sgl_list[chain_idx];
|
||||||
priv->chain_idx = chain_idx;
|
if (meta_sg)
|
||||||
|
priv->meta_chain_idx = chain_idx;
|
||||||
|
else
|
||||||
|
priv->chain_idx = chain_idx;
|
||||||
|
|
||||||
chain = chain_req->addr;
|
chain = chain_req->addr;
|
||||||
chain_dma = chain_req->dma_addr;
|
chain_dma = chain_req->dma_addr;
|
||||||
@ -2106,6 +2363,13 @@ static int mpi3mr_build_sg_scmd(struct mpi3mr_ioc *mrioc,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
if (scsiio_req->msg_flags == MPI3_SCSIIO_MSGFLAGS_METASGL_VALID) {
|
||||||
|
/* There is a valid meta sg */
|
||||||
|
scsiio_req->flags |=
|
||||||
|
cpu_to_le32(MPI3_SCSIIO_FLAGS_DMAOPERATION_HOST_PI);
|
||||||
|
ret = mpi3mr_prepare_sg_scmd(mrioc, scmd, scsiio_req);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3113,6 +3377,8 @@ static int mpi3mr_qcmd(struct Scsi_Host *shost,
|
|||||||
scsiio_req->function = MPI3_FUNCTION_SCSI_IO;
|
scsiio_req->function = MPI3_FUNCTION_SCSI_IO;
|
||||||
scsiio_req->host_tag = cpu_to_le16(host_tag);
|
scsiio_req->host_tag = cpu_to_le16(host_tag);
|
||||||
|
|
||||||
|
mpi3mr_setup_eedp(mrioc, scmd, scsiio_req);
|
||||||
|
|
||||||
memcpy(scsiio_req->cdb.cdb32, scmd->cmnd, scmd->cmd_len);
|
memcpy(scsiio_req->cdb.cdb32, scmd->cmnd, scmd->cmd_len);
|
||||||
scsiio_req->data_length = cpu_to_le32(scsi_bufflen(scmd));
|
scsiio_req->data_length = cpu_to_le32(scsi_bufflen(scmd));
|
||||||
scsiio_req->dev_handle = cpu_to_le16(dev_handle);
|
scsiio_req->dev_handle = cpu_to_le16(dev_handle);
|
||||||
@ -3336,6 +3602,31 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||||||
shost->max_channel = 1;
|
shost->max_channel = 1;
|
||||||
shost->max_id = 0xFFFFFFFF;
|
shost->max_id = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
if (prot_mask >= 0)
|
||||||
|
scsi_host_set_prot(shost, prot_mask);
|
||||||
|
else {
|
||||||
|
prot_mask = SHOST_DIF_TYPE1_PROTECTION
|
||||||
|
| SHOST_DIF_TYPE2_PROTECTION
|
||||||
|
| SHOST_DIF_TYPE3_PROTECTION;
|
||||||
|
scsi_host_set_prot(shost, prot_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
ioc_info(mrioc,
|
||||||
|
"%s :host protection capabilities enabled %s%s%s%s%s%s%s\n",
|
||||||
|
__func__,
|
||||||
|
(prot_mask & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "",
|
||||||
|
(prot_mask & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "",
|
||||||
|
(prot_mask & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "",
|
||||||
|
(prot_mask & SHOST_DIX_TYPE0_PROTECTION) ? " DIX0" : "",
|
||||||
|
(prot_mask & SHOST_DIX_TYPE1_PROTECTION) ? " DIX1" : "",
|
||||||
|
(prot_mask & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "",
|
||||||
|
(prot_mask & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : "");
|
||||||
|
|
||||||
|
if (prot_guard_mask)
|
||||||
|
scsi_host_set_guard(shost, (prot_guard_mask & 3));
|
||||||
|
else
|
||||||
|
scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
|
||||||
|
|
||||||
snprintf(mrioc->fwevt_worker_name, sizeof(mrioc->fwevt_worker_name),
|
snprintf(mrioc->fwevt_worker_name, sizeof(mrioc->fwevt_worker_name),
|
||||||
"%s%d_fwevt_wrkr", mrioc->driver_name, mrioc->id);
|
"%s%d_fwevt_wrkr", mrioc->driver_name, mrioc->id);
|
||||||
mrioc->fwevt_worker_thread = alloc_ordered_workqueue(
|
mrioc->fwevt_worker_thread = alloc_ordered_workqueue(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user