};
 
 struct mt76x02_beacon_ops {
+       unsigned int nslots;
+       unsigned int slot_size;
        void (*pre_tbtt_enable) (struct mt76x02_dev *, bool);
        void (*beacon_enable) (struct mt76x02_dev *, bool);
 };
                              struct ieee80211_vif *vif,
                              struct ieee80211_bss_conf *info, u32 changed);
 
-extern const u16 mt76x02_beacon_offsets[16];
 struct beacon_bc_data {
        struct mt76x02_dev *dev;
        struct sk_buff_head q;
 
 
 #include "mt76x02.h"
 
-const u16 mt76x02_beacon_offsets[16] = {
-       /* 1024 byte per beacon */
-       0xc000,
-       0xc400,
-       0xc800,
-       0xcc00,
-       0xd000,
-       0xd400,
-       0xd800,
-       0xdc00,
-       /* BSS idx 8-15 not used for beacons */
-       0xc000,
-       0xc000,
-       0xc000,
-       0xc000,
-       0xc000,
-       0xc000,
-       0xc000,
-       0xc000,
-};
-EXPORT_SYMBOL_GPL(mt76x02_beacon_offsets);
-
 static void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev)
 {
-       u16 val, base = MT_BEACON_BASE;
        u32 regs[4] = {};
+       u16 val;
        int i;
 
-       for (i = 0; i < 16; i++) {
-               val = mt76x02_beacon_offsets[i] - base;
+       for (i = 0; i < dev->beacon_ops->nslots; i++) {
+               val = i * dev->beacon_ops->slot_size;
                regs[i / 4] |= (val / 64) << (8 * (i % 4));
        }
 
 static int
 mt76x02_write_beacon(struct mt76x02_dev *dev, int offset, struct sk_buff *skb)
 {
-       int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0];
+       int beacon_len = dev->beacon_ops->slot_size;
        struct mt76x02_txwi txwi;
 
        if (WARN_ON_ONCE(beacon_len < skb->len + sizeof(struct mt76x02_txwi)))
 __mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 bcn_idx,
                         struct sk_buff *skb)
 {
-       int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0];
-       int beacon_addr = mt76x02_beacon_offsets[bcn_idx];
+       int beacon_len = dev->beacon_ops->slot_size;
+       int beacon_addr = MT_BEACON_BASE + (beacon_len * bcn_idx);
        int ret = 0;
        int i;
 
 
 
 /* Trigger pre-TBTT event 8 ms before TBTT */
 #define PRE_TBTT_USEC 8000
+
+/* Beacon SRAM memory is limited to 8kB. We need to send PS buffered frames
+ * (which can be 1500 bytes big) via beacon memory. That make limit of number
+ * of slots to 5. TODO: dynamically calculate offsets in beacon SRAM.
+ */
+#define N_BCN_SLOTS 5
+
 static void mt76x02u_start_pre_tbtt_timer(struct mt76x02_dev *dev)
 {
        u64 time;
 {
        struct mt76x02_dev *dev =
                container_of(work, struct mt76x02_dev, pre_tbtt_work);
-       int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0];
        struct beacon_bc_data data = {};
        struct sk_buff *skb;
        int i, nbeacons;
                mt76x02_update_beacon_iter, dev);
 
        nbeacons = hweight8(dev->beacon_mask);
-       mt76x02_enqueue_buffered_bc(dev, &data, 8 - nbeacons);
+       mt76x02_enqueue_buffered_bc(dev, &data, N_BCN_SLOTS - nbeacons);
 
-       for (i = nbeacons; i < 8; i++) {
+       for (i = nbeacons; i < N_BCN_SLOTS; i++) {
                skb = __skb_dequeue(&data.q);
-               if (skb && skb->len >= beacon_len) {
-                       dev_kfree_skb(skb);
-                       skb = NULL;
-               }
                mt76x02_mac_set_beacon(dev, i, skb);
        }
 
                /* Timer is already stopped, only clean up
                 * PS buffered frames if any.
                 */
-               for (i = 0; i < 8; i++)
+               for (i = 0; i < N_BCN_SLOTS; i++)
                        mt76x02_mac_set_beacon(dev, i, NULL);
        }
 }
 void mt76x02u_init_beacon_config(struct mt76x02_dev *dev)
 {
        static const struct mt76x02_beacon_ops beacon_ops = {
+               .nslots = N_BCN_SLOTS,
+               .slot_size = (8192 / N_BCN_SLOTS) & ~63,
                .pre_tbtt_enable = mt76x02u_pre_tbtt_enable,
                .beacon_enable = mt76x02u_beacon_enable,
        };