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

Commit feeb9785 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "wil6210: P2P_DEVICE virtual interface support"

parents fa70b1b6 172c3aac
Loading
Loading
Loading
Loading
+121 −14
Original line number Diff line number Diff line
@@ -78,6 +78,12 @@ wil_mgmt_stypes[NUM_NL80211_IFTYPES] = {
		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
		BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
	},
	[NL80211_IFTYPE_P2P_DEVICE] = {
		.tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
		BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
		BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
	},
};

static const u32 wil_cipher_suites[] = {
@@ -234,13 +240,67 @@ static int wil_cfg80211_dump_station(struct wiphy *wiphy,
	return rc;
}

static struct wireless_dev *
wil_cfg80211_add_iface(struct wiphy *wiphy, const char *name,
		       enum nl80211_iftype type,
		       u32 *flags, struct vif_params *params)
{
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
	struct net_device *ndev = wil_to_ndev(wil);
	struct wireless_dev *p2p_wdev;

	wil_dbg_misc(wil, "%s()\n", __func__);

	if (type != NL80211_IFTYPE_P2P_DEVICE) {
		wil_err(wil, "%s: unsupported iftype %d\n", __func__, type);
		return ERR_PTR(-EINVAL);
	}

	if (wil->p2p_wdev) {
		wil_err(wil, "%s: P2P_DEVICE interface already created\n",
			__func__);
		return ERR_PTR(-EINVAL);
	}

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

	p2p_wdev->iftype = type;
	p2p_wdev->wiphy = wiphy;
	/* use our primary ethernet address */
	ether_addr_copy(p2p_wdev->address, ndev->perm_addr);

	wil->p2p_wdev = p2p_wdev;

	return p2p_wdev;
}

static int wil_cfg80211_del_iface(struct wiphy *wiphy,
				  struct wireless_dev *wdev)
{
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);

	wil_dbg_misc(wil, "%s()\n", __func__);

	if (wdev != wil->p2p_wdev) {
		wil_err(wil, "%s: delete of incorrect interface 0x%p\n",
			__func__, wdev);
		return -EINVAL;
	}

	wil_p2p_wdev_free(wil);

	return 0;
}

static int wil_cfg80211_change_iface(struct wiphy *wiphy,
				     struct net_device *ndev,
				     enum nl80211_iftype type, u32 *flags,
				     struct vif_params *params)
{
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
	struct wireless_dev *wdev = wil->wdev;
	struct wireless_dev *wdev = wil_to_wdev(wil);
	int rc;

	wil_dbg_misc(wil, "%s() type=%d\n", __func__, type);
@@ -282,7 +342,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
			     struct cfg80211_scan_request *request)
{
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
	struct wireless_dev *wdev = wil->wdev;
	struct wireless_dev *wdev = request->wdev;
	struct {
		struct wmi_start_scan_cmd cmd;
		u16 chnl[4];
@@ -290,7 +350,8 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
	uint i, n;
	int rc;

	wil_dbg_misc(wil, "%s()\n", __func__);
	wil_dbg_misc(wil, "%s(), wdev=0x%p iftype=%d\n",
		     __func__, wdev, wdev->iftype);

	if (wil->scan_request) {
		wil_err(wil, "Already scanning\n");
@@ -301,6 +362,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
	switch (wdev->iftype) {
	case NL80211_IFTYPE_STATION:
	case NL80211_IFTYPE_P2P_CLIENT:
	case NL80211_IFTYPE_P2P_DEVICE:
		break;
	default:
		return -EOPNOTSUPP;
@@ -312,10 +374,16 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
		return -EBUSY;
	}

	/* check if scan request is a P2P search request */
	if (wil_scan_is_p2p_search(wil, request)) {
	/* scan on P2P_DEVICE is handled as p2p search */
	if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
		wil->scan_request = request;
		return wil_p2p_search(wil, request);
		wil->radio_wdev = wdev;
		rc = wil_p2p_search(wil, request);
		if (rc) {
			wil->radio_wdev = wil_to_wdev(wil);
			wil->scan_request = NULL;
		}
		return rc;
	}

	wil_p2p_stop_discovery(wil);
@@ -378,12 +446,14 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
		wil_dbg_misc(wil, "active scan with discovery_mode=1\n");
	}

	wil->radio_wdev = wdev;
	rc = wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) +
			cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0]));

out:
	if (rc) {
		del_timer_sync(&wil->scan_timer);
		wil->radio_wdev = wil_to_wdev(wil);
		wil->scan_request = NULL;
	}

@@ -647,7 +717,7 @@ static int wil_cfg80211_set_channel(struct wiphy *wiphy,
				    struct cfg80211_chan_def *chandef)
{
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
	struct wireless_dev *wdev = wil->wdev;
	struct wireless_dev *wdev = wil_to_wdev(wil);

	wdev->preset_chandef = *chandef;

@@ -657,7 +727,7 @@ static int wil_cfg80211_set_channel(struct wiphy *wiphy,
static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil,
					       bool pairwise)
{
	struct wireless_dev *wdev = wil->wdev;
	struct wireless_dev *wdev = wil_to_wdev(wil);
	enum wmi_key_usage rc;

	if (pairwise) {
@@ -809,14 +879,16 @@ static int wil_remain_on_channel(struct wiphy *wiphy,
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
	int rc;

	wil_dbg_misc(wil, "%s() center_freq=%d, duration=%d\n", __func__,
		     chan->center_freq, duration);
	wil_dbg_misc(wil, "%s() center_freq=%d, duration=%d iftype=%d\n",
		     __func__, chan->center_freq, duration, wdev->iftype);

	rc = wil_p2p_listen(wil, duration, chan, cookie);
	if (rc)
		return rc;

	cfg80211_ready_on_channel(wil->wdev, *cookie, chan, duration,
	wil->radio_wdev = wdev;

	cfg80211_ready_on_channel(wdev, *cookie, chan, duration,
				  GFP_KERNEL);

	return 0;
@@ -1263,7 +1335,26 @@ static int wil_cfg80211_change_bss(struct wiphy *wiphy,
	return 0;
}

static int wil_cfg80211_start_p2p_device(struct wiphy *wiphy,
					 struct wireless_dev *wdev)
{
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);

	wil_dbg_misc(wil, "%s: entered\n", __func__);
	return 0;
}

static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy,
					 struct wireless_dev *wdev)
{
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);

	wil_dbg_misc(wil, "%s: entered\n", __func__);
}

static struct cfg80211_ops wil_cfg80211_ops = {
	.add_virtual_intf = wil_cfg80211_add_iface,
	.del_virtual_intf = wil_cfg80211_del_iface,
	.scan = wil_cfg80211_scan,
	.connect = wil_cfg80211_connect,
	.disconnect = wil_cfg80211_disconnect,
@@ -1284,6 +1375,9 @@ static struct cfg80211_ops wil_cfg80211_ops = {
	.del_station = wil_cfg80211_del_station,
	.probe_client = wil_cfg80211_probe_client,
	.change_bss = wil_cfg80211_change_bss,
	/* P2P device */
	.start_p2p_device = wil_cfg80211_start_p2p_device,
	.stop_p2p_device = wil_cfg80211_stop_p2p_device,
};

static void wil_wiphy_init(struct wiphy *wiphy)
@@ -1296,9 +1390,7 @@ static void wil_wiphy_init(struct wiphy *wiphy)
				 BIT(NL80211_IFTYPE_AP) |
				 BIT(NL80211_IFTYPE_P2P_CLIENT) |
				 BIT(NL80211_IFTYPE_P2P_GO) |
				 /* enable this when supporting multi vif
				  * BIT(NL80211_IFTYPE_P2P_DEVICE) |
				  */
				 BIT(NL80211_IFTYPE_P2P_DEVICE) |
				 BIT(NL80211_IFTYPE_MONITOR);
	wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
			WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
@@ -1369,3 +1461,18 @@ void wil_wdev_free(struct wil6210_priv *wil)
	wiphy_free(wdev->wiphy);
	kfree(wdev);
}

void wil_p2p_wdev_free(struct wil6210_priv *wil)
{
	struct wireless_dev *p2p_wdev;

	mutex_lock(&wil->p2p_wdev_mutex);
	p2p_wdev = wil->p2p_wdev;
	if (p2p_wdev) {
		wil->p2p_wdev = NULL;
		wil->radio_wdev = wil_to_wdev(wil);
		cfg80211_unregister_wdev(p2p_wdev);
		kfree(p2p_wdev);
	}
	mutex_unlock(&wil->p2p_wdev_mutex);
}
+1 −0
Original line number Diff line number Diff line
@@ -446,6 +446,7 @@ int wil_priv_init(struct wil6210_priv *wil)
	mutex_init(&wil->mutex);
	mutex_init(&wil->wmi_mutex);
	mutex_init(&wil->probe_client_mutex);
	mutex_init(&wil->p2p_wdev_mutex);

	init_completion(&wil->wmi_ready);
	init_completion(&wil->wmi_call);
+1 −0
Original line number Diff line number Diff line
@@ -149,6 +149,7 @@ void *wil_if_alloc(struct device *dev)

	wil = wdev_to_wil(wdev);
	wil->wdev = wdev;
	wil->radio_wdev = wdev;

	wil_dbg_misc(wil, "%s()\n", __func__);

+15 −9
Original line number Diff line number Diff line
@@ -22,13 +22,6 @@
#define P2P_SEARCH_DURATION_MS 500
#define P2P_DEFAULT_BI 100

int wil_scan_is_p2p_search(struct wil6210_priv *wil,
			   struct cfg80211_scan_request *request)
{
	/* need P2P_DEVICE changes to make this work */
	return 0;
}

void wil_p2p_discovery_timer_fn(ulong x)
{
	struct wil6210_priv *wil = (void *)x;
@@ -183,10 +176,14 @@ void wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie)
			 __func__, p2p->cookie, cookie);

	wil_p2p_stop_discovery(wil);
	cfg80211_remain_on_channel_expired(wil->wdev,

	mutex_lock(&wil->p2p_wdev_mutex);
	cfg80211_remain_on_channel_expired(wil->radio_wdev,
					   p2p->cookie,
					   &p2p->listen_chan,
					   GFP_KERNEL);
	wil->radio_wdev = wil->wdev;
	mutex_unlock(&wil->p2p_wdev_mutex);
}

void wil_p2p_listen_expired(struct work_struct *work)
@@ -199,10 +196,15 @@ void wil_p2p_listen_expired(struct work_struct *work)
	wil_dbg_misc(wil, "%s()\n", __func__);

	wil_p2p_stop_discovery(wil);
	cfg80211_remain_on_channel_expired(wil->wdev,

	mutex_lock(&wil->p2p_wdev_mutex);
	cfg80211_remain_on_channel_expired(wil->radio_wdev,
					   p2p->cookie,
					   &p2p->listen_chan,
					   GFP_KERNEL);
	wil->radio_wdev = wil->wdev;
	mutex_unlock(&wil->p2p_wdev_mutex);

}

void wil_p2p_search_expired(struct work_struct *work)
@@ -215,6 +217,10 @@ void wil_p2p_search_expired(struct work_struct *work)
	wil_dbg_misc(wil, "%s()\n", __func__);

	wil_p2p_stop_discovery(wil);

	mutex_lock(&wil->p2p_wdev_mutex);
	cfg80211_scan_done(wil->scan_request, 0);
	wil->scan_request = NULL;
	wil->radio_wdev = wil->wdev;
	mutex_unlock(&wil->p2p_wdev_mutex);
}
+1 −0
Original line number Diff line number Diff line
@@ -275,6 +275,7 @@ static void wil_pcie_remove(struct pci_dev *pdev)
	pci_disable_device(pdev);
	if (wil->platform_ops.uninit)
		wil->platform_ops.uninit(wil->platform_handle);
	wil_p2p_wdev_free(wil);
	wil_if_free(wil);
}

Loading