--- zzzz-none-000/linux-2.6.28.10/net/atm/pppoatm.c 2009-05-02 18:54:43.000000000 +0000 +++ puma5-6360-529/linux-2.6.28.10/net/atm/pppoatm.c 2010-10-01 08:25:34.000000000 +0000 @@ -46,6 +46,15 @@ #include "common.h" + +#if defined(CONFIG_MACH_FUSIV) +#define LLC_PPPOA_OVERHEAD 6 +#define VC_PPPOA_OVERHEAD 2 +extern int (*AtmUpdateNewVCInfo_ptr)(int encap, struct atm_vcc *atmvcc, int moduleId, char *ifname); +extern int (*AtmDeleteVCInfo_ptr)(short vpi,int vci); +extern int get_PPPOAOverhead(struct ppp_channel *ppp_chan); +#endif + enum pppoatm_encaps { e_autodetect = PPPOATM_ENCAPS_AUTODETECT, e_vc = PPPOATM_ENCAPS_VC, @@ -118,6 +127,11 @@ { struct pppoatm_vcc *pvcc; pvcc = atmvcc_to_pvcc(atmvcc); + +#if defined(CONFIG_MACH_FUSIV) + (*AtmDeleteVCInfo_ptr)(atmvcc->vpi,atmvcc->vci); +#endif + atmvcc->push = pvcc->old_push; atmvcc->pop = pvcc->old_pop; tasklet_kill(&pvcc->wakeup_tasklet); @@ -142,10 +156,12 @@ atm_return(atmvcc, skb->truesize); switch (pvcc->encaps) { case e_llc: +#if !defined(CONFIG_MACH_FUSIV) if (skb->len < LLC_LEN || memcmp(skb->data, pppllc, LLC_LEN)) goto error; skb_pull(skb, LLC_LEN); +#endif break; case e_autodetect: if (pvcc->chan.ppp == NULL) { /* Not bound yet! */ @@ -199,6 +215,7 @@ (void) skb_pull(skb, 1); switch (pvcc->encaps) { /* LLC encapsulation needed */ case e_llc: +#if !defined(CONFIG_MACH_FUSIV) if (skb_headroom(skb) < LLC_LEN) { struct sk_buff *n; n = skb_realloc_headroom(skb, LLC_LEN); @@ -213,6 +230,7 @@ } else if (!atm_may_send(pvcc->atmvcc, skb->truesize)) goto nospace; memcpy(skb_push(skb, LLC_LEN), pppllc, LLC_LEN); +#endif /*--- #if !defined(CONFIG_MACH_FUSIV) ---*/ break; case e_vc: if (!atm_may_send(pvcc->atmvcc, skb->truesize)) @@ -224,7 +242,9 @@ return 1; } +#if !defined(CONFIG_MACH_FUSIV) atomic_add(skb->truesize, &sk_atm(ATM_SKB(skb)->vcc)->sk_wmem_alloc); +#endif ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options; pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, ATM_SKB(skb)->vcc, ATM_SKB(skb)->vcc->dev); @@ -256,11 +276,23 @@ return -ENOTTY; } +int getInfaceUnit(void* atmVCC) +{ + int unit = -1; + struct atm_vcc *atmvcc = (struct atm_vcc *)atmVCC; + struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc); + unit = ppp_unit_number(&(pvcc->chan)); + return unit; +} + static /*const*/ struct ppp_channel_ops pppoatm_ops = { .start_xmit = pppoatm_send, .ioctl = pppoatm_devppp_ioctl, }; +#if defined(CONFIG_IFX_PPA_A6) || defined(CONFIG_IFX_PPA_A5) || defined(CONFIG_IFX_PPA_A4) + extern void (*ppa_hook_mpoa_setup)(struct atm_vcc *, int, int); +#endif static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg) { struct atm_backend_ppp be; @@ -297,6 +329,14 @@ atmvcc->push = pppoatm_push; atmvcc->pop = pppoatm_pop; __module_get(THIS_MODULE); +#if defined(CONFIG_IFX_PPA_A6) || defined(CONFIG_IFX_PPA_A5) || defined(CONFIG_IFX_PPA_A4) + if ( ppa_hook_mpoa_setup ) + ppa_hook_mpoa_setup(atmvcc, 2, pvcc->encaps == e_llc ? 1 : 0); // PPPoA +#endif +#if defined(CONFIG_MACH_FUSIV) + (*AtmUpdateNewVCInfo_ptr)(be.encaps, atmvcc, ADI_PPPOA_MODULE, "ppp0"); +#endif + return 0; } @@ -323,6 +363,22 @@ return -EPERM; return pppoatm_assign_vcc(atmvcc, argp); } +#if defined(CONFIG_MACH_FUSIV) + case ATM_DEL_INTERFACE: + { + atm_backend_t b; + if (get_user(b, (atm_backend_t *) arg)) + return -EFAULT; + if (b != ATM_BACKEND_PPP) + return -ENOIOCTLCMD; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + pppoatm_unassign_vcc(atmvcc); + + } + + return 0; +#endif case PPPIOCGCHAN: return put_user(ppp_channel_index(&atmvcc_to_pvcc(atmvcc)-> chan), (int __user *) argp) ? -EFAULT : 0; @@ -333,6 +389,31 @@ return -ENOIOCTLCMD; } +int isPPPModTypePPPoA(struct ppp_channel *pppchan) +{ + if ((pppchan->ops) && + (pppchan->ops->start_xmit) && + (pppchan->ops->start_xmit == pppoatm_send)) + return 1; + + return 0; +} + +#if defined(CONFIG_MACH_FUSIV) +int get_PPPOAOverhead(struct ppp_channel *pppchan) +{ + struct pppoatm_vcc *pvcc = chan_to_pvcc(pppchan); + if (pvcc->encaps == e_llc) + { + return LLC_PPPOA_OVERHEAD; + } + else + { + return VC_PPPOA_OVERHEAD; + } +} +#endif + static struct atm_ioctl pppoatm_ioctl_ops = { .owner = THIS_MODULE, .ioctl = pppoatm_ioctl, @@ -349,9 +430,64 @@ deregister_atm_ioctl(&pppoatm_ioctl_ops); } + module_init(pppoatm_init); module_exit(pppoatm_exit); +#if defined(CONFIG_IFX_PPA_API) || defined(CONFIG_IFX_PPA_API_MODULE) +extern int32_t ppa_ppp_get_chan(struct net_device *netif, struct ppp_channel **chan); + +int32_t ppa_pppoa_get_vcc(struct net_device *netif, struct atm_vcc **patmvcc) +{ + struct ppp_channel *chan; + struct pppoatm_vcc *pvcc; + + if ( ppa_ppp_get_chan(netif, &chan) >= 0 ) + { + pvcc = (struct pppoatm_vcc *)chan->private; + if ( (unsigned int)pvcc >= KSEG0 && &pvcc->chan == chan && pvcc->atmvcc ) + { + *patmvcc = pvcc->atmvcc; + return 0; + } + } + + return -1; +} + +int32_t ppa_if_is_pppoa(struct net_device *netif, char *ifname) +{ + struct ppp_channel *chan; + struct pppoatm_vcc *pvcc; + + if ( !netif ) + { + netif = dev_get_by_name(ifname); + if ( netif ) + dev_put(netif); + else + return 0; // can not get + } + + if ( ppa_ppp_get_chan(netif, &chan) >= 0 ) + { + pvcc = (struct pppoatm_vcc *)chan->private; + return (unsigned int)pvcc >= KSEG0 && &pvcc->chan == chan ? 1 : 0; + } + + return 0; +} + +EXPORT_SYMBOL(ppa_pppoa_get_vcc); +EXPORT_SYMBOL(ppa_if_is_pppoa); +#endif + +EXPORT_SYMBOL(isPPPModTypePPPoA); +EXPORT_SYMBOL(getInfaceUnit); +#if defined(CONFIG_MACH_FUSIV) +EXPORT_SYMBOL(get_PPPOAOverhead); +#endif + MODULE_AUTHOR("Mitchell Blank Jr "); MODULE_DESCRIPTION("RFC2364 PPP over ATM/AAL5"); MODULE_LICENSE("GPL");