Skip to content

Commit a91740e

Browse files
jfischer-nokartben
authored andcommitted
drivers: uhc: implement the dequeue function
Implement the dequeue function and remove the timeout parameter as it is no longer necessary and can be handled in the upper layer. The dequeue function is required for the USBIP implementation. Signed-off-by: Johann Fischer <[email protected]>
1 parent 3fd7ea9 commit a91740e

File tree

7 files changed

+149
-49
lines changed

7 files changed

+149
-49
lines changed

drivers/usb/uhc/uhc_common.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ struct uhc_transfer *uhc_xfer_alloc(const struct device *dev,
9696
const uint8_t ep,
9797
const uint8_t attrib,
9898
const uint16_t mps,
99-
const uint16_t timeout,
10099
void *const udev,
101100
void *const cb)
102101
{
@@ -122,7 +121,6 @@ struct uhc_transfer *uhc_xfer_alloc(const struct device *dev,
122121
xfer->ep = ep;
123122
xfer->attrib = attrib;
124123
xfer->mps = mps;
125-
xfer->timeout = timeout;
126124
xfer->udev = udev;
127125
xfer->cb = cb;
128126

@@ -137,7 +135,6 @@ struct uhc_transfer *uhc_xfer_alloc_with_buf(const struct device *dev,
137135
const uint8_t ep,
138136
const uint8_t attrib,
139137
const uint16_t mps,
140-
const uint16_t timeout,
141138
void *const udev,
142139
void *const cb,
143140
size_t size)
@@ -150,7 +147,7 @@ struct uhc_transfer *uhc_xfer_alloc_with_buf(const struct device *dev,
150147
return NULL;
151148
}
152149

153-
xfer = uhc_xfer_alloc(dev, addr, ep, attrib, mps, timeout, udev, cb);
150+
xfer = uhc_xfer_alloc(dev, addr, ep, attrib, mps, udev, cb);
154151
if (xfer == NULL) {
155152
net_buf_unref(buf);
156153
return NULL;

drivers/usb/uhc/uhc_max3421e.c

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -377,12 +377,14 @@ static int max3421e_xfer_bulk(const struct device *dev,
377377
static int max3421e_schedule_xfer(const struct device *dev)
378378
{
379379
struct max3421e_data *priv = uhc_get_private(dev);
380-
const uint8_t hirq = priv->hirq;
381-
const uint8_t hrsl = priv->hrsl;
380+
uint8_t hrsl = priv->hrsl;
382381

383382
if (priv->last_xfer == NULL) {
384383
int ret;
385384

385+
/* Do not restart last transfer */
386+
hrsl = 0;
387+
386388
priv->last_xfer = uhc_xfer_get_next(dev);
387389
if (priv->last_xfer == NULL) {
388390
LOG_DBG("Nothing to transfer");
@@ -396,14 +398,6 @@ static int max3421e_schedule_xfer(const struct device *dev)
396398
}
397399
}
398400

399-
if (hirq & MAX3421E_FRAME) {
400-
if (priv->last_xfer->timeout) {
401-
priv->last_xfer->timeout--;
402-
} else {
403-
LOG_INF("Transfer timeout");
404-
}
405-
}
406-
407401
/*
408402
* TODO: currently we only support control transfers and
409403
* treat all others as bulk.
@@ -425,6 +419,23 @@ static void max3421e_xfer_drop_active(const struct device *dev, int err)
425419
}
426420
}
427421

422+
static void max3421e_xfer_cleanup_cancelled(const struct device *dev)
423+
{
424+
struct max3421e_data *priv = uhc_get_private(dev);
425+
struct uhc_data *data = dev->data;
426+
struct uhc_transfer *tmp;
427+
428+
if (priv->last_xfer != NULL && priv->last_xfer->err == -ECONNRESET) {
429+
max3421e_xfer_drop_active(dev, -ECONNRESET);
430+
}
431+
432+
SYS_DLIST_FOR_EACH_CONTAINER(&data->ctrl_xfers, tmp, node) {
433+
if (tmp->err == -ECONNRESET) {
434+
uhc_xfer_return(dev, tmp, -ECONNRESET);
435+
}
436+
}
437+
}
438+
428439
static int max3421e_hrslt_success(const struct device *dev)
429440
{
430441
struct max3421e_data *priv = uhc_get_private(dev);
@@ -527,17 +538,6 @@ static int max3421e_handle_hxfrdn(const struct device *dev)
527538

528539
switch (MAX3421E_HRSLT(hrsl)) {
529540
case MAX3421E_HR_NAK:
530-
/*
531-
* The transfer did not take place within
532-
* the specified number of frames.
533-
*
534-
* TODO: Transfer cancel request (xfer->cancel)
535-
* can be handled here as well.
536-
*/
537-
if (xfer->timeout == 0) {
538-
max3421e_xfer_drop_active(dev, -ETIMEDOUT);
539-
}
540-
541541
break;
542542
case MAX3421E_HR_STALL:
543543
max3421e_xfer_drop_active(dev, -EPIPE);
@@ -682,7 +682,9 @@ static void uhc_max3421e_thread(void *p1, void *p2, void *p3)
682682
/* Host Transfer Done Interrupt */
683683
if (priv->hirq & MAX3421E_HXFRDN) {
684684
err = max3421e_handle_hxfrdn(dev);
685-
schedule = true;
685+
if (unlikely(err)) {
686+
uhc_submit_event(dev, UHC_EVT_ERROR, err);
687+
}
686688
}
687689

688690
/* Frame Generator Interrupt */
@@ -704,6 +706,8 @@ static void uhc_max3421e_thread(void *p1, void *p2, void *p3)
704706
uhc_submit_event(dev, UHC_EVT_ERROR, err);
705707
}
706708

709+
max3421e_xfer_cleanup_cancelled(dev);
710+
707711
if (schedule) {
708712
err = max3421e_schedule_xfer(dev);
709713
if (unlikely(err)) {
@@ -797,7 +801,19 @@ static int max3421e_enqueue(const struct device *dev,
797801
static int max3421e_dequeue(const struct device *dev,
798802
struct uhc_transfer *const xfer)
799803
{
800-
/* TODO */
804+
struct uhc_data *data = dev->data;
805+
struct uhc_transfer *tmp;
806+
unsigned int key;
807+
808+
key = irq_lock();
809+
SYS_DLIST_FOR_EACH_CONTAINER(&data->ctrl_xfers, tmp, node) {
810+
if (xfer == tmp) {
811+
tmp->err = -ECONNRESET;
812+
}
813+
}
814+
815+
irq_unlock(key);
816+
801817
return 0;
802818
}
803819

drivers/usb/uhc/uhc_virtual.c

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,24 @@ static int vrt_handle_reply(const struct device *dev,
308308
return ret;
309309
}
310310

311+
static void vrt_xfer_cleanup_cancelled(const struct device *dev)
312+
{
313+
struct uhc_vrt_data *priv = uhc_get_private(dev);
314+
struct uhc_data *data = dev->data;
315+
struct uhc_transfer *tmp;
316+
317+
if (priv->last_xfer != NULL && priv->last_xfer->err == -ECONNRESET) {
318+
priv->busy = false;
319+
vrt_xfer_drop_active(dev, -ECONNRESET);
320+
}
321+
322+
SYS_DLIST_FOR_EACH_CONTAINER(&data->ctrl_xfers, tmp, node) {
323+
if (tmp->err == -ECONNRESET) {
324+
uhc_xfer_return(dev, tmp, -ECONNRESET);
325+
}
326+
}
327+
}
328+
311329
static void xfer_work_handler(struct k_work *work)
312330
{
313331
struct uhc_vrt_data *priv = CONTAINER_OF(work, struct uhc_vrt_data, work);
@@ -332,20 +350,13 @@ static void xfer_work_handler(struct k_work *work)
332350
schedule = true;
333351
break;
334352
case UHC_VRT_EVT_SOF:
335-
if (priv->last_xfer != NULL) {
336-
if (priv->last_xfer->timeout) {
337-
priv->last_xfer->timeout--;
338-
} else {
339-
vrt_xfer_drop_active(dev, -ETIMEDOUT);
340-
priv->busy = false;
341-
LOG_WRN("Transfer timeout");
342-
}
343-
}
344353
break;
345354
default:
346355
break;
347356
}
348357

358+
vrt_xfer_cleanup_cancelled(dev);
359+
349360
if (schedule && !priv->busy) {
350361
err = vrt_schedule_xfer(dev);
351362
if (unlikely(err)) {
@@ -458,7 +469,21 @@ static int uhc_vrt_enqueue(const struct device *dev,
458469
static int uhc_vrt_dequeue(const struct device *dev,
459470
struct uhc_transfer *const xfer)
460471
{
461-
/* TODO */
472+
struct uhc_data *data = dev->data;
473+
struct uhc_transfer *tmp;
474+
unsigned int key;
475+
476+
key = irq_lock();
477+
478+
SYS_DLIST_FOR_EACH_CONTAINER(&data->ctrl_xfers, tmp, node) {
479+
if (xfer == tmp) {
480+
tmp->err = -ECONNRESET;
481+
}
482+
}
483+
484+
irq_unlock(key);
485+
vrt_event_submit(dev, UHC_VRT_EVT_XFER, NULL);
486+
462487
return 0;
463488
}
464489

include/zephyr/drivers/usb/uhc.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ struct uhc_transfer {
6161
uint8_t attrib;
6262
/** Maximum packet size */
6363
uint16_t mps;
64-
/** Timeout in number of frames */
65-
uint16_t timeout;
6664
/** Flag marks request buffer is queued */
6765
unsigned int queued : 1;
6866
/** Control stage status, up to the driver to use it or not */
@@ -340,7 +338,6 @@ static inline int uhc_bus_resume(const struct device *dev)
340338
* @param[in] ep Endpoint address
341339
* @param[in] attrib Endpoint attributes
342340
* @param[in] mps Maximum packet size of the endpoint
343-
* @param[in] timeout Timeout in number of frames
344341
* @param[in] udev Opaque pointer to USB device
345342
* @param[in] cb Transfer completion callback
346343
*
@@ -351,7 +348,6 @@ struct uhc_transfer *uhc_xfer_alloc(const struct device *dev,
351348
const uint8_t ep,
352349
const uint8_t attrib,
353350
const uint16_t mps,
354-
const uint16_t timeout,
355351
void *const udev,
356352
void *const cb);
357353

@@ -365,7 +361,6 @@ struct uhc_transfer *uhc_xfer_alloc(const struct device *dev,
365361
* @param[in] ep Endpoint address
366362
* @param[in] attrib Endpoint attributes
367363
* @param[in] mps Maximum packet size of the endpoint
368-
* @param[in] timeout Timeout in number of frames
369364
* @param[in] udev Opaque pointer to USB device
370365
* @param[in] cb Transfer completion callback
371366
* @param[in] size Size of the buffer
@@ -377,7 +372,6 @@ struct uhc_transfer *uhc_xfer_alloc_with_buf(const struct device *dev,
377372
const uint8_t ep,
378373
const uint8_t attrib,
379374
const uint16_t mps,
380-
const uint16_t timeout,
381375
void *const udev,
382376
void *const cb,
383377
size_t size);

subsys/usb/host/usbh_ch9.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ K_SEM_DEFINE(ch9_req_sync, 0, 1);
2929
static int ch9_req_cb(struct usb_device *const udev, struct uhc_transfer *const xfer)
3030
{
3131
LOG_DBG("Request finished %p, err %d", xfer, xfer->err);
32+
if (xfer->err == -ECONNRESET) {
33+
LOG_INF("Transfer %p cancelled", (void *)xfer);
34+
usbh_xfer_free(udev, xfer);
35+
36+
return 0;
37+
}
38+
3239
k_sem_give(&ch9_req_sync);
3340

3441
return 0;
@@ -53,7 +60,7 @@ int usbh_req_setup(struct usb_device *const udev,
5360
uint8_t ep = usb_reqtype_is_to_device(&req) ? 0x00 : 0x80;
5461
int ret;
5562

56-
xfer = usbh_xfer_alloc(udev, ep, 0, 64, SETUP_REQ_TIMEOUT, ch9_req_cb);
63+
xfer = usbh_xfer_alloc(udev, ep, 0, 64, ch9_req_cb);
5764
if (!xfer) {
5865
return -ENOMEM;
5966
}
@@ -74,7 +81,17 @@ int usbh_req_setup(struct usb_device *const udev,
7481
goto buf_alloc_err;
7582
}
7683

77-
k_sem_take(&ch9_req_sync, K_MSEC(SETUP_REQ_TIMEOUT));
84+
if (k_sem_take(&ch9_req_sync, K_MSEC(SETUP_REQ_TIMEOUT)) != 0) {
85+
ret = usbh_xfer_dequeue(udev, xfer);
86+
if (ret != 0) {
87+
LOG_ERR("Failed to cancel transfer");
88+
return ret;
89+
}
90+
91+
LOG_ERR("Timeout");
92+
return -ETIMEDOUT;
93+
}
94+
7895
ret = xfer->err;
7996

8097
buf_alloc_err:

subsys/usb/host/usbh_device.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,11 @@ static inline struct uhc_transfer *usbh_xfer_alloc(struct usb_device *udev,
4343
const uint8_t ep,
4444
const uint8_t attrib,
4545
const uint16_t mps,
46-
const uint16_t timeout,
4746
usbh_udev_cb_t cb)
4847
{
4948
struct usbh_contex *const ctx = udev->ctx;
5049

51-
return uhc_xfer_alloc(ctx->dev, udev->addr, ep, attrib, mps, timeout, udev, cb);
50+
return uhc_xfer_alloc(ctx->dev, udev->addr, ep, attrib, mps, udev, cb);
5251
}
5352

5453
static inline int usbh_xfer_buf_add(const struct usb_device *udev,
@@ -92,4 +91,12 @@ static inline int usbh_xfer_enqueue(const struct usb_device *udev,
9291
return uhc_ep_enqueue(ctx->dev, xfer);
9392
}
9493

94+
static inline int usbh_xfer_dequeue(const struct usb_device *udev,
95+
struct uhc_transfer *const xfer)
96+
{
97+
struct usbh_contex *const ctx = udev->ctx;
98+
99+
return uhc_ep_dequeue(ctx->dev, xfer);
100+
}
101+
95102
#endif /* ZEPHYR_INCLUDE_USBH_DEVICE_H */

0 commit comments

Comments
 (0)