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 12:36:07 -0400 |
commit | 7f86059ac016d8662e5fbfab4875529510977b47 (patch) | |
tree | d0baa921c2c2b642663d25a615905f7a302f567f /drivers/scsi/lpfc | |
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')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 11 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 41 |
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 | **/ |
688 | static int | 688 | int |
689 | lpfc_selective_reset(struct lpfc_hba *phba) | 689 | lpfc_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 *); | |||
254 | void lpfc_sli_cancel_iocbs(struct lpfc_hba *, struct list_head *, uint32_t, | 254 | void lpfc_sli_cancel_iocbs(struct lpfc_hba *, struct list_head *, uint32_t, |
255 | uint32_t); | 255 | uint32_t); |
256 | void lpfc_sli_wake_mbox_wait(struct lpfc_hba *, LPFC_MBOXQ_t *); | 256 | void lpfc_sli_wake_mbox_wait(struct lpfc_hba *, LPFC_MBOXQ_t *); |
257 | 257 | int lpfc_selective_reset(struct lpfc_hba *); | |
258 | void lpfc_reset_barrier(struct lpfc_hba * phba); | 258 | void lpfc_reset_barrier(struct lpfc_hba *); |
259 | int lpfc_sli_brdready(struct lpfc_hba *, uint32_t); | 259 | int lpfc_sli_brdready(struct lpfc_hba *, uint32_t); |
260 | int lpfc_sli_brdkill(struct lpfc_hba *); | 260 | int lpfc_sli_brdkill(struct lpfc_hba *); |
261 | int lpfc_sli_brdreset(struct lpfc_hba *); | 261 | int 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 | ||
1716 | struct 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 |