aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-pci.c
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2010-10-26 14:03:44 -0400
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2011-03-13 21:07:13 -0400
commitb02d0ed677acb3465e7600366f2353413bf24074 (patch)
tree8efdbb5ea07a387a687aa24f0bcda8ba3a454d76 /drivers/usb/host/xhci-pci.c
parent214f76f7d9198ddd090bd927a4bcd49391bfcd36 (diff)
xhci: Change hcd_priv into a pointer.
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). Deallocate the xhci_hcd at PCI remove time, so the hcd_priv will be deallocated after the usb_hcd is deallocated. We do this by registering a different PCI remove function that calls the usb_hcd_pci_remove() function, and then frees the xhci_hcd. usb_hcd_pci_remove() calls kput() on the usb_hcd structure, which will deallocate the memory that contains the hcd_priv pointer, but not the memory it points to. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Diffstat (limited to 'drivers/usb/host/xhci-pci.c')
-rw-r--r--drivers/usb/host/xhci-pci.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index bb668a894ab9..009082829364 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)
57 57
58 hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 2; 58 hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 2;
59 59
60 xhci = kzalloc(sizeof(struct xhci_hcd), GFP_KERNEL);
61 if (!xhci)
62 return -ENOMEM;
63 *((struct xhci_hcd **) hcd->hcd_priv) = xhci;
64 xhci->main_hcd = hcd;
65
60 xhci->cap_regs = hcd->regs; 66 xhci->cap_regs = hcd->regs;
61 xhci->op_regs = hcd->regs + 67 xhci->op_regs = hcd->regs +
62 HC_LENGTH(xhci_readl(xhci, &xhci->cap_regs->hc_capbase)); 68 HC_LENGTH(xhci_readl(xhci, &xhci->cap_regs->hc_capbase));
@@ -85,13 +91,13 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
85 /* Make sure the HC is halted. */ 91 /* Make sure the HC is halted. */
86 retval = xhci_halt(xhci); 92 retval = xhci_halt(xhci);
87 if (retval) 93 if (retval)
88 return retval; 94 goto error;
89 95
90 xhci_dbg(xhci, "Resetting HCD\n"); 96 xhci_dbg(xhci, "Resetting HCD\n");
91 /* Reset the internal HC memory state and registers. */ 97 /* Reset the internal HC memory state and registers. */
92 retval = xhci_reset(xhci); 98 retval = xhci_reset(xhci);
93 if (retval) 99 if (retval)
94 return retval; 100 goto error;
95 xhci_dbg(xhci, "Reset complete\n"); 101 xhci_dbg(xhci, "Reset complete\n");
96 102
97 temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params); 103 temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
@@ -106,14 +112,29 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
106 /* Initialize HCD and host controller data structures. */ 112 /* Initialize HCD and host controller data structures. */
107 retval = xhci_init(hcd); 113 retval = xhci_init(hcd);
108 if (retval) 114 if (retval)
109 return retval; 115 goto error;
110 xhci_dbg(xhci, "Called HCD init\n"); 116 xhci_dbg(xhci, "Called HCD init\n");
111 117
112 pci_read_config_byte(pdev, XHCI_SBRN_OFFSET, &xhci->sbrn); 118 pci_read_config_byte(pdev, XHCI_SBRN_OFFSET, &xhci->sbrn);
113 xhci_dbg(xhci, "Got SBRN %u\n", (unsigned int) xhci->sbrn); 119 xhci_dbg(xhci, "Got SBRN %u\n", (unsigned int) xhci->sbrn);
114 120
115 /* Find any debug ports */ 121 /* Find any debug ports */
116 return xhci_pci_reinit(xhci, pdev); 122 retval = xhci_pci_reinit(xhci, pdev);
123 if (!retval)
124 return retval;
125
126error:
127 kfree(xhci);
128 return retval;
129}
130
131static void xhci_pci_remove(struct pci_dev *dev)
132{
133 struct xhci_hcd *xhci;
134
135 xhci = hcd_to_xhci(pci_get_drvdata(dev));
136 usb_hcd_pci_remove(dev);
137 kfree(xhci);
117} 138}
118 139
119#ifdef CONFIG_PM 140#ifdef CONFIG_PM
@@ -143,7 +164,7 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
143static const struct hc_driver xhci_pci_hc_driver = { 164static const struct hc_driver xhci_pci_hc_driver = {
144 .description = hcd_name, 165 .description = hcd_name,
145 .product_desc = "xHCI Host Controller", 166 .product_desc = "xHCI Host Controller",
146 .hcd_priv_size = sizeof(struct xhci_hcd), 167 .hcd_priv_size = sizeof(struct xhci_hcd *),
147 168
148 /* 169 /*
149 * generic hardware linkage 170 * generic hardware linkage
@@ -211,7 +232,7 @@ static struct pci_driver xhci_pci_driver = {
211 .id_table = pci_ids, 232 .id_table = pci_ids,
212 233
213 .probe = usb_hcd_pci_probe, 234 .probe = usb_hcd_pci_probe,
214 .remove = usb_hcd_pci_remove, 235 .remove = xhci_pci_remove,
215 /* suspend and resume implemented later */ 236 /* suspend and resume implemented later */
216 237
217 .shutdown = usb_hcd_pci_shutdown, 238 .shutdown = usb_hcd_pci_shutdown,