diff options
Diffstat (limited to 'drivers/net/wireless/ath/wcn36xx')
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/Kconfig | 16 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/Makefile | 7 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/debug.c | 181 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/debug.h | 49 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/dxe.c | 805 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/dxe.h | 284 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/hal.h | 4657 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/main.c | 1036 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/pmc.c | 62 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/pmc.h | 33 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/smd.c | 2126 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/smd.h | 127 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/txrx.c | 284 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/txrx.h | 160 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 238 |
15 files changed, 10065 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/wcn36xx/Kconfig b/drivers/net/wireless/ath/wcn36xx/Kconfig new file mode 100644 index 000000000000..591ebaea8265 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/Kconfig | |||
@@ -0,0 +1,16 @@ | |||
1 | config WCN36XX | ||
2 | tristate "Qualcomm Atheros WCN3660/3680 support" | ||
3 | depends on MAC80211 && HAS_DMA | ||
4 | ---help--- | ||
5 | This module adds support for wireless adapters based on | ||
6 | Qualcomm Atheros WCN3660 and WCN3680 mobile chipsets. | ||
7 | |||
8 | If you choose to build a module, it'll be called wcn36xx. | ||
9 | |||
10 | config WCN36XX_DEBUGFS | ||
11 | bool "WCN36XX debugfs support" | ||
12 | depends on WCN36XX | ||
13 | ---help--- | ||
14 | Enabled debugfs support | ||
15 | |||
16 | If unsure, say Y to make it easier to debug problems. | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/Makefile b/drivers/net/wireless/ath/wcn36xx/Makefile new file mode 100644 index 000000000000..50c43b4382ba --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | obj-$(CONFIG_WCN36XX) := wcn36xx.o | ||
2 | wcn36xx-y += main.o \ | ||
3 | dxe.o \ | ||
4 | txrx.o \ | ||
5 | smd.o \ | ||
6 | pmc.o \ | ||
7 | debug.o | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/debug.c b/drivers/net/wireless/ath/wcn36xx/debug.c new file mode 100644 index 000000000000..5b84f7ae0b1e --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/debug.c | |||
@@ -0,0 +1,181 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
19 | #include <linux/debugfs.h> | ||
20 | #include <linux/uaccess.h> | ||
21 | #include "wcn36xx.h" | ||
22 | #include "debug.h" | ||
23 | #include "pmc.h" | ||
24 | |||
25 | #ifdef CONFIG_WCN36XX_DEBUGFS | ||
26 | |||
27 | static ssize_t read_file_bool_bmps(struct file *file, char __user *user_buf, | ||
28 | size_t count, loff_t *ppos) | ||
29 | { | ||
30 | struct wcn36xx *wcn = file->private_data; | ||
31 | struct wcn36xx_vif *vif_priv = NULL; | ||
32 | struct ieee80211_vif *vif = NULL; | ||
33 | char buf[3]; | ||
34 | |||
35 | list_for_each_entry(vif_priv, &wcn->vif_list, list) { | ||
36 | vif = container_of((void *)vif_priv, | ||
37 | struct ieee80211_vif, | ||
38 | drv_priv); | ||
39 | if (NL80211_IFTYPE_STATION == vif->type) { | ||
40 | if (vif_priv->pw_state == WCN36XX_BMPS) | ||
41 | buf[0] = '1'; | ||
42 | else | ||
43 | buf[0] = '0'; | ||
44 | break; | ||
45 | } | ||
46 | } | ||
47 | buf[1] = '\n'; | ||
48 | buf[2] = 0x00; | ||
49 | |||
50 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | ||
51 | } | ||
52 | |||
53 | static ssize_t write_file_bool_bmps(struct file *file, | ||
54 | const char __user *user_buf, | ||
55 | size_t count, loff_t *ppos) | ||
56 | { | ||
57 | struct wcn36xx *wcn = file->private_data; | ||
58 | struct wcn36xx_vif *vif_priv = NULL; | ||
59 | struct ieee80211_vif *vif = NULL; | ||
60 | |||
61 | char buf[32]; | ||
62 | int buf_size; | ||
63 | |||
64 | buf_size = min(count, (sizeof(buf)-1)); | ||
65 | if (copy_from_user(buf, user_buf, buf_size)) | ||
66 | return -EFAULT; | ||
67 | |||
68 | switch (buf[0]) { | ||
69 | case 'y': | ||
70 | case 'Y': | ||
71 | case '1': | ||
72 | list_for_each_entry(vif_priv, &wcn->vif_list, list) { | ||
73 | vif = container_of((void *)vif_priv, | ||
74 | struct ieee80211_vif, | ||
75 | drv_priv); | ||
76 | if (NL80211_IFTYPE_STATION == vif->type) { | ||
77 | wcn36xx_enable_keep_alive_null_packet(wcn, vif); | ||
78 | wcn36xx_pmc_enter_bmps_state(wcn, vif); | ||
79 | } | ||
80 | } | ||
81 | break; | ||
82 | case 'n': | ||
83 | case 'N': | ||
84 | case '0': | ||
85 | list_for_each_entry(vif_priv, &wcn->vif_list, list) { | ||
86 | vif = container_of((void *)vif_priv, | ||
87 | struct ieee80211_vif, | ||
88 | drv_priv); | ||
89 | if (NL80211_IFTYPE_STATION == vif->type) | ||
90 | wcn36xx_pmc_exit_bmps_state(wcn, vif); | ||
91 | } | ||
92 | break; | ||
93 | } | ||
94 | |||
95 | return count; | ||
96 | } | ||
97 | |||
98 | static const struct file_operations fops_wcn36xx_bmps = { | ||
99 | .open = simple_open, | ||
100 | .read = read_file_bool_bmps, | ||
101 | .write = write_file_bool_bmps, | ||
102 | }; | ||
103 | |||
104 | static ssize_t write_file_dump(struct file *file, | ||
105 | const char __user *user_buf, | ||
106 | size_t count, loff_t *ppos) | ||
107 | { | ||
108 | struct wcn36xx *wcn = file->private_data; | ||
109 | char buf[255], *tmp; | ||
110 | int buf_size; | ||
111 | u32 arg[WCN36xx_MAX_DUMP_ARGS]; | ||
112 | int i; | ||
113 | |||
114 | memset(buf, 0, sizeof(buf)); | ||
115 | memset(arg, 0, sizeof(arg)); | ||
116 | |||
117 | buf_size = min(count, (sizeof(buf) - 1)); | ||
118 | if (copy_from_user(buf, user_buf, buf_size)) | ||
119 | return -EFAULT; | ||
120 | |||
121 | tmp = buf; | ||
122 | |||
123 | for (i = 0; i < WCN36xx_MAX_DUMP_ARGS; i++) { | ||
124 | char *begin; | ||
125 | begin = strsep(&tmp, " "); | ||
126 | if (begin == NULL) | ||
127 | break; | ||
128 | |||
129 | if (kstrtoul(begin, 0, (unsigned long *)(arg + i)) != 0) | ||
130 | break; | ||
131 | } | ||
132 | |||
133 | wcn36xx_info("DUMP args is %d %d %d %d %d\n", arg[0], arg[1], arg[2], | ||
134 | arg[3], arg[4]); | ||
135 | wcn36xx_smd_dump_cmd_req(wcn, arg[0], arg[1], arg[2], arg[3], arg[4]); | ||
136 | |||
137 | return count; | ||
138 | } | ||
139 | |||
140 | static const struct file_operations fops_wcn36xx_dump = { | ||
141 | .open = simple_open, | ||
142 | .write = write_file_dump, | ||
143 | }; | ||
144 | |||
145 | #define ADD_FILE(name, mode, fop, priv_data) \ | ||
146 | do { \ | ||
147 | struct dentry *d; \ | ||
148 | d = debugfs_create_file(__stringify(name), \ | ||
149 | mode, dfs->rootdir, \ | ||
150 | priv_data, fop); \ | ||
151 | dfs->file_##name.dentry = d; \ | ||
152 | if (IS_ERR(d)) { \ | ||
153 | wcn36xx_warn("Create the debugfs entry failed");\ | ||
154 | dfs->file_##name.dentry = NULL; \ | ||
155 | } \ | ||
156 | } while (0) | ||
157 | |||
158 | |||
159 | void wcn36xx_debugfs_init(struct wcn36xx *wcn) | ||
160 | { | ||
161 | struct wcn36xx_dfs_entry *dfs = &wcn->dfs; | ||
162 | |||
163 | dfs->rootdir = debugfs_create_dir(KBUILD_MODNAME, | ||
164 | wcn->hw->wiphy->debugfsdir); | ||
165 | if (IS_ERR(dfs->rootdir)) { | ||
166 | wcn36xx_warn("Create the debugfs failed\n"); | ||
167 | dfs->rootdir = NULL; | ||
168 | } | ||
169 | |||
170 | ADD_FILE(bmps_switcher, S_IRUSR | S_IWUSR, | ||
171 | &fops_wcn36xx_bmps, wcn); | ||
172 | ADD_FILE(dump, S_IWUSR, &fops_wcn36xx_dump, wcn); | ||
173 | } | ||
174 | |||
175 | void wcn36xx_debugfs_exit(struct wcn36xx *wcn) | ||
176 | { | ||
177 | struct wcn36xx_dfs_entry *dfs = &wcn->dfs; | ||
178 | debugfs_remove_recursive(dfs->rootdir); | ||
179 | } | ||
180 | |||
181 | #endif /* CONFIG_WCN36XX_DEBUGFS */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/debug.h b/drivers/net/wireless/ath/wcn36xx/debug.h new file mode 100644 index 000000000000..46307aa562d3 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/debug.h | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _WCN36XX_DEBUG_H_ | ||
18 | #define _WCN36XX_DEBUG_H_ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | |||
22 | #define WCN36xx_MAX_DUMP_ARGS 5 | ||
23 | |||
24 | #ifdef CONFIG_WCN36XX_DEBUGFS | ||
25 | struct wcn36xx_dfs_file { | ||
26 | struct dentry *dentry; | ||
27 | u32 value; | ||
28 | }; | ||
29 | |||
30 | struct wcn36xx_dfs_entry { | ||
31 | struct dentry *rootdir; | ||
32 | struct wcn36xx_dfs_file file_bmps_switcher; | ||
33 | struct wcn36xx_dfs_file file_dump; | ||
34 | }; | ||
35 | |||
36 | void wcn36xx_debugfs_init(struct wcn36xx *wcn); | ||
37 | void wcn36xx_debugfs_exit(struct wcn36xx *wcn); | ||
38 | |||
39 | #else | ||
40 | static inline void wcn36xx_debugfs_init(struct wcn36xx *wcn) | ||
41 | { | ||
42 | } | ||
43 | static inline void wcn36xx_debugfs_exit(struct wcn36xx *wcn) | ||
44 | { | ||
45 | } | ||
46 | |||
47 | #endif /* CONFIG_WCN36XX_DEBUGFS */ | ||
48 | |||
49 | #endif /* _WCN36XX_DEBUG_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c new file mode 100644 index 000000000000..ee25786b4447 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c | |||
@@ -0,0 +1,805 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | /* DXE - DMA transfer engine | ||
18 | * we have 2 channels(High prio and Low prio) for TX and 2 channels for RX. | ||
19 | * through low channels data packets are transfered | ||
20 | * through high channels managment packets are transfered | ||
21 | */ | ||
22 | |||
23 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
24 | |||
25 | #include <linux/interrupt.h> | ||
26 | #include "wcn36xx.h" | ||
27 | #include "txrx.h" | ||
28 | |||
29 | void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool is_low) | ||
30 | { | ||
31 | struct wcn36xx_dxe_ch *ch = is_low ? | ||
32 | &wcn->dxe_tx_l_ch : | ||
33 | &wcn->dxe_tx_h_ch; | ||
34 | |||
35 | return ch->head_blk_ctl->bd_cpu_addr; | ||
36 | } | ||
37 | |||
38 | static void wcn36xx_dxe_write_register(struct wcn36xx *wcn, int addr, int data) | ||
39 | { | ||
40 | wcn36xx_dbg(WCN36XX_DBG_DXE, | ||
41 | "wcn36xx_dxe_write_register: addr=%x, data=%x\n", | ||
42 | addr, data); | ||
43 | |||
44 | writel(data, wcn->mmio + addr); | ||
45 | } | ||
46 | |||
47 | static void wcn36xx_dxe_read_register(struct wcn36xx *wcn, int addr, int *data) | ||
48 | { | ||
49 | *data = readl(wcn->mmio + addr); | ||
50 | |||
51 | wcn36xx_dbg(WCN36XX_DBG_DXE, | ||
52 | "wcn36xx_dxe_read_register: addr=%x, data=%x\n", | ||
53 | addr, *data); | ||
54 | } | ||
55 | |||
56 | static void wcn36xx_dxe_free_ctl_block(struct wcn36xx_dxe_ch *ch) | ||
57 | { | ||
58 | struct wcn36xx_dxe_ctl *ctl = ch->head_blk_ctl, *next; | ||
59 | int i; | ||
60 | |||
61 | for (i = 0; i < ch->desc_num && ctl; i++) { | ||
62 | next = ctl->next; | ||
63 | kfree(ctl); | ||
64 | ctl = next; | ||
65 | } | ||
66 | } | ||
67 | |||
68 | static int wcn36xx_dxe_allocate_ctl_block(struct wcn36xx_dxe_ch *ch) | ||
69 | { | ||
70 | struct wcn36xx_dxe_ctl *prev_ctl = NULL; | ||
71 | struct wcn36xx_dxe_ctl *cur_ctl = NULL; | ||
72 | int i; | ||
73 | |||
74 | for (i = 0; i < ch->desc_num; i++) { | ||
75 | cur_ctl = kzalloc(sizeof(*cur_ctl), GFP_KERNEL); | ||
76 | if (!cur_ctl) | ||
77 | goto out_fail; | ||
78 | |||
79 | cur_ctl->ctl_blk_order = i; | ||
80 | if (i == 0) { | ||
81 | ch->head_blk_ctl = cur_ctl; | ||
82 | ch->tail_blk_ctl = cur_ctl; | ||
83 | } else if (ch->desc_num - 1 == i) { | ||
84 | prev_ctl->next = cur_ctl; | ||
85 | cur_ctl->next = ch->head_blk_ctl; | ||
86 | } else { | ||
87 | prev_ctl->next = cur_ctl; | ||
88 | } | ||
89 | prev_ctl = cur_ctl; | ||
90 | } | ||
91 | |||
92 | return 0; | ||
93 | |||
94 | out_fail: | ||
95 | wcn36xx_dxe_free_ctl_block(ch); | ||
96 | return -ENOMEM; | ||
97 | } | ||
98 | |||
99 | int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn) | ||
100 | { | ||
101 | int ret; | ||
102 | |||
103 | wcn->dxe_tx_l_ch.ch_type = WCN36XX_DXE_CH_TX_L; | ||
104 | wcn->dxe_tx_h_ch.ch_type = WCN36XX_DXE_CH_TX_H; | ||
105 | wcn->dxe_rx_l_ch.ch_type = WCN36XX_DXE_CH_RX_L; | ||
106 | wcn->dxe_rx_h_ch.ch_type = WCN36XX_DXE_CH_RX_H; | ||
107 | |||
108 | wcn->dxe_tx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_TX_L; | ||
109 | wcn->dxe_tx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_TX_H; | ||
110 | wcn->dxe_rx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_L; | ||
111 | wcn->dxe_rx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_H; | ||
112 | |||
113 | wcn->dxe_tx_l_ch.dxe_wq = WCN36XX_DXE_WQ_TX_L; | ||
114 | wcn->dxe_tx_h_ch.dxe_wq = WCN36XX_DXE_WQ_TX_H; | ||
115 | |||
116 | wcn->dxe_tx_l_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_L_BD; | ||
117 | wcn->dxe_tx_h_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_H_BD; | ||
118 | |||
119 | wcn->dxe_tx_l_ch.ctrl_skb = WCN36XX_DXE_CTRL_TX_L_SKB; | ||
120 | wcn->dxe_tx_h_ch.ctrl_skb = WCN36XX_DXE_CTRL_TX_H_SKB; | ||
121 | |||
122 | wcn->dxe_tx_l_ch.reg_ctrl = WCN36XX_DXE_REG_CTL_TX_L; | ||
123 | wcn->dxe_tx_h_ch.reg_ctrl = WCN36XX_DXE_REG_CTL_TX_H; | ||
124 | |||
125 | wcn->dxe_tx_l_ch.def_ctrl = WCN36XX_DXE_CH_DEFAULT_CTL_TX_L; | ||
126 | wcn->dxe_tx_h_ch.def_ctrl = WCN36XX_DXE_CH_DEFAULT_CTL_TX_H; | ||
127 | |||
128 | /* DXE control block allocation */ | ||
129 | ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_tx_l_ch); | ||
130 | if (ret) | ||
131 | goto out_err; | ||
132 | ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_tx_h_ch); | ||
133 | if (ret) | ||
134 | goto out_err; | ||
135 | ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_rx_l_ch); | ||
136 | if (ret) | ||
137 | goto out_err; | ||
138 | ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_rx_h_ch); | ||
139 | if (ret) | ||
140 | goto out_err; | ||
141 | |||
142 | /* Initialize SMSM state Clear TX Enable RING EMPTY STATE */ | ||
143 | ret = wcn->ctrl_ops->smsm_change_state( | ||
144 | WCN36XX_SMSM_WLAN_TX_ENABLE, | ||
145 | WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY); | ||
146 | |||
147 | return 0; | ||
148 | |||
149 | out_err: | ||
150 | wcn36xx_err("Failed to allocate DXE control blocks\n"); | ||
151 | wcn36xx_dxe_free_ctl_blks(wcn); | ||
152 | return -ENOMEM; | ||
153 | } | ||
154 | |||
155 | void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn) | ||
156 | { | ||
157 | wcn36xx_dxe_free_ctl_block(&wcn->dxe_tx_l_ch); | ||
158 | wcn36xx_dxe_free_ctl_block(&wcn->dxe_tx_h_ch); | ||
159 | wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_l_ch); | ||
160 | wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_h_ch); | ||
161 | } | ||
162 | |||
163 | static int wcn36xx_dxe_init_descs(struct wcn36xx_dxe_ch *wcn_ch) | ||
164 | { | ||
165 | struct wcn36xx_dxe_desc *cur_dxe = NULL; | ||
166 | struct wcn36xx_dxe_desc *prev_dxe = NULL; | ||
167 | struct wcn36xx_dxe_ctl *cur_ctl = NULL; | ||
168 | size_t size; | ||
169 | int i; | ||
170 | |||
171 | size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc); | ||
172 | wcn_ch->cpu_addr = dma_alloc_coherent(NULL, size, &wcn_ch->dma_addr, | ||
173 | GFP_KERNEL); | ||
174 | if (!wcn_ch->cpu_addr) | ||
175 | return -ENOMEM; | ||
176 | |||
177 | memset(wcn_ch->cpu_addr, 0, size); | ||
178 | |||
179 | cur_dxe = (struct wcn36xx_dxe_desc *)wcn_ch->cpu_addr; | ||
180 | cur_ctl = wcn_ch->head_blk_ctl; | ||
181 | |||
182 | for (i = 0; i < wcn_ch->desc_num; i++) { | ||
183 | cur_ctl->desc = cur_dxe; | ||
184 | cur_ctl->desc_phy_addr = wcn_ch->dma_addr + | ||
185 | i * sizeof(struct wcn36xx_dxe_desc); | ||
186 | |||
187 | switch (wcn_ch->ch_type) { | ||
188 | case WCN36XX_DXE_CH_TX_L: | ||
189 | cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_L; | ||
190 | cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_L; | ||
191 | break; | ||
192 | case WCN36XX_DXE_CH_TX_H: | ||
193 | cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_H; | ||
194 | cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_H; | ||
195 | break; | ||
196 | case WCN36XX_DXE_CH_RX_L: | ||
197 | cur_dxe->ctrl = WCN36XX_DXE_CTRL_RX_L; | ||
198 | cur_dxe->src_addr_l = WCN36XX_DXE_WQ_RX_L; | ||
199 | break; | ||
200 | case WCN36XX_DXE_CH_RX_H: | ||
201 | cur_dxe->ctrl = WCN36XX_DXE_CTRL_RX_H; | ||
202 | cur_dxe->src_addr_l = WCN36XX_DXE_WQ_RX_H; | ||
203 | break; | ||
204 | } | ||
205 | if (0 == i) { | ||
206 | cur_dxe->phy_next_l = 0; | ||
207 | } else if ((0 < i) && (i < wcn_ch->desc_num - 1)) { | ||
208 | prev_dxe->phy_next_l = | ||
209 | cur_ctl->desc_phy_addr; | ||
210 | } else if (i == (wcn_ch->desc_num - 1)) { | ||
211 | prev_dxe->phy_next_l = | ||
212 | cur_ctl->desc_phy_addr; | ||
213 | cur_dxe->phy_next_l = | ||
214 | wcn_ch->head_blk_ctl->desc_phy_addr; | ||
215 | } | ||
216 | cur_ctl = cur_ctl->next; | ||
217 | prev_dxe = cur_dxe; | ||
218 | cur_dxe++; | ||
219 | } | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static void wcn36xx_dxe_init_tx_bd(struct wcn36xx_dxe_ch *ch, | ||
225 | struct wcn36xx_dxe_mem_pool *pool) | ||
226 | { | ||
227 | int i, chunk_size = pool->chunk_size; | ||
228 | dma_addr_t bd_phy_addr = pool->phy_addr; | ||
229 | void *bd_cpu_addr = pool->virt_addr; | ||
230 | struct wcn36xx_dxe_ctl *cur = ch->head_blk_ctl; | ||
231 | |||
232 | for (i = 0; i < ch->desc_num; i++) { | ||
233 | /* Only every second dxe needs a bd pointer, | ||
234 | the other will point to the skb data */ | ||
235 | if (!(i & 1)) { | ||
236 | cur->bd_phy_addr = bd_phy_addr; | ||
237 | cur->bd_cpu_addr = bd_cpu_addr; | ||
238 | bd_phy_addr += chunk_size; | ||
239 | bd_cpu_addr += chunk_size; | ||
240 | } else { | ||
241 | cur->bd_phy_addr = 0; | ||
242 | cur->bd_cpu_addr = NULL; | ||
243 | } | ||
244 | cur = cur->next; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | static int wcn36xx_dxe_enable_ch_int(struct wcn36xx *wcn, u16 wcn_ch) | ||
249 | { | ||
250 | int reg_data = 0; | ||
251 | |||
252 | wcn36xx_dxe_read_register(wcn, | ||
253 | WCN36XX_DXE_INT_MASK_REG, | ||
254 | ®_data); | ||
255 | |||
256 | reg_data |= wcn_ch; | ||
257 | |||
258 | wcn36xx_dxe_write_register(wcn, | ||
259 | WCN36XX_DXE_INT_MASK_REG, | ||
260 | (int)reg_data); | ||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static int wcn36xx_dxe_fill_skb(struct wcn36xx_dxe_ctl *ctl) | ||
265 | { | ||
266 | struct wcn36xx_dxe_desc *dxe = ctl->desc; | ||
267 | struct sk_buff *skb; | ||
268 | |||
269 | skb = alloc_skb(WCN36XX_PKT_SIZE, GFP_ATOMIC); | ||
270 | if (skb == NULL) | ||
271 | return -ENOMEM; | ||
272 | |||
273 | dxe->dst_addr_l = dma_map_single(NULL, | ||
274 | skb_tail_pointer(skb), | ||
275 | WCN36XX_PKT_SIZE, | ||
276 | DMA_FROM_DEVICE); | ||
277 | ctl->skb = skb; | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | static int wcn36xx_dxe_ch_alloc_skb(struct wcn36xx *wcn, | ||
283 | struct wcn36xx_dxe_ch *wcn_ch) | ||
284 | { | ||
285 | int i; | ||
286 | struct wcn36xx_dxe_ctl *cur_ctl = NULL; | ||
287 | |||
288 | cur_ctl = wcn_ch->head_blk_ctl; | ||
289 | |||
290 | for (i = 0; i < wcn_ch->desc_num; i++) { | ||
291 | wcn36xx_dxe_fill_skb(cur_ctl); | ||
292 | cur_ctl = cur_ctl->next; | ||
293 | } | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static void wcn36xx_dxe_ch_free_skbs(struct wcn36xx *wcn, | ||
299 | struct wcn36xx_dxe_ch *wcn_ch) | ||
300 | { | ||
301 | struct wcn36xx_dxe_ctl *cur = wcn_ch->head_blk_ctl; | ||
302 | int i; | ||
303 | |||
304 | for (i = 0; i < wcn_ch->desc_num; i++) { | ||
305 | kfree_skb(cur->skb); | ||
306 | cur = cur->next; | ||
307 | } | ||
308 | } | ||
309 | |||
310 | void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status) | ||
311 | { | ||
312 | struct ieee80211_tx_info *info; | ||
313 | struct sk_buff *skb; | ||
314 | unsigned long flags; | ||
315 | |||
316 | spin_lock_irqsave(&wcn->dxe_lock, flags); | ||
317 | skb = wcn->tx_ack_skb; | ||
318 | wcn->tx_ack_skb = NULL; | ||
319 | spin_unlock_irqrestore(&wcn->dxe_lock, flags); | ||
320 | |||
321 | if (!skb) { | ||
322 | wcn36xx_warn("Spurious TX complete indication\n"); | ||
323 | return; | ||
324 | } | ||
325 | |||
326 | info = IEEE80211_SKB_CB(skb); | ||
327 | |||
328 | if (status == 1) | ||
329 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
330 | |||
331 | wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ack status: %d\n", status); | ||
332 | |||
333 | ieee80211_tx_status_irqsafe(wcn->hw, skb); | ||
334 | ieee80211_wake_queues(wcn->hw); | ||
335 | } | ||
336 | |||
337 | static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) | ||
338 | { | ||
339 | struct wcn36xx_dxe_ctl *ctl = ch->tail_blk_ctl; | ||
340 | struct ieee80211_tx_info *info; | ||
341 | unsigned long flags; | ||
342 | |||
343 | /* | ||
344 | * Make at least one loop of do-while because in case ring is | ||
345 | * completely full head and tail are pointing to the same element | ||
346 | * and while-do will not make any cycles. | ||
347 | */ | ||
348 | do { | ||
349 | if (ctl->skb) { | ||
350 | dma_unmap_single(NULL, ctl->desc->src_addr_l, | ||
351 | ctl->skb->len, DMA_TO_DEVICE); | ||
352 | info = IEEE80211_SKB_CB(ctl->skb); | ||
353 | if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) { | ||
354 | /* Keep frame until TX status comes */ | ||
355 | ieee80211_free_txskb(wcn->hw, ctl->skb); | ||
356 | } | ||
357 | spin_lock_irqsave(&ctl->skb_lock, flags); | ||
358 | if (wcn->queues_stopped) { | ||
359 | wcn->queues_stopped = false; | ||
360 | ieee80211_wake_queues(wcn->hw); | ||
361 | } | ||
362 | spin_unlock_irqrestore(&ctl->skb_lock, flags); | ||
363 | |||
364 | ctl->skb = NULL; | ||
365 | } | ||
366 | ctl = ctl->next; | ||
367 | } while (ctl != ch->head_blk_ctl && | ||
368 | !(ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)); | ||
369 | |||
370 | ch->tail_blk_ctl = ctl; | ||
371 | } | ||
372 | |||
373 | static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) | ||
374 | { | ||
375 | struct wcn36xx *wcn = (struct wcn36xx *)dev; | ||
376 | int int_src, int_reason; | ||
377 | |||
378 | wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src); | ||
379 | |||
380 | if (int_src & WCN36XX_INT_MASK_CHAN_TX_H) { | ||
381 | wcn36xx_dxe_read_register(wcn, | ||
382 | WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_H, | ||
383 | &int_reason); | ||
384 | |||
385 | /* TODO: Check int_reason */ | ||
386 | |||
387 | wcn36xx_dxe_write_register(wcn, | ||
388 | WCN36XX_DXE_0_INT_CLR, | ||
389 | WCN36XX_INT_MASK_CHAN_TX_H); | ||
390 | |||
391 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR, | ||
392 | WCN36XX_INT_MASK_CHAN_TX_H); | ||
393 | wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready high\n"); | ||
394 | reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch); | ||
395 | } | ||
396 | |||
397 | if (int_src & WCN36XX_INT_MASK_CHAN_TX_L) { | ||
398 | wcn36xx_dxe_read_register(wcn, | ||
399 | WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_L, | ||
400 | &int_reason); | ||
401 | /* TODO: Check int_reason */ | ||
402 | |||
403 | wcn36xx_dxe_write_register(wcn, | ||
404 | WCN36XX_DXE_0_INT_CLR, | ||
405 | WCN36XX_INT_MASK_CHAN_TX_L); | ||
406 | |||
407 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR, | ||
408 | WCN36XX_INT_MASK_CHAN_TX_L); | ||
409 | wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready low\n"); | ||
410 | reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch); | ||
411 | } | ||
412 | |||
413 | return IRQ_HANDLED; | ||
414 | } | ||
415 | |||
416 | static irqreturn_t wcn36xx_irq_rx_ready(int irq, void *dev) | ||
417 | { | ||
418 | struct wcn36xx *wcn = (struct wcn36xx *)dev; | ||
419 | |||
420 | disable_irq_nosync(wcn->rx_irq); | ||
421 | wcn36xx_dxe_rx_frame(wcn); | ||
422 | enable_irq(wcn->rx_irq); | ||
423 | return IRQ_HANDLED; | ||
424 | } | ||
425 | |||
426 | static int wcn36xx_dxe_request_irqs(struct wcn36xx *wcn) | ||
427 | { | ||
428 | int ret; | ||
429 | |||
430 | ret = request_irq(wcn->tx_irq, wcn36xx_irq_tx_complete, | ||
431 | IRQF_TRIGGER_HIGH, "wcn36xx_tx", wcn); | ||
432 | if (ret) { | ||
433 | wcn36xx_err("failed to alloc tx irq\n"); | ||
434 | goto out_err; | ||
435 | } | ||
436 | |||
437 | ret = request_irq(wcn->rx_irq, wcn36xx_irq_rx_ready, IRQF_TRIGGER_HIGH, | ||
438 | "wcn36xx_rx", wcn); | ||
439 | if (ret) { | ||
440 | wcn36xx_err("failed to alloc rx irq\n"); | ||
441 | goto out_txirq; | ||
442 | } | ||
443 | |||
444 | enable_irq_wake(wcn->rx_irq); | ||
445 | |||
446 | return 0; | ||
447 | |||
448 | out_txirq: | ||
449 | free_irq(wcn->tx_irq, wcn); | ||
450 | out_err: | ||
451 | return ret; | ||
452 | |||
453 | } | ||
454 | |||
455 | static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn, | ||
456 | struct wcn36xx_dxe_ch *ch) | ||
457 | { | ||
458 | struct wcn36xx_dxe_ctl *ctl = ch->head_blk_ctl; | ||
459 | struct wcn36xx_dxe_desc *dxe = ctl->desc; | ||
460 | dma_addr_t dma_addr; | ||
461 | struct sk_buff *skb; | ||
462 | |||
463 | while (!(dxe->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)) { | ||
464 | skb = ctl->skb; | ||
465 | dma_addr = dxe->dst_addr_l; | ||
466 | wcn36xx_dxe_fill_skb(ctl); | ||
467 | |||
468 | switch (ch->ch_type) { | ||
469 | case WCN36XX_DXE_CH_RX_L: | ||
470 | dxe->ctrl = WCN36XX_DXE_CTRL_RX_L; | ||
471 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_ENCH_ADDR, | ||
472 | WCN36XX_DXE_INT_CH1_MASK); | ||
473 | break; | ||
474 | case WCN36XX_DXE_CH_RX_H: | ||
475 | dxe->ctrl = WCN36XX_DXE_CTRL_RX_H; | ||
476 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_ENCH_ADDR, | ||
477 | WCN36XX_DXE_INT_CH3_MASK); | ||
478 | break; | ||
479 | default: | ||
480 | wcn36xx_warn("Unknown channel\n"); | ||
481 | } | ||
482 | |||
483 | dma_unmap_single(NULL, dma_addr, WCN36XX_PKT_SIZE, | ||
484 | DMA_FROM_DEVICE); | ||
485 | wcn36xx_rx_skb(wcn, skb); | ||
486 | ctl = ctl->next; | ||
487 | dxe = ctl->desc; | ||
488 | } | ||
489 | |||
490 | ch->head_blk_ctl = ctl; | ||
491 | |||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | void wcn36xx_dxe_rx_frame(struct wcn36xx *wcn) | ||
496 | { | ||
497 | int int_src; | ||
498 | |||
499 | wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src); | ||
500 | |||
501 | /* RX_LOW_PRI */ | ||
502 | if (int_src & WCN36XX_DXE_INT_CH1_MASK) { | ||
503 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR, | ||
504 | WCN36XX_DXE_INT_CH1_MASK); | ||
505 | wcn36xx_rx_handle_packets(wcn, &(wcn->dxe_rx_l_ch)); | ||
506 | } | ||
507 | |||
508 | /* RX_HIGH_PRI */ | ||
509 | if (int_src & WCN36XX_DXE_INT_CH3_MASK) { | ||
510 | /* Clean up all the INT within this channel */ | ||
511 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR, | ||
512 | WCN36XX_DXE_INT_CH3_MASK); | ||
513 | wcn36xx_rx_handle_packets(wcn, &(wcn->dxe_rx_h_ch)); | ||
514 | } | ||
515 | |||
516 | if (!int_src) | ||
517 | wcn36xx_warn("No DXE interrupt pending\n"); | ||
518 | } | ||
519 | |||
520 | int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn) | ||
521 | { | ||
522 | size_t s; | ||
523 | void *cpu_addr; | ||
524 | |||
525 | /* Allocate BD headers for MGMT frames */ | ||
526 | |||
527 | /* Where this come from ask QC */ | ||
528 | wcn->mgmt_mem_pool.chunk_size = WCN36XX_BD_CHUNK_SIZE + | ||
529 | 16 - (WCN36XX_BD_CHUNK_SIZE % 8); | ||
530 | |||
531 | s = wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H; | ||
532 | cpu_addr = dma_alloc_coherent(NULL, s, &wcn->mgmt_mem_pool.phy_addr, | ||
533 | GFP_KERNEL); | ||
534 | if (!cpu_addr) | ||
535 | goto out_err; | ||
536 | |||
537 | wcn->mgmt_mem_pool.virt_addr = cpu_addr; | ||
538 | memset(cpu_addr, 0, s); | ||
539 | |||
540 | /* Allocate BD headers for DATA frames */ | ||
541 | |||
542 | /* Where this come from ask QC */ | ||
543 | wcn->data_mem_pool.chunk_size = WCN36XX_BD_CHUNK_SIZE + | ||
544 | 16 - (WCN36XX_BD_CHUNK_SIZE % 8); | ||
545 | |||
546 | s = wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L; | ||
547 | cpu_addr = dma_alloc_coherent(NULL, s, &wcn->data_mem_pool.phy_addr, | ||
548 | GFP_KERNEL); | ||
549 | if (!cpu_addr) | ||
550 | goto out_err; | ||
551 | |||
552 | wcn->data_mem_pool.virt_addr = cpu_addr; | ||
553 | memset(cpu_addr, 0, s); | ||
554 | |||
555 | return 0; | ||
556 | |||
557 | out_err: | ||
558 | wcn36xx_dxe_free_mem_pools(wcn); | ||
559 | wcn36xx_err("Failed to allocate BD mempool\n"); | ||
560 | return -ENOMEM; | ||
561 | } | ||
562 | |||
563 | void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn) | ||
564 | { | ||
565 | if (wcn->mgmt_mem_pool.virt_addr) | ||
566 | dma_free_coherent(NULL, wcn->mgmt_mem_pool.chunk_size * | ||
567 | WCN36XX_DXE_CH_DESC_NUMB_TX_H, | ||
568 | wcn->mgmt_mem_pool.virt_addr, | ||
569 | wcn->mgmt_mem_pool.phy_addr); | ||
570 | |||
571 | if (wcn->data_mem_pool.virt_addr) { | ||
572 | dma_free_coherent(NULL, wcn->data_mem_pool.chunk_size * | ||
573 | WCN36XX_DXE_CH_DESC_NUMB_TX_L, | ||
574 | wcn->data_mem_pool.virt_addr, | ||
575 | wcn->data_mem_pool.phy_addr); | ||
576 | } | ||
577 | } | ||
578 | |||
579 | int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, | ||
580 | struct wcn36xx_vif *vif_priv, | ||
581 | struct sk_buff *skb, | ||
582 | bool is_low) | ||
583 | { | ||
584 | struct wcn36xx_dxe_ctl *ctl = NULL; | ||
585 | struct wcn36xx_dxe_desc *desc = NULL; | ||
586 | struct wcn36xx_dxe_ch *ch = NULL; | ||
587 | unsigned long flags; | ||
588 | |||
589 | ch = is_low ? &wcn->dxe_tx_l_ch : &wcn->dxe_tx_h_ch; | ||
590 | |||
591 | ctl = ch->head_blk_ctl; | ||
592 | |||
593 | spin_lock_irqsave(&ctl->next->skb_lock, flags); | ||
594 | |||
595 | /* | ||
596 | * If skb is not null that means that we reached the tail of the ring | ||
597 | * hence ring is full. Stop queues to let mac80211 back off until ring | ||
598 | * has an empty slot again. | ||
599 | */ | ||
600 | if (NULL != ctl->next->skb) { | ||
601 | ieee80211_stop_queues(wcn->hw); | ||
602 | wcn->queues_stopped = true; | ||
603 | spin_unlock_irqrestore(&ctl->next->skb_lock, flags); | ||
604 | return -EBUSY; | ||
605 | } | ||
606 | spin_unlock_irqrestore(&ctl->next->skb_lock, flags); | ||
607 | |||
608 | ctl->skb = NULL; | ||
609 | desc = ctl->desc; | ||
610 | |||
611 | /* Set source address of the BD we send */ | ||
612 | desc->src_addr_l = ctl->bd_phy_addr; | ||
613 | |||
614 | desc->dst_addr_l = ch->dxe_wq; | ||
615 | desc->fr_len = sizeof(struct wcn36xx_tx_bd); | ||
616 | desc->ctrl = ch->ctrl_bd; | ||
617 | |||
618 | wcn36xx_dbg(WCN36XX_DBG_DXE, "DXE TX\n"); | ||
619 | |||
620 | wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC1 >>> ", | ||
621 | (char *)desc, sizeof(*desc)); | ||
622 | wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, | ||
623 | "BD >>> ", (char *)ctl->bd_cpu_addr, | ||
624 | sizeof(struct wcn36xx_tx_bd)); | ||
625 | |||
626 | /* Set source address of the SKB we send */ | ||
627 | ctl = ctl->next; | ||
628 | ctl->skb = skb; | ||
629 | desc = ctl->desc; | ||
630 | if (ctl->bd_cpu_addr) { | ||
631 | wcn36xx_err("bd_cpu_addr cannot be NULL for skb DXE\n"); | ||
632 | return -EINVAL; | ||
633 | } | ||
634 | |||
635 | desc->src_addr_l = dma_map_single(NULL, | ||
636 | ctl->skb->data, | ||
637 | ctl->skb->len, | ||
638 | DMA_TO_DEVICE); | ||
639 | |||
640 | desc->dst_addr_l = ch->dxe_wq; | ||
641 | desc->fr_len = ctl->skb->len; | ||
642 | |||
643 | /* set dxe descriptor to VALID */ | ||
644 | desc->ctrl = ch->ctrl_skb; | ||
645 | |||
646 | wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC2 >>> ", | ||
647 | (char *)desc, sizeof(*desc)); | ||
648 | wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "SKB >>> ", | ||
649 | (char *)ctl->skb->data, ctl->skb->len); | ||
650 | |||
651 | /* Move the head of the ring to the next empty descriptor */ | ||
652 | ch->head_blk_ctl = ctl->next; | ||
653 | |||
654 | /* | ||
655 | * When connected and trying to send data frame chip can be in sleep | ||
656 | * mode and writing to the register will not wake up the chip. Instead | ||
657 | * notify chip about new frame through SMSM bus. | ||
658 | */ | ||
659 | if (is_low && vif_priv->pw_state == WCN36XX_BMPS) { | ||
660 | wcn->ctrl_ops->smsm_change_state( | ||
661 | 0, | ||
662 | WCN36XX_SMSM_WLAN_TX_ENABLE); | ||
663 | } else { | ||
664 | /* indicate End Of Packet and generate interrupt on descriptor | ||
665 | * done. | ||
666 | */ | ||
667 | wcn36xx_dxe_write_register(wcn, | ||
668 | ch->reg_ctrl, ch->def_ctrl); | ||
669 | } | ||
670 | |||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | int wcn36xx_dxe_init(struct wcn36xx *wcn) | ||
675 | { | ||
676 | int reg_data = 0, ret; | ||
677 | |||
678 | reg_data = WCN36XX_DXE_REG_RESET; | ||
679 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CSR_RESET, reg_data); | ||
680 | |||
681 | /* Setting interrupt path */ | ||
682 | reg_data = WCN36XX_DXE_CCU_INT; | ||
683 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CCU_INT, reg_data); | ||
684 | |||
685 | /***************************************/ | ||
686 | /* Init descriptors for TX LOW channel */ | ||
687 | /***************************************/ | ||
688 | wcn36xx_dxe_init_descs(&wcn->dxe_tx_l_ch); | ||
689 | wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_l_ch, &wcn->data_mem_pool); | ||
690 | |||
691 | /* Write channel head to a NEXT register */ | ||
692 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_L, | ||
693 | wcn->dxe_tx_l_ch.head_blk_ctl->desc_phy_addr); | ||
694 | |||
695 | /* Program DMA destination addr for TX LOW */ | ||
696 | wcn36xx_dxe_write_register(wcn, | ||
697 | WCN36XX_DXE_CH_DEST_ADDR_TX_L, | ||
698 | WCN36XX_DXE_WQ_TX_L); | ||
699 | |||
700 | wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data); | ||
701 | wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L); | ||
702 | |||
703 | /***************************************/ | ||
704 | /* Init descriptors for TX HIGH channel */ | ||
705 | /***************************************/ | ||
706 | wcn36xx_dxe_init_descs(&wcn->dxe_tx_h_ch); | ||
707 | wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_h_ch, &wcn->mgmt_mem_pool); | ||
708 | |||
709 | /* Write channel head to a NEXT register */ | ||
710 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_H, | ||
711 | wcn->dxe_tx_h_ch.head_blk_ctl->desc_phy_addr); | ||
712 | |||
713 | /* Program DMA destination addr for TX HIGH */ | ||
714 | wcn36xx_dxe_write_register(wcn, | ||
715 | WCN36XX_DXE_CH_DEST_ADDR_TX_H, | ||
716 | WCN36XX_DXE_WQ_TX_H); | ||
717 | |||
718 | wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data); | ||
719 | |||
720 | /* Enable channel interrupts */ | ||
721 | wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H); | ||
722 | |||
723 | /***************************************/ | ||
724 | /* Init descriptors for RX LOW channel */ | ||
725 | /***************************************/ | ||
726 | wcn36xx_dxe_init_descs(&wcn->dxe_rx_l_ch); | ||
727 | |||
728 | /* For RX we need to preallocated buffers */ | ||
729 | wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch); | ||
730 | |||
731 | /* Write channel head to a NEXT register */ | ||
732 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_L, | ||
733 | wcn->dxe_rx_l_ch.head_blk_ctl->desc_phy_addr); | ||
734 | |||
735 | /* Write DMA source address */ | ||
736 | wcn36xx_dxe_write_register(wcn, | ||
737 | WCN36XX_DXE_CH_SRC_ADDR_RX_L, | ||
738 | WCN36XX_DXE_WQ_RX_L); | ||
739 | |||
740 | /* Program preallocated destination address */ | ||
741 | wcn36xx_dxe_write_register(wcn, | ||
742 | WCN36XX_DXE_CH_DEST_ADDR_RX_L, | ||
743 | wcn->dxe_rx_l_ch.head_blk_ctl->desc->phy_next_l); | ||
744 | |||
745 | /* Enable default control registers */ | ||
746 | wcn36xx_dxe_write_register(wcn, | ||
747 | WCN36XX_DXE_REG_CTL_RX_L, | ||
748 | WCN36XX_DXE_CH_DEFAULT_CTL_RX_L); | ||
749 | |||
750 | /* Enable channel interrupts */ | ||
751 | wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L); | ||
752 | |||
753 | /***************************************/ | ||
754 | /* Init descriptors for RX HIGH channel */ | ||
755 | /***************************************/ | ||
756 | wcn36xx_dxe_init_descs(&wcn->dxe_rx_h_ch); | ||
757 | |||
758 | /* For RX we need to prealocat buffers */ | ||
759 | wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch); | ||
760 | |||
761 | /* Write chanel head to a NEXT register */ | ||
762 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_H, | ||
763 | wcn->dxe_rx_h_ch.head_blk_ctl->desc_phy_addr); | ||
764 | |||
765 | /* Write DMA source address */ | ||
766 | wcn36xx_dxe_write_register(wcn, | ||
767 | WCN36XX_DXE_CH_SRC_ADDR_RX_H, | ||
768 | WCN36XX_DXE_WQ_RX_H); | ||
769 | |||
770 | /* Program preallocated destination address */ | ||
771 | wcn36xx_dxe_write_register(wcn, | ||
772 | WCN36XX_DXE_CH_DEST_ADDR_RX_H, | ||
773 | wcn->dxe_rx_h_ch.head_blk_ctl->desc->phy_next_l); | ||
774 | |||
775 | /* Enable default control registers */ | ||
776 | wcn36xx_dxe_write_register(wcn, | ||
777 | WCN36XX_DXE_REG_CTL_RX_H, | ||
778 | WCN36XX_DXE_CH_DEFAULT_CTL_RX_H); | ||
779 | |||
780 | /* Enable channel interrupts */ | ||
781 | wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H); | ||
782 | |||
783 | ret = wcn36xx_dxe_request_irqs(wcn); | ||
784 | if (ret < 0) | ||
785 | goto out_err; | ||
786 | |||
787 | return 0; | ||
788 | |||
789 | out_err: | ||
790 | return ret; | ||
791 | } | ||
792 | |||
793 | void wcn36xx_dxe_deinit(struct wcn36xx *wcn) | ||
794 | { | ||
795 | free_irq(wcn->tx_irq, wcn); | ||
796 | free_irq(wcn->rx_irq, wcn); | ||
797 | |||
798 | if (wcn->tx_ack_skb) { | ||
799 | ieee80211_tx_status_irqsafe(wcn->hw, wcn->tx_ack_skb); | ||
800 | wcn->tx_ack_skb = NULL; | ||
801 | } | ||
802 | |||
803 | wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_l_ch); | ||
804 | wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_h_ch); | ||
805 | } | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.h b/drivers/net/wireless/ath/wcn36xx/dxe.h new file mode 100644 index 000000000000..c88562f85de1 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/dxe.h | |||
@@ -0,0 +1,284 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _DXE_H_ | ||
18 | #define _DXE_H_ | ||
19 | |||
20 | #include "wcn36xx.h" | ||
21 | |||
22 | /* | ||
23 | TX_LOW = DMA0 | ||
24 | TX_HIGH = DMA4 | ||
25 | RX_LOW = DMA1 | ||
26 | RX_HIGH = DMA3 | ||
27 | H2H_TEST_RX_TX = DMA2 | ||
28 | */ | ||
29 | |||
30 | /* DXE registers */ | ||
31 | #define WCN36XX_DXE_MEM_BASE 0x03000000 | ||
32 | #define WCN36XX_DXE_MEM_REG 0x202000 | ||
33 | |||
34 | #define WCN36XX_DXE_CCU_INT 0xA0011 | ||
35 | #define WCN36XX_DXE_REG_CCU_INT 0x200b10 | ||
36 | |||
37 | /* TODO This must calculated properly but not hardcoded */ | ||
38 | #define WCN36XX_DXE_CTRL_TX_L 0x328a44 | ||
39 | #define WCN36XX_DXE_CTRL_TX_H 0x32ce44 | ||
40 | #define WCN36XX_DXE_CTRL_RX_L 0x12ad2f | ||
41 | #define WCN36XX_DXE_CTRL_RX_H 0x12d12f | ||
42 | #define WCN36XX_DXE_CTRL_TX_H_BD 0x30ce45 | ||
43 | #define WCN36XX_DXE_CTRL_TX_H_SKB 0x32ce4d | ||
44 | #define WCN36XX_DXE_CTRL_TX_L_BD 0x308a45 | ||
45 | #define WCN36XX_DXE_CTRL_TX_L_SKB 0x328a4d | ||
46 | |||
47 | /* TODO This must calculated properly but not hardcoded */ | ||
48 | #define WCN36XX_DXE_WQ_TX_L 0x17 | ||
49 | #define WCN36XX_DXE_WQ_TX_H 0x17 | ||
50 | #define WCN36XX_DXE_WQ_RX_L 0xB | ||
51 | #define WCN36XX_DXE_WQ_RX_H 0x4 | ||
52 | |||
53 | /* DXE descriptor control filed */ | ||
54 | #define WCN36XX_DXE_CTRL_VALID_MASK (0x00000001) | ||
55 | |||
56 | /* TODO This must calculated properly but not hardcoded */ | ||
57 | /* DXE default control register values */ | ||
58 | #define WCN36XX_DXE_CH_DEFAULT_CTL_RX_L 0x847EAD2F | ||
59 | #define WCN36XX_DXE_CH_DEFAULT_CTL_RX_H 0x84FED12F | ||
60 | #define WCN36XX_DXE_CH_DEFAULT_CTL_TX_H 0x853ECF4D | ||
61 | #define WCN36XX_DXE_CH_DEFAULT_CTL_TX_L 0x843e8b4d | ||
62 | |||
63 | /* Common DXE registers */ | ||
64 | #define WCN36XX_DXE_MEM_CSR (WCN36XX_DXE_MEM_REG + 0x00) | ||
65 | #define WCN36XX_DXE_REG_CSR_RESET (WCN36XX_DXE_MEM_REG + 0x00) | ||
66 | #define WCN36XX_DXE_ENCH_ADDR (WCN36XX_DXE_MEM_REG + 0x04) | ||
67 | #define WCN36XX_DXE_REG_CH_EN (WCN36XX_DXE_MEM_REG + 0x08) | ||
68 | #define WCN36XX_DXE_REG_CH_DONE (WCN36XX_DXE_MEM_REG + 0x0C) | ||
69 | #define WCN36XX_DXE_REG_CH_ERR (WCN36XX_DXE_MEM_REG + 0x10) | ||
70 | #define WCN36XX_DXE_INT_MASK_REG (WCN36XX_DXE_MEM_REG + 0x18) | ||
71 | #define WCN36XX_DXE_INT_SRC_RAW_REG (WCN36XX_DXE_MEM_REG + 0x20) | ||
72 | /* #define WCN36XX_DXE_INT_CH6_MASK 0x00000040 */ | ||
73 | /* #define WCN36XX_DXE_INT_CH5_MASK 0x00000020 */ | ||
74 | #define WCN36XX_DXE_INT_CH4_MASK 0x00000010 | ||
75 | #define WCN36XX_DXE_INT_CH3_MASK 0x00000008 | ||
76 | /* #define WCN36XX_DXE_INT_CH2_MASK 0x00000004 */ | ||
77 | #define WCN36XX_DXE_INT_CH1_MASK 0x00000002 | ||
78 | #define WCN36XX_DXE_INT_CH0_MASK 0x00000001 | ||
79 | #define WCN36XX_DXE_0_INT_CLR (WCN36XX_DXE_MEM_REG + 0x30) | ||
80 | #define WCN36XX_DXE_0_INT_ED_CLR (WCN36XX_DXE_MEM_REG + 0x34) | ||
81 | #define WCN36XX_DXE_0_INT_DONE_CLR (WCN36XX_DXE_MEM_REG + 0x38) | ||
82 | #define WCN36XX_DXE_0_INT_ERR_CLR (WCN36XX_DXE_MEM_REG + 0x3C) | ||
83 | |||
84 | #define WCN36XX_DXE_0_CH0_STATUS (WCN36XX_DXE_MEM_REG + 0x404) | ||
85 | #define WCN36XX_DXE_0_CH1_STATUS (WCN36XX_DXE_MEM_REG + 0x444) | ||
86 | #define WCN36XX_DXE_0_CH2_STATUS (WCN36XX_DXE_MEM_REG + 0x484) | ||
87 | #define WCN36XX_DXE_0_CH3_STATUS (WCN36XX_DXE_MEM_REG + 0x4C4) | ||
88 | #define WCN36XX_DXE_0_CH4_STATUS (WCN36XX_DXE_MEM_REG + 0x504) | ||
89 | |||
90 | #define WCN36XX_DXE_REG_RESET 0x5c89 | ||
91 | |||
92 | /* Temporary BMU Workqueue 4 */ | ||
93 | #define WCN36XX_DXE_BMU_WQ_RX_LOW 0xB | ||
94 | #define WCN36XX_DXE_BMU_WQ_RX_HIGH 0x4 | ||
95 | /* DMA channel offset */ | ||
96 | #define WCN36XX_DXE_TX_LOW_OFFSET 0x400 | ||
97 | #define WCN36XX_DXE_TX_HIGH_OFFSET 0x500 | ||
98 | #define WCN36XX_DXE_RX_LOW_OFFSET 0x440 | ||
99 | #define WCN36XX_DXE_RX_HIGH_OFFSET 0x4C0 | ||
100 | |||
101 | /* Address of the next DXE descriptor */ | ||
102 | #define WCN36XX_DXE_CH_NEXT_DESC_ADDR 0x001C | ||
103 | #define WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_L (WCN36XX_DXE_MEM_REG + \ | ||
104 | WCN36XX_DXE_TX_LOW_OFFSET + \ | ||
105 | WCN36XX_DXE_CH_NEXT_DESC_ADDR) | ||
106 | #define WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_H (WCN36XX_DXE_MEM_REG + \ | ||
107 | WCN36XX_DXE_TX_HIGH_OFFSET + \ | ||
108 | WCN36XX_DXE_CH_NEXT_DESC_ADDR) | ||
109 | #define WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_L (WCN36XX_DXE_MEM_REG + \ | ||
110 | WCN36XX_DXE_RX_LOW_OFFSET + \ | ||
111 | WCN36XX_DXE_CH_NEXT_DESC_ADDR) | ||
112 | #define WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_H (WCN36XX_DXE_MEM_REG + \ | ||
113 | WCN36XX_DXE_RX_HIGH_OFFSET + \ | ||
114 | WCN36XX_DXE_CH_NEXT_DESC_ADDR) | ||
115 | |||
116 | /* DXE Descriptor source address */ | ||
117 | #define WCN36XX_DXE_CH_SRC_ADDR 0x000C | ||
118 | #define WCN36XX_DXE_CH_SRC_ADDR_RX_L (WCN36XX_DXE_MEM_REG + \ | ||
119 | WCN36XX_DXE_RX_LOW_OFFSET + \ | ||
120 | WCN36XX_DXE_CH_SRC_ADDR) | ||
121 | #define WCN36XX_DXE_CH_SRC_ADDR_RX_H (WCN36XX_DXE_MEM_REG + \ | ||
122 | WCN36XX_DXE_RX_HIGH_OFFSET + \ | ||
123 | WCN36XX_DXE_CH_SRC_ADDR) | ||
124 | |||
125 | /* DXE Descriptor address destination address */ | ||
126 | #define WCN36XX_DXE_CH_DEST_ADDR 0x0014 | ||
127 | #define WCN36XX_DXE_CH_DEST_ADDR_TX_L (WCN36XX_DXE_MEM_REG + \ | ||
128 | WCN36XX_DXE_TX_LOW_OFFSET + \ | ||
129 | WCN36XX_DXE_CH_DEST_ADDR) | ||
130 | #define WCN36XX_DXE_CH_DEST_ADDR_TX_H (WCN36XX_DXE_MEM_REG + \ | ||
131 | WCN36XX_DXE_TX_HIGH_OFFSET + \ | ||
132 | WCN36XX_DXE_CH_DEST_ADDR) | ||
133 | #define WCN36XX_DXE_CH_DEST_ADDR_RX_L (WCN36XX_DXE_MEM_REG + \ | ||
134 | WCN36XX_DXE_RX_LOW_OFFSET + \ | ||
135 | WCN36XX_DXE_CH_DEST_ADDR) | ||
136 | #define WCN36XX_DXE_CH_DEST_ADDR_RX_H (WCN36XX_DXE_MEM_REG + \ | ||
137 | WCN36XX_DXE_RX_HIGH_OFFSET + \ | ||
138 | WCN36XX_DXE_CH_DEST_ADDR) | ||
139 | |||
140 | /* Interrupt status */ | ||
141 | #define WCN36XX_DXE_CH_STATUS_REG_ADDR 0x0004 | ||
142 | #define WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_L (WCN36XX_DXE_MEM_REG + \ | ||
143 | WCN36XX_DXE_TX_LOW_OFFSET + \ | ||
144 | WCN36XX_DXE_CH_STATUS_REG_ADDR) | ||
145 | #define WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_H (WCN36XX_DXE_MEM_REG + \ | ||
146 | WCN36XX_DXE_TX_HIGH_OFFSET + \ | ||
147 | WCN36XX_DXE_CH_STATUS_REG_ADDR) | ||
148 | #define WCN36XX_DXE_CH_STATUS_REG_ADDR_RX_L (WCN36XX_DXE_MEM_REG + \ | ||
149 | WCN36XX_DXE_RX_LOW_OFFSET + \ | ||
150 | WCN36XX_DXE_CH_STATUS_REG_ADDR) | ||
151 | #define WCN36XX_DXE_CH_STATUS_REG_ADDR_RX_H (WCN36XX_DXE_MEM_REG + \ | ||
152 | WCN36XX_DXE_RX_HIGH_OFFSET + \ | ||
153 | WCN36XX_DXE_CH_STATUS_REG_ADDR) | ||
154 | |||
155 | |||
156 | /* DXE default control register */ | ||
157 | #define WCN36XX_DXE_REG_CTL_RX_L (WCN36XX_DXE_MEM_REG + \ | ||
158 | WCN36XX_DXE_RX_LOW_OFFSET) | ||
159 | #define WCN36XX_DXE_REG_CTL_RX_H (WCN36XX_DXE_MEM_REG + \ | ||
160 | WCN36XX_DXE_RX_HIGH_OFFSET) | ||
161 | #define WCN36XX_DXE_REG_CTL_TX_H (WCN36XX_DXE_MEM_REG + \ | ||
162 | WCN36XX_DXE_TX_HIGH_OFFSET) | ||
163 | #define WCN36XX_DXE_REG_CTL_TX_L (WCN36XX_DXE_MEM_REG + \ | ||
164 | WCN36XX_DXE_TX_LOW_OFFSET) | ||
165 | |||
166 | #define WCN36XX_SMSM_WLAN_TX_ENABLE 0x00000400 | ||
167 | #define WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY 0x00000200 | ||
168 | |||
169 | |||
170 | /* Interrupt control channel mask */ | ||
171 | #define WCN36XX_INT_MASK_CHAN_TX_L 0x00000001 | ||
172 | #define WCN36XX_INT_MASK_CHAN_RX_L 0x00000002 | ||
173 | #define WCN36XX_INT_MASK_CHAN_RX_H 0x00000008 | ||
174 | #define WCN36XX_INT_MASK_CHAN_TX_H 0x00000010 | ||
175 | |||
176 | #define WCN36XX_BD_CHUNK_SIZE 128 | ||
177 | |||
178 | #define WCN36XX_PKT_SIZE 0xF20 | ||
179 | enum wcn36xx_dxe_ch_type { | ||
180 | WCN36XX_DXE_CH_TX_L, | ||
181 | WCN36XX_DXE_CH_TX_H, | ||
182 | WCN36XX_DXE_CH_RX_L, | ||
183 | WCN36XX_DXE_CH_RX_H | ||
184 | }; | ||
185 | |||
186 | /* amount of descriptors per channel */ | ||
187 | enum wcn36xx_dxe_ch_desc_num { | ||
188 | WCN36XX_DXE_CH_DESC_NUMB_TX_L = 128, | ||
189 | WCN36XX_DXE_CH_DESC_NUMB_TX_H = 10, | ||
190 | WCN36XX_DXE_CH_DESC_NUMB_RX_L = 512, | ||
191 | WCN36XX_DXE_CH_DESC_NUMB_RX_H = 40 | ||
192 | }; | ||
193 | |||
194 | /** | ||
195 | * struct wcn36xx_dxe_desc - describes descriptor of one DXE buffer | ||
196 | * | ||
197 | * @ctrl: is a union that consists of following bits: | ||
198 | * union { | ||
199 | * u32 valid :1; //0 = DMA stop, 1 = DMA continue with this | ||
200 | * //descriptor | ||
201 | * u32 transfer_type :2; //0 = Host to Host space | ||
202 | * u32 eop :1; //End of Packet | ||
203 | * u32 bd_handling :1; //if transferType = Host to BMU, then 0 | ||
204 | * // means first 128 bytes contain BD, and 1 | ||
205 | * // means create new empty BD | ||
206 | * u32 siq :1; // SIQ | ||
207 | * u32 diq :1; // DIQ | ||
208 | * u32 pdu_rel :1; //0 = don't release BD and PDUs when done, | ||
209 | * // 1 = release them | ||
210 | * u32 bthld_sel :4; //BMU Threshold Select | ||
211 | * u32 prio :3; //Specifies the priority level to use for | ||
212 | * // the transfer | ||
213 | * u32 stop_channel :1; //1 = DMA stops processing further, channel | ||
214 | * //requires re-enabling after this | ||
215 | * u32 intr :1; //Interrupt on Descriptor Done | ||
216 | * u32 rsvd :1; //reserved | ||
217 | * u32 size :14;//14 bits used - ignored for BMU transfers, | ||
218 | * //only used for host to host transfers? | ||
219 | * } ctrl; | ||
220 | */ | ||
221 | struct wcn36xx_dxe_desc { | ||
222 | u32 ctrl; | ||
223 | u32 fr_len; | ||
224 | |||
225 | u32 src_addr_l; | ||
226 | u32 dst_addr_l; | ||
227 | u32 phy_next_l; | ||
228 | u32 src_addr_h; | ||
229 | u32 dst_addr_h; | ||
230 | u32 phy_next_h; | ||
231 | } __packed; | ||
232 | |||
233 | /* DXE Control block */ | ||
234 | struct wcn36xx_dxe_ctl { | ||
235 | struct wcn36xx_dxe_ctl *next; | ||
236 | struct wcn36xx_dxe_desc *desc; | ||
237 | unsigned int desc_phy_addr; | ||
238 | int ctl_blk_order; | ||
239 | struct sk_buff *skb; | ||
240 | spinlock_t skb_lock; | ||
241 | void *bd_cpu_addr; | ||
242 | dma_addr_t bd_phy_addr; | ||
243 | }; | ||
244 | |||
245 | struct wcn36xx_dxe_ch { | ||
246 | enum wcn36xx_dxe_ch_type ch_type; | ||
247 | void *cpu_addr; | ||
248 | dma_addr_t dma_addr; | ||
249 | enum wcn36xx_dxe_ch_desc_num desc_num; | ||
250 | /* DXE control block ring */ | ||
251 | struct wcn36xx_dxe_ctl *head_blk_ctl; | ||
252 | struct wcn36xx_dxe_ctl *tail_blk_ctl; | ||
253 | |||
254 | /* DXE channel specific configs */ | ||
255 | u32 dxe_wq; | ||
256 | u32 ctrl_bd; | ||
257 | u32 ctrl_skb; | ||
258 | u32 reg_ctrl; | ||
259 | u32 def_ctrl; | ||
260 | }; | ||
261 | |||
262 | /* Memory Pool for BD headers */ | ||
263 | struct wcn36xx_dxe_mem_pool { | ||
264 | int chunk_size; | ||
265 | void *virt_addr; | ||
266 | dma_addr_t phy_addr; | ||
267 | }; | ||
268 | |||
269 | struct wcn36xx_vif; | ||
270 | int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn); | ||
271 | void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn); | ||
272 | void wcn36xx_dxe_rx_frame(struct wcn36xx *wcn); | ||
273 | int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn); | ||
274 | void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn); | ||
275 | int wcn36xx_dxe_init(struct wcn36xx *wcn); | ||
276 | void wcn36xx_dxe_deinit(struct wcn36xx *wcn); | ||
277 | int wcn36xx_dxe_init_channels(struct wcn36xx *wcn); | ||
278 | int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, | ||
279 | struct wcn36xx_vif *vif_priv, | ||
280 | struct sk_buff *skb, | ||
281 | bool is_low); | ||
282 | void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status); | ||
283 | void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool is_low); | ||
284 | #endif /* _DXE_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h new file mode 100644 index 000000000000..c02dbc618724 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/hal.h | |||
@@ -0,0 +1,4657 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _HAL_H_ | ||
18 | #define _HAL_H_ | ||
19 | |||
20 | /*--------------------------------------------------------------------------- | ||
21 | API VERSIONING INFORMATION | ||
22 | |||
23 | The RIVA API is versioned as MAJOR.MINOR.VERSION.REVISION | ||
24 | The MAJOR is incremented for major product/architecture changes | ||
25 | (and then MINOR/VERSION/REVISION are zeroed) | ||
26 | The MINOR is incremented for minor product/architecture changes | ||
27 | (and then VERSION/REVISION are zeroed) | ||
28 | The VERSION is incremented if a significant API change occurs | ||
29 | (and then REVISION is zeroed) | ||
30 | The REVISION is incremented if an insignificant API change occurs | ||
31 | or if a new API is added | ||
32 | All values are in the range 0..255 (ie they are 8-bit values) | ||
33 | ---------------------------------------------------------------------------*/ | ||
34 | #define WCN36XX_HAL_VER_MAJOR 1 | ||
35 | #define WCN36XX_HAL_VER_MINOR 4 | ||
36 | #define WCN36XX_HAL_VER_VERSION 1 | ||
37 | #define WCN36XX_HAL_VER_REVISION 2 | ||
38 | |||
39 | /* This is to force compiler to use the maximum of an int ( 4 bytes ) */ | ||
40 | #define WCN36XX_HAL_MAX_ENUM_SIZE 0x7FFFFFFF | ||
41 | #define WCN36XX_HAL_MSG_TYPE_MAX_ENUM_SIZE 0x7FFF | ||
42 | |||
43 | /* Max no. of transmit categories */ | ||
44 | #define STACFG_MAX_TC 8 | ||
45 | |||
46 | /* The maximum value of access category */ | ||
47 | #define WCN36XX_HAL_MAX_AC 4 | ||
48 | |||
49 | #define WCN36XX_HAL_IPV4_ADDR_LEN 4 | ||
50 | |||
51 | #define WALN_HAL_STA_INVALID_IDX 0xFF | ||
52 | #define WCN36XX_HAL_BSS_INVALID_IDX 0xFF | ||
53 | |||
54 | /* Default Beacon template size */ | ||
55 | #define BEACON_TEMPLATE_SIZE 0x180 | ||
56 | |||
57 | /* Param Change Bitmap sent to HAL */ | ||
58 | #define PARAM_BCN_INTERVAL_CHANGED (1 << 0) | ||
59 | #define PARAM_SHORT_PREAMBLE_CHANGED (1 << 1) | ||
60 | #define PARAM_SHORT_SLOT_TIME_CHANGED (1 << 2) | ||
61 | #define PARAM_llACOEXIST_CHANGED (1 << 3) | ||
62 | #define PARAM_llBCOEXIST_CHANGED (1 << 4) | ||
63 | #define PARAM_llGCOEXIST_CHANGED (1 << 5) | ||
64 | #define PARAM_HT20MHZCOEXIST_CHANGED (1<<6) | ||
65 | #define PARAM_NON_GF_DEVICES_PRESENT_CHANGED (1<<7) | ||
66 | #define PARAM_RIFS_MODE_CHANGED (1<<8) | ||
67 | #define PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED (1<<9) | ||
68 | #define PARAM_OBSS_MODE_CHANGED (1<<10) | ||
69 | #define PARAM_BEACON_UPDATE_MASK \ | ||
70 | (PARAM_BCN_INTERVAL_CHANGED | \ | ||
71 | PARAM_SHORT_PREAMBLE_CHANGED | \ | ||
72 | PARAM_SHORT_SLOT_TIME_CHANGED | \ | ||
73 | PARAM_llACOEXIST_CHANGED | \ | ||
74 | PARAM_llBCOEXIST_CHANGED | \ | ||
75 | PARAM_llGCOEXIST_CHANGED | \ | ||
76 | PARAM_HT20MHZCOEXIST_CHANGED | \ | ||
77 | PARAM_NON_GF_DEVICES_PRESENT_CHANGED | \ | ||
78 | PARAM_RIFS_MODE_CHANGED | \ | ||
79 | PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED | \ | ||
80 | PARAM_OBSS_MODE_CHANGED) | ||
81 | |||
82 | /* dump command response Buffer size */ | ||
83 | #define DUMPCMD_RSP_BUFFER 100 | ||
84 | |||
85 | /* version string max length (including NULL) */ | ||
86 | #define WCN36XX_HAL_VERSION_LENGTH 64 | ||
87 | |||
88 | /* message types for messages exchanged between WDI and HAL */ | ||
89 | enum wcn36xx_hal_host_msg_type { | ||
90 | /* Init/De-Init */ | ||
91 | WCN36XX_HAL_START_REQ = 0, | ||
92 | WCN36XX_HAL_START_RSP = 1, | ||
93 | WCN36XX_HAL_STOP_REQ = 2, | ||
94 | WCN36XX_HAL_STOP_RSP = 3, | ||
95 | |||
96 | /* Scan */ | ||
97 | WCN36XX_HAL_INIT_SCAN_REQ = 4, | ||
98 | WCN36XX_HAL_INIT_SCAN_RSP = 5, | ||
99 | WCN36XX_HAL_START_SCAN_REQ = 6, | ||
100 | WCN36XX_HAL_START_SCAN_RSP = 7, | ||
101 | WCN36XX_HAL_END_SCAN_REQ = 8, | ||
102 | WCN36XX_HAL_END_SCAN_RSP = 9, | ||
103 | WCN36XX_HAL_FINISH_SCAN_REQ = 10, | ||
104 | WCN36XX_HAL_FINISH_SCAN_RSP = 11, | ||
105 | |||
106 | /* HW STA configuration/deconfiguration */ | ||
107 | WCN36XX_HAL_CONFIG_STA_REQ = 12, | ||
108 | WCN36XX_HAL_CONFIG_STA_RSP = 13, | ||
109 | WCN36XX_HAL_DELETE_STA_REQ = 14, | ||
110 | WCN36XX_HAL_DELETE_STA_RSP = 15, | ||
111 | WCN36XX_HAL_CONFIG_BSS_REQ = 16, | ||
112 | WCN36XX_HAL_CONFIG_BSS_RSP = 17, | ||
113 | WCN36XX_HAL_DELETE_BSS_REQ = 18, | ||
114 | WCN36XX_HAL_DELETE_BSS_RSP = 19, | ||
115 | |||
116 | /* Infra STA asscoiation */ | ||
117 | WCN36XX_HAL_JOIN_REQ = 20, | ||
118 | WCN36XX_HAL_JOIN_RSP = 21, | ||
119 | WCN36XX_HAL_POST_ASSOC_REQ = 22, | ||
120 | WCN36XX_HAL_POST_ASSOC_RSP = 23, | ||
121 | |||
122 | /* Security */ | ||
123 | WCN36XX_HAL_SET_BSSKEY_REQ = 24, | ||
124 | WCN36XX_HAL_SET_BSSKEY_RSP = 25, | ||
125 | WCN36XX_HAL_SET_STAKEY_REQ = 26, | ||
126 | WCN36XX_HAL_SET_STAKEY_RSP = 27, | ||
127 | WCN36XX_HAL_RMV_BSSKEY_REQ = 28, | ||
128 | WCN36XX_HAL_RMV_BSSKEY_RSP = 29, | ||
129 | WCN36XX_HAL_RMV_STAKEY_REQ = 30, | ||
130 | WCN36XX_HAL_RMV_STAKEY_RSP = 31, | ||
131 | |||
132 | /* Qos Related */ | ||
133 | WCN36XX_HAL_ADD_TS_REQ = 32, | ||
134 | WCN36XX_HAL_ADD_TS_RSP = 33, | ||
135 | WCN36XX_HAL_DEL_TS_REQ = 34, | ||
136 | WCN36XX_HAL_DEL_TS_RSP = 35, | ||
137 | WCN36XX_HAL_UPD_EDCA_PARAMS_REQ = 36, | ||
138 | WCN36XX_HAL_UPD_EDCA_PARAMS_RSP = 37, | ||
139 | WCN36XX_HAL_ADD_BA_REQ = 38, | ||
140 | WCN36XX_HAL_ADD_BA_RSP = 39, | ||
141 | WCN36XX_HAL_DEL_BA_REQ = 40, | ||
142 | WCN36XX_HAL_DEL_BA_RSP = 41, | ||
143 | |||
144 | WCN36XX_HAL_CH_SWITCH_REQ = 42, | ||
145 | WCN36XX_HAL_CH_SWITCH_RSP = 43, | ||
146 | WCN36XX_HAL_SET_LINK_ST_REQ = 44, | ||
147 | WCN36XX_HAL_SET_LINK_ST_RSP = 45, | ||
148 | WCN36XX_HAL_GET_STATS_REQ = 46, | ||
149 | WCN36XX_HAL_GET_STATS_RSP = 47, | ||
150 | WCN36XX_HAL_UPDATE_CFG_REQ = 48, | ||
151 | WCN36XX_HAL_UPDATE_CFG_RSP = 49, | ||
152 | |||
153 | WCN36XX_HAL_MISSED_BEACON_IND = 50, | ||
154 | WCN36XX_HAL_UNKNOWN_ADDR2_FRAME_RX_IND = 51, | ||
155 | WCN36XX_HAL_MIC_FAILURE_IND = 52, | ||
156 | WCN36XX_HAL_FATAL_ERROR_IND = 53, | ||
157 | WCN36XX_HAL_SET_KEYDONE_MSG = 54, | ||
158 | |||
159 | /* NV Interface */ | ||
160 | WCN36XX_HAL_DOWNLOAD_NV_REQ = 55, | ||
161 | WCN36XX_HAL_DOWNLOAD_NV_RSP = 56, | ||
162 | |||
163 | WCN36XX_HAL_ADD_BA_SESSION_REQ = 57, | ||
164 | WCN36XX_HAL_ADD_BA_SESSION_RSP = 58, | ||
165 | WCN36XX_HAL_TRIGGER_BA_REQ = 59, | ||
166 | WCN36XX_HAL_TRIGGER_BA_RSP = 60, | ||
167 | WCN36XX_HAL_UPDATE_BEACON_REQ = 61, | ||
168 | WCN36XX_HAL_UPDATE_BEACON_RSP = 62, | ||
169 | WCN36XX_HAL_SEND_BEACON_REQ = 63, | ||
170 | WCN36XX_HAL_SEND_BEACON_RSP = 64, | ||
171 | |||
172 | WCN36XX_HAL_SET_BCASTKEY_REQ = 65, | ||
173 | WCN36XX_HAL_SET_BCASTKEY_RSP = 66, | ||
174 | WCN36XX_HAL_DELETE_STA_CONTEXT_IND = 67, | ||
175 | WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ = 68, | ||
176 | WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP = 69, | ||
177 | |||
178 | /* PTT interface support */ | ||
179 | WCN36XX_HAL_PROCESS_PTT_REQ = 70, | ||
180 | WCN36XX_HAL_PROCESS_PTT_RSP = 71, | ||
181 | |||
182 | /* BTAMP related events */ | ||
183 | WCN36XX_HAL_SIGNAL_BTAMP_EVENT_REQ = 72, | ||
184 | WCN36XX_HAL_SIGNAL_BTAMP_EVENT_RSP = 73, | ||
185 | WCN36XX_HAL_TL_HAL_FLUSH_AC_REQ = 74, | ||
186 | WCN36XX_HAL_TL_HAL_FLUSH_AC_RSP = 75, | ||
187 | |||
188 | WCN36XX_HAL_ENTER_IMPS_REQ = 76, | ||
189 | WCN36XX_HAL_EXIT_IMPS_REQ = 77, | ||
190 | WCN36XX_HAL_ENTER_BMPS_REQ = 78, | ||
191 | WCN36XX_HAL_EXIT_BMPS_REQ = 79, | ||
192 | WCN36XX_HAL_ENTER_UAPSD_REQ = 80, | ||
193 | WCN36XX_HAL_EXIT_UAPSD_REQ = 81, | ||
194 | WCN36XX_HAL_UPDATE_UAPSD_PARAM_REQ = 82, | ||
195 | WCN36XX_HAL_CONFIGURE_RXP_FILTER_REQ = 83, | ||
196 | WCN36XX_HAL_ADD_BCN_FILTER_REQ = 84, | ||
197 | WCN36XX_HAL_REM_BCN_FILTER_REQ = 85, | ||
198 | WCN36XX_HAL_ADD_WOWL_BCAST_PTRN = 86, | ||
199 | WCN36XX_HAL_DEL_WOWL_BCAST_PTRN = 87, | ||
200 | WCN36XX_HAL_ENTER_WOWL_REQ = 88, | ||
201 | WCN36XX_HAL_EXIT_WOWL_REQ = 89, | ||
202 | WCN36XX_HAL_HOST_OFFLOAD_REQ = 90, | ||
203 | WCN36XX_HAL_SET_RSSI_THRESH_REQ = 91, | ||
204 | WCN36XX_HAL_GET_RSSI_REQ = 92, | ||
205 | WCN36XX_HAL_SET_UAPSD_AC_PARAMS_REQ = 93, | ||
206 | WCN36XX_HAL_CONFIGURE_APPS_CPU_WAKEUP_STATE_REQ = 94, | ||
207 | |||
208 | WCN36XX_HAL_ENTER_IMPS_RSP = 95, | ||
209 | WCN36XX_HAL_EXIT_IMPS_RSP = 96, | ||
210 | WCN36XX_HAL_ENTER_BMPS_RSP = 97, | ||
211 | WCN36XX_HAL_EXIT_BMPS_RSP = 98, | ||
212 | WCN36XX_HAL_ENTER_UAPSD_RSP = 99, | ||
213 | WCN36XX_HAL_EXIT_UAPSD_RSP = 100, | ||
214 | WCN36XX_HAL_SET_UAPSD_AC_PARAMS_RSP = 101, | ||
215 | WCN36XX_HAL_UPDATE_UAPSD_PARAM_RSP = 102, | ||
216 | WCN36XX_HAL_CONFIGURE_RXP_FILTER_RSP = 103, | ||
217 | WCN36XX_HAL_ADD_BCN_FILTER_RSP = 104, | ||
218 | WCN36XX_HAL_REM_BCN_FILTER_RSP = 105, | ||
219 | WCN36XX_HAL_SET_RSSI_THRESH_RSP = 106, | ||
220 | WCN36XX_HAL_HOST_OFFLOAD_RSP = 107, | ||
221 | WCN36XX_HAL_ADD_WOWL_BCAST_PTRN_RSP = 108, | ||
222 | WCN36XX_HAL_DEL_WOWL_BCAST_PTRN_RSP = 109, | ||
223 | WCN36XX_HAL_ENTER_WOWL_RSP = 110, | ||
224 | WCN36XX_HAL_EXIT_WOWL_RSP = 111, | ||
225 | WCN36XX_HAL_RSSI_NOTIFICATION_IND = 112, | ||
226 | WCN36XX_HAL_GET_RSSI_RSP = 113, | ||
227 | WCN36XX_HAL_CONFIGURE_APPS_CPU_WAKEUP_STATE_RSP = 114, | ||
228 | |||
229 | /* 11k related events */ | ||
230 | WCN36XX_HAL_SET_MAX_TX_POWER_REQ = 115, | ||
231 | WCN36XX_HAL_SET_MAX_TX_POWER_RSP = 116, | ||
232 | |||
233 | /* 11R related msgs */ | ||
234 | WCN36XX_HAL_AGGR_ADD_TS_REQ = 117, | ||
235 | WCN36XX_HAL_AGGR_ADD_TS_RSP = 118, | ||
236 | |||
237 | /* P2P WLAN_FEATURE_P2P */ | ||
238 | WCN36XX_HAL_SET_P2P_GONOA_REQ = 119, | ||
239 | WCN36XX_HAL_SET_P2P_GONOA_RSP = 120, | ||
240 | |||
241 | /* WLAN Dump commands */ | ||
242 | WCN36XX_HAL_DUMP_COMMAND_REQ = 121, | ||
243 | WCN36XX_HAL_DUMP_COMMAND_RSP = 122, | ||
244 | |||
245 | /* OEM_DATA FEATURE SUPPORT */ | ||
246 | WCN36XX_HAL_START_OEM_DATA_REQ = 123, | ||
247 | WCN36XX_HAL_START_OEM_DATA_RSP = 124, | ||
248 | |||
249 | /* ADD SELF STA REQ and RSP */ | ||
250 | WCN36XX_HAL_ADD_STA_SELF_REQ = 125, | ||
251 | WCN36XX_HAL_ADD_STA_SELF_RSP = 126, | ||
252 | |||
253 | /* DEL SELF STA SUPPORT */ | ||
254 | WCN36XX_HAL_DEL_STA_SELF_REQ = 127, | ||
255 | WCN36XX_HAL_DEL_STA_SELF_RSP = 128, | ||
256 | |||
257 | /* Coex Indication */ | ||
258 | WCN36XX_HAL_COEX_IND = 129, | ||
259 | |||
260 | /* Tx Complete Indication */ | ||
261 | WCN36XX_HAL_OTA_TX_COMPL_IND = 130, | ||
262 | |||
263 | /* Host Suspend/resume messages */ | ||
264 | WCN36XX_HAL_HOST_SUSPEND_IND = 131, | ||
265 | WCN36XX_HAL_HOST_RESUME_REQ = 132, | ||
266 | WCN36XX_HAL_HOST_RESUME_RSP = 133, | ||
267 | |||
268 | WCN36XX_HAL_SET_TX_POWER_REQ = 134, | ||
269 | WCN36XX_HAL_SET_TX_POWER_RSP = 135, | ||
270 | WCN36XX_HAL_GET_TX_POWER_REQ = 136, | ||
271 | WCN36XX_HAL_GET_TX_POWER_RSP = 137, | ||
272 | |||
273 | WCN36XX_HAL_P2P_NOA_ATTR_IND = 138, | ||
274 | |||
275 | WCN36XX_HAL_ENABLE_RADAR_DETECT_REQ = 139, | ||
276 | WCN36XX_HAL_ENABLE_RADAR_DETECT_RSP = 140, | ||
277 | WCN36XX_HAL_GET_TPC_REPORT_REQ = 141, | ||
278 | WCN36XX_HAL_GET_TPC_REPORT_RSP = 142, | ||
279 | WCN36XX_HAL_RADAR_DETECT_IND = 143, | ||
280 | WCN36XX_HAL_RADAR_DETECT_INTR_IND = 144, | ||
281 | WCN36XX_HAL_KEEP_ALIVE_REQ = 145, | ||
282 | WCN36XX_HAL_KEEP_ALIVE_RSP = 146, | ||
283 | |||
284 | /* PNO messages */ | ||
285 | WCN36XX_HAL_SET_PREF_NETWORK_REQ = 147, | ||
286 | WCN36XX_HAL_SET_PREF_NETWORK_RSP = 148, | ||
287 | WCN36XX_HAL_SET_RSSI_FILTER_REQ = 149, | ||
288 | WCN36XX_HAL_SET_RSSI_FILTER_RSP = 150, | ||
289 | WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ = 151, | ||
290 | WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP = 152, | ||
291 | WCN36XX_HAL_PREF_NETW_FOUND_IND = 153, | ||
292 | |||
293 | WCN36XX_HAL_SET_TX_PER_TRACKING_REQ = 154, | ||
294 | WCN36XX_HAL_SET_TX_PER_TRACKING_RSP = 155, | ||
295 | WCN36XX_HAL_TX_PER_HIT_IND = 156, | ||
296 | |||
297 | WCN36XX_HAL_8023_MULTICAST_LIST_REQ = 157, | ||
298 | WCN36XX_HAL_8023_MULTICAST_LIST_RSP = 158, | ||
299 | |||
300 | WCN36XX_HAL_SET_PACKET_FILTER_REQ = 159, | ||
301 | WCN36XX_HAL_SET_PACKET_FILTER_RSP = 160, | ||
302 | WCN36XX_HAL_PACKET_FILTER_MATCH_COUNT_REQ = 161, | ||
303 | WCN36XX_HAL_PACKET_FILTER_MATCH_COUNT_RSP = 162, | ||
304 | WCN36XX_HAL_CLEAR_PACKET_FILTER_REQ = 163, | ||
305 | WCN36XX_HAL_CLEAR_PACKET_FILTER_RSP = 164, | ||
306 | |||
307 | /* | ||
308 | * This is temp fix. Should be removed once Host and Riva code is | ||
309 | * in sync. | ||
310 | */ | ||
311 | WCN36XX_HAL_INIT_SCAN_CON_REQ = 165, | ||
312 | |||
313 | WCN36XX_HAL_SET_POWER_PARAMS_REQ = 166, | ||
314 | WCN36XX_HAL_SET_POWER_PARAMS_RSP = 167, | ||
315 | |||
316 | WCN36XX_HAL_TSM_STATS_REQ = 168, | ||
317 | WCN36XX_HAL_TSM_STATS_RSP = 169, | ||
318 | |||
319 | /* wake reason indication (WOW) */ | ||
320 | WCN36XX_HAL_WAKE_REASON_IND = 170, | ||
321 | |||
322 | /* GTK offload support */ | ||
323 | WCN36XX_HAL_GTK_OFFLOAD_REQ = 171, | ||
324 | WCN36XX_HAL_GTK_OFFLOAD_RSP = 172, | ||
325 | WCN36XX_HAL_GTK_OFFLOAD_GETINFO_REQ = 173, | ||
326 | WCN36XX_HAL_GTK_OFFLOAD_GETINFO_RSP = 174, | ||
327 | |||
328 | WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ = 175, | ||
329 | WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP = 176, | ||
330 | WCN36XX_HAL_EXCLUDE_UNENCRYPTED_IND = 177, | ||
331 | |||
332 | WCN36XX_HAL_SET_THERMAL_MITIGATION_REQ = 178, | ||
333 | WCN36XX_HAL_SET_THERMAL_MITIGATION_RSP = 179, | ||
334 | |||
335 | WCN36XX_HAL_UPDATE_VHT_OP_MODE_REQ = 182, | ||
336 | WCN36XX_HAL_UPDATE_VHT_OP_MODE_RSP = 183, | ||
337 | |||
338 | WCN36XX_HAL_P2P_NOA_START_IND = 184, | ||
339 | |||
340 | WCN36XX_HAL_GET_ROAM_RSSI_REQ = 185, | ||
341 | WCN36XX_HAL_GET_ROAM_RSSI_RSP = 186, | ||
342 | |||
343 | WCN36XX_HAL_CLASS_B_STATS_IND = 187, | ||
344 | WCN36XX_HAL_DEL_BA_IND = 188, | ||
345 | WCN36XX_HAL_DHCP_START_IND = 189, | ||
346 | WCN36XX_HAL_DHCP_STOP_IND = 190, | ||
347 | |||
348 | WCN36XX_HAL_MSG_MAX = WCN36XX_HAL_MSG_TYPE_MAX_ENUM_SIZE | ||
349 | }; | ||
350 | |||
351 | /* Enumeration for Version */ | ||
352 | enum wcn36xx_hal_host_msg_version { | ||
353 | WCN36XX_HAL_MSG_VERSION0 = 0, | ||
354 | WCN36XX_HAL_MSG_VERSION1 = 1, | ||
355 | /* define as 2 bytes data */ | ||
356 | WCN36XX_HAL_MSG_WCNSS_CTRL_VERSION = 0x7FFF, | ||
357 | WCN36XX_HAL_MSG_VERSION_MAX_FIELD = WCN36XX_HAL_MSG_WCNSS_CTRL_VERSION | ||
358 | }; | ||
359 | |||
360 | enum driver_type { | ||
361 | DRIVER_TYPE_PRODUCTION = 0, | ||
362 | DRIVER_TYPE_MFG = 1, | ||
363 | DRIVER_TYPE_DVT = 2, | ||
364 | DRIVER_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
365 | }; | ||
366 | |||
367 | enum wcn36xx_hal_stop_type { | ||
368 | HAL_STOP_TYPE_SYS_RESET, | ||
369 | HAL_STOP_TYPE_SYS_DEEP_SLEEP, | ||
370 | HAL_STOP_TYPE_RF_KILL, | ||
371 | HAL_STOP_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
372 | }; | ||
373 | |||
374 | enum wcn36xx_hal_sys_mode { | ||
375 | HAL_SYS_MODE_NORMAL, | ||
376 | HAL_SYS_MODE_LEARN, | ||
377 | HAL_SYS_MODE_SCAN, | ||
378 | HAL_SYS_MODE_PROMISC, | ||
379 | HAL_SYS_MODE_SUSPEND_LINK, | ||
380 | HAL_SYS_MODE_ROAM_SCAN, | ||
381 | HAL_SYS_MODE_ROAM_SUSPEND_LINK, | ||
382 | HAL_SYS_MODE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
383 | }; | ||
384 | |||
385 | enum phy_chan_bond_state { | ||
386 | /* 20MHz IF bandwidth centered on IF carrier */ | ||
387 | PHY_SINGLE_CHANNEL_CENTERED = 0, | ||
388 | |||
389 | /* 40MHz IF bandwidth with lower 20MHz supporting the primary channel */ | ||
390 | PHY_DOUBLE_CHANNEL_LOW_PRIMARY = 1, | ||
391 | |||
392 | /* 40MHz IF bandwidth centered on IF carrier */ | ||
393 | PHY_DOUBLE_CHANNEL_CENTERED = 2, | ||
394 | |||
395 | /* 40MHz IF bandwidth with higher 20MHz supporting the primary ch */ | ||
396 | PHY_DOUBLE_CHANNEL_HIGH_PRIMARY = 3, | ||
397 | |||
398 | /* 20/40MHZ offset LOW 40/80MHZ offset CENTERED */ | ||
399 | PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED = 4, | ||
400 | |||
401 | /* 20/40MHZ offset CENTERED 40/80MHZ offset CENTERED */ | ||
402 | PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED = 5, | ||
403 | |||
404 | /* 20/40MHZ offset HIGH 40/80MHZ offset CENTERED */ | ||
405 | PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED = 6, | ||
406 | |||
407 | /* 20/40MHZ offset LOW 40/80MHZ offset LOW */ | ||
408 | PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW = 7, | ||
409 | |||
410 | /* 20/40MHZ offset HIGH 40/80MHZ offset LOW */ | ||
411 | PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW = 8, | ||
412 | |||
413 | /* 20/40MHZ offset LOW 40/80MHZ offset HIGH */ | ||
414 | PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH = 9, | ||
415 | |||
416 | /* 20/40MHZ offset-HIGH 40/80MHZ offset HIGH */ | ||
417 | PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH = 10, | ||
418 | |||
419 | PHY_CHANNEL_BONDING_STATE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
420 | }; | ||
421 | |||
422 | /* Spatial Multiplexing(SM) Power Save mode */ | ||
423 | enum wcn36xx_hal_ht_mimo_state { | ||
424 | /* Static SM Power Save mode */ | ||
425 | WCN36XX_HAL_HT_MIMO_PS_STATIC = 0, | ||
426 | |||
427 | /* Dynamic SM Power Save mode */ | ||
428 | WCN36XX_HAL_HT_MIMO_PS_DYNAMIC = 1, | ||
429 | |||
430 | /* reserved */ | ||
431 | WCN36XX_HAL_HT_MIMO_PS_NA = 2, | ||
432 | |||
433 | /* SM Power Save disabled */ | ||
434 | WCN36XX_HAL_HT_MIMO_PS_NO_LIMIT = 3, | ||
435 | |||
436 | WCN36XX_HAL_HT_MIMO_PS_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
437 | }; | ||
438 | |||
439 | /* each station added has a rate mode which specifies the sta attributes */ | ||
440 | enum sta_rate_mode { | ||
441 | STA_TAURUS = 0, | ||
442 | STA_TITAN, | ||
443 | STA_POLARIS, | ||
444 | STA_11b, | ||
445 | STA_11bg, | ||
446 | STA_11a, | ||
447 | STA_11n, | ||
448 | STA_11ac, | ||
449 | STA_INVALID_RATE_MODE = WCN36XX_HAL_MAX_ENUM_SIZE | ||
450 | }; | ||
451 | |||
452 | /* 1,2,5.5,11 */ | ||
453 | #define WCN36XX_HAL_NUM_DSSS_RATES 4 | ||
454 | |||
455 | /* 6,9,12,18,24,36,48,54 */ | ||
456 | #define WCN36XX_HAL_NUM_OFDM_RATES 8 | ||
457 | |||
458 | /* 72,96,108 */ | ||
459 | #define WCN36XX_HAL_NUM_POLARIS_RATES 3 | ||
460 | |||
461 | #define WCN36XX_HAL_MAC_MAX_SUPPORTED_MCS_SET 16 | ||
462 | |||
463 | enum wcn36xx_hal_bss_type { | ||
464 | WCN36XX_HAL_INFRASTRUCTURE_MODE, | ||
465 | |||
466 | /* Added for softAP support */ | ||
467 | WCN36XX_HAL_INFRA_AP_MODE, | ||
468 | |||
469 | WCN36XX_HAL_IBSS_MODE, | ||
470 | |||
471 | /* Added for BT-AMP support */ | ||
472 | WCN36XX_HAL_BTAMP_STA_MODE, | ||
473 | |||
474 | /* Added for BT-AMP support */ | ||
475 | WCN36XX_HAL_BTAMP_AP_MODE, | ||
476 | |||
477 | WCN36XX_HAL_AUTO_MODE, | ||
478 | |||
479 | WCN36XX_HAL_DONOT_USE_BSS_TYPE = WCN36XX_HAL_MAX_ENUM_SIZE | ||
480 | }; | ||
481 | |||
482 | enum wcn36xx_hal_nw_type { | ||
483 | WCN36XX_HAL_11A_NW_TYPE, | ||
484 | WCN36XX_HAL_11B_NW_TYPE, | ||
485 | WCN36XX_HAL_11G_NW_TYPE, | ||
486 | WCN36XX_HAL_11N_NW_TYPE, | ||
487 | WCN36XX_HAL_DONOT_USE_NW_TYPE = WCN36XX_HAL_MAX_ENUM_SIZE | ||
488 | }; | ||
489 | |||
490 | #define WCN36XX_HAL_MAC_RATESET_EID_MAX 12 | ||
491 | |||
492 | enum wcn36xx_hal_ht_operating_mode { | ||
493 | /* No Protection */ | ||
494 | WCN36XX_HAL_HT_OP_MODE_PURE, | ||
495 | |||
496 | /* Overlap Legacy device present, protection is optional */ | ||
497 | WCN36XX_HAL_HT_OP_MODE_OVERLAP_LEGACY, | ||
498 | |||
499 | /* No legacy device, but 20 MHz HT present */ | ||
500 | WCN36XX_HAL_HT_OP_MODE_NO_LEGACY_20MHZ_HT, | ||
501 | |||
502 | /* Protection is required */ | ||
503 | WCN36XX_HAL_HT_OP_MODE_MIXED, | ||
504 | |||
505 | WCN36XX_HAL_HT_OP_MODE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
506 | }; | ||
507 | |||
508 | /* Encryption type enum used with peer */ | ||
509 | enum ani_ed_type { | ||
510 | WCN36XX_HAL_ED_NONE, | ||
511 | WCN36XX_HAL_ED_WEP40, | ||
512 | WCN36XX_HAL_ED_WEP104, | ||
513 | WCN36XX_HAL_ED_TKIP, | ||
514 | WCN36XX_HAL_ED_CCMP, | ||
515 | WCN36XX_HAL_ED_WPI, | ||
516 | WCN36XX_HAL_ED_AES_128_CMAC, | ||
517 | WCN36XX_HAL_ED_NOT_IMPLEMENTED = WCN36XX_HAL_MAX_ENUM_SIZE | ||
518 | }; | ||
519 | |||
520 | #define WLAN_MAX_KEY_RSC_LEN 16 | ||
521 | #define WLAN_WAPI_KEY_RSC_LEN 16 | ||
522 | |||
523 | /* MAX key length when ULA is used */ | ||
524 | #define WCN36XX_HAL_MAC_MAX_KEY_LENGTH 32 | ||
525 | #define WCN36XX_HAL_MAC_MAX_NUM_OF_DEFAULT_KEYS 4 | ||
526 | |||
527 | /* | ||
528 | * Enum to specify whether key is used for TX only, RX only or both. | ||
529 | */ | ||
530 | enum ani_key_direction { | ||
531 | WCN36XX_HAL_TX_ONLY, | ||
532 | WCN36XX_HAL_RX_ONLY, | ||
533 | WCN36XX_HAL_TX_RX, | ||
534 | WCN36XX_HAL_TX_DEFAULT, | ||
535 | WCN36XX_HAL_DONOT_USE_KEY_DIRECTION = WCN36XX_HAL_MAX_ENUM_SIZE | ||
536 | }; | ||
537 | |||
538 | enum ani_wep_type { | ||
539 | WCN36XX_HAL_WEP_STATIC, | ||
540 | WCN36XX_HAL_WEP_DYNAMIC, | ||
541 | WCN36XX_HAL_WEP_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
542 | }; | ||
543 | |||
544 | enum wcn36xx_hal_link_state { | ||
545 | |||
546 | WCN36XX_HAL_LINK_IDLE_STATE = 0, | ||
547 | WCN36XX_HAL_LINK_PREASSOC_STATE = 1, | ||
548 | WCN36XX_HAL_LINK_POSTASSOC_STATE = 2, | ||
549 | WCN36XX_HAL_LINK_AP_STATE = 3, | ||
550 | WCN36XX_HAL_LINK_IBSS_STATE = 4, | ||
551 | |||
552 | /* BT-AMP Case */ | ||
553 | WCN36XX_HAL_LINK_BTAMP_PREASSOC_STATE = 5, | ||
554 | WCN36XX_HAL_LINK_BTAMP_POSTASSOC_STATE = 6, | ||
555 | WCN36XX_HAL_LINK_BTAMP_AP_STATE = 7, | ||
556 | WCN36XX_HAL_LINK_BTAMP_STA_STATE = 8, | ||
557 | |||
558 | /* Reserved for HAL Internal Use */ | ||
559 | WCN36XX_HAL_LINK_LEARN_STATE = 9, | ||
560 | WCN36XX_HAL_LINK_SCAN_STATE = 10, | ||
561 | WCN36XX_HAL_LINK_FINISH_SCAN_STATE = 11, | ||
562 | WCN36XX_HAL_LINK_INIT_CAL_STATE = 12, | ||
563 | WCN36XX_HAL_LINK_FINISH_CAL_STATE = 13, | ||
564 | WCN36XX_HAL_LINK_LISTEN_STATE = 14, | ||
565 | |||
566 | WCN36XX_HAL_LINK_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
567 | }; | ||
568 | |||
569 | enum wcn36xx_hal_stats_mask { | ||
570 | HAL_SUMMARY_STATS_INFO = 0x00000001, | ||
571 | HAL_GLOBAL_CLASS_A_STATS_INFO = 0x00000002, | ||
572 | HAL_GLOBAL_CLASS_B_STATS_INFO = 0x00000004, | ||
573 | HAL_GLOBAL_CLASS_C_STATS_INFO = 0x00000008, | ||
574 | HAL_GLOBAL_CLASS_D_STATS_INFO = 0x00000010, | ||
575 | HAL_PER_STA_STATS_INFO = 0x00000020 | ||
576 | }; | ||
577 | |||
578 | /* BT-AMP events type */ | ||
579 | enum bt_amp_event_type { | ||
580 | BTAMP_EVENT_CONNECTION_START, | ||
581 | BTAMP_EVENT_CONNECTION_STOP, | ||
582 | BTAMP_EVENT_CONNECTION_TERMINATED, | ||
583 | |||
584 | /* This and beyond are invalid values */ | ||
585 | BTAMP_EVENT_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE, | ||
586 | }; | ||
587 | |||
588 | /* PE Statistics */ | ||
589 | enum pe_stats_mask { | ||
590 | PE_SUMMARY_STATS_INFO = 0x00000001, | ||
591 | PE_GLOBAL_CLASS_A_STATS_INFO = 0x00000002, | ||
592 | PE_GLOBAL_CLASS_B_STATS_INFO = 0x00000004, | ||
593 | PE_GLOBAL_CLASS_C_STATS_INFO = 0x00000008, | ||
594 | PE_GLOBAL_CLASS_D_STATS_INFO = 0x00000010, | ||
595 | PE_PER_STA_STATS_INFO = 0x00000020, | ||
596 | |||
597 | /* This and beyond are invalid values */ | ||
598 | PE_STATS_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
599 | }; | ||
600 | |||
601 | /* | ||
602 | * Configuration Parameter IDs | ||
603 | */ | ||
604 | #define WCN36XX_HAL_CFG_STA_ID 0 | ||
605 | #define WCN36XX_HAL_CFG_CURRENT_TX_ANTENNA 1 | ||
606 | #define WCN36XX_HAL_CFG_CURRENT_RX_ANTENNA 2 | ||
607 | #define WCN36XX_HAL_CFG_LOW_GAIN_OVERRIDE 3 | ||
608 | #define WCN36XX_HAL_CFG_POWER_STATE_PER_CHAIN 4 | ||
609 | #define WCN36XX_HAL_CFG_CAL_PERIOD 5 | ||
610 | #define WCN36XX_HAL_CFG_CAL_CONTROL 6 | ||
611 | #define WCN36XX_HAL_CFG_PROXIMITY 7 | ||
612 | #define WCN36XX_HAL_CFG_NETWORK_DENSITY 8 | ||
613 | #define WCN36XX_HAL_CFG_MAX_MEDIUM_TIME 9 | ||
614 | #define WCN36XX_HAL_CFG_MAX_MPDUS_IN_AMPDU 10 | ||
615 | #define WCN36XX_HAL_CFG_RTS_THRESHOLD 11 | ||
616 | #define WCN36XX_HAL_CFG_SHORT_RETRY_LIMIT 12 | ||
617 | #define WCN36XX_HAL_CFG_LONG_RETRY_LIMIT 13 | ||
618 | #define WCN36XX_HAL_CFG_FRAGMENTATION_THRESHOLD 14 | ||
619 | #define WCN36XX_HAL_CFG_DYNAMIC_THRESHOLD_ZERO 15 | ||
620 | #define WCN36XX_HAL_CFG_DYNAMIC_THRESHOLD_ONE 16 | ||
621 | #define WCN36XX_HAL_CFG_DYNAMIC_THRESHOLD_TWO 17 | ||
622 | #define WCN36XX_HAL_CFG_FIXED_RATE 18 | ||
623 | #define WCN36XX_HAL_CFG_RETRYRATE_POLICY 19 | ||
624 | #define WCN36XX_HAL_CFG_RETRYRATE_SECONDARY 20 | ||
625 | #define WCN36XX_HAL_CFG_RETRYRATE_TERTIARY 21 | ||
626 | #define WCN36XX_HAL_CFG_FORCE_POLICY_PROTECTION 22 | ||
627 | #define WCN36XX_HAL_CFG_FIXED_RATE_MULTICAST_24GHZ 23 | ||
628 | #define WCN36XX_HAL_CFG_FIXED_RATE_MULTICAST_5GHZ 24 | ||
629 | #define WCN36XX_HAL_CFG_DEFAULT_RATE_INDEX_24GHZ 25 | ||
630 | #define WCN36XX_HAL_CFG_DEFAULT_RATE_INDEX_5GHZ 26 | ||
631 | #define WCN36XX_HAL_CFG_MAX_BA_SESSIONS 27 | ||
632 | #define WCN36XX_HAL_CFG_PS_DATA_INACTIVITY_TIMEOUT 28 | ||
633 | #define WCN36XX_HAL_CFG_PS_ENABLE_BCN_FILTER 29 | ||
634 | #define WCN36XX_HAL_CFG_PS_ENABLE_RSSI_MONITOR 30 | ||
635 | #define WCN36XX_HAL_CFG_NUM_BEACON_PER_RSSI_AVERAGE 31 | ||
636 | #define WCN36XX_HAL_CFG_STATS_PERIOD 32 | ||
637 | #define WCN36XX_HAL_CFG_CFP_MAX_DURATION 33 | ||
638 | #define WCN36XX_HAL_CFG_FRAME_TRANS_ENABLED 34 | ||
639 | #define WCN36XX_HAL_CFG_DTIM_PERIOD 35 | ||
640 | #define WCN36XX_HAL_CFG_EDCA_WMM_ACBK 36 | ||
641 | #define WCN36XX_HAL_CFG_EDCA_WMM_ACBE 37 | ||
642 | #define WCN36XX_HAL_CFG_EDCA_WMM_ACVO 38 | ||
643 | #define WCN36XX_HAL_CFG_EDCA_WMM_ACVI 39 | ||
644 | #define WCN36XX_HAL_CFG_BA_THRESHOLD_HIGH 40 | ||
645 | #define WCN36XX_HAL_CFG_MAX_BA_BUFFERS 41 | ||
646 | #define WCN36XX_HAL_CFG_RPE_POLLING_THRESHOLD 42 | ||
647 | #define WCN36XX_HAL_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG 43 | ||
648 | #define WCN36XX_HAL_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG 44 | ||
649 | #define WCN36XX_HAL_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG 45 | ||
650 | #define WCN36XX_HAL_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG 46 | ||
651 | #define WCN36XX_HAL_CFG_NO_OF_ONCHIP_REORDER_SESSIONS 47 | ||
652 | #define WCN36XX_HAL_CFG_PS_LISTEN_INTERVAL 48 | ||
653 | #define WCN36XX_HAL_CFG_PS_HEART_BEAT_THRESHOLD 49 | ||
654 | #define WCN36XX_HAL_CFG_PS_NTH_BEACON_FILTER 50 | ||
655 | #define WCN36XX_HAL_CFG_PS_MAX_PS_POLL 51 | ||
656 | #define WCN36XX_HAL_CFG_PS_MIN_RSSI_THRESHOLD 52 | ||
657 | #define WCN36XX_HAL_CFG_PS_RSSI_FILTER_PERIOD 53 | ||
658 | #define WCN36XX_HAL_CFG_PS_BROADCAST_FRAME_FILTER_ENABLE 54 | ||
659 | #define WCN36XX_HAL_CFG_PS_IGNORE_DTIM 55 | ||
660 | #define WCN36XX_HAL_CFG_PS_ENABLE_BCN_EARLY_TERM 56 | ||
661 | #define WCN36XX_HAL_CFG_DYNAMIC_PS_POLL_VALUE 57 | ||
662 | #define WCN36XX_HAL_CFG_PS_NULLDATA_AP_RESP_TIMEOUT 58 | ||
663 | #define WCN36XX_HAL_CFG_TELE_BCN_WAKEUP_EN 59 | ||
664 | #define WCN36XX_HAL_CFG_TELE_BCN_TRANS_LI 60 | ||
665 | #define WCN36XX_HAL_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS 61 | ||
666 | #define WCN36XX_HAL_CFG_TELE_BCN_MAX_LI 62 | ||
667 | #define WCN36XX_HAL_CFG_TELE_BCN_MAX_LI_IDLE_BCNS 63 | ||
668 | #define WCN36XX_HAL_CFG_TX_PWR_CTRL_ENABLE 64 | ||
669 | #define WCN36XX_HAL_CFG_VALID_RADAR_CHANNEL_LIST 65 | ||
670 | #define WCN36XX_HAL_CFG_TX_POWER_24_20 66 | ||
671 | #define WCN36XX_HAL_CFG_TX_POWER_24_40 67 | ||
672 | #define WCN36XX_HAL_CFG_TX_POWER_50_20 68 | ||
673 | #define WCN36XX_HAL_CFG_TX_POWER_50_40 69 | ||
674 | #define WCN36XX_HAL_CFG_MCAST_BCAST_FILTER_SETTING 70 | ||
675 | #define WCN36XX_HAL_CFG_BCN_EARLY_TERM_WAKEUP_INTERVAL 71 | ||
676 | #define WCN36XX_HAL_CFG_MAX_TX_POWER_2_4 72 | ||
677 | #define WCN36XX_HAL_CFG_MAX_TX_POWER_5 73 | ||
678 | #define WCN36XX_HAL_CFG_INFRA_STA_KEEP_ALIVE_PERIOD 74 | ||
679 | #define WCN36XX_HAL_CFG_ENABLE_CLOSE_LOOP 75 | ||
680 | #define WCN36XX_HAL_CFG_BTC_EXECUTION_MODE 76 | ||
681 | #define WCN36XX_HAL_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK 77 | ||
682 | #define WCN36XX_HAL_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS 78 | ||
683 | #define WCN36XX_HAL_CFG_PS_TX_INACTIVITY_TIMEOUT 79 | ||
684 | #define WCN36XX_HAL_CFG_WCNSS_API_VERSION 80 | ||
685 | #define WCN36XX_HAL_CFG_AP_KEEPALIVE_TIMEOUT 81 | ||
686 | #define WCN36XX_HAL_CFG_GO_KEEPALIVE_TIMEOUT 82 | ||
687 | #define WCN36XX_HAL_CFG_ENABLE_MC_ADDR_LIST 83 | ||
688 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_INQ_BT 84 | ||
689 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_PAGE_BT 85 | ||
690 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_CONN_BT 86 | ||
691 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_LE_BT 87 | ||
692 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_INQ_WLAN 88 | ||
693 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_PAGE_WLAN 89 | ||
694 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_CONN_WLAN 90 | ||
695 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_LE_WLAN 91 | ||
696 | #define WCN36XX_HAL_CFG_BTC_DYN_MAX_LEN_BT 92 | ||
697 | #define WCN36XX_HAL_CFG_BTC_DYN_MAX_LEN_WLAN 93 | ||
698 | #define WCN36XX_HAL_CFG_BTC_MAX_SCO_BLOCK_PERC 94 | ||
699 | #define WCN36XX_HAL_CFG_BTC_DHCP_PROT_ON_A2DP 95 | ||
700 | #define WCN36XX_HAL_CFG_BTC_DHCP_PROT_ON_SCO 96 | ||
701 | #define WCN36XX_HAL_CFG_ENABLE_UNICAST_FILTER 97 | ||
702 | #define WCN36XX_HAL_CFG_MAX_ASSOC_LIMIT 98 | ||
703 | #define WCN36XX_HAL_CFG_ENABLE_LPWR_IMG_TRANSITION 99 | ||
704 | #define WCN36XX_HAL_CFG_ENABLE_MCC_ADAPTIVE_SCHEDULER 100 | ||
705 | #define WCN36XX_HAL_CFG_ENABLE_DETECT_PS_SUPPORT 101 | ||
706 | #define WCN36XX_HAL_CFG_AP_LINK_MONITOR_TIMEOUT 102 | ||
707 | #define WCN36XX_HAL_CFG_BTC_DWELL_TIME_MULTIPLIER 103 | ||
708 | #define WCN36XX_HAL_CFG_ENABLE_TDLS_OXYGEN_MODE 104 | ||
709 | #define WCN36XX_HAL_CFG_MAX_PARAMS 105 | ||
710 | |||
711 | /* Message definitons - All the messages below need to be packed */ | ||
712 | |||
713 | /* Definition for HAL API Version. */ | ||
714 | struct wcnss_wlan_version { | ||
715 | u8 revision; | ||
716 | u8 version; | ||
717 | u8 minor; | ||
718 | u8 major; | ||
719 | } __packed; | ||
720 | |||
721 | /* Definition for Encryption Keys */ | ||
722 | struct wcn36xx_hal_keys { | ||
723 | u8 id; | ||
724 | |||
725 | /* 0 for multicast */ | ||
726 | u8 unicast; | ||
727 | |||
728 | enum ani_key_direction direction; | ||
729 | |||
730 | /* Usage is unknown */ | ||
731 | u8 rsc[WLAN_MAX_KEY_RSC_LEN]; | ||
732 | |||
733 | /* =1 for authenticator,=0 for supplicant */ | ||
734 | u8 pae_role; | ||
735 | |||
736 | u16 length; | ||
737 | u8 key[WCN36XX_HAL_MAC_MAX_KEY_LENGTH]; | ||
738 | } __packed; | ||
739 | |||
740 | /* | ||
741 | * set_sta_key_params Moving here since it is shared by | ||
742 | * configbss/setstakey msgs | ||
743 | */ | ||
744 | struct wcn36xx_hal_set_sta_key_params { | ||
745 | /* STA Index */ | ||
746 | u16 sta_index; | ||
747 | |||
748 | /* Encryption Type used with peer */ | ||
749 | enum ani_ed_type enc_type; | ||
750 | |||
751 | /* STATIC/DYNAMIC - valid only for WEP */ | ||
752 | enum ani_wep_type wep_type; | ||
753 | |||
754 | /* Default WEP key, valid only for static WEP, must between 0 and 3. */ | ||
755 | u8 def_wep_idx; | ||
756 | |||
757 | /* valid only for non-static WEP encyrptions */ | ||
758 | struct wcn36xx_hal_keys key[WCN36XX_HAL_MAC_MAX_NUM_OF_DEFAULT_KEYS]; | ||
759 | |||
760 | /* | ||
761 | * Control for Replay Count, 1= Single TID based replay count on Tx | ||
762 | * 0 = Per TID based replay count on TX | ||
763 | */ | ||
764 | u8 single_tid_rc; | ||
765 | |||
766 | } __packed; | ||
767 | |||
768 | /* 4-byte control message header used by HAL*/ | ||
769 | struct wcn36xx_hal_msg_header { | ||
770 | enum wcn36xx_hal_host_msg_type msg_type:16; | ||
771 | enum wcn36xx_hal_host_msg_version msg_version:16; | ||
772 | u32 len; | ||
773 | } __packed; | ||
774 | |||
775 | /* Config format required by HAL for each CFG item*/ | ||
776 | struct wcn36xx_hal_cfg { | ||
777 | /* Cfg Id. The Id required by HAL is exported by HAL | ||
778 | * in shared header file between UMAC and HAL.*/ | ||
779 | u16 id; | ||
780 | |||
781 | /* Length of the Cfg. This parameter is used to go to next cfg | ||
782 | * in the TLV format.*/ | ||
783 | u16 len; | ||
784 | |||
785 | /* Padding bytes for unaligned address's */ | ||
786 | u16 pad_bytes; | ||
787 | |||
788 | /* Reserve bytes for making cfgVal to align address */ | ||
789 | u16 reserve; | ||
790 | |||
791 | /* Following the uCfgLen field there should be a 'uCfgLen' bytes | ||
792 | * containing the uCfgValue ; u8 uCfgValue[uCfgLen] */ | ||
793 | } __packed; | ||
794 | |||
795 | struct wcn36xx_hal_mac_start_parameters { | ||
796 | /* Drive Type - Production or FTM etc */ | ||
797 | enum driver_type type; | ||
798 | |||
799 | /* Length of the config buffer */ | ||
800 | u32 len; | ||
801 | |||
802 | /* Following this there is a TLV formatted buffer of length | ||
803 | * "len" bytes containing all config values. | ||
804 | * The TLV is expected to be formatted like this: | ||
805 | * 0 15 31 31+CFG_LEN-1 length-1 | ||
806 | * | CFG_ID | CFG_LEN | CFG_BODY | CFG_ID |......| | ||
807 | */ | ||
808 | } __packed; | ||
809 | |||
810 | struct wcn36xx_hal_mac_start_req_msg { | ||
811 | /* config buffer must start in TLV format just here */ | ||
812 | struct wcn36xx_hal_msg_header header; | ||
813 | struct wcn36xx_hal_mac_start_parameters params; | ||
814 | } __packed; | ||
815 | |||
816 | struct wcn36xx_hal_mac_start_rsp_params { | ||
817 | /* success or failure */ | ||
818 | u16 status; | ||
819 | |||
820 | /* Max number of STA supported by the device */ | ||
821 | u8 stations; | ||
822 | |||
823 | /* Max number of BSS supported by the device */ | ||
824 | u8 bssids; | ||
825 | |||
826 | /* API Version */ | ||
827 | struct wcnss_wlan_version version; | ||
828 | |||
829 | /* CRM build information */ | ||
830 | u8 crm_version[WCN36XX_HAL_VERSION_LENGTH]; | ||
831 | |||
832 | /* hardware/chipset/misc version information */ | ||
833 | u8 wlan_version[WCN36XX_HAL_VERSION_LENGTH]; | ||
834 | |||
835 | } __packed; | ||
836 | |||
837 | struct wcn36xx_hal_mac_start_rsp_msg { | ||
838 | struct wcn36xx_hal_msg_header header; | ||
839 | struct wcn36xx_hal_mac_start_rsp_params start_rsp_params; | ||
840 | } __packed; | ||
841 | |||
842 | struct wcn36xx_hal_mac_stop_req_params { | ||
843 | /* The reason for which the device is being stopped */ | ||
844 | enum wcn36xx_hal_stop_type reason; | ||
845 | |||
846 | } __packed; | ||
847 | |||
848 | struct wcn36xx_hal_mac_stop_req_msg { | ||
849 | struct wcn36xx_hal_msg_header header; | ||
850 | struct wcn36xx_hal_mac_stop_req_params stop_req_params; | ||
851 | } __packed; | ||
852 | |||
853 | struct wcn36xx_hal_mac_stop_rsp_msg { | ||
854 | struct wcn36xx_hal_msg_header header; | ||
855 | |||
856 | /* success or failure */ | ||
857 | u32 status; | ||
858 | } __packed; | ||
859 | |||
860 | struct wcn36xx_hal_update_cfg_req_msg { | ||
861 | /* | ||
862 | * Note: The length specified in tHalUpdateCfgReqMsg messages should be | ||
863 | * header.msgLen = sizeof(tHalUpdateCfgReqMsg) + uConfigBufferLen | ||
864 | */ | ||
865 | struct wcn36xx_hal_msg_header header; | ||
866 | |||
867 | /* Length of the config buffer. Allows UMAC to update multiple CFGs */ | ||
868 | u32 len; | ||
869 | |||
870 | /* | ||
871 | * Following this there is a TLV formatted buffer of length | ||
872 | * "uConfigBufferLen" bytes containing all config values. | ||
873 | * The TLV is expected to be formatted like this: | ||
874 | * 0 15 31 31+CFG_LEN-1 length-1 | ||
875 | * | CFG_ID | CFG_LEN | CFG_BODY | CFG_ID |......| | ||
876 | */ | ||
877 | |||
878 | } __packed; | ||
879 | |||
880 | struct wcn36xx_hal_update_cfg_rsp_msg { | ||
881 | struct wcn36xx_hal_msg_header header; | ||
882 | |||
883 | /* success or failure */ | ||
884 | u32 status; | ||
885 | |||
886 | } __packed; | ||
887 | |||
888 | /* Frame control field format (2 bytes) */ | ||
889 | struct wcn36xx_hal_mac_frame_ctl { | ||
890 | |||
891 | #ifndef ANI_LITTLE_BIT_ENDIAN | ||
892 | |||
893 | u8 subType:4; | ||
894 | u8 type:2; | ||
895 | u8 protVer:2; | ||
896 | |||
897 | u8 order:1; | ||
898 | u8 wep:1; | ||
899 | u8 moreData:1; | ||
900 | u8 powerMgmt:1; | ||
901 | u8 retry:1; | ||
902 | u8 moreFrag:1; | ||
903 | u8 fromDS:1; | ||
904 | u8 toDS:1; | ||
905 | |||
906 | #else | ||
907 | |||
908 | u8 protVer:2; | ||
909 | u8 type:2; | ||
910 | u8 subType:4; | ||
911 | |||
912 | u8 toDS:1; | ||
913 | u8 fromDS:1; | ||
914 | u8 moreFrag:1; | ||
915 | u8 retry:1; | ||
916 | u8 powerMgmt:1; | ||
917 | u8 moreData:1; | ||
918 | u8 wep:1; | ||
919 | u8 order:1; | ||
920 | |||
921 | #endif | ||
922 | |||
923 | }; | ||
924 | |||
925 | /* Sequence control field */ | ||
926 | struct wcn36xx_hal_mac_seq_ctl { | ||
927 | u8 fragNum:4; | ||
928 | u8 seqNumLo:4; | ||
929 | u8 seqNumHi:8; | ||
930 | }; | ||
931 | |||
932 | /* Management header format */ | ||
933 | struct wcn36xx_hal_mac_mgmt_hdr { | ||
934 | struct wcn36xx_hal_mac_frame_ctl fc; | ||
935 | u8 durationLo; | ||
936 | u8 durationHi; | ||
937 | u8 da[6]; | ||
938 | u8 sa[6]; | ||
939 | u8 bssId[6]; | ||
940 | struct wcn36xx_hal_mac_seq_ctl seqControl; | ||
941 | }; | ||
942 | |||
943 | /* FIXME: pronto v1 apparently has 4 */ | ||
944 | #define WCN36XX_HAL_NUM_BSSID 2 | ||
945 | |||
946 | /* Scan Entry to hold active BSS idx's */ | ||
947 | struct wcn36xx_hal_scan_entry { | ||
948 | u8 bss_index[WCN36XX_HAL_NUM_BSSID]; | ||
949 | u8 active_bss_count; | ||
950 | }; | ||
951 | |||
952 | struct wcn36xx_hal_init_scan_req_msg { | ||
953 | struct wcn36xx_hal_msg_header header; | ||
954 | |||
955 | /* LEARN - AP Role | ||
956 | SCAN - STA Role */ | ||
957 | enum wcn36xx_hal_sys_mode mode; | ||
958 | |||
959 | /* BSSID of the BSS */ | ||
960 | u8 bssid[ETH_ALEN]; | ||
961 | |||
962 | /* Whether BSS needs to be notified */ | ||
963 | u8 notify; | ||
964 | |||
965 | /* Kind of frame to be used for notifying the BSS (Data Null, QoS | ||
966 | * Null, or CTS to Self). Must always be a valid frame type. */ | ||
967 | u8 frame_type; | ||
968 | |||
969 | /* UMAC has the option of passing the MAC frame to be used for | ||
970 | * notifying the BSS. If non-zero, HAL will use the MAC frame | ||
971 | * buffer pointed to by macMgmtHdr. If zero, HAL will generate the | ||
972 | * appropriate MAC frame based on frameType. */ | ||
973 | u8 frame_len; | ||
974 | |||
975 | /* Following the framelength there is a MAC frame buffer if | ||
976 | * frameLength is non-zero. */ | ||
977 | struct wcn36xx_hal_mac_mgmt_hdr mac_mgmt_hdr; | ||
978 | |||
979 | /* Entry to hold number of active BSS idx's */ | ||
980 | struct wcn36xx_hal_scan_entry scan_entry; | ||
981 | }; | ||
982 | |||
983 | struct wcn36xx_hal_init_scan_con_req_msg { | ||
984 | struct wcn36xx_hal_msg_header header; | ||
985 | |||
986 | /* LEARN - AP Role | ||
987 | SCAN - STA Role */ | ||
988 | enum wcn36xx_hal_sys_mode mode; | ||
989 | |||
990 | /* BSSID of the BSS */ | ||
991 | u8 bssid[ETH_ALEN]; | ||
992 | |||
993 | /* Whether BSS needs to be notified */ | ||
994 | u8 notify; | ||
995 | |||
996 | /* Kind of frame to be used for notifying the BSS (Data Null, QoS | ||
997 | * Null, or CTS to Self). Must always be a valid frame type. */ | ||
998 | u8 frame_type; | ||
999 | |||
1000 | /* UMAC has the option of passing the MAC frame to be used for | ||
1001 | * notifying the BSS. If non-zero, HAL will use the MAC frame | ||
1002 | * buffer pointed to by macMgmtHdr. If zero, HAL will generate the | ||
1003 | * appropriate MAC frame based on frameType. */ | ||
1004 | u8 frame_length; | ||
1005 | |||
1006 | /* Following the framelength there is a MAC frame buffer if | ||
1007 | * frameLength is non-zero. */ | ||
1008 | struct wcn36xx_hal_mac_mgmt_hdr mac_mgmt_hdr; | ||
1009 | |||
1010 | /* Entry to hold number of active BSS idx's */ | ||
1011 | struct wcn36xx_hal_scan_entry scan_entry; | ||
1012 | |||
1013 | /* Single NoA usage in Scanning */ | ||
1014 | u8 use_noa; | ||
1015 | |||
1016 | /* Indicates the scan duration (in ms) */ | ||
1017 | u16 scan_duration; | ||
1018 | |||
1019 | }; | ||
1020 | |||
1021 | struct wcn36xx_hal_init_scan_rsp_msg { | ||
1022 | struct wcn36xx_hal_msg_header header; | ||
1023 | |||
1024 | /* success or failure */ | ||
1025 | u32 status; | ||
1026 | |||
1027 | } __packed; | ||
1028 | |||
1029 | struct wcn36xx_hal_start_scan_req_msg { | ||
1030 | struct wcn36xx_hal_msg_header header; | ||
1031 | |||
1032 | /* Indicates the channel to scan */ | ||
1033 | u8 scan_channel; | ||
1034 | } __packed; | ||
1035 | |||
1036 | struct wcn36xx_hal_start_rsp_msg { | ||
1037 | struct wcn36xx_hal_msg_header header; | ||
1038 | |||
1039 | /* success or failure */ | ||
1040 | u32 status; | ||
1041 | |||
1042 | u32 start_tsf[2]; | ||
1043 | u8 tx_mgmt_power; | ||
1044 | |||
1045 | } __packed; | ||
1046 | |||
1047 | struct wcn36xx_hal_end_scan_req_msg { | ||
1048 | struct wcn36xx_hal_msg_header header; | ||
1049 | |||
1050 | /* Indicates the channel to stop scanning. Not used really. But | ||
1051 | * retained for symmetry with "start Scan" message. It can also | ||
1052 | * help in error check if needed. */ | ||
1053 | u8 scan_channel; | ||
1054 | } __packed; | ||
1055 | |||
1056 | struct wcn36xx_hal_end_scan_rsp_msg { | ||
1057 | struct wcn36xx_hal_msg_header header; | ||
1058 | |||
1059 | /* success or failure */ | ||
1060 | u32 status; | ||
1061 | } __packed; | ||
1062 | |||
1063 | struct wcn36xx_hal_finish_scan_req_msg { | ||
1064 | struct wcn36xx_hal_msg_header header; | ||
1065 | |||
1066 | /* Identifies the operational state of the AP/STA | ||
1067 | * LEARN - AP Role SCAN - STA Role */ | ||
1068 | enum wcn36xx_hal_sys_mode mode; | ||
1069 | |||
1070 | /* Operating channel to tune to. */ | ||
1071 | u8 oper_channel; | ||
1072 | |||
1073 | /* Channel Bonding state If 20/40 MHz is operational, this will | ||
1074 | * indicate the 40 MHz extension channel in combination with the | ||
1075 | * control channel */ | ||
1076 | enum phy_chan_bond_state cb_state; | ||
1077 | |||
1078 | /* BSSID of the BSS */ | ||
1079 | u8 bssid[ETH_ALEN]; | ||
1080 | |||
1081 | /* Whether BSS needs to be notified */ | ||
1082 | u8 notify; | ||
1083 | |||
1084 | /* Kind of frame to be used for notifying the BSS (Data Null, QoS | ||
1085 | * Null, or CTS to Self). Must always be a valid frame type. */ | ||
1086 | u8 frame_type; | ||
1087 | |||
1088 | /* UMAC has the option of passing the MAC frame to be used for | ||
1089 | * notifying the BSS. If non-zero, HAL will use the MAC frame | ||
1090 | * buffer pointed to by macMgmtHdr. If zero, HAL will generate the | ||
1091 | * appropriate MAC frame based on frameType. */ | ||
1092 | u8 frame_length; | ||
1093 | |||
1094 | /* Following the framelength there is a MAC frame buffer if | ||
1095 | * frameLength is non-zero. */ | ||
1096 | struct wcn36xx_hal_mac_mgmt_hdr mac_mgmt_hdr; | ||
1097 | |||
1098 | /* Entry to hold number of active BSS idx's */ | ||
1099 | struct wcn36xx_hal_scan_entry scan_entry; | ||
1100 | |||
1101 | } __packed; | ||
1102 | |||
1103 | struct wcn36xx_hal_finish_scan_rsp_msg { | ||
1104 | struct wcn36xx_hal_msg_header header; | ||
1105 | |||
1106 | /* success or failure */ | ||
1107 | u32 status; | ||
1108 | |||
1109 | } __packed; | ||
1110 | |||
1111 | enum wcn36xx_hal_rate_index { | ||
1112 | HW_RATE_INDEX_1MBPS = 0x82, | ||
1113 | HW_RATE_INDEX_2MBPS = 0x84, | ||
1114 | HW_RATE_INDEX_5_5MBPS = 0x8B, | ||
1115 | HW_RATE_INDEX_6MBPS = 0x0C, | ||
1116 | HW_RATE_INDEX_9MBPS = 0x12, | ||
1117 | HW_RATE_INDEX_11MBPS = 0x96, | ||
1118 | HW_RATE_INDEX_12MBPS = 0x18, | ||
1119 | HW_RATE_INDEX_18MBPS = 0x24, | ||
1120 | HW_RATE_INDEX_24MBPS = 0x30, | ||
1121 | HW_RATE_INDEX_36MBPS = 0x48, | ||
1122 | HW_RATE_INDEX_48MBPS = 0x60, | ||
1123 | HW_RATE_INDEX_54MBPS = 0x6C | ||
1124 | }; | ||
1125 | |||
1126 | struct wcn36xx_hal_supported_rates { | ||
1127 | /* | ||
1128 | * For Self STA Entry: this represents Self Mode. | ||
1129 | * For Peer Stations, this represents the mode of the peer. | ||
1130 | * On Station: | ||
1131 | * | ||
1132 | * --this mode is updated when PE adds the Self Entry. | ||
1133 | * | ||
1134 | * -- OR when PE sends 'ADD_BSS' message and station context in BSS | ||
1135 | * is used to indicate the mode of the AP. | ||
1136 | * | ||
1137 | * ON AP: | ||
1138 | * | ||
1139 | * -- this mode is updated when PE sends 'ADD_BSS' and Sta entry | ||
1140 | * for that BSS is used to indicate the self mode of the AP. | ||
1141 | * | ||
1142 | * -- OR when a station is associated, PE sends 'ADD_STA' message | ||
1143 | * with this mode updated. | ||
1144 | */ | ||
1145 | |||
1146 | enum sta_rate_mode op_rate_mode; | ||
1147 | |||
1148 | /* 11b, 11a and aniLegacyRates are IE rates which gives rate in | ||
1149 | * unit of 500Kbps */ | ||
1150 | u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES]; | ||
1151 | u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES]; | ||
1152 | u16 legacy_rates[WCN36XX_HAL_NUM_POLARIS_RATES]; | ||
1153 | u16 reserved; | ||
1154 | |||
1155 | /* Taurus only supports 26 Titan Rates(no ESF/concat Rates will be | ||
1156 | * supported) First 26 bits are reserved for those Titan rates and | ||
1157 | * the last 4 bits(bit28-31) for Taurus, 2(bit26-27) bits are | ||
1158 | * reserved. */ | ||
1159 | /* Titan and Taurus Rates */ | ||
1160 | u32 enhanced_rate_bitmap; | ||
1161 | |||
1162 | /* | ||
1163 | * 0-76 bits used, remaining reserved | ||
1164 | * bits 0-15 and 32 should be set. | ||
1165 | */ | ||
1166 | u8 supported_mcs_set[WCN36XX_HAL_MAC_MAX_SUPPORTED_MCS_SET]; | ||
1167 | |||
1168 | /* | ||
1169 | * RX Highest Supported Data Rate defines the highest data | ||
1170 | * rate that the STA is able to receive, in unites of 1Mbps. | ||
1171 | * This value is derived from "Supported MCS Set field" inside | ||
1172 | * the HT capability element. | ||
1173 | */ | ||
1174 | u16 rx_highest_data_rate; | ||
1175 | |||
1176 | } __packed; | ||
1177 | |||
1178 | struct wcn36xx_hal_config_sta_params { | ||
1179 | /* BSSID of STA */ | ||
1180 | u8 bssid[ETH_ALEN]; | ||
1181 | |||
1182 | /* ASSOC ID, as assigned by UMAC */ | ||
1183 | u16 aid; | ||
1184 | |||
1185 | /* STA entry Type: 0 - Self, 1 - Other/Peer, 2 - BSSID, 3 - BCAST */ | ||
1186 | u8 type; | ||
1187 | |||
1188 | /* Short Preamble Supported. */ | ||
1189 | u8 short_preamble_supported; | ||
1190 | |||
1191 | /* MAC Address of STA */ | ||
1192 | u8 mac[ETH_ALEN]; | ||
1193 | |||
1194 | /* Listen interval of the STA */ | ||
1195 | u16 listen_interval; | ||
1196 | |||
1197 | /* Support for 11e/WMM */ | ||
1198 | u8 wmm_enabled; | ||
1199 | |||
1200 | /* 11n HT capable STA */ | ||
1201 | u8 ht_capable; | ||
1202 | |||
1203 | /* TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz */ | ||
1204 | u8 tx_channel_width_set; | ||
1205 | |||
1206 | /* RIFS mode 0 - NA, 1 - Allowed */ | ||
1207 | u8 rifs_mode; | ||
1208 | |||
1209 | /* L-SIG TXOP Protection mechanism | ||
1210 | 0 - No Support, 1 - Supported | ||
1211 | SG - there is global field */ | ||
1212 | u8 lsig_txop_protection; | ||
1213 | |||
1214 | /* Max Ampdu Size supported by STA. TPE programming. | ||
1215 | 0 : 8k , 1 : 16k, 2 : 32k, 3 : 64k */ | ||
1216 | u8 max_ampdu_size; | ||
1217 | |||
1218 | /* Max Ampdu density. Used by RA. 3 : 0~7 : 2^(11nAMPDUdensity -4) */ | ||
1219 | u8 max_ampdu_density; | ||
1220 | |||
1221 | /* Max AMSDU size 1 : 3839 bytes, 0 : 7935 bytes */ | ||
1222 | u8 max_amsdu_size; | ||
1223 | |||
1224 | /* Short GI support for 40Mhz packets */ | ||
1225 | u8 sgi_40mhz; | ||
1226 | |||
1227 | /* Short GI support for 20Mhz packets */ | ||
1228 | u8 sgi_20Mhz; | ||
1229 | |||
1230 | /* TODO move this parameter to the end for 3680 */ | ||
1231 | /* These rates are the intersection of peer and self capabilities. */ | ||
1232 | struct wcn36xx_hal_supported_rates supported_rates; | ||
1233 | |||
1234 | /* Robust Management Frame (RMF) enabled/disabled */ | ||
1235 | u8 rmf; | ||
1236 | |||
1237 | /* The unicast encryption type in the association */ | ||
1238 | u32 encrypt_type; | ||
1239 | |||
1240 | /* HAL should update the existing STA entry, if this flag is set. UMAC | ||
1241 | will set this flag in case of RE-ASSOC, where we want to reuse the | ||
1242 | old STA ID. 0 = Add, 1 = Update */ | ||
1243 | u8 action; | ||
1244 | |||
1245 | /* U-APSD Flags: 1b per AC. Encoded as follows: | ||
1246 | b7 b6 b5 b4 b3 b2 b1 b0 = | ||
1247 | X X X X BE BK VI VO */ | ||
1248 | u8 uapsd; | ||
1249 | |||
1250 | /* Max SP Length */ | ||
1251 | u8 max_sp_len; | ||
1252 | |||
1253 | /* 11n Green Field preamble support | ||
1254 | 0 - Not supported, 1 - Supported */ | ||
1255 | u8 green_field_capable; | ||
1256 | |||
1257 | /* MIMO Power Save mode */ | ||
1258 | enum wcn36xx_hal_ht_mimo_state mimo_ps; | ||
1259 | |||
1260 | /* Delayed BA Support */ | ||
1261 | u8 delayed_ba_support; | ||
1262 | |||
1263 | /* Max AMPDU duration in 32us */ | ||
1264 | u8 max_ampdu_duration; | ||
1265 | |||
1266 | /* HT STA should set it to 1 if it is enabled in BSS. HT STA should | ||
1267 | * set it to 0 if AP does not support it. This indication is sent | ||
1268 | * to HAL and HAL uses this flag to pickup up appropriate 40Mhz | ||
1269 | * rates. */ | ||
1270 | u8 dsss_cck_mode_40mhz; | ||
1271 | |||
1272 | /* Valid STA Idx when action=Update. Set to 0xFF when invalid! | ||
1273 | * Retained for backward compalibity with existing HAL code */ | ||
1274 | u8 sta_index; | ||
1275 | |||
1276 | /* BSSID of BSS to which station is associated. Set to 0xFF when | ||
1277 | * invalid. Retained for backward compalibity with existing HAL | ||
1278 | * code */ | ||
1279 | u8 bssid_index; | ||
1280 | |||
1281 | u8 p2p; | ||
1282 | |||
1283 | /* TODO add this parameter for 3680. */ | ||
1284 | /* Reserved to align next field on a dword boundary */ | ||
1285 | /* u8 reserved; */ | ||
1286 | } __packed; | ||
1287 | |||
1288 | struct wcn36xx_hal_config_sta_req_msg { | ||
1289 | struct wcn36xx_hal_msg_header header; | ||
1290 | struct wcn36xx_hal_config_sta_params sta_params; | ||
1291 | } __packed; | ||
1292 | |||
1293 | struct wcn36xx_hal_config_sta_params_v1 { | ||
1294 | /* BSSID of STA */ | ||
1295 | u8 bssid[ETH_ALEN]; | ||
1296 | |||
1297 | /* ASSOC ID, as assigned by UMAC */ | ||
1298 | u16 aid; | ||
1299 | |||
1300 | /* STA entry Type: 0 - Self, 1 - Other/Peer, 2 - BSSID, 3 - BCAST */ | ||
1301 | u8 type; | ||
1302 | |||
1303 | /* Short Preamble Supported. */ | ||
1304 | u8 short_preamble_supported; | ||
1305 | |||
1306 | /* MAC Address of STA */ | ||
1307 | u8 mac[ETH_ALEN]; | ||
1308 | |||
1309 | /* Listen interval of the STA */ | ||
1310 | u16 listen_interval; | ||
1311 | |||
1312 | /* Support for 11e/WMM */ | ||
1313 | u8 wmm_enabled; | ||
1314 | |||
1315 | /* 11n HT capable STA */ | ||
1316 | u8 ht_capable; | ||
1317 | |||
1318 | /* TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz */ | ||
1319 | u8 tx_channel_width_set; | ||
1320 | |||
1321 | /* RIFS mode 0 - NA, 1 - Allowed */ | ||
1322 | u8 rifs_mode; | ||
1323 | |||
1324 | /* L-SIG TXOP Protection mechanism | ||
1325 | 0 - No Support, 1 - Supported | ||
1326 | SG - there is global field */ | ||
1327 | u8 lsig_txop_protection; | ||
1328 | |||
1329 | /* Max Ampdu Size supported by STA. TPE programming. | ||
1330 | 0 : 8k , 1 : 16k, 2 : 32k, 3 : 64k */ | ||
1331 | u8 max_ampdu_size; | ||
1332 | |||
1333 | /* Max Ampdu density. Used by RA. 3 : 0~7 : 2^(11nAMPDUdensity -4) */ | ||
1334 | u8 max_ampdu_density; | ||
1335 | |||
1336 | /* Max AMSDU size 1 : 3839 bytes, 0 : 7935 bytes */ | ||
1337 | u8 max_amsdu_size; | ||
1338 | |||
1339 | /* Short GI support for 40Mhz packets */ | ||
1340 | u8 sgi_40mhz; | ||
1341 | |||
1342 | /* Short GI support for 20Mhz packets */ | ||
1343 | u8 sgi_20Mhz; | ||
1344 | |||
1345 | /* Robust Management Frame (RMF) enabled/disabled */ | ||
1346 | u8 rmf; | ||
1347 | |||
1348 | /* The unicast encryption type in the association */ | ||
1349 | u32 encrypt_type; | ||
1350 | |||
1351 | /* HAL should update the existing STA entry, if this flag is set. UMAC | ||
1352 | will set this flag in case of RE-ASSOC, where we want to reuse the | ||
1353 | old STA ID. 0 = Add, 1 = Update */ | ||
1354 | u8 action; | ||
1355 | |||
1356 | /* U-APSD Flags: 1b per AC. Encoded as follows: | ||
1357 | b7 b6 b5 b4 b3 b2 b1 b0 = | ||
1358 | X X X X BE BK VI VO */ | ||
1359 | u8 uapsd; | ||
1360 | |||
1361 | /* Max SP Length */ | ||
1362 | u8 max_sp_len; | ||
1363 | |||
1364 | /* 11n Green Field preamble support | ||
1365 | 0 - Not supported, 1 - Supported */ | ||
1366 | u8 green_field_capable; | ||
1367 | |||
1368 | /* MIMO Power Save mode */ | ||
1369 | enum wcn36xx_hal_ht_mimo_state mimo_ps; | ||
1370 | |||
1371 | /* Delayed BA Support */ | ||
1372 | u8 delayed_ba_support; | ||
1373 | |||
1374 | /* Max AMPDU duration in 32us */ | ||
1375 | u8 max_ampdu_duration; | ||
1376 | |||
1377 | /* HT STA should set it to 1 if it is enabled in BSS. HT STA should | ||
1378 | * set it to 0 if AP does not support it. This indication is sent | ||
1379 | * to HAL and HAL uses this flag to pickup up appropriate 40Mhz | ||
1380 | * rates. */ | ||
1381 | u8 dsss_cck_mode_40mhz; | ||
1382 | |||
1383 | /* Valid STA Idx when action=Update. Set to 0xFF when invalid! | ||
1384 | * Retained for backward compalibity with existing HAL code */ | ||
1385 | u8 sta_index; | ||
1386 | |||
1387 | /* BSSID of BSS to which station is associated. Set to 0xFF when | ||
1388 | * invalid. Retained for backward compalibity with existing HAL | ||
1389 | * code */ | ||
1390 | u8 bssid_index; | ||
1391 | |||
1392 | u8 p2p; | ||
1393 | |||
1394 | /* Reserved to align next field on a dword boundary */ | ||
1395 | u8 reserved; | ||
1396 | |||
1397 | /* These rates are the intersection of peer and self capabilities. */ | ||
1398 | struct wcn36xx_hal_supported_rates supported_rates; | ||
1399 | } __packed; | ||
1400 | |||
1401 | struct wcn36xx_hal_config_sta_req_msg_v1 { | ||
1402 | struct wcn36xx_hal_msg_header header; | ||
1403 | struct wcn36xx_hal_config_sta_params_v1 sta_params; | ||
1404 | } __packed; | ||
1405 | |||
1406 | struct config_sta_rsp_params { | ||
1407 | /* success or failure */ | ||
1408 | u32 status; | ||
1409 | |||
1410 | /* Station index; valid only when 'status' field value SUCCESS */ | ||
1411 | u8 sta_index; | ||
1412 | |||
1413 | /* BSSID Index of BSS to which the station is associated */ | ||
1414 | u8 bssid_index; | ||
1415 | |||
1416 | /* DPU Index for PTK */ | ||
1417 | u8 dpu_index; | ||
1418 | |||
1419 | /* DPU Index for GTK */ | ||
1420 | u8 bcast_dpu_index; | ||
1421 | |||
1422 | /* DPU Index for IGTK */ | ||
1423 | u8 bcast_mgmt_dpu_idx; | ||
1424 | |||
1425 | /* PTK DPU signature */ | ||
1426 | u8 uc_ucast_sig; | ||
1427 | |||
1428 | /* GTK DPU isignature */ | ||
1429 | u8 uc_bcast_sig; | ||
1430 | |||
1431 | /* IGTK DPU signature */ | ||
1432 | u8 uc_mgmt_sig; | ||
1433 | |||
1434 | u8 p2p; | ||
1435 | |||
1436 | } __packed; | ||
1437 | |||
1438 | struct wcn36xx_hal_config_sta_rsp_msg { | ||
1439 | struct wcn36xx_hal_msg_header header; | ||
1440 | |||
1441 | struct config_sta_rsp_params params; | ||
1442 | } __packed; | ||
1443 | |||
1444 | /* Delete STA Request message */ | ||
1445 | struct wcn36xx_hal_delete_sta_req_msg { | ||
1446 | struct wcn36xx_hal_msg_header header; | ||
1447 | |||
1448 | /* Index of STA to delete */ | ||
1449 | u8 sta_index; | ||
1450 | |||
1451 | } __packed; | ||
1452 | |||
1453 | /* Delete STA Response message */ | ||
1454 | struct wcn36xx_hal_delete_sta_rsp_msg { | ||
1455 | struct wcn36xx_hal_msg_header header; | ||
1456 | |||
1457 | /* success or failure */ | ||
1458 | u32 status; | ||
1459 | |||
1460 | /* Index of STA deleted */ | ||
1461 | u8 sta_id; | ||
1462 | } __packed; | ||
1463 | |||
1464 | /* 12 Bytes long because this structure can be used to represent rate and | ||
1465 | * extended rate set IEs. The parser assume this to be at least 12 */ | ||
1466 | struct wcn36xx_hal_rate_set { | ||
1467 | u8 num_rates; | ||
1468 | u8 rate[WCN36XX_HAL_MAC_RATESET_EID_MAX]; | ||
1469 | } __packed; | ||
1470 | |||
1471 | /* access category record */ | ||
1472 | struct wcn36xx_hal_aci_aifsn { | ||
1473 | #ifndef ANI_LITTLE_BIT_ENDIAN | ||
1474 | u8 rsvd:1; | ||
1475 | u8 aci:2; | ||
1476 | u8 acm:1; | ||
1477 | u8 aifsn:4; | ||
1478 | #else | ||
1479 | u8 aifsn:4; | ||
1480 | u8 acm:1; | ||
1481 | u8 aci:2; | ||
1482 | u8 rsvd:1; | ||
1483 | #endif | ||
1484 | } __packed; | ||
1485 | |||
1486 | /* contention window size */ | ||
1487 | struct wcn36xx_hal_mac_cw { | ||
1488 | #ifndef ANI_LITTLE_BIT_ENDIAN | ||
1489 | u8 max:4; | ||
1490 | u8 min:4; | ||
1491 | #else | ||
1492 | u8 min:4; | ||
1493 | u8 max:4; | ||
1494 | #endif | ||
1495 | } __packed; | ||
1496 | |||
1497 | struct wcn36xx_hal_edca_param_record { | ||
1498 | struct wcn36xx_hal_aci_aifsn aci; | ||
1499 | struct wcn36xx_hal_mac_cw cw; | ||
1500 | u16 txop_limit; | ||
1501 | } __packed; | ||
1502 | |||
1503 | struct wcn36xx_hal_mac_ssid { | ||
1504 | u8 length; | ||
1505 | u8 ssid[32]; | ||
1506 | } __packed; | ||
1507 | |||
1508 | /* Concurrency role. These are generic IDs that identify the various roles | ||
1509 | * in the software system. */ | ||
1510 | enum wcn36xx_hal_con_mode { | ||
1511 | WCN36XX_HAL_STA_MODE = 0, | ||
1512 | |||
1513 | /* to support softAp mode . This is misleading. | ||
1514 | It means AP MODE only. */ | ||
1515 | WCN36XX_HAL_STA_SAP_MODE = 1, | ||
1516 | |||
1517 | WCN36XX_HAL_P2P_CLIENT_MODE, | ||
1518 | WCN36XX_HAL_P2P_GO_MODE, | ||
1519 | WCN36XX_HAL_MONITOR_MODE, | ||
1520 | }; | ||
1521 | |||
1522 | /* This is a bit pattern to be set for each mode | ||
1523 | * bit 0 - sta mode | ||
1524 | * bit 1 - ap mode | ||
1525 | * bit 2 - p2p client mode | ||
1526 | * bit 3 - p2p go mode */ | ||
1527 | enum wcn36xx_hal_concurrency_mode { | ||
1528 | HAL_STA = 1, | ||
1529 | HAL_SAP = 2, | ||
1530 | |||
1531 | /* to support sta, softAp mode . This means STA+AP mode */ | ||
1532 | HAL_STA_SAP = 3, | ||
1533 | |||
1534 | HAL_P2P_CLIENT = 4, | ||
1535 | HAL_P2P_GO = 8, | ||
1536 | HAL_MAX_CONCURRENCY_PERSONA = 4 | ||
1537 | }; | ||
1538 | |||
1539 | struct wcn36xx_hal_config_bss_params { | ||
1540 | /* BSSID */ | ||
1541 | u8 bssid[ETH_ALEN]; | ||
1542 | |||
1543 | /* Self Mac Address */ | ||
1544 | u8 self_mac_addr[ETH_ALEN]; | ||
1545 | |||
1546 | /* BSS type */ | ||
1547 | enum wcn36xx_hal_bss_type bss_type; | ||
1548 | |||
1549 | /* Operational Mode: AP =0, STA = 1 */ | ||
1550 | u8 oper_mode; | ||
1551 | |||
1552 | /* Network Type */ | ||
1553 | enum wcn36xx_hal_nw_type nw_type; | ||
1554 | |||
1555 | /* Used to classify PURE_11G/11G_MIXED to program MTU */ | ||
1556 | u8 short_slot_time_supported; | ||
1557 | |||
1558 | /* Co-exist with 11a STA */ | ||
1559 | u8 lla_coexist; | ||
1560 | |||
1561 | /* Co-exist with 11b STA */ | ||
1562 | u8 llb_coexist; | ||
1563 | |||
1564 | /* Co-exist with 11g STA */ | ||
1565 | u8 llg_coexist; | ||
1566 | |||
1567 | /* Coexistence with 11n STA */ | ||
1568 | u8 ht20_coexist; | ||
1569 | |||
1570 | /* Non GF coexist flag */ | ||
1571 | u8 lln_non_gf_coexist; | ||
1572 | |||
1573 | /* TXOP protection support */ | ||
1574 | u8 lsig_tx_op_protection_full_support; | ||
1575 | |||
1576 | /* RIFS mode */ | ||
1577 | u8 rifs_mode; | ||
1578 | |||
1579 | /* Beacon Interval in TU */ | ||
1580 | u16 beacon_interval; | ||
1581 | |||
1582 | /* DTIM period */ | ||
1583 | u8 dtim_period; | ||
1584 | |||
1585 | /* TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz */ | ||
1586 | u8 tx_channel_width_set; | ||
1587 | |||
1588 | /* Operating channel */ | ||
1589 | u8 oper_channel; | ||
1590 | |||
1591 | /* Extension channel for channel bonding */ | ||
1592 | u8 ext_channel; | ||
1593 | |||
1594 | /* Reserved to align next field on a dword boundary */ | ||
1595 | u8 reserved; | ||
1596 | |||
1597 | /* TODO move sta to the end for 3680 */ | ||
1598 | /* Context of the station being added in HW | ||
1599 | * Add a STA entry for "itself" - | ||
1600 | * | ||
1601 | * On AP - Add the AP itself in an "STA context" | ||
1602 | * | ||
1603 | * On STA - Add the AP to which this STA is joining in an | ||
1604 | * "STA context" | ||
1605 | */ | ||
1606 | struct wcn36xx_hal_config_sta_params sta; | ||
1607 | /* SSID of the BSS */ | ||
1608 | struct wcn36xx_hal_mac_ssid ssid; | ||
1609 | |||
1610 | /* HAL should update the existing BSS entry, if this flag is set. | ||
1611 | * UMAC will set this flag in case of reassoc, where we want to | ||
1612 | * resue the the old BSSID and still return success 0 = Add, 1 = | ||
1613 | * Update */ | ||
1614 | u8 action; | ||
1615 | |||
1616 | /* MAC Rate Set */ | ||
1617 | struct wcn36xx_hal_rate_set rateset; | ||
1618 | |||
1619 | /* Enable/Disable HT capabilities of the BSS */ | ||
1620 | u8 ht; | ||
1621 | |||
1622 | /* Enable/Disable OBSS protection */ | ||
1623 | u8 obss_prot_enabled; | ||
1624 | |||
1625 | /* RMF enabled/disabled */ | ||
1626 | u8 rmf; | ||
1627 | |||
1628 | /* HT Operating Mode operating mode of the 802.11n STA */ | ||
1629 | enum wcn36xx_hal_ht_operating_mode ht_oper_mode; | ||
1630 | |||
1631 | /* Dual CTS Protection: 0 - Unused, 1 - Used */ | ||
1632 | u8 dual_cts_protection; | ||
1633 | |||
1634 | /* Probe Response Max retries */ | ||
1635 | u8 max_probe_resp_retry_limit; | ||
1636 | |||
1637 | /* To Enable Hidden ssid */ | ||
1638 | u8 hidden_ssid; | ||
1639 | |||
1640 | /* To Enable Disable FW Proxy Probe Resp */ | ||
1641 | u8 proxy_probe_resp; | ||
1642 | |||
1643 | /* Boolean to indicate if EDCA params are valid. UMAC might not | ||
1644 | * have valid EDCA params or might not desire to apply EDCA params | ||
1645 | * during config BSS. 0 implies Not Valid ; Non-Zero implies | ||
1646 | * valid */ | ||
1647 | u8 edca_params_valid; | ||
1648 | |||
1649 | /* EDCA Parameters for Best Effort Access Category */ | ||
1650 | struct wcn36xx_hal_edca_param_record acbe; | ||
1651 | |||
1652 | /* EDCA Parameters forBackground Access Category */ | ||
1653 | struct wcn36xx_hal_edca_param_record acbk; | ||
1654 | |||
1655 | /* EDCA Parameters for Video Access Category */ | ||
1656 | struct wcn36xx_hal_edca_param_record acvi; | ||
1657 | |||
1658 | /* EDCA Parameters for Voice Access Category */ | ||
1659 | struct wcn36xx_hal_edca_param_record acvo; | ||
1660 | |||
1661 | /* Ext Bss Config Msg if set */ | ||
1662 | u8 ext_set_sta_key_param_valid; | ||
1663 | |||
1664 | /* SetStaKeyParams for ext bss msg */ | ||
1665 | struct wcn36xx_hal_set_sta_key_params ext_set_sta_key_param; | ||
1666 | |||
1667 | /* Persona for the BSS can be STA,AP,GO,CLIENT value same as enum | ||
1668 | * wcn36xx_hal_con_mode */ | ||
1669 | u8 wcn36xx_hal_persona; | ||
1670 | |||
1671 | u8 spectrum_mgt_enable; | ||
1672 | |||
1673 | /* HAL fills in the tx power used for mgmt frames in txMgmtPower */ | ||
1674 | s8 tx_mgmt_power; | ||
1675 | |||
1676 | /* maxTxPower has max power to be used after applying the power | ||
1677 | * constraint if any */ | ||
1678 | s8 max_tx_power; | ||
1679 | } __packed; | ||
1680 | |||
1681 | struct wcn36xx_hal_config_bss_req_msg { | ||
1682 | struct wcn36xx_hal_msg_header header; | ||
1683 | struct wcn36xx_hal_config_bss_params bss_params; | ||
1684 | } __packed; | ||
1685 | |||
1686 | struct wcn36xx_hal_config_bss_params_v1 { | ||
1687 | /* BSSID */ | ||
1688 | u8 bssid[ETH_ALEN]; | ||
1689 | |||
1690 | /* Self Mac Address */ | ||
1691 | u8 self_mac_addr[ETH_ALEN]; | ||
1692 | |||
1693 | /* BSS type */ | ||
1694 | enum wcn36xx_hal_bss_type bss_type; | ||
1695 | |||
1696 | /* Operational Mode: AP =0, STA = 1 */ | ||
1697 | u8 oper_mode; | ||
1698 | |||
1699 | /* Network Type */ | ||
1700 | enum wcn36xx_hal_nw_type nw_type; | ||
1701 | |||
1702 | /* Used to classify PURE_11G/11G_MIXED to program MTU */ | ||
1703 | u8 short_slot_time_supported; | ||
1704 | |||
1705 | /* Co-exist with 11a STA */ | ||
1706 | u8 lla_coexist; | ||
1707 | |||
1708 | /* Co-exist with 11b STA */ | ||
1709 | u8 llb_coexist; | ||
1710 | |||
1711 | /* Co-exist with 11g STA */ | ||
1712 | u8 llg_coexist; | ||
1713 | |||
1714 | /* Coexistence with 11n STA */ | ||
1715 | u8 ht20_coexist; | ||
1716 | |||
1717 | /* Non GF coexist flag */ | ||
1718 | u8 lln_non_gf_coexist; | ||
1719 | |||
1720 | /* TXOP protection support */ | ||
1721 | u8 lsig_tx_op_protection_full_support; | ||
1722 | |||
1723 | /* RIFS mode */ | ||
1724 | u8 rifs_mode; | ||
1725 | |||
1726 | /* Beacon Interval in TU */ | ||
1727 | u16 beacon_interval; | ||
1728 | |||
1729 | /* DTIM period */ | ||
1730 | u8 dtim_period; | ||
1731 | |||
1732 | /* TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz */ | ||
1733 | u8 tx_channel_width_set; | ||
1734 | |||
1735 | /* Operating channel */ | ||
1736 | u8 oper_channel; | ||
1737 | |||
1738 | /* Extension channel for channel bonding */ | ||
1739 | u8 ext_channel; | ||
1740 | |||
1741 | /* Reserved to align next field on a dword boundary */ | ||
1742 | u8 reserved; | ||
1743 | |||
1744 | /* SSID of the BSS */ | ||
1745 | struct wcn36xx_hal_mac_ssid ssid; | ||
1746 | |||
1747 | /* HAL should update the existing BSS entry, if this flag is set. | ||
1748 | * UMAC will set this flag in case of reassoc, where we want to | ||
1749 | * resue the the old BSSID and still return success 0 = Add, 1 = | ||
1750 | * Update */ | ||
1751 | u8 action; | ||
1752 | |||
1753 | /* MAC Rate Set */ | ||
1754 | struct wcn36xx_hal_rate_set rateset; | ||
1755 | |||
1756 | /* Enable/Disable HT capabilities of the BSS */ | ||
1757 | u8 ht; | ||
1758 | |||
1759 | /* Enable/Disable OBSS protection */ | ||
1760 | u8 obss_prot_enabled; | ||
1761 | |||
1762 | /* RMF enabled/disabled */ | ||
1763 | u8 rmf; | ||
1764 | |||
1765 | /* HT Operating Mode operating mode of the 802.11n STA */ | ||
1766 | enum wcn36xx_hal_ht_operating_mode ht_oper_mode; | ||
1767 | |||
1768 | /* Dual CTS Protection: 0 - Unused, 1 - Used */ | ||
1769 | u8 dual_cts_protection; | ||
1770 | |||
1771 | /* Probe Response Max retries */ | ||
1772 | u8 max_probe_resp_retry_limit; | ||
1773 | |||
1774 | /* To Enable Hidden ssid */ | ||
1775 | u8 hidden_ssid; | ||
1776 | |||
1777 | /* To Enable Disable FW Proxy Probe Resp */ | ||
1778 | u8 proxy_probe_resp; | ||
1779 | |||
1780 | /* Boolean to indicate if EDCA params are valid. UMAC might not | ||
1781 | * have valid EDCA params or might not desire to apply EDCA params | ||
1782 | * during config BSS. 0 implies Not Valid ; Non-Zero implies | ||
1783 | * valid */ | ||
1784 | u8 edca_params_valid; | ||
1785 | |||
1786 | /* EDCA Parameters for Best Effort Access Category */ | ||
1787 | struct wcn36xx_hal_edca_param_record acbe; | ||
1788 | |||
1789 | /* EDCA Parameters forBackground Access Category */ | ||
1790 | struct wcn36xx_hal_edca_param_record acbk; | ||
1791 | |||
1792 | /* EDCA Parameters for Video Access Category */ | ||
1793 | struct wcn36xx_hal_edca_param_record acvi; | ||
1794 | |||
1795 | /* EDCA Parameters for Voice Access Category */ | ||
1796 | struct wcn36xx_hal_edca_param_record acvo; | ||
1797 | |||
1798 | /* Ext Bss Config Msg if set */ | ||
1799 | u8 ext_set_sta_key_param_valid; | ||
1800 | |||
1801 | /* SetStaKeyParams for ext bss msg */ | ||
1802 | struct wcn36xx_hal_set_sta_key_params ext_set_sta_key_param; | ||
1803 | |||
1804 | /* Persona for the BSS can be STA,AP,GO,CLIENT value same as enum | ||
1805 | * wcn36xx_hal_con_mode */ | ||
1806 | u8 wcn36xx_hal_persona; | ||
1807 | |||
1808 | u8 spectrum_mgt_enable; | ||
1809 | |||
1810 | /* HAL fills in the tx power used for mgmt frames in txMgmtPower */ | ||
1811 | s8 tx_mgmt_power; | ||
1812 | |||
1813 | /* maxTxPower has max power to be used after applying the power | ||
1814 | * constraint if any */ | ||
1815 | s8 max_tx_power; | ||
1816 | |||
1817 | /* Context of the station being added in HW | ||
1818 | * Add a STA entry for "itself" - | ||
1819 | * | ||
1820 | * On AP - Add the AP itself in an "STA context" | ||
1821 | * | ||
1822 | * On STA - Add the AP to which this STA is joining in an | ||
1823 | * "STA context" | ||
1824 | */ | ||
1825 | struct wcn36xx_hal_config_sta_params_v1 sta; | ||
1826 | } __packed; | ||
1827 | |||
1828 | struct wcn36xx_hal_config_bss_req_msg_v1 { | ||
1829 | struct wcn36xx_hal_msg_header header; | ||
1830 | struct wcn36xx_hal_config_bss_params_v1 bss_params; | ||
1831 | } __packed; | ||
1832 | |||
1833 | struct wcn36xx_hal_config_bss_rsp_params { | ||
1834 | /* Success or Failure */ | ||
1835 | u32 status; | ||
1836 | |||
1837 | /* BSS index allocated by HAL */ | ||
1838 | u8 bss_index; | ||
1839 | |||
1840 | /* DPU descriptor index for PTK */ | ||
1841 | u8 dpu_desc_index; | ||
1842 | |||
1843 | /* PTK DPU signature */ | ||
1844 | u8 ucast_dpu_signature; | ||
1845 | |||
1846 | /* DPU descriptor index for GTK */ | ||
1847 | u8 bcast_dpu_desc_indx; | ||
1848 | |||
1849 | /* GTK DPU signature */ | ||
1850 | u8 bcast_dpu_signature; | ||
1851 | |||
1852 | /* DPU descriptor for IGTK */ | ||
1853 | u8 mgmt_dpu_desc_index; | ||
1854 | |||
1855 | /* IGTK DPU signature */ | ||
1856 | u8 mgmt_dpu_signature; | ||
1857 | |||
1858 | /* Station Index for BSS entry */ | ||
1859 | u8 bss_sta_index; | ||
1860 | |||
1861 | /* Self station index for this BSS */ | ||
1862 | u8 bss_self_sta_index; | ||
1863 | |||
1864 | /* Bcast station for buffering bcast frames in AP role */ | ||
1865 | u8 bss_bcast_sta_idx; | ||
1866 | |||
1867 | /* MAC Address of STA(PEER/SELF) in staContext of configBSSReq */ | ||
1868 | u8 mac[ETH_ALEN]; | ||
1869 | |||
1870 | /* HAL fills in the tx power used for mgmt frames in this field. */ | ||
1871 | s8 tx_mgmt_power; | ||
1872 | |||
1873 | } __packed; | ||
1874 | |||
1875 | struct wcn36xx_hal_config_bss_rsp_msg { | ||
1876 | struct wcn36xx_hal_msg_header header; | ||
1877 | struct wcn36xx_hal_config_bss_rsp_params bss_rsp_params; | ||
1878 | } __packed; | ||
1879 | |||
1880 | struct wcn36xx_hal_delete_bss_req_msg { | ||
1881 | struct wcn36xx_hal_msg_header header; | ||
1882 | |||
1883 | /* BSS index to be deleted */ | ||
1884 | u8 bss_index; | ||
1885 | |||
1886 | } __packed; | ||
1887 | |||
1888 | struct wcn36xx_hal_delete_bss_rsp_msg { | ||
1889 | struct wcn36xx_hal_msg_header header; | ||
1890 | |||
1891 | /* Success or Failure */ | ||
1892 | u32 status; | ||
1893 | |||
1894 | /* BSS index that has been deleted */ | ||
1895 | u8 bss_index; | ||
1896 | |||
1897 | } __packed; | ||
1898 | |||
1899 | struct wcn36xx_hal_join_req_msg { | ||
1900 | struct wcn36xx_hal_msg_header header; | ||
1901 | |||
1902 | /* Indicates the BSSID to which STA is going to associate */ | ||
1903 | u8 bssid[ETH_ALEN]; | ||
1904 | |||
1905 | /* Indicates the channel to switch to. */ | ||
1906 | u8 channel; | ||
1907 | |||
1908 | /* Self STA MAC */ | ||
1909 | u8 self_sta_mac_addr[ETH_ALEN]; | ||
1910 | |||
1911 | /* Local power constraint */ | ||
1912 | u8 local_power_constraint; | ||
1913 | |||
1914 | /* Secondary channel offset */ | ||
1915 | enum phy_chan_bond_state secondary_channel_offset; | ||
1916 | |||
1917 | /* link State */ | ||
1918 | enum wcn36xx_hal_link_state link_state; | ||
1919 | |||
1920 | /* Max TX power */ | ||
1921 | s8 max_tx_power; | ||
1922 | } __packed; | ||
1923 | |||
1924 | struct wcn36xx_hal_join_rsp_msg { | ||
1925 | struct wcn36xx_hal_msg_header header; | ||
1926 | |||
1927 | /* success or failure */ | ||
1928 | u32 status; | ||
1929 | |||
1930 | /* HAL fills in the tx power used for mgmt frames in this field */ | ||
1931 | u8 tx_mgmt_power; | ||
1932 | } __packed; | ||
1933 | |||
1934 | struct post_assoc_req_msg { | ||
1935 | struct wcn36xx_hal_msg_header header; | ||
1936 | |||
1937 | struct wcn36xx_hal_config_sta_params sta_params; | ||
1938 | struct wcn36xx_hal_config_bss_params bss_params; | ||
1939 | }; | ||
1940 | |||
1941 | struct post_assoc_rsp_msg { | ||
1942 | struct wcn36xx_hal_msg_header header; | ||
1943 | struct config_sta_rsp_params sta_rsp_params; | ||
1944 | struct wcn36xx_hal_config_bss_rsp_params bss_rsp_params; | ||
1945 | }; | ||
1946 | |||
1947 | /* This is used to create a set of WEP keys for a given BSS. */ | ||
1948 | struct wcn36xx_hal_set_bss_key_req_msg { | ||
1949 | struct wcn36xx_hal_msg_header header; | ||
1950 | |||
1951 | /* BSS Index of the BSS */ | ||
1952 | u8 bss_idx; | ||
1953 | |||
1954 | /* Encryption Type used with peer */ | ||
1955 | enum ani_ed_type enc_type; | ||
1956 | |||
1957 | /* Number of keys */ | ||
1958 | u8 num_keys; | ||
1959 | |||
1960 | /* Array of keys. */ | ||
1961 | struct wcn36xx_hal_keys keys[WCN36XX_HAL_MAC_MAX_NUM_OF_DEFAULT_KEYS]; | ||
1962 | |||
1963 | /* Control for Replay Count, 1= Single TID based replay count on Tx | ||
1964 | * 0 = Per TID based replay count on TX */ | ||
1965 | u8 single_tid_rc; | ||
1966 | } __packed; | ||
1967 | |||
1968 | /* tagged version of set bss key */ | ||
1969 | struct wcn36xx_hal_set_bss_key_req_msg_tagged { | ||
1970 | struct wcn36xx_hal_set_bss_key_req_msg Msg; | ||
1971 | u32 tag; | ||
1972 | } __packed; | ||
1973 | |||
1974 | struct wcn36xx_hal_set_bss_key_rsp_msg { | ||
1975 | struct wcn36xx_hal_msg_header header; | ||
1976 | |||
1977 | /* success or failure */ | ||
1978 | u32 status; | ||
1979 | } __packed; | ||
1980 | |||
1981 | /* | ||
1982 | * This is used configure the key information on a given station. | ||
1983 | * When the sec_type is WEP40 or WEP104, the def_wep_idx is used to locate | ||
1984 | * a preconfigured key from a BSS the station assoicated with; otherwise | ||
1985 | * a new key descriptor is created based on the key field. | ||
1986 | */ | ||
1987 | struct wcn36xx_hal_set_sta_key_req_msg { | ||
1988 | struct wcn36xx_hal_msg_header header; | ||
1989 | struct wcn36xx_hal_set_sta_key_params set_sta_key_params; | ||
1990 | } __packed; | ||
1991 | |||
1992 | struct wcn36xx_hal_set_sta_key_rsp_msg { | ||
1993 | struct wcn36xx_hal_msg_header header; | ||
1994 | |||
1995 | /* success or failure */ | ||
1996 | u32 status; | ||
1997 | } __packed; | ||
1998 | |||
1999 | struct wcn36xx_hal_remove_bss_key_req_msg { | ||
2000 | struct wcn36xx_hal_msg_header header; | ||
2001 | |||
2002 | /* BSS Index of the BSS */ | ||
2003 | u8 bss_idx; | ||
2004 | |||
2005 | /* Encryption Type used with peer */ | ||
2006 | enum ani_ed_type enc_type; | ||
2007 | |||
2008 | /* Key Id */ | ||
2009 | u8 key_id; | ||
2010 | |||
2011 | /* STATIC/DYNAMIC. Used in Nullifying in Key Descriptors for | ||
2012 | * Static/Dynamic keys */ | ||
2013 | enum ani_wep_type wep_type; | ||
2014 | } __packed; | ||
2015 | |||
2016 | struct wcn36xx_hal_remove_bss_key_rsp_msg { | ||
2017 | struct wcn36xx_hal_msg_header header; | ||
2018 | |||
2019 | /* success or failure */ | ||
2020 | u32 status; | ||
2021 | } __packed; | ||
2022 | |||
2023 | /* | ||
2024 | * This is used by PE to Remove the key information on a given station. | ||
2025 | */ | ||
2026 | struct wcn36xx_hal_remove_sta_key_req_msg { | ||
2027 | struct wcn36xx_hal_msg_header header; | ||
2028 | |||
2029 | /* STA Index */ | ||
2030 | u16 sta_idx; | ||
2031 | |||
2032 | /* Encryption Type used with peer */ | ||
2033 | enum ani_ed_type enc_type; | ||
2034 | |||
2035 | /* Key Id */ | ||
2036 | u8 key_id; | ||
2037 | |||
2038 | /* Whether to invalidate the Broadcast key or Unicast key. In case | ||
2039 | * of WEP, the same key is used for both broadcast and unicast. */ | ||
2040 | u8 unicast; | ||
2041 | |||
2042 | } __packed; | ||
2043 | |||
2044 | struct wcn36xx_hal_remove_sta_key_rsp_msg { | ||
2045 | struct wcn36xx_hal_msg_header header; | ||
2046 | |||
2047 | /*success or failure */ | ||
2048 | u32 status; | ||
2049 | |||
2050 | } __packed; | ||
2051 | |||
2052 | #ifdef FEATURE_OEM_DATA_SUPPORT | ||
2053 | |||
2054 | #ifndef OEM_DATA_REQ_SIZE | ||
2055 | #define OEM_DATA_REQ_SIZE 134 | ||
2056 | #endif | ||
2057 | |||
2058 | #ifndef OEM_DATA_RSP_SIZE | ||
2059 | #define OEM_DATA_RSP_SIZE 1968 | ||
2060 | #endif | ||
2061 | |||
2062 | struct start_oem_data_req_msg { | ||
2063 | struct wcn36xx_hal_msg_header header; | ||
2064 | |||
2065 | u32 status; | ||
2066 | tSirMacAddr self_mac_addr; | ||
2067 | u8 oem_data_req[OEM_DATA_REQ_SIZE]; | ||
2068 | |||
2069 | }; | ||
2070 | |||
2071 | struct start_oem_data_rsp_msg { | ||
2072 | struct wcn36xx_hal_msg_header header; | ||
2073 | |||
2074 | u8 oem_data_rsp[OEM_DATA_RSP_SIZE]; | ||
2075 | }; | ||
2076 | |||
2077 | #endif | ||
2078 | |||
2079 | struct wcn36xx_hal_switch_channel_req_msg { | ||
2080 | struct wcn36xx_hal_msg_header header; | ||
2081 | |||
2082 | /* Channel number */ | ||
2083 | u8 channel_number; | ||
2084 | |||
2085 | /* Local power constraint */ | ||
2086 | u8 local_power_constraint; | ||
2087 | |||
2088 | /* Secondary channel offset */ | ||
2089 | enum phy_chan_bond_state secondary_channel_offset; | ||
2090 | |||
2091 | /* HAL fills in the tx power used for mgmt frames in this field. */ | ||
2092 | u8 tx_mgmt_power; | ||
2093 | |||
2094 | /* Max TX power */ | ||
2095 | u8 max_tx_power; | ||
2096 | |||
2097 | /* Self STA MAC */ | ||
2098 | u8 self_sta_mac_addr[ETH_ALEN]; | ||
2099 | |||
2100 | /* VO WIFI comment: BSSID needed to identify session. As the | ||
2101 | * request has power constraints, this should be applied only to | ||
2102 | * that session Since MTU timing and EDCA are sessionized, this | ||
2103 | * struct needs to be sessionized and bssid needs to be out of the | ||
2104 | * VOWifi feature flag V IMP: Keep bssId field at the end of this | ||
2105 | * msg. It is used to mantain backward compatbility by way of | ||
2106 | * ignoring if using new host/old FW or old host/new FW since it is | ||
2107 | * at the end of this struct | ||
2108 | */ | ||
2109 | u8 bssid[ETH_ALEN]; | ||
2110 | } __packed; | ||
2111 | |||
2112 | struct wcn36xx_hal_switch_channel_rsp_msg { | ||
2113 | struct wcn36xx_hal_msg_header header; | ||
2114 | |||
2115 | /* Status */ | ||
2116 | u32 status; | ||
2117 | |||
2118 | /* Channel number - same as in request */ | ||
2119 | u8 channel_number; | ||
2120 | |||
2121 | /* HAL fills in the tx power used for mgmt frames in this field */ | ||
2122 | u8 tx_mgmt_power; | ||
2123 | |||
2124 | /* BSSID needed to identify session - same as in request */ | ||
2125 | u8 bssid[ETH_ALEN]; | ||
2126 | |||
2127 | } __packed; | ||
2128 | |||
2129 | struct update_edca_params_req_msg { | ||
2130 | struct wcn36xx_hal_msg_header header; | ||
2131 | |||
2132 | /*BSS Index */ | ||
2133 | u16 bss_index; | ||
2134 | |||
2135 | /* Best Effort */ | ||
2136 | struct wcn36xx_hal_edca_param_record acbe; | ||
2137 | |||
2138 | /* Background */ | ||
2139 | struct wcn36xx_hal_edca_param_record acbk; | ||
2140 | |||
2141 | /* Video */ | ||
2142 | struct wcn36xx_hal_edca_param_record acvi; | ||
2143 | |||
2144 | /* Voice */ | ||
2145 | struct wcn36xx_hal_edca_param_record acvo; | ||
2146 | }; | ||
2147 | |||
2148 | struct update_edca_params_rsp_msg { | ||
2149 | struct wcn36xx_hal_msg_header header; | ||
2150 | |||
2151 | /* success or failure */ | ||
2152 | u32 status; | ||
2153 | }; | ||
2154 | |||
2155 | struct dpu_stats_params { | ||
2156 | /* Index of STA to which the statistics */ | ||
2157 | u16 sta_index; | ||
2158 | |||
2159 | /* Encryption mode */ | ||
2160 | u8 enc_mode; | ||
2161 | |||
2162 | /* status */ | ||
2163 | u32 status; | ||
2164 | |||
2165 | /* Statistics */ | ||
2166 | u32 send_blocks; | ||
2167 | u32 recv_blocks; | ||
2168 | u32 replays; | ||
2169 | u8 mic_error_cnt; | ||
2170 | u32 prot_excl_cnt; | ||
2171 | u16 format_err_cnt; | ||
2172 | u16 un_decryptable_cnt; | ||
2173 | u32 decrypt_err_cnt; | ||
2174 | u32 decrypt_ok_cnt; | ||
2175 | }; | ||
2176 | |||
2177 | struct wcn36xx_hal_stats_req_msg { | ||
2178 | struct wcn36xx_hal_msg_header header; | ||
2179 | |||
2180 | /* Valid STA Idx for per STA stats request */ | ||
2181 | u32 sta_id; | ||
2182 | |||
2183 | /* Categories of stats requested as specified in eHalStatsMask */ | ||
2184 | u32 stats_mask; | ||
2185 | }; | ||
2186 | |||
2187 | struct ani_summary_stats_info { | ||
2188 | /* Total number of packets(per AC) that were successfully | ||
2189 | * transmitted with retries */ | ||
2190 | u32 retry_cnt[4]; | ||
2191 | |||
2192 | /* The number of MSDU packets and MMPDU frames per AC that the | ||
2193 | * 802.11 station successfully transmitted after more than one | ||
2194 | * retransmission attempt */ | ||
2195 | u32 multiple_retry_cnt[4]; | ||
2196 | |||
2197 | /* Total number of packets(per AC) that were successfully | ||
2198 | * transmitted (with and without retries, including multi-cast, | ||
2199 | * broadcast) */ | ||
2200 | u32 tx_frm_cnt[4]; | ||
2201 | |||
2202 | /* Total number of packets that were successfully received (after | ||
2203 | * appropriate filter rules including multi-cast, broadcast) */ | ||
2204 | u32 rx_frm_cnt; | ||
2205 | |||
2206 | /* Total number of duplicate frames received successfully */ | ||
2207 | u32 frm_dup_cnt; | ||
2208 | |||
2209 | /* Total number packets(per AC) failed to transmit */ | ||
2210 | u32 fail_cnt[4]; | ||
2211 | |||
2212 | /* Total number of RTS/CTS sequence failures for transmission of a | ||
2213 | * packet */ | ||
2214 | u32 rts_fail_cnt; | ||
2215 | |||
2216 | /* Total number packets failed transmit because of no ACK from the | ||
2217 | * remote entity */ | ||
2218 | u32 ack_fail_cnt; | ||
2219 | |||
2220 | /* Total number of RTS/CTS sequence success for transmission of a | ||
2221 | * packet */ | ||
2222 | u32 rts_succ_cnt; | ||
2223 | |||
2224 | /* The sum of the receive error count and dropped-receive-buffer | ||
2225 | * error count. HAL will provide this as a sum of (FCS error) + | ||
2226 | * (Fail get BD/PDU in HW) */ | ||
2227 | u32 rx_discard_cnt; | ||
2228 | |||
2229 | /* | ||
2230 | * The receive error count. HAL will provide the RxP FCS error | ||
2231 | * global counter. */ | ||
2232 | u32 rx_error_cnt; | ||
2233 | |||
2234 | /* The sum of the transmit-directed byte count, transmit-multicast | ||
2235 | * byte count and transmit-broadcast byte count. HAL will sum TPE | ||
2236 | * UC/MC/BCAST global counters to provide this. */ | ||
2237 | u32 tx_byte_cnt; | ||
2238 | }; | ||
2239 | |||
2240 | /* defines tx_rate_flags */ | ||
2241 | enum tx_rate_info { | ||
2242 | /* Legacy rates */ | ||
2243 | HAL_TX_RATE_LEGACY = 0x1, | ||
2244 | |||
2245 | /* HT20 rates */ | ||
2246 | HAL_TX_RATE_HT20 = 0x2, | ||
2247 | |||
2248 | /* HT40 rates */ | ||
2249 | HAL_TX_RATE_HT40 = 0x4, | ||
2250 | |||
2251 | /* Rate with Short guard interval */ | ||
2252 | HAL_TX_RATE_SGI = 0x8, | ||
2253 | |||
2254 | /* Rate with Long guard interval */ | ||
2255 | HAL_TX_RATE_LGI = 0x10 | ||
2256 | }; | ||
2257 | |||
2258 | struct ani_global_class_a_stats_info { | ||
2259 | /* The number of MPDU frames received by the 802.11 station for | ||
2260 | * MSDU packets or MMPDU frames */ | ||
2261 | u32 rx_frag_cnt; | ||
2262 | |||
2263 | /* The number of MPDU frames received by the 802.11 station for | ||
2264 | * MSDU packets or MMPDU frames when a promiscuous packet filter | ||
2265 | * was enabled */ | ||
2266 | u32 promiscuous_rx_frag_cnt; | ||
2267 | |||
2268 | /* The receiver input sensitivity referenced to a FER of 8% at an | ||
2269 | * MPDU length of 1024 bytes at the antenna connector. Each element | ||
2270 | * of the array shall correspond to a supported rate and the order | ||
2271 | * shall be the same as the supporteRates parameter. */ | ||
2272 | u32 rx_input_sensitivity; | ||
2273 | |||
2274 | /* The maximum transmit power in dBm upto one decimal. for eg: if | ||
2275 | * it is 10.5dBm, the value would be 105 */ | ||
2276 | u32 max_pwr; | ||
2277 | |||
2278 | /* Number of times the receiver failed to synchronize with the | ||
2279 | * incoming signal after detecting the sync in the preamble of the | ||
2280 | * transmitted PLCP protocol data unit. */ | ||
2281 | u32 sync_fail_cnt; | ||
2282 | |||
2283 | /* Legacy transmit rate, in units of 500 kbit/sec, for the most | ||
2284 | * recently transmitted frame */ | ||
2285 | u32 tx_rate; | ||
2286 | |||
2287 | /* mcs index for HT20 and HT40 rates */ | ||
2288 | u32 mcs_index; | ||
2289 | |||
2290 | /* to differentiate between HT20 and HT40 rates; short and long | ||
2291 | * guard interval */ | ||
2292 | u32 tx_rate_flags; | ||
2293 | }; | ||
2294 | |||
2295 | struct ani_global_security_stats { | ||
2296 | /* The number of unencrypted received MPDU frames that the MAC | ||
2297 | * layer discarded when the IEEE 802.11 dot11ExcludeUnencrypted | ||
2298 | * management information base (MIB) object is enabled */ | ||
2299 | u32 rx_wep_unencrypted_frm_cnt; | ||
2300 | |||
2301 | /* The number of received MSDU packets that that the 802.11 station | ||
2302 | * discarded because of MIC failures */ | ||
2303 | u32 rx_mic_fail_cnt; | ||
2304 | |||
2305 | /* The number of encrypted MPDU frames that the 802.11 station | ||
2306 | * failed to decrypt because of a TKIP ICV error */ | ||
2307 | u32 tkip_icv_err; | ||
2308 | |||
2309 | /* The number of received MPDU frames that the 802.11 discarded | ||
2310 | * because of an invalid AES-CCMP format */ | ||
2311 | u32 aes_ccmp_format_err; | ||
2312 | |||
2313 | /* The number of received MPDU frames that the 802.11 station | ||
2314 | * discarded because of the AES-CCMP replay protection procedure */ | ||
2315 | u32 aes_ccmp_replay_cnt; | ||
2316 | |||
2317 | /* The number of received MPDU frames that the 802.11 station | ||
2318 | * discarded because of errors detected by the AES-CCMP decryption | ||
2319 | * algorithm */ | ||
2320 | u32 aes_ccmp_decrpt_err; | ||
2321 | |||
2322 | /* The number of encrypted MPDU frames received for which a WEP | ||
2323 | * decryption key was not available on the 802.11 station */ | ||
2324 | u32 wep_undecryptable_cnt; | ||
2325 | |||
2326 | /* The number of encrypted MPDU frames that the 802.11 station | ||
2327 | * failed to decrypt because of a WEP ICV error */ | ||
2328 | u32 wep_icv_err; | ||
2329 | |||
2330 | /* The number of received encrypted packets that the 802.11 station | ||
2331 | * successfully decrypted */ | ||
2332 | u32 rx_decrypt_succ_cnt; | ||
2333 | |||
2334 | /* The number of encrypted packets that the 802.11 station failed | ||
2335 | * to decrypt */ | ||
2336 | u32 rx_decrypt_fail_cnt; | ||
2337 | }; | ||
2338 | |||
2339 | struct ani_global_class_b_stats_info { | ||
2340 | struct ani_global_security_stats uc_stats; | ||
2341 | struct ani_global_security_stats mc_bc_stats; | ||
2342 | }; | ||
2343 | |||
2344 | struct ani_global_class_c_stats_info { | ||
2345 | /* This counter shall be incremented for a received A-MSDU frame | ||
2346 | * with the stations MAC address in the address 1 field or an | ||
2347 | * A-MSDU frame with a group address in the address 1 field */ | ||
2348 | u32 rx_amsdu_cnt; | ||
2349 | |||
2350 | /* This counter shall be incremented when the MAC receives an AMPDU | ||
2351 | * from the PHY */ | ||
2352 | u32 rx_ampdu_cnt; | ||
2353 | |||
2354 | /* This counter shall be incremented when a Frame is transmitted | ||
2355 | * only on the primary channel */ | ||
2356 | u32 tx_20_frm_cnt; | ||
2357 | |||
2358 | /* This counter shall be incremented when a Frame is received only | ||
2359 | * on the primary channel */ | ||
2360 | u32 rx_20_frm_cnt; | ||
2361 | |||
2362 | /* This counter shall be incremented by the number of MPDUs | ||
2363 | * received in the A-MPDU when an A-MPDU is received */ | ||
2364 | u32 rx_mpdu_in_ampdu_cnt; | ||
2365 | |||
2366 | /* This counter shall be incremented when an MPDU delimiter has a | ||
2367 | * CRC error when this is the first CRC error in the received AMPDU | ||
2368 | * or when the previous delimiter has been decoded correctly */ | ||
2369 | u32 ampdu_delimiter_crc_err; | ||
2370 | }; | ||
2371 | |||
2372 | struct ani_per_sta_stats_info { | ||
2373 | /* The number of MPDU frames that the 802.11 station transmitted | ||
2374 | * and acknowledged through a received 802.11 ACK frame */ | ||
2375 | u32 tx_frag_cnt[4]; | ||
2376 | |||
2377 | /* This counter shall be incremented when an A-MPDU is transmitted */ | ||
2378 | u32 tx_ampdu_cnt; | ||
2379 | |||
2380 | /* This counter shall increment by the number of MPDUs in the AMPDU | ||
2381 | * when an A-MPDU is transmitted */ | ||
2382 | u32 tx_mpdu_in_ampdu_cnt; | ||
2383 | }; | ||
2384 | |||
2385 | struct wcn36xx_hal_stats_rsp_msg { | ||
2386 | struct wcn36xx_hal_msg_header header; | ||
2387 | |||
2388 | /* Success or Failure */ | ||
2389 | u32 status; | ||
2390 | |||
2391 | /* STA Idx */ | ||
2392 | u32 sta_index; | ||
2393 | |||
2394 | /* Categories of STATS being returned as per eHalStatsMask */ | ||
2395 | u32 stats_mask; | ||
2396 | |||
2397 | /* message type is same as the request type */ | ||
2398 | u16 msg_type; | ||
2399 | |||
2400 | /* length of the entire request, includes the pStatsBuf length too */ | ||
2401 | u16 msg_len; | ||
2402 | }; | ||
2403 | |||
2404 | struct wcn36xx_hal_set_link_state_req_msg { | ||
2405 | struct wcn36xx_hal_msg_header header; | ||
2406 | |||
2407 | u8 bssid[ETH_ALEN]; | ||
2408 | enum wcn36xx_hal_link_state state; | ||
2409 | u8 self_mac_addr[ETH_ALEN]; | ||
2410 | |||
2411 | } __packed; | ||
2412 | |||
2413 | struct set_link_state_rsp_msg { | ||
2414 | struct wcn36xx_hal_msg_header header; | ||
2415 | |||
2416 | /* success or failure */ | ||
2417 | u32 status; | ||
2418 | }; | ||
2419 | |||
2420 | /* TSPEC Params */ | ||
2421 | struct wcn36xx_hal_ts_info_tfc { | ||
2422 | #ifndef ANI_LITTLE_BIT_ENDIAN | ||
2423 | u16 ackPolicy:2; | ||
2424 | u16 userPrio:3; | ||
2425 | u16 psb:1; | ||
2426 | u16 aggregation:1; | ||
2427 | u16 accessPolicy:2; | ||
2428 | u16 direction:2; | ||
2429 | u16 tsid:4; | ||
2430 | u16 trafficType:1; | ||
2431 | #else | ||
2432 | u16 trafficType:1; | ||
2433 | u16 tsid:4; | ||
2434 | u16 direction:2; | ||
2435 | u16 accessPolicy:2; | ||
2436 | u16 aggregation:1; | ||
2437 | u16 psb:1; | ||
2438 | u16 userPrio:3; | ||
2439 | u16 ackPolicy:2; | ||
2440 | #endif | ||
2441 | }; | ||
2442 | |||
2443 | /* Flag to schedule the traffic type */ | ||
2444 | struct wcn36xx_hal_ts_info_sch { | ||
2445 | #ifndef ANI_LITTLE_BIT_ENDIAN | ||
2446 | u8 rsvd:7; | ||
2447 | u8 schedule:1; | ||
2448 | #else | ||
2449 | u8 schedule:1; | ||
2450 | u8 rsvd:7; | ||
2451 | #endif | ||
2452 | }; | ||
2453 | |||
2454 | /* Traffic and scheduling info */ | ||
2455 | struct wcn36xx_hal_ts_info { | ||
2456 | struct wcn36xx_hal_ts_info_tfc traffic; | ||
2457 | struct wcn36xx_hal_ts_info_sch schedule; | ||
2458 | }; | ||
2459 | |||
2460 | /* Information elements */ | ||
2461 | struct wcn36xx_hal_tspec_ie { | ||
2462 | u8 type; | ||
2463 | u8 length; | ||
2464 | struct wcn36xx_hal_ts_info ts_info; | ||
2465 | u16 nom_msdu_size; | ||
2466 | u16 max_msdu_size; | ||
2467 | u32 min_svc_interval; | ||
2468 | u32 max_svc_interval; | ||
2469 | u32 inact_interval; | ||
2470 | u32 suspend_interval; | ||
2471 | u32 svc_start_time; | ||
2472 | u32 min_data_rate; | ||
2473 | u32 mean_data_rate; | ||
2474 | u32 peak_data_rate; | ||
2475 | u32 max_burst_sz; | ||
2476 | u32 delay_bound; | ||
2477 | u32 min_phy_rate; | ||
2478 | u16 surplus_bw; | ||
2479 | u16 medium_time; | ||
2480 | }; | ||
2481 | |||
2482 | struct add_ts_req_msg { | ||
2483 | struct wcn36xx_hal_msg_header header; | ||
2484 | |||
2485 | /* Station Index */ | ||
2486 | u16 sta_index; | ||
2487 | |||
2488 | /* TSPEC handler uniquely identifying a TSPEC for a STA in a BSS */ | ||
2489 | u16 tspec_index; | ||
2490 | |||
2491 | /* To program TPE with required parameters */ | ||
2492 | struct wcn36xx_hal_tspec_ie tspec; | ||
2493 | |||
2494 | /* U-APSD Flags: 1b per AC. Encoded as follows: | ||
2495 | b7 b6 b5 b4 b3 b2 b1 b0 = | ||
2496 | X X X X BE BK VI VO */ | ||
2497 | u8 uapsd; | ||
2498 | |||
2499 | /* These parameters are for all the access categories */ | ||
2500 | |||
2501 | /* Service Interval */ | ||
2502 | u32 service_interval[WCN36XX_HAL_MAX_AC]; | ||
2503 | |||
2504 | /* Suspend Interval */ | ||
2505 | u32 suspend_interval[WCN36XX_HAL_MAX_AC]; | ||
2506 | |||
2507 | /* Delay Interval */ | ||
2508 | u32 delay_interval[WCN36XX_HAL_MAX_AC]; | ||
2509 | }; | ||
2510 | |||
2511 | struct add_rs_rsp_msg { | ||
2512 | struct wcn36xx_hal_msg_header header; | ||
2513 | |||
2514 | /* success or failure */ | ||
2515 | u32 status; | ||
2516 | }; | ||
2517 | |||
2518 | struct del_ts_req_msg { | ||
2519 | struct wcn36xx_hal_msg_header header; | ||
2520 | |||
2521 | /* Station Index */ | ||
2522 | u16 sta_index; | ||
2523 | |||
2524 | /* TSPEC identifier uniquely identifying a TSPEC for a STA in a BSS */ | ||
2525 | u16 tspec_index; | ||
2526 | |||
2527 | /* To lookup station id using the mac address */ | ||
2528 | u8 bssid[ETH_ALEN]; | ||
2529 | }; | ||
2530 | |||
2531 | struct del_ts_rsp_msg { | ||
2532 | struct wcn36xx_hal_msg_header header; | ||
2533 | |||
2534 | /* success or failure */ | ||
2535 | u32 status; | ||
2536 | }; | ||
2537 | |||
2538 | /* End of TSpec Parameters */ | ||
2539 | |||
2540 | /* Start of BLOCK ACK related Parameters */ | ||
2541 | |||
2542 | struct wcn36xx_hal_add_ba_session_req_msg { | ||
2543 | struct wcn36xx_hal_msg_header header; | ||
2544 | |||
2545 | /* Station Index */ | ||
2546 | u16 sta_index; | ||
2547 | |||
2548 | /* Peer MAC Address */ | ||
2549 | u8 mac_addr[ETH_ALEN]; | ||
2550 | |||
2551 | /* ADDBA Action Frame dialog token | ||
2552 | HAL will not interpret this object */ | ||
2553 | u8 dialog_token; | ||
2554 | |||
2555 | /* TID for which the BA is being setup | ||
2556 | This identifies the TC or TS of interest */ | ||
2557 | u8 tid; | ||
2558 | |||
2559 | /* 0 - Delayed BA (Not supported) | ||
2560 | 1 - Immediate BA */ | ||
2561 | u8 policy; | ||
2562 | |||
2563 | /* Indicates the number of buffers for this TID (baTID) | ||
2564 | NOTE - This is the requested buffer size. When this | ||
2565 | is processed by HAL and subsequently by HDD, it is | ||
2566 | possible that HDD may change this buffer size. Any | ||
2567 | change in the buffer size should be noted by PE and | ||
2568 | advertized appropriately in the ADDBA response */ | ||
2569 | u16 buffer_size; | ||
2570 | |||
2571 | /* BA timeout in TU's 0 means no timeout will occur */ | ||
2572 | u16 timeout; | ||
2573 | |||
2574 | /* b0..b3 - Fragment Number - Always set to 0 | ||
2575 | b4..b15 - Starting Sequence Number of first MSDU | ||
2576 | for which this BA is setup */ | ||
2577 | u16 ssn; | ||
2578 | |||
2579 | /* ADDBA direction | ||
2580 | 1 - Originator | ||
2581 | 0 - Recipient */ | ||
2582 | u8 direction; | ||
2583 | } __packed; | ||
2584 | |||
2585 | struct wcn36xx_hal_add_ba_session_rsp_msg { | ||
2586 | struct wcn36xx_hal_msg_header header; | ||
2587 | |||
2588 | /* success or failure */ | ||
2589 | u32 status; | ||
2590 | |||
2591 | /* Dialog token */ | ||
2592 | u8 dialog_token; | ||
2593 | |||
2594 | /* TID for which the BA session has been setup */ | ||
2595 | u8 ba_tid; | ||
2596 | |||
2597 | /* BA Buffer Size allocated for the current BA session */ | ||
2598 | u8 ba_buffer_size; | ||
2599 | |||
2600 | u8 ba_session_id; | ||
2601 | |||
2602 | /* Reordering Window buffer */ | ||
2603 | u8 win_size; | ||
2604 | |||
2605 | /* Station Index to id the sta */ | ||
2606 | u8 sta_index; | ||
2607 | |||
2608 | /* Starting Sequence Number */ | ||
2609 | u16 ssn; | ||
2610 | } __packed; | ||
2611 | |||
2612 | struct wcn36xx_hal_add_ba_req_msg { | ||
2613 | struct wcn36xx_hal_msg_header header; | ||
2614 | |||
2615 | /* Session Id */ | ||
2616 | u8 session_id; | ||
2617 | |||
2618 | /* Reorder Window Size */ | ||
2619 | u8 win_size; | ||
2620 | /* Old FW 1.2.2.4 does not support this*/ | ||
2621 | #ifdef FEATURE_ON_CHIP_REORDERING | ||
2622 | u8 reordering_done_on_chip; | ||
2623 | #endif | ||
2624 | } __packed; | ||
2625 | |||
2626 | struct wcn36xx_hal_add_ba_rsp_msg { | ||
2627 | struct wcn36xx_hal_msg_header header; | ||
2628 | |||
2629 | /* success or failure */ | ||
2630 | u32 status; | ||
2631 | |||
2632 | /* Dialog token */ | ||
2633 | u8 dialog_token; | ||
2634 | } __packed; | ||
2635 | |||
2636 | struct add_ba_info { | ||
2637 | u16 ba_enable:1; | ||
2638 | u16 starting_seq_num:12; | ||
2639 | u16 reserved:3; | ||
2640 | }; | ||
2641 | |||
2642 | struct wcn36xx_hal_trigger_ba_rsp_candidate { | ||
2643 | u8 sta_addr[ETH_ALEN]; | ||
2644 | struct add_ba_info ba_info[STACFG_MAX_TC]; | ||
2645 | } __packed; | ||
2646 | |||
2647 | struct wcn36xx_hal_trigget_ba_req_candidate { | ||
2648 | u8 sta_index; | ||
2649 | u8 tid_bitmap; | ||
2650 | } __packed; | ||
2651 | |||
2652 | struct wcn36xx_hal_trigger_ba_req_msg { | ||
2653 | struct wcn36xx_hal_msg_header header; | ||
2654 | |||
2655 | /* Session Id */ | ||
2656 | u8 session_id; | ||
2657 | |||
2658 | /* baCandidateCnt is followed by trigger BA | ||
2659 | * Candidate List(tTriggerBaCandidate) | ||
2660 | */ | ||
2661 | u16 candidate_cnt; | ||
2662 | |||
2663 | } __packed; | ||
2664 | |||
2665 | struct wcn36xx_hal_trigger_ba_rsp_msg { | ||
2666 | struct wcn36xx_hal_msg_header header; | ||
2667 | |||
2668 | /* TO SUPPORT BT-AMP */ | ||
2669 | u8 bssid[ETH_ALEN]; | ||
2670 | |||
2671 | /* success or failure */ | ||
2672 | u32 status; | ||
2673 | |||
2674 | /* baCandidateCnt is followed by trigger BA | ||
2675 | * Rsp Candidate List(tTriggerRspBaCandidate) | ||
2676 | */ | ||
2677 | u16 candidate_cnt; | ||
2678 | } __packed; | ||
2679 | |||
2680 | struct wcn36xx_hal_del_ba_req_msg { | ||
2681 | struct wcn36xx_hal_msg_header header; | ||
2682 | |||
2683 | /* Station Index */ | ||
2684 | u16 sta_index; | ||
2685 | |||
2686 | /* TID for which the BA session is being deleted */ | ||
2687 | u8 tid; | ||
2688 | |||
2689 | /* DELBA direction | ||
2690 | 1 - Originator | ||
2691 | 0 - Recipient */ | ||
2692 | u8 direction; | ||
2693 | } __packed; | ||
2694 | |||
2695 | struct wcn36xx_hal_del_ba_rsp_msg { | ||
2696 | struct wcn36xx_hal_msg_header header; | ||
2697 | |||
2698 | /* success or failure */ | ||
2699 | u32 status; | ||
2700 | } __packed; | ||
2701 | |||
2702 | struct tsm_stats_req_msg { | ||
2703 | struct wcn36xx_hal_msg_header header; | ||
2704 | |||
2705 | /* Traffic Id */ | ||
2706 | u8 tid; | ||
2707 | |||
2708 | u8 bssid[ETH_ALEN]; | ||
2709 | }; | ||
2710 | |||
2711 | struct tsm_stats_rsp_msg { | ||
2712 | struct wcn36xx_hal_msg_header header; | ||
2713 | |||
2714 | /*success or failure */ | ||
2715 | u32 status; | ||
2716 | |||
2717 | /* Uplink Packet Queue delay */ | ||
2718 | u16 uplink_pkt_queue_delay; | ||
2719 | |||
2720 | /* Uplink Packet Queue delay histogram */ | ||
2721 | u16 uplink_pkt_queue_delay_hist[4]; | ||
2722 | |||
2723 | /* Uplink Packet Transmit delay */ | ||
2724 | u32 uplink_pkt_tx_delay; | ||
2725 | |||
2726 | /* Uplink Packet loss */ | ||
2727 | u16 uplink_pkt_loss; | ||
2728 | |||
2729 | /* Uplink Packet count */ | ||
2730 | u16 uplink_pkt_count; | ||
2731 | |||
2732 | /* Roaming count */ | ||
2733 | u8 roaming_count; | ||
2734 | |||
2735 | /* Roaming Delay */ | ||
2736 | u16 roaming_delay; | ||
2737 | }; | ||
2738 | |||
2739 | struct set_key_done_msg { | ||
2740 | struct wcn36xx_hal_msg_header header; | ||
2741 | |||
2742 | /*bssid of the keys */ | ||
2743 | u8 bssidx; | ||
2744 | u8 enc_type; | ||
2745 | }; | ||
2746 | |||
2747 | struct wcn36xx_hal_nv_img_download_req_msg { | ||
2748 | /* Note: The length specified in wcn36xx_hal_nv_img_download_req_msg | ||
2749 | * messages should be | ||
2750 | * header.len = sizeof(wcn36xx_hal_nv_img_download_req_msg) + | ||
2751 | * nv_img_buffer_size */ | ||
2752 | struct wcn36xx_hal_msg_header header; | ||
2753 | |||
2754 | /* Fragment sequence number of the NV Image. Note that NV Image | ||
2755 | * might not fit into one message due to size limitation of the SMD | ||
2756 | * channel FIFO. UMAC can hence choose to chop the NV blob into | ||
2757 | * multiple fragments starting with seqeunce number 0, 1, 2 etc. | ||
2758 | * The last fragment MUST be indicated by marking the | ||
2759 | * isLastFragment field to 1. Note that all the NV blobs would be | ||
2760 | * concatenated together by HAL without any padding bytes in | ||
2761 | * between.*/ | ||
2762 | u16 frag_number; | ||
2763 | |||
2764 | /* Is this the last fragment? When set to 1 it indicates that no | ||
2765 | * more fragments will be sent by UMAC and HAL can concatenate all | ||
2766 | * the NV blobs rcvd & proceed with the parsing. HAL would generate | ||
2767 | * a WCN36XX_HAL_DOWNLOAD_NV_RSP to the WCN36XX_HAL_DOWNLOAD_NV_REQ | ||
2768 | * after it receives each fragment */ | ||
2769 | u16 last_fragment; | ||
2770 | |||
2771 | /* NV Image size (number of bytes) */ | ||
2772 | u32 nv_img_buffer_size; | ||
2773 | |||
2774 | /* Following the 'nv_img_buffer_size', there should be | ||
2775 | * nv_img_buffer_size bytes of NV Image i.e. | ||
2776 | * u8[nv_img_buffer_size] */ | ||
2777 | } __packed; | ||
2778 | |||
2779 | struct wcn36xx_hal_nv_img_download_rsp_msg { | ||
2780 | struct wcn36xx_hal_msg_header header; | ||
2781 | |||
2782 | /* Success or Failure. HAL would generate a | ||
2783 | * WCN36XX_HAL_DOWNLOAD_NV_RSP after each fragment */ | ||
2784 | u32 status; | ||
2785 | } __packed; | ||
2786 | |||
2787 | struct wcn36xx_hal_nv_store_ind { | ||
2788 | /* Note: The length specified in tHalNvStoreInd messages should be | ||
2789 | * header.msgLen = sizeof(tHalNvStoreInd) + nvBlobSize */ | ||
2790 | struct wcn36xx_hal_msg_header header; | ||
2791 | |||
2792 | /* NV Item */ | ||
2793 | u32 table_id; | ||
2794 | |||
2795 | /* Size of NV Blob */ | ||
2796 | u32 nv_blob_size; | ||
2797 | |||
2798 | /* Following the 'nvBlobSize', there should be nvBlobSize bytes of | ||
2799 | * NV blob i.e. u8[nvBlobSize] */ | ||
2800 | }; | ||
2801 | |||
2802 | /* End of Block Ack Related Parameters */ | ||
2803 | |||
2804 | #define WCN36XX_HAL_CIPHER_SEQ_CTR_SIZE 6 | ||
2805 | |||
2806 | /* Definition for MIC failure indication MAC reports this each time a MIC | ||
2807 | * failure occures on Rx TKIP packet | ||
2808 | */ | ||
2809 | struct mic_failure_ind_msg { | ||
2810 | struct wcn36xx_hal_msg_header header; | ||
2811 | |||
2812 | u8 bssid[ETH_ALEN]; | ||
2813 | |||
2814 | /* address used to compute MIC */ | ||
2815 | u8 src_addr[ETH_ALEN]; | ||
2816 | |||
2817 | /* transmitter address */ | ||
2818 | u8 ta_addr[ETH_ALEN]; | ||
2819 | |||
2820 | u8 dst_addr[ETH_ALEN]; | ||
2821 | |||
2822 | u8 multicast; | ||
2823 | |||
2824 | /* first byte of IV */ | ||
2825 | u8 iv1; | ||
2826 | |||
2827 | /* second byte of IV */ | ||
2828 | u8 key_id; | ||
2829 | |||
2830 | /* sequence number */ | ||
2831 | u8 tsc[WCN36XX_HAL_CIPHER_SEQ_CTR_SIZE]; | ||
2832 | |||
2833 | /* receive address */ | ||
2834 | u8 rx_addr[ETH_ALEN]; | ||
2835 | }; | ||
2836 | |||
2837 | struct update_vht_op_mode_req_msg { | ||
2838 | struct wcn36xx_hal_msg_header header; | ||
2839 | |||
2840 | u16 op_mode; | ||
2841 | u16 sta_id; | ||
2842 | }; | ||
2843 | |||
2844 | struct update_vht_op_mode_params_rsp_msg { | ||
2845 | struct wcn36xx_hal_msg_header header; | ||
2846 | |||
2847 | u32 status; | ||
2848 | }; | ||
2849 | |||
2850 | struct update_beacon_req_msg { | ||
2851 | struct wcn36xx_hal_msg_header header; | ||
2852 | |||
2853 | u8 bss_index; | ||
2854 | |||
2855 | /* shortPreamble mode. HAL should update all the STA rates when it | ||
2856 | * receives this message */ | ||
2857 | u8 short_preamble; | ||
2858 | |||
2859 | /* short Slot time. */ | ||
2860 | u8 short_slot_time; | ||
2861 | |||
2862 | /* Beacon Interval */ | ||
2863 | u16 beacon_interval; | ||
2864 | |||
2865 | /* Protection related */ | ||
2866 | u8 lla_coexist; | ||
2867 | u8 llb_coexist; | ||
2868 | u8 llg_coexist; | ||
2869 | u8 ht20_coexist; | ||
2870 | u8 lln_non_gf_coexist; | ||
2871 | u8 lsig_tx_op_protection_full_support; | ||
2872 | u8 rifs_mode; | ||
2873 | |||
2874 | u16 param_change_bitmap; | ||
2875 | }; | ||
2876 | |||
2877 | struct update_beacon_rsp_msg { | ||
2878 | struct wcn36xx_hal_msg_header header; | ||
2879 | u32 status; | ||
2880 | }; | ||
2881 | |||
2882 | struct wcn36xx_hal_send_beacon_req_msg { | ||
2883 | struct wcn36xx_hal_msg_header header; | ||
2884 | |||
2885 | /* length of the template. */ | ||
2886 | u32 beacon_length; | ||
2887 | |||
2888 | /* Beacon data. */ | ||
2889 | u8 beacon[BEACON_TEMPLATE_SIZE]; | ||
2890 | |||
2891 | u8 bssid[ETH_ALEN]; | ||
2892 | |||
2893 | /* TIM IE offset from the beginning of the template. */ | ||
2894 | u32 tim_ie_offset; | ||
2895 | |||
2896 | /* P2P IE offset from the begining of the template */ | ||
2897 | u16 p2p_ie_offset; | ||
2898 | } __packed; | ||
2899 | |||
2900 | struct send_beacon_rsp_msg { | ||
2901 | struct wcn36xx_hal_msg_header header; | ||
2902 | u32 status; | ||
2903 | } __packed; | ||
2904 | |||
2905 | struct enable_radar_req_msg { | ||
2906 | struct wcn36xx_hal_msg_header header; | ||
2907 | |||
2908 | u8 bssid[ETH_ALEN]; | ||
2909 | u8 channel; | ||
2910 | }; | ||
2911 | |||
2912 | struct enable_radar_rsp_msg { | ||
2913 | struct wcn36xx_hal_msg_header header; | ||
2914 | |||
2915 | /* Link Parameters */ | ||
2916 | u8 bssid[ETH_ALEN]; | ||
2917 | |||
2918 | /* success or failure */ | ||
2919 | u32 status; | ||
2920 | }; | ||
2921 | |||
2922 | struct radar_detect_intr_ind_msg { | ||
2923 | struct wcn36xx_hal_msg_header header; | ||
2924 | |||
2925 | u8 radar_det_channel; | ||
2926 | }; | ||
2927 | |||
2928 | struct radar_detect_ind_msg { | ||
2929 | struct wcn36xx_hal_msg_header header; | ||
2930 | |||
2931 | /* channel number in which the RADAR detected */ | ||
2932 | u8 channel_number; | ||
2933 | |||
2934 | /* RADAR pulse width in usecond */ | ||
2935 | u16 radar_pulse_width; | ||
2936 | |||
2937 | /* Number of RADAR pulses */ | ||
2938 | u16 num_radar_pulse; | ||
2939 | }; | ||
2940 | |||
2941 | struct wcn36xx_hal_get_tpc_report_req_msg { | ||
2942 | struct wcn36xx_hal_msg_header header; | ||
2943 | |||
2944 | u8 sta[ETH_ALEN]; | ||
2945 | u8 dialog_token; | ||
2946 | u8 txpower; | ||
2947 | }; | ||
2948 | |||
2949 | struct wcn36xx_hal_get_tpc_report_rsp_msg { | ||
2950 | struct wcn36xx_hal_msg_header header; | ||
2951 | |||
2952 | /* success or failure */ | ||
2953 | u32 status; | ||
2954 | }; | ||
2955 | |||
2956 | struct wcn36xx_hal_send_probe_resp_req_msg { | ||
2957 | struct wcn36xx_hal_msg_header header; | ||
2958 | |||
2959 | u8 probe_resp_template[BEACON_TEMPLATE_SIZE]; | ||
2960 | u32 probe_resp_template_len; | ||
2961 | u32 proxy_probe_req_valid_ie_bmap[8]; | ||
2962 | u8 bssid[ETH_ALEN]; | ||
2963 | }; | ||
2964 | |||
2965 | struct send_probe_resp_rsp_msg { | ||
2966 | struct wcn36xx_hal_msg_header header; | ||
2967 | |||
2968 | /* success or failure */ | ||
2969 | u32 status; | ||
2970 | }; | ||
2971 | |||
2972 | struct send_unknown_frame_rx_ind_msg { | ||
2973 | struct wcn36xx_hal_msg_header header; | ||
2974 | |||
2975 | /* success or failure */ | ||
2976 | u32 status; | ||
2977 | }; | ||
2978 | |||
2979 | struct wcn36xx_hal_delete_sta_context_ind_msg { | ||
2980 | struct wcn36xx_hal_msg_header header; | ||
2981 | |||
2982 | u16 aid; | ||
2983 | u16 sta_id; | ||
2984 | |||
2985 | /* TO SUPPORT BT-AMP */ | ||
2986 | u8 bssid[ETH_ALEN]; | ||
2987 | |||
2988 | /* HAL copies bssid from the sta table. */ | ||
2989 | u8 addr2[ETH_ALEN]; | ||
2990 | |||
2991 | /* To unify the keepalive / unknown A2 / tim-based disa */ | ||
2992 | u16 reason_code; | ||
2993 | } __packed; | ||
2994 | |||
2995 | struct indicate_del_sta { | ||
2996 | struct wcn36xx_hal_msg_header header; | ||
2997 | u8 aid; | ||
2998 | u8 sta_index; | ||
2999 | u8 bss_index; | ||
3000 | u8 reason_code; | ||
3001 | u32 status; | ||
3002 | }; | ||
3003 | |||
3004 | struct bt_amp_event_msg { | ||
3005 | struct wcn36xx_hal_msg_header header; | ||
3006 | |||
3007 | enum bt_amp_event_type btAmpEventType; | ||
3008 | }; | ||
3009 | |||
3010 | struct bt_amp_event_rsp { | ||
3011 | struct wcn36xx_hal_msg_header header; | ||
3012 | |||
3013 | /* success or failure */ | ||
3014 | u32 status; | ||
3015 | }; | ||
3016 | |||
3017 | struct tl_hal_flush_ac_req_msg { | ||
3018 | struct wcn36xx_hal_msg_header header; | ||
3019 | |||
3020 | /* Station Index. originates from HAL */ | ||
3021 | u8 sta_id; | ||
3022 | |||
3023 | /* TID for which the transmit queue is being flushed */ | ||
3024 | u8 tid; | ||
3025 | }; | ||
3026 | |||
3027 | struct tl_hal_flush_ac_rsp_msg { | ||
3028 | struct wcn36xx_hal_msg_header header; | ||
3029 | |||
3030 | /* Station Index. originates from HAL */ | ||
3031 | u8 sta_id; | ||
3032 | |||
3033 | /* TID for which the transmit queue is being flushed */ | ||
3034 | u8 tid; | ||
3035 | |||
3036 | /* success or failure */ | ||
3037 | u32 status; | ||
3038 | }; | ||
3039 | |||
3040 | struct wcn36xx_hal_enter_imps_req_msg { | ||
3041 | struct wcn36xx_hal_msg_header header; | ||
3042 | }; | ||
3043 | |||
3044 | struct wcn36xx_hal_exit_imps_req { | ||
3045 | struct wcn36xx_hal_msg_header header; | ||
3046 | }; | ||
3047 | |||
3048 | struct wcn36xx_hal_enter_bmps_req_msg { | ||
3049 | struct wcn36xx_hal_msg_header header; | ||
3050 | |||
3051 | u8 bss_index; | ||
3052 | |||
3053 | /* TBTT value derived from the last beacon */ | ||
3054 | #ifndef BUILD_QWPTTSTATIC | ||
3055 | u64 tbtt; | ||
3056 | #endif | ||
3057 | u8 dtim_count; | ||
3058 | |||
3059 | /* DTIM period given to HAL during association may not be valid, if | ||
3060 | * association is based on ProbeRsp instead of beacon. */ | ||
3061 | u8 dtim_period; | ||
3062 | |||
3063 | /* For CCX and 11R Roaming */ | ||
3064 | u32 rssi_filter_period; | ||
3065 | |||
3066 | u32 num_beacon_per_rssi_average; | ||
3067 | u8 rssi_filter_enable; | ||
3068 | } __packed; | ||
3069 | |||
3070 | struct wcn36xx_hal_exit_bmps_req_msg { | ||
3071 | struct wcn36xx_hal_msg_header header; | ||
3072 | |||
3073 | u8 send_data_null; | ||
3074 | u8 bss_index; | ||
3075 | } __packed; | ||
3076 | |||
3077 | struct wcn36xx_hal_missed_beacon_ind_msg { | ||
3078 | struct wcn36xx_hal_msg_header header; | ||
3079 | |||
3080 | u8 bss_index; | ||
3081 | } __packed; | ||
3082 | |||
3083 | /* Beacon Filtering data structures */ | ||
3084 | |||
3085 | /* The above structure would be followed by multiple of below mentioned | ||
3086 | * structure | ||
3087 | */ | ||
3088 | struct beacon_filter_ie { | ||
3089 | u8 element_id; | ||
3090 | u8 check_ie_presence; | ||
3091 | u8 offset; | ||
3092 | u8 value; | ||
3093 | u8 bitmask; | ||
3094 | u8 ref; | ||
3095 | }; | ||
3096 | |||
3097 | struct wcn36xx_hal_add_bcn_filter_req_msg { | ||
3098 | struct wcn36xx_hal_msg_header header; | ||
3099 | |||
3100 | u16 capability_info; | ||
3101 | u16 capability_mask; | ||
3102 | u16 beacon_interval; | ||
3103 | u16 ie_num; | ||
3104 | u8 bss_index; | ||
3105 | u8 reserved; | ||
3106 | }; | ||
3107 | |||
3108 | struct wcn36xx_hal_rem_bcn_filter_req { | ||
3109 | struct wcn36xx_hal_msg_header header; | ||
3110 | |||
3111 | u8 ie_Count; | ||
3112 | u8 rem_ie_id[1]; | ||
3113 | }; | ||
3114 | |||
3115 | #define WCN36XX_HAL_IPV4_ARP_REPLY_OFFLOAD 0 | ||
3116 | #define WCN36XX_HAL_IPV6_NEIGHBOR_DISCOVERY_OFFLOAD 1 | ||
3117 | #define WCN36XX_HAL_IPV6_NS_OFFLOAD 2 | ||
3118 | #define WCN36XX_HAL_IPV6_ADDR_LEN 16 | ||
3119 | #define WCN36XX_HAL_OFFLOAD_DISABLE 0 | ||
3120 | #define WCN36XX_HAL_OFFLOAD_ENABLE 1 | ||
3121 | #define WCN36XX_HAL_OFFLOAD_BCAST_FILTER_ENABLE 0x2 | ||
3122 | #define WCN36XX_HAL_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE \ | ||
3123 | (HAL_OFFLOAD_ENABLE|HAL_OFFLOAD_BCAST_FILTER_ENABLE) | ||
3124 | |||
3125 | struct wcn36xx_hal_ns_offload_params { | ||
3126 | u8 src_ipv6_addr[WCN36XX_HAL_IPV6_ADDR_LEN]; | ||
3127 | u8 self_ipv6_addr[WCN36XX_HAL_IPV6_ADDR_LEN]; | ||
3128 | |||
3129 | /* Only support 2 possible Network Advertisement IPv6 address */ | ||
3130 | u8 target_ipv6_addr1[WCN36XX_HAL_IPV6_ADDR_LEN]; | ||
3131 | u8 target_ipv6_addr2[WCN36XX_HAL_IPV6_ADDR_LEN]; | ||
3132 | |||
3133 | u8 self_addr[ETH_ALEN]; | ||
3134 | u8 src_ipv6_addr_valid:1; | ||
3135 | u8 target_ipv6_addr1_valid:1; | ||
3136 | u8 target_ipv6_addr2_valid:1; | ||
3137 | u8 reserved1:5; | ||
3138 | |||
3139 | /* make it DWORD aligned */ | ||
3140 | u8 reserved2; | ||
3141 | |||
3142 | /* slot index for this offload */ | ||
3143 | u32 slot_index; | ||
3144 | u8 bss_index; | ||
3145 | }; | ||
3146 | |||
3147 | struct wcn36xx_hal_host_offload_req { | ||
3148 | u8 offload_Type; | ||
3149 | |||
3150 | /* enable or disable */ | ||
3151 | u8 enable; | ||
3152 | |||
3153 | union { | ||
3154 | u8 host_ipv4_addr[4]; | ||
3155 | u8 host_ipv6_addr[WCN36XX_HAL_IPV6_ADDR_LEN]; | ||
3156 | } u; | ||
3157 | }; | ||
3158 | |||
3159 | struct wcn36xx_hal_host_offload_req_msg { | ||
3160 | struct wcn36xx_hal_msg_header header; | ||
3161 | struct wcn36xx_hal_host_offload_req host_offload_params; | ||
3162 | struct wcn36xx_hal_ns_offload_params ns_offload_params; | ||
3163 | }; | ||
3164 | |||
3165 | /* Packet Types. */ | ||
3166 | #define WCN36XX_HAL_KEEP_ALIVE_NULL_PKT 1 | ||
3167 | #define WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP 2 | ||
3168 | |||
3169 | /* Enable or disable keep alive */ | ||
3170 | #define WCN36XX_HAL_KEEP_ALIVE_DISABLE 0 | ||
3171 | #define WCN36XX_HAL_KEEP_ALIVE_ENABLE 1 | ||
3172 | #define WCN36XX_KEEP_ALIVE_TIME_PERIOD 30 /* unit: s */ | ||
3173 | |||
3174 | /* Keep Alive request. */ | ||
3175 | struct wcn36xx_hal_keep_alive_req_msg { | ||
3176 | struct wcn36xx_hal_msg_header header; | ||
3177 | |||
3178 | u8 packet_type; | ||
3179 | u32 time_period; | ||
3180 | u8 host_ipv4_addr[WCN36XX_HAL_IPV4_ADDR_LEN]; | ||
3181 | u8 dest_ipv4_addr[WCN36XX_HAL_IPV4_ADDR_LEN]; | ||
3182 | u8 dest_addr[ETH_ALEN]; | ||
3183 | u8 bss_index; | ||
3184 | } __packed; | ||
3185 | |||
3186 | struct wcn36xx_hal_rssi_threshold_req_msg { | ||
3187 | struct wcn36xx_hal_msg_header header; | ||
3188 | |||
3189 | s8 threshold1:8; | ||
3190 | s8 threshold2:8; | ||
3191 | s8 threshold3:8; | ||
3192 | u8 thres1_pos_notify:1; | ||
3193 | u8 thres1_neg_notify:1; | ||
3194 | u8 thres2_pos_notify:1; | ||
3195 | u8 thres2_neg_notify:1; | ||
3196 | u8 thres3_pos_notify:1; | ||
3197 | u8 thres3_neg_notify:1; | ||
3198 | u8 reserved10:2; | ||
3199 | }; | ||
3200 | |||
3201 | struct wcn36xx_hal_enter_uapsd_req_msg { | ||
3202 | struct wcn36xx_hal_msg_header header; | ||
3203 | |||
3204 | u8 bk_delivery:1; | ||
3205 | u8 be_delivery:1; | ||
3206 | u8 vi_delivery:1; | ||
3207 | u8 vo_delivery:1; | ||
3208 | u8 bk_trigger:1; | ||
3209 | u8 be_trigger:1; | ||
3210 | u8 vi_trigger:1; | ||
3211 | u8 vo_trigger:1; | ||
3212 | u8 bss_index; | ||
3213 | }; | ||
3214 | |||
3215 | struct wcn36xx_hal_exit_uapsd_req_msg { | ||
3216 | struct wcn36xx_hal_msg_header header; | ||
3217 | u8 bss_index; | ||
3218 | }; | ||
3219 | |||
3220 | #define WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE 128 | ||
3221 | #define WCN36XX_HAL_WOWL_BCAST_MAX_NUM_PATTERNS 16 | ||
3222 | |||
3223 | struct wcn36xx_hal_wowl_add_bcast_ptrn_req_msg { | ||
3224 | struct wcn36xx_hal_msg_header header; | ||
3225 | |||
3226 | /* Pattern ID */ | ||
3227 | u8 id; | ||
3228 | |||
3229 | /* Pattern byte offset from beginning of the 802.11 packet to start | ||
3230 | * of the wake-up pattern */ | ||
3231 | u8 byte_Offset; | ||
3232 | |||
3233 | /* Non-Zero Pattern size */ | ||
3234 | u8 size; | ||
3235 | |||
3236 | /* Pattern */ | ||
3237 | u8 pattern[WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE]; | ||
3238 | |||
3239 | /* Non-zero pattern mask size */ | ||
3240 | u8 mask_size; | ||
3241 | |||
3242 | /* Pattern mask */ | ||
3243 | u8 mask[WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE]; | ||
3244 | |||
3245 | /* Extra pattern */ | ||
3246 | u8 extra[WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE]; | ||
3247 | |||
3248 | /* Extra pattern mask */ | ||
3249 | u8 mask_extra[WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE]; | ||
3250 | |||
3251 | u8 bss_index; | ||
3252 | }; | ||
3253 | |||
3254 | struct wcn36xx_hal_wow_del_bcast_ptrn_req_msg { | ||
3255 | struct wcn36xx_hal_msg_header header; | ||
3256 | |||
3257 | /* Pattern ID of the wakeup pattern to be deleted */ | ||
3258 | u8 id; | ||
3259 | u8 bss_index; | ||
3260 | }; | ||
3261 | |||
3262 | struct wcn36xx_hal_wowl_enter_req_msg { | ||
3263 | struct wcn36xx_hal_msg_header header; | ||
3264 | |||
3265 | /* Enables/disables magic packet filtering */ | ||
3266 | u8 magic_packet_enable; | ||
3267 | |||
3268 | /* Magic pattern */ | ||
3269 | u8 magic_pattern[ETH_ALEN]; | ||
3270 | |||
3271 | /* Enables/disables packet pattern filtering in firmware. Enabling | ||
3272 | * this flag enables broadcast pattern matching in Firmware. If | ||
3273 | * unicast pattern matching is also desired, | ||
3274 | * ucUcastPatternFilteringEnable flag must be set tot true as well | ||
3275 | */ | ||
3276 | u8 pattern_filtering_enable; | ||
3277 | |||
3278 | /* Enables/disables unicast packet pattern filtering. This flag | ||
3279 | * specifies whether we want to do pattern match on unicast packets | ||
3280 | * as well and not just broadcast packets. This flag has no effect | ||
3281 | * if the ucPatternFilteringEnable (main controlling flag) is set | ||
3282 | * to false | ||
3283 | */ | ||
3284 | u8 ucast_pattern_filtering_enable; | ||
3285 | |||
3286 | /* This configuration is valid only when magicPktEnable=1. It | ||
3287 | * requests hardware to wake up when it receives the Channel Switch | ||
3288 | * Action Frame. | ||
3289 | */ | ||
3290 | u8 wow_channel_switch_receive; | ||
3291 | |||
3292 | /* This configuration is valid only when magicPktEnable=1. It | ||
3293 | * requests hardware to wake up when it receives the | ||
3294 | * Deauthentication Frame. | ||
3295 | */ | ||
3296 | u8 wow_deauth_receive; | ||
3297 | |||
3298 | /* This configuration is valid only when magicPktEnable=1. It | ||
3299 | * requests hardware to wake up when it receives the Disassociation | ||
3300 | * Frame. | ||
3301 | */ | ||
3302 | u8 wow_disassoc_receive; | ||
3303 | |||
3304 | /* This configuration is valid only when magicPktEnable=1. It | ||
3305 | * requests hardware to wake up when it has missed consecutive | ||
3306 | * beacons. This is a hardware register configuration (NOT a | ||
3307 | * firmware configuration). | ||
3308 | */ | ||
3309 | u8 wow_max_missed_beacons; | ||
3310 | |||
3311 | /* This configuration is valid only when magicPktEnable=1. This is | ||
3312 | * a timeout value in units of microsec. It requests hardware to | ||
3313 | * unconditionally wake up after it has stayed in WoWLAN mode for | ||
3314 | * some time. Set 0 to disable this feature. | ||
3315 | */ | ||
3316 | u8 wow_max_sleep; | ||
3317 | |||
3318 | /* This configuration directs the WoW packet filtering to look for | ||
3319 | * EAP-ID requests embedded in EAPOL frames and use this as a wake | ||
3320 | * source. | ||
3321 | */ | ||
3322 | u8 wow_eap_id_request_enable; | ||
3323 | |||
3324 | /* This configuration directs the WoW packet filtering to look for | ||
3325 | * EAPOL-4WAY requests and use this as a wake source. | ||
3326 | */ | ||
3327 | u8 wow_eapol_4way_enable; | ||
3328 | |||
3329 | /* This configuration allows a host wakeup on an network scan | ||
3330 | * offload match. | ||
3331 | */ | ||
3332 | u8 wow_net_scan_offload_match; | ||
3333 | |||
3334 | /* This configuration allows a host wakeup on any GTK rekeying | ||
3335 | * error. | ||
3336 | */ | ||
3337 | u8 wow_gtk_rekey_error; | ||
3338 | |||
3339 | /* This configuration allows a host wakeup on BSS connection loss. | ||
3340 | */ | ||
3341 | u8 wow_bss_connection_loss; | ||
3342 | |||
3343 | u8 bss_index; | ||
3344 | }; | ||
3345 | |||
3346 | struct wcn36xx_hal_wowl_exit_req_msg { | ||
3347 | struct wcn36xx_hal_msg_header header; | ||
3348 | |||
3349 | u8 bss_index; | ||
3350 | }; | ||
3351 | |||
3352 | struct wcn36xx_hal_get_rssi_req_msg { | ||
3353 | struct wcn36xx_hal_msg_header header; | ||
3354 | }; | ||
3355 | |||
3356 | struct wcn36xx_hal_get_roam_rssi_req_msg { | ||
3357 | struct wcn36xx_hal_msg_header header; | ||
3358 | |||
3359 | /* Valid STA Idx for per STA stats request */ | ||
3360 | u32 sta_id; | ||
3361 | }; | ||
3362 | |||
3363 | struct wcn36xx_hal_set_uapsd_ac_params_req_msg { | ||
3364 | struct wcn36xx_hal_msg_header header; | ||
3365 | |||
3366 | /* STA index */ | ||
3367 | u8 sta_idx; | ||
3368 | |||
3369 | /* Access Category */ | ||
3370 | u8 ac; | ||
3371 | |||
3372 | /* User Priority */ | ||
3373 | u8 up; | ||
3374 | |||
3375 | /* Service Interval */ | ||
3376 | u32 service_interval; | ||
3377 | |||
3378 | /* Suspend Interval */ | ||
3379 | u32 suspend_interval; | ||
3380 | |||
3381 | /* Delay Interval */ | ||
3382 | u32 delay_interval; | ||
3383 | }; | ||
3384 | |||
3385 | struct wcn36xx_hal_configure_rxp_filter_req_msg { | ||
3386 | struct wcn36xx_hal_msg_header header; | ||
3387 | |||
3388 | u8 set_mcst_bcst_filter_setting; | ||
3389 | u8 set_mcst_bcst_filter; | ||
3390 | }; | ||
3391 | |||
3392 | struct wcn36xx_hal_enter_imps_rsp_msg { | ||
3393 | struct wcn36xx_hal_msg_header header; | ||
3394 | |||
3395 | /* success or failure */ | ||
3396 | u32 status; | ||
3397 | }; | ||
3398 | |||
3399 | struct wcn36xx_hal_exit_imps_rsp_msg { | ||
3400 | struct wcn36xx_hal_msg_header header; | ||
3401 | |||
3402 | /* success or failure */ | ||
3403 | u32 status; | ||
3404 | }; | ||
3405 | |||
3406 | struct wcn36xx_hal_enter_bmps_rsp_msg { | ||
3407 | struct wcn36xx_hal_msg_header header; | ||
3408 | |||
3409 | /* success or failure */ | ||
3410 | u32 status; | ||
3411 | |||
3412 | u8 bss_index; | ||
3413 | } __packed; | ||
3414 | |||
3415 | struct wcn36xx_hal_exit_bmps_rsp_msg { | ||
3416 | struct wcn36xx_hal_msg_header header; | ||
3417 | |||
3418 | /* success or failure */ | ||
3419 | u32 status; | ||
3420 | |||
3421 | u8 bss_index; | ||
3422 | } __packed; | ||
3423 | |||
3424 | struct wcn36xx_hal_enter_uapsd_rsp_msg { | ||
3425 | struct wcn36xx_hal_msg_header header; | ||
3426 | |||
3427 | /* success or failure */ | ||
3428 | u32 status; | ||
3429 | |||
3430 | u8 bss_index; | ||
3431 | }; | ||
3432 | |||
3433 | struct wcn36xx_hal_exit_uapsd_rsp_msg { | ||
3434 | struct wcn36xx_hal_msg_header header; | ||
3435 | |||
3436 | /* success or failure */ | ||
3437 | u32 status; | ||
3438 | |||
3439 | u8 bss_index; | ||
3440 | }; | ||
3441 | |||
3442 | struct wcn36xx_hal_rssi_notification_ind_msg { | ||
3443 | struct wcn36xx_hal_msg_header header; | ||
3444 | |||
3445 | u32 rssi_thres1_pos_cross:1; | ||
3446 | u32 rssi_thres1_neg_cross:1; | ||
3447 | u32 rssi_thres2_pos_cross:1; | ||
3448 | u32 rssi_thres2_neg_cross:1; | ||
3449 | u32 rssi_thres3_pos_cross:1; | ||
3450 | u32 rssi_thres3_neg_cross:1; | ||
3451 | u32 avg_rssi:8; | ||
3452 | u32 reserved:18; | ||
3453 | |||
3454 | }; | ||
3455 | |||
3456 | struct wcn36xx_hal_get_rssio_rsp_msg { | ||
3457 | struct wcn36xx_hal_msg_header header; | ||
3458 | |||
3459 | /* success or failure */ | ||
3460 | u32 status; | ||
3461 | s8 rssi; | ||
3462 | |||
3463 | }; | ||
3464 | |||
3465 | struct wcn36xx_hal_get_roam_rssi_rsp_msg { | ||
3466 | struct wcn36xx_hal_msg_header header; | ||
3467 | |||
3468 | /* success or failure */ | ||
3469 | u32 status; | ||
3470 | |||
3471 | u8 sta_id; | ||
3472 | s8 rssi; | ||
3473 | }; | ||
3474 | |||
3475 | struct wcn36xx_hal_wowl_enter_rsp_msg { | ||
3476 | struct wcn36xx_hal_msg_header header; | ||
3477 | |||
3478 | /* success or failure */ | ||
3479 | u32 status; | ||
3480 | u8 bss_index; | ||
3481 | }; | ||
3482 | |||
3483 | struct wcn36xx_hal_wowl_exit_rsp_msg { | ||
3484 | struct wcn36xx_hal_msg_header header; | ||
3485 | |||
3486 | /* success or failure */ | ||
3487 | u32 status; | ||
3488 | u8 bss_index; | ||
3489 | }; | ||
3490 | |||
3491 | struct wcn36xx_hal_add_bcn_filter_rsp_msg { | ||
3492 | struct wcn36xx_hal_msg_header header; | ||
3493 | |||
3494 | /* success or failure */ | ||
3495 | u32 status; | ||
3496 | }; | ||
3497 | |||
3498 | struct wcn36xx_hal_rem_bcn_filter_rsp_msg { | ||
3499 | struct wcn36xx_hal_msg_header header; | ||
3500 | |||
3501 | /* success or failure */ | ||
3502 | u32 status; | ||
3503 | }; | ||
3504 | |||
3505 | struct wcn36xx_hal_add_wowl_bcast_ptrn_rsp_msg { | ||
3506 | struct wcn36xx_hal_msg_header header; | ||
3507 | |||
3508 | /* success or failure */ | ||
3509 | u32 status; | ||
3510 | u8 bss_index; | ||
3511 | }; | ||
3512 | |||
3513 | struct wcn36xx_hal_del_wowl_bcast_ptrn_rsp_msg { | ||
3514 | struct wcn36xx_hal_msg_header header; | ||
3515 | |||
3516 | /* success or failure */ | ||
3517 | u32 status; | ||
3518 | u8 bss_index; | ||
3519 | }; | ||
3520 | |||
3521 | struct wcn36xx_hal_host_offload_rsp_msg { | ||
3522 | struct wcn36xx_hal_msg_header header; | ||
3523 | |||
3524 | /* success or failure */ | ||
3525 | u32 status; | ||
3526 | }; | ||
3527 | |||
3528 | struct wcn36xx_hal_keep_alive_rsp_msg { | ||
3529 | struct wcn36xx_hal_msg_header header; | ||
3530 | |||
3531 | /* success or failure */ | ||
3532 | u32 status; | ||
3533 | }; | ||
3534 | |||
3535 | struct wcn36xx_hal_set_rssi_thresh_rsp_msg { | ||
3536 | struct wcn36xx_hal_msg_header header; | ||
3537 | |||
3538 | /* success or failure */ | ||
3539 | u32 status; | ||
3540 | }; | ||
3541 | |||
3542 | struct wcn36xx_hal_set_uapsd_ac_params_rsp_msg { | ||
3543 | struct wcn36xx_hal_msg_header header; | ||
3544 | |||
3545 | /* success or failure */ | ||
3546 | u32 status; | ||
3547 | }; | ||
3548 | |||
3549 | struct wcn36xx_hal_configure_rxp_filter_rsp_msg { | ||
3550 | struct wcn36xx_hal_msg_header header; | ||
3551 | |||
3552 | /* success or failure */ | ||
3553 | u32 status; | ||
3554 | }; | ||
3555 | |||
3556 | struct set_max_tx_pwr_req { | ||
3557 | struct wcn36xx_hal_msg_header header; | ||
3558 | |||
3559 | /* BSSID is needed to identify which session issued this request. | ||
3560 | * As the request has power constraints, this should be applied | ||
3561 | * only to that session */ | ||
3562 | u8 bssid[ETH_ALEN]; | ||
3563 | |||
3564 | u8 self_addr[ETH_ALEN]; | ||
3565 | |||
3566 | /* In request, power == MaxTx power to be used. */ | ||
3567 | u8 power; | ||
3568 | }; | ||
3569 | |||
3570 | struct set_max_tx_pwr_rsp_msg { | ||
3571 | struct wcn36xx_hal_msg_header header; | ||
3572 | |||
3573 | /* power == tx power used for management frames */ | ||
3574 | u8 power; | ||
3575 | |||
3576 | /* success or failure */ | ||
3577 | u32 status; | ||
3578 | }; | ||
3579 | |||
3580 | struct set_tx_pwr_req_msg { | ||
3581 | struct wcn36xx_hal_msg_header header; | ||
3582 | |||
3583 | /* TX Power in milli watts */ | ||
3584 | u32 tx_power; | ||
3585 | |||
3586 | u8 bss_index; | ||
3587 | }; | ||
3588 | |||
3589 | struct set_tx_pwr_rsp_msg { | ||
3590 | struct wcn36xx_hal_msg_header header; | ||
3591 | |||
3592 | /* success or failure */ | ||
3593 | u32 status; | ||
3594 | }; | ||
3595 | |||
3596 | struct get_tx_pwr_req_msg { | ||
3597 | struct wcn36xx_hal_msg_header header; | ||
3598 | |||
3599 | u8 sta_id; | ||
3600 | }; | ||
3601 | |||
3602 | struct get_tx_pwr_rsp_msg { | ||
3603 | struct wcn36xx_hal_msg_header header; | ||
3604 | |||
3605 | /* success or failure */ | ||
3606 | u32 status; | ||
3607 | |||
3608 | /* TX Power in milli watts */ | ||
3609 | u32 tx_power; | ||
3610 | }; | ||
3611 | |||
3612 | struct set_p2p_gonoa_req_msg { | ||
3613 | struct wcn36xx_hal_msg_header header; | ||
3614 | |||
3615 | u8 opp_ps; | ||
3616 | u32 ct_window; | ||
3617 | u8 count; | ||
3618 | u32 duration; | ||
3619 | u32 interval; | ||
3620 | u32 single_noa_duration; | ||
3621 | u8 ps_selection; | ||
3622 | }; | ||
3623 | |||
3624 | struct set_p2p_gonoa_rsp_msg { | ||
3625 | struct wcn36xx_hal_msg_header header; | ||
3626 | |||
3627 | /* success or failure */ | ||
3628 | u32 status; | ||
3629 | }; | ||
3630 | |||
3631 | struct wcn36xx_hal_add_sta_self_req { | ||
3632 | struct wcn36xx_hal_msg_header header; | ||
3633 | |||
3634 | u8 self_addr[ETH_ALEN]; | ||
3635 | u32 status; | ||
3636 | } __packed; | ||
3637 | |||
3638 | struct wcn36xx_hal_add_sta_self_rsp_msg { | ||
3639 | struct wcn36xx_hal_msg_header header; | ||
3640 | |||
3641 | /* success or failure */ | ||
3642 | u32 status; | ||
3643 | |||
3644 | /* Self STA Index */ | ||
3645 | u8 self_sta_index; | ||
3646 | |||
3647 | /* DPU Index (IGTK, PTK, GTK all same) */ | ||
3648 | u8 dpu_index; | ||
3649 | |||
3650 | /* DPU Signature */ | ||
3651 | u8 dpu_signature; | ||
3652 | } __packed; | ||
3653 | |||
3654 | struct wcn36xx_hal_del_sta_self_req_msg { | ||
3655 | struct wcn36xx_hal_msg_header header; | ||
3656 | |||
3657 | u8 self_addr[ETH_ALEN]; | ||
3658 | } __packed; | ||
3659 | |||
3660 | struct wcn36xx_hal_del_sta_self_rsp_msg { | ||
3661 | struct wcn36xx_hal_msg_header header; | ||
3662 | |||
3663 | /*success or failure */ | ||
3664 | u32 status; | ||
3665 | |||
3666 | u8 self_addr[ETH_ALEN]; | ||
3667 | } __packed; | ||
3668 | |||
3669 | struct aggr_add_ts_req { | ||
3670 | struct wcn36xx_hal_msg_header header; | ||
3671 | |||
3672 | /* Station Index */ | ||
3673 | u16 sta_idx; | ||
3674 | |||
3675 | /* TSPEC handler uniquely identifying a TSPEC for a STA in a BSS. | ||
3676 | * This will carry the bitmap with the bit positions representing | ||
3677 | * different AC.s */ | ||
3678 | u16 tspec_index; | ||
3679 | |||
3680 | /* Tspec info per AC To program TPE with required parameters */ | ||
3681 | struct wcn36xx_hal_tspec_ie tspec[WCN36XX_HAL_MAX_AC]; | ||
3682 | |||
3683 | /* U-APSD Flags: 1b per AC. Encoded as follows: | ||
3684 | b7 b6 b5 b4 b3 b2 b1 b0 = | ||
3685 | X X X X BE BK VI VO */ | ||
3686 | u8 uapsd; | ||
3687 | |||
3688 | /* These parameters are for all the access categories */ | ||
3689 | |||
3690 | /* Service Interval */ | ||
3691 | u32 service_interval[WCN36XX_HAL_MAX_AC]; | ||
3692 | |||
3693 | /* Suspend Interval */ | ||
3694 | u32 suspend_interval[WCN36XX_HAL_MAX_AC]; | ||
3695 | |||
3696 | /* Delay Interval */ | ||
3697 | u32 delay_interval[WCN36XX_HAL_MAX_AC]; | ||
3698 | }; | ||
3699 | |||
3700 | struct aggr_add_ts_rsp_msg { | ||
3701 | struct wcn36xx_hal_msg_header header; | ||
3702 | |||
3703 | /* success or failure */ | ||
3704 | u32 status0; | ||
3705 | |||
3706 | /* FIXME PRIMA for future use for 11R */ | ||
3707 | u32 status1; | ||
3708 | }; | ||
3709 | |||
3710 | struct wcn36xx_hal_configure_apps_cpu_wakeup_state_req_msg { | ||
3711 | struct wcn36xx_hal_msg_header header; | ||
3712 | |||
3713 | u8 is_apps_cpu_awake; | ||
3714 | }; | ||
3715 | |||
3716 | struct wcn36xx_hal_configure_apps_cpu_wakeup_state_rsp_msg { | ||
3717 | struct wcn36xx_hal_msg_header header; | ||
3718 | |||
3719 | /* success or failure */ | ||
3720 | u32 status; | ||
3721 | }; | ||
3722 | |||
3723 | struct wcn36xx_hal_dump_cmd_req_msg { | ||
3724 | struct wcn36xx_hal_msg_header header; | ||
3725 | |||
3726 | u32 arg1; | ||
3727 | u32 arg2; | ||
3728 | u32 arg3; | ||
3729 | u32 arg4; | ||
3730 | u32 arg5; | ||
3731 | } __packed; | ||
3732 | |||
3733 | struct wcn36xx_hal_dump_cmd_rsp_msg { | ||
3734 | struct wcn36xx_hal_msg_header header; | ||
3735 | |||
3736 | /* success or failure */ | ||
3737 | u32 status; | ||
3738 | |||
3739 | /* Length of the responce message */ | ||
3740 | u32 rsp_length; | ||
3741 | |||
3742 | /* FIXME: Currently considering the the responce will be less than | ||
3743 | * 100bytes */ | ||
3744 | u8 rsp_buffer[DUMPCMD_RSP_BUFFER]; | ||
3745 | } __packed; | ||
3746 | |||
3747 | #define WLAN_COEX_IND_DATA_SIZE (4) | ||
3748 | #define WLAN_COEX_IND_TYPE_DISABLE_HB_MONITOR (0) | ||
3749 | #define WLAN_COEX_IND_TYPE_ENABLE_HB_MONITOR (1) | ||
3750 | |||
3751 | struct coex_ind_msg { | ||
3752 | struct wcn36xx_hal_msg_header header; | ||
3753 | |||
3754 | /* Coex Indication Type */ | ||
3755 | u32 type; | ||
3756 | |||
3757 | /* Coex Indication Data */ | ||
3758 | u32 data[WLAN_COEX_IND_DATA_SIZE]; | ||
3759 | }; | ||
3760 | |||
3761 | struct wcn36xx_hal_tx_compl_ind_msg { | ||
3762 | struct wcn36xx_hal_msg_header header; | ||
3763 | |||
3764 | /* Tx Complete Indication Success or Failure */ | ||
3765 | u32 status; | ||
3766 | }; | ||
3767 | |||
3768 | struct wcn36xx_hal_wlan_host_suspend_ind_msg { | ||
3769 | struct wcn36xx_hal_msg_header header; | ||
3770 | |||
3771 | u32 configured_mcst_bcst_filter_setting; | ||
3772 | u32 active_session_count; | ||
3773 | }; | ||
3774 | |||
3775 | struct wcn36xx_hal_wlan_exclude_unencrpted_ind_msg { | ||
3776 | struct wcn36xx_hal_msg_header header; | ||
3777 | |||
3778 | u8 dot11_exclude_unencrypted; | ||
3779 | u8 bssid[ETH_ALEN]; | ||
3780 | }; | ||
3781 | |||
3782 | struct noa_attr_ind_msg { | ||
3783 | struct wcn36xx_hal_msg_header header; | ||
3784 | |||
3785 | u8 index; | ||
3786 | u8 opp_ps_flag; | ||
3787 | u16 ctwin; | ||
3788 | |||
3789 | u16 noa1_interval_count; | ||
3790 | u16 bss_index; | ||
3791 | u32 noa1_duration; | ||
3792 | u32 noa1_interval; | ||
3793 | u32 noa1_starttime; | ||
3794 | |||
3795 | u16 noa2_interval_count; | ||
3796 | u16 reserved2; | ||
3797 | u32 noa2_duration; | ||
3798 | u32 noa2_interval; | ||
3799 | u32 noa2_start_time; | ||
3800 | |||
3801 | u32 status; | ||
3802 | }; | ||
3803 | |||
3804 | struct noa_start_ind_msg { | ||
3805 | struct wcn36xx_hal_msg_header header; | ||
3806 | |||
3807 | u32 status; | ||
3808 | u32 bss_index; | ||
3809 | }; | ||
3810 | |||
3811 | struct wcn36xx_hal_wlan_host_resume_req_msg { | ||
3812 | struct wcn36xx_hal_msg_header header; | ||
3813 | |||
3814 | u8 configured_mcst_bcst_filter_setting; | ||
3815 | }; | ||
3816 | |||
3817 | struct wcn36xx_hal_host_resume_rsp_msg { | ||
3818 | struct wcn36xx_hal_msg_header header; | ||
3819 | |||
3820 | /* success or failure */ | ||
3821 | u32 status; | ||
3822 | }; | ||
3823 | |||
3824 | struct wcn36xx_hal_del_ba_ind_msg { | ||
3825 | struct wcn36xx_hal_msg_header header; | ||
3826 | |||
3827 | u16 sta_idx; | ||
3828 | |||
3829 | /* Peer MAC Address, whose BA session has timed out */ | ||
3830 | u8 peer_addr[ETH_ALEN]; | ||
3831 | |||
3832 | /* TID for which a BA session timeout is being triggered */ | ||
3833 | u8 ba_tid; | ||
3834 | |||
3835 | /* DELBA direction | ||
3836 | * 1 - Originator | ||
3837 | * 0 - Recipient | ||
3838 | */ | ||
3839 | u8 direction; | ||
3840 | |||
3841 | u32 reason_code; | ||
3842 | |||
3843 | /* TO SUPPORT BT-AMP */ | ||
3844 | u8 bssid[ETH_ALEN]; | ||
3845 | }; | ||
3846 | |||
3847 | /* PNO Messages */ | ||
3848 | |||
3849 | /* Max number of channels that a network can be found on */ | ||
3850 | #define WCN36XX_HAL_PNO_MAX_NETW_CHANNELS 26 | ||
3851 | |||
3852 | /* Max number of channels that a network can be found on */ | ||
3853 | #define WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX 60 | ||
3854 | |||
3855 | /* Maximum numbers of networks supported by PNO */ | ||
3856 | #define WCN36XX_HAL_PNO_MAX_SUPP_NETWORKS 16 | ||
3857 | |||
3858 | /* The number of scan time intervals that can be programmed into PNO */ | ||
3859 | #define WCN36XX_HAL_PNO_MAX_SCAN_TIMERS 10 | ||
3860 | |||
3861 | /* Maximum size of the probe template */ | ||
3862 | #define WCN36XX_HAL_PNO_MAX_PROBE_SIZE 450 | ||
3863 | |||
3864 | /* Type of PNO enabling: | ||
3865 | * | ||
3866 | * Immediate - scanning will start immediately and PNO procedure will be | ||
3867 | * repeated based on timer | ||
3868 | * | ||
3869 | * Suspend - scanning will start at suspend | ||
3870 | * | ||
3871 | * Resume - scanning will start on system resume | ||
3872 | */ | ||
3873 | enum pno_mode { | ||
3874 | PNO_MODE_IMMEDIATE, | ||
3875 | PNO_MODE_ON_SUSPEND, | ||
3876 | PNO_MODE_ON_RESUME, | ||
3877 | PNO_MODE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
3878 | }; | ||
3879 | |||
3880 | /* Authentication type */ | ||
3881 | enum auth_type { | ||
3882 | AUTH_TYPE_ANY = 0, | ||
3883 | AUTH_TYPE_OPEN_SYSTEM = 1, | ||
3884 | |||
3885 | /* Upper layer authentication types */ | ||
3886 | AUTH_TYPE_WPA = 2, | ||
3887 | AUTH_TYPE_WPA_PSK = 3, | ||
3888 | |||
3889 | AUTH_TYPE_RSN = 4, | ||
3890 | AUTH_TYPE_RSN_PSK = 5, | ||
3891 | AUTH_TYPE_FT_RSN = 6, | ||
3892 | AUTH_TYPE_FT_RSN_PSK = 7, | ||
3893 | AUTH_TYPE_WAPI_WAI_CERTIFICATE = 8, | ||
3894 | AUTH_TYPE_WAPI_WAI_PSK = 9, | ||
3895 | |||
3896 | AUTH_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
3897 | }; | ||
3898 | |||
3899 | /* Encryption type */ | ||
3900 | enum ed_type { | ||
3901 | ED_ANY = 0, | ||
3902 | ED_NONE = 1, | ||
3903 | ED_WEP = 2, | ||
3904 | ED_TKIP = 3, | ||
3905 | ED_CCMP = 4, | ||
3906 | ED_WPI = 5, | ||
3907 | |||
3908 | ED_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
3909 | }; | ||
3910 | |||
3911 | /* SSID broadcast type */ | ||
3912 | enum ssid_bcast_type { | ||
3913 | BCAST_UNKNOWN = 0, | ||
3914 | BCAST_NORMAL = 1, | ||
3915 | BCAST_HIDDEN = 2, | ||
3916 | |||
3917 | BCAST_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
3918 | }; | ||
3919 | |||
3920 | /* The network description for which PNO will have to look for */ | ||
3921 | struct network_type { | ||
3922 | /* SSID of the BSS */ | ||
3923 | struct wcn36xx_hal_mac_ssid ssid; | ||
3924 | |||
3925 | /* Authentication type for the network */ | ||
3926 | enum auth_type authentication; | ||
3927 | |||
3928 | /* Encryption type for the network */ | ||
3929 | enum ed_type encryption; | ||
3930 | |||
3931 | /* Indicate the channel on which the Network can be found 0 - if | ||
3932 | * all channels */ | ||
3933 | u8 channel_count; | ||
3934 | u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS]; | ||
3935 | |||
3936 | /* Indicates the RSSI threshold for the network to be considered */ | ||
3937 | u8 rssi_threshold; | ||
3938 | }; | ||
3939 | |||
3940 | struct scan_timer { | ||
3941 | /* How much it should wait */ | ||
3942 | u32 value; | ||
3943 | |||
3944 | /* How many times it should repeat that wait value 0 - keep using | ||
3945 | * this timer until PNO is disabled */ | ||
3946 | u32 repeat; | ||
3947 | |||
3948 | /* e.g: 2 3 4 0 - it will wait 2s between consecutive scans for 3 | ||
3949 | * times - after that it will wait 4s between consecutive scans | ||
3950 | * until disabled */ | ||
3951 | }; | ||
3952 | |||
3953 | /* The network parameters to be sent to the PNO algorithm */ | ||
3954 | struct scan_timers_type { | ||
3955 | /* set to 0 if you wish for PNO to use its default telescopic timer */ | ||
3956 | u8 count; | ||
3957 | |||
3958 | /* A set value represents the amount of time that PNO will wait | ||
3959 | * between two consecutive scan procedures If the desired is for a | ||
3960 | * uniform timer that fires always at the exact same interval - one | ||
3961 | * single value is to be set If there is a desire for a more | ||
3962 | * complex - telescopic like timer multiple values can be set - | ||
3963 | * once PNO reaches the end of the array it will continue scanning | ||
3964 | * at intervals presented by the last value */ | ||
3965 | struct scan_timer values[WCN36XX_HAL_PNO_MAX_SCAN_TIMERS]; | ||
3966 | }; | ||
3967 | |||
3968 | /* Preferred network list request */ | ||
3969 | struct set_pref_netw_list_req { | ||
3970 | struct wcn36xx_hal_msg_header header; | ||
3971 | |||
3972 | /* Enable PNO */ | ||
3973 | u32 enable; | ||
3974 | |||
3975 | /* Immediate, On Suspend, On Resume */ | ||
3976 | enum pno_mode mode; | ||
3977 | |||
3978 | /* Number of networks sent for PNO */ | ||
3979 | u32 networks_count; | ||
3980 | |||
3981 | /* The networks that PNO needs to look for */ | ||
3982 | struct network_type networks[WCN36XX_HAL_PNO_MAX_SUPP_NETWORKS]; | ||
3983 | |||
3984 | /* The scan timers required for PNO */ | ||
3985 | struct scan_timers_type scan_timers; | ||
3986 | |||
3987 | /* Probe template for 2.4GHz band */ | ||
3988 | u16 band_24g_probe_size; | ||
3989 | u8 band_24g_probe_template[WCN36XX_HAL_PNO_MAX_PROBE_SIZE]; | ||
3990 | |||
3991 | /* Probe template for 5GHz band */ | ||
3992 | u16 band_5g_probe_size; | ||
3993 | u8 band_5g_probe_template[WCN36XX_HAL_PNO_MAX_PROBE_SIZE]; | ||
3994 | }; | ||
3995 | |||
3996 | /* The network description for which PNO will have to look for */ | ||
3997 | struct network_type_new { | ||
3998 | /* SSID of the BSS */ | ||
3999 | struct wcn36xx_hal_mac_ssid ssid; | ||
4000 | |||
4001 | /* Authentication type for the network */ | ||
4002 | enum auth_type authentication; | ||
4003 | |||
4004 | /* Encryption type for the network */ | ||
4005 | enum ed_type encryption; | ||
4006 | |||
4007 | /* SSID broadcast type, normal, hidden or unknown */ | ||
4008 | enum ssid_bcast_type bcast_network_type; | ||
4009 | |||
4010 | /* Indicate the channel on which the Network can be found 0 - if | ||
4011 | * all channels */ | ||
4012 | u8 channel_count; | ||
4013 | u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS]; | ||
4014 | |||
4015 | /* Indicates the RSSI threshold for the network to be considered */ | ||
4016 | u8 rssi_threshold; | ||
4017 | }; | ||
4018 | |||
4019 | /* Preferred network list request new */ | ||
4020 | struct set_pref_netw_list_req_new { | ||
4021 | struct wcn36xx_hal_msg_header header; | ||
4022 | |||
4023 | /* Enable PNO */ | ||
4024 | u32 enable; | ||
4025 | |||
4026 | /* Immediate, On Suspend, On Resume */ | ||
4027 | enum pno_mode mode; | ||
4028 | |||
4029 | /* Number of networks sent for PNO */ | ||
4030 | u32 networks_count; | ||
4031 | |||
4032 | /* The networks that PNO needs to look for */ | ||
4033 | struct network_type_new networks[WCN36XX_HAL_PNO_MAX_SUPP_NETWORKS]; | ||
4034 | |||
4035 | /* The scan timers required for PNO */ | ||
4036 | struct scan_timers_type scan_timers; | ||
4037 | |||
4038 | /* Probe template for 2.4GHz band */ | ||
4039 | u16 band_24g_probe_size; | ||
4040 | u8 band_24g_probe_template[WCN36XX_HAL_PNO_MAX_PROBE_SIZE]; | ||
4041 | |||
4042 | /* Probe template for 5GHz band */ | ||
4043 | u16 band_5g_probe_size; | ||
4044 | u8 band_5g_probe_template[WCN36XX_HAL_PNO_MAX_PROBE_SIZE]; | ||
4045 | }; | ||
4046 | |||
4047 | /* Preferred network list response */ | ||
4048 | struct set_pref_netw_list_resp { | ||
4049 | struct wcn36xx_hal_msg_header header; | ||
4050 | |||
4051 | /* status of the request - just to indicate that PNO has | ||
4052 | * acknowledged the request and will start scanning */ | ||
4053 | u32 status; | ||
4054 | }; | ||
4055 | |||
4056 | /* Preferred network found indication */ | ||
4057 | struct pref_netw_found_ind { | ||
4058 | |||
4059 | struct wcn36xx_hal_msg_header header; | ||
4060 | |||
4061 | /* Network that was found with the highest RSSI */ | ||
4062 | struct wcn36xx_hal_mac_ssid ssid; | ||
4063 | |||
4064 | /* Indicates the RSSI */ | ||
4065 | u8 rssi; | ||
4066 | }; | ||
4067 | |||
4068 | /* RSSI Filter request */ | ||
4069 | struct set_rssi_filter_req { | ||
4070 | struct wcn36xx_hal_msg_header header; | ||
4071 | |||
4072 | /* RSSI Threshold */ | ||
4073 | u8 rssi_threshold; | ||
4074 | }; | ||
4075 | |||
4076 | /* Set RSSI filter resp */ | ||
4077 | struct set_rssi_filter_resp { | ||
4078 | struct wcn36xx_hal_msg_header header; | ||
4079 | |||
4080 | /* status of the request */ | ||
4081 | u32 status; | ||
4082 | }; | ||
4083 | |||
4084 | /* Update scan params - sent from host to PNO to be used during PNO | ||
4085 | * scanningx */ | ||
4086 | struct wcn36xx_hal_update_scan_params_req { | ||
4087 | |||
4088 | struct wcn36xx_hal_msg_header header; | ||
4089 | |||
4090 | /* Host setting for 11d */ | ||
4091 | u8 dot11d_enabled; | ||
4092 | |||
4093 | /* Lets PNO know that host has determined the regulatory domain */ | ||
4094 | u8 dot11d_resolved; | ||
4095 | |||
4096 | /* Channels on which PNO is allowed to scan */ | ||
4097 | u8 channel_count; | ||
4098 | u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS]; | ||
4099 | |||
4100 | /* Minimum channel time */ | ||
4101 | u16 active_min_ch_time; | ||
4102 | |||
4103 | /* Maximum channel time */ | ||
4104 | u16 active_max_ch_time; | ||
4105 | |||
4106 | /* Minimum channel time */ | ||
4107 | u16 passive_min_ch_time; | ||
4108 | |||
4109 | /* Maximum channel time */ | ||
4110 | u16 passive_max_ch_time; | ||
4111 | |||
4112 | /* Cb State */ | ||
4113 | enum phy_chan_bond_state state; | ||
4114 | } __packed; | ||
4115 | |||
4116 | /* Update scan params - sent from host to PNO to be used during PNO | ||
4117 | * scanningx */ | ||
4118 | struct update_scan_params_req_ex { | ||
4119 | |||
4120 | struct wcn36xx_hal_msg_header header; | ||
4121 | |||
4122 | /* Host setting for 11d */ | ||
4123 | u8 dot11d_enabled; | ||
4124 | |||
4125 | /* Lets PNO know that host has determined the regulatory domain */ | ||
4126 | u8 dot11d_resolved; | ||
4127 | |||
4128 | /* Channels on which PNO is allowed to scan */ | ||
4129 | u8 channel_count; | ||
4130 | u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX]; | ||
4131 | |||
4132 | /* Minimum channel time */ | ||
4133 | u16 active_min_ch_time; | ||
4134 | |||
4135 | /* Maximum channel time */ | ||
4136 | u16 active_max_ch_time; | ||
4137 | |||
4138 | /* Minimum channel time */ | ||
4139 | u16 passive_min_ch_time; | ||
4140 | |||
4141 | /* Maximum channel time */ | ||
4142 | u16 passive_max_ch_time; | ||
4143 | |||
4144 | /* Cb State */ | ||
4145 | enum phy_chan_bond_state state; | ||
4146 | }; | ||
4147 | |||
4148 | /* Update scan params - sent from host to PNO to be used during PNO | ||
4149 | * scanningx */ | ||
4150 | struct wcn36xx_hal_update_scan_params_resp { | ||
4151 | |||
4152 | struct wcn36xx_hal_msg_header header; | ||
4153 | |||
4154 | /* status of the request */ | ||
4155 | u32 status; | ||
4156 | } __packed; | ||
4157 | |||
4158 | struct wcn36xx_hal_set_tx_per_tracking_req_msg { | ||
4159 | struct wcn36xx_hal_msg_header header; | ||
4160 | |||
4161 | /* 0: disable, 1:enable */ | ||
4162 | u8 tx_per_tracking_enable; | ||
4163 | |||
4164 | /* Check period, unit is sec. */ | ||
4165 | u8 tx_per_tracking_period; | ||
4166 | |||
4167 | /* (Fail TX packet)/(Total TX packet) ratio, the unit is 10%. */ | ||
4168 | u8 tx_per_tracking_ratio; | ||
4169 | |||
4170 | /* A watermark of check number, once the tx packet exceed this | ||
4171 | * number, we do the check, default is 5 */ | ||
4172 | u32 tx_per_tracking_watermark; | ||
4173 | }; | ||
4174 | |||
4175 | struct wcn36xx_hal_set_tx_per_tracking_rsp_msg { | ||
4176 | struct wcn36xx_hal_msg_header header; | ||
4177 | |||
4178 | /* success or failure */ | ||
4179 | u32 status; | ||
4180 | |||
4181 | }; | ||
4182 | |||
4183 | struct tx_per_hit_ind_msg { | ||
4184 | struct wcn36xx_hal_msg_header header; | ||
4185 | }; | ||
4186 | |||
4187 | /* Packet Filtering Definitions Begin */ | ||
4188 | #define WCN36XX_HAL_PROTOCOL_DATA_LEN 8 | ||
4189 | #define WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS 240 | ||
4190 | #define WCN36XX_HAL_MAX_NUM_FILTERS 20 | ||
4191 | #define WCN36XX_HAL_MAX_CMP_PER_FILTER 10 | ||
4192 | |||
4193 | enum wcn36xx_hal_receive_packet_filter_type { | ||
4194 | HAL_RCV_FILTER_TYPE_INVALID, | ||
4195 | HAL_RCV_FILTER_TYPE_FILTER_PKT, | ||
4196 | HAL_RCV_FILTER_TYPE_BUFFER_PKT, | ||
4197 | HAL_RCV_FILTER_TYPE_MAX_ENUM_SIZE | ||
4198 | }; | ||
4199 | |||
4200 | enum wcn36xx_hal_rcv_pkt_flt_protocol_type { | ||
4201 | HAL_FILTER_PROTO_TYPE_INVALID, | ||
4202 | HAL_FILTER_PROTO_TYPE_MAC, | ||
4203 | HAL_FILTER_PROTO_TYPE_ARP, | ||
4204 | HAL_FILTER_PROTO_TYPE_IPV4, | ||
4205 | HAL_FILTER_PROTO_TYPE_IPV6, | ||
4206 | HAL_FILTER_PROTO_TYPE_UDP, | ||
4207 | HAL_FILTER_PROTO_TYPE_MAX | ||
4208 | }; | ||
4209 | |||
4210 | enum wcn36xx_hal_rcv_pkt_flt_cmp_flag_type { | ||
4211 | HAL_FILTER_CMP_TYPE_INVALID, | ||
4212 | HAL_FILTER_CMP_TYPE_EQUAL, | ||
4213 | HAL_FILTER_CMP_TYPE_MASK_EQUAL, | ||
4214 | HAL_FILTER_CMP_TYPE_NOT_EQUAL, | ||
4215 | HAL_FILTER_CMP_TYPE_MAX | ||
4216 | }; | ||
4217 | |||
4218 | struct wcn36xx_hal_rcv_pkt_filter_params { | ||
4219 | u8 protocol_layer; | ||
4220 | u8 cmp_flag; | ||
4221 | |||
4222 | /* Length of the data to compare */ | ||
4223 | u16 data_length; | ||
4224 | |||
4225 | /* from start of the respective frame header */ | ||
4226 | u8 data_offset; | ||
4227 | |||
4228 | /* Reserved field */ | ||
4229 | u8 reserved; | ||
4230 | |||
4231 | /* Data to compare */ | ||
4232 | u8 compare_data[WCN36XX_HAL_PROTOCOL_DATA_LEN]; | ||
4233 | |||
4234 | /* Mask to be applied on the received packet data before compare */ | ||
4235 | u8 data_mask[WCN36XX_HAL_PROTOCOL_DATA_LEN]; | ||
4236 | }; | ||
4237 | |||
4238 | struct wcn36xx_hal_sessionized_rcv_pkt_filter_cfg_type { | ||
4239 | u8 id; | ||
4240 | u8 type; | ||
4241 | u8 params_count; | ||
4242 | u32 coleasce_time; | ||
4243 | u8 bss_index; | ||
4244 | struct wcn36xx_hal_rcv_pkt_filter_params params[1]; | ||
4245 | }; | ||
4246 | |||
4247 | struct wcn36xx_hal_set_rcv_pkt_filter_req_msg { | ||
4248 | struct wcn36xx_hal_msg_header header; | ||
4249 | |||
4250 | u8 id; | ||
4251 | u8 type; | ||
4252 | u8 params_count; | ||
4253 | u32 coalesce_time; | ||
4254 | struct wcn36xx_hal_rcv_pkt_filter_params params[1]; | ||
4255 | }; | ||
4256 | |||
4257 | struct wcn36xx_hal_rcv_flt_mc_addr_list_type { | ||
4258 | /* from start of the respective frame header */ | ||
4259 | u8 data_offset; | ||
4260 | |||
4261 | u32 mc_addr_count; | ||
4262 | u8 mc_addr[ETH_ALEN][WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS]; | ||
4263 | u8 bss_index; | ||
4264 | }; | ||
4265 | |||
4266 | struct wcn36xx_hal_set_pkt_filter_rsp_msg { | ||
4267 | struct wcn36xx_hal_msg_header header; | ||
4268 | |||
4269 | /* success or failure */ | ||
4270 | u32 status; | ||
4271 | |||
4272 | u8 bss_index; | ||
4273 | }; | ||
4274 | |||
4275 | struct wcn36xx_hal_rcv_flt_pkt_match_cnt_req_msg { | ||
4276 | struct wcn36xx_hal_msg_header header; | ||
4277 | |||
4278 | u8 bss_index; | ||
4279 | }; | ||
4280 | |||
4281 | struct wcn36xx_hal_rcv_flt_pkt_match_cnt { | ||
4282 | u8 id; | ||
4283 | u32 match_cnt; | ||
4284 | }; | ||
4285 | |||
4286 | struct wcn36xx_hal_rcv_flt_pkt_match_cnt_rsp_msg { | ||
4287 | struct wcn36xx_hal_msg_header header; | ||
4288 | |||
4289 | /* Success or Failure */ | ||
4290 | u32 status; | ||
4291 | |||
4292 | u32 match_count; | ||
4293 | struct wcn36xx_hal_rcv_flt_pkt_match_cnt | ||
4294 | matches[WCN36XX_HAL_MAX_NUM_FILTERS]; | ||
4295 | u8 bss_index; | ||
4296 | }; | ||
4297 | |||
4298 | struct wcn36xx_hal_rcv_flt_pkt_clear_param { | ||
4299 | /* only valid for response message */ | ||
4300 | u32 status; | ||
4301 | u8 id; | ||
4302 | u8 bss_index; | ||
4303 | }; | ||
4304 | |||
4305 | struct wcn36xx_hal_rcv_flt_pkt_clear_req_msg { | ||
4306 | struct wcn36xx_hal_msg_header header; | ||
4307 | struct wcn36xx_hal_rcv_flt_pkt_clear_param param; | ||
4308 | }; | ||
4309 | |||
4310 | struct wcn36xx_hal_rcv_flt_pkt_clear_rsp_msg { | ||
4311 | struct wcn36xx_hal_msg_header header; | ||
4312 | struct wcn36xx_hal_rcv_flt_pkt_clear_param param; | ||
4313 | }; | ||
4314 | |||
4315 | struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg { | ||
4316 | struct wcn36xx_hal_msg_header header; | ||
4317 | struct wcn36xx_hal_rcv_flt_mc_addr_list_type mc_addr_list; | ||
4318 | }; | ||
4319 | |||
4320 | struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_rsp_msg { | ||
4321 | struct wcn36xx_hal_msg_header header; | ||
4322 | u32 status; | ||
4323 | u8 bss_index; | ||
4324 | }; | ||
4325 | |||
4326 | /* Packet Filtering Definitions End */ | ||
4327 | |||
4328 | struct wcn36xx_hal_set_power_params_req_msg { | ||
4329 | struct wcn36xx_hal_msg_header header; | ||
4330 | |||
4331 | /* Ignore DTIM */ | ||
4332 | u32 ignore_dtim; | ||
4333 | |||
4334 | /* DTIM Period */ | ||
4335 | u32 dtim_period; | ||
4336 | |||
4337 | /* Listen Interval */ | ||
4338 | u32 listen_interval; | ||
4339 | |||
4340 | /* Broadcast Multicast Filter */ | ||
4341 | u32 bcast_mcast_filter; | ||
4342 | |||
4343 | /* Beacon Early Termination */ | ||
4344 | u32 enable_bet; | ||
4345 | |||
4346 | /* Beacon Early Termination Interval */ | ||
4347 | u32 bet_interval; | ||
4348 | } __packed; | ||
4349 | |||
4350 | struct wcn36xx_hal_set_power_params_resp { | ||
4351 | |||
4352 | struct wcn36xx_hal_msg_header header; | ||
4353 | |||
4354 | /* status of the request */ | ||
4355 | u32 status; | ||
4356 | } __packed; | ||
4357 | |||
4358 | /* Capability bitmap exchange definitions and macros starts */ | ||
4359 | |||
4360 | enum place_holder_in_cap_bitmap { | ||
4361 | MCC = 0, | ||
4362 | P2P = 1, | ||
4363 | DOT11AC = 2, | ||
4364 | SLM_SESSIONIZATION = 3, | ||
4365 | DOT11AC_OPMODE = 4, | ||
4366 | SAP32STA = 5, | ||
4367 | TDLS = 6, | ||
4368 | P2P_GO_NOA_DECOUPLE_INIT_SCAN = 7, | ||
4369 | WLANACTIVE_OFFLOAD = 8, | ||
4370 | BEACON_OFFLOAD = 9, | ||
4371 | SCAN_OFFLOAD = 10, | ||
4372 | ROAM_OFFLOAD = 11, | ||
4373 | BCN_MISS_OFFLOAD = 12, | ||
4374 | STA_POWERSAVE = 13, | ||
4375 | STA_ADVANCED_PWRSAVE = 14, | ||
4376 | AP_UAPSD = 15, | ||
4377 | AP_DFS = 16, | ||
4378 | BLOCKACK = 17, | ||
4379 | PHY_ERR = 18, | ||
4380 | BCN_FILTER = 19, | ||
4381 | RTT = 20, | ||
4382 | RATECTRL = 21, | ||
4383 | WOW = 22, | ||
4384 | MAX_FEATURE_SUPPORTED = 128, | ||
4385 | }; | ||
4386 | |||
4387 | struct wcn36xx_hal_feat_caps_msg { | ||
4388 | |||
4389 | struct wcn36xx_hal_msg_header header; | ||
4390 | |||
4391 | u32 feat_caps[4]; | ||
4392 | } __packed; | ||
4393 | |||
4394 | /* status codes to help debug rekey failures */ | ||
4395 | enum gtk_rekey_status { | ||
4396 | WCN36XX_HAL_GTK_REKEY_STATUS_SUCCESS = 0, | ||
4397 | |||
4398 | /* rekey detected, but not handled */ | ||
4399 | WCN36XX_HAL_GTK_REKEY_STATUS_NOT_HANDLED = 1, | ||
4400 | |||
4401 | /* MIC check error on M1 */ | ||
4402 | WCN36XX_HAL_GTK_REKEY_STATUS_MIC_ERROR = 2, | ||
4403 | |||
4404 | /* decryption error on M1 */ | ||
4405 | WCN36XX_HAL_GTK_REKEY_STATUS_DECRYPT_ERROR = 3, | ||
4406 | |||
4407 | /* M1 replay detected */ | ||
4408 | WCN36XX_HAL_GTK_REKEY_STATUS_REPLAY_ERROR = 4, | ||
4409 | |||
4410 | /* missing GTK key descriptor in M1 */ | ||
4411 | WCN36XX_HAL_GTK_REKEY_STATUS_MISSING_KDE = 5, | ||
4412 | |||
4413 | /* missing iGTK key descriptor in M1 */ | ||
4414 | WCN36XX_HAL_GTK_REKEY_STATUS_MISSING_IGTK_KDE = 6, | ||
4415 | |||
4416 | /* key installation error */ | ||
4417 | WCN36XX_HAL_GTK_REKEY_STATUS_INSTALL_ERROR = 7, | ||
4418 | |||
4419 | /* iGTK key installation error */ | ||
4420 | WCN36XX_HAL_GTK_REKEY_STATUS_IGTK_INSTALL_ERROR = 8, | ||
4421 | |||
4422 | /* GTK rekey M2 response TX error */ | ||
4423 | WCN36XX_HAL_GTK_REKEY_STATUS_RESP_TX_ERROR = 9, | ||
4424 | |||
4425 | /* non-specific general error */ | ||
4426 | WCN36XX_HAL_GTK_REKEY_STATUS_GEN_ERROR = 255 | ||
4427 | }; | ||
4428 | |||
4429 | /* wake reason types */ | ||
4430 | enum wake_reason_type { | ||
4431 | WCN36XX_HAL_WAKE_REASON_NONE = 0, | ||
4432 | |||
4433 | /* magic packet match */ | ||
4434 | WCN36XX_HAL_WAKE_REASON_MAGIC_PACKET = 1, | ||
4435 | |||
4436 | /* host defined pattern match */ | ||
4437 | WCN36XX_HAL_WAKE_REASON_PATTERN_MATCH = 2, | ||
4438 | |||
4439 | /* EAP-ID frame detected */ | ||
4440 | WCN36XX_HAL_WAKE_REASON_EAPID_PACKET = 3, | ||
4441 | |||
4442 | /* start of EAPOL 4-way handshake detected */ | ||
4443 | WCN36XX_HAL_WAKE_REASON_EAPOL4WAY_PACKET = 4, | ||
4444 | |||
4445 | /* network scan offload match */ | ||
4446 | WCN36XX_HAL_WAKE_REASON_NETSCAN_OFFL_MATCH = 5, | ||
4447 | |||
4448 | /* GTK rekey status wakeup (see status) */ | ||
4449 | WCN36XX_HAL_WAKE_REASON_GTK_REKEY_STATUS = 6, | ||
4450 | |||
4451 | /* BSS connection lost */ | ||
4452 | WCN36XX_HAL_WAKE_REASON_BSS_CONN_LOST = 7, | ||
4453 | }; | ||
4454 | |||
4455 | /* | ||
4456 | Wake Packet which is saved at tWakeReasonParams.DataStart | ||
4457 | This data is sent for any wake reasons that involve a packet-based wakeup : | ||
4458 | |||
4459 | WCN36XX_HAL_WAKE_REASON_TYPE_MAGIC_PACKET | ||
4460 | WCN36XX_HAL_WAKE_REASON_TYPE_PATTERN_MATCH | ||
4461 | WCN36XX_HAL_WAKE_REASON_TYPE_EAPID_PACKET | ||
4462 | WCN36XX_HAL_WAKE_REASON_TYPE_EAPOL4WAY_PACKET | ||
4463 | WCN36XX_HAL_WAKE_REASON_TYPE_GTK_REKEY_STATUS | ||
4464 | |||
4465 | The information is provided to the host for auditing and debug purposes | ||
4466 | |||
4467 | */ | ||
4468 | |||
4469 | /* Wake reason indication */ | ||
4470 | struct wcn36xx_hal_wake_reason_ind { | ||
4471 | struct wcn36xx_hal_msg_header header; | ||
4472 | |||
4473 | /* see tWakeReasonType */ | ||
4474 | u32 reason; | ||
4475 | |||
4476 | /* argument specific to the reason type */ | ||
4477 | u32 reason_arg; | ||
4478 | |||
4479 | /* length of optional data stored in this message, in case HAL | ||
4480 | * truncates the data (i.e. data packets) this length will be less | ||
4481 | * than the actual length */ | ||
4482 | u32 stored_data_len; | ||
4483 | |||
4484 | /* actual length of data */ | ||
4485 | u32 actual_data_len; | ||
4486 | |||
4487 | /* variable length start of data (length == storedDataLen) see | ||
4488 | * specific wake type */ | ||
4489 | u8 data_start[1]; | ||
4490 | |||
4491 | u32 bss_index:8; | ||
4492 | u32 reserved:24; | ||
4493 | }; | ||
4494 | |||
4495 | #define WCN36XX_HAL_GTK_KEK_BYTES 16 | ||
4496 | #define WCN36XX_HAL_GTK_KCK_BYTES 16 | ||
4497 | |||
4498 | #define WCN36XX_HAL_GTK_OFFLOAD_FLAGS_DISABLE (1 << 0) | ||
4499 | |||
4500 | #define GTK_SET_BSS_KEY_TAG 0x1234AA55 | ||
4501 | |||
4502 | struct wcn36xx_hal_gtk_offload_req_msg { | ||
4503 | struct wcn36xx_hal_msg_header header; | ||
4504 | |||
4505 | /* optional flags */ | ||
4506 | u32 flags; | ||
4507 | |||
4508 | /* Key confirmation key */ | ||
4509 | u8 kck[WCN36XX_HAL_GTK_KCK_BYTES]; | ||
4510 | |||
4511 | /* key encryption key */ | ||
4512 | u8 kek[WCN36XX_HAL_GTK_KEK_BYTES]; | ||
4513 | |||
4514 | /* replay counter */ | ||
4515 | u64 key_replay_counter; | ||
4516 | |||
4517 | u8 bss_index; | ||
4518 | }; | ||
4519 | |||
4520 | struct wcn36xx_hal_gtk_offload_rsp_msg { | ||
4521 | struct wcn36xx_hal_msg_header header; | ||
4522 | |||
4523 | /* success or failure */ | ||
4524 | u32 status; | ||
4525 | |||
4526 | u8 bss_index; | ||
4527 | }; | ||
4528 | |||
4529 | struct wcn36xx_hal_gtk_offload_get_info_req_msg { | ||
4530 | struct wcn36xx_hal_msg_header header; | ||
4531 | u8 bss_index; | ||
4532 | }; | ||
4533 | |||
4534 | struct wcn36xx_hal_gtk_offload_get_info_rsp_msg { | ||
4535 | struct wcn36xx_hal_msg_header header; | ||
4536 | |||
4537 | /* success or failure */ | ||
4538 | u32 status; | ||
4539 | |||
4540 | /* last rekey status when the rekey was offloaded */ | ||
4541 | u32 last_rekey_status; | ||
4542 | |||
4543 | /* current replay counter value */ | ||
4544 | u64 key_replay_counter; | ||
4545 | |||
4546 | /* total rekey attempts */ | ||
4547 | u32 total_rekey_count; | ||
4548 | |||
4549 | /* successful GTK rekeys */ | ||
4550 | u32 gtk_rekey_count; | ||
4551 | |||
4552 | /* successful iGTK rekeys */ | ||
4553 | u32 igtk_rekey_count; | ||
4554 | |||
4555 | u8 bss_index; | ||
4556 | }; | ||
4557 | |||
4558 | struct dhcp_info { | ||
4559 | /* Indicates the device mode which indicates about the DHCP activity */ | ||
4560 | u8 device_mode; | ||
4561 | |||
4562 | u8 addr[ETH_ALEN]; | ||
4563 | }; | ||
4564 | |||
4565 | struct dhcp_ind_status { | ||
4566 | struct wcn36xx_hal_msg_header header; | ||
4567 | |||
4568 | /* success or failure */ | ||
4569 | u32 status; | ||
4570 | }; | ||
4571 | |||
4572 | /* | ||
4573 | * Thermal Mitigation mode of operation. | ||
4574 | * | ||
4575 | * WCN36XX_HAL_THERMAL_MITIGATION_MODE_0 - Based on AMPDU disabling aggregation | ||
4576 | * | ||
4577 | * WCN36XX_HAL_THERMAL_MITIGATION_MODE_1 - Based on AMPDU disabling aggregation | ||
4578 | * and reducing transmit power | ||
4579 | * | ||
4580 | * WCN36XX_HAL_THERMAL_MITIGATION_MODE_2 - Not supported */ | ||
4581 | enum wcn36xx_hal_thermal_mitigation_mode_type { | ||
4582 | HAL_THERMAL_MITIGATION_MODE_INVALID = -1, | ||
4583 | HAL_THERMAL_MITIGATION_MODE_0, | ||
4584 | HAL_THERMAL_MITIGATION_MODE_1, | ||
4585 | HAL_THERMAL_MITIGATION_MODE_2, | ||
4586 | HAL_THERMAL_MITIGATION_MODE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE, | ||
4587 | }; | ||
4588 | |||
4589 | |||
4590 | /* | ||
4591 | * Thermal Mitigation level. | ||
4592 | * Note the levels are incremental i.e WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_2 = | ||
4593 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_0 + | ||
4594 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_1 | ||
4595 | * | ||
4596 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_0 - lowest level of thermal mitigation. | ||
4597 | * This level indicates normal mode of operation | ||
4598 | * | ||
4599 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_1 - 1st level of thermal mitigation | ||
4600 | * | ||
4601 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_2 - 2nd level of thermal mitigation | ||
4602 | * | ||
4603 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_3 - 3rd level of thermal mitigation | ||
4604 | * | ||
4605 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_4 - 4th level of thermal mitigation | ||
4606 | */ | ||
4607 | enum wcn36xx_hal_thermal_mitigation_level_type { | ||
4608 | HAL_THERMAL_MITIGATION_LEVEL_INVALID = -1, | ||
4609 | HAL_THERMAL_MITIGATION_LEVEL_0, | ||
4610 | HAL_THERMAL_MITIGATION_LEVEL_1, | ||
4611 | HAL_THERMAL_MITIGATION_LEVEL_2, | ||
4612 | HAL_THERMAL_MITIGATION_LEVEL_3, | ||
4613 | HAL_THERMAL_MITIGATION_LEVEL_4, | ||
4614 | HAL_THERMAL_MITIGATION_LEVEL_MAX = WCN36XX_HAL_MAX_ENUM_SIZE, | ||
4615 | }; | ||
4616 | |||
4617 | |||
4618 | /* WCN36XX_HAL_SET_THERMAL_MITIGATION_REQ */ | ||
4619 | struct set_thermal_mitigation_req_msg { | ||
4620 | struct wcn36xx_hal_msg_header header; | ||
4621 | |||
4622 | /* Thermal Mitigation Operation Mode */ | ||
4623 | enum wcn36xx_hal_thermal_mitigation_mode_type mode; | ||
4624 | |||
4625 | /* Thermal Mitigation Level */ | ||
4626 | enum wcn36xx_hal_thermal_mitigation_level_type level; | ||
4627 | }; | ||
4628 | |||
4629 | struct set_thermal_mitigation_resp { | ||
4630 | |||
4631 | struct wcn36xx_hal_msg_header header; | ||
4632 | |||
4633 | /* status of the request */ | ||
4634 | u32 status; | ||
4635 | }; | ||
4636 | |||
4637 | /* Per STA Class B Statistics. Class B statistics are STA TX/RX stats | ||
4638 | * provided to FW from Host via periodic messages */ | ||
4639 | struct stats_class_b_ind { | ||
4640 | struct wcn36xx_hal_msg_header header; | ||
4641 | |||
4642 | /* Duration over which this stats was collected */ | ||
4643 | u32 duration; | ||
4644 | |||
4645 | /* Per STA Stats */ | ||
4646 | |||
4647 | /* TX stats */ | ||
4648 | u32 tx_bytes_pushed; | ||
4649 | u32 tx_packets_pushed; | ||
4650 | |||
4651 | /* RX stats */ | ||
4652 | u32 rx_bytes_rcvd; | ||
4653 | u32 rx_packets_rcvd; | ||
4654 | u32 rx_time_total; | ||
4655 | }; | ||
4656 | |||
4657 | #endif /* _HAL_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c new file mode 100644 index 000000000000..7839b31e4826 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/main.c | |||
@@ -0,0 +1,1036 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include "wcn36xx.h" | ||
22 | |||
23 | unsigned int wcn36xx_dbg_mask; | ||
24 | module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644); | ||
25 | MODULE_PARM_DESC(debug_mask, "Debugging mask"); | ||
26 | |||
27 | #define CHAN2G(_freq, _idx) { \ | ||
28 | .band = IEEE80211_BAND_2GHZ, \ | ||
29 | .center_freq = (_freq), \ | ||
30 | .hw_value = (_idx), \ | ||
31 | .max_power = 25, \ | ||
32 | } | ||
33 | |||
34 | #define CHAN5G(_freq, _idx) { \ | ||
35 | .band = IEEE80211_BAND_5GHZ, \ | ||
36 | .center_freq = (_freq), \ | ||
37 | .hw_value = (_idx), \ | ||
38 | .max_power = 25, \ | ||
39 | } | ||
40 | |||
41 | /* The wcn firmware expects channel values to matching | ||
42 | * their mnemonic values. So use these for .hw_value. */ | ||
43 | static struct ieee80211_channel wcn_2ghz_channels[] = { | ||
44 | CHAN2G(2412, 1), /* Channel 1 */ | ||
45 | CHAN2G(2417, 2), /* Channel 2 */ | ||
46 | CHAN2G(2422, 3), /* Channel 3 */ | ||
47 | CHAN2G(2427, 4), /* Channel 4 */ | ||
48 | CHAN2G(2432, 5), /* Channel 5 */ | ||
49 | CHAN2G(2437, 6), /* Channel 6 */ | ||
50 | CHAN2G(2442, 7), /* Channel 7 */ | ||
51 | CHAN2G(2447, 8), /* Channel 8 */ | ||
52 | CHAN2G(2452, 9), /* Channel 9 */ | ||
53 | CHAN2G(2457, 10), /* Channel 10 */ | ||
54 | CHAN2G(2462, 11), /* Channel 11 */ | ||
55 | CHAN2G(2467, 12), /* Channel 12 */ | ||
56 | CHAN2G(2472, 13), /* Channel 13 */ | ||
57 | CHAN2G(2484, 14) /* Channel 14 */ | ||
58 | |||
59 | }; | ||
60 | |||
61 | static struct ieee80211_channel wcn_5ghz_channels[] = { | ||
62 | CHAN5G(5180, 36), | ||
63 | CHAN5G(5200, 40), | ||
64 | CHAN5G(5220, 44), | ||
65 | CHAN5G(5240, 48), | ||
66 | CHAN5G(5260, 52), | ||
67 | CHAN5G(5280, 56), | ||
68 | CHAN5G(5300, 60), | ||
69 | CHAN5G(5320, 64), | ||
70 | CHAN5G(5500, 100), | ||
71 | CHAN5G(5520, 104), | ||
72 | CHAN5G(5540, 108), | ||
73 | CHAN5G(5560, 112), | ||
74 | CHAN5G(5580, 116), | ||
75 | CHAN5G(5600, 120), | ||
76 | CHAN5G(5620, 124), | ||
77 | CHAN5G(5640, 128), | ||
78 | CHAN5G(5660, 132), | ||
79 | CHAN5G(5700, 140), | ||
80 | CHAN5G(5745, 149), | ||
81 | CHAN5G(5765, 153), | ||
82 | CHAN5G(5785, 157), | ||
83 | CHAN5G(5805, 161), | ||
84 | CHAN5G(5825, 165) | ||
85 | }; | ||
86 | |||
87 | #define RATE(_bitrate, _hw_rate, _flags) { \ | ||
88 | .bitrate = (_bitrate), \ | ||
89 | .flags = (_flags), \ | ||
90 | .hw_value = (_hw_rate), \ | ||
91 | .hw_value_short = (_hw_rate) \ | ||
92 | } | ||
93 | |||
94 | static struct ieee80211_rate wcn_2ghz_rates[] = { | ||
95 | RATE(10, HW_RATE_INDEX_1MBPS, 0), | ||
96 | RATE(20, HW_RATE_INDEX_2MBPS, IEEE80211_RATE_SHORT_PREAMBLE), | ||
97 | RATE(55, HW_RATE_INDEX_5_5MBPS, IEEE80211_RATE_SHORT_PREAMBLE), | ||
98 | RATE(110, HW_RATE_INDEX_11MBPS, IEEE80211_RATE_SHORT_PREAMBLE), | ||
99 | RATE(60, HW_RATE_INDEX_6MBPS, 0), | ||
100 | RATE(90, HW_RATE_INDEX_9MBPS, 0), | ||
101 | RATE(120, HW_RATE_INDEX_12MBPS, 0), | ||
102 | RATE(180, HW_RATE_INDEX_18MBPS, 0), | ||
103 | RATE(240, HW_RATE_INDEX_24MBPS, 0), | ||
104 | RATE(360, HW_RATE_INDEX_36MBPS, 0), | ||
105 | RATE(480, HW_RATE_INDEX_48MBPS, 0), | ||
106 | RATE(540, HW_RATE_INDEX_54MBPS, 0) | ||
107 | }; | ||
108 | |||
109 | static struct ieee80211_rate wcn_5ghz_rates[] = { | ||
110 | RATE(60, HW_RATE_INDEX_6MBPS, 0), | ||
111 | RATE(90, HW_RATE_INDEX_9MBPS, 0), | ||
112 | RATE(120, HW_RATE_INDEX_12MBPS, 0), | ||
113 | RATE(180, HW_RATE_INDEX_18MBPS, 0), | ||
114 | RATE(240, HW_RATE_INDEX_24MBPS, 0), | ||
115 | RATE(360, HW_RATE_INDEX_36MBPS, 0), | ||
116 | RATE(480, HW_RATE_INDEX_48MBPS, 0), | ||
117 | RATE(540, HW_RATE_INDEX_54MBPS, 0) | ||
118 | }; | ||
119 | |||
120 | static struct ieee80211_supported_band wcn_band_2ghz = { | ||
121 | .channels = wcn_2ghz_channels, | ||
122 | .n_channels = ARRAY_SIZE(wcn_2ghz_channels), | ||
123 | .bitrates = wcn_2ghz_rates, | ||
124 | .n_bitrates = ARRAY_SIZE(wcn_2ghz_rates), | ||
125 | .ht_cap = { | ||
126 | .cap = IEEE80211_HT_CAP_GRN_FLD | | ||
127 | IEEE80211_HT_CAP_SGI_20 | | ||
128 | IEEE80211_HT_CAP_DSSSCCK40 | | ||
129 | IEEE80211_HT_CAP_LSIG_TXOP_PROT, | ||
130 | .ht_supported = true, | ||
131 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, | ||
132 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | ||
133 | .mcs = { | ||
134 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, | ||
135 | .rx_highest = cpu_to_le16(72), | ||
136 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, | ||
137 | } | ||
138 | } | ||
139 | }; | ||
140 | |||
141 | static struct ieee80211_supported_band wcn_band_5ghz = { | ||
142 | .channels = wcn_5ghz_channels, | ||
143 | .n_channels = ARRAY_SIZE(wcn_5ghz_channels), | ||
144 | .bitrates = wcn_5ghz_rates, | ||
145 | .n_bitrates = ARRAY_SIZE(wcn_5ghz_rates), | ||
146 | .ht_cap = { | ||
147 | .cap = IEEE80211_HT_CAP_GRN_FLD | | ||
148 | IEEE80211_HT_CAP_SGI_20 | | ||
149 | IEEE80211_HT_CAP_DSSSCCK40 | | ||
150 | IEEE80211_HT_CAP_LSIG_TXOP_PROT | | ||
151 | IEEE80211_HT_CAP_SGI_40 | | ||
152 | IEEE80211_HT_CAP_SUP_WIDTH_20_40, | ||
153 | .ht_supported = true, | ||
154 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, | ||
155 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | ||
156 | .mcs = { | ||
157 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, | ||
158 | .rx_highest = cpu_to_le16(72), | ||
159 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, | ||
160 | } | ||
161 | } | ||
162 | }; | ||
163 | |||
164 | #ifdef CONFIG_PM | ||
165 | |||
166 | static const struct wiphy_wowlan_support wowlan_support = { | ||
167 | .flags = WIPHY_WOWLAN_ANY | ||
168 | }; | ||
169 | |||
170 | #endif | ||
171 | |||
172 | static inline u8 get_sta_index(struct ieee80211_vif *vif, | ||
173 | struct wcn36xx_sta *sta_priv) | ||
174 | { | ||
175 | return NL80211_IFTYPE_STATION == vif->type ? | ||
176 | sta_priv->bss_sta_index : | ||
177 | sta_priv->sta_index; | ||
178 | } | ||
179 | |||
180 | static int wcn36xx_start(struct ieee80211_hw *hw) | ||
181 | { | ||
182 | struct wcn36xx *wcn = hw->priv; | ||
183 | int ret; | ||
184 | |||
185 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac start\n"); | ||
186 | |||
187 | /* SMD initialization */ | ||
188 | ret = wcn36xx_smd_open(wcn); | ||
189 | if (ret) { | ||
190 | wcn36xx_err("Failed to open smd channel: %d\n", ret); | ||
191 | goto out_err; | ||
192 | } | ||
193 | |||
194 | /* Allocate memory pools for Mgmt BD headers and Data BD headers */ | ||
195 | ret = wcn36xx_dxe_allocate_mem_pools(wcn); | ||
196 | if (ret) { | ||
197 | wcn36xx_err("Failed to alloc DXE mempool: %d\n", ret); | ||
198 | goto out_smd_close; | ||
199 | } | ||
200 | |||
201 | ret = wcn36xx_dxe_alloc_ctl_blks(wcn); | ||
202 | if (ret) { | ||
203 | wcn36xx_err("Failed to alloc DXE ctl blocks: %d\n", ret); | ||
204 | goto out_free_dxe_pool; | ||
205 | } | ||
206 | |||
207 | wcn->hal_buf = kmalloc(WCN36XX_HAL_BUF_SIZE, GFP_KERNEL); | ||
208 | if (!wcn->hal_buf) { | ||
209 | wcn36xx_err("Failed to allocate smd buf\n"); | ||
210 | ret = -ENOMEM; | ||
211 | goto out_free_dxe_ctl; | ||
212 | } | ||
213 | |||
214 | ret = wcn36xx_smd_load_nv(wcn); | ||
215 | if (ret) { | ||
216 | wcn36xx_err("Failed to push NV to chip\n"); | ||
217 | goto out_free_smd_buf; | ||
218 | } | ||
219 | |||
220 | ret = wcn36xx_smd_start(wcn); | ||
221 | if (ret) { | ||
222 | wcn36xx_err("Failed to start chip\n"); | ||
223 | goto out_free_smd_buf; | ||
224 | } | ||
225 | |||
226 | /* DMA channel initialization */ | ||
227 | ret = wcn36xx_dxe_init(wcn); | ||
228 | if (ret) { | ||
229 | wcn36xx_err("DXE init failed\n"); | ||
230 | goto out_smd_stop; | ||
231 | } | ||
232 | |||
233 | wcn36xx_debugfs_init(wcn); | ||
234 | |||
235 | if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { | ||
236 | ret = wcn36xx_smd_feature_caps_exchange(wcn); | ||
237 | if (ret) | ||
238 | wcn36xx_warn("Exchange feature caps failed\n"); | ||
239 | } | ||
240 | INIT_LIST_HEAD(&wcn->vif_list); | ||
241 | return 0; | ||
242 | |||
243 | out_smd_stop: | ||
244 | wcn36xx_smd_stop(wcn); | ||
245 | out_free_smd_buf: | ||
246 | kfree(wcn->hal_buf); | ||
247 | out_free_dxe_pool: | ||
248 | wcn36xx_dxe_free_mem_pools(wcn); | ||
249 | out_free_dxe_ctl: | ||
250 | wcn36xx_dxe_free_ctl_blks(wcn); | ||
251 | out_smd_close: | ||
252 | wcn36xx_smd_close(wcn); | ||
253 | out_err: | ||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | static void wcn36xx_stop(struct ieee80211_hw *hw) | ||
258 | { | ||
259 | struct wcn36xx *wcn = hw->priv; | ||
260 | |||
261 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop\n"); | ||
262 | |||
263 | wcn36xx_debugfs_exit(wcn); | ||
264 | wcn36xx_smd_stop(wcn); | ||
265 | wcn36xx_dxe_deinit(wcn); | ||
266 | wcn36xx_smd_close(wcn); | ||
267 | |||
268 | wcn36xx_dxe_free_mem_pools(wcn); | ||
269 | wcn36xx_dxe_free_ctl_blks(wcn); | ||
270 | |||
271 | kfree(wcn->hal_buf); | ||
272 | } | ||
273 | |||
274 | static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed) | ||
275 | { | ||
276 | struct wcn36xx *wcn = hw->priv; | ||
277 | struct ieee80211_vif *vif = NULL; | ||
278 | struct wcn36xx_vif *tmp; | ||
279 | |||
280 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed); | ||
281 | |||
282 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | ||
283 | int ch = WCN36XX_HW_CHANNEL(wcn); | ||
284 | wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n", | ||
285 | ch); | ||
286 | list_for_each_entry(tmp, &wcn->vif_list, list) { | ||
287 | vif = container_of((void *)tmp, | ||
288 | struct ieee80211_vif, | ||
289 | drv_priv); | ||
290 | wcn36xx_smd_switch_channel(wcn, vif, ch); | ||
291 | } | ||
292 | } | ||
293 | |||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | #define WCN36XX_SUPPORTED_FILTERS (0) | ||
298 | |||
299 | static void wcn36xx_configure_filter(struct ieee80211_hw *hw, | ||
300 | unsigned int changed, | ||
301 | unsigned int *total, u64 multicast) | ||
302 | { | ||
303 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n"); | ||
304 | |||
305 | *total &= WCN36XX_SUPPORTED_FILTERS; | ||
306 | } | ||
307 | |||
308 | static void wcn36xx_tx(struct ieee80211_hw *hw, | ||
309 | struct ieee80211_tx_control *control, | ||
310 | struct sk_buff *skb) | ||
311 | { | ||
312 | struct wcn36xx *wcn = hw->priv; | ||
313 | struct wcn36xx_sta *sta_priv = NULL; | ||
314 | |||
315 | if (control->sta) | ||
316 | sta_priv = (struct wcn36xx_sta *)control->sta->drv_priv; | ||
317 | |||
318 | if (wcn36xx_start_tx(wcn, sta_priv, skb)) | ||
319 | ieee80211_free_txskb(wcn->hw, skb); | ||
320 | } | ||
321 | |||
322 | static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | ||
323 | struct ieee80211_vif *vif, | ||
324 | struct ieee80211_sta *sta, | ||
325 | struct ieee80211_key_conf *key_conf) | ||
326 | { | ||
327 | struct wcn36xx *wcn = hw->priv; | ||
328 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
329 | struct wcn36xx_sta *sta_priv = vif_priv->sta; | ||
330 | int ret = 0; | ||
331 | u8 key[WLAN_MAX_KEY_LEN]; | ||
332 | |||
333 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 set key\n"); | ||
334 | wcn36xx_dbg(WCN36XX_DBG_MAC, "Key: cmd=0x%x algo:0x%x, id:%d, len:%d flags 0x%x\n", | ||
335 | cmd, key_conf->cipher, key_conf->keyidx, | ||
336 | key_conf->keylen, key_conf->flags); | ||
337 | wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "KEY: ", | ||
338 | key_conf->key, | ||
339 | key_conf->keylen); | ||
340 | |||
341 | switch (key_conf->cipher) { | ||
342 | case WLAN_CIPHER_SUITE_WEP40: | ||
343 | vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40; | ||
344 | break; | ||
345 | case WLAN_CIPHER_SUITE_WEP104: | ||
346 | vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40; | ||
347 | break; | ||
348 | case WLAN_CIPHER_SUITE_CCMP: | ||
349 | vif_priv->encrypt_type = WCN36XX_HAL_ED_CCMP; | ||
350 | break; | ||
351 | case WLAN_CIPHER_SUITE_TKIP: | ||
352 | vif_priv->encrypt_type = WCN36XX_HAL_ED_TKIP; | ||
353 | break; | ||
354 | default: | ||
355 | wcn36xx_err("Unsupported key type 0x%x\n", | ||
356 | key_conf->cipher); | ||
357 | ret = -EOPNOTSUPP; | ||
358 | goto out; | ||
359 | } | ||
360 | |||
361 | switch (cmd) { | ||
362 | case SET_KEY: | ||
363 | if (WCN36XX_HAL_ED_TKIP == vif_priv->encrypt_type) { | ||
364 | /* | ||
365 | * Supplicant is sending key in the wrong order: | ||
366 | * Temporal Key (16 b) - TX MIC (8 b) - RX MIC (8 b) | ||
367 | * but HW expects it to be in the order as described in | ||
368 | * IEEE 802.11 spec (see chapter 11.7) like this: | ||
369 | * Temporal Key (16 b) - RX MIC (8 b) - TX MIC (8 b) | ||
370 | */ | ||
371 | memcpy(key, key_conf->key, 16); | ||
372 | memcpy(key + 16, key_conf->key + 24, 8); | ||
373 | memcpy(key + 24, key_conf->key + 16, 8); | ||
374 | } else { | ||
375 | memcpy(key, key_conf->key, key_conf->keylen); | ||
376 | } | ||
377 | |||
378 | if (IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags) { | ||
379 | sta_priv->is_data_encrypted = true; | ||
380 | /* Reconfigure bss with encrypt_type */ | ||
381 | if (NL80211_IFTYPE_STATION == vif->type) | ||
382 | wcn36xx_smd_config_bss(wcn, | ||
383 | vif, | ||
384 | sta, | ||
385 | sta->addr, | ||
386 | true); | ||
387 | |||
388 | wcn36xx_smd_set_stakey(wcn, | ||
389 | vif_priv->encrypt_type, | ||
390 | key_conf->keyidx, | ||
391 | key_conf->keylen, | ||
392 | key, | ||
393 | get_sta_index(vif, sta_priv)); | ||
394 | } else { | ||
395 | wcn36xx_smd_set_bsskey(wcn, | ||
396 | vif_priv->encrypt_type, | ||
397 | key_conf->keyidx, | ||
398 | key_conf->keylen, | ||
399 | key); | ||
400 | if ((WLAN_CIPHER_SUITE_WEP40 == key_conf->cipher) || | ||
401 | (WLAN_CIPHER_SUITE_WEP104 == key_conf->cipher)) { | ||
402 | sta_priv->is_data_encrypted = true; | ||
403 | wcn36xx_smd_set_stakey(wcn, | ||
404 | vif_priv->encrypt_type, | ||
405 | key_conf->keyidx, | ||
406 | key_conf->keylen, | ||
407 | key, | ||
408 | get_sta_index(vif, sta_priv)); | ||
409 | } | ||
410 | } | ||
411 | break; | ||
412 | case DISABLE_KEY: | ||
413 | if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) { | ||
414 | wcn36xx_smd_remove_bsskey(wcn, | ||
415 | vif_priv->encrypt_type, | ||
416 | key_conf->keyidx); | ||
417 | } else { | ||
418 | sta_priv->is_data_encrypted = false; | ||
419 | /* do not remove key if disassociated */ | ||
420 | if (sta_priv->aid) | ||
421 | wcn36xx_smd_remove_stakey(wcn, | ||
422 | vif_priv->encrypt_type, | ||
423 | key_conf->keyidx, | ||
424 | get_sta_index(vif, sta_priv)); | ||
425 | } | ||
426 | break; | ||
427 | default: | ||
428 | wcn36xx_err("Unsupported key cmd 0x%x\n", cmd); | ||
429 | ret = -EOPNOTSUPP; | ||
430 | goto out; | ||
431 | break; | ||
432 | } | ||
433 | |||
434 | out: | ||
435 | return ret; | ||
436 | } | ||
437 | |||
438 | static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw) | ||
439 | { | ||
440 | struct wcn36xx *wcn = hw->priv; | ||
441 | |||
442 | wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN); | ||
443 | wcn36xx_smd_start_scan(wcn); | ||
444 | } | ||
445 | |||
446 | static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw) | ||
447 | { | ||
448 | struct wcn36xx *wcn = hw->priv; | ||
449 | |||
450 | wcn36xx_smd_end_scan(wcn); | ||
451 | wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN); | ||
452 | } | ||
453 | |||
454 | static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta, | ||
455 | enum ieee80211_band band) | ||
456 | { | ||
457 | int i, size; | ||
458 | u16 *rates_table; | ||
459 | struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; | ||
460 | u32 rates = sta->supp_rates[band]; | ||
461 | |||
462 | memset(&sta_priv->supported_rates, 0, | ||
463 | sizeof(sta_priv->supported_rates)); | ||
464 | sta_priv->supported_rates.op_rate_mode = STA_11n; | ||
465 | |||
466 | size = ARRAY_SIZE(sta_priv->supported_rates.dsss_rates); | ||
467 | rates_table = sta_priv->supported_rates.dsss_rates; | ||
468 | if (band == IEEE80211_BAND_2GHZ) { | ||
469 | for (i = 0; i < size; i++) { | ||
470 | if (rates & 0x01) { | ||
471 | rates_table[i] = wcn_2ghz_rates[i].hw_value; | ||
472 | rates = rates >> 1; | ||
473 | } | ||
474 | } | ||
475 | } | ||
476 | |||
477 | size = ARRAY_SIZE(sta_priv->supported_rates.ofdm_rates); | ||
478 | rates_table = sta_priv->supported_rates.ofdm_rates; | ||
479 | for (i = 0; i < size; i++) { | ||
480 | if (rates & 0x01) { | ||
481 | rates_table[i] = wcn_5ghz_rates[i].hw_value; | ||
482 | rates = rates >> 1; | ||
483 | } | ||
484 | } | ||
485 | |||
486 | if (sta->ht_cap.ht_supported) { | ||
487 | BUILD_BUG_ON(sizeof(sta->ht_cap.mcs.rx_mask) > | ||
488 | sizeof(sta_priv->supported_rates.supported_mcs_set)); | ||
489 | memcpy(sta_priv->supported_rates.supported_mcs_set, | ||
490 | sta->ht_cap.mcs.rx_mask, | ||
491 | sizeof(sta->ht_cap.mcs.rx_mask)); | ||
492 | } | ||
493 | } | ||
494 | void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates) | ||
495 | { | ||
496 | u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES] = { | ||
497 | HW_RATE_INDEX_6MBPS, | ||
498 | HW_RATE_INDEX_9MBPS, | ||
499 | HW_RATE_INDEX_12MBPS, | ||
500 | HW_RATE_INDEX_18MBPS, | ||
501 | HW_RATE_INDEX_24MBPS, | ||
502 | HW_RATE_INDEX_36MBPS, | ||
503 | HW_RATE_INDEX_48MBPS, | ||
504 | HW_RATE_INDEX_54MBPS | ||
505 | }; | ||
506 | u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES] = { | ||
507 | HW_RATE_INDEX_1MBPS, | ||
508 | HW_RATE_INDEX_2MBPS, | ||
509 | HW_RATE_INDEX_5_5MBPS, | ||
510 | HW_RATE_INDEX_11MBPS | ||
511 | }; | ||
512 | |||
513 | rates->op_rate_mode = STA_11n; | ||
514 | memcpy(rates->dsss_rates, dsss_rates, | ||
515 | sizeof(*dsss_rates) * WCN36XX_HAL_NUM_DSSS_RATES); | ||
516 | memcpy(rates->ofdm_rates, ofdm_rates, | ||
517 | sizeof(*ofdm_rates) * WCN36XX_HAL_NUM_OFDM_RATES); | ||
518 | rates->supported_mcs_set[0] = 0xFF; | ||
519 | } | ||
520 | static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, | ||
521 | struct ieee80211_vif *vif, | ||
522 | struct ieee80211_bss_conf *bss_conf, | ||
523 | u32 changed) | ||
524 | { | ||
525 | struct wcn36xx *wcn = hw->priv; | ||
526 | struct sk_buff *skb = NULL; | ||
527 | u16 tim_off, tim_len; | ||
528 | enum wcn36xx_hal_link_state link_state; | ||
529 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
530 | |||
531 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n", | ||
532 | vif, changed); | ||
533 | |||
534 | if (changed & BSS_CHANGED_BEACON_INFO) { | ||
535 | wcn36xx_dbg(WCN36XX_DBG_MAC, | ||
536 | "mac bss changed dtim period %d\n", | ||
537 | bss_conf->dtim_period); | ||
538 | |||
539 | vif_priv->dtim_period = bss_conf->dtim_period; | ||
540 | } | ||
541 | |||
542 | if (changed & BSS_CHANGED_PS) { | ||
543 | wcn36xx_dbg(WCN36XX_DBG_MAC, | ||
544 | "mac bss PS set %d\n", | ||
545 | bss_conf->ps); | ||
546 | if (bss_conf->ps) { | ||
547 | wcn36xx_pmc_enter_bmps_state(wcn, vif); | ||
548 | } else { | ||
549 | wcn36xx_pmc_exit_bmps_state(wcn, vif); | ||
550 | } | ||
551 | } | ||
552 | |||
553 | if (changed & BSS_CHANGED_BSSID) { | ||
554 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed_bssid %pM\n", | ||
555 | bss_conf->bssid); | ||
556 | |||
557 | if (!is_zero_ether_addr(bss_conf->bssid)) { | ||
558 | vif_priv->is_joining = true; | ||
559 | vif_priv->bss_index = 0xff; | ||
560 | wcn36xx_smd_join(wcn, bss_conf->bssid, | ||
561 | vif->addr, WCN36XX_HW_CHANNEL(wcn)); | ||
562 | wcn36xx_smd_config_bss(wcn, vif, NULL, | ||
563 | bss_conf->bssid, false); | ||
564 | } else { | ||
565 | vif_priv->is_joining = false; | ||
566 | wcn36xx_smd_delete_bss(wcn, vif); | ||
567 | } | ||
568 | } | ||
569 | |||
570 | if (changed & BSS_CHANGED_SSID) { | ||
571 | wcn36xx_dbg(WCN36XX_DBG_MAC, | ||
572 | "mac bss changed ssid\n"); | ||
573 | wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "ssid ", | ||
574 | bss_conf->ssid, bss_conf->ssid_len); | ||
575 | |||
576 | vif_priv->ssid.length = bss_conf->ssid_len; | ||
577 | memcpy(&vif_priv->ssid.ssid, | ||
578 | bss_conf->ssid, | ||
579 | bss_conf->ssid_len); | ||
580 | } | ||
581 | |||
582 | if (changed & BSS_CHANGED_ASSOC) { | ||
583 | vif_priv->is_joining = false; | ||
584 | if (bss_conf->assoc) { | ||
585 | struct ieee80211_sta *sta; | ||
586 | struct wcn36xx_sta *sta_priv; | ||
587 | |||
588 | wcn36xx_dbg(WCN36XX_DBG_MAC, | ||
589 | "mac assoc bss %pM vif %pM AID=%d\n", | ||
590 | bss_conf->bssid, | ||
591 | vif->addr, | ||
592 | bss_conf->aid); | ||
593 | |||
594 | rcu_read_lock(); | ||
595 | sta = ieee80211_find_sta(vif, bss_conf->bssid); | ||
596 | if (!sta) { | ||
597 | wcn36xx_err("sta %pM is not found\n", | ||
598 | bss_conf->bssid); | ||
599 | rcu_read_unlock(); | ||
600 | goto out; | ||
601 | } | ||
602 | sta_priv = (struct wcn36xx_sta *)sta->drv_priv; | ||
603 | |||
604 | wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn)); | ||
605 | |||
606 | wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, | ||
607 | vif->addr, | ||
608 | WCN36XX_HAL_LINK_POSTASSOC_STATE); | ||
609 | wcn36xx_smd_config_bss(wcn, vif, sta, | ||
610 | bss_conf->bssid, | ||
611 | true); | ||
612 | sta_priv->aid = bss_conf->aid; | ||
613 | /* | ||
614 | * config_sta must be called from because this is the | ||
615 | * place where AID is available. | ||
616 | */ | ||
617 | wcn36xx_smd_config_sta(wcn, vif, sta); | ||
618 | rcu_read_unlock(); | ||
619 | } else { | ||
620 | wcn36xx_dbg(WCN36XX_DBG_MAC, | ||
621 | "disassociated bss %pM vif %pM AID=%d\n", | ||
622 | bss_conf->bssid, | ||
623 | vif->addr, | ||
624 | bss_conf->aid); | ||
625 | wcn36xx_smd_set_link_st(wcn, | ||
626 | bss_conf->bssid, | ||
627 | vif->addr, | ||
628 | WCN36XX_HAL_LINK_IDLE_STATE); | ||
629 | } | ||
630 | } | ||
631 | |||
632 | if (changed & BSS_CHANGED_AP_PROBE_RESP) { | ||
633 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed ap probe resp\n"); | ||
634 | skb = ieee80211_proberesp_get(hw, vif); | ||
635 | if (!skb) { | ||
636 | wcn36xx_err("failed to alloc probereq skb\n"); | ||
637 | goto out; | ||
638 | } | ||
639 | |||
640 | wcn36xx_smd_update_proberesp_tmpl(wcn, vif, skb); | ||
641 | dev_kfree_skb(skb); | ||
642 | } | ||
643 | |||
644 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | ||
645 | wcn36xx_dbg(WCN36XX_DBG_MAC, | ||
646 | "mac bss changed beacon enabled %d\n", | ||
647 | bss_conf->enable_beacon); | ||
648 | |||
649 | if (bss_conf->enable_beacon) { | ||
650 | vif_priv->bss_index = 0xff; | ||
651 | wcn36xx_smd_config_bss(wcn, vif, NULL, | ||
652 | vif->addr, false); | ||
653 | skb = ieee80211_beacon_get_tim(hw, vif, &tim_off, | ||
654 | &tim_len); | ||
655 | if (!skb) { | ||
656 | wcn36xx_err("failed to alloc beacon skb\n"); | ||
657 | goto out; | ||
658 | } | ||
659 | wcn36xx_smd_send_beacon(wcn, vif, skb, tim_off, 0); | ||
660 | dev_kfree_skb(skb); | ||
661 | |||
662 | if (vif->type == NL80211_IFTYPE_ADHOC || | ||
663 | vif->type == NL80211_IFTYPE_MESH_POINT) | ||
664 | link_state = WCN36XX_HAL_LINK_IBSS_STATE; | ||
665 | else | ||
666 | link_state = WCN36XX_HAL_LINK_AP_STATE; | ||
667 | |||
668 | wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, | ||
669 | link_state); | ||
670 | } else { | ||
671 | wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, | ||
672 | WCN36XX_HAL_LINK_IDLE_STATE); | ||
673 | wcn36xx_smd_delete_bss(wcn, vif); | ||
674 | } | ||
675 | } | ||
676 | out: | ||
677 | return; | ||
678 | } | ||
679 | |||
680 | /* this is required when using IEEE80211_HW_HAS_RATE_CONTROL */ | ||
681 | static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | ||
682 | { | ||
683 | struct wcn36xx *wcn = hw->priv; | ||
684 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac set RTS threshold %d\n", value); | ||
685 | |||
686 | wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_RTS_THRESHOLD, value); | ||
687 | return 0; | ||
688 | } | ||
689 | |||
690 | static void wcn36xx_remove_interface(struct ieee80211_hw *hw, | ||
691 | struct ieee80211_vif *vif) | ||
692 | { | ||
693 | struct wcn36xx *wcn = hw->priv; | ||
694 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
695 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif); | ||
696 | |||
697 | list_del(&vif_priv->list); | ||
698 | wcn36xx_smd_delete_sta_self(wcn, vif->addr); | ||
699 | } | ||
700 | |||
701 | static int wcn36xx_add_interface(struct ieee80211_hw *hw, | ||
702 | struct ieee80211_vif *vif) | ||
703 | { | ||
704 | struct wcn36xx *wcn = hw->priv; | ||
705 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
706 | |||
707 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n", | ||
708 | vif, vif->type); | ||
709 | |||
710 | if (!(NL80211_IFTYPE_STATION == vif->type || | ||
711 | NL80211_IFTYPE_AP == vif->type || | ||
712 | NL80211_IFTYPE_ADHOC == vif->type || | ||
713 | NL80211_IFTYPE_MESH_POINT == vif->type)) { | ||
714 | wcn36xx_warn("Unsupported interface type requested: %d\n", | ||
715 | vif->type); | ||
716 | return -EOPNOTSUPP; | ||
717 | } | ||
718 | |||
719 | list_add(&vif_priv->list, &wcn->vif_list); | ||
720 | wcn36xx_smd_add_sta_self(wcn, vif); | ||
721 | |||
722 | return 0; | ||
723 | } | ||
724 | |||
725 | static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
726 | struct ieee80211_sta *sta) | ||
727 | { | ||
728 | struct wcn36xx *wcn = hw->priv; | ||
729 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
730 | struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; | ||
731 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n", | ||
732 | vif, sta->addr); | ||
733 | |||
734 | vif_priv->sta = sta_priv; | ||
735 | sta_priv->vif = vif_priv; | ||
736 | /* | ||
737 | * For STA mode HW will be configured on BSS_CHANGED_ASSOC because | ||
738 | * at this stage AID is not available yet. | ||
739 | */ | ||
740 | if (NL80211_IFTYPE_STATION != vif->type) { | ||
741 | wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn)); | ||
742 | sta_priv->aid = sta->aid; | ||
743 | wcn36xx_smd_config_sta(wcn, vif, sta); | ||
744 | } | ||
745 | return 0; | ||
746 | } | ||
747 | |||
748 | static int wcn36xx_sta_remove(struct ieee80211_hw *hw, | ||
749 | struct ieee80211_vif *vif, | ||
750 | struct ieee80211_sta *sta) | ||
751 | { | ||
752 | struct wcn36xx *wcn = hw->priv; | ||
753 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
754 | struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; | ||
755 | |||
756 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n", | ||
757 | vif, sta->addr, sta_priv->sta_index); | ||
758 | |||
759 | wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index); | ||
760 | vif_priv->sta = NULL; | ||
761 | sta_priv->vif = NULL; | ||
762 | return 0; | ||
763 | } | ||
764 | |||
765 | #ifdef CONFIG_PM | ||
766 | |||
767 | static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow) | ||
768 | { | ||
769 | struct wcn36xx *wcn = hw->priv; | ||
770 | |||
771 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac suspend\n"); | ||
772 | |||
773 | flush_workqueue(wcn->hal_ind_wq); | ||
774 | wcn36xx_smd_set_power_params(wcn, true); | ||
775 | return 0; | ||
776 | } | ||
777 | |||
778 | static int wcn36xx_resume(struct ieee80211_hw *hw) | ||
779 | { | ||
780 | struct wcn36xx *wcn = hw->priv; | ||
781 | |||
782 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac resume\n"); | ||
783 | |||
784 | flush_workqueue(wcn->hal_ind_wq); | ||
785 | wcn36xx_smd_set_power_params(wcn, false); | ||
786 | return 0; | ||
787 | } | ||
788 | |||
789 | #endif | ||
790 | |||
791 | static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, | ||
792 | struct ieee80211_vif *vif, | ||
793 | enum ieee80211_ampdu_mlme_action action, | ||
794 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, | ||
795 | u8 buf_size) | ||
796 | { | ||
797 | struct wcn36xx *wcn = hw->priv; | ||
798 | struct wcn36xx_sta *sta_priv = NULL; | ||
799 | |||
800 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n", | ||
801 | action, tid); | ||
802 | |||
803 | sta_priv = (struct wcn36xx_sta *)sta->drv_priv; | ||
804 | |||
805 | switch (action) { | ||
806 | case IEEE80211_AMPDU_RX_START: | ||
807 | sta_priv->tid = tid; | ||
808 | wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0, | ||
809 | get_sta_index(vif, sta_priv)); | ||
810 | wcn36xx_smd_add_ba(wcn); | ||
811 | wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv)); | ||
812 | ieee80211_start_tx_ba_session(sta, tid, 0); | ||
813 | break; | ||
814 | case IEEE80211_AMPDU_RX_STOP: | ||
815 | wcn36xx_smd_del_ba(wcn, tid, get_sta_index(vif, sta_priv)); | ||
816 | break; | ||
817 | case IEEE80211_AMPDU_TX_START: | ||
818 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
819 | break; | ||
820 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
821 | wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1, | ||
822 | get_sta_index(vif, sta_priv)); | ||
823 | break; | ||
824 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | ||
825 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | ||
826 | case IEEE80211_AMPDU_TX_STOP_CONT: | ||
827 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
828 | break; | ||
829 | default: | ||
830 | wcn36xx_err("Unknown AMPDU action\n"); | ||
831 | } | ||
832 | |||
833 | return 0; | ||
834 | } | ||
835 | |||
836 | static const struct ieee80211_ops wcn36xx_ops = { | ||
837 | .start = wcn36xx_start, | ||
838 | .stop = wcn36xx_stop, | ||
839 | .add_interface = wcn36xx_add_interface, | ||
840 | .remove_interface = wcn36xx_remove_interface, | ||
841 | #ifdef CONFIG_PM | ||
842 | .suspend = wcn36xx_suspend, | ||
843 | .resume = wcn36xx_resume, | ||
844 | #endif | ||
845 | .config = wcn36xx_config, | ||
846 | .configure_filter = wcn36xx_configure_filter, | ||
847 | .tx = wcn36xx_tx, | ||
848 | .set_key = wcn36xx_set_key, | ||
849 | .sw_scan_start = wcn36xx_sw_scan_start, | ||
850 | .sw_scan_complete = wcn36xx_sw_scan_complete, | ||
851 | .bss_info_changed = wcn36xx_bss_info_changed, | ||
852 | .set_rts_threshold = wcn36xx_set_rts_threshold, | ||
853 | .sta_add = wcn36xx_sta_add, | ||
854 | .sta_remove = wcn36xx_sta_remove, | ||
855 | .ampdu_action = wcn36xx_ampdu_action, | ||
856 | }; | ||
857 | |||
858 | static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) | ||
859 | { | ||
860 | int ret = 0; | ||
861 | |||
862 | static const u32 cipher_suites[] = { | ||
863 | WLAN_CIPHER_SUITE_WEP40, | ||
864 | WLAN_CIPHER_SUITE_WEP104, | ||
865 | WLAN_CIPHER_SUITE_TKIP, | ||
866 | WLAN_CIPHER_SUITE_CCMP, | ||
867 | }; | ||
868 | |||
869 | wcn->hw->flags = IEEE80211_HW_SIGNAL_DBM | | ||
870 | IEEE80211_HW_HAS_RATE_CONTROL | | ||
871 | IEEE80211_HW_SUPPORTS_PS | | ||
872 | IEEE80211_HW_CONNECTION_MONITOR | | ||
873 | IEEE80211_HW_AMPDU_AGGREGATION | | ||
874 | IEEE80211_HW_TIMING_BEACON_ONLY; | ||
875 | |||
876 | wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | ||
877 | BIT(NL80211_IFTYPE_AP) | | ||
878 | BIT(NL80211_IFTYPE_ADHOC) | | ||
879 | BIT(NL80211_IFTYPE_MESH_POINT); | ||
880 | |||
881 | wcn->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wcn_band_2ghz; | ||
882 | wcn->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wcn_band_5ghz; | ||
883 | |||
884 | wcn->hw->wiphy->cipher_suites = cipher_suites; | ||
885 | wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | ||
886 | |||
887 | wcn->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; | ||
888 | |||
889 | #ifdef CONFIG_PM | ||
890 | wcn->hw->wiphy->wowlan = &wowlan_support; | ||
891 | #endif | ||
892 | |||
893 | wcn->hw->max_listen_interval = 200; | ||
894 | |||
895 | wcn->hw->queues = 4; | ||
896 | |||
897 | SET_IEEE80211_DEV(wcn->hw, wcn->dev); | ||
898 | |||
899 | wcn->hw->sta_data_size = sizeof(struct wcn36xx_sta); | ||
900 | wcn->hw->vif_data_size = sizeof(struct wcn36xx_vif); | ||
901 | |||
902 | return ret; | ||
903 | } | ||
904 | |||
905 | static int wcn36xx_platform_get_resources(struct wcn36xx *wcn, | ||
906 | struct platform_device *pdev) | ||
907 | { | ||
908 | struct resource *res; | ||
909 | /* Set TX IRQ */ | ||
910 | res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, | ||
911 | "wcnss_wlantx_irq"); | ||
912 | if (!res) { | ||
913 | wcn36xx_err("failed to get tx_irq\n"); | ||
914 | return -ENOENT; | ||
915 | } | ||
916 | wcn->tx_irq = res->start; | ||
917 | |||
918 | /* Set RX IRQ */ | ||
919 | res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, | ||
920 | "wcnss_wlanrx_irq"); | ||
921 | if (!res) { | ||
922 | wcn36xx_err("failed to get rx_irq\n"); | ||
923 | return -ENOENT; | ||
924 | } | ||
925 | wcn->rx_irq = res->start; | ||
926 | |||
927 | /* Map the memory */ | ||
928 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||
929 | "wcnss_mmio"); | ||
930 | if (!res) { | ||
931 | wcn36xx_err("failed to get mmio\n"); | ||
932 | return -ENOENT; | ||
933 | } | ||
934 | wcn->mmio = ioremap(res->start, resource_size(res)); | ||
935 | if (!wcn->mmio) { | ||
936 | wcn36xx_err("failed to map io memory\n"); | ||
937 | return -ENOMEM; | ||
938 | } | ||
939 | return 0; | ||
940 | } | ||
941 | |||
942 | static int wcn36xx_probe(struct platform_device *pdev) | ||
943 | { | ||
944 | struct ieee80211_hw *hw; | ||
945 | struct wcn36xx *wcn; | ||
946 | int ret; | ||
947 | u8 addr[ETH_ALEN]; | ||
948 | |||
949 | wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n"); | ||
950 | |||
951 | hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops); | ||
952 | if (!hw) { | ||
953 | wcn36xx_err("failed to alloc hw\n"); | ||
954 | ret = -ENOMEM; | ||
955 | goto out_err; | ||
956 | } | ||
957 | platform_set_drvdata(pdev, hw); | ||
958 | wcn = hw->priv; | ||
959 | wcn->hw = hw; | ||
960 | wcn->dev = &pdev->dev; | ||
961 | wcn->ctrl_ops = pdev->dev.platform_data; | ||
962 | |||
963 | mutex_init(&wcn->hal_mutex); | ||
964 | |||
965 | if (!wcn->ctrl_ops->get_hw_mac(addr)) { | ||
966 | wcn36xx_info("mac address: %pM\n", addr); | ||
967 | SET_IEEE80211_PERM_ADDR(wcn->hw, addr); | ||
968 | } | ||
969 | |||
970 | ret = wcn36xx_platform_get_resources(wcn, pdev); | ||
971 | if (ret) | ||
972 | goto out_wq; | ||
973 | |||
974 | wcn36xx_init_ieee80211(wcn); | ||
975 | ret = ieee80211_register_hw(wcn->hw); | ||
976 | if (ret) | ||
977 | goto out_unmap; | ||
978 | |||
979 | return 0; | ||
980 | |||
981 | out_unmap: | ||
982 | iounmap(wcn->mmio); | ||
983 | out_wq: | ||
984 | ieee80211_free_hw(hw); | ||
985 | out_err: | ||
986 | return ret; | ||
987 | } | ||
988 | static int wcn36xx_remove(struct platform_device *pdev) | ||
989 | { | ||
990 | struct ieee80211_hw *hw = platform_get_drvdata(pdev); | ||
991 | struct wcn36xx *wcn = hw->priv; | ||
992 | wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n"); | ||
993 | |||
994 | mutex_destroy(&wcn->hal_mutex); | ||
995 | |||
996 | ieee80211_unregister_hw(hw); | ||
997 | iounmap(wcn->mmio); | ||
998 | ieee80211_free_hw(hw); | ||
999 | |||
1000 | return 0; | ||
1001 | } | ||
1002 | static const struct platform_device_id wcn36xx_platform_id_table[] = { | ||
1003 | { | ||
1004 | .name = "wcn36xx", | ||
1005 | .driver_data = 0 | ||
1006 | }, | ||
1007 | {} | ||
1008 | }; | ||
1009 | MODULE_DEVICE_TABLE(platform, wcn36xx_platform_id_table); | ||
1010 | |||
1011 | static struct platform_driver wcn36xx_driver = { | ||
1012 | .probe = wcn36xx_probe, | ||
1013 | .remove = wcn36xx_remove, | ||
1014 | .driver = { | ||
1015 | .name = "wcn36xx", | ||
1016 | .owner = THIS_MODULE, | ||
1017 | }, | ||
1018 | .id_table = wcn36xx_platform_id_table, | ||
1019 | }; | ||
1020 | |||
1021 | static int __init wcn36xx_init(void) | ||
1022 | { | ||
1023 | platform_driver_register(&wcn36xx_driver); | ||
1024 | return 0; | ||
1025 | } | ||
1026 | module_init(wcn36xx_init); | ||
1027 | |||
1028 | static void __exit wcn36xx_exit(void) | ||
1029 | { | ||
1030 | platform_driver_unregister(&wcn36xx_driver); | ||
1031 | } | ||
1032 | module_exit(wcn36xx_exit); | ||
1033 | |||
1034 | MODULE_LICENSE("Dual BSD/GPL"); | ||
1035 | MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com"); | ||
1036 | MODULE_FIRMWARE(WLAN_NV_FILE); | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/pmc.c b/drivers/net/wireless/ath/wcn36xx/pmc.c new file mode 100644 index 000000000000..28b515c81b0e --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/pmc.c | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
19 | #include "wcn36xx.h" | ||
20 | |||
21 | int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn, | ||
22 | struct ieee80211_vif *vif) | ||
23 | { | ||
24 | int ret = 0; | ||
25 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
26 | /* TODO: Make sure the TX chain clean */ | ||
27 | ret = wcn36xx_smd_enter_bmps(wcn, vif); | ||
28 | if (!ret) { | ||
29 | wcn36xx_dbg(WCN36XX_DBG_PMC, "Entered BMPS\n"); | ||
30 | vif_priv->pw_state = WCN36XX_BMPS; | ||
31 | } else { | ||
32 | /* | ||
33 | * One of the reasons why HW will not enter BMPS is because | ||
34 | * driver is trying to enter bmps before first beacon was | ||
35 | * received just after auth complete | ||
36 | */ | ||
37 | wcn36xx_err("Can not enter BMPS!\n"); | ||
38 | } | ||
39 | return ret; | ||
40 | } | ||
41 | |||
42 | int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn, | ||
43 | struct ieee80211_vif *vif) | ||
44 | { | ||
45 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
46 | |||
47 | if (WCN36XX_BMPS != vif_priv->pw_state) { | ||
48 | wcn36xx_err("Not in BMPS mode, no need to exit from BMPS mode!\n"); | ||
49 | return -EINVAL; | ||
50 | } | ||
51 | wcn36xx_smd_exit_bmps(wcn, vif); | ||
52 | vif_priv->pw_state = WCN36XX_FULL_POWER; | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | int wcn36xx_enable_keep_alive_null_packet(struct wcn36xx *wcn, | ||
57 | struct ieee80211_vif *vif) | ||
58 | { | ||
59 | wcn36xx_dbg(WCN36XX_DBG_PMC, "%s\n", __func__); | ||
60 | return wcn36xx_smd_keep_alive_req(wcn, vif, | ||
61 | WCN36XX_HAL_KEEP_ALIVE_NULL_PKT); | ||
62 | } | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/pmc.h b/drivers/net/wireless/ath/wcn36xx/pmc.h new file mode 100644 index 000000000000..f72ed68b5a07 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/pmc.h | |||
@@ -0,0 +1,33 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _WCN36XX_PMC_H_ | ||
18 | #define _WCN36XX_PMC_H_ | ||
19 | |||
20 | struct wcn36xx; | ||
21 | |||
22 | enum wcn36xx_power_state { | ||
23 | WCN36XX_FULL_POWER, | ||
24 | WCN36XX_BMPS | ||
25 | }; | ||
26 | |||
27 | int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn, | ||
28 | struct ieee80211_vif *vif); | ||
29 | int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn, | ||
30 | struct ieee80211_vif *vif); | ||
31 | int wcn36xx_enable_keep_alive_null_packet(struct wcn36xx *wcn, | ||
32 | struct ieee80211_vif *vif); | ||
33 | #endif /* _WCN36XX_PMC_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c new file mode 100644 index 000000000000..f8c3a10510c2 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/smd.c | |||
@@ -0,0 +1,2126 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
19 | #include <linux/etherdevice.h> | ||
20 | #include <linux/firmware.h> | ||
21 | #include <linux/bitops.h> | ||
22 | #include "smd.h" | ||
23 | |||
24 | static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value) | ||
25 | { | ||
26 | struct wcn36xx_hal_cfg *entry; | ||
27 | u32 *val; | ||
28 | |||
29 | if (*len + sizeof(*entry) + sizeof(u32) >= WCN36XX_HAL_BUF_SIZE) { | ||
30 | wcn36xx_err("Not enough room for TLV entry\n"); | ||
31 | return -ENOMEM; | ||
32 | } | ||
33 | |||
34 | entry = (struct wcn36xx_hal_cfg *) (wcn->hal_buf + *len); | ||
35 | entry->id = id; | ||
36 | entry->len = sizeof(u32); | ||
37 | entry->pad_bytes = 0; | ||
38 | entry->reserve = 0; | ||
39 | |||
40 | val = (u32 *) (entry + 1); | ||
41 | *val = value; | ||
42 | |||
43 | *len += sizeof(*entry) + sizeof(u32); | ||
44 | |||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | static void wcn36xx_smd_set_bss_nw_type(struct wcn36xx *wcn, | ||
49 | struct ieee80211_sta *sta, | ||
50 | struct wcn36xx_hal_config_bss_params *bss_params) | ||
51 | { | ||
52 | if (IEEE80211_BAND_5GHZ == WCN36XX_BAND(wcn)) | ||
53 | bss_params->nw_type = WCN36XX_HAL_11A_NW_TYPE; | ||
54 | else if (sta && sta->ht_cap.ht_supported) | ||
55 | bss_params->nw_type = WCN36XX_HAL_11N_NW_TYPE; | ||
56 | else if (sta && (sta->supp_rates[IEEE80211_BAND_2GHZ] & 0x7f)) | ||
57 | bss_params->nw_type = WCN36XX_HAL_11G_NW_TYPE; | ||
58 | else | ||
59 | bss_params->nw_type = WCN36XX_HAL_11B_NW_TYPE; | ||
60 | } | ||
61 | |||
62 | static inline u8 is_cap_supported(unsigned long caps, unsigned long flag) | ||
63 | { | ||
64 | return caps & flag ? 1 : 0; | ||
65 | } | ||
66 | static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif *vif, | ||
67 | struct ieee80211_sta *sta, | ||
68 | struct wcn36xx_hal_config_bss_params *bss_params) | ||
69 | { | ||
70 | if (sta && sta->ht_cap.ht_supported) { | ||
71 | unsigned long caps = sta->ht_cap.cap; | ||
72 | bss_params->ht = sta->ht_cap.ht_supported; | ||
73 | bss_params->tx_channel_width_set = is_cap_supported(caps, | ||
74 | IEEE80211_HT_CAP_SUP_WIDTH_20_40); | ||
75 | bss_params->lsig_tx_op_protection_full_support = | ||
76 | is_cap_supported(caps, | ||
77 | IEEE80211_HT_CAP_LSIG_TXOP_PROT); | ||
78 | |||
79 | bss_params->ht_oper_mode = vif->bss_conf.ht_operation_mode; | ||
80 | bss_params->lln_non_gf_coexist = | ||
81 | !!(vif->bss_conf.ht_operation_mode & | ||
82 | IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); | ||
83 | /* IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT */ | ||
84 | bss_params->dual_cts_protection = 0; | ||
85 | /* IEEE80211_HT_OP_MODE_PROTECTION_20MHZ */ | ||
86 | bss_params->ht20_coexist = 0; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta, | ||
91 | struct wcn36xx_hal_config_sta_params *sta_params) | ||
92 | { | ||
93 | if (sta->ht_cap.ht_supported) { | ||
94 | unsigned long caps = sta->ht_cap.cap; | ||
95 | sta_params->ht_capable = sta->ht_cap.ht_supported; | ||
96 | sta_params->tx_channel_width_set = is_cap_supported(caps, | ||
97 | IEEE80211_HT_CAP_SUP_WIDTH_20_40); | ||
98 | sta_params->lsig_txop_protection = is_cap_supported(caps, | ||
99 | IEEE80211_HT_CAP_LSIG_TXOP_PROT); | ||
100 | |||
101 | sta_params->max_ampdu_size = sta->ht_cap.ampdu_factor; | ||
102 | sta_params->max_ampdu_density = sta->ht_cap.ampdu_density; | ||
103 | sta_params->max_amsdu_size = is_cap_supported(caps, | ||
104 | IEEE80211_HT_CAP_MAX_AMSDU); | ||
105 | sta_params->sgi_20Mhz = is_cap_supported(caps, | ||
106 | IEEE80211_HT_CAP_SGI_20); | ||
107 | sta_params->sgi_40mhz = is_cap_supported(caps, | ||
108 | IEEE80211_HT_CAP_SGI_40); | ||
109 | sta_params->green_field_capable = is_cap_supported(caps, | ||
110 | IEEE80211_HT_CAP_GRN_FLD); | ||
111 | sta_params->delayed_ba_support = is_cap_supported(caps, | ||
112 | IEEE80211_HT_CAP_DELAY_BA); | ||
113 | sta_params->dsss_cck_mode_40mhz = is_cap_supported(caps, | ||
114 | IEEE80211_HT_CAP_DSSSCCK40); | ||
115 | } | ||
116 | } | ||
117 | |||
118 | static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, | ||
119 | struct ieee80211_vif *vif, | ||
120 | struct ieee80211_sta *sta, | ||
121 | struct wcn36xx_hal_config_sta_params *sta_params) | ||
122 | { | ||
123 | struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; | ||
124 | struct wcn36xx_sta *priv_sta = NULL; | ||
125 | if (vif->type == NL80211_IFTYPE_ADHOC || | ||
126 | vif->type == NL80211_IFTYPE_AP || | ||
127 | vif->type == NL80211_IFTYPE_MESH_POINT) { | ||
128 | sta_params->type = 1; | ||
129 | sta_params->sta_index = 0xFF; | ||
130 | } else { | ||
131 | sta_params->type = 0; | ||
132 | sta_params->sta_index = 1; | ||
133 | } | ||
134 | |||
135 | sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn); | ||
136 | |||
137 | /* | ||
138 | * In STA mode ieee80211_sta contains bssid and ieee80211_vif | ||
139 | * contains our mac address. In AP mode we are bssid so vif | ||
140 | * contains bssid and ieee80211_sta contains mac. | ||
141 | */ | ||
142 | if (NL80211_IFTYPE_STATION == vif->type) | ||
143 | memcpy(&sta_params->mac, vif->addr, ETH_ALEN); | ||
144 | else | ||
145 | memcpy(&sta_params->bssid, vif->addr, ETH_ALEN); | ||
146 | |||
147 | sta_params->encrypt_type = priv_vif->encrypt_type; | ||
148 | sta_params->short_preamble_supported = | ||
149 | !(WCN36XX_FLAGS(wcn) & | ||
150 | IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE); | ||
151 | |||
152 | sta_params->rifs_mode = 0; | ||
153 | sta_params->rmf = 0; | ||
154 | sta_params->action = 0; | ||
155 | sta_params->uapsd = 0; | ||
156 | sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC; | ||
157 | sta_params->max_ampdu_duration = 0; | ||
158 | sta_params->bssid_index = priv_vif->bss_index; | ||
159 | sta_params->p2p = 0; | ||
160 | |||
161 | if (sta) { | ||
162 | priv_sta = (struct wcn36xx_sta *)sta->drv_priv; | ||
163 | if (NL80211_IFTYPE_STATION == vif->type) | ||
164 | memcpy(&sta_params->bssid, sta->addr, ETH_ALEN); | ||
165 | else | ||
166 | memcpy(&sta_params->mac, sta->addr, ETH_ALEN); | ||
167 | sta_params->wmm_enabled = sta->wme; | ||
168 | sta_params->max_sp_len = sta->max_sp; | ||
169 | sta_params->aid = priv_sta->aid; | ||
170 | wcn36xx_smd_set_sta_ht_params(sta, sta_params); | ||
171 | memcpy(&sta_params->supported_rates, &priv_sta->supported_rates, | ||
172 | sizeof(priv_sta->supported_rates)); | ||
173 | } else { | ||
174 | wcn36xx_set_default_rates(&sta_params->supported_rates); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len) | ||
179 | { | ||
180 | int ret = 0; | ||
181 | wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "HAL >>> ", wcn->hal_buf, len); | ||
182 | |||
183 | init_completion(&wcn->hal_rsp_compl); | ||
184 | ret = wcn->ctrl_ops->tx(wcn->hal_buf, len); | ||
185 | if (ret) { | ||
186 | wcn36xx_err("HAL TX failed\n"); | ||
187 | goto out; | ||
188 | } | ||
189 | if (wait_for_completion_timeout(&wcn->hal_rsp_compl, | ||
190 | msecs_to_jiffies(HAL_MSG_TIMEOUT)) <= 0) { | ||
191 | wcn36xx_err("Timeout while waiting SMD response\n"); | ||
192 | ret = -ETIME; | ||
193 | goto out; | ||
194 | } | ||
195 | out: | ||
196 | return ret; | ||
197 | } | ||
198 | |||
199 | #define INIT_HAL_MSG(msg_body, type) \ | ||
200 | do { \ | ||
201 | memset(&msg_body, 0, sizeof(msg_body)); \ | ||
202 | msg_body.header.msg_type = type; \ | ||
203 | msg_body.header.msg_version = WCN36XX_HAL_MSG_VERSION0; \ | ||
204 | msg_body.header.len = sizeof(msg_body); \ | ||
205 | } while (0) \ | ||
206 | |||
207 | #define PREPARE_HAL_BUF(send_buf, msg_body) \ | ||
208 | do { \ | ||
209 | memset(send_buf, 0, msg_body.header.len); \ | ||
210 | memcpy(send_buf, &msg_body, sizeof(msg_body)); \ | ||
211 | } while (0) \ | ||
212 | |||
213 | static int wcn36xx_smd_rsp_status_check(void *buf, size_t len) | ||
214 | { | ||
215 | struct wcn36xx_fw_msg_status_rsp *rsp; | ||
216 | |||
217 | if (len < sizeof(struct wcn36xx_hal_msg_header) + | ||
218 | sizeof(struct wcn36xx_fw_msg_status_rsp)) | ||
219 | return -EIO; | ||
220 | |||
221 | rsp = (struct wcn36xx_fw_msg_status_rsp *) | ||
222 | (buf + sizeof(struct wcn36xx_hal_msg_header)); | ||
223 | |||
224 | if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) | ||
225 | return rsp->status; | ||
226 | |||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | int wcn36xx_smd_load_nv(struct wcn36xx *wcn) | ||
231 | { | ||
232 | const struct firmware *nv; | ||
233 | struct nv_data *nv_d; | ||
234 | struct wcn36xx_hal_nv_img_download_req_msg msg_body; | ||
235 | int fw_bytes_left; | ||
236 | int ret; | ||
237 | u16 fm_offset = 0; | ||
238 | |||
239 | ret = request_firmware(&nv, WLAN_NV_FILE, wcn->dev); | ||
240 | if (ret) { | ||
241 | wcn36xx_err("Failed to load nv file %s: %d\n", | ||
242 | WLAN_NV_FILE, ret); | ||
243 | goto out_free_nv; | ||
244 | } | ||
245 | |||
246 | nv_d = (struct nv_data *)nv->data; | ||
247 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ); | ||
248 | |||
249 | msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE; | ||
250 | |||
251 | msg_body.frag_number = 0; | ||
252 | /* hal_buf must be protected with mutex */ | ||
253 | mutex_lock(&wcn->hal_mutex); | ||
254 | |||
255 | do { | ||
256 | fw_bytes_left = nv->size - fm_offset - 4; | ||
257 | if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) { | ||
258 | msg_body.last_fragment = 0; | ||
259 | msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE; | ||
260 | } else { | ||
261 | msg_body.last_fragment = 1; | ||
262 | msg_body.nv_img_buffer_size = fw_bytes_left; | ||
263 | |||
264 | /* Do not forget update general message len */ | ||
265 | msg_body.header.len = sizeof(msg_body) + fw_bytes_left; | ||
266 | |||
267 | } | ||
268 | |||
269 | /* Add load NV request message header */ | ||
270 | memcpy(wcn->hal_buf, &msg_body, sizeof(msg_body)); | ||
271 | |||
272 | /* Add NV body itself */ | ||
273 | memcpy(wcn->hal_buf + sizeof(msg_body), | ||
274 | &nv_d->table + fm_offset, | ||
275 | msg_body.nv_img_buffer_size); | ||
276 | |||
277 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
278 | if (ret) | ||
279 | goto out_unlock; | ||
280 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, | ||
281 | wcn->hal_rsp_len); | ||
282 | if (ret) { | ||
283 | wcn36xx_err("hal_load_nv response failed err=%d\n", | ||
284 | ret); | ||
285 | goto out_unlock; | ||
286 | } | ||
287 | msg_body.frag_number++; | ||
288 | fm_offset += WCN36XX_NV_FRAGMENT_SIZE; | ||
289 | |||
290 | } while (msg_body.last_fragment != 1); | ||
291 | |||
292 | out_unlock: | ||
293 | mutex_unlock(&wcn->hal_mutex); | ||
294 | out_free_nv: | ||
295 | release_firmware(nv); | ||
296 | |||
297 | return ret; | ||
298 | } | ||
299 | |||
300 | static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len) | ||
301 | { | ||
302 | struct wcn36xx_hal_mac_start_rsp_msg *rsp; | ||
303 | |||
304 | if (len < sizeof(*rsp)) | ||
305 | return -EIO; | ||
306 | |||
307 | rsp = (struct wcn36xx_hal_mac_start_rsp_msg *)buf; | ||
308 | |||
309 | if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->start_rsp_params.status) | ||
310 | return -EIO; | ||
311 | |||
312 | memcpy(wcn->crm_version, rsp->start_rsp_params.crm_version, | ||
313 | WCN36XX_HAL_VERSION_LENGTH); | ||
314 | memcpy(wcn->wlan_version, rsp->start_rsp_params.wlan_version, | ||
315 | WCN36XX_HAL_VERSION_LENGTH); | ||
316 | |||
317 | /* null terminate the strings, just in case */ | ||
318 | wcn->crm_version[WCN36XX_HAL_VERSION_LENGTH] = '\0'; | ||
319 | wcn->wlan_version[WCN36XX_HAL_VERSION_LENGTH] = '\0'; | ||
320 | |||
321 | wcn->fw_revision = rsp->start_rsp_params.version.revision; | ||
322 | wcn->fw_version = rsp->start_rsp_params.version.version; | ||
323 | wcn->fw_minor = rsp->start_rsp_params.version.minor; | ||
324 | wcn->fw_major = rsp->start_rsp_params.version.major; | ||
325 | |||
326 | wcn36xx_info("firmware WLAN version '%s' and CRM version '%s'\n", | ||
327 | wcn->wlan_version, wcn->crm_version); | ||
328 | |||
329 | wcn36xx_info("firmware API %u.%u.%u.%u, %u stations, %u bssids\n", | ||
330 | wcn->fw_major, wcn->fw_minor, | ||
331 | wcn->fw_version, wcn->fw_revision, | ||
332 | rsp->start_rsp_params.stations, | ||
333 | rsp->start_rsp_params.bssids); | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | int wcn36xx_smd_start(struct wcn36xx *wcn) | ||
339 | { | ||
340 | struct wcn36xx_hal_mac_start_req_msg msg_body; | ||
341 | int ret = 0; | ||
342 | |||
343 | mutex_lock(&wcn->hal_mutex); | ||
344 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ); | ||
345 | |||
346 | msg_body.params.type = DRIVER_TYPE_PRODUCTION; | ||
347 | msg_body.params.len = 0; | ||
348 | |||
349 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
350 | |||
351 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start type %d\n", | ||
352 | msg_body.params.type); | ||
353 | |||
354 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
355 | if (ret) { | ||
356 | wcn36xx_err("Sending hal_start failed\n"); | ||
357 | goto out; | ||
358 | } | ||
359 | |||
360 | ret = wcn36xx_smd_start_rsp(wcn, wcn->hal_buf, wcn->hal_rsp_len); | ||
361 | if (ret) { | ||
362 | wcn36xx_err("hal_start response failed err=%d\n", ret); | ||
363 | goto out; | ||
364 | } | ||
365 | |||
366 | out: | ||
367 | mutex_unlock(&wcn->hal_mutex); | ||
368 | return ret; | ||
369 | } | ||
370 | |||
371 | int wcn36xx_smd_stop(struct wcn36xx *wcn) | ||
372 | { | ||
373 | struct wcn36xx_hal_mac_stop_req_msg msg_body; | ||
374 | int ret = 0; | ||
375 | |||
376 | mutex_lock(&wcn->hal_mutex); | ||
377 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_REQ); | ||
378 | |||
379 | msg_body.stop_req_params.reason = HAL_STOP_TYPE_RF_KILL; | ||
380 | |||
381 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
382 | |||
383 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
384 | if (ret) { | ||
385 | wcn36xx_err("Sending hal_stop failed\n"); | ||
386 | goto out; | ||
387 | } | ||
388 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
389 | if (ret) { | ||
390 | wcn36xx_err("hal_stop response failed err=%d\n", ret); | ||
391 | goto out; | ||
392 | } | ||
393 | out: | ||
394 | mutex_unlock(&wcn->hal_mutex); | ||
395 | return ret; | ||
396 | } | ||
397 | |||
398 | int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode) | ||
399 | { | ||
400 | struct wcn36xx_hal_init_scan_req_msg msg_body; | ||
401 | int ret = 0; | ||
402 | |||
403 | mutex_lock(&wcn->hal_mutex); | ||
404 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_INIT_SCAN_REQ); | ||
405 | |||
406 | msg_body.mode = mode; | ||
407 | |||
408 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
409 | |||
410 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal init scan mode %d\n", msg_body.mode); | ||
411 | |||
412 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
413 | if (ret) { | ||
414 | wcn36xx_err("Sending hal_init_scan failed\n"); | ||
415 | goto out; | ||
416 | } | ||
417 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
418 | if (ret) { | ||
419 | wcn36xx_err("hal_init_scan response failed err=%d\n", ret); | ||
420 | goto out; | ||
421 | } | ||
422 | out: | ||
423 | mutex_unlock(&wcn->hal_mutex); | ||
424 | return ret; | ||
425 | } | ||
426 | |||
427 | int wcn36xx_smd_start_scan(struct wcn36xx *wcn) | ||
428 | { | ||
429 | struct wcn36xx_hal_start_scan_req_msg msg_body; | ||
430 | int ret = 0; | ||
431 | |||
432 | mutex_lock(&wcn->hal_mutex); | ||
433 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_REQ); | ||
434 | |||
435 | msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn); | ||
436 | |||
437 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
438 | |||
439 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start scan channel %d\n", | ||
440 | msg_body.scan_channel); | ||
441 | |||
442 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
443 | if (ret) { | ||
444 | wcn36xx_err("Sending hal_start_scan failed\n"); | ||
445 | goto out; | ||
446 | } | ||
447 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
448 | if (ret) { | ||
449 | wcn36xx_err("hal_start_scan response failed err=%d\n", ret); | ||
450 | goto out; | ||
451 | } | ||
452 | out: | ||
453 | mutex_unlock(&wcn->hal_mutex); | ||
454 | return ret; | ||
455 | } | ||
456 | |||
457 | int wcn36xx_smd_end_scan(struct wcn36xx *wcn) | ||
458 | { | ||
459 | struct wcn36xx_hal_end_scan_req_msg msg_body; | ||
460 | int ret = 0; | ||
461 | |||
462 | mutex_lock(&wcn->hal_mutex); | ||
463 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ); | ||
464 | |||
465 | msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn); | ||
466 | |||
467 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
468 | |||
469 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal end scan channel %d\n", | ||
470 | msg_body.scan_channel); | ||
471 | |||
472 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
473 | if (ret) { | ||
474 | wcn36xx_err("Sending hal_end_scan failed\n"); | ||
475 | goto out; | ||
476 | } | ||
477 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
478 | if (ret) { | ||
479 | wcn36xx_err("hal_end_scan response failed err=%d\n", ret); | ||
480 | goto out; | ||
481 | } | ||
482 | out: | ||
483 | mutex_unlock(&wcn->hal_mutex); | ||
484 | return ret; | ||
485 | } | ||
486 | |||
487 | int wcn36xx_smd_finish_scan(struct wcn36xx *wcn, | ||
488 | enum wcn36xx_hal_sys_mode mode) | ||
489 | { | ||
490 | struct wcn36xx_hal_finish_scan_req_msg msg_body; | ||
491 | int ret = 0; | ||
492 | |||
493 | mutex_lock(&wcn->hal_mutex); | ||
494 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_FINISH_SCAN_REQ); | ||
495 | |||
496 | msg_body.mode = mode; | ||
497 | |||
498 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
499 | |||
500 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal finish scan mode %d\n", | ||
501 | msg_body.mode); | ||
502 | |||
503 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
504 | if (ret) { | ||
505 | wcn36xx_err("Sending hal_finish_scan failed\n"); | ||
506 | goto out; | ||
507 | } | ||
508 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
509 | if (ret) { | ||
510 | wcn36xx_err("hal_finish_scan response failed err=%d\n", ret); | ||
511 | goto out; | ||
512 | } | ||
513 | out: | ||
514 | mutex_unlock(&wcn->hal_mutex); | ||
515 | return ret; | ||
516 | } | ||
517 | |||
518 | static int wcn36xx_smd_switch_channel_rsp(void *buf, size_t len) | ||
519 | { | ||
520 | struct wcn36xx_hal_switch_channel_rsp_msg *rsp; | ||
521 | int ret = 0; | ||
522 | |||
523 | ret = wcn36xx_smd_rsp_status_check(buf, len); | ||
524 | if (ret) | ||
525 | return ret; | ||
526 | rsp = (struct wcn36xx_hal_switch_channel_rsp_msg *)buf; | ||
527 | wcn36xx_dbg(WCN36XX_DBG_HAL, "channel switched to: %d, status: %d\n", | ||
528 | rsp->channel_number, rsp->status); | ||
529 | return ret; | ||
530 | } | ||
531 | |||
532 | int wcn36xx_smd_switch_channel(struct wcn36xx *wcn, | ||
533 | struct ieee80211_vif *vif, int ch) | ||
534 | { | ||
535 | struct wcn36xx_hal_switch_channel_req_msg msg_body; | ||
536 | int ret = 0; | ||
537 | |||
538 | mutex_lock(&wcn->hal_mutex); | ||
539 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_CH_SWITCH_REQ); | ||
540 | |||
541 | msg_body.channel_number = (u8)ch; | ||
542 | msg_body.tx_mgmt_power = 0xbf; | ||
543 | msg_body.max_tx_power = 0xbf; | ||
544 | memcpy(msg_body.self_sta_mac_addr, vif->addr, ETH_ALEN); | ||
545 | |||
546 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
547 | |||
548 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
549 | if (ret) { | ||
550 | wcn36xx_err("Sending hal_switch_channel failed\n"); | ||
551 | goto out; | ||
552 | } | ||
553 | ret = wcn36xx_smd_switch_channel_rsp(wcn->hal_buf, wcn->hal_rsp_len); | ||
554 | if (ret) { | ||
555 | wcn36xx_err("hal_switch_channel response failed err=%d\n", ret); | ||
556 | goto out; | ||
557 | } | ||
558 | out: | ||
559 | mutex_unlock(&wcn->hal_mutex); | ||
560 | return ret; | ||
561 | } | ||
562 | |||
563 | static int wcn36xx_smd_update_scan_params_rsp(void *buf, size_t len) | ||
564 | { | ||
565 | struct wcn36xx_hal_update_scan_params_resp *rsp; | ||
566 | |||
567 | rsp = (struct wcn36xx_hal_update_scan_params_resp *)buf; | ||
568 | |||
569 | /* Remove the PNO version bit */ | ||
570 | rsp->status &= (~(WCN36XX_FW_MSG_PNO_VERSION_MASK)); | ||
571 | |||
572 | if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) { | ||
573 | wcn36xx_warn("error response from update scan\n"); | ||
574 | return rsp->status; | ||
575 | } | ||
576 | |||
577 | return 0; | ||
578 | } | ||
579 | |||
580 | int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn) | ||
581 | { | ||
582 | struct wcn36xx_hal_update_scan_params_req msg_body; | ||
583 | int ret = 0; | ||
584 | |||
585 | mutex_lock(&wcn->hal_mutex); | ||
586 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ); | ||
587 | |||
588 | msg_body.dot11d_enabled = 0; | ||
589 | msg_body.dot11d_resolved = 0; | ||
590 | msg_body.channel_count = 26; | ||
591 | msg_body.active_min_ch_time = 60; | ||
592 | msg_body.active_max_ch_time = 120; | ||
593 | msg_body.passive_min_ch_time = 60; | ||
594 | msg_body.passive_max_ch_time = 110; | ||
595 | msg_body.state = 0; | ||
596 | |||
597 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
598 | |||
599 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
600 | "hal update scan params channel_count %d\n", | ||
601 | msg_body.channel_count); | ||
602 | |||
603 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
604 | if (ret) { | ||
605 | wcn36xx_err("Sending hal_update_scan_params failed\n"); | ||
606 | goto out; | ||
607 | } | ||
608 | ret = wcn36xx_smd_update_scan_params_rsp(wcn->hal_buf, | ||
609 | wcn->hal_rsp_len); | ||
610 | if (ret) { | ||
611 | wcn36xx_err("hal_update_scan_params response failed err=%d\n", | ||
612 | ret); | ||
613 | goto out; | ||
614 | } | ||
615 | out: | ||
616 | mutex_unlock(&wcn->hal_mutex); | ||
617 | return ret; | ||
618 | } | ||
619 | |||
620 | static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn, | ||
621 | struct ieee80211_vif *vif, | ||
622 | void *buf, | ||
623 | size_t len) | ||
624 | { | ||
625 | struct wcn36xx_hal_add_sta_self_rsp_msg *rsp; | ||
626 | struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; | ||
627 | |||
628 | if (len < sizeof(*rsp)) | ||
629 | return -EINVAL; | ||
630 | |||
631 | rsp = (struct wcn36xx_hal_add_sta_self_rsp_msg *)buf; | ||
632 | |||
633 | if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { | ||
634 | wcn36xx_warn("hal add sta self failure: %d\n", | ||
635 | rsp->status); | ||
636 | return rsp->status; | ||
637 | } | ||
638 | |||
639 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
640 | "hal add sta self status %d self_sta_index %d dpu_index %d\n", | ||
641 | rsp->status, rsp->self_sta_index, rsp->dpu_index); | ||
642 | |||
643 | priv_vif->self_sta_index = rsp->self_sta_index; | ||
644 | priv_vif->self_dpu_desc_index = rsp->dpu_index; | ||
645 | |||
646 | return 0; | ||
647 | } | ||
648 | |||
649 | int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif) | ||
650 | { | ||
651 | struct wcn36xx_hal_add_sta_self_req msg_body; | ||
652 | int ret = 0; | ||
653 | |||
654 | mutex_lock(&wcn->hal_mutex); | ||
655 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_STA_SELF_REQ); | ||
656 | |||
657 | memcpy(&msg_body.self_addr, vif->addr, ETH_ALEN); | ||
658 | |||
659 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
660 | |||
661 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
662 | "hal add sta self self_addr %pM status %d\n", | ||
663 | msg_body.self_addr, msg_body.status); | ||
664 | |||
665 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
666 | if (ret) { | ||
667 | wcn36xx_err("Sending hal_add_sta_self failed\n"); | ||
668 | goto out; | ||
669 | } | ||
670 | ret = wcn36xx_smd_add_sta_self_rsp(wcn, | ||
671 | vif, | ||
672 | wcn->hal_buf, | ||
673 | wcn->hal_rsp_len); | ||
674 | if (ret) { | ||
675 | wcn36xx_err("hal_add_sta_self response failed err=%d\n", ret); | ||
676 | goto out; | ||
677 | } | ||
678 | out: | ||
679 | mutex_unlock(&wcn->hal_mutex); | ||
680 | return ret; | ||
681 | } | ||
682 | |||
683 | int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr) | ||
684 | { | ||
685 | struct wcn36xx_hal_del_sta_self_req_msg msg_body; | ||
686 | int ret = 0; | ||
687 | |||
688 | mutex_lock(&wcn->hal_mutex); | ||
689 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_STA_SELF_REQ); | ||
690 | |||
691 | memcpy(&msg_body.self_addr, addr, ETH_ALEN); | ||
692 | |||
693 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
694 | |||
695 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
696 | if (ret) { | ||
697 | wcn36xx_err("Sending hal_delete_sta_self failed\n"); | ||
698 | goto out; | ||
699 | } | ||
700 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
701 | if (ret) { | ||
702 | wcn36xx_err("hal_delete_sta_self response failed err=%d\n", | ||
703 | ret); | ||
704 | goto out; | ||
705 | } | ||
706 | out: | ||
707 | mutex_unlock(&wcn->hal_mutex); | ||
708 | return ret; | ||
709 | } | ||
710 | |||
711 | int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index) | ||
712 | { | ||
713 | struct wcn36xx_hal_delete_sta_req_msg msg_body; | ||
714 | int ret = 0; | ||
715 | |||
716 | mutex_lock(&wcn->hal_mutex); | ||
717 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_STA_REQ); | ||
718 | |||
719 | msg_body.sta_index = sta_index; | ||
720 | |||
721 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
722 | |||
723 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
724 | "hal delete sta sta_index %d\n", | ||
725 | msg_body.sta_index); | ||
726 | |||
727 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
728 | if (ret) { | ||
729 | wcn36xx_err("Sending hal_delete_sta failed\n"); | ||
730 | goto out; | ||
731 | } | ||
732 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
733 | if (ret) { | ||
734 | wcn36xx_err("hal_delete_sta response failed err=%d\n", ret); | ||
735 | goto out; | ||
736 | } | ||
737 | out: | ||
738 | mutex_unlock(&wcn->hal_mutex); | ||
739 | return ret; | ||
740 | } | ||
741 | |||
742 | static int wcn36xx_smd_join_rsp(void *buf, size_t len) | ||
743 | { | ||
744 | struct wcn36xx_hal_join_rsp_msg *rsp; | ||
745 | |||
746 | if (wcn36xx_smd_rsp_status_check(buf, len)) | ||
747 | return -EIO; | ||
748 | |||
749 | rsp = (struct wcn36xx_hal_join_rsp_msg *)buf; | ||
750 | |||
751 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
752 | "hal rsp join status %d tx_mgmt_power %d\n", | ||
753 | rsp->status, rsp->tx_mgmt_power); | ||
754 | |||
755 | return 0; | ||
756 | } | ||
757 | |||
758 | int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch) | ||
759 | { | ||
760 | struct wcn36xx_hal_join_req_msg msg_body; | ||
761 | int ret = 0; | ||
762 | |||
763 | mutex_lock(&wcn->hal_mutex); | ||
764 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_JOIN_REQ); | ||
765 | |||
766 | memcpy(&msg_body.bssid, bssid, ETH_ALEN); | ||
767 | memcpy(&msg_body.self_sta_mac_addr, vif, ETH_ALEN); | ||
768 | msg_body.channel = ch; | ||
769 | |||
770 | if (conf_is_ht40_minus(&wcn->hw->conf)) | ||
771 | msg_body.secondary_channel_offset = | ||
772 | PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; | ||
773 | else if (conf_is_ht40_plus(&wcn->hw->conf)) | ||
774 | msg_body.secondary_channel_offset = | ||
775 | PHY_DOUBLE_CHANNEL_LOW_PRIMARY; | ||
776 | else | ||
777 | msg_body.secondary_channel_offset = | ||
778 | PHY_SINGLE_CHANNEL_CENTERED; | ||
779 | |||
780 | msg_body.link_state = WCN36XX_HAL_LINK_PREASSOC_STATE; | ||
781 | |||
782 | msg_body.max_tx_power = 0xbf; | ||
783 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
784 | |||
785 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
786 | "hal join req bssid %pM self_sta_mac_addr %pM channel %d link_state %d\n", | ||
787 | msg_body.bssid, msg_body.self_sta_mac_addr, | ||
788 | msg_body.channel, msg_body.link_state); | ||
789 | |||
790 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
791 | if (ret) { | ||
792 | wcn36xx_err("Sending hal_join failed\n"); | ||
793 | goto out; | ||
794 | } | ||
795 | ret = wcn36xx_smd_join_rsp(wcn->hal_buf, wcn->hal_rsp_len); | ||
796 | if (ret) { | ||
797 | wcn36xx_err("hal_join response failed err=%d\n", ret); | ||
798 | goto out; | ||
799 | } | ||
800 | out: | ||
801 | mutex_unlock(&wcn->hal_mutex); | ||
802 | return ret; | ||
803 | } | ||
804 | |||
805 | int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid, | ||
806 | const u8 *sta_mac, | ||
807 | enum wcn36xx_hal_link_state state) | ||
808 | { | ||
809 | struct wcn36xx_hal_set_link_state_req_msg msg_body; | ||
810 | int ret = 0; | ||
811 | |||
812 | mutex_lock(&wcn->hal_mutex); | ||
813 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_LINK_ST_REQ); | ||
814 | |||
815 | memcpy(&msg_body.bssid, bssid, ETH_ALEN); | ||
816 | memcpy(&msg_body.self_mac_addr, sta_mac, ETH_ALEN); | ||
817 | msg_body.state = state; | ||
818 | |||
819 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
820 | |||
821 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
822 | "hal set link state bssid %pM self_mac_addr %pM state %d\n", | ||
823 | msg_body.bssid, msg_body.self_mac_addr, msg_body.state); | ||
824 | |||
825 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
826 | if (ret) { | ||
827 | wcn36xx_err("Sending hal_set_link_st failed\n"); | ||
828 | goto out; | ||
829 | } | ||
830 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
831 | if (ret) { | ||
832 | wcn36xx_err("hal_set_link_st response failed err=%d\n", ret); | ||
833 | goto out; | ||
834 | } | ||
835 | out: | ||
836 | mutex_unlock(&wcn->hal_mutex); | ||
837 | return ret; | ||
838 | } | ||
839 | |||
840 | static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn, | ||
841 | const struct wcn36xx_hal_config_sta_params *orig, | ||
842 | struct wcn36xx_hal_config_sta_params_v1 *v1) | ||
843 | { | ||
844 | /* convert orig to v1 format */ | ||
845 | memcpy(&v1->bssid, orig->bssid, ETH_ALEN); | ||
846 | memcpy(&v1->mac, orig->mac, ETH_ALEN); | ||
847 | v1->aid = orig->aid; | ||
848 | v1->type = orig->type; | ||
849 | v1->listen_interval = orig->listen_interval; | ||
850 | v1->ht_capable = orig->ht_capable; | ||
851 | |||
852 | v1->max_ampdu_size = orig->max_ampdu_size; | ||
853 | v1->max_ampdu_density = orig->max_ampdu_density; | ||
854 | v1->sgi_40mhz = orig->sgi_40mhz; | ||
855 | v1->sgi_20Mhz = orig->sgi_20Mhz; | ||
856 | |||
857 | memcpy(&v1->supported_rates, &orig->supported_rates, | ||
858 | sizeof(orig->supported_rates)); | ||
859 | v1->sta_index = orig->sta_index; | ||
860 | } | ||
861 | |||
862 | static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn, | ||
863 | struct ieee80211_sta *sta, | ||
864 | void *buf, | ||
865 | size_t len) | ||
866 | { | ||
867 | struct wcn36xx_hal_config_sta_rsp_msg *rsp; | ||
868 | struct config_sta_rsp_params *params; | ||
869 | struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; | ||
870 | |||
871 | if (len < sizeof(*rsp)) | ||
872 | return -EINVAL; | ||
873 | |||
874 | rsp = (struct wcn36xx_hal_config_sta_rsp_msg *)buf; | ||
875 | params = &rsp->params; | ||
876 | |||
877 | if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { | ||
878 | wcn36xx_warn("hal config sta response failure: %d\n", | ||
879 | params->status); | ||
880 | return -EIO; | ||
881 | } | ||
882 | |||
883 | sta_priv->sta_index = params->sta_index; | ||
884 | sta_priv->dpu_desc_index = params->dpu_index; | ||
885 | |||
886 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
887 | "hal config sta rsp status %d sta_index %d bssid_index %d p2p %d\n", | ||
888 | params->status, params->sta_index, params->bssid_index, | ||
889 | params->p2p); | ||
890 | |||
891 | return 0; | ||
892 | } | ||
893 | |||
894 | static int wcn36xx_smd_config_sta_v1(struct wcn36xx *wcn, | ||
895 | const struct wcn36xx_hal_config_sta_req_msg *orig) | ||
896 | { | ||
897 | struct wcn36xx_hal_config_sta_req_msg_v1 msg_body; | ||
898 | struct wcn36xx_hal_config_sta_params_v1 *sta = &msg_body.sta_params; | ||
899 | |||
900 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ); | ||
901 | |||
902 | wcn36xx_smd_convert_sta_to_v1(wcn, &orig->sta_params, | ||
903 | &msg_body.sta_params); | ||
904 | |||
905 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
906 | |||
907 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
908 | "hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n", | ||
909 | sta->action, sta->sta_index, sta->bssid_index, | ||
910 | sta->bssid, sta->type, sta->mac, sta->aid); | ||
911 | |||
912 | return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
913 | } | ||
914 | |||
915 | int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif, | ||
916 | struct ieee80211_sta *sta) | ||
917 | { | ||
918 | struct wcn36xx_hal_config_sta_req_msg msg; | ||
919 | struct wcn36xx_hal_config_sta_params *sta_params; | ||
920 | int ret = 0; | ||
921 | |||
922 | mutex_lock(&wcn->hal_mutex); | ||
923 | INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_STA_REQ); | ||
924 | |||
925 | sta_params = &msg.sta_params; | ||
926 | |||
927 | wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params); | ||
928 | |||
929 | if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { | ||
930 | ret = wcn36xx_smd_config_sta_v1(wcn, &msg); | ||
931 | } else { | ||
932 | PREPARE_HAL_BUF(wcn->hal_buf, msg); | ||
933 | |||
934 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
935 | "hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n", | ||
936 | sta_params->action, sta_params->sta_index, | ||
937 | sta_params->bssid_index, sta_params->bssid, | ||
938 | sta_params->type, sta_params->mac, sta_params->aid); | ||
939 | |||
940 | ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len); | ||
941 | } | ||
942 | if (ret) { | ||
943 | wcn36xx_err("Sending hal_config_sta failed\n"); | ||
944 | goto out; | ||
945 | } | ||
946 | ret = wcn36xx_smd_config_sta_rsp(wcn, | ||
947 | sta, | ||
948 | wcn->hal_buf, | ||
949 | wcn->hal_rsp_len); | ||
950 | if (ret) { | ||
951 | wcn36xx_err("hal_config_sta response failed err=%d\n", ret); | ||
952 | goto out; | ||
953 | } | ||
954 | out: | ||
955 | mutex_unlock(&wcn->hal_mutex); | ||
956 | return ret; | ||
957 | } | ||
958 | |||
959 | static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn, | ||
960 | const struct wcn36xx_hal_config_bss_req_msg *orig) | ||
961 | { | ||
962 | struct wcn36xx_hal_config_bss_req_msg_v1 msg_body; | ||
963 | struct wcn36xx_hal_config_bss_params_v1 *bss = &msg_body.bss_params; | ||
964 | struct wcn36xx_hal_config_sta_params_v1 *sta = &bss->sta; | ||
965 | |||
966 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_BSS_REQ); | ||
967 | |||
968 | /* convert orig to v1 */ | ||
969 | memcpy(&msg_body.bss_params.bssid, | ||
970 | &orig->bss_params.bssid, ETH_ALEN); | ||
971 | memcpy(&msg_body.bss_params.self_mac_addr, | ||
972 | &orig->bss_params.self_mac_addr, ETH_ALEN); | ||
973 | |||
974 | msg_body.bss_params.bss_type = orig->bss_params.bss_type; | ||
975 | msg_body.bss_params.oper_mode = orig->bss_params.oper_mode; | ||
976 | msg_body.bss_params.nw_type = orig->bss_params.nw_type; | ||
977 | |||
978 | msg_body.bss_params.short_slot_time_supported = | ||
979 | orig->bss_params.short_slot_time_supported; | ||
980 | msg_body.bss_params.lla_coexist = orig->bss_params.lla_coexist; | ||
981 | msg_body.bss_params.llb_coexist = orig->bss_params.llb_coexist; | ||
982 | msg_body.bss_params.llg_coexist = orig->bss_params.llg_coexist; | ||
983 | msg_body.bss_params.ht20_coexist = orig->bss_params.ht20_coexist; | ||
984 | msg_body.bss_params.lln_non_gf_coexist = | ||
985 | orig->bss_params.lln_non_gf_coexist; | ||
986 | |||
987 | msg_body.bss_params.lsig_tx_op_protection_full_support = | ||
988 | orig->bss_params.lsig_tx_op_protection_full_support; | ||
989 | msg_body.bss_params.rifs_mode = orig->bss_params.rifs_mode; | ||
990 | msg_body.bss_params.beacon_interval = orig->bss_params.beacon_interval; | ||
991 | msg_body.bss_params.dtim_period = orig->bss_params.dtim_period; | ||
992 | msg_body.bss_params.tx_channel_width_set = | ||
993 | orig->bss_params.tx_channel_width_set; | ||
994 | msg_body.bss_params.oper_channel = orig->bss_params.oper_channel; | ||
995 | msg_body.bss_params.ext_channel = orig->bss_params.ext_channel; | ||
996 | |||
997 | msg_body.bss_params.reserved = orig->bss_params.reserved; | ||
998 | |||
999 | memcpy(&msg_body.bss_params.ssid, | ||
1000 | &orig->bss_params.ssid, | ||
1001 | sizeof(orig->bss_params.ssid)); | ||
1002 | |||
1003 | msg_body.bss_params.action = orig->bss_params.action; | ||
1004 | msg_body.bss_params.rateset = orig->bss_params.rateset; | ||
1005 | msg_body.bss_params.ht = orig->bss_params.ht; | ||
1006 | msg_body.bss_params.obss_prot_enabled = | ||
1007 | orig->bss_params.obss_prot_enabled; | ||
1008 | msg_body.bss_params.rmf = orig->bss_params.rmf; | ||
1009 | msg_body.bss_params.ht_oper_mode = orig->bss_params.ht_oper_mode; | ||
1010 | msg_body.bss_params.dual_cts_protection = | ||
1011 | orig->bss_params.dual_cts_protection; | ||
1012 | |||
1013 | msg_body.bss_params.max_probe_resp_retry_limit = | ||
1014 | orig->bss_params.max_probe_resp_retry_limit; | ||
1015 | msg_body.bss_params.hidden_ssid = orig->bss_params.hidden_ssid; | ||
1016 | msg_body.bss_params.proxy_probe_resp = | ||
1017 | orig->bss_params.proxy_probe_resp; | ||
1018 | msg_body.bss_params.edca_params_valid = | ||
1019 | orig->bss_params.edca_params_valid; | ||
1020 | |||
1021 | memcpy(&msg_body.bss_params.acbe, | ||
1022 | &orig->bss_params.acbe, | ||
1023 | sizeof(orig->bss_params.acbe)); | ||
1024 | memcpy(&msg_body.bss_params.acbk, | ||
1025 | &orig->bss_params.acbk, | ||
1026 | sizeof(orig->bss_params.acbk)); | ||
1027 | memcpy(&msg_body.bss_params.acvi, | ||
1028 | &orig->bss_params.acvi, | ||
1029 | sizeof(orig->bss_params.acvi)); | ||
1030 | memcpy(&msg_body.bss_params.acvo, | ||
1031 | &orig->bss_params.acvo, | ||
1032 | sizeof(orig->bss_params.acvo)); | ||
1033 | |||
1034 | msg_body.bss_params.ext_set_sta_key_param_valid = | ||
1035 | orig->bss_params.ext_set_sta_key_param_valid; | ||
1036 | |||
1037 | memcpy(&msg_body.bss_params.ext_set_sta_key_param, | ||
1038 | &orig->bss_params.ext_set_sta_key_param, | ||
1039 | sizeof(orig->bss_params.acvo)); | ||
1040 | |||
1041 | msg_body.bss_params.wcn36xx_hal_persona = | ||
1042 | orig->bss_params.wcn36xx_hal_persona; | ||
1043 | msg_body.bss_params.spectrum_mgt_enable = | ||
1044 | orig->bss_params.spectrum_mgt_enable; | ||
1045 | msg_body.bss_params.tx_mgmt_power = orig->bss_params.tx_mgmt_power; | ||
1046 | msg_body.bss_params.max_tx_power = orig->bss_params.max_tx_power; | ||
1047 | |||
1048 | wcn36xx_smd_convert_sta_to_v1(wcn, &orig->bss_params.sta, | ||
1049 | &msg_body.bss_params.sta); | ||
1050 | |||
1051 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1052 | |||
1053 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
1054 | "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n", | ||
1055 | bss->bssid, bss->self_mac_addr, bss->bss_type, | ||
1056 | bss->oper_mode, bss->nw_type); | ||
1057 | |||
1058 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
1059 | "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n", | ||
1060 | sta->bssid, sta->action, sta->sta_index, | ||
1061 | sta->bssid_index, sta->aid, sta->type, sta->mac); | ||
1062 | |||
1063 | return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1064 | } | ||
1065 | |||
1066 | |||
1067 | static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, | ||
1068 | struct ieee80211_vif *vif, | ||
1069 | void *buf, | ||
1070 | size_t len) | ||
1071 | { | ||
1072 | struct wcn36xx_hal_config_bss_rsp_msg *rsp; | ||
1073 | struct wcn36xx_hal_config_bss_rsp_params *params; | ||
1074 | struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; | ||
1075 | |||
1076 | if (len < sizeof(*rsp)) | ||
1077 | return -EINVAL; | ||
1078 | |||
1079 | rsp = (struct wcn36xx_hal_config_bss_rsp_msg *)buf; | ||
1080 | params = &rsp->bss_rsp_params; | ||
1081 | |||
1082 | if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { | ||
1083 | wcn36xx_warn("hal config bss response failure: %d\n", | ||
1084 | params->status); | ||
1085 | return -EIO; | ||
1086 | } | ||
1087 | |||
1088 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
1089 | "hal config bss rsp status %d bss_idx %d dpu_desc_index %d" | ||
1090 | " sta_idx %d self_idx %d bcast_idx %d mac %pM" | ||
1091 | " power %d ucast_dpu_signature %d\n", | ||
1092 | params->status, params->bss_index, params->dpu_desc_index, | ||
1093 | params->bss_sta_index, params->bss_self_sta_index, | ||
1094 | params->bss_bcast_sta_idx, params->mac, | ||
1095 | params->tx_mgmt_power, params->ucast_dpu_signature); | ||
1096 | |||
1097 | priv_vif->bss_index = params->bss_index; | ||
1098 | |||
1099 | if (priv_vif->sta) { | ||
1100 | priv_vif->sta->bss_sta_index = params->bss_sta_index; | ||
1101 | priv_vif->sta->bss_dpu_desc_index = params->dpu_desc_index; | ||
1102 | } | ||
1103 | |||
1104 | priv_vif->ucast_dpu_signature = params->ucast_dpu_signature; | ||
1105 | |||
1106 | return 0; | ||
1107 | } | ||
1108 | |||
1109 | int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, | ||
1110 | struct ieee80211_sta *sta, const u8 *bssid, | ||
1111 | bool update) | ||
1112 | { | ||
1113 | struct wcn36xx_hal_config_bss_req_msg msg; | ||
1114 | struct wcn36xx_hal_config_bss_params *bss; | ||
1115 | struct wcn36xx_hal_config_sta_params *sta_params; | ||
1116 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
1117 | int ret = 0; | ||
1118 | |||
1119 | mutex_lock(&wcn->hal_mutex); | ||
1120 | INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_BSS_REQ); | ||
1121 | |||
1122 | bss = &msg.bss_params; | ||
1123 | sta_params = &bss->sta; | ||
1124 | |||
1125 | WARN_ON(is_zero_ether_addr(bssid)); | ||
1126 | |||
1127 | memcpy(&bss->bssid, bssid, ETH_ALEN); | ||
1128 | |||
1129 | memcpy(bss->self_mac_addr, vif->addr, ETH_ALEN); | ||
1130 | |||
1131 | if (vif->type == NL80211_IFTYPE_STATION) { | ||
1132 | bss->bss_type = WCN36XX_HAL_INFRASTRUCTURE_MODE; | ||
1133 | |||
1134 | /* STA */ | ||
1135 | bss->oper_mode = 1; | ||
1136 | bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_MODE; | ||
1137 | } else if (vif->type == NL80211_IFTYPE_AP) { | ||
1138 | bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE; | ||
1139 | |||
1140 | /* AP */ | ||
1141 | bss->oper_mode = 0; | ||
1142 | bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_SAP_MODE; | ||
1143 | } else if (vif->type == NL80211_IFTYPE_ADHOC || | ||
1144 | vif->type == NL80211_IFTYPE_MESH_POINT) { | ||
1145 | bss->bss_type = WCN36XX_HAL_IBSS_MODE; | ||
1146 | |||
1147 | /* STA */ | ||
1148 | bss->oper_mode = 1; | ||
1149 | } else { | ||
1150 | wcn36xx_warn("Unknown type for bss config: %d\n", vif->type); | ||
1151 | } | ||
1152 | |||
1153 | if (vif->type == NL80211_IFTYPE_STATION) | ||
1154 | wcn36xx_smd_set_bss_nw_type(wcn, sta, bss); | ||
1155 | else | ||
1156 | bss->nw_type = WCN36XX_HAL_11N_NW_TYPE; | ||
1157 | |||
1158 | bss->short_slot_time_supported = vif->bss_conf.use_short_slot; | ||
1159 | bss->lla_coexist = 0; | ||
1160 | bss->llb_coexist = 0; | ||
1161 | bss->llg_coexist = 0; | ||
1162 | bss->rifs_mode = 0; | ||
1163 | bss->beacon_interval = vif->bss_conf.beacon_int; | ||
1164 | bss->dtim_period = vif_priv->dtim_period; | ||
1165 | |||
1166 | wcn36xx_smd_set_bss_ht_params(vif, sta, bss); | ||
1167 | |||
1168 | bss->oper_channel = WCN36XX_HW_CHANNEL(wcn); | ||
1169 | |||
1170 | if (conf_is_ht40_minus(&wcn->hw->conf)) | ||
1171 | bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
1172 | else if (conf_is_ht40_plus(&wcn->hw->conf)) | ||
1173 | bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
1174 | else | ||
1175 | bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_NONE; | ||
1176 | |||
1177 | bss->reserved = 0; | ||
1178 | wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params); | ||
1179 | |||
1180 | /* wcn->ssid is only valid in AP and IBSS mode */ | ||
1181 | bss->ssid.length = vif_priv->ssid.length; | ||
1182 | memcpy(bss->ssid.ssid, vif_priv->ssid.ssid, vif_priv->ssid.length); | ||
1183 | |||
1184 | bss->obss_prot_enabled = 0; | ||
1185 | bss->rmf = 0; | ||
1186 | bss->max_probe_resp_retry_limit = 0; | ||
1187 | bss->hidden_ssid = vif->bss_conf.hidden_ssid; | ||
1188 | bss->proxy_probe_resp = 0; | ||
1189 | bss->edca_params_valid = 0; | ||
1190 | |||
1191 | /* FIXME: set acbe, acbk, acvi and acvo */ | ||
1192 | |||
1193 | bss->ext_set_sta_key_param_valid = 0; | ||
1194 | |||
1195 | /* FIXME: set ext_set_sta_key_param */ | ||
1196 | |||
1197 | bss->spectrum_mgt_enable = 0; | ||
1198 | bss->tx_mgmt_power = 0; | ||
1199 | bss->max_tx_power = WCN36XX_MAX_POWER(wcn); | ||
1200 | |||
1201 | bss->action = update; | ||
1202 | |||
1203 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
1204 | "hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n", | ||
1205 | bss->bssid, bss->self_mac_addr, bss->bss_type, | ||
1206 | bss->oper_mode, bss->nw_type); | ||
1207 | |||
1208 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
1209 | "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n", | ||
1210 | sta_params->bssid, sta_params->action, | ||
1211 | sta_params->sta_index, sta_params->bssid_index, | ||
1212 | sta_params->aid, sta_params->type, | ||
1213 | sta_params->mac); | ||
1214 | |||
1215 | if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { | ||
1216 | ret = wcn36xx_smd_config_bss_v1(wcn, &msg); | ||
1217 | } else { | ||
1218 | PREPARE_HAL_BUF(wcn->hal_buf, msg); | ||
1219 | |||
1220 | ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len); | ||
1221 | } | ||
1222 | if (ret) { | ||
1223 | wcn36xx_err("Sending hal_config_bss failed\n"); | ||
1224 | goto out; | ||
1225 | } | ||
1226 | ret = wcn36xx_smd_config_bss_rsp(wcn, | ||
1227 | vif, | ||
1228 | wcn->hal_buf, | ||
1229 | wcn->hal_rsp_len); | ||
1230 | if (ret) { | ||
1231 | wcn36xx_err("hal_config_bss response failed err=%d\n", ret); | ||
1232 | goto out; | ||
1233 | } | ||
1234 | out: | ||
1235 | mutex_unlock(&wcn->hal_mutex); | ||
1236 | return ret; | ||
1237 | } | ||
1238 | |||
1239 | int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif) | ||
1240 | { | ||
1241 | struct wcn36xx_hal_delete_bss_req_msg msg_body; | ||
1242 | struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; | ||
1243 | int ret = 0; | ||
1244 | |||
1245 | mutex_lock(&wcn->hal_mutex); | ||
1246 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ); | ||
1247 | |||
1248 | msg_body.bss_index = priv_vif->bss_index; | ||
1249 | |||
1250 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1251 | |||
1252 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal delete bss %d\n", msg_body.bss_index); | ||
1253 | |||
1254 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1255 | if (ret) { | ||
1256 | wcn36xx_err("Sending hal_delete_bss failed\n"); | ||
1257 | goto out; | ||
1258 | } | ||
1259 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1260 | if (ret) { | ||
1261 | wcn36xx_err("hal_delete_bss response failed err=%d\n", ret); | ||
1262 | goto out; | ||
1263 | } | ||
1264 | out: | ||
1265 | mutex_unlock(&wcn->hal_mutex); | ||
1266 | return ret; | ||
1267 | } | ||
1268 | |||
1269 | int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif, | ||
1270 | struct sk_buff *skb_beacon, u16 tim_off, | ||
1271 | u16 p2p_off) | ||
1272 | { | ||
1273 | struct wcn36xx_hal_send_beacon_req_msg msg_body; | ||
1274 | int ret = 0; | ||
1275 | |||
1276 | mutex_lock(&wcn->hal_mutex); | ||
1277 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ); | ||
1278 | |||
1279 | /* TODO need to find out why this is needed? */ | ||
1280 | msg_body.beacon_length = skb_beacon->len + 6; | ||
1281 | |||
1282 | if (BEACON_TEMPLATE_SIZE > msg_body.beacon_length) { | ||
1283 | memcpy(&msg_body.beacon, &skb_beacon->len, sizeof(u32)); | ||
1284 | memcpy(&(msg_body.beacon[4]), skb_beacon->data, | ||
1285 | skb_beacon->len); | ||
1286 | } else { | ||
1287 | wcn36xx_err("Beacon is to big: beacon size=%d\n", | ||
1288 | msg_body.beacon_length); | ||
1289 | return -ENOMEM; | ||
1290 | } | ||
1291 | memcpy(msg_body.bssid, vif->addr, ETH_ALEN); | ||
1292 | |||
1293 | /* TODO need to find out why this is needed? */ | ||
1294 | msg_body.tim_ie_offset = tim_off+4; | ||
1295 | msg_body.p2p_ie_offset = p2p_off; | ||
1296 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1297 | |||
1298 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
1299 | "hal send beacon beacon_length %d\n", | ||
1300 | msg_body.beacon_length); | ||
1301 | |||
1302 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1303 | if (ret) { | ||
1304 | wcn36xx_err("Sending hal_send_beacon failed\n"); | ||
1305 | goto out; | ||
1306 | } | ||
1307 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1308 | if (ret) { | ||
1309 | wcn36xx_err("hal_send_beacon response failed err=%d\n", ret); | ||
1310 | goto out; | ||
1311 | } | ||
1312 | out: | ||
1313 | mutex_unlock(&wcn->hal_mutex); | ||
1314 | return ret; | ||
1315 | } | ||
1316 | |||
1317 | int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn, | ||
1318 | struct ieee80211_vif *vif, | ||
1319 | struct sk_buff *skb) | ||
1320 | { | ||
1321 | struct wcn36xx_hal_send_probe_resp_req_msg msg; | ||
1322 | int ret = 0; | ||
1323 | |||
1324 | mutex_lock(&wcn->hal_mutex); | ||
1325 | INIT_HAL_MSG(msg, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ); | ||
1326 | |||
1327 | if (skb->len > BEACON_TEMPLATE_SIZE) { | ||
1328 | wcn36xx_warn("probe response template is too big: %d\n", | ||
1329 | skb->len); | ||
1330 | return -E2BIG; | ||
1331 | } | ||
1332 | |||
1333 | msg.probe_resp_template_len = skb->len; | ||
1334 | memcpy(&msg.probe_resp_template, skb->data, skb->len); | ||
1335 | |||
1336 | memcpy(msg.bssid, vif->addr, ETH_ALEN); | ||
1337 | |||
1338 | PREPARE_HAL_BUF(wcn->hal_buf, msg); | ||
1339 | |||
1340 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
1341 | "hal update probe rsp len %d bssid %pM\n", | ||
1342 | msg.probe_resp_template_len, msg.bssid); | ||
1343 | |||
1344 | ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len); | ||
1345 | if (ret) { | ||
1346 | wcn36xx_err("Sending hal_update_proberesp_tmpl failed\n"); | ||
1347 | goto out; | ||
1348 | } | ||
1349 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1350 | if (ret) { | ||
1351 | wcn36xx_err("hal_update_proberesp_tmpl response failed err=%d\n", | ||
1352 | ret); | ||
1353 | goto out; | ||
1354 | } | ||
1355 | out: | ||
1356 | mutex_unlock(&wcn->hal_mutex); | ||
1357 | return ret; | ||
1358 | } | ||
1359 | |||
1360 | int wcn36xx_smd_set_stakey(struct wcn36xx *wcn, | ||
1361 | enum ani_ed_type enc_type, | ||
1362 | u8 keyidx, | ||
1363 | u8 keylen, | ||
1364 | u8 *key, | ||
1365 | u8 sta_index) | ||
1366 | { | ||
1367 | struct wcn36xx_hal_set_sta_key_req_msg msg_body; | ||
1368 | int ret = 0; | ||
1369 | |||
1370 | mutex_lock(&wcn->hal_mutex); | ||
1371 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_STAKEY_REQ); | ||
1372 | |||
1373 | msg_body.set_sta_key_params.sta_index = sta_index; | ||
1374 | msg_body.set_sta_key_params.enc_type = enc_type; | ||
1375 | |||
1376 | msg_body.set_sta_key_params.key[0].id = keyidx; | ||
1377 | msg_body.set_sta_key_params.key[0].unicast = 1; | ||
1378 | msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX; | ||
1379 | msg_body.set_sta_key_params.key[0].pae_role = 0; | ||
1380 | msg_body.set_sta_key_params.key[0].length = keylen; | ||
1381 | memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen); | ||
1382 | msg_body.set_sta_key_params.single_tid_rc = 1; | ||
1383 | |||
1384 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1385 | |||
1386 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1387 | if (ret) { | ||
1388 | wcn36xx_err("Sending hal_set_stakey failed\n"); | ||
1389 | goto out; | ||
1390 | } | ||
1391 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1392 | if (ret) { | ||
1393 | wcn36xx_err("hal_set_stakey response failed err=%d\n", ret); | ||
1394 | goto out; | ||
1395 | } | ||
1396 | out: | ||
1397 | mutex_unlock(&wcn->hal_mutex); | ||
1398 | return ret; | ||
1399 | } | ||
1400 | |||
1401 | int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn, | ||
1402 | enum ani_ed_type enc_type, | ||
1403 | u8 keyidx, | ||
1404 | u8 keylen, | ||
1405 | u8 *key) | ||
1406 | { | ||
1407 | struct wcn36xx_hal_set_bss_key_req_msg msg_body; | ||
1408 | int ret = 0; | ||
1409 | |||
1410 | mutex_lock(&wcn->hal_mutex); | ||
1411 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_BSSKEY_REQ); | ||
1412 | msg_body.bss_idx = 0; | ||
1413 | msg_body.enc_type = enc_type; | ||
1414 | msg_body.num_keys = 1; | ||
1415 | msg_body.keys[0].id = keyidx; | ||
1416 | msg_body.keys[0].unicast = 0; | ||
1417 | msg_body.keys[0].direction = WCN36XX_HAL_RX_ONLY; | ||
1418 | msg_body.keys[0].pae_role = 0; | ||
1419 | msg_body.keys[0].length = keylen; | ||
1420 | memcpy(msg_body.keys[0].key, key, keylen); | ||
1421 | |||
1422 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1423 | |||
1424 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1425 | if (ret) { | ||
1426 | wcn36xx_err("Sending hal_set_bsskey failed\n"); | ||
1427 | goto out; | ||
1428 | } | ||
1429 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1430 | if (ret) { | ||
1431 | wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret); | ||
1432 | goto out; | ||
1433 | } | ||
1434 | out: | ||
1435 | mutex_unlock(&wcn->hal_mutex); | ||
1436 | return ret; | ||
1437 | } | ||
1438 | |||
1439 | int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn, | ||
1440 | enum ani_ed_type enc_type, | ||
1441 | u8 keyidx, | ||
1442 | u8 sta_index) | ||
1443 | { | ||
1444 | struct wcn36xx_hal_remove_sta_key_req_msg msg_body; | ||
1445 | int ret = 0; | ||
1446 | |||
1447 | mutex_lock(&wcn->hal_mutex); | ||
1448 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_STAKEY_REQ); | ||
1449 | |||
1450 | msg_body.sta_idx = sta_index; | ||
1451 | msg_body.enc_type = enc_type; | ||
1452 | msg_body.key_id = keyidx; | ||
1453 | |||
1454 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1455 | |||
1456 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1457 | if (ret) { | ||
1458 | wcn36xx_err("Sending hal_remove_stakey failed\n"); | ||
1459 | goto out; | ||
1460 | } | ||
1461 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1462 | if (ret) { | ||
1463 | wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret); | ||
1464 | goto out; | ||
1465 | } | ||
1466 | out: | ||
1467 | mutex_unlock(&wcn->hal_mutex); | ||
1468 | return ret; | ||
1469 | } | ||
1470 | |||
1471 | int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn, | ||
1472 | enum ani_ed_type enc_type, | ||
1473 | u8 keyidx) | ||
1474 | { | ||
1475 | struct wcn36xx_hal_remove_bss_key_req_msg msg_body; | ||
1476 | int ret = 0; | ||
1477 | |||
1478 | mutex_lock(&wcn->hal_mutex); | ||
1479 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_BSSKEY_REQ); | ||
1480 | msg_body.bss_idx = 0; | ||
1481 | msg_body.enc_type = enc_type; | ||
1482 | msg_body.key_id = keyidx; | ||
1483 | |||
1484 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1485 | |||
1486 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1487 | if (ret) { | ||
1488 | wcn36xx_err("Sending hal_remove_bsskey failed\n"); | ||
1489 | goto out; | ||
1490 | } | ||
1491 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1492 | if (ret) { | ||
1493 | wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret); | ||
1494 | goto out; | ||
1495 | } | ||
1496 | out: | ||
1497 | mutex_unlock(&wcn->hal_mutex); | ||
1498 | return ret; | ||
1499 | } | ||
1500 | |||
1501 | int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) | ||
1502 | { | ||
1503 | struct wcn36xx_hal_enter_bmps_req_msg msg_body; | ||
1504 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
1505 | int ret = 0; | ||
1506 | |||
1507 | mutex_lock(&wcn->hal_mutex); | ||
1508 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ); | ||
1509 | |||
1510 | msg_body.bss_index = vif_priv->bss_index; | ||
1511 | msg_body.tbtt = vif->bss_conf.sync_tsf; | ||
1512 | msg_body.dtim_period = vif_priv->dtim_period; | ||
1513 | |||
1514 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1515 | |||
1516 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1517 | if (ret) { | ||
1518 | wcn36xx_err("Sending hal_enter_bmps failed\n"); | ||
1519 | goto out; | ||
1520 | } | ||
1521 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1522 | if (ret) { | ||
1523 | wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret); | ||
1524 | goto out; | ||
1525 | } | ||
1526 | out: | ||
1527 | mutex_unlock(&wcn->hal_mutex); | ||
1528 | return ret; | ||
1529 | } | ||
1530 | |||
1531 | int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) | ||
1532 | { | ||
1533 | struct wcn36xx_hal_enter_bmps_req_msg msg_body; | ||
1534 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
1535 | int ret = 0; | ||
1536 | |||
1537 | mutex_lock(&wcn->hal_mutex); | ||
1538 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ); | ||
1539 | |||
1540 | msg_body.bss_index = vif_priv->bss_index; | ||
1541 | |||
1542 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1543 | |||
1544 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1545 | if (ret) { | ||
1546 | wcn36xx_err("Sending hal_exit_bmps failed\n"); | ||
1547 | goto out; | ||
1548 | } | ||
1549 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1550 | if (ret) { | ||
1551 | wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret); | ||
1552 | goto out; | ||
1553 | } | ||
1554 | out: | ||
1555 | mutex_unlock(&wcn->hal_mutex); | ||
1556 | return ret; | ||
1557 | } | ||
1558 | int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim) | ||
1559 | { | ||
1560 | struct wcn36xx_hal_set_power_params_req_msg msg_body; | ||
1561 | int ret = 0; | ||
1562 | |||
1563 | mutex_lock(&wcn->hal_mutex); | ||
1564 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_POWER_PARAMS_REQ); | ||
1565 | |||
1566 | /* | ||
1567 | * When host is down ignore every second dtim | ||
1568 | */ | ||
1569 | if (ignore_dtim) { | ||
1570 | msg_body.ignore_dtim = 1; | ||
1571 | msg_body.dtim_period = 2; | ||
1572 | } | ||
1573 | msg_body.listen_interval = WCN36XX_LISTEN_INTERVAL(wcn); | ||
1574 | |||
1575 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1576 | |||
1577 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1578 | if (ret) { | ||
1579 | wcn36xx_err("Sending hal_set_power_params failed\n"); | ||
1580 | goto out; | ||
1581 | } | ||
1582 | |||
1583 | out: | ||
1584 | mutex_unlock(&wcn->hal_mutex); | ||
1585 | return ret; | ||
1586 | } | ||
1587 | /* Notice: This function should be called after associated, or else it | ||
1588 | * will be invalid | ||
1589 | */ | ||
1590 | int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn, | ||
1591 | struct ieee80211_vif *vif, | ||
1592 | int packet_type) | ||
1593 | { | ||
1594 | struct wcn36xx_hal_keep_alive_req_msg msg_body; | ||
1595 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
1596 | int ret = 0; | ||
1597 | |||
1598 | mutex_lock(&wcn->hal_mutex); | ||
1599 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ); | ||
1600 | |||
1601 | if (packet_type == WCN36XX_HAL_KEEP_ALIVE_NULL_PKT) { | ||
1602 | msg_body.bss_index = vif_priv->bss_index; | ||
1603 | msg_body.packet_type = WCN36XX_HAL_KEEP_ALIVE_NULL_PKT; | ||
1604 | msg_body.time_period = WCN36XX_KEEP_ALIVE_TIME_PERIOD; | ||
1605 | } else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) { | ||
1606 | /* TODO: it also support ARP response type */ | ||
1607 | } else { | ||
1608 | wcn36xx_warn("unknow keep alive packet type %d\n", packet_type); | ||
1609 | return -EINVAL; | ||
1610 | } | ||
1611 | |||
1612 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1613 | |||
1614 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1615 | if (ret) { | ||
1616 | wcn36xx_err("Sending hal_exit_bmps failed\n"); | ||
1617 | goto out; | ||
1618 | } | ||
1619 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1620 | if (ret) { | ||
1621 | wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret); | ||
1622 | goto out; | ||
1623 | } | ||
1624 | out: | ||
1625 | mutex_unlock(&wcn->hal_mutex); | ||
1626 | return ret; | ||
1627 | } | ||
1628 | |||
1629 | int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2, | ||
1630 | u32 arg3, u32 arg4, u32 arg5) | ||
1631 | { | ||
1632 | struct wcn36xx_hal_dump_cmd_req_msg msg_body; | ||
1633 | int ret = 0; | ||
1634 | |||
1635 | mutex_lock(&wcn->hal_mutex); | ||
1636 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_DUMP_COMMAND_REQ); | ||
1637 | |||
1638 | msg_body.arg1 = arg1; | ||
1639 | msg_body.arg2 = arg2; | ||
1640 | msg_body.arg3 = arg3; | ||
1641 | msg_body.arg4 = arg4; | ||
1642 | msg_body.arg5 = arg5; | ||
1643 | |||
1644 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1645 | |||
1646 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1647 | if (ret) { | ||
1648 | wcn36xx_err("Sending hal_dump_cmd failed\n"); | ||
1649 | goto out; | ||
1650 | } | ||
1651 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1652 | if (ret) { | ||
1653 | wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret); | ||
1654 | goto out; | ||
1655 | } | ||
1656 | out: | ||
1657 | mutex_unlock(&wcn->hal_mutex); | ||
1658 | return ret; | ||
1659 | } | ||
1660 | |||
1661 | static inline void set_feat_caps(u32 *bitmap, | ||
1662 | enum place_holder_in_cap_bitmap cap) | ||
1663 | { | ||
1664 | int arr_idx, bit_idx; | ||
1665 | |||
1666 | if (cap < 0 || cap > 127) { | ||
1667 | wcn36xx_warn("error cap idx %d\n", cap); | ||
1668 | return; | ||
1669 | } | ||
1670 | |||
1671 | arr_idx = cap / 32; | ||
1672 | bit_idx = cap % 32; | ||
1673 | bitmap[arr_idx] |= (1 << bit_idx); | ||
1674 | } | ||
1675 | |||
1676 | static inline int get_feat_caps(u32 *bitmap, | ||
1677 | enum place_holder_in_cap_bitmap cap) | ||
1678 | { | ||
1679 | int arr_idx, bit_idx; | ||
1680 | int ret = 0; | ||
1681 | |||
1682 | if (cap < 0 || cap > 127) { | ||
1683 | wcn36xx_warn("error cap idx %d\n", cap); | ||
1684 | return -EINVAL; | ||
1685 | } | ||
1686 | |||
1687 | arr_idx = cap / 32; | ||
1688 | bit_idx = cap % 32; | ||
1689 | ret = (bitmap[arr_idx] & (1 << bit_idx)) ? 1 : 0; | ||
1690 | return ret; | ||
1691 | } | ||
1692 | |||
1693 | static inline void clear_feat_caps(u32 *bitmap, | ||
1694 | enum place_holder_in_cap_bitmap cap) | ||
1695 | { | ||
1696 | int arr_idx, bit_idx; | ||
1697 | |||
1698 | if (cap < 0 || cap > 127) { | ||
1699 | wcn36xx_warn("error cap idx %d\n", cap); | ||
1700 | return; | ||
1701 | } | ||
1702 | |||
1703 | arr_idx = cap / 32; | ||
1704 | bit_idx = cap % 32; | ||
1705 | bitmap[arr_idx] &= ~(1 << bit_idx); | ||
1706 | } | ||
1707 | |||
1708 | int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn) | ||
1709 | { | ||
1710 | struct wcn36xx_hal_feat_caps_msg msg_body; | ||
1711 | int ret = 0; | ||
1712 | |||
1713 | mutex_lock(&wcn->hal_mutex); | ||
1714 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ); | ||
1715 | |||
1716 | set_feat_caps(msg_body.feat_caps, STA_POWERSAVE); | ||
1717 | |||
1718 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1719 | |||
1720 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1721 | if (ret) { | ||
1722 | wcn36xx_err("Sending hal_feature_caps_exchange failed\n"); | ||
1723 | goto out; | ||
1724 | } | ||
1725 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1726 | if (ret) { | ||
1727 | wcn36xx_err("hal_feature_caps_exchange response failed err=%d\n", | ||
1728 | ret); | ||
1729 | goto out; | ||
1730 | } | ||
1731 | out: | ||
1732 | mutex_unlock(&wcn->hal_mutex); | ||
1733 | return ret; | ||
1734 | } | ||
1735 | |||
1736 | int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn, | ||
1737 | struct ieee80211_sta *sta, | ||
1738 | u16 tid, | ||
1739 | u16 *ssn, | ||
1740 | u8 direction, | ||
1741 | u8 sta_index) | ||
1742 | { | ||
1743 | struct wcn36xx_hal_add_ba_session_req_msg msg_body; | ||
1744 | int ret = 0; | ||
1745 | |||
1746 | mutex_lock(&wcn->hal_mutex); | ||
1747 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ); | ||
1748 | |||
1749 | msg_body.sta_index = sta_index; | ||
1750 | memcpy(&msg_body.mac_addr, sta->addr, ETH_ALEN); | ||
1751 | msg_body.dialog_token = 0x10; | ||
1752 | msg_body.tid = tid; | ||
1753 | |||
1754 | /* Immediate BA because Delayed BA is not supported */ | ||
1755 | msg_body.policy = 1; | ||
1756 | msg_body.buffer_size = WCN36XX_AGGR_BUFFER_SIZE; | ||
1757 | msg_body.timeout = 0; | ||
1758 | if (ssn) | ||
1759 | msg_body.ssn = *ssn; | ||
1760 | msg_body.direction = direction; | ||
1761 | |||
1762 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1763 | |||
1764 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1765 | if (ret) { | ||
1766 | wcn36xx_err("Sending hal_add_ba_session failed\n"); | ||
1767 | goto out; | ||
1768 | } | ||
1769 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1770 | if (ret) { | ||
1771 | wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret); | ||
1772 | goto out; | ||
1773 | } | ||
1774 | out: | ||
1775 | mutex_unlock(&wcn->hal_mutex); | ||
1776 | return ret; | ||
1777 | } | ||
1778 | |||
1779 | int wcn36xx_smd_add_ba(struct wcn36xx *wcn) | ||
1780 | { | ||
1781 | struct wcn36xx_hal_add_ba_req_msg msg_body; | ||
1782 | int ret = 0; | ||
1783 | |||
1784 | mutex_lock(&wcn->hal_mutex); | ||
1785 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ); | ||
1786 | |||
1787 | msg_body.session_id = 0; | ||
1788 | msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE; | ||
1789 | |||
1790 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1791 | |||
1792 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1793 | if (ret) { | ||
1794 | wcn36xx_err("Sending hal_add_ba failed\n"); | ||
1795 | goto out; | ||
1796 | } | ||
1797 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1798 | if (ret) { | ||
1799 | wcn36xx_err("hal_add_ba response failed err=%d\n", ret); | ||
1800 | goto out; | ||
1801 | } | ||
1802 | out: | ||
1803 | mutex_unlock(&wcn->hal_mutex); | ||
1804 | return ret; | ||
1805 | } | ||
1806 | |||
1807 | int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index) | ||
1808 | { | ||
1809 | struct wcn36xx_hal_del_ba_req_msg msg_body; | ||
1810 | int ret = 0; | ||
1811 | |||
1812 | mutex_lock(&wcn->hal_mutex); | ||
1813 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ); | ||
1814 | |||
1815 | msg_body.sta_index = sta_index; | ||
1816 | msg_body.tid = tid; | ||
1817 | msg_body.direction = 0; | ||
1818 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1819 | |||
1820 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1821 | if (ret) { | ||
1822 | wcn36xx_err("Sending hal_del_ba failed\n"); | ||
1823 | goto out; | ||
1824 | } | ||
1825 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1826 | if (ret) { | ||
1827 | wcn36xx_err("hal_del_ba response failed err=%d\n", ret); | ||
1828 | goto out; | ||
1829 | } | ||
1830 | out: | ||
1831 | mutex_unlock(&wcn->hal_mutex); | ||
1832 | return ret; | ||
1833 | } | ||
1834 | |||
1835 | int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index) | ||
1836 | { | ||
1837 | struct wcn36xx_hal_trigger_ba_req_msg msg_body; | ||
1838 | struct wcn36xx_hal_trigget_ba_req_candidate *candidate; | ||
1839 | int ret = 0; | ||
1840 | |||
1841 | mutex_lock(&wcn->hal_mutex); | ||
1842 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ); | ||
1843 | |||
1844 | msg_body.session_id = 0; | ||
1845 | msg_body.candidate_cnt = 1; | ||
1846 | msg_body.header.len += sizeof(*candidate); | ||
1847 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1848 | |||
1849 | candidate = (struct wcn36xx_hal_trigget_ba_req_candidate *) | ||
1850 | (wcn->hal_buf + sizeof(msg_body)); | ||
1851 | candidate->sta_index = sta_index; | ||
1852 | candidate->tid_bitmap = 1; | ||
1853 | |||
1854 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1855 | if (ret) { | ||
1856 | wcn36xx_err("Sending hal_trigger_ba failed\n"); | ||
1857 | goto out; | ||
1858 | } | ||
1859 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1860 | if (ret) { | ||
1861 | wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret); | ||
1862 | goto out; | ||
1863 | } | ||
1864 | out: | ||
1865 | mutex_unlock(&wcn->hal_mutex); | ||
1866 | return ret; | ||
1867 | } | ||
1868 | |||
1869 | static int wcn36xx_smd_tx_compl_ind(struct wcn36xx *wcn, void *buf, size_t len) | ||
1870 | { | ||
1871 | struct wcn36xx_hal_tx_compl_ind_msg *rsp = buf; | ||
1872 | |||
1873 | if (len != sizeof(*rsp)) { | ||
1874 | wcn36xx_warn("Bad TX complete indication\n"); | ||
1875 | return -EIO; | ||
1876 | } | ||
1877 | |||
1878 | wcn36xx_dxe_tx_ack_ind(wcn, rsp->status); | ||
1879 | |||
1880 | return 0; | ||
1881 | } | ||
1882 | |||
1883 | static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn, | ||
1884 | void *buf, | ||
1885 | size_t len) | ||
1886 | { | ||
1887 | struct wcn36xx_hal_missed_beacon_ind_msg *rsp = buf; | ||
1888 | struct ieee80211_vif *vif = NULL; | ||
1889 | struct wcn36xx_vif *tmp; | ||
1890 | |||
1891 | /* Old FW does not have bss index */ | ||
1892 | if (wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { | ||
1893 | list_for_each_entry(tmp, &wcn->vif_list, list) { | ||
1894 | wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", | ||
1895 | tmp->bss_index); | ||
1896 | vif = container_of((void *)tmp, | ||
1897 | struct ieee80211_vif, | ||
1898 | drv_priv); | ||
1899 | ieee80211_connection_loss(vif); | ||
1900 | } | ||
1901 | return 0; | ||
1902 | } | ||
1903 | |||
1904 | if (len != sizeof(*rsp)) { | ||
1905 | wcn36xx_warn("Corrupted missed beacon indication\n"); | ||
1906 | return -EIO; | ||
1907 | } | ||
1908 | |||
1909 | list_for_each_entry(tmp, &wcn->vif_list, list) { | ||
1910 | if (tmp->bss_index == rsp->bss_index) { | ||
1911 | wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", | ||
1912 | rsp->bss_index); | ||
1913 | vif = container_of((void *)tmp, | ||
1914 | struct ieee80211_vif, | ||
1915 | drv_priv); | ||
1916 | ieee80211_connection_loss(vif); | ||
1917 | return 0; | ||
1918 | } | ||
1919 | } | ||
1920 | |||
1921 | wcn36xx_warn("BSS index %d not found\n", rsp->bss_index); | ||
1922 | return -ENOENT; | ||
1923 | } | ||
1924 | |||
1925 | static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn, | ||
1926 | void *buf, | ||
1927 | size_t len) | ||
1928 | { | ||
1929 | struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf; | ||
1930 | struct wcn36xx_vif *tmp; | ||
1931 | struct ieee80211_sta *sta = NULL; | ||
1932 | |||
1933 | if (len != sizeof(*rsp)) { | ||
1934 | wcn36xx_warn("Corrupted delete sta indication\n"); | ||
1935 | return -EIO; | ||
1936 | } | ||
1937 | |||
1938 | list_for_each_entry(tmp, &wcn->vif_list, list) { | ||
1939 | if (sta && (tmp->sta->sta_index == rsp->sta_id)) { | ||
1940 | sta = container_of((void *)tmp->sta, | ||
1941 | struct ieee80211_sta, | ||
1942 | drv_priv); | ||
1943 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
1944 | "delete station indication %pM index %d\n", | ||
1945 | rsp->addr2, | ||
1946 | rsp->sta_id); | ||
1947 | ieee80211_report_low_ack(sta, 0); | ||
1948 | return 0; | ||
1949 | } | ||
1950 | } | ||
1951 | |||
1952 | wcn36xx_warn("STA with addr %pM and index %d not found\n", | ||
1953 | rsp->addr2, | ||
1954 | rsp->sta_id); | ||
1955 | return -ENOENT; | ||
1956 | } | ||
1957 | |||
1958 | int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value) | ||
1959 | { | ||
1960 | struct wcn36xx_hal_update_cfg_req_msg msg_body, *body; | ||
1961 | size_t len; | ||
1962 | int ret = 0; | ||
1963 | |||
1964 | mutex_lock(&wcn->hal_mutex); | ||
1965 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_CFG_REQ); | ||
1966 | |||
1967 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1968 | |||
1969 | body = (struct wcn36xx_hal_update_cfg_req_msg *) wcn->hal_buf; | ||
1970 | len = msg_body.header.len; | ||
1971 | |||
1972 | put_cfg_tlv_u32(wcn, &len, cfg_id, value); | ||
1973 | body->header.len = len; | ||
1974 | body->len = len - sizeof(*body); | ||
1975 | |||
1976 | ret = wcn36xx_smd_send_and_wait(wcn, body->header.len); | ||
1977 | if (ret) { | ||
1978 | wcn36xx_err("Sending hal_update_cfg failed\n"); | ||
1979 | goto out; | ||
1980 | } | ||
1981 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1982 | if (ret) { | ||
1983 | wcn36xx_err("hal_update_cfg response failed err=%d\n", ret); | ||
1984 | goto out; | ||
1985 | } | ||
1986 | out: | ||
1987 | mutex_unlock(&wcn->hal_mutex); | ||
1988 | return ret; | ||
1989 | } | ||
1990 | static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) | ||
1991 | { | ||
1992 | struct wcn36xx_hal_msg_header *msg_header = buf; | ||
1993 | struct wcn36xx_hal_ind_msg *msg_ind; | ||
1994 | wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len); | ||
1995 | |||
1996 | switch (msg_header->msg_type) { | ||
1997 | case WCN36XX_HAL_START_RSP: | ||
1998 | case WCN36XX_HAL_CONFIG_STA_RSP: | ||
1999 | case WCN36XX_HAL_CONFIG_BSS_RSP: | ||
2000 | case WCN36XX_HAL_ADD_STA_SELF_RSP: | ||
2001 | case WCN36XX_HAL_STOP_RSP: | ||
2002 | case WCN36XX_HAL_DEL_STA_SELF_RSP: | ||
2003 | case WCN36XX_HAL_DELETE_STA_RSP: | ||
2004 | case WCN36XX_HAL_INIT_SCAN_RSP: | ||
2005 | case WCN36XX_HAL_START_SCAN_RSP: | ||
2006 | case WCN36XX_HAL_END_SCAN_RSP: | ||
2007 | case WCN36XX_HAL_FINISH_SCAN_RSP: | ||
2008 | case WCN36XX_HAL_DOWNLOAD_NV_RSP: | ||
2009 | case WCN36XX_HAL_DELETE_BSS_RSP: | ||
2010 | case WCN36XX_HAL_SEND_BEACON_RSP: | ||
2011 | case WCN36XX_HAL_SET_LINK_ST_RSP: | ||
2012 | case WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP: | ||
2013 | case WCN36XX_HAL_SET_BSSKEY_RSP: | ||
2014 | case WCN36XX_HAL_SET_STAKEY_RSP: | ||
2015 | case WCN36XX_HAL_RMV_STAKEY_RSP: | ||
2016 | case WCN36XX_HAL_RMV_BSSKEY_RSP: | ||
2017 | case WCN36XX_HAL_ENTER_BMPS_RSP: | ||
2018 | case WCN36XX_HAL_SET_POWER_PARAMS_RSP: | ||
2019 | case WCN36XX_HAL_EXIT_BMPS_RSP: | ||
2020 | case WCN36XX_HAL_KEEP_ALIVE_RSP: | ||
2021 | case WCN36XX_HAL_DUMP_COMMAND_RSP: | ||
2022 | case WCN36XX_HAL_ADD_BA_SESSION_RSP: | ||
2023 | case WCN36XX_HAL_ADD_BA_RSP: | ||
2024 | case WCN36XX_HAL_DEL_BA_RSP: | ||
2025 | case WCN36XX_HAL_TRIGGER_BA_RSP: | ||
2026 | case WCN36XX_HAL_UPDATE_CFG_RSP: | ||
2027 | case WCN36XX_HAL_JOIN_RSP: | ||
2028 | case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP: | ||
2029 | case WCN36XX_HAL_CH_SWITCH_RSP: | ||
2030 | case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP: | ||
2031 | memcpy(wcn->hal_buf, buf, len); | ||
2032 | wcn->hal_rsp_len = len; | ||
2033 | complete(&wcn->hal_rsp_compl); | ||
2034 | break; | ||
2035 | |||
2036 | case WCN36XX_HAL_OTA_TX_COMPL_IND: | ||
2037 | case WCN36XX_HAL_MISSED_BEACON_IND: | ||
2038 | case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: | ||
2039 | mutex_lock(&wcn->hal_ind_mutex); | ||
2040 | msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL); | ||
2041 | msg_ind->msg_len = len; | ||
2042 | msg_ind->msg = kmalloc(len, GFP_KERNEL); | ||
2043 | memcpy(msg_ind->msg, buf, len); | ||
2044 | list_add_tail(&msg_ind->list, &wcn->hal_ind_queue); | ||
2045 | queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work); | ||
2046 | wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n"); | ||
2047 | mutex_unlock(&wcn->hal_ind_mutex); | ||
2048 | break; | ||
2049 | default: | ||
2050 | wcn36xx_err("SMD_EVENT (%d) not supported\n", | ||
2051 | msg_header->msg_type); | ||
2052 | } | ||
2053 | } | ||
2054 | static void wcn36xx_ind_smd_work(struct work_struct *work) | ||
2055 | { | ||
2056 | struct wcn36xx *wcn = | ||
2057 | container_of(work, struct wcn36xx, hal_ind_work); | ||
2058 | struct wcn36xx_hal_msg_header *msg_header; | ||
2059 | struct wcn36xx_hal_ind_msg *hal_ind_msg; | ||
2060 | |||
2061 | mutex_lock(&wcn->hal_ind_mutex); | ||
2062 | |||
2063 | hal_ind_msg = list_first_entry(&wcn->hal_ind_queue, | ||
2064 | struct wcn36xx_hal_ind_msg, | ||
2065 | list); | ||
2066 | |||
2067 | msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg; | ||
2068 | |||
2069 | switch (msg_header->msg_type) { | ||
2070 | case WCN36XX_HAL_OTA_TX_COMPL_IND: | ||
2071 | wcn36xx_smd_tx_compl_ind(wcn, | ||
2072 | hal_ind_msg->msg, | ||
2073 | hal_ind_msg->msg_len); | ||
2074 | break; | ||
2075 | case WCN36XX_HAL_MISSED_BEACON_IND: | ||
2076 | wcn36xx_smd_missed_beacon_ind(wcn, | ||
2077 | hal_ind_msg->msg, | ||
2078 | hal_ind_msg->msg_len); | ||
2079 | break; | ||
2080 | case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: | ||
2081 | wcn36xx_smd_delete_sta_context_ind(wcn, | ||
2082 | hal_ind_msg->msg, | ||
2083 | hal_ind_msg->msg_len); | ||
2084 | break; | ||
2085 | default: | ||
2086 | wcn36xx_err("SMD_EVENT (%d) not supported\n", | ||
2087 | msg_header->msg_type); | ||
2088 | } | ||
2089 | list_del(wcn->hal_ind_queue.next); | ||
2090 | kfree(hal_ind_msg->msg); | ||
2091 | kfree(hal_ind_msg); | ||
2092 | mutex_unlock(&wcn->hal_ind_mutex); | ||
2093 | } | ||
2094 | int wcn36xx_smd_open(struct wcn36xx *wcn) | ||
2095 | { | ||
2096 | int ret = 0; | ||
2097 | wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind"); | ||
2098 | if (!wcn->hal_ind_wq) { | ||
2099 | wcn36xx_err("failed to allocate wq\n"); | ||
2100 | ret = -ENOMEM; | ||
2101 | goto out; | ||
2102 | } | ||
2103 | INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work); | ||
2104 | INIT_LIST_HEAD(&wcn->hal_ind_queue); | ||
2105 | mutex_init(&wcn->hal_ind_mutex); | ||
2106 | |||
2107 | ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process); | ||
2108 | if (ret) { | ||
2109 | wcn36xx_err("failed to open control channel\n"); | ||
2110 | goto free_wq; | ||
2111 | } | ||
2112 | |||
2113 | return ret; | ||
2114 | |||
2115 | free_wq: | ||
2116 | destroy_workqueue(wcn->hal_ind_wq); | ||
2117 | out: | ||
2118 | return ret; | ||
2119 | } | ||
2120 | |||
2121 | void wcn36xx_smd_close(struct wcn36xx *wcn) | ||
2122 | { | ||
2123 | wcn->ctrl_ops->close(); | ||
2124 | destroy_workqueue(wcn->hal_ind_wq); | ||
2125 | mutex_destroy(&wcn->hal_ind_mutex); | ||
2126 | } | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h new file mode 100644 index 000000000000..e7c39019c6f1 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/smd.h | |||
@@ -0,0 +1,127 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _SMD_H_ | ||
18 | #define _SMD_H_ | ||
19 | |||
20 | #include "wcn36xx.h" | ||
21 | |||
22 | /* Max shared size is 4k but we take less.*/ | ||
23 | #define WCN36XX_NV_FRAGMENT_SIZE 3072 | ||
24 | |||
25 | #define WCN36XX_HAL_BUF_SIZE 4096 | ||
26 | |||
27 | #define HAL_MSG_TIMEOUT 200 | ||
28 | #define WCN36XX_SMSM_WLAN_TX_ENABLE 0x00000400 | ||
29 | #define WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY 0x00000200 | ||
30 | /* The PNO version info be contained in the rsp msg */ | ||
31 | #define WCN36XX_FW_MSG_PNO_VERSION_MASK 0x8000 | ||
32 | |||
33 | enum wcn36xx_fw_msg_result { | ||
34 | WCN36XX_FW_MSG_RESULT_SUCCESS = 0, | ||
35 | WCN36XX_FW_MSG_RESULT_SUCCESS_SYNC = 1, | ||
36 | |||
37 | WCN36XX_FW_MSG_RESULT_MEM_FAIL = 5, | ||
38 | }; | ||
39 | |||
40 | /******************************/ | ||
41 | /* SMD requests and responses */ | ||
42 | /******************************/ | ||
43 | struct wcn36xx_fw_msg_status_rsp { | ||
44 | u32 status; | ||
45 | } __packed; | ||
46 | |||
47 | struct wcn36xx_hal_ind_msg { | ||
48 | struct list_head list; | ||
49 | u8 *msg; | ||
50 | size_t msg_len; | ||
51 | }; | ||
52 | |||
53 | struct wcn36xx; | ||
54 | |||
55 | int wcn36xx_smd_open(struct wcn36xx *wcn); | ||
56 | void wcn36xx_smd_close(struct wcn36xx *wcn); | ||
57 | |||
58 | int wcn36xx_smd_load_nv(struct wcn36xx *wcn); | ||
59 | int wcn36xx_smd_start(struct wcn36xx *wcn); | ||
60 | int wcn36xx_smd_stop(struct wcn36xx *wcn); | ||
61 | int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode); | ||
62 | int wcn36xx_smd_start_scan(struct wcn36xx *wcn); | ||
63 | int wcn36xx_smd_end_scan(struct wcn36xx *wcn); | ||
64 | int wcn36xx_smd_finish_scan(struct wcn36xx *wcn, | ||
65 | enum wcn36xx_hal_sys_mode mode); | ||
66 | int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn); | ||
67 | int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif); | ||
68 | int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr); | ||
69 | int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index); | ||
70 | int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch); | ||
71 | int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid, | ||
72 | const u8 *sta_mac, | ||
73 | enum wcn36xx_hal_link_state state); | ||
74 | int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, | ||
75 | struct ieee80211_sta *sta, const u8 *bssid, | ||
76 | bool update); | ||
77 | int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif); | ||
78 | int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif, | ||
79 | struct ieee80211_sta *sta); | ||
80 | int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif, | ||
81 | struct sk_buff *skb_beacon, u16 tim_off, | ||
82 | u16 p2p_off); | ||
83 | int wcn36xx_smd_switch_channel(struct wcn36xx *wcn, | ||
84 | struct ieee80211_vif *vif, int ch); | ||
85 | int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn, | ||
86 | struct ieee80211_vif *vif, | ||
87 | struct sk_buff *skb); | ||
88 | int wcn36xx_smd_set_stakey(struct wcn36xx *wcn, | ||
89 | enum ani_ed_type enc_type, | ||
90 | u8 keyidx, | ||
91 | u8 keylen, | ||
92 | u8 *key, | ||
93 | u8 sta_index); | ||
94 | int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn, | ||
95 | enum ani_ed_type enc_type, | ||
96 | u8 keyidx, | ||
97 | u8 keylen, | ||
98 | u8 *key); | ||
99 | int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn, | ||
100 | enum ani_ed_type enc_type, | ||
101 | u8 keyidx, | ||
102 | u8 sta_index); | ||
103 | int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn, | ||
104 | enum ani_ed_type enc_type, | ||
105 | u8 keyidx); | ||
106 | int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif); | ||
107 | int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif); | ||
108 | int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim); | ||
109 | int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn, | ||
110 | struct ieee80211_vif *vif, | ||
111 | int packet_type); | ||
112 | int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2, | ||
113 | u32 arg3, u32 arg4, u32 arg5); | ||
114 | int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn); | ||
115 | |||
116 | int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn, | ||
117 | struct ieee80211_sta *sta, | ||
118 | u16 tid, | ||
119 | u16 *ssn, | ||
120 | u8 direction, | ||
121 | u8 sta_index); | ||
122 | int wcn36xx_smd_add_ba(struct wcn36xx *wcn); | ||
123 | int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index); | ||
124 | int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index); | ||
125 | |||
126 | int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value); | ||
127 | #endif /* _SMD_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c new file mode 100644 index 000000000000..b2b60e30caaf --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/txrx.c | |||
@@ -0,0 +1,284 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
19 | #include "txrx.h" | ||
20 | |||
21 | static inline int get_rssi0(struct wcn36xx_rx_bd *bd) | ||
22 | { | ||
23 | return 100 - ((bd->phy_stat0 >> 24) & 0xff); | ||
24 | } | ||
25 | |||
26 | int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) | ||
27 | { | ||
28 | struct ieee80211_rx_status status; | ||
29 | struct ieee80211_hdr *hdr; | ||
30 | struct wcn36xx_rx_bd *bd; | ||
31 | u16 fc, sn; | ||
32 | |||
33 | /* | ||
34 | * All fields must be 0, otherwise it can lead to | ||
35 | * unexpected consequences. | ||
36 | */ | ||
37 | memset(&status, 0, sizeof(status)); | ||
38 | |||
39 | bd = (struct wcn36xx_rx_bd *)skb->data; | ||
40 | buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32)); | ||
41 | wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP, | ||
42 | "BD <<< ", (char *)bd, | ||
43 | sizeof(struct wcn36xx_rx_bd)); | ||
44 | |||
45 | skb_put(skb, bd->pdu.mpdu_header_off + bd->pdu.mpdu_len); | ||
46 | skb_pull(skb, bd->pdu.mpdu_header_off); | ||
47 | |||
48 | status.mactime = 10; | ||
49 | status.freq = WCN36XX_CENTER_FREQ(wcn); | ||
50 | status.band = WCN36XX_BAND(wcn); | ||
51 | status.signal = -get_rssi0(bd); | ||
52 | status.antenna = 1; | ||
53 | status.rate_idx = 1; | ||
54 | status.flag = 0; | ||
55 | status.rx_flags = 0; | ||
56 | status.flag |= RX_FLAG_IV_STRIPPED | | ||
57 | RX_FLAG_MMIC_STRIPPED | | ||
58 | RX_FLAG_DECRYPTED; | ||
59 | |||
60 | wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x status->vendor_radiotap_len=%x\n", | ||
61 | status.flag, status.vendor_radiotap_len); | ||
62 | |||
63 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); | ||
64 | |||
65 | hdr = (struct ieee80211_hdr *) skb->data; | ||
66 | fc = __le16_to_cpu(hdr->frame_control); | ||
67 | sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)); | ||
68 | |||
69 | if (ieee80211_is_beacon(hdr->frame_control)) { | ||
70 | wcn36xx_dbg(WCN36XX_DBG_BEACON, "beacon skb %p len %d fc %04x sn %d\n", | ||
71 | skb, skb->len, fc, sn); | ||
72 | wcn36xx_dbg_dump(WCN36XX_DBG_BEACON_DUMP, "SKB <<< ", | ||
73 | (char *)skb->data, skb->len); | ||
74 | } else { | ||
75 | wcn36xx_dbg(WCN36XX_DBG_RX, "rx skb %p len %d fc %04x sn %d\n", | ||
76 | skb, skb->len, fc, sn); | ||
77 | wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP, "SKB <<< ", | ||
78 | (char *)skb->data, skb->len); | ||
79 | } | ||
80 | |||
81 | ieee80211_rx_irqsafe(wcn->hw, skb); | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static void wcn36xx_set_tx_pdu(struct wcn36xx_tx_bd *bd, | ||
87 | u32 mpdu_header_len, | ||
88 | u32 len, | ||
89 | u16 tid) | ||
90 | { | ||
91 | bd->pdu.mpdu_header_len = mpdu_header_len; | ||
92 | bd->pdu.mpdu_header_off = sizeof(*bd); | ||
93 | bd->pdu.mpdu_data_off = bd->pdu.mpdu_header_len + | ||
94 | bd->pdu.mpdu_header_off; | ||
95 | bd->pdu.mpdu_len = len; | ||
96 | bd->pdu.tid = tid; | ||
97 | } | ||
98 | |||
99 | static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn, | ||
100 | u8 *addr) | ||
101 | { | ||
102 | struct wcn36xx_vif *vif_priv = NULL; | ||
103 | struct ieee80211_vif *vif = NULL; | ||
104 | list_for_each_entry(vif_priv, &wcn->vif_list, list) { | ||
105 | vif = container_of((void *)vif_priv, | ||
106 | struct ieee80211_vif, | ||
107 | drv_priv); | ||
108 | if (memcmp(vif->addr, addr, ETH_ALEN) == 0) | ||
109 | return vif_priv; | ||
110 | } | ||
111 | wcn36xx_warn("vif %pM not found\n", addr); | ||
112 | return NULL; | ||
113 | } | ||
114 | static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd, | ||
115 | struct wcn36xx *wcn, | ||
116 | struct wcn36xx_vif **vif_priv, | ||
117 | struct wcn36xx_sta *sta_priv, | ||
118 | struct ieee80211_hdr *hdr, | ||
119 | bool bcast) | ||
120 | { | ||
121 | struct ieee80211_vif *vif = NULL; | ||
122 | struct wcn36xx_vif *__vif_priv = NULL; | ||
123 | bd->bd_rate = WCN36XX_BD_RATE_DATA; | ||
124 | |||
125 | /* | ||
126 | * For not unicast frames mac80211 will not set sta pointer so use | ||
127 | * self_sta_index instead. | ||
128 | */ | ||
129 | if (sta_priv) { | ||
130 | __vif_priv = sta_priv->vif; | ||
131 | vif = container_of((void *)__vif_priv, | ||
132 | struct ieee80211_vif, | ||
133 | drv_priv); | ||
134 | |||
135 | if (vif->type == NL80211_IFTYPE_STATION) { | ||
136 | bd->sta_index = sta_priv->bss_sta_index; | ||
137 | bd->dpu_desc_idx = sta_priv->bss_dpu_desc_index; | ||
138 | } else if (vif->type == NL80211_IFTYPE_AP || | ||
139 | vif->type == NL80211_IFTYPE_ADHOC || | ||
140 | vif->type == NL80211_IFTYPE_MESH_POINT) { | ||
141 | bd->sta_index = sta_priv->sta_index; | ||
142 | bd->dpu_desc_idx = sta_priv->dpu_desc_index; | ||
143 | } | ||
144 | } else { | ||
145 | __vif_priv = get_vif_by_addr(wcn, hdr->addr2); | ||
146 | bd->sta_index = __vif_priv->self_sta_index; | ||
147 | bd->dpu_desc_idx = __vif_priv->self_dpu_desc_index; | ||
148 | } | ||
149 | |||
150 | bd->dpu_sign = __vif_priv->ucast_dpu_signature; | ||
151 | |||
152 | if (ieee80211_is_nullfunc(hdr->frame_control) || | ||
153 | (sta_priv && !sta_priv->is_data_encrypted)) | ||
154 | bd->dpu_ne = 1; | ||
155 | |||
156 | if (bcast) { | ||
157 | bd->ub = 1; | ||
158 | bd->ack_policy = 1; | ||
159 | } | ||
160 | *vif_priv = __vif_priv; | ||
161 | } | ||
162 | |||
163 | static void wcn36xx_set_tx_mgmt(struct wcn36xx_tx_bd *bd, | ||
164 | struct wcn36xx *wcn, | ||
165 | struct wcn36xx_vif **vif_priv, | ||
166 | struct ieee80211_hdr *hdr, | ||
167 | bool bcast) | ||
168 | { | ||
169 | struct wcn36xx_vif *__vif_priv = | ||
170 | get_vif_by_addr(wcn, hdr->addr2); | ||
171 | bd->sta_index = __vif_priv->self_sta_index; | ||
172 | bd->dpu_desc_idx = __vif_priv->self_dpu_desc_index; | ||
173 | bd->dpu_ne = 1; | ||
174 | |||
175 | /* default rate for unicast */ | ||
176 | if (ieee80211_is_mgmt(hdr->frame_control)) | ||
177 | bd->bd_rate = (WCN36XX_BAND(wcn) == IEEE80211_BAND_5GHZ) ? | ||
178 | WCN36XX_BD_RATE_CTRL : | ||
179 | WCN36XX_BD_RATE_MGMT; | ||
180 | else if (ieee80211_is_ctl(hdr->frame_control)) | ||
181 | bd->bd_rate = WCN36XX_BD_RATE_CTRL; | ||
182 | else | ||
183 | wcn36xx_warn("frame control type unknown\n"); | ||
184 | |||
185 | /* | ||
186 | * In joining state trick hardware that probe is sent as | ||
187 | * unicast even if address is broadcast. | ||
188 | */ | ||
189 | if (__vif_priv->is_joining && | ||
190 | ieee80211_is_probe_req(hdr->frame_control)) | ||
191 | bcast = false; | ||
192 | |||
193 | if (bcast) { | ||
194 | /* broadcast */ | ||
195 | bd->ub = 1; | ||
196 | /* No ack needed not unicast */ | ||
197 | bd->ack_policy = 1; | ||
198 | bd->queue_id = WCN36XX_TX_B_WQ_ID; | ||
199 | } else | ||
200 | bd->queue_id = WCN36XX_TX_U_WQ_ID; | ||
201 | *vif_priv = __vif_priv; | ||
202 | } | ||
203 | |||
204 | int wcn36xx_start_tx(struct wcn36xx *wcn, | ||
205 | struct wcn36xx_sta *sta_priv, | ||
206 | struct sk_buff *skb) | ||
207 | { | ||
208 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
209 | struct wcn36xx_vif *vif_priv = NULL; | ||
210 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
211 | unsigned long flags; | ||
212 | bool is_low = ieee80211_is_data(hdr->frame_control); | ||
213 | bool bcast = is_broadcast_ether_addr(hdr->addr1) || | ||
214 | is_multicast_ether_addr(hdr->addr1); | ||
215 | struct wcn36xx_tx_bd *bd = wcn36xx_dxe_get_next_bd(wcn, is_low); | ||
216 | |||
217 | if (!bd) { | ||
218 | /* | ||
219 | * TX DXE are used in pairs. One for the BD and one for the | ||
220 | * actual frame. The BD DXE's has a preallocated buffer while | ||
221 | * the skb ones does not. If this isn't true something is really | ||
222 | * wierd. TODO: Recover from this situation | ||
223 | */ | ||
224 | |||
225 | wcn36xx_err("bd address may not be NULL for BD DXE\n"); | ||
226 | return -EINVAL; | ||
227 | } | ||
228 | |||
229 | memset(bd, 0, sizeof(*bd)); | ||
230 | |||
231 | wcn36xx_dbg(WCN36XX_DBG_TX, | ||
232 | "tx skb %p len %d fc %04x sn %d %s %s\n", | ||
233 | skb, skb->len, __le16_to_cpu(hdr->frame_control), | ||
234 | IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)), | ||
235 | is_low ? "low" : "high", bcast ? "bcast" : "ucast"); | ||
236 | |||
237 | wcn36xx_dbg_dump(WCN36XX_DBG_TX_DUMP, "", skb->data, skb->len); | ||
238 | |||
239 | bd->dpu_rf = WCN36XX_BMU_WQ_TX; | ||
240 | |||
241 | bd->tx_comp = info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
242 | if (bd->tx_comp) { | ||
243 | wcn36xx_dbg(WCN36XX_DBG_DXE, "TX_ACK status requested\n"); | ||
244 | spin_lock_irqsave(&wcn->dxe_lock, flags); | ||
245 | if (wcn->tx_ack_skb) { | ||
246 | spin_unlock_irqrestore(&wcn->dxe_lock, flags); | ||
247 | wcn36xx_warn("tx_ack_skb already set\n"); | ||
248 | return -EINVAL; | ||
249 | } | ||
250 | |||
251 | wcn->tx_ack_skb = skb; | ||
252 | spin_unlock_irqrestore(&wcn->dxe_lock, flags); | ||
253 | |||
254 | /* Only one at a time is supported by fw. Stop the TX queues | ||
255 | * until the ack status gets back. | ||
256 | * | ||
257 | * TODO: Add watchdog in case FW does not answer | ||
258 | */ | ||
259 | ieee80211_stop_queues(wcn->hw); | ||
260 | } | ||
261 | |||
262 | /* Data frames served first*/ | ||
263 | if (is_low) { | ||
264 | wcn36xx_set_tx_data(bd, wcn, &vif_priv, sta_priv, hdr, bcast); | ||
265 | wcn36xx_set_tx_pdu(bd, | ||
266 | ieee80211_is_data_qos(hdr->frame_control) ? | ||
267 | sizeof(struct ieee80211_qos_hdr) : | ||
268 | sizeof(struct ieee80211_hdr_3addr), | ||
269 | skb->len, sta_priv ? sta_priv->tid : 0); | ||
270 | } else { | ||
271 | /* MGMT and CTRL frames are handeld here*/ | ||
272 | wcn36xx_set_tx_mgmt(bd, wcn, &vif_priv, hdr, bcast); | ||
273 | wcn36xx_set_tx_pdu(bd, | ||
274 | ieee80211_is_data_qos(hdr->frame_control) ? | ||
275 | sizeof(struct ieee80211_qos_hdr) : | ||
276 | sizeof(struct ieee80211_hdr_3addr), | ||
277 | skb->len, WCN36XX_TID); | ||
278 | } | ||
279 | |||
280 | buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32)); | ||
281 | bd->tx_bd_sign = 0xbdbdbdbd; | ||
282 | |||
283 | return wcn36xx_dxe_tx_frame(wcn, vif_priv, skb, is_low); | ||
284 | } | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.h b/drivers/net/wireless/ath/wcn36xx/txrx.h new file mode 100644 index 000000000000..bbfbcf808c77 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/txrx.h | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _TXRX_H_ | ||
18 | #define _TXRX_H_ | ||
19 | |||
20 | #include <linux/etherdevice.h> | ||
21 | #include "wcn36xx.h" | ||
22 | |||
23 | /* TODO describe all properties */ | ||
24 | #define WCN36XX_802_11_HEADER_LEN 24 | ||
25 | #define WCN36XX_BMU_WQ_TX 25 | ||
26 | #define WCN36XX_TID 7 | ||
27 | /* broadcast wq ID */ | ||
28 | #define WCN36XX_TX_B_WQ_ID 0xA | ||
29 | #define WCN36XX_TX_U_WQ_ID 0x9 | ||
30 | /* bd_rate */ | ||
31 | #define WCN36XX_BD_RATE_DATA 0 | ||
32 | #define WCN36XX_BD_RATE_MGMT 2 | ||
33 | #define WCN36XX_BD_RATE_CTRL 3 | ||
34 | |||
35 | struct wcn36xx_pdu { | ||
36 | u32 dpu_fb:8; | ||
37 | u32 adu_fb:8; | ||
38 | u32 pdu_id:16; | ||
39 | |||
40 | /* 0x04*/ | ||
41 | u32 tail_pdu_idx:16; | ||
42 | u32 head_pdu_idx:16; | ||
43 | |||
44 | /* 0x08*/ | ||
45 | u32 pdu_count:7; | ||
46 | u32 mpdu_data_off:9; | ||
47 | u32 mpdu_header_off:8; | ||
48 | u32 mpdu_header_len:8; | ||
49 | |||
50 | /* 0x0c*/ | ||
51 | u32 reserved4:8; | ||
52 | u32 tid:4; | ||
53 | u32 reserved3:4; | ||
54 | u32 mpdu_len:16; | ||
55 | }; | ||
56 | |||
57 | struct wcn36xx_rx_bd { | ||
58 | u32 bdt:2; | ||
59 | u32 ft:1; | ||
60 | u32 dpu_ne:1; | ||
61 | u32 rx_key_id:3; | ||
62 | u32 ub:1; | ||
63 | u32 rmf:1; | ||
64 | u32 uma_bypass:1; | ||
65 | u32 csr11:1; | ||
66 | u32 reserved0:1; | ||
67 | u32 scan_learn:1; | ||
68 | u32 rx_ch:4; | ||
69 | u32 rtsf:1; | ||
70 | u32 bsf:1; | ||
71 | u32 a2hf:1; | ||
72 | u32 st_auf:1; | ||
73 | u32 dpu_sign:3; | ||
74 | u32 dpu_rf:8; | ||
75 | |||
76 | struct wcn36xx_pdu pdu; | ||
77 | |||
78 | /* 0x14*/ | ||
79 | u32 addr3:8; | ||
80 | u32 addr2:8; | ||
81 | u32 addr1:8; | ||
82 | u32 dpu_desc_idx:8; | ||
83 | |||
84 | /* 0x18*/ | ||
85 | u32 rxp_flags:23; | ||
86 | u32 rate_id:9; | ||
87 | |||
88 | u32 phy_stat0; | ||
89 | u32 phy_stat1; | ||
90 | |||
91 | /* 0x24 */ | ||
92 | u32 rx_times; | ||
93 | |||
94 | u32 pmi_cmd[6]; | ||
95 | |||
96 | /* 0x40 */ | ||
97 | u32 reserved7:4; | ||
98 | u32 reorder_slot_id:6; | ||
99 | u32 reorder_fwd_id:6; | ||
100 | u32 reserved6:12; | ||
101 | u32 reorder_code:4; | ||
102 | |||
103 | /* 0x44 */ | ||
104 | u32 exp_seq_num:12; | ||
105 | u32 cur_seq_num:12; | ||
106 | u32 fr_type_subtype:8; | ||
107 | |||
108 | /* 0x48 */ | ||
109 | u32 msdu_size:16; | ||
110 | u32 sub_fr_id:4; | ||
111 | u32 proc_order:4; | ||
112 | u32 reserved9:4; | ||
113 | u32 aef:1; | ||
114 | u32 lsf:1; | ||
115 | u32 esf:1; | ||
116 | u32 asf:1; | ||
117 | }; | ||
118 | |||
119 | struct wcn36xx_tx_bd { | ||
120 | u32 bdt:2; | ||
121 | u32 ft:1; | ||
122 | u32 dpu_ne:1; | ||
123 | u32 fw_tx_comp:1; | ||
124 | u32 tx_comp:1; | ||
125 | u32 reserved1:1; | ||
126 | u32 ub:1; | ||
127 | u32 rmf:1; | ||
128 | u32 reserved0:12; | ||
129 | u32 dpu_sign:3; | ||
130 | u32 dpu_rf:8; | ||
131 | |||
132 | struct wcn36xx_pdu pdu; | ||
133 | |||
134 | /* 0x14*/ | ||
135 | u32 reserved5:7; | ||
136 | u32 queue_id:5; | ||
137 | u32 bd_rate:2; | ||
138 | u32 ack_policy:2; | ||
139 | u32 sta_index:8; | ||
140 | u32 dpu_desc_idx:8; | ||
141 | |||
142 | u32 tx_bd_sign; | ||
143 | u32 reserved6; | ||
144 | u32 dxe_start_time; | ||
145 | u32 dxe_end_time; | ||
146 | |||
147 | /*u32 tcp_udp_start_off:10; | ||
148 | u32 header_cks:16; | ||
149 | u32 reserved7:6;*/ | ||
150 | }; | ||
151 | |||
152 | struct wcn36xx_sta; | ||
153 | struct wcn36xx; | ||
154 | |||
155 | int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb); | ||
156 | int wcn36xx_start_tx(struct wcn36xx *wcn, | ||
157 | struct wcn36xx_sta *sta_priv, | ||
158 | struct sk_buff *skb); | ||
159 | |||
160 | #endif /* _TXRX_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h new file mode 100644 index 000000000000..58b63833e8e7 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h | |||
@@ -0,0 +1,238 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _WCN36XX_H_ | ||
18 | #define _WCN36XX_H_ | ||
19 | |||
20 | #include <linux/completion.h> | ||
21 | #include <linux/printk.h> | ||
22 | #include <linux/spinlock.h> | ||
23 | #include <net/mac80211.h> | ||
24 | |||
25 | #include "hal.h" | ||
26 | #include "smd.h" | ||
27 | #include "txrx.h" | ||
28 | #include "dxe.h" | ||
29 | #include "pmc.h" | ||
30 | #include "debug.h" | ||
31 | |||
32 | #define WLAN_NV_FILE "wlan/prima/WCNSS_qcom_wlan_nv.bin" | ||
33 | #define WCN36XX_AGGR_BUFFER_SIZE 64 | ||
34 | |||
35 | extern unsigned int wcn36xx_dbg_mask; | ||
36 | |||
37 | enum wcn36xx_debug_mask { | ||
38 | WCN36XX_DBG_DXE = 0x00000001, | ||
39 | WCN36XX_DBG_DXE_DUMP = 0x00000002, | ||
40 | WCN36XX_DBG_SMD = 0x00000004, | ||
41 | WCN36XX_DBG_SMD_DUMP = 0x00000008, | ||
42 | WCN36XX_DBG_RX = 0x00000010, | ||
43 | WCN36XX_DBG_RX_DUMP = 0x00000020, | ||
44 | WCN36XX_DBG_TX = 0x00000040, | ||
45 | WCN36XX_DBG_TX_DUMP = 0x00000080, | ||
46 | WCN36XX_DBG_HAL = 0x00000100, | ||
47 | WCN36XX_DBG_HAL_DUMP = 0x00000200, | ||
48 | WCN36XX_DBG_MAC = 0x00000400, | ||
49 | WCN36XX_DBG_BEACON = 0x00000800, | ||
50 | WCN36XX_DBG_BEACON_DUMP = 0x00001000, | ||
51 | WCN36XX_DBG_PMC = 0x00002000, | ||
52 | WCN36XX_DBG_PMC_DUMP = 0x00004000, | ||
53 | WCN36XX_DBG_ANY = 0xffffffff, | ||
54 | }; | ||
55 | |||
56 | #define wcn36xx_err(fmt, arg...) \ | ||
57 | printk(KERN_ERR pr_fmt("ERROR " fmt), ##arg); | ||
58 | |||
59 | #define wcn36xx_warn(fmt, arg...) \ | ||
60 | printk(KERN_WARNING pr_fmt("WARNING " fmt), ##arg) | ||
61 | |||
62 | #define wcn36xx_info(fmt, arg...) \ | ||
63 | printk(KERN_INFO pr_fmt(fmt), ##arg) | ||
64 | |||
65 | #define wcn36xx_dbg(mask, fmt, arg...) do { \ | ||
66 | if (wcn36xx_dbg_mask & mask) \ | ||
67 | printk(KERN_DEBUG pr_fmt(fmt), ##arg); \ | ||
68 | } while (0) | ||
69 | |||
70 | #define wcn36xx_dbg_dump(mask, prefix_str, buf, len) do { \ | ||
71 | if (wcn36xx_dbg_mask & mask) \ | ||
72 | print_hex_dump(KERN_DEBUG, pr_fmt(prefix_str), \ | ||
73 | DUMP_PREFIX_OFFSET, 32, 1, \ | ||
74 | buf, len, false); \ | ||
75 | } while (0) | ||
76 | |||
77 | #define WCN36XX_HW_CHANNEL(__wcn) (__wcn->hw->conf.chandef.chan->hw_value) | ||
78 | #define WCN36XX_BAND(__wcn) (__wcn->hw->conf.chandef.chan->band) | ||
79 | #define WCN36XX_CENTER_FREQ(__wcn) (__wcn->hw->conf.chandef.chan->center_freq) | ||
80 | #define WCN36XX_LISTEN_INTERVAL(__wcn) (__wcn->hw->conf.listen_interval) | ||
81 | #define WCN36XX_FLAGS(__wcn) (__wcn->hw->flags) | ||
82 | #define WCN36XX_MAX_POWER(__wcn) (__wcn->hw->conf.chandef.chan->max_power) | ||
83 | |||
84 | static inline void buff_to_be(u32 *buf, size_t len) | ||
85 | { | ||
86 | int i; | ||
87 | for (i = 0; i < len; i++) | ||
88 | buf[i] = cpu_to_be32(buf[i]); | ||
89 | } | ||
90 | |||
91 | struct nv_data { | ||
92 | int is_valid; | ||
93 | u8 table; | ||
94 | }; | ||
95 | |||
96 | /* Interface for platform control path | ||
97 | * | ||
98 | * @open: hook must be called when wcn36xx wants to open control channel. | ||
99 | * @tx: sends a buffer. | ||
100 | */ | ||
101 | struct wcn36xx_platform_ctrl_ops { | ||
102 | int (*open)(void *drv_priv, void *rsp_cb); | ||
103 | void (*close)(void); | ||
104 | int (*tx)(char *buf, size_t len); | ||
105 | int (*get_hw_mac)(u8 *addr); | ||
106 | int (*smsm_change_state)(u32 clear_mask, u32 set_mask); | ||
107 | }; | ||
108 | |||
109 | /** | ||
110 | * struct wcn36xx_vif - holds VIF related fields | ||
111 | * | ||
112 | * @bss_index: bss_index is initially set to 0xFF. bss_index is received from | ||
113 | * HW after first config_bss call and must be used in delete_bss and | ||
114 | * enter/exit_bmps. | ||
115 | */ | ||
116 | struct wcn36xx_vif { | ||
117 | struct list_head list; | ||
118 | struct wcn36xx_sta *sta; | ||
119 | u8 dtim_period; | ||
120 | enum ani_ed_type encrypt_type; | ||
121 | bool is_joining; | ||
122 | struct wcn36xx_hal_mac_ssid ssid; | ||
123 | |||
124 | /* Power management */ | ||
125 | enum wcn36xx_power_state pw_state; | ||
126 | |||
127 | u8 bss_index; | ||
128 | u8 ucast_dpu_signature; | ||
129 | /* Returned from WCN36XX_HAL_ADD_STA_SELF_RSP */ | ||
130 | u8 self_sta_index; | ||
131 | u8 self_dpu_desc_index; | ||
132 | }; | ||
133 | |||
134 | /** | ||
135 | * struct wcn36xx_sta - holds STA related fields | ||
136 | * | ||
137 | * @tid: traffic ID that is used during AMPDU and in TX BD. | ||
138 | * @sta_index: STA index is returned from HW after config_sta call and is | ||
139 | * used in both SMD channel and TX BD. | ||
140 | * @dpu_desc_index: DPU descriptor index is returned from HW after config_sta | ||
141 | * call and is used in TX BD. | ||
142 | * @bss_sta_index: STA index is returned from HW after config_bss call and is | ||
143 | * used in both SMD channel and TX BD. See table bellow when it is used. | ||
144 | * @bss_dpu_desc_index: DPU descriptor index is returned from HW after | ||
145 | * config_bss call and is used in TX BD. | ||
146 | * ______________________________________________ | ||
147 | * | | STA | AP | | ||
148 | * |______________|_____________|_______________| | ||
149 | * | TX BD |bss_sta_index| sta_index | | ||
150 | * |______________|_____________|_______________| | ||
151 | * |all SMD calls |bss_sta_index| sta_index | | ||
152 | * |______________|_____________|_______________| | ||
153 | * |smd_delete_sta| sta_index | sta_index | | ||
154 | * |______________|_____________|_______________| | ||
155 | */ | ||
156 | struct wcn36xx_sta { | ||
157 | struct wcn36xx_vif *vif; | ||
158 | u16 aid; | ||
159 | u16 tid; | ||
160 | u8 sta_index; | ||
161 | u8 dpu_desc_index; | ||
162 | u8 bss_sta_index; | ||
163 | u8 bss_dpu_desc_index; | ||
164 | bool is_data_encrypted; | ||
165 | /* Rates */ | ||
166 | struct wcn36xx_hal_supported_rates supported_rates; | ||
167 | }; | ||
168 | struct wcn36xx_dxe_ch; | ||
169 | struct wcn36xx { | ||
170 | struct ieee80211_hw *hw; | ||
171 | struct device *dev; | ||
172 | struct list_head vif_list; | ||
173 | |||
174 | u8 fw_revision; | ||
175 | u8 fw_version; | ||
176 | u8 fw_minor; | ||
177 | u8 fw_major; | ||
178 | |||
179 | /* extra byte for the NULL termination */ | ||
180 | u8 crm_version[WCN36XX_HAL_VERSION_LENGTH + 1]; | ||
181 | u8 wlan_version[WCN36XX_HAL_VERSION_LENGTH + 1]; | ||
182 | |||
183 | /* IRQs */ | ||
184 | int tx_irq; | ||
185 | int rx_irq; | ||
186 | void __iomem *mmio; | ||
187 | |||
188 | struct wcn36xx_platform_ctrl_ops *ctrl_ops; | ||
189 | /* | ||
190 | * smd_buf must be protected with smd_mutex to garantee | ||
191 | * that all messages are sent one after another | ||
192 | */ | ||
193 | u8 *hal_buf; | ||
194 | size_t hal_rsp_len; | ||
195 | struct mutex hal_mutex; | ||
196 | struct completion hal_rsp_compl; | ||
197 | struct workqueue_struct *hal_ind_wq; | ||
198 | struct work_struct hal_ind_work; | ||
199 | struct mutex hal_ind_mutex; | ||
200 | struct list_head hal_ind_queue; | ||
201 | |||
202 | /* DXE channels */ | ||
203 | struct wcn36xx_dxe_ch dxe_tx_l_ch; /* TX low */ | ||
204 | struct wcn36xx_dxe_ch dxe_tx_h_ch; /* TX high */ | ||
205 | struct wcn36xx_dxe_ch dxe_rx_l_ch; /* RX low */ | ||
206 | struct wcn36xx_dxe_ch dxe_rx_h_ch; /* RX high */ | ||
207 | |||
208 | /* For synchronization of DXE resources from BH, IRQ and WQ contexts */ | ||
209 | spinlock_t dxe_lock; | ||
210 | bool queues_stopped; | ||
211 | |||
212 | /* Memory pools */ | ||
213 | struct wcn36xx_dxe_mem_pool mgmt_mem_pool; | ||
214 | struct wcn36xx_dxe_mem_pool data_mem_pool; | ||
215 | |||
216 | struct sk_buff *tx_ack_skb; | ||
217 | |||
218 | #ifdef CONFIG_WCN36XX_DEBUGFS | ||
219 | /* Debug file system entry */ | ||
220 | struct wcn36xx_dfs_entry dfs; | ||
221 | #endif /* CONFIG_WCN36XX_DEBUGFS */ | ||
222 | |||
223 | }; | ||
224 | |||
225 | static inline bool wcn36xx_is_fw_version(struct wcn36xx *wcn, | ||
226 | u8 major, | ||
227 | u8 minor, | ||
228 | u8 version, | ||
229 | u8 revision) | ||
230 | { | ||
231 | return (wcn->fw_major == major && | ||
232 | wcn->fw_minor == minor && | ||
233 | wcn->fw_version == version && | ||
234 | wcn->fw_revision == revision); | ||
235 | } | ||
236 | void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates); | ||
237 | |||
238 | #endif /* _WCN36XX_H_ */ | ||