diff options
author | Roman Yeryomin <roman@advem.lv> | 2013-05-17 20:40:24 +0300 |
---|---|---|
committer | Roman Yeryomin <roman@advem.lv> | 2013-05-17 20:40:24 +0300 |
commit | e6d87036412b952cb083eff2dc716aee97a771f2 (patch) | |
tree | 273dd3daaa85553832d3cc6d48276229dc7fbe09 /target/linux/realtek/files/drivers/net/rtl819x/rtl_nic.c | |
parent | a18fec42221baa52fff4c5ffd45ec8f32e3add36 (diff) |
Move to rsdk 3.2.4. Compiles cleanly.
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'target/linux/realtek/files/drivers/net/rtl819x/rtl_nic.c')
-rw-r--r-- | target/linux/realtek/files/drivers/net/rtl819x/rtl_nic.c | 2601 |
1 files changed, 2455 insertions, 146 deletions
diff --git a/target/linux/realtek/files/drivers/net/rtl819x/rtl_nic.c b/target/linux/realtek/files/drivers/net/rtl819x/rtl_nic.c index 2bb69510f..bdce954be 100644 --- a/target/linux/realtek/files/drivers/net/rtl819x/rtl_nic.c +++ b/target/linux/realtek/files/drivers/net/rtl819x/rtl_nic.c @@ -45,6 +45,9 @@ #undef CONFIG_RTL_IGMP_SNOOPING #endif +//if you need to use the fake eth driver, please also disable the "CONFIG_RTL_ETH_PRIV_SK" in kernel +//#define CONFIG_RTK_FAKE_ETH 1 + #include "version.h" #include <net/rtl/rtl_types.h> #include <net/rtl/rtl_glue.h> @@ -88,6 +91,9 @@ #include "romeperf.h" #endif #include <net/rtl/rtl_nic.h> +#if defined(CONFIG_RTL_FASTBRIDGE) +#include <net/rtl/features/fast_bridge.h> +#endif #if defined(CONFIG_RTL_HW_QOS_SUPPORT) && defined(CONFIG_NET_SCHED) && defined(CONFIG_RTL_LAYERED_DRIVER) #include <net/rtl/rtl865x_outputQueue.h> #endif @@ -100,6 +106,10 @@ #include <net/rtl/rtk_stp.h> #endif +#if defined(CONFIG_RTL_8196C_ESD) || defined(CONFIG_RTL_8198_ESD) +#include <linux/reboot.h> +#endif + #if defined (CONFIG_RTL_IGMP_SNOOPING) #include <net/rtl/rtl865x_igmpsnooping.h> #include <linux/if_ether.h> @@ -117,6 +127,13 @@ extern uint32 br0SwFwdPortMask; #endif #endif +#if defined(CONFIG_RTK_VLAN_WAN_TAG_SUPPORT) +uint32 nicIgmpModuleIndex_2=0xFFFFFFFF; +extern uint32 brIgmpModuleIndex_2; +#define VLAN_CONFIG_SIZE sizeof(vlanconfig)/sizeof(struct rtl865x_vlanConfig) +#define VLAN_CONFIG_PPPOE_INDEX (VLAN_CONFIG_SIZE-1) +#endif + #if defined (CONFIG_RTL_8198_INBAND_AP) || defined (CONFIG_RTL_8198_NFBI_BOARD) #define CONFIG_819X_PHY_RW 1 #endif @@ -124,6 +141,10 @@ extern uint32 br0SwFwdPortMask; static unsigned int curLinkPortMask=0; static unsigned int newLinkPortMask=0; +#ifdef CONFIG_RTL_8197D_DYN_THR +static int _8197d_link_check = 0; +#endif + #define SET_MODULE_OWNER(dev) do { } while (0) #if defined (CONFIG_RTL_HARDWARE_MULTICAST) @@ -135,6 +156,23 @@ static unsigned int newLinkPortMask=0; #include "RTL8366RB_DRIVER/rtl8366rb_apiBasic.h" #endif +#ifdef CONFIG_RTK_VOIP_PORT_LINK +#include <net/netlink.h> +#include <linux/rtnetlink.h> +static int rtnl_fill_ifinfo_voip(struct sk_buff *skb, struct net_device *dev, + int type, u32 pid, u32 seq, u32 change, unsigned int flags); +static void rtmsg_ifinfo_voip(int type, struct net_device *dev, unsigned change); +#endif + +#ifdef CONFIG_RTK_VOIP_ETHERNET_DSP +void voip_dsp_L2_pkt_rx(unsigned char* eth_pkt); +#endif + +#ifdef CONFIG_RTK_VOIP_ETHERNET_DSP +//merged from r8627 may conflict later +void ( *voip_dsp_L2_pkt_rx_trap )(unsigned char* eth_pkt, unsigned long size) = NULL; // pkshih: eth_pkt content may be modified!! +#endif + #if (defined(CONFIG_RTL_CUSTOM_PASSTHRU) && !defined(CONFIG_RTL8196_RTL8366)) __DRAM_FWD static int oldStatus; static struct proc_dir_entry *res=NULL; @@ -144,7 +182,7 @@ static int32 rtl8651_initStormCtrl(void); static inline int32 rtl_isPassthruFrame(uint8 *data); #endif -#if (defined(CONFIG_RTL_8198)) +#if defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) static struct proc_dir_entry *phyTest_entry=NULL; #endif @@ -181,6 +219,13 @@ EXPORT_SYMBOL(wirelessnet_hook); #endif #endif +#if defined(BR_SHORTCUT_C2) +__DRAM_FWD unsigned char cached_eth_addr2[ETHER_ADDR_LEN]; +EXPORT_SYMBOL(cached_eth_addr2); +__DRAM_FWD struct net_device *cached_dev2; +EXPORT_SYMBOL(cached_dev2); +int last_used = 1; +#endif #if defined(CONFIG_RTL_REINIT_SWITCH_CORE) #define STATE_NO_ERROR 0 @@ -213,6 +258,23 @@ static void linkup_time_handle(unsigned long arg); static int32 initPortStateCtrl(void); static void exitPortStateCtrl(void); #endif + +#ifdef CONFIG_RTL_HW_VLAN_SUPPORT +#define PORT_NUMBER 6 +struct hw_vlan_port_setting{ + int32 vlan_port_enabled; + int32 vlan_port_bridge; + int32 vlan_port_tag; + int32 vlan_port_vid; +}; +int rtl_hw_vlan_ignore_tagged_mc = 1; + +struct hw_vlan_port_setting hw_vlan_info[PORT_NUMBER]; + +int32 rtl_hw_vlan_enable = 0; +#endif + + #if defined(CONFIG_RTL_ETH_PRIV_SKB) __MIPS16 __IRAM_FWD static struct sk_buff *dev_alloc_skb_priv_eth(unsigned int size); static void init_priv_eth_skb_buf(void); @@ -221,14 +283,25 @@ static void init_priv_eth_skb_buf(void); #if defined(CONFIG_RTK_QOS_FOR_CABLE_MODEM) static void rtl_initVlanTableForCableMode(void); #endif + +static int32 rtl819x_eee_proc_init(void); + __DRAM_FWD static struct ring_que rx_skb_queue; int skb_num=0; #if defined(CONFIG_RTL_MULTIPLE_WAN) +#define MULTICAST_NETIF_VLAN_ID 678 +static char multiCastNetIf[20]={"multiCastNetIf"}; +static char multiCastNetIfMac[6]={ 0x00, 0x11, 0x12, 0x13, 0x14, 0x15 }; static struct net_device *rtl_multiWan_net_dev; static int rtl_regist_multipleWan_dev(void); static int rtl_config_multipleWan_netif(int32 cmd); static int rtl_port_used_by_device(uint32 portMask); +static int rtl865x_addMultiCastNetif(void); +#if 0 +static int rtl865x_delMultiCastNetif(void); +int rtl865x_setMultiCastSrcMac(unsigned char *srcMac); +#endif #endif int32 rtl865x_init(void); @@ -276,6 +349,14 @@ __IRAM_GEN static inline void rtl_link_change_interrupt_process(unsigned int sta static int rtl_rxTxDoneCnt = 0; static atomic_t rtl_devOpened; +#if defined(CONFIG_RTL_PROC_DEBUG) +extern unsigned int tx_ringFull_cnt; +#endif + +#if defined(CONFIG_RTL_819XD) +static int rtl_port0Refined = 0; +#endif + __MIPS16 __IRAM_GEN void rtl_rxSetTxDone(int enable) { if (unlikely(rtl_devOpened.counter==0)) @@ -309,14 +390,32 @@ static unsigned int rxRingSize[RTL865X_SWNIC_RXRING_HW_PKTDESC] = NUM_RX_PKTHDR_DESC3, NUM_RX_PKTHDR_DESC4, NUM_RX_PKTHDR_DESC5}; + +#if defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) +static unsigned int txRingSize[RTL865X_SWNIC_TXRING_HW_PKTDESC] = + {NUM_TX_PKTHDR_DESC, + NUM_TX_PKTHDR_DESC1, + NUM_TX_PKTHDR_DESC2, + NUM_TX_PKTHDR_DESC3 + }; +#else static unsigned int txRingSize[RTL865X_SWNIC_TXRING_HW_PKTDESC] = {NUM_TX_PKTHDR_DESC, NUM_TX_PKTHDR_DESC1}; +#endif #if defined (CONFIG_RTL_MULTI_LAN_DEV)||defined(CONFIG_RTK_VLAN_SUPPORT) static struct rtl865x_vlanConfig packedVlanConfig[NETIF_NUMBER]; #endif +#ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + int vlan_tag; + int vlan_host_pri; + int vlan_bridge_tag; + int vlan_bridge_port; + int vlan_bridge_multicast_tag; +#endif + /* linux protocol stack netif VS rtl819x driver network interface the name of ps netif maybe different with driver. @@ -352,6 +451,9 @@ static struct rtl865x_vlanConfig vlanconfig[] = { #ifdef CONFIG_8198_PORT5_GMII { RTL_DRV_LAN_P5_NETIF_NAME, 0, IF_ETHER, RTL_LANVLANID, RTL_LAN_FID, RTL_LANPORT_MASK_5, RTL_LANPORT_MASK_5, 1500, { { 0x00, 0x12, 0x34, 0x56, 0x78, 0x95 } }, 0 }, #endif //CONFIG_8198_PORT5_GMII +#ifdef CONFIG_RTK_VLAN_NEW_FEATURE + { RTL_DRV_LAN_P7_NETIF_NAME, 0, IF_ETHER, RTL_LANVLANID, RTL_LAN_FID, 0, 0, 1500, { { 0x00, 0x12, 0x34, 0x56, 0x78, 0x97 } }, 0 }, +#endif #endif #endif #else /*CONFIG_BRIDGE*/ @@ -368,6 +470,9 @@ static struct rtl865x_vlanConfig vlanconfig[] = { { RTL_DRV_LAN_P1_NETIF_NAME, 0, IF_ETHER, RTL_LANVLANID, RTL_LAN_FID, RTL_LANPORT_MASK_3, RTL_LANPORT_MASK_3, 1500, { { 0x00, 0x12, 0x34, 0x56, 0x78, 0x92 } }, 0 }, { RTL_DRV_LAN_P2_NETIF_NAME, 0, IF_ETHER, RTL_LANVLANID, RTL_LAN_FID, RTL_LANPORT_MASK_2, RTL_LANPORT_MASK_2, 1500, { { 0x00, 0x12, 0x34, 0x56, 0x78, 0x93 } }, 0 }, { RTL_DRV_LAN_P3_NETIF_NAME, 0, IF_ETHER, RTL_LANVLANID, RTL_LAN_FID, RTL_LANPORT_MASK_1, RTL_LANPORT_MASK_1, 1500, { { 0x00, 0x12, 0x34, 0x56, 0x78, 0x94 } }, 0 }, +#ifdef CONFIG_RTK_VLAN_NEW_FEATURE + { RTL_DRV_LAN_P7_NETIF_NAME, 0, IF_ETHER, RTL_LANVLANID, RTL_LAN_FID, 0, 0, 1500, { { 0x00, 0x12, 0x34, 0x56, 0x78, 0x97 } }, 0 }, +#endif #endif #endif #endif @@ -399,6 +504,11 @@ __DRAM_FWD static struct list_head eth_skbbuf_list; __DRAM_FWD int eth_skb_free_num; EXPORT_SYMBOL(eth_skb_free_num); extern struct sk_buff *dev_alloc_8190_skb(unsigned char *data, int size); +struct sk_buff *priv_skb_copy(struct sk_buff *skb); +#endif + +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) + struct vlan_info management_vlan; #endif #ifdef CONFIG_POCKET_AP_SUPPORT @@ -438,8 +548,22 @@ static int read_proc_vlan(char *page, char **start, off_t off,int count, int *eo static int write_proc_vlan(struct file *file, const char *buffer,unsigned long count, void *data); static int32 rtk_vlan_support_read( char *page, char **start, off_t off, int count, int *eof, void *data ); static int32 rtk_vlan_support_write( struct file *filp, const char *buff,unsigned long len, void *data ); +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) +static int rtk_vlan_management_read(char *page, char **start, off_t off, int count, int *eof, void *data); +static int rtk_vlan_management_write(struct file *file, const char *buffer, unsigned long len, void *data); +#endif + //__DRAM_FWD int rtk_vlan_support_enable; int rtk_vlan_support_enable; + + +#ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT +static int32 rtk_vlan_wan_tag_getportmask(int bridge_port); +static int32 rtk_vlan_wan_tag_support_read( char *page, char **start, off_t off, int count, int *eof, void *data ); +static int32 rtk_vlan_wan_tag_support_write( struct file *filp, const char *buff,unsigned long len, void *data ); +#endif + + #if defined(CONFIG_819X_PHY_RW) //#if defined(CONFIG_RTK_VLAN_FOR_CABLE_MODEM) static int32 rtl_phy_status_read( char *page, char **start, off_t off, int count, int *eof, void *data ); static int32 rtl_phy_status_write( struct file *filp, const char *buff,unsigned long len, void *data ); @@ -509,6 +633,15 @@ struct port_mibStatistics { #endif //#if defined(CONFIG_819X_PHY_RW) #endif +#if defined(CONFIG_RTL_HW_VLAN_SUPPORT) +static int32 rtl_hw_vlan_support_read( char *page, char **start, off_t off, int count, int *eof, void *data ); +static int32 rtl_hw_vlan_support_write( struct file *filp, const char *buff,unsigned long len, void *data ); +static int32 rtl_hw_vlan_tagged_bridge_multicast_read( char *page, char **start, off_t off, int count, int *eof, void *data ); +static int32 rtl_hw_vlan_tagged_bridge_multicast_write( struct file *filp, const char *buff,unsigned long len, void *data ); +int rtl_process_hw_vlan_tx(rtl_nicTx_info *txInfo); +#endif + + #if defined(RTL8196C_EEE_MAC) extern int eee_enabled; extern void eee_phy_enable(void); @@ -734,6 +867,90 @@ void disable_led_ctrl(int port) } #endif // PATCH_GPIO_FOR_LED +#if defined(CONFIG_RTL_819XD)&&defined(CONFIG_RTL_8211DS_SUPPORT)&&defined(CONFIG_RTL_8197D) +int lanPortMask = 0x10f; +int wanPortMask = 0x10; +#if defined(CONFIG_RTK_VLAN_SUPPORT) || defined (CONFIG_RTL_MULTI_LAN_DEV) +int lanPortMask1 = 0x8; +int lanPortMask2 = 0x4; +int lanPortMask3 = 0x2; +int lanPortMask4 = 0x1; +#endif + +#undef RTL_WANPORT_MASK +#undef RTL_LANPORT_MASK +#if defined(CONFIG_RTK_VLAN_SUPPORT) || defined (CONFIG_RTL_MULTI_LAN_DEV) +#undef RTL_LANPORT_MASK_1 +#undef RTL_LANPORT_MASK_2 +#undef RTL_LANPORT_MASK_3 +#undef RTL_LANPORT_MASK_4 +#endif + +#define RTL_WANPORT_MASK wanPortMask +#define RTL_LANPORT_MASK lanPortMask +#if defined(CONFIG_RTK_VLAN_SUPPORT) || defined (CONFIG_RTL_MULTI_LAN_DEV) +#define RTL_LANPORT_MASK_1 lanPortMask1 +#define RTL_LANPORT_MASK_2 lanPortMask2 +#define RTL_LANPORT_MASK_3 lanPortMask3 +#define RTL_LANPORT_MASK_4 lanPortMask4 +#endif + +void rtl_setPppMask(void) +{ + int i; + int totalVlans; + totalVlans=((sizeof(vlanconfig))/(sizeof(struct rtl865x_vlanConfig)))-1; + for(i=0;i<totalVlans;i++) + { + if(vlanconfig[i].if_type==IF_PPPOE){ + vlanconfig[i].memPort = 0x1; + vlanconfig[i].untagSet = 0x1; + } + } +} + +void rtl_resetRegisterNotFound8211ds(void) +{ + REG32(0xbb804104) =0x00FF2039; + REG32(0xbb80414c) =0; + REG32(0xbb804100) =0; +} + +void rtl_setPortMask(uint32 reg_data) +{ + if((reg_data != 0)&&(reg_data != 0xFFFF)) + { + /*8211ds is found*/ + lanPortMask = 0x11e; + wanPortMask = 0x1; + #if defined(CONFIG_RTK_VLAN_SUPPORT) || defined (CONFIG_RTL_MULTI_LAN_DEV) + lanPortMask1 = 0x10; + lanPortMask2 = 0x8; + lanPortMask3 = 0x4; + lanPortMask4 = 0x2; + #endif + rtl_setPppMask(); + + // Flow control DSC tolerance: change to 32 pages to fix "port 0 (8211D) has Rx CRC" issue. + REG32(MACCR) = (REG32(MACCR) & ~CF_FCDSC_MASK) | (0x20 << CF_FCDSC_OFFSET); + } + else + { + /*8211ds is not found*/ + lanPortMask = 0x10f; + wanPortMask = 0x10; + #if defined(CONFIG_RTK_VLAN_SUPPORT) || defined (CONFIG_RTL_MULTI_LAN_DEV) + lanPortMask1 = 0x8; + lanPortMask2 = 0x4; + lanPortMask3 = 0x2; + lanPortMask4 = 0x1; + #endif + rtl_resetRegisterNotFound8211ds(); + } +} +#endif + + /* device mapping mainten */ @@ -894,7 +1111,7 @@ static void re865x_set_rx_mode (struct net_device *dev){ void re865x_accumulate_port_stats(uint32 portnum, struct net_device_stats *net_stats) { uint32 addrOffset_fromP0 =0; - + extern uint64 rtl865xC_returnAsicCounter64(uint32 offset); if( portnum < 0 || portnum > CPU) return ; addrOffset_fromP0 = portnum * MIB_ADDROFFSETBYPORT; @@ -907,8 +1124,8 @@ static void re865x_set_rx_mode (struct net_device *dev){ net_stats->tx_packets += rtl8651_returnAsicCounter( OFFSET_IFOUTMULTICASTPKTS_P0 + addrOffset_fromP0 ) ; net_stats->tx_packets += rtl8651_returnAsicCounter( OFFSET_IFOUTBROADCASTPKTS_P0 + addrOffset_fromP0 ) ; - net_stats->rx_bytes += rtl8651_returnAsicCounter( OFFSET_IFINOCTETS_P0 + addrOffset_fromP0 ) ; - net_stats->tx_bytes += rtl8651_returnAsicCounter( OFFSET_IFOUTOCTETS_P0 + addrOffset_fromP0 ) ; + net_stats->rx_bytes += rtl865xC_returnAsicCounter64( OFFSET_IFINOCTETS_P0 + addrOffset_fromP0 ) ; + net_stats->tx_bytes += rtl865xC_returnAsicCounter64( OFFSET_IFOUTOCTETS_P0 + addrOffset_fromP0 ) ; /*rx_errors = CRC error + Jabber error + Fragment error*/ net_stats->rx_errors += rtl8651_returnAsicCounter( OFFSET_DOT3STATSFCSERRORS_P0 + addrOffset_fromP0 ) ; net_stats->rx_errors += rtl8651_returnAsicCounter( OFFSET_ETHERSTATSJABBERS_P0 + addrOffset_fromP0 ) ; @@ -1078,10 +1295,27 @@ static void rtl865x_disableDevPortForward(struct net_device *dev, struct dev_pri } } #ifdef CONFIG_RTL_8196C_ESD - _96c_esd_counter = 0; // stop counting + if ((cp->portmask) & 0x10) // port 4 + _96c_esd_counter = 0; // stop counting #endif } -#if defined(CONFIG_819X_PHY_RW)//#if defined(CONFIG_RTK_VLAN_FOR_CABLE_MODEM) + +#if !defined(CONFIG_RTL_8196C) +static void rtl865x_restartDevPHYNway(struct net_device *dev, struct dev_priv *cp) +{ + int port; + for(port=0;port<RTL8651_AGGREGATOR_NUMBER;port++) + { + if((1<<port) & cp->portmask) + { + rtl8651_restartAsicEthernetPHYNway(port); + } + } + return; +} +#endif + +#if defined(CONFIG_819X_PHY_RW) || defined(CONFIG_RTL_HW_VLAN_SUPPORT) static void rtl865x_setPortForward(int port_num, int forward) { if(port_num < 0 || port_num >= RTL8651_AGGREGATOR_NUMBER) @@ -1090,11 +1324,20 @@ static void rtl865x_setPortForward(int port_num, int forward) if(forward == FALSE) { REG32(PCRP0+(port_num<<2))= ((REG32(PCRP0+(port_num<<2)))&(~EnablePHYIf)); #ifdef CONFIG_RTL_8196C_ESD - _96c_esd_counter = 0; // stop counting + if (port_num == 4) // port 4 + _96c_esd_counter = 0; // stop counting #endif } - else + else { REG32(PCRP0+(port_num<<2))= ((REG32(PCRP0+(port_num<<2)))|(EnablePHYIf)); + +#ifdef CONFIG_RTL_8196C_ESD + if (port_num == 4) { // port 4 + _96c_esd_counter = 1; // start counting and check ESD + _96c_esd_reboot_counter = 0; // reset counter + } +#endif + } TOGGLE_BIT_IN_REG_TWICE(PCRP0+(port_num<<2),EnForceMode); } @@ -1118,8 +1361,10 @@ static void rtl865x_enableDevPortForward(struct net_device *dev, struct dev_priv } } #ifdef CONFIG_RTL_8196C_ESD - _96c_esd_counter = 1; // start counting and check ESD - _96c_esd_reboot_counter = 0; // reset counter + if ((cp->portmask) & 0x10) { // port 4 + _96c_esd_counter = 1; // start counting and check ESD + _96c_esd_reboot_counter = 0; // reset counter + } #endif } @@ -1140,6 +1385,17 @@ static void rtk_queue_init(struct ring_que *que) que->qmax = rtl865x_maxPreAllocRxSkb; } +static void rtk_queue_exit(struct ring_que *que) +{ + + if(que->ring!=NULL) + { + kfree(que->ring); + que->ring=NULL; + } +} + + __MIPS16 __IRAM_FWD static int rtk_queue_tail(struct ring_que *que, struct sk_buff *skb) @@ -1209,9 +1465,9 @@ static void refill_rx_skb(void) idx = RTL865X_SWNIC_RXRING_MAX_PKTDESC -1; #ifdef DELAY_REFILL_ETH_RX_BUF - while (rx_skb_queue.qlen < rtl865x_maxPreAllocRxSkb || ((idx>=0)&&(SUCCESS==check_rx_pkthdr_ring(idx, &idx)))) + while (rx_skb_queue.qlen < rtl865x_maxPreAllocRxSkb || ((idx>=0)&&(SUCCESS==check_rx_pkthdr_ring(idx, &idx)))) #else - while (rx_skb_queue.qlen < rtl865x_maxPreAllocRxSkb) + while (rx_skb_queue.qlen < rtl865x_maxPreAllocRxSkb) #endif { #if defined(CONFIG_RTL_ETH_PRIV_SKB) @@ -1294,6 +1550,10 @@ unsigned char *alloc_rx_buf(void **skb, int buflen) if (new_skb == NULL) return NULL; +#if 0//defined(CONFIG_RTL_ULINKER_BRSC) + skb_reserve(new_skb, 2); +#endif + *skb = new_skb; return new_skb->data; @@ -1363,7 +1623,7 @@ void tx_done_callback(void *skb) ((struct sk_buff *)skb)->srcVlanPriority=0; #endif -#if defined(CONFIG_NETFILTER_XT_MATCH_PHYPORT)|| defined(CONFIG_RTL_FAST_FILTER) || defined(CONFIG_RTL_QOS_PATCH) +#if defined(CONFIG_NETFILTER_XT_MATCH_PHYPORT)|| defined(CONFIG_RTL_FAST_FILTER) || defined(CONFIG_RTL_QOS_PATCH) || defined(CONFIG_RTK_VOIP_QOS) || defined(CONFIG_RTK_VLAN_WAN_TAG_SUPPORT) ||defined(CONFIG_RTL_MAC_FILTER_CARE_INPORT) ((struct sk_buff *)skb)->srcPhyPort=0xFF; ((struct sk_buff *)skb)->dstPhyPort=0xFF; #endif @@ -1620,6 +1880,11 @@ static inline void re865x_relayTrappedMCast(struct sk_buff *skb, unsigned int vi rtl_nicTx_info nicTx; struct sk_buff *skb2=NULL; + #ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + struct sk_buff *skb_wan=NULL; + rtl_nicTx_info nicTx_wan; + #endif + if(mcastFwdPortMask==0) { return; @@ -1636,17 +1901,54 @@ static inline void re865x_relayTrappedMCast(struct sk_buff *skb, unsigned int vi if(skb2!=NULL) { + +#ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + if( vlan_bridge_tag && vlan_bridge_multicast_tag &&(vid == vlan_bridge_tag)&&(mcastFwdPortMask & RTL_WANPORT_MASK)) + { + mcastFwdPortMask &= (~RTL_WANPORT_MASK); + skb_wan = skb_copy(skb, GFP_ATOMIC); + if(skb_wan!=NULL) + { + nicTx_wan.txIdx=0; + nicTx_wan.vid = vlan_bridge_multicast_tag; + nicTx_wan.portlist = RTL_WANPORT_MASK; + nicTx_wan.srcExtPort = 0; + + nicTx_wan.tagport = RTL_WANPORT_MASK; + + // flush cache 0515 by tim + _dma_cache_wback_inv((unsigned long) skb_wan->data, skb_wan->len); + if (swNic_send((void *)skb_wan, skb_wan->data, skb_wan->len, &nicTx_wan) < 0) + { + dev_kfree_skb_any(skb_wan); + } + } + } + + if(!mcastFwdPortMask) + { + dev_kfree_skb_any(skb2); + return; + } +#endif nicTx.txIdx=0; -#if defined(CONFIG_RTL_QOS_PATCH) - if(((struct sk_buff *)skb)->srcPhyPort == QOS_PATCH_RX_FROM_LOCAL){ +#if defined(CONFIG_RTL_QOS_PATCH)|| defined(CONFIG_RTK_VOIP_QOS) + if(((struct sk_buff *)skb)->srcPhyPort == QOS_PATCH_RX_FROM_LOCAL) +{ nicTx.priority = QOS_PATCH_HIGH_QUEUE_PRIO; nicTx.txIdx=RTL865X_SWNIC_TXRING_MAX_PKTDESC-1; //use the highest tx ring index, note: not RTL865X_SWNIC_TXRING_HW_PKTDESC-1 } #endif nicTx.vid = vid; - nicTx.portlist = mcastFwdPortMask; + nicTx.portlist = mcastFwdPortMask&((struct dev_priv *)(skb->dev->priv))->portmask; nicTx.srcExtPort = 0; nicTx.flags = (PKTHDR_USED|PKT_OUTGOING); + #ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + if( (vlan_tag && vid == vlan_tag) || (vlan_bridge_tag && (vid == vlan_bridge_tag))) + { + nicTx.tagport = RTL_WANPORT_MASK; + } + #endif _dma_cache_wback_inv((unsigned long)skb2->data, skb2->len); if (swNic_send((void *)skb2, skb2->data, skb2->len, &nicTx) < 0) { @@ -1716,7 +2018,16 @@ static bool rtl_MulticastRxFilterOff(struct sk_buff *skb, int ipversion) skb->data = skb->data+ETH_HLEN; if(ipversion ==4) + { + struct net_device *origDev=skb->dev; + if((skb->dev->br_port!=NULL)) + { + skb->dev=__dev_get_by_name(dev_net(skb->dev),RTL_PS_BR0_DEV_NAME); + + } ret = ((IgmpRxFilter_Hook(skb, NF_INET_PRE_ROUTING, skb->dev, NULL,dev_net(skb->dev)->ipv4.iptable_filter)) !=NF_ACCEPT); + skb->dev=origDev; + } else if(ipversion ==6) ret = false;//ipv6 hava no iptables rule now @@ -1756,6 +2067,11 @@ int rtl_MulticastRxCheck(struct sk_buff *skb,rtl_nicRx_info *info) return -1; } + //when tag ignore is set, vid from packet buffer is zero , so get vid from pvid + //if(vid == 0) + // rtl8651_getAsicPVlanId(pid,&vid); + + /*set flooding port mask first*/ vlanRelayPortMask=rtl865x_getVlanPortMask(vid) & (~(1<<pid)) & ((1<<RTL8651_MAC_NUMBER)-1); @@ -1786,13 +2102,47 @@ int rtl_MulticastRxCheck(struct sk_buff *skb,rtl_nicRx_info *info) /*relay packets which are trapped by hardware multicast table*/ #if defined (CONFIG_RTL_HARDWARE_MULTICAST) + #ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + if(vlan_bridge_tag && !strcmp(cp_this->dev->name,RTL_PS_ETH_NAME_ETH2)) + { + if(igmpsnoopenabled && (nicIgmpModuleIndex_2!=0xFFFFFFFF)) + { + multicastDataInfo.ipVersion=4; + multicastDataInfo.sourceIp[0]= (uint32)(iph->saddr); + multicastDataInfo.groupAddr[0]= (uint32)(iph->daddr); + ret=rtl_getMulticastDataFwdInfo(nicIgmpModuleIndex_2, &multicastDataInfo, &nicMCastFwdInfo); + vlanRelayPortMask=rtl865x_getVlanPortMask(vid)& (~(1<<pid)) & nicMCastFwdInfo.fwdPortMask & ((1<<RTL8651_MAC_NUMBER)-1); + if(ret==SUCCESS) + { + + } + else + { + ret=rtl_getMulticastDataFwdInfo(brIgmpModuleIndex_2, &multicastDataInfo, &br0MCastFwdInfo); + if(ret==SUCCESS) + { + /*there is wireless client,can not flooding in vlan */ + vlanRelayPortMask=0; + } + } + + } + } + else + #endif if(igmpsnoopenabled && (nicIgmpModuleIndex!=0xFFFFFFFF)) { multicastDataInfo.ipVersion=4; + #if defined(CONFIG_RTL_ULINKER_BRSC) // assign value will cause coredump + memcpy(&multicastDataInfo.sourceIp, &iph->saddr, 4); + memcpy(&multicastDataInfo.groupAddr, &iph->daddr, 4); + #else multicastDataInfo.sourceIp[0]= (uint32)(iph->saddr); multicastDataInfo.groupAddr[0]= (uint32)(iph->daddr); + #endif + ret=rtl_getMulticastDataFwdInfo(nicIgmpModuleIndex, &multicastDataInfo, &nicMCastFwdInfo); - vlanRelayPortMask=rtl865x_getVlanPortMask(vid)& (~(1<<pid)) & nicMCastFwdInfo.fwdPortMask & ((1<<RTL8651_MAC_NUMBER)-1); + vlanRelayPortMask=rtl865x_getVlanPortMask(vid)& (~(1<<pid)) & nicMCastFwdInfo.fwdPortMask &cp_this->portmask& ((1<<RTL8651_MAC_NUMBER)-1); if(ret==SUCCESS) { @@ -1814,6 +2164,20 @@ int rtl_MulticastRxCheck(struct sk_buff *skb,rtl_nicRx_info *info) } else if(l4Protocol==IPPROTO_IGMP) { + #ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + if(vlan_bridge_tag && !strcmp(cp_this->dev->name,RTL_PS_ETH_NAME_ETH2)) + { + + if(igmpsnoopenabled && (nicIgmpModuleIndex_2!=0xFFFFFFFF)) + { + rtl_igmpMldProcess(nicIgmpModuleIndex_2, skb->data, pid, &vlanRelayPortMask); + //just flooding + vlanRelayPortMask=rtl865x_getVlanPortMask(vid) & (~(1<<pid)) & ((1<<RTL8651_MAC_NUMBER)-1); + } + } + else + { + #endif if(igmpsnoopenabled && (nicIgmpModuleIndex!=0xFFFFFFFF)) { /*igmp packet*/ @@ -1824,7 +2188,9 @@ int rtl_MulticastRxCheck(struct sk_buff *skb,rtl_nicRx_info *info) rtl_igmpMldProcess(nicIgmpModuleIndex, skb->data, pid, &vlanRelayPortMask); vlanRelayPortMask=rtl865x_getVlanPortMask(vid) & vlanRelayPortMask & ((1<<RTL8651_MAC_NUMBER)-1); } - + #ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + } + #endif re865x_relayTrappedMCast( skb, vid, vlanRelayPortMask, TRUE); } @@ -1886,7 +2252,7 @@ int rtl_MulticastRxCheck(struct sk_buff *skb,rtl_nicRx_info *info) ret=rtl_getMulticastDataFwdInfo(nicIgmpModuleIndex, &multicastDataInfo, &nicMCastFwdInfo); - vlanRelayPortMask=rtl865x_getVlanPortMask(vid)& (~(1<<pid)) & nicMCastFwdInfo.fwdPortMask & ((1<<RTL8651_MAC_NUMBER)-1); + vlanRelayPortMask=rtl865x_getVlanPortMask(vid)& (~(1<<pid)) & nicMCastFwdInfo.fwdPortMask &cp_this->portmask& ((1<<RTL8651_MAC_NUMBER)-1); if(ret==SUCCESS) { @@ -2144,18 +2510,21 @@ static inline int32 rtl_decideRxDevice(rtl_nicRx_info *info) #if defined(CONFIG_RTL_STP) int32 dev_no; #endif - #if defined(CONFIG_RTL_CUSTOM_PASSTHRU) + #if defined(CONFIG_RTL_CUSTOM_PASSTHRU_PPPOE) unsigned char dest_mac[MAX_ADDR_LEN]; #endif +#ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + int32 vid=0; + vid = info->vid; +#endif pid = info->pid; skb = info->input; data = skb->data; - #if defined(CONFIG_RTL_CUSTOM_PASSTHRU) + #if defined(CONFIG_RTL_CUSTOM_PASSTHRU_PPPOE) memcpy(dest_mac, data, 6); #endif - info->isPdev=FALSE; ret = SUCCESS; @@ -2180,25 +2549,27 @@ static inline int32 rtl_decideRxDevice(rtl_nicRx_info *info) #endif { #if defined(CONFIG_RTL_MULTIPLE_WAN) - //mac based decision - for(i = 0; i < ETH_INTF_NUM; i++) - { - cp = ((struct dev_priv *)_rtl86xx_dev.dev[i]->priv); - if(cp && cp->opened && memcmp(skb->data,cp->dev->dev_addr,6) == 0) - { - info->priv = cp; - goto out; - } - } - //rtl_multiWan_config - if(rtl_multiWan_net_dev) - { - cp = (struct dev_priv *)rtl_multiWan_net_dev->priv; - if(cp && cp->opened && memcmp(skb->data,cp->dev->dev_addr,6) == 0) - { - info->priv = cp; - goto out; + if(rtl865x_curOpMode == GATEWAY_MODE){ + //mac based decision + for(i = 0; i < ETH_INTF_NUM; i++) + { + cp = ((struct dev_priv *)_rtl86xx_dev.dev[i]->priv); + if(cp && cp->opened && memcmp(skb->data,cp->dev->dev_addr,6) == 0) + { + info->priv = cp; + goto out; + } } + //rtl_multiWan_config + if(rtl_multiWan_net_dev) + { + cp = (struct dev_priv *)rtl_multiWan_net_dev->priv; + if(cp && cp->opened && memcmp(skb->data,cp->dev->dev_addr,6) == 0) + { + info->priv = cp; + goto out; + } + } } #endif @@ -2206,11 +2577,53 @@ static inline int32 rtl_decideRxDevice(rtl_nicRx_info *info) { cp = ((struct dev_priv *)_rtl86xx_dev.dev[i]->priv); //printk("=========%s(%d),cp(%s),i(%d)\n",__FUNCTION__,__LINE__,cp->dev->name,i); + #ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + if(*((unsigned short *)(skb->data+(ETH_ALEN<<1)))== __constant_htons(ETH_P_8021Q)) + { + vid = *((unsigned short *)(skb->data+(ETH_ALEN<<1)+2))&0x0fff; + + if( vlan_tag && vid == vlan_tag) + { + if(rtl865x_curOpMode == BRIDGE_MODE) + vid = RTL_LANVLANID; + } + else if (vlan_bridge_tag && vid == vlan_bridge_tag) + { + vid = vlan_bridge_tag; + } + else if(vlan_bridge_multicast_tag && vid == vlan_bridge_multicast_tag) + { + vid = vlan_bridge_tag; + } + #ifdef CONFIG_VLAN_8021Q + else + { + vid = vlanconfig[1].vid;//default from WAN eth1 + } + #endif + if(cp && cp->opened && (vid==cp->id)) + { + info->priv = cp; + ret = SUCCESS; + break; + } + } + else + { + if(cp && cp->opened && (cp->portmask & (1<<pid))) + { + info->priv = cp; + ret = SUCCESS; + break; + } + } + #else if(cp && cp->opened && (cp->portmask & (1<<pid))) { info->priv = cp; break; } + #endif } //printk("====%s(%d),dev(%s),i(%d)\n",__FUNCTION__,__LINE__,cp->dev->name,i); @@ -2218,11 +2631,14 @@ static inline int32 rtl_decideRxDevice(rtl_nicRx_info *info) { info->priv = NULL; dev_kfree_skb_any(skb); - ret = FAILED;; + ret = FAILED; } #if defined(CONFIG_RTL_CUSTOM_PASSTHRU) else if (SUCCESS==rtl_isPassthruFrame(data)&&(rtl_isWanDev(cp)==TRUE) - && (compare_ether_addr((char* )cp->dev->dev_addr, (char*)dest_mac))) + #if defined(CONFIG_RTL_CUSTOM_PASSTHRU_PPPOE) + && (compare_ether_addr((char* )cp->dev->dev_addr, (char*)dest_mac)) + #endif + ) { info->priv = _rtl86xx_dev.pdev->priv; info->isPdev=TRUE; @@ -2235,35 +2651,105 @@ out: return ret; } +#if defined(CONFIG_RTL_ULINKER_BRSC) +#include "linux/ulinker_brsc.h" +#endif + #if defined(BR_SHORTCUT) __MIPS16 __IRAM_FWD static inline int32 rtl_processBridgeShortCut(struct sk_buff *skb, struct dev_priv *cp_this, rtl_nicRx_info *info) { struct net_device *dev; + /*2011-09-13 fix wlan sta can not access internet when wan mac clone sta mac*/ + if(rtl_isWanDev(cp_this) && (rtl865x_curOpMode == GATEWAY_MODE)) + { + return FAILED; + } + + /*if lltd, don't go shortcut*/ + if(*(unsigned short *)(skb->data+ETH_ALEN*2)==htons(0x88d9)) + return FAILED; if ( #if 0 (eth_flag & BIT(2)) && #endif -#if defined(CONFIG_DOMAIN_NAME_QUERY_SUPPORT) +#if defined(CONFIG_DOMAIN_NAME_QUERY_SUPPORT) || defined(CONFIG_RTL_ULINKER) (skb->data[37] != 68) && /*port 68 is dhcp dest port. In order to hack dns ip, so dhcp packag can't enter bridge short cut.*/ #endif #if defined(CONFIG_WIRELESS_LAN_MODULE) (wirelessnet_hook_shortcut !=NULL ) && ((dev = wirelessnet_hook_shortcut(skb->data)) != NULL) #else + #if defined(CONFIG_RTL_ULINKER_BRSC) + (((dev=brsc_get_cached_dev(0, skb->data))!=NULL) || ((dev = get_shortcut_dev(skb->data)) != NULL)) + #else ((dev = get_shortcut_dev(skb->data)) != NULL) + #endif + #endif + #ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + && rtl865x_same_root(skb->dev,dev) #endif ) { + #if defined(CONFIG_RTL_ULINKER_BRSC) + if (cached_usb.dev && dev == cached_usb.dev) { + BRSC_COUNTER_UPDATE(tx_eth_sc); + BDBG_BRSC("BRSC: get shortcut dev[%s]\n", cached_usb.dev->name); + + if (skb->dev) + brsc_cache_dev(2, skb->dev, skb->data+ETH_ALEN); + } + else + #endif /* #if defined(CONFIG_RTL_ULINKER_BRSC) */ + { #if defined(CONFIG_RTL_HARDWARE_NAT) if (memcmp(&skb->data[ETH_ALEN], cp_this->dev->dev_addr, ETH_ALEN)) #endif { + #ifdef BR_SHORTCUT_C2 + /* + if (cached_dev == NULL) { + memcpy(cached_eth_addr, &skb->data[ETH_ALEN], ETH_ALEN); + cached_dev = cp_this->dev; + last_used = 0; + } + + else if (cached_dev2 == NULL) { + memcpy(cached_eth_addr2, &skb->data[ETH_ALEN], ETH_ALEN); + cached_dev2 = cp_this->dev; + last_used = 1; + } + + else */ + if (memcmp(cached_eth_addr, &skb->data[ETH_ALEN], ETH_ALEN) == 0) { + //memcpy(cached_eth_addr, &skb->data[ETH_ALEN], ETH_ALEN); + cached_dev = cp_this->dev; + last_used = 0; + } + else if (memcmp(cached_eth_addr2, &skb->data[ETH_ALEN], ETH_ALEN) == 0) { + //memcpy(cached_eth_addr2, &skb->data[ETH_ALEN], ETH_ALEN); + cached_dev2 = cp_this->dev; + last_used = 1; + } + else if (last_used == 1) { + memcpy(cached_eth_addr, &skb->data[ETH_ALEN], ETH_ALEN); + cached_dev = cp_this->dev; + last_used = 0; + } + else if (last_used == 0) { + memcpy(cached_eth_addr2, &skb->data[ETH_ALEN], ETH_ALEN); + cached_dev2 = cp_this->dev; + last_used = 1; + } + + + #else memcpy(cached_eth_addr, &skb->data[ETH_ALEN], ETH_ALEN); cached_dev = cp_this->dev; + #endif } - + } #if defined(CONFIG_RTL_HW_QOS_SUPPORT) && defined(CONFIG_RTL_HARDWARE_NAT) skb->cb[0] = info->rxPri; #endif @@ -2291,6 +2777,7 @@ static inline int32 rtl_processBridgeShortCut(struct sk_buff *skb, struct dev_pr return FAILED; } #elif defined(CONFIG_RTL_HARDWARE_NAT)&&(defined(CONFIG_RTL8192SE)||defined(CONFIG_RTL8192CD)) +#if 0 __MIPS16 __IRAM_FWD static inline int32 rtl_processExtensionPortShortCut(struct sk_buff *skb, struct dev_priv *cp_this, rtl_nicRx_info *info) @@ -2331,6 +2818,7 @@ static inline int32 rtl_processExtensionPortShortCut(struct sk_buff *skb, struct return FAILED; } #endif +#endif __MIPS16 __IRAM_FWD @@ -2377,20 +2865,24 @@ static inline void rtl_processRxFrame(rtl_nicRx_info *info) goto RxToPs; } #endif - +#if 0 /* sanity check */ if ((memcmp(&data[ETH_ALEN], cp_this->dev->dev_addr, ETH_ALEN)==0)||PKTHDR_EXTPORT_MAGIC2==vid||PKTHDR_EXTPORT_MAGIC==vid)// check source mac { #if defined(CONFIG_RTL_HARDWARE_NAT)&&(defined(CONFIG_RTL8192SE)||defined(CONFIG_RTL8192CD)) + #ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + if ((PKTHDR_EXTPORT_MAGIC!=vid)||(info->pid!=PKTHDR_EXTPORT_P3 &&info->pid!=PKTHDR_EXTPORT_P2)) + #else if ((PKTHDR_EXTPORT_MAGIC!=vid)||(info->pid!=PKTHDR_EXTPORT_P3)) #endif + #endif { cp_this->net_stats.rx_dropped++; dev_kfree_skb_any(skb); return; } } - +#endif if (skb->head==NULL||skb->end==NULL) { dev_kfree_skb_any(skb); @@ -2405,7 +2897,23 @@ static inline void rtl_processRxFrame(rtl_nicRx_info *info) skb->dev=info->isPdev?_rtl86xx_dev.pdev:info->priv->dev; //skb->dev=cp_this->dev; -#if defined(CONFIG_NETFILTER_XT_MATCH_PHYPORT) || defined(CONFIG_RTL_FAST_FILTER) || defined(CONFIG_RTL_QOS_PATCH) +#ifdef CONFIG_RTK_VOIP_ETHERNET_DSP + //merged from r8627 may conflict later + //printk("type: %x, skb->mac=%p, skb->data=%p\n", skb->mac.ethernet->h_proto, skb->mac.ethernet, skb->data); + //extern void voip_dsp_L2_pkt_rx(unsigned char* eth_pkt); + if (*(uint16*)(&(skb->data[12])) == htons(0x8899) && voip_dsp_L2_pkt_rx_trap ) + { + //dsp_id = *(uint16*)(&(skb->data[14]); + voip_dsp_L2_pkt_rx_trap(skb->data, skb->len); + dev_kfree_skb_any(skb); + //printk("0x%x ", *(uint16*)(&(skb->data[12]))); + return; + } +#endif + + + +#if defined(CONFIG_NETFILTER_XT_MATCH_PHYPORT) || defined(CONFIG_RTL_FAST_FILTER) || defined(CONFIG_RTL_QOS_PATCH) || defined(CONFIG_RTK_VOIP_QOS) || defined(CONFIG_RTK_VLAN_WAN_TAG_SUPPORT) ||defined(CONFIG_RTL_MAC_FILTER_CARE_INPORT) skb->srcPhyPort=(uint8)pid; #endif //printk("=======%s(%d),cp_this(%s)\n",__FUNCTION__,__LINE__,cp_this->dev->name); @@ -2413,12 +2921,27 @@ static inline void rtl_processRxFrame(rtl_nicRx_info *info) #if defined(CONFIG_RTK_VLAN_SUPPORT) if (rtk_vlan_support_enable && cp_this->vlan_setting.global_vlan) { + #if defined(CONFIG_RTK_VLAN_NEW_FEATURE) + struct sk_buff *new_skb = NULL; + int vlan_check; + vlan_check = rx_vlan_process(cp_this->dev, &cp_this->vlan_setting, skb, &new_skb); + if((vlan_check==0) && new_skb){ + rtl_processRxToProtcolStack(new_skb, cp_this); + }else if(vlan_check == 1){ + cp_this->net_stats.rx_dropped++; + dev_kfree_skb_any(skb); + return; + }else if((vlan_check == 2) && new_skb){ + dev_kfree_skb_any(new_skb); + } + #else if (rx_vlan_process(cp_this->dev, &cp_this->vlan_setting, skb)) { cp_this->net_stats.rx_dropped++; dev_kfree_skb_any(skb); return; } + #endif #if defined(CONFIG_RTK_VLAN_FOR_CABLE_MODEM) if(rtk_vlan_support_enable == 2) @@ -2447,14 +2970,68 @@ static inline void rtl_processRxFrame(rtl_nicRx_info *info) #endif /* defined(CONFIG_RTK_VLAN_SUPPORT) */ if (*((uint16*)(skb->data+(ETH_ALEN<<1))) == __constant_htons(ETH_P_8021Q)) { + #if defined(CONFIG_RTL_HW_VLAN_SUPPORT) + if((skb->data[0]&1)||((skb->data[0]==0x33)&&(skb->data[1]==0x33)&&(skb->data[2]!=0xFF))) + { + memcpy(&skb->tag, skb->data+ETH_ALEN*2, sizeof(struct vlan_tag)); + } + #endif vid = *((unsigned short *)(data+(ETH_ALEN<<1)+2)); #if defined(CONFIG_RTL_QOS_8021P_SUPPORT) skb->srcVlanPriority = (vid>>13)&0x7; #endif vid &= 0x0fff; + #ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + //for later arp reply to WAN port + //memcpy(&(skb->tag), skb->data+ETH_ALEN*2, VLAN_HLEN); + + if(vlan_tag && vid == vlan_tag) + { + goto Remove_tag; + } + else if(vlan_bridge_tag && vid == vlan_bridge_tag) + { + if(vlan_bridge_multicast_tag) + { + if((skb->data[0]==0x01) && (skb->data[1]==0x00) && (skb->data[2]==0x5e)) + { + cp_this->net_stats.rx_dropped++; + dev_kfree_skb_any(skb); + return; + } + } + goto Remove_tag; + } + else if(vlan_bridge_multicast_tag && vid == vlan_bridge_multicast_tag) + { + if((skb->data[0]==0x01) && (skb->data[1]==0x00) && (skb->data[2]==0x5e)) + { + info->vid = vlan_bridge_tag;//for later check ??? + goto Remove_tag; + } + } + else + { + #ifndef CONFIG_VLAN_8021Q + cp_this->net_stats.rx_dropped++; + dev_kfree_skb_any(skb); + return; + #endif + } + #ifdef CONFIG_VLAN_8021Q + goto Reserve_tag; + #endif +Remove_tag: + #endif memmove(data + VLAN_HLEN, data, VLAN_ETH_ALEN<<1); skb_pull(skb, VLAN_HLEN); + +#ifdef CONFIG_VLAN_8021Q +Reserve_tag: + ;//don't remove tag +#endif + } /* vlan process end (vlan tag has already stripped) */ @@ -2474,11 +3051,17 @@ static inline void rtl_processRxFrame(rtl_nicRx_info *info) return; } #elif defined(CONFIG_RTL_HARDWARE_NAT)&&(defined(CONFIG_RTL8192SE)||defined(CONFIG_RTL8192CD)) + /* if (SUCCESS==rtl_processExtensionPortShortCut(skb,cp_this, info)) { return; } + */ #endif + #if defined(CONFIG_RTL_FASTBRIDGE) + if (RTL_FB_RETURN_SUCCESS==rtl_fb_process_in_nic(skb, cp_this->dev)) + return; + #endif /* shortcut process end */ /* unknow unicast control */ @@ -2542,7 +3125,7 @@ __IRAM_FWD static void interrupt_dsr_rx_done(rtlInterruptRxData *rxData) local_irq_save(flags); rtl_rxSetTxDone(TRUE); - REG32(CPUIIMR) |= (RX_DONE_IP_ALL); + REG32(CPUIIMR) |= (RX_DONE_IE_ALL | PKTHDR_DESC_RUNOUT_IE_ALL); rtl_rx_tasklet_running = 0; local_irq_restore(flags); #endif @@ -2681,9 +3264,9 @@ static int re865x_setPhyGrayCode(void) /*=========== ###02 ===========*/ /* - 1. reg17 = 0x1f10¡Aread reg29, for SNR - 2. reg17 = 0x1f11¡Aread reg29, for AGC - 3. reg17 = 0x1f18¡Aread reg29, for cb0 + 1. reg17 = 0x1f10,read reg29, for SNR + 2. reg17 = 0x1f11,read reg29, for AGC + 3. reg17 = 0x1f18,read reg29, for cb0 */ // 1. for SNR snr = 0; @@ -2783,7 +3366,7 @@ static int re865x_checkPhySnr(void) if((1<<port) & (newLinkPortMask & (~curLinkPortMask)) ) { snr=re865x_getPhySnr(port); - + // 3. for cb0 rtl8651_getAsicEthernetPHYReg( port, 17, &val ); val = (val & 0xfff0) | 0x8; @@ -2797,7 +3380,7 @@ static int re865x_checkPhySnr(void) //printk("snr is %d\n",snr); //printk("cb0 is 0x%x,agc is 0x%x\n",cb0,agc); //if( ((cb0 & 0x80) != 0)|| (snr>4155)) - if ( ( ( ((agc & 0x70) >> 4) < 4 ) && ((cb0 & 0x80) != 0) ) || (snr > 4155) ) + if ( ( ( ((agc & 0x70) >> 4) < 4 ) && ((cb0 & 0x80) != 0) ) || (snr > 4155) ) { //printk("restart nway\n"); rtl8651_restartAsicEthernetPHYNway(port); @@ -2889,7 +3472,7 @@ unsigned int rtl865x_getPhysicalPortLinkStatus(void) } #if defined(CONFIG_RTL_REPORT_LINK_STATUS) -unsigned int rtl865x_setLinkStatusFlag(unsigned int newportmask) +unsigned int rtl865x_setLinkStatusFlag(unsigned int curLinkPortMask, unsigned int newportmask) { int i; struct dev_priv * cp=NULL; @@ -2898,7 +3481,7 @@ unsigned int rtl865x_setLinkStatusFlag(unsigned int newportmask) for(i = 0; i < ETH_INTF_NUM; i++) { cp = ((struct dev_priv *)_rtl86xx_dev.dev[i]->priv); - if(cp && cp->opened && rtl_isWanDev(cp) && (cp->portmask & newportmask)) + if(cp && cp->opened && rtl_isWanDev(cp) && ((cp->portmask & curLinkPortMask)==0) && (cp->portmask & newportmask)) { wan_linkStatus[0] = 1; return SUCCESS; @@ -2909,11 +3492,22 @@ unsigned int rtl865x_setLinkStatusFlag(unsigned int newportmask) } #endif + +#ifdef CONFIG_RTL_819X_SWCORE +int cnt_swcore = 0; +int cnt_swcore_tx = 0; +int cnt_swcore_rx = 0; +int cnt_swcore_link = 0; +int cnt_swcore_err = 0; +#endif + + #ifdef CONFIG_RTL_8198_ESD static uint32 phy_reg30[RTL8651_PHY_NUMBER] = { 0, 0, 0, 0, 0}; static int one_second_counter = 0; static int first_time_read_reg6 = 1; static int need_to_check_esd2 = 1; +static int esd3_skip_one = 1; inline static int diff_more_than_1(uint32 a, uint32 b) { @@ -2951,6 +3545,70 @@ static int esd_recovery(void) } #endif +#if defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) +/* +krammer add this according to " Jim Hsieh/5458 "'s algorithm +Description: +when phy0's link partner link in force mode, we will force to half duplex mode, +in this condition, if there is some traffic in port0's rx, sometimes port0 will die. +so we add this patch, only work when phy0's link state change, if link partner +is link in force mode, we will change our port0 into full duplex. +*/ +void rtl819x_port0_force_refined(void){ + unsigned int regData; + + if((curLinkPortMask & 0x01) == (newLinkPortMask & 0x01)){ + //no change -> return + return; + } + + //default disable phy i/f(0xbb804104 b0=0) + REG32(PCRP0) &= ~(EnablePHYIf); + + //if port#0=link up + if(newLinkPortMask & 0x01){ + //if AN =0(reg6[0]) + rtl8651_getAsicEthernetPHYReg(rtl8651_tblAsicDrvPara.externalPHYId[0], 6, ®Data); + if((regData & 0x01) == 0){ + rtl8651_getAsicEthernetPHYReg(rtl8651_tblAsicDrvPara.externalPHYId[0], 5, ®Data); + if(regData & 0x080){//if spd = 100M(reg5[7]) + //force MAC 100M Full duplex + //(set 0xbb804104 b25=1 b24=1 b23=0 b20-19=1 b18=1 b17-16=0x3) + regData = REG32(PCRP0); + regData |= (EnForceMode | PollLinkStatus | ForceDuplex | PauseFlowControlEtxErx); + regData &= ~(ForceLink | ForceSpeedMask); + regData |= (ForceSpeed100M); + //panic_printk("phy0 link partner is force 100M, we force to 100M Full duplex!regData = 0x%x\n", regData); + REG32(PCRP0) = regData; + } + else if(regData & 0x20){//else spd = 10M(reg5[5]) + //force MAC 10M Full duplex + //(set 0xbb804104 b25=1 b24=1 b23=0 b20-19=0 b18=1 b17-16=0x3) + regData = REG32(PCRP0); + regData |= (EnForceMode | PollLinkStatus | ForceDuplex | PauseFlowControlEtxErx); + regData &= ~(ForceLink | ForceSpeedMask); + regData |= (ForceSpeed10M); + //panic_printk("phy0 link partner is force 10M, we force to 10M Full duplex!regData = 0x%x\n", regData); + REG32(PCRP0) = regData; + } + } + //enable phy i/f + //set 0xbb804104 b0=1 + REG32(PCRP0) |= EnablePHYIf; + //panic_printk("phy0 link up, PCRP0 = 0x%x\n", REG32(PCRP0)); + } + else{//if port#0=link down + //recovery MAC AN setting and disable phy i/f + //(set 0xbb804104 b25=0 b20-18 0x7 b0=0) + regData = REG32(PCRP0); + regData &= ~(EnForceMode | EnablePHYIf); + regData |= (ForceSpeed1000M | ForceDuplex); + //panic_printk("phy0 link down, we reset phy0!regData = 0x%x\n", regData); + REG32(PCRP0) = regData; + } +} +#endif + static void interrupt_dsr_link(unsigned long task_priv) { #ifdef CONFIG_RTL_8198_ESD @@ -2964,8 +3622,13 @@ static void interrupt_dsr_link(unsigned long task_priv) newLinkPortMask=rtl865x_getPhysicalPortLinkStatus(); +#ifdef CONFIG_RTL_8197D_DYN_THR + rtl819x_setQosThreshold(curLinkPortMask, newLinkPortMask); +#endif + #if defined(CONFIG_RTL_REPORT_LINK_STATUS) - rtl865x_setLinkStatusFlag(newLinkPortMask); +// rtl865x_setLinkStatusFlag(newLinkPortMask); + rtl865x_setLinkStatusFlag(curLinkPortMask, newLinkPortMask); #endif #if defined(CONFIG_RTL_IGMP_SNOOPING) rtl865x_igmpSyncLinkStatus(); @@ -2978,6 +3641,14 @@ static void interrupt_dsr_link(unsigned long task_priv) #if defined(CONFIG_RTL_8196C) && defined(CONFIG_RTL_PHY_PATCH) re865x_checkPhySnr(); #endif + +#if defined(CONFIG_RTL_819XD) + if (rtl_port0Refined == 1) + { + rtl819x_port0_force_refined(); + } +#endif + curLinkPortMask=newLinkPortMask; #ifdef LINK_TASKLET @@ -2996,12 +3667,12 @@ __IRAM_GEN static inline void rtl_rx_interrupt_process(unsigned int status, stru } #endif - //if (status & (RX_DONE_IP_ALL)) + //if (status & (RX_DONE_IP_ALL | PKTHDR_DESC_RUNOUT_IP_ALL)) { #if defined(RX_TASKLET) if (rtl_rx_tasklet_running==0) { rtl_rx_tasklet_running=1; - REG32(CPUIIMR) &= ~(RX_DONE_IE_ALL); + REG32(CPUIIMR) &= ~(RX_DONE_IE_ALL | PKTHDR_DESC_RUNOUT_IE_ALL); rtl_rxSetTxDone(FALSE); tasklet_hi_schedule(&cp->rx_dsr_tasklet); } @@ -3044,6 +3715,10 @@ __IRAM_GEN static inline void rtl_link_change_interrupt_process(unsigned int sta #else interrupt_dsr_link((unsigned long)cp); #endif + #ifdef CONFIG_RTK_VOIP_PORT_LINK + if(cp->opened) + rtmsg_ifinfo_voip(RTM_LINKCHANGE, cp->dev, ~0U); + #endif } } #endif @@ -3060,6 +3735,18 @@ irqreturn_t interrupt_isr(int irq, void *dev_instance) REG32(CPUIISR) = status; status &= REG32(CPUIIMR); +#ifdef CONFIG_RTL_819X_SWCORE + cnt_swcore++; + if (status & (RX_DONE_IP_ALL)) + cnt_swcore_rx++; + if (status & TX_ALL_DONE_IP_ALL) + cnt_swcore_tx++; + if (status&LINK_CHANGE_IP) + cnt_swcore_link++; + if (status&(PKTHDR_DESC_RUNOUT_IP_ALL|MBUF_DESC_RUNOUT_IP_ALL)) + cnt_swcore_err++; +#endif + rtl_rx_interrupt_process(status, cp); rtl_tx_interrupt_process(status, cp); @@ -3118,12 +3805,48 @@ static void reset_hw_mib_counter(struct net_device *dev) } #endif +#if defined (CONFIG_RTL_8197D) +extern void rtl819x_poll_sw(void); +#endif + #ifdef CONFIG_RTL8196C_GREEN_ETHERNET int total_time_for_5_port = 15*HZ; int port_pwr_save_low = 0; #endif -#if defined(DYNAMIC_ADJUST_TASKLET) || defined(CONFIG_RTL8186_TR) || defined(CONFIG_RTL8196C_REVISION_B) || defined(CONFIG_RTL_8198) || defined(RTL8196C_EEE_MAC) || defined(RTL_CPU_QOS_ENABLED) +#ifdef CONFIG_RTL_8196E +void refine_phy_setting(void) +{ + int i, start_port = 0; + uint32 val; + + val = (REG32(BOND_OPTION) & BOND_ID_MASK); + if (val == BOND_8196ES) + return; + + if (val == BOND_8196EU) + start_port = 4; + + for (i=start_port; i<5; i++) { + rtl8651_setAsicEthernetPHYReg( i, 25, 0x6964); + rtl8651_getAsicEthernetPHYReg(i, 26, &val); + rtl8651_setAsicEthernetPHYReg(i, 26, ((val & (0xff00)) | 0x9E) ); + + rtl8651_getAsicEthernetPHYReg(i, 17, &val); + rtl8651_setAsicEthernetPHYReg( i, 17, ((val & (0xfff0)) | 0x8) ); + + rtl8651_getAsicEthernetPHYReg( i, 29, &val ); + if ((val & 0x8080) == 0x8080) { + rtl8651_getAsicEthernetPHYReg( i, 21, &val ); + rtl8651_setAsicEthernetPHYReg( i, 21, (val | 0x8000) ); + rtl8651_setAsicEthernetPHYReg( i, 21, (val & ~0x8000) ); + } + } + return; +} +#endif + +#if defined(DYNAMIC_ADJUST_TASKLET) || defined(CONFIG_RTL8186_TR) || defined(CONFIG_RTL8196C_REVISION_B) || defined(CONFIG_RTL_8198) || defined(RTL8196C_EEE_MAC) || defined(RTL_CPU_QOS_ENABLED) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) static void one_sec_timer(unsigned long task_priv) { unsigned long flags; @@ -3181,6 +3904,17 @@ static void one_sec_timer(unsigned long task_priv) cp->rx_byte_cnt = 0; #endif +#ifdef CONFIG_RTL_8197D_DYN_THR + if (_8197d_link_check == 0) { + newLinkPortMask=rtl865x_getPhysicalPortLinkStatus(); + + rtl819x_setQosThreshold(curLinkPortMask, newLinkPortMask); + + curLinkPortMask=newLinkPortMask; + _8197d_link_check = 1; + } +#endif + #ifdef CONFIG_RTL8196C_REVISION_B if ((REG32(REVR) == RTL8196C_REVISION_A) && (eee_enabled)) { int i, curr_sts; @@ -3266,7 +4000,8 @@ static void one_sec_timer(unsigned long task_priv) if ((val & 0xffff) != 0xAE04) { panic_printk(" ESD-1\n"); - do {} while(1); // reboot + //do {} while(1); // reboot + machine_restart(NULL); } if (need_to_check_esd2) { @@ -3279,7 +4014,8 @@ static void one_sec_timer(unsigned long task_priv) if ((val & 0xff) != 0xFC) { panic_printk(" ESD-2\n"); - do {} while(1); // reboot + //do {} while(1); // reboot + machine_restart(NULL); } } @@ -3287,20 +4023,27 @@ static void one_sec_timer(unsigned long task_priv) rtl8651_setAsicEthernetPHYReg( phy, 22, ((val & (0xff00)) | 0x17) ); rtl8651_getAsicEthernetPHYReg( phy, 30, &val ); + if (esd3_skip_one == 1) { + phy_reg30[phy] = BIT(31) | (val & 0xfff); + } + else if ((phy_reg30[phy] & 0xfff) != (val & 0xfff)) { if (diff_more_than_1((phy_reg30[phy] & 0xf), (val & 0xf)) || diff_more_than_1(((phy_reg30[phy] >> 4) & 0xf), ((val >> 4) & 0xf)) || diff_more_than_1(((phy_reg30[phy] >> 8) & 0xf), ((val >> 8) & 0xf)) ) { panic_printk(" ESD-3: old= 0x%x, new= 0x%x\n", phy_reg30[phy] & 0xfff, val & 0xfff); - do {} while(1); // reboot + //do {} while(1); // reboot + machine_restart(NULL); } phy_reg30[phy] = BIT(31) | (val & 0xfff); } } } - + if (esd3_skip_one == 1) { + esd3_skip_one = 0; + } one_second_counter = 0; } } @@ -3311,32 +4054,16 @@ static void one_sec_timer(unsigned long task_priv) #define panic_printk printk #endif if (_96c_esd_counter) { - - extern int is_fault; -#if 0 - if (++_96c_esd_counter >= 20) { - - if( (RTL_R32(PCRP4) & EnablePHYIf) == 0) - { - panic_printk(" ESD reboot...\n"); - is_fault = 1; - } - _96c_esd_counter = 1; - } -#else if( (RTL_R32(PCRP4) & EnablePHYIf) == 0) { if (++_96c_esd_reboot_counter >= 20) { panic_printk(" ESD reboot...\n"); - is_fault = 1; + machine_restart(NULL); } } else { _96c_esd_reboot_counter = 0; } -#endif - - } #endif @@ -3345,10 +4072,17 @@ static void one_sec_timer(unsigned long task_priv) { struct dev_priv *tmp_cp; - int portnum; + int portnum, startport=0; tmp_cp = ((struct dev_priv *)_rtl86xx_dev.dev[i]->priv); if(tmp_cp && tmp_cp->portmask && tmp_cp->opened) { - for(portnum=0;portnum<5;portnum++) + +#if defined(CONFIG_RTL_819XD) + if (rtl_port0Refined == 1) + { + startport = 1; + } +#endif + for(portnum=startport;portnum<5;portnum++) { if(tmp_cp->portmask & (1<<portnum)) break; @@ -3401,7 +4135,16 @@ static void one_sec_timer(unsigned long task_priv) } } } + +#if defined (CONFIG_RTL_8197D) || defined(CONFIG_RTL_8196D) + rtl819x_poll_sw(); +#endif + #endif +#ifdef CONFIG_RTL_8196E + refine_phy_setting(); +#endif + mod_timer(&cp->expire_timer, jiffies + HZ); //spin_unlock_irqrestore(&cp->lock, flags); @@ -3452,6 +4195,12 @@ static int re865x_open (struct net_device *dev) /* this is the first open dev */ /* should not call rtl865x_down() here */ /* rtl865x_down();*/ +#ifdef CONFIG_RTL_8198 + { + extern void disable_phy_power_down(void); + disable_phy_power_down(); + } +#endif //spin_lock_irqsave(&cp->lock, flags); local_irq_save(flags); rtk_queue_init(&rx_skb_queue); @@ -3500,7 +4249,7 @@ static int re865x_open (struct net_device *dev) netif_start_queue(dev); -#if defined(DYNAMIC_ADJUST_TASKLET) || defined(CONFIG_RTL8186_TR) || defined(CONFIG_RTL8196C_REVISION_B)|| defined(CONFIG_RTL_8198) || defined(RTL8196C_EEE_MAC) +#if defined(DYNAMIC_ADJUST_TASKLET) || defined(CONFIG_RTL8186_TR) || defined(CONFIG_RTL8196C_REVISION_B)|| defined(CONFIG_RTL_8198) || defined(RTL8196C_EEE_MAC) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) #if !defined(CONFIG_RTL8186_TR) if (dev->name[3] == '0') #endif @@ -3608,6 +4357,9 @@ static int re865x_close (struct net_device *dev) memset(re865x_restartNWayCtrl,0, sizeof(re865x_restartNWayCtrl)); #endif free_rx_skb(); + + rtk_queue_exit(&rx_skb_queue); + } memset(&cp->net_stats, '\0', sizeof(struct net_device_stats)); @@ -3623,10 +4375,14 @@ static int re865x_close (struct net_device *dev) #endif { rtl865x_disableDevPortForward(dev, cp); +#if !defined(CONFIG_RTL_8196C) + /*for lan dhcp client to renew ip address*/ + rtl865x_restartDevPHYNway(dev, cp); +#endif rtl8186_stop_hw(dev, cp); } -#if defined(DYNAMIC_ADJUST_TASKLET) || defined(CONFIG_RTL8186_TR) || defined(BR_SHORTCUT) || defined(CONFIG_RTL8196C_REVISION_B) || defined(CONFIG_RTL_8198) +#if defined(DYNAMIC_ADJUST_TASKLET) || defined(CONFIG_RTL8186_TR) || defined(BR_SHORTCUT) || defined(CONFIG_RTL8196C_REVISION_B) || defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) if (timer_pending(&cp->expire_timer)) del_timer_sync(&cp->expire_timer); #endif @@ -3651,6 +4407,11 @@ static int re865x_close (struct net_device *dev) cached_dev=NULL; #endif +#ifdef BR_SHORTCUT_C2 + if (dev == cached_dev2) + cached_dev2=NULL; +#endif + #ifdef CONFIG_RTL_HARDWARE_NAT reset_hw_mib_counter(dev); #endif @@ -3692,6 +4453,10 @@ static int re865x_pseudo_close (struct net_device *dev) if (dev == cached_dev) cached_dev=NULL; #endif +#ifdef BR_SHORTCUT_C2 + if (dev == cached_dev2) + cached_dev2=NULL; +#endif return SUCCESS; } #endif @@ -3841,6 +4606,11 @@ int re865x_setMCastTxInfo(struct sk_buff *skb,struct net_device *dev, rtl_nicTx_ struct rtl_multicastDataInfo multicastDataInfo; struct rtl_multicastFwdInfo multicastFwdInfo; +#ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + struct sk_buff *skb_wan=NULL; + rtl_nicTx_info nicTx_wan; +#endif + if((skb==NULL) || (dev==NULL) ||(nicTx==NULL)) { return -1; @@ -3883,6 +4653,33 @@ int re865x_setMCastTxInfo(struct sk_buff *skb,struct net_device *dev, rtl_nicTx_ } + #ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + //fix tim; upnp + if( vlan_bridge_multicast_tag) + { + if((cp->id == vlan_bridge_tag) && (nicTx->portlist & RTL_WANPORT_MASK)) + { + nicTx->portlist &= (~RTL_WANPORT_MASK); + skb_wan = skb_copy(skb, GFP_ATOMIC); + if(skb_wan!=NULL) + { + nicTx_wan.txIdx=0; + nicTx_wan.vid = vlan_bridge_multicast_tag; + nicTx_wan.portlist = RTL_WANPORT_MASK; + nicTx_wan.srcExtPort = 0; + nicTx_wan.flags = (PKTHDR_USED|PKT_OUTGOING); + nicTx_wan.tagport = RTL_WANPORT_MASK; + _dma_cache_wback_inv((unsigned long) skb_wan->data, skb_wan->len); + if (swNic_send((void *)skb_wan, skb_wan->data, skb_wan->len, &nicTx_wan) < 0) + { + dev_kfree_skb_any(skb_wan); + } + } + } + + }//hw-vlan + #endif + } } #if defined (CONFIG_RTL_MLD_SNOOPING) @@ -3980,6 +4777,58 @@ static inline int rtl_process_stp_tx(rtl_nicTx_info *txInfo) } #endif +#ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT +static inline int rtl_process_vlan_tag(rtl_nicTx_info *txInfo) +{ + + struct sk_buff *skb = NULL; + struct sk_buff *newskb; + struct net_device *dev; + struct dev_priv *cp; + + skb = txInfo->out_skb; + dev = skb->dev; + cp = dev->priv; + + if(vlan_tag && skb->srcPhyPort == RX_FROM_LOCAL) + { + if((rtl865x_curOpMode == GATEWAY_MODE && cp->id == vlanconfig[1].vid )||(rtl865x_curOpMode == BRIDGE_MODE)) + { + + newskb = NULL; + if (skb_cloned(skb)) + { + newskb = skb_copy(skb, GFP_ATOMIC); + if (newskb == NULL) + { + cp->net_stats.tx_dropped++; + dev_kfree_skb_any(skb); + return FAILED; + } + dev_kfree_skb_any(skb); + skb = newskb; + txInfo->out_skb = skb; + } + if (*((unsigned short *)(skb->data+ETH_ALEN*2)) != __constant_htons(ETH_P_8021Q)) + { + if (skb_headroom(skb) < VLAN_HLEN && skb_cow(skb, VLAN_HLEN) !=0 ) + { + printk("%s-%d: error! (skb_headroom(skb) == %d < %d). Enlarge it!\n", + __FUNCTION__, __LINE__, skb_headroom(skb), VLAN_HLEN); + while (1) ; + } + skb_push(skb, VLAN_HLEN); + memmove(skb->data, skb->data + VLAN_HLEN, VLAN_ETH_ALEN<<1); + *(uint16*)(&(skb->data[12])) = __constant_htons(ETH_P_8021Q); + *(uint16*)(&(skb->data[14])) = htons(vlan_tag)&0x0fff;// VID + *(uint8*)(&(skb->data[14])) |= (((uint8)vlan_host_pri)&0x7) << 5; + } + } + } + return SUCCESS; +} +#endif + //__MIPS16 #if defined(CONFIG_RTL_CUSTOM_PASSTHRU) static inline int rtl_process_passthru_tx(rtl_nicTx_info *txInfo) @@ -4029,7 +4878,11 @@ static inline int rtl_process_rtk_vlan_tx(rtl_nicTx_info *txInfo) newskb = NULL; if (skb_cloned(skb)) { + #if defined(CONFIG_RTL_ETH_PRIV_SKB) + newskb = priv_skb_copy(skb); + #else newskb = skb_copy(skb, GFP_ATOMIC); + #endif if (newskb == NULL) { cp->net_stats.tx_dropped++; @@ -4076,12 +4929,20 @@ static inline int rtl_preProcess_xmit(rtl_nicTx_info *txInfo) if(FAILED == retval) return retval; #endif + #if defined(CONFIG_RTL_HW_VLAN_SUPPORT) + retval = rtl_process_hw_vlan_tx(txInfo); + if(FAILED == retval) + return retval; + #endif #if defined(CONFIG_RTK_VLAN_SUPPORT) retval = rtl_process_rtk_vlan_tx(txInfo); if(FAILED == retval) return retval; #endif - + #ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + retval = rtl_process_vlan_tag(txInfo); + return retval; + #endif #if defined(CONFIG_RTL_REINIT_SWITCH_CORE) if(rtl865x_duringReInitSwtichCore==1) { dev_kfree_skb_any(txInfo->out_skb); @@ -4106,6 +4967,14 @@ static inline void rtl_hwLookup_txInfo(rtl_nicTx_info *txInfo) txInfo->flags = (PKTHDR_USED|PKTHDR_HWLOOKUP|PKTHDR_BRIDGING|PKT_OUTGOING); } +#ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT +static inline void rtl_hwLookup_txInfo2(rtl_nicTx_info *txInfo) +{ + txInfo->portlist = RTL8651_CPU_PORT; /* must be set 0x7 */ + txInfo->srcExtPort = PKTHDR_EXTPORT_LIST_P2;//2->7 + txInfo->flags = (PKTHDR_USED|PKTHDR_HWLOOKUP|PKTHDR_BRIDGING|PKT_OUTGOING); +} +#endif static inline int rtl_ip_option_check(struct sk_buff *skb) { int flag = FALSE; @@ -4135,6 +5004,12 @@ static inline int rtl_isHwlookup(struct sk_buff *skb, struct dev_priv *cp, uint3 flag = FALSE; } +#if defined(CONFIG_RTL_HW_VLAN_SUPPORT) + if((rtk_vlan_support_enable == 0) && ((!memcmp(cp->dev->name, "eth2", 5)) || + (!memcmp(cp->dev->name, "eth3", 5)) ||(!memcmp(cp->dev->name, "eth4", 5)))) + flag = FALSE; +#endif + #if defined (CONFIG_RTL_LOCAL_PUBLIC) //hyking: //when hw local public and sw localpublic exist at same time, @@ -4148,7 +5023,7 @@ static inline int rtl_isHwlookup(struct sk_buff *skb, struct dev_priv *cp, uint3 } else #endif if (flag==FALSE) { -#if defined(CONFIG_RTL_MULTI_LAN_DEV) || defined(CONFIG_POCKET_ROUTER_SUPPORT) || defined(CONFIG_RTK_VLAN_SUPPORT) +#if defined(CONFIG_RTL_MULTI_LAN_DEV) ||defined (CONFIG_POCKET_ROUTER_SUPPORT)||defined(CONFIG_RTK_VLAN_SUPPORT) assign_portmask: #endif *portlist = cp->portmask; @@ -4164,6 +5039,9 @@ static inline int rtl_fill_txInfo(rtl_nicTx_info *txInfo) cp = skb->dev->priv; txInfo->vid = cp->id; + #if defined(CONFIG_RTK_VOIP_QOS) + txInfo->priority = 0 ; + #endif #if defined(CONFIG_RTL_HW_QOS_SUPPORT) txInfo->priority= rtl_qosGetPriorityByVid(cp->id, skb->mark); #endif @@ -4171,17 +5049,31 @@ static inline int rtl_fill_txInfo(rtl_nicTx_info *txInfo) //default output queue is 0 txInfo->txIdx = 0; + #ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + txInfo->tagport = 0 ; + #endif + if((skb->data[0]&0x01)==0) { + if(rtl_isHwlookup(skb, cp, &portlist) == TRUE) { + #ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + if ( vlan_bridge_tag && cp->id == vlan_bridge_tag) + { + rtl_hwLookup_txInfo2(txInfo); + } + else + #endif rtl_hwLookup_txInfo(txInfo); } else { rtl_direct_txInfo(portlist, txInfo); } - } else { + } + else + { /*multicast process*/ rtl_direct_txInfo(cp->portmask,txInfo); #if defined (CONFIG_RTL_IGMP_SNOOPING) @@ -4197,6 +5089,13 @@ static inline int rtl_fill_txInfo(rtl_nicTx_info *txInfo) #endif } + + //for WAN Tag + #ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + if((vlan_bridge_tag && cp->id == vlan_bridge_tag) || (vlan_tag && cp->id == vlan_tag)) + txInfo->tagport = RTL_WANPORT_MASK; + #endif + if(txInfo->portlist==0) { dev_kfree_skb_any(skb); @@ -4205,6 +5104,26 @@ static inline int rtl_fill_txInfo(rtl_nicTx_info *txInfo) return SUCCESS; } +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) +static int rtl_bridge_wan_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct net_device *wan_dev = NULL; + if(!memcmp(lan_macaddr,skb->data+6, 6)) { + dev_kfree_skb_any(skb); + return 0; + } + //printk("[%s][%d]-skb->dev[%s],proto(0x%x)\n", __FUNCTION__, __LINE__, skb->dev->name,skb->protocol); + wan_dev = rtl_get_wan_from_vlan_info(); + + if(wan_dev){ + skb->dev = wan_dev; + wan_dev->netdev_ops->ndo_start_xmit(skb, wan_dev); + } + return 0; +} +#endif + + #define RTL_NIC_TX_RETRY_MAX (128) __MIPS16 __IRAM_FWD @@ -4215,29 +5134,27 @@ static int re865x_start_xmit(struct sk_buff *skb, struct net_device *dev) struct sk_buff *tx_skb; rtl_nicTx_info nicTx; + nicTx.out_skb = skb; retval = rtl_preProcess_xmit(&nicTx); if(FAILED == retval) - { return 0; - } + tx_skb = nicTx.out_skb; cp = tx_skb->dev->priv; if((cp->id==0) || (cp->portmask ==0)) { - dev_kfree_skb_any(tx_skb); + dev_kfree_skb_any(tx_skb); return 0; } -#if defined (CONFIG_RTL_IGMP_SNOOPING) + retval = rtl_fill_txInfo(&nicTx); if(FAILED == retval) - { return 0; - } -#if defined(CONFIG_RTL_QOS_PATCH) +#if defined(CONFIG_RTL_QOS_PATCH) || defined(CONFIG_RTK_VOIP_QOS) if(((struct sk_buff *)tx_skb)->srcPhyPort == QOS_PATCH_RX_FROM_LOCAL){ nicTx.priority = QOS_PATCH_HIGH_QUEUE_PRIO; nicTx.txIdx=RTL865X_SWNIC_TXRING_MAX_PKTDESC-1; //use the highest tx ring index, note: not RTL865X_SWNIC_TXRING_HW_PKTDESC-1 @@ -4247,7 +5164,10 @@ static int re865x_start_xmit(struct sk_buff *skb, struct net_device *dev) _dma_cache_wback_inv((unsigned long) tx_skb->data, tx_skb->len); tx_retry_cnt = 0; while(swNic_send((void *)tx_skb, tx_skb->data, tx_skb->len, &nicTx) < 0) - { + { + #if defined(CONFIG_RTL_PROC_DEBUG) + tx_ringFull_cnt++; + #endif swNic_txDone(nicTx.txIdx); if ((tx_retry_cnt++)>RTL_NIC_TX_RETRY_MAX) { dev_kfree_skb_any(tx_skb); @@ -4255,9 +5175,7 @@ static int re865x_start_xmit(struct sk_buff *skb, struct net_device *dev) } } -#else //CONFIG_RTL_IGMP_SNOOPING - #error "By default should define CONFIG_RTL_IGMP_SNOOPING" -#endif + rtl_pstProcess_xmit(cp,tx_skb->len); //cp->net_stats.tx_packets++; @@ -4358,10 +5276,12 @@ int re865x_priv_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { case RTL819X_IOCTL_READ_PORT_STATUS: rc = rtl819x_get_port_status(portnum,&port_status); //portnumber - if(rc != 0) + if(rc != 0) { return -EFAULT; - if (copy_to_user((void *)rq->ifr_data, (void *)&port_status, sizeof(struct lan_port_status))) + } + if (copy_to_user((void *)rq->ifr_data, (void *)&port_status, sizeof(struct lan_port_status))) { return -EFAULT; + } break; case RTL819X_IOCTL_READ_PORT_STATS: rc = rtl819x_get_port_stats(portnum,&port_stats); //portnumber @@ -4390,6 +5310,19 @@ int re865x_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) uint32 *pU32; #endif + if (cmd == RTL8651_IOCTL_CLEARBRSHORTCUTENTRY) + { + #ifdef BR_SHORTCUT + cached_dev=NULL; + #endif + + #ifdef BR_SHORTCUT_C2 + cached_dev2=NULL; + #endif + + return 0; + } + if (cmd != SIOCDEVPRIVATE) { #if defined(RTL819X_PRIV_IOCTL_ENABLE) @@ -4451,7 +5384,6 @@ int re865x_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) if(vlanconfig[i].isWan==TRUE) wanPortMask = vlanconfig[i].memPort; } - if (wanPortMask==0) { /* no wan port exist */ @@ -5043,6 +5975,26 @@ static const struct net_device_ops rtl819x_netdev_ops = { .ndo_change_mtu = rtl865x_set_mtu, }; + +#if !defined(CONFIG_COMPAT_NET_DEV_OPS) && defined(CONFIG_RTK_VLAN_NEW_FEATURE) +static const struct net_device_ops rtl819x_netdev_ops_bridge = { + .ndo_open = re865x_open, + .ndo_stop = re865x_close, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = rtl865x_set_hwaddr, + .ndo_set_multicast_list = re865x_set_rx_mode, + .ndo_get_stats = re865x_get_stats, + .ndo_do_ioctl = re865x_ioctl, + .ndo_start_xmit = rtl_bridge_wan_start_xmit, + .ndo_tx_timeout = re865x_tx_timeout, +#if defined(CP_VLAN_TAG_USED) + .ndo_vlan_rx_register = cp_vlan_rx_register, +#endif + .ndo_change_mtu = rtl865x_set_mtu, + +}; +#endif + #endif @@ -5136,9 +6088,11 @@ static int rtl865x_addAclForMldSnooping(struct rtl865x_vlanConfig* vlanConfig) } #if defined(CONFIG_RTL_IPTABLES_RULE_2_ACL) - #else - rtl865x_reConfigDefaultAcl(pVlanConfig[i].ifname); + if(rtl865x_curOpMode == WISP_MODE) #endif + rtl865x_reConfigDefaultAcl(pVlanConfig[i].ifname); + + } return SUCCESS; @@ -5231,6 +6185,9 @@ int __init re865x_probe (void) #if defined(CONFIG_RTL_REPORT_LINK_STATUS) || defined(CONFIG_RTK_VLAN_SUPPORT) struct proc_dir_entry *res_stats_root; #endif +#if defined(CONFIG_RTL_819XD)&&defined(CONFIG_RTL_8211DS_SUPPORT)&&defined(CONFIG_RTL_8197D) + uint32 reg_tmp=0; +#endif #if defined(CONFIG_RTL_REPORT_LINK_STATUS) struct proc_dir_entry *rtk_link_status_entry; @@ -5239,6 +6196,9 @@ int __init re865x_probe (void) #if defined(CONFIG_RTK_VLAN_SUPPORT) struct proc_dir_entry *res_stats; struct proc_dir_entry *rtk_vlan_support_entry; +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) + struct proc_dir_entry *rtk_vlan_management_entry; +#endif #if defined(CONFIG_819X_PHY_RW)//#if defined(CONFIG_RTK_VLAN_FOR_CABLE_MODEM) uint32 portnum; char port_mibEntry_name[10]; @@ -5248,6 +6208,12 @@ int __init re865x_probe (void) #endif //#if defined(CONFIG_819X_PHY_RW) #endif +#if defined(CONFIG_RTL_HW_VLAN_SUPPORT) + struct proc_dir_entry *rtl_hw_vlan_support_entry; + struct proc_dir_entry *rtl_hw_vlan_tagged_bridge_multicast_entry; + memset(hw_vlan_info, 0, PORT_NUMBER*sizeof(struct hw_vlan_port_setting)); +#endif + #if defined (CONFIG_RTL_LOCAL_PUBLIC) struct rtl865x_interface_info ifInfo; #endif @@ -5255,6 +6221,11 @@ int __init re865x_probe (void) #if defined(PATCH_GPIO_FOR_LED) int port; #endif + +#ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + struct proc_dir_entry *rtk_vlan_wan_tag_support_entry; +#endif + //WRITE_MEM32(PIN_MUX_SEL_2, 0x7<<21); rtlglue_printf("\n\n\nProbing RTL8186 10/100 NIC-kenel stack size order[%d]...\n", THREAD_SIZE_ORDER); @@ -5262,19 +6233,15 @@ int __init re865x_probe (void) REG32(CPUICR) &= ~(TXCMD | RXCMD); rxMbufRing=NULL; - /*Initial ASIC table*/ -#ifdef CONFIG_RTL8198_REVISION_B - if (REG32(BSP_REVR) >= BSP_RTL8198_REVISION_B) +#if defined(CONFIG_RTL_819XD) + if ((REG32(REVR) == 0x8197C000) || (REG32(REVR) == 0x8197C001)) { - REG32(SYS_CLK_MAG)&=(~(SYS_SW_RESET)); - mdelay(300); - REG32(SYS_CLK_MAG)|=(SYS_SW_RESET); - mdelay(50); + rtl_port0Refined = 1; } - else #endif - FullAndSemiReset(); + /*Initial ASIC table*/ + FullAndSemiReset(); { rtl8651_tblAsic_InitPara_t para; @@ -5291,7 +6258,7 @@ int __init re865x_probe (void) #ifdef CONFIG_RTL_LAYERED_ASIC_DRIVER_L3 INIT_CHECK(rtl865x_initAsicL3()); #endif -#if defined(CONFIG_RTL_LAYERED_ASIC_DRIVER_L4) && defined(CONFIG_RTL_8198) +#if defined(CONFIG_RTL_LAYERED_ASIC_DRIVER_L4) && (defined(CONFIG_RTL_8198) ||defined(CONFIG_RTL_8196CT) ||defined(CONFIG_RTL_819XDT)) INIT_CHECK(rtl865x_initAsicL4()); #endif @@ -5370,7 +6337,11 @@ int __init re865x_probe (void) #ifdef BR_SHORTCUT cached_dev=NULL; #endif +#ifdef BR_SHORTCUT_C2 + cached_dev2=NULL; +#endif /*init PHY LED style*/ +#if !defined(CONFIG_RTL_819XD) && !defined(CONFIG_RTL_8196E) #if defined(CONFIG_RTL865X_BICOLOR_LED) #ifdef BICOLOR_LED_VENDOR_BXXX REG32(LEDCR) |= (1 << 19); // 5 ledmode set to 1 for bi-color LED @@ -5387,11 +6358,18 @@ int __init re865x_probe (void) #else /* CONFIG_RTL865X_BICOLOR_LED */ /* config LED mode */ +#if defined(CONFIG_RTK_VOIP_BOARD) + WRITE_MEM32(LEDCR, 0x00055500 ); // 15 LED + //avoiv bad voip quality + WRITE_MEM32(0xb8000048, REG32(0xb8000048)&0xfffffff3); +#else WRITE_MEM32(LEDCR, 0x00000000 ); // 15 LED +#endif WRITE_MEM32(SWTAA, PORT5_PHY_CONTROL); WRITE_MEM32(TCR0, 0x000002C7); //8651 demo board default: 15 LED boards WRITE_MEM32(SWTACR, CMD_FORCE | ACTION_START); // force add #endif /* CONFIG_RTL865X_BICOLOR_LED */ +#endif /*2007-12-19*/ #if defined(CONFIG_RTK_VLAN_SUPPORT) @@ -5401,6 +6379,10 @@ int __init re865x_probe (void) #endif +#if defined(CONFIG_RTL_819XD)&&defined(CONFIG_RTL_8211DS_SUPPORT)&&defined(CONFIG_RTL_8197D) + rtl8651_getAsicEthernetPHYReg(0x6, 0, ®_tmp); + rtl_setPortMask(reg_tmp); +#endif INIT_CHECK(rtl865x_init()); @@ -5465,6 +6447,13 @@ int __init re865x_probe (void) dev->open = re865x_open; dev->stop = re865x_close; dev->set_multicast_list = re865x_set_rx_mode; + #if defined(CONFIG_RTK_VLAN_NEW_FEATURE) + if(memcmp((vlanconfig[i].ifname), RTL_DRV_LAN_P7_NETIF_NAME, 4) == 0){ + memcpy((char*)dev->name, (char*)(&(vlanconfig[i].ifname)), 5); + dev->hard_start_xmit = rtl_bridge_wan_start_xmit; + } + else + #endif dev->hard_start_xmit = re865x_start_xmit; dev->get_stats = re865x_get_stats; dev->do_ioctl = re865x_ioctl; @@ -5481,7 +6470,14 @@ int __init re865x_probe (void) #endif #else - dev->netdev_ops = &rtl819x_netdev_ops; + #if defined(CONFIG_RTK_VLAN_NEW_FEATURE) + if(memcmp((vlanconfig[i].ifname), RTL_DRV_LAN_P7_NETIF_NAME, 4) == 0){ + memcpy((char*)dev->name, (char*)(&(vlanconfig[i].ifname)), 5); + dev->netdev_ops = &rtl819x_netdev_ops_bridge; + } + else + #endif + dev->netdev_ops = &rtl819x_netdev_ops; #endif dev->watchdog_timeo = TX_TIMEOUT; #if 0 @@ -5493,6 +6489,7 @@ int __init re865x_probe (void) dev->irq = BSP_SWCORE_IRQ; rc = register_netdev(dev); + if(!rc){ _rtl86xx_dev.dev[i]=dev; rtl_add_ps_drv_netif_mapping(dev,vlanconfig[i].ifname); @@ -5522,7 +6519,7 @@ int __init re865x_probe (void) #if defined(CONFIG_RTL_REPORT_LINK_STATUS) /*FIXME if mutliple-WAN*/ wan_linkStatus[0]=0; - rtk_link_status_entry=create_proc_entry("up_flag",0,res_stats_root); + rtk_link_status_entry=create_proc_entry("up_event",0,res_stats_root); if(rtk_link_status_entry) { rtk_link_status_entry->read_proc=rtk_link_status_read; @@ -5534,7 +6531,8 @@ int __init re865x_probe (void) } #if defined(CONFIG_RTL_MULTIPLE_WAN) - retVal = rtl_config_multipleWan_netif(RTL_MULTIWAN_ADD); + rtl_config_multipleWan_netif(RTL_MULTIWAN_ADD); + rtl865x_addMultiCastNetif(); rtl_regist_multipleWan_dev(); #endif @@ -5557,7 +6555,7 @@ int __init re865x_probe (void) rtl_setIgmpSnoopingModuleDevInfo(nicIgmpModuleIndex, &devInfo); } #endif - rtl_setIpv4UnknownMCastFloodMap(nicIgmpModuleIndex, 0x0); + rtl_setIpv4UnknownMCastFloodMap(nicIgmpModuleIndex, 0xFFFFFFFF); rtl_setIpv6UnknownMCastFloodMap(nicIgmpModuleIndex, 0xFFFFFFFF); curLinkPortMask=rtl865x_getPhysicalPortLinkStatus(); @@ -5645,7 +6643,9 @@ int __init re865x_probe (void) #endif rtl8651_initStormCtrl(); -#if (defined(CONFIG_RTL_8198)) + rtl819x_eee_proc_init(); + +#if defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) // initial proc for phyRegTest phyRegTest_init(); #endif @@ -5667,8 +6667,43 @@ int __init re865x_probe (void) rtk_vlan_support_entry->read_proc=rtk_vlan_support_read; rtk_vlan_support_entry->write_proc=rtk_vlan_support_write; } + +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) + memset(&management_vlan, 0, sizeof(struct vlan_info*)); + rtk_vlan_management_entry = create_proc_entry("rtk_vlan_management_entry", 0, NULL); + if(rtk_vlan_management_entry) + { + rtk_vlan_management_entry->read_proc=rtk_vlan_management_read; + rtk_vlan_management_entry->write_proc=rtk_vlan_management_write; + } +#endif #endif +#ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT + rtk_vlan_wan_tag_support_entry = create_proc_entry("rtk_vlan_wan_tag",0,NULL); + if (rtk_vlan_wan_tag_support_entry) + { + rtk_vlan_wan_tag_support_entry->read_proc=rtk_vlan_wan_tag_support_read; + rtk_vlan_wan_tag_support_entry->write_proc=rtk_vlan_wan_tag_support_write; + } +#endif + +#if defined(CONFIG_RTL_HW_VLAN_SUPPORT) + rtl_hw_vlan_support_entry = create_proc_entry("rtl_hw_vlan_support", 0, NULL); + if (rtl_hw_vlan_support_entry) + { + rtl_hw_vlan_support_entry->read_proc=rtl_hw_vlan_support_read; + rtl_hw_vlan_support_entry->write_proc=rtl_hw_vlan_support_write; + } + rtl_hw_vlan_tagged_bridge_multicast_entry = create_proc_entry("rtl_hw_vlan_tagged_mc", 0, NULL); + if (rtl_hw_vlan_tagged_bridge_multicast_entry) + { + rtl_hw_vlan_tagged_bridge_multicast_entry->read_proc=rtl_hw_vlan_tagged_bridge_multicast_read; + rtl_hw_vlan_tagged_bridge_multicast_entry->write_proc=rtl_hw_vlan_tagged_bridge_multicast_write; + } +#endif + + #if defined(CONFIG_819X_PHY_RW) //#if defined(CONFIG_RTK_VLAN_FOR_CABLE_MODEM) rtl_phy = create_proc_entry("rtl_phy_status",0,NULL); @@ -5766,6 +6801,18 @@ int __init re865x_probe (void) #if defined(TX_TASKLET) rtl_tx_tasklet_running=0; #endif +#if defined (CONFIG_RTL_SOCK_DEBUG) + rtl865x_creatSockDebugProc(); +#endif + +#if 0//def CONFIG_RTL_ULINKER //led + REG32(PIN_MUX_SEL_2) = REG32(PIN_MUX_SEL_2) | 0x00003000; + REG32(PABCD_CNR) = REG32(PABCD_CNR) & ~(0x00004000); + REG32(PABCD_DIR) = REG32(PABCD_DIR) | 0x00004000; + REG32(PABCD_DAT) = REG32(PABCD_DAT) & ~(0x00004000); +#endif + + memset(&rx_skb_queue, 0, sizeof(struct ring_que)); return 0; } @@ -5925,10 +6972,12 @@ EXPORT_SYMBOL(priv_skb_copy); static void __exit re865x_exit (void) { -#ifdef RTL865X_DRIVER_DEBUG_FLAG +#if defined(CONFIG_RTL_PROC_DEBUG)||defined(CONFIG_RTL_DEBUG_TOOL) + rtl865x_proc_debug_cleanup(); #endif + #if defined(CONFIG_PROC_FS) && defined(CONFIG_NET_SCHED) && defined(CONFIG_RTL_LAYERED_DRIVER) #if defined(CONFIG_RTL_HW_QOS_SUPPORT) rtl865x_exitOutputQueue(); @@ -5945,8 +6994,236 @@ static void __exit re865x_exit (void) return; } +#ifdef CONFIG_RTK_FAKE_ETH + +int32 rtl8651_EthernetPowerDown(void) +{ + uint32 statCtrlReg0; + int i; + + //## from rtl8651_setAllAsicEthernetPHYPowerDown + for (i=0; i<5; i++) { + + /* read current PHY reg 0 value */ + rtl8651_getAsicEthernetPHYReg( i, 0, &statCtrlReg0 ); + + REG32(PCRP0+(i*4)) |= EnForceMode; + statCtrlReg0 |= POWER_DOWN; + + /* write PHY reg 0 */ + rtl8651_setAsicEthernetPHYReg( i, 0, statCtrlReg0 ); + } + //####################################### + + //then set bit 9 of 0xb800-0010 to 0. deactive switch core + + REG32(SYS_CLK_MAG)&=(~(SYS_SW_CLK_ENABLE)); + + return SUCCESS; +} + +int re865x_ioctl_fake (struct net_device *dev, struct ifreq *rq, int cmd) +{ + int32 rc = 0; + unsigned long *data; + int32 args[4]; + int32 * pRet; + + data = (unsigned long *)rq->ifr_data; + + if (copy_from_user(args, data, 4*sizeof(unsigned long))) + { + return -EFAULT; + } + + switch (args[0]) + { + case RTL8651_IOCTL_GETWANLINKSTATUS: + { + pRet = (int32 *)args[3]; + *pRet = FAILED; + rc = SUCCESS; + + break; + } + + case RTL8651_IOCTL_GETWANLINKSPEED: + { + int wanPortMask; + + pRet = (int32 *)args[3]; + *pRet = FAILED; + rc = SUCCESS; + + wanPortMask = 0; + + /* no wan port exist */ + break; + } + default: + rc = SUCCESS; + break; + } + + return rc; + +} + + +static int rtl865x_set_mtu_fake(struct net_device *dev, int new_mtu) +{ + unsigned long flags; + + local_irq_save(flags); + dev->mtu = new_mtu; + + local_irq_restore(flags); + + return SUCCESS; +} + +static int rtl865x_set_hwaddr_fake(struct net_device *dev, void *addr) +{ + unsigned long flags; + int i; + unsigned char *p; + + p = ((struct sockaddr *)addr)->sa_data; + local_irq_save(flags); + + for (i = 0; i<ETHER_ADDR_LEN; ++i) { + dev->dev_addr[i] = p[i]; + } + + local_irq_restore(flags); + return SUCCESS; +} + +static int re865x_start_xmit_fake(struct sk_buff *skb, struct net_device *dev) +{ + + dev_kfree_skb_any(skb); + return 0; + +} + +static int re865x_open_fake (struct net_device *dev) +{ + struct dev_priv *cp; + + cp = dev->priv; + //cp = netdev_priv(dev); + if (cp->opened) + return SUCCESS; + + cp->opened = 1; + netif_start_queue(dev); + return SUCCESS; +} + + +static int re865x_close_fake (struct net_device *dev) +{ + struct dev_priv *cp; + + cp = dev->priv; +// cp = netdev_priv(dev); + + if (!cp->opened) + return SUCCESS; + netif_stop_queue(dev); + +// memset(&cp->net_stats, '\0', sizeof(struct net_device_stats)); + cp->opened = 0; + +#ifdef BR_SHORTCUT + if (dev == cached_dev) + cached_dev=NULL; +#endif + return SUCCESS; +} + +#if defined(CONFIG_COMPAT_NET_DEV_OPS) +#else +static const struct net_device_ops rtl819x_netdev_ops_fake = { + .ndo_open = re865x_open_fake, + .ndo_stop = re865x_close_fake, +// .ndo_validate_addr = eth_validate_addr_fake, + .ndo_set_mac_address = rtl865x_set_hwaddr_fake, +// .ndo_set_multicast_list = re865x_set_rx_mode_fake, +// .ndo_get_stats = re865x_get_stats_fake, + .ndo_do_ioctl = re865x_ioctl_fake, + .ndo_start_xmit = re865x_start_xmit_fake, +// .ndo_tx_timeout = re865x_tx_timeout_fake, +//#if defined(CP_VLAN_TAG_USED) +// .ndo_vlan_rx_register = cp_vlan_rx_register, +//endif + .ndo_change_mtu = rtl865x_set_mtu_fake, + +}; +#endif + + +int __init re865x_probe_fake (void) +{ + struct net_device *dev; + struct dev_priv *dp; + int rc; + + dev = alloc_etherdev(sizeof(struct dev_priv)); + if (!dev) { + printk("failed to allocate dev %d", 0); + return -1; + } + + dp = dev->priv; + memset(dp,0,sizeof(*dp)); + dp->dev = dev; + + memcpy((char*)dev->dev_addr,(char*)(&(vlanconfig[0].mac)),ETHER_ADDR_LEN); //mark_FIXME. + +#if defined(CONFIG_COMPAT_NET_DEV_OPS) + dev->open = re865x_open_fake; + dev->stop = re865x_close_fake; + //dev->set_multicast_list = re865x_set_rx_mode; + dev->hard_start_xmit = re865x_start_xmit_fake; + //dev->get_stats = re865x_get_stats; + dev->do_ioctl = re865x_ioctl_fake; + //dev->tx_timeout = re865x_tx_timeout; + dev->set_mac_address = rtl865x_set_hwaddr_fake; + dev->change_mtu = rtl865x_set_mtu_fake; +#else + dev->netdev_ops = &rtl819x_netdev_ops_fake; +#endif + + dev->watchdog_timeo = TX_TIMEOUT; + + rc = register_netdev(dev); + +#ifdef BR_SHORTCUT + cached_dev=NULL; +#endif + + if(rc) + rtlglue_printf("Failed to allocate eth%d\n", 0); + + rc = rtl8651_EthernetPowerDown(); + + return 0; +} +static void __exit re865x_exit_fake (void) +{ + return ; +} +#endif + +#ifdef CONFIG_RTK_FAKE_ETH +module_init(re865x_probe_fake); +module_exit(re865x_exit_fake); +#else module_init(re865x_probe); module_exit(re865x_exit); +#endif /* @func enum RTL_RESULT | rtl865x_init | Initialize light rome driver and RTL865x ASIC. @@ -6024,7 +7301,7 @@ int32 rtl865x_init(void) #endif /*layer4*/ -#if defined(CONFIG_RTL_LAYERED_DRIVER_L4) && defined(CONFIG_RTL_8198) +#if defined(CONFIG_RTL_LAYERED_DRIVER_L4) && (defined(CONFIG_RTL_8198) ||defined(CONFIG_RTL_8196CT) ||defined(CONFIG_RTL_819XDT)) rtl865x_nat_init(); #endif @@ -6036,7 +7313,8 @@ int32 rtl865x_init(void) rtl8651_setAsicOutputQueueNumber(CPU, RTL_CPU_RX_RING_NUM); -#ifdef RTL865X_DRIVER_DEBUG_FLAG +/*CONFIG_RTL_PROC_DEBUG:marco forproc debug. CONFIG_RTL_DEBUG_TOOL: marco for debug tool*/ +#if defined(CONFIG_RTL_PROC_DEBUG)||defined(CONFIG_RTL_DEBUG_TOOL) rtl865x_proc_debug_init(); #endif @@ -6177,6 +7455,19 @@ int32 rtl865x_config(struct rtl865x_vlanConfig vlanconfig[]) rtl865x_initOutputQueue((uint8 **)netIfName); #endif + #ifdef CONFIG_RTK_VOIP_QOS + rtl8651_setAsicOutputQueueNumber(0,QNUM3); + rtl8651_setAsicOutputQueueNumber(1,QNUM3); + rtl8651_setAsicOutputQueueNumber(2,QNUM3); + rtl8651_setAsicOutputQueueNumber(3,QNUM3); + rtl8651_setAsicOutputQueueNumber(4,QNUM3); + rtl8651_setAsicOutputQueueNumber(6,QNUM2); + REG32(CPUQIDMCR0)=0x55550000; + rtl8651_setAsicPriorityDecision(2, 1, 2, 1, 1); + rtl8651_resetAsicOutputQueue(); + #endif + + #if defined (CONFIG_RTL_UNKOWN_UNICAST_CONTROL) { rtl865x_tblAsicDrv_rateLimitParam_t asic_rl; @@ -6315,7 +7606,7 @@ static int re865x_reInitIgmpSetting(int mode) } //rtl_setIgmpSnoopingModuleUnknownMCastFloodMap(nicIgmpModuleIndex, 0x0); - rtl_setIpv4UnknownMCastFloodMap(nicIgmpModuleIndex, 0x0); + rtl_setIpv4UnknownMCastFloodMap(nicIgmpModuleIndex, 0xFFFFFFFF); rtl_setIpv6UnknownMCastFloodMap(nicIgmpModuleIndex, 0xFFFFFFFF); } @@ -6365,7 +7656,7 @@ static int32 rtl_reinit_hw_table(void) rtl865x_reInitEventMgr(); /*l4*/ - #if defined(CONFIG_RTL_LAYERED_DRIVER_L4) && defined(CONFIG_RTL_8198) + #if defined(CONFIG_RTL_LAYERED_DRIVER_L4) && (defined(CONFIG_RTL_8198) ||defined(CONFIG_RTL_8196CT) ||defined(CONFIG_RTL_819XDT)) rtl865x_nat_reinit(); #endif @@ -6515,6 +7806,7 @@ static int rtl_config_lanwan_dev_vlanconfig(int mode) vlanconfig[1].untagSet = RTL_WANPORT_MASK; ((struct dev_priv *)_rtl86xx_dev.dev[1]->priv)->portmask = RTL_WANPORT_MASK; //eth1 ((struct dev_priv *)_rtl86xx_dev.dev[1]->priv)->id = RTL_WANVLANID; //eth1 + #endif //endif CONFIG_POCKET_ROUTER_SUPPORT #else @@ -6612,6 +7904,9 @@ static int rtl_config_vlanconfig(int mode) int32 rtl865x_changeOpMode(int mode) { +#ifdef CONFIG_RTK_FAKE_ETH + return SUCCESS; +#endif #if defined (CONFIG_RTL_LOCAL_PUBLIC) struct rtl865x_interface_info ifInfo; #endif @@ -6763,12 +8058,18 @@ int32 rtl865x_changeOpMode(int mode) //setAsicOperationLayer rtl_config_operation_layer(mode); + #if defined(CONFIG_RTL_MULTIPLE_WAN) + if(rtl865x_curOpMode != GATEWAY_MODE) + rtl865xC_setNetDecisionPolicy(NETIF_PORT_BASED); + #endif +#ifdef CONFIG_RTL_LAYERED_DRIVER_L3 //always init the default route... if(rtl8651_getAsicOperationLayer() >2) { rtl865x_addRoute(0,0,0,RTL_DRV_WAN0_NETIF_NAME,0); } +#endif //checksum control register switch(mode) @@ -6879,6 +8180,7 @@ static int32 reinit_vlan_configure(struct rtl865x_vlanConfig new_vlanconfig[]) #if defined(CONFIG_RTL_MULTIPLE_WAN) rtl_config_multipleWan_netif(RTL_MULTIWAN_ADD); + rtl865x_addMultiCastNetif(); #endif #if defined(CONFIG_RTK_VLAN_SUPPORT) @@ -6907,12 +8209,76 @@ static int32 reinit_vlan_configure(struct rtl865x_vlanConfig new_vlanconfig[]) rtl865x_setPortToNetif(pvlanconfig[j].ifname, i); } } + +#if defined(CONFIG_RTL_HW_VLAN_SUPPORT) + if(rtl_hw_vlan_enable) + { + if((hw_vlan_info[1].vlan_port_enabled)&&hw_vlan_info[1].vlan_port_tag){ + rtl865x_setVlanPortTag(vlanconfig[1].vid,RTL_WANPORT_MASK,1); //eth1 vlan port 1 tag + } + swNic_setVlanPortTag(RTL_WANPORT_MASK);//packet from CPU, HW add tag + + if((hw_vlan_info[0].vlan_port_enabled)&&(hw_vlan_info[0].vlan_port_bridge == 1)){ + rtl865x_addVlan(hw_vlan_info[0].vlan_port_vid); + rtl865x_addVlanPortMember(hw_vlan_info[0].vlan_port_vid, RTL_LANPORT_MASK_4|RTL_WANPORT_MASK); + rtl865x_setVlanPortTag(hw_vlan_info[0].vlan_port_vid, RTL_WANPORT_MASK,1); //wan port tag + if(hw_vlan_info[0].vlan_port_tag){ + rtl865x_setVlanPortTag(hw_vlan_info[0].vlan_port_vid, RTL_LANPORT_MASK_4,1); //wan port tag + } + rtl865x_setVlanFilterDatabase(hw_vlan_info[0].vlan_port_vid,0); + rtl8651_setAsicPvid(0, hw_vlan_info[0].vlan_port_vid); //port vid + rtl865x_setPortForward(RTL_LANPORT_MASK_4, TRUE); + } + if((hw_vlan_info[2].vlan_port_enabled)&&(hw_vlan_info[2].vlan_port_bridge == 1)){ + rtl865x_addVlan(hw_vlan_info[2].vlan_port_vid); + rtl865x_addVlanPortMember(hw_vlan_info[2].vlan_port_vid, RTL_LANPORT_MASK_3|RTL_WANPORT_MASK); + rtl865x_setVlanPortTag(hw_vlan_info[2].vlan_port_vid, RTL_WANPORT_MASK,1); //wan port tag + if(hw_vlan_info[2].vlan_port_tag){ + rtl865x_setVlanPortTag(hw_vlan_info[2].vlan_port_vid, RTL_LANPORT_MASK_3,1); //wan port tag + } + rtl865x_setVlanFilterDatabase(hw_vlan_info[2].vlan_port_vid,0); + rtl8651_setAsicPvid(1, hw_vlan_info[2].vlan_port_vid); //port vid + rtl865x_setPortForward(RTL_LANPORT_MASK_3, TRUE); + } + if((hw_vlan_info[3].vlan_port_enabled)&&(hw_vlan_info[3].vlan_port_bridge == 1)){ + rtl865x_addVlan(hw_vlan_info[3].vlan_port_vid); + rtl865x_addVlanPortMember(hw_vlan_info[3].vlan_port_vid, RTL_LANPORT_MASK_2|RTL_WANPORT_MASK); + rtl865x_setVlanPortTag(hw_vlan_info[3].vlan_port_vid, RTL_WANPORT_MASK,1); //wan port tag + if(hw_vlan_info[3].vlan_port_tag){ + rtl865x_setVlanPortTag(hw_vlan_info[3].vlan_port_vid, RTL_LANPORT_MASK_2,1); //wan port tag + } + rtl865x_setVlanFilterDatabase(hw_vlan_info[3].vlan_port_vid,0); + rtl8651_setAsicPvid(2, hw_vlan_info[3].vlan_port_vid); //port vid + rtl865x_setPortForward(RTL_LANPORT_MASK_2, TRUE); + } + if((hw_vlan_info[4].vlan_port_enabled)&&(hw_vlan_info[4].vlan_port_bridge == 1)){ + rtl865x_addVlan(hw_vlan_info[4].vlan_port_vid); + rtl865x_addVlanPortMember(hw_vlan_info[4].vlan_port_vid, RTL_LANPORT_MASK_1|RTL_WANPORT_MASK); + rtl865x_setVlanPortTag(hw_vlan_info[4].vlan_port_vid, RTL_WANPORT_MASK,1); //wan port tag + if(hw_vlan_info[4].vlan_port_tag){ + rtl865x_setVlanPortTag(hw_vlan_info[4].vlan_port_vid, RTL_LANPORT_MASK_1,1); //wan port tag + } + rtl865x_setVlanFilterDatabase(hw_vlan_info[4].vlan_port_vid,0); + rtl8651_setAsicPvid(3, hw_vlan_info[4].vlan_port_vid); //port vid + rtl865x_setPortForward(RTL_LANPORT_MASK_1, TRUE); + } + } + else{ + swNic_setVlanPortTag(0); + } +#endif + #ifdef CONFIG_RTL_STP re865x_stp_mapping_reinit(); #endif rtl_config_operation_layer(rtl865x_curOpMode); + #if defined(CONFIG_RTL_MULTIPLE_WAN) + if(rtl865x_curOpMode != GATEWAY_MODE) + rtl865xC_setNetDecisionPolicy(NETIF_PORT_BASED); + #endif + return SUCCESS; } #if defined(CONFIG_RTL_REPORT_LINK_STATUS) @@ -6943,6 +8309,216 @@ static int32 rtk_link_status_write( struct file *filp, const char *buff,unsigned } #endif #if defined(CONFIG_RTK_VLAN_SUPPORT) +#ifdef CONFIG_RTK_VLAN_WAN_TAG_SUPPORT +static int32 rtk_vlan_wan_tag_getportmask(int bridge_port) +{ + int32 port_mask = 0x80;// PKTHDR_EXTPORT_LIST_P2 2=> bit 7 + + if(vlan_bridge_port&(1<<3)) + port_mask |= RTL_LANPORT_MASK_1; + + if(vlan_bridge_port&(1<<2)) + port_mask |= RTL_LANPORT_MASK_2; + + if(vlan_bridge_port&(1<<1)) + port_mask |= RTL_LANPORT_MASK_3; + + if(vlan_bridge_port&(1<<0)) + port_mask |= RTL_LANPORT_MASK_4; + + return port_mask; +} +static int32 rtk_vlan_wan_tag_support_write( struct file *filp, const char *buff,unsigned long len, void *data ) +{ + char tmpbuf[100]; + int lan_portmask; + int num ; + int i=0; + int j=0; + struct net_device *dev; + struct dev_priv *dp; + #ifdef CONFIG_RTL_IGMP_SNOOPING + int ret = 0; + rtl_multicastDeviceInfo_t devInfo; + #endif + + if (buff && !copy_from_user(tmpbuf, buff, len)) + { + + num = sscanf(tmpbuf, "%d %d %d %d %d", &vlan_tag, &vlan_host_pri, &vlan_bridge_tag, &vlan_bridge_port,&vlan_bridge_multicast_tag); + if (num != 5) { + printk("invalid rtk_vlan_wan_tag_support_write parameter!\n"); + return len; + } + if(rtl865x_curOpMode == WISP_MODE) //not support in WISP mode + { + vlan_tag = 0; + vlan_bridge_tag = 0; + } + else if(rtl865x_curOpMode == BRIDGE_MODE) + { + vlan_bridge_tag = 0; + } + if(vlan_bridge_tag == vlan_tag) + vlan_bridge_tag = 0; + + rtl_config_rtkVlan_vlanconfig(rtl865x_curOpMode); + + //Reset PPPoE vlan id to original + vlanconfig[VLAN_CONFIG_PPPOE_INDEX].vid = RTL_WANVLANID; + + + lan_portmask = 0; + + if(vlan_bridge_tag) + { + lan_portmask = rtk_vlan_wan_tag_getportmask(vlan_bridge_port); + vlanconfig[2] .vid = vlan_bridge_tag; + vlanconfig[2].memPort = lan_portmask|RTL_WANPORT_MASK; + vlanconfig[2].untagSet = lan_portmask; + + //need verify + vlanconfig[2].fid = 1; + ((struct dev_priv *)_rtl86xx_dev.dev[2]->priv)->portmask = lan_portmask|RTL_WANPORT_MASK; + ((struct dev_priv *)_rtl86xx_dev.dev[2]->priv)->id = vlan_bridge_tag; //eth2 + //vlanconfig[0].vid= RTL_LANVLANID; + vlanconfig[0].memPort = RTL_LANPORT_MASK &(~lan_portmask); + vlanconfig[0].untagSet = RTL_LANPORT_MASK &(~lan_portmask); + ((struct dev_priv *)_rtl86xx_dev.dev[0]->priv)->portmask = RTL_LANPORT_MASK &(~lan_portmask); //eth0 + //((struct dev_priv *)_rtl86xx_dev.dev[0]->priv)->id = RTL_LANVLANID; + } + + if(rtl865x_curOpMode == GATEWAY_MODE && vlan_tag) + { + vlanconfig[1].vid = vlan_tag; + vlanconfig[1].memPort = RTL_WANPORT_MASK; + vlanconfig[1].untagSet = 0; // need tag + ((struct dev_priv *)_rtl86xx_dev.dev[1]->priv)->portmask = RTL_WANPORT_MASK; //eth1 + ((struct dev_priv *)_rtl86xx_dev.dev[1]->priv)->id = vlan_tag; //eth1 + //PPPOE + vlanconfig[VLAN_CONFIG_PPPOE_INDEX].vid = vlan_tag; + } + + re865x_packVlanConfig(vlanconfig, packedVlanConfig); + rtl_reinit_hw_table(); + if(vlan_bridge_tag) + { + packedVlanConfig[2].memPort &= (~0x100); //eth2 use port 7, not port 8 + packedVlanConfig[2].untagSet &= (~0x100); + } + reinit_vlan_configure(packedVlanConfig); + + if(rtl865x_curOpMode == GATEWAY_MODE && vlan_tag) + { + rtl865x_setVlanPortTag(vlan_tag, RTL_WANPORT_MASK, true); //eth1 vlan port 1 tag + } + if(rtl865x_curOpMode == BRIDGE_MODE && vlan_tag) + { + rtl865x_addVlan(vlan_tag); + rtl865x_addVlanPortMember(vlan_tag,RTL_LANPORT_MASK | RTL_WANPORT_MASK); + rtl865x_setVlanPortTag(vlan_tag, (RTL_LANPORT_MASK|RTL_WANPORT_MASK)&(~0x100),1); + rtl865x_setVlanFilterDatabase(vlan_tag,0); + } + + if(vlan_bridge_tag) + { + rtl865x_setVlanPortTag(vlan_bridge_tag, RTL_WANPORT_MASK, true); //eth1 vlan port 1 tag + if(nicIgmpModuleIndex_2==0xFFFFFFFF) + { + ret = rtl_registerIgmpSnoopingModule(&nicIgmpModuleIndex_2); + #if defined (CONFIG_RTL_HARDWARE_MULTICAST) + memset(&devInfo, 0, sizeof(rtl_multicastDeviceInfo_t )); + strcpy(devInfo.devName, RTL_PS_ETH_NAME_ETH2); + if(ret==0) + rtl_setIgmpSnoopingModuleDevInfo(nicIgmpModuleIndex_2,&devInfo); + #endif + } + if(vlan_bridge_multicast_tag) + { + if (vlan_bridge_multicast_tag == vlan_bridge_tag) + { + vlan_bridge_multicast_tag = 0; + } + else + { + rtl865x_addVlan(vlan_bridge_multicast_tag); + rtl865x_addVlanPortMember(vlan_bridge_multicast_tag,RTL_WANPORT_MASK); + rtl865x_setVlanPortTag(vlan_bridge_multicast_tag,RTL_WANPORT_MASK,1); //wan port tag + rtl865x_setVlanFilterDatabase(vlan_bridge_multicast_tag,1); + } + } + } + else + { + if(nicIgmpModuleIndex_2!=0xFFFFFFFF) + rtl_unregisterIgmpSnoopingModule(nicIgmpModuleIndex_2); + //rtl865x_setVlanPortTag(vlanconfig[1].vid,RTL_WANPORT_MASK,false); //eth1 vlan port 1 tag + #ifdef CONFIG_RTL_IGMP_SNOOPING + if(nicIgmpModuleIndex_2!=0xFFFFFFFF) + rtl_unregisterIgmpSnoopingModule(nicIgmpModuleIndex_2); + #endif + } + + /*update dev port number*/ + for(i=0; vlanconfig[i].vid != 0; i++) + { + if (IF_ETHER!=vlanconfig[i].if_type) + { + continue; + } + + dev=_rtl86xx_dev.dev[i]; + dp = dev->priv; + dp->portnum = 0; + for(j=0;j<RTL8651_AGGREGATOR_NUMBER;j++) + { + if(dp->portmask & (1<<j)) + dp->portnum++; + } + + } + + #if defined (CONFIG_RTL_IGMP_SNOOPING) + re865x_reInitIgmpSetting(rtl865x_curOpMode); + #if defined (CONFIG_RTL_MLD_SNOOPING) + if(mldSnoopEnabled) + { + re865x_packVlanConfig(vlanconfig, packedVlanConfig); + rtl865x_addAclForMldSnooping(packedVlanConfig); + } + #endif + #endif + + //always init the default route... + if(rtl8651_getAsicOperationLayer() >2) + { +#ifdef CONFIG_RTL_LAYERED_DRIVER_L3 + rtl865x_addRoute(0,0,0,RTL_DRV_WAN0_NETIF_NAME,0); +#endif + } + WRITE_MEM32(SWTCR0,(READ_MEM32(SWTCR0)| EnUkVIDtoCPU)); + + + } + + return len; +} +static int32 rtk_vlan_wan_tag_support_read( char *page, char **start, off_t off, int count, int *eof, void *data ) +{ + int len; + len = sprintf(page, "vlan_tag: %d vlan_host_pri: %d \nvlan_bridge_tag: %d, vlan_bridge_port: 0x%x vlan_bridge_stream_tag: %d\n", + vlan_tag, vlan_host_pri, vlan_bridge_tag, vlan_bridge_port,vlan_bridge_multicast_tag); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) + len = count; + if (len<0) + len = 0; + return len; +} + +#endif static int32 rtk_vlan_support_read( char *page, char **start, off_t off, int count, int *eof, void *data ) { int len; @@ -6959,7 +8535,6 @@ static int32 rtk_vlan_support_read( char *page, char **start, off_t off, int cou return len; } - static int32 rtk_vlan_support_write( struct file *filp, const char *buff,unsigned long len, void *data ) { char tmpbuf[32]; @@ -7055,7 +8630,9 @@ static int32 rtk_vlan_support_write( struct file *filp, const char *buff,unsigne //always init the default route... if(rtl8651_getAsicOperationLayer() >2) { +#ifdef CONFIG_RTL_LAYERED_DRIVER_L3 rtl865x_addRoute(0,0,0,RTL_DRV_WAN0_NETIF_NAME,0); +#endif } } @@ -7472,9 +9049,17 @@ static int read_proc_vlan(char *page, char **start, off_t off, int len; cp = dev->priv; - len = sprintf(page, "gvlan=%d, lan=%d, vlan=%d, tag=%d, vid=%d, priority=%d, cfi=%d\n", +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) + len = sprintf(page, "gvlan=%d, lan=%d, vlan=%d, tag=%d, vid=%d, priority=%d, cfi=%d, forwarding_rule=%d\n", +#else + len = sprintf(page, "gvlan=%d, lan=%d, vlan=%d, tag=%d, vid=%d, priority=%d, cfi=%d\n", +#endif cp->vlan_setting.global_vlan, cp->vlan_setting.is_lan, cp->vlan_setting.vlan, cp->vlan_setting.tag, - cp->vlan_setting.id, cp->vlan_setting.pri, cp->vlan_setting.cfi); + cp->vlan_setting.id, cp->vlan_setting.pri, cp->vlan_setting.cfi +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) + ,cp->vlan_setting.forwarding_rule +#endif + ); if (len <= off+count) *eof = 1; @@ -7505,16 +9090,33 @@ static int write_proc_vlan(struct file *file, const char *buffer, if (buffer && !copy_from_user(tmp, buffer, VLAN_MAX_INPUT_LEN)) { - int num = sscanf(tmp, "%d %d %d %d %d %d %d", +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) + int num = sscanf(tmp, "%d %d %d %d %d %d %d %d", +#else + int num = sscanf(tmp, "%d %d %d %d %d %d %d", +#endif &cp->vlan_setting.global_vlan, &cp->vlan_setting.is_lan, &cp->vlan_setting.vlan, &cp->vlan_setting.tag, &cp->vlan_setting.id, &cp->vlan_setting.pri, - &cp->vlan_setting.cfi); + &cp->vlan_setting.cfi +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) + , &cp->vlan_setting.forwarding_rule +#endif + ); - if (num != 7) { +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) + if (num !=8) +#else + if (num !=7) +#endif + { printk("invalid vlan parameter!\n"); goto out; } + +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) + rtl_add_vlan_info(&cp->vlan_setting, dev); +#endif #if 0 printk("===%s(%d), cp->name(%s),global_vlan(%d),is_lan(%d),vlan(%d),tag(%d),id(%d),pri(%d),cfi(%d)",__FUNCTION__,__LINE__, cp->dev->name,cp->vlan_setting.global_vlan,cp->vlan_setting.is_lan,cp->vlan_setting.vlan,cp->vlan_setting.tag, @@ -7530,6 +9132,367 @@ out: } #endif // CONFIG_RTK_VLAN_SUPPORT +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) +static int rtk_vlan_management_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + + int len; + + len = sprintf(page, "Management vlan: vid=%d, priority=%d, cfi=%d\n", + management_vlan.id, management_vlan.pri, management_vlan.cfi + ); + + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; +} + +static int rtk_vlan_management_write(struct file *file, const char *buffer, + unsigned long len, void *data) +{ + char tmpbuf[128]; + int num; + + if (buffer && !copy_from_user(tmpbuf, buffer, len)) + { + tmpbuf[len] = '\0'; + + num = sscanf(tmpbuf, "%d %d %d", + &management_vlan.id, &management_vlan.pri, + &management_vlan.cfi); + + if (num != 3) { + printk("invalid vlan parameter!\n"); + } + + } + + return len; +} + +#endif + +#if defined(CONFIG_RTL_HW_VLAN_SUPPORT) + +uint32 rtl_hw_vlan_get_tagged_portmask(void) +{ + uint32 portmask = 0; + int i, temp; + + for(i=0; i<PORT_NUMBER; i++) + { + if((hw_vlan_info[i].vlan_port_enabled) && (hw_vlan_info[i].vlan_port_tag)) + { + temp = (i==0)?0:(i-1); + portmask |= 1<<temp; + } + } + + return portmask; +} + +int rtl_process_hw_vlan_tx(rtl_nicTx_info *txInfo) +{ + int i, temp; + int flag = 0; + unsigned short vid; + struct sk_buff *newskb; + struct sk_buff *skb = NULL; + unsigned short vid; + struct vlan_tag tag, port_tag; + struct vlan_tag *adding_tag = NULL; + struct net_device *dev; + struct dev_priv *cp; + + memset(&tag, 0, sizeof(struct vlan_tag)); + memset(&port_tag, 0, sizeof(struct vlan_tag)); + skb = txInfo->out_skb; + dev = skb->dev; + cp = dev->priv; + + newskb = NULL; + if (skb_cloned(skb)) + { + newskb = skb_copy(skb, GFP_ATOMIC); + if (newskb == NULL) + { + cp->net_stats.tx_dropped++; + dev_kfree_skb_any(skb); + return FAILED; + } + dev_kfree_skb_any(skb); + skb = newskb; + txInfo->out_skb = skb; + } + + //if((skb->data[0]&1) ||((skb->data[0]==0x33) &&(skb->data[1]==0x33) && (skb->data[2]!=0xFF))) + { + if(skb->tag.f.tpid == htons(ETH_P_8021Q)) + { + vid = ntohs(skb->tag.f.pci & 0xfff); + for(i=0; i<PORT_NUMBER; i++) + { + temp = (i==0)?i:(i-1); + if((((struct dev_priv*)skb->dev->priv)->portmask & (0x1<<temp))&&(vid == hw_vlan_info[i].vlan_port_vid)&& + (hw_vlan_info[i].vlan_port_bridge == 1)&&(hw_vlan_info[i].vlan_port_tag)&&(hw_vlan_info[i].vlan_port_enabled)) + { + flag = 1; + break; + } + } + + if(flag) + { + //printk("dev name is %s, portmask is 0x%x, i is %d, vid is %d\n", skb->dev->name, ((struct dev_priv*)skb->dev->priv)->portmask, i, vid); + adding_tag = &skb->tag; + } + }else{ + for(i=0; i<PORT_NUMBER; i++) + { + if(((struct dev_priv*)skb->dev->priv)->portmask & (0x1<<i)) + { + flag = 1; + break; + } + } + temp = (i==0)?i:(i+1); + if((flag)&&(hw_vlan_info[temp].vlan_port_bridge == 1)&& (hw_vlan_info[temp].vlan_port_tag) && + (hw_vlan_info[temp].vlan_port_enabled)) + { + port_tag.f.tpid = htons(ETH_P_8021Q); + port_tag.f.pci = (unsigned short) ((0x3 << 13) |(0x1 << 12) | + ((unsigned short)(hw_vlan_info[temp].vlan_port_vid&0xfff))); + port_tag.f.pci = htons(port_tag.f.pci); + adding_tag = &port_tag; + } + } + + if(adding_tag != NULL) + { + memcpy(&tag, skb->data+ETH_ALEN*2, VLAN_HLEN); + if (tag.f.tpid != htons(ETH_P_8021Q)) { // tag not existed, insert tag + if (skb_headroom(skb) < VLAN_HLEN && skb_cow(skb, VLAN_HLEN) !=0 ) { + printk("%s-%d: error! (skb_headroom(skb) == %d < 4). Enlarge it!\n", + __FUNCTION__, __LINE__, skb_headroom(skb)); + while (1) ; + } + skb_push(skb, VLAN_HLEN); + memmove(skb->data, skb->data+VLAN_HLEN, ETH_ALEN*2); + } + + memcpy(skb->data+ETH_ALEN*2, adding_tag, VLAN_HLEN); + } + + } + + return SUCCESS; + +} + +static int32 rtl_hw_vlan_support_read( char *page, char **start, off_t off, int count, int *eof, void *data ) +{ + int len; + int i; + + len = sprintf(page, "rtl_hw_vlan_enable: %d\n", rtl_hw_vlan_enable); + for(i=0; i<PORT_NUMBER; i++) + { + if(i == 1) + continue; + + len += sprintf(page + len, "lan_%d_bridge_enabled: %d, lan_%d_bridge: %d, lan_%d_tag: %d, lan_%d_vid: %d\n", + ((i==0)? i: i-1), hw_vlan_info[i].vlan_port_enabled, ((i==0)? i: i-1), hw_vlan_info[i].vlan_port_bridge, ((i==0)? i: i-1), hw_vlan_info[i].vlan_port_tag, + ((i==0)? i: i-1), hw_vlan_info[i].vlan_port_vid); + } + + len += sprintf(page + len, "wan_port_enabled: %d, wan_port_tag: %d, wan_port_vid: %d\n", hw_vlan_info[1].vlan_port_enabled, hw_vlan_info[1].vlan_port_tag, hw_vlan_info[1].vlan_port_vid); + + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) + len = count; + if (len<0) + len = 0; + return len; +} + + +static int32 rtl_hw_vlan_support_write( struct file *filp, const char *buff,unsigned long len, void *data ) +{ + char tmpbuf[100]; + int lan_portmask = 0; + int num=0 ; + int i=0; + int j=0; + int bridge_num = 0; + struct net_device *dev; + struct dev_priv *dp; + + if (buff && !copy_from_user(tmpbuf, buff, len)) + { + num = sscanf(tmpbuf, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", + &rtl_hw_vlan_enable, &hw_vlan_info[1].vlan_port_enabled, &hw_vlan_info[1].vlan_port_tag, &hw_vlan_info[1].vlan_port_vid, + &hw_vlan_info[0].vlan_port_enabled, &hw_vlan_info[0].vlan_port_bridge, &hw_vlan_info[0].vlan_port_tag, &hw_vlan_info[0].vlan_port_vid, + &hw_vlan_info[2].vlan_port_enabled, &hw_vlan_info[2].vlan_port_bridge, &hw_vlan_info[2].vlan_port_tag, &hw_vlan_info[2].vlan_port_vid, + &hw_vlan_info[3].vlan_port_enabled, &hw_vlan_info[3].vlan_port_bridge, &hw_vlan_info[3].vlan_port_tag, &hw_vlan_info[3].vlan_port_vid, + &hw_vlan_info[4].vlan_port_enabled, &hw_vlan_info[4].vlan_port_bridge, &hw_vlan_info[4].vlan_port_tag, &hw_vlan_info[4].vlan_port_vid + ); + + if (num != 20) { + printk("invalid rtl_hw_vlan_support_write parameter!\n"); + return len; + } + + rtl_config_rtkVlan_vlanconfig(rtl865x_curOpMode); + + /*get rid of port who bridge with wan from RTL_LANPORT_MASK*/ + if(rtl_hw_vlan_enable && (rtl865x_curOpMode == GATEWAY_MODE)) + { + lan_portmask = RTL_LANPORT_MASK; + + if((hw_vlan_info[0].vlan_port_enabled == 1)&&(hw_vlan_info[0].vlan_port_bridge == 1)) + lan_portmask &= ~RTL_LANPORT_MASK_4; //port0 is bridge, so port0 need to get out of lan_port_mask + if((hw_vlan_info[2].vlan_port_enabled == 1)&&(hw_vlan_info[2].vlan_port_bridge == 1)) + lan_portmask &= ~RTL_LANPORT_MASK_3; + if((hw_vlan_info[3].vlan_port_enabled == 1)&&(hw_vlan_info[3].vlan_port_bridge == 1)) + lan_portmask &= ~RTL_LANPORT_MASK_2; + if((hw_vlan_info[4].vlan_port_enabled == 1)&&(hw_vlan_info[4].vlan_port_bridge == 1)) + lan_portmask &= ~RTL_LANPORT_MASK_1; + + vlanconfig[0].memPort = lan_portmask; + vlanconfig[0].vid= RTL_LANVLANID; + vlanconfig[0].untagSet = lan_portmask; + ((struct dev_priv *)_rtl86xx_dev.dev[0]->priv)->portmask = lan_portmask; //eth0 + ((struct dev_priv *)_rtl86xx_dev.dev[0]->priv)->id = RTL_LANVLANID; + + vlanconfig[1].vid = hw_vlan_info[1].vlan_port_vid; + vlanconfig[1].memPort = RTL_WANPORT_MASK; + vlanconfig[1].untagSet = 0; // need tag + ((struct dev_priv *)_rtl86xx_dev.dev[1]->priv)->portmask = RTL_WANPORT_MASK; //eth1 + ((struct dev_priv *)_rtl86xx_dev.dev[1]->priv)->id = hw_vlan_info[1].vlan_port_vid; //eth1 + + for(i=0; i<PORT_NUMBER; i++) + { + if(i==1) /*bypass eth1*/ + continue; + + if((hw_vlan_info[i].vlan_port_enabled == 1)&&(hw_vlan_info[i].vlan_port_bridge == 1)) + { + if(i == 0) + { + vlanconfig[2+bridge_num].memPort = 1<<i; + vlanconfig[2+bridge_num].vid = hw_vlan_info[i].vlan_port_vid; + vlanconfig[2+bridge_num].untagSet = 1<<i; + ((struct dev_priv *)_rtl86xx_dev.dev[2+bridge_num]->priv)->portmask = 1<<i; + ((struct dev_priv *)_rtl86xx_dev.dev[2+bridge_num]->priv)->id = hw_vlan_info[i].vlan_port_vid; + bridge_num ++; + }else{ + vlanconfig[2+bridge_num].memPort = 1<<(i-1); + vlanconfig[2+bridge_num].vid = hw_vlan_info[i].vlan_port_vid; + vlanconfig[2+bridge_num].untagSet = 1<<(i-1); + ((struct dev_priv *)_rtl86xx_dev.dev[2+bridge_num]->priv)->portmask = 1<<(i-1); + ((struct dev_priv *)_rtl86xx_dev.dev[2+bridge_num]->priv)->id = hw_vlan_info[i].vlan_port_vid; + bridge_num ++; + } + } + } + //PPPOE + vlanconfig[5].vid = hw_vlan_info[1].vlan_port_vid; + } + + + re865x_packVlanConfig(vlanconfig, packedVlanConfig); + + rtl_reinit_hw_table(); + reinit_vlan_configure(packedVlanConfig); + + //unknow vlan drop + //REG32(SWTCR0) &= ~(1 << 15); + + /*update dev port number*/ + for(i=0; vlanconfig[i].vid != 0; i++) + { + if (IF_ETHER!=vlanconfig[i].if_type) + { + continue; + } + + dev=_rtl86xx_dev.dev[i]; + dp = dev->priv; + dp->portnum = 0; + for(j=0;j<RTL8651_AGGREGATOR_NUMBER;j++) + { + if(dp->portmask & (1<<j)) + dp->portnum++; + } + + } + + #if defined (CONFIG_RTL_IGMP_SNOOPING) + re865x_reInitIgmpSetting(rtl865x_curOpMode); + #if defined (CONFIG_RTL_MLD_SNOOPING) + if(mldSnoopEnabled && (rtk_vlan_support_enable==0)) + { + re865x_packVlanConfig(vlanconfig, packedVlanConfig); + rtl865x_addAclForMldSnooping(packedVlanConfig); + } + #endif + #endif + + //always init the default route... + if(rtl8651_getAsicOperationLayer() >2) + { + rtl865x_addRoute(0,0,0,RTL_DRV_WAN0_NETIF_NAME,0); + } + + rtl8651_setAsicMulticastEnable(TRUE); + } + return len; +} + + +static int32 rtl_hw_vlan_tagged_bridge_multicast_read( char *page, char **start, off_t off, int count, int *eof, void *data ) +{ + int len; + len = sprintf(page, "%s %d\n", "rtl_hw_vlan_tagged_mc:",rtl_hw_vlan_ignore_tagged_mc); + + + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) + len = count; + if (len<0) + len = 0; + + return len; +} + +static int32 rtl_hw_vlan_tagged_bridge_multicast_write( struct file *filp, const char *buff,unsigned long len, void *data ) +{ + char tmpbuf[32]; + + if (buff && !copy_from_user(tmpbuf, buff, len)) + { + tmpbuf[len] = '\0'; + + rtl_hw_vlan_ignore_tagged_mc = tmpbuf[0] - '0'; + } + return len; +} + + +#endif + + #if (defined(CONFIG_RTL_CUSTOM_PASSTHRU) && !defined(CONFIG_RTL8196_RTL8366)) static unsigned long atoi_dec(char *s) @@ -7819,7 +9782,7 @@ void __exit rtl8651_exitStormCtrl(void) #endif -#if defined(CONFIG_RTL_8198) +#if defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) static int32 proc_phyTest_read( char *page, char **start, off_t off, int count, int *eof, void *data ) { return 0; @@ -8173,7 +10136,7 @@ int32 rtl8651_initMldSnooping(void) void __exit rtl8651_exitMldSnoopingCtrl(void) { if (mldSnoopingProc) { - remove_proc_entry("mldSnooping", mldSnoopingProc); + remove_proc_entry("br_mldsnoop", mldSnoopingProc); mldSnoopingProc = NULL; } } @@ -8563,6 +10526,7 @@ static int rtl_regist_multipleWan_dev(void) #endif dev->irq = 0; + memcpy((char*)dev->name,rtl_multiWan_config.ifname,MAX_IFNAMESIZE); rc = register_netdev(dev); if(!rc){ rtl_multiWan_net_dev = dev; @@ -8571,6 +10535,7 @@ static int rtl_regist_multipleWan_dev(void) }else printk("===%s(%d) Failed to allocate,rc(%d)\n",__FUNCTION__,__LINE__,rc); + return SUCCESS; // } #if 0 @@ -8639,6 +10604,100 @@ static int rtl_config_multipleWan_netif(int32 cmd) return retval; } + +static int rtl865x_addMultiCastNetif(void) +{ + rtl865x_netif_t netif; + int ret=FAILED; + + rtl865x_delVlan(MULTICAST_NETIF_VLAN_ID); + rtl865x_addVlan(MULTICAST_NETIF_VLAN_ID); + ret=rtl865x_addVlanPortMember(MULTICAST_NETIF_VLAN_ID, rtl_multiWan_config.memPort); + ret=rtl865x_setVlanFilterDatabase(MULTICAST_NETIF_VLAN_ID, rtl_multiWan_config.fid); + + if(_rtl865x_getNetifByName(multiCastNetIf)!=NULL) + { + return SUCCESS; + } + + memset(&netif, 0, sizeof(rtl865x_netif_t)); + strcpy(netif.name, multiCastNetIf); + memcpy(&netif.macAddr, multiCastNetIfMac, 6); + netif.mtu = 1500; + netif.if_type = IF_ETHER; + netif.vid = MULTICAST_NETIF_VLAN_ID; + netif.is_wan = 1; + netif.is_slave = 0; + netif.enableRoute=1; + netif.forMacBasedMCast=TRUE; + //printk("%s:%d,entry->lpNetif is %s \n",__FUNCTION__,__LINE__,entry->lpNetif); + ret = rtl865x_addNetif(&netif); + if(ret!=SUCCESS) + { + rtl865x_delVlan(MULTICAST_NETIF_VLAN_ID); + return FAILED; + } + +#if defined(CONFIG_RTK_VLAN_SUPPORT) + { + rtl865x_AclRule_t rule; + bzero((void*)&rule,sizeof(rtl865x_AclRule_t)); + rule.ruleType_ = RTL865X_ACL_MAC; + rule.pktOpApp_ = RTL865X_ACL_ALL_LAYER; + rule.actionType_ = RTL865X_ACL_PERMIT; + ret=rtl865x_add_acl(&rule, multiCastNetIf, RTL865X_ACL_SYSTEM_USED); + } +#endif + + return ret; +} + +#if 0 +static int rtl865x_delMultiCastNetif(void) +{ + int ret=FAILED; + +#if defined(CONFIG_RTK_VLAN_SUPPORT) + { + rtl865x_AclRule_t rule; + bzero((void*)&rule,sizeof(rtl865x_AclRule_t)); + rule.ruleType_ = RTL865X_ACL_MAC; + rule.pktOpApp_ = RTL865X_ACL_ALL_LAYER; + rule.actionType_ = RTL865X_ACL_PERMIT; + ret=rtl865x_del_acl(&rule, multiCastNetIf, RTL865X_ACL_SYSTEM_USED); + } +#endif + + ret=rtl865x_delNetif(multiCastNetIf); + + if(ret==SUCCESS) + { + ret=rtl865x_delVlan(MULTICAST_NETIF_VLAN_ID); + } + return ret; + +} + +int rtl865x_setMultiCastSrcMac(unsigned char *srcMac) +{ + + if(srcMac==NULL) + { + return FAILED; + } + + memcpy(multiCastNetIfMac, srcMac, 6); + + if(_rtl865x_getNetifByName(multiCastNetIf)!=NULL) + { + rtl865x_delMCastNetif(); + rtl865x_addMCastNetif(); + } + + return SUCCESS; +} +#endif + #endif @@ -8647,23 +10706,14 @@ int re865x_reProbe (void) { rtl8651_tblAsic_InitPara_t para; unsigned long flags; +#if defined(CONFIG_RTL_819XD)&&defined(CONFIG_RTL_8211DS_SUPPORT)&&defined(CONFIG_RTL_8197D) + uint32 reg_tmp=0; +#endif local_irq_save(flags); //WRITE_MEM32(PIN_MUX_SEL_2, 0x7<<21); /*Initial ASIC table*/ - -#ifdef CONFIG_RTL8198_REVISION_B - if (REG32(BSP_REVR) >= BSP_RTL8198_REVISION_B) - { - REG32(SYS_CLK_MAG)&=(~(SYS_SW_RESET)); - mdelay(300); - REG32(SYS_CLK_MAG)|=(SYS_SW_RESET); - mdelay(100); - - } - else -#endif - FullAndSemiReset(); + FullAndSemiReset(); memset(¶, 0, sizeof(rtl8651_tblAsic_InitPara_t)); @@ -8676,12 +10726,13 @@ int re865x_reProbe (void) #ifdef CONFIG_RTL_LAYERED_ASIC_DRIVER_L3 INIT_CHECK(rtl865x_initAsicL3()); #endif -#if defined(CONFIG_RTL_LAYERED_ASIC_DRIVER_L4) && defined(CONFIG_RTL_8198) +#if defined(CONFIG_RTL_LAYERED_ASIC_DRIVER_L4) && (defined(CONFIG_RTL_8198) ||defined(CONFIG_RTL_8196CT) ||defined(CONFIG_RTL_819XDT)) INIT_CHECK(rtl865x_initAsicL4()); #endif /*init PHY LED style*/ +#if !defined(CONFIG_RTL_819XD) && !defined(CONFIG_RTL_8196E) #if defined(CONFIG_RTL865X_BICOLOR_LED) #ifdef BICOLOR_LED_VENDOR_BXXX REG32(LEDCR) |= (1 << 19); // 5 ledmode set to 1 for bi-color LED @@ -8703,13 +10754,18 @@ int re865x_reProbe (void) WRITE_MEM32(TCR0, 0x000002C7); //8651 demo board default: 15 LED boards WRITE_MEM32(SWTACR, CMD_FORCE | ACTION_START); // force add #endif /* CONFIG_RTL865X_BICOLOR_LED */ +#endif /*2007-12-19*/ #if defined(CONFIG_RTK_VLAN_SUPPORT) //port based decision rtl865xC_setNetDecisionPolicy(NETIF_PORT_BASED); WRITE_MEM32(PLITIMR,0); +#endif +#if defined(CONFIG_RTL_819XD)&&defined(CONFIG_RTL_8211DS_SUPPORT)&&defined(CONFIG_RTL_8197D) + rtl8651_getAsicEthernetPHYReg(0x6, 0, ®_tmp); + rtl_setPortMask(reg_tmp); #endif /*queue id & rx ring descriptor mapping*/ @@ -8734,6 +10790,21 @@ int re865x_reProbe (void) rtl8651_setAsicMulticastEnable(FALSE); #endif #endif + +#ifdef CONFIG_RTL_8198_ESD + esd3_skip_one = 1; + one_second_counter = 0; + first_time_read_reg6 = 1; + phy_reg30[0] = phy_reg30[1] = phy_reg30[2] = phy_reg30[3] = phy_reg30[4] = 0; +#endif + +#ifdef CONFIG_RTL_8198 + { + extern void disable_phy_power_down(void); + disable_phy_power_down(); + } +#endif + local_irq_restore(flags); return 0; } @@ -8754,7 +10825,8 @@ int rtl865x_reinitSwitchCore(void) /*enable switch core interrupt*/ REG32(CPUICR) = TXCMD | RXCMD | BUSBURST_32WORDS | MBUF_2048BYTES; - REG32(CPUIIMR) = RX_DONE_IE_ALL | TX_ALL_DONE_IE_ALL | LINK_CHANGE_IE; + REG32(CPUIIMR) = RX_DONE_IE_ALL | TX_ALL_DONE_IE_ALL | LINK_CHANGE_IE | PKTHDR_DESC_RUNOUT_IE_ALL; + REG32(SIRR) |= TRXRDY; REG32(GIMR) |= (BSP_SW_IE); rtl865x_duringReInitSwtichCore=0; @@ -8842,5 +10914,242 @@ void __exit rtl865x_destroyReInitResetSwitchCore(void) #endif +#ifdef CONFIG_RTK_VOIP_QOS +int wan_port_check(int port) +{ + if(1<<port & RTL_WANPORT_MASK) + return TRUE; + else + return FALSE; +} +#endif + +#ifdef CONFIG_RTK_VOIP_PORT_LINK +static int rtnl_fill_ifinfo_voip(struct sk_buff *skb, struct net_device *dev, + int type, u32 pid, u32 seq, u32 change, + unsigned int flags) +{ + struct ifinfomsg *ifm; + struct nlmsghdr *nlh; + + nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags); + if (nlh == NULL) + return -ENOBUFS; + + ifm = nlmsg_data(nlh); + ifm->ifi_family = AF_UNSPEC; + ifm->__ifi_pad = 0; + ifm->ifi_type = dev->type; + ifm->ifi_index = dev->ifindex; + ifm->ifi_flags = dev_get_flags(dev); + ifm->ifi_change = change; + return nlmsg_end(skb, nlh); +} +static void rtmsg_ifinfo_voip(int type, struct net_device *dev, unsigned change) +{ + struct net *net = dev_net(dev); + struct sk_buff *skb; + int err = -ENOBUFS; + + skb = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); + if (skb == NULL) + goto errout; + + err = rtnl_fill_ifinfo_voip(skb, dev, type, 0, 0, change, 0); + if (err < 0) { + /* -EMSGSIZE implies BUG in if_nlmsg_size() */ + WARN_ON(err == -EMSGSIZE); + kfree_skb(skb); + goto errout; + } + rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); + return; +errout: + if (err < 0) + rtnl_set_sk_err(net, RTNLGRP_LINK, err); +} +#endif + + +#if defined (CONFIG_RTL_SOCK_DEBUG) +static struct proc_dir_entry *rtl865x_sockDebugProc=NULL; +extern int dumpRawSockInfo(void); +extern int dumpUdpSockInfo(void); +extern int dumpTcpSockInfo(void); +static int rtl865x_sockDebugReadProc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len=0; + len = 0; + + if (len <= off+count) + *eof = 1; + + *start = page + off; + len -= off; + + if (len>count) + len = count; + + if (len<0) len = 0; + + return len; +} + +static int rtl865x_sockDebugWriteProc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + char tmpBuf[256]; + char *strptr; + char *tokptr; + unsigned int tmp; + + if (buffer && !copy_from_user(tmpBuf, buffer, count)) + { + tmpBuf[count-1]=0; + strptr=tmpBuf; + + tokptr = strsep(&strptr," "); + if (tokptr==NULL) + { + goto errOut; + } + + //printk("here to reset switch core\n"); + tmp=simple_strtol(tokptr, NULL, 0); + if(tmp==1) + { + dumpRawSockInfo(); + dumpUdpSockInfo(); + dumpTcpSockInfo(); + + } + + + return count; + } + +errOut: + return -EFAULT; +} + +int rtl865x_creatSockDebugProc(void) +{ + rtl865x_sockDebugProc = create_proc_entry("sockDebug", 0, NULL); + if(rtl865x_sockDebugProc) + { + rtl865x_sockDebugProc->read_proc = rtl865x_sockDebugReadProc; + rtl865x_sockDebugProc->write_proc = rtl865x_sockDebugWriteProc; + } + + return 0; +} + +void __exit rtl865x_removeSockDebugProc(void) +{ + if (rtl865x_sockDebugProc) { + remove_proc_entry("sockDebug", rtl865x_sockDebugProc); + rtl865x_sockDebugProc = NULL; + } +} +#endif + +#ifdef CONFIG_RTL_ULINKER +void eth_led_recover(void) +{ + REG32(PIN_MUX_SEL_2) = REG32(PIN_MUX_SEL_2) & ~(0x00003000); +} +#endif + +extern int eee_enabled; +#if defined(RTL8198_EEE_MAC) +extern void eee_phy_enable_98(void); +extern void eee_phy_disable_98(void); +#endif + +static struct proc_dir_entry *res_eee=NULL; +static int eee_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data); +static int eee_write_proc(struct file *file, const char *buffer, unsigned long count, void *data); +extern void enable_EEE(void); +extern void disable_EEE(void); + +static int32 rtl819x_eee_proc_init(void) +{ + res_eee = create_proc_entry("eee", 0, NULL); + if(res_eee) + { + res_eee->read_proc = eee_read_proc; + res_eee->write_proc = eee_write_proc; + } + return 0; +} + +void __exit rtl819x_eee_proc_exit(void) +{ + if (res_eee) { + remove_proc_entry("eee", res_eee); + res_eee = NULL; + } +} + +static int eee_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len=0; + + len += sprintf(page+len, "eee %sabled.\n", ((eee_enabled) ? "en" : "dis") ); + + if (len <= off+count) + *eof = 1; + + *start = page + off; + len -= off; + + if (len>count) + len = count; + + if (len<0) len = 0; + + return len; +} + +static int eee_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + char tmpBuf[32]; + + if (buffer && !copy_from_user(tmpBuf, buffer, count)) + { + if (tmpBuf[0] == '0') { + eee_enabled = FALSE; + disable_EEE(); + } + else if (tmpBuf[0] == '1') { + eee_enabled = TRUE; + enable_EEE(); + } +#ifdef CONFIG_RTL_8198_ESD + esd3_skip_one = 1; +#endif + return count; + } + return -EFAULT; +} +#ifdef CONFIG_RTL865X_LANPORT_RESTRICTION +char *rtl_getDevNameByPort(int32 port_num) +{ + int i; + struct dev_priv *cp; + + for(i = 0; i < ETH_INTF_NUM; i++) + { + cp = ((struct dev_priv *)_rtl86xx_dev.dev[i]->priv); + if(cp && cp->opened && (cp->portmask & (1<<port_num))) + return cp->dev->name; + } + + return NULL; +} +#endif |