aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-11-16 10:02:47 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-11-21 16:20:43 -0500
commit11127e9121d4dd9da868cf0fd89dcac35f7f0fa3 (patch)
tree8cb16ecbd5942679c18934064b935a7e256a77da /net
parent74e4dbfd57a38c4ec4131cebdbfa3d621d38dd6a (diff)
mac80211: transmit fragment list to drivers
Drivers can usually handle fragmented packets much easier when they get the entire list of fragments at once. The only thing they need to do is keep enough space on the queues for up to ten fragments of a single MSDU. This allows them to implement this with a new operation tx_frags. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
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/*