cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

wlan.c (34857B)


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