blob: 3e62abd47153492e9dac05234a6d0f2ade3c535e [file] [log] [blame]
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001#include "wilc_wlan_if.h"
Tony Cho60bd1002015-10-12 16:56:04 +09002#include "wilc_wfi_netdevice.h"
Glen Lee17e8f162015-10-02 14:22:07 +09003#include "wilc_wlan_cfg.h"
Johnny Kimc5c77ba2015-05-11 14:30:56 +09004
Johnny Kimc5c77ba2015-05-11 14:30:56 +09005extern wilc_hif_func_t hif_sdio;
6extern wilc_hif_func_t hif_spi;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09007u32 wilc_get_chipid(u8 update);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09008
Johnny Kimc5c77ba2015-05-11 14:30:56 +09009typedef struct {
10 int quit;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090011 wilc_wlan_io_func_t io_func;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090012 wilc_hif_func_t hif_func;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090013 int cfg_frame_in_use;
14 wilc_cfg_frame_t cfg_frame;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +090015 u32 cfg_frame_offset;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090016 int cfg_seq_no;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090017
Johnny Kimc5c77ba2015-05-11 14:30:56 +090018 #ifdef MEMORY_STATIC
Chaehyun Lim51e825f2015-09-15 14:06:14 +090019 u8 *rx_buffer;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +090020 u32 rx_buffer_offset;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090021 #endif
Chaehyun Lim51e825f2015-09-15 14:06:14 +090022 u8 *tx_buffer;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +090023 u32 tx_buffer_offset;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090024
Johnny Kimc5c77ba2015-05-11 14:30:56 +090025 unsigned long txq_spinlock_flags;
26
27 struct txq_entry_t *txq_head;
28 struct txq_entry_t *txq_tail;
29 int txq_entries;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090030 int txq_exit;
31
Johnny Kimc5c77ba2015-05-11 14:30:56 +090032 struct rxq_entry_t *rxq_head;
33 struct rxq_entry_t *rxq_tail;
34 int rxq_entries;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090035 int rxq_exit;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090036} wilc_wlan_dev_t;
37
38static wilc_wlan_dev_t g_wlan;
39
Chaehyun Lim9af382b2015-09-16 20:11:27 +090040static inline void chip_allow_sleep(void);
41static inline void chip_wakeup(void);
Chaehyun Limfbc2fe12015-09-15 14:06:16 +090042static u32 dbgflag = N_INIT | N_ERR | N_INTR | N_TXQ | N_RXQ;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090043
Chaehyun Limfbc2fe12015-09-15 14:06:16 +090044static void wilc_debug(u32 flag, char *fmt, ...)
Johnny Kimc5c77ba2015-05-11 14:30:56 +090045{
46 char buf[256];
47 va_list args;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090048
49 if (flag & dbgflag) {
50 va_start(args, fmt);
Hari Prasath Gujulan Elango81053222015-06-22 13:13:58 +000051 vsprintf(buf, fmt, args);
Johnny Kimc5c77ba2015-05-11 14:30:56 +090052 va_end(args);
53
Glen Leeef2b7842015-09-24 18:14:55 +090054 linux_wlan_dbg(buf);
Johnny Kimc5c77ba2015-05-11 14:30:56 +090055 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +090056}
57
Leo Kimb7d1e182015-11-06 11:12:30 +090058static CHIP_PS_STATE_T chip_ps_state = CHIP_WAKEDUP;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090059
Chaehyun Lim9af382b2015-09-16 20:11:27 +090060static inline void acquire_bus(BUS_ACQUIRE_T acquire)
Johnny Kimc5c77ba2015-05-11 14:30:56 +090061{
Glen Lee187f1ef2015-09-24 18:15:01 +090062 mutex_lock(&g_linux_wlan->hif_cs);
Johnny Kimc5c77ba2015-05-11 14:30:56 +090063 #ifndef WILC_OPTIMIZE_SLEEP_INT
Leo Kimb7d1e182015-11-06 11:12:30 +090064 if (chip_ps_state != CHIP_WAKEDUP)
Johnny Kimc5c77ba2015-05-11 14:30:56 +090065 #endif
66 {
67 if (acquire == ACQUIRE_AND_WAKEUP)
68 chip_wakeup();
69 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +090070}
Leo Kim2d6973e2015-11-06 11:12:28 +090071
Chaehyun Lim9af382b2015-09-16 20:11:27 +090072static inline void release_bus(BUS_RELEASE_T release)
Johnny Kimc5c77ba2015-05-11 14:30:56 +090073{
74 #ifdef WILC_OPTIMIZE_SLEEP_INT
75 if (release == RELEASE_ALLOW_SLEEP)
76 chip_allow_sleep();
77 #endif
Glen Lee187f1ef2015-09-24 18:15:01 +090078 mutex_unlock(&g_linux_wlan->hif_cs);
Johnny Kimc5c77ba2015-05-11 14:30:56 +090079}
Johnny Kimc5c77ba2015-05-11 14:30:56 +090080
81static void wilc_wlan_txq_remove(struct txq_entry_t *tqe)
82{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +053083 wilc_wlan_dev_t *p = &g_wlan;
Leo Kim8739eeb2015-11-06 11:12:29 +090084
Johnny Kimc5c77ba2015-05-11 14:30:56 +090085 if (tqe == p->txq_head) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +090086 p->txq_head = tqe->next;
87 if (p->txq_head)
88 p->txq_head->prev = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090089 } else if (tqe == p->txq_tail) {
90 p->txq_tail = (tqe->prev);
91 if (p->txq_tail)
92 p->txq_tail->next = NULL;
93 } else {
94 tqe->prev->next = tqe->next;
95 tqe->next->prev = tqe->prev;
96 }
97 p->txq_entries -= 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090098}
99
Glen Lee718fc2c2015-10-29 12:18:43 +0900100static struct txq_entry_t *
101wilc_wlan_txq_remove_from_head(struct net_device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900102{
103 struct txq_entry_t *tqe;
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530104 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900105 unsigned long flags;
Glen Lee718fc2c2015-10-29 12:18:43 +0900106 perInterface_wlan_t *nic;
107 struct wilc *wilc;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900108
Glen Lee718fc2c2015-10-29 12:18:43 +0900109 nic = netdev_priv(dev);
110 wilc = nic->wilc;
111
112 spin_lock_irqsave(&wilc->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900113 if (p->txq_head) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900114 tqe = p->txq_head;
115 p->txq_head = tqe->next;
Alison Schofield39823a52015-10-08 21:18:03 -0700116 if (p->txq_head)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900117 p->txq_head->prev = NULL;
Alison Schofield39823a52015-10-08 21:18:03 -0700118
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900119 p->txq_entries -= 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900120 } else {
121 tqe = NULL;
122 }
Glen Lee718fc2c2015-10-29 12:18:43 +0900123 spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900124 return tqe;
125}
126
Glen Lee32f03322015-10-29 12:18:45 +0900127static void wilc_wlan_txq_add_to_tail(struct net_device *dev,
128 struct txq_entry_t *tqe)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900129{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530130 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900131 unsigned long flags;
Glen Lee32f03322015-10-29 12:18:45 +0900132 perInterface_wlan_t *nic;
133 struct wilc *wilc;
134
135 nic = netdev_priv(dev);
136 wilc = nic->wilc;
137
138 spin_lock_irqsave(&wilc->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900139
Leo Kima4b17192015-11-06 11:12:31 +0900140 if (!p->txq_head) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900141 tqe->next = NULL;
142 tqe->prev = NULL;
143 p->txq_head = tqe;
144 p->txq_tail = tqe;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900145 } else {
146 tqe->next = NULL;
147 tqe->prev = p->txq_tail;
148 p->txq_tail->next = tqe;
149 p->txq_tail = tqe;
150 }
151 p->txq_entries += 1;
152 PRINT_D(TX_DBG, "Number of entries in TxQ = %d\n", p->txq_entries);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900153
Glen Lee32f03322015-10-29 12:18:45 +0900154 spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900155
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900156 PRINT_D(TX_DBG, "Wake the txq_handling\n");
157
Glen Lee32f03322015-10-29 12:18:45 +0900158 up(&wilc->txq_event);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900159}
160
161static int wilc_wlan_txq_add_to_head(struct txq_entry_t *tqe)
162{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530163 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900164 unsigned long flags;
Glen Leeb002e202015-09-24 18:15:05 +0900165 if (linux_wlan_lock_timeout(&g_linux_wlan->txq_add_to_head_cs,
166 CFG_PKTS_TIMEOUT))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900167 return -1;
168
Glen Lee85e57562015-09-24 18:14:56 +0900169 spin_lock_irqsave(&g_linux_wlan->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900170
Leo Kima4b17192015-11-06 11:12:31 +0900171 if (!p->txq_head) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900172 tqe->next = NULL;
173 tqe->prev = NULL;
174 p->txq_head = tqe;
175 p->txq_tail = tqe;
176 } else {
177 tqe->next = p->txq_head;
178 tqe->prev = NULL;
179 p->txq_head->prev = tqe;
180 p->txq_head = tqe;
181 }
182 p->txq_entries += 1;
183 PRINT_D(TX_DBG, "Number of entries in TxQ = %d\n", p->txq_entries);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900184
Glen Lee85e57562015-09-24 18:14:56 +0900185 spin_unlock_irqrestore(&g_linux_wlan->txq_spinlock, flags);
Glen Leed5a63a82015-09-24 18:15:00 +0900186 up(&g_linux_wlan->txq_add_to_head_cs);
Glen Lee5cd63632015-09-24 18:14:58 +0900187 up(&g_linux_wlan->txq_event);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900188 PRINT_D(TX_DBG, "Wake up the txq_handler\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900189
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900190 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900191}
192
Leo Kimeb59da32015-11-06 11:12:33 +0900193u32 total_acks = 0, dropped_acks = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900194
195#ifdef TCP_ACK_FILTER
Leo Kim130a41f2015-11-06 11:12:34 +0900196struct ack_session_info;
197struct ack_session_info {
Leo Kimd06b6cb2015-11-06 11:12:35 +0900198 u32 seq_num;
Leo Kim9d54d3d2015-11-06 11:12:36 +0900199 u32 bigger_ack_num;
Chaehyun Limec53adf2015-09-15 14:06:15 +0900200 u16 src_port;
201 u16 dst_port;
202 u16 status;
Shraddha Barkeeeb1c062015-08-05 01:29:22 +0530203};
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900204
Leo Kim08b90b12015-11-06 11:12:37 +0900205struct pending_acks_info {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900206 u32 ack_num;
Leo Kim84136972015-11-06 11:12:38 +0900207 u32 session_index;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900208 struct txq_entry_t *txqe;
Leo Kim08b90b12015-11-06 11:12:37 +0900209};
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900210
Leo Kim130a41f2015-11-06 11:12:34 +0900211struct ack_session_info *Free_head;
212struct ack_session_info *Alloc_head;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900213
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900214#define NOT_TCP_ACK (-1)
215
216#define MAX_TCP_SESSION 25
217#define MAX_PENDING_ACKS 256
Leo Kim32065052015-11-06 11:12:39 +0900218struct ack_session_info ack_session_info[2 * MAX_TCP_SESSION];
Leo Kim2bb17082015-11-06 11:12:40 +0900219struct pending_acks_info pending_acks_info[MAX_PENDING_ACKS];
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900220
Leo Kim2ae91ed2015-11-06 11:12:41 +0900221u32 pending_base;
Leo Kim3056ec32015-11-06 11:12:42 +0900222u32 tcp_session;
Leo Kimd12ac7e2015-11-06 11:12:43 +0900223u32 pending_acks;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900224
Leo Kimef06b5f2015-11-06 11:12:44 +0900225static inline int init_tcp_tracking(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900226{
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900227 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900228}
Leo Kim2d6973e2015-11-06 11:12:28 +0900229
Leo Kim67620782015-11-06 11:12:45 +0900230static inline int add_tcp_session(u32 src_prt, u32 dst_prt, u32 seq)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900231{
Leo Kim3056ec32015-11-06 11:12:42 +0900232 ack_session_info[tcp_session].seq_num = seq;
233 ack_session_info[tcp_session].bigger_ack_num = 0;
234 ack_session_info[tcp_session].src_port = src_prt;
235 ack_session_info[tcp_session].dst_port = dst_prt;
236 tcp_session++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900237
Leo Kim3056ec32015-11-06 11:12:42 +0900238 PRINT_D(TCP_ENH, "TCP Session %d to Ack %d\n", tcp_session, seq);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900239 return 0;
240}
241
Leo Kimbbf3dbd2015-11-06 11:12:46 +0900242static inline int update_tcp_session(u32 index, u32 Ack)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900243{
Leo Kim32065052015-11-06 11:12:39 +0900244 if (Ack > ack_session_info[index].bigger_ack_num)
245 ack_session_info[index].bigger_ack_num = Ack;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900246 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900247}
Leo Kim2d6973e2015-11-06 11:12:28 +0900248
Leo Kimbdc13ad2015-11-06 11:12:47 +0900249static inline int add_tcp_pending_ack(u32 Ack, u32 Session_index,
250 struct txq_entry_t *txqe)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900251{
Leo Kim821466d2015-11-06 11:12:32 +0900252 total_acks++;
Leo Kimd12ac7e2015-11-06 11:12:43 +0900253 if (pending_acks < MAX_PENDING_ACKS) {
254 pending_acks_info[pending_base + pending_acks].ack_num = Ack;
255 pending_acks_info[pending_base + pending_acks].txqe = txqe;
256 pending_acks_info[pending_base + pending_acks].session_index = Session_index;
257 txqe->tcp_PendingAck_index = pending_base + pending_acks;
258 pending_acks++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900259 } else {
260
261 }
262 return 0;
263}
Chaehyun Limfed16f22015-09-17 16:48:43 +0900264static inline int remove_TCP_related(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900265{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530266 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900267 unsigned long flags;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900268
Glen Lee85e57562015-09-24 18:14:56 +0900269 spin_lock_irqsave(&g_linux_wlan->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900270
Glen Lee85e57562015-09-24 18:14:56 +0900271 spin_unlock_irqrestore(&g_linux_wlan->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900272 return 0;
273}
274
Glen Lee82bb18e2015-10-27 18:28:03 +0900275static inline int tcp_process(struct net_device *dev, struct txq_entry_t *tqe)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900276{
277 int ret;
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900278 u8 *eth_hdr_ptr;
279 u8 *buffer = tqe->buffer;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900280 unsigned short h_proto;
281 int i;
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530282 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900283 unsigned long flags;
Glen Lee82bb18e2015-10-27 18:28:03 +0900284 perInterface_wlan_t *nic;
285 struct wilc *wilc;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900286
Glen Lee82bb18e2015-10-27 18:28:03 +0900287 nic = netdev_priv(dev);
288 wilc = nic->wilc;
289
290 spin_lock_irqsave(&wilc->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900291
292 eth_hdr_ptr = &buffer[0];
293 h_proto = ntohs(*((unsigned short *)&eth_hdr_ptr[12]));
Leo Kimac087c82015-11-06 11:12:25 +0900294 if (h_proto == 0x0800) {
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900295 u8 *ip_hdr_ptr;
296 u8 protocol;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900297
298 ip_hdr_ptr = &buffer[ETHERNET_HDR_LEN];
299 protocol = ip_hdr_ptr[9];
300
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900301 if (protocol == 0x06) {
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900302 u8 *tcp_hdr_ptr;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900303 u32 IHL, Total_Length, Data_offset;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900304
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900305 tcp_hdr_ptr = &ip_hdr_ptr[IP_HDR_LEN];
306 IHL = (ip_hdr_ptr[0] & 0xf) << 2;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900307 Total_Length = (((u32)ip_hdr_ptr[2]) << 8) + ((u32)ip_hdr_ptr[3]);
308 Data_offset = (((u32)tcp_hdr_ptr[12] & 0xf0) >> 2);
Leo Kimac087c82015-11-06 11:12:25 +0900309 if (Total_Length == (IHL + Data_offset)) {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900310 u32 seq_no, Ack_no;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900311
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900312 seq_no = (((u32)tcp_hdr_ptr[4]) << 24) + (((u32)tcp_hdr_ptr[5]) << 16) + (((u32)tcp_hdr_ptr[6]) << 8) + ((u32)tcp_hdr_ptr[7]);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900313
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900314 Ack_no = (((u32)tcp_hdr_ptr[8]) << 24) + (((u32)tcp_hdr_ptr[9]) << 16) + (((u32)tcp_hdr_ptr[10]) << 8) + ((u32)tcp_hdr_ptr[11]);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900315
Leo Kim3056ec32015-11-06 11:12:42 +0900316 for (i = 0; i < tcp_session; i++) {
Leo Kim32065052015-11-06 11:12:39 +0900317 if (ack_session_info[i].seq_num == seq_no) {
Leo Kimbbf3dbd2015-11-06 11:12:46 +0900318 update_tcp_session(i, Ack_no);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900319 break;
320 }
321 }
Leo Kim3056ec32015-11-06 11:12:42 +0900322 if (i == tcp_session)
Leo Kim67620782015-11-06 11:12:45 +0900323 add_tcp_session(0, 0, seq_no);
Alison Schofield39823a52015-10-08 21:18:03 -0700324
Leo Kimbdc13ad2015-11-06 11:12:47 +0900325 add_tcp_pending_ack(Ack_no, i, tqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900326 }
327
328 } else {
329 ret = 0;
330 }
331 } else {
332 ret = 0;
333 }
Glen Lee82bb18e2015-10-27 18:28:03 +0900334 spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900335 return ret;
336}
337
Glen Leec029e992015-10-27 18:27:48 +0900338static int wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900339{
Glen Leec029e992015-10-27 18:27:48 +0900340 perInterface_wlan_t *nic;
341 struct wilc *wilc;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900342 u32 i = 0;
343 u32 Dropped = 0;
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530344 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900345
Glen Leec029e992015-10-27 18:27:48 +0900346 nic = netdev_priv(dev);
347 wilc = nic->wilc;
348
349 spin_lock_irqsave(&wilc->txq_spinlock, p->txq_spinlock_flags);
Leo Kimd12ac7e2015-11-06 11:12:43 +0900350 for (i = pending_base; i < (pending_base + pending_acks); i++) {
Leo Kim2bb17082015-11-06 11:12:40 +0900351 if (pending_acks_info[i].ack_num < ack_session_info[pending_acks_info[i].session_index].bigger_ack_num) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900352 struct txq_entry_t *tqe;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900353
Leo Kim2bb17082015-11-06 11:12:40 +0900354 PRINT_D(TCP_ENH, "DROP ACK: %u\n",
355 pending_acks_info[i].ack_num);
356 tqe = pending_acks_info[i].txqe;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900357 if (tqe) {
358 wilc_wlan_txq_remove(tqe);
Leo Kimeb59da32015-11-06 11:12:33 +0900359 dropped_acks++;
Leo Kimac087c82015-11-06 11:12:25 +0900360 tqe->status = 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900361 if (tqe->tx_complete_func)
362 tqe->tx_complete_func(tqe->priv, tqe->status);
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -0700363 kfree(tqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900364 Dropped++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900365 }
366 }
367 }
Leo Kimd12ac7e2015-11-06 11:12:43 +0900368 pending_acks = 0;
Leo Kim3056ec32015-11-06 11:12:42 +0900369 tcp_session = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900370
Leo Kim2ae91ed2015-11-06 11:12:41 +0900371 if (pending_base == 0)
372 pending_base = MAX_TCP_SESSION;
Chandra S Gorentla78174ad2015-08-08 17:41:36 +0530373 else
Leo Kim2ae91ed2015-11-06 11:12:41 +0900374 pending_base = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900375
Glen Leec029e992015-10-27 18:27:48 +0900376 spin_unlock_irqrestore(&wilc->txq_spinlock, p->txq_spinlock_flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900377
378 while (Dropped > 0) {
Glen Leec029e992015-10-27 18:27:48 +0900379 linux_wlan_lock_timeout(&wilc->txq_event, 1);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900380 Dropped--;
381 }
382
383 return 1;
384}
385#endif
386
Dean Lee72ed4dc2015-06-12 14:11:44 +0900387bool EnableTCPAckFilter = false;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900388
Dean Lee72ed4dc2015-06-12 14:11:44 +0900389void Enable_TCP_ACK_Filter(bool value)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900390{
391 EnableTCPAckFilter = value;
392}
393
Dean Lee72ed4dc2015-06-12 14:11:44 +0900394bool is_TCP_ACK_Filter_Enabled(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900395{
396 return EnableTCPAckFilter;
397}
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900398
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900399static int wilc_wlan_txq_add_cfg_pkt(u8 *buffer, u32 buffer_size)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900400{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530401 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900402 struct txq_entry_t *tqe;
403
404 PRINT_D(TX_DBG, "Adding config packet ...\n");
405 if (p->quit) {
406 PRINT_D(TX_DBG, "Return due to clear function\n");
Glen Lee6a3b94f2015-09-24 18:14:59 +0900407 up(&g_linux_wlan->cfg_event);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900408 return 0;
409 }
410
Greg Kroah-Hartman47c632d2015-09-03 18:55:43 -0700411 tqe = kmalloc(sizeof(struct txq_entry_t), GFP_ATOMIC);
Leo Kima4b17192015-11-06 11:12:31 +0900412 if (!tqe) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900413 PRINT_ER("Failed to allocate memory\n");
414 return 0;
415 }
416
417 tqe->type = WILC_CFG_PKT;
418 tqe->buffer = buffer;
419 tqe->buffer_size = buffer_size;
420 tqe->tx_complete_func = NULL;
421 tqe->priv = NULL;
422#ifdef TCP_ACK_FILTER
423 tqe->tcp_PendingAck_index = NOT_TCP_ACK;
424#endif
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900425 PRINT_D(TX_DBG, "Adding the config packet at the Queue tail\n");
426
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900427 if (wilc_wlan_txq_add_to_head(tqe))
428 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900429 return 1;
430}
431
Glen Lee691bbd42015-10-27 18:28:02 +0900432int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
433 u32 buffer_size, wilc_tx_complete_func_t func)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900434{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530435 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900436 struct txq_entry_t *tqe;
437
438 if (p->quit)
439 return 0;
440
Greg Kroah-Hartman47c632d2015-09-03 18:55:43 -0700441 tqe = kmalloc(sizeof(struct txq_entry_t), GFP_ATOMIC);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900442
Leo Kima4b17192015-11-06 11:12:31 +0900443 if (!tqe)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900444 return 0;
445 tqe->type = WILC_NET_PKT;
446 tqe->buffer = buffer;
447 tqe->buffer_size = buffer_size;
448 tqe->tx_complete_func = func;
449 tqe->priv = priv;
450
451 PRINT_D(TX_DBG, "Adding mgmt packet at the Queue tail\n");
452#ifdef TCP_ACK_FILTER
453 tqe->tcp_PendingAck_index = NOT_TCP_ACK;
Abdul Hussain5a66bf22015-06-16 09:44:06 +0000454 if (is_TCP_ACK_Filter_Enabled())
Glen Lee82bb18e2015-10-27 18:28:03 +0900455 tcp_process(dev, tqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900456#endif
Glen Lee32f03322015-10-29 12:18:45 +0900457 wilc_wlan_txq_add_to_tail(dev, tqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900458 return p->txq_entries;
459}
Glen Leefcc6ef92015-09-16 18:53:21 +0900460
Glen Lee829c4772015-10-29 12:18:44 +0900461int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer,
462 u32 buffer_size, wilc_tx_complete_func_t func)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900463{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530464 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900465 struct txq_entry_t *tqe;
466
467 if (p->quit)
468 return 0;
469
Greg Kroah-Hartman47c632d2015-09-03 18:55:43 -0700470 tqe = kmalloc(sizeof(struct txq_entry_t), GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900471
Leo Kima4b17192015-11-06 11:12:31 +0900472 if (!tqe)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900473 return 0;
474 tqe->type = WILC_MGMT_PKT;
475 tqe->buffer = buffer;
476 tqe->buffer_size = buffer_size;
477 tqe->tx_complete_func = func;
478 tqe->priv = priv;
479#ifdef TCP_ACK_FILTER
480 tqe->tcp_PendingAck_index = NOT_TCP_ACK;
481#endif
482 PRINT_D(TX_DBG, "Adding Network packet at the Queue tail\n");
Glen Lee32f03322015-10-29 12:18:45 +0900483 wilc_wlan_txq_add_to_tail(dev, tqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900484 return 1;
485}
Glen Leefcc6ef92015-09-16 18:53:21 +0900486
Glen Lee7af05222015-10-29 12:18:41 +0900487static struct txq_entry_t *wilc_wlan_txq_get_first(struct wilc *wilc)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900488{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530489 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900490 struct txq_entry_t *tqe;
491 unsigned long flags;
492
Glen Lee7af05222015-10-29 12:18:41 +0900493 spin_lock_irqsave(&wilc->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900494
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900495 tqe = p->txq_head;
496
Glen Lee7af05222015-10-29 12:18:41 +0900497 spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900498
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900499 return tqe;
500}
501
Glen Lee50a0b3b2015-10-27 18:28:00 +0900502static struct txq_entry_t *wilc_wlan_txq_get_next(struct wilc *wilc,
503 struct txq_entry_t *tqe)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900504{
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900505 unsigned long flags;
Leo Kim8739eeb2015-11-06 11:12:29 +0900506
Glen Lee50a0b3b2015-10-27 18:28:00 +0900507 spin_lock_irqsave(&wilc->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900508
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900509 tqe = tqe->next;
Glen Lee50a0b3b2015-10-27 18:28:00 +0900510 spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900511
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900512 return tqe;
513}
514
Glen Leed06f3622015-10-27 18:27:59 +0900515static int wilc_wlan_rxq_add(struct wilc *wilc, struct rxq_entry_t *rqe)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900516{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530517 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900518
519 if (p->quit)
520 return 0;
521
Glen Leed06f3622015-10-27 18:27:59 +0900522 mutex_lock(&wilc->rxq_cs);
Leo Kima4b17192015-11-06 11:12:31 +0900523 if (!p->rxq_head) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900524 PRINT_D(RX_DBG, "Add to Queue head\n");
525 rqe->next = NULL;
526 p->rxq_head = rqe;
527 p->rxq_tail = rqe;
528 } else {
529 PRINT_D(RX_DBG, "Add to Queue tail\n");
530 p->rxq_tail->next = rqe;
531 rqe->next = NULL;
532 p->rxq_tail = rqe;
533 }
534 p->rxq_entries += 1;
535 PRINT_D(RX_DBG, "Number of queue entries: %d\n", p->rxq_entries);
Glen Leed06f3622015-10-27 18:27:59 +0900536 mutex_unlock(&wilc->rxq_cs);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900537 return p->rxq_entries;
538}
539
Glen Leedb387632015-10-27 18:27:55 +0900540static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900541{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530542 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900543
544 PRINT_D(RX_DBG, "Getting rxQ element\n");
545 if (p->rxq_head) {
546 struct rxq_entry_t *rqe;
547
Glen Leedb387632015-10-27 18:27:55 +0900548 mutex_lock(&wilc->rxq_cs);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900549 rqe = p->rxq_head;
550 p->rxq_head = p->rxq_head->next;
551 p->rxq_entries -= 1;
552 PRINT_D(RX_DBG, "RXQ entries decreased\n");
Glen Leedb387632015-10-27 18:27:55 +0900553 mutex_unlock(&wilc->rxq_cs);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900554 return rqe;
555 }
556 PRINT_D(RX_DBG, "Nothing to get from Q\n");
557 return NULL;
558}
559
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900560#ifdef WILC_OPTIMIZE_SLEEP_INT
561
Chaehyun Lim9af382b2015-09-16 20:11:27 +0900562static inline void chip_allow_sleep(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900563{
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900564 u32 reg = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900565
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900566 g_wlan.hif_func.hif_read_reg(0xf0, &reg);
567
Anish Bhattffda2032015-09-29 12:15:49 -0700568 g_wlan.hif_func.hif_write_reg(0xf0, reg & ~BIT(0));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900569}
570
Chaehyun Lim9af382b2015-09-16 20:11:27 +0900571static inline void chip_wakeup(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900572{
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900573 u32 reg, clk_status_reg, trials = 0;
574 u32 sleep_time;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900575
576 if ((g_wlan.io_func.io_type & 0x1) == HIF_SPI) {
577 do {
578 g_wlan.hif_func.hif_read_reg(1, &reg);
Anish Bhattffda2032015-09-29 12:15:49 -0700579 g_wlan.hif_func.hif_write_reg(1, reg | BIT(1));
Anish Bhattffda2032015-09-29 12:15:49 -0700580 g_wlan.hif_func.hif_write_reg(1, reg & ~BIT(1));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900581
582 do {
Greg Kroah-Hartman80e29c72015-08-14 19:42:23 -0700583 usleep_range(2 * 1000, 2 * 1000);
Alison Schofield39823a52015-10-08 21:18:03 -0700584 if ((wilc_get_chipid(true) == 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900585 wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n");
Alison Schofield39823a52015-10-08 21:18:03 -0700586
Dean Lee72ed4dc2015-06-12 14:11:44 +0900587 } while ((wilc_get_chipid(true) == 0) && ((++trials % 3) == 0));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900588
Dean Lee72ed4dc2015-06-12 14:11:44 +0900589 } while (wilc_get_chipid(true) == 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900590 } else if ((g_wlan.io_func.io_type & 0x1) == HIF_SDIO) {
591 g_wlan.hif_func.hif_read_reg(0xf0, &reg);
592 do {
Anish Bhattffda2032015-09-29 12:15:49 -0700593 g_wlan.hif_func.hif_write_reg(0xf0, reg | BIT(0));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900594 g_wlan.hif_func.hif_read_reg(0xf1, &clk_status_reg);
595
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900596 while (((clk_status_reg & 0x1) == 0) && (((++trials) % 3) == 0)) {
Greg Kroah-Hartman80e29c72015-08-14 19:42:23 -0700597 usleep_range(2 * 1000, 2 * 1000);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900598
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900599 g_wlan.hif_func.hif_read_reg(0xf1, &clk_status_reg);
600
Alison Schofield39823a52015-10-08 21:18:03 -0700601 if ((clk_status_reg & 0x1) == 0)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900602 wilc_debug(N_ERR, "clocks still OFF. Wake up failed\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900603 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900604 if ((clk_status_reg & 0x1) == 0) {
Anish Bhattffda2032015-09-29 12:15:49 -0700605 g_wlan.hif_func.hif_write_reg(0xf0, reg &
606 (~BIT(0)));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900607 }
608 } while ((clk_status_reg & 0x1) == 0);
609 }
610
Leo Kimb7d1e182015-11-06 11:12:30 +0900611 if (chip_ps_state == CHIP_SLEEPING_MANUAL) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900612 g_wlan.hif_func.hif_read_reg(0x1C0C, &reg);
Anish Bhattffda2032015-09-29 12:15:49 -0700613 reg &= ~BIT(0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900614 g_wlan.hif_func.hif_write_reg(0x1C0C, reg);
615
Dean Lee72ed4dc2015-06-12 14:11:44 +0900616 if (wilc_get_chipid(false) >= 0x1002b0) {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900617 u32 val32;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900618
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900619 g_wlan.hif_func.hif_read_reg(0x1e1c, &val32);
Anish Bhattffda2032015-09-29 12:15:49 -0700620 val32 |= BIT(6);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900621 g_wlan.hif_func.hif_write_reg(0x1e1c, val32);
622
623 g_wlan.hif_func.hif_read_reg(0x1e9c, &val32);
Anish Bhattffda2032015-09-29 12:15:49 -0700624 val32 |= BIT(6);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900625 g_wlan.hif_func.hif_write_reg(0x1e9c, val32);
626 }
627 }
Leo Kimb7d1e182015-11-06 11:12:30 +0900628 chip_ps_state = CHIP_WAKEDUP;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900629}
630#else
Chaehyun Lim9af382b2015-09-16 20:11:27 +0900631static inline void chip_wakeup(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900632{
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900633 u32 reg, trials = 0;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900634
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900635 do {
636 if ((g_wlan.io_func.io_type & 0x1) == HIF_SPI) {
637 g_wlan.hif_func.hif_read_reg(1, &reg);
Anish Bhattffda2032015-09-29 12:15:49 -0700638 g_wlan.hif_func.hif_write_reg(1, reg & ~BIT(1));
Anish Bhattffda2032015-09-29 12:15:49 -0700639 g_wlan.hif_func.hif_write_reg(1, reg | BIT(1));
Anish Bhattffda2032015-09-29 12:15:49 -0700640 g_wlan.hif_func.hif_write_reg(1, reg & ~BIT(1));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900641 } else if ((g_wlan.io_func.io_type & 0x1) == HIF_SDIO) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900642 g_wlan.hif_func.hif_read_reg(0xf0, &reg);
Anish Bhattffda2032015-09-29 12:15:49 -0700643 g_wlan.hif_func.hif_write_reg(0xf0, reg & ~BIT(0));
Anish Bhattffda2032015-09-29 12:15:49 -0700644 g_wlan.hif_func.hif_write_reg(0xf0, reg | BIT(0));
Anish Bhattffda2032015-09-29 12:15:49 -0700645 g_wlan.hif_func.hif_write_reg(0xf0, reg & ~BIT(0));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900646 }
647
648 do {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900649 mdelay(3);
650
Alison Schofield39823a52015-10-08 21:18:03 -0700651 if ((wilc_get_chipid(true) == 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900652 wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n");
Alison Schofield39823a52015-10-08 21:18:03 -0700653
Dean Lee72ed4dc2015-06-12 14:11:44 +0900654 } while ((wilc_get_chipid(true) == 0) && ((++trials % 3) == 0));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900655
Dean Lee72ed4dc2015-06-12 14:11:44 +0900656 } while (wilc_get_chipid(true) == 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900657
Leo Kimb7d1e182015-11-06 11:12:30 +0900658 if (chip_ps_state == CHIP_SLEEPING_MANUAL) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900659 g_wlan.hif_func.hif_read_reg(0x1C0C, &reg);
Anish Bhattffda2032015-09-29 12:15:49 -0700660 reg &= ~BIT(0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900661 g_wlan.hif_func.hif_write_reg(0x1C0C, reg);
662
Dean Lee72ed4dc2015-06-12 14:11:44 +0900663 if (wilc_get_chipid(false) >= 0x1002b0) {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900664 u32 val32;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900665
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900666 g_wlan.hif_func.hif_read_reg(0x1e1c, &val32);
Anish Bhattffda2032015-09-29 12:15:49 -0700667 val32 |= BIT(6);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900668 g_wlan.hif_func.hif_write_reg(0x1e1c, val32);
669
670 g_wlan.hif_func.hif_read_reg(0x1e9c, &val32);
Anish Bhattffda2032015-09-29 12:15:49 -0700671 val32 |= BIT(6);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900672 g_wlan.hif_func.hif_write_reg(0x1e9c, val32);
673 }
674 }
Leo Kimb7d1e182015-11-06 11:12:30 +0900675 chip_ps_state = CHIP_WAKEDUP;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900676}
677#endif
Chaehyun Lim4e4467f2015-06-11 14:35:55 +0900678void chip_sleep_manually(u32 u32SleepTime)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900679{
Leo Kimb7d1e182015-11-06 11:12:30 +0900680 if (chip_ps_state != CHIP_WAKEDUP)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900681 return;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900682 acquire_bus(ACQUIRE_ONLY);
683
684#ifdef WILC_OPTIMIZE_SLEEP_INT
685 chip_allow_sleep();
686#endif
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900687 g_wlan.hif_func.hif_write_reg(0x10a8, 1);
688
Leo Kimb7d1e182015-11-06 11:12:30 +0900689 chip_ps_state = CHIP_SLEEPING_MANUAL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900690 release_bus(RELEASE_ONLY);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900691}
692
Glen Leea1332ca2015-10-27 18:27:47 +0900693int wilc_wlan_handle_txq(struct net_device *dev, u32 *pu32TxqCount)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900694{
695 wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
696 int i, entries = 0;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900697 u32 sum;
698 u32 reg;
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900699 u8 *txb = p->tx_buffer;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900700 u32 offset = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900701 int vmm_sz = 0;
702 struct txq_entry_t *tqe;
703 int ret = 0;
704 int counter;
705 int timeout;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900706 u32 vmm_table[WILC_VMM_TBL_SIZE];
Glen Leea1332ca2015-10-27 18:27:47 +0900707 perInterface_wlan_t *nic;
708 struct wilc *wilc;
709
710 nic = netdev_priv(dev);
711 wilc = nic->wilc;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900712
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900713 p->txq_exit = 0;
714 do {
715 if (p->quit)
716 break;
717
Glen Leea1332ca2015-10-27 18:27:47 +0900718 linux_wlan_lock_timeout(&wilc->txq_add_to_head_cs,
Glen Leeb002e202015-09-24 18:15:05 +0900719 CFG_PKTS_TIMEOUT);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900720#ifdef TCP_ACK_FILTER
Glen Leec029e992015-10-27 18:27:48 +0900721 wilc_wlan_txq_filter_dup_tcp_ack(dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900722#endif
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900723 PRINT_D(TX_DBG, "Getting the head of the TxQ\n");
Glen Lee7af05222015-10-29 12:18:41 +0900724 tqe = wilc_wlan_txq_get_first(wilc);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900725 i = 0;
726 sum = 0;
727 do {
Leo Kima4b17192015-11-06 11:12:31 +0900728 if (tqe && (i < (WILC_VMM_TBL_SIZE - 1))) {
Alison Schofield39823a52015-10-08 21:18:03 -0700729 if (tqe->type == WILC_CFG_PKT)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900730 vmm_sz = ETH_CONFIG_PKT_HDR_OFFSET;
Alison Schofield39823a52015-10-08 21:18:03 -0700731
732 else if (tqe->type == WILC_NET_PKT)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900733 vmm_sz = ETH_ETHERNET_HDR_OFFSET;
Alison Schofield39823a52015-10-08 21:18:03 -0700734
735 else
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900736 vmm_sz = HOST_HDR_OFFSET;
Alison Schofield39823a52015-10-08 21:18:03 -0700737
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900738 vmm_sz += tqe->buffer_size;
739 PRINT_D(TX_DBG, "VMM Size before alignment = %d\n", vmm_sz);
Leo Kimac087c82015-11-06 11:12:25 +0900740 if (vmm_sz & 0x3)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900741 vmm_sz = (vmm_sz + 4) & ~0x3;
Leo Kimac087c82015-11-06 11:12:25 +0900742
Alison Schofield39823a52015-10-08 21:18:03 -0700743 if ((sum + vmm_sz) > LINUX_TX_SIZE)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900744 break;
Alison Schofield39823a52015-10-08 21:18:03 -0700745
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900746 PRINT_D(TX_DBG, "VMM Size AFTER alignment = %d\n", vmm_sz);
Leo Kimac087c82015-11-06 11:12:25 +0900747 vmm_table[i] = vmm_sz / 4;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900748 PRINT_D(TX_DBG, "VMMTable entry size = %d\n", vmm_table[i]);
749
750 if (tqe->type == WILC_CFG_PKT) {
Anish Bhattffda2032015-09-29 12:15:49 -0700751 vmm_table[i] |= BIT(10);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900752 PRINT_D(TX_DBG, "VMMTable entry changed for CFG packet = %d\n", vmm_table[i]);
753 }
754#ifdef BIG_ENDIAN
755 vmm_table[i] = BYTE_SWAP(vmm_table[i]);
756#endif
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900757
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900758 i++;
759 sum += vmm_sz;
760 PRINT_D(TX_DBG, "sum = %d\n", sum);
Glen Lee50a0b3b2015-10-27 18:28:00 +0900761 tqe = wilc_wlan_txq_get_next(wilc, tqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900762 } else {
763 break;
764 }
765 } while (1);
766
Leo Kimac087c82015-11-06 11:12:25 +0900767 if (i == 0) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900768 PRINT_D(TX_DBG, "Nothing in TX-Q\n");
769 break;
770 } else {
771 PRINT_D(TX_DBG, "Mark the last entry in VMM table - number of previous entries = %d\n", i);
Leo Kimac087c82015-11-06 11:12:25 +0900772 vmm_table[i] = 0x0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900773 }
774 acquire_bus(ACQUIRE_AND_WAKEUP);
775 counter = 0;
776 do {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900777 ret = p->hif_func.hif_read_reg(WILC_HOST_TX_CTRL, &reg);
778 if (!ret) {
779 wilc_debug(N_ERR, "[wilc txq]: fail can't read reg vmm_tbl_entry..\n");
780 break;
781 }
782
783 if ((reg & 0x1) == 0) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900784 PRINT_D(TX_DBG, "Writing VMM table ... with Size = %d\n", ((i + 1) * 4));
785 break;
786 } else {
787 counter++;
788 if (counter > 200) {
789 counter = 0;
790 PRINT_D(TX_DBG, "Looping in tx ctrl , forcce quit\n");
791 ret = p->hif_func.hif_write_reg(WILC_HOST_TX_CTRL, 0);
792 break;
793 }
Chandra S Gorentla17aacd42015-08-08 17:41:35 +0530794 PRINT_WRN(GENERIC_DBG, "[wilc txq]: warn, vmm table not clear yet, wait...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900795 release_bus(RELEASE_ALLOW_SLEEP);
Greg Kroah-Hartman2b922cb2015-09-04 09:30:51 -0700796 usleep_range(3000, 3000);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900797 acquire_bus(ACQUIRE_AND_WAKEUP);
798 }
799 } while (!p->quit);
800
Alison Schofield39823a52015-10-08 21:18:03 -0700801 if (!ret)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900802 goto _end_;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900803
804 timeout = 200;
805 do {
Chaehyun Limc3ca6372015-09-20 15:51:19 +0900806 ret = p->hif_func.hif_block_tx(WILC_VMM_TBL_RX_SHADOW_BASE, (u8 *)vmm_table, ((i + 1) * 4));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900807 if (!ret) {
808 wilc_debug(N_ERR, "ERR block TX of VMM table.\n");
809 break;
810 }
811
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900812 ret = p->hif_func.hif_write_reg(WILC_HOST_VMM_CTL, 0x2);
813 if (!ret) {
814 wilc_debug(N_ERR, "[wilc txq]: fail can't write reg host_vmm_ctl..\n");
815 break;
816 }
817
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900818 do {
819 ret = p->hif_func.hif_read_reg(WILC_HOST_VMM_CTL, &reg);
820 if (!ret) {
821 wilc_debug(N_ERR, "[wilc txq]: fail can't read reg host_vmm_ctl..\n");
822 break;
823 }
824 if ((reg >> 2) & 0x1) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900825 entries = ((reg >> 3) & 0x3f);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900826 break;
827 } else {
828 release_bus(RELEASE_ALLOW_SLEEP);
Greg Kroah-Hartman2b922cb2015-09-04 09:30:51 -0700829 usleep_range(3000, 3000);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900830 acquire_bus(ACQUIRE_AND_WAKEUP);
831 PRINT_WRN(GENERIC_DBG, "Can't get VMM entery - reg = %2x\n", reg);
832 }
833 } while (--timeout);
834 if (timeout <= 0) {
835 ret = p->hif_func.hif_write_reg(WILC_HOST_VMM_CTL, 0x0);
836 break;
837 }
838
Alison Schofield39823a52015-10-08 21:18:03 -0700839 if (!ret)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900840 break;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900841
842 if (entries == 0) {
Chandra S Gorentla17aacd42015-08-08 17:41:35 +0530843 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]);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900844
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900845 ret = p->hif_func.hif_read_reg(WILC_HOST_TX_CTRL, &reg);
846 if (!ret) {
847 wilc_debug(N_ERR, "[wilc txq]: fail can't read reg WILC_HOST_TX_CTRL..\n");
848 break;
849 }
Anish Bhattffda2032015-09-29 12:15:49 -0700850 reg &= ~BIT(0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900851 ret = p->hif_func.hif_write_reg(WILC_HOST_TX_CTRL, reg);
852 if (!ret) {
853 wilc_debug(N_ERR, "[wilc txq]: fail can't write reg WILC_HOST_TX_CTRL..\n");
854 break;
855 }
856 break;
857 } else {
858 break;
859 }
860 } while (1);
861
Alison Schofield39823a52015-10-08 21:18:03 -0700862 if (!ret)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900863 goto _end_;
Alison Schofield39823a52015-10-08 21:18:03 -0700864
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900865 if (entries == 0) {
866 ret = WILC_TX_ERR_NO_BUF;
867 goto _end_;
868 }
869
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900870 release_bus(RELEASE_ALLOW_SLEEP);
871
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900872 offset = 0;
873 i = 0;
874 do {
Glen Lee718fc2c2015-10-29 12:18:43 +0900875 tqe = wilc_wlan_txq_remove_from_head(dev);
Leo Kima4b17192015-11-06 11:12:31 +0900876 if (tqe && (vmm_table[i] != 0)) {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900877 u32 header, buffer_offset;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900878
879#ifdef BIG_ENDIAN
880 vmm_table[i] = BYTE_SWAP(vmm_table[i]);
881#endif
Leo Kimac087c82015-11-06 11:12:25 +0900882 vmm_sz = (vmm_table[i] & 0x3ff);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900883 vmm_sz *= 4;
884 header = (tqe->type << 31) | (tqe->buffer_size << 15) | vmm_sz;
Chandra S Gorentla78174ad2015-08-08 17:41:36 +0530885 if (tqe->type == WILC_MGMT_PKT)
Anish Bhattffda2032015-09-29 12:15:49 -0700886 header |= BIT(30);
Chandra S Gorentla78174ad2015-08-08 17:41:36 +0530887 else
Anish Bhattffda2032015-09-29 12:15:49 -0700888 header &= ~BIT(30);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900889
890#ifdef BIG_ENDIAN
891 header = BYTE_SWAP(header);
892#endif
893 memcpy(&txb[offset], &header, 4);
894 if (tqe->type == WILC_CFG_PKT) {
895 buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET;
896 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900897 else if (tqe->type == WILC_NET_PKT) {
898 char *pBSSID = ((struct tx_complete_data *)(tqe->priv))->pBssid;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900899
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900900 buffer_offset = ETH_ETHERNET_HDR_OFFSET;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900901 memcpy(&txb[offset + 4], pBSSID, 6);
902 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900903 else {
904 buffer_offset = HOST_HDR_OFFSET;
905 }
906
907 memcpy(&txb[offset + buffer_offset], tqe->buffer, tqe->buffer_size);
908 offset += vmm_sz;
909 i++;
Leo Kimac087c82015-11-06 11:12:25 +0900910 tqe->status = 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900911 if (tqe->tx_complete_func)
912 tqe->tx_complete_func(tqe->priv, tqe->status);
913 #ifdef TCP_ACK_FILTER
Alison Schofield39823a52015-10-08 21:18:03 -0700914 if (tqe->tcp_PendingAck_index != NOT_TCP_ACK)
Leo Kim2bb17082015-11-06 11:12:40 +0900915 pending_acks_info[tqe->tcp_PendingAck_index].txqe = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900916 #endif
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -0700917 kfree(tqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900918 } else {
919 break;
920 }
921 } while (--entries);
922
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900923 acquire_bus(ACQUIRE_AND_WAKEUP);
924
925 ret = p->hif_func.hif_clear_int_ext(ENABLE_TX_VMM);
926 if (!ret) {
927 wilc_debug(N_ERR, "[wilc txq]: fail can't start tx VMM ...\n");
928 goto _end_;
929 }
930
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900931 ret = p->hif_func.hif_block_tx_ext(0, txb, offset);
932 if (!ret) {
933 wilc_debug(N_ERR, "[wilc txq]: fail can't block tx ext...\n");
934 goto _end_;
935 }
936
937_end_:
938
939 release_bus(RELEASE_ALLOW_SLEEP);
940 if (ret != 1)
941 break;
942 } while (0);
Glen Leea1332ca2015-10-27 18:27:47 +0900943 up(&wilc->txq_add_to_head_cs);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900944
945 p->txq_exit = 1;
946 PRINT_D(TX_DBG, "THREAD: Exiting txq\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900947 *pu32TxqCount = p->txq_entries;
948 return ret;
949}
950
Glen Lee39ce4d32015-10-27 18:27:42 +0900951static void wilc_wlan_handle_rxq(struct wilc *wilc)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900952{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530953 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900954 int offset = 0, size, has_packet = 0;
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900955 u8 *buffer;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900956 struct rxq_entry_t *rqe;
957
958 p->rxq_exit = 0;
959
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900960 do {
961 if (p->quit) {
Chandra S Gorentla17aacd42015-08-08 17:41:35 +0530962 PRINT_D(RX_DBG, "exit 1st do-while due to Clean_UP function\n");
Glen Lee39ce4d32015-10-27 18:27:42 +0900963 up(&wilc->cfg_event);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900964 break;
965 }
Glen Leedb387632015-10-27 18:27:55 +0900966 rqe = wilc_wlan_rxq_remove(wilc);
Leo Kima4b17192015-11-06 11:12:31 +0900967 if (!rqe) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900968 PRINT_D(RX_DBG, "nothing in the queue - exit 1st do-while\n");
969 break;
970 }
971 buffer = rqe->buffer;
972 size = rqe->buffer_size;
973 PRINT_D(RX_DBG, "rxQ entery Size = %d - Address = %p\n", size, buffer);
974 offset = 0;
975
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900976 do {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900977 u32 header;
978 u32 pkt_len, pkt_offset, tp_len;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900979 int is_cfg_packet;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900980
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900981 PRINT_D(RX_DBG, "In the 2nd do-while\n");
982 memcpy(&header, &buffer[offset], 4);
983#ifdef BIG_ENDIAN
984 header = BYTE_SWAP(header);
985#endif
986 PRINT_D(RX_DBG, "Header = %04x - Offset = %d\n", header, offset);
987
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900988 is_cfg_packet = (header >> 31) & 0x1;
989 pkt_offset = (header >> 22) & 0x1ff;
990 tp_len = (header >> 11) & 0x7ff;
991 pkt_len = header & 0x7ff;
992
993 if (pkt_len == 0 || tp_len == 0) {
994 wilc_debug(N_RXQ, "[wilc rxq]: data corrupt, packet len or tp_len is 0 [%d][%d]\n", pkt_len, tp_len);
995 break;
996 }
997
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900998 #define IS_MANAGMEMENT 0x100
999 #define IS_MANAGMEMENT_CALLBACK 0x080
1000 #define IS_MGMT_STATUS_SUCCES 0x040
1001
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001002 if (pkt_offset & IS_MANAGMEMENT) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001003 pkt_offset &= ~(IS_MANAGMEMENT | IS_MANAGMEMENT_CALLBACK | IS_MGMT_STATUS_SUCCES);
1004
Glen Lee11f4b2e2015-10-27 18:27:51 +09001005 WILC_WFI_mgmt_rx(wilc, &buffer[offset + HOST_HDR_OFFSET], pkt_len);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001006 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001007 else
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001008 {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001009 if (!is_cfg_packet) {
Glen Lee63611672015-09-24 18:14:52 +09001010 if (pkt_len > 0) {
Glen Leecb1991a2015-10-27 18:27:56 +09001011 frmw_to_linux(wilc,
1012 &buffer[offset],
Glen Lee63611672015-09-24 18:14:52 +09001013 pkt_len,
1014 pkt_offset);
1015 has_packet = 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001016 }
1017 } else {
1018 wilc_cfg_rsp_t rsp;
1019
Glen Lee30f535a2015-10-02 14:22:10 +09001020 wilc_wlan_cfg_indicate_rx(&buffer[pkt_offset + offset], pkt_len, &rsp);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001021 if (rsp.type == WILC_CFG_RSP) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001022 PRINT_D(RX_DBG, "p->cfg_seq_no = %d - rsp.seq_no = %d\n", p->cfg_seq_no, rsp.seq_no);
Alison Schofield39823a52015-10-08 21:18:03 -07001023 if (p->cfg_seq_no == rsp.seq_no)
Glen Lee39ce4d32015-10-27 18:27:42 +09001024 up(&wilc->cfg_event);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001025 } else if (rsp.type == WILC_CFG_RSP_STATUS) {
Glen Lee64f2b712015-10-27 18:27:43 +09001026 linux_wlan_mac_indicate(wilc, WILC_MAC_INDICATE_STATUS);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001027
1028 } else if (rsp.type == WILC_CFG_RSP_SCAN) {
Glen Lee64f2b712015-10-27 18:27:43 +09001029 linux_wlan_mac_indicate(wilc, WILC_MAC_INDICATE_SCAN);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001030 }
1031 }
1032 }
1033 offset += tp_len;
1034 if (offset >= size)
1035 break;
1036 } while (1);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001037#ifndef MEMORY_STATIC
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001038 kfree(buffer);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001039#endif
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001040 kfree(rqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001041
Alison Schofield39823a52015-10-08 21:18:03 -07001042 if (has_packet)
Glen Leec0cadaa2015-09-24 18:14:54 +09001043 linux_wlan_rx_complete();
Alison Schofield39823a52015-10-08 21:18:03 -07001044
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001045 } while (1);
1046
1047 p->rxq_exit = 1;
Chandra S Gorentla17aacd42015-08-08 17:41:35 +05301048 PRINT_D(RX_DBG, "THREAD: Exiting RX thread\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001049}
1050
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001051static void wilc_unknown_isr_ext(void)
1052{
1053 g_wlan.hif_func.hif_clear_int_ext(0);
1054}
Leo Kim2d6973e2015-11-06 11:12:28 +09001055
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001056static void wilc_pllupdate_isr_ext(u32 int_stats)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001057{
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001058 int trials = 10;
1059
1060 g_wlan.hif_func.hif_clear_int_ext(PLL_INT_CLR);
1061
Greg Kroah-Hartmanc2e4c0f2015-09-03 19:09:50 -07001062 mdelay(WILC_PLL_TO);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001063
Dean Lee72ed4dc2015-06-12 14:11:44 +09001064 while (!(ISWILC1000(wilc_get_chipid(true)) && --trials)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001065 PRINT_D(TX_DBG, "PLL update retrying\n");
Greg Kroah-Hartmanc2e4c0f2015-09-03 19:09:50 -07001066 mdelay(1);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001067 }
1068}
1069
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001070static void wilc_sleeptimer_isr_ext(u32 int_stats1)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001071{
1072 g_wlan.hif_func.hif_clear_int_ext(SLEEP_INT_CLR);
1073#ifndef WILC_OPTIMIZE_SLEEP_INT
Leo Kimb7d1e182015-11-06 11:12:30 +09001074 chip_ps_state = CHIP_SLEEPING_AUTO;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001075#endif
1076}
1077
Glen Lee3bcd45b2015-10-27 18:27:41 +09001078static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001079{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +05301080 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001081#ifdef MEMORY_STATIC
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001082 u32 offset = p->rx_buffer_offset;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001083#endif
Chaehyun Lim51e825f2015-09-15 14:06:14 +09001084 u8 *buffer = NULL;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001085 u32 size;
1086 u32 retries = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001087 int ret = 0;
1088 struct rxq_entry_t *rqe;
1089
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001090 size = ((int_status & 0x7fff) << 2);
1091
1092 while (!size && retries < 10) {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001093 u32 time = 0;
Leo Kimac087c82015-11-06 11:12:25 +09001094
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001095 wilc_debug(N_ERR, "RX Size equal zero ... Trying to read it again for %d time\n", time++);
1096 p->hif_func.hif_read_size(&size);
1097 size = ((size & 0x7fff) << 2);
1098 retries++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001099 }
1100
1101 if (size > 0) {
1102#ifdef MEMORY_STATIC
Glen Lee03eb7262015-09-24 18:15:03 +09001103 if (LINUX_RX_SIZE - offset < size)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001104 offset = 0;
1105
1106 if (p->rx_buffer)
1107 buffer = &p->rx_buffer[offset];
1108 else {
1109 wilc_debug(N_ERR, "[wilc isr]: fail Rx Buffer is NULL...drop the packets (%d)\n", size);
1110 goto _end_;
1111 }
1112
1113#else
Greg Kroah-Hartmanf019b9d2015-09-03 18:50:27 -07001114 buffer = kmalloc(size, GFP_KERNEL);
Leo Kima4b17192015-11-06 11:12:31 +09001115 if (!buffer) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001116 wilc_debug(N_ERR, "[wilc isr]: fail alloc host memory...drop the packets (%d)\n", size);
Greg Kroah-Hartman80e29c72015-08-14 19:42:23 -07001117 usleep_range(100 * 1000, 100 * 1000);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001118 goto _end_;
1119 }
1120#endif
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001121 p->hif_func.hif_clear_int_ext(DATA_INT_CLR | ENABLE_RX_VMM);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001122 ret = p->hif_func.hif_block_rx_ext(0, buffer, size);
1123
1124 if (!ret) {
1125 wilc_debug(N_ERR, "[wilc isr]: fail block rx...\n");
1126 goto _end_;
1127 }
1128_end_:
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001129 if (ret) {
1130#ifdef MEMORY_STATIC
1131 offset += size;
1132 p->rx_buffer_offset = offset;
1133#endif
Greg Kroah-Hartmanf019b9d2015-09-03 18:50:27 -07001134 rqe = kmalloc(sizeof(struct rxq_entry_t), GFP_KERNEL);
Leo Kima4b17192015-11-06 11:12:31 +09001135 if (rqe) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001136 rqe->buffer = buffer;
1137 rqe->buffer_size = size;
1138 PRINT_D(RX_DBG, "rxq entery Size= %d - Address = %p\n", rqe->buffer_size, rqe->buffer);
Glen Leed06f3622015-10-27 18:27:59 +09001139 wilc_wlan_rxq_add(wilc, rqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001140 }
1141 } else {
1142#ifndef MEMORY_STATIC
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001143 kfree(buffer);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001144#endif
1145 }
1146 }
Glen Lee39ce4d32015-10-27 18:27:42 +09001147 wilc_wlan_handle_rxq(wilc);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001148}
1149
Glen Lee50b929e2015-10-27 18:27:40 +09001150void wilc_handle_isr(void *wilc)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001151{
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001152 u32 int_status;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001153
1154 acquire_bus(ACQUIRE_AND_WAKEUP);
1155 g_wlan.hif_func.hif_read_int(&int_status);
1156
Alison Schofield39823a52015-10-08 21:18:03 -07001157 if (int_status & PLL_INT_EXT)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001158 wilc_pllupdate_isr_ext(int_status);
Alison Schofield39823a52015-10-08 21:18:03 -07001159
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001160 if (int_status & DATA_INT_EXT) {
Glen Lee3bcd45b2015-10-27 18:27:41 +09001161 wilc_wlan_handle_isr_ext(wilc, int_status);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001162 #ifndef WILC_OPTIMIZE_SLEEP_INT
Leo Kimb7d1e182015-11-06 11:12:30 +09001163 chip_ps_state = CHIP_WAKEDUP;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001164 #endif
1165 }
Alison Schofield39823a52015-10-08 21:18:03 -07001166 if (int_status & SLEEP_INT_EXT)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001167 wilc_sleeptimer_isr_ext(int_status);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001168
1169 if (!(int_status & (ALL_INT_EXT))) {
1170#ifdef WILC_SDIO
1171 PRINT_D(TX_DBG, ">> UNKNOWN_INTERRUPT - 0x%08x\n", int_status);
1172#endif
1173 wilc_unknown_isr_ext();
1174 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001175 release_bus(RELEASE_ALLOW_SLEEP);
1176}
1177
Glen Lee63d7ab82015-10-01 16:03:32 +09001178int wilc_wlan_firmware_download(const u8 *buffer, u32 buffer_size)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001179{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +05301180 wilc_wlan_dev_t *p = &g_wlan;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001181 u32 offset;
1182 u32 addr, size, size2, blksz;
Chaehyun Lim51e825f2015-09-15 14:06:14 +09001183 u8 *dma_buffer;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001184 int ret = 0;
1185
Anish Bhattffda2032015-09-29 12:15:49 -07001186 blksz = BIT(12);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001187
Greg Kroah-Hartmanf019b9d2015-09-03 18:50:27 -07001188 dma_buffer = kmalloc(blksz, GFP_KERNEL);
Leo Kima4b17192015-11-06 11:12:31 +09001189 if (!dma_buffer) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001190 ret = -5;
1191 PRINT_ER("Can't allocate buffer for firmware download IO error\n ");
1192 goto _fail_1;
1193 }
1194
1195 PRINT_D(INIT_DBG, "Downloading firmware size = %d ...\n", buffer_size);
Leo Kimac087c82015-11-06 11:12:25 +09001196
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001197 offset = 0;
1198 do {
1199 memcpy(&addr, &buffer[offset], 4);
1200 memcpy(&size, &buffer[offset + 4], 4);
1201#ifdef BIG_ENDIAN
1202 addr = BYTE_SWAP(addr);
1203 size = BYTE_SWAP(size);
1204#endif
1205 acquire_bus(ACQUIRE_ONLY);
1206 offset += 8;
1207 while (((int)size) && (offset < buffer_size)) {
Chandra S Gorentla78174ad2015-08-08 17:41:36 +05301208 if (size <= blksz)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001209 size2 = size;
Chandra S Gorentla78174ad2015-08-08 17:41:36 +05301210 else
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001211 size2 = blksz;
Leo Kimac087c82015-11-06 11:12:25 +09001212
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001213 memcpy(dma_buffer, &buffer[offset], size2);
1214 ret = p->hif_func.hif_block_tx(addr, dma_buffer, size2);
1215 if (!ret)
1216 break;
1217
1218 addr += size2;
1219 offset += size2;
1220 size -= size2;
1221 }
1222 release_bus(RELEASE_ONLY);
1223
1224 if (!ret) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001225 ret = -5;
1226 PRINT_ER("Can't download firmware IO error\n ");
1227 goto _fail_;
1228 }
1229 PRINT_D(INIT_DBG, "Offset = %d\n", offset);
1230 } while (offset < buffer_size);
1231
1232_fail_:
1233
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001234 kfree(dma_buffer);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001235
1236_fail_1:
1237
1238 return (ret < 0) ? ret : 0;
1239}
1240
Glen Leee42563b2015-10-01 16:03:33 +09001241int wilc_wlan_start(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001242{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +05301243 wilc_wlan_dev_t *p = &g_wlan;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001244 u32 reg = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001245 int ret;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001246 u32 chipid;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001247
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001248 if (p->io_func.io_type == HIF_SDIO) {
1249 reg = 0;
Leo Kimac087c82015-11-06 11:12:25 +09001250 reg |= BIT(3);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001251 } else if (p->io_func.io_type == HIF_SPI) {
1252 reg = 1;
1253 }
1254 acquire_bus(ACQUIRE_ONLY);
1255 ret = p->hif_func.hif_write_reg(WILC_VMM_CORE_CFG, reg);
1256 if (!ret) {
1257 wilc_debug(N_ERR, "[wilc start]: fail write reg vmm_core_cfg...\n");
1258 release_bus(RELEASE_ONLY);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001259 ret = -5;
1260 return ret;
1261 }
1262 reg = 0;
1263#ifdef WILC_SDIO_IRQ_GPIO
1264 reg |= WILC_HAVE_SDIO_IRQ_GPIO;
1265#endif
1266
1267#ifdef WILC_DISABLE_PMU
1268#else
1269 reg |= WILC_HAVE_USE_PMU;
1270#endif
1271
1272#ifdef WILC_SLEEP_CLK_SRC_XO
1273 reg |= WILC_HAVE_SLEEP_CLK_SRC_XO;
1274#elif defined WILC_SLEEP_CLK_SRC_RTC
1275 reg |= WILC_HAVE_SLEEP_CLK_SRC_RTC;
1276#endif
1277
1278#ifdef WILC_EXT_PA_INV_TX_RX
1279 reg |= WILC_HAVE_EXT_PA_INV_TX_RX;
1280#endif
1281
1282 reg |= WILC_HAVE_LEGACY_RF_SETTINGS;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001283#ifdef XTAL_24
1284 reg |= WILC_HAVE_XTAL_24;
1285#endif
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001286#ifdef DISABLE_WILC_UART
1287 reg |= WILC_HAVE_DISABLE_WILC_UART;
1288#endif
1289
1290 ret = p->hif_func.hif_write_reg(WILC_GP_REG_1, reg);
1291 if (!ret) {
1292 wilc_debug(N_ERR, "[wilc start]: fail write WILC_GP_REG_1 ...\n");
1293 release_bus(RELEASE_ONLY);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001294 ret = -5;
1295 return ret;
1296 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001297
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001298 p->hif_func.hif_sync_ext(NUM_INT_EXT);
1299
1300 ret = p->hif_func.hif_read_reg(0x1000, &chipid);
1301 if (!ret) {
1302 wilc_debug(N_ERR, "[wilc start]: fail read reg 0x1000 ...\n");
1303 release_bus(RELEASE_ONLY);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001304 ret = -5;
1305 return ret;
1306 }
1307
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001308 p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
Anish Bhattffda2032015-09-29 12:15:49 -07001309 if ((reg & BIT(10)) == BIT(10)) {
1310 reg &= ~BIT(10);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001311 p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
1312 p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1313 }
1314
Anish Bhattffda2032015-09-29 12:15:49 -07001315 reg |= BIT(10);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001316 ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
1317 p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1318 release_bus(RELEASE_ONLY);
1319
1320 return (ret < 0) ? ret : 0;
1321}
1322
1323void wilc_wlan_global_reset(void)
1324{
1325
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +05301326 wilc_wlan_dev_t *p = &g_wlan;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +09001327
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001328 acquire_bus(ACQUIRE_AND_WAKEUP);
1329 p->hif_func.hif_write_reg(WILC_GLB_RESET_0, 0x0);
1330 release_bus(RELEASE_ONLY);
1331}
Glen Lee8cec7412015-10-01 16:03:34 +09001332int wilc_wlan_stop(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001333{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +05301334 wilc_wlan_dev_t *p = &g_wlan;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001335 u32 reg = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001336 int ret;
Chaehyun Lim51e825f2015-09-15 14:06:14 +09001337 u8 timeout = 10;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001338 acquire_bus(ACQUIRE_AND_WAKEUP);
1339
1340 ret = p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1341 if (!ret) {
1342 PRINT_ER("Error while reading reg\n");
1343 release_bus(RELEASE_ALLOW_SLEEP);
1344 return ret;
1345 }
1346
Anish Bhattffda2032015-09-29 12:15:49 -07001347 reg &= ~BIT(10);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001348 ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
1349 if (!ret) {
1350 PRINT_ER("Error while writing reg\n");
1351 release_bus(RELEASE_ALLOW_SLEEP);
1352 return ret;
1353 }
1354
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001355 do {
1356 ret = p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1357 if (!ret) {
1358 PRINT_ER("Error while reading reg\n");
1359 release_bus(RELEASE_ALLOW_SLEEP);
1360 return ret;
1361 }
1362 PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n", reg, timeout);
Leo Kimac087c82015-11-06 11:12:25 +09001363
Anish Bhattffda2032015-09-29 12:15:49 -07001364 if ((reg & BIT(10))) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001365 PRINT_D(GENERIC_DBG, "Bit 10 not reset : Retry %d\n", timeout);
Anish Bhattffda2032015-09-29 12:15:49 -07001366 reg &= ~BIT(10);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001367 ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
1368 timeout--;
1369 } else {
1370 PRINT_D(GENERIC_DBG, "Bit 10 reset after : Retry %d\n", timeout);
1371 ret = p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1372 if (!ret) {
1373 PRINT_ER("Error while reading reg\n");
1374 release_bus(RELEASE_ALLOW_SLEEP);
1375 return ret;
1376 }
1377 PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n", reg, timeout);
1378 break;
1379 }
1380
1381 } while (timeout);
Anish Bhattffda2032015-09-29 12:15:49 -07001382 reg = (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(8) | BIT(9) | BIT(26) |
1383 BIT(29) | BIT(30) | BIT(31));
Anish Bhatt65ead4e2015-09-29 12:15:48 -07001384
1385 p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
Anish Bhattffda2032015-09-29 12:15:49 -07001386 reg = (u32)~BIT(10);
Anish Bhatt65ead4e2015-09-29 12:15:48 -07001387
1388 ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001389
1390 release_bus(RELEASE_ALLOW_SLEEP);
1391
1392 return ret;
1393}
1394
Glen Lee2de7cbe2015-10-27 18:27:54 +09001395void wilc_wlan_cleanup(struct net_device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001396{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +05301397 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001398 struct txq_entry_t *tqe;
1399 struct rxq_entry_t *rqe;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001400 u32 reg = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001401 int ret;
Glen Leedb387632015-10-27 18:27:55 +09001402 perInterface_wlan_t *nic;
1403 struct wilc *wilc;
1404
1405 nic = netdev_priv(dev);
1406 wilc = nic->wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001407
1408 p->quit = 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001409 do {
Glen Lee718fc2c2015-10-29 12:18:43 +09001410 tqe = wilc_wlan_txq_remove_from_head(dev);
Leo Kima4b17192015-11-06 11:12:31 +09001411 if (!tqe)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001412 break;
1413 if (tqe->tx_complete_func)
1414 tqe->tx_complete_func(tqe->priv, 0);
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001415 kfree(tqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001416 } while (1);
1417
1418 do {
Glen Leedb387632015-10-27 18:27:55 +09001419 rqe = wilc_wlan_rxq_remove(wilc);
Leo Kima4b17192015-11-06 11:12:31 +09001420 if (!rqe)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001421 break;
Javier Martinez Canillas6a272242015-09-22 15:24:50 +02001422#ifndef MEMORY_STATIC
1423 kfree(rqe->buffer);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001424#endif
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001425 kfree(rqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001426 } while (1);
1427
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001428 #ifdef MEMORY_STATIC
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001429 kfree(p->rx_buffer);
1430 p->rx_buffer = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001431 #endif
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001432 kfree(p->tx_buffer);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001433
1434 acquire_bus(ACQUIRE_AND_WAKEUP);
1435
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001436 ret = p->hif_func.hif_read_reg(WILC_GP_REG_0, &reg);
1437 if (!ret) {
1438 PRINT_ER("Error while reading reg\n");
1439 release_bus(RELEASE_ALLOW_SLEEP);
1440 }
1441 PRINT_ER("Writing ABORT reg\n");
1442 ret = p->hif_func.hif_write_reg(WILC_GP_REG_0, (reg | ABORT_INT));
1443 if (!ret) {
1444 PRINT_ER("Error while writing reg\n");
1445 release_bus(RELEASE_ALLOW_SLEEP);
1446 }
1447 release_bus(RELEASE_ALLOW_SLEEP);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001448 p->hif_func.hif_deinit(NULL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001449}
1450
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001451static int wilc_wlan_cfg_commit(int type, u32 drvHandler)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001452{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +05301453 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001454 wilc_cfg_frame_t *cfg = &p->cfg_frame;
1455 int total_len = p->cfg_frame_offset + 4 + DRIVER_HANDLER_SIZE;
1456 int seq_no = p->cfg_seq_no % 256;
Chaehyun Lim4e4467f2015-06-11 14:35:55 +09001457 int driver_handler = (u32)drvHandler;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001458
Leo Kimac087c82015-11-06 11:12:25 +09001459 if (type == WILC_CFG_SET) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001460 cfg->wid_header[0] = 'W';
Leo Kimac087c82015-11-06 11:12:25 +09001461 } else {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001462 cfg->wid_header[0] = 'Q';
1463 }
Leo Kimac087c82015-11-06 11:12:25 +09001464 cfg->wid_header[1] = seq_no;
Chaehyun Lim51e825f2015-09-15 14:06:14 +09001465 cfg->wid_header[2] = (u8)total_len;
1466 cfg->wid_header[3] = (u8)(total_len >> 8);
1467 cfg->wid_header[4] = (u8)driver_handler;
1468 cfg->wid_header[5] = (u8)(driver_handler >> 8);
1469 cfg->wid_header[6] = (u8)(driver_handler >> 16);
1470 cfg->wid_header[7] = (u8)(driver_handler >> 24);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001471 p->cfg_seq_no = seq_no;
1472
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001473 if (!wilc_wlan_txq_add_cfg_pkt(&cfg->wid_header[0], total_len))
1474 return -1;
1475
1476 return 0;
1477}
1478
Glen Lee1028e5a2015-10-01 16:03:40 +09001479int wilc_wlan_cfg_set(int start, u32 wid, u8 *buffer, u32 buffer_size,
1480 int commit, u32 drvHandler)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001481{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +05301482 wilc_wlan_dev_t *p = &g_wlan;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001483 u32 offset;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001484 int ret_size;
1485
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001486 if (p->cfg_frame_in_use)
1487 return 0;
1488
1489 if (start)
1490 p->cfg_frame_offset = 0;
1491
1492 offset = p->cfg_frame_offset;
Glen Lee17e8f162015-10-02 14:22:07 +09001493 ret_size = wilc_wlan_cfg_set_wid(p->cfg_frame.frame, offset, (u16)wid,
1494 buffer, buffer_size);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001495 offset += ret_size;
1496 p->cfg_frame_offset = offset;
1497
1498 if (commit) {
1499 PRINT_D(TX_DBG, "[WILC]PACKET Commit with sequence number %d\n", p->cfg_seq_no);
1500 PRINT_D(RX_DBG, "Processing cfg_set()\n");
1501 p->cfg_frame_in_use = 1;
1502
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001503 if (wilc_wlan_cfg_commit(WILC_CFG_SET, drvHandler))
Chaehyun Lim5af6b852015-09-17 16:48:48 +09001504 ret_size = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001505
Glen Leeb002e202015-09-24 18:15:05 +09001506 if (linux_wlan_lock_timeout(&g_linux_wlan->cfg_event,
1507 CFG_PKTS_TIMEOUT)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001508 PRINT_D(TX_DBG, "Set Timed Out\n");
1509 ret_size = 0;
1510 }
1511 p->cfg_frame_in_use = 0;
1512 p->cfg_frame_offset = 0;
1513 p->cfg_seq_no += 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001514 }
1515
1516 return ret_size;
1517}
Leo Kim2d6973e2015-11-06 11:12:28 +09001518
Glen Lee07056a82015-10-01 16:03:41 +09001519int wilc_wlan_cfg_get(int start, u32 wid, int commit, u32 drvHandler)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001520{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +05301521 wilc_wlan_dev_t *p = &g_wlan;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001522 u32 offset;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001523 int ret_size;
1524
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001525 if (p->cfg_frame_in_use)
1526 return 0;
1527
1528 if (start)
1529 p->cfg_frame_offset = 0;
1530
1531 offset = p->cfg_frame_offset;
Glen Leeec1b86b2015-10-02 14:22:08 +09001532 ret_size = wilc_wlan_cfg_get_wid(p->cfg_frame.frame, offset, (u16)wid);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001533 offset += ret_size;
1534 p->cfg_frame_offset = offset;
1535
1536 if (commit) {
1537 p->cfg_frame_in_use = 1;
1538
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001539 if (wilc_wlan_cfg_commit(WILC_CFG_QUERY, drvHandler))
Chaehyun Lim5af6b852015-09-17 16:48:48 +09001540 ret_size = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001541
Glen Leeb002e202015-09-24 18:15:05 +09001542 if (linux_wlan_lock_timeout(&g_linux_wlan->cfg_event,
1543 CFG_PKTS_TIMEOUT)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001544 PRINT_D(TX_DBG, "Get Timed Out\n");
1545 ret_size = 0;
1546 }
1547 PRINT_D(GENERIC_DBG, "[WILC]Get Response received\n");
1548 p->cfg_frame_in_use = 0;
1549 p->cfg_frame_offset = 0;
1550 p->cfg_seq_no += 1;
1551 }
1552
1553 return ret_size;
1554}
1555
Glen Lee894de36b2015-10-01 16:03:42 +09001556int wilc_wlan_cfg_get_val(u32 wid, u8 *buffer, u32 buffer_size)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001557{
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001558 int ret;
1559
Glen Lee355cca22015-10-02 14:22:09 +09001560 ret = wilc_wlan_cfg_get_wid_value((u16)wid, buffer, buffer_size);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001561
1562 return ret;
1563}
1564
1565void wilc_bus_set_max_speed(void)
1566{
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001567 g_wlan.hif_func.hif_set_max_bus_speed();
1568}
1569
1570void wilc_bus_set_default_speed(void)
1571{
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001572 g_wlan.hif_func.hif_set_default_bus_speed();
1573}
Leo Kim2d6973e2015-11-06 11:12:28 +09001574
Glen Leeae6f7722015-10-29 12:18:48 +09001575u32 init_chip(struct net_device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001576{
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001577 u32 chipid;
1578 u32 reg, ret = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001579
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001580 acquire_bus(ACQUIRE_ONLY);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001581
Dean Lee72ed4dc2015-06-12 14:11:44 +09001582 chipid = wilc_get_chipid(true);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001583
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001584 if ((chipid & 0xfff) != 0xa0) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001585 ret = g_wlan.hif_func.hif_read_reg(0x1118, &reg);
1586 if (!ret) {
1587 wilc_debug(N_ERR, "[wilc start]: fail read reg 0x1118 ...\n");
1588 return ret;
1589 }
Anish Bhattffda2032015-09-29 12:15:49 -07001590 reg |= BIT(0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001591 ret = g_wlan.hif_func.hif_write_reg(0x1118, reg);
1592 if (!ret) {
1593 wilc_debug(N_ERR, "[wilc start]: fail write reg 0x1118 ...\n");
1594 return ret;
1595 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001596 ret = g_wlan.hif_func.hif_write_reg(0xc0000, 0x71);
1597 if (!ret) {
1598 wilc_debug(N_ERR, "[wilc start]: fail write reg 0xc0000 ...\n");
1599 return ret;
1600 }
1601 }
1602
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001603 release_bus(RELEASE_ONLY);
1604
1605 return ret;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001606}
1607
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001608u32 wilc_get_chipid(u8 update)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001609{
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001610 static u32 chipid;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001611 u32 tempchipid = 0;
1612 u32 rfrevid;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001613
1614 if (chipid == 0 || update != 0) {
1615 g_wlan.hif_func.hif_read_reg(0x1000, &tempchipid);
1616 g_wlan.hif_func.hif_read_reg(0x13f4, &rfrevid);
1617 if (!ISWILC1000(tempchipid)) {
1618 chipid = 0;
1619 goto _fail_;
1620 }
1621 if (tempchipid == 0x1002a0) {
Leo Kimac087c82015-11-06 11:12:25 +09001622 if (rfrevid == 0x1) {
1623 } else {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001624 tempchipid = 0x1002a1;
1625 }
1626 } else if (tempchipid == 0x1002b0) {
Leo Kimac087c82015-11-06 11:12:25 +09001627 if (rfrevid == 3) {
1628 } else if (rfrevid == 4) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001629 tempchipid = 0x1002b1;
Leo Kimac087c82015-11-06 11:12:25 +09001630 } else {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001631 tempchipid = 0x1002b2;
1632 }
1633 } else {
1634 }
1635
1636 chipid = tempchipid;
1637 }
1638_fail_:
1639 return chipid;
1640}
1641
Glen Lee47a466f2015-10-29 12:18:47 +09001642int wilc_wlan_init(struct net_device *dev, wilc_wlan_inp_t *inp)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001643{
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001644 int ret = 0;
1645
1646 PRINT_D(INIT_DBG, "Initializing WILC_Wlan ...\n");
1647
1648 memset((void *)&g_wlan, 0, sizeof(wilc_wlan_dev_t));
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001649 memcpy((void *)&g_wlan.io_func, (void *)&inp->io_func, sizeof(wilc_wlan_io_func_t));
Leo Kimac087c82015-11-06 11:12:25 +09001650
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001651 if ((inp->io_func.io_type & 0x1) == HIF_SDIO) {
1652 if (!hif_sdio.hif_init(inp, wilc_debug)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001653 ret = -5;
1654 goto _fail_;
1655 }
1656 memcpy((void *)&g_wlan.hif_func, &hif_sdio, sizeof(wilc_hif_func_t));
1657 } else {
1658 if ((inp->io_func.io_type & 0x1) == HIF_SPI) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001659 if (!hif_spi.hif_init(inp, wilc_debug)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001660 ret = -5;
1661 goto _fail_;
1662 }
1663 memcpy((void *)&g_wlan.hif_func, &hif_spi, sizeof(wilc_hif_func_t));
1664 } else {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001665 ret = -5;
1666 goto _fail_;
1667 }
1668 }
1669
Glen Lee814bc362015-10-02 14:22:11 +09001670 if (!wilc_wlan_cfg_init(wilc_debug)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001671 ret = -105;
1672 goto _fail_;
1673 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001674
Leo Kima4b17192015-11-06 11:12:31 +09001675 if (!g_wlan.tx_buffer)
Glen Lee7015b5d2015-09-24 18:15:02 +09001676 g_wlan.tx_buffer = kmalloc(LINUX_TX_SIZE, GFP_KERNEL);
Arnd Bergmann7a8fd842015-06-01 21:06:45 +02001677 PRINT_D(TX_DBG, "g_wlan.tx_buffer = %p\n", g_wlan.tx_buffer);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001678
Leo Kima4b17192015-11-06 11:12:31 +09001679 if (!g_wlan.tx_buffer) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001680 ret = -105;
1681 PRINT_ER("Can't allocate Tx Buffer");
1682 goto _fail_;
1683 }
1684
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001685#if defined (MEMORY_STATIC)
Leo Kima4b17192015-11-06 11:12:31 +09001686 if (!g_wlan.rx_buffer)
Glen Lee03eb7262015-09-24 18:15:03 +09001687 g_wlan.rx_buffer = kmalloc(LINUX_RX_SIZE, GFP_KERNEL);
Arnd Bergmann7a8fd842015-06-01 21:06:45 +02001688 PRINT_D(TX_DBG, "g_wlan.rx_buffer =%p\n", g_wlan.rx_buffer);
Leo Kima4b17192015-11-06 11:12:31 +09001689 if (!g_wlan.rx_buffer) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001690 ret = -105;
1691 PRINT_ER("Can't allocate Rx Buffer");
1692 goto _fail_;
1693 }
1694#endif
1695
Glen Leeae6f7722015-10-29 12:18:48 +09001696 if (!init_chip(dev)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001697 ret = -5;
1698 goto _fail_;
1699 }
1700#ifdef TCP_ACK_FILTER
Leo Kimef06b5f2015-11-06 11:12:44 +09001701 init_tcp_tracking();
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001702#endif
1703
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001704 return 1;
1705
1706_fail_:
1707
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001708 #ifdef MEMORY_STATIC
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001709 kfree(g_wlan.rx_buffer);
1710 g_wlan.rx_buffer = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001711 #endif
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001712 kfree(g_wlan.tx_buffer);
1713 g_wlan.tx_buffer = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001714
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001715 return ret;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001716}
1717
Leo Kim2ad8c472015-11-05 14:36:35 +09001718u16 set_machw_change_vir_if(struct net_device *dev, bool bValue)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001719{
Chaehyun Limd85f5322015-06-11 14:35:54 +09001720 u16 ret;
Chaehyun Lim4e4467f2015-06-11 14:35:55 +09001721 u32 reg;
Glen Lee178c3832015-10-27 18:27:58 +09001722 perInterface_wlan_t *nic;
1723 struct wilc *wilc;
1724
1725 nic = netdev_priv(dev);
1726 wilc = nic->wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001727
Glen Lee178c3832015-10-27 18:27:58 +09001728 mutex_lock(&wilc->hif_cs);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001729 ret = (&g_wlan)->hif_func.hif_read_reg(WILC_CHANGING_VIR_IF, &reg);
Alison Schofield39823a52015-10-08 21:18:03 -07001730 if (!ret)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001731 PRINT_ER("Error while Reading reg WILC_CHANGING_VIR_IF\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001732
Chandra S Gorentla78174ad2015-08-08 17:41:36 +05301733 if (bValue)
Chaehyun Lim50b51da2015-09-16 20:11:26 +09001734 reg |= BIT(31);
Chandra S Gorentla78174ad2015-08-08 17:41:36 +05301735 else
Chaehyun Lim50b51da2015-09-16 20:11:26 +09001736 reg &= ~BIT(31);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001737
1738 ret = (&g_wlan)->hif_func.hif_write_reg(WILC_CHANGING_VIR_IF, reg);
1739
Alison Schofield39823a52015-10-08 21:18:03 -07001740 if (!ret)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001741 PRINT_ER("Error while writing reg WILC_CHANGING_VIR_IF\n");
Alison Schofield39823a52015-10-08 21:18:03 -07001742
Glen Lee178c3832015-10-27 18:27:58 +09001743 mutex_unlock(&wilc->hif_cs);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001744
1745 return ret;
1746}