File Index
Files and directories
Sign in
FILE

vendor_cmd.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/ti/wlcore/vendor_cmd.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * This file is part of wlcore
  4 *
  5 * Copyright (C) 2014 Texas Instruments. All rights reserved.
  6 */
  7
  8#include <linux/pm_runtime.h>
  9
 10#include <net/mac80211.h>
 11#include <net/netlink.h>
 12
 13#include "wlcore.h"
 14#include "debug.h"
 15#include "hw_ops.h"
 16#include "vendor_cmd.h"
 17
 18static const
 19struct nla_policy wlcore_vendor_attr_policy[NUM_WLCORE_VENDOR_ATTR] = {
 20	[WLCORE_VENDOR_ATTR_FREQ]		= { .type = NLA_U32 },
 21	[WLCORE_VENDOR_ATTR_GROUP_ID]		= { .type = NLA_U32 },
 22	[WLCORE_VENDOR_ATTR_GROUP_KEY]		= { .type = NLA_BINARY,
 23						    .len = WLAN_MAX_KEY_LEN },
 24};
 25
 26static int
 27wlcore_vendor_cmd_smart_config_start(struct wiphy *wiphy,
 28				     struct wireless_dev *wdev,
 29				     const void *data, int data_len)
 30{
 31	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
 32	struct wl1271 *wl = hw->priv;
 33	struct nlattr *tb[NUM_WLCORE_VENDOR_ATTR];
 34	int ret;
 35
 36	wl1271_debug(DEBUG_CMD, "vendor cmd smart config start");
 37
 38	if (!data)
 39		return -EINVAL;
 40
 41	ret = nla_parse_deprecated(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len,
 42				   wlcore_vendor_attr_policy, NULL);
 43	if (ret)
 44		return ret;
 45
 46	if (!tb[WLCORE_VENDOR_ATTR_GROUP_ID])
 47		return -EINVAL;
 48
 49	mutex_lock(&wl->mutex);
 50
 51	if (unlikely(wl->state != WLCORE_STATE_ON)) {
 52		ret = -EINVAL;
 53		goto out;
 54	}
 55
 56	ret = pm_runtime_resume_and_get(wl->dev);
 57	if (ret < 0)
 58		goto out;
 59
 60	ret = wlcore_smart_config_start(wl,
 61			nla_get_u32(tb[WLCORE_VENDOR_ATTR_GROUP_ID]));
 62
 63	pm_runtime_put_autosuspend(wl->dev);
 64out:
 65	mutex_unlock(&wl->mutex);
 66
 67	return ret;
 68}
 69
 70static int
 71wlcore_vendor_cmd_smart_config_stop(struct wiphy *wiphy,
 72				    struct wireless_dev *wdev,
 73				    const void *data, int data_len)
 74{
 75	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
 76	struct wl1271 *wl = hw->priv;
 77	int ret;
 78
 79	wl1271_debug(DEBUG_CMD, "testmode cmd smart config stop");
 80
 81	mutex_lock(&wl->mutex);
 82
 83	if (unlikely(wl->state != WLCORE_STATE_ON)) {
 84		ret = -EINVAL;
 85		goto out;
 86	}
 87
 88	ret = pm_runtime_resume_and_get(wl->dev);
 89	if (ret < 0)
 90		goto out;
 91
 92	ret = wlcore_smart_config_stop(wl);
 93
 94	pm_runtime_put_autosuspend(wl->dev);
 95out:
 96	mutex_unlock(&wl->mutex);
 97
 98	return ret;
 99}
100
101static int
102wlcore_vendor_cmd_smart_config_set_group_key(struct wiphy *wiphy,
103					     struct wireless_dev *wdev,
104					     const void *data, int data_len)
105{
106	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
107	struct wl1271 *wl = hw->priv;
108	struct nlattr *tb[NUM_WLCORE_VENDOR_ATTR];
109	int ret;
110
111	wl1271_debug(DEBUG_CMD, "testmode cmd smart config set group key");
112
113	if (!data)
114		return -EINVAL;
115
116	ret = nla_parse_deprecated(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len,
117				   wlcore_vendor_attr_policy, NULL);
118	if (ret)
119		return ret;
120
121	if (!tb[WLCORE_VENDOR_ATTR_GROUP_ID] ||
122	    !tb[WLCORE_VENDOR_ATTR_GROUP_KEY])
123		return -EINVAL;
124
125	mutex_lock(&wl->mutex);
126
127	if (unlikely(wl->state != WLCORE_STATE_ON)) {
128		ret = -EINVAL;
129		goto out;
130	}
131
132	ret = pm_runtime_resume_and_get(wl->dev);
133	if (ret < 0)
134		goto out;
135
136	ret = wlcore_smart_config_set_group_key(wl,
137			nla_get_u32(tb[WLCORE_VENDOR_ATTR_GROUP_ID]),
138			nla_len(tb[WLCORE_VENDOR_ATTR_GROUP_KEY]),
139			nla_data(tb[WLCORE_VENDOR_ATTR_GROUP_KEY]));
140
141	pm_runtime_put_autosuspend(wl->dev);
142out:
143	mutex_unlock(&wl->mutex);
144
145	return ret;
146}
147
148static const struct wiphy_vendor_command wlcore_vendor_commands[] = {
149	{
150		.info = {
151			.vendor_id = TI_OUI,
152			.subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_START,
153		},
154		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
155			 WIPHY_VENDOR_CMD_NEED_RUNNING,
156		.doit = wlcore_vendor_cmd_smart_config_start,
157		.policy = wlcore_vendor_attr_policy,
158	},
159	{
160		.info = {
161			.vendor_id = TI_OUI,
162			.subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_STOP,
163		},
164		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
165			 WIPHY_VENDOR_CMD_NEED_RUNNING,
166		.doit = wlcore_vendor_cmd_smart_config_stop,
167		.policy = wlcore_vendor_attr_policy,
168	},
169	{
170		.info = {
171			.vendor_id = TI_OUI,
172			.subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_SET_GROUP_KEY,
173		},
174		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
175			 WIPHY_VENDOR_CMD_NEED_RUNNING,
176		.doit = wlcore_vendor_cmd_smart_config_set_group_key,
177		.policy = wlcore_vendor_attr_policy,
178	},
179};
180
181static const struct nl80211_vendor_cmd_info wlcore_vendor_events[] = {
182	{
183		.vendor_id = TI_OUI,
184		.subcmd = WLCORE_VENDOR_EVENT_SC_SYNC,
185	},
186	{
187		.vendor_id = TI_OUI,
188		.subcmd = WLCORE_VENDOR_EVENT_SC_DECODE,
189	},
190};
191
192void wlcore_set_vendor_commands(struct wiphy *wiphy)
193{
194	wiphy->vendor_commands = wlcore_vendor_commands;
195	wiphy->n_vendor_commands = ARRAY_SIZE(wlcore_vendor_commands);
196	wiphy->vendor_events = wlcore_vendor_events;
197	wiphy->n_vendor_events = ARRAY_SIZE(wlcore_vendor_events);
198}
~/ Read-only file preview.