Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f23a4780 authored by Arik Nemtsov's avatar Arik Nemtsov Committed by John W. Linville
Browse files

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: default avatarArik Nemtsov <arik@wizery.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent ca4a0831
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -1652,6 +1652,11 @@ enum ieee80211_ampdu_mlme_action {
 *	and IV16) for the given key from hardware.
 *	The callback must be atomic.
 *
 * @set_frag_threshold: Configuration of fragmentation threshold. Assign this
 *	if the device does fragmentation by itself; if this callback is
 *	implemented then the stack will not do fragmentation.
 *	The callback can sleep.
 *
 * @set_rts_threshold: Configuration of RTS threshold (if device needs it)
 *	The callback can sleep.
 *
@@ -1765,6 +1770,7 @@ struct ieee80211_ops {
			 struct ieee80211_low_level_stats *stats);
	void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx,
			     u32 *iv32, u16 *iv16);
	int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value);
	int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value);
	int (*sta_add)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
		       struct ieee80211_sta *sta);
+7 −0
Original line number Diff line number Diff line
@@ -1299,6 +1299,13 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
	struct ieee80211_local *local = wiphy_priv(wiphy);
	int err;

	if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
		err = drv_set_frag_threshold(local, wiphy->frag_threshold);

		if (err)
			return err;
	}

	if (changed & WIPHY_PARAM_COVERAGE_CLASS) {
		err = drv_set_coverage_class(local, wiphy->coverage_class);

+14 −0
Original line number Diff line number Diff line
@@ -233,6 +233,20 @@ static inline void drv_get_tkip_seq(struct ieee80211_local *local,
	trace_drv_get_tkip_seq(local, hw_key_idx, iv32, iv16);
}

static inline int drv_set_frag_threshold(struct ieee80211_local *local,
					u32 value)
{
	int ret = 0;

	might_sleep();

	trace_drv_set_frag_threshold(local, value);
	if (local->ops->set_frag_threshold)
		ret = local->ops->set_frag_threshold(&local->hw, value);
	trace_drv_return_int(local, ret);
	return ret;
}

static inline int drv_set_rts_threshold(struct ieee80211_local *local,
					u32 value)
{
+21 −0
Original line number Diff line number Diff line
@@ -531,6 +531,27 @@ TRACE_EVENT(drv_get_tkip_seq,
	)
);

TRACE_EVENT(drv_set_frag_threshold,
	TP_PROTO(struct ieee80211_local *local, u32 value),

	TP_ARGS(local, value),

	TP_STRUCT__entry(
		LOCAL_ENTRY
		__field(u32, value)
	),

	TP_fast_assign(
		LOCAL_ASSIGN;
		__entry->value = value;
	),

	TP_printk(
		LOCAL_PR_FMT " value:%d",
		LOCAL_PR_ARG, __entry->value
	)
);

TRACE_EVENT(drv_set_rts_threshold,
	TP_PROTO(struct ieee80211_local *local, u32 value),

+9 −2
Original line number Diff line number Diff line
@@ -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,7 +1186,9 @@ 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.
	 */
	if (!local->ops->set_frag_threshold)
		tx->flags |= IEEE80211_TX_FRAGMENTED;

	/* process and remove the injection radiotap header */
Loading