wifi->esp8089:
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / esp8089 / esp_driver / esp_utils.c
1 /*
2  * Copyright (c) 2009 - 2014 Espressif System.
3  */
4
5 #include "linux/types.h"
6 #include "linux/kernel.h"
7 #include <linux/ieee80211.h>
8 #include <net/mac80211.h>
9 #include <linux/skbuff.h>
10
11 #include <net/tcp.h>
12 #include <linux/ip.h>
13 #include <asm/checksum.h>
14
15 #include "esp_pub.h"
16 #include "esp_utils.h"
17 #include "esp_wmac.h"
18 #include "esp_debug.h"
19
20 /*
21  * Convert IEEE channel number to MHz frequency.
22  */
23 u32 esp_ieee2mhz(u8 chan)
24 {
25         if (chan == 14)
26                 return 2484;
27
28         if (chan < 14)
29                 return 2407 + chan*5;
30         else
31                 return 2512 + ((chan-15)*20);
32         //TODO, add 5GHz
33 }
34 enum {
35         ESP_RATE_1_LONG = 0x0,
36         ESP_RATE_2_LONG = 0x1,
37         ESP_RATE_2_SHORT = 0x5,
38         ESP_RATE_5_SHORT = 0x6,
39         ESP_RATE_5_LONG = 0x2,
40         ESP_RATE_11_SHORT = 0x7,
41         ESP_RATE_11_LONG = 0x3,
42         ESP_RATE_6 = 0xb,
43         ESP_RATE_9 = 0xf,
44         ESP_RATE_12 = 0xa,
45         ESP_RATE_18 = 0xe,
46         ESP_RATE_24 = 0x9,
47         ESP_RATE_36 = 0xd,
48         ESP_RATE_48 = 0x8,
49         ESP_RATE_54 = 0xc,
50         /*        ESP_RATE_MCS0 =0x10,
51                 ESP_RATE_MCS1 =0x11,
52                 ESP_RATE_MCS2 =0x12,
53                 ESP_RATE_MCS3 =0x13,
54                 ESP_RATE_MCS4 =0x14,
55                 ESP_RATE_MCS5 =0x15,
56                 ESP_RATE_MCS6 =0x16,
57                 ESP_RATE_MCS7 =0x17,
58         */
59 };
60
61 static u8 esp_rate_table[20] = {
62         ESP_RATE_1_LONG,
63         ESP_RATE_2_SHORT,
64         ESP_RATE_5_SHORT,
65         ESP_RATE_11_SHORT,
66         ESP_RATE_6,
67         ESP_RATE_9,
68         ESP_RATE_12,
69         ESP_RATE_18,
70         ESP_RATE_24,
71         ESP_RATE_36,
72         ESP_RATE_48,
73         ESP_RATE_54,
74         /*      ESP_RATE_MCS0,
75                 ESP_RATE_MCS1,
76                 ESP_RATE_MCS2,
77                 ESP_RATE_MCS3,
78                 ESP_RATE_MCS4,
79                 ESP_RATE_MCS5,
80                 ESP_RATE_MCS6,
81                 ESP_RATE_MCS7,
82         */
83 };
84
85 s8 esp_wmac_rate2idx(u8 rate)
86 {
87         int i;
88
89         if (rate == ESP_RATE_2_LONG)
90                 return 1;
91         if (rate == ESP_RATE_5_LONG)
92                 return 2;
93         if (rate == ESP_RATE_11_LONG)
94                 return 3;
95         
96         for (i = 0; i < 20; i++) {
97                 if (rate == esp_rate_table[i])
98                         return i;
99         }
100
101         esp_dbg(ESP_DBG_ERROR,"%s unknown rate 0x%02x \n", __func__, rate);
102
103         return 0;
104 }
105
106 bool esp_wmac_rxsec_error(u8 error)
107 {
108         return (error >= RX_SECOV_ERR && error <= RX_SECFIFO_TIMEOUT) || (error >= RX_WEPICV_ERR && error <= RX_WAPIMIC_ERR);
109 }
110
111 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
112 int esp_cipher2alg(int cipher)
113 {
114         if (cipher == WLAN_CIPHER_SUITE_TKIP)
115                 return ALG_TKIP;
116
117         if (cipher == WLAN_CIPHER_SUITE_CCMP)
118                 return ALG_CCMP;
119
120         if (cipher == WLAN_CIPHER_SUITE_WEP40 || cipher == WLAN_CIPHER_SUITE_WEP104)
121                 return ALG_WEP;
122         
123         if (cipher == WLAN_CIPHER_SUITE_AES_CMAC)
124                         return ALG_AES_CMAC;
125
126         //printk("%s wrong cipher 0x%x!\n",__func__,cipher);
127
128         return -1;
129 }
130 #endif /* NEW_KERNEL */
131
132 #ifdef RX_CHECKSUM_TEST
133 atomic_t g_iv_len;
134 void esp_rx_checksum_test(struct sk_buff *skb)
135 {
136         static u32 ip_err = 0;
137         static u32 tcp_err = 0;
138         struct ieee80211_hdr *pwh = (struct ieee80211_hdr *)skb->data;
139         int hdrlen = ieee80211_hdrlen(pwh->frame_control);
140         
141         if(ieee80211_has_protected(pwh->frame_control))
142                 hdrlen += atomic_read(&g_iv_len);
143
144         if (ieee80211_is_data(pwh->frame_control)) {
145                 struct llc_snap_hdr * llc = (struct llc_snap_hdr *)(skb->data + hdrlen);
146                 if (ntohs(llc->eth_type) == ETH_P_IP) {
147                         int llclen = sizeof(struct llc_snap_hdr);
148                         struct iphdr *iph = (struct iphdr *)(skb->data + hdrlen + llclen);
149                         __sum16 csum_bak = iph->check;
150
151                         iph->check = 0;
152                         iph->check = ip_fast_csum(iph, iph->ihl);
153                         if (iph->check != csum_bak) {
154                                 esp_dbg(ESP_DBG_ERROR, "total ip checksum error %d\n", ++ip_err);
155                         }
156                         iph->check = csum_bak;
157
158                         if (iph->protocol == 0x06) {
159                                 struct tcphdr *tcph = (struct tcphdr *)(skb->data + hdrlen + llclen + iph->ihl * 4);
160                                 int datalen = skb->len - (hdrlen + llclen + iph->ihl * 4);
161                                 csum_bak = tcph->check;
162
163                                 tcph->check = 0;
164                                 tcph->check = tcp_v4_check(datalen, iph->saddr, iph->daddr, csum_partial((char *)tcph, datalen, 0));
165                                 if (tcph->check != csum_bak)
166                                 {
167                                         esp_dbg(ESP_DBG_ERROR, "total tcp checksum error %d\n", ++tcp_err);
168                                 }
169                                 tcph->check = csum_bak;
170                         }
171         }
172         }
173 }
174
175 #endif
176
177 #ifdef GEN_ERR_CHECKSUM
178
179 void esp_gen_err_checksum(struct sk_buff *skb)
180 {
181         static u32 tx_seq = 0;
182         if ((tx_seq++ % 16) == 0)
183         {
184                 struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
185                 int hdrlen = ieee80211_hdrlen(hdr->frame_control);
186         
187                 if(ieee80211_has_protected(pwh->frame_control))
188                         hdrlen += IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
189
190                 struct llc_snap_hdr * llc = (struct llc_snap_hdr *)(skb->data + hdrlen);
191                 if (ntohs(llc->eth_type) == ETH_P_IP) {
192                         int llclen = sizeof(struct llc_snap_hdr);
193                         struct iphdr *iph = (struct iphdr *)(skb->data + hdrlen + llclen);
194
195                         iph->check = ~iph->check;
196
197                         if (iph->protocol == 0x06) {
198                                 struct tcphdr *tcph = (struct tcphdr *)(skb->data + hdrlen + llclen + iph->ihl * 4);
199                                 tcph->check = ~tcph->check;
200                         }
201                 }
202         }
203 }
204 #endif
205
206 bool esp_is_ip_pkt(struct sk_buff *skb)
207 {
208                 struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
209                 int hdrlen;
210                 struct llc_snap_hdr * llc;
211                 
212                 if (!ieee80211_is_data(hdr->frame_control))
213                         return false;
214                 
215                 hdrlen = ieee80211_hdrlen(hdr->frame_control);
216                 if(ieee80211_has_protected(hdr->frame_control))
217 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27))
218                         hdrlen += IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
219 #else
220                         hdrlen += IEEE80211_SKB_CB(skb)->control.iv_len;
221 #endif
222 #ifdef RX_CHECKSUM_TEST
223                 atomic_set(&g_iv_len, IEEE80211_SKB_CB(skb)->control.hw_key->iv_len);
224 #endif
225                 if(skb->len < hdrlen + sizeof(struct llc_snap_hdr))
226                         return false;
227                 llc = (struct llc_snap_hdr *)(skb->data + hdrlen);
228                 if (ntohs(llc->eth_type) != ETH_P_IP)
229                         return false;
230                 else
231                         return true;
232 }