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