1 // SPDX-License-Identifier: ISC 2 /* 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 5 * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl> 6 */ 7 8 #include "mt76x02.h" 9 10 static void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev) 11 { 12 u32 regs[4] = {}; 13 u16 val; 14 int i; 15 16 for (i = 0; i < dev->beacon_ops->nslots; i++) { 17 val = i * dev->beacon_ops->slot_size; 18 regs[i / 4] |= (val / 64) << (8 * (i % 4)); 19 } 20 21 for (i = 0; i < 4; i++) 22 mt76_wr(dev, MT_BCN_OFFSET(i), regs[i]); 23 } 24 25 static int 26 mt76x02_write_beacon(struct mt76x02_dev *dev, int offset, struct sk_buff *skb) 27 { 28 int beacon_len = dev->beacon_ops->slot_size; 29 30 if (WARN_ON_ONCE(beacon_len < skb->len + sizeof(struct mt76x02_txwi))) 31 return -ENOSPC; 32 33 /* USB devices already reserve enough skb headroom for txwi's. This 34 * helps to save slow copies over USB. 35 */ 36 if (mt76_is_usb(&dev->mt76)) { 37 struct mt76x02_txwi *txwi; 38 39 txwi = (struct mt76x02_txwi *)(skb->data - sizeof(*txwi)); 40 mt76x02_mac_write_txwi(dev, txwi, skb, NULL, NULL, skb->len); 41 skb_push(skb, sizeof(*txwi)); 42 } else { 43 struct mt76x02_txwi txwi; 44 45 mt76x02_mac_write_txwi(dev, &txwi, skb, NULL, NULL, skb->len); 46 mt76_wr_copy(dev, offset, &txwi, sizeof(txwi)); 47 offset += sizeof(txwi); 48 } 49 50 mt76_wr_copy(dev, offset, skb->data, skb->len); 51 return 0; 52 } 53 54 void mt76x02_mac_set_beacon(struct mt76x02_dev *dev, 55 struct sk_buff *skb) 56 { 57 int bcn_len = dev->beacon_ops->slot_size; 58 int bcn_addr = MT_BEACON_BASE + (bcn_len * dev->beacon_data_count); 59 60 if (!mt76x02_write_beacon(dev, bcn_addr, skb)) { 61 if (!dev->beacon_data_count) 62 dev->beacon_hang_check++; 63 dev->beacon_data_count++; 64 } 65 dev_kfree_skb(skb); 66 } 67 EXPORT_SYMBOL_GPL(mt76x02_mac_set_beacon); 68 69 void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, 70 struct ieee80211_vif *vif, bool enable) 71 { 72 struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; 73 u8 old_mask = dev->mt76.beacon_mask; 74 75 mt76x02_pre_tbtt_enable(dev, false); 76 77 if (!dev->mt76.beacon_mask) 78 dev->tbtt_count = 0; 79 80 dev->beacon_hang_check = 0; 81 if (enable) { 82 dev->mt76.beacon_mask |= BIT(mvif->idx); 83 } else { 84 dev->mt76.beacon_mask &= ~BIT(mvif->idx); 85 } 86 87 if (!!old_mask == !!dev->mt76.beacon_mask) 88 goto out; 89 90 if (dev->mt76.beacon_mask) 91 mt76_set(dev, MT_BEACON_TIME_CFG, 92 MT_BEACON_TIME_CFG_BEACON_TX | 93 MT_BEACON_TIME_CFG_TBTT_EN | 94 MT_BEACON_TIME_CFG_TIMER_EN); 95 else 96 mt76_clear(dev, MT_BEACON_TIME_CFG, 97 MT_BEACON_TIME_CFG_BEACON_TX | 98 MT_BEACON_TIME_CFG_TBTT_EN | 99 MT_BEACON_TIME_CFG_TIMER_EN); 100 mt76x02_beacon_enable(dev, !!dev->mt76.beacon_mask); 101 102 out: 103 mt76x02_pre_tbtt_enable(dev, true); 104 } 105 106 void 107 mt76x02_resync_beacon_timer(struct mt76x02_dev *dev) 108 { 109 u32 timer_val = dev->mt76.beacon_int << 4; 110 111 dev->tbtt_count++; 112 113 /* 114 * Beacon timer drifts by 1us every tick, the timer is configured 115 * in 1/16 TU (64us) units. 116 */ 117 if (dev->tbtt_count < 63) 118 return; 119 120 /* 121 * The updated beacon interval takes effect after two TBTT, because 122 * at this point the original interval has already been loaded into 123 * the next TBTT_TIMER value 124 */ 125 if (dev->tbtt_count == 63) 126 timer_val -= 1; 127 128 mt76_rmw_field(dev, MT_BEACON_TIME_CFG, 129 MT_BEACON_TIME_CFG_INTVAL, timer_val); 130 131 if (dev->tbtt_count >= 64) 132 dev->tbtt_count = 0; 133 } 134 EXPORT_SYMBOL_GPL(mt76x02_resync_beacon_timer); 135 136 void 137 mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) 138 { 139 struct mt76x02_dev *dev = (struct mt76x02_dev *)priv; 140 struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; 141 struct sk_buff *skb = NULL; 142 143 if (!(dev->mt76.beacon_mask & BIT(mvif->idx))) 144 return; 145 146 skb = ieee80211_beacon_get(mt76_hw(dev), vif, 0); 147 if (!skb) 148 return; 149 150 mt76x02_mac_set_beacon(dev, skb); 151 } 152 EXPORT_SYMBOL_GPL(mt76x02_update_beacon_iter); 153 154 static void 155 mt76x02_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif) 156 { 157 struct beacon_bc_data *data = priv; 158 struct mt76x02_dev *dev = data->dev; 159 struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; 160 struct ieee80211_tx_info *info; 161 struct sk_buff *skb; 162 163 if (!(dev->mt76.beacon_mask & BIT(mvif->idx))) 164 return; 165 166 skb = ieee80211_get_buffered_bc(mt76_hw(dev), vif); 167 if (!skb) 168 return; 169 170 info = IEEE80211_SKB_CB(skb); 171 info->control.vif = vif; 172 info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; 173 mt76_skb_set_moredata(skb, true); 174 __skb_queue_tail(&data->q, skb); 175 data->tail[mvif->idx] = skb; 176 } 177 178 void 179 mt76x02_enqueue_buffered_bc(struct mt76x02_dev *dev, 180 struct beacon_bc_data *data, 181 int max_nframes) 182 { 183 int i, nframes; 184 185 data->dev = dev; 186 __skb_queue_head_init(&data->q); 187 188 do { 189 nframes = skb_queue_len(&data->q); 190 ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), 191 IEEE80211_IFACE_ITER_RESUME_ALL, 192 mt76x02_add_buffered_bc, data); 193 } while (nframes != skb_queue_len(&data->q) && 194 skb_queue_len(&data->q) < max_nframes); 195 196 if (!skb_queue_len(&data->q)) 197 return; 198 199 for (i = 0; i < ARRAY_SIZE(data->tail); i++) { 200 if (!data->tail[i]) 201 continue; 202 mt76_skb_set_moredata(data->tail[i], false); 203 } 204 } 205 EXPORT_SYMBOL_GPL(mt76x02_enqueue_buffered_bc); 206 207 void mt76x02_init_beacon_config(struct mt76x02_dev *dev) 208 { 209 mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN | 210 MT_BEACON_TIME_CFG_TBTT_EN | 211 MT_BEACON_TIME_CFG_BEACON_TX)); 212 mt76_set(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_SYNC_MODE); 213 mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff); 214 mt76x02_set_beacon_offsets(dev); 215 } 216 EXPORT_SYMBOL_GPL(mt76x02_init_beacon_config); 217 218