Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
0004  * All rights reserved.
0005  */
0006 
0007 #include <linux/irq.h>
0008 #include <linux/kthread.h>
0009 #include <linux/firmware.h>
0010 #include <linux/netdevice.h>
0011 #include <linux/inetdevice.h>
0012 
0013 #include "cfg80211.h"
0014 #include "wlan_cfg.h"
0015 
0016 #define WILC_MULTICAST_TABLE_SIZE   8
0017 #define WILC_MAX_FW_VERSION_STR_SIZE    50
0018 
0019 /* latest API version supported */
0020 #define WILC1000_API_VER        1
0021 
0022 #define WILC1000_FW_PREFIX      "atmel/wilc1000_wifi_firmware-"
0023 #define __WILC1000_FW(api)      WILC1000_FW_PREFIX #api ".bin"
0024 #define WILC1000_FW(api)        __WILC1000_FW(api)
0025 
0026 static irqreturn_t isr_uh_routine(int irq, void *user_data)
0027 {
0028     struct wilc *wilc = user_data;
0029 
0030     if (wilc->close) {
0031         pr_err("Can't handle UH interrupt\n");
0032         return IRQ_HANDLED;
0033     }
0034     return IRQ_WAKE_THREAD;
0035 }
0036 
0037 static irqreturn_t isr_bh_routine(int irq, void *userdata)
0038 {
0039     struct wilc *wilc = userdata;
0040 
0041     if (wilc->close) {
0042         pr_err("Can't handle BH interrupt\n");
0043         return IRQ_HANDLED;
0044     }
0045 
0046     wilc_handle_isr(wilc);
0047 
0048     return IRQ_HANDLED;
0049 }
0050 
0051 static int init_irq(struct net_device *dev)
0052 {
0053     struct wilc_vif *vif = netdev_priv(dev);
0054     struct wilc *wl = vif->wilc;
0055     int ret;
0056 
0057     ret = request_threaded_irq(wl->dev_irq_num, isr_uh_routine,
0058                    isr_bh_routine,
0059                    IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
0060                    dev->name, wl);
0061     if (ret) {
0062         netdev_err(dev, "Failed to request IRQ [%d]\n", ret);
0063         return ret;
0064     }
0065     netdev_dbg(dev, "IRQ request succeeded IRQ-NUM= %d\n", wl->dev_irq_num);
0066 
0067     return 0;
0068 }
0069 
0070 static void deinit_irq(struct net_device *dev)
0071 {
0072     struct wilc_vif *vif = netdev_priv(dev);
0073     struct wilc *wilc = vif->wilc;
0074 
0075     /* Deinitialize IRQ */
0076     if (wilc->dev_irq_num)
0077         free_irq(wilc->dev_irq_num, wilc);
0078 }
0079 
0080 void wilc_mac_indicate(struct wilc *wilc)
0081 {
0082     s8 status;
0083 
0084     wilc_wlan_cfg_get_val(wilc, WID_STATUS, &status, 1);
0085     if (wilc->mac_status == WILC_MAC_STATUS_INIT) {
0086         wilc->mac_status = status;
0087         complete(&wilc->sync_event);
0088     } else {
0089         wilc->mac_status = status;
0090     }
0091 }
0092 
0093 static struct net_device *get_if_handler(struct wilc *wilc, u8 *mac_header)
0094 {
0095     struct net_device *ndev = NULL;
0096     struct wilc_vif *vif;
0097     struct ieee80211_hdr *h = (struct ieee80211_hdr *)mac_header;
0098 
0099     list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
0100         if (vif->iftype == WILC_STATION_MODE)
0101             if (ether_addr_equal_unaligned(h->addr2, vif->bssid)) {
0102                 ndev = vif->ndev;
0103                 goto out;
0104             }
0105         if (vif->iftype == WILC_AP_MODE)
0106             if (ether_addr_equal_unaligned(h->addr1, vif->bssid)) {
0107                 ndev = vif->ndev;
0108                 goto out;
0109             }
0110     }
0111 out:
0112     return ndev;
0113 }
0114 
0115 void wilc_wlan_set_bssid(struct net_device *wilc_netdev, const u8 *bssid,
0116              u8 mode)
0117 {
0118     struct wilc_vif *vif = netdev_priv(wilc_netdev);
0119 
0120     if (bssid)
0121         ether_addr_copy(vif->bssid, bssid);
0122     else
0123         eth_zero_addr(vif->bssid);
0124 
0125     vif->iftype = mode;
0126 }
0127 
0128 int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc)
0129 {
0130     int srcu_idx;
0131     u8 ret_val = 0;
0132     struct wilc_vif *vif;
0133 
0134     srcu_idx = srcu_read_lock(&wilc->srcu);
0135     list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
0136         if (!is_zero_ether_addr(vif->bssid))
0137             ret_val++;
0138     }
0139     srcu_read_unlock(&wilc->srcu, srcu_idx);
0140     return ret_val;
0141 }
0142 
0143 static int wilc_txq_task(void *vp)
0144 {
0145     int ret;
0146     u32 txq_count;
0147     struct wilc *wl = vp;
0148 
0149     complete(&wl->txq_thread_started);
0150     while (1) {
0151         wait_for_completion(&wl->txq_event);
0152 
0153         if (wl->close) {
0154             complete(&wl->txq_thread_started);
0155 
0156             while (!kthread_should_stop())
0157                 schedule();
0158             break;
0159         }
0160         do {
0161             ret = wilc_wlan_handle_txq(wl, &txq_count);
0162             if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD) {
0163                 int srcu_idx;
0164                 struct wilc_vif *ifc;
0165 
0166                 srcu_idx = srcu_read_lock(&wl->srcu);
0167                 list_for_each_entry_rcu(ifc, &wl->vif_list,
0168                             list) {
0169                     if (ifc->mac_opened && ifc->ndev)
0170                         netif_wake_queue(ifc->ndev);
0171                 }
0172                 srcu_read_unlock(&wl->srcu, srcu_idx);
0173             }
0174         } while (ret == WILC_VMM_ENTRY_FULL_RETRY && !wl->close);
0175     }
0176     return 0;
0177 }
0178 
0179 static int wilc_wlan_get_firmware(struct net_device *dev)
0180 {
0181     struct wilc_vif *vif = netdev_priv(dev);
0182     struct wilc *wilc = vif->wilc;
0183     int chip_id;
0184     const struct firmware *wilc_fw;
0185     int ret;
0186 
0187     chip_id = wilc_get_chipid(wilc, false);
0188 
0189     netdev_info(dev, "ChipID [%x] loading firmware [%s]\n", chip_id,
0190             WILC1000_FW(WILC1000_API_VER));
0191 
0192     ret = request_firmware(&wilc_fw, WILC1000_FW(WILC1000_API_VER),
0193                    wilc->dev);
0194     if (ret != 0) {
0195         netdev_err(dev, "%s - firmware not available\n",
0196                WILC1000_FW(WILC1000_API_VER));
0197         return -EINVAL;
0198     }
0199     wilc->firmware = wilc_fw;
0200 
0201     return 0;
0202 }
0203 
0204 static int wilc_start_firmware(struct net_device *dev)
0205 {
0206     struct wilc_vif *vif = netdev_priv(dev);
0207     struct wilc *wilc = vif->wilc;
0208     int ret = 0;
0209 
0210     ret = wilc_wlan_start(wilc);
0211     if (ret)
0212         return ret;
0213 
0214     if (!wait_for_completion_timeout(&wilc->sync_event,
0215                      msecs_to_jiffies(5000)))
0216         return -ETIME;
0217 
0218     return 0;
0219 }
0220 
0221 static int wilc1000_firmware_download(struct net_device *dev)
0222 {
0223     struct wilc_vif *vif = netdev_priv(dev);
0224     struct wilc *wilc = vif->wilc;
0225     int ret = 0;
0226 
0227     if (!wilc->firmware) {
0228         netdev_err(dev, "Firmware buffer is NULL\n");
0229         return -ENOBUFS;
0230     }
0231 
0232     ret = wilc_wlan_firmware_download(wilc, wilc->firmware->data,
0233                       wilc->firmware->size);
0234     if (ret)
0235         return ret;
0236 
0237     release_firmware(wilc->firmware);
0238     wilc->firmware = NULL;
0239 
0240     netdev_dbg(dev, "Download Succeeded\n");
0241 
0242     return 0;
0243 }
0244 
0245 static int wilc_init_fw_config(struct net_device *dev, struct wilc_vif *vif)
0246 {
0247     struct wilc_priv *priv = &vif->priv;
0248     struct host_if_drv *hif_drv;
0249     u8 b;
0250     u16 hw;
0251     u32 w;
0252 
0253     netdev_dbg(dev, "Start configuring Firmware\n");
0254     hif_drv = (struct host_if_drv *)priv->hif_drv;
0255     netdev_dbg(dev, "Host = %p\n", hif_drv);
0256 
0257     w = vif->iftype;
0258     cpu_to_le32s(&w);
0259     if (!wilc_wlan_cfg_set(vif, 1, WID_SET_OPERATION_MODE, (u8 *)&w, 4,
0260                    0, 0))
0261         goto fail;
0262 
0263     b = WILC_FW_BSS_TYPE_INFRA;
0264     if (!wilc_wlan_cfg_set(vif, 0, WID_BSS_TYPE, &b, 1, 0, 0))
0265         goto fail;
0266 
0267     b = WILC_FW_TX_RATE_AUTO;
0268     if (!wilc_wlan_cfg_set(vif, 0, WID_CURRENT_TX_RATE, &b, 1, 0, 0))
0269         goto fail;
0270 
0271     b = WILC_FW_OPER_MODE_G_MIXED_11B_2;
0272     if (!wilc_wlan_cfg_set(vif, 0, WID_11G_OPERATING_MODE, &b, 1, 0, 0))
0273         goto fail;
0274 
0275     b = WILC_FW_PREAMBLE_SHORT;
0276     if (!wilc_wlan_cfg_set(vif, 0, WID_PREAMBLE, &b, 1, 0, 0))
0277         goto fail;
0278 
0279     b = WILC_FW_11N_PROT_AUTO;
0280     if (!wilc_wlan_cfg_set(vif, 0, WID_11N_PROT_MECH, &b, 1, 0, 0))
0281         goto fail;
0282 
0283     b = WILC_FW_ACTIVE_SCAN;
0284     if (!wilc_wlan_cfg_set(vif, 0, WID_SCAN_TYPE, &b, 1, 0, 0))
0285         goto fail;
0286 
0287     b = WILC_FW_SITE_SURVEY_OFF;
0288     if (!wilc_wlan_cfg_set(vif, 0, WID_SITE_SURVEY, &b, 1, 0, 0))
0289         goto fail;
0290 
0291     hw = 0xffff;
0292     cpu_to_le16s(&hw);
0293     if (!wilc_wlan_cfg_set(vif, 0, WID_RTS_THRESHOLD, (u8 *)&hw, 2, 0, 0))
0294         goto fail;
0295 
0296     hw = 2346;
0297     cpu_to_le16s(&hw);
0298     if (!wilc_wlan_cfg_set(vif, 0, WID_FRAG_THRESHOLD, (u8 *)&hw, 2, 0, 0))
0299         goto fail;
0300 
0301     b = 0;
0302     if (!wilc_wlan_cfg_set(vif, 0, WID_BCAST_SSID, &b, 1, 0, 0))
0303         goto fail;
0304 
0305     b = 1;
0306     if (!wilc_wlan_cfg_set(vif, 0, WID_QOS_ENABLE, &b, 1, 0, 0))
0307         goto fail;
0308 
0309     b = WILC_FW_NO_POWERSAVE;
0310     if (!wilc_wlan_cfg_set(vif, 0, WID_POWER_MANAGEMENT, &b, 1, 0, 0))
0311         goto fail;
0312 
0313     b = WILC_FW_SEC_NO;
0314     if (!wilc_wlan_cfg_set(vif, 0, WID_11I_MODE, &b, 1, 0, 0))
0315         goto fail;
0316 
0317     b = WILC_FW_AUTH_OPEN_SYSTEM;
0318     if (!wilc_wlan_cfg_set(vif, 0, WID_AUTH_TYPE, &b, 1, 0, 0))
0319         goto fail;
0320 
0321     b = 3;
0322     if (!wilc_wlan_cfg_set(vif, 0, WID_LISTEN_INTERVAL, &b, 1, 0, 0))
0323         goto fail;
0324 
0325     b = 3;
0326     if (!wilc_wlan_cfg_set(vif, 0, WID_DTIM_PERIOD, &b, 1, 0, 0))
0327         goto fail;
0328 
0329     b = WILC_FW_ACK_POLICY_NORMAL;
0330     if (!wilc_wlan_cfg_set(vif, 0, WID_ACK_POLICY, &b, 1, 0, 0))
0331         goto fail;
0332 
0333     b = 0;
0334     if (!wilc_wlan_cfg_set(vif, 0, WID_USER_CONTROL_ON_TX_POWER, &b, 1,
0335                    0, 0))
0336         goto fail;
0337 
0338     b = 48;
0339     if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11A, &b, 1, 0, 0))
0340         goto fail;
0341 
0342     b = 28;
0343     if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11B, &b, 1, 0, 0))
0344         goto fail;
0345 
0346     hw = 100;
0347     cpu_to_le16s(&hw);
0348     if (!wilc_wlan_cfg_set(vif, 0, WID_BEACON_INTERVAL, (u8 *)&hw, 2, 0, 0))
0349         goto fail;
0350 
0351     b = WILC_FW_REKEY_POLICY_DISABLE;
0352     if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_POLICY, &b, 1, 0, 0))
0353         goto fail;
0354 
0355     w = 84600;
0356     cpu_to_le32s(&w);
0357     if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PERIOD, (u8 *)&w, 4, 0, 0))
0358         goto fail;
0359 
0360     w = 500;
0361     cpu_to_le32s(&w);
0362     if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PACKET_COUNT, (u8 *)&w, 4, 0,
0363                    0))
0364         goto fail;
0365 
0366     b = 1;
0367     if (!wilc_wlan_cfg_set(vif, 0, WID_SHORT_SLOT_ALLOWED, &b, 1, 0,
0368                    0))
0369         goto fail;
0370 
0371     b = WILC_FW_ERP_PROT_SELF_CTS;
0372     if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ERP_PROT_TYPE, &b, 1, 0, 0))
0373         goto fail;
0374 
0375     b = 1;
0376     if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ENABLE, &b, 1, 0, 0))
0377         goto fail;
0378 
0379     b = WILC_FW_11N_OP_MODE_HT_MIXED;
0380     if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OPERATING_MODE, &b, 1, 0, 0))
0381         goto fail;
0382 
0383     b = 1;
0384     if (!wilc_wlan_cfg_set(vif, 0, WID_11N_TXOP_PROT_DISABLE, &b, 1, 0, 0))
0385         goto fail;
0386 
0387     b = WILC_FW_OBBS_NONHT_DETECT_PROTECT_REPORT;
0388     if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OBSS_NONHT_DETECTION, &b, 1,
0389                    0, 0))
0390         goto fail;
0391 
0392     b = WILC_FW_HT_PROT_RTS_CTS_NONHT;
0393     if (!wilc_wlan_cfg_set(vif, 0, WID_11N_HT_PROT_TYPE, &b, 1, 0, 0))
0394         goto fail;
0395 
0396     b = 0;
0397     if (!wilc_wlan_cfg_set(vif, 0, WID_11N_RIFS_PROT_ENABLE, &b, 1, 0,
0398                    0))
0399         goto fail;
0400 
0401     b = 7;
0402     if (!wilc_wlan_cfg_set(vif, 0, WID_11N_CURRENT_TX_MCS, &b, 1, 0, 0))
0403         goto fail;
0404 
0405     b = 1;
0406     if (!wilc_wlan_cfg_set(vif, 0, WID_11N_IMMEDIATE_BA_ENABLED, &b, 1,
0407                    1, 1))
0408         goto fail;
0409 
0410     return 0;
0411 
0412 fail:
0413     return -EINVAL;
0414 }
0415 
0416 static void wlan_deinitialize_threads(struct net_device *dev)
0417 {
0418     struct wilc_vif *vif = netdev_priv(dev);
0419     struct wilc *wl = vif->wilc;
0420 
0421     wl->close = 1;
0422 
0423     complete(&wl->txq_event);
0424 
0425     if (wl->txq_thread) {
0426         kthread_stop(wl->txq_thread);
0427         wl->txq_thread = NULL;
0428     }
0429 }
0430 
0431 static void wilc_wlan_deinitialize(struct net_device *dev)
0432 {
0433     struct wilc_vif *vif = netdev_priv(dev);
0434     struct wilc *wl = vif->wilc;
0435 
0436     if (!wl) {
0437         netdev_err(dev, "wl is NULL\n");
0438         return;
0439     }
0440 
0441     if (wl->initialized) {
0442         netdev_info(dev, "Deinitializing wilc1000...\n");
0443 
0444         if (!wl->dev_irq_num &&
0445             wl->hif_func->disable_interrupt) {
0446             mutex_lock(&wl->hif_cs);
0447             wl->hif_func->disable_interrupt(wl);
0448             mutex_unlock(&wl->hif_cs);
0449         }
0450         complete(&wl->txq_event);
0451 
0452         wlan_deinitialize_threads(dev);
0453         deinit_irq(dev);
0454 
0455         wilc_wlan_stop(wl, vif);
0456         wilc_wlan_cleanup(dev);
0457 
0458         wl->initialized = false;
0459 
0460         netdev_dbg(dev, "wilc1000 deinitialization Done\n");
0461     } else {
0462         netdev_dbg(dev, "wilc1000 is not initialized\n");
0463     }
0464 }
0465 
0466 static int wlan_initialize_threads(struct net_device *dev)
0467 {
0468     struct wilc_vif *vif = netdev_priv(dev);
0469     struct wilc *wilc = vif->wilc;
0470 
0471     wilc->txq_thread = kthread_run(wilc_txq_task, (void *)wilc,
0472                        "%s-tx", dev->name);
0473     if (IS_ERR(wilc->txq_thread)) {
0474         netdev_err(dev, "couldn't create TXQ thread\n");
0475         wilc->close = 1;
0476         return PTR_ERR(wilc->txq_thread);
0477     }
0478     wait_for_completion(&wilc->txq_thread_started);
0479 
0480     return 0;
0481 }
0482 
0483 static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
0484 {
0485     int ret = 0;
0486     struct wilc *wl = vif->wilc;
0487 
0488     if (!wl->initialized) {
0489         wl->mac_status = WILC_MAC_STATUS_INIT;
0490         wl->close = 0;
0491 
0492         ret = wilc_wlan_init(dev);
0493         if (ret)
0494             return ret;
0495 
0496         ret = wlan_initialize_threads(dev);
0497         if (ret)
0498             goto fail_wilc_wlan;
0499 
0500         if (wl->dev_irq_num && init_irq(dev)) {
0501             ret = -EIO;
0502             goto fail_threads;
0503         }
0504 
0505         if (!wl->dev_irq_num &&
0506             wl->hif_func->enable_interrupt &&
0507             wl->hif_func->enable_interrupt(wl)) {
0508             ret = -EIO;
0509             goto fail_irq_init;
0510         }
0511 
0512         ret = wilc_wlan_get_firmware(dev);
0513         if (ret)
0514             goto fail_irq_enable;
0515 
0516         ret = wilc1000_firmware_download(dev);
0517         if (ret)
0518             goto fail_irq_enable;
0519 
0520         ret = wilc_start_firmware(dev);
0521         if (ret)
0522             goto fail_irq_enable;
0523 
0524         if (wilc_wlan_cfg_get(vif, 1, WID_FIRMWARE_VERSION, 1, 0)) {
0525             int size;
0526             char firmware_ver[WILC_MAX_FW_VERSION_STR_SIZE];
0527 
0528             size = wilc_wlan_cfg_get_val(wl, WID_FIRMWARE_VERSION,
0529                              firmware_ver,
0530                              sizeof(firmware_ver));
0531             firmware_ver[size] = '\0';
0532             netdev_dbg(dev, "Firmware Ver = %s\n", firmware_ver);
0533         }
0534 
0535         ret = wilc_init_fw_config(dev, vif);
0536         if (ret) {
0537             netdev_err(dev, "Failed to configure firmware\n");
0538             goto fail_fw_start;
0539         }
0540         wl->initialized = true;
0541         return 0;
0542 
0543 fail_fw_start:
0544         wilc_wlan_stop(wl, vif);
0545 
0546 fail_irq_enable:
0547         if (!wl->dev_irq_num &&
0548             wl->hif_func->disable_interrupt)
0549             wl->hif_func->disable_interrupt(wl);
0550 fail_irq_init:
0551         if (wl->dev_irq_num)
0552             deinit_irq(dev);
0553 fail_threads:
0554         wlan_deinitialize_threads(dev);
0555 fail_wilc_wlan:
0556         wilc_wlan_cleanup(dev);
0557         netdev_err(dev, "WLAN initialization FAILED\n");
0558     } else {
0559         netdev_dbg(dev, "wilc1000 already initialized\n");
0560     }
0561     return ret;
0562 }
0563 
0564 static int mac_init_fn(struct net_device *ndev)
0565 {
0566     netif_start_queue(ndev);
0567     netif_stop_queue(ndev);
0568 
0569     return 0;
0570 }
0571 
0572 static int wilc_mac_open(struct net_device *ndev)
0573 {
0574     struct wilc_vif *vif = netdev_priv(ndev);
0575     struct wilc *wl = vif->wilc;
0576     int ret = 0;
0577     struct mgmt_frame_regs mgmt_regs = {};
0578     u8 addr[ETH_ALEN] __aligned(2);
0579 
0580     if (!wl || !wl->dev) {
0581         netdev_err(ndev, "device not ready\n");
0582         return -ENODEV;
0583     }
0584 
0585     netdev_dbg(ndev, "MAC OPEN[%p]\n", ndev);
0586 
0587     ret = wilc_init_host_int(ndev);
0588     if (ret)
0589         return ret;
0590 
0591     ret = wilc_wlan_initialize(ndev, vif);
0592     if (ret) {
0593         wilc_deinit_host_int(ndev);
0594         return ret;
0595     }
0596 
0597     wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), vif->iftype,
0598                 vif->idx);
0599 
0600     if (is_valid_ether_addr(ndev->dev_addr)) {
0601         ether_addr_copy(addr, ndev->dev_addr);
0602         wilc_set_mac_address(vif, addr);
0603     } else {
0604         wilc_get_mac_address(vif, addr);
0605         eth_hw_addr_set(ndev, addr);
0606     }
0607     netdev_dbg(ndev, "Mac address: %pM\n", ndev->dev_addr);
0608 
0609     if (!is_valid_ether_addr(ndev->dev_addr)) {
0610         netdev_err(ndev, "Wrong MAC address\n");
0611         wilc_deinit_host_int(ndev);
0612         wilc_wlan_deinitialize(ndev);
0613         return -EINVAL;
0614     }
0615 
0616     mgmt_regs.interface_stypes = vif->mgmt_reg_stypes;
0617     /* so we detect a change */
0618     vif->mgmt_reg_stypes = 0;
0619     wilc_update_mgmt_frame_registrations(vif->ndev->ieee80211_ptr->wiphy,
0620                          vif->ndev->ieee80211_ptr,
0621                          &mgmt_regs);
0622     netif_wake_queue(ndev);
0623     wl->open_ifcs++;
0624     vif->mac_opened = 1;
0625     return 0;
0626 }
0627 
0628 static struct net_device_stats *mac_stats(struct net_device *dev)
0629 {
0630     struct wilc_vif *vif = netdev_priv(dev);
0631 
0632     return &vif->netstats;
0633 }
0634 
0635 static int wilc_set_mac_addr(struct net_device *dev, void *p)
0636 {
0637     int result;
0638     struct wilc_vif *vif = netdev_priv(dev);
0639     struct wilc *wilc = vif->wilc;
0640     struct sockaddr *addr = (struct sockaddr *)p;
0641     unsigned char mac_addr[ETH_ALEN];
0642     struct wilc_vif *tmp_vif;
0643     int srcu_idx;
0644 
0645     if (!is_valid_ether_addr(addr->sa_data))
0646         return -EADDRNOTAVAIL;
0647 
0648     if (!vif->mac_opened) {
0649         eth_commit_mac_addr_change(dev, p);
0650         return 0;
0651     }
0652 
0653     /* Verify MAC Address is not already in use: */
0654 
0655     srcu_idx = srcu_read_lock(&wilc->srcu);
0656     list_for_each_entry_rcu(tmp_vif, &wilc->vif_list, list) {
0657         wilc_get_mac_address(tmp_vif, mac_addr);
0658         if (ether_addr_equal(addr->sa_data, mac_addr)) {
0659             if (vif != tmp_vif) {
0660                 srcu_read_unlock(&wilc->srcu, srcu_idx);
0661                 return -EADDRNOTAVAIL;
0662             }
0663             srcu_read_unlock(&wilc->srcu, srcu_idx);
0664             return 0;
0665         }
0666     }
0667     srcu_read_unlock(&wilc->srcu, srcu_idx);
0668 
0669     result = wilc_set_mac_address(vif, (u8 *)addr->sa_data);
0670     if (result)
0671         return result;
0672 
0673     eth_commit_mac_addr_change(dev, p);
0674     return result;
0675 }
0676 
0677 static void wilc_set_multicast_list(struct net_device *dev)
0678 {
0679     struct netdev_hw_addr *ha;
0680     struct wilc_vif *vif = netdev_priv(dev);
0681     int i;
0682     u8 *mc_list;
0683     u8 *cur_mc;
0684 
0685     if (dev->flags & IFF_PROMISC)
0686         return;
0687 
0688     if (dev->flags & IFF_ALLMULTI ||
0689         dev->mc.count > WILC_MULTICAST_TABLE_SIZE) {
0690         wilc_setup_multicast_filter(vif, 0, 0, NULL);
0691         return;
0692     }
0693 
0694     if (dev->mc.count == 0) {
0695         wilc_setup_multicast_filter(vif, 1, 0, NULL);
0696         return;
0697     }
0698 
0699     mc_list = kmalloc_array(dev->mc.count, ETH_ALEN, GFP_ATOMIC);
0700     if (!mc_list)
0701         return;
0702 
0703     cur_mc = mc_list;
0704     i = 0;
0705     netdev_for_each_mc_addr(ha, dev) {
0706         memcpy(cur_mc, ha->addr, ETH_ALEN);
0707         netdev_dbg(dev, "Entry[%d]: %pM\n", i, cur_mc);
0708         i++;
0709         cur_mc += ETH_ALEN;
0710     }
0711 
0712     if (wilc_setup_multicast_filter(vif, 1, dev->mc.count, mc_list))
0713         kfree(mc_list);
0714 }
0715 
0716 static void wilc_tx_complete(void *priv, int status)
0717 {
0718     struct tx_complete_data *pv_data = priv;
0719 
0720     dev_kfree_skb(pv_data->skb);
0721     kfree(pv_data);
0722 }
0723 
0724 netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev)
0725 {
0726     struct wilc_vif *vif = netdev_priv(ndev);
0727     struct wilc *wilc = vif->wilc;
0728     struct tx_complete_data *tx_data = NULL;
0729     int queue_count;
0730 
0731     if (skb->dev != ndev) {
0732         netdev_err(ndev, "Packet not destined to this device\n");
0733         return NETDEV_TX_OK;
0734     }
0735 
0736     tx_data = kmalloc(sizeof(*tx_data), GFP_ATOMIC);
0737     if (!tx_data) {
0738         dev_kfree_skb(skb);
0739         netif_wake_queue(ndev);
0740         return NETDEV_TX_OK;
0741     }
0742 
0743     tx_data->buff = skb->data;
0744     tx_data->size = skb->len;
0745     tx_data->skb  = skb;
0746 
0747     vif->netstats.tx_packets++;
0748     vif->netstats.tx_bytes += tx_data->size;
0749     queue_count = wilc_wlan_txq_add_net_pkt(ndev, tx_data,
0750                         tx_data->buff, tx_data->size,
0751                         wilc_tx_complete);
0752 
0753     if (queue_count > FLOW_CONTROL_UPPER_THRESHOLD) {
0754         int srcu_idx;
0755         struct wilc_vif *vif;
0756 
0757         srcu_idx = srcu_read_lock(&wilc->srcu);
0758         list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
0759             if (vif->mac_opened)
0760                 netif_stop_queue(vif->ndev);
0761         }
0762         srcu_read_unlock(&wilc->srcu, srcu_idx);
0763     }
0764 
0765     return NETDEV_TX_OK;
0766 }
0767 
0768 static int wilc_mac_close(struct net_device *ndev)
0769 {
0770     struct wilc_vif *vif = netdev_priv(ndev);
0771     struct wilc *wl = vif->wilc;
0772 
0773     netdev_dbg(ndev, "Mac close\n");
0774 
0775     if (wl->open_ifcs > 0)
0776         wl->open_ifcs--;
0777     else
0778         return 0;
0779 
0780     if (vif->ndev) {
0781         netif_stop_queue(vif->ndev);
0782 
0783         wilc_handle_disconnect(vif);
0784         wilc_deinit_host_int(vif->ndev);
0785     }
0786 
0787     if (wl->open_ifcs == 0) {
0788         netdev_dbg(ndev, "Deinitializing wilc1000\n");
0789         wl->close = 1;
0790         wilc_wlan_deinitialize(ndev);
0791     }
0792 
0793     vif->mac_opened = 0;
0794 
0795     return 0;
0796 }
0797 
0798 void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size,
0799                u32 pkt_offset)
0800 {
0801     unsigned int frame_len = 0;
0802     int stats;
0803     unsigned char *buff_to_send = NULL;
0804     struct sk_buff *skb;
0805     struct net_device *wilc_netdev;
0806     struct wilc_vif *vif;
0807 
0808     if (!wilc)
0809         return;
0810 
0811     wilc_netdev = get_if_handler(wilc, buff);
0812     if (!wilc_netdev)
0813         return;
0814 
0815     buff += pkt_offset;
0816     vif = netdev_priv(wilc_netdev);
0817 
0818     if (size > 0) {
0819         frame_len = size;
0820         buff_to_send = buff;
0821 
0822         skb = dev_alloc_skb(frame_len);
0823         if (!skb)
0824             return;
0825 
0826         skb->dev = wilc_netdev;
0827 
0828         skb_put_data(skb, buff_to_send, frame_len);
0829 
0830         skb->protocol = eth_type_trans(skb, wilc_netdev);
0831         vif->netstats.rx_packets++;
0832         vif->netstats.rx_bytes += frame_len;
0833         skb->ip_summed = CHECKSUM_UNNECESSARY;
0834         stats = netif_rx(skb);
0835         netdev_dbg(wilc_netdev, "netif_rx ret value is: %d\n", stats);
0836     }
0837 }
0838 
0839 void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size, bool is_auth)
0840 {
0841     int srcu_idx;
0842     struct wilc_vif *vif;
0843 
0844     srcu_idx = srcu_read_lock(&wilc->srcu);
0845     list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
0846         struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buff;
0847         u16 type = le16_to_cpup((__le16 *)buff);
0848         u32 type_bit = BIT(type >> 4);
0849         u32 auth_bit = BIT(IEEE80211_STYPE_AUTH >> 4);
0850 
0851         if ((vif->mgmt_reg_stypes & auth_bit &&
0852              ieee80211_is_auth(mgmt->frame_control)) &&
0853             vif->iftype == WILC_STATION_MODE && is_auth) {
0854             wilc_wfi_mgmt_frame_rx(vif, buff, size);
0855             break;
0856         }
0857 
0858         if (vif->priv.p2p_listen_state &&
0859             vif->mgmt_reg_stypes & type_bit)
0860             wilc_wfi_p2p_rx(vif, buff, size);
0861 
0862         if (vif->monitor_flag)
0863             wilc_wfi_monitor_rx(wilc->monitor_dev, buff, size);
0864     }
0865     srcu_read_unlock(&wilc->srcu, srcu_idx);
0866 }
0867 
0868 static const struct net_device_ops wilc_netdev_ops = {
0869     .ndo_init = mac_init_fn,
0870     .ndo_open = wilc_mac_open,
0871     .ndo_stop = wilc_mac_close,
0872     .ndo_set_mac_address = wilc_set_mac_addr,
0873     .ndo_start_xmit = wilc_mac_xmit,
0874     .ndo_get_stats = mac_stats,
0875     .ndo_set_rx_mode  = wilc_set_multicast_list,
0876 };
0877 
0878 void wilc_netdev_cleanup(struct wilc *wilc)
0879 {
0880     struct wilc_vif *vif;
0881     int srcu_idx, ifc_cnt = 0;
0882 
0883     if (!wilc)
0884         return;
0885 
0886     if (wilc->firmware) {
0887         release_firmware(wilc->firmware);
0888         wilc->firmware = NULL;
0889     }
0890 
0891     srcu_idx = srcu_read_lock(&wilc->srcu);
0892     list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
0893         if (vif->ndev)
0894             unregister_netdev(vif->ndev);
0895     }
0896     srcu_read_unlock(&wilc->srcu, srcu_idx);
0897 
0898     wilc_wfi_deinit_mon_interface(wilc, false);
0899     destroy_workqueue(wilc->hif_workqueue);
0900 
0901     while (ifc_cnt < WILC_NUM_CONCURRENT_IFC) {
0902         mutex_lock(&wilc->vif_mutex);
0903         if (wilc->vif_num <= 0) {
0904             mutex_unlock(&wilc->vif_mutex);
0905             break;
0906         }
0907         vif = wilc_get_wl_to_vif(wilc);
0908         if (!IS_ERR(vif))
0909             list_del_rcu(&vif->list);
0910 
0911         wilc->vif_num--;
0912         mutex_unlock(&wilc->vif_mutex);
0913         synchronize_srcu(&wilc->srcu);
0914         ifc_cnt++;
0915     }
0916 
0917     wilc_wlan_cfg_deinit(wilc);
0918     wlan_deinit_locks(wilc);
0919     wiphy_unregister(wilc->wiphy);
0920     wiphy_free(wilc->wiphy);
0921 }
0922 EXPORT_SYMBOL_GPL(wilc_netdev_cleanup);
0923 
0924 static u8 wilc_get_available_idx(struct wilc *wl)
0925 {
0926     int idx = 0;
0927     struct wilc_vif *vif;
0928     int srcu_idx;
0929 
0930     srcu_idx = srcu_read_lock(&wl->srcu);
0931     list_for_each_entry_rcu(vif, &wl->vif_list, list) {
0932         if (vif->idx == 0)
0933             idx = 1;
0934         else
0935             idx = 0;
0936     }
0937     srcu_read_unlock(&wl->srcu, srcu_idx);
0938     return idx;
0939 }
0940 
0941 struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name,
0942                       int vif_type, enum nl80211_iftype type,
0943                       bool rtnl_locked)
0944 {
0945     struct net_device *ndev;
0946     struct wilc_vif *vif;
0947     int ret;
0948 
0949     ndev = alloc_etherdev(sizeof(*vif));
0950     if (!ndev)
0951         return ERR_PTR(-ENOMEM);
0952 
0953     vif = netdev_priv(ndev);
0954     ndev->ieee80211_ptr = &vif->priv.wdev;
0955     strcpy(ndev->name, name);
0956     vif->wilc = wl;
0957     vif->ndev = ndev;
0958     ndev->ml_priv = vif;
0959 
0960     ndev->netdev_ops = &wilc_netdev_ops;
0961 
0962     SET_NETDEV_DEV(ndev, wiphy_dev(wl->wiphy));
0963 
0964     vif->priv.wdev.wiphy = wl->wiphy;
0965     vif->priv.wdev.netdev = ndev;
0966     vif->priv.wdev.iftype = type;
0967     vif->priv.dev = ndev;
0968 
0969     if (rtnl_locked)
0970         ret = cfg80211_register_netdevice(ndev);
0971     else
0972         ret = register_netdev(ndev);
0973 
0974     if (ret) {
0975         ret = -EFAULT;
0976         goto error;
0977     }
0978 
0979     wl->hif_workqueue = alloc_ordered_workqueue("%s-wq", WQ_MEM_RECLAIM,
0980                             ndev->name);
0981     if (!wl->hif_workqueue) {
0982         ret = -ENOMEM;
0983         goto error;
0984     }
0985 
0986     ndev->needs_free_netdev = true;
0987     vif->iftype = vif_type;
0988     vif->idx = wilc_get_available_idx(wl);
0989     vif->mac_opened = 0;
0990     mutex_lock(&wl->vif_mutex);
0991     list_add_tail_rcu(&vif->list, &wl->vif_list);
0992     wl->vif_num += 1;
0993     mutex_unlock(&wl->vif_mutex);
0994     synchronize_srcu(&wl->srcu);
0995 
0996     return vif;
0997 
0998   error:
0999     free_netdev(ndev);
1000     return ERR_PTR(ret);
1001 }
1002 
1003 MODULE_LICENSE("GPL");
1004 MODULE_FIRMWARE(WILC1000_FW(WILC1000_API_VER));