aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/driver-ops.h8
-rw-r--r--net/mac80211/main.c2
-rw-r--r--net/mac80211/tx.c94
3 files changed, 69 insertions, 35 deletions
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index b12ed52732c8..49cc5e0e8a6a 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -15,6 +15,14 @@ static inline void drv_tx(struct ieee80211_local *local, struct sk_buff *skb)
15 local->ops->tx(&local->hw, skb); 15 local->ops->tx(&local->hw, skb);
16} 16}
17 17
18static inline void drv_tx_frags(struct ieee80211_local *local,
19 struct ieee80211_vif *vif,
20 struct ieee80211_sta *sta,
21 struct sk_buff_head *skbs)
22{
23 local->ops->tx_frags(&local->hw, vif, sta, skbs);
24}
25
18static inline int drv_start(struct ieee80211_local *local) 26static inline int drv_start(struct ieee80211_local *local)
19{ 27{
20 int ret; 28 int ret;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index e323d4e6647b..3df4482bb1d9 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -609,7 +609,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
609 609
610 local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN); 610 local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN);
611 611
612 BUG_ON(!ops->tx); 612 BUG_ON(!ops->tx && !ops->tx_frags);
613 BUG_ON(!ops->start); 613 BUG_ON(!ops->start);
614 BUG_ON(!ops->stop); 614 BUG_ON(!ops->stop);
615 BUG_ON(!ops->config); 615 BUG_ON(!ops->config);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 0cc68d0796a2..facc80d23b0c 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1200,24 +1200,15 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
1200 return TX_CONTINUE; 1200 return TX_CONTINUE;
1201} 1201}
1202 1202
1203/* 1203static bool ieee80211_tx_frags(struct ieee80211_local *local,
1204 * Returns false if the frame couldn't be transmitted but was queued instead. 1204 struct ieee80211_vif *vif,
1205 */ 1205 struct ieee80211_sta *sta,
1206static bool __ieee80211_tx(struct ieee80211_local *local, 1206 struct sk_buff_head *skbs,
1207 struct sk_buff_head *skbs, int led_len, 1207 bool txpending)
1208 struct sta_info *sta, bool txpending)
1209{ 1208{
1210 struct sk_buff *skb, *tmp; 1209 struct sk_buff *skb, *tmp;
1211 struct ieee80211_tx_info *info; 1210 struct ieee80211_tx_info *info;
1212 struct ieee80211_sub_if_data *sdata;
1213 unsigned long flags; 1211 unsigned long flags;
1214 __le16 fc;
1215
1216 if (WARN_ON(skb_queue_empty(skbs)))
1217 return true;
1218
1219 skb = skb_peek(skbs);
1220 fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
1221 1212
1222 skb_queue_walk_safe(skbs, skb, tmp) { 1213 skb_queue_walk_safe(skbs, skb, tmp) {
1223 int q = skb_get_queue_mapping(skb); 1214 int q = skb_get_queue_mapping(skb);
@@ -1242,37 +1233,72 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
1242 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 1233 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
1243 1234
1244 info = IEEE80211_SKB_CB(skb); 1235 info = IEEE80211_SKB_CB(skb);
1236 info->control.vif = vif;
1237 info->control.sta = sta;
1245 1238
1246 sdata = vif_to_sdata(info->control.vif); 1239 __skb_unlink(skb, skbs);
1240 drv_tx(local, skb);
1241 }
1247 1242
1248 switch (sdata->vif.type) { 1243 return true;
1249 case NL80211_IFTYPE_MONITOR: 1244}
1250 info->control.vif = NULL;
1251 break;
1252 case NL80211_IFTYPE_AP_VLAN:
1253 info->control.vif = &container_of(sdata->bss,
1254 struct ieee80211_sub_if_data, u.ap)->vif;
1255 break;
1256 default:
1257 /* keep */
1258 break;
1259 }
1260 1245
1261 if (sta && sta->uploaded) 1246/*
1262 info->control.sta = &sta->sta; 1247 * Returns false if the frame couldn't be transmitted but was queued instead.
1263 else 1248 */
1264 info->control.sta = NULL; 1249static bool __ieee80211_tx(struct ieee80211_local *local,
1250 struct sk_buff_head *skbs, int led_len,
1251 struct sta_info *sta, bool txpending)
1252{
1253 struct ieee80211_tx_info *info;
1254 struct ieee80211_sub_if_data *sdata;
1255 struct ieee80211_vif *vif;
1256 struct ieee80211_sta *pubsta;
1257 struct sk_buff *skb;
1258 bool result = true;
1259 __le16 fc;
1265 1260
1266 __skb_unlink(skb, skbs); 1261 if (WARN_ON(skb_queue_empty(skbs)))
1267 drv_tx(local, skb); 1262 return true;
1263
1264 skb = skb_peek(skbs);
1265 fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
1266 info = IEEE80211_SKB_CB(skb);
1267 sdata = vif_to_sdata(info->control.vif);
1268 if (sta && !sta->uploaded)
1269 sta = NULL;
1270
1271 if (sta)
1272 pubsta = &sta->sta;
1273 else
1274 pubsta = NULL;
1275
1276 switch (sdata->vif.type) {
1277 case NL80211_IFTYPE_MONITOR:
1278 sdata = NULL;
1279 vif = NULL;
1280 break;
1281 case NL80211_IFTYPE_AP_VLAN:
1282 sdata = container_of(sdata->bss,
1283 struct ieee80211_sub_if_data, u.ap);
1284 /* fall through */
1285 default:
1286 vif = &sdata->vif;
1287 break;
1268 } 1288 }
1269 1289
1290 if (local->ops->tx_frags)
1291 drv_tx_frags(local, vif, pubsta, skbs);
1292 else
1293 result = ieee80211_tx_frags(local, vif, pubsta, skbs,
1294 txpending);
1295
1270 ieee80211_tpt_led_trig_tx(local, fc, led_len); 1296 ieee80211_tpt_led_trig_tx(local, fc, led_len);
1271 ieee80211_led_tx(local, 1); 1297 ieee80211_led_tx(local, 1);
1272 1298
1273 WARN_ON(!skb_queue_empty(skbs)); 1299 WARN_ON(!skb_queue_empty(skbs));
1274 1300
1275 return true; 1301 return result;
1276} 1302}
1277 1303
1278/* 1304/*