usb: gadget: add SS descriptors to Ethernet gadget
Add SuperSpeed descriptors to the Network USB function drivers. This has been lightly tested using a Linux host. I was able to ssh from device to host and host to device, no obvious problems seen. Signed-off-by: Paul Zimmerman <paulz@synopsys.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:

committed by
Felipe Balbi

parent
96fe53ef54
commit
04617db7aa
@@ -77,10 +77,12 @@ static inline struct f_ecm *func_to_ecm(struct usb_function *f)
|
||||
/* peak (theoretical) bulk transfer rate in bits-per-second */
|
||||
static inline unsigned ecm_bitrate(struct usb_gadget *g)
|
||||
{
|
||||
if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
|
||||
if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
|
||||
return 13 * 1024 * 8 * 1000 * 8;
|
||||
else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
|
||||
return 13 * 512 * 8 * 1000 * 8;
|
||||
else
|
||||
return 19 * 64 * 1 * 1000 * 8;
|
||||
return 19 * 64 * 1 * 1000 * 8;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@@ -210,8 +212,10 @@ static struct usb_descriptor_header *ecm_fs_function[] = {
|
||||
(struct usb_descriptor_header *) &ecm_header_desc,
|
||||
(struct usb_descriptor_header *) &ecm_union_desc,
|
||||
(struct usb_descriptor_header *) &ecm_desc,
|
||||
|
||||
/* NOTE: status endpoint might need to be removed */
|
||||
(struct usb_descriptor_header *) &fs_ecm_notify_desc,
|
||||
|
||||
/* data interface, altsettings 0 and 1 */
|
||||
(struct usb_descriptor_header *) &ecm_data_nop_intf,
|
||||
(struct usb_descriptor_header *) &ecm_data_intf,
|
||||
@@ -231,6 +235,7 @@ static struct usb_endpoint_descriptor hs_ecm_notify_desc = {
|
||||
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
|
||||
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
|
||||
};
|
||||
|
||||
static struct usb_endpoint_descriptor hs_ecm_in_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
@@ -255,8 +260,10 @@ static struct usb_descriptor_header *ecm_hs_function[] = {
|
||||
(struct usb_descriptor_header *) &ecm_header_desc,
|
||||
(struct usb_descriptor_header *) &ecm_union_desc,
|
||||
(struct usb_descriptor_header *) &ecm_desc,
|
||||
|
||||
/* NOTE: status endpoint might need to be removed */
|
||||
(struct usb_descriptor_header *) &hs_ecm_notify_desc,
|
||||
|
||||
/* data interface, altsettings 0 and 1 */
|
||||
(struct usb_descriptor_header *) &ecm_data_nop_intf,
|
||||
(struct usb_descriptor_header *) &ecm_data_intf,
|
||||
@@ -265,6 +272,76 @@ static struct usb_descriptor_header *ecm_hs_function[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* super speed support: */
|
||||
|
||||
static struct usb_endpoint_descriptor ss_ecm_notify_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
|
||||
.bEndpointAddress = USB_DIR_IN,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
||||
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
|
||||
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
|
||||
};
|
||||
|
||||
static struct usb_ss_ep_comp_descriptor ss_ecm_intr_comp_desc = {
|
||||
.bLength = sizeof ss_ecm_intr_comp_desc,
|
||||
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
|
||||
|
||||
/* the following 3 values can be tweaked if necessary */
|
||||
/* .bMaxBurst = 0, */
|
||||
/* .bmAttributes = 0, */
|
||||
.wBytesPerInterval = cpu_to_le16(ECM_STATUS_BYTECOUNT),
|
||||
};
|
||||
|
||||
static struct usb_endpoint_descriptor ss_ecm_in_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
|
||||
.bEndpointAddress = USB_DIR_IN,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_BULK,
|
||||
.wMaxPacketSize = cpu_to_le16(1024),
|
||||
};
|
||||
|
||||
static struct usb_endpoint_descriptor ss_ecm_out_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
|
||||
.bEndpointAddress = USB_DIR_OUT,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_BULK,
|
||||
.wMaxPacketSize = cpu_to_le16(1024),
|
||||
};
|
||||
|
||||
static struct usb_ss_ep_comp_descriptor ss_ecm_bulk_comp_desc = {
|
||||
.bLength = sizeof ss_ecm_bulk_comp_desc,
|
||||
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
|
||||
|
||||
/* the following 2 values can be tweaked if necessary */
|
||||
/* .bMaxBurst = 0, */
|
||||
/* .bmAttributes = 0, */
|
||||
};
|
||||
|
||||
static struct usb_descriptor_header *ecm_ss_function[] = {
|
||||
/* CDC ECM control descriptors */
|
||||
(struct usb_descriptor_header *) &ecm_control_intf,
|
||||
(struct usb_descriptor_header *) &ecm_header_desc,
|
||||
(struct usb_descriptor_header *) &ecm_union_desc,
|
||||
(struct usb_descriptor_header *) &ecm_desc,
|
||||
|
||||
/* NOTE: status endpoint might need to be removed */
|
||||
(struct usb_descriptor_header *) &ss_ecm_notify_desc,
|
||||
(struct usb_descriptor_header *) &ss_ecm_intr_comp_desc,
|
||||
|
||||
/* data interface, altsettings 0 and 1 */
|
||||
(struct usb_descriptor_header *) &ecm_data_nop_intf,
|
||||
(struct usb_descriptor_header *) &ecm_data_intf,
|
||||
(struct usb_descriptor_header *) &ss_ecm_in_desc,
|
||||
(struct usb_descriptor_header *) &ss_ecm_bulk_comp_desc,
|
||||
(struct usb_descriptor_header *) &ss_ecm_out_desc,
|
||||
(struct usb_descriptor_header *) &ss_ecm_bulk_comp_desc,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* string descriptors: */
|
||||
|
||||
static struct usb_string ecm_string_defs[] = {
|
||||
@@ -679,6 +756,20 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (gadget_is_superspeed(c->cdev->gadget)) {
|
||||
ss_ecm_in_desc.bEndpointAddress =
|
||||
fs_ecm_in_desc.bEndpointAddress;
|
||||
ss_ecm_out_desc.bEndpointAddress =
|
||||
fs_ecm_out_desc.bEndpointAddress;
|
||||
ss_ecm_notify_desc.bEndpointAddress =
|
||||
fs_ecm_notify_desc.bEndpointAddress;
|
||||
|
||||
/* copy descriptors, and track endpoint copies */
|
||||
f->ss_descriptors = usb_copy_descriptors(ecm_ss_function);
|
||||
if (!f->ss_descriptors)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* NOTE: all that is done without knowing or caring about
|
||||
* the network link ... which is unavailable to this code
|
||||
* until we're activated via set_alt().
|
||||
@@ -688,6 +779,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
ecm->port.close = ecm_close;
|
||||
|
||||
DBG(cdev, "CDC Ethernet: %s speed IN/%s OUT/%s NOTIFY/%s\n",
|
||||
gadget_is_superspeed(c->cdev->gadget) ? "super" :
|
||||
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
|
||||
ecm->port.in_ep->name, ecm->port.out_ep->name,
|
||||
ecm->notify->name);
|
||||
@@ -696,6 +788,8 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
fail:
|
||||
if (f->descriptors)
|
||||
usb_free_descriptors(f->descriptors);
|
||||
if (f->hs_descriptors)
|
||||
usb_free_descriptors(f->hs_descriptors);
|
||||
|
||||
if (ecm->notify_req) {
|
||||
kfree(ecm->notify_req->buf);
|
||||
@@ -722,6 +816,8 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)
|
||||
|
||||
DBG(c->cdev, "ecm unbind\n");
|
||||
|
||||
if (gadget_is_superspeed(c->cdev->gadget))
|
||||
usb_free_descriptors(f->ss_descriptors);
|
||||
if (gadget_is_dualspeed(c->cdev->gadget))
|
||||
usb_free_descriptors(f->hs_descriptors);
|
||||
usb_free_descriptors(f->descriptors);
|
||||
|
Reference in New Issue
Block a user