Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions drivers/usb/udc/udc_ambiq.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,14 +258,10 @@ static int udc_ambiq_ep_dequeue(const struct device *dev, struct udc_ep_config *
{
unsigned int lock_key;
struct udc_ambiq_data *priv = udc_get_private(dev);
struct net_buf *buf;

lock_key = irq_lock();

buf = udc_buf_get_all(ep_cfg);
if (buf) {
udc_submit_ep_event(dev, buf, -ECONNABORTED);
}
udc_ep_cancel_queued(dev, ep_cfg);

udc_ep_set_busy(ep_cfg, false);
am_hal_usb_ep_state_reset(priv->usb_handle, ep_cfg->addr);
Expand Down
5 changes: 1 addition & 4 deletions drivers/usb/udc/udc_bflb_v1.c
Original file line number Diff line number Diff line change
Expand Up @@ -1336,7 +1336,7 @@
const mm_reg_t base = config->base;
uint8_t ep_idx = USB_EP_GET_IDX(ep_cfg->addr);
unsigned int lock_key;
struct net_buf *buf;

Check warning on line 1339 in drivers/usb/udc/udc_bflb_v1.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

unused variable 'buf'

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZ0Mf2ljxQIG-OxPpgcO&open=AZ0Mf2ljxQIG-OxPpgcO&pullRequest=100876

lock_key = irq_lock();

Expand All @@ -1350,10 +1350,7 @@
fifo_rx_clear(base, ep_idx);
}

buf = udc_buf_get_all(ep_cfg);
if (buf != NULL) {
udc_submit_ep_event(dev, buf, -ECONNABORTED);
}
udc_ep_cancel_queued(dev, ep_cfg);

/* Clear pending completion signal to prevent stale processing */
atomic_and(&priv->xfer_finished, ~BIT(ep_to_bnum(ep_cfg->addr)));
Expand Down
30 changes: 9 additions & 21 deletions drivers/usb/udc/udc_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,27 +81,6 @@
return k_fifo_get(&ep_cfg->fifo, K_NO_WAIT);
}

struct net_buf *udc_buf_get_all(struct udc_ep_config *const ep_cfg)
{
struct net_buf *buf;

buf = k_fifo_get(&ep_cfg->fifo, K_NO_WAIT);
if (!buf) {
return NULL;
}

LOG_DBG("ep 0x%02x dequeue %p", ep_cfg->addr, buf);
for (struct net_buf *n = buf; !k_fifo_is_empty(&ep_cfg->fifo); n = n->frags) {
n->frags = k_fifo_get(&ep_cfg->fifo, K_NO_WAIT);
LOG_DBG("|-> %p ", n->frags);
if (n->frags == NULL) {
break;
}
}

return buf;
}

Comment on lines -84 to -104
Copy link
Copy Markdown
Contributor

@jfischer-no jfischer-no Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC it should be reworked after 3d306c1, but yes maybe it is better to remove it.

It looks like there should be helpers for the two common patterns to flush the queue and cancel all transfers.

-	buf = udc_buf_get_all(cfg);
-	if (buf) {
+	while ((buf = udc_buf_get(cfg))) {
		udc_submit_ep_event(dev, buf, -ECONNABORTED);
	}
-	buf = udc_buf_get_all(cfg);
-	if (buf) {
+	while ((buf = udc_buf_get(cfg_out))) {
		net_buf_unref(buf);
	}

while ((buf = udc_buf_get(cfg_out))) is a bit problematic as it is foreseeable that people will get confused. Also, I do not want someone to get triggered, for IMO valid reasons here, by the rule "The result of an assignment operator should not be used". Please add helpers like:

/**
 * @brief Unref all queued UDC request
 *
 * Remove all the request from the endpoint FIFO and unref them.
 *
 * @param[in] cfg Pointer to endpoint configuration
 */
void udc_ep_unref_queued(struct udc_ep_config *const cfg);

void udc_ep_unref_queued(struct udc_ep_config *const cfg)
{
	struct net_buf *buf;

	buf = udc_buf_get(cfg)
	while (buf != NULL) {
		net_buf_unref(buf);
		buf = udc_buf_get(cfg)
	}
}
/**
 * @brief Cancel all queued UDC request
 *
 * Remove all the request from the endpoint FIFO and submit
 * them to higher level.
 *
 * @param[in] cfg Pointer to endpoint configuration
 */
void udc_ep_cancel_queued(struct udc_ep_config *const cfg);

void udc_ep_cancel_queued(struct udc_ep_config *const cfg)
{
	struct net_buf *buf;

	buf = udc_buf_get(cfg)
	while (buf != NULL) {
		udc_submit_ep_event(dev, buf, -ECONNABORTED);
		buf = udc_buf_get(cfg)
	}
}

Copy link
Copy Markdown
Contributor Author

@tmon-nordic tmon-nordic Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while ((buf = udc_buf_get(cfg_out))) is a bit problematic as it is foreseeable that people will get confused

The while (( is rather common in Zephyr codebase, for example:

while ((buf = k_fifo_get(&chan->iso->iso.txq, K_NO_WAIT))) {

while ((buf = k_fifo_get(&le_chan->tx_queue, K_NO_WAIT))) {
net_buf_unref(buf);
}
/* Remove buffers on the RX queue */
while ((buf = k_fifo_get(&le_chan->rx_queue, K_NO_WAIT))) {
net_buf_unref(buf);
}

while ((buf = k_fifo_get(&le_chan->tx_queue, K_NO_WAIT))) {

void udc_ep_unref_queued(struct udc_ep_config *const cfg)

This sounds like a bad advice to me. UDC should not be freeing queued buffers on its own, but rather it should be completing them. The only reason why the requests are currently freed by UDC driver is the broken design for how control transfers are handled. Hopefully this is resolved by #103493

void udc_ep_cancel_queued(struct udc_ep_config *const cfg)

I don't see the point. Maybe if the reason was provided as parameter (instead of hardcoding -ECONNABORTED) there would be some merit to it.

Would you revise your -1 given above argumentation?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The while (( is rather common in Zephyr codebase, for example:

It is up to Bluetooth to fix "The result of an assignment operator should not be used".

Would you revise your -1 given above argumentation?

No, after #103493 is merged, there is still at common pattern in your changes

-	buf = udc_buf_get_all(cfg);
-	if (buf) {
+	while ((buf = udc_buf_get(cfg))) {
		udc_submit_ep_event(dev, buf, -ECONNABORTED);
	}

and that should be moved to something like

/**
 * @brief Cancel all queued UDC request
 *
 * Remove all the request from the endpoint FIFO and submit
 * them to higher level.
 *
 * @param[in] cfg Pointer to endpoint configuration
 */
void udc_ep_cancel_queued(struct udc_ep_config *const cfg);

void udc_ep_cancel_queued(struct udc_ep_config *const cfg)
{
	struct net_buf *buf;

	buf = udc_buf_get(cfg)
	while (buf != NULL) {
		udc_submit_ep_event(dev, buf, -ECONNABORTED);
		buf = udc_buf_get(cfg)
	}
}

This sounds like a bad advice to me. UDC should not be freeing queued buffers on its own, but rather it should be completing them. The only reason why the requests are currently freed by UDC driver is the broken design for how control transfers are handled. Hopefully this is resolved by #103493

One still can find this pattern here:
3a619d9#diff-9636542b03fbd14ba20898a4f5562fc753535a02a6547cb9ac3e346b9a2b6e2dR2182-R2184
and here

for (buf = udc_buf_get(cfg); buf; buf = udc_buf_get(cfg)) {
net_buf_unref(buf);
}

for (buf = udc_buf_get(cfg); buf; buf = udc_buf_get(cfg)) {
net_buf_unref(buf);
}

Looks like it still makes sense to have helper function void udc_ep_unref_queued().

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is up to Bluetooth to fix "The result of an assignment operator should not be used".

Please open bug report so they are aware that this is an issue. That having said, I am fairly certain it is not issue and you are completely unreasonably forcing people to use different constructs.

I added void udc_ep_cancel_queued(const struct device *dev, struct udc_ep_config *const cfg);

Looks like it still makes sense to have helper function void udc_ep_unref_queued().

I prefer not to. These should eventually get removed, but it should be considered out-of-scope here.

struct net_buf *udc_buf_peek(struct udc_ep_config *const ep_cfg)
{
return k_fifo_peek_head(&ep_cfg->fifo);
Expand All @@ -127,6 +106,15 @@
bi->zlp = false;
}

void udc_ep_cancel_queued(const struct device *dev, struct udc_ep_config *const cfg)
{
struct net_buf *buf;

for (buf = udc_buf_get(cfg); buf; buf = udc_buf_get(cfg)) {

Check warning on line 113 in drivers/usb/udc/udc_common.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Declare the variable "buf" inside the loop.

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZ0LFM2Patn3-FHAE33F&open=AZ0LFM2Patn3-FHAE33F&pullRequest=100876
udc_submit_ep_event(dev, buf, -ECONNABORTED);
}
}

void udc_setup_received(const struct device *dev, const void *const setup)
{
struct udc_ep_config *cfg_out = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT);
Expand Down
26 changes: 13 additions & 13 deletions drivers/usb/udc/udc_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,19 +81,6 @@ void udc_ep_set_busy(struct udc_ep_config *const ep_cfg,
*/
struct net_buf *udc_buf_get(struct udc_ep_config *const ep_cfg);

/**
* @brief Get all UDC request from endpoint FIFO.
*
* Get all UDC request from endpoint FIFO as single-linked list.
* This function removes all request from endpoint FIFO and
* is typically used to dequeue endpoint FIFO.
*
* @param[in] ep_cfg Pointer to endpoint configuration
*
* @return pointer to UDC request or NULL on error.
*/
struct net_buf *udc_buf_get_all(struct udc_ep_config *const ep_cfg);

/**
* @brief Peek request at the head of endpoint FIFO.
*
Expand Down Expand Up @@ -238,6 +225,19 @@ bool udc_ep_buf_has_zlp(const struct net_buf *const buf);
*/
void udc_ep_buf_clear_zlp(const struct net_buf *const buf);

/**
* @brief Cancel all queued UDC requests
*
* UDC driver must ensure that driver will not access any of queued endpoint
* buffers before calling this funcition.
*
* Remove all queued requests from endpoint FIFO and submit them to USB stack.
*
* @param[in] dev Pointer to device struct of the driver instance
* @param[in] cfg Pointer to endpoint configuration
*/
void udc_ep_cancel_queued(const struct device *dev, struct udc_ep_config *const cfg);

/**
* @brief Submit control transfer data to USB stack
*
Expand Down
17 changes: 7 additions & 10 deletions drivers/usb/udc/udc_dwc2.c
Original file line number Diff line number Diff line change
Expand Up @@ -1676,18 +1676,15 @@
struct udc_ep_config *const cfg)
{
struct net_buf *buf;
bool invd;

udc_dwc2_ep_disable(dev, cfg, false, true);

buf = udc_buf_get_all(cfg);

if (dwc2_in_buffer_dma_mode(dev) && USB_EP_DIR_IS_OUT(cfg->addr)) {
for (struct net_buf *iter = buf; iter; iter = iter->frags) {
sys_cache_data_invd_range(iter->data, iter->len);
invd = dwc2_in_buffer_dma_mode(dev) && USB_EP_DIR_IS_OUT(cfg->addr);
for (buf = udc_buf_get(cfg); buf; buf = udc_buf_get(cfg)) {
if (invd) {
sys_cache_data_invd_range(buf->data, buf->len);
}
}

if (buf) {
udc_submit_ep_event(dev, buf, -ECONNABORTED);
}

Expand Down Expand Up @@ -2142,6 +2139,7 @@
static int udc_dwc2_disable(const struct device *dev)
{
const struct udc_dwc2_config *const config = dev->config;
struct udc_ep_config *cfg_out = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT);
struct udc_dwc2_data *const priv = udc_get_private(dev);
struct usb_dwc2_reg *const base = dwc2_get_base(dev);
mem_addr_t dctl_reg = (mem_addr_t)&base->dctl;
Expand Down Expand Up @@ -2181,8 +2179,7 @@
* triggering Soft Reset seems to be enough on shutdown clean up.
*/
dwc2_core_soft_reset(dev);
buf = udc_buf_get_all(udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT));
if (buf) {
for (buf = udc_buf_get(cfg_out); buf; buf = udc_buf_get(cfg_out)) {

Check warning on line 2182 in drivers/usb/udc/udc_dwc2.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Declare the variable "buf" inside the loop.

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZ0LFM-xatn3-FHAE33G&open=AZ0LFM-xatn3-FHAE33G&pullRequest=100876
net_buf_unref(buf);
}

Expand Down
6 changes: 1 addition & 5 deletions drivers/usb/udc/udc_it82xx2.c
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,6 @@ static int it82xx2_ep_dequeue(const struct device *dev, struct udc_ep_config *co
const struct usb_it82xx2_config *config = dev->config;
struct usb_it82xx2_regs *const usb_regs = config->base;
struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs;
struct net_buf *buf;
unsigned int lock_key;
uint8_t fifo_idx;

Expand All @@ -522,10 +521,7 @@ static int it82xx2_ep_dequeue(const struct device *dev, struct udc_ep_config *co
}
irq_unlock(lock_key);

buf = udc_buf_get_all(cfg);
if (buf) {
udc_submit_ep_event(dev, buf, -ECONNABORTED);
}
udc_ep_cancel_queued(dev, cfg);

udc_ep_set_busy(cfg, false);

Expand Down
6 changes: 1 addition & 5 deletions drivers/usb/udc/udc_kinetis.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,6 @@ static int usbfsotg_ep_dequeue(const struct device *dev,
{
struct usbfsotg_bd *bd;
unsigned int lock_key;
struct net_buf *buf;

bd = usbfsotg_get_ebd(dev, cfg, false);

Expand All @@ -573,10 +572,7 @@ static int usbfsotg_ep_dequeue(const struct device *dev,
irq_unlock(lock_key);

cfg->stat.halted = false;
buf = udc_buf_get_all(cfg);
if (buf) {
udc_submit_ep_event(dev, buf, -ECONNABORTED);
}
udc_ep_cancel_queued(dev, cfg);

udc_ep_set_busy(cfg, false);

Expand Down
8 changes: 1 addition & 7 deletions drivers/usb/udc/udc_max32.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,16 +340,10 @@ static int udc_max32_ep_enqueue(const struct device *dev, struct udc_ep_config *
static int udc_max32_ep_dequeue(const struct device *dev, struct udc_ep_config *const cfg)
{
unsigned int lock_key;
struct net_buf *buf;

lock_key = irq_lock();

buf = udc_buf_get_all(cfg);
if (buf) {
udc_submit_ep_event(dev, buf, -ECONNABORTED);
} else {
LOG_INF("ep 0x%02x queue is empty", cfg->addr);
}
udc_ep_cancel_queued(dev, cfg);

irq_unlock(lock_key);

Expand Down
7 changes: 1 addition & 6 deletions drivers/usb/udc/udc_mcux_ehci.c
Original file line number Diff line number Diff line change
Expand Up @@ -525,13 +525,8 @@ static int udc_mcux_ep_enqueue(const struct device *dev,
static int udc_mcux_ep_dequeue(const struct device *dev,
struct udc_ep_config *const cfg)
{
struct net_buf *buf;

cfg->stat.halted = false;
buf = udc_buf_get_all(cfg);
if (buf) {
udc_submit_ep_event(dev, buf, -ECONNABORTED);
}
udc_ep_cancel_queued(dev, cfg);

udc_mcux_lock(dev);
udc_ep_set_busy(cfg, false);
Expand Down
7 changes: 1 addition & 6 deletions drivers/usb/udc/udc_mcux_ip3511.c
Original file line number Diff line number Diff line change
Expand Up @@ -511,13 +511,8 @@ static int udc_mcux_ep_enqueue(const struct device *dev,
static int udc_mcux_ep_dequeue(const struct device *dev,
struct udc_ep_config *const cfg)
{
struct net_buf *buf;

cfg->stat.halted = false;
buf = udc_buf_get_all(cfg);
if (buf) {
udc_submit_ep_event(dev, buf, -ECONNABORTED);
}
udc_ep_cancel_queued(dev, cfg);

udc_mcux_lock(dev);
udc_ep_set_busy(cfg, false);
Expand Down
9 changes: 1 addition & 8 deletions drivers/usb/udc/udc_nrf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1503,16 +1503,9 @@ static int udc_nrf_ep_enqueue(const struct device *dev,
static int udc_nrf_ep_dequeue(const struct device *dev,
struct udc_ep_config *cfg)
{
struct net_buf *buf;

nrf_usbd_legacy_ep_abort(cfg->addr);

buf = udc_buf_get_all(cfg);
if (buf) {
udc_submit_ep_event(dev, buf, -ECONNABORTED);
} else {
LOG_INF("ep 0x%02x queue is empty", cfg->addr);
}
udc_ep_cancel_queued(dev, cfg);

udc_ep_set_busy(cfg, false);

Expand Down
6 changes: 1 addition & 5 deletions drivers/usb/udc/udc_numaker.c
Original file line number Diff line number Diff line change
Expand Up @@ -2605,7 +2605,6 @@ static int udc_numaker_ep_enqueue(const struct device *dev, struct udc_ep_config

static int udc_numaker_ep_dequeue(const struct device *dev, struct udc_ep_config *const ep_cfg)
{
struct net_buf *buf;
struct numaker_usbd_ep *ep_cur;

/* Bind EP H/W context to EP address */
Expand All @@ -2617,10 +2616,7 @@ static int udc_numaker_ep_dequeue(const struct device *dev, struct udc_ep_config

numaker_usbd_ep_abort(ep_cur, false);

buf = udc_buf_get_all(ep_cfg);
if (buf) {
udc_submit_ep_event(dev, buf, -ECONNABORTED);
}
udc_ep_cancel_queued(dev, ep_cfg);

return 0;
}
Expand Down
6 changes: 1 addition & 5 deletions drivers/usb/udc/udc_renesas_ra.c
Original file line number Diff line number Diff line change
Expand Up @@ -322,14 +322,10 @@ static int udc_renesas_ra_ep_dequeue(const struct device *dev, struct udc_ep_con
{
struct udc_renesas_ra_data *data = udc_get_private(dev);
unsigned int lock_key;
struct net_buf *buf;

lock_key = irq_lock();

buf = udc_buf_get_all(cfg);
if (buf != NULL) {
udc_submit_ep_event(dev, buf, -ECONNABORTED);
}
udc_ep_cancel_queued(dev, cfg);

if (FSP_SUCCESS != R_USBD_XferAbort(&data->udc, cfg->addr)) {
return -EIO;
Expand Down
6 changes: 1 addition & 5 deletions drivers/usb/udc/udc_rpi_pico.c
Original file line number Diff line number Diff line change
Expand Up @@ -734,15 +734,11 @@ static int udc_rpi_pico_ep_dequeue(const struct device *dev,
struct udc_ep_config *const cfg)
{
unsigned int lock_key;
struct net_buf *buf;

lock_key = irq_lock();

rpi_pico_ep_cancel(dev, cfg->addr);
buf = udc_buf_get_all(cfg);
if (buf) {
udc_submit_ep_event(dev, buf, -ECONNABORTED);
}
udc_ep_cancel_queued(dev, cfg);

irq_unlock(lock_key);

Expand Down
9 changes: 3 additions & 6 deletions drivers/usb/udc/udc_sam0.c
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,6 @@ static int udc_sam0_ep_dequeue(const struct device *dev, struct udc_ep_config *c
{
UsbDeviceEndpoint *const endpoint = sam0_get_ep_reg(dev, ep_cfg->addr);
unsigned int lock_key;
struct net_buf *buf;

lock_key = irq_lock();

Expand All @@ -652,11 +651,9 @@ static int udc_sam0_ep_dequeue(const struct device *dev, struct udc_ep_config *c
endpoint->EPSTATUSSET.bit.BK0RDY = 1;
}

buf = udc_buf_get_all(ep_cfg);
if (buf) {
udc_submit_ep_event(dev, buf, -ECONNABORTED);
udc_ep_set_busy(ep_cfg, false);
}
udc_ep_cancel_queued(dev, ep_cfg);

udc_ep_set_busy(ep_cfg, false);

irq_unlock(lock_key);

Expand Down
6 changes: 1 addition & 5 deletions drivers/usb/udc/udc_sam_udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,6 @@ static int udc_sam_udp_ep_dequeue(const struct device *dev,
{
Udp *base = udc_sam_udp_get_base(dev);
uint8_t hw_ep = USB_EP_GET_IDX(cfg->addr);
struct net_buf *buf;

/* Cancel pending TX data for IN endpoints per datasheet 40.6.2.5 */
if (USB_EP_DIR_IS_IN(cfg->addr)) {
Expand All @@ -586,10 +585,7 @@ static int udc_sam_udp_ep_dequeue(const struct device *dev,
* rapid queue/cancel cycles (unlink tests).
*/

buf = udc_buf_get_all(cfg);
if (buf) {
udc_submit_ep_event(dev, buf, -ECONNABORTED);
}
udc_ep_cancel_queued(dev, cfg);

return 0;
}
Expand Down
8 changes: 2 additions & 6 deletions drivers/usb/udc/udc_sam_usbc.c
Original file line number Diff line number Diff line change
Expand Up @@ -887,7 +887,6 @@ static int udc_sam_usbc_ep_dequeue(const struct device *const dev,
Usbc *const base = config->base;
const uint8_t phys_ep = virt_to_phys_ep(dev, ep_cfg->addr);
unsigned int lock_key;
struct net_buf *buf;

lock_key = irq_lock();

Expand All @@ -905,11 +904,8 @@ static int udc_sam_usbc_ep_dequeue(const struct device *const dev,
}

/* Always dequeue pending buffers and notify class layer */
buf = udc_buf_get_all(ep_cfg);
if (buf) {
udc_submit_ep_event(dev, buf, -ECONNABORTED);
udc_ep_set_busy(ep_cfg, false);
}
udc_ep_cancel_queued(dev, ep_cfg);
udc_ep_set_busy(ep_cfg, false);

irq_unlock(lock_key);

Expand Down
8 changes: 2 additions & 6 deletions drivers/usb/udc/udc_sam_usbhs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1038,7 +1038,6 @@ static int udc_sam_usbhs_ep_dequeue(const struct device *dev,
uint8_t ep_idx = ep_addr_to_hw_ep(ep_cfg->addr);
int bit = ep_to_bit(ep_cfg->addr);
unsigned int lock_key;
struct net_buf *buf;

lock_key = irq_lock();

Expand All @@ -1059,11 +1058,8 @@ static int udc_sam_usbhs_ep_dequeue(const struct device *dev,
*/
atomic_clear_bit(&priv->xfer_finished, bit);

buf = udc_buf_get_all(ep_cfg);
if (buf) {
udc_submit_ep_event(dev, buf, -ECONNABORTED);
udc_ep_set_busy(ep_cfg, false);
}
udc_ep_cancel_queued(dev, ep_cfg);
udc_ep_set_busy(ep_cfg, false);

irq_unlock(lock_key);

Expand Down
Loading
Loading