blob: a8822fe2bd60295ded9a8dfc15d5ee75556bd406 [file] [log] [blame]
Wolfram Sang13a99302016-05-31 12:56:13 +02001/*
2 * Driver for KeyStream wireless LAN cards.
3 *
Wolfram Sang13a99302016-05-31 12:56:13 +02004 * Copyright (C) 2005-2008 KeyStream Corp.
5 * Copyright (C) 2009 Renesas Technology Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
Wolfram Sangc5d9a032016-05-31 12:56:43 +02008 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
Wolfram Sang13a99302016-05-31 12:56:13 +020010 */
11
12#include "ks_wlan.h"
Wolfram Sang13a99302016-05-31 12:56:13 +020013#include "ks_hostif.h"
14#include "eap_packet.h"
15#include "michael_mic.h"
16
17#include <linux/if_ether.h>
18#include <linux/if_arp.h>
19
20/* Include Wireless Extension definition and check version */
Wolfram Sang13a99302016-05-31 12:56:13 +020021#include <net/iw_handler.h> /* New driver API */
Wolfram Sang13a99302016-05-31 12:56:13 +020022
Wolfram Sang20c4f9c2016-05-31 12:56:30 +020023extern int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p,
24 unsigned long size,
25 void (*complete_handler) (void *arg1, void *arg2),
26 void *arg1, void *arg2);
Wolfram Sang13a99302016-05-31 12:56:13 +020027extern void send_packet_complete(void *, void *);
28
Wolfram Sangfeedcf12016-05-31 12:56:26 +020029extern void ks_wlan_hw_wakeup_request(struct ks_wlan_private *priv);
30extern int ks_wlan_hw_power_save(struct ks_wlan_private *priv);
Wolfram Sang13a99302016-05-31 12:56:13 +020031
32/* macro */
33#define inc_smeqhead(priv) \
34 ( priv->sme_i.qhead = (priv->sme_i.qhead + 1) % SME_EVENT_BUFF_SIZE )
35#define inc_smeqtail(priv) \
36 ( priv->sme_i.qtail = (priv->sme_i.qtail + 1) % SME_EVENT_BUFF_SIZE )
37#define cnt_smeqbody(priv) \
38 (((priv->sme_i.qtail + SME_EVENT_BUFF_SIZE) - (priv->sme_i.qhead)) % SME_EVENT_BUFF_SIZE )
39
40#define KS_WLAN_MEM_FLAG (GFP_ATOMIC)
41
42static
Wolfram Sangfeedcf12016-05-31 12:56:26 +020043inline u8 get_BYTE(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +020044{
45 u8 data;
46 data = *(priv->rxp)++;
47 /* length check in advance ! */
48 --(priv->rx_size);
49 return data;
50}
51
52static
Wolfram Sangfeedcf12016-05-31 12:56:26 +020053inline u16 get_WORD(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +020054{
55 u16 data;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +020056 data = (get_BYTE(priv) & 0xff);
Wolfram Sang13a99302016-05-31 12:56:13 +020057 data |= ((get_BYTE(priv) << 8) & 0xff00);
58 return data;
59}
60
61static
Wolfram Sangfeedcf12016-05-31 12:56:26 +020062inline u32 get_DWORD(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +020063{
64 u32 data;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +020065 data = (get_BYTE(priv) & 0xff);
Wolfram Sang13a99302016-05-31 12:56:13 +020066 data |= ((get_BYTE(priv) << 8) & 0x0000ff00);
67 data |= ((get_BYTE(priv) << 16) & 0x00ff0000);
68 data |= ((get_BYTE(priv) << 24) & 0xff000000);
69 return data;
70}
71
72void ks_wlan_hw_wakeup_task(struct work_struct *work)
73{
Wolfram Sang20c4f9c2016-05-31 12:56:30 +020074 struct ks_wlan_private *priv =
75 container_of(work, struct ks_wlan_private, ks_wlan_wakeup_task);
Wolfram Sang13a99302016-05-31 12:56:13 +020076 int ps_status = atomic_read(&priv->psstatus.status);
77
Wolfram Sang20c4f9c2016-05-31 12:56:30 +020078 if (ps_status == PS_SNOOZE) {
Wolfram Sang13a99302016-05-31 12:56:13 +020079 ks_wlan_hw_wakeup_request(priv);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +020080 if (!wait_for_completion_interruptible_timeout(&priv->psstatus.wakeup_wait, HZ / 50)) { /* 20ms timeout */
81 DPRINTK(1, "wake up timeout !!!\n");
Wolfram Sang13a99302016-05-31 12:56:13 +020082 schedule_work(&priv->ks_wlan_wakeup_task);
83 return;
84 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +020085 } else {
86 DPRINTK(1, "ps_status=%d\n", ps_status);
Wolfram Sang13a99302016-05-31 12:56:13 +020087 }
88
89 /* power save */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +020090 if (atomic_read(&priv->sme_task.count) > 0) {
91 DPRINTK(4, "sme task enable.\n");
Wolfram Sang13a99302016-05-31 12:56:13 +020092 tasklet_enable(&priv->sme_task);
93 }
94}
95
96static
Wolfram Sangfeedcf12016-05-31 12:56:26 +020097int ks_wlan_do_power_save(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +020098{
Wolfram Sang20c4f9c2016-05-31 12:56:30 +020099 int rc = 0;
Wolfram Sang13a99302016-05-31 12:56:13 +0200100
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200101 DPRINTK(4, "psstatus.status=%d\n", atomic_read(&priv->psstatus.status));
Wolfram Sang13a99302016-05-31 12:56:13 +0200102
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200103 if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200104 hostif_sme_enqueue(priv, SME_POW_MNGMT_REQUEST);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200105 } else {
Wolfram Sang13a99302016-05-31 12:56:13 +0200106 priv->dev_state = DEVICE_STATE_READY;
107 }
Wolfram Sang13a99302016-05-31 12:56:13 +0200108 return rc;
109}
110
111static
Wolfram Sangfeedcf12016-05-31 12:56:26 +0200112int get_current_ap(struct ks_wlan_private *priv, struct link_ap_info_t *ap_info)
Wolfram Sang13a99302016-05-31 12:56:13 +0200113{
114 struct local_ap_t *ap;
Wolfram Sang13a99302016-05-31 12:56:13 +0200115 union iwreq_data wrqu;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200116 struct net_device *netdev = priv->net_dev;
117 int rc = 0;
Wolfram Sang13a99302016-05-31 12:56:13 +0200118
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200119 DPRINTK(3, "\n");
Wolfram Sang13a99302016-05-31 12:56:13 +0200120 ap = &(priv->current_ap);
121
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200122 if ((priv->connect_status & CONNECT_STATUS_MASK) == DISCONNECT_STATUS) {
123 memset(ap, 0, sizeof(struct local_ap_t));
Wolfram Sang13a99302016-05-31 12:56:13 +0200124 return 1;
125 }
126
127 /* bssid */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200128 memcpy(&(ap->bssid[0]), &(ap_info->bssid[0]), ETH_ALEN);
Wolfram Sang13a99302016-05-31 12:56:13 +0200129 /* essid */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200130 memcpy(&(ap->ssid.body[0]), &(priv->reg.ssid.body[0]),
131 priv->reg.ssid.size);
Wolfram Sang13a99302016-05-31 12:56:13 +0200132 ap->ssid.size = priv->reg.ssid.size;
133 /* rate_set */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200134 memcpy(&(ap->rate_set.body[0]), &(ap_info->rate_set.body[0]),
135 ap_info->rate_set.size);
Wolfram Sang13a99302016-05-31 12:56:13 +0200136 ap->rate_set.size = ap_info->rate_set.size;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200137 if (ap_info->ext_rate_set.size) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200138 /* rate_set */
139 memcpy(&(ap->rate_set.body[ap->rate_set.size]),
140 &(ap_info->ext_rate_set.body[0]),
141 ap_info->ext_rate_set.size);
142 ap->rate_set.size += ap_info->ext_rate_set.size;
143 }
144 /* channel */
145 ap->channel = ap_info->ds_parameter.channel;
146 /* rssi */
147 ap->rssi = ap_info->rssi;
148 /* sq */
149 ap->sq = ap_info->sq;
150 /* noise */
151 ap->noise = ap_info->noise;
152 /* capability */
153 ap->capability = ap_info->capability;
154 /* rsn */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200155 if ((ap_info->rsn_mode & RSN_MODE_WPA2)
156 && (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200157 ap->rsn_ie.id = 0x30;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200158 if (ap_info->rsn.size <= RSN_IE_BODY_MAX) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200159 ap->rsn_ie.size = ap_info->rsn.size;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200160 memcpy(&(ap->rsn_ie.body[0]), &(ap_info->rsn.body[0]),
161 ap_info->rsn.size);
162 } else {
Wolfram Sang13a99302016-05-31 12:56:13 +0200163 ap->rsn_ie.size = RSN_IE_BODY_MAX;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200164 memcpy(&(ap->rsn_ie.body[0]), &(ap_info->rsn.body[0]),
165 RSN_IE_BODY_MAX);
Wolfram Sang13a99302016-05-31 12:56:13 +0200166 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200167 } else if ((ap_info->rsn_mode & RSN_MODE_WPA)
168 && (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA)) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200169 ap->wpa_ie.id = 0xdd;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200170 if (ap_info->rsn.size <= RSN_IE_BODY_MAX) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200171 ap->wpa_ie.size = ap_info->rsn.size;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200172 memcpy(&(ap->wpa_ie.body[0]), &(ap_info->rsn.body[0]),
173 ap_info->rsn.size);
174 } else {
Wolfram Sang13a99302016-05-31 12:56:13 +0200175 ap->wpa_ie.size = RSN_IE_BODY_MAX;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200176 memcpy(&(ap->wpa_ie.body[0]), &(ap_info->rsn.body[0]),
177 RSN_IE_BODY_MAX);
Wolfram Sang13a99302016-05-31 12:56:13 +0200178 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200179 } else {
Wolfram Sang13a99302016-05-31 12:56:13 +0200180 ap->rsn_ie.id = 0;
181 ap->rsn_ie.size = 0;
182 ap->wpa_ie.id = 0;
183 ap->wpa_ie.size = 0;
184 }
185
Wolfram Sang13a99302016-05-31 12:56:13 +0200186 wrqu.data.length = 0;
187 wrqu.data.flags = 0;
188 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200189 if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200190 memcpy(wrqu.ap_addr.sa_data,
191 &(priv->current_ap.bssid[0]), ETH_ALEN);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200192 DPRINTK(3,
193 "IWEVENT: connect bssid=%02x:%02x:%02x:%02x:%02x:%02x\n",
194 (unsigned char)wrqu.ap_addr.sa_data[0],
195 (unsigned char)wrqu.ap_addr.sa_data[1],
196 (unsigned char)wrqu.ap_addr.sa_data[2],
197 (unsigned char)wrqu.ap_addr.sa_data[3],
198 (unsigned char)wrqu.ap_addr.sa_data[4],
199 (unsigned char)wrqu.ap_addr.sa_data[5]);
Wolfram Sang13a99302016-05-31 12:56:13 +0200200 wireless_send_event(netdev, SIOCGIWAP, &wrqu, NULL);
201 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200202 DPRINTK(4, "\n Link AP\n");
203 DPRINTK(4, " bssid=%02X:%02X:%02X:%02X:%02X:%02X\n \
Wolfram Sang13a99302016-05-31 12:56:13 +0200204 essid=%s\n rate_set=%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X\n channel=%d\n \
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200205 rssi=%d\n sq=%d\n capability=%04X\n", ap->bssid[0], ap->bssid[1], ap->bssid[2], ap->bssid[3], ap->bssid[4], ap->bssid[5], &(ap->ssid.body[0]), ap->rate_set.body[0], ap->rate_set.body[1], ap->rate_set.body[2], ap->rate_set.body[3], ap->rate_set.body[4], ap->rate_set.body[5], ap->rate_set.body[6], ap->rate_set.body[7], ap->channel, ap->rssi, ap->sq, ap->capability);
206 DPRINTK(4, "\n Link AP\n rsn.mode=%d\n rsn.size=%d\n",
207 ap_info->rsn_mode, ap_info->rsn.size);
208 DPRINTK(4, "\n ext_rate_set_size=%d\n rate_set_size=%d\n",
209 ap_info->ext_rate_set.size, ap_info->rate_set.size);
Wolfram Sang13a99302016-05-31 12:56:13 +0200210
211 return rc;
212}
213
214static
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200215int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info,
216 struct local_ap_t *ap)
Wolfram Sang13a99302016-05-31 12:56:13 +0200217{
218 unsigned char *bp;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200219 int bsize, offset;
220 int rc = 0;
Wolfram Sang13a99302016-05-31 12:56:13 +0200221
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200222 DPRINTK(3, "\n");
223 memset(ap, 0, sizeof(struct local_ap_t));
Wolfram Sang13a99302016-05-31 12:56:13 +0200224
225 /* bssid */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200226 memcpy(&(ap->bssid[0]), &(ap_info->bssid[0]), ETH_ALEN);
Wolfram Sang13a99302016-05-31 12:56:13 +0200227 /* rssi */
228 ap->rssi = ap_info->rssi;
229 /* sq */
230 ap->sq = ap_info->sq;
231 /* noise */
232 ap->noise = ap_info->noise;
233 /* capability */
234 ap->capability = ap_info->capability;
235 /* channel */
236 ap->channel = ap_info->ch_info;
237
238 bp = &(ap_info->body[0]);
239 bsize = ap_info->body_size;
240 offset = 0;
241
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200242 while (bsize > offset) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200243 /* DPRINTK(4, "Element ID=%d \n",*bp); */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200244 switch (*bp) {
245 case 0: /* ssid */
246 if (*(bp + 1) <= SSID_MAX_SIZE) {
247 ap->ssid.size = *(bp + 1);
248 } else {
249 DPRINTK(1, "size over :: ssid size=%d \n",
250 *(bp + 1));
Wolfram Sang13a99302016-05-31 12:56:13 +0200251 ap->ssid.size = SSID_MAX_SIZE;
252 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200253 memcpy(&(ap->ssid.body[0]), bp + 2, ap->ssid.size);
Wolfram Sang13a99302016-05-31 12:56:13 +0200254 break;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200255 case 1: /* rate */
256 case 50: /* ext rate */
257 if ((*(bp + 1) + ap->rate_set.size) <=
258 RATE_SET_MAX_SIZE) {
259 memcpy(&(ap->rate_set.body[ap->rate_set.size]),
260 bp + 2, *(bp + 1));
261 ap->rate_set.size += *(bp + 1);
262 } else {
Wolfram Sang13a99302016-05-31 12:56:13 +0200263 DPRINTK(1, "size over :: rate size=%d \n",
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200264 (*(bp + 1) + ap->rate_set.size));
265 memcpy(&(ap->rate_set.body[ap->rate_set.size]),
266 bp + 2,
Wolfram Sang13a99302016-05-31 12:56:13 +0200267 RATE_SET_MAX_SIZE - ap->rate_set.size);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200268 ap->rate_set.size +=
269 (RATE_SET_MAX_SIZE - ap->rate_set.size);
Wolfram Sang13a99302016-05-31 12:56:13 +0200270 }
271 break;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200272 case 3: /* DS parameter */
Wolfram Sang13a99302016-05-31 12:56:13 +0200273 break;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200274 case 48: /* RSN(WPA2) */
Wolfram Sang13a99302016-05-31 12:56:13 +0200275 ap->rsn_ie.id = *bp;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200276 if (*(bp + 1) <= RSN_IE_BODY_MAX) {
277 ap->rsn_ie.size = *(bp + 1);
278 } else {
279 DPRINTK(1, "size over :: rsn size=%d \n",
280 *(bp + 1));
Wolfram Sang13a99302016-05-31 12:56:13 +0200281 ap->rsn_ie.size = RSN_IE_BODY_MAX;
282 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200283 memcpy(&(ap->rsn_ie.body[0]), bp + 2, ap->rsn_ie.size);
Wolfram Sang13a99302016-05-31 12:56:13 +0200284 break;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200285 case 221: /* WPA */
286 if (!memcmp(bp + 2, "\x00\x50\xf2\x01", 4)) { /* WPA OUI check */
Wolfram Sang13a99302016-05-31 12:56:13 +0200287 ap->wpa_ie.id = *bp;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200288 if (*(bp + 1) <= RSN_IE_BODY_MAX) {
289 ap->wpa_ie.size = *(bp + 1);
290 } else {
291 DPRINTK(1,
292 "size over :: wpa size=%d \n",
293 *(bp + 1));
Wolfram Sang13a99302016-05-31 12:56:13 +0200294 ap->wpa_ie.size = RSN_IE_BODY_MAX;
295 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200296 memcpy(&(ap->wpa_ie.body[0]), bp + 2,
297 ap->wpa_ie.size);
Wolfram Sang13a99302016-05-31 12:56:13 +0200298 }
299 break;
300
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200301 case 2: /* FH parameter */
302 case 4: /* CF parameter */
303 case 5: /* TIM */
304 case 6: /* IBSS parameter */
305 case 7: /* Country */
306 case 42: /* ERP information */
307 case 47: /* Reserve ID 47 Broadcom AP */
Wolfram Sang13a99302016-05-31 12:56:13 +0200308 break;
309 default:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200310 DPRINTK(4, "unknown Element ID=%d \n", *bp);
Wolfram Sang13a99302016-05-31 12:56:13 +0200311 break;
312 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200313 offset += 2; /* id & size field */
314 offset += *(bp + 1); /* +size offset */
315 bp += (*(bp + 1) + 2); /* pointer update */
Wolfram Sang13a99302016-05-31 12:56:13 +0200316 }
317
318 return rc;
319}
320
321static
Wolfram Sangfeedcf12016-05-31 12:56:26 +0200322void hostif_data_indication(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +0200323{
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200324 unsigned int rx_ind_size; /* indicate data size */
Wolfram Sang13a99302016-05-31 12:56:13 +0200325 struct sk_buff *skb;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200326 unsigned short auth_type;
327 unsigned char temp[256];
Wolfram Sang13a99302016-05-31 12:56:13 +0200328
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200329 unsigned char RecvMIC[8];
Wolfram Sang13a99302016-05-31 12:56:13 +0200330 char buf[128];
331 struct ether_hdr *eth_hdr;
332 unsigned short eth_proto;
333 unsigned long now;
334 struct mic_failure_t *mic_failure;
335 struct ieee802_1x_hdr *aa1x_hdr;
336 struct wpa_eapol_key *eap_key;
337 struct michel_mic_t michel_mic;
Wolfram Sang13a99302016-05-31 12:56:13 +0200338 union iwreq_data wrqu;
Wolfram Sang13a99302016-05-31 12:56:13 +0200339
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200340 DPRINTK(3, "\n");
Wolfram Sang13a99302016-05-31 12:56:13 +0200341
342 /* min length check */
343 if (priv->rx_size <= ETH_HLEN) {
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200344 DPRINTK(3, "rx_size = %d\n", priv->rx_size);
Wolfram Sang13a99302016-05-31 12:56:13 +0200345 priv->nstats.rx_errors++;
346 return;
347 }
348
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200349 auth_type = get_WORD(priv); /* AuthType */
350 get_WORD(priv); /* Reserve Area */
Wolfram Sang13a99302016-05-31 12:56:13 +0200351
352 eth_hdr = (struct ether_hdr *)(priv->rxp);
353 eth_proto = ntohs(eth_hdr->h_proto);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200354 DPRINTK(3, "ether protocol = %04X\n", eth_proto);
Wolfram Sang13a99302016-05-31 12:56:13 +0200355
356 /* source address check */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200357 if (!memcmp(&priv->eth_addr[0], eth_hdr->h_source, ETH_ALEN)) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200358 DPRINTK(1, "invalid : source is own mac address !!\n");
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200359 DPRINTK(1,
360 "eth_hdrernet->h_dest=%02X:%02X:%02X:%02X:%02X:%02X\n",
361 eth_hdr->h_source[0], eth_hdr->h_source[1],
362 eth_hdr->h_source[2], eth_hdr->h_source[3],
363 eth_hdr->h_source[4], eth_hdr->h_source[5]);
Wolfram Sang13a99302016-05-31 12:56:13 +0200364 priv->nstats.rx_errors++;
365 return;
366 }
367
368 /* for WPA */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200369 if (auth_type != TYPE_DATA && priv->wpa.rsn_enabled) {
370 if (memcmp(&eth_hdr->h_source[0], &priv->eth_addr[0], ETH_ALEN)) { /* source address check */
371 if (eth_hdr->h_dest_snap != eth_hdr->h_source_snap) {
372 DPRINTK(1, "invalid data format\n");
Wolfram Sang13a99302016-05-31 12:56:13 +0200373 priv->nstats.rx_errors++;
374 return;
375 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200376 if (((auth_type == TYPE_PMK1
377 && priv->wpa.pairwise_suite ==
378 IW_AUTH_CIPHER_TKIP) || (auth_type == TYPE_GMK1
379 && priv->wpa.
380 group_suite ==
381 IW_AUTH_CIPHER_TKIP)
382 || (auth_type == TYPE_GMK2
383 && priv->wpa.group_suite ==
384 IW_AUTH_CIPHER_TKIP))
385 && priv->wpa.key[auth_type - 1].key_len) {
386 DPRINTK(4, "TKIP: protocol=%04X: size=%u\n",
387 eth_proto, priv->rx_size);
Wolfram Sang13a99302016-05-31 12:56:13 +0200388 /* MIC save */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200389 memcpy(&RecvMIC[0],
390 (priv->rxp) + ((priv->rx_size) - 8), 8);
Wolfram Sang13a99302016-05-31 12:56:13 +0200391 priv->rx_size = priv->rx_size - 8;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200392 if (auth_type > 0 && auth_type < 4) { /* auth_type check */
393 MichaelMICFunction(&michel_mic, (uint8_t *) priv->wpa.key[auth_type - 1].rx_mic_key, (uint8_t *) priv->rxp, (int)priv->rx_size, (uint8_t) 0, /* priority */
394 (uint8_t *)
395 michel_mic.Result);
Wolfram Sang13a99302016-05-31 12:56:13 +0200396 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200397 if (memcmp(michel_mic.Result, RecvMIC, 8)) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200398 now = jiffies;
399 mic_failure = &priv->wpa.mic_failure;
400 /* MIC FAILURE */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200401 if (mic_failure->last_failure_time &&
402 (now -
403 mic_failure->last_failure_time) /
404 HZ >= 60) {
405 mic_failure->failure = 0;
Wolfram Sang13a99302016-05-31 12:56:13 +0200406 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200407 DPRINTK(4, "MIC FAILURE \n");
408 if (mic_failure->failure == 0) {
409 mic_failure->failure = 1;
410 mic_failure->counter = 0;
411 } else if (mic_failure->failure == 1) {
412 mic_failure->failure = 2;
Wolfram Sang13a99302016-05-31 12:56:13 +0200413 mic_failure->counter =
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200414 (uint16_t) ((now -
415 mic_failure->
416 last_failure_time)
417 / HZ);
418 if (!mic_failure->counter) /* mic_failure counter value range 1-60 */
419 mic_failure->counter =
420 1;
Wolfram Sang13a99302016-05-31 12:56:13 +0200421 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200422 priv->wpa.mic_failure.
423 last_failure_time = now;
Wolfram Sang13a99302016-05-31 12:56:13 +0200424 /* needed parameters: count, keyid, key type, TSC */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200425 sprintf(buf,
426 "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
Wolfram Sang13a99302016-05-31 12:56:13 +0200427 "%02x:%02x:%02x:%02x:%02x:%02x)",
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200428 auth_type - 1,
429 eth_hdr->
430 h_dest[0] & 0x01 ? "broad" :
431 "uni", eth_hdr->h_source[0],
432 eth_hdr->h_source[1],
433 eth_hdr->h_source[2],
434 eth_hdr->h_source[3],
435 eth_hdr->h_source[4],
436 eth_hdr->h_source[5]);
Wolfram Sang13a99302016-05-31 12:56:13 +0200437 memset(&wrqu, 0, sizeof(wrqu));
438 wrqu.data.length = strlen(buf);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200439 DPRINTK(4,
440 "IWEVENT:MICHAELMICFAILURE\n");
441 wireless_send_event(priv->net_dev,
442 IWEVCUSTOM, &wrqu,
443 buf);
Wolfram Sang13a99302016-05-31 12:56:13 +0200444 return;
445 }
446 }
447 }
448 }
449
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200450 if ((priv->connect_status & FORCE_DISCONNECT) ||
451 priv->wpa.mic_failure.failure == 2) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200452 return;
453 }
454
455 /* check 13th byte at rx data */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200456 switch (*(priv->rxp + 12)) {
457 case 0xAA: /* SNAP */
Wolfram Sang13a99302016-05-31 12:56:13 +0200458 rx_ind_size = priv->rx_size - 6;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200459 skb = dev_alloc_skb(rx_ind_size);
460 DPRINTK(4, "SNAP, rx_ind_size = %d\n", rx_ind_size);
Wolfram Sang13a99302016-05-31 12:56:13 +0200461
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200462 if (skb) {
463 memcpy(skb_put(skb, 12), priv->rxp, 12); /* 8802/FDDI MAC copy */
464 /* (SNAP+UI..) skip */
465 memcpy(skb_put(skb, rx_ind_size - 12), priv->rxp + 18, rx_ind_size - 12); /* copy after Type */
Wolfram Sang13a99302016-05-31 12:56:13 +0200466
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200467 aa1x_hdr = (struct ieee802_1x_hdr *)(priv->rxp + 20);
468 if (aa1x_hdr->type == IEEE802_1X_TYPE_EAPOL_KEY
469 && priv->wpa.rsn_enabled) {
470 eap_key =
471 (struct wpa_eapol_key *)(aa1x_hdr + 1);
Wolfram Sang13a99302016-05-31 12:56:13 +0200472 atomic_set(&priv->psstatus.snooze_guard, 1);
473 }
474
475 /* rx indication */
476 skb->dev = priv->net_dev;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200477 skb->protocol = eth_type_trans(skb, skb->dev);
Wolfram Sang13a99302016-05-31 12:56:13 +0200478 priv->nstats.rx_packets++;
479 priv->nstats.rx_bytes += rx_ind_size;
480 skb->dev->last_rx = jiffies;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200481 netif_rx(skb);
Wolfram Sang13a99302016-05-31 12:56:13 +0200482 } else {
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200483 printk(KERN_WARNING
484 "%s: Memory squeeze, dropping packet.\n",
485 skb->dev->name);
Wolfram Sang13a99302016-05-31 12:56:13 +0200486 priv->nstats.rx_dropped++;
487 }
488 break;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200489 case 0xF0: /* NETBEUI/NetBIOS */
Wolfram Sang13a99302016-05-31 12:56:13 +0200490 rx_ind_size = (priv->rx_size + 2);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200491 skb = dev_alloc_skb(rx_ind_size);
492 DPRINTK(3, "NETBEUI/NetBIOS rx_ind_size=%d\n", rx_ind_size);
Wolfram Sang13a99302016-05-31 12:56:13 +0200493
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200494 if (skb) {
495 memcpy(skb_put(skb, 12), priv->rxp, 12); /* 8802/FDDI MAC copy */
Wolfram Sang13a99302016-05-31 12:56:13 +0200496
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200497 temp[0] = (((rx_ind_size - 12) >> 8) & 0xff); /* NETBEUI size add */
498 temp[1] = ((rx_ind_size - 12) & 0xff);
499 memcpy(skb_put(skb, 2), temp, 2);
Wolfram Sang13a99302016-05-31 12:56:13 +0200500
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200501 memcpy(skb_put(skb, rx_ind_size - 14), priv->rxp + 12, rx_ind_size - 14); /* copy after Type */
Wolfram Sang13a99302016-05-31 12:56:13 +0200502
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200503 aa1x_hdr = (struct ieee802_1x_hdr *)(priv->rxp + 14);
504 if (aa1x_hdr->type == IEEE802_1X_TYPE_EAPOL_KEY
505 && priv->wpa.rsn_enabled) {
506 eap_key =
507 (struct wpa_eapol_key *)(aa1x_hdr + 1);
Wolfram Sang13a99302016-05-31 12:56:13 +0200508 atomic_set(&priv->psstatus.snooze_guard, 1);
509 }
510
511 /* rx indication */
512 skb->dev = priv->net_dev;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200513 skb->protocol = eth_type_trans(skb, skb->dev);
Wolfram Sang13a99302016-05-31 12:56:13 +0200514 priv->nstats.rx_packets++;
515 priv->nstats.rx_bytes += rx_ind_size;
516 skb->dev->last_rx = jiffies;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200517 netif_rx(skb);
Wolfram Sang13a99302016-05-31 12:56:13 +0200518 } else {
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200519 printk(KERN_WARNING
520 "%s: Memory squeeze, dropping packet.\n",
521 skb->dev->name);
Wolfram Sang13a99302016-05-31 12:56:13 +0200522 priv->nstats.rx_dropped++;
523 }
524 break;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200525 default: /* other rx data */
526 DPRINTK(2, "invalid data format\n");
Wolfram Sang13a99302016-05-31 12:56:13 +0200527 priv->nstats.rx_errors++;
528 }
529}
530
531static
Wolfram Sangfeedcf12016-05-31 12:56:26 +0200532void hostif_mib_get_confirm(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +0200533{
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200534 struct net_device *dev = priv->net_dev;
535 uint32_t mib_status;
536 uint32_t mib_attribute;
537 uint16_t mib_val_size;
538 uint16_t mib_val_type;
Wolfram Sang13a99302016-05-31 12:56:13 +0200539
540 DPRINTK(3, "\n");
541
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200542 mib_status = get_DWORD(priv); /* MIB status */
543 mib_attribute = get_DWORD(priv); /* MIB atttibute */
544 mib_val_size = get_WORD(priv); /* MIB value size */
545 mib_val_type = get_WORD(priv); /* MIB value type */
Wolfram Sang13a99302016-05-31 12:56:13 +0200546
547 if (mib_status != 0) {
548 /* in case of error */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200549 DPRINTK(1, "attribute=%08X, status=%08X\n", mib_attribute,
550 mib_status);
Wolfram Sang13a99302016-05-31 12:56:13 +0200551 return;
552 }
553
554 switch (mib_attribute) {
555 case DOT11_MAC_ADDRESS:
556 /* MAC address */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200557 DPRINTK(3, " mib_attribute=DOT11_MAC_ADDRESS\n");
Wolfram Sang13a99302016-05-31 12:56:13 +0200558 hostif_sme_enqueue(priv, SME_GET_MAC_ADDRESS);
559 memcpy(priv->eth_addr, priv->rxp, ETH_ALEN);
560 priv->mac_address_valid = 1;
561 dev->dev_addr[0] = priv->eth_addr[0];
562 dev->dev_addr[1] = priv->eth_addr[1];
563 dev->dev_addr[2] = priv->eth_addr[2];
564 dev->dev_addr[3] = priv->eth_addr[3];
565 dev->dev_addr[4] = priv->eth_addr[4];
566 dev->dev_addr[5] = priv->eth_addr[5];
567 dev->dev_addr[6] = 0x00;
568 dev->dev_addr[7] = 0x00;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200569 printk(KERN_INFO
570 "ks_wlan: MAC ADDRESS = %02x:%02x:%02x:%02x:%02x:%02x\n",
571 priv->eth_addr[0], priv->eth_addr[1], priv->eth_addr[2],
572 priv->eth_addr[3], priv->eth_addr[4], priv->eth_addr[5]);
Wolfram Sang13a99302016-05-31 12:56:13 +0200573 break;
574 case DOT11_PRODUCT_VERSION:
575 /* firmware version */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200576 DPRINTK(3, " mib_attribute=DOT11_PRODUCT_VERSION\n");
Wolfram Sang13a99302016-05-31 12:56:13 +0200577 priv->version_size = priv->rx_size;
578 memcpy(priv->firmware_version, priv->rxp, priv->rx_size);
579 priv->firmware_version[priv->rx_size] = '\0';
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200580 printk(KERN_INFO "ks_wlan: firmware ver. = %s\n",
581 priv->firmware_version);
Wolfram Sang13a99302016-05-31 12:56:13 +0200582 hostif_sme_enqueue(priv, SME_GET_PRODUCT_VERSION);
583 /* wake_up_interruptible_all(&priv->confirm_wait); */
584 complete(&priv->confirm_wait);
585 break;
586 case LOCAL_GAIN:
587 memcpy(&priv->gain, priv->rxp, sizeof(priv->gain));
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200588 DPRINTK(3, "TxMode=%d, RxMode=%d, TxGain=%d, RxGain=%d\n",
589 priv->gain.TxMode, priv->gain.RxMode, priv->gain.TxGain,
590 priv->gain.RxGain);
Wolfram Sang13a99302016-05-31 12:56:13 +0200591 break;
592 case LOCAL_EEPROM_SUM:
593 memcpy(&priv->eeprom_sum, priv->rxp, sizeof(priv->eeprom_sum));
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200594 DPRINTK(1, "eeprom_sum.type=%x, eeprom_sum.result=%x\n",
595 priv->eeprom_sum.type, priv->eeprom_sum.result);
596 if (priv->eeprom_sum.type == 0) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200597 priv->eeprom_checksum = EEPROM_CHECKSUM_NONE;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200598 } else if (priv->eeprom_sum.type == 1) {
599 if (priv->eeprom_sum.result == 0) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200600 priv->eeprom_checksum = EEPROM_NG;
601 printk("LOCAL_EEPROM_SUM NG\n");
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200602 } else if (priv->eeprom_sum.result == 1) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200603 priv->eeprom_checksum = EEPROM_OK;
604 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200605 } else {
Wolfram Sang13a99302016-05-31 12:56:13 +0200606 printk("LOCAL_EEPROM_SUM error!\n");
607 }
608 break;
609 default:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200610 DPRINTK(1, "mib_attribute=%08x\n", (unsigned int)mib_attribute);
Wolfram Sang13a99302016-05-31 12:56:13 +0200611 break;
612 }
613}
614
615static
Wolfram Sangfeedcf12016-05-31 12:56:26 +0200616void hostif_mib_set_confirm(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +0200617{
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200618 uint32_t mib_status; /* +04 MIB Status */
619 uint32_t mib_attribute; /* +08 MIB attribute */
Wolfram Sang13a99302016-05-31 12:56:13 +0200620
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200621 DPRINTK(3, "\n");
Wolfram Sang13a99302016-05-31 12:56:13 +0200622
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200623 mib_status = get_DWORD(priv); /* MIB Status */
624 mib_attribute = get_DWORD(priv); /* MIB attribute */
Wolfram Sang13a99302016-05-31 12:56:13 +0200625
626 if (mib_status != 0) {
627 /* in case of error */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200628 DPRINTK(1, "error :: attribute=%08X, status=%08X\n",
629 mib_attribute, mib_status);
Wolfram Sang13a99302016-05-31 12:56:13 +0200630 }
631
632 switch (mib_attribute) {
633 case DOT11_RTS_THRESHOLD:
634 hostif_sme_enqueue(priv, SME_RTS_THRESHOLD_CONFIRM);
635 break;
636 case DOT11_FRAGMENTATION_THRESHOLD:
637 hostif_sme_enqueue(priv, SME_FRAGMENTATION_THRESHOLD_CONFIRM);
638 break;
639 case DOT11_WEP_DEFAULT_KEY_ID:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200640 if (!priv->wpa.wpa_enabled)
Wolfram Sang13a99302016-05-31 12:56:13 +0200641 hostif_sme_enqueue(priv, SME_WEP_INDEX_CONFIRM);
642 break;
643 case DOT11_WEP_DEFAULT_KEY_VALUE1:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200644 DPRINTK(2, "DOT11_WEP_DEFAULT_KEY_VALUE1:mib_status=%d\n",
645 (int)mib_status);
646 if (priv->wpa.rsn_enabled)
Wolfram Sang13a99302016-05-31 12:56:13 +0200647 hostif_sme_enqueue(priv, SME_SET_PMK_TSC);
648 else
649 hostif_sme_enqueue(priv, SME_WEP_KEY1_CONFIRM);
650 break;
651 case DOT11_WEP_DEFAULT_KEY_VALUE2:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200652 DPRINTK(2, "DOT11_WEP_DEFAULT_KEY_VALUE2:mib_status=%d\n",
653 (int)mib_status);
654 if (priv->wpa.rsn_enabled)
Wolfram Sang13a99302016-05-31 12:56:13 +0200655 hostif_sme_enqueue(priv, SME_SET_GMK1_TSC);
656 else
657 hostif_sme_enqueue(priv, SME_WEP_KEY2_CONFIRM);
658 break;
659 case DOT11_WEP_DEFAULT_KEY_VALUE3:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200660 DPRINTK(2, "DOT11_WEP_DEFAULT_KEY_VALUE3:mib_status=%d\n",
661 (int)mib_status);
662 if (priv->wpa.rsn_enabled)
Wolfram Sang13a99302016-05-31 12:56:13 +0200663 hostif_sme_enqueue(priv, SME_SET_GMK2_TSC);
664 else
665 hostif_sme_enqueue(priv, SME_WEP_KEY3_CONFIRM);
666 break;
667 case DOT11_WEP_DEFAULT_KEY_VALUE4:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200668 DPRINTK(2, "DOT11_WEP_DEFAULT_KEY_VALUE4:mib_status=%d\n",
669 (int)mib_status);
670 if (!priv->wpa.rsn_enabled)
Wolfram Sang13a99302016-05-31 12:56:13 +0200671 hostif_sme_enqueue(priv, SME_WEP_KEY4_CONFIRM);
672 break;
673 case DOT11_PRIVACY_INVOKED:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200674 if (!priv->wpa.rsn_enabled)
Wolfram Sang13a99302016-05-31 12:56:13 +0200675 hostif_sme_enqueue(priv, SME_WEP_FLAG_CONFIRM);
676 break;
677 case DOT11_RSN_ENABLED:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200678 DPRINTK(2, "DOT11_RSN_ENABLED:mib_status=%d\n",
679 (int)mib_status);
Wolfram Sang13a99302016-05-31 12:56:13 +0200680 hostif_sme_enqueue(priv, SME_RSN_ENABLED_CONFIRM);
681 break;
682 case LOCAL_RSN_MODE:
683 hostif_sme_enqueue(priv, SME_RSN_MODE_CONFIRM);
684 break;
685 case LOCAL_MULTICAST_ADDRESS:
686 hostif_sme_enqueue(priv, SME_MULTICAST_REQUEST);
687 break;
688 case LOCAL_MULTICAST_FILTER:
689 hostif_sme_enqueue(priv, SME_MULTICAST_CONFIRM);
690 break;
691 case LOCAL_CURRENTADDRESS:
692 priv->mac_address_valid = 1;
693 break;
694 case DOT11_RSN_CONFIG_MULTICAST_CIPHER:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200695 DPRINTK(2, "DOT11_RSN_CONFIG_MULTICAST_CIPHER:mib_status=%d\n",
696 (int)mib_status);
Wolfram Sang13a99302016-05-31 12:56:13 +0200697 hostif_sme_enqueue(priv, SME_RSN_MCAST_CONFIRM);
698 break;
699 case DOT11_RSN_CONFIG_UNICAST_CIPHER:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200700 DPRINTK(2, "DOT11_RSN_CONFIG_UNICAST_CIPHER:mib_status=%d\n",
701 (int)mib_status);
Wolfram Sang13a99302016-05-31 12:56:13 +0200702 hostif_sme_enqueue(priv, SME_RSN_UCAST_CONFIRM);
703 break;
704 case DOT11_RSN_CONFIG_AUTH_SUITE:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200705 DPRINTK(2, "DOT11_RSN_CONFIG_AUTH_SUITE:mib_status=%d\n",
706 (int)mib_status);
Wolfram Sang13a99302016-05-31 12:56:13 +0200707 hostif_sme_enqueue(priv, SME_RSN_AUTH_CONFIRM);
708 break;
709 case DOT11_PMK_TSC:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200710 DPRINTK(2, "DOT11_PMK_TSC:mib_status=%d\n", (int)mib_status);
Wolfram Sang13a99302016-05-31 12:56:13 +0200711 break;
712 case DOT11_GMK1_TSC:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200713 DPRINTK(2, "DOT11_GMK1_TSC:mib_status=%d\n", (int)mib_status);
714 if (atomic_read(&priv->psstatus.snooze_guard)) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200715 atomic_set(&priv->psstatus.snooze_guard, 0);
716 }
717 break;
718 case DOT11_GMK2_TSC:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200719 DPRINTK(2, "DOT11_GMK2_TSC:mib_status=%d\n", (int)mib_status);
720 if (atomic_read(&priv->psstatus.snooze_guard)) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200721 atomic_set(&priv->psstatus.snooze_guard, 0);
722 }
723 break;
724 case LOCAL_PMK:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200725 DPRINTK(2, "LOCAL_PMK:mib_status=%d\n", (int)mib_status);
Wolfram Sang13a99302016-05-31 12:56:13 +0200726 break;
727 case LOCAL_GAIN:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200728 DPRINTK(2, "LOCAL_GAIN:mib_status=%d\n", (int)mib_status);
Wolfram Sang13a99302016-05-31 12:56:13 +0200729 break;
730#ifdef WPS
731 case LOCAL_WPS_ENABLE:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200732 DPRINTK(2, "LOCAL_WPS_ENABLE:mib_status=%d\n", (int)mib_status);
Wolfram Sang13a99302016-05-31 12:56:13 +0200733 break;
734 case LOCAL_WPS_PROBE_REQ:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200735 DPRINTK(2, "LOCAL_WPS_PROBE_REQ:mib_status=%d\n",
736 (int)mib_status);
Wolfram Sang13a99302016-05-31 12:56:13 +0200737 break;
738#endif /* WPS */
739 case LOCAL_REGION:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200740 DPRINTK(2, "LOCAL_REGION:mib_status=%d\n", (int)mib_status);
741 default:
Wolfram Sang13a99302016-05-31 12:56:13 +0200742 break;
743 }
744}
745
746static
Wolfram Sangfeedcf12016-05-31 12:56:26 +0200747void hostif_power_mngmt_confirm(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +0200748{
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200749 DPRINTK(3, "\n");
Wolfram Sang13a99302016-05-31 12:56:13 +0200750
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200751 if (priv->reg.powermgt > POWMGT_ACTIVE_MODE &&
752 priv->reg.operation_mode == MODE_INFRASTRUCTURE) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200753 atomic_set(&priv->psstatus.confirm_wait, 0);
754 priv->dev_state = DEVICE_STATE_SLEEP;
755 ks_wlan_hw_power_save(priv);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200756 } else {
Wolfram Sang13a99302016-05-31 12:56:13 +0200757 priv->dev_state = DEVICE_STATE_READY;
Wolfram Sang13a99302016-05-31 12:56:13 +0200758 }
759
760}
761
762static
Wolfram Sangfeedcf12016-05-31 12:56:26 +0200763void hostif_sleep_confirm(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +0200764{
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200765 DPRINTK(3, "\n");
Wolfram Sang13a99302016-05-31 12:56:13 +0200766
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200767 atomic_set(&priv->sleepstatus.doze_request, 1);
768 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
769 &priv->ks_wlan_hw.rw_wq, 1);
Wolfram Sang13a99302016-05-31 12:56:13 +0200770}
771
772static
Wolfram Sangfeedcf12016-05-31 12:56:26 +0200773void hostif_start_confirm(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +0200774{
775#ifdef WPS
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200776 union iwreq_data wrqu;
777 wrqu.data.length = 0;
778 wrqu.data.flags = 0;
779 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
780 if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) {
781 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
782 DPRINTK(3, "IWEVENT: disconnect\n");
783 wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);
784 }
Wolfram Sang13a99302016-05-31 12:56:13 +0200785#endif
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200786 DPRINTK(3, " scan_ind_count=%d\n", priv->scan_ind_count);
Wolfram Sang13a99302016-05-31 12:56:13 +0200787 hostif_sme_enqueue(priv, SME_START_CONFIRM);
788}
789
790static
Wolfram Sangfeedcf12016-05-31 12:56:26 +0200791void hostif_connect_indication(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +0200792{
793 unsigned short connect_code;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200794 unsigned int tmp = 0;
795 unsigned int old_status = priv->connect_status;
796 struct net_device *netdev = priv->net_dev;
Wolfram Sang13a99302016-05-31 12:56:13 +0200797 union iwreq_data wrqu0;
Wolfram Sang13a99302016-05-31 12:56:13 +0200798 connect_code = get_WORD(priv);
799
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200800 switch (connect_code) {
801 case RESULT_CONNECT: /* connect */
802 DPRINTK(3, "connect :: scan_ind_count=%d\n",
803 priv->scan_ind_count);
804 if (!(priv->connect_status & FORCE_DISCONNECT))
Wolfram Sang13a99302016-05-31 12:56:13 +0200805 netif_carrier_on(netdev);
806 tmp = FORCE_DISCONNECT & priv->connect_status;
807 priv->connect_status = tmp + CONNECT_STATUS;
808 break;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200809 case RESULT_DISCONNECT: /* disconnect */
810 DPRINTK(3, "disconnect :: scan_ind_count=%d\n",
811 priv->scan_ind_count);
Wolfram Sang13a99302016-05-31 12:56:13 +0200812 netif_carrier_off(netdev);
813 tmp = FORCE_DISCONNECT & priv->connect_status;
814 priv->connect_status = tmp + DISCONNECT_STATUS;
815 break;
816 default:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200817 DPRINTK(1, "unknown connect_code=%d :: scan_ind_count=%d\n",
818 connect_code, priv->scan_ind_count);
Wolfram Sang13a99302016-05-31 12:56:13 +0200819 netif_carrier_off(netdev);
820 tmp = FORCE_DISCONNECT & priv->connect_status;
821 priv->connect_status = tmp + DISCONNECT_STATUS;
822 break;
823 }
824
825 get_current_ap(priv, (struct link_ap_info_t *)priv->rxp);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200826 if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS &&
827 (old_status & CONNECT_STATUS_MASK) == DISCONNECT_STATUS) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200828 /* for power save */
829 atomic_set(&priv->psstatus.snooze_guard, 0);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200830 atomic_set(&priv->psstatus.confirm_wait, 0);
Wolfram Sang13a99302016-05-31 12:56:13 +0200831 }
832 ks_wlan_do_power_save(priv);
833
Wolfram Sang13a99302016-05-31 12:56:13 +0200834 wrqu0.data.length = 0;
835 wrqu0.data.flags = 0;
836 wrqu0.ap_addr.sa_family = ARPHRD_ETHER;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200837 if ((priv->connect_status & CONNECT_STATUS_MASK) == DISCONNECT_STATUS &&
838 (old_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200839 memset(wrqu0.ap_addr.sa_data, '\0', ETH_ALEN);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200840 DPRINTK(3, "IWEVENT: disconnect\n");
841 DPRINTK(3, "disconnect :: scan_ind_count=%d\n",
842 priv->scan_ind_count);
Wolfram Sang13a99302016-05-31 12:56:13 +0200843 wireless_send_event(netdev, SIOCGIWAP, &wrqu0, NULL);
844 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200845 priv->scan_ind_count = 0;
Wolfram Sang13a99302016-05-31 12:56:13 +0200846}
847
848static
Wolfram Sangfeedcf12016-05-31 12:56:26 +0200849void hostif_scan_indication(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +0200850{
851 int i;
852 struct ap_info_t *ap_info;
853
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200854 DPRINTK(3, "scan_ind_count = %d\n", priv->scan_ind_count);
Wolfram Sang13a99302016-05-31 12:56:13 +0200855 ap_info = (struct ap_info_t *)(priv->rxp);
856
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200857 if (priv->scan_ind_count != 0) {
858 for (i = 0; i < priv->aplist.size; i++) { /* bssid check */
859 if (!memcmp
860 (&(ap_info->bssid[0]),
861 &(priv->aplist.ap[i].bssid[0]), ETH_ALEN)) {
862 if (ap_info->frame_type ==
863 FRAME_TYPE_PROBE_RESP)
864 get_ap_information(priv, ap_info,
865 &(priv->aplist.
866 ap[i]));
Wolfram Sang13a99302016-05-31 12:56:13 +0200867 return;
868 }
869 }
870 }
871 priv->scan_ind_count++;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200872 if (priv->scan_ind_count < LOCAL_APLIST_MAX + 1) {
873 DPRINTK(4, " scan_ind_count=%d :: aplist.size=%d\n",
874 priv->scan_ind_count, priv->aplist.size);
875 get_ap_information(priv, (struct ap_info_t *)(priv->rxp),
876 &(priv->aplist.
877 ap[priv->scan_ind_count - 1]));
Wolfram Sang13a99302016-05-31 12:56:13 +0200878 priv->aplist.size = priv->scan_ind_count;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200879 } else {
880 DPRINTK(4, " count over :: scan_ind_count=%d\n",
881 priv->scan_ind_count);
Wolfram Sang13a99302016-05-31 12:56:13 +0200882 }
Wolfram Sang13a99302016-05-31 12:56:13 +0200883
884}
885
886static
Wolfram Sangfeedcf12016-05-31 12:56:26 +0200887void hostif_stop_confirm(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +0200888{
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200889 unsigned int tmp = 0;
890 unsigned int old_status = priv->connect_status;
891 struct net_device *netdev = priv->net_dev;
Wolfram Sang13a99302016-05-31 12:56:13 +0200892 union iwreq_data wrqu0;
893
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200894 DPRINTK(3, "\n");
895 if (priv->dev_state == DEVICE_STATE_SLEEP)
Wolfram Sang13a99302016-05-31 12:56:13 +0200896 priv->dev_state = DEVICE_STATE_READY;
Wolfram Sang13a99302016-05-31 12:56:13 +0200897
898 /* disconnect indication */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200899 if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200900 netif_carrier_off(netdev);
901 tmp = FORCE_DISCONNECT & priv->connect_status;
902 priv->connect_status = tmp | DISCONNECT_STATUS;
903 printk("IWEVENT: disconnect\n");
904
905 wrqu0.data.length = 0;
906 wrqu0.data.flags = 0;
907 wrqu0.ap_addr.sa_family = ARPHRD_ETHER;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200908 if ((priv->connect_status & CONNECT_STATUS_MASK) ==
909 DISCONNECT_STATUS
910 && (old_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) {
Wolfram Sang13a99302016-05-31 12:56:13 +0200911 memset(wrqu0.ap_addr.sa_data, '\0', ETH_ALEN);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200912 DPRINTK(3, "IWEVENT: disconnect\n");
Wolfram Sang13a99302016-05-31 12:56:13 +0200913 printk("IWEVENT: disconnect\n");
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200914 DPRINTK(3, "disconnect :: scan_ind_count=%d\n",
915 priv->scan_ind_count);
Wolfram Sang13a99302016-05-31 12:56:13 +0200916 wireless_send_event(netdev, SIOCGIWAP, &wrqu0, NULL);
917 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200918 priv->scan_ind_count = 0;
Wolfram Sang13a99302016-05-31 12:56:13 +0200919 }
920
921 hostif_sme_enqueue(priv, SME_STOP_CONFIRM);
922}
923
924static
Wolfram Sangfeedcf12016-05-31 12:56:26 +0200925void hostif_ps_adhoc_set_confirm(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +0200926{
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200927 DPRINTK(3, "\n");
928 priv->infra_status = 0; /* infrastructure mode cancel */
Wolfram Sang13a99302016-05-31 12:56:13 +0200929 hostif_sme_enqueue(priv, SME_MODE_SET_CONFIRM);
930
931}
932
933static
Wolfram Sangfeedcf12016-05-31 12:56:26 +0200934void hostif_infrastructure_set_confirm(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +0200935{
936 uint16_t result_code;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200937 DPRINTK(3, "\n");
Wolfram Sang13a99302016-05-31 12:56:13 +0200938 result_code = get_WORD(priv);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200939 DPRINTK(3, "result code = %d\n", result_code);
940 priv->infra_status = 1; /* infrastructure mode set */
Wolfram Sang13a99302016-05-31 12:56:13 +0200941 hostif_sme_enqueue(priv, SME_MODE_SET_CONFIRM);
942}
943
944static
Wolfram Sangfeedcf12016-05-31 12:56:26 +0200945void hostif_adhoc_set_confirm(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +0200946{
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200947 DPRINTK(3, "\n");
948 priv->infra_status = 1; /* infrastructure mode set */
Wolfram Sang13a99302016-05-31 12:56:13 +0200949 hostif_sme_enqueue(priv, SME_MODE_SET_CONFIRM);
950}
951
952static
Wolfram Sangfeedcf12016-05-31 12:56:26 +0200953void hostif_associate_indication(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +0200954{
Wolfram Sang13a99302016-05-31 12:56:13 +0200955 struct association_request_t *assoc_req;
956 struct association_response_t *assoc_resp;
957 unsigned char *pb;
958 union iwreq_data wrqu;
959 char buf[IW_CUSTOM_MAX];
960 char *pbuf = &buf[0];
961 int i;
962
963 static const char associnfo_leader0[] = "ASSOCINFO(ReqIEs=";
964 static const char associnfo_leader1[] = " RespIEs=";
965
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200966 DPRINTK(3, "\n");
Wolfram Sang13a99302016-05-31 12:56:13 +0200967 assoc_req = (struct association_request_t *)(priv->rxp);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200968 assoc_resp = (struct association_response_t *)(assoc_req + 1);
969 pb = (unsigned char *)(assoc_resp + 1);
Wolfram Sang13a99302016-05-31 12:56:13 +0200970
971 memset(&wrqu, 0, sizeof(wrqu));
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200972 memcpy(pbuf, associnfo_leader0, sizeof(associnfo_leader0) - 1);
973 wrqu.data.length += sizeof(associnfo_leader0) - 1;
974 pbuf += sizeof(associnfo_leader0) - 1;
Wolfram Sang13a99302016-05-31 12:56:13 +0200975
976 for (i = 0; i < assoc_req->reqIEs_size; i++)
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200977 pbuf += sprintf(pbuf, "%02x", *(pb + i));
978 wrqu.data.length += (assoc_req->reqIEs_size) * 2;
Wolfram Sang13a99302016-05-31 12:56:13 +0200979
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200980 memcpy(pbuf, associnfo_leader1, sizeof(associnfo_leader1) - 1);
981 wrqu.data.length += sizeof(associnfo_leader1) - 1;
982 pbuf += sizeof(associnfo_leader1) - 1;
Wolfram Sang13a99302016-05-31 12:56:13 +0200983
984 pb += assoc_req->reqIEs_size;
985 for (i = 0; i < assoc_resp->respIEs_size; i++)
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200986 pbuf += sprintf(pbuf, "%02x", *(pb + i));
987 wrqu.data.length += (assoc_resp->respIEs_size) * 2;
Wolfram Sang13a99302016-05-31 12:56:13 +0200988
989 pbuf += sprintf(pbuf, ")");
990 wrqu.data.length += 1;
991
Wolfram Sang20c4f9c2016-05-31 12:56:30 +0200992 DPRINTK(3, "IWEVENT:ASSOCINFO\n");
Wolfram Sang13a99302016-05-31 12:56:13 +0200993 wireless_send_event(priv->net_dev, IWEVCUSTOM, &wrqu, buf);
Wolfram Sang13a99302016-05-31 12:56:13 +0200994}
995
996static
Wolfram Sangfeedcf12016-05-31 12:56:26 +0200997void hostif_bss_scan_confirm(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +0200998{
999 unsigned int result_code;
Wolfram Sang13a99302016-05-31 12:56:13 +02001000 struct net_device *dev = priv->net_dev;
1001 union iwreq_data wrqu;
Wolfram Sang13a99302016-05-31 12:56:13 +02001002 result_code = get_DWORD(priv);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001003 DPRINTK(2, "result=%d :: scan_ind_count=%d\n", result_code,
1004 priv->scan_ind_count);
Wolfram Sang13a99302016-05-31 12:56:13 +02001005
1006 priv->sme_i.sme_flag &= ~SME_AP_SCAN;
1007 hostif_sme_enqueue(priv, SME_BSS_SCAN_CONFIRM);
1008
Wolfram Sang13a99302016-05-31 12:56:13 +02001009 wrqu.data.length = 0;
1010 wrqu.data.flags = 0;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001011 DPRINTK(3, "IWEVENT: SCAN CONFIRM\n");
Wolfram Sang13a99302016-05-31 12:56:13 +02001012 wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001013 priv->scan_ind_count = 0;
Wolfram Sang13a99302016-05-31 12:56:13 +02001014}
1015
1016static
Wolfram Sangfeedcf12016-05-31 12:56:26 +02001017void hostif_phy_information_confirm(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +02001018{
1019 struct iw_statistics *wstats = &priv->wstats;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001020 unsigned char rssi, signal, noise;
Wolfram Sang13a99302016-05-31 12:56:13 +02001021 unsigned char LinkSpeed;
1022 unsigned int TransmittedFrameCount, ReceivedFragmentCount;
1023 unsigned int FailedCount, FCSErrorCount;
1024
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001025 DPRINTK(3, "\n");
Wolfram Sang13a99302016-05-31 12:56:13 +02001026 rssi = get_BYTE(priv);
1027 signal = get_BYTE(priv);
1028 noise = get_BYTE(priv);
1029 LinkSpeed = get_BYTE(priv);
1030 TransmittedFrameCount = get_DWORD(priv);
1031 ReceivedFragmentCount = get_DWORD(priv);
1032 FailedCount = get_DWORD(priv);
1033 FCSErrorCount = get_DWORD(priv);
1034
1035 DPRINTK(4, "phyinfo confirm rssi=%d signal=%d\n", rssi, signal);
1036 priv->current_rate = (LinkSpeed & RATE_MASK);
1037 wstats->qual.qual = signal;
1038 wstats->qual.level = 256 - rssi;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001039 wstats->qual.noise = 0; /* invalid noise value */
Wolfram Sang13a99302016-05-31 12:56:13 +02001040 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1041
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001042 DPRINTK(3, "\n rssi=%u\n signal=%u\n LinkSpeed=%ux500Kbps\n \
Wolfram Sang13a99302016-05-31 12:56:13 +02001043 TransmittedFrameCount=%u\n ReceivedFragmentCount=%u\n FailedCount=%u\n \
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001044 FCSErrorCount=%u\n", rssi, signal, LinkSpeed, TransmittedFrameCount, ReceivedFragmentCount, FailedCount, FCSErrorCount);
Wolfram Sang13a99302016-05-31 12:56:13 +02001045
1046 /* wake_up_interruptible_all(&priv->confirm_wait); */
1047 complete(&priv->confirm_wait);
1048}
1049
1050static
Wolfram Sangfeedcf12016-05-31 12:56:26 +02001051void hostif_mic_failure_confirm(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +02001052{
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001053 DPRINTK(3, "mic_failure=%u\n", priv->wpa.mic_failure.failure);
Wolfram Sang13a99302016-05-31 12:56:13 +02001054 hostif_sme_enqueue(priv, SME_MIC_FAILURE_CONFIRM);
1055}
1056
Wolfram Sang13a99302016-05-31 12:56:13 +02001057static
Wolfram Sangfeedcf12016-05-31 12:56:26 +02001058void hostif_event_check(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +02001059{
1060 unsigned short event;
1061
1062 DPRINTK(4, "\n");
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001063 event = get_WORD(priv); /* get event */
Wolfram Sang13a99302016-05-31 12:56:13 +02001064 switch (event) {
1065 case HIF_DATA_IND:
1066 hostif_data_indication(priv);
1067 break;
1068 case HIF_MIB_GET_CONF:
1069 hostif_mib_get_confirm(priv);
1070 break;
1071 case HIF_MIB_SET_CONF:
1072 hostif_mib_set_confirm(priv);
1073 break;
1074 case HIF_POWERMGT_CONF:
1075 hostif_power_mngmt_confirm(priv);
1076 break;
1077 case HIF_SLEEP_CONF:
1078 hostif_sleep_confirm(priv);
1079 break;
1080 case HIF_START_CONF:
1081 hostif_start_confirm(priv);
1082 break;
1083 case HIF_CONNECT_IND:
1084 hostif_connect_indication(priv);
1085 break;
1086 case HIF_STOP_CONF:
1087 hostif_stop_confirm(priv);
1088 break;
1089 case HIF_PS_ADH_SET_CONF:
1090 hostif_ps_adhoc_set_confirm(priv);
1091 break;
1092 case HIF_INFRA_SET_CONF:
1093 case HIF_INFRA_SET2_CONF:
1094 hostif_infrastructure_set_confirm(priv);
1095 break;
1096 case HIF_ADH_SET_CONF:
1097 case HIF_ADH_SET2_CONF:
1098 hostif_adhoc_set_confirm(priv);
1099 break;
1100 case HIF_ASSOC_INFO_IND:
1101 hostif_associate_indication(priv);
1102 break;
1103 case HIF_MIC_FAILURE_CONF:
1104 hostif_mic_failure_confirm(priv);
1105 break;
1106 case HIF_SCAN_CONF:
1107 hostif_bss_scan_confirm(priv);
1108 break;
1109 case HIF_PHY_INFO_CONF:
1110 case HIF_PHY_INFO_IND:
1111 hostif_phy_information_confirm(priv);
1112 break;
1113 case HIF_SCAN_IND:
1114 hostif_scan_indication(priv);
1115 break;
1116 case HIF_AP_SET_CONF:
1117 default:
1118 //DPRINTK(1, "undefined event[%04X]\n", event);
1119 printk("undefined event[%04X]\n", event);
1120 /* wake_up_all(&priv->confirm_wait); */
1121 complete(&priv->confirm_wait);
1122 break;
1123 }
1124
1125 /* add event to hostt buffer */
1126 priv->hostt.buff[priv->hostt.qtail] = event;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001127 priv->hostt.qtail = (priv->hostt.qtail + 1) % SME_EVENT_BUFF_SIZE;
Wolfram Sang13a99302016-05-31 12:56:13 +02001128}
1129
1130#define CHECK_ALINE(size) (size%4 ? (size+(4-(size%4))):size)
1131
Wolfram Sangfeedcf12016-05-31 12:56:26 +02001132int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *packet)
Wolfram Sang13a99302016-05-31 12:56:13 +02001133{
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001134 unsigned int packet_len = 0;
Wolfram Sang13a99302016-05-31 12:56:13 +02001135
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001136 unsigned char *buffer = NULL;
1137 unsigned int length = 0;
Wolfram Sang13a99302016-05-31 12:56:13 +02001138 struct hostif_data_request_t *pp;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001139 unsigned char *p;
1140 int result = 0;
Wolfram Sang13a99302016-05-31 12:56:13 +02001141 unsigned short eth_proto;
1142 struct ether_hdr *eth_hdr;
1143 struct michel_mic_t michel_mic;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001144 unsigned short keyinfo = 0;
Wolfram Sang13a99302016-05-31 12:56:13 +02001145 struct ieee802_1x_hdr *aa1x_hdr;
1146 struct wpa_eapol_key *eap_key;
1147 struct ethhdr *eth;
1148
1149 packet_len = packet->len;
1150 if (packet_len > ETH_FRAME_LEN) {
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001151 DPRINTK(1, "bad length packet_len=%d \n", packet_len);
Wolfram Sang13a99302016-05-31 12:56:13 +02001152 dev_kfree_skb(packet);
1153 return -1;
1154 }
1155
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001156 if (((priv->connect_status & CONNECT_STATUS_MASK) == DISCONNECT_STATUS)
1157 || (priv->connect_status & FORCE_DISCONNECT)
1158 || priv->wpa.mic_failure.stop) {
1159 DPRINTK(3, " DISCONNECT\n");
1160 if (netif_queue_stopped(priv->net_dev))
Wolfram Sang13a99302016-05-31 12:56:13 +02001161 netif_wake_queue(priv->net_dev);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001162 if (packet)
Wolfram Sang13a99302016-05-31 12:56:13 +02001163 dev_kfree_skb(packet);
1164
1165 return 0;
1166 }
1167
1168 /* for PowerSave */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001169 if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) { /* power save wakeup */
1170 if (!netif_queue_stopped(priv->net_dev))
Wolfram Sang13a99302016-05-31 12:56:13 +02001171 netif_stop_queue(priv->net_dev);
Wolfram Sang13a99302016-05-31 12:56:13 +02001172 }
1173
1174 DPRINTK(4, "skb_buff length=%d\n", packet_len);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001175 pp = (struct hostif_data_request_t *)
1176 kmalloc(hif_align_size(sizeof(*pp) + 6 + packet_len + 8),
1177 KS_WLAN_MEM_FLAG);
Wolfram Sang13a99302016-05-31 12:56:13 +02001178
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001179 if (pp == NULL) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001180 DPRINTK(3, "allocate memory failed..\n");
1181 dev_kfree_skb(packet);
1182 return -2;
1183 }
1184
1185 p = (unsigned char *)pp->data;
1186
1187 buffer = packet->data;
1188 length = packet->len;
1189
1190 /* packet check */
1191 eth = (struct ethhdr *)packet->data;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001192 if (memcmp(&priv->eth_addr[0], eth->h_source, ETH_ALEN)) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001193 DPRINTK(1, "invalid mac address !!\n");
1194 DPRINTK(1, "ethernet->h_source=%02X:%02X:%02X:%02X:%02X:%02X\n",
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001195 eth->h_source[0], eth->h_source[1], eth->h_source[2],
1196 eth->h_source[3], eth->h_source[4], eth->h_source[5]);
Wolfram Sang13a99302016-05-31 12:56:13 +02001197 return -3;
1198 }
1199
1200 /* MAC address copy */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001201 memcpy(p, buffer, 12); /* DST/SRC MAC address */
Wolfram Sang13a99302016-05-31 12:56:13 +02001202 p += 12;
1203 buffer += 12;
1204 length -= 12;
1205 /* EtherType/Length check */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001206 if (*(buffer + 1) + (*buffer << 8) > 1500) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001207 /* ProtocolEAP = *(buffer+1) + (*buffer << 8); */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001208 /* DPRINTK(2, "Send [SNAP]Type %x\n",ProtocolEAP); */
Wolfram Sang13a99302016-05-31 12:56:13 +02001209 /* SAP/CTL/OUI(6 byte) add */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001210 *p++ = 0xAA; /* DSAP */
1211 *p++ = 0xAA; /* SSAP */
1212 *p++ = 0x03; /* CTL */
1213 *p++ = 0x00; /* OUI ("000000") */
1214 *p++ = 0x00; /* OUI ("000000") */
1215 *p++ = 0x00; /* OUI ("000000") */
Wolfram Sang13a99302016-05-31 12:56:13 +02001216 packet_len += 6;
1217 } else {
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001218 DPRINTK(4, "DIX\n");
1219 /* Length(2 byte) delete */
Wolfram Sang13a99302016-05-31 12:56:13 +02001220 buffer += 2;
1221 length -= 2;
1222 packet_len -= 2;
1223 }
1224
1225 /* pp->data copy */
1226 memcpy(p, buffer, length);
1227
1228 p += length;
1229
1230 /* for WPA */
1231 eth_hdr = (struct ether_hdr *)&pp->data[0];
1232 eth_proto = ntohs(eth_hdr->h_proto);
1233
1234 /* for MIC FAILUER REPORT check */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001235 if (eth_proto == ETHER_PROTOCOL_TYPE_EAP
1236 && priv->wpa.mic_failure.failure > 0) {
1237 aa1x_hdr = (struct ieee802_1x_hdr *)(eth_hdr + 1);
1238 if (aa1x_hdr->type == IEEE802_1X_TYPE_EAPOL_KEY) {
1239 eap_key = (struct wpa_eapol_key *)(aa1x_hdr + 1);
1240 keyinfo = ntohs(eap_key->key_info);
Wolfram Sang13a99302016-05-31 12:56:13 +02001241 }
1242 }
1243
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001244 if (priv->wpa.rsn_enabled && priv->wpa.key[0].key_len) {
1245 if (eth_proto == ETHER_PROTOCOL_TYPE_EAP
1246 && !(priv->wpa.key[1].key_len)
1247 && !(priv->wpa.key[2].key_len)
1248 && !(priv->wpa.key[3].key_len)) {
1249 pp->auth_type = cpu_to_le16((uint16_t) TYPE_AUTH); /* no encryption */
1250 } else {
1251 if (priv->wpa.pairwise_suite == IW_AUTH_CIPHER_TKIP) {
1252 MichaelMICFunction(&michel_mic, (uint8_t *) priv->wpa.key[0].tx_mic_key, (uint8_t *) & pp->data[0], (int)packet_len, (uint8_t) 0, /* priority */
1253 (uint8_t *) michel_mic.
1254 Result);
Wolfram Sang13a99302016-05-31 12:56:13 +02001255 memcpy(p, michel_mic.Result, 8);
1256 length += 8;
1257 packet_len += 8;
1258 p += 8;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001259 pp->auth_type =
1260 cpu_to_le16((uint16_t) TYPE_DATA);
Wolfram Sang13a99302016-05-31 12:56:13 +02001261
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001262 } else if (priv->wpa.pairwise_suite ==
1263 IW_AUTH_CIPHER_CCMP) {
1264 pp->auth_type =
1265 cpu_to_le16((uint16_t) TYPE_DATA);
Wolfram Sang13a99302016-05-31 12:56:13 +02001266 }
1267 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001268 } else {
1269 if (eth_proto == ETHER_PROTOCOL_TYPE_EAP)
1270 pp->auth_type = cpu_to_le16((uint16_t) TYPE_AUTH);
Wolfram Sang13a99302016-05-31 12:56:13 +02001271 else
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001272 pp->auth_type = cpu_to_le16((uint16_t) TYPE_DATA);
Wolfram Sang13a99302016-05-31 12:56:13 +02001273 }
1274
1275 /* header value set */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001276 pp->header.size =
1277 cpu_to_le16((uint16_t)
1278 (sizeof(*pp) - sizeof(pp->header.size) + packet_len));
1279 pp->header.event = cpu_to_le16((uint16_t) HIF_DATA_REQ);
Wolfram Sang13a99302016-05-31 12:56:13 +02001280
1281 /* tx request */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001282 result =
1283 ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp) + packet_len),
1284 (void *)send_packet_complete, (void *)priv,
1285 (void *)packet);
Wolfram Sang13a99302016-05-31 12:56:13 +02001286
1287 /* MIC FAILUER REPORT check */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001288 if (eth_proto == ETHER_PROTOCOL_TYPE_EAP
1289 && priv->wpa.mic_failure.failure > 0) {
1290 if (keyinfo & WPA_KEY_INFO_ERROR
1291 && keyinfo & WPA_KEY_INFO_REQUEST) {
1292 DPRINTK(3, " MIC ERROR Report SET : %04X\n", keyinfo);
Wolfram Sang13a99302016-05-31 12:56:13 +02001293 hostif_sme_enqueue(priv, SME_MIC_FAILURE_REQUEST);
1294 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001295 if (priv->wpa.mic_failure.failure == 2)
1296 priv->wpa.mic_failure.stop = 1;
Wolfram Sang13a99302016-05-31 12:56:13 +02001297 }
1298
1299 return result;
1300}
1301
Wolfram Sang13a99302016-05-31 12:56:13 +02001302#define ps_confirm_wait_inc(priv) do{if(atomic_read(&priv->psstatus.status) > PS_ACTIVE_SET){ \
1303 atomic_inc(&priv->psstatus.confirm_wait); \
1304 /* atomic_set(&priv->psstatus.status, PS_CONF_WAIT);*/ \
1305 } }while(0)
Wolfram Sang13a99302016-05-31 12:56:13 +02001306
1307static
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001308void hostif_mib_get_request(struct ks_wlan_private *priv,
1309 unsigned long mib_attribute)
Wolfram Sang13a99302016-05-31 12:56:13 +02001310{
1311 struct hostif_mib_get_request_t *pp;
1312
1313 DPRINTK(3, "\n");
1314
1315 /* make primitive */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001316 pp = (struct hostif_mib_get_request_t *)
1317 kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG);
1318 if (pp == NULL) {
1319 DPRINTK(3, "allocate memory failed..\n");
Wolfram Sang13a99302016-05-31 12:56:13 +02001320 return;
1321 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001322 pp->header.size =
1323 cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
1324 pp->header.event = cpu_to_le16((uint16_t) HIF_MIB_GET_REQ);
1325 pp->mib_attribute = cpu_to_le32((uint32_t) mib_attribute);
Wolfram Sang13a99302016-05-31 12:56:13 +02001326
1327 /* send to device request */
1328 ps_confirm_wait_inc(priv);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001329 ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL);
Wolfram Sang13a99302016-05-31 12:56:13 +02001330}
1331
1332static
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001333void hostif_mib_set_request(struct ks_wlan_private *priv,
1334 unsigned long mib_attribute, unsigned short size,
1335 unsigned short type, void *vp)
Wolfram Sang13a99302016-05-31 12:56:13 +02001336{
1337 struct hostif_mib_set_request_t *pp;
1338
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001339 DPRINTK(3, "\n");
Wolfram Sang13a99302016-05-31 12:56:13 +02001340
1341 if (priv->dev_state < DEVICE_STATE_BOOT) {
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001342 DPRINTK(3, "DeviceRemove\n");
Wolfram Sang13a99302016-05-31 12:56:13 +02001343 return;
1344 }
1345
1346 /* make primitive */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001347 pp = (struct hostif_mib_set_request_t *)
1348 kmalloc(hif_align_size(sizeof(*pp) + size), KS_WLAN_MEM_FLAG);
1349 if (pp == NULL) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001350 DPRINTK(3, "allocate memory failed..\n");
1351 return;
1352 }
1353
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001354 pp->header.size =
1355 cpu_to_le16((uint16_t)
1356 (sizeof(*pp) - sizeof(pp->header.size) + size));
1357 pp->header.event = cpu_to_le16((uint16_t) HIF_MIB_SET_REQ);
1358 pp->mib_attribute = cpu_to_le32((uint32_t) mib_attribute);
1359 pp->mib_value.size = cpu_to_le16((uint16_t) size);
1360 pp->mib_value.type = cpu_to_le16((uint16_t) type);
Wolfram Sang13a99302016-05-31 12:56:13 +02001361 memcpy(&pp->mib_value.body, vp, size);
1362
1363 /* send to device request */
1364 ps_confirm_wait_inc(priv);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001365 ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp) + size), NULL, NULL,
1366 NULL);
Wolfram Sang13a99302016-05-31 12:56:13 +02001367}
1368
1369static
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001370void hostif_start_request(struct ks_wlan_private *priv, unsigned char mode)
Wolfram Sang13a99302016-05-31 12:56:13 +02001371{
1372 struct hostif_start_request_t *pp;
1373
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001374 DPRINTK(3, "\n");
Wolfram Sang13a99302016-05-31 12:56:13 +02001375
1376 /* make primitive */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001377 pp = (struct hostif_start_request_t *)
1378 kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG);
1379 if (pp == NULL) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001380 DPRINTK(3, "allocate memory failed..\n");
1381 return;
1382 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001383 pp->header.size =
1384 cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
1385 pp->header.event = cpu_to_le16((uint16_t) HIF_START_REQ);
1386 pp->mode = cpu_to_le16((uint16_t) mode);
Wolfram Sang13a99302016-05-31 12:56:13 +02001387
1388 /* send to device request */
1389 ps_confirm_wait_inc(priv);
1390 ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL);
1391
1392 priv->aplist.size = 0;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001393 priv->scan_ind_count = 0;
Wolfram Sang13a99302016-05-31 12:56:13 +02001394}
1395
1396static
Wolfram Sangfeedcf12016-05-31 12:56:26 +02001397void hostif_ps_adhoc_set_request(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +02001398{
1399 struct hostif_ps_adhoc_set_request_t *pp;
1400 uint16_t capability;
1401
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001402 DPRINTK(3, "\n");
Wolfram Sang13a99302016-05-31 12:56:13 +02001403
1404 /* make primitive */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001405 pp = (struct hostif_ps_adhoc_set_request_t *)
1406 kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG);
1407 if (pp == NULL) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001408 DPRINTK(3, "allocate memory failed..\n");
1409 return;
1410 }
1411 memset(pp, 0, sizeof(*pp));
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001412 pp->header.size =
1413 cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
1414 pp->header.event = cpu_to_le16((uint16_t) HIF_PS_ADH_SET_REQ);
1415 pp->phy_type = cpu_to_le16((uint16_t) (priv->reg.phy_type));
1416 pp->cts_mode = cpu_to_le16((uint16_t) (priv->reg.cts_mode));
1417 pp->scan_type = cpu_to_le16((uint16_t) (priv->reg.scan_type));
1418 pp->channel = cpu_to_le16((uint16_t) (priv->reg.channel));
Wolfram Sang13a99302016-05-31 12:56:13 +02001419 pp->rate_set.size = priv->reg.rate_set.size;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001420 memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0],
1421 priv->reg.rate_set.size);
Wolfram Sang13a99302016-05-31 12:56:13 +02001422
1423 capability = 0x0000;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001424 if (priv->reg.preamble == SHORT_PREAMBLE) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001425 /* short preamble */
1426 capability |= BSS_CAP_SHORT_PREAMBLE;
1427 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001428 capability &= ~(BSS_CAP_PBCC); /* pbcc not support */
1429 if (priv->reg.phy_type != D_11B_ONLY_MODE) {
1430 capability |= BSS_CAP_SHORT_SLOT_TIME; /* ShortSlotTime support */
1431 capability &= ~(BSS_CAP_DSSS_OFDM); /* DSSS OFDM */
Wolfram Sang13a99302016-05-31 12:56:13 +02001432 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001433 pp->capability = cpu_to_le16((uint16_t) capability);
Wolfram Sang13a99302016-05-31 12:56:13 +02001434
1435 /* send to device request */
1436 ps_confirm_wait_inc(priv);
1437 ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL);
1438}
1439
1440static
Wolfram Sangfeedcf12016-05-31 12:56:26 +02001441void hostif_infrastructure_set_request(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +02001442{
1443 struct hostif_infrastructure_set_request_t *pp;
1444 uint16_t capability;
1445
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001446 DPRINTK(3, "ssid.size=%d \n", priv->reg.ssid.size);
Wolfram Sang13a99302016-05-31 12:56:13 +02001447
1448 /* make primitive */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001449 pp = (struct hostif_infrastructure_set_request_t *)
1450 kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG);
1451 if (pp == NULL) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001452 DPRINTK(3, "allocate memory failed..\n");
1453 return;
1454 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001455 pp->header.size =
1456 cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
1457 pp->header.event = cpu_to_le16((uint16_t) HIF_INFRA_SET_REQ);
1458 pp->phy_type = cpu_to_le16((uint16_t) (priv->reg.phy_type));
1459 pp->cts_mode = cpu_to_le16((uint16_t) (priv->reg.cts_mode));
1460 pp->scan_type = cpu_to_le16((uint16_t) (priv->reg.scan_type));
Wolfram Sang13a99302016-05-31 12:56:13 +02001461
1462 pp->rate_set.size = priv->reg.rate_set.size;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001463 memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0],
1464 priv->reg.rate_set.size);
Wolfram Sang13a99302016-05-31 12:56:13 +02001465 pp->ssid.size = priv->reg.ssid.size;
1466 memcpy(&pp->ssid.body[0], &priv->reg.ssid.body[0], priv->reg.ssid.size);
1467
1468 capability = 0x0000;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001469 if (priv->reg.preamble == SHORT_PREAMBLE) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001470 /* short preamble */
1471 capability |= BSS_CAP_SHORT_PREAMBLE;
1472 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001473 capability &= ~(BSS_CAP_PBCC); /* pbcc not support */
1474 if (priv->reg.phy_type != D_11B_ONLY_MODE) {
1475 capability |= BSS_CAP_SHORT_SLOT_TIME; /* ShortSlotTime support */
1476 capability &= ~(BSS_CAP_DSSS_OFDM); /* DSSS OFDM not support */
Wolfram Sang13a99302016-05-31 12:56:13 +02001477 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001478 pp->capability = cpu_to_le16((uint16_t) capability);
1479 pp->beacon_lost_count =
1480 cpu_to_le16((uint16_t) (priv->reg.beacon_lost_count));
1481 pp->auth_type = cpu_to_le16((uint16_t) (priv->reg.authenticate_type));
Wolfram Sang13a99302016-05-31 12:56:13 +02001482
1483 pp->channel_list.body[0] = 1;
1484 pp->channel_list.body[1] = 8;
1485 pp->channel_list.body[2] = 2;
1486 pp->channel_list.body[3] = 9;
1487 pp->channel_list.body[4] = 3;
1488 pp->channel_list.body[5] = 10;
1489 pp->channel_list.body[6] = 4;
1490 pp->channel_list.body[7] = 11;
1491 pp->channel_list.body[8] = 5;
1492 pp->channel_list.body[9] = 12;
1493 pp->channel_list.body[10] = 6;
1494 pp->channel_list.body[11] = 13;
1495 pp->channel_list.body[12] = 7;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001496 if (priv->reg.phy_type == D_11G_ONLY_MODE) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001497 pp->channel_list.size = 13;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001498 } else {
Wolfram Sang13a99302016-05-31 12:56:13 +02001499 pp->channel_list.body[13] = 14;
1500 pp->channel_list.size = 14;
1501 }
1502
1503 /* send to device request */
1504 ps_confirm_wait_inc(priv);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001505 ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL);
Wolfram Sang13a99302016-05-31 12:56:13 +02001506}
1507
Wolfram Sangfeedcf12016-05-31 12:56:26 +02001508void hostif_infrastructure_set2_request(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +02001509{
1510 struct hostif_infrastructure_set2_request_t *pp;
1511 uint16_t capability;
1512
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001513 DPRINTK(2, "ssid.size=%d \n", priv->reg.ssid.size);
Wolfram Sang13a99302016-05-31 12:56:13 +02001514
1515 /* make primitive */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001516 pp = (struct hostif_infrastructure_set2_request_t *)
1517 kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG);
1518 if (pp == NULL) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001519 DPRINTK(3, "allocate memory failed..\n");
1520 return;
1521 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001522 pp->header.size =
1523 cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
1524 pp->header.event = cpu_to_le16((uint16_t) HIF_INFRA_SET2_REQ);
1525 pp->phy_type = cpu_to_le16((uint16_t) (priv->reg.phy_type));
1526 pp->cts_mode = cpu_to_le16((uint16_t) (priv->reg.cts_mode));
1527 pp->scan_type = cpu_to_le16((uint16_t) (priv->reg.scan_type));
Wolfram Sang13a99302016-05-31 12:56:13 +02001528
1529 pp->rate_set.size = priv->reg.rate_set.size;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001530 memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0],
1531 priv->reg.rate_set.size);
Wolfram Sang13a99302016-05-31 12:56:13 +02001532 pp->ssid.size = priv->reg.ssid.size;
1533 memcpy(&pp->ssid.body[0], &priv->reg.ssid.body[0], priv->reg.ssid.size);
1534
1535 capability = 0x0000;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001536 if (priv->reg.preamble == SHORT_PREAMBLE) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001537 /* short preamble */
1538 capability |= BSS_CAP_SHORT_PREAMBLE;
1539 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001540 capability &= ~(BSS_CAP_PBCC); /* pbcc not support */
1541 if (priv->reg.phy_type != D_11B_ONLY_MODE) {
1542 capability |= BSS_CAP_SHORT_SLOT_TIME; /* ShortSlotTime support */
1543 capability &= ~(BSS_CAP_DSSS_OFDM); /* DSSS OFDM not support */
Wolfram Sang13a99302016-05-31 12:56:13 +02001544 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001545 pp->capability = cpu_to_le16((uint16_t) capability);
1546 pp->beacon_lost_count =
1547 cpu_to_le16((uint16_t) (priv->reg.beacon_lost_count));
1548 pp->auth_type = cpu_to_le16((uint16_t) (priv->reg.authenticate_type));
Wolfram Sang13a99302016-05-31 12:56:13 +02001549
1550 pp->channel_list.body[0] = 1;
1551 pp->channel_list.body[1] = 8;
1552 pp->channel_list.body[2] = 2;
1553 pp->channel_list.body[3] = 9;
1554 pp->channel_list.body[4] = 3;
1555 pp->channel_list.body[5] = 10;
1556 pp->channel_list.body[6] = 4;
1557 pp->channel_list.body[7] = 11;
1558 pp->channel_list.body[8] = 5;
1559 pp->channel_list.body[9] = 12;
1560 pp->channel_list.body[10] = 6;
1561 pp->channel_list.body[11] = 13;
1562 pp->channel_list.body[12] = 7;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001563 if (priv->reg.phy_type == D_11G_ONLY_MODE) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001564 pp->channel_list.size = 13;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001565 } else {
Wolfram Sang13a99302016-05-31 12:56:13 +02001566 pp->channel_list.body[13] = 14;
1567 pp->channel_list.size = 14;
1568 }
1569
1570 memcpy(pp->bssid, priv->reg.bssid, ETH_ALEN);
1571
1572 /* send to device request */
1573 ps_confirm_wait_inc(priv);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001574 ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL);
Wolfram Sang13a99302016-05-31 12:56:13 +02001575}
1576
1577static
Wolfram Sangfeedcf12016-05-31 12:56:26 +02001578void hostif_adhoc_set_request(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +02001579{
1580 struct hostif_adhoc_set_request_t *pp;
1581 uint16_t capability;
1582
1583 DPRINTK(3, "\n");
1584
1585 /* make primitive */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001586 pp = (struct hostif_adhoc_set_request_t *)
1587 kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG);
1588 if (pp == NULL) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001589 DPRINTK(3, "allocate memory failed..\n");
1590 return;
1591 }
1592 memset(pp, 0, sizeof(*pp));
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001593 pp->header.size =
1594 cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
1595 pp->header.event = cpu_to_le16((uint16_t) HIF_ADH_SET_REQ);
1596 pp->phy_type = cpu_to_le16((uint16_t) (priv->reg.phy_type));
1597 pp->cts_mode = cpu_to_le16((uint16_t) (priv->reg.cts_mode));
1598 pp->scan_type = cpu_to_le16((uint16_t) (priv->reg.scan_type));
1599 pp->channel = cpu_to_le16((uint16_t) (priv->reg.channel));
Wolfram Sang13a99302016-05-31 12:56:13 +02001600 pp->rate_set.size = priv->reg.rate_set.size;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001601 memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0],
1602 priv->reg.rate_set.size);
Wolfram Sang13a99302016-05-31 12:56:13 +02001603 pp->ssid.size = priv->reg.ssid.size;
1604 memcpy(&pp->ssid.body[0], &priv->reg.ssid.body[0], priv->reg.ssid.size);
1605
1606 capability = 0x0000;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001607 if (priv->reg.preamble == SHORT_PREAMBLE) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001608 /* short preamble */
1609 capability |= BSS_CAP_SHORT_PREAMBLE;
1610 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001611 capability &= ~(BSS_CAP_PBCC); /* pbcc not support */
1612 if (priv->reg.phy_type != D_11B_ONLY_MODE) {
1613 capability |= BSS_CAP_SHORT_SLOT_TIME; /* ShortSlotTime support */
1614 capability &= ~(BSS_CAP_DSSS_OFDM); /* DSSS OFDM not support */
Wolfram Sang13a99302016-05-31 12:56:13 +02001615 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001616 pp->capability = cpu_to_le16((uint16_t) capability);
Wolfram Sang13a99302016-05-31 12:56:13 +02001617
1618 /* send to device request */
1619 ps_confirm_wait_inc(priv);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001620 ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL);
Wolfram Sang13a99302016-05-31 12:56:13 +02001621}
1622
1623static
Wolfram Sangfeedcf12016-05-31 12:56:26 +02001624void hostif_adhoc_set2_request(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +02001625{
1626 struct hostif_adhoc_set2_request_t *pp;
1627 uint16_t capability;
1628
1629 DPRINTK(3, "\n");
1630
1631 /* make primitive */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001632 pp = (struct hostif_adhoc_set2_request_t *)
1633 kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG);
1634 if (pp == NULL) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001635 DPRINTK(3, "allocate memory failed..\n");
1636 return;
1637 }
1638 memset(pp, 0, sizeof(*pp));
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001639 pp->header.size =
1640 cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
1641 pp->header.event = cpu_to_le16((uint16_t) HIF_ADH_SET_REQ);
1642 pp->phy_type = cpu_to_le16((uint16_t) (priv->reg.phy_type));
1643 pp->cts_mode = cpu_to_le16((uint16_t) (priv->reg.cts_mode));
1644 pp->scan_type = cpu_to_le16((uint16_t) (priv->reg.scan_type));
Wolfram Sang13a99302016-05-31 12:56:13 +02001645 pp->rate_set.size = priv->reg.rate_set.size;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001646 memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0],
1647 priv->reg.rate_set.size);
Wolfram Sang13a99302016-05-31 12:56:13 +02001648 pp->ssid.size = priv->reg.ssid.size;
1649 memcpy(&pp->ssid.body[0], &priv->reg.ssid.body[0], priv->reg.ssid.size);
1650
1651 capability = 0x0000;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001652 if (priv->reg.preamble == SHORT_PREAMBLE) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001653 /* short preamble */
1654 capability |= BSS_CAP_SHORT_PREAMBLE;
1655 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001656 capability &= ~(BSS_CAP_PBCC); /* pbcc not support */
1657 if (priv->reg.phy_type != D_11B_ONLY_MODE) {
1658 capability |= BSS_CAP_SHORT_SLOT_TIME; /* ShortSlotTime support */
1659 capability &= ~(BSS_CAP_DSSS_OFDM); /* DSSS OFDM not support */
Wolfram Sang13a99302016-05-31 12:56:13 +02001660 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001661 pp->capability = cpu_to_le16((uint16_t) capability);
Wolfram Sang13a99302016-05-31 12:56:13 +02001662
1663 pp->channel_list.body[0] = priv->reg.channel;
1664 pp->channel_list.size = 1;
1665 memcpy(pp->bssid, priv->reg.bssid, ETH_ALEN);
1666
1667 /* send to device request */
1668 ps_confirm_wait_inc(priv);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001669 ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL);
Wolfram Sang13a99302016-05-31 12:56:13 +02001670}
1671
1672static
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001673void hostif_stop_request(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +02001674{
1675 struct hostif_stop_request_t *pp;
1676
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001677 DPRINTK(3, "\n");
Wolfram Sang13a99302016-05-31 12:56:13 +02001678
1679 /* make primitive */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001680 pp = (struct hostif_stop_request_t *)
1681 kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG);
1682 if (pp == NULL) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001683 DPRINTK(3, "allocate memory failed..\n");
1684 return;
1685 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001686 pp->header.size =
1687 cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
1688 pp->header.event = cpu_to_le16((uint16_t) HIF_STOP_REQ);
1689
1690 /* send to device request */
1691 ps_confirm_wait_inc(priv);
1692 ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL);
1693}
1694
1695static
1696void hostif_phy_information_request(struct ks_wlan_private *priv)
1697{
1698 struct hostif_phy_information_request_t *pp;
1699
1700 DPRINTK(3, "\n");
1701
1702 /* make primitive */
1703 pp = (struct hostif_phy_information_request_t *)
1704 kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG);
1705 if (pp == NULL) {
1706 DPRINTK(3, "allocate memory failed..\n");
1707 return;
1708 }
1709 pp->header.size =
1710 cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
1711 pp->header.event = cpu_to_le16((uint16_t) HIF_PHY_INFO_REQ);
1712 if (priv->reg.phy_info_timer) {
1713 pp->type = cpu_to_le16((uint16_t) TIME_TYPE);
1714 pp->time = cpu_to_le16((uint16_t) (priv->reg.phy_info_timer));
1715 } else {
1716 pp->type = cpu_to_le16((uint16_t) NORMAL_TYPE);
1717 pp->time = cpu_to_le16((uint16_t) 0);
Wolfram Sang13a99302016-05-31 12:56:13 +02001718 }
1719
1720 /* send to device request */
1721 ps_confirm_wait_inc(priv);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001722 ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL);
Wolfram Sang13a99302016-05-31 12:56:13 +02001723}
1724
1725static
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001726void hostif_power_mngmt_request(struct ks_wlan_private *priv,
1727 unsigned long mode, unsigned long wake_up,
1728 unsigned long receiveDTIMs)
Wolfram Sang13a99302016-05-31 12:56:13 +02001729{
1730 struct hostif_power_mngmt_request_t *pp;
1731
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001732 DPRINTK(3, "mode=%lu wake_up=%lu receiveDTIMs=%lu\n", mode, wake_up,
1733 receiveDTIMs);
Wolfram Sang13a99302016-05-31 12:56:13 +02001734 /* make primitive */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001735 pp = (struct hostif_power_mngmt_request_t *)
1736 kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG);
1737 if (pp == NULL) {
1738 DPRINTK(3, "allocate memory failed..\n");
Wolfram Sang13a99302016-05-31 12:56:13 +02001739 return;
1740 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001741 pp->header.size =
1742 cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
1743 pp->header.event = cpu_to_le16((uint16_t) HIF_POWERMGT_REQ);
1744 pp->mode = cpu_to_le32((uint32_t) mode);
1745 pp->wake_up = cpu_to_le32((uint32_t) wake_up);
1746 pp->receiveDTIMs = cpu_to_le32((uint32_t) receiveDTIMs);
Wolfram Sang13a99302016-05-31 12:56:13 +02001747
1748 /* send to device request */
1749 ps_confirm_wait_inc(priv);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001750 ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL);
Wolfram Sang13a99302016-05-31 12:56:13 +02001751}
1752
1753static
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001754void hostif_sleep_request(struct ks_wlan_private *priv, unsigned long mode)
Wolfram Sang13a99302016-05-31 12:56:13 +02001755{
1756 struct hostif_sleep_request_t *pp;
1757
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001758 DPRINTK(3, "mode=%lu \n", mode);
Wolfram Sang13a99302016-05-31 12:56:13 +02001759
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001760 if (mode == SLP_SLEEP) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001761 /* make primitive */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001762 pp = (struct hostif_sleep_request_t *)
1763 kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG);
1764 if (pp == NULL) {
1765 DPRINTK(3, "allocate memory failed..\n");
Wolfram Sang13a99302016-05-31 12:56:13 +02001766 return;
1767 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001768 pp->header.size =
1769 cpu_to_le16((uint16_t)
1770 (sizeof(*pp) - sizeof(pp->header.size)));
1771 pp->header.event = cpu_to_le16((uint16_t) HIF_SLEEP_REQ);
Wolfram Sang13a99302016-05-31 12:56:13 +02001772
1773 /* send to device request */
1774 ps_confirm_wait_inc(priv);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001775 ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL,
1776 NULL);
1777 } else if (mode == SLP_ACTIVE) {
1778 atomic_set(&priv->sleepstatus.wakeup_request, 1);
1779 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
1780 &priv->ks_wlan_hw.rw_wq, 1);
1781 } else {
1782 DPRINTK(3, "invalid mode %ld \n", mode);
Wolfram Sang13a99302016-05-31 12:56:13 +02001783 return;
1784 }
1785}
1786
Wolfram Sang13a99302016-05-31 12:56:13 +02001787static
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001788void hostif_bss_scan_request(struct ks_wlan_private *priv,
1789 unsigned long scan_type, uint8_t * scan_ssid,
1790 uint8_t scan_ssid_len)
Wolfram Sang13a99302016-05-31 12:56:13 +02001791{
1792 struct hostif_bss_scan_request_t *pp;
1793
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001794 DPRINTK(2, "\n");
Wolfram Sang13a99302016-05-31 12:56:13 +02001795 /* make primitive */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001796 pp = (struct hostif_bss_scan_request_t *)
1797 kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG);
1798 if (pp == NULL) {
1799 DPRINTK(3, "allocate memory failed..\n");
Wolfram Sang13a99302016-05-31 12:56:13 +02001800 return;
1801 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001802 pp->header.size =
1803 cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
1804 pp->header.event = cpu_to_le16((uint16_t) HIF_SCAN_REQ);
Wolfram Sang13a99302016-05-31 12:56:13 +02001805 pp->scan_type = scan_type;
1806
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001807 pp->ch_time_min = cpu_to_le32((uint32_t) 110); /* default value */
1808 pp->ch_time_max = cpu_to_le32((uint32_t) 130); /* default value */
Wolfram Sang13a99302016-05-31 12:56:13 +02001809 pp->channel_list.body[0] = 1;
1810 pp->channel_list.body[1] = 8;
1811 pp->channel_list.body[2] = 2;
1812 pp->channel_list.body[3] = 9;
1813 pp->channel_list.body[4] = 3;
1814 pp->channel_list.body[5] = 10;
1815 pp->channel_list.body[6] = 4;
1816 pp->channel_list.body[7] = 11;
1817 pp->channel_list.body[8] = 5;
1818 pp->channel_list.body[9] = 12;
1819 pp->channel_list.body[10] = 6;
1820 pp->channel_list.body[11] = 13;
1821 pp->channel_list.body[12] = 7;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001822 if (priv->reg.phy_type == D_11G_ONLY_MODE) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001823 pp->channel_list.size = 13;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001824 } else {
Wolfram Sang13a99302016-05-31 12:56:13 +02001825 pp->channel_list.body[13] = 14;
1826 pp->channel_list.size = 14;
1827 }
1828 pp->ssid.size = 0;
1829
1830 /* specified SSID SCAN */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001831 if (scan_ssid_len > 0 && scan_ssid_len <= 32) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001832 pp->ssid.size = scan_ssid_len;
1833 memcpy(&pp->ssid.body[0], scan_ssid, scan_ssid_len);
1834 }
1835
Wolfram Sang13a99302016-05-31 12:56:13 +02001836 /* send to device request */
1837 ps_confirm_wait_inc(priv);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001838 ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL);
Wolfram Sang13a99302016-05-31 12:56:13 +02001839
1840 priv->aplist.size = 0;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001841 priv->scan_ind_count = 0;
Wolfram Sang13a99302016-05-31 12:56:13 +02001842}
1843
1844static
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001845void hostif_mic_failure_request(struct ks_wlan_private *priv,
1846 unsigned short failure_count,
1847 unsigned short timer)
Wolfram Sang13a99302016-05-31 12:56:13 +02001848{
1849 struct hostif_mic_failure_request_t *pp;
1850
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001851 DPRINTK(3, "count=%d :: timer=%d\n", failure_count, timer);
Wolfram Sang13a99302016-05-31 12:56:13 +02001852 /* make primitive */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001853 pp = (struct hostif_mic_failure_request_t *)
1854 kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG);
1855 if (pp == NULL) {
1856 DPRINTK(3, "allocate memory failed..\n");
Wolfram Sang13a99302016-05-31 12:56:13 +02001857 return;
1858 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001859 pp->header.size =
1860 cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
1861 pp->header.event = cpu_to_le16((uint16_t) HIF_MIC_FAILURE_REQ);
1862 pp->failure_count = cpu_to_le16((uint16_t) failure_count);
1863 pp->timer = cpu_to_le16((uint16_t) timer);
Wolfram Sang13a99302016-05-31 12:56:13 +02001864
1865 /* send to device request */
1866 ps_confirm_wait_inc(priv);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001867 ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL);
Wolfram Sang13a99302016-05-31 12:56:13 +02001868}
1869
1870/* Device I/O Recieve indicate */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001871static void devio_rec_ind(struct ks_wlan_private *priv, unsigned char *p,
1872 unsigned int size)
Wolfram Sang13a99302016-05-31 12:56:13 +02001873{
1874 if (priv->device_open_status) {
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001875 spin_lock(&priv->dev_read_lock); /* request spin lock */
Wolfram Sang13a99302016-05-31 12:56:13 +02001876 priv->dev_data[atomic_read(&priv->rec_count)] = p;
1877 priv->dev_size[atomic_read(&priv->rec_count)] = size;
1878
1879 if (atomic_read(&priv->event_count) != DEVICE_STOCK_COUNT) {
1880 /* rx event count inc */
1881 atomic_inc(&priv->event_count);
1882 }
1883 atomic_inc(&priv->rec_count);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001884 if (atomic_read(&priv->rec_count) == DEVICE_STOCK_COUNT)
Wolfram Sang13a99302016-05-31 12:56:13 +02001885 atomic_set(&priv->rec_count, 0);
1886
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001887 wake_up_interruptible_all(&priv->devread_wait);
Wolfram Sang13a99302016-05-31 12:56:13 +02001888
1889 /* release spin lock */
1890 spin_unlock(&priv->dev_read_lock);
1891 }
1892}
1893
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001894void hostif_receive(struct ks_wlan_private *priv, unsigned char *p,
1895 unsigned int size)
Wolfram Sang13a99302016-05-31 12:56:13 +02001896{
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001897 DPRINTK(4, "\n");
Wolfram Sang13a99302016-05-31 12:56:13 +02001898
1899 devio_rec_ind(priv, p, size);
1900
1901 priv->rxp = p;
1902 priv->rx_size = size;
1903
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001904 if (get_WORD(priv) == priv->rx_size) { /* length check !! */
1905 hostif_event_check(priv); /* event check */
Wolfram Sang13a99302016-05-31 12:56:13 +02001906 }
1907}
1908
Wolfram Sang13a99302016-05-31 12:56:13 +02001909static
Wolfram Sangfeedcf12016-05-31 12:56:26 +02001910void hostif_sme_set_wep(struct ks_wlan_private *priv, int type)
Wolfram Sang13a99302016-05-31 12:56:13 +02001911{
1912 uint32_t val;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001913 switch (type) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001914 case SME_WEP_INDEX_REQUEST:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001915 val = cpu_to_le32((uint32_t) (priv->reg.wep_index));
Wolfram Sang13a99302016-05-31 12:56:13 +02001916 hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_ID,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001917 sizeof(val), MIB_VALUE_TYPE_INT, &val);
Wolfram Sang13a99302016-05-31 12:56:13 +02001918 break;
1919 case SME_WEP_KEY1_REQUEST:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001920 if (!priv->wpa.wpa_enabled)
1921 hostif_mib_set_request(priv,
1922 DOT11_WEP_DEFAULT_KEY_VALUE1,
1923 priv->reg.wep_key[0].size,
1924 MIB_VALUE_TYPE_OSTRING,
1925 &priv->reg.wep_key[0].val[0]);
Wolfram Sang13a99302016-05-31 12:56:13 +02001926 break;
1927 case SME_WEP_KEY2_REQUEST:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001928 if (!priv->wpa.wpa_enabled)
1929 hostif_mib_set_request(priv,
1930 DOT11_WEP_DEFAULT_KEY_VALUE2,
1931 priv->reg.wep_key[1].size,
1932 MIB_VALUE_TYPE_OSTRING,
Wolfram Sang13a99302016-05-31 12:56:13 +02001933 &priv->reg.wep_key[1].val[0]);
1934 break;
1935 case SME_WEP_KEY3_REQUEST:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001936 if (!priv->wpa.wpa_enabled)
1937 hostif_mib_set_request(priv,
1938 DOT11_WEP_DEFAULT_KEY_VALUE3,
1939 priv->reg.wep_key[2].size,
1940 MIB_VALUE_TYPE_OSTRING,
1941 &priv->reg.wep_key[2].val[0]);
Wolfram Sang13a99302016-05-31 12:56:13 +02001942 break;
1943 case SME_WEP_KEY4_REQUEST:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001944 if (!priv->wpa.wpa_enabled)
1945 hostif_mib_set_request(priv,
1946 DOT11_WEP_DEFAULT_KEY_VALUE4,
1947 priv->reg.wep_key[3].size,
1948 MIB_VALUE_TYPE_OSTRING,
Wolfram Sang13a99302016-05-31 12:56:13 +02001949 &priv->reg.wep_key[3].val[0]);
1950 break;
1951 case SME_WEP_FLAG_REQUEST:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001952 val = cpu_to_le32((uint32_t) (priv->reg.privacy_invoked));
Wolfram Sang13a99302016-05-31 12:56:13 +02001953 hostif_mib_set_request(priv, DOT11_PRIVACY_INVOKED,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001954 sizeof(val), MIB_VALUE_TYPE_BOOL, &val);
Wolfram Sang13a99302016-05-31 12:56:13 +02001955 break;
1956 }
1957
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001958 return;
Wolfram Sang13a99302016-05-31 12:56:13 +02001959}
1960
1961struct wpa_suite_t {
1962 unsigned short size;
1963 unsigned char suite[4][CIPHER_ID_LEN];
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001964} __attribute__ ((packed));
Wolfram Sang13a99302016-05-31 12:56:13 +02001965
1966struct rsn_mode_t {
1967 uint32_t rsn_mode;
1968 uint16_t rsn_capability;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001969} __attribute__ ((packed));
Wolfram Sang13a99302016-05-31 12:56:13 +02001970
1971static
Wolfram Sangfeedcf12016-05-31 12:56:26 +02001972void hostif_sme_set_rsn(struct ks_wlan_private *priv, int type)
Wolfram Sang13a99302016-05-31 12:56:13 +02001973{
1974 struct wpa_suite_t wpa_suite;
1975 struct rsn_mode_t rsn_mode;
1976 uint32_t val;
1977
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001978 memset(&wpa_suite, 0, sizeof(wpa_suite));
Wolfram Sang13a99302016-05-31 12:56:13 +02001979
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001980 switch (type) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001981 case SME_RSN_UCAST_REQUEST:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001982 wpa_suite.size = cpu_to_le16((uint16_t) 1);
1983 switch (priv->wpa.pairwise_suite) {
Wolfram Sang13a99302016-05-31 12:56:13 +02001984 case IW_AUTH_CIPHER_NONE:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001985 if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)
1986 memcpy(&wpa_suite.suite[0][0],
1987 CIPHER_ID_WPA2_NONE, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02001988 else
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001989 memcpy(&wpa_suite.suite[0][0],
1990 CIPHER_ID_WPA_NONE, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02001991 break;
1992 case IW_AUTH_CIPHER_WEP40:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001993 if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)
1994 memcpy(&wpa_suite.suite[0][0],
1995 CIPHER_ID_WPA2_WEP40, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02001996 else
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02001997 memcpy(&wpa_suite.suite[0][0],
1998 CIPHER_ID_WPA_WEP40, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02001999 break;
2000 case IW_AUTH_CIPHER_TKIP:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002001 if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)
2002 memcpy(&wpa_suite.suite[0][0],
2003 CIPHER_ID_WPA2_TKIP, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002004 else
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002005 memcpy(&wpa_suite.suite[0][0],
2006 CIPHER_ID_WPA_TKIP, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002007 break;
2008 case IW_AUTH_CIPHER_CCMP:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002009 if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)
2010 memcpy(&wpa_suite.suite[0][0],
2011 CIPHER_ID_WPA2_CCMP, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002012 else
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002013 memcpy(&wpa_suite.suite[0][0],
2014 CIPHER_ID_WPA_CCMP, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002015 break;
2016 case IW_AUTH_CIPHER_WEP104:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002017 if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)
2018 memcpy(&wpa_suite.suite[0][0],
2019 CIPHER_ID_WPA2_WEP104, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002020 else
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002021 memcpy(&wpa_suite.suite[0][0],
2022 CIPHER_ID_WPA_WEP104, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002023 break;
2024 }
2025
2026 hostif_mib_set_request(priv, DOT11_RSN_CONFIG_UNICAST_CIPHER,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002027 sizeof(wpa_suite.size) +
2028 CIPHER_ID_LEN * wpa_suite.size,
Wolfram Sang13a99302016-05-31 12:56:13 +02002029 MIB_VALUE_TYPE_OSTRING, &wpa_suite);
2030 break;
2031 case SME_RSN_MCAST_REQUEST:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002032 switch (priv->wpa.group_suite) {
Wolfram Sang13a99302016-05-31 12:56:13 +02002033 case IW_AUTH_CIPHER_NONE:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002034 if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)
2035 memcpy(&wpa_suite.suite[0][0],
2036 CIPHER_ID_WPA2_NONE, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002037 else
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002038 memcpy(&wpa_suite.suite[0][0],
2039 CIPHER_ID_WPA_NONE, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002040 break;
2041 case IW_AUTH_CIPHER_WEP40:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002042 if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)
2043 memcpy(&wpa_suite.suite[0][0],
2044 CIPHER_ID_WPA2_WEP40, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002045 else
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002046 memcpy(&wpa_suite.suite[0][0],
2047 CIPHER_ID_WPA_WEP40, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002048 break;
2049 case IW_AUTH_CIPHER_TKIP:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002050 if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)
2051 memcpy(&wpa_suite.suite[0][0],
2052 CIPHER_ID_WPA2_TKIP, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002053 else
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002054 memcpy(&wpa_suite.suite[0][0],
2055 CIPHER_ID_WPA_TKIP, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002056 break;
2057 case IW_AUTH_CIPHER_CCMP:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002058 if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)
2059 memcpy(&wpa_suite.suite[0][0],
2060 CIPHER_ID_WPA2_CCMP, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002061 else
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002062 memcpy(&wpa_suite.suite[0][0],
2063 CIPHER_ID_WPA_CCMP, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002064 break;
2065 case IW_AUTH_CIPHER_WEP104:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002066 if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)
2067 memcpy(&wpa_suite.suite[0][0],
2068 CIPHER_ID_WPA2_WEP104, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002069 else
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002070 memcpy(&wpa_suite.suite[0][0],
2071 CIPHER_ID_WPA_WEP104, CIPHER_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002072 break;
2073 }
2074
2075 hostif_mib_set_request(priv, DOT11_RSN_CONFIG_MULTICAST_CIPHER,
2076 CIPHER_ID_LEN, MIB_VALUE_TYPE_OSTRING,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002077 &wpa_suite.suite[0][0]);
Wolfram Sang13a99302016-05-31 12:56:13 +02002078 break;
2079 case SME_RSN_AUTH_REQUEST:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002080 wpa_suite.size = cpu_to_le16((uint16_t) 1);
2081 switch (priv->wpa.key_mgmt_suite) {
Wolfram Sang13a99302016-05-31 12:56:13 +02002082 case IW_AUTH_KEY_MGMT_802_1X:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002083 if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)
2084 memcpy(&wpa_suite.suite[0][0],
2085 KEY_MGMT_ID_WPA2_1X, KEY_MGMT_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002086 else
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002087 memcpy(&wpa_suite.suite[0][0],
2088 KEY_MGMT_ID_WPA_1X, KEY_MGMT_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002089 break;
2090 case IW_AUTH_KEY_MGMT_PSK:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002091 if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)
2092 memcpy(&wpa_suite.suite[0][0],
2093 KEY_MGMT_ID_WPA2_PSK, KEY_MGMT_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002094 else
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002095 memcpy(&wpa_suite.suite[0][0],
2096 KEY_MGMT_ID_WPA_PSK, KEY_MGMT_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002097 break;
2098 case 0:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002099 if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)
2100 memcpy(&wpa_suite.suite[0][0],
2101 KEY_MGMT_ID_WPA2_NONE, KEY_MGMT_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002102 else
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002103 memcpy(&wpa_suite.suite[0][0],
2104 KEY_MGMT_ID_WPA_NONE, KEY_MGMT_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002105 break;
2106 case 4:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002107 if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)
2108 memcpy(&wpa_suite.suite[0][0],
2109 KEY_MGMT_ID_WPA2_WPANONE,
2110 KEY_MGMT_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002111 else
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002112 memcpy(&wpa_suite.suite[0][0],
2113 KEY_MGMT_ID_WPA_WPANONE,
2114 KEY_MGMT_ID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002115 break;
2116 }
2117
2118 hostif_mib_set_request(priv, DOT11_RSN_CONFIG_AUTH_SUITE,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002119 sizeof(wpa_suite.size) +
2120 KEY_MGMT_ID_LEN * wpa_suite.size,
Wolfram Sang13a99302016-05-31 12:56:13 +02002121 MIB_VALUE_TYPE_OSTRING, &wpa_suite);
2122 break;
2123 case SME_RSN_ENABLED_REQUEST:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002124 val = cpu_to_le32((uint32_t) (priv->wpa.rsn_enabled));
Wolfram Sang13a99302016-05-31 12:56:13 +02002125 hostif_mib_set_request(priv, DOT11_RSN_ENABLED,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002126 sizeof(val), MIB_VALUE_TYPE_BOOL, &val);
Wolfram Sang13a99302016-05-31 12:56:13 +02002127 break;
2128 case SME_RSN_MODE_REQUEST:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002129 if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) {
2130 rsn_mode.rsn_mode =
2131 cpu_to_le32((uint32_t) RSN_MODE_WPA2);
2132 rsn_mode.rsn_capability = cpu_to_le16((uint16_t) 0);
2133 } else if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA) {
2134 rsn_mode.rsn_mode =
2135 cpu_to_le32((uint32_t) RSN_MODE_WPA);
2136 rsn_mode.rsn_capability = cpu_to_le16((uint16_t) 0);
2137 } else {
2138 rsn_mode.rsn_mode =
2139 cpu_to_le32((uint32_t) RSN_MODE_NONE);
2140 rsn_mode.rsn_capability = cpu_to_le16((uint16_t) 0);
Wolfram Sang13a99302016-05-31 12:56:13 +02002141 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002142 hostif_mib_set_request(priv, LOCAL_RSN_MODE, sizeof(rsn_mode),
2143 MIB_VALUE_TYPE_OSTRING, &rsn_mode);
Wolfram Sang13a99302016-05-31 12:56:13 +02002144 break;
2145
2146 }
2147 return;
2148}
2149
2150static
Wolfram Sangfeedcf12016-05-31 12:56:26 +02002151void hostif_sme_mode_setup(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +02002152{
2153 unsigned char rate_size;
2154 unsigned char rate_octet[RATE_SET_MAX_SIZE];
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002155 int i = 0;
Wolfram Sang13a99302016-05-31 12:56:13 +02002156
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002157 /* rate setting if rate segging is auto for changing phy_type (#94) */
2158 if (priv->reg.tx_rate == TX_RATE_FULL_AUTO) {
2159 if (priv->reg.phy_type == D_11B_ONLY_MODE) {
Wolfram Sang13a99302016-05-31 12:56:13 +02002160 priv->reg.rate_set.body[3] = TX_RATE_11M;
2161 priv->reg.rate_set.body[2] = TX_RATE_5M;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002162 priv->reg.rate_set.body[1] = TX_RATE_2M | BASIC_RATE;
2163 priv->reg.rate_set.body[0] = TX_RATE_1M | BASIC_RATE;
Wolfram Sang13a99302016-05-31 12:56:13 +02002164 priv->reg.rate_set.size = 4;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002165 } else { /* D_11G_ONLY_MODE or D_11BG_COMPATIBLE_MODE */
Wolfram Sang13a99302016-05-31 12:56:13 +02002166 priv->reg.rate_set.body[11] = TX_RATE_54M;
2167 priv->reg.rate_set.body[10] = TX_RATE_48M;
2168 priv->reg.rate_set.body[9] = TX_RATE_36M;
2169 priv->reg.rate_set.body[8] = TX_RATE_18M;
2170 priv->reg.rate_set.body[7] = TX_RATE_9M;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002171 priv->reg.rate_set.body[6] = TX_RATE_24M | BASIC_RATE;
2172 priv->reg.rate_set.body[5] = TX_RATE_12M | BASIC_RATE;
2173 priv->reg.rate_set.body[4] = TX_RATE_6M | BASIC_RATE;
2174 priv->reg.rate_set.body[3] = TX_RATE_11M | BASIC_RATE;
2175 priv->reg.rate_set.body[2] = TX_RATE_5M | BASIC_RATE;
2176 priv->reg.rate_set.body[1] = TX_RATE_2M | BASIC_RATE;
2177 priv->reg.rate_set.body[0] = TX_RATE_1M | BASIC_RATE;
Wolfram Sang13a99302016-05-31 12:56:13 +02002178 priv->reg.rate_set.size = 12;
2179 }
2180 }
2181
2182 /* rate mask by phy setting */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002183 if (priv->reg.phy_type == D_11B_ONLY_MODE) {
2184 for (i = 0; i < priv->reg.rate_set.size; i++) {
2185 if (IS_11B_RATE(priv->reg.rate_set.body[i])) {
2186 if ((priv->reg.rate_set.body[i] & RATE_MASK) >=
2187 TX_RATE_5M)
2188 rate_octet[i] =
2189 priv->reg.rate_set.
2190 body[i] & RATE_MASK;
Wolfram Sang13a99302016-05-31 12:56:13 +02002191 else
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002192 rate_octet[i] =
2193 priv->reg.rate_set.body[i];
2194 } else
Wolfram Sang13a99302016-05-31 12:56:13 +02002195 break;
2196 }
2197
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002198 } else { /* D_11G_ONLY_MODE or D_11BG_COMPATIBLE_MODE */
2199 for (i = 0; i < priv->reg.rate_set.size; i++) {
2200 if (IS_11BG_RATE(priv->reg.rate_set.body[i])) {
2201 if (IS_OFDM_EXT_RATE
2202 (priv->reg.rate_set.body[i]))
2203 rate_octet[i] =
2204 priv->reg.rate_set.
2205 body[i] & RATE_MASK;
Wolfram Sang13a99302016-05-31 12:56:13 +02002206 else
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002207 rate_octet[i] =
2208 priv->reg.rate_set.body[i];
2209 } else
Wolfram Sang13a99302016-05-31 12:56:13 +02002210 break;
2211 }
2212 }
2213 rate_size = i;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002214 if (rate_size == 0) {
2215 if (priv->reg.phy_type == D_11G_ONLY_MODE)
2216 rate_octet[0] = TX_RATE_6M | BASIC_RATE;
Wolfram Sang13a99302016-05-31 12:56:13 +02002217 else
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002218 rate_octet[0] = TX_RATE_2M | BASIC_RATE;
Wolfram Sang13a99302016-05-31 12:56:13 +02002219 rate_size = 1;
2220 }
2221
2222 /* rate set update */
2223 priv->reg.rate_set.size = rate_size;
2224 memcpy(&priv->reg.rate_set.body[0], &rate_octet[0], rate_size);
2225
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002226 switch (priv->reg.operation_mode) {
Wolfram Sang13a99302016-05-31 12:56:13 +02002227 case MODE_PSEUDO_ADHOC:
2228 /* Pseudo Ad-Hoc mode */
2229 hostif_ps_adhoc_set_request(priv);
2230 break;
2231 case MODE_INFRASTRUCTURE:
2232 /* Infrastructure mode */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002233 if (!is_valid_ether_addr((u8 *) priv->reg.bssid)) {
Wolfram Sang13a99302016-05-31 12:56:13 +02002234 hostif_infrastructure_set_request(priv);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002235 } else {
Wolfram Sang13a99302016-05-31 12:56:13 +02002236 hostif_infrastructure_set2_request(priv);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002237 DPRINTK(2,
2238 "Infra bssid = %02x:%02x:%02x:%02x:%02x:%02x\n",
2239 priv->reg.bssid[0], priv->reg.bssid[1],
2240 priv->reg.bssid[2], priv->reg.bssid[3],
2241 priv->reg.bssid[4], priv->reg.bssid[5]);
Wolfram Sang13a99302016-05-31 12:56:13 +02002242 }
2243 break;
2244 case MODE_ADHOC:
2245 /* IEEE802.11 Ad-Hoc mode */
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002246 if (!is_valid_ether_addr((u8 *) priv->reg.bssid)) {
Wolfram Sang13a99302016-05-31 12:56:13 +02002247 hostif_adhoc_set_request(priv);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002248 } else {
Wolfram Sang13a99302016-05-31 12:56:13 +02002249 hostif_adhoc_set2_request(priv);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002250 DPRINTK(2,
2251 "Adhoc bssid = %02x:%02x:%02x:%02x:%02x:%02x\n",
2252 priv->reg.bssid[0], priv->reg.bssid[1],
2253 priv->reg.bssid[2], priv->reg.bssid[3],
2254 priv->reg.bssid[4], priv->reg.bssid[5]);
Wolfram Sang13a99302016-05-31 12:56:13 +02002255 }
2256 break;
2257 default:
2258 break;
2259 }
2260
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002261 return;
Wolfram Sang13a99302016-05-31 12:56:13 +02002262}
2263
2264static
Wolfram Sangfeedcf12016-05-31 12:56:26 +02002265void hostif_sme_multicast_set(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +02002266{
2267
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002268 struct net_device *dev = priv->net_dev;
Wolfram Sang13a99302016-05-31 12:56:13 +02002269 int mc_count;
Wolfram Sang13a99302016-05-31 12:56:13 +02002270 struct netdev_hw_addr *ha;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002271 char set_address[NIC_MAX_MCAST_LIST * ETH_ALEN];
Wolfram Sang13a99302016-05-31 12:56:13 +02002272 unsigned long filter_type;
Wolfram Sangf88e6d32016-05-31 12:56:22 +02002273 int i = 0;
Wolfram Sang13a99302016-05-31 12:56:13 +02002274
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002275 DPRINTK(3, "\n");
Wolfram Sang13a99302016-05-31 12:56:13 +02002276
2277 spin_lock(&priv->multicast_spin);
2278
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002279 memset(set_address, 0, NIC_MAX_MCAST_LIST * ETH_ALEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002280
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002281 if (dev->flags & IFF_PROMISC) {
2282 filter_type = cpu_to_le32((uint32_t) MCAST_FILTER_PROMISC);
2283 hostif_mib_set_request(priv, LOCAL_MULTICAST_FILTER,
2284 sizeof(filter_type), MIB_VALUE_TYPE_BOOL,
2285 &filter_type);
2286 } else if ((netdev_mc_count(dev) > NIC_MAX_MCAST_LIST)
2287 || (dev->flags & IFF_ALLMULTI)) {
2288 filter_type = cpu_to_le32((uint32_t) MCAST_FILTER_MCASTALL);
2289 hostif_mib_set_request(priv, LOCAL_MULTICAST_FILTER,
2290 sizeof(filter_type), MIB_VALUE_TYPE_BOOL,
2291 &filter_type);
2292 } else {
2293 if (priv->sme_i.sme_flag & SME_MULTICAST) {
Wolfram Sang13a99302016-05-31 12:56:13 +02002294 mc_count = netdev_mc_count(dev);
Wolfram Sang13a99302016-05-31 12:56:13 +02002295 netdev_for_each_mc_addr(ha, dev) {
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002296 memcpy(&set_address[i * ETH_ALEN], ha->addr,
2297 ETH_ALEN);
Wolfram Sangf88e6d32016-05-31 12:56:22 +02002298 i++;
Wolfram Sang13a99302016-05-31 12:56:13 +02002299 }
Wolfram Sang13a99302016-05-31 12:56:13 +02002300 priv->sme_i.sme_flag &= ~SME_MULTICAST;
2301 hostif_mib_set_request(priv, LOCAL_MULTICAST_ADDRESS,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002302 (ETH_ALEN * mc_count),
2303 MIB_VALUE_TYPE_OSTRING,
2304 &set_address[0]);
2305 } else {
2306 filter_type =
2307 cpu_to_le32((uint32_t) MCAST_FILTER_MCAST);
Wolfram Sang13a99302016-05-31 12:56:13 +02002308 priv->sme_i.sme_flag |= SME_MULTICAST;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002309 hostif_mib_set_request(priv, LOCAL_MULTICAST_FILTER,
2310 sizeof(filter_type),
2311 MIB_VALUE_TYPE_BOOL,
2312 &filter_type);
Wolfram Sang13a99302016-05-31 12:56:13 +02002313 }
2314 }
2315
2316 spin_unlock(&priv->multicast_spin);
2317
2318}
2319
2320static
Wolfram Sangfeedcf12016-05-31 12:56:26 +02002321void hostif_sme_powermgt_set(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +02002322{
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002323 unsigned long mode, wake_up, receiveDTIMs;
Wolfram Sang13a99302016-05-31 12:56:13 +02002324
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002325 DPRINTK(3, "\n");
2326 switch (priv->reg.powermgt) {
Wolfram Sang13a99302016-05-31 12:56:13 +02002327 case POWMGT_ACTIVE_MODE:
2328 mode = POWER_ACTIVE;
2329 wake_up = 0;
2330 receiveDTIMs = 0;
2331 break;
2332 case POWMGT_SAVE1_MODE:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002333 if (priv->reg.operation_mode == MODE_INFRASTRUCTURE) {
Wolfram Sang13a99302016-05-31 12:56:13 +02002334 mode = POWER_SAVE;
2335 wake_up = 0;
2336 receiveDTIMs = 0;
2337 } else {
2338 mode = POWER_ACTIVE;
2339 wake_up = 0;
2340 receiveDTIMs = 0;
2341 }
2342 break;
2343 case POWMGT_SAVE2_MODE:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002344 if (priv->reg.operation_mode == MODE_INFRASTRUCTURE) {
Wolfram Sang13a99302016-05-31 12:56:13 +02002345 mode = POWER_SAVE;
2346 wake_up = 0;
2347 receiveDTIMs = 1;
2348 } else {
2349 mode = POWER_ACTIVE;
2350 wake_up = 0;
2351 receiveDTIMs = 0;
2352 }
2353 break;
2354 default:
2355 mode = POWER_ACTIVE;
2356 wake_up = 0;
2357 receiveDTIMs = 0;
2358 break;
2359 }
2360 hostif_power_mngmt_request(priv, mode, wake_up, receiveDTIMs);
2361
2362 return;
2363}
2364
2365static
Wolfram Sangfeedcf12016-05-31 12:56:26 +02002366void hostif_sme_sleep_set(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +02002367{
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002368 DPRINTK(3, "\n");
2369 switch (priv->sleep_mode) {
Wolfram Sang13a99302016-05-31 12:56:13 +02002370 case SLP_SLEEP:
2371 hostif_sleep_request(priv, priv->sleep_mode);
2372 break;
2373 case SLP_ACTIVE:
2374 hostif_sleep_request(priv, priv->sleep_mode);
2375 break;
2376 default:
2377 break;
2378 }
2379
2380 return;
2381}
2382
2383static
Wolfram Sangfeedcf12016-05-31 12:56:26 +02002384void hostif_sme_set_key(struct ks_wlan_private *priv, int type)
Wolfram Sang13a99302016-05-31 12:56:13 +02002385{
2386 uint32_t val;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002387 switch (type) {
Wolfram Sang13a99302016-05-31 12:56:13 +02002388 case SME_SET_FLAG:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002389 val = cpu_to_le32((uint32_t) (priv->reg.privacy_invoked));
Wolfram Sang13a99302016-05-31 12:56:13 +02002390 hostif_mib_set_request(priv, DOT11_PRIVACY_INVOKED,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002391 sizeof(val), MIB_VALUE_TYPE_BOOL, &val);
Wolfram Sang13a99302016-05-31 12:56:13 +02002392 break;
2393 case SME_SET_TXKEY:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002394 val = cpu_to_le32((uint32_t) (priv->wpa.txkey));
Wolfram Sang13a99302016-05-31 12:56:13 +02002395 hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_ID,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002396 sizeof(val), MIB_VALUE_TYPE_INT, &val);
Wolfram Sang13a99302016-05-31 12:56:13 +02002397 break;
2398 case SME_SET_KEY1:
2399 hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_VALUE1,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002400 priv->wpa.key[0].key_len,
2401 MIB_VALUE_TYPE_OSTRING,
2402 &priv->wpa.key[0].key_val[0]);
Wolfram Sang13a99302016-05-31 12:56:13 +02002403 break;
2404 case SME_SET_KEY2:
2405 hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_VALUE2,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002406 priv->wpa.key[1].key_len,
2407 MIB_VALUE_TYPE_OSTRING,
2408 &priv->wpa.key[1].key_val[0]);
Wolfram Sang13a99302016-05-31 12:56:13 +02002409 break;
2410 case SME_SET_KEY3:
2411 hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_VALUE3,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002412 priv->wpa.key[2].key_len,
2413 MIB_VALUE_TYPE_OSTRING,
2414 &priv->wpa.key[2].key_val[0]);
Wolfram Sang13a99302016-05-31 12:56:13 +02002415 break;
2416 case SME_SET_KEY4:
2417 hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_VALUE4,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002418 priv->wpa.key[3].key_len,
2419 MIB_VALUE_TYPE_OSTRING,
2420 &priv->wpa.key[3].key_val[0]);
Wolfram Sang13a99302016-05-31 12:56:13 +02002421 break;
2422 case SME_SET_PMK_TSC:
2423 hostif_mib_set_request(priv, DOT11_PMK_TSC,
2424 WPA_RX_SEQ_LEN, MIB_VALUE_TYPE_OSTRING,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002425 &priv->wpa.key[0].rx_seq[0]);
Wolfram Sang13a99302016-05-31 12:56:13 +02002426 break;
2427 case SME_SET_GMK1_TSC:
2428 hostif_mib_set_request(priv, DOT11_GMK1_TSC,
2429 WPA_RX_SEQ_LEN, MIB_VALUE_TYPE_OSTRING,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002430 &priv->wpa.key[1].rx_seq[0]);
Wolfram Sang13a99302016-05-31 12:56:13 +02002431 break;
2432 case SME_SET_GMK2_TSC:
2433 hostif_mib_set_request(priv, DOT11_GMK2_TSC,
2434 WPA_RX_SEQ_LEN, MIB_VALUE_TYPE_OSTRING,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002435 &priv->wpa.key[2].rx_seq[0]);
Wolfram Sang13a99302016-05-31 12:56:13 +02002436 break;
2437 }
2438 return;
2439}
2440
2441static
Wolfram Sangfeedcf12016-05-31 12:56:26 +02002442void hostif_sme_set_pmksa(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +02002443{
2444 struct pmk_cache_t {
2445 uint16_t size;
2446 struct {
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002447 uint8_t bssid[ETH_ALEN];
2448 uint8_t pmkid[IW_PMKID_LEN];
2449 } __attribute__ ((packed)) list[PMK_LIST_MAX];
2450 } __attribute__ ((packed)) pmkcache;
Wolfram Sang13a99302016-05-31 12:56:13 +02002451 struct pmk_t *pmk;
2452 struct list_head *ptr;
2453 int i;
2454
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002455 DPRINTK(4, "pmklist.size=%d\n", priv->pmklist.size);
2456 i = 0;
2457 list_for_each(ptr, &priv->pmklist.head) {
Wolfram Sang13a99302016-05-31 12:56:13 +02002458 pmk = list_entry(ptr, struct pmk_t, list);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002459 if (i < PMK_LIST_MAX) {
Wolfram Sang13a99302016-05-31 12:56:13 +02002460 memcpy(pmkcache.list[i].bssid, pmk->bssid, ETH_ALEN);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002461 memcpy(pmkcache.list[i].pmkid, pmk->pmkid,
2462 IW_PMKID_LEN);
Wolfram Sang13a99302016-05-31 12:56:13 +02002463 i++;
2464 }
2465 }
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002466 pmkcache.size = cpu_to_le16((uint16_t) (priv->pmklist.size));
Wolfram Sang13a99302016-05-31 12:56:13 +02002467 hostif_mib_set_request(priv, LOCAL_PMK,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002468 sizeof(priv->pmklist.size) + (ETH_ALEN +
2469 IW_PMKID_LEN) *
2470 (priv->pmklist.size), MIB_VALUE_TYPE_OSTRING,
2471 &pmkcache);
Wolfram Sang13a99302016-05-31 12:56:13 +02002472}
2473
2474/* execute sme */
2475static
Wolfram Sangfeedcf12016-05-31 12:56:26 +02002476void hostif_sme_execute(struct ks_wlan_private *priv, int event)
Wolfram Sang13a99302016-05-31 12:56:13 +02002477{
2478 uint32_t val;
2479
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002480 DPRINTK(3, "event=%d\n", event);
Wolfram Sang13a99302016-05-31 12:56:13 +02002481 switch (event) {
2482 case SME_START:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002483 if (priv->dev_state == DEVICE_STATE_BOOT) {
Wolfram Sang13a99302016-05-31 12:56:13 +02002484 hostif_mib_get_request(priv, DOT11_MAC_ADDRESS);
2485 }
2486 break;
2487 case SME_MULTICAST_REQUEST:
2488 hostif_sme_multicast_set(priv);
2489 break;
2490 case SME_MACADDRESS_SET_REQUEST:
2491 hostif_mib_set_request(priv, LOCAL_CURRENTADDRESS, ETH_ALEN,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002492 MIB_VALUE_TYPE_OSTRING,
2493 &priv->eth_addr[0]);
Wolfram Sang13a99302016-05-31 12:56:13 +02002494 break;
2495 case SME_BSS_SCAN_REQUEST:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002496 hostif_bss_scan_request(priv, priv->reg.scan_type,
2497 priv->scan_ssid, priv->scan_ssid_len);
Wolfram Sang13a99302016-05-31 12:56:13 +02002498 break;
2499 case SME_POW_MNGMT_REQUEST:
2500 hostif_sme_powermgt_set(priv);
2501 break;
2502 case SME_PHY_INFO_REQUEST:
2503 hostif_phy_information_request(priv);
2504 break;
2505 case SME_MIC_FAILURE_REQUEST:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002506 if (priv->wpa.mic_failure.failure == 1) {
2507 hostif_mic_failure_request(priv,
2508 priv->wpa.mic_failure.
2509 failure - 1, 0);
2510 } else if (priv->wpa.mic_failure.failure == 2) {
2511 hostif_mic_failure_request(priv,
2512 priv->wpa.mic_failure.
2513 failure - 1,
2514 priv->wpa.mic_failure.
2515 counter);
2516 } else
2517 DPRINTK(4,
2518 "SME_MIC_FAILURE_REQUEST: failure count=%u error?\n",
Wolfram Sang13a99302016-05-31 12:56:13 +02002519 priv->wpa.mic_failure.failure);
2520 break;
2521 case SME_MIC_FAILURE_CONFIRM:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002522 if (priv->wpa.mic_failure.failure == 2) {
2523 if (priv->wpa.mic_failure.stop)
Wolfram Sang13a99302016-05-31 12:56:13 +02002524 priv->wpa.mic_failure.stop = 0;
2525 priv->wpa.mic_failure.failure = 0;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002526 hostif_start_request(priv, priv->reg.operation_mode);
Wolfram Sang13a99302016-05-31 12:56:13 +02002527 }
2528 break;
2529 case SME_GET_MAC_ADDRESS:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002530 if (priv->dev_state == DEVICE_STATE_BOOT) {
Wolfram Sang13a99302016-05-31 12:56:13 +02002531 hostif_mib_get_request(priv, DOT11_PRODUCT_VERSION);
2532 }
2533 break;
2534 case SME_GET_PRODUCT_VERSION:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002535 if (priv->dev_state == DEVICE_STATE_BOOT) {
Wolfram Sang13a99302016-05-31 12:56:13 +02002536 priv->dev_state = DEVICE_STATE_PREINIT;
2537 }
2538 break;
2539 case SME_STOP_REQUEST:
2540 hostif_stop_request(priv);
2541 break;
2542 case SME_RTS_THRESHOLD_REQUEST:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002543 val = cpu_to_le32((uint32_t) (priv->reg.rts));
Wolfram Sang13a99302016-05-31 12:56:13 +02002544 hostif_mib_set_request(priv, DOT11_RTS_THRESHOLD,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002545 sizeof(val), MIB_VALUE_TYPE_INT, &val);
Wolfram Sang13a99302016-05-31 12:56:13 +02002546 break;
2547 case SME_FRAGMENTATION_THRESHOLD_REQUEST:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002548 val = cpu_to_le32((uint32_t) (priv->reg.fragment));
Wolfram Sang13a99302016-05-31 12:56:13 +02002549 hostif_mib_set_request(priv, DOT11_FRAGMENTATION_THRESHOLD,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002550 sizeof(val), MIB_VALUE_TYPE_INT, &val);
Wolfram Sang13a99302016-05-31 12:56:13 +02002551 break;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002552 case SME_WEP_INDEX_REQUEST:
2553 case SME_WEP_KEY1_REQUEST:
2554 case SME_WEP_KEY2_REQUEST:
2555 case SME_WEP_KEY3_REQUEST:
2556 case SME_WEP_KEY4_REQUEST:
2557 case SME_WEP_FLAG_REQUEST:
2558 hostif_sme_set_wep(priv, event);
Wolfram Sang13a99302016-05-31 12:56:13 +02002559 break;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002560 case SME_RSN_UCAST_REQUEST:
2561 case SME_RSN_MCAST_REQUEST:
2562 case SME_RSN_AUTH_REQUEST:
2563 case SME_RSN_ENABLED_REQUEST:
Wolfram Sang13a99302016-05-31 12:56:13 +02002564 case SME_RSN_MODE_REQUEST:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002565 hostif_sme_set_rsn(priv, event);
Wolfram Sang13a99302016-05-31 12:56:13 +02002566 break;
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002567 case SME_SET_FLAG:
2568 case SME_SET_TXKEY:
2569 case SME_SET_KEY1:
2570 case SME_SET_KEY2:
2571 case SME_SET_KEY3:
2572 case SME_SET_KEY4:
2573 case SME_SET_PMK_TSC:
2574 case SME_SET_GMK1_TSC:
Wolfram Sang13a99302016-05-31 12:56:13 +02002575 case SME_SET_GMK2_TSC:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002576 hostif_sme_set_key(priv, event);
Wolfram Sang13a99302016-05-31 12:56:13 +02002577 break;
2578 case SME_SET_PMKSA:
2579 hostif_sme_set_pmksa(priv);
2580 break;
2581#ifdef WPS
2582 case SME_WPS_ENABLE_REQUEST:
2583 hostif_mib_set_request(priv, LOCAL_WPS_ENABLE,
2584 sizeof(priv->wps.wps_enabled),
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002585 MIB_VALUE_TYPE_INT,
2586 &priv->wps.wps_enabled);
Wolfram Sang13a99302016-05-31 12:56:13 +02002587 break;
2588 case SME_WPS_PROBE_REQUEST:
2589 hostif_mib_set_request(priv, LOCAL_WPS_PROBE_REQ,
2590 priv->wps.ielen,
2591 MIB_VALUE_TYPE_OSTRING, priv->wps.ie);
2592 break;
2593#endif /* WPS */
2594 case SME_MODE_SET_REQUEST:
2595 hostif_sme_mode_setup(priv);
2596 break;
2597 case SME_SET_GAIN:
2598 hostif_mib_set_request(priv, LOCAL_GAIN,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002599 sizeof(priv->gain),
2600 MIB_VALUE_TYPE_OSTRING, &priv->gain);
Wolfram Sang13a99302016-05-31 12:56:13 +02002601 break;
2602 case SME_GET_GAIN:
2603 hostif_mib_get_request(priv, LOCAL_GAIN);
2604 break;
2605 case SME_GET_EEPROM_CKSUM:
2606 priv->eeprom_checksum = EEPROM_FW_NOT_SUPPORT; /* initialize */
2607 hostif_mib_get_request(priv, LOCAL_EEPROM_SUM);
2608 break;
2609 case SME_START_REQUEST:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002610 hostif_start_request(priv, priv->reg.operation_mode);
Wolfram Sang13a99302016-05-31 12:56:13 +02002611 break;
2612 case SME_START_CONFIRM:
2613 /* for power save */
2614 atomic_set(&priv->psstatus.snooze_guard, 0);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002615 atomic_set(&priv->psstatus.confirm_wait, 0);
2616 if (priv->dev_state == DEVICE_STATE_PREINIT) {
Wolfram Sang13a99302016-05-31 12:56:13 +02002617 priv->dev_state = DEVICE_STATE_INIT;
2618 }
2619 /* wake_up_interruptible_all(&priv->confirm_wait); */
2620 complete(&priv->confirm_wait);
2621 break;
2622 case SME_SLEEP_REQUEST:
2623 hostif_sme_sleep_set(priv);
2624 break;
2625 case SME_SET_REGION:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002626 val = cpu_to_le32((uint32_t) (priv->region));
Wolfram Sang13a99302016-05-31 12:56:13 +02002627 hostif_mib_set_request(priv, LOCAL_REGION,
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002628 sizeof(val), MIB_VALUE_TYPE_INT, &val);
Wolfram Sang13a99302016-05-31 12:56:13 +02002629 break;
2630 case SME_MULTICAST_CONFIRM:
2631 case SME_BSS_SCAN_CONFIRM:
2632 case SME_POW_MNGMT_CONFIRM:
2633 case SME_PHY_INFO_CONFIRM:
2634 case SME_STOP_CONFIRM:
2635 case SME_RTS_THRESHOLD_CONFIRM:
2636 case SME_FRAGMENTATION_THRESHOLD_CONFIRM:
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002637 case SME_WEP_INDEX_CONFIRM:
2638 case SME_WEP_KEY1_CONFIRM:
2639 case SME_WEP_KEY2_CONFIRM:
2640 case SME_WEP_KEY3_CONFIRM:
2641 case SME_WEP_KEY4_CONFIRM:
2642 case SME_WEP_FLAG_CONFIRM:
2643 case SME_RSN_UCAST_CONFIRM:
2644 case SME_RSN_MCAST_CONFIRM:
2645 case SME_RSN_AUTH_CONFIRM:
2646 case SME_RSN_ENABLED_CONFIRM:
Wolfram Sang13a99302016-05-31 12:56:13 +02002647 case SME_RSN_MODE_CONFIRM:
2648 case SME_MODE_SET_CONFIRM:
2649 break;
2650 case SME_TERMINATE:
2651 default:
2652 break;
2653 }
2654}
2655
2656static
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002657void hostif_sme_task(unsigned long dev)
Wolfram Sang13a99302016-05-31 12:56:13 +02002658{
Wolfram Sangfeedcf12016-05-31 12:56:26 +02002659 struct ks_wlan_private *priv = (struct ks_wlan_private *)dev;
Wolfram Sang13a99302016-05-31 12:56:13 +02002660
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002661 DPRINTK(3, "\n");
Wolfram Sang13a99302016-05-31 12:56:13 +02002662
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002663 if (priv->dev_state >= DEVICE_STATE_BOOT) {
2664 if (0 < cnt_smeqbody(priv)
2665 && priv->dev_state >= DEVICE_STATE_BOOT) {
2666 hostif_sme_execute(priv,
2667 priv->sme_i.event_buff[priv->sme_i.
2668 qhead]);
Wolfram Sang13a99302016-05-31 12:56:13 +02002669 inc_smeqhead(priv);
2670 if (0 < cnt_smeqbody(priv))
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002671 tasklet_schedule(&priv->sme_task);
Wolfram Sang13a99302016-05-31 12:56:13 +02002672 }
2673 }
2674 return;
2675}
2676
2677/* send to Station Management Entity module */
Wolfram Sangfeedcf12016-05-31 12:56:26 +02002678void hostif_sme_enqueue(struct ks_wlan_private *priv, unsigned short event)
Wolfram Sang13a99302016-05-31 12:56:13 +02002679{
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002680 DPRINTK(3, "\n");
Wolfram Sang13a99302016-05-31 12:56:13 +02002681
2682 /* enqueue sme event */
2683 if (cnt_smeqbody(priv) < (SME_EVENT_BUFF_SIZE - 1)) {
2684 priv->sme_i.event_buff[priv->sme_i.qtail] = event;
2685 inc_smeqtail(priv);
2686 //DPRINTK(3,"inc_smeqtail \n");
2687#ifdef KS_WLAN_DEBUG
2688 if (priv->sme_i.max_event_count < cnt_smeqbody(priv))
2689 priv->sme_i.max_event_count = cnt_smeqbody(priv);
2690#endif /* KS_WLAN_DEBUG */
2691 } else {
2692 /* in case of buffer overflow */
2693 //DPRINTK(2,"sme queue buffer overflow\n");
2694 printk("sme queue buffer overflow\n");
2695 }
2696
2697 tasklet_schedule(&priv->sme_task);
2698
2699}
2700
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002701int hostif_init(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +02002702{
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002703 int rc = 0;
Wolfram Sang13a99302016-05-31 12:56:13 +02002704 int i;
2705
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002706 DPRINTK(3, "\n");
Wolfram Sang13a99302016-05-31 12:56:13 +02002707
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002708 priv->aplist.size = 0;
2709 for (i = 0; i < LOCAL_APLIST_MAX; i++)
2710 memset(&(priv->aplist.ap[i]), 0, sizeof(struct local_ap_t));
Wolfram Sang13a99302016-05-31 12:56:13 +02002711 priv->infra_status = 0;
2712 priv->current_rate = 4;
2713 priv->connect_status = DISCONNECT_STATUS;
2714
2715 spin_lock_init(&priv->multicast_spin);
2716
2717 spin_lock_init(&priv->dev_read_lock);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002718 init_waitqueue_head(&priv->devread_wait);
Wolfram Sang13a99302016-05-31 12:56:13 +02002719 priv->dev_count = 0;
2720 atomic_set(&priv->event_count, 0);
2721 atomic_set(&priv->rec_count, 0);
2722
2723 /* for power save */
2724 atomic_set(&priv->psstatus.status, PS_NONE);
2725 atomic_set(&priv->psstatus.confirm_wait, 0);
2726 atomic_set(&priv->psstatus.snooze_guard, 0);
2727 /* init_waitqueue_head(&priv->psstatus.wakeup_wait); */
2728 init_completion(&priv->psstatus.wakeup_wait);
2729 //INIT_WORK(&priv->ks_wlan_wakeup_task, ks_wlan_hw_wakeup_task, (void *)priv);
2730 INIT_WORK(&priv->ks_wlan_wakeup_task, ks_wlan_hw_wakeup_task);
2731
2732 /* WPA */
2733 memset(&(priv->wpa), 0, sizeof(priv->wpa));
2734 priv->wpa.rsn_enabled = 0;
2735 priv->wpa.mic_failure.failure = 0;
2736 priv->wpa.mic_failure.last_failure_time = 0;
2737 priv->wpa.mic_failure.stop = 0;
2738 memset(&(priv->pmklist), 0, sizeof(priv->pmklist));
2739 INIT_LIST_HEAD(&priv->pmklist.head);
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002740 for (i = 0; i < PMK_LIST_MAX; i++)
Wolfram Sang13a99302016-05-31 12:56:13 +02002741 INIT_LIST_HEAD(&priv->pmklist.pmk[i].list);
2742
2743 priv->sme_i.sme_status = SME_IDLE;
2744 priv->sme_i.qhead = priv->sme_i.qtail = 0;
2745#ifdef KS_WLAN_DEBUG
2746 priv->sme_i.max_event_count = 0;
2747#endif
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002748 spin_lock_init(&priv->sme_i.sme_spin);
Wolfram Sang13a99302016-05-31 12:56:13 +02002749 priv->sme_i.sme_flag = 0;
2750
2751 tasklet_init(&priv->sme_task, hostif_sme_task, (unsigned long)priv);
2752
2753 return rc;
2754}
2755
Wolfram Sang20c4f9c2016-05-31 12:56:30 +02002756void hostif_exit(struct ks_wlan_private *priv)
Wolfram Sang13a99302016-05-31 12:56:13 +02002757{
2758 tasklet_kill(&priv->sme_task);
2759 return;
2760}