Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
[linux-2.6-block.git] / drivers / staging / wilc1000 / wilc_netdev.c
CommitLineData
903ac63f 1// SPDX-License-Identifier: GPL-2.0
e61c7a1c
AS
2/*
3 * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
4 * All rights reserved.
5 */
6
c5c77ba1 7#include <linux/irq.h>
c5c77ba1
JK
8#include <linux/kthread.h>
9#include <linux/firmware.h>
c5c77ba1 10#include <linux/netdevice.h>
c5c77ba1 11#include <linux/inetdevice.h>
880e404e
AS
12
13#include "wilc_wfi_cfgoperations.h"
4ad36601 14#include "wilc_wlan_cfg.h"
c5c77ba1 15
6b0b7d86
AS
16#define WILC_MULTICAST_TABLE_SIZE 8
17
c5c77ba1
JK
18static irqreturn_t isr_uh_routine(int irq, void *user_data)
19{
d5c89442 20 struct net_device *dev = user_data;
6bcba96e
AS
21 struct wilc_vif *vif = netdev_priv(dev);
22 struct wilc *wilc = vif->wilc;
c5c77ba1 23
3948362d 24 if (wilc->close) {
5ac24427 25 netdev_err(dev, "Can't handle UH interrupt\n");
c5c77ba1 26 return IRQ_HANDLED;
c5c77ba1 27 }
c5c77ba1 28 return IRQ_WAKE_THREAD;
c5c77ba1 29}
c5c77ba1 30
1608c403 31static irqreturn_t isr_bh_routine(int irq, void *userdata)
c5c77ba1 32{
d5c89442 33 struct net_device *dev = userdata;
6bcba96e
AS
34 struct wilc_vif *vif = netdev_priv(userdata);
35 struct wilc *wilc = vif->wilc;
2e7933d0 36
2e7933d0 37 if (wilc->close) {
5ac24427 38 netdev_err(dev, "Can't handle BH interrupt\n");
c5c77ba1 39 return IRQ_HANDLED;
c5c77ba1
JK
40 }
41
50b929e0 42 wilc_handle_isr(wilc);
c5c77ba1 43
c5c77ba1 44 return IRQ_HANDLED;
c5c77ba1 45}
c5c77ba1 46
2c1d05d1 47static int init_irq(struct net_device *dev)
c5c77ba1
JK
48{
49 int ret = 0;
6bcba96e
AS
50 struct wilc_vif *vif = netdev_priv(dev);
51 struct wilc *wl = vif->wilc;
c5c77ba1 52
367b9559
AS
53 ret = gpiod_direction_input(wl->gpio_irq);
54 if (ret) {
5ac24427 55 netdev_err(dev, "could not obtain gpio for WILC_INTR\n");
367b9559 56 return ret;
c5c77ba1
JK
57 }
58
367b9559
AS
59 wl->dev_irq_num = gpiod_to_irq(wl->gpio_irq);
60
61 ret = request_threaded_irq(wl->dev_irq_num, isr_uh_routine,
62 isr_bh_routine,
9a4c56be 63 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
367b9559
AS
64 "WILC_IRQ", dev);
65 if (ret < 0)
66 netdev_err(dev, "Failed to request IRQ\n");
67 else
68 netdev_dbg(dev, "IRQ request succeeded IRQ-NUM= %d\n",
69 wl->dev_irq_num);
c5c77ba1
JK
70
71 return ret;
72}
c5c77ba1 73
ec5cc750 74static void deinit_irq(struct net_device *dev)
c5c77ba1 75{
6bcba96e
AS
76 struct wilc_vif *vif = netdev_priv(dev);
77 struct wilc *wilc = vif->wilc;
ec5cc750 78
1cce2000 79 /* Deinitialize IRQ */
367b9559 80 if (wilc->dev_irq_num)
ec5cc750 81 free_irq(wilc->dev_irq_num, wilc);
c5c77ba1
JK
82}
83
c7ceac21 84void wilc_mac_indicate(struct wilc *wilc)
c5c77ba1 85{
de11f709 86 s8 status;
c5c77ba1 87
acceb12a 88 wilc_wlan_cfg_get_val(wilc, WID_STATUS, &status, 1);
8c4574d6 89 if (wilc->mac_status == WILC_MAC_STATUS_INIT) {
c7ceac21
AS
90 wilc->mac_status = status;
91 complete(&wilc->sync_event);
92 } else {
93 wilc->mac_status = status;
c5c77ba1 94 }
c5c77ba1
JK
95}
96
1608c403 97static struct net_device *get_if_handler(struct wilc *wilc, u8 *mac_header)
c5c77ba1 98{
660786ea 99 u8 *bssid, *bssid1;
c5c77ba1 100 int i = 0;
9bc061e8 101 struct net_device *ndev = NULL;
c5c77ba1 102
d239222e 103 bssid = mac_header + 10;
660786ea 104 bssid1 = mac_header + 4;
c5c77ba1 105
9bc061e8 106 mutex_lock(&wilc->vif_mutex);
ba615f1e 107 for (i = 0; i < wilc->vif_num; i++) {
d0e41eff 108 if (wilc->vif[i]->mode == WILC_STATION_MODE)
fa633941 109 if (ether_addr_equal_unaligned(bssid,
9bc061e8
AS
110 wilc->vif[i]->bssid)) {
111 ndev = wilc->vif[i]->ndev;
112 goto out;
113 }
d0e41eff 114 if (wilc->vif[i]->mode == WILC_AP_MODE)
fa633941 115 if (ether_addr_equal_unaligned(bssid1,
9bc061e8
AS
116 wilc->vif[i]->bssid)) {
117 ndev = wilc->vif[i]->ndev;
118 goto out;
119 }
ba615f1e 120 }
9bc061e8
AS
121out:
122 mutex_unlock(&wilc->vif_mutex);
123 return ndev;
c5c77ba1
JK
124}
125
080de249 126void wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode)
c5c77ba1 127{
735bb39c 128 struct wilc_vif *vif = netdev_priv(wilc_netdev);
472791a9 129
4e90d5f3
AS
130 if (bssid)
131 ether_addr_copy(vif->bssid, bssid);
132 else
133 eth_zero_addr(vif->bssid);
134
735bb39c 135 vif->mode = mode;
c5c77ba1
JK
136}
137
562ed3f1 138int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc)
c5c77ba1 139{
51e825f7 140 u8 i = 0;
51e825f7 141 u8 ret_val = 0;
c5c77ba1 142
562ed3f1 143 for (i = 0; i < wilc->vif_num; i++)
4c00f705 144 if (!is_zero_ether_addr(wilc->vif[i]->bssid))
c5c77ba1 145 ret_val++;
8259a53e 146
c5c77ba1
JK
147 return ret_val;
148}
149
c6eab5e6 150static int wilc_txq_task(void *vp)
c5c77ba1 151{
8a88dd46
IS
152 int ret;
153 u32 txq_count;
9bc061e8 154 struct wilc *wl = vp;
88687584 155
11a54b3f 156 complete(&wl->txq_thread_started);
c5c77ba1 157 while (1) {
b27a6d5e 158 wait_for_completion(&wl->txq_event);
c5c77ba1 159
88687584 160 if (wl->close) {
11a54b3f 161 complete(&wl->txq_thread_started);
c5c77ba1
JK
162
163 while (!kthread_should_stop())
164 schedule();
c5c77ba1
JK
165 break;
166 }
c5c77ba1 167 do {
9bc061e8 168 ret = wilc_wlan_handle_txq(wl, &txq_count);
98b89847 169 if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD) {
9bc061e8
AS
170 int i;
171 struct wilc_vif *ifc;
172
173 mutex_lock(&wl->vif_mutex);
174 for (i = 0; i < wl->vif_num; i++) {
175 ifc = wl->vif[i];
176 if (ifc->mac_opened && ifc->ndev)
177 netif_wake_queue(ifc->ndev);
178 }
179 mutex_unlock(&wl->vif_mutex);
c5c77ba1 180 }
68b4f745 181 } while (ret == -ENOBUFS && !wl->close);
c5c77ba1
JK
182 }
183 return 0;
184}
185
ead6cb05 186static int wilc_wlan_get_firmware(struct net_device *dev)
c5c77ba1 187{
6bcba96e
AS
188 struct wilc_vif *vif = netdev_priv(dev);
189 struct wilc *wilc = vif->wilc;
14823bf2 190 int chip_id, ret = 0;
c5c77ba1
JK
191 const struct firmware *wilc_firmware;
192 char *firmware;
193
65c3f000 194 chip_id = wilc_get_chipid(wilc, false);
14823bf2
GL
195
196 if (chip_id < 0x1003a0)
197 firmware = FIRMWARE_1002;
198 else
199 firmware = FIRMWARE_1003;
200
201 netdev_info(dev, "loading firmware %s\n", firmware);
c5c77ba1 202
b03314e2 203 if (request_firmware(&wilc_firmware, firmware, wilc->dev) != 0) {
b9811891 204 netdev_err(dev, "%s - firmware not available\n", firmware);
c5c77ba1 205 ret = -1;
5fe678b1 206 goto fail;
c5c77ba1 207 }
65c8adcf 208 wilc->firmware = wilc_firmware;
c5c77ba1 209
5fe678b1 210fail:
c5c77ba1
JK
211
212 return ret;
c5c77ba1
JK
213}
214
c6eab5e6 215static int wilc_start_firmware(struct net_device *dev)
c5c77ba1 216{
6bcba96e
AS
217 struct wilc_vif *vif = netdev_priv(dev);
218 struct wilc *wilc = vif->wilc;
c5c77ba1 219 int ret = 0;
9bf3d727 220
562ed3f1 221 ret = wilc_wlan_start(wilc);
1408603c 222 if (ret < 0)
0aeea1ad 223 return ret;
c5c77ba1 224
04247e7d 225 if (!wait_for_completion_timeout(&wilc->sync_event,
36190caa 226 msecs_to_jiffies(5000)))
04247e7d 227 return -ETIME;
c5c77ba1 228
0aeea1ad 229 return 0;
c5c77ba1 230}
a40b22c5 231
562ed3f1 232static int wilc1000_firmware_download(struct net_device *dev)
c5c77ba1 233{
6bcba96e
AS
234 struct wilc_vif *vif = netdev_priv(dev);
235 struct wilc *wilc = vif->wilc;
c5c77ba1
JK
236 int ret = 0;
237
ed760b67 238 if (!wilc->firmware) {
5ac24427 239 netdev_err(dev, "Firmware buffer is NULL\n");
14b1821d 240 return -ENOBUFS;
c5c77ba1 241 }
1408603c 242
562ed3f1 243 ret = wilc_wlan_firmware_download(wilc, wilc->firmware->data,
ed760b67 244 wilc->firmware->size);
fc4b95d6 245 if (ret < 0)
14b1821d 246 return ret;
c5c77ba1 247
ed760b67 248 release_firmware(wilc->firmware);
6f72ed75 249 wilc->firmware = NULL;
c5c77ba1 250
5ac24427 251 netdev_dbg(dev, "Download Succeeded\n");
c5c77ba1 252
14b1821d 253 return 0;
c5c77ba1
JK
254}
255
c6eab5e6 256static int wilc_init_fw_config(struct net_device *dev, struct wilc_vif *vif)
c5c77ba1 257{
9bc061e8 258 struct wilc_priv *priv = &vif->priv;
0fa66c71 259 struct host_if_drv *hif_drv;
9a4b45fb
AS
260 u8 b;
261 u16 hw;
262 u32 w;
c5c77ba1 263
5ac24427 264 netdev_dbg(dev, "Start configuring Firmware\n");
48b28df9 265 hif_drv = (struct host_if_drv *)priv->hif_drv;
5ac24427 266 netdev_dbg(dev, "Host = %p\n", hif_drv);
c5c77ba1 267
9a4b45fb
AS
268 w = vif->iftype;
269 cpu_to_le32s(&w);
270 if (!wilc_wlan_cfg_set(vif, 1, WID_SET_OPERATION_MODE, (u8 *)&w, 4,
271 0, 0))
5fe678b1 272 goto fail;
c5c77ba1 273
9a4b45fb
AS
274 b = WILC_FW_BSS_TYPE_INFRA;
275 if (!wilc_wlan_cfg_set(vif, 0, WID_BSS_TYPE, &b, 1, 0, 0))
5fe678b1 276 goto fail;
c5c77ba1 277
9a4b45fb
AS
278 b = WILC_FW_TX_RATE_AUTO;
279 if (!wilc_wlan_cfg_set(vif, 0, WID_CURRENT_TX_RATE, &b, 1, 0, 0))
5fe678b1 280 goto fail;
c5c77ba1 281
9a4b45fb
AS
282 b = WILC_FW_OPER_MODE_G_MIXED_11B_2;
283 if (!wilc_wlan_cfg_set(vif, 0, WID_11G_OPERATING_MODE, &b, 1, 0, 0))
5fe678b1 284 goto fail;
c5c77ba1 285
9a4b45fb
AS
286 b = WILC_FW_PREAMBLE_SHORT;
287 if (!wilc_wlan_cfg_set(vif, 0, WID_PREAMBLE, &b, 1, 0, 0))
5fe678b1 288 goto fail;
c5c77ba1 289
9a4b45fb
AS
290 b = WILC_FW_11N_PROT_AUTO;
291 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_PROT_MECH, &b, 1, 0, 0))
5fe678b1 292 goto fail;
c5c77ba1 293
9a4b45fb
AS
294 b = WILC_FW_ACTIVE_SCAN;
295 if (!wilc_wlan_cfg_set(vif, 0, WID_SCAN_TYPE, &b, 1, 0, 0))
5fe678b1 296 goto fail;
c5c77ba1 297
9a4b45fb
AS
298 b = WILC_FW_SITE_SURVEY_OFF;
299 if (!wilc_wlan_cfg_set(vif, 0, WID_SITE_SURVEY, &b, 1, 0, 0))
5fe678b1 300 goto fail;
c5c77ba1 301
9a4b45fb
AS
302 hw = 0xffff;
303 cpu_to_le16s(&hw);
304 if (!wilc_wlan_cfg_set(vif, 0, WID_RTS_THRESHOLD, (u8 *)&hw, 2, 0, 0))
5fe678b1 305 goto fail;
c5c77ba1 306
9a4b45fb
AS
307 hw = 2346;
308 cpu_to_le16s(&hw);
309 if (!wilc_wlan_cfg_set(vif, 0, WID_FRAG_THRESHOLD, (u8 *)&hw, 2, 0, 0))
5fe678b1 310 goto fail;
c5c77ba1 311
9a4b45fb
AS
312 b = 0;
313 if (!wilc_wlan_cfg_set(vif, 0, WID_BCAST_SSID, &b, 1, 0, 0))
5fe678b1 314 goto fail;
c5c77ba1 315
9a4b45fb
AS
316 b = 1;
317 if (!wilc_wlan_cfg_set(vif, 0, WID_QOS_ENABLE, &b, 1, 0, 0))
5fe678b1 318 goto fail;
c5c77ba1 319
9a4b45fb
AS
320 b = WILC_FW_NO_POWERSAVE;
321 if (!wilc_wlan_cfg_set(vif, 0, WID_POWER_MANAGEMENT, &b, 1, 0, 0))
5fe678b1 322 goto fail;
c5c77ba1 323
9a4b45fb
AS
324 b = WILC_FW_SEC_NO;
325 if (!wilc_wlan_cfg_set(vif, 0, WID_11I_MODE, &b, 1, 0, 0))
5fe678b1 326 goto fail;
c5c77ba1 327
9a4b45fb
AS
328 b = WILC_FW_AUTH_OPEN_SYSTEM;
329 if (!wilc_wlan_cfg_set(vif, 0, WID_AUTH_TYPE, &b, 1, 0, 0))
5fe678b1 330 goto fail;
c5c77ba1 331
9a4b45fb
AS
332 b = 3;
333 if (!wilc_wlan_cfg_set(vif, 0, WID_LISTEN_INTERVAL, &b, 1, 0, 0))
5fe678b1 334 goto fail;
c5c77ba1 335
9a4b45fb
AS
336 b = 3;
337 if (!wilc_wlan_cfg_set(vif, 0, WID_DTIM_PERIOD, &b, 1, 0, 0))
5fe678b1 338 goto fail;
c5c77ba1 339
9a4b45fb
AS
340 b = WILC_FW_ACK_POLICY_NORMAL;
341 if (!wilc_wlan_cfg_set(vif, 0, WID_ACK_POLICY, &b, 1, 0, 0))
5fe678b1 342 goto fail;
c5c77ba1 343
9a4b45fb
AS
344 b = 0;
345 if (!wilc_wlan_cfg_set(vif, 0, WID_USER_CONTROL_ON_TX_POWER, &b, 1,
89758e13 346 0, 0))
5fe678b1 347 goto fail;
c5c77ba1 348
9a4b45fb
AS
349 b = 48;
350 if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11A, &b, 1, 0, 0))
5fe678b1 351 goto fail;
c5c77ba1 352
9a4b45fb
AS
353 b = 28;
354 if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11B, &b, 1, 0, 0))
5fe678b1 355 goto fail;
c5c77ba1 356
9a4b45fb
AS
357 hw = 100;
358 cpu_to_le16s(&hw);
359 if (!wilc_wlan_cfg_set(vif, 0, WID_BEACON_INTERVAL, (u8 *)&hw, 2, 0, 0))
5fe678b1 360 goto fail;
c5c77ba1 361
9a4b45fb
AS
362 b = WILC_FW_REKEY_POLICY_DISABLE;
363 if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_POLICY, &b, 1, 0, 0))
5fe678b1 364 goto fail;
c5c77ba1 365
9a4b45fb
AS
366 w = 84600;
367 cpu_to_le32s(&w);
368 if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PERIOD, (u8 *)&w, 4, 0, 0))
5fe678b1 369 goto fail;
c5c77ba1 370
9a4b45fb
AS
371 w = 500;
372 cpu_to_le32s(&w);
373 if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PACKET_COUNT, (u8 *)&w, 4, 0,
89758e13 374 0))
5fe678b1 375 goto fail;
c5c77ba1 376
9a4b45fb
AS
377 b = 1;
378 if (!wilc_wlan_cfg_set(vif, 0, WID_SHORT_SLOT_ALLOWED, &b, 1, 0,
89758e13 379 0))
5fe678b1 380 goto fail;
c5c77ba1 381
9a4b45fb
AS
382 b = WILC_FW_ERP_PROT_SELF_CTS;
383 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ERP_PROT_TYPE, &b, 1, 0, 0))
5fe678b1 384 goto fail;
c5c77ba1 385
9a4b45fb
AS
386 b = 1;
387 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ENABLE, &b, 1, 0, 0))
5fe678b1 388 goto fail;
c5c77ba1 389
9a4b45fb
AS
390 b = WILC_FW_11N_OP_MODE_HT_MIXED;
391 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OPERATING_MODE, &b, 1, 0, 0))
5fe678b1 392 goto fail;
c5c77ba1 393
9a4b45fb
AS
394 b = 1;
395 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_TXOP_PROT_DISABLE, &b, 1, 0, 0))
5fe678b1 396 goto fail;
c5c77ba1 397
9a4b45fb
AS
398 b = WILC_FW_OBBS_NONHT_DETECT_PROTECT_REPORT;
399 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OBSS_NONHT_DETECTION, &b, 1,
89758e13 400 0, 0))
5fe678b1 401 goto fail;
c5c77ba1 402
9a4b45fb
AS
403 b = WILC_FW_HT_PROT_RTS_CTS_NONHT;
404 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_HT_PROT_TYPE, &b, 1, 0, 0))
5fe678b1 405 goto fail;
c5c77ba1 406
9a4b45fb
AS
407 b = 0;
408 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_RIFS_PROT_ENABLE, &b, 1, 0,
89758e13 409 0))
5fe678b1 410 goto fail;
c5c77ba1 411
9a4b45fb
AS
412 b = 7;
413 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_CURRENT_TX_MCS, &b, 1, 0, 0))
5fe678b1 414 goto fail;
c5c77ba1 415
9a4b45fb
AS
416 b = 1;
417 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_IMMEDIATE_BA_ENABLED, &b, 1,
89758e13 418 1, 1))
5fe678b1 419 goto fail;
c5c77ba1
JK
420
421 return 0;
422
5fe678b1 423fail:
c5c77ba1
JK
424 return -1;
425}
426
d579112b 427static void wlan_deinit_locks(struct net_device *dev)
fec2dbfe 428{
6bcba96e
AS
429 struct wilc_vif *vif = netdev_priv(dev);
430 struct wilc *wilc = vif->wilc;
fec2dbfe
AS
431
432 mutex_destroy(&wilc->hif_cs);
433 mutex_destroy(&wilc->rxq_cs);
6dea3302 434 mutex_destroy(&wilc->cfg_cmd_lock);
fec2dbfe 435 mutex_destroy(&wilc->txq_add_to_head_cs);
9bc061e8 436 mutex_destroy(&wilc->vif_mutex);
fec2dbfe
AS
437}
438
439static void wlan_deinitialize_threads(struct net_device *dev)
440{
6bcba96e
AS
441 struct wilc_vif *vif = netdev_priv(dev);
442 struct wilc *wl = vif->wilc;
fec2dbfe
AS
443
444 wl->close = 1;
445
446 complete(&wl->txq_event);
447
448 if (wl->txq_thread) {
449 kthread_stop(wl->txq_thread);
450 wl->txq_thread = NULL;
451 }
452}
453
ead6cb05 454static void wilc_wlan_deinitialize(struct net_device *dev)
c5c77ba1 455{
6bcba96e
AS
456 struct wilc_vif *vif = netdev_priv(dev);
457 struct wilc *wl = vif->wilc;
53dc0cfe
GL
458
459 if (!wl) {
460 netdev_err(dev, "wl is NULL\n");
461 return;
462 }
463
74cffafb 464 if (wl->initialized) {
53dc0cfe 465 netdev_info(dev, "Deinitializing wilc1000...\n");
c5c77ba1 466
5547c1f0 467 if (!wl->dev_irq_num &&
af9ae09a 468 wl->hif_func->disable_interrupt) {
c4d139cb 469 mutex_lock(&wl->hif_cs);
af9ae09a 470 wl->hif_func->disable_interrupt(wl);
c4d139cb
AB
471 mutex_unlock(&wl->hif_cs);
472 }
1646ff6c 473 complete(&wl->txq_event);
c5c77ba1 474
32dd51bc 475 wlan_deinitialize_threads(dev);
ec5cc750 476 deinit_irq(dev);
c5c77ba1 477
0d1b57c1 478 wilc_wlan_stop(wl, vif);
2de7cbec 479 wilc_wlan_cleanup(dev);
7c67c053 480 wlan_deinit_locks(dev);
c5c77ba1 481
53dc0cfe 482 wl->initialized = false;
c5c77ba1 483
5ac24427 484 netdev_dbg(dev, "wilc1000 deinitialization Done\n");
c5c77ba1 485 } else {
5ac24427 486 netdev_dbg(dev, "wilc1000 is not initialized\n");
c5c77ba1 487 }
c5c77ba1
JK
488}
489
1608c403 490static int wlan_initialize_threads(struct net_device *dev)
c5c77ba1 491{
6bcba96e
AS
492 struct wilc_vif *vif = netdev_priv(dev);
493 struct wilc *wilc = vif->wilc;
75a94665 494
9bc061e8 495 wilc->txq_thread = kthread_run(wilc_txq_task, (void *)wilc,
387fbf00 496 "K_TXQ_TASK");
b3e6916d 497 if (IS_ERR(wilc->txq_thread)) {
5ac24427 498 netdev_err(dev, "couldn't create TXQ thread\n");
6bc72c5a 499 wilc->close = 0;
b3e6916d 500 return PTR_ERR(wilc->txq_thread);
c5c77ba1 501 }
11a54b3f 502 wait_for_completion(&wilc->txq_thread_started);
c5c77ba1
JK
503
504 return 0;
c5c77ba1
JK
505}
506
ead6cb05 507static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
c5c77ba1 508{
c5c77ba1 509 int ret = 0;
a4cac481 510 struct wilc *wl = vif->wilc;
c5c77ba1 511
0fa683b6 512 if (!wl->initialized) {
8c4574d6 513 wl->mac_status = WILC_MAC_STATUS_INIT;
0fa683b6 514 wl->close = 0;
c5c77ba1 515
4bd7baf0 516 ret = wilc_wlan_init(dev);
9bc061e8
AS
517 if (ret < 0)
518 return -EIO;
c5c77ba1 519
75a94665 520 ret = wlan_initialize_threads(dev);
b46d6882 521 if (ret < 0) {
b46d6882 522 ret = -EIO;
8eb658f1 523 goto fail_wilc_wlan;
b46d6882
TC
524 }
525
6419f818
AS
526 if (wl->gpio_irq && init_irq(dev)) {
527 ret = -EIO;
528 goto fail_threads;
529 }
530
5547c1f0 531 if (!wl->dev_irq_num &&
af9ae09a
GL
532 wl->hif_func->enable_interrupt &&
533 wl->hif_func->enable_interrupt(wl)) {
c5c77ba1 534 ret = -EIO;
8eb658f1 535 goto fail_irq_init;
c5c77ba1 536 }
c5c77ba1 537
0e1af73d 538 if (wilc_wlan_get_firmware(dev)) {
c5c77ba1 539 ret = -EIO;
8eb658f1 540 goto fail_irq_enable;
c5c77ba1
JK
541 }
542
562ed3f1 543 ret = wilc1000_firmware_download(dev);
c5c77ba1 544 if (ret < 0) {
c5c77ba1 545 ret = -EIO;
8eb658f1 546 goto fail_irq_enable;
c5c77ba1
JK
547 }
548
c6eab5e6 549 ret = wilc_start_firmware(dev);
c5c77ba1 550 if (ret < 0) {
c5c77ba1 551 ret = -EIO;
8eb658f1 552 goto fail_irq_enable;
c5c77ba1
JK
553 }
554
79df6a49 555 if (wilc_wlan_cfg_get(vif, 1, WID_FIRMWARE_VERSION, 1, 0)) {
c5c77ba1 556 int size;
5ac24427 557 char firmware_ver[20];
8dfaafd6 558
acceb12a 559 size = wilc_wlan_cfg_get_val(wl, WID_FIRMWARE_VERSION,
5ac24427
LK
560 firmware_ver,
561 sizeof(firmware_ver));
562 firmware_ver[size] = '\0';
563 netdev_dbg(dev, "Firmware Ver = %s\n", firmware_ver);
c5c77ba1 564 }
c6eab5e6 565 ret = wilc_init_fw_config(dev, vif);
c5c77ba1
JK
566
567 if (ret < 0) {
5ac24427 568 netdev_err(dev, "Failed to configure firmware\n");
c5c77ba1 569 ret = -EIO;
8eb658f1 570 goto fail_fw_start;
c5c77ba1 571 }
0fa683b6 572 wl->initialized = true;
98b89847 573 return 0;
c5c77ba1 574
8eb658f1 575fail_fw_start:
0d1b57c1 576 wilc_wlan_stop(wl, vif);
c5c77ba1 577
8eb658f1 578fail_irq_enable:
5547c1f0 579 if (!wl->dev_irq_num &&
af9ae09a
GL
580 wl->hif_func->disable_interrupt)
581 wl->hif_func->disable_interrupt(wl);
8eb658f1 582fail_irq_init:
c4d139cb
AB
583 if (wl->dev_irq_num)
584 deinit_irq(dev);
6419f818 585fail_threads:
32dd51bc 586 wlan_deinitialize_threads(dev);
8eb658f1 587fail_wilc_wlan:
2de7cbec 588 wilc_wlan_cleanup(dev);
073cbb6c 589 netdev_err(dev, "WLAN initialization FAILED\n");
c5c77ba1 590 } else {
5ac24427 591 netdev_dbg(dev, "wilc1000 already initialized\n");
c5c77ba1
JK
592 }
593 return ret;
594}
595
1608c403 596static int mac_init_fn(struct net_device *ndev)
c5c77ba1 597{
98b89847
LK
598 netif_start_queue(ndev);
599 netif_stop_queue(ndev);
c5c77ba1
JK
600
601 return 0;
602}
c5c77ba1 603
68a30a63 604static int wilc_mac_open(struct net_device *ndev)
c5c77ba1 605{
6bcba96e
AS
606 struct wilc_vif *vif = netdev_priv(ndev);
607 struct wilc *wl = vif->wilc;
f41cf246 608 struct wilc_priv *priv = wdev_priv(vif->ndev->ieee80211_ptr);
c5c77ba1 609 unsigned char mac_add[ETH_ALEN] = {0};
c5c77ba1 610 int ret = 0;
c5c77ba1 611
40095ad9 612 if (!wl || !wl->dev) {
90fd4cc5 613 netdev_err(ndev, "device not ready\n");
7d05652c
CG
614 return -ENODEV;
615 }
b03314e2 616
5ac24427 617 netdev_dbg(ndev, "MAC OPEN[%p]\n", ndev);
c5c77ba1 618
dd4b6a83 619 ret = wilc_init_host_int(ndev);
1408603c 620 if (ret < 0)
c5c77ba1 621 return ret;
c5c77ba1 622
81a7dc3d 623 ret = wilc_wlan_initialize(ndev, vif);
c5c77ba1 624 if (ret < 0) {
a9a16823 625 wilc_deinit_host_int(ndev);
c5c77ba1
JK
626 return ret;
627 }
628
4b1b8b08
AA
629 wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), vif->iftype,
630 vif->idx);
76c01fdd
HE
631 wilc_get_mac_address(vif, mac_add);
632 netdev_dbg(ndev, "Mac address: %pM\n", mac_add);
39cf54fc 633 ether_addr_copy(ndev->dev_addr, mac_add);
c5c77ba1
JK
634
635 if (!is_valid_ether_addr(ndev->dev_addr)) {
5ac24427 636 netdev_err(ndev, "Wrong MAC address\n");
339d244a 637 wilc_deinit_host_int(ndev);
81a7dc3d 638 wilc_wlan_deinitialize(ndev);
339d244a 639 return -EINVAL;
c5c77ba1
JK
640 }
641
1006b5c7
GL
642 wilc_mgmt_frame_register(vif->ndev->ieee80211_ptr->wiphy,
643 vif->ndev->ieee80211_ptr,
340a84ff 644 vif->frame_reg[0].type,
89febb21 645 vif->frame_reg[0].reg);
1006b5c7
GL
646 wilc_mgmt_frame_register(vif->ndev->ieee80211_ptr->wiphy,
647 vif->ndev->ieee80211_ptr,
340a84ff 648 vif->frame_reg[1].type,
89febb21 649 vif->frame_reg[1].reg);
c5c77ba1 650 netif_wake_queue(ndev);
f3c1366e 651 wl->open_ifcs++;
f41cf246 652 priv->p2p.local_random = 0x01;
a4cac481 653 vif->mac_opened = 1;
c5c77ba1 654 return 0;
c5c77ba1 655}
c5c77ba1 656
1608c403 657static struct net_device_stats *mac_stats(struct net_device *dev)
c5c77ba1 658{
40095ad9 659 struct wilc_vif *vif = netdev_priv(dev);
c5c77ba1 660
a4cac481 661 return &vif->netstats;
c5c77ba1
JK
662}
663
c5c77ba1
JK
664static void wilc_set_multicast_list(struct net_device *dev)
665{
c5c77ba1 666 struct netdev_hw_addr *ha;
6bcba96e 667 struct wilc_vif *vif = netdev_priv(dev);
ba853fe6 668 int i;
e624c58c 669 u8 *mc_list;
ba853fe6 670 u8 *cur_mc;
8dfaafd6 671
1408603c 672 if (dev->flags & IFF_PROMISC)
c5c77ba1 673 return;
c5c77ba1 674
7bf0242a
AS
675 if (dev->flags & IFF_ALLMULTI ||
676 dev->mc.count > WILC_MULTICAST_TABLE_SIZE) {
a0c6a32e 677 wilc_setup_multicast_filter(vif, 0, 0, NULL);
c5c77ba1
JK
678 return;
679 }
680
7bf0242a 681 if (dev->mc.count == 0) {
a0c6a32e 682 wilc_setup_multicast_filter(vif, 1, 0, NULL);
c5c77ba1
JK
683 return;
684 }
685
ae26aa84 686 mc_list = kmalloc_array(dev->mc.count, ETH_ALEN, GFP_ATOMIC);
e624c58c
AS
687 if (!mc_list)
688 return;
689
ba853fe6
AS
690 cur_mc = mc_list;
691 i = 0;
c8537e6d 692 netdev_for_each_mc_addr(ha, dev) {
ba853fe6
AS
693 memcpy(cur_mc, ha->addr, ETH_ALEN);
694 netdev_dbg(dev, "Entry[%d]: %pM\n", i, cur_mc);
695 i++;
696 cur_mc += ETH_ALEN;
c5c77ba1
JK
697 }
698
a0c6a32e 699 if (wilc_setup_multicast_filter(vif, 1, dev->mc.count, mc_list))
e624c58c 700 kfree(mc_list);
c5c77ba1
JK
701}
702
c6eab5e6 703static void wilc_tx_complete(void *priv, int status)
c5c77ba1 704{
d5c89442 705 struct tx_complete_data *pv_data = priv;
8dfaafd6 706
c5c77ba1 707 dev_kfree_skb(pv_data->skb);
a18dd630 708 kfree(pv_data);
c5c77ba1
JK
709}
710
ad891807 711netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev)
c5c77ba1 712{
6bcba96e
AS
713 struct wilc_vif *vif = netdev_priv(ndev);
714 struct wilc *wilc = vif->wilc;
c5c77ba1 715 struct tx_complete_data *tx_data = NULL;
44ec3b75 716 int queue_count;
c5c77ba1 717
c5c77ba1 718 if (skb->dev != ndev) {
5ac24427 719 netdev_err(ndev, "Packet not destined to this device\n");
c5c77ba1
JK
720 return 0;
721 }
722
b38e9030 723 tx_data = kmalloc(sizeof(*tx_data), GFP_ATOMIC);
3a147c07 724 if (!tx_data) {
c5c77ba1
JK
725 dev_kfree_skb(skb);
726 netif_wake_queue(ndev);
727 return 0;
728 }
729
730 tx_data->buff = skb->data;
731 tx_data->size = skb->len;
732 tx_data->skb = skb;
733
a4cac481
GL
734 vif->netstats.tx_packets++;
735 vif->netstats.tx_bytes += tx_data->size;
44ec3b75
LK
736 queue_count = wilc_wlan_txq_add_net_pkt(ndev, (void *)tx_data,
737 tx_data->buff, tx_data->size,
c6eab5e6 738 wilc_tx_complete);
c5c77ba1 739
44ec3b75 740 if (queue_count > FLOW_CONTROL_UPPER_THRESHOLD) {
9bc061e8
AS
741 int i;
742
743 mutex_lock(&wilc->vif_mutex);
744 for (i = 0; i < wilc->vif_num; i++) {
745 if (wilc->vif[i]->mac_opened)
746 netif_stop_queue(wilc->vif[i]->ndev);
747 }
748 mutex_unlock(&wilc->vif_mutex);
c5c77ba1
JK
749 }
750
751 return 0;
752}
753
68a30a63 754static int wilc_mac_close(struct net_device *ndev)
c5c77ba1 755{
6bcba96e 756 struct wilc_vif *vif = netdev_priv(ndev);
440592df 757 struct wilc *wl = vif->wilc;
c5c77ba1 758
5ac24427 759 netdev_dbg(ndev, "Mac close\n");
c5c77ba1 760
7bf0242a 761 if (wl->open_ifcs > 0)
ca64ad6e 762 wl->open_ifcs--;
1408603c 763 else
c5c77ba1 764 return 0;
c5c77ba1 765
1006b5c7
GL
766 if (vif->ndev) {
767 netif_stop_queue(vif->ndev);
c5c77ba1 768
1006b5c7 769 wilc_deinit_host_int(vif->ndev);
c5c77ba1
JK
770 }
771
ca64ad6e 772 if (wl->open_ifcs == 0) {
5ac24427 773 netdev_dbg(ndev, "Deinitializing wilc1000\n");
ca64ad6e 774 wl->close = 1;
81a7dc3d 775 wilc_wlan_deinitialize(ndev);
c5c77ba1
JK
776 }
777
a4cac481 778 vif->mac_opened = 0;
c5c77ba1
JK
779
780 return 0;
781}
782
55e311d8
AS
783void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size,
784 u32 pkt_offset)
c5c77ba1 785{
c5c77ba1
JK
786 unsigned int frame_len = 0;
787 int stats;
788 unsigned char *buff_to_send = NULL;
789 struct sk_buff *skb;
c5c77ba1 790 struct net_device *wilc_netdev;
a4cac481 791 struct wilc_vif *vif;
c5c77ba1 792
0953a2e3
LK
793 if (!wilc)
794 return;
795
7e725b47 796 wilc_netdev = get_if_handler(wilc, buff);
3a147c07 797 if (!wilc_netdev)
c5c77ba1
JK
798 return;
799
800 buff += pkt_offset;
a4cac481 801 vif = netdev_priv(wilc_netdev);
c5c77ba1
JK
802
803 if (size > 0) {
c5c77ba1
JK
804 frame_len = size;
805 buff_to_send = buff;
806
c5c77ba1 807 skb = dev_alloc_skb(frame_len);
1408603c 808 if (!skb)
c5c77ba1 809 return;
1408603c 810
c5c77ba1
JK
811 skb->dev = wilc_netdev;
812
59ae1d12 813 skb_put_data(skb, buff_to_send, frame_len);
c5c77ba1 814
c5c77ba1 815 skb->protocol = eth_type_trans(skb, wilc_netdev);
a4cac481
GL
816 vif->netstats.rx_packets++;
817 vif->netstats.rx_bytes += frame_len;
c5c77ba1
JK
818 skb->ip_summed = CHECKSUM_UNNECESSARY;
819 stats = netif_rx(skb);
5ac24427 820 netdev_dbg(wilc_netdev, "netif_rx ret value is: %d\n", stats);
c5c77ba1 821 }
c5c77ba1
JK
822}
823
44b4709c 824void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size)
c5c77ba1
JK
825{
826 int i = 0;
a4cac481 827 struct wilc_vif *vif;
c5c77ba1 828
9bc061e8 829 mutex_lock(&wilc->vif_mutex);
11f4b2ee 830 for (i = 0; i < wilc->vif_num; i++) {
9bc061e8
AS
831 u16 type = le16_to_cpup((__le16 *)buff);
832
1f435d2e 833 vif = netdev_priv(wilc->vif[i]->ndev);
9bc061e8
AS
834 if ((type == vif->frame_reg[0].type && vif->frame_reg[0].reg) ||
835 (type == vif->frame_reg[1].type && vif->frame_reg[1].reg)) {
836 wilc_wfi_p2p_rx(vif, buff, size);
837 break;
838 }
839
a4cac481 840 if (vif->monitor_flag) {
58871300 841 wilc_wfi_monitor_rx(wilc->monitor_dev, buff, size);
9bc061e8 842 break;
c5c77ba1
JK
843 }
844 }
9bc061e8 845 mutex_unlock(&wilc->vif_mutex);
c5c77ba1
JK
846}
847
f2bf97cb
AS
848static const struct net_device_ops wilc_netdev_ops = {
849 .ndo_init = mac_init_fn,
850 .ndo_open = wilc_mac_open,
851 .ndo_stop = wilc_mac_close,
852 .ndo_start_xmit = wilc_mac_xmit,
853 .ndo_get_stats = mac_stats,
854 .ndo_set_rx_mode = wilc_set_multicast_list,
855};
856
857c7b00 857void wilc_netdev_cleanup(struct wilc *wilc)
4875c499 858{
735bb39c 859 int i;
4875c499 860
b4a01d8f
CIK
861 if (!wilc)
862 return;
863
b4a01d8f 864 if (wilc->firmware) {
90b984c8 865 release_firmware(wilc->firmware);
3f626cf4
LK
866 wilc->firmware = NULL;
867 }
4875c499 868
9bc061e8
AS
869 for (i = 0; i < wilc->vif_num; i++) {
870 if (wilc->vif[i] && wilc->vif[i]->ndev)
1f435d2e 871 unregister_netdev(wilc->vif[i]->ndev);
4875c499
TC
872 }
873
9bc061e8 874 wilc_wfi_deinit_mon_interface(wilc, false);
b3ee105c
AS
875 flush_workqueue(wilc->hif_workqueue);
876 destroy_workqueue(wilc->hif_workqueue);
acceb12a 877 wilc_wlan_cfg_deinit(wilc);
97eaff57 878 kfree(wilc->bus_data);
9bc061e8
AS
879 wiphy_unregister(wilc->wiphy);
880 wiphy_free(wilc->wiphy);
4875c499 881}
f45b8934 882EXPORT_SYMBOL_GPL(wilc_netdev_cleanup);
4875c499 883
9bc061e8
AS
884struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name,
885 int vif_type, enum nl80211_iftype type,
886 bool rtnl_locked)
c5c77ba1 887{
c5c77ba1 888 struct net_device *ndev;
9bc061e8
AS
889 struct wilc_vif *vif;
890 int ret;
026e14ae 891
9bc061e8
AS
892 ndev = alloc_etherdev(sizeof(*vif));
893 if (!ndev)
894 return ERR_PTR(-ENOMEM);
c5c77ba1 895
9bc061e8
AS
896 vif = netdev_priv(ndev);
897 ndev->ieee80211_ptr = &vif->priv.wdev;
898 strcpy(ndev->name, name);
899 vif->wilc = wl;
900 vif->ndev = ndev;
901 ndev->ml_priv = vif;
c5c77ba1 902
9bc061e8 903 ndev->netdev_ops = &wilc_netdev_ops;
c5c77ba1 904
9bc061e8 905 SET_NETDEV_DEV(ndev, wiphy_dev(wl->wiphy));
a53b0b13 906
9bc061e8
AS
907 vif->priv.wdev.wiphy = wl->wiphy;
908 vif->priv.wdev.netdev = ndev;
909 vif->priv.wdev.iftype = type;
910 vif->priv.dev = ndev;
026e14ae 911
9bc061e8
AS
912 if (rtnl_locked)
913 ret = register_netdevice(ndev);
914 else
fe747f0f 915 ret = register_netdev(ndev);
c5c77ba1 916
9bc061e8
AS
917 if (ret) {
918 free_netdev(ndev);
919 return ERR_PTR(-EFAULT);
c5c77ba1
JK
920 }
921
9bc061e8
AS
922 ndev->needs_free_netdev = true;
923 vif->iftype = vif_type;
924 vif->wilc->vif[wl->vif_num] = vif;
9bc061e8
AS
925 vif->idx = wl->vif_num;
926 wl->vif_num += 1;
927 vif->mac_opened = 0;
928 return vif;
c5c77ba1 929}
f45b8934
AB
930
931MODULE_LICENSE("GPL");