diff options
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/agg-rx.c')
| -rw-r--r-- | drivers/net/wireless/mediatek/mt76/agg-rx.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/agg-rx.c b/drivers/net/wireless/mediatek/mt76/agg-rx.c index fcb208d1f276..73c8b2805c97 100644 --- a/drivers/net/wireless/mediatek/mt76/agg-rx.c +++ b/drivers/net/wireless/mediatek/mt76/agg-rx.c | |||
| @@ -103,6 +103,7 @@ mt76_rx_aggr_reorder_work(struct work_struct *work) | |||
| 103 | __skb_queue_head_init(&frames); | 103 | __skb_queue_head_init(&frames); |
| 104 | 104 | ||
| 105 | local_bh_disable(); | 105 | local_bh_disable(); |
| 106 | rcu_read_lock(); | ||
| 106 | 107 | ||
| 107 | spin_lock(&tid->lock); | 108 | spin_lock(&tid->lock); |
| 108 | mt76_rx_aggr_check_release(tid, &frames); | 109 | mt76_rx_aggr_check_release(tid, &frames); |
| @@ -112,8 +113,9 @@ mt76_rx_aggr_reorder_work(struct work_struct *work) | |||
| 112 | if (nframes) | 113 | if (nframes) |
| 113 | ieee80211_queue_delayed_work(tid->dev->hw, &tid->reorder_work, | 114 | ieee80211_queue_delayed_work(tid->dev->hw, &tid->reorder_work, |
| 114 | REORDER_TIMEOUT); | 115 | REORDER_TIMEOUT); |
| 115 | mt76_rx_complete(dev, &frames, -1); | 116 | mt76_rx_complete(dev, &frames, NULL); |
| 116 | 117 | ||
| 118 | rcu_read_unlock(); | ||
| 117 | local_bh_enable(); | 119 | local_bh_enable(); |
| 118 | } | 120 | } |
| 119 | 121 | ||
| @@ -147,12 +149,13 @@ mt76_rx_aggr_check_ctl(struct sk_buff *skb, struct sk_buff_head *frames) | |||
| 147 | void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames) | 149 | void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames) |
| 148 | { | 150 | { |
| 149 | struct mt76_rx_status *status = (struct mt76_rx_status *) skb->cb; | 151 | struct mt76_rx_status *status = (struct mt76_rx_status *) skb->cb; |
| 152 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
| 150 | struct mt76_wcid *wcid = status->wcid; | 153 | struct mt76_wcid *wcid = status->wcid; |
| 151 | struct ieee80211_sta *sta; | 154 | struct ieee80211_sta *sta; |
| 152 | struct mt76_rx_tid *tid; | 155 | struct mt76_rx_tid *tid; |
| 153 | bool sn_less; | 156 | bool sn_less; |
| 154 | u16 seqno, head, size; | 157 | u16 seqno, head, size; |
| 155 | u8 idx; | 158 | u8 ackp, idx; |
| 156 | 159 | ||
| 157 | __skb_queue_tail(frames, skb); | 160 | __skb_queue_tail(frames, skb); |
| 158 | 161 | ||
| @@ -165,10 +168,17 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames) | |||
| 165 | return; | 168 | return; |
| 166 | } | 169 | } |
| 167 | 170 | ||
| 171 | /* not part of a BA session */ | ||
| 172 | ackp = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_ACK_POLICY_MASK; | ||
| 173 | if (ackp != IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK && | ||
| 174 | ackp != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL) | ||
| 175 | return; | ||
| 176 | |||
| 168 | tid = rcu_dereference(wcid->aggr[status->tid]); | 177 | tid = rcu_dereference(wcid->aggr[status->tid]); |
| 169 | if (!tid) | 178 | if (!tid) |
| 170 | return; | 179 | return; |
| 171 | 180 | ||
| 181 | status->flag |= RX_FLAG_DUP_VALIDATED; | ||
| 172 | spin_lock_bh(&tid->lock); | 182 | spin_lock_bh(&tid->lock); |
| 173 | 183 | ||
| 174 | if (tid->stopped) | 184 | if (tid->stopped) |
| @@ -236,8 +246,7 @@ int mt76_rx_aggr_start(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tidno, | |||
| 236 | 246 | ||
| 237 | mt76_rx_aggr_stop(dev, wcid, tidno); | 247 | mt76_rx_aggr_stop(dev, wcid, tidno); |
| 238 | 248 | ||
| 239 | tid = kzalloc(sizeof(*tid) + size * sizeof(tid->reorder_buf[0]), | 249 | tid = kzalloc(struct_size(tid, reorder_buf, size), GFP_KERNEL); |
| 240 | GFP_KERNEL); | ||
| 241 | if (!tid) | 250 | if (!tid) |
| 242 | return -ENOMEM; | 251 | return -ENOMEM; |
| 243 | 252 | ||
| @@ -258,6 +267,8 @@ static void mt76_rx_aggr_shutdown(struct mt76_dev *dev, struct mt76_rx_tid *tid) | |||
| 258 | u8 size = tid->size; | 267 | u8 size = tid->size; |
| 259 | int i; | 268 | int i; |
| 260 | 269 | ||
| 270 | cancel_delayed_work(&tid->reorder_work); | ||
| 271 | |||
| 261 | spin_lock_bh(&tid->lock); | 272 | spin_lock_bh(&tid->lock); |
| 262 | 273 | ||
| 263 | tid->stopped = true; | 274 | tid->stopped = true; |
| @@ -272,8 +283,6 @@ static void mt76_rx_aggr_shutdown(struct mt76_dev *dev, struct mt76_rx_tid *tid) | |||
| 272 | } | 283 | } |
| 273 | 284 | ||
| 274 | spin_unlock_bh(&tid->lock); | 285 | spin_unlock_bh(&tid->lock); |
| 275 | |||
| 276 | cancel_delayed_work_sync(&tid->reorder_work); | ||
| 277 | } | 286 | } |
| 278 | 287 | ||
| 279 | void mt76_rx_aggr_stop(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tidno) | 288 | void mt76_rx_aggr_stop(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tidno) |
