deal with resource allocation bugs in arcmsr
a) for type B we should _not_ iounmap() acb->pmu; it's not ioremapped.
b) for type B we should iounmap() two regions we _do_ ioremap.
c) if ioremap() fails, we need to bail out (and clean up).
Signed-off-by Al Viro <[email protected]>
--- drivers/scsi/arcmsr/arcmsr.h | 9 --------- drivers/scsi/arcmsr/arcmsr_hba.c | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 12 deletions(-)
drivers/scsi/arcmsr/arcmsr.h +0 -9
@@ -348,14 +348,6 @@ struct MessageUnit_Buint32_t __iomem *ioctl_rbuffer_reg; }; -struct MessageUnit -{ -union - { -struct MessageUnit_A pmu_A; -struct MessageUnit_B pmu_B; - } u; -};/* ******************************************************************************* ** Adapter Control Block
@@ -375,7 +367,6 @@ struct AdapterControlBlockuint32_t outbound_int_enable;union { -struct MessageUnit * pmu;struct MessageUnit_A __iomem * pmuA;struct MessageUnit_B * pmuB; };
drivers/scsi/arcmsr/arcmsr_hba.c +30 -3
@@ -240,14 +240,18 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)if (!acb->pmuA) {printk (KERN_NOTICE "arcmsr%d: memory mapping region fail \n" , acb->host->host_no); +return -ENOMEM ; } dma_coherent =dma_alloc_coherent (&pdev->dev,ARCMSR_MAX_FREECCB_NUM *sizeof (struct CommandControlBlock ) +0x20 , &dma_coherent_handle,GFP_KERNEL ); -if (!dma_coherent) + +if (!dma_coherent) { +iounmap (acb->pmuA);return -ENOMEM ; + } acb->dma_coherent = dma_coherent; acb->dma_coherent_handle = dma_coherent_handle;
@@ -331,8 +335,16 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) acb->pmuB = reg; mem_base0 =ioremap (pci_resource_start (pdev,0 ),pci_resource_len (pdev,0 )); +if (!mem_base0) + goto out; + mem_base1 =ioremap (pci_resource_start (pdev,2 ),pci_resource_len (pdev,2 )); +if (!mem_base1) { +iounmap (mem_base0); + goto out; + } + reg->drv2iop_doorbell_reg = mem_base0 +ARCMSR_DRV2IOP_DOORBELL ; reg->drv2iop_doorbell_mask_reg = mem_base0 +ARCMSR_DRV2IOP_DOORBELL_MASK ;
@@ -357,6 +369,12 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)break ; }return 0 ; + +out: +dma_free_coherent (&acb->pdev->dev, +ARCMSR_MAX_FREECCB_NUM *sizeof (struct CommandControlBlock ) +0x20 , + acb->dma_coherent, acb->dma_coherent_handle); +return -ENOMEM ; } static int arcmsr_probe(struct pci_dev *pdev,
@@ -449,7 +467,6 @@ static int arcmsr_probe(struct pci_dev *pdev,free_irq (pdev->irq, acb); out_free_ccb_pool:arcmsr_free_ccb_pool (acb); -iounmap (acb->pmu); out_release_regions:pci_release_regions (pdev); out_host_put:
@@ -810,7 +827,6 @@ static void arcmsr_remove(struct pci_dev *pdev) }free_irq (pdev->irq, acb); -iounmap (acb->pmu);arcmsr_free_ccb_pool (acb);pci_release_regions (pdev);
@@ -1018,6 +1034,17 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)static void arcmsr_free_ccb_pool (struct AdapterControlBlock *acb) { +switch (acb->adapter_type) { +case ACB_ADAPTER_TYPE_A : { +iounmap (acb->pmuA); +break ; + } +case ACB_ADAPTER_TYPE_B : { +struct MessageUnit_B *reg = acb->pmuB; +iounmap (reg->drv2iop_doorbell_reg -ARCMSR_DRV2IOP_DOORBELL ); +iounmap (reg->ioctl_wbuffer_reg -ARCMSR_IOCTL_WBUFFER ); + } + } dma_free_coherent(&acb->pdev->dev, ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20, acb->dma_coherent,
Signature · 1 line
1.5.3.GIT