diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.c | 69 |
1 files changed, 46 insertions, 23 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index c17fcf2..893c9d5 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(®, MAC_BSSID_DW1_BSS_ID_MASK, 3); - rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 7); + rt2x00_set_field32(®, 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, ®); - rt2x00_set_field32(®, BCN_OFFSET0_BCN0, - rt2800_get_beacon_offset(rt2x00dev, 0)); - rt2x00_set_field32(®, BCN_OFFSET0_BCN1, - rt2800_get_beacon_offset(rt2x00dev, 1)); - rt2x00_set_field32(®, BCN_OFFSET0_BCN2, - rt2800_get_beacon_offset(rt2x00dev, 2)); - rt2x00_set_field32(®, BCN_OFFSET0_BCN3, - rt2800_get_beacon_offset(rt2x00dev, 3)); - rt2800_register_write(rt2x00dev, BCN_OFFSET0, reg); - - rt2800_register_read(rt2x00dev, BCN_OFFSET1, ®); - rt2x00_set_field32(®, BCN_OFFSET1_BCN4, - rt2800_get_beacon_offset(rt2x00dev, 4)); - rt2x00_set_field32(®, BCN_OFFSET1_BCN5, - rt2800_get_beacon_offset(rt2x00dev, 5)); - rt2x00_set_field32(®, BCN_OFFSET1_BCN6, - rt2800_get_beacon_offset(rt2x00dev, 6)); - rt2x00_set_field32(®, 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); |