diff options
Diffstat (limited to 'drivers/scsi/megaraid.c')
| -rw-r--r-- | drivers/scsi/megaraid.c | 70 |
1 files changed, 50 insertions, 20 deletions
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 6f308ebe3e79..61a6fd810bb4 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c | |||
| @@ -621,8 +621,6 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy) | |||
| 621 | if(islogical) { | 621 | if(islogical) { |
| 622 | switch (cmd->cmnd[0]) { | 622 | switch (cmd->cmnd[0]) { |
| 623 | case TEST_UNIT_READY: | 623 | case TEST_UNIT_READY: |
| 624 | memset(cmd->request_buffer, 0, cmd->request_bufflen); | ||
| 625 | |||
| 626 | #if MEGA_HAVE_CLUSTERING | 624 | #if MEGA_HAVE_CLUSTERING |
| 627 | /* | 625 | /* |
| 628 | * Do we support clustering and is the support enabled | 626 | * Do we support clustering and is the support enabled |
| @@ -652,11 +650,28 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy) | |||
| 652 | return NULL; | 650 | return NULL; |
| 653 | #endif | 651 | #endif |
| 654 | 652 | ||
| 655 | case MODE_SENSE: | 653 | case MODE_SENSE: { |
| 654 | char *buf; | ||
| 655 | |||
| 656 | if (cmd->use_sg) { | ||
| 657 | struct scatterlist *sg; | ||
| 658 | |||
| 659 | sg = (struct scatterlist *)cmd->request_buffer; | ||
| 660 | buf = kmap_atomic(sg->page, KM_IRQ0) + | ||
| 661 | sg->offset; | ||
| 662 | } else | ||
| 663 | buf = cmd->request_buffer; | ||
| 656 | memset(cmd->request_buffer, 0, cmd->cmnd[4]); | 664 | memset(cmd->request_buffer, 0, cmd->cmnd[4]); |
| 665 | if (cmd->use_sg) { | ||
| 666 | struct scatterlist *sg; | ||
| 667 | |||
| 668 | sg = (struct scatterlist *)cmd->request_buffer; | ||
| 669 | kunmap_atomic(buf - sg->offset, KM_IRQ0); | ||
| 670 | } | ||
| 657 | cmd->result = (DID_OK << 16); | 671 | cmd->result = (DID_OK << 16); |
| 658 | cmd->scsi_done(cmd); | 672 | cmd->scsi_done(cmd); |
| 659 | return NULL; | 673 | return NULL; |
| 674 | } | ||
| 660 | 675 | ||
| 661 | case READ_CAPACITY: | 676 | case READ_CAPACITY: |
| 662 | case INQUIRY: | 677 | case INQUIRY: |
| @@ -1685,14 +1700,23 @@ mega_rundoneq (adapter_t *adapter) | |||
| 1685 | static void | 1700 | static void |
| 1686 | mega_free_scb(adapter_t *adapter, scb_t *scb) | 1701 | mega_free_scb(adapter_t *adapter, scb_t *scb) |
| 1687 | { | 1702 | { |
| 1703 | unsigned long length; | ||
| 1704 | |||
| 1688 | switch( scb->dma_type ) { | 1705 | switch( scb->dma_type ) { |
| 1689 | 1706 | ||
| 1690 | case MEGA_DMA_TYPE_NONE: | 1707 | case MEGA_DMA_TYPE_NONE: |
| 1691 | break; | 1708 | break; |
| 1692 | 1709 | ||
| 1693 | case MEGA_BULK_DATA: | 1710 | case MEGA_BULK_DATA: |
| 1711 | if (scb->cmd->use_sg == 0) | ||
| 1712 | length = scb->cmd->request_bufflen; | ||
| 1713 | else { | ||
| 1714 | struct scatterlist *sgl = | ||
| 1715 | (struct scatterlist *)scb->cmd->request_buffer; | ||
| 1716 | length = sgl->length; | ||
| 1717 | } | ||
| 1694 | pci_unmap_page(adapter->dev, scb->dma_h_bulkdata, | 1718 | pci_unmap_page(adapter->dev, scb->dma_h_bulkdata, |
| 1695 | scb->cmd->request_bufflen, scb->dma_direction); | 1719 | length, scb->dma_direction); |
| 1696 | break; | 1720 | break; |
| 1697 | 1721 | ||
| 1698 | case MEGA_SGLIST: | 1722 | case MEGA_SGLIST: |
| @@ -1741,6 +1765,7 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len) | |||
| 1741 | struct scatterlist *sgl; | 1765 | struct scatterlist *sgl; |
| 1742 | struct page *page; | 1766 | struct page *page; |
| 1743 | unsigned long offset; | 1767 | unsigned long offset; |
| 1768 | unsigned int length; | ||
| 1744 | Scsi_Cmnd *cmd; | 1769 | Scsi_Cmnd *cmd; |
| 1745 | int sgcnt; | 1770 | int sgcnt; |
| 1746 | int idx; | 1771 | int idx; |
| @@ -1748,14 +1773,23 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len) | |||
| 1748 | cmd = scb->cmd; | 1773 | cmd = scb->cmd; |
| 1749 | 1774 | ||
| 1750 | /* Scatter-gather not used */ | 1775 | /* Scatter-gather not used */ |
| 1751 | if( !cmd->use_sg ) { | 1776 | if( cmd->use_sg == 0 || (cmd->use_sg == 1 && |
| 1752 | 1777 | !adapter->has_64bit_addr)) { | |
| 1753 | page = virt_to_page(cmd->request_buffer); | 1778 | |
| 1754 | offset = offset_in_page(cmd->request_buffer); | 1779 | if (cmd->use_sg == 0) { |
| 1780 | page = virt_to_page(cmd->request_buffer); | ||
| 1781 | offset = offset_in_page(cmd->request_buffer); | ||
| 1782 | length = cmd->request_bufflen; | ||
| 1783 | } else { | ||
| 1784 | sgl = (struct scatterlist *)cmd->request_buffer; | ||
| 1785 | page = sgl->page; | ||
| 1786 | offset = sgl->offset; | ||
| 1787 | length = sgl->length; | ||
| 1788 | } | ||
| 1755 | 1789 | ||
| 1756 | scb->dma_h_bulkdata = pci_map_page(adapter->dev, | 1790 | scb->dma_h_bulkdata = pci_map_page(adapter->dev, |
| 1757 | page, offset, | 1791 | page, offset, |
| 1758 | cmd->request_bufflen, | 1792 | length, |
| 1759 | scb->dma_direction); | 1793 | scb->dma_direction); |
| 1760 | scb->dma_type = MEGA_BULK_DATA; | 1794 | scb->dma_type = MEGA_BULK_DATA; |
| 1761 | 1795 | ||
| @@ -1765,14 +1799,14 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len) | |||
| 1765 | */ | 1799 | */ |
| 1766 | if( adapter->has_64bit_addr ) { | 1800 | if( adapter->has_64bit_addr ) { |
| 1767 | scb->sgl64[0].address = scb->dma_h_bulkdata; | 1801 | scb->sgl64[0].address = scb->dma_h_bulkdata; |
| 1768 | scb->sgl64[0].length = cmd->request_bufflen; | 1802 | scb->sgl64[0].length = length; |
| 1769 | *buf = (u32)scb->sgl_dma_addr; | 1803 | *buf = (u32)scb->sgl_dma_addr; |
| 1770 | *len = (u32)cmd->request_bufflen; | 1804 | *len = (u32)length; |
| 1771 | return 1; | 1805 | return 1; |
| 1772 | } | 1806 | } |
| 1773 | else { | 1807 | else { |
| 1774 | *buf = (u32)scb->dma_h_bulkdata; | 1808 | *buf = (u32)scb->dma_h_bulkdata; |
| 1775 | *len = (u32)cmd->request_bufflen; | 1809 | *len = (u32)length; |
| 1776 | } | 1810 | } |
| 1777 | return 0; | 1811 | return 0; |
| 1778 | } | 1812 | } |
| @@ -1791,27 +1825,23 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len) | |||
| 1791 | 1825 | ||
| 1792 | if( sgcnt > adapter->sglen ) BUG(); | 1826 | if( sgcnt > adapter->sglen ) BUG(); |
| 1793 | 1827 | ||
| 1828 | *len = 0; | ||
| 1829 | |||
| 1794 | for( idx = 0; idx < sgcnt; idx++, sgl++ ) { | 1830 | for( idx = 0; idx < sgcnt; idx++, sgl++ ) { |
| 1795 | 1831 | ||
| 1796 | if( adapter->has_64bit_addr ) { | 1832 | if( adapter->has_64bit_addr ) { |
| 1797 | scb->sgl64[idx].address = sg_dma_address(sgl); | 1833 | scb->sgl64[idx].address = sg_dma_address(sgl); |
| 1798 | scb->sgl64[idx].length = sg_dma_len(sgl); | 1834 | *len += scb->sgl64[idx].length = sg_dma_len(sgl); |
| 1799 | } | 1835 | } |
| 1800 | else { | 1836 | else { |
| 1801 | scb->sgl[idx].address = sg_dma_address(sgl); | 1837 | scb->sgl[idx].address = sg_dma_address(sgl); |
| 1802 | scb->sgl[idx].length = sg_dma_len(sgl); | 1838 | *len += scb->sgl[idx].length = sg_dma_len(sgl); |
| 1803 | } | 1839 | } |
| 1804 | } | 1840 | } |
| 1805 | 1841 | ||
| 1806 | /* Reset pointer and length fields */ | 1842 | /* Reset pointer and length fields */ |
| 1807 | *buf = scb->sgl_dma_addr; | 1843 | *buf = scb->sgl_dma_addr; |
| 1808 | 1844 | ||
| 1809 | /* | ||
| 1810 | * For passthru command, dataxferlen must be set, even for commands | ||
| 1811 | * with a sg list | ||
| 1812 | */ | ||
| 1813 | *len = (u32)cmd->request_bufflen; | ||
| 1814 | |||
| 1815 | /* Return count of SG requests */ | 1845 | /* Return count of SG requests */ |
| 1816 | return sgcnt; | 1846 | return sgcnt; |
| 1817 | } | 1847 | } |
