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