linux/drivers/staging/wilc1000/wilc_wlan.c
<<
>>
Prefs
   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 "wilc_wfi_cfgoperations.h"
  10#include "wilc_wlan_cfg.h"
  11
  12static inline bool is_wilc1000(u32 id)
  13{
  14        return (id & 0xfffff000) == 0x100000;
  15}
  16
  17static inline void acquire_bus(struct wilc *wilc, enum bus_acquire acquire)
  18{
  19        mutex_lock(&wilc->hif_cs);
  20        if (acquire == WILC_BUS_ACQUIRE_AND_WAKEUP)
  21                chip_wakeup(wilc);
  22}
  23
  24static inline void release_bus(struct wilc *wilc, enum bus_release release)
  25{
  26        if (release == WILC_BUS_RELEASE_ALLOW_SLEEP)
  27                chip_allow_sleep(wilc);
  28        mutex_unlock(&wilc->hif_cs);
  29}
  30
  31static void wilc_wlan_txq_remove(struct wilc *wilc, struct txq_entry_t *tqe)
  32{
  33        list_del(&tqe->list);
  34        wilc->txq_entries -= 1;
  35}
  36
  37static struct txq_entry_t *
  38wilc_wlan_txq_remove_from_head(struct net_device *dev)
  39{
  40        struct txq_entry_t *tqe = NULL;
  41        unsigned long flags;
  42        struct wilc_vif *vif = netdev_priv(dev);
  43        struct wilc *wilc = vif->wilc;
  44
  45        spin_lock_irqsave(&wilc->txq_spinlock, flags);
  46
  47        if (!list_empty(&wilc->txq_head.list)) {
  48                tqe = list_first_entry(&wilc->txq_head.list, struct txq_entry_t,
  49                                       list);
  50                list_del(&tqe->list);
  51                wilc->txq_entries -= 1;
  52        }
  53        spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
  54        return tqe;
  55}
  56
  57static void wilc_wlan_txq_add_to_tail(struct net_device *dev,
  58                                      struct txq_entry_t *tqe)
  59{
  60        unsigned long flags;
  61        struct wilc_vif *vif = netdev_priv(dev);
  62        struct wilc *wilc = vif->wilc;
  63
  64        spin_lock_irqsave(&wilc->txq_spinlock, flags);
  65
  66        list_add_tail(&tqe->list, &wilc->txq_head.list);
  67        wilc->txq_entries += 1;
  68
  69        spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
  70
  71        complete(&wilc->txq_event);
  72}
  73
  74static void wilc_wlan_txq_add_to_head(struct wilc_vif *vif,
  75                                      struct txq_entry_t *tqe)
  76{
  77        unsigned long flags;
  78        struct wilc *wilc = vif->wilc;
  79
  80        mutex_lock(&wilc->txq_add_to_head_cs);
  81
  82        spin_lock_irqsave(&wilc->txq_spinlock, flags);
  83
  84        list_add(&tqe->list, &wilc->txq_head.list);
  85        wilc->txq_entries += 1;
  86
  87        spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
  88        mutex_unlock(&wilc->txq_add_to_head_cs);
  89        complete(&wilc->txq_event);
  90}
  91
  92#define NOT_TCP_ACK                     (-1)
  93
  94static inline void add_tcp_session(struct wilc_vif *vif, u32 src_prt,
  95                                   u32 dst_prt, u32 seq)
  96{
  97        struct tcp_ack_filter *f = &vif->ack_filter;
  98
  99        if (f->tcp_session < 2 * MAX_TCP_SESSION) {
 100                f->ack_session_info[f->tcp_session].seq_num = seq;
 101                f->ack_session_info[f->tcp_session].bigger_ack_num = 0;
 102                f->ack_session_info[f->tcp_session].src_port = src_prt;
 103                f->ack_session_info[f->tcp_session].dst_port = dst_prt;
 104                f->tcp_session++;
 105        }
 106}
 107
 108static inline void update_tcp_session(struct wilc_vif *vif, u32 index, u32 ack)
 109{
 110        struct tcp_ack_filter *f = &vif->ack_filter;
 111
 112        if (index < 2 * MAX_TCP_SESSION &&
 113            ack > f->ack_session_info[index].bigger_ack_num)
 114                f->ack_session_info[index].bigger_ack_num = ack;
 115}
 116
 117static inline void add_tcp_pending_ack(struct wilc_vif *vif, u32 ack,
 118                                       u32 session_index,
 119                                       struct txq_entry_t *txqe)
 120{
 121        struct tcp_ack_filter *f = &vif->ack_filter;
 122        u32 i = f->pending_base + f->pending_acks_idx;
 123
 124        if (i < MAX_PENDING_ACKS) {
 125                f->pending_acks[i].ack_num = ack;
 126                f->pending_acks[i].txqe = txqe;
 127                f->pending_acks[i].session_index = session_index;
 128                txqe->ack_idx = i;
 129                f->pending_acks_idx++;
 130        }
 131}
 132
 133static inline void tcp_process(struct net_device *dev, struct txq_entry_t *tqe)
 134{
 135        void *buffer = tqe->buffer;
 136        const struct ethhdr *eth_hdr_ptr = buffer;
 137        int i;
 138        unsigned long flags;
 139        struct wilc_vif *vif = netdev_priv(dev);
 140        struct wilc *wilc = vif->wilc;
 141        struct tcp_ack_filter *f = &vif->ack_filter;
 142        const struct iphdr *ip_hdr_ptr;
 143        const struct tcphdr *tcp_hdr_ptr;
 144        u32 ihl, total_length, data_offset;
 145
 146        spin_lock_irqsave(&wilc->txq_spinlock, flags);
 147
 148        if (eth_hdr_ptr->h_proto != htons(ETH_P_IP))
 149                goto out;
 150
 151        ip_hdr_ptr = buffer + ETH_HLEN;
 152
 153        if (ip_hdr_ptr->protocol != IPPROTO_TCP)
 154                goto out;
 155
 156        ihl = ip_hdr_ptr->ihl << 2;
 157        tcp_hdr_ptr = buffer + ETH_HLEN + ihl;
 158        total_length = ntohs(ip_hdr_ptr->tot_len);
 159
 160        data_offset = tcp_hdr_ptr->doff << 2;
 161        if (total_length == (ihl + data_offset)) {
 162                u32 seq_no, ack_no;
 163
 164                seq_no = ntohl(tcp_hdr_ptr->seq);
 165                ack_no = ntohl(tcp_hdr_ptr->ack_seq);
 166                for (i = 0; i < f->tcp_session; i++) {
 167                        u32 j = f->ack_session_info[i].seq_num;
 168
 169                        if (i < 2 * MAX_TCP_SESSION &&
 170                            j == seq_no) {
 171                                update_tcp_session(vif, i, ack_no);
 172                                break;
 173                        }
 174                }
 175                if (i == f->tcp_session)
 176                        add_tcp_session(vif, 0, 0, seq_no);
 177
 178                add_tcp_pending_ack(vif, ack_no, i, tqe);
 179        }
 180
 181out:
 182        spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
 183}
 184
 185static void wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev)
 186{
 187        struct wilc_vif *vif = netdev_priv(dev);
 188        struct wilc *wilc = vif->wilc;
 189        struct tcp_ack_filter *f = &vif->ack_filter;
 190        u32 i = 0;
 191        u32 dropped = 0;
 192        unsigned long flags;
 193
 194        spin_lock_irqsave(&wilc->txq_spinlock, flags);
 195        for (i = f->pending_base;
 196             i < (f->pending_base + f->pending_acks_idx); i++) {
 197                u32 index;
 198                u32 bigger_ack_num;
 199
 200                if (i >= MAX_PENDING_ACKS)
 201                        break;
 202
 203                index = f->pending_acks[i].session_index;
 204
 205                if (index >= 2 * MAX_TCP_SESSION)
 206                        break;
 207
 208                bigger_ack_num = f->ack_session_info[index].bigger_ack_num;
 209
 210                if (f->pending_acks[i].ack_num < bigger_ack_num) {
 211                        struct txq_entry_t *tqe;
 212
 213                        tqe = f->pending_acks[i].txqe;
 214                        if (tqe) {
 215                                wilc_wlan_txq_remove(wilc, tqe);
 216                                tqe->status = 1;
 217                                if (tqe->tx_complete_func)
 218                                        tqe->tx_complete_func(tqe->priv,
 219                                                              tqe->status);
 220                                kfree(tqe);
 221                                dropped++;
 222                        }
 223                }
 224        }
 225        f->pending_acks_idx = 0;
 226        f->tcp_session = 0;
 227
 228        if (f->pending_base == 0)
 229                f->pending_base = MAX_TCP_SESSION;
 230        else
 231                f->pending_base = 0;
 232
 233        spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
 234
 235        while (dropped > 0) {
 236                wait_for_completion_timeout(&wilc->txq_event,
 237                                            msecs_to_jiffies(1));
 238                dropped--;
 239        }
 240}
 241
 242void wilc_enable_tcp_ack_filter(struct wilc_vif *vif, bool value)
 243{
 244        vif->ack_filter.enabled = value;
 245}
 246
 247static int wilc_wlan_txq_add_cfg_pkt(struct wilc_vif *vif, u8 *buffer,
 248                                     u32 buffer_size)
 249{
 250        struct txq_entry_t *tqe;
 251        struct wilc *wilc = vif->wilc;
 252
 253        netdev_dbg(vif->ndev, "Adding config packet ...\n");
 254        if (wilc->quit) {
 255                netdev_dbg(vif->ndev, "Return due to clear function\n");
 256                complete(&wilc->cfg_event);
 257                return 0;
 258        }
 259
 260        tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC);
 261        if (!tqe)
 262                return 0;
 263
 264        tqe->type = WILC_CFG_PKT;
 265        tqe->buffer = buffer;
 266        tqe->buffer_size = buffer_size;
 267        tqe->tx_complete_func = NULL;
 268        tqe->priv = NULL;
 269        tqe->ack_idx = NOT_TCP_ACK;
 270        tqe->vif = vif;
 271
 272        wilc_wlan_txq_add_to_head(vif, tqe);
 273
 274        return 1;
 275}
 276
 277int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
 278                              u32 buffer_size,
 279                              void (*tx_complete_fn)(void *, int))
 280{
 281        struct txq_entry_t *tqe;
 282        struct wilc_vif *vif = netdev_priv(dev);
 283        struct wilc *wilc;
 284
 285        wilc = vif->wilc;
 286
 287        if (wilc->quit)
 288                return 0;
 289
 290        tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC);
 291
 292        if (!tqe)
 293                return 0;
 294        tqe->type = WILC_NET_PKT;
 295        tqe->buffer = buffer;
 296        tqe->buffer_size = buffer_size;
 297        tqe->tx_complete_func = tx_complete_fn;
 298        tqe->priv = priv;
 299        tqe->vif = vif;
 300
 301        tqe->ack_idx = NOT_TCP_ACK;
 302        if (vif->ack_filter.enabled)
 303                tcp_process(dev, tqe);
 304        wilc_wlan_txq_add_to_tail(dev, tqe);
 305        return wilc->txq_entries;
 306}
 307
 308int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer,
 309                               u32 buffer_size,
 310                               void (*tx_complete_fn)(void *, int))
 311{
 312        struct txq_entry_t *tqe;
 313        struct wilc_vif *vif = netdev_priv(dev);
 314        struct wilc *wilc;
 315
 316        wilc = vif->wilc;
 317
 318        if (wilc->quit)
 319                return 0;
 320
 321        tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC);
 322
 323        if (!tqe)
 324                return 0;
 325        tqe->type = WILC_MGMT_PKT;
 326        tqe->buffer = buffer;
 327        tqe->buffer_size = buffer_size;
 328        tqe->tx_complete_func = tx_complete_fn;
 329        tqe->priv = priv;
 330        tqe->ack_idx = NOT_TCP_ACK;
 331        tqe->vif = vif;
 332        wilc_wlan_txq_add_to_tail(dev, tqe);
 333        return 1;
 334}
 335
 336static struct txq_entry_t *wilc_wlan_txq_get_first(struct wilc *wilc)
 337{
 338        struct txq_entry_t *tqe = NULL;
 339        unsigned long flags;
 340
 341        spin_lock_irqsave(&wilc->txq_spinlock, flags);
 342
 343        if (!list_empty(&wilc->txq_head.list))
 344                tqe = list_first_entry(&wilc->txq_head.list, struct txq_entry_t,
 345                                       list);
 346
 347        spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
 348
 349        return tqe;
 350}
 351
 352static struct txq_entry_t *wilc_wlan_txq_get_next(struct wilc *wilc,
 353                                                  struct txq_entry_t *tqe)
 354{
 355        unsigned long flags;
 356
 357        spin_lock_irqsave(&wilc->txq_spinlock, flags);
 358
 359        if (!list_is_last(&tqe->list, &wilc->txq_head.list))
 360                tqe = list_next_entry(tqe, list);
 361        else
 362                tqe = NULL;
 363        spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
 364
 365        return tqe;
 366}
 367
 368static void wilc_wlan_rxq_add(struct wilc *wilc, struct rxq_entry_t *rqe)
 369{
 370        if (wilc->quit)
 371                return;
 372
 373        mutex_lock(&wilc->rxq_cs);
 374        list_add_tail(&rqe->list, &wilc->rxq_head.list);
 375        mutex_unlock(&wilc->rxq_cs);
 376}
 377
 378static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc)
 379{
 380        struct rxq_entry_t *rqe = NULL;
 381
 382        mutex_lock(&wilc->rxq_cs);
 383        if (!list_empty(&wilc->rxq_head.list)) {
 384                rqe = list_first_entry(&wilc->rxq_head.list, struct rxq_entry_t,
 385                                       list);
 386                list_del(&rqe->list);
 387        }
 388        mutex_unlock(&wilc->rxq_cs);
 389        return rqe;
 390}
 391
 392void chip_allow_sleep(struct wilc *wilc)
 393{
 394        u32 reg = 0;
 395
 396        wilc->hif_func->hif_read_reg(wilc, 0xf0, &reg);
 397
 398        wilc->hif_func->hif_write_reg(wilc, 0xf0, reg & ~BIT(0));
 399        wilc->hif_func->hif_write_reg(wilc, 0xfa, 0);
 400}
 401EXPORT_SYMBOL_GPL(chip_allow_sleep);
 402
 403void chip_wakeup(struct wilc *wilc)
 404{
 405        u32 reg, clk_status_reg;
 406
 407        if ((wilc->io_type & 0x1) == WILC_HIF_SPI) {
 408                do {
 409                        wilc->hif_func->hif_read_reg(wilc, 1, &reg);
 410                        wilc->hif_func->hif_write_reg(wilc, 1, reg | BIT(1));
 411                        wilc->hif_func->hif_write_reg(wilc, 1, reg & ~BIT(1));
 412
 413                        do {
 414                                usleep_range(2000, 2500);
 415                                wilc_get_chipid(wilc, true);
 416                        } while (wilc_get_chipid(wilc, true) == 0);
 417                } while (wilc_get_chipid(wilc, true) == 0);
 418        } else if ((wilc->io_type & 0x1) == WILC_HIF_SDIO) {
 419                wilc->hif_func->hif_write_reg(wilc, 0xfa, 1);
 420                usleep_range(200, 400);
 421                wilc->hif_func->hif_read_reg(wilc, 0xf0, &reg);
 422                do {
 423                        wilc->hif_func->hif_write_reg(wilc, 0xf0,
 424                                                      reg | BIT(0));
 425                        wilc->hif_func->hif_read_reg(wilc, 0xf1,
 426                                                     &clk_status_reg);
 427
 428                        while ((clk_status_reg & 0x1) == 0) {
 429                                usleep_range(2000, 2500);
 430
 431                                wilc->hif_func->hif_read_reg(wilc, 0xf1,
 432                                                             &clk_status_reg);
 433                        }
 434                        if ((clk_status_reg & 0x1) == 0) {
 435                                wilc->hif_func->hif_write_reg(wilc, 0xf0,
 436                                                              reg & (~BIT(0)));
 437                        }
 438                } while ((clk_status_reg & 0x1) == 0);
 439        }
 440
 441        if (wilc->chip_ps_state == WILC_CHIP_SLEEPING_MANUAL) {
 442                if (wilc_get_chipid(wilc, false) < 0x1002b0) {
 443                        u32 val32;
 444
 445                        wilc->hif_func->hif_read_reg(wilc, 0x1e1c, &val32);
 446                        val32 |= BIT(6);
 447                        wilc->hif_func->hif_write_reg(wilc, 0x1e1c, val32);
 448
 449                        wilc->hif_func->hif_read_reg(wilc, 0x1e9c, &val32);
 450                        val32 |= BIT(6);
 451                        wilc->hif_func->hif_write_reg(wilc, 0x1e9c, val32);
 452                }
 453        }
 454        wilc->chip_ps_state = WILC_CHIP_WAKEDUP;
 455}
 456EXPORT_SYMBOL_GPL(chip_wakeup);
 457
 458void wilc_chip_sleep_manually(struct wilc *wilc)
 459{
 460        if (wilc->chip_ps_state != WILC_CHIP_WAKEDUP)
 461                return;
 462        acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
 463
 464        chip_allow_sleep(wilc);
 465        wilc->hif_func->hif_write_reg(wilc, 0x10a8, 1);
 466
 467        wilc->chip_ps_state = WILC_CHIP_SLEEPING_MANUAL;
 468        release_bus(wilc, WILC_BUS_RELEASE_ONLY);
 469}
 470EXPORT_SYMBOL_GPL(wilc_chip_sleep_manually);
 471
 472void host_wakeup_notify(struct wilc *wilc)
 473{
 474        acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
 475        wilc->hif_func->hif_write_reg(wilc, 0x10b0, 1);
 476        release_bus(wilc, WILC_BUS_RELEASE_ONLY);
 477}
 478EXPORT_SYMBOL_GPL(host_wakeup_notify);
 479
 480void host_sleep_notify(struct wilc *wilc)
 481{
 482        acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
 483        wilc->hif_func->hif_write_reg(wilc, 0x10ac, 1);
 484        release_bus(wilc, WILC_BUS_RELEASE_ONLY);
 485}
 486EXPORT_SYMBOL_GPL(host_sleep_notify);
 487
 488int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
 489{
 490        int i, entries = 0;
 491        u32 sum;
 492        u32 reg;
 493        u32 offset = 0;
 494        int vmm_sz = 0;
 495        struct txq_entry_t *tqe;
 496        int ret = 0;
 497        int counter;
 498        int timeout;
 499        u32 vmm_table[WILC_VMM_TBL_SIZE];
 500        const struct wilc_hif_func *func;
 501        u8 *txb = wilc->tx_buffer;
 502        struct net_device *dev;
 503        struct wilc_vif *vif;
 504
 505        if (wilc->quit)
 506                goto out;
 507
 508        mutex_lock(&wilc->txq_add_to_head_cs);
 509        tqe = wilc_wlan_txq_get_first(wilc);
 510        if (!tqe)
 511                goto out;
 512        dev = tqe->vif->ndev;
 513        wilc_wlan_txq_filter_dup_tcp_ack(dev);
 514        i = 0;
 515        sum = 0;
 516        do {
 517                if (tqe && (i < (WILC_VMM_TBL_SIZE - 1))) {
 518                        if (tqe->type == WILC_CFG_PKT)
 519                                vmm_sz = ETH_CONFIG_PKT_HDR_OFFSET;
 520
 521                        else if (tqe->type == WILC_NET_PKT)
 522                                vmm_sz = ETH_ETHERNET_HDR_OFFSET;
 523
 524                        else
 525                                vmm_sz = HOST_HDR_OFFSET;
 526
 527                        vmm_sz += tqe->buffer_size;
 528
 529                        if (vmm_sz & 0x3)
 530                                vmm_sz = (vmm_sz + 4) & ~0x3;
 531
 532                        if ((sum + vmm_sz) > WILC_TX_BUFF_SIZE)
 533                                break;
 534
 535                        vmm_table[i] = vmm_sz / 4;
 536                        if (tqe->type == WILC_CFG_PKT)
 537                                vmm_table[i] |= BIT(10);
 538                        cpu_to_le32s(&vmm_table[i]);
 539
 540                        i++;
 541                        sum += vmm_sz;
 542                        tqe = wilc_wlan_txq_get_next(wilc, tqe);
 543                } else {
 544                        break;
 545                }
 546        } while (1);
 547
 548        if (i == 0)
 549                goto out;
 550        vmm_table[i] = 0x0;
 551
 552        acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
 553        counter = 0;
 554        func = wilc->hif_func;
 555        do {
 556                ret = func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, &reg);
 557                if (!ret)
 558                        break;
 559
 560                if ((reg & 0x1) == 0)
 561                        break;
 562
 563                counter++;
 564                if (counter > 200) {
 565                        counter = 0;
 566                        ret = func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, 0);
 567                        break;
 568                }
 569        } while (!wilc->quit);
 570
 571        if (!ret)
 572                goto out_release_bus;
 573
 574        timeout = 200;
 575        do {
 576                ret = func->hif_block_tx(wilc,
 577                                         WILC_VMM_TBL_RX_SHADOW_BASE,
 578                                         (u8 *)vmm_table,
 579                                         ((i + 1) * 4));
 580                if (!ret)
 581                        break;
 582
 583                ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x2);
 584                if (!ret)
 585                        break;
 586
 587                do {
 588                        ret = func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, &reg);
 589                        if (!ret)
 590                                break;
 591                        if ((reg >> 2) & 0x1) {
 592                                entries = ((reg >> 3) & 0x3f);
 593                                break;
 594                        }
 595                        release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
 596                } while (--timeout);
 597                if (timeout <= 0) {
 598                        ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x0);
 599                        break;
 600                }
 601
 602                if (!ret)
 603                        break;
 604
 605                if (entries == 0) {
 606                        ret = func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, &reg);
 607                        if (!ret)
 608                                break;
 609                        reg &= ~BIT(0);
 610                        ret = func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, reg);
 611                        if (!ret)
 612                                break;
 613                        break;
 614                }
 615                break;
 616        } while (1);
 617
 618        if (!ret)
 619                goto out_release_bus;
 620
 621        if (entries == 0) {
 622                ret = -ENOBUFS;
 623                goto out_release_bus;
 624        }
 625
 626        release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
 627
 628        offset = 0;
 629        i = 0;
 630        do {
 631                u32 header, buffer_offset;
 632                char *bssid;
 633
 634                tqe = wilc_wlan_txq_remove_from_head(dev);
 635                if (!tqe)
 636                        break;
 637
 638                vif = tqe->vif;
 639                if (vmm_table[i] == 0)
 640                        break;
 641
 642                le32_to_cpus(&vmm_table[i]);
 643                vmm_sz = (vmm_table[i] & 0x3ff);
 644                vmm_sz *= 4;
 645                header = (tqe->type << 31) |
 646                         (tqe->buffer_size << 15) |
 647                         vmm_sz;
 648                if (tqe->type == WILC_MGMT_PKT)
 649                        header |= BIT(30);
 650                else
 651                        header &= ~BIT(30);
 652
 653                cpu_to_le32s(&header);
 654                memcpy(&txb[offset], &header, 4);
 655                if (tqe->type == WILC_CFG_PKT) {
 656                        buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET;
 657                } else if (tqe->type == WILC_NET_PKT) {
 658                        bssid = tqe->vif->bssid;
 659                        buffer_offset = ETH_ETHERNET_HDR_OFFSET;
 660                        memcpy(&txb[offset + 8], bssid, 6);
 661                } else {
 662                        buffer_offset = HOST_HDR_OFFSET;
 663                }
 664
 665                memcpy(&txb[offset + buffer_offset],
 666                       tqe->buffer, tqe->buffer_size);
 667                offset += vmm_sz;
 668                i++;
 669                tqe->status = 1;
 670                if (tqe->tx_complete_func)
 671                        tqe->tx_complete_func(tqe->priv, tqe->status);
 672                if (tqe->ack_idx != NOT_TCP_ACK &&
 673                    tqe->ack_idx < MAX_PENDING_ACKS)
 674                        vif->ack_filter.pending_acks[tqe->ack_idx].txqe = NULL;
 675                kfree(tqe);
 676        } while (--entries);
 677
 678        acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
 679
 680        ret = func->hif_clear_int_ext(wilc, ENABLE_TX_VMM);
 681        if (!ret)
 682                goto out_release_bus;
 683
 684        ret = func->hif_block_tx_ext(wilc, 0, txb, offset);
 685
 686out_release_bus:
 687        release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
 688
 689out:
 690        mutex_unlock(&wilc->txq_add_to_head_cs);
 691
 692        *txq_count = wilc->txq_entries;
 693        return ret;
 694}
 695
 696static void wilc_wlan_handle_rx_buff(struct wilc *wilc, u8 *buffer, int size)
 697{
 698        int offset = 0;
 699        u32 header;
 700        u32 pkt_len, pkt_offset, tp_len;
 701        int is_cfg_packet;
 702        u8 *buff_ptr;
 703
 704        do {
 705                buff_ptr = buffer + offset;
 706                memcpy(&header, buff_ptr, 4);
 707                le32_to_cpus(&header);
 708
 709                is_cfg_packet = (header >> 31) & 0x1;
 710                pkt_offset = (header >> 22) & 0x1ff;
 711                tp_len = (header >> 11) & 0x7ff;
 712                pkt_len = header & 0x7ff;
 713
 714                if (pkt_len == 0 || tp_len == 0)
 715                        break;
 716
 717                if (pkt_offset & IS_MANAGMEMENT) {
 718                        buff_ptr += HOST_HDR_OFFSET;
 719                        wilc_wfi_mgmt_rx(wilc, buff_ptr, pkt_len);
 720                } else {
 721                        if (!is_cfg_packet) {
 722                                if (pkt_len > 0) {
 723                                        wilc_frmw_to_host(wilc, buff_ptr,
 724                                                          pkt_len, pkt_offset);
 725                                }
 726                        } else {
 727                                struct wilc_cfg_rsp rsp;
 728
 729                                buff_ptr += pkt_offset;
 730
 731                                wilc_wlan_cfg_indicate_rx(wilc, buff_ptr,
 732                                                          pkt_len,
 733                                                          &rsp);
 734                                if (rsp.type == WILC_CFG_RSP) {
 735                                        if (wilc->cfg_seq_no == rsp.seq_no)
 736                                                complete(&wilc->cfg_event);
 737                                } else if (rsp.type == WILC_CFG_RSP_STATUS) {
 738                                        wilc_mac_indicate(wilc);
 739                                }
 740                        }
 741                }
 742                offset += tp_len;
 743                if (offset >= size)
 744                        break;
 745        } while (1);
 746}
 747
 748static void wilc_wlan_handle_rxq(struct wilc *wilc)
 749{
 750        int size;
 751        u8 *buffer;
 752        struct rxq_entry_t *rqe;
 753
 754        do {
 755                if (wilc->quit) {
 756                        complete(&wilc->cfg_event);
 757                        break;
 758                }
 759                rqe = wilc_wlan_rxq_remove(wilc);
 760                if (!rqe)
 761                        break;
 762
 763                buffer = rqe->buffer;
 764                size = rqe->buffer_size;
 765                wilc_wlan_handle_rx_buff(wilc, buffer, size);
 766
 767                kfree(rqe);
 768        } while (1);
 769}
 770
 771static void wilc_unknown_isr_ext(struct wilc *wilc)
 772{
 773        wilc->hif_func->hif_clear_int_ext(wilc, 0);
 774}
 775
 776static void wilc_pllupdate_isr_ext(struct wilc *wilc, u32 int_stats)
 777{
 778        int trials = 10;
 779
 780        wilc->hif_func->hif_clear_int_ext(wilc, PLL_INT_CLR);
 781
 782        if (wilc->io_type == WILC_HIF_SDIO)
 783                mdelay(WILC_PLL_TO_SDIO);
 784        else
 785                mdelay(WILC_PLL_TO_SPI);
 786
 787        while (!(is_wilc1000(wilc_get_chipid(wilc, true)) && --trials))
 788                mdelay(1);
 789}
 790
 791static void wilc_sleeptimer_isr_ext(struct wilc *wilc, u32 int_stats1)
 792{
 793        wilc->hif_func->hif_clear_int_ext(wilc, SLEEP_INT_CLR);
 794}
 795
 796static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status)
 797{
 798        u32 offset = wilc->rx_buffer_offset;
 799        u8 *buffer = NULL;
 800        u32 size;
 801        u32 retries = 0;
 802        int ret = 0;
 803        struct rxq_entry_t *rqe;
 804
 805        size = (int_status & 0x7fff) << 2;
 806
 807        while (!size && retries < 10) {
 808                wilc->hif_func->hif_read_size(wilc, &size);
 809                size = (size & 0x7fff) << 2;
 810                retries++;
 811        }
 812
 813        if (size <= 0)
 814                return;
 815
 816        if (WILC_RX_BUFF_SIZE - offset < size)
 817                offset = 0;
 818
 819        buffer = &wilc->rx_buffer[offset];
 820
 821        wilc->hif_func->hif_clear_int_ext(wilc, DATA_INT_CLR | ENABLE_RX_VMM);
 822        ret = wilc->hif_func->hif_block_rx_ext(wilc, 0, buffer, size);
 823        if (!ret)
 824                return;
 825
 826        offset += size;
 827        wilc->rx_buffer_offset = offset;
 828        rqe = kmalloc(sizeof(*rqe), GFP_KERNEL);
 829        if (!rqe)
 830                return;
 831
 832        rqe->buffer = buffer;
 833        rqe->buffer_size = size;
 834        wilc_wlan_rxq_add(wilc, rqe);
 835        wilc_wlan_handle_rxq(wilc);
 836}
 837
 838void wilc_handle_isr(struct wilc *wilc)
 839{
 840        u32 int_status;
 841
 842        acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
 843        wilc->hif_func->hif_read_int(wilc, &int_status);
 844
 845        if (int_status & PLL_INT_EXT)
 846                wilc_pllupdate_isr_ext(wilc, int_status);
 847
 848        if (int_status & DATA_INT_EXT)
 849                wilc_wlan_handle_isr_ext(wilc, int_status);
 850
 851        if (int_status & SLEEP_INT_EXT)
 852                wilc_sleeptimer_isr_ext(wilc, int_status);
 853
 854        if (!(int_status & (ALL_INT_EXT)))
 855                wilc_unknown_isr_ext(wilc);
 856
 857        release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
 858}
 859EXPORT_SYMBOL_GPL(wilc_handle_isr);
 860
 861int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
 862                                u32 buffer_size)
 863{
 864        u32 offset;
 865        u32 addr, size, size2, blksz;
 866        u8 *dma_buffer;
 867        int ret = 0;
 868
 869        blksz = BIT(12);
 870
 871        dma_buffer = kmalloc(blksz, GFP_KERNEL);
 872        if (!dma_buffer)
 873                return -EIO;
 874
 875        offset = 0;
 876        do {
 877                memcpy(&addr, &buffer[offset], 4);
 878                memcpy(&size, &buffer[offset + 4], 4);
 879                le32_to_cpus(&addr);
 880                le32_to_cpus(&size);
 881                acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
 882                offset += 8;
 883                while (((int)size) && (offset < buffer_size)) {
 884                        if (size <= blksz)
 885                                size2 = size;
 886                        else
 887                                size2 = blksz;
 888
 889                        memcpy(dma_buffer, &buffer[offset], size2);
 890                        ret = wilc->hif_func->hif_block_tx(wilc, addr,
 891                                                           dma_buffer, size2);
 892                        if (!ret)
 893                                break;
 894
 895                        addr += size2;
 896                        offset += size2;
 897                        size -= size2;
 898                }
 899                release_bus(wilc, WILC_BUS_RELEASE_ONLY);
 900
 901                if (!ret) {
 902                        ret = -EIO;
 903                        goto fail;
 904                }
 905        } while (offset < buffer_size);
 906
 907fail:
 908
 909        kfree(dma_buffer);
 910
 911        return (ret < 0) ? ret : 0;
 912}
 913
 914int wilc_wlan_start(struct wilc *wilc)
 915{
 916        u32 reg = 0;
 917        int ret;
 918        u32 chipid;
 919
 920        if (wilc->io_type == WILC_HIF_SDIO) {
 921                reg = 0;
 922                reg |= BIT(3);
 923        } else if (wilc->io_type == WILC_HIF_SPI) {
 924                reg = 1;
 925        }
 926        acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
 927        ret = wilc->hif_func->hif_write_reg(wilc, WILC_VMM_CORE_CFG, reg);
 928        if (!ret) {
 929                release_bus(wilc, WILC_BUS_RELEASE_ONLY);
 930                return -EIO;
 931        }
 932        reg = 0;
 933        if (wilc->io_type == WILC_HIF_SDIO && wilc->dev_irq_num)
 934                reg |= WILC_HAVE_SDIO_IRQ_GPIO;
 935
 936#ifdef WILC_DISABLE_PMU
 937#else
 938        reg |= WILC_HAVE_USE_PMU;
 939#endif
 940
 941#ifdef WILC_SLEEP_CLK_SRC_XO
 942        reg |= WILC_HAVE_SLEEP_CLK_SRC_XO;
 943#elif defined WILC_SLEEP_CLK_SRC_RTC
 944        reg |= WILC_HAVE_SLEEP_CLK_SRC_RTC;
 945#endif
 946
 947#ifdef WILC_EXT_PA_INV_TX_RX
 948        reg |= WILC_HAVE_EXT_PA_INV_TX_RX;
 949#endif
 950        reg |= WILC_HAVE_USE_IRQ_AS_HOST_WAKE;
 951        reg |= WILC_HAVE_LEGACY_RF_SETTINGS;
 952#ifdef XTAL_24
 953        reg |= WILC_HAVE_XTAL_24;
 954#endif
 955#ifdef DISABLE_WILC_UART
 956        reg |= WILC_HAVE_DISABLE_WILC_UART;
 957#endif
 958
 959        ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_1, reg);
 960        if (!ret) {
 961                release_bus(wilc, WILC_BUS_RELEASE_ONLY);
 962                return -EIO;
 963        }
 964
 965        wilc->hif_func->hif_sync_ext(wilc, NUM_INT_EXT);
 966
 967        ret = wilc->hif_func->hif_read_reg(wilc, 0x1000, &chipid);
 968        if (!ret) {
 969                release_bus(wilc, WILC_BUS_RELEASE_ONLY);
 970                return -EIO;
 971        }
 972
 973        wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
 974        if ((reg & BIT(10)) == BIT(10)) {
 975                reg &= ~BIT(10);
 976                wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg);
 977                wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
 978        }
 979
 980        reg |= BIT(10);
 981        ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg);
 982        wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
 983        release_bus(wilc, WILC_BUS_RELEASE_ONLY);
 984
 985        return (ret < 0) ? ret : 0;
 986}
 987
 988int wilc_wlan_stop(struct wilc *wilc)
 989{
 990        u32 reg = 0;
 991        int ret;
 992        u8 timeout = 10;
 993
 994        acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
 995
 996        ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
 997        if (!ret) {
 998                release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
 999                return ret;
1000        }
1001
1002        reg &= ~BIT(10);
1003        ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg);
1004        if (!ret) {
1005                release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
1006                return ret;
1007        }
1008
1009        do {
1010                ret = wilc->hif_func->hif_read_reg(wilc,
1011                                                   WILC_GLB_RESET_0, &reg);
1012                if (!ret) {
1013                        release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
1014                        return ret;
1015                }
1016
1017                if ((reg & BIT(10))) {
1018                        reg &= ~BIT(10);
1019                        ret = wilc->hif_func->hif_write_reg(wilc,
1020                                                            WILC_GLB_RESET_0,
1021                                                            reg);
1022                        timeout--;
1023                } else {
1024                        ret = wilc->hif_func->hif_read_reg(wilc,
1025                                                           WILC_GLB_RESET_0,
1026                                                           &reg);
1027                        if (!ret) {
1028                                release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
1029                                return ret;
1030                        }
1031                        break;
1032                }
1033
1034        } while (timeout);
1035        reg = (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(8) | BIT(9) | BIT(26) |
1036               BIT(29) | BIT(30) | BIT(31));
1037
1038        wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg);
1039        reg = (u32)~BIT(10);
1040
1041        ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg);
1042
1043        release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
1044
1045        return ret;
1046}
1047
1048void wilc_wlan_cleanup(struct net_device *dev)
1049{
1050        struct txq_entry_t *tqe;
1051        struct rxq_entry_t *rqe;
1052        u32 reg = 0;
1053        int ret;
1054        struct wilc_vif *vif = netdev_priv(dev);
1055        struct wilc *wilc = vif->wilc;
1056
1057        wilc->quit = 1;
1058        do {
1059                tqe = wilc_wlan_txq_remove_from_head(dev);
1060                if (!tqe)
1061                        break;
1062                if (tqe->tx_complete_func)
1063                        tqe->tx_complete_func(tqe->priv, 0);
1064                kfree(tqe);
1065        } while (1);
1066
1067        do {
1068                rqe = wilc_wlan_rxq_remove(wilc);
1069                if (!rqe)
1070                        break;
1071                kfree(rqe);
1072        } while (1);
1073
1074        kfree(wilc->rx_buffer);
1075        wilc->rx_buffer = NULL;
1076        kfree(wilc->tx_buffer);
1077        wilc->tx_buffer = NULL;
1078
1079        acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
1080
1081        ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, &reg);
1082        if (!ret) {
1083                release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
1084                return;
1085        }
1086
1087        ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0,
1088                                        (reg | ABORT_INT));
1089        if (!ret) {
1090                release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
1091                return;
1092        }
1093
1094        release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
1095        wilc->hif_func->hif_deinit(NULL);
1096}
1097
1098static int wilc_wlan_cfg_commit(struct wilc_vif *vif, int type,
1099                                u32 drv_handler)
1100{
1101        struct wilc *wilc = vif->wilc;
1102        struct wilc_cfg_frame *cfg = &wilc->cfg_frame;
1103        int t_len = wilc->cfg_frame_offset + sizeof(struct wilc_cfg_cmd_hdr);
1104
1105        if (type == WILC_CFG_SET)
1106                cfg->hdr.cmd_type = 'W';
1107        else
1108                cfg->hdr.cmd_type = 'Q';
1109
1110        cfg->hdr.seq_no = wilc->cfg_seq_no % 256;
1111        cfg->hdr.total_len = cpu_to_le16(t_len);
1112        cfg->hdr.driver_handler = cpu_to_le32(drv_handler);
1113        wilc->cfg_seq_no = cfg->hdr.seq_no;
1114
1115        if (!wilc_wlan_txq_add_cfg_pkt(vif, (u8 *)&cfg->hdr, t_len))
1116                return -1;
1117
1118        return 0;
1119}
1120
1121int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer,
1122                      u32 buffer_size, int commit, u32 drv_handler)
1123{
1124        u32 offset;
1125        int ret_size;
1126        struct wilc *wilc = vif->wilc;
1127
1128        mutex_lock(&wilc->cfg_cmd_lock);
1129
1130        if (start)
1131                wilc->cfg_frame_offset = 0;
1132
1133        offset = wilc->cfg_frame_offset;
1134        ret_size = wilc_wlan_cfg_set_wid(wilc->cfg_frame.frame, offset,
1135                                         wid, buffer, buffer_size);
1136        offset += ret_size;
1137        wilc->cfg_frame_offset = offset;
1138
1139        if (!commit) {
1140                mutex_unlock(&wilc->cfg_cmd_lock);
1141                return ret_size;
1142        }
1143
1144        netdev_dbg(vif->ndev, "%s: seqno[%d]\n", __func__, wilc->cfg_seq_no);
1145
1146        if (wilc_wlan_cfg_commit(vif, WILC_CFG_SET, drv_handler))
1147                ret_size = 0;
1148
1149        if (!wait_for_completion_timeout(&wilc->cfg_event,
1150                                         WILC_CFG_PKTS_TIMEOUT)) {
1151                netdev_dbg(vif->ndev, "%s: Timed Out\n", __func__);
1152                ret_size = 0;
1153        }
1154
1155        wilc->cfg_frame_offset = 0;
1156        wilc->cfg_seq_no += 1;
1157        mutex_unlock(&wilc->cfg_cmd_lock);
1158
1159        return ret_size;
1160}
1161
1162int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit,
1163                      u32 drv_handler)
1164{
1165        u32 offset;
1166        int ret_size;
1167        struct wilc *wilc = vif->wilc;
1168
1169        mutex_lock(&wilc->cfg_cmd_lock);
1170
1171        if (start)
1172                wilc->cfg_frame_offset = 0;
1173
1174        offset = wilc->cfg_frame_offset;
1175        ret_size = wilc_wlan_cfg_get_wid(wilc->cfg_frame.frame, offset, wid);
1176        offset += ret_size;
1177        wilc->cfg_frame_offset = offset;
1178
1179        if (!commit) {
1180                mutex_unlock(&wilc->cfg_cmd_lock);
1181                return ret_size;
1182        }
1183
1184        if (wilc_wlan_cfg_commit(vif, WILC_CFG_QUERY, drv_handler))
1185                ret_size = 0;
1186
1187        if (!wait_for_completion_timeout(&wilc->cfg_event,
1188                                         WILC_CFG_PKTS_TIMEOUT)) {
1189                netdev_dbg(vif->ndev, "%s: Timed Out\n", __func__);
1190                ret_size = 0;
1191        }
1192        wilc->cfg_frame_offset = 0;
1193        wilc->cfg_seq_no += 1;
1194        mutex_unlock(&wilc->cfg_cmd_lock);
1195
1196        return ret_size;
1197}
1198
1199int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, u32 buffer_size)
1200{
1201        return wilc_wlan_cfg_get_wid_value(wl, wid, buffer, buffer_size);
1202}
1203
1204int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids,
1205                         u32 count)
1206{
1207        int i;
1208        int ret = 0;
1209        u32 drv = wilc_get_vif_idx(vif);
1210
1211        if (mode == WILC_GET_CFG) {
1212                for (i = 0; i < count; i++) {
1213                        if (!wilc_wlan_cfg_get(vif, !i,
1214                                               wids[i].id,
1215                                               (i == count - 1),
1216                                               drv)) {
1217                                ret = -ETIMEDOUT;
1218                                break;
1219                        }
1220                }
1221                for (i = 0; i < count; i++) {
1222                        wids[i].size = wilc_wlan_cfg_get_val(vif->wilc,
1223                                                             wids[i].id,
1224                                                             wids[i].val,
1225                                                             wids[i].size);
1226                }
1227        } else if (mode == WILC_SET_CFG) {
1228                for (i = 0; i < count; i++) {
1229                        if (!wilc_wlan_cfg_set(vif, !i,
1230                                               wids[i].id,
1231                                               wids[i].val,
1232                                               wids[i].size,
1233                                               (i == count - 1),
1234                                               drv)) {
1235                                ret = -ETIMEDOUT;
1236                                break;
1237                        }
1238                }
1239        }
1240
1241        return ret;
1242}
1243
1244static u32 init_chip(struct net_device *dev)
1245{
1246        u32 chipid;
1247        u32 reg, ret = 0;
1248        struct wilc_vif *vif = netdev_priv(dev);
1249        struct wilc *wilc = vif->wilc;
1250
1251        acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
1252
1253        chipid = wilc_get_chipid(wilc, true);
1254
1255        if ((chipid & 0xfff) != 0xa0) {
1256                ret = wilc->hif_func->hif_read_reg(wilc, 0x1118, &reg);
1257                if (!ret) {
1258                        netdev_err(dev, "fail read reg 0x1118\n");
1259                        goto release;
1260                }
1261                reg |= BIT(0);
1262                ret = wilc->hif_func->hif_write_reg(wilc, 0x1118, reg);
1263                if (!ret) {
1264                        netdev_err(dev, "fail write reg 0x1118\n");
1265                        goto release;
1266                }
1267                ret = wilc->hif_func->hif_write_reg(wilc, 0xc0000, 0x71);
1268                if (!ret) {
1269                        netdev_err(dev, "fail write reg 0xc0000\n");
1270                        goto release;
1271                }
1272        }
1273
1274release:
1275        release_bus(wilc, WILC_BUS_RELEASE_ONLY);
1276
1277        return ret;
1278}
1279
1280u32 wilc_get_chipid(struct wilc *wilc, bool update)
1281{
1282        static u32 chipid;
1283        u32 tempchipid = 0;
1284        u32 rfrevid = 0;
1285
1286        if (chipid == 0 || update) {
1287                wilc->hif_func->hif_read_reg(wilc, 0x1000, &tempchipid);
1288                wilc->hif_func->hif_read_reg(wilc, 0x13f4, &rfrevid);
1289                if (!is_wilc1000(tempchipid)) {
1290                        chipid = 0;
1291                        return chipid;
1292                }
1293                if (tempchipid == 0x1002a0) {
1294                        if (rfrevid != 0x1)
1295                                tempchipid = 0x1002a1;
1296                } else if (tempchipid == 0x1002b0) {
1297                        if (rfrevid == 0x4)
1298                                tempchipid = 0x1002b1;
1299                        else if (rfrevid != 0x3)
1300                                tempchipid = 0x1002b2;
1301                }
1302
1303                chipid = tempchipid;
1304        }
1305        return chipid;
1306}
1307
1308int wilc_wlan_init(struct net_device *dev)
1309{
1310        int ret = 0;
1311        struct wilc_vif *vif = netdev_priv(dev);
1312        struct wilc *wilc;
1313
1314        wilc = vif->wilc;
1315
1316        wilc->quit = 0;
1317
1318        if (!wilc->hif_func->hif_init(wilc, false)) {
1319                ret = -EIO;
1320                goto fail;
1321        }
1322
1323        if (!wilc->tx_buffer)
1324                wilc->tx_buffer = kmalloc(WILC_TX_BUFF_SIZE, GFP_KERNEL);
1325
1326        if (!wilc->tx_buffer) {
1327                ret = -ENOBUFS;
1328                goto fail;
1329        }
1330
1331        if (!wilc->rx_buffer)
1332                wilc->rx_buffer = kmalloc(WILC_RX_BUFF_SIZE, GFP_KERNEL);
1333
1334        if (!wilc->rx_buffer) {
1335                ret = -ENOBUFS;
1336                goto fail;
1337        }
1338
1339        if (!init_chip(dev)) {
1340                ret = -EIO;
1341                goto fail;
1342        }
1343
1344        return 1;
1345
1346fail:
1347
1348        kfree(wilc->rx_buffer);
1349        wilc->rx_buffer = NULL;
1350        kfree(wilc->tx_buffer);
1351        wilc->tx_buffer = NULL;
1352
1353        return ret;
1354}
1355