1017 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.4 * All rights reserved.5 */6 7#include <linux/irq.h>8#include <linux/kthread.h>9#include <linux/firmware.h>10#include <linux/netdevice.h>11#include <linux/inetdevice.h>12 13#include "cfg80211.h"14#include "wlan_cfg.h"15 16#define WILC_MULTICAST_TABLE_SIZE 817#define WILC_MAX_FW_VERSION_STR_SIZE 5018 19/* latest API version supported */20#define WILC1000_API_VER 121 22#define WILC1000_FW_PREFIX "atmel/wilc1000_wifi_firmware-"23#define __WILC1000_FW(api) WILC1000_FW_PREFIX #api ".bin"24#define WILC1000_FW(api) __WILC1000_FW(api)25 26static irqreturn_t isr_uh_routine(int irq, void *user_data)27{28 struct wilc *wilc = user_data;29 30 if (wilc->close) {31 pr_err("Can't handle UH interrupt\n");32 return IRQ_HANDLED;33 }34 return IRQ_WAKE_THREAD;35}36 37static irqreturn_t isr_bh_routine(int irq, void *userdata)38{39 struct wilc *wilc = userdata;40 41 if (wilc->close) {42 pr_err("Can't handle BH interrupt\n");43 return IRQ_HANDLED;44 }45 46 wilc_handle_isr(wilc);47 48 return IRQ_HANDLED;49}50 51static int init_irq(struct net_device *dev)52{53 struct wilc_vif *vif = netdev_priv(dev);54 struct wilc *wl = vif->wilc;55 int ret;56 57 ret = request_threaded_irq(wl->dev_irq_num, isr_uh_routine,58 isr_bh_routine,59 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,60 dev->name, wl);61 if (ret) {62 netdev_err(dev, "Failed to request IRQ [%d]\n", ret);63 return ret;64 }65 netdev_dbg(dev, "IRQ request succeeded IRQ-NUM= %d\n", wl->dev_irq_num);66 67 return 0;68}69 70static void deinit_irq(struct net_device *dev)71{72 struct wilc_vif *vif = netdev_priv(dev);73 struct wilc *wilc = vif->wilc;74 75 /* Deinitialize IRQ */76 if (wilc->dev_irq_num)77 free_irq(wilc->dev_irq_num, wilc);78}79 80void wilc_mac_indicate(struct wilc *wilc)81{82 s8 status;83 84 wilc_wlan_cfg_get_val(wilc, WID_STATUS, &status, 1);85 if (wilc->mac_status == WILC_MAC_STATUS_INIT) {86 wilc->mac_status = status;87 complete(&wilc->sync_event);88 } else {89 wilc->mac_status = status;90 }91}92 93static struct net_device *get_if_handler(struct wilc *wilc, u8 *mac_header)94{95 struct net_device *ndev = NULL;96 struct wilc_vif *vif;97 struct ieee80211_hdr *h = (struct ieee80211_hdr *)mac_header;98 99 wilc_for_each_vif(wilc, vif) {100 if (vif->iftype == WILC_STATION_MODE)101 if (ether_addr_equal_unaligned(h->addr2, vif->bssid)) {102 ndev = vif->ndev;103 goto out;104 }105 if (vif->iftype == WILC_AP_MODE)106 if (ether_addr_equal_unaligned(h->addr1, vif->bssid)) {107 ndev = vif->ndev;108 goto out;109 }110 }111out:112 return ndev;113}114 115void wilc_wlan_set_bssid(struct net_device *wilc_netdev, const u8 *bssid,116 u8 mode)117{118 struct wilc_vif *vif = netdev_priv(wilc_netdev);119 120 if (bssid)121 ether_addr_copy(vif->bssid, bssid);122 else123 eth_zero_addr(vif->bssid);124 125 vif->iftype = mode;126}127 128int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc)129{130 int srcu_idx;131 u8 ret_val = 0;132 struct wilc_vif *vif;133 134 srcu_idx = srcu_read_lock(&wilc->srcu);135 wilc_for_each_vif(wilc, vif) {136 if (!is_zero_ether_addr(vif->bssid))137 ret_val++;138 }139 srcu_read_unlock(&wilc->srcu, srcu_idx);140 return ret_val;141}142 143static void wilc_wake_tx_queues(struct wilc *wl)144{145 int srcu_idx;146 struct wilc_vif *ifc;147 148 srcu_idx = srcu_read_lock(&wl->srcu);149 wilc_for_each_vif(wl, ifc) {150 if (ifc->mac_opened && netif_queue_stopped(ifc->ndev))151 netif_wake_queue(ifc->ndev);152 }153 srcu_read_unlock(&wl->srcu, srcu_idx);154}155 156static int wilc_txq_task(void *vp)157{158 int ret;159 u32 txq_count;160 struct wilc *wl = vp;161 162 complete(&wl->txq_thread_started);163 while (1) {164 if (wait_for_completion_interruptible(&wl->txq_event))165 continue;166 if (wl->close) {167 complete(&wl->txq_thread_started);168 169 while (!kthread_should_stop())170 schedule();171 break;172 }173 do {174 ret = wilc_wlan_handle_txq(wl, &txq_count);175 if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD) {176 wilc_wake_tx_queues(wl);177 }178 if (ret != WILC_VMM_ENTRY_FULL_RETRY)179 break;180 /* Back off TX task from sending packets for some time.181 * msleep_interruptible will allow RX task to run and182 * free buffers. TX task will be in TASK_INTERRUPTIBLE183 * state which will put the thread back to CPU running184 * queue when it's signaled even if the timeout isn't185 * elapsed. This gives faster chance for reserved SK186 * buffers to be free.187 */188 msleep_interruptible(TX_BACKOFF_WEIGHT_MS);189 } while (!wl->close);190 }191 return 0;192}193 194static int wilc_wlan_get_firmware(struct net_device *dev)195{196 struct wilc_vif *vif = netdev_priv(dev);197 struct wilc *wilc = vif->wilc;198 int chip_id;199 const struct firmware *wilc_fw;200 int ret;201 202 chip_id = wilc_get_chipid(wilc, false);203 204 netdev_info(dev, "ChipID [%x] loading firmware [%s]\n", chip_id,205 WILC1000_FW(WILC1000_API_VER));206 207 ret = request_firmware(&wilc_fw, WILC1000_FW(WILC1000_API_VER),208 wilc->dev);209 if (ret != 0) {210 netdev_err(dev, "%s - firmware not available\n",211 WILC1000_FW(WILC1000_API_VER));212 return -EINVAL;213 }214 wilc->firmware = wilc_fw;215 216 return 0;217}218 219static int wilc_start_firmware(struct net_device *dev)220{221 struct wilc_vif *vif = netdev_priv(dev);222 struct wilc *wilc = vif->wilc;223 int ret = 0;224 225 ret = wilc_wlan_start(wilc);226 if (ret)227 return ret;228 229 if (!wait_for_completion_timeout(&wilc->sync_event,230 msecs_to_jiffies(5000)))231 return -ETIME;232 233 return 0;234}235 236static int wilc1000_firmware_download(struct net_device *dev)237{238 struct wilc_vif *vif = netdev_priv(dev);239 struct wilc *wilc = vif->wilc;240 int ret = 0;241 242 if (!wilc->firmware) {243 netdev_err(dev, "Firmware buffer is NULL\n");244 return -ENOBUFS;245 }246 247 ret = wilc_wlan_firmware_download(wilc, wilc->firmware->data,248 wilc->firmware->size);249 if (ret)250 return ret;251 252 release_firmware(wilc->firmware);253 wilc->firmware = NULL;254 255 netdev_dbg(dev, "Download Succeeded\n");256 257 return 0;258}259 260static int wilc_init_fw_config(struct net_device *dev, struct wilc_vif *vif)261{262 struct wilc_priv *priv = &vif->priv;263 struct host_if_drv *hif_drv;264 u8 b;265 u16 hw;266 u32 w;267 268 netdev_dbg(dev, "Start configuring Firmware\n");269 hif_drv = (struct host_if_drv *)priv->hif_drv;270 netdev_dbg(dev, "Host = %p\n", hif_drv);271 272 w = vif->iftype;273 cpu_to_le32s(&w);274 if (!wilc_wlan_cfg_set(vif, 1, WID_SET_OPERATION_MODE, (u8 *)&w, 4,275 0, 0))276 goto fail;277 278 b = WILC_FW_BSS_TYPE_INFRA;279 if (!wilc_wlan_cfg_set(vif, 0, WID_BSS_TYPE, &b, 1, 0, 0))280 goto fail;281 282 b = WILC_FW_TX_RATE_AUTO;283 if (!wilc_wlan_cfg_set(vif, 0, WID_CURRENT_TX_RATE, &b, 1, 0, 0))284 goto fail;285 286 b = WILC_FW_OPER_MODE_G_MIXED_11B_2;287 if (!wilc_wlan_cfg_set(vif, 0, WID_11G_OPERATING_MODE, &b, 1, 0, 0))288 goto fail;289 290 b = WILC_FW_PREAMBLE_AUTO;291 if (!wilc_wlan_cfg_set(vif, 0, WID_PREAMBLE, &b, 1, 0, 0))292 goto fail;293 294 b = WILC_FW_11N_PROT_AUTO;295 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_PROT_MECH, &b, 1, 0, 0))296 goto fail;297 298 b = WILC_FW_ACTIVE_SCAN;299 if (!wilc_wlan_cfg_set(vif, 0, WID_SCAN_TYPE, &b, 1, 0, 0))300 goto fail;301 302 b = WILC_FW_SITE_SURVEY_OFF;303 if (!wilc_wlan_cfg_set(vif, 0, WID_SITE_SURVEY, &b, 1, 0, 0))304 goto fail;305 306 hw = 0xffff;307 cpu_to_le16s(&hw);308 if (!wilc_wlan_cfg_set(vif, 0, WID_RTS_THRESHOLD, (u8 *)&hw, 2, 0, 0))309 goto fail;310 311 hw = 2346;312 cpu_to_le16s(&hw);313 if (!wilc_wlan_cfg_set(vif, 0, WID_FRAG_THRESHOLD, (u8 *)&hw, 2, 0, 0))314 goto fail;315 316 b = 0;317 if (!wilc_wlan_cfg_set(vif, 0, WID_BCAST_SSID, &b, 1, 0, 0))318 goto fail;319 320 b = 1;321 if (!wilc_wlan_cfg_set(vif, 0, WID_QOS_ENABLE, &b, 1, 0, 0))322 goto fail;323 324 b = WILC_FW_NO_POWERSAVE;325 if (!wilc_wlan_cfg_set(vif, 0, WID_POWER_MANAGEMENT, &b, 1, 0, 0))326 goto fail;327 328 b = WILC_FW_SEC_NO;329 if (!wilc_wlan_cfg_set(vif, 0, WID_11I_MODE, &b, 1, 0, 0))330 goto fail;331 332 b = WILC_FW_AUTH_OPEN_SYSTEM;333 if (!wilc_wlan_cfg_set(vif, 0, WID_AUTH_TYPE, &b, 1, 0, 0))334 goto fail;335 336 b = 3;337 if (!wilc_wlan_cfg_set(vif, 0, WID_LISTEN_INTERVAL, &b, 1, 0, 0))338 goto fail;339 340 b = 3;341 if (!wilc_wlan_cfg_set(vif, 0, WID_DTIM_PERIOD, &b, 1, 0, 0))342 goto fail;343 344 b = WILC_FW_ACK_POLICY_NORMAL;345 if (!wilc_wlan_cfg_set(vif, 0, WID_ACK_POLICY, &b, 1, 0, 0))346 goto fail;347 348 b = 0;349 if (!wilc_wlan_cfg_set(vif, 0, WID_USER_CONTROL_ON_TX_POWER, &b, 1,350 0, 0))351 goto fail;352 353 b = 48;354 if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11A, &b, 1, 0, 0))355 goto fail;356 357 b = 28;358 if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11B, &b, 1, 0, 0))359 goto fail;360 361 hw = 100;362 cpu_to_le16s(&hw);363 if (!wilc_wlan_cfg_set(vif, 0, WID_BEACON_INTERVAL, (u8 *)&hw, 2, 0, 0))364 goto fail;365 366 b = WILC_FW_REKEY_POLICY_DISABLE;367 if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_POLICY, &b, 1, 0, 0))368 goto fail;369 370 w = 84600;371 cpu_to_le32s(&w);372 if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PERIOD, (u8 *)&w, 4, 0, 0))373 goto fail;374 375 w = 500;376 cpu_to_le32s(&w);377 if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PACKET_COUNT, (u8 *)&w, 4, 0,378 0))379 goto fail;380 381 b = 1;382 if (!wilc_wlan_cfg_set(vif, 0, WID_SHORT_SLOT_ALLOWED, &b, 1, 0,383 0))384 goto fail;385 386 b = WILC_FW_ERP_PROT_SELF_CTS;387 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ERP_PROT_TYPE, &b, 1, 0, 0))388 goto fail;389 390 b = 1;391 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ENABLE, &b, 1, 0, 0))392 goto fail;393 394 b = WILC_FW_11N_OP_MODE_HT_MIXED;395 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OPERATING_MODE, &b, 1, 0, 0))396 goto fail;397 398 b = 1;399 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_TXOP_PROT_DISABLE, &b, 1, 0, 0))400 goto fail;401 402 b = WILC_FW_OBBS_NONHT_DETECT_PROTECT_REPORT;403 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OBSS_NONHT_DETECTION, &b, 1,404 0, 0))405 goto fail;406 407 b = WILC_FW_HT_PROT_RTS_CTS_NONHT;408 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_HT_PROT_TYPE, &b, 1, 0, 0))409 goto fail;410 411 b = 0;412 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_RIFS_PROT_ENABLE, &b, 1, 0,413 0))414 goto fail;415 416 b = 7;417 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_CURRENT_TX_MCS, &b, 1, 0, 0))418 goto fail;419 420 b = 1;421 if (!wilc_wlan_cfg_set(vif, 0, WID_11N_IMMEDIATE_BA_ENABLED, &b, 1,422 1, 0))423 goto fail;424 425 return 0;426 427fail:428 return -EINVAL;429}430 431static void wlan_deinitialize_threads(struct net_device *dev)432{433 struct wilc_vif *vif = netdev_priv(dev);434 struct wilc *wl = vif->wilc;435 436 wl->close = 1;437 438 complete(&wl->txq_event);439 440 if (wl->txq_thread) {441 kthread_stop(wl->txq_thread);442 wl->txq_thread = NULL;443 }444}445 446static void wilc_wlan_deinitialize(struct net_device *dev)447{448 struct wilc_vif *vif = netdev_priv(dev);449 struct wilc *wl = vif->wilc;450 451 if (!wl) {452 netdev_err(dev, "wl is NULL\n");453 return;454 }455 456 if (wl->initialized) {457 netdev_info(dev, "Deinitializing wilc1000...\n");458 459 if (!wl->dev_irq_num &&460 wl->hif_func->disable_interrupt) {461 mutex_lock(&wl->hif_cs);462 wl->hif_func->disable_interrupt(wl);463 mutex_unlock(&wl->hif_cs);464 }465 complete(&wl->txq_event);466 467 wlan_deinitialize_threads(dev);468 deinit_irq(dev);469 470 wilc_wlan_stop(wl, vif);471 wilc_wlan_cleanup(dev);472 473 wl->initialized = false;474 475 netdev_dbg(dev, "wilc1000 deinitialization Done\n");476 } else {477 netdev_dbg(dev, "wilc1000 is not initialized\n");478 }479}480 481static int wlan_initialize_threads(struct net_device *dev)482{483 struct wilc_vif *vif = netdev_priv(dev);484 struct wilc *wilc = vif->wilc;485 486 wilc->txq_thread = kthread_run(wilc_txq_task, (void *)wilc,487 "%s-tx", dev->name);488 if (IS_ERR(wilc->txq_thread)) {489 netdev_err(dev, "couldn't create TXQ thread\n");490 wilc->close = 1;491 return PTR_ERR(wilc->txq_thread);492 }493 wait_for_completion(&wilc->txq_thread_started);494 495 return 0;496}497 498static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)499{500 int ret = 0;501 struct wilc *wl = vif->wilc;502 503 if (!wl->initialized) {504 wl->mac_status = WILC_MAC_STATUS_INIT;505 wl->close = 0;506 507 ret = wilc_wlan_init(dev);508 if (ret)509 return ret;510 511 ret = wlan_initialize_threads(dev);512 if (ret)513 goto fail_wilc_wlan;514 515 if (wl->dev_irq_num && init_irq(dev)) {516 ret = -EIO;517 goto fail_threads;518 }519 520 if (!wl->dev_irq_num &&521 wl->hif_func->enable_interrupt &&522 wl->hif_func->enable_interrupt(wl)) {523 ret = -EIO;524 goto fail_irq_init;525 }526 527 ret = wilc_wlan_get_firmware(dev);528 if (ret)529 goto fail_irq_enable;530 531 ret = wilc1000_firmware_download(dev);532 if (ret)533 goto fail_irq_enable;534 535 ret = wilc_start_firmware(dev);536 if (ret)537 goto fail_irq_enable;538 539 if (wilc_wlan_cfg_get(vif, 1, WID_FIRMWARE_VERSION, 1, 0)) {540 int size;541 char firmware_ver[WILC_MAX_FW_VERSION_STR_SIZE];542 543 size = wilc_wlan_cfg_get_val(wl, WID_FIRMWARE_VERSION,544 firmware_ver,545 sizeof(firmware_ver));546 firmware_ver[size] = '\0';547 netdev_dbg(dev, "Firmware Ver = %s\n", firmware_ver);548 }549 550 ret = wilc_init_fw_config(dev, vif);551 if (ret) {552 netdev_err(dev, "Failed to configure firmware\n");553 goto fail_fw_start;554 }555 wl->initialized = true;556 return 0;557 558fail_fw_start:559 wilc_wlan_stop(wl, vif);560 561fail_irq_enable:562 if (!wl->dev_irq_num &&563 wl->hif_func->disable_interrupt)564 wl->hif_func->disable_interrupt(wl);565fail_irq_init:566 if (wl->dev_irq_num)567 deinit_irq(dev);568fail_threads:569 wlan_deinitialize_threads(dev);570fail_wilc_wlan:571 wilc_wlan_cleanup(dev);572 netdev_err(dev, "WLAN initialization FAILED\n");573 } else {574 netdev_dbg(dev, "wilc1000 already initialized\n");575 }576 return ret;577}578 579static int mac_init_fn(struct net_device *ndev)580{581 netif_start_queue(ndev);582 netif_stop_queue(ndev);583 584 return 0;585}586 587static int wilc_mac_open(struct net_device *ndev)588{589 struct wilc_vif *vif = netdev_priv(ndev);590 struct wilc *wl = vif->wilc;591 int ret = 0;592 struct mgmt_frame_regs mgmt_regs = {};593 594 if (!wl || !wl->dev) {595 netdev_err(ndev, "device not ready\n");596 return -ENODEV;597 }598 599 netdev_dbg(ndev, "MAC OPEN[%p]\n", ndev);600 601 ret = wilc_init_host_int(ndev);602 if (ret)603 return ret;604 605 ret = wilc_wlan_initialize(ndev, vif);606 if (ret) {607 wilc_deinit_host_int(ndev);608 return ret;609 }610 611 netdev_dbg(ndev, "Mac address: %pM\n", ndev->dev_addr);612 ret = wilc_set_mac_address(vif, ndev->dev_addr);613 if (ret) {614 netdev_err(ndev, "Failed to enforce MAC address in chip");615 wilc_deinit_host_int(ndev);616 if (!wl->open_ifcs)617 wilc_wlan_deinitialize(ndev);618 return ret;619 }620 621 wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), vif->iftype,622 vif->idx);623 624 mgmt_regs.interface_stypes = vif->mgmt_reg_stypes;625 /* so we detect a change */626 vif->mgmt_reg_stypes = 0;627 wilc_update_mgmt_frame_registrations(vif->ndev->ieee80211_ptr->wiphy,628 vif->ndev->ieee80211_ptr,629 &mgmt_regs);630 netif_wake_queue(ndev);631 wl->open_ifcs++;632 vif->mac_opened = 1;633 return 0;634}635 636static struct net_device_stats *mac_stats(struct net_device *dev)637{638 struct wilc_vif *vif = netdev_priv(dev);639 640 return &vif->netstats;641}642 643static int wilc_set_mac_addr(struct net_device *dev, void *p)644{645 int result;646 struct wilc_vif *vif = netdev_priv(dev);647 struct wilc *wilc = vif->wilc;648 struct sockaddr *addr = (struct sockaddr *)p;649 unsigned char mac_addr[ETH_ALEN];650 struct wilc_vif *tmp_vif;651 int srcu_idx;652 653 if (!is_valid_ether_addr(addr->sa_data))654 return -EADDRNOTAVAIL;655 656 if (!vif->mac_opened) {657 eth_commit_mac_addr_change(dev, p);658 return 0;659 }660 661 /* Verify MAC Address is not already in use: */662 663 srcu_idx = srcu_read_lock(&wilc->srcu);664 wilc_for_each_vif(wilc, tmp_vif) {665 wilc_get_mac_address(tmp_vif, mac_addr);666 if (ether_addr_equal(addr->sa_data, mac_addr)) {667 if (vif != tmp_vif) {668 srcu_read_unlock(&wilc->srcu, srcu_idx);669 return -EADDRNOTAVAIL;670 }671 srcu_read_unlock(&wilc->srcu, srcu_idx);672 return 0;673 }674 }675 srcu_read_unlock(&wilc->srcu, srcu_idx);676 677 result = wilc_set_mac_address(vif, addr->sa_data);678 if (result)679 return result;680 681 eth_commit_mac_addr_change(dev, p);682 return result;683}684 685static void wilc_set_multicast_list(struct net_device *dev)686{687 struct netdev_hw_addr *ha;688 struct wilc_vif *vif = netdev_priv(dev);689 int i;690 u8 *mc_list;691 u8 *cur_mc;692 693 if (dev->flags & IFF_PROMISC)694 return;695 696 if (dev->flags & IFF_ALLMULTI ||697 dev->mc.count > WILC_MULTICAST_TABLE_SIZE) {698 wilc_setup_multicast_filter(vif, 0, 0, NULL);699 return;700 }701 702 if (dev->mc.count == 0) {703 wilc_setup_multicast_filter(vif, 1, 0, NULL);704 return;705 }706 707 mc_list = kmalloc_array(dev->mc.count, ETH_ALEN, GFP_ATOMIC);708 if (!mc_list)709 return;710 711 cur_mc = mc_list;712 i = 0;713 netdev_for_each_mc_addr(ha, dev) {714 memcpy(cur_mc, ha->addr, ETH_ALEN);715 netdev_dbg(dev, "Entry[%d]: %pM\n", i, cur_mc);716 i++;717 cur_mc += ETH_ALEN;718 }719 720 if (wilc_setup_multicast_filter(vif, 1, dev->mc.count, mc_list))721 kfree(mc_list);722}723 724static void wilc_tx_complete(void *priv, int status)725{726 struct tx_complete_data *pv_data = priv;727 728 dev_kfree_skb(pv_data->skb);729 kfree(pv_data);730}731 732netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev)733{734 struct wilc_vif *vif = netdev_priv(ndev);735 struct wilc *wilc = vif->wilc;736 struct tx_complete_data *tx_data = NULL;737 int queue_count;738 739 if (skb->dev != ndev) {740 netdev_err(ndev, "Packet not destined to this device\n");741 dev_kfree_skb(skb);742 return NETDEV_TX_OK;743 }744 745 tx_data = kmalloc(sizeof(*tx_data), GFP_ATOMIC);746 if (!tx_data) {747 dev_kfree_skb(skb);748 netif_wake_queue(ndev);749 return NETDEV_TX_OK;750 }751 752 tx_data->buff = skb->data;753 tx_data->size = skb->len;754 tx_data->skb = skb;755 756 vif->netstats.tx_packets++;757 vif->netstats.tx_bytes += tx_data->size;758 queue_count = wilc_wlan_txq_add_net_pkt(ndev, tx_data,759 tx_data->buff, tx_data->size,760 wilc_tx_complete);761 762 if (queue_count > FLOW_CONTROL_UPPER_THRESHOLD) {763 int srcu_idx;764 struct wilc_vif *vif;765 766 srcu_idx = srcu_read_lock(&wilc->srcu);767 wilc_for_each_vif(wilc, vif) {768 if (vif->mac_opened)769 netif_stop_queue(vif->ndev);770 }771 srcu_read_unlock(&wilc->srcu, srcu_idx);772 }773 774 return NETDEV_TX_OK;775}776 777static int wilc_mac_close(struct net_device *ndev)778{779 struct wilc_vif *vif = netdev_priv(ndev);780 struct wilc *wl = vif->wilc;781 782 netdev_dbg(ndev, "Mac close\n");783 784 if (wl->open_ifcs > 0)785 wl->open_ifcs--;786 else787 return 0;788 789 if (vif->ndev) {790 netif_stop_queue(vif->ndev);791 792 wilc_handle_disconnect(vif);793 wilc_deinit_host_int(vif->ndev);794 }795 796 if (wl->open_ifcs == 0) {797 netdev_dbg(ndev, "Deinitializing wilc1000\n");798 wl->close = 1;799 wilc_wlan_deinitialize(ndev);800 }801 802 vif->mac_opened = 0;803 804 return 0;805}806 807void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size,808 u32 pkt_offset)809{810 unsigned char *buff_to_send = NULL;811 struct net_device *wilc_netdev;812 unsigned int frame_len = 0;813 struct wilc_vif *vif;814 struct sk_buff *skb;815 int srcu_idx;816 int stats;817 818 if (!wilc)819 return;820 821 srcu_idx = srcu_read_lock(&wilc->srcu);822 wilc_netdev = get_if_handler(wilc, buff);823 if (!wilc_netdev)824 goto out;825 826 buff += pkt_offset;827 vif = netdev_priv(wilc_netdev);828 829 if (size > 0) {830 frame_len = size;831 buff_to_send = buff;832 833 skb = dev_alloc_skb(frame_len);834 if (!skb)835 goto out;836 837 skb->dev = wilc_netdev;838 839 skb_put_data(skb, buff_to_send, frame_len);840 841 skb->protocol = eth_type_trans(skb, wilc_netdev);842 vif->netstats.rx_packets++;843 vif->netstats.rx_bytes += frame_len;844 skb->ip_summed = CHECKSUM_UNNECESSARY;845 stats = netif_rx(skb);846 netdev_dbg(wilc_netdev, "netif_rx ret value is: %d\n", stats);847 }848out:849 srcu_read_unlock(&wilc->srcu, srcu_idx);850}851 852void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size, bool is_auth)853{854 int srcu_idx;855 struct wilc_vif *vif;856 857 srcu_idx = srcu_read_lock(&wilc->srcu);858 wilc_for_each_vif(wilc, vif) {859 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buff;860 u16 type = le16_to_cpup((__le16 *)buff);861 u32 type_bit = BIT(type >> 4);862 u32 auth_bit = BIT(IEEE80211_STYPE_AUTH >> 4);863 864 if ((vif->mgmt_reg_stypes & auth_bit &&865 ieee80211_is_auth(mgmt->frame_control)) &&866 vif->iftype == WILC_STATION_MODE && is_auth) {867 wilc_wfi_mgmt_frame_rx(vif, buff, size);868 break;869 }870 871 if (vif->priv.p2p_listen_state &&872 vif->mgmt_reg_stypes & type_bit)873 wilc_wfi_p2p_rx(vif, buff, size);874 875 if (vif->monitor_flag)876 wilc_wfi_monitor_rx(wilc->monitor_dev, buff, size);877 }878 srcu_read_unlock(&wilc->srcu, srcu_idx);879}880 881static const struct net_device_ops wilc_netdev_ops = {882 .ndo_init = mac_init_fn,883 .ndo_open = wilc_mac_open,884 .ndo_stop = wilc_mac_close,885 .ndo_set_mac_address = wilc_set_mac_addr,886 .ndo_start_xmit = wilc_mac_xmit,887 .ndo_get_stats = mac_stats,888 .ndo_set_rx_mode = wilc_set_multicast_list,889};890 891void wilc_netdev_cleanup(struct wilc *wilc)892{893 struct wilc_vif *vif, *vif_tmp;894 895 if (!wilc)896 return;897 898 if (wilc->firmware) {899 release_firmware(wilc->firmware);900 wilc->firmware = NULL;901 }902 903 list_for_each_entry_safe(vif, vif_tmp, &wilc->vif_list, list) {904 mutex_lock(&wilc->vif_mutex);905 list_del_rcu(&vif->list);906 wilc->vif_num--;907 mutex_unlock(&wilc->vif_mutex);908 synchronize_srcu(&wilc->srcu);909 if (vif->ndev)910 unregister_netdev(vif->ndev);911 }912 913 wilc_wfi_deinit_mon_interface(wilc, false);914 destroy_workqueue(wilc->hif_workqueue);915 916 wilc_wlan_cfg_deinit(wilc);917 wlan_deinit_locks(wilc);918 wiphy_unregister(wilc->wiphy);919 wiphy_free(wilc->wiphy);920}921EXPORT_SYMBOL_GPL(wilc_netdev_cleanup);922 923static u8 wilc_get_available_idx(struct wilc *wl)924{925 int idx = 0;926 struct wilc_vif *vif;927 int srcu_idx;928 929 srcu_idx = srcu_read_lock(&wl->srcu);930 wilc_for_each_vif(wl, vif) {931 if (vif->idx == 0)932 idx = 1;933 else934 idx = 0;935 }936 srcu_read_unlock(&wl->srcu, srcu_idx);937 return idx;938}939 940struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name,941 int vif_type, enum nl80211_iftype type,942 bool rtnl_locked)943{944 u8 mac_address[ETH_ALEN];945 struct net_device *ndev;946 struct wilc_vif *vif;947 int ret;948 949 ndev = alloc_etherdev(sizeof(*vif));950 if (!ndev)951 return ERR_PTR(-ENOMEM);952 953 vif = netdev_priv(ndev);954 ndev->ieee80211_ptr = &vif->priv.wdev;955 strcpy(ndev->name, name);956 vif->wilc = wl;957 vif->ndev = ndev;958 ndev->ml_priv = vif;959 960 ndev->netdev_ops = &wilc_netdev_ops;961 962 SET_NETDEV_DEV(ndev, wiphy_dev(wl->wiphy));963 964 vif->priv.wdev.wiphy = wl->wiphy;965 vif->priv.wdev.netdev = ndev;966 vif->priv.wdev.iftype = type;967 vif->priv.dev = ndev;968 969 ndev->needs_free_netdev = true;970 vif->iftype = vif_type;971 vif->idx = wilc_get_available_idx(wl);972 vif->mac_opened = 0;973 974 memcpy(mac_address, wl->nv_mac_address, ETH_ALEN);975 /* WILC firmware uses locally administered MAC address for the976 * second virtual interface (bit 1 of first byte set), but977 * since it is possibly not loaded/running yet, reproduce this behavior978 * in the driver during interface creation.979 */980 if (vif->idx)981 mac_address[0] |= 0x2;982 983 eth_hw_addr_set(vif->ndev, mac_address);984 985 mutex_lock(&wl->vif_mutex);986 list_add_tail_rcu(&vif->list, &wl->vif_list);987 wl->vif_num += 1;988 mutex_unlock(&wl->vif_mutex);989 synchronize_srcu(&wl->srcu);990 991 if (rtnl_locked)992 ret = cfg80211_register_netdevice(ndev);993 else994 ret = register_netdev(ndev);995 996 if (ret) {997 ret = -EFAULT;998 goto error_remove_vif;999 }1000 1001 return vif;1002 1003error_remove_vif:1004 mutex_lock(&wl->vif_mutex);1005 list_del_rcu(&vif->list);1006 wl->vif_num -= 1;1007 mutex_unlock(&wl->vif_mutex);1008 synchronize_srcu(&wl->srcu);1009 free_netdev(ndev);1010 return ERR_PTR(ret);1011}1012EXPORT_SYMBOL_GPL(wilc_netdev_ifc_init);1013 1014MODULE_DESCRIPTION("Atmel WILC1000 core wireless driver");1015MODULE_LICENSE("GPL");1016MODULE_FIRMWARE(WILC1000_FW(WILC1000_API_VER));1017