diff options
author | James Smart <james.smart@emulex.com> | 2011-03-11 16:05:52 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2011-03-23 11:36:07 -0500 |
commit | 7f86059ac016d8662e5fbfab4875529510977b47 (patch) | |
tree | d0baa921c2c2b642663d25a615905f7a302f567f /drivers/scsi/lpfc/lpfc_scsi.c | |
parent | 5a6f133eea2d0b4f8f75367b803fef0f03acf268 (diff) |
[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: Alex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_scsi.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index bf34178b80bf..e3a1d295e4dc 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -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 lpfc_pde5 *pde5 = NULL; struct lpfc_pde6 *pde6 = NULL; - struct ulp_bde64 *prot_bde = NULL; + struct lpfc_pde7 *pde7 = NULL; dma_addr_t dataphysaddr, protphysaddr; 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 remainder, subtotal; int status; @@ -1585,23 +1586,33 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, bpl++; /* setup the first BDE that points to protection buffer */ - prot_bde = (struct ulp_bde64 *) bpl; - protphysaddr = sg_dma_address(sgpe); - prot_bde->addrHigh = le32_to_cpu(putPaddrLow(protphysaddr)); - prot_bde->addrLow = le32_to_cpu(putPaddrHigh(protphysaddr)); - protgroup_len = sg_dma_len(sgpe); + protphysaddr = sg_dma_address(sgpe) + protgroup_offset; + protgroup_len = sg_dma_len(sgpe) - protgroup_offset; /* must be integer multiple of the DIF block length */ 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_bytes = protgrp_blks * blksize; - prot_bde->tus.f.bdeSize = protgroup_len; - prot_bde->tus.f.bdeFlags = LPFC_PDE7_DESCRIPTOR; - prot_bde->tus.w = le32_to_cpu(bpl->tus.w); + /* check if this pde is crossing the 4K boundary; if so split */ + if ((pde7->addrLow & 0xfff) + protgroup_len > 0x1000) { + 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++; /* 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, } + if (protgroup_offset) { + /* update the reference tag */ + reftag += protgrp_blks; + bpl++; + continue; + } + /* are we done ? */ if (curr_prot == protcnt) { alldone = 1; @@ -1675,6 +1693,7 @@ out: return num_bde; } + /* * Given a SCSI command that supports DIF, determine composition of protection * groups involved in setting up buffer lists |