--- zzzz-none-000/linux-2.6.28.10/net/atm/br2684.c 2009-05-02 18:54:43.000000000 +0000 +++ puma5-6360-529/linux-2.6.28.10/net/atm/br2684.c 2010-10-01 08:25:34.000000000 +0000 @@ -26,6 +26,43 @@ #include "common.h" +/*------------------------------------------------------------------------------------------*\ +\*------------------------------------------------------------------------------------------*/ + + +#if defined(CONFIG_MACH_FUSIV) +static unsigned char atmMacAddr[6] = {0x0,0x0,0x1,0x0,0x0,0x0}; +// =========================================================================== +// Function name: ATM_getPermanentMacAddress +// Input Parameters: none +// Output Parameters: mac address +// Result: none +// Description: Returns the mac address to be used for all ATM based +// logical interfaces. +// =========================================================================== +void ATM_getPermanentMacAddress_local(unsigned char *macAddr) +{ + memcpy(macAddr, atmMacAddr, 6); +} +//extern int AtmUpdateNewVCInfo(int encap, struct atm_vcc *atmvcc, int moduleId,char *ifname); +int (*AtmUpdateNewVCInfo_ptr)(int encap, struct atm_vcc *atmvcc, int moduleId, char *ifname) = NULL; +int (*AtmUpdateVCInfo_ptr)(void *atmqos) = NULL; +//extern int AtmDeleteVCInfo(short vpi,int vci); +int (*AtmDeleteVCInfo_ptr)(short vpi,int vci) =NULL; +//extern void ATM_getPermanentMacAddress(unsigned char *macAddr); +#define ADI_BR2684_MODULE 2 +struct atm_vcc * adi_getvcc(char *ifname); +#define LLC_BRIDGED_OVERHEAD 10 +#define VC_BRIDGED_OVERHEAD 2 +#define LLC_ROUTED_OVERHEAD 8 +#define VC_ROUTED_OVERHEAD 0 +#endif + +#if defined(CONFIG_FUSIV_KERNEL_AP_2_AP) || defined(CONFIG_FUSIV_KERNEL_AP_2_AP_MODULE) +int (*br2684AddMacAddrToAP_ptr)(unsigned char* dev_addr) = NULL; +int (*br2684DelMacAddrFromAP_ptr)(unsigned char* dev_addr) = NULL; +#endif + #ifdef SKB_DEBUG static void skb_debug(const struct sk_buff *skb) { @@ -41,6 +78,12 @@ #define skb_debug(skb) do {} while (0) #endif + +#if defined(CONFIG_FUSIV_KERNEL_PPPOE_RELAY) || defined(CONFIG_FUSIV_KERNEL_PPPOE_RELAY_MODULE) +int (*getConfigModuleId_ptr)(int vpi,int vci) = NULL; +int (*checkPPPOERelayStatus_ptr)(char *name) = NULL; +#endif + #define BR2684_ETHERTYPE_LEN 2 #define BR2684_PAD_LEN 2 @@ -78,6 +121,7 @@ unsigned copies_needed, copies_failed; }; +static void br2684_close_vcc(struct br2684_vcc *brvcc); struct br2684_dev { struct net_device *net_dev; struct list_head br2684_devs; @@ -209,7 +253,9 @@ dev_kfree_skb(skb); return 0; } - atomic_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc); +#if !defined(CONFIG_MACH_FUSIV) + atomic_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc); +#endif ATM_SKB(skb)->atm_options = atmvcc->atm_options; brdev->stats.tx_packets++; brdev->stats.tx_bytes += skb->len; @@ -261,6 +307,83 @@ return &BRPRIV(dev)->stats; } +#if defined(CONFIG_MACH_FUSIV) +static int br2684_delete(struct atm_vcc *atmvcc, void __user *arg) +{ + int modId __attribute__((unused)); + struct br2684_vcc *brvcc; + struct br2684_dev *brdev; + struct net_device *net_dev; + struct atm_backend_br2684 be; + + if (copy_from_user(&be, arg, sizeof be)) { + return -EFAULT; + } + + atmvcc = adi_getvcc (be.ifspec.spec.ifname); + + if (!atmvcc) + { + printk(" ATM VCC not configured \n"); + return -EFAULT; + } +#if defined(CONFIG_FUSIV_KERNEL_PPPOE_RELAY) || defined(CONFIG_FUSIV_KERNEL_PPPOE_RELAY_MODULE) + if(getConfigModuleId_ptr == NULL || checkPPPOERelayStatus_ptr == NULL) + { + printk("\nbr2684: pppoerelay module not get initialized properly...\n"); + return -1; + } + if ( (modId = (*getConfigModuleId_ptr)(atmvcc->vpi,atmvcc->vci)) != -1) + { + if ( modId == 5) + { + if( ((*checkPPPOERelayStatus_ptr)(be.ifspec.spec.ifname)) ) + { + printk("Device %s is Busy.Disable PPPOE Relay and Delete %s interface from Relay\n",be.ifspec.spec.ifname,be.ifspec.spec.ifname); + return -EFAULT; + } + } + } +#endif + + brvcc = BR2684_VCC(atmvcc); + net_dev = brvcc->device; + brdev = BRPRIV(net_dev); + + br2684_close_vcc(brvcc); + if (list_empty(&brdev->brvccs)) + { + read_lock(&devs_lock); + list_del(&brdev->br2684_devs); + read_unlock(&devs_lock); +#if defined(CONFIG_MACH_FUSIV) +#if defined(CONFIG_FUSIV_KERNEL_AP_2_AP) || defined(CONFIG_FUSIV_KERNEL_AP_2_AP_MODULE) + if (br2684DelMacAddrFromAP_ptr) + { + br2684DelMacAddrFromAP_ptr(net_dev->dev_addr); + } +#endif +#endif + unregister_netdev(net_dev); + free_netdev(net_dev); + } + + clear_bit(ATM_VF_READY, &atmvcc->flags); + clear_bit(ATM_VF_ADDR, &atmvcc->flags); + +#if defined(CONFIG_MACH_FUSIV) + if(AtmDeleteVCInfo_ptr != NULL) + { + (*AtmDeleteVCInfo_ptr)(atmvcc->vpi, atmvcc->vci); + } + else + printk("\nbr2684: atmdriver_lkm not initialized properly...\n"); + // AtmDeleteVCInfo(atmvcc->vpi, atmvcc->vci); +#endif + return 0; +} +#endif + /* * We remember when the MAC gets set, so we don't override it later with * the ESI of the ATM card of the first VC @@ -268,9 +391,24 @@ static int (*my_eth_mac_addr) (struct net_device *, void *); static int br2684_mac_addr(struct net_device *dev, void *p) { - int err = my_eth_mac_addr(dev, p); + int err = 0; + unsigned char old_mac[6]; + + memcpy(old_mac , dev->dev_addr , 6); + + err = my_eth_mac_addr(dev, p); if (!err) - BRPRIV(dev)->mac_was_set = 1; + { + BRPRIV(dev)->mac_was_set = 1; +#if defined(CONFIG_FUSIV_KERNEL_AP_2_AP) || defined(CONFIG_FUSIV_KERNEL_AP_2_AP_MODULE) + // delete the old mac in AP and add new one + if (br2684DelMacAddrFromAP_ptr) + br2684DelMacAddrFromAP_ptr(old_mac); + if (br2684AddMacAddrToAP_ptr) + br2684AddMacAddrToAP_ptr(dev->dev_addr); +#endif + } + return err; } @@ -340,8 +478,25 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) { struct br2684_vcc *brvcc = BR2684_VCC(atmvcc); - struct net_device *net_dev = brvcc->device; - struct br2684_dev *brdev = BRPRIV(net_dev); +#if !defined(CONFIG_MACH_FUSIV) + struct net_device *net_dev = brvcc->device; + struct br2684_dev *brdev = BRPRIV(net_dev); +#else + struct net_device *net_dev = NULL; + struct br2684_dev *brdev = NULL; + + if (brvcc) + { + net_dev = brvcc->device; + + if (net_dev) + brdev = BRPRIV(net_dev); + else + return; + } + else + return; +#endif pr_debug("br2684_push\n"); @@ -352,9 +507,25 @@ write_lock_irq(&devs_lock); list_del(&brdev->br2684_devs); write_unlock_irq(&devs_lock); +#if defined(CONFIG_MACH_FUSIV) +#if defined(CONFIG_FUSIV_KERNEL_AP_2_AP) || defined(CONFIG_FUSIV_KERNEL_AP_2_AP_MODULE) + if (br2684DelMacAddrFromAP_ptr) + { + br2684DelMacAddrFromAP_ptr(net_dev->dev_addr); + + } +#endif +#endif unregister_netdev(net_dev); free_netdev(net_dev); } + +#if defined(CONFIG_MACH_FUSIV) + if(AtmDeleteVCInfo_ptr != NULL) + (*AtmDeleteVCInfo_ptr)(atmvcc->vpi, atmvcc->vci); + else + printk("\nbr2684: atmdriver_lkm not initialized properly...\n"); +#endif return; } @@ -362,7 +533,7 @@ atm_return(atmvcc, skb->truesize); pr_debug("skb from brdev %p\n", brdev); if (brvcc->encaps == e_llc) { - +#if !defined(CONFIG_MACH_FUSIV) if (skb->len > 7 && skb->data[7] == 0x01) __skb_trim(skb, skb->len - 4); @@ -396,8 +567,12 @@ skb->protocol = eth_type_trans(skb, net_dev); } else goto error; - +#else + skb->pkt_type = PACKET_HOST; + skb->protocol = eth_type_trans(skb, net_dev); +#endif } else { /* e_vc */ +#if !defined(CONFIG_MACH_FUSIV) if (brdev->payload == p_routed) { struct iphdr *iph; @@ -417,6 +592,10 @@ skb_pull(skb, BR2684_PAD_LEN); skb->protocol = eth_type_trans(skb, net_dev); } +#else + skb->pkt_type = PACKET_HOST; + skb->protocol = eth_type_trans(skb, net_dev); +#endif } #ifdef CONFIG_ATM_BR2684_IPFILTER @@ -439,13 +618,19 @@ dropped: brdev->stats.rx_dropped++; goto free_skb; +#if !defined(CONFIG_MACH_FUSIV) error: brdev->stats.rx_errors++; +#endif free_skb: dev_kfree_skb(skb); return; } +#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 + /* * Assign a vcc to a dev * Note: we do not have explicit unassign, but look at _push() @@ -497,6 +682,10 @@ be.encaps, brvcc); if (list_empty(&brdev->brvccs) && !brdev->mac_was_set) { unsigned char *esi = atmvcc->dev->esi; +#if defined(CONFIG_MACH_FUSIV) + atmvcc->dev->esi[5] = 0x1+brdev->number; + esi = atmvcc->dev->esi; +#endif if (esi[0] | esi[1] | esi[2] | esi[3] | esi[4] | esi[5]) memcpy(net_dev->dev_addr, esi, net_dev->addr_len); else @@ -512,6 +701,11 @@ barrier(); atmvcc->push = br2684_push; +#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, brdev->payload == p_routed ? 3 : 0, brvcc->encaps == BR2684_ENCAPS_LLC ? 1 : 0); // IPoA or EoA w/o FCS +#endif + rq = &sk_atm(atmvcc)->sk_receive_queue; spin_lock_irqsave(&rq->lock, flags); @@ -537,6 +731,36 @@ skb = next; } __module_get(THIS_MODULE); + + +#if defined(CONFIG_MACH_FUSIV) + if(AtmUpdateNewVCInfo_ptr != NULL) + { + if((err =(*AtmUpdateNewVCInfo_ptr)(be.encaps, + atmvcc, + ADI_BR2684_MODULE, + brdev->net_dev->name)) < 0) + { + return err; + } +#if defined(CONFIG_FUSIV_KERNEL_AP_2_AP) || defined(CONFIG_FUSIV_KERNEL_AP_2_AP_MODULE) + if (br2684AddMacAddrToAP_ptr) + { + err = br2684AddMacAddrToAP_ptr( net_dev->dev_addr); + if (err < 0) + return err; + } + else + { + printk("\nbr2684AddMacToAP: Atmdriver_lkm not initialized properly\n"); + } +#endif + } + else + printk("\nbr2684: Atmdriver_lkm not initialized properly\n"); +#endif + + return 0; error: write_unlock_irq(&devs_lock); @@ -664,6 +888,18 @@ return err; #endif /* CONFIG_ATM_BR2684_IPFILTER */ +#if defined(CONFIG_MACH_FUSIV) + case ATM_DEL_INTERFACE: + { + atm_backend_t b; + err = get_user(b, (atm_backend_t __user *) argp); + if (err) + return -EFAULT; + + br2684_delete(atmvcc, argp); + } + return 0; +#endif } return -ENOIOCTLCMD; } @@ -787,9 +1023,178 @@ } } + + +#if defined(CONFIG_MACH_FUSIV) +/* Just temporary -need to modify a lot */ +struct atm_vcc * adi_getvcc(char *ifname) +{ + struct list_head *lh; + struct br2684_dev *brdev; + struct br2684_vcc *br_vcc; + struct net_device *net_dev; + + list_for_each(lh, &br2684_devs) + { + net_dev = list_entry_brdev(lh); + if (strcmp(net_dev->name, ifname) == 0 ) + { + brdev = BRPRIV(net_dev); + br_vcc = list_entry_brvcc(brdev->brvccs.next); + return br_vcc->atmvcc; + } + } + return NULL; +} + +int get_br2684_encap(struct atm_vcc *atmvcc) +{ + struct br2684_vcc *brvcc = BR2684_VCC(atmvcc); + if(brvcc->encaps == e_llc ) + return 1; + else + return 0; +} + +int get_br2684_overhead(struct net_device *net_dev) +{ + struct br2684_dev *brdev = NULL; + struct br2684_vcc *brvcc = NULL; + + brdev = BRPRIV(net_dev); + if(brdev == NULL) + return 0; + else + { + brvcc = list_entry_brvcc(brdev->brvccs.next); + if(brvcc == NULL) + return 0; + } + if(brdev->payload == BR2684_PAYLOAD_BRIDGED) + { + if (brvcc->encaps == e_llc) + return LLC_BRIDGED_OVERHEAD; + else + return VC_BRIDGED_OVERHEAD; + } + else + { + if (brvcc->encaps == e_llc) + return LLC_ROUTED_OVERHEAD; + else + return VC_ROUTED_OVERHEAD; + } +} + +struct net_device* get_br2684_ifname(struct atm_vcc *atmvcc) +{ + struct br2684_vcc *brvcc = BR2684_VCC(atmvcc); + + if (!brvcc) + return NULL; + + return brvcc->device; +} +EXPORT_SYMBOL(adi_getvcc); +EXPORT_SYMBOL(get_br2684_encap); +EXPORT_SYMBOL(get_br2684_ifname); +EXPORT_SYMBOL(get_br2684_overhead); +#endif + module_init(br2684_init); module_exit(br2684_exit); + +#if defined(CONFIG_MACH_FUSIV) +EXPORT_SYMBOL(AtmUpdateNewVCInfo_ptr); +EXPORT_SYMBOL(AtmUpdateVCInfo_ptr); +EXPORT_SYMBOL(AtmDeleteVCInfo_ptr); +#if defined(CONFIG_FUSIV_KERNEL_AP_2_AP) || defined(CONFIG_FUSIV_KERNEL_AP_2_AP_MODULE) +EXPORT_SYMBOL(br2684AddMacAddrToAP_ptr); +EXPORT_SYMBOL(br2684DelMacAddrFromAP_ptr); +#endif +#endif + +#if defined(CONFIG_FUSIV_KERNEL_PPPOE_RELAY) || defined(CONFIG_FUSIV_KERNEL_PPPOE_RELAY_MODULE) +EXPORT_SYMBOL(checkPPPOERelayStatus_ptr); +EXPORT_SYMBOL(getConfigModuleId_ptr); +#endif + +#if defined(CONFIG_IFX_PPA_API) || defined(CONFIG_IFX_PPA_API_MODULE) +int ppa_br2684_get_vcc(struct net_device *netif, struct atm_vcc **pvcc) +{ + if ( netif && (uint32_t)br2684_start_xmit == (uint32_t)netif->hard_start_xmit ) + { + struct br2684_dev *brdev; + struct br2684_vcc *brvcc; + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) + brdev = (struct br2684_dev *)netif->priv; + #else + brdev = (struct br2684_dev *)((char *)(netif) - (unsigned long)(&((struct br2684_dev *)0)->net_dev)); + #endif + brvcc = list_empty(&brdev->brvccs) ? NULL : list_entry(brdev->brvccs.next, struct br2684_vcc, brvccs); + + if ( brvcc ) + { + *pvcc = brvcc->atmvcc; + return 0; + } + } + + return -1; +} + +int32_t ppa_if_is_br2684(struct net_device *netif, char *ifname) +{ + if ( !netif ) + { + netif = dev_get_by_name(ifname); + if ( !netif ) + return 0; // can not get + else + dev_put(netif); + } + + return (uint32_t)br2684_start_xmit == (uint32_t)netif->hard_start_xmit ? 1 : 0; +} + +int32_t ppa_if_is_ipoa(struct net_device *netif, char *ifname) +{ + if ( !netif ) + { + netif = dev_get_by_name(ifname); + if ( !netif ) + return 0; + else + dev_put(netif); + } + + if ( ppa_if_is_br2684(netif, ifname) ) + { + struct br2684_dev *brdev; + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) + //brdev = (struct br2684_dev *)netif->priv; + brdev = BRPRIV(netif); + #else + brdev = (struct br2684_dev *)((char *)(netif) - (unsigned long)(&((struct br2684_dev *)0)->net_dev)); + #endif + + return brdev && brdev->payload == p_routed ? 1 : 0; + } + + return 0; +} +#endif + + MODULE_AUTHOR("Marcell GAL"); MODULE_DESCRIPTION("RFC2684 bridged protocols over ATM/AAL5"); MODULE_LICENSE("GPL"); + +#if defined(CONFIG_IFX_PPA_API_MODULE) + EXPORT_SYMBOL(ppa_if_is_ipoa); + EXPORT_SYMBOL(ppa_if_is_br2684); + EXPORT_SYMBOL(ppa_br2684_get_vcc); +#endif