Make pci FE/BE resumable.
Signed-off-by Kevin Tian <kevin.tian@xxxxxxxxx>
diff -r eeff197b56e4 -r 7c8c027475f5
linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c Mon Feb 05
16:57:58 2007 +0800
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c Mon Feb 05
16:58:10 2007 +0800
@@ -114,8 +114,11 @@ static int pciback_attach(struct pciback
XenbusStateInitialised)
goto out;
- /* Wait for frontend to state that it has published the
configuration */
- if (xenbus_read_driver_state(pdev->xdev->otherend) !=
+ /* Wait for frontend to state that it has published the
+ * configuration. Frontend may be in connected state
+ * immediately after resume.
+ */
+ if (xenbus_read_driver_state(pdev->xdev->otherend) <
XenbusStateInitialised)
goto out;
diff -r eeff197b56e4 -r 7c8c027475f5
linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c Mon Feb
05 16:57:58 2007 +0800
+++ b/linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c Mon Feb
05 16:58:10 2007 +0800
@@ -21,48 +21,59 @@ static struct pcifront_device *alloc_pde
if (pdev == NULL)
goto out;
+ pdev->sh_info = NULL;
+ xdev->dev.driver_data = pdev;
+ pdev->xdev = xdev;
+
+ INIT_LIST_HEAD(&pdev->root_buses);
+
+ spin_lock_init(&pdev->dev_lock);
+ spin_lock_init(&pdev->sh_info_lock);
+
+ pdev->evtchn = INVALID_EVTCHN;
+ pdev->gnt_ref = INVALID_GRANT_REF;
+
+ dev_dbg(&xdev->dev, "Allocated pdev @ 0x%p pdev->sh_info @
0x%p\n",
+ pdev, pdev->sh_info);
+ out:
+ return pdev;
+}
+
+static void free_pdev(struct pcifront_device *pdev)
+{
+ dev_dbg(&pdev->xdev->dev, "freeing pdev @ 0x%p\n", pdev);
+
+ if (pdev->evtchn != INVALID_EVTCHN) {
+ xenbus_free_evtchn(pdev->xdev, pdev->evtchn);
+ pdev->evtchn = INVALID_EVTCHN;
+ }
+
+ if (pdev->gnt_ref != INVALID_GRANT_REF) {
+ gnttab_end_foreign_access(pdev->gnt_ref, 0,
+ (unsigned long)pdev->sh_info);
+ pdev->gnt_ref = INVALID_GRANT_REF;
+ pdev->sh_info = NULL;
+ }
+}
+
+static int setup_shring(struct pcifront_device *pdev)
+{
+ int err;
+
pdev->sh_info =
(struct xen_pci_sharedinfo *)__get_free_page(GFP_KERNEL);
- if (pdev->sh_info == NULL) {
- kfree(pdev);
- pdev = NULL;
- goto out;
- }
+ if (pdev->sh_info == NULL)
+ return -ENOMEM;
+
pdev->sh_info->flags = 0;
-
- xdev->dev.driver_data = pdev;
- pdev->xdev = xdev;
-
- INIT_LIST_HEAD(&pdev->root_buses);
-
- spin_lock_init(&pdev->dev_lock);
- spin_lock_init(&pdev->sh_info_lock);
-
- pdev->evtchn = INVALID_EVTCHN;
- pdev->gnt_ref = INVALID_GRANT_REF;
-
- dev_dbg(&xdev->dev, "Allocated pdev @ 0x%p pdev->sh_info @
0x%p\n",
- pdev, pdev->sh_info);
- out:
- return pdev;
-}
-
-static void free_pdev(struct pcifront_device *pdev)
-{
- dev_dbg(&pdev->xdev->dev, "freeing pdev @ 0x%p\n", pdev);
-
- pcifront_free_roots(pdev);
-
- if (pdev->evtchn != INVALID_EVTCHN)
- xenbus_free_evtchn(pdev->xdev, pdev->evtchn);
-
- if (pdev->gnt_ref != INVALID_GRANT_REF)
- gnttab_end_foreign_access(pdev->gnt_ref, 0,
- (unsigned long)pdev->sh_info);
-
- pdev->xdev->dev.driver_data = NULL;
-
- kfree(pdev);
+ err = xenbus_grant_ring(pdev->xdev, virt_to_mfn(pdev->sh_info));
+ if (err < 0)
+ goto out;
+ pdev->gnt_ref = err;
+
+ err = xenbus_alloc_evtchn(pdev->xdev, &pdev->evtchn);
+ out:
+ return err;
}
static int pcifront_publish_info(struct pcifront_device *pdev)
@@ -70,14 +81,8 @@ static int pcifront_publish_info(struct
int err = 0;
struct xenbus_transaction trans;
- err = xenbus_grant_ring(pdev->xdev, virt_to_mfn(pdev->sh_info));
+ err = setup_shring(pdev);
if (err < 0)
- goto out;
-
- pdev->gnt_ref = err;
-
- err = xenbus_alloc_evtchn(pdev->xdev, &pdev->evtchn);
- if (err)
goto out;
do_publish:
@@ -263,10 +268,38 @@ static int pcifront_xenbus_probe(struct
static int pcifront_xenbus_remove(struct xenbus_device *xdev)
{
- if (xdev->dev.driver_data)
- free_pdev(xdev->dev.driver_data);
-
+ struct pcifront_device *pdev = xdev->dev.driver_data;
+
+ if (!pdev)
+ return 0;
+
+ pcifront_free_roots(pdev);
+
+ free_pdev(pdev);
+
+ pdev->xdev->dev.driver_data = NULL;
+
+ kfree(pdev);
return 0;
+}
+
+static int pcifront_xenbus_resume(struct xenbus_device *dev)
+{
+ struct pcifront_device *pdev = dev->dev.driver_data;
+ int err;
+
+ dev_dbg(&pdev->xdev->dev, "pcifront_xenbus_resume: %s\n",
+ dev->nodename);
+
+ free_pdev(pdev);
+
+ err = pcifront_publish_info(pdev);
+ if (err)
+ goto out;
+
+ err = xenbus_switch_state(pdev->xdev, XenbusStateConnected);
+ out:
+ return err;
}
static struct xenbus_device_id xenpci_ids[] = {
@@ -280,6 +313,7 @@ static struct xenbus_driver xenbus_pcifr
.ids = xenpci_ids,
.probe = pcifront_xenbus_probe,
.remove = pcifront_xenbus_remove,
+ .resume = pcifront_xenbus_resume,
.otherend_changed = pcifront_backend_changed,
};
pcifront_resume.patch
Description: pcifront_resume.patch
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|