Skip to content

Commit

Permalink
USB: convert usb_hcd bitfields into atomic flags
Browse files Browse the repository at this point in the history
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: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Aug 10, 2010
1 parent 89ba85d commit 541c7d4
Show file tree
Hide file tree
Showing 21 changed files with 80 additions and 73 deletions.
6 changes: 3 additions & 3 deletions drivers/staging/usbip/vhci_hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;

/*
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions drivers/usb/c67x00/c67x00-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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;
}
Expand Down
26 changes: 12 additions & 14 deletions drivers/usb/core/hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
}
Expand All @@ -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));
}
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;

Expand All @@ -2320,11 +2318,11 @@ int usb_add_hcd(struct usb_hcd *hcd,
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)
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions drivers/usb/gadget/dummy_hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/host/ehci-dbg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 0 additions & 1 deletion drivers/usb/host/ehci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,6 @@ static int ehci_run (struct usb_hcd *hcd)
u32 hcc_params;

hcd->uses_new_polling = 1;
hcd->poll_rh = 0;

/* EHCI spec section 4.1 */
if ((retval = ehci_reset(ehci)) != 0) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/host/ehci-hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
if (time_before (jiffies, ehci->next_statechange))
msleep(5);
spin_lock_irq (&ehci->lock);
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
if (!HCD_HW_ACCESSIBLE(hcd)) {
spin_unlock_irq(&ehci->lock);
return -ESHUTDOWN;
}
Expand Down
3 changes: 1 addition & 2 deletions drivers/usb/host/ehci-q.c
Original file line number Diff line number Diff line change
Expand Up @@ -1126,8 +1126,7 @@ submit_async (
#endif

spin_lock_irqsave (&ehci->lock, flags);
if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
&ehci_to_hcd(ehci)->flags))) {
if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) {
rc = -ESHUTDOWN;
goto done;
}
Expand Down
9 changes: 3 additions & 6 deletions drivers/usb/host/ehci-sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -880,8 +880,7 @@ static int intr_submit (

spin_lock_irqsave (&ehci->lock, flags);

if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
&ehci_to_hcd(ehci)->flags))) {
if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) {
status = -ESHUTDOWN;
goto done_not_linked;
}
Expand Down Expand Up @@ -1815,8 +1814,7 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,

/* schedule ... need to lock */
spin_lock_irqsave (&ehci->lock, flags);
if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
&ehci_to_hcd(ehci)->flags))) {
if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) {
status = -ESHUTDOWN;
goto done_not_linked;
}
Expand Down Expand Up @@ -2201,8 +2199,7 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,

/* schedule ... need to lock */
spin_lock_irqsave (&ehci->lock, flags);
if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
&ehci_to_hcd(ehci)->flags))) {
if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) {
status = -ESHUTDOWN;
goto done_not_linked;
}
Expand Down
4 changes: 2 additions & 2 deletions drivers/usb/host/hwa-hc.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ static int hwahc_op_start(struct usb_hcd *usb_hcd)
goto error_set_cluster_id;

usb_hcd->uses_new_polling = 1;
usb_hcd->poll_rh = 1;
set_bit(HCD_FLAG_POLL_RH, &usb_hcd->flags);
usb_hcd->state = HC_STATE_RUNNING;
result = 0;
out:
Expand Down Expand Up @@ -776,7 +776,7 @@ static int hwahc_probe(struct usb_interface *usb_iface,
goto error_alloc;
}
usb_hcd->wireless = 1;
usb_hcd->flags |= HCD_FLAG_SAW_IRQ;
set_bit(HCD_FLAG_SAW_IRQ, &usb_hcd->flags);
wusbhc = usb_hcd_to_wusbhc(usb_hcd);
hwahc = container_of(wusbhc, struct hwahc, wusbhc);
hwahc_init(hwahc);
Expand Down
3 changes: 1 addition & 2 deletions drivers/usb/host/isp1760-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,6 @@ static int isp1760_run(struct usb_hcd *hcd)
u32 chipid;

hcd->uses_new_polling = 1;
hcd->poll_rh = 0;

hcd->state = HC_STATE_RUNNING;
isp1760_enable_interrupts(hcd);
Expand Down Expand Up @@ -1450,7 +1449,7 @@ static int isp1760_prepare_enqueue(struct isp1760_hcd *priv, struct urb *urb,
epnum = urb->ep->desc.bEndpointAddress;

spin_lock_irqsave(&priv->lock, flags);
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &priv_to_hcd(priv)->flags)) {
if (!HCD_HW_ACCESSIBLE(priv_to_hcd(priv))) {
rc = -ESHUTDOWN;
goto done;
}
Expand Down
4 changes: 2 additions & 2 deletions drivers/usb/host/ohci-dbg.c
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
hcd->product_desc,
hcd_name);

if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
if (!HCD_HW_ACCESSIBLE(hcd)) {
size -= scnprintf (next, size,
"SUSPENDED (no register access)\n");
goto done;
Expand Down Expand Up @@ -687,7 +687,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
next += temp;

temp = scnprintf (next, size, "hub poll timer %s\n",
ohci_to_hcd(ohci)->poll_rh ? "ON" : "off");
HCD_POLL_RH(ohci_to_hcd(ohci)) ? "ON" : "off");
size -= temp;
next += temp;

Expand Down
6 changes: 3 additions & 3 deletions drivers/usb/host/ohci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ static int ohci_urb_enqueue (
spin_lock_irqsave (&ohci->lock, flags);

/* don't submit to a dead HC */
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
if (!HCD_HW_ACCESSIBLE(hcd)) {
retval = -ENODEV;
goto fail;
}
Expand Down Expand Up @@ -685,7 +685,7 @@ static int ohci_run (struct ohci_hcd *ohci)
}

/* use rhsc irqs after khubd is fully initialized */
hcd->poll_rh = 1;
set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
hcd->uses_new_polling = 1;

/* start controller operations */
Expand Down Expand Up @@ -822,7 +822,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
else if (ints & OHCI_INTR_RD) {
ohci_vdbg(ohci, "resume detect\n");
ohci_writel(ohci, OHCI_INTR_RD, &regs->intrstatus);
hcd->poll_rh = 1;
set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
if (ohci->autostop) {
spin_lock (&ohci->lock);
ohci_rh_resume (ohci);
Expand Down
16 changes: 10 additions & 6 deletions drivers/usb/host/ohci-hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)

spin_lock_irq (&ohci->lock);

if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
if (unlikely(!HCD_HW_ACCESSIBLE(hcd)))
rc = -ESHUTDOWN;
else
rc = ohci_rh_suspend (ohci, 0);
Expand All @@ -302,7 +302,7 @@ static int ohci_bus_resume (struct usb_hcd *hcd)

spin_lock_irq (&ohci->lock);

if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
if (unlikely(!HCD_HW_ACCESSIBLE(hcd)))
rc = -ESHUTDOWN;
else
rc = ohci_rh_resume (ohci);
Expand Down Expand Up @@ -489,7 +489,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
unsigned long flags;

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

/* undocumented erratum seen on at least rev D */
Expand Down Expand Up @@ -533,8 +533,12 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
}
}

hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed,
any_connected, rhsc_status);
if (ohci_root_hub_state_changes(ohci, changed,
any_connected, rhsc_status))
set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
else
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);


done:
spin_unlock_irqrestore (&ohci->lock, flags);
Expand Down Expand Up @@ -701,7 +705,7 @@ static int ohci_hub_control (
u32 temp;
int retval = 0;

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

switch (typeReq) {
Expand Down
Loading

0 comments on commit 541c7d4

Please sign in to comment.