From 758d11bf096ada9d38fc690c2efe5e4661685bfc Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 24 Apr 2005 19:14:36 -0700 Subject: [ATM]: ENI155P error handling fix From: Panagiotis Issaris In the ENI155P device driver in six possible failure cases the requested irq is not being released. In three of the above possible failure cases additionally there seems to be a memory leak. Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/atm/eni.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers/atm') diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c index 78e34ee..10da369 100644 --- a/drivers/atm/eni.c +++ b/drivers/atm/eni.c @@ -59,7 +59,6 @@ * - doesn't support OAM cells * - eni_put_free may hang if not putting memory fragments that _complete_ * 2^n block (never happens in real life, though) - * - keeps IRQ even if initialization fails */ @@ -1802,22 +1801,22 @@ static int __devinit eni_start(struct atm_dev *dev) if (request_irq(eni_dev->irq,&eni_int,SA_SHIRQ,DEV_LABEL,dev)) { printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n", dev->number,eni_dev->irq); - return -EAGAIN; + error = -EAGAIN; + goto out; } - /* @@@ should release IRQ on error */ pci_set_master(eni_dev->pci_dev); if ((error = pci_write_config_word(eni_dev->pci_dev,PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | (eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) { printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory+" "master (0x%02x)\n",dev->number,error); - return error; + goto free_irq; } if ((error = pci_write_config_byte(eni_dev->pci_dev,PCI_TONGA_CTRL, END_SWAP_DMA))) { printk(KERN_ERR DEV_LABEL "(itf %d): can't set endian swap " "(0x%02x)\n",dev->number,error); - return error; + goto free_irq; } /* determine addresses of internal tables */ eni_dev->vci = eni_dev->ram; @@ -1839,7 +1838,8 @@ static int __devinit eni_start(struct atm_dev *dev) if (!eni_dev->free_list) { printk(KERN_ERR DEV_LABEL "(itf %d): couldn't get free page\n", dev->number); - return -ENOMEM; + error = -ENOMEM; + goto free_irq; } eni_dev->free_len = 0; eni_put_free(eni_dev,buf,buffer_mem); @@ -1855,17 +1855,26 @@ static int __devinit eni_start(struct atm_dev *dev) */ eni_out(0xffffffff,MID_IE); error = start_tx(dev); - if (error) return error; + if (error) goto free_list; error = start_rx(dev); - if (error) return error; + if (error) goto free_list; error = dev->phy->start(dev); - if (error) return error; + if (error) goto free_list; eni_out(eni_in(MID_MC_S) | (1 << MID_INT_SEL_SHIFT) | MID_TX_LOCK_MODE | MID_DMA_ENABLE | MID_TX_ENABLE | MID_RX_ENABLE, MID_MC_S); /* Tonga uses SBus INTReq1 */ (void) eni_in(MID_ISA); /* clear Midway interrupts */ return 0; + +free_list: + kfree(eni_dev->free_list); + +free_irq: + free_irq(eni_dev->irq, eni_dev); + +out: + return error; } -- cgit v1.1