Instead of allocating space for the whole xhci_hcd structure at the end of usb_hcd, make the USB core allocate enough space for a pointer to the xhci_hcd structure. This will make it easy to share the xhci_hcd structure across the two roothubs (the USB 3.0 usb_hcd and the USB 2.0 usb_hcd). This method of sharing the xhci_hcd pointer is better than modifying all xhci_functions to check whether the passed in usb_hcd contains the real xhci_hcd. Signed-off-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx> --- drivers/usb/host/xhci-pci.c | 22 +++++++++++++++++----- drivers/usb/host/xhci.c | 2 ++ drivers/usb/host/xhci.h | 5 +++-- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index bb668a8..b3ed661 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -57,6 +57,12 @@ static int xhci_pci_setup(struct usb_hcd *hcd) hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 2; + xhci = kzalloc(sizeof(struct xhci_hcd), GFP_KERNEL); + if (!xhci) + return -ENOMEM; + *((struct xhci_hcd **) hcd->hcd_priv) = xhci; + xhci->main_hcd = hcd; + xhci->cap_regs = hcd->regs; xhci->op_regs = hcd->regs + HC_LENGTH(xhci_readl(xhci, &xhci->cap_regs->hc_capbase)); @@ -85,13 +91,13 @@ static int xhci_pci_setup(struct usb_hcd *hcd) /* Make sure the HC is halted. */ retval = xhci_halt(xhci); if (retval) - return retval; + goto error; xhci_dbg(xhci, "Resetting HCD\n"); /* Reset the internal HC memory state and registers. */ retval = xhci_reset(xhci); if (retval) - return retval; + goto error; xhci_dbg(xhci, "Reset complete\n"); temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params); @@ -106,14 +112,20 @@ static int xhci_pci_setup(struct usb_hcd *hcd) /* Initialize HCD and host controller data structures. */ retval = xhci_init(hcd); if (retval) - return retval; + goto error; xhci_dbg(xhci, "Called HCD init\n"); pci_read_config_byte(pdev, XHCI_SBRN_OFFSET, &xhci->sbrn); xhci_dbg(xhci, "Got SBRN %u\n", (unsigned int) xhci->sbrn); /* Find any debug ports */ - return xhci_pci_reinit(xhci, pdev); + retval = xhci_pci_reinit(xhci, pdev); + if (!retval) + return retval; + +error: + kfree(xhci); + return retval; } #ifdef CONFIG_PM @@ -143,7 +155,7 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) static const struct hc_driver xhci_pci_hc_driver = { .description = hcd_name, .product_desc = "xHCI Host Controller", - .hcd_priv_size = sizeof(struct xhci_hcd), + .hcd_priv_size = sizeof(struct xhci_hcd *), /* * generic hardware linkage diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index ff65ea6..7577876 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -519,6 +519,8 @@ void xhci_stop(struct usb_hcd *hcd) xhci_mem_cleanup(xhci); xhci_dbg(xhci, "xhci_stop completed - status = %x\n", xhci_readl(xhci, &xhci->op_regs->status)); + kfree(xhci); + *((struct xhci_hcd **) hcd->hcd_priv) = NULL; } /* diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 3658564..29747a1 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1144,6 +1144,7 @@ struct s3_save { /* There is one ehci_hci structure per controller */ struct xhci_hcd { + struct usb_hcd *main_hcd; /* glue to PCI and HCD framework */ struct xhci_cap_regs __iomem *cap_regs; struct xhci_op_regs __iomem *op_regs; @@ -1238,12 +1239,12 @@ struct xhci_hcd { /* convert between an HCD pointer and the corresponding EHCI_HCD */ static inline struct xhci_hcd *hcd_to_xhci(struct usb_hcd *hcd) { - return (struct xhci_hcd *) (hcd->hcd_priv); + return *((struct xhci_hcd **) (hcd->hcd_priv)); } static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci) { - return container_of((void *) xhci, struct usb_hcd, hcd_priv); + return xhci->main_hcd; } #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING -- 1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html