Commit 7f86059a authored by James Smart's avatar James Smart Committed by James Bottomley

[SCSI] lpfc 8.3.22: T10-DIF corrections

T10-DIF corrections
- Add selective reset jump table entry
- Split T10-DIF BDEs that cross 4K boundary
Signed-off-by: default avatarAlex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 5a6f133e
...@@ -539,6 +539,8 @@ struct lpfc_hba { ...@@ -539,6 +539,8 @@ struct lpfc_hba {
(struct lpfc_hba *, uint32_t); (struct lpfc_hba *, uint32_t);
int (*lpfc_hba_down_link) int (*lpfc_hba_down_link)
(struct lpfc_hba *, uint32_t); (struct lpfc_hba *, uint32_t);
int (*lpfc_selective_reset)
(struct lpfc_hba *);
/* SLI4 specific HBA data structure */ /* SLI4 specific HBA data structure */
struct lpfc_sli4_hba sli4_hba; struct lpfc_sli4_hba sli4_hba;
......
...@@ -685,7 +685,7 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type) ...@@ -685,7 +685,7 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
* -EIO reset not configured or error posting the event * -EIO reset not configured or error posting the event
* zero for success * zero for success
**/ **/
static int int
lpfc_selective_reset(struct lpfc_hba *phba) lpfc_selective_reset(struct lpfc_hba *phba)
{ {
struct completion online_compl; struct completion online_compl;
...@@ -746,7 +746,7 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr, ...@@ -746,7 +746,7 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
int status = -EINVAL; int status = -EINVAL;
if (strncmp(buf, "selective", sizeof("selective") - 1) == 0) if (strncmp(buf, "selective", sizeof("selective") - 1) == 0)
status = lpfc_selective_reset(phba); status = phba->lpfc_selective_reset(phba);
if (status == 0) if (status == 0)
return strlen(buf); return strlen(buf);
......
...@@ -254,8 +254,8 @@ uint16_t lpfc_sli_next_iotag(struct lpfc_hba *, struct lpfc_iocbq *); ...@@ -254,8 +254,8 @@ uint16_t lpfc_sli_next_iotag(struct lpfc_hba *, struct lpfc_iocbq *);
void lpfc_sli_cancel_iocbs(struct lpfc_hba *, struct list_head *, uint32_t, void lpfc_sli_cancel_iocbs(struct lpfc_hba *, struct list_head *, uint32_t,
uint32_t); uint32_t);
void lpfc_sli_wake_mbox_wait(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_sli_wake_mbox_wait(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_selective_reset(struct lpfc_hba *);
void lpfc_reset_barrier(struct lpfc_hba * phba); void lpfc_reset_barrier(struct lpfc_hba *);
int lpfc_sli_brdready(struct lpfc_hba *, uint32_t); int lpfc_sli_brdready(struct lpfc_hba *, uint32_t);
int lpfc_sli_brdkill(struct lpfc_hba *); int lpfc_sli_brdkill(struct lpfc_hba *);
int lpfc_sli_brdreset(struct lpfc_hba *); int lpfc_sli_brdreset(struct lpfc_hba *);
......
...@@ -1713,6 +1713,17 @@ struct lpfc_pde6 { ...@@ -1713,6 +1713,17 @@ struct lpfc_pde6 {
#define pde6_apptagval_WORD word2 #define pde6_apptagval_WORD word2
}; };
struct lpfc_pde7 {
uint32_t word0;
#define pde7_type_SHIFT 24
#define pde7_type_MASK 0x000000ff
#define pde7_type_WORD word0
#define pde7_rsvd0_SHIFT 0
#define pde7_rsvd0_MASK 0x00ffffff
#define pde7_rsvd0_WORD word0
uint32_t addrHigh;
uint32_t addrLow;
};
/* Structure for MB Command LOAD_SM and DOWN_LOAD */ /* Structure for MB Command LOAD_SM and DOWN_LOAD */
......
...@@ -4474,6 +4474,7 @@ lpfc_init_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) ...@@ -4474,6 +4474,7 @@ lpfc_init_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
{ {
phba->lpfc_hba_init_link = lpfc_hba_init_link; phba->lpfc_hba_init_link = lpfc_hba_init_link;
phba->lpfc_hba_down_link = lpfc_hba_down_link; phba->lpfc_hba_down_link = lpfc_hba_down_link;
phba->lpfc_selective_reset = lpfc_selective_reset;
switch (dev_grp) { switch (dev_grp) {
case LPFC_PCI_DEV_LP: case LPFC_PCI_DEV_LP:
phba->lpfc_hba_down_post = lpfc_hba_down_post_s3; phba->lpfc_hba_down_post = lpfc_hba_down_post_s3;
......
...@@ -1514,10 +1514,11 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, ...@@ -1514,10 +1514,11 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
struct scatterlist *sgpe = NULL; /* s/g prot entry */ struct scatterlist *sgpe = NULL; /* s/g prot entry */
struct lpfc_pde5 *pde5 = NULL; struct lpfc_pde5 *pde5 = NULL;
struct lpfc_pde6 *pde6 = NULL; struct lpfc_pde6 *pde6 = NULL;
struct ulp_bde64 *prot_bde = NULL; struct lpfc_pde7 *pde7 = NULL;
dma_addr_t dataphysaddr, protphysaddr; dma_addr_t dataphysaddr, protphysaddr;
unsigned short curr_data = 0, curr_prot = 0; unsigned short curr_data = 0, curr_prot = 0;
unsigned int split_offset, protgroup_len; unsigned int split_offset;
unsigned int protgroup_len, protgroup_offset = 0, protgroup_remainder;
unsigned int protgrp_blks, protgrp_bytes; unsigned int protgrp_blks, protgrp_bytes;
unsigned int remainder, subtotal; unsigned int remainder, subtotal;
int status; int status;
...@@ -1585,23 +1586,33 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, ...@@ -1585,23 +1586,33 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
bpl++; bpl++;
/* setup the first BDE that points to protection buffer */ /* setup the first BDE that points to protection buffer */
prot_bde = (struct ulp_bde64 *) bpl; protphysaddr = sg_dma_address(sgpe) + protgroup_offset;
protphysaddr = sg_dma_address(sgpe); protgroup_len = sg_dma_len(sgpe) - protgroup_offset;
prot_bde->addrHigh = le32_to_cpu(putPaddrLow(protphysaddr));
prot_bde->addrLow = le32_to_cpu(putPaddrHigh(protphysaddr));
protgroup_len = sg_dma_len(sgpe);
/* must be integer multiple of the DIF block length */ /* must be integer multiple of the DIF block length */
BUG_ON(protgroup_len % 8); BUG_ON(protgroup_len % 8);
pde7 = (struct lpfc_pde7 *) bpl;
memset(pde7, 0, sizeof(struct lpfc_pde7));
bf_set(pde7_type, pde7, LPFC_PDE7_DESCRIPTOR);
pde7->addrHigh = le32_to_cpu(putPaddrLow(protphysaddr));
pde7->addrLow = le32_to_cpu(putPaddrHigh(protphysaddr));
protgrp_blks = protgroup_len / 8; protgrp_blks = protgroup_len / 8;
protgrp_bytes = protgrp_blks * blksize; protgrp_bytes = protgrp_blks * blksize;
prot_bde->tus.f.bdeSize = protgroup_len; /* check if this pde is crossing the 4K boundary; if so split */
prot_bde->tus.f.bdeFlags = LPFC_PDE7_DESCRIPTOR; if ((pde7->addrLow & 0xfff) + protgroup_len > 0x1000) {
prot_bde->tus.w = le32_to_cpu(bpl->tus.w); protgroup_remainder = 0x1000 - (pde7->addrLow & 0xfff);
protgroup_offset += protgroup_remainder;
protgrp_blks = protgroup_remainder / 8;
protgrp_bytes = protgroup_remainder * blksize;
} else {
protgroup_offset = 0;
curr_prot++;
}
curr_prot++;
num_bde++; num_bde++;
/* setup BDE's for data blocks associated with DIF data */ /* setup BDE's for data blocks associated with DIF data */
...@@ -1653,6 +1664,13 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, ...@@ -1653,6 +1664,13 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
} }
if (protgroup_offset) {
/* update the reference tag */
reftag += protgrp_blks;
bpl++;
continue;
}
/* are we done ? */ /* are we done ? */
if (curr_prot == protcnt) { if (curr_prot == protcnt) {
alldone = 1; alldone = 1;
...@@ -1675,6 +1693,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, ...@@ -1675,6 +1693,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
return num_bde; return num_bde;
} }
/* /*
* Given a SCSI command that supports DIF, determine composition of protection * Given a SCSI command that supports DIF, determine composition of protection
* groups involved in setting up buffer lists * groups involved in setting up buffer lists
......
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