Commit 1041f509 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'usb-5.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB fixes from Greg KH:
 "Here are some small USB fixes for 5.3-rc4.

  The "biggest" one here is moving code from one file to another in
  order to fix a long-standing race condition with the creation of sysfs
  files for USB devices. Turns out that there are now userspace tools
  out there that are hitting this long-known bug, so it's time to fix
  them. Thankfully the tool-maker in this case fixed the issue :)

  The other patches in here are all fixes for reported issues. Now that
  syzbot knows how to fuzz USB drivers better, and is starting to now
  fuzz the userspace facing side of them at the same time, there will be
  more and more small fixes like these coming, which is a good thing.

  All of these have been in linux-next with no reported issues"

* tag 'usb-5.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: setup authorized_default attributes using usb_bus_notify
  usb: iowarrior: fix deadlock on disconnect
  Revert "USB: rio500: simplify locking"
  usb: usbfs: fix double-free of usb memory upon submiturb error
  usb: yurex: Fix use-after-free in yurex_delete
  usb: typec: tcpm: Ignore unsupported/unknown alternate mode requests
  xhci: Fix NULL pointer dereference at endpoint zero reset.
  usb: host: xhci-rcar: Fix timeout in xhci_suspend()
  usb: typec: ucsi: ccg: Fix uninitilized symbol error
  usb: typec: tcpm: remove tcpm dir if no children
  usb: typec: tcpm: free log buf memory when remove debug file
  usb: typec: tcpm: Add NULL check before dereferencing config
parents 97946f59 27709ae4
...@@ -1812,8 +1812,6 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb ...@@ -1812,8 +1812,6 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
return 0; return 0;
error: error:
if (as && as->usbm)
dec_usb_memory_use_count(as->usbm, &as->usbm->urb_use_count);
kfree(isopkt); kfree(isopkt);
kfree(dr); kfree(dr);
if (as) if (as)
......
...@@ -103,11 +103,6 @@ static DEFINE_SPINLOCK(hcd_urb_unlink_lock); ...@@ -103,11 +103,6 @@ static DEFINE_SPINLOCK(hcd_urb_unlink_lock);
/* wait queue for synchronous unlinks */ /* wait queue for synchronous unlinks */
DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue); DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue);
static inline int is_root_hub(struct usb_device *udev)
{
return (udev->parent == NULL);
}
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* /*
...@@ -880,101 +875,6 @@ static int usb_rh_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ...@@ -880,101 +875,6 @@ static int usb_rh_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
} }
/*
* Show & store the current value of authorized_default
*/
static ssize_t authorized_default_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_device *rh_usb_dev = to_usb_device(dev);
struct usb_bus *usb_bus = rh_usb_dev->bus;
struct usb_hcd *hcd;
hcd = bus_to_hcd(usb_bus);
return snprintf(buf, PAGE_SIZE, "%u\n", hcd->dev_policy);
}
static ssize_t authorized_default_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
ssize_t result;
unsigned val;
struct usb_device *rh_usb_dev = to_usb_device(dev);
struct usb_bus *usb_bus = rh_usb_dev->bus;
struct usb_hcd *hcd;
hcd = bus_to_hcd(usb_bus);
result = sscanf(buf, "%u\n", &val);
if (result == 1) {
hcd->dev_policy = val <= USB_DEVICE_AUTHORIZE_INTERNAL ?
val : USB_DEVICE_AUTHORIZE_ALL;
result = size;
} else {
result = -EINVAL;
}
return result;
}
static DEVICE_ATTR_RW(authorized_default);
/*
* interface_authorized_default_show - show default authorization status
* for USB interfaces
*
* note: interface_authorized_default is the default value
* for initializing the authorized attribute of interfaces
*/
static ssize_t interface_authorized_default_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_device *usb_dev = to_usb_device(dev);
struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
return sprintf(buf, "%u\n", !!HCD_INTF_AUTHORIZED(hcd));
}
/*
* interface_authorized_default_store - store default authorization status
* for USB interfaces
*
* note: interface_authorized_default is the default value
* for initializing the authorized attribute of interfaces
*/
static ssize_t interface_authorized_default_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct usb_device *usb_dev = to_usb_device(dev);
struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
int rc = count;
bool val;
if (strtobool(buf, &val) != 0)
return -EINVAL;
if (val)
set_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
else
clear_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
return rc;
}
static DEVICE_ATTR_RW(interface_authorized_default);
/* Group all the USB bus attributes */
static struct attribute *usb_bus_attrs[] = {
&dev_attr_authorized_default.attr,
&dev_attr_interface_authorized_default.attr,
NULL,
};
static const struct attribute_group usb_bus_attr_group = {
.name = NULL, /* we want them in the same directory */
.attrs = usb_bus_attrs,
};
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/** /**
...@@ -2894,32 +2794,11 @@ int usb_add_hcd(struct usb_hcd *hcd, ...@@ -2894,32 +2794,11 @@ int usb_add_hcd(struct usb_hcd *hcd,
if (retval != 0) if (retval != 0)
goto err_register_root_hub; goto err_register_root_hub;
retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group);
if (retval < 0) {
printk(KERN_ERR "Cannot register USB bus sysfs attributes: %d\n",
retval);
goto error_create_attr_group;
}
if (hcd->uses_new_polling && HCD_POLL_RH(hcd)) if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
usb_hcd_poll_rh_status(hcd); usb_hcd_poll_rh_status(hcd);
return retval; return retval;
error_create_attr_group:
clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
if (HC_IS_RUNNING(hcd->state))
hcd->state = HC_STATE_QUIESCING;
spin_lock_irq(&hcd_root_hub_lock);
hcd->rh_registered = 0;
spin_unlock_irq(&hcd_root_hub_lock);
#ifdef CONFIG_PM
cancel_work_sync(&hcd->wakeup_work);
#endif
cancel_work_sync(&hcd->died_work);
mutex_lock(&usb_bus_idr_lock);
usb_disconnect(&rhdev); /* Sets rhdev to NULL */
mutex_unlock(&usb_bus_idr_lock);
err_register_root_hub: err_register_root_hub:
hcd->rh_pollable = 0; hcd->rh_pollable = 0;
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
...@@ -2963,8 +2842,6 @@ void usb_remove_hcd(struct usb_hcd *hcd) ...@@ -2963,8 +2842,6 @@ void usb_remove_hcd(struct usb_hcd *hcd)
dev_info(hcd->self.controller, "remove, state %x\n", hcd->state); dev_info(hcd->self.controller, "remove, state %x\n", hcd->state);
usb_get_dev(rhdev); usb_get_dev(rhdev);
sysfs_remove_group(&rhdev->dev.kobj, &usb_bus_attr_group);
clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags); clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
if (HC_IS_RUNNING (hcd->state)) if (HC_IS_RUNNING (hcd->state))
hcd->state = HC_STATE_QUIESCING; hcd->state = HC_STATE_QUIESCING;
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/usb/quirks.h> #include <linux/usb/quirks.h>
#include <linux/of.h> #include <linux/of.h>
#include "usb.h" #include "usb.h"
...@@ -922,6 +923,116 @@ static struct bin_attribute dev_bin_attr_descriptors = { ...@@ -922,6 +923,116 @@ static struct bin_attribute dev_bin_attr_descriptors = {
.size = 18 + 65535, /* dev descr + max-size raw descriptor */ .size = 18 + 65535, /* dev descr + max-size raw descriptor */
}; };
/*
* Show & store the current value of authorized_default
*/
static ssize_t authorized_default_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_device *rh_usb_dev = to_usb_device(dev);
struct usb_bus *usb_bus = rh_usb_dev->bus;
struct usb_hcd *hcd;
hcd = bus_to_hcd(usb_bus);
return snprintf(buf, PAGE_SIZE, "%u\n", hcd->dev_policy);
}
static ssize_t authorized_default_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
ssize_t result;
unsigned int val;
struct usb_device *rh_usb_dev = to_usb_device(dev);
struct usb_bus *usb_bus = rh_usb_dev->bus;
struct usb_hcd *hcd;
hcd = bus_to_hcd(usb_bus);
result = sscanf(buf, "%u\n", &val);
if (result == 1) {
hcd->dev_policy = val <= USB_DEVICE_AUTHORIZE_INTERNAL ?
val : USB_DEVICE_AUTHORIZE_ALL;
result = size;
} else {
result = -EINVAL;
}
return result;
}
static DEVICE_ATTR_RW(authorized_default);
/*
* interface_authorized_default_show - show default authorization status
* for USB interfaces
*
* note: interface_authorized_default is the default value
* for initializing the authorized attribute of interfaces
*/
static ssize_t interface_authorized_default_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_device *usb_dev = to_usb_device(dev);
struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
return sprintf(buf, "%u\n", !!HCD_INTF_AUTHORIZED(hcd));
}
/*
* interface_authorized_default_store - store default authorization status
* for USB interfaces
*
* note: interface_authorized_default is the default value
* for initializing the authorized attribute of interfaces
*/
static ssize_t interface_authorized_default_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct usb_device *usb_dev = to_usb_device(dev);
struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
int rc = count;
bool val;
if (strtobool(buf, &val) != 0)
return -EINVAL;
if (val)
set_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
else
clear_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
return rc;
}
static DEVICE_ATTR_RW(interface_authorized_default);
/* Group all the USB bus attributes */
static struct attribute *usb_bus_attrs[] = {
&dev_attr_authorized_default.attr,
&dev_attr_interface_authorized_default.attr,
NULL,
};
static const struct attribute_group usb_bus_attr_group = {
.name = NULL, /* we want them in the same directory */
.attrs = usb_bus_attrs,
};
static int add_default_authorized_attributes(struct device *dev)
{
int rc = 0;
if (is_usb_device(dev))
rc = sysfs_create_group(&dev->kobj, &usb_bus_attr_group);
return rc;
}
static void remove_default_authorized_attributes(struct device *dev)
{
if (is_usb_device(dev)) {
sysfs_remove_group(&dev->kobj, &usb_bus_attr_group);
}
}
int usb_create_sysfs_dev_files(struct usb_device *udev) int usb_create_sysfs_dev_files(struct usb_device *udev)
{ {
struct device *dev = &udev->dev; struct device *dev = &udev->dev;
...@@ -938,7 +1049,14 @@ int usb_create_sysfs_dev_files(struct usb_device *udev) ...@@ -938,7 +1049,14 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
retval = add_power_attributes(dev); retval = add_power_attributes(dev);
if (retval) if (retval)
goto error; goto error;
if (is_root_hub(udev)) {
retval = add_default_authorized_attributes(dev);
if (retval)
goto error;
}
return retval; return retval;
error: error:
usb_remove_sysfs_dev_files(udev); usb_remove_sysfs_dev_files(udev);
return retval; return retval;
...@@ -948,6 +1066,9 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev) ...@@ -948,6 +1066,9 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
{ {
struct device *dev = &udev->dev; struct device *dev = &udev->dev;
if (is_root_hub(udev))
remove_default_authorized_attributes(dev);
remove_power_attributes(dev); remove_power_attributes(dev);
remove_persist_attributes(dev); remove_persist_attributes(dev);
device_remove_bin_file(dev, &dev_bin_attr_descriptors); device_remove_bin_file(dev, &dev_bin_attr_descriptors);
......
...@@ -153,6 +153,11 @@ static inline int is_usb_port(const struct device *dev) ...@@ -153,6 +153,11 @@ static inline int is_usb_port(const struct device *dev)
return dev->type == &usb_port_device_type; return dev->type == &usb_port_device_type;
} }
static inline int is_root_hub(struct usb_device *udev)
{
return (udev->parent == NULL);
}
/* Do the same for device drivers and interface drivers. */ /* Do the same for device drivers and interface drivers. */
static inline int is_usb_device_driver(struct device_driver *drv) static inline int is_usb_device_driver(struct device_driver *drv)
......
...@@ -238,10 +238,15 @@ int xhci_rcar_init_quirk(struct usb_hcd *hcd) ...@@ -238,10 +238,15 @@ int xhci_rcar_init_quirk(struct usb_hcd *hcd)
* pointers. So, this driver clears the AC64 bit of xhci->hcc_params * pointers. So, this driver clears the AC64 bit of xhci->hcc_params
* to call dma_set_coherent_mask(dev, DMA_BIT_MASK(32)) in * to call dma_set_coherent_mask(dev, DMA_BIT_MASK(32)) in
* xhci_gen_setup(). * xhci_gen_setup().
*
* And, since the firmware/internal CPU control the USBSTS.STS_HALT
* and the process speed is down when the roothub port enters U3,
* long delay for the handshake of STS_HALT is neeed in xhci_suspend().
*/ */
if (xhci_rcar_is_gen2(hcd->self.controller) || if (xhci_rcar_is_gen2(hcd->self.controller) ||
xhci_rcar_is_gen3(hcd->self.controller)) xhci_rcar_is_gen3(hcd->self.controller)) {
xhci->quirks |= XHCI_NO_64BIT_SUPPORT; xhci->quirks |= XHCI_NO_64BIT_SUPPORT | XHCI_SLOW_SUSPEND;
}
if (!xhci_rcar_wait_for_pll_active(hcd)) if (!xhci_rcar_wait_for_pll_active(hcd))
return -ETIMEDOUT; return -ETIMEDOUT;
......
...@@ -3089,8 +3089,18 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd, ...@@ -3089,8 +3089,18 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
return; return;
udev = (struct usb_device *) host_ep->hcpriv; udev = (struct usb_device *) host_ep->hcpriv;
vdev = xhci->devs[udev->slot_id]; vdev = xhci->devs[udev->slot_id];
/*
* vdev may be lost due to xHC restore error and re-initialization
* during S3/S4 resume. A new vdev will be allocated later by
* xhci_discover_or_reset_device()
*/
if (!udev->slot_id || !vdev)
return;
ep_index = xhci_get_endpoint_index(&host_ep->desc); ep_index = xhci_get_endpoint_index(&host_ep->desc);
ep = &vdev->eps[ep_index]; ep = &vdev->eps[ep_index];
if (!ep)
return;
/* Bail out if toggle is already being cleared by a endpoint reset */ /* Bail out if toggle is already being cleared by a endpoint reset */
if (ep->ep_state & EP_HARD_CLEAR_TOGGLE) { if (ep->ep_state & EP_HARD_CLEAR_TOGGLE) {
......
...@@ -866,19 +866,20 @@ static void iowarrior_disconnect(struct usb_interface *interface) ...@@ -866,19 +866,20 @@ static void iowarrior_disconnect(struct usb_interface *interface)
dev = usb_get_intfdata(interface); dev = usb_get_intfdata(interface);
mutex_lock(&iowarrior_open_disc_lock); mutex_lock(&iowarrior_open_disc_lock);
usb_set_intfdata(interface, NULL); usb_set_intfdata(interface, NULL);
/* prevent device read, write and ioctl */
dev->present = 0;
minor = dev->minor; minor = dev->minor;
mutex_unlock(&iowarrior_open_disc_lock);
/* give back our minor - this will call close() locks need to be dropped at this point*/
/* give back our minor */
usb_deregister_dev(interface, &iowarrior_class); usb_deregister_dev(interface, &iowarrior_class);
mutex_lock(&dev->mutex); mutex_lock(&dev->mutex);
/* prevent device read, write and ioctl */ /* prevent device read, write and ioctl */
dev->present = 0;
mutex_unlock(&dev->mutex); mutex_unlock(&dev->mutex);
mutex_unlock(&iowarrior_open_disc_lock);
if (dev->opened) { if (dev->opened) {
/* There is a process that holds a filedescriptor to the device , /* There is a process that holds a filedescriptor to the device ,
......
...@@ -51,6 +51,7 @@ struct rio_usb_data { ...@@ -51,6 +51,7 @@ struct rio_usb_data {
char *obuf, *ibuf; /* transfer buffers */ char *obuf, *ibuf; /* transfer buffers */
char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */ char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */
wait_queue_head_t wait_q; /* for timeouts */ wait_queue_head_t wait_q; /* for timeouts */
struct mutex lock; /* general race avoidance */
}; };
static DEFINE_MUTEX(rio500_mutex); static DEFINE_MUTEX(rio500_mutex);
...@@ -62,8 +63,10 @@ static int open_rio(struct inode *inode, struct file *file) ...@@ -62,8 +63,10 @@ static int open_rio(struct inode *inode, struct file *file)
/* against disconnect() */ /* against disconnect() */
mutex_lock(&rio500_mutex); mutex_lock(&rio500_mutex);
mutex_lock(&(rio->lock));
if (rio->isopen || !rio->present) { if (rio->isopen || !rio->present) {
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex); mutex_unlock(&rio500_mutex);
return -EBUSY; return -EBUSY;
} }
...@@ -71,6 +74,7 @@ static int open_rio(struct inode *inode, struct file *file) ...@@ -71,6 +74,7 @@ static int open_rio(struct inode *inode, struct file *file)
init_waitqueue_head(&rio->wait_q); init_waitqueue_head(&rio->wait_q);
mutex_unlock(&(rio->lock));
dev_info(&rio->rio_dev->dev, "Rio opened.\n"); dev_info(&rio->rio_dev->dev, "Rio opened.\n");
mutex_unlock(&rio500_mutex); mutex_unlock(&rio500_mutex);
...@@ -84,6 +88,7 @@ static int close_rio(struct inode *inode, struct file *file) ...@@ -84,6 +88,7 @@ static int close_rio(struct inode *inode, struct file *file)
/* against disconnect() */ /* against disconnect() */
mutex_lock(&rio500_mutex); mutex_lock(&rio500_mutex);
mutex_lock(&(rio->lock));
rio->isopen = 0; rio->isopen = 0;
if (!rio->present) { if (!rio->present) {
...@@ -95,6 +100,7 @@ static int close_rio(struct inode *inode, struct file *file) ...@@ -95,6 +100,7 @@ static int close_rio(struct inode *inode, struct file *file)
} else { } else {
dev_info(&rio->rio_dev->dev, "Rio closed.\n"); dev_info(&rio->rio_dev->dev, "Rio closed.\n");
} }
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex); mutex_unlock(&rio500_mutex);
return 0; return 0;
} }
...@@ -109,7 +115,7 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -109,7 +115,7 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
int retries; int retries;
int retval=0; int retval=0;
mutex_lock(&rio500_mutex); mutex_lock(&(rio->lock));
/* Sanity check to make sure rio is connected, powered, etc */ /* Sanity check to make sure rio is connected, powered, etc */
if (rio->present == 0 || rio->rio_dev == NULL) { if (rio->present == 0 || rio->rio_dev == NULL) {
retval = -ENODEV; retval = -ENODEV;
...@@ -253,7 +259,7 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -253,7 +259,7 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
err_out: err_out:
mutex_unlock(&rio500_mutex); mutex_unlock(&(rio->lock));
return retval; return retval;
} }
...@@ -273,12 +279,12 @@ write_rio(struct file *file, const char __user *buffer, ...@@ -273,12 +279,12 @@ write_rio(struct file *file, const char __user *buffer,
int errn = 0; int errn = 0;
int intr; int intr;
intr = mutex_lock_interruptible(&rio500_mutex); intr = mutex_lock_interruptible(&(rio->lock));
if (intr) if (intr)
return -EINTR; return -EINTR;
/* Sanity check to make sure rio is connected, powered, etc */ /* Sanity check to make sure rio is connected, powered, etc */
if (rio->present == 0 || rio->rio_dev == NULL) { if (rio->present == 0 || rio->rio_dev == NULL) {
mutex_unlock(&rio500_mutex); mutex_unlock(&(rio->lock));
return -ENODEV; return -ENODEV;
} }
...@@ -301,7 +307,7 @@ write_rio(struct file *file, const char __user *buffer, ...@@ -301,7 +307,7 @@ write_rio(struct file *file, const char __user *buffer,
goto error; goto error;
} }
if (signal_pending(current)) { if (signal_pending(current)) {
mutex_unlock(&rio500_mutex); mutex_unlock(&(rio->lock));
return bytes_written ? bytes_written : -EINTR; return bytes_written ? bytes_written : -EINTR;
} }
...@@ -339,12 +345,12 @@ write_rio(struct file *file, const char __user *buffer, ...@@ -339,12 +345,12 @@ write_rio(struct file *file, const char __user *buffer,
buffer += copy_size; buffer += copy_size;
} while (count > 0); } while (count > 0);
mutex_unlock(&rio500_mutex); mutex_unlock(&(rio->lock));
return bytes_written ? bytes_written : -EIO; return bytes_written ? bytes_written : -EIO;
error: error:
mutex_unlock(&rio500_mutex); mutex_unlock(&(rio->lock));
return errn; return errn;
} }
...@@ -361,12 +367,12 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) ...@@ -361,12 +367,12 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
char *ibuf; char *ibuf;
int intr; int intr;
intr = mutex_lock_interruptible(&rio500_mutex); intr = mutex_lock_interruptible(&(rio->lock));
if (intr) if (intr)
return -EINTR; return -EINTR;
/* Sanity check to make sure rio is connected, powered, etc */ /* Sanity check to make sure rio is connected, powered, etc */
if (rio->present == 0 || rio->rio_dev == NULL) { if (rio->present == 0 || rio->rio_dev == NULL) {
mutex_unlock(&rio500_mutex); mutex_unlock(&(rio->lock));
return -ENODEV; return -ENODEV;
} }
...@@ -377,11 +383,11 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) ...@@ -377,11 +383,11 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
while (count > 0) { while (count > 0) {
if (signal_pending(current)) { if (signal_pending(current)) {
mutex_unlock(&rio500_mutex); mutex_unlock(&(rio->lock));
return read_count ? read_count : -EINTR; return read_count ? read_count : -EINTR;
} }
if (!rio->rio_dev) { if (!rio->rio_dev) {
mutex_unlock(&rio500_mutex); mutex_unlock(&(rio->lock));
return -ENODEV; return -ENODEV;
} }
this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count; this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
...@@ -399,7 +405,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) ...@@ -399,7 +405,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
count = this_read = partial; count = this_read = partial;
} else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */ } else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */
if (!maxretry--) { if (!maxretry--) {
mutex_unlock(&rio500_mutex); mutex_unlock(&(rio->lock));
dev_err(&rio->rio_dev->dev, dev_err(&rio->rio_dev->dev,
"read_rio: maxretry timeout\n"); "read_rio: maxretry timeout\n");
return -ETIME; return -ETIME;
...@@ -409,19 +415,19 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) ...@@ -409,19 +415,19 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
finish_wait(&rio->wait_q, &wait); finish_wait(&rio->wait_q, &wait);
continue; continue;
} else if (result != -EREMOTEIO) { } else if (result != -EREMOTEIO) {
mutex_unlock(&rio500_mutex); mutex_unlock(&(rio->lock));
dev_err(&rio->rio_dev->dev, dev_err(&rio->rio_dev->dev,
"Read Whoops - result:%d partial:%u this_read:%u\n", "Read Whoops - result:%d partial:%u this_read:%u\n",
result, partial, this_read); result, partial, this_read);
return -EIO; return -EIO;
} else { } else {
mutex_unlock(&rio500_mutex); mutex_unlock(&(rio->lock));
return (0); return (0);
} }
if (this_read) { if (this_read) {
if (copy_to_user(buffer, ibuf, this_read)) { if (copy_to_user(buffer, ibuf, this_read)) {
mutex_unlock(&rio500_mutex); mutex_unlock(&(rio->lock));
return -EFAULT; return -EFAULT;
} }
count -= this_read; count -= this_read;
...@@ -429,7 +435,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) ...@@ -429,7 +435,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
buffer += this_read; buffer += this_read;
} }
} }
mutex_unlock(&rio500_mutex); mutex_unlock(&(rio->lock));
return read_count; return read_count;
} }
...@@ -494,6 +500,8 @@ static int probe_rio(struct usb_interface *intf, ...@@ -494,6 +500,8 @@ static int probe_rio(struct usb_interface *intf,
} }
dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf); dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf);
mutex_init(&(rio->lock));
usb_set_intfdata (intf, rio); usb_set_intfdata (intf, rio);
rio->present = 1; rio->present = 1;
bail_out: bail_out:
...@@ -511,10 +519,12 @@ static void disconnect_rio(struct usb_interface *intf) ...@@ -511,10 +519,12 @@ static void disconnect_rio(struct usb_interface *intf)
if (rio) { if (rio) {
usb_deregister_dev(intf, &usb_rio_class); usb_deregister_dev(intf, &usb_rio_class);
mutex_lock(&(rio->lock));
if (rio->isopen) { if (rio->isopen) {
rio->isopen = 0; rio->isopen = 0;
/* better let it finish - the release will do whats needed */ /* better let it finish - the release will do whats needed */
rio->rio_dev = NULL; rio->rio_dev = NULL;
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex); mutex_unlock(&rio500_mutex);
return; return;
} }
...@@ -524,6 +534,7 @@ static void disconnect_rio(struct usb_interface *intf) ...@@ -524,6 +534,7 @@ static void disconnect_rio(struct usb_interface *intf)
dev_info(&intf->dev, "USB Rio disconnected.\n"); dev_info(&intf->dev, "USB Rio disconnected.\n");
rio->present = 0; rio->present = 0;
mutex_unlock(&(rio->lock));
} }
mutex_unlock(&rio500_mutex); mutex_unlock(&rio500_mutex);
} }
......
...@@ -92,7 +92,6 @@ static void yurex_delete(struct kref *kref) ...@@ -92,7 +92,6 @@ static void yurex_delete(struct kref *kref)
dev_dbg(&dev->interface->dev, "%s\n", __func__); dev_dbg(&dev->interface->dev, "%s\n", __func__);
usb_put_dev(dev->udev);
if (dev->cntl_urb) { if (dev->cntl_urb) {
usb_kill_urb(dev->cntl_urb); usb_kill_urb(dev->cntl_urb);
kfree(dev->cntl_req); kfree(dev->cntl_req);
...@@ -108,6 +107,7 @@ static void yurex_delete(struct kref *kref) ...@@ -108,6 +107,7 @@ static void yurex_delete(struct kref *kref)
dev->int_buffer, dev->urb->transfer_dma); dev->int_buffer, dev->urb->transfer_dma);
usb_free_urb(dev->urb); usb_free_urb(dev->urb);
} }
usb_put_dev(dev->udev);
kfree(dev); kfree(dev);
} }
......
...@@ -379,7 +379,8 @@ static enum tcpm_state tcpm_default_state(struct tcpm_port *port) ...@@ -379,7 +379,8 @@ static enum tcpm_state tcpm_default_state(struct tcpm_port *port)
return SNK_UNATTACHED; return SNK_UNATTACHED;
else if (port->try_role == TYPEC_SOURCE) else if (port->try_role == TYPEC_SOURCE)
return SRC_UNATTACHED; return SRC_UNATTACHED;
else if (port->tcpc->config->default_role == TYPEC_SINK) else if (port->tcpc->config &&
port->tcpc->config->default_role == TYPEC_SINK)
return SNK_UNATTACHED; return SNK_UNATTACHED;
/* Fall through to return SRC_UNATTACHED */ /* Fall through to return SRC_UNATTACHED */
} else if (port->port_type == TYPEC_PORT_SNK) { } else if (port->port_type == TYPEC_PORT_SNK) {
...@@ -586,7 +587,20 @@ static void tcpm_debugfs_init(struct tcpm_port *port) ...@@ -586,7 +587,20 @@ static void tcpm_debugfs_init(struct tcpm_port *port)
static void tcpm_debugfs_exit(struct tcpm_port *port) static void tcpm_debugfs_exit(struct tcpm_port *port)
{ {
int i;
mutex_lock(&port->logbuffer_lock);
for (i = 0; i < LOG_BUFFER_ENTRIES; i++) {
kfree(port->logbuffer[i]);
port->logbuffer[i] = NULL;
}
mutex_unlock(&port->logbuffer_lock);
debugfs_remove(port->dentry); debugfs_remove(port->dentry);
if (list_empty(&rootdir->d_subdirs)) {
debugfs_remove(rootdir);
rootdir = NULL;
}
} }
#else #else
...@@ -1095,6 +1109,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt, ...@@ -1095,6 +1109,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
break; break;
case CMD_ATTENTION: case CMD_ATTENTION:
/* Attention command does not have response */ /* Attention command does not have response */
if (adev)
typec_altmode_attention(adev, p[1]); typec_altmode_attention(adev, p[1]);
return 0; return 0;
default: default:
...@@ -1147,20 +1162,26 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt, ...@@ -1147,20 +1162,26 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
} }
break; break;
case CMD_ENTER_MODE: case CMD_ENTER_MODE:
if (adev && pdev) {
typec_altmode_update_active(pdev, true); typec_altmode_update_active(pdev, true);
if (typec_altmode_vdm(adev, p[0], &p[1], cnt)) { if (typec_altmode_vdm(adev, p[0], &p[1], cnt)) {
response[0] = VDO(adev->svid, 1, CMD_EXIT_MODE); response[0] = VDO(adev->svid, 1,
CMD_EXIT_MODE);
response[0] |= VDO_OPOS(adev->mode); response[0] |= VDO_OPOS(adev->mode);
return 1; return 1;
} }
}
return 0; return 0;
case CMD_EXIT_MODE: case CMD_EXIT_MODE:
if (adev && pdev) {
typec_altmode_update_active(pdev, false); typec_altmode_update_active(pdev, false);
/* Back to USB Operation */ /* Back to USB Operation */
WARN_ON(typec_altmode_notify(adev, TYPEC_STATE_USB, WARN_ON(typec_altmode_notify(adev,
TYPEC_STATE_USB,
NULL)); NULL));
}
break; break;
default: default:
break; break;
...@@ -1170,7 +1191,9 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt, ...@@ -1170,7 +1191,9 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
switch (cmd) { switch (cmd) {
case CMD_ENTER_MODE: case CMD_ENTER_MODE:
/* Back to USB Operation */ /* Back to USB Operation */
WARN_ON(typec_altmode_notify(adev, TYPEC_STATE_USB, if (adev)
WARN_ON(typec_altmode_notify(adev,
TYPEC_STATE_USB,
NULL)); NULL));
break; break;
default: default:
...@@ -1182,6 +1205,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt, ...@@ -1182,6 +1205,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
} }
/* Informing the alternate mode drivers about everything */ /* Informing the alternate mode drivers about everything */
if (adev)
typec_altmode_vdm(adev, p[0], &p[1], cnt); typec_altmode_vdm(adev, p[0], &p[1], cnt);
return rlen; return rlen;
...@@ -4114,7 +4138,7 @@ static int tcpm_try_role(const struct typec_capability *cap, int role) ...@@ -4114,7 +4138,7 @@ static int tcpm_try_role(const struct typec_capability *cap, int role)
mutex_lock(&port->lock); mutex_lock(&port->lock);
if (tcpc->try_role) if (tcpc->try_role)
ret = tcpc->try_role(tcpc, role); ret = tcpc->try_role(tcpc, role);
if (!ret && !tcpc->config->try_role_hw) if (!ret && (!tcpc->config || !tcpc->config->try_role_hw))
port->try_role = role; port->try_role = role;
port->try_src_count = 0; port->try_src_count = 0;
port->try_snk_count = 0; port->try_snk_count = 0;
...@@ -4701,7 +4725,7 @@ static int tcpm_copy_caps(struct tcpm_port *port, ...@@ -4701,7 +4725,7 @@ static int tcpm_copy_caps(struct tcpm_port *port,
port->typec_caps.prefer_role = tcfg->default_role; port->typec_caps.prefer_role = tcfg->default_role;
port->typec_caps.type = tcfg->type; port->typec_caps.type = tcfg->type;
port->typec_caps.data = tcfg->data; port->typec_caps.data = tcfg->data;
port->self_powered = port->tcpc->config->self_powered; port->self_powered = tcfg->self_powered;
return 0; return 0;
} }
......
...@@ -1018,7 +1018,7 @@ static int do_flash(struct ucsi_ccg *uc, enum enum_flash_mode mode) ...@@ -1018,7 +1018,7 @@ static int do_flash(struct ucsi_ccg *uc, enum enum_flash_mode mode)
******************************************************************************/ ******************************************************************************/
static int ccg_fw_update(struct ucsi_ccg *uc, enum enum_flash_mode flash_mode) static int ccg_fw_update(struct ucsi_ccg *uc, enum enum_flash_mode flash_mode)
{ {
int err; int err = 0;
while (flash_mode != FLASH_NOT_NEEDED) { while (flash_mode != FLASH_NOT_NEEDED) {
err = do_flash(uc, flash_mode); err = do_flash(uc, flash_mode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment