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