aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAl Viro <viro@ftp.linux.org.uk>2007-10-29 01:08:38 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-29 10:41:33 -0400
commitdb3a91fe2b425c9adde47069efebdba44e665cef (patch)
tree85137ad8531f2dfa667bad11c82116c8f5feed48 /drivers
parent142956af525002c5378e7d91d81a01189841a785 (diff)
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 <viro@zeniv.linux.org.uk> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/arcmsr/arcmsr.h9
-rw-r--r--drivers/scsi/arcmsr/arcmsr_hba.c33
2 files changed, 30 insertions, 12 deletions
diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h
index 3c38cd8d7117..a67e29f83ae5 100644
--- a/drivers/scsi/arcmsr/arcmsr.h
+++ b/drivers/scsi/arcmsr/arcmsr.h
@@ -348,14 +348,6 @@ struct MessageUnit_B
348 uint32_t __iomem *ioctl_rbuffer_reg; 348 uint32_t __iomem *ioctl_rbuffer_reg;
349}; 349};
350 350
351struct MessageUnit
352{
353 union
354 {
355 struct MessageUnit_A pmu_A;
356 struct MessageUnit_B pmu_B;
357 } u;
358};
359/* 351/*
360******************************************************************************* 352*******************************************************************************
361** Adapter Control Block 353** Adapter Control Block
@@ -375,7 +367,6 @@ struct AdapterControlBlock
375 uint32_t outbound_int_enable; 367 uint32_t outbound_int_enable;
376 368
377 union { 369 union {
378 struct MessageUnit * pmu;
379 struct MessageUnit_A __iomem * pmuA; 370 struct MessageUnit_A __iomem * pmuA;
380 struct MessageUnit_B * pmuB; 371 struct MessageUnit_B * pmuB;
381 }; 372 };
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 2f34cdb0bec1..d466a2dac1db 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -240,14 +240,18 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
240 if (!acb->pmuA) { 240 if (!acb->pmuA) {
241 printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", 241 printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n",
242 acb->host->host_no); 242 acb->host->host_no);
243 return -ENOMEM;
243 } 244 }
244 245
245 dma_coherent = dma_alloc_coherent(&pdev->dev, 246 dma_coherent = dma_alloc_coherent(&pdev->dev,
246 ARCMSR_MAX_FREECCB_NUM * 247 ARCMSR_MAX_FREECCB_NUM *
247 sizeof (struct CommandControlBlock) + 0x20, 248 sizeof (struct CommandControlBlock) + 0x20,
248 &dma_coherent_handle, GFP_KERNEL); 249 &dma_coherent_handle, GFP_KERNEL);
249 if (!dma_coherent) 250
251 if (!dma_coherent) {
252 iounmap(acb->pmuA);
250 return -ENOMEM; 253 return -ENOMEM;
254 }
251 255
252 acb->dma_coherent = dma_coherent; 256 acb->dma_coherent = dma_coherent;
253 acb->dma_coherent_handle = dma_coherent_handle; 257 acb->dma_coherent_handle = dma_coherent_handle;
@@ -331,8 +335,16 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
331 acb->pmuB = reg; 335 acb->pmuB = reg;
332 mem_base0 = ioremap(pci_resource_start(pdev, 0), 336 mem_base0 = ioremap(pci_resource_start(pdev, 0),
333 pci_resource_len(pdev, 0)); 337 pci_resource_len(pdev, 0));
338 if (!mem_base0)
339 goto out;
340
334 mem_base1 = ioremap(pci_resource_start(pdev, 2), 341 mem_base1 = ioremap(pci_resource_start(pdev, 2),
335 pci_resource_len(pdev, 2)); 342 pci_resource_len(pdev, 2));
343 if (!mem_base1) {
344 iounmap(mem_base0);
345 goto out;
346 }
347
336 reg->drv2iop_doorbell_reg = mem_base0 + ARCMSR_DRV2IOP_DOORBELL; 348 reg->drv2iop_doorbell_reg = mem_base0 + ARCMSR_DRV2IOP_DOORBELL;
337 reg->drv2iop_doorbell_mask_reg = mem_base0 + 349 reg->drv2iop_doorbell_mask_reg = mem_base0 +
338 ARCMSR_DRV2IOP_DOORBELL_MASK; 350 ARCMSR_DRV2IOP_DOORBELL_MASK;
@@ -357,6 +369,12 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
357 break; 369 break;
358 } 370 }
359 return 0; 371 return 0;
372
373out:
374 dma_free_coherent(&acb->pdev->dev,
375 ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20,
376 acb->dma_coherent, acb->dma_coherent_handle);
377 return -ENOMEM;
360} 378}
361 379
362static int arcmsr_probe(struct pci_dev *pdev, 380static int arcmsr_probe(struct pci_dev *pdev,
@@ -449,7 +467,6 @@ static int arcmsr_probe(struct pci_dev *pdev,
449 free_irq(pdev->irq, acb); 467 free_irq(pdev->irq, acb);
450 out_free_ccb_pool: 468 out_free_ccb_pool:
451 arcmsr_free_ccb_pool(acb); 469 arcmsr_free_ccb_pool(acb);
452 iounmap(acb->pmu);
453 out_release_regions: 470 out_release_regions:
454 pci_release_regions(pdev); 471 pci_release_regions(pdev);
455 out_host_put: 472 out_host_put:
@@ -810,7 +827,6 @@ static void arcmsr_remove(struct pci_dev *pdev)
810 } 827 }
811 828
812 free_irq(pdev->irq, acb); 829 free_irq(pdev->irq, acb);
813 iounmap(acb->pmu);
814 arcmsr_free_ccb_pool(acb); 830 arcmsr_free_ccb_pool(acb);
815 pci_release_regions(pdev); 831 pci_release_regions(pdev);
816 832
@@ -1018,6 +1034,17 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
1018 1034
1019static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb) 1035static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb)
1020{ 1036{
1037 switch (acb->adapter_type) {
1038 case ACB_ADAPTER_TYPE_A: {
1039 iounmap(acb->pmuA);
1040 break;
1041 }
1042 case ACB_ADAPTER_TYPE_B: {
1043 struct MessageUnit_B *reg = acb->pmuB;
1044 iounmap(reg->drv2iop_doorbell_reg - ARCMSR_DRV2IOP_DOORBELL);
1045 iounmap(reg->ioctl_wbuffer_reg - ARCMSR_IOCTL_WBUFFER);
1046 }
1047 }
1021 dma_free_coherent(&acb->pdev->dev, 1048 dma_free_coherent(&acb->pdev->dev,
1022 ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20, 1049 ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20,
1023 acb->dma_coherent, 1050 acb->dma_coherent,