summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/early/ehci-dbgp.c17
-rw-r--r--drivers/usb/host/ehci-hcd.c4
-rw-r--r--drivers/usb/host/ehci-hub.c4
-rw-r--r--drivers/xen/Makefile2
-rw-r--r--drivers/xen/dbgp.c48
-rw-r--r--include/linux/usb/ehci_def.h29
-rw-r--r--include/xen/interface/physdev.h16
7 files changed, 105 insertions, 15 deletions
diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c
index 89dcf155d57e..e426ad626d74 100644
--- a/drivers/usb/early/ehci-dbgp.c
+++ b/drivers/usb/early/ehci-dbgp.c
@@ -491,7 +491,7 @@ static int ehci_wait_for_port(int port);
  * Return -ENODEV for any general failure
  * Return -EIO if wait for port fails
  */
-int dbgp_external_startup(void)
+static int _dbgp_external_startup(void)
 {
 	int devnum;
 	struct usb_debug_descriptor dbgp_desc;
@@ -613,6 +613,11 @@ err:
 		goto try_again;
 	return -ENODEV;
 }
+
+int dbgp_external_startup(struct usb_hcd *hcd)
+{
+	return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup();
+}
 EXPORT_SYMBOL_GPL(dbgp_external_startup);
 
 static int ehci_reset_port(int port)
@@ -804,7 +809,7 @@ try_next_port:
 		dbgp_ehci_status("ehci skip - already configured");
 	}
 
-	ret = dbgp_external_startup();
+	ret = _dbgp_external_startup();
 	if (ret == -EIO)
 		goto next_debug_port;
 
@@ -934,7 +939,7 @@ static void early_dbgp_write(struct console *con, const char *str, u32 n)
 		ctrl = readl(&ehci_debug->control);
 		if (!(ctrl & DBGP_ENABLED)) {
 			dbgp_not_safe = 1;
-			dbgp_external_startup();
+			_dbgp_external_startup();
 		} else {
 			cmd |= CMD_RUN;
 			writel(cmd, &ehci_regs->command);
@@ -974,10 +979,14 @@ struct console early_dbgp_console = {
 	.index =	-1,
 };
 
-int dbgp_reset_prep(void)
+int dbgp_reset_prep(struct usb_hcd *hcd)
 {
+	int ret = xen_dbgp_reset_prep(hcd);
 	u32 ctrl;
 
+	if (ret)
+		return ret;
+
 	dbgp_not_safe = 1;
 	if (!ehci_debug)
 		return 0;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index b05c6865b610..6bf6c42481e8 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -228,7 +228,7 @@ static int ehci_reset (struct ehci_hcd *ehci)
 
 	/* If the EHCI debug controller is active, special care must be
 	 * taken before and after a host controller reset */
-	if (ehci->debug && !dbgp_reset_prep())
+	if (ehci->debug && !dbgp_reset_prep(ehci_to_hcd(ehci)))
 		ehci->debug = NULL;
 
 	command |= CMD_RESET;
@@ -251,7 +251,7 @@ static int ehci_reset (struct ehci_hcd *ehci)
 		tdi_reset (ehci);
 
 	if (ehci->debug)
-		dbgp_external_startup();
+		dbgp_external_startup(ehci_to_hcd(ehci));
 
 	ehci->port_c_suspend = ehci->suspended_ports =
 			ehci->resuming_ports = 0;
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index c7880223738a..914ce9370e70 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -353,10 +353,10 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
 		goto shutdown;
 
 	if (unlikely(ehci->debug)) {
-		if (!dbgp_reset_prep())
+		if (!dbgp_reset_prep(hcd))
 			ehci->debug = NULL;
 		else
-			dbgp_external_startup();
+			dbgp_external_startup(hcd);
 	}
 
 	/* Ideally and we've got a real resume here, and no port's power
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index d80bea5535a2..a4a3cab2f459 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -18,7 +18,7 @@ obj-$(CONFIG_XEN_PVHVM)			+= platform-pci.o
 obj-$(CONFIG_XEN_TMEM)			+= tmem.o
 obj-$(CONFIG_SWIOTLB_XEN)		+= swiotlb-xen.o
 obj-$(CONFIG_XEN_DOM0)			+= pcpu.o
-obj-$(CONFIG_XEN_DOM0)			+= pci.o acpi.o
+obj-$(CONFIG_XEN_DOM0)			+= pci.o dbgp.o acpi.o
 obj-$(CONFIG_XEN_MCE_LOG)		+= mcelog.o
 obj-$(CONFIG_XEN_PCIDEV_BACKEND)	+= xen-pciback/
 obj-$(CONFIG_XEN_PRIVCMD)		+= xen-privcmd.o
diff --git a/drivers/xen/dbgp.c b/drivers/xen/dbgp.c
new file mode 100644
index 000000000000..42569c77ccc8
--- /dev/null
+++ b/drivers/xen/dbgp.c
@@ -0,0 +1,48 @@
+#include <linux/pci.h>
+#include <linux/usb.h>
+#include <linux/usb/ehci_def.h>
+#include <linux/usb/hcd.h>
+#include <asm/xen/hypercall.h>
+#include <xen/interface/physdev.h>
+#include <xen/xen.h>
+
+static int xen_dbgp_op(struct usb_hcd *hcd, int op)
+{
+	const struct device *ctrlr = hcd_to_bus(hcd)->controller;
+	struct physdev_dbgp_op dbgp;
+
+	if (!xen_initial_domain())
+		return 0;
+
+	dbgp.op = op;
+
+#ifdef CONFIG_PCI
+	if (ctrlr->bus == &pci_bus_type) {
+		const struct pci_dev *pdev = to_pci_dev(ctrlr);
+
+		dbgp.u.pci.seg = pci_domain_nr(pdev->bus);
+		dbgp.u.pci.bus = pdev->bus->number;
+		dbgp.u.pci.devfn = pdev->devfn;
+		dbgp.bus = PHYSDEVOP_DBGP_BUS_PCI;
+	} else
+#endif
+		dbgp.bus = PHYSDEVOP_DBGP_BUS_UNKNOWN;
+
+	return HYPERVISOR_physdev_op(PHYSDEVOP_dbgp_op, &dbgp);
+}
+
+int xen_dbgp_reset_prep(struct usb_hcd *hcd)
+{
+	return xen_dbgp_op(hcd, PHYSDEVOP_DBGP_RESET_PREPARE);
+}
+
+int xen_dbgp_external_startup(struct usb_hcd *hcd)
+{
+	return xen_dbgp_op(hcd, PHYSDEVOP_DBGP_RESET_DONE);
+}
+
+#ifndef CONFIG_EARLY_PRINTK_DBGP
+#include <linux/export.h>
+EXPORT_SYMBOL_GPL(xen_dbgp_reset_prep);
+EXPORT_SYMBOL_GPL(xen_dbgp_external_startup);
+#endif
diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h
index de4b9ed5d5dd..9a446302b658 100644
--- a/include/linux/usb/ehci_def.h
+++ b/include/linux/usb/ehci_def.h
@@ -221,18 +221,35 @@ extern int __init early_dbgp_init(char *s);
 extern struct console early_dbgp_console;
 #endif /* CONFIG_EARLY_PRINTK_DBGP */
 
+struct usb_hcd;
+
+#ifdef CONFIG_XEN_DOM0
+extern int xen_dbgp_reset_prep(struct usb_hcd *);
+extern int xen_dbgp_external_startup(struct usb_hcd *);
+#else
+static inline int xen_dbgp_reset_prep(struct usb_hcd *hcd)
+{
+	return 1; /* Shouldn't this be 0? */
+}
+
+static inline int xen_dbgp_external_startup(struct usb_hcd *hcd)
+{
+	return -1;
+}
+#endif
+
 #ifdef CONFIG_EARLY_PRINTK_DBGP
 /* Call backs from ehci host driver to ehci debug driver */
-extern int dbgp_external_startup(void);
-extern int dbgp_reset_prep(void);
+extern int dbgp_external_startup(struct usb_hcd *);
+extern int dbgp_reset_prep(struct usb_hcd *hcd);
 #else
-static inline int dbgp_reset_prep(void)
+static inline int dbgp_reset_prep(struct usb_hcd *hcd)
 {
-	return 1;
+	return xen_dbgp_reset_prep(hcd);
 }
-static inline int dbgp_external_startup(void)
+static inline int dbgp_external_startup(struct usb_hcd *hcd)
 {
-	return -1;
+	return xen_dbgp_external_startup(hcd);
 }
 #endif
 
diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h
index 9ce788d8cf49..bfa1d50fe15b 100644
--- a/include/xen/interface/physdev.h
+++ b/include/xen/interface/physdev.h
@@ -258,6 +258,22 @@ struct physdev_pci_device {
     uint8_t devfn;
 };
 
+#define PHYSDEVOP_DBGP_RESET_PREPARE    1
+#define PHYSDEVOP_DBGP_RESET_DONE       2
+
+#define PHYSDEVOP_DBGP_BUS_UNKNOWN      0
+#define PHYSDEVOP_DBGP_BUS_PCI          1
+
+#define PHYSDEVOP_dbgp_op               29
+struct physdev_dbgp_op {
+    /* IN */
+    uint8_t op;
+    uint8_t bus;
+    union {
+        struct physdev_pci_device pci;
+    } u;
+};
+
 /*
  * Notify that some PIRQ-bound event channels have been unmasked.
  * ** This command is obsolete since interface version 0x00030202 and is **