[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>
This commit is contained in:
parent
d5ac99a648
commit
758d11bf09
|
@ -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)
|
||||||
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)
|
||||||
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)
|
||||||
*/
|
*/
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue