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

Commit 0c9b7f22 authored by Xinming Hu's avatar Xinming Hu Committed by Kalle Valo
Browse files

mwifiex: add schedule scan support



This patch add sched scan support for mwifiex, include cfg80211
sched_scan_start/sched_scan_stop handler, corresponding bgscan
command path and event handler.

Signed-off-by: default avatarXinming Hu <huxm@marvell.com>
Signed-off-by: default avatarchunfan chen <jeffc@marvell.com>
Signed-off-by: default avatarCathy Luo <cluo@marvell.com>
Signed-off-by: default avatarAmitkumar Karwar <akarwar@marvell.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent dc896b15
Loading
Loading
Loading
Loading
+134 −0
Original line number Diff line number Diff line
@@ -1962,6 +1962,9 @@ mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
{
	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);

	if (!mwifiex_stop_bg_scan(priv))
		cfg80211_sched_scan_stopped_rtnl(priv->wdev.wiphy);

	if (mwifiex_deauthenticate(priv, NULL))
		return -EFAULT;

@@ -2217,6 +2220,9 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
		    "info: Trying to associate to %s and bssid %pM\n",
		    (char *)sme->ssid, sme->bssid);

	if (!mwifiex_stop_bg_scan(priv))
		cfg80211_sched_scan_stopped_rtnl(priv->wdev.wiphy);

	ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid,
				     priv->bss_mode, sme->channel, sme, 0);
	if (!ret) {
@@ -2420,6 +2426,9 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
		return -EBUSY;
	}

	if (!mwifiex_stop_bg_scan(priv))
		cfg80211_sched_scan_stopped_rtnl(priv->wdev.wiphy);

	user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
	if (!user_scan_cfg)
		return -ENOMEM;
@@ -2487,6 +2496,121 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
	return 0;
}

/* CFG802.11 operation handler for sched_scan_start.
 *
 * This function issues a bgscan config request to the firmware based upon
 * the user specified sched_scan configuration. On successful completion,
 * firmware will generate BGSCAN_REPORT event, driver should issue bgscan
 * query command to get sched_scan results from firmware.
 */
static int
mwifiex_cfg80211_sched_scan_start(struct wiphy *wiphy,
				  struct net_device *dev,
				  struct cfg80211_sched_scan_request *request)
{
	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
	int i, offset;
	struct ieee80211_channel *chan;
	struct mwifiex_bg_scan_cfg *bgscan_cfg;
	struct ieee_types_header *ie;

	if (!request || (!request->n_ssids && !request->n_match_sets)) {
		wiphy_err(wiphy, "%s : Invalid Sched_scan parameters",
			  __func__);
		return -EINVAL;
	}

	wiphy_info(wiphy, "sched_scan start : n_ssids=%d n_match_sets=%d ",
		   request->n_ssids, request->n_match_sets);
	wiphy_info(wiphy, "n_channels=%d interval=%d ie_len=%d\n",
		   request->n_channels, request->scan_plans->interval,
		   (int)request->ie_len);

	bgscan_cfg = kzalloc(sizeof(*bgscan_cfg), GFP_KERNEL);
	if (!bgscan_cfg)
		return -ENOMEM;

	if (priv->scan_request || priv->scan_aborting)
		bgscan_cfg->start_later = true;

	bgscan_cfg->num_ssids = request->n_match_sets;
	bgscan_cfg->ssid_list = request->match_sets;

	if (request->ie && request->ie_len) {
		offset = 0;
		for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {
			if (priv->vs_ie[i].mask != MWIFIEX_VSIE_MASK_CLEAR)
				continue;
			priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_BGSCAN;
			ie = (struct ieee_types_header *)(request->ie + offset);
			memcpy(&priv->vs_ie[i].ie, ie, sizeof(*ie) + ie->len);
			offset += sizeof(*ie) + ie->len;

			if (offset >= request->ie_len)
				break;
		}
	}

	for (i = 0; i < min_t(u32, request->n_channels,
			      MWIFIEX_BG_SCAN_CHAN_MAX); i++) {
		chan = request->channels[i];
		bgscan_cfg->chan_list[i].chan_number = chan->hw_value;
		bgscan_cfg->chan_list[i].radio_type = chan->band;

		if ((chan->flags & IEEE80211_CHAN_NO_IR) || !request->n_ssids)
			bgscan_cfg->chan_list[i].scan_type =
						MWIFIEX_SCAN_TYPE_PASSIVE;
		else
			bgscan_cfg->chan_list[i].scan_type =
						MWIFIEX_SCAN_TYPE_ACTIVE;

		bgscan_cfg->chan_list[i].scan_time = 0;
	}

	bgscan_cfg->chan_per_scan = min_t(u32, request->n_channels,
					  MWIFIEX_BG_SCAN_CHAN_MAX);

	/* Use at least 15 second for per scan cycle */
	bgscan_cfg->scan_interval = (request->scan_plans->interval >
				     MWIFIEX_BGSCAN_INTERVAL) ?
				request->scan_plans->interval :
				MWIFIEX_BGSCAN_INTERVAL;

	bgscan_cfg->repeat_count = MWIFIEX_BGSCAN_REPEAT_COUNT;
	bgscan_cfg->report_condition = MWIFIEX_BGSCAN_SSID_MATCH |
				MWIFIEX_BGSCAN_WAIT_ALL_CHAN_DONE;
	bgscan_cfg->bss_type = MWIFIEX_BSS_MODE_INFRA;
	bgscan_cfg->action = MWIFIEX_BGSCAN_ACT_SET;
	bgscan_cfg->enable = true;

	if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_CONFIG,
			     HostCmd_ACT_GEN_SET, 0, bgscan_cfg, true)) {
		kfree(bgscan_cfg);
		return -EFAULT;
	}

	priv->sched_scanning = true;

	kfree(bgscan_cfg);
	return 0;
}

/* CFG802.11 operation handler for sched_scan_stop.
 *
 * This function issues a bgscan config command to disable
 * previous bgscan configuration in the firmware
 */
static int mwifiex_cfg80211_sched_scan_stop(struct wiphy *wiphy,
					    struct net_device *dev)
{
	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);

	wiphy_info(wiphy, "sched scan stop!");
	mwifiex_stop_bg_scan(priv);

	return 0;
}

static void mwifiex_setup_vht_caps(struct ieee80211_sta_vht_cap *vht_info,
				   struct mwifiex_private *priv)
{
@@ -2848,6 +2972,9 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
	mwifiex_dev_debugfs_remove(priv);
#endif

	if (priv->sched_scanning)
		priv->sched_scanning = false;

	mwifiex_stop_net_dev_queue(priv->netdev, adapter);

	skb_queue_walk_safe(&priv->bypass_txq, skb, tmp)
@@ -3701,6 +3828,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
	.set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config,
	.set_antenna = mwifiex_cfg80211_set_antenna,
	.del_station = mwifiex_cfg80211_del_station,
	.sched_scan_start = mwifiex_cfg80211_sched_scan_start,
	.sched_scan_stop = mwifiex_cfg80211_sched_scan_stop,
#ifdef CONFIG_PM
	.suspend = mwifiex_cfg80211_suspend,
	.resume = mwifiex_cfg80211_resume,
@@ -3829,6 +3958,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
	wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
			WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
			WIPHY_FLAG_AP_UAPSD |
			WIPHY_FLAG_SUPPORTS_SCHED_SCAN |
			WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
			WIPHY_FLAG_HAS_CHANNEL_SWITCH |
			WIPHY_FLAG_PS_ON_BY_DEFAULT;
@@ -3847,6 +3977,10 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
				    NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
				    NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;

	wiphy->max_sched_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;
	wiphy->max_sched_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
	wiphy->max_match_sets = MWIFIEX_MAX_SSID_LIST_LENGTH;

	wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;
	wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;

+59 −0
Original line number Diff line number Diff line
@@ -144,6 +144,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define TLV_TYPE_WILDCARDSSID       (PROPRIETARY_TLV_BASE_ID + 18)
#define TLV_TYPE_TSFTIMESTAMP       (PROPRIETARY_TLV_BASE_ID + 19)
#define TLV_TYPE_RSSI_HIGH          (PROPRIETARY_TLV_BASE_ID + 22)
#define TLV_TYPE_BGSCAN_START_LATER (PROPRIETARY_TLV_BASE_ID + 30)
#define TLV_TYPE_AUTH_TYPE          (PROPRIETARY_TLV_BASE_ID + 31)
#define TLV_TYPE_STA_MAC_ADDR       (PROPRIETARY_TLV_BASE_ID + 32)
#define TLV_TYPE_BSSID              (PROPRIETARY_TLV_BASE_ID + 35)
@@ -177,6 +178,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define TLV_TYPE_TX_PAUSE           (PROPRIETARY_TLV_BASE_ID + 148)
#define TLV_TYPE_COALESCE_RULE      (PROPRIETARY_TLV_BASE_ID + 154)
#define TLV_TYPE_KEY_PARAM_V2       (PROPRIETARY_TLV_BASE_ID + 156)
#define TLV_TYPE_REPEAT_COUNT       (PROPRIETARY_TLV_BASE_ID + 176)
#define TLV_TYPE_MULTI_CHAN_INFO    (PROPRIETARY_TLV_BASE_ID + 183)
#define TLV_TYPE_MC_GROUP_INFO      (PROPRIETARY_TLV_BASE_ID + 184)
#define TLV_TYPE_TDLS_IDLE_TIMEOUT  (PROPRIETARY_TLV_BASE_ID + 194)
@@ -331,6 +333,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define HostCmd_CMD_802_11_MAC_ADDRESS                0x004D
#define HostCmd_CMD_802_11D_DOMAIN_INFO               0x005b
#define HostCmd_CMD_802_11_KEY_MATERIAL               0x005e
#define HostCmd_CMD_802_11_BG_SCAN_CONFIG             0x006b
#define HostCmd_CMD_802_11_BG_SCAN_QUERY              0x006c
#define HostCmd_CMD_WMM_GET_STATUS                    0x0071
#define HostCmd_CMD_802_11_SUBSCRIBE_EVENT            0x0075
@@ -523,6 +526,7 @@ enum P2P_MODES {
#define EVENT_CHANNEL_REPORT_RDY        0x00000054
#define EVENT_TX_DATA_PAUSE             0x00000055
#define EVENT_EXT_SCAN_REPORT           0x00000058
#define EVENT_BG_SCAN_STOPPED           0x00000065
#define EVENT_REMAIN_ON_CHAN_EXPIRED    0x0000005f
#define EVENT_MULTI_CHAN_INFO           0x0000006a
#define EVENT_TX_STATUS_REPORT		0x00000074
@@ -733,6 +737,16 @@ struct mwifiex_ie_types_num_probes {
	__le16 num_probes;
} __packed;

struct mwifiex_ie_types_repeat_count {
	struct mwifiex_ie_types_header header;
	__le16 repeat_count;
} __packed;

struct mwifiex_ie_types_bgscan_start_later {
	struct mwifiex_ie_types_header header;
	__le16 start_later;
} __packed;

struct mwifiex_ie_types_scan_chan_gap {
	struct mwifiex_ie_types_header header;
	/* time gap in TUs to be used between two consecutive channels scan */
@@ -1425,6 +1439,36 @@ struct mwifiex_user_scan_cfg {
	u16 scan_chan_gap;
} __packed;

#define MWIFIEX_BG_SCAN_CHAN_MAX 38
#define MWIFIEX_BSS_MODE_INFRA 1
#define MWIFIEX_BGSCAN_ACT_GET     0x0000
#define MWIFIEX_BGSCAN_ACT_SET     0x0001
#define MWIFIEX_BGSCAN_ACT_SET_ALL 0xff01
/** ssid match */
#define MWIFIEX_BGSCAN_SSID_MATCH          0x0001
/** ssid match and RSSI exceeded */
#define MWIFIEX_BGSCAN_SSID_RSSI_MATCH     0x0004
/**wait for all channel scan to complete to report scan result*/
#define MWIFIEX_BGSCAN_WAIT_ALL_CHAN_DONE  0x80000000

struct mwifiex_bg_scan_cfg {
	u16 action;
	u8 enable;
	u8 bss_type;
	u8 chan_per_scan;
	u32 scan_interval;
	u32 report_condition;
	u8 num_probes;
	u8 rssi_threshold;
	u8 snr_threshold;
	u16 repeat_count;
	u16 start_later;
	struct cfg80211_match_set *ssid_list;
	u8 num_ssids;
	struct mwifiex_user_scan_chan chan_list[MWIFIEX_BG_SCAN_CHAN_MAX];
	u16 scan_chan_gap;
} __packed;

struct ie_body {
	u8 grp_key_oui[4];
	u8 ptk_cnt[2];
@@ -1470,6 +1514,20 @@ struct mwifiex_ie_types_bss_scan_info {
	__le64 tsf;
} __packed;

struct host_cmd_ds_802_11_bg_scan_config {
	__le16 action;
	u8 enable;
	u8 bss_type;
	u8 chan_per_scan;
	u8 reserved;
	__le16 reserved1;
	__le32 scan_interval;
	__le32 reserved2;
	__le32 report_condition;
	__le16 reserved3;
	u8 tlv[0];
} __packed;

struct host_cmd_ds_802_11_bg_scan_query {
	u8 flush;
} __packed;
@@ -2124,6 +2182,7 @@ struct host_cmd_ds_command {
		struct host_cmd_ds_802_11_scan scan;
		struct host_cmd_ds_802_11_scan_ext ext_scan;
		struct host_cmd_ds_802_11_scan_rsp scan_resp;
		struct host_cmd_ds_802_11_bg_scan_config bg_scan_config;
		struct host_cmd_ds_802_11_bg_scan_query bg_scan_query;
		struct host_cmd_ds_802_11_bg_scan_query_rsp bg_scan_query_resp;
		struct host_cmd_ds_802_11_associate associate;
+1 −0
Original line number Diff line number Diff line
@@ -414,6 +414,7 @@ struct mwifiex_ds_mef_cfg {
#define MWIFIEX_VSIE_MASK_SCAN     0x01
#define MWIFIEX_VSIE_MASK_ASSOC    0x02
#define MWIFIEX_VSIE_MASK_ADHOC    0x04
#define MWIFIEX_VSIE_MASK_BGSCAN   0x08

enum {
	MWIFIEX_FUNC_INIT = 1,
+7 −0
Original line number Diff line number Diff line
@@ -746,6 +746,13 @@ int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb)

	mwifiex_queue_main_work(priv->adapter);

	if (priv->sched_scanning) {
		mwifiex_dbg(priv->adapter, INFO,
			    "aborting bgscan on ndo_stop\n");
		mwifiex_stop_bg_scan(priv);
		cfg80211_sched_scan_stopped(priv->wdev.wiphy);
	}

	return 0;
}

+10 −0
Original line number Diff line number Diff line
@@ -198,6 +198,11 @@ do { \
			       buf, len, false);		\
} while (0)

/** Min BGSCAN interval 15 second */
#define MWIFIEX_BGSCAN_INTERVAL 15000
/** default repeat count */
#define MWIFIEX_BGSCAN_REPEAT_COUNT 6

struct mwifiex_dbg {
	u32 num_cmd_host_to_card_failure;
	u32 num_cmd_sleep_cfm_host_to_card_failure;
@@ -641,6 +646,7 @@ struct mwifiex_private {
	u32 mgmt_frame_mask;
	struct mwifiex_roc_cfg roc_cfg;
	bool scan_aborting;
	u8 sched_scanning;
	u8 csa_chan;
	unsigned long csa_expire_time;
	u8 del_list_idx;
@@ -1198,6 +1204,10 @@ int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
				struct host_cmd_ds_command *resp);
int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
					 void *buf);
int mwifiex_cmd_802_11_bg_scan_config(struct mwifiex_private *priv,
				      struct host_cmd_ds_command *cmd,
				      void *data_buf);
int mwifiex_stop_bg_scan(struct mwifiex_private *priv);

/*
 * This function checks if the queuing is RA based or not.
Loading