Skip to content

Commit 1650113

Browse files
Jussi KivilinnaFelipe Balbi
authored andcommitted
usb: gadget: f_ncm: add SuperSpeed descriptors for CDC NCM
Patch enables SuperSpeed for NCM gadget. Tested with USB3380 and measured TCP throughput with two Intel PCs: udc to host: 920 Mbit/s host to udc: 550 Mbit/s Signed-off-by: Jussi Kivilinna <[email protected]> Signed-off-by: Felipe Balbi <[email protected]>
1 parent 8dc7d30 commit 1650113

File tree

1 file changed

+80
-2
lines changed

1 file changed

+80
-2
lines changed

drivers/usb/gadget/function/f_ncm.c

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ static inline struct f_ncm *func_to_ncm(struct usb_function *f)
9090
/* peak (theoretical) bulk transfer rate in bits-per-second */
9191
static inline unsigned ncm_bitrate(struct usb_gadget *g)
9292
{
93-
if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
93+
if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
94+
return 13 * 1024 * 8 * 1000 * 8;
95+
else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
9496
return 13 * 512 * 8 * 1000 * 8;
9597
else
9698
return 19 * 64 * 1 * 1000 * 8;
@@ -333,6 +335,76 @@ static struct usb_descriptor_header *ncm_hs_function[] = {
333335
NULL,
334336
};
335337

338+
339+
/* super speed support: */
340+
341+
static struct usb_endpoint_descriptor ss_ncm_notify_desc = {
342+
.bLength = USB_DT_ENDPOINT_SIZE,
343+
.bDescriptorType = USB_DT_ENDPOINT,
344+
345+
.bEndpointAddress = USB_DIR_IN,
346+
.bmAttributes = USB_ENDPOINT_XFER_INT,
347+
.wMaxPacketSize = cpu_to_le16(NCM_STATUS_BYTECOUNT),
348+
.bInterval = USB_MS_TO_HS_INTERVAL(NCM_STATUS_INTERVAL_MS)
349+
};
350+
351+
static struct usb_ss_ep_comp_descriptor ss_ncm_notify_comp_desc = {
352+
.bLength = sizeof(ss_ncm_notify_comp_desc),
353+
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
354+
355+
/* the following 3 values can be tweaked if necessary */
356+
/* .bMaxBurst = 0, */
357+
/* .bmAttributes = 0, */
358+
.wBytesPerInterval = cpu_to_le16(NCM_STATUS_BYTECOUNT),
359+
};
360+
361+
static struct usb_endpoint_descriptor ss_ncm_in_desc = {
362+
.bLength = USB_DT_ENDPOINT_SIZE,
363+
.bDescriptorType = USB_DT_ENDPOINT,
364+
365+
.bEndpointAddress = USB_DIR_IN,
366+
.bmAttributes = USB_ENDPOINT_XFER_BULK,
367+
.wMaxPacketSize = cpu_to_le16(1024),
368+
};
369+
370+
static struct usb_endpoint_descriptor ss_ncm_out_desc = {
371+
.bLength = USB_DT_ENDPOINT_SIZE,
372+
.bDescriptorType = USB_DT_ENDPOINT,
373+
374+
.bEndpointAddress = USB_DIR_OUT,
375+
.bmAttributes = USB_ENDPOINT_XFER_BULK,
376+
.wMaxPacketSize = cpu_to_le16(1024),
377+
};
378+
379+
static struct usb_ss_ep_comp_descriptor ss_ncm_bulk_comp_desc = {
380+
.bLength = sizeof(ss_ncm_bulk_comp_desc),
381+
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
382+
383+
/* the following 2 values can be tweaked if necessary */
384+
/* .bMaxBurst = 0, */
385+
/* .bmAttributes = 0, */
386+
};
387+
388+
static struct usb_descriptor_header *ncm_ss_function[] = {
389+
(struct usb_descriptor_header *) &ncm_iad_desc,
390+
/* CDC NCM control descriptors */
391+
(struct usb_descriptor_header *) &ncm_control_intf,
392+
(struct usb_descriptor_header *) &ncm_header_desc,
393+
(struct usb_descriptor_header *) &ncm_union_desc,
394+
(struct usb_descriptor_header *) &ecm_desc,
395+
(struct usb_descriptor_header *) &ncm_desc,
396+
(struct usb_descriptor_header *) &ss_ncm_notify_desc,
397+
(struct usb_descriptor_header *) &ss_ncm_notify_comp_desc,
398+
/* data interface, altsettings 0 and 1 */
399+
(struct usb_descriptor_header *) &ncm_data_nop_intf,
400+
(struct usb_descriptor_header *) &ncm_data_intf,
401+
(struct usb_descriptor_header *) &ss_ncm_in_desc,
402+
(struct usb_descriptor_header *) &ss_ncm_bulk_comp_desc,
403+
(struct usb_descriptor_header *) &ss_ncm_out_desc,
404+
(struct usb_descriptor_header *) &ss_ncm_bulk_comp_desc,
405+
NULL,
406+
};
407+
336408
/* string descriptors: */
337409

338410
#define STRING_CTRL_IDX 0
@@ -1431,8 +1503,13 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
14311503
hs_ncm_notify_desc.bEndpointAddress =
14321504
fs_ncm_notify_desc.bEndpointAddress;
14331505

1506+
ss_ncm_in_desc.bEndpointAddress = fs_ncm_in_desc.bEndpointAddress;
1507+
ss_ncm_out_desc.bEndpointAddress = fs_ncm_out_desc.bEndpointAddress;
1508+
ss_ncm_notify_desc.bEndpointAddress =
1509+
fs_ncm_notify_desc.bEndpointAddress;
1510+
14341511
status = usb_assign_descriptors(f, ncm_fs_function, ncm_hs_function,
1435-
NULL, NULL);
1512+
ncm_ss_function, NULL);
14361513
if (status)
14371514
goto fail;
14381515

@@ -1450,6 +1527,7 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
14501527
ncm->task_timer.function = ncm_tx_timeout;
14511528

14521529
DBG(cdev, "CDC Network: %s speed IN/%s OUT/%s NOTIFY/%s\n",
1530+
gadget_is_superspeed(c->cdev->gadget) ? "super" :
14531531
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
14541532
ncm->port.in_ep->name, ncm->port.out_ep->name,
14551533
ncm->notify->name);

0 commit comments

Comments
 (0)