17b3115f2SLuciano Coelho /*
27b3115f2SLuciano Coelho  * This file is part of wl1271
37b3115f2SLuciano Coelho  *
47b3115f2SLuciano Coelho  * Copyright (C) 2010 Nokia Corporation
57b3115f2SLuciano Coelho  *
67b3115f2SLuciano Coelho  * Contact: Luciano Coelho <luciano.coelho@nokia.com>
77b3115f2SLuciano Coelho  *
87b3115f2SLuciano Coelho  * This program is free software; you can redistribute it and/or
97b3115f2SLuciano Coelho  * modify it under the terms of the GNU General Public License
107b3115f2SLuciano Coelho  * version 2 as published by the Free Software Foundation.
117b3115f2SLuciano Coelho  *
127b3115f2SLuciano Coelho  * This program is distributed in the hope that it will be useful, but
137b3115f2SLuciano Coelho  * WITHOUT ANY WARRANTY; without even the implied warranty of
147b3115f2SLuciano Coelho  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
157b3115f2SLuciano Coelho  * General Public License for more details.
167b3115f2SLuciano Coelho  *
177b3115f2SLuciano Coelho  * You should have received a copy of the GNU General Public License
187b3115f2SLuciano Coelho  * along with this program; if not, write to the Free Software
197b3115f2SLuciano Coelho  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
207b3115f2SLuciano Coelho  * 02110-1301 USA
217b3115f2SLuciano Coelho  *
227b3115f2SLuciano Coelho  */
237b3115f2SLuciano Coelho #include "testmode.h"
247b3115f2SLuciano Coelho 
257b3115f2SLuciano Coelho #include <linux/slab.h>
267b3115f2SLuciano Coelho #include <net/genetlink.h>
277b3115f2SLuciano Coelho 
28c31be25aSLuciano Coelho #include "wlcore.h"
297b3115f2SLuciano Coelho #include "debug.h"
307b3115f2SLuciano Coelho #include "acx.h"
317b3115f2SLuciano Coelho #include "ps.h"
327b3115f2SLuciano Coelho #include "io.h"
337b3115f2SLuciano Coelho 
347b3115f2SLuciano Coelho #define WL1271_TM_MAX_DATA_LENGTH 1024
357b3115f2SLuciano Coelho 
367b3115f2SLuciano Coelho enum wl1271_tm_commands {
377b3115f2SLuciano Coelho 	WL1271_TM_CMD_UNSPEC,
387b3115f2SLuciano Coelho 	WL1271_TM_CMD_TEST,
397b3115f2SLuciano Coelho 	WL1271_TM_CMD_INTERROGATE,
407b3115f2SLuciano Coelho 	WL1271_TM_CMD_CONFIGURE,
417b3115f2SLuciano Coelho 	WL1271_TM_CMD_NVS_PUSH,		/* Not in use. Keep to not break ABI */
427b3115f2SLuciano Coelho 	WL1271_TM_CMD_SET_PLT_MODE,
43fd92dc5dSArik Nemtsov 	WL1271_TM_CMD_RECOVER,		/* Not in use. Keep to not break ABI */
447b3115f2SLuciano Coelho 	WL1271_TM_CMD_GET_MAC,
457b3115f2SLuciano Coelho 
467b3115f2SLuciano Coelho 	__WL1271_TM_CMD_AFTER_LAST
477b3115f2SLuciano Coelho };
487b3115f2SLuciano Coelho #define WL1271_TM_CMD_MAX (__WL1271_TM_CMD_AFTER_LAST - 1)
497b3115f2SLuciano Coelho 
507b3115f2SLuciano Coelho enum wl1271_tm_attrs {
517b3115f2SLuciano Coelho 	WL1271_TM_ATTR_UNSPEC,
527b3115f2SLuciano Coelho 	WL1271_TM_ATTR_CMD_ID,
537b3115f2SLuciano Coelho 	WL1271_TM_ATTR_ANSWER,
547b3115f2SLuciano Coelho 	WL1271_TM_ATTR_DATA,
557b3115f2SLuciano Coelho 	WL1271_TM_ATTR_IE_ID,
567b3115f2SLuciano Coelho 	WL1271_TM_ATTR_PLT_MODE,
577b3115f2SLuciano Coelho 
587b3115f2SLuciano Coelho 	__WL1271_TM_ATTR_AFTER_LAST
597b3115f2SLuciano Coelho };
607b3115f2SLuciano Coelho #define WL1271_TM_ATTR_MAX (__WL1271_TM_ATTR_AFTER_LAST - 1)
617b3115f2SLuciano Coelho 
627b3115f2SLuciano Coelho static struct nla_policy wl1271_tm_policy[WL1271_TM_ATTR_MAX + 1] = {
637b3115f2SLuciano Coelho 	[WL1271_TM_ATTR_CMD_ID] =	{ .type = NLA_U32 },
647b3115f2SLuciano Coelho 	[WL1271_TM_ATTR_ANSWER] =	{ .type = NLA_U8 },
657b3115f2SLuciano Coelho 	[WL1271_TM_ATTR_DATA] =		{ .type = NLA_BINARY,
667b3115f2SLuciano Coelho 					  .len = WL1271_TM_MAX_DATA_LENGTH },
677b3115f2SLuciano Coelho 	[WL1271_TM_ATTR_IE_ID] =	{ .type = NLA_U32 },
687b3115f2SLuciano Coelho 	[WL1271_TM_ATTR_PLT_MODE] =	{ .type = NLA_U32 },
697b3115f2SLuciano Coelho };
707b3115f2SLuciano Coelho 
717b3115f2SLuciano Coelho 
727b3115f2SLuciano Coelho static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[])
737b3115f2SLuciano Coelho {
747b3115f2SLuciano Coelho 	int buf_len, ret, len;
757b3115f2SLuciano Coelho 	struct sk_buff *skb;
767b3115f2SLuciano Coelho 	void *buf;
777b3115f2SLuciano Coelho 	u8 answer = 0;
787b3115f2SLuciano Coelho 
797b3115f2SLuciano Coelho 	wl1271_debug(DEBUG_TESTMODE, "testmode cmd test");
807b3115f2SLuciano Coelho 
817b3115f2SLuciano Coelho 	if (!tb[WL1271_TM_ATTR_DATA])
827b3115f2SLuciano Coelho 		return -EINVAL;
837b3115f2SLuciano Coelho 
847b3115f2SLuciano Coelho 	buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
857b3115f2SLuciano Coelho 	buf_len = nla_len(tb[WL1271_TM_ATTR_DATA]);
867b3115f2SLuciano Coelho 
877b3115f2SLuciano Coelho 	if (tb[WL1271_TM_ATTR_ANSWER])
887b3115f2SLuciano Coelho 		answer = nla_get_u8(tb[WL1271_TM_ATTR_ANSWER]);
897b3115f2SLuciano Coelho 
907b3115f2SLuciano Coelho 	if (buf_len > sizeof(struct wl1271_command))
917b3115f2SLuciano Coelho 		return -EMSGSIZE;
927b3115f2SLuciano Coelho 
937b3115f2SLuciano Coelho 	mutex_lock(&wl->mutex);
947b3115f2SLuciano Coelho 
957b3115f2SLuciano Coelho 	if (wl->state == WL1271_STATE_OFF) {
967b3115f2SLuciano Coelho 		ret = -EINVAL;
977b3115f2SLuciano Coelho 		goto out;
987b3115f2SLuciano Coelho 	}
997b3115f2SLuciano Coelho 
1007b3115f2SLuciano Coelho 	ret = wl1271_ps_elp_wakeup(wl);
1017b3115f2SLuciano Coelho 	if (ret < 0)
1027b3115f2SLuciano Coelho 		goto out;
1037b3115f2SLuciano Coelho 
1047b3115f2SLuciano Coelho 	ret = wl1271_cmd_test(wl, buf, buf_len, answer);
1057b3115f2SLuciano Coelho 	if (ret < 0) {
1067b3115f2SLuciano Coelho 		wl1271_warning("testmode cmd test failed: %d", ret);
1077b3115f2SLuciano Coelho 		goto out_sleep;
1087b3115f2SLuciano Coelho 	}
1097b3115f2SLuciano Coelho 
1107b3115f2SLuciano Coelho 	if (answer) {
111b0b09e31SYair Shapira 		/* If we got bip calibration answer print radio status */
112b0b09e31SYair Shapira 		struct wl1271_cmd_cal_p2g *params =
113b0b09e31SYair Shapira 			(struct wl1271_cmd_cal_p2g *) buf;
114b0b09e31SYair Shapira 
115b0b09e31SYair Shapira 		s16 radio_status = (s16) le16_to_cpu(params->radio_status);
116b0b09e31SYair Shapira 
117b0b09e31SYair Shapira 		if (params->test.id == TEST_CMD_P2G_CAL &&
118b0b09e31SYair Shapira 		    radio_status < 0)
119b0b09e31SYair Shapira 			wl1271_warning("testmode cmd: radio status=%d",
120b0b09e31SYair Shapira 					radio_status);
121b0b09e31SYair Shapira 		else
122b0b09e31SYair Shapira 			wl1271_info("testmode cmd: radio status=%d",
123b0b09e31SYair Shapira 					radio_status);
124b0b09e31SYair Shapira 
1257b3115f2SLuciano Coelho 		len = nla_total_size(buf_len);
1267b3115f2SLuciano Coelho 		skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, len);
1277b3115f2SLuciano Coelho 		if (!skb) {
1287b3115f2SLuciano Coelho 			ret = -ENOMEM;
1297b3115f2SLuciano Coelho 			goto out_sleep;
1307b3115f2SLuciano Coelho 		}
1317b3115f2SLuciano Coelho 
13259ef43e6SJohn W. Linville 		if (nla_put(skb, WL1271_TM_ATTR_DATA, buf_len, buf))
13359ef43e6SJohn W. Linville 			goto nla_put_failure;
1347b3115f2SLuciano Coelho 		ret = cfg80211_testmode_reply(skb);
1357b3115f2SLuciano Coelho 		if (ret < 0)
1367b3115f2SLuciano Coelho 			goto out_sleep;
1377b3115f2SLuciano Coelho 	}
1387b3115f2SLuciano Coelho 
1397b3115f2SLuciano Coelho out_sleep:
1407b3115f2SLuciano Coelho 	wl1271_ps_elp_sleep(wl);
1417b3115f2SLuciano Coelho out:
1427b3115f2SLuciano Coelho 	mutex_unlock(&wl->mutex);
1437b3115f2SLuciano Coelho 
1447b3115f2SLuciano Coelho 	return ret;
1457b3115f2SLuciano Coelho 
1467b3115f2SLuciano Coelho nla_put_failure:
1477b3115f2SLuciano Coelho 	kfree_skb(skb);
1487b3115f2SLuciano Coelho 	ret = -EMSGSIZE;
1497b3115f2SLuciano Coelho 	goto out_sleep;
1507b3115f2SLuciano Coelho }
1517b3115f2SLuciano Coelho 
1527b3115f2SLuciano Coelho static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[])
1537b3115f2SLuciano Coelho {
1547b3115f2SLuciano Coelho 	int ret;
1557b3115f2SLuciano Coelho 	struct wl1271_command *cmd;
1567b3115f2SLuciano Coelho 	struct sk_buff *skb;
1577b3115f2SLuciano Coelho 	u8 ie_id;
1587b3115f2SLuciano Coelho 
1597b3115f2SLuciano Coelho 	wl1271_debug(DEBUG_TESTMODE, "testmode cmd interrogate");
1607b3115f2SLuciano Coelho 
1617b3115f2SLuciano Coelho 	if (!tb[WL1271_TM_ATTR_IE_ID])
1627b3115f2SLuciano Coelho 		return -EINVAL;
1637b3115f2SLuciano Coelho 
1647b3115f2SLuciano Coelho 	ie_id = nla_get_u8(tb[WL1271_TM_ATTR_IE_ID]);
1657b3115f2SLuciano Coelho 
1667b3115f2SLuciano Coelho 	mutex_lock(&wl->mutex);
1677b3115f2SLuciano Coelho 
1687b3115f2SLuciano Coelho 	if (wl->state == WL1271_STATE_OFF) {
1697b3115f2SLuciano Coelho 		ret = -EINVAL;
1707b3115f2SLuciano Coelho 		goto out;
1717b3115f2SLuciano Coelho 	}
1727b3115f2SLuciano Coelho 
1737b3115f2SLuciano Coelho 	ret = wl1271_ps_elp_wakeup(wl);
1747b3115f2SLuciano Coelho 	if (ret < 0)
1757b3115f2SLuciano Coelho 		goto out;
1767b3115f2SLuciano Coelho 
1777b3115f2SLuciano Coelho 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1787b3115f2SLuciano Coelho 	if (!cmd) {
1797b3115f2SLuciano Coelho 		ret = -ENOMEM;
1807b3115f2SLuciano Coelho 		goto out_sleep;
1817b3115f2SLuciano Coelho 	}
1827b3115f2SLuciano Coelho 
1837b3115f2SLuciano Coelho 	ret = wl1271_cmd_interrogate(wl, ie_id, cmd, sizeof(*cmd));
1847b3115f2SLuciano Coelho 	if (ret < 0) {
1857b3115f2SLuciano Coelho 		wl1271_warning("testmode cmd interrogate failed: %d", ret);
1867b3115f2SLuciano Coelho 		goto out_free;
1877b3115f2SLuciano Coelho 	}
1887b3115f2SLuciano Coelho 
1897b3115f2SLuciano Coelho 	skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, sizeof(*cmd));
1907b3115f2SLuciano Coelho 	if (!skb) {
1917b3115f2SLuciano Coelho 		ret = -ENOMEM;
1927b3115f2SLuciano Coelho 		goto out_free;
1937b3115f2SLuciano Coelho 	}
1947b3115f2SLuciano Coelho 
19559ef43e6SJohn W. Linville 	if (nla_put(skb, WL1271_TM_ATTR_DATA, sizeof(*cmd), cmd))
19659ef43e6SJohn W. Linville 		goto nla_put_failure;
1977b3115f2SLuciano Coelho 	ret = cfg80211_testmode_reply(skb);
1987b3115f2SLuciano Coelho 	if (ret < 0)
1997b3115f2SLuciano Coelho 		goto out_free;
2007b3115f2SLuciano Coelho 
2017b3115f2SLuciano Coelho out_free:
2027b3115f2SLuciano Coelho 	kfree(cmd);
2037b3115f2SLuciano Coelho out_sleep:
2047b3115f2SLuciano Coelho 	wl1271_ps_elp_sleep(wl);
2057b3115f2SLuciano Coelho out:
2067b3115f2SLuciano Coelho 	mutex_unlock(&wl->mutex);
2077b3115f2SLuciano Coelho 
2087b3115f2SLuciano Coelho 	return ret;
2097b3115f2SLuciano Coelho 
2107b3115f2SLuciano Coelho nla_put_failure:
2117b3115f2SLuciano Coelho 	kfree_skb(skb);
2127b3115f2SLuciano Coelho 	ret = -EMSGSIZE;
2137b3115f2SLuciano Coelho 	goto out_free;
2147b3115f2SLuciano Coelho }
2157b3115f2SLuciano Coelho 
2167b3115f2SLuciano Coelho static int wl1271_tm_cmd_configure(struct wl1271 *wl, struct nlattr *tb[])
2177b3115f2SLuciano Coelho {
2187b3115f2SLuciano Coelho 	int buf_len, ret;
2197b3115f2SLuciano Coelho 	void *buf;
2207b3115f2SLuciano Coelho 	u8 ie_id;
2217b3115f2SLuciano Coelho 
2227b3115f2SLuciano Coelho 	wl1271_debug(DEBUG_TESTMODE, "testmode cmd configure");
2237b3115f2SLuciano Coelho 
2247b3115f2SLuciano Coelho 	if (!tb[WL1271_TM_ATTR_DATA])
2257b3115f2SLuciano Coelho 		return -EINVAL;
2267b3115f2SLuciano Coelho 	if (!tb[WL1271_TM_ATTR_IE_ID])
2277b3115f2SLuciano Coelho 		return -EINVAL;
2287b3115f2SLuciano Coelho 
2297b3115f2SLuciano Coelho 	ie_id = nla_get_u8(tb[WL1271_TM_ATTR_IE_ID]);
2307b3115f2SLuciano Coelho 	buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
2317b3115f2SLuciano Coelho 	buf_len = nla_len(tb[WL1271_TM_ATTR_DATA]);
2327b3115f2SLuciano Coelho 
2337b3115f2SLuciano Coelho 	if (buf_len > sizeof(struct wl1271_command))
2347b3115f2SLuciano Coelho 		return -EMSGSIZE;
2357b3115f2SLuciano Coelho 
2367b3115f2SLuciano Coelho 	mutex_lock(&wl->mutex);
2377b3115f2SLuciano Coelho 	ret = wl1271_cmd_configure(wl, ie_id, buf, buf_len);
2387b3115f2SLuciano Coelho 	mutex_unlock(&wl->mutex);
2397b3115f2SLuciano Coelho 
2407b3115f2SLuciano Coelho 	if (ret < 0) {
2417b3115f2SLuciano Coelho 		wl1271_warning("testmode cmd configure failed: %d", ret);
2427b3115f2SLuciano Coelho 		return ret;
2437b3115f2SLuciano Coelho 	}
2447b3115f2SLuciano Coelho 
2457b3115f2SLuciano Coelho 	return 0;
2467b3115f2SLuciano Coelho }
2477b3115f2SLuciano Coelho 
2487b3115f2SLuciano Coelho static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[])
2497b3115f2SLuciano Coelho {
2507b3115f2SLuciano Coelho 	u32 val;
2517b3115f2SLuciano Coelho 	int ret;
2527b3115f2SLuciano Coelho 
2537b3115f2SLuciano Coelho 	wl1271_debug(DEBUG_TESTMODE, "testmode cmd set plt mode");
2547b3115f2SLuciano Coelho 
2557b3115f2SLuciano Coelho 	if (!tb[WL1271_TM_ATTR_PLT_MODE])
2567b3115f2SLuciano Coelho 		return -EINVAL;
2577b3115f2SLuciano Coelho 
2587b3115f2SLuciano Coelho 	val = nla_get_u32(tb[WL1271_TM_ATTR_PLT_MODE]);
2597b3115f2SLuciano Coelho 
2607b3115f2SLuciano Coelho 	switch (val) {
2617b3115f2SLuciano Coelho 	case 0:
2627b3115f2SLuciano Coelho 		ret = wl1271_plt_stop(wl);
2637b3115f2SLuciano Coelho 		break;
2647b3115f2SLuciano Coelho 	case 1:
2657b3115f2SLuciano Coelho 		ret = wl1271_plt_start(wl);
2667b3115f2SLuciano Coelho 		break;
2677b3115f2SLuciano Coelho 	default:
2687b3115f2SLuciano Coelho 		ret = -EINVAL;
2697b3115f2SLuciano Coelho 		break;
2707b3115f2SLuciano Coelho 	}
2717b3115f2SLuciano Coelho 
2727b3115f2SLuciano Coelho 	return ret;
2737b3115f2SLuciano Coelho }
2747b3115f2SLuciano Coelho 
2757b3115f2SLuciano Coelho static int wl12xx_tm_cmd_get_mac(struct wl1271 *wl, struct nlattr *tb[])
2767b3115f2SLuciano Coelho {
2777b3115f2SLuciano Coelho 	struct sk_buff *skb;
2787b3115f2SLuciano Coelho 	u8 mac_addr[ETH_ALEN];
2797b3115f2SLuciano Coelho 	int ret = 0;
2807b3115f2SLuciano Coelho 
2817b3115f2SLuciano Coelho 	mutex_lock(&wl->mutex);
2827b3115f2SLuciano Coelho 
2837b3115f2SLuciano Coelho 	if (!wl->plt) {
2847b3115f2SLuciano Coelho 		ret = -EINVAL;
2857b3115f2SLuciano Coelho 		goto out;
2867b3115f2SLuciano Coelho 	}
2877b3115f2SLuciano Coelho 
2887b3115f2SLuciano Coelho 	if (wl->fuse_oui_addr == 0 && wl->fuse_nic_addr == 0) {
2897b3115f2SLuciano Coelho 		ret = -EOPNOTSUPP;
2907b3115f2SLuciano Coelho 		goto out;
2917b3115f2SLuciano Coelho 	}
2927b3115f2SLuciano Coelho 
2937b3115f2SLuciano Coelho 	mac_addr[0] = (u8)(wl->fuse_oui_addr >> 16);
2947b3115f2SLuciano Coelho 	mac_addr[1] = (u8)(wl->fuse_oui_addr >> 8);
2957b3115f2SLuciano Coelho 	mac_addr[2] = (u8) wl->fuse_oui_addr;
2967b3115f2SLuciano Coelho 	mac_addr[3] = (u8)(wl->fuse_nic_addr >> 16);
2977b3115f2SLuciano Coelho 	mac_addr[4] = (u8)(wl->fuse_nic_addr >> 8);
2987b3115f2SLuciano Coelho 	mac_addr[5] = (u8) wl->fuse_nic_addr;
2997b3115f2SLuciano Coelho 
3007b3115f2SLuciano Coelho 	skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, ETH_ALEN);
3017b3115f2SLuciano Coelho 	if (!skb) {
3027b3115f2SLuciano Coelho 		ret = -ENOMEM;
3037b3115f2SLuciano Coelho 		goto out;
3047b3115f2SLuciano Coelho 	}
3057b3115f2SLuciano Coelho 
30659ef43e6SJohn W. Linville 	if (nla_put(skb, WL1271_TM_ATTR_DATA, ETH_ALEN, mac_addr))
30759ef43e6SJohn W. Linville 		goto nla_put_failure;
3087b3115f2SLuciano Coelho 	ret = cfg80211_testmode_reply(skb);
3097b3115f2SLuciano Coelho 	if (ret < 0)
3107b3115f2SLuciano Coelho 		goto out;
3117b3115f2SLuciano Coelho 
3127b3115f2SLuciano Coelho out:
3137b3115f2SLuciano Coelho 	mutex_unlock(&wl->mutex);
3147b3115f2SLuciano Coelho 	return ret;
3157b3115f2SLuciano Coelho 
3167b3115f2SLuciano Coelho nla_put_failure:
3177b3115f2SLuciano Coelho 	kfree_skb(skb);
3187b3115f2SLuciano Coelho 	ret = -EMSGSIZE;
3197b3115f2SLuciano Coelho 	goto out;
3207b3115f2SLuciano Coelho }
3217b3115f2SLuciano Coelho 
3227b3115f2SLuciano Coelho int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len)
3237b3115f2SLuciano Coelho {
3247b3115f2SLuciano Coelho 	struct wl1271 *wl = hw->priv;
3257b3115f2SLuciano Coelho 	struct nlattr *tb[WL1271_TM_ATTR_MAX + 1];
3267b3115f2SLuciano Coelho 	int err;
3277b3115f2SLuciano Coelho 
3287b3115f2SLuciano Coelho 	err = nla_parse(tb, WL1271_TM_ATTR_MAX, data, len, wl1271_tm_policy);
3297b3115f2SLuciano Coelho 	if (err)
3307b3115f2SLuciano Coelho 		return err;
3317b3115f2SLuciano Coelho 
3327b3115f2SLuciano Coelho 	if (!tb[WL1271_TM_ATTR_CMD_ID])
3337b3115f2SLuciano Coelho 		return -EINVAL;
3347b3115f2SLuciano Coelho 
3357b3115f2SLuciano Coelho 	switch (nla_get_u32(tb[WL1271_TM_ATTR_CMD_ID])) {
3367b3115f2SLuciano Coelho 	case WL1271_TM_CMD_TEST:
3377b3115f2SLuciano Coelho 		return wl1271_tm_cmd_test(wl, tb);
3387b3115f2SLuciano Coelho 	case WL1271_TM_CMD_INTERROGATE:
3397b3115f2SLuciano Coelho 		return wl1271_tm_cmd_interrogate(wl, tb);
3407b3115f2SLuciano Coelho 	case WL1271_TM_CMD_CONFIGURE:
3417b3115f2SLuciano Coelho 		return wl1271_tm_cmd_configure(wl, tb);
3427b3115f2SLuciano Coelho 	case WL1271_TM_CMD_SET_PLT_MODE:
3437b3115f2SLuciano Coelho 		return wl1271_tm_cmd_set_plt_mode(wl, tb);
3447b3115f2SLuciano Coelho 	case WL1271_TM_CMD_GET_MAC:
3457b3115f2SLuciano Coelho 		return wl12xx_tm_cmd_get_mac(wl, tb);
3467b3115f2SLuciano Coelho 	default:
3477b3115f2SLuciano Coelho 		return -EOPNOTSUPP;
3487b3115f2SLuciano Coelho 	}
3497b3115f2SLuciano Coelho }
350