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));
        /* 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);
        /* 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;
+}
+
+static void xhci_pci_remove(struct pci_dev *dev)
+{
+       struct xhci_hcd *xhci;
+
+       xhci = hcd_to_xhci(pci_get_drvdata(dev));
+       usb_hcd_pci_remove(dev);
+       kfree(xhci);
 }
 
 #ifdef CONFIG_PM
 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
        .id_table =     pci_ids,
 
        .probe =        usb_hcd_pci_probe,
-       .remove =       usb_hcd_pci_remove,
+       .remove =       xhci_pci_remove,
        /* suspend and resume implemented later */
 
        .shutdown =     usb_hcd_pci_shutdown,
 
 
 /* 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;
 /* 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