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