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

Commit ab13315a authored by Kalle Valo's avatar Kalle Valo Committed by John W. Linville
Browse files

mac80211: add U-APSD client support



Add Unscheduled Automatic Power-Save Delivery (U-APSD) client support. The
idea is that the data frames from the client trigger AP to send the buffered
frames with ACs which have U-APSD enabled. This decreases latency and makes it
possible to save even more power.

Driver needs to use IEEE80211_HW_UAPSD to enable the feature. The current
implementation assumes that firmware takes care of the wakeup and
hardware needing IEEE80211_HW_PS_NULLFUNC_STACK is not yet supported.

Tested with wl1251 on a Nokia N900 and Cisco Aironet 1231G AP and running
various test traffic with ping.

Signed-off-by: default avatarKalle Valo <kalle.valo@nokia.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 2d46d7c1
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -120,6 +120,24 @@
#define IEEE80211_QOS_CTL_TID_MASK	0x000F
#define IEEE80211_QOS_CTL_TAG1D_MASK	0x0007

/* U-APSD queue for WMM IEs sent by AP */
#define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD	(1<<7)

/* U-APSD queues for WMM IEs sent by STA */
#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VO	(1<<0)
#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VI	(1<<1)
#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BK	(1<<2)
#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BE	(1<<3)
#define IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK	0x0f

/* U-APSD max SP length for WMM IEs sent by STA */
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL	0x00
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_2	0x01
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_4	0x02
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_6	0x03
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK	0x03
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT	5

struct ieee80211_hdr {
	__le16 frame_control;
	__le16 duration_id;
+7 −0
Original line number Diff line number Diff line
@@ -113,6 +113,7 @@ struct ieee80211_tx_queue_params {
	u16 cw_min;
	u16 cw_max;
	u8 aifs;
	bool uapsd;
};

/**
@@ -929,6 +930,11 @@ enum ieee80211_tkip_key_type {
 *	Hardware supports dynamic spatial multiplexing powersave,
 *	ie. can turn off all but one chain and then wake the rest
 *	up as required after, for example, rts/cts handshake.
 *
 * @IEEE80211_HW_SUPPORTS_UAPSD:
 *	Hardware supports Unscheduled Automatic Power Save Delivery
 *	(U-APSD) in managed mode. The mode is configured with
 *	conf_tx() operation.
 */
enum ieee80211_hw_flags {
	IEEE80211_HW_HAS_RATE_CONTROL			= 1<<0,
@@ -948,6 +954,7 @@ enum ieee80211_hw_flags {
	IEEE80211_HW_BEACON_FILTER			= 1<<14,
	IEEE80211_HW_SUPPORTS_STATIC_SMPS		= 1<<15,
	IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS		= 1<<16,
	IEEE80211_HW_SUPPORTS_UAPSD			= 1<<17,
};

/**
+7 −0
Original line number Diff line number Diff line
@@ -1128,6 +1128,13 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
	p.cw_max = params->cwmax;
	p.cw_min = params->cwmin;
	p.txop = params->txop;

	/*
	 * Setting tx queue params disables u-apsd because it's only
	 * called in master mode.
	 */
	p.uapsd = false;

	if (drv_conf_tx(local, params->queue, &p)) {
		printk(KERN_DEBUG "%s: failed to set TX queue "
		       "parameters for queue %d\n",
+12 −1
Original line number Diff line number Diff line
@@ -58,6 +58,15 @@ struct ieee80211_local;

#define TU_TO_EXP_TIME(x)	(jiffies + usecs_to_jiffies((x) * 1024))

#define IEEE80211_DEFAULT_UAPSD_QUEUES \
	(IEEE80211_WMM_IE_STA_QOSINFO_AC_BK |	\
	 IEEE80211_WMM_IE_STA_QOSINFO_AC_BE |	\
	 IEEE80211_WMM_IE_STA_QOSINFO_AC_VI |	\
	 IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)

#define IEEE80211_DEFAULT_MAX_SP_LEN		\
	IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL

struct ieee80211_fragment_entry {
	unsigned long first_frag_time;
	unsigned int seq;
@@ -78,6 +87,7 @@ struct ieee80211_bss {
	u8 dtim_period;

	bool wmm_used;
	bool uapsd_supported;

	unsigned long last_probe_resp;

@@ -285,7 +295,7 @@ struct ieee80211_work {
			u8 ssid[IEEE80211_MAX_SSID_LEN];
			u8 ssid_len;
			u8 supp_rates_len;
			bool wmm_used, use_11n;
			bool wmm_used, use_11n, uapsd_used;
		} assoc;
		struct {
			u32 duration;
@@ -306,6 +316,7 @@ enum ieee80211_sta_flags {
	IEEE80211_STA_DISABLE_11N	= BIT(4),
	IEEE80211_STA_CSA_RECEIVED	= BIT(5),
	IEEE80211_STA_MFP_ENABLED	= BIT(6),
	IEEE80211_STA_UAPSD_ENABLED	= BIT(7),
};

struct ieee80211_if_managed {
+4 −0
Original line number Diff line number Diff line
@@ -491,6 +491,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
	else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
		local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;

	WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)
	     && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK),
	     "U-APSD not supported with HW_PS_NULLFUNC_STACK\n");

	/*
	 * Calculate scan IE length -- we need this to alloc
	 * memory and to subtract from the driver limit. It
Loading