Subject: scx200_acb: Fix PCI device reference count The scx200_acb driver supports two kind of devices, PCI ones and ISA ones. Even ISA ones are detected using the presence of PCI devices, and we get a reference to these, but never actually put it back, so we have a leak. We could put the reference back as soon as we're done with the detection, but as we also need a valid device to call i2c_add_adapter(), it's convenient to keep the PCI device reference and use it as our base device. It's kind of a hack, but that'll do for now, until someone decides to rewrite the whole driver to fit better in the device driver model. Signed-off-by: Jean Delvare --- drivers/i2c/busses/scx200_acb.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) --- linux-2.6.21-rc2.orig/drivers/i2c/busses/scx200_acb.c 2007-03-07 09:39:08.000000000 +0100 +++ linux-2.6.21-rc2/drivers/i2c/busses/scx200_acb.c 2007-03-07 18:26:49.000000000 +0100 @@ -519,8 +519,8 @@ static __init int scx200_create_pci(cons return rc; } -static int __init scx200_create_isa(const char *text, unsigned long base, - int index) +static int __init scx200_create_isa(const char *text, struct pci_dev *pdev, + unsigned long base, int index) { struct scx200_acb_iface *iface; int rc; @@ -530,6 +530,9 @@ static int __init scx200_create_isa(cons if (iface == NULL) return -ENOMEM; + iface->pdev = pdev; + iface->bar = -1; /* Not actually a PCI device */ + if (request_region(base, 8, iface->adapter.name) == 0) { printk(KERN_ERR NAME ": can't allocate io 0x%lx-0x%lx\n", base, base + 8 - 1); @@ -544,6 +547,7 @@ static int __init scx200_create_isa(cons return 0; release_region(base, 8); + pci_dev_put(iface->pdev); errout_free: kfree(iface); return rc; @@ -604,8 +608,7 @@ static __init int scx200_scan_pci(void) continue; rc = scx200_create_isa(scx200_data[data].name, - base[i], - i); + pdev, base[i], i); } } @@ -640,13 +643,12 @@ static void __exit scx200_acb_cleanup(vo i2c_del_adapter(&iface->adapter); - if (iface->pdev) { + if (iface->bar >= 0) pci_release_region(iface->pdev, iface->bar); - pci_dev_put(iface->pdev); - } else release_region(iface->base, 8); + pci_dev_put(iface->pdev); kfree(iface); down(&scx200_acb_list_mutex); }