linux/drivers/staging/wilc1000/wilc_wlan.c
<<
>>
Prefs
   1/* ////////////////////////////////////////////////////////////////////////// */
   2/*  */
   3/* Copyright (c) Atmel Corporation.  All rights reserved. */
   4/*  */
   5/* Module Name:  wilc_wlan.c */
   6/*  */
   7/*  */
   8/* //////////////////////////////////////////////////////////////////////////// */
   9
  10#include "wilc_wlan_if.h"
  11#include "wilc_wlan.h"
  12#define INLINE static __inline
  13
  14/********************************************
  15 *
  16 *      Global
  17 *
  18 ********************************************/
  19extern unsigned int int_clrd;
  20extern wilc_hif_func_t hif_sdio;
  21extern wilc_hif_func_t hif_spi;
  22extern wilc_cfg_func_t mac_cfg;
  23#if defined(PLAT_RK3026_TCHIP)
  24extern u8 g_wilc_initialized; /* AMR : 0422 RK3026 Crash issue */
  25#endif
  26extern void WILC_WFI_mgmt_rx(uint8_t *buff, uint32_t size);
  27extern void frmw_to_linux(uint8_t *buff, uint32_t size);
  28int sdio_xfer_cnt(void);
  29uint32_t wilc_get_chipid(uint8_t update);
  30u16 Set_machw_change_vir_if(bool bValue);
  31
  32
  33
  34typedef struct {
  35        int quit;
  36
  37        /**
  38         *      input interface functions
  39         **/
  40        wilc_wlan_os_func_t os_func;
  41        wilc_wlan_io_func_t io_func;
  42        wilc_wlan_net_func_t net_func;
  43        wilc_wlan_indicate_func_t indicate_func;
  44
  45        /**
  46         *      host interface functions
  47         **/
  48        wilc_hif_func_t hif_func;
  49        void *hif_lock;
  50
  51        /**
  52         *      configuration interface functions
  53         **/
  54        wilc_cfg_func_t cif_func;
  55        int cfg_frame_in_use;
  56        wilc_cfg_frame_t cfg_frame;
  57        uint32_t cfg_frame_offset;
  58        int cfg_seq_no;
  59        void *cfg_wait;
  60
  61        /**
  62         *      RX buffer
  63         **/
  64        #ifdef MEMORY_STATIC
  65        uint32_t rx_buffer_size;
  66        uint8_t *rx_buffer;
  67        uint32_t rx_buffer_offset;
  68        #endif
  69        /**
  70         *      TX buffer
  71         **/
  72        uint32_t tx_buffer_size;
  73        uint8_t *tx_buffer;
  74        uint32_t tx_buffer_offset;
  75
  76        /**
  77         *      TX queue
  78         **/
  79        void *txq_lock;
  80
  81        /*Added by Amr - BugID_4720*/
  82        void *txq_add_to_head_lock;
  83        void *txq_spinlock;
  84        unsigned long txq_spinlock_flags;
  85
  86        struct txq_entry_t *txq_head;
  87        struct txq_entry_t *txq_tail;
  88        int txq_entries;
  89        void *txq_wait;
  90        int txq_exit;
  91
  92        /**
  93         *      RX queue
  94         **/
  95        void *rxq_lock;
  96        struct rxq_entry_t *rxq_head;
  97        struct rxq_entry_t *rxq_tail;
  98        int rxq_entries;
  99        void *rxq_wait;
 100        int rxq_exit;
 101
 102
 103} wilc_wlan_dev_t;
 104
 105static wilc_wlan_dev_t g_wlan;
 106
 107INLINE void chip_allow_sleep(void);
 108INLINE void chip_wakeup(void);
 109/********************************************
 110 *
 111 *      Debug
 112 *
 113 ********************************************/
 114
 115static uint32_t dbgflag = N_INIT | N_ERR | N_INTR | N_TXQ | N_RXQ;
 116
 117static void wilc_debug(uint32_t flag, char *fmt, ...)
 118{
 119        char buf[256];
 120        va_list args;
 121        int len;
 122
 123        if (flag & dbgflag) {
 124                va_start(args, fmt);
 125                len = vsprintf(buf, fmt, args);
 126                va_end(args);
 127
 128                if (g_wlan.os_func.os_debug)
 129                        g_wlan.os_func.os_debug(buf);
 130        }
 131
 132        return;
 133}
 134
 135static CHIP_PS_STATE_T genuChipPSstate = CHIP_WAKEDUP;
 136
 137/*BugID_5213*/
 138/*acquire_bus() and release_bus() are made INLINE functions*/
 139/*as a temporary workaround to fix a problem of receiving*/
 140/*unknown interrupt from FW*/
 141INLINE void acquire_bus(BUS_ACQUIRE_T acquire)
 142{
 143
 144        g_wlan.os_func.os_enter_cs(g_wlan.hif_lock);
 145        #ifndef WILC_OPTIMIZE_SLEEP_INT
 146        if (genuChipPSstate != CHIP_WAKEDUP)
 147        #endif
 148        {
 149                if (acquire == ACQUIRE_AND_WAKEUP)
 150                        chip_wakeup();
 151        }
 152
 153}
 154INLINE void release_bus(BUS_RELEASE_T release)
 155{
 156        #ifdef WILC_OPTIMIZE_SLEEP_INT
 157        if (release == RELEASE_ALLOW_SLEEP)
 158                chip_allow_sleep();
 159        #endif
 160        g_wlan.os_func.os_leave_cs(g_wlan.hif_lock);
 161}
 162/********************************************
 163 *
 164 *      Queue
 165 *
 166 ********************************************/
 167
 168static void wilc_wlan_txq_remove(struct txq_entry_t *tqe)
 169{
 170
 171        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
 172        /* unsigned long flags; */
 173        if (tqe == p->txq_head) {
 174
 175                p->txq_head = tqe->next;
 176                if (p->txq_head)
 177                        p->txq_head->prev = NULL;
 178
 179
 180        } else if (tqe == p->txq_tail)      {
 181                p->txq_tail = (tqe->prev);
 182                if (p->txq_tail)
 183                        p->txq_tail->next = NULL;
 184        } else {
 185                tqe->prev->next = tqe->next;
 186                tqe->next->prev = tqe->prev;
 187        }
 188        p->txq_entries -= 1;
 189
 190}
 191
 192static struct txq_entry_t *wilc_wlan_txq_remove_from_head(void)
 193{
 194        struct txq_entry_t *tqe;
 195        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
 196        unsigned long flags;
 197        p->os_func.os_spin_lock(p->txq_spinlock, &flags);
 198        if (p->txq_head) {
 199                tqe = p->txq_head;
 200                p->txq_head = tqe->next;
 201                if (p->txq_head) {
 202                        p->txq_head->prev = NULL;
 203                }
 204                p->txq_entries -= 1;
 205
 206                /*Added by Amr - BugID_4720*/
 207
 208
 209
 210        } else {
 211                tqe = NULL;
 212        }
 213        p->os_func.os_spin_unlock(p->txq_spinlock, &flags);
 214        return tqe;
 215}
 216
 217static void wilc_wlan_txq_add_to_tail(struct txq_entry_t *tqe)
 218{
 219        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
 220        unsigned long flags;
 221        /*Added by Amr - BugID_4720*/
 222        p->os_func.os_spin_lock(p->txq_spinlock, &flags);
 223
 224        if (p->txq_head == NULL) {
 225                tqe->next = NULL;
 226                tqe->prev = NULL;
 227                p->txq_head = tqe;
 228                p->txq_tail = tqe;
 229        } else {
 230                tqe->next = NULL;
 231                tqe->prev = p->txq_tail;
 232                p->txq_tail->next = tqe;
 233                p->txq_tail = tqe;
 234        }
 235        p->txq_entries += 1;
 236        PRINT_D(TX_DBG, "Number of entries in TxQ = %d\n", p->txq_entries);
 237
 238        /*Added by Amr - BugID_4720*/
 239        p->os_func.os_spin_unlock(p->txq_spinlock, &flags);
 240
 241        /**
 242         *      wake up TX queue
 243         **/
 244        PRINT_D(TX_DBG, "Wake the txq_handling\n");
 245
 246        p->os_func.os_signal(p->txq_wait);
 247
 248
 249}
 250
 251static int wilc_wlan_txq_add_to_head(struct txq_entry_t *tqe)
 252{
 253        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
 254        unsigned long flags;
 255        /*Added by Amr - BugID_4720*/
 256        if (p->os_func.os_wait(p->txq_add_to_head_lock, CFG_PKTS_TIMEOUT))
 257                return -1;
 258
 259        p->os_func.os_spin_lock(p->txq_spinlock, &flags);
 260
 261        if (p->txq_head == NULL) {
 262                tqe->next = NULL;
 263                tqe->prev = NULL;
 264                p->txq_head = tqe;
 265                p->txq_tail = tqe;
 266        } else {
 267                tqe->next = p->txq_head;
 268                tqe->prev = NULL;
 269                p->txq_head->prev = tqe;
 270                p->txq_head = tqe;
 271        }
 272        p->txq_entries += 1;
 273        PRINT_D(TX_DBG, "Number of entries in TxQ = %d\n", p->txq_entries);
 274
 275        /*Added by Amr - BugID_4720*/
 276        p->os_func.os_spin_unlock(p->txq_spinlock, &flags);
 277        p->os_func.os_signal(p->txq_add_to_head_lock);
 278
 279
 280        /**
 281         *      wake up TX queue
 282         **/
 283        p->os_func.os_signal(p->txq_wait);
 284        PRINT_D(TX_DBG, "Wake up the txq_handler\n");
 285
 286        /*Added by Amr - BugID_4720*/
 287        return 0;
 288
 289}
 290
 291uint32_t Statisitcs_totalAcks = 0, Statisitcs_DroppedAcks = 0;
 292
 293#ifdef  TCP_ACK_FILTER
 294struct Ack_session_info;
 295typedef struct Ack_session_info {
 296        uint32_t Ack_seq_num;
 297        uint32_t Bigger_Ack_num;
 298        uint16_t src_port;
 299        uint16_t dst_port;
 300        uint16_t status;
 301} Ack_session_info_t;
 302
 303typedef struct {
 304        uint32_t ack_num;
 305        uint32_t Session_index;
 306        struct txq_entry_t  *txqe;
 307} Pending_Acks_info_t /*Ack_info_t*/;
 308
 309
 310
 311
 312struct Ack_session_info *Free_head;
 313struct Ack_session_info *Alloc_head;
 314
 315#define TCP_FIN_MASK            (1 << 0)
 316#define TCP_SYN_MASK            (1 << 1)
 317#define TCP_Ack_MASK            (1 << 4)
 318#define NOT_TCP_ACK                     (-1)
 319
 320#define MAX_TCP_SESSION         25
 321#define MAX_PENDING_ACKS                256
 322Ack_session_info_t Acks_keep_track_info[2 * MAX_TCP_SESSION];
 323Pending_Acks_info_t Pending_Acks_info[MAX_PENDING_ACKS];
 324
 325uint32_t PendingAcks_arrBase;
 326uint32_t Opened_TCP_session;
 327uint32_t Pending_Acks;
 328
 329
 330
 331static __inline int Init_TCP_tracking(void)
 332{
 333
 334        return 0;
 335
 336}
 337static __inline int add_TCP_track_session(uint32_t src_prt, uint32_t dst_prt, uint32_t seq)
 338{
 339        Acks_keep_track_info[Opened_TCP_session].Ack_seq_num = seq;
 340        Acks_keep_track_info[Opened_TCP_session].Bigger_Ack_num = 0;
 341        Acks_keep_track_info[Opened_TCP_session].src_port = src_prt;
 342        Acks_keep_track_info[Opened_TCP_session].dst_port = dst_prt;
 343        Opened_TCP_session++;
 344
 345        PRINT_D(TCP_ENH, "TCP Session %d to Ack %d\n", Opened_TCP_session, seq);
 346        return 0;
 347}
 348
 349static __inline int Update_TCP_track_session(uint32_t index, uint32_t Ack)
 350{
 351
 352        if (Ack > Acks_keep_track_info[index].Bigger_Ack_num) {
 353                Acks_keep_track_info[index].Bigger_Ack_num = Ack;
 354        }
 355        return 0;
 356
 357}
 358static __inline int add_TCP_Pending_Ack(uint32_t Ack, uint32_t Session_index, struct txq_entry_t  *txqe)
 359{
 360        Statisitcs_totalAcks++;
 361        if (Pending_Acks < MAX_PENDING_ACKS) {
 362                Pending_Acks_info[PendingAcks_arrBase + Pending_Acks].ack_num = Ack;
 363                Pending_Acks_info[PendingAcks_arrBase + Pending_Acks].txqe = txqe;
 364                Pending_Acks_info[PendingAcks_arrBase + Pending_Acks].Session_index = Session_index;
 365                txqe->tcp_PendingAck_index = PendingAcks_arrBase + Pending_Acks;
 366                Pending_Acks++;
 367
 368        } else {
 369
 370        }
 371        return 0;
 372}
 373static __inline int remove_TCP_related(void)
 374{
 375        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
 376        unsigned long flags;
 377        p->os_func.os_spin_lock(p->txq_spinlock, &flags);
 378
 379        p->os_func.os_spin_unlock(p->txq_spinlock, &flags);
 380        return 0;
 381}
 382
 383static __inline int tcp_process(struct txq_entry_t *tqe)
 384{
 385        int ret;
 386        uint8_t *eth_hdr_ptr;
 387        uint8_t *buffer = tqe->buffer;
 388        unsigned short h_proto;
 389        int i;
 390        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
 391        unsigned long flags;
 392        p->os_func.os_spin_lock(p->txq_spinlock, &flags);
 393
 394        eth_hdr_ptr = &buffer[0];
 395        h_proto = ntohs(*((unsigned short *)&eth_hdr_ptr[12]));
 396        if (h_proto == 0x0800) { /* IP */
 397                uint8_t *ip_hdr_ptr;
 398                uint8_t protocol;
 399
 400                ip_hdr_ptr = &buffer[ETHERNET_HDR_LEN];
 401                protocol = ip_hdr_ptr[9];
 402
 403
 404                if (protocol == 0x06) {
 405                        uint8_t *tcp_hdr_ptr;
 406                        uint32_t IHL, Total_Length, Data_offset;
 407                        tcp_hdr_ptr = &ip_hdr_ptr[IP_HDR_LEN];
 408                        IHL = (ip_hdr_ptr[0] & 0xf) << 2;
 409                        Total_Length = (((uint32_t)ip_hdr_ptr[2]) << 8) + ((uint32_t)ip_hdr_ptr[3]);
 410                        Data_offset = (((uint32_t)tcp_hdr_ptr[12] & 0xf0) >> 2);
 411                        if (Total_Length == (IHL + Data_offset)) { /*we want to recognize the clear Acks(packet only carry Ack infos not with data) so data size must be equal zero*/
 412                                uint32_t seq_no, Ack_no;
 413                                seq_no  = (((uint32_t)tcp_hdr_ptr[4]) << 24) + (((uint32_t)tcp_hdr_ptr[5]) << 16) + (((uint32_t)tcp_hdr_ptr[6]) << 8) + ((uint32_t)tcp_hdr_ptr[7]);
 414
 415                                Ack_no  = (((uint32_t)tcp_hdr_ptr[8]) << 24) + (((uint32_t)tcp_hdr_ptr[9]) << 16) + (((uint32_t)tcp_hdr_ptr[10]) << 8) + ((uint32_t)tcp_hdr_ptr[11]);
 416
 417
 418                                for (i = 0; i < Opened_TCP_session; i++) {
 419                                        if (Acks_keep_track_info[i].Ack_seq_num == seq_no) {
 420                                                Update_TCP_track_session(i, Ack_no);
 421                                                break;
 422                                        }
 423                                }
 424                                if (i == Opened_TCP_session) {
 425                                        add_TCP_track_session(0, 0, seq_no);
 426                                }
 427                                add_TCP_Pending_Ack(Ack_no, i, tqe);
 428
 429
 430                        }
 431
 432                } else {
 433                        ret = 0;
 434                }
 435        } else {
 436                ret = 0;
 437        }
 438        p->os_func.os_spin_unlock(p->txq_spinlock, &flags);
 439        return ret;
 440}
 441
 442
 443static int wilc_wlan_txq_filter_dup_tcp_ack(void)
 444{
 445
 446        uint32_t i = 0;
 447        uint32_t Dropped = 0;
 448        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
 449
 450        p->os_func.os_spin_lock(p->txq_spinlock, &p->txq_spinlock_flags);
 451        for (i = PendingAcks_arrBase; i < (PendingAcks_arrBase + Pending_Acks); i++) {
 452                if (Pending_Acks_info[i].ack_num < Acks_keep_track_info[Pending_Acks_info[i].Session_index].Bigger_Ack_num) {
 453                        struct txq_entry_t *tqe;
 454                        PRINT_D(TCP_ENH, "DROP ACK: %u \n", Pending_Acks_info[i].ack_num);
 455                        tqe = Pending_Acks_info[i].txqe;
 456                        if (tqe) {
 457                                wilc_wlan_txq_remove(tqe);
 458                                Statisitcs_DroppedAcks++;
 459                                tqe->status = 1;                                /* mark the packet send */
 460                                if (tqe->tx_complete_func)
 461                                        tqe->tx_complete_func(tqe->priv, tqe->status);
 462                                p->os_func.os_free(tqe);
 463                                Dropped++;
 464                        }
 465                }
 466        }
 467        Pending_Acks = 0;
 468        Opened_TCP_session = 0;
 469
 470        if (PendingAcks_arrBase == 0) {
 471                PendingAcks_arrBase = MAX_TCP_SESSION;
 472        } else {
 473                PendingAcks_arrBase = 0;
 474        }
 475
 476
 477        p->os_func.os_spin_unlock(p->txq_spinlock, &p->txq_spinlock_flags);
 478
 479        while (Dropped > 0) {
 480                /*consume the semaphore count of the removed packet*/
 481                p->os_func.os_wait(p->txq_wait, 1);
 482                Dropped--;
 483        }
 484
 485        return 1;
 486}
 487#endif
 488
 489#ifdef TCP_ENHANCEMENTS
 490bool EnableTCPAckFilter = false;
 491
 492void Enable_TCP_ACK_Filter(bool value)
 493{
 494        EnableTCPAckFilter = value;
 495}
 496
 497bool is_TCP_ACK_Filter_Enabled(void)
 498{
 499        return EnableTCPAckFilter;
 500}
 501#endif
 502
 503static int wilc_wlan_txq_add_cfg_pkt(uint8_t *buffer, uint32_t buffer_size)
 504{
 505        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
 506        struct txq_entry_t *tqe;
 507
 508        PRINT_D(TX_DBG, "Adding config packet ...\n");
 509        if (p->quit) {
 510                PRINT_D(TX_DBG, "Return due to clear function\n");
 511                p->os_func.os_signal(p->cfg_wait);
 512                return 0;
 513        }
 514
 515        tqe = (struct txq_entry_t *)p->os_func.os_malloc_atomic(sizeof(struct txq_entry_t));
 516        if (tqe == NULL) {
 517                PRINT_ER("Failed to allocate memory\n");
 518                return 0;
 519        }
 520
 521        tqe->type = WILC_CFG_PKT;
 522        tqe->buffer = buffer;
 523        tqe->buffer_size = buffer_size;
 524        tqe->tx_complete_func = NULL;
 525        tqe->priv = NULL;
 526#ifdef TCP_ACK_FILTER
 527        tqe->tcp_PendingAck_index = NOT_TCP_ACK;
 528#endif
 529        /**
 530         *      Configuration packet always at the front
 531         **/
 532        PRINT_D(TX_DBG, "Adding the config packet at the Queue tail\n");
 533
 534        /*Edited by Amr - BugID_4720*/
 535        if (wilc_wlan_txq_add_to_head(tqe))
 536                return 0;
 537        return 1;
 538}
 539
 540static int wilc_wlan_txq_add_net_pkt(void *priv, uint8_t *buffer, uint32_t buffer_size, wilc_tx_complete_func_t func)
 541{
 542        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
 543        struct txq_entry_t *tqe;
 544
 545        if (p->quit)
 546                return 0;
 547
 548        tqe = (struct txq_entry_t *)p->os_func.os_malloc_atomic(sizeof(struct txq_entry_t));
 549
 550        if (tqe == NULL)
 551                return 0;
 552        tqe->type = WILC_NET_PKT;
 553        tqe->buffer = buffer;
 554        tqe->buffer_size = buffer_size;
 555        tqe->tx_complete_func = func;
 556        tqe->priv = priv;
 557
 558        PRINT_D(TX_DBG, "Adding mgmt packet at the Queue tail\n");
 559#ifdef TCP_ACK_FILTER
 560        tqe->tcp_PendingAck_index = NOT_TCP_ACK;
 561#ifdef TCP_ENHANCEMENTS
 562        if (is_TCP_ACK_Filter_Enabled())
 563#endif
 564        tcp_process(tqe);
 565#endif
 566        wilc_wlan_txq_add_to_tail(tqe);
 567        /*return number of itemes in the queue*/
 568        return p->txq_entries;
 569}
 570/*Bug3959: transmitting mgmt frames received from host*/
 571#if defined(WILC_AP_EXTERNAL_MLME) || defined(WILC_P2P)
 572int wilc_wlan_txq_add_mgmt_pkt(void *priv, uint8_t *buffer, uint32_t buffer_size, wilc_tx_complete_func_t func)
 573{
 574
 575        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
 576        struct txq_entry_t *tqe;
 577
 578        if (p->quit)
 579                return 0;
 580
 581        tqe = (struct txq_entry_t *)p->os_func.os_malloc_atomic(sizeof(struct txq_entry_t));
 582
 583        if (tqe == NULL)
 584                return 0;
 585        tqe->type = WILC_MGMT_PKT;
 586        tqe->buffer = buffer;
 587        tqe->buffer_size = buffer_size;
 588        tqe->tx_complete_func = func;
 589        tqe->priv = priv;
 590#ifdef TCP_ACK_FILTER
 591        tqe->tcp_PendingAck_index = NOT_TCP_ACK;
 592#endif
 593        PRINT_D(TX_DBG, "Adding Network packet at the Queue tail\n");
 594        wilc_wlan_txq_add_to_tail(tqe);
 595        return 1;
 596}
 597
 598#ifdef WILC_FULLY_HOSTING_AP
 599int wilc_FH_wlan_txq_add_net_pkt(void *priv, uint8_t *buffer, uint32_t buffer_size, wilc_tx_complete_func_t func)
 600{
 601        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
 602        struct txq_entry_t *tqe;
 603
 604        if (p->quit)
 605                return 0;
 606
 607        tqe = (struct txq_entry_t *)p->os_func.os_malloc_atomic(sizeof(struct txq_entry_t));
 608
 609        if (tqe == NULL)
 610                return 0;
 611        tqe->type = WILC_FH_DATA_PKT;
 612        tqe->buffer = buffer;
 613        tqe->buffer_size = buffer_size;
 614        tqe->tx_complete_func = func;
 615        tqe->priv = priv;
 616        PRINT_D(TX_DBG, "Adding mgmt packet at the Queue tail\n");
 617        wilc_wlan_txq_add_to_tail(tqe);
 618        /*return number of itemes in the queue*/
 619        return p->txq_entries;
 620}
 621#endif  /* WILC_FULLY_HOSTING_AP*/
 622#endif /*WILC_AP_EXTERNAL_MLME*/
 623static struct txq_entry_t *wilc_wlan_txq_get_first(void)
 624{
 625        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
 626        struct txq_entry_t *tqe;
 627        unsigned long flags;
 628
 629        /*Added by Amr - BugID_4720*/
 630        p->os_func.os_spin_lock(p->txq_spinlock, &flags);
 631
 632        tqe = p->txq_head;
 633
 634        /*Added by Amr - BugID_4720*/
 635        p->os_func.os_spin_unlock(p->txq_spinlock, &flags);
 636
 637
 638        return tqe;
 639}
 640
 641static struct txq_entry_t *wilc_wlan_txq_get_next(struct txq_entry_t *tqe)
 642{
 643        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
 644        unsigned long flags;
 645        /*Added by Amr - BugID_4720*/
 646        p->os_func.os_spin_lock(p->txq_spinlock, &flags);
 647
 648        tqe = tqe->next;
 649        /*Added by Amr - BugID_4720*/
 650        p->os_func.os_spin_unlock(p->txq_spinlock, &flags);
 651
 652
 653        return tqe;
 654}
 655
 656static int wilc_wlan_rxq_add(struct rxq_entry_t *rqe)
 657{
 658        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
 659
 660        if (p->quit)
 661                return 0;
 662
 663        p->os_func.os_enter_cs(p->rxq_lock);
 664        if (p->rxq_head == NULL) {
 665                PRINT_D(RX_DBG, "Add to Queue head\n");
 666                rqe->next = NULL;
 667                p->rxq_head = rqe;
 668                p->rxq_tail = rqe;
 669        } else {
 670                PRINT_D(RX_DBG, "Add to Queue tail\n");
 671                p->rxq_tail->next = rqe;
 672                rqe->next = NULL;
 673                p->rxq_tail = rqe;
 674        }
 675        p->rxq_entries += 1;
 676        PRINT_D(RX_DBG, "Number of queue entries: %d\n", p->rxq_entries);
 677        p->os_func.os_leave_cs(p->rxq_lock);
 678        return p->rxq_entries;
 679}
 680
 681static struct rxq_entry_t *wilc_wlan_rxq_remove(void)
 682{
 683        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
 684
 685        PRINT_D(RX_DBG, "Getting rxQ element\n");
 686        if (p->rxq_head) {
 687                struct rxq_entry_t *rqe;
 688
 689                p->os_func.os_enter_cs(p->rxq_lock);
 690                rqe = p->rxq_head;
 691                p->rxq_head = p->rxq_head->next;
 692                p->rxq_entries -= 1;
 693                PRINT_D(RX_DBG, "RXQ entries decreased\n");
 694                p->os_func.os_leave_cs(p->rxq_lock);
 695                return rqe;
 696        }
 697        PRINT_D(RX_DBG, "Nothing to get from Q\n");
 698        return NULL;
 699}
 700
 701
 702/********************************************
 703 *
 704 *      Power Save handle functions
 705 *
 706 ********************************************/
 707
 708
 709
 710#ifdef WILC_OPTIMIZE_SLEEP_INT
 711
 712INLINE void chip_allow_sleep(void)
 713{
 714        uint32_t reg = 0;
 715
 716        /* Clear bit 1 */
 717        g_wlan.hif_func.hif_read_reg(0xf0, &reg);
 718
 719        g_wlan.hif_func.hif_write_reg(0xf0, reg & ~(1 << 0));
 720}
 721
 722INLINE void chip_wakeup(void)
 723{
 724        uint32_t reg, clk_status_reg, trials = 0;
 725        uint32_t sleep_time;
 726
 727        if ((g_wlan.io_func.io_type & 0x1) == HIF_SPI) {
 728                do {
 729                        g_wlan.hif_func.hif_read_reg(1, &reg);
 730                        /* Set bit 1 */
 731                        g_wlan.hif_func.hif_write_reg(1, reg | (1 << 1));
 732
 733                        /* Clear bit 1*/
 734                        g_wlan.hif_func.hif_write_reg(1, reg & ~(1 << 1));
 735
 736                        do {
 737                                /* Wait for the chip to stabilize*/
 738                                WILC_Sleep(2);
 739                                /* Make sure chip is awake. This is an extra step that can be removed */
 740                                /* later to avoid the bus access overhead */
 741                                if ((wilc_get_chipid(true) == 0)) {
 742                                        wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n");
 743                                }
 744                        } while ((wilc_get_chipid(true) == 0) && ((++trials % 3) == 0));
 745
 746                } while (wilc_get_chipid(true) == 0);
 747        } else if ((g_wlan.io_func.io_type & 0x1) == HIF_SDIO)   {
 748                g_wlan.hif_func.hif_read_reg(0xf0, &reg);
 749                do {
 750                        /* Set bit 1 */
 751                        g_wlan.hif_func.hif_write_reg(0xf0, reg | (1 << 0));
 752
 753                        /* Check the clock status */
 754                        g_wlan.hif_func.hif_read_reg(0xf1, &clk_status_reg);
 755
 756                        /* in case of clocks off, wait 2ms, and check it again. */
 757                        /* if still off, wait for another 2ms, for a total wait of 6ms. */
 758                        /* If still off, redo the wake up sequence */
 759                        while (((clk_status_reg & 0x1) == 0) && (((++trials) % 3) == 0)) {
 760                                /* Wait for the chip to stabilize*/
 761                                WILC_Sleep(2);
 762
 763                                /* Make sure chip is awake. This is an extra step that can be removed */
 764                                /* later to avoid the bus access overhead */
 765                                g_wlan.hif_func.hif_read_reg(0xf1, &clk_status_reg);
 766
 767                                if ((clk_status_reg & 0x1) == 0) {
 768                                        wilc_debug(N_ERR, "clocks still OFF. Wake up failed\n");
 769                                }
 770                        }
 771                        /* in case of failure, Reset the wakeup bit to introduce a new edge on the next loop */
 772                        if ((clk_status_reg & 0x1) == 0) {
 773                                /* Reset bit 0 */
 774                                g_wlan.hif_func.hif_write_reg(0xf0, reg & (~(1 << 0)));
 775                        }
 776                } while ((clk_status_reg & 0x1) == 0);
 777        }
 778
 779
 780        if (genuChipPSstate == CHIP_SLEEPING_MANUAL) {
 781                g_wlan.hif_func.hif_read_reg(0x1C0C, &reg);
 782                reg &= ~(1 << 0);
 783                g_wlan.hif_func.hif_write_reg(0x1C0C, reg);
 784
 785                if (wilc_get_chipid(false) >= 0x1002b0) {
 786                        /* Enable PALDO back right after wakeup */
 787                        uint32_t val32;
 788                        g_wlan.hif_func.hif_read_reg(0x1e1c, &val32);
 789                        val32 |= (1 << 6);
 790                        g_wlan.hif_func.hif_write_reg(0x1e1c, val32);
 791
 792                        g_wlan.hif_func.hif_read_reg(0x1e9c, &val32);
 793                        val32 |= (1 << 6);
 794                        g_wlan.hif_func.hif_write_reg(0x1e9c, val32);
 795                }
 796        }
 797        genuChipPSstate = CHIP_WAKEDUP;
 798}
 799#else
 800INLINE void chip_wakeup(void)
 801{
 802        uint32_t reg, trials = 0;
 803        do {
 804                if ((g_wlan.io_func.io_type & 0x1) == HIF_SPI) {
 805                        g_wlan.hif_func.hif_read_reg(1, &reg);
 806                        /* Make sure bit 1 is 0 before we start. */
 807                        g_wlan.hif_func.hif_write_reg(1, reg & ~(1 << 1));
 808                        /* Set bit 1 */
 809                        g_wlan.hif_func.hif_write_reg(1, reg | (1 << 1));
 810                        /* Clear bit 1*/
 811                        g_wlan.hif_func.hif_write_reg(1, reg  & ~(1 << 1));
 812                } else if ((g_wlan.io_func.io_type & 0x1) == HIF_SDIO)   {
 813                        /* Make sure bit 0 is 0 before we start. */
 814                        g_wlan.hif_func.hif_read_reg(0xf0, &reg);
 815                        g_wlan.hif_func.hif_write_reg(0xf0, reg & ~(1 << 0));
 816                        /* Set bit 1 */
 817                        g_wlan.hif_func.hif_write_reg(0xf0, reg | (1 << 0));
 818                        /* Clear bit 1 */
 819                        g_wlan.hif_func.hif_write_reg(0xf0, reg  & ~(1 << 0));
 820                }
 821
 822                do {
 823                        /* Wait for the chip to stabilize*/
 824                        mdelay(3);
 825
 826                        /* Make sure chip is awake. This is an extra step that can be removed */
 827                        /* later to avoid the bus access overhead */
 828                        if ((wilc_get_chipid(true) == 0)) {
 829                                wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n");
 830                        }
 831                } while ((wilc_get_chipid(true) == 0) && ((++trials % 3) == 0));
 832
 833        } while (wilc_get_chipid(true) == 0);
 834
 835        if (genuChipPSstate == CHIP_SLEEPING_MANUAL) {
 836                g_wlan.hif_func.hif_read_reg(0x1C0C, &reg);
 837                reg &= ~(1 << 0);
 838                g_wlan.hif_func.hif_write_reg(0x1C0C, reg);
 839
 840                if (wilc_get_chipid(false) >= 0x1002b0) {
 841                        /* Enable PALDO back right after wakeup */
 842                        uint32_t val32;
 843                        g_wlan.hif_func.hif_read_reg(0x1e1c, &val32);
 844                        val32 |= (1 << 6);
 845                        g_wlan.hif_func.hif_write_reg(0x1e1c, val32);
 846
 847                        g_wlan.hif_func.hif_read_reg(0x1e9c, &val32);
 848                        val32 |= (1 << 6);
 849                        g_wlan.hif_func.hif_write_reg(0x1e9c, val32);
 850                }
 851        }
 852        genuChipPSstate = CHIP_WAKEDUP;
 853}
 854#endif
 855void chip_sleep_manually(u32 u32SleepTime)
 856{
 857        if (genuChipPSstate != CHIP_WAKEDUP) {
 858                /* chip is already sleeping. Do nothing */
 859                return;
 860        }
 861        acquire_bus(ACQUIRE_ONLY);
 862
 863#ifdef WILC_OPTIMIZE_SLEEP_INT
 864        chip_allow_sleep();
 865#endif
 866
 867        /* Trigger the manual sleep interrupt */
 868        g_wlan.hif_func.hif_write_reg(0x10a8, 1);
 869
 870        genuChipPSstate = CHIP_SLEEPING_MANUAL;
 871        release_bus(RELEASE_ONLY);
 872
 873}
 874
 875
 876/********************************************
 877 *
 878 *      Tx, Rx queue handle functions
 879 *
 880 ********************************************/
 881static int wilc_wlan_handle_txq(uint32_t *pu32TxqCount)
 882{
 883        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
 884        int i, entries = 0;
 885        uint32_t sum;
 886        uint32_t reg;
 887        uint8_t *txb = p->tx_buffer;
 888        uint32_t offset = 0;
 889        int vmm_sz = 0;
 890        struct txq_entry_t *tqe;
 891        int ret = 0;
 892        int counter;
 893        int timeout;
 894        uint32_t vmm_table[WILC_VMM_TBL_SIZE];
 895        p->txq_exit = 0;
 896        do {
 897                if (p->quit)
 898                        break;
 899
 900                /*Added by Amr - BugID_4720*/
 901                p->os_func.os_wait(p->txq_add_to_head_lock, CFG_PKTS_TIMEOUT);
 902#ifdef  TCP_ACK_FILTER
 903                wilc_wlan_txq_filter_dup_tcp_ack();
 904#endif
 905                /**
 906                 *      build the vmm list
 907                 **/
 908                PRINT_D(TX_DBG, "Getting the head of the TxQ\n");
 909                tqe = wilc_wlan_txq_get_first();
 910                i = 0;
 911                sum = 0;
 912                do {
 913                        /* if ((tqe != NULL) && (i < (8)) && */
 914                        /* if ((tqe != NULL) && (i < (WILC_VMM_TBL_SIZE-1)) && */
 915                        if ((tqe != NULL) && (i < (WILC_VMM_TBL_SIZE - 1)) /* reserve last entry to 0 */) {
 916
 917                                if (tqe->type == WILC_CFG_PKT) {
 918                                        vmm_sz = ETH_CONFIG_PKT_HDR_OFFSET;
 919                                }
 920                                /*Bug3959: transmitting mgmt frames received from host*/
 921                                /*vmm_sz will only be equal to tqe->buffer_size + 4 bytes (HOST_HDR_OFFSET)*/
 922                                /* in other cases WILC_MGMT_PKT and WILC_DATA_PKT_MAC_HDR*/
 923                                else if (tqe->type == WILC_NET_PKT) {
 924                                        vmm_sz = ETH_ETHERNET_HDR_OFFSET;
 925                                }
 926#ifdef WILC_FULLY_HOSTING_AP
 927                                else if (tqe->type == WILC_FH_DATA_PKT) {
 928                                        vmm_sz = FH_TX_HOST_HDR_OFFSET;
 929                                }
 930#endif
 931#ifdef WILC_AP_EXTERNAL_MLME
 932                                else {
 933                                        vmm_sz = HOST_HDR_OFFSET;
 934                                }
 935#endif
 936                                vmm_sz += tqe->buffer_size;
 937                                PRINT_D(TX_DBG, "VMM Size before alignment = %d\n", vmm_sz);
 938                                if (vmm_sz & 0x3) {                                                                                                     /* has to be word aligned */
 939                                        vmm_sz = (vmm_sz + 4) & ~0x3;
 940                                }
 941                                if ((sum + vmm_sz) > p->tx_buffer_size) {
 942                                        break;
 943                                }
 944                                PRINT_D(TX_DBG, "VMM Size AFTER alignment = %d\n", vmm_sz);
 945                                vmm_table[i] = vmm_sz / 4;                                                                                /* table take the word size */
 946                                PRINT_D(TX_DBG, "VMMTable entry size = %d\n", vmm_table[i]);
 947
 948                                if (tqe->type == WILC_CFG_PKT) {
 949                                        vmm_table[i] |= (1 << 10);
 950                                        PRINT_D(TX_DBG, "VMMTable entry changed for CFG packet = %d\n", vmm_table[i]);
 951                                }
 952#ifdef BIG_ENDIAN
 953                                vmm_table[i] = BYTE_SWAP(vmm_table[i]);
 954#endif
 955
 956                                i++;
 957                                sum += vmm_sz;
 958                                PRINT_D(TX_DBG, "sum = %d\n", sum);
 959                                tqe = wilc_wlan_txq_get_next(tqe);
 960                        } else {
 961                                break;
 962                        }
 963                } while (1);
 964
 965                if (i == 0) {           /* nothing in the queue */
 966                        PRINT_D(TX_DBG, "Nothing in TX-Q\n");
 967                        break;
 968                } else {
 969                        PRINT_D(TX_DBG, "Mark the last entry in VMM table - number of previous entries = %d\n", i);
 970                        vmm_table[i] = 0x0;     /* mark the last element to 0 */
 971                }
 972                acquire_bus(ACQUIRE_AND_WAKEUP);
 973                counter = 0;
 974                do {
 975
 976                        ret = p->hif_func.hif_read_reg(WILC_HOST_TX_CTRL, &reg);
 977                        if (!ret) {
 978                                wilc_debug(N_ERR, "[wilc txq]: fail can't read reg vmm_tbl_entry..\n");
 979                                break;
 980                        }
 981
 982                        if ((reg & 0x1) == 0) {
 983                                /**
 984                                 *      write to vmm table
 985                                 **/
 986                                PRINT_D(TX_DBG, "Writing VMM table ... with Size = %d\n", ((i + 1) * 4));
 987                                break;
 988                        } else {
 989                                counter++;
 990                                if (counter > 200) {
 991                                        counter = 0;
 992                                        PRINT_D(TX_DBG, "Looping in tx ctrl , forcce quit\n");
 993                                        ret = p->hif_func.hif_write_reg(WILC_HOST_TX_CTRL, 0);
 994                                        break;
 995                                }
 996                                /**
 997                                 *      wait for vmm table is ready
 998                                 **/
 999                                PRINT_WRN(GENERIC_DBG, "[wilc txq]: warn, vmm table not clear yet, wait... \n");
1000                                release_bus(RELEASE_ALLOW_SLEEP);
1001                                p->os_func.os_sleep(3); /* wait 3 ms */
1002                                acquire_bus(ACQUIRE_AND_WAKEUP);
1003                        }
1004                } while (!p->quit);
1005
1006                if (!ret) {
1007                        goto _end_;
1008                }
1009
1010                timeout = 200;
1011                do {
1012
1013                        /**
1014                         * write to vmm table
1015                         **/
1016                        ret = p->hif_func.hif_block_tx(WILC_VMM_TBL_RX_SHADOW_BASE, (uint8_t *)vmm_table, ((i + 1) * 4)); /* Bug 4477 fix */
1017                        if (!ret) {
1018                                wilc_debug(N_ERR, "ERR block TX of VMM table.\n");
1019                                break;
1020                        }
1021
1022
1023                        /**
1024                         * interrupt firmware
1025                         **/
1026                        ret = p->hif_func.hif_write_reg(WILC_HOST_VMM_CTL, 0x2);
1027                        if (!ret) {
1028                                wilc_debug(N_ERR, "[wilc txq]: fail can't write reg host_vmm_ctl..\n");
1029                                break;
1030                        }
1031
1032                        /**
1033                         *      wait for confirm...
1034                         **/
1035
1036                        do {
1037                                ret = p->hif_func.hif_read_reg(WILC_HOST_VMM_CTL, &reg);
1038                                if (!ret) {
1039                                        wilc_debug(N_ERR, "[wilc txq]: fail can't read reg host_vmm_ctl..\n");
1040                                        break;
1041                                }
1042                                if ((reg >> 2) & 0x1) {
1043                                        /**
1044                                         *      Get the entries
1045                                         **/
1046                                        entries = ((reg >> 3) & 0x3f);
1047                                        /* entries = ((reg>>3)&0x2f); */
1048                                        break;
1049                                } else {
1050                                        release_bus(RELEASE_ALLOW_SLEEP);
1051                                        p->os_func.os_sleep(3); /* wait 3 ms */
1052                                        acquire_bus(ACQUIRE_AND_WAKEUP);
1053                                        PRINT_WRN(GENERIC_DBG, "Can't get VMM entery - reg = %2x\n", reg);
1054                                }
1055                        } while (--timeout);
1056                        if (timeout <= 0) {
1057                                ret = p->hif_func.hif_write_reg(WILC_HOST_VMM_CTL, 0x0);
1058                                break;
1059                        }
1060
1061                        if (!ret) {
1062                                break;
1063                        }
1064
1065                        if (entries == 0) {
1066                                PRINT_WRN(GENERIC_DBG, "[wilc txq]: no more buffer in the chip (reg: %08x), retry later [[ %d, %x ]] \n", reg, i, vmm_table[i - 1]);
1067
1068                                /* undo the transaction. */
1069                                ret = p->hif_func.hif_read_reg(WILC_HOST_TX_CTRL, &reg);
1070                                if (!ret) {
1071                                        wilc_debug(N_ERR, "[wilc txq]: fail can't read reg WILC_HOST_TX_CTRL..\n");
1072                                        break;
1073                                }
1074                                reg &= ~(1ul << 0);
1075                                ret = p->hif_func.hif_write_reg(WILC_HOST_TX_CTRL, reg);
1076                                if (!ret) {
1077                                        wilc_debug(N_ERR, "[wilc txq]: fail can't write reg WILC_HOST_TX_CTRL..\n");
1078                                        break;
1079                                }
1080                                break;
1081                        } else {
1082                                break;
1083                        }
1084                } while (1);
1085
1086                if (!ret) {
1087                        goto _end_;
1088                }
1089                if (entries == 0) {
1090                        ret = WILC_TX_ERR_NO_BUF;
1091                        goto _end_;
1092                }
1093
1094                /* since copying data into txb takes some time, then
1095                 * allow the bus lock to be released let the RX task go. */
1096                release_bus(RELEASE_ALLOW_SLEEP);
1097
1098                /**
1099                 *      Copy data to the TX buffer
1100                 **/
1101                offset = 0;
1102                i = 0;
1103                do {
1104                        tqe = wilc_wlan_txq_remove_from_head();
1105                        if (tqe != NULL && (vmm_table[i] != 0)) {
1106                                uint32_t header, buffer_offset;
1107
1108#ifdef BIG_ENDIAN
1109                                vmm_table[i] = BYTE_SWAP(vmm_table[i]);
1110#endif
1111                                vmm_sz = (vmm_table[i] & 0x3ff);        /* in word unit */
1112                                vmm_sz *= 4;
1113                                header = (tqe->type << 31) | (tqe->buffer_size << 15) | vmm_sz;
1114                                /*Bug3959: transmitting mgmt frames received from host*/
1115                                /*setting bit 30 in the host header to indicate mgmt frame*/
1116#ifdef WILC_AP_EXTERNAL_MLME
1117                                if (tqe->type == WILC_MGMT_PKT) {
1118                                        header |= (1 << 30);
1119                                } else {
1120                                        header &= ~(1 << 30);
1121                                }
1122#endif
1123
1124#ifdef BIG_ENDIAN
1125                                header = BYTE_SWAP(header);
1126#endif
1127                                memcpy(&txb[offset], &header, 4);
1128                                if (tqe->type == WILC_CFG_PKT) {
1129                                        buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET;
1130                                }
1131                                /*Bug3959: transmitting mgmt frames received from host*/
1132                                /*buffer offset = HOST_HDR_OFFSET in other cases: WILC_MGMT_PKT*/
1133                                /* and WILC_DATA_PKT_MAC_HDR*/
1134                                else if (tqe->type == WILC_NET_PKT) {
1135                                        char *pBSSID = ((struct tx_complete_data *)(tqe->priv))->pBssid;
1136                                        buffer_offset = ETH_ETHERNET_HDR_OFFSET;
1137                                        /* copy the bssid at the sart of the buffer */
1138                                        memcpy(&txb[offset + 4], pBSSID, 6);
1139                                }
1140#ifdef WILC_FULLY_HOSTING_AP
1141                                else if (tqe->type == WILC_FH_DATA_PKT) {
1142                                        buffer_offset = FH_TX_HOST_HDR_OFFSET;
1143                                }
1144#endif
1145                                else {
1146                                        buffer_offset = HOST_HDR_OFFSET;
1147                                }
1148
1149                                memcpy(&txb[offset + buffer_offset], tqe->buffer, tqe->buffer_size);
1150                                offset += vmm_sz;
1151                                i++;
1152                                tqe->status = 1;                                /* mark the packet send */
1153                                if (tqe->tx_complete_func)
1154                                        tqe->tx_complete_func(tqe->priv, tqe->status);
1155                                #ifdef TCP_ACK_FILTER
1156                                if (tqe->tcp_PendingAck_index != NOT_TCP_ACK) {
1157                                        Pending_Acks_info[tqe->tcp_PendingAck_index].txqe = NULL;
1158                                }
1159                                #endif
1160                                p->os_func.os_free(tqe);
1161                        } else {
1162                                break;
1163                        }
1164                } while (--entries);
1165
1166                /**
1167                 *      lock the bus
1168                 **/
1169                acquire_bus(ACQUIRE_AND_WAKEUP);
1170
1171                ret = p->hif_func.hif_clear_int_ext(ENABLE_TX_VMM);
1172                if (!ret) {
1173                        wilc_debug(N_ERR, "[wilc txq]: fail can't start tx VMM ...\n");
1174                        goto _end_;
1175                }
1176
1177                /**
1178                 *      transfer
1179                 **/
1180                ret = p->hif_func.hif_block_tx_ext(0, txb, offset);
1181                if (!ret) {
1182                        wilc_debug(N_ERR, "[wilc txq]: fail can't block tx ext...\n");
1183                        goto _end_;
1184                }
1185
1186_end_:
1187
1188                release_bus(RELEASE_ALLOW_SLEEP);
1189                if (ret != 1)
1190                        break;
1191        } while (0);
1192        /*Added by Amr - BugID_4720*/
1193        p->os_func.os_signal(p->txq_add_to_head_lock);
1194
1195        p->txq_exit = 1;
1196        PRINT_D(TX_DBG, "THREAD: Exiting txq\n");
1197        /* return tx[]q count */
1198        *pu32TxqCount = p->txq_entries;
1199        return ret;
1200}
1201
1202static void wilc_wlan_handle_rxq(void)
1203{
1204        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1205        int offset = 0, size, has_packet = 0;
1206        uint8_t *buffer;
1207        struct rxq_entry_t *rqe;
1208
1209        p->rxq_exit = 0;
1210
1211
1212
1213
1214        do {
1215                if (p->quit) {
1216                        PRINT_D(RX_DBG, "exit 1st do-while due to Clean_UP function \n");
1217                        p->os_func.os_signal(p->cfg_wait);
1218                        break;
1219                }
1220                rqe = wilc_wlan_rxq_remove();
1221                if (rqe == NULL) {
1222                        PRINT_D(RX_DBG, "nothing in the queue - exit 1st do-while\n");
1223                        break;
1224                }
1225                buffer = rqe->buffer;
1226                size = rqe->buffer_size;
1227                PRINT_D(RX_DBG, "rxQ entery Size = %d - Address = %p\n", size, buffer);
1228                offset = 0;
1229
1230
1231
1232                do {
1233                        uint32_t header;
1234                        uint32_t pkt_len, pkt_offset, tp_len;
1235                        int is_cfg_packet;
1236                        PRINT_D(RX_DBG, "In the 2nd do-while\n");
1237                        memcpy(&header, &buffer[offset], 4);
1238#ifdef BIG_ENDIAN
1239                        header = BYTE_SWAP(header);
1240#endif
1241                        PRINT_D(RX_DBG, "Header = %04x - Offset = %d\n", header, offset);
1242
1243
1244
1245                        is_cfg_packet = (header >> 31) & 0x1;
1246                        pkt_offset = (header >> 22) & 0x1ff;
1247                        tp_len = (header >> 11) & 0x7ff;
1248                        pkt_len = header & 0x7ff;
1249
1250                        if (pkt_len == 0 || tp_len == 0) {
1251                                wilc_debug(N_RXQ, "[wilc rxq]: data corrupt, packet len or tp_len is 0 [%d][%d]\n", pkt_len, tp_len);
1252                                break;
1253                        }
1254
1255/*bug 3887: [AP] Allow Management frames to be passed to the host*/
1256                        #if defined(WILC_AP_EXTERNAL_MLME) || defined(WILC_P2P)
1257                        #define IS_MANAGMEMENT                          0x100
1258                        #define IS_MANAGMEMENT_CALLBACK                 0x080
1259                        #define IS_MGMT_STATUS_SUCCES                   0x040
1260
1261
1262                        if (pkt_offset & IS_MANAGMEMENT) {
1263                                /* reset mgmt indicator bit, to use pkt_offeset in furthur calculations */
1264                                pkt_offset &= ~(IS_MANAGMEMENT | IS_MANAGMEMENT_CALLBACK | IS_MGMT_STATUS_SUCCES);
1265
1266#ifdef USE_WIRELESS
1267                                WILC_WFI_mgmt_rx(&buffer[offset + HOST_HDR_OFFSET], pkt_len);
1268
1269#endif
1270
1271                        }
1272                        /* BUG4530 fix */
1273                        else
1274                        #endif
1275                        {
1276
1277                                if (!is_cfg_packet) {
1278
1279                                        if (p->net_func.rx_indicate) {
1280                                                if (pkt_len > 0) {
1281                                                        p->net_func.rx_indicate(&buffer[offset], pkt_len, pkt_offset);
1282                                                        has_packet = 1;
1283                                                }
1284                                        }
1285                                } else {
1286                                        wilc_cfg_rsp_t rsp;
1287
1288
1289
1290                                        p->cif_func.rx_indicate(&buffer[pkt_offset + offset], pkt_len, &rsp);
1291                                        if (rsp.type == WILC_CFG_RSP) {
1292                                                /**
1293                                                 *      wake up the waiting task...
1294                                                 **/
1295                                                PRINT_D(RX_DBG, "p->cfg_seq_no = %d - rsp.seq_no = %d\n", p->cfg_seq_no, rsp.seq_no);
1296                                                if (p->cfg_seq_no == rsp.seq_no) {
1297                                                        p->os_func.os_signal(p->cfg_wait);
1298                                                }
1299                                        } else if (rsp.type == WILC_CFG_RSP_STATUS) {
1300                                                /**
1301                                                 *      Call back to indicate status...
1302                                                 **/
1303                                                if (p->indicate_func.mac_indicate) {
1304                                                        p->indicate_func.mac_indicate(WILC_MAC_INDICATE_STATUS);
1305                                                }
1306
1307                                        } else if (rsp.type == WILC_CFG_RSP_SCAN) {
1308                                                if (p->indicate_func.mac_indicate)
1309                                                        p->indicate_func.mac_indicate(WILC_MAC_INDICATE_SCAN);
1310                                        }
1311                                }
1312                        }
1313                        offset += tp_len;
1314                        if (offset >= size)
1315                                break;
1316                } while (1);
1317
1318
1319#ifndef MEMORY_STATIC
1320                if (buffer != NULL)
1321                        p->os_func.os_free((void *)buffer);
1322#endif
1323                if (rqe != NULL)
1324                        p->os_func.os_free((void *)rqe);
1325
1326                if (has_packet) {
1327                        if (p->net_func.rx_complete)
1328                                p->net_func.rx_complete();
1329                }
1330        } while (1);
1331
1332        p->rxq_exit = 1;
1333        PRINT_D(RX_DBG, "THREAD: Exiting RX thread \n");
1334        return;
1335}
1336
1337/********************************************
1338 *
1339 *      Fast DMA Isr
1340 *
1341 ********************************************/
1342static void wilc_unknown_isr_ext(void)
1343{
1344        g_wlan.hif_func.hif_clear_int_ext(0);
1345}
1346static void wilc_pllupdate_isr_ext(uint32_t int_stats)
1347{
1348
1349        int trials = 10;
1350
1351        g_wlan.hif_func.hif_clear_int_ext(PLL_INT_CLR);
1352
1353        /* Waiting for PLL */
1354        g_wlan.os_func.os_atomic_sleep(WILC_PLL_TO);
1355
1356        /* poll till read a valid data */
1357        while (!(ISWILC1000(wilc_get_chipid(true)) && --trials)) {
1358                PRINT_D(TX_DBG, "PLL update retrying\n");
1359                g_wlan.os_func.os_atomic_sleep(1);
1360        }
1361}
1362
1363static void wilc_sleeptimer_isr_ext(uint32_t int_stats1)
1364{
1365        g_wlan.hif_func.hif_clear_int_ext(SLEEP_INT_CLR);
1366#ifndef WILC_OPTIMIZE_SLEEP_INT
1367        genuChipPSstate = CHIP_SLEEPING_AUTO;
1368#endif
1369}
1370
1371static void wilc_wlan_handle_isr_ext(uint32_t int_status)
1372{
1373        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1374#ifdef MEMORY_STATIC
1375        uint32_t offset = p->rx_buffer_offset;
1376#endif
1377        uint8_t *buffer = NULL;
1378        uint32_t size;
1379        uint32_t retries = 0;
1380        int ret = 0;
1381        struct rxq_entry_t *rqe;
1382
1383
1384        /**
1385         *      Get the rx size
1386         **/
1387
1388        size = ((int_status & 0x7fff) << 2);
1389
1390        while (!size && retries < 10) {
1391                uint32_t time = 0;
1392                /*looping more secure*/
1393                /*zero size make a crashe because the dma will not happen and that will block the firmware*/
1394                wilc_debug(N_ERR, "RX Size equal zero ... Trying to read it again for %d time\n", time++);
1395                p->hif_func.hif_read_size(&size);
1396                size = ((size & 0x7fff) << 2);
1397                retries++;
1398
1399        }
1400
1401        if (size > 0) {
1402#ifdef MEMORY_STATIC
1403                if (p->rx_buffer_size - offset < size)
1404                        offset = 0;
1405
1406                if (p->rx_buffer)
1407                        buffer = &p->rx_buffer[offset];
1408                else {
1409                        wilc_debug(N_ERR, "[wilc isr]: fail Rx Buffer is NULL...drop the packets (%d)\n", size);
1410                        goto _end_;
1411                }
1412
1413#else
1414                buffer = p->os_func.os_malloc(size);
1415                if (buffer == NULL) {
1416                        wilc_debug(N_ERR, "[wilc isr]: fail alloc host memory...drop the packets (%d)\n", size);
1417                        WILC_Sleep(100);
1418                        goto _end_;
1419                }
1420#endif
1421
1422                /**
1423                 *      clear the chip's interrupt       after getting size some register getting corrupted after clear the interrupt
1424                 **/
1425                p->hif_func.hif_clear_int_ext(DATA_INT_CLR | ENABLE_RX_VMM);
1426
1427
1428                /**
1429                 * start transfer
1430                 **/
1431                ret = p->hif_func.hif_block_rx_ext(0, buffer, size);
1432
1433                if (!ret) {
1434                        wilc_debug(N_ERR, "[wilc isr]: fail block rx...\n");
1435                        goto _end_;
1436                }
1437_end_:
1438
1439
1440                if (ret) {
1441#ifdef MEMORY_STATIC
1442                        offset += size;
1443                        p->rx_buffer_offset = offset;
1444#endif
1445                        /**
1446                         *      add to rx queue
1447                         **/
1448                        rqe = (struct rxq_entry_t *)p->os_func.os_malloc(sizeof(struct rxq_entry_t));
1449                        if (rqe != NULL) {
1450                                rqe->buffer = buffer;
1451                                rqe->buffer_size = size;
1452                                PRINT_D(RX_DBG, "rxq entery Size= %d - Address = %p\n", rqe->buffer_size, rqe->buffer);
1453                                wilc_wlan_rxq_add(rqe);
1454                                p->os_func.os_signal(p->rxq_wait);
1455                        }
1456                } else {
1457#ifndef MEMORY_STATIC
1458                        if (buffer != NULL)
1459                                p->os_func.os_free(buffer);
1460#endif
1461                }
1462        }
1463#ifdef TCP_ENHANCEMENTS
1464        wilc_wlan_handle_rxq();
1465#endif
1466}
1467
1468void wilc_handle_isr(void)
1469{
1470        uint32_t int_status;
1471
1472        acquire_bus(ACQUIRE_AND_WAKEUP);
1473        g_wlan.hif_func.hif_read_int(&int_status);
1474
1475        if (int_status & PLL_INT_EXT) {
1476                wilc_pllupdate_isr_ext(int_status);
1477        }
1478        if (int_status & DATA_INT_EXT) {
1479                wilc_wlan_handle_isr_ext(int_status);
1480        #ifndef WILC_OPTIMIZE_SLEEP_INT
1481                /* Chip is up and talking*/
1482                genuChipPSstate = CHIP_WAKEDUP;
1483        #endif
1484        }
1485        if (int_status & SLEEP_INT_EXT) {
1486                wilc_sleeptimer_isr_ext(int_status);
1487        }
1488
1489        if (!(int_status & (ALL_INT_EXT))) {
1490#ifdef WILC_SDIO
1491                PRINT_D(TX_DBG, ">> UNKNOWN_INTERRUPT - 0x%08x\n", int_status);
1492#endif
1493                wilc_unknown_isr_ext();
1494        }
1495#if ((!defined WILC_SDIO) || (defined WILC_SDIO_IRQ_GPIO))
1496        linux_wlan_enable_irq();
1497#endif
1498        release_bus(RELEASE_ALLOW_SLEEP);
1499}
1500
1501/********************************************
1502 *
1503 *      Firmware download
1504 *
1505 ********************************************/
1506static int wilc_wlan_firmware_download(const uint8_t *buffer, uint32_t buffer_size)
1507{
1508        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1509        uint32_t offset;
1510        uint32_t addr, size, size2, blksz;
1511        uint8_t *dma_buffer;
1512        int ret = 0;
1513
1514        blksz = (1ul << 12); /* Bug 4703: 4KB Good enough size for most platforms = PAGE_SIZE. */
1515        /* Allocate a DMA coherent  buffer. */
1516
1517#if (defined WILC_PREALLOC_AT_BOOT)
1518        {
1519                extern void *get_fw_buffer(void);
1520                dma_buffer = (uint8_t *)get_fw_buffer();
1521                PRINT_D(TX_DBG, "fw_buffer = 0x%x\n", dma_buffer);
1522        }
1523#else
1524        dma_buffer = (uint8_t *)g_wlan.os_func.os_malloc(blksz);
1525#endif
1526        if (dma_buffer == NULL) {
1527                /*EIO   5*/
1528                ret = -5;
1529                PRINT_ER("Can't allocate buffer for firmware download IO error\n ");
1530                goto _fail_1;
1531        }
1532
1533        PRINT_D(INIT_DBG, "Downloading firmware size = %d ...\n", buffer_size);
1534        /**
1535         *      load the firmware
1536         **/
1537        offset = 0;
1538        do {
1539                memcpy(&addr, &buffer[offset], 4);
1540                memcpy(&size, &buffer[offset + 4], 4);
1541#ifdef BIG_ENDIAN
1542                addr = BYTE_SWAP(addr);
1543                size = BYTE_SWAP(size);
1544#endif
1545                acquire_bus(ACQUIRE_ONLY);
1546                offset += 8;
1547                while (((int)size) && (offset < buffer_size)) {
1548                        if (size <= blksz) {
1549                                size2 = size;
1550                        } else {
1551                                size2 = blksz;
1552                        }
1553                        /* Copy firmware into a DMA coherent buffer */
1554                        memcpy(dma_buffer, &buffer[offset], size2);
1555                        ret = p->hif_func.hif_block_tx(addr, dma_buffer, size2);
1556                        if (!ret)
1557                                break;
1558
1559                        addr += size2;
1560                        offset += size2;
1561                        size -= size2;
1562                }
1563                release_bus(RELEASE_ONLY);
1564
1565                if (!ret) {
1566                        /*EIO   5*/
1567                        ret = -5;
1568                        PRINT_ER("Can't download firmware IO error\n ");
1569                        goto _fail_;
1570                }
1571                PRINT_D(INIT_DBG, "Offset = %d\n", offset);
1572        } while (offset < buffer_size);
1573
1574_fail_:
1575
1576#if (defined WILC_PREALLOC_AT_BOOT)
1577
1578#else
1579        if (dma_buffer)
1580                g_wlan.os_func.os_free(dma_buffer);
1581#endif
1582
1583_fail_1:
1584
1585        return (ret < 0) ? ret : 0;
1586}
1587
1588/********************************************
1589 *
1590 *      Common
1591 *
1592 ********************************************/
1593static int wilc_wlan_start(void)
1594{
1595        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1596        uint32_t reg = 0;
1597        int ret;
1598        uint32_t chipid;
1599
1600        /**
1601         *      Set the host interface
1602         **/
1603#ifdef OLD_FPGA_BITFILE
1604        acquire_bus(ACQUIRE_ONLY);
1605        ret = p->hif_func.hif_read_reg(WILC_VMM_CORE_CTL, &reg);
1606        if (!ret) {
1607                wilc_debug(N_ERR, "[wilc start]: fail read reg vmm_core_ctl...\n");
1608                release_bus(RELEASE_ALLOW_SLEEP);
1609                return ret;
1610        }
1611        reg |= (p->io_func.io_type << 2);
1612        ret = p->hif_func.hif_write_reg(WILC_VMM_CORE_CTL, reg);
1613        if (!ret) {
1614                wilc_debug(N_ERR, "[wilc start]: fail write reg vmm_core_ctl...\n");
1615                release_bus(RELEASE_ONLY);
1616                return ret;
1617        }
1618#else
1619        if (p->io_func.io_type == HIF_SDIO) {
1620                reg = 0;
1621                reg |= (1 << 3); /* bug 4456 and 4557 */
1622        } else if (p->io_func.io_type == HIF_SPI) {
1623                reg = 1;
1624        }
1625        acquire_bus(ACQUIRE_ONLY);
1626        ret = p->hif_func.hif_write_reg(WILC_VMM_CORE_CFG, reg);
1627        if (!ret) {
1628                wilc_debug(N_ERR, "[wilc start]: fail write reg vmm_core_cfg...\n");
1629                release_bus(RELEASE_ONLY);
1630                /* EIO  5*/
1631                ret = -5;
1632                return ret;
1633        }
1634        reg = 0;
1635#ifdef WILC_SDIO_IRQ_GPIO
1636        reg |= WILC_HAVE_SDIO_IRQ_GPIO;
1637#endif
1638
1639#ifdef WILC_DISABLE_PMU
1640#else
1641        reg |= WILC_HAVE_USE_PMU;
1642#endif
1643
1644#ifdef WILC_SLEEP_CLK_SRC_XO
1645        reg |= WILC_HAVE_SLEEP_CLK_SRC_XO;
1646#elif defined WILC_SLEEP_CLK_SRC_RTC
1647        reg |= WILC_HAVE_SLEEP_CLK_SRC_RTC;
1648#endif
1649
1650#ifdef WILC_EXT_PA_INV_TX_RX
1651        reg |= WILC_HAVE_EXT_PA_INV_TX_RX;
1652#endif
1653
1654        reg |= WILC_HAVE_LEGACY_RF_SETTINGS;
1655
1656
1657/*BugID_5257*/
1658/*Set oscillator frequency*/
1659#ifdef XTAL_24
1660        reg |= WILC_HAVE_XTAL_24;
1661#endif
1662
1663/*BugID_5271*/
1664/*Enable/Disable GPIO configuration for FW logs*/
1665#ifdef DISABLE_WILC_UART
1666        reg |= WILC_HAVE_DISABLE_WILC_UART;
1667#endif
1668
1669        ret = p->hif_func.hif_write_reg(WILC_GP_REG_1, reg);
1670        if (!ret) {
1671                wilc_debug(N_ERR, "[wilc start]: fail write WILC_GP_REG_1 ...\n");
1672                release_bus(RELEASE_ONLY);
1673                /* EIO  5*/
1674                ret = -5;
1675                return ret;
1676        }
1677#endif
1678
1679
1680        /**
1681         *      Bus related
1682         **/
1683        p->hif_func.hif_sync_ext(NUM_INT_EXT);
1684
1685        ret = p->hif_func.hif_read_reg(0x1000, &chipid);
1686        if (!ret) {
1687                wilc_debug(N_ERR, "[wilc start]: fail read reg 0x1000 ...\n");
1688                release_bus(RELEASE_ONLY);
1689                /* EIO  5*/
1690                ret = -5;
1691                return ret;
1692        }
1693
1694        /**
1695         *      Go...
1696         **/
1697
1698
1699        p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1700        if ((reg & (1ul << 10)) == (1ul << 10)) {
1701                reg &= ~(1ul << 10);
1702                p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
1703                p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1704        }
1705
1706        reg |= (1ul << 10);
1707        ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
1708        p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1709        release_bus(RELEASE_ONLY);
1710
1711        return (ret < 0) ? ret : 0;
1712}
1713
1714void wilc_wlan_global_reset(void)
1715{
1716
1717        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1718        acquire_bus(ACQUIRE_AND_WAKEUP);
1719        p->hif_func.hif_write_reg(WILC_GLB_RESET_0, 0x0);
1720        release_bus(RELEASE_ONLY);
1721}
1722static int wilc_wlan_stop(void)
1723{
1724        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1725        uint32_t reg = 0;
1726        int ret;
1727        uint8_t timeout = 10;
1728        /**
1729         *      TODO: stop the firmware, need a re-download
1730         **/
1731        acquire_bus(ACQUIRE_AND_WAKEUP);
1732
1733        ret = p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1734        if (!ret) {
1735                PRINT_ER("Error while reading reg\n");
1736                release_bus(RELEASE_ALLOW_SLEEP);
1737                return ret;
1738        }
1739
1740        reg &= ~(1 << 10);
1741
1742
1743        ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
1744        if (!ret) {
1745                PRINT_ER("Error while writing reg\n");
1746                release_bus(RELEASE_ALLOW_SLEEP);
1747                return ret;
1748        }
1749
1750
1751
1752        do {
1753                ret = p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1754                if (!ret) {
1755                        PRINT_ER("Error while reading reg\n");
1756                        release_bus(RELEASE_ALLOW_SLEEP);
1757                        return ret;
1758                }
1759                PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n", reg, timeout);
1760                /*Workaround to ensure that the chip is actually reset*/
1761                if ((reg & (1 << 10))) {
1762                        PRINT_D(GENERIC_DBG, "Bit 10 not reset : Retry %d\n", timeout);
1763                        reg &= ~(1 << 10);
1764                        ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
1765                        timeout--;
1766                } else {
1767                        PRINT_D(GENERIC_DBG, "Bit 10 reset after : Retry %d\n", timeout);
1768                        ret = p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1769                        if (!ret) {
1770                                PRINT_ER("Error while reading reg\n");
1771                                release_bus(RELEASE_ALLOW_SLEEP);
1772                                return ret;
1773                        }
1774                        PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n", reg, timeout);
1775                        break;
1776                }
1777
1778        } while (timeout);
1779#if 1
1780/******************************************************************************/
1781/* This was add at Bug 4595 to reset the chip while maintaining the bus state */
1782/******************************************************************************/
1783        reg = ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 8) | (1 << 9) | (1 << 26) | (1 << 29) | (1 << 30) | (1 << 31)); /**/
1784        /**/
1785        ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);                                 /**/
1786        reg = ~(1 << 10);                                                                                               /**/
1787        /**/
1788        ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);                                 /**/
1789/******************************************************************************/
1790#endif
1791
1792        release_bus(RELEASE_ALLOW_SLEEP);
1793
1794        return ret;
1795}
1796
1797static void wilc_wlan_cleanup(void)
1798{
1799        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1800        struct txq_entry_t *tqe;
1801        struct rxq_entry_t *rqe;
1802        uint32_t reg = 0;
1803        int ret;
1804
1805        p->quit = 1;
1806        do {
1807                tqe = wilc_wlan_txq_remove_from_head();
1808                if (tqe == NULL)
1809                        break;
1810                if (tqe->tx_complete_func)
1811                        tqe->tx_complete_func(tqe->priv, 0);
1812                p->os_func.os_free((void *)tqe);
1813        } while (1);
1814
1815        do {
1816                rqe = wilc_wlan_rxq_remove();
1817                if (rqe == NULL)
1818                        break;
1819#ifdef MEMORY_DYNAMIC
1820                p->os_func.os_free((void *)tqe->buffer);
1821#endif
1822                p->os_func.os_free((void *)rqe);
1823        } while (1);
1824
1825        /**
1826         *      clean up buffer
1827         **/
1828
1829#if (defined WILC_PREALLOC_AT_BOOT)
1830
1831#else
1832        #ifdef MEMORY_STATIC
1833        if (p->rx_buffer) {
1834                p->os_func.os_free(p->rx_buffer);
1835                p->rx_buffer = NULL;
1836        }
1837        #endif
1838        if (p->tx_buffer) {
1839                p->os_func.os_free(p->tx_buffer);
1840                p->tx_buffer = NULL;
1841        }
1842#endif
1843
1844        acquire_bus(ACQUIRE_AND_WAKEUP);
1845
1846
1847        ret = p->hif_func.hif_read_reg(WILC_GP_REG_0, &reg);
1848        if (!ret) {
1849                PRINT_ER("Error while reading reg\n");
1850                release_bus(RELEASE_ALLOW_SLEEP);
1851        }
1852        PRINT_ER("Writing ABORT reg\n");
1853        ret = p->hif_func.hif_write_reg(WILC_GP_REG_0, (reg | ABORT_INT));
1854        if (!ret) {
1855                PRINT_ER("Error while writing reg\n");
1856                release_bus(RELEASE_ALLOW_SLEEP);
1857        }
1858        release_bus(RELEASE_ALLOW_SLEEP);
1859        /**
1860         *      io clean up
1861         **/
1862        p->hif_func.hif_deinit(NULL);
1863
1864}
1865
1866static int wilc_wlan_cfg_commit(int type, uint32_t drvHandler)
1867{
1868        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1869        wilc_cfg_frame_t *cfg = &p->cfg_frame;
1870        int total_len = p->cfg_frame_offset + 4 + DRIVER_HANDLER_SIZE;
1871        int seq_no = p->cfg_seq_no % 256;
1872        int driver_handler = (u32)drvHandler;
1873
1874
1875        /**
1876         *      Set up header
1877         **/
1878        if (type == WILC_CFG_SET) {             /* Set */
1879                cfg->wid_header[0] = 'W';
1880        } else {                                        /* Query */
1881                cfg->wid_header[0] = 'Q';
1882        }
1883        cfg->wid_header[1] = seq_no;    /* sequence number */
1884        cfg->wid_header[2] = (uint8_t)total_len;
1885        cfg->wid_header[3] = (uint8_t)(total_len >> 8);
1886        cfg->wid_header[4] = (uint8_t)driver_handler;
1887        cfg->wid_header[5] = (uint8_t)(driver_handler >> 8);
1888        cfg->wid_header[6] = (uint8_t)(driver_handler >> 16);
1889        cfg->wid_header[7] = (uint8_t)(driver_handler >> 24);
1890        p->cfg_seq_no = seq_no;
1891
1892        /**
1893         *      Add to TX queue
1894         **/
1895
1896        /*Edited by Amr - BugID_4720*/
1897        if (!wilc_wlan_txq_add_cfg_pkt(&cfg->wid_header[0], total_len))
1898                return -1;
1899
1900        return 0;
1901}
1902
1903static int wilc_wlan_cfg_set(int start, uint32_t wid, uint8_t *buffer, uint32_t buffer_size, int commit, uint32_t drvHandler)
1904{
1905        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1906        uint32_t offset;
1907        int ret_size;
1908
1909
1910        if (p->cfg_frame_in_use)
1911                return 0;
1912
1913        if (start)
1914                p->cfg_frame_offset = 0;
1915
1916        offset = p->cfg_frame_offset;
1917        ret_size = p->cif_func.cfg_wid_set(p->cfg_frame.frame, offset, (uint16_t)wid, buffer, buffer_size);
1918        offset += ret_size;
1919        p->cfg_frame_offset = offset;
1920
1921        if (commit) {
1922                PRINT_D(TX_DBG, "[WILC]PACKET Commit with sequence number %d\n", p->cfg_seq_no);
1923                PRINT_D(RX_DBG, "Processing cfg_set()\n");
1924                p->cfg_frame_in_use = 1;
1925
1926                /*Edited by Amr - BugID_4720*/
1927                if (wilc_wlan_cfg_commit(WILC_CFG_SET, drvHandler))
1928                        ret_size = 0;   /* BugID_5213 */
1929
1930                if (p->os_func.os_wait(p->cfg_wait, CFG_PKTS_TIMEOUT)) {
1931                        PRINT_D(TX_DBG, "Set Timed Out\n");
1932                        ret_size = 0;
1933                }
1934                p->cfg_frame_in_use = 0;
1935                p->cfg_frame_offset = 0;
1936                p->cfg_seq_no += 1;
1937
1938        }
1939
1940        return ret_size;
1941}
1942static int wilc_wlan_cfg_get(int start, uint32_t wid, int commit, uint32_t drvHandler)
1943{
1944        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1945        uint32_t offset;
1946        int ret_size;
1947
1948
1949        if (p->cfg_frame_in_use)
1950                return 0;
1951
1952        if (start)
1953                p->cfg_frame_offset = 0;
1954
1955        offset = p->cfg_frame_offset;
1956        ret_size = p->cif_func.cfg_wid_get(p->cfg_frame.frame, offset, (uint16_t)wid);
1957        offset += ret_size;
1958        p->cfg_frame_offset = offset;
1959
1960        if (commit) {
1961                p->cfg_frame_in_use = 1;
1962
1963                /*Edited by Amr - BugID_4720*/
1964                if (wilc_wlan_cfg_commit(WILC_CFG_QUERY, drvHandler))
1965                        ret_size = 0;   /* BugID_5213 */
1966
1967
1968                if (p->os_func.os_wait(p->cfg_wait, CFG_PKTS_TIMEOUT)) {
1969                        PRINT_D(TX_DBG, "Get Timed Out\n");
1970                        ret_size = 0;
1971                }
1972                PRINT_D(GENERIC_DBG, "[WILC]Get Response received\n");
1973                p->cfg_frame_in_use = 0;
1974                p->cfg_frame_offset = 0;
1975                p->cfg_seq_no += 1;
1976        }
1977
1978        return ret_size;
1979}
1980
1981static int wilc_wlan_cfg_get_val(uint32_t wid, uint8_t *buffer, uint32_t buffer_size)
1982{
1983        wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1984        int ret;
1985
1986        ret = p->cif_func.cfg_wid_get_val((uint16_t)wid, buffer, buffer_size);
1987
1988        return ret;
1989}
1990
1991void wilc_bus_set_max_speed(void)
1992{
1993
1994        /* Increase bus speed to max possible.  */
1995        g_wlan.hif_func.hif_set_max_bus_speed();
1996}
1997
1998void wilc_bus_set_default_speed(void)
1999{
2000
2001        /* Restore bus speed to default.  */
2002        g_wlan.hif_func.hif_set_default_bus_speed();
2003}
2004uint32_t init_chip(void)
2005{
2006        uint32_t chipid;
2007        uint32_t reg, ret = 0;
2008
2009#if defined(PLAT_RK3026_TCHIP)
2010        acquire_bus(ACQUIRE_AND_WAKEUP); /* AMR : 0422 RK3026 Crash issue */
2011#else
2012        acquire_bus(ACQUIRE_ONLY);
2013#endif
2014
2015        chipid = wilc_get_chipid(true);
2016
2017
2018
2019        if ((chipid & 0xfff) != 0xa0) {
2020                /**
2021                 * Avoid booting from boot ROM. Make sure that Drive IRQN [SDIO platform]
2022                 * or SD_DAT3 [SPI platform] to ?1?
2023                 **/
2024                /* Set cortus reset register to register control. */
2025                ret = g_wlan.hif_func.hif_read_reg(0x1118, &reg);
2026                if (!ret) {
2027                        wilc_debug(N_ERR, "[wilc start]: fail read reg 0x1118 ...\n");
2028                        return ret;
2029                }
2030                reg |= (1 << 0);
2031                ret = g_wlan.hif_func.hif_write_reg(0x1118, reg);
2032                if (!ret) {
2033                        wilc_debug(N_ERR, "[wilc start]: fail write reg 0x1118 ...\n");
2034                        return ret;
2035                }
2036                /**
2037                 * Write branch intruction to IRAM (0x71 trap) at location 0xFFFF0000
2038                 * (Cortus map) or C0000 (AHB map).
2039                 **/
2040                ret = g_wlan.hif_func.hif_write_reg(0xc0000, 0x71);
2041                if (!ret) {
2042                        wilc_debug(N_ERR, "[wilc start]: fail write reg 0xc0000 ...\n");
2043                        return ret;
2044                }
2045        }
2046
2047        release_bus(RELEASE_ONLY);
2048
2049        return ret;
2050
2051}
2052
2053uint32_t wilc_get_chipid(uint8_t update)
2054{
2055        static uint32_t chipid;
2056        /* SDIO can't read into global variables */
2057        /* Use this variable as a temp, then copy to the global */
2058        uint32_t tempchipid = 0;
2059        uint32_t rfrevid;
2060
2061        if (chipid == 0 || update != 0) {
2062                g_wlan.hif_func.hif_read_reg(0x1000, &tempchipid);
2063                g_wlan.hif_func.hif_read_reg(0x13f4, &rfrevid);
2064                if (!ISWILC1000(tempchipid)) {
2065                        chipid = 0;
2066                        goto _fail_;
2067                }
2068                if (tempchipid == 0x1002a0) {
2069                        if (rfrevid == 0x1) { /* 1002A0 */
2070                        } else { /* if (rfrevid == 0x2) */   /* 1002A1 */
2071                                tempchipid = 0x1002a1;
2072                        }
2073                } else if (tempchipid == 0x1002b0) {
2074                        if (rfrevid == 3) { /* 1002B0 */
2075                        } else if (rfrevid == 4) { /* 1002B1 */
2076                                tempchipid = 0x1002b1;
2077                        } else { /* if(rfrevid == 5) */   /* 1002B2 */
2078                                tempchipid = 0x1002b2;
2079                        }
2080                } else {
2081                }
2082
2083                chipid = tempchipid;
2084        }
2085_fail_:
2086        return chipid;
2087}
2088
2089#ifdef COMPLEMENT_BOOT
2090uint8_t core_11b_ready(void)
2091{
2092        uint32_t reg_val;
2093
2094        acquire_bus(ACQUIRE_ONLY);
2095        g_wlan.hif_func.hif_write_reg(0x16082c, 1);
2096        g_wlan.hif_func.hif_write_reg(0x161600, 0x90);
2097        g_wlan.hif_func.hif_read_reg(0x161600, &reg_val);
2098        release_bus(RELEASE_ONLY);
2099
2100        if (reg_val == 0x90)
2101                return 0;
2102        else
2103                return 1;
2104}
2105#endif
2106
2107int wilc_wlan_init(wilc_wlan_inp_t *inp, wilc_wlan_oup_t *oup)
2108{
2109
2110        int ret = 0;
2111
2112        PRINT_D(INIT_DBG, "Initializing WILC_Wlan ...\n");
2113
2114        memset((void *)&g_wlan, 0, sizeof(wilc_wlan_dev_t));
2115
2116        /**
2117         *      store the input
2118         **/
2119        memcpy((void *)&g_wlan.os_func, (void *)&inp->os_func, sizeof(wilc_wlan_os_func_t));
2120        memcpy((void *)&g_wlan.io_func, (void *)&inp->io_func, sizeof(wilc_wlan_io_func_t));
2121        memcpy((void *)&g_wlan.net_func, (void *)&inp->net_func, sizeof(wilc_wlan_net_func_t));
2122        memcpy((void *)&g_wlan.indicate_func, (void *)&inp->indicate_func, sizeof(wilc_wlan_net_func_t));
2123        g_wlan.hif_lock = inp->os_context.hif_critical_section;
2124        g_wlan.txq_lock = inp->os_context.txq_critical_section;
2125
2126        /*Added by Amr - BugID_4720*/
2127        g_wlan.txq_add_to_head_lock = inp->os_context.txq_add_to_head_critical_section;
2128
2129        /*Added by Amr - BugID_4720*/
2130        g_wlan.txq_spinlock = inp->os_context.txq_spin_lock;
2131
2132        g_wlan.rxq_lock = inp->os_context.rxq_critical_section;
2133        g_wlan.txq_wait = inp->os_context.txq_wait_event;
2134        g_wlan.rxq_wait = inp->os_context.rxq_wait_event;
2135        g_wlan.cfg_wait = inp->os_context.cfg_wait_event;
2136        g_wlan.tx_buffer_size = inp->os_context.tx_buffer_size;
2137#if defined (MEMORY_STATIC)
2138        g_wlan.rx_buffer_size = inp->os_context.rx_buffer_size;
2139#endif
2140        /***
2141         *      host interface init
2142         **/
2143#if defined(PLAT_RK3026_TCHIP) /* AMR : 0422 RK3026 Crash issue */
2144        if (!g_wilc_initialized) {
2145                custom_lock_bus(g_mac_open);
2146                custom_wakeup(g_mac_open);
2147        }
2148#endif
2149
2150        if ((inp->io_func.io_type & 0x1) == HIF_SDIO) {
2151                if (!hif_sdio.hif_init(inp, wilc_debug)) {
2152                        /* EIO  5 */
2153                        ret = -5;
2154                        goto _fail_;
2155                }
2156                memcpy((void *)&g_wlan.hif_func, &hif_sdio, sizeof(wilc_hif_func_t));
2157        } else {
2158                if ((inp->io_func.io_type & 0x1) == HIF_SPI) {
2159                        /**
2160                         *      TODO:
2161                         **/
2162                        if (!hif_spi.hif_init(inp, wilc_debug)) {
2163                                /* EIO  5 */
2164                                ret = -5;
2165                                goto _fail_;
2166                        }
2167                        memcpy((void *)&g_wlan.hif_func, &hif_spi, sizeof(wilc_hif_func_t));
2168                } else {
2169                        /* EIO  5 */
2170                        ret = -5;
2171                        goto _fail_;
2172                }
2173        }
2174
2175        /***
2176         *      mac interface init
2177         **/
2178        if (!mac_cfg.cfg_init(wilc_debug)) {
2179                /* ENOBUFS      105 */
2180                ret = -105;
2181                goto _fail_;
2182        }
2183        memcpy((void *)&g_wlan.cif_func, &mac_cfg, sizeof(wilc_cfg_func_t));
2184
2185
2186        /**
2187         *      alloc tx, rx buffer
2188         **/
2189#if (defined WILC_PREALLOC_AT_BOOT)
2190        extern void *get_tx_buffer(void);
2191        extern void *get_rx_buffer(void);
2192
2193        PRINT_D(TX_DBG, "malloc before, g_wlan.tx_buffer = 0x%x, g_wlan.rx_buffer = 0x%x\n", g_wlan.tx_buffer, g_wlan.rx_buffer);
2194#endif
2195
2196
2197
2198        if (g_wlan.tx_buffer == NULL)
2199#if (defined WILC_PREALLOC_AT_BOOT)
2200                g_wlan.tx_buffer = (uint8_t *)get_tx_buffer();
2201#else
2202                g_wlan.tx_buffer = (uint8_t *)g_wlan.os_func.os_malloc(g_wlan.tx_buffer_size);
2203#endif
2204        PRINT_D(TX_DBG, "g_wlan.tx_buffer = %p\n", g_wlan.tx_buffer);
2205
2206        if (g_wlan.tx_buffer == NULL) {
2207                /* ENOBUFS      105 */
2208                ret = -105;
2209                PRINT_ER("Can't allocate Tx Buffer");
2210                goto _fail_;
2211        }
2212
2213/* rx_buffer is not used unless we activate USE_MEM STATIC which is not applicable, allocating such memory is useless*/
2214#if defined (MEMORY_STATIC)
2215        if (g_wlan.rx_buffer == NULL)
2216  #if (defined WILC_PREALLOC_AT_BOOT)
2217                g_wlan.rx_buffer = (uint8_t *)get_rx_buffer();
2218  #else
2219                g_wlan.rx_buffer = (uint8_t *)g_wlan.os_func.os_malloc(g_wlan.rx_buffer_size);
2220  #endif
2221        PRINT_D(TX_DBG, "g_wlan.rx_buffer =%p\n", g_wlan.rx_buffer);
2222        if (g_wlan.rx_buffer == NULL) {
2223                /* ENOBUFS      105 */
2224                ret = -105;
2225                PRINT_ER("Can't allocate Rx Buffer");
2226                goto _fail_;
2227        }
2228#endif
2229
2230        /**
2231         *      export functions
2232         **/
2233        oup->wlan_firmware_download = wilc_wlan_firmware_download;
2234        oup->wlan_start = wilc_wlan_start;
2235        oup->wlan_stop = wilc_wlan_stop;
2236        oup->wlan_add_to_tx_que = wilc_wlan_txq_add_net_pkt;
2237        oup->wlan_handle_tx_que = wilc_wlan_handle_txq;
2238        oup->wlan_handle_rx_que = wilc_wlan_handle_rxq;
2239        oup->wlan_handle_rx_isr = wilc_handle_isr;
2240        oup->wlan_cleanup = wilc_wlan_cleanup;
2241        oup->wlan_cfg_set = wilc_wlan_cfg_set;
2242        oup->wlan_cfg_get = wilc_wlan_cfg_get;
2243        oup->wlan_cfg_get_value = wilc_wlan_cfg_get_val;
2244
2245        /*Bug3959: transmitting mgmt frames received from host*/
2246        #if defined(WILC_AP_EXTERNAL_MLME) || defined(WILC_P2P)
2247        oup->wlan_add_mgmt_to_tx_que = wilc_wlan_txq_add_mgmt_pkt;
2248
2249        #ifdef WILC_FULLY_HOSTING_AP
2250        oup->wlan_add_data_to_tx_que = wilc_FH_wlan_txq_add_net_pkt;
2251        #endif
2252        #endif
2253
2254        if (!init_chip()) {
2255                /* EIO  5 */
2256                ret = -5;
2257                goto _fail_;
2258        }
2259#ifdef  TCP_ACK_FILTER
2260        Init_TCP_tracking();
2261#endif
2262
2263#if defined(PLAT_RK3026_TCHIP) /* AMR : 0422 RK3026 Crash issue */
2264        if (!g_wilc_initialized)
2265                custom_unlock_bus(g_mac_open);
2266#endif
2267
2268        return 1;
2269
2270_fail_:
2271
2272#if (defined WILC_PREALLOC_AT_BOOT)
2273
2274#else
2275  #ifdef MEMORY_STATIC
2276        if (g_wlan.rx_buffer) {
2277                g_wlan.os_func.os_free(g_wlan.rx_buffer);
2278                g_wlan.rx_buffer = NULL;
2279        }
2280  #endif
2281        if (g_wlan.tx_buffer) {
2282                g_wlan.os_func.os_free(g_wlan.tx_buffer);
2283                g_wlan.tx_buffer = NULL;
2284        }
2285#endif
2286
2287#if defined(PLAT_RK3026_TCHIP) /* AMR : 0422 RK3026 Crash issue */
2288        if (!g_wilc_initialized)
2289                custom_unlock_bus(g_mac_open);
2290#endif
2291
2292        return ret;
2293
2294}
2295
2296#define BIT31 (1 << 31)
2297u16 Set_machw_change_vir_if(bool bValue)
2298{
2299        u16 ret;
2300        u32 reg;
2301
2302        /*Reset WILC_CHANGING_VIR_IF register to allow adding futrue keys to CE H/W*/
2303        (&g_wlan)->os_func.os_enter_cs((&g_wlan)->hif_lock);
2304        ret = (&g_wlan)->hif_func.hif_read_reg(WILC_CHANGING_VIR_IF, &reg);
2305        if (!ret) {
2306                PRINT_ER("Error while Reading reg WILC_CHANGING_VIR_IF\n");
2307        }
2308
2309        if (bValue) {
2310                reg |= (BIT31);
2311        } else {
2312                reg &= ~(BIT31);
2313        }
2314
2315        ret = (&g_wlan)->hif_func.hif_write_reg(WILC_CHANGING_VIR_IF, reg);
2316
2317        if (!ret) {
2318                PRINT_ER("Error while writing reg WILC_CHANGING_VIR_IF\n");
2319        }
2320        (&g_wlan)->os_func.os_leave_cs((&g_wlan)->hif_lock);
2321
2322        return ret;
2323}
2324
2325#ifdef WILC_FULLY_HOSTING_AP
2326wilc_wlan_dev_t *Get_wlan_context(u16 *pu16size)
2327{
2328        *pu16size = sizeof(wilc_wlan_dev_t);
2329        return &g_wlan;
2330}
2331#endif
2332
2333