Merge 5.7-rc6 into usb-next
We need the USB fixes in here as well. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
@@ -2548,7 +2548,7 @@ found:
|
||||
link_trb = priv_req->trb;
|
||||
|
||||
/* Update ring only if removed request is on pending_req_list list */
|
||||
if (req_on_hw_ring) {
|
||||
if (req_on_hw_ring && link_trb) {
|
||||
link_trb->buffer = TRB_BUFFER(priv_ep->trb_pool_dma +
|
||||
((priv_req->end_trb + 1) * TRB_SIZE));
|
||||
link_trb->control = (link_trb->control & TRB_CYCLE) |
|
||||
|
@@ -251,9 +251,19 @@ static int usbdev_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
usbm->vma_use_count = 1;
|
||||
INIT_LIST_HEAD(&usbm->memlist);
|
||||
|
||||
if (dma_mmap_coherent(hcd->self.sysdev, vma, mem, dma_handle, size)) {
|
||||
dec_usb_memory_use_count(usbm, &usbm->vma_use_count);
|
||||
return -EAGAIN;
|
||||
if (hcd->localmem_pool || !hcd_uses_dma(hcd)) {
|
||||
if (remap_pfn_range(vma, vma->vm_start,
|
||||
virt_to_phys(usbm->mem) >> PAGE_SHIFT,
|
||||
size, vma->vm_page_prot) < 0) {
|
||||
dec_usb_memory_use_count(usbm, &usbm->vma_use_count);
|
||||
return -EAGAIN;
|
||||
}
|
||||
} else {
|
||||
if (dma_mmap_coherent(hcd->self.sysdev, vma, mem, dma_handle,
|
||||
size)) {
|
||||
dec_usb_memory_use_count(usbm, &usbm->vma_use_count);
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
vma->vm_flags |= VM_IO;
|
||||
|
@@ -39,6 +39,7 @@
|
||||
|
||||
#define USB_VENDOR_GENESYS_LOGIC 0x05e3
|
||||
#define USB_VENDOR_SMSC 0x0424
|
||||
#define USB_PRODUCT_USB5534B 0x5534
|
||||
#define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01
|
||||
#define HUB_QUIRK_DISABLE_AUTOSUSPEND 0x02
|
||||
|
||||
@@ -5621,8 +5622,11 @@ out_hdev_lock:
|
||||
}
|
||||
|
||||
static const struct usb_device_id hub_id_table[] = {
|
||||
{ .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_CLASS,
|
||||
{ .match_flags = USB_DEVICE_ID_MATCH_VENDOR
|
||||
| USB_DEVICE_ID_MATCH_PRODUCT
|
||||
| USB_DEVICE_ID_MATCH_INT_CLASS,
|
||||
.idVendor = USB_VENDOR_SMSC,
|
||||
.idProduct = USB_PRODUCT_USB5534B,
|
||||
.bInterfaceClass = USB_CLASS_HUB,
|
||||
.driver_info = HUB_QUIRK_DISABLE_AUTOSUSPEND},
|
||||
{ .match_flags = USB_DEVICE_ID_MATCH_VENDOR
|
||||
|
@@ -4,6 +4,7 @@ config USB_DWC3
|
||||
tristate "DesignWare USB3 DRD Core Support"
|
||||
depends on (USB || USB_GADGET) && HAS_DMA
|
||||
select USB_XHCI_PLATFORM if USB_XHCI_HCD
|
||||
select USB_ROLE_SWITCH if USB_DWC3_DUAL_ROLE
|
||||
help
|
||||
Say Y or M here if your system has a Dual Role SuperSpeed
|
||||
USB controller based on the DesignWare USB3 IP Core.
|
||||
|
@@ -114,6 +114,7 @@ static const struct property_entry dwc3_pci_intel_properties[] = {
|
||||
|
||||
static const struct property_entry dwc3_pci_mrfld_properties[] = {
|
||||
PROPERTY_ENTRY_STRING("dr_mode", "otg"),
|
||||
PROPERTY_ENTRY_STRING("linux,extcon-name", "mrfld_bcove_pwrsrc"),
|
||||
PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
|
||||
{}
|
||||
};
|
||||
|
@@ -2483,9 +2483,6 @@ static int dwc3_gadget_ep_reclaim_trb_sg(struct dwc3_ep *dep,
|
||||
for_each_sg(sg, s, pending, i) {
|
||||
trb = &dep->trb_pool[dep->trb_dequeue];
|
||||
|
||||
if (trb->ctrl & DWC3_TRB_CTRL_HWO)
|
||||
break;
|
||||
|
||||
req->sg = sg_next(s);
|
||||
req->num_pending_sgs--;
|
||||
|
||||
|
@@ -260,6 +260,9 @@ static ssize_t gadget_dev_desc_UDC_store(struct config_item *item,
|
||||
char *name;
|
||||
int ret;
|
||||
|
||||
if (strlen(page) < len)
|
||||
return -EOVERFLOW;
|
||||
|
||||
name = kstrdup(page, GFP_KERNEL);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
@@ -300,8 +300,10 @@ static int audio_bind(struct usb_composite_dev *cdev)
|
||||
struct usb_descriptor_header *usb_desc;
|
||||
|
||||
usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
|
||||
if (!usb_desc)
|
||||
if (!usb_desc) {
|
||||
status = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
usb_otg_descriptor_init(cdev->gadget, usb_desc);
|
||||
otg_desc[0] = usb_desc;
|
||||
otg_desc[1] = NULL;
|
||||
|
@@ -179,8 +179,10 @@ static int cdc_bind(struct usb_composite_dev *cdev)
|
||||
struct usb_descriptor_header *usb_desc;
|
||||
|
||||
usb_desc = usb_otg_descriptor_alloc(gadget);
|
||||
if (!usb_desc)
|
||||
if (!usb_desc) {
|
||||
status = -ENOMEM;
|
||||
goto fail1;
|
||||
}
|
||||
usb_otg_descriptor_init(gadget, usb_desc);
|
||||
otg_desc[0] = usb_desc;
|
||||
otg_desc[1] = NULL;
|
||||
|
@@ -156,8 +156,10 @@ static int gncm_bind(struct usb_composite_dev *cdev)
|
||||
struct usb_descriptor_header *usb_desc;
|
||||
|
||||
usb_desc = usb_otg_descriptor_alloc(gadget);
|
||||
if (!usb_desc)
|
||||
if (!usb_desc) {
|
||||
status = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
usb_otg_descriptor_init(gadget, usb_desc);
|
||||
otg_desc[0] = usb_desc;
|
||||
otg_desc[1] = NULL;
|
||||
|
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kref.h>
|
||||
@@ -123,8 +124,6 @@ static void raw_event_queue_destroy(struct raw_event_queue *queue)
|
||||
|
||||
struct raw_dev;
|
||||
|
||||
#define USB_RAW_MAX_ENDPOINTS 32
|
||||
|
||||
enum ep_state {
|
||||
STATE_EP_DISABLED,
|
||||
STATE_EP_ENABLED,
|
||||
@@ -134,6 +133,7 @@ struct raw_ep {
|
||||
struct raw_dev *dev;
|
||||
enum ep_state state;
|
||||
struct usb_ep *ep;
|
||||
u8 addr;
|
||||
struct usb_request *req;
|
||||
bool urb_queued;
|
||||
bool disabling;
|
||||
@@ -168,7 +168,8 @@ struct raw_dev {
|
||||
bool ep0_out_pending;
|
||||
bool ep0_urb_queued;
|
||||
ssize_t ep0_status;
|
||||
struct raw_ep eps[USB_RAW_MAX_ENDPOINTS];
|
||||
struct raw_ep eps[USB_RAW_EPS_NUM_MAX];
|
||||
int eps_num;
|
||||
|
||||
struct completion ep0_done;
|
||||
struct raw_event_queue queue;
|
||||
@@ -202,8 +203,8 @@ static void dev_free(struct kref *kref)
|
||||
usb_ep_free_request(dev->gadget->ep0, dev->req);
|
||||
}
|
||||
raw_event_queue_destroy(&dev->queue);
|
||||
for (i = 0; i < USB_RAW_MAX_ENDPOINTS; i++) {
|
||||
if (dev->eps[i].state != STATE_EP_ENABLED)
|
||||
for (i = 0; i < dev->eps_num; i++) {
|
||||
if (dev->eps[i].state == STATE_EP_DISABLED)
|
||||
continue;
|
||||
usb_ep_disable(dev->eps[i].ep);
|
||||
usb_ep_free_request(dev->eps[i].ep, dev->eps[i].req);
|
||||
@@ -249,12 +250,26 @@ static void gadget_ep0_complete(struct usb_ep *ep, struct usb_request *req)
|
||||
complete(&dev->ep0_done);
|
||||
}
|
||||
|
||||
static u8 get_ep_addr(const char *name)
|
||||
{
|
||||
/* If the endpoint has fixed function (named as e.g. "ep12out-bulk"),
|
||||
* parse the endpoint address from its name. We deliberately use
|
||||
* deprecated simple_strtoul() function here, as the number isn't
|
||||
* followed by '\0' nor '\n'.
|
||||
*/
|
||||
if (isdigit(name[2]))
|
||||
return simple_strtoul(&name[2], NULL, 10);
|
||||
/* Otherwise the endpoint is configurable (named as e.g. "ep-a"). */
|
||||
return USB_RAW_EP_ADDR_ANY;
|
||||
}
|
||||
|
||||
static int gadget_bind(struct usb_gadget *gadget,
|
||||
struct usb_gadget_driver *driver)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0, i = 0;
|
||||
struct raw_dev *dev = container_of(driver, struct raw_dev, driver);
|
||||
struct usb_request *req;
|
||||
struct usb_ep *ep;
|
||||
unsigned long flags;
|
||||
|
||||
if (strcmp(gadget->name, dev->udc_name) != 0)
|
||||
@@ -273,6 +288,13 @@ static int gadget_bind(struct usb_gadget *gadget,
|
||||
dev->req->context = dev;
|
||||
dev->req->complete = gadget_ep0_complete;
|
||||
dev->gadget = gadget;
|
||||
gadget_for_each_ep(ep, dev->gadget) {
|
||||
dev->eps[i].ep = ep;
|
||||
dev->eps[i].addr = get_ep_addr(ep->name);
|
||||
dev->eps[i].state = STATE_EP_DISABLED;
|
||||
i++;
|
||||
}
|
||||
dev->eps_num = i;
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
/* Matches kref_put() in gadget_unbind(). */
|
||||
@@ -555,7 +577,7 @@ static void *raw_alloc_io_data(struct usb_raw_ep_io *io, void __user *ptr,
|
||||
|
||||
if (copy_from_user(io, ptr, sizeof(*io)))
|
||||
return ERR_PTR(-EFAULT);
|
||||
if (io->ep >= USB_RAW_MAX_ENDPOINTS)
|
||||
if (io->ep >= USB_RAW_EPS_NUM_MAX)
|
||||
return ERR_PTR(-EINVAL);
|
||||
if (!usb_raw_io_flags_valid(io->flags))
|
||||
return ERR_PTR(-EINVAL);
|
||||
@@ -669,43 +691,61 @@ static int raw_ioctl_ep0_read(struct raw_dev *dev, unsigned long value)
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
ret = raw_process_ep0_io(dev, &io, data, false);
|
||||
if (ret)
|
||||
if (ret < 0)
|
||||
goto free;
|
||||
|
||||
length = min(io.length, (unsigned int)ret);
|
||||
if (copy_to_user((void __user *)(value + sizeof(io)), data, length))
|
||||
ret = -EFAULT;
|
||||
else
|
||||
ret = length;
|
||||
free:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool check_ep_caps(struct usb_ep *ep,
|
||||
struct usb_endpoint_descriptor *desc)
|
||||
static int raw_ioctl_ep0_stall(struct raw_dev *dev, unsigned long value)
|
||||
{
|
||||
switch (usb_endpoint_type(desc)) {
|
||||
case USB_ENDPOINT_XFER_ISOC:
|
||||
if (!ep->caps.type_iso)
|
||||
return false;
|
||||
break;
|
||||
case USB_ENDPOINT_XFER_BULK:
|
||||
if (!ep->caps.type_bulk)
|
||||
return false;
|
||||
break;
|
||||
case USB_ENDPOINT_XFER_INT:
|
||||
if (!ep->caps.type_int)
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
|
||||
if (value)
|
||||
return -EINVAL;
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
if (dev->state != STATE_DEV_RUNNING) {
|
||||
dev_dbg(dev->dev, "fail, device is not running\n");
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (!dev->gadget) {
|
||||
dev_dbg(dev->dev, "fail, gadget is not bound\n");
|
||||
ret = -EBUSY;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (dev->ep0_urb_queued) {
|
||||
dev_dbg(&dev->gadget->dev, "fail, urb already queued\n");
|
||||
ret = -EBUSY;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (!dev->ep0_in_pending && !dev->ep0_out_pending) {
|
||||
dev_dbg(&dev->gadget->dev, "fail, no request pending\n");
|
||||
ret = -EBUSY;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in)
|
||||
return false;
|
||||
if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out)
|
||||
return false;
|
||||
ret = usb_ep_set_halt(dev->gadget->ep0);
|
||||
if (ret < 0)
|
||||
dev_err(&dev->gadget->dev,
|
||||
"fail, usb_ep_set_halt returned %d\n", ret);
|
||||
|
||||
return true;
|
||||
if (dev->ep0_in_pending)
|
||||
dev->ep0_in_pending = false;
|
||||
else
|
||||
dev->ep0_out_pending = false;
|
||||
|
||||
out_unlock:
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int raw_ioctl_ep_enable(struct raw_dev *dev, unsigned long value)
|
||||
@@ -713,7 +753,7 @@ static int raw_ioctl_ep_enable(struct raw_dev *dev, unsigned long value)
|
||||
int ret = 0, i;
|
||||
unsigned long flags;
|
||||
struct usb_endpoint_descriptor *desc;
|
||||
struct usb_ep *ep = NULL;
|
||||
struct raw_ep *ep;
|
||||
|
||||
desc = memdup_user((void __user *)value, sizeof(*desc));
|
||||
if (IS_ERR(desc))
|
||||
@@ -741,41 +781,32 @@ static int raw_ioctl_ep_enable(struct raw_dev *dev, unsigned long value)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
for (i = 0; i < USB_RAW_MAX_ENDPOINTS; i++) {
|
||||
if (dev->eps[i].state == STATE_EP_ENABLED)
|
||||
for (i = 0; i < dev->eps_num; i++) {
|
||||
ep = &dev->eps[i];
|
||||
if (ep->state != STATE_EP_DISABLED)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (i == USB_RAW_MAX_ENDPOINTS) {
|
||||
dev_dbg(&dev->gadget->dev,
|
||||
"fail, no device endpoints available\n");
|
||||
ret = -EBUSY;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
gadget_for_each_ep(ep, dev->gadget) {
|
||||
if (ep->enabled)
|
||||
if (ep->addr != usb_endpoint_num(desc) &&
|
||||
ep->addr != USB_RAW_EP_ADDR_ANY)
|
||||
continue;
|
||||
if (!check_ep_caps(ep, desc))
|
||||
if (!usb_gadget_ep_match_desc(dev->gadget, ep->ep, desc, NULL))
|
||||
continue;
|
||||
ep->desc = desc;
|
||||
ret = usb_ep_enable(ep);
|
||||
ep->ep->desc = desc;
|
||||
ret = usb_ep_enable(ep->ep);
|
||||
if (ret < 0) {
|
||||
dev_err(&dev->gadget->dev,
|
||||
"fail, usb_ep_enable returned %d\n", ret);
|
||||
goto out_free;
|
||||
}
|
||||
dev->eps[i].req = usb_ep_alloc_request(ep, GFP_ATOMIC);
|
||||
if (!dev->eps[i].req) {
|
||||
ep->req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC);
|
||||
if (!ep->req) {
|
||||
dev_err(&dev->gadget->dev,
|
||||
"fail, usb_ep_alloc_request failed\n");
|
||||
usb_ep_disable(ep);
|
||||
usb_ep_disable(ep->ep);
|
||||
ret = -ENOMEM;
|
||||
goto out_free;
|
||||
}
|
||||
dev->eps[i].ep = ep;
|
||||
dev->eps[i].state = STATE_EP_ENABLED;
|
||||
ep->driver_data = &dev->eps[i];
|
||||
ep->state = STATE_EP_ENABLED;
|
||||
ep->ep->driver_data = ep;
|
||||
ret = i;
|
||||
goto out_unlock;
|
||||
}
|
||||
@@ -794,10 +825,6 @@ static int raw_ioctl_ep_disable(struct raw_dev *dev, unsigned long value)
|
||||
{
|
||||
int ret = 0, i = value;
|
||||
unsigned long flags;
|
||||
const void *desc;
|
||||
|
||||
if (i < 0 || i >= USB_RAW_MAX_ENDPOINTS)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
if (dev->state != STATE_DEV_RUNNING) {
|
||||
@@ -810,7 +837,12 @@ static int raw_ioctl_ep_disable(struct raw_dev *dev, unsigned long value)
|
||||
ret = -EBUSY;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (dev->eps[i].state != STATE_EP_ENABLED) {
|
||||
if (i < 0 || i >= dev->eps_num) {
|
||||
dev_dbg(dev->dev, "fail, invalid endpoint\n");
|
||||
ret = -EBUSY;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (dev->eps[i].state == STATE_EP_DISABLED) {
|
||||
dev_dbg(&dev->gadget->dev, "fail, endpoint is not enabled\n");
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
@@ -834,10 +866,8 @@ static int raw_ioctl_ep_disable(struct raw_dev *dev, unsigned long value)
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
usb_ep_free_request(dev->eps[i].ep, dev->eps[i].req);
|
||||
desc = dev->eps[i].ep->desc;
|
||||
dev->eps[i].ep = NULL;
|
||||
kfree(dev->eps[i].ep->desc);
|
||||
dev->eps[i].state = STATE_EP_DISABLED;
|
||||
kfree(desc);
|
||||
dev->eps[i].disabling = false;
|
||||
|
||||
out_unlock:
|
||||
@@ -845,6 +875,74 @@ out_unlock:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int raw_ioctl_ep_set_clear_halt_wedge(struct raw_dev *dev,
|
||||
unsigned long value, bool set, bool halt)
|
||||
{
|
||||
int ret = 0, i = value;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
if (dev->state != STATE_DEV_RUNNING) {
|
||||
dev_dbg(dev->dev, "fail, device is not running\n");
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (!dev->gadget) {
|
||||
dev_dbg(dev->dev, "fail, gadget is not bound\n");
|
||||
ret = -EBUSY;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (i < 0 || i >= dev->eps_num) {
|
||||
dev_dbg(dev->dev, "fail, invalid endpoint\n");
|
||||
ret = -EBUSY;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (dev->eps[i].state == STATE_EP_DISABLED) {
|
||||
dev_dbg(&dev->gadget->dev, "fail, endpoint is not enabled\n");
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (dev->eps[i].disabling) {
|
||||
dev_dbg(&dev->gadget->dev,
|
||||
"fail, disable is in progress\n");
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (dev->eps[i].urb_queued) {
|
||||
dev_dbg(&dev->gadget->dev,
|
||||
"fail, waiting for urb completion\n");
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (usb_endpoint_xfer_isoc(dev->eps[i].ep->desc)) {
|
||||
dev_dbg(&dev->gadget->dev,
|
||||
"fail, can't halt/wedge ISO endpoint\n");
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (set && halt) {
|
||||
ret = usb_ep_set_halt(dev->eps[i].ep);
|
||||
if (ret < 0)
|
||||
dev_err(&dev->gadget->dev,
|
||||
"fail, usb_ep_set_halt returned %d\n", ret);
|
||||
} else if (!set && halt) {
|
||||
ret = usb_ep_clear_halt(dev->eps[i].ep);
|
||||
if (ret < 0)
|
||||
dev_err(&dev->gadget->dev,
|
||||
"fail, usb_ep_clear_halt returned %d\n", ret);
|
||||
} else if (set && !halt) {
|
||||
ret = usb_ep_set_wedge(dev->eps[i].ep);
|
||||
if (ret < 0)
|
||||
dev_err(&dev->gadget->dev,
|
||||
"fail, usb_ep_set_wedge returned %d\n", ret);
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void gadget_ep_complete(struct usb_ep *ep, struct usb_request *req)
|
||||
{
|
||||
struct raw_ep *r_ep = (struct raw_ep *)ep->driver_data;
|
||||
@@ -866,7 +964,7 @@ static int raw_process_ep_io(struct raw_dev *dev, struct usb_raw_ep_io *io,
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
struct raw_ep *ep = &dev->eps[io->ep];
|
||||
struct raw_ep *ep;
|
||||
DECLARE_COMPLETION_ONSTACK(done);
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
@@ -880,6 +978,12 @@ static int raw_process_ep_io(struct raw_dev *dev, struct usb_raw_ep_io *io,
|
||||
ret = -EBUSY;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (io->ep >= dev->eps_num) {
|
||||
dev_dbg(&dev->gadget->dev, "fail, invalid endpoint\n");
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
ep = &dev->eps[io->ep];
|
||||
if (ep->state != STATE_EP_ENABLED) {
|
||||
dev_dbg(&dev->gadget->dev, "fail, endpoint is not enabled\n");
|
||||
ret = -EBUSY;
|
||||
@@ -964,12 +1068,14 @@ static int raw_ioctl_ep_read(struct raw_dev *dev, unsigned long value)
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
ret = raw_process_ep_io(dev, &io, data, false);
|
||||
if (ret)
|
||||
if (ret < 0)
|
||||
goto free;
|
||||
|
||||
length = min(io.length, (unsigned int)ret);
|
||||
if (copy_to_user((void __user *)(value + sizeof(io)), data, length))
|
||||
ret = -EFAULT;
|
||||
else
|
||||
ret = length;
|
||||
free:
|
||||
kfree(data);
|
||||
return ret;
|
||||
@@ -1023,6 +1129,71 @@ out_unlock:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void fill_ep_caps(struct usb_ep_caps *caps,
|
||||
struct usb_raw_ep_caps *raw_caps)
|
||||
{
|
||||
raw_caps->type_control = caps->type_control;
|
||||
raw_caps->type_iso = caps->type_iso;
|
||||
raw_caps->type_bulk = caps->type_bulk;
|
||||
raw_caps->type_int = caps->type_int;
|
||||
raw_caps->dir_in = caps->dir_in;
|
||||
raw_caps->dir_out = caps->dir_out;
|
||||
}
|
||||
|
||||
static void fill_ep_limits(struct usb_ep *ep, struct usb_raw_ep_limits *limits)
|
||||
{
|
||||
limits->maxpacket_limit = ep->maxpacket_limit;
|
||||
limits->max_streams = ep->max_streams;
|
||||
}
|
||||
|
||||
static int raw_ioctl_eps_info(struct raw_dev *dev, unsigned long value)
|
||||
{
|
||||
int ret = 0, i;
|
||||
unsigned long flags;
|
||||
struct usb_raw_eps_info *info;
|
||||
struct raw_ep *ep;
|
||||
|
||||
info = kmalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
if (dev->state != STATE_DEV_RUNNING) {
|
||||
dev_dbg(dev->dev, "fail, device is not running\n");
|
||||
ret = -EINVAL;
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
goto out_free;
|
||||
}
|
||||
if (!dev->gadget) {
|
||||
dev_dbg(dev->dev, "fail, gadget is not bound\n");
|
||||
ret = -EBUSY;
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
for (i = 0; i < dev->eps_num; i++) {
|
||||
ep = &dev->eps[i];
|
||||
strscpy(&info->eps[i].name[0], ep->ep->name,
|
||||
USB_RAW_EP_NAME_MAX);
|
||||
info->eps[i].addr = ep->addr;
|
||||
fill_ep_caps(&ep->ep->caps, &info->eps[i].caps);
|
||||
fill_ep_limits(ep->ep, &info->eps[i].limits);
|
||||
}
|
||||
ret = dev->eps_num;
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
if (copy_to_user((void __user *)value, info, sizeof(*info)))
|
||||
ret = -EFAULT;
|
||||
|
||||
out_free:
|
||||
kfree(info);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long raw_ioctl(struct file *fd, unsigned int cmd, unsigned long value)
|
||||
{
|
||||
struct raw_dev *dev = fd->private_data;
|
||||
@@ -1065,6 +1236,24 @@ static long raw_ioctl(struct file *fd, unsigned int cmd, unsigned long value)
|
||||
case USB_RAW_IOCTL_VBUS_DRAW:
|
||||
ret = raw_ioctl_vbus_draw(dev, value);
|
||||
break;
|
||||
case USB_RAW_IOCTL_EPS_INFO:
|
||||
ret = raw_ioctl_eps_info(dev, value);
|
||||
break;
|
||||
case USB_RAW_IOCTL_EP0_STALL:
|
||||
ret = raw_ioctl_ep0_stall(dev, value);
|
||||
break;
|
||||
case USB_RAW_IOCTL_EP_SET_HALT:
|
||||
ret = raw_ioctl_ep_set_clear_halt_wedge(
|
||||
dev, value, true, true);
|
||||
break;
|
||||
case USB_RAW_IOCTL_EP_CLEAR_HALT:
|
||||
ret = raw_ioctl_ep_set_clear_halt_wedge(
|
||||
dev, value, false, true);
|
||||
break;
|
||||
case USB_RAW_IOCTL_EP_SET_WEDGE:
|
||||
ret = raw_ioctl_ep_set_clear_halt_wedge(
|
||||
dev, value, true, false);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
@@ -185,7 +185,7 @@ static int regs_dbg_release(struct inode *inode, struct file *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct file_operations queue_dbg_fops = {
|
||||
static const struct file_operations queue_dbg_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = queue_dbg_open,
|
||||
.llseek = no_llseek,
|
||||
@@ -193,7 +193,7 @@ const struct file_operations queue_dbg_fops = {
|
||||
.release = queue_dbg_release,
|
||||
};
|
||||
|
||||
const struct file_operations regs_dbg_fops = {
|
||||
static const struct file_operations regs_dbg_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = regs_dbg_open,
|
||||
.llseek = generic_file_llseek,
|
||||
|
@@ -2647,6 +2647,8 @@ net2272_plat_probe(struct platform_device *pdev)
|
||||
err_req:
|
||||
release_mem_region(base, len);
|
||||
err:
|
||||
kfree(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@@ -3840,11 +3840,11 @@ static int __maybe_unused tegra_xudc_suspend(struct device *dev)
|
||||
|
||||
flush_work(&xudc->usb_role_sw_work);
|
||||
|
||||
/* Forcibly disconnect before powergating. */
|
||||
tegra_xudc_device_mode_off(xudc);
|
||||
|
||||
if (!pm_runtime_status_suspended(dev))
|
||||
if (!pm_runtime_status_suspended(dev)) {
|
||||
/* Forcibly disconnect before powergating. */
|
||||
tegra_xudc_device_mode_off(xudc);
|
||||
tegra_xudc_powergate(xudc);
|
||||
}
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
|
@@ -372,6 +372,7 @@ static int xhci_plat_remove(struct platform_device *dev)
|
||||
struct clk *reg_clk = xhci->reg_clk;
|
||||
struct usb_hcd *shared_hcd = xhci->shared_hcd;
|
||||
|
||||
pm_runtime_get_sync(&dev->dev);
|
||||
xhci->xhc_state |= XHCI_STATE_REMOVING;
|
||||
|
||||
usb_remove_hcd(shared_hcd);
|
||||
@@ -385,8 +386,9 @@ static int xhci_plat_remove(struct platform_device *dev)
|
||||
clk_disable_unprepare(reg_clk);
|
||||
usb_put_hcd(hcd);
|
||||
|
||||
pm_runtime_set_suspended(&dev->dev);
|
||||
pm_runtime_disable(&dev->dev);
|
||||
pm_runtime_put_noidle(&dev->dev);
|
||||
pm_runtime_set_suspended(&dev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -3433,8 +3433,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
/* New sg entry */
|
||||
--num_sgs;
|
||||
sent_len -= block_len;
|
||||
if (num_sgs != 0) {
|
||||
sg = sg_next(sg);
|
||||
sg = sg_next(sg);
|
||||
if (num_sgs != 0 && sg) {
|
||||
block_len = sg_dma_len(sg);
|
||||
addr = (u64) sg_dma_address(sg);
|
||||
addr += sent_len;
|
||||
|
@@ -276,7 +276,7 @@ static const struct file_operations mtu3_ep_fops = {
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static struct debugfs_reg32 mtu3_prb_regs[] = {
|
||||
static const struct debugfs_reg32 mtu3_prb_regs[] = {
|
||||
dump_prb_reg("enable", U3D_SSUSB_PRB_CTRL0),
|
||||
dump_prb_reg("byte-sell", U3D_SSUSB_PRB_CTRL1),
|
||||
dump_prb_reg("byte-selh", U3D_SSUSB_PRB_CTRL2),
|
||||
@@ -349,7 +349,7 @@ static const struct file_operations mtu3_probe_fops = {
|
||||
static void mtu3_debugfs_create_prb_files(struct mtu3 *mtu)
|
||||
{
|
||||
struct ssusb_mtk *ssusb = mtu->ssusb;
|
||||
struct debugfs_reg32 *regs;
|
||||
const struct debugfs_reg32 *regs;
|
||||
struct dentry *dir_prb;
|
||||
int i;
|
||||
|
||||
|
@@ -377,7 +377,7 @@ static int twl6030_usb_probe(struct platform_device *pdev)
|
||||
if (status < 0) {
|
||||
dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
|
||||
twl->irq1, status);
|
||||
return status;
|
||||
goto err_put_regulator;
|
||||
}
|
||||
|
||||
status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq,
|
||||
@@ -386,8 +386,7 @@ static int twl6030_usb_probe(struct platform_device *pdev)
|
||||
if (status < 0) {
|
||||
dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
|
||||
twl->irq2, status);
|
||||
free_irq(twl->irq1, twl);
|
||||
return status;
|
||||
goto err_free_irq1;
|
||||
}
|
||||
|
||||
twl->asleep = 0;
|
||||
@@ -396,6 +395,13 @@ static int twl6030_usb_probe(struct platform_device *pdev)
|
||||
dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_irq1:
|
||||
free_irq(twl->irq1, twl);
|
||||
err_put_regulator:
|
||||
regulator_put(twl->usb3v3);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int twl6030_usb_remove(struct platform_device *pdev)
|
||||
|
@@ -63,6 +63,7 @@ enum {
|
||||
#define PMC_USB_ALTMODE_DP_MODE_SHIFT 8
|
||||
|
||||
/* TBT specific Mode Data bits */
|
||||
#define PMC_USB_ALTMODE_HPD_HIGH BIT(14)
|
||||
#define PMC_USB_ALTMODE_TBT_TYPE BIT(17)
|
||||
#define PMC_USB_ALTMODE_CABLE_TYPE BIT(18)
|
||||
#define PMC_USB_ALTMODE_ACTIVE_LINK BIT(20)
|
||||
@@ -74,8 +75,8 @@ enum {
|
||||
#define PMC_USB_ALTMODE_TBT_GEN(_g_) (((_g_) & GENMASK(1, 0)) << 28)
|
||||
|
||||
/* Display HPD Request bits */
|
||||
#define PMC_USB_DP_HPD_LVL BIT(4)
|
||||
#define PMC_USB_DP_HPD_IRQ BIT(5)
|
||||
#define PMC_USB_DP_HPD_LVL BIT(6)
|
||||
|
||||
struct pmc_usb;
|
||||
|
||||
@@ -178,8 +179,7 @@ pmc_usb_mux_dp(struct pmc_usb_port *port, struct typec_mux_state *state)
|
||||
PMC_USB_ALTMODE_DP_MODE_SHIFT;
|
||||
|
||||
if (data->status & DP_STATUS_HPD_STATE)
|
||||
req.mode_data |= PMC_USB_DP_HPD_LVL <<
|
||||
PMC_USB_ALTMODE_DP_MODE_SHIFT;
|
||||
req.mode_data |= PMC_USB_ALTMODE_HPD_HIGH;
|
||||
|
||||
return pmc_usb_command(port, (void *)&req, sizeof(req));
|
||||
}
|
||||
|
Referens i nytt ärende
Block a user