diff options
author | Ed Lin <ed.lin@promise.com> | 2009-09-28 22:58:17 -0800 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-10-29 13:03:25 -0400 |
commit | cbacfb5fd9a4689b55157753b8ba4455415fb85c (patch) | |
tree | bb0a6ed9efd197ef45c5bbedfd4cd04c07fdc884 /drivers/scsi/stex.c | |
parent | 080bb708ad8f21ea743d1a9233fbc62af0feb10b (diff) |
[SCSI] stex: add small dma buffer support
The controllers of st_seq and st_vsc type can work
if only small dma buffer is available, with a reduced
firmware feature set. Add support for this case.
Signed-off-by: Ed Lin <ed.lin@promise.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/stex.c')
-rw-r--r-- | drivers/scsi/stex.c | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index 09fa8861fc5..af5bafcccf1 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -160,6 +160,7 @@ enum { INQUIRY_EVPD = 0x01, ST_ADDITIONAL_MEM = 0x200000, + ST_ADDITIONAL_MEM_MIN = 0x80000, }; struct st_sgitem { @@ -1001,7 +1002,7 @@ static int stex_common_handshake(struct st_hba *hba) h->partner_type = HMU_PARTNER_TYPE; if (hba->extra_offset) { h->extra_offset = cpu_to_le32(hba->extra_offset); - h->extra_size = cpu_to_le32(ST_ADDITIONAL_MEM); + h->extra_size = cpu_to_le32(hba->dma_size - hba->extra_offset); } else h->extra_offset = h->extra_size = 0; @@ -1528,10 +1529,24 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) hba->dma_mem = dma_alloc_coherent(&pdev->dev, hba->dma_size, &hba->dma_handle, GFP_KERNEL); if (!hba->dma_mem) { - err = -ENOMEM; - printk(KERN_ERR DRV_NAME "(%s): dma mem alloc failed\n", - pci_name(pdev)); - goto out_iounmap; + /* Retry minimum coherent mapping for st_seq and st_vsc */ + if (hba->cardtype == st_seq || + (hba->cardtype == st_vsc && (pdev->subsystem_device & 1))) { + printk(KERN_WARNING DRV_NAME + "(%s): allocating min buffer for controller\n", + pci_name(pdev)); + hba->dma_size = hba->extra_offset + + ST_ADDITIONAL_MEM_MIN; + hba->dma_mem = dma_alloc_coherent(&pdev->dev, + hba->dma_size, &hba->dma_handle, GFP_KERNEL); + } + + if (!hba->dma_mem) { + err = -ENOMEM; + printk(KERN_ERR DRV_NAME "(%s): dma mem alloc failed\n", + pci_name(pdev)); + goto out_iounmap; + } } hba->ccb = kcalloc(ci->rq_count, sizeof(struct st_ccb), GFP_KERNEL); |