Commit 758d11bf authored by Andrew Morton's avatar Andrew Morton Committed by David S. Miller

[ATM]: ENI155P error handling fix

From: Panagiotis Issaris <takis@lumumba.luc.ac.be>

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: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d5ac99a6
...@@ -59,7 +59,6 @@ ...@@ -59,7 +59,6 @@
* - doesn't support OAM cells * - doesn't support OAM cells
* - eni_put_free may hang if not putting memory fragments that _complete_ * - eni_put_free may hang if not putting memory fragments that _complete_
* 2^n block (never happens in real life, though) * 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) ...@@ -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)) { 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", printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n",
dev->number,eni_dev->irq); dev->number,eni_dev->irq);
return -EAGAIN; error = -EAGAIN;
goto out;
} }
/* @@@ should release IRQ on error */
pci_set_master(eni_dev->pci_dev); pci_set_master(eni_dev->pci_dev);
if ((error = pci_write_config_word(eni_dev->pci_dev,PCI_COMMAND, if ((error = pci_write_config_word(eni_dev->pci_dev,PCI_COMMAND,
PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
(eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) { (eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) {
printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory+" printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory+"
"master (0x%02x)\n",dev->number,error); "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, if ((error = pci_write_config_byte(eni_dev->pci_dev,PCI_TONGA_CTRL,
END_SWAP_DMA))) { END_SWAP_DMA))) {
printk(KERN_ERR DEV_LABEL "(itf %d): can't set endian swap " printk(KERN_ERR DEV_LABEL "(itf %d): can't set endian swap "
"(0x%02x)\n",dev->number,error); "(0x%02x)\n",dev->number,error);
return error; goto free_irq;
} }
/* determine addresses of internal tables */ /* determine addresses of internal tables */
eni_dev->vci = eni_dev->ram; eni_dev->vci = eni_dev->ram;
...@@ -1839,7 +1838,8 @@ static int __devinit eni_start(struct atm_dev *dev) ...@@ -1839,7 +1838,8 @@ static int __devinit eni_start(struct atm_dev *dev)
if (!eni_dev->free_list) { if (!eni_dev->free_list) {
printk(KERN_ERR DEV_LABEL "(itf %d): couldn't get free page\n", printk(KERN_ERR DEV_LABEL "(itf %d): couldn't get free page\n",
dev->number); dev->number);
return -ENOMEM; error = -ENOMEM;
goto free_irq;
} }
eni_dev->free_len = 0; eni_dev->free_len = 0;
eni_put_free(eni_dev,buf,buffer_mem); eni_put_free(eni_dev,buf,buffer_mem);
...@@ -1855,17 +1855,26 @@ static int __devinit eni_start(struct atm_dev *dev) ...@@ -1855,17 +1855,26 @@ static int __devinit eni_start(struct atm_dev *dev)
*/ */
eni_out(0xffffffff,MID_IE); eni_out(0xffffffff,MID_IE);
error = start_tx(dev); error = start_tx(dev);
if (error) return error; if (error) goto free_list;
error = start_rx(dev); error = start_rx(dev);
if (error) return error; if (error) goto free_list;
error = dev->phy->start(dev); 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) | 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_TX_LOCK_MODE | MID_DMA_ENABLE | MID_TX_ENABLE | MID_RX_ENABLE,
MID_MC_S); MID_MC_S);
/* Tonga uses SBus INTReq1 */ /* Tonga uses SBus INTReq1 */
(void) eni_in(MID_ISA); /* clear Midway interrupts */ (void) eni_in(MID_ISA); /* clear Midway interrupts */
return 0; return 0;
free_list:
kfree(eni_dev->free_list);
free_irq:
free_irq(eni_dev->irq, eni_dev);
out:
return error;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment