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 
287b3115f2SLuciano Coelho #include "wl12xx.h"
297b3115f2SLuciano Coelho #include "debug.h"
307b3115f2SLuciano Coelho #include "acx.h"
317b3115f2SLuciano Coelho #include "reg.h"
327b3115f2SLuciano Coelho #include "ps.h"
337b3115f2SLuciano Coelho #include "io.h"
347b3115f2SLuciano Coelho 
357b3115f2SLuciano Coelho #define WL1271_TM_MAX_DATA_LENGTH 1024
367b3115f2SLuciano Coelho 
377b3115f2SLuciano Coelho enum wl1271_tm_commands {
387b3115f2SLuciano Coelho 	WL1271_TM_CMD_UNSPEC,
397b3115f2SLuciano Coelho 	WL1271_TM_CMD_TEST,
407b3115f2SLuciano Coelho 	WL1271_TM_CMD_INTERROGATE,
417b3115f2SLuciano Coelho 	WL1271_TM_CMD_CONFIGURE,
427b3115f2SLuciano Coelho 	WL1271_TM_CMD_NVS_PUSH,		/* Not in use. Keep to not break ABI */
437b3115f2SLuciano Coelho 	WL1271_TM_CMD_SET_PLT_MODE,
447b3115f2SLuciano Coelho 	WL1271_TM_CMD_RECOVER,
457b3115f2SLuciano Coelho 	WL1271_TM_CMD_GET_MAC,
467b3115f2SLuciano Coelho 
477b3115f2SLuciano Coelho 	__WL1271_TM_CMD_AFTER_LAST
487b3115f2SLuciano Coelho };
497b3115f2SLuciano Coelho #define WL1271_TM_CMD_MAX (__WL1271_TM_CMD_AFTER_LAST - 1)
507b3115f2SLuciano Coelho 
517b3115f2SLuciano Coelho enum wl1271_tm_attrs {
527b3115f2SLuciano Coelho 	WL1271_TM_ATTR_UNSPEC,
537b3115f2SLuciano Coelho 	WL1271_TM_ATTR_CMD_ID,
547b3115f2SLuciano Coelho 	WL1271_TM_ATTR_ANSWER,
557b3115f2SLuciano Coelho 	WL1271_TM_ATTR_DATA,
567b3115f2SLuciano Coelho 	WL1271_TM_ATTR_IE_ID,
577b3115f2SLuciano Coelho 	WL1271_TM_ATTR_PLT_MODE,
587b3115f2SLuciano Coelho 
597b3115f2SLuciano Coelho 	__WL1271_TM_ATTR_AFTER_LAST
607b3115f2SLuciano Coelho };
617b3115f2SLuciano Coelho #define WL1271_TM_ATTR_MAX (__WL1271_TM_ATTR_AFTER_LAST - 1)
627b3115f2SLuciano Coelho 
637b3115f2SLuciano Coelho static struct nla_policy wl1271_tm_policy[WL1271_TM_ATTR_MAX + 1] = {
647b3115f2SLuciano Coelho 	[WL1271_TM_ATTR_CMD_ID] =	{ .type = NLA_U32 },
657b3115f2SLuciano Coelho 	[WL1271_TM_ATTR_ANSWER] =	{ .type = NLA_U8 },
667b3115f2SLuciano Coelho 	[WL1271_TM_ATTR_DATA] =		{ .type = NLA_BINARY,
677b3115f2SLuciano Coelho 					  .len = WL1271_TM_MAX_DATA_LENGTH },
687b3115f2SLuciano Coelho 	[WL1271_TM_ATTR_IE_ID] =	{ .type = NLA_U32 },
697b3115f2SLuciano Coelho 	[WL1271_TM_ATTR_PLT_MODE] =	{ .type = NLA_U32 },
707b3115f2SLuciano Coelho };
717b3115f2SLuciano Coelho 
727b3115f2SLuciano Coelho 
737b3115f2SLuciano Coelho static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[])
747b3115f2SLuciano Coelho {
757b3115f2SLuciano Coelho 	int buf_len, ret, len;
767b3115f2SLuciano Coelho 	struct sk_buff *skb;
777b3115f2SLuciano Coelho 	void *buf;
787b3115f2SLuciano Coelho 	u8 answer = 0;
797b3115f2SLuciano Coelho 
807b3115f2SLuciano Coelho 	wl1271_debug(DEBUG_TESTMODE, "testmode cmd test");
817b3115f2SLuciano Coelho 
827b3115f2SLuciano Coelho 	if (!tb[WL1271_TM_ATTR_DATA])
837b3115f2SLuciano Coelho 		return -EINVAL;
847b3115f2SLuciano Coelho 
857b3115f2SLuciano Coelho 	buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
867b3115f2SLuciano Coelho 	buf_len = nla_len(tb[WL1271_TM_ATTR_DATA]);
877b3115f2SLuciano Coelho 
887b3115f2SLuciano Coelho 	if (tb[WL1271_TM_ATTR_ANSWER])
897b3115f2SLuciano Coelho 		answer = nla_get_u8(tb[WL1271_TM_ATTR_ANSWER]);
907b3115f2SLuciano Coelho 
917b3115f2SLuciano Coelho 	if (buf_len > sizeof(struct wl1271_command))
927b3115f2SLuciano Coelho 		return -EMSGSIZE;
937b3115f2SLuciano Coelho 
947b3115f2SLuciano Coelho 	mutex_lock(&wl->mutex);
957b3115f2SLuciano Coelho 
967b3115f2SLuciano Coelho 	if (wl->state == WL1271_STATE_OFF) {
977b3115f2SLuciano Coelho 		ret = -EINVAL;
987b3115f2SLuciano Coelho 		goto out;
997b3115f2SLuciano Coelho 	}
1007b3115f2SLuciano Coelho 
1017b3115f2SLuciano Coelho 	ret = wl1271_ps_elp_wakeup(wl);
1027b3115f2SLuciano Coelho 	if (ret < 0)
1037b3115f2SLuciano Coelho 		goto out;
1047b3115f2SLuciano Coelho 
1057b3115f2SLuciano Coelho 	ret = wl1271_cmd_test(wl, buf, buf_len, answer);
1067b3115f2SLuciano Coelho 	if (ret < 0) {
1077b3115f2SLuciano Coelho 		wl1271_warning("testmode cmd test failed: %d", ret);
1087b3115f2SLuciano Coelho 		goto out_sleep;
1097b3115f2SLuciano Coelho 	}
1107b3115f2SLuciano Coelho 
1117b3115f2SLuciano Coelho 	if (answer) {
1127b3115f2SLuciano Coelho 		len = nla_total_size(buf_len);
1137b3115f2SLuciano Coelho 		skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, len);
1147b3115f2SLuciano Coelho 		if (!skb) {
1157b3115f2SLuciano Coelho 			ret = -ENOMEM;
1167b3115f2SLuciano Coelho 			goto out_sleep;
1177b3115f2SLuciano Coelho 		}
1187b3115f2SLuciano Coelho 
1197b3115f2SLuciano Coelho 		NLA_PUT(skb, WL1271_TM_ATTR_DATA, buf_len, buf);
1207b3115f2SLuciano Coelho 		ret = cfg80211_testmode_reply(skb);
1217b3115f2SLuciano Coelho 		if (ret < 0)
1227b3115f2SLuciano Coelho 			goto out_sleep;
1237b3115f2SLuciano Coelho 	}
1247b3115f2SLuciano Coelho 
1257b3115f2SLuciano Coelho out_sleep:
1267b3115f2SLuciano Coelho 	wl1271_ps_elp_sleep(wl);
1277b3115f2SLuciano Coelho out:
1287b3115f2SLuciano Coelho 	mutex_unlock(&wl->mutex);
1297b3115f2SLuciano Coelho 
1307b3115f2SLuciano Coelho 	return ret;
1317b3115f2SLuciano Coelho 
1327b3115f2SLuciano Coelho nla_put_failure:
1337b3115f2SLuciano Coelho 	kfree_skb(skb);
1347b3115f2SLuciano Coelho 	ret = -EMSGSIZE;
1357b3115f2SLuciano Coelho 	goto out_sleep;
1367b3115f2SLuciano Coelho }
1377b3115f2SLuciano Coelho 
1387b3115f2SLuciano Coelho static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[])
1397b3115f2SLuciano Coelho {
1407b3115f2SLuciano Coelho 	int ret;
1417b3115f2SLuciano Coelho 	struct wl1271_command *cmd;
1427b3115f2SLuciano Coelho 	struct sk_buff *skb;
1437b3115f2SLuciano Coelho 	u8 ie_id;
1447b3115f2SLuciano Coelho 
1457b3115f2SLuciano Coelho 	wl1271_debug(DEBUG_TESTMODE, "testmode cmd interrogate");
1467b3115f2SLuciano Coelho 
1477b3115f2SLuciano Coelho 	if (!tb[WL1271_TM_ATTR_IE_ID])
1487b3115f2SLuciano Coelho 		return -EINVAL;
1497b3115f2SLuciano Coelho 
1507b3115f2SLuciano Coelho 	ie_id = nla_get_u8(tb[WL1271_TM_ATTR_IE_ID]);
1517b3115f2SLuciano Coelho 
1527b3115f2SLuciano Coelho 	mutex_lock(&wl->mutex);
1537b3115f2SLuciano Coelho 
1547b3115f2SLuciano Coelho 	if (wl->state == WL1271_STATE_OFF) {
1557b3115f2SLuciano Coelho 		ret = -EINVAL;
1567b3115f2SLuciano Coelho 		goto out;
1577b3115f2SLuciano Coelho 	}
1587b3115f2SLuciano Coelho 
1597b3115f2SLuciano Coelho 	ret = wl1271_ps_elp_wakeup(wl);
1607b3115f2SLuciano Coelho 	if (ret < 0)
1617b3115f2SLuciano Coelho 		goto out;
1627b3115f2SLuciano Coelho 
1637b3115f2SLuciano Coelho 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1647b3115f2SLuciano Coelho 	if (!cmd) {
1657b3115f2SLuciano Coelho 		ret = -ENOMEM;
1667b3115f2SLuciano Coelho 		goto out_sleep;
1677b3115f2SLuciano Coelho 	}
1687b3115f2SLuciano Coelho 
1697b3115f2SLuciano Coelho 	ret = wl1271_cmd_interrogate(wl, ie_id, cmd, sizeof(*cmd));
1707b3115f2SLuciano Coelho 	if (ret < 0) {
1717b3115f2SLuciano Coelho 		wl1271_warning("testmode cmd interrogate failed: %d", ret);
1727b3115f2SLuciano Coelho 		goto out_free;
1737b3115f2SLuciano Coelho 	}
1747b3115f2SLuciano Coelho 
1757b3115f2SLuciano Coelho 	skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, sizeof(*cmd));
1767b3115f2SLuciano Coelho 	if (!skb) {
1777b3115f2SLuciano Coelho 		ret = -ENOMEM;
1787b3115f2SLuciano Coelho 		goto out_free;
1797b3115f2SLuciano Coelho 	}
1807b3115f2SLuciano Coelho 
1817b3115f2SLuciano Coelho 	NLA_PUT(skb, WL1271_TM_ATTR_DATA, sizeof(*cmd), cmd);
1827b3115f2SLuciano Coelho 	ret = cfg80211_testmode_reply(skb);
1837b3115f2SLuciano Coelho 	if (ret < 0)
1847b3115f2SLuciano Coelho 		goto out_free;
1857b3115f2SLuciano Coelho 
1867b3115f2SLuciano Coelho out_free:
1877b3115f2SLuciano Coelho 	kfree(cmd);
1887b3115f2SLuciano Coelho out_sleep:
1897b3115f2SLuciano Coelho 	wl1271_ps_elp_sleep(wl);
1907b3115f2SLuciano Coelho out:
1917b3115f2SLuciano Coelho 	mutex_unlock(&wl->mutex);
1927b3115f2SLuciano Coelho 
1937b3115f2SLuciano Coelho 	return ret;
1947b3115f2SLuciano Coelho 
1957b3115f2SLuciano Coelho nla_put_failure:
1967b3115f2SLuciano Coelho 	kfree_skb(skb);
1977b3115f2SLuciano Coelho 	ret = -EMSGSIZE;
1987b3115f2SLuciano Coelho 	goto out_free;
1997b3115f2SLuciano Coelho }
2007b3115f2SLuciano Coelho 
2017b3115f2SLuciano Coelho static int wl1271_tm_cmd_configure(struct wl1271 *wl, struct nlattr *tb[])
2027b3115f2SLuciano Coelho {
2037b3115f2SLuciano Coelho 	int buf_len, ret;
2047b3115f2SLuciano Coelho 	void *buf;
2057b3115f2SLuciano Coelho 	u8 ie_id;
2067b3115f2SLuciano Coelho 
2077b3115f2SLuciano Coelho 	wl1271_debug(DEBUG_TESTMODE, "testmode cmd configure");
2087b3115f2SLuciano Coelho 
2097b3115f2SLuciano Coelho 	if (!tb[WL1271_TM_ATTR_DATA])
2107b3115f2SLuciano Coelho 		return -EINVAL;
2117b3115f2SLuciano Coelho 	if (!tb[WL1271_TM_ATTR_IE_ID])
2127b3115f2SLuciano Coelho 		return -EINVAL;
2137b3115f2SLuciano Coelho 
2147b3115f2SLuciano Coelho 	ie_id = nla_get_u8(tb[WL1271_TM_ATTR_IE_ID]);
2157b3115f2SLuciano Coelho 	buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
2167b3115f2SLuciano Coelho 	buf_len = nla_len(tb[WL1271_TM_ATTR_DATA]);
2177b3115f2SLuciano Coelho 
2187b3115f2SLuciano Coelho 	if (buf_len > sizeof(struct wl1271_command))
2197b3115f2SLuciano Coelho 		return -EMSGSIZE;
2207b3115f2SLuciano Coelho 
2217b3115f2SLuciano Coelho 	mutex_lock(&wl->mutex);
2227b3115f2SLuciano Coelho 	ret = wl1271_cmd_configure(wl, ie_id, buf, buf_len);
2237b3115f2SLuciano Coelho 	mutex_unlock(&wl->mutex);
2247b3115f2SLuciano Coelho 
2257b3115f2SLuciano Coelho 	if (ret < 0) {
2267b3115f2SLuciano Coelho 		wl1271_warning("testmode cmd configure failed: %d", ret);
2277b3115f2SLuciano Coelho 		return ret;
2287b3115f2SLuciano Coelho 	}
2297b3115f2SLuciano Coelho 
2307b3115f2SLuciano Coelho 	return 0;
2317b3115f2SLuciano Coelho }
2327b3115f2SLuciano Coelho 
2337b3115f2SLuciano Coelho static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[])
2347b3115f2SLuciano Coelho {
2357b3115f2SLuciano Coelho 	u32 val;
2367b3115f2SLuciano Coelho 	int ret;
2377b3115f2SLuciano Coelho 
2387b3115f2SLuciano Coelho 	wl1271_debug(DEBUG_TESTMODE, "testmode cmd set plt mode");
2397b3115f2SLuciano Coelho 
2407b3115f2SLuciano Coelho 	if (!tb[WL1271_TM_ATTR_PLT_MODE])
2417b3115f2SLuciano Coelho 		return -EINVAL;
2427b3115f2SLuciano Coelho 
2437b3115f2SLuciano Coelho 	val = nla_get_u32(tb[WL1271_TM_ATTR_PLT_MODE]);
2447b3115f2SLuciano Coelho 
2457b3115f2SLuciano Coelho 	switch (val) {
2467b3115f2SLuciano Coelho 	case 0:
2477b3115f2SLuciano Coelho 		ret = wl1271_plt_stop(wl);
2487b3115f2SLuciano Coelho 		break;
2497b3115f2SLuciano Coelho 	case 1:
2507b3115f2SLuciano Coelho 		ret = wl1271_plt_start(wl);
2517b3115f2SLuciano Coelho 		break;
2527b3115f2SLuciano Coelho 	default:
2537b3115f2SLuciano Coelho 		ret = -EINVAL;
2547b3115f2SLuciano Coelho 		break;
2557b3115f2SLuciano Coelho 	}
2567b3115f2SLuciano Coelho 
2577b3115f2SLuciano Coelho 	return ret;
2587b3115f2SLuciano Coelho }
2597b3115f2SLuciano Coelho 
2607b3115f2SLuciano Coelho static int wl1271_tm_cmd_recover(struct wl1271 *wl, struct nlattr *tb[])
2617b3115f2SLuciano Coelho {
2627b3115f2SLuciano Coelho 	wl1271_debug(DEBUG_TESTMODE, "testmode cmd recover");
2637b3115f2SLuciano Coelho 
2647b3115f2SLuciano Coelho 	wl12xx_queue_recovery_work(wl);
2657b3115f2SLuciano Coelho 
2667b3115f2SLuciano Coelho 	return 0;
2677b3115f2SLuciano Coelho }
2687b3115f2SLuciano Coelho 
2697b3115f2SLuciano Coelho static int wl12xx_tm_cmd_get_mac(struct wl1271 *wl, struct nlattr *tb[])
2707b3115f2SLuciano Coelho {
2717b3115f2SLuciano Coelho 	struct sk_buff *skb;
2727b3115f2SLuciano Coelho 	u8 mac_addr[ETH_ALEN];
2737b3115f2SLuciano Coelho 	int ret = 0;
2747b3115f2SLuciano Coelho 
2757b3115f2SLuciano Coelho 	mutex_lock(&wl->mutex);
2767b3115f2SLuciano Coelho 
2777b3115f2SLuciano Coelho 	if (!wl->plt) {
2787b3115f2SLuciano Coelho 		ret = -EINVAL;
2797b3115f2SLuciano Coelho 		goto out;
2807b3115f2SLuciano Coelho 	}
2817b3115f2SLuciano Coelho 
2827b3115f2SLuciano Coelho 	if (wl->fuse_oui_addr == 0 && wl->fuse_nic_addr == 0) {
2837b3115f2SLuciano Coelho 		ret = -EOPNOTSUPP;
2847b3115f2SLuciano Coelho 		goto out;
2857b3115f2SLuciano Coelho 	}
2867b3115f2SLuciano Coelho 
2877b3115f2SLuciano Coelho 	mac_addr[0] = (u8)(wl->fuse_oui_addr >> 16);
2887b3115f2SLuciano Coelho 	mac_addr[1] = (u8)(wl->fuse_oui_addr >> 8);
2897b3115f2SLuciano Coelho 	mac_addr[2] = (u8) wl->fuse_oui_addr;
2907b3115f2SLuciano Coelho 	mac_addr[3] = (u8)(wl->fuse_nic_addr >> 16);
2917b3115f2SLuciano Coelho 	mac_addr[4] = (u8)(wl->fuse_nic_addr >> 8);
2927b3115f2SLuciano Coelho 	mac_addr[5] = (u8) wl->fuse_nic_addr;
2937b3115f2SLuciano Coelho 
2947b3115f2SLuciano Coelho 	skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, ETH_ALEN);
2957b3115f2SLuciano Coelho 	if (!skb) {
2967b3115f2SLuciano Coelho 		ret = -ENOMEM;
2977b3115f2SLuciano Coelho 		goto out;
2987b3115f2SLuciano Coelho 	}
2997b3115f2SLuciano Coelho 
3007b3115f2SLuciano Coelho 	NLA_PUT(skb, WL1271_TM_ATTR_DATA, ETH_ALEN, mac_addr);
3017b3115f2SLuciano Coelho 	ret = cfg80211_testmode_reply(skb);
3027b3115f2SLuciano Coelho 	if (ret < 0)
3037b3115f2SLuciano Coelho 		goto out;
3047b3115f2SLuciano Coelho 
3057b3115f2SLuciano Coelho out:
3067b3115f2SLuciano Coelho 	mutex_unlock(&wl->mutex);
3077b3115f2SLuciano Coelho 	return ret;
3087b3115f2SLuciano Coelho 
3097b3115f2SLuciano Coelho nla_put_failure:
3107b3115f2SLuciano Coelho 	kfree_skb(skb);
3117b3115f2SLuciano Coelho 	ret = -EMSGSIZE;
3127b3115f2SLuciano Coelho 	goto out;
3137b3115f2SLuciano Coelho }
3147b3115f2SLuciano Coelho 
3157b3115f2SLuciano Coelho int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len)
3167b3115f2SLuciano Coelho {
3177b3115f2SLuciano Coelho 	struct wl1271 *wl = hw->priv;
3187b3115f2SLuciano Coelho 	struct nlattr *tb[WL1271_TM_ATTR_MAX + 1];
3197b3115f2SLuciano Coelho 	int err;
3207b3115f2SLuciano Coelho 
3217b3115f2SLuciano Coelho 	err = nla_parse(tb, WL1271_TM_ATTR_MAX, data, len, wl1271_tm_policy);
3227b3115f2SLuciano Coelho 	if (err)
3237b3115f2SLuciano Coelho 		return err;
3247b3115f2SLuciano Coelho 
3257b3115f2SLuciano Coelho 	if (!tb[WL1271_TM_ATTR_CMD_ID])
3267b3115f2SLuciano Coelho 		return -EINVAL;
3277b3115f2SLuciano Coelho 
3287b3115f2SLuciano Coelho 	switch (nla_get_u32(tb[WL1271_TM_ATTR_CMD_ID])) {
3297b3115f2SLuciano Coelho 	case WL1271_TM_CMD_TEST:
3307b3115f2SLuciano Coelho 		return wl1271_tm_cmd_test(wl, tb);
3317b3115f2SLuciano Coelho 	case WL1271_TM_CMD_INTERROGATE:
3327b3115f2SLuciano Coelho 		return wl1271_tm_cmd_interrogate(wl, tb);
3337b3115f2SLuciano Coelho 	case WL1271_TM_CMD_CONFIGURE:
3347b3115f2SLuciano Coelho 		return wl1271_tm_cmd_configure(wl, tb);
3357b3115f2SLuciano Coelho 	case WL1271_TM_CMD_SET_PLT_MODE:
3367b3115f2SLuciano Coelho 		return wl1271_tm_cmd_set_plt_mode(wl, tb);
3377b3115f2SLuciano Coelho 	case WL1271_TM_CMD_RECOVER:
3387b3115f2SLuciano Coelho 		return wl1271_tm_cmd_recover(wl, tb);
3397b3115f2SLuciano Coelho 	case WL1271_TM_CMD_GET_MAC:
3407b3115f2SLuciano Coelho 		return wl12xx_tm_cmd_get_mac(wl, tb);
3417b3115f2SLuciano Coelho 	default:
3427b3115f2SLuciano Coelho 		return -EOPNOTSUPP;
3437b3115f2SLuciano Coelho 	}
3447b3115f2SLuciano Coelho }
345