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