1 // SPDX-License-Identifier: GPL-2.0
2
3 /*
4 * xHCI host controller sideband support
5 *
6 * Copyright (c) 2023-2025, Intel Corporation.
7 *
8 * Author: Mathias Nyman
9 */
10
11 #include <linux/usb/xhci-sideband.h>
12 #include <linux/dma-direct.h>
13
14 #include "xhci.h"
15
16 /* sideband internal helpers */
17 static struct sg_table *
xhci_ring_to_sgtable(struct xhci_sideband * sb,struct xhci_ring * ring)18 xhci_ring_to_sgtable(struct xhci_sideband *sb, struct xhci_ring *ring)
19 {
20 struct xhci_segment *seg;
21 struct sg_table *sgt;
22 unsigned int n_pages;
23 struct page **pages;
24 struct device *dev;
25 size_t sz;
26 int i;
27
28 dev = xhci_to_hcd(sb->xhci)->self.sysdev;
29 sz = ring->num_segs * TRB_SEGMENT_SIZE;
30 n_pages = PAGE_ALIGN(sz) >> PAGE_SHIFT;
31 pages = kvmalloc_array(n_pages, sizeof(struct page *), GFP_KERNEL);
32 if (!pages)
33 return NULL;
34
35 sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
36 if (!sgt) {
37 kvfree(pages);
38 return NULL;
39 }
40
41 seg = ring->first_seg;
42 if (!seg)
43 goto err;
44 /*
45 * Rings can potentially have multiple segments, create an array that
46 * carries page references to allocated segments. Utilize the
47 * sg_alloc_table_from_pages() to create the sg table, and to ensure
48 * that page links are created.
49 */
50 for (i = 0; i < ring->num_segs; i++) {
51 dma_get_sgtable(dev, sgt, seg->trbs, seg->dma,
52 TRB_SEGMENT_SIZE);
53 pages[i] = sg_page(sgt->sgl);
54 sg_free_table(sgt);
55 seg = seg->next;
56 }
57
58 if (sg_alloc_table_from_pages(sgt, pages, n_pages, 0, sz, GFP_KERNEL))
59 goto err;
60
61 /*
62 * Save first segment dma address to sg dma_address field for the sideband
63 * client to have access to the IOVA of the ring.
64 */
65 sg_dma_address(sgt->sgl) = ring->first_seg->dma;
66
67 return sgt;
68
69 err:
70 kvfree(pages);
71 kfree(sgt);
72
73 return NULL;
74 }
75
76 static void
__xhci_sideband_remove_endpoint(struct xhci_sideband * sb,struct xhci_virt_ep * ep)77 __xhci_sideband_remove_endpoint(struct xhci_sideband *sb, struct xhci_virt_ep *ep)
78 {
79 /*
80 * Issue a stop endpoint command when an endpoint is removed.
81 * The stop ep cmd handler will handle the ring cleanup.
82 */
83 xhci_stop_endpoint_sync(sb->xhci, ep, 0, GFP_KERNEL);
84
85 ep->sideband = NULL;
86 sb->eps[ep->ep_index] = NULL;
87 }
88
89 /* sideband api functions */
90
91 /**
92 * xhci_sideband_notify_ep_ring_free - notify client of xfer ring free
93 * @sb: sideband instance for this usb device
94 * @ep_index: usb endpoint index
95 *
96 * Notifies the xHCI sideband client driver of a xHCI transfer ring free
97 * routine. This will allow for the client to ensure that all transfers
98 * are completed.
99 *
100 * The callback should be synchronous, as the ring free happens after.
101 */
xhci_sideband_notify_ep_ring_free(struct xhci_sideband * sb,unsigned int ep_index)102 void xhci_sideband_notify_ep_ring_free(struct xhci_sideband *sb,
103 unsigned int ep_index)
104 {
105 struct xhci_sideband_event evt;
106
107 evt.type = XHCI_SIDEBAND_XFER_RING_FREE;
108 evt.evt_data = &ep_index;
109
110 if (sb->notify_client)
111 sb->notify_client(sb->intf, &evt);
112 }
113 EXPORT_SYMBOL_GPL(xhci_sideband_notify_ep_ring_free);
114
115 /**
116 * xhci_sideband_add_endpoint - add endpoint to sideband access list
117 * @sb: sideband instance for this usb device
118 * @host_ep: usb host endpoint
119 *
120 * Adds an endpoint to the list of sideband accessed endpoints for this usb
121 * device.
122 * After an endpoint is added the sideband client can get the endpoint transfer
123 * ring buffer by calling xhci_sideband_endpoint_buffer()
124 *
125 * Return: 0 on success, negative error otherwise.
126 */
127 int
xhci_sideband_add_endpoint(struct xhci_sideband * sb,struct usb_host_endpoint * host_ep)128 xhci_sideband_add_endpoint(struct xhci_sideband *sb,
129 struct usb_host_endpoint *host_ep)
130 {
131 struct xhci_virt_ep *ep;
132 unsigned int ep_index;
133
134 mutex_lock(&sb->mutex);
135 ep_index = xhci_get_endpoint_index(&host_ep->desc);
136 ep = &sb->vdev->eps[ep_index];
137
138 if (ep->ep_state & EP_HAS_STREAMS) {
139 mutex_unlock(&sb->mutex);
140 return -EINVAL;
141 }
142
143 /*
144 * Note, we don't know the DMA mask of the audio DSP device, if its
145 * smaller than for xhci it won't be able to access the endpoint ring
146 * buffer. This could be solved by not allowing the audio class driver
147 * to add the endpoint the normal way, but instead offload it immediately,
148 * and let this function add the endpoint and allocate the ring buffer
149 * with the smallest common DMA mask
150 */
151 if (sb->eps[ep_index] || ep->sideband) {
152 mutex_unlock(&sb->mutex);
153 return -EBUSY;
154 }
155
156 ep->sideband = sb;
157 sb->eps[ep_index] = ep;
158 mutex_unlock(&sb->mutex);
159
160 return 0;
161 }
162 EXPORT_SYMBOL_GPL(xhci_sideband_add_endpoint);
163
164 /**
165 * xhci_sideband_remove_endpoint - remove endpoint from sideband access list
166 * @sb: sideband instance for this usb device
167 * @host_ep: usb host endpoint
168 *
169 * Removes an endpoint from the list of sideband accessed endpoints for this usb
170 * device.
171 * sideband client should no longer touch the endpoint transfer buffer after
172 * calling this.
173 *
174 * Return: 0 on success, negative error otherwise.
175 */
176 int
xhci_sideband_remove_endpoint(struct xhci_sideband * sb,struct usb_host_endpoint * host_ep)177 xhci_sideband_remove_endpoint(struct xhci_sideband *sb,
178 struct usb_host_endpoint *host_ep)
179 {
180 struct xhci_virt_ep *ep;
181 unsigned int ep_index;
182
183 mutex_lock(&sb->mutex);
184 ep_index = xhci_get_endpoint_index(&host_ep->desc);
185 ep = sb->eps[ep_index];
186
187 if (!ep || !ep->sideband || ep->sideband != sb) {
188 mutex_unlock(&sb->mutex);
189 return -ENODEV;
190 }
191
192 __xhci_sideband_remove_endpoint(sb, ep);
193 xhci_initialize_ring_info(ep->ring);
194 mutex_unlock(&sb->mutex);
195
196 return 0;
197 }
198 EXPORT_SYMBOL_GPL(xhci_sideband_remove_endpoint);
199
200 int
xhci_sideband_stop_endpoint(struct xhci_sideband * sb,struct usb_host_endpoint * host_ep)201 xhci_sideband_stop_endpoint(struct xhci_sideband *sb,
202 struct usb_host_endpoint *host_ep)
203 {
204 struct xhci_virt_ep *ep;
205 unsigned int ep_index;
206
207 ep_index = xhci_get_endpoint_index(&host_ep->desc);
208 ep = sb->eps[ep_index];
209
210 if (!ep || !ep->sideband || ep->sideband != sb)
211 return -EINVAL;
212
213 return xhci_stop_endpoint_sync(sb->xhci, ep, 0, GFP_KERNEL);
214 }
215 EXPORT_SYMBOL_GPL(xhci_sideband_stop_endpoint);
216
217 /**
218 * xhci_sideband_get_endpoint_buffer - gets the endpoint transfer buffer address
219 * @sb: sideband instance for this usb device
220 * @host_ep: usb host endpoint
221 *
222 * Returns the address of the endpoint buffer where xHC controller reads queued
223 * transfer TRBs from. This is the starting address of the ringbuffer where the
224 * sideband client should write TRBs to.
225 *
226 * Caller needs to free the returned sg_table
227 *
228 * Return: struct sg_table * if successful. NULL otherwise.
229 */
230 struct sg_table *
xhci_sideband_get_endpoint_buffer(struct xhci_sideband * sb,struct usb_host_endpoint * host_ep)231 xhci_sideband_get_endpoint_buffer(struct xhci_sideband *sb,
232 struct usb_host_endpoint *host_ep)
233 {
234 struct xhci_virt_ep *ep;
235 unsigned int ep_index;
236
237 ep_index = xhci_get_endpoint_index(&host_ep->desc);
238 ep = sb->eps[ep_index];
239
240 if (!ep || !ep->ring || !ep->sideband || ep->sideband != sb)
241 return NULL;
242
243 return xhci_ring_to_sgtable(sb, ep->ring);
244 }
245 EXPORT_SYMBOL_GPL(xhci_sideband_get_endpoint_buffer);
246
247 /**
248 * xhci_sideband_get_event_buffer - return the event buffer for this device
249 * @sb: sideband instance for this usb device
250 *
251 * If a secondary xhci interupter is set up for this usb device then this
252 * function returns the address of the event buffer where xHC writes
253 * the transfer completion events.
254 *
255 * Caller needs to free the returned sg_table
256 *
257 * Return: struct sg_table * if successful. NULL otherwise.
258 */
259 struct sg_table *
xhci_sideband_get_event_buffer(struct xhci_sideband * sb)260 xhci_sideband_get_event_buffer(struct xhci_sideband *sb)
261 {
262 if (!sb || !sb->ir)
263 return NULL;
264
265 return xhci_ring_to_sgtable(sb, sb->ir->event_ring);
266 }
267 EXPORT_SYMBOL_GPL(xhci_sideband_get_event_buffer);
268
269 /**
270 * xhci_sideband_create_interrupter - creates a new interrupter for this sideband
271 * @sb: sideband instance for this usb device
272 * @num_seg: number of event ring segments to allocate
273 * @ip_autoclear: IP autoclearing support such as MSI implemented
274 *
275 * Sets up a xhci interrupter that can be used for this sideband accessed usb
276 * device. Transfer events for this device can be routed to this interrupters
277 * event ring by setting the 'Interrupter Target' field correctly when queueing
278 * the transfer TRBs.
279 * Once this interrupter is created the interrupter target ID can be obtained
280 * by calling xhci_sideband_interrupter_id()
281 *
282 * Returns 0 on success, negative error otherwise
283 */
284 int
xhci_sideband_create_interrupter(struct xhci_sideband * sb,int num_seg,bool ip_autoclear,u32 imod_interval,int intr_num)285 xhci_sideband_create_interrupter(struct xhci_sideband *sb, int num_seg,
286 bool ip_autoclear, u32 imod_interval, int intr_num)
287 {
288 int ret = 0;
289
290 if (!sb || !sb->xhci)
291 return -ENODEV;
292
293 mutex_lock(&sb->mutex);
294 if (sb->ir) {
295 ret = -EBUSY;
296 goto out;
297 }
298
299 sb->ir = xhci_create_secondary_interrupter(xhci_to_hcd(sb->xhci),
300 num_seg, imod_interval,
301 intr_num);
302 if (!sb->ir) {
303 ret = -ENOMEM;
304 goto out;
305 }
306
307 sb->ir->ip_autoclear = ip_autoclear;
308
309 out:
310 mutex_unlock(&sb->mutex);
311
312 return ret;
313 }
314 EXPORT_SYMBOL_GPL(xhci_sideband_create_interrupter);
315
316 /**
317 * xhci_sideband_remove_interrupter - remove the interrupter from a sideband
318 * @sb: sideband instance for this usb device
319 *
320 * Removes a registered interrupt for a sideband. This would allow for other
321 * sideband users to utilize this interrupter.
322 */
323 void
xhci_sideband_remove_interrupter(struct xhci_sideband * sb)324 xhci_sideband_remove_interrupter(struct xhci_sideband *sb)
325 {
326 if (!sb || !sb->ir)
327 return;
328
329 mutex_lock(&sb->mutex);
330 xhci_remove_secondary_interrupter(xhci_to_hcd(sb->xhci), sb->ir);
331
332 sb->ir = NULL;
333 mutex_unlock(&sb->mutex);
334 }
335 EXPORT_SYMBOL_GPL(xhci_sideband_remove_interrupter);
336
337 /**
338 * xhci_sideband_interrupter_id - return the interrupter target id
339 * @sb: sideband instance for this usb device
340 *
341 * If a secondary xhci interrupter is set up for this usb device then this
342 * function returns the ID used by the interrupter. The sideband client
343 * needs to write this ID to the 'Interrupter Target' field of the transfer TRBs
344 * it queues on the endpoints transfer ring to ensure transfer completion event
345 * are written by xHC to the correct interrupter event ring.
346 *
347 * Returns interrupter id on success, negative error othgerwise
348 */
349 int
xhci_sideband_interrupter_id(struct xhci_sideband * sb)350 xhci_sideband_interrupter_id(struct xhci_sideband *sb)
351 {
352 if (!sb || !sb->ir)
353 return -ENODEV;
354
355 return sb->ir->intr_num;
356 }
357 EXPORT_SYMBOL_GPL(xhci_sideband_interrupter_id);
358
359 /**
360 * xhci_sideband_register - register a sideband for a usb device
361 * @intf: usb interface associated with the sideband device
362 *
363 * Allows for clients to utilize XHCI interrupters and fetch transfer and event
364 * ring parameters for executing data transfers.
365 *
366 * Return: pointer to a new xhci_sideband instance if successful. NULL otherwise.
367 */
368 struct xhci_sideband *
xhci_sideband_register(struct usb_interface * intf,enum xhci_sideband_type type,int (* notify_client)(struct usb_interface * intf,struct xhci_sideband_event * evt))369 xhci_sideband_register(struct usb_interface *intf, enum xhci_sideband_type type,
370 int (*notify_client)(struct usb_interface *intf,
371 struct xhci_sideband_event *evt))
372 {
373 struct usb_device *udev = interface_to_usbdev(intf);
374 struct usb_hcd *hcd = bus_to_hcd(udev->bus);
375 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
376 struct xhci_virt_device *vdev;
377 struct xhci_sideband *sb;
378
379 /*
380 * Make sure the usb device is connected to a xhci controller. Fail
381 * registration if the type is anything other than XHCI_SIDEBAND_VENDOR,
382 * as this is the only type that is currently supported by xhci-sideband.
383 */
384 if (!udev->slot_id || type != XHCI_SIDEBAND_VENDOR)
385 return NULL;
386
387 sb = kzalloc_node(sizeof(*sb), GFP_KERNEL, dev_to_node(hcd->self.sysdev));
388 if (!sb)
389 return NULL;
390
391 mutex_init(&sb->mutex);
392
393 /* check this device isn't already controlled via sideband */
394 spin_lock_irq(&xhci->lock);
395
396 vdev = xhci->devs[udev->slot_id];
397
398 if (!vdev || vdev->sideband) {
399 xhci_warn(xhci, "XHCI sideband for slot %d already in use\n",
400 udev->slot_id);
401 spin_unlock_irq(&xhci->lock);
402 kfree(sb);
403 return NULL;
404 }
405
406 sb->xhci = xhci;
407 sb->vdev = vdev;
408 sb->intf = intf;
409 sb->type = type;
410 sb->notify_client = notify_client;
411 vdev->sideband = sb;
412
413 spin_unlock_irq(&xhci->lock);
414
415 return sb;
416 }
417 EXPORT_SYMBOL_GPL(xhci_sideband_register);
418
419 /**
420 * xhci_sideband_unregister - unregister sideband access to a usb device
421 * @sb: sideband instance to be unregistered
422 *
423 * Unregisters sideband access to a usb device and frees the sideband
424 * instance.
425 * After this the endpoint and interrupter event buffers should no longer
426 * be accessed via sideband. The xhci driver can now take over handling
427 * the buffers.
428 */
429 void
xhci_sideband_unregister(struct xhci_sideband * sb)430 xhci_sideband_unregister(struct xhci_sideband *sb)
431 {
432 struct xhci_hcd *xhci;
433 int i;
434
435 if (!sb)
436 return;
437
438 xhci = sb->xhci;
439
440 mutex_lock(&sb->mutex);
441 for (i = 0; i < EP_CTX_PER_DEV; i++)
442 if (sb->eps[i])
443 __xhci_sideband_remove_endpoint(sb, sb->eps[i]);
444 mutex_unlock(&sb->mutex);
445
446 xhci_sideband_remove_interrupter(sb);
447
448 spin_lock_irq(&xhci->lock);
449 sb->xhci = NULL;
450 sb->vdev->sideband = NULL;
451 spin_unlock_irq(&xhci->lock);
452
453 kfree(sb);
454 }
455 EXPORT_SYMBOL_GPL(xhci_sideband_unregister);
456 MODULE_DESCRIPTION("xHCI sideband driver for secondary interrupter management");
457 MODULE_LICENSE("GPL");
458