aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mediatek/mt76/agg-rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/agg-rx.c')
-rw-r--r--drivers/net/wireless/mediatek/mt76/agg-rx.c21
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)
147void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames) 149void 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
279void mt76_rx_aggr_stop(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tidno) 288void mt76_rx_aggr_stop(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tidno)