1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Driver for KeyStream wireless LAN cards. |
4 | * |
5 | * Copyright (C) 2005-2008 KeyStream Corp. |
6 | * Copyright (C) 2009 Renesas Technology Corp. |
7 | */ |
8 | |
9 | #include <crypto/hash.h> |
10 | #include <linux/circ_buf.h> |
11 | #include <linux/if_arp.h> |
12 | #include <net/iw_handler.h> |
13 | #include <uapi/linux/llc.h> |
14 | #include "eap_packet.h" |
15 | #include "ks_wlan.h" |
16 | #include "ks_hostif.h" |
17 | |
18 | #define MICHAEL_MIC_KEY_LEN 8 |
19 | #define MICHAEL_MIC_LEN 8 |
20 | |
21 | static inline void inc_smeqhead(struct ks_wlan_private *priv) |
22 | { |
23 | priv->sme_i.qhead = (priv->sme_i.qhead + 1) % SME_EVENT_BUFF_SIZE; |
24 | } |
25 | |
26 | static inline void inc_smeqtail(struct ks_wlan_private *priv) |
27 | { |
28 | priv->sme_i.qtail = (priv->sme_i.qtail + 1) % SME_EVENT_BUFF_SIZE; |
29 | } |
30 | |
31 | static inline unsigned int cnt_smeqbody(struct ks_wlan_private *priv) |
32 | { |
33 | return CIRC_CNT_TO_END(priv->sme_i.qhead, priv->sme_i.qtail, |
34 | SME_EVENT_BUFF_SIZE); |
35 | } |
36 | |
37 | static inline u8 get_byte(struct ks_wlan_private *priv) |
38 | { |
39 | u8 data; |
40 | |
41 | data = *priv->rxp++; |
42 | /* length check in advance ! */ |
43 | --(priv->rx_size); |
44 | return data; |
45 | } |
46 | |
47 | static inline u16 get_word(struct ks_wlan_private *priv) |
48 | { |
49 | u16 data; |
50 | |
51 | data = (get_byte(priv) & 0xff); |
52 | data |= ((get_byte(priv) << 8) & 0xff00); |
53 | return data; |
54 | } |
55 | |
56 | static inline u32 get_dword(struct ks_wlan_private *priv) |
57 | { |
58 | u32 data; |
59 | |
60 | data = (get_byte(priv) & 0xff); |
61 | data |= ((get_byte(priv) << 8) & 0x0000ff00); |
62 | data |= ((get_byte(priv) << 16) & 0x00ff0000); |
63 | data |= ((get_byte(priv) << 24) & 0xff000000); |
64 | return data; |
65 | } |
66 | |
67 | static void ks_wlan_hw_wakeup_task(struct work_struct *work) |
68 | { |
69 | struct ks_wlan_private *priv; |
70 | int ps_status; |
71 | long time_left; |
72 | |
73 | priv = container_of(work, struct ks_wlan_private, wakeup_work); |
74 | ps_status = atomic_read(v: &priv->psstatus.status); |
75 | |
76 | if (ps_status == PS_SNOOZE) { |
77 | ks_wlan_hw_wakeup_request(priv); |
78 | time_left = wait_for_completion_interruptible_timeout(x: &priv->psstatus.wakeup_wait, |
79 | timeout: msecs_to_jiffies(m: 20)); |
80 | if (time_left <= 0) { |
81 | netdev_dbg(priv->net_dev, "wake up timeout or interrupted !!!\n" ); |
82 | schedule_work(work: &priv->wakeup_work); |
83 | return; |
84 | } |
85 | } |
86 | } |
87 | |
88 | static void ks_wlan_do_power_save(struct ks_wlan_private *priv) |
89 | { |
90 | if (is_connect_status(status: priv->connect_status)) |
91 | hostif_sme_enqueue(priv, event: SME_POW_MNGMT_REQUEST); |
92 | else |
93 | priv->dev_state = DEVICE_STATE_READY; |
94 | } |
95 | |
96 | static |
97 | int get_current_ap(struct ks_wlan_private *priv, struct link_ap_info *ap_info) |
98 | { |
99 | struct local_ap *ap; |
100 | union iwreq_data wrqu; |
101 | struct net_device *netdev = priv->net_dev; |
102 | u8 size; |
103 | |
104 | ap = &priv->current_ap; |
105 | |
106 | if (is_disconnect_status(status: priv->connect_status)) { |
107 | memset(ap, 0, sizeof(struct local_ap)); |
108 | return -EPERM; |
109 | } |
110 | |
111 | ether_addr_copy(dst: ap->bssid, src: ap_info->bssid); |
112 | memcpy(ap->ssid.body, priv->reg.ssid.body, |
113 | priv->reg.ssid.size); |
114 | ap->ssid.size = priv->reg.ssid.size; |
115 | memcpy(ap->rate_set.body, ap_info->rate_set.body, |
116 | ap_info->rate_set.size); |
117 | ap->rate_set.size = ap_info->rate_set.size; |
118 | if (ap_info->ext_rate_set.size != 0) { |
119 | memcpy(&ap->rate_set.body[ap->rate_set.size], |
120 | ap_info->ext_rate_set.body, |
121 | ap_info->ext_rate_set.size); |
122 | ap->rate_set.size += ap_info->ext_rate_set.size; |
123 | } |
124 | ap->channel = ap_info->ds_parameter.channel; |
125 | ap->rssi = ap_info->rssi; |
126 | ap->sq = ap_info->sq; |
127 | ap->noise = ap_info->noise; |
128 | ap->capability = le16_to_cpu(ap_info->capability); |
129 | size = (ap_info->rsn.size <= RSN_IE_BODY_MAX) ? |
130 | ap_info->rsn.size : RSN_IE_BODY_MAX; |
131 | if ((ap_info->rsn_mode & RSN_MODE_WPA2) && |
132 | (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)) { |
133 | ap->rsn_ie.id = RSN_INFO_ELEM_ID; |
134 | ap->rsn_ie.size = size; |
135 | memcpy(ap->rsn_ie.body, ap_info->rsn.body, size); |
136 | } else if ((ap_info->rsn_mode & RSN_MODE_WPA) && |
137 | (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA)) { |
138 | ap->wpa_ie.id = WPA_INFO_ELEM_ID; |
139 | ap->wpa_ie.size = size; |
140 | memcpy(ap->wpa_ie.body, ap_info->rsn.body, size); |
141 | } else { |
142 | ap->rsn_ie.id = 0; |
143 | ap->rsn_ie.size = 0; |
144 | ap->wpa_ie.id = 0; |
145 | ap->wpa_ie.size = 0; |
146 | } |
147 | |
148 | wrqu.data.length = 0; |
149 | wrqu.data.flags = 0; |
150 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; |
151 | if (is_connect_status(status: priv->connect_status)) { |
152 | ether_addr_copy(dst: wrqu.ap_addr.sa_data, src: priv->current_ap.bssid); |
153 | netdev_dbg(priv->net_dev, |
154 | "IWEVENT: connect bssid=%pM\n" , |
155 | wrqu.ap_addr.sa_data); |
156 | wireless_send_event(dev: netdev, SIOCGIWAP, wrqu: &wrqu, NULL); |
157 | } |
158 | netdev_dbg(priv->net_dev, "Link AP\n" |
159 | "- bssid=%pM\n" |
160 | "- essid=%s\n" |
161 | "- rate_set=%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X\n" |
162 | "- channel=%d\n" |
163 | "- rssi=%d\n" |
164 | "- sq=%d\n" |
165 | "- capability=%04X\n" |
166 | "- rsn.mode=%d\n" |
167 | "- rsn.size=%d\n" |
168 | "- ext_rate_set_size=%d\n" |
169 | "- rate_set_size=%d\n" , |
170 | ap->bssid, |
171 | &ap->ssid.body[0], |
172 | ap->rate_set.body[0], ap->rate_set.body[1], |
173 | ap->rate_set.body[2], ap->rate_set.body[3], |
174 | ap->rate_set.body[4], ap->rate_set.body[5], |
175 | ap->rate_set.body[6], ap->rate_set.body[7], |
176 | ap->channel, ap->rssi, ap->sq, ap->capability, |
177 | ap_info->rsn_mode, ap_info->rsn.size, |
178 | ap_info->ext_rate_set.size, ap_info->rate_set.size); |
179 | |
180 | return 0; |
181 | } |
182 | |
183 | static u8 read_ie(unsigned char *bp, u8 max, u8 *body) |
184 | { |
185 | u8 size = (*(bp + 1) <= max) ? *(bp + 1) : max; |
186 | |
187 | memcpy(body, bp + 2, size); |
188 | return size; |
189 | } |
190 | |
191 | static int |
192 | michael_mic(u8 *key, u8 *data, unsigned int len, u8 priority, u8 *result) |
193 | { |
194 | u8 pad_data[4] = { priority, 0, 0, 0 }; |
195 | struct crypto_shash *tfm = NULL; |
196 | struct shash_desc *desc = NULL; |
197 | int ret; |
198 | |
199 | tfm = crypto_alloc_shash(alg_name: "michael_mic" , type: 0, mask: 0); |
200 | if (IS_ERR(ptr: tfm)) { |
201 | ret = PTR_ERR(ptr: tfm); |
202 | goto err; |
203 | } |
204 | |
205 | ret = crypto_shash_setkey(tfm, key, MICHAEL_MIC_KEY_LEN); |
206 | if (ret < 0) |
207 | goto err_free_tfm; |
208 | |
209 | desc = kmalloc(size: sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL); |
210 | if (!desc) { |
211 | ret = -ENOMEM; |
212 | goto err_free_tfm; |
213 | } |
214 | |
215 | desc->tfm = tfm; |
216 | |
217 | ret = crypto_shash_init(desc); |
218 | if (ret < 0) |
219 | goto err_free_desc; |
220 | |
221 | // Compute the MIC value |
222 | /* |
223 | * IEEE802.11i page 47 |
224 | * Figure 43g TKIP MIC processing format |
225 | * +--+--+--------+--+----+--+--+--+--+--+--+--+--+ |
226 | * |6 |6 |1 |3 |M |1 |1 |1 |1 |1 |1 |1 |1 | Octet |
227 | * +--+--+--------+--+----+--+--+--+--+--+--+--+--+ |
228 | * |DA|SA|Priority|0 |Data|M0|M1|M2|M3|M4|M5|M6|M7| |
229 | * +--+--+--------+--+----+--+--+--+--+--+--+--+--+ |
230 | */ |
231 | |
232 | ret = crypto_shash_update(desc, data, len: 12); |
233 | if (ret < 0) |
234 | goto err_free_desc; |
235 | |
236 | ret = crypto_shash_update(desc, data: pad_data, len: 4); |
237 | if (ret < 0) |
238 | goto err_free_desc; |
239 | |
240 | ret = crypto_shash_finup(desc, data: data + 12, len: len - 12, out: result); |
241 | |
242 | err_free_desc: |
243 | kfree_sensitive(objp: desc); |
244 | |
245 | err_free_tfm: |
246 | crypto_free_shash(tfm); |
247 | |
248 | err: |
249 | return ret; |
250 | } |
251 | |
252 | static |
253 | int get_ap_information(struct ks_wlan_private *priv, struct ap_info *ap_info, |
254 | struct local_ap *ap) |
255 | { |
256 | unsigned char *bp; |
257 | int bsize, offset; |
258 | |
259 | memset(ap, 0, sizeof(struct local_ap)); |
260 | |
261 | ether_addr_copy(dst: ap->bssid, src: ap_info->bssid); |
262 | ap->rssi = ap_info->rssi; |
263 | ap->sq = ap_info->sq; |
264 | ap->noise = ap_info->noise; |
265 | ap->capability = le16_to_cpu(ap_info->capability); |
266 | ap->channel = ap_info->ch_info; |
267 | |
268 | bp = ap_info->body; |
269 | bsize = le16_to_cpu(ap_info->body_size); |
270 | offset = 0; |
271 | |
272 | while (bsize > offset) { |
273 | switch (*bp) { /* Information Element ID */ |
274 | case WLAN_EID_SSID: |
275 | ap->ssid.size = read_ie(bp, IEEE80211_MAX_SSID_LEN, |
276 | body: ap->ssid.body); |
277 | break; |
278 | case WLAN_EID_SUPP_RATES: |
279 | case WLAN_EID_EXT_SUPP_RATES: |
280 | if ((*(bp + 1) + ap->rate_set.size) <= |
281 | RATE_SET_MAX_SIZE) { |
282 | memcpy(&ap->rate_set.body[ap->rate_set.size], |
283 | bp + 2, *(bp + 1)); |
284 | ap->rate_set.size += *(bp + 1); |
285 | } else { |
286 | memcpy(&ap->rate_set.body[ap->rate_set.size], |
287 | bp + 2, |
288 | RATE_SET_MAX_SIZE - ap->rate_set.size); |
289 | ap->rate_set.size += |
290 | (RATE_SET_MAX_SIZE - ap->rate_set.size); |
291 | } |
292 | break; |
293 | case WLAN_EID_RSN: |
294 | ap->rsn_ie.id = *bp; |
295 | ap->rsn_ie.size = read_ie(bp, RSN_IE_BODY_MAX, |
296 | body: ap->rsn_ie.body); |
297 | break; |
298 | case WLAN_EID_VENDOR_SPECIFIC: /* WPA */ |
299 | /* WPA OUI check */ |
300 | if (memcmp(p: bp + 2, CIPHER_ID_WPA_WEP40, size: 4) == 0) { |
301 | ap->wpa_ie.id = *bp; |
302 | ap->wpa_ie.size = read_ie(bp, RSN_IE_BODY_MAX, |
303 | body: ap->wpa_ie.body); |
304 | } |
305 | break; |
306 | case WLAN_EID_DS_PARAMS: |
307 | case WLAN_EID_FH_PARAMS: |
308 | case WLAN_EID_CF_PARAMS: |
309 | case WLAN_EID_TIM: |
310 | case WLAN_EID_IBSS_PARAMS: |
311 | case WLAN_EID_COUNTRY: |
312 | case WLAN_EID_ERP_INFO: |
313 | break; |
314 | default: |
315 | netdev_err(dev: priv->net_dev, |
316 | format: "unknown Element ID=%d\n" , *bp); |
317 | break; |
318 | } |
319 | |
320 | offset += 2; /* id & size field */ |
321 | offset += *(bp + 1); /* +size offset */ |
322 | bp += (*(bp + 1) + 2); /* pointer update */ |
323 | } |
324 | |
325 | return 0; |
326 | } |
327 | |
328 | static |
329 | int hostif_data_indication_wpa(struct ks_wlan_private *priv, |
330 | unsigned short auth_type) |
331 | { |
332 | struct ether_hdr *eth_hdr; |
333 | unsigned short eth_proto; |
334 | unsigned char recv_mic[MICHAEL_MIC_LEN]; |
335 | char buf[128]; |
336 | unsigned long now; |
337 | struct mic_failure *mic_failure; |
338 | u8 mic[MICHAEL_MIC_LEN]; |
339 | union iwreq_data wrqu; |
340 | unsigned int key_index = auth_type - 1; |
341 | struct wpa_key *key = &priv->wpa.key[key_index]; |
342 | |
343 | eth_hdr = (struct ether_hdr *)(priv->rxp); |
344 | eth_proto = ntohs(eth_hdr->h_proto); |
345 | |
346 | if (eth_hdr->h_dest_snap != eth_hdr->h_source_snap) { |
347 | netdev_err(dev: priv->net_dev, format: "invalid data format\n" ); |
348 | priv->nstats.rx_errors++; |
349 | return -EINVAL; |
350 | } |
351 | if (((auth_type == TYPE_PMK1 && |
352 | priv->wpa.pairwise_suite == IW_AUTH_CIPHER_TKIP) || |
353 | (auth_type == TYPE_GMK1 && |
354 | priv->wpa.group_suite == IW_AUTH_CIPHER_TKIP) || |
355 | (auth_type == TYPE_GMK2 && |
356 | priv->wpa.group_suite == IW_AUTH_CIPHER_TKIP)) && |
357 | key->key_len) { |
358 | int ret; |
359 | |
360 | netdev_dbg(priv->net_dev, "TKIP: protocol=%04X: size=%u\n" , |
361 | eth_proto, priv->rx_size); |
362 | /* MIC save */ |
363 | memcpy(&recv_mic[0], |
364 | (priv->rxp) + ((priv->rx_size) - sizeof(recv_mic)), |
365 | sizeof(recv_mic)); |
366 | priv->rx_size = priv->rx_size - sizeof(recv_mic); |
367 | |
368 | ret = michael_mic(key: key->rx_mic_key, data: priv->rxp, len: priv->rx_size, |
369 | priority: 0, result: mic); |
370 | if (ret < 0) |
371 | return ret; |
372 | if (memcmp(p: mic, q: recv_mic, size: sizeof(mic)) != 0) { |
373 | now = jiffies; |
374 | mic_failure = &priv->wpa.mic_failure; |
375 | /* MIC FAILURE */ |
376 | if (mic_failure->last_failure_time && |
377 | (now - mic_failure->last_failure_time) / HZ >= 60) { |
378 | mic_failure->failure = 0; |
379 | } |
380 | netdev_err(dev: priv->net_dev, format: "MIC FAILURE\n" ); |
381 | if (mic_failure->failure == 0) { |
382 | mic_failure->failure = 1; |
383 | mic_failure->counter = 0; |
384 | } else if (mic_failure->failure == 1) { |
385 | mic_failure->failure = 2; |
386 | mic_failure->counter = |
387 | (u16)((now - mic_failure->last_failure_time) / HZ); |
388 | /* range 1-60 */ |
389 | if (!mic_failure->counter) |
390 | mic_failure->counter = 1; |
391 | } |
392 | priv->wpa.mic_failure.last_failure_time = now; |
393 | |
394 | /* needed parameters: count, keyid, key type, TSC */ |
395 | sprintf(buf, |
396 | fmt: "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr=%pM)" , |
397 | key_index, |
398 | eth_hdr->h_dest[0] & 0x01 ? "broad" : "uni" , |
399 | eth_hdr->h_source); |
400 | memset(&wrqu, 0, sizeof(wrqu)); |
401 | wrqu.data.length = strlen(buf); |
402 | wireless_send_event(dev: priv->net_dev, IWEVCUSTOM, wrqu: &wrqu, |
403 | extra: buf); |
404 | return -EINVAL; |
405 | } |
406 | } |
407 | return 0; |
408 | } |
409 | |
410 | static |
411 | void hostif_data_indication(struct ks_wlan_private *priv) |
412 | { |
413 | unsigned int rx_ind_size; /* indicate data size */ |
414 | struct sk_buff *skb; |
415 | u16 auth_type; |
416 | unsigned char temp[256]; |
417 | struct ether_hdr *eth_hdr; |
418 | struct ieee802_1x_hdr *aa1x_hdr; |
419 | size_t size; |
420 | int ret; |
421 | |
422 | /* min length check */ |
423 | if (priv->rx_size <= ETH_HLEN) { |
424 | priv->nstats.rx_errors++; |
425 | return; |
426 | } |
427 | |
428 | auth_type = get_word(priv); /* AuthType */ |
429 | get_word(priv); /* Reserve Area */ |
430 | |
431 | eth_hdr = (struct ether_hdr *)(priv->rxp); |
432 | |
433 | /* source address check */ |
434 | if (ether_addr_equal(addr1: &priv->eth_addr[0], addr2: eth_hdr->h_source)) { |
435 | netdev_err(dev: priv->net_dev, format: "invalid : source is own mac address !!\n" ); |
436 | netdev_err(dev: priv->net_dev, format: "eth_hdrernet->h_dest=%pM\n" , eth_hdr->h_source); |
437 | priv->nstats.rx_errors++; |
438 | return; |
439 | } |
440 | |
441 | /* for WPA */ |
442 | if (auth_type != TYPE_DATA && priv->wpa.rsn_enabled) { |
443 | ret = hostif_data_indication_wpa(priv, auth_type); |
444 | if (ret) |
445 | return; |
446 | } |
447 | |
448 | if ((priv->connect_status & FORCE_DISCONNECT) || |
449 | priv->wpa.mic_failure.failure == 2) { |
450 | return; |
451 | } |
452 | |
453 | /* check 13th byte at rx data */ |
454 | switch (*(priv->rxp + 12)) { |
455 | case LLC_SAP_SNAP: |
456 | rx_ind_size = priv->rx_size - 6; |
457 | skb = dev_alloc_skb(length: rx_ind_size); |
458 | if (!skb) { |
459 | priv->nstats.rx_dropped++; |
460 | return; |
461 | } |
462 | netdev_dbg(priv->net_dev, "SNAP, rx_ind_size = %d\n" , |
463 | rx_ind_size); |
464 | |
465 | size = ETH_ALEN * 2; |
466 | skb_put_data(skb, data: priv->rxp, len: size); |
467 | |
468 | /* (SNAP+UI..) skip */ |
469 | |
470 | size = rx_ind_size - (ETH_ALEN * 2); |
471 | skb_put_data(skb, data: ð_hdr->h_proto, len: size); |
472 | |
473 | aa1x_hdr = (struct ieee802_1x_hdr *)(priv->rxp + ETHER_HDR_SIZE); |
474 | break; |
475 | case LLC_SAP_NETBEUI: |
476 | rx_ind_size = (priv->rx_size + 2); |
477 | skb = dev_alloc_skb(length: rx_ind_size); |
478 | if (!skb) { |
479 | priv->nstats.rx_dropped++; |
480 | return; |
481 | } |
482 | netdev_dbg(priv->net_dev, "NETBEUI/NetBIOS rx_ind_size=%d\n" , |
483 | rx_ind_size); |
484 | |
485 | /* 8802/FDDI MAC copy */ |
486 | skb_put_data(skb, data: priv->rxp, len: 12); |
487 | |
488 | /* NETBEUI size add */ |
489 | temp[0] = (((rx_ind_size - 12) >> 8) & 0xff); |
490 | temp[1] = ((rx_ind_size - 12) & 0xff); |
491 | skb_put_data(skb, data: temp, len: 2); |
492 | |
493 | /* copy after Type */ |
494 | skb_put_data(skb, data: priv->rxp + 12, len: rx_ind_size - 14); |
495 | |
496 | aa1x_hdr = (struct ieee802_1x_hdr *)(priv->rxp + 14); |
497 | break; |
498 | default: /* other rx data */ |
499 | netdev_err(dev: priv->net_dev, format: "invalid data format\n" ); |
500 | priv->nstats.rx_errors++; |
501 | return; |
502 | } |
503 | |
504 | if (aa1x_hdr->type == IEEE802_1X_TYPE_EAPOL_KEY && |
505 | priv->wpa.rsn_enabled) |
506 | atomic_set(v: &priv->psstatus.snooze_guard, i: 1); |
507 | |
508 | /* rx indication */ |
509 | skb->dev = priv->net_dev; |
510 | skb->protocol = eth_type_trans(skb, dev: skb->dev); |
511 | priv->nstats.rx_packets++; |
512 | priv->nstats.rx_bytes += rx_ind_size; |
513 | netif_rx(skb); |
514 | } |
515 | |
516 | static |
517 | void hostif_mib_get_confirm(struct ks_wlan_private *priv) |
518 | { |
519 | struct net_device *dev = priv->net_dev; |
520 | u32 mib_status; |
521 | u32 mib_attribute; |
522 | |
523 | mib_status = get_dword(priv); |
524 | mib_attribute = get_dword(priv); |
525 | get_word(priv); /* mib_val_size */ |
526 | get_word(priv); /* mib_val_type */ |
527 | |
528 | if (mib_status) { |
529 | netdev_err(dev: priv->net_dev, format: "attribute=%08X, status=%08X\n" , |
530 | mib_attribute, mib_status); |
531 | return; |
532 | } |
533 | |
534 | switch (mib_attribute) { |
535 | case DOT11_MAC_ADDRESS: |
536 | hostif_sme_enqueue(priv, event: SME_GET_MAC_ADDRESS); |
537 | ether_addr_copy(dst: priv->eth_addr, src: priv->rxp); |
538 | priv->mac_address_valid = true; |
539 | eth_hw_addr_set(dev, addr: priv->eth_addr); |
540 | netdev_info(dev, format: "MAC ADDRESS = %pM\n" , priv->eth_addr); |
541 | break; |
542 | case DOT11_PRODUCT_VERSION: |
543 | priv->version_size = priv->rx_size; |
544 | memcpy(priv->firmware_version, priv->rxp, priv->rx_size); |
545 | priv->firmware_version[priv->rx_size] = '\0'; |
546 | netdev_info(dev, format: "firmware ver. = %s\n" , |
547 | priv->firmware_version); |
548 | hostif_sme_enqueue(priv, event: SME_GET_PRODUCT_VERSION); |
549 | /* wake_up_interruptible_all(&priv->confirm_wait); */ |
550 | complete(&priv->confirm_wait); |
551 | break; |
552 | case LOCAL_GAIN: |
553 | memcpy(&priv->gain, priv->rxp, sizeof(priv->gain)); |
554 | netdev_dbg(priv->net_dev, "tx_mode=%d, rx_mode=%d, tx_gain=%d, rx_gain=%d\n" , |
555 | priv->gain.tx_mode, priv->gain.rx_mode, |
556 | priv->gain.tx_gain, priv->gain.rx_gain); |
557 | break; |
558 | case LOCAL_EEPROM_SUM: |
559 | memcpy(&priv->eeprom_sum, priv->rxp, sizeof(priv->eeprom_sum)); |
560 | if (priv->eeprom_sum.type != 0 && |
561 | priv->eeprom_sum.type != 1) { |
562 | netdev_err(dev, format: "LOCAL_EEPROM_SUM error!\n" ); |
563 | return; |
564 | } |
565 | priv->eeprom_checksum = (priv->eeprom_sum.type == 0) ? |
566 | EEPROM_CHECKSUM_NONE : |
567 | (priv->eeprom_sum.result == 0) ? |
568 | EEPROM_NG : EEPROM_OK; |
569 | break; |
570 | default: |
571 | netdev_err(dev: priv->net_dev, format: "mib_attribute=%08x\n" , |
572 | (unsigned int)mib_attribute); |
573 | break; |
574 | } |
575 | } |
576 | |
577 | static |
578 | void hostif_mib_set_confirm(struct ks_wlan_private *priv) |
579 | { |
580 | u32 mib_status; |
581 | u32 mib_attribute; |
582 | |
583 | mib_status = get_dword(priv); |
584 | mib_attribute = get_dword(priv); |
585 | |
586 | if (mib_status) { |
587 | /* in case of error */ |
588 | netdev_err(dev: priv->net_dev, format: "error :: attribute=%08X, status=%08X\n" , |
589 | mib_attribute, mib_status); |
590 | } |
591 | |
592 | switch (mib_attribute) { |
593 | case DOT11_RTS_THRESHOLD: |
594 | hostif_sme_enqueue(priv, event: SME_RTS_THRESHOLD_CONFIRM); |
595 | break; |
596 | case DOT11_FRAGMENTATION_THRESHOLD: |
597 | hostif_sme_enqueue(priv, event: SME_FRAGMENTATION_THRESHOLD_CONFIRM); |
598 | break; |
599 | case DOT11_WEP_DEFAULT_KEY_ID: |
600 | if (!priv->wpa.wpa_enabled) |
601 | hostif_sme_enqueue(priv, event: SME_WEP_INDEX_CONFIRM); |
602 | break; |
603 | case DOT11_WEP_DEFAULT_KEY_VALUE1: |
604 | if (priv->wpa.rsn_enabled) |
605 | hostif_sme_enqueue(priv, event: SME_SET_PMK_TSC); |
606 | else |
607 | hostif_sme_enqueue(priv, event: SME_WEP_KEY1_CONFIRM); |
608 | break; |
609 | case DOT11_WEP_DEFAULT_KEY_VALUE2: |
610 | if (priv->wpa.rsn_enabled) |
611 | hostif_sme_enqueue(priv, event: SME_SET_GMK1_TSC); |
612 | else |
613 | hostif_sme_enqueue(priv, event: SME_WEP_KEY2_CONFIRM); |
614 | break; |
615 | case DOT11_WEP_DEFAULT_KEY_VALUE3: |
616 | if (priv->wpa.rsn_enabled) |
617 | hostif_sme_enqueue(priv, event: SME_SET_GMK2_TSC); |
618 | else |
619 | hostif_sme_enqueue(priv, event: SME_WEP_KEY3_CONFIRM); |
620 | break; |
621 | case DOT11_WEP_DEFAULT_KEY_VALUE4: |
622 | if (!priv->wpa.rsn_enabled) |
623 | hostif_sme_enqueue(priv, event: SME_WEP_KEY4_CONFIRM); |
624 | break; |
625 | case DOT11_PRIVACY_INVOKED: |
626 | if (!priv->wpa.rsn_enabled) |
627 | hostif_sme_enqueue(priv, event: SME_WEP_FLAG_CONFIRM); |
628 | break; |
629 | case DOT11_RSN_ENABLED: |
630 | hostif_sme_enqueue(priv, event: SME_RSN_ENABLED_CONFIRM); |
631 | break; |
632 | case LOCAL_RSN_MODE: |
633 | hostif_sme_enqueue(priv, event: SME_RSN_MODE_CONFIRM); |
634 | break; |
635 | case LOCAL_MULTICAST_ADDRESS: |
636 | hostif_sme_enqueue(priv, event: SME_MULTICAST_REQUEST); |
637 | break; |
638 | case LOCAL_MULTICAST_FILTER: |
639 | hostif_sme_enqueue(priv, event: SME_MULTICAST_CONFIRM); |
640 | break; |
641 | case LOCAL_CURRENTADDRESS: |
642 | priv->mac_address_valid = true; |
643 | break; |
644 | case DOT11_RSN_CONFIG_MULTICAST_CIPHER: |
645 | hostif_sme_enqueue(priv, event: SME_RSN_MCAST_CONFIRM); |
646 | break; |
647 | case DOT11_RSN_CONFIG_UNICAST_CIPHER: |
648 | hostif_sme_enqueue(priv, event: SME_RSN_UCAST_CONFIRM); |
649 | break; |
650 | case DOT11_RSN_CONFIG_AUTH_SUITE: |
651 | hostif_sme_enqueue(priv, event: SME_RSN_AUTH_CONFIRM); |
652 | break; |
653 | case DOT11_GMK1_TSC: |
654 | if (atomic_read(v: &priv->psstatus.snooze_guard)) |
655 | atomic_set(v: &priv->psstatus.snooze_guard, i: 0); |
656 | break; |
657 | case DOT11_GMK2_TSC: |
658 | if (atomic_read(v: &priv->psstatus.snooze_guard)) |
659 | atomic_set(v: &priv->psstatus.snooze_guard, i: 0); |
660 | break; |
661 | case DOT11_PMK_TSC: |
662 | case LOCAL_PMK: |
663 | case LOCAL_GAIN: |
664 | case LOCAL_WPS_ENABLE: |
665 | case LOCAL_WPS_PROBE_REQ: |
666 | case LOCAL_REGION: |
667 | default: |
668 | break; |
669 | } |
670 | } |
671 | |
672 | static |
673 | void hostif_power_mgmt_confirm(struct ks_wlan_private *priv) |
674 | { |
675 | if (priv->reg.power_mgmt > POWER_MGMT_ACTIVE && |
676 | priv->reg.operation_mode == MODE_INFRASTRUCTURE) { |
677 | atomic_set(v: &priv->psstatus.confirm_wait, i: 0); |
678 | priv->dev_state = DEVICE_STATE_SLEEP; |
679 | ks_wlan_hw_power_save(priv); |
680 | } else { |
681 | priv->dev_state = DEVICE_STATE_READY; |
682 | } |
683 | } |
684 | |
685 | static |
686 | void hostif_sleep_confirm(struct ks_wlan_private *priv) |
687 | { |
688 | atomic_set(v: &priv->sleepstatus.doze_request, i: 1); |
689 | queue_delayed_work(wq: priv->wq, dwork: &priv->rw_dwork, delay: 1); |
690 | } |
691 | |
692 | static |
693 | void hostif_start_confirm(struct ks_wlan_private *priv) |
694 | { |
695 | union iwreq_data wrqu; |
696 | |
697 | wrqu.data.length = 0; |
698 | wrqu.data.flags = 0; |
699 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; |
700 | if (is_connect_status(status: priv->connect_status)) { |
701 | eth_zero_addr(addr: wrqu.ap_addr.sa_data); |
702 | wireless_send_event(dev: priv->net_dev, SIOCGIWAP, wrqu: &wrqu, NULL); |
703 | } |
704 | netdev_dbg(priv->net_dev, " scan_ind_count=%d\n" , priv->scan_ind_count); |
705 | hostif_sme_enqueue(priv, event: SME_START_CONFIRM); |
706 | } |
707 | |
708 | static |
709 | void hostif_connect_indication(struct ks_wlan_private *priv) |
710 | { |
711 | u16 connect_code; |
712 | unsigned int tmp = 0; |
713 | unsigned int old_status = priv->connect_status; |
714 | struct net_device *netdev = priv->net_dev; |
715 | union iwreq_data wrqu0; |
716 | |
717 | connect_code = get_word(priv); |
718 | |
719 | switch (connect_code) { |
720 | case RESULT_CONNECT: |
721 | if (!(priv->connect_status & FORCE_DISCONNECT)) |
722 | netif_carrier_on(dev: netdev); |
723 | tmp = FORCE_DISCONNECT & priv->connect_status; |
724 | priv->connect_status = tmp + CONNECT_STATUS; |
725 | break; |
726 | case RESULT_DISCONNECT: |
727 | netif_carrier_off(dev: netdev); |
728 | tmp = FORCE_DISCONNECT & priv->connect_status; |
729 | priv->connect_status = tmp + DISCONNECT_STATUS; |
730 | break; |
731 | default: |
732 | netdev_dbg(priv->net_dev, "unknown connect_code=%d :: scan_ind_count=%d\n" , |
733 | connect_code, priv->scan_ind_count); |
734 | netif_carrier_off(dev: netdev); |
735 | tmp = FORCE_DISCONNECT & priv->connect_status; |
736 | priv->connect_status = tmp + DISCONNECT_STATUS; |
737 | break; |
738 | } |
739 | |
740 | get_current_ap(priv, ap_info: (struct link_ap_info *)priv->rxp); |
741 | if (is_connect_status(status: priv->connect_status) && |
742 | is_disconnect_status(status: old_status)) { |
743 | /* for power save */ |
744 | atomic_set(v: &priv->psstatus.snooze_guard, i: 0); |
745 | atomic_set(v: &priv->psstatus.confirm_wait, i: 0); |
746 | } |
747 | ks_wlan_do_power_save(priv); |
748 | |
749 | wrqu0.data.length = 0; |
750 | wrqu0.data.flags = 0; |
751 | wrqu0.ap_addr.sa_family = ARPHRD_ETHER; |
752 | if (is_disconnect_status(status: priv->connect_status) && |
753 | is_connect_status(status: old_status)) { |
754 | eth_zero_addr(addr: wrqu0.ap_addr.sa_data); |
755 | netdev_dbg(priv->net_dev, "disconnect :: scan_ind_count=%d\n" , |
756 | priv->scan_ind_count); |
757 | wireless_send_event(dev: netdev, SIOCGIWAP, wrqu: &wrqu0, NULL); |
758 | } |
759 | priv->scan_ind_count = 0; |
760 | } |
761 | |
762 | static |
763 | void hostif_scan_indication(struct ks_wlan_private *priv) |
764 | { |
765 | int i; |
766 | struct ap_info *ap_info; |
767 | |
768 | netdev_dbg(priv->net_dev, |
769 | "scan_ind_count = %d\n" , priv->scan_ind_count); |
770 | ap_info = (struct ap_info *)(priv->rxp); |
771 | |
772 | if (priv->scan_ind_count) { |
773 | /* bssid check */ |
774 | for (i = 0; i < priv->aplist.size; i++) { |
775 | u8 *bssid = priv->aplist.ap[i].bssid; |
776 | |
777 | if (ether_addr_equal(addr1: ap_info->bssid, addr2: bssid)) |
778 | continue; |
779 | |
780 | if (ap_info->frame_type == IEEE80211_STYPE_PROBE_RESP) |
781 | get_ap_information(priv, ap_info, |
782 | ap: &priv->aplist.ap[i]); |
783 | return; |
784 | } |
785 | } |
786 | priv->scan_ind_count++; |
787 | if (priv->scan_ind_count < LOCAL_APLIST_MAX + 1) { |
788 | netdev_dbg(priv->net_dev, " scan_ind_count=%d :: aplist.size=%d\n" , |
789 | priv->scan_ind_count, priv->aplist.size); |
790 | get_ap_information(priv, ap_info: (struct ap_info *)(priv->rxp), |
791 | ap: &priv->aplist.ap[priv->scan_ind_count - 1]); |
792 | priv->aplist.size = priv->scan_ind_count; |
793 | } else { |
794 | netdev_dbg(priv->net_dev, " count over :: scan_ind_count=%d\n" , |
795 | priv->scan_ind_count); |
796 | } |
797 | } |
798 | |
799 | static |
800 | void hostif_stop_confirm(struct ks_wlan_private *priv) |
801 | { |
802 | unsigned int tmp = 0; |
803 | unsigned int old_status = priv->connect_status; |
804 | struct net_device *netdev = priv->net_dev; |
805 | union iwreq_data wrqu0; |
806 | |
807 | if (priv->dev_state == DEVICE_STATE_SLEEP) |
808 | priv->dev_state = DEVICE_STATE_READY; |
809 | |
810 | /* disconnect indication */ |
811 | if (is_connect_status(status: priv->connect_status)) { |
812 | netif_carrier_off(dev: netdev); |
813 | tmp = FORCE_DISCONNECT & priv->connect_status; |
814 | priv->connect_status = tmp | DISCONNECT_STATUS; |
815 | netdev_info(dev: netdev, format: "IWEVENT: disconnect\n" ); |
816 | |
817 | wrqu0.data.length = 0; |
818 | wrqu0.data.flags = 0; |
819 | wrqu0.ap_addr.sa_family = ARPHRD_ETHER; |
820 | if (is_disconnect_status(status: priv->connect_status) && |
821 | is_connect_status(status: old_status)) { |
822 | eth_zero_addr(addr: wrqu0.ap_addr.sa_data); |
823 | netdev_info(dev: netdev, format: "IWEVENT: disconnect\n" ); |
824 | wireless_send_event(dev: netdev, SIOCGIWAP, wrqu: &wrqu0, NULL); |
825 | } |
826 | priv->scan_ind_count = 0; |
827 | } |
828 | |
829 | hostif_sme_enqueue(priv, event: SME_STOP_CONFIRM); |
830 | } |
831 | |
832 | static |
833 | void hostif_ps_adhoc_set_confirm(struct ks_wlan_private *priv) |
834 | { |
835 | priv->infra_status = 0; /* infrastructure mode cancel */ |
836 | hostif_sme_enqueue(priv, event: SME_MODE_SET_CONFIRM); |
837 | } |
838 | |
839 | static |
840 | void hostif_infrastructure_set_confirm(struct ks_wlan_private *priv) |
841 | { |
842 | get_word(priv); /* result_code */ |
843 | priv->infra_status = 1; /* infrastructure mode set */ |
844 | hostif_sme_enqueue(priv, event: SME_MODE_SET_CONFIRM); |
845 | } |
846 | |
847 | static |
848 | void hostif_adhoc_set_confirm(struct ks_wlan_private *priv) |
849 | { |
850 | priv->infra_status = 1; /* infrastructure mode set */ |
851 | hostif_sme_enqueue(priv, event: SME_MODE_SET_CONFIRM); |
852 | } |
853 | |
854 | static |
855 | void hostif_associate_indication(struct ks_wlan_private *priv) |
856 | { |
857 | struct association_request *assoc_req; |
858 | struct association_response *assoc_resp; |
859 | unsigned char *pb; |
860 | union iwreq_data wrqu; |
861 | char buf[IW_CUSTOM_MAX]; |
862 | char *pbuf = &buf[0]; |
863 | int i; |
864 | |
865 | static const char associnfo_leader0[] = "ASSOCINFO(ReqIEs=" ; |
866 | static const char associnfo_leader1[] = " RespIEs=" ; |
867 | |
868 | assoc_req = (struct association_request *)(priv->rxp); |
869 | assoc_resp = (struct association_response *)(assoc_req + 1); |
870 | pb = (unsigned char *)(assoc_resp + 1); |
871 | |
872 | memset(&wrqu, 0, sizeof(wrqu)); |
873 | memcpy(pbuf, associnfo_leader0, sizeof(associnfo_leader0) - 1); |
874 | wrqu.data.length += sizeof(associnfo_leader0) - 1; |
875 | pbuf += sizeof(associnfo_leader0) - 1; |
876 | |
877 | for (i = 0; i < le16_to_cpu(assoc_req->req_ies_size); i++) |
878 | pbuf += sprintf(buf: pbuf, fmt: "%02x" , *(pb + i)); |
879 | wrqu.data.length += (le16_to_cpu(assoc_req->req_ies_size)) * 2; |
880 | |
881 | memcpy(pbuf, associnfo_leader1, sizeof(associnfo_leader1) - 1); |
882 | wrqu.data.length += sizeof(associnfo_leader1) - 1; |
883 | pbuf += sizeof(associnfo_leader1) - 1; |
884 | |
885 | pb += le16_to_cpu(assoc_req->req_ies_size); |
886 | for (i = 0; i < le16_to_cpu(assoc_resp->resp_ies_size); i++) |
887 | pbuf += sprintf(buf: pbuf, fmt: "%02x" , *(pb + i)); |
888 | wrqu.data.length += (le16_to_cpu(assoc_resp->resp_ies_size)) * 2; |
889 | |
890 | pbuf += sprintf(buf: pbuf, fmt: ")" ); |
891 | wrqu.data.length += 1; |
892 | |
893 | wireless_send_event(dev: priv->net_dev, IWEVCUSTOM, wrqu: &wrqu, extra: buf); |
894 | } |
895 | |
896 | static |
897 | void hostif_bss_scan_confirm(struct ks_wlan_private *priv) |
898 | { |
899 | u32 result_code; |
900 | struct net_device *dev = priv->net_dev; |
901 | union iwreq_data wrqu; |
902 | |
903 | result_code = get_dword(priv); |
904 | netdev_dbg(priv->net_dev, "result=%d :: scan_ind_count=%d\n" , |
905 | result_code, priv->scan_ind_count); |
906 | |
907 | priv->sme_i.sme_flag &= ~SME_AP_SCAN; |
908 | hostif_sme_enqueue(priv, event: SME_BSS_SCAN_CONFIRM); |
909 | |
910 | wrqu.data.length = 0; |
911 | wrqu.data.flags = 0; |
912 | wireless_send_event(dev, SIOCGIWSCAN, wrqu: &wrqu, NULL); |
913 | priv->scan_ind_count = 0; |
914 | } |
915 | |
916 | static |
917 | void hostif_phy_information_confirm(struct ks_wlan_private *priv) |
918 | { |
919 | struct iw_statistics *wstats = &priv->wstats; |
920 | u8 , signal; |
921 | u8 link_speed; |
922 | u32 transmitted_frame_count, received_fragment_count; |
923 | u32 failed_count, fcs_error_count; |
924 | |
925 | rssi = get_byte(priv); |
926 | signal = get_byte(priv); |
927 | get_byte(priv); /* noise */ |
928 | link_speed = get_byte(priv); |
929 | transmitted_frame_count = get_dword(priv); |
930 | received_fragment_count = get_dword(priv); |
931 | failed_count = get_dword(priv); |
932 | fcs_error_count = get_dword(priv); |
933 | |
934 | netdev_dbg(priv->net_dev, "phyinfo confirm rssi=%d signal=%d\n" , |
935 | rssi, signal); |
936 | priv->current_rate = (link_speed & RATE_MASK); |
937 | wstats->qual.qual = signal; |
938 | wstats->qual.level = 256 - rssi; |
939 | wstats->qual.noise = 0; /* invalid noise value */ |
940 | wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; |
941 | |
942 | netdev_dbg(priv->net_dev, "\n rssi=%u\n" |
943 | " signal=%u\n" |
944 | " link_speed=%ux500Kbps\n" |
945 | " transmitted_frame_count=%u\n" |
946 | " received_fragment_count=%u\n" |
947 | " failed_count=%u\n" |
948 | " fcs_error_count=%u\n" , |
949 | rssi, signal, link_speed, transmitted_frame_count, |
950 | received_fragment_count, failed_count, fcs_error_count); |
951 | /* wake_up_interruptible_all(&priv->confirm_wait); */ |
952 | complete(&priv->confirm_wait); |
953 | } |
954 | |
955 | static |
956 | void hostif_mic_failure_confirm(struct ks_wlan_private *priv) |
957 | { |
958 | netdev_dbg(priv->net_dev, "mic_failure=%u\n" , |
959 | priv->wpa.mic_failure.failure); |
960 | hostif_sme_enqueue(priv, event: SME_MIC_FAILURE_CONFIRM); |
961 | } |
962 | |
963 | static |
964 | void hostif_event_check(struct ks_wlan_private *priv) |
965 | { |
966 | u16 event; |
967 | |
968 | event = get_word(priv); |
969 | switch (event) { |
970 | case HIF_DATA_IND: |
971 | hostif_data_indication(priv); |
972 | break; |
973 | case HIF_MIB_GET_CONF: |
974 | hostif_mib_get_confirm(priv); |
975 | break; |
976 | case HIF_MIB_SET_CONF: |
977 | hostif_mib_set_confirm(priv); |
978 | break; |
979 | case HIF_POWER_MGMT_CONF: |
980 | hostif_power_mgmt_confirm(priv); |
981 | break; |
982 | case HIF_SLEEP_CONF: |
983 | hostif_sleep_confirm(priv); |
984 | break; |
985 | case HIF_START_CONF: |
986 | hostif_start_confirm(priv); |
987 | break; |
988 | case HIF_CONNECT_IND: |
989 | hostif_connect_indication(priv); |
990 | break; |
991 | case HIF_STOP_CONF: |
992 | hostif_stop_confirm(priv); |
993 | break; |
994 | case HIF_PS_ADH_SET_CONF: |
995 | hostif_ps_adhoc_set_confirm(priv); |
996 | break; |
997 | case HIF_INFRA_SET_CONF: |
998 | case HIF_INFRA_SET2_CONF: |
999 | hostif_infrastructure_set_confirm(priv); |
1000 | break; |
1001 | case HIF_ADH_SET_CONF: |
1002 | case HIF_ADH_SET2_CONF: |
1003 | hostif_adhoc_set_confirm(priv); |
1004 | break; |
1005 | case HIF_ASSOC_INFO_IND: |
1006 | hostif_associate_indication(priv); |
1007 | break; |
1008 | case HIF_MIC_FAILURE_CONF: |
1009 | hostif_mic_failure_confirm(priv); |
1010 | break; |
1011 | case HIF_SCAN_CONF: |
1012 | hostif_bss_scan_confirm(priv); |
1013 | break; |
1014 | case HIF_PHY_INFO_CONF: |
1015 | case HIF_PHY_INFO_IND: |
1016 | hostif_phy_information_confirm(priv); |
1017 | break; |
1018 | case HIF_SCAN_IND: |
1019 | hostif_scan_indication(priv); |
1020 | break; |
1021 | case HIF_AP_SET_CONF: |
1022 | default: |
1023 | netdev_err(dev: priv->net_dev, format: "undefined event[%04X]\n" , event); |
1024 | /* wake_up_all(&priv->confirm_wait); */ |
1025 | complete(&priv->confirm_wait); |
1026 | break; |
1027 | } |
1028 | |
1029 | /* add event to hostt buffer */ |
1030 | priv->hostt.buff[priv->hostt.qtail] = event; |
1031 | priv->hostt.qtail = (priv->hostt.qtail + 1) % SME_EVENT_BUFF_SIZE; |
1032 | } |
1033 | |
1034 | /* allocate size bytes, set header size and event */ |
1035 | static void *hostif_generic_request(size_t size, int event) |
1036 | { |
1037 | struct hostif_hdr *p; |
1038 | |
1039 | p = kzalloc(size: hif_align_size(size), GFP_ATOMIC); |
1040 | if (!p) |
1041 | return NULL; |
1042 | |
1043 | p->size = cpu_to_le16(size - sizeof(p->size)); |
1044 | p->event = cpu_to_le16(event); |
1045 | |
1046 | return p; |
1047 | } |
1048 | |
1049 | int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *skb) |
1050 | { |
1051 | unsigned int skb_len = 0; |
1052 | unsigned char *buffer = NULL; |
1053 | unsigned int length = 0; |
1054 | struct hostif_data_request *pp; |
1055 | unsigned char *p; |
1056 | unsigned short eth_proto; |
1057 | struct ether_hdr *eth_hdr; |
1058 | unsigned short keyinfo = 0; |
1059 | struct ieee802_1x_hdr *aa1x_hdr; |
1060 | struct wpa_eapol_key *eap_key; |
1061 | struct ethhdr *eth; |
1062 | size_t size; |
1063 | int ret; |
1064 | |
1065 | skb_len = skb->len; |
1066 | if (skb_len > ETH_FRAME_LEN) { |
1067 | netdev_err(dev: priv->net_dev, format: "bad length skb_len=%d\n" , skb_len); |
1068 | ret = -EOVERFLOW; |
1069 | goto err_kfree_skb; |
1070 | } |
1071 | |
1072 | if (is_disconnect_status(status: priv->connect_status) || |
1073 | (priv->connect_status & FORCE_DISCONNECT) || |
1074 | priv->wpa.mic_failure.stop) { |
1075 | if (netif_queue_stopped(dev: priv->net_dev)) |
1076 | netif_wake_queue(dev: priv->net_dev); |
1077 | |
1078 | dev_kfree_skb(skb); |
1079 | |
1080 | return 0; |
1081 | } |
1082 | |
1083 | /* power save wakeup */ |
1084 | if (atomic_read(v: &priv->psstatus.status) == PS_SNOOZE) { |
1085 | if (!netif_queue_stopped(dev: priv->net_dev)) |
1086 | netif_stop_queue(dev: priv->net_dev); |
1087 | } |
1088 | |
1089 | size = sizeof(*pp) + 6 + skb_len + 8; |
1090 | pp = kmalloc(size: hif_align_size(size), GFP_ATOMIC); |
1091 | if (!pp) { |
1092 | ret = -ENOMEM; |
1093 | goto err_kfree_skb; |
1094 | } |
1095 | |
1096 | p = (unsigned char *)pp->data; |
1097 | |
1098 | buffer = skb->data; |
1099 | length = skb->len; |
1100 | |
1101 | /* skb check */ |
1102 | eth = (struct ethhdr *)skb->data; |
1103 | if (!ether_addr_equal(addr1: &priv->eth_addr[0], addr2: eth->h_source)) { |
1104 | netdev_err(dev: priv->net_dev, |
1105 | format: "Invalid mac address: ethernet->h_source=%pM\n" , |
1106 | eth->h_source); |
1107 | ret = -ENXIO; |
1108 | goto err_kfree; |
1109 | } |
1110 | |
1111 | /* dest and src MAC address copy */ |
1112 | size = ETH_ALEN * 2; |
1113 | memcpy(p, buffer, size); |
1114 | p += size; |
1115 | buffer += size; |
1116 | length -= size; |
1117 | |
1118 | /* EtherType/Length check */ |
1119 | if (*(buffer + 1) + (*buffer << 8) > 1500) { |
1120 | /* ProtocolEAP = *(buffer+1) + (*buffer << 8); */ |
1121 | /* SAP/CTL/OUI(6 byte) add */ |
1122 | *p++ = 0xAA; /* DSAP */ |
1123 | *p++ = 0xAA; /* SSAP */ |
1124 | *p++ = 0x03; /* CTL */ |
1125 | *p++ = 0x00; /* OUI ("000000") */ |
1126 | *p++ = 0x00; /* OUI ("000000") */ |
1127 | *p++ = 0x00; /* OUI ("000000") */ |
1128 | skb_len += 6; |
1129 | } else { |
1130 | /* Length(2 byte) delete */ |
1131 | buffer += 2; |
1132 | length -= 2; |
1133 | skb_len -= 2; |
1134 | } |
1135 | |
1136 | /* pp->data copy */ |
1137 | memcpy(p, buffer, length); |
1138 | |
1139 | p += length; |
1140 | |
1141 | /* for WPA */ |
1142 | eth_hdr = (struct ether_hdr *)&pp->data[0]; |
1143 | eth_proto = ntohs(eth_hdr->h_proto); |
1144 | |
1145 | /* for MIC FAILURE REPORT check */ |
1146 | if (eth_proto == ETH_P_PAE && |
1147 | priv->wpa.mic_failure.failure > 0) { |
1148 | aa1x_hdr = (struct ieee802_1x_hdr *)(eth_hdr + 1); |
1149 | if (aa1x_hdr->type == IEEE802_1X_TYPE_EAPOL_KEY) { |
1150 | eap_key = (struct wpa_eapol_key *)(aa1x_hdr + 1); |
1151 | keyinfo = ntohs(eap_key->key_info); |
1152 | } |
1153 | } |
1154 | |
1155 | if (priv->wpa.rsn_enabled && priv->wpa.key[0].key_len) { |
1156 | /* no encryption */ |
1157 | if (eth_proto == ETH_P_PAE && |
1158 | priv->wpa.key[1].key_len == 0 && |
1159 | priv->wpa.key[2].key_len == 0 && |
1160 | priv->wpa.key[3].key_len == 0) { |
1161 | pp->auth_type = cpu_to_le16(TYPE_AUTH); |
1162 | } else { |
1163 | if (priv->wpa.pairwise_suite == IW_AUTH_CIPHER_TKIP) { |
1164 | u8 mic[MICHAEL_MIC_LEN]; |
1165 | |
1166 | ret = michael_mic(key: priv->wpa.key[0].tx_mic_key, |
1167 | data: &pp->data[0], len: skb_len, |
1168 | priority: 0, result: mic); |
1169 | if (ret < 0) |
1170 | goto err_kfree; |
1171 | |
1172 | memcpy(p, mic, sizeof(mic)); |
1173 | length += sizeof(mic); |
1174 | skb_len += sizeof(mic); |
1175 | p += sizeof(mic); |
1176 | pp->auth_type = |
1177 | cpu_to_le16(TYPE_DATA); |
1178 | } else if (priv->wpa.pairwise_suite == |
1179 | IW_AUTH_CIPHER_CCMP) { |
1180 | pp->auth_type = |
1181 | cpu_to_le16(TYPE_DATA); |
1182 | } |
1183 | } |
1184 | } else { |
1185 | if (eth_proto == ETH_P_PAE) |
1186 | pp->auth_type = cpu_to_le16(TYPE_AUTH); |
1187 | else |
1188 | pp->auth_type = cpu_to_le16(TYPE_DATA); |
1189 | } |
1190 | |
1191 | /* header value set */ |
1192 | pp->header.size = |
1193 | cpu_to_le16((sizeof(*pp) - sizeof(pp->header.size) + skb_len)); |
1194 | pp->header.event = cpu_to_le16(HIF_DATA_REQ); |
1195 | |
1196 | /* tx request */ |
1197 | ret = ks_wlan_hw_tx(priv, p: pp, size: hif_align_size(size: sizeof(*pp) + skb_len), |
1198 | complete_handler: send_packet_complete, skb); |
1199 | |
1200 | /* MIC FAILURE REPORT check */ |
1201 | if (eth_proto == ETH_P_PAE && |
1202 | priv->wpa.mic_failure.failure > 0) { |
1203 | if (keyinfo & WPA_KEY_INFO_ERROR && |
1204 | keyinfo & WPA_KEY_INFO_REQUEST) { |
1205 | netdev_err(dev: priv->net_dev, |
1206 | format: "MIC ERROR Report SET : %04X\n" , keyinfo); |
1207 | hostif_sme_enqueue(priv, event: SME_MIC_FAILURE_REQUEST); |
1208 | } |
1209 | if (priv->wpa.mic_failure.failure == 2) |
1210 | priv->wpa.mic_failure.stop = 1; |
1211 | } |
1212 | |
1213 | return ret; |
1214 | |
1215 | err_kfree: |
1216 | kfree(objp: pp); |
1217 | err_kfree_skb: |
1218 | dev_kfree_skb(skb); |
1219 | |
1220 | return ret; |
1221 | } |
1222 | |
1223 | static inline void ps_confirm_wait_inc(struct ks_wlan_private *priv) |
1224 | { |
1225 | if (atomic_read(v: &priv->psstatus.status) > PS_ACTIVE_SET) |
1226 | atomic_inc(v: &priv->psstatus.confirm_wait); |
1227 | } |
1228 | |
1229 | static inline void send_request_to_device(struct ks_wlan_private *priv, |
1230 | void *data, size_t size) |
1231 | { |
1232 | ps_confirm_wait_inc(priv); |
1233 | ks_wlan_hw_tx(priv, p: data, size, NULL, NULL); |
1234 | } |
1235 | |
1236 | static void hostif_mib_get_request(struct ks_wlan_private *priv, |
1237 | u32 mib_attribute) |
1238 | { |
1239 | struct hostif_mib_get_request *pp; |
1240 | |
1241 | pp = hostif_generic_request(size: sizeof(*pp), HIF_MIB_GET_REQ); |
1242 | if (!pp) |
1243 | return; |
1244 | |
1245 | pp->mib_attribute = cpu_to_le32(mib_attribute); |
1246 | |
1247 | send_request_to_device(priv, data: pp, size: hif_align_size(size: sizeof(*pp))); |
1248 | } |
1249 | |
1250 | static void hostif_mib_set_request(struct ks_wlan_private *priv, |
1251 | enum mib_attribute attr, |
1252 | enum mib_data_type type, |
1253 | void *data, size_t size) |
1254 | { |
1255 | struct hostif_mib_set_request_t *pp; |
1256 | |
1257 | if (priv->dev_state < DEVICE_STATE_BOOT) |
1258 | return; |
1259 | |
1260 | pp = hostif_generic_request(size: sizeof(*pp), HIF_MIB_SET_REQ); |
1261 | if (!pp) |
1262 | return; |
1263 | |
1264 | pp->mib_attribute = cpu_to_le32(attr); |
1265 | pp->mib_value.size = cpu_to_le16(size); |
1266 | pp->mib_value.type = cpu_to_le16(type); |
1267 | memcpy(&pp->mib_value.body, data, size); |
1268 | |
1269 | send_request_to_device(priv, data: pp, size: hif_align_size(size: sizeof(*pp) + size)); |
1270 | } |
1271 | |
1272 | static inline void hostif_mib_set_request_int(struct ks_wlan_private *priv, |
1273 | enum mib_attribute attr, int val) |
1274 | { |
1275 | __le32 v = cpu_to_le32(val); |
1276 | size_t size = sizeof(v); |
1277 | |
1278 | hostif_mib_set_request(priv, attr, type: MIB_VALUE_TYPE_INT, data: &v, size); |
1279 | } |
1280 | |
1281 | static inline void hostif_mib_set_request_bool(struct ks_wlan_private *priv, |
1282 | enum mib_attribute attr, |
1283 | bool val) |
1284 | { |
1285 | __le32 v = cpu_to_le32(val); |
1286 | size_t size = sizeof(v); |
1287 | |
1288 | hostif_mib_set_request(priv, attr, type: MIB_VALUE_TYPE_BOOL, data: &v, size); |
1289 | } |
1290 | |
1291 | static inline void hostif_mib_set_request_ostring(struct ks_wlan_private *priv, |
1292 | enum mib_attribute attr, |
1293 | void *data, size_t size) |
1294 | { |
1295 | hostif_mib_set_request(priv, attr, type: MIB_VALUE_TYPE_OSTRING, data, size); |
1296 | } |
1297 | |
1298 | static |
1299 | void hostif_start_request(struct ks_wlan_private *priv, unsigned char mode) |
1300 | { |
1301 | struct hostif_start_request *pp; |
1302 | |
1303 | pp = hostif_generic_request(size: sizeof(*pp), HIF_START_REQ); |
1304 | if (!pp) |
1305 | return; |
1306 | |
1307 | pp->mode = cpu_to_le16(mode); |
1308 | |
1309 | send_request_to_device(priv, data: pp, size: hif_align_size(size: sizeof(*pp))); |
1310 | |
1311 | priv->aplist.size = 0; |
1312 | priv->scan_ind_count = 0; |
1313 | } |
1314 | |
1315 | static __le16 ks_wlan_cap(struct ks_wlan_private *priv) |
1316 | { |
1317 | u16 capability = 0x0000; |
1318 | |
1319 | if (priv->reg.preamble == SHORT_PREAMBLE) |
1320 | capability |= WLAN_CAPABILITY_SHORT_PREAMBLE; |
1321 | |
1322 | capability &= ~(WLAN_CAPABILITY_PBCC); /* pbcc not support */ |
1323 | |
1324 | if (priv->reg.phy_type != D_11B_ONLY_MODE) { |
1325 | capability |= WLAN_CAPABILITY_SHORT_SLOT_TIME; |
1326 | capability &= ~(WLAN_CAPABILITY_DSSS_OFDM); |
1327 | } |
1328 | |
1329 | return cpu_to_le16(capability); |
1330 | } |
1331 | |
1332 | static void init_request(struct ks_wlan_private *priv, |
1333 | struct hostif_request *req) |
1334 | { |
1335 | req->phy_type = cpu_to_le16(priv->reg.phy_type); |
1336 | req->cts_mode = cpu_to_le16(priv->reg.cts_mode); |
1337 | req->scan_type = cpu_to_le16(priv->reg.scan_type); |
1338 | req->rate_set.size = priv->reg.rate_set.size; |
1339 | req->capability = ks_wlan_cap(priv); |
1340 | memcpy(&req->rate_set.body[0], &priv->reg.rate_set.body[0], |
1341 | priv->reg.rate_set.size); |
1342 | } |
1343 | |
1344 | static |
1345 | void hostif_ps_adhoc_set_request(struct ks_wlan_private *priv) |
1346 | { |
1347 | struct hostif_ps_adhoc_set_request *pp; |
1348 | |
1349 | pp = hostif_generic_request(size: sizeof(*pp), HIF_PS_ADH_SET_REQ); |
1350 | if (!pp) |
1351 | return; |
1352 | |
1353 | init_request(priv, req: &pp->request); |
1354 | pp->channel = cpu_to_le16(priv->reg.channel); |
1355 | |
1356 | send_request_to_device(priv, data: pp, size: hif_align_size(size: sizeof(*pp))); |
1357 | } |
1358 | |
1359 | static |
1360 | void hostif_infrastructure_set_request(struct ks_wlan_private *priv, int event) |
1361 | { |
1362 | struct hostif_infrastructure_set_request *pp; |
1363 | |
1364 | pp = hostif_generic_request(size: sizeof(*pp), event); |
1365 | if (!pp) |
1366 | return; |
1367 | |
1368 | init_request(priv, req: &pp->request); |
1369 | pp->ssid.size = priv->reg.ssid.size; |
1370 | memcpy(&pp->ssid.body[0], &priv->reg.ssid.body[0], priv->reg.ssid.size); |
1371 | pp->beacon_lost_count = |
1372 | cpu_to_le16(priv->reg.beacon_lost_count); |
1373 | pp->auth_type = cpu_to_le16(priv->reg.authenticate_type); |
1374 | |
1375 | pp->channel_list.body[0] = 1; |
1376 | pp->channel_list.body[1] = 8; |
1377 | pp->channel_list.body[2] = 2; |
1378 | pp->channel_list.body[3] = 9; |
1379 | pp->channel_list.body[4] = 3; |
1380 | pp->channel_list.body[5] = 10; |
1381 | pp->channel_list.body[6] = 4; |
1382 | pp->channel_list.body[7] = 11; |
1383 | pp->channel_list.body[8] = 5; |
1384 | pp->channel_list.body[9] = 12; |
1385 | pp->channel_list.body[10] = 6; |
1386 | pp->channel_list.body[11] = 13; |
1387 | pp->channel_list.body[12] = 7; |
1388 | if (priv->reg.phy_type == D_11G_ONLY_MODE) { |
1389 | pp->channel_list.size = 13; |
1390 | } else { |
1391 | pp->channel_list.body[13] = 14; |
1392 | pp->channel_list.size = 14; |
1393 | } |
1394 | |
1395 | send_request_to_device(priv, data: pp, size: hif_align_size(size: sizeof(*pp))); |
1396 | } |
1397 | |
1398 | static |
1399 | void hostif_adhoc_set_request(struct ks_wlan_private *priv) |
1400 | { |
1401 | struct hostif_adhoc_set_request *pp; |
1402 | |
1403 | pp = hostif_generic_request(size: sizeof(*pp), HIF_ADH_SET_REQ); |
1404 | if (!pp) |
1405 | return; |
1406 | |
1407 | init_request(priv, req: &pp->request); |
1408 | pp->channel = cpu_to_le16(priv->reg.channel); |
1409 | pp->ssid.size = priv->reg.ssid.size; |
1410 | memcpy(&pp->ssid.body[0], &priv->reg.ssid.body[0], priv->reg.ssid.size); |
1411 | |
1412 | send_request_to_device(priv, data: pp, size: hif_align_size(size: sizeof(*pp))); |
1413 | } |
1414 | |
1415 | static |
1416 | void hostif_adhoc_set2_request(struct ks_wlan_private *priv) |
1417 | { |
1418 | struct hostif_adhoc_set2_request *pp; |
1419 | |
1420 | pp = hostif_generic_request(size: sizeof(*pp), HIF_ADH_SET_REQ); |
1421 | if (!pp) |
1422 | return; |
1423 | |
1424 | init_request(priv, req: &pp->request); |
1425 | pp->ssid.size = priv->reg.ssid.size; |
1426 | memcpy(&pp->ssid.body[0], &priv->reg.ssid.body[0], priv->reg.ssid.size); |
1427 | |
1428 | pp->channel_list.body[0] = priv->reg.channel; |
1429 | pp->channel_list.size = 1; |
1430 | memcpy(pp->bssid, priv->reg.bssid, ETH_ALEN); |
1431 | |
1432 | send_request_to_device(priv, data: pp, size: hif_align_size(size: sizeof(*pp))); |
1433 | } |
1434 | |
1435 | static |
1436 | void hostif_stop_request(struct ks_wlan_private *priv) |
1437 | { |
1438 | struct hostif_stop_request *pp; |
1439 | |
1440 | pp = hostif_generic_request(size: sizeof(*pp), HIF_STOP_REQ); |
1441 | if (!pp) |
1442 | return; |
1443 | |
1444 | send_request_to_device(priv, data: pp, size: hif_align_size(size: sizeof(*pp))); |
1445 | } |
1446 | |
1447 | static |
1448 | void hostif_phy_information_request(struct ks_wlan_private *priv) |
1449 | { |
1450 | struct hostif_phy_information_request *pp; |
1451 | |
1452 | pp = hostif_generic_request(size: sizeof(*pp), HIF_PHY_INFO_REQ); |
1453 | if (!pp) |
1454 | return; |
1455 | |
1456 | if (priv->reg.phy_info_timer) { |
1457 | pp->type = cpu_to_le16(TIME_TYPE); |
1458 | pp->time = cpu_to_le16(priv->reg.phy_info_timer); |
1459 | } else { |
1460 | pp->type = cpu_to_le16(NORMAL_TYPE); |
1461 | pp->time = cpu_to_le16(0); |
1462 | } |
1463 | |
1464 | send_request_to_device(priv, data: pp, size: hif_align_size(size: sizeof(*pp))); |
1465 | } |
1466 | |
1467 | static |
1468 | void hostif_power_mgmt_request(struct ks_wlan_private *priv, |
1469 | u32 mode, u32 wake_up, u32 receive_dtims) |
1470 | { |
1471 | struct hostif_power_mgmt_request *pp; |
1472 | |
1473 | pp = hostif_generic_request(size: sizeof(*pp), HIF_POWER_MGMT_REQ); |
1474 | if (!pp) |
1475 | return; |
1476 | |
1477 | pp->mode = cpu_to_le32(mode); |
1478 | pp->wake_up = cpu_to_le32(wake_up); |
1479 | pp->receive_dtims = cpu_to_le32(receive_dtims); |
1480 | |
1481 | send_request_to_device(priv, data: pp, size: hif_align_size(size: sizeof(*pp))); |
1482 | } |
1483 | |
1484 | static |
1485 | void hostif_sleep_request(struct ks_wlan_private *priv, |
1486 | enum sleep_mode_type mode) |
1487 | { |
1488 | struct hostif_sleep_request *pp; |
1489 | |
1490 | if (mode == SLP_SLEEP) { |
1491 | pp = hostif_generic_request(size: sizeof(*pp), HIF_SLEEP_REQ); |
1492 | if (!pp) |
1493 | return; |
1494 | |
1495 | send_request_to_device(priv, data: pp, size: hif_align_size(size: sizeof(*pp))); |
1496 | } else if (mode == SLP_ACTIVE) { |
1497 | atomic_set(v: &priv->sleepstatus.wakeup_request, i: 1); |
1498 | queue_delayed_work(wq: priv->wq, dwork: &priv->rw_dwork, delay: 1); |
1499 | } else { |
1500 | netdev_err(dev: priv->net_dev, format: "invalid mode %ld\n" , (long)mode); |
1501 | return; |
1502 | } |
1503 | } |
1504 | |
1505 | static |
1506 | void hostif_bss_scan_request(struct ks_wlan_private *priv, |
1507 | unsigned long scan_type, u8 *scan_ssid, |
1508 | u8 scan_ssid_len) |
1509 | { |
1510 | struct hostif_bss_scan_request *pp; |
1511 | |
1512 | pp = hostif_generic_request(size: sizeof(*pp), HIF_SCAN_REQ); |
1513 | if (!pp) |
1514 | return; |
1515 | |
1516 | pp->scan_type = scan_type; |
1517 | |
1518 | pp->ch_time_min = cpu_to_le32(110); /* default value */ |
1519 | pp->ch_time_max = cpu_to_le32(130); /* default value */ |
1520 | pp->channel_list.body[0] = 1; |
1521 | pp->channel_list.body[1] = 8; |
1522 | pp->channel_list.body[2] = 2; |
1523 | pp->channel_list.body[3] = 9; |
1524 | pp->channel_list.body[4] = 3; |
1525 | pp->channel_list.body[5] = 10; |
1526 | pp->channel_list.body[6] = 4; |
1527 | pp->channel_list.body[7] = 11; |
1528 | pp->channel_list.body[8] = 5; |
1529 | pp->channel_list.body[9] = 12; |
1530 | pp->channel_list.body[10] = 6; |
1531 | pp->channel_list.body[11] = 13; |
1532 | pp->channel_list.body[12] = 7; |
1533 | if (priv->reg.phy_type == D_11G_ONLY_MODE) { |
1534 | pp->channel_list.size = 13; |
1535 | } else { |
1536 | pp->channel_list.body[13] = 14; |
1537 | pp->channel_list.size = 14; |
1538 | } |
1539 | pp->ssid.size = 0; |
1540 | |
1541 | /* specified SSID SCAN */ |
1542 | if (scan_ssid_len > 0 && scan_ssid_len <= 32) { |
1543 | pp->ssid.size = scan_ssid_len; |
1544 | memcpy(&pp->ssid.body[0], scan_ssid, scan_ssid_len); |
1545 | } |
1546 | |
1547 | send_request_to_device(priv, data: pp, size: hif_align_size(size: sizeof(*pp))); |
1548 | |
1549 | priv->aplist.size = 0; |
1550 | priv->scan_ind_count = 0; |
1551 | } |
1552 | |
1553 | static |
1554 | void hostif_mic_failure_request(struct ks_wlan_private *priv, |
1555 | u16 failure_count, u16 timer) |
1556 | { |
1557 | struct hostif_mic_failure_request *pp; |
1558 | |
1559 | pp = hostif_generic_request(size: sizeof(*pp), HIF_MIC_FAILURE_REQ); |
1560 | if (!pp) |
1561 | return; |
1562 | |
1563 | pp->failure_count = cpu_to_le16(failure_count); |
1564 | pp->timer = cpu_to_le16(timer); |
1565 | |
1566 | send_request_to_device(priv, data: pp, size: hif_align_size(size: sizeof(*pp))); |
1567 | } |
1568 | |
1569 | /* Device I/O Receive indicate */ |
1570 | static void devio_rec_ind(struct ks_wlan_private *priv, unsigned char *p, |
1571 | unsigned int size) |
1572 | { |
1573 | if (!priv->is_device_open) |
1574 | return; |
1575 | |
1576 | spin_lock(lock: &priv->dev_read_lock); |
1577 | priv->dev_data[atomic_read(v: &priv->rec_count)] = p; |
1578 | priv->dev_size[atomic_read(v: &priv->rec_count)] = size; |
1579 | |
1580 | if (atomic_read(v: &priv->event_count) != DEVICE_STOCK_COUNT) { |
1581 | /* rx event count inc */ |
1582 | atomic_inc(v: &priv->event_count); |
1583 | } |
1584 | atomic_inc(v: &priv->rec_count); |
1585 | if (atomic_read(v: &priv->rec_count) == DEVICE_STOCK_COUNT) |
1586 | atomic_set(v: &priv->rec_count, i: 0); |
1587 | |
1588 | wake_up_interruptible_all(&priv->devread_wait); |
1589 | |
1590 | spin_unlock(lock: &priv->dev_read_lock); |
1591 | } |
1592 | |
1593 | void hostif_receive(struct ks_wlan_private *priv, unsigned char *p, |
1594 | unsigned int size) |
1595 | { |
1596 | devio_rec_ind(priv, p, size); |
1597 | |
1598 | priv->rxp = p; |
1599 | priv->rx_size = size; |
1600 | |
1601 | if (get_word(priv) == priv->rx_size) |
1602 | hostif_event_check(priv); |
1603 | } |
1604 | |
1605 | static void hostif_sme_set_wep(struct ks_wlan_private *priv, int type) |
1606 | { |
1607 | switch (type) { |
1608 | case SME_WEP_INDEX_REQUEST: |
1609 | hostif_mib_set_request_int(priv, attr: DOT11_WEP_DEFAULT_KEY_ID, |
1610 | val: priv->reg.wep_index); |
1611 | break; |
1612 | case SME_WEP_KEY1_REQUEST: |
1613 | if (priv->wpa.wpa_enabled) |
1614 | return; |
1615 | hostif_mib_set_request_ostring(priv, |
1616 | attr: DOT11_WEP_DEFAULT_KEY_VALUE1, |
1617 | data: &priv->reg.wep_key[0].val[0], |
1618 | size: priv->reg.wep_key[0].size); |
1619 | break; |
1620 | case SME_WEP_KEY2_REQUEST: |
1621 | if (priv->wpa.wpa_enabled) |
1622 | return; |
1623 | hostif_mib_set_request_ostring(priv, |
1624 | attr: DOT11_WEP_DEFAULT_KEY_VALUE2, |
1625 | data: &priv->reg.wep_key[1].val[0], |
1626 | size: priv->reg.wep_key[1].size); |
1627 | break; |
1628 | case SME_WEP_KEY3_REQUEST: |
1629 | if (priv->wpa.wpa_enabled) |
1630 | return; |
1631 | hostif_mib_set_request_ostring(priv, |
1632 | attr: DOT11_WEP_DEFAULT_KEY_VALUE3, |
1633 | data: &priv->reg.wep_key[2].val[0], |
1634 | size: priv->reg.wep_key[2].size); |
1635 | break; |
1636 | case SME_WEP_KEY4_REQUEST: |
1637 | if (priv->wpa.wpa_enabled) |
1638 | return; |
1639 | hostif_mib_set_request_ostring(priv, |
1640 | attr: DOT11_WEP_DEFAULT_KEY_VALUE4, |
1641 | data: &priv->reg.wep_key[3].val[0], |
1642 | size: priv->reg.wep_key[3].size); |
1643 | break; |
1644 | case SME_WEP_FLAG_REQUEST: |
1645 | hostif_mib_set_request_bool(priv, attr: DOT11_PRIVACY_INVOKED, |
1646 | val: priv->reg.privacy_invoked); |
1647 | break; |
1648 | } |
1649 | } |
1650 | |
1651 | struct wpa_suite { |
1652 | __le16 size; |
1653 | unsigned char suite[4][CIPHER_ID_LEN]; |
1654 | } __packed; |
1655 | |
1656 | struct rsn_mode { |
1657 | __le32 rsn_mode; |
1658 | __le16 rsn_capability; |
1659 | } __packed; |
1660 | |
1661 | static void hostif_sme_set_rsn(struct ks_wlan_private *priv, int type) |
1662 | { |
1663 | struct wpa_suite wpa_suite; |
1664 | struct rsn_mode rsn_mode; |
1665 | size_t size; |
1666 | u32 mode; |
1667 | const u8 *buf = NULL; |
1668 | |
1669 | memset(&wpa_suite, 0, sizeof(wpa_suite)); |
1670 | |
1671 | switch (type) { |
1672 | case SME_RSN_UCAST_REQUEST: |
1673 | wpa_suite.size = cpu_to_le16(1); |
1674 | switch (priv->wpa.pairwise_suite) { |
1675 | case IW_AUTH_CIPHER_NONE: |
1676 | buf = (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) ? |
1677 | CIPHER_ID_WPA2_NONE : CIPHER_ID_WPA_NONE; |
1678 | break; |
1679 | case IW_AUTH_CIPHER_WEP40: |
1680 | buf = (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) ? |
1681 | CIPHER_ID_WPA2_WEP40 : CIPHER_ID_WPA_WEP40; |
1682 | break; |
1683 | case IW_AUTH_CIPHER_TKIP: |
1684 | buf = (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) ? |
1685 | CIPHER_ID_WPA2_TKIP : CIPHER_ID_WPA_TKIP; |
1686 | break; |
1687 | case IW_AUTH_CIPHER_CCMP: |
1688 | buf = (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) ? |
1689 | CIPHER_ID_WPA2_CCMP : CIPHER_ID_WPA_CCMP; |
1690 | break; |
1691 | case IW_AUTH_CIPHER_WEP104: |
1692 | buf = (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) ? |
1693 | CIPHER_ID_WPA2_WEP104 : CIPHER_ID_WPA_WEP104; |
1694 | break; |
1695 | } |
1696 | |
1697 | if (buf) |
1698 | memcpy(&wpa_suite.suite[0][0], buf, CIPHER_ID_LEN); |
1699 | size = sizeof(wpa_suite.size) + |
1700 | (CIPHER_ID_LEN * le16_to_cpu(wpa_suite.size)); |
1701 | hostif_mib_set_request_ostring(priv, |
1702 | attr: DOT11_RSN_CONFIG_UNICAST_CIPHER, |
1703 | data: &wpa_suite, size); |
1704 | break; |
1705 | case SME_RSN_MCAST_REQUEST: |
1706 | switch (priv->wpa.group_suite) { |
1707 | case IW_AUTH_CIPHER_NONE: |
1708 | buf = (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) ? |
1709 | CIPHER_ID_WPA2_NONE : CIPHER_ID_WPA_NONE; |
1710 | break; |
1711 | case IW_AUTH_CIPHER_WEP40: |
1712 | buf = (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) ? |
1713 | CIPHER_ID_WPA2_WEP40 : CIPHER_ID_WPA_WEP40; |
1714 | break; |
1715 | case IW_AUTH_CIPHER_TKIP: |
1716 | buf = (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) ? |
1717 | CIPHER_ID_WPA2_TKIP : CIPHER_ID_WPA_TKIP; |
1718 | break; |
1719 | case IW_AUTH_CIPHER_CCMP: |
1720 | buf = (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) ? |
1721 | CIPHER_ID_WPA2_CCMP : CIPHER_ID_WPA_CCMP; |
1722 | break; |
1723 | case IW_AUTH_CIPHER_WEP104: |
1724 | buf = (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) ? |
1725 | CIPHER_ID_WPA2_WEP104 : CIPHER_ID_WPA_WEP104; |
1726 | break; |
1727 | } |
1728 | if (buf) |
1729 | memcpy(&wpa_suite.suite[0][0], buf, CIPHER_ID_LEN); |
1730 | hostif_mib_set_request_ostring(priv, |
1731 | attr: DOT11_RSN_CONFIG_MULTICAST_CIPHER, |
1732 | data: &wpa_suite.suite[0][0], |
1733 | CIPHER_ID_LEN); |
1734 | break; |
1735 | case SME_RSN_AUTH_REQUEST: |
1736 | wpa_suite.size = cpu_to_le16(1); |
1737 | switch (priv->wpa.key_mgmt_suite) { |
1738 | case IW_AUTH_KEY_MGMT_802_1X: |
1739 | buf = (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) ? |
1740 | KEY_MGMT_ID_WPA2_1X : KEY_MGMT_ID_WPA_1X; |
1741 | break; |
1742 | case IW_AUTH_KEY_MGMT_PSK: |
1743 | buf = (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) ? |
1744 | KEY_MGMT_ID_WPA2_PSK : KEY_MGMT_ID_WPA_PSK; |
1745 | break; |
1746 | case 0: |
1747 | buf = (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) ? |
1748 | KEY_MGMT_ID_WPA2_NONE : KEY_MGMT_ID_WPA_NONE; |
1749 | break; |
1750 | case 4: |
1751 | buf = (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) ? |
1752 | KEY_MGMT_ID_WPA2_WPANONE : |
1753 | KEY_MGMT_ID_WPA_WPANONE; |
1754 | break; |
1755 | } |
1756 | |
1757 | if (buf) |
1758 | memcpy(&wpa_suite.suite[0][0], buf, KEY_MGMT_ID_LEN); |
1759 | size = sizeof(wpa_suite.size) + |
1760 | (KEY_MGMT_ID_LEN * le16_to_cpu(wpa_suite.size)); |
1761 | hostif_mib_set_request_ostring(priv, |
1762 | attr: DOT11_RSN_CONFIG_AUTH_SUITE, |
1763 | data: &wpa_suite, size); |
1764 | break; |
1765 | case SME_RSN_ENABLED_REQUEST: |
1766 | hostif_mib_set_request_bool(priv, attr: DOT11_RSN_ENABLED, |
1767 | val: priv->wpa.rsn_enabled); |
1768 | break; |
1769 | case SME_RSN_MODE_REQUEST: |
1770 | mode = (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) ? |
1771 | RSN_MODE_WPA2 : |
1772 | (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA) ? |
1773 | RSN_MODE_WPA : RSN_MODE_NONE; |
1774 | rsn_mode.rsn_mode = cpu_to_le32(mode); |
1775 | rsn_mode.rsn_capability = cpu_to_le16(0); |
1776 | hostif_mib_set_request_ostring(priv, attr: LOCAL_RSN_MODE, |
1777 | data: &rsn_mode, size: sizeof(rsn_mode)); |
1778 | break; |
1779 | } |
1780 | } |
1781 | |
1782 | static |
1783 | void hostif_sme_mode_setup(struct ks_wlan_private *priv) |
1784 | { |
1785 | unsigned char rate_size; |
1786 | unsigned char rate_octet[RATE_SET_MAX_SIZE]; |
1787 | int i = 0; |
1788 | |
1789 | /* rate setting if rate segging is auto for changing phy_type (#94) */ |
1790 | if (priv->reg.tx_rate == TX_RATE_FULL_AUTO) { |
1791 | if (priv->reg.phy_type == D_11B_ONLY_MODE) { |
1792 | priv->reg.rate_set.body[3] = TX_RATE_11M; |
1793 | priv->reg.rate_set.body[2] = TX_RATE_5M; |
1794 | priv->reg.rate_set.body[1] = TX_RATE_2M | BASIC_RATE; |
1795 | priv->reg.rate_set.body[0] = TX_RATE_1M | BASIC_RATE; |
1796 | priv->reg.rate_set.size = 4; |
1797 | } else { /* D_11G_ONLY_MODE or D_11BG_COMPATIBLE_MODE */ |
1798 | priv->reg.rate_set.body[11] = TX_RATE_54M; |
1799 | priv->reg.rate_set.body[10] = TX_RATE_48M; |
1800 | priv->reg.rate_set.body[9] = TX_RATE_36M; |
1801 | priv->reg.rate_set.body[8] = TX_RATE_18M; |
1802 | priv->reg.rate_set.body[7] = TX_RATE_9M; |
1803 | priv->reg.rate_set.body[6] = TX_RATE_24M | BASIC_RATE; |
1804 | priv->reg.rate_set.body[5] = TX_RATE_12M | BASIC_RATE; |
1805 | priv->reg.rate_set.body[4] = TX_RATE_6M | BASIC_RATE; |
1806 | priv->reg.rate_set.body[3] = TX_RATE_11M | BASIC_RATE; |
1807 | priv->reg.rate_set.body[2] = TX_RATE_5M | BASIC_RATE; |
1808 | priv->reg.rate_set.body[1] = TX_RATE_2M | BASIC_RATE; |
1809 | priv->reg.rate_set.body[0] = TX_RATE_1M | BASIC_RATE; |
1810 | priv->reg.rate_set.size = 12; |
1811 | } |
1812 | } |
1813 | |
1814 | /* rate mask by phy setting */ |
1815 | if (priv->reg.phy_type == D_11B_ONLY_MODE) { |
1816 | for (i = 0; i < priv->reg.rate_set.size; i++) { |
1817 | if (!is_11b_rate(rate: priv->reg.rate_set.body[i])) |
1818 | break; |
1819 | |
1820 | if ((priv->reg.rate_set.body[i] & RATE_MASK) >= TX_RATE_5M) { |
1821 | rate_octet[i] = priv->reg.rate_set.body[i] & |
1822 | RATE_MASK; |
1823 | } else { |
1824 | rate_octet[i] = priv->reg.rate_set.body[i]; |
1825 | } |
1826 | } |
1827 | |
1828 | } else { /* D_11G_ONLY_MODE or D_11BG_COMPATIBLE_MODE */ |
1829 | for (i = 0; i < priv->reg.rate_set.size; i++) { |
1830 | if (!is_11bg_rate(rate: priv->reg.rate_set.body[i])) |
1831 | break; |
1832 | |
1833 | if (is_ofdm_ext_rate(rate: priv->reg.rate_set.body[i])) { |
1834 | rate_octet[i] = priv->reg.rate_set.body[i] & |
1835 | RATE_MASK; |
1836 | } else { |
1837 | rate_octet[i] = priv->reg.rate_set.body[i]; |
1838 | } |
1839 | } |
1840 | } |
1841 | rate_size = i; |
1842 | if (rate_size == 0) { |
1843 | if (priv->reg.phy_type == D_11G_ONLY_MODE) |
1844 | rate_octet[0] = TX_RATE_6M | BASIC_RATE; |
1845 | else |
1846 | rate_octet[0] = TX_RATE_2M | BASIC_RATE; |
1847 | rate_size = 1; |
1848 | } |
1849 | |
1850 | /* rate set update */ |
1851 | priv->reg.rate_set.size = rate_size; |
1852 | memcpy(&priv->reg.rate_set.body[0], &rate_octet[0], rate_size); |
1853 | |
1854 | switch (priv->reg.operation_mode) { |
1855 | case MODE_PSEUDO_ADHOC: |
1856 | hostif_ps_adhoc_set_request(priv); |
1857 | break; |
1858 | case MODE_INFRASTRUCTURE: |
1859 | if (!is_valid_ether_addr(addr: (u8 *)priv->reg.bssid)) { |
1860 | hostif_infrastructure_set_request(priv, |
1861 | HIF_INFRA_SET_REQ); |
1862 | } else { |
1863 | hostif_infrastructure_set_request(priv, |
1864 | HIF_INFRA_SET2_REQ); |
1865 | netdev_dbg(priv->net_dev, |
1866 | "Infra bssid = %pM\n" , priv->reg.bssid); |
1867 | } |
1868 | break; |
1869 | case MODE_ADHOC: |
1870 | if (!is_valid_ether_addr(addr: (u8 *)priv->reg.bssid)) { |
1871 | hostif_adhoc_set_request(priv); |
1872 | } else { |
1873 | hostif_adhoc_set2_request(priv); |
1874 | netdev_dbg(priv->net_dev, |
1875 | "Adhoc bssid = %pM\n" , priv->reg.bssid); |
1876 | } |
1877 | break; |
1878 | default: |
1879 | break; |
1880 | } |
1881 | } |
1882 | |
1883 | static |
1884 | void hostif_sme_multicast_set(struct ks_wlan_private *priv) |
1885 | { |
1886 | struct net_device *dev = priv->net_dev; |
1887 | int mc_count; |
1888 | struct netdev_hw_addr *ha; |
1889 | char set_address[NIC_MAX_MCAST_LIST * ETH_ALEN]; |
1890 | int i = 0; |
1891 | |
1892 | spin_lock(lock: &priv->multicast_spin); |
1893 | |
1894 | memset(set_address, 0, NIC_MAX_MCAST_LIST * ETH_ALEN); |
1895 | |
1896 | if (dev->flags & IFF_PROMISC) { |
1897 | hostif_mib_set_request_int(priv, attr: LOCAL_MULTICAST_FILTER, |
1898 | val: MCAST_FILTER_PROMISC); |
1899 | goto spin_unlock; |
1900 | } |
1901 | |
1902 | if ((netdev_mc_count(dev) > NIC_MAX_MCAST_LIST) || |
1903 | (dev->flags & IFF_ALLMULTI)) { |
1904 | hostif_mib_set_request_int(priv, attr: LOCAL_MULTICAST_FILTER, |
1905 | val: MCAST_FILTER_MCASTALL); |
1906 | goto spin_unlock; |
1907 | } |
1908 | |
1909 | if (priv->sme_i.sme_flag & SME_MULTICAST) { |
1910 | mc_count = netdev_mc_count(dev); |
1911 | netdev_for_each_mc_addr(ha, dev) { |
1912 | ether_addr_copy(dst: &set_address[i * ETH_ALEN], src: ha->addr); |
1913 | i++; |
1914 | } |
1915 | priv->sme_i.sme_flag &= ~SME_MULTICAST; |
1916 | hostif_mib_set_request_ostring(priv, attr: LOCAL_MULTICAST_ADDRESS, |
1917 | data: &set_address[0], |
1918 | ETH_ALEN * mc_count); |
1919 | } else { |
1920 | priv->sme_i.sme_flag |= SME_MULTICAST; |
1921 | hostif_mib_set_request_int(priv, attr: LOCAL_MULTICAST_FILTER, |
1922 | val: MCAST_FILTER_MCAST); |
1923 | } |
1924 | |
1925 | spin_unlock: |
1926 | spin_unlock(lock: &priv->multicast_spin); |
1927 | } |
1928 | |
1929 | static void hostif_sme_power_mgmt_set(struct ks_wlan_private *priv) |
1930 | { |
1931 | u32 mode, wake_up, receive_dtims; |
1932 | |
1933 | if (priv->reg.power_mgmt != POWER_MGMT_SAVE1 && |
1934 | priv->reg.power_mgmt != POWER_MGMT_SAVE2) { |
1935 | mode = POWER_ACTIVE; |
1936 | wake_up = 0; |
1937 | receive_dtims = 0; |
1938 | } else { |
1939 | mode = (priv->reg.operation_mode == MODE_INFRASTRUCTURE) ? |
1940 | POWER_SAVE : POWER_ACTIVE; |
1941 | wake_up = 0; |
1942 | receive_dtims = (priv->reg.operation_mode == MODE_INFRASTRUCTURE && |
1943 | priv->reg.power_mgmt == POWER_MGMT_SAVE2); |
1944 | } |
1945 | |
1946 | hostif_power_mgmt_request(priv, mode, wake_up, receive_dtims); |
1947 | } |
1948 | |
1949 | static void hostif_sme_sleep_set(struct ks_wlan_private *priv) |
1950 | { |
1951 | if (priv->sleep_mode != SLP_SLEEP && |
1952 | priv->sleep_mode != SLP_ACTIVE) |
1953 | return; |
1954 | |
1955 | hostif_sleep_request(priv, mode: priv->sleep_mode); |
1956 | } |
1957 | |
1958 | static |
1959 | void hostif_sme_set_key(struct ks_wlan_private *priv, int type) |
1960 | { |
1961 | switch (type) { |
1962 | case SME_SET_FLAG: |
1963 | hostif_mib_set_request_bool(priv, attr: DOT11_PRIVACY_INVOKED, |
1964 | val: priv->reg.privacy_invoked); |
1965 | break; |
1966 | case SME_SET_TXKEY: |
1967 | hostif_mib_set_request_int(priv, attr: DOT11_WEP_DEFAULT_KEY_ID, |
1968 | val: priv->wpa.txkey); |
1969 | break; |
1970 | case SME_SET_KEY1: |
1971 | hostif_mib_set_request_ostring(priv, |
1972 | attr: DOT11_WEP_DEFAULT_KEY_VALUE1, |
1973 | data: &priv->wpa.key[0].key_val[0], |
1974 | size: priv->wpa.key[0].key_len); |
1975 | break; |
1976 | case SME_SET_KEY2: |
1977 | hostif_mib_set_request_ostring(priv, |
1978 | attr: DOT11_WEP_DEFAULT_KEY_VALUE2, |
1979 | data: &priv->wpa.key[1].key_val[0], |
1980 | size: priv->wpa.key[1].key_len); |
1981 | break; |
1982 | case SME_SET_KEY3: |
1983 | hostif_mib_set_request_ostring(priv, |
1984 | attr: DOT11_WEP_DEFAULT_KEY_VALUE3, |
1985 | data: &priv->wpa.key[2].key_val[0], |
1986 | size: priv->wpa.key[2].key_len); |
1987 | break; |
1988 | case SME_SET_KEY4: |
1989 | hostif_mib_set_request_ostring(priv, |
1990 | attr: DOT11_WEP_DEFAULT_KEY_VALUE4, |
1991 | data: &priv->wpa.key[3].key_val[0], |
1992 | size: priv->wpa.key[3].key_len); |
1993 | break; |
1994 | case SME_SET_PMK_TSC: |
1995 | hostif_mib_set_request_ostring(priv, attr: DOT11_PMK_TSC, |
1996 | data: &priv->wpa.key[0].rx_seq[0], |
1997 | WPA_RX_SEQ_LEN); |
1998 | break; |
1999 | case SME_SET_GMK1_TSC: |
2000 | hostif_mib_set_request_ostring(priv, attr: DOT11_GMK1_TSC, |
2001 | data: &priv->wpa.key[1].rx_seq[0], |
2002 | WPA_RX_SEQ_LEN); |
2003 | break; |
2004 | case SME_SET_GMK2_TSC: |
2005 | hostif_mib_set_request_ostring(priv, attr: DOT11_GMK2_TSC, |
2006 | data: &priv->wpa.key[2].rx_seq[0], |
2007 | WPA_RX_SEQ_LEN); |
2008 | break; |
2009 | } |
2010 | } |
2011 | |
2012 | static |
2013 | void hostif_sme_set_pmksa(struct ks_wlan_private *priv) |
2014 | { |
2015 | struct pmk_cache { |
2016 | __le16 size; |
2017 | struct { |
2018 | u8 bssid[ETH_ALEN]; |
2019 | u8 pmkid[IW_PMKID_LEN]; |
2020 | } __packed list[PMK_LIST_MAX]; |
2021 | } __packed pmkcache; |
2022 | struct pmk *pmk; |
2023 | size_t size; |
2024 | int i = 0; |
2025 | |
2026 | list_for_each_entry(pmk, &priv->pmklist.head, list) { |
2027 | if (i >= PMK_LIST_MAX) |
2028 | break; |
2029 | ether_addr_copy(dst: pmkcache.list[i].bssid, src: pmk->bssid); |
2030 | memcpy(pmkcache.list[i].pmkid, pmk->pmkid, IW_PMKID_LEN); |
2031 | i++; |
2032 | } |
2033 | pmkcache.size = cpu_to_le16(priv->pmklist.size); |
2034 | size = sizeof(priv->pmklist.size) + |
2035 | ((ETH_ALEN + IW_PMKID_LEN) * priv->pmklist.size); |
2036 | hostif_mib_set_request_ostring(priv, attr: LOCAL_PMK, data: &pmkcache, size); |
2037 | } |
2038 | |
2039 | /* execute sme */ |
2040 | static void hostif_sme_execute(struct ks_wlan_private *priv, int event) |
2041 | { |
2042 | u16 failure; |
2043 | |
2044 | switch (event) { |
2045 | case SME_START: |
2046 | if (priv->dev_state == DEVICE_STATE_BOOT) |
2047 | hostif_mib_get_request(priv, mib_attribute: DOT11_MAC_ADDRESS); |
2048 | break; |
2049 | case SME_MULTICAST_REQUEST: |
2050 | hostif_sme_multicast_set(priv); |
2051 | break; |
2052 | case SME_MACADDRESS_SET_REQUEST: |
2053 | hostif_mib_set_request_ostring(priv, attr: LOCAL_CURRENTADDRESS, |
2054 | data: &priv->eth_addr[0], ETH_ALEN); |
2055 | break; |
2056 | case SME_BSS_SCAN_REQUEST: |
2057 | hostif_bss_scan_request(priv, scan_type: priv->reg.scan_type, |
2058 | scan_ssid: priv->scan_ssid, scan_ssid_len: priv->scan_ssid_len); |
2059 | break; |
2060 | case SME_POW_MNGMT_REQUEST: |
2061 | hostif_sme_power_mgmt_set(priv); |
2062 | break; |
2063 | case SME_PHY_INFO_REQUEST: |
2064 | hostif_phy_information_request(priv); |
2065 | break; |
2066 | case SME_MIC_FAILURE_REQUEST: |
2067 | failure = priv->wpa.mic_failure.failure; |
2068 | if (failure != 1 && failure != 2) { |
2069 | netdev_err(dev: priv->net_dev, |
2070 | format: "SME_MIC_FAILURE_REQUEST: failure count=%u error?\n" , |
2071 | failure); |
2072 | return; |
2073 | } |
2074 | hostif_mic_failure_request(priv, failure_count: failure - 1, timer: (failure == 1) ? |
2075 | 0 : priv->wpa.mic_failure.counter); |
2076 | break; |
2077 | case SME_MIC_FAILURE_CONFIRM: |
2078 | if (priv->wpa.mic_failure.failure == 2) { |
2079 | if (priv->wpa.mic_failure.stop) |
2080 | priv->wpa.mic_failure.stop = 0; |
2081 | priv->wpa.mic_failure.failure = 0; |
2082 | hostif_start_request(priv, mode: priv->reg.operation_mode); |
2083 | } |
2084 | break; |
2085 | case SME_GET_MAC_ADDRESS: |
2086 | if (priv->dev_state == DEVICE_STATE_BOOT) |
2087 | hostif_mib_get_request(priv, mib_attribute: DOT11_PRODUCT_VERSION); |
2088 | break; |
2089 | case SME_GET_PRODUCT_VERSION: |
2090 | if (priv->dev_state == DEVICE_STATE_BOOT) |
2091 | priv->dev_state = DEVICE_STATE_PREINIT; |
2092 | break; |
2093 | case SME_STOP_REQUEST: |
2094 | hostif_stop_request(priv); |
2095 | break; |
2096 | case SME_RTS_THRESHOLD_REQUEST: |
2097 | hostif_mib_set_request_int(priv, attr: DOT11_RTS_THRESHOLD, |
2098 | val: priv->reg.rts); |
2099 | break; |
2100 | case SME_FRAGMENTATION_THRESHOLD_REQUEST: |
2101 | hostif_mib_set_request_int(priv, attr: DOT11_FRAGMENTATION_THRESHOLD, |
2102 | val: priv->reg.fragment); |
2103 | break; |
2104 | case SME_WEP_INDEX_REQUEST: |
2105 | case SME_WEP_KEY1_REQUEST: |
2106 | case SME_WEP_KEY2_REQUEST: |
2107 | case SME_WEP_KEY3_REQUEST: |
2108 | case SME_WEP_KEY4_REQUEST: |
2109 | case SME_WEP_FLAG_REQUEST: |
2110 | hostif_sme_set_wep(priv, type: event); |
2111 | break; |
2112 | case SME_RSN_UCAST_REQUEST: |
2113 | case SME_RSN_MCAST_REQUEST: |
2114 | case SME_RSN_AUTH_REQUEST: |
2115 | case SME_RSN_ENABLED_REQUEST: |
2116 | case SME_RSN_MODE_REQUEST: |
2117 | hostif_sme_set_rsn(priv, type: event); |
2118 | break; |
2119 | case SME_SET_FLAG: |
2120 | case SME_SET_TXKEY: |
2121 | case SME_SET_KEY1: |
2122 | case SME_SET_KEY2: |
2123 | case SME_SET_KEY3: |
2124 | case SME_SET_KEY4: |
2125 | case SME_SET_PMK_TSC: |
2126 | case SME_SET_GMK1_TSC: |
2127 | case SME_SET_GMK2_TSC: |
2128 | hostif_sme_set_key(priv, type: event); |
2129 | break; |
2130 | case SME_SET_PMKSA: |
2131 | hostif_sme_set_pmksa(priv); |
2132 | break; |
2133 | case SME_WPS_ENABLE_REQUEST: |
2134 | hostif_mib_set_request_int(priv, attr: LOCAL_WPS_ENABLE, |
2135 | val: priv->wps.wps_enabled); |
2136 | break; |
2137 | case SME_WPS_PROBE_REQUEST: |
2138 | hostif_mib_set_request_ostring(priv, attr: LOCAL_WPS_PROBE_REQ, |
2139 | data: priv->wps.ie, size: priv->wps.ielen); |
2140 | break; |
2141 | case SME_MODE_SET_REQUEST: |
2142 | hostif_sme_mode_setup(priv); |
2143 | break; |
2144 | case SME_SET_GAIN: |
2145 | hostif_mib_set_request_ostring(priv, attr: LOCAL_GAIN, |
2146 | data: &priv->gain, size: sizeof(priv->gain)); |
2147 | break; |
2148 | case SME_GET_GAIN: |
2149 | hostif_mib_get_request(priv, mib_attribute: LOCAL_GAIN); |
2150 | break; |
2151 | case SME_GET_EEPROM_CKSUM: |
2152 | priv->eeprom_checksum = EEPROM_FW_NOT_SUPPORT; /* initialize */ |
2153 | hostif_mib_get_request(priv, mib_attribute: LOCAL_EEPROM_SUM); |
2154 | break; |
2155 | case SME_START_REQUEST: |
2156 | hostif_start_request(priv, mode: priv->reg.operation_mode); |
2157 | break; |
2158 | case SME_START_CONFIRM: |
2159 | /* for power save */ |
2160 | atomic_set(v: &priv->psstatus.snooze_guard, i: 0); |
2161 | atomic_set(v: &priv->psstatus.confirm_wait, i: 0); |
2162 | if (priv->dev_state == DEVICE_STATE_PREINIT) |
2163 | priv->dev_state = DEVICE_STATE_INIT; |
2164 | /* wake_up_interruptible_all(&priv->confirm_wait); */ |
2165 | complete(&priv->confirm_wait); |
2166 | break; |
2167 | case SME_SLEEP_REQUEST: |
2168 | hostif_sme_sleep_set(priv); |
2169 | break; |
2170 | case SME_SET_REGION: |
2171 | hostif_mib_set_request_int(priv, attr: LOCAL_REGION, val: priv->region); |
2172 | break; |
2173 | case SME_MULTICAST_CONFIRM: |
2174 | case SME_BSS_SCAN_CONFIRM: |
2175 | case SME_POW_MNGMT_CONFIRM: |
2176 | case SME_PHY_INFO_CONFIRM: |
2177 | case SME_STOP_CONFIRM: |
2178 | case SME_RTS_THRESHOLD_CONFIRM: |
2179 | case SME_FRAGMENTATION_THRESHOLD_CONFIRM: |
2180 | case SME_WEP_INDEX_CONFIRM: |
2181 | case SME_WEP_KEY1_CONFIRM: |
2182 | case SME_WEP_KEY2_CONFIRM: |
2183 | case SME_WEP_KEY3_CONFIRM: |
2184 | case SME_WEP_KEY4_CONFIRM: |
2185 | case SME_WEP_FLAG_CONFIRM: |
2186 | case SME_RSN_UCAST_CONFIRM: |
2187 | case SME_RSN_MCAST_CONFIRM: |
2188 | case SME_RSN_AUTH_CONFIRM: |
2189 | case SME_RSN_ENABLED_CONFIRM: |
2190 | case SME_RSN_MODE_CONFIRM: |
2191 | case SME_MODE_SET_CONFIRM: |
2192 | case SME_TERMINATE: |
2193 | default: |
2194 | break; |
2195 | } |
2196 | } |
2197 | |
2198 | static void hostif_sme_work(struct work_struct *work) |
2199 | { |
2200 | struct ks_wlan_private *priv; |
2201 | |
2202 | priv = container_of(work, struct ks_wlan_private, sme_work); |
2203 | |
2204 | if (priv->dev_state < DEVICE_STATE_BOOT) |
2205 | return; |
2206 | |
2207 | if (cnt_smeqbody(priv) <= 0) |
2208 | return; |
2209 | |
2210 | hostif_sme_execute(priv, event: priv->sme_i.event_buff[priv->sme_i.qhead]); |
2211 | inc_smeqhead(priv); |
2212 | if (cnt_smeqbody(priv) > 0) |
2213 | schedule_work(work: &priv->sme_work); |
2214 | } |
2215 | |
2216 | /* send to Station Management Entity module */ |
2217 | void hostif_sme_enqueue(struct ks_wlan_private *priv, u16 event) |
2218 | { |
2219 | /* enqueue sme event */ |
2220 | if (cnt_smeqbody(priv) < (SME_EVENT_BUFF_SIZE - 1)) { |
2221 | priv->sme_i.event_buff[priv->sme_i.qtail] = event; |
2222 | inc_smeqtail(priv); |
2223 | } else { |
2224 | /* in case of buffer overflow */ |
2225 | netdev_err(dev: priv->net_dev, format: "sme queue buffer overflow\n" ); |
2226 | } |
2227 | |
2228 | schedule_work(work: &priv->sme_work); |
2229 | } |
2230 | |
2231 | static inline void hostif_aplist_init(struct ks_wlan_private *priv) |
2232 | { |
2233 | size_t size = LOCAL_APLIST_MAX * sizeof(struct local_ap); |
2234 | |
2235 | priv->aplist.size = 0; |
2236 | memset(&priv->aplist.ap[0], 0, size); |
2237 | } |
2238 | |
2239 | static inline void hostif_status_init(struct ks_wlan_private *priv) |
2240 | { |
2241 | priv->infra_status = 0; |
2242 | priv->current_rate = 4; |
2243 | priv->connect_status = DISCONNECT_STATUS; |
2244 | } |
2245 | |
2246 | static inline void hostif_sme_init(struct ks_wlan_private *priv) |
2247 | { |
2248 | priv->sme_i.sme_status = SME_IDLE; |
2249 | priv->sme_i.qhead = 0; |
2250 | priv->sme_i.qtail = 0; |
2251 | spin_lock_init(&priv->sme_i.sme_spin); |
2252 | priv->sme_i.sme_flag = 0; |
2253 | INIT_WORK(&priv->sme_work, hostif_sme_work); |
2254 | } |
2255 | |
2256 | static inline void hostif_wpa_init(struct ks_wlan_private *priv) |
2257 | { |
2258 | memset(&priv->wpa, 0, sizeof(priv->wpa)); |
2259 | priv->wpa.rsn_enabled = false; |
2260 | priv->wpa.mic_failure.failure = 0; |
2261 | priv->wpa.mic_failure.last_failure_time = 0; |
2262 | priv->wpa.mic_failure.stop = 0; |
2263 | } |
2264 | |
2265 | static inline void hostif_power_save_init(struct ks_wlan_private *priv) |
2266 | { |
2267 | atomic_set(v: &priv->psstatus.status, i: PS_NONE); |
2268 | atomic_set(v: &priv->psstatus.confirm_wait, i: 0); |
2269 | atomic_set(v: &priv->psstatus.snooze_guard, i: 0); |
2270 | init_completion(x: &priv->psstatus.wakeup_wait); |
2271 | INIT_WORK(&priv->wakeup_work, ks_wlan_hw_wakeup_task); |
2272 | } |
2273 | |
2274 | static inline void hostif_pmklist_init(struct ks_wlan_private *priv) |
2275 | { |
2276 | int i; |
2277 | |
2278 | memset(&priv->pmklist, 0, sizeof(priv->pmklist)); |
2279 | INIT_LIST_HEAD(list: &priv->pmklist.head); |
2280 | for (i = 0; i < PMK_LIST_MAX; i++) |
2281 | INIT_LIST_HEAD(list: &priv->pmklist.pmk[i].list); |
2282 | } |
2283 | |
2284 | static inline void hostif_counters_init(struct ks_wlan_private *priv) |
2285 | { |
2286 | priv->dev_count = 0; |
2287 | atomic_set(v: &priv->event_count, i: 0); |
2288 | atomic_set(v: &priv->rec_count, i: 0); |
2289 | } |
2290 | |
2291 | int hostif_init(struct ks_wlan_private *priv) |
2292 | { |
2293 | hostif_aplist_init(priv); |
2294 | hostif_status_init(priv); |
2295 | |
2296 | spin_lock_init(&priv->multicast_spin); |
2297 | spin_lock_init(&priv->dev_read_lock); |
2298 | init_waitqueue_head(&priv->devread_wait); |
2299 | |
2300 | hostif_counters_init(priv); |
2301 | hostif_power_save_init(priv); |
2302 | hostif_wpa_init(priv); |
2303 | hostif_pmklist_init(priv); |
2304 | hostif_sme_init(priv); |
2305 | |
2306 | return 0; |
2307 | } |
2308 | |
2309 | void hostif_exit(struct ks_wlan_private *priv) |
2310 | { |
2311 | cancel_work_sync(work: &priv->sme_work); |
2312 | } |
2313 | |