staging: wilc1000: remove unnecessary blank line between variable declaration
[linux-2.6-block.git] / drivers / staging / wilc1000 / linux_wlan.c
CommitLineData
903ac63f 1// SPDX-License-Identifier: GPL-2.0
c5c77ba1 2#include <linux/irq.h>
f1a99830 3#include <linux/gpio.h>
c5c77ba1
JK
4#include <linux/kthread.h>
5#include <linux/firmware.h>
c5c77ba1 6#include <linux/netdevice.h>
c5c77ba1 7#include <linux/inetdevice.h>
880e404e
AS
8
9#include "wilc_wfi_cfgoperations.h"
c5c77ba1 10
0e1af73d 11bool wilc_enable_ps = true;
c5c77ba1 12
885cabcc
LK
13static int dev_state_ev_handler(struct notifier_block *this,
14 unsigned long event, void *ptr)
c5c77ba1 15{
d5c89442 16 struct in_ifaddr *dev_iface = ptr;
2726887c 17 struct wilc_priv *priv;
f24374aa 18 struct host_if_drv *hif_drv;
c5c77ba1 19 struct net_device *dev;
eac3e8f6 20 u8 *ip_addr_buf;
a4cac481 21 struct wilc_vif *vif;
63d03e47 22 u8 null_ip[4] = {0};
c5c77ba1
JK
23 char wlan_dev_name[5] = "wlan0";
24
1408603c 25 if (!dev_iface || !dev_iface->ifa_dev || !dev_iface->ifa_dev->dev)
c5c77ba1 26 return NOTIFY_DONE;
c5c77ba1 27
582f8a27 28 if (memcmp(dev_iface->ifa_label, "wlan0", 5) &&
1408603c 29 memcmp(dev_iface->ifa_label, "p2p0", 4))
c5c77ba1 30 return NOTIFY_DONE;
c5c77ba1
JK
31
32 dev = (struct net_device *)dev_iface->ifa_dev->dev;
1408603c 33 if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
c5c77ba1 34 return NOTIFY_DONE;
1408603c 35
c5c77ba1 36 priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
1408603c 37 if (!priv)
c5c77ba1 38 return NOTIFY_DONE;
1408603c 39
48b28df9 40 hif_drv = (struct host_if_drv *)priv->hif_drv;
a4cac481 41 vif = netdev_priv(dev);
1408603c 42 if (!vif || !hif_drv)
c5c77ba1 43 return NOTIFY_DONE;
c5c77ba1
JK
44
45 switch (event) {
46 case NETDEV_UP:
a4cac481 47 if (vif->iftype == STATION_MODE || vif->iftype == CLIENT_MODE) {
742a4869 48 hif_drv->ifc_up = 1;
0e1af73d
AB
49 wilc_optaining_ip = false;
50 del_timer(&wilc_during_ip_timer);
c5c77ba1
JK
51 }
52
0e1af73d 53 if (wilc_enable_ps)
fbf5379b 54 wilc_set_power_mgmt(vif, 1, 0);
c5c77ba1 55
5ac24427 56 netdev_dbg(dev, "[%s] Up IP\n", dev_iface->ifa_label);
c5c77ba1 57
eac3e8f6 58 ip_addr_buf = (char *)&dev_iface->ifa_address;
5ac24427
LK
59 netdev_dbg(dev, "IP add=%d:%d:%d:%d\n",
60 ip_addr_buf[0], ip_addr_buf[1],
61 ip_addr_buf[2], ip_addr_buf[3]);
6750140d 62 wilc_setup_ipaddress(vif, ip_addr_buf, vif->idx);
c5c77ba1
JK
63
64 break;
65
66 case NETDEV_DOWN:
a4cac481 67 if (vif->iftype == STATION_MODE || vif->iftype == CLIENT_MODE) {
742a4869 68 hif_drv->ifc_up = 0;
0e1af73d 69 wilc_optaining_ip = false;
c5c77ba1
JK
70 }
71
72 if (memcmp(dev_iface->ifa_label, wlan_dev_name, 5) == 0)
fbf5379b 73 wilc_set_power_mgmt(vif, 0, 0);
c5c77ba1 74
fbf5379b 75 wilc_resolve_disconnect_aberration(vif);
c5c77ba1 76
5ac24427 77 netdev_dbg(dev, "[%s] Down IP\n", dev_iface->ifa_label);
c5c77ba1 78
eac3e8f6 79 ip_addr_buf = null_ip;
5ac24427
LK
80 netdev_dbg(dev, "IP add=%d:%d:%d:%d\n",
81 ip_addr_buf[0], ip_addr_buf[1],
82 ip_addr_buf[2], ip_addr_buf[3]);
c5c77ba1 83
6750140d 84 wilc_setup_ipaddress(vif, ip_addr_buf, vif->idx);
c5c77ba1
JK
85
86 break;
87
88 default:
c5c77ba1
JK
89 break;
90 }
91
92 return NOTIFY_DONE;
c5c77ba1 93}
c5c77ba1 94
c5c77ba1
JK
95static irqreturn_t isr_uh_routine(int irq, void *user_data)
96{
a4cac481 97 struct wilc_vif *vif;
3948362d 98 struct wilc *wilc;
d5c89442 99 struct net_device *dev = user_data;
3948362d 100
a4cac481
GL
101 vif = netdev_priv(dev);
102 wilc = vif->wilc;
c5c77ba1 103
3948362d 104 if (wilc->close) {
5ac24427 105 netdev_err(dev, "Can't handle UH interrupt\n");
c5c77ba1 106 return IRQ_HANDLED;
c5c77ba1 107 }
c5c77ba1 108 return IRQ_WAKE_THREAD;
c5c77ba1 109}
c5c77ba1 110
1608c403 111static irqreturn_t isr_bh_routine(int irq, void *userdata)
c5c77ba1 112{
a4cac481 113 struct wilc_vif *vif;
2e7933d0 114 struct wilc *wilc;
d5c89442 115 struct net_device *dev = userdata;
2e7933d0 116
a4cac481
GL
117 vif = netdev_priv(userdata);
118 wilc = vif->wilc;
2e7933d0 119
2e7933d0 120 if (wilc->close) {
5ac24427 121 netdev_err(dev, "Can't handle BH interrupt\n");
c5c77ba1 122 return IRQ_HANDLED;
c5c77ba1
JK
123 }
124
50b929e0 125 wilc_handle_isr(wilc);
c5c77ba1 126
c5c77ba1 127 return IRQ_HANDLED;
c5c77ba1 128}
c5c77ba1 129
2c1d05d1 130static int init_irq(struct net_device *dev)
c5c77ba1
JK
131{
132 int ret = 0;
a4cac481 133 struct wilc_vif *vif;
2c1d05d1
GL
134 struct wilc *wl;
135
a4cac481
GL
136 vif = netdev_priv(dev);
137 wl = vif->wilc;
c5c77ba1 138
c4d139cb
AB
139 if ((gpio_request(wl->gpio, "WILC_INTR") == 0) &&
140 (gpio_direction_input(wl->gpio) == 0)) {
141 wl->dev_irq_num = gpio_to_irq(wl->gpio);
c5c77ba1
JK
142 } else {
143 ret = -1;
5ac24427 144 netdev_err(dev, "could not obtain gpio for WILC_INTR\n");
c5c77ba1
JK
145 }
146
83231b72
LK
147 if (ret != -1 && request_threaded_irq(wl->dev_irq_num,
148 isr_uh_routine,
149 isr_bh_routine,
150 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
151 "WILC_IRQ", dev) < 0) {
5ac24427 152 netdev_err(dev, "Failed to request IRQ GPIO: %d\n", wl->gpio);
c4d139cb 153 gpio_free(wl->gpio);
c5c77ba1
JK
154 ret = -1;
155 } else {
5ac24427
LK
156 netdev_dbg(dev,
157 "IRQ request succeeded IRQ-NUM= %d on GPIO: %d\n",
158 wl->dev_irq_num, wl->gpio);
c5c77ba1
JK
159 }
160
161 return ret;
162}
c5c77ba1 163
ec5cc750 164static void deinit_irq(struct net_device *dev)
c5c77ba1 165{
a4cac481 166 struct wilc_vif *vif;
ec5cc750
GL
167 struct wilc *wilc;
168
a4cac481
GL
169 vif = netdev_priv(dev);
170 wilc = vif->wilc;
ec5cc750 171
1cce2000 172 /* Deinitialize IRQ */
c4d139cb 173 if (wilc->dev_irq_num) {
ec5cc750 174 free_irq(wilc->dev_irq_num, wilc);
c4d139cb 175 gpio_free(wilc->gpio);
c5c77ba1 176 }
c5c77ba1
JK
177}
178
c7ceac21 179void wilc_mac_indicate(struct wilc *wilc)
c5c77ba1 180{
c5c77ba1
JK
181 int status;
182
c7ceac21
AS
183 wilc_wlan_cfg_get_val(WID_STATUS, (unsigned char *)&status, 4);
184 if (wilc->mac_status == MAC_STATUS_INIT) {
185 wilc->mac_status = status;
186 complete(&wilc->sync_event);
187 } else {
188 wilc->mac_status = status;
c5c77ba1 189 }
c5c77ba1
JK
190}
191
1608c403 192static struct net_device *get_if_handler(struct wilc *wilc, u8 *mac_header)
c5c77ba1 193{
660786ea 194 u8 *bssid, *bssid1;
c5c77ba1
JK
195 int i = 0;
196
d239222e 197 bssid = mac_header + 10;
660786ea 198 bssid1 = mac_header + 4;
c5c77ba1 199
ba615f1e
GL
200 for (i = 0; i < wilc->vif_num; i++) {
201 if (wilc->vif[i]->mode == STATION_MODE)
fa633941
LK
202 if (ether_addr_equal_unaligned(bssid,
203 wilc->vif[i]->bssid))
ba615f1e
GL
204 return wilc->vif[i]->ndev;
205 if (wilc->vif[i]->mode == AP_MODE)
fa633941
LK
206 if (ether_addr_equal_unaligned(bssid1,
207 wilc->vif[i]->bssid))
ba615f1e
GL
208 return wilc->vif[i]->ndev;
209 }
8259a53e 210
c5c77ba1
JK
211 return NULL;
212}
213
ba615f1e 214int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode)
c5c77ba1 215{
735bb39c 216 struct wilc_vif *vif = netdev_priv(wilc_netdev);
472791a9 217
735bb39c
AB
218 memcpy(vif->bssid, bssid, 6);
219 vif->mode = mode;
8259a53e 220
735bb39c 221 return 0;
c5c77ba1
JK
222}
223
562ed3f1 224int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc)
c5c77ba1 225{
51e825f7
CL
226 u8 i = 0;
227 u8 null_bssid[6] = {0};
228 u8 ret_val = 0;
c5c77ba1 229
562ed3f1 230 for (i = 0; i < wilc->vif_num; i++)
1f435d2e 231 if (memcmp(wilc->vif[i]->bssid, null_bssid, 6))
c5c77ba1 232 ret_val++;
8259a53e 233
c5c77ba1
JK
234 return ret_val;
235}
236
c5c77ba1
JK
237static int linux_wlan_txq_task(void *vp)
238{
8a88dd46
IS
239 int ret;
240 u32 txq_count;
a4cac481 241 struct wilc_vif *vif;
88687584
GL
242 struct wilc *wl;
243 struct net_device *dev = vp;
c5c77ba1 244
a4cac481
GL
245 vif = netdev_priv(dev);
246 wl = vif->wilc;
88687584 247
11a54b3f 248 complete(&wl->txq_thread_started);
c5c77ba1 249 while (1) {
b27a6d5e 250 wait_for_completion(&wl->txq_event);
c5c77ba1 251
88687584 252 if (wl->close) {
11a54b3f 253 complete(&wl->txq_thread_started);
c5c77ba1
JK
254
255 while (!kthread_should_stop())
256 schedule();
c5c77ba1
JK
257 break;
258 }
c5c77ba1 259 do {
a1332cad 260 ret = wilc_wlan_handle_txq(dev, &txq_count);
98b89847 261 if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD) {
1f435d2e
GL
262 if (netif_queue_stopped(wl->vif[0]->ndev))
263 netif_wake_queue(wl->vif[0]->ndev);
264 if (netif_queue_stopped(wl->vif[1]->ndev))
265 netif_wake_queue(wl->vif[1]->ndev);
c5c77ba1 266 }
98b89847 267 } while (ret == WILC_TX_ERR_NO_BUF && !wl->close);
c5c77ba1
JK
268 }
269 return 0;
270}
271
ead6cb05 272static int wilc_wlan_get_firmware(struct net_device *dev)
c5c77ba1 273{
a4cac481 274 struct wilc_vif *vif;
65c8adcf 275 struct wilc *wilc;
14823bf2 276 int chip_id, ret = 0;
c5c77ba1
JK
277 const struct firmware *wilc_firmware;
278 char *firmware;
279
a4cac481
GL
280 vif = netdev_priv(dev);
281 wilc = vif->wilc;
65c8adcf 282
65c3f000 283 chip_id = wilc_get_chipid(wilc, false);
14823bf2
GL
284
285 if (chip_id < 0x1003a0)
286 firmware = FIRMWARE_1002;
287 else
288 firmware = FIRMWARE_1003;
289
290 netdev_info(dev, "loading firmware %s\n", firmware);
c5c77ba1 291
1408603c 292 if (!(&vif->ndev->dev))
5fe678b1 293 goto fail;
c5c77ba1 294
b03314e2 295 if (request_firmware(&wilc_firmware, firmware, wilc->dev) != 0) {
b9811891 296 netdev_err(dev, "%s - firmware not available\n", firmware);
c5c77ba1 297 ret = -1;
5fe678b1 298 goto fail;
c5c77ba1 299 }
65c8adcf 300 wilc->firmware = wilc_firmware;
c5c77ba1 301
5fe678b1 302fail:
c5c77ba1
JK
303
304 return ret;
c5c77ba1
JK
305}
306
9bf3d727 307static int linux_wlan_start_firmware(struct net_device *dev)
c5c77ba1 308{
a4cac481 309 struct wilc_vif *vif;
9bf3d727 310 struct wilc *wilc;
c5c77ba1 311 int ret = 0;
9bf3d727 312
a4cac481
GL
313 vif = netdev_priv(dev);
314 wilc = vif->wilc;
9bf3d727 315
562ed3f1 316 ret = wilc_wlan_start(wilc);
1408603c 317 if (ret < 0)
0aeea1ad 318 return ret;
c5c77ba1 319
04247e7d 320 if (!wait_for_completion_timeout(&wilc->sync_event,
36190caa 321 msecs_to_jiffies(5000)))
04247e7d 322 return -ETIME;
c5c77ba1 323
0aeea1ad 324 return 0;
c5c77ba1 325}
a40b22c5 326
562ed3f1 327static int wilc1000_firmware_download(struct net_device *dev)
c5c77ba1 328{
a4cac481 329 struct wilc_vif *vif;
ed760b67 330 struct wilc *wilc;
c5c77ba1
JK
331 int ret = 0;
332
a4cac481
GL
333 vif = netdev_priv(dev);
334 wilc = vif->wilc;
ed760b67
GL
335
336 if (!wilc->firmware) {
5ac24427 337 netdev_err(dev, "Firmware buffer is NULL\n");
14b1821d 338 return -ENOBUFS;
c5c77ba1 339 }
1408603c 340
562ed3f1 341 ret = wilc_wlan_firmware_download(wilc, wilc->firmware->data,
ed760b67 342 wilc->firmware->size);
fc4b95d6 343 if (ret < 0)
14b1821d 344 return ret;
c5c77ba1 345
ed760b67 346 release_firmware(wilc->firmware);
6f72ed75 347 wilc->firmware = NULL;
c5c77ba1 348
5ac24427 349 netdev_dbg(dev, "Download Succeeded\n");
c5c77ba1 350
14b1821d 351 return 0;
c5c77ba1
JK
352}
353
00215dde 354static int linux_wlan_init_test_config(struct net_device *dev,
b8f6ca0b 355 struct wilc_vif *vif)
c5c77ba1 356{
c5c77ba1 357 unsigned char c_val[64];
b8f6ca0b 358 struct wilc *wilc = vif->wilc;
2726887c 359 struct wilc_priv *priv;
0fa66c71 360 struct host_if_drv *hif_drv;
c5c77ba1 361
5ac24427 362 netdev_dbg(dev, "Start configuring Firmware\n");
c5c77ba1 363 priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
48b28df9 364 hif_drv = (struct host_if_drv *)priv->hif_drv;
5ac24427 365 netdev_dbg(dev, "Host = %p\n", hif_drv);
65c3f000 366 wilc_get_chipid(wilc, false);
c5c77ba1 367
e5d57e91 368 *(int *)c_val = 1;
c5c77ba1 369
79df6a49 370 if (!wilc_wlan_cfg_set(vif, 1, WID_SET_DRV_HANDLER, c_val, 4, 0, 0))
5fe678b1 371 goto fail;
c5c77ba1 372
c5c77ba1 373 c_val[0] = 0;
79df6a49 374 if (!wilc_wlan_cfg_set(vif, 0, WID_PC_TEST_MODE, c_val, 1, 0, 0))
5fe678b1 375 goto fail;
c5c77ba1
JK
376
377 c_val[0] = INFRASTRUCTURE;
79df6a49 378 if (!wilc_wlan_cfg_set(vif, 0, WID_BSS_TYPE, c_val, 1, 0, 0))
5fe678b1 379 goto fail;
c5c77ba1 380
b69845ea 381 c_val[0] = AUTORATE;
79df6a49 382 if (!wilc_wlan_cfg_set(vif, 0, WID_CURRENT_TX_RATE, c_val, 1, 0, 0))
5fe678b1 383 goto fail;
c5c77ba1
JK
384
385 c_val[0] = G_MIXED_11B_2_MODE;
79df6a49 386 if (!wilc_wlan_cfg_set(vif, 0, WID_11G_OPERATING_MODE, c_val, 1, 0,
89758e13 387 0))
5fe678b1 388 goto fail;
c5c77ba1
JK
389
390 c_val[0] = 1;
79df6a49 391 if (!wilc_wlan_cfg_set(vif, 0, WID_CURRENT_CHANNEL, c_val, 1, 0, 0))
5fe678b1 392 goto fail;
c5c77ba1
JK
393
394 c_val[0] = G_SHORT_PREAMBLE;
79df6a49 395 if (!wilc_wlan_cfg_set(vif, 0, WID_PREAMBLE, c_val, 1, 0, 0))
5fe678b1 396 goto fail;
c5c77ba1
JK
397
398 c_val[0] = AUTO_PROT;
79df6a49 399 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_PROT_MECH, c_val, 1, 0, 0))
5fe678b1 400 goto fail;
c5c77ba1 401
c5c77ba1 402 c_val[0] = ACTIVE_SCAN;
79df6a49 403 if (!wilc_wlan_cfg_set(vif, 0, WID_SCAN_TYPE, c_val, 1, 0, 0))
5fe678b1 404 goto fail;
c5c77ba1
JK
405
406 c_val[0] = SITE_SURVEY_OFF;
79df6a49 407 if (!wilc_wlan_cfg_set(vif, 0, WID_SITE_SURVEY, c_val, 1, 0, 0))
5fe678b1 408 goto fail;
c5c77ba1 409
98b89847 410 *((int *)c_val) = 0xffff;
79df6a49 411 if (!wilc_wlan_cfg_set(vif, 0, WID_RTS_THRESHOLD, c_val, 2, 0, 0))
5fe678b1 412 goto fail;
c5c77ba1
JK
413
414 *((int *)c_val) = 2346;
79df6a49 415 if (!wilc_wlan_cfg_set(vif, 0, WID_FRAG_THRESHOLD, c_val, 2, 0, 0))
5fe678b1 416 goto fail;
c5c77ba1 417
c5c77ba1 418 c_val[0] = 0;
79df6a49 419 if (!wilc_wlan_cfg_set(vif, 0, WID_BCAST_SSID, c_val, 1, 0, 0))
5fe678b1 420 goto fail;
c5c77ba1
JK
421
422 c_val[0] = 1;
79df6a49 423 if (!wilc_wlan_cfg_set(vif, 0, WID_QOS_ENABLE, c_val, 1, 0, 0))
5fe678b1 424 goto fail;
c5c77ba1
JK
425
426 c_val[0] = NO_POWERSAVE;
79df6a49 427 if (!wilc_wlan_cfg_set(vif, 0, WID_POWER_MANAGEMENT, c_val, 1, 0, 0))
5fe678b1 428 goto fail;
c5c77ba1 429
b4d04c15 430 c_val[0] = NO_SECURITY; /* NO_ENCRYPT, 0x79 */
79df6a49 431 if (!wilc_wlan_cfg_set(vif, 0, WID_11I_MODE, c_val, 1, 0, 0))
5fe678b1 432 goto fail;
c5c77ba1
JK
433
434 c_val[0] = OPEN_SYSTEM;
79df6a49 435 if (!wilc_wlan_cfg_set(vif, 0, WID_AUTH_TYPE, c_val, 1, 0, 0))
5fe678b1 436 goto fail;
c5c77ba1 437
c5c77ba1 438 strcpy(c_val, "123456790abcdef1234567890");
79df6a49 439 if (!wilc_wlan_cfg_set(vif, 0, WID_WEP_KEY_VALUE, c_val,
89758e13 440 (strlen(c_val) + 1), 0, 0))
5fe678b1 441 goto fail;
c5c77ba1 442
c5c77ba1 443 strcpy(c_val, "12345678");
79df6a49 444 if (!wilc_wlan_cfg_set(vif, 0, WID_11I_PSK, c_val, (strlen(c_val)), 0,
89758e13 445 0))
5fe678b1 446 goto fail;
c5c77ba1 447
c5c77ba1 448 strcpy(c_val, "password");
79df6a49 449 if (!wilc_wlan_cfg_set(vif, 0, WID_1X_KEY, c_val, (strlen(c_val) + 1),
89758e13 450 0, 0))
5fe678b1 451 goto fail;
c5c77ba1 452
c5c77ba1
JK
453 c_val[0] = 192;
454 c_val[1] = 168;
455 c_val[2] = 1;
456 c_val[3] = 112;
79df6a49 457 if (!wilc_wlan_cfg_set(vif, 0, WID_1X_SERV_ADDR, c_val, 4, 0, 0))
5fe678b1 458 goto fail;
c5c77ba1
JK
459
460 c_val[0] = 3;
79df6a49 461 if (!wilc_wlan_cfg_set(vif, 0, WID_LISTEN_INTERVAL, c_val, 1, 0, 0))
5fe678b1 462 goto fail;
c5c77ba1
JK
463
464 c_val[0] = 3;
79df6a49 465 if (!wilc_wlan_cfg_set(vif, 0, WID_DTIM_PERIOD, c_val, 1, 0, 0))
5fe678b1 466 goto fail;
c5c77ba1
JK
467
468 c_val[0] = NORMAL_ACK;
79df6a49 469 if (!wilc_wlan_cfg_set(vif, 0, WID_ACK_POLICY, c_val, 1, 0, 0))
5fe678b1 470 goto fail;
c5c77ba1
JK
471
472 c_val[0] = 0;
79df6a49 473 if (!wilc_wlan_cfg_set(vif, 0, WID_USER_CONTROL_ON_TX_POWER, c_val, 1,
89758e13 474 0, 0))
5fe678b1 475 goto fail;
c5c77ba1
JK
476
477 c_val[0] = 48;
79df6a49 478 if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11A, c_val, 1, 0,
89758e13 479 0))
5fe678b1 480 goto fail;
c5c77ba1
JK
481
482 c_val[0] = 28;
79df6a49 483 if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11B, c_val, 1, 0,
89758e13 484 0))
5fe678b1 485 goto fail;
c5c77ba1 486
c5c77ba1 487 *((int *)c_val) = 100;
79df6a49 488 if (!wilc_wlan_cfg_set(vif, 0, WID_BEACON_INTERVAL, c_val, 2, 0, 0))
5fe678b1 489 goto fail;
c5c77ba1
JK
490
491 c_val[0] = REKEY_DISABLE;
79df6a49 492 if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_POLICY, c_val, 1, 0, 0))
5fe678b1 493 goto fail;
c5c77ba1 494
c5c77ba1 495 *((int *)c_val) = 84600;
79df6a49 496 if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PERIOD, c_val, 4, 0, 0))
5fe678b1 497 goto fail;
c5c77ba1 498
c5c77ba1 499 *((int *)c_val) = 500;
79df6a49 500 if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PACKET_COUNT, c_val, 4, 0,
89758e13 501 0))
5fe678b1 502 goto fail;
c5c77ba1
JK
503
504 c_val[0] = 1;
79df6a49 505 if (!wilc_wlan_cfg_set(vif, 0, WID_SHORT_SLOT_ALLOWED, c_val, 1, 0,
89758e13 506 0))
5fe678b1 507 goto fail;
c5c77ba1
JK
508
509 c_val[0] = G_SELF_CTS_PROT;
79df6a49 510 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ERP_PROT_TYPE, c_val, 1, 0, 0))
5fe678b1 511 goto fail;
c5c77ba1 512
98b89847 513 c_val[0] = 1;
79df6a49 514 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ENABLE, c_val, 1, 0, 0))
5fe678b1 515 goto fail;
c5c77ba1
JK
516
517 c_val[0] = HT_MIXED_MODE;
79df6a49 518 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OPERATING_MODE, c_val, 1, 0,
89758e13 519 0))
5fe678b1 520 goto fail;
c5c77ba1 521
98b89847 522 c_val[0] = 1;
79df6a49 523 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_TXOP_PROT_DISABLE, c_val, 1, 0,
89758e13 524 0))
5fe678b1 525 goto fail;
c5c77ba1 526
c5c77ba1 527 c_val[0] = DETECT_PROTECT_REPORT;
79df6a49 528 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OBSS_NONHT_DETECTION, c_val, 1,
89758e13 529 0, 0))
5fe678b1 530 goto fail;
c5c77ba1
JK
531
532 c_val[0] = RTS_CTS_NONHT_PROT;
79df6a49 533 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_HT_PROT_TYPE, c_val, 1, 0, 0))
5fe678b1 534 goto fail;
c5c77ba1
JK
535
536 c_val[0] = 0;
79df6a49 537 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_RIFS_PROT_ENABLE, c_val, 1, 0,
89758e13 538 0))
5fe678b1 539 goto fail;
c5c77ba1
JK
540
541 c_val[0] = MIMO_MODE;
79df6a49 542 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_SMPS_MODE, c_val, 1, 0, 0))
5fe678b1 543 goto fail;
c5c77ba1
JK
544
545 c_val[0] = 7;
79df6a49 546 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_CURRENT_TX_MCS, c_val, 1, 0,
89758e13 547 0))
5fe678b1 548 goto fail;
c5c77ba1 549
98b89847 550 c_val[0] = 1;
79df6a49 551 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_IMMEDIATE_BA_ENABLED, c_val, 1,
89758e13 552 1, 1))
5fe678b1 553 goto fail;
c5c77ba1
JK
554
555 return 0;
556
5fe678b1 557fail:
c5c77ba1
JK
558 return -1;
559}
560
fec2dbfe
AS
561static int wlan_deinit_locks(struct net_device *dev)
562{
563 struct wilc_vif *vif;
564 struct wilc *wilc;
565
566 vif = netdev_priv(dev);
567 wilc = vif->wilc;
568
569 mutex_destroy(&wilc->hif_cs);
570 mutex_destroy(&wilc->rxq_cs);
571 mutex_destroy(&wilc->txq_add_to_head_cs);
572
573 return 0;
574}
575
576static void wlan_deinitialize_threads(struct net_device *dev)
577{
578 struct wilc_vif *vif;
579 struct wilc *wl;
580
581 vif = netdev_priv(dev);
582 wl = vif->wilc;
583
584 wl->close = 1;
585
586 complete(&wl->txq_event);
587
588 if (wl->txq_thread) {
589 kthread_stop(wl->txq_thread);
590 wl->txq_thread = NULL;
591 }
592}
593
ead6cb05 594static void wilc_wlan_deinitialize(struct net_device *dev)
c5c77ba1 595{
a4cac481 596 struct wilc_vif *vif;
53dc0cfe 597 struct wilc *wl;
c5c77ba1 598
a4cac481
GL
599 vif = netdev_priv(dev);
600 wl = vif->wilc;
53dc0cfe
GL
601
602 if (!wl) {
603 netdev_err(dev, "wl is NULL\n");
604 return;
605 }
606
607 if (wl->initialized) {
608 netdev_info(dev, "Deinitializing wilc1000...\n");
c5c77ba1 609
5547c1f0 610 if (!wl->dev_irq_num &&
af9ae09a 611 wl->hif_func->disable_interrupt) {
c4d139cb 612 mutex_lock(&wl->hif_cs);
af9ae09a 613 wl->hif_func->disable_interrupt(wl);
c4d139cb
AB
614 mutex_unlock(&wl->hif_cs);
615 }
1646ff6c 616 complete(&wl->txq_event);
c5c77ba1 617
32dd51bc 618 wlan_deinitialize_threads(dev);
ec5cc750 619 deinit_irq(dev);
c5c77ba1 620
562ed3f1 621 wilc_wlan_stop(wl);
2de7cbec 622 wilc_wlan_cleanup(dev);
7c67c053 623 wlan_deinit_locks(dev);
c5c77ba1 624
53dc0cfe 625 wl->initialized = false;
c5c77ba1 626
5ac24427 627 netdev_dbg(dev, "wilc1000 deinitialization Done\n");
c5c77ba1 628 } else {
5ac24427 629 netdev_dbg(dev, "wilc1000 is not initialized\n");
c5c77ba1 630 }
c5c77ba1
JK
631}
632
1608c403 633static int wlan_init_locks(struct net_device *dev)
c5c77ba1 634{
a4cac481 635 struct wilc_vif *vif;
38afb390
GL
636 struct wilc *wl;
637
a4cac481
GL
638 vif = netdev_priv(dev);
639 wl = vif->wilc;
c5c77ba1 640
38afb390
GL
641 mutex_init(&wl->hif_cs);
642 mutex_init(&wl->rxq_cs);
c5c77ba1 643
38afb390 644 spin_lock_init(&wl->txq_spinlock);
334bed08 645 mutex_init(&wl->txq_add_to_head_cs);
c5c77ba1 646
b27a6d5e 647 init_completion(&wl->txq_event);
c5c77ba1 648
fa659698 649 init_completion(&wl->cfg_event);
04247e7d 650 init_completion(&wl->sync_event);
11a54b3f 651 init_completion(&wl->txq_thread_started);
c5c77ba1 652
c5c77ba1
JK
653 return 0;
654}
655
1608c403 656static int wlan_initialize_threads(struct net_device *dev)
c5c77ba1 657{
a4cac481 658 struct wilc_vif *vif;
75a94665 659 struct wilc *wilc;
8dfaafd6 660
a4cac481
GL
661 vif = netdev_priv(dev);
662 wilc = vif->wilc;
75a94665 663
88687584 664 wilc->txq_thread = kthread_run(linux_wlan_txq_task, (void *)dev,
387fbf00 665 "K_TXQ_TASK");
b3e6916d 666 if (IS_ERR(wilc->txq_thread)) {
5ac24427 667 netdev_err(dev, "couldn't create TXQ thread\n");
6bc72c5a 668 wilc->close = 0;
b3e6916d 669 return PTR_ERR(wilc->txq_thread);
c5c77ba1 670 }
11a54b3f 671 wait_for_completion(&wilc->txq_thread_started);
c5c77ba1
JK
672
673 return 0;
c5c77ba1
JK
674}
675
ead6cb05 676static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
c5c77ba1 677{
c5c77ba1 678 int ret = 0;
a4cac481 679 struct wilc *wl = vif->wilc;
c5c77ba1 680
0fa683b6 681 if (!wl->initialized) {
52b1d208 682 wl->mac_status = MAC_STATUS_INIT;
0fa683b6 683 wl->close = 0;
c5c77ba1 684
38afb390 685 wlan_init_locks(dev);
c5c77ba1 686
4bd7baf0 687 ret = wilc_wlan_init(dev);
c5c77ba1 688 if (ret < 0) {
c5c77ba1 689 ret = -EIO;
8eb658f1 690 goto fail_locks;
c5c77ba1 691 }
c5c77ba1 692
c4d139cb 693 if (wl->gpio >= 0 && init_irq(dev)) {
c5c77ba1 694 ret = -EIO;
8eb658f1 695 goto fail_locks;
c5c77ba1 696 }
c5c77ba1 697
75a94665 698 ret = wlan_initialize_threads(dev);
b46d6882 699 if (ret < 0) {
b46d6882 700 ret = -EIO;
8eb658f1 701 goto fail_wilc_wlan;
b46d6882
TC
702 }
703
5547c1f0 704 if (!wl->dev_irq_num &&
af9ae09a
GL
705 wl->hif_func->enable_interrupt &&
706 wl->hif_func->enable_interrupt(wl)) {
c5c77ba1 707 ret = -EIO;
8eb658f1 708 goto fail_irq_init;
c5c77ba1 709 }
c5c77ba1 710
0e1af73d 711 if (wilc_wlan_get_firmware(dev)) {
c5c77ba1 712 ret = -EIO;
8eb658f1 713 goto fail_irq_enable;
c5c77ba1
JK
714 }
715
562ed3f1 716 ret = wilc1000_firmware_download(dev);
c5c77ba1 717 if (ret < 0) {
c5c77ba1 718 ret = -EIO;
8eb658f1 719 goto fail_irq_enable;
c5c77ba1
JK
720 }
721
9bf3d727 722 ret = linux_wlan_start_firmware(dev);
c5c77ba1 723 if (ret < 0) {
c5c77ba1 724 ret = -EIO;
8eb658f1 725 goto fail_irq_enable;
c5c77ba1
JK
726 }
727
79df6a49 728 if (wilc_wlan_cfg_get(vif, 1, WID_FIRMWARE_VERSION, 1, 0)) {
c5c77ba1 729 int size;
5ac24427 730 char firmware_ver[20];
8dfaafd6 731
5ac24427
LK
732 size = wilc_wlan_cfg_get_val(WID_FIRMWARE_VERSION,
733 firmware_ver,
734 sizeof(firmware_ver));
735 firmware_ver[size] = '\0';
736 netdev_dbg(dev, "Firmware Ver = %s\n", firmware_ver);
c5c77ba1 737 }
b8f6ca0b 738 ret = linux_wlan_init_test_config(dev, vif);
c5c77ba1
JK
739
740 if (ret < 0) {
5ac24427 741 netdev_err(dev, "Failed to configure firmware\n");
c5c77ba1 742 ret = -EIO;
8eb658f1 743 goto fail_fw_start;
c5c77ba1
JK
744 }
745
0fa683b6 746 wl->initialized = true;
98b89847 747 return 0;
c5c77ba1 748
8eb658f1 749fail_fw_start:
562ed3f1 750 wilc_wlan_stop(wl);
c5c77ba1 751
8eb658f1 752fail_irq_enable:
5547c1f0 753 if (!wl->dev_irq_num &&
af9ae09a
GL
754 wl->hif_func->disable_interrupt)
755 wl->hif_func->disable_interrupt(wl);
8eb658f1 756fail_irq_init:
c4d139cb
AB
757 if (wl->dev_irq_num)
758 deinit_irq(dev);
c5c77ba1 759
32dd51bc 760 wlan_deinitialize_threads(dev);
8eb658f1 761fail_wilc_wlan:
2de7cbec 762 wilc_wlan_cleanup(dev);
8eb658f1 763fail_locks:
7c67c053 764 wlan_deinit_locks(dev);
073cbb6c 765 netdev_err(dev, "WLAN initialization FAILED\n");
c5c77ba1 766 } else {
5ac24427 767 netdev_dbg(dev, "wilc1000 already initialized\n");
c5c77ba1
JK
768 }
769 return ret;
770}
771
1608c403 772static int mac_init_fn(struct net_device *ndev)
c5c77ba1 773{
98b89847
LK
774 netif_start_queue(ndev);
775 netif_stop_queue(ndev);
c5c77ba1
JK
776
777 return 0;
778}
c5c77ba1 779
68a30a63 780static int wilc_mac_open(struct net_device *ndev)
c5c77ba1 781{
a4cac481 782 struct wilc_vif *vif;
c5c77ba1 783 unsigned char mac_add[ETH_ALEN] = {0};
c5c77ba1
JK
784 int ret = 0;
785 int i = 0;
f3c1366e
GL
786 struct wilc *wl;
787
a4cac481
GL
788 vif = netdev_priv(ndev);
789 wl = vif->wilc;
c5c77ba1 790
40095ad9 791 if (!wl || !wl->dev) {
90fd4cc5 792 netdev_err(ndev, "device not ready\n");
7d05652c
CG
793 return -ENODEV;
794 }
b03314e2 795
5ac24427 796 netdev_dbg(ndev, "MAC OPEN[%p]\n", ndev);
c5c77ba1 797
dd4b6a83 798 ret = wilc_init_host_int(ndev);
1408603c 799 if (ret < 0)
c5c77ba1 800 return ret;
c5c77ba1 801
81a7dc3d 802 ret = wilc_wlan_initialize(ndev, vif);
c5c77ba1 803 if (ret < 0) {
a9a16823 804 wilc_deinit_host_int(ndev);
c5c77ba1
JK
805 return ret;
806 }
807
f3c1366e 808 for (i = 0; i < wl->vif_num; i++) {
1f435d2e 809 if (ndev == wl->vif[i]->ndev) {
46949b48
AS
810 wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
811 vif->iftype, vif->ifc_id);
e32737e9 812 wilc_set_operation_mode(vif, vif->iftype);
c5c77ba1
JK
813 break;
814 }
815 }
816
76c01fdd
HE
817 wilc_get_mac_address(vif, mac_add);
818 netdev_dbg(ndev, "Mac address: %pM\n", mac_add);
819 memcpy(wl->vif[i]->src_addr, mac_add, ETH_ALEN);
1f435d2e 820 memcpy(ndev->dev_addr, wl->vif[i]->src_addr, ETH_ALEN);
c5c77ba1
JK
821
822 if (!is_valid_ether_addr(ndev->dev_addr)) {
5ac24427 823 netdev_err(ndev, "Wrong MAC address\n");
339d244a 824 wilc_deinit_host_int(ndev);
81a7dc3d 825 wilc_wlan_deinitialize(ndev);
339d244a 826 return -EINVAL;
c5c77ba1
JK
827 }
828
1006b5c7
GL
829 wilc_mgmt_frame_register(vif->ndev->ieee80211_ptr->wiphy,
830 vif->ndev->ieee80211_ptr,
340a84ff 831 vif->frame_reg[0].type,
89febb21 832 vif->frame_reg[0].reg);
1006b5c7
GL
833 wilc_mgmt_frame_register(vif->ndev->ieee80211_ptr->wiphy,
834 vif->ndev->ieee80211_ptr,
340a84ff 835 vif->frame_reg[1].type,
89febb21 836 vif->frame_reg[1].reg);
c5c77ba1 837 netif_wake_queue(ndev);
f3c1366e 838 wl->open_ifcs++;
a4cac481 839 vif->mac_opened = 1;
c5c77ba1 840 return 0;
c5c77ba1 841}
c5c77ba1 842
1608c403 843static struct net_device_stats *mac_stats(struct net_device *dev)
c5c77ba1 844{
40095ad9 845 struct wilc_vif *vif = netdev_priv(dev);
c5c77ba1 846
a4cac481 847 return &vif->netstats;
c5c77ba1
JK
848}
849
c5c77ba1
JK
850static void wilc_set_multicast_list(struct net_device *dev)
851{
c5c77ba1 852 struct netdev_hw_addr *ha;
cf60106b 853 struct wilc_vif *vif;
c5c77ba1 854 int i = 0;
8dfaafd6 855
cf60106b 856 vif = netdev_priv(dev);
c5c77ba1 857
1408603c 858 if (dev->flags & IFF_PROMISC)
c5c77ba1 859 return;
c5c77ba1 860
7bf0242a
AS
861 if (dev->flags & IFF_ALLMULTI ||
862 dev->mc.count > WILC_MULTICAST_TABLE_SIZE) {
fbf5379b 863 wilc_setup_multicast_filter(vif, false, 0);
c5c77ba1
JK
864 return;
865 }
866
7bf0242a 867 if (dev->mc.count == 0) {
fbf5379b 868 wilc_setup_multicast_filter(vif, true, 0);
c5c77ba1
JK
869 return;
870 }
871
c8537e6d 872 netdev_for_each_mc_addr(ha, dev) {
0e1af73d 873 memcpy(wilc_multicast_mac_addr_list[i], ha->addr, ETH_ALEN);
5ac24427
LK
874 netdev_dbg(dev, "Entry[%d]: %x:%x:%x:%x:%x:%x\n", i,
875 wilc_multicast_mac_addr_list[i][0],
876 wilc_multicast_mac_addr_list[i][1],
877 wilc_multicast_mac_addr_list[i][2],
878 wilc_multicast_mac_addr_list[i][3],
879 wilc_multicast_mac_addr_list[i][4],
880 wilc_multicast_mac_addr_list[i][5]);
c5c77ba1
JK
881 i++;
882 }
883
fbf5379b 884 wilc_setup_multicast_filter(vif, true, (dev->mc.count));
c5c77ba1
JK
885}
886
c5c77ba1
JK
887static void linux_wlan_tx_complete(void *priv, int status)
888{
d5c89442 889 struct tx_complete_data *pv_data = priv;
8dfaafd6 890
c5c77ba1 891 dev_kfree_skb(pv_data->skb);
a18dd630 892 kfree(pv_data);
c5c77ba1
JK
893}
894
ad891807 895netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev)
c5c77ba1 896{
a4cac481 897 struct wilc_vif *vif;
c5c77ba1 898 struct tx_complete_data *tx_data = NULL;
44ec3b75 899 int queue_count;
fd8f0367 900 char *udp_buf;
c5c77ba1
JK
901 struct iphdr *ih;
902 struct ethhdr *eth_h;
b7495be5 903 struct wilc *wilc;
8dfaafd6 904
a4cac481
GL
905 vif = netdev_priv(ndev);
906 wilc = vif->wilc;
c5c77ba1 907
c5c77ba1 908 if (skb->dev != ndev) {
5ac24427 909 netdev_err(ndev, "Packet not destined to this device\n");
c5c77ba1
JK
910 return 0;
911 }
912
b38e9030 913 tx_data = kmalloc(sizeof(*tx_data), GFP_ATOMIC);
3a147c07 914 if (!tx_data) {
c5c77ba1
JK
915 dev_kfree_skb(skb);
916 netif_wake_queue(ndev);
917 return 0;
918 }
919
920 tx_data->buff = skb->data;
921 tx_data->size = skb->len;
922 tx_data->skb = skb;
923
924 eth_h = (struct ethhdr *)(skb->data);
94500d56 925 if (eth_h->h_proto == cpu_to_be16(0x8e88))
5ac24427 926 netdev_dbg(ndev, "EAPOL transmitted\n");
c5c77ba1 927
c5c77ba1
JK
928 ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr));
929
fd8f0367
LK
930 udp_buf = (char *)ih + sizeof(struct iphdr);
931 if ((udp_buf[1] == 68 && udp_buf[3] == 67) ||
932 (udp_buf[1] == 67 && udp_buf[3] == 68))
5ac24427
LK
933 netdev_dbg(ndev, "DHCP Message transmitted, type:%x %x %x\n",
934 udp_buf[248], udp_buf[249], udp_buf[250]);
c5c77ba1 935
a4cac481
GL
936 vif->netstats.tx_packets++;
937 vif->netstats.tx_bytes += tx_data->size;
6750140d 938 tx_data->bssid = wilc->vif[vif->idx]->bssid;
44ec3b75
LK
939 queue_count = wilc_wlan_txq_add_net_pkt(ndev, (void *)tx_data,
940 tx_data->buff, tx_data->size,
941 linux_wlan_tx_complete);
c5c77ba1 942
44ec3b75 943 if (queue_count > FLOW_CONTROL_UPPER_THRESHOLD) {
1f435d2e
GL
944 netif_stop_queue(wilc->vif[0]->ndev);
945 netif_stop_queue(wilc->vif[1]->ndev);
c5c77ba1
JK
946 }
947
948 return 0;
949}
950
68a30a63 951static int wilc_mac_close(struct net_device *ndev)
c5c77ba1 952{
2726887c 953 struct wilc_priv *priv;
a4cac481 954 struct wilc_vif *vif;
2db2c8a7 955 struct host_if_drv *hif_drv;
ca64ad6e 956 struct wilc *wl;
c5c77ba1 957
a4cac481 958 vif = netdev_priv(ndev);
c5c77ba1 959
1006b5c7 960 if (!vif || !vif->ndev || !vif->ndev->ieee80211_ptr ||
1408603c 961 !vif->ndev->ieee80211_ptr->wiphy)
c5c77ba1 962 return 0;
c5c77ba1 963
1006b5c7 964 priv = wiphy_priv(vif->ndev->ieee80211_ptr->wiphy);
a4cac481 965 wl = vif->wilc;
c5c77ba1 966
1408603c 967 if (!priv)
c5c77ba1 968 return 0;
c5c77ba1 969
48b28df9 970 hif_drv = (struct host_if_drv *)priv->hif_drv;
c5c77ba1 971
5ac24427 972 netdev_dbg(ndev, "Mac close\n");
c5c77ba1 973
1408603c 974 if (!wl)
c5c77ba1 975 return 0;
c5c77ba1 976
1408603c 977 if (!hif_drv)
c5c77ba1 978 return 0;
c5c77ba1 979
7bf0242a 980 if (wl->open_ifcs > 0)
ca64ad6e 981 wl->open_ifcs--;
1408603c 982 else
c5c77ba1 983 return 0;
c5c77ba1 984
1006b5c7
GL
985 if (vif->ndev) {
986 netif_stop_queue(vif->ndev);
c5c77ba1 987
1006b5c7 988 wilc_deinit_host_int(vif->ndev);
c5c77ba1
JK
989 }
990
ca64ad6e 991 if (wl->open_ifcs == 0) {
5ac24427 992 netdev_dbg(ndev, "Deinitializing wilc1000\n");
ca64ad6e 993 wl->close = 1;
81a7dc3d 994 wilc_wlan_deinitialize(ndev);
30324405 995 wilc_wfi_deinit_mon_interface();
c5c77ba1
JK
996 }
997
a4cac481 998 vif->mac_opened = 0;
c5c77ba1
JK
999
1000 return 0;
1001}
1002
562ed3f1 1003void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset)
c5c77ba1 1004{
c5c77ba1
JK
1005 unsigned int frame_len = 0;
1006 int stats;
1007 unsigned char *buff_to_send = NULL;
1008 struct sk_buff *skb;
c5c77ba1 1009 struct net_device *wilc_netdev;
a4cac481 1010 struct wilc_vif *vif;
c5c77ba1 1011
0953a2e3
LK
1012 if (!wilc)
1013 return;
1014
7e725b47 1015 wilc_netdev = get_if_handler(wilc, buff);
3a147c07 1016 if (!wilc_netdev)
c5c77ba1
JK
1017 return;
1018
1019 buff += pkt_offset;
a4cac481 1020 vif = netdev_priv(wilc_netdev);
c5c77ba1
JK
1021
1022 if (size > 0) {
c5c77ba1
JK
1023 frame_len = size;
1024 buff_to_send = buff;
1025
c5c77ba1 1026 skb = dev_alloc_skb(frame_len);
1408603c 1027 if (!skb)
c5c77ba1 1028 return;
1408603c 1029
c5c77ba1
JK
1030 skb->dev = wilc_netdev;
1031
59ae1d12 1032 skb_put_data(skb, buff_to_send, frame_len);
c5c77ba1 1033
c5c77ba1 1034 skb->protocol = eth_type_trans(skb, wilc_netdev);
a4cac481
GL
1035 vif->netstats.rx_packets++;
1036 vif->netstats.rx_bytes += frame_len;
c5c77ba1
JK
1037 skb->ip_summed = CHECKSUM_UNNECESSARY;
1038 stats = netif_rx(skb);
5ac24427 1039 netdev_dbg(wilc_netdev, "netif_rx ret value is: %d\n", stats);
c5c77ba1 1040 }
c5c77ba1
JK
1041}
1042
44b4709c 1043void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size)
c5c77ba1
JK
1044{
1045 int i = 0;
a4cac481 1046 struct wilc_vif *vif;
c5c77ba1 1047
11f4b2ee 1048 for (i = 0; i < wilc->vif_num; i++) {
1f435d2e 1049 vif = netdev_priv(wilc->vif[i]->ndev);
a4cac481 1050 if (vif->monitor_flag) {
436d918a 1051 wilc_wfi_monitor_rx(buff, size);
c5c77ba1
JK
1052 return;
1053 }
1054 }
1055
1f435d2e 1056 vif = netdev_priv(wilc->vif[1]->ndev);
340a84ff
LK
1057 if ((buff[0] == vif->frame_reg[0].type && vif->frame_reg[0].reg) ||
1058 (buff[0] == vif->frame_reg[1].type && vif->frame_reg[1].reg))
34db1aac 1059 wilc_wfi_p2p_rx(wilc->vif[1]->ndev, buff, size);
c5c77ba1
JK
1060}
1061
fec2dbfe
AS
1062static struct notifier_block g_dev_notifier = {
1063 .notifier_call = dev_state_ev_handler
1064};
1065
857c7b00 1066void wilc_netdev_cleanup(struct wilc *wilc)
4875c499 1067{
735bb39c 1068 int i;
4875c499 1069
735bb39c 1070 if (wilc && (wilc->vif[0]->ndev || wilc->vif[1]->ndev))
4875c499
TC
1071 unregister_inetaddr_notifier(&g_dev_notifier);
1072
3f626cf4 1073 if (wilc && wilc->firmware) {
90b984c8 1074 release_firmware(wilc->firmware);
3f626cf4
LK
1075 wilc->firmware = NULL;
1076 }
4875c499 1077
1f435d2e 1078 if (wilc && (wilc->vif[0]->ndev || wilc->vif[1]->ndev)) {
4875c499 1079 for (i = 0; i < NUM_CONCURRENT_IFC; i++)
1f435d2e 1080 if (wilc->vif[i]->ndev)
735bb39c 1081 if (wilc->vif[i]->mac_opened)
1f435d2e 1082 wilc_mac_close(wilc->vif[i]->ndev);
4875c499
TC
1083
1084 for (i = 0; i < NUM_CONCURRENT_IFC; i++) {
1f435d2e
GL
1085 unregister_netdev(wilc->vif[i]->ndev);
1086 wilc_free_wiphy(wilc->vif[i]->ndev);
1087 free_netdev(wilc->vif[i]->ndev);
4875c499
TC
1088 }
1089 }
1090
90b984c8 1091 kfree(wilc);
4875c499 1092}
750ffe9b 1093EXPORT_SYMBOL_GPL(wilc_netdev_cleanup);
4875c499 1094
fec2dbfe
AS
1095static const struct net_device_ops wilc_netdev_ops = {
1096 .ndo_init = mac_init_fn,
1097 .ndo_open = wilc_mac_open,
1098 .ndo_stop = wilc_mac_close,
1099 .ndo_start_xmit = wilc_mac_xmit,
1100 .ndo_get_stats = mac_stats,
1101 .ndo_set_rx_mode = wilc_set_multicast_list,
1102};
1103
7d37a4a1
AB
1104int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type,
1105 int gpio, const struct wilc_hif_func *ops)
c5c77ba1 1106{
fe747f0f 1107 int i, ret;
a4cac481 1108 struct wilc_vif *vif;
c5c77ba1 1109 struct net_device *ndev;
562ed3f1 1110 struct wilc *wl;
c5c77ba1 1111
825b966f 1112 wl = kzalloc(sizeof(*wl), GFP_KERNEL);
562ed3f1 1113 if (!wl)
ac61ef86 1114 return -ENOMEM;
c5c77ba1 1115
562ed3f1
AB
1116 *wilc = wl;
1117 wl->io_type = io_type;
1118 wl->gpio = gpio;
af9ae09a 1119 wl->hif_func = ops;
3d9241d6 1120 INIT_LIST_HEAD(&wl->txq_head.list);
6adc35d9 1121 INIT_LIST_HEAD(&wl->rxq_head.list);
c4d139cb 1122
c5c77ba1 1123 register_inetaddr_notifier(&g_dev_notifier);
c5c77ba1
JK
1124
1125 for (i = 0; i < NUM_CONCURRENT_IFC; i++) {
026e14ae
AS
1126 struct wireless_dev *wdev;
1127
a4cac481 1128 ndev = alloc_etherdev(sizeof(struct wilc_vif));
1408603c 1129 if (!ndev)
fe747f0f 1130 return -ENOMEM;
c5c77ba1 1131
a4cac481
GL
1132 vif = netdev_priv(ndev);
1133 memset(vif, 0, sizeof(struct wilc_vif));
c5c77ba1 1134
46949b48 1135 if (i == 0) {
c5c77ba1 1136 strcpy(ndev->name, "wlan%d");
46949b48
AS
1137 vif->ifc_id = 1;
1138 } else {
c5c77ba1 1139 strcpy(ndev->name, "p2p%d");
46949b48
AS
1140 vif->ifc_id = 0;
1141 }
a4cac481 1142 vif->wilc = *wilc;
735bb39c 1143 vif->ndev = ndev;
1f435d2e 1144 wl->vif[i] = vif;
735bb39c 1145 wl->vif_num = i;
0e490657
AS
1146 vif->idx = wl->vif_num;
1147
e5af0561 1148 ndev->netdev_ops = &wilc_netdev_ops;
c5c77ba1 1149
026e14ae 1150 wdev = wilc_create_wiphy(ndev, dev);
c5c77ba1 1151
026e14ae
AS
1152 if (dev)
1153 SET_NETDEV_DEV(ndev, dev);
c5c77ba1 1154
026e14ae
AS
1155 if (!wdev) {
1156 netdev_err(ndev, "Can't register WILC Wiphy\n");
1157 return -1;
c5c77ba1 1158 }
c5c77ba1 1159
026e14ae
AS
1160 vif->ndev->ieee80211_ptr = wdev;
1161 vif->ndev->ml_priv = vif;
1162 wdev->netdev = vif->ndev;
1163 vif->netstats.rx_packets = 0;
1164 vif->netstats.tx_packets = 0;
1165 vif->netstats.rx_bytes = 0;
1166 vif->netstats.tx_bytes = 0;
1167
fe747f0f
AKC
1168 ret = register_netdev(ndev);
1169 if (ret)
1170 return ret;
c5c77ba1 1171
a4cac481
GL
1172 vif->iftype = STATION_MODE;
1173 vif->mac_opened = 0;
c5c77ba1
JK
1174 }
1175
c5c77ba1
JK
1176 return 0;
1177}
750ffe9b 1178EXPORT_SYMBOL_GPL(wilc_netdev_init);
c94f05ee
AB
1179
1180MODULE_LICENSE("GPL");