brintos

brintos / linux-shallow public Read only

0
0
Text · 35.7 KiB · 533939e Raw
1584 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/if_ether.h>8#include <linux/ip.h>9#include <net/dsfield.h>10#include "cfg80211.h"11#include "wlan_cfg.h"12 13#define WAKE_UP_TRIAL_RETRY		1000014 15static inline void acquire_bus(struct wilc *wilc, enum bus_acquire acquire)16{17	mutex_lock(&wilc->hif_cs);18	if (acquire == WILC_BUS_ACQUIRE_AND_WAKEUP && wilc->power_save_mode)19		chip_wakeup(wilc);20}21 22static inline void release_bus(struct wilc *wilc, enum bus_release release)23{24	if (release == WILC_BUS_RELEASE_ALLOW_SLEEP && wilc->power_save_mode)25		chip_allow_sleep(wilc);26	mutex_unlock(&wilc->hif_cs);27}28 29static void wilc_wlan_txq_remove(struct wilc *wilc, u8 q_num,30				 struct txq_entry_t *tqe)31{32	list_del(&tqe->list);33	wilc->txq_entries -= 1;34	wilc->txq[q_num].count--;35}36 37static struct txq_entry_t *38wilc_wlan_txq_remove_from_head(struct wilc *wilc, u8 q_num)39{40	struct txq_entry_t *tqe = NULL;41	unsigned long flags;42 43	spin_lock_irqsave(&wilc->txq_spinlock, flags);44 45	if (!list_empty(&wilc->txq[q_num].txq_head.list)) {46		tqe = list_first_entry(&wilc->txq[q_num].txq_head.list,47				       struct txq_entry_t, list);48		list_del(&tqe->list);49		wilc->txq_entries -= 1;50		wilc->txq[q_num].count--;51	}52	spin_unlock_irqrestore(&wilc->txq_spinlock, flags);53	return tqe;54}55 56static void wilc_wlan_txq_add_to_tail(struct net_device *dev, u8 q_num,57				      struct txq_entry_t *tqe)58{59	unsigned long flags;60	struct wilc_vif *vif = netdev_priv(dev);61	struct wilc *wilc = vif->wilc;62 63	spin_lock_irqsave(&wilc->txq_spinlock, flags);64 65	list_add_tail(&tqe->list, &wilc->txq[q_num].txq_head.list);66	wilc->txq_entries += 1;67	wilc->txq[q_num].count++;68 69	spin_unlock_irqrestore(&wilc->txq_spinlock, flags);70 71	complete(&wilc->txq_event);72}73 74static void wilc_wlan_txq_add_to_head(struct wilc_vif *vif, u8 q_num,75				      struct txq_entry_t *tqe)76{77	unsigned long flags;78	struct wilc *wilc = vif->wilc;79 80	mutex_lock(&wilc->txq_add_to_head_cs);81 82	spin_lock_irqsave(&wilc->txq_spinlock, flags);83 84	list_add(&tqe->list, &wilc->txq[q_num].txq_head.list);85	wilc->txq_entries += 1;86	wilc->txq[q_num].count++;87 88	spin_unlock_irqrestore(&wilc->txq_spinlock, flags);89	mutex_unlock(&wilc->txq_add_to_head_cs);90	complete(&wilc->txq_event);91}92 93#define NOT_TCP_ACK			(-1)94 95static inline void add_tcp_session(struct wilc_vif *vif, u32 src_prt,96				   u32 dst_prt, u32 seq)97{98	struct tcp_ack_filter *f = &vif->ack_filter;99 100	if (f->tcp_session < 2 * MAX_TCP_SESSION) {101		f->ack_session_info[f->tcp_session].seq_num = seq;102		f->ack_session_info[f->tcp_session].bigger_ack_num = 0;103		f->ack_session_info[f->tcp_session].src_port = src_prt;104		f->ack_session_info[f->tcp_session].dst_port = dst_prt;105		f->tcp_session++;106	}107}108 109static inline void update_tcp_session(struct wilc_vif *vif, u32 index, u32 ack)110{111	struct tcp_ack_filter *f = &vif->ack_filter;112 113	if (index < 2 * MAX_TCP_SESSION &&114	    ack > f->ack_session_info[index].bigger_ack_num)115		f->ack_session_info[index].bigger_ack_num = ack;116}117 118static inline void add_tcp_pending_ack(struct wilc_vif *vif, u32 ack,119				       u32 session_index,120				       struct txq_entry_t *txqe)121{122	struct tcp_ack_filter *f = &vif->ack_filter;123	u32 i = f->pending_base + f->pending_acks_idx;124 125	if (i < MAX_PENDING_ACKS) {126		f->pending_acks[i].ack_num = ack;127		f->pending_acks[i].txqe = txqe;128		f->pending_acks[i].session_index = session_index;129		txqe->ack_idx = i;130		f->pending_acks_idx++;131	}132}133 134static inline void tcp_process(struct net_device *dev, struct txq_entry_t *tqe)135{136	void *buffer = tqe->buffer;137	const struct ethhdr *eth_hdr_ptr = buffer;138	int i;139	unsigned long flags;140	struct wilc_vif *vif = netdev_priv(dev);141	struct wilc *wilc = vif->wilc;142	struct tcp_ack_filter *f = &vif->ack_filter;143	const struct iphdr *ip_hdr_ptr;144	const struct tcphdr *tcp_hdr_ptr;145	u32 ihl, total_length, data_offset;146 147	spin_lock_irqsave(&wilc->txq_spinlock, flags);148 149	if (eth_hdr_ptr->h_proto != htons(ETH_P_IP))150		goto out;151 152	ip_hdr_ptr = buffer + ETH_HLEN;153 154	if (ip_hdr_ptr->protocol != IPPROTO_TCP)155		goto out;156 157	ihl = ip_hdr_ptr->ihl << 2;158	tcp_hdr_ptr = buffer + ETH_HLEN + ihl;159	total_length = ntohs(ip_hdr_ptr->tot_len);160 161	data_offset = tcp_hdr_ptr->doff << 2;162	if (total_length == (ihl + data_offset)) {163		u32 seq_no, ack_no;164 165		seq_no = ntohl(tcp_hdr_ptr->seq);166		ack_no = ntohl(tcp_hdr_ptr->ack_seq);167		for (i = 0; i < f->tcp_session; i++) {168			u32 j = f->ack_session_info[i].seq_num;169 170			if (i < 2 * MAX_TCP_SESSION &&171			    j == seq_no) {172				update_tcp_session(vif, i, ack_no);173				break;174			}175		}176		if (i == f->tcp_session)177			add_tcp_session(vif, 0, 0, seq_no);178 179		add_tcp_pending_ack(vif, ack_no, i, tqe);180	}181 182out:183	spin_unlock_irqrestore(&wilc->txq_spinlock, flags);184}185 186static void wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev)187{188	struct wilc_vif *vif = netdev_priv(dev);189	struct wilc *wilc = vif->wilc;190	struct tcp_ack_filter *f = &vif->ack_filter;191	u32 i = 0;192	u32 dropped = 0;193	unsigned long flags;194 195	spin_lock_irqsave(&wilc->txq_spinlock, flags);196	for (i = f->pending_base;197	     i < (f->pending_base + f->pending_acks_idx); i++) {198		u32 index;199		u32 bigger_ack_num;200 201		if (i >= MAX_PENDING_ACKS)202			break;203 204		index = f->pending_acks[i].session_index;205 206		if (index >= 2 * MAX_TCP_SESSION)207			break;208 209		bigger_ack_num = f->ack_session_info[index].bigger_ack_num;210 211		if (f->pending_acks[i].ack_num < bigger_ack_num) {212			struct txq_entry_t *tqe;213 214			tqe = f->pending_acks[i].txqe;215			if (tqe) {216				wilc_wlan_txq_remove(wilc, tqe->q_num, tqe);217				tqe->status = 1;218				if (tqe->tx_complete_func)219					tqe->tx_complete_func(tqe->priv,220							      tqe->status);221				kfree(tqe);222				dropped++;223			}224		}225	}226	f->pending_acks_idx = 0;227	f->tcp_session = 0;228 229	if (f->pending_base == 0)230		f->pending_base = MAX_TCP_SESSION;231	else232		f->pending_base = 0;233 234	spin_unlock_irqrestore(&wilc->txq_spinlock, flags);235 236	while (dropped > 0) {237		wait_for_completion_timeout(&wilc->txq_event,238					    msecs_to_jiffies(1));239		dropped--;240	}241}242 243void wilc_enable_tcp_ack_filter(struct wilc_vif *vif, bool value)244{245	vif->ack_filter.enabled = value;246}247 248static int wilc_wlan_txq_add_cfg_pkt(struct wilc_vif *vif, u8 *buffer,249				     u32 buffer_size)250{251	struct txq_entry_t *tqe;252	struct wilc *wilc = vif->wilc;253 254	netdev_dbg(vif->ndev, "Adding config packet ...\n");255	if (wilc->quit) {256		netdev_dbg(vif->ndev, "Return due to clear function\n");257		complete(&wilc->cfg_event);258		return 0;259	}260 261	tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC);262	if (!tqe) {263		complete(&wilc->cfg_event);264		return 0;265	}266 267	tqe->type = WILC_CFG_PKT;268	tqe->buffer = buffer;269	tqe->buffer_size = buffer_size;270	tqe->tx_complete_func = NULL;271	tqe->priv = NULL;272	tqe->q_num = AC_VO_Q;273	tqe->ack_idx = NOT_TCP_ACK;274	tqe->vif = vif;275 276	wilc_wlan_txq_add_to_head(vif, AC_VO_Q, tqe);277 278	return 1;279}280 281static bool is_ac_q_limit(struct wilc *wl, u8 q_num)282{283	u8 factors[NQUEUES] = {1, 1, 1, 1};284	u16 i;285	unsigned long flags;286	struct wilc_tx_queue_status *q = &wl->tx_q_limit;287	u8 end_index;288	u8 q_limit;289	bool ret = false;290 291	spin_lock_irqsave(&wl->txq_spinlock, flags);292	if (!q->initialized) {293		for (i = 0; i < AC_BUFFER_SIZE; i++)294			q->buffer[i] = i % NQUEUES;295 296		for (i = 0; i < NQUEUES; i++) {297			q->cnt[i] = AC_BUFFER_SIZE * factors[i] / NQUEUES;298			q->sum += q->cnt[i];299		}300		q->end_index = AC_BUFFER_SIZE - 1;301		q->initialized = 1;302	}303 304	end_index = q->end_index;305	q->cnt[q->buffer[end_index]] -= factors[q->buffer[end_index]];306	q->cnt[q_num] += factors[q_num];307	q->sum += (factors[q_num] - factors[q->buffer[end_index]]);308 309	q->buffer[end_index] = q_num;310	if (end_index > 0)311		q->end_index--;312	else313		q->end_index = AC_BUFFER_SIZE - 1;314 315	if (!q->sum)316		q_limit = 1;317	else318		q_limit = (q->cnt[q_num] * FLOW_CONTROL_UPPER_THRESHOLD / q->sum) + 1;319 320	if (wl->txq[q_num].count <= q_limit)321		ret = true;322 323	spin_unlock_irqrestore(&wl->txq_spinlock, flags);324 325	return ret;326}327 328static inline u8 ac_classify(struct wilc *wilc, struct sk_buff *skb)329{330	u8 q_num = AC_BE_Q;331	u8 dscp;332 333	switch (skb->protocol) {334	case htons(ETH_P_IP):335		dscp = ipv4_get_dsfield(ip_hdr(skb)) & 0xfc;336		break;337	case htons(ETH_P_IPV6):338		dscp = ipv6_get_dsfield(ipv6_hdr(skb)) & 0xfc;339		break;340	default:341		return q_num;342	}343 344	switch (dscp) {345	case 0x08:346	case 0x20:347	case 0x40:348		q_num = AC_BK_Q;349		break;350	case 0x80:351	case 0xA0:352	case 0x28:353		q_num = AC_VI_Q;354		break;355	case 0xC0:356	case 0xD0:357	case 0xE0:358	case 0x88:359	case 0xB8:360		q_num = AC_VO_Q;361		break;362	}363 364	return q_num;365}366 367static inline int ac_balance(struct wilc *wl, u8 *ratio)368{369	u8 i, max_count = 0;370 371	if (!ratio)372		return -EINVAL;373 374	for (i = 0; i < NQUEUES; i++)375		if (wl->txq[i].fw.count > max_count)376			max_count = wl->txq[i].fw.count;377 378	for (i = 0; i < NQUEUES; i++)379		ratio[i] = max_count - wl->txq[i].fw.count;380 381	return 0;382}383 384static inline void ac_update_fw_ac_pkt_info(struct wilc *wl, u32 reg)385{386	wl->txq[AC_BK_Q].fw.count = FIELD_GET(BK_AC_COUNT_FIELD, reg);387	wl->txq[AC_BE_Q].fw.count = FIELD_GET(BE_AC_COUNT_FIELD, reg);388	wl->txq[AC_VI_Q].fw.count = FIELD_GET(VI_AC_COUNT_FIELD, reg);389	wl->txq[AC_VO_Q].fw.count = FIELD_GET(VO_AC_COUNT_FIELD, reg);390 391	wl->txq[AC_BK_Q].fw.acm = FIELD_GET(BK_AC_ACM_STAT_FIELD, reg);392	wl->txq[AC_BE_Q].fw.acm = FIELD_GET(BE_AC_ACM_STAT_FIELD, reg);393	wl->txq[AC_VI_Q].fw.acm = FIELD_GET(VI_AC_ACM_STAT_FIELD, reg);394	wl->txq[AC_VO_Q].fw.acm = FIELD_GET(VO_AC_ACM_STAT_FIELD, reg);395}396 397static inline u8 ac_change(struct wilc *wilc, u8 *ac)398{399	do {400		if (wilc->txq[*ac].fw.acm == 0)401			return 0;402		(*ac)++;403	} while (*ac < NQUEUES);404 405	return 1;406}407 408int wilc_wlan_txq_add_net_pkt(struct net_device *dev,409			      struct tx_complete_data *tx_data, u8 *buffer,410			      u32 buffer_size,411			      void (*tx_complete_fn)(void *, int))412{413	struct txq_entry_t *tqe;414	struct wilc_vif *vif = netdev_priv(dev);415	struct wilc *wilc;416	u8 q_num;417 418	wilc = vif->wilc;419 420	if (wilc->quit) {421		tx_complete_fn(tx_data, 0);422		return 0;423	}424 425	if (!wilc->initialized) {426		tx_complete_fn(tx_data, 0);427		return 0;428	}429 430	tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC);431 432	if (!tqe) {433		tx_complete_fn(tx_data, 0);434		return 0;435	}436	tqe->type = WILC_NET_PKT;437	tqe->buffer = buffer;438	tqe->buffer_size = buffer_size;439	tqe->tx_complete_func = tx_complete_fn;440	tqe->priv = tx_data;441	tqe->vif = vif;442 443	q_num = ac_classify(wilc, tx_data->skb);444	tqe->q_num = q_num;445	if (ac_change(wilc, &q_num)) {446		tx_complete_fn(tx_data, 0);447		kfree(tqe);448		return 0;449	}450 451	if (is_ac_q_limit(wilc, q_num)) {452		tqe->ack_idx = NOT_TCP_ACK;453		if (vif->ack_filter.enabled)454			tcp_process(dev, tqe);455		wilc_wlan_txq_add_to_tail(dev, q_num, tqe);456	} else {457		tx_complete_fn(tx_data, 0);458		kfree(tqe);459	}460 461	return wilc->txq_entries;462}463 464int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer,465			       u32 buffer_size,466			       void (*tx_complete_fn)(void *, int))467{468	struct txq_entry_t *tqe;469	struct wilc_vif *vif = netdev_priv(dev);470	struct wilc *wilc;471 472	wilc = vif->wilc;473 474	if (wilc->quit) {475		tx_complete_fn(priv, 0);476		return 0;477	}478 479	if (!wilc->initialized) {480		tx_complete_fn(priv, 0);481		return 0;482	}483	tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC);484 485	if (!tqe) {486		tx_complete_fn(priv, 0);487		return 0;488	}489	tqe->type = WILC_MGMT_PKT;490	tqe->buffer = buffer;491	tqe->buffer_size = buffer_size;492	tqe->tx_complete_func = tx_complete_fn;493	tqe->priv = priv;494	tqe->q_num = AC_BE_Q;495	tqe->ack_idx = NOT_TCP_ACK;496	tqe->vif = vif;497	wilc_wlan_txq_add_to_tail(dev, AC_VO_Q, tqe);498	return 1;499}500 501static struct txq_entry_t *wilc_wlan_txq_get_first(struct wilc *wilc, u8 q_num)502{503	struct txq_entry_t *tqe = NULL;504	unsigned long flags;505 506	spin_lock_irqsave(&wilc->txq_spinlock, flags);507 508	if (!list_empty(&wilc->txq[q_num].txq_head.list))509		tqe = list_first_entry(&wilc->txq[q_num].txq_head.list,510				       struct txq_entry_t, list);511 512	spin_unlock_irqrestore(&wilc->txq_spinlock, flags);513 514	return tqe;515}516 517static struct txq_entry_t *wilc_wlan_txq_get_next(struct wilc *wilc,518						  struct txq_entry_t *tqe,519						  u8 q_num)520{521	unsigned long flags;522 523	spin_lock_irqsave(&wilc->txq_spinlock, flags);524 525	if (!list_is_last(&tqe->list, &wilc->txq[q_num].txq_head.list))526		tqe = list_next_entry(tqe, list);527	else528		tqe = NULL;529	spin_unlock_irqrestore(&wilc->txq_spinlock, flags);530 531	return tqe;532}533 534static void wilc_wlan_rxq_add(struct wilc *wilc, struct rxq_entry_t *rqe)535{536	if (wilc->quit)537		return;538 539	mutex_lock(&wilc->rxq_cs);540	list_add_tail(&rqe->list, &wilc->rxq_head.list);541	mutex_unlock(&wilc->rxq_cs);542}543 544static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc)545{546	struct rxq_entry_t *rqe = NULL;547 548	mutex_lock(&wilc->rxq_cs);549	if (!list_empty(&wilc->rxq_head.list)) {550		rqe = list_first_entry(&wilc->rxq_head.list, struct rxq_entry_t,551				       list);552		list_del(&rqe->list);553	}554	mutex_unlock(&wilc->rxq_cs);555	return rqe;556}557 558void chip_allow_sleep(struct wilc *wilc)559{560	u32 reg = 0;561	const struct wilc_hif_func *hif_func = wilc->hif_func;562	u32 wakeup_reg, wakeup_bit;563	u32 to_host_from_fw_reg, to_host_from_fw_bit;564	u32 from_host_to_fw_reg, from_host_to_fw_bit;565	u32 trials = 100;566	int ret;567 568	if (wilc->io_type == WILC_HIF_SDIO) {569		wakeup_reg = WILC_SDIO_WAKEUP_REG;570		wakeup_bit = WILC_SDIO_WAKEUP_BIT;571		from_host_to_fw_reg = WILC_SDIO_HOST_TO_FW_REG;572		from_host_to_fw_bit = WILC_SDIO_HOST_TO_FW_BIT;573		to_host_from_fw_reg = WILC_SDIO_FW_TO_HOST_REG;574		to_host_from_fw_bit = WILC_SDIO_FW_TO_HOST_BIT;575	} else {576		wakeup_reg = WILC_SPI_WAKEUP_REG;577		wakeup_bit = WILC_SPI_WAKEUP_BIT;578		from_host_to_fw_reg = WILC_SPI_HOST_TO_FW_REG;579		from_host_to_fw_bit = WILC_SPI_HOST_TO_FW_BIT;580		to_host_from_fw_reg = WILC_SPI_FW_TO_HOST_REG;581		to_host_from_fw_bit = WILC_SPI_FW_TO_HOST_BIT;582	}583 584	while (--trials) {585		ret = hif_func->hif_read_reg(wilc, to_host_from_fw_reg, &reg);586		if (ret)587			return;588		if ((reg & to_host_from_fw_bit) == 0)589			break;590	}591	if (!trials)592		pr_warn("FW not responding\n");593 594	/* Clear bit 1 */595	ret = hif_func->hif_read_reg(wilc, wakeup_reg, &reg);596	if (ret)597		return;598	if (reg & wakeup_bit) {599		reg &= ~wakeup_bit;600		ret = hif_func->hif_write_reg(wilc, wakeup_reg, reg);601		if (ret)602			return;603	}604 605	ret = hif_func->hif_read_reg(wilc, from_host_to_fw_reg, &reg);606	if (ret)607		return;608	if (reg & from_host_to_fw_bit) {609		reg &= ~from_host_to_fw_bit;610		ret = hif_func->hif_write_reg(wilc, from_host_to_fw_reg, reg);611		if (ret)612			return;613 614	}615}616EXPORT_SYMBOL_GPL(chip_allow_sleep);617 618void chip_wakeup(struct wilc *wilc)619{620	u32 ret = 0;621	u32 clk_status_val = 0, trials = 0;622	u32 wakeup_reg, wakeup_bit;623	u32 clk_status_reg, clk_status_bit;624	u32 from_host_to_fw_reg, from_host_to_fw_bit;625	const struct wilc_hif_func *hif_func = wilc->hif_func;626 627	if (wilc->io_type == WILC_HIF_SDIO) {628		wakeup_reg = WILC_SDIO_WAKEUP_REG;629		wakeup_bit = WILC_SDIO_WAKEUP_BIT;630		clk_status_reg = WILC_SDIO_CLK_STATUS_REG;631		clk_status_bit = WILC_SDIO_CLK_STATUS_BIT;632		from_host_to_fw_reg = WILC_SDIO_HOST_TO_FW_REG;633		from_host_to_fw_bit = WILC_SDIO_HOST_TO_FW_BIT;634	} else {635		wakeup_reg = WILC_SPI_WAKEUP_REG;636		wakeup_bit = WILC_SPI_WAKEUP_BIT;637		clk_status_reg = WILC_SPI_CLK_STATUS_REG;638		clk_status_bit = WILC_SPI_CLK_STATUS_BIT;639		from_host_to_fw_reg = WILC_SPI_HOST_TO_FW_REG;640		from_host_to_fw_bit = WILC_SPI_HOST_TO_FW_BIT;641	}642 643	/* indicate host wakeup */644	ret = hif_func->hif_write_reg(wilc, from_host_to_fw_reg,645				      from_host_to_fw_bit);646	if (ret)647		return;648 649	/* Set wake-up bit */650	ret = hif_func->hif_write_reg(wilc, wakeup_reg,651				      wakeup_bit);652	if (ret)653		return;654 655	while (trials < WAKE_UP_TRIAL_RETRY) {656		ret = hif_func->hif_read_reg(wilc, clk_status_reg,657					     &clk_status_val);658		if (ret) {659			pr_err("Bus error %d %x\n", ret, clk_status_val);660			return;661		}662		if (clk_status_val & clk_status_bit)663			break;664 665		trials++;666	}667	if (trials >= WAKE_UP_TRIAL_RETRY) {668		pr_err("Failed to wake-up the chip\n");669		return;670	}671	/* Sometimes spi fail to read clock regs after reading672	 * writing clockless registers673	 */674	if (wilc->io_type == WILC_HIF_SPI)675		wilc->hif_func->hif_reset(wilc);676}677EXPORT_SYMBOL_GPL(chip_wakeup);678 679void host_wakeup_notify(struct wilc *wilc)680{681	acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);682	wilc->hif_func->hif_write_reg(wilc, WILC_CORTUS_INTERRUPT_2, 1);683	release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);684}685EXPORT_SYMBOL_GPL(host_wakeup_notify);686 687void host_sleep_notify(struct wilc *wilc)688{689	acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);690	wilc->hif_func->hif_write_reg(wilc, WILC_CORTUS_INTERRUPT_1, 1);691	release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);692}693EXPORT_SYMBOL_GPL(host_sleep_notify);694 695int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)696{697	int i, entries = 0;698	u8 k, ac;699	u32 sum;700	u32 reg;701	u8 ac_desired_ratio[NQUEUES] = {0, 0, 0, 0};702	u8 ac_preserve_ratio[NQUEUES] = {1, 1, 1, 1};703	u8 *num_pkts_to_add;704	u8 vmm_entries_ac[WILC_VMM_TBL_SIZE];705	u32 offset = 0;706	bool max_size_over = 0, ac_exist = 0;707	int vmm_sz = 0;708	struct txq_entry_t *tqe_q[NQUEUES];709	int ret = 0;710	int counter;711	int timeout;712	u32 *vmm_table = wilc->vmm_table;713	u8 ac_pkt_num_to_chip[NQUEUES] = {0, 0, 0, 0};714	const struct wilc_hif_func *func;715	int srcu_idx;716	u8 *txb = wilc->tx_buffer;717	struct wilc_vif *vif;718 719	if (wilc->quit)720		goto out_update_cnt;721 722	if (ac_balance(wilc, ac_desired_ratio))723		return -EINVAL;724 725	mutex_lock(&wilc->txq_add_to_head_cs);726 727	srcu_idx = srcu_read_lock(&wilc->srcu);728	wilc_for_each_vif(wilc, vif)729		wilc_wlan_txq_filter_dup_tcp_ack(vif->ndev);730	srcu_read_unlock(&wilc->srcu, srcu_idx);731 732	for (ac = 0; ac < NQUEUES; ac++)733		tqe_q[ac] = wilc_wlan_txq_get_first(wilc, ac);734 735	i = 0;736	sum = 0;737	max_size_over = 0;738	num_pkts_to_add = ac_desired_ratio;739	do {740		ac_exist = 0;741		for (ac = 0; (ac < NQUEUES) && (!max_size_over); ac++) {742			if (!tqe_q[ac])743				continue;744 745			ac_exist = 1;746			for (k = 0; (k < num_pkts_to_add[ac]) &&747			     (!max_size_over) && tqe_q[ac]; k++) {748				if (i >= (WILC_VMM_TBL_SIZE - 1)) {749					max_size_over = 1;750					break;751				}752 753				if (tqe_q[ac]->type == WILC_CFG_PKT)754					vmm_sz = ETH_CONFIG_PKT_HDR_OFFSET;755				else if (tqe_q[ac]->type == WILC_NET_PKT)756					vmm_sz = ETH_ETHERNET_HDR_OFFSET;757				else758					vmm_sz = HOST_HDR_OFFSET;759 760				vmm_sz += tqe_q[ac]->buffer_size;761				vmm_sz = ALIGN(vmm_sz, 4);762 763				if ((sum + vmm_sz) > WILC_TX_BUFF_SIZE) {764					max_size_over = 1;765					break;766				}767				vmm_table[i] = vmm_sz / 4;768				if (tqe_q[ac]->type == WILC_CFG_PKT)769					vmm_table[i] |= BIT(10);770 771				cpu_to_le32s(&vmm_table[i]);772				vmm_entries_ac[i] = ac;773 774				i++;775				sum += vmm_sz;776				tqe_q[ac] = wilc_wlan_txq_get_next(wilc,777								   tqe_q[ac],778								   ac);779			}780		}781		num_pkts_to_add = ac_preserve_ratio;782	} while (!max_size_over && ac_exist);783 784	if (i == 0)785		goto out_unlock;786	vmm_table[i] = 0x0;787 788	acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);789	counter = 0;790	func = wilc->hif_func;791	do {792		ret = func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, &reg);793		if (ret)794			break;795 796		if ((reg & 0x1) == 0) {797			ac_update_fw_ac_pkt_info(wilc, reg);798			break;799		}800 801		counter++;802		if (counter > 200) {803			counter = 0;804			ret = func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, 0);805			break;806		}807	} while (!wilc->quit);808 809	if (ret)810		goto out_release_bus;811 812	timeout = 200;813	do {814		ret = func->hif_block_tx(wilc,815					 WILC_VMM_TBL_RX_SHADOW_BASE,816					 (u8 *)vmm_table,817					 ((i + 1) * 4));818		if (ret)819			break;820 821		ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x2);822		if (ret)823			break;824 825		do {826			ret = func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, &reg);827			if (ret)828				break;829			if (FIELD_GET(WILC_VMM_ENTRY_AVAILABLE, reg)) {830				entries = FIELD_GET(WILC_VMM_ENTRY_COUNT, reg);831				break;832			}833		} while (--timeout);834		if (timeout <= 0) {835			ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x0);836			break;837		}838 839		if (ret)840			break;841 842		if (entries == 0) {843			ret = func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, &reg);844			if (ret)845				break;846			reg &= ~BIT(0);847			ret = func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, reg);848		}849	} while (0);850 851	if (ret)852		goto out_release_bus;853 854	if (entries == 0) {855		/*856		 * No VMM space available in firmware so retry to transmit857		 * the packet from tx queue.858		 */859		ret = WILC_VMM_ENTRY_FULL_RETRY;860		goto out_release_bus;861	}862 863	release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);864 865	offset = 0;866	i = 0;867	do {868		struct txq_entry_t *tqe;869		u32 header, buffer_offset;870		char *bssid;871		u8 mgmt_ptk = 0;872 873		if (vmm_table[i] == 0 || vmm_entries_ac[i] >= NQUEUES)874			break;875 876		tqe = wilc_wlan_txq_remove_from_head(wilc, vmm_entries_ac[i]);877		if (!tqe)878			break;879 880		ac_pkt_num_to_chip[vmm_entries_ac[i]]++;881		vif = tqe->vif;882 883		le32_to_cpus(&vmm_table[i]);884		vmm_sz = FIELD_GET(WILC_VMM_BUFFER_SIZE, vmm_table[i]);885		vmm_sz *= 4;886 887		if (tqe->type == WILC_MGMT_PKT)888			mgmt_ptk = 1;889 890		header = (FIELD_PREP(WILC_VMM_HDR_TYPE, tqe->type) |891			  FIELD_PREP(WILC_VMM_HDR_MGMT_FIELD, mgmt_ptk) |892			  FIELD_PREP(WILC_VMM_HDR_PKT_SIZE, tqe->buffer_size) |893			  FIELD_PREP(WILC_VMM_HDR_BUFF_SIZE, vmm_sz));894 895		cpu_to_le32s(&header);896		memcpy(&txb[offset], &header, 4);897		if (tqe->type == WILC_CFG_PKT) {898			buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET;899		} else if (tqe->type == WILC_NET_PKT) {900			int prio = tqe->q_num;901 902			bssid = tqe->vif->bssid;903			buffer_offset = ETH_ETHERNET_HDR_OFFSET;904			memcpy(&txb[offset + 4], &prio, sizeof(prio));905			memcpy(&txb[offset + 8], bssid, 6);906		} else {907			buffer_offset = HOST_HDR_OFFSET;908		}909 910		memcpy(&txb[offset + buffer_offset],911		       tqe->buffer, tqe->buffer_size);912		offset += vmm_sz;913		i++;914		tqe->status = 1;915		if (tqe->tx_complete_func)916			tqe->tx_complete_func(tqe->priv, tqe->status);917		if (tqe->ack_idx != NOT_TCP_ACK &&918		    tqe->ack_idx < MAX_PENDING_ACKS)919			vif->ack_filter.pending_acks[tqe->ack_idx].txqe = NULL;920		kfree(tqe);921	} while (--entries);922	for (i = 0; i < NQUEUES; i++)923		wilc->txq[i].fw.count += ac_pkt_num_to_chip[i];924 925	acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);926 927	ret = func->hif_clear_int_ext(wilc, ENABLE_TX_VMM);928	if (ret)929		goto out_release_bus;930 931	ret = func->hif_block_tx_ext(wilc, 0, txb, offset);932 933out_release_bus:934	release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);935 936out_unlock:937	mutex_unlock(&wilc->txq_add_to_head_cs);938 939out_update_cnt:940	*txq_count = wilc->txq_entries;941	return ret;942}943 944static void wilc_wlan_handle_rx_buff(struct wilc *wilc, u8 *buffer, int size)945{946	int offset = 0;947	u32 header;948	u32 pkt_len, pkt_offset, tp_len;949	int is_cfg_packet;950	u8 *buff_ptr;951 952	do {953		buff_ptr = buffer + offset;954		header = get_unaligned_le32(buff_ptr);955 956		is_cfg_packet = FIELD_GET(WILC_PKT_HDR_CONFIG_FIELD, header);957		pkt_offset = FIELD_GET(WILC_PKT_HDR_OFFSET_FIELD, header);958		tp_len = FIELD_GET(WILC_PKT_HDR_TOTAL_LEN_FIELD, header);959		pkt_len = FIELD_GET(WILC_PKT_HDR_LEN_FIELD, header);960 961		if (pkt_len == 0 || tp_len == 0)962			break;963 964		if (pkt_offset & IS_MANAGMEMENT) {965			buff_ptr += HOST_HDR_OFFSET;966			wilc_wfi_mgmt_rx(wilc, buff_ptr, pkt_len,967					 pkt_offset & IS_MGMT_AUTH_PKT);968		} else {969			if (!is_cfg_packet) {970				wilc_frmw_to_host(wilc, buff_ptr, pkt_len,971						  pkt_offset);972			} else {973				struct wilc_cfg_rsp rsp;974 975				buff_ptr += pkt_offset;976 977				wilc_wlan_cfg_indicate_rx(wilc, buff_ptr,978							  pkt_len,979							  &rsp);980				if (rsp.type == WILC_CFG_RSP) {981					if (wilc->cfg_seq_no == rsp.seq_no)982						complete(&wilc->cfg_event);983				} else if (rsp.type == WILC_CFG_RSP_STATUS) {984					wilc_mac_indicate(wilc);985				}986			}987		}988		offset += tp_len;989	} while (offset < size);990}991 992static void wilc_wlan_handle_rxq(struct wilc *wilc)993{994	int size;995	u8 *buffer;996	struct rxq_entry_t *rqe;997 998	while (!wilc->quit) {999		rqe = wilc_wlan_rxq_remove(wilc);1000		if (!rqe)1001			break;1002 1003		buffer = rqe->buffer;1004		size = rqe->buffer_size;1005		wilc_wlan_handle_rx_buff(wilc, buffer, size);1006 1007		kfree(rqe);1008	}1009	if (wilc->quit)1010		complete(&wilc->cfg_event);1011}1012 1013static void wilc_unknown_isr_ext(struct wilc *wilc)1014{1015	wilc->hif_func->hif_clear_int_ext(wilc, 0);1016}1017 1018static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status)1019{1020	u32 offset = wilc->rx_buffer_offset;1021	u8 *buffer = NULL;1022	u32 size;1023	u32 retries = 0;1024	int ret = 0;1025	struct rxq_entry_t *rqe;1026 1027	size = FIELD_GET(WILC_INTERRUPT_DATA_SIZE, int_status) << 2;1028 1029	while (!size && retries < 10) {1030		wilc->hif_func->hif_read_size(wilc, &size);1031		size = FIELD_GET(WILC_INTERRUPT_DATA_SIZE, size) << 2;1032		retries++;1033	}1034 1035	if (size <= 0)1036		return;1037 1038	if (WILC_RX_BUFF_SIZE - offset < size)1039		offset = 0;1040 1041	buffer = &wilc->rx_buffer[offset];1042 1043	wilc->hif_func->hif_clear_int_ext(wilc, DATA_INT_CLR | ENABLE_RX_VMM);1044	ret = wilc->hif_func->hif_block_rx_ext(wilc, 0, buffer, size);1045	if (ret)1046		return;1047 1048	offset += size;1049	wilc->rx_buffer_offset = offset;1050	rqe = kmalloc(sizeof(*rqe), GFP_KERNEL);1051	if (!rqe)1052		return;1053 1054	rqe->buffer = buffer;1055	rqe->buffer_size = size;1056	wilc_wlan_rxq_add(wilc, rqe);1057	wilc_wlan_handle_rxq(wilc);1058}1059 1060void wilc_handle_isr(struct wilc *wilc)1061{1062	u32 int_status;1063 1064	acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);1065	wilc->hif_func->hif_read_int(wilc, &int_status);1066 1067	if (int_status & DATA_INT_EXT)1068		wilc_wlan_handle_isr_ext(wilc, int_status);1069 1070	if (!(int_status & (ALL_INT_EXT)))1071		wilc_unknown_isr_ext(wilc);1072 1073	release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);1074}1075EXPORT_SYMBOL_GPL(wilc_handle_isr);1076 1077int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,1078				u32 buffer_size)1079{1080	u32 offset;1081	u32 addr, size, size2, blksz;1082	u8 *dma_buffer;1083	int ret = 0;1084	u32 reg = 0;1085 1086	blksz = BIT(12);1087 1088	dma_buffer = kmalloc(blksz, GFP_KERNEL);1089	if (!dma_buffer)1090		return -EIO;1091 1092	offset = 0;1093	pr_debug("%s: Downloading firmware size = %d\n", __func__, buffer_size);1094 1095	acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);1096 1097	wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);1098	reg &= ~BIT(10);1099	ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg);1100	wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);1101	if (reg & BIT(10))1102		pr_err("%s: Failed to reset\n", __func__);1103 1104	release_bus(wilc, WILC_BUS_RELEASE_ONLY);1105	do {1106		addr = get_unaligned_le32(&buffer[offset]);1107		size = get_unaligned_le32(&buffer[offset + 4]);1108		acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);1109		offset += 8;1110		while (((int)size) && (offset < buffer_size)) {1111			if (size <= blksz)1112				size2 = size;1113			else1114				size2 = blksz;1115 1116			memcpy(dma_buffer, &buffer[offset], size2);1117			ret = wilc->hif_func->hif_block_tx(wilc, addr,1118							   dma_buffer, size2);1119			if (ret)1120				break;1121 1122			addr += size2;1123			offset += size2;1124			size -= size2;1125		}1126		release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);1127 1128		if (ret) {1129			pr_err("%s Bus error\n", __func__);1130			goto fail;1131		}1132		pr_debug("%s Offset = %d\n", __func__, offset);1133	} while (offset < buffer_size);1134 1135fail:1136 1137	kfree(dma_buffer);1138 1139	return ret;1140}1141 1142int wilc_wlan_start(struct wilc *wilc)1143{1144	u32 reg = 0;1145	int ret;1146	u32 chipid;1147 1148	if (wilc->io_type == WILC_HIF_SDIO) {1149		reg = 0;1150		reg |= BIT(3);1151	} else if (wilc->io_type == WILC_HIF_SPI) {1152		reg = 1;1153	}1154	acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);1155	ret = wilc->hif_func->hif_write_reg(wilc, WILC_VMM_CORE_CFG, reg);1156	if (ret)1157		goto release;1158 1159	reg = 0;1160	if (wilc->io_type == WILC_HIF_SDIO && wilc->dev_irq_num)1161		reg |= WILC_HAVE_SDIO_IRQ_GPIO;1162 1163	ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_1, reg);1164	if (ret)1165		goto release;1166 1167	wilc->hif_func->hif_sync_ext(wilc, NUM_INT_EXT);1168 1169	ret = wilc->hif_func->hif_read_reg(wilc, WILC_CHIPID, &chipid);1170	if (ret)1171		goto release;1172 1173	wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);1174	if ((reg & BIT(10)) == BIT(10)) {1175		reg &= ~BIT(10);1176		wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg);1177		wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);1178	}1179 1180	reg |= BIT(10);1181	ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg);1182	wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);1183 1184release:1185	release_bus(wilc, WILC_BUS_RELEASE_ONLY);1186	return ret;1187}1188 1189int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif)1190{1191	u32 reg = 0;1192	int ret;1193 1194	acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);1195 1196	ret = wilc->hif_func->hif_read_reg(wilc, GLOBAL_MODE_CONTROL, &reg);1197	if (ret)1198		goto release;1199 1200	reg &= ~WILC_GLOBAL_MODE_ENABLE_WIFI;1201	ret = wilc->hif_func->hif_write_reg(wilc, GLOBAL_MODE_CONTROL, reg);1202	if (ret)1203		goto release;1204 1205	ret = wilc->hif_func->hif_read_reg(wilc, PWR_SEQ_MISC_CTRL, &reg);1206	if (ret)1207		goto release;1208 1209	reg &= ~WILC_PWR_SEQ_ENABLE_WIFI_SLEEP;1210	ret = wilc->hif_func->hif_write_reg(wilc, PWR_SEQ_MISC_CTRL, reg);1211	if (ret)1212		goto release;1213 1214	ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, &reg);1215	if (ret) {1216		netdev_err(vif->ndev, "Error while reading reg\n");1217		goto release;1218	}1219 1220	ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0,1221					(reg | WILC_ABORT_REQ_BIT));1222	if (ret) {1223		netdev_err(vif->ndev, "Error while writing reg\n");1224		goto release;1225	}1226 1227	ret = 0;1228release:1229	/* host comm is disabled - we can't issue sleep command anymore: */1230	release_bus(wilc, WILC_BUS_RELEASE_ONLY);1231 1232	return ret;1233}1234 1235void wilc_wlan_cleanup(struct net_device *dev)1236{1237	struct txq_entry_t *tqe;1238	struct rxq_entry_t *rqe;1239	u8 ac;1240	struct wilc_vif *vif = netdev_priv(dev);1241	struct wilc *wilc = vif->wilc;1242 1243	wilc->quit = 1;1244	for (ac = 0; ac < NQUEUES; ac++) {1245		while ((tqe = wilc_wlan_txq_remove_from_head(wilc, ac))) {1246			if (tqe->tx_complete_func)1247				tqe->tx_complete_func(tqe->priv, 0);1248			kfree(tqe);1249		}1250	}1251 1252	while ((rqe = wilc_wlan_rxq_remove(wilc)))1253		kfree(rqe);1254 1255	kfree(wilc->vmm_table);1256	wilc->vmm_table = NULL;1257	kfree(wilc->rx_buffer);1258	wilc->rx_buffer = NULL;1259	kfree(wilc->tx_buffer);1260	wilc->tx_buffer = NULL;1261	wilc->hif_func->hif_deinit(wilc);1262}1263 1264static int wilc_wlan_cfg_commit(struct wilc_vif *vif, int type,1265				u32 drv_handler)1266{1267	struct wilc *wilc = vif->wilc;1268	struct wilc_cfg_frame *cfg = &wilc->cfg_frame;1269	int t_len = wilc->cfg_frame_offset + sizeof(struct wilc_cfg_cmd_hdr);1270 1271	if (type == WILC_CFG_SET)1272		cfg->hdr.cmd_type = 'W';1273	else1274		cfg->hdr.cmd_type = 'Q';1275 1276	cfg->hdr.seq_no = wilc->cfg_seq_no % 256;1277	cfg->hdr.total_len = cpu_to_le16(t_len);1278	cfg->hdr.driver_handler = cpu_to_le32(drv_handler);1279	wilc->cfg_seq_no = cfg->hdr.seq_no;1280 1281	if (!wilc_wlan_txq_add_cfg_pkt(vif, (u8 *)&cfg->hdr, t_len))1282		return -1;1283 1284	return 0;1285}1286 1287int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer,1288		      u32 buffer_size, int commit, u32 drv_handler)1289{1290	u32 offset;1291	int ret_size;1292	struct wilc *wilc = vif->wilc;1293 1294	mutex_lock(&wilc->cfg_cmd_lock);1295 1296	if (start)1297		wilc->cfg_frame_offset = 0;1298 1299	offset = wilc->cfg_frame_offset;1300	ret_size = wilc_wlan_cfg_set_wid(wilc->cfg_frame.frame, offset,1301					 wid, buffer, buffer_size);1302	offset += ret_size;1303	wilc->cfg_frame_offset = offset;1304 1305	if (!commit) {1306		mutex_unlock(&wilc->cfg_cmd_lock);1307		return ret_size;1308	}1309 1310	netdev_dbg(vif->ndev, "%s: seqno[%d]\n", __func__, wilc->cfg_seq_no);1311 1312	if (wilc_wlan_cfg_commit(vif, WILC_CFG_SET, drv_handler))1313		ret_size = 0;1314 1315	if (!wait_for_completion_timeout(&wilc->cfg_event,1316					 WILC_CFG_PKTS_TIMEOUT)) {1317		netdev_dbg(vif->ndev, "%s: Timed Out\n", __func__);1318		ret_size = 0;1319	}1320 1321	wilc->cfg_frame_offset = 0;1322	wilc->cfg_seq_no += 1;1323	mutex_unlock(&wilc->cfg_cmd_lock);1324 1325	return ret_size;1326}1327 1328int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit,1329		      u32 drv_handler)1330{1331	u32 offset;1332	int ret_size;1333	struct wilc *wilc = vif->wilc;1334 1335	mutex_lock(&wilc->cfg_cmd_lock);1336 1337	if (start)1338		wilc->cfg_frame_offset = 0;1339 1340	offset = wilc->cfg_frame_offset;1341	ret_size = wilc_wlan_cfg_get_wid(wilc->cfg_frame.frame, offset, wid);1342	offset += ret_size;1343	wilc->cfg_frame_offset = offset;1344 1345	if (!commit) {1346		mutex_unlock(&wilc->cfg_cmd_lock);1347		return ret_size;1348	}1349 1350	if (wilc_wlan_cfg_commit(vif, WILC_CFG_QUERY, drv_handler))1351		ret_size = 0;1352 1353	if (!wait_for_completion_timeout(&wilc->cfg_event,1354					 WILC_CFG_PKTS_TIMEOUT)) {1355		netdev_dbg(vif->ndev, "%s: Timed Out\n", __func__);1356		ret_size = 0;1357	}1358	wilc->cfg_frame_offset = 0;1359	wilc->cfg_seq_no += 1;1360	mutex_unlock(&wilc->cfg_cmd_lock);1361 1362	return ret_size;1363}1364 1365int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids,1366			 u32 count)1367{1368	int i;1369	int ret = 0;1370	u32 drv = wilc_get_vif_idx(vif);1371 1372	if (mode == WILC_GET_CFG) {1373		for (i = 0; i < count; i++) {1374			if (!wilc_wlan_cfg_get(vif, !i,1375					       wids[i].id,1376					       (i == count - 1),1377					       drv)) {1378				ret = -ETIMEDOUT;1379				break;1380			}1381		}1382		for (i = 0; i < count; i++) {1383			wids[i].size = wilc_wlan_cfg_get_val(vif->wilc,1384							     wids[i].id,1385							     wids[i].val,1386							     wids[i].size);1387		}1388	} else if (mode == WILC_SET_CFG) {1389		for (i = 0; i < count; i++) {1390			if (!wilc_wlan_cfg_set(vif, !i,1391					       wids[i].id,1392					       wids[i].val,1393					       wids[i].size,1394					       (i == count - 1),1395					       drv)) {1396				ret = -ETIMEDOUT;1397				break;1398			}1399		}1400	}1401 1402	return ret;1403}1404 1405static int init_chip(struct net_device *dev)1406{1407	u32 chipid;1408	u32 reg;1409	int ret = 0;1410	struct wilc_vif *vif = netdev_priv(dev);1411	struct wilc *wilc = vif->wilc;1412 1413	acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);1414 1415	chipid = wilc_get_chipid(wilc, true);1416 1417	if ((chipid & 0xfff) != 0xa0) {1418		ret = wilc->hif_func->hif_read_reg(wilc,1419						   WILC_CORTUS_RESET_MUX_SEL,1420						   &reg);1421		if (ret) {1422			netdev_err(dev, "fail read reg 0x1118\n");1423			goto release;1424		}1425		reg |= BIT(0);1426		ret = wilc->hif_func->hif_write_reg(wilc,1427						    WILC_CORTUS_RESET_MUX_SEL,1428						    reg);1429		if (ret) {1430			netdev_err(dev, "fail write reg 0x1118\n");1431			goto release;1432		}1433		ret = wilc->hif_func->hif_write_reg(wilc,1434						    WILC_CORTUS_BOOT_REGISTER,1435						    WILC_CORTUS_BOOT_FROM_IRAM);1436		if (ret) {1437			netdev_err(dev, "fail write reg 0xc0000\n");1438			goto release;1439		}1440	}1441 1442release:1443	release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);1444 1445	return ret;1446}1447 1448u32 wilc_get_chipid(struct wilc *wilc, bool update)1449{1450	u32 chipid = 0;1451	u32 rfrevid = 0;1452 1453	if (wilc->chipid == 0 || update) {1454		wilc->hif_func->hif_read_reg(wilc, WILC_CHIPID, &chipid);1455		wilc->hif_func->hif_read_reg(wilc, WILC_RF_REVISION_ID,1456					     &rfrevid);1457		if (!is_wilc1000(chipid)) {1458			wilc->chipid = 0;1459			return wilc->chipid;1460		}1461		if (chipid == WILC_1000_BASE_ID_2A) { /* 0x1002A0 */1462			if (rfrevid != 0x1)1463				chipid = WILC_1000_BASE_ID_2A_REV1;1464		} else if (chipid == WILC_1000_BASE_ID_2B) { /* 0x1002B0 */1465			if (rfrevid == 0x4)1466				chipid = WILC_1000_BASE_ID_2B_REV1;1467			else if (rfrevid != 0x3)1468				chipid = WILC_1000_BASE_ID_2B_REV2;1469		}1470 1471		wilc->chipid = chipid;1472	}1473	return wilc->chipid;1474}1475 1476int wilc_load_mac_from_nv(struct wilc *wl)1477{1478	int ret = -EINVAL;1479	unsigned int i;1480 1481	acquire_bus(wl, WILC_BUS_ACQUIRE_AND_WAKEUP);1482 1483	for (i = 0; i < WILC_NVMEM_MAX_NUM_BANK; i++) {1484		int bank_offset = get_bank_offset_from_bank_index(i);1485		u32 reg1, reg2;1486		u8 invalid;1487		u8 used;1488 1489		ret = wl->hif_func->hif_read_reg(wl,1490						 WILC_NVMEM_BANK_BASE + bank_offset,1491						 &reg1);1492		if (ret) {1493			pr_err("Can not read address %d lower part", i);1494			break;1495		}1496		ret = wl->hif_func->hif_read_reg(wl,1497						 WILC_NVMEM_BANK_BASE + bank_offset + 4,1498						 &reg2);1499		if (ret) {1500			pr_err("Can not read address %d upper part", i);1501			break;1502		}1503 1504		used = FIELD_GET(WILC_NVMEM_IS_BANK_USED, reg1);1505		invalid = FIELD_GET(WILC_NVMEM_IS_BANK_INVALID, reg1);1506		if (!used || invalid)1507			continue;1508 1509		wl->nv_mac_address[0] = FIELD_GET(GENMASK(23, 16), reg1);1510		wl->nv_mac_address[1] = FIELD_GET(GENMASK(15, 8), reg1);1511		wl->nv_mac_address[2] = FIELD_GET(GENMASK(7, 0), reg1);1512		wl->nv_mac_address[3] = FIELD_GET(GENMASK(31, 24), reg2);1513		wl->nv_mac_address[4] = FIELD_GET(GENMASK(23, 16), reg2);1514		wl->nv_mac_address[5] = FIELD_GET(GENMASK(15, 8), reg2);1515 1516		ret = 0;1517		break;1518	}1519 1520	release_bus(wl, WILC_BUS_RELEASE_ALLOW_SLEEP);1521	return ret;1522}1523EXPORT_SYMBOL_GPL(wilc_load_mac_from_nv);1524 1525int wilc_wlan_init(struct net_device *dev)1526{1527	int ret = 0;1528	struct wilc_vif *vif = netdev_priv(dev);1529	struct wilc *wilc;1530 1531	wilc = vif->wilc;1532 1533	wilc->quit = 0;1534 1535	if (!wilc->hif_func->hif_is_init(wilc)) {1536		acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);1537		ret = wilc->hif_func->hif_init(wilc, false);1538		release_bus(wilc, WILC_BUS_RELEASE_ONLY);1539		if (ret)1540			goto fail;1541	}1542 1543	if (!wilc->vmm_table)1544		wilc->vmm_table = kcalloc(WILC_VMM_TBL_SIZE, sizeof(u32), GFP_KERNEL);1545 1546	if (!wilc->vmm_table) {1547		ret = -ENOBUFS;1548		goto fail;1549	}1550 1551	if (!wilc->tx_buffer)1552		wilc->tx_buffer = kmalloc(WILC_TX_BUFF_SIZE, GFP_KERNEL);1553 1554	if (!wilc->tx_buffer) {1555		ret = -ENOBUFS;1556		goto fail;1557	}1558 1559	if (!wilc->rx_buffer)1560		wilc->rx_buffer = kmalloc(WILC_RX_BUFF_SIZE, GFP_KERNEL);1561 1562	if (!wilc->rx_buffer) {1563		ret = -ENOBUFS;1564		goto fail;1565	}1566 1567	if (init_chip(dev)) {1568		ret = -EIO;1569		goto fail;1570	}1571 1572	return 0;1573 1574fail:1575	kfree(wilc->vmm_table);1576	wilc->vmm_table = NULL;1577	kfree(wilc->rx_buffer);1578	wilc->rx_buffer = NULL;1579	kfree(wilc->tx_buffer);1580	wilc->tx_buffer = NULL;1581 1582	return ret;1583}1584