brintos

brintos / linux-shallow public Read only

0
0
Text · 22.3 KiB · 9ecf3fb Raw
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