mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-15 09:34:17 +00:00
[SCSI] lpfc 8.3.29: T10 Diff fixes and enhancements
T10 Diff fixes and enhancements: - Add SLI4 Lancer support for T10 DIF / BlockGuard (121980) - Fix SLI4 BlockGuard behavior when protection data is generated by HBA (121980) - Enhance debugfs for injecting T10 DIF errors (123966, 132966) - Fix Incorrect usage of bghm for BlockGuard errors (127022) Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com> Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
6b5151fd7b
commit
acd6859b08
@ -534,6 +534,7 @@ struct lpfc_hba {
|
||||
void (*lpfc_scsi_prep_cmnd)
|
||||
(struct lpfc_vport *, struct lpfc_scsi_buf *,
|
||||
struct lpfc_nodelist *);
|
||||
|
||||
/* IOCB interface function jump table entries */
|
||||
int (*__lpfc_sli_issue_iocb)
|
||||
(struct lpfc_hba *, uint32_t,
|
||||
@ -541,8 +542,6 @@ struct lpfc_hba {
|
||||
void (*__lpfc_sli_release_iocbq)(struct lpfc_hba *,
|
||||
struct lpfc_iocbq *);
|
||||
int (*lpfc_hba_down_post)(struct lpfc_hba *phba);
|
||||
|
||||
|
||||
IOCB_t * (*lpfc_get_iocb_from_iocbq)
|
||||
(struct lpfc_iocbq *);
|
||||
void (*lpfc_scsi_cmd_iocb_cmpl)
|
||||
@ -551,10 +550,12 @@ struct lpfc_hba {
|
||||
/* MBOX interface function jump table entries */
|
||||
int (*lpfc_sli_issue_mbox)
|
||||
(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
|
||||
|
||||
/* Slow-path IOCB process function jump table entries */
|
||||
void (*lpfc_sli_handle_slow_ring_event)
|
||||
(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
||||
uint32_t mask);
|
||||
|
||||
/* INIT device interface function jump table entries */
|
||||
int (*lpfc_sli_hbq_to_firmware)
|
||||
(struct lpfc_hba *, uint32_t, struct hbq_dmabuf *);
|
||||
@ -573,6 +574,10 @@ struct lpfc_hba {
|
||||
int (*lpfc_selective_reset)
|
||||
(struct lpfc_hba *);
|
||||
|
||||
int (*lpfc_bg_scsi_prep_dma_buf)
|
||||
(struct lpfc_hba *, struct lpfc_scsi_buf *);
|
||||
/* Add new entries here */
|
||||
|
||||
/* SLI4 specific HBA data structure */
|
||||
struct lpfc_sli4_hba sli4_hba;
|
||||
|
||||
@ -838,6 +843,7 @@ struct lpfc_hba {
|
||||
struct dentry *debug_writeGuard; /* inject write guard_tag errors */
|
||||
struct dentry *debug_writeApp; /* inject write app_tag errors */
|
||||
struct dentry *debug_writeRef; /* inject write ref_tag errors */
|
||||
struct dentry *debug_readGuard; /* inject read guard_tag errors */
|
||||
struct dentry *debug_readApp; /* inject read app_tag errors */
|
||||
struct dentry *debug_readRef; /* inject read ref_tag errors */
|
||||
|
||||
@ -845,10 +851,11 @@ struct lpfc_hba {
|
||||
uint32_t lpfc_injerr_wgrd_cnt;
|
||||
uint32_t lpfc_injerr_wapp_cnt;
|
||||
uint32_t lpfc_injerr_wref_cnt;
|
||||
uint32_t lpfc_injerr_rgrd_cnt;
|
||||
uint32_t lpfc_injerr_rapp_cnt;
|
||||
uint32_t lpfc_injerr_rref_cnt;
|
||||
sector_t lpfc_injerr_lba;
|
||||
#define LPFC_INJERR_LBA_OFF (sector_t)0xffffffffffffffff
|
||||
#define LPFC_INJERR_LBA_OFF (sector_t)(-1)
|
||||
|
||||
struct dentry *debug_slow_ring_trc;
|
||||
struct lpfc_debugfs_trc *slow_ring_trc;
|
||||
|
@ -1019,6 +1019,8 @@ lpfc_debugfs_dif_err_read(struct file *file, char __user *buf,
|
||||
cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_wapp_cnt);
|
||||
else if (dent == phba->debug_writeRef)
|
||||
cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_wref_cnt);
|
||||
else if (dent == phba->debug_readGuard)
|
||||
cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_rgrd_cnt);
|
||||
else if (dent == phba->debug_readApp)
|
||||
cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_rapp_cnt);
|
||||
else if (dent == phba->debug_readRef)
|
||||
@ -1057,6 +1059,8 @@ lpfc_debugfs_dif_err_write(struct file *file, const char __user *buf,
|
||||
phba->lpfc_injerr_wapp_cnt = (uint32_t)tmp;
|
||||
else if (dent == phba->debug_writeRef)
|
||||
phba->lpfc_injerr_wref_cnt = (uint32_t)tmp;
|
||||
else if (dent == phba->debug_readGuard)
|
||||
phba->lpfc_injerr_rgrd_cnt = (uint32_t)tmp;
|
||||
else if (dent == phba->debug_readApp)
|
||||
phba->lpfc_injerr_rapp_cnt = (uint32_t)tmp;
|
||||
else if (dent == phba->debug_readRef)
|
||||
@ -3978,6 +3982,17 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
|
||||
goto debug_failed;
|
||||
}
|
||||
|
||||
snprintf(name, sizeof(name), "readGuardInjErr");
|
||||
phba->debug_readGuard =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_op_dif_err);
|
||||
if (!phba->debug_readGuard) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
|
||||
"0808 Cannot create debugfs readGuard\n");
|
||||
goto debug_failed;
|
||||
}
|
||||
|
||||
snprintf(name, sizeof(name), "readAppInjErr");
|
||||
phba->debug_readApp =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
@ -4318,6 +4333,10 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
|
||||
debugfs_remove(phba->debug_writeRef); /* writeRef */
|
||||
phba->debug_writeRef = NULL;
|
||||
}
|
||||
if (phba->debug_readGuard) {
|
||||
debugfs_remove(phba->debug_readGuard); /* readGuard */
|
||||
phba->debug_readGuard = NULL;
|
||||
}
|
||||
if (phba->debug_readApp) {
|
||||
debugfs_remove(phba->debug_readApp); /* readApp */
|
||||
phba->debug_readApp = NULL;
|
||||
|
@ -321,6 +321,10 @@ struct lpfc_cqe {
|
||||
#define CQE_STATUS_CMD_REJECT 0xb
|
||||
#define CQE_STATUS_FCP_TGT_LENCHECK 0xc
|
||||
#define CQE_STATUS_NEED_BUFF_ENTRY 0xf
|
||||
#define CQE_STATUS_DI_ERROR 0x16
|
||||
|
||||
/* Used when mapping CQE status to IOCB */
|
||||
#define LPFC_IOCB_STATUS_MASK 0xf
|
||||
|
||||
/* Status returned by hardware (valid only if status = CQE_STATUS_SUCCESS). */
|
||||
#define CQE_HW_STATUS_NO_ERR 0x0
|
||||
@ -348,6 +352,21 @@ struct lpfc_wcqe_complete {
|
||||
#define lpfc_wcqe_c_hw_status_WORD word0
|
||||
uint32_t total_data_placed;
|
||||
uint32_t parameter;
|
||||
#define lpfc_wcqe_c_bg_edir_SHIFT 5
|
||||
#define lpfc_wcqe_c_bg_edir_MASK 0x00000001
|
||||
#define lpfc_wcqe_c_bg_edir_WORD parameter
|
||||
#define lpfc_wcqe_c_bg_tdpv_SHIFT 3
|
||||
#define lpfc_wcqe_c_bg_tdpv_MASK 0x00000001
|
||||
#define lpfc_wcqe_c_bg_tdpv_WORD parameter
|
||||
#define lpfc_wcqe_c_bg_re_SHIFT 2
|
||||
#define lpfc_wcqe_c_bg_re_MASK 0x00000001
|
||||
#define lpfc_wcqe_c_bg_re_WORD parameter
|
||||
#define lpfc_wcqe_c_bg_ae_SHIFT 1
|
||||
#define lpfc_wcqe_c_bg_ae_MASK 0x00000001
|
||||
#define lpfc_wcqe_c_bg_ae_WORD parameter
|
||||
#define lpfc_wcqe_c_bg_ge_SHIFT 0
|
||||
#define lpfc_wcqe_c_bg_ge_MASK 0x00000001
|
||||
#define lpfc_wcqe_c_bg_ge_WORD parameter
|
||||
uint32_t word3;
|
||||
#define lpfc_wcqe_c_valid_SHIFT lpfc_cqe_valid_SHIFT
|
||||
#define lpfc_wcqe_c_valid_MASK lpfc_cqe_valid_MASK
|
||||
@ -359,8 +378,8 @@ struct lpfc_wcqe_complete {
|
||||
#define lpfc_wcqe_c_pv_MASK 0x00000001
|
||||
#define lpfc_wcqe_c_pv_WORD word3
|
||||
#define lpfc_wcqe_c_priority_SHIFT 24
|
||||
#define lpfc_wcqe_c_priority_MASK 0x00000007
|
||||
#define lpfc_wcqe_c_priority_WORD word3
|
||||
#define lpfc_wcqe_c_priority_MASK 0x00000007
|
||||
#define lpfc_wcqe_c_priority_WORD word3
|
||||
#define lpfc_wcqe_c_code_SHIFT lpfc_cqe_code_SHIFT
|
||||
#define lpfc_wcqe_c_code_MASK lpfc_cqe_code_MASK
|
||||
#define lpfc_wcqe_c_code_WORD lpfc_cqe_code_WORD
|
||||
|
@ -4380,6 +4380,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
|
||||
uint8_t pn_page[LPFC_MAX_SUPPORTED_PAGES] = {0};
|
||||
struct lpfc_mqe *mqe;
|
||||
int longs, sli_family;
|
||||
int sges_per_segment;
|
||||
|
||||
/* Before proceed, wait for POST done and device ready */
|
||||
rc = lpfc_sli4_post_status_check(phba);
|
||||
@ -4443,6 +4444,11 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
|
||||
phba->fc_map[1] = LPFC_FCOE_FCF_MAP1;
|
||||
phba->fc_map[2] = LPFC_FCOE_FCF_MAP2;
|
||||
|
||||
/* With BlockGuard we can have multiple SGEs per Data Segemnt */
|
||||
sges_per_segment = 1;
|
||||
if (phba->cfg_enable_bg)
|
||||
sges_per_segment = 2;
|
||||
|
||||
/*
|
||||
* Since the sg_tablesize is module parameter, the sg_dma_buf_size
|
||||
* used to create the sg_dma_buf_pool must be dynamically calculated.
|
||||
@ -4451,7 +4457,8 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
|
||||
* sgl sizes of must be a power of 2.
|
||||
*/
|
||||
buf_size = (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp) +
|
||||
((phba->cfg_sg_seg_cnt + 2) * sizeof(struct sli4_sge)));
|
||||
(((phba->cfg_sg_seg_cnt * sges_per_segment) + 2) *
|
||||
sizeof(struct sli4_sge)));
|
||||
|
||||
sli_family = bf_get(lpfc_sli_intf_sli_family, &phba->sli4_hba.sli_intf);
|
||||
max_buf_size = LPFC_SLI4_MAX_BUF_SIZE;
|
||||
@ -4468,6 +4475,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (dma_buf_size = LPFC_SLI4_MIN_BUF_SIZE;
|
||||
dma_buf_size < max_buf_size && buf_size > dma_buf_size;
|
||||
dma_buf_size = dma_buf_size << 1)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7839,12 +7839,16 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
|
||||
bf_set(wqe_lnk, &wqe->fcp_iwrite.wqe_com, iocbq->iocb.ulpXS);
|
||||
/* Always open the exchange */
|
||||
bf_set(wqe_xc, &wqe->fcp_iwrite.wqe_com, 0);
|
||||
bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 1);
|
||||
bf_set(wqe_iod, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_IOD_WRITE);
|
||||
bf_set(wqe_lenloc, &wqe->fcp_iwrite.wqe_com,
|
||||
LPFC_WQE_LENLOC_WORD4);
|
||||
bf_set(wqe_ebde_cnt, &wqe->fcp_iwrite.wqe_com, 0);
|
||||
bf_set(wqe_pu, &wqe->fcp_iwrite.wqe_com, iocbq->iocb.ulpPU);
|
||||
if (iocbq->iocb_flag & LPFC_IO_DIF) {
|
||||
iocbq->iocb_flag &= ~LPFC_IO_DIF;
|
||||
bf_set(wqe_dif, &wqe->generic.wqe_com, 1);
|
||||
}
|
||||
bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 1);
|
||||
break;
|
||||
case CMD_FCP_IREAD64_CR:
|
||||
/* word3 iocb=iotag wqe=payload_offset_len */
|
||||
@ -7858,12 +7862,16 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
|
||||
bf_set(wqe_lnk, &wqe->fcp_iread.wqe_com, iocbq->iocb.ulpXS);
|
||||
/* Always open the exchange */
|
||||
bf_set(wqe_xc, &wqe->fcp_iread.wqe_com, 0);
|
||||
bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 1);
|
||||
bf_set(wqe_iod, &wqe->fcp_iread.wqe_com, LPFC_WQE_IOD_READ);
|
||||
bf_set(wqe_lenloc, &wqe->fcp_iread.wqe_com,
|
||||
LPFC_WQE_LENLOC_WORD4);
|
||||
bf_set(wqe_ebde_cnt, &wqe->fcp_iread.wqe_com, 0);
|
||||
bf_set(wqe_pu, &wqe->fcp_iread.wqe_com, iocbq->iocb.ulpPU);
|
||||
if (iocbq->iocb_flag & LPFC_IO_DIF) {
|
||||
iocbq->iocb_flag &= ~LPFC_IO_DIF;
|
||||
bf_set(wqe_dif, &wqe->generic.wqe_com, 1);
|
||||
}
|
||||
bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 1);
|
||||
break;
|
||||
case CMD_FCP_ICMND64_CR:
|
||||
/* word3 iocb=IO_TAG wqe=reserved */
|
||||
@ -10672,12 +10680,14 @@ lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba,
|
||||
struct lpfc_wcqe_complete *wcqe)
|
||||
{
|
||||
unsigned long iflags;
|
||||
uint32_t status;
|
||||
size_t offset = offsetof(struct lpfc_iocbq, iocb);
|
||||
|
||||
memcpy((char *)pIocbIn + offset, (char *)pIocbOut + offset,
|
||||
sizeof(struct lpfc_iocbq) - offset);
|
||||
/* Map WCQE parameters into irspiocb parameters */
|
||||
pIocbIn->iocb.ulpStatus = bf_get(lpfc_wcqe_c_status, wcqe);
|
||||
status = bf_get(lpfc_wcqe_c_status, wcqe);
|
||||
pIocbIn->iocb.ulpStatus = (status & LPFC_IOCB_STATUS_MASK);
|
||||
if (pIocbOut->iocb_flag & LPFC_IO_FCP)
|
||||
if (pIocbIn->iocb.ulpStatus == IOSTAT_FCP_RSP_ERROR)
|
||||
pIocbIn->iocb.un.fcpi.fcpi_parm =
|
||||
@ -10690,6 +10700,44 @@ lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba,
|
||||
pIocbIn->iocb.un.genreq64.bdl.bdeSize = wcqe->total_data_placed;
|
||||
}
|
||||
|
||||
/* Convert BG errors for completion status */
|
||||
if (status == CQE_STATUS_DI_ERROR) {
|
||||
pIocbIn->iocb.ulpStatus = IOSTAT_LOCAL_REJECT;
|
||||
|
||||
if (bf_get(lpfc_wcqe_c_bg_edir, wcqe))
|
||||
pIocbIn->iocb.un.ulpWord[4] = IOERR_RX_DMA_FAILED;
|
||||
else
|
||||
pIocbIn->iocb.un.ulpWord[4] = IOERR_TX_DMA_FAILED;
|
||||
|
||||
pIocbIn->iocb.unsli3.sli3_bg.bgstat = 0;
|
||||
if (bf_get(lpfc_wcqe_c_bg_ge, wcqe)) /* Guard Check failed */
|
||||
pIocbIn->iocb.unsli3.sli3_bg.bgstat |=
|
||||
BGS_GUARD_ERR_MASK;
|
||||
if (bf_get(lpfc_wcqe_c_bg_ae, wcqe)) /* App Tag Check failed */
|
||||
pIocbIn->iocb.unsli3.sli3_bg.bgstat |=
|
||||
BGS_APPTAG_ERR_MASK;
|
||||
if (bf_get(lpfc_wcqe_c_bg_re, wcqe)) /* Ref Tag Check failed */
|
||||
pIocbIn->iocb.unsli3.sli3_bg.bgstat |=
|
||||
BGS_REFTAG_ERR_MASK;
|
||||
|
||||
/* Check to see if there was any good data before the error */
|
||||
if (bf_get(lpfc_wcqe_c_bg_tdpv, wcqe)) {
|
||||
pIocbIn->iocb.unsli3.sli3_bg.bgstat |=
|
||||
BGS_HI_WATER_MARK_PRESENT_MASK;
|
||||
pIocbIn->iocb.unsli3.sli3_bg.bghm =
|
||||
wcqe->total_data_placed;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set ALL the error bits to indicate we don't know what
|
||||
* type of error it is.
|
||||
*/
|
||||
if (!pIocbIn->iocb.unsli3.sli3_bg.bgstat)
|
||||
pIocbIn->iocb.unsli3.sli3_bg.bgstat |=
|
||||
(BGS_REFTAG_ERR_MASK | BGS_APPTAG_ERR_MASK |
|
||||
BGS_GUARD_ERR_MASK);
|
||||
}
|
||||
|
||||
/* Pick up HBA exchange busy condition */
|
||||
if (bf_get(lpfc_wcqe_c_xb, wcqe)) {
|
||||
spin_lock_irqsave(&phba->hbalock, iflags);
|
||||
|
@ -69,6 +69,7 @@ struct lpfc_iocbq {
|
||||
#define LPFC_USE_FCPWQIDX 0x80 /* Submit to specified FCPWQ index */
|
||||
#define DSS_SECURITY_OP 0x100 /* security IO */
|
||||
#define LPFC_IO_ON_Q 0x200 /* The IO is still on the TXCMPLQ */
|
||||
#define LPFC_IO_DIF 0x400 /* T10 DIF IO */
|
||||
|
||||
#define LPFC_FIP_ELS_ID_MASK 0xc000 /* ELS_ID range 0-3, non-shifted mask */
|
||||
#define LPFC_FIP_ELS_ID_SHIFT 14
|
||||
|
Loading…
x
Reference in New Issue
Block a user