Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 541c7d43 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman
Browse files

USB: convert usb_hcd bitfields into atomic flags



This patch (as1393) converts several of the single-bit fields in
struct usb_hcd to atomic flags.  This is for safety's sake; not all
CPUs can update bitfield values atomically, and these flags are used
in multiple contexts.

The flag fields that are set only during registration or removal can
remain as they are, since non-atomic accesses at those times will not
cause any problems.

(Strictly speaking, the authorized_default flag should become atomic
as well.  I didn't bother with it because it gets changed only via
sysfs.  It can be done later, if anyone wants.)

Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 89ba85d4
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -215,7 +215,7 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf)
	vhci = hcd_to_vhci(hcd);

	spin_lock_irqsave(&vhci->lock, flags);
	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
	if (!HCD_HW_ACCESSIBLE(hcd)) {
		usbip_dbg_vhci_rh("hw accessible flag in on?\n");
		goto done;
	}
@@ -269,7 +269,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,

	u32 prev_port_status[VHCI_NPORTS];

	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
	if (!HCD_HW_ACCESSIBLE(hcd))
		return -ETIMEDOUT;

	/*
@@ -1041,7 +1041,7 @@ static int vhci_bus_resume(struct usb_hcd *hcd)
	dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);

	spin_lock_irq(&vhci->lock);
	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
	if (!HCD_HW_ACCESSIBLE(hcd)) {
		rc = -ESHUTDOWN;
	} else {
		/* vhci->rh_state = DUMMY_RH_RUNNING;
+2 −2
Original line number Diff line number Diff line
@@ -264,7 +264,7 @@ static void c67x00_hcd_irq(struct c67x00_sie *sie, u16 int_status, u16 msg)
	if (unlikely(hcd->state == HC_STATE_HALT))
		return;

	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
	if (!HCD_HW_ACCESSIBLE(hcd))
		return;

	/* Handle Start of frame events */
@@ -282,7 +282,7 @@ static int c67x00_hcd_start(struct usb_hcd *hcd)
{
	hcd->uses_new_polling = 1;
	hcd->state = HC_STATE_RUNNING;
	hcd->poll_rh = 1;
	set_bit(HCD_FLAG_POLL_RH, &hcd->flags);

	return 0;
}
+12 −14
Original line number Diff line number Diff line
@@ -679,7 +679,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
		spin_lock_irqsave(&hcd_root_hub_lock, flags);
		urb = hcd->status_urb;
		if (urb) {
			hcd->poll_pending = 0;
			clear_bit(HCD_FLAG_POLL_PENDING, &hcd->flags);
			hcd->status_urb = NULL;
			urb->actual_length = length;
			memcpy(urb->transfer_buffer, buffer, length);
@@ -690,7 +690,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
			spin_lock(&hcd_root_hub_lock);
		} else {
			length = 0;
			hcd->poll_pending = 1;
			set_bit(HCD_FLAG_POLL_PENDING, &hcd->flags);
		}
		spin_unlock_irqrestore(&hcd_root_hub_lock, flags);
	}
@@ -699,7 +699,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
	 * exceed that limit if HZ is 100. The math is more clunky than
	 * maybe expected, this is to make sure that all timers for USB devices
	 * fire at the same time to give the CPU a break inbetween */
	if (hcd->uses_new_polling ? hcd->poll_rh :
	if (hcd->uses_new_polling ? HCD_POLL_RH(hcd) :
			(length == 0 && hcd->status_urb != NULL))
		mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4));
}
@@ -736,7 +736,7 @@ static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb)
		mod_timer(&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4));

	/* If a status change has already occurred, report it ASAP */
	else if (hcd->poll_pending)
	else if (HCD_POLL_PENDING(hcd))
		mod_timer(&hcd->rh_timer, jiffies);
	retval = 0;
 done:
@@ -1150,8 +1150,7 @@ int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
	 * finish unlinking the initial failed usb_set_address()
	 * or device descriptor fetch.
	 */
	if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) &&
			!is_root_hub(urb->dev)) {
	if (!HCD_SAW_IRQ(hcd) && !is_root_hub(urb->dev)) {
		dev_warn(hcd->self.controller, "Unlink after no-IRQ?  "
			"Controller is probably using the wrong IRQ.\n");
		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
@@ -2063,8 +2062,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
	 */
	local_irq_save(flags);

	if (unlikely(hcd->state == HC_STATE_HALT ||
		     !test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
	if (unlikely(hcd->state == HC_STATE_HALT || !HCD_HW_ACCESSIBLE(hcd))) {
		rc = IRQ_NONE;
	} else if (hcd->driver->irq(hcd) == IRQ_NONE) {
		rc = IRQ_NONE;
@@ -2098,7 +2096,7 @@ void usb_hc_died (struct usb_hcd *hcd)

	spin_lock_irqsave (&hcd_root_hub_lock, flags);
	if (hcd->rh_registered) {
		hcd->poll_rh = 0;
		clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);

		/* make khubd clean up old urbs and devices */
		usb_set_device_state (hcd->self.root_hub,
@@ -2301,7 +2299,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
		       retval);
		goto error_create_attr_group;
	}
	if (hcd->uses_new_polling && hcd->poll_rh)
	if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
		usb_hcd_poll_rh_status(hcd);
	return retval;

@@ -2320,11 +2318,11 @@ error_create_attr_group:
	mutex_unlock(&usb_bus_list_lock);
err_register_root_hub:
	hcd->rh_pollable = 0;
	hcd->poll_rh = 0;
	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
	del_timer_sync(&hcd->rh_timer);
	hcd->driver->stop(hcd);
	hcd->state = HC_STATE_HALT;
	hcd->poll_rh = 0;
	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
	del_timer_sync(&hcd->rh_timer);
err_hcd_driver_start:
	if (hcd->irq >= 0)
@@ -2380,14 +2378,14 @@ void usb_remove_hcd(struct usb_hcd *hcd)
	 * the hub_status_data() callback.
	 */
	hcd->rh_pollable = 0;
	hcd->poll_rh = 0;
	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
	del_timer_sync(&hcd->rh_timer);

	hcd->driver->stop(hcd);
	hcd->state = HC_STATE_HALT;

	/* In case the HCD restarted the timer, stop it again. */
	hcd->poll_rh = 0;
	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
	del_timer_sync(&hcd->rh_timer);

	if (hcd->irq >= 0)
+3 −3
Original line number Diff line number Diff line
@@ -1542,7 +1542,7 @@ static int dummy_hub_status (struct usb_hcd *hcd, char *buf)
	dum = hcd_to_dummy (hcd);

	spin_lock_irqsave (&dum->lock, flags);
	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
	if (!HCD_HW_ACCESSIBLE(hcd))
		goto done;

	if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) {
@@ -1588,7 +1588,7 @@ static int dummy_hub_control (
	int		retval = 0;
	unsigned long	flags;

	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
	if (!HCD_HW_ACCESSIBLE(hcd))
		return -ETIMEDOUT;

	dum = hcd_to_dummy (hcd);
@@ -1739,7 +1739,7 @@ static int dummy_bus_resume (struct usb_hcd *hcd)
	dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__);

	spin_lock_irq (&dum->lock);
	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
	if (!HCD_HW_ACCESSIBLE(hcd)) {
		rc = -ESHUTDOWN;
	} else {
		dum->rh_state = DUMMY_RH_RUNNING;
+1 −1
Original line number Diff line number Diff line
@@ -712,7 +712,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)

	spin_lock_irqsave (&ehci->lock, flags);

	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
	if (!HCD_HW_ACCESSIBLE(hcd)) {
		size = scnprintf (next, size,
			"bus %s, device %s\n"
			"%s\n"
Loading