|
@@ -1033,6 +1033,7 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
|
|
|
struct ieee80211_radiotap_header *rthdr =
|
|
|
(struct ieee80211_radiotap_header *) skb->data;
|
|
|
struct ieee80211_supported_band *sband;
|
|
|
+ bool hw_frag;
|
|
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
|
|
int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
|
|
|
NULL);
|
|
@@ -1042,6 +1043,9 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
|
|
|
info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
|
|
tx->flags &= ~IEEE80211_TX_FRAGMENTED;
|
|
|
|
|
|
+ /* packet is fragmented in HW if we have a non-NULL driver callback */
|
|
|
+ hw_frag = (tx->local->ops->set_frag_threshold != NULL);
|
|
|
+
|
|
|
/*
|
|
|
* for every radiotap entry that is present
|
|
|
* (ieee80211_radiotap_iterator_next returns -ENOENT when no more
|
|
@@ -1078,7 +1082,8 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
|
|
|
}
|
|
|
if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP)
|
|
|
info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
|
|
- if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG)
|
|
|
+ if ((*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) &&
|
|
|
+ !hw_frag)
|
|
|
tx->flags |= IEEE80211_TX_FRAGMENTED;
|
|
|
break;
|
|
|
|
|
@@ -1181,8 +1186,10 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
|
|
|
/*
|
|
|
* Set this flag (used below to indicate "automatic fragmentation"),
|
|
|
* it will be cleared/left by radiotap as desired.
|
|
|
+ * Only valid when fragmentation is done by the stack.
|
|
|
*/
|
|
|
- tx->flags |= IEEE80211_TX_FRAGMENTED;
|
|
|
+ if (!local->ops->set_frag_threshold)
|
|
|
+ tx->flags |= IEEE80211_TX_FRAGMENTED;
|
|
|
|
|
|
/* process and remove the injection radiotap header */
|
|
|
if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) {
|