# HG changeset patch
# User Keir Fraser <keir@xxxxxxx>
# Date 1286195460 -3600
# Node ID 5dd203fba38095fde17610623542af7c2b0ee326
# Parent 37ec32c7b0796687d445291e9d9f0aa265cfd6e1
linux/pcifront: fix freeing of device
unbind_from_irqhandler() takes irq, not evtchn, as its first argument.
Once at it, improve error handling.
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
Reported-by: Rafal Wojtczuk <rafal@xxxxxxxxxxxxxxxxxxxxxx>
---
drivers/xen/pcifront/pcifront.h | 1 +
drivers/xen/pcifront/xenbus.c | 21 ++++++++++++++++++---
2 files changed, 19 insertions(+), 3 deletions(-)
diff -r 37ec32c7b079 -r 5dd203fba380 drivers/xen/pcifront/pcifront.h
--- a/drivers/xen/pcifront/pcifront.h Mon Oct 04 13:30:33 2010 +0100
+++ b/drivers/xen/pcifront/pcifront.h Mon Oct 04 13:31:00 2010 +0100
@@ -30,6 +30,7 @@ struct pcifront_device {
int evtchn;
int gnt_ref;
+ int irq;
/* Lock this when doing any operations in sh_info */
spinlock_t sh_info_lock;
diff -r 37ec32c7b079 -r 5dd203fba380 drivers/xen/pcifront/xenbus.c
--- a/drivers/xen/pcifront/xenbus.c Mon Oct 04 13:30:33 2010 +0100
+++ b/drivers/xen/pcifront/xenbus.c Mon Oct 04 13:31:00 2010 +0100
@@ -48,6 +48,7 @@ static struct pcifront_device *alloc_pde
pdev->evtchn = INVALID_EVTCHN;
pdev->gnt_ref = INVALID_GRANT_REF;
+ pdev->irq = -1;
INIT_WORK(&pdev->op_work, pcifront_do_aer, pdev);
@@ -65,7 +66,9 @@ static void free_pdev(struct pcifront_de
/*For PCIE_AER error handling job*/
flush_scheduled_work();
- unbind_from_irqhandler(pdev->evtchn, pdev);
+
+ if (pdev->irq > 0)
+ unbind_from_irqhandler(pdev->irq, pdev);
if (pdev->evtchn != INVALID_EVTCHN)
xenbus_free_evtchn(pdev->xdev, pdev->evtchn);
@@ -73,6 +76,8 @@ static void free_pdev(struct pcifront_de
if (pdev->gnt_ref != INVALID_GRANT_REF)
gnttab_end_foreign_access(pdev->gnt_ref,
(unsigned long)pdev->sh_info);
+ else
+ free_page((unsigned long)pdev->sh_info);
pdev->xdev->dev.driver_data = NULL;
@@ -94,8 +99,16 @@ static int pcifront_publish_info(struct
if (err)
goto out;
- bind_caller_port_to_irqhandler(pdev->evtchn, pcifront_handler_aer,
- SA_SAMPLE_RANDOM, "pcifront", pdev);
+ err = bind_caller_port_to_irqhandler(pdev->evtchn,
+ pcifront_handler_aer,
+ SA_SAMPLE_RANDOM,
+ "pcifront", pdev);
+ if (err < 0) {
+ xenbus_dev_fatal(pdev->xdev, err,
+ "Failed to bind event channel");
+ goto out;
+ }
+ pdev->irq = err;
do_publish:
err = xenbus_transaction_start(&trans);
@@ -428,6 +441,8 @@ static int pcifront_xenbus_probe(struct
}
err = pcifront_publish_info(pdev);
+ if (err)
+ free_pdev(pdev);
out:
return err;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|