Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
0004  * All rights reserved.
0005  */
0006 
0007 #include <linux/if_ether.h>
0008 #include <linux/ip.h>
0009 #include <net/dsfield.h>
0010 #include "cfg80211.h"
0011 #include "wlan_cfg.h"
0012 
0013 #define WAKE_UP_TRIAL_RETRY     10000
0014 
0015 static inline bool is_wilc1000(u32 id)
0016 {
0017     return (id & (~WILC_CHIP_REV_FIELD)) == WILC_1000_BASE_ID;
0018 }
0019 
0020 static inline void acquire_bus(struct wilc *wilc, enum bus_acquire acquire)
0021 {
0022     mutex_lock(&wilc->hif_cs);
0023     if (acquire == WILC_BUS_ACQUIRE_AND_WAKEUP && wilc->power_save_mode)
0024         chip_wakeup(wilc);
0025 }
0026 
0027 static inline void release_bus(struct wilc *wilc, enum bus_release release)
0028 {
0029     if (release == WILC_BUS_RELEASE_ALLOW_SLEEP && wilc->power_save_mode)
0030         chip_allow_sleep(wilc);
0031     mutex_unlock(&wilc->hif_cs);
0032 }
0033 
0034 static void wilc_wlan_txq_remove(struct wilc *wilc, u8 q_num,
0035                  struct txq_entry_t *tqe)
0036 {
0037     list_del(&tqe->list);
0038     wilc->txq_entries -= 1;
0039     wilc->txq[q_num].count--;
0040 }
0041 
0042 static struct txq_entry_t *
0043 wilc_wlan_txq_remove_from_head(struct wilc *wilc, u8 q_num)
0044 {
0045     struct txq_entry_t *tqe = NULL;
0046     unsigned long flags;
0047 
0048     spin_lock_irqsave(&wilc->txq_spinlock, flags);
0049 
0050     if (!list_empty(&wilc->txq[q_num].txq_head.list)) {
0051         tqe = list_first_entry(&wilc->txq[q_num].txq_head.list,
0052                        struct txq_entry_t, list);
0053         list_del(&tqe->list);
0054         wilc->txq_entries -= 1;
0055         wilc->txq[q_num].count--;
0056     }
0057     spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
0058     return tqe;
0059 }
0060 
0061 static void wilc_wlan_txq_add_to_tail(struct net_device *dev, u8 q_num,
0062                       struct txq_entry_t *tqe)
0063 {
0064     unsigned long flags;
0065     struct wilc_vif *vif = netdev_priv(dev);
0066     struct wilc *wilc = vif->wilc;
0067 
0068     spin_lock_irqsave(&wilc->txq_spinlock, flags);
0069 
0070     list_add_tail(&tqe->list, &wilc->txq[q_num].txq_head.list);
0071     wilc->txq_entries += 1;
0072     wilc->txq[q_num].count++;
0073 
0074     spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
0075 
0076     complete(&wilc->txq_event);
0077 }
0078 
0079 static void wilc_wlan_txq_add_to_head(struct wilc_vif *vif, u8 q_num,
0080                       struct txq_entry_t *tqe)
0081 {
0082     unsigned long flags;
0083     struct wilc *wilc = vif->wilc;
0084 
0085     mutex_lock(&wilc->txq_add_to_head_cs);
0086 
0087     spin_lock_irqsave(&wilc->txq_spinlock, flags);
0088 
0089     list_add(&tqe->list, &wilc->txq[q_num].txq_head.list);
0090     wilc->txq_entries += 1;
0091     wilc->txq[q_num].count++;
0092 
0093     spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
0094     mutex_unlock(&wilc->txq_add_to_head_cs);
0095     complete(&wilc->txq_event);
0096 }
0097 
0098 #define NOT_TCP_ACK         (-1)
0099 
0100 static inline void add_tcp_session(struct wilc_vif *vif, u32 src_prt,
0101                    u32 dst_prt, u32 seq)
0102 {
0103     struct tcp_ack_filter *f = &vif->ack_filter;
0104 
0105     if (f->tcp_session < 2 * MAX_TCP_SESSION) {
0106         f->ack_session_info[f->tcp_session].seq_num = seq;
0107         f->ack_session_info[f->tcp_session].bigger_ack_num = 0;
0108         f->ack_session_info[f->tcp_session].src_port = src_prt;
0109         f->ack_session_info[f->tcp_session].dst_port = dst_prt;
0110         f->tcp_session++;
0111     }
0112 }
0113 
0114 static inline void update_tcp_session(struct wilc_vif *vif, u32 index, u32 ack)
0115 {
0116     struct tcp_ack_filter *f = &vif->ack_filter;
0117 
0118     if (index < 2 * MAX_TCP_SESSION &&
0119         ack > f->ack_session_info[index].bigger_ack_num)
0120         f->ack_session_info[index].bigger_ack_num = ack;
0121 }
0122 
0123 static inline void add_tcp_pending_ack(struct wilc_vif *vif, u32 ack,
0124                        u32 session_index,
0125                        struct txq_entry_t *txqe)
0126 {
0127     struct tcp_ack_filter *f = &vif->ack_filter;
0128     u32 i = f->pending_base + f->pending_acks_idx;
0129 
0130     if (i < MAX_PENDING_ACKS) {
0131         f->pending_acks[i].ack_num = ack;
0132         f->pending_acks[i].txqe = txqe;
0133         f->pending_acks[i].session_index = session_index;
0134         txqe->ack_idx = i;
0135         f->pending_acks_idx++;
0136     }
0137 }
0138 
0139 static inline void tcp_process(struct net_device *dev, struct txq_entry_t *tqe)
0140 {
0141     void *buffer = tqe->buffer;
0142     const struct ethhdr *eth_hdr_ptr = buffer;
0143     int i;
0144     unsigned long flags;
0145     struct wilc_vif *vif = netdev_priv(dev);
0146     struct wilc *wilc = vif->wilc;
0147     struct tcp_ack_filter *f = &vif->ack_filter;
0148     const struct iphdr *ip_hdr_ptr;
0149     const struct tcphdr *tcp_hdr_ptr;
0150     u32 ihl, total_length, data_offset;
0151 
0152     spin_lock_irqsave(&wilc->txq_spinlock, flags);
0153 
0154     if (eth_hdr_ptr->h_proto != htons(ETH_P_IP))
0155         goto out;
0156 
0157     ip_hdr_ptr = buffer + ETH_HLEN;
0158 
0159     if (ip_hdr_ptr->protocol != IPPROTO_TCP)
0160         goto out;
0161 
0162     ihl = ip_hdr_ptr->ihl << 2;
0163     tcp_hdr_ptr = buffer + ETH_HLEN + ihl;
0164     total_length = ntohs(ip_hdr_ptr->tot_len);
0165 
0166     data_offset = tcp_hdr_ptr->doff << 2;
0167     if (total_length == (ihl + data_offset)) {
0168         u32 seq_no, ack_no;
0169 
0170         seq_no = ntohl(tcp_hdr_ptr->seq);
0171         ack_no = ntohl(tcp_hdr_ptr->ack_seq);
0172         for (i = 0; i < f->tcp_session; i++) {
0173             u32 j = f->ack_session_info[i].seq_num;
0174 
0175             if (i < 2 * MAX_TCP_SESSION &&
0176                 j == seq_no) {
0177                 update_tcp_session(vif, i, ack_no);
0178                 break;
0179             }
0180         }
0181         if (i == f->tcp_session)
0182             add_tcp_session(vif, 0, 0, seq_no);
0183 
0184         add_tcp_pending_ack(vif, ack_no, i, tqe);
0185     }
0186 
0187 out:
0188     spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
0189 }
0190 
0191 static void wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev)
0192 {
0193     struct wilc_vif *vif = netdev_priv(dev);
0194     struct wilc *wilc = vif->wilc;
0195     struct tcp_ack_filter *f = &vif->ack_filter;
0196     u32 i = 0;
0197     u32 dropped = 0;
0198     unsigned long flags;
0199 
0200     spin_lock_irqsave(&wilc->txq_spinlock, flags);
0201     for (i = f->pending_base;
0202          i < (f->pending_base + f->pending_acks_idx); i++) {
0203         u32 index;
0204         u32 bigger_ack_num;
0205 
0206         if (i >= MAX_PENDING_ACKS)
0207             break;
0208 
0209         index = f->pending_acks[i].session_index;
0210 
0211         if (index >= 2 * MAX_TCP_SESSION)
0212             break;
0213 
0214         bigger_ack_num = f->ack_session_info[index].bigger_ack_num;
0215 
0216         if (f->pending_acks[i].ack_num < bigger_ack_num) {
0217             struct txq_entry_t *tqe;
0218 
0219             tqe = f->pending_acks[i].txqe;
0220             if (tqe) {
0221                 wilc_wlan_txq_remove(wilc, tqe->q_num, tqe);
0222                 tqe->status = 1;
0223                 if (tqe->tx_complete_func)
0224                     tqe->tx_complete_func(tqe->priv,
0225                                   tqe->status);
0226                 kfree(tqe);
0227                 dropped++;
0228             }
0229         }
0230     }
0231     f->pending_acks_idx = 0;
0232     f->tcp_session = 0;
0233 
0234     if (f->pending_base == 0)
0235         f->pending_base = MAX_TCP_SESSION;
0236     else
0237         f->pending_base = 0;
0238 
0239     spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
0240 
0241     while (dropped > 0) {
0242         wait_for_completion_timeout(&wilc->txq_event,
0243                         msecs_to_jiffies(1));
0244         dropped--;
0245     }
0246 }
0247 
0248 void wilc_enable_tcp_ack_filter(struct wilc_vif *vif, bool value)
0249 {
0250     vif->ack_filter.enabled = value;
0251 }
0252 
0253 static int wilc_wlan_txq_add_cfg_pkt(struct wilc_vif *vif, u8 *buffer,
0254                      u32 buffer_size)
0255 {
0256     struct txq_entry_t *tqe;
0257     struct wilc *wilc = vif->wilc;
0258 
0259     netdev_dbg(vif->ndev, "Adding config packet ...\n");
0260     if (wilc->quit) {
0261         netdev_dbg(vif->ndev, "Return due to clear function\n");
0262         complete(&wilc->cfg_event);
0263         return 0;
0264     }
0265 
0266     tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC);
0267     if (!tqe) {
0268         complete(&wilc->cfg_event);
0269         return 0;
0270     }
0271 
0272     tqe->type = WILC_CFG_PKT;
0273     tqe->buffer = buffer;
0274     tqe->buffer_size = buffer_size;
0275     tqe->tx_complete_func = NULL;
0276     tqe->priv = NULL;
0277     tqe->q_num = AC_VO_Q;
0278     tqe->ack_idx = NOT_TCP_ACK;
0279     tqe->vif = vif;
0280 
0281     wilc_wlan_txq_add_to_head(vif, AC_VO_Q, tqe);
0282 
0283     return 1;
0284 }
0285 
0286 static bool is_ac_q_limit(struct wilc *wl, u8 q_num)
0287 {
0288     u8 factors[NQUEUES] = {1, 1, 1, 1};
0289     u16 i;
0290     unsigned long flags;
0291     struct wilc_tx_queue_status *q = &wl->tx_q_limit;
0292     u8 end_index;
0293     u8 q_limit;
0294     bool ret = false;
0295 
0296     spin_lock_irqsave(&wl->txq_spinlock, flags);
0297     if (!q->initialized) {
0298         for (i = 0; i < AC_BUFFER_SIZE; i++)
0299             q->buffer[i] = i % NQUEUES;
0300 
0301         for (i = 0; i < NQUEUES; i++) {
0302             q->cnt[i] = AC_BUFFER_SIZE * factors[i] / NQUEUES;
0303             q->sum += q->cnt[i];
0304         }
0305         q->end_index = AC_BUFFER_SIZE - 1;
0306         q->initialized = 1;
0307     }
0308 
0309     end_index = q->end_index;
0310     q->cnt[q->buffer[end_index]] -= factors[q->buffer[end_index]];
0311     q->cnt[q_num] += factors[q_num];
0312     q->sum += (factors[q_num] - factors[q->buffer[end_index]]);
0313 
0314     q->buffer[end_index] = q_num;
0315     if (end_index > 0)
0316         q->end_index--;
0317     else
0318         q->end_index = AC_BUFFER_SIZE - 1;
0319 
0320     if (!q->sum)
0321         q_limit = 1;
0322     else
0323         q_limit = (q->cnt[q_num] * FLOW_CONTROL_UPPER_THRESHOLD / q->sum) + 1;
0324 
0325     if (wl->txq[q_num].count <= q_limit)
0326         ret = true;
0327 
0328     spin_unlock_irqrestore(&wl->txq_spinlock, flags);
0329 
0330     return ret;
0331 }
0332 
0333 static inline u8 ac_classify(struct wilc *wilc, struct sk_buff *skb)
0334 {
0335     u8 q_num = AC_BE_Q;
0336     u8 dscp;
0337 
0338     switch (skb->protocol) {
0339     case htons(ETH_P_IP):
0340         dscp = ipv4_get_dsfield(ip_hdr(skb)) & 0xfc;
0341         break;
0342     case htons(ETH_P_IPV6):
0343         dscp = ipv6_get_dsfield(ipv6_hdr(skb)) & 0xfc;
0344         break;
0345     default:
0346         return q_num;
0347     }
0348 
0349     switch (dscp) {
0350     case 0x08:
0351     case 0x20:
0352     case 0x40:
0353         q_num = AC_BK_Q;
0354         break;
0355     case 0x80:
0356     case 0xA0:
0357     case 0x28:
0358         q_num = AC_VI_Q;
0359         break;
0360     case 0xC0:
0361     case 0xD0:
0362     case 0xE0:
0363     case 0x88:
0364     case 0xB8:
0365         q_num = AC_VO_Q;
0366         break;
0367     }
0368 
0369     return q_num;
0370 }
0371 
0372 static inline int ac_balance(struct wilc *wl, u8 *ratio)
0373 {
0374     u8 i, max_count = 0;
0375 
0376     if (!ratio)
0377         return -EINVAL;
0378 
0379     for (i = 0; i < NQUEUES; i++)
0380         if (wl->txq[i].fw.count > max_count)
0381             max_count = wl->txq[i].fw.count;
0382 
0383     for (i = 0; i < NQUEUES; i++)
0384         ratio[i] = max_count - wl->txq[i].fw.count;
0385 
0386     return 0;
0387 }
0388 
0389 static inline void ac_update_fw_ac_pkt_info(struct wilc *wl, u32 reg)
0390 {
0391     wl->txq[AC_BK_Q].fw.count = FIELD_GET(BK_AC_COUNT_FIELD, reg);
0392     wl->txq[AC_BE_Q].fw.count = FIELD_GET(BE_AC_COUNT_FIELD, reg);
0393     wl->txq[AC_VI_Q].fw.count = FIELD_GET(VI_AC_COUNT_FIELD, reg);
0394     wl->txq[AC_VO_Q].fw.count = FIELD_GET(VO_AC_COUNT_FIELD, reg);
0395 
0396     wl->txq[AC_BK_Q].fw.acm = FIELD_GET(BK_AC_ACM_STAT_FIELD, reg);
0397     wl->txq[AC_BE_Q].fw.acm = FIELD_GET(BE_AC_ACM_STAT_FIELD, reg);
0398     wl->txq[AC_VI_Q].fw.acm = FIELD_GET(VI_AC_ACM_STAT_FIELD, reg);
0399     wl->txq[AC_VO_Q].fw.acm = FIELD_GET(VO_AC_ACM_STAT_FIELD, reg);
0400 }
0401 
0402 static inline u8 ac_change(struct wilc *wilc, u8 *ac)
0403 {
0404     do {
0405         if (wilc->txq[*ac].fw.acm == 0)
0406             return 0;
0407         (*ac)++;
0408     } while (*ac < NQUEUES);
0409 
0410     return 1;
0411 }
0412 
0413 int wilc_wlan_txq_add_net_pkt(struct net_device *dev,
0414                   struct tx_complete_data *tx_data, u8 *buffer,
0415                   u32 buffer_size,
0416                   void (*tx_complete_fn)(void *, int))
0417 {
0418     struct txq_entry_t *tqe;
0419     struct wilc_vif *vif = netdev_priv(dev);
0420     struct wilc *wilc;
0421     u8 q_num;
0422 
0423     wilc = vif->wilc;
0424 
0425     if (wilc->quit) {
0426         tx_complete_fn(tx_data, 0);
0427         return 0;
0428     }
0429 
0430     if (!wilc->initialized) {
0431         tx_complete_fn(tx_data, 0);
0432         return 0;
0433     }
0434 
0435     tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC);
0436 
0437     if (!tqe) {
0438         tx_complete_fn(tx_data, 0);
0439         return 0;
0440     }
0441     tqe->type = WILC_NET_PKT;
0442     tqe->buffer = buffer;
0443     tqe->buffer_size = buffer_size;
0444     tqe->tx_complete_func = tx_complete_fn;
0445     tqe->priv = tx_data;
0446     tqe->vif = vif;
0447 
0448     q_num = ac_classify(wilc, tx_data->skb);
0449     tqe->q_num = q_num;
0450     if (ac_change(wilc, &q_num)) {
0451         tx_complete_fn(tx_data, 0);
0452         kfree(tqe);
0453         return 0;
0454     }
0455 
0456     if (is_ac_q_limit(wilc, q_num)) {
0457         tqe->ack_idx = NOT_TCP_ACK;
0458         if (vif->ack_filter.enabled)
0459             tcp_process(dev, tqe);
0460         wilc_wlan_txq_add_to_tail(dev, q_num, tqe);
0461     } else {
0462         tx_complete_fn(tx_data, 0);
0463         kfree(tqe);
0464     }
0465 
0466     return wilc->txq_entries;
0467 }
0468 
0469 int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer,
0470                    u32 buffer_size,
0471                    void (*tx_complete_fn)(void *, int))
0472 {
0473     struct txq_entry_t *tqe;
0474     struct wilc_vif *vif = netdev_priv(dev);
0475     struct wilc *wilc;
0476 
0477     wilc = vif->wilc;
0478 
0479     if (wilc->quit) {
0480         tx_complete_fn(priv, 0);
0481         return 0;
0482     }
0483 
0484     if (!wilc->initialized) {
0485         tx_complete_fn(priv, 0);
0486         return 0;
0487     }
0488     tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC);
0489 
0490     if (!tqe) {
0491         tx_complete_fn(priv, 0);
0492         return 0;
0493     }
0494     tqe->type = WILC_MGMT_PKT;
0495     tqe->buffer = buffer;
0496     tqe->buffer_size = buffer_size;
0497     tqe->tx_complete_func = tx_complete_fn;
0498     tqe->priv = priv;
0499     tqe->q_num = AC_BE_Q;
0500     tqe->ack_idx = NOT_TCP_ACK;
0501     tqe->vif = vif;
0502     wilc_wlan_txq_add_to_tail(dev, AC_VO_Q, tqe);
0503     return 1;
0504 }
0505 
0506 static struct txq_entry_t *wilc_wlan_txq_get_first(struct wilc *wilc, u8 q_num)
0507 {
0508     struct txq_entry_t *tqe = NULL;
0509     unsigned long flags;
0510 
0511     spin_lock_irqsave(&wilc->txq_spinlock, flags);
0512 
0513     if (!list_empty(&wilc->txq[q_num].txq_head.list))
0514         tqe = list_first_entry(&wilc->txq[q_num].txq_head.list,
0515                        struct txq_entry_t, list);
0516 
0517     spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
0518 
0519     return tqe;
0520 }
0521 
0522 static struct txq_entry_t *wilc_wlan_txq_get_next(struct wilc *wilc,
0523                           struct txq_entry_t *tqe,
0524                           u8 q_num)
0525 {
0526     unsigned long flags;
0527 
0528     spin_lock_irqsave(&wilc->txq_spinlock, flags);
0529 
0530     if (!list_is_last(&tqe->list, &wilc->txq[q_num].txq_head.list))
0531         tqe = list_next_entry(tqe, list);
0532     else
0533         tqe = NULL;
0534     spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
0535 
0536     return tqe;
0537 }
0538 
0539 static void wilc_wlan_rxq_add(struct wilc *wilc, struct rxq_entry_t *rqe)
0540 {
0541     if (wilc->quit)
0542         return;
0543 
0544     mutex_lock(&wilc->rxq_cs);
0545     list_add_tail(&rqe->list, &wilc->rxq_head.list);
0546     mutex_unlock(&wilc->rxq_cs);
0547 }
0548 
0549 static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc)
0550 {
0551     struct rxq_entry_t *rqe = NULL;
0552 
0553     mutex_lock(&wilc->rxq_cs);
0554     if (!list_empty(&wilc->rxq_head.list)) {
0555         rqe = list_first_entry(&wilc->rxq_head.list, struct rxq_entry_t,
0556                        list);
0557         list_del(&rqe->list);
0558     }
0559     mutex_unlock(&wilc->rxq_cs);
0560     return rqe;
0561 }
0562 
0563 void chip_allow_sleep(struct wilc *wilc)
0564 {
0565     u32 reg = 0;
0566     const struct wilc_hif_func *hif_func = wilc->hif_func;
0567     u32 wakeup_reg, wakeup_bit;
0568     u32 to_host_from_fw_reg, to_host_from_fw_bit;
0569     u32 from_host_to_fw_reg, from_host_to_fw_bit;
0570     u32 trials = 100;
0571     int ret;
0572 
0573     if (wilc->io_type == WILC_HIF_SDIO) {
0574         wakeup_reg = WILC_SDIO_WAKEUP_REG;
0575         wakeup_bit = WILC_SDIO_WAKEUP_BIT;
0576         from_host_to_fw_reg = WILC_SDIO_HOST_TO_FW_REG;
0577         from_host_to_fw_bit = WILC_SDIO_HOST_TO_FW_BIT;
0578         to_host_from_fw_reg = WILC_SDIO_FW_TO_HOST_REG;
0579         to_host_from_fw_bit = WILC_SDIO_FW_TO_HOST_BIT;
0580     } else {
0581         wakeup_reg = WILC_SPI_WAKEUP_REG;
0582         wakeup_bit = WILC_SPI_WAKEUP_BIT;
0583         from_host_to_fw_reg = WILC_SPI_HOST_TO_FW_REG;
0584         from_host_to_fw_bit = WILC_SPI_HOST_TO_FW_BIT;
0585         to_host_from_fw_reg = WILC_SPI_FW_TO_HOST_REG;
0586         to_host_from_fw_bit = WILC_SPI_FW_TO_HOST_BIT;
0587     }
0588 
0589     while (--trials) {
0590         ret = hif_func->hif_read_reg(wilc, to_host_from_fw_reg, &reg);
0591         if (ret)
0592             return;
0593         if ((reg & to_host_from_fw_bit) == 0)
0594             break;
0595     }
0596     if (!trials)
0597         pr_warn("FW not responding\n");
0598 
0599     /* Clear bit 1 */
0600     ret = hif_func->hif_read_reg(wilc, wakeup_reg, &reg);
0601     if (ret)
0602         return;
0603     if (reg & wakeup_bit) {
0604         reg &= ~wakeup_bit;
0605         ret = hif_func->hif_write_reg(wilc, wakeup_reg, reg);
0606         if (ret)
0607             return;
0608     }
0609 
0610     ret = hif_func->hif_read_reg(wilc, from_host_to_fw_reg, &reg);
0611     if (ret)
0612         return;
0613     if (reg & from_host_to_fw_bit) {
0614         reg &= ~from_host_to_fw_bit;
0615         ret = hif_func->hif_write_reg(wilc, from_host_to_fw_reg, reg);
0616         if (ret)
0617             return;
0618 
0619     }
0620 }
0621 EXPORT_SYMBOL_GPL(chip_allow_sleep);
0622 
0623 void chip_wakeup(struct wilc *wilc)
0624 {
0625     u32 ret = 0;
0626     u32 clk_status_val = 0, trials = 0;
0627     u32 wakeup_reg, wakeup_bit;
0628     u32 clk_status_reg, clk_status_bit;
0629     u32 from_host_to_fw_reg, from_host_to_fw_bit;
0630     const struct wilc_hif_func *hif_func = wilc->hif_func;
0631 
0632     if (wilc->io_type == WILC_HIF_SDIO) {
0633         wakeup_reg = WILC_SDIO_WAKEUP_REG;
0634         wakeup_bit = WILC_SDIO_WAKEUP_BIT;
0635         clk_status_reg = WILC_SDIO_CLK_STATUS_REG;
0636         clk_status_bit = WILC_SDIO_CLK_STATUS_BIT;
0637         from_host_to_fw_reg = WILC_SDIO_HOST_TO_FW_REG;
0638         from_host_to_fw_bit = WILC_SDIO_HOST_TO_FW_BIT;
0639     } else {
0640         wakeup_reg = WILC_SPI_WAKEUP_REG;
0641         wakeup_bit = WILC_SPI_WAKEUP_BIT;
0642         clk_status_reg = WILC_SPI_CLK_STATUS_REG;
0643         clk_status_bit = WILC_SPI_CLK_STATUS_BIT;
0644         from_host_to_fw_reg = WILC_SPI_HOST_TO_FW_REG;
0645         from_host_to_fw_bit = WILC_SPI_HOST_TO_FW_BIT;
0646     }
0647 
0648     /* indicate host wakeup */
0649     ret = hif_func->hif_write_reg(wilc, from_host_to_fw_reg,
0650                       from_host_to_fw_bit);
0651     if (ret)
0652         return;
0653 
0654     /* Set wake-up bit */
0655     ret = hif_func->hif_write_reg(wilc, wakeup_reg,
0656                       wakeup_bit);
0657     if (ret)
0658         return;
0659 
0660     while (trials < WAKE_UP_TRIAL_RETRY) {
0661         ret = hif_func->hif_read_reg(wilc, clk_status_reg,
0662                          &clk_status_val);
0663         if (ret) {
0664             pr_err("Bus error %d %x\n", ret, clk_status_val);
0665             return;
0666         }
0667         if (clk_status_val & clk_status_bit)
0668             break;
0669 
0670         trials++;
0671     }
0672     if (trials >= WAKE_UP_TRIAL_RETRY) {
0673         pr_err("Failed to wake-up the chip\n");
0674         return;
0675     }
0676     /* Sometimes spi fail to read clock regs after reading
0677      * writing clockless registers
0678      */
0679     if (wilc->io_type == WILC_HIF_SPI)
0680         wilc->hif_func->hif_reset(wilc);
0681 }
0682 EXPORT_SYMBOL_GPL(chip_wakeup);
0683 
0684 void host_wakeup_notify(struct wilc *wilc)
0685 {
0686     acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
0687     wilc->hif_func->hif_write_reg(wilc, WILC_CORTUS_INTERRUPT_2, 1);
0688     release_bus(wilc, WILC_BUS_RELEASE_ONLY);
0689 }
0690 EXPORT_SYMBOL_GPL(host_wakeup_notify);
0691 
0692 void host_sleep_notify(struct wilc *wilc)
0693 {
0694     acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
0695     wilc->hif_func->hif_write_reg(wilc, WILC_CORTUS_INTERRUPT_1, 1);
0696     release_bus(wilc, WILC_BUS_RELEASE_ONLY);
0697 }
0698 EXPORT_SYMBOL_GPL(host_sleep_notify);
0699 
0700 int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
0701 {
0702     int i, entries = 0;
0703     u8 k, ac;
0704     u32 sum;
0705     u32 reg;
0706     u8 ac_desired_ratio[NQUEUES] = {0, 0, 0, 0};
0707     u8 ac_preserve_ratio[NQUEUES] = {1, 1, 1, 1};
0708     u8 *num_pkts_to_add;
0709     u8 vmm_entries_ac[WILC_VMM_TBL_SIZE];
0710     u32 offset = 0;
0711     bool max_size_over = 0, ac_exist = 0;
0712     int vmm_sz = 0;
0713     struct txq_entry_t *tqe_q[NQUEUES];
0714     int ret = 0;
0715     int counter;
0716     int timeout;
0717     u32 *vmm_table = wilc->vmm_table;
0718     u8 ac_pkt_num_to_chip[NQUEUES] = {0, 0, 0, 0};
0719     const struct wilc_hif_func *func;
0720     int srcu_idx;
0721     u8 *txb = wilc->tx_buffer;
0722     struct wilc_vif *vif;
0723 
0724     if (wilc->quit)
0725         goto out_update_cnt;
0726 
0727     if (ac_balance(wilc, ac_desired_ratio))
0728         return -EINVAL;
0729 
0730     mutex_lock(&wilc->txq_add_to_head_cs);
0731 
0732     srcu_idx = srcu_read_lock(&wilc->srcu);
0733     list_for_each_entry_rcu(vif, &wilc->vif_list, list)
0734         wilc_wlan_txq_filter_dup_tcp_ack(vif->ndev);
0735     srcu_read_unlock(&wilc->srcu, srcu_idx);
0736 
0737     for (ac = 0; ac < NQUEUES; ac++)
0738         tqe_q[ac] = wilc_wlan_txq_get_first(wilc, ac);
0739 
0740     i = 0;
0741     sum = 0;
0742     max_size_over = 0;
0743     num_pkts_to_add = ac_desired_ratio;
0744     do {
0745         ac_exist = 0;
0746         for (ac = 0; (ac < NQUEUES) && (!max_size_over); ac++) {
0747             if (!tqe_q[ac])
0748                 continue;
0749 
0750             ac_exist = 1;
0751             for (k = 0; (k < num_pkts_to_add[ac]) &&
0752                  (!max_size_over) && tqe_q[ac]; k++) {
0753                 if (i >= (WILC_VMM_TBL_SIZE - 1)) {
0754                     max_size_over = 1;
0755                     break;
0756                 }
0757 
0758                 if (tqe_q[ac]->type == WILC_CFG_PKT)
0759                     vmm_sz = ETH_CONFIG_PKT_HDR_OFFSET;
0760                 else if (tqe_q[ac]->type == WILC_NET_PKT)
0761                     vmm_sz = ETH_ETHERNET_HDR_OFFSET;
0762                 else
0763                     vmm_sz = HOST_HDR_OFFSET;
0764 
0765                 vmm_sz += tqe_q[ac]->buffer_size;
0766                 vmm_sz = ALIGN(vmm_sz, 4);
0767 
0768                 if ((sum + vmm_sz) > WILC_TX_BUFF_SIZE) {
0769                     max_size_over = 1;
0770                     break;
0771                 }
0772                 vmm_table[i] = vmm_sz / 4;
0773                 if (tqe_q[ac]->type == WILC_CFG_PKT)
0774                     vmm_table[i] |= BIT(10);
0775 
0776                 cpu_to_le32s(&vmm_table[i]);
0777                 vmm_entries_ac[i] = ac;
0778 
0779                 i++;
0780                 sum += vmm_sz;
0781                 tqe_q[ac] = wilc_wlan_txq_get_next(wilc,
0782                                    tqe_q[ac],
0783                                    ac);
0784             }
0785         }
0786         num_pkts_to_add = ac_preserve_ratio;
0787     } while (!max_size_over && ac_exist);
0788 
0789     if (i == 0)
0790         goto out_unlock;
0791     vmm_table[i] = 0x0;
0792 
0793     acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
0794     counter = 0;
0795     func = wilc->hif_func;
0796     do {
0797         ret = func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, &reg);
0798         if (ret)
0799             break;
0800 
0801         if ((reg & 0x1) == 0) {
0802             ac_update_fw_ac_pkt_info(wilc, reg);
0803             break;
0804         }
0805 
0806         counter++;
0807         if (counter > 200) {
0808             counter = 0;
0809             ret = func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, 0);
0810             break;
0811         }
0812     } while (!wilc->quit);
0813 
0814     if (ret)
0815         goto out_release_bus;
0816 
0817     timeout = 200;
0818     do {
0819         ret = func->hif_block_tx(wilc,
0820                      WILC_VMM_TBL_RX_SHADOW_BASE,
0821                      (u8 *)vmm_table,
0822                      ((i + 1) * 4));
0823         if (ret)
0824             break;
0825 
0826         ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x2);
0827         if (ret)
0828             break;
0829 
0830         do {
0831             ret = func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, &reg);
0832             if (ret)
0833                 break;
0834             if (FIELD_GET(WILC_VMM_ENTRY_AVAILABLE, reg)) {
0835                 entries = FIELD_GET(WILC_VMM_ENTRY_COUNT, reg);
0836                 break;
0837             }
0838         } while (--timeout);
0839         if (timeout <= 0) {
0840             ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x0);
0841             break;
0842         }
0843 
0844         if (ret)
0845             break;
0846 
0847         if (entries == 0) {
0848             ret = func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, &reg);
0849             if (ret)
0850                 break;
0851             reg &= ~BIT(0);
0852             ret = func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, reg);
0853         }
0854     } while (0);
0855 
0856     if (ret)
0857         goto out_release_bus;
0858 
0859     if (entries == 0) {
0860         /*
0861          * No VMM space available in firmware so retry to transmit
0862          * the packet from tx queue.
0863          */
0864         ret = WILC_VMM_ENTRY_FULL_RETRY;
0865         goto out_release_bus;
0866     }
0867 
0868     release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
0869 
0870     offset = 0;
0871     i = 0;
0872     do {
0873         struct txq_entry_t *tqe;
0874         u32 header, buffer_offset;
0875         char *bssid;
0876         u8 mgmt_ptk = 0;
0877 
0878         if (vmm_table[i] == 0 || vmm_entries_ac[i] >= NQUEUES)
0879             break;
0880 
0881         tqe = wilc_wlan_txq_remove_from_head(wilc, vmm_entries_ac[i]);
0882         if (!tqe)
0883             break;
0884 
0885         ac_pkt_num_to_chip[vmm_entries_ac[i]]++;
0886         vif = tqe->vif;
0887 
0888         le32_to_cpus(&vmm_table[i]);
0889         vmm_sz = FIELD_GET(WILC_VMM_BUFFER_SIZE, vmm_table[i]);
0890         vmm_sz *= 4;
0891 
0892         if (tqe->type == WILC_MGMT_PKT)
0893             mgmt_ptk = 1;
0894 
0895         header = (FIELD_PREP(WILC_VMM_HDR_TYPE, tqe->type) |
0896               FIELD_PREP(WILC_VMM_HDR_MGMT_FIELD, mgmt_ptk) |
0897               FIELD_PREP(WILC_VMM_HDR_PKT_SIZE, tqe->buffer_size) |
0898               FIELD_PREP(WILC_VMM_HDR_BUFF_SIZE, vmm_sz));
0899 
0900         cpu_to_le32s(&header);
0901         memcpy(&txb[offset], &header, 4);
0902         if (tqe->type == WILC_CFG_PKT) {
0903             buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET;
0904         } else if (tqe->type == WILC_NET_PKT) {
0905             int prio = tqe->q_num;
0906 
0907             bssid = tqe->vif->bssid;
0908             buffer_offset = ETH_ETHERNET_HDR_OFFSET;
0909             memcpy(&txb[offset + 4], &prio, sizeof(prio));
0910             memcpy(&txb[offset + 8], bssid, 6);
0911         } else {
0912             buffer_offset = HOST_HDR_OFFSET;
0913         }
0914 
0915         memcpy(&txb[offset + buffer_offset],
0916                tqe->buffer, tqe->buffer_size);
0917         offset += vmm_sz;
0918         i++;
0919         tqe->status = 1;
0920         if (tqe->tx_complete_func)
0921             tqe->tx_complete_func(tqe->priv, tqe->status);
0922         if (tqe->ack_idx != NOT_TCP_ACK &&
0923             tqe->ack_idx < MAX_PENDING_ACKS)
0924             vif->ack_filter.pending_acks[tqe->ack_idx].txqe = NULL;
0925         kfree(tqe);
0926     } while (--entries);
0927     for (i = 0; i < NQUEUES; i++)
0928         wilc->txq[i].fw.count += ac_pkt_num_to_chip[i];
0929 
0930     acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
0931 
0932     ret = func->hif_clear_int_ext(wilc, ENABLE_TX_VMM);
0933     if (ret)
0934         goto out_release_bus;
0935 
0936     ret = func->hif_block_tx_ext(wilc, 0, txb, offset);
0937 
0938 out_release_bus:
0939     release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
0940 
0941 out_unlock:
0942     mutex_unlock(&wilc->txq_add_to_head_cs);
0943 
0944 out_update_cnt:
0945     *txq_count = wilc->txq_entries;
0946     return ret;
0947 }
0948 
0949 static void wilc_wlan_handle_rx_buff(struct wilc *wilc, u8 *buffer, int size)
0950 {
0951     int offset = 0;
0952     u32 header;
0953     u32 pkt_len, pkt_offset, tp_len;
0954     int is_cfg_packet;
0955     u8 *buff_ptr;
0956 
0957     do {
0958         buff_ptr = buffer + offset;
0959         header = get_unaligned_le32(buff_ptr);
0960 
0961         is_cfg_packet = FIELD_GET(WILC_PKT_HDR_CONFIG_FIELD, header);
0962         pkt_offset = FIELD_GET(WILC_PKT_HDR_OFFSET_FIELD, header);
0963         tp_len = FIELD_GET(WILC_PKT_HDR_TOTAL_LEN_FIELD, header);
0964         pkt_len = FIELD_GET(WILC_PKT_HDR_LEN_FIELD, header);
0965 
0966         if (pkt_len == 0 || tp_len == 0)
0967             break;
0968 
0969         if (pkt_offset & IS_MANAGMEMENT) {
0970             buff_ptr += HOST_HDR_OFFSET;
0971             wilc_wfi_mgmt_rx(wilc, buff_ptr, pkt_len,
0972                      pkt_offset & IS_MGMT_AUTH_PKT);
0973         } else {
0974             if (!is_cfg_packet) {
0975                 wilc_frmw_to_host(wilc, buff_ptr, pkt_len,
0976                           pkt_offset);
0977             } else {
0978                 struct wilc_cfg_rsp rsp;
0979 
0980                 buff_ptr += pkt_offset;
0981 
0982                 wilc_wlan_cfg_indicate_rx(wilc, buff_ptr,
0983                               pkt_len,
0984                               &rsp);
0985                 if (rsp.type == WILC_CFG_RSP) {
0986                     if (wilc->cfg_seq_no == rsp.seq_no)
0987                         complete(&wilc->cfg_event);
0988                 } else if (rsp.type == WILC_CFG_RSP_STATUS) {
0989                     wilc_mac_indicate(wilc);
0990                 }
0991             }
0992         }
0993         offset += tp_len;
0994     } while (offset < size);
0995 }
0996 
0997 static void wilc_wlan_handle_rxq(struct wilc *wilc)
0998 {
0999     int size;
1000     u8 *buffer;
1001     struct rxq_entry_t *rqe;
1002 
1003     while (!wilc->quit) {
1004         rqe = wilc_wlan_rxq_remove(wilc);
1005         if (!rqe)
1006             break;
1007 
1008         buffer = rqe->buffer;
1009         size = rqe->buffer_size;
1010         wilc_wlan_handle_rx_buff(wilc, buffer, size);
1011 
1012         kfree(rqe);
1013     }
1014     if (wilc->quit)
1015         complete(&wilc->cfg_event);
1016 }
1017 
1018 static void wilc_unknown_isr_ext(struct wilc *wilc)
1019 {
1020     wilc->hif_func->hif_clear_int_ext(wilc, 0);
1021 }
1022 
1023 static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status)
1024 {
1025     u32 offset = wilc->rx_buffer_offset;
1026     u8 *buffer = NULL;
1027     u32 size;
1028     u32 retries = 0;
1029     int ret = 0;
1030     struct rxq_entry_t *rqe;
1031 
1032     size = FIELD_GET(WILC_INTERRUPT_DATA_SIZE, int_status) << 2;
1033 
1034     while (!size && retries < 10) {
1035         wilc->hif_func->hif_read_size(wilc, &size);
1036         size = FIELD_GET(WILC_INTERRUPT_DATA_SIZE, size) << 2;
1037         retries++;
1038     }
1039 
1040     if (size <= 0)
1041         return;
1042 
1043     if (WILC_RX_BUFF_SIZE - offset < size)
1044         offset = 0;
1045 
1046     buffer = &wilc->rx_buffer[offset];
1047 
1048     wilc->hif_func->hif_clear_int_ext(wilc, DATA_INT_CLR | ENABLE_RX_VMM);
1049     ret = wilc->hif_func->hif_block_rx_ext(wilc, 0, buffer, size);
1050     if (ret)
1051         return;
1052 
1053     offset += size;
1054     wilc->rx_buffer_offset = offset;
1055     rqe = kmalloc(sizeof(*rqe), GFP_KERNEL);
1056     if (!rqe)
1057         return;
1058 
1059     rqe->buffer = buffer;
1060     rqe->buffer_size = size;
1061     wilc_wlan_rxq_add(wilc, rqe);
1062     wilc_wlan_handle_rxq(wilc);
1063 }
1064 
1065 void wilc_handle_isr(struct wilc *wilc)
1066 {
1067     u32 int_status;
1068 
1069     acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
1070     wilc->hif_func->hif_read_int(wilc, &int_status);
1071 
1072     if (int_status & DATA_INT_EXT)
1073         wilc_wlan_handle_isr_ext(wilc, int_status);
1074 
1075     if (!(int_status & (ALL_INT_EXT)))
1076         wilc_unknown_isr_ext(wilc);
1077 
1078     release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
1079 }
1080 EXPORT_SYMBOL_GPL(wilc_handle_isr);
1081 
1082 int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
1083                 u32 buffer_size)
1084 {
1085     u32 offset;
1086     u32 addr, size, size2, blksz;
1087     u8 *dma_buffer;
1088     int ret = 0;
1089     u32 reg = 0;
1090 
1091     blksz = BIT(12);
1092 
1093     dma_buffer = kmalloc(blksz, GFP_KERNEL);
1094     if (!dma_buffer)
1095         return -EIO;
1096 
1097     offset = 0;
1098     pr_debug("%s: Downloading firmware size = %d\n", __func__, buffer_size);
1099 
1100     acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
1101 
1102     wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
1103     reg &= ~BIT(10);
1104     ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg);
1105     wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
1106     if (reg & BIT(10))
1107         pr_err("%s: Failed to reset\n", __func__);
1108 
1109     release_bus(wilc, WILC_BUS_RELEASE_ONLY);
1110     do {
1111         addr = get_unaligned_le32(&buffer[offset]);
1112         size = get_unaligned_le32(&buffer[offset + 4]);
1113         acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
1114         offset += 8;
1115         while (((int)size) && (offset < buffer_size)) {
1116             if (size <= blksz)
1117                 size2 = size;
1118             else
1119                 size2 = blksz;
1120 
1121             memcpy(dma_buffer, &buffer[offset], size2);
1122             ret = wilc->hif_func->hif_block_tx(wilc, addr,
1123                                dma_buffer, size2);
1124             if (ret)
1125                 break;
1126 
1127             addr += size2;
1128             offset += size2;
1129             size -= size2;
1130         }
1131         release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
1132 
1133         if (ret) {
1134             pr_err("%s Bus error\n", __func__);
1135             goto fail;
1136         }
1137         pr_debug("%s Offset = %d\n", __func__, offset);
1138     } while (offset < buffer_size);
1139 
1140 fail:
1141 
1142     kfree(dma_buffer);
1143 
1144     return ret;
1145 }
1146 
1147 int wilc_wlan_start(struct wilc *wilc)
1148 {
1149     u32 reg = 0;
1150     int ret;
1151     u32 chipid;
1152 
1153     if (wilc->io_type == WILC_HIF_SDIO) {
1154         reg = 0;
1155         reg |= BIT(3);
1156     } else if (wilc->io_type == WILC_HIF_SPI) {
1157         reg = 1;
1158     }
1159     acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
1160     ret = wilc->hif_func->hif_write_reg(wilc, WILC_VMM_CORE_CFG, reg);
1161     if (ret)
1162         goto release;
1163 
1164     reg = 0;
1165     if (wilc->io_type == WILC_HIF_SDIO && wilc->dev_irq_num)
1166         reg |= WILC_HAVE_SDIO_IRQ_GPIO;
1167 
1168     ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_1, reg);
1169     if (ret)
1170         goto release;
1171 
1172     wilc->hif_func->hif_sync_ext(wilc, NUM_INT_EXT);
1173 
1174     ret = wilc->hif_func->hif_read_reg(wilc, WILC_CHIPID, &chipid);
1175     if (ret)
1176         goto release;
1177 
1178     wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
1179     if ((reg & BIT(10)) == BIT(10)) {
1180         reg &= ~BIT(10);
1181         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     }
1184 
1185     reg |= BIT(10);
1186     ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg);
1187     wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
1188 
1189 release:
1190     release_bus(wilc, WILC_BUS_RELEASE_ONLY);
1191     return ret;
1192 }
1193 
1194 int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif)
1195 {
1196     u32 reg = 0;
1197     int ret;
1198 
1199     acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
1200 
1201     ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, &reg);
1202     if (ret) {
1203         netdev_err(vif->ndev, "Error while reading reg\n");
1204         goto release;
1205     }
1206 
1207     ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0,
1208                     (reg | WILC_ABORT_REQ_BIT));
1209     if (ret) {
1210         netdev_err(vif->ndev, "Error while writing reg\n");
1211         goto release;
1212     }
1213 
1214     ret = wilc->hif_func->hif_read_reg(wilc, WILC_FW_HOST_COMM, &reg);
1215     if (ret) {
1216         netdev_err(vif->ndev, "Error while reading reg\n");
1217         goto release;
1218     }
1219     reg = BIT(0);
1220 
1221     ret = wilc->hif_func->hif_write_reg(wilc, WILC_FW_HOST_COMM, reg);
1222     if (ret) {
1223         netdev_err(vif->ndev, "Error while writing reg\n");
1224         goto release;
1225     }
1226 
1227     ret = 0;
1228 release:
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 
1235 void 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 
1264 static 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     else
1274         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 
1287 int 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 
1328 int 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 
1365 int 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 
1405 static 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_ONLY);
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 
1442 release:
1443     release_bus(wilc, WILC_BUS_RELEASE_ONLY);
1444 
1445     return ret;
1446 }
1447 
1448 u32 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 
1476 int wilc_wlan_init(struct net_device *dev)
1477 {
1478     int ret = 0;
1479     struct wilc_vif *vif = netdev_priv(dev);
1480     struct wilc *wilc;
1481 
1482     wilc = vif->wilc;
1483 
1484     wilc->quit = 0;
1485 
1486     if (!wilc->hif_func->hif_is_init(wilc)) {
1487         acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
1488         ret = wilc->hif_func->hif_init(wilc, false);
1489         release_bus(wilc, WILC_BUS_RELEASE_ONLY);
1490         if (ret)
1491             goto fail;
1492     }
1493 
1494     if (!wilc->vmm_table)
1495         wilc->vmm_table = kzalloc(WILC_VMM_TBL_SIZE, GFP_KERNEL);
1496 
1497     if (!wilc->vmm_table) {
1498         ret = -ENOBUFS;
1499         goto fail;
1500     }
1501 
1502     if (!wilc->tx_buffer)
1503         wilc->tx_buffer = kmalloc(WILC_TX_BUFF_SIZE, GFP_KERNEL);
1504 
1505     if (!wilc->tx_buffer) {
1506         ret = -ENOBUFS;
1507         goto fail;
1508     }
1509 
1510     if (!wilc->rx_buffer)
1511         wilc->rx_buffer = kmalloc(WILC_RX_BUFF_SIZE, GFP_KERNEL);
1512 
1513     if (!wilc->rx_buffer) {
1514         ret = -ENOBUFS;
1515         goto fail;
1516     }
1517 
1518     if (init_chip(dev)) {
1519         ret = -EIO;
1520         goto fail;
1521     }
1522 
1523     return 0;
1524 
1525 fail:
1526     kfree(wilc->vmm_table);
1527     wilc->vmm_table = NULL;
1528     kfree(wilc->rx_buffer);
1529     wilc->rx_buffer = NULL;
1530     kfree(wilc->tx_buffer);
1531     wilc->tx_buffer = NULL;
1532 
1533     return ret;
1534 }