deal with resource allocation bugs in arcmsr
authorAl Viro <viro@ftp.linux.org.uk>
Mon, 29 Oct 2007 05:08:38 +0000 (05:08 +0000)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Mon, 29 Oct 2007 14:41:33 +0000 (07:41 -0700)
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 <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/scsi/arcmsr/arcmsr.h
drivers/scsi/arcmsr/arcmsr_hba.c

index 3c38cd8d71178063fdde265cd70b14c96680d7be..a67e29f83ae5003cdcb8e65e75951d7fee3093b6 100644 (file)
@@ -348,14 +348,6 @@ struct MessageUnit_B
        uint32_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 AdapterControlBlock
        uint32_t                        outbound_int_enable;
 
        union {
-               struct MessageUnit *            pmu;
                struct MessageUnit_A __iomem *  pmuA;
                struct MessageUnit_B *          pmuB;
        };
index 2f34cdb0bec197333912ea72a98cb51770de4830..d466a2dac1dbcba2d5e28d44260408bfa6979792 100644 (file)
@@ -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,