Skip to content

Commit f378de7

Browse files
MarkWangChinesenashif
authored andcommitted
drivers: udc: mcux: move isr context codes to work context
Move the transfer process codes to work context becuase it lock the mutex, move bus reset process codes too because it calls some common udc apis (they may add mutex lock in future). Signed-off-by: Mark Wang <[email protected]>
1 parent b9a3edc commit f378de7

File tree

3 files changed

+247
-137
lines changed

3 files changed

+247
-137
lines changed

drivers/usb/udc/Kconfig.mcux

+11-1
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,22 @@ config UDC_NXP_EHCI
77
depends on DT_HAS_NXP_EHCI_ENABLED
88
select NOCACHE_MEMORY if HAS_MCUX_CACHE && CPU_HAS_DCACHE
99
imply UDC_BUF_FORCE_NOCACHE
10+
imply UDC_WORKQUEUE
1011
help
1112
NXP MCUX USB Device Controller Driver for EHCI.
1213

1314
config UDC_NXP_IP3511
1415
bool "NXP MCUX USB IP3511 Device controller driver"
1516
default y
1617
depends on DT_HAS_NXP_LPCIP3511_ENABLED
18+
imply UDC_WORKQUEUE
1719
help
18-
NXP MCUX USB Device Controller Driver for KHCI.
20+
NXP MCUX USB Device Controller Driver for IP3511.
21+
22+
config UDC_NXP_EVENT_COUNT
23+
int "Number or blocks in event slab"
24+
depends on UDC_NXP_EHCI || UDC_NXP_IP3511
25+
range 4 16
26+
default 4
27+
help
28+
Number of blocks in slab for internal controller events.

drivers/usb/udc/udc_mcux_ehci.c

+118-68
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,31 @@ struct udc_mcux_config {
4949
struct udc_mcux_data {
5050
const struct device *dev;
5151
usb_device_struct_t mcux_device;
52+
struct k_work work;
53+
struct k_fifo fifo;
5254
uint8_t controller_id; /* 0xFF is invalid value */
5355
};
5456

57+
/* Structure for driver's events */
58+
struct udc_mcux_event {
59+
sys_snode_t node;
60+
const struct device *dev;
61+
usb_device_callback_message_struct_t mcux_msg;
62+
};
63+
64+
K_MEM_SLAB_DEFINE(udc_event_slab, sizeof(struct udc_mcux_event),
65+
CONFIG_UDC_NXP_EVENT_COUNT, sizeof(void *));
66+
67+
static int udc_mcux_lock(const struct device *dev)
68+
{
69+
return udc_lock_internal(dev, K_FOREVER);
70+
}
71+
72+
static int udc_mcux_unlock(const struct device *dev)
73+
{
74+
return udc_unlock_internal(dev);
75+
}
76+
5577
static int udc_mcux_control(const struct device *dev, usb_device_control_type_t command,
5678
void *param)
5779
{
@@ -81,7 +103,6 @@ static int udc_mcux_ep_feed(const struct device *dev,
81103
usb_status_t status = kStatus_USB_Success;
82104
uint8_t *data;
83105
uint32_t len;
84-
unsigned int key;
85106
usb_device_endpoint_status_struct_t ep_status;
86107

87108
ep_status.endpointAddress = cfg->addr;
@@ -90,10 +111,10 @@ static int udc_mcux_ep_feed(const struct device *dev,
90111
return -EACCES; /* stalled */
91112
}
92113

93-
key = irq_lock();
114+
udc_mcux_lock(dev);
94115
if (!udc_ep_is_busy(dev, cfg->addr)) {
95116
udc_ep_set_busy(dev, cfg->addr, true);
96-
irq_unlock(key);
117+
udc_mcux_unlock(dev);
97118

98119
if (USB_EP_DIR_IS_OUT(cfg->addr)) {
99120
len = net_buf_tailroom(buf);
@@ -107,13 +128,13 @@ static int udc_mcux_ep_feed(const struct device *dev,
107128
cfg->addr, data, len);
108129
}
109130

110-
key = irq_lock();
131+
udc_mcux_lock(dev);
111132
if (status != kStatus_USB_Success) {
112133
udc_ep_set_busy(dev, cfg->addr, false);
113134
}
114-
irq_unlock(key);
135+
udc_mcux_unlock(dev);
115136
} else {
116-
irq_unlock(key);
137+
udc_mcux_unlock(dev);
117138
return -EBUSY;
118139
}
119140

@@ -303,13 +324,12 @@ static int udc_mcux_handler_out(const struct device *dev, uint8_t ep,
303324
{
304325
int err;
305326
struct net_buf *buf;
306-
unsigned int key;
307327

308328
buf = udc_buf_get(dev, ep);
309329

310-
key = irq_lock();
330+
udc_mcux_lock(dev);
311331
udc_ep_set_busy(dev, ep, false);
312-
irq_unlock(key);
332+
udc_mcux_unlock(dev);
313333

314334
if (buf == NULL) {
315335
udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS);
@@ -357,7 +377,6 @@ static int udc_mcux_handler_in(const struct device *dev, uint8_t ep,
357377
{
358378
int err;
359379
struct net_buf *buf;
360-
unsigned int key;
361380

362381
buf = udc_buf_peek(dev, ep);
363382
if (buf == NULL) {
@@ -371,9 +390,9 @@ static int udc_mcux_handler_in(const struct device *dev, uint8_t ep,
371390

372391
buf = udc_buf_get(dev, ep);
373392

374-
key = irq_lock();
393+
udc_mcux_lock(dev);
375394
udc_ep_set_busy(dev, ep, false);
376-
irq_unlock(key);
395+
udc_mcux_unlock(dev);
377396

378397
if (buf == NULL) {
379398
udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS);
@@ -388,16 +407,95 @@ static int udc_mcux_handler_in(const struct device *dev, uint8_t ep,
388407
return err;
389408
}
390409

410+
static void udc_mcux_event_submit(const struct device *dev,
411+
const usb_device_callback_message_struct_t *mcux_msg)
412+
{
413+
struct udc_mcux_data *priv = udc_get_private(dev);
414+
struct udc_mcux_event *ev;
415+
int ret;
416+
417+
ret = k_mem_slab_alloc(&udc_event_slab, (void **)&ev, K_NO_WAIT);
418+
if (ret) {
419+
udc_submit_event(dev, UDC_EVT_ERROR, ret);
420+
LOG_ERR("Failed to allocate slab");
421+
return;
422+
}
423+
424+
ev->dev = dev;
425+
ev->mcux_msg = *mcux_msg;
426+
k_fifo_put(&priv->fifo, ev);
427+
k_work_submit_to_queue(udc_get_work_q(), &priv->work);
428+
}
429+
430+
static void udc_mcux_work_handler(struct k_work *item)
431+
{
432+
struct udc_mcux_event *ev;
433+
struct udc_mcux_data *priv;
434+
usb_device_callback_message_struct_t *mcux_msg;
435+
int err;
436+
uint8_t ep;
437+
438+
priv = CONTAINER_OF(item, struct udc_mcux_data, work);
439+
while ((ev = k_fifo_get(&priv->fifo, K_NO_WAIT)) != NULL) {
440+
mcux_msg = &ev->mcux_msg;
441+
442+
if (mcux_msg->code == kUSB_DeviceNotifyBusReset) {
443+
struct udc_ep_config *cfg;
444+
445+
udc_mcux_control(ev->dev, kUSB_DeviceControlSetDefaultStatus, NULL);
446+
cfg = udc_get_ep_cfg(ev->dev, USB_CONTROL_EP_OUT);
447+
if (cfg->stat.enabled) {
448+
udc_ep_disable_internal(ev->dev, USB_CONTROL_EP_OUT);
449+
}
450+
cfg = udc_get_ep_cfg(ev->dev, USB_CONTROL_EP_IN);
451+
if (cfg->stat.enabled) {
452+
udc_ep_disable_internal(ev->dev, USB_CONTROL_EP_IN);
453+
}
454+
if (udc_ep_enable_internal(ev->dev, USB_CONTROL_EP_OUT,
455+
USB_EP_TYPE_CONTROL,
456+
USB_MCUX_EP0_SIZE, 0)) {
457+
LOG_ERR("Failed to enable control endpoint");
458+
}
459+
460+
if (udc_ep_enable_internal(ev->dev, USB_CONTROL_EP_IN,
461+
USB_EP_TYPE_CONTROL,
462+
USB_MCUX_EP0_SIZE, 0)) {
463+
LOG_ERR("Failed to enable control endpoint");
464+
}
465+
udc_submit_event(ev->dev, UDC_EVT_RESET, 0);
466+
} else {
467+
ep = mcux_msg->code;
468+
469+
if (mcux_msg->isSetup) {
470+
struct usb_setup_packet *setup =
471+
(struct usb_setup_packet *)mcux_msg->buffer;
472+
473+
err = udc_mcux_handler_setup(ev->dev, setup);
474+
} else if (USB_EP_DIR_IS_IN(ep)) {
475+
err = udc_mcux_handler_in(ev->dev, ep, mcux_msg->buffer,
476+
mcux_msg->length);
477+
} else {
478+
err = udc_mcux_handler_out(ev->dev, ep, mcux_msg->buffer,
479+
mcux_msg->length);
480+
}
481+
482+
if (unlikely(err)) {
483+
udc_submit_event(ev->dev, UDC_EVT_ERROR, err);
484+
}
485+
}
486+
487+
k_mem_slab_free(&udc_event_slab, (void *)ev);
488+
}
489+
}
490+
391491
/* NXP MCUX controller driver notify transfers/status through this interface */
392492
usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg)
393493
{
394494
usb_device_callback_message_struct_t *mcux_msg = msg;
395-
uint8_t ep;
396495
usb_device_notification_t mcux_notify;
397496
struct udc_mcux_data *priv;
398497
const struct device *dev;
399498
usb_status_t mcux_status = kStatus_USB_Success;
400-
int err = 0;
401499

402500
if ((NULL == msg) || (NULL == handle)) {
403501
return kStatus_USB_InvalidHandle;
@@ -409,31 +507,7 @@ usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg)
409507

410508
switch (mcux_notify) {
411509
case kUSB_DeviceNotifyBusReset:
412-
struct udc_ep_config *cfg;
413-
414-
udc_mcux_control(dev, kUSB_DeviceControlSetDefaultStatus, NULL);
415-
cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT);
416-
if (cfg->stat.enabled) {
417-
udc_ep_disable_internal(dev, USB_CONTROL_EP_OUT);
418-
}
419-
cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_IN);
420-
if (cfg->stat.enabled) {
421-
udc_ep_disable_internal(dev, USB_CONTROL_EP_IN);
422-
}
423-
if (udc_ep_enable_internal(dev, USB_CONTROL_EP_OUT,
424-
USB_EP_TYPE_CONTROL,
425-
USB_MCUX_EP0_SIZE, 0)) {
426-
LOG_ERR("Failed to enable control endpoint");
427-
return -EIO;
428-
}
429-
430-
if (udc_ep_enable_internal(dev, USB_CONTROL_EP_IN,
431-
USB_EP_TYPE_CONTROL,
432-
USB_MCUX_EP0_SIZE, 0)) {
433-
LOG_ERR("Failed to enable control endpoint");
434-
return -EIO;
435-
}
436-
udc_submit_event(dev, UDC_EVT_RESET, 0);
510+
udc_mcux_event_submit(dev, mcux_msg);
437511
break;
438512
case kUSB_DeviceNotifyError:
439513
udc_submit_event(dev, UDC_EVT_ERROR, -EIO);
@@ -458,25 +532,10 @@ usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg)
458532
udc_submit_event(dev, UDC_EVT_SOF, 0);
459533
break;
460534
default:
461-
ep = mcux_msg->code;
462-
if (mcux_msg->isSetup) {
463-
struct usb_setup_packet *setup =
464-
(struct usb_setup_packet *)mcux_msg->buffer;
465-
466-
err = udc_mcux_handler_setup(dev, setup);
467-
} else if (USB_EP_DIR_IS_IN(ep)) {
468-
err = udc_mcux_handler_in(dev, ep, mcux_msg->buffer, mcux_msg->length);
469-
} else {
470-
err = udc_mcux_handler_out(dev, ep, mcux_msg->buffer, mcux_msg->length);
471-
}
472-
535+
udc_mcux_event_submit(dev, mcux_msg);
473536
break;
474537
}
475538

476-
if (unlikely(err)) {
477-
udc_submit_event(dev, UDC_EVT_ERROR, err);
478-
mcux_status = kStatus_USB_Error;
479-
}
480539
return mcux_status;
481540
}
482541

@@ -532,17 +591,16 @@ static int udc_mcux_ep_dequeue(const struct device *dev,
532591
struct udc_ep_config *const cfg)
533592
{
534593
struct net_buf *buf;
535-
unsigned int key;
536594

537595
cfg->stat.halted = false;
538596
buf = udc_buf_get_all(dev, cfg->addr);
539597
if (buf) {
540598
udc_submit_ep_event(dev, buf, -ECONNABORTED);
541599
}
542600

543-
key = irq_lock();
601+
udc_mcux_lock(dev);
544602
udc_ep_set_busy(dev, cfg->addr, false);
545-
irq_unlock(key);
603+
udc_mcux_unlock(dev);
546604

547605
return 0;
548606
}
@@ -676,16 +734,6 @@ static int udc_mcux_shutdown(const struct device *dev)
676734
return 0;
677735
}
678736

679-
static int udc_mcux_lock(const struct device *dev)
680-
{
681-
return udc_lock_internal(dev, K_FOREVER);
682-
}
683-
684-
static int udc_mcux_unlock(const struct device *dev)
685-
{
686-
return udc_unlock_internal(dev);
687-
}
688-
689737
static inline void udc_mcux_get_hal_driver_id(struct udc_mcux_data *priv,
690738
const struct udc_mcux_config *config)
691739
{
@@ -723,6 +771,8 @@ static int udc_mcux_driver_preinit(const struct device *dev)
723771
}
724772

725773
k_mutex_init(&data->mutex);
774+
k_fifo_init(&priv->fifo);
775+
k_work_init(&priv->work, udc_mcux_work_handler);
726776

727777
for (int i = 0; i < config->num_of_eps; i++) {
728778
config->ep_cfg_out[i].caps.out = 1;

0 commit comments

Comments
 (0)