diff options
-rw-r--r-- | drivers/net/wireless/wl12xx/acx.c | 690 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/acx.h | 126 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/cmd.c | 311 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/cmd.h | 168 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 87 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/ps.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/ps.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/rx.c | 27 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1251.c | 74 |
9 files changed, 896 insertions, 591 deletions
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 1cfd458ad5ab..d0daf69558f0 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c | |||
@@ -13,126 +13,160 @@ | |||
13 | int wl12xx_acx_frame_rates(struct wl12xx *wl, u8 ctrl_rate, u8 ctrl_mod, | 13 | int wl12xx_acx_frame_rates(struct wl12xx *wl, u8 ctrl_rate, u8 ctrl_mod, |
14 | u8 mgt_rate, u8 mgt_mod) | 14 | u8 mgt_rate, u8 mgt_mod) |
15 | { | 15 | { |
16 | struct acx_fw_gen_frame_rates *rates; | ||
16 | int ret; | 17 | int ret; |
17 | struct acx_fw_gen_frame_rates rates; | ||
18 | 18 | ||
19 | wl12xx_debug(DEBUG_ACX, "acx frame rates"); | 19 | wl12xx_debug(DEBUG_ACX, "acx frame rates"); |
20 | 20 | ||
21 | rates.header.id = ACX_FW_GEN_FRAME_RATES; | 21 | rates = kzalloc(sizeof(*rates), GFP_KERNEL); |
22 | rates.header.len = sizeof(struct acx_fw_gen_frame_rates) - | 22 | if (!rates) { |
23 | sizeof(struct acx_header); | 23 | ret = -ENOMEM; |
24 | goto out; | ||
25 | } | ||
24 | 26 | ||
25 | rates.tx_ctrl_frame_rate = ctrl_rate; | 27 | rates->tx_ctrl_frame_rate = ctrl_rate; |
26 | rates.tx_ctrl_frame_mod = ctrl_mod; | 28 | rates->tx_ctrl_frame_mod = ctrl_mod; |
27 | rates.tx_mgt_frame_rate = mgt_rate; | 29 | rates->tx_mgt_frame_rate = mgt_rate; |
28 | rates.tx_mgt_frame_mod = mgt_mod; | 30 | rates->tx_mgt_frame_mod = mgt_mod; |
29 | 31 | ||
30 | ret = wl12xx_cmd_configure(wl, &rates, sizeof(rates)); | 32 | ret = wl12xx_cmd_configure(wl, ACX_FW_GEN_FRAME_RATES, |
33 | rates, sizeof(*rates)); | ||
31 | if (ret < 0) { | 34 | if (ret < 0) { |
32 | wl12xx_error("Failed to set FW rates and modulation"); | 35 | wl12xx_error("Failed to set FW rates and modulation"); |
33 | return ret; | 36 | goto out; |
34 | } | 37 | } |
35 | 38 | ||
36 | return 0; | 39 | out: |
40 | kfree(rates); | ||
41 | return ret; | ||
37 | } | 42 | } |
38 | 43 | ||
39 | 44 | ||
40 | int wl12xx_acx_station_id(struct wl12xx *wl) | 45 | int wl12xx_acx_station_id(struct wl12xx *wl) |
41 | { | 46 | { |
47 | struct acx_dot11_station_id *mac; | ||
42 | int ret, i; | 48 | int ret, i; |
43 | struct dot11_station_id mac; | ||
44 | 49 | ||
45 | wl12xx_debug(DEBUG_ACX, "acx dot11_station_id"); | 50 | wl12xx_debug(DEBUG_ACX, "acx dot11_station_id"); |
46 | 51 | ||
47 | mac.header.id = DOT11_STATION_ID; | 52 | mac = kzalloc(sizeof(*mac), GFP_KERNEL); |
48 | mac.header.len = sizeof(mac) - sizeof(struct acx_header); | 53 | if (!mac) { |
54 | ret = -ENOMEM; | ||
55 | goto out; | ||
56 | } | ||
49 | 57 | ||
50 | for (i = 0; i < ETH_ALEN; i++) | 58 | for (i = 0; i < ETH_ALEN; i++) |
51 | mac.mac[i] = wl->mac_addr[ETH_ALEN - 1 - i]; | 59 | mac->mac[i] = wl->mac_addr[ETH_ALEN - 1 - i]; |
52 | 60 | ||
53 | ret = wl12xx_cmd_configure(wl, &mac, sizeof(mac)); | 61 | ret = wl12xx_cmd_configure(wl, DOT11_STATION_ID, mac, sizeof(*mac)); |
54 | if (ret < 0) | 62 | if (ret < 0) |
55 | return ret; | 63 | goto out; |
56 | 64 | ||
57 | return 0; | 65 | out: |
66 | kfree(mac); | ||
67 | return ret; | ||
58 | } | 68 | } |
59 | 69 | ||
60 | int wl12xx_acx_default_key(struct wl12xx *wl, u8 key_id) | 70 | int wl12xx_acx_default_key(struct wl12xx *wl, u8 key_id) |
61 | { | 71 | { |
62 | struct acx_dot11_default_key default_key; | 72 | struct acx_dot11_default_key *default_key; |
63 | int ret; | 73 | int ret; |
64 | 74 | ||
65 | wl12xx_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id); | 75 | wl12xx_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id); |
66 | 76 | ||
67 | default_key.header.id = DOT11_DEFAULT_KEY; | 77 | default_key = kzalloc(sizeof(*default_key), GFP_KERNEL); |
68 | default_key.header.len = sizeof(default_key) - | 78 | if (!default_key) { |
69 | sizeof(struct acx_header); | 79 | ret = -ENOMEM; |
80 | goto out; | ||
81 | } | ||
70 | 82 | ||
71 | default_key.id = key_id; | 83 | default_key->id = key_id; |
72 | 84 | ||
73 | ret = wl12xx_cmd_configure(wl, &default_key, sizeof(default_key)); | 85 | ret = wl12xx_cmd_configure(wl, DOT11_DEFAULT_KEY, |
86 | default_key, sizeof(*default_key)); | ||
74 | if (ret < 0) { | 87 | if (ret < 0) { |
75 | wl12xx_error("Couldnt set default key"); | 88 | wl12xx_error("Couldnt set default key"); |
76 | return ret; | 89 | goto out; |
77 | } | 90 | } |
78 | 91 | ||
79 | wl->default_key = key_id; | 92 | wl->default_key = key_id; |
80 | 93 | ||
81 | return 0; | 94 | out: |
95 | kfree(default_key); | ||
96 | return ret; | ||
82 | } | 97 | } |
83 | 98 | ||
84 | int wl12xx_acx_wake_up_conditions(struct wl12xx *wl, u8 listen_interval) | 99 | int wl12xx_acx_wake_up_conditions(struct wl12xx *wl, u8 listen_interval) |
85 | { | 100 | { |
86 | struct acx_wake_up_condition wake_up; | 101 | struct acx_wake_up_condition *wake_up; |
102 | int ret; | ||
87 | 103 | ||
88 | wl12xx_debug(DEBUG_ACX, "acx wake up conditions"); | 104 | wl12xx_debug(DEBUG_ACX, "acx wake up conditions"); |
89 | 105 | ||
90 | wake_up.header.id = ACX_WAKE_UP_CONDITIONS; | 106 | wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL); |
91 | wake_up.header.len = sizeof(wake_up) - sizeof(struct acx_header); | 107 | if (!wake_up) { |
108 | ret = -ENOMEM; | ||
109 | goto out; | ||
110 | } | ||
92 | 111 | ||
93 | wake_up.wake_up_event = WAKE_UP_EVENT_DTIM_BITMAP; | 112 | wake_up->wake_up_event = WAKE_UP_EVENT_DTIM_BITMAP; |
94 | wake_up.listen_interval = listen_interval; | 113 | wake_up->listen_interval = listen_interval; |
95 | 114 | ||
96 | return wl12xx_cmd_configure(wl, &wake_up, sizeof(wake_up)); | 115 | ret = wl12xx_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS, |
116 | wake_up, sizeof(*wake_up)); | ||
117 | if (ret < 0) { | ||
118 | wl12xx_warning("could not set wake up conditions: %d", ret); | ||
119 | goto out; | ||
120 | } | ||
121 | |||
122 | out: | ||
123 | kfree(wake_up); | ||
124 | return ret; | ||
97 | } | 125 | } |
98 | 126 | ||
99 | int wl12xx_acx_sleep_auth(struct wl12xx *wl, u8 sleep_auth) | 127 | int wl12xx_acx_sleep_auth(struct wl12xx *wl, u8 sleep_auth) |
100 | { | 128 | { |
129 | struct acx_sleep_auth *auth; | ||
101 | int ret; | 130 | int ret; |
102 | struct acx_sleep_auth auth; | ||
103 | 131 | ||
104 | wl12xx_debug(DEBUG_ACX, "acx sleep auth"); | 132 | wl12xx_debug(DEBUG_ACX, "acx sleep auth"); |
105 | 133 | ||
106 | auth.header.id = ACX_SLEEP_AUTH; | 134 | auth = kzalloc(sizeof(*auth), GFP_KERNEL); |
107 | auth.header.len = sizeof(auth) - sizeof(struct acx_header); | 135 | if (!auth) { |
136 | ret = -ENOMEM; | ||
137 | goto out; | ||
138 | } | ||
108 | 139 | ||
109 | auth.sleep_auth = sleep_auth; | 140 | auth->sleep_auth = sleep_auth; |
110 | 141 | ||
111 | ret = wl12xx_cmd_configure(wl, &auth, sizeof(auth)); | 142 | ret = wl12xx_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth)); |
112 | if (ret < 0) | 143 | if (ret < 0) |
113 | return ret; | 144 | return ret; |
114 | 145 | ||
115 | return 0; | 146 | out: |
147 | kfree(auth); | ||
148 | return ret; | ||
116 | } | 149 | } |
117 | 150 | ||
118 | int wl12xx_acx_fw_version(struct wl12xx *wl, char *buf, size_t len) | 151 | int wl12xx_acx_fw_version(struct wl12xx *wl, char *buf, size_t len) |
119 | { | 152 | { |
120 | struct wl12xx_command cmd; | ||
121 | struct acx_revision *rev; | 153 | struct acx_revision *rev; |
122 | int ret; | 154 | int ret; |
123 | 155 | ||
124 | wl12xx_debug(DEBUG_ACX, "acx fw rev"); | 156 | wl12xx_debug(DEBUG_ACX, "acx fw rev"); |
125 | 157 | ||
126 | memset(&cmd, 0, sizeof(cmd)); | 158 | rev = kzalloc(sizeof(*rev), GFP_KERNEL); |
159 | if (!rev) { | ||
160 | ret = -ENOMEM; | ||
161 | goto out; | ||
162 | } | ||
127 | 163 | ||
128 | ret = wl12xx_cmd_interrogate(wl, ACX_FW_REV, sizeof(*rev), &cmd); | 164 | ret = wl12xx_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev)); |
129 | if (ret < 0) { | 165 | if (ret < 0) { |
130 | wl12xx_warning("ACX_FW_REV interrogate failed"); | 166 | wl12xx_warning("ACX_FW_REV interrogate failed"); |
131 | return ret; | 167 | goto out; |
132 | } | 168 | } |
133 | 169 | ||
134 | rev = (struct acx_revision *) &cmd.parameters; | ||
135 | |||
136 | /* be careful with the buffer sizes */ | 170 | /* be careful with the buffer sizes */ |
137 | strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version))); | 171 | strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version))); |
138 | 172 | ||
@@ -143,12 +177,14 @@ int wl12xx_acx_fw_version(struct wl12xx *wl, char *buf, size_t len) | |||
143 | */ | 177 | */ |
144 | buf[min(len, sizeof(rev->fw_version)) - 1] = '\0'; | 178 | buf[min(len, sizeof(rev->fw_version)) - 1] = '\0'; |
145 | 179 | ||
146 | return 0; | 180 | out: |
181 | kfree(rev); | ||
182 | return ret; | ||
147 | } | 183 | } |
148 | 184 | ||
149 | int wl12xx_acx_tx_power(struct wl12xx *wl, int power) | 185 | int wl12xx_acx_tx_power(struct wl12xx *wl, int power) |
150 | { | 186 | { |
151 | struct acx_current_tx_power ie; | 187 | struct acx_current_tx_power *acx; |
152 | int ret; | 188 | int ret; |
153 | 189 | ||
154 | wl12xx_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr"); | 190 | wl12xx_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr"); |
@@ -156,534 +192,648 @@ int wl12xx_acx_tx_power(struct wl12xx *wl, int power) | |||
156 | if (power < 0 || power > 25) | 192 | if (power < 0 || power > 25) |
157 | return -EINVAL; | 193 | return -EINVAL; |
158 | 194 | ||
159 | memset(&ie, 0, sizeof(ie)); | 195 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
196 | if (!acx) { | ||
197 | ret = -ENOMEM; | ||
198 | goto out; | ||
199 | } | ||
160 | 200 | ||
161 | ie.header.id = DOT11_CUR_TX_PWR; | 201 | acx->current_tx_power = power * 10; |
162 | ie.header.len = sizeof(ie) - sizeof(struct acx_header); | ||
163 | ie.current_tx_power = power * 10; | ||
164 | 202 | ||
165 | ret = wl12xx_cmd_configure(wl, &ie, sizeof(ie)); | 203 | ret = wl12xx_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); |
166 | if (ret < 0) { | 204 | if (ret < 0) { |
167 | wl12xx_warning("configure of tx power failed: %d", ret); | 205 | wl12xx_warning("configure of tx power failed: %d", ret); |
168 | return ret; | 206 | goto out; |
169 | } | 207 | } |
170 | 208 | ||
171 | return 0; | 209 | out: |
210 | kfree(acx); | ||
211 | return ret; | ||
172 | } | 212 | } |
173 | 213 | ||
174 | int wl12xx_acx_feature_cfg(struct wl12xx *wl) | 214 | int wl12xx_acx_feature_cfg(struct wl12xx *wl) |
175 | { | 215 | { |
176 | struct acx_feature_config feature; | 216 | struct acx_feature_config *feature; |
177 | int ret; | 217 | int ret; |
178 | 218 | ||
179 | wl12xx_debug(DEBUG_ACX, "acx feature cfg"); | 219 | wl12xx_debug(DEBUG_ACX, "acx feature cfg"); |
180 | 220 | ||
181 | memset(&feature, 0, sizeof(feature)); | 221 | feature = kzalloc(sizeof(*feature), GFP_KERNEL); |
182 | 222 | if (!feature) { | |
183 | feature.header.id = ACX_FEATURE_CFG; | 223 | ret = -ENOMEM; |
184 | feature.header.len = sizeof(feature) - sizeof(struct acx_header); | 224 | goto out; |
225 | } | ||
185 | 226 | ||
186 | /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */ | 227 | /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */ |
187 | feature.data_flow_options = 0; | 228 | feature->data_flow_options = 0; |
188 | feature.options = 0; | 229 | feature->options = 0; |
189 | 230 | ||
190 | ret = wl12xx_cmd_configure(wl, &feature, sizeof(feature)); | 231 | ret = wl12xx_cmd_configure(wl, ACX_FEATURE_CFG, |
191 | if (ret < 0) | 232 | feature, sizeof(*feature)); |
233 | if (ret < 0) { | ||
192 | wl12xx_error("Couldnt set HW encryption"); | 234 | wl12xx_error("Couldnt set HW encryption"); |
235 | goto out; | ||
236 | } | ||
193 | 237 | ||
238 | out: | ||
239 | kfree(feature); | ||
194 | return ret; | 240 | return ret; |
195 | } | 241 | } |
196 | 242 | ||
197 | int wl12xx_acx_mem_map(struct wl12xx *wl, void *mem_map, size_t len) | 243 | int wl12xx_acx_mem_map(struct wl12xx *wl, struct acx_header *mem_map, |
244 | size_t len) | ||
198 | { | 245 | { |
199 | struct wl12xx_command cmd; | ||
200 | int ret; | 246 | int ret; |
201 | 247 | ||
202 | wl12xx_debug(DEBUG_ACX, "acx mem map"); | 248 | wl12xx_debug(DEBUG_ACX, "acx mem map"); |
203 | 249 | ||
204 | ret = wl12xx_cmd_interrogate(wl, ACX_MEM_MAP, len, &cmd); | 250 | ret = wl12xx_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len); |
205 | if (ret < 0) | 251 | if (ret < 0) |
206 | return ret; | 252 | return ret; |
207 | else if (cmd.status != CMD_STATUS_SUCCESS) | ||
208 | return -EIO; | ||
209 | |||
210 | memcpy(mem_map, &cmd.parameters, len); | ||
211 | 253 | ||
212 | return 0; | 254 | return 0; |
213 | } | 255 | } |
214 | 256 | ||
215 | int wl12xx_acx_data_path_params(struct wl12xx *wl, | 257 | int wl12xx_acx_data_path_params(struct wl12xx *wl, |
216 | struct acx_data_path_params_resp *data_path) | 258 | struct acx_data_path_params_resp *resp) |
217 | { | 259 | { |
218 | struct acx_data_path_params params; | 260 | struct acx_data_path_params *params; |
219 | struct wl12xx_command cmd; | ||
220 | int ret; | 261 | int ret; |
221 | 262 | ||
222 | wl12xx_debug(DEBUG_ACX, "acx data path params"); | 263 | wl12xx_debug(DEBUG_ACX, "acx data path params"); |
223 | 264 | ||
224 | params.rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE; | 265 | params = kzalloc(sizeof(*params), GFP_KERNEL); |
225 | params.tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE; | 266 | if (!params) { |
267 | ret = -ENOMEM; | ||
268 | goto out; | ||
269 | } | ||
226 | 270 | ||
227 | params.rx_packet_ring_chunk_num = DP_RX_PACKET_RING_CHUNK_NUM; | 271 | params->rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE; |
228 | params.tx_packet_ring_chunk_num = DP_TX_PACKET_RING_CHUNK_NUM; | 272 | params->tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE; |
229 | 273 | ||
230 | params.tx_complete_threshold = 1; | 274 | params->rx_packet_ring_chunk_num = DP_RX_PACKET_RING_CHUNK_NUM; |
275 | params->tx_packet_ring_chunk_num = DP_TX_PACKET_RING_CHUNK_NUM; | ||
231 | 276 | ||
232 | params.tx_complete_ring_depth = FW_TX_CMPLT_BLOCK_SIZE; | 277 | params->tx_complete_threshold = 1; |
233 | 278 | ||
234 | params.tx_complete_timeout = DP_TX_COMPLETE_TIME_OUT; | 279 | params->tx_complete_ring_depth = FW_TX_CMPLT_BLOCK_SIZE; |
235 | 280 | ||
236 | params.header.id = ACX_DATA_PATH_PARAMS; | 281 | params->tx_complete_timeout = DP_TX_COMPLETE_TIME_OUT; |
237 | params.header.len = sizeof(params) - sizeof(struct acx_header); | ||
238 | 282 | ||
239 | ret = wl12xx_cmd_configure(wl, ¶ms, sizeof(params)); | 283 | ret = wl12xx_cmd_configure(wl, ACX_DATA_PATH_PARAMS, |
284 | params, sizeof(*params)); | ||
240 | if (ret < 0) | 285 | if (ret < 0) |
241 | return ret; | 286 | goto out; |
242 | |||
243 | 287 | ||
288 | /* FIXME: shouldn't this be ACX_DATA_PATH_RESP_PARAMS? */ | ||
244 | ret = wl12xx_cmd_interrogate(wl, ACX_DATA_PATH_PARAMS, | 289 | ret = wl12xx_cmd_interrogate(wl, ACX_DATA_PATH_PARAMS, |
245 | sizeof(struct acx_data_path_params_resp), | 290 | resp, sizeof(*resp)); |
246 | &cmd); | ||
247 | 291 | ||
248 | if (ret < 0) { | 292 | if (ret < 0) { |
249 | wl12xx_warning("failed to read data path parameters: %d", ret); | 293 | wl12xx_warning("failed to read data path parameters: %d", ret); |
250 | return ret; | 294 | goto out; |
251 | } else if (cmd.status != CMD_STATUS_SUCCESS) { | 295 | } else if (resp->header.cmd.status != CMD_STATUS_SUCCESS) { |
252 | wl12xx_warning("data path parameter acx status failed"); | 296 | wl12xx_warning("data path parameter acx status failed"); |
253 | return -EIO; | 297 | ret = -EIO; |
298 | goto out; | ||
254 | } | 299 | } |
255 | 300 | ||
256 | memcpy(data_path, &cmd.parameters, sizeof(*data_path)); | 301 | out: |
257 | 302 | kfree(params); | |
258 | return 0; | 303 | return ret; |
259 | } | 304 | } |
260 | 305 | ||
261 | int wl12xx_acx_rx_msdu_life_time(struct wl12xx *wl, u32 life_time) | 306 | int wl12xx_acx_rx_msdu_life_time(struct wl12xx *wl, u32 life_time) |
262 | { | 307 | { |
263 | struct rx_msdu_lifetime msdu_lifetime; | 308 | struct acx_rx_msdu_lifetime *acx; |
264 | int ret; | 309 | int ret; |
265 | 310 | ||
266 | wl12xx_debug(DEBUG_ACX, "acx rx msdu life time"); | 311 | wl12xx_debug(DEBUG_ACX, "acx rx msdu life time"); |
267 | 312 | ||
268 | msdu_lifetime.header.id = DOT11_RX_MSDU_LIFE_TIME; | 313 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
269 | msdu_lifetime.header.len = sizeof(msdu_lifetime) - | 314 | if (!acx) { |
270 | sizeof(struct acx_header); | 315 | ret = -ENOMEM; |
271 | msdu_lifetime.lifetime = life_time; | 316 | goto out; |
317 | } | ||
272 | 318 | ||
273 | ret = wl12xx_cmd_configure(wl, &msdu_lifetime, sizeof(msdu_lifetime)); | 319 | ret = wl12xx_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME, |
320 | acx, sizeof(*acx)); | ||
274 | if (ret < 0) { | 321 | if (ret < 0) { |
275 | wl12xx_warning("failed to set rx msdu life time: %d", ret); | 322 | wl12xx_warning("failed to set rx msdu life time: %d", ret); |
276 | return ret; | 323 | goto out; |
277 | } | 324 | } |
278 | 325 | ||
279 | return 0; | 326 | out: |
327 | kfree(acx); | ||
328 | return ret; | ||
280 | } | 329 | } |
281 | 330 | ||
282 | int wl12xx_acx_rx_config(struct wl12xx *wl, u32 config, u32 filter) | 331 | int wl12xx_acx_rx_config(struct wl12xx *wl, u32 config, u32 filter) |
283 | { | 332 | { |
284 | struct acx_rx_config rx_config; | 333 | struct acx_rx_config *rx_config; |
285 | int ret; | 334 | int ret; |
286 | 335 | ||
287 | wl12xx_debug(DEBUG_ACX, "acx rx config"); | 336 | wl12xx_debug(DEBUG_ACX, "acx rx config"); |
288 | 337 | ||
289 | rx_config.header.id = ACX_RX_CFG; | 338 | rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL); |
290 | rx_config.header.len = sizeof(rx_config) - sizeof(struct acx_header); | 339 | if (!rx_config) { |
291 | rx_config.config_options = config; | 340 | ret = -ENOMEM; |
292 | rx_config.filter_options = filter; | 341 | goto out; |
342 | } | ||
343 | |||
344 | rx_config->config_options = config; | ||
345 | rx_config->filter_options = filter; | ||
293 | 346 | ||
294 | ret = wl12xx_cmd_configure(wl, &rx_config, sizeof(rx_config)); | 347 | ret = wl12xx_cmd_configure(wl, ACX_RX_CFG, |
348 | rx_config, sizeof(*rx_config)); | ||
295 | if (ret < 0) { | 349 | if (ret < 0) { |
296 | wl12xx_warning("failed to set rx config: %d", ret); | 350 | wl12xx_warning("failed to set rx config: %d", ret); |
297 | return ret; | 351 | goto out; |
298 | } | 352 | } |
299 | 353 | ||
300 | return 0; | 354 | out: |
355 | kfree(rx_config); | ||
356 | return ret; | ||
301 | } | 357 | } |
302 | 358 | ||
303 | int wl12xx_acx_pd_threshold(struct wl12xx *wl) | 359 | int wl12xx_acx_pd_threshold(struct wl12xx *wl) |
304 | { | 360 | { |
305 | struct acx_packet_detection packet_detection; | 361 | struct acx_packet_detection *pd; |
306 | int ret; | 362 | int ret; |
307 | 363 | ||
308 | wl12xx_debug(DEBUG_ACX, "acx data pd threshold"); | 364 | wl12xx_debug(DEBUG_ACX, "acx data pd threshold"); |
309 | 365 | ||
366 | pd = kzalloc(sizeof(*pd), GFP_KERNEL); | ||
367 | if (!pd) { | ||
368 | ret = -ENOMEM; | ||
369 | goto out; | ||
370 | } | ||
371 | |||
310 | /* FIXME: threshold value not set */ | 372 | /* FIXME: threshold value not set */ |
311 | packet_detection.header.id = ACX_PD_THRESHOLD; | ||
312 | packet_detection.header.len = sizeof(packet_detection) - | ||
313 | sizeof(struct acx_header); | ||
314 | 373 | ||
315 | ret = wl12xx_cmd_configure(wl, &packet_detection, | 374 | ret = wl12xx_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd)); |
316 | sizeof(packet_detection)); | ||
317 | if (ret < 0) { | 375 | if (ret < 0) { |
318 | wl12xx_warning("failed to set pd threshold: %d", ret); | 376 | wl12xx_warning("failed to set pd threshold: %d", ret); |
319 | return ret; | 377 | goto out; |
320 | } | 378 | } |
321 | 379 | ||
380 | out: | ||
381 | kfree(pd); | ||
322 | return 0; | 382 | return 0; |
323 | } | 383 | } |
324 | 384 | ||
325 | int wl12xx_acx_slot(struct wl12xx *wl, enum acx_slot_type slot_time) | 385 | int wl12xx_acx_slot(struct wl12xx *wl, enum acx_slot_type slot_time) |
326 | { | 386 | { |
327 | struct acx_slot slot; | 387 | struct acx_slot *slot; |
328 | int ret; | 388 | int ret; |
329 | 389 | ||
330 | wl12xx_debug(DEBUG_ACX, "acx slot"); | 390 | wl12xx_debug(DEBUG_ACX, "acx slot"); |
331 | 391 | ||
332 | slot.header.id = ACX_SLOT; | 392 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); |
333 | slot.header.len = sizeof(slot) - sizeof(struct acx_header); | 393 | if (!slot) { |
394 | ret = -ENOMEM; | ||
395 | goto out; | ||
396 | } | ||
334 | 397 | ||
335 | slot.wone_index = STATION_WONE_INDEX; | 398 | slot->wone_index = STATION_WONE_INDEX; |
336 | slot.slot_time = slot_time; | 399 | slot->slot_time = slot_time; |
337 | 400 | ||
338 | ret = wl12xx_cmd_configure(wl, &slot, sizeof(slot)); | 401 | ret = wl12xx_cmd_configure(wl, ACX_SLOT, slot, sizeof(*slot)); |
339 | if (ret < 0) { | 402 | if (ret < 0) { |
340 | wl12xx_warning("failed to set slot time: %d", ret); | 403 | wl12xx_warning("failed to set slot time: %d", ret); |
341 | return ret; | 404 | goto out; |
342 | } | 405 | } |
343 | 406 | ||
344 | return 0; | 407 | out: |
408 | kfree(slot); | ||
409 | return ret; | ||
345 | } | 410 | } |
346 | 411 | ||
347 | int wl12xx_acx_group_address_tbl(struct wl12xx *wl) | 412 | int wl12xx_acx_group_address_tbl(struct wl12xx *wl) |
348 | { | 413 | { |
349 | struct multicast_grp_addr_start multicast; | 414 | struct acx_dot11_grp_addr_tbl *acx; |
350 | int ret; | 415 | int ret; |
351 | 416 | ||
352 | wl12xx_debug(DEBUG_ACX, "acx group address tbl"); | 417 | wl12xx_debug(DEBUG_ACX, "acx group address tbl"); |
353 | 418 | ||
354 | /* MAC filtering */ | 419 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
355 | multicast.header.id = DOT11_GROUP_ADDRESS_TBL; | 420 | if (!acx) { |
356 | multicast.header.len = sizeof(multicast) - sizeof(struct acx_header); | 421 | ret = -ENOMEM; |
422 | goto out; | ||
423 | } | ||
357 | 424 | ||
358 | multicast.enabled = 0; | 425 | /* MAC filtering */ |
359 | multicast.num_groups = 0; | 426 | acx->enabled = 0; |
360 | memset(multicast.mac_table, 0, ADDRESS_GROUP_MAX_LEN); | 427 | acx->num_groups = 0; |
428 | memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN); | ||
361 | 429 | ||
362 | ret = wl12xx_cmd_configure(wl, &multicast, sizeof(multicast)); | 430 | ret = wl12xx_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL, |
431 | acx, sizeof(*acx)); | ||
363 | if (ret < 0) { | 432 | if (ret < 0) { |
364 | wl12xx_warning("failed to set group addr table: %d", ret); | 433 | wl12xx_warning("failed to set group addr table: %d", ret); |
365 | return ret; | 434 | goto out; |
366 | } | 435 | } |
367 | 436 | ||
368 | return 0; | 437 | out: |
438 | kfree(acx); | ||
439 | return ret; | ||
369 | } | 440 | } |
370 | 441 | ||
371 | int wl12xx_acx_service_period_timeout(struct wl12xx *wl) | 442 | int wl12xx_acx_service_period_timeout(struct wl12xx *wl) |
372 | { | 443 | { |
373 | struct acx_rx_timeout rx_timeout; | 444 | struct acx_rx_timeout *rx_timeout; |
374 | int ret; | 445 | int ret; |
375 | 446 | ||
376 | wl12xx_debug(DEBUG_ACX, "acx service period timeout"); | 447 | rx_timeout = kzalloc(sizeof(*rx_timeout), GFP_KERNEL); |
448 | if (!rx_timeout) { | ||
449 | ret = -ENOMEM; | ||
450 | goto out; | ||
451 | } | ||
377 | 452 | ||
378 | /* RX timeout */ | 453 | wl12xx_debug(DEBUG_ACX, "acx service period timeout"); |
379 | rx_timeout.header.id = ACX_SERVICE_PERIOD_TIMEOUT; | ||
380 | rx_timeout.header.len = sizeof(rx_timeout) - sizeof(struct acx_header); | ||
381 | 454 | ||
382 | rx_timeout.ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF; | 455 | rx_timeout->ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF; |
383 | rx_timeout.upsd_timeout = RX_TIMEOUT_UPSD_DEF; | 456 | rx_timeout->upsd_timeout = RX_TIMEOUT_UPSD_DEF; |
384 | 457 | ||
385 | ret = wl12xx_cmd_configure(wl, &rx_timeout, sizeof(rx_timeout)); | 458 | ret = wl12xx_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT, |
459 | rx_timeout, sizeof(*rx_timeout)); | ||
386 | if (ret < 0) { | 460 | if (ret < 0) { |
387 | wl12xx_warning("failed to set service period timeout: %d", | 461 | wl12xx_warning("failed to set service period timeout: %d", |
388 | ret); | 462 | ret); |
389 | return ret; | 463 | goto out; |
390 | } | 464 | } |
391 | 465 | ||
392 | return 0; | 466 | out: |
467 | kfree(rx_timeout); | ||
468 | return ret; | ||
393 | } | 469 | } |
394 | 470 | ||
395 | int wl12xx_acx_rts_threshold(struct wl12xx *wl, u16 rts_threshold) | 471 | int wl12xx_acx_rts_threshold(struct wl12xx *wl, u16 rts_threshold) |
396 | { | 472 | { |
397 | struct acx_rts_threshold rts; | 473 | struct acx_rts_threshold *rts; |
398 | int ret; | 474 | int ret; |
399 | 475 | ||
400 | wl12xx_debug(DEBUG_ACX, "acx rts threshold"); | 476 | wl12xx_debug(DEBUG_ACX, "acx rts threshold"); |
401 | 477 | ||
402 | rts.header.id = DOT11_RTS_THRESHOLD; | 478 | rts = kzalloc(sizeof(*rts), GFP_KERNEL); |
403 | rts.header.len = sizeof(rts) - sizeof(struct acx_header); | 479 | if (!rts) { |
480 | ret = -ENOMEM; | ||
481 | goto out; | ||
482 | } | ||
404 | 483 | ||
405 | rts.threshold = rts_threshold; | 484 | rts->threshold = rts_threshold; |
406 | 485 | ||
407 | ret = wl12xx_cmd_configure(wl, &rts, sizeof(rts)); | 486 | ret = wl12xx_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts)); |
408 | if (ret < 0) { | 487 | if (ret < 0) { |
409 | wl12xx_warning("failed to set rts threshold: %d", ret); | 488 | wl12xx_warning("failed to set rts threshold: %d", ret); |
410 | return ret; | 489 | goto out; |
411 | } | 490 | } |
412 | 491 | ||
413 | return 0; | 492 | out: |
493 | kfree(rts); | ||
494 | return ret; | ||
414 | } | 495 | } |
415 | 496 | ||
416 | int wl12xx_acx_beacon_filter_opt(struct wl12xx *wl) | 497 | int wl12xx_acx_beacon_filter_opt(struct wl12xx *wl) |
417 | { | 498 | { |
418 | struct acx_beacon_filter_option beacon_filter; | 499 | struct acx_beacon_filter_option *beacon_filter; |
419 | int ret; | 500 | int ret; |
420 | 501 | ||
421 | wl12xx_debug(DEBUG_ACX, "acx beacon filter opt"); | 502 | wl12xx_debug(DEBUG_ACX, "acx beacon filter opt"); |
422 | 503 | ||
423 | beacon_filter.header.id = ACX_BEACON_FILTER_OPT; | 504 | beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL); |
424 | beacon_filter.header.len = sizeof(beacon_filter) - | 505 | if (!beacon_filter) { |
425 | sizeof(struct acx_header); | 506 | ret = -ENOMEM; |
507 | goto out; | ||
508 | } | ||
426 | 509 | ||
427 | beacon_filter.enable = 0; | 510 | beacon_filter->enable = 0; |
428 | beacon_filter.max_num_beacons = 0; | 511 | beacon_filter->max_num_beacons = 0; |
429 | 512 | ||
430 | ret = wl12xx_cmd_configure(wl, &beacon_filter, sizeof(beacon_filter)); | 513 | ret = wl12xx_cmd_configure(wl, ACX_BEACON_FILTER_OPT, |
514 | beacon_filter, sizeof(*beacon_filter)); | ||
431 | if (ret < 0) { | 515 | if (ret < 0) { |
432 | wl12xx_warning("failed to set beacon filter opt: %d", ret); | 516 | wl12xx_warning("failed to set beacon filter opt: %d", ret); |
433 | return ret; | 517 | goto out; |
434 | } | 518 | } |
435 | 519 | ||
436 | return 0; | 520 | out: |
521 | kfree(beacon_filter); | ||
522 | return ret; | ||
437 | } | 523 | } |
438 | 524 | ||
439 | int wl12xx_acx_beacon_filter_table(struct wl12xx *wl) | 525 | int wl12xx_acx_beacon_filter_table(struct wl12xx *wl) |
440 | { | 526 | { |
441 | struct acx_beacon_filter_ie_table ie_table; | 527 | struct acx_beacon_filter_ie_table *ie_table; |
442 | int ret; | 528 | int ret; |
443 | 529 | ||
444 | wl12xx_debug(DEBUG_ACX, "acx beacon filter table"); | 530 | wl12xx_debug(DEBUG_ACX, "acx beacon filter table"); |
445 | 531 | ||
446 | ie_table.header.id = ACX_BEACON_FILTER_TABLE; | 532 | ie_table = kzalloc(sizeof(*ie_table), GFP_KERNEL); |
447 | ie_table.header.len = sizeof(ie_table) - sizeof(struct acx_header); | 533 | if (!ie_table) { |
534 | ret = -ENOMEM; | ||
535 | goto out; | ||
536 | } | ||
448 | 537 | ||
449 | ie_table.num_ie = 0; | 538 | ie_table->num_ie = 0; |
450 | memset(ie_table.table, 0, BEACON_FILTER_TABLE_MAX_SIZE); | 539 | memset(ie_table->table, 0, BEACON_FILTER_TABLE_MAX_SIZE); |
451 | 540 | ||
452 | ret = wl12xx_cmd_configure(wl, &ie_table, sizeof(ie_table)); | 541 | ret = wl12xx_cmd_configure(wl, ACX_BEACON_FILTER_TABLE, |
542 | ie_table, sizeof(*ie_table)); | ||
453 | if (ret < 0) { | 543 | if (ret < 0) { |
454 | wl12xx_warning("failed to set beacon filter table: %d", ret); | 544 | wl12xx_warning("failed to set beacon filter table: %d", ret); |
455 | return ret; | 545 | goto out; |
456 | } | 546 | } |
457 | 547 | ||
458 | return 0; | 548 | out: |
549 | kfree(ie_table); | ||
550 | return ret; | ||
459 | } | 551 | } |
460 | 552 | ||
461 | int wl12xx_acx_sg_enable(struct wl12xx *wl) | 553 | int wl12xx_acx_sg_enable(struct wl12xx *wl) |
462 | { | 554 | { |
463 | struct acx_bt_wlan_coex pta; | 555 | struct acx_bt_wlan_coex *pta; |
464 | int ret; | 556 | int ret; |
465 | 557 | ||
466 | wl12xx_debug(DEBUG_ACX, "acx sg enable"); | 558 | wl12xx_debug(DEBUG_ACX, "acx sg enable"); |
467 | 559 | ||
468 | pta.header.id = ACX_SG_ENABLE; | 560 | pta = kzalloc(sizeof(*pta), GFP_KERNEL); |
469 | pta.header.len = sizeof(pta) - sizeof(struct acx_header); | 561 | if (!pta) { |
562 | ret = -ENOMEM; | ||
563 | goto out; | ||
564 | } | ||
470 | 565 | ||
471 | pta.enable = SG_ENABLE; | 566 | pta->enable = SG_ENABLE; |
472 | 567 | ||
473 | ret = wl12xx_cmd_configure(wl, &pta, sizeof(pta)); | 568 | ret = wl12xx_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta)); |
474 | if (ret < 0) { | 569 | if (ret < 0) { |
475 | wl12xx_warning("failed to set softgemini enable: %d", ret); | 570 | wl12xx_warning("failed to set softgemini enable: %d", ret); |
476 | return ret; | 571 | goto out; |
477 | } | 572 | } |
478 | 573 | ||
479 | return 0; | 574 | out: |
575 | kfree(pta); | ||
576 | return ret; | ||
480 | } | 577 | } |
481 | 578 | ||
482 | int wl12xx_acx_sg_cfg(struct wl12xx *wl) | 579 | int wl12xx_acx_sg_cfg(struct wl12xx *wl) |
483 | { | 580 | { |
484 | struct acx_bt_wlan_coex_param param; | 581 | struct acx_bt_wlan_coex_param *param; |
485 | int ret; | 582 | int ret; |
486 | 583 | ||
487 | wl12xx_debug(DEBUG_ACX, "acx sg cfg"); | 584 | wl12xx_debug(DEBUG_ACX, "acx sg cfg"); |
488 | 585 | ||
586 | param = kzalloc(sizeof(*param), GFP_KERNEL); | ||
587 | if (!param) { | ||
588 | ret = -ENOMEM; | ||
589 | goto out; | ||
590 | } | ||
591 | |||
489 | /* BT-WLAN coext parameters */ | 592 | /* BT-WLAN coext parameters */ |
490 | param.header.id = ACX_SG_CFG; | 593 | param->min_rate = RATE_INDEX_24MBPS; |
491 | param.header.len = sizeof(param) - sizeof(struct acx_header); | 594 | param->bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF; |
492 | 595 | param->wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF; | |
493 | param.min_rate = RATE_INDEX_24MBPS; | 596 | param->sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF; |
494 | param.bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF; | 597 | param->rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF; |
495 | param.wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF; | 598 | param->tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF; |
496 | param.sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF; | 599 | param->rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF; |
497 | param.rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF; | 600 | param->tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF; |
498 | param.tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF; | 601 | param->wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF; |
499 | param.rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF; | 602 | param->bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF; |
500 | param.tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF; | 603 | param->next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF; |
501 | param.wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF; | 604 | param->wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF; |
502 | param.bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF; | 605 | param->hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF; |
503 | param.next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF; | 606 | param->next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF; |
504 | param.wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF; | 607 | param->antenna_type = PTA_ANTENNA_TYPE_DEF; |
505 | param.hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF; | 608 | param->signal_type = PTA_SIGNALING_TYPE_DEF; |
506 | param.next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF; | 609 | param->afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF; |
507 | param.antenna_type = PTA_ANTENNA_TYPE_DEF; | 610 | param->quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF; |
508 | param.signal_type = PTA_SIGNALING_TYPE_DEF; | 611 | param->max_cts = PTA_MAX_NUM_CTS_DEF; |
509 | param.afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF; | 612 | param->wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF; |
510 | param.quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF; | 613 | param->bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF; |
511 | param.max_cts = PTA_MAX_NUM_CTS_DEF; | 614 | param->missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF; |
512 | param.wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF; | 615 | param->wlan_elp_hp = PTA_ELP_HP_DEF; |
513 | param.bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF; | 616 | param->bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF; |
514 | param.missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF; | 617 | param->ack_mode_dual_ant = PTA_ACK_MODE_DEF; |
515 | param.wlan_elp_hp = PTA_ELP_HP_DEF; | 618 | param->pa_sd_enable = PTA_ALLOW_PA_SD_DEF; |
516 | param.bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF; | 619 | param->pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF; |
517 | param.ack_mode_dual_ant = PTA_ACK_MODE_DEF; | 620 | param->bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF; |
518 | param.pa_sd_enable = PTA_ALLOW_PA_SD_DEF; | 621 | |
519 | param.pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF; | 622 | ret = wl12xx_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); |
520 | param.bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF; | ||
521 | |||
522 | ret = wl12xx_cmd_configure(wl, ¶m, sizeof(param)); | ||
523 | if (ret < 0) { | 623 | if (ret < 0) { |
524 | wl12xx_warning("failed to set sg config: %d", ret); | 624 | wl12xx_warning("failed to set sg config: %d", ret); |
525 | return ret; | 625 | goto out; |
526 | } | 626 | } |
527 | 627 | ||
528 | return 0; | 628 | out: |
629 | kfree(param); | ||
630 | return ret; | ||
529 | } | 631 | } |
530 | 632 | ||
531 | int wl12xx_acx_cca_threshold(struct wl12xx *wl) | 633 | int wl12xx_acx_cca_threshold(struct wl12xx *wl) |
532 | { | 634 | { |
533 | struct acx_energy_detection detection; | 635 | struct acx_energy_detection *detection; |
534 | int ret; | 636 | int ret; |
535 | 637 | ||
536 | wl12xx_debug(DEBUG_ACX, "acx cca threshold"); | 638 | wl12xx_debug(DEBUG_ACX, "acx cca threshold"); |
537 | 639 | ||
538 | detection.header.id = ACX_CCA_THRESHOLD; | 640 | detection = kzalloc(sizeof(*detection), GFP_KERNEL); |
539 | detection.header.len = sizeof(detection) - sizeof(struct acx_header); | 641 | if (!detection) { |
642 | ret = -ENOMEM; | ||
643 | goto out; | ||
644 | } | ||
540 | 645 | ||
541 | detection.rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D; | 646 | detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D; |
542 | detection.tx_energy_detection = 0; | 647 | detection->tx_energy_detection = 0; |
543 | 648 | ||
544 | ret = wl12xx_cmd_configure(wl, &detection, sizeof(detection)); | 649 | ret = wl12xx_cmd_configure(wl, ACX_CCA_THRESHOLD, |
650 | detection, sizeof(*detection)); | ||
545 | if (ret < 0) { | 651 | if (ret < 0) { |
546 | wl12xx_warning("failed to set cca threshold: %d", ret); | 652 | wl12xx_warning("failed to set cca threshold: %d", ret); |
547 | return ret; | 653 | return ret; |
548 | } | 654 | } |
549 | 655 | ||
550 | return 0; | 656 | out: |
657 | kfree(detection); | ||
658 | return ret; | ||
551 | } | 659 | } |
552 | 660 | ||
553 | int wl12xx_acx_bcn_dtim_options(struct wl12xx *wl) | 661 | int wl12xx_acx_bcn_dtim_options(struct wl12xx *wl) |
554 | { | 662 | { |
555 | struct acx_beacon_broadcast bb; | 663 | struct acx_beacon_broadcast *bb; |
556 | int ret; | 664 | int ret; |
557 | 665 | ||
558 | wl12xx_debug(DEBUG_ACX, "acx bcn dtim options"); | 666 | wl12xx_debug(DEBUG_ACX, "acx bcn dtim options"); |
559 | 667 | ||
560 | bb.header.id = ACX_BCN_DTIM_OPTIONS; | 668 | bb = kzalloc(sizeof(*bb), GFP_KERNEL); |
561 | bb.header.len = sizeof(bb) - sizeof(struct acx_header); | 669 | if (!bb) { |
670 | ret = -ENOMEM; | ||
671 | goto out; | ||
672 | } | ||
562 | 673 | ||
563 | bb.beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE; | 674 | bb->beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE; |
564 | bb.broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE; | 675 | bb->broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE; |
565 | bb.rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE; | 676 | bb->rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE; |
566 | bb.ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF; | 677 | bb->ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF; |
567 | 678 | ||
568 | ret = wl12xx_cmd_configure(wl, &bb, sizeof(bb)); | 679 | ret = wl12xx_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb)); |
569 | if (ret < 0) { | 680 | if (ret < 0) { |
570 | wl12xx_warning("failed to set rx config: %d", ret); | 681 | wl12xx_warning("failed to set rx config: %d", ret); |
571 | return ret; | 682 | goto out; |
572 | } | 683 | } |
573 | 684 | ||
574 | return 0; | 685 | out: |
686 | kfree(bb); | ||
687 | return ret; | ||
575 | } | 688 | } |
576 | 689 | ||
577 | int wl12xx_acx_aid(struct wl12xx *wl, u16 aid) | 690 | int wl12xx_acx_aid(struct wl12xx *wl, u16 aid) |
578 | { | 691 | { |
579 | struct acx_aid acx_aid; | 692 | struct acx_aid *acx_aid; |
580 | int ret; | 693 | int ret; |
581 | 694 | ||
582 | wl12xx_debug(DEBUG_ACX, "acx aid"); | 695 | wl12xx_debug(DEBUG_ACX, "acx aid"); |
583 | 696 | ||
584 | acx_aid.header.id = ACX_AID; | 697 | acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL); |
585 | acx_aid.header.len = sizeof(acx_aid) - sizeof(struct acx_header); | 698 | if (!acx_aid) { |
699 | ret = -ENOMEM; | ||
700 | goto out; | ||
701 | } | ||
586 | 702 | ||
587 | acx_aid.aid = aid; | 703 | acx_aid->aid = aid; |
588 | 704 | ||
589 | ret = wl12xx_cmd_configure(wl, &acx_aid, sizeof(acx_aid)); | 705 | ret = wl12xx_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid)); |
590 | if (ret < 0) { | 706 | if (ret < 0) { |
591 | wl12xx_warning("failed to set aid: %d", ret); | 707 | wl12xx_warning("failed to set aid: %d", ret); |
592 | return ret; | 708 | goto out; |
593 | } | 709 | } |
594 | 710 | ||
595 | return 0; | 711 | out: |
712 | kfree(acx_aid); | ||
713 | return ret; | ||
596 | } | 714 | } |
597 | 715 | ||
598 | int wl12xx_acx_event_mbox_mask(struct wl12xx *wl, u32 event_mask) | 716 | int wl12xx_acx_event_mbox_mask(struct wl12xx *wl, u32 event_mask) |
599 | { | 717 | { |
600 | struct acx_event_mask mask; | 718 | struct acx_event_mask *mask; |
601 | int ret; | 719 | int ret; |
602 | 720 | ||
603 | wl12xx_debug(DEBUG_ACX, "acx event mbox mask"); | 721 | wl12xx_debug(DEBUG_ACX, "acx event mbox mask"); |
604 | 722 | ||
605 | mask.header.id = ACX_EVENT_MBOX_MASK; | 723 | mask = kzalloc(sizeof(*mask), GFP_KERNEL); |
606 | mask.header.len = sizeof(mask) - sizeof(struct acx_header); | 724 | if (!mask) { |
725 | ret = -ENOMEM; | ||
726 | goto out; | ||
727 | } | ||
607 | 728 | ||
608 | /* high event mask is unused */ | 729 | /* high event mask is unused */ |
609 | mask.high_event_mask = 0xffffffff; | 730 | mask->high_event_mask = 0xffffffff; |
610 | 731 | ||
611 | mask.event_mask = event_mask; | 732 | mask->event_mask = event_mask; |
612 | 733 | ||
613 | ret = wl12xx_cmd_configure(wl, &mask, sizeof(mask)); | 734 | ret = wl12xx_cmd_configure(wl, ACX_EVENT_MBOX_MASK, |
735 | mask, sizeof(*mask)); | ||
614 | if (ret < 0) { | 736 | if (ret < 0) { |
615 | wl12xx_warning("failed to set aid: %d", ret); | 737 | wl12xx_warning("failed to set aid: %d", ret); |
616 | return ret; | 738 | goto out; |
617 | } | 739 | } |
618 | 740 | ||
619 | return 0; | 741 | out: |
742 | kfree(mask); | ||
743 | return ret; | ||
620 | } | 744 | } |
621 | 745 | ||
622 | int wl12xx_acx_set_preamble(struct wl12xx *wl, enum acx_preamble_type preamble) | 746 | int wl12xx_acx_set_preamble(struct wl12xx *wl, enum acx_preamble_type preamble) |
623 | { | 747 | { |
624 | struct acx_preamble ie; | 748 | struct acx_preamble *acx; |
625 | int ret; | 749 | int ret; |
626 | 750 | ||
627 | wl12xx_debug(DEBUG_ACX, "acx_set_preamble"); | 751 | wl12xx_debug(DEBUG_ACX, "acx_set_preamble"); |
628 | 752 | ||
629 | memset(&ie, 0, sizeof(ie)); | 753 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
754 | if (!acx) { | ||
755 | ret = -ENOMEM; | ||
756 | goto out; | ||
757 | } | ||
630 | 758 | ||
631 | ie.header.id = ACX_PREAMBLE_TYPE; | 759 | acx->preamble = preamble; |
632 | ie.header.len = sizeof(ie) - sizeof(struct acx_header); | 760 | |
633 | ie.preamble = preamble; | 761 | ret = wl12xx_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx)); |
634 | ret = wl12xx_cmd_configure(wl, &ie, sizeof(ie)); | ||
635 | if (ret < 0) { | 762 | if (ret < 0) { |
636 | wl12xx_warning("Setting of preamble failed: %d", ret); | 763 | wl12xx_warning("Setting of preamble failed: %d", ret); |
637 | return ret; | 764 | goto out; |
638 | } | 765 | } |
639 | return 0; | 766 | |
767 | out: | ||
768 | kfree(acx); | ||
769 | return ret; | ||
640 | } | 770 | } |
641 | 771 | ||
642 | int wl12xx_acx_cts_protect(struct wl12xx *wl, | 772 | int wl12xx_acx_cts_protect(struct wl12xx *wl, |
643 | enum acx_ctsprotect_type ctsprotect) | 773 | enum acx_ctsprotect_type ctsprotect) |
644 | { | 774 | { |
645 | struct acx_ctsprotect ie; | 775 | struct acx_ctsprotect *acx; |
646 | int ret; | 776 | int ret; |
647 | 777 | ||
648 | wl12xx_debug(DEBUG_ACX, "acx_set_ctsprotect"); | 778 | wl12xx_debug(DEBUG_ACX, "acx_set_ctsprotect"); |
649 | 779 | ||
650 | memset(&ie, 0, sizeof(ie)); | 780 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
781 | if (!acx) { | ||
782 | ret = -ENOMEM; | ||
783 | goto out; | ||
784 | } | ||
785 | |||
786 | acx->ctsprotect = ctsprotect; | ||
651 | 787 | ||
652 | ie.header.id = ACX_CTS_PROTECTION; | 788 | ret = wl12xx_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx)); |
653 | ie.header.len = sizeof(ie) - sizeof(struct acx_header); | ||
654 | ie.ctsprotect = ctsprotect; | ||
655 | ret = wl12xx_cmd_configure(wl, &ie, sizeof(ie)); | ||
656 | if (ret < 0) { | 789 | if (ret < 0) { |
657 | wl12xx_warning("Setting of ctsprotect failed: %d", ret); | 790 | wl12xx_warning("Setting of ctsprotect failed: %d", ret); |
658 | return ret; | 791 | goto out; |
659 | } | 792 | } |
660 | return 0; | 793 | |
794 | out: | ||
795 | kfree(acx); | ||
796 | return ret; | ||
661 | } | 797 | } |
662 | 798 | ||
663 | int wl12xx_acx_statistics(struct wl12xx *wl, struct acx_statistics *stats) | 799 | int wl12xx_acx_tsf_info(struct wl12xx *wl, u64 *mactime) |
664 | { | 800 | { |
665 | struct wl12xx_command *answer; | 801 | struct acx_tsf_info *tsf_info; |
666 | int ret; | 802 | int ret; |
667 | 803 | ||
668 | wl12xx_debug(DEBUG_ACX, "acx statistics"); | 804 | tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL); |
669 | 805 | if (!tsf_info) { | |
670 | answer = kmalloc(sizeof(*answer), GFP_KERNEL); | ||
671 | if (!answer) { | ||
672 | wl12xx_warning("could not allocate memory for acx statistics"); | ||
673 | ret = -ENOMEM; | 806 | ret = -ENOMEM; |
674 | goto out; | 807 | goto out; |
675 | } | 808 | } |
676 | 809 | ||
677 | ret = wl12xx_cmd_interrogate(wl, ACX_STATISTICS, sizeof(*answer), | 810 | ret = wl12xx_cmd_interrogate(wl, ACX_TSF_INFO, |
678 | answer); | 811 | tsf_info, sizeof(*tsf_info)); |
679 | if (ret < 0) { | 812 | if (ret < 0) { |
680 | wl12xx_warning("acx statistics failed: %d", ret); | 813 | wl12xx_warning("ACX_FW_REV interrogate failed"); |
681 | goto out; | 814 | goto out; |
682 | } | 815 | } |
683 | 816 | ||
684 | memcpy(stats, answer->parameters, sizeof(*stats)); | 817 | *mactime = tsf_info->current_tsf_lsb | |
818 | (tsf_info->current_tsf_msb << 31); | ||
685 | 819 | ||
686 | out: | 820 | out: |
687 | kfree(answer); | 821 | kfree(tsf_info); |
688 | return ret; | 822 | return ret; |
689 | } | 823 | } |
824 | |||
825 | int wl12xx_acx_statistics(struct wl12xx *wl, struct acx_statistics *stats) | ||
826 | { | ||
827 | int ret; | ||
828 | |||
829 | wl12xx_debug(DEBUG_ACX, "acx statistics"); | ||
830 | |||
831 | ret = wl12xx_cmd_interrogate(wl, ACX_STATISTICS, stats, | ||
832 | sizeof(*stats)); | ||
833 | if (ret < 0) { | ||
834 | wl12xx_warning("acx statistics failed: %d", ret); | ||
835 | return -ENOMEM; | ||
836 | } | ||
837 | |||
838 | return 0; | ||
839 | } | ||
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index fb2d2340993c..549e537d2e6e 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h | |||
@@ -26,10 +26,16 @@ | |||
26 | #define __WL12XX_ACX_H__ | 26 | #define __WL12XX_ACX_H__ |
27 | 27 | ||
28 | #include "wl12xx.h" | 28 | #include "wl12xx.h" |
29 | #include "cmd.h" | ||
29 | 30 | ||
30 | /* Target's information element */ | 31 | /* Target's information element */ |
31 | struct acx_header { | 32 | struct acx_header { |
33 | struct wl12xx_cmd_header cmd; | ||
34 | |||
35 | /* acx (or information element) header */ | ||
32 | u16 id; | 36 | u16 id; |
37 | |||
38 | /* payload length (not including headers */ | ||
33 | u16 len; | 39 | u16 len; |
34 | }; | 40 | }; |
35 | 41 | ||
@@ -107,25 +113,6 @@ struct acx_sleep_auth { | |||
107 | u8 padding[3]; | 113 | u8 padding[3]; |
108 | } __attribute__ ((packed)); | 114 | } __attribute__ ((packed)); |
109 | 115 | ||
110 | #define TIM_ELE_ID 5 | ||
111 | #define PARTIAL_VBM_MAX 251 | ||
112 | |||
113 | struct tim { | ||
114 | u8 identity; | ||
115 | u8 length; | ||
116 | u8 dtim_count; | ||
117 | u8 dtim_period; | ||
118 | u8 bitmap_ctrl; | ||
119 | u8 pvb_field[PARTIAL_VBM_MAX]; /* Partial Virtual Bitmap */ | ||
120 | } __attribute__ ((packed)); | ||
121 | |||
122 | /* Virtual Bit Map update */ | ||
123 | struct vbm_update_request { | ||
124 | __le16 len; | ||
125 | u8 padding[2]; | ||
126 | struct tim tim; | ||
127 | } __attribute__ ((packed)); | ||
128 | |||
129 | enum { | 116 | enum { |
130 | HOSTIF_PCI_MASTER_HOST_INDIRECT, | 117 | HOSTIF_PCI_MASTER_HOST_INDIRECT, |
131 | HOSTIF_PCI_MASTER_HOST_DIRECT, | 118 | HOSTIF_PCI_MASTER_HOST_DIRECT, |
@@ -202,7 +189,7 @@ struct acx_data_path_params_resp { | |||
202 | #define RX_MSDU_LIFETIME_MAX 0xFFFFFFFF | 189 | #define RX_MSDU_LIFETIME_MAX 0xFFFFFFFF |
203 | #define RX_MSDU_LIFETIME_DEF 512000 | 190 | #define RX_MSDU_LIFETIME_DEF 512000 |
204 | 191 | ||
205 | struct rx_msdu_lifetime { | 192 | struct acx_rx_msdu_lifetime { |
206 | struct acx_header header; | 193 | struct acx_header header; |
207 | 194 | ||
208 | /* | 195 | /* |
@@ -368,7 +355,7 @@ struct acx_slot { | |||
368 | #define ADDRESS_GROUP_MAX (8) | 355 | #define ADDRESS_GROUP_MAX (8) |
369 | #define ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ADDRESS_GROUP_MAX) | 356 | #define ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ADDRESS_GROUP_MAX) |
370 | 357 | ||
371 | struct multicast_grp_addr_start { | 358 | struct acx_dot11_grp_addr_tbl { |
372 | struct acx_header header; | 359 | struct acx_header header; |
373 | 360 | ||
374 | u8 enabled; | 361 | u8 enabled; |
@@ -730,22 +717,13 @@ struct acx_fw_gen_frame_rates { | |||
730 | } __attribute__ ((packed)); | 717 | } __attribute__ ((packed)); |
731 | 718 | ||
732 | /* STA MAC */ | 719 | /* STA MAC */ |
733 | struct dot11_station_id { | 720 | struct acx_dot11_station_id { |
734 | struct acx_header header; | 721 | struct acx_header header; |
735 | 722 | ||
736 | u8 mac[ETH_ALEN]; | 723 | u8 mac[ETH_ALEN]; |
737 | u8 pad[2]; | 724 | u8 pad[2]; |
738 | } __attribute__ ((packed)); | 725 | } __attribute__ ((packed)); |
739 | 726 | ||
740 | /* HW encryption keys */ | ||
741 | #define NUM_ACCESS_CATEGORIES_COPY 4 | ||
742 | #define MAX_KEY_SIZE 32 | ||
743 | |||
744 | /* When set, disable HW encryption */ | ||
745 | #define DF_ENCRYPTION_DISABLE 0x01 | ||
746 | /* When set, disable HW decryption */ | ||
747 | #define DF_SNIFF_MODE_ENABLE 0x80 | ||
748 | |||
749 | struct acx_feature_config { | 727 | struct acx_feature_config { |
750 | struct acx_header header; | 728 | struct acx_header header; |
751 | 729 | ||
@@ -753,67 +731,6 @@ struct acx_feature_config { | |||
753 | u32 data_flow_options; | 731 | u32 data_flow_options; |
754 | } __attribute__ ((packed)); | 732 | } __attribute__ ((packed)); |
755 | 733 | ||
756 | enum acx_key_action { | ||
757 | KEY_ADD_OR_REPLACE = 1, | ||
758 | KEY_REMOVE = 2, | ||
759 | KEY_SET_ID = 3, | ||
760 | MAX_KEY_ACTION = 0xffff, | ||
761 | }; | ||
762 | |||
763 | enum acx_key_type { | ||
764 | KEY_WEP_DEFAULT = 0, | ||
765 | KEY_WEP_ADDR = 1, | ||
766 | KEY_AES_GROUP = 4, | ||
767 | KEY_AES_PAIRWISE = 5, | ||
768 | KEY_WEP_GROUP = 6, | ||
769 | KEY_TKIP_MIC_GROUP = 10, | ||
770 | KEY_TKIP_MIC_PAIRWISE = 11, | ||
771 | }; | ||
772 | |||
773 | /* | ||
774 | * | ||
775 | * key_type_e key size key format | ||
776 | * ---------- --------- ---------- | ||
777 | * 0x00 5, 13, 29 Key data | ||
778 | * 0x01 5, 13, 29 Key data | ||
779 | * 0x04 16 16 bytes of key data | ||
780 | * 0x05 16 16 bytes of key data | ||
781 | * 0x0a 32 16 bytes of TKIP key data | ||
782 | * 8 bytes of RX MIC key data | ||
783 | * 8 bytes of TX MIC key data | ||
784 | * 0x0b 32 16 bytes of TKIP key data | ||
785 | * 8 bytes of RX MIC key data | ||
786 | * 8 bytes of TX MIC key data | ||
787 | * | ||
788 | */ | ||
789 | |||
790 | struct acx_set_key { | ||
791 | /* Ignored for default WEP key */ | ||
792 | u8 addr[ETH_ALEN]; | ||
793 | |||
794 | /* key_action_e */ | ||
795 | u16 key_action; | ||
796 | |||
797 | u16 reserved_1; | ||
798 | |||
799 | /* key size in bytes */ | ||
800 | u8 key_size; | ||
801 | |||
802 | /* key_type_e */ | ||
803 | u8 key_type; | ||
804 | u8 ssid_profile; | ||
805 | |||
806 | /* | ||
807 | * TKIP, AES: frame's key id field. | ||
808 | * For WEP default key: key id; | ||
809 | */ | ||
810 | u8 id; | ||
811 | u8 reserved_2[6]; | ||
812 | u8 key[MAX_KEY_SIZE]; | ||
813 | u16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY]; | ||
814 | u32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY]; | ||
815 | } __attribute__ ((packed)); | ||
816 | |||
817 | struct acx_current_tx_power { | 734 | struct acx_current_tx_power { |
818 | struct acx_header header; | 735 | struct acx_header header; |
819 | 736 | ||
@@ -839,26 +756,6 @@ struct acx_tsf_info { | |||
839 | u8 pad[3]; | 756 | u8 pad[3]; |
840 | } __attribute__ ((packed)); | 757 | } __attribute__ ((packed)); |
841 | 758 | ||
842 | /* 802.11 PS */ | ||
843 | enum acx_ps_mode { | ||
844 | STATION_ACTIVE_MODE, | ||
845 | STATION_POWER_SAVE_MODE | ||
846 | }; | ||
847 | |||
848 | struct acx_ps_params { | ||
849 | u8 ps_mode; /* STATION_* */ | ||
850 | u8 send_null_data; /* Do we have to send NULL data packet ? */ | ||
851 | u8 retries; /* Number of retires for the initial NULL data packet */ | ||
852 | |||
853 | /* | ||
854 | * TUs during which the target stays awake after switching | ||
855 | * to power save mode. | ||
856 | */ | ||
857 | u8 hang_over_period; | ||
858 | u16 null_data_rate; | ||
859 | u8 pad[2]; | ||
860 | } __attribute__ ((packed)); | ||
861 | |||
862 | enum acx_wake_up_event { | 759 | enum acx_wake_up_event { |
863 | WAKE_UP_EVENT_BEACON_BITMAP = 0x01, /* Wake on every Beacon*/ | 760 | WAKE_UP_EVENT_BEACON_BITMAP = 0x01, /* Wake on every Beacon*/ |
864 | WAKE_UP_EVENT_DTIM_BITMAP = 0x02, /* Wake on every DTIM*/ | 761 | WAKE_UP_EVENT_DTIM_BITMAP = 0x02, /* Wake on every DTIM*/ |
@@ -892,6 +789,7 @@ enum acx_preamble_type { | |||
892 | 789 | ||
893 | struct acx_preamble { | 790 | struct acx_preamble { |
894 | struct acx_header header; | 791 | struct acx_header header; |
792 | |||
895 | /* | 793 | /* |
896 | * When set, the WiLink transmits the frames with a short preamble and | 794 | * When set, the WiLink transmits the frames with a short preamble and |
897 | * when cleared, the WiLink transmits the frames with a long preamble. | 795 | * when cleared, the WiLink transmits the frames with a long preamble. |
@@ -1219,7 +1117,8 @@ int wl12xx_acx_sleep_auth(struct wl12xx *wl, u8 sleep_auth); | |||
1219 | int wl12xx_acx_fw_version(struct wl12xx *wl, char *buf, size_t len); | 1117 | int wl12xx_acx_fw_version(struct wl12xx *wl, char *buf, size_t len); |
1220 | int wl12xx_acx_tx_power(struct wl12xx *wl, int power); | 1118 | int wl12xx_acx_tx_power(struct wl12xx *wl, int power); |
1221 | int wl12xx_acx_feature_cfg(struct wl12xx *wl); | 1119 | int wl12xx_acx_feature_cfg(struct wl12xx *wl); |
1222 | int wl12xx_acx_mem_map(struct wl12xx *wl, void *mem_map, size_t len); | 1120 | int wl12xx_acx_mem_map(struct wl12xx *wl, |
1121 | struct acx_header *mem_map, size_t len); | ||
1223 | int wl12xx_acx_data_path_params(struct wl12xx *wl, | 1122 | int wl12xx_acx_data_path_params(struct wl12xx *wl, |
1224 | struct acx_data_path_params_resp *data_path); | 1123 | struct acx_data_path_params_resp *data_path); |
1225 | int wl12xx_acx_rx_msdu_life_time(struct wl12xx *wl, u32 life_time); | 1124 | int wl12xx_acx_rx_msdu_life_time(struct wl12xx *wl, u32 life_time); |
@@ -1241,5 +1140,6 @@ int wl12xx_acx_set_preamble(struct wl12xx *wl, enum acx_preamble_type preamble); | |||
1241 | int wl12xx_acx_cts_protect(struct wl12xx *wl, | 1140 | int wl12xx_acx_cts_protect(struct wl12xx *wl, |
1242 | enum acx_ctsprotect_type ctsprotect); | 1141 | enum acx_ctsprotect_type ctsprotect); |
1243 | int wl12xx_acx_statistics(struct wl12xx *wl, struct acx_statistics *stats); | 1142 | int wl12xx_acx_statistics(struct wl12xx *wl, struct acx_statistics *stats); |
1143 | int wl12xx_acx_tsf_info(struct wl12xx *wl, u64 *mactime); | ||
1244 | 1144 | ||
1245 | #endif /* __WL12XX_ACX_H__ */ | 1145 | #endif /* __WL12XX_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index f73ab602b7ae..0a02cdde935b 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c | |||
@@ -9,24 +9,32 @@ | |||
9 | #include "reg.h" | 9 | #include "reg.h" |
10 | #include "spi.h" | 10 | #include "spi.h" |
11 | #include "ps.h" | 11 | #include "ps.h" |
12 | 12 | #include "acx.h" | |
13 | int wl12xx_cmd_send(struct wl12xx *wl, u16 type, void *buf, size_t buf_len) | 13 | |
14 | /** | ||
15 | * send command to firmware | ||
16 | * | ||
17 | * @wl: wl struct | ||
18 | * @id: command id | ||
19 | * @buf: buffer containing the command, must work with dma | ||
20 | * @len: length of the buffer | ||
21 | */ | ||
22 | int wl12xx_cmd_send(struct wl12xx *wl, u16 id, void *buf, size_t len) | ||
14 | { | 23 | { |
15 | struct wl12xx_command cmd; | 24 | struct wl12xx_cmd_header *cmd; |
16 | unsigned long timeout; | 25 | unsigned long timeout; |
17 | size_t cmd_len; | ||
18 | u32 intr; | 26 | u32 intr; |
19 | int ret = 0; | 27 | int ret = 0; |
20 | 28 | ||
21 | memset(&cmd, 0, sizeof(cmd)); | 29 | cmd = buf; |
22 | cmd.id = type; | 30 | cmd->id = id; |
23 | cmd.status = 0; | 31 | cmd->status = 0; |
24 | memcpy(cmd.parameters, buf, buf_len); | 32 | |
25 | cmd_len = ALIGN(buf_len, 4) + CMDMBOX_HEADER_LEN; | 33 | WARN_ON(len % 4 != 0); |
26 | 34 | ||
27 | wl12xx_ps_elp_wakeup(wl); | 35 | wl12xx_ps_elp_wakeup(wl); |
28 | 36 | ||
29 | wl12xx_spi_mem_write(wl, wl->cmd_box_addr, &cmd, cmd_len); | 37 | wl12xx_spi_mem_write(wl, wl->cmd_box_addr, buf, len); |
30 | 38 | ||
31 | wl12xx_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); | 39 | wl12xx_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); |
32 | 40 | ||
@@ -54,21 +62,42 @@ out: | |||
54 | return ret; | 62 | return ret; |
55 | } | 63 | } |
56 | 64 | ||
65 | /** | ||
66 | * send test command to firmware | ||
67 | * | ||
68 | * @wl: wl struct | ||
69 | * @buf: buffer containing the command, without headers, no dma requirements | ||
70 | * @len: length of the buffer | ||
71 | * @answer: is answer needed | ||
72 | * | ||
73 | * FIXME: cmd_test users need to be converted to the new interface | ||
74 | */ | ||
57 | int wl12xx_cmd_test(struct wl12xx *wl, void *buf, size_t buf_len, u8 answer) | 75 | int wl12xx_cmd_test(struct wl12xx *wl, void *buf, size_t buf_len, u8 answer) |
58 | { | 76 | { |
77 | struct wl12xx_command *cmd; | ||
78 | size_t cmd_len; | ||
59 | int ret; | 79 | int ret; |
60 | 80 | ||
61 | wl12xx_debug(DEBUG_CMD, "cmd test"); | 81 | wl12xx_debug(DEBUG_CMD, "cmd test"); |
62 | 82 | ||
63 | ret = wl12xx_cmd_send(wl, CMD_TEST, buf, buf_len); | 83 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
84 | if (!cmd) { | ||
85 | ret = -ENOMEM; | ||
86 | goto out; | ||
87 | } | ||
88 | |||
89 | memcpy(cmd->parameters, buf, buf_len); | ||
90 | |||
91 | /* FIXME: ugly */ | ||
92 | cmd_len = sizeof(struct wl12xx_cmd_header) + buf_len; | ||
93 | |||
94 | ret = wl12xx_cmd_send(wl, CMD_TEST, cmd, cmd_len); | ||
64 | if (ret < 0) { | 95 | if (ret < 0) { |
65 | wl12xx_warning("TEST command failed"); | 96 | wl12xx_warning("TEST command failed"); |
66 | return ret; | 97 | goto out; |
67 | } | 98 | } |
68 | 99 | ||
69 | if (answer) { | 100 | if (answer) { |
70 | struct wl12xx_command *cmd_answer; | ||
71 | |||
72 | /* | 101 | /* |
73 | * The test command got in, we can read the answer. | 102 | * The test command got in, we can read the answer. |
74 | * The answer would be a wl12xx_command, where the | 103 | * The answer would be a wl12xx_command, where the |
@@ -77,109 +106,146 @@ int wl12xx_cmd_test(struct wl12xx *wl, void *buf, size_t buf_len, u8 answer) | |||
77 | 106 | ||
78 | wl12xx_ps_elp_wakeup(wl); | 107 | wl12xx_ps_elp_wakeup(wl); |
79 | 108 | ||
80 | wl12xx_spi_mem_read(wl, wl->cmd_box_addr, buf, buf_len); | 109 | wl12xx_spi_mem_read(wl, wl->cmd_box_addr, cmd, cmd_len); |
81 | 110 | ||
82 | wl12xx_ps_elp_sleep(wl); | 111 | wl12xx_ps_elp_sleep(wl); |
83 | 112 | ||
84 | cmd_answer = buf; | 113 | if (cmd->header.status != CMD_STATUS_SUCCESS) |
85 | if (cmd_answer->status != CMD_STATUS_SUCCESS) | ||
86 | wl12xx_error("TEST command answer error: %d", | 114 | wl12xx_error("TEST command answer error: %d", |
87 | cmd_answer->status); | 115 | cmd->header.status); |
116 | memcpy(buf, cmd->parameters, buf_len); | ||
88 | } | 117 | } |
89 | 118 | ||
90 | return 0; | 119 | out: |
120 | kfree(cmd); | ||
121 | return ret; | ||
91 | } | 122 | } |
92 | 123 | ||
93 | 124 | /** | |
94 | int wl12xx_cmd_interrogate(struct wl12xx *wl, u16 ie_id, u16 ie_len, | 125 | * read acx from firmware |
95 | void *answer) | 126 | * |
127 | * @wl: wl struct | ||
128 | * @id: acx id | ||
129 | * @buf: buffer for the response, including all headers, must work with dma | ||
130 | * @len: lenght of buf | ||
131 | */ | ||
132 | int wl12xx_cmd_interrogate(struct wl12xx *wl, u16 id, void *buf, size_t len) | ||
96 | { | 133 | { |
97 | struct wl12xx_command *cmd; | 134 | struct acx_header *acx = buf; |
98 | struct acx_header header; | ||
99 | int ret; | 135 | int ret; |
100 | 136 | ||
101 | wl12xx_debug(DEBUG_CMD, "cmd interrogate"); | 137 | wl12xx_debug(DEBUG_CMD, "cmd interrogate"); |
102 | 138 | ||
103 | header.id = ie_id; | 139 | acx->id = id; |
104 | header.len = ie_len - sizeof(header); | ||
105 | 140 | ||
106 | ret = wl12xx_cmd_send(wl, CMD_INTERROGATE, &header, sizeof(header)); | 141 | /* payload length, does not include any headers */ |
142 | acx->len = len - sizeof(*acx); | ||
143 | |||
144 | ret = wl12xx_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx)); | ||
107 | if (ret < 0) { | 145 | if (ret < 0) { |
108 | wl12xx_error("INTERROGATE command failed"); | 146 | wl12xx_error("INTERROGATE command failed"); |
109 | return ret; | 147 | goto out; |
110 | } | 148 | } |
111 | 149 | ||
112 | wl12xx_ps_elp_wakeup(wl); | 150 | wl12xx_ps_elp_wakeup(wl); |
113 | 151 | ||
114 | /* the interrogate command got in, we can read the answer */ | 152 | /* the interrogate command got in, we can read the answer */ |
115 | wl12xx_spi_mem_read(wl, wl->cmd_box_addr, answer, | 153 | wl12xx_spi_mem_read(wl, wl->cmd_box_addr, buf, len); |
116 | CMDMBOX_HEADER_LEN + ie_len); | ||
117 | 154 | ||
118 | wl12xx_ps_elp_sleep(wl); | 155 | wl12xx_ps_elp_sleep(wl); |
119 | 156 | ||
120 | cmd = answer; | 157 | acx = buf; |
121 | if (cmd->status != CMD_STATUS_SUCCESS) | 158 | if (acx->cmd.status != CMD_STATUS_SUCCESS) |
122 | wl12xx_error("INTERROGATE command error: %d", | 159 | wl12xx_error("INTERROGATE command error: %d", |
123 | cmd->status); | 160 | acx->cmd.status); |
124 | |||
125 | return 0; | ||
126 | 161 | ||
162 | out: | ||
163 | return ret; | ||
127 | } | 164 | } |
128 | 165 | ||
129 | int wl12xx_cmd_configure(struct wl12xx *wl, void *ie, int ie_len) | 166 | /** |
167 | * write acx value to firmware | ||
168 | * | ||
169 | * @wl: wl struct | ||
170 | * @id: acx id | ||
171 | * @buf: buffer containing acx, including all headers, must work with dma | ||
172 | * @len: length of buf | ||
173 | */ | ||
174 | int wl12xx_cmd_configure(struct wl12xx *wl, u16 id, void *buf, size_t len) | ||
130 | { | 175 | { |
176 | struct acx_header *acx = buf; | ||
131 | int ret; | 177 | int ret; |
132 | 178 | ||
133 | wl12xx_debug(DEBUG_CMD, "cmd configure"); | 179 | wl12xx_debug(DEBUG_CMD, "cmd configure"); |
134 | 180 | ||
135 | ret = wl12xx_cmd_send(wl, CMD_CONFIGURE, ie, | 181 | acx->id = id; |
136 | ie_len); | 182 | |
183 | /* payload length, does not include any headers */ | ||
184 | acx->len = len - sizeof(*acx); | ||
185 | |||
186 | ret = wl12xx_cmd_send(wl, CMD_CONFIGURE, acx, len); | ||
137 | if (ret < 0) { | 187 | if (ret < 0) { |
138 | wl12xx_warning("CONFIGURE command NOK"); | 188 | wl12xx_warning("CONFIGURE command NOK"); |
139 | return ret; | 189 | return ret; |
140 | } | 190 | } |
141 | 191 | ||
142 | return 0; | 192 | return 0; |
143 | |||
144 | } | 193 | } |
145 | 194 | ||
146 | int wl12xx_cmd_vbm(struct wl12xx *wl, u8 identity, | 195 | int wl12xx_cmd_vbm(struct wl12xx *wl, u8 identity, |
147 | void *bitmap, u16 bitmap_len, u8 bitmap_control) | 196 | void *bitmap, u16 bitmap_len, u8 bitmap_control) |
148 | { | 197 | { |
149 | struct vbm_update_request vbm; | 198 | struct wl12xx_cmd_vbm_update *vbm; |
150 | int ret; | 199 | int ret; |
151 | 200 | ||
152 | wl12xx_debug(DEBUG_CMD, "cmd vbm"); | 201 | wl12xx_debug(DEBUG_CMD, "cmd vbm"); |
153 | 202 | ||
203 | vbm = kzalloc(sizeof(*vbm), GFP_KERNEL); | ||
204 | if (!vbm) { | ||
205 | ret = -ENOMEM; | ||
206 | goto out; | ||
207 | } | ||
208 | |||
154 | /* Count and period will be filled by the target */ | 209 | /* Count and period will be filled by the target */ |
155 | vbm.tim.bitmap_ctrl = bitmap_control; | 210 | vbm->tim.bitmap_ctrl = bitmap_control; |
156 | if (bitmap_len > PARTIAL_VBM_MAX) { | 211 | if (bitmap_len > PARTIAL_VBM_MAX) { |
157 | wl12xx_warning("cmd vbm len is %d B, truncating to %d", | 212 | wl12xx_warning("cmd vbm len is %d B, truncating to %d", |
158 | bitmap_len, PARTIAL_VBM_MAX); | 213 | bitmap_len, PARTIAL_VBM_MAX); |
159 | bitmap_len = PARTIAL_VBM_MAX; | 214 | bitmap_len = PARTIAL_VBM_MAX; |
160 | } | 215 | } |
161 | memcpy(vbm.tim.pvb_field, bitmap, bitmap_len); | 216 | memcpy(vbm->tim.pvb_field, bitmap, bitmap_len); |
162 | vbm.tim.identity = identity; | 217 | vbm->tim.identity = identity; |
163 | vbm.tim.length = bitmap_len + 3; | 218 | vbm->tim.length = bitmap_len + 3; |
164 | 219 | ||
165 | vbm.len = cpu_to_le16(bitmap_len + 5); | 220 | vbm->len = cpu_to_le16(bitmap_len + 5); |
166 | 221 | ||
167 | ret = wl12xx_cmd_send(wl, CMD_VBM, &vbm, sizeof(vbm)); | 222 | ret = wl12xx_cmd_send(wl, CMD_VBM, vbm, sizeof(*vbm)); |
168 | if (ret < 0) { | 223 | if (ret < 0) { |
169 | wl12xx_error("VBM command failed"); | 224 | wl12xx_error("VBM command failed"); |
170 | return ret; | 225 | goto out; |
171 | } | 226 | } |
172 | 227 | ||
228 | out: | ||
229 | kfree(vbm); | ||
173 | return 0; | 230 | return 0; |
174 | } | 231 | } |
175 | 232 | ||
176 | int wl12xx_cmd_data_path(struct wl12xx *wl, u8 channel, u8 enable) | 233 | int wl12xx_cmd_data_path(struct wl12xx *wl, u8 channel, bool enable) |
177 | { | 234 | { |
235 | struct cmd_enabledisable_path *cmd; | ||
178 | int ret; | 236 | int ret; |
179 | u16 cmd_rx, cmd_tx; | 237 | u16 cmd_rx, cmd_tx; |
180 | 238 | ||
181 | wl12xx_debug(DEBUG_CMD, "cmd data path"); | 239 | wl12xx_debug(DEBUG_CMD, "cmd data path"); |
182 | 240 | ||
241 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
242 | if (!cmd) { | ||
243 | ret = -ENOMEM; | ||
244 | goto out; | ||
245 | } | ||
246 | |||
247 | cmd->channel = channel; | ||
248 | |||
183 | if (enable) { | 249 | if (enable) { |
184 | cmd_rx = CMD_ENABLE_RX; | 250 | cmd_rx = CMD_ENABLE_RX; |
185 | cmd_tx = CMD_ENABLE_TX; | 251 | cmd_tx = CMD_ENABLE_TX; |
@@ -188,17 +254,17 @@ int wl12xx_cmd_data_path(struct wl12xx *wl, u8 channel, u8 enable) | |||
188 | cmd_tx = CMD_DISABLE_TX; | 254 | cmd_tx = CMD_DISABLE_TX; |
189 | } | 255 | } |
190 | 256 | ||
191 | ret = wl12xx_cmd_send(wl, cmd_rx, &channel, sizeof(channel)); | 257 | ret = wl12xx_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd)); |
192 | if (ret < 0) { | 258 | if (ret < 0) { |
193 | wl12xx_error("rx %s cmd for channel %d failed", | 259 | wl12xx_error("rx %s cmd for channel %d failed", |
194 | enable ? "start" : "stop", channel); | 260 | enable ? "start" : "stop", channel); |
195 | return ret; | 261 | goto out; |
196 | } | 262 | } |
197 | 263 | ||
198 | wl12xx_debug(DEBUG_BOOT, "rx %s cmd channel %d", | 264 | wl12xx_debug(DEBUG_BOOT, "rx %s cmd channel %d", |
199 | enable ? "start" : "stop", channel); | 265 | enable ? "start" : "stop", channel); |
200 | 266 | ||
201 | ret = wl12xx_cmd_send(wl, cmd_tx, &channel, sizeof(channel)); | 267 | ret = wl12xx_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd)); |
202 | if (ret < 0) { | 268 | if (ret < 0) { |
203 | wl12xx_error("tx %s cmd for channel %d failed", | 269 | wl12xx_error("tx %s cmd for channel %d failed", |
204 | enable ? "start" : "stop", channel); | 270 | enable ? "start" : "stop", channel); |
@@ -208,48 +274,56 @@ int wl12xx_cmd_data_path(struct wl12xx *wl, u8 channel, u8 enable) | |||
208 | wl12xx_debug(DEBUG_BOOT, "tx %s cmd channel %d", | 274 | wl12xx_debug(DEBUG_BOOT, "tx %s cmd channel %d", |
209 | enable ? "start" : "stop", channel); | 275 | enable ? "start" : "stop", channel); |
210 | 276 | ||
211 | return 0; | 277 | out: |
278 | kfree(cmd); | ||
279 | return ret; | ||
212 | } | 280 | } |
213 | 281 | ||
214 | int wl12xx_cmd_join(struct wl12xx *wl, u8 bss_type, u8 dtim_interval, | 282 | int wl12xx_cmd_join(struct wl12xx *wl, u8 bss_type, u8 dtim_interval, |
215 | u16 beacon_interval, u8 wait) | 283 | u16 beacon_interval, u8 wait) |
216 | { | 284 | { |
217 | unsigned long timeout; | 285 | unsigned long timeout; |
218 | struct cmd_join join = {}; | 286 | struct cmd_join *join; |
219 | int ret, i; | 287 | int ret, i; |
220 | u8 *bssid; | 288 | u8 *bssid; |
221 | 289 | ||
290 | join = kzalloc(sizeof(*join), GFP_KERNEL); | ||
291 | if (!join) { | ||
292 | ret = -ENOMEM; | ||
293 | goto out; | ||
294 | } | ||
295 | |||
222 | /* FIXME: this should be in main.c */ | 296 | /* FIXME: this should be in main.c */ |
223 | ret = wl12xx_acx_frame_rates(wl, DEFAULT_HW_GEN_TX_RATE, | 297 | ret = wl12xx_acx_frame_rates(wl, DEFAULT_HW_GEN_TX_RATE, |
224 | DEFAULT_HW_GEN_MODULATION_TYPE, | 298 | DEFAULT_HW_GEN_MODULATION_TYPE, |
225 | wl->tx_mgmt_frm_rate, | 299 | wl->tx_mgmt_frm_rate, |
226 | wl->tx_mgmt_frm_mod); | 300 | wl->tx_mgmt_frm_mod); |
227 | if (ret < 0) | 301 | if (ret < 0) |
228 | return ret; | 302 | goto out; |
229 | 303 | ||
230 | wl12xx_debug(DEBUG_CMD, "cmd join"); | 304 | wl12xx_debug(DEBUG_CMD, "cmd join"); |
231 | 305 | ||
232 | /* Reverse order BSSID */ | 306 | /* Reverse order BSSID */ |
233 | bssid = (u8 *)&join.bssid_lsb; | 307 | bssid = (u8 *) &join->bssid_lsb; |
234 | for (i = 0; i < ETH_ALEN; i++) | 308 | for (i = 0; i < ETH_ALEN; i++) |
235 | bssid[i] = wl->bssid[ETH_ALEN - i - 1]; | 309 | bssid[i] = wl->bssid[ETH_ALEN - i - 1]; |
236 | 310 | ||
237 | join.rx_config_options = wl->rx_config; | 311 | join->rx_config_options = wl->rx_config; |
238 | join.rx_filter_options = wl->rx_filter; | 312 | join->rx_filter_options = wl->rx_filter; |
239 | 313 | ||
240 | join.basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS | | 314 | join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS | |
241 | RATE_MASK_5_5MBPS | RATE_MASK_11MBPS; | 315 | RATE_MASK_5_5MBPS | RATE_MASK_11MBPS; |
242 | 316 | ||
243 | join.beacon_interval = beacon_interval; | 317 | join->beacon_interval = beacon_interval; |
244 | join.dtim_interval = dtim_interval; | 318 | join->dtim_interval = dtim_interval; |
245 | join.bss_type = bss_type; | 319 | join->bss_type = bss_type; |
246 | join.channel = wl->channel; | 320 | join->channel = wl->channel; |
247 | join.ctrl = JOIN_CMD_CTRL_TX_FLUSH; | 321 | join->ctrl = JOIN_CMD_CTRL_TX_FLUSH; |
248 | 322 | ||
249 | ret = wl12xx_cmd_send(wl, CMD_START_JOIN, &join, sizeof(join)); | 323 | ret = wl12xx_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join)); |
250 | if (ret < 0) { | 324 | if (ret < 0) { |
251 | wl12xx_error("failed to initiate cmd join"); | 325 | wl12xx_error("failed to initiate cmd join"); |
252 | return ret; | 326 | goto out; |
253 | } | 327 | } |
254 | 328 | ||
255 | timeout = msecs_to_jiffies(JOIN_TIMEOUT); | 329 | timeout = msecs_to_jiffies(JOIN_TIMEOUT); |
@@ -261,93 +335,120 @@ int wl12xx_cmd_join(struct wl12xx *wl, u8 bss_type, u8 dtim_interval, | |||
261 | if (wait) | 335 | if (wait) |
262 | msleep(10); | 336 | msleep(10); |
263 | 337 | ||
264 | return 0; | 338 | out: |
339 | kfree(join); | ||
340 | return ret; | ||
265 | } | 341 | } |
266 | 342 | ||
267 | int wl12xx_cmd_ps_mode(struct wl12xx *wl, u8 ps_mode) | 343 | int wl12xx_cmd_ps_mode(struct wl12xx *wl, u8 ps_mode) |
268 | { | 344 | { |
269 | int ret; | 345 | struct wl12xx_cmd_ps_params *ps_params = NULL; |
270 | struct acx_ps_params ps_params; | 346 | int ret = 0; |
271 | 347 | ||
272 | /* FIXME: this should be in ps.c */ | 348 | /* FIXME: this should be in ps.c */ |
273 | ret = wl12xx_acx_wake_up_conditions(wl, wl->listen_int); | 349 | ret = wl12xx_acx_wake_up_conditions(wl, wl->listen_int); |
274 | if (ret < 0) { | 350 | if (ret < 0) { |
275 | wl12xx_error("Couldnt set wake up conditions"); | 351 | wl12xx_error("couldn't set wake up conditions"); |
276 | return ret; | 352 | goto out; |
277 | } | 353 | } |
278 | 354 | ||
279 | wl12xx_debug(DEBUG_CMD, "cmd set ps mode"); | 355 | wl12xx_debug(DEBUG_CMD, "cmd set ps mode"); |
280 | 356 | ||
281 | ps_params.ps_mode = ps_mode; | 357 | ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL); |
282 | ps_params.send_null_data = 1; | 358 | if (!ps_params) { |
283 | ps_params.retries = 5; | 359 | ret = -ENOMEM; |
284 | ps_params.hang_over_period = 128; | 360 | goto out; |
285 | ps_params.null_data_rate = 1; /* 1 Mbps */ | 361 | } |
362 | |||
363 | ps_params->ps_mode = ps_mode; | ||
364 | ps_params->send_null_data = 1; | ||
365 | ps_params->retries = 5; | ||
366 | ps_params->hang_over_period = 128; | ||
367 | ps_params->null_data_rate = 1; /* 1 Mbps */ | ||
286 | 368 | ||
287 | ret = wl12xx_cmd_send(wl, CMD_SET_PS_MODE, &ps_params, | 369 | ret = wl12xx_cmd_send(wl, CMD_SET_PS_MODE, ps_params, |
288 | sizeof(ps_params)); | 370 | sizeof(*ps_params)); |
289 | if (ret < 0) { | 371 | if (ret < 0) { |
290 | wl12xx_error("cmd set_ps_mode failed"); | 372 | wl12xx_error("cmd set_ps_mode failed"); |
291 | return ret; | 373 | goto out; |
292 | } | 374 | } |
293 | 375 | ||
294 | return 0; | 376 | out: |
377 | kfree(ps_params); | ||
378 | return ret; | ||
295 | } | 379 | } |
296 | 380 | ||
297 | int wl12xx_cmd_read_memory(struct wl12xx *wl, u32 addr, u32 len, void *answer) | 381 | int wl12xx_cmd_read_memory(struct wl12xx *wl, u32 addr, void *answer, |
382 | size_t len) | ||
298 | { | 383 | { |
299 | struct cmd_read_write_memory mem_cmd, *mem_answer; | 384 | struct cmd_read_write_memory *cmd; |
300 | struct wl12xx_command cmd; | 385 | int ret = 0; |
301 | int ret; | ||
302 | 386 | ||
303 | wl12xx_debug(DEBUG_CMD, "cmd read memory"); | 387 | wl12xx_debug(DEBUG_CMD, "cmd read memory"); |
304 | 388 | ||
305 | memset(&mem_cmd, 0, sizeof(mem_cmd)); | 389 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
306 | mem_cmd.addr = addr; | 390 | if (!cmd) { |
307 | mem_cmd.size = len; | 391 | ret = -ENOMEM; |
392 | goto out; | ||
393 | } | ||
394 | |||
395 | WARN_ON(len > MAX_READ_SIZE); | ||
396 | len = min_t(size_t, len, MAX_READ_SIZE); | ||
397 | |||
398 | cmd->addr = addr; | ||
399 | cmd->size = len; | ||
308 | 400 | ||
309 | ret = wl12xx_cmd_send(wl, CMD_READ_MEMORY, &mem_cmd, sizeof(mem_cmd)); | 401 | ret = wl12xx_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd)); |
310 | if (ret < 0) { | 402 | if (ret < 0) { |
311 | wl12xx_error("read memory command failed: %d", ret); | 403 | wl12xx_error("read memory command failed: %d", ret); |
312 | return ret; | 404 | goto out; |
313 | } | 405 | } |
314 | 406 | ||
315 | /* the read command got in, we can now read the answer */ | 407 | /* the read command got in, we can now read the answer */ |
316 | wl12xx_spi_mem_read(wl, wl->cmd_box_addr, &cmd, | 408 | wl12xx_spi_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd)); |
317 | CMDMBOX_HEADER_LEN + sizeof(mem_cmd)); | ||
318 | 409 | ||
319 | if (cmd.status != CMD_STATUS_SUCCESS) | 410 | if (cmd->header.status != CMD_STATUS_SUCCESS) |
320 | wl12xx_error("error in read command result: %d", cmd.status); | 411 | wl12xx_error("error in read command result: %d", |
412 | cmd->header.status); | ||
321 | 413 | ||
322 | mem_answer = (struct cmd_read_write_memory *) cmd.parameters; | 414 | memcpy(answer, cmd->value, len); |
323 | memcpy(answer, mem_answer->value, len); | ||
324 | 415 | ||
325 | return 0; | 416 | out: |
417 | kfree(cmd); | ||
418 | return ret; | ||
326 | } | 419 | } |
327 | 420 | ||
328 | int wl12xx_cmd_template_set(struct wl12xx *wl, u16 cmd_id, | 421 | int wl12xx_cmd_template_set(struct wl12xx *wl, u16 cmd_id, |
329 | void *buf, size_t buf_len) | 422 | void *buf, size_t buf_len) |
330 | { | 423 | { |
331 | struct wl12xx_cmd_packet_template template; | 424 | struct wl12xx_cmd_packet_template *cmd; |
332 | int ret; | 425 | size_t cmd_len; |
426 | int ret = 0; | ||
333 | 427 | ||
334 | wl12xx_debug(DEBUG_CMD, "cmd template %d", cmd_id); | 428 | wl12xx_debug(DEBUG_CMD, "cmd template %d", cmd_id); |
335 | 429 | ||
336 | memset(&template, 0, sizeof(template)); | ||
337 | |||
338 | WARN_ON(buf_len > WL12XX_MAX_TEMPLATE_SIZE); | 430 | WARN_ON(buf_len > WL12XX_MAX_TEMPLATE_SIZE); |
339 | buf_len = min_t(size_t, buf_len, WL12XX_MAX_TEMPLATE_SIZE); | 431 | buf_len = min_t(size_t, buf_len, WL12XX_MAX_TEMPLATE_SIZE); |
340 | template.size = cpu_to_le16(buf_len); | 432 | cmd_len = ALIGN(sizeof(*cmd) + buf_len, 4); |
433 | |||
434 | cmd = kzalloc(cmd_len, GFP_KERNEL); | ||
435 | if (!cmd) { | ||
436 | ret = -ENOMEM; | ||
437 | goto out; | ||
438 | } | ||
439 | |||
440 | cmd->size = cpu_to_le16(buf_len); | ||
341 | 441 | ||
342 | if (buf) | 442 | if (buf) |
343 | memcpy(template.template, buf, buf_len); | 443 | memcpy(cmd->data, buf, buf_len); |
344 | 444 | ||
345 | ret = wl12xx_cmd_send(wl, cmd_id, &template, | 445 | ret = wl12xx_cmd_send(wl, cmd_id, cmd, cmd_len); |
346 | sizeof(template.size) + buf_len); | ||
347 | if (ret < 0) { | 446 | if (ret < 0) { |
348 | wl12xx_warning("cmd set_template failed: %d", ret); | 447 | wl12xx_warning("cmd set_template failed: %d", ret); |
349 | return ret; | 448 | goto out; |
350 | } | 449 | } |
351 | 450 | ||
352 | return 0; | 451 | out: |
452 | kfree(cmd); | ||
453 | return ret; | ||
353 | } | 454 | } |
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index aa307dcd081f..7aef1f24352d 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h | |||
@@ -27,31 +27,26 @@ | |||
27 | 27 | ||
28 | #include "wl12xx.h" | 28 | #include "wl12xx.h" |
29 | 29 | ||
30 | struct acx_header; | ||
31 | |||
30 | int wl12xx_cmd_send(struct wl12xx *wl, u16 type, void *buf, size_t buf_len); | 32 | int wl12xx_cmd_send(struct wl12xx *wl, u16 type, void *buf, size_t buf_len); |
31 | int wl12xx_cmd_test(struct wl12xx *wl, void *buf, size_t buf_len, u8 answer); | 33 | int wl12xx_cmd_test(struct wl12xx *wl, void *buf, size_t buf_len, u8 answer); |
32 | int wl12xx_cmd_interrogate(struct wl12xx *wl, u16 ie_id, u16 ie_len, | 34 | int wl12xx_cmd_interrogate(struct wl12xx *wl, u16 id, void *buf, size_t len); |
33 | void *answer); | 35 | int wl12xx_cmd_configure(struct wl12xx *wl, u16 id, void *buf, size_t len); |
34 | int wl12xx_cmd_configure(struct wl12xx *wl, void *ie, int ie_len); | ||
35 | int wl12xx_cmd_vbm(struct wl12xx *wl, u8 identity, | 36 | int wl12xx_cmd_vbm(struct wl12xx *wl, u8 identity, |
36 | void *bitmap, u16 bitmap_len, u8 bitmap_control); | 37 | void *bitmap, u16 bitmap_len, u8 bitmap_control); |
37 | int wl12xx_cmd_data_path(struct wl12xx *wl, u8 channel, u8 enable); | 38 | int wl12xx_cmd_data_path(struct wl12xx *wl, u8 channel, bool enable); |
38 | int wl12xx_cmd_join(struct wl12xx *wl, u8 bss_type, u8 dtim_interval, | 39 | int wl12xx_cmd_join(struct wl12xx *wl, u8 bss_type, u8 dtim_interval, |
39 | u16 beacon_interval, u8 wait); | 40 | u16 beacon_interval, u8 wait); |
40 | int wl12xx_cmd_ps_mode(struct wl12xx *wl, u8 ps_mode); | 41 | int wl12xx_cmd_ps_mode(struct wl12xx *wl, u8 ps_mode); |
41 | int wl12xx_cmd_read_memory(struct wl12xx *wl, u32 addr, u32 len, void *answer); | 42 | int wl12xx_cmd_read_memory(struct wl12xx *wl, u32 addr, void *answer, |
43 | size_t len); | ||
42 | int wl12xx_cmd_template_set(struct wl12xx *wl, u16 cmd_id, | 44 | int wl12xx_cmd_template_set(struct wl12xx *wl, u16 cmd_id, |
43 | void *buf, size_t buf_len); | 45 | void *buf, size_t buf_len); |
44 | 46 | ||
45 | /* unit ms */ | 47 | /* unit ms */ |
46 | #define WL12XX_COMMAND_TIMEOUT 2000 | 48 | #define WL12XX_COMMAND_TIMEOUT 2000 |
47 | 49 | ||
48 | #define WL12XX_MAX_TEMPLATE_SIZE 300 | ||
49 | |||
50 | struct wl12xx_cmd_packet_template { | ||
51 | __le16 size; | ||
52 | u8 template[WL12XX_MAX_TEMPLATE_SIZE]; | ||
53 | } __attribute__ ((packed)); | ||
54 | |||
55 | enum wl12xx_commands { | 50 | enum wl12xx_commands { |
56 | CMD_RESET = 0, | 51 | CMD_RESET = 0, |
57 | CMD_INTERROGATE = 1, /*use this to read information elements*/ | 52 | CMD_INTERROGATE = 1, /*use this to read information elements*/ |
@@ -100,9 +95,15 @@ enum wl12xx_commands { | |||
100 | 95 | ||
101 | #define MAX_CMD_PARAMS 572 | 96 | #define MAX_CMD_PARAMS 572 |
102 | 97 | ||
103 | struct wl12xx_command { | 98 | struct wl12xx_cmd_header { |
104 | u16 id; | 99 | u16 id; |
105 | u16 status; | 100 | u16 status; |
101 | /* payload */ | ||
102 | u8 data[0]; | ||
103 | } __attribute__ ((packed)); | ||
104 | |||
105 | struct wl12xx_command { | ||
106 | struct wl12xx_cmd_header header; | ||
106 | u8 parameters[MAX_CMD_PARAMS]; | 107 | u8 parameters[MAX_CMD_PARAMS]; |
107 | }; | 108 | }; |
108 | 109 | ||
@@ -144,6 +145,8 @@ enum { | |||
144 | #define MAX_READ_SIZE 256 | 145 | #define MAX_READ_SIZE 256 |
145 | 146 | ||
146 | struct cmd_read_write_memory { | 147 | struct cmd_read_write_memory { |
148 | struct wl12xx_cmd_header header; | ||
149 | |||
147 | /* The address of the memory to read from or write to.*/ | 150 | /* The address of the memory to read from or write to.*/ |
148 | u32 addr; | 151 | u32 addr; |
149 | 152 | ||
@@ -211,6 +214,8 @@ struct basic_scan_channel_parameters { | |||
211 | #define SCAN_MAX_NUM_OF_CHANNELS 16 | 214 | #define SCAN_MAX_NUM_OF_CHANNELS 16 |
212 | 215 | ||
213 | struct cmd_scan { | 216 | struct cmd_scan { |
217 | struct wl12xx_cmd_header header; | ||
218 | |||
214 | struct basic_scan_parameters params; | 219 | struct basic_scan_parameters params; |
215 | struct basic_scan_channel_parameters channels[SCAN_MAX_NUM_OF_CHANNELS]; | 220 | struct basic_scan_channel_parameters channels[SCAN_MAX_NUM_OF_CHANNELS]; |
216 | } __attribute__ ((packed)); | 221 | } __attribute__ ((packed)); |
@@ -227,6 +232,8 @@ enum { | |||
227 | 232 | ||
228 | 233 | ||
229 | struct cmd_join { | 234 | struct cmd_join { |
235 | struct wl12xx_cmd_header header; | ||
236 | |||
230 | u32 bssid_lsb; | 237 | u32 bssid_lsb; |
231 | u16 bssid_msb; | 238 | u16 bssid_msb; |
232 | u16 beacon_interval; /* in TBTTs */ | 239 | u16 beacon_interval; /* in TBTTs */ |
@@ -261,5 +268,140 @@ struct cmd_join { | |||
261 | u8 reserved; | 268 | u8 reserved; |
262 | } __attribute__ ((packed)); | 269 | } __attribute__ ((packed)); |
263 | 270 | ||
271 | struct cmd_enabledisable_path { | ||
272 | struct wl12xx_cmd_header header; | ||
273 | |||
274 | u8 channel; | ||
275 | u8 padding[3]; | ||
276 | } __attribute__ ((packed)); | ||
277 | |||
278 | #define WL12XX_MAX_TEMPLATE_SIZE 300 | ||
279 | |||
280 | struct wl12xx_cmd_packet_template { | ||
281 | struct wl12xx_cmd_header header; | ||
282 | |||
283 | __le16 size; | ||
284 | u8 data[0]; | ||
285 | } __attribute__ ((packed)); | ||
286 | |||
287 | #define TIM_ELE_ID 5 | ||
288 | #define PARTIAL_VBM_MAX 251 | ||
289 | |||
290 | struct wl12xx_tim { | ||
291 | u8 identity; | ||
292 | u8 length; | ||
293 | u8 dtim_count; | ||
294 | u8 dtim_period; | ||
295 | u8 bitmap_ctrl; | ||
296 | u8 pvb_field[PARTIAL_VBM_MAX]; /* Partial Virtual Bitmap */ | ||
297 | } __attribute__ ((packed)); | ||
298 | |||
299 | /* Virtual Bit Map update */ | ||
300 | struct wl12xx_cmd_vbm_update { | ||
301 | struct wl12xx_cmd_header header; | ||
302 | __le16 len; | ||
303 | u8 padding[2]; | ||
304 | struct wl12xx_tim tim; | ||
305 | } __attribute__ ((packed)); | ||
306 | |||
307 | enum wl12xx_cmd_ps_mode { | ||
308 | STATION_ACTIVE_MODE, | ||
309 | STATION_POWER_SAVE_MODE | ||
310 | }; | ||
311 | |||
312 | struct wl12xx_cmd_ps_params { | ||
313 | struct wl12xx_cmd_header header; | ||
314 | |||
315 | u8 ps_mode; /* STATION_* */ | ||
316 | u8 send_null_data; /* Do we have to send NULL data packet ? */ | ||
317 | u8 retries; /* Number of retires for the initial NULL data packet */ | ||
318 | |||
319 | /* | ||
320 | * TUs during which the target stays awake after switching | ||
321 | * to power save mode. | ||
322 | */ | ||
323 | u8 hang_over_period; | ||
324 | u16 null_data_rate; | ||
325 | u8 pad[2]; | ||
326 | } __attribute__ ((packed)); | ||
327 | |||
328 | struct wl12xx_cmd_trigger_scan_to { | ||
329 | struct wl12xx_cmd_header header; | ||
330 | |||
331 | u32 timeout; | ||
332 | }; | ||
333 | |||
334 | /* HW encryption keys */ | ||
335 | #define NUM_ACCESS_CATEGORIES_COPY 4 | ||
336 | #define MAX_KEY_SIZE 32 | ||
337 | |||
338 | /* When set, disable HW encryption */ | ||
339 | #define DF_ENCRYPTION_DISABLE 0x01 | ||
340 | /* When set, disable HW decryption */ | ||
341 | #define DF_SNIFF_MODE_ENABLE 0x80 | ||
342 | |||
343 | enum wl12xx_cmd_key_action { | ||
344 | KEY_ADD_OR_REPLACE = 1, | ||
345 | KEY_REMOVE = 2, | ||
346 | KEY_SET_ID = 3, | ||
347 | MAX_KEY_ACTION = 0xffff, | ||
348 | }; | ||
349 | |||
350 | enum wl12xx_cmd_key_type { | ||
351 | KEY_WEP_DEFAULT = 0, | ||
352 | KEY_WEP_ADDR = 1, | ||
353 | KEY_AES_GROUP = 4, | ||
354 | KEY_AES_PAIRWISE = 5, | ||
355 | KEY_WEP_GROUP = 6, | ||
356 | KEY_TKIP_MIC_GROUP = 10, | ||
357 | KEY_TKIP_MIC_PAIRWISE = 11, | ||
358 | }; | ||
359 | |||
360 | /* | ||
361 | * | ||
362 | * key_type_e key size key format | ||
363 | * ---------- --------- ---------- | ||
364 | * 0x00 5, 13, 29 Key data | ||
365 | * 0x01 5, 13, 29 Key data | ||
366 | * 0x04 16 16 bytes of key data | ||
367 | * 0x05 16 16 bytes of key data | ||
368 | * 0x0a 32 16 bytes of TKIP key data | ||
369 | * 8 bytes of RX MIC key data | ||
370 | * 8 bytes of TX MIC key data | ||
371 | * 0x0b 32 16 bytes of TKIP key data | ||
372 | * 8 bytes of RX MIC key data | ||
373 | * 8 bytes of TX MIC key data | ||
374 | * | ||
375 | */ | ||
376 | |||
377 | struct wl12xx_cmd_set_keys { | ||
378 | struct wl12xx_cmd_header header; | ||
379 | |||
380 | /* Ignored for default WEP key */ | ||
381 | u8 addr[ETH_ALEN]; | ||
382 | |||
383 | /* key_action_e */ | ||
384 | u16 key_action; | ||
385 | |||
386 | u16 reserved_1; | ||
387 | |||
388 | /* key size in bytes */ | ||
389 | u8 key_size; | ||
390 | |||
391 | /* key_type_e */ | ||
392 | u8 key_type; | ||
393 | u8 ssid_profile; | ||
394 | |||
395 | /* | ||
396 | * TKIP, AES: frame's key id field. | ||
397 | * For WEP default key: key id; | ||
398 | */ | ||
399 | u8 id; | ||
400 | u8 reserved_2[6]; | ||
401 | u8 key[MAX_KEY_SIZE]; | ||
402 | u16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY]; | ||
403 | u32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY]; | ||
404 | } __attribute__ ((packed)); | ||
405 | |||
264 | 406 | ||
265 | #endif /* __WL12XX_CMD_H__ */ | 407 | #endif /* __WL12XX_CMD_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 603d6114882e..c6a454439711 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -618,7 +618,8 @@ static void wl12xx_op_configure_filter(struct ieee80211_hw *hw, | |||
618 | } | 618 | } |
619 | 619 | ||
620 | /* HW encryption */ | 620 | /* HW encryption */ |
621 | static int wl12xx_set_key_type(struct wl12xx *wl, struct acx_set_key *key, | 621 | static int wl12xx_set_key_type(struct wl12xx *wl, |
622 | struct wl12xx_cmd_set_keys *key, | ||
622 | enum set_key_cmd cmd, | 623 | enum set_key_cmd cmd, |
623 | struct ieee80211_key_conf *mac80211_key, | 624 | struct ieee80211_key_conf *mac80211_key, |
624 | const u8 *addr) | 625 | const u8 *addr) |
@@ -661,7 +662,7 @@ static int wl12xx_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
661 | struct ieee80211_key_conf *key) | 662 | struct ieee80211_key_conf *key) |
662 | { | 663 | { |
663 | struct wl12xx *wl = hw->priv; | 664 | struct wl12xx *wl = hw->priv; |
664 | struct acx_set_key wl_key; | 665 | struct wl12xx_cmd_set_keys *wl_cmd; |
665 | const u8 *addr; | 666 | const u8 *addr; |
666 | int ret; | 667 | int ret; |
667 | 668 | ||
@@ -670,7 +671,11 @@ static int wl12xx_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
670 | 671 | ||
671 | wl12xx_debug(DEBUG_MAC80211, "mac80211 set key"); | 672 | wl12xx_debug(DEBUG_MAC80211, "mac80211 set key"); |
672 | 673 | ||
673 | memset(&wl_key, 0, sizeof(wl_key)); | 674 | wl_cmd = kzalloc(sizeof(*wl_cmd), GFP_KERNEL); |
675 | if (!wl_cmd) { | ||
676 | ret = -ENOMEM; | ||
677 | goto out; | ||
678 | } | ||
674 | 679 | ||
675 | addr = sta ? sta->addr : bcast_addr; | 680 | addr = sta ? sta->addr : bcast_addr; |
676 | 681 | ||
@@ -680,59 +685,69 @@ static int wl12xx_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
680 | key->alg, key->keyidx, key->keylen, key->flags); | 685 | key->alg, key->keyidx, key->keylen, key->flags); |
681 | wl12xx_dump(DEBUG_CRYPT, "KEY: ", key->key, key->keylen); | 686 | wl12xx_dump(DEBUG_CRYPT, "KEY: ", key->key, key->keylen); |
682 | 687 | ||
688 | if (is_zero_ether_addr(addr)) { | ||
689 | /* We dont support TX only encryption */ | ||
690 | ret = -EOPNOTSUPP; | ||
691 | goto out; | ||
692 | } | ||
693 | |||
683 | mutex_lock(&wl->mutex); | 694 | mutex_lock(&wl->mutex); |
684 | 695 | ||
685 | switch (cmd) { | 696 | switch (cmd) { |
686 | case SET_KEY: | 697 | case SET_KEY: |
687 | wl_key.key_action = KEY_ADD_OR_REPLACE; | 698 | wl_cmd->key_action = KEY_ADD_OR_REPLACE; |
688 | break; | 699 | break; |
689 | case DISABLE_KEY: | 700 | case DISABLE_KEY: |
690 | wl_key.key_action = KEY_REMOVE; | 701 | wl_cmd->key_action = KEY_REMOVE; |
691 | break; | 702 | break; |
692 | default: | 703 | default: |
693 | wl12xx_error("Unsupported key cmd 0x%x", cmd); | 704 | wl12xx_error("Unsupported key cmd 0x%x", cmd); |
694 | break; | 705 | break; |
695 | } | 706 | } |
696 | 707 | ||
697 | ret = wl12xx_set_key_type(wl, &wl_key, cmd, key, addr); | 708 | ret = wl12xx_set_key_type(wl, wl_cmd, cmd, key, addr); |
698 | if (ret < 0) { | 709 | if (ret < 0) { |
699 | wl12xx_error("Set KEY type failed"); | 710 | wl12xx_error("Set KEY type failed"); |
700 | goto out; | 711 | goto out_unlock; |
701 | } | 712 | } |
702 | 713 | ||
703 | if (wl_key.key_type != KEY_WEP_DEFAULT) | 714 | if (wl_cmd->key_type != KEY_WEP_DEFAULT) |
704 | memcpy(wl_key.addr, addr, ETH_ALEN); | 715 | memcpy(wl_cmd->addr, addr, ETH_ALEN); |
705 | 716 | ||
706 | if ((wl_key.key_type == KEY_TKIP_MIC_GROUP) || | 717 | if ((wl_cmd->key_type == KEY_TKIP_MIC_GROUP) || |
707 | (wl_key.key_type == KEY_TKIP_MIC_PAIRWISE)) { | 718 | (wl_cmd->key_type == KEY_TKIP_MIC_PAIRWISE)) { |
708 | /* | 719 | /* |
709 | * We get the key in the following form: | 720 | * We get the key in the following form: |
710 | * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes) | 721 | * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes) |
711 | * but the target is expecting: | 722 | * but the target is expecting: |
712 | * TKIP - RX MIC - TX MIC | 723 | * TKIP - RX MIC - TX MIC |
713 | */ | 724 | */ |
714 | memcpy(wl_key.key, key->key, 16); | 725 | memcpy(wl_cmd->key, key->key, 16); |
715 | memcpy(wl_key.key + 16, key->key + 24, 8); | 726 | memcpy(wl_cmd->key + 16, key->key + 24, 8); |
716 | memcpy(wl_key.key + 24, key->key + 16, 8); | 727 | memcpy(wl_cmd->key + 24, key->key + 16, 8); |
717 | 728 | ||
718 | } else { | 729 | } else { |
719 | memcpy(wl_key.key, key->key, key->keylen); | 730 | memcpy(wl_cmd->key, key->key, key->keylen); |
720 | } | 731 | } |
721 | wl_key.key_size = key->keylen; | 732 | wl_cmd->key_size = key->keylen; |
722 | 733 | ||
723 | wl_key.id = key->keyidx; | 734 | wl_cmd->id = key->keyidx; |
724 | wl_key.ssid_profile = 0; | 735 | wl_cmd->ssid_profile = 0; |
725 | 736 | ||
726 | wl12xx_dump(DEBUG_CRYPT, "TARGET KEY: ", &wl_key, sizeof(wl_key)); | 737 | wl12xx_dump(DEBUG_CRYPT, "TARGET KEY: ", wl_cmd, sizeof(*wl_cmd)); |
727 | 738 | ||
728 | if (wl12xx_cmd_send(wl, CMD_SET_KEYS, &wl_key, sizeof(wl_key)) < 0) { | 739 | ret = wl12xx_cmd_send(wl, CMD_SET_KEYS, wl_cmd, sizeof(*wl_cmd)); |
729 | wl12xx_error("Set KEY failed"); | 740 | if (ret < 0) { |
730 | ret = -EOPNOTSUPP; | 741 | wl12xx_warning("could not set keys"); |
731 | goto out; | 742 | goto out_unlock; |
732 | } | 743 | } |
733 | 744 | ||
734 | out: | 745 | out_unlock: |
735 | mutex_unlock(&wl->mutex); | 746 | mutex_unlock(&wl->mutex); |
747 | |||
748 | out: | ||
749 | kfree(wl_cmd); | ||
750 | |||
736 | return ret; | 751 | return ret; |
737 | } | 752 | } |
738 | 753 | ||
@@ -812,11 +827,10 @@ static int wl12xx_hw_scan(struct wl12xx *wl, u8 *ssid, size_t len, | |||
812 | u8 active_scan, u8 high_prio, u8 num_channels, | 827 | u8 active_scan, u8 high_prio, u8 num_channels, |
813 | u8 probe_requests) | 828 | u8 probe_requests) |
814 | { | 829 | { |
830 | struct wl12xx_cmd_trigger_scan_to *trigger = NULL; | ||
831 | struct cmd_scan *params = NULL; | ||
815 | int i, ret; | 832 | int i, ret; |
816 | u32 split_scan = 0; | ||
817 | u16 scan_options = 0; | 833 | u16 scan_options = 0; |
818 | struct cmd_scan *params; | ||
819 | struct wl12xx_command *cmd_answer; | ||
820 | 834 | ||
821 | if (wl->scanning) | 835 | if (wl->scanning) |
822 | return -EINVAL; | 836 | return -EINVAL; |
@@ -870,10 +884,16 @@ static int wl12xx_hw_scan(struct wl12xx *wl, u8 *ssid, size_t len, | |||
870 | goto out; | 884 | goto out; |
871 | } | 885 | } |
872 | 886 | ||
873 | ret = wl12xx_cmd_send(wl, CMD_TRIGGER_SCAN_TO, &split_scan, | 887 | trigger = kzalloc(sizeof(*trigger), GFP_KERNEL); |
874 | sizeof(u32)); | 888 | if (!trigger) |
889 | goto out; | ||
890 | |||
891 | trigger->timeout = 0; | ||
892 | |||
893 | ret = wl12xx_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger, | ||
894 | sizeof(*trigger)); | ||
875 | if (ret < 0) { | 895 | if (ret < 0) { |
876 | wl12xx_error("Split SCAN failed"); | 896 | wl12xx_error("trigger scan to failed for hw scan"); |
877 | goto out; | 897 | goto out; |
878 | } | 898 | } |
879 | 899 | ||
@@ -887,10 +907,9 @@ static int wl12xx_hw_scan(struct wl12xx *wl, u8 *ssid, size_t len, | |||
887 | 907 | ||
888 | wl12xx_spi_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params)); | 908 | wl12xx_spi_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params)); |
889 | 909 | ||
890 | cmd_answer = (struct wl12xx_command *) params; | 910 | if (params->header.status != CMD_STATUS_SUCCESS) { |
891 | if (cmd_answer->status != CMD_STATUS_SUCCESS) { | ||
892 | wl12xx_error("TEST command answer error: %d", | 911 | wl12xx_error("TEST command answer error: %d", |
893 | cmd_answer->status); | 912 | params->header.status); |
894 | wl->scanning = false; | 913 | wl->scanning = false; |
895 | ret = -EIO; | 914 | ret = -EIO; |
896 | goto out; | 915 | goto out; |
@@ -942,7 +961,7 @@ static void wl12xx_op_bss_info_changed(struct ieee80211_hw *hw, | |||
942 | struct ieee80211_bss_conf *bss_conf, | 961 | struct ieee80211_bss_conf *bss_conf, |
943 | u32 changed) | 962 | u32 changed) |
944 | { | 963 | { |
945 | enum acx_ps_mode mode; | 964 | enum wl12xx_cmd_ps_mode mode; |
946 | struct wl12xx *wl = hw->priv; | 965 | struct wl12xx *wl = hw->priv; |
947 | struct sk_buff *beacon; | 966 | struct sk_buff *beacon; |
948 | int ret; | 967 | int ret; |
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index 83a10117330b..fe5e2d13acf2 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c | |||
@@ -114,7 +114,7 @@ static int wl12xx_ps_set_elp(struct wl12xx *wl, bool enable) | |||
114 | return 0; | 114 | return 0; |
115 | } | 115 | } |
116 | 116 | ||
117 | int wl12xx_ps_set_mode(struct wl12xx *wl, enum acx_ps_mode mode) | 117 | int wl12xx_ps_set_mode(struct wl12xx *wl, enum wl12xx_cmd_ps_mode mode) |
118 | { | 118 | { |
119 | int ret; | 119 | int ret; |
120 | 120 | ||
diff --git a/drivers/net/wireless/wl12xx/ps.h b/drivers/net/wireless/wl12xx/ps.h index 5d7c52553830..ad61b4a0b5ee 100644 --- a/drivers/net/wireless/wl12xx/ps.h +++ b/drivers/net/wireless/wl12xx/ps.h | |||
@@ -28,7 +28,7 @@ | |||
28 | #include "wl12xx.h" | 28 | #include "wl12xx.h" |
29 | #include "acx.h" | 29 | #include "acx.h" |
30 | 30 | ||
31 | int wl12xx_ps_set_mode(struct wl12xx *wl, enum acx_ps_mode mode); | 31 | int wl12xx_ps_set_mode(struct wl12xx *wl, enum wl12xx_cmd_ps_mode mode); |
32 | void wl12xx_ps_elp_sleep(struct wl12xx *wl); | 32 | void wl12xx_ps_elp_sleep(struct wl12xx *wl); |
33 | int wl12xx_ps_elp_wakeup(struct wl12xx *wl); | 33 | int wl12xx_ps_elp_wakeup(struct wl12xx *wl); |
34 | 34 | ||
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index 981ea259eb89..5fd916a0b254 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c | |||
@@ -48,6 +48,9 @@ static void wl12xx_rx_status(struct wl12xx *wl, | |||
48 | struct ieee80211_rx_status *status, | 48 | struct ieee80211_rx_status *status, |
49 | u8 beacon) | 49 | u8 beacon) |
50 | { | 50 | { |
51 | u64 mactime; | ||
52 | int ret; | ||
53 | |||
51 | memset(status, 0, sizeof(struct ieee80211_rx_status)); | 54 | memset(status, 0, sizeof(struct ieee80211_rx_status)); |
52 | 55 | ||
53 | status->band = IEEE80211_BAND_2GHZ; | 56 | status->band = IEEE80211_BAND_2GHZ; |
@@ -62,27 +65,9 @@ static void wl12xx_rx_status(struct wl12xx *wl, | |||
62 | * this one must be atomic, while our SPI routines can sleep. | 65 | * this one must be atomic, while our SPI routines can sleep. |
63 | */ | 66 | */ |
64 | if ((wl->bss_type == BSS_TYPE_IBSS) && beacon) { | 67 | if ((wl->bss_type == BSS_TYPE_IBSS) && beacon) { |
65 | u64 mactime; | 68 | ret = wl12xx_acx_tsf_info(wl, &mactime); |
66 | int ret; | 69 | if (ret == 0) |
67 | struct wl12xx_command cmd; | 70 | status->mactime = mactime; |
68 | struct acx_tsf_info *tsf_info; | ||
69 | |||
70 | memset(&cmd, 0, sizeof(cmd)); | ||
71 | |||
72 | ret = wl12xx_cmd_interrogate(wl, ACX_TSF_INFO, | ||
73 | sizeof(struct acx_tsf_info), | ||
74 | &cmd); | ||
75 | if (ret < 0) { | ||
76 | wl12xx_warning("ACX_FW_REV interrogate failed"); | ||
77 | return; | ||
78 | } | ||
79 | |||
80 | tsf_info = (struct acx_tsf_info *)&(cmd.parameters); | ||
81 | |||
82 | mactime = tsf_info->current_tsf_lsb | | ||
83 | (tsf_info->current_tsf_msb << 31); | ||
84 | |||
85 | status->mactime = mactime; | ||
86 | } | 71 | } |
87 | 72 | ||
88 | status->signal = desc->rssi; | 73 | status->signal = desc->rssi; |
diff --git a/drivers/net/wireless/wl12xx/wl1251.c b/drivers/net/wireless/wl12xx/wl1251.c index ce1561a41fa4..1a352cf8c3ec 100644 --- a/drivers/net/wireless/wl12xx/wl1251.c +++ b/drivers/net/wireless/wl12xx/wl1251.c | |||
@@ -297,45 +297,48 @@ out: | |||
297 | 297 | ||
298 | static int wl1251_mem_cfg(struct wl12xx *wl) | 298 | static int wl1251_mem_cfg(struct wl12xx *wl) |
299 | { | 299 | { |
300 | struct wl1251_acx_config_memory mem_conf; | 300 | struct wl1251_acx_config_memory *mem_conf; |
301 | int ret, i; | 301 | int ret, i; |
302 | 302 | ||
303 | wl12xx_debug(DEBUG_ACX, "wl1251 mem cfg"); | 303 | wl12xx_debug(DEBUG_ACX, "wl1251 mem cfg"); |
304 | 304 | ||
305 | mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL); | ||
306 | if (!mem_conf) { | ||
307 | ret = -ENOMEM; | ||
308 | goto out; | ||
309 | } | ||
310 | |||
305 | /* memory config */ | 311 | /* memory config */ |
306 | mem_conf.mem_config.num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS); | 312 | mem_conf->mem_config.num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS); |
307 | mem_conf.mem_config.rx_mem_block_num = 35; | 313 | mem_conf->mem_config.rx_mem_block_num = 35; |
308 | mem_conf.mem_config.tx_min_mem_block_num = 64; | 314 | mem_conf->mem_config.tx_min_mem_block_num = 64; |
309 | mem_conf.mem_config.num_tx_queues = MAX_TX_QUEUES; | 315 | mem_conf->mem_config.num_tx_queues = MAX_TX_QUEUES; |
310 | mem_conf.mem_config.host_if_options = HOSTIF_PKT_RING; | 316 | mem_conf->mem_config.host_if_options = HOSTIF_PKT_RING; |
311 | mem_conf.mem_config.num_ssid_profiles = 1; | 317 | mem_conf->mem_config.num_ssid_profiles = 1; |
312 | mem_conf.mem_config.debug_buffer_size = | 318 | mem_conf->mem_config.debug_buffer_size = |
313 | cpu_to_le16(TRACE_BUFFER_MAX_SIZE); | 319 | cpu_to_le16(TRACE_BUFFER_MAX_SIZE); |
314 | 320 | ||
315 | /* RX queue config */ | 321 | /* RX queue config */ |
316 | mem_conf.rx_queue_config.dma_address = 0; | 322 | mem_conf->rx_queue_config.dma_address = 0; |
317 | mem_conf.rx_queue_config.num_descs = ACX_RX_DESC_DEF; | 323 | mem_conf->rx_queue_config.num_descs = ACX_RX_DESC_DEF; |
318 | mem_conf.rx_queue_config.priority = DEFAULT_RXQ_PRIORITY; | 324 | mem_conf->rx_queue_config.priority = DEFAULT_RXQ_PRIORITY; |
319 | mem_conf.rx_queue_config.type = DEFAULT_RXQ_TYPE; | 325 | mem_conf->rx_queue_config.type = DEFAULT_RXQ_TYPE; |
320 | 326 | ||
321 | /* TX queue config */ | 327 | /* TX queue config */ |
322 | for (i = 0; i < MAX_TX_QUEUES; i++) { | 328 | for (i = 0; i < MAX_TX_QUEUES; i++) { |
323 | mem_conf.tx_queue_config[i].num_descs = ACX_TX_DESC_DEF; | 329 | mem_conf->tx_queue_config[i].num_descs = ACX_TX_DESC_DEF; |
324 | mem_conf.tx_queue_config[i].attributes = i; | 330 | mem_conf->tx_queue_config[i].attributes = i; |
325 | } | 331 | } |
326 | 332 | ||
327 | mem_conf.header.id = ACX_MEM_CFG; | 333 | ret = wl12xx_cmd_configure(wl, ACX_MEM_CFG, mem_conf, |
328 | mem_conf.header.len = sizeof(struct wl1251_acx_config_memory) - | 334 | sizeof(*mem_conf)); |
329 | sizeof(struct acx_header); | 335 | if (ret < 0) { |
330 | mem_conf.header.len -= | ||
331 | (MAX_TX_QUEUE_CONFIGS - mem_conf.mem_config.num_tx_queues) * | ||
332 | sizeof(struct wl1251_acx_tx_queue_config); | ||
333 | |||
334 | ret = wl12xx_cmd_configure(wl, &mem_conf, | ||
335 | sizeof(struct wl1251_acx_config_memory)); | ||
336 | if (ret < 0) | ||
337 | wl12xx_warning("wl1251 mem config failed: %d", ret); | 336 | wl12xx_warning("wl1251 mem config failed: %d", ret); |
337 | goto out; | ||
338 | } | ||
338 | 339 | ||
340 | out: | ||
341 | kfree(mem_conf); | ||
339 | return ret; | 342 | return ret; |
340 | } | 343 | } |
341 | 344 | ||
@@ -529,28 +532,33 @@ static int wl1251_hw_init_txq_fill(u8 qid, | |||
529 | 532 | ||
530 | static int wl1251_hw_init_tx_queue_config(struct wl12xx *wl) | 533 | static int wl1251_hw_init_tx_queue_config(struct wl12xx *wl) |
531 | { | 534 | { |
532 | struct acx_tx_queue_qos_config config; | 535 | struct acx_tx_queue_qos_config *config; |
533 | struct wl1251_acx_mem_map *wl_mem_map = wl->target_mem_map; | 536 | struct wl1251_acx_mem_map *wl_mem_map = wl->target_mem_map; |
534 | int ret, i; | 537 | int ret, i; |
535 | 538 | ||
536 | wl12xx_debug(DEBUG_ACX, "acx tx queue config"); | 539 | wl12xx_debug(DEBUG_ACX, "acx tx queue config"); |
537 | 540 | ||
538 | config.header.id = ACX_TX_QUEUE_CFG; | 541 | config = kzalloc(sizeof(*config), GFP_KERNEL); |
539 | config.header.len = sizeof(struct acx_tx_queue_qos_config) - | 542 | if (!config) { |
540 | sizeof(struct acx_header); | 543 | ret = -ENOMEM; |
544 | goto out; | ||
545 | } | ||
541 | 546 | ||
542 | for (i = 0; i < MAX_NUM_OF_AC; i++) { | 547 | for (i = 0; i < MAX_NUM_OF_AC; i++) { |
543 | ret = wl1251_hw_init_txq_fill(i, &config, | 548 | ret = wl1251_hw_init_txq_fill(i, config, |
544 | wl_mem_map->num_tx_mem_blocks); | 549 | wl_mem_map->num_tx_mem_blocks); |
545 | if (ret < 0) | 550 | if (ret < 0) |
546 | return ret; | 551 | goto out; |
547 | 552 | ||
548 | ret = wl12xx_cmd_configure(wl, &config, sizeof(config)); | 553 | ret = wl12xx_cmd_configure(wl, ACX_TX_QUEUE_CFG, |
554 | config, sizeof(*config)); | ||
549 | if (ret < 0) | 555 | if (ret < 0) |
550 | return ret; | 556 | goto out; |
551 | } | 557 | } |
552 | 558 | ||
553 | return 0; | 559 | out: |
560 | kfree(config); | ||
561 | return ret; | ||
554 | } | 562 | } |
555 | 563 | ||
556 | static int wl1251_hw_init_data_path_config(struct wl12xx *wl) | 564 | static int wl1251_hw_init_data_path_config(struct wl12xx *wl) |