aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2005-04-24 22:14:36 -0400
committerDavid S. Miller <davem@davemloft.net>2005-04-24 22:14:36 -0400
commit758d11bf096ada9d38fc690c2efe5e4661685bfc (patch)
tree3e6659e01973d3ee028aae15d679aab218c830a9
parentd5ac99a648b8c61d0c7f1c32a8ab7f1dca0123d2 (diff)
[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: Andrew Morton <akpm@osdl.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/atm/eni.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 78e34ee79df8..10da36934769 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -59,7 +59,6 @@
59 * - doesn't support OAM cells 59 * - doesn't support OAM cells
60 * - eni_put_free may hang if not putting memory fragments that _complete_ 60 * - eni_put_free may hang if not putting memory fragments that _complete_
61 * 2^n block (never happens in real life, though) 61 * 2^n block (never happens in real life, though)
62 * - keeps IRQ even if initialization fails
63 */ 62 */
64 63
65 64
@@ -1802,22 +1801,22 @@ static int __devinit eni_start(struct atm_dev *dev)
1802 if (request_irq(eni_dev->irq,&eni_int,SA_SHIRQ,DEV_LABEL,dev)) { 1801 if (request_irq(eni_dev->irq,&eni_int,SA_SHIRQ,DEV_LABEL,dev)) {
1803 printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n", 1802 printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n",
1804 dev->number,eni_dev->irq); 1803 dev->number,eni_dev->irq);
1805 return -EAGAIN; 1804 error = -EAGAIN;
1805 goto out;
1806 } 1806 }
1807 /* @@@ should release IRQ on error */
1808 pci_set_master(eni_dev->pci_dev); 1807 pci_set_master(eni_dev->pci_dev);
1809 if ((error = pci_write_config_word(eni_dev->pci_dev,PCI_COMMAND, 1808 if ((error = pci_write_config_word(eni_dev->pci_dev,PCI_COMMAND,
1810 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | 1809 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
1811 (eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) { 1810 (eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) {
1812 printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory+" 1811 printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory+"
1813 "master (0x%02x)\n",dev->number,error); 1812 "master (0x%02x)\n",dev->number,error);
1814 return error; 1813 goto free_irq;
1815 } 1814 }
1816 if ((error = pci_write_config_byte(eni_dev->pci_dev,PCI_TONGA_CTRL, 1815 if ((error = pci_write_config_byte(eni_dev->pci_dev,PCI_TONGA_CTRL,
1817 END_SWAP_DMA))) { 1816 END_SWAP_DMA))) {
1818 printk(KERN_ERR DEV_LABEL "(itf %d): can't set endian swap " 1817 printk(KERN_ERR DEV_LABEL "(itf %d): can't set endian swap "
1819 "(0x%02x)\n",dev->number,error); 1818 "(0x%02x)\n",dev->number,error);
1820 return error; 1819 goto free_irq;
1821 } 1820 }
1822 /* determine addresses of internal tables */ 1821 /* determine addresses of internal tables */
1823 eni_dev->vci = eni_dev->ram; 1822 eni_dev->vci = eni_dev->ram;
@@ -1839,7 +1838,8 @@ static int __devinit eni_start(struct atm_dev *dev)
1839 if (!eni_dev->free_list) { 1838 if (!eni_dev->free_list) {
1840 printk(KERN_ERR DEV_LABEL "(itf %d): couldn't get free page\n", 1839 printk(KERN_ERR DEV_LABEL "(itf %d): couldn't get free page\n",
1841 dev->number); 1840 dev->number);
1842 return -ENOMEM; 1841 error = -ENOMEM;
1842 goto free_irq;
1843 } 1843 }
1844 eni_dev->free_len = 0; 1844 eni_dev->free_len = 0;
1845 eni_put_free(eni_dev,buf,buffer_mem); 1845 eni_put_free(eni_dev,buf,buffer_mem);
@@ -1855,17 +1855,26 @@ static int __devinit eni_start(struct atm_dev *dev)
1855 */ 1855 */
1856 eni_out(0xffffffff,MID_IE); 1856 eni_out(0xffffffff,MID_IE);
1857 error = start_tx(dev); 1857 error = start_tx(dev);
1858 if (error) return error; 1858 if (error) goto free_list;
1859 error = start_rx(dev); 1859 error = start_rx(dev);
1860 if (error) return error; 1860 if (error) goto free_list;
1861 error = dev->phy->start(dev); 1861 error = dev->phy->start(dev);
1862 if (error) return error; 1862 if (error) goto free_list;
1863 eni_out(eni_in(MID_MC_S) | (1 << MID_INT_SEL_SHIFT) | 1863 eni_out(eni_in(MID_MC_S) | (1 << MID_INT_SEL_SHIFT) |
1864 MID_TX_LOCK_MODE | MID_DMA_ENABLE | MID_TX_ENABLE | MID_RX_ENABLE, 1864 MID_TX_LOCK_MODE | MID_DMA_ENABLE | MID_TX_ENABLE | MID_RX_ENABLE,
1865 MID_MC_S); 1865 MID_MC_S);
1866 /* Tonga uses SBus INTReq1 */ 1866 /* Tonga uses SBus INTReq1 */
1867 (void) eni_in(MID_ISA); /* clear Midway interrupts */ 1867 (void) eni_in(MID_ISA); /* clear Midway interrupts */
1868 return 0; 1868 return 0;
1869
1870free_list:
1871 kfree(eni_dev->free_list);
1872
1873free_irq:
1874 free_irq(eni_dev->irq, eni_dev);
1875
1876out:
1877 return error;
1869} 1878}
1870 1879
1871 1880