aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2011-03-11 16:05:52 -0500
committerJames Bottomley <James.Bottomley@suse.de>2011-03-23 12:36:07 -0400
commit7f86059ac016d8662e5fbfab4875529510977b47 (patch)
treed0baa921c2c2b642663d25a615905f7a302f567f /drivers/scsi/lpfc
parent5a6f133eea2d0b4f8f75367b803fef0f03acf268 (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')
-rw-r--r--drivers/scsi/lpfc/lpfc.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h4
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h11
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c1
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c41
6 files changed, 48 insertions, 15 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index b64c6da870d3..d9869f417d4f 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -539,6 +539,8 @@ struct lpfc_hba {
539 (struct lpfc_hba *, uint32_t); 539 (struct lpfc_hba *, uint32_t);
540 int (*lpfc_hba_down_link) 540 int (*lpfc_hba_down_link)
541 (struct lpfc_hba *, uint32_t); 541 (struct lpfc_hba *, uint32_t);
542 int (*lpfc_selective_reset)
543 (struct lpfc_hba *);
542 544
543 /* SLI4 specific HBA data structure */ 545 /* SLI4 specific HBA data structure */
544 struct lpfc_sli4_hba sli4_hba; 546 struct lpfc_sli4_hba sli4_hba;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index e7c020df12fa..427c046e8209 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -685,7 +685,7 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
685 * -EIO reset not configured or error posting the event 685 * -EIO reset not configured or error posting the event
686 * zero for success 686 * zero for success
687 **/ 687 **/
688static int 688int
689lpfc_selective_reset(struct lpfc_hba *phba) 689lpfc_selective_reset(struct lpfc_hba *phba)
690{ 690{
691 struct completion online_compl; 691 struct completion online_compl;
@@ -746,7 +746,7 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
746 int status = -EINVAL; 746 int status = -EINVAL;
747 747
748 if (strncmp(buf, "selective", sizeof("selective") - 1) == 0) 748 if (strncmp(buf, "selective", sizeof("selective") - 1) == 0)
749 status = lpfc_selective_reset(phba); 749 status = phba->lpfc_selective_reset(phba);
750 750
751 if (status == 0) 751 if (status == 0)
752 return strlen(buf); 752 return strlen(buf);
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 3d40023f4804..60281d875184 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -254,8 +254,8 @@ uint16_t lpfc_sli_next_iotag(struct lpfc_hba *, struct lpfc_iocbq *);
254void lpfc_sli_cancel_iocbs(struct lpfc_hba *, struct list_head *, uint32_t, 254void lpfc_sli_cancel_iocbs(struct lpfc_hba *, struct list_head *, uint32_t,
255 uint32_t); 255 uint32_t);
256void lpfc_sli_wake_mbox_wait(struct lpfc_hba *, LPFC_MBOXQ_t *); 256void lpfc_sli_wake_mbox_wait(struct lpfc_hba *, LPFC_MBOXQ_t *);
257 257int lpfc_selective_reset(struct lpfc_hba *);
258void lpfc_reset_barrier(struct lpfc_hba * phba); 258void lpfc_reset_barrier(struct lpfc_hba *);
259int lpfc_sli_brdready(struct lpfc_hba *, uint32_t); 259int lpfc_sli_brdready(struct lpfc_hba *, uint32_t);
260int lpfc_sli_brdkill(struct lpfc_hba *); 260int lpfc_sli_brdkill(struct lpfc_hba *);
261int lpfc_sli_brdreset(struct lpfc_hba *); 261int lpfc_sli_brdreset(struct lpfc_hba *);
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 94ae37c5111a..057ab82bf399 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -1713,6 +1713,17 @@ struct lpfc_pde6 {
1713#define pde6_apptagval_WORD word2 1713#define pde6_apptagval_WORD word2
1714}; 1714};
1715 1715
1716struct lpfc_pde7 {
1717 uint32_t word0;
1718#define pde7_type_SHIFT 24
1719#define pde7_type_MASK 0x000000ff
1720#define pde7_type_WORD word0
1721#define pde7_rsvd0_SHIFT 0
1722#define pde7_rsvd0_MASK 0x00ffffff
1723#define pde7_rsvd0_WORD word0
1724 uint32_t addrHigh;
1725 uint32_t addrLow;
1726};
1716 1727
1717/* Structure for MB Command LOAD_SM and DOWN_LOAD */ 1728/* Structure for MB Command LOAD_SM and DOWN_LOAD */
1718 1729
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 35665cfb5689..29aab9432af9 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -4474,6 +4474,7 @@ lpfc_init_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
4474{ 4474{
4475 phba->lpfc_hba_init_link = lpfc_hba_init_link; 4475 phba->lpfc_hba_init_link = lpfc_hba_init_link;
4476 phba->lpfc_hba_down_link = lpfc_hba_down_link; 4476 phba->lpfc_hba_down_link = lpfc_hba_down_link;
4477 phba->lpfc_selective_reset = lpfc_selective_reset;
4477 switch (dev_grp) { 4478 switch (dev_grp) {
4478 case LPFC_PCI_DEV_LP: 4479 case LPFC_PCI_DEV_LP:
4479 phba->lpfc_hba_down_post = lpfc_hba_down_post_s3; 4480 phba->lpfc_hba_down_post = lpfc_hba_down_post_s3;
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,
1514 struct scatterlist *sgpe = NULL; /* s/g prot entry */ 1514 struct scatterlist *sgpe = NULL; /* s/g prot entry */
1515 struct lpfc_pde5 *pde5 = NULL; 1515 struct lpfc_pde5 *pde5 = NULL;
1516 struct lpfc_pde6 *pde6 = NULL; 1516 struct lpfc_pde6 *pde6 = NULL;
1517 struct ulp_bde64 *prot_bde = NULL; 1517 struct lpfc_pde7 *pde7 = NULL;
1518 dma_addr_t dataphysaddr, protphysaddr; 1518 dma_addr_t dataphysaddr, protphysaddr;
1519 unsigned short curr_data = 0, curr_prot = 0; 1519 unsigned short curr_data = 0, curr_prot = 0;
1520 unsigned int split_offset, protgroup_len; 1520 unsigned int split_offset;
1521 unsigned int protgroup_len, protgroup_offset = 0, protgroup_remainder;
1521 unsigned int protgrp_blks, protgrp_bytes; 1522 unsigned int protgrp_blks, protgrp_bytes;
1522 unsigned int remainder, subtotal; 1523 unsigned int remainder, subtotal;
1523 int status; 1524 int status;
@@ -1585,23 +1586,33 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
1585 bpl++; 1586 bpl++;
1586 1587
1587 /* setup the first BDE that points to protection buffer */ 1588 /* setup the first BDE that points to protection buffer */
1588 prot_bde = (struct ulp_bde64 *) bpl; 1589 protphysaddr = sg_dma_address(sgpe) + protgroup_offset;
1589 protphysaddr = sg_dma_address(sgpe); 1590 protgroup_len = sg_dma_len(sgpe) - protgroup_offset;
1590 prot_bde->addrHigh = le32_to_cpu(putPaddrLow(protphysaddr));
1591 prot_bde->addrLow = le32_to_cpu(putPaddrHigh(protphysaddr));
1592 protgroup_len = sg_dma_len(sgpe);
1593 1591
1594 /* must be integer multiple of the DIF block length */ 1592 /* must be integer multiple of the DIF block length */
1595 BUG_ON(protgroup_len % 8); 1593 BUG_ON(protgroup_len % 8);
1596 1594
1595 pde7 = (struct lpfc_pde7 *) bpl;
1596 memset(pde7, 0, sizeof(struct lpfc_pde7));
1597 bf_set(pde7_type, pde7, LPFC_PDE7_DESCRIPTOR);
1598
1599 pde7->addrHigh = le32_to_cpu(putPaddrLow(protphysaddr));
1600 pde7->addrLow = le32_to_cpu(putPaddrHigh(protphysaddr));
1601
1597 protgrp_blks = protgroup_len / 8; 1602 protgrp_blks = protgroup_len / 8;
1598 protgrp_bytes = protgrp_blks * blksize; 1603 protgrp_bytes = protgrp_blks * blksize;
1599 1604
1600 prot_bde->tus.f.bdeSize = protgroup_len; 1605 /* check if this pde is crossing the 4K boundary; if so split */
1601 prot_bde->tus.f.bdeFlags = LPFC_PDE7_DESCRIPTOR; 1606 if ((pde7->addrLow & 0xfff) + protgroup_len > 0x1000) {
1602 prot_bde->tus.w = le32_to_cpu(bpl->tus.w); 1607 protgroup_remainder = 0x1000 - (pde7->addrLow & 0xfff);
1608 protgroup_offset += protgroup_remainder;
1609 protgrp_blks = protgroup_remainder / 8;
1610 protgrp_bytes = protgroup_remainder * blksize;
1611 } else {
1612 protgroup_offset = 0;
1613 curr_prot++;
1614 }
1603 1615
1604 curr_prot++;
1605 num_bde++; 1616 num_bde++;
1606 1617
1607 /* setup BDE's for data blocks associated with DIF data */ 1618 /* 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 1664
1654 } 1665 }
1655 1666
1667 if (protgroup_offset) {
1668 /* update the reference tag */
1669 reftag += protgrp_blks;
1670 bpl++;
1671 continue;
1672 }
1673
1656 /* are we done ? */ 1674 /* are we done ? */
1657 if (curr_prot == protcnt) { 1675 if (curr_prot == protcnt) {
1658 alldone = 1; 1676 alldone = 1;
@@ -1675,6 +1693,7 @@ out:
1675 1693
1676 return num_bde; 1694 return num_bde;
1677} 1695}
1696
1678/* 1697/*
1679 * Given a SCSI command that supports DIF, determine composition of protection 1698 * Given a SCSI command that supports DIF, determine composition of protection
1680 * groups involved in setting up buffer lists 1699 * groups involved in setting up buffer lists