[Feature][ZXW-88]merge P50 version

Only Configure: No
Affected branch: master
Affected module: unknown
Is it affected on both ZXIC and MTK: only ZXIC
Self-test: Yes
Doc Update: No

Change-Id: I34667719d9e0e7e29e8e4368848601cde0a48408
diff --git a/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/pcu.c b/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/pcu.c
index ae9db65..5124b9d 100755
--- a/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/pcu.c
+++ b/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/pcu.c
@@ -21,6 +21,44 @@
 #include <mach/irqs.h>
 #include <mach/spinlock.h>
 
+typedef enum _T_Pcu_CoreId
+{
+       CPU_M0 = 0,
+       CPU_PS,
+       CPU_AP,
+       CPU_PHY,
+       MAX_CPU
+} T_Pcu_CoreId;
+
+/**
+ * pcu_CoreIsActive
+ * 
+ * 
+ */
+int pcu_CoreIsActive(T_Pcu_CoreId core)
+{
+   int  active=0;
+
+   switch (core)
+   {
+       case CPU_AP:
+           if((zx_read_reg(DEBUG_SIGNAL_READ_REG0)&(0x1<<4))!=(0x1<<4))
+               active=1;
+           break;
+       case CPU_PS:
+           if((zx_read_reg(DEBUG_SIGNAL_READ_REG1)&(0x1<<11))!=(0x1<<11))
+               active=1;
+           break;
+       case CPU_PHY:
+           if((zx_read_reg(DEBUG_SIGNAL_READ_REG1)&(0x1<<10))!=(0x1<<10))
+                   active=1;
+           break;
+       default:
+               break;
+   }
+
+   return active;
+}
 
 /**
  * helper function
diff --git a/ap/os/linux/linux-3.4.x/arch/arm/mm/fault.c b/ap/os/linux/linux-3.4.x/arch/arm/mm/fault.c
index 27e4e4d..a9dcbe2 100755
--- a/ap/os/linux/linux-3.4.x/arch/arm/mm/fault.c
+++ b/ap/os/linux/linux-3.4.x/arch/arm/mm/fault.c
@@ -21,12 +21,12 @@
 #ifdef CONFIG_MMU
 #ifdef CONFIG_KPROBES
 static inline int notify_page_fault(struct pt_regs*regs,unsigned int fsr){int 
-ret=(0x6ef+1787-0xdea);if(!user_mode(regs)){preempt_disable();if(kprobe_running(
-)&&kprobe_fault_handler(regs,fsr))ret=(0x1c3c+2058-0x2445);preempt_enable();}
+ret=(0xc92+3858-0x1ba4);if(!user_mode(regs)){preempt_disable();if(kprobe_running
+()&&kprobe_fault_handler(regs,fsr))ret=(0x11c+4383-0x123a);preempt_enable();}
 return ret;}
 #else
 static inline int notify_page_fault(struct pt_regs*regs,unsigned int fsr){return
-(0x1f50+1157-0x23d5);}
+(0x22cc+96-0x232c);}
 #endif
 void show_pte(struct mm_struct*mm,unsigned long addr){pgd_t*pgd;if(!mm)mm=&
 init_mm;printk(KERN_ALERT"\x70\x67\x64\x20\x3d\x20\x25\x70" "\n",mm->pgd);pgd=
@@ -34,10 +34,10 @@
 "\x5b\x25\x30\x38\x6c\x78\x5d\x20\x2a\x70\x67\x64\x3d\x25\x30\x38\x6c\x6c\x78",
 addr,(long long)pgd_val(*pgd));do{pud_t*pud;pmd_t*pmd;pte_t*pte;if(pgd_none(*pgd
 ))break;if(pgd_bad(*pgd)){printk("\x28\x62\x61\x64\x29");break;}pud=pud_offset(
-pgd,addr);if(PTRS_PER_PUD!=(0xa17+4067-0x19f9))printk(
+pgd,addr);if(PTRS_PER_PUD!=(0x1312+3764-0x21c5))printk(
 "\x2c\x20\x2a\x70\x75\x64\x3d\x25\x30\x38\x6c\x6c\x78",(long long)pud_val(*pud))
 ;if(pud_none(*pud))break;if(pud_bad(*pud)){printk("\x28\x62\x61\x64\x29");break;
-}pmd=pmd_offset(pud,addr);if(PTRS_PER_PMD!=(0x566+5292-0x1a11))printk(
+}pmd=pmd_offset(pud,addr);if(PTRS_PER_PMD!=(0x1410+3631-0x223e))printk(
 "\x2c\x20\x2a\x70\x6d\x64\x3d\x25\x30\x38\x6c\x6c\x78",(long long)pmd_val(*pmd))
 ;if(pmd_none(*pmd))break;if(pmd_bad(*pmd)){printk("\x28\x62\x61\x64\x29");break;
 }if(PageHighMem(pfn_to_page(pmd_val(*pmd)>>PAGE_SHIFT)))break;pte=pte_offset_map
@@ -47,18 +47,18 @@
 printk("\x2c\x20\x2a\x70\x70\x74\x65\x3d\x25\x30\x38\x6c\x6c\x78",(long long)
 pte_val(pte[PTE_HWTABLE_PTRS]));
 #endif
-pte_unmap(pte);}while((0x1090+1845-0x17c5));printk("\n");}
+pte_unmap(pte);}while((0xf8c+5561-0x2545));printk("\n");}
 #else					
 void show_pte(struct mm_struct*mm,unsigned long addr){}
 #endif					
 static void __do_kernel_fault(struct mm_struct*mm,unsigned long addr,unsigned 
 int fsr,struct pt_regs*regs){if(fixup_exception(regs))return;bust_spinlocks(
-(0x18fd+2706-0x238e));printk(KERN_ALERT
+(0x1e3a+25-0x1e52));printk(KERN_ALERT
 "\x55\x6e\x61\x62\x6c\x65\x20\x74\x6f\x20\x68\x61\x6e\x64\x6c\x65\x20\x6b\x65\x72\x6e\x65\x6c\x20\x25\x73\x20\x61\x74\x20\x76\x69\x72\x74\x75\x61\x6c\x20\x61\x64\x64\x72\x65\x73\x73\x20\x25\x30\x38\x6c\x78" "\n"
 ,(addr<PAGE_SIZE)?
 "\x4e\x55\x4c\x4c\x20\x70\x6f\x69\x6e\x74\x65\x72\x20\x64\x65\x72\x65\x66\x65\x72\x65\x6e\x63\x65"
 :"\x70\x61\x67\x69\x6e\x67\x20\x72\x65\x71\x75\x65\x73\x74",addr);show_pte(mm,
-addr);die("\x4f\x6f\x70\x73",regs,fsr);bust_spinlocks((0xe81+2270-0x175f));
+addr);die("\x4f\x6f\x70\x73",regs,fsr);bust_spinlocks((0x141f+181-0x14d4));
 do_exit(SIGKILL);}static void __do_user_fault(struct task_struct*tsk,unsigned 
 long addr,unsigned int fsr,unsigned int sig,int code,struct pt_regs*regs){struct
  siginfo si;
@@ -69,7 +69,7 @@
 ,tsk->comm,sig,addr,fsr);show_pte(tsk->mm,addr);show_regs(regs);}
 #endif
 tsk->thread.address=addr;tsk->thread.error_code=fsr;tsk->thread.trap_no=
-(0xd65+5191-0x219e);si.si_signo=sig;si.si_errno=(0x184+9332-0x25f8);si.si_code=
+(0xa65+4689-0x1ca8);si.si_signo=sig;si.si_errno=(0xf55+2544-0x1945);si.si_code=
 code;si.si_addr=(void __user*)addr;force_sig_info(sig,&si,tsk);}void do_bad_area
 (unsigned long addr,unsigned int fsr,struct pt_regs*regs){struct task_struct*tsk
 =current;struct mm_struct*mm=tsk->active_mm;if(user_mode(regs))__do_user_fault(
@@ -91,9 +91,9 @@
 static int __kprobes do_page_fault(unsigned long addr,unsigned int fsr,struct 
 pt_regs*regs){struct task_struct*tsk;struct mm_struct*mm;int fault,sig,code;int 
 write=fsr&FSR_WRITE;unsigned int flags=FAULT_FLAG_ALLOW_RETRY|
-FAULT_FLAG_KILLABLE|(write?FAULT_FLAG_WRITE:(0x1838+1160-0x1cc0));if(
-notify_page_fault(regs,fsr))return(0xc4f+4994-0x1fd1);tsk=current;mm=tsk->mm;if(
-interrupts_enabled(regs))local_irq_enable();if(!mm||pagefault_disabled())goto 
+FAULT_FLAG_KILLABLE|(write?FAULT_FLAG_WRITE:(0xeb4+372-0x1028));if(
+notify_page_fault(regs,fsr))return(0x1117+5217-0x2578);tsk=current;mm=tsk->mm;if
+(interrupts_enabled(regs))local_irq_enable();if(!mm||pagefault_disabled())goto 
 no_context;if(!down_read_trylock(&mm->mmap_sem)){if(!user_mode(regs)&&!
 search_exception_tables(regs->ARM_pc))goto no_context;retry:down_read(&mm->
 mmap_sem);}else{might_sleep();
@@ -101,23 +101,23 @@
 if(!user_mode(regs)&&!search_exception_tables(regs->ARM_pc))goto no_context;
 #endif
 }fault=__do_page_fault(mm,addr,fsr,flags,tsk);if((fault&VM_FAULT_RETRY)&&
-fatal_signal_pending(current))return(0x333+8251-0x236e);perf_sw_event(
-PERF_COUNT_SW_PAGE_FAULTS,(0x1bd0+1313-0x20f0),regs,addr);if(!(fault&
+fatal_signal_pending(current))return(0x71b+6588-0x20d7);perf_sw_event(
+PERF_COUNT_SW_PAGE_FAULTS,(0x10e4+4358-0x21e9),regs,addr);if(!(fault&
 VM_FAULT_ERROR)&&flags&FAULT_FLAG_ALLOW_RETRY){if(fault&VM_FAULT_MAJOR){tsk->
-maj_flt++;perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ,(0x420+2661-0xe84),regs,
+maj_flt++;perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ,(0x12db+2597-0x1cff),regs,
 addr);}else{tsk->min_flt++;perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN,
-(0x648+7540-0x23bb),regs,addr);}if(fault&VM_FAULT_RETRY){flags&=~
+(0x202d+467-0x21ff),regs,addr);}if(fault&VM_FAULT_RETRY){flags&=~
 FAULT_FLAG_ALLOW_RETRY;goto retry;}}up_read(&mm->mmap_sem);if(likely(!(fault&(
-VM_FAULT_ERROR|VM_FAULT_BADMAP|VM_FAULT_BADACCESS))))return(0x10d9+5310-0x2597);
-if(fault&VM_FAULT_OOM){pagefault_out_of_memory();return(0x1b03+2939-0x267e);}if(
-!user_mode(regs))goto no_context;if(fault&VM_FAULT_SIGBUS){sig=SIGBUS;code=
+VM_FAULT_ERROR|VM_FAULT_BADMAP|VM_FAULT_BADACCESS))))return(0x113+2808-0xc0b);if
+(fault&VM_FAULT_OOM){pagefault_out_of_memory();return(0x941+780-0xc4d);}if(!
+user_mode(regs))goto no_context;if(fault&VM_FAULT_SIGBUS){sig=SIGBUS;code=
 BUS_ADRERR;}else{sig=SIGSEGV;code=fault==VM_FAULT_BADACCESS?SEGV_ACCERR:
 SEGV_MAPERR;}__do_user_fault(tsk,addr,fsr,sig,code,regs);return
-(0x2246+675-0x24e9);no_context:__do_kernel_fault(mm,addr,fsr,regs);return
-(0x120b+3454-0x1f89);}
+(0xb55+2826-0x165f);no_context:__do_kernel_fault(mm,addr,fsr,regs);return
+(0x30a+3334-0x1010);}
 #else					
 static int do_page_fault(unsigned long addr,unsigned int fsr,struct pt_regs*regs
-){return(0x218b+1329-0x26bc);}
+){return(0x1df0+2011-0x25cb);}
 #endif					
 #ifdef CONFIG_MMU
 static int __kprobes do_translation_fault(unsigned long addr,unsigned int fsr,
@@ -130,21 +130,21 @@
 bad_area;if(!pud_present(*pud))set_pud(pud,*pud_k);pmd=pmd_offset(pud,addr);
 pmd_k=pmd_offset(pud_k,addr);
 #ifdef CONFIG_ARM_LPAE
-index=(0x556+6466-0x1e98);
+index=(0xf8+4197-0x115d);
 #else
-index=(addr>>SECTION_SHIFT)&(0x2ad+2390-0xc02);
+index=(addr>>SECTION_SHIFT)&(0x129+5633-0x1729);
 #endif
 if(pmd_none(pmd_k[index]))goto bad_area;copy_pmd(pmd,pmd_k);return
-(0x100b+5156-0x242f);bad_area:do_bad_area(addr,fsr,regs);return
-(0x1a61+415-0x1c00);}
+(0x615+4683-0x1860);bad_area:do_bad_area(addr,fsr,regs);return
+(0x1964+2399-0x22c3);}
 #else					
 static int do_translation_fault(unsigned long addr,unsigned int fsr,struct 
-pt_regs*regs){return(0x216f+575-0x23ae);}
+pt_regs*regs){return(0x675+6018-0x1df7);}
 #endif					
 static int do_sect_fault(unsigned long addr,unsigned int fsr,struct pt_regs*regs
 ){if(interrupts_enabled(regs))local_irq_enable();do_bad_area(addr,fsr,regs);
-return(0x178a+442-0x1944);}static int do_bad(unsigned long addr,unsigned int fsr
-,struct pt_regs*regs){return(0x1986+838-0x1ccb);}struct fsr_info{int(*fn)(
+return(0xf8+1312-0x618);}static int do_bad(unsigned long addr,unsigned int fsr,
+struct pt_regs*regs){return(0x75b+3411-0x14ad);}struct fsr_info{int(*fn)(
 unsigned long addr,unsigned int fsr,struct pt_regs*regs);int sig;int code;const 
 char*name;};
 #ifdef CONFIG_ARM_LPAE
@@ -153,42 +153,42 @@
 #include "fsr-2level.c"
 #endif
 void __init hook_fault_code(int nr,int(*fn)(unsigned long,unsigned int,struct 
-pt_regs*),int sig,int code,const char*name){if(nr<(0xbf9+1207-0x10b0)||nr>=
+pt_regs*),int sig,int code,const char*name){if(nr<(0x1974+368-0x1ae4)||nr>=
 ARRAY_SIZE(fsr_info))BUG();fsr_info[nr].fn=fn;fsr_info[nr].sig=sig;fsr_info[nr].
 code=code;fsr_info[nr].name=name;}
 #ifdef CONFIG_MODEM_CODE_IS_MAPPING
 static DECLARE_RWSEM(shrinker_rwsem);atomic_t _code_page_count=ATOMIC_INIT(
-(0x3a5+1630-0xa03));struct addr_info{struct list_head node;unsigned long vaddr;
-unsigned long kaddr;unsigned long page_index;};enum modem_access_technology{GSM=
-(0x9d4+2796-0x14c0),UTRAN=(0x19b9+1702-0x205e),LTE=(0x1182+1686-0x1816),COM=
-(0x79d+190-0x858),NR_MODEM_ACCESS=(0xc18+34-0xc36)};struct list_head 
+(0x169f+4028-0x265b));struct addr_info{struct list_head node;unsigned long vaddr
+;unsigned long kaddr;unsigned long page_index;};enum modem_access_technology{GSM
+=(0xf2+105-0x15b),UTRAN=(0x12aa+2629-0x1cee),LTE=(0xae8+4652-0x1d12),COM=
+(0x1c50+1062-0x2073),NR_MODEM_ACCESS=(0x46f+4843-0x1756)};struct list_head 
 modem_page_list[NR_MODEM_ACCESS]={LIST_HEAD_INIT(modem_page_list[
-(0x884+455-0xa4b)]),LIST_HEAD_INIT(modem_page_list[(0x13d1+1582-0x19fe)]),
-LIST_HEAD_INIT(modem_page_list[(0x1cfd+2123-0x2546)]),LIST_HEAD_INIT(
-modem_page_list[(0xbc3+3792-0x1a90)]),};unsigned int page_used[
-(0x260+6029-0x19c5)];struct completion page_completion[(0xb4d+2529-0x1506)*
-(0x7f4+37-0x7f9)];static void unmap_pte_range(pmd_t*pmd,unsigned long addr,
-unsigned long end){pte_t*pte;pte=pte_offset_kernel(pmd,addr);do{pte_t ptent=
-ptep_get_and_clear(&init_mm,addr,pte);WARN_ON(!pte_none(ptent)&&!pte_present(
-ptent));}while(pte++,addr+=PAGE_SIZE,addr!=end);}static void unmap_pmd_range(
-pud_t*pud,unsigned long addr,unsigned long end){pmd_t*pmd;unsigned long next;pmd
-=pmd_offset(pud,addr);do{next=pmd_addr_end(addr,end);if(pmd_none_or_clear_bad(
-pmd))continue;unmap_pte_range(pmd,addr,next);}while(pmd++,addr=next,addr!=end);}
-static void unmap_pud_range(pgd_t*pgd,unsigned long addr,unsigned long end){
-pud_t*pud;unsigned long next;pud=pud_offset(pgd,addr);do{next=pud_addr_end(addr,
-end);if(pud_none_or_clear_bad(pud))continue;unmap_pmd_range(pud,addr,next);}
-while(pud++,addr=next,addr!=end);}static void unmap_page_range(unsigned long 
-addr,unsigned long end){pgd_t*pgd;unsigned long next;BUG_ON(addr>=end);pgd=
-pgd_offset_k(addr);do{next=pgd_addr_end(addr,end);if(pgd_none_or_clear_bad(pgd))
-continue;unmap_pud_range(pgd,addr,next);}while(pgd++,addr=next,addr!=end);}void 
-shrink_modem_mem(unsigned int access_type){int i=(0x129c+1251-0x177f);unsigned 
+(0xeb1+4232-0x1f39)]),LIST_HEAD_INIT(modem_page_list[(0x3a6+1703-0xa4c)]),
+LIST_HEAD_INIT(modem_page_list[(0x7bc+539-0x9d5)]),LIST_HEAD_INIT(
+modem_page_list[(0x24ac+515-0x26ac)]),};unsigned int page_used[(0x3a+15-0x21)];
+struct completion page_completion[(0x1a1+6451-0x1aac)*(0x132b+3356-0x2027)];
+static void unmap_pte_range(pmd_t*pmd,unsigned long addr,unsigned long end){
+pte_t*pte;pte=pte_offset_kernel(pmd,addr);do{pte_t ptent=ptep_get_and_clear(&
+init_mm,addr,pte);WARN_ON(!pte_none(ptent)&&!pte_present(ptent));}while(pte++,
+addr+=PAGE_SIZE,addr!=end);}static void unmap_pmd_range(pud_t*pud,unsigned long 
+addr,unsigned long end){pmd_t*pmd;unsigned long next;pmd=pmd_offset(pud,addr);do
+{next=pmd_addr_end(addr,end);if(pmd_none_or_clear_bad(pmd))continue;
+unmap_pte_range(pmd,addr,next);}while(pmd++,addr=next,addr!=end);}static void 
+unmap_pud_range(pgd_t*pgd,unsigned long addr,unsigned long end){pud_t*pud;
+unsigned long next;pud=pud_offset(pgd,addr);do{next=pud_addr_end(addr,end);if(
+pud_none_or_clear_bad(pud))continue;unmap_pmd_range(pud,addr,next);}while(pud++,
+addr=next,addr!=end);}static void unmap_page_range(unsigned long addr,unsigned 
+long end){pgd_t*pgd;unsigned long next;BUG_ON(addr>=end);pgd=pgd_offset_k(addr);
+do{next=pgd_addr_end(addr,end);if(pgd_none_or_clear_bad(pgd))continue;
+unmap_pud_range(pgd,addr,next);}while(pgd++,addr=next,addr!=end);}void 
+shrink_modem_mem(unsigned int access_type){int i=(0x196d+2610-0x239f);unsigned 
 long vaddr;struct addr_info*addr,*tmp_addr;struct list_head tmp_page_list;for(i=
-(0xdaf+1270-0x12a5);i<NR_MODEM_ACCESS;i++){if(i==access_type)continue;down_write
+(0x6f6+2488-0x10ae);i<NR_MODEM_ACCESS;i++){if(i==access_type)continue;down_write
 (&shrinker_rwsem);list_replace_init(&modem_page_list[i],&tmp_page_list);up_write
 (&shrinker_rwsem);list_for_each_entry_safe(addr,tmp_addr,&tmp_page_list,node){
 list_del_init(&addr->node);page_completion[addr->page_index].done=
-(0x3a3+15-0x3b2);page_used[addr->page_index/BITS_PER_LONG]&=~(
-(0x1431+116-0x14a4)<<(addr->page_index%BITS_PER_LONG));vaddr=addr->vaddr&
+(0x1296+1173-0x172b);page_used[addr->page_index/BITS_PER_LONG]&=~(
+(0xd13+5648-0x2322)<<(addr->page_index%BITS_PER_LONG));vaddr=addr->vaddr&
 PAGE_MASK;if(vaddr<cpps_global_var.cpko_text_start||vaddr>cpps_global_var.
 modem_text_end){panic(
 "\x61\x64\x64\x72\x5f\x69\x6e\x66\x6f\x3a\x20\x25\x30\x38\x78\x20\x69\x73\x20\x20\x64\x65\x73\x74\x72\x6f\x79"
@@ -196,28 +196,28 @@
 PAGE_SIZE);flush_tlb_kernel_range(vaddr,vaddr+PAGE_SIZE);
 #ifdef CONFIG_DEBUG_RODATA
 unsigned int flags;local_irq_save(flags);set_memory_rw(addr->kaddr,
-(0x4b0+2552-0xea7));local_irq_restore(flags);
+(0x236+3876-0x1159));local_irq_restore(flags);
 #endif
 free_page(addr->kaddr);kfree(addr);atomic_dec(&_code_page_count);};}}
 EXPORT_SYMBOL(shrink_modem_mem);phys_addr_t virt_is_mapping(unsigned long addr){
 pgd_t*pgd;pmd_t*pmd;pte_t*ptep,pte;unsigned long pfn;pgd=pgd_offset_k(addr);if(!
 pgd_none(*pgd)){pmd=pmd_offset(pgd,addr);if(!pmd_none(*pmd)){ptep=pte_offset_map
 (pmd,addr);pte=*ptep;if(pte_present(pte)){pfn=pte_pfn(pte);return __pfn_to_phys(
-pfn);}}}return(0x3eb+976-0x7bb);}static int sync_pgd(unsigned long addr,unsigned
- int fsr,struct pt_regs*regs){unsigned int index;pgd_t*pgd,*pgd_k;pud_t*pud,*
-pud_k;pmd_t*pmd,*pmd_k;index=pgd_index(addr);pgd=cpu_get_pgd()+index;pgd_k=
+pfn);}}}return(0x18b4+115-0x1927);}static int sync_pgd(unsigned long addr,
+unsigned int fsr,struct pt_regs*regs){unsigned int index;pgd_t*pgd,*pgd_k;pud_t*
+pud,*pud_k;pmd_t*pmd,*pmd_k;index=pgd_index(addr);pgd=cpu_get_pgd()+index;pgd_k=
 init_mm.pgd+index;if(pgd_none(*pgd_k))goto bad_area;if(!pgd_present(*pgd))
 set_pgd(pgd,*pgd_k);pud=pud_offset(pgd,addr);pud_k=pud_offset(pgd_k,addr);if(
 pud_none(*pud_k))goto bad_area;if(!pud_present(*pud))set_pud(pud,*pud_k);pmd=
 pmd_offset(pud,addr);pmd_k=pmd_offset(pud_k,addr);
 #ifdef CONFIG_ARM_LPAE
-index=(0x532+6727-0x1f79);
+index=(0x12fa+3801-0x21d3);
 #else
-index=(addr>>SECTION_SHIFT)&(0xc67+4122-0x1c80);
+index=(addr>>SECTION_SHIFT)&(0x9b4+895-0xd32);
 #endif
 if(pmd_none(pmd_k[index]))goto bad_area;copy_pmd(pmd,pmd_k);return
-(0xebf+3585-0x1cc0);bad_area:do_bad_area(addr,fsr,regs);return
-(0x12a3+3758-0x2151);}unsigned long*read_code_file(unsigned long page_index){
+(0x16f1+2780-0x21cd);bad_area:do_bad_area(addr,fsr,regs);return
+(0xe64+6096-0x2634);}unsigned long*read_code_file(unsigned long page_index){
 unsigned long*code_buf;ssize_t result;code_buf=get_zeroed_page(GFP_ATOMIC);if(!
 code_buf)panic(
 "\x6d\x65\x6d\x65\x6f\x72\x79\x20\x6e\x6f\x74\x20\x65\x6e\x6f\x75\x67\x68\x21\x21"
@@ -226,80 +226,80 @@
 "\x6f\x70\x65\x6e\x20\x66\x69\x6c\x65\x20\x65\x72\x72\x6f\x72" "\n");}
 mm_segment_t old_fs;old_fs=get_fs();set_fs(KERNEL_DS);loff_t pos;pos=page_index*
 PAGE_SIZE+cpps_global_var.modem_offset;result=vfs_read(cpps_global_var.fp_code,(
-char*)code_buf,PAGE_SIZE,&pos);if(result<(0x59d+1700-0xc41)){panic(
+char*)code_buf,PAGE_SIZE,&pos);if(result<(0x620+4549-0x17e5)){panic(
 "\x72\x65\x61\x64\x20\x63\x6f\x64\x65\x20\x66\x69\x6c\x65\x20\x65\x72\x72\x6f\x72" "\n"
 );}
 #ifdef CONFIG_DEBUG_RODATA
 unsigned int flags;local_irq_save(flags);set_memory_ro((unsigned long)code_buf,
-(0x1f+9427-0x24f1));local_irq_restore(flags);
+(0x1bf+9361-0x264f));local_irq_restore(flags);
 #endif
 set_fs(old_fs);return code_buf;}void read_code_mapping(unsigned long addr,
 unsigned int fsr,struct pt_regs*regs){unsigned long offset;unsigned long vaddr;
 const struct mem_type*mtype;unsigned long*vir_codebuf;unsigned long page_index;
-unsigned long page_shift;if(virt_is_mapping(addr&PAGE_MASK)!=(0x9c2+6248-0x222a)
-){sync_pgd(addr&PAGE_MASK,fsr,regs);return;}vaddr=addr&PAGE_MASK;offset=vaddr&(~
-cpps_global_var.cpko_text_start);page_index=offset>>PAGE_SHIFT;page_shift=
-page_index%BITS_PER_LONG;if((page_used[page_index/BITS_PER_LONG]>>page_shift)&
-(0x982+4838-0x1c67)){wait_for_completion(&page_completion[page_index]);sync_pgd(
-vaddr,fsr,regs);return;}else page_used[page_index/BITS_PER_LONG]|=(
-(0x936+3686-0x179b)<<page_shift);local_irq_enable();vir_codebuf=read_code_file(
-page_index);struct addr_info*addr_info;addr_info=kzalloc(sizeof(struct addr_info
-),GFP_KERNEL);addr_info->kaddr=vir_codebuf;addr_info->vaddr=addr;addr_info->
-page_index=page_index;down_write(&shrinker_rwsem);if(vaddr<cpps_global_var.
-__utran_modem_text_start)list_add(&addr_info->node,&modem_page_list[GSM]);else 
-if(vaddr<cpps_global_var.__lte_modem_text_start)list_add(&addr_info->node,&
-modem_page_list[UTRAN]);else if(vaddr<cpps_global_var.__comm_modem_text_start)
-list_add(&addr_info->node,&modem_page_list[LTE]);else list_add(&addr_info->node,
-&modem_page_list[COM]);up_write(&shrinker_rwsem);local_irq_disable();mtype=
-get_mem_type(MT_MEMORY);ioremap_page(vaddr,__pa(vir_codebuf),mtype);sync_pgd(
-vaddr,fsr,regs);flush_icache_range(vaddr,vaddr+PAGE_SIZE);if(waitqueue_active(&
-page_completion[page_index].wait))complete_all(&page_completion[page_index]);
-return;}
+unsigned long page_shift;if(virt_is_mapping(addr&PAGE_MASK)!=
+(0x1df5+1764-0x24d9)){sync_pgd(addr&PAGE_MASK,fsr,regs);return;}vaddr=addr&
+PAGE_MASK;offset=vaddr&(~cpps_global_var.cpko_text_start);page_index=offset>>
+PAGE_SHIFT;page_shift=page_index%BITS_PER_LONG;if((page_used[page_index/
+BITS_PER_LONG]>>page_shift)&(0xc6+8408-0x219d)){wait_for_completion(&
+page_completion[page_index]);sync_pgd(vaddr,fsr,regs);return;}else page_used[
+page_index/BITS_PER_LONG]|=((0x2d1+7082-0x1e7a)<<page_shift);local_irq_enable();
+vir_codebuf=read_code_file(page_index);struct addr_info*addr_info;addr_info=
+kzalloc(sizeof(struct addr_info),GFP_KERNEL);addr_info->kaddr=vir_codebuf;
+addr_info->vaddr=addr;addr_info->page_index=page_index;down_write(&
+shrinker_rwsem);if(vaddr<cpps_global_var.__utran_modem_text_start)list_add(&
+addr_info->node,&modem_page_list[GSM]);else if(vaddr<cpps_global_var.
+__lte_modem_text_start)list_add(&addr_info->node,&modem_page_list[UTRAN]);else 
+if(vaddr<cpps_global_var.__comm_modem_text_start)list_add(&addr_info->node,&
+modem_page_list[LTE]);else list_add(&addr_info->node,&modem_page_list[COM]);
+up_write(&shrinker_rwsem);local_irq_disable();mtype=get_mem_type(MT_MEMORY);
+ioremap_page(vaddr,__pa(vir_codebuf),mtype);sync_pgd(vaddr,fsr,regs);
+flush_icache_range(vaddr,vaddr+PAGE_SIZE);if(waitqueue_active(&page_completion[
+page_index].wait))complete_all(&page_completion[page_index]);return;}
 #endif
 asmlinkage void __exception do_DataAbort(unsigned long addr,unsigned int fsr,
 struct pt_regs*regs){const struct fsr_info*inf=fsr_info+fsr_fs(fsr);struct 
 siginfo info;
 #ifdef CONFIG_MODEM_CODE_IS_MAPPING
-if(addr!=(0x1ccd+2394-0x2627)&&addr>=cpps_global_var.cpko_text_start&&addr<=
+if(addr!=(0x1d86+2141-0x25e3)&&addr>=cpps_global_var.cpko_text_start&&addr<=
 cpps_global_var.modem_text_end){read_code_mapping(addr,fsr&~FSR_LNX_PF,regs);
 return;}
 #endif
 if(!inf->fn(addr,fsr&~FSR_LNX_PF,regs))return;printk(KERN_ALERT
 "\x55\x6e\x68\x61\x6e\x64\x6c\x65\x64\x20\x66\x61\x75\x6c\x74\x3a\x20\x25\x73\x20\x28\x30\x78\x25\x30\x33\x78\x29\x20\x61\x74\x20\x30\x78\x25\x30\x38\x6c\x78" "\n"
-,inf->name,fsr,addr);info.si_signo=inf->sig;info.si_errno=(0x10dd+3541-0x1eb2);
+,inf->name,fsr,addr);info.si_signo=inf->sig;info.si_errno=(0x9b9+4581-0x1b9e);
 info.si_code=inf->code;info.si_addr=(void __user*)addr;arm_notify_die("",regs,&
-info,fsr,(0x390+3520-0x1150));}void __init hook_ifault_code(int nr,int(*fn)(
+info,fsr,(0x242f+486-0x2615));}void __init hook_ifault_code(int nr,int(*fn)(
 unsigned long,unsigned int,struct pt_regs*),int sig,int code,const char*name){if
-(nr<(0xbb5+3866-0x1acf)||nr>=ARRAY_SIZE(ifsr_info))BUG();ifsr_info[nr].fn=fn;
+(nr<(0x795+1718-0xe4b)||nr>=ARRAY_SIZE(ifsr_info))BUG();ifsr_info[nr].fn=fn;
 ifsr_info[nr].sig=sig;ifsr_info[nr].code=code;ifsr_info[nr].name=name;}
 asmlinkage void __exception do_PrefetchAbort(unsigned long addr,unsigned int 
 ifsr,struct pt_regs*regs){const struct fsr_info*inf=ifsr_info+fsr_fs(ifsr);
 struct siginfo info;
 #ifdef CONFIG_MODEM_CODE_IS_MAPPING
-if(addr!=(0xdc7+6420-0x26db)&&addr>=cpps_global_var.cpko_text_start&&addr<=
+if(addr!=(0x1b73+1424-0x2103)&&addr>=cpps_global_var.cpko_text_start&&addr<=
 cpps_global_var.modem_text_end){read_code_mapping(addr,ifsr|FSR_LNX_PF,regs);
 return;}
 #endif
 if(!inf->fn(addr,ifsr|FSR_LNX_PF,regs))return;printk(KERN_ALERT
 "\x55\x6e\x68\x61\x6e\x64\x6c\x65\x64\x20\x70\x72\x65\x66\x65\x74\x63\x68\x20\x61\x62\x6f\x72\x74\x3a\x20\x25\x73\x20\x28\x30\x78\x25\x30\x33\x78\x29\x20\x61\x74\x20\x30\x78\x25\x30\x38\x6c\x78" "\n"
-,inf->name,ifsr,addr);info.si_signo=inf->sig;info.si_errno=(0x8b3+2422-0x1229);
+,inf->name,ifsr,addr);info.si_signo=inf->sig;info.si_errno=(0x10b6+3532-0x1e82);
 info.si_code=inf->code;info.si_addr=(void __user*)addr;arm_notify_die("",regs,&
-info,ifsr,(0x9dd+4243-0x1a70));}
+info,ifsr,(0x11+5858-0x16f3));}
 #ifndef CONFIG_ARM_LPAE
 static int __init exceptions_init(void){if(cpu_architecture()>=CPU_ARCH_ARMv6){
-hook_fault_code((0x6cb+7772-0x2523),do_translation_fault,SIGSEGV,SEGV_MAPERR,
+hook_fault_code((0x11+2540-0x9f9),do_translation_fault,SIGSEGV,SEGV_MAPERR,
 "\x49\x2d\x63\x61\x63\x68\x65\x20\x6d\x61\x69\x6e\x74\x65\x6e\x61\x6e\x63\x65\x20\x66\x61\x75\x6c\x74"
-);}if(cpu_architecture()>=CPU_ARCH_ARMv7){hook_fault_code((0xa8+69-0xea),do_bad,
-SIGSEGV,SEGV_MAPERR,
+);}if(cpu_architecture()>=CPU_ARCH_ARMv7){hook_fault_code((0x397+544-0x5b4),
+do_bad,SIGSEGV,SEGV_MAPERR,
 "\x73\x65\x63\x74\x69\x6f\x6e\x20\x61\x63\x63\x65\x73\x73\x20\x66\x6c\x61\x67\x20\x66\x61\x75\x6c\x74"
-);hook_fault_code((0x630+1162-0xab4),do_bad,SIGSEGV,SEGV_MAPERR,
+);hook_fault_code((0xb36+6682-0x254a),do_bad,SIGSEGV,SEGV_MAPERR,
 "\x73\x65\x63\x74\x69\x6f\x6e\x20\x61\x63\x63\x65\x73\x73\x20\x66\x6c\x61\x67\x20\x66\x61\x75\x6c\x74"
 );}
 #ifdef CONFIG_MODEM_CODE_IS_MAPPING
-int index=(0x74f+298-0x879);for(index=(0x6c+5061-0x1431);index<
-(0x190+7054-0x1cf6)*(0x13cf+4383-0x24ce);index++)init_completion(&
-page_completion[index]);
+int index=(0xa5f+2859-0x158a);for(index=(0xf49+5337-0x2422);index<
+(0xd97+1707-0x141a)*(0xaa6+1773-0x1173);index++)init_completion(&page_completion
+[index]);
 #endif
-return(0x16fa+3252-0x23ae);}arch_initcall(exceptions_init);
+return(0x148d+4593-0x267e);}arch_initcall(exceptions_init);
 #endif
 
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 9808d24..09782a0 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
@@ -82,31 +82,30 @@
 __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
-(0x588+2748-0x1044);}extern unsigned int SysEntry(void);static int 
+(0x1019+2285-0x1906);}extern unsigned int SysEntry(void);static int 
 ko_Main_Thread(void*data){struct sched_param param={.sched_priority=
-MAX_USER_RT_PRIO/(0x1aa2+478-0x1c7e)-(0xb4b+3818-0x1a32)};int ret=
-(0x985+3929-0x18de);sched_setscheduler(current,SCHED_FIFO,&param);ret=SysEntry()
-;if(ret!=(0xacd+2158-0x133b))panic("Main_Thread\n");param.sched_priority=
-MAX_USER_RT_PRIO-(0x1194+2176-0x19e6);sched_setscheduler(kthreadd_task,
-SCHED_FIFO,&param);return(0x1e56+83-0x1ea9);}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
-(0x1109+1789-0x1806);}static void cpko_sectioninfo_set(void){int ret;struct file
-*fp;mm_segment_t old_fs;loff_t cpko_pos=(0x16fb+814-0x1a29);struct 
+MAX_USER_RT_PRIO/(0x1e05+849-0x2154)-(0x163f+244-0x1730)};int ret=
+(0x6a0+1651-0xd13);sched_setscheduler(current,SCHED_FIFO,&param);ret=SysEntry();
+if(ret!=(0x1c59+477-0x1e36))panic("Main_Thread\n");param.sched_priority=
+MAX_USER_RT_PRIO-(0xa62+2452-0x13c8);sched_setscheduler(kthreadd_task,SCHED_FIFO
+,&param);return(0x1874+837-0x1bb9);}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(0x16ed+2471-0x2094);}static void cpko_sectioninfo_set(void){int ret;
+struct file*fp;mm_segment_t old_fs;loff_t cpko_pos=(0x82b+1876-0xf7f);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"
-,(0x2fa+1778-0x9ec),(0x13ec+700-0x16a8));if(IS_ERR(fp)||fp==NULL)panic(
+,(0xe32+3591-0x1c39),(0xe13+5426-0x2345));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<=(0xd62+2480-0x1712))panic(
+cpko_section_layout),&cpko_pos);if(ret<=(0x16f9+2110-0x1f37))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",
-(0x172f+1154-0x1bb1),(0xc82+3654-0x1ac8));if(IS_ERR(fp)||fp==NULL)panic(
+(0xa57+3978-0x19e1),(0x1938+3499-0x26e3));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=(0xb17+2019-0x12fa);
+ra_pages=(0x90+7657-0x1e79);
 #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 +125,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={(0x800+2644-0x1254)};callback.
+cpko_start(void){struct cpps_callbacks callback={(0xfcd+1554-0x15df)};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.
@@ -196,5 +195,5 @@
 psm_GetModemSleepFlagStatus=psm_GetModemSleepFlagStatus;
 #endif
 cpps_callbacks_register(&callback);cpko_sectioninfo_set();zte_modem_ko_start();
-return(0x990+7510-0x26e6);}static int cpko_stop(void){return(0xe70+451-0x1033);}
-module_init(cpko_start);module_exit(cpko_stop);
+return(0x99a+2509-0x1367);}static int cpko_stop(void){return(0xa38+1976-0x11f0);
+}module_init(cpko_start);module_exit(cpko_stop);
diff --git a/ap/os/linux/linux-3.4.x/drivers/mfd/zx234290-core.c b/ap/os/linux/linux-3.4.x/drivers/mfd/zx234290-core.c
old mode 100644
new mode 100755
index 7fc94b3..21fda0e
--- a/ap/os/linux/linux-3.4.x/drivers/mfd/zx234290-core.c
+++ b/ap/os/linux/linux-3.4.x/drivers/mfd/zx234290-core.c
@@ -576,7 +576,9 @@
 	}
 
 /*************************/
-#ifndef AP_NO_NEED_PMU_INT_FOR_PHONE
+#if (defined AP_NO_NEED_PMU_INT_FOR_PHONE) || (defined _USE_VEHICLE_DC)
+
+#else
 	//init_data->irq = pmic_plat_data->irq;
 	//init_data->irq_base = pmic_plat_data->irq_base;
 	irq = gpio_to_irq(pmic_plat_data->irq_gpio_num);
diff --git a/ap/os/linux/linux-3.4.x/drivers/mmc/core/mmc.c b/ap/os/linux/linux-3.4.x/drivers/mmc/core/mmc.c
old mode 100644
new mode 100755
index 6d74683..d79088d
--- a/ap/os/linux/linux-3.4.x/drivers/mmc/core/mmc.c
+++ b/ap/os/linux/linux-3.4.x/drivers/mmc/core/mmc.c
@@ -22,6 +22,7 @@
 #include "bus.h"
 #include "mmc_ops.h"
 #include "sd_ops.h"
+#include "pub_debug_info.h"
 
 static const unsigned int tran_exp[] = {
 	10000,		100000,		1000000,	10000000,
@@ -1537,6 +1538,8 @@
 	host->card = NULL;
 err:
 	mmc_detach_bus(host);
+	sc_debug_info_record(MODULE_ID_AP_MMC, "%s: error %d whilst initialising MMC card\n",
+		mmc_hostname(host),err);
 
 	pr_err("%s: error %d whilst initialising MMC card\n",
 		mmc_hostname(host), err);
diff --git a/ap/os/linux/linux-3.4.x/drivers/mmc/core/sdio.c b/ap/os/linux/linux-3.4.x/drivers/mmc/core/sdio.c
old mode 100644
new mode 100755
index 4bcac91..81a5f51
--- a/ap/os/linux/linux-3.4.x/drivers/mmc/core/sdio.c
+++ b/ap/os/linux/linux-3.4.x/drivers/mmc/core/sdio.c
@@ -30,6 +30,7 @@
 #include "sd_ops.h"
 #include "sdio_ops.h"
 #include "sdio_cis.h"
+#include "pub_debug_info.h"
 
 #ifdef CONFIG_MMC_EMBEDDED_SDIO
 #include <linux/mmc/sdio_ids.h>
@@ -1267,6 +1268,9 @@
 err:
 	mmc_printk("%s: Error resetting SDIO communications (%d)\n",
 	       mmc_hostname(host), err);		//xiu
+	sc_debug_info_record(MODULE_ID_AP_MMC, "%s: Error resetting SDIO communications (%d)\n",
+		mmc_hostname(host),err);
+	       
 	mmc_release_host(host);
 	return err;
 }
diff --git a/ap/os/linux/linux-3.4.x/drivers/mmc/host/zx29_mmc.c b/ap/os/linux/linux-3.4.x/drivers/mmc/host/zx29_mmc.c
old mode 100644
new mode 100755
index b1a7a72..425d6a7
--- a/ap/os/linux/linux-3.4.x/drivers/mmc/host/zx29_mmc.c
+++ b/ap/os/linux/linux-3.4.x/drivers/mmc/host/zx29_mmc.c
@@ -50,6 +50,7 @@
 #include <linux/gpio.h>
 //#include "dw_mmc.h"
 #include "zx29_mmc.h"
+#include "pub_debug_info.h"
 
 #if (defined CONFIG_ARCH_ZX297520V2)||(defined CONFIG_ARCH_ZX297520V3)
 #include <mach/gpio_cfg.h>
@@ -235,6 +236,9 @@
 		"ERROR dw_dto_timer_expired", host->dw_dto_timer_expired_cnt, host->completed_events, host->state);
 	xlog_mmc_log_opkey(host->host_id, opcode,
 		"ERROR dw_dto_timer_expired", mci_readl(host, STATUS), mci_readl(host,IDSTS), mci_readl(host, RINTSTS));
+	sc_debug_info_record(MODULE_ID_AP_MMC, "ERROR dw_dto_timer_expired cnt=%d,STATUS=0x%x\n",
+		host->dw_dto_timer_expired_cnt,mci_readl(host, STATUS));
+
 /*
 	mmc_printk("ERROR %s,STATUS=0x%x,IDSTS=0x%x, RINTSTS=0x%x,MINTSTS=0x%x\n", __func__,
 			mci_readl(host, STATUS),mci_readl(host,IDSTS),mci_readl(host, RINTSTS),mci_readl(host, MINTSTS));		//xiu
@@ -1605,7 +1609,9 @@
 		if (!(cmd_status & SDMMC_CMD_START))
 			return 0;
 	}
-	xlog_mmc_log(host->host_id, "INFO mci_send_cmd TIMEOUT", cmd, arg, cmd_status);
+	xlog_mmc_log(host->host_id, "INFO mci_send_cmd TIMEOUT", cmd, arg, cmd_status);	
+	sc_debug_info_record(MODULE_ID_AP_MMC, "Timeout sending command (cmd %#x arg %#x status %#x)\n",
+		cmd, arg, cmd_status);
 	dev_err(&slot->mmc->class_dev,
 		"Timeout sending command (cmd %#x arg %#x status %#x)\n",
 		cmd, arg, cmd_status);
@@ -1713,6 +1719,7 @@
         } while (time_before(jiffies, timeout));
 
         dev_err(host->dev, "%s: SDIO device busy timeout,status is 0x%08x\n",__func__,status);
+		sc_debug_info_record(MODULE_ID_AP_MMC,"%s(%d): timeout,status is 0x%08x\n",__func__,host->host_id,status);
 
         return -1;
 
@@ -2277,14 +2284,20 @@
 		}
 	}
 
-	if (status & SDMMC_INT_HLE)
-		cmd->error = -EIO;
+	if (status & SDMMC_INT_HLE){
+		cmd->error = -EIO;		
+		sc_debug_info_record(MODULE_ID_AP_MMC,"%s(%d): cmd->error=0x%x\n",__func__,host->host_id,cmd->error);
+	}
 	else if (status & SDMMC_INT_RTO)
 		cmd->error = -ETIMEDOUT;
-	else if ((cmd->flags & MMC_RSP_CRC) && (status & SDMMC_INT_RCRC))
+	else if ((cmd->flags & MMC_RSP_CRC) && (status & SDMMC_INT_RCRC)){
 		cmd->error = -EILSEQ;
-	else if (status & SDMMC_INT_RESP_ERR)
-		cmd->error = -EIO;
+		sc_debug_info_record(MODULE_ID_AP_MMC,"%s(%d): cmd->error=0x%x\n",__func__,host->host_id,cmd->error);		
+	}
+	else if (status & SDMMC_INT_RESP_ERR){
+		cmd->error = -EIO;		
+		sc_debug_info_record(MODULE_ID_AP_MMC,"%s(%d): cmd->error=0x%x\n",__func__,host->host_id,cmd->error);		
+	}
 	else
 		cmd->error = 0;
 
@@ -2330,7 +2343,8 @@
 		}
 
 		temp = mci_readl(host, STATUS);
-		dev_err(host->dev, "DATA ERROR, MINTSTS 0x%X, STATUS 0x%X\n", status, temp);
+		dev_err(host->dev, "DATA ERROR, MINTSTS 0x%X, STATUS 0x%X\n", status, temp);		
+		sc_debug_info_record(MODULE_ID_AP_MMC,"DATA ERROR, MINTSTS 0x%X, STATUS 0x%X\n", status, temp);		
 		xlog_mmc_status(host->host_id, data->mrq->cmd->opcode, XLOG_TF_STATUS_DATA_COMPLETE, data->error, status, temp);
 		if (status & SDMMC_INT_FRUN) {
 			xlog_mmc_log_opkey(host->host_id, data->mrq->cmd->opcode,
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/ppp/ppp_generic.c b/ap/os/linux/linux-3.4.x/drivers/net/ppp/ppp_generic.c
old mode 100644
new mode 100755
index db2c894..7888719
--- a/ap/os/linux/linux-3.4.x/drivers/net/ppp/ppp_generic.c
+++ b/ap/os/linux/linux-3.4.x/drivers/net/ppp/ppp_generic.c
@@ -2282,8 +2282,9 @@
 	spin_lock_bh(&pn->all_channels_lock);
 	list_del(&pch->list);
 	spin_unlock_bh(&pn->all_channels_lock);
-	put_net(pch->chan_net);
-	pch->chan_net = NULL;
+	//205e1e255c479f3fd77446415706463b282f94e4
+	//put_net(pch->chan_net);
+	//pch->chan_net = NULL;
 
 	pch->file.dead = 1;
 	wake_up_interruptible(&pch->file.rwait);
@@ -2890,6 +2891,9 @@
  */
 static void ppp_destroy_channel(struct channel *pch)
 {
+	put_net(pch->chan_net);
+	pch->chan_net = NULL;
+	//205e1e255c479f3fd77446415706463b282f94e4
 	atomic_dec(&channel_count);
 
 	if (!pch->file.dead) {
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/ppp/pppoe.c b/ap/os/linux/linux-3.4.x/drivers/net/ppp/pppoe.c
old mode 100644
new mode 100755
index 98e92cb..79090d0
--- a/ap/os/linux/linux-3.4.x/drivers/net/ppp/pppoe.c
+++ b/ap/os/linux/linux-3.4.x/drivers/net/ppp/pppoe.c
@@ -577,7 +577,9 @@
 
 	po = pppox_sk(sk);
 
-	if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
+	//if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
+	//1acea4f6ce1b1c0941438aca75dd2e5c6b09db60
+	if (po->pppoe_dev) {
 		dev_put(po->pppoe_dev);
 		po->pppoe_dev = NULL;
 	}
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/zvnet/zvnet_dev.c b/ap/os/linux/linux-3.4.x/drivers/net/zvnet/zvnet_dev.c
old mode 100644
new mode 100755
index 723810d..6e22779
--- a/ap/os/linux/linux-3.4.x/drivers/net/zvnet/zvnet_dev.c
+++ b/ap/os/linux/linux-3.4.x/drivers/net/zvnet/zvnet_dev.c
@@ -4,6 +4,10 @@
 #include <linux/module.h>

 #include <linux/etherdevice.h>

 #include <net/sock.h>

+#include <linux/in.h>

+#include <linux/ip.h>

+#include <linux/ipv6.h>

+#include <net/addrconf.h>

 #include "zvnet_dev.h"

 

 /*******************************************************************************

@@ -413,6 +417,7 @@
 	}

 }

 #endif

+extern int pcu_CoreIsActive(int core);

 static netdev_tx_t zvnet_xmit(struct sk_buff *skb, struct net_device *net)

 {

 #ifdef USE_ZVNET_PACKET

@@ -426,7 +431,43 @@
 		kfree_skb(skb);

 		return NET_XMIT_SUCCESS;

 	}

-		

+	if(!(skb->now_location & (FASTNAT_SUCC | FASTBR_SUCC))){

+		struct iphdr *iph;

+		iph = ip_hdr(skb);

+		if (iph->version == 4){

+			if (ipv4_is_multicast(iph->daddr) || ipv4_is_lbcast(iph->daddr)){

+				if(pcu_CoreIsActive(2) == 0){

+					net->stats.tx_errors++;

+					net->stats.tx_dropped++;

+					zv_err("cap psm zvnet drop v4!");

+					kfree_skb(skb);

+					return NET_XMIT_SUCCESS;

+				}

+			}

+		}else if (iph->version == 6){

+			if(ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)){

+				if(pcu_CoreIsActive(2) == 0){

+					net->stats.tx_errors++;

+					net->stats.tx_dropped++;

+					zv_err("cap psm zvnet drop v6!");

+					kfree_skb(skb);

+					return NET_XMIT_SUCCESS;

+				}

+			}

+		}else{

+#if 0

+			if(is_multicast_ether_addr(skb_mac_header(skb))){

+				if(pcu_CoreIsActive(2) == 0){

+					net->stats.tx_errors++;

+					net->stats.tx_dropped++;

+					zv_err("cap psm zvnet drop arp?");

+					kfree_skb(skb);

+					return NET_XMIT_SUCCESS;

+				}

+			}

+#endif

+		}

+	}

 	if(unlikely(skb->capHead || skb->next || skb->fclone || skb->cloned 

 		|| (skb_shinfo(skb)->nr_frags) || (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) 

 		|| (skb_has_frag_list(skb)))){

diff --git a/ap/os/linux/linux-3.4.x/drivers/rtc/zx234290-rtc.c b/ap/os/linux/linux-3.4.x/drivers/rtc/zx234290-rtc.c
old mode 100644
new mode 100755
index ddfa780..54428db
--- a/ap/os/linux/linux-3.4.x/drivers/rtc/zx234290-rtc.c
+++ b/ap/os/linux/linux-3.4.x/drivers/rtc/zx234290-rtc.c
@@ -1111,6 +1111,9 @@
 	rtc->max_user_freq = 64; //32768;//32k clock

 	zx234290_rtc_irqno = zx234290_rtc.zx234290->chip_irq;

 	platform_set_drvdata(pdev, rtc);

+#ifdef _USE_VEHICLE_DC

+	printk("rtc get time only probe ok!\n");

+#else

 	ret = zx234290_rtc_request_irq(pdev, rtc);

 	if (ret)

 	{

@@ -1120,6 +1123,8 @@
 	zx234290_rtc_write_register(ZX234290_REG_ADDR_RTC_CTRL1, 0, 0xff);

 	zx234290_rtc_setuie(&pdev->dev, 0);

 	zx234290_rtc_enable(&pdev->dev, 0);

+#endif    

+	

 	sema_init(&timerSemaphore,0);

     //zx234290_rtc_ioctl(NULL,ZX234290_SET_TIMER,20);

 	return 0;

diff --git a/ap/os/linux/linux-3.4.x/drivers/rtc/zx234290-rtc.h b/ap/os/linux/linux-3.4.x/drivers/rtc/zx234290-rtc.h
old mode 100644
new mode 100755
index 4e68c8e..3233c6e
--- a/ap/os/linux/linux-3.4.x/drivers/rtc/zx234290-rtc.h
+++ b/ap/os/linux/linux-3.4.x/drivers/rtc/zx234290-rtc.h
@@ -42,7 +42,7 @@
 #define ZX234290_RTC_TIME_CENTURY_WID           (1)

 

 #define ZX234290_RTC_TIME_YEAR_LSH              (0)

-#define ZX234290_RTC_TIME_YEAR_WID              (7)

+#define ZX234290_RTC_TIME_YEAR_WID              (8)

 

 #define ZX234290_RTC_TIME_WEEKDAY_LSH           (0)

 #define ZX234290_RTC_TIME_WEEKDAY_WID           (3)

diff --git a/ap/os/linux/linux-3.4.x/drivers/staging/android/Kconfig b/ap/os/linux/linux-3.4.x/drivers/staging/android/Kconfig
old mode 100644
new mode 100755
index 43d17c2..e66333a
--- a/ap/os/linux/linux-3.4.x/drivers/staging/android/Kconfig
+++ b/ap/os/linux/linux-3.4.x/drivers/staging/android/Kconfig
@@ -87,6 +87,10 @@
 	  elapsed realtime, and a non-wakeup alarm on the monotonic clock.
 	  Also exports the alarm interface to user-space.
 
+config ANDROID_BINDER_RPC
+	bool "Android Binder RPC Driver"
+	default n
+	
 endif # if ANDROID
 
 endmenu
diff --git a/ap/os/linux/linux-3.4.x/drivers/staging/android/Makefile b/ap/os/linux/linux-3.4.x/drivers/staging/android/Makefile
old mode 100644
new mode 100755
index 8769e32..8f9caaf
--- a/ap/os/linux/linux-3.4.x/drivers/staging/android/Makefile
+++ b/ap/os/linux/linux-3.4.x/drivers/staging/android/Makefile
@@ -11,5 +11,6 @@
 obj-$(CONFIG_ANDROID_SWITCH)		+= switch/
 obj-$(CONFIG_ANDROID_INTF_ALARM_DEV)	+= alarm-dev.o
 obj-$(CONFIG_PERSISTENT_TRACER)		+= trace_persistent.o
+obj-$(CONFIG_ANDROID_BINDER_RPC)	+= binder_rpc.o
 
 CFLAGS_REMOVE_trace_persistent.o = -pg
diff --git a/ap/os/linux/linux-3.4.x/drivers/staging/android/binder.c b/ap/os/linux/linux-3.4.x/drivers/staging/android/binder.c
old mode 100644
new mode 100755
index c831dcc..aab6c15
--- a/ap/os/linux/linux-3.4.x/drivers/staging/android/binder.c
+++ b/ap/os/linux/linux-3.4.x/drivers/staging/android/binder.c
@@ -36,6 +36,13 @@
 
 #include "binder.h"
 #include "binder_trace.h"
+#ifdef CONFIG_ANDROID_BINDER_RPC
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <asm-generic/mman-common.h>
+
+#include "binder_rpc.h"
+#endif
 
 static DEFINE_MUTEX(binder_main_lock);
 static DEFINE_MUTEX(binder_deferred_lock);
@@ -51,7 +58,38 @@
 static uid_t binder_context_mgr_uid = -1;
 static int binder_last_id;
 static struct workqueue_struct *binder_deferred_workqueue;
+#ifdef CONFIG_ANDROID_BINDER_RPC
+/***********************************************************************
+        BINDER RPC DEFINE START
+***********************************************************************/
+#define BINDER_RPC_IGNORE_PRIV  (0xFFFFFFFF)
+struct binder_transaction;
+struct binder_proc;
+struct binder_thread;
 
+struct binder_transaction_entry {
+	struct list_head list;
+	struct binder_transaction *t;
+};
+struct binder_rpc_operations_struct binder_rpc_ops;
+
+struct binder_proc *rpc_own_proc = NULL;
+struct binder_proc *rpc_proc = NULL;
+struct binder_thread *rpc_thread = NULL;
+
+static int binder_init_rpc(struct binder_proc *own_proc);
+static int binder_deinit_rpc(void);
+static struct binder_proc *binder_get_rpcproc(void);
+static struct binder_thread *binder_get_rpcthread(void);
+static void binder_rpc_dequeue_todo(struct binder_transaction *t,
+			  struct binder_thread *target_thread);
+static void binder_rpc_enqueue_todo(struct binder_transaction *t,
+			   struct binder_thread *target_thread);
+
+/***********************************************************************
+        BINDER RPC DEFINE END
+***********************************************************************/
+#endif
 #define BINDER_DEBUG_ENTRY(name) \
 static int binder_##name##_open(struct inode *inode, struct file *file) \
 { \
@@ -177,6 +215,8 @@
 	int to_node;
 	int data_size;
 	int offsets_size;
+	int return_error_line;
+	uint32_t return_error;
 };
 struct binder_transaction_log {
 	int next;
@@ -358,6 +398,10 @@
 	long	priority;
 	long	saved_priority;
 	uid_t	sender_euid;
+#ifdef CONFIG_ANDROID_BINDER_RPC	
+	/*¹ØÁªremote tr,ÓÃÓÚÏìӦʱ²éÕÒremote target*/
+	binder_uintptr_t remote_priv;
+#endif
 };
 
 static void
@@ -1022,7 +1066,10 @@
 			node->local_strong_refs++;
 		if (!node->has_strong_ref && target_list) {
 			list_del_init(&node->work.entry);
-			list_add_tail(&node->work.entry, target_list);
+#ifdef CONFIG_ANDROID_BINDER_RPC			
+			if(target_list != (&(binder_get_rpcthread()->todo)))
+#endif				
+				list_add_tail(&node->work.entry, target_list);
 		}
 	} else {
 		if (!internal)
@@ -1033,7 +1080,10 @@
 					"for %d\n", node->debug_id);
 				return -EINVAL;
 			}
-			list_add_tail(&node->work.entry, target_list);
+#ifdef CONFIG_ANDROID_BINDER_RPC			
+			if(target_list != (&(binder_get_rpcthread()->todo)))
+#endif				
+				list_add_tail(&node->work.entry, target_list);
 		}
 	}
 	return 0;
@@ -1253,7 +1303,11 @@
 static void binder_pop_transaction(struct binder_thread *target_thread,
 				   struct binder_transaction *t)
 {
-	if (target_thread) {
+	if (target_thread
+#ifdef CONFIG_ANDROID_BINDER_RPC		
+		&& target_thread != binder_get_rpcthread()
+#endif		
+		) {
 		BUG_ON(target_thread->transaction_stack != t);
 		BUG_ON(target_thread->transaction_stack->from != target_thread);
 		target_thread->transaction_stack =
@@ -1290,7 +1344,21 @@
 
 				binder_pop_transaction(target_thread, t);
 				target_thread->return_error = error_code;
+#ifdef CONFIG_ANDROID_BINDER_RPC		
+				if(target_thread == binder_get_rpcthread()) {
+					struct binder_rpc_operations_info ops_info;
+							
+					ops_info.tr = NULL;					
+					ops_info.cmd = target_thread->return_error;
+					ops_info.priv = t->remote_priv;
+
+					/*send error to remote thread*/
+					binder_rpc_ops.binder_return_error(&ops_info, 1);
+				}
+#else				
 				wake_up_interruptible(&target_thread->wait);
+#endif
+
 			} else {
 				printk(KERN_ERR "binder: reply failed, target "
 					"thread, %d:%d, has error code %d "
@@ -1411,7 +1479,11 @@
 	wait_queue_head_t *target_wait;
 	struct binder_transaction *in_reply_to = NULL;
 	struct binder_transaction_log_entry *e;
-	uint32_t return_error;
+	uint32_t return_error;	
+	uint32_t return_error_line;
+#ifdef CONFIG_ANDROID_BINDER_RPC	
+	u32 fp_handle = 0;
+#endif
 
 	e = binder_transaction_log_add(&binder_transaction_log);
 	e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY);
@@ -1428,6 +1500,7 @@
 					  "with no transaction stack\n",
 					  proc->pid, thread->pid);
 			return_error = BR_FAILED_REPLY;
+			return_error_line = __LINE__;
 			goto err_empty_call_stack;
 		}
 		binder_set_nice(in_reply_to->saved_priority);
@@ -1441,6 +1514,7 @@
 				in_reply_to->to_thread ?
 				in_reply_to->to_thread->pid : 0);
 			return_error = BR_FAILED_REPLY;
+			return_error_line = __LINE__;
 			in_reply_to = NULL;
 			goto err_bad_call_stack;
 		}
@@ -1448,9 +1522,14 @@
 		target_thread = in_reply_to->from;
 		if (target_thread == NULL) {
 			return_error = BR_DEAD_REPLY;
+			return_error_line = __LINE__;
 			goto err_dead_binder;
 		}
-		if (target_thread->transaction_stack != in_reply_to) {
+		if (target_thread->transaction_stack != in_reply_to
+#ifdef CONFIG_ANDROID_BINDER_RPC			
+			&& target_thread != binder_get_rpcthread()
+#endif						
+			) {
 			binder_user_error("binder: %d:%d got reply transaction "
 				"with bad target transaction stack %d, "
 				"expected %d\n",
@@ -1459,6 +1538,7 @@
 				target_thread->transaction_stack->debug_id : 0,
 				in_reply_to->debug_id);
 			return_error = BR_FAILED_REPLY;
+			return_error_line = __LINE__;
 			in_reply_to = NULL;
 			target_thread = NULL;
 			goto err_dead_binder;
@@ -1473,6 +1553,7 @@
 					"transaction to invalid handle\n",
 					proc->pid, thread->pid);
 				return_error = BR_FAILED_REPLY;
+				return_error_line = __LINE__;
 				goto err_invalid_target_handle;
 			}
 			target_node = ref->node;
@@ -1480,6 +1561,7 @@
 			target_node = binder_context_mgr_node;
 			if (target_node == NULL) {
 				return_error = BR_DEAD_REPLY;
+				return_error_line = __LINE__;
 				goto err_no_context_mgr_node;
 			}
 		}
@@ -1487,9 +1569,19 @@
 		target_proc = target_node->proc;
 		if (target_proc == NULL) {
 			return_error = BR_DEAD_REPLY;
+			return_error_line = __LINE__;
 			goto err_dead_binder;
 		}
-		if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {
+#ifdef CONFIG_ANDROID_BINDER_RPC
+		if(target_proc == binder_get_rpcproc()) {
+			target_thread = binder_get_rpcthread();
+		}
+#endif		
+		if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack
+#ifdef CONFIG_ANDROID_BINDER_RPC			
+			&& (thread != binder_get_rpcthread())
+#endif			
+		) {
 			struct binder_transaction *tmp;
 			tmp = thread->transaction_stack;
 			if (tmp->to_thread != thread) {
@@ -1501,6 +1593,7 @@
 					tmp->to_thread ?
 					tmp->to_thread->pid : 0);
 				return_error = BR_FAILED_REPLY;
+				return_error_line = __LINE__;
 				goto err_bad_call_stack;
 			}
 			while (tmp) {
@@ -1524,6 +1617,7 @@
 	t = kzalloc(sizeof(*t), GFP_KERNEL);
 	if (t == NULL) {
 		return_error = BR_FAILED_REPLY;
+		return_error_line = __LINE__;
 		goto err_alloc_t_failed;
 	}
 	binder_stats_created(BINDER_STAT_TRANSACTION);
@@ -1531,6 +1625,7 @@
 	tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
 	if (tcomplete == NULL) {
 		return_error = BR_FAILED_REPLY;
+		return_error_line = __LINE__;
 		goto err_alloc_tcomplete_failed;
 	}
 	binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE);
@@ -1572,6 +1667,7 @@
 		tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
 	if (t->buffer == NULL) {
 		return_error = BR_FAILED_REPLY;
+		return_error_line = __LINE__;
 		goto err_binder_alloc_buf_failed;
 	}
 	t->buffer->allow_user_free = 0;
@@ -1588,12 +1684,14 @@
 		binder_user_error("binder: %d:%d got transaction with invalid "
 			"data ptr\n", proc->pid, thread->pid);
 		return_error = BR_FAILED_REPLY;
+		return_error_line = __LINE__;
 		goto err_copy_data_failed;
 	}
 	if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) {
 		binder_user_error("binder: %d:%d got transaction with invalid "
 			"offsets ptr\n", proc->pid, thread->pid);
 		return_error = BR_FAILED_REPLY;
+		return_error_line = __LINE__;
 		goto err_copy_data_failed;
 	}
 	if (!IS_ALIGNED(tr->offsets_size, sizeof(size_t))) {
@@ -1601,6 +1699,7 @@
 			"invalid offsets size, %zd\n",
 			proc->pid, thread->pid, tr->offsets_size);
 		return_error = BR_FAILED_REPLY;
+		return_error_line = __LINE__;
 		goto err_bad_offset;
 	}
 	off_end = (void *)offp + tr->offsets_size;
@@ -1613,6 +1712,7 @@
 				"invalid offset, %zd\n",
 				proc->pid, thread->pid, *offp);
 			return_error = BR_FAILED_REPLY;
+			return_error_line = __LINE__;
 			goto err_bad_offset;
 		}
 		fp = (struct flat_binder_object *)(t->buffer->data + *offp);
@@ -1625,6 +1725,7 @@
 				node = binder_new_node(proc, fp->binder, fp->cookie);
 				if (node == NULL) {
 					return_error = BR_FAILED_REPLY;
+					return_error_line = __LINE__;
 					goto err_binder_new_node_failed;
 				}
 				node->min_priority = fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
@@ -1641,6 +1742,7 @@
 			ref = binder_get_ref_for_node(target_proc, node);
 			if (ref == NULL) {
 				return_error = BR_FAILED_REPLY;
+				return_error_line = __LINE__;
 				goto err_binder_get_ref_for_node_failed;
 			}
 			if (fp->type == BINDER_TYPE_BINDER)
@@ -1656,6 +1758,39 @@
 				     "        node %d u%p -> ref %d desc %d\n",
 				     node->debug_id, node->ptr, ref->debug_id,
 				     ref->desc);
+#ifdef CONFIG_ANDROID_BINDER_RPC
+			/*1.service add (tr->target.handle == 0 && tr->code == 3)
+			 *2.client add listen (target_thread == rpc_thread)
+			*/
+			if((proc != binder_get_rpcproc() || thread != binder_get_rpcthread()) &&
+				NULL != binder_rpc_ops.binder_broadcast) {
+				struct binder_rpc_operations_info ops_info;
+				
+				fp_handle = fp->handle;
+				/*tagret isn't rpc_proc. err?*/
+				/**/
+				binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,"%s %d 0x%x debug_id:%d\n",__FUNCTION__,fp->handle, fp->type, node->debug_id);
+				if(NULL != node &&
+					((tr->target.handle == 0 && tr->code == ADD_SERVICE_TRANSACTION))) {
+					ref = binder_get_ref_for_node(binder_get_rpcproc(), node);
+					if (NULL != ref) {						
+						fp_handle = ref->desc;
+
+						ops_info.cmd = BC_TRANSACTION;
+						ops_info.tr = tr;
+						ops_info.priv = BINDER_RPC_IGNORE_PRIV;
+						
+						if(0 != binder_rpc_ops.binder_broadcast(&ops_info, fp_handle)) {
+							binder_delete_ref(ref);
+							binder_user_error("%s binder_broadcast fail. \n",__FUNCTION__);
+						}
+					}
+					else {
+						binder_user_error("%s binder_get_ref_for_node fail,\n",__FUNCTION__);
+					}
+				}
+			}
+#endif				
 		} break;
 		case BINDER_TYPE_HANDLE:
 		case BINDER_TYPE_WEAK_HANDLE: {
@@ -1666,6 +1801,7 @@
 					"handle, %ld\n", proc->pid,
 					thread->pid, fp->handle);
 				return_error = BR_FAILED_REPLY;
+				return_error_line = __LINE__;
 				goto err_binder_get_ref_failed;
 			}
 			if (ref->node->proc == target_proc) {
@@ -1686,6 +1822,7 @@
 				new_ref = binder_get_ref_for_node(target_proc, ref->node);
 				if (new_ref == NULL) {
 					return_error = BR_FAILED_REPLY;
+					return_error_line = __LINE__;
 					goto err_binder_get_ref_for_node_failed;
 				}
 				fp->handle = new_ref->desc;
@@ -1708,12 +1845,14 @@
 					binder_user_error("binder: %d:%d got reply with fd, %ld, but target does not allow fds\n",
 						proc->pid, thread->pid, fp->handle);
 					return_error = BR_FAILED_REPLY;
+					return_error_line = __LINE__;
 					goto err_fd_not_allowed;
 				}
 			} else if (!target_node->accept_fds) {
 				binder_user_error("binder: %d:%d got transaction with fd, %ld, but target does not allow fds\n",
 					proc->pid, thread->pid, fp->handle);
 				return_error = BR_FAILED_REPLY;
+				return_error_line = __LINE__;
 				goto err_fd_not_allowed;
 			}
 
@@ -1722,12 +1861,14 @@
 				binder_user_error("binder: %d:%d got transaction with invalid fd, %ld\n",
 					proc->pid, thread->pid, fp->handle);
 				return_error = BR_FAILED_REPLY;
+				return_error_line = __LINE__;
 				goto err_fget_failed;
 			}
 			target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
 			if (target_fd < 0) {
 				fput(file);
 				return_error = BR_FAILED_REPLY;
+				return_error_line = __LINE__;
 				goto err_get_unused_fd_failed;
 			}
 			task_fd_install(target_proc, target_fd, file);
@@ -1743,17 +1884,79 @@
 				"n with invalid object type, %lx\n",
 				proc->pid, thread->pid, fp->type);
 			return_error = BR_FAILED_REPLY;
+			return_error_line = __LINE__;
 			goto err_bad_object_type;
 		}
 	}
 	if (reply) {
 		BUG_ON(t->buffer->async_transaction != 0);
-		binder_pop_transaction(target_thread, in_reply_to);
+#ifdef CONFIG_ANDROID_BINDER_RPC		
+		if(target_thread == binder_get_rpcthread() && target_proc == binder_get_rpcproc()) {
+			binder_rpc_dequeue_todo(in_reply_to, target_thread);
+			if(NULL != binder_rpc_ops.binder_reply) {
+				struct binder_rpc_operations_info ops_info;
+				struct binder_buffer *tmp_buffer = t->buffer;
+				
+				ops_info.cmd = BC_REPLY;
+				ops_info.tr = tr;
+				ops_info.priv = in_reply_to->remote_priv;
+				
+				/*free t*/
+				if (tmp_buffer->transaction) {
+					binder_debug(BINDER_DEBUG_TRANSACTION,"%s %d 0x%x\n",__FUNCTION__, __LINE__, tmp_buffer);	
+					tmp_buffer->transaction->buffer = NULL;
+					tmp_buffer->transaction = NULL;
+				}
+				if (tmp_buffer->async_transaction && tmp_buffer->target_node) {
+					BUG_ON(!tmp_buffer->target_node->has_async_transaction);
+					if (list_empty(&tmp_buffer->target_node->async_todo))
+						tmp_buffer->target_node->has_async_transaction = 0;
+					else {
+						//list_move_tail(tmp_buffer->target_node->async_todo.next, &target_thread->todo);
+						binder_debug(BINDER_DEBUG_TRANSACTION,"%s %d\n",__FUNCTION__, __LINE__);				     		
+					}
+				}
+				trace_binder_transaction_buffer_release(tmp_buffer);
+
+				//binder_transaction_buffer_release(target_proc, tmp_buffer, NULL);
+
+				//t->buffer->transaction = NULL;
+				binder_free_buf(target_proc, tmp_buffer);
+				
+				binder_pop_transaction(NULL, t);	
+
+				binder_rpc_ops.binder_reply(&ops_info, fp_handle);
+			}
+
+			binder_pop_transaction(NULL, in_reply_to);
+		}
+		else {
+#endif		
+			binder_pop_transaction(target_thread, in_reply_to);
+#ifdef CONFIG_ANDROID_BINDER_RPC
+		}
+#endif		
 	} else if (!(t->flags & TF_ONE_WAY)) {
 		BUG_ON(t->buffer->async_transaction != 0);
 		t->need_reply = 1;
 		t->from_parent = thread->transaction_stack;
 		thread->transaction_stack = t;
+#ifdef CONFIG_ANDROID_BINDER_RPC		
+		if((target_proc == binder_get_rpcproc() && target_thread == binder_get_rpcthread()) &&
+			NULL != binder_rpc_ops.binder_transaction) {
+			struct binder_node *target_node = t->buffer->target_node;
+			struct binder_rpc_operations_info ops_info;
+				
+			ops_info.cmd = BC_TRANSACTION;
+			ops_info.tr = tr;
+			ops_info.priv = (binder_uintptr_t)t;
+			
+			binder_rpc_enqueue_todo(t, target_thread);
+			if(0 != binder_rpc_ops.binder_transaction(&ops_info,fp_handle, (void *)target_node->ptr, (void *)target_node->cookie)) {
+				binder_rpc_dequeue_todo(t, target_thread);
+			}
+		}
+#endif		
 	} else {
 		BUG_ON(target_node == NULL);
 		BUG_ON(t->buffer->async_transaction != 1);
@@ -1762,13 +1965,76 @@
 			target_wait = NULL;
 		} else
 			target_node->has_async_transaction = 1;
+#ifdef CONFIG_ANDROID_BINDER_RPC
+		if((target_proc == binder_get_rpcproc() && target_thread == binder_get_rpcthread()) &&
+			NULL != binder_rpc_ops.binder_transaction) {
+			struct binder_node *target_node = t->buffer->target_node;
+			struct binder_rpc_operations_info ops_info;
+			struct binder_buffer *tmp_buffer = t->buffer;
+				
+			ops_info.cmd = BC_TRANSACTION;
+			ops_info.tr = tr;
+			ops_info.priv = (binder_uintptr_t)t;
+
+			binder_rpc_enqueue_todo(t, target_thread);
+			if(0 != binder_rpc_ops.binder_transaction(&ops_info,fp_handle, (void *)target_node->ptr, (void *)target_node->cookie)) {
+				binder_rpc_dequeue_todo(t, target_thread);
+			}
+
+			/*free t*/
+			if (tmp_buffer->transaction) {
+				binder_debug(BINDER_DEBUG_TRANSACTION,"%s %d 0x%x\n",__FUNCTION__, __LINE__, tmp_buffer);	
+				tmp_buffer->transaction->buffer = NULL;
+				tmp_buffer->transaction = NULL;
+			}
+			if (tmp_buffer->async_transaction && tmp_buffer->target_node) {
+				BUG_ON(!tmp_buffer->target_node->has_async_transaction);
+				if (list_empty(&tmp_buffer->target_node->async_todo))
+					tmp_buffer->target_node->has_async_transaction = 0;
+				else {
+					//list_move_tail(tmp_buffer->target_node->async_todo.next, &target_thread->todo);
+					binder_debug(BINDER_DEBUG_TRANSACTION,"%s %d\n",__FUNCTION__, __LINE__);				     		
+				}
+			}
+			trace_binder_transaction_buffer_release(tmp_buffer);
+
+			binder_free_buf(target_proc, tmp_buffer);
+			
+			binder_pop_transaction(NULL, t);
+		}
+#endif			
 	}
-	t->work.type = BINDER_WORK_TRANSACTION;
-	list_add_tail(&t->work.entry, target_list);
-	tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
-	list_add_tail(&tcomplete->entry, &thread->todo);
+#ifdef CONFIG_ANDROID_BINDER_RPC
+	if(target_thread != binder_get_rpcthread()) {
+#endif		
+		t->work.type = BINDER_WORK_TRANSACTION;
+		list_add_tail(&t->work.entry, target_list);
+#ifdef CONFIG_ANDROID_BINDER_RPC
+	}
+#endif
+		
+#ifdef CONFIG_ANDROID_BINDER_RPC
+	if(thread != binder_get_rpcthread()) {
+#endif		
+		tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
+		list_add_tail(&tcomplete->entry, &thread->todo);
+				
+#ifdef CONFIG_ANDROID_BINDER_RPC		
+	}
+	else {
+		kfree(tcomplete);
+	}
+#endif	
+
+#ifdef CONFIG_ANDROID_BINDER_RPC
+	if(target_thread != binder_get_rpcthread()) {
+#endif
 	if (target_wait)
 		wake_up_interruptible(target_wait);
+
+#ifdef CONFIG_ANDROID_BINDER_RPC
+	}
+#endif	
 	return;
 
 err_get_unused_fd_failed:
@@ -1802,12 +2068,16 @@
 		     tr->data_size, tr->offsets_size);
 
 	{
-		struct binder_transaction_log_entry *fe;
+		struct binder_transaction_log_entry *fe;	
+		
+		e->return_error = return_error;
+		e->return_error_line = return_error_line;
 		fe = binder_transaction_log_add(&binder_transaction_log_failed);
 		*fe = *e;
 	}
 
 	BUG_ON(thread->return_error != BR_OK);
+	binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,"return_error_line %d \n",return_error_line);
 	if (in_reply_to) {
 		thread->return_error = BR_TRANSACTION_COMPLETE;
 		binder_send_failed_reply(in_reply_to, return_error);
@@ -2822,6 +3092,11 @@
 	if (thread)
 		thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
 	binder_unlock(__func__);
+#ifdef CONFIG_ANDROID_BINDER_RPC	
+	if(BINDER_SET_CONTEXT_MGR == cmd && NULL == binder_get_rpcproc()) {
+		binder_init_rpc(proc);
+	}
+#endif	
 	wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
 	if (ret && ret != -ERESTARTSYS)
 		printk(KERN_INFO "binder: %d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
@@ -3023,6 +3298,11 @@
 	struct binder_proc *proc = filp->private_data;
 	debugfs_remove(proc->debugfs_entry);
 	binder_defer_work(proc, BINDER_DEFERRED_RELEASE);
+#ifdef CONFIG_ANDROID_BINDER_RPC	
+	if(proc == rpc_own_proc) {
+		binder_deinit_rpc();
+	}
+#endif	
 
 	return 0;
 }
@@ -3061,6 +3341,12 @@
 		rb_erase(&node->rb_node, &proc->nodes);
 		list_del_init(&node->work.entry);
 		binder_release_work(&node->async_todo);
+		
+#ifdef CONFIG_ANDROID_BINDER_RPC
+		if(binder_rpc_ops.binder_release) {
+			binder_rpc_ops.binder_release((void *)proc, (void *)node);
+		}
+#endif		
 		if (hlist_empty(&node->refs)) {
 			kfree(node);
 			binder_stats_deleted(BINDER_STAT_NODE);
@@ -3206,6 +3492,854 @@
 	}
 	mutex_unlock(&binder_deferred_lock);
 }
+#ifdef CONFIG_ANDROID_BINDER_RPC
+/***********************************************************************
+        BINDER RPC API START
+***********************************************************************/
+static int binder_init_rpc(struct binder_proc *own_proc)
+{
+	struct binder_proc *proc;
+	unsigned long unused;
+	unsigned long mmap_base;
+	unsigned long mmap_size;
+
+	struct file *pfile = filp_open("/dev/binder",O_RDWR,0);
+	
+	if(NULL == pfile) {
+		binder_user_error("%s: filp_open fail.\n", __func__);
+		return -1;
+	}
+	proc = pfile->private_data;
+
+	mmap_size = 16*PAGE_SIZE;
+	mmap_base = do_mmap(pfile, 0, mmap_size,
+				       PROT_READ,
+				       MAP_PRIVATE | MAP_NORESERVE, 0);
+	
+	rpc_proc = proc;
+	rpc_own_proc = own_proc;
+	return binder_rpc_init((void *)proc, pfile, &binder_rpc_ops);
+}
+
+static int binder_deinit_rpc(void)
+{
+	struct binder_proc *proc = binder_get_rpcproc();
+	struct vm_area_struct *vma = proc->vma;
+
+	binder_debug(BINDER_DEBUG_OPEN_CLOSE,"%s rpc proc %d release.\n",__FUNCTION__, proc->pid);
+	binder_rpc_deinit(vma);	
+
+	rpc_proc = NULL;
+	rpc_own_proc = NULL;
+	return 0;	
+}
+
+static struct binder_proc *binder_get_rpcproc(void)
+{
+	return rpc_proc;
+}
+static struct binder_thread *binder_get_rpcthread(void)
+{
+	return rpc_thread;
+}
+
+/*ÓÃÓÚÌí¼ÓÉÏÐÐbinder_transactionµ½target_thread->todoÁ´±í*/
+static void binder_rpc_enqueue_todo(struct binder_transaction *t,
+			   struct binder_thread *target_thread)
+{
+	struct binder_transaction_entry *entry;
+	struct list_head *target_list = &target_thread->todo;
+	
+	BUG_ON(target_list == NULL || t == NULL);
+
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (entry == NULL) {
+		return;
+	}
+	entry->t = t;
+
+	//binder_inner_proc_lock(target_thread->proc);
+	list_add_tail(&entry->list, target_list);
+	//binder_inner_proc_unlock(target_thread->proc);
+	binder_debug(BINDER_DEBUG_TRANSACTION, "%s add %x to thread(%d) todo", __FUNCTION__, t, target_thread->pid);
+}
+/*ÓÃÓÚɾ³ýÉÏÐÐbinder_transaction½Úµã*/			   
+static void binder_rpc_dequeue_todo(struct binder_transaction *t,
+			  struct binder_thread *target_thread)
+{
+	struct binder_transaction_entry *entry,*tmp_entry;
+	struct binder_transaction *tmp_t;
+	struct list_head *target_list = &target_thread->todo;
+
+	//binder_inner_proc_lock(target_thread->proc);
+	list_for_each_entry_safe(entry,tmp_entry,target_list,list) {
+		tmp_t = entry->t;
+		if(t == tmp_t) {
+			list_del(&entry->list);
+			kfree(entry);
+			binder_debug(BINDER_DEBUG_TRANSACTION, "%s del %x from thread(%d) todo", __FUNCTION__, t, target_thread->pid);
+			return;
+		}
+	}
+	//binder_inner_proc_unlock(target_thread->proc);
+}
+			  
+/*ÓÃÓÚ²éÕÒÆ¥ÅäÏÂÐÐBC_REPLYÃüÁîʱbinder_transaction*/			  
+static struct binder_transaction *binder_rpc_find_todo_by_priv(binder_uintptr_t priv,
+			   											struct binder_thread *target_thread)
+{
+	struct binder_transaction_entry *entry,*tmp_entry;
+	struct binder_transaction *tmp_t;
+	struct list_head *target_list = &target_thread->todo;
+
+	//binder_inner_proc_lock(target_thread->proc);
+	list_for_each_entry_safe(entry,tmp_entry,target_list,list) {
+		tmp_t = entry->t;
+		if(priv == (binder_uintptr_t)tmp_t) {
+			list_del(&entry->list);
+			kfree(entry);
+			//binder_inner_proc_unlock(target_thread->proc);
+			binder_debug(BINDER_DEBUG_TRANSACTION, "%s del %x from thread(%d) todo", __FUNCTION__, priv, target_thread->pid);
+			return tmp_t;
+		}
+	}
+
+	//binder_inner_proc_unlock(target_thread->proc);
+	return NULL;
+}
+
+			  
+void *binder_rpc_get_thread(void *brpc_proc)
+{
+	rpc_thread = binder_get_thread(brpc_proc);
+
+	return (void *)rpc_thread;
+}
+int binder_rpc_thread_write(void *brpc_proc,
+			binder_uintptr_t brpc_buffer, size_t size,
+			binder_size_t *consumed)
+{
+	struct binder_proc *proc = brpc_proc;
+	struct binder_thread *thread = binder_get_thread(proc);
+	int ret = 0;
+	
+	binder_lock(__func__);
+	ret=  binder_thread_write(proc, thread, brpc_buffer, size, consumed);
+	binder_unlock(__func__);
+
+	return ret;
+}
+/*ÏÂÐÐtransanction´¦Àíº¯Êý£¬ÉÏÐÐtransanction´¦ÀíÓÉrpc_transactionº¯Êý´¦Àí*/
+void binder_rpc_transaction(void *prpc_proc,
+				   void *prpc_thread,
+				   struct binder_transaction_data *tr, int reply,
+				   binder_size_t extra_buffers_size,
+				   binder_uintptr_t priv)
+{
+	struct binder_proc *proc = (struct binder_proc *)prpc_proc;
+	struct binder_thread *thread = (struct binder_thread *)prpc_thread;
+	struct binder_transaction *t;
+	struct binder_work *tcomplete;
+	size_t *offp, *off_end;
+	struct binder_proc *target_proc;
+	struct binder_thread *target_thread = NULL;
+	struct binder_node *target_node = NULL;
+	struct list_head *target_list;
+	wait_queue_head_t *target_wait;
+	struct binder_transaction *in_reply_to = NULL;
+	struct binder_transaction_log_entry *e;
+	uint32_t return_error;
+	uint32_t return_error_line;
+
+	binder_lock(__func__);
+	
+	/*ignore binder_rpc_ops.binder_broadcast reply*/
+	if(reply && (priv == BINDER_RPC_IGNORE_PRIV)) {
+		binder_unlock(__func__);
+		return;
+	}
+	
+	e = binder_transaction_log_add(&binder_transaction_log);
+	e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY);
+	e->from_proc = proc->pid;
+	e->from_thread = thread->pid;
+	e->target_handle = tr->target.handle;
+	e->data_size = tr->data_size;
+	e->offsets_size = tr->offsets_size;
+
+	if (reply) {
+		if((thread == binder_get_rpcthread() && proc == binder_get_rpcproc())) {			
+			in_reply_to = binder_rpc_find_todo_by_priv(priv, thread);			
+		}
+		else {
+			in_reply_to = thread->transaction_stack;
+		}
+
+		if (in_reply_to == NULL) {
+			binder_user_error("binder: %d:%d got reply transaction "
+					  "with no transaction stack\n",
+					  proc->pid, thread->pid);
+			return_error = BR_FAILED_REPLY;
+			return_error_line = __LINE__;
+			goto err_empty_call_stack;
+		}
+		binder_set_nice(in_reply_to->saved_priority);
+		if (in_reply_to->to_thread != thread) {
+			binder_user_error("binder: %d:%d got reply transaction "
+				"with bad transaction stack,"
+				" transaction %d has target %d:%d\n",
+				proc->pid, thread->pid, in_reply_to->debug_id,
+				in_reply_to->to_proc ?
+				in_reply_to->to_proc->pid : 0,
+				in_reply_to->to_thread ?
+				in_reply_to->to_thread->pid : 0);
+			return_error = BR_FAILED_REPLY;
+			return_error_line = __LINE__;
+			in_reply_to = NULL;
+			goto err_bad_call_stack;
+		}
+		thread->transaction_stack = in_reply_to->to_parent;
+		target_thread = in_reply_to->from;
+		if (target_thread == NULL) {
+			return_error = BR_DEAD_REPLY;
+			return_error_line = __LINE__;
+			goto err_dead_binder;
+		}
+		if (target_thread->transaction_stack != in_reply_to) {
+			binder_user_error("binder: %d:%d got reply transaction "
+				"with bad target transaction stack %d, "
+				"expected %d\n",
+				proc->pid, thread->pid,
+				target_thread->transaction_stack ?
+				target_thread->transaction_stack->debug_id : 0,
+				in_reply_to->debug_id);
+			return_error = BR_FAILED_REPLY;
+			return_error_line = __LINE__;
+			in_reply_to = NULL;
+			target_thread = NULL;
+			goto err_dead_binder;
+		}
+		target_proc = target_thread->proc;
+	} else {
+		if (tr->target.handle) {
+			struct binder_ref *ref;
+			ref = binder_get_ref(proc, tr->target.handle);
+			if (ref == NULL) {
+				binder_user_error("binder: %d:%d got "
+					"transaction to invalid handle\n",
+					proc->pid, thread->pid);
+				return_error = BR_FAILED_REPLY;
+				return_error_line = __LINE__;
+				//panic("binder_get_ref fail.\n");
+				goto err_invalid_target_handle;
+			}
+			target_node = ref->node;
+		} else {
+			target_node = binder_context_mgr_node;
+			if (target_node == NULL) {
+				return_error = BR_DEAD_REPLY;
+				return_error_line = __LINE__;
+				goto err_no_context_mgr_node;
+			}
+		}
+		e->to_node = target_node->debug_id;
+		target_proc = target_node->proc;
+		if (target_proc == NULL) {
+			return_error = BR_DEAD_REPLY;
+			return_error_line = __LINE__;
+			goto err_dead_binder;
+		}
+		if(target_proc == binder_get_rpcproc()) {
+			target_thread = binder_get_rpcthread();
+		}
+		if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack && (thread != binder_get_rpcthread())) {
+			struct binder_transaction *tmp;
+			tmp = thread->transaction_stack;
+			if (tmp->to_thread != thread) {
+				binder_user_error("binder: %d:%d got new "
+					"transaction with bad transaction stack"
+					", transaction %d has target %d:%d\n",
+					proc->pid, thread->pid, tmp->debug_id,
+					tmp->to_proc ? tmp->to_proc->pid : 0,
+					tmp->to_thread ?
+					tmp->to_thread->pid : 0);
+				return_error = BR_FAILED_REPLY;
+				return_error_line = __LINE__;
+				goto err_bad_call_stack;
+			}
+			while (tmp) {
+				if (tmp->from && tmp->from->proc == target_proc)
+					target_thread = tmp->from;
+				tmp = tmp->from_parent;
+			}
+		}
+	}
+	if (target_thread) {
+		e->to_thread = target_thread->pid;
+		target_list = &target_thread->todo;
+		target_wait = &target_thread->wait;
+	} else {
+		target_list = &target_proc->todo;
+		target_wait = &target_proc->wait;
+	}
+	e->to_proc = target_proc->pid;
+
+	/* TODO: reuse incoming transaction for reply */
+	t = kzalloc(sizeof(*t), GFP_KERNEL);
+	if (t == NULL) {
+		return_error = BR_FAILED_REPLY;
+		return_error_line = __LINE__;
+		goto err_alloc_t_failed;
+	}
+	binder_stats_created(BINDER_STAT_TRANSACTION);
+
+	tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
+	if (tcomplete == NULL) {
+		return_error = BR_FAILED_REPLY;
+		return_error_line = __LINE__;
+		goto err_alloc_tcomplete_failed;
+	}
+	binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE);
+
+	t->debug_id = ++binder_last_id;
+	e->debug_id = t->debug_id;
+
+	if (reply)
+		binder_debug(BINDER_DEBUG_TRANSACTION,
+				 "binder: %d:%d BC_REPLY %d -> %d:%d, "
+				 "data %p-%p size %zd-%zd\n",
+				 proc->pid, thread->pid, t->debug_id,
+				 target_proc->pid, target_thread->pid,
+				 tr->data.ptr.buffer, tr->data.ptr.offsets,
+				 tr->data_size, tr->offsets_size);
+	else
+		binder_debug(BINDER_DEBUG_TRANSACTION,
+				 "binder: %d:%d BC_TRANSACTION %d -> "
+				 "%d - node %d, data %p-%p size %zd-%zd\n",
+				 proc->pid, thread->pid, t->debug_id,
+				 target_proc->pid, target_node->debug_id,
+				 tr->data.ptr.buffer, tr->data.ptr.offsets,
+				 tr->data_size, tr->offsets_size);
+
+	if (!reply && !(tr->flags & TF_ONE_WAY))
+		t->from = thread;
+	else
+		t->from = NULL;
+	t->sender_euid = proc->tsk->cred->euid;
+	t->to_proc = target_proc;
+	t->to_thread = target_thread;
+	t->code = tr->code;
+	t->flags = tr->flags;
+	t->priority = task_nice(current);
+
+	trace_binder_transaction(reply, t, target_node);
+
+	t->buffer = binder_alloc_buf(target_proc, tr->data_size,
+		tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
+	if (t->buffer == NULL) {
+		return_error = BR_FAILED_REPLY;
+		return_error_line = __LINE__;
+		goto err_binder_alloc_buf_failed;
+	}
+	t->buffer->allow_user_free = 0;
+	t->buffer->debug_id = t->debug_id;
+	t->buffer->transaction = t;
+	t->buffer->target_node = target_node;
+	trace_binder_transaction_alloc_buf(t->buffer);
+	if (target_node)
+		binder_inc_node(target_node, 1, 0, NULL);
+
+	offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *)));
+
+	if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) {
+		binder_user_error("binder: %d:%d got transaction with invalid "
+			"data ptr\n", proc->pid, thread->pid);
+		return_error = BR_FAILED_REPLY;
+		return_error_line = __LINE__;
+		goto err_copy_data_failed;
+	}
+	if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) {
+		binder_user_error("binder: %d:%d got transaction with invalid "
+			"offsets ptr\n", proc->pid, thread->pid);
+		return_error = BR_FAILED_REPLY;
+		return_error_line = __LINE__;
+		goto err_copy_data_failed;
+	}
+	if (!IS_ALIGNED(tr->offsets_size, sizeof(size_t))) {
+		binder_user_error("binder: %d:%d got transaction with "
+			"invalid offsets size, %zd\n",
+			proc->pid, thread->pid, tr->offsets_size);
+		return_error = BR_FAILED_REPLY;
+		return_error_line = __LINE__;
+		goto err_bad_offset;
+	}
+	off_end = (void *)offp + tr->offsets_size;
+	for (; offp < off_end; offp++) {
+		struct flat_binder_object *fp;
+		if (*offp > t->buffer->data_size - sizeof(*fp) ||
+			t->buffer->data_size < sizeof(*fp) ||
+			!IS_ALIGNED(*offp, sizeof(void *))) {
+			binder_user_error("binder: %d:%d got transaction with "
+				"invalid offset, %zd\n",
+				proc->pid, thread->pid, *offp);
+			return_error = BR_FAILED_REPLY;
+			return_error_line = __LINE__;
+			goto err_bad_offset;
+		}
+		fp = (struct flat_binder_object *)(t->buffer->data + *offp);
+		switch (fp->type) {
+		case BINDER_TYPE_BINDER:
+		case BINDER_TYPE_WEAK_BINDER: {
+			struct binder_ref *ref;
+			struct binder_node *node = binder_get_node(proc, fp->binder);
+			if (node == NULL) {
+				node = binder_new_node(proc, fp->binder, fp->cookie);
+				if (node == NULL) {
+					return_error = BR_FAILED_REPLY;
+					return_error_line = __LINE__;
+					goto err_binder_new_node_failed;
+				}
+				node->min_priority = fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
+				node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
+			}
+			if (fp->cookie != node->cookie) {
+				binder_user_error("binder: %d:%d sending u%p "
+					"node %d, cookie mismatch %p != %p\n",
+					proc->pid, thread->pid,
+					fp->binder, node->debug_id,
+					fp->cookie, node->cookie);
+				goto err_binder_get_ref_for_node_failed;
+			}
+			ref = binder_get_ref_for_node(target_proc, node);
+			if (ref == NULL) {
+				return_error = BR_FAILED_REPLY;
+				return_error_line = __LINE__;
+				goto err_binder_get_ref_for_node_failed;
+			}
+			if (fp->type == BINDER_TYPE_BINDER)
+				fp->type = BINDER_TYPE_HANDLE;
+			else
+				fp->type = BINDER_TYPE_WEAK_HANDLE;
+			fp->handle = ref->desc;
+			binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,
+					   &thread->todo);
+
+			trace_binder_transaction_node_to_ref(t, node, ref);
+			binder_debug(BINDER_DEBUG_TRANSACTION,
+					 "		  node %d u%p -> ref %d desc %d\n",
+					 node->debug_id, node->ptr, ref->debug_id,
+					 ref->desc);
+		} break;
+		case BINDER_TYPE_HANDLE:
+		case BINDER_TYPE_WEAK_HANDLE: {
+			struct binder_ref *ref = binder_get_ref(proc, fp->handle);
+			if (ref == NULL) {
+				binder_user_error("binder: %d:%d got "
+					"transaction with invalid "
+					"handle, %ld\n", proc->pid,
+					thread->pid, fp->handle);
+				return_error = BR_FAILED_REPLY;
+				return_error_line = __LINE__;
+				goto err_binder_get_ref_failed;
+			}
+			if (ref->node->proc == target_proc) {
+				if (fp->type == BINDER_TYPE_HANDLE)
+					fp->type = BINDER_TYPE_BINDER;
+				else
+					fp->type = BINDER_TYPE_WEAK_BINDER;
+				fp->binder = ref->node->ptr;
+				fp->cookie = ref->node->cookie;
+				binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
+				trace_binder_transaction_ref_to_node(t, ref);
+				binder_debug(BINDER_DEBUG_TRANSACTION,
+						 "		  ref %d desc %d -> node %d u%p\n",
+						 ref->debug_id, ref->desc, ref->node->debug_id,
+						 ref->node->ptr);
+			} else {
+				struct binder_ref *new_ref;
+				new_ref = binder_get_ref_for_node(target_proc, ref->node);
+				if (new_ref == NULL) {
+					return_error = BR_FAILED_REPLY;
+					return_error_line = __LINE__;
+					goto err_binder_get_ref_for_node_failed;
+				}
+				fp->handle = new_ref->desc;
+				binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
+				trace_binder_transaction_ref_to_ref(t, ref,
+									new_ref);
+				binder_debug(BINDER_DEBUG_TRANSACTION,
+						 "		  ref %d desc %d -> ref %d desc %d (node %d)\n",
+						 ref->debug_id, ref->desc, new_ref->debug_id,
+						 new_ref->desc, ref->node->debug_id);
+			}
+		} break;
+
+		case BINDER_TYPE_FD: {
+			int target_fd;
+			struct file *file;
+
+			if (reply) {
+				if (!(in_reply_to->flags & TF_ACCEPT_FDS)) {
+					binder_user_error("binder: %d:%d got reply with fd, %ld, but target does not allow fds\n",
+						proc->pid, thread->pid, fp->handle);
+					return_error = BR_FAILED_REPLY;
+					return_error_line = __LINE__;
+					goto err_fd_not_allowed;
+				}
+			} else if (!target_node->accept_fds) {
+				binder_user_error("binder: %d:%d got transaction with fd, %ld, but target does not allow fds\n",
+					proc->pid, thread->pid, fp->handle);
+				return_error = BR_FAILED_REPLY;
+				return_error_line = __LINE__;
+				goto err_fd_not_allowed;
+			}
+
+			file = fget(fp->handle);
+			if (file == NULL) {
+				binder_user_error("binder: %d:%d got transaction with invalid fd, %ld\n",
+					proc->pid, thread->pid, fp->handle);
+				return_error = BR_FAILED_REPLY;
+				return_error_line = __LINE__;
+				goto err_fget_failed;
+			}
+			target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
+			if (target_fd < 0) {
+				fput(file);
+				return_error = BR_FAILED_REPLY;
+				return_error_line = __LINE__;
+				goto err_get_unused_fd_failed;
+			}
+			task_fd_install(target_proc, target_fd, file);
+			trace_binder_transaction_fd(t, fp->handle, target_fd);
+			binder_debug(BINDER_DEBUG_TRANSACTION,
+					 "		  fd %ld -> %d\n", fp->handle, target_fd);
+			/* TODO: fput? */
+			fp->handle = target_fd;
+		} break;
+
+		default:
+			binder_user_error("binder: %d:%d got transactio"
+				"n with invalid object type, %lx\n",
+				proc->pid, thread->pid, fp->type);
+			return_error = BR_FAILED_REPLY;
+			return_error_line = __LINE__;
+			goto err_bad_object_type;
+		}
+	}
+	if (reply) {
+		BUG_ON(t->buffer->async_transaction != 0);
+		
+		if(in_reply_to->to_proc == binder_get_rpcproc() && in_reply_to->to_thread == binder_get_rpcthread()) {
+			struct binder_buffer *tmp_buffer = in_reply_to->buffer;
+			
+			binder_debug(BINDER_DEBUG_TRANSACTION, "%s %d \n", __FUNCTION__, __LINE__);
+
+			/*free in_reply_to*/
+			if (tmp_buffer->transaction) {
+				binder_debug(BINDER_DEBUG_TRANSACTION,"%s %d 0x%x\n",__FUNCTION__, __LINE__, tmp_buffer);	
+				tmp_buffer->transaction->buffer = NULL;
+				tmp_buffer->transaction = NULL;
+			}
+			if (tmp_buffer->async_transaction && tmp_buffer->target_node) {
+				BUG_ON(!tmp_buffer->target_node->has_async_transaction);
+				if (list_empty(&tmp_buffer->target_node->async_todo))
+					tmp_buffer->target_node->has_async_transaction = 0;
+				else {
+					//list_move_tail(tmp_buffer->target_node->async_todo.next, &thread->todo);
+					binder_debug(BINDER_DEBUG_TRANSACTION,"%s %d\n",__FUNCTION__, __LINE__);				     		
+				}
+			}
+			trace_binder_transaction_buffer_release(tmp_buffer);
+
+			//binder_transaction_buffer_release(in_reply_to->to_proc, tmp_buffer, NULL);
+
+			binder_free_buf(in_reply_to->to_proc, tmp_buffer);
+		}
+		binder_pop_transaction(target_thread, in_reply_to);
+	} else if (!(t->flags & TF_ONE_WAY)) {
+		BUG_ON(t->buffer->async_transaction != 0);
+		t->need_reply = 1;
+		t->from_parent = thread->transaction_stack;
+		thread->transaction_stack = t;
+		if(thread == binder_get_rpcthread() && proc == binder_get_rpcproc()) {
+			t->remote_priv = priv;
+			binder_rpc_enqueue_todo(t, thread);
+		}
+	} else {
+		BUG_ON(target_node == NULL);
+		BUG_ON(t->buffer->async_transaction != 1);
+		if (target_node->has_async_transaction) {
+			target_list = &target_node->async_todo;
+			target_wait = NULL;
+		} else
+			target_node->has_async_transaction = 1;
+		
+		if(thread == binder_get_rpcthread() && proc == binder_get_rpcproc()) {
+			binder_debug(BINDER_DEBUG_TRANSACTION, "%s %d \n", __FUNCTION__, __LINE__);
+			
+			//t->remote_priv = priv;
+			//binder_rpc_enqueue_todo(t, thread);
+		}
+	}
+	if(target_thread != binder_get_rpcthread()) {
+		t->work.type = BINDER_WORK_TRANSACTION;
+		list_add_tail(&t->work.entry, target_list);
+	}
+	
+	if(thread != binder_get_rpcthread()) {
+		tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;	
+		list_add_tail(&tcomplete->entry, &thread->todo);
+	}
+	else {
+		kfree(tcomplete);
+	}
+
+	if(target_thread != binder_get_rpcthread()) {
+		if (target_wait)
+			wake_up_interruptible(target_wait);
+	}
+	binder_unlock(__func__);
+	return;
+
+err_get_unused_fd_failed:
+err_fget_failed:
+err_fd_not_allowed:
+err_binder_get_ref_for_node_failed:
+err_binder_get_ref_failed:
+err_binder_new_node_failed:
+err_bad_object_type:
+err_bad_offset:
+err_copy_data_failed:
+	trace_binder_transaction_failed_buffer_release(t->buffer);
+	binder_transaction_buffer_release(target_proc, t->buffer, offp);
+	t->buffer->transaction = NULL;
+	binder_free_buf(target_proc, t->buffer);
+err_binder_alloc_buf_failed:
+	kfree(tcomplete);
+	binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
+err_alloc_tcomplete_failed:
+	kfree(t);
+	binder_stats_deleted(BINDER_STAT_TRANSACTION);
+err_alloc_t_failed:
+err_bad_call_stack:
+err_empty_call_stack:
+err_dead_binder:
+err_invalid_target_handle:
+err_no_context_mgr_node:
+	binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
+			 "binder: %d:%d transaction failed %d, size %zd-%zd\n",
+			 proc->pid, thread->pid, return_error,
+			 tr->data_size, tr->offsets_size);
+
+	{
+		struct binder_transaction_log_entry *fe;
+		fe = binder_transaction_log_add(&binder_transaction_log_failed);
+		*fe = *e;
+	}
+
+	BUG_ON(thread->return_error != BR_OK);
+	binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,"return_error_line %d \n",return_error_line);
+	if(thread == binder_get_rpcthread() && proc == binder_get_rpcproc()) {
+		if(NULL != binder_rpc_ops.binder_return_error) {
+			struct binder_rpc_operations_info ops_info;
+							
+			ops_info.tr = NULL;
+			
+			if (in_reply_to) {
+				ops_info.cmd = BR_TRANSACTION_COMPLETE;
+				/*this cmd will be ignored on remote thread.*/
+				ops_info.priv = BINDER_RPC_IGNORE_PRIV;
+
+				/*send target_thread fail reply*/
+				binder_send_failed_reply(in_reply_to, return_error);
+			}
+			else {
+				ops_info.cmd = return_error;
+				ops_info.priv = priv;
+			}			
+			/*send error to remote thread*/
+			binder_rpc_ops.binder_return_error(&ops_info, reply);
+		}
+	}
+	else {
+		if (in_reply_to) {
+			thread->return_error = BR_TRANSACTION_COMPLETE;
+			binder_send_failed_reply(in_reply_to, return_error);
+		} else
+			thread->return_error = return_error;
+	}
+
+	binder_unlock(__func__);
+}
+
+void binder_rpc_return_error(void *brpc_proc,
+				 void *prpc_thread,
+				 uint32_t return_error,
+				 binder_uintptr_t priv,
+				 int reply)
+{
+	struct binder_proc *proc = (struct binder_proc *)brpc_proc;
+	struct binder_thread *thread = (struct binder_thread *)prpc_thread;	
+
+	struct binder_proc *target_proc = NULL;
+	struct binder_thread *target_thread = NULL;
+	struct binder_transaction *in_reply_to = NULL;
+
+	binder_lock(__func__);
+	/*ignore binder_rpc_ops.binder_broadcast reply*/
+	if(priv == BINDER_RPC_IGNORE_PRIV) {
+		binder_unlock(__func__);
+		return;
+	}
+	binder_debug(BINDER_DEBUG_TRANSACTION,"%s %d \n",__FUNCTION__,__LINE__);
+	if((thread == binder_get_rpcthread() && proc == binder_get_rpcproc())) {			
+		in_reply_to = binder_rpc_find_todo_by_priv(priv, thread);		
+	}	
+
+	if (in_reply_to == NULL) {
+		binder_user_error("%s binder: %d:%d got reply transaction "
+				  "with no transaction stack\n", __FUNCTION__, proc->pid, thread->pid);
+		binder_unlock(__func__);
+		return;
+	}
+	/*no reply*/
+	if(in_reply_to->flags & TF_ONE_WAY) {
+		binder_unlock(__func__);
+		return;
+	}
+	
+	binder_set_nice(in_reply_to->saved_priority);
+	if (in_reply_to->to_thread != thread) {
+		binder_user_error("binder: %d:%d got reply transaction "
+			"with bad transaction stack,"
+			" transaction %d has target %d:%d\n",
+			proc->pid, thread->pid, in_reply_to->debug_id,
+			in_reply_to->to_proc ?
+			in_reply_to->to_proc->pid : 0,
+			in_reply_to->to_thread ?
+			in_reply_to->to_thread->pid : 0);
+		binder_unlock(__func__);
+		return;
+	}
+
+	target_thread = in_reply_to->from;
+	if (target_thread == NULL) {
+		binder_unlock(__func__);
+		return;
+	}
+	if (target_thread->transaction_stack != in_reply_to) {
+		binder_user_error("binder: %d:%d got reply transaction "
+			"with bad target transaction stack %d, "
+			"expected %d\n",
+			proc->pid, thread->pid,
+			target_thread->transaction_stack ?
+			target_thread->transaction_stack->debug_id : 0,
+			in_reply_to->debug_id);
+		binder_unlock(__func__);
+		return;
+	}
+
+	binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,"%s %d:%d transaction failed %d \n",
+			 __FUNCTION__, target_thread->proc->pid, target_thread->pid, return_error);	
+	
+	if(reply) {
+		//target_thread->return_error = BR_TRANSACTION_COMPLETE;		
+		binder_send_failed_reply(in_reply_to, return_error);
+	}
+	else {
+		target_thread->return_error = return_error;
+		wake_up_interruptible(&target_thread->wait);//need ?		
+	}
+
+	binder_unlock(__func__);
+}
+
+void binder_rpc_node_release(void *node)
+{
+   struct binder_proc *proc = binder_get_rpcproc();
+   struct rb_node *n;
+   struct binder_node *releasing_node = (struct binder_node *)node;
+
+   binder_lock(__func__);
+   for (n = rb_first(&proc->refs_by_desc);
+		  n != NULL;
+		  n = rb_next(n)) {
+		  
+	 struct binder_ref *ref;
+
+	 ref = rb_entry(n, struct binder_ref, rb_node_desc);	 
+		 
+	 if(ref->node == releasing_node) {
+		 binder_debug(BINDER_DEBUG_OPEN_CLOSE,"%s %d debug_id:%d desc:%d strong:%d weak:%d \n",__FUNCTION__,__LINE__, 
+								 ref->debug_id,ref->desc,ref->strong,ref->weak);
+		 if(binder_rpc_ops.binder_dead_notify) {
+			 binder_rpc_ops.binder_dead_notify(ref->desc);
+		 }
+
+		 binder_delete_ref(ref);
+	 }
+   }
+   binder_unlock(__func__);
+}
+
+void binder_rpc_dead(void *brpc_proc, uint32_t handle)
+{
+	struct binder_proc *proc = (struct binder_proc *)brpc_proc;
+	struct binder_node *node;
+
+	struct hlist_node *pos, *n;
+	struct binder_transaction *t;
+	int incoming_refs = 0;
+
+	binder_lock(__func__);
+	node = binder_get_node(proc, handle);
+	if(!node) {
+		binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,"binder_get_node(%d) fail\n",handle);
+	}
+	else {
+		binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,"binder_get_node(%d) success\n",handle);
+		rb_erase(&node->rb_node, &proc->nodes);
+		list_del_init(&node->work.entry);
+		//binder_release_work(&node->async_todo);
+		if (hlist_empty(&node->refs)) {
+			kfree(node);
+			binder_stats_deleted(BINDER_STAT_NODE);
+		} else {
+			struct binder_ref *ref;
+			int death = 0;
+
+			node->proc = NULL;
+			node->local_strong_refs = 0;
+			node->local_weak_refs = 0;
+			hlist_add_head(&node->dead_node, &binder_dead_nodes);
+			hlist_for_each_entry_safe(ref, pos, n, &node->refs, node_entry) {
+				binder_debug(BINDER_DEBUG_OPEN_CLOSE,"%s %d debug_id:%d desc:%d strong:%d weak:%d \n",
+					__FUNCTION__, ref->proc->pid, ref->debug_id,ref->desc,ref->strong,ref->weak);
+				incoming_refs++;
+				if (ref->death) {
+					death++;
+					if (list_empty(&ref->death->work.entry)) {
+						ref->death->work.type = BINDER_WORK_DEAD_BINDER;
+						list_add_tail(&ref->death->work.entry, &ref->proc->todo);
+						wake_up_interruptible(&ref->proc->wait);
+					} else
+						BUG();
+				}
+			}
+			binder_debug(BINDER_DEBUG_DEAD_BINDER,
+				     "binder: node %d now dead, "
+				     "refs %d, death %d\n", node->debug_id,
+				     incoming_refs, death);
+		}		
+	}	
+
+	binder_unlock(__func__);
+}
+
+/***********************************************************************
+        BINDER RPC API END
+***********************************************************************/
+#endif
 
 static void print_binder_transaction(struct seq_file *m, const char *prefix,
 				     struct binder_transaction *t)
@@ -3283,7 +4417,12 @@
 	size_t start_pos = m->count;
 	size_t header_pos;
 
-	seq_printf(m, "  thread %d: l %02x\n", thread->pid, thread->looper);
+	seq_printf(m, "  thread %d: l %02x\n", thread->pid, thread->looper);	
+#ifdef CONFIG_ANDROID_BINDER_RPC
+	if(thread == binder_get_rpcthread) {
+		return;
+	}
+#endif	
 	header_pos = m->count;
 	t = thread->transaction_stack;
 	while (t) {
diff --git a/ap/os/linux/linux-3.4.x/drivers/staging/android/binder_rpc.c b/ap/os/linux/linux-3.4.x/drivers/staging/android/binder_rpc.c
new file mode 100755
index 0000000..1dc410e
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/staging/android/binder_rpc.c
@@ -0,0 +1,752 @@
+#include <linux/fdtable.h>

+#include <linux/file.h>

+#include <linux/freezer.h>

+#include <linux/fs.h>

+#include <linux/list.h>

+#include <linux/miscdevice.h>

+#include <linux/module.h>

+#include <linux/mutex.h>

+#include <linux/nsproxy.h>

+#include <linux/poll.h>

+#include <linux/debugfs.h>

+#include <linux/rbtree.h>

+//#include <linux/sched/signal.h>

+//#include <linux/sched/mm.h>

+#include <linux/seq_file.h>

+#include <linux/string.h>

+#include <linux/uaccess.h>

+#include <linux/pid_namespace.h>

+#include <linux/security.h>

+#include <linux/spinlock.h>

+#include <linux/ratelimit.h>

+#include <linux/syscalls.h>

+//#include <linux/task_work.h>

+//#include <linux/sizes.h>

+

+#include <linux/delay.h>

+//#include "binder_alloc.h"

+#include "binder_rpc.h"

+#include "binder_rpc_common.h"

+

+#define brpc_init_sema sema_init

+#define brpc_get_sema down_interruptible

+#define brpc_put_sema up

+

+enum binder_driver_command_protocol_ext {

+	BC_DEAD_BINDER_NOTIFY = _IOW('c', 100, struct brpc_dead_data),

+

+};

+

+struct binder_rpc_context brpc_ctx;

+

+static int brpc_rpctr_convert_tr(struct brpc_data *prpc_data, struct binder_transaction_data *tr);

+static struct brpc_data_entry *brpc_tr_convert_rpctr(struct binder_rpc_operations_info *ops_info,

+													void *ptr, 

+													void *cookie);

+static int brpc_update_object_binder(struct brpc_data *prpc_data, uint32_t local_handle);

+static int brpc_chn_recv_proc(struct brpc_data *prpc_data);

+static int brpc_chn_write(struct brpc_rpmg_channel *chninfo, void *buf, unsigned int len);

+static int brpc_chn_receive_thread(void *argv);

+static int brpc_chn_create(struct binder_rpc_context *pbrpc_ctx);

+static int brpc_write_remote(struct brpc_data *data);

+static int brpc_send_trdata(struct brpc_data_entry *rpc_data_node);

+static int brpc_thread_enqueue_data(struct brpc_agent_thread_info *pagent_thread, struct brpc_data_entry *rpcdata_node);

+static int brpc_thread_write(void *brpc_proc,

+			binder_uintptr_t brpc_buffer, size_t size,

+			binder_size_t *consumed);

+static int brpc_agent_write_refs(struct binder_rpc_context *pbrpc_ctx);

+static void brpc_transaction(void *prpc_proc,

+						   void *prpc_thread,

+						   struct binder_transaction_data *tr, int reply,

+						   binder_size_t extra_buffers_size,

+						   binder_uintptr_t priv);

+

+static void brpc_uld_handle(struct binder_rpc_context *pbrpc_ctx, struct brpc_data *prpc_data);

+static void brpc_dld_handle(struct binder_rpc_context *pbrpc_ctx, struct brpc_data *prpc_data);

+static int brpc_agent_loop(void *argv);

+static int brpc_agent_create(struct binder_rpc_context *pbrpc_ctx);

+

+

+static int brpc_rpctr_convert_tr(struct brpc_data *prpc_data, struct binder_transaction_data *tr)

+{

+	struct brpc_transaction_data *prpc_tr = &prpc_data->rpc_tr;

+	

+	tr->target.handle = prpc_tr->handle;

+	tr->cookie = prpc_tr->cookie;

+	tr->code = prpc_tr->code;

+	tr->flags = prpc_tr->flags;

+	tr->data_size = prpc_tr->data_size;

+	tr->offsets_size = prpc_tr->offsets_size;

+

+	tr->data.ptr.buffer = (void *)kzalloc(tr->data_size, GFP_KERNEL);

+	tr->data.ptr.offsets = (void *)kzalloc(tr->offsets_size, GFP_KERNEL);

+	memcpy(tr->data.ptr.buffer, prpc_tr->buffer, tr->data_size);

+	memcpy(tr->data.ptr.offsets, prpc_tr->offsets, tr->offsets_size);

+

+	return 0;

+}

+

+static struct brpc_data_entry *brpc_tr_convert_rpctr(struct binder_rpc_operations_info *ops_info,

+													void *ptr, 

+													void *cookie)

+{

+	struct brpc_data_entry *rpc_data_node;

+	struct brpc_data *prpc_data;

+	struct brpc_transaction_data *prpc_tr;

+

+	uint32_t cmd = ops_info->cmd;

+	struct binder_transaction_data *tr = ops_info->tr;

+	binder_uintptr_t priv = ops_info->priv;

+

+	/*construct brpc_data*/

+	rpc_data_node = kzalloc(sizeof(*rpc_data_node), GFP_KERNEL);

+	if (rpc_data_node == NULL) {

+		brpc_err("kzalloc fial!!");

+		return NULL;

+	}

+

+	rpc_data_node->dir = BRPC_DIR_UPLINK;

+

+	prpc_data = &rpc_data_node->rpc_data;

+	prpc_data->cmd = cmd;

+

+	prpc_tr = &prpc_data->rpc_tr;

+	prpc_tr->priv = priv;

+	prpc_tr->handle = NULL == ptr ? tr->target.handle : ptr;

+	prpc_tr->cookie = NULL == cookie ? tr->cookie : cookie;

+	prpc_tr->code = tr->code;

+	prpc_tr->flags = tr->flags;		

+	prpc_tr->data_size = tr->data_size;

+	prpc_tr->offsets_size = tr->offsets_size;

+	

+	brpc_dbg("target.handle=%d code=%d ",prpc_tr->handle, prpc_tr->code);

+	

+	if(prpc_tr->data_size >= BRPC_TR_BUFFER_SIZE_MAX || prpc_tr->offsets_size >= BRPC_TR_BUFFER_SIZE_MAX) {

+		brpc_err("data_size=%d offsets_size=%d ",prpc_tr->data_size,prpc_tr->offsets_size);

+		kfree(rpc_data_node);

+		return NULL;

+	}

+	

+	if (copy_from_user(prpc_tr->buffer, tr->data.ptr.buffer, prpc_tr->data_size)) {

+		brpc_err("copy_from_user fail\n");

+		kfree(rpc_data_node);

+		return NULL;

+	}

+

+	if (copy_from_user(prpc_tr->offsets, tr->data.ptr.offsets, prpc_tr->offsets_size)) {

+		brpc_dbg("copy_from_user fail\n");

+		kfree(rpc_data_node);

+		return NULL;

+	}

+

+	return rpc_data_node;

+}

+

+

+static int brpc_update_object_binder(struct brpc_data *prpc_data, uint32_t local_handle) 

+{

+	binder_size_t buffer_offset = 0;

+	binder_size_t off_start_offset, off_end_offset;

+	binder_size_t off_min;

+

+	struct brpc_transaction_data *prpc_tr = &prpc_data->rpc_tr;

+	size_t *offp, *off_end;

+	

+	offp = (size_t *)prpc_tr->offsets;	

+	off_end = (void *)offp + prpc_tr->offsets_size;

+	

+	for (; offp < off_end; offp++) {

+		struct flat_binder_object *fp;

+		if (*offp > prpc_tr->data_size - sizeof(*fp) ||

+		    prpc_tr->data_size < sizeof(*fp) ||

+		    !IS_ALIGNED(*offp, sizeof(void *))) {

+			brpc_err("binder: got transaction with "

+				"invalid offset, %zd\n",

+				*offp);

+			return -1;

+		}

+		fp = (struct flat_binder_object *)(prpc_tr->buffer + *offp);

+		switch (fp->type) {

+		case BINDER_TYPE_BINDER:

+		case BINDER_TYPE_WEAK_BINDER: {			

+			fp->binder = local_handle;

+			fp->cookie = 0;			

+			brpc_info("fp->binder:%d",fp->binder);

+		} break;

+		case BINDER_TYPE_HANDLE:

+		case BINDER_TYPE_WEAK_HANDLE:

+			brpc_info("fp->handle:%d",fp->handle);

+			break;

+

+		case BINDER_TYPE_FD: 

+		default:

+			brpc_err("got transaction with invalid object type, %x\n",fp->type);

+			return -1;

+		}

+	}

+	

+	return 0;

+}

+static int brpc_binder_return_error(struct binder_rpc_operations_info *ops_info, int reply)

+{

+	struct brpc_data_entry *rpc_data_node = NULL;

+

+	rpc_data_node = kzalloc(sizeof(*rpc_data_node), GFP_KERNEL);

+	if (rpc_data_node == NULL) {

+		brpc_err("kzalloc fial!!");

+		return -1;

+	}

+

+	rpc_data_node->dir = BRPC_DIR_UPLINK;

+	rpc_data_node->rpc_data.cmd = ops_info->cmd;

+	rpc_data_node->rpc_data.rpc_reply_error.priv = ops_info->priv;

+	rpc_data_node->rpc_data.rpc_reply_error.reply = reply;

+	

+	brpc_send_trdata(rpc_data_node);

+	return 0;

+}

+static int brpc_binder_release(void *proc, void *node)

+{

+	struct brpc_data_entry *rpc_data_node = NULL;

+

+	rpc_data_node = kzalloc(sizeof(*rpc_data_node), GFP_KERNEL);

+	if (rpc_data_node == NULL) {

+		brpc_err("kzalloc fial!!");

+		return -1;

+	}

+

+	rpc_data_node->dir = BRPC_DIR_LOCAL;

+	rpc_data_node->rpc_data.rpc_local.proc = proc;

+	rpc_data_node->rpc_data.rpc_local.node = node;

+	brpc_send_trdata(rpc_data_node);

+	return 0;

+}

+static int brpc_binder_dead(uint32_t handle)

+{

+	struct brpc_data_entry *rpc_data_node = NULL;

+

+	rpc_data_node = kzalloc(sizeof(*rpc_data_node), GFP_KERNEL);

+	if (rpc_data_node == NULL) {

+		brpc_err("kzalloc fial!!");

+		return -1;

+	}

+

+	rpc_data_node->dir = BRPC_DIR_UPLINK;

+	rpc_data_node->rpc_data.cmd = BC_DEAD_BINDER_NOTIFY;

+	rpc_data_node->rpc_data.rpc_dead.handle = handle;

+	brpc_send_trdata(rpc_data_node);

+	

+	return 0;

+}

+

+static int brpc_binder_transaction(struct binder_rpc_operations_info *ops_info, 

+								uint32_t local_handle, 

+								void *remote_ptr, 

+								void *remote_cookie)

+{

+	struct brpc_data_entry *rpc_data_node = NULL;

+	struct brpc_data *prpc_data;

+	struct flat_binder_object *obj;

+	binder_size_t buffer_offset = 0;

+	binder_size_t off_start_offset, off_end_offset;

+	binder_size_t off_min;

+

+	uint32_t cmd = ops_info->cmd;

+	struct binder_transaction_data *tr = ops_info->tr;

+	binder_uintptr_t priv = ops_info->priv;

+	

+	brpc_info("tr cmd:0x%x local_handle:%d handle:%d code:%d",cmd, local_handle, tr->target.handle, tr->code);

+	brpc_info("tr cmd:0x%x",tr->flags);

+	if(0 != tr->target.handle) {

+		rpc_data_node = brpc_tr_convert_rpctr(ops_info,remote_ptr,remote_cookie);

+		if(NULL == rpc_data_node) {

+			return -1;

+		}

+

+		if(0 != local_handle && brpc_update_object_binder(&rpc_data_node->rpc_data, local_handle)) {

+			brpc_err("brpc_update_object_binder(local_handle %d) fail.",local_handle);

+			kfree(rpc_data_node);

+			return -1;

+		}

+

+		brpc_send_trdata(rpc_data_node);

+	}

+

+	return 0;

+}

+

+static int brpc_binder_reply(struct binder_rpc_operations_info *ops_info, uint32_t local_handle)

+{

+	struct brpc_data_entry *rpc_data_node = NULL;

+	struct brpc_data *prpc_data;

+	

+	uint32_t cmd = ops_info->cmd;

+	struct binder_transaction_data *tr = ops_info->tr;

+	binder_uintptr_t priv = ops_info->priv;

+	

+	brpc_info("tr cmd:0x%x local_handle:%d handle:%d code:%d",cmd, local_handle, tr->target.handle, tr->code);

+

+	rpc_data_node = brpc_tr_convert_rpctr(ops_info, NULL ,NULL);

+	if(NULL == rpc_data_node) {

+		brpc_err("drop this tr.");

+		return -1;

+	}

+	if(0 != local_handle && brpc_update_object_binder(&rpc_data_node->rpc_data, local_handle)) {

+		brpc_err("brpc_update_object_binder(local_handle %d) fail.",local_handle);

+		kfree(rpc_data_node);

+		return -1;

+	}

+

+	brpc_send_trdata(rpc_data_node);

+

+	return 0;

+}

+

+static int brpc_binder_broadcast(struct binder_rpc_operations_info *ops_info, uint32_t local_handle)

+{

+	struct brpc_data_entry *rpc_data_node = NULL;

+	struct brpc_data *prpc_data;

+	struct flat_binder_object *obj;

+	binder_size_t buffer_offset = 0;

+	binder_size_t off_start_offset, off_end_offset;

+	binder_size_t off_min;

+

+	uint32_t cmd = ops_info->cmd;

+	struct binder_transaction_data *tr = ops_info->tr;

+	binder_uintptr_t priv = ops_info->priv;

+

+	brpc_info("tr handle:%d code:%d",tr->target.handle, tr->code);

+	/*broadcat add service*/

+	if(0 == tr->target.handle && ADD_SERVICE_TRANSACTION == tr->code) {	

+		rpc_data_node = brpc_tr_convert_rpctr(ops_info, NULL, NULL);

+		if(NULL == rpc_data_node) {

+			brpc_err("brpc_tr_convert_rpctr fail.");

+			return -1;

+		}

+		if(brpc_update_object_binder(&rpc_data_node->rpc_data, local_handle)) {

+			brpc_err("brpc_update_object_binder fail.");

+			kfree(rpc_data_node);

+			return -1;

+		}							

+		

+		return brpc_send_trdata(rpc_data_node);		

+	}

+

+	return 0;

+}

+

+static int brpc_chn_recv_proc(struct brpc_data *prpc_data)

+{

+	struct brpc_data_entry *rpc_data_node;

+

+	rpc_data_node = kzalloc(sizeof(*rpc_data_node), GFP_KERNEL);

+	if (rpc_data_node == NULL) {

+		return -1;

+	}

+	brpc_dbg("cmd=0x%x",prpc_data->cmd);

+	if(BC_TRANSACTION == prpc_data->cmd || BC_REPLY == prpc_data->cmd) {

+		brpc_dbg("target.handle=%d code=%d",prpc_data->rpc_tr.handle, prpc_data->rpc_tr.code);

+		brpc_dbg("data_size=%d offsets_size=%d",prpc_data->rpc_tr.data_size,prpc_data->rpc_tr.offsets_size);

+	}

+	else if(BC_DEAD_BINDER_NOTIFY == prpc_data->cmd) {

+		brpc_dbg("BC_DEAD_BINDER_NOTIFY handle=%d",prpc_data->rpc_dead.handle);

+	}

+	rpc_data_node->dir = BRPC_DIR_DOWNLINK;

+

+	memcpy(&rpc_data_node->rpc_data, prpc_data, sizeof(struct brpc_data));

+

+	return brpc_send_trdata(rpc_data_node);

+}

+

+/*·µ»ØÖµ´óÓÚµÈÓÚ0£¬±íʾдͨµÀ³É¹¦£»Ð¡ÓÚ0±íʾдͨµÀʧ°Ü*/

+static int brpc_chn_write(struct brpc_rpmg_channel *chninfo, void *buf, unsigned int len)

+{

+    T_ZDrvRpMsg_Msg msg;

+

+    if(NULL == buf) {

+        return -EINVAL;

+    }

+    memset(&msg, 0, sizeof(msg));

+    msg.actorID = chninfo->core_id;

+    msg.chID   = chninfo->channel_id;

+    msg.flag |= RPMSG_WRITE_INT;

+    msg.buf = buf;

+    msg.len = len;

+

+    return binderWrite(&msg);

+}

+

+static int brpc_chn_receive_thread(void *argv)

+{

+	struct binder_rpc_context *pbrpc_ctx = (struct binder_rpc_context *)argv;

+	T_ZDrvRpMsg_Msg msg;

+	struct brpc_data data;

+	

+	int ret;

+

+	memset(&msg, 0, sizeof(msg));

+	msg.actorID = pbrpc_ctx->chn.core_id;

+	msg.chID = pbrpc_ctx->chn.channel_id;

+	msg.flag = 0;

+	

+	while(!pbrpc_ctx->chn.channel_stop) {

+		msg.buf = &data;

+		msg.len = sizeof(data);

+

+		ret = binderRead(&msg);

+		if(ret <= 0) {

+			brpc_warn("binderRead ret=%d ", ret);

+			msleep(10000);

+			continue;

+		}

+

+		if(pbrpc_ctx->chn.channel_stop) {

+			break;

+		}

+

+		brpc_chn_recv_proc(&data);							

+	}

+	

+	return 0;

+}

+

+static int brpc_chn_create(struct binder_rpc_context *pbrpc_ctx)

+{

+	struct task_struct *th = NULL;

+    int retval = 0;

+

+	retval = binderCreateChannel(pbrpc_ctx->chn.core_id, pbrpc_ctx->chn.channel_id, pbrpc_ctx->chn.channel_size);

+   	if(retval != RPMSG_SUCCESS && retval != RPMSG_CHANNEL_ALREADY_EXIST) {

+        brpc_err("binderCreateChannel fail.");

+        return retval;

+    }

+

+    th = kthread_run(brpc_chn_receive_thread, (void *)pbrpc_ctx, "brpc-chn%d", pbrpc_ctx->chn.channel_id);

+    if (IS_ERR(th)) {

+        brpc_err("kthread_run fail.");

+        return PTR_ERR(th);

+    }

+    pbrpc_ctx->chn.rcv_thread = th;

+

+	return 0;

+}

+

+static int brpc_write_remote(struct brpc_data *data)

+{

+	struct binder_rpc_context *pbrpc_ctx = &brpc_ctx;

+	

+	if(0 > brpc_chn_write(&(pbrpc_ctx->chn), data, sizeof(struct brpc_data))) {

+		brpc_err("brpc_channel_write fail.\n");

+		return -1;

+	}

+	return 0;

+}

+

+static int brpc_thread_enqueue_data(struct brpc_agent_thread_info *pagent_thread, struct brpc_data_entry *rpcdata_node)

+{

+	unsigned long flags;

+	

+	spin_lock_irqsave(&pagent_thread->p_transaction_lock,flags);

+	list_add_tail(&rpcdata_node->list, &pagent_thread->p_transaction_list);

+	spin_unlock_irqrestore(&pagent_thread->p_transaction_lock,flags);

+	brpc_put_sema(&pagent_thread->p_transaction_sem);

+

+	return 0;

+}

+

+static int brpc_send_trdata(struct brpc_data_entry *rpc_data_node)

+{	

+	struct binder_rpc_context *pbrpc_ctx = &brpc_ctx;

+

+	return brpc_thread_enqueue_data(&pbrpc_ctx->agent_thread, rpc_data_node);

+}

+

+static int brpc_thread_write(void *brpc_proc,

+			binder_uintptr_t brpc_buffer, size_t size,

+			binder_size_t *consumed)

+{

+	struct binder_proc *proc = brpc_proc;

+	int ret;

+	mm_segment_t old_fs;

+	

+	old_fs = get_fs();

+	set_fs(KERNEL_DS);

+

+	ret = binder_rpc_thread_write(brpc_proc, brpc_buffer, size, consumed);

+

+	set_fs(old_fs);

+	

+	return ret;

+}

+

+

+/*·¢ËÍBC_INCREFS/BC_ACQUIRE*/

+static int brpc_agent_write_refs(struct binder_rpc_context *pbrpc_ctx)

+{

+	int ret;

+	binder_size_t consumed = 0;

+	struct {

+        __u32 cmd;

+        __u32 handle;

+    } writebuf;

+

+	writebuf.cmd = BC_INCREFS;

+	writebuf.handle = 0;

+

+	ret = brpc_thread_write(pbrpc_ctx->brpc_proc, (binder_uintptr_t)&writebuf, sizeof(writebuf), &consumed);

+	if(ret) {

+		brpc_err("write BC_INCREFS fail, ret:%d",ret);

+		return -1;

+	}

+	brpc_dbg("BC_INCREFS consumed:%d ",consumed);

+

+	writebuf.cmd = BC_ACQUIRE;

+	writebuf.handle = 0;

+

+	ret = brpc_thread_write(pbrpc_ctx->brpc_proc, (binder_uintptr_t)&writebuf, sizeof(writebuf), &consumed);

+	if(ret) {

+		brpc_err("write BC_ACQUIRE fail, ret:%d",ret);

+		return -1;

+	}

+	brpc_dbg("BC_ACQUIRE consumed:%d ",consumed);

+

+	return 0;

+}

+

+static void brpc_transaction(void *prpc_proc,

+						   void *prpc_thread,

+						   struct binder_transaction_data *tr, int reply,

+						   binder_size_t extra_buffers_size,

+						   binder_uintptr_t priv)

+{

+	mm_segment_t old_fs;

+	const char __user *p, *q;

+

+	old_fs = get_fs();

+	set_fs(KERNEL_DS);

+	

+	p = (__force const char __user *)(tr->data.ptr.buffer);

+	q = (__force const char __user *)(tr->data.ptr.offsets);

+	

+	binder_rpc_transaction(prpc_proc, 

+						prpc_thread, 

+						tr,

+						reply,

+						0,

+						priv);

+

+	set_fs(old_fs);

+}

+

+static void brpc_uld_handle(struct binder_rpc_context *pbrpc_ctx, struct brpc_data *prpc_data)

+{

+	if(BC_TRANSACTION == prpc_data->cmd || BC_REPLY == prpc_data->cmd) {

+		brpc_dbg("BRPC_DIR_UPLINK cmd:0x%x priv:0x%x",prpc_data->cmd,prpc_data->rpc_tr.priv);

+	}

+	else if(BC_DEAD_BINDER_NOTIFY == prpc_data->cmd) {

+		brpc_dbg("BRPC_DIR_UPLINK cmd:0x%x handle:0x%x",prpc_data->cmd,prpc_data->rpc_dead.handle);

+	}

+	else if(BR_ERROR == prpc_data->cmd ||

+		BR_DEAD_REPLY == prpc_data->cmd ||

+		BR_TRANSACTION_COMPLETE == prpc_data->cmd ||

+		BR_DEAD_BINDER == prpc_data->cmd ||

+		BR_CLEAR_DEATH_NOTIFICATION_DONE == prpc_data->cmd ||

+		BR_FAILED_REPLY == prpc_data->cmd) {

+		brpc_dbg("BRPC_DIR_UPLINK cmd:0x%x priv:0x%x",prpc_data->cmd,prpc_data->rpc_reply_error.priv);

+	}

+	else {

+		brpc_err("unknow cmd 0x%x",prpc_data->cmd);

+	}

+	brpc_write_remote(prpc_data);

+}

+static void brpc_dld_handle(struct binder_rpc_context *pbrpc_ctx, struct brpc_data *prpc_data)

+{

+	struct binder_transaction_data tr;

+	struct brpc_transaction_data *prpc_tr = &prpc_data->rpc_tr;

+	binder_uintptr_t priv;

+	

+	if(BC_TRANSACTION == prpc_data->cmd || BC_REPLY == prpc_data->cmd) {

+		brpc_dbg("BRPC_DIR_DOWNLINK cmd:0x%x priv:0x%x",prpc_data->cmd,prpc_data->rpc_tr.priv);

+		brpc_rpctr_convert_tr(prpc_data, &tr);

+

+		brpc_transaction(pbrpc_ctx->brpc_proc, 

+						pbrpc_ctx->brpc_thread, 

+						&tr,

+						BC_REPLY == prpc_data->cmd,

+						0,

+						prpc_tr->priv);

+

+		if(0 != tr.data.ptr.buffer) {

+			kfree(tr.data.ptr.buffer);

+		}

+		if(0 != tr.data.ptr.offsets) {

+			kfree(tr.data.ptr.offsets);

+		}

+	}

+	else if(BC_DEAD_BINDER_NOTIFY == prpc_data->cmd) {

+		brpc_dbg("BRPC_DIR_DOWNLINK cmd:0x%x handle:0x%x",prpc_data->cmd,prpc_data->rpc_dead.handle);

+		binder_rpc_dead(pbrpc_ctx->brpc_proc, prpc_data->rpc_dead.handle);

+	}

+	else if(BR_ERROR == prpc_data->cmd ||

+		BR_DEAD_REPLY == prpc_data->cmd ||

+		BR_TRANSACTION_COMPLETE == prpc_data->cmd ||

+		BR_DEAD_BINDER == prpc_data->cmd ||

+		BR_CLEAR_DEATH_NOTIFICATION_DONE == prpc_data->cmd ||

+		BR_FAILED_REPLY == prpc_data->cmd) {

+		brpc_dbg("BRPC_DIR_DOWNLINK cmd:0x%x priv:0x%x",prpc_data->cmd,prpc_data->rpc_reply_error.priv);

+		binder_rpc_return_error(pbrpc_ctx->brpc_proc, 

+							pbrpc_ctx->brpc_thread,

+							prpc_data->cmd,

+							prpc_data->rpc_reply_error.priv,

+							prpc_data->rpc_reply_error.reply);

+	}

+	else {

+		brpc_err("unknow cmd 0x%x",prpc_data->cmd);

+	}

+}

+

+static void brpc_local_handle(struct binder_rpc_context *pbrpc_ctx, struct brpc_data *prpc_data)

+{

+	binder_rpc_node_release(prpc_data->rpc_local.node);

+}

+

+static int brpc_agent_loop(void *argv)

+{

+	struct binder_rpc_context *pbrpc_ctx = (struct binder_rpc_context *)argv;

+	struct brpc_agent_thread_info *pagent_thread = &pbrpc_ctx->agent_thread;

+	struct list_head	tmp_list;

+	struct brpc_data_entry *entry,*tmp_entry;

+	unsigned long flags;

+

+	pbrpc_ctx->brpc_thread = binder_rpc_get_thread(pbrpc_ctx->brpc_proc);

+	

+	if(brpc_agent_write_refs(pbrpc_ctx)) {

+		brpc_err("brpc_agent_write_refs fail.");

+		return -1;

+	}

+	INIT_LIST_HEAD(&tmp_list);

+	while(!pagent_thread->bstop) {

+		brpc_get_sema(&pagent_thread->p_transaction_sem);

+

+		spin_lock_irqsave(&pagent_thread->p_transaction_lock,flags);	

+		if (list_empty(&pagent_thread->p_transaction_list)) {

+			spin_unlock_irqrestore(&pagent_thread->p_transaction_lock,flags);

+			continue;

+		}

+		list_replace_init(&pagent_thread->p_transaction_list,&tmp_list);

+		list_del_init(&pagent_thread->p_transaction_list);		

+		spin_unlock_irqrestore(&pagent_thread->p_transaction_lock,flags);

+

+		list_for_each_entry_safe(entry,tmp_entry,&tmp_list,list) {

+			if(!pagent_thread->bstop) {			

+				if(BRPC_DIR_UPLINK == entry->dir) {				

+					brpc_uld_handle(pbrpc_ctx, &entry->rpc_data);

+				}

+				else if(BRPC_DIR_DOWNLINK == entry->dir) {				

+					brpc_dld_handle(pbrpc_ctx, &entry->rpc_data);

+				}

+				else if(BRPC_DIR_LOCAL == entry->dir) {

+					brpc_local_handle(pbrpc_ctx, &entry->rpc_data);

+				}

+				else {

+					brpc_warn("brpc data unknow dir(%d).",entry->dir);

+				}

+			}

+

+			list_del(&entry->list);

+			kfree(entry);

+		}

+	}

+

+	spin_lock_irqsave(&pagent_thread->p_transaction_lock,flags);

+	list_for_each_entry_safe(entry,tmp_entry,&pagent_thread->p_transaction_list,list) {

+		list_del(&entry->list);

+		kfree(entry);

+	}

+	spin_unlock_irqrestore(&pagent_thread->p_transaction_lock,flags);

+

+	brpc_err("the agnet loop stop!\n");

+

+	return 0;

+}

+

+static int brpc_agent_create(struct binder_rpc_context *pbrpc_ctx)

+{

+	struct brpc_agent_thread_info *pagent_thread = &pbrpc_ctx->agent_thread;

+	struct task_struct *th = NULL;

+    int retval = 0;

+

+	INIT_LIST_HEAD(&pagent_thread->p_transaction_list);

+	spin_lock_init(&pagent_thread->p_transaction_lock);

+	brpc_init_sema(&pagent_thread->p_transaction_sem, 0);

+	

+	th = kthread_run(brpc_agent_loop, (void *)pbrpc_ctx, "brpc-agent");

+    if (IS_ERR(th)) {

+        brpc_err("kthread_run fail.");

+        return PTR_ERR(th);

+    }

+

+	pagent_thread->p_thread = th;

+	

+	return 0;

+}

+

+int binder_rpc_init(void *proc, struct file *pfile, struct binder_rpc_operations_struct *cb)

+{

+	struct binder_rpc_context *pbrpc_ctx = &brpc_ctx;

+	int ret = 0;

+

+	memset(pbrpc_ctx, 0, sizeof(struct binder_rpc_context));

+

+	pbrpc_ctx->brpc_proc = proc;

+	pbrpc_ctx->prpc_file = pfile;

+	

+	pbrpc_ctx->chn.core_id = CAP_ID;

+	pbrpc_ctx->chn.channel_id = ICP_CHN_BINDER_RPC;

+	pbrpc_ctx->chn.channel_size = ICP_CHN_BINDER_RPC_SIZE;

+	

+	if(brpc_chn_create(pbrpc_ctx)) {

+		brpc_err("brpc_chn_create fail.");

+		return -1;

+	}

+

+	if(brpc_agent_create(pbrpc_ctx)) {

+		brpc_err("brpc_agent_create fail.");

+		return -1;

+	}

+

+	if(NULL != cb) {

+		memset(cb, 0, sizeof(struct binder_rpc_operations_struct));

+		cb->binder_transaction = brpc_binder_transaction;

+		cb->binder_broadcast = brpc_binder_broadcast;

+		cb->binder_reply = brpc_binder_reply;

+		cb->binder_return_error = brpc_binder_return_error;

+		cb->binder_release = brpc_binder_release;

+		cb->binder_dead_notify = brpc_binder_dead;

+	}

+	

+	brpc_info("success!");

+	

+	return 0;

+}

+

+int binder_rpc_deinit(struct vm_area_struct *vma)

+{

+	struct binder_rpc_context *pbrpc_ctx = &brpc_ctx;

+

+	pbrpc_ctx->chn.channel_stop = 1;

+	pbrpc_ctx->agent_thread.bstop = 1;

+	

+	if(pbrpc_ctx->prpc_file) {			

+		filp_close(pbrpc_ctx->prpc_file, current->files);		

+

+		if(NULL != vma) {

+			do_munmap(current->mm, vma->vm_start, vma->vm_end - vma->vm_start);

+		}

+	}

+	

+	brpc_info("success!");

+	

+	return 0;

+}

+

diff --git a/ap/os/linux/linux-3.4.x/drivers/staging/android/binder_rpc.h b/ap/os/linux/linux-3.4.x/drivers/staging/android/binder_rpc.h
new file mode 100755
index 0000000..7315494
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/staging/android/binder_rpc.h
@@ -0,0 +1,51 @@
+#ifndef _LINUX_BINDER_RPC_H

+#define _LINUX_BINDER_RPC_H

+

+#include "binder.h"

+

+typedef __u32 binder_size_t;

+typedef __u32 binder_uintptr_t;

+

+enum {

+    GET_SERVICE_TRANSACTION = 0x00000001,

+    CHECK_SERVICE_TRANSACTION,

+    ADD_SERVICE_TRANSACTION,

+    LIST_SERVICES_TRANSACTION,

+};

+

+struct binder_rpc_operations_info {

+	uint32_t cmd;

+	struct binder_transaction_data *tr;

+	binder_uintptr_t priv;

+};

+

+struct binder_rpc_operations_struct {

+	int (*binder_broadcast)(struct binder_rpc_operations_info *ops_info, uint32_t local_handle);

+	int (*binder_reply)(struct binder_rpc_operations_info *ops_info, uint32_t local_handle);

+	int (*binder_transaction)(struct binder_rpc_operations_info *ops_info, uint32_t local_handle, void *remote_ptr, void *remote_cookie);

+	int (*binder_return_error)(struct binder_rpc_operations_info *ops_info, int reply);

+	int (*binder_release)(void *proc, void *node);

+	int (*binder_dead_notify)(uint32_t handle);

+};

+

+int binder_rpc_init(void *proc, struct file *pfile, struct binder_rpc_operations_struct *cb);

+int binder_rpc_deinit(struct vm_area_struct *vma);

+int binder_rpc_thread_write(void *brpc_proc,

+			binder_uintptr_t brpc_buffer, size_t size,

+			binder_size_t *consumed);

+void *binder_rpc_get_thread(void *brpc_proc);

+void binder_rpc_transaction(void *prpc_proc,

+				   void *prpc_thread,

+				   struct binder_transaction_data *tr, int reply,

+				   binder_size_t extra_buffers_size,

+				   binder_uintptr_t priv);

+void binder_rpc_node_release(void *node);

+void binder_rpc_dead(void *brpc_proc, uint32_t handle);

+void binder_rpc_return_error(void *brpc_proc,

+				 void *prpc_thread,

+				 uint32_t return_error,

+				 binder_uintptr_t priv,

+				 int reply);

+

+

+#endif /* _LINUX_BINDER_RPC_H*/

diff --git a/ap/os/linux/linux-3.4.x/drivers/staging/android/binder_rpc_common.h b/ap/os/linux/linux-3.4.x/drivers/staging/android/binder_rpc_common.h
new file mode 100755
index 0000000..5541022
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/staging/android/binder_rpc_common.h
@@ -0,0 +1,126 @@
+#ifndef _LINUX_BINDER_RPC_COMM_H

+#define _LINUX_BINDER_RPC_COMM_H

+

+#include <linux/interrupt.h>

+#include <linux/kthread.h>

+#include <linux/spinlock.h>

+#include <linux/semaphore.h>

+#include <linux/soc/zte/rpm/rpmsg.h>

+

+#include <binder.h>

+

+int brpc_debug = 0;

+module_param(brpc_debug,int,0644);

+

+#define brpc_dbg(format, arg...) if(brpc_debug == 1) \

+	printk(KERN_INFO " [brpc]<%s>: " format "\n" , __func__ , ## arg)

+#define brpc_info(format, arg...) if(brpc_debug == 1) \

+	printk(KERN_INFO " [brpc]<%s>: " format "\n" , __func__ , ## arg)	

+

+#define brpc_err(format, arg...) printk(KERN_ERR " [brpc]<%s>: " format "\n" , \

+	__func__ , ## arg)

+

+#define brpc_warn(format, arg...) printk(KERN_WARNING " [brpc]<%s>: " format "\n" , \

+	__func__ , ## arg)

+

+/*local data ,to remote,need write rpmsg channel*/

+#define BRPC_DIR_UPLINK		1

+/*remote data ,to local,read from rpmsg channel*/

+#define BRPC_DIR_DOWNLINK	2

+#define BRPC_DIR_LOCAL	3

+

+#define  ICP_CHN_BINDER_RPC 33

+#define	 ICP_CHN_BINDER_RPC_SIZE 	(8 * 1024 *2)

+#define binderCreateChannel zDrvRpMsg_CreateChannel_Cap

+#define binderWrite         zDrvRpMsg_Write_Cap

+#define binderRead          zDrvRpMsg_Read_Cap

+

+struct brpc_rpmg_channel {

+    T_ZDrvRpMsg_ActorID core_id;

+    T_ZDrvRpMsg_ChID channel_id;

+    unsigned int channel_size;

+    struct task_struct *rcv_thread;

+	int channel_stop;

+};

+

+/*thread proxy list*/

+struct brpc_agent_thread_info {

+	struct task_struct *p_thread;	

+	struct list_head	p_transaction_list;

+	struct spinlock 	p_transaction_lock;

+	struct semaphore 	p_transaction_sem;

+

+	int bstop;

+};

+

+struct binder_rpc_context {	

+	void *brpc_proc;

+	void *brpc_thread;

+	struct file *prpc_file;

+	struct brpc_agent_thread_info agent_thread; 

+	struct brpc_rpmg_channel chn;

+	//struct list_head svc_list;

+};

+

+struct brpc_transaction_data {

+	union {

+		/*cmd == BC_TRANSACTION*/

+		binder_uintptr_t local_tr;

+		/*cmd == BC_REPLY*/

+		binder_uintptr_t remote_tr;

+

+		binder_uintptr_t priv;

+	};

+    __u32	handle;	/* target descriptor of command transaction */

+    binder_uintptr_t	cookie;	/* target object cookie */

+    __u32		code;		/* transaction command */

+

+    /* General information about the transaction. */

+    __u32	        flags;

+

+    binder_size_t	data_size;	/* number of bytes of data */

+    binder_size_t	offsets_size;	/* number of bytes of offsets */

+#define BRPC_TR_BUFFER_SIZE_MAX 256

+	char buffer[BRPC_TR_BUFFER_SIZE_MAX];

+	char offsets[BRPC_TR_BUFFER_SIZE_MAX];    

+};

+

+struct brpc_ref_data {

+	uint32_t target;

+};

+

+struct brpc_local_data {

+	void *proc;

+	void *node;

+};

+

+struct brpc_dead_data {

+	uint32_t handle;

+};

+

+struct brpc_reply_error_data {

+	binder_uintptr_t priv;

+	int reply;

+};

+

+struct brpc_data {

+	/*BC_## command*/

+	uint32_t cmd;

+	union {

+		struct brpc_ref_data rpc_ref;

+		struct brpc_transaction_data rpc_tr;

+		struct brpc_local_data rpc_local;

+		struct brpc_dead_data rpc_dead;

+		struct brpc_reply_error_data rpc_reply_error;

+	};

+};

+

+struct brpc_data_entry {

+	struct list_head list;

+	/*BRPC_DIR_UPLINK / BRPC_DIR_DOWNLINK/*/

+	uint32_t dir;

+	struct brpc_data rpc_data;

+};

+

+#endif /* _LINUX_BINDER_RPC_COMM_H*/

+

diff --git a/ap/os/linux/linux-3.4.x/drivers/tty/serial/zx29_uart.c b/ap/os/linux/linux-3.4.x/drivers/tty/serial/zx29_uart.c
index eed941f..2c0496b 100755
--- a/ap/os/linux/linux-3.4.x/drivers/tty/serial/zx29_uart.c
+++ b/ap/os/linux/linux-3.4.x/drivers/tty/serial/zx29_uart.c
@@ -1825,10 +1825,10 @@
 	}
 
  	if(fifo_len){
-		printk("qq >> fifo len %d.\n",fifo_len);
+		//printk("qq >> fifo len %d.\n",fifo_len);
 		fifo_count = tty_insert_flip_string(&zup->port.state->port,
 						   fifo_buf, fifo_len);
-		printk("qq >>fifo count %d,buf is %x %x %x .\n",fifo_count, fifo_buf[0],fifo_buf[1],fifo_buf[2]);
+		//printk("qq >>fifo count %d,buf is %x %x %x .\n",fifo_count, fifo_buf[0],fifo_buf[1],fifo_buf[2]);
 		fifo_buf[0] = '\0';
 		fifo_buf[1] = '\0';
 		fifo_buf[2] = '\0';
diff --git a/ap/os/linux/linux-3.4.x/drivers/usb/gadget/adb_server.c b/ap/os/linux/linux-3.4.x/drivers/usb/gadget/adb_server.c
index ff872df..a71960d 100755
--- a/ap/os/linux/linux-3.4.x/drivers/usb/gadget/adb_server.c
+++ b/ap/os/linux/linux-3.4.x/drivers/usb/gadget/adb_server.c
@@ -439,7 +439,7 @@
 			adb_server_plug_notify(USB_RPMSG_NOTIFY_ADB_ONLINE);
 			dev->agent_start = 1;	
 			dev->agt_error = 0;
-			//wake_up(&dev->agt_start_wait);
+			wake_up(&dev->agt_start_wait);
 		//wakeup adb read and return	
 		//dev->rx_done = 1;
 		//wake_up(&dev->read_wq);
@@ -476,6 +476,10 @@
 		printk("adb_enable_rpmsg_agent, adb is NULL, fail\n");
 		return -1;
 	}
+	if(g_adb_agent->adb_ready == 0){
+		printk("adb_enable_rpmsg_agent, adb has not init ok, return\n");
+		return;
+	}
 	g_adb_agent->agent_state = ((flag != 0) ? 1 : 0);
 	atomic_set(&g_adb_agent->agent_switch, 1);
 	printk("adb_enable_rpmsg_agent,now %s adb agent\n", (g_adb_agent->agent_state == 1) ? "start" : "stop");
@@ -552,7 +556,7 @@
 			pr_debug("rpmsg_recv: failed to queue req %p (%d)\n", req, ret);
 			r = -EIO;
 			dev->agt_error = 1;
-			printk("rpmsg_recv ep-queue fail ret:%d", r);
+			USBSTACK_DBG("rpmsg_recv ep-queue fail ret:%d", r);
 			goto done;
 		} else {
 			USBSTACK_DBG("rx %p queue\n", req);
diff --git a/ap/os/linux/linux-3.4.x/drivers/usb/gadget/f_adb.c b/ap/os/linux/linux-3.4.x/drivers/usb/gadget/f_adb.c
index 9561ca8..3a506fc 100755
--- a/ap/os/linux/linux-3.4.x/drivers/usb/gadget/f_adb.c
+++ b/ap/os/linux/linux-3.4.x/drivers/usb/gadget/f_adb.c
@@ -88,7 +88,9 @@
 #endif	
 	struct work_struct online_inform;	 /* online inform USB adb  */	
 	struct work_struct offline_inform;	 /* offline inform USB adb  */	
-	
+
+	//this flag means adb is ok
+	int adb_ready;	
 #ifdef CONFIG_PM
 	u32 suspend_state;
 #endif
@@ -734,9 +736,18 @@
 		usb_ep_disable(dev->ep_in);
 		return ret;
 	}
+	
+	dev->adb_ready = 1;
+	
 #ifdef _USE_VEHICLE_DC	
 	//maybe need clear adb server state
 	adb_agent_close();	
+	if(usb_get_adb_agent() == 1){
+		//delay time is num of jiffies
+		printk("---adb_function_set_alt, switch to cap\n");
+		dev->online = 1;
+		schedule_delayed_work(&_adb_dev->agent_switch_work, 0);
+	}else
 #endif
 	schedule_work(&dev->online_inform);
 
@@ -750,7 +761,6 @@
 		/* readers may be blocked waiting for us to go online */
 		wake_up(&dev->read_wq);
 	}
-	
 	return 0;
 }
 
@@ -761,6 +771,7 @@
 
 	USBSTACK_DBG("%s", __func__);
 
+	dev->adb_ready = 0;
 	if(atomic_read(&dev->enable_excl)==0)
 		return;
 	else
diff --git a/ap/os/linux/linux-3.4.x/drivers/usb/gadget/usb_netlink.c b/ap/os/linux/linux-3.4.x/drivers/usb/gadget/usb_netlink.c
index 7e53a63..b2f470f 100755
--- a/ap/os/linux/linux-3.4.x/drivers/usb/gadget/usb_netlink.c
+++ b/ap/os/linux/linux-3.4.x/drivers/usb/gadget/usb_netlink.c
@@ -1020,6 +1020,11 @@
 			switch_mode = USB_SWITCH_DEBUG;

 			usb_record_dbginfo(USB_SWITCH_TO_DEBUG, 0, 0);

 			schedule_work(&switch_usbmode);

+			//if boot from user mode, this flag doesn't set

+			if(adb_agent_state == 0){

+				printk("usb_parse_cap_notify,set debug mode, set adb_agent_state \n");

+				adb_agent_state =1;				

+			}

 			break;

 		case USB_RPMSG_SWITCH_USER_MODE:

 			if(switch_mode == USB_SWITCH_USER){

diff --git a/ap/os/linux/linux-3.4.x/fs/open.c b/ap/os/linux/linux-3.4.x/fs/open.c
old mode 100644
new mode 100755
index cf1d34f..ece5fe5
--- a/ap/os/linux/linux-3.4.x/fs/open.c
+++ b/ap/os/linux/linux-3.4.x/fs/open.c
@@ -33,6 +33,10 @@
 
 #include "internal.h"
 
+#ifdef CONFIG_SYSVIPC_CROSS_SHM
+#include <../ipc/shm_ctrl.h>
+#endif
+
 int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
 	struct file *filp)
 {
@@ -977,7 +981,9 @@
 	int lookup = build_open_flags(flags, mode, &op);
 	char *tmp = getname(filename);
 	int fd = PTR_ERR(tmp);
-
+#ifdef CONFIG_SYSVIPC_CROSS_SHM
+	char *ptr = NULL;
+#endif	
 	if (!IS_ERR(tmp)) {
 		fd = get_unused_fd_flags(flags);
 		if (fd >= 0) {
@@ -988,6 +994,16 @@
 			} else {
 				fsnotify_open(f);
 				fd_install(fd, f);
+#ifdef CONFIG_SYSVIPC_CROSS_SHM
+				ptr = strrchr(tmp, '/');
+				if (ptr)
+				{
+					if (strncmp(ptr + 1, "remote-", strlen("remote-"))== 0)
+					{
+						f->shm_flags =  SHM_REMOTE_POSIX_YES;
+					}
+				}
+#endif
 			}
 		}
 		putname(tmp);
diff --git a/ap/os/linux/linux-3.4.x/include/linux/fs.h b/ap/os/linux/linux-3.4.x/include/linux/fs.h
old mode 100644
new mode 100755
index 210c347..463df11
--- a/ap/os/linux/linux-3.4.x/include/linux/fs.h
+++ b/ap/os/linux/linux-3.4.x/include/linux/fs.h
@@ -1021,6 +1021,9 @@
 #ifdef CONFIG_DEBUG_WRITECOUNT
 	unsigned long f_mnt_write_state;
 #endif
+#ifdef CONFIG_SYSVIPC_CROSS_SHM
+	unsigned int 	shm_flags;
+#endif
 };
 
 struct file_handle {
diff --git a/ap/os/linux/linux-3.4.x/include/linux/net.h b/ap/os/linux/linux-3.4.x/include/linux/net.h
old mode 100644
new mode 100755
index 16b4996..f323b7d
--- a/ap/os/linux/linux-3.4.x/include/linux/net.h
+++ b/ap/os/linux/linux-3.4.x/include/linux/net.h
@@ -148,6 +148,10 @@
 	struct socket_wq __rcu	*wq;
 
 	struct file		*file;
+#ifdef CONFIG_IPC_SOCKET
+	int fd;
+	struct hlist_head peer;
+#endif
 	struct sock		*sk;
 	const struct proto_ops	*ops;
 };
diff --git a/ap/os/linux/linux-3.4.x/include/linux/socket.h b/ap/os/linux/linux-3.4.x/include/linux/socket.h
old mode 100644
new mode 100755
index 9b54ebe..cc1afdc
--- a/ap/os/linux/linux-3.4.x/include/linux/socket.h
+++ b/ap/os/linux/linux-3.4.x/include/linux/socket.h
@@ -343,5 +343,6 @@
 			  unsigned int flags, struct timespec *timeout);
 extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg,
 			  unsigned int vlen, unsigned int flags);
+
 #endif /* not kernel and not glibc */
 #endif /* _LINUX_SOCKET_H */
diff --git a/ap/os/linux/linux-3.4.x/include/linux/socket_rpmsg.h b/ap/os/linux/linux-3.4.x/include/linux/socket_rpmsg.h
new file mode 100755
index 0000000..c6a9292
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/include/linux/socket_rpmsg.h
@@ -0,0 +1,227 @@
+#ifndef SOCKET_RPMSG_H

+#define SOCKET_RPMSG_H

+

+#include <linux/interrupt.h>

+#include <linux/kthread.h>

+#include <linux/spinlock.h>

+#include <linux/semaphore.h>

+#include <linux/netdevice.h>

+#include <linux/skbuff.h>

+#include <linux/un.h>

+#include <linux/types.h>

+#include <linux/soc/zte/rpm/rpmsg.h>

+

+#include <net/sock.h>

+

+extern int socket_rpmsg_debug;

+

+#define sk_soc_dbg(format, arg...) if(socket_rpmsg_debug == 1) \

+	printk(KERN_DEBUG "[socket_rpmsg]<%s>: " format "\n" ,__func__ , ## arg)

+#define sk_soc_info(format, arg...) if(socket_rpmsg_debug == 1) \

+	printk(KERN_INFO "[socket_rpmsg]<%s>: " format "\n" ,__func__ , ## arg)

+

+#define sk_soc_err(format, arg...) printk(KERN_ERR "[socket_rpmsg]<%s>: " format "\n" , \

+	__func__ , ## arg)

+

+#define sk_soc_warn(format, arg...) printk(KERN_WARNING "[socket_rpmsg]<%s>: " format "\n" , \

+	__func__ , ## arg)

+

+

+

+#define	 ICP_CHANNEL_SIZE 	(16 * 1024)

+

+/*remote data ,to local,read from rpmsg channel*/

+#define DIR_UPLINK		1

+/*local data ,to remote,need write rpmsg channel*/

+#define DIR_DOWNLINK	2

+#define sockSocCreateChannel zDrvRpMsg_CreateChannel_Cap

+#define sockSocWrite         zDrvRpMsg_Write_Cap

+#define sockSocRead          zDrvRpMsg_Read_Cap

+

+#define SOCK_OP_RESULT		0

+

+extern spinlock_t sock_table_lock;

+extern spinlock_t sock_rpmsg_table_lock;

+extern spinlock_t sock_socket_table_lock;

+extern spinlock_t sock_release_table_lock;

+extern spinlock_t sock_release_lock;

+extern spinlock_t  sock_release_peer_lock;

+typedef enum _soc_msg_type

+{

+	MSG_TYPE_FIND = 0,

+	MSG_TYPE_FIND_RESULT,

+	MSG_TYPE_ADD_WAIT_QUEUE,

+	MSG_TYPE_REMOVE_WAIT_QUEUE,

+	MSG_TYPE_SYNC_IPC_SOCKET,

+	MSG_TYPE_WAIT_FOR_PEER,

+	MSG_TYPE_DATA_READY,

+	MSG_TYPE_SEND_MSG,

+	MSG_TYPE_SET_PEER,

+	MSG_TYPE_UPDATE_PEER,

+	MSG_TYPE_SOCK_PUT,

+	MSG_TYPE_ADD_SKB_QUEUE_TAIL,

+	MSG_TYPE_RECVQ_FULL,

+	MSG_TYPE_RECVQ_FULL_RESULT,

+	MSG_TYPE_RECVQ_FULL_LOCKLESS_AND_DEAD,

+	MSG_TYPE_RECVQ_FULL_LOCKLESS_AND_DEAD_RESULT,

+	MSG_TYPE_PEER_CLEAR,

+	MSG_TYPE_WAKE_UP_INTERRUPTIBLE_POLL,

+	MSG_TYPE_TEST_FLAG,

+	MSG_TYPE_TEST_FLAG_RESULT,

+	MSG_TYPE_GET_SOCKET_STATES,

+	MSG_TYPE_GET_SOCKET_STATES_RESULT,

+	MSG_TYPE_STREAM_CONNECT, //21

+	MSG_TYPE_SOCKET_RELEASE, //22

+	MSG_TYPE_DGRAM_DISCONNECTED,

+	MSG_TYPE_STATE_LOCK,

+	MSG_TYPE_STATE_UNLOCK,

+	MSG_TYPE_SOCK_HOLD,

+	MSG_TYPE_RELEASE_PEER,

+	MSG_TYPE_NOTIFY_PROXY_CHANGE,

+}soc_msg_type;

+

+struct sock_thread_info {

+	struct task_struct *p_thread;	

+	struct list_head	p_sock_list;

+	struct spinlock 	p_sock_lock;

+	struct semaphore 	p_sock_sem;

+

+	int bstop;

+};

+

+struct sock_channel {

+    T_ZDrvRpMsg_ActorID core_id;

+    T_ZDrvRpMsg_ChID channel_id;

+    unsigned int channel_size;

+    //struct task_struct *rcv_thread;

+	//struct task_struct *main_thread;

+	struct sock_thread_info recv_thread_info;

+	struct sock_thread_info main_thread_info;

+};

+

+struct sock_elem_flag {

+	int sk_err;

+	int sk_error_report;

+	int skstate;

+	u8 skshutdown;

+};

+

+struct	sock_rpmsg

+{

+	struct list_head list;

+	soc_msg_type msg_type;

+	uint32_t dir;

+	struct sockaddr_un sockaddr;

+	int addr_len;

+	int socktype; 

+	unsigned int hash;

+	struct sock_elem_flag elem;

+	//struct sock sock;	

+	int clientfd;

+	int serverfd;

+	int clientproxyfd;

+	int serverproxyfd;

+	int newclientfd;

+	void* clientsock; //ÀàÐÍΪstruct socket

+	void* serversock; //ÀàÐÍΪstruct socket

+	void* newsock;

+	void* clientproxysock; //ÀàÐÍΪstruct socket

+	void* serverproxysock; //ÀàÐÍΪstruct socket

+	int result;

+	enum sock_flags flag;

+	unsigned long flags;

+	long timeo;

+	unsigned int  msg_flags;

+	int isfistfind;

+	void* key;

+	unsigned int index;

+	int data_len;

+	unsigned char data[0];	

+};

+

+struct	ipc_socket

+{	

+	struct hlist_node	hlist_node;

+	struct socket* socket;

+	struct sock* sock;

+	int socktype; 

+	int localfd;  //±¾µØ¿Í»§¶Ëfd

+	int sockfd;   //±¾µØ´úÀísocketµÄfd

+	int remotefd; //¶ÔÓ¦Ô¶¶ËʵÌåµÄfd

+	int remoteproxyfd; //¶ÔÓ¦Ô¶¶Ë´úÀíµÄ fd

+	struct socket* localsocket; //±¾µØ¿Í»§¶Ësocket

+	struct socket* proxysocket; //±¾µØ´úÀísocket

+	struct socket* remotesocket; //¶ÔÓ¦Ô¶¶ËʵÌåµÄsocket

+	struct socket* remoteproxysocket; //¶ÔÓ¦Ô¶¶Ë´úÀíµÄsocket

+	void* key;

+};

+

+struct sock_rpmsg_info

+{

+	struct hlist_node	hlist_node;

+	struct sock_rpmsg sock_rpmsg;

+	struct semaphore sock_sem;

+	struct ipc_socket * ipc_socket;

+	void* key; //±êʶrpmsgµÄ¹Ø¼ü×Ö

+};

+

+struct	peer_sock_info

+{	

+	int fd;

+	int peerfd;

+	struct sock* sock;

+	struct sock* peersock;

+	long timeo;

+};

+

+struct release_socket{

+	struct list_head	list_node;

+#if 0	

+	struct socket* sock;

+	int clientfd;

+	void* clientsock;

+#endif	

+	int localfd; //¿Í»§¶Ëfd

+	int proxyfd;   //±¾µØ´úÀísocketµÄfd

+	int remotefd; //¶ÔÓ¦Ô¶¶ËʵÌåµÄfd

+	struct socket* localsocket; //±¾µØ¿Í»§¶Ësocket

+	struct socket* proxysocket; //±¾µØ´úÀísocket

+	struct socket* remotesocket; //¶ÔÓ¦Ô¶¶ËʵÌåµÄsocket

+	struct socket* remoteproxysocket; //¶ÔÓ¦´úÀíµÄsocket

+};

+

+//´æ·ÅËùÓвÎÓë½»»¥µÄsocketµØÖ·

+struct socket_info{

+	struct hlist_node	hlist_node;

+	struct socket* proxysocket;

+	struct socket* localsocket;

+};

+

+int sock_soc_recvq_full(const struct sock *sk);

+int sock_soc_set_peer(struct sock *sock, struct sock *other);

+int sock_soc_sock_put(struct sock *other);

+int sock_soc_msg_send(struct sock *sock, struct sock *other, struct msghdr *msg, size_t len);

+long sock_wait_for_peer(struct sock *sock, struct sock *other, long timeo);

+int sock_soc_sk_data_ready(struct sock *sk);

+int sock_sync_ipc_socket(struct sock_elem_flag* elem_flag, struct sock *other);

+void sock_soc_add_skb_queue_tail(struct sock *sock, struct sock *other);

+void sock_soc_add_wait_queue(struct sock *sock, struct sock *other);

+void sock_soc_remove_wait_queue(struct sock *sock, struct sock *other);

+struct sock *sock_soc_find_other(struct socket* socket,

+				    struct sockaddr_un *sunname, int len,

+				    int type, unsigned int hash, int *error);

+int unix_is_ipc_socket(struct sock *sock);

+int unix_is_ipc_local_socket(struct sock *sock);

+int sock_soc_test_flags(struct sock *other, enum sock_flags flag);

+int sock_soc_recvq_full_lockless_and_dead(const struct sock *other);

+int sock_soc_get_state(struct sock_elem_flag* elem_flag, struct sock *other);

+void sock_soc_stream_connect(struct sock *sock, struct sock *other, struct sockaddr_un *sunname, int len,int flags);

+int sock_soc_update_peer(struct socket *sock, struct socket *newsock);

+int sock_soc_dgram_disconnected(struct sock *sock, struct sock *other);

+void sock_soc_state_lock(struct sock *other);

+void sock_soc_state_unlock(struct sock *other);

+void sock_soc_delay_release(struct socket *sock);

+void sock_soc_sock_hold(struct sock *other);

+

+#endif

+

diff --git a/ap/os/linux/linux-3.4.x/include/net/af_unix.h b/ap/os/linux/linux-3.4.x/include/net/af_unix.h
old mode 100644
new mode 100755
index ca68e2c..d997e45
--- a/ap/os/linux/linux-3.4.x/include/net/af_unix.h
+++ b/ap/os/linux/linux-3.4.x/include/net/af_unix.h
@@ -5,6 +5,9 @@
 #include <linux/un.h>
 #include <linux/mutex.h>
 #include <net/sock.h>
+#ifdef CONFIG_IPC_SOCKET
+#include <linux/socket_rpmsg.h>
+#endif
 
 extern void unix_inflight(struct file *fp);
 extern void unix_notinflight(struct file *fp);
@@ -60,6 +63,9 @@
 	unsigned int		gc_maybe_cycle : 1;
 	unsigned char		recursion_level;
 	struct socket_wq	peer_wq;
+#ifdef CONFIG_IPC_SOCKET
+	struct release_socket rsock;
+#endif	
 };
 #define unix_sk(__sk) ((struct unix_sock *)__sk)
 
diff --git a/ap/os/linux/linux-3.4.x/include/net/sock.h b/ap/os/linux/linux-3.4.x/include/net/sock.h
index efab120..7f2098b 100755
--- a/ap/os/linux/linux-3.4.x/include/net/sock.h
+++ b/ap/os/linux/linux-3.4.x/include/net/sock.h
@@ -85,6 +85,16 @@
 {
 }
 #endif
+
+#ifdef CONFIG_IPC_SOCKET
+extern int socket_rpmsg_debug;
+
+#define sk_soc_dbg(format, arg...) if(socket_rpmsg_debug == 1) \
+	printk(KERN_DEBUG "[socket_rpmsg]<%s>: " format "\n" ,__func__ , ## arg)
+#define sk_soc_info(format, arg...) if(socket_rpmsg_debug == 1) \
+	printk(KERN_INFO "[socket_rpmsg]<%s>: " format "\n" ,__func__ , ## arg)
+
+#endif
 /*
  * This structure really needs to be cleaned up.
  * Most of it is for TCP, and not used by any of
@@ -127,6 +137,15 @@
 struct proto;
 struct net;
 
+#ifdef CONFIG_IPC_SOCKET
+
+enum sock_flags;
+extern int unix_is_ipc_socket(struct sock *sock);
+extern int sock_soc_test_flags(struct sock *other, enum sock_flags flag);
+extern int sock_soc_sock_put(struct sock *other);
+extern void sock_soc_sock_hold(struct sock *other);
+
+#endif
 /**
  *	struct sock_common - minimal network layer representation of sockets
  *	@skc_daddr: Foreign IPv4 addr
@@ -382,6 +401,12 @@
   	int			(*sk_backlog_rcv)(struct sock *sk,
 						  struct sk_buff *skb);  
 	void                    (*sk_destruct)(struct sock *sk);
+#ifdef CONFIG_IPC_SOCKET
+	int ipc_flag;
+	int sk_fd;
+	struct sock* proxy_sock;
+	u8 closed;
+#endif	
 };
 
 static inline int sk_peek_offset(struct sock *sk, int flags)
@@ -495,6 +520,9 @@
 static inline void sock_hold(struct sock *sk)
 {
 	atomic_inc(&sk->sk_refcnt);
+#ifdef CONFIG_IPC_SOCKET
+    sk_soc_dbg("sock_hold sk=%x, sk->sk_refcnt=%d\n", sk, sk->sk_refcnt);
+#endif	
 }
 
 /* Ungrab socket in the context, which assumes that socket refcnt
@@ -502,6 +530,9 @@
  */
 static inline void __sock_put(struct sock *sk)
 {
+#ifdef CONFIG_IPC_SOCKET	
+	sk_soc_dbg("__sock_put sk=%x, sk->sk_refcnt=%d\n",sk, sk->sk_refcnt);
+#endif	
 	atomic_dec(&sk->sk_refcnt);
 }
 
@@ -629,6 +660,10 @@
 		     * Will use last 4 bytes of packet sent from
 		     * user-space instead.
 		     */
+#ifdef CONFIG_IPC_SOCKET
+    SOCK_IPCSOCK,  /*Indicates whether it is a cross core socket */
+    SOCK_IPC_LOCAL,
+#endif
 };
 
 static inline void sock_copy_flags(struct sock *nsk, struct sock *osk)
@@ -648,7 +683,16 @@
 
 static inline int sock_flag(struct sock *sk, enum sock_flags flag)
 {
+#ifdef CONFIG_IPC_SOCKET
+	if(unix_is_ipc_socket(sk)){
+		return sock_soc_test_flags(sk, flag);
+	}
+	else{
+#endif
 	return test_bit(flag, &sk->sk_flags);
+#ifdef CONFIG_IPC_SOCKET
+	}
+#endif
 }
 
 static inline void sk_acceptq_removed(struct sock *sk)
@@ -1586,7 +1630,10 @@
 }
 
 static inline void sk_set_socket(struct sock *sk, struct socket *sock)
-{
+{	
+#ifdef CONFIG_IPC_SOCKET	
+	sk_soc_dbg("sk_set_socket sk=%x, sock=%x \n", sk, sock);
+#endif	
 	sk_tx_queue_clear(sk);
 	sk->sk_socket = sock;
 }
diff --git a/ap/os/linux/linux-3.4.x/ipc/shm.c b/ap/os/linux/linux-3.4.x/ipc/shm.c
index 47d3255..8bf7f7b 100755
--- a/ap/os/linux/linux-3.4.x/ipc/shm.c
+++ b/ap/os/linux/linux-3.4.x/ipc/shm.c
@@ -72,11 +72,6 @@
 static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
 #endif
 
-#ifdef CONFIG_SYSVIPC_CROSS_SHM
-extern int shm_remote_free_pages(struct vm_area_struct *unmap_vma);
-extern int shm_do_remote_map_vma(struct vm_area_struct *vma, key_t key);
-#endif
-
 void shm_init_ns(struct ipc_namespace *ns)
 {
 	ns->shm_ctlmax = SHMMAX;
@@ -150,20 +145,50 @@
 }
 
 #ifdef CONFIG_SYSVIPC_CROSS_SHM
-void shm_mmap_pagetable(struct vm_area_struct *vma, struct file *file)
+key_t shm_do_remote_analy_key(struct file *file)
 {
-	int ret = 0;
+	key_t  key = 0;	
+	char   *shm_name = NULL;
 	struct shm_file_data *sfd;
 	struct shmid_kernel  *shp;
+	struct path    *shm_path  = NULL;
+	struct dentry  *shm_dentry = NULL;
 
-	sfd = shm_file_data(file);
-	shp = shm_lock(sfd->ns, sfd->id);
+	if (file && (file->shm_flags == SHM_REMOTE_SYSV_YES))
+	{
+		sfd = shm_file_data(file);
+		shp = shm_lock(sfd->ns, sfd->id);
+		key = shp->shm_perm.key;
+		shm_unlock(shp);
+	}
+	else if (file && (file->shm_flags == SHM_REMOTE_POSIX_YES))
+	{
+		shm_path = &file->f_path;
+		
+		if(shm_path && (shm_path->dentry))
+		{
+			shm_name = shm_path->dentry->d_name.name;
+			if (!shm_name)
+				panic("shm_posix_mmap_pagetable name is NULL\n");
+		}
+		key = shm_hash_name_to_key(shm_name, strlen(shm_name));
+	}
+	return key;
+}
 
-	ret = shm_do_remote_map_vma(vma, shp->shm_perm.key);
+int shm_ipc_mmap_pagetable(struct vm_area_struct *vma, struct file *file)
+{
+	int   ret = 0;
+	key_t shm_key = 0;
+		
+	shm_key = shm_do_remote_analy_key(file);
+	ret     = shm_do_remote_map_vma(vma, shm_key);
 	if (ret < 0)
-		printk("shm_mmap_pagetable Error");
-
-	shm_unlock(shp);
+	{
+		printk("shm_ipc_mmap_pagetable Error: No Mem\n");
+		return -ENOMEM;
+	}
+	return ret;
 }
 #endif
 
@@ -266,10 +291,7 @@
 	shp->shm_lprid = task_tgid_vnr(current);
 	shp->shm_dtim = get_seconds();
 	shp->shm_nattch--;
-#ifdef CONFIG_SYSVIPC_CROSS_SHM
-	if (shp->shm_perm.rpmflag == TRUE)
-		shm_remote_free_pages(shp->shm_perm.key);
-#endif
+
 	if (shm_may_destroy(ns, shp))
 		shm_destroy(ns, shp);
 	else
@@ -548,10 +570,21 @@
 	shp->shm_file = file;
 	shp->shm_creator = current;
 #ifdef CONFIG_SYSVIPC_CROSS_SHM
-	if((key & SHM_REMOTE_ATTR_MASK) == SHM_REMOTE_ATTR_MASK)
-		shp->shm_perm.rpmflag = TRUE;
+	if((key & SHM_REMOTE_SYSV_MASK) == SHM_REMOTE_SYSV_MASK)
+	{
+		error = shm_do_newseg_check(key, size);
+		if (error < 0)
+		{
+			printk("shm size error, should be the same PAGE_ALIGN size\n");
+			return error;
+		}
+		else
+			shp->shm_perm.rpmflag = TRUE;
+	}
 	else
+	{
 		shp->shm_perm.rpmflag = FALSE;
+	}
 #endif
 	/*
 	 * shmid gets reported as "inode#" in /proc/pid/maps.
@@ -1087,7 +1120,7 @@
 	sfd->vm_ops = NULL;
 #ifdef CONFIG_SYSVIPC_CROSS_SHM	
 	if(shp->shm_perm.rpmflag == TRUE)
-		file->f_flags = SHM_REMOTE_ATTR_YES;
+		file->shm_flags = SHM_REMOTE_SYSV_YES;
 #endif
 	down_write(&current->mm->mmap_sem);
 	if (addr && !(shmflg & SHM_REMAP)) {
diff --git a/ap/os/linux/linux-3.4.x/ipc/shm_ctrl.c b/ap/os/linux/linux-3.4.x/ipc/shm_ctrl.c
index 598cb28..183a8bd 100755
--- a/ap/os/linux/linux-3.4.x/ipc/shm_ctrl.c
+++ b/ap/os/linux/linux-3.4.x/ipc/shm_ctrl.c
@@ -23,6 +23,10 @@
 #define SHM_UNIT_BUFF_ORDER       (12)
 #define SHM_KEYS_STATUS_LEN       (4*1024)
 #define SHM_REMOTE_BUFF_LEN       (128*1024)
+#define SHM_POSIX_HASH_CHARS      (26)
+#define SHM_POSIX_HASH_BASE       (62)
+#define SHM_POSIX_HASH_MASK       (0x7FF)
+
 #define SHM_BUFF_BASE_PHY_ADDR    (g_shm_phyAddr)
  
 #define SHM_UNIT_BUFF_SIZE        (1UL<<SHM_UNIT_BUFF_ORDER) /*4KB*/
@@ -51,6 +55,36 @@
 struct shm_entity *shm_remote_manager;
 
 /*******************************************************************************
+* ¹¦ÄÜÃèÊö:     shm_hash_name_to_key
+* ²ÎÊý˵Ã÷:
+*    (´«Èë²ÎÊý) name: ¹²ÏíÄÚ´æÃû³Æ
+*    (´«Èë²ÎÊý) len: ¹²ÏíÄÚ´æÃû³Æ³¤¶È
+*    (´«³ö²ÎÊý) ÎÞ
+* ·µ »Ø Öµ:     
+* ÆäËü˵Ã÷:     This function is used for calc hash value of the name(-2048~-4096)
+*******************************************************************************/
+key_t shm_hash_name_to_key(const char *name, int len)
+{
+    int   i        = 0;
+    key_t tmp_key  = 0;
+    key_t hash_key = 0;
+    unsigned long long id = 0;
+
+    for (; i < len; i++)
+    {
+        if (name[i] >= 'A' && name[i] <= 'Z')
+            id = id*SHM_POSIX_HASH_BASE + name[i]-'A';
+        else if (name[i] >= 'a' && name[i] <= 'z')
+            id = id*SHM_POSIX_HASH_BASE + name[i]-'a' + SHM_POSIX_HASH_CHARS;
+        else if (name[i] >= '0' && name[i] <= '9')
+            id = id*SHM_POSIX_HASH_BASE + name[i]-'0' + 2*SHM_POSIX_HASH_CHARS;
+    }
+    tmp_key =(id & SHM_POSIX_HASH_MASK) + (SHM_POSIX_HASH_MASK + 1);
+    hash_key = ~tmp_key + 1; 
+    return hash_key;
+}
+
+/*******************************************************************************
 * ¹¦ÄÜÃèÊö:     shm_quary_keyArray
 * ²ÎÊý˵Ã÷:
 *    (´«Èë²ÎÊý)    void
@@ -330,6 +364,58 @@
 }
 
 /*******************************************************************************
+* ¹¦ÄÜÃèÊö:     shm_do_newseg_check
+* ²ÎÊý˵Ã÷:     
+*    (´«Èë²ÎÊý)    void
+*    (´«³ö²ÎÊý)    void
+* ·µ »Ø Öµ:     SHM_CTRL_OK or SHM_CTRL_ERROR
+* ÆäËü˵Ã÷:     This function is used for check key and len                    
+*******************************************************************************/
+int shm_do_newseg_check(key_t key, unsigned long len)
+{
+    int                  ret        = 0;
+    int                  key_index  = 0;
+    unsigned int         shm_weight = 0;
+    unsigned int         shm_pages  = 0;
+    struct shm_key_node  *key_node  = NULL;
+
+    if(g_shm_region == NULL)
+    {
+        printk("shm_do_newsg_check:Shm region is not ready\n");
+        return SHM_CTRL_ERROR;
+    }
+    soft_spin_lock(SHM_SFLOCK);
+
+    key_index = shm_quary_keyArray(key);
+
+    if (key_index < 0) 
+    {
+        soft_spin_unlock(SHM_SFLOCK);    
+        return SHM_CTRL_OK;
+    }
+    
+    if ((0 <= key_index) && (key_index < SHM_UNIT_NUM_BITS))
+    {
+        key_node = &shm_remote_manager->keys_info_head[key_index];
+    }
+    else
+    {
+        soft_spin_unlock(SHM_SFLOCK);
+        panic("key_index out of range: failed\n");
+    }
+
+    shm_pages  =  PAGE_ALIGN(len) >> PAGE_SHIFT;
+    shm_weight = bitmap_weight(key_node->shm_inuse_index, SHM_UNIT_NUM_BITS);
+    soft_spin_unlock(SHM_SFLOCK);
+
+    /*APºÍCAP¹²ÏíÄÚ´æ´óСӦƥÅä*/
+    if(shm_weight != shm_pages) 
+        return -EINVAL;
+    else
+        return SHM_CTRL_OK;
+}
+
+/*******************************************************************************
 * ¹¦ÄÜÃèÊö:     shm_do_remote_map_vma
 * ²ÎÊý˵Ã÷:     
 *    (´«Èë²ÎÊý)    void
@@ -374,9 +460,14 @@
     vm_addr = vma->vm_start;
     
     if ((0 <= key_index) && (key_index < SHM_UNIT_NUM_BITS))
+    {
         key_node = &shm_remote_manager->keys_info_head[key_index];
+    }
     else
+    {
+        soft_spin_unlock(SHM_SFLOCK);
         panic("key_index out of range: failed\n");
+    }
 
     memcpy(shm_inuse_tmp, key_node->shm_inuse_index, sizeof(shm_inuse_tmp));
 
diff --git a/ap/os/linux/linux-3.4.x/ipc/shm_ctrl.h b/ap/os/linux/linux-3.4.x/ipc/shm_ctrl.h
index 5a850a1..4726ea8 100755
--- a/ap/os/linux/linux-3.4.x/ipc/shm_ctrl.h
+++ b/ap/os/linux/linux-3.4.x/ipc/shm_ctrl.h
@@ -29,19 +29,24 @@
 #include <mach/spinlock.h>
 
 /**
- * Êý¾ÝÀàÐͶ¨Òå
- */
+ * ºê¶¨Òå
+*/
 #define TRUE   1
 #define FALSE  0
-#define SHM_REMOTE_ATTR_YES       (0x594553) /*YES ASCIIÂë*/
-#define SHM_REMOTE_ATTR_MASK      (0xFFFFF000)
+
 #define SHM_CTRL_OK               (0)
 #define SHM_CTRL_ERROR            (-1)
 #define SHM_CTRL_VMA_LINK_NUM     (2)
 #define SHM_CTRL_MEMSYNC_CHANNEL  (15)
 #define SHM_CTRL_CHANNEL_SIZE     (0x40)
 #define SHM_CTRL_LONG_32BIT       (32)
+#define SHM_REMOTE_SYSV_YES       (0x73797376) /*SYSV ASCIIÂë*/
+#define SHM_REMOTE_POSIX_YES      (0x706F7378)  /*POSX ASCIIÂë*/
+#define SHM_REMOTE_SYSV_MASK      (0xFFFFF800) /*(key:-1~-2047)*/
 
+/**
+ * Êý¾ÝÀàÐͶ¨Òå
+ */
 struct shm_pool_msg
 {
     unsigned int shm_len;
@@ -50,7 +55,12 @@
     phys_addr_t  key_manage_phy;
 };
 
-
+extern int shm_remote_free_pages(key_t key);
+extern key_t shm_hash_name_to_key(const char *name, int len);
+extern int shm_do_newseg_check(key_t key, unsigned long len);
+extern int shm_do_remote_map_vma(struct vm_area_struct *vma, key_t key);
+extern void shm_unmap_page_range(struct mm_struct *mm, struct vm_area_struct *vma,
+                                 unsigned long addr, unsigned long end);
 #endif
 #endif // _SHM_CTRL_H
 
diff --git a/ap/os/linux/linux-3.4.x/mm/mmap.c b/ap/os/linux/linux-3.4.x/mm/mmap.c
index 88d133b..702f65d 100755
--- a/ap/os/linux/linux-3.4.x/mm/mmap.c
+++ b/ap/os/linux/linux-3.4.x/mm/mmap.c
@@ -41,9 +41,11 @@
 
 #ifdef CONFIG_SYSVIPC_CROSS_SHM
 #include <../ipc/shm_ctrl.h>
-extern void shm_mmap_pagetable(struct vm_area_struct *vma, struct file *file);
-extern void shm_unmap_page_range(struct mm_struct *mm, struct vm_area_struct *vma,
-			                      unsigned long addr, unsigned long end);
+extern key_t shm_do_remote_analy_key(struct file *file);
+extern int   shm_ipc_mmap_pagetable(struct vm_area_struct *vma, struct file *file);
+static void  shm_delete_vma_from_mm(struct vm_area_struct *vma);
+static void  shm_delete_vma(struct mm_struct *mm, struct vm_area_struct *vma);
+
 #define kenter(FMT, ...) \
 	no_printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__)
 #define kleave(FMT, ...) \
@@ -1435,11 +1437,18 @@
 		make_pages_present(addr, addr + len);
 	
 #ifdef CONFIG_SYSVIPC_CROSS_SHM 
-	/*Get real phy pgae*/
-	if (file && (file->f_flags == SHM_REMOTE_ATTR_YES))
-	{		
-		shm_mmap_pagetable(vma, file);		
-	}
+	if (file && ((file->shm_flags == SHM_REMOTE_SYSV_YES)
+		      || (file->shm_flags == SHM_REMOTE_POSIX_YES))) {
+		/*Get real phy pgae*/
+		error = shm_ipc_mmap_pagetable(vma, file);	
+		if (error < 0)
+		{
+			shm_delete_vma_from_mm(vma);
+			shm_delete_vma(mm, vma);
+			return error;
+		}
+	}	
+
 #endif
 	return addr;
 
@@ -2147,6 +2156,18 @@
 }
 
 #ifdef CONFIG_SYSVIPC_CROSS_SHM
+int shm_try_to_free_pages(struct file *file)
+{
+	int ret = 0;
+	key_t shm_key;
+
+	shm_key = shm_do_remote_analy_key(file);
+	ret     = shm_remote_free_pages(shm_key);
+	if (ret < 0)
+		printk("shm_try_to_free_pages Error\n");
+	return ret;
+}
+
 /*
  * delete a VMA from its owning mm_struct and address space
  */
@@ -2270,7 +2291,8 @@
 	}
 
 erase_whole_vma:
-	shm_unmap_page_range(mm, vma, start, end);
+	shm_unmap_page_range(mm, vma, start, end);	
+	shm_try_to_free_pages(vma->vm_file);
 	shm_delete_vma_from_mm(vma);
 	shm_delete_vma(mm, vma);
 	return 0;
@@ -2340,7 +2362,9 @@
 	vma = prev? prev->vm_next: mm->mmap;
 		
 #ifdef CONFIG_SYSVIPC_CROSS_SHM
-	if (vma->vm_file && (vma->vm_file->f_flags == SHM_REMOTE_ATTR_YES)) {
+	if (vma->vm_file && 
+		((vma->vm_file->shm_flags == SHM_REMOTE_SYSV_YES)
+		|| (vma->vm_file->shm_flags == SHM_REMOTE_POSIX_YES))) {
 		shm_ctrl_do_munmap(mm, start, len);
 		return 0;
 	}
@@ -2527,7 +2551,8 @@
 	vma_shm = mm->mmap;
 	while (vma_shm) {		
 		if ((vma_shm->vm_file) && 
-		   (vma_shm->vm_file->f_flags == SHM_REMOTE_ATTR_YES)) {
+		   ((vma_shm->vm_file->shm_flags == SHM_REMOTE_SYSV_YES)
+		    ||(vma_shm->vm_file->shm_flags == SHM_REMOTE_POSIX_YES))) {
 			vma = vma_shm->vm_next;
 			shm_ctrl_do_munmap(mm, vma_shm->vm_start, (vma_shm->vm_end - vma_shm->vm_start));
 			vma_shm = vma;
diff --git a/ap/os/linux/linux-3.4.x/net/Kconfig b/ap/os/linux/linux-3.4.x/net/Kconfig
old mode 100644
new mode 100755
index b3f685b..e3054f2
--- a/ap/os/linux/linux-3.4.x/net/Kconfig
+++ b/ap/os/linux/linux-3.4.x/net/Kconfig
@@ -382,5 +382,7 @@
 source "net/ceph/Kconfig"
 source "net/nfc/Kconfig"
 
-
+config IPC_SOCKET
+	bool "Config ipc socket"
+	default n
 endif   # if NET
diff --git a/ap/os/linux/linux-3.4.x/net/Makefile b/ap/os/linux/linux-3.4.x/net/Makefile
old mode 100644
new mode 100755
index 6865dab..3f9d8c1
--- a/ap/os/linux/linux-3.4.x/net/Makefile
+++ b/ap/os/linux/linux-3.4.x/net/Makefile
@@ -71,3 +71,4 @@
 obj-$(CONFIG_NFC)		+= nfc/
 obj-$(CONFIG_OPENVSWITCH)	+= openvswitch/
 obj-$(CONFIG_NET_ACTIVITY_STATS)		+= activity_stats.o
+obj-$(CONFIG_IPC_SOCKET) += socket_rpmsg.o
diff --git a/ap/os/linux/linux-3.4.x/net/bridge/br_forward.c b/ap/os/linux/linux-3.4.x/net/bridge/br_forward.c
index b3dc65f..36cde04 100755
--- a/ap/os/linux/linux-3.4.x/net/bridge/br_forward.c
+++ b/ap/os/linux/linux-3.4.x/net/bridge/br_forward.c
@@ -267,8 +267,6 @@
 void br_multicast_deliver(struct net_bridge_mdb_entry *mdst,
 			  struct sk_buff *skb)
 {
-	if(br_multicast_off)
-		return;
 	br_multicast_flood(mdst, skb, NULL, __br_deliver);
 }
 
@@ -276,8 +274,6 @@
 void br_multicast_forward(struct net_bridge_mdb_entry *mdst,
 			  struct sk_buff *skb, struct sk_buff *skb2)
 {
-	if(br_multicast_off)
-		return;
 	br_multicast_flood(mdst, skb, skb2, __br_forward);
 }
 #endif
diff --git a/ap/os/linux/linux-3.4.x/net/bridge/br_multicast.c b/ap/os/linux/linux-3.4.x/net/bridge/br_multicast.c
index 548920d..87ae8c3 100755
--- a/ap/os/linux/linux-3.4.x/net/bridge/br_multicast.c
+++ b/ap/os/linux/linux-3.4.x/net/bridge/br_multicast.c
@@ -38,7 +38,7 @@
 
 static void br_multicast_add_router(struct net_bridge *br,
 				    struct net_bridge_port *port);
-int br_multicast_off = 0;
+
 #if IS_ENABLED(CONFIG_IPV6)
 static inline int ipv6_is_transient_multicast(const struct in6_addr *addr)
 {
@@ -140,8 +140,6 @@
 struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
 					struct sk_buff *skb)
 {
-	if(br_multicast_off)
-		return NULL;
 	struct net_bridge_mdb_htable *mdb = rcu_dereference(br->mdb);
 	struct br_ip ip;
 
@@ -228,8 +226,6 @@
 
 static void br_multicast_group_expired(unsigned long data)
 {
-	if(br_multicast_off)
-		return;
 	struct net_bridge_mdb_entry *mp = (void *)data;
 	struct net_bridge *br = mp->br;
 	struct net_bridge_mdb_htable *mdb;
@@ -291,8 +287,6 @@
 
 static void br_multicast_port_group_expired(unsigned long data)
 {
-	if(br_multicast_off)
-		return;
 	struct net_bridge_port_group *pg = (void *)data;
 	struct net_bridge *br = pg->port->br;
 
@@ -731,8 +725,6 @@
 
 static void br_multicast_router_expired(unsigned long data)
 {
-	if(br_multicast_off)
-		return;
 	struct net_bridge_port *port = (void *)data;
 	struct net_bridge *br = port->br;
 
@@ -801,8 +793,6 @@
 
 static void br_multicast_port_query_expired(unsigned long data)
 {
-	if(br_multicast_off)
-		return;
 	struct net_bridge_port *port = (void *)data;
 	struct net_bridge *br = port->br;
 
@@ -824,8 +814,6 @@
 
 void br_multicast_add_port(struct net_bridge_port *port)
 {
-	if(br_multicast_off)
-		return;
 	port->multicast_router = 1;
 
 	setup_timer(&port->multicast_router_timer, br_multicast_router_expired,
@@ -836,8 +824,6 @@
 
 void br_multicast_del_port(struct net_bridge_port *port)
 {
-	if(br_multicast_off)
-		return;
 	del_timer_sync(&port->multicast_router_timer);
 }
 
@@ -853,8 +839,7 @@
 void br_multicast_enable_port(struct net_bridge_port *port)
 {
 	struct net_bridge *br = port->br;
-	if(br_multicast_off)
-		return;
+
 	spin_lock(&br->multicast_lock);
 	if (br->multicast_disabled || !netif_running(br->dev))
 		goto out;
@@ -872,8 +857,7 @@
 	struct net_bridge *br = port->br;
 	struct net_bridge_port_group *pg;
 	struct hlist_node *p, *n;
-	if(br_multicast_off)
-		return;
+
 	spin_lock(&br->multicast_lock);
 	hlist_for_each_entry_safe(pg, p, n, &port->mglist, mglist)
 		br_multicast_del_pg(br, pg);
@@ -1538,8 +1522,6 @@
 int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port,
 		     struct sk_buff *skb)
 {
-	if(br_multicast_off)
-		return 0;
 	BR_INPUT_SKB_CB(skb)->igmp = 0;
 	BR_INPUT_SKB_CB(skb)->mrouters_only = 0;
 
@@ -1561,8 +1543,7 @@
 static void br_multicast_query_expired(unsigned long data)
 {
 	struct net_bridge *br = (void *)data;
-	if(br_multicast_off)
-		return;
+
 	spin_lock(&br->multicast_lock);
 	if (br->multicast_startup_queries_sent <
 	    br->multicast_startup_query_count)
@@ -1575,8 +1556,6 @@
 
 void br_multicast_init(struct net_bridge *br)
 {
-	if(br_multicast_off)
-		return;
 	br->hash_elasticity = 4;
 	br->hash_max = 512;
 
@@ -1602,8 +1581,6 @@
 
 void br_multicast_open(struct net_bridge *br)
 {
-	if(br_multicast_off)
-		return;
 	br->multicast_startup_queries_sent = 0;
 
 	if (br->multicast_disabled)
@@ -1619,8 +1596,7 @@
 	struct hlist_node *p, *n;
 	u32 ver;
 	int i;
-	if(br_multicast_off)
-		return;
+
 	del_timer_sync(&br->multicast_router_timer);
 	del_timer_sync(&br->multicast_querier_timer);
 	del_timer_sync(&br->multicast_query_timer);
diff --git a/ap/os/linux/linux-3.4.x/net/bridge/br_private.h b/ap/os/linux/linux-3.4.x/net/bridge/br_private.h
index bfb0f3d..6822ef1 100755
--- a/ap/os/linux/linux-3.4.x/net/bridge/br_private.h
+++ b/ap/os/linux/linux-3.4.x/net/bridge/br_private.h
@@ -421,11 +421,8 @@
 extern int br_multicast_toggle(struct net_bridge *br, unsigned long val);
 extern int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val);
 
-extern int br_multicast_off;
 static inline bool br_multicast_is_router(struct net_bridge *br)
 {
-	if(br_multicast_off)
-		return 0;
 	return br->multicast_router == 2 ||
 	       (br->multicast_router == 1 &&
 		timer_pending(&br->multicast_router_timer));
diff --git a/ap/os/linux/linux-3.4.x/net/core/fastproc/fast_common.c b/ap/os/linux/linux-3.4.x/net/core/fastproc/fast_common.c
index d3f740d..787b227 100755
--- a/ap/os/linux/linux-3.4.x/net/core/fastproc/fast_common.c
+++ b/ap/os/linux/linux-3.4.x/net/core/fastproc/fast_common.c
@@ -1801,24 +1801,24 @@
     {
         skb_num6++;
         skb_bytes6 += skb->len;
-        
+
         //×é²¥µÄ¿ìËÙת·¢£¬´ýʵÏÖ£¬ÔÝʱֱ½Ó·µ»Ø¿ìËÙת·¢Ê§°Ü
         if(ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr))
         {
             multicast_num6++;
             return 0;
         }
-        
-        if (skb->nfct_reasm && printk_ratelimit()) {
-            printk("fast6_fw reasm \n");
+
+        if (skb->nfct_reasm) {
+            //printk("fast6_fw reasm\n");
             return 0;
         }
-        
+
       	/*  if (ipv6_hdr(skb)->nexthdr != IPPROTO_TCP && ipv6_hdr(skb)->nexthdr != IPPROTO_UDP){
         //    printk("wrong protocol v6 = %d\n", ipv6_hdr(skb)->nexthdr);
             return 0;
         }*/
-        
+
         if(!fast_iphdr_check(skb, ETH_P_IPV6)) 
     	{
 	    	ip6hdr_err_num++;
diff --git a/ap/os/linux/linux-3.4.x/net/core/fastproc/fast_track.c b/ap/os/linux/linux-3.4.x/net/core/fastproc/fast_track.c
index c118526..5d55426 100755
--- a/ap/os/linux/linux-3.4.x/net/core/fastproc/fast_track.c
+++ b/ap/os/linux/linux-3.4.x/net/core/fastproc/fast_track.c
@@ -1196,20 +1196,6 @@
 	.write = skb_debug_off_set,

 };

 

-extern int br_multicast_off;

-static ssize_t br_multicast_off_set(struct file *file,

-		const char __user *buffer, size_t count, loff_t *pos)

-{

-	br_multicast_off = 1;

-	printk("br_multicast_off\n");

-	return count;

-}

-		

-static const struct file_operations br_multicast_off_file_ops = {

-	.owner = THIS_MODULE,

-	.write = br_multicast_off_set,

-};

-

 //¿ìËÙת·¢procÎļþµÄ³õʼ»¯

 int fast_conntrack_init_proc(void)

 {

@@ -1242,10 +1228,6 @@
 	

     //turn off skb debug

     proc_create("skb_debug_off", 0440, init_net.proc_net, &skb_debug_off_file_ops);

-    

-    //turn off br multicast

-    proc_create("br_multi_off", 0440, init_net.proc_net, &br_multicast_off_file_ops);

-	

     return 1;

 }

 

diff --git a/ap/os/linux/linux-3.4.x/net/core/sock.c b/ap/os/linux/linux-3.4.x/net/core/sock.c
index 3204c53..5dec66d 100755
--- a/ap/os/linux/linux-3.4.x/net/core/sock.c
+++ b/ap/os/linux/linux-3.4.x/net/core/sock.c
@@ -137,6 +137,9 @@
 #endif
 
 #include <net/netfilter/nf_conntrack.h>
+#ifdef CONFIG_IPC_SOCKET
+#include <linux/socket_rpmsg.h>
+#endif
 
 
 static DEFINE_MUTEX(proto_list_mutex);
@@ -2694,7 +2697,10 @@
 extern void fast_sock_release(struct sock *sk);
 
 void sock_put(struct sock *sk)
-{    
+{	
+#ifdef CONFIG_IPC_SOCKET
+	sk_soc_info("sock_put enter sk=%x, sk->sk_refcnt=%d\n", sk, sk->sk_refcnt);
+#endif
     if (atomic_dec_and_test(&sk->sk_refcnt))
     {
         fast_sock_release(sk);
diff --git a/ap/os/linux/linux-3.4.x/net/ipv4/ping.c b/ap/os/linux/linux-3.4.x/net/ipv4/ping.c
old mode 100644
new mode 100755
index 5ff3ed1..0d2f13a
--- a/ap/os/linux/linux-3.4.x/net/ipv4/ping.c
+++ b/ap/os/linux/linux-3.4.x/net/ipv4/ping.c
@@ -135,16 +135,17 @@
 {
 	struct inet_sock *isk = inet_sk(sk);
 	pr_debug("ping_v4_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num);
+	//BDSA-2017-0084(CVE-2017-2671)
+	write_lock_bh(&ping_table.lock);
 	if (sk_hashed(sk)) {
-		write_lock_bh(&ping_table.lock);
 		hlist_nulls_del(&sk->sk_nulls_node);
 		sk_nulls_node_init(&sk->sk_nulls_node);
 		sock_put(sk);
 		isk->inet_num = 0;
 		isk->inet_sport = 0;
 		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
-		write_unlock_bh(&ping_table.lock);
 	}
+	write_unlock_bh(&ping_table.lock);
 }
 
 static struct sock *ping_v4_lookup(struct net *net, __be32 saddr, __be32 daddr,
diff --git a/ap/os/linux/linux-3.4.x/net/socket.c b/ap/os/linux/linux-3.4.x/net/socket.c
index 5406a3d..7ea3abd 100755
--- a/ap/os/linux/linux-3.4.x/net/socket.c
+++ b/ap/os/linux/linux-3.4.x/net/socket.c
@@ -402,7 +402,9 @@
 
 	if (likely(fd >= 0))
 		fd_install(fd, newfile);
-
+#ifdef CONFIG_IPC_SOCKET		
+	sock->fd = fd;
+#endif
 	return fd;
 }
 EXPORT_SYMBOL(sock_map_fd);
@@ -487,7 +489,9 @@
 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
 	inode->i_uid = current_fsuid();
 	inode->i_gid = current_fsgid();
-
+#ifdef CONFIG_IPC_SOCKET		
+	INIT_HLIST_HEAD(&sock->peer);
+#endif
 	percpu_add(sockets_in_use, 1);
 	return sock;
 }
@@ -1379,7 +1383,7 @@
 out_release:
 	sock_release(sock);	
 	//return retval;
-	return ERRNO_TRACK(retval);
+	return ERRNO_TRACK(retval);	
 }
 
 /*
@@ -1572,7 +1576,9 @@
 		sock_release(newsock);
 		goto out_put;
 	}
-
+#ifdef CONFIG_IPC_SOCKET
+	newsock->fd = newfd;
+#endif
 	err = security_socket_accept(sock, newsock);
 	if (err)
 		goto out_fd;
diff --git a/ap/os/linux/linux-3.4.x/net/socket_rpmsg.c b/ap/os/linux/linux-3.4.x/net/socket_rpmsg.c
new file mode 100755
index 0000000..867b943
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/net/socket_rpmsg.c
@@ -0,0 +1,2662 @@
+/*******************************************************************************

+ *                           Include header files                              *

+ ******************************************************************************/

+#include <linux/module.h>

+#include <net/sock.h>

+#include <net/af_unix.h>

+#include <linux/syscalls.h>

+#include <linux/file.h>

+//#include "ram_config.h"

+#include <linux/socket_rpmsg.h>

+

+#define SOCK_DATA_ALIGN(X)	ALIGN(X, SMP_CACHE_BYTES)

+#define SOCK_DATA_MAX_LEN 8*1024

+#define  ICP_CHN_SOCKET 32

+#define sock_init_sema sema_init

+#define sock_get_sema down_interruptible

+#define sock_put_sema up

+

+struct sock_channel g_sock_chn_info;

+struct sock_rpmsg g_sock_rpmsg;

+struct ipc_socket *g_socket_ipc;

+

+struct semaphore g_sock_sem;

+unsigned int g_sock_timeout = 5*1000;

+//´æ·ÅÁ´Â·ÐÅÏ¢£¬Ò»¶Ësocket¹Ø±Õ£¬ÆäËùÓйØÁªµÄsocket¾ùɾ³ý£¬Á´Â·ÐÅÏ¢Öдæ·Å5Ôª×飨¿Í»§¶Ë¡¢·þÎñ¶Ë¡¢ºÍ´úÀí£©

+struct hlist_head g_ipc_sockets;

+struct hlist_head g_sock_rpmsg_info;

+struct hlist_head g_sockets_info;

+	

+char* flag_value[] ={

+	"SOCK_DEAD",

+	"SOCK_DONE",

+	"SOCK_URGINLINE",

+	"SOCK_KEEPOPEN",

+	"SOCK_LINGER",

+	"SOCK_DESTROY",

+	"SOCK_BROADCAST",

+	"SOCK_TIMESTAMP",

+	"SOCK_ZAPPED",

+	"SOCK_USE_WRITE_QUEUE", /* whether to call sk->sk_write_space in sock_wfree */

+	"SOCK_DBG", /* %SO_DEBUG setting */

+	"SOCK_RCVTSTAMP", /* %SO_TIMESTAMP setting */

+	"SOCK_RCVTSTAMPNS", /* %SO_TIMESTAMPNS setting */

+	"SOCK_LOCALROUTE", /* route locally only, %SO_DONTROUTE setting */

+	"SOCK_QUEUE_SHRUNK", /* write queue has been shrunk recently */

+	"SOCK_TIMESTAMPING_TX_HARDWARE",  /* %SOF_TIMESTAMPING_TX_HARDWARE */

+	"SOCK_TIMESTAMPING_TX_SOFTWARE",  /* %SOF_TIMESTAMPING_TX_SOFTWARE */

+	"SOCK_TIMESTAMPING_RX_HARDWARE",  /* %SOF_TIMESTAMPING_RX_HARDWARE */

+	"SOCK_TIMESTAMPING_RX_SOFTWARE",  /* %SOF_TIMESTAMPING_RX_SOFTWARE */

+	"SOCK_TIMESTAMPING_SOFTWARE",     /* %SOF_TIMESTAMPING_SOFTWARE */

+	"SOCK_TIMESTAMPING_RAW_HARDWARE", /* %SOF_TIMESTAMPING_RAW_HARDWARE */

+	"SOCK_TIMESTAMPING_SYS_HARDWARE", /* %SOF_TIMESTAMPING_SYS_HARDWARE */

+	"SOCK_FASYNC", /* fasync() active */

+	"SOCK_RXQ_OVFL",

+	"SOCK_ZEROCOPY", /* buffers from userspace */

+	"SOCK_WIFI_STATUS", /* push wifi status to userspace */

+	"SOCK_NOFCS",

+	"SOCK_IPCSOCK"

+};

+

+DEFINE_SPINLOCK(sock_table_lock);

+EXPORT_SYMBOL_GPL(sock_table_lock);

+

+DEFINE_SPINLOCK(sock_rpmsg_table_lock);

+EXPORT_SYMBOL_GPL(sock_rpmsg_table_lock);

+

+DEFINE_SPINLOCK(sock_socket_table_lock);

+EXPORT_SYMBOL_GPL(sock_socket_table_lock);

+

+DEFINE_SPINLOCK(sock_release_table_lock);

+EXPORT_SYMBOL_GPL(sock_release_table_lock);

+

+DEFINE_SPINLOCK(sock_release_lock);

+EXPORT_SYMBOL_GPL(sock_release_lock);

+

+DEFINE_SPINLOCK(sock_release_peer_lock);

+EXPORT_SYMBOL_GPL(sock_release_peer_lock);

+

+#define unix_peer(sk) (unix_sk(sk)->peer)

+

+extern struct sock *unix_find_other_proxy(struct net *net,

+				    struct sockaddr_un *sunname, int len,

+				    int type, unsigned int hash, int *error);

+

+extern int unix_dgram_peer_wake_connect_proxy(struct sock *sk, struct sock *other);

+

+extern void unix_dgram_peer_wake_disconnect_proxy(struct sock *sk, struct sock *other);

+

+extern void unix_dgram_peer_wake_disconnect_wakeup_proxy(struct sock *sk,

+						   struct sock *other);

+extern long unix_wait_for_peer_proxy(struct sock *other, long timeo);

+extern int unix_recvq_full_proxy(const struct sock *sk);

+extern int unix_recvq_full_proxy_lockless_and_deadstate(const struct sock *other);

+extern int unix_stream_connect_proxy(struct socket *sock, struct sockaddr *uaddr,

+			       int addr_len, int flags);

+extern void unix_dgram_disconnected_proxy(struct sock *sk, struct sock *other);

+extern int unix_mkname_proxy(struct sockaddr_un *sunaddr, int len, unsigned *hashp);

+extern void unix_release_sock_proxy(struct sock *sk);

+

+//static void delayed_release(struct work_struct *unused);

+int sock_soc_socket_is_valid(struct socket* proxysock, struct socket* localsock);

+int sock_soc_release_peer(struct release_socket* rsock);

+

+static LIST_HEAD(delayed_release_list);

+

+enum sock_flags_cap {

+	SOCK_DEAD_CAP,

+	SOCK_DONE_CAP,

+	SOCK_URGINLINE_CAP,

+	SOCK_KEEPOPEN_CAP,

+	SOCK_LINGER_CAP,

+	SOCK_DESTROY_CAP,

+	SOCK_BROADCAST_CAP,

+	SOCK_TIMESTAMP_CAP,

+	SOCK_ZAPPED_CAP,

+	SOCK_USE_WRITE_QUEUE_CAP, /* whether to call sk->sk_write_space in sock_wfree */

+	SOCK_DBG_CAP, /* %SO_DEBUG setting */

+	SOCK_RCVTSTAMP_CAP, /* %SO_TIMESTAMP setting */

+	SOCK_RCVTSTAMPNS_CAP, /* %SO_TIMESTAMPNS setting */

+	SOCK_LOCALROUTE_CAP, /* route locally only, %SO_DONTROUTE setting */

+	SOCK_MEMALLOC_CAP, /* VM depends on this socket for swapping */

+	SOCK_TIMESTAMPING_RX_SOFTWARE_CAP,  /* %SOF_TIMESTAMPING_RX_SOFTWARE */

+	SOCK_FASYNC_CAP, /* fasync() active */

+	SOCK_RXQ_OVFL_CAP,

+	SOCK_ZEROCOPY_CAP, /* buffers from userspace */

+	SOCK_WIFI_STATUS_CAP, /* push wifi status to userspace */

+	SOCK_NOFCS_CAP, /* Tell NIC not to do the Ethernet FCS.

+		     * Will use last 4 bytes of packet sent from

+		     * user-space instead.

+		     */

+	SOCK_FILTER_LOCKED_CAP, /* Filter cannot be changed anymore */

+	SOCK_SELECT_ERR_QUEUE_CAP, /* Wake select on error queue */

+	SOCK_RCU_FREE_CAP, /* wait rcu grace period in sk_destruct() */

+	SOCK_TXTIME_CAP,

+	SOCK_XDP_CAP, /* XDP is attached */

+	SOCK_TSTAMP_NEW_CAP, /* Indicates 64 bit timestamps always */

+

+    SOCK_IPCSOCK_CAP,  /*Indicates whether it is a cross core socket */

+

+};

+	

+

+enum sock_flags_cap convert_to_cap_sock_flag(enum sock_flags flag)

+{

+	switch(flag){

+		case SOCK_DEAD:

+			return SOCK_DEAD_CAP;

+		case SOCK_DONE:

+			return SOCK_DONE_CAP;

+		case SOCK_URGINLINE:

+			return SOCK_URGINLINE_CAP;

+		case SOCK_KEEPOPEN:

+			return SOCK_KEEPOPEN_CAP;

+		case SOCK_LINGER:

+			return SOCK_LINGER_CAP;

+		case SOCK_DESTROY:

+			return SOCK_DESTROY_CAP; 

+		case SOCK_BROADCAST:

+			return SOCK_BROADCAST_CAP;

+		case SOCK_TIMESTAMP:

+			return SOCK_TIMESTAMP_CAP;

+		case SOCK_ZAPPED:

+			return SOCK_ZAPPED_CAP;

+		case SOCK_USE_WRITE_QUEUE:

+			return SOCK_USE_WRITE_QUEUE_CAP;

+		case SOCK_DBG:

+			return SOCK_DBG_CAP;

+		case SOCK_RCVTSTAMP:

+			return SOCK_RCVTSTAMP_CAP;

+		case SOCK_RCVTSTAMPNS:

+			return SOCK_RCVTSTAMPNS_CAP;

+		case SOCK_LOCALROUTE:

+			return SOCK_LOCALROUTE_CAP;

+		case SOCK_QUEUE_SHRUNK:

+			return -1;

+		case SOCK_TIMESTAMPING_TX_HARDWARE:

+			return -1;

+		case SOCK_TIMESTAMPING_TX_SOFTWARE:

+			return -1;

+		case SOCK_TIMESTAMPING_RX_HARDWARE:

+			return -1;

+		case SOCK_TIMESTAMPING_RX_SOFTWARE:

+			return SOCK_TIMESTAMPING_RX_SOFTWARE_CAP;

+		case SOCK_TIMESTAMPING_SOFTWARE:

+			return -1;

+		case SOCK_TIMESTAMPING_RAW_HARDWARE:

+			return -1;

+		case SOCK_TIMESTAMPING_SYS_HARDWARE:

+			return -1;

+		case SOCK_FASYNC:

+			return SOCK_FASYNC_CAP;

+		case SOCK_RXQ_OVFL:

+			return SOCK_RXQ_OVFL_CAP;

+		case SOCK_ZEROCOPY:

+			return SOCK_ZEROCOPY_CAP;

+		case SOCK_WIFI_STATUS:

+			return SOCK_WIFI_STATUS_CAP;

+		case SOCK_NOFCS:

+			return SOCK_NOFCS_CAP;		

+		default:

+			return -1;

+	}

+}

+

+static int sock_soc_is_socket_peer(struct socket* socket, struct socket* peer)

+{

+	struct socket_info *p;

+	struct hlist_node *n, *pos;

+	spin_lock(&sock_release_peer_lock);

+	hlist_for_each_entry_safe(p, pos, n, &socket->peer, hlist_node) {

+		if(p->proxysocket == peer){			

+			spin_unlock(&sock_release_peer_lock);			

+			return 0;

+		}

+	}

+	spin_unlock(&sock_release_peer_lock);

+	return -1;

+}

+

+static inline void sock_soc_insert_socket_peer(struct socket* socket, struct socket* peer)

+{

+	struct socket_info *psock_socket_info = NULL;

+

+	//ÏȲ鿴peerÊÇ·ñÒѾ­ÔÚsocketµÄpeer_listÖÐ

+	if(0 == sock_soc_is_socket_peer(socket, peer)){

+		sk_soc_info("sock_soc_insert_socket_peer, peer already exist");

+		return;

+	}

+	psock_socket_info = (struct socket_info *)kzalloc(sizeof(struct socket_info), GFP_ATOMIC);

+	if(psock_socket_info == NULL){

+		return;

+	}

+	memset(psock_socket_info, 0, sizeof(struct socket_info));

+	psock_socket_info->proxysocket = peer;

+	psock_socket_info->localsocket = socket;	

+	

+	sk_soc_info("sock_soc_insert_socket_peer sucess, proxysocket=%x, localsock=%x", psock_socket_info->proxysocket, psock_socket_info->localsocket);

+	

+	spin_lock(&sock_release_peer_lock);

+	INIT_HLIST_NODE(&psock_socket_info->hlist_node);

+	hlist_add_head(&psock_socket_info->hlist_node, &socket->peer);

+	spin_unlock(&sock_release_peer_lock);

+}

+

+static int sock_soc_del_socket_peer(struct socket* socket, struct socket* peer)

+{

+	struct socket_info *p;

+	struct hlist_node *n, *pos;

+	spin_lock(&sock_release_peer_lock);

+	hlist_for_each_entry_safe(p, pos, n, &socket->peer, hlist_node) {

+		if(p->proxysocket == peer){

+			hlist_del(&p->hlist_node);

+			spin_unlock(&sock_release_peer_lock);

+			kfree(p);

+			return 0;

+		}

+	}

+	spin_unlock(&sock_release_peer_lock);

+	return -1;

+}

+

+static inline void sock_soc_insert_socket(struct hlist_node *list_node)

+{

+	spin_lock(&sock_table_lock);

+	hlist_add_head(list_node, &g_ipc_sockets);

+	spin_unlock(&sock_table_lock);

+}

+

+//ÓÃÓÚÅжϱ¾µØsocketÊÇ·ñÔÚipcÁбíÖУ¬¿ÉÄÜ´æÔÚ¶àÌõ¼Ç¼

+static struct ipc_socket *sock_soc_get_ipcsocket_by_localsocket(struct socket *localsocket)

+{	

+	struct ipc_socket *p;

+	struct hlist_node *pos,*n;

+	spin_lock(&sock_table_lock);

+	if(hlist_empty(&g_ipc_sockets))

+	{

+		sk_soc_info("sock_soc_get_ipcsocket_by_proxysock  g_ipc_sockets is empty");

+		spin_unlock(&sock_table_lock);

+		return NULL;

+	}

+	hlist_for_each_entry_safe(p, pos, n, &g_ipc_sockets, hlist_node) {

+		if(p->localsocket == localsocket){

+			spin_unlock(&sock_table_lock);

+			return p;

+		}

+	}

+	spin_unlock(&sock_table_lock);

+	return NULL;

+}

+

+//´Ë´¦µÄsockΪ´úÀísocket¶ÔÓ¦µÄsock£¬ÒòΪÿ¸ö´úÀísocketÔÚg_ipc_sockets±íÖÐÊÇΨһµÄ

+static struct ipc_socket *sock_soc_get_ipcsocket_by_proxysock(struct sock *s)

+{	

+	struct ipc_socket *p;

+	struct hlist_node *pos,*n;

+	spin_lock(&sock_table_lock);

+	if(hlist_empty(&g_ipc_sockets))

+	{

+		sk_soc_info("sock_soc_get_ipcsocket_by_proxysock  g_ipc_sockets is empty");

+		spin_unlock(&sock_table_lock);

+		return NULL;

+	}

+	hlist_for_each_entry_safe(p, pos, n, &g_ipc_sockets, hlist_node) {

+		if(p->sock == s){

+			spin_unlock(&sock_table_lock);

+			return p;

+		}

+	}

+	spin_unlock(&sock_table_lock);

+	return NULL;

+}

+

+//¸ù¾Ý¿Í»§¶ËsocketºÍ·þÎñ¶Ësocket²éÕÒ¶ÔÓ¦µÄipc_socket

+static struct ipc_socket *sock_get_ipcsocket_by_local_and_remote(void* localsock, void* remotesock)

+{	

+	struct ipc_socket *p;

+	struct hlist_node *pos,*n;

+	spin_lock(&sock_table_lock);

+	if(hlist_empty(&g_ipc_sockets))

+	{

+		sk_soc_info("sock_get_ipcsocket_by_local_and_remote  g_ipc_sockets is empty");

+		spin_unlock(&sock_table_lock);

+		return NULL;

+	}

+	hlist_for_each_entry_safe(p, pos, n, &g_ipc_sockets, hlist_node) {

+		if((p->localsocket == localsock)&&(p->remotesocket == remotesock)){

+			spin_unlock(&sock_table_lock);

+			return p;

+		}

+	}

+	spin_unlock(&sock_table_lock);

+	return NULL;

+}

+

+int sock_del_ipc_socket_by_proxysocket(struct socket* socket)

+{

+	struct ipc_socket *p;

+	struct hlist_node *pos, *n;

+	spin_lock(&sock_table_lock);

+	if(hlist_empty(&g_ipc_sockets))

+	{

+		sk_soc_info("sock_del_ipc_socket_by_proxysocket  g_ipc_sockets is empty");

+		spin_unlock(&sock_table_lock);

+		return -1;

+	}

+	hlist_for_each_entry_safe(p, pos, n, &g_ipc_sockets, hlist_node) {

+		if(p->socket == socket){

+			hlist_del(&p->hlist_node);

+			spin_unlock(&sock_table_lock);

+			kfree(p);

+			return 0;

+		}

+	}

+	spin_unlock(&sock_table_lock);

+	return -1;

+}

+

+//ĿǰÏȸù¾Ý¿Í»§¶Ësocket¡¢±¾¶Ë´úÀísocketºÍ·þÎñ¶Ësocket½øÐÐÆ¥Åä

+int sock_is_valide_ipc_socket(struct socket* localsocket, struct socket* proxysocket, struct socket* remotesocket/*, struct socket* remoteproxysocket*/)

+{

+	struct ipc_socket *p;

+	struct hlist_node *pos, *n;

+	spin_lock(&sock_table_lock);

+	if(hlist_empty(&g_ipc_sockets))

+	{

+		sk_soc_info("sock_is_valide_ipc_socket  g_ipc_sockets is empty");

+		spin_unlock(&sock_table_lock);

+		return -1;

+	}

+	hlist_for_each_entry_safe(p, pos, n, &g_ipc_sockets, hlist_node) {

+		if((p->localsocket == localsocket)&&(p->proxysocket == proxysocket)&&(p->remotesocket == remotesocket)/*&&(p->remoteproxysocket == remoteproxysocket)*/){

+			

+			spin_unlock(&sock_table_lock);

+			

+			return 0;

+		}

+	}

+	spin_unlock(&sock_table_lock);

+	sk_soc_info("sock_is_valide_ipc_socket failed, localsocket=%x, proxysocket=%x, remotesocket=%x", localsocket, proxysocket, remotesocket);

+	return -1;

+}

+

+struct socket *sock_get_local_socket(int fd, int *err)

+{

+	struct socket* sock; 

+	sock = sockfd_lookup(fd, err);

+	if(NULL == sock){

+		return NULL;

+	}

+	sockfd_put(sock);

+	sk_soc_info("sock_get_local_socket fd=%d, file->f_count=%d ", fd, sock->file->f_count);

+	return sock;

+}

+

+static inline void sock_soc_insert_rpmsg_info(struct hlist_node *list_node)

+{

+	spin_lock(&sock_rpmsg_table_lock);

+	hlist_add_head(list_node, &g_sock_rpmsg_info);

+	spin_unlock(&sock_rpmsg_table_lock);

+}

+

+struct sock_rpmsg_info * sock_soc_create_rpmsg_info(void* key)

+{

+	struct sock_rpmsg_info *psock_sock_rpmsg_info = NULL;

+	

+	psock_sock_rpmsg_info = (struct sock_rpmsg_info *)kzalloc(sizeof(struct sock_rpmsg_info), GFP_ATOMIC);

+	if(psock_sock_rpmsg_info == NULL){

+		sk_soc_info("sock_soc_create_rpmsg_info kzalloc failed \n");

+		return NULL;

+	}

+	memset(psock_sock_rpmsg_info, 0, sizeof(struct sock_rpmsg_info));

+	psock_sock_rpmsg_info->key = key;

+	sema_init(&psock_sock_rpmsg_info->sock_sem, 0);

+	sk_soc_info("sock_soc_create_rpmsg_info sucess, key=%x", key);

+	sock_soc_insert_rpmsg_info(&psock_sock_rpmsg_info->hlist_node);

+	return psock_sock_rpmsg_info;

+}

+

+struct sock_rpmsg_info * sock_soc_get_rpmsg_info(void* key)

+{

+	struct sock_rpmsg_info *p;

+	struct hlist_node *pos,*n;

+	//sk_soc_info("sock_soc_get_rpmsg_info key=%x \n", key);

+	spin_lock(&sock_rpmsg_table_lock);

+	hlist_for_each_entry_safe(p, pos, n, &g_sock_rpmsg_info, hlist_node) {		

+		if(p->key == key){			

+			spin_unlock(&sock_rpmsg_table_lock);

+			return p;

+		}

+	}

+	spin_unlock(&sock_rpmsg_table_lock);

+	return NULL;

+}

+

+struct sock_rpmsg_info * sock_soc_del_rpmsg_info(void* key)

+{

+	struct sock_rpmsg_info *p;

+	struct hlist_node *pos,*n;

+	//sk_soc_info("sock_soc_del_rpmsg_info key=%x \n", key);

+	spin_lock(&sock_rpmsg_table_lock);

+	hlist_for_each_entry_safe(p, pos, n, &g_sock_rpmsg_info, hlist_node) {

+		if(p->key == key){

+			hlist_del(&p->hlist_node);

+			spin_unlock(&sock_rpmsg_table_lock);

+			sk_soc_info("sock_soc_del_rpmsg_info sucess, key=%x \n", key);

+			kfree(p);

+			return 0;

+		}

+	}

+	spin_unlock(&sock_rpmsg_table_lock);

+	sk_soc_info("sock_soc_del_rpmsg_info failed, key=%x \n", key);

+	return -1;

+}

+

+static inline void sock_soc_insert_socket_info(struct hlist_node *list_node)

+{

+	spin_lock(&sock_socket_table_lock);

+	hlist_add_head(list_node, &g_sockets_info);

+	spin_unlock(&sock_socket_table_lock);

+}

+

+struct socket_info * sock_soc_set_socket_info(struct socket* proxysock, struct socket* localsock)

+{

+	struct socket_info *psock_socket_info = NULL;

+

+	if(0 == sock_soc_socket_is_valid(proxysock, localsock)){

+		sk_soc_info("sock_soc_socket_is_valid is true , do not add again");

+		return NULL;

+	}

+	psock_socket_info = (struct socket_info *)kzalloc(sizeof(struct socket_info), GFP_ATOMIC);

+	if(psock_socket_info == NULL){

+		return NULL;

+	}

+	memset(psock_socket_info, 0, sizeof(struct socket_info));

+	psock_socket_info->proxysocket = proxysock;

+	psock_socket_info->localsocket = localsock;

+	//sk_soc_info("sock_soc_set_socket_info sucess, key=%x", sock);

+	sock_soc_insert_socket_info(&psock_socket_info->hlist_node);

+	sk_soc_info("sock_soc_set_socket_info sucess, proxysocket=%x, localsock=%x", psock_socket_info->proxysocket, psock_socket_info->localsocket);

+	return psock_socket_info;

+}

+

+int sock_soc_socket_is_valid(struct socket* proxysock, struct socket* localsock)

+{

+	struct ipc_socket *p;

+	struct hlist_node *pos,*n;

+	spin_lock(&sock_table_lock);

+	if(hlist_empty(&g_ipc_sockets))

+	{

+		sk_soc_info("sock_soc_socket_is_valid  g_ipc_sockets is empty");

+		spin_unlock(&sock_table_lock);

+		return -1;

+	}

+	hlist_for_each_entry_safe(p, pos, n, &g_ipc_sockets, hlist_node) {

+		if((p->proxysocket == proxysock)&&(p->localsocket == localsock)){

+			spin_unlock(&sock_table_lock);

+			return 0;

+		}

+	}

+	spin_unlock(&sock_table_lock);

+	return -1;

+}

+

+int sock_soc_del_socket_info(struct socket* proxysock, struct socket* localsock)

+{

+	struct ipc_socket *p;

+	struct hlist_node *pos,*n;

+	//sk_soc_info("sock_soc_del_socket_info key=%x \n", sock);

+	spin_lock(&sock_table_lock);

+	if(hlist_empty(&g_ipc_sockets))

+	{

+		sk_soc_info("sock_soc_del_socket_info  g_ipc_sockets is empty");

+		spin_unlock(&sock_table_lock);

+		return -1;

+	}

+	hlist_for_each_entry_safe(p, pos, n, &g_ipc_sockets, hlist_node) {

+		if((p->proxysocket == proxysock)&&(p->localsocket == localsock)){

+			hlist_del(&p->hlist_node);

+			spin_unlock(&sock_table_lock);

+			sk_soc_info("sock_soc_del_socket_info sucess, proxysock=%x, localsock=%x \n", proxysock, localsock);

+			kfree(p);

+			return 0;

+		}

+	}

+	spin_unlock(&sock_table_lock);

+	sk_soc_info("sock_soc_del_socket_info failed, proxysock=%x,localsock=%x \n", proxysock, localsock);

+	return -1;

+}

+

+int sock_soc_socket_is_valid_other(struct socket* other)

+{

+	return 0;

+}

+

+int sock_soc_socket_is_valid_ipc(struct socket* localsocket, struct socket* remotesocket)

+{	

+	struct ipc_socket *p;

+	struct hlist_node *pos,*n;

+	spin_lock(&sock_table_lock);

+	if(hlist_empty(&g_ipc_sockets))

+	{

+		sk_soc_info("sock_soc_socket_is_valid_ipc  g_ipc_sockets is empty");

+		spin_unlock(&sock_table_lock);

+		return -1;

+	}

+	hlist_for_each_entry_safe(p, pos, n, &g_ipc_sockets, hlist_node) {

+		if((p->localsocket == localsocket)&&(p->remotesocket == remotesocket)){

+			spin_unlock(&sock_table_lock);

+			return 0;

+		}

+	}

+	spin_unlock(&sock_table_lock);

+	return -1;

+}

+

+struct sock_rpmsg_info * sock_soc_rsp_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct sock_rpmsg_info *psock_rpmsg_info;

+	psock_rpmsg_info = sock_soc_get_rpmsg_info(psock_rpmsg->key);	

+	if(NULL == psock_rpmsg_info){

+		sk_soc_err("sock_soc_get_rpmsg_info failed!");

+		return NULL;

+	}

+	memset(&psock_rpmsg_info->sock_rpmsg, 0, sizeof(struct sock_rpmsg));

+	memcpy(&psock_rpmsg_info->sock_rpmsg, psock_rpmsg, sizeof(struct sock_rpmsg));	

+	up(&psock_rpmsg_info->sock_sem);

+	return psock_rpmsg_info;

+}

+int unix_is_ipc_socket(struct sock *sock)

+{

+	int result;

+	result = test_bit(SOCK_IPCSOCK, &sock->sk_flags);

+	//sk_soc_info("unix_is_ipc_socket result=%d", result);

+	return result;

+}

+EXPORT_SYMBOL_GPL(unix_is_ipc_socket);

+

+int unix_is_ipc_local_socket(struct sock *sock)

+{

+	int result;

+	result = test_bit(SOCK_IPC_LOCAL, &sock->sk_flags);

+	//sk_soc_info("unix_is_ipc_socket result=%d", result);

+	return result;

+}

+EXPORT_SYMBOL_GPL(unix_is_ipc_local_socket);

+

+/*·µ»ØÖµ´óÓÚµÈÓÚ0£¬±íʾдͨµÀ³É¹¦£»Ð¡ÓÚ0±íʾдͨµÀʧ°Ü*/

+static int sock_channel_write(struct sock_channel *chninfo, void *buf, unsigned int len)

+{

+    T_ZDrvRpMsg_Msg msg;

+

+    if(NULL == buf) {

+        return -EINVAL;

+    }

+    memset(&msg, 0, sizeof(msg));

+    msg.actorID = chninfo->core_id;

+    msg.chID   = chninfo->channel_id;

+    msg.flag |= RPMSG_WRITE_INT; //| RPMSG_WRITE_IRQLOCK;

+    msg.buf = buf;

+    msg.len = len;

+	//sk_soc_info("sock_channel_write process, len=%d", len);

+    return sockSocWrite(&msg);

+}

+

+/*·µ»ØÖµ´óÓÚ0£¬±íʾ¶ÁȡͨµÀ³É¹¦£»Ð¡ÓÚµÈÓÚ0±íʾͨµÀÊý¾ÝΪ¿Õ»òʧ°Ü*/

+static int sock_channel_read(struct sock_channel *chninfo, void *buf, unsigned int len)

+{

+    T_ZDrvRpMsg_Msg msg;

+    int ret = 0;

+

+    if(NULL == buf) {

+        return -EINVAL;

+    }

+	sk_soc_info("sock_channel_read enter");

+    memset(&msg, 0, sizeof(msg));

+    msg.actorID = chninfo->core_id;

+    msg.chID   = chninfo->channel_id;

+    msg.buf    = buf;

+    msg.len    = len;

+

+    ret = sockSocRead(&msg);

+    if (ret <= 0) {

+        sk_soc_err("rpm read err=%d!",ret);

+        return ret;

+    }

+

+    return ret;

+}

+

+static int sock_thread_enqueue_data(struct sock_rpmsg *sock_rpmsg)

+{

+	unsigned long flags;

+	struct sock_thread_info* p_main_thread_info;

+	p_main_thread_info = &g_sock_chn_info.main_thread_info;

+	

+	spin_lock_irqsave(&p_main_thread_info->p_sock_lock,flags);

+	list_add_tail(&sock_rpmsg->list, &p_main_thread_info->p_sock_list);

+	spin_unlock_irqrestore(&p_main_thread_info->p_sock_lock,flags);

+	sock_put_sema(&p_main_thread_info->p_sock_sem);

+

+	return 0;

+}

+

+struct sock_rpmsg* sock_create_rpmsg(unsigned int size)

+{

+	struct sock_rpmsg* sock_rpmsg;

+	

+	size = SOCK_DATA_ALIGN(size);

+	size += SOCK_DATA_ALIGN(sizeof(struct sock_rpmsg));

+	if(size > SOCK_DATA_MAX_LEN){

+		sk_soc_err("size of data is too large, max support size is %d", SOCK_DATA_MAX_LEN-sizeof(struct sock_rpmsg));

+	}

+	sock_rpmsg = kzalloc(size, GFP_KERNEL);

+	if (sock_rpmsg == NULL) {

+		sk_soc_err("kzalloc fial!!");

+		return NULL;

+	}

+	return sock_rpmsg;

+}

+

+static int sock_send_ipc_msg(struct	sock_rpmsg* psock_rpmsg)

+{	

+	struct	sock_rpmsg* sock_rpmsg;

+	sock_rpmsg = sock_create_rpmsg(0);

+	if(NULL == sock_rpmsg){

+		sk_soc_err("kzalloc fial!!");

+		return -1;

+	}

+	memcpy(sock_rpmsg, psock_rpmsg, sizeof(struct	sock_rpmsg));

+	sock_rpmsg->dir = DIR_DOWNLINK;

+	sock_thread_enqueue_data(sock_rpmsg);

+	//sk_soc_info("sock_send_ipc_msg write len=%d", len);

+	return 0;

+}

+

+static int sock_send_ipc_msg_data(struct	sock_rpmsg* psock_rpmsg)

+{	

+	if(NULL == psock_rpmsg){

+		sk_soc_err("psock_rpmsg is NULL!!");

+		return -1;

+	}

+	

+	psock_rpmsg->dir = DIR_DOWNLINK;

+	sock_thread_enqueue_data(psock_rpmsg);

+	//sk_soc_info("sock_send_ipc_msg write len=%d", len);

+	return 0;

+}

+

+static int sock_recv_ipc_msg(struct	sock_rpmsg* psock_rpmsg)

+{	

+	struct	sock_rpmsg* sock_rpmsg;

+	sk_soc_info("sock_receive_thread sock_rpmsg.msg_type=%d,index=%d", psock_rpmsg->msg_type, psock_rpmsg->index);

+	sock_rpmsg = sock_create_rpmsg(psock_rpmsg->data_len);

+	if(NULL == sock_rpmsg){

+		sk_soc_err("kzalloc fial!!");

+		return -1;

+	}

+	memcpy(sock_rpmsg, psock_rpmsg, psock_rpmsg->data_len+sizeof(struct sock_rpmsg));

+	sock_rpmsg->dir = DIR_UPLINK;

+	sock_thread_enqueue_data(sock_rpmsg);

+	//sk_soc_info("sock_send_ipc_msg write len=%d", len);

+	return 0;

+}

+

+int sock_lookup_fd_by_sock(struct sock *sock)

+{

+	struct socket *socket;

+	socket = sock->sk_socket;

+	sk_soc_info("sock_lookup_fd_by_sock socket=%x, socket->fd=%d\n", socket, socket->fd);

+	return socket->fd;

+}

+

+static int sock_channel_clear(struct sock_channel *chninfo)

+{

+    char *tbuf = NULL;

+    unsigned int tlen = chninfo->channel_size/2;

+    int ret = 0;

+

+    tbuf = (char *)kzalloc(tlen,GFP_ATOMIC);

+    if(IS_ERR(tbuf)) {

+        sk_soc_err("kzalloc fail! %d byte.", tlen);

+        return -ENOMEM;

+    }

+    ret = sock_channel_read(chninfo, tbuf, tlen);

+    if(ret < 0) {

+        sk_soc_err("zvnet_channel_read fail!");

+        ret = 0;

+    }

+    kfree(tbuf);

+    sk_soc_err("Drop channel data. %d byte.",ret);

+

+    return ret;

+}

+

+void usock_print(struct unix_sock* usock){	

+	sk_soc_info("usock->rsock.localfd=%d", usock->rsock.localfd);

+	sk_soc_info("usock->rsock.localsocket=%x", usock->rsock.localsocket);

+	sk_soc_info("usock->rsock.proxyfd=%d", usock->rsock.proxyfd);

+	sk_soc_info("usock->rsock.proxysocket=%x", usock->rsock.proxysocket);

+	sk_soc_info("usock->rsock.remotefd=%d", usock->rsock.remotefd);

+	sk_soc_info("usock->rsock.remotesocket=%x", usock->rsock.remotesocket);

+}

+

+void usock_init(struct sock* sock, int localfd, struct socket* localsocket, int proxyfd, struct socket* proxysocket, int remotefd, struct socket* remotesocket){

+	struct unix_sock* usock;

+	if(NULL == sock){

+		return;

+	}

+	usock = unix_sk(sock);

+	usock->rsock.localfd = localfd;

+	usock->rsock.localsocket = localsocket;

+	usock->rsock.proxyfd = proxyfd;

+	usock->rsock.proxysocket = proxysocket;

+	usock->rsock.remotefd = remotefd;

+	usock->rsock.remotesocket = remotesocket;

+}

+

+void usock_update_remote_proxy_socket(struct sock* sock, struct socket* remoteproxysocket)

+{

+	struct unix_sock* usock;

+	usock = unix_sk(sock);

+	usock->rsock.remoteproxysocket = remoteproxysocket;

+}

+

+static struct ipc_socket * sock_create_proxy_socket_server(struct sock_rpmsg* psock_rpmsg)

+{

+	struct ipc_socket *psocket_ipc = NULL;	

+	struct socket *sock;

+	

+	int err;	

+	

+	sk_soc_info("clientsock=%x, serversock=%x!\n", psock_rpmsg->clientsock, psock_rpmsg->serversock);

+	psocket_ipc = sock_get_ipcsocket_by_local_and_remote(psock_rpmsg->clientsock, psock_rpmsg->serversock);

+	if(NULL != psocket_ipc) {  //Èç¹ûÒѾ­´´½¨¹ýͬһ·þÎñ¶ËµÄ´úÀí£¬Ôò²»ÔÙÖØ¸´´´½¨

+		sk_soc_info("socket_server already exist, do not create again!\n");

+		sock_hold(psocket_ipc->sock); //0705

+		return psocket_ipc;

+	}

+	

+	psocket_ipc = (struct ipc_socket *)kzalloc(sizeof(struct ipc_socket), GFP_ATOMIC);

+	if(NULL == psocket_ipc){		

+		sk_soc_err("kzalloc failed!\n");

+		return NULL;

+	}

+	psocket_ipc->sockfd = sys_socket(AF_UNIX, psock_rpmsg->socktype, 0); //´´½¨·þÎñ¶Ësocket´úÀí

+	sk_soc_info("sock_create_proxy_socket_server socktype=%d, socket->fd=%d", psock_rpmsg->socktype, psocket_ipc->sockfd);

+	//memcpy(&psocket_ipc->sock, &g_sock_rpmsg.sock, sizeof(struct sock));

+	//psocket_ipc->socket.sk = &psocket_ipc->sock;

+    psocket_ipc->socket = sock_get_local_socket(psocket_ipc->sockfd, &err);

+	if(NULL != psocket_ipc->socket){

+		sk_soc_info("sock_create_proxy_socket_server sucess\n");

+		psocket_ipc->sock = psocket_ipc->socket->sk;

+		psocket_ipc->proxysocket = psocket_ipc->socket;

+		psocket_ipc->socktype = psock_rpmsg->socktype;

+		set_bit(SOCK_IPCSOCK,&psocket_ipc->sock->sk_flags);

+		psocket_ipc->sock->ipc_flag = 1;

+		psocket_ipc->sock->sk_fd = psocket_ipc->sockfd;

+		//sock_soc_set_socket_info(psocket_ipc->socket, psock_rpmsg->clientsock);

+		sock_hold(psocket_ipc->sock); //0704

+		//³õʼ»¯´úÀísocketµÄusockÐÅÏ¢

+		usock_init(psocket_ipc->sock, psock_rpmsg->clientfd, psock_rpmsg->clientsock, psocket_ipc->sockfd, psocket_ipc->socket, psock_rpmsg->serverfd, psock_rpmsg->serversock);

+		usock_update_remote_proxy_socket(psocket_ipc->sock, psock_rpmsg->serverproxysock);

+		//usock_print(usock);

+	}

+	else{

+		sk_soc_info("sock_create_proxy_socket_server failed, socket = NULL\n");

+	}

+	//ͬ²½·þÎñÆ÷¶ËÅäÖÃ

+	//psocket_ipc->sock->sk_flags = g_sock_rpmsg.sock.sk_flags;

+	//psocket_ipc->sock->sk_state = g_sock_rpmsg.sock.sk_state;

+	//psocket_ipc->sock->sk_shutdown = g_sock_rpmsg.sock.sk_shutdown;

+	//psocket_ipc->sock->sk_receive_queue.qlen = g_sock_rpmsg.sock.sk_receive_queue.qlen;

+	//psocket_ipc->sock->sk_max_ack_backlog = g_sock_rpmsg.sock.sk_max_ack_backlog;

+	psocket_ipc->localfd = psock_rpmsg->clientfd;

+	psocket_ipc->localsocket = psock_rpmsg->clientsock;

+	psocket_ipc->remotefd = psock_rpmsg->serverfd;

+	psocket_ipc->remotesocket = psock_rpmsg->serversock;

+	psocket_ipc->remoteproxyfd = psock_rpmsg->serverproxyfd;

+	psocket_ipc->remoteproxysocket = psock_rpmsg->serverproxysock;

+	psocket_ipc->key = psock_rpmsg->serversock;

+	sk_soc_info("sock_create_proxy_socket_server sockfd=%d, remotefd=%d, key=%x\n", psocket_ipc->sockfd, psocket_ipc->remotefd, psocket_ipc->key);

+	INIT_HLIST_NODE(&psocket_ipc->hlist_node);

+	sock_soc_insert_socket(&psocket_ipc->hlist_node);

+	return psocket_ipc;

+}

+

+static struct ipc_socket * sock_create_proxy_socket_client(struct sock_rpmsg* psock_rpmsg)

+{

+	struct ipc_socket *psocket_ipc = NULL;	

+	struct socket *sock;

+	struct unix_sock* usock;

+	int err;

+	//½öƾÕâÁ½¸ö²ÎÊý»¹²»ÄÜÈ·¶¨ÊÇ·ñͬһ¿Í»§¶ËµÄ´úÀí£¬ÒòΪ¶Ô¶Ë¿ÉÄܹرղ¢ÖØÐÂÉú³ÉÒ»¸öÏàͬµØÖ·µÄsocket

+	if(0 == psock_rpmsg->isfistfind){

+		psocket_ipc = sock_get_ipcsocket_by_local_and_remote(psock_rpmsg->serversock, psock_rpmsg->clientsock);

+		if(NULL != psocket_ipc) {  //Èç¹ûÒѾ­´´½¨¹ýͬһ¿Í»§¶ËµÄ´úÀí£¬Ôò²»ÔÙÖØ¸´´´½¨

+			//sock_hold(psocket_ipc->sock); //0703

+			return psocket_ipc;

+		}

+	}

+	

+	psocket_ipc = (struct ipc_socket *)kzalloc(sizeof(struct ipc_socket), GFP_ATOMIC);

+	if(NULL == psocket_ipc){		

+		sk_soc_err("kzalloc failed!\n");

+		return NULL;

+	}

+	sk_soc_info("sock_create_proxy_socket_client socktype=%d\n", psock_rpmsg->socktype);

+	psocket_ipc->sockfd = sys_socket(AF_UNIX, psock_rpmsg->socktype, 0); //´´½¨¿Í»§¶Ësocket´úÀí

+	sk_soc_info("sock_create_proxy_socket_client socket->fd=%d\n", psocket_ipc->sockfd);

+	psocket_ipc->socket = sock_get_local_socket(psocket_ipc->sockfd, &err);

+	

+	//usock_print(usock);	

+	

+	if(NULL != psocket_ipc->socket){

+		sk_soc_info("sockfd_lookup sucess, socket=%x \n", psocket_ipc->socket);

+		//³õʼ»¯´úÀísocketµÄusockÐÅÏ¢

+		usock_init(psocket_ipc->socket->sk, psock_rpmsg->serverfd, psock_rpmsg->serversock, psocket_ipc->sockfd, psocket_ipc->socket, psock_rpmsg->clientfd, psock_rpmsg->clientsock);

+

+		psocket_ipc->sock = psocket_ipc->socket->sk;

+		set_bit(SOCK_IPCSOCK,&psocket_ipc->sock->sk_flags);

+		psocket_ipc->sock->ipc_flag = 1;

+		psocket_ipc->sock->sk_fd = psocket_ipc->sockfd;

+		//sock_hold(psocket_ipc->sock); //todo: clientÊDz»ÊDz»Ó¦¸Ãµ÷ÓÃsock_hold?

+	}

+	else{

+		sk_soc_info("server socket = NULL");

+	}

+	//ÒòΪ´Ëʱ¶Ô¶ËµÄ´úÀísocket»¹Î´´´½¨£¬ËùÒÔÎÞ·¨»ñÈ¡remoteproxyfdºÍremoteproxysocket

+	psocket_ipc->localfd = 	psock_rpmsg->serverfd;

+	psocket_ipc->localsocket = psock_rpmsg->serversock;

+	psocket_ipc->remotefd = psock_rpmsg->clientfd;

+	psocket_ipc->remotesocket = psock_rpmsg->clientsock;	

+	psocket_ipc->proxysocket = psocket_ipc->socket;

+	

+	psocket_ipc->key = psock_rpmsg->clientsock;

+	sk_soc_info("sock_create_proxy_socket_client sockfd=%d,remotefd=%d,key=%x", psocket_ipc->sockfd, psocket_ipc->remotefd,psocket_ipc->key);

+	INIT_HLIST_NODE(&psocket_ipc->hlist_node);

+	sock_soc_insert_socket(&psocket_ipc->hlist_node);	

+	return psocket_ipc;

+}

+

+int sock_soc_recvq_full(const struct sock *other)

+{

+	struct sock_rpmsg sock_rpmsg = {0};

+	struct ipc_socket * ipc_socket; 

+	struct sock_rpmsg_info *psock_rpmsg_info;

+	int sockfd;

+	int result;

+	sk_soc_info("sock_soc_recvq_full enter");

+	sock_rpmsg.msg_type = MSG_TYPE_RECVQ_FULL;

+	sockfd = sock_lookup_fd_by_sock(other);

+	//sock_rpmsg.serverfd = sock_lookup_serverfd_by_clientfd(sockfd);

+	//ipc_socket = sock_lookup_server_by_clientfd(sockfd);

+	ipc_socket = sock_soc_get_ipcsocket_by_proxysock(other);

+	if(NULL == ipc_socket){

+		sk_soc_info("sock_soc_recvq_full get ipc_socket faild \n");

+		return -1;

+	}

+	sock_rpmsg.serverfd = ipc_socket->remotefd;

+	sock_rpmsg.serversock = ipc_socket->remotesocket;

+	sock_rpmsg.clientsock = ipc_socket->localsocket;

+	sock_rpmsg.key = other;

+	psock_rpmsg_info = sock_soc_create_rpmsg_info(sock_rpmsg.key);

+	if(NULL == psock_rpmsg_info){

+		sk_soc_info("sock_soc_recvq_full create rpmsg faild \n");

+		return -1;

+	}

+	sock_send_ipc_msg(&sock_rpmsg);

+	down_timeout(&psock_rpmsg_info->sock_sem, msecs_to_jiffies(g_sock_timeout));

+	result = psock_rpmsg_info->sock_rpmsg.result;

+	sock_soc_del_rpmsg_info(sock_rpmsg.key);

+	return result;

+}

+EXPORT_SYMBOL_GPL(sock_soc_recvq_full);

+

+int sock_soc_recvq_full_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct ipc_socket* ipcsocket;	 

+	struct socket *other;

+	int err;

+	int result;

+	struct sock_rpmsg sock_rpmsg = {0};

+	sk_soc_info("sock_soc_recvq_full_proc serverfd=%d", psock_rpmsg->serverfd);

+	sock_rpmsg.msg_type = MSG_TYPE_RECVQ_FULL_RESULT;

+	sock_rpmsg.key = psock_rpmsg->key;

+	//other = sock_get_local_socket(psock_rpmsg->serverfd, &err);

+	other = (struct socket*)psock_rpmsg->serversock;

+	if(sock_soc_socket_is_valid_ipc(other, psock_rpmsg->clientsock) == -1){ //serversockÒѹرÕ

+		sk_soc_info("sock_soc_socket_is_valid is false \n");

+		sock_send_ipc_msg(&sock_rpmsg);

+		return -1;

+	}

+	sock_rpmsg.result = unix_recvq_full_proxy(other->sk);

+	sk_soc_info("sock_soc_recvq_full_proc result=%d\n", sock_rpmsg.result);

+	sock_rpmsg.serverfd = other->fd; //sock_lookup_fd_by_sock(other->sk);	

+	sock_send_ipc_msg(&sock_rpmsg);

+	return 0;

+}

+

+int sock_soc_recvq_full_result_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	sk_soc_info("sock_soc_recvq_full_result_proc\n");

+	sock_soc_rsp_proc(psock_rpmsg);

+	return 0;

+}

+

+int sock_soc_recvq_full_lockless_and_dead(const struct sock *other)

+{

+	struct sock_rpmsg sock_rpmsg = {0};

+	struct ipc_socket *ipc_socket; 

+	struct sock_rpmsg_info *psock_rpmsg_info;

+	int sockfd;

+	int result;

+	sk_soc_info("sock_soc_recvq_full_lockless_and_dead\n");

+	sock_rpmsg.msg_type = MSG_TYPE_RECVQ_FULL_LOCKLESS_AND_DEAD;

+	sockfd = sock_lookup_fd_by_sock(other);

+	//sock_rpmsg.serverfd = sock_lookup_serverfd_by_clientfd(sockfd);

+	//ipc_socket = sock_lookup_server_by_clientfd(sockfd);

+	ipc_socket = sock_soc_get_ipcsocket_by_proxysock(other);

+	if(NULL == ipc_socket){

+		sk_soc_info("sock_soc_recvq_full_lockless_and_dead get ipc_socket faild \n");

+		return -1;

+	}

+	sock_rpmsg.serverfd = ipc_socket->remotefd;

+	sock_rpmsg.serversock = ipc_socket->remotesocket;

+	sock_rpmsg.clientsock = ipc_socket->localsocket;

+	sock_rpmsg.key = other;

+	psock_rpmsg_info = sock_soc_create_rpmsg_info(sock_rpmsg.key);

+	if(NULL == psock_rpmsg_info){

+		sk_soc_info("sock_soc_recvq_full_lockless_and_dead create rpmsg faild \n");

+		return -1;

+	}

+	sock_send_ipc_msg(&sock_rpmsg);	

+	down_timeout(&psock_rpmsg_info->sock_sem, msecs_to_jiffies(g_sock_timeout));

+	result = psock_rpmsg_info->sock_rpmsg.result;

+	sock_soc_del_rpmsg_info(sock_rpmsg.key);

+	return result;

+}

+EXPORT_SYMBOL_GPL(sock_soc_recvq_full_lockless_and_dead);

+

+int sock_soc_recvq_full_lockless_and_dead_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct ipc_socket* ipcsocket;	 

+	struct socket *other;

+	int err;

+	int result;

+	struct sock_rpmsg sock_rpmsg = {0};

+	sk_soc_info("sock_soc_recvq_full_lockless_and_dead_proc");

+	sock_rpmsg.msg_type = MSG_TYPE_RECVQ_FULL_LOCKLESS_AND_DEAD_RESULT;

+	sock_rpmsg.key = psock_rpmsg->key;

+	//other = sock_get_local_socket(psock_rpmsg->serverfd, &err);

+	other = (struct socket*)psock_rpmsg->serversock;

+	if(sock_soc_socket_is_valid_ipc(other, psock_rpmsg->clientsock) == -1){ //serversockÒѹرÕ

+		sk_soc_info("sock_soc_socket_is_valid is false \n");

+		sock_send_ipc_msg(&sock_rpmsg);

+		return -1;

+	}

+	sock_rpmsg.result = unix_recvq_full_proxy_lockless_and_deadstate(other->sk);

+	sock_rpmsg.serverfd = sock_lookup_fd_by_sock(other->sk);	

+	sock_send_ipc_msg(&sock_rpmsg);

+	return 0;

+}

+

+int sock_soc_recvq_full_lockless_and_dead_result_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	sk_soc_info("sock_soc_recvq_full_lockless_and_dead_result_proc");

+	sock_soc_rsp_proc(psock_rpmsg);

+	return 0;

+}

+/*

+** sock: ±¾µØsocket

+** other:¶Ô¶ËsocketµÄ±¾µØ´úÀí

+*/

+int sock_soc_set_peer(struct sock *sock, struct sock *other)

+{

+	struct sock_rpmsg sock_rpmsg = {0};

+	struct ipc_socket *ipc_socket;

+	int sockfd; 

+	sock_rpmsg.msg_type = MSG_TYPE_SET_PEER;

+	sock_rpmsg.clientfd = sock_lookup_fd_by_sock(sock);

+	sock_rpmsg.clientsock = sock->sk_socket;

+	sockfd = sock_lookup_fd_by_sock(other);

+	//sock_rpmsg.serverfd = sock_lookup_serverfd_by_clientfd(sockfd);	

+	//ipc_socket = sock_lookup_server_by_clientfd(sockfd);

+	ipc_socket = sock_soc_get_ipcsocket_by_proxysock(other);

+	if(NULL == ipc_socket){

+		sk_soc_info("sock_soc_set_peer get ipc_socket faild \n");

+		return -1;

+	}

+	sock_rpmsg.serverfd = ipc_socket->remotefd;

+	sock_rpmsg.serversock = ipc_socket->remotesocket;

+	sk_soc_info("sock_soc_set_peer clientfd=%d, serverfd=%d\n", sock_rpmsg.clientfd, sock_rpmsg.serverfd);

+

+	unix_peer(sock) = other;

+	sock_send_ipc_msg(&sock_rpmsg);

+	return 0;

+}

+EXPORT_SYMBOL_GPL(sock_soc_set_peer);

+

+int sock_soc_set_peer_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct ipc_socket* ipcsocket;

+	struct socket *clientsocket; 

+	struct socket *serversocket;

+	struct sock *sock; 

+	struct sock *other;

+	int err;

+	sk_soc_info("sock_soc_set_peer_proc clientfd=%d, serverfd=%d", psock_rpmsg->clientfd, psock_rpmsg->serverfd);

+	//¶ÔÓÚ·þÎñ¶ËÀ´Ëµ,serversockÊôÓÚ±¾µØsocket£¬clientsockÊôÓÚÔ¶¶Ësocket

+	ipcsocket = sock_get_ipcsocket_by_local_and_remote(psock_rpmsg->serversock, psock_rpmsg->clientsock);

+	if(ipcsocket == NULL){

+		sk_soc_info("sock_soc_set_peer_proc failed, clientfd=%d,clientsock=%x\n ", psock_rpmsg->clientfd, psock_rpmsg->clientsock);

+		return -1;

+	}	

+	//clientsocket = (struct socket*)psock_rpmsg->clientsock;

+	sock = ipcsocket->sock;

+	//serversocket = sock_get_local_socket(psock_rpmsg->serverfd, &err);

+	serversocket = (struct socket*)psock_rpmsg->serversock;

+	if(sock_soc_socket_is_valid_ipc(serversocket, psock_rpmsg->clientsock) == -1){ //serversockÒѹرÕ

+		sk_soc_info("sock_soc_socket_is_valid is false \n");		

+		return -1;

+	}

+	other = serversocket->sk; 

+	

+	unix_peer(sock) = other;

+	sock_hold(other);

+	//unix_peer(other) = sock; //0703

+	return 0;

+}

+

+/*½«ËùÓÐsocket->peer==sockµÄsocket,È«²¿¸üÐÂΪsocket->peer=newsock*/

+//¸Ã½Ó¿ÚÓÃÓÚ·þÎñ¶Ë֪ͨ¿Í»§¶Ë

+int sock_soc_update_peer(struct socket *sock, struct socket *newsock)

+{

+	struct sock_rpmsg sock_rpmsg = {0};

+	struct sock* proxysock;

+	struct ipc_socket* ipcsocket;

+	int sockfd;

+	struct unix_sock* usock;

+	//newsock->sk->peerÖ¸ÏòµÄÊǿͻ§¶Ë´úÀísock

+	proxysock = unix_peer(newsock->sk);

+	usock = unix_sk(proxysock);

+	usock->rsock.localsocket = newsock;

+	ipcsocket = sock_soc_get_ipcsocket_by_proxysock(proxysock);

+	if(NULL != ipcsocket){

+		sock_rpmsg.serversock = ipcsocket->remotesocket;

+		ipcsocket->localsocket = newsock;

+		sk_soc_info("remotesocket=%x, localsocket=%x", ipcsocket->remotesocket, ipcsocket->localsocket);

+	}else{

+		sk_soc_info("sock_soc_get_ipcsocket_by_proxysock failed, sock=%x", sock);

+		return -1;

+	}

+	sk_soc_info("sock=%x, newsock=%x", sock, newsock);

+	sock_rpmsg.msg_type = MSG_TYPE_UPDATE_PEER;

+	sock_rpmsg.clientfd = sock->fd;

+	sock_rpmsg.clientsock = sock;

+	sock_rpmsg.newclientfd = newsock->fd;	

+	sock_rpmsg.newsock = newsock;

+	sock_soc_del_socket_peer(sock, ipcsocket->proxysocket);

+	sock_soc_insert_socket_peer(newsock, ipcsocket->proxysocket);

+	//newsock->peer = sock->peer; //0706

+	//sock->peer = NULL; //0706

+	sock_rpmsg.key = sock_rpmsg.serversock;

+	sk_soc_info("clientfd=%d, newclientfd=%d\n", sock_rpmsg.clientfd, sock_rpmsg.newclientfd);

+	//sock_soc_del_socket_info(proxysock->sk_socket, sock); //ɾ³ý¾ÉµÄÐÅÏ¢

+	//sock_soc_set_socket_info(proxysock->sk_socket, newsock); //Ìí¼ÓеÄÐÅÏ¢

+	sock_send_ipc_msg(&sock_rpmsg);

+	return 0;

+}

+

+EXPORT_SYMBOL_GPL(sock_soc_update_peer);

+

+int sock_soc_update_peer_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct ipc_socket* ipcsocket;

+	struct socket *clientsocket; 

+	struct socket *serversocket;

+	struct sock *sock; 

+	struct sock *other;

+	struct unix_sock* usock;

+	int err;

+	sk_soc_info("sock_soc_update_peer_proc clientfd=%d, newclientfd=%d", psock_rpmsg->clientfd, psock_rpmsg->newclientfd);

+	ipcsocket = sock_get_ipcsocket_by_local_and_remote(psock_rpmsg->serversock, psock_rpmsg->clientsock);

+	if(ipcsocket == NULL){

+		sk_soc_info("sock_soc_update_peer_proc failed, clientfd=%d,clientsock=%x\n ", psock_rpmsg->clientfd, psock_rpmsg->clientsock);

+		return -1;

+	}	

+	sk_soc_info("sock_soc_update_peer_proc sock=%x, newsock=%x", ipcsocket->remotesocket, psock_rpmsg->newsock);

+	ipcsocket->remotefd = psock_rpmsg->newclientfd;

+	ipcsocket->remotesocket = psock_rpmsg->newsock;

+	ipcsocket->key = psock_rpmsg->newsock;

+	usock = unix_sk(ipcsocket->proxysocket->sk);

+	usock->rsock.remotefd = psock_rpmsg->newclientfd;

+	usock->rsock.remotesocket = psock_rpmsg->newsock;

+	sock_soc_rsp_proc(psock_rpmsg);//ÊÍ·ÅconnectµÈ´ýµÄÐźÅÁ¿

+	return 0;

+}

+

+void sock_soc_sock_hold(struct sock *other)

+{

+	struct ipc_socket *psocket_ipc = NULL;

+	struct sock_rpmsg sock_rpmsg = {0};

+	sock_rpmsg.msg_type = MSG_TYPE_SOCK_HOLD;

+	//dump_stack();	

+	//²éÕÒ·þÎñÆ÷¶Ë´úÀísocketÏà¹ØÐÅÏ¢

+	psocket_ipc = sock_soc_get_ipcsocket_by_proxysock(other);

+	if(psocket_ipc == NULL){

+		sk_soc_info("sock_soc_sock_hold failed, other->fd=%d\n ", other->sk_fd);

+		return;

+	}

+	//·þÎñÆ÷¶Ësocket fd

+	sock_rpmsg.serverfd = psocket_ipc->remotefd;

+	sock_rpmsg.serversock = psocket_ipc->remotesocket;

+	sock_rpmsg.clientsock = psocket_ipc->localsocket;

+	sk_soc_info("sock_soc_sock_hold serverfd=%d \n", sock_rpmsg.serverfd);

+	sock_send_ipc_msg(&sock_rpmsg); 

+}

+

+int sock_soc_sock_hold_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct socket* serversocket;	

+	struct sock* other;

+	

+	serversocket = (struct socket*)psock_rpmsg->serversock;

+	if(sock_soc_socket_is_valid_ipc(serversocket, psock_rpmsg->clientsock) == -1){ //serversockÒѹرÕ

+		sk_soc_info("sock_soc_socket_is_valid is false \n");

+		return -1;

+	}

+	other = serversocket->sk;	

+	

+	sk_soc_info("sock_soc_sock_hold_proc serverfd=%d \n", psock_rpmsg->serverfd);

+	sock_hold(other);

+	return 0;

+}

+

+int sock_soc_sock_put(struct sock *other)

+{

+	struct sock_rpmsg sock_rpmsg = {0};

+	int sockfd;

+	struct ipc_socket *ipc_socket;

+	sock_rpmsg.msg_type = MSG_TYPE_SOCK_PUT;

+	//other->sk_socket¿ÉÄÜÒѱ»ÖÃΪnull

+	if(!other->sk_socket){

+		sockfd = other->sk_fd;

+	}

+	else{

+		sockfd = sock_lookup_fd_by_sock(other);

+	}

+	

+	//sock_rpmsg.serverfd = sock_lookup_serverfd_by_clientfd(sockfd);

+	//ipc_socket = sock_lookup_server_by_clientfd(sockfd);

+	ipc_socket = sock_soc_get_ipcsocket_by_proxysock(other);

+	if(NULL == ipc_socket){

+		sk_soc_info("sock_soc_sock_put get ipc_socket faild \n");

+		return -1;

+	}

+	sock_rpmsg.serverfd = ipc_socket->remotefd;

+	sock_rpmsg.serversock = ipc_socket->remotesocket;

+	sock_rpmsg.clientsock = ipc_socket->localsocket;

+	sk_soc_info("sock_soc_sock_put serverfd=%d\n", sock_rpmsg.serverfd);

+	sock_send_ipc_msg(&sock_rpmsg);

+	return 0;

+}

+EXPORT_SYMBOL_GPL(sock_soc_sock_put);

+

+int sock_soc_sock_put_proc(struct sock_rpmsg* psock_rpmsg)

+{	

+	struct socket *other;

+	int err;	

+	//other = sock_get_local_socket(psock_rpmsg->serverfd, &err);

+	other = (struct socket*)psock_rpmsg->serversock;

+	if(sock_soc_socket_is_valid_ipc(other, psock_rpmsg->clientsock) == -1){ //serversockÒѹرÕ

+		sk_soc_info("sock_soc_socket_is_valid is false \n");		

+		return -1;

+	}

+	sk_soc_info("sock_soc_sock_put_proc serversock=%x, serverfd=%d",other, psock_rpmsg->serverfd);

+	if(other->sk){

+		sock_put(other->sk);

+	}

+	

+	return 0;

+}

+

+int sock_soc_msg_send(struct sock *sock, struct sock *other, struct msghdr *msg, size_t len)

+{

+	struct ipc_socket *psocket_ipc = NULL;

+	//struct sock_rpmsg sock_rpmsg = {0};

+	//sock_rpmsg.msg_type = MSG_TYPE_SEND_MSG;

+	struct sock_rpmsg* psock_rpmsg =NULL;

+	

+	psock_rpmsg = sock_create_rpmsg(len);

+	if(psock_rpmsg == NULL){

+		sk_soc_err("sock_soc_msg_send failed, sock_create_rpmsg failed\n ");

+		return -1;

+	}

+	psock_rpmsg->msg_type = MSG_TYPE_SEND_MSG;

+	//¿Í»§¶Ësocket fd

+	psock_rpmsg->clientfd = sock_lookup_fd_by_sock(sock);

+	psock_rpmsg->clientsock = sock->sk_socket;

+	//²éÕÒ·þÎñÆ÷¶Ë´úÀísocketÏà¹ØÐÅÏ¢

+	psocket_ipc = sock_soc_get_ipcsocket_by_proxysock(other);

+	if(psocket_ipc == NULL){

+		sk_soc_info("sock_soc_msg_send failed, other->sk_fd=%d\n ", other->sk_fd);

+		kfree(psock_rpmsg);

+		return -1;

+	}

+	//·þÎñÆ÷¶Ësocket fd

+	psock_rpmsg->serverfd = psocket_ipc->remotefd;

+	psock_rpmsg->serversock = psocket_ipc->remotesocket;

+	psock_rpmsg->clientsock = psocket_ipc->localsocket;

+	

+	psock_rpmsg->msg_flags = msg->msg_flags;

+	//¿½±´·¢Ë͵ÄÊý¾Ý

+	memcpy_fromiovec(psock_rpmsg->data, msg->msg_iov, len);

+	psock_rpmsg->data_len = len;	

+	//strcpy(sock_rpmsg.data, "test");

+	//sock_rpmsg.data_len = 4;

+	//¿½±´socketµØÖ·

+	if(msg->msg_namelen > 0){

+		memcpy(&psock_rpmsg->sockaddr, (struct sockaddr_un*)msg->msg_name, msg->msg_namelen);

+	}

+	psock_rpmsg->addr_len = msg->msg_namelen;

+	sk_soc_info("sock_soc_msg_send clientfd=%d, serverfd=%d, data=%s, len=%d\n", psock_rpmsg->clientfd, psock_rpmsg->serverfd, psock_rpmsg->data, len);

+	sock_send_ipc_msg_data(psock_rpmsg);

+	return 0;

+}

+

+int sock_soc_msg_send_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct ipc_socket* clientsocket;

+	struct socket* serversocket;

+	struct sock* sock;

+	struct sock* other;

+	char __user * p,q;

+	mm_segment_t old_fs;

+	struct msghdr msg;

+	unsigned int  msg_flags;

+	struct iovec iov;

+	int err;

+	

+	//serversocket = sock_get_local_socket(psock_rpmsg->serverfd, &err);

+	serversocket = (struct socket*)psock_rpmsg->serversock;

+	if(sock_soc_socket_is_valid_ipc(serversocket, psock_rpmsg->clientsock) == -1){ //serversockÒѹرÕ

+		sk_soc_info("sock_soc_socket_is_valid is false \n");

+		return -1;

+	}

+	other = serversocket->sk;

+

+	clientsocket = sock_get_ipcsocket_by_local_and_remote(psock_rpmsg->serversock, psock_rpmsg->clientsock);

+	if(clientsocket == NULL){

+		sk_soc_info("sock_soc_msg_send_proc failed, serversock=%x,clientsock=%x\n ", psock_rpmsg->serversock, psock_rpmsg->clientsock);

+		return -1;

+	}

+	sk_soc_info("sock_soc_msg_send_proc, serversock=%x,clientsock=%x\n ", psock_rpmsg->serversock, psock_rpmsg->clientsock);

+	sock = clientsocket->sock;

+	

+	sk_soc_info("sock_soc_msg_send_proc clientfd=%d, serverfd=%d, len=%d", psock_rpmsg->clientfd, psock_rpmsg->serverfd, psock_rpmsg->data_len);

+	

+	old_fs = get_fs();

+	set_fs(KERNEL_DS);	

+	if(psock_rpmsg->addr_len > 0){

+		p = (__force struct sockaddr_un __user *)(&psock_rpmsg->sockaddr);	

+	}

+	q = (__force const char __user *)(psock_rpmsg->data);

+	//sys_sendto(psock_rpmsg->serverfd, psock_rpmsg->data, psock_rpmsg->data_len, psock_rpmsg->msg_flags, NULL, 0);

+	if(psock_rpmsg->addr_len > 0){

+		sys_sendto(clientsocket->sockfd, psock_rpmsg->data, psock_rpmsg->data_len, psock_rpmsg->msg_flags, &psock_rpmsg->sockaddr, psock_rpmsg->addr_len);

+	}else{

+		sys_sendto(clientsocket->sockfd, psock_rpmsg->data, psock_rpmsg->data_len, psock_rpmsg->msg_flags, NULL, 0);		

+	}		

+	set_fs(old_fs);

+	//other->sk_data_ready(other, psock_rpmsg->data_len);

+	//sock_put(other);

+	return 0;

+}

+

+long sock_wait_for_peer(struct sock *sock, struct sock *other, long timeo)

+{

+	struct ipc_socket * ipcsocket;	

+	struct sock_rpmsg sock_rpmsg = {0};

+	sock_rpmsg.clientfd = sock_lookup_fd_by_sock(sock);

+	sock_rpmsg.clientsock = sock->sk_socket;

+	ipcsocket = sock_soc_get_ipcsocket_by_proxysock(other);

+	if(ipcsocket == NULL){

+		sk_soc_info("sock_wait_for_peer failed, other->fd=%d\n ", other->sk_fd);

+		return -1;

+	}

+	sock_rpmsg.serverfd = ipcsocket->remotefd;

+	sock_rpmsg.serversock = ipcsocket->remotesocket;

+	sock_rpmsg.msg_type = MSG_TYPE_WAIT_FOR_PEER;

+	sock_rpmsg.timeo = timeo;

+	sk_soc_info("sock_wait_for_peer clientfd=%d, serverfd=%d", sock_rpmsg.clientfd, sock_rpmsg.serverfd);

+	sock_send_ipc_msg(&sock_rpmsg);

+	return 0;

+}

+

+static int sock_wait_for_peer_thread(void *argv)

+{

+	struct peer_sock_info* peer_info = (struct peer_sock_info*)argv;

+	sk_soc_info("sock_wait_for_peer_thread enter");

+	unix_wait_for_peer_proxy(peer_info->peersock, peer_info->timeo);

+	return 0;

+}

+

+int sock_wait_for_peer_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct ipc_socket *socket_ipc;

+	struct task_struct *th = NULL;

+	struct socket* clientsocket;

+	struct socket* serversocket;

+	int err;

+	socket_ipc = sock_get_ipcsocket_by_local_and_remote(psock_rpmsg->serversock, psock_rpmsg->clientsock); 

+	if(socket_ipc == NULL){

+		sk_soc_info("sock_wait_for_peer_proc failed, clientfd=%d,clientsock=%x\n ", psock_rpmsg->clientfd, psock_rpmsg->clientsock);

+		return -1;

+	}

+	struct peer_sock_info* peer_info = (struct peer_sock_info *)kzalloc(sizeof(struct peer_sock_info), GFP_ATOMIC);

+	if(NULL == peer_info){

+		sk_soc_err("kzalloc failed!");

+		return -1;

+	}

+	peer_info->timeo = psock_rpmsg->timeo;

+	clientsocket= sock_get_local_socket(socket_ipc->sockfd, &err);

+	if(NULL == clientsocket){

+		kfree(peer_info);

+		sk_soc_err("clientsocket is NULL!");

+		return -1;

+	}

+	//clientsocket = (struct socket*)psock_rpmsg->clientsock;

+	peer_info->sock = clientsocket->sk;

+	//serversocket = sock_get_local_socket(psock_rpmsg->serverfd, &err);

+	serversocket = (struct socket*)psock_rpmsg->serversock;

+	if(sock_soc_socket_is_valid_other(serversocket) == -1){ //serversockÒѹرÕ

+		sk_soc_info("sock_soc_socket_is_valid is false \n");

+		return -1;

+	}

+	peer_info->peersock = serversocket->sk;

+	sk_soc_info("sock_wait_for_peer_proc clientfd=%d, serverfd=%d", socket_ipc->sockfd, psock_rpmsg->serverfd);

+	th = kthread_run(sock_wait_for_peer_thread, peer_info, "wait_for_peer");

+	    if (IS_ERR(th)) {

+	        sk_soc_err("Unable to start receive thread.");

+	        return PTR_ERR(th);

+	    }

+	return 0;

+}

+

+int sock_soc_unix_peer_clear(struct sock *sk)

+{

+	struct sock_rpmsg sock_rpmsg = {0};

+	struct ipc_socket *socket_ipc;

+	sk_soc_info("sock_soc_unix_peer_clear enter\n");

+	//socket_ipc = sock_soc_get_ipcsocket_by_fd(psock_rpmsg->clientfd, psock_rpmsg->clientsock);

+	sock_rpmsg.clientfd = sock_lookup_fd_by_sock(sk);

+	sock_rpmsg.clientsock = sk->sk_socket;

+	sock_rpmsg.msg_type = MSG_TYPE_PEER_CLEAR;

+	sock_send_ipc_msg(&sock_rpmsg);

+	return 0;

+}

+

+int sock_soc_unix_peer_clear_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct socket* socket;

+	struct sock* sock;

+	int err;

+	sk_soc_info("sock_soc_unix_peer_clear_proc enter");

+	//socket = sock_get_local_socket(psock_rpmsg->serverfd, &err);

+	socket = (struct socket*)psock_rpmsg->serversock;

+	if(sock_soc_socket_is_valid_other(socket) == -1){ //serversockÒѹرÕ

+		sk_soc_info("sock_soc_socket_is_valid is false \n");

+		return -1;

+	}

+	sock = socket->sk;

+	if(sock == NULL){

+		sk_soc_info("sock_soc_unix_peer_clear_proc sock is NULL");		

+		return -1;

+	}

+	unix_sk(sock)->peer = NULL;

+	return 0;

+}

+

+int sock_soc_wake_up_interruptible_poll(struct sock *sk)

+{

+	struct sock_rpmsg sock_rpmsg = {0};	

+	

+	sock_rpmsg.clientfd = sock_lookup_fd_by_sock(sk);	

+	sock_rpmsg.clientsock = sk->sk_socket;

+	sock_rpmsg.msg_type = MSG_TYPE_WAKE_UP_INTERRUPTIBLE_POLL;

+	sk_soc_info("sock_soc_wake_up_interruptible_poll clientfd=%d", sock_rpmsg.clientfd);

+	sock_send_ipc_msg(&sock_rpmsg);

+	return 0;

+}

+

+int sock_soc_wake_up_interruptible_poll_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct socket* socket;

+	struct sock* sock;

+	int err;

+	//serverfd = sock_lookup_serverfd_by_clientfd(psock_rpmsg->clientfd);

+	//socket = sock_get_local_socket(serverfd, &err);

+	socket = (struct socket*)psock_rpmsg->serversock;

+	if(sock_soc_socket_is_valid_other(socket) == -1){ //serversockÒѹرÕ

+		sk_soc_info("sock_soc_socket_is_valid is false \n");

+		return -1;

+	}

+	sock = socket->sk;

+	if(sock == NULL){

+		sk_soc_info("sock_soc_wake_up_interruptible_poll_proc sock is NULL");		

+		return -1;

+	}

+	

+	wake_up_interruptible_poll(sk_sleep(sock),

+				   POLLOUT |

+				   POLLWRNORM |

+				   POLLWRBAND);

+	return 0;

+}

+

+int sock_soc_sk_data_ready(struct sock *sk)

+{

+	struct sock_rpmsg sock_rpmsg = {0};

+	struct ipc_socket * ipcsocket;

+	ipcsocket = sock_soc_get_ipcsocket_by_proxysock(sk);

+	if(ipcsocket == NULL){

+		sk_soc_info("sock_soc_sk_data_ready failed, sk->fd=%d\n ", sk->sk_fd);

+		return -1;

+	}

+	sock_rpmsg.serverfd = ipcsocket->remotefd;

+	sock_rpmsg.serversock = ipcsocket->remotesocket;

+	sock_rpmsg.clientsock = ipcsocket->localsocket;

+	sk_soc_info("sock_soc_sk_data_ready serverfd=%d", sock_rpmsg.serverfd);

+	sock_rpmsg.msg_type = MSG_TYPE_DATA_READY;

+	sock_send_ipc_msg(&sock_rpmsg);

+	return 0;

+}

+

+int sock_soc_sk_data_ready_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct socket* socket;

+	struct sock* sock;

+	int err;

+	//socket = sock_get_local_socket(psock_rpmsg->serverfd, &err);

+	socket = (struct socket*)psock_rpmsg->serversock;

+	if(sock_soc_socket_is_valid_ipc(socket, psock_rpmsg->clientsock) == -1){ //serversockÒѹرÕ

+		sk_soc_info("sock_soc_socket_is_valid is false \n");

+		return -1;

+	}

+	sk_soc_info("sock_soc_sk_data_ready_proc serverfd=%d", psock_rpmsg->serverfd);

+	sock = socket->sk;

+	if(sock == NULL){

+		sk_soc_info("sock_soc_sk_data_ready_proc sock is NULL");		

+		return -1;

+	}

+	sock->sk_data_ready(sock, 1);

+	return 0;

+}

+

+int sock_sync_ipc_socket(struct sock_elem_flag* elem_flag, struct sock *other)

+{

+	struct sock_rpmsg sock_rpmsg = {0};

+	struct ipc_socket * ipcsocket;

+	sock_rpmsg.msg_type = MSG_TYPE_SYNC_IPC_SOCKET;

+	memcpy(&sock_rpmsg.elem, elem_flag, sizeof(struct sock_elem_flag));

+	//memcpy(&sock_rpmsg.sock, other, sizeof(struct sock));

+	ipcsocket = sock_soc_get_ipcsocket_by_proxysock(other);

+	if(ipcsocket == NULL){

+		sk_soc_info("sock_sync_ipc_socket failed, other->fd=%d\n ", other->sk_fd);

+		return -1;

+	}

+	sock_rpmsg.serverfd = ipcsocket->remotefd;

+	sock_rpmsg.serversock = ipcsocket->remotesocket;

+	sock_rpmsg.clientsock = ipcsocket->localsocket;

+	sk_soc_info("sock_sync_ipc_socket serverfd=%d", sock_rpmsg.serverfd);

+	sock_send_ipc_msg(&sock_rpmsg);

+	

+	return 0;

+}

+

+int sock_sync_ipc_socket_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct socket* socket;

+	struct sock *other;

+	int err;

+	//socket = sock_get_local_socket(psock_rpmsg->serverfd, &err);

+	socket = (struct socket*)psock_rpmsg->serversock;

+	if(NULL == socket){

+		return -1;

+	}

+	if(sock_soc_socket_is_valid_ipc(socket, psock_rpmsg->clientsock) == -1){ //serversockÒѹرÕ

+		sk_soc_info("sock_soc_socket_is_valid is false \n");

+		return -1;

+	}

+	other = socket->sk;

+	if(other == NULL){

+		sk_soc_info("sock_sync_ipc_socket_proc other is NULL");		

+		return -1;

+	}

+	sk_soc_info("sock_sync_ipc_socket_proc serverfd=%d", psock_rpmsg->serverfd);

+	if(psock_rpmsg->elem.sk_err){

+		//other->sk_err = psock_rpmsg->sock.sk_err;		

+	}

+

+	if(psock_rpmsg->elem.sk_error_report){

+		other->sk_error_report(other);		

+	}

+	

+	return 0;

+}

+

+int sock_soc_get_state(struct sock_elem_flag* elem_flag, struct sock *other)

+{

+	struct sock_rpmsg sock_rpmsg = {0};

+	struct ipc_socket * ipcsocket;

+	struct sock_rpmsg_info *psock_rpmsg_info;

+	sock_rpmsg.msg_type = MSG_TYPE_GET_SOCKET_STATES;

+	memcpy(&sock_rpmsg.elem, elem_flag, sizeof(struct sock_elem_flag));	

+	ipcsocket = sock_soc_get_ipcsocket_by_proxysock(other);

+	if(ipcsocket == NULL){

+		sk_soc_info("sock_soc_get_state failed, other->fd=%d\n ", other->sk_fd);

+		return -1;

+	}

+	sock_rpmsg.serverfd = ipcsocket->remotefd;

+	sock_rpmsg.serversock = ipcsocket->remotesocket;

+	sock_rpmsg.clientsock = ipcsocket->localsocket;

+	sock_rpmsg.key = other;

+	sk_soc_info("sock_soc_get_state serverfd=%d", sock_rpmsg.serverfd);

+	

+	psock_rpmsg_info = sock_soc_create_rpmsg_info(sock_rpmsg.key);

+	if(NULL == psock_rpmsg_info){

+		sk_soc_info("sock_soc_get_state create rpmsg faild \n");

+		return -1;

+	}

+	sock_send_ipc_msg(&sock_rpmsg);

+	down_timeout(&psock_rpmsg_info->sock_sem, msecs_to_jiffies(g_sock_timeout));

+	

+	if(psock_rpmsg_info->sock_rpmsg.elem.skstate){

+		other->sk_state = psock_rpmsg_info->sock_rpmsg.elem.skstate;

+		sk_soc_info("sk_state=%d", other->sk_state);

+	}

+

+	if(psock_rpmsg_info->sock_rpmsg.elem.skshutdown){

+		other->sk_shutdown = psock_rpmsg_info->sock_rpmsg.elem.skshutdown;

+		sk_soc_info("sk_shutdown=%d", other->sk_shutdown);

+	}

+	sock_soc_del_rpmsg_info(sock_rpmsg.key);

+	sk_soc_info("sock_soc_get_state end");

+	return 0;

+}

+

+int sock_soc_get_state_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct socket* socket;

+	struct sock *other;

+	struct sock_rpmsg sock_rpmsg = {0};

+	int err;	

+	sock_rpmsg.msg_type = MSG_TYPE_GET_SOCKET_STATES_RESULT;

+	sock_rpmsg.key = psock_rpmsg->key;

+	sk_soc_info("sock_soc_get_state_proc serverfd=%d", psock_rpmsg->serverfd);

+	//socket = sock_get_local_socket(psock_rpmsg->serverfd, &err);

+	socket = (struct socket*)psock_rpmsg->serversock;

+	if(sock_soc_socket_is_valid_ipc(socket, psock_rpmsg->clientsock) == -1){ //serversockÒѹرÕ

+		sk_soc_info("sock_soc_socket_is_valid is false \n");

+		sock_send_ipc_msg(&sock_rpmsg);

+		return -1;

+	}

+	if(NULL != socket){

+		sk_soc_info("sock_soc_get_state_proc sucess");

+		other = socket->sk;

+		if(other == NULL){

+			sk_soc_info("sock_soc_get_state_proc other is NULL");

+			sock_send_ipc_msg(&sock_rpmsg);

+			return -1;

+		}

+		if(psock_rpmsg->elem.skstate){

+			sock_rpmsg.elem.skstate = other->sk_state;

+			sk_soc_info("sk_state=%d", other->sk_state);

+		}

+

+		if(psock_rpmsg->elem.skshutdown){

+			sock_rpmsg.elem.skshutdown = other->sk_shutdown;

+			sk_soc_info("sk_shutdown=%d", other->sk_shutdown);

+		}	

+	}

+	else

+	{

+		sk_soc_info("sock_soc_get_state_proc failed");

+	}	

+	sock_send_ipc_msg(&sock_rpmsg);	

+	return 0;

+}

+

+int sock_soc_get_state_result_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	sk_soc_info("sock_soc_find_other_result_proc");

+	sock_soc_rsp_proc(psock_rpmsg);

+	return 0;

+}

+

+int sock_soc_test_flags(struct sock *other, enum sock_flags flag)

+{

+	struct sock_rpmsg sock_rpmsg = {0};

+	struct ipc_socket * ipcsocket;

+	struct sock_rpmsg_info *psock_rpmsg_info;

+	int result;

+	sock_rpmsg.msg_type = MSG_TYPE_TEST_FLAG;	

+	ipcsocket = sock_soc_get_ipcsocket_by_proxysock(other);

+	if(ipcsocket == NULL){

+		sk_soc_info("sock_soc_test_flags failed, other->fd=%d\n ", other->sk_fd);

+		return -1;

+	}

+	sock_rpmsg.serverfd = ipcsocket->remotefd;

+	sock_rpmsg.serversock = ipcsocket->remotesocket;

+	sock_rpmsg.clientsock = ipcsocket->localsocket;

+	//sock_rpmsg.flag = flag;

+	sock_rpmsg.flag = convert_to_cap_sock_flag(flag);

+	if(sock_rpmsg.flag == -1)

+	{

+		sk_soc_info("cap do not support flag=%s ", flag_value[flag]);

+		return 0;

+	}

+	sock_rpmsg.key = other;

+	sk_soc_info("sock_soc_test_flags serverfd=%d", sock_rpmsg.serverfd);

+	

+	psock_rpmsg_info = sock_soc_create_rpmsg_info(sock_rpmsg.key);

+	if(NULL == psock_rpmsg_info){

+		sk_soc_info("sock_soc_get_state create rpmsg faild \n");

+		return -1;

+	}

+	sock_send_ipc_msg(&sock_rpmsg);

+	down_timeout(&psock_rpmsg_info->sock_sem, msecs_to_jiffies(g_sock_timeout));

+	sk_soc_info("sock_soc_test_flags flag=%s, result=%d\n",flag_value[flag], g_sock_rpmsg.result);

+	result = psock_rpmsg_info->sock_rpmsg.result;

+	sock_soc_del_rpmsg_info(sock_rpmsg.key);

+	return result;	

+}

+EXPORT_SYMBOL_GPL(sock_soc_test_flags);

+

+int sock_soc_test_flags_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct sock_rpmsg sock_rpmsg = {0};

+	struct socket* socket;

+	struct sock *other;

+	int err;

+	//socket = sock_get_local_socket(psock_rpmsg->serverfd, &err);

+	sock_rpmsg.msg_type = MSG_TYPE_TEST_FLAG_RESULT;

+	sock_rpmsg.key = psock_rpmsg->key;

+	socket = (struct socket*)psock_rpmsg->serversock;

+	if(sock_soc_socket_is_valid_ipc(socket, psock_rpmsg->clientsock) == -1){ //serversockÒѹرÕ

+		sk_soc_info("sock_soc_socket_is_valid is false \n");

+		sock_send_ipc_msg(&sock_rpmsg);

+		return -1;

+	}

+	if(NULL == socket){

+		sk_soc_info("sock_soc_test_flags_proc failed, flag=%s", flag_value[psock_rpmsg->flag]);

+		sock_send_ipc_msg(&sock_rpmsg);

+		return -1;

+	}

+	other = socket->sk;

+	if(other == NULL){

+		sock_send_ipc_msg(&sock_rpmsg);

+		return -1;

+	}	

+	sock_rpmsg.result = test_bit(psock_rpmsg->flag, &other->sk_flags);	

+	sk_soc_info("sock_soc_test_flags_proc flag=%s, result=%d", flag_value[psock_rpmsg->flag], sock_rpmsg.result);

+	sock_send_ipc_msg(&sock_rpmsg);

+	return 0;

+}

+

+int sock_soc_test_flags_result_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	sk_soc_info("sock_soc_test_flags_result_proc enter");

+	sock_soc_rsp_proc(psock_rpmsg);

+	

+	return 0;

+}

+

+void sock_soc_add_skb_queue_tail(struct sock *sock, struct sock *other)

+{

+	struct ipc_socket * ipcsocket;	

+	struct sock_rpmsg sock_rpmsg = {0};

+	sock_rpmsg.clientfd = sock_lookup_fd_by_sock(sock);

+	sock_rpmsg.clientsock = sock->sk_socket;

+	ipcsocket = sock_soc_get_ipcsocket_by_proxysock(other);

+	if(ipcsocket == NULL){

+		sk_soc_info("sock_soc_add_skb_queue_tail failed, other->fd=%d\n ", other->sk_fd);

+		return;

+	}

+	sock_rpmsg.serverfd = ipcsocket->remotefd;

+	sock_rpmsg.serversock = ipcsocket->remotesocket;

+	sock_rpmsg.clientsock = ipcsocket->localsocket;

+	sock_rpmsg.msg_type = MSG_TYPE_ADD_SKB_QUEUE_TAIL;

+	sk_soc_info("sock_soc_add_skb_queue_tail clientfd=%d, serverfd=%d", sock_rpmsg.clientfd, sock_rpmsg.serverfd);

+	sock_send_ipc_msg(&sock_rpmsg);

+}

+

+void sock_soc_add_skb_queue_tail_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct ipc_socket * ipcsocket;	

+	struct socket* other;

+	struct sk_buff *skb = NULL;

+	int err;

+	//¸ù¾ÝclientfdÕÒµ½±¾µØ´úÀísocket

+	ipcsocket = sock_get_ipcsocket_by_local_and_remote(psock_rpmsg->serversock, psock_rpmsg->clientsock);

+	if(ipcsocket == NULL){

+		sk_soc_info("sock_soc_add_skb_queue_tail_proc failed, clientfd=%d,clientsock=%x\n ", psock_rpmsg->clientfd, psock_rpmsg->clientsock);

+		return;

+	}

+	//other = sockfd_lookup(psock_rpmsg->serverfd, &err);

+	other = (struct socket*)psock_rpmsg->serversock;

+	if(sock_soc_socket_is_valid_ipc(other, psock_rpmsg->clientsock) == -1){ //serversockÒѹرÕ

+		sk_soc_info("sock_soc_socket_is_valid is false \n");

+		return;

+	}

+	sk_soc_info("sock_soc_add_skb_queue_tail clientfd=%d, serverfd=%d", psock_rpmsg->clientfd, psock_rpmsg->serverfd);

+	if((NULL != ipcsocket) && (NULL != other)){

+		/* Allocate skb for sending to listening sock */

+		skb = sock_wmalloc(ipcsocket->sock, 1, 0, GFP_KERNEL);

+		if (skb == NULL)

+		{

+			return; 

+		}

+

+		__skb_queue_tail(&other->sk->sk_receive_queue, skb);

+		sk_soc_info("sock_soc_add_skb_queue_tail sucess! \n");

+	}	

+}

+

+void sock_soc_stream_connect(struct sock *sock, struct sock *other, struct sockaddr_un *sunname, int len,int flags)

+{

+	struct ipc_socket * ipcsocket;	

+	struct sock_rpmsg sock_rpmsg = {0};

+	struct sock_rpmsg_info *psock_rpmsg_info;

+	if(len > 0){

+		memcpy(&sock_rpmsg.sockaddr, sunname, sizeof(struct sockaddr_un));

+		sk_soc_info("sock_soc_stream_connect sockaddr=%s", sock_rpmsg.sockaddr.sun_path);

+		sock_rpmsg.addr_len = len;

+	}

+	sock_rpmsg.flags = flags;

+	sock_rpmsg.clientfd = sock_lookup_fd_by_sock(sock);

+	sock_rpmsg.clientsock = sock->sk_socket;

+	ipcsocket = sock_soc_get_ipcsocket_by_proxysock(other);

+	if(ipcsocket == NULL){

+		sk_soc_info("sock_soc_stream_connect failed, other->fd=%d\n ", other->sk_fd);

+		return;

+	}

+	sock_rpmsg.serverfd = ipcsocket->remotefd;

+	sock_rpmsg.serversock = ipcsocket->remotesocket;

+	sock_rpmsg.msg_type = MSG_TYPE_STREAM_CONNECT;

+	sock_rpmsg.key = sock_rpmsg.clientsock;

+	psock_rpmsg_info = sock_soc_create_rpmsg_info(sock_rpmsg.key);

+	if(NULL == psock_rpmsg_info){

+		sk_soc_info("sock_soc_stream_connect create rpmsg faild \n");

+		return;

+	}

+	sock_send_ipc_msg(&sock_rpmsg);

+	//ÒªµÈµ½ÊÕµ½update_peer²ÅÄÜ·µ»Ø

+	down_timeout(&psock_rpmsg_info->sock_sem, msecs_to_jiffies(g_sock_timeout));

+	sk_soc_info("sock_soc_stream_connect clientfd=%d, serverfd=%d\n", sock_rpmsg.clientfd, sock_rpmsg.serverfd);

+	sock_soc_del_rpmsg_info(sock_rpmsg.key);

+}

+

+void sock_soc_stream_connect_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct ipc_socket * ipcsocket;	

+	struct socket* other;

+	struct sk_buff *skb = NULL;

+	struct sock *newsk = NULL;

+	int result = -1;

+	int err;

+	//¸ù¾ÝclientfdÕÒµ½±¾µØ´úÀísocket

+	ipcsocket = sock_get_ipcsocket_by_local_and_remote(psock_rpmsg->serversock, psock_rpmsg->clientsock);

+	if(ipcsocket == NULL){

+		sk_soc_info("sock_soc_stream_connect_proc failed, clientfd=%d,clientsock=%x\n ", psock_rpmsg->clientfd, psock_rpmsg->clientsock);

+		return;

+	}

+	//other = sockfd_lookup(psock_rpmsg->serverfd, &err);

+	other = (struct socket*)psock_rpmsg->serversock;

+	

+	sk_soc_info("sock_soc_stream_connect_proc clientfd=%d, serverfd=%d\n", psock_rpmsg->clientfd, psock_rpmsg->serverfd);

+	if((NULL != ipcsocket) && (NULL != other)){	

+		sk_soc_info("sockaddr=%s", psock_rpmsg->sockaddr.sun_path);

+		result = unix_stream_connect_proxy(ipcsocket->socket, (struct sockaddr *)&psock_rpmsg->sockaddr, psock_rpmsg->addr_len, psock_rpmsg->flags);

+		if(0 == result){

+			sk_soc_info("sock_soc_stream_connect_proc sucess! ");

+		}else{

+			sk_soc_info("sock_soc_stream_connect_proc failed! ");

+		}	    

+	}	

+}

+

+void sock_soc_add_wait_queue(struct sock *sock, struct sock *other)

+{

+	struct ipc_socket * ipcsocket;	

+	struct sock_rpmsg sock_rpmsg = {0};

+	sock_rpmsg.clientfd = sock_lookup_fd_by_sock(sock);

+	sock_rpmsg.clientsock = sock->sk_socket;

+	ipcsocket = sock_soc_get_ipcsocket_by_proxysock(other);

+	if(ipcsocket == NULL){

+		sk_soc_info("sock_soc_add_wait_queue failed, other->fd=%d\n ", other->sk_fd);

+		return;

+	}

+	sock_rpmsg.serverfd = ipcsocket->remotefd;

+	sock_rpmsg.serversock = ipcsocket->remotesocket;

+	sock_rpmsg.msg_type = MSG_TYPE_ADD_WAIT_QUEUE;

+	sk_soc_info("sock_soc_add_wait_queue enter");

+	sock_send_ipc_msg(&sock_rpmsg);

+}

+

+void sock_soc_add_wait_queue_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct ipc_socket * ipcsocket;	

+	struct socket* socket;

+	int err;

+	//¸ù¾ÝclientfdÕÒµ½±¾µØ´úÀísocket

+	ipcsocket = sock_get_ipcsocket_by_local_and_remote(psock_rpmsg->serversock, psock_rpmsg->clientsock);

+	if(ipcsocket == NULL){

+		sk_soc_info("sock_soc_add_wait_queue_proc failed, clientfd=%d,clientsock=%x\n ", psock_rpmsg->clientfd, psock_rpmsg->clientsock);

+		return;

+	}

+	//socket = sockfd_lookup(psock_rpmsg->serverfd, &err);

+	socket = (struct socket*)psock_rpmsg->serversock;

+	

+	sk_soc_info("sock_soc_add_wait_queue_proc clientfd=%d, serverfd=%d", psock_rpmsg->clientfd, psock_rpmsg->serverfd);

+	if((NULL != ipcsocket) && (NULL != socket)){

+		unix_dgram_peer_wake_connect_proxy(ipcsocket->sock, socket->sk);

+	}	

+}

+

+void sock_soc_remove_wait_queue(struct sock *sock, struct sock *other)

+{

+	struct ipc_socket * ipcsocket;	

+	struct sock_rpmsg sock_rpmsg = {0};

+	sock_rpmsg.clientfd = sock_lookup_fd_by_sock(sock);

+	sock_rpmsg.clientsock = sock->sk_socket;

+	ipcsocket = sock_soc_get_ipcsocket_by_proxysock(other);

+	if(ipcsocket == NULL){

+		sk_soc_info("sock_soc_remove_wait_queue failed, other->fd=%d\n ", other->sk_fd);

+		return;

+	}

+	sock_rpmsg.serverfd = ipcsocket->remotefd;

+	sock_rpmsg.serversock = ipcsocket->remotesocket;

+	sock_rpmsg.msg_type = MSG_TYPE_REMOVE_WAIT_QUEUE;

+	sk_soc_info("sock_soc_remove_wait_queue clientfd=%d, serverfd=%d", sock_rpmsg.clientfd, sock_rpmsg.serverfd);

+	sock_send_ipc_msg(&sock_rpmsg);

+}

+

+void sock_soc_remove_wait_queue_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct ipc_socket * ipcsocket;	

+	struct socket* socket;

+	int err;

+	//¸ù¾ÝclientfdÕÒµ½±¾µØ´úÀísocket

+	ipcsocket = sock_get_ipcsocket_by_local_and_remote(psock_rpmsg->serversock, psock_rpmsg->clientsock);

+	if(ipcsocket == NULL){

+		sk_soc_info("sock_soc_remove_wait_queue_proc failed, clientfd=%d,clientsock=%x\n ", psock_rpmsg->clientfd, psock_rpmsg->clientsock);

+		return;

+	}

+	//socket = sockfd_lookup(psock_rpmsg->serverfd, &err);

+	socket = (struct socket*)psock_rpmsg->serversock;

+	

+	sk_soc_info("sock_soc_remove_wait_queue_proc clientfd=%d, serverfd=%d", psock_rpmsg->clientfd, psock_rpmsg->serverfd);

+	if((NULL != ipcsocket) && (NULL != socket)){

+		unix_dgram_peer_wake_connect_proxy(ipcsocket->sock, socket->sk);

+	}	

+}

+

+void sock_soc_notify_proxy_change_to_server(struct socket* proxysocket, struct socket* remoteproxysocket)

+{

+	struct sock_rpmsg sock_rpmsg = {0};

+	sock_rpmsg.clientproxyfd = proxysocket->fd;

+	sock_rpmsg.clientproxysock = proxysocket;

+	sock_rpmsg.serverproxysock = remoteproxysocket;

+	sock_rpmsg.msg_type = MSG_TYPE_NOTIFY_PROXY_CHANGE;

+	sk_soc_info("sock_soc_notify_proxy_change_to_server clientproxysock=%x, serverproxysock=%x", sock_rpmsg.clientproxysock, sock_rpmsg.serverproxysock);

+	sock_send_ipc_msg(&sock_rpmsg);

+}

+

+void sock_soc_notify_proxy_change_to_server_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct ipc_socket* ipc_socket;

+	struct socket* serverproxysock;

+	ipc_socket = sock_soc_get_ipcsocket_by_proxysock(psock_rpmsg->serverproxysock);

+	if(NULL != ipc_socket){

+		sk_soc_info("sock_soc_notify_proxy_change_to_server_proc remoteproxysocket=%x", psock_rpmsg->clientproxysock);

+		ipc_socket->remoteproxyfd = psock_rpmsg->clientproxyfd;

+		ipc_socket->remoteproxysocket = psock_rpmsg->clientproxysock;

+		serverproxysock = (struct socket*)psock_rpmsg->serverproxysock;

+		usock_update_remote_proxy_socket(serverproxysock->sk, psock_rpmsg->clientproxysock);

+	}	

+}

+

+struct sock *sock_soc_find_other(struct socket * socket/*int fd*/,

+				    struct sockaddr_un *sunname, int len,

+				    int type, unsigned int hash, int *error)

+{

+	struct sock_rpmsg sock_rpmsg = {0};

+	struct ipc_socket *psocket_ipc = NULL;

+	struct sock_rpmsg_info *psock_rpmsg_info = NULL;

+	int err;

+	//struct socket *clisocket = sock_get_local_socket(fd, &err);

+	memcpy(&sock_rpmsg.sockaddr, sunname, sizeof(struct sockaddr_un));

+	sock_rpmsg.addr_len = len;

+	sock_rpmsg.socktype = type;

+	sock_rpmsg.hash = hash;

+	sock_rpmsg.clientfd = socket->fd;

+	sock_rpmsg.clientsock = socket;

+	sock_rpmsg.key = socket;

+	sock_rpmsg.msg_type = MSG_TYPE_FIND; 

+	sock_rpmsg.isfistfind = 0;

+	

+	if(sock_soc_get_ipcsocket_by_localsocket(socket) == NULL){ //˵Ã÷ÊǵÚÒ»´Î·¢Æð²éÕÒ

+		sock_rpmsg.isfistfind = 1;

+	}

+	

+	psock_rpmsg_info = sock_soc_create_rpmsg_info(sock_rpmsg.key);

+	sk_soc_info("sock_soc_find_other clientfd=%d, key=%x", sock_rpmsg.clientfd, sock_rpmsg.key);

+	sock_send_ipc_msg(&sock_rpmsg);

+	down_timeout(&psock_rpmsg_info->sock_sem, msecs_to_jiffies(g_sock_timeout));

+

+	if(test_bit(SOCK_OP_RESULT, &psock_rpmsg_info->sock_rpmsg.flags)){		

+		sk_soc_info("sock_soc_find_other sucess serverfd=%d", psock_rpmsg_info->sock_rpmsg.serverfd);

+		psocket_ipc = psock_rpmsg_info->ipc_socket;

+		sk_soc_info("sock_soc_find_other sockfd=%d, remotefd=%d", psocket_ipc->sockfd, psocket_ipc->remotefd);

+		//socket->peer = psocket_ipc->socket;

+		sock_soc_insert_socket_peer(socket, psocket_ipc->proxysocket);

+		sock_soc_del_rpmsg_info(sock_rpmsg.key);

+		sock_soc_notify_proxy_change_to_server(psocket_ipc->proxysocket, psocket_ipc->remoteproxysocket);

+		//sock_soc_set_socket_info(psocket_ipc->socket, socket);

+		return psocket_ipc->sock;

+	} else {

+		sk_soc_info("sock_soc_find_other failed, no matched socket");

+	}

+	sock_soc_del_rpmsg_info(sock_rpmsg.key);

+	

+	return NULL;

+}

+

+int sock_soc_find_other_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct sock *u;

+	struct ipc_socket *psocket_ipc = NULL;

+	//struct net tmpnet={0};

+	struct sock_rpmsg sock_rpmsg = {0};

+	int serverfd;

+	int error = -1;

+	unsigned int hash;

+	sk_soc_info("sock_soc_find_other_proc index=%d", psock_rpmsg->index);

+	if((NULL == psock_rpmsg) || (psock_rpmsg->msg_type != MSG_TYPE_FIND)){

+		sk_soc_info("sock_soc_find_other_proc failed, NULL == psock_rpmsg");

+		return -1;

+	}

+	sock_rpmsg.msg_type = MSG_TYPE_FIND_RESULT; 

+	sk_soc_info("sockaddr=%s,socktype=%d, hash=%d",psock_rpmsg->sockaddr.sun_path,psock_rpmsg->socktype,psock_rpmsg->hash);

+	error = unix_mkname_proxy(&psock_rpmsg->sockaddr, psock_rpmsg->addr_len, &hash);

+	if (error < 0){

+		sk_soc_info("unix_mkname_proxy failed, error=%d", error);

+	}

+	sk_soc_info("unix_mkname_proxy sucess, hash=%d", hash);

+	//init_net

+	u = unix_find_other_proxy(&init_net, &psock_rpmsg->sockaddr, psock_rpmsg->addr_len, psock_rpmsg->socktype, hash, &error);

+	if(u){		

+		sk_soc_info("find_other_proc: u(%x)->sk_socket=%x\n", u, u->sk_socket);

+		serverfd = sock_lookup_fd_by_sock(u);

+		psock_rpmsg->serverfd = serverfd;

+		psock_rpmsg->serversock = u->sk_socket;

+		psocket_ipc = sock_create_proxy_socket_client(psock_rpmsg);

+		if(NULL != psocket_ipc){

+			psocket_ipc->localsocket = u->sk_socket;

+			set_bit(SOCK_OP_RESULT, &sock_rpmsg.flags);

+			//memcpy(&sock_rpmsg.sock, u, sizeof(struct sock));

+			sock_rpmsg.serverfd = serverfd;

+			sock_rpmsg.serversock = u->sk_socket;

+			sock_rpmsg.socktype = u->sk_socket->type;		

+			sock_rpmsg.serverproxyfd = psocket_ipc->sockfd;

+			sock_rpmsg.serverproxysock = psocket_ipc->proxysocket;

+			//u->sk_socket->peer = psocket_ipc->socket; //TODO:u¿ÉÄܱ»¶à¸ö¿Í»§¶Ë²éÕÒ£¬´Ë´¦peerÖ¸Ïò´úÀísocketÓÐÎÊÌ⣬ÒòΪ¿ÉÄÜ´æÔÚ¶à¸ö´úÀísocket

+			sock_soc_insert_socket_peer(u->sk_socket, psocket_ipc->proxysocket);

+		}		

+		

+		sock_put(u); //0707

+		sk_soc_info("sock_soc_find_other_proc success, socktype=%d, serverfd=%d, key=%x, index=%d\n", sock_rpmsg.socktype, sock_rpmsg.serverfd, psock_rpmsg->key, psock_rpmsg->index);

+	}

+	else

+	{

+		sk_soc_info("sock_soc_find_other_proc failed, error=%d", error);

+	}

+	sock_rpmsg.key = psock_rpmsg->key;

+	sock_rpmsg.clientfd = psock_rpmsg->clientfd;

+	sock_rpmsg.clientsock = psock_rpmsg->clientsock;

+	sock_rpmsg.index = psock_rpmsg->index;

+	sock_send_ipc_msg(&sock_rpmsg);

+

+	return 0;

+}

+

+int sock_soc_find_other_result_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct sock_rpmsg_info *psock_rpmsg_info = NULL;	

+	

+	psock_rpmsg_info = sock_soc_get_rpmsg_info(psock_rpmsg->key);

+	if(NULL == psock_rpmsg_info){

+		sk_soc_info("sock_soc_find_other_result_proc failed\n");

+		return -1;

+	}

+	memset(&psock_rpmsg_info->sock_rpmsg, 0, sizeof(struct sock_rpmsg));

+	memcpy(&psock_rpmsg_info->sock_rpmsg, psock_rpmsg, sizeof(struct sock_rpmsg));

+	if(test_bit(SOCK_OP_RESULT, &psock_rpmsg->flags)){

+		psock_rpmsg_info->ipc_socket = sock_create_proxy_socket_server(psock_rpmsg);

+	}

+	up(&psock_rpmsg_info->sock_sem);

+	return 0;

+}

+

+static void delayed_release(struct work_struct *unused)

+{

+	//struct llist_node *node = llist_del_all(&delayed_release_list);

+	struct release_socket *rsock, *t;

+	sk_soc_info("delayed_release enter\n");

+	spin_lock(&sock_release_table_lock);

+	list_for_each_entry_safe(rsock, t, &delayed_release_list, list_node){

+		//sock_soc_release_sock(rsock);

+		sock_soc_release_peer(rsock);

+		list_del(&rsock->list_node);

+		kfree(rsock);

+	}

+	spin_unlock(&sock_release_table_lock);

+}

+

+static DECLARE_DELAYED_WORK(delayed_release_work, delayed_release);

+

+void sock_soc_delay_release(struct socket *sock)

+{

+	struct release_socket* prelease_socket = NULL;

+	struct unix_sock* usock;

+	struct socket_info *p;

+	struct hlist_node *pos,*n;

+	if(!hlist_empty(&sock->peer)){

+		spin_lock(&sock_release_peer_lock);

+		hlist_for_each_entry_safe(p, pos, n, &sock->peer, hlist_node) {

+			usock = unix_sk(p->proxysocket->sk);		    

+			//ÅжÏusockÐÅÏ¢ÊÇ·ñ»¹ÔÚ´úÀíÁ´±íÖÐ

+			if(0 != sock_is_valide_ipc_socket(usock->rsock.localsocket, usock->rsock.proxysocket, usock->rsock.remotesocket)){

+				sk_soc_info("sock_soc_delay_release failed \n");

+				continue;

+			}

+			prelease_socket = (struct release_socket *)kzalloc(sizeof(struct release_socket), GFP_ATOMIC);

+			if(NULL == prelease_socket){

+				sk_soc_info("kzalloc failed \n");

+				continue;

+			}

+			memcpy(prelease_socket, &usock->rsock, sizeof(struct release_socket));			

+			list_add(&prelease_socket->list_node, &delayed_release_list);			

+			sock_soc_del_socket_info(p->proxysocket, sock);

+		}

+		

+		//sock_put(sock->sk); /* It may now die */

+		

+		INIT_HLIST_HEAD(&sock->peer);

+		spin_unlock(&sock_release_peer_lock);

+		schedule_delayed_work(&delayed_release_work, 1);						

+		//}			

+	}

+	

+}

+

+int sock_soc_release_peer(struct release_socket* rsock)

+{	

+	struct sock_rpmsg sock_rpmsg = {0};

+	struct socket* peersocket;

+	struct ipc_socket * ipcsocket;

+	struct sock* proxy_sock = NULL;

+	//ɾ³ý±¾µØ¶ÔÓ¦µÄ´úÀísocket

+	if(rsock->proxysocket){		

+		sk_soc_info("sock_soc_release_peer close fd=%d \n", rsock->proxysocket->fd);

+		sock_rpmsg.socktype = rsock->proxysocket->type;

+		//ipcsocket = sock_soc_get_ipcsocket(rsock->sock->sk); //0706¸ù¾Ý±¾µØ´úÀísocket,ÕÒµ½¶ÔÓ¦·þÎñ¶Ësocket 

+		if(NULL != rsock->remotesocket){

+			sock_rpmsg.serverfd = rsock->remotefd;

+			sock_rpmsg.serversock = rsock->remotesocket;

+		}else{

+			sk_soc_info("sock_soc_get_ipcsocket_by_proxysock failed \n");

+		}

+		

+	    spin_lock(&sock_release_lock);

+		

+		rsock->proxysocket->sk->closed = 1;

+		proxy_sock = rsock->proxysocket->sk->proxy_sock;

+		sys_close(rsock->proxysocket->fd);

+		if(proxy_sock != NULL){ //0706

+			unix_release_sock_proxy(proxy_sock);

+		}

+		//Ç°ÃæÒѾ­É¾³ý¹ýÁË

+		//sock_del_ipc_socket_by_proxysocket(rsock->proxysocket);

+		spin_unlock(&sock_release_lock);

+	}

+	sock_rpmsg.clientfd = rsock->localfd;

+	sock_rpmsg.clientsock = rsock->localsocket;

+	sock_rpmsg.serversock = rsock->remotesocket;

+	sock_rpmsg.serverproxysock = rsock->remoteproxysocket;

+	sock_rpmsg.msg_type = MSG_TYPE_RELEASE_PEER;

+	sk_soc_info("sock_soc_release_peer clientfd=%d \n", sock_rpmsg.clientfd);

+	sock_send_ipc_msg(&sock_rpmsg);

+	return 0;

+}

+

+int sock_soc_release_peer_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct ipc_socket * ipcsocket;	

+	struct socket* proxysocket;

+	struct socket* serversocket;

+	struct sock* skpair;

+	int			type;

+	int closefd;

+	int err;

+	sk_soc_info("sock_soc_release_peer_proc clientfd=%d \n", psock_rpmsg->clientfd);

+	//¸ù¾ÝclientfdÕÒµ½±¾µØ´úÀísocket

+	spin_lock(&sock_release_lock);

+	//ÅжÏsocketÐÅÏ¢ÊÇ·ñ»¹ÔÚ´úÀíÁ´±íÖÐ

+	if(0 != sock_is_valide_ipc_socket(psock_rpmsg->serversock, psock_rpmsg->serverproxysock, psock_rpmsg->clientsock)){

+		sk_soc_info("sock_soc_release_peer_proc failed, sock_is_valide_ipc_socket=false \n");

+		spin_unlock(&sock_release_lock);

+		return -1;

+	}

+	

+	ipcsocket = sock_get_ipcsocket_by_local_and_remote(psock_rpmsg->serversock, psock_rpmsg->clientsock);

+	if(ipcsocket != NULL){

+		type = psock_rpmsg->socktype;

+		sk_soc_info("sock_soc_release_peer_proc close sockfd=%d, socktype=%d\n", ipcsocket->sockfd, type);

+		//sock_soc_del_socket_info(ipcsocket->socket, ipcsocket->localsocket); //0706 ½«´úÀísocket´ÓsocketsÁбíÖÐɾ³ý

+		

+		serversocket = (struct socket*)psock_rpmsg->serversock;

+		proxysocket = (struct socket*)ipcsocket->proxysocket;

+		//ĿǰSOCK_STREAMºÍSOCK_DGRAMÊÍ·ÅÁ÷³ÌÓÐÇø±ð

+		if(type == SOCK_STREAM){

+			//sock_del_ipc_socket_by_socket(ipcsocket->proxysocket);

+			skpair = serversocket->sk;

+			unix_state_lock(skpair);

+			/* No more writes */

+			skpair->sk_shutdown = SHUTDOWN_MASK;

+			//if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)

+			//	serversocket->sk_err = ECONNRESET;

+			unix_state_unlock(skpair);

+			skpair->sk_state_change(skpair);

+			sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP);

+		}else if(type == SOCK_DGRAM){

+			

+			sock_soc_del_socket_peer(serversocket, proxysocket);	

+			ipcsocket->sock->closed = 1;

+			closefd = ipcsocket->sockfd;

+			sock_soc_del_socket_info(ipcsocket->socket, ipcsocket->localsocket); //0706 ½«´úÀísocket´ÓsocketsÁбíÖÐɾ³ý

+			

+			sys_close(closefd);			

+		}		

+	}else{

+		sk_soc_info("sock_soc_release_peer_proc failed, localsock=%x, remotesock=%x", psock_rpmsg->serversock, psock_rpmsg->clientsock);

+		

+	}

+	spin_unlock(&sock_release_lock);

+	return 0;

+}

+

+int sock_soc_dgram_disconnected(struct sock *sock, struct sock *other)

+{

+	struct ipc_socket *psocket_ipc = NULL;

+	struct sock_rpmsg sock_rpmsg = {0};

+	sock_rpmsg.msg_type = MSG_TYPE_DGRAM_DISCONNECTED;

+	

+	//¿Í»§¶Ësocket fd

+	sock_rpmsg.clientfd = sock_lookup_fd_by_sock(sock);

+	sock_rpmsg.clientsock = sock->sk_socket;

+	//²éÕÒ·þÎñÆ÷¶Ë´úÀísocketÏà¹ØÐÅÏ¢

+	psocket_ipc = sock_soc_get_ipcsocket_by_proxysock(other);

+	if(psocket_ipc == NULL){

+		sk_soc_info("sock_soc_remove_wait_queue failed, other->fd=%d\n ", other->sk_fd);

+		return -1;

+	}

+	//·þÎñÆ÷¶Ësocket fd

+	sock_rpmsg.serverfd = psocket_ipc->remotefd;

+	sock_rpmsg.serversock = psocket_ipc->remotesocket;

+	sk_soc_info("sock_soc_dgram_disconnected clientfd=%d, serverfd=%d \n", sock_rpmsg.clientfd, sock_rpmsg.serverfd);

+	sock_send_ipc_msg(&sock_rpmsg);

+	return 0;

+}

+

+int sock_soc_dgram_disconnected_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct ipc_socket* clientsocket;

+	struct socket* serversocket;

+	struct sock* sock;

+	struct sock* other;

+	

+	serversocket = (struct socket*)psock_rpmsg->serversock;

+	if(sock_soc_socket_is_valid_ipc(serversocket, psock_rpmsg->clientsock) == -1){ //serversockÒѹرÕ

+		sk_soc_info("sock_soc_socket_is_valid is false \n");

+		return -1;

+	}

+	other = serversocket->sk;

+

+	clientsocket = sock_get_ipcsocket_by_local_and_remote(psock_rpmsg->serversock, psock_rpmsg->clientsock);

+	if(clientsocket == NULL){

+		sk_soc_info("sock_soc_dgram_disconnected_proc failed, clientfd=%d,clientsock=%x\n ", psock_rpmsg->clientfd, psock_rpmsg->clientsock);

+		return -1;

+	}

+	sock = clientsocket->sock;

+	

+	sk_soc_info("sock_soc_dgram_disconnected_proc clientfd=%d, serverfd=%d \n", psock_rpmsg->clientfd, psock_rpmsg->serverfd);

+	unix_dgram_disconnected_proxy(sock, other);

+	return 0;

+}

+

+void sock_soc_state_lock(struct sock *other)

+{

+	struct ipc_socket *psocket_ipc = NULL;

+	struct sock_rpmsg sock_rpmsg = {0};

+	sock_rpmsg.msg_type = MSG_TYPE_STATE_LOCK;

+		

+	//²éÕÒ·þÎñÆ÷¶Ë´úÀísocketÏà¹ØÐÅÏ¢

+	psocket_ipc = sock_soc_get_ipcsocket_by_proxysock(other);

+	if(psocket_ipc == NULL){

+		sk_soc_info("sock_soc_state_lock failed, other->fd=%d\n ", other->sk_fd);

+		return;

+	}

+	//·þÎñÆ÷¶Ësocket fd

+	sock_rpmsg.serverfd = psocket_ipc->remotefd;

+	sock_rpmsg.serversock = psocket_ipc->remotesocket;

+	sock_rpmsg.clientsock = psocket_ipc->localsocket;

+	sk_soc_info("sock_soc_state_lock serverfd=%d \n", sock_rpmsg.serverfd);

+	sock_send_ipc_msg(&sock_rpmsg); 

+}

+

+int sock_soc_state_lock_proc(struct sock_rpmsg* psock_rpmsg)

+{	

+	struct socket* serversocket;	

+	struct sock* other;

+	

+	serversocket = (struct socket*)psock_rpmsg->serversock;

+	if(sock_soc_socket_is_valid_ipc(serversocket, psock_rpmsg->clientsock) == -1){ //serversockÒѹرÕ

+		sk_soc_info("sock_soc_socket_is_valid is false \n");

+		return -1;

+	}

+	other = serversocket->sk;	

+	

+	sk_soc_info("sock_soc_state_lock_proc serverfd=%d \n", psock_rpmsg->serverfd);

+	unix_state_lock(other);

+	return 0;

+}

+

+void sock_soc_state_unlock(struct sock *other)

+{

+	struct ipc_socket *psocket_ipc = NULL;

+	struct sock_rpmsg sock_rpmsg = {0};

+	sock_rpmsg.msg_type = MSG_TYPE_STATE_UNLOCK;

+		

+	//²éÕÒ·þÎñÆ÷¶Ë´úÀísocketÏà¹ØÐÅÏ¢

+	psocket_ipc = sock_soc_get_ipcsocket_by_proxysock(other);

+	if(psocket_ipc == NULL){

+		sk_soc_info("sock_soc_state_unlock failed, other->fd=%d\n ", other->sk_fd);

+		return;

+	}

+	//·þÎñÆ÷¶Ësocket fd

+	sock_rpmsg.serverfd = psocket_ipc->remotefd;

+	sock_rpmsg.serversock = psocket_ipc->remotesocket;

+	sock_rpmsg.clientsock = psocket_ipc->localsocket;

+	sk_soc_info("sock_soc_state_unlock serverfd=%d \n", sock_rpmsg.serverfd);

+	sock_send_ipc_msg(&sock_rpmsg); 

+}

+

+int sock_soc_state_unlock_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct socket* serversocket;	

+	struct sock* other;

+	

+	serversocket = (struct socket*)psock_rpmsg->serversock;

+	if(sock_soc_socket_is_valid_ipc(serversocket, psock_rpmsg->clientsock) == -1){ //serversockÒѹرÕ

+		sk_soc_info("sock_soc_socket_is_valid is false \n");

+		return -1;

+	}

+	other = serversocket->sk;	

+	

+	sk_soc_info("sock_soc_state_unlock_proc serverfd=%d \n", psock_rpmsg->serverfd);

+	unix_state_lock(other);

+	return 0;

+}

+

+static int sock_create_icp_channel(T_ZDrvRpMsg_ActorID core_id, T_ZDrvRpMsg_ChID channel_id, unsigned int channel_size)

+{

+    int retval;

+

+    retval = sockSocCreateChannel (core_id, channel_id, channel_size);

+    if(retval != RPMSG_SUCCESS && retval != RPMSG_CHANNEL_ALREADY_EXIST)

+        goto out;

+

+	sk_soc_info("sock_create_icp_channel success");

+    return retval;

+

+out:

+    sk_soc_err("could not create channel.");

+    return retval;

+}

+

+static void sock_dld_handle(struct	sock_rpmsg* sock_rpmsg)

+{

+	int len;	

+	len = sock_channel_write(&g_sock_chn_info, sock_rpmsg, sock_rpmsg->data_len + sizeof(struct sock_rpmsg));

+	sk_soc_info("sock_dld_handle len=%d, index=%d", len, sock_rpmsg->index);

+	return;

+}

+static void sock_uld_handle(struct	sock_rpmsg* sock_rpmsg)

+{

+	if(NULL == sock_rpmsg){

+		return;

+	}

+	

+	switch(sock_rpmsg->msg_type) {

+		case MSG_TYPE_FIND:

+			sock_soc_find_other_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_FIND_RESULT:

+			sock_soc_find_other_result_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_ADD_WAIT_QUEUE:

+			sock_soc_add_wait_queue_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_REMOVE_WAIT_QUEUE:

+			sock_soc_remove_wait_queue_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_SYNC_IPC_SOCKET:

+			sock_sync_ipc_socket_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_WAIT_FOR_PEER:

+			sock_wait_for_peer_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_DATA_READY:

+			sock_soc_sk_data_ready_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_SEND_MSG:

+			sock_soc_msg_send_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_ADD_SKB_QUEUE_TAIL:

+			sock_soc_add_skb_queue_tail_proc(sock_rpmsg);

+			break;	

+		case MSG_TYPE_SET_PEER:

+			sock_soc_set_peer_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_RECVQ_FULL:

+			sock_soc_recvq_full_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_RECVQ_FULL_RESULT:

+			sock_soc_recvq_full_result_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_PEER_CLEAR:

+			sock_soc_unix_peer_clear_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_WAKE_UP_INTERRUPTIBLE_POLL:

+			sock_soc_wake_up_interruptible_poll_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_RECVQ_FULL_LOCKLESS_AND_DEAD:

+			sock_soc_recvq_full_lockless_and_dead_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_RECVQ_FULL_LOCKLESS_AND_DEAD_RESULT:

+			sock_soc_recvq_full_lockless_and_dead_result_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_TEST_FLAG:

+			sock_soc_test_flags_proc(sock_rpmsg);					

+			break;

+		case MSG_TYPE_TEST_FLAG_RESULT:

+			sock_soc_test_flags_result_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_SOCK_PUT:

+			sock_soc_sock_put_proc(sock_rpmsg);

+			break;					

+		case MSG_TYPE_GET_SOCKET_STATES:

+			sock_soc_get_state_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_GET_SOCKET_STATES_RESULT:

+			sock_soc_get_state_result_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_STREAM_CONNECT:

+			sock_soc_stream_connect_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_UPDATE_PEER:

+			sock_soc_update_peer_proc(sock_rpmsg);

+			break;		

+		case MSG_TYPE_DGRAM_DISCONNECTED:

+			sock_soc_dgram_disconnected_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_STATE_LOCK:

+			sock_soc_state_lock_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_STATE_UNLOCK:

+			sock_soc_state_unlock_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_SOCK_HOLD:

+			sock_soc_sock_hold_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_RELEASE_PEER:

+			sock_soc_release_peer_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_NOTIFY_PROXY_CHANGE:

+			sock_soc_notify_proxy_change_to_server_proc(sock_rpmsg);

+			break;

+		default:

+		    break;

+	}

+}

+

+static int sock_receive_thread(void *argv)

+{   

+	int index,ret_len,i,num;

+    unsigned long flags;

+	//static struct sock_rpmsg sock_rpmsg = {0};

+	static char recvbuf[SOCK_DATA_MAX_LEN] = {0};

+	sk_soc_info("sock_receive_thread process");

+	while(1){

+		if(0 < sock_channel_read(&g_sock_chn_info, recvbuf, sizeof(recvbuf))) {

+			//sk_soc_info("sock_receive_thread sock_rpmsg.msg_type=%d,index=%d", sock_rpmsg.msg_type, sock_rpmsg.index);	

+#if 1

+			sock_recv_ipc_msg((struct sock_rpmsg*)recvbuf);

+#else

+	        switch(sock_rpmsg.msg_type) {

+				case MSG_TYPE_FIND:

+					sock_soc_find_other_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_FIND_RESULT:

+					sock_soc_find_other_result_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_ADD_WAIT_QUEUE:

+					sock_soc_add_wait_queue_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_REMOVE_WAIT_QUEUE:

+					sock_soc_remove_wait_queue_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_SYNC_IPC_SOCKET:

+					sock_sync_ipc_socket_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_WAIT_FOR_PEER:

+					sock_wait_for_peer_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_DATA_READY:

+					sock_soc_sk_data_ready_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_SEND_MSG:

+					sock_soc_msg_send_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_ADD_SKB_QUEUE_TAIL:

+					sock_soc_add_skb_queue_tail_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_SET_PEER:

+					sock_soc_set_peer_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_RECVQ_FULL:

+					sock_soc_recvq_full_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_RECVQ_FULL_RESULT:

+					sock_soc_recvq_full_result_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_PEER_CLEAR:

+					sock_soc_unix_peer_clear_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_WAKE_UP_INTERRUPTIBLE_POLL:

+					sock_soc_wake_up_interruptible_poll_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_RECVQ_FULL_LOCKLESS_AND_DEAD:

+					sock_soc_recvq_full_lockless_and_dead_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_RECVQ_FULL_LOCKLESS_AND_DEAD_RESULT:

+					sock_soc_recvq_full_lockless_and_dead_result_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_TEST_FLAG:

+					sock_soc_test_flags_proc(&sock_rpmsg);					

+					break;

+				case MSG_TYPE_TEST_FLAG_RESULT:

+					sock_soc_test_flags_result_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_SOCK_PUT:

+					sock_soc_sock_put_proc(&sock_rpmsg);

+					break;					

+				case MSG_TYPE_GET_SOCKET_STATES:

+					sock_soc_get_state_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_GET_SOCKET_STATES_RESULT:

+					sock_soc_get_state_result_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_STREAM_CONNECT:

+					sock_soc_stream_connect_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_UPDATE_PEER:

+					sock_soc_update_peer_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_SOCKET_RELEASE:

+					sock_soc_release_sock_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_DGRAM_DISCONNECTED:

+					sock_soc_dgram_disconnected_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_STATE_LOCK:

+					sock_soc_state_lock_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_STATE_UNLOCK:

+					sock_soc_state_unlock_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_SOCK_HOLD:

+					sock_soc_sock_hold_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_RELEASE_PEER:

+					sock_soc_release_peer_proc(&sock_rpmsg);

+					break;

+				case MSG_TYPE_NOTIFY_PROXY_CHANGE:

+					sock_soc_notify_proxy_change_to_server_proc(&sock_rpmsg);

+					break;

+				default:

+				    break;

+			}

+#endif			

+	    }

+	    else {

+	        sk_soc_err("sock_channel_read fail.");

+	        msleep(1000);

+			continue;

+	    } 

+		

+	}      

+

+    sk_soc_err("The receive thread exit!");

+    return 0;

+}

+

+static int sock_main_thread(void *argv)

+{ 	

+	struct list_head	tmp_list;

+	struct sock_rpmsg *entry,*tmp_entry;

+	unsigned long flags;

+	struct sock_thread_info* p_main_thread_info;

+	p_main_thread_info = &g_sock_chn_info.main_thread_info;

+	

+	while(!p_main_thread_info->bstop) {

+		sock_get_sema(&p_main_thread_info->p_sock_sem);

+

+		spin_lock_irqsave(&p_main_thread_info->p_sock_lock,flags);	

+		if (list_empty(&p_main_thread_info->p_sock_list)) {

+			spin_unlock_irqrestore(&p_main_thread_info->p_sock_lock,flags);

+			continue;

+		}

+		list_replace_init(&p_main_thread_info->p_sock_list,&tmp_list);

+		list_del_init(&p_main_thread_info->p_sock_list);		

+		spin_unlock_irqrestore(&p_main_thread_info->p_sock_lock,flags);

+

+		list_for_each_entry_safe(entry,tmp_entry,&tmp_list,list) {

+			if(DIR_DOWNLINK == entry->dir) {				

+				sock_dld_handle(entry);

+			}

+			else if(DIR_UPLINK == entry->dir) {

+				sock_uld_handle(entry);				

+			}

+			else {

+				sk_soc_warn("sock data unknow dir(%d).",entry->dir);

+			}

+			list_del(&entry->list);

+			kfree(entry);

+		}

+	}

+

+	sk_soc_err("the sock_main_thread stop!\n");    

+    return 0;

+}

+

+static int __init sock_soc_init(void)

+{

+	struct task_struct *th = NULL;

+	int retval = 0;

+	struct sock_thread_info* p_main_thread_info;

+	

+	sema_init(&g_sock_sem, 0);

+	g_sock_chn_info.core_id = CAP_ID;

+	g_sock_chn_info.channel_id = ICP_CHN_SOCKET;

+	g_sock_chn_info.channel_size = ICP_CHANNEL_SIZE;

+	

+	sk_soc_info("sock_soc_init process");

+	INIT_HLIST_HEAD(&g_ipc_sockets);

+	INIT_HLIST_HEAD(&g_sock_rpmsg_info);

+	INIT_HLIST_HEAD(&g_sockets_info);

+	retval = sock_create_icp_channel(CAP_ID, ICP_CHN_SOCKET, ICP_CHANNEL_SIZE);

+	if(retval < 0) {

+		sk_soc_err("Create IcpChannel channel_32 fail.");

+		return retval;

+	}

+	

+	p_main_thread_info = &g_sock_chn_info.main_thread_info;

+	

+	INIT_LIST_HEAD(&p_main_thread_info->p_sock_list);

+	spin_lock_init(&p_main_thread_info->p_sock_lock);

+	sema_init(&p_main_thread_info->p_sock_sem, 0);

+	

+	th = kthread_run(sock_main_thread, 0, "sock-soc-main%d", ICP_CHN_SOCKET);

+	if (IS_ERR(th)) {

+		sk_soc_err("Unable to start receive thread.");

+		return PTR_ERR(th);

+	}

+	g_sock_chn_info.main_thread_info.p_thread = th;

+

+	th = kthread_run(sock_receive_thread, 0, "sock-soc-recv%d", ICP_CHN_SOCKET);

+	if (IS_ERR(th)) {

+		sk_soc_err("Unable to start receive thread.");

+		return PTR_ERR(th);

+	}

+	g_sock_chn_info.recv_thread_info.p_thread = th;

+	

+	return 0;

+}

+

+static void __exit sock_soc_exit(void)

+{

+    memset(&g_sock_chn_info, 0, sizeof(struct sock_channel));

+    sk_soc_warn("success.\n");

+}

+

+late_initcall(sock_soc_init);

+module_exit(sock_soc_exit);

+

+MODULE_AUTHOR("ZXIC");

+MODULE_DESCRIPTION("ZXIC CAP LAN NET DEVICE");

+MODULE_LICENSE("GPL");

+

diff --git a/ap/os/linux/linux-3.4.x/net/unix/af_unix.c b/ap/os/linux/linux-3.4.x/net/unix/af_unix.c
index 2ff802c..013b685 100755
--- a/ap/os/linux/linux-3.4.x/net/unix/af_unix.c
+++ b/ap/os/linux/linux-3.4.x/net/unix/af_unix.c
@@ -115,6 +115,11 @@
 #include <net/checksum.h>
 #include <linux/security.h>
 
+#ifdef CONFIG_IPC_SOCKET
+#include <linux/socket_rpmsg.h>
+int socket_rpmsg_debug = 0;
+module_param(socket_rpmsg_debug, int, 0644);
+#endif
 struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1];
 EXPORT_SYMBOL_GPL(unix_socket_table);
 DEFINE_SPINLOCK(unix_table_lock);
@@ -171,6 +176,12 @@
 
 static inline int unix_recvq_full(struct sock const *sk)
 {
+#ifdef CONFIG_IPC_SOCKET
+	if(unix_is_ipc_socket(sk)){
+		return sock_soc_recvq_full(sk);
+	} 
+#endif
+
 	return skb_queue_len(&sk->sk_receive_queue) > sk->sk_max_ack_backlog;
 }
 
@@ -345,6 +356,11 @@
 			other->sk_error_report(other);
 		}
 	}
+#ifdef CONFIG_IPC_SOCKET
+	if(unix_is_ipc_socket(other)){ //Èç¹ûotherÊÇ´úÀísocket£¬Ôò֪ͨÆä¶ÔÓ¦µÄʵÌåÖ´ÐÐÏàͬ²Ù×÷
+		sock_soc_dgram_disconnected(sk, other);
+	}			
+#endif
 }
 
 static void unix_sock_destructor(struct sock *sk)
@@ -695,7 +711,14 @@
 
 	if (!sk)
 		return 0;
-
+#ifdef CONFIG_IPC_SOCKET //ÊͷŸÃsocket¶ÔÓ¦µÄ´úÀí
+	if(!hlist_empty(&sock->peer)){
+		
+		sock_soc_delay_release(sock);		
+	}else{
+		sk_soc_info("sock->peer is null \n");
+	}	
+#endif
 	unix_release_sock(sk, 0);
 	sock->sk = NULL;
 
@@ -986,9 +1009,16 @@
 
 restart:
 		other = unix_find_other(net, sunaddr, alen, sock->type, hash, &err);
-		if (!other)
-			goto out;
-
+		if (!other) {
+#ifdef CONFIG_IPC_SOCKET			
+			sk_soc_dbg("unix_dgram_connect sock_soc_find_other");
+			/*±¾µØ²éÕÒ²»µ½£¬Ôò½øÐпçºË²éÕÒ*/
+			other = sock_soc_find_other(sock, sunaddr, alen, sock->type, hash, &err);
+				
+			if (!other)
+#endif				
+				goto out;
+		}
 		unix_state_double_lock(sk, other);
 
 		/* Apparently VFS overslept socket death. Retry. */
@@ -1027,6 +1057,12 @@
 		sock_put(old_peer);
 	} else {
 		unix_peer(sk) = other;
+#ifdef CONFIG_IPC_SOCKET
+		if(unix_is_ipc_socket(other)){ //Èç¹ûotherÊÇ´úÀísocket£¬Ôò֪ͨÆä¶ÔÓ¦µÄʵÌåÖ´ÐÐÏàͬ²Ù×÷
+			sk_soc_dbg("unix_dgram_connect sock_soc_set_peer");
+			sock_soc_set_peer(sk, other);
+		}
+#endif
 		unix_state_double_unlock(sk, other);
 	}
 	return 0;
@@ -1105,8 +1141,16 @@
 restart:
 	/*  Find listening sock. */
 	other = unix_find_other(net, sunaddr, addr_len, sk->sk_type, hash, &err);
-	if (!other)
-		goto out;
+	if (!other){
+#ifdef CONFIG_IPC_SOCKET
+		sk_soc_dbg("unix_stream_connect sock_soc_find_other");
+		/*±¾µØ²éÕÒ²»µ½£¬Ôò½øÐпçºË²éÕÒ*/
+		other = sock_soc_find_other(sock, sunaddr, addr_len, sock->type, hash, &err);
+			
+		if (!other)
+#endif				
+			goto out;
+	}
 
 	/* Latch state of peer */
 	unix_state_lock(other);
@@ -1119,6 +1163,16 @@
 	}
 
 	err = -ECONNREFUSED;
+#ifdef CONFIG_IPC_SOCKET
+	if(unix_is_ipc_socket(other)){
+		struct sock_elem_flag elem_flag = {0};
+		elem_flag.skstate = 1;
+		elem_flag.skshutdown = 1;
+		sock_soc_get_state(&elem_flag, other);
+	}
+	sk_soc_dbg("unix_stream_connect other->sk_state=%d, other->sk_shutdown=%d", other->sk_state, other->sk_shutdown);	
+#endif	
+	
 	if (other->sk_state != TCP_LISTEN)
 		goto out_unlock;
 	if (other->sk_shutdown & RCV_SHUTDOWN)
@@ -1129,6 +1183,11 @@
 		if (!timeo)
 			goto out_unlock;
 
+#ifdef CONFIG_IPC_SOCKET
+		if(unix_is_ipc_socket(other)){ //Èç¹ûotherÊÇ´úÀísocket£¬Ôò֪ͨÆä¶ÔÓ¦µÄʵÌåÖ´ÐÐÏàͬ²Ù×÷
+			sock_wait_for_peer(sk, other, timeo);
+		}
+#endif
 		timeo = unix_wait_for_peer(other, timeo);
 
 		err = sock_intr_errno(timeo);
@@ -1214,10 +1273,36 @@
 
 	/* take ten and and send info to listening sock */
 	spin_lock(&other->sk_receive_queue.lock);
+#ifdef CONFIG_IPC_SOCKET
+	if(unix_is_ipc_socket(other)){
+		set_bit(SOCK_IPC_LOCAL,&newsk->sk_flags);
+		newsk->proxy_sock = other;
+		other->proxy_sock = newsk; 
+		sock_soc_stream_connect(sk, other, uaddr, addr_len, flags);
+		//ÊÍ·Åskb
+		kfree_skb(skb);
+	}
+	else{
+#endif
 	__skb_queue_tail(&other->sk_receive_queue, skb);
+
+#ifdef CONFIG_IPC_SOCKET
+	}
+#endif	
 	spin_unlock(&other->sk_receive_queue.lock);
+#ifdef CONFIG_IPC_SOCKET
+	unix_state_unlock(other);
+
+	if(unix_is_ipc_socket(other)){
+		sock_soc_sk_data_ready(other);		
+	}
+	else{
+#endif
 	unix_state_unlock(other);
 	other->sk_data_ready(other, 0);
+#ifdef CONFIG_IPC_SOCKET
+	}
+#endif
 	sock_put(other);
 	return 0;
 
@@ -1300,6 +1385,9 @@
 	newsock->state = SS_CONNECTED;
 	unix_sock_inherit_flags(sock, newsock);
 	sock_graft(tsk, newsock);
+#ifdef CONFIG_IPC_SOCKET	
+	sock_soc_update_peer(sock, newsock);
+#endif
 	unix_state_unlock(tsk);
 	return 0;
 
@@ -1503,10 +1591,12 @@
 	unix_get_secdata(siocb->scm, skb);
 
 	skb_reset_transport_header(skb);
+#ifndef CONFIG_IPC_SOCKET	
 	err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
 	if (err)
 		goto out_free;
 
+#endif	
 	timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
 
 restart:
@@ -1517,10 +1607,31 @@
 
 		other = unix_find_other(net, sunaddr, namelen, sk->sk_type,
 					hash, &err);
-		if (other == NULL)
-			goto out_free;
+		if (other == NULL) {
+#ifdef CONFIG_IPC_SOCKET
+			sk_soc_dbg("unix_find_other fail, call sock_soc_find_other");
+			/*±¾µØ²éÕÒ²»µ½£¬Ôò½øÐпçºË²éÕÒ*/
+			other = sock_soc_find_other(sock, sunaddr, namelen, sk->sk_type, hash, &err);
+				
+			if (other == NULL)
+#endif				
+				goto out_free;
+		}
+		
 	}
 
+#ifdef CONFIG_IPC_SOCKET
+	if(unix_is_ipc_socket(other)){ //Èç¹û¿çºËsocket£¬ÔòÖ±½Ó½«Êý¾Ý·¢Ë͸ø¿çºËsocket´¦Àí
+		printk("other is ipc socket, do nothing\n");
+	}
+	else{ 
+		err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
+		if (err)
+			goto out_free;
+		
+	}
+#endif
+
 	if (sk_filter(other, skb) < 0) {
 		/* Toss the packet but do not return any error to the sender */
 		err = len;
@@ -1584,6 +1695,16 @@
 		goto restart;
 	}
 
+#ifdef CONFIG_IPC_SOCKET
+	if(unix_is_ipc_socket(other)){ //Èç¹û¿çºËsocket£¬ÔòÖ±½Ó½«Êý¾Ý·¢Ë͸ø¿çºËsocket´¦Àí
+		sk_soc_dbg("send to other core, len=%d", len);
+		sock_soc_msg_send(sk, other, msg, len);
+		unix_state_unlock(other);
+		sock_put(other);
+		kfree_skb(skb);
+	}
+	else{ //·Ç¿çºË×ßÕý³£Á÷³Ì
+#endif
 	if (sock_flag(other, SOCK_RCVTSTAMP))
 		__net_timestamp(skb);
 	maybe_add_creds(skb, sock, other);
@@ -1593,6 +1714,9 @@
 	unix_state_unlock(other);
 	other->sk_data_ready(other, len);
 	sock_put(other);
+#ifdef CONFIG_IPC_SOCKET
+	}
+#endif	
 	scm_destroy(siocb->scm);
 	return len;
 
@@ -1620,13 +1744,25 @@
 	struct scm_cookie tmp_scm;
 	bool fds_sent = false;
 	int max_level;
-
+#ifdef CONFIG_IPC_SOCKET
+	char* data;
+	char* data_buf;
+#endif
+	
+	
 	if (NULL == siocb->scm)
 		siocb->scm = &tmp_scm;
 	wait_for_unix_gc();
 	err = scm_send(sock, msg, siocb->scm, false);
 	if (err < 0)
 		return err;
+#ifdef CONFIG_IPC_SOCKET
+		if(unix_is_ipc_socket(sk)){ //Èç¹û´Ë´¦µÄsockÊÇ´úÀísocket£¬Ôò½«skÌæ»»Îªconnectʱ·ÖÅäµÄnewsk
+			if(sk->proxy_sock){
+				sk = sk->proxy_sock;
+			}
+		}
+#endif
 
 	err = -EOPNOTSUPP;
 	if (msg->msg_flags&MSG_OOB)
@@ -1688,8 +1824,16 @@
 		}
 		max_level = err + 1;
 		fds_sent = true;
-
+#ifdef CONFIG_IPC_SOCKET
+		if(unix_is_ipc_socket(other) || unix_is_ipc_local_socket(other)){
+			//do nothing
+		} else {
+#endif
+	
 		err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
+#ifdef CONFIG_IPC_SOCKET
+		}
+#endif
 		if (err) {
 			kfree_skb(skb);
 			goto out_err;
@@ -1701,6 +1845,25 @@
 		    (other->sk_shutdown & RCV_SHUTDOWN))
 			goto pipe_err_free;
 
+#ifdef CONFIG_IPC_SOCKET
+		if(unix_is_ipc_socket(other)){ //Èç¹û¿çºËsocket£¬ÔòÖ±½Ó½«Êý¾Ý·¢Ë͸ø¿çºËsocket´¦Àí
+			sk_soc_dbg("sock_soc_msg_send");
+			unix_state_unlock(other);
+
+			sock_soc_msg_send(sk, other, msg, size);
+		    sent += size;
+			kfree_skb(skb);
+		}
+		else if(unix_is_ipc_local_socket(other)){
+			sk_soc_dbg("sock_soc_msg_send to proxy_sock");
+			unix_state_unlock(other);
+	
+			sock_soc_msg_send(sk, other->proxy_sock, msg, size);
+		    sent += size;
+			kfree_skb(skb);
+		}
+		else{ //·Ç¿çºË×ßÕý³£Á÷³Ì
+#endif		
 		maybe_add_creds(skb, sock, other);
 		skb_queue_tail(&other->sk_receive_queue, skb);
 		if (max_level > unix_sk(other)->recursion_level)
@@ -1708,6 +1871,9 @@
 		unix_state_unlock(other);
 		other->sk_data_ready(other, size);
 		sent += size;
+#ifdef CONFIG_IPC_SOCKET
+		}
+#endif		
 	}
 
 	scm_destroy(siocb->scm);
@@ -2386,6 +2552,73 @@
 
 #endif
 
+#ifdef CONFIG_IPC_SOCKET
+struct sock *unix_find_other_proxy(struct net *net,
+				    struct sockaddr_un *sunname, int len,
+				    int type, unsigned int hash, int *error)
+{
+	return unix_find_other(net, sunname, len, type, hash, error);
+}
+
+int unix_dgram_peer_wake_connect_proxy(struct sock *sk, struct sock *other)
+{
+	//return unix_dgram_peer_wake_connect(sk, other);
+	return 0;
+}
+
+void unix_dgram_peer_wake_disconnect_proxy(struct sock *sk, struct sock *other)
+{
+	//unix_dgram_peer_wake_disconnect(sk, other);
+}
+
+void unix_dgram_peer_wake_disconnect_wakeup_proxy(struct sock *sk,
+						   struct sock *other)
+{
+	//unix_dgram_peer_wake_disconnect(sk, other);
+	wake_up_interruptible_poll(sk_sleep(sk),
+				   POLLOUT |
+				   POLLWRNORM |
+				   POLLWRBAND);
+}
+
+long unix_wait_for_peer_proxy(struct sock *other, long timeo)
+{
+	return unix_wait_for_peer(other, timeo);
+}
+
+int unix_recvq_full_proxy(const struct sock *sk)
+{
+	return unix_recvq_full(sk);
+}
+
+int unix_recvq_full_proxy_lockless_and_deadstate(const struct sock *other)
+{
+	//return unix_recvq_full_lockless(other) && !sock_flag(other, SOCK_DEAD);
+	return 0;
+}
+
+int unix_stream_connect_proxy(struct socket *sock, struct sockaddr *uaddr,
+			       int addr_len, int flags)
+{
+	return unix_stream_connect(sock, uaddr, addr_len, flags);
+}
+
+void unix_dgram_disconnected_proxy(struct sock *sk, struct sock *other)
+{
+   unix_dgram_disconnected(sk, other);
+}
+
+int unix_mkname_proxy(struct sockaddr_un *sunaddr, int len, unsigned *hashp){
+	return unix_mkname(sunaddr, len, hashp);
+}
+
+void unix_release_sock_proxy(struct sock *sk)
+{
+	unix_release_sock(sk, 0);
+}
+
+#endif
+
 static const struct net_proto_family unix_family_ops = {
 	.family = PF_UNIX,
 	.create = unix_create,
diff --git a/ap/os/linux/linux-3.4.x/net/xfrm/xfrm_user.c b/ap/os/linux/linux-3.4.x/net/xfrm/xfrm_user.c
index ccf0f6e..0889855 100755
--- a/ap/os/linux/linux-3.4.x/net/xfrm/xfrm_user.c
+++ b/ap/os/linux/linux-3.4.x/net/xfrm/xfrm_user.c
@@ -858,7 +858,7 @@
 static int xfrm_dump_sa_done(struct netlink_callback *cb)
 {
 	struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1];
-	if(walk)
+	if(cb->args[1])
 	xfrm_state_walk_done(walk);
 	return 0;
 }
@@ -869,7 +869,7 @@
 	struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1];
 	struct xfrm_dump_info info;
 
-	if(walk == NULL)
+	if(cb->args[1] == 0)
 		return 0;
 	BUILD_BUG_ON(sizeof(struct xfrm_state_walk) >
 		     sizeof(cb->args) - sizeof(cb->args[0]));
@@ -1538,7 +1538,7 @@
 static int xfrm_dump_policy_done(struct netlink_callback *cb)
 {
 	struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];
-	if(walk)
+	if(cb->args[1])
 	xfrm_policy_walk_done(walk);
 	return 0;
 }
@@ -1549,7 +1549,7 @@
 	struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];
 	struct xfrm_dump_info info;
 
-	if(walk == NULL)
+	if(cb->args[1] == 0)
 		return 0;
 	BUILD_BUG_ON(sizeof(struct xfrm_policy_walk) >
 		     sizeof(cb->args) - sizeof(cb->args[0]));
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/sanechips/zx297520v3_dummy.c b/ap/os/linux/linux-3.4.x/sound/soc/sanechips/zx297520v3_dummy.c
index 0124154..5c0257c 100755
--- a/ap/os/linux/linux-3.4.x/sound/soc/sanechips/zx297520v3_dummy.c
+++ b/ap/os/linux/linux-3.4.x/sound/soc/sanechips/zx297520v3_dummy.c
@@ -425,6 +425,24 @@
 {
 	unsigned int i2s_top_reg;
 	int ret = 0;
+	
+
+	
+#ifdef _ALSA_CODEC_IN_CAP
+	print_audio("Alsa mc zx29_i2s_top_reg_cfg: ZX29_I2S_LOOP_CFG=0x%x \n",ZX29_I2S_LOOP_CFG);
+
+	// inter loop
+	i2s_top_reg = zx_read_reg(ZX29_I2S_LOOP_CFG);
+	i2s_top_reg &= 0xfffffe07;
+	i2s_top_reg |= 0x000000a8; //  inter arm_i2s2--afe i2s
+	zx_write_reg(ZX29_I2S_LOOP_CFG, i2s_top_reg);
+
+	print_audio("Alsa %s i2s loop cfg reg=%x\n",__func__, zx_read_reg(ZX29_I2S_LOOP_CFG));	
+	print_audio("Alsa mc %s: defined _ALSA_CODEC_IN_CAP,i2s top cfg return\n", __func__);
+
+    return;
+
+#endif
 
 #ifdef CONFIG_USE_PIN_I2S0
 	ret = gpio_request(PIN_I2S0_WS, "i2s0_ws");
@@ -474,12 +492,7 @@
 	zx_write_reg(ZX29_I2S_LOOP_CFG, i2s_top_reg);
 #endif
 
-	// inter loop
-    i2s_top_reg = zx_read_reg(ZX29_I2S_LOOP_CFG);
-    i2s_top_reg &= 0xfffffe07;
-    i2s_top_reg |= 0x000000a8; //  inter arm_i2s2--afe i2s
-    zx_write_reg(ZX29_I2S_LOOP_CFG, i2s_top_reg);
-	
+
 //	print_audio("Alsa %s i2s loop cfg reg=%x\n",__func__, zx_read_reg(ZX29_I2S_LOOP_CFG));	
 }
 
@@ -585,9 +598,8 @@
 
 	print_audio("Alsa zx297520v3_dummy SoC Audio driver\n");
 
-#ifndef	_ALSA_CODEC_IN_CAP
 	zx29_i2s_top_reg_cfg();
-#endif
+	
 	zx297520v3_dummy_snd_device = platform_device_alloc("soc-audio", -1);
 	if (!zx297520v3_dummy_snd_device) {
 		printk(KERN_ERR "Alsa zx297520v3_dummy SoC Audio: Unable to register\n");