diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2010-06-22 16:39:10 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-10 17:35:37 -0400 |
commit | 541c7d432f76771079e7c295d596ea47cc6a3030 (patch) | |
tree | 9e04330713366d21849cecf0f3fd2f2c1834574d /drivers/usb/core | |
parent | 89ba85d4015b7fa738b35bcc228075c117a9a578 (diff) |
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: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/hcd.c | 26 |
1 files changed, 12 insertions, 14 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 53f14c82ff2e..f2fe7c8e991d 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -679,7 +679,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) | |||
679 | spin_lock_irqsave(&hcd_root_hub_lock, flags); | 679 | spin_lock_irqsave(&hcd_root_hub_lock, flags); |
680 | urb = hcd->status_urb; | 680 | urb = hcd->status_urb; |
681 | if (urb) { | 681 | if (urb) { |
682 | hcd->poll_pending = 0; | 682 | clear_bit(HCD_FLAG_POLL_PENDING, &hcd->flags); |
683 | hcd->status_urb = NULL; | 683 | hcd->status_urb = NULL; |
684 | urb->actual_length = length; | 684 | urb->actual_length = length; |
685 | memcpy(urb->transfer_buffer, buffer, length); | 685 | memcpy(urb->transfer_buffer, buffer, length); |
@@ -690,7 +690,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) | |||
690 | spin_lock(&hcd_root_hub_lock); | 690 | spin_lock(&hcd_root_hub_lock); |
691 | } else { | 691 | } else { |
692 | length = 0; | 692 | length = 0; |
693 | hcd->poll_pending = 1; | 693 | set_bit(HCD_FLAG_POLL_PENDING, &hcd->flags); |
694 | } | 694 | } |
695 | spin_unlock_irqrestore(&hcd_root_hub_lock, flags); | 695 | spin_unlock_irqrestore(&hcd_root_hub_lock, flags); |
696 | } | 696 | } |
@@ -699,7 +699,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) | |||
699 | * exceed that limit if HZ is 100. The math is more clunky than | 699 | * exceed that limit if HZ is 100. The math is more clunky than |
700 | * maybe expected, this is to make sure that all timers for USB devices | 700 | * maybe expected, this is to make sure that all timers for USB devices |
701 | * fire at the same time to give the CPU a break inbetween */ | 701 | * fire at the same time to give the CPU a break inbetween */ |
702 | if (hcd->uses_new_polling ? hcd->poll_rh : | 702 | if (hcd->uses_new_polling ? HCD_POLL_RH(hcd) : |
703 | (length == 0 && hcd->status_urb != NULL)) | 703 | (length == 0 && hcd->status_urb != NULL)) |
704 | mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4)); | 704 | mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4)); |
705 | } | 705 | } |
@@ -736,7 +736,7 @@ static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb) | |||
736 | mod_timer(&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4)); | 736 | mod_timer(&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4)); |
737 | 737 | ||
738 | /* If a status change has already occurred, report it ASAP */ | 738 | /* If a status change has already occurred, report it ASAP */ |
739 | else if (hcd->poll_pending) | 739 | else if (HCD_POLL_PENDING(hcd)) |
740 | mod_timer(&hcd->rh_timer, jiffies); | 740 | mod_timer(&hcd->rh_timer, jiffies); |
741 | retval = 0; | 741 | retval = 0; |
742 | done: | 742 | done: |
@@ -1150,8 +1150,7 @@ int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb, | |||
1150 | * finish unlinking the initial failed usb_set_address() | 1150 | * finish unlinking the initial failed usb_set_address() |
1151 | * or device descriptor fetch. | 1151 | * or device descriptor fetch. |
1152 | */ | 1152 | */ |
1153 | if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) && | 1153 | if (!HCD_SAW_IRQ(hcd) && !is_root_hub(urb->dev)) { |
1154 | !is_root_hub(urb->dev)) { | ||
1155 | dev_warn(hcd->self.controller, "Unlink after no-IRQ? " | 1154 | dev_warn(hcd->self.controller, "Unlink after no-IRQ? " |
1156 | "Controller is probably using the wrong IRQ.\n"); | 1155 | "Controller is probably using the wrong IRQ.\n"); |
1157 | set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); | 1156 | set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); |
@@ -2063,8 +2062,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd) | |||
2063 | */ | 2062 | */ |
2064 | local_irq_save(flags); | 2063 | local_irq_save(flags); |
2065 | 2064 | ||
2066 | if (unlikely(hcd->state == HC_STATE_HALT || | 2065 | if (unlikely(hcd->state == HC_STATE_HALT || !HCD_HW_ACCESSIBLE(hcd))) { |
2067 | !test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) { | ||
2068 | rc = IRQ_NONE; | 2066 | rc = IRQ_NONE; |
2069 | } else if (hcd->driver->irq(hcd) == IRQ_NONE) { | 2067 | } else if (hcd->driver->irq(hcd) == IRQ_NONE) { |
2070 | rc = IRQ_NONE; | 2068 | rc = IRQ_NONE; |
@@ -2098,7 +2096,7 @@ void usb_hc_died (struct usb_hcd *hcd) | |||
2098 | 2096 | ||
2099 | spin_lock_irqsave (&hcd_root_hub_lock, flags); | 2097 | spin_lock_irqsave (&hcd_root_hub_lock, flags); |
2100 | if (hcd->rh_registered) { | 2098 | if (hcd->rh_registered) { |
2101 | hcd->poll_rh = 0; | 2099 | clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); |
2102 | 2100 | ||
2103 | /* make khubd clean up old urbs and devices */ | 2101 | /* make khubd clean up old urbs and devices */ |
2104 | usb_set_device_state (hcd->self.root_hub, | 2102 | usb_set_device_state (hcd->self.root_hub, |
@@ -2301,7 +2299,7 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
2301 | retval); | 2299 | retval); |
2302 | goto error_create_attr_group; | 2300 | goto error_create_attr_group; |
2303 | } | 2301 | } |
2304 | if (hcd->uses_new_polling && hcd->poll_rh) | 2302 | if (hcd->uses_new_polling && HCD_POLL_RH(hcd)) |
2305 | usb_hcd_poll_rh_status(hcd); | 2303 | usb_hcd_poll_rh_status(hcd); |
2306 | return retval; | 2304 | return retval; |
2307 | 2305 | ||
@@ -2320,11 +2318,11 @@ error_create_attr_group: | |||
2320 | mutex_unlock(&usb_bus_list_lock); | 2318 | mutex_unlock(&usb_bus_list_lock); |
2321 | err_register_root_hub: | 2319 | err_register_root_hub: |
2322 | hcd->rh_pollable = 0; | 2320 | hcd->rh_pollable = 0; |
2323 | hcd->poll_rh = 0; | 2321 | clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); |
2324 | del_timer_sync(&hcd->rh_timer); | 2322 | del_timer_sync(&hcd->rh_timer); |
2325 | hcd->driver->stop(hcd); | 2323 | hcd->driver->stop(hcd); |
2326 | hcd->state = HC_STATE_HALT; | 2324 | hcd->state = HC_STATE_HALT; |
2327 | hcd->poll_rh = 0; | 2325 | clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); |
2328 | del_timer_sync(&hcd->rh_timer); | 2326 | del_timer_sync(&hcd->rh_timer); |
2329 | err_hcd_driver_start: | 2327 | err_hcd_driver_start: |
2330 | if (hcd->irq >= 0) | 2328 | if (hcd->irq >= 0) |
@@ -2380,14 +2378,14 @@ void usb_remove_hcd(struct usb_hcd *hcd) | |||
2380 | * the hub_status_data() callback. | 2378 | * the hub_status_data() callback. |
2381 | */ | 2379 | */ |
2382 | hcd->rh_pollable = 0; | 2380 | hcd->rh_pollable = 0; |
2383 | hcd->poll_rh = 0; | 2381 | clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); |
2384 | del_timer_sync(&hcd->rh_timer); | 2382 | del_timer_sync(&hcd->rh_timer); |
2385 | 2383 | ||
2386 | hcd->driver->stop(hcd); | 2384 | hcd->driver->stop(hcd); |
2387 | hcd->state = HC_STATE_HALT; | 2385 | hcd->state = HC_STATE_HALT; |
2388 | 2386 | ||
2389 | /* In case the HCD restarted the timer, stop it again. */ | 2387 | /* In case the HCD restarted the timer, stop it again. */ |
2390 | hcd->poll_rh = 0; | 2388 | clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); |
2391 | del_timer_sync(&hcd->rh_timer); | 2389 | del_timer_sync(&hcd->rh_timer); |
2392 | 2390 | ||
2393 | if (hcd->irq >= 0) | 2391 | if (hcd->irq >= 0) |