From mboxrd@z Thu Jan 1 00:00:00 1970 From: Yosuke Iwamatsu Subject: [PATCH] pcifront/pciback: Fix Handling of Device Disconnect Date: Wed, 16 Jul 2008 19:46:44 +0900 Message-ID: <487DD194.3080200@ab.jp.nec.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------000109090403020303080409" Return-path: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: xen-devel@lists.xensource.com List-Id: xen-devel@lists.xenproject.org This is a multi-part message in MIME format. --------------000109090403020303080409 Content-Type: text/plain; charset=ISO-2022-JP Content-Transfer-Encoding: 7bit When destroying pcifront/pciback, the following message appears in the guest linux kernel log. WARNING: g.e. still in use! WARNING: leaking g.e. and page still in use! This is caused by the wrong disconnect procedure that pcifront terminates the gnttab foreign access before pciback unmaps the ring. This patch corrects the handling of pcifront/pciback destruction sequence. Firstly pcifront cleans up root buses to ensure no more pci_op is issued, then pciback unmaps the shared ring and finally devices are discarded. Signed-off-by: Yosuke Iwamatsu Regards, ----------------------- Yosuke Iwamatsu NEC Corporation --------------000109090403020303080409 Content-Type: all/allfiles; name="pcifront_back_disconnect.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="pcifront_back_disconnect.patch" pcifront/back: Fix handling of device disconnect. Signed-off-by: Yosuke Iwamatsu diff -r a682229d0eac drivers/xen/pciback/xenbus.c --- a/drivers/xen/pciback/xenbus.c Tue Jul 15 16:39:39 2008 +0100 +++ b/drivers/xen/pciback/xenbus.c Wed Jul 16 11:44:29 2008 +0900 @@ -42,22 +42,35 @@ static struct pciback_device *alloc_pdev return pdev; } -static void free_pdev(struct pciback_device *pdev) -{ - if (pdev->be_watching) - unregister_xenbus_watch(&pdev->be_watch); +static void pciback_disconnect(struct pciback_device *pdev) +{ + spin_lock(&pdev->dev_lock); /* Ensure the guest can't trigger our handler before removing devices */ - if (pdev->evtchn_irq != INVALID_EVTCHN_IRQ) + if (pdev->evtchn_irq != INVALID_EVTCHN_IRQ) { unbind_from_irqhandler(pdev->evtchn_irq, pdev); + pdev->evtchn_irq = INVALID_EVTCHN_IRQ; + } /* If the driver domain started an op, make sure we complete it or * delete it before releasing the shared memory */ cancel_delayed_work(&pdev->op_work); flush_scheduled_work(); - if (pdev->sh_info) + if (pdev->sh_info != NULL) { xenbus_unmap_ring_vfree(pdev->xdev, pdev->sh_area); + pdev->sh_info = NULL; + } + + spin_unlock(&pdev->dev_lock); +} + +static void free_pdev(struct pciback_device *pdev) +{ + if (pdev->be_watching) + unregister_xenbus_watch(&pdev->be_watch); + + pciback_disconnect(pdev); pciback_release_devices(pdev); @@ -471,16 +484,6 @@ static void pciback_frontend_changed(str pciback_attach(pdev); break; - case XenbusStateClosing: - xenbus_switch_state(xdev, XenbusStateClosed); - break; - - case XenbusStateUnknown: - case XenbusStateClosed: - dev_dbg(&xdev->dev, "frontend is gone! unregister device\n"); - device_unregister(&xdev->dev); - break; - case XenbusStateReconfiguring: pciback_reconfigure(pdev); break; @@ -490,6 +493,22 @@ static void pciback_frontend_changed(str * Then switch to connected state. */ xenbus_switch_state(xdev, XenbusStateConnected); + break; + + case XenbusStateClosing: + pciback_disconnect(pdev); + xenbus_switch_state(xdev, XenbusStateClosing); + break; + + case XenbusStateClosed: + pciback_disconnect(pdev); + xenbus_switch_state(xdev, XenbusStateClosed); + if (xenbus_dev_is_online(xdev)) + break; + /* fall through if not online */ + case XenbusStateUnknown: + dev_dbg(&xdev->dev, "frontend is gone! unregister device\n"); + device_unregister(&xdev->dev); break; default: diff -r a682229d0eac drivers/xen/pcifront/xenbus.c --- a/drivers/xen/pcifront/xenbus.c Tue Jul 15 16:39:39 2008 +0100 +++ b/drivers/xen/pcifront/xenbus.c Wed Jul 16 11:44:29 2008 +0900 @@ -207,12 +207,17 @@ static int pcifront_try_disconnect(struc prev_state = xenbus_read_driver_state(pdev->xdev->nodename); - if (prev_state < XenbusStateClosing) - err = xenbus_switch_state(pdev->xdev, XenbusStateClosing); - - if (!err && prev_state == XenbusStateConnected) + if (prev_state >= XenbusStateClosing) + goto out; + + if(prev_state == XenbusStateConnected) { + pcifront_free_roots(pdev); pcifront_disconnect(pdev); - + } + + err = xenbus_switch_state(pdev->xdev, XenbusStateClosed); + + out: spin_unlock(&pdev->dev_lock); return err; @@ -370,32 +375,28 @@ static void __init_refok pcifront_backen struct pcifront_device *pdev = xdev->dev.driver_data; switch (be_state) { + case XenbusStateUnknown: + case XenbusStateInitialising: + case XenbusStateInitWait: + case XenbusStateInitialised: + case XenbusStateClosed: + break; + + case XenbusStateConnected: + pcifront_try_connect(pdev); + break; + case XenbusStateClosing: dev_warn(&xdev->dev, "backend going away!\n"); pcifront_try_disconnect(pdev); break; - case XenbusStateUnknown: - case XenbusStateClosed: - dev_warn(&xdev->dev, "backend went away!\n"); - pcifront_try_disconnect(pdev); - - device_unregister(&pdev->xdev->dev); - break; - - case XenbusStateConnected: - pcifront_try_connect(pdev); - break; - case XenbusStateReconfiguring: pcifront_detach_devices(pdev); break; case XenbusStateReconfigured: pcifront_attach_devices(pdev); - break; - - default: break; } } --------------000109090403020303080409 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel --------------000109090403020303080409--