diff options
Diffstat (limited to 'drivers/usb/gadget/udc/core.c')
-rw-r--r-- | drivers/usb/gadget/udc/core.c | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index efce68e9a8e0..e6f04eee95c4 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -23,6 +23,7 @@ #include <linux/list.h> #include <linux/err.h> #include <linux/dma-mapping.h> +#include <linux/sched/task_stack.h> #include <linux/workqueue.h> #include <linux/usb/ch9.h> @@ -139,10 +140,8 @@ int usb_ep_disable(struct usb_ep *ep) goto out; ret = ep->ops->disable(ep); - if (ret) { - ret = ret; + if (ret) goto out; - } ep->enabled = false; @@ -798,6 +797,14 @@ int usb_gadget_map_request_by_dev(struct device *dev, req->num_mapped_sgs = mapped; } else { + if (is_vmalloc_addr(req->buf)) { + dev_err(dev, "buffer is not dma capable\n"); + return -EFAULT; + } else if (object_is_on_stack(req->buf)) { + dev_err(dev, "buffer is on stack\n"); + return -EFAULT; + } + req->dma = dma_map_single(dev, req->buf, req->length, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); @@ -1058,6 +1065,23 @@ static inline void usb_gadget_udc_stop(struct usb_udc *udc) } /** + * usb_gadget_udc_set_speed - tells usb device controller speed supported by + * current driver + * @udc: The device we want to set maximum speed + * @speed: The maximum speed to allowed to run + * + * This call is issued by the UDC Class driver before calling + * usb_gadget_udc_start() in order to make sure that we don't try to + * connect on speeds the gadget driver doesn't support. + */ +static inline void usb_gadget_udc_set_speed(struct usb_udc *udc, + enum usb_device_speed speed) +{ + if (udc->gadget->ops->udc_set_speed) + udc->gadget->ops->udc_set_speed(udc->gadget, speed); +} + +/** * usb_udc_release - release the usb_udc struct * @dev: the dev member within usb_udc * @@ -1290,6 +1314,9 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri udc->dev.driver = &driver->driver; udc->gadget->dev.driver = &driver->driver; + if (driver->max_speed < udc->gadget->max_speed) + usb_gadget_udc_set_speed(udc, driver->max_speed); + ret = driver->bind(udc->gadget, driver); if (ret) goto err1; @@ -1442,6 +1469,18 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RO(state); +static ssize_t function_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct usb_udc *udc = container_of(dev, struct usb_udc, dev); + struct usb_gadget_driver *drv = udc->driver; + + if (!drv || !drv->function) + return 0; + return scnprintf(buf, PAGE_SIZE, "%s\n", drv->function); +} +static DEVICE_ATTR_RO(function); + #define USB_UDC_SPEED_ATTR(name, param) \ ssize_t name##_show(struct device *dev, \ struct device_attribute *attr, char *buf) \ @@ -1477,6 +1516,7 @@ static struct attribute *usb_udc_attrs[] = { &dev_attr_srp.attr, &dev_attr_soft_connect.attr, &dev_attr_state.attr, + &dev_attr_function.attr, &dev_attr_current_speed.attr, &dev_attr_maximum_speed.attr, |