summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/rt2x00/rt2800lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c69
1 files changed, 46 insertions, 23 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index c17fcf272728..893c9d5f3d6f 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -947,6 +947,40 @@ static inline u8 rt2800_get_beacon_offset(struct rt2x00_dev *rt2x00dev,
return BEACON_BASE_TO_OFFSET(rt2800_hw_beacon_base(rt2x00dev, index));
}
+static void rt2800_update_beacons_setup(struct rt2x00_dev *rt2x00dev)
+{
+ struct data_queue *queue = rt2x00dev->bcn;
+ struct queue_entry *entry;
+ int i, bcn_num = 0;
+ u64 off, reg = 0;
+ u32 bssid_dw1;
+
+ /*
+ * Setup offsets of all active beacons in BCN_OFFSET{0,1} registers.
+ */
+ for (i = 0; i < queue->limit; i++) {
+ entry = &queue->entries[i];
+ if (!test_bit(ENTRY_BCN_ENABLED, &entry->flags))
+ continue;
+ off = rt2800_get_beacon_offset(rt2x00dev, entry->entry_idx);
+ reg |= off << (8 * bcn_num);
+ bcn_num++;
+ }
+
+ WARN_ON_ONCE(bcn_num != rt2x00dev->intf_beaconing);
+
+ rt2800_register_write(rt2x00dev, BCN_OFFSET0, (u32) reg);
+ rt2800_register_write(rt2x00dev, BCN_OFFSET1, (u32) (reg >> 32));
+
+ /*
+ * H/W sends up to MAC_BSSID_DW1_BSS_BCN_NUM + 1 consecutive beacons.
+ */
+ rt2800_register_read(rt2x00dev, MAC_BSSID_DW1, &bssid_dw1);
+ rt2x00_set_field32(&bssid_dw1, MAC_BSSID_DW1_BSS_BCN_NUM,
+ bcn_num > 0 ? bcn_num - 1 : 0);
+ rt2800_register_write(rt2x00dev, MAC_BSSID_DW1, bssid_dw1);
+}
+
void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
@@ -1003,6 +1037,12 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
entry->skb->len + padding_len);
+ __set_bit(ENTRY_BCN_ENABLED, &entry->flags);
+
+ /*
+ * Change global beacons settings.
+ */
+ rt2800_update_beacons_setup(rt2x00dev);
/*
* Restore beaconing state.
@@ -1053,8 +1093,13 @@ void rt2800_clear_beacon(struct queue_entry *entry)
* Clear beacon.
*/
rt2800_clear_beacon_register(rt2x00dev, entry->entry_idx);
+ __clear_bit(ENTRY_BCN_ENABLED, &entry->flags);
/*
+ * Change global beacons settings.
+ */
+ rt2800_update_beacons_setup(rt2x00dev);
+ /*
* Restore beaconing state.
*/
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);
@@ -1556,7 +1601,7 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
if (!is_zero_ether_addr((const u8 *)conf->bssid)) {
reg = le32_to_cpu(conf->bssid[1]);
rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
- rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 7);
+ rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 0);
conf->bssid[1] = cpu_to_le32(reg);
}
@@ -4517,28 +4562,6 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
if (ret)
return ret;
- rt2800_register_read(rt2x00dev, BCN_OFFSET0, &reg);
- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN0,
- rt2800_get_beacon_offset(rt2x00dev, 0));
- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN1,
- rt2800_get_beacon_offset(rt2x00dev, 1));
- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN2,
- rt2800_get_beacon_offset(rt2x00dev, 2));
- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN3,
- rt2800_get_beacon_offset(rt2x00dev, 3));
- rt2800_register_write(rt2x00dev, BCN_OFFSET0, reg);
-
- rt2800_register_read(rt2x00dev, BCN_OFFSET1, &reg);
- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN4,
- rt2800_get_beacon_offset(rt2x00dev, 4));
- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN5,
- rt2800_get_beacon_offset(rt2x00dev, 5));
- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN6,
- rt2800_get_beacon_offset(rt2x00dev, 6));
- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN7,
- rt2800_get_beacon_offset(rt2x00dev, 7));
- rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg);
-
rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);
rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);