[Feature][ZXW-237]merge P54U03 version
Only Configure: No
Affected branch: master
Affected module: unknow
Is it affected on both ZXIC and MTK: only ZXIC
Self-test: Yes
Doc Update: No
Change-Id: Id39ef8b992af691eab09c01d4ea26da89e5f4049
diff --git a/ap/os/linux/linux-3.4.x/drivers/cpko/cpko_main.c b/ap/os/linux/linux-3.4.x/drivers/cpko/cpko_main.c
index 5a45243..7a9c22c 100755
--- a/ap/os/linux/linux-3.4.x/drivers/cpko/cpko_main.c
+++ b/ap/os/linux/linux-3.4.x/drivers/cpko/cpko_main.c
@@ -83,30 +83,30 @@
unsigned int __comm_modem_text_start;unsigned int modem_text_end;unsigned int
cpko_data_start;unsigned int cpko_bss_start;unsigned int cpko_text_offset;}
cpko_section_layout;cpko_section_layout cpko_ps_section;int raise(int signo){
-return(0x316+6712-0x1d4e);}extern unsigned int SysEntry(void);static int
+return(0x404+8970-0x270e);}extern unsigned int SysEntry(void);static int
ko_Main_Thread(void*data){struct sched_param param={.sched_priority=
-MAX_USER_RT_PRIO/(0xe6b+2120-0x16b1)-(0x1975+1578-0x1f9c)};int ret=
-(0x3a0+6131-0x1b93);sched_setscheduler(current,SCHED_FIFO,¶m);ret=SysEntry()
-;if(ret!=(0x1419+3950-0x2387))panic("Main_Thread\n");param.sched_priority=
-MAX_USER_RT_PRIO-(0x10ed+82-0x1111);sched_setscheduler(kthreadd_task,SCHED_FIFO,
-¶m);return(0x227+8075-0x21b2);}int zte_modem_ko_start(void){kthread_run(
+MAX_USER_RT_PRIO/(0xafb+4511-0x1c98)-(0x1633+3815-0x2517)};int ret=
+(0x1f43+402-0x20d5);sched_setscheduler(current,SCHED_FIFO,¶m);ret=SysEntry()
+;if(ret!=(0x10b8+3966-0x2036))panic("Main_Thread\n");param.sched_priority=
+MAX_USER_RT_PRIO-(0xfb3+2852-0x1aa9);sched_setscheduler(kthreadd_task,SCHED_FIFO
+,¶m);return(0xaa6+6401-0x23a7);}int zte_modem_ko_start(void){kthread_run(
ko_Main_Thread,NULL,"\x5a\x54\x45\x4d\x61\x69\x6e\x54\x68\x72\x65\x61\x64");
-return(0x890+7748-0x26d4);}static void cpko_sectioninfo_set(void){int ret;struct
- file*fp;mm_segment_t old_fs;loff_t cpko_pos=(0x1570+4436-0x26c4);struct
+return(0x8b9+1955-0x105c);}static void cpko_sectioninfo_set(void){int ret;struct
+ file*fp;mm_segment_t old_fs;loff_t cpko_pos=(0x6ed+5503-0x1c6c);struct
cpps_globalModem globalVar;fp=filp_open(
"\x2f\x6c\x69\x62\x2f\x63\x70\x6b\x6f\x2f\x63\x70\x6b\x6f\x5f\x73\x65\x63\x69\x6e\x66\x6f\x2e\x62\x69\x6e"
-,(0x294+1512-0x87c),(0xe06+3271-0x1acd));if(IS_ERR(fp)||fp==NULL)panic(
+,(0xf28+2571-0x1933),(0xa59+1171-0xeec));if(IS_ERR(fp)||fp==NULL)panic(
"\x6f\x70\x65\x6e\x20\x66\x69\x6c\x65\x20\x65\x72\x72\x6f\x72" "\n");old_fs=
get_fs();set_fs(KERNEL_DS);ret=vfs_read(fp,(char*)&cpko_ps_section,sizeof(
-cpko_section_layout),&cpko_pos);if(ret<=(0x3ca+7257-0x2023))panic(
+cpko_section_layout),&cpko_pos);if(ret<=(0x304+3756-0x11b0))panic(
"\x72\x65\x61\x64\x20\x66\x69\x6c\x65\x20\x65\x72\x72\x6f\x72" "\n");filp_close(
fp,NULL);
#ifdef CONFIG_MODEM_CODE_IS_MAPPING
fp=filp_open(
"\x2f\x6c\x69\x62\x2f\x63\x70\x6b\x6f\x2f\x63\x70\x6b\x6f\x2e\x6b\x6f",
-(0x9ca+4617-0x1bd3),(0x659+7219-0x228c));if(IS_ERR(fp)||fp==NULL)panic(
+(0x1019+4563-0x21ec),(0x1cf2+1837-0x241f));if(IS_ERR(fp)||fp==NULL)panic(
"\x6f\x70\x65\x6e\x20\x66\x69\x6c\x65\x20\x65\x72\x72\x6f\x72" "\n");fp->f_ra.
-ra_pages=(0xac6+6080-0x2286);
+ra_pages=(0x53f+4485-0x16c4);
#endif
if(cpko_ps_section.cpko_text_start){globalVar.cpko_text_start=(unsigned long)
cpko_ps_section.cpko_text_start;globalVar.cpko_rodata_start=(unsigned long)
@@ -126,7 +126,7 @@
vfree_modem_section(globalVar.cpko_text_start,globalVar.modem_text_end);
#endif
}else panic("\x66\x69\x6c\x65\x20\x65\x72\x72\x6f\x72" "\n");}static int
-cpko_start(void){struct cpps_callbacks callback={(0x5b7+4236-0x1643)};callback.
+cpko_start(void){struct cpps_callbacks callback={(0x913+4588-0x1aff)};callback.
zOss_ResetNVFactory=zOss_ResetNVFactory;callback.zOss_NvramFlush=zOss_NvramFlush
;callback.zOss_NvItemWrite=zOss_NvItemWrite;callback.zOss_NvItemWriteFactory=
zOss_NvItemWriteFactory;callback.zOss_NvItemRead=zOss_NvItemRead;callback.
@@ -198,5 +198,5 @@
psm_GetModemSleepFlagStatus=psm_GetModemSleepFlagStatus;
#endif
cpps_callbacks_register(&callback);cpko_sectioninfo_set();zte_modem_ko_start();
-return(0x1997+168-0x1a3f);}static int cpko_stop(void){return(0x636+5784-0x1cce);
+return(0xb43+4520-0x1ceb);}static int cpko_stop(void){return(0x20cd+460-0x2299);
}module_init(cpko_start);module_exit(cpko_stop);
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/psnet/psnet_dev.c b/ap/os/linux/linux-3.4.x/drivers/net/psnet/psnet_dev.c
index 5df877d..09a1b2b 100755
--- a/ap/os/linux/linux-3.4.x/drivers/net/psnet/psnet_dev.c
+++ b/ap/os/linux/linux-3.4.x/drivers/net/psnet/psnet_dev.c
@@ -6,6 +6,14 @@
#include "psnet.h"
#include "psnet_io.h"
#include <mach/iomap.h>
+
+#include <linux/if_addr.h>
+#include <linux/ip.h>
+#include <net/ip.h>
+#include <linux/ipv6.h>
+#include <net/ipv6.h>
+#include <net/protocol.h>
+
#define WATCHDOG_TIMEO (5*HZ)
/* NET NUMBER; channel id; lan/wan*/
@@ -248,6 +256,49 @@
netif_wake_queue(net);
}
+typedef int (*set_xlat_CB)(unsigned char *ip_info, unsigned char *dev_name);
+extern set_xlat_CB g_set_xlat_cb;
+extern struct in6_addr g_plat_subnet;
+extern struct in6_addr g_ipv6_local_subnet;
+extern struct in_addr g_ipv4_local_subnet;
+extern struct net_device *g_xlat_dev;
+int psnet_set_xlat(unsigned char *ip_info, unsigned char *dev_name)
+{
+ unsigned char *buff = ip_info;
+ memcpy(&g_plat_subnet, buff, sizeof(struct in6_addr));
+ buff = buff + sizeof(struct in6_addr);
+ memcpy(&g_ipv6_local_subnet, buff, sizeof(struct in6_addr));
+ buff = buff + sizeof(struct in6_addr);
+ memcpy(&g_ipv4_local_subnet, buff, sizeof(struct in_addr));
+ g_xlat_dev = dev_get_by_name(&init_net, dev_name);
+}
+
+int fill_ip_header(struct iphdr *ip, const struct ipv6hdr *old_header) {
+ if(memcmp(&old_header->saddr, &g_plat_subnet, 12)){
+ return 0;
+ }
+ if(memcmp(&old_header->daddr, &g_ipv6_local_subnet, 16)){
+ return 0;
+ }
+ ip->saddr = old_header->saddr.s6_addr32[3];
+ ip->daddr = g_ipv4_local_subnet.s_addr;
+ ip->ihl = 5;
+ ip->version = 4;
+ ip->tos = 0;
+ ip->tot_len = htons(sizeof(struct iphdr) + ntohs(old_header->payload_len));
+ ip->id = 0;
+ ip->frag_off = htons(IP_DF);
+ ip->ttl = old_header->hop_limit;
+ ip->protocol = old_header->nexthdr;
+ ip->check = 0;
+ return 1;
+}
+extern int fast_nat_check(unsigned char *data);
+extern uint32_t ipv6_pseudo_header_checksum(const struct ipv6hdr *ip6, uint16_t len, uint8_t protocol);
+extern uint32_t ipv4_pseudo_header_checksum(const struct iphdr *ip, uint16_t len);
+extern uint16_t ip_checksum(const void *data, int len);
+extern uint16_t ip_checksum_adjust(uint16_t checksum, uint32_t old_hdr_sum, uint32_t new_hdr_sum);
+
#define PSBUFF_DL_HEADER_OFFSET 64 //80
//extern void * zGetpsbufferHead(void * data);
void psnet_recv_notify(unsigned int index, const void *buffer, unsigned int length)//(T_ZDrvRpMsg_Msg rpmsg)
@@ -267,6 +318,41 @@
psData.pbuf_head = buffer - PSBUFF_DL_HEADER_OFFSET;
#endif
psData.datalen = length;
+
+ unsigned char header[40] = {0};
+ if(unlikely(g_xlat_dev) && g_xlat_dev == dev->net && ((*(uint8_t *)psData.pbuf_data)&0xf0) == 0x60 && (g_xlat_dev->flags & IFF_UP)){
+ struct iphdr *ip_h = header;
+ struct ipv6hdr *ip6_h = (struct ipv6hdr *)psData.pbuf_data;
+ memcpy(header + sizeof(struct iphdr), psData.pbuf_data + sizeof(struct ipv6hdr), 4);
+ if(fill_ip_header(ip_h, ip6_h) && fast_nat_check(ip_h)){//
+ uint32_t old_sum, new_sum;
+ uint16_t checksum, len_left;
+ uint8_t protocol = ip6_h->nexthdr;
+
+ len_left = ntohs(ip6_h->payload_len);
+ old_sum = ipv6_pseudo_header_checksum(psData.pbuf_data, len_left, protocol);
+ new_sum = ipv4_pseudo_header_checksum(ip_h, len_left);
+ ip_h->check = ip_checksum(ip_h, sizeof(struct iphdr));
+ if (protocol == IPPROTO_TCP) {
+ struct tcphdr *tcp_targ = (struct tcphdr *)(psData.pbuf_data + sizeof(struct ipv6hdr));
+ checksum = ip_checksum_adjust(tcp_targ->check, old_sum, new_sum);
+ tcp_targ->check = checksum;
+ psData.pbuf_data = psData.pbuf_data + sizeof(struct ipv6hdr) - sizeof(struct iphdr);
+ memcpy(psData.pbuf_data, ip_h, sizeof(struct iphdr));
+ psData.datalen = psData.datalen - sizeof(struct ipv6hdr) + sizeof(struct iphdr);
+ }else if (protocol == IPPROTO_UDP) {
+ struct udphdr *udp_targ = (struct udphdr *)(psData.pbuf_data + sizeof(struct ipv6hdr));
+ if(udp_targ->check){
+ checksum = ip_checksum_adjust(udp_targ->check, old_sum, new_sum);
+ udp_targ->check = checksum;
+ }
+ psData.pbuf_data = psData.pbuf_data + sizeof(struct ipv6hdr) - sizeof(struct iphdr);
+ memcpy(psData.pbuf_data, ip_h, sizeof(struct iphdr));
+ psData.datalen = psData.datalen - sizeof(struct ipv6hdr) + sizeof(struct iphdr);
+ }
+ }
+ }
+
skb = skb_build_psbuf(&psData);
if (!skb)
@@ -369,7 +455,7 @@
int err;
struct psnet *dev;
struct net_device *net;
-
+ g_set_xlat_cb = psnet_set_xlat;
dbg("ddr_ap_net_lan_init.\n");
err = -ENOMEM;
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/tun.c b/ap/os/linux/linux-3.4.x/drivers/net/tun.c
old mode 100644
new mode 100755
index 8e8b74e..3309fc9
--- a/ap/os/linux/linux-3.4.x/drivers/net/tun.c
+++ b/ap/os/linux/linux-3.4.x/drivers/net/tun.c
@@ -603,7 +603,7 @@
return skb;
}
-
+extern int (*fast_from_softirq) (struct sk_buff *skb);
/* Get packet from user space buffer */
static ssize_t tun_get_user(struct tun_struct *tun,
const struct iovec *iv, size_t count,
@@ -733,7 +733,12 @@
skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
skb_shinfo(skb)->gso_segs = 0;
}
-
+ if (fast_from_softirq && fast_from_softirq(skb))
+ {
+ tun->dev->stats.rx_packets++;
+ tun->dev->stats.rx_bytes += len;
+ return count;
+ }
netif_rx_ni(skb);
tun->dev->stats.rx_packets++;