aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2010-11-08 04:51:06 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-11-16 16:37:04 -0500
commitf23a478075659db8a4fd62fa6e264a8bb052cc5b (patch)
treeba1492a4a781770644359b88e8ca2d8d3a00adc2 /net/mac80211
parentca4a0831917d6541b45f03542257fcb20dc9cf4a (diff)
mac80211: support hardware TX fragmentation offload
The lower driver is notified when the fragmentation threshold changes and upon a reconfig of the interface. If the driver supports hardware TX fragmentation, don't fragment packets in the stack. Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c7
-rw-r--r--net/mac80211/driver-ops.h14
-rw-r--r--net/mac80211/driver-trace.h21
-rw-r--r--net/mac80211/tx.c11
-rw-r--r--net/mac80211/util.c3
5 files changed, 54 insertions, 2 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 18bd0e550600..3df12f7d0cfe 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1299,6 +1299,13 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1299 struct ieee80211_local *local = wiphy_priv(wiphy); 1299 struct ieee80211_local *local = wiphy_priv(wiphy);
1300 int err; 1300 int err;
1301 1301
1302 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
1303 err = drv_set_frag_threshold(local, wiphy->frag_threshold);
1304
1305 if (err)
1306 return err;
1307 }
1308
1302 if (changed & WIPHY_PARAM_COVERAGE_CLASS) { 1309 if (changed & WIPHY_PARAM_COVERAGE_CLASS) {
1303 err = drv_set_coverage_class(local, wiphy->coverage_class); 1310 err = drv_set_coverage_class(local, wiphy->coverage_class);
1304 1311
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 16983825f8e8..79019f94f621 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -233,6 +233,20 @@ static inline void drv_get_tkip_seq(struct ieee80211_local *local,
233 trace_drv_get_tkip_seq(local, hw_key_idx, iv32, iv16); 233 trace_drv_get_tkip_seq(local, hw_key_idx, iv32, iv16);
234} 234}
235 235
236static inline int drv_set_frag_threshold(struct ieee80211_local *local,
237 u32 value)
238{
239 int ret = 0;
240
241 might_sleep();
242
243 trace_drv_set_frag_threshold(local, value);
244 if (local->ops->set_frag_threshold)
245 ret = local->ops->set_frag_threshold(&local->hw, value);
246 trace_drv_return_int(local, ret);
247 return ret;
248}
249
236static inline int drv_set_rts_threshold(struct ieee80211_local *local, 250static inline int drv_set_rts_threshold(struct ieee80211_local *local,
237 u32 value) 251 u32 value)
238{ 252{
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 6831fb1641c8..431d65500d6a 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -531,6 +531,27 @@ TRACE_EVENT(drv_get_tkip_seq,
531 ) 531 )
532); 532);
533 533
534TRACE_EVENT(drv_set_frag_threshold,
535 TP_PROTO(struct ieee80211_local *local, u32 value),
536
537 TP_ARGS(local, value),
538
539 TP_STRUCT__entry(
540 LOCAL_ENTRY
541 __field(u32, value)
542 ),
543
544 TP_fast_assign(
545 LOCAL_ASSIGN;
546 __entry->value = value;
547 ),
548
549 TP_printk(
550 LOCAL_PR_FMT " value:%d",
551 LOCAL_PR_ARG, __entry->value
552 )
553);
554
534TRACE_EVENT(drv_set_rts_threshold, 555TRACE_EVENT(drv_set_rts_threshold,
535 TP_PROTO(struct ieee80211_local *local, u32 value), 556 TP_PROTO(struct ieee80211_local *local, u32 value),
536 557
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 96c594309506..b392876af7d8 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1033,6 +1033,7 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
1033 struct ieee80211_radiotap_header *rthdr = 1033 struct ieee80211_radiotap_header *rthdr =
1034 (struct ieee80211_radiotap_header *) skb->data; 1034 (struct ieee80211_radiotap_header *) skb->data;
1035 struct ieee80211_supported_band *sband; 1035 struct ieee80211_supported_band *sband;
1036 bool hw_frag;
1036 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1037 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1037 int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, 1038 int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
1038 NULL); 1039 NULL);
@@ -1042,6 +1043,9 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
1042 info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; 1043 info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
1043 tx->flags &= ~IEEE80211_TX_FRAGMENTED; 1044 tx->flags &= ~IEEE80211_TX_FRAGMENTED;
1044 1045
1046 /* packet is fragmented in HW if we have a non-NULL driver callback */
1047 hw_frag = (tx->local->ops->set_frag_threshold != NULL);
1048
1045 /* 1049 /*
1046 * for every radiotap entry that is present 1050 * for every radiotap entry that is present
1047 * (ieee80211_radiotap_iterator_next returns -ENOENT when no more 1051 * (ieee80211_radiotap_iterator_next returns -ENOENT when no more
@@ -1078,7 +1082,8 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
1078 } 1082 }
1079 if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) 1083 if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP)
1080 info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT; 1084 info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT;
1081 if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) 1085 if ((*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) &&
1086 !hw_frag)
1082 tx->flags |= IEEE80211_TX_FRAGMENTED; 1087 tx->flags |= IEEE80211_TX_FRAGMENTED;
1083 break; 1088 break;
1084 1089
@@ -1181,8 +1186,10 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
1181 /* 1186 /*
1182 * Set this flag (used below to indicate "automatic fragmentation"), 1187 * Set this flag (used below to indicate "automatic fragmentation"),
1183 * it will be cleared/left by radiotap as desired. 1188 * it will be cleared/left by radiotap as desired.
1189 * Only valid when fragmentation is done by the stack.
1184 */ 1190 */
1185 tx->flags |= IEEE80211_TX_FRAGMENTED; 1191 if (!local->ops->set_frag_threshold)
1192 tx->flags |= IEEE80211_TX_FRAGMENTED;
1186 1193
1187 /* process and remove the injection radiotap header */ 1194 /* process and remove the injection radiotap header */
1188 if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) { 1195 if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) {
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 0b6fc92bc0d7..e486286ebf1a 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1152,6 +1152,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1152 } 1152 }
1153 mutex_unlock(&local->sta_mtx); 1153 mutex_unlock(&local->sta_mtx);
1154 1154
1155 /* setup fragmentation threshold */
1156 drv_set_frag_threshold(local, hw->wiphy->frag_threshold);
1157
1155 /* setup RTS threshold */ 1158 /* setup RTS threshold */
1156 drv_set_rts_threshold(local, hw->wiphy->rts_threshold); 1159 drv_set_rts_threshold(local, hw->wiphy->rts_threshold);
1157 1160