forked from Minki/linux
USB/Thunderbolt fixes for 5.12-rc7
Here are a few small USB and Thunderbolt driver fixes for 5.12-rc7 for reported issues: - thunderbolt leaks and off-by-one fix - cdnsp deque fix - usbip fixes for syzbot-reported issues. all have been in linux-next with no reported problems. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCYHGiGA8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ynSDgCfa1jQ40rNFkf749XtvgbYGmjCfSwAoKPc4A7N 2Fc6WE1+fDR1l9JfERJ7 =qk3Z -----END PGP SIGNATURE----- Merge tag 'usb-5.12-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB/Thunderbolt fixes from Greg KH: "Here are a few small USB and Thunderbolt driver fixes for 5.12-rc7 for reported issues: - thunderbolt leaks and off-by-one fix - cdnsp deque fix - usbip fixes for syzbot-reported issues All have been in linux-next with no reported problems" * tag 'usb-5.12-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: usbip: synchronize event handler with sysfs code paths usbip: vudc synchronize sysfs code paths usbip: stub-dev synchronize sysfs code paths usbip: add sysfs_lock to synchronize sysfs code paths thunderbolt: Fix off by one in tb_port_find_retimer() thunderbolt: Fix a leak in tb_retimer_add() usb: cdnsp: Fixes issue with dequeuing requests after disabling endpoint
This commit is contained in:
commit
445e09e797
@ -347,7 +347,7 @@ static int tb_retimer_add(struct tb_port *port, u8 index, u32 auth_status)
|
||||
ret = tb_retimer_nvm_add(rt);
|
||||
if (ret) {
|
||||
dev_err(&rt->dev, "failed to add NVM devices: %d\n", ret);
|
||||
device_del(&rt->dev);
|
||||
device_unregister(&rt->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -406,7 +406,7 @@ static struct tb_retimer *tb_port_find_retimer(struct tb_port *port, u8 index)
|
||||
*/
|
||||
int tb_retimer_scan(struct tb_port *port)
|
||||
{
|
||||
u32 status[TB_MAX_RETIMER_INDEX] = {};
|
||||
u32 status[TB_MAX_RETIMER_INDEX + 1] = {};
|
||||
int ret, i, last_idx = 0;
|
||||
|
||||
if (!port->cap_usb4)
|
||||
|
@ -1128,6 +1128,10 @@ static int cdnsp_gadget_ep_dequeue(struct usb_ep *ep,
|
||||
return -ESHUTDOWN;
|
||||
}
|
||||
|
||||
/* Requests has been dequeued during disabling endpoint. */
|
||||
if (!(pep->ep_state & EP_ENABLED))
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&pdev->lock, flags);
|
||||
ret = cdnsp_ep_dequeue(pep, to_cdnsp_request(request));
|
||||
spin_unlock_irqrestore(&pdev->lock, flags);
|
||||
|
@ -63,6 +63,7 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
|
||||
|
||||
dev_info(dev, "stub up\n");
|
||||
|
||||
mutex_lock(&sdev->ud.sysfs_lock);
|
||||
spin_lock_irq(&sdev->ud.lock);
|
||||
|
||||
if (sdev->ud.status != SDEV_ST_AVAILABLE) {
|
||||
@ -87,13 +88,13 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
|
||||
tcp_rx = kthread_create(stub_rx_loop, &sdev->ud, "stub_rx");
|
||||
if (IS_ERR(tcp_rx)) {
|
||||
sockfd_put(socket);
|
||||
return -EINVAL;
|
||||
goto unlock_mutex;
|
||||
}
|
||||
tcp_tx = kthread_create(stub_tx_loop, &sdev->ud, "stub_tx");
|
||||
if (IS_ERR(tcp_tx)) {
|
||||
kthread_stop(tcp_rx);
|
||||
sockfd_put(socket);
|
||||
return -EINVAL;
|
||||
goto unlock_mutex;
|
||||
}
|
||||
|
||||
/* get task structs now */
|
||||
@ -112,6 +113,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
|
||||
wake_up_process(sdev->ud.tcp_rx);
|
||||
wake_up_process(sdev->ud.tcp_tx);
|
||||
|
||||
mutex_unlock(&sdev->ud.sysfs_lock);
|
||||
|
||||
} else {
|
||||
dev_info(dev, "stub down\n");
|
||||
|
||||
@ -122,6 +125,7 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
|
||||
spin_unlock_irq(&sdev->ud.lock);
|
||||
|
||||
usbip_event_add(&sdev->ud, SDEV_EVENT_DOWN);
|
||||
mutex_unlock(&sdev->ud.sysfs_lock);
|
||||
}
|
||||
|
||||
return count;
|
||||
@ -130,6 +134,8 @@ sock_err:
|
||||
sockfd_put(socket);
|
||||
err:
|
||||
spin_unlock_irq(&sdev->ud.lock);
|
||||
unlock_mutex:
|
||||
mutex_unlock(&sdev->ud.sysfs_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
static DEVICE_ATTR_WO(usbip_sockfd);
|
||||
@ -270,6 +276,7 @@ static struct stub_device *stub_device_alloc(struct usb_device *udev)
|
||||
sdev->ud.side = USBIP_STUB;
|
||||
sdev->ud.status = SDEV_ST_AVAILABLE;
|
||||
spin_lock_init(&sdev->ud.lock);
|
||||
mutex_init(&sdev->ud.sysfs_lock);
|
||||
sdev->ud.tcp_socket = NULL;
|
||||
sdev->ud.sockfd = -1;
|
||||
|
||||
|
@ -263,6 +263,9 @@ struct usbip_device {
|
||||
/* lock for status */
|
||||
spinlock_t lock;
|
||||
|
||||
/* mutex for synchronizing sysfs store paths */
|
||||
struct mutex sysfs_lock;
|
||||
|
||||
int sockfd;
|
||||
struct socket *tcp_socket;
|
||||
|
||||
|
@ -70,6 +70,7 @@ static void event_handler(struct work_struct *work)
|
||||
while ((ud = get_event()) != NULL) {
|
||||
usbip_dbg_eh("pending event %lx\n", ud->event);
|
||||
|
||||
mutex_lock(&ud->sysfs_lock);
|
||||
/*
|
||||
* NOTE: shutdown must come first.
|
||||
* Shutdown the device.
|
||||
@ -90,6 +91,7 @@ static void event_handler(struct work_struct *work)
|
||||
ud->eh_ops.unusable(ud);
|
||||
unset_event(ud, USBIP_EH_UNUSABLE);
|
||||
}
|
||||
mutex_unlock(&ud->sysfs_lock);
|
||||
|
||||
wake_up(&ud->eh_waitq);
|
||||
}
|
||||
|
@ -1101,6 +1101,7 @@ static void vhci_device_init(struct vhci_device *vdev)
|
||||
vdev->ud.side = USBIP_VHCI;
|
||||
vdev->ud.status = VDEV_ST_NULL;
|
||||
spin_lock_init(&vdev->ud.lock);
|
||||
mutex_init(&vdev->ud.sysfs_lock);
|
||||
|
||||
INIT_LIST_HEAD(&vdev->priv_rx);
|
||||
INIT_LIST_HEAD(&vdev->priv_tx);
|
||||
|
@ -185,6 +185,8 @@ static int vhci_port_disconnect(struct vhci_hcd *vhci_hcd, __u32 rhport)
|
||||
|
||||
usbip_dbg_vhci_sysfs("enter\n");
|
||||
|
||||
mutex_lock(&vdev->ud.sysfs_lock);
|
||||
|
||||
/* lock */
|
||||
spin_lock_irqsave(&vhci->lock, flags);
|
||||
spin_lock(&vdev->ud.lock);
|
||||
@ -195,6 +197,7 @@ static int vhci_port_disconnect(struct vhci_hcd *vhci_hcd, __u32 rhport)
|
||||
/* unlock */
|
||||
spin_unlock(&vdev->ud.lock);
|
||||
spin_unlock_irqrestore(&vhci->lock, flags);
|
||||
mutex_unlock(&vdev->ud.sysfs_lock);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -205,6 +208,8 @@ static int vhci_port_disconnect(struct vhci_hcd *vhci_hcd, __u32 rhport)
|
||||
|
||||
usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN);
|
||||
|
||||
mutex_unlock(&vdev->ud.sysfs_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -349,30 +354,36 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr,
|
||||
else
|
||||
vdev = &vhci->vhci_hcd_hs->vdev[rhport];
|
||||
|
||||
mutex_lock(&vdev->ud.sysfs_lock);
|
||||
|
||||
/* Extract socket from fd. */
|
||||
socket = sockfd_lookup(sockfd, &err);
|
||||
if (!socket) {
|
||||
dev_err(dev, "failed to lookup sock");
|
||||
return -EINVAL;
|
||||
err = -EINVAL;
|
||||
goto unlock_mutex;
|
||||
}
|
||||
if (socket->type != SOCK_STREAM) {
|
||||
dev_err(dev, "Expecting SOCK_STREAM - found %d",
|
||||
socket->type);
|
||||
sockfd_put(socket);
|
||||
return -EINVAL;
|
||||
err = -EINVAL;
|
||||
goto unlock_mutex;
|
||||
}
|
||||
|
||||
/* create threads before locking */
|
||||
tcp_rx = kthread_create(vhci_rx_loop, &vdev->ud, "vhci_rx");
|
||||
if (IS_ERR(tcp_rx)) {
|
||||
sockfd_put(socket);
|
||||
return -EINVAL;
|
||||
err = -EINVAL;
|
||||
goto unlock_mutex;
|
||||
}
|
||||
tcp_tx = kthread_create(vhci_tx_loop, &vdev->ud, "vhci_tx");
|
||||
if (IS_ERR(tcp_tx)) {
|
||||
kthread_stop(tcp_rx);
|
||||
sockfd_put(socket);
|
||||
return -EINVAL;
|
||||
err = -EINVAL;
|
||||
goto unlock_mutex;
|
||||
}
|
||||
|
||||
/* get task structs now */
|
||||
@ -397,7 +408,8 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr,
|
||||
* Will be retried from userspace
|
||||
* if there's another free port.
|
||||
*/
|
||||
return -EBUSY;
|
||||
err = -EBUSY;
|
||||
goto unlock_mutex;
|
||||
}
|
||||
|
||||
dev_info(dev, "pdev(%u) rhport(%u) sockfd(%d)\n",
|
||||
@ -423,7 +435,15 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr,
|
||||
|
||||
rh_port_connect(vdev, speed);
|
||||
|
||||
dev_info(dev, "Device attached\n");
|
||||
|
||||
mutex_unlock(&vdev->ud.sysfs_lock);
|
||||
|
||||
return count;
|
||||
|
||||
unlock_mutex:
|
||||
mutex_unlock(&vdev->ud.sysfs_lock);
|
||||
return err;
|
||||
}
|
||||
static DEVICE_ATTR_WO(attach);
|
||||
|
||||
|
@ -572,6 +572,7 @@ static int init_vudc_hw(struct vudc *udc)
|
||||
init_waitqueue_head(&udc->tx_waitq);
|
||||
|
||||
spin_lock_init(&ud->lock);
|
||||
mutex_init(&ud->sysfs_lock);
|
||||
ud->status = SDEV_ST_AVAILABLE;
|
||||
ud->side = USBIP_VUDC;
|
||||
|
||||
|
@ -112,6 +112,7 @@ static ssize_t usbip_sockfd_store(struct device *dev,
|
||||
dev_err(dev, "no device");
|
||||
return -ENODEV;
|
||||
}
|
||||
mutex_lock(&udc->ud.sysfs_lock);
|
||||
spin_lock_irqsave(&udc->lock, flags);
|
||||
/* Don't export what we don't have */
|
||||
if (!udc->driver || !udc->pullup) {
|
||||
@ -187,6 +188,8 @@ static ssize_t usbip_sockfd_store(struct device *dev,
|
||||
|
||||
wake_up_process(udc->ud.tcp_rx);
|
||||
wake_up_process(udc->ud.tcp_tx);
|
||||
|
||||
mutex_unlock(&udc->ud.sysfs_lock);
|
||||
return count;
|
||||
|
||||
} else {
|
||||
@ -207,6 +210,7 @@ static ssize_t usbip_sockfd_store(struct device *dev,
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&udc->lock, flags);
|
||||
mutex_unlock(&udc->ud.sysfs_lock);
|
||||
|
||||
return count;
|
||||
|
||||
@ -216,6 +220,7 @@ unlock_ud:
|
||||
spin_unlock_irq(&udc->ud.lock);
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&udc->lock, flags);
|
||||
mutex_unlock(&udc->ud.sysfs_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user