1 // SPDX-License-Identifier: GPL-2.0-only
3 * This file is part of wlcore
5 * Copyright (C) 2014 Texas Instruments. All rights reserved.
8 #include <linux/pm_runtime.h>
10 #include <net/mac80211.h>
11 #include <net/netlink.h>
16 #include "vendor_cmd.h"
19 struct 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 },
27 wlcore_vendor_cmd_smart_config_start(struct wiphy *wiphy,
28 struct wireless_dev *wdev,
29 const void *data, int data_len)
31 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
32 struct wl1271 *wl = hw->priv;
33 struct nlattr *tb[NUM_WLCORE_VENDOR_ATTR];
36 wl1271_debug(DEBUG_CMD, "vendor cmd smart config start");
41 ret = nla_parse_deprecated(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len,
42 wlcore_vendor_attr_policy, NULL);
46 if (!tb[WLCORE_VENDOR_ATTR_GROUP_ID])
49 mutex_lock(&wl->mutex);
51 if (unlikely(wl->state != WLCORE_STATE_ON)) {
56 ret = pm_runtime_get_sync(wl->dev);
58 pm_runtime_put_noidle(wl->dev);
62 ret = wlcore_smart_config_start(wl,
63 nla_get_u32(tb[WLCORE_VENDOR_ATTR_GROUP_ID]));
65 pm_runtime_mark_last_busy(wl->dev);
66 pm_runtime_put_autosuspend(wl->dev);
68 mutex_unlock(&wl->mutex);
74 wlcore_vendor_cmd_smart_config_stop(struct wiphy *wiphy,
75 struct wireless_dev *wdev,
76 const void *data, int data_len)
78 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
79 struct wl1271 *wl = hw->priv;
82 wl1271_debug(DEBUG_CMD, "testmode cmd smart config stop");
84 mutex_lock(&wl->mutex);
86 if (unlikely(wl->state != WLCORE_STATE_ON)) {
91 ret = pm_runtime_get_sync(wl->dev);
93 pm_runtime_put_noidle(wl->dev);
97 ret = wlcore_smart_config_stop(wl);
99 pm_runtime_mark_last_busy(wl->dev);
100 pm_runtime_put_autosuspend(wl->dev);
102 mutex_unlock(&wl->mutex);
108 wlcore_vendor_cmd_smart_config_set_group_key(struct wiphy *wiphy,
109 struct wireless_dev *wdev,
110 const void *data, int data_len)
112 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
113 struct wl1271 *wl = hw->priv;
114 struct nlattr *tb[NUM_WLCORE_VENDOR_ATTR];
117 wl1271_debug(DEBUG_CMD, "testmode cmd smart config set group key");
122 ret = nla_parse_deprecated(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len,
123 wlcore_vendor_attr_policy, NULL);
127 if (!tb[WLCORE_VENDOR_ATTR_GROUP_ID] ||
128 !tb[WLCORE_VENDOR_ATTR_GROUP_KEY])
131 mutex_lock(&wl->mutex);
133 if (unlikely(wl->state != WLCORE_STATE_ON)) {
138 ret = pm_runtime_get_sync(wl->dev);
140 pm_runtime_put_noidle(wl->dev);
144 ret = wlcore_smart_config_set_group_key(wl,
145 nla_get_u32(tb[WLCORE_VENDOR_ATTR_GROUP_ID]),
146 nla_len(tb[WLCORE_VENDOR_ATTR_GROUP_KEY]),
147 nla_data(tb[WLCORE_VENDOR_ATTR_GROUP_KEY]));
149 pm_runtime_mark_last_busy(wl->dev);
150 pm_runtime_put_autosuspend(wl->dev);
152 mutex_unlock(&wl->mutex);
157 static const struct wiphy_vendor_command wlcore_vendor_commands[] = {
161 .subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_START,
163 .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
164 WIPHY_VENDOR_CMD_NEED_RUNNING,
165 .doit = wlcore_vendor_cmd_smart_config_start,
170 .subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_STOP,
172 .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
173 WIPHY_VENDOR_CMD_NEED_RUNNING,
174 .doit = wlcore_vendor_cmd_smart_config_stop,
179 .subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_SET_GROUP_KEY,
181 .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
182 WIPHY_VENDOR_CMD_NEED_RUNNING,
183 .doit = wlcore_vendor_cmd_smart_config_set_group_key,
187 static const struct nl80211_vendor_cmd_info wlcore_vendor_events[] = {
190 .subcmd = WLCORE_VENDOR_EVENT_SC_SYNC,
194 .subcmd = WLCORE_VENDOR_EVENT_SC_DECODE,
198 void wlcore_set_vendor_commands(struct wiphy *wiphy)
200 wiphy->vendor_commands = wlcore_vendor_commands;
201 wiphy->n_vendor_commands = ARRAY_SIZE(wlcore_vendor_commands);
202 wiphy->vendor_events = wlcore_vendor_events;
203 wiphy->n_vendor_events = ARRAY_SIZE(wlcore_vendor_events);