Commit 445e09e7 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 12a0cf72 bc2f3e4c
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -347,7 +347,7 @@ static int tb_retimer_add(struct tb_port *port, u8 index, u32 auth_status)
	ret = tb_retimer_nvm_add(rt);
	ret = tb_retimer_nvm_add(rt);
	if (ret) {
	if (ret) {
		dev_err(&rt->dev, "failed to add NVM devices: %d\n", ret);
		dev_err(&rt->dev, "failed to add NVM devices: %d\n", ret);
		device_del(&rt->dev);
		device_unregister(&rt->dev);
		return ret;
		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)
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;
	int ret, i, last_idx = 0;


	if (!port->cap_usb4)
	if (!port->cap_usb4)
+4 −0
Original line number Original line Diff line number Diff line
@@ -1128,6 +1128,10 @@ static int cdnsp_gadget_ep_dequeue(struct usb_ep *ep,
		return -ESHUTDOWN;
		return -ESHUTDOWN;
	}
	}


	/* Requests has been dequeued during disabling endpoint. */
	if (!(pep->ep_state & EP_ENABLED))
		return 0;

	spin_lock_irqsave(&pdev->lock, flags);
	spin_lock_irqsave(&pdev->lock, flags);
	ret = cdnsp_ep_dequeue(pep, to_cdnsp_request(request));
	ret = cdnsp_ep_dequeue(pep, to_cdnsp_request(request));
	spin_unlock_irqrestore(&pdev->lock, flags);
	spin_unlock_irqrestore(&pdev->lock, flags);
+9 −2
Original line number Original line Diff line number Diff line
@@ -63,6 +63,7 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a


		dev_info(dev, "stub up\n");
		dev_info(dev, "stub up\n");


		mutex_lock(&sdev->ud.sysfs_lock);
		spin_lock_irq(&sdev->ud.lock);
		spin_lock_irq(&sdev->ud.lock);


		if (sdev->ud.status != SDEV_ST_AVAILABLE) {
		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");
		tcp_rx = kthread_create(stub_rx_loop, &sdev->ud, "stub_rx");
		if (IS_ERR(tcp_rx)) {
		if (IS_ERR(tcp_rx)) {
			sockfd_put(socket);
			sockfd_put(socket);
			return -EINVAL;
			goto unlock_mutex;
		}
		}
		tcp_tx = kthread_create(stub_tx_loop, &sdev->ud, "stub_tx");
		tcp_tx = kthread_create(stub_tx_loop, &sdev->ud, "stub_tx");
		if (IS_ERR(tcp_tx)) {
		if (IS_ERR(tcp_tx)) {
			kthread_stop(tcp_rx);
			kthread_stop(tcp_rx);
			sockfd_put(socket);
			sockfd_put(socket);
			return -EINVAL;
			goto unlock_mutex;
		}
		}


		/* get task structs now */
		/* 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_rx);
		wake_up_process(sdev->ud.tcp_tx);
		wake_up_process(sdev->ud.tcp_tx);


		mutex_unlock(&sdev->ud.sysfs_lock);

	} else {
	} else {
		dev_info(dev, "stub down\n");
		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);
		spin_unlock_irq(&sdev->ud.lock);


		usbip_event_add(&sdev->ud, SDEV_EVENT_DOWN);
		usbip_event_add(&sdev->ud, SDEV_EVENT_DOWN);
		mutex_unlock(&sdev->ud.sysfs_lock);
	}
	}


	return count;
	return count;
@@ -130,6 +134,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
	sockfd_put(socket);
	sockfd_put(socket);
err:
err:
	spin_unlock_irq(&sdev->ud.lock);
	spin_unlock_irq(&sdev->ud.lock);
unlock_mutex:
	mutex_unlock(&sdev->ud.sysfs_lock);
	return -EINVAL;
	return -EINVAL;
}
}
static DEVICE_ATTR_WO(usbip_sockfd);
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.side		= USBIP_STUB;
	sdev->ud.status		= SDEV_ST_AVAILABLE;
	sdev->ud.status		= SDEV_ST_AVAILABLE;
	spin_lock_init(&sdev->ud.lock);
	spin_lock_init(&sdev->ud.lock);
	mutex_init(&sdev->ud.sysfs_lock);
	sdev->ud.tcp_socket	= NULL;
	sdev->ud.tcp_socket	= NULL;
	sdev->ud.sockfd		= -1;
	sdev->ud.sockfd		= -1;


+3 −0
Original line number Original line Diff line number Diff line
@@ -263,6 +263,9 @@ struct usbip_device {
	/* lock for status */
	/* lock for status */
	spinlock_t lock;
	spinlock_t lock;


	/* mutex for synchronizing sysfs store paths */
	struct mutex sysfs_lock;

	int sockfd;
	int sockfd;
	struct socket *tcp_socket;
	struct socket *tcp_socket;


+2 −0
Original line number Original line Diff line number Diff line
@@ -70,6 +70,7 @@ static void event_handler(struct work_struct *work)
	while ((ud = get_event()) != NULL) {
	while ((ud = get_event()) != NULL) {
		usbip_dbg_eh("pending event %lx\n", ud->event);
		usbip_dbg_eh("pending event %lx\n", ud->event);


		mutex_lock(&ud->sysfs_lock);
		/*
		/*
		 * NOTE: shutdown must come first.
		 * NOTE: shutdown must come first.
		 * Shutdown the device.
		 * Shutdown the device.
@@ -90,6 +91,7 @@ static void event_handler(struct work_struct *work)
			ud->eh_ops.unusable(ud);
			ud->eh_ops.unusable(ud);
			unset_event(ud, USBIP_EH_UNUSABLE);
			unset_event(ud, USBIP_EH_UNUSABLE);
		}
		}
		mutex_unlock(&ud->sysfs_lock);


		wake_up(&ud->eh_waitq);
		wake_up(&ud->eh_waitq);
	}
	}
Loading