diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/driver-ops.h | 8 | ||||
-rw-r--r-- | net/mac80211/main.c | 2 | ||||
-rw-r--r-- | net/mac80211/tx.c | 94 |
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 | ||
18 | static 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 | |||
18 | static inline int drv_start(struct ieee80211_local *local) | 26 | static 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 | /* | 1203 | static 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, |
1206 | static 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; | 1249 | static 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 | /* |