blob: 9b1ca170c8dad965500a25e473d7e16df4ba4897 [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
196struct Ack_session_info;
Shraddha Barkeeeb1c062015-08-05 01:29:22 +0530197struct Ack_session_info {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900198 u32 Ack_seq_num;
199 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
205typedef struct {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900206 u32 ack_num;
207 u32 Session_index;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900208 struct txq_entry_t *txqe;
Leo Kimac087c82015-11-06 11:12:25 +0900209} Pending_Acks_info_t;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900210
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900211struct Ack_session_info *Free_head;
212struct Ack_session_info *Alloc_head;
213
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
Shraddha Barkeeeb1c062015-08-05 01:29:22 +0530218struct Ack_session_info Acks_keep_track_info[2 * MAX_TCP_SESSION];
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900219Pending_Acks_info_t Pending_Acks_info[MAX_PENDING_ACKS];
220
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900221u32 PendingAcks_arrBase;
222u32 Opened_TCP_session;
223u32 Pending_Acks;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900224
Chaehyun Limfed16f22015-09-17 16:48:43 +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
Chaehyun Limfed16f22015-09-17 16:48:43 +0900230static inline int add_TCP_track_session(u32 src_prt, u32 dst_prt, u32 seq)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900231{
232 Acks_keep_track_info[Opened_TCP_session].Ack_seq_num = seq;
233 Acks_keep_track_info[Opened_TCP_session].Bigger_Ack_num = 0;
234 Acks_keep_track_info[Opened_TCP_session].src_port = src_prt;
235 Acks_keep_track_info[Opened_TCP_session].dst_port = dst_prt;
236 Opened_TCP_session++;
237
238 PRINT_D(TCP_ENH, "TCP Session %d to Ack %d\n", Opened_TCP_session, seq);
239 return 0;
240}
241
Chaehyun Limfed16f22015-09-17 16:48:43 +0900242static inline int Update_TCP_track_session(u32 index, u32 Ack)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900243{
Alison Schofield39823a52015-10-08 21:18:03 -0700244 if (Ack > Acks_keep_track_info[index].Bigger_Ack_num)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900245 Acks_keep_track_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
Chaehyun Limfed16f22015-09-17 16:48:43 +0900249static inline int add_TCP_Pending_Ack(u32 Ack, u32 Session_index, struct txq_entry_t *txqe)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900250{
Leo Kim821466d2015-11-06 11:12:32 +0900251 total_acks++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900252 if (Pending_Acks < MAX_PENDING_ACKS) {
253 Pending_Acks_info[PendingAcks_arrBase + Pending_Acks].ack_num = Ack;
254 Pending_Acks_info[PendingAcks_arrBase + Pending_Acks].txqe = txqe;
255 Pending_Acks_info[PendingAcks_arrBase + Pending_Acks].Session_index = Session_index;
256 txqe->tcp_PendingAck_index = PendingAcks_arrBase + Pending_Acks;
257 Pending_Acks++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900258 } else {
259
260 }
261 return 0;
262}
Chaehyun Limfed16f22015-09-17 16:48:43 +0900263static inline int remove_TCP_related(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900264{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530265 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900266 unsigned long flags;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900267
Glen Lee85e57562015-09-24 18:14:56 +0900268 spin_lock_irqsave(&g_linux_wlan->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900269
Glen Lee85e57562015-09-24 18:14:56 +0900270 spin_unlock_irqrestore(&g_linux_wlan->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900271 return 0;
272}
273
Glen Lee82bb18e2015-10-27 18:28:03 +0900274static inline int tcp_process(struct net_device *dev, struct txq_entry_t *tqe)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900275{
276 int ret;
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900277 u8 *eth_hdr_ptr;
278 u8 *buffer = tqe->buffer;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900279 unsigned short h_proto;
280 int i;
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530281 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900282 unsigned long flags;
Glen Lee82bb18e2015-10-27 18:28:03 +0900283 perInterface_wlan_t *nic;
284 struct wilc *wilc;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900285
Glen Lee82bb18e2015-10-27 18:28:03 +0900286 nic = netdev_priv(dev);
287 wilc = nic->wilc;
288
289 spin_lock_irqsave(&wilc->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900290
291 eth_hdr_ptr = &buffer[0];
292 h_proto = ntohs(*((unsigned short *)&eth_hdr_ptr[12]));
Leo Kimac087c82015-11-06 11:12:25 +0900293 if (h_proto == 0x0800) {
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900294 u8 *ip_hdr_ptr;
295 u8 protocol;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900296
297 ip_hdr_ptr = &buffer[ETHERNET_HDR_LEN];
298 protocol = ip_hdr_ptr[9];
299
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900300 if (protocol == 0x06) {
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900301 u8 *tcp_hdr_ptr;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900302 u32 IHL, Total_Length, Data_offset;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900303
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900304 tcp_hdr_ptr = &ip_hdr_ptr[IP_HDR_LEN];
305 IHL = (ip_hdr_ptr[0] & 0xf) << 2;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900306 Total_Length = (((u32)ip_hdr_ptr[2]) << 8) + ((u32)ip_hdr_ptr[3]);
307 Data_offset = (((u32)tcp_hdr_ptr[12] & 0xf0) >> 2);
Leo Kimac087c82015-11-06 11:12:25 +0900308 if (Total_Length == (IHL + Data_offset)) {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900309 u32 seq_no, Ack_no;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900310
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900311 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 +0900312
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900313 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 +0900314
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900315 for (i = 0; i < Opened_TCP_session; i++) {
316 if (Acks_keep_track_info[i].Ack_seq_num == seq_no) {
317 Update_TCP_track_session(i, Ack_no);
318 break;
319 }
320 }
Alison Schofield39823a52015-10-08 21:18:03 -0700321 if (i == Opened_TCP_session)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900322 add_TCP_track_session(0, 0, seq_no);
Alison Schofield39823a52015-10-08 21:18:03 -0700323
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900324 add_TCP_Pending_Ack(Ack_no, i, tqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900325 }
326
327 } else {
328 ret = 0;
329 }
330 } else {
331 ret = 0;
332 }
Glen Lee82bb18e2015-10-27 18:28:03 +0900333 spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900334 return ret;
335}
336
Glen Leec029e992015-10-27 18:27:48 +0900337static int wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900338{
Glen Leec029e992015-10-27 18:27:48 +0900339 perInterface_wlan_t *nic;
340 struct wilc *wilc;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900341 u32 i = 0;
342 u32 Dropped = 0;
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530343 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900344
Glen Leec029e992015-10-27 18:27:48 +0900345 nic = netdev_priv(dev);
346 wilc = nic->wilc;
347
348 spin_lock_irqsave(&wilc->txq_spinlock, p->txq_spinlock_flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900349 for (i = PendingAcks_arrBase; i < (PendingAcks_arrBase + Pending_Acks); i++) {
350 if (Pending_Acks_info[i].ack_num < Acks_keep_track_info[Pending_Acks_info[i].Session_index].Bigger_Ack_num) {
351 struct txq_entry_t *tqe;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900352
Chandra S Gorentla17aacd42015-08-08 17:41:35 +0530353 PRINT_D(TCP_ENH, "DROP ACK: %u\n", Pending_Acks_info[i].ack_num);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900354 tqe = Pending_Acks_info[i].txqe;
355 if (tqe) {
356 wilc_wlan_txq_remove(tqe);
Leo Kimeb59da32015-11-06 11:12:33 +0900357 dropped_acks++;
Leo Kimac087c82015-11-06 11:12:25 +0900358 tqe->status = 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900359 if (tqe->tx_complete_func)
360 tqe->tx_complete_func(tqe->priv, tqe->status);
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -0700361 kfree(tqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900362 Dropped++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900363 }
364 }
365 }
366 Pending_Acks = 0;
367 Opened_TCP_session = 0;
368
Chandra S Gorentla78174ad2015-08-08 17:41:36 +0530369 if (PendingAcks_arrBase == 0)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900370 PendingAcks_arrBase = MAX_TCP_SESSION;
Chandra S Gorentla78174ad2015-08-08 17:41:36 +0530371 else
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900372 PendingAcks_arrBase = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900373
Glen Leec029e992015-10-27 18:27:48 +0900374 spin_unlock_irqrestore(&wilc->txq_spinlock, p->txq_spinlock_flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900375
376 while (Dropped > 0) {
Glen Leec029e992015-10-27 18:27:48 +0900377 linux_wlan_lock_timeout(&wilc->txq_event, 1);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900378 Dropped--;
379 }
380
381 return 1;
382}
383#endif
384
Dean Lee72ed4dc2015-06-12 14:11:44 +0900385bool EnableTCPAckFilter = false;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900386
Dean Lee72ed4dc2015-06-12 14:11:44 +0900387void Enable_TCP_ACK_Filter(bool value)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900388{
389 EnableTCPAckFilter = value;
390}
391
Dean Lee72ed4dc2015-06-12 14:11:44 +0900392bool is_TCP_ACK_Filter_Enabled(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900393{
394 return EnableTCPAckFilter;
395}
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900396
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900397static int wilc_wlan_txq_add_cfg_pkt(u8 *buffer, u32 buffer_size)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900398{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530399 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900400 struct txq_entry_t *tqe;
401
402 PRINT_D(TX_DBG, "Adding config packet ...\n");
403 if (p->quit) {
404 PRINT_D(TX_DBG, "Return due to clear function\n");
Glen Lee6a3b94f2015-09-24 18:14:59 +0900405 up(&g_linux_wlan->cfg_event);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900406 return 0;
407 }
408
Greg Kroah-Hartman47c632d2015-09-03 18:55:43 -0700409 tqe = kmalloc(sizeof(struct txq_entry_t), GFP_ATOMIC);
Leo Kima4b17192015-11-06 11:12:31 +0900410 if (!tqe) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900411 PRINT_ER("Failed to allocate memory\n");
412 return 0;
413 }
414
415 tqe->type = WILC_CFG_PKT;
416 tqe->buffer = buffer;
417 tqe->buffer_size = buffer_size;
418 tqe->tx_complete_func = NULL;
419 tqe->priv = NULL;
420#ifdef TCP_ACK_FILTER
421 tqe->tcp_PendingAck_index = NOT_TCP_ACK;
422#endif
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900423 PRINT_D(TX_DBG, "Adding the config packet at the Queue tail\n");
424
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900425 if (wilc_wlan_txq_add_to_head(tqe))
426 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900427 return 1;
428}
429
Glen Lee691bbd42015-10-27 18:28:02 +0900430int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
431 u32 buffer_size, wilc_tx_complete_func_t func)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900432{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530433 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900434 struct txq_entry_t *tqe;
435
436 if (p->quit)
437 return 0;
438
Greg Kroah-Hartman47c632d2015-09-03 18:55:43 -0700439 tqe = kmalloc(sizeof(struct txq_entry_t), GFP_ATOMIC);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900440
Leo Kima4b17192015-11-06 11:12:31 +0900441 if (!tqe)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900442 return 0;
443 tqe->type = WILC_NET_PKT;
444 tqe->buffer = buffer;
445 tqe->buffer_size = buffer_size;
446 tqe->tx_complete_func = func;
447 tqe->priv = priv;
448
449 PRINT_D(TX_DBG, "Adding mgmt packet at the Queue tail\n");
450#ifdef TCP_ACK_FILTER
451 tqe->tcp_PendingAck_index = NOT_TCP_ACK;
Abdul Hussain5a66bf22015-06-16 09:44:06 +0000452 if (is_TCP_ACK_Filter_Enabled())
Glen Lee82bb18e2015-10-27 18:28:03 +0900453 tcp_process(dev, tqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900454#endif
Glen Lee32f03322015-10-29 12:18:45 +0900455 wilc_wlan_txq_add_to_tail(dev, tqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900456 return p->txq_entries;
457}
Glen Leefcc6ef92015-09-16 18:53:21 +0900458
Glen Lee829c4772015-10-29 12:18:44 +0900459int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer,
460 u32 buffer_size, wilc_tx_complete_func_t func)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900461{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530462 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900463 struct txq_entry_t *tqe;
464
465 if (p->quit)
466 return 0;
467
Greg Kroah-Hartman47c632d2015-09-03 18:55:43 -0700468 tqe = kmalloc(sizeof(struct txq_entry_t), GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900469
Leo Kima4b17192015-11-06 11:12:31 +0900470 if (!tqe)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900471 return 0;
472 tqe->type = WILC_MGMT_PKT;
473 tqe->buffer = buffer;
474 tqe->buffer_size = buffer_size;
475 tqe->tx_complete_func = func;
476 tqe->priv = priv;
477#ifdef TCP_ACK_FILTER
478 tqe->tcp_PendingAck_index = NOT_TCP_ACK;
479#endif
480 PRINT_D(TX_DBG, "Adding Network packet at the Queue tail\n");
Glen Lee32f03322015-10-29 12:18:45 +0900481 wilc_wlan_txq_add_to_tail(dev, tqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900482 return 1;
483}
Glen Leefcc6ef92015-09-16 18:53:21 +0900484
Glen Lee7af05222015-10-29 12:18:41 +0900485static struct txq_entry_t *wilc_wlan_txq_get_first(struct wilc *wilc)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900486{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530487 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900488 struct txq_entry_t *tqe;
489 unsigned long flags;
490
Glen Lee7af05222015-10-29 12:18:41 +0900491 spin_lock_irqsave(&wilc->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900492
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900493 tqe = p->txq_head;
494
Glen Lee7af05222015-10-29 12:18:41 +0900495 spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900496
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900497 return tqe;
498}
499
Glen Lee50a0b3b2015-10-27 18:28:00 +0900500static struct txq_entry_t *wilc_wlan_txq_get_next(struct wilc *wilc,
501 struct txq_entry_t *tqe)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900502{
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900503 unsigned long flags;
Leo Kim8739eeb2015-11-06 11:12:29 +0900504
Glen Lee50a0b3b2015-10-27 18:28:00 +0900505 spin_lock_irqsave(&wilc->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900506
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900507 tqe = tqe->next;
Glen Lee50a0b3b2015-10-27 18:28:00 +0900508 spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900509
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900510 return tqe;
511}
512
Glen Leed06f3622015-10-27 18:27:59 +0900513static int wilc_wlan_rxq_add(struct wilc *wilc, struct rxq_entry_t *rqe)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900514{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530515 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900516
517 if (p->quit)
518 return 0;
519
Glen Leed06f3622015-10-27 18:27:59 +0900520 mutex_lock(&wilc->rxq_cs);
Leo Kima4b17192015-11-06 11:12:31 +0900521 if (!p->rxq_head) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900522 PRINT_D(RX_DBG, "Add to Queue head\n");
523 rqe->next = NULL;
524 p->rxq_head = rqe;
525 p->rxq_tail = rqe;
526 } else {
527 PRINT_D(RX_DBG, "Add to Queue tail\n");
528 p->rxq_tail->next = rqe;
529 rqe->next = NULL;
530 p->rxq_tail = rqe;
531 }
532 p->rxq_entries += 1;
533 PRINT_D(RX_DBG, "Number of queue entries: %d\n", p->rxq_entries);
Glen Leed06f3622015-10-27 18:27:59 +0900534 mutex_unlock(&wilc->rxq_cs);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900535 return p->rxq_entries;
536}
537
Glen Leedb387632015-10-27 18:27:55 +0900538static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900539{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530540 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900541
542 PRINT_D(RX_DBG, "Getting rxQ element\n");
543 if (p->rxq_head) {
544 struct rxq_entry_t *rqe;
545
Glen Leedb387632015-10-27 18:27:55 +0900546 mutex_lock(&wilc->rxq_cs);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900547 rqe = p->rxq_head;
548 p->rxq_head = p->rxq_head->next;
549 p->rxq_entries -= 1;
550 PRINT_D(RX_DBG, "RXQ entries decreased\n");
Glen Leedb387632015-10-27 18:27:55 +0900551 mutex_unlock(&wilc->rxq_cs);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900552 return rqe;
553 }
554 PRINT_D(RX_DBG, "Nothing to get from Q\n");
555 return NULL;
556}
557
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900558#ifdef WILC_OPTIMIZE_SLEEP_INT
559
Chaehyun Lim9af382b2015-09-16 20:11:27 +0900560static inline void chip_allow_sleep(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900561{
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900562 u32 reg = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900563
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900564 g_wlan.hif_func.hif_read_reg(0xf0, &reg);
565
Anish Bhattffda2032015-09-29 12:15:49 -0700566 g_wlan.hif_func.hif_write_reg(0xf0, reg & ~BIT(0));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900567}
568
Chaehyun Lim9af382b2015-09-16 20:11:27 +0900569static inline void chip_wakeup(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900570{
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900571 u32 reg, clk_status_reg, trials = 0;
572 u32 sleep_time;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900573
574 if ((g_wlan.io_func.io_type & 0x1) == HIF_SPI) {
575 do {
576 g_wlan.hif_func.hif_read_reg(1, &reg);
Anish Bhattffda2032015-09-29 12:15:49 -0700577 g_wlan.hif_func.hif_write_reg(1, reg | BIT(1));
Anish Bhattffda2032015-09-29 12:15:49 -0700578 g_wlan.hif_func.hif_write_reg(1, reg & ~BIT(1));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900579
580 do {
Greg Kroah-Hartman80e29c72015-08-14 19:42:23 -0700581 usleep_range(2 * 1000, 2 * 1000);
Alison Schofield39823a52015-10-08 21:18:03 -0700582 if ((wilc_get_chipid(true) == 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900583 wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n");
Alison Schofield39823a52015-10-08 21:18:03 -0700584
Dean Lee72ed4dc2015-06-12 14:11:44 +0900585 } while ((wilc_get_chipid(true) == 0) && ((++trials % 3) == 0));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900586
Dean Lee72ed4dc2015-06-12 14:11:44 +0900587 } while (wilc_get_chipid(true) == 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900588 } else if ((g_wlan.io_func.io_type & 0x1) == HIF_SDIO) {
589 g_wlan.hif_func.hif_read_reg(0xf0, &reg);
590 do {
Anish Bhattffda2032015-09-29 12:15:49 -0700591 g_wlan.hif_func.hif_write_reg(0xf0, reg | BIT(0));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900592 g_wlan.hif_func.hif_read_reg(0xf1, &clk_status_reg);
593
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900594 while (((clk_status_reg & 0x1) == 0) && (((++trials) % 3) == 0)) {
Greg Kroah-Hartman80e29c72015-08-14 19:42:23 -0700595 usleep_range(2 * 1000, 2 * 1000);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900596
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900597 g_wlan.hif_func.hif_read_reg(0xf1, &clk_status_reg);
598
Alison Schofield39823a52015-10-08 21:18:03 -0700599 if ((clk_status_reg & 0x1) == 0)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900600 wilc_debug(N_ERR, "clocks still OFF. Wake up failed\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900601 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900602 if ((clk_status_reg & 0x1) == 0) {
Anish Bhattffda2032015-09-29 12:15:49 -0700603 g_wlan.hif_func.hif_write_reg(0xf0, reg &
604 (~BIT(0)));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900605 }
606 } while ((clk_status_reg & 0x1) == 0);
607 }
608
Leo Kimb7d1e182015-11-06 11:12:30 +0900609 if (chip_ps_state == CHIP_SLEEPING_MANUAL) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900610 g_wlan.hif_func.hif_read_reg(0x1C0C, &reg);
Anish Bhattffda2032015-09-29 12:15:49 -0700611 reg &= ~BIT(0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900612 g_wlan.hif_func.hif_write_reg(0x1C0C, reg);
613
Dean Lee72ed4dc2015-06-12 14:11:44 +0900614 if (wilc_get_chipid(false) >= 0x1002b0) {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900615 u32 val32;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900616
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900617 g_wlan.hif_func.hif_read_reg(0x1e1c, &val32);
Anish Bhattffda2032015-09-29 12:15:49 -0700618 val32 |= BIT(6);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900619 g_wlan.hif_func.hif_write_reg(0x1e1c, val32);
620
621 g_wlan.hif_func.hif_read_reg(0x1e9c, &val32);
Anish Bhattffda2032015-09-29 12:15:49 -0700622 val32 |= BIT(6);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900623 g_wlan.hif_func.hif_write_reg(0x1e9c, val32);
624 }
625 }
Leo Kimb7d1e182015-11-06 11:12:30 +0900626 chip_ps_state = CHIP_WAKEDUP;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900627}
628#else
Chaehyun Lim9af382b2015-09-16 20:11:27 +0900629static inline void chip_wakeup(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900630{
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900631 u32 reg, trials = 0;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900632
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900633 do {
634 if ((g_wlan.io_func.io_type & 0x1) == HIF_SPI) {
635 g_wlan.hif_func.hif_read_reg(1, &reg);
Anish Bhattffda2032015-09-29 12:15:49 -0700636 g_wlan.hif_func.hif_write_reg(1, reg & ~BIT(1));
Anish Bhattffda2032015-09-29 12:15:49 -0700637 g_wlan.hif_func.hif_write_reg(1, reg | BIT(1));
Anish Bhattffda2032015-09-29 12:15:49 -0700638 g_wlan.hif_func.hif_write_reg(1, reg & ~BIT(1));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900639 } else if ((g_wlan.io_func.io_type & 0x1) == HIF_SDIO) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900640 g_wlan.hif_func.hif_read_reg(0xf0, &reg);
Anish Bhattffda2032015-09-29 12:15:49 -0700641 g_wlan.hif_func.hif_write_reg(0xf0, reg & ~BIT(0));
Anish Bhattffda2032015-09-29 12:15:49 -0700642 g_wlan.hif_func.hif_write_reg(0xf0, reg | BIT(0));
Anish Bhattffda2032015-09-29 12:15:49 -0700643 g_wlan.hif_func.hif_write_reg(0xf0, reg & ~BIT(0));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900644 }
645
646 do {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900647 mdelay(3);
648
Alison Schofield39823a52015-10-08 21:18:03 -0700649 if ((wilc_get_chipid(true) == 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900650 wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n");
Alison Schofield39823a52015-10-08 21:18:03 -0700651
Dean Lee72ed4dc2015-06-12 14:11:44 +0900652 } while ((wilc_get_chipid(true) == 0) && ((++trials % 3) == 0));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900653
Dean Lee72ed4dc2015-06-12 14:11:44 +0900654 } while (wilc_get_chipid(true) == 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900655
Leo Kimb7d1e182015-11-06 11:12:30 +0900656 if (chip_ps_state == CHIP_SLEEPING_MANUAL) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900657 g_wlan.hif_func.hif_read_reg(0x1C0C, &reg);
Anish Bhattffda2032015-09-29 12:15:49 -0700658 reg &= ~BIT(0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900659 g_wlan.hif_func.hif_write_reg(0x1C0C, reg);
660
Dean Lee72ed4dc2015-06-12 14:11:44 +0900661 if (wilc_get_chipid(false) >= 0x1002b0) {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900662 u32 val32;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900663
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900664 g_wlan.hif_func.hif_read_reg(0x1e1c, &val32);
Anish Bhattffda2032015-09-29 12:15:49 -0700665 val32 |= BIT(6);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900666 g_wlan.hif_func.hif_write_reg(0x1e1c, val32);
667
668 g_wlan.hif_func.hif_read_reg(0x1e9c, &val32);
Anish Bhattffda2032015-09-29 12:15:49 -0700669 val32 |= BIT(6);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900670 g_wlan.hif_func.hif_write_reg(0x1e9c, val32);
671 }
672 }
Leo Kimb7d1e182015-11-06 11:12:30 +0900673 chip_ps_state = CHIP_WAKEDUP;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900674}
675#endif
Chaehyun Lim4e4467f2015-06-11 14:35:55 +0900676void chip_sleep_manually(u32 u32SleepTime)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900677{
Leo Kimb7d1e182015-11-06 11:12:30 +0900678 if (chip_ps_state != CHIP_WAKEDUP)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900679 return;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900680 acquire_bus(ACQUIRE_ONLY);
681
682#ifdef WILC_OPTIMIZE_SLEEP_INT
683 chip_allow_sleep();
684#endif
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900685 g_wlan.hif_func.hif_write_reg(0x10a8, 1);
686
Leo Kimb7d1e182015-11-06 11:12:30 +0900687 chip_ps_state = CHIP_SLEEPING_MANUAL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900688 release_bus(RELEASE_ONLY);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900689}
690
Glen Leea1332ca2015-10-27 18:27:47 +0900691int wilc_wlan_handle_txq(struct net_device *dev, u32 *pu32TxqCount)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900692{
693 wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
694 int i, entries = 0;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900695 u32 sum;
696 u32 reg;
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900697 u8 *txb = p->tx_buffer;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900698 u32 offset = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900699 int vmm_sz = 0;
700 struct txq_entry_t *tqe;
701 int ret = 0;
702 int counter;
703 int timeout;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900704 u32 vmm_table[WILC_VMM_TBL_SIZE];
Glen Leea1332ca2015-10-27 18:27:47 +0900705 perInterface_wlan_t *nic;
706 struct wilc *wilc;
707
708 nic = netdev_priv(dev);
709 wilc = nic->wilc;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900710
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900711 p->txq_exit = 0;
712 do {
713 if (p->quit)
714 break;
715
Glen Leea1332ca2015-10-27 18:27:47 +0900716 linux_wlan_lock_timeout(&wilc->txq_add_to_head_cs,
Glen Leeb002e202015-09-24 18:15:05 +0900717 CFG_PKTS_TIMEOUT);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900718#ifdef TCP_ACK_FILTER
Glen Leec029e992015-10-27 18:27:48 +0900719 wilc_wlan_txq_filter_dup_tcp_ack(dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900720#endif
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900721 PRINT_D(TX_DBG, "Getting the head of the TxQ\n");
Glen Lee7af05222015-10-29 12:18:41 +0900722 tqe = wilc_wlan_txq_get_first(wilc);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900723 i = 0;
724 sum = 0;
725 do {
Leo Kima4b17192015-11-06 11:12:31 +0900726 if (tqe && (i < (WILC_VMM_TBL_SIZE - 1))) {
Alison Schofield39823a52015-10-08 21:18:03 -0700727 if (tqe->type == WILC_CFG_PKT)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900728 vmm_sz = ETH_CONFIG_PKT_HDR_OFFSET;
Alison Schofield39823a52015-10-08 21:18:03 -0700729
730 else if (tqe->type == WILC_NET_PKT)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900731 vmm_sz = ETH_ETHERNET_HDR_OFFSET;
Alison Schofield39823a52015-10-08 21:18:03 -0700732
733 else
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900734 vmm_sz = HOST_HDR_OFFSET;
Alison Schofield39823a52015-10-08 21:18:03 -0700735
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900736 vmm_sz += tqe->buffer_size;
737 PRINT_D(TX_DBG, "VMM Size before alignment = %d\n", vmm_sz);
Leo Kimac087c82015-11-06 11:12:25 +0900738 if (vmm_sz & 0x3)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900739 vmm_sz = (vmm_sz + 4) & ~0x3;
Leo Kimac087c82015-11-06 11:12:25 +0900740
Alison Schofield39823a52015-10-08 21:18:03 -0700741 if ((sum + vmm_sz) > LINUX_TX_SIZE)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900742 break;
Alison Schofield39823a52015-10-08 21:18:03 -0700743
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900744 PRINT_D(TX_DBG, "VMM Size AFTER alignment = %d\n", vmm_sz);
Leo Kimac087c82015-11-06 11:12:25 +0900745 vmm_table[i] = vmm_sz / 4;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900746 PRINT_D(TX_DBG, "VMMTable entry size = %d\n", vmm_table[i]);
747
748 if (tqe->type == WILC_CFG_PKT) {
Anish Bhattffda2032015-09-29 12:15:49 -0700749 vmm_table[i] |= BIT(10);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900750 PRINT_D(TX_DBG, "VMMTable entry changed for CFG packet = %d\n", vmm_table[i]);
751 }
752#ifdef BIG_ENDIAN
753 vmm_table[i] = BYTE_SWAP(vmm_table[i]);
754#endif
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900755
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900756 i++;
757 sum += vmm_sz;
758 PRINT_D(TX_DBG, "sum = %d\n", sum);
Glen Lee50a0b3b2015-10-27 18:28:00 +0900759 tqe = wilc_wlan_txq_get_next(wilc, tqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900760 } else {
761 break;
762 }
763 } while (1);
764
Leo Kimac087c82015-11-06 11:12:25 +0900765 if (i == 0) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900766 PRINT_D(TX_DBG, "Nothing in TX-Q\n");
767 break;
768 } else {
769 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 +0900770 vmm_table[i] = 0x0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900771 }
772 acquire_bus(ACQUIRE_AND_WAKEUP);
773 counter = 0;
774 do {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900775 ret = p->hif_func.hif_read_reg(WILC_HOST_TX_CTRL, &reg);
776 if (!ret) {
777 wilc_debug(N_ERR, "[wilc txq]: fail can't read reg vmm_tbl_entry..\n");
778 break;
779 }
780
781 if ((reg & 0x1) == 0) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900782 PRINT_D(TX_DBG, "Writing VMM table ... with Size = %d\n", ((i + 1) * 4));
783 break;
784 } else {
785 counter++;
786 if (counter > 200) {
787 counter = 0;
788 PRINT_D(TX_DBG, "Looping in tx ctrl , forcce quit\n");
789 ret = p->hif_func.hif_write_reg(WILC_HOST_TX_CTRL, 0);
790 break;
791 }
Chandra S Gorentla17aacd42015-08-08 17:41:35 +0530792 PRINT_WRN(GENERIC_DBG, "[wilc txq]: warn, vmm table not clear yet, wait...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900793 release_bus(RELEASE_ALLOW_SLEEP);
Greg Kroah-Hartman2b922cb2015-09-04 09:30:51 -0700794 usleep_range(3000, 3000);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900795 acquire_bus(ACQUIRE_AND_WAKEUP);
796 }
797 } while (!p->quit);
798
Alison Schofield39823a52015-10-08 21:18:03 -0700799 if (!ret)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900800 goto _end_;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900801
802 timeout = 200;
803 do {
Chaehyun Limc3ca6372015-09-20 15:51:19 +0900804 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 +0900805 if (!ret) {
806 wilc_debug(N_ERR, "ERR block TX of VMM table.\n");
807 break;
808 }
809
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900810 ret = p->hif_func.hif_write_reg(WILC_HOST_VMM_CTL, 0x2);
811 if (!ret) {
812 wilc_debug(N_ERR, "[wilc txq]: fail can't write reg host_vmm_ctl..\n");
813 break;
814 }
815
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900816 do {
817 ret = p->hif_func.hif_read_reg(WILC_HOST_VMM_CTL, &reg);
818 if (!ret) {
819 wilc_debug(N_ERR, "[wilc txq]: fail can't read reg host_vmm_ctl..\n");
820 break;
821 }
822 if ((reg >> 2) & 0x1) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900823 entries = ((reg >> 3) & 0x3f);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900824 break;
825 } else {
826 release_bus(RELEASE_ALLOW_SLEEP);
Greg Kroah-Hartman2b922cb2015-09-04 09:30:51 -0700827 usleep_range(3000, 3000);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900828 acquire_bus(ACQUIRE_AND_WAKEUP);
829 PRINT_WRN(GENERIC_DBG, "Can't get VMM entery - reg = %2x\n", reg);
830 }
831 } while (--timeout);
832 if (timeout <= 0) {
833 ret = p->hif_func.hif_write_reg(WILC_HOST_VMM_CTL, 0x0);
834 break;
835 }
836
Alison Schofield39823a52015-10-08 21:18:03 -0700837 if (!ret)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900838 break;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900839
840 if (entries == 0) {
Chandra S Gorentla17aacd42015-08-08 17:41:35 +0530841 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 +0900842
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900843 ret = p->hif_func.hif_read_reg(WILC_HOST_TX_CTRL, &reg);
844 if (!ret) {
845 wilc_debug(N_ERR, "[wilc txq]: fail can't read reg WILC_HOST_TX_CTRL..\n");
846 break;
847 }
Anish Bhattffda2032015-09-29 12:15:49 -0700848 reg &= ~BIT(0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900849 ret = p->hif_func.hif_write_reg(WILC_HOST_TX_CTRL, reg);
850 if (!ret) {
851 wilc_debug(N_ERR, "[wilc txq]: fail can't write reg WILC_HOST_TX_CTRL..\n");
852 break;
853 }
854 break;
855 } else {
856 break;
857 }
858 } while (1);
859
Alison Schofield39823a52015-10-08 21:18:03 -0700860 if (!ret)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900861 goto _end_;
Alison Schofield39823a52015-10-08 21:18:03 -0700862
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900863 if (entries == 0) {
864 ret = WILC_TX_ERR_NO_BUF;
865 goto _end_;
866 }
867
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900868 release_bus(RELEASE_ALLOW_SLEEP);
869
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900870 offset = 0;
871 i = 0;
872 do {
Glen Lee718fc2c2015-10-29 12:18:43 +0900873 tqe = wilc_wlan_txq_remove_from_head(dev);
Leo Kima4b17192015-11-06 11:12:31 +0900874 if (tqe && (vmm_table[i] != 0)) {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900875 u32 header, buffer_offset;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900876
877#ifdef BIG_ENDIAN
878 vmm_table[i] = BYTE_SWAP(vmm_table[i]);
879#endif
Leo Kimac087c82015-11-06 11:12:25 +0900880 vmm_sz = (vmm_table[i] & 0x3ff);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900881 vmm_sz *= 4;
882 header = (tqe->type << 31) | (tqe->buffer_size << 15) | vmm_sz;
Chandra S Gorentla78174ad2015-08-08 17:41:36 +0530883 if (tqe->type == WILC_MGMT_PKT)
Anish Bhattffda2032015-09-29 12:15:49 -0700884 header |= BIT(30);
Chandra S Gorentla78174ad2015-08-08 17:41:36 +0530885 else
Anish Bhattffda2032015-09-29 12:15:49 -0700886 header &= ~BIT(30);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900887
888#ifdef BIG_ENDIAN
889 header = BYTE_SWAP(header);
890#endif
891 memcpy(&txb[offset], &header, 4);
892 if (tqe->type == WILC_CFG_PKT) {
893 buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET;
894 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900895 else if (tqe->type == WILC_NET_PKT) {
896 char *pBSSID = ((struct tx_complete_data *)(tqe->priv))->pBssid;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900897
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900898 buffer_offset = ETH_ETHERNET_HDR_OFFSET;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900899 memcpy(&txb[offset + 4], pBSSID, 6);
900 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900901 else {
902 buffer_offset = HOST_HDR_OFFSET;
903 }
904
905 memcpy(&txb[offset + buffer_offset], tqe->buffer, tqe->buffer_size);
906 offset += vmm_sz;
907 i++;
Leo Kimac087c82015-11-06 11:12:25 +0900908 tqe->status = 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900909 if (tqe->tx_complete_func)
910 tqe->tx_complete_func(tqe->priv, tqe->status);
911 #ifdef TCP_ACK_FILTER
Alison Schofield39823a52015-10-08 21:18:03 -0700912 if (tqe->tcp_PendingAck_index != NOT_TCP_ACK)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900913 Pending_Acks_info[tqe->tcp_PendingAck_index].txqe = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900914 #endif
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -0700915 kfree(tqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900916 } else {
917 break;
918 }
919 } while (--entries);
920
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900921 acquire_bus(ACQUIRE_AND_WAKEUP);
922
923 ret = p->hif_func.hif_clear_int_ext(ENABLE_TX_VMM);
924 if (!ret) {
925 wilc_debug(N_ERR, "[wilc txq]: fail can't start tx VMM ...\n");
926 goto _end_;
927 }
928
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900929 ret = p->hif_func.hif_block_tx_ext(0, txb, offset);
930 if (!ret) {
931 wilc_debug(N_ERR, "[wilc txq]: fail can't block tx ext...\n");
932 goto _end_;
933 }
934
935_end_:
936
937 release_bus(RELEASE_ALLOW_SLEEP);
938 if (ret != 1)
939 break;
940 } while (0);
Glen Leea1332ca2015-10-27 18:27:47 +0900941 up(&wilc->txq_add_to_head_cs);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900942
943 p->txq_exit = 1;
944 PRINT_D(TX_DBG, "THREAD: Exiting txq\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900945 *pu32TxqCount = p->txq_entries;
946 return ret;
947}
948
Glen Lee39ce4d32015-10-27 18:27:42 +0900949static void wilc_wlan_handle_rxq(struct wilc *wilc)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900950{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +0530951 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900952 int offset = 0, size, has_packet = 0;
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900953 u8 *buffer;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900954 struct rxq_entry_t *rqe;
955
956 p->rxq_exit = 0;
957
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900958 do {
959 if (p->quit) {
Chandra S Gorentla17aacd42015-08-08 17:41:35 +0530960 PRINT_D(RX_DBG, "exit 1st do-while due to Clean_UP function\n");
Glen Lee39ce4d32015-10-27 18:27:42 +0900961 up(&wilc->cfg_event);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900962 break;
963 }
Glen Leedb387632015-10-27 18:27:55 +0900964 rqe = wilc_wlan_rxq_remove(wilc);
Leo Kima4b17192015-11-06 11:12:31 +0900965 if (!rqe) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900966 PRINT_D(RX_DBG, "nothing in the queue - exit 1st do-while\n");
967 break;
968 }
969 buffer = rqe->buffer;
970 size = rqe->buffer_size;
971 PRINT_D(RX_DBG, "rxQ entery Size = %d - Address = %p\n", size, buffer);
972 offset = 0;
973
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900974 do {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900975 u32 header;
976 u32 pkt_len, pkt_offset, tp_len;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900977 int is_cfg_packet;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900978
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900979 PRINT_D(RX_DBG, "In the 2nd do-while\n");
980 memcpy(&header, &buffer[offset], 4);
981#ifdef BIG_ENDIAN
982 header = BYTE_SWAP(header);
983#endif
984 PRINT_D(RX_DBG, "Header = %04x - Offset = %d\n", header, offset);
985
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900986 is_cfg_packet = (header >> 31) & 0x1;
987 pkt_offset = (header >> 22) & 0x1ff;
988 tp_len = (header >> 11) & 0x7ff;
989 pkt_len = header & 0x7ff;
990
991 if (pkt_len == 0 || tp_len == 0) {
992 wilc_debug(N_RXQ, "[wilc rxq]: data corrupt, packet len or tp_len is 0 [%d][%d]\n", pkt_len, tp_len);
993 break;
994 }
995
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900996 #define IS_MANAGMEMENT 0x100
997 #define IS_MANAGMEMENT_CALLBACK 0x080
998 #define IS_MGMT_STATUS_SUCCES 0x040
999
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001000 if (pkt_offset & IS_MANAGMEMENT) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001001 pkt_offset &= ~(IS_MANAGMEMENT | IS_MANAGMEMENT_CALLBACK | IS_MGMT_STATUS_SUCCES);
1002
Glen Lee11f4b2e2015-10-27 18:27:51 +09001003 WILC_WFI_mgmt_rx(wilc, &buffer[offset + HOST_HDR_OFFSET], pkt_len);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001004 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001005 else
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001006 {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001007 if (!is_cfg_packet) {
Glen Lee63611672015-09-24 18:14:52 +09001008 if (pkt_len > 0) {
Glen Leecb1991a2015-10-27 18:27:56 +09001009 frmw_to_linux(wilc,
1010 &buffer[offset],
Glen Lee63611672015-09-24 18:14:52 +09001011 pkt_len,
1012 pkt_offset);
1013 has_packet = 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001014 }
1015 } else {
1016 wilc_cfg_rsp_t rsp;
1017
Glen Lee30f535a2015-10-02 14:22:10 +09001018 wilc_wlan_cfg_indicate_rx(&buffer[pkt_offset + offset], pkt_len, &rsp);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001019 if (rsp.type == WILC_CFG_RSP) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001020 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 -07001021 if (p->cfg_seq_no == rsp.seq_no)
Glen Lee39ce4d32015-10-27 18:27:42 +09001022 up(&wilc->cfg_event);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001023 } else if (rsp.type == WILC_CFG_RSP_STATUS) {
Glen Lee64f2b712015-10-27 18:27:43 +09001024 linux_wlan_mac_indicate(wilc, WILC_MAC_INDICATE_STATUS);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001025
1026 } else if (rsp.type == WILC_CFG_RSP_SCAN) {
Glen Lee64f2b712015-10-27 18:27:43 +09001027 linux_wlan_mac_indicate(wilc, WILC_MAC_INDICATE_SCAN);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001028 }
1029 }
1030 }
1031 offset += tp_len;
1032 if (offset >= size)
1033 break;
1034 } while (1);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001035#ifndef MEMORY_STATIC
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001036 kfree(buffer);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001037#endif
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001038 kfree(rqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001039
Alison Schofield39823a52015-10-08 21:18:03 -07001040 if (has_packet)
Glen Leec0cadaa2015-09-24 18:14:54 +09001041 linux_wlan_rx_complete();
Alison Schofield39823a52015-10-08 21:18:03 -07001042
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001043 } while (1);
1044
1045 p->rxq_exit = 1;
Chandra S Gorentla17aacd42015-08-08 17:41:35 +05301046 PRINT_D(RX_DBG, "THREAD: Exiting RX thread\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001047}
1048
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001049static void wilc_unknown_isr_ext(void)
1050{
1051 g_wlan.hif_func.hif_clear_int_ext(0);
1052}
Leo Kim2d6973e2015-11-06 11:12:28 +09001053
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001054static void wilc_pllupdate_isr_ext(u32 int_stats)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001055{
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001056 int trials = 10;
1057
1058 g_wlan.hif_func.hif_clear_int_ext(PLL_INT_CLR);
1059
Greg Kroah-Hartmanc2e4c0f2015-09-03 19:09:50 -07001060 mdelay(WILC_PLL_TO);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001061
Dean Lee72ed4dc2015-06-12 14:11:44 +09001062 while (!(ISWILC1000(wilc_get_chipid(true)) && --trials)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001063 PRINT_D(TX_DBG, "PLL update retrying\n");
Greg Kroah-Hartmanc2e4c0f2015-09-03 19:09:50 -07001064 mdelay(1);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001065 }
1066}
1067
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001068static void wilc_sleeptimer_isr_ext(u32 int_stats1)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001069{
1070 g_wlan.hif_func.hif_clear_int_ext(SLEEP_INT_CLR);
1071#ifndef WILC_OPTIMIZE_SLEEP_INT
Leo Kimb7d1e182015-11-06 11:12:30 +09001072 chip_ps_state = CHIP_SLEEPING_AUTO;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001073#endif
1074}
1075
Glen Lee3bcd45b2015-10-27 18:27:41 +09001076static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001077{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +05301078 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001079#ifdef MEMORY_STATIC
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001080 u32 offset = p->rx_buffer_offset;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001081#endif
Chaehyun Lim51e825f2015-09-15 14:06:14 +09001082 u8 *buffer = NULL;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001083 u32 size;
1084 u32 retries = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001085 int ret = 0;
1086 struct rxq_entry_t *rqe;
1087
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001088 size = ((int_status & 0x7fff) << 2);
1089
1090 while (!size && retries < 10) {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001091 u32 time = 0;
Leo Kimac087c82015-11-06 11:12:25 +09001092
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001093 wilc_debug(N_ERR, "RX Size equal zero ... Trying to read it again for %d time\n", time++);
1094 p->hif_func.hif_read_size(&size);
1095 size = ((size & 0x7fff) << 2);
1096 retries++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001097 }
1098
1099 if (size > 0) {
1100#ifdef MEMORY_STATIC
Glen Lee03eb7262015-09-24 18:15:03 +09001101 if (LINUX_RX_SIZE - offset < size)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001102 offset = 0;
1103
1104 if (p->rx_buffer)
1105 buffer = &p->rx_buffer[offset];
1106 else {
1107 wilc_debug(N_ERR, "[wilc isr]: fail Rx Buffer is NULL...drop the packets (%d)\n", size);
1108 goto _end_;
1109 }
1110
1111#else
Greg Kroah-Hartmanf019b9d2015-09-03 18:50:27 -07001112 buffer = kmalloc(size, GFP_KERNEL);
Leo Kima4b17192015-11-06 11:12:31 +09001113 if (!buffer) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001114 wilc_debug(N_ERR, "[wilc isr]: fail alloc host memory...drop the packets (%d)\n", size);
Greg Kroah-Hartman80e29c72015-08-14 19:42:23 -07001115 usleep_range(100 * 1000, 100 * 1000);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001116 goto _end_;
1117 }
1118#endif
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001119 p->hif_func.hif_clear_int_ext(DATA_INT_CLR | ENABLE_RX_VMM);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001120 ret = p->hif_func.hif_block_rx_ext(0, buffer, size);
1121
1122 if (!ret) {
1123 wilc_debug(N_ERR, "[wilc isr]: fail block rx...\n");
1124 goto _end_;
1125 }
1126_end_:
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001127 if (ret) {
1128#ifdef MEMORY_STATIC
1129 offset += size;
1130 p->rx_buffer_offset = offset;
1131#endif
Greg Kroah-Hartmanf019b9d2015-09-03 18:50:27 -07001132 rqe = kmalloc(sizeof(struct rxq_entry_t), GFP_KERNEL);
Leo Kima4b17192015-11-06 11:12:31 +09001133 if (rqe) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001134 rqe->buffer = buffer;
1135 rqe->buffer_size = size;
1136 PRINT_D(RX_DBG, "rxq entery Size= %d - Address = %p\n", rqe->buffer_size, rqe->buffer);
Glen Leed06f3622015-10-27 18:27:59 +09001137 wilc_wlan_rxq_add(wilc, rqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001138 }
1139 } else {
1140#ifndef MEMORY_STATIC
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001141 kfree(buffer);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001142#endif
1143 }
1144 }
Glen Lee39ce4d32015-10-27 18:27:42 +09001145 wilc_wlan_handle_rxq(wilc);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001146}
1147
Glen Lee50b929e2015-10-27 18:27:40 +09001148void wilc_handle_isr(void *wilc)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001149{
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001150 u32 int_status;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001151
1152 acquire_bus(ACQUIRE_AND_WAKEUP);
1153 g_wlan.hif_func.hif_read_int(&int_status);
1154
Alison Schofield39823a52015-10-08 21:18:03 -07001155 if (int_status & PLL_INT_EXT)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001156 wilc_pllupdate_isr_ext(int_status);
Alison Schofield39823a52015-10-08 21:18:03 -07001157
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001158 if (int_status & DATA_INT_EXT) {
Glen Lee3bcd45b2015-10-27 18:27:41 +09001159 wilc_wlan_handle_isr_ext(wilc, int_status);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001160 #ifndef WILC_OPTIMIZE_SLEEP_INT
Leo Kimb7d1e182015-11-06 11:12:30 +09001161 chip_ps_state = CHIP_WAKEDUP;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001162 #endif
1163 }
Alison Schofield39823a52015-10-08 21:18:03 -07001164 if (int_status & SLEEP_INT_EXT)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001165 wilc_sleeptimer_isr_ext(int_status);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001166
1167 if (!(int_status & (ALL_INT_EXT))) {
1168#ifdef WILC_SDIO
1169 PRINT_D(TX_DBG, ">> UNKNOWN_INTERRUPT - 0x%08x\n", int_status);
1170#endif
1171 wilc_unknown_isr_ext();
1172 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001173 release_bus(RELEASE_ALLOW_SLEEP);
1174}
1175
Glen Lee63d7ab82015-10-01 16:03:32 +09001176int wilc_wlan_firmware_download(const u8 *buffer, u32 buffer_size)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001177{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +05301178 wilc_wlan_dev_t *p = &g_wlan;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001179 u32 offset;
1180 u32 addr, size, size2, blksz;
Chaehyun Lim51e825f2015-09-15 14:06:14 +09001181 u8 *dma_buffer;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001182 int ret = 0;
1183
Anish Bhattffda2032015-09-29 12:15:49 -07001184 blksz = BIT(12);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001185
Greg Kroah-Hartmanf019b9d2015-09-03 18:50:27 -07001186 dma_buffer = kmalloc(blksz, GFP_KERNEL);
Leo Kima4b17192015-11-06 11:12:31 +09001187 if (!dma_buffer) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001188 ret = -5;
1189 PRINT_ER("Can't allocate buffer for firmware download IO error\n ");
1190 goto _fail_1;
1191 }
1192
1193 PRINT_D(INIT_DBG, "Downloading firmware size = %d ...\n", buffer_size);
Leo Kimac087c82015-11-06 11:12:25 +09001194
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001195 offset = 0;
1196 do {
1197 memcpy(&addr, &buffer[offset], 4);
1198 memcpy(&size, &buffer[offset + 4], 4);
1199#ifdef BIG_ENDIAN
1200 addr = BYTE_SWAP(addr);
1201 size = BYTE_SWAP(size);
1202#endif
1203 acquire_bus(ACQUIRE_ONLY);
1204 offset += 8;
1205 while (((int)size) && (offset < buffer_size)) {
Chandra S Gorentla78174ad2015-08-08 17:41:36 +05301206 if (size <= blksz)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001207 size2 = size;
Chandra S Gorentla78174ad2015-08-08 17:41:36 +05301208 else
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001209 size2 = blksz;
Leo Kimac087c82015-11-06 11:12:25 +09001210
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001211 memcpy(dma_buffer, &buffer[offset], size2);
1212 ret = p->hif_func.hif_block_tx(addr, dma_buffer, size2);
1213 if (!ret)
1214 break;
1215
1216 addr += size2;
1217 offset += size2;
1218 size -= size2;
1219 }
1220 release_bus(RELEASE_ONLY);
1221
1222 if (!ret) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001223 ret = -5;
1224 PRINT_ER("Can't download firmware IO error\n ");
1225 goto _fail_;
1226 }
1227 PRINT_D(INIT_DBG, "Offset = %d\n", offset);
1228 } while (offset < buffer_size);
1229
1230_fail_:
1231
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001232 kfree(dma_buffer);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001233
1234_fail_1:
1235
1236 return (ret < 0) ? ret : 0;
1237}
1238
Glen Leee42563b2015-10-01 16:03:33 +09001239int wilc_wlan_start(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001240{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +05301241 wilc_wlan_dev_t *p = &g_wlan;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001242 u32 reg = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001243 int ret;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001244 u32 chipid;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001245
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001246 if (p->io_func.io_type == HIF_SDIO) {
1247 reg = 0;
Leo Kimac087c82015-11-06 11:12:25 +09001248 reg |= BIT(3);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001249 } else if (p->io_func.io_type == HIF_SPI) {
1250 reg = 1;
1251 }
1252 acquire_bus(ACQUIRE_ONLY);
1253 ret = p->hif_func.hif_write_reg(WILC_VMM_CORE_CFG, reg);
1254 if (!ret) {
1255 wilc_debug(N_ERR, "[wilc start]: fail write reg vmm_core_cfg...\n");
1256 release_bus(RELEASE_ONLY);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001257 ret = -5;
1258 return ret;
1259 }
1260 reg = 0;
1261#ifdef WILC_SDIO_IRQ_GPIO
1262 reg |= WILC_HAVE_SDIO_IRQ_GPIO;
1263#endif
1264
1265#ifdef WILC_DISABLE_PMU
1266#else
1267 reg |= WILC_HAVE_USE_PMU;
1268#endif
1269
1270#ifdef WILC_SLEEP_CLK_SRC_XO
1271 reg |= WILC_HAVE_SLEEP_CLK_SRC_XO;
1272#elif defined WILC_SLEEP_CLK_SRC_RTC
1273 reg |= WILC_HAVE_SLEEP_CLK_SRC_RTC;
1274#endif
1275
1276#ifdef WILC_EXT_PA_INV_TX_RX
1277 reg |= WILC_HAVE_EXT_PA_INV_TX_RX;
1278#endif
1279
1280 reg |= WILC_HAVE_LEGACY_RF_SETTINGS;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001281#ifdef XTAL_24
1282 reg |= WILC_HAVE_XTAL_24;
1283#endif
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001284#ifdef DISABLE_WILC_UART
1285 reg |= WILC_HAVE_DISABLE_WILC_UART;
1286#endif
1287
1288 ret = p->hif_func.hif_write_reg(WILC_GP_REG_1, reg);
1289 if (!ret) {
1290 wilc_debug(N_ERR, "[wilc start]: fail write WILC_GP_REG_1 ...\n");
1291 release_bus(RELEASE_ONLY);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001292 ret = -5;
1293 return ret;
1294 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001295
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001296 p->hif_func.hif_sync_ext(NUM_INT_EXT);
1297
1298 ret = p->hif_func.hif_read_reg(0x1000, &chipid);
1299 if (!ret) {
1300 wilc_debug(N_ERR, "[wilc start]: fail read reg 0x1000 ...\n");
1301 release_bus(RELEASE_ONLY);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001302 ret = -5;
1303 return ret;
1304 }
1305
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001306 p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
Anish Bhattffda2032015-09-29 12:15:49 -07001307 if ((reg & BIT(10)) == BIT(10)) {
1308 reg &= ~BIT(10);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001309 p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
1310 p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1311 }
1312
Anish Bhattffda2032015-09-29 12:15:49 -07001313 reg |= BIT(10);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001314 ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
1315 p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1316 release_bus(RELEASE_ONLY);
1317
1318 return (ret < 0) ? ret : 0;
1319}
1320
1321void wilc_wlan_global_reset(void)
1322{
1323
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +05301324 wilc_wlan_dev_t *p = &g_wlan;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +09001325
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001326 acquire_bus(ACQUIRE_AND_WAKEUP);
1327 p->hif_func.hif_write_reg(WILC_GLB_RESET_0, 0x0);
1328 release_bus(RELEASE_ONLY);
1329}
Glen Lee8cec7412015-10-01 16:03:34 +09001330int wilc_wlan_stop(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001331{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +05301332 wilc_wlan_dev_t *p = &g_wlan;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001333 u32 reg = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001334 int ret;
Chaehyun Lim51e825f2015-09-15 14:06:14 +09001335 u8 timeout = 10;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001336 acquire_bus(ACQUIRE_AND_WAKEUP);
1337
1338 ret = p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1339 if (!ret) {
1340 PRINT_ER("Error while reading reg\n");
1341 release_bus(RELEASE_ALLOW_SLEEP);
1342 return ret;
1343 }
1344
Anish Bhattffda2032015-09-29 12:15:49 -07001345 reg &= ~BIT(10);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001346 ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
1347 if (!ret) {
1348 PRINT_ER("Error while writing reg\n");
1349 release_bus(RELEASE_ALLOW_SLEEP);
1350 return ret;
1351 }
1352
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001353 do {
1354 ret = p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1355 if (!ret) {
1356 PRINT_ER("Error while reading reg\n");
1357 release_bus(RELEASE_ALLOW_SLEEP);
1358 return ret;
1359 }
1360 PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n", reg, timeout);
Leo Kimac087c82015-11-06 11:12:25 +09001361
Anish Bhattffda2032015-09-29 12:15:49 -07001362 if ((reg & BIT(10))) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001363 PRINT_D(GENERIC_DBG, "Bit 10 not reset : Retry %d\n", timeout);
Anish Bhattffda2032015-09-29 12:15:49 -07001364 reg &= ~BIT(10);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001365 ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
1366 timeout--;
1367 } else {
1368 PRINT_D(GENERIC_DBG, "Bit 10 reset after : Retry %d\n", timeout);
1369 ret = p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1370 if (!ret) {
1371 PRINT_ER("Error while reading reg\n");
1372 release_bus(RELEASE_ALLOW_SLEEP);
1373 return ret;
1374 }
1375 PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n", reg, timeout);
1376 break;
1377 }
1378
1379 } while (timeout);
Anish Bhattffda2032015-09-29 12:15:49 -07001380 reg = (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(8) | BIT(9) | BIT(26) |
1381 BIT(29) | BIT(30) | BIT(31));
Anish Bhatt65ead4e2015-09-29 12:15:48 -07001382
1383 p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
Anish Bhattffda2032015-09-29 12:15:49 -07001384 reg = (u32)~BIT(10);
Anish Bhatt65ead4e2015-09-29 12:15:48 -07001385
1386 ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001387
1388 release_bus(RELEASE_ALLOW_SLEEP);
1389
1390 return ret;
1391}
1392
Glen Lee2de7cbe2015-10-27 18:27:54 +09001393void wilc_wlan_cleanup(struct net_device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001394{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +05301395 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001396 struct txq_entry_t *tqe;
1397 struct rxq_entry_t *rqe;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001398 u32 reg = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001399 int ret;
Glen Leedb387632015-10-27 18:27:55 +09001400 perInterface_wlan_t *nic;
1401 struct wilc *wilc;
1402
1403 nic = netdev_priv(dev);
1404 wilc = nic->wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001405
1406 p->quit = 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001407 do {
Glen Lee718fc2c2015-10-29 12:18:43 +09001408 tqe = wilc_wlan_txq_remove_from_head(dev);
Leo Kima4b17192015-11-06 11:12:31 +09001409 if (!tqe)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001410 break;
1411 if (tqe->tx_complete_func)
1412 tqe->tx_complete_func(tqe->priv, 0);
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001413 kfree(tqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001414 } while (1);
1415
1416 do {
Glen Leedb387632015-10-27 18:27:55 +09001417 rqe = wilc_wlan_rxq_remove(wilc);
Leo Kima4b17192015-11-06 11:12:31 +09001418 if (!rqe)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001419 break;
Javier Martinez Canillas6a272242015-09-22 15:24:50 +02001420#ifndef MEMORY_STATIC
1421 kfree(rqe->buffer);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001422#endif
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001423 kfree(rqe);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001424 } while (1);
1425
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001426 #ifdef MEMORY_STATIC
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001427 kfree(p->rx_buffer);
1428 p->rx_buffer = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001429 #endif
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001430 kfree(p->tx_buffer);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001431
1432 acquire_bus(ACQUIRE_AND_WAKEUP);
1433
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001434 ret = p->hif_func.hif_read_reg(WILC_GP_REG_0, &reg);
1435 if (!ret) {
1436 PRINT_ER("Error while reading reg\n");
1437 release_bus(RELEASE_ALLOW_SLEEP);
1438 }
1439 PRINT_ER("Writing ABORT reg\n");
1440 ret = p->hif_func.hif_write_reg(WILC_GP_REG_0, (reg | ABORT_INT));
1441 if (!ret) {
1442 PRINT_ER("Error while writing reg\n");
1443 release_bus(RELEASE_ALLOW_SLEEP);
1444 }
1445 release_bus(RELEASE_ALLOW_SLEEP);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001446 p->hif_func.hif_deinit(NULL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001447}
1448
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001449static int wilc_wlan_cfg_commit(int type, u32 drvHandler)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001450{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +05301451 wilc_wlan_dev_t *p = &g_wlan;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001452 wilc_cfg_frame_t *cfg = &p->cfg_frame;
1453 int total_len = p->cfg_frame_offset + 4 + DRIVER_HANDLER_SIZE;
1454 int seq_no = p->cfg_seq_no % 256;
Chaehyun Lim4e4467f2015-06-11 14:35:55 +09001455 int driver_handler = (u32)drvHandler;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001456
Leo Kimac087c82015-11-06 11:12:25 +09001457 if (type == WILC_CFG_SET) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001458 cfg->wid_header[0] = 'W';
Leo Kimac087c82015-11-06 11:12:25 +09001459 } else {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001460 cfg->wid_header[0] = 'Q';
1461 }
Leo Kimac087c82015-11-06 11:12:25 +09001462 cfg->wid_header[1] = seq_no;
Chaehyun Lim51e825f2015-09-15 14:06:14 +09001463 cfg->wid_header[2] = (u8)total_len;
1464 cfg->wid_header[3] = (u8)(total_len >> 8);
1465 cfg->wid_header[4] = (u8)driver_handler;
1466 cfg->wid_header[5] = (u8)(driver_handler >> 8);
1467 cfg->wid_header[6] = (u8)(driver_handler >> 16);
1468 cfg->wid_header[7] = (u8)(driver_handler >> 24);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001469 p->cfg_seq_no = seq_no;
1470
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001471 if (!wilc_wlan_txq_add_cfg_pkt(&cfg->wid_header[0], total_len))
1472 return -1;
1473
1474 return 0;
1475}
1476
Glen Lee1028e5a2015-10-01 16:03:40 +09001477int wilc_wlan_cfg_set(int start, u32 wid, u8 *buffer, u32 buffer_size,
1478 int commit, u32 drvHandler)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001479{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +05301480 wilc_wlan_dev_t *p = &g_wlan;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001481 u32 offset;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001482 int ret_size;
1483
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001484 if (p->cfg_frame_in_use)
1485 return 0;
1486
1487 if (start)
1488 p->cfg_frame_offset = 0;
1489
1490 offset = p->cfg_frame_offset;
Glen Lee17e8f162015-10-02 14:22:07 +09001491 ret_size = wilc_wlan_cfg_set_wid(p->cfg_frame.frame, offset, (u16)wid,
1492 buffer, buffer_size);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001493 offset += ret_size;
1494 p->cfg_frame_offset = offset;
1495
1496 if (commit) {
1497 PRINT_D(TX_DBG, "[WILC]PACKET Commit with sequence number %d\n", p->cfg_seq_no);
1498 PRINT_D(RX_DBG, "Processing cfg_set()\n");
1499 p->cfg_frame_in_use = 1;
1500
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001501 if (wilc_wlan_cfg_commit(WILC_CFG_SET, drvHandler))
Chaehyun Lim5af6b852015-09-17 16:48:48 +09001502 ret_size = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001503
Glen Leeb002e202015-09-24 18:15:05 +09001504 if (linux_wlan_lock_timeout(&g_linux_wlan->cfg_event,
1505 CFG_PKTS_TIMEOUT)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001506 PRINT_D(TX_DBG, "Set Timed Out\n");
1507 ret_size = 0;
1508 }
1509 p->cfg_frame_in_use = 0;
1510 p->cfg_frame_offset = 0;
1511 p->cfg_seq_no += 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001512 }
1513
1514 return ret_size;
1515}
Leo Kim2d6973e2015-11-06 11:12:28 +09001516
Glen Lee07056a82015-10-01 16:03:41 +09001517int wilc_wlan_cfg_get(int start, u32 wid, int commit, u32 drvHandler)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001518{
Shivani Bhardwaj7ee82912015-10-13 17:04:48 +05301519 wilc_wlan_dev_t *p = &g_wlan;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001520 u32 offset;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001521 int ret_size;
1522
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001523 if (p->cfg_frame_in_use)
1524 return 0;
1525
1526 if (start)
1527 p->cfg_frame_offset = 0;
1528
1529 offset = p->cfg_frame_offset;
Glen Leeec1b86b2015-10-02 14:22:08 +09001530 ret_size = wilc_wlan_cfg_get_wid(p->cfg_frame.frame, offset, (u16)wid);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001531 offset += ret_size;
1532 p->cfg_frame_offset = offset;
1533
1534 if (commit) {
1535 p->cfg_frame_in_use = 1;
1536
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001537 if (wilc_wlan_cfg_commit(WILC_CFG_QUERY, drvHandler))
Chaehyun Lim5af6b852015-09-17 16:48:48 +09001538 ret_size = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001539
Glen Leeb002e202015-09-24 18:15:05 +09001540 if (linux_wlan_lock_timeout(&g_linux_wlan->cfg_event,
1541 CFG_PKTS_TIMEOUT)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001542 PRINT_D(TX_DBG, "Get Timed Out\n");
1543 ret_size = 0;
1544 }
1545 PRINT_D(GENERIC_DBG, "[WILC]Get Response received\n");
1546 p->cfg_frame_in_use = 0;
1547 p->cfg_frame_offset = 0;
1548 p->cfg_seq_no += 1;
1549 }
1550
1551 return ret_size;
1552}
1553
Glen Lee894de36b2015-10-01 16:03:42 +09001554int wilc_wlan_cfg_get_val(u32 wid, u8 *buffer, u32 buffer_size)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001555{
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001556 int ret;
1557
Glen Lee355cca22015-10-02 14:22:09 +09001558 ret = wilc_wlan_cfg_get_wid_value((u16)wid, buffer, buffer_size);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001559
1560 return ret;
1561}
1562
1563void wilc_bus_set_max_speed(void)
1564{
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001565 g_wlan.hif_func.hif_set_max_bus_speed();
1566}
1567
1568void wilc_bus_set_default_speed(void)
1569{
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001570 g_wlan.hif_func.hif_set_default_bus_speed();
1571}
Leo Kim2d6973e2015-11-06 11:12:28 +09001572
Glen Leeae6f7722015-10-29 12:18:48 +09001573u32 init_chip(struct net_device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001574{
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001575 u32 chipid;
1576 u32 reg, ret = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001577
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001578 acquire_bus(ACQUIRE_ONLY);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001579
Dean Lee72ed4dc2015-06-12 14:11:44 +09001580 chipid = wilc_get_chipid(true);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001581
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001582 if ((chipid & 0xfff) != 0xa0) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001583 ret = g_wlan.hif_func.hif_read_reg(0x1118, &reg);
1584 if (!ret) {
1585 wilc_debug(N_ERR, "[wilc start]: fail read reg 0x1118 ...\n");
1586 return ret;
1587 }
Anish Bhattffda2032015-09-29 12:15:49 -07001588 reg |= BIT(0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001589 ret = g_wlan.hif_func.hif_write_reg(0x1118, reg);
1590 if (!ret) {
1591 wilc_debug(N_ERR, "[wilc start]: fail write reg 0x1118 ...\n");
1592 return ret;
1593 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001594 ret = g_wlan.hif_func.hif_write_reg(0xc0000, 0x71);
1595 if (!ret) {
1596 wilc_debug(N_ERR, "[wilc start]: fail write reg 0xc0000 ...\n");
1597 return ret;
1598 }
1599 }
1600
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001601 release_bus(RELEASE_ONLY);
1602
1603 return ret;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001604}
1605
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001606u32 wilc_get_chipid(u8 update)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001607{
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001608 static u32 chipid;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001609 u32 tempchipid = 0;
1610 u32 rfrevid;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001611
1612 if (chipid == 0 || update != 0) {
1613 g_wlan.hif_func.hif_read_reg(0x1000, &tempchipid);
1614 g_wlan.hif_func.hif_read_reg(0x13f4, &rfrevid);
1615 if (!ISWILC1000(tempchipid)) {
1616 chipid = 0;
1617 goto _fail_;
1618 }
1619 if (tempchipid == 0x1002a0) {
Leo Kimac087c82015-11-06 11:12:25 +09001620 if (rfrevid == 0x1) {
1621 } else {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001622 tempchipid = 0x1002a1;
1623 }
1624 } else if (tempchipid == 0x1002b0) {
Leo Kimac087c82015-11-06 11:12:25 +09001625 if (rfrevid == 3) {
1626 } else if (rfrevid == 4) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001627 tempchipid = 0x1002b1;
Leo Kimac087c82015-11-06 11:12:25 +09001628 } else {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001629 tempchipid = 0x1002b2;
1630 }
1631 } else {
1632 }
1633
1634 chipid = tempchipid;
1635 }
1636_fail_:
1637 return chipid;
1638}
1639
Glen Lee47a466f2015-10-29 12:18:47 +09001640int wilc_wlan_init(struct net_device *dev, wilc_wlan_inp_t *inp)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001641{
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001642 int ret = 0;
1643
1644 PRINT_D(INIT_DBG, "Initializing WILC_Wlan ...\n");
1645
1646 memset((void *)&g_wlan, 0, sizeof(wilc_wlan_dev_t));
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001647 memcpy((void *)&g_wlan.io_func, (void *)&inp->io_func, sizeof(wilc_wlan_io_func_t));
Leo Kimac087c82015-11-06 11:12:25 +09001648
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001649 if ((inp->io_func.io_type & 0x1) == HIF_SDIO) {
1650 if (!hif_sdio.hif_init(inp, wilc_debug)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001651 ret = -5;
1652 goto _fail_;
1653 }
1654 memcpy((void *)&g_wlan.hif_func, &hif_sdio, sizeof(wilc_hif_func_t));
1655 } else {
1656 if ((inp->io_func.io_type & 0x1) == HIF_SPI) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001657 if (!hif_spi.hif_init(inp, wilc_debug)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001658 ret = -5;
1659 goto _fail_;
1660 }
1661 memcpy((void *)&g_wlan.hif_func, &hif_spi, sizeof(wilc_hif_func_t));
1662 } else {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001663 ret = -5;
1664 goto _fail_;
1665 }
1666 }
1667
Glen Lee814bc362015-10-02 14:22:11 +09001668 if (!wilc_wlan_cfg_init(wilc_debug)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001669 ret = -105;
1670 goto _fail_;
1671 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001672
Leo Kima4b17192015-11-06 11:12:31 +09001673 if (!g_wlan.tx_buffer)
Glen Lee7015b5d2015-09-24 18:15:02 +09001674 g_wlan.tx_buffer = kmalloc(LINUX_TX_SIZE, GFP_KERNEL);
Arnd Bergmann7a8fd842015-06-01 21:06:45 +02001675 PRINT_D(TX_DBG, "g_wlan.tx_buffer = %p\n", g_wlan.tx_buffer);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001676
Leo Kima4b17192015-11-06 11:12:31 +09001677 if (!g_wlan.tx_buffer) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001678 ret = -105;
1679 PRINT_ER("Can't allocate Tx Buffer");
1680 goto _fail_;
1681 }
1682
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001683#if defined (MEMORY_STATIC)
Leo Kima4b17192015-11-06 11:12:31 +09001684 if (!g_wlan.rx_buffer)
Glen Lee03eb7262015-09-24 18:15:03 +09001685 g_wlan.rx_buffer = kmalloc(LINUX_RX_SIZE, GFP_KERNEL);
Arnd Bergmann7a8fd842015-06-01 21:06:45 +02001686 PRINT_D(TX_DBG, "g_wlan.rx_buffer =%p\n", g_wlan.rx_buffer);
Leo Kima4b17192015-11-06 11:12:31 +09001687 if (!g_wlan.rx_buffer) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001688 ret = -105;
1689 PRINT_ER("Can't allocate Rx Buffer");
1690 goto _fail_;
1691 }
1692#endif
1693
Glen Leeae6f7722015-10-29 12:18:48 +09001694 if (!init_chip(dev)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001695 ret = -5;
1696 goto _fail_;
1697 }
1698#ifdef TCP_ACK_FILTER
1699 Init_TCP_tracking();
1700#endif
1701
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001702 return 1;
1703
1704_fail_:
1705
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001706 #ifdef MEMORY_STATIC
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001707 kfree(g_wlan.rx_buffer);
1708 g_wlan.rx_buffer = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001709 #endif
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001710 kfree(g_wlan.tx_buffer);
1711 g_wlan.tx_buffer = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001712
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001713 return ret;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001714}
1715
Leo Kim2ad8c472015-11-05 14:36:35 +09001716u16 set_machw_change_vir_if(struct net_device *dev, bool bValue)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001717{
Chaehyun Limd85f5322015-06-11 14:35:54 +09001718 u16 ret;
Chaehyun Lim4e4467f2015-06-11 14:35:55 +09001719 u32 reg;
Glen Lee178c3832015-10-27 18:27:58 +09001720 perInterface_wlan_t *nic;
1721 struct wilc *wilc;
1722
1723 nic = netdev_priv(dev);
1724 wilc = nic->wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001725
Glen Lee178c3832015-10-27 18:27:58 +09001726 mutex_lock(&wilc->hif_cs);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001727 ret = (&g_wlan)->hif_func.hif_read_reg(WILC_CHANGING_VIR_IF, &reg);
Alison Schofield39823a52015-10-08 21:18:03 -07001728 if (!ret)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001729 PRINT_ER("Error while Reading reg WILC_CHANGING_VIR_IF\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001730
Chandra S Gorentla78174ad2015-08-08 17:41:36 +05301731 if (bValue)
Chaehyun Lim50b51da2015-09-16 20:11:26 +09001732 reg |= BIT(31);
Chandra S Gorentla78174ad2015-08-08 17:41:36 +05301733 else
Chaehyun Lim50b51da2015-09-16 20:11:26 +09001734 reg &= ~BIT(31);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001735
1736 ret = (&g_wlan)->hif_func.hif_write_reg(WILC_CHANGING_VIR_IF, reg);
1737
Alison Schofield39823a52015-10-08 21:18:03 -07001738 if (!ret)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001739 PRINT_ER("Error while writing reg WILC_CHANGING_VIR_IF\n");
Alison Schofield39823a52015-10-08 21:18:03 -07001740
Glen Lee178c3832015-10-27 18:27:58 +09001741 mutex_unlock(&wilc->hif_cs);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001742
1743 return ret;
1744}