Commit 8b325d2a authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'mac80211-next-for-net-next-2021-08-26' of...

Merge tag 'mac80211-next-for-net-next-2021-08-26' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next



Johannes Berg says:

====================
A few more things:
 * Use correct DFS domain for self-managed devices
 * some preparations for transmit power element handling
   and other 6 GHz regulatory handling
 * TWT support in AP mode in mac80211
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 723783d0 90bd5bee
Loading
Loading
Loading
Loading
+105 −1
Original line number Diff line number Diff line
@@ -1088,6 +1088,48 @@ struct ieee80211_ext {
	} u;
} __packed __aligned(2);

#define IEEE80211_TWT_CONTROL_NDP			BIT(0)
#define IEEE80211_TWT_CONTROL_RESP_MODE			BIT(1)
#define IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST	BIT(3)
#define IEEE80211_TWT_CONTROL_RX_DISABLED		BIT(4)
#define IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT		BIT(5)

#define IEEE80211_TWT_REQTYPE_REQUEST			BIT(0)
#define IEEE80211_TWT_REQTYPE_SETUP_CMD			GENMASK(3, 1)
#define IEEE80211_TWT_REQTYPE_TRIGGER			BIT(4)
#define IEEE80211_TWT_REQTYPE_IMPLICIT			BIT(5)
#define IEEE80211_TWT_REQTYPE_FLOWTYPE			BIT(6)
#define IEEE80211_TWT_REQTYPE_FLOWID			GENMASK(9, 7)
#define IEEE80211_TWT_REQTYPE_WAKE_INT_EXP		GENMASK(14, 10)
#define IEEE80211_TWT_REQTYPE_PROTECTION		BIT(15)

enum ieee80211_twt_setup_cmd {
	TWT_SETUP_CMD_REQUEST,
	TWT_SETUP_CMD_SUGGEST,
	TWT_SETUP_CMD_DEMAND,
	TWT_SETUP_CMD_GROUPING,
	TWT_SETUP_CMD_ACCEPT,
	TWT_SETUP_CMD_ALTERNATE,
	TWT_SETUP_CMD_DICTATE,
	TWT_SETUP_CMD_REJECT,
};

struct ieee80211_twt_params {
	__le16 req_type;
	__le64 twt;
	u8 min_twt_dur;
	__le16 mantissa;
	u8 channel;
} __packed;

struct ieee80211_twt_setup {
	u8 dialog_token;
	u8 element_id;
	u8 length;
	u8 control;
	u8 params[];
} __packed;

struct ieee80211_mgmt {
	__le16 frame_control;
	__le16 duration;
@@ -1252,6 +1294,10 @@ struct ieee80211_mgmt {
					__le16 toa_error;
					u8 variable[0];
				} __packed ftm;
				struct {
					u8 action_code;
					u8 variable[];
				} __packed s1g;
			} u;
		} __packed action;
	} u;
@@ -2266,6 +2312,9 @@ ieee80211_he_ppe_size(u8 ppe_thres_hdr, const u8 *phy_cap_info)
#define IEEE80211_HE_OPERATION_PARTIAL_BSS_COLOR		0x40000000
#define IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED		0x80000000

#define IEEE80211_6GHZ_CTRL_REG_LPI_AP	0
#define IEEE80211_6GHZ_CTRL_REG_SP_AP	1

/**
 * ieee80211_he_6ghz_oper - HE 6 GHz operation Information field
 * @primary: primary channel
@@ -2282,12 +2331,51 @@ struct ieee80211_he_6ghz_oper {
#define		IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_80MHZ	2
#define		IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ	3
#define IEEE80211_HE_6GHZ_OPER_CTRL_DUP_BEACON	0x4
#define IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO	0x38
	u8 control;
	u8 ccfs0;
	u8 ccfs1;
	u8 minrate;
} __packed;

/*
 * In "9.4.2.161 Transmit Power Envelope element" of "IEEE Std 802.11ax-2021",
 * it show four types in "Table 9-275a-Maximum Transmit Power Interpretation
 * subfield encoding", and two category for each type in "Table E-12-Regulatory
 * Info subfield encoding in the United States".
 * So it it totally max 8 Transmit Power Envelope element.
 */
#define IEEE80211_TPE_MAX_IE_COUNT	8
/*
 * In "Table 9-277—Meaning of Maximum Transmit Power Count subfield"
 * of "IEEE Std 802.11ax™‐2021", the max power level is 8.
 */
#define IEEE80211_MAX_NUM_PWR_LEVEL	8

#define IEEE80211_TPE_MAX_POWER_COUNT	8

/* transmit power interpretation type of transmit power envelope element */
enum ieee80211_tx_power_intrpt_type {
	IEEE80211_TPE_LOCAL_EIRP,
	IEEE80211_TPE_LOCAL_EIRP_PSD,
	IEEE80211_TPE_REG_CLIENT_EIRP,
	IEEE80211_TPE_REG_CLIENT_EIRP_PSD,
};

/**
 * struct ieee80211_tx_pwr_env
 *
 * This structure represents the "Transmit Power Envelope element"
 */
struct ieee80211_tx_pwr_env {
	u8 tx_power_info;
	s8 tx_power[IEEE80211_TPE_MAX_POWER_COUNT];
} __packed;

#define IEEE80211_TX_PWR_ENV_INFO_COUNT 0x7
#define IEEE80211_TX_PWR_ENV_INFO_INTERPRET 0x38
#define IEEE80211_TX_PWR_ENV_INFO_CATEGORY 0xC0

/*
 * ieee80211_he_oper_size - calculate 802.11ax HE Operations IE size
 * @he_oper_ie: byte data of the He Operations IE, stating from the byte
@@ -2869,7 +2957,7 @@ enum ieee80211_eid {
	WLAN_EID_VHT_OPERATION = 192,
	WLAN_EID_EXTENDED_BSS_LOAD = 193,
	WLAN_EID_WIDE_BW_CHANNEL_SWITCH = 194,
	WLAN_EID_VHT_TX_POWER_ENVELOPE = 195,
	WLAN_EID_TX_POWER_ENVELOPE = 195,
	WLAN_EID_CHANNEL_SWITCH_WRAPPER = 196,
	WLAN_EID_AID = 197,
	WLAN_EID_QUIET_CHANNEL = 198,
@@ -2881,6 +2969,7 @@ enum ieee80211_eid {
	WLAN_EID_AID_RESPONSE = 211,
	WLAN_EID_S1G_BCN_COMPAT = 213,
	WLAN_EID_S1G_SHORT_BCN_INTERVAL = 214,
	WLAN_EID_S1G_TWT = 216,
	WLAN_EID_S1G_CAPABILITIES = 217,
	WLAN_EID_VENDOR_SPECIFIC = 221,
	WLAN_EID_QOS_PARAMETER = 222,
@@ -2950,6 +3039,7 @@ enum ieee80211_category {
	WLAN_CATEGORY_FST = 18,
	WLAN_CATEGORY_UNPROT_DMG = 20,
	WLAN_CATEGORY_VHT = 21,
	WLAN_CATEGORY_S1G = 22,
	WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126,
	WLAN_CATEGORY_VENDOR_SPECIFIC = 127,
};
@@ -3023,6 +3113,20 @@ enum ieee80211_key_len {
	WLAN_KEY_LEN_BIP_GMAC_256 = 32,
};

enum ieee80211_s1g_actioncode {
	WLAN_S1G_AID_SWITCH_REQUEST,
	WLAN_S1G_AID_SWITCH_RESPONSE,
	WLAN_S1G_SYNC_CONTROL,
	WLAN_S1G_STA_INFO_ANNOUNCE,
	WLAN_S1G_EDCA_PARAM_SET,
	WLAN_S1G_EL_OPERATION,
	WLAN_S1G_TWT_SETUP,
	WLAN_S1G_TWT_TEARDOWN,
	WLAN_S1G_SECT_GROUP_ID_LIST,
	WLAN_S1G_SECT_ID_FEEDBACK,
	WLAN_S1G_TWT_INFORMATION = 11,
};

#define IEEE80211_WEP_IV_LEN		4
#define IEEE80211_WEP_ICV_LEN		4
#define IEEE80211_CCMP_HDR_LEN		8
+12 −0
Original line number Diff line number Diff line
@@ -3926,6 +3926,13 @@ struct ieee80211_prep_tx_info {
 * @set_sar_specs: Update the SAR (TX power) settings.
 * @sta_set_decap_offload: Called to notify the driver when a station is allowed
 *	to use rx decapsulation offload
 * @add_twt_setup: Update hw with TWT agreement parameters received from the peer.
 *	This callback allows the hw to check if requested parameters
 *	are supported and if there is enough room for a new agreement.
 *	The hw is expected to set agreement result in the req_type field of
 *	twt structure.
 * @twt_teardown_request: Update the hw with TWT teardown request received
 *	from the peer.
 */
struct ieee80211_ops {
	void (*tx)(struct ieee80211_hw *hw,
@@ -4249,6 +4256,11 @@ struct ieee80211_ops {
	void (*sta_set_decap_offload)(struct ieee80211_hw *hw,
				      struct ieee80211_vif *vif,
				      struct ieee80211_sta *sta, bool enabled);
	void (*add_twt_setup)(struct ieee80211_hw *hw,
			      struct ieee80211_sta *sta,
			      struct ieee80211_twt_setup *twt);
	void (*twt_teardown_request)(struct ieee80211_hw *hw,
				     struct ieee80211_sta *sta, u8 flowid);
};

/**
+36 −0
Original line number Diff line number Diff line
@@ -1447,4 +1447,40 @@ static inline void drv_sta_set_decap_offload(struct ieee80211_local *local,
	trace_drv_return_void(local);
}

static inline void drv_add_twt_setup(struct ieee80211_local *local,
				     struct ieee80211_sub_if_data *sdata,
				     struct ieee80211_sta *sta,
				     struct ieee80211_twt_setup *twt)
{
	struct ieee80211_twt_params *twt_agrt;

	might_sleep();

	if (!check_sdata_in_driver(sdata))
		return;

	twt_agrt = (void *)twt->params;

	trace_drv_add_twt_setup(local, sta, twt, twt_agrt);
	local->ops->add_twt_setup(&local->hw, sta, twt);
	trace_drv_return_void(local);
}

static inline void drv_twt_teardown_request(struct ieee80211_local *local,
					    struct ieee80211_sub_if_data *sdata,
					    struct ieee80211_sta *sta,
					    u8 flowid)
{
	might_sleep();
	if (!check_sdata_in_driver(sdata))
		return;

	if (!local->ops->twt_teardown_request)
		return;

	trace_drv_twt_teardown_request(local, sta, flowid);
	local->ops->twt_teardown_request(&local->hw, sta, flowid);
	trace_drv_return_void(local);
}

#endif /* __MAC80211_DRIVER_OPS */
+9 −0
Original line number Diff line number Diff line
@@ -946,6 +946,7 @@ struct ieee80211_sub_if_data {

	struct work_struct work;
	struct sk_buff_head skb_queue;
	struct sk_buff_head status_queue;

	u8 needed_rx_chains;
	enum ieee80211_smps_mode smps_mode;
@@ -1533,6 +1534,7 @@ struct ieee802_11_elems {
	const struct ieee80211_he_spr *he_spr;
	const struct ieee80211_mu_edca_param_set *mu_edca_param_set;
	const struct ieee80211_he_6ghz_capa *he_6ghz_capa;
	const struct ieee80211_tx_pwr_env *tx_pwr_env[IEEE80211_TPE_MAX_IE_COUNT];
	const u8 *uora_element;
	const u8 *mesh_id;
	const u8 *peering;
@@ -1583,6 +1585,8 @@ struct ieee802_11_elems {
	u8 perr_len;
	u8 country_elem_len;
	u8 bssid_index_len;
	u8 tx_pwr_env_len[IEEE80211_TPE_MAX_IE_COUNT];
	u8 tx_pwr_env_num;

	/* whether a parse error occurred while retrieving these elements */
	bool parse_error;
@@ -2080,6 +2084,11 @@ ieee80211_he_op_ie_to_bss_conf(struct ieee80211_vif *vif,

/* S1G */
void ieee80211_s1g_sta_rate_init(struct sta_info *sta);
bool ieee80211_s1g_is_twt_setup(struct sk_buff *skb);
void ieee80211_s1g_rx_twt_action(struct ieee80211_sub_if_data *sdata,
				 struct sk_buff *skb);
void ieee80211_s1g_status_twt_action(struct ieee80211_sub_if_data *sdata,
				     struct sk_buff *skb);

/* Spectrum management */
void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
+41 −0
Original line number Diff line number Diff line
@@ -552,6 +552,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
		 */
		ieee80211_free_keys(sdata, true);
		skb_queue_purge(&sdata->skb_queue);
		skb_queue_purge(&sdata->status_queue);
	}

	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
@@ -984,6 +985,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
	}

	skb_queue_head_init(&sdata->skb_queue);
	skb_queue_head_init(&sdata->status_queue);
	INIT_WORK(&sdata->work, ieee80211_iface_work);

	return 0;
@@ -1382,6 +1384,16 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
			WARN_ON(1);
			break;
		}
	} else if (ieee80211_is_action(mgmt->frame_control) &&
		   mgmt->u.action.category == WLAN_CATEGORY_S1G) {
		switch (mgmt->u.action.u.s1g.action_code) {
		case WLAN_S1G_TWT_TEARDOWN:
		case WLAN_S1G_TWT_SETUP:
			ieee80211_s1g_rx_twt_action(sdata, skb);
			break;
		default:
			break;
		}
	} else if (ieee80211_is_ext(mgmt->frame_control)) {
		if (sdata->vif.type == NL80211_IFTYPE_STATION)
			ieee80211_sta_rx_queued_ext(sdata, skb);
@@ -1437,6 +1449,24 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
	}
}

static void ieee80211_iface_process_status(struct ieee80211_sub_if_data *sdata,
					   struct sk_buff *skb)
{
	struct ieee80211_mgmt *mgmt = (void *)skb->data;

	if (ieee80211_is_action(mgmt->frame_control) &&
	    mgmt->u.action.category == WLAN_CATEGORY_S1G) {
		switch (mgmt->u.action.u.s1g.action_code) {
		case WLAN_S1G_TWT_TEARDOWN:
		case WLAN_S1G_TWT_SETUP:
			ieee80211_s1g_status_twt_action(sdata, skb);
			break;
		default:
			break;
		}
	}
}

static void ieee80211_iface_work(struct work_struct *work)
{
	struct ieee80211_sub_if_data *sdata =
@@ -1466,6 +1496,16 @@ static void ieee80211_iface_work(struct work_struct *work)
		kcov_remote_stop();
	}

	/* process status queue */
	while ((skb = skb_dequeue(&sdata->status_queue))) {
		kcov_remote_start_common(skb_get_kcov_handle(skb));

		ieee80211_iface_process_status(sdata, skb);
		kfree_skb(skb);

		kcov_remote_stop();
	}

	/* then other type-dependent work */
	switch (sdata->vif.type) {
	case NL80211_IFTYPE_STATION:
@@ -1529,6 +1569,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
	}

	skb_queue_head_init(&sdata->skb_queue);
	skb_queue_head_init(&sdata->status_queue);
	INIT_WORK(&sdata->work, ieee80211_iface_work);
	INIT_WORK(&sdata->recalc_smps, ieee80211_recalc_smps_work);
	INIT_WORK(&sdata->csa_finalize_work, ieee80211_csa_finalize_work);
Loading