Skip to content

Commit

Permalink
rt2x00: Fix race conditions in flag handling
Browse files Browse the repository at this point in the history
Some of the flags should be accessed atomically to
prevent race conditions. The flags that are most important
are those that can change often and indicate the actual
state of the device, queue or queue entry.

The big flag rename was done to move all state flags to
the same naming type as the other rt2x00dev flags and
made sure all places where the flags were used were changed. ;)

Thanks to Stephen for most of the queue flags updates,
which fixes some of the most obvious consequences of the
race conditions. Among those the notorious:

rt2x00queue_write_tx_frame: Error - Arrived at non-free entry in the non-full queue 0.
rt2x00queue_write_tx_frame: Error - Arrived at non-free entry in the non-full queue 0.
rt2x00queue_write_tx_frame: Error - Arrived at non-free entry in the non-full queue 0.

Signed-off-by: Stephen Blackheath <tramp.enshrine.stephen@blacksapphire.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Ivo van Doorn authored and John W. Linville committed Aug 29, 2008
1 parent de9cc7a commit 0262ab0
Show file tree
Hide file tree
Showing 11 changed files with 68 additions and 66 deletions.
2 changes: 1 addition & 1 deletion drivers/net/wireless/rt2x00/rt2400pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1241,7 +1241,7 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
if (!reg)
return IRQ_NONE;

if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return IRQ_HANDLED;

/*
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/rt2x00/rt2500pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1377,7 +1377,7 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
if (!reg)
return IRQ_NONE;

if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return IRQ_HANDLED;

/*
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/rt2x00/rt2500usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1297,7 +1297,7 @@ static void rt2500usb_beacondone(struct urb *urb)
struct queue_entry *entry = (struct queue_entry *)urb->context;
struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;

if (!test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags))
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags))
return;

/*
Expand Down
16 changes: 8 additions & 8 deletions drivers/net/wireless/rt2x00/rt2x00.h
Original file line number Diff line number Diff line change
Expand Up @@ -629,14 +629,14 @@ enum rt2x00_flags {
/*
* Device state flags
*/
DEVICE_PRESENT,
DEVICE_REGISTERED_HW,
DEVICE_INITIALIZED,
DEVICE_STARTED,
DEVICE_STARTED_SUSPEND,
DEVICE_ENABLED_RADIO,
DEVICE_DISABLED_RADIO_HW,
DEVICE_DIRTY_CONFIG,
DEVICE_STATE_PRESENT,
DEVICE_STATE_REGISTERED_HW,
DEVICE_STATE_INITIALIZED,
DEVICE_STATE_STARTED,
DEVICE_STATE_STARTED_SUSPEND,
DEVICE_STATE_ENABLED_RADIO,
DEVICE_STATE_DISABLED_RADIO_HW,
DEVICE_STATE_DIRTY_CONFIG,

/*
* Driver requirements
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/rt2x00/rt2x00config.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
* Antenna setup changes require the RX to be disabled,
* else the changes will be ignored by the device.
*/
if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK);

/*
Expand All @@ -136,7 +136,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
rt2x00dev->link.ant.active.rx = libconf.ant.rx;
rt2x00dev->link.ant.active.tx = libconf.ant.tx;

if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK);
}

Expand Down
58 changes: 30 additions & 28 deletions drivers/net/wireless/rt2x00/rt2x00dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
*/
void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev)
{
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return;

/*
Expand Down Expand Up @@ -94,8 +94,8 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
* Don't enable the radio twice.
* And check if the hardware button has been disabled.
*/
if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
test_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags))
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
test_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags))
return 0;

/*
Expand All @@ -117,7 +117,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
rt2x00leds_led_radio(rt2x00dev, true);
rt2x00led_led_activity(rt2x00dev, true);

__set_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags);
set_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags);

/*
* Enable RX.
Expand All @@ -134,7 +134,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)

void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
{
if (!__test_and_clear_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
if (!test_and_clear_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return;

/*
Expand Down Expand Up @@ -354,7 +354,7 @@ static void rt2x00lib_link_tuner(struct work_struct *work)
* When the radio is shutting down we should
* immediately cease all link tuning.
*/
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return;

/*
Expand Down Expand Up @@ -431,7 +431,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
* note that in the spinlock protected area above the delayed_flags
* have been cleared correctly.
*/
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return;

if (delayed_flags & DELAYED_UPDATE_BEACON)
Expand Down Expand Up @@ -484,7 +484,7 @@ static void rt2x00lib_beacondone_iter(void *data, u8 *mac,

void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
{
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return;

ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
Expand Down Expand Up @@ -572,7 +572,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,

rt2x00dev->ops->lib->init_txentry(rt2x00dev, entry);

__clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);

/*
Expand Down Expand Up @@ -888,7 +888,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,

static void rt2x00lib_remove_hw(struct rt2x00_dev *rt2x00dev)
{
if (test_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags))
if (test_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags))
ieee80211_unregister_hw(rt2x00dev->hw);

if (likely(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ])) {
Expand All @@ -906,6 +906,9 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
struct hw_mode_spec *spec = &rt2x00dev->spec;
int status;

if (test_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags))
return 0;

/*
* Initialize HW modes.
*/
Expand All @@ -927,7 +930,7 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
return status;
}

__set_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags);
set_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags);

return 0;
}
Expand All @@ -937,7 +940,7 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
*/
static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
{
if (!__test_and_clear_bit(DEVICE_INITIALIZED, &rt2x00dev->flags))
if (!test_and_clear_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags))
return;

/*
Expand All @@ -960,7 +963,7 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
{
int status;

if (test_bit(DEVICE_INITIALIZED, &rt2x00dev->flags))
if (test_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags))
return 0;

/*
Expand All @@ -979,7 +982,7 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
return status;
}

__set_bit(DEVICE_INITIALIZED, &rt2x00dev->flags);
set_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags);

/*
* Register the extra components.
Expand All @@ -993,7 +996,7 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
{
int retval;

if (test_bit(DEVICE_STARTED, &rt2x00dev->flags))
if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
return 0;

/*
Expand Down Expand Up @@ -1024,15 +1027,15 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
rt2x00dev->intf_sta_count = 0;
rt2x00dev->intf_associated = 0;

__set_bit(DEVICE_STARTED, &rt2x00dev->flags);
__set_bit(DEVICE_DIRTY_CONFIG, &rt2x00dev->flags);
set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags);
set_bit(DEVICE_STATE_DIRTY_CONFIG, &rt2x00dev->flags);

return 0;
}

void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)
{
if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags))
if (!test_and_clear_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
return;

/*
Expand All @@ -1044,8 +1047,6 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)
rt2x00dev->intf_ap_count = 0;
rt2x00dev->intf_sta_count = 0;
rt2x00dev->intf_associated = 0;

__clear_bit(DEVICE_STARTED, &rt2x00dev->flags);
}

/*
Expand Down Expand Up @@ -1100,7 +1101,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
rt2x00rfkill_allocate(rt2x00dev);
rt2x00debug_register(rt2x00dev);

__set_bit(DEVICE_PRESENT, &rt2x00dev->flags);
set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);

return 0;

Expand All @@ -1113,7 +1114,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_probe_dev);

void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
{
__clear_bit(DEVICE_PRESENT, &rt2x00dev->flags);
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);

/*
* Disable radio.
Expand Down Expand Up @@ -1158,14 +1159,15 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state)
int retval;

NOTICE(rt2x00dev, "Going to sleep.\n");
__clear_bit(DEVICE_PRESENT, &rt2x00dev->flags);

/*
* Only continue if mac80211 has open interfaces.
*/
if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags))
if (!test_and_clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
goto exit;
__set_bit(DEVICE_STARTED_SUSPEND, &rt2x00dev->flags);

set_bit(DEVICE_STATE_STARTED_SUSPEND, &rt2x00dev->flags);

/*
* Disable radio.
Expand Down Expand Up @@ -1237,7 +1239,7 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
/*
* Only continue if mac80211 had open interfaces.
*/
if (!__test_and_clear_bit(DEVICE_STARTED_SUSPEND, &rt2x00dev->flags))
if (!test_and_clear_bit(DEVICE_STATE_STARTED_SUSPEND, &rt2x00dev->flags))
return 0;

/*
Expand All @@ -1264,7 +1266,7 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
/*
* We are ready again to receive requests from mac80211.
*/
__set_bit(DEVICE_PRESENT, &rt2x00dev->flags);
set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);

/*
* It is possible that during that mac80211 has attempted
Expand All @@ -1284,7 +1286,7 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
return 0;

exit:
rt2x00lib_disable_radio(rt2x00dev);
rt2x00lib_stop(rt2x00dev);
rt2x00lib_uninitialize(rt2x00dev);
rt2x00debug_deregister(rt2x00dev);

Expand Down
Loading

0 comments on commit 0262ab0

Please sign in to comment.