From 716ca530e1c4515d8683c9d5be3d56b301758b66 Mon Sep 17 00:00:00 2001 From: James <> Date: Wed, 4 Nov 2015 11:49:21 +0000 Subject: trunk-47381 --- .../0063-arm-mediatek-add-SDK-ethernet.patch | 20654 +++++++++++++++++++ 1 file changed, 20654 insertions(+) create mode 100644 target/linux/mediatek/patches/0063-arm-mediatek-add-SDK-ethernet.patch (limited to 'target/linux/mediatek/patches/0063-arm-mediatek-add-SDK-ethernet.patch') diff --git a/target/linux/mediatek/patches/0063-arm-mediatek-add-SDK-ethernet.patch b/target/linux/mediatek/patches/0063-arm-mediatek-add-SDK-ethernet.patch new file mode 100644 index 0000000..7263bb2 --- /dev/null +++ b/target/linux/mediatek/patches/0063-arm-mediatek-add-SDK-ethernet.patch @@ -0,0 +1,20654 @@ +From e3aece79d5003b6879298b05551e113117d5cdd8 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sat, 27 Jun 2015 13:13:36 +0200 +Subject: [PATCH 63/76] arm: mediatek: add SDK ethernet + +Signed-off-by: John Crispin +--- + drivers/net/ethernet/Kconfig | 1 + + drivers/net/ethernet/Makefile | 1 + + drivers/net/ethernet/raeth/Kconfig | 415 ++ + drivers/net/ethernet/raeth/Makefile | 67 + + drivers/net/ethernet/raeth/Makefile.release | 60 + + drivers/net/ethernet/raeth/csr_netlink.h | 27 + + drivers/net/ethernet/raeth/dvt/pkt_gen.c | 88 + + drivers/net/ethernet/raeth/dvt/pkt_gen_tcp_frag.c | 138 + + drivers/net/ethernet/raeth/dvt/pkt_gen_udp_frag.c | 191 + + drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.c | 1527 +++++ + drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.h | 75 + + drivers/net/ethernet/raeth/ethtool_readme.txt | 44 + + drivers/net/ethernet/raeth/mcast.c | 187 + + drivers/net/ethernet/raeth/mii_mgr.c | 603 ++ + drivers/net/ethernet/raeth/ra2882ethreg.h | 1985 +++++++ + drivers/net/ethernet/raeth/ra_ethtool.c | 515 ++ + drivers/net/ethernet/raeth/ra_ethtool.h | 13 + + drivers/net/ethernet/raeth/ra_ioctl.h | 102 + + drivers/net/ethernet/raeth/ra_mac.c | 2645 +++++++++ + drivers/net/ethernet/raeth/ra_mac.h | 57 + + drivers/net/ethernet/raeth/ra_netlink.c | 142 + + drivers/net/ethernet/raeth/ra_netlink.h | 10 + + drivers/net/ethernet/raeth/ra_qos.c | 655 +++ + drivers/net/ethernet/raeth/ra_qos.h | 18 + + drivers/net/ethernet/raeth/ra_rfrw.c | 66 + + drivers/net/ethernet/raeth/ra_rfrw.h | 6 + + drivers/net/ethernet/raeth/raether.c | 6401 +++++++++++++++++++++ + drivers/net/ethernet/raeth/raether.h | 126 + + drivers/net/ethernet/raeth/raether_hwlro.c | 347 ++ + drivers/net/ethernet/raeth/raether_pdma.c | 1121 ++++ + drivers/net/ethernet/raeth/raether_qdma.c | 1407 +++++ + drivers/net/ethernet/raeth/raether_qdma_mt7623.c | 1020 ++++ + drivers/net/ethernet/raeth/smb_hook.c | 17 + + drivers/net/ethernet/raeth/smb_nf.c | 177 + + drivers/net/ethernet/raeth/sync_write.h | 103 + + 35 files changed, 20357 insertions(+) + create mode 100644 drivers/net/ethernet/raeth/Kconfig + create mode 100644 drivers/net/ethernet/raeth/Makefile + create mode 100644 drivers/net/ethernet/raeth/Makefile.release + create mode 100644 drivers/net/ethernet/raeth/csr_netlink.h + create mode 100755 drivers/net/ethernet/raeth/dvt/pkt_gen.c + create mode 100755 drivers/net/ethernet/raeth/dvt/pkt_gen_tcp_frag.c + create mode 100755 drivers/net/ethernet/raeth/dvt/pkt_gen_udp_frag.c + create mode 100755 drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.c + create mode 100755 drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.h + create mode 100644 drivers/net/ethernet/raeth/ethtool_readme.txt + create mode 100644 drivers/net/ethernet/raeth/mcast.c + create mode 100644 drivers/net/ethernet/raeth/mii_mgr.c + create mode 100644 drivers/net/ethernet/raeth/ra2882ethreg.h + create mode 100644 drivers/net/ethernet/raeth/ra_ethtool.c + create mode 100644 drivers/net/ethernet/raeth/ra_ethtool.h + create mode 100644 drivers/net/ethernet/raeth/ra_ioctl.h + create mode 100644 drivers/net/ethernet/raeth/ra_mac.c + create mode 100644 drivers/net/ethernet/raeth/ra_mac.h + create mode 100644 drivers/net/ethernet/raeth/ra_netlink.c + create mode 100644 drivers/net/ethernet/raeth/ra_netlink.h + create mode 100644 drivers/net/ethernet/raeth/ra_qos.c + create mode 100644 drivers/net/ethernet/raeth/ra_qos.h + create mode 100644 drivers/net/ethernet/raeth/ra_rfrw.c + create mode 100644 drivers/net/ethernet/raeth/ra_rfrw.h + create mode 100644 drivers/net/ethernet/raeth/raether.c + create mode 100644 drivers/net/ethernet/raeth/raether.h + create mode 100755 drivers/net/ethernet/raeth/raether_hwlro.c + create mode 100755 drivers/net/ethernet/raeth/raether_pdma.c + create mode 100644 drivers/net/ethernet/raeth/raether_qdma.c + create mode 100644 drivers/net/ethernet/raeth/raether_qdma_mt7623.c + create mode 100644 drivers/net/ethernet/raeth/smb_hook.c + create mode 100644 drivers/net/ethernet/raeth/smb_nf.c + create mode 100644 drivers/net/ethernet/raeth/sync_write.h + +diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig +index eadcb05..627e1d4 100644 +--- a/drivers/net/ethernet/Kconfig ++++ b/drivers/net/ethernet/Kconfig +@@ -17,6 +17,7 @@ config MDIO + config SUNGEM_PHY + tristate + ++source "drivers/net/ethernet/raeth/Kconfig" + source "drivers/net/ethernet/3com/Kconfig" + source "drivers/net/ethernet/adaptec/Kconfig" + source "drivers/net/ethernet/aeroflex/Kconfig" +diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile +index 1367afc..abdd636 100644 +--- a/drivers/net/ethernet/Makefile ++++ b/drivers/net/ethernet/Makefile +@@ -84,3 +84,4 @@ obj-$(CONFIG_NET_VENDOR_VIA) += via/ + obj-$(CONFIG_NET_VENDOR_WIZNET) += wiznet/ + obj-$(CONFIG_NET_VENDOR_XILINX) += xilinx/ + obj-$(CONFIG_NET_VENDOR_XIRCOM) += xircom/ ++obj-$(CONFIG_RAETH) += raeth/ +diff --git a/drivers/net/ethernet/raeth/Kconfig b/drivers/net/ethernet/raeth/Kconfig +new file mode 100644 +index 0000000..c252c85 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/Kconfig +@@ -0,0 +1,415 @@ ++config ARCH_MT7623 ++ bool ++ default y ++ ++config RA_NAT_NONE ++ bool ++ default y ++ ++config RAETH ++ tristate "Ralink GMAC" ++ ---help--- ++ This driver supports Ralink gigabit ethernet family of ++ adapters. ++ ++config PDMA_NEW ++ bool ++ default y if (RALINK_MT7620 || RALINK_MT7621 || ARCH_MT7623) ++ depends on RAETH ++ ++config RAETH_SCATTER_GATHER_RX_DMA ++ bool ++ default y if (RALINK_MT7620 || RALINK_MT7621 || ARCH_MT7623) ++ depends on RAETH ++ ++ ++choice ++ prompt "Network BottomHalves" ++ depends on RAETH ++ default RA_NETWORK_WORKQUEUE_BH ++ ++ config RA_NETWORK_TASKLET_BH ++ bool "Tasklet" ++ ++ config RA_NETWORK_WORKQUEUE_BH ++ bool "Work Queue" ++ ++ config RAETH_NAPI ++ bool "NAPI" ++ ++endchoice ++ ++#config TASKLET_WORKQUEUE_SW ++# bool "Tasklet and Workqueue switch" ++# depends on RA_NETWORK_TASKLET_BH ++ ++config RAETH_SKB_RECYCLE_2K ++ bool "SKB Recycling" ++ depends on RAETH ++ ++config RAETH_SPECIAL_TAG ++ bool "Ralink Special Tag (0x810x)" ++ depends on RAETH && RT_3052_ESW ++ ++#config RAETH_JUMBOFRAME ++# bool "Jumbo Frame up to 4K bytes" ++# depends on RAETH && !(RALINK_RT3052 || RALINK_RT3352 || RALINK_RT5350 || RALINK_MT7628) ++ ++config RAETH_CHECKSUM_OFFLOAD ++ bool "TCP/UDP/IP checksum offload" ++ default y ++ depends on RAETH && !RALINK_RT2880 ++ ++#config RAETH_SW_FC ++# bool "When TX ring is full, inform kernel stop transmit and stop RX handler" ++# default n ++# depends on RAETH ++ ++#config RAETH_8023AZ_EEE ++# bool "Enable Embeded Switch EEE" ++# default n ++# depends on RAETH && (RALINK_MT7620 || RALINK_MT7621 || RALINK_MT7628) ++ ++ ++ ++config 32B_DESC ++ bool "32bytes TX/RX description" ++ default n ++ depends on RAETH && (RALINK_MT7620 || RALINK_MT7621) ++ ---help--- ++ At this moment, you cannot enable 32B description with Multiple RX ring at the same time. ++ ++config RAETH_LRO ++ bool "LRO (Large Receive Offload )" ++ select INET_LRO ++ depends on RAETH && (RALINK_RT6855A || RALINK_MT7620 || RALINK_MT7621 || ARCH_MT7623) ++ ++config RAETH_HW_LRO ++ bool "HW LRO (Large Receive Offload)" ++ default n ++ depends on RAETH ++ ++config RAETH_HW_LRO_DBG ++ bool "HW LRO Debug" ++ default n ++ depends on RAETH_HW_LRO ++ ++config RAETH_HW_LRO_AUTO_ADJ_DBG ++ bool "HW LRO Auto Adjustment Debug" ++ default y ++ depends on RAETH_HW_LRO ++ ++config RAETH_HW_LRO_REASON_DBG ++ bool "HW LRO Flush Reason Debug" ++ default n ++ depends on RAETH_HW_LRO ++ ++config RAETH_HW_VLAN_TX ++ bool "Transmit VLAN HW (DoubleVLAN is not supported)" ++ depends on RAETH && !(RALINK_RT5350 || RALINK_MT7628) ++ ---help--- ++ Please disable HW_VLAN_TX if you need double vlan ++ ++config RAETH_HW_VLAN_RX ++ bool "Receive VLAN HW (DoubleVLAN is not supported)" ++ depends on RAETH && RALINK_MT7621 ++ ---help--- ++ Please disable HW_VLAN_RX if you need double vlan ++ ++config RAETH_TSO ++ bool "TSOV4 (Tcp Segmentaton Offload)" ++ depends on (RAETH_HW_VLAN_TX && (RALINK_RT6855 || RALINK_RT6855A || RALINK_MT7620))||((RALINK_MT7621 || ARCH_MT7623) &&(RAETH_HW_VLAN_TX || RAETH_GMAC2 )) ++ ++config RAETH_TSOV6 ++ bool "TSOV6 (Tcp Segmentaton Offload)" ++ depends on RAETH_TSO ++ ++config RAETH_RW_PDMAPTR_FROM_VAR ++ bool ++ default y if RALINK_RT6855A || RALINK_MT7620 ++ depends on RAETH ++ ++config MTK_SMB_HOOK ++ bool "Samba Speedup Module" ++ depends on RAETH ++ ++config SPLICE_NET_SUPPORT ++ default y if MTK_SMB_HOOK ++ depends on MTK_SMB_HOOK ++ bool ++ ++ ++config RAETH_DVT ++ bool "RAETH DVT" ++ depends on RAETH && (RALINK_MT7621 || ARCH_MT7623) ++ ++config RAETH_PDMA_DVT ++ bool "PDMA DVT" ++ depends on RAETH_DVT ++ ++config RAETH_PDMA_LEGACY_MODE ++ bool "PDMA legacy mode" ++ depends on RAETH_PDMA_DVT ++ ++#config RAETH_QOS ++# bool "QoS Feature" ++# depends on RAETH && !RALINK_RT2880 && !RALINK_MT7620 && !RALINK_MT7621 && !RAETH_TSO ++ ++choice ++ prompt "QoS Type" ++ depends on RAETH_QOS ++ default DSCP_QOS_DSCP ++ ++config RAETH_QOS_DSCP_BASED ++ bool "DSCP-based" ++ depends on RAETH_QOS ++ ++config RAETH_QOS_VPRI_BASED ++ bool "VPRI-based" ++ depends on RAETH_QOS ++ ++endchoice ++ ++config RAETH_QDMA ++ bool "Choose QDMA instead PDMA" ++ default n ++ depends on RAETH && (RALINK_MT7621 || ARCH_MT7623) ++ ++config RAETH_QDMATX_QDMARX ++ bool "Choose QDMA RX instead PDMA RX" ++ default n ++ depends on RAETH_QDMA && !RALINK_MT7621 ++ ++ ++ ++choice ++ prompt "GMAC is connected to" ++ depends on RAETH ++ default GE1_RGMII_FORCE_1000 ++ ++config GE1_MII_FORCE_100 ++ bool "MII_FORCE_100 (10/100M Switch)" ++ depends on (RALINK_RT2880 || RALINK_RT3883 || RALINK_MT7621) ++ ++config GE1_MII_AN ++ bool "MII_AN (100Phy)" ++ depends on (RALINK_RT2880 || RALINK_RT3883 || RALINK_MT7621) ++ ++config GE1_RVMII_FORCE_100 ++ bool "RvMII_FORCE_100 (CPU)" ++ depends on (RALINK_RT2880 || RALINK_RT3883 || RALINK_MT7621) ++ ++config GE1_RGMII_FORCE_1000 ++ bool "RGMII_FORCE_1000 (GigaSW, CPU)" ++ depends on (RALINK_RT2880 || RALINK_RT3883) ++ select RALINK_SPI ++ ++config GE1_RGMII_FORCE_1000 ++ bool "RGMII_FORCE_1000 (GigaSW, CPU)" ++ depends on (RALINK_MT7621 || ARCH_MT7623) ++ select RT_3052_ESW ++ ++config GE1_TRGMII_FORCE_1200 ++ bool "TRGMII_FORCE_1200 (GigaSW, CPU)" ++ depends on (RALINK_MT7621) ++ select RT_3052_ESW ++ ++config GE1_TRGMII_FORCE_2000 ++ bool "TRGMII_FORCE_2000 (GigaSW, CPU, for MT7623 and MT7683)" ++ depends on (ARCH_MT7623) ++ select RT_3052_ESW ++ ++config GE1_TRGMII_FORCE_2600 ++ bool "TRGMII_FORCE_2600 (GigaSW, CPU, MT7623 only)" ++ depends on (ARCH_MT7623) ++ select RT_3052_ESW ++ ++config GE1_RGMII_AN ++ bool "RGMII_AN (GigaPhy)" ++ depends on (RALINK_RT2880 || RALINK_RT3883 || RALINK_MT7621 || ARCH_MT7623) ++ ++config GE1_RGMII_NONE ++ bool "NONE (NO CONNECT)" ++ depends on (RALINK_MT7621 || ARCH_MT7623) ++ ++endchoice ++ ++config HW_SFQ ++ bool "HW_SFQ" ++ default n ++ depends on RAETH_QDMA && (ARCH_MT7623) ++ ++ ++config RT_3052_ESW ++ bool "Ralink Embedded Switch" ++ default y ++ depends on RAETH && (RALINK_RT3052 || RALINK_RT3352 || RALINK_RT5350 || RALINK_RT6855 || RALINK_RT6855A || RALINK_MT7620 || RALINK_MT7621 || RALINK_MT7628 || ARCH_MT7623) ++ ++config LAN_WAN_SUPPORT ++ bool "LAN/WAN Partition" ++ depends on RAETH && (RAETH_ROUTER || RT_3052_ESW) ++ ++config ETH_MEMORY_OPTIMIZATION ++ bool "Ethernet memory optimization" ++ depends on RALINK_MT7628 ++ ++config ETH_ONE_PORT_ONLY ++ bool "One Port Only" ++ depends on RALINK_MT7628 ++ ++choice ++ prompt "Switch Board Layout Type" ++ depends on LAN_WAN_SUPPORT || P5_RGMII_TO_MAC_MODE || GE1_RGMII_FORCE_1000 || GE1_TRGMII_FORCE_1200 || GE2_RGMII_FORCE_1000 ++ default WAN_AT_P0 ++ ++ config WAN_AT_P4 ++ bool "LLLL/W" ++ ++ config WAN_AT_P0 ++ bool "W/LLLL" ++endchoice ++ ++config RALINK_VISTA_BASIC ++ bool 'Vista Basic Logo for IC+ 175C' ++ depends on LAN_WAN_SUPPORT && (RALINK_RT2880 || RALINK_RT3883) ++ ++config ESW_DOUBLE_VLAN_TAG ++ bool ++ default y if RT_3052_ESW ++ ++config RAETH_HAS_PORT4 ++ bool "Port 4 Support" ++ depends on RAETH && RALINK_MT7620 ++choice ++ prompt "Target Mode" ++ depends on RAETH_HAS_PORT4 ++ default P4_RGMII_TO_MAC_MODE ++ ++ config P4_MAC_TO_PHY_MODE ++ bool "Giga_Phy (RGMII)" ++ config GE_RGMII_MT7530_P0_AN ++ bool "GE_RGMII_MT7530_P0_AN (MT7530 Internal GigaPhy)" ++ config GE_RGMII_MT7530_P4_AN ++ bool "GE_RGMII_MT7530_P4_AN (MT7530 Internal GigaPhy)" ++ config P4_RGMII_TO_MAC_MODE ++ bool "Giga_SW/iNIC (RGMII)" ++ config P4_MII_TO_MAC_MODE ++ bool "External_CPU (MII_RvMII)" ++ config P4_RMII_TO_MAC_MODE ++ bool "External_CPU (RvMII_MII)" ++endchoice ++ ++config MAC_TO_GIGAPHY_MODE_ADDR2 ++ hex "Port4 Phy Address" ++ default 0x4 ++ depends on P4_MAC_TO_PHY_MODE ++ ++config RAETH_HAS_PORT5 ++ bool "Port 5 Support" ++ depends on RAETH && (RALINK_RT3052 || RALINK_RT3352 || RALINK_RT6855 || RALINK_RT6855A || RALINK_MT7620) ++choice ++ prompt "Target Mode" ++ depends on RAETH_HAS_PORT5 ++ default P5_RGMII_TO_MAC_MODE ++ ++ config P5_MAC_TO_PHY_MODE ++ bool "Giga_Phy (RGMII)" ++ config P5_RGMII_TO_MAC_MODE ++ bool "Giga_SW/iNIC (RGMII)" ++ config P5_RGMII_TO_MT7530_MODE ++ bool "MT7530 Giga_SW (RGMII)" ++ depends on RALINK_MT7620 ++ config P5_MII_TO_MAC_MODE ++ bool "External_CPU (MII_RvMII)" ++ config P5_RMII_TO_MAC_MODE ++ bool "External_CPU (RvMII_MII)" ++endchoice ++ ++config MAC_TO_GIGAPHY_MODE_ADDR ++ hex "GE1 Phy Address" ++ default 0x1F ++ depends on GE1_MII_AN || GE1_RGMII_AN ++ ++config MAC_TO_GIGAPHY_MODE_ADDR ++ hex "Port5 Phy Address" ++ default 0x5 ++ depends on P5_MAC_TO_PHY_MODE ++ ++config RAETH_GMAC2 ++ bool "GMAC2 Support" ++ depends on RAETH && (RALINK_RT3883 || RALINK_MT7621 || ARCH_MT7623) ++ ++choice ++ prompt "GMAC2 is connected to" ++ depends on RAETH_GMAC2 ++ default GE2_RGMII_AN ++ ++config GE2_MII_FORCE_100 ++ bool "MII_FORCE_100 (10/100M Switch)" ++ depends on RAETH_GMAC2 ++ ++config GE2_MII_AN ++ bool "MII_AN (100Phy)" ++ depends on RAETH_GMAC2 ++ ++config GE2_RVMII_FORCE_100 ++ bool "RvMII_FORCE_100 (CPU)" ++ depends on RAETH_GMAC2 ++ ++config GE2_RGMII_FORCE_1000 ++ bool "RGMII_FORCE_1000 (GigaSW, CPU)" ++ depends on RAETH_GMAC2 ++ select RALINK_SPI ++ ++config GE2_RGMII_AN ++ bool "RGMII_AN (External GigaPhy)" ++ depends on RAETH_GMAC2 ++ ++config GE2_INTERNAL_GPHY ++ bool "RGMII_AN (Internal GigaPny)" ++ depends on RAETH_GMAC2 ++ select LAN_WAN_SUPPORT ++ ++endchoice ++ ++config GE_RGMII_INTERNAL_P0_AN ++ bool ++ depends on GE2_INTERNAL_GPHY ++ default y if WAN_AT_P0 ++ ++config GE_RGMII_INTERNAL_P4_AN ++ bool ++ depends on GE2_INTERNAL_GPHY ++ default y if WAN_AT_P4 ++ ++config MAC_TO_GIGAPHY_MODE_ADDR2 ++ hex ++ default 0 if GE_RGMII_INTERNAL_P0_AN ++ default 4 if GE_RGMII_INTERNAL_P4_AN ++ depends on GE_RGMII_INTERNAL_P0_AN || GE_RGMII_INTERNAL_P4_AN ++ ++config MAC_TO_GIGAPHY_MODE_ADDR2 ++ hex "GE2 Phy Address" ++ default 0x1E ++ depends on GE2_MII_AN || GE2_RGMII_AN ++ ++#force 100M ++config RAETH_ROUTER ++bool ++default y if GE1_MII_FORCE_100 || GE2_MII_FORCE_100 || GE1_RVMII_FORCE_100 || GE2_RVMII_FORCE_100 ++ ++#force 1000M ++config MAC_TO_MAC_MODE ++bool ++default y if GE1_RGMII_FORCE_1000 || GE2_RGMII_FORCE_1000 ++depends on (RALINK_RT2880 || RALINK_RT3883) ++ ++#AN ++config GIGAPHY ++bool ++default y if GE1_RGMII_AN || GE2_RGMII_AN ++ ++#AN ++config 100PHY ++bool ++default y if GE1_MII_AN || GE2_MII_AN +diff --git a/drivers/net/ethernet/raeth/Makefile b/drivers/net/ethernet/raeth/Makefile +new file mode 100644 +index 0000000..563af05 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/Makefile +@@ -0,0 +1,67 @@ ++obj-$(CONFIG_RAETH) += raeth.o ++raeth-objs := ra_mac.o mii_mgr.o ra_rfrw.o ++ ++ifeq ($(CONFIG_MTK_SMB_HOOK),y) ++obj-y += smb_hook.o ++obj-m += smb.o ++smb-objs := smb_nf.o ++endif ++ ++#EXTRA_CFLAGS += -DCONFIG_RAETH_MULTIPLE_RX_RING ++ ++ifeq ($(CONFIG_RAETH_QOS),y) ++raeth-objs += ra_qos.o ++endif ++ ++ifeq ($(CONFIG_RAETH_QDMA),y) ++raeth-objs += raether_qdma.o ++endif ++ ++ifneq ($(CONFIG_RAETH_QDMA),y) ++raeth-objs += raether_pdma.o ++endif ++ ++raeth-objs += raether.o ++ ++ifeq ($(CONFIG_ETHTOOL),y) ++raeth-objs += ra_ethtool.o ++endif ++ ++ifeq ($(CONFIG_RALINK_RT3052_MP2),y) ++raeth-objs += mcast.o ++endif ++ ++ifeq ($(CONFIG_RAETH_NETLINK),y) ++raeth-objs += ra_netlink.o ++endif ++ ++ifeq ($(CONFIG_RAETH_PDMA_DVT),y) ++raeth-objs += dvt/raether_pdma_dvt.o ++obj-m += dvt/pkt_gen.o ++obj-m += dvt/pkt_gen_udp_frag.o ++obj-m += dvt/pkt_gen_tcp_frag.o ++endif ++ ++ifeq ($(CONFIG_RAETH_HW_LRO),y) ++raeth-objs += raether_hwlro.o ++endif ++ ++ifeq ($(CONFIG_RAETH_GMAC2),y) ++EXTRA_CFLAGS += -DCONFIG_PSEUDO_SUPPORT ++endif ++ ++ifeq ($(CONFIG_ETH_MEMORY_OPTIMIZATION),y) ++EXTRA_CFLAGS += -DMEMORY_OPTIMIZATION ++endif ++ ++ifeq ($(CONFIG_RT2860V2_AP_MEMORY_OPTIMIZATION),y) ++EXTRA_CFLAGS += -DMEMORY_OPTIMIZATION ++endif ++ ++ifeq ($(CONFIG_RA_NETWORK_WORKQUEUE_BH),y) ++EXTRA_CFLAGS += -DWORKQUEUE_BH ++endif ++ ++ifeq ($(CONFIG_TASKLET_WORKQUEUE_SW),y) ++EXTRA_CFLAGS += -DTASKLET_WORKQUEUE_SW ++endif +diff --git a/drivers/net/ethernet/raeth/Makefile.release b/drivers/net/ethernet/raeth/Makefile.release +new file mode 100644 +index 0000000..ecdeeda +--- /dev/null ++++ b/drivers/net/ethernet/raeth/Makefile.release +@@ -0,0 +1,60 @@ ++obj-$(CONFIG_RAETH) += raeth.o ++raeth-objs := ra_mac.o mii_mgr.o ra_rfrw.o ++ ++ifeq ($(CONFIG_MTK_SMB_HOOK),y) ++obj-y += smb_hook.o ++obj-m += smb.o ++smb-objs := smb_nf.o ++endif ++ ++#EXTRA_CFLAGS += -DCONFIG_RAETH_MULTIPLE_RX_RING ++ ++ifeq ($(CONFIG_RAETH_QOS),y) ++raeth-objs += ra_qos.o ++endif ++ ++ifeq ($(CONFIG_RAETH_QDMA),y) ++raeth-objs += raether_qdma.o ++endif ++ ++ifneq ($(CONFIG_RAETH_QDMA),y) ++raeth-objs += raether_pdma.o ++endif ++ ++raeth-objs += raether.o ++ ++ifeq ($(CONFIG_ETHTOOL),y) ++raeth-objs += ra_ethtool.o ++endif ++ ++ifeq ($(CONFIG_RALINK_RT3052_MP2),y) ++raeth-objs += mcast.o ++endif ++ ++ifeq ($(CONFIG_RAETH_NETLINK),y) ++raeth-objs += ra_netlink.o ++endif ++ ++ifeq ($(CONFIG_RAETH_HW_LRO),y) ++raeth-objs += raether_hwlro.o ++endif ++ ++ifeq ($(CONFIG_RAETH_GMAC2),y) ++EXTRA_CFLAGS += -DCONFIG_PSEUDO_SUPPORT ++endif ++ ++ifeq ($(CONFIG_ETH_MEMORY_OPTIMIZATION),y) ++EXTRA_CFLAGS += -DMEMORY_OPTIMIZATION ++endif ++ ++ifeq ($(CONFIG_RT2860V2_AP_MEMORY_OPTIMIZATION),y) ++EXTRA_CFLAGS += -DMEMORY_OPTIMIZATION ++endif ++ ++ifeq ($(CONFIG_RA_NETWORK_WORKQUEUE_BH),y) ++EXTRA_CFLAGS += -DWORKQUEUE_BH ++endif ++ ++ifeq ($(CONFIG_TASKLET_WORKQUEUE_SW),y) ++EXTRA_CFLAGS += -DTASKLET_WORKQUEUE_SW ++endif +diff --git a/drivers/net/ethernet/raeth/csr_netlink.h b/drivers/net/ethernet/raeth/csr_netlink.h +new file mode 100644 +index 0000000..add7745 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/csr_netlink.h +@@ -0,0 +1,27 @@ ++#ifndef CSR_NETLINK_H ++#define CSR_NETLINK_H ++ ++#define CSR_NETLINK 30 ++#define CSR_READ 0 ++#define CSR_WRITE 1 ++#define CSR_TEST 2 ++ ++#define RALINK_CSR_GROUP 2882 ++ ++typedef struct rt2880_csr_msg { ++ int enable; ++ char reg_name[32]; ++ unsigned long address; ++ unsigned long default_value; ++ unsigned long reserved_bits; /* 1 : not reserved, 0 : reserved */ ++ unsigned long write_mask; ++ unsigned long write_value; ++ int status; ++} CSR_MSG; ++ ++int csr_msg_send(CSR_MSG* msg); ++int csr_msg_recv(void); ++ ++// static CSR_MSG input_csr_msg; ++ ++#endif +diff --git a/drivers/net/ethernet/raeth/dvt/pkt_gen.c b/drivers/net/ethernet/raeth/dvt/pkt_gen.c +new file mode 100755 +index 0000000..b351b21 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/dvt/pkt_gen.c +@@ -0,0 +1,88 @@ ++//#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++char *ifname="eth3"; ++ ++static int32_t PktGenInitMod(void) ++{ ++ ++ struct net_dev *dev; ++ struct sk_buff *skb; ++ int i=0; ++ ++ unsigned char pkt[]={ ++ //0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // dest bcast mac ++ 0x00, 0x21, 0x86, 0xee, 0xe3, 0x95, // dest macA ++ //0x00, 0x30, 0xdb, 0x02, 0x02, 0x01, // dest macB ++ 0x00, 0x0c, 0x43, 0x28, 0x80, 0x33, // src mac ++ 0x81, 0x00, // vlan tag ++ //0x81, 0x10, // vlan tag ++ //0x87, 0x39, // do not learn ++ //0xc1, 0x03, // vlan tag SA=0, VID=2, LV=1 ++ 0x00, 0x03, // pri=0, vlan=3 ++ 0x08, 0x00, // eth type=ip ++ 0x45, 0x00, 0x00, 0x30, 0x12, 0x34, 0x40, 0x00, 0xff, 0x06, ++ 0x40, 0x74, 0x0a, 0x0a, 0x1e, 0x0a, 0x0a, 0x0a, 0x1e, 0x0b, ++ 0x00, 0x1e, 0x00, 0x28, 0x00, 0x1c, 0x81, 0x06, 0x00, 0x00, ++ 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; ++ ++ skb = alloc_skb(256, GFP_ATOMIC); ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ if((dev=dev_get_by_name(&init_net,ifname))){ ++#else ++ if((dev=dev_get_by_name(ifname))){ ++#endif ++ ++ ++ ++ skb->dev=dev; ++ skb_put(skb,sizeof(pkt)); ++ memcpy(skb->data, pkt, sizeof(pkt)); ++ ++ printk("send pkt(len=%d) to %s\n", skb->len, skb->dev->name); ++ ++ ++ for(i=0;idata[i]); ++ } ++ ++ dev_queue_xmit(skb); ++ }else{ ++ printk("interface %s not found\n",ifname); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static void PktGenCleanupMod(void) ++{ ++} ++ ++module_init(PktGenInitMod); ++module_exit(PktGenCleanupMod); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12) ++MODULE_PARM (ifname, "s"); ++#else ++module_param (ifname, charp, 0); ++#endif ++ ++MODULE_DESCRIPTION("Ralink PktGen Module"); ++MODULE_AUTHOR("Steven Liu"); ++MODULE_LICENSE("Proprietary"); ++MODULE_PARM_DESC (ifname, "interface name"); ++ +diff --git a/drivers/net/ethernet/raeth/dvt/pkt_gen_tcp_frag.c b/drivers/net/ethernet/raeth/dvt/pkt_gen_tcp_frag.c +new file mode 100755 +index 0000000..e78c65a +--- /dev/null ++++ b/drivers/net/ethernet/raeth/dvt/pkt_gen_tcp_frag.c +@@ -0,0 +1,138 @@ ++//#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++char *ifname="eth3"; ++ ++ ++static int32_t PktGenInitMod(void) ++{ ++ unsigned char pkt_1[]={ ++ 0x00, 0x21, 0x86, 0xee, 0xe3, 0x90, // dest mac ++ 0x00, 0x0c, 0x43, 0x28, 0x80, 0x33, // src mac ++ 0x08, 0x00, // type: ip ++ 0x45, 0x00, 0x00, 0x34, // ip: ..., total len (0x034 = 52) ++ 0xa1, 0x78, 0x20, 0x00, // ip: id, frag, frag offset ++ 0x80, 0x06, 0x63, 0x07, // ip: ttl, protocol, hdr checksum (0x6307) ++ 0x0a, 0x0a, 0x1e, 0x7b, // src ip (10.10.30.123) ++ 0x0a, 0x0a, 0x1e, 0x05, // dst ip (10.10.30.5) ++ 0x0d, 0xd5, //tcp src port ++ 0x13, 0x89, //tcp dst port ++ 0x40, 0xf5, 0x15, 0x04, //tcp sequence number ++ 0xf6, 0x4f, 0x1e, 0x31, //tcp ack number ++ 0x50, 0x10, 0xfc, 0x00, //tcp flags, win size ++ 0xf1, 0xfe, 0x00, 0x00, //tcp checksum (0xf1fe) ++ 0x01, 0x02, 0x03, 0x04, 0x05, //payload (12 bytes) ++ 0x06, 0x07, 0x08, 0x09, 0x0a, ++ 0x0b, 0x0c ++ }; ++ ++ unsigned char pkt_2[]={ ++ 0x00, 0x21, 0x86, 0xee, 0xe3, 0x90, // dest mac ++ 0x00, 0x0c, 0x43, 0x28, 0x80, 0x33, // src mac ++ 0x08, 0x00, // type: ip ++ 0x45, 0x00, 0x00, 0x20, // ip: ..., total len (0x020 = 32) ++ 0xa1, 0x78, 0x00, 0x04, // ip: id, frag, frag offset (32) ++ 0x40, 0x11, 0x63, 0x07, // ip: ttl, protocol, hdr checksum (0x6307) ++ 0x0a, 0x0a, 0x1e, 0x7b, // src ip (10.10.30.123) ++ 0x0a, 0x0a, 0x1e, 0x05, // dst ip (10.10.30.5) ++ 0x11, 0x12, 0x13, 0x14, 0x15, //payload (12 bytes) ++ 0x16, 0x17, 0x18, 0x19, 0x1a, ++ 0x1b, 0x1c ++ }; ++ ++ struct net_dev *dev; ++ struct sk_buff *skb_1; ++ struct sk_buff *skb_2; ++ int i=0; ++ ++ skb_1 = alloc_skb(256, GFP_ATOMIC); ++ skb_2 = alloc_skb(256, GFP_ATOMIC); ++ ++ ++#if 1 ++/* send packet 1 */ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ if((dev=dev_get_by_name(&init_net,ifname))){ ++#else ++ if((dev=dev_get_by_name(ifname))){ ++#endif ++ ++ skb_1->dev=dev; ++ skb_put(skb_1,sizeof(pkt_1)); ++ memcpy(skb_1->data, pkt_1, sizeof(pkt_1)); ++ ++ printk("send pkt(len=%d) to %s\n", skb_1->len, skb_1->dev->name); ++ ++ ++ for(i=0;idata[i]); ++ } ++ ++ dev_queue_xmit(skb_1); ++ }else{ ++ printk("interface %s not found\n",ifname); ++ return 1; ++ } ++#endif ++ ++#if 1 ++/* send packet 2 */ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ if((dev=dev_get_by_name(&init_net,ifname))){ ++#else ++ if((dev=dev_get_by_name(ifname))){ ++#endif ++ ++ skb_2->dev=dev; ++ skb_put(skb_2,sizeof(pkt_2)); ++ memcpy(skb_2->data, pkt_2, sizeof(pkt_2)); ++ ++ printk("send pkt(len=%d) to %s\n", skb_2->len, skb_2->dev->name); ++ ++ ++ for(i=0;idata[i]); ++ } ++ ++ dev_queue_xmit(skb_2); ++ }else{ ++ printk("interface %s not found\n",ifname); ++ return 1; ++ } ++#endif ++ ++ return 0; ++} ++ ++static void PktGenCleanupMod(void) ++{ ++} ++ ++module_init(PktGenInitMod); ++module_exit(PktGenCleanupMod); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12) ++MODULE_PARM (ifname, "s"); ++#else ++module_param (ifname, charp, 0); ++#endif ++ ++MODULE_DESCRIPTION("Ralink PktGen Module"); ++MODULE_AUTHOR("Steven Liu"); ++MODULE_LICENSE("Proprietary"); ++MODULE_PARM_DESC (ifname, "interface name"); ++ +diff --git a/drivers/net/ethernet/raeth/dvt/pkt_gen_udp_frag.c b/drivers/net/ethernet/raeth/dvt/pkt_gen_udp_frag.c +new file mode 100755 +index 0000000..917e7ad +--- /dev/null ++++ b/drivers/net/ethernet/raeth/dvt/pkt_gen_udp_frag.c +@@ -0,0 +1,191 @@ ++//#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++char *ifname="eth3"; ++ ++ ++static int32_t PktGenInitMod(void) ++{ ++#if 0 ++ unsigned char pkt_0[]={ ++// 0x00, 0x21, 0x86, 0xee, 0xe3, 0x95, // dest mac ++ 0x00, 0x21, 0x86, 0xee, 0xe3, 0x90, // dest mac ++ 0x00, 0x0c, 0x43, 0x28, 0x80, 0x33, // src mac ++ 0x08, 0x00, // type: ip ++ 0x45, 0x00, 0x00, 0x26, // ip: ..., total len (0x026 = 38) ++// 0xa1, 0x78, 0x20, 0x00, // ip: id, frag, frag offset ++ 0xa1, 0x78, 0x40, 0x00, // ip: id, frag, frag offset ++ 0x40, 0x11, 0x63, 0x07, // ip: ttl, protocol, hdr checksum (0x6307) ++ 0x0a, 0x0a, 0x1e, 0x7b, // src ip (10.10.30.123) ++// 0x0a, 0x0a, 0x1e, 0x03, // dst ip (10.10.30.3) ++ 0x0a, 0x0a, 0x1e, 0x05, // dst ip (10.10.30.5) ++ 0xca, 0x7b, //udp src port ++ 0x13, 0x89, //udp dst port ++ 0x00, 0x12, //udp len (0x01c = 18) ++ 0x2f, 0x96, //udp checksum (0x2f96) ++ 0x01, 0x02, 0x03, 0x04, 0x05, //payload (10 bytes) ++ 0x06, 0x07, 0x08, 0x09, 0x0a ++ }; ++#endif ++ ++ unsigned char pkt_1[]={ ++// 0x00, 0x21, 0x86, 0xee, 0xe3, 0x95, // dest mac ++ 0x00, 0x21, 0x86, 0xee, 0xe3, 0x90, // dest mac ++ 0x00, 0x0c, 0x43, 0x28, 0x80, 0x33, // src mac ++ 0x08, 0x00, // type: ip ++ 0x45, 0x00, 0x00, 0x24, // ip: ..., total len (0x024 = 36) ++ 0xa1, 0x78, 0x20, 0x00, // ip: id, frag, frag offset ++// 0xa1, 0x78, 0x40, 0x00, // ip: id, frag, frag offset ++ 0x40, 0x11, 0x63, 0x07, // ip: ttl, protocol, hdr checksum (0x6307) ++ 0x0a, 0x0a, 0x1e, 0x7b, // src ip (10.10.30.123) ++// 0x0a, 0x0a, 0x1e, 0x03, // dst ip (10.10.30.3) ++ 0x0a, 0x0a, 0x1e, 0x05, // dst ip (10.10.30.5) ++ 0xca, 0x7b, //udp src port ++ 0x13, 0x89, //udp dst port ++ 0x00, 0x1a, //udp len (0x01a = 26) ++ 0x2f, 0x96, //udp checksum (0x2f96) ++ 0x01, 0x02, 0x03, 0x04, 0x05, //payload (8 bytes) ++ 0x06, 0x07, 0x08 ++ }; ++ ++ unsigned char pkt_2[]={ ++// 0x00, 0x21, 0x86, 0xee, 0xe3, 0x95, // dest mac ++ 0x00, 0x21, 0x86, 0xee, 0xe3, 0x90, // dest mac ++ 0x00, 0x0c, 0x43, 0x28, 0x80, 0x33, // src mac ++ 0x08, 0x00, // type: ip ++ 0x45, 0x00, 0x00, 0x1e, // ip: ..., total len (0x01e = 30) ++ 0xa1, 0x78, 0x00, 0x02, // ip: id, frag, frag offset (16) ++ 0x40, 0x11, 0x63, 0x07, // ip: ttl, protocol, hdr checksum (0x6307) ++ 0x0a, 0x0a, 0x1e, 0x7b, // src ip (10.10.30.123) ++// 0x0a, 0x0a, 0x1e, 0x03, // dst ip (10.10.30.3) ++ 0x0a, 0x0a, 0x1e, 0x05, // dst ip (10.10.30.5) ++ 0x11, 0x12, 0x13, 0x14, 0x15, //payload (10 bytes) ++ 0x16, 0x17, 0x18, 0x19, 0x1a ++ }; ++ ++ struct net_dev *dev; ++// struct sk_buff *skb_0; ++ struct sk_buff *skb_1; ++ struct sk_buff *skb_2; ++ int i=0; ++ ++// skb_0 = alloc_skb(256, GFP_ATOMIC); ++ skb_1 = alloc_skb(256, GFP_ATOMIC); ++ skb_2 = alloc_skb(256, GFP_ATOMIC); ++ ++#if 0 ++/* send packet 0 */ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ if((dev=dev_get_by_name(&init_net,ifname))){ ++#else ++ if((dev=dev_get_by_name(ifname))){ ++#endif ++ ++ skb_0->dev=dev; ++ skb_put(skb_0,sizeof(pkt_0)); ++ memcpy(skb_0->data, pkt_0, sizeof(pkt_0)); ++ ++ printk("send pkt(len=%d) to %s\n", skb_0->len, skb_0->dev->name); ++ ++ ++ for(i=0;idata[i]); ++ } ++ ++ dev_queue_xmit(skb_0); ++ }else{ ++ printk("interface %s not found\n",ifname); ++ return 1; ++ } ++#endif ++ ++#if 1 ++/* send packet 1 */ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ if((dev=dev_get_by_name(&init_net,ifname))){ ++#else ++ if((dev=dev_get_by_name(ifname))){ ++#endif ++ ++ skb_1->dev=dev; ++ skb_put(skb_1,sizeof(pkt_1)); ++ memcpy(skb_1->data, pkt_1, sizeof(pkt_1)); ++ ++ printk("send pkt(len=%d) to %s\n", skb_1->len, skb_1->dev->name); ++ ++ ++ for(i=0;idata[i]); ++ } ++ ++ dev_queue_xmit(skb_1); ++ }else{ ++ printk("interface %s not found\n",ifname); ++ return 1; ++ } ++#endif ++ ++#if 1 ++/* send packet 2 */ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ if((dev=dev_get_by_name(&init_net,ifname))){ ++#else ++ if((dev=dev_get_by_name(ifname))){ ++#endif ++ ++ skb_2->dev=dev; ++ skb_put(skb_2,sizeof(pkt_2)); ++ memcpy(skb_2->data, pkt_2, sizeof(pkt_2)); ++ ++ printk("send pkt(len=%d) to %s\n", skb_2->len, skb_2->dev->name); ++ ++ ++ for(i=0;idata[i]); ++ } ++ ++ dev_queue_xmit(skb_2); ++ }else{ ++ printk("interface %s not found\n",ifname); ++ return 1; ++ } ++#endif ++ ++ return 0; ++} ++ ++static void PktGenCleanupMod(void) ++{ ++} ++ ++module_init(PktGenInitMod); ++module_exit(PktGenCleanupMod); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12) ++MODULE_PARM (ifname, "s"); ++#else ++module_param (ifname, charp, 0); ++#endif ++ ++MODULE_DESCRIPTION("Ralink PktGen Module"); ++MODULE_AUTHOR("Steven Liu"); ++MODULE_LICENSE("Proprietary"); ++MODULE_PARM_DESC (ifname, "interface name"); ++ +diff --git a/drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.c b/drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.c +new file mode 100755 +index 0000000..971a821 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.c +@@ -0,0 +1,1527 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if defined(CONFIG_RAETH_TSO) ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#endif ++#if defined(CONFIG_RAETH_LRO) ++#include ++#endif ++#include ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35) ++#include ++#endif ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 0) ++#include ++#else ++#include ++#endif ++ ++#include "../ra2882ethreg.h" ++#include "../raether.h" ++#include "../ra_mac.h" ++#include "../ra_ioctl.h" ++#include "../ra_rfrw.h" ++#ifdef CONFIG_RAETH_NETLINK ++#include "../ra_netlink.h" ++#endif ++#if defined(CONFIG_RAETH_QOS) ++#include "../ra_qos.h" ++#endif ++#include "raether_pdma_dvt.h" ++ ++/* Global variables */ ++static unsigned int g_pdma_dvt_show_config; ++static unsigned int g_pdma_dvt_rx_test_config; ++static unsigned int g_pdma_dvt_tx_test_config; ++static unsigned int g_pdma_dvt_debug_test_config; ++static unsigned int g_pdma_dvt_lro_test_config; ++ ++unsigned int g_pdma_dev_lanport = 0; ++unsigned int g_pdma_dev_wanport = 0; ++ ++void skb_dump(struct sk_buff *sk) ++{ ++ unsigned int i; ++ ++ printk("skb_dump: from %s with len %d (%d) headroom=%d tailroom=%d\n", ++ sk->dev ? sk->dev->name : "ip stack", sk->len, sk->truesize, ++ skb_headroom(sk), skb_tailroom(sk)); ++ ++ /* for(i=(unsigned int)sk->head;i<=(unsigned int)sk->tail;i++) { */ ++ /* for(i=(unsigned int)sk->head;i<=(unsigned int)sk->data+20;i++) { */ ++ for (i = (unsigned int)sk->head; i <= (unsigned int)sk->data + 60; i++) { ++ if ((i % 20) == 0) ++ printk("\n"); ++ if (i == (unsigned int)sk->data) ++ printk("{"); ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 21) ++ if (i == (unsigned int)sk->transport_header) ++ printk("#"); ++ if (i == (unsigned int)sk->network_header) ++ printk("|"); ++ if (i == (unsigned int)sk->mac_header) ++ printk("*"); ++#else ++ if (i == (unsigned int)sk->h.raw) ++ printk("#"); ++ if (i == (unsigned int)sk->nh.raw) ++ printk("|"); ++ if (i == (unsigned int)sk->mac.raw) ++ printk("*"); ++#endif ++ printk("%02X-", *((unsigned char *)i)); ++ if (i == (unsigned int)sk->tail) ++ printk("}"); ++ } ++ printk("\n"); ++} ++ ++#if defined(CONFIG_RAETH_HW_LRO) ++/* PDMA LRO test functions start */ ++int pdma_lro_disable_dvt(void) ++{ ++ unsigned int regVal = 0; ++ ++ printk("pdma_lro_disable_dvt()\n"); ++ ++ /* 1. Invalid LRO ring1~3 */ ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 0); ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 0); ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 0); ++ ++ /* 2 Polling relinguish */ ++ while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) {; ++ } ++ ++ /* 3. Disable LRO */ ++ regVal = sysRegRead(ADMA_LRO_CTRL_DW0); ++ regVal &= ~(PDMA_LRO_EN); ++ sysRegWrite(ADMA_LRO_CTRL_DW0, regVal); ++ ++#if 0 ++ /* 4. Disable non-lro multiple rx */ ++ SET_PDMA_NON_LRO_MULTI_EN(0); ++ ++ /* 5.1. Set GDM1 to ring0 */ ++ SET_GDM_PID1_RXID_SEL(0); ++ /* 5.2. Set GDM2 to ring0 */ ++ SET_GDM_PID2_RXID_SEL(0); ++#endif ++ ++ return 0; ++} ++ ++int pdma_lro_force_aggre_dvt(void) ++{ ++ unsigned int regVal = 0; ++ unsigned int ip; ++ ++ printk("pdma_lro_force_aggre_dvt()\n"); ++ ++/* pdma rx ring1 */ ++ /* 1. Set RX ring mode to force port */ ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_FORCE_PORT); ++ ++ /* 2. Configure lro ring */ ++ /* 2.1 set src/destination TCP ports */ ++ SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING1, 3423); ++ SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING1, 2301); ++ /* 2.2 set src/destination IPs */ ++ str_to_ip(&ip, "10.10.10.3"); ++ sysRegWrite(LRO_RX_RING1_SIP_DW0, ip); ++ str_to_ip(&ip, "10.10.10.100"); ++ sysRegWrite(LRO_RX_RING1_DIP_DW0, ip); ++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING1, 1); ++ ++ /* 2.3 Valid LRO ring */ ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1); ++ ++ /* 2.4 Set AGE timer */ ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, 0); ++ ++ /* 2.5 Set max AGG timer */ ++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING1, 0); ++ ++ /* 2.6 Set max LRO agg count */ ++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING1, HW_LRO_MAX_AGG_CNT); ++ ++ /* 3. IPv4 checksum update enable */ ++ SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1); ++ ++ /* 4. Polling relinguish */ ++ while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) {; ++ } ++ ++ /* 5. Enable LRO */ ++ regVal = sysRegRead(ADMA_LRO_CTRL_DW0); ++ regVal |= PDMA_LRO_EN; ++ sysRegWrite(ADMA_LRO_CTRL_DW0, regVal); ++ ++ return 0; ++} ++ ++int pdma_lro_auto_aggre_dvt(void) ++{ ++ unsigned int regVal = 0; ++ unsigned int ip; ++ ++ printk("pdma_lro_auto_aggre_dvt()\n"); ++ ++ /* 1.1 Set my IP_1 */ ++ str_to_ip(&ip, "10.10.10.254"); ++ sysRegWrite(LRO_RX_RING0_DIP_DW0, ip); ++ sysRegWrite(LRO_RX_RING0_DIP_DW1, 0); ++ sysRegWrite(LRO_RX_RING0_DIP_DW2, 0); ++ sysRegWrite(LRO_RX_RING0_DIP_DW3, 0); ++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING0, 1); ++ ++ /* 1.2 Set my IP_2 */ ++ str_to_ip(&ip, "10.10.20.254"); ++ sysRegWrite(LRO_RX_RING1_DIP_DW0, ip); ++ sysRegWrite(LRO_RX_RING1_DIP_DW1, 0); ++ sysRegWrite(LRO_RX_RING1_DIP_DW2, 0); ++ sysRegWrite(LRO_RX_RING1_DIP_DW3, 0); ++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING1, 1); ++ ++ /* 1.3 Set my IP_3 */ ++ sysRegWrite(LRO_RX_RING2_DIP_DW3, 0x20010238); ++ sysRegWrite(LRO_RX_RING2_DIP_DW2, 0x08000000); ++ sysRegWrite(LRO_RX_RING2_DIP_DW1, 0x00000000); ++ sysRegWrite(LRO_RX_RING2_DIP_DW0, 0x00000254); ++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING2, 1); ++ ++ /* 1.4 Set my IP_4 */ ++ sysRegWrite(LRO_RX_RING3_DIP_DW3, 0x20010238); ++ sysRegWrite(LRO_RX_RING3_DIP_DW2, 0x08010000); ++ sysRegWrite(LRO_RX_RING3_DIP_DW1, 0x00000000); ++ sysRegWrite(LRO_RX_RING3_DIP_DW0, 0x00000254); ++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING3, 1); ++ ++ /* 2.1 Set RX ring1~3 to auto-learn modes */ ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_AUTO_LEARN); ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_AUTO_LEARN); ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_AUTO_LEARN); ++ ++ /* 2.2 Valid LRO ring */ ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING0, 1); ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1); ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 1); ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 1); ++ ++ /* 2.3 Set AGE timer */ ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, 0); ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, 0); ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, 0); ++ ++ /* 2.4 Set max AGG timer */ ++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING1, 0); ++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING2, 0); ++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING3, 0); ++ ++ /* 2.5 Set max LRO agg count */ ++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING1, HW_LRO_MAX_AGG_CNT); ++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING2, HW_LRO_MAX_AGG_CNT); ++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING3, HW_LRO_MAX_AGG_CNT); ++ ++ /* 3.0 IPv6 LRO enable */ ++ SET_PDMA_LRO_IPV6_EN(1); ++ ++ /* 3.1 IPv4 checksum update disable */ ++ SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1); ++ ++ /* 3.2 switch priority comparision to byte count mode */ ++ SET_PDMA_LRO_ALT_SCORE_MODE(PDMA_LRO_ALT_BYTE_CNT_MODE); ++ ++ /* 3.3 bandwidth threshold setting */ ++ SET_PDMA_LRO_BW_THRESHOLD(0); ++ ++ /* 3.4 auto-learn score delta setting */ ++ sysRegWrite(LRO_ALT_SCORE_DELTA, 0); ++ ++ /* 3.5 Set ALT timer to 20us: (unit: 20us) */ ++ SET_PDMA_LRO_ALT_REFRESH_TIMER_UNIT(HW_LRO_TIMER_UNIT); ++ /* 3.6 Set ALT refresh timer to 1 sec. (unit: 20us) */ ++ SET_PDMA_LRO_ALT_REFRESH_TIMER(HW_LRO_REFRESH_TIME); ++ ++ /* 4. Polling relinguish */ ++ while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) {; ++ } ++ ++ /* 5. Enable LRO */ ++ regVal = sysRegRead(ADMA_LRO_CTRL_DW0); ++ regVal |= PDMA_LRO_EN; ++ sysRegWrite(ADMA_LRO_CTRL_DW0, regVal); ++ ++ return 0; ++} ++ ++int pdma_lro_auto_ipv6_dvt(void) ++{ ++ unsigned int regVal = 0; ++ ++ printk("pdma_lro_auto_ipv6_dvt()\n"); ++ ++ /* 1. Set my IP */ ++ sysRegWrite(LRO_RX_RING1_DIP_DW3, 0x20010238); ++ sysRegWrite(LRO_RX_RING1_DIP_DW2, 0x08000000); ++ sysRegWrite(LRO_RX_RING1_DIP_DW1, 0x00000000); ++ sysRegWrite(LRO_RX_RING1_DIP_DW0, 0x00000254); ++ ++ /* 2.1 Set RX ring1~3 to auto-learn modes */ ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_AUTO_LEARN); ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_AUTO_LEARN); ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_AUTO_LEARN); ++ ++ /* 2.2 Valid LRO ring */ ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1); ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 1); ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 1); ++ ++ /* 2.3 Set AGE timer */ ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, HW_LRO_AGE_TIME); ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, HW_LRO_AGE_TIME); ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, HW_LRO_AGE_TIME); ++ ++ /* 3.0 IPv6 LRO enable */ ++ SET_PDMA_LRO_IPV6_EN(1); ++ ++ /* 3.1 IPv4 checksum update disable */ ++ SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1); ++ ++ /* 3.2 switch priority comparision to byte count mode */ ++ SET_PDMA_LRO_ALT_SCORE_MODE(PDMA_LRO_ALT_BYTE_CNT_MODE); ++ ++ /* 3.3 bandwidth threshold setting */ ++ SET_PDMA_LRO_BW_THRESHOLD(0); ++ ++ /* 3.4 auto-learn score delta setting */ ++ sysRegWrite(LRO_ALT_SCORE_DELTA, 0); ++ ++ /* 3.5 Set ALT timer to 500us: (unit: 20us) */ ++ SET_PDMA_LRO_ALT_REFRESH_TIMER_UNIT(25); ++ /* 3.6 Set ALT refresh timer to 1 sec. (unit: 500us) */ ++ SET_PDMA_LRO_ALT_REFRESH_TIMER(2000); ++ ++ /* 3.7 Set max AGG timer: 10 msec. */ ++ SET_PDMA_LRO_MAX_AGG_TIME(HW_LRO_AGG_TIME); ++ ++ /* 4. Polling relinguish */ ++ while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) {; ++ } ++ ++ /* 5. Enable LRO */ ++ regVal = sysRegRead(ADMA_LRO_CTRL_DW0); ++ regVal |= PDMA_LRO_EN; ++ sysRegWrite(ADMA_LRO_CTRL_DW0, regVal); ++ ++ return 0; ++} ++ ++int pdma_lro_auto_myIP_dvt(void) ++{ ++ unsigned int regVal = 0; ++ unsigned int ip; ++ ++ printk("pdma_lro_auto_myIP_dvt()\n"); ++ ++ /* 1.1 Set my IP_1 */ ++ str_to_ip(&ip, "10.10.10.254"); ++ sysRegWrite(LRO_RX_RING0_DIP_DW0, ip); ++ sysRegWrite(LRO_RX_RING0_DIP_DW1, 0); ++ sysRegWrite(LRO_RX_RING0_DIP_DW2, 0); ++ sysRegWrite(LRO_RX_RING0_DIP_DW3, 0); ++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING0, 1); ++ /* 1.2 Set my IP_2 */ ++ str_to_ip(&ip, "10.10.20.254"); ++ sysRegWrite(LRO_RX_RING1_DIP_DW0, ip); ++ sysRegWrite(LRO_RX_RING1_DIP_DW1, 0); ++ sysRegWrite(LRO_RX_RING1_DIP_DW2, 0); ++ sysRegWrite(LRO_RX_RING1_DIP_DW3, 0); ++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING1, 1); ++ /* 1.3 Set my IP_3 */ ++ sysRegWrite(LRO_RX_RING2_DIP_DW3, 0x20010238); ++ sysRegWrite(LRO_RX_RING2_DIP_DW2, 0x08000000); ++ sysRegWrite(LRO_RX_RING2_DIP_DW1, 0x00000000); ++ sysRegWrite(LRO_RX_RING2_DIP_DW0, 0x00000254); ++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING2, 1); ++ /* 1.4 Set my IP_4 */ ++ sysRegWrite(LRO_RX_RING3_DIP_DW3, 0x20010238); ++ sysRegWrite(LRO_RX_RING3_DIP_DW2, 0x08010000); ++ sysRegWrite(LRO_RX_RING3_DIP_DW1, 0x00000000); ++ sysRegWrite(LRO_RX_RING3_DIP_DW0, 0x00000254); ++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING3, 1); ++ ++ /* 2.1 Set RX ring1~3 to auto-learn modes */ ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_AUTO_LEARN); ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_AUTO_LEARN); ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_AUTO_LEARN); ++ ++ /* 2.2 Valid LRO ring */ ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING0, 1); ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1); ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 1); ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 1); ++ ++ /* 2.3 Set AGE timer */ ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, HW_LRO_AGE_TIME); ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, HW_LRO_AGE_TIME); ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, HW_LRO_AGE_TIME); ++ ++ /* 3.0 IPv6 LRO enable */ ++ SET_PDMA_LRO_IPV6_EN(1); ++ ++ /* 3.1 IPv4 checksum update disable */ ++ SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1); ++ ++ /* 3.2 switch priority comparision to byte count mode */ ++ SET_PDMA_LRO_ALT_SCORE_MODE(PDMA_LRO_ALT_BYTE_CNT_MODE); ++ ++ /* 3.3 bandwidth threshold setting */ ++ SET_PDMA_LRO_BW_THRESHOLD(0); ++ ++ /* 3.4 auto-learn score delta setting */ ++ sysRegWrite(LRO_ALT_SCORE_DELTA, 0); ++ ++ /* 3.5 Set ALT timer to 500us: (unit: 20us) */ ++ SET_PDMA_LRO_ALT_REFRESH_TIMER_UNIT(25); ++ /* 3.6 Set ALT refresh timer to 1 sec. (unit: 500us) */ ++ SET_PDMA_LRO_ALT_REFRESH_TIMER(2000); ++ ++ /* 3.7 Set max AGG timer: 10 msec. */ ++ SET_PDMA_LRO_MAX_AGG_TIME(HW_LRO_AGG_TIME); ++ ++ /* 4. Polling relinguish */ ++ while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) {; ++ } ++ ++ /* 5. Enable LRO */ ++ regVal = sysRegRead(ADMA_LRO_CTRL_DW0); ++ regVal |= PDMA_LRO_EN; ++ sysRegWrite(ADMA_LRO_CTRL_DW0, regVal); ++ ++ return 0; ++} ++ ++int pdma_lro_dly_int_dvt(int index) ++{ ++ unsigned int regVal = 0; ++ unsigned int ip; ++ ++ printk("pdma_lro_dly_int_dvt(%d)\n", index); ++ ++#if 0 ++ /* 1.1 Set my IP_1 */ ++ /* str_to_ip( &ip, "10.10.10.254" ); */ ++ str_to_ip(&ip, "10.10.10.100"); ++ sysRegWrite(LRO_RX_RING0_DIP_DW0, ip); ++ sysRegWrite(LRO_RX_RING0_DIP_DW1, 0); ++ sysRegWrite(LRO_RX_RING0_DIP_DW2, 0); ++ sysRegWrite(LRO_RX_RING0_DIP_DW3, 0); ++#else ++ /* 1.1 set src/destination TCP ports */ ++ SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING1, 3423); ++ SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING1, 2301); ++ SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING2, 3423); ++ SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING2, 2301); ++ SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING3, 3423); ++ SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING3, 2301); ++ /* 1.2 set src/destination IPs */ ++ str_to_ip(&ip, "10.10.10.3"); ++ sysRegWrite(LRO_RX_RING1_SIP_DW0, ip); ++ str_to_ip(&ip, "10.10.10.100"); ++ sysRegWrite(LRO_RX_RING1_DIP_DW0, ip); ++ str_to_ip(&ip, "10.10.10.3"); ++ sysRegWrite(LRO_RX_RING2_SIP_DW0, ip); ++ str_to_ip(&ip, "10.10.10.100"); ++ sysRegWrite(LRO_RX_RING2_DIP_DW0, ip); ++ str_to_ip(&ip, "10.10.10.3"); ++ sysRegWrite(LRO_RX_RING3_SIP_DW0, ip); ++ str_to_ip(&ip, "10.10.10.100"); ++ sysRegWrite(LRO_RX_RING3_DIP_DW0, ip); ++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING1, 1); ++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING2, 1); ++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING3, 1); ++#endif ++ ++ if (index == 0) { ++ /* 1.2 Disable DLY_INT for lro ring */ ++ SET_PDMA_LRO_DLY_INT_EN(0); ++ } else { ++ /* 1.2 Enable DLY_INT for lro ring */ ++ SET_PDMA_LRO_DLY_INT_EN(1); ++ } ++ ++ /* 1.3 LRO ring DLY_INT setting */ ++ if (index == 1) { ++ sysRegWrite(LRO_RX1_DLY_INT, DELAY_INT_INIT); ++ } else if (index == 2) { ++ sysRegWrite(LRO_RX2_DLY_INT, DELAY_INT_INIT); ++ } else if (index == 3) { ++ sysRegWrite(LRO_RX3_DLY_INT, DELAY_INT_INIT); ++ } ++#if 0 ++ /* 2.1 Set RX rings to auto-learn modes */ ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_AUTO_LEARN); ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_AUTO_LEARN); ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_AUTO_LEARN); ++#else ++ /* 2.0 set rx ring mode */ ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_FORCE_PORT); ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_FORCE_PORT); ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_FORCE_PORT); ++ ++ /* 2.1 IPv4 force port mode */ ++ SET_PDMA_RXRING_IPV4_FORCE_MODE(ADMA_RX_RING1, 1); ++ SET_PDMA_RXRING_IPV4_FORCE_MODE(ADMA_RX_RING2, 1); ++ SET_PDMA_RXRING_IPV4_FORCE_MODE(ADMA_RX_RING3, 1); ++#endif ++ ++ /* 2.2 Valid LRO ring */ ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING0, 1); ++ if ((index == 0) || (index == 1)) { ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1); ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 0); ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 0); ++ } else if (index == 2) { ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 0); ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 1); ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 0); ++ } else { ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 0); ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 0); ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 1); ++ } ++ ++ /* 2.3 Set AGE timer */ ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, HW_LRO_AGE_TIME); ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, HW_LRO_AGE_TIME); ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, HW_LRO_AGE_TIME); ++ ++ /* 3.1 IPv4 checksum update enable */ ++ SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1); ++ ++ /* 3.2 switch priority comparision to byte count mode */ ++ SET_PDMA_LRO_ALT_SCORE_MODE(PDMA_LRO_ALT_BYTE_CNT_MODE); ++ ++ /* 3.3 bandwidth threshold setting */ ++ SET_PDMA_LRO_BW_THRESHOLD(0); ++ ++ /* 3.4 auto-learn score delta setting */ ++ sysRegWrite(LRO_ALT_SCORE_DELTA, 0); ++ ++ /* 3.5 Set ALT timer to 500us: (unit: 20us) */ ++ SET_PDMA_LRO_ALT_REFRESH_TIMER_UNIT(25); ++ /* 3.6 Set ALT refresh timer to 1 sec. (unit: 500us) */ ++ SET_PDMA_LRO_ALT_REFRESH_TIMER(2000); ++ ++ /* 3.7 Set max AGG timer */ ++ SET_PDMA_LRO_MAX_AGG_TIME(HW_LRO_AGG_TIME); ++ ++ /* 4. Polling relinguish */ ++ while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) {; ++ } ++ ++ /* 5. Enable LRO */ ++ regVal = sysRegRead(ADMA_LRO_CTRL_DW0); ++ regVal |= PDMA_LRO_EN; ++ sysRegWrite(ADMA_LRO_CTRL_DW0, regVal); ++ ++ return 0; ++} ++ ++int pdma_lro_dly_int0_dvt(void) ++{ ++ return pdma_lro_dly_int_dvt(0); ++} ++ ++int pdma_lro_dly_int1_dvt(void) ++{ ++ return pdma_lro_dly_int_dvt(1); ++} ++ ++int pdma_lro_dly_int2_dvt(void) ++{ ++ return pdma_lro_dly_int_dvt(2); ++} ++ ++int pdma_lro_dly_int3_dvt(void) ++{ ++ return pdma_lro_dly_int_dvt(3); ++} ++ ++#endif /* CONFIG_RAETH_HW_LRO */ ++ ++#if defined(CONFIG_RAETH_MULTIPLE_RX_RING) ++int pdma_gdm_rxid_config(void) ++{ ++ unsigned int regVal = 0; ++ ++ printk("pdma_gdm_rxid_config()\n"); ++ ++ /* 1. Set RX ring1~3 to pse modes */ ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_PSE_MODE); ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_PSE_MODE); ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_PSE_MODE); ++ ++ /* 2. Enable non-lro multiple rx */ ++ SET_PDMA_NON_LRO_MULTI_EN(1); ++ ++ return 0; ++} ++ ++int pdma_non_lro_portid_dvt(void) ++{ ++ unsigned int regVal = 0; ++ ++ printk("pdma_non_lro_portid_dvt()\n"); ++ ++ /* 1. Set GDM1 to ring3 */ ++ SET_GDM_PID1_RXID_SEL(3); ++#if 0 ++ /* 2. Set GDM2 to ring1 */ ++ SET_GDM_PID2_RXID_SEL(1); ++#endif ++ ++ /* 3. Set priority rule: pid */ ++ SET_GDM_RXID_PRI_SEL(GDM_PRI_PID); ++ ++ /* PDMA multi-rx enable */ ++ pdma_gdm_rxid_config(); ++ ++ return 0; ++} ++ ++int pdma_non_lro_stag_dvt(void) ++{ ++ unsigned int regVal = 0; ++ ++ printk("pdma_non_lro_stag_dvt()\n"); ++ ++ /* 1. Set STAG4 to ring0 */ ++ GDM_STAG_RXID_SEL(4, 0); ++ /* 2. Set STAG3 to ring1 */ ++ GDM_STAG_RXID_SEL(3, 1); ++ /* 3. Set STAG2 to ring2 */ ++ GDM_STAG_RXID_SEL(2, 2); ++ /* 4. Set STAG1 to ring3 */ ++ GDM_STAG_RXID_SEL(1, 3); ++ ++ /* 5. Set priority rule: stag/pid */ ++ SET_GDM_RXID_PRI_SEL(GDM_PRI_PID); ++ ++ /* PDMA multi-rx enable */ ++ pdma_gdm_rxid_config(); ++ ++ return 0; ++} ++ ++int pdma_non_lro_vlan_dvt(void) ++{ ++ unsigned int regVal = 0; ++ ++ printk("pdma_non_lro_vlan_dvt()\n"); ++ ++ /* 1. Set vlan priority=3 to ring1 */ ++ SET_GDM_VLAN_PRI_RXID_SEL(3, 1); ++ /* 2. Set vlan priority=2 to ring2 */ ++ SET_GDM_VLAN_PRI_RXID_SEL(2, 2); ++ /* 3. Set vlan priority=1 to ring3 */ ++ SET_GDM_VLAN_PRI_RXID_SEL(1, 3); ++ /* 4. Set vlan priority=0 to ring3 */ ++ SET_GDM_VLAN_PRI_RXID_SEL(0, 3); ++ ++ /* 1. Set vlan priority=4 to ring1 */ ++ SET_GDM_VLAN_PRI_RXID_SEL(4, 1); ++ /* 2. Set vlan priority=5 to ring2 */ ++ SET_GDM_VLAN_PRI_RXID_SEL(5, 2); ++ /* 3. Set vlan priority=6 to ring3 */ ++ SET_GDM_VLAN_PRI_RXID_SEL(6, 3); ++ /* 4. Set vlan priority=7 to ring3 */ ++ SET_GDM_VLAN_PRI_RXID_SEL(7, 3); ++ ++ /* 4. Set priority rule: vlan > pid */ ++ SET_GDM_RXID_PRI_SEL(GDM_PRI_VLAN_PID); ++ ++ /* PDMA multi-rx enable */ ++ pdma_gdm_rxid_config(); ++ ++ return 0; ++} ++ ++int pdma_non_lro_tcpack_dvt(void) ++{ ++ unsigned int regVal = 0; ++ ++ printk("pdma_non_lro_tcpack_dvt()\n"); ++ ++ /* 1. Enable TCP ACK with zero payload check */ ++ SET_GDM_TCP_ACK_WZPC(1); ++ /* 2. Set TCP ACK to ring3 */ ++ SET_GDM_TCP_ACK_RXID_SEL(3); ++ ++ /* 3. Set priority rule: ack > pid */ ++ SET_GDM_RXID_PRI_SEL(GDM_PRI_ACK_PID); ++ ++ /* PDMA multi-rx enable */ ++ pdma_gdm_rxid_config(); ++ ++ return 0; ++} ++ ++int pdma_non_lro_pri1_dvt(void) ++{ ++ unsigned int regVal = 0; ++ ++ printk("pdma_non_lro_pri1_dvt()\n"); ++ ++ /* 1. Set GDM1 to ring0 */ ++ SET_GDM_PID1_RXID_SEL(0); ++ ++ /* 2.1 Disable TCP ACK with zero payload check */ ++ SET_GDM_TCP_ACK_WZPC(0); ++ /* 2.2 Set TCP ACK to ring1 */ ++ SET_GDM_TCP_ACK_RXID_SEL(1); ++ ++ /* 3. Set vlan priority=1 to ring2 */ ++ SET_GDM_VLAN_PRI_RXID_SEL(1, 2); ++ ++ /* 4. Set priority rule: vlan > ack > pid */ ++ SET_GDM_RXID_PRI_SEL(GDM_PRI_VLAN_ACK_PID); ++ ++ /* PDMA multi-rx enable */ ++ pdma_gdm_rxid_config(); ++ ++ return 0; ++} ++ ++int pdma_non_lro_pri2_dvt(void) ++{ ++ unsigned int regVal = 0; ++ ++ printk("pdma_non_lro_pri2_dvt()\n"); ++ ++ /* 1. Set GDM1 to ring0 */ ++ SET_GDM_PID1_RXID_SEL(0); ++ ++ /* 2.1 Disable TCP ACK with zero payload check */ ++ SET_GDM_TCP_ACK_WZPC(0); ++ /* 2.2 Set TCP ACK to ring1 */ ++ SET_GDM_TCP_ACK_RXID_SEL(1); ++ ++ /* 3. Set vlan priority=1 to ring2 */ ++ SET_GDM_VLAN_PRI_RXID_SEL(1, 2); ++ ++ /* 4. Set priority rule: ack > vlan > pid */ ++ SET_GDM_RXID_PRI_SEL(GDM_PRI_ACK_VLAN_PID); ++ ++ /* PDMA multi-rx enable */ ++ pdma_gdm_rxid_config(); ++ ++ return 0; ++} ++#endif /* CONFIG_RAETH_MULTIPLE_RX_RING */ ++const static PDMA_LRO_DVT_FUNC pdma_dvt_lro_func[] = { ++#if defined(CONFIG_RAETH_HW_LRO) ++ [0] = pdma_lro_disable_dvt, /* PDMA_TEST_LRO_DISABLE */ ++ [1] = pdma_lro_force_aggre_dvt, /* PDMA_TEST_LRO_FORCE_PORT */ ++ [2] = pdma_lro_auto_aggre_dvt, /* PDMA_TEST_LRO_AUTO_LEARN */ ++ [3] = pdma_lro_auto_ipv6_dvt, /* PDMA_TEST_LRO_AUTO_IPV6 */ ++ [4] = pdma_lro_auto_myIP_dvt, /* PDMA_TEST_LRO_AUTO_MYIP */ ++ [5] = pdma_lro_force_aggre_dvt, /* PDMA_TEST_LRO_FORCE_AGGREGATE */ ++#endif /* CONFIG_RAETH_HW_LRO */ ++#if defined(CONFIG_RAETH_MULTIPLE_RX_RING) ++ [6] = pdma_non_lro_portid_dvt, /* PDMA_TEST_NON_LRO_PORT_ID */ ++ [7] = pdma_non_lro_stag_dvt, /* PDMA_TEST_NON_LRO_STAG */ ++ [8] = pdma_non_lro_vlan_dvt, /* PDMA_TEST_NON_LRO_VLAN */ ++ [9] = pdma_non_lro_tcpack_dvt, /* PDMA_TEST_NON_LRO_TCP_ACK */ ++ [10] = pdma_non_lro_pri1_dvt, /* PDMA_TEST_NON_LRO_PRI1 */ ++ [11] = pdma_non_lro_pri2_dvt, /* PDMA_TEST_NON_LRO_PRI2 */ ++#endif /* CONFIG_RAETH_MULTIPLE_RX_RING */ ++#if defined(CONFIG_RAETH_HW_LRO) ++ [12] = pdma_lro_dly_int0_dvt, /* PDMA_TEST_LRO_DLY_INT0 */ ++ [13] = pdma_lro_dly_int1_dvt, /* PDMA_TEST_LRO_DLY_INT1 */ ++ [14] = pdma_lro_dly_int2_dvt, /* PDMA_TEST_LRO_DLY_INT2 */ ++ [15] = pdma_lro_dly_int3_dvt, /* PDMA_TEST_LRO_DLY_INT3 */ ++#endif /* CONFIG_RAETH_HW_LRO */ ++}; ++ ++/* PDMA LRO test functions end */ ++ ++#if defined(CONFIG_RAETH_HW_LRO) || defined(CONFIG_RAETH_MULTIPLE_RX_RING) ++void raeth_pdma_lro_dvt(int rx_ring_no, END_DEVICE *ei_local, ++ int rx_dma_owner_idx0) ++{ ++ if (pdma_dvt_get_show_config() & PDMA_SHOW_RX_DESC) { ++ if (rx_ring_no == 1) { ++ printk("------- rt2880_eth_recv (ring1) --------\n"); ++ printk("rx_info1=0x%x\n", ++ *(unsigned int *) ++ &ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info1); ++ printk("rx_info2=0x%x\n", ++ *(unsigned int *) ++ &ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info2); ++ printk("rx_info3=0x%x\n", ++ *(unsigned int *) ++ &ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info3); ++ printk("rx_info4=0x%x\n", ++ *(unsigned int *) ++ &ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info4); ++ printk("-------------------------------\n"); ++ } else if (rx_ring_no == 2) { ++ printk("------- rt2880_eth_recv (ring2) --------\n"); ++ printk("rx_info1=0x%x\n", ++ *(unsigned int *) ++ &ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info1); ++ printk("rx_info2=0x%x\n", ++ *(unsigned int *) ++ &ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info2); ++ printk("rx_info3=0x%x\n", ++ *(unsigned int *) ++ &ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info3); ++ printk("rx_info4=0x%x\n", ++ *(unsigned int *) ++ &ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info4); ++ printk("-------------------------------\n"); ++ } else if (rx_ring_no == 3) { ++ printk("------- rt2880_eth_recv (ring3) --------\n"); ++ printk("rx_info1=0x%x\n", ++ *(unsigned int *) ++ &ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info1); ++ printk("rx_info2=0x%x\n", ++ *(unsigned int *) ++ &ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info2); ++ printk("rx_info3=0x%x\n", ++ *(unsigned int *) ++ &ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info3); ++ printk("rx_info4=0x%x\n", ++ *(unsigned int *) ++ &ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info4); ++ printk("-------------------------------\n"); ++ } ++#if 0 ++ else { ++ printk("------- rt2880_eth_recv (ring0) --------\n"); ++ printk("rx_info1=0x%x\n", ++ *(unsigned int *) ++ &ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info1); ++ printk("rx_info2=0x%x\n", ++ *(unsigned int *) ++ &ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info2); ++ printk("rx_info3=0x%x\n", ++ *(unsigned int *) ++ &ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info3); ++ printk("rx_info4=0x%x\n", ++ *(unsigned int *) ++ &ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info4); ++ printk("-------------------------------\n"); ++ } ++#endif ++ } ++ if ((pdma_dvt_get_show_config() & PDMA_SHOW_DETAIL_RX_DESC) || ++ (pdma_dvt_get_lro_test_config()==PDMA_TEST_LRO_FORCE_PORT)) { ++ if (rx_ring_no == 1) { ++ printk("------- rt2880_eth_recv (ring1) --------\n"); ++ printk("rx_info1.PDP0=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info1.PDP0); ++ printk("rx_info2.DDONE_bit=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info2.DDONE_bit); ++ printk("rx_info2.LS0=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info2.LS0); ++ printk("rx_info2.PLEN0=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info2.PLEN0); ++ printk("rx_info2.TAG=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info2.TAG); ++#if defined(CONFIG_ARCH_MT7623) ++ printk("rx_info2.LRO_AGG_CNT=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info2.LRO_AGG_CNT); ++ printk("rx_info2.REV=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info2.REV); ++#else ++ printk("rx_info2.LS1=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info2.LS1); ++#endif /* CONFIG_RAETH_HW_LRO */ ++ printk("rx_info2.PLEN1=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info2.PLEN1); ++ printk("rx_info3.TPID=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info3.TPID); ++ printk("rx_info3.VID=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info3.VID); ++ printk("rx_info4.IP6=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info4.IP6); ++ printk("rx_info4.IP4=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info4.IP4); ++ printk("rx_info4.IP4F=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info4.IP4F); ++ printk("rx_info4.TACK=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info4.TACK); ++ printk("rx_info4.L4VLD=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info4.L4VLD); ++ printk("rx_info4.L4F=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info4.L4F); ++ printk("rx_info4.SPORT=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info4.SP); ++ printk("rx_info4.CRSN=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info4.CRSN); ++ printk("rx_info4.FOE_Entry=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info4.FOE_Entry); ++ printk("-------------------------------\n"); ++ } else if (rx_ring_no == 2) { ++ printk("------- rt2880_eth_recv (ring2) --------\n"); ++ printk("rx_info1.PDP0=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info1.PDP0); ++ printk("rx_info2.DDONE_bit=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info2.DDONE_bit); ++ printk("rx_info2.LS0=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info2.LS0); ++ printk("rx_info2.PLEN0=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info2.PLEN0); ++ printk("rx_info2.TAG=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info2.TAG); ++#if defined(CONFIG_ARCH_MT7623) ++ printk("rx_info2.LRO_AGG_CNT=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info2.LRO_AGG_CNT); ++ printk("rx_info2.REV=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info2.REV); ++#else ++ printk("rx_info2.LS1=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info2.LS1); ++#endif /* CONFIG_RAETH_HW_LRO */ ++ printk("rx_info2.PLEN1=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info2.PLEN1); ++ printk("rx_info3.TPID=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info3.TPID); ++ printk("rx_info3.VID=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info3.VID); ++ printk("rx_info4.IP6=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info4.IP6); ++ printk("rx_info4.IP4=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info4.IP4); ++ printk("rx_info4.IP4F=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info4.IP4F); ++ printk("rx_info4.TACK=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info4.TACK); ++ printk("rx_info4.L4VLD=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info4.L4VLD); ++ printk("rx_info4.L4F=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info4.L4F); ++ printk("rx_info4.SPORT=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info4.SP); ++ printk("rx_info4.CRSN=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info4.CRSN); ++ printk("rx_info4.FOE_Entry=0x%x\n", ++ ei_local->rx_ring2[rx_dma_owner_idx0]. ++ rxd_info4.FOE_Entry); ++ printk("-------------------------------\n"); ++ } else if (rx_ring_no == 3) { ++ printk("------- rt2880_eth_recv (ring3) --------\n"); ++ printk("rx_info1.PDP0=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info1.PDP0); ++ printk("rx_info2.DDONE_bit=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info2.DDONE_bit); ++ printk("rx_info2.LS0=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info2.LS0); ++ printk("rx_info2.PLEN0=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info2.PLEN0); ++ printk("rx_info2.TAG=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info2.TAG); ++#if defined(CONFIG_ARCH_MT7623) ++ printk("rx_info2.LRO_AGG_CNT=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info2.LRO_AGG_CNT); ++ printk("rx_info2.REV=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info2.REV); ++#else ++ printk("rx_info2.LS1=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info2.LS1); ++#endif /* CONFIG_RAETH_HW_LRO */ ++ printk("rx_info2.PLEN1=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info2.PLEN1); ++ printk("rx_info3.TPID=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info3.TPID); ++ printk("rx_info3.VID=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info3.VID); ++ printk("rx_info4.IP6=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info4.IP6); ++ printk("rx_info4.IP4=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info4.IP4); ++ printk("rx_info4.IP4F=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info4.IP4F); ++ printk("rx_info4.TACK=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info4.TACK); ++ printk("rx_info4.L4VLD=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info4.L4VLD); ++ printk("rx_info4.L4F=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info4.L4F); ++ printk("rx_info4.SPORT=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info4.SP); ++ printk("rx_info4.CRSN=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info4.CRSN); ++ printk("rx_info4.FOE_Entry=0x%x\n", ++ ei_local->rx_ring3[rx_dma_owner_idx0]. ++ rxd_info4.FOE_Entry); ++ printk("-------------------------------\n"); ++ } ++#if 0 ++ else { ++ printk("------- rt2880_eth_recv (ring0) --------\n"); ++ printk("rx_info1.PDP0=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info1.PDP0); ++ printk("rx_info2.DDONE_bit=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info2.DDONE_bit); ++ printk("rx_info2.LS0=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info2.LS0); ++ printk("rx_info2.PLEN0=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info2.PLEN0); ++ printk("rx_info2.TAG=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info2.TAG); ++ printk("rx_info2.LS1=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info2.LS1); ++ printk("rx_info2.PLEN1=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info2.PLEN1); ++ printk("rx_info3.TPID=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info3.TPID); ++ printk("rx_info3.VID=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info3.VID); ++ printk("rx_info4.IP6=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info4.IP6); ++ printk("rx_info4.IP4=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info4.IP4); ++ printk("rx_info4.IP4F=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info4.IP4F); ++ printk("rx_info4.TACK=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info4.TACK); ++ printk("rx_info4.L4VLD=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info4.L4VLD); ++ printk("rx_info4.L4F=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info4.L4F); ++ printk("rx_info4.SPORT=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info4.SP); ++ printk("rx_info4.CRSN=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info4.CRSN); ++ printk("rx_info4.FOE_Entry=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info4.FOE_Entry); ++ printk("-------------------------------\n"); ++ } ++#endif ++ } ++ if (pdma_dvt_get_lro_test_config() == PDMA_TEST_LRO_FORCE_AGGREGATE) { ++ if (rx_ring_no == 1) { ++ printk("PASS!!! => RING1: rxd_info1.PDP0=0x%x\n", ++ ei_local->rx_ring1[rx_dma_owner_idx0]. ++ rxd_info1.PDP0); ++ skb_dump(ei_local->netrx1_skbuf[rx_dma_owner_idx0]); ++ pdma_dvt_reset_config(); ++ } ++ } ++} ++#endif ++ ++int pdma_dvt_show_ctrl(int par1, int par2) ++{ ++ if (par2 == 0) ++ g_pdma_dvt_show_config = 0; ++ else ++ g_pdma_dvt_show_config |= (1 << par2); ++ ++ return 0; ++} ++ ++int pdma_dvt_test_rx_ctrl(int par1, int par2) ++{ ++ if (par2 == 0) ++ g_pdma_dvt_rx_test_config = 0; ++ else ++ g_pdma_dvt_rx_test_config |= (1 << par2); ++ ++ return 0; ++} ++ ++int pdma_dvt_test_tx_ctrl(int par1, int par2) ++{ ++ if (par2 == 0) ++ g_pdma_dvt_tx_test_config = 0; ++ else ++ g_pdma_dvt_tx_test_config |= (1 << par2); ++ ++ return 0; ++} ++ ++int pdma_dvt_test_debug_ctrl(int par1, int par2) ++{ ++ if (par2 == 0) ++ g_pdma_dvt_debug_test_config = 0; ++ else ++ g_pdma_dvt_debug_test_config |= (1 << par2); ++ ++ return 0; ++} ++ ++int pdma_dvt_test_lro_ctrl(int par1, int par2) ++{ ++ g_pdma_dvt_lro_test_config = par2; ++ ++#if defined(CONFIG_RAETH_HW_LRO) || defined(CONFIG_RAETH_MULTIPLE_RX_RING) ++ if (pdma_dvt_lro_func[par2]) ++ (*pdma_dvt_lro_func[par2]) (); ++#endif /* #if defined (CONFIG_RAETH_HW_LRO) */ ++ ++ return 0; ++} ++ ++unsigned int pdma_dvt_get_show_config() ++{ ++ return g_pdma_dvt_show_config; ++} ++ ++unsigned int pdma_dvt_get_rx_test_config() ++{ ++ return g_pdma_dvt_rx_test_config; ++} ++ ++unsigned int pdma_dvt_get_tx_test_config() ++{ ++ return g_pdma_dvt_tx_test_config; ++} ++ ++unsigned int pdma_dvt_get_debug_test_config() ++{ ++ return g_pdma_dvt_debug_test_config; ++} ++ ++unsigned int pdma_dvt_get_lro_test_config() ++{ ++ return g_pdma_dvt_lro_test_config; ++} ++ ++void pdma_dvt_reset_config() ++{ ++ g_pdma_dvt_show_config = 0; ++ g_pdma_dvt_rx_test_config = 0; ++ g_pdma_dvt_tx_test_config = 0; ++ g_pdma_dvt_lro_test_config = 0; ++} ++ ++void raeth_pdma_rx_desc_dvt(END_DEVICE *ei_local, int rx_dma_owner_idx0) ++{ ++#if 0 ++ unsigned int udf = 0; ++#endif ++ ++ if (pdma_dvt_get_show_config() & PDMA_SHOW_RX_DESC) { ++ printk("------- rt2880_eth_recv --------\n"); ++ printk("rx_info1=0x%x\n", ++ *(unsigned int *)&ei_local-> ++ rx_ring0[rx_dma_owner_idx0].rxd_info1); ++ printk("rx_info2=0x%x\n", ++ *(unsigned int *)&ei_local-> ++ rx_ring0[rx_dma_owner_idx0].rxd_info2); ++ printk("rx_info3=0x%x\n", ++ *(unsigned int *)&ei_local-> ++ rx_ring0[rx_dma_owner_idx0].rxd_info3); ++ printk("rx_info4=0x%x\n", ++ *(unsigned int *)&ei_local-> ++ rx_ring0[rx_dma_owner_idx0].rxd_info4); ++ printk("-------------------------------\n"); ++ } ++ if ((pdma_dvt_get_show_config() & PDMA_SHOW_DETAIL_RX_DESC) || ++ pdma_dvt_get_rx_test_config()) { ++#if 0 ++ udf = ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP6 << 5 | ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP4 << 4 | ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP4F << 3 | ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.TACK << 2 | ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.L4VLD << 1 | ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.L4F; ++#endif ++ printk("------- rt2880_eth_recv --------\n"); ++ printk("rx_info1.PDP0=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info1.PDP0); ++ printk("rx_info2.DDONE_bit=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info2.DDONE_bit); ++ printk("rx_info2.LS0=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.LS0); ++ printk("rx_info2.PLEN0=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.PLEN0); ++ printk("rx_info2.TAG=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.TAG); ++#if defined(CONFIG_ARCH_MT7623) ++ printk("rx_info2.LRO_AGG_CNT=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info2.LRO_AGG_CNT); ++#else ++ printk("rx_info2.LS1=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.LS1); ++#endif /* CONFIG_RAETH_HW_LRO */ ++ printk("rx_info2.PLEN1=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.PLEN1); ++ printk("rx_info3.TPID=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info3.TPID); ++ printk("rx_info3.VID=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info3.VID); ++#if 0 ++ printk("rx_info4.UDF=0x%x\n", udf); ++#endif ++ printk("rx_info4.IP6=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP6); ++ printk("rx_info4.IP4=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP4); ++ printk("rx_info4.IP4F=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP4F); ++ printk("rx_info4.TACK=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.TACK); ++ printk("rx_info4.L4VLD=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.L4VLD); ++ printk("rx_info4.L4F=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.L4F); ++ printk("rx_info4.SPORT=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.SP); ++ printk("rx_info4.CRSN=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.CRSN); ++ printk("rx_info4.FOE_Entry=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info4.FOE_Entry); ++ printk("-------------------------------\n"); ++ } ++ if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_IPV6)) { ++ if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP6) { ++ printk("PASS!!! => rx_info4.IP6=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info4.IP6); ++ pdma_dvt_reset_config(); ++ } ++ } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_IPV4)) { ++ if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP4) { ++ printk("PASS!!! => rx_info4.IP4=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info4.IP4); ++ pdma_dvt_reset_config(); ++ } ++ } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_IPV4F)) { ++ if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP4F) { ++ printk("PASS!!! => rx_info4.IP4F=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info4.IP4F); ++ pdma_dvt_reset_config(); ++ } ++ } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_L4VLD)) { ++ if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.L4VLD) { ++ printk("PASS!!! => rx_info4.L4VLD=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info4.L4VLD); ++ pdma_dvt_reset_config(); ++ } ++ } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_L4F)) { ++ if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.L4F) { ++ printk("PASS!!! => rx_info4.L4F=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info4.L4F); ++ pdma_dvt_reset_config(); ++ } ++ } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_SPORT)) { ++ if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.SP == 1) { ++ g_pdma_dev_lanport++; ++ } else if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.SP == ++ 2) { ++ g_pdma_dev_wanport++; ++ } ++ if (g_pdma_dev_lanport && g_pdma_dev_wanport) { ++ printk ++ ("PASS!!! => g_pdma_dev_lanport=0x%x, g_pdma_dev_wanport=0x%x", ++ g_pdma_dev_lanport, g_pdma_dev_wanport); ++ ++ g_pdma_dev_lanport = 0; ++ g_pdma_dev_wanport = 0; ++ pdma_dvt_reset_config(); ++ } ++ } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_VID_OFF)) { ++ if (!ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info3.VID) { ++ printk("PASS!!! => rxd_info3.VID=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info3.VID); ++ pdma_dvt_reset_config(); ++ } ++ } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_VID_ON)) { ++ printk("RX data: (PDP0=%x)\n", ++ (unsigned int)ei_local-> ++ netrx0_skbuf[rx_dma_owner_idx0]->data); ++ ++ skb_dump(ei_local->netrx0_skbuf[rx_dma_owner_idx0]); ++ ++ if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info3.VID && ++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.TAG) { ++ printk("PASS!!! => rxd_info2.TAG=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info2.TAG); ++ printk("PASS!!! => rxd_info3.VID=0x%x\n", ++ ei_local->rx_ring0[rx_dma_owner_idx0]. ++ rxd_info3.VID); ++ pdma_dvt_reset_config(); ++ } ++ } ++} ++ ++void raeth_pdma_tx_vlan_dvt(END_DEVICE *ei_local, ++ unsigned long tx_cpu_owner_idx0) ++{ ++ if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_ON)) { ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0x10000 | 0xE007; /* VLAN_TAG = 0x1E007 */ ++ } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_ZERO)) { ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0x10000 | 0x0000; /* VLAN_TAG = 0x10000 */ ++ } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_MAX)) { ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0x10000 | 0xFFFF; /* VLAN_TAG = 0x1FFFF */ ++ } ++} ++ ++void raeth_pdma_tx_desc_dvt(END_DEVICE *ei_local, ++ unsigned long tx_cpu_owner_idx0) ++{ ++ if (PDMA_TEST_RX_UDF == pdma_dvt_get_rx_test_config()) { ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 4; /* PPE */ ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.UDF = 0x2F; ++ } ++ if (pdma_dvt_get_show_config() & PDMA_SHOW_TX_DESC) { ++ printk("------- rt2880_eth_send --------\n"); ++ printk("tx_info1=%x\n", ++ *(unsigned int *)&ei_local-> ++ tx_ring0[tx_cpu_owner_idx0].txd_info1); ++ printk("tx_info2=%x\n", ++ *(unsigned int *)&ei_local-> ++ tx_ring0[tx_cpu_owner_idx0].txd_info2); ++ printk("tx_info3=%x\n", ++ *(unsigned int *)&ei_local-> ++ tx_ring0[tx_cpu_owner_idx0].txd_info3); ++ printk("tx_info4=%x\n", ++ *(unsigned int *)&ei_local-> ++ tx_ring0[tx_cpu_owner_idx0].txd_info4); ++ printk("--------------------------------\n"); ++ } ++ if ((pdma_dvt_get_show_config() & PDMA_SHOW_DETAIL_TX_DESC) || ++ pdma_dvt_get_tx_test_config()) { ++ printk("------- rt2880_eth_send --------\n"); ++ printk("tx_info1.SDP0=%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info1.SDP0); ++ printk("tx_info2.DDONE_bit=%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0]. ++ txd_info2.DDONE_bit); ++ printk("tx_info2.LS0_bit=%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS0_bit); ++ printk("tx_info2.SDL0=%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.SDL0); ++ printk("tx_info2.BURST_bit=%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0]. ++ txd_info2.BURST_bit); ++ printk("tx_info2.LS1_bit=%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS1_bit); ++ printk("tx_info2.SDL1=%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.SDL1); ++ printk("tx_info3.SDP1=%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info3.SDP1); ++ printk("tx_info4.TUI_CO=%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TUI_CO); ++ printk("tx_info4.TSO=%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TSO); ++ printk("tx_info4.FPORT=%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT); ++ printk("tx_info4.UDF=%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.UDF); ++ printk("tx_info4.RESV=%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.RESV); ++ printk("tx_info4.VLAN_TAG=%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0]. ++ txd_info4.VLAN_TAG); ++ printk("--------------------------------\n"); ++ } ++ if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_LAN_SPORT)) { ++ if (ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT == 1) { ++ printk("PASS!!! => txd_info4.FPORT=0x%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0]. ++ txd_info4.FPORT); ++ pdma_dvt_reset_config(); ++ } ++ } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_WAN_SPORT)) { ++ if (ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT == 2) { ++ printk("PASS!!! => txd_info4.FPORT=0x%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0]. ++ txd_info4.FPORT); ++ pdma_dvt_reset_config(); ++ } ++ } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_ON)) { ++ if (ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG) { ++ printk("PASS!!! => txd_info4.VLAN_TAG=0x%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0]. ++ txd_info4.VLAN_TAG); ++ /* pdma_dvt_reset_config(); */ ++ } ++ } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_OFF)) { ++ if (!ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG) { ++ printk("PASS!!! => txd_info4.VLAN_TAG=0x%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0]. ++ txd_info4.VLAN_TAG); ++ pdma_dvt_reset_config(); ++ } ++ } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_ZERO)) { ++ if (ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG) { ++ printk("PASS!!! => txd_info4.VLAN_TAG=0x%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0]. ++ txd_info4.VLAN_TAG); ++ /* pdma_dvt_reset_config(); */ ++ } ++ } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_MAX)) { ++ if (ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG) { ++ printk("PASS!!! => txd_info4.VLAN_TAG=0x%x\n", ++ ei_local->tx_ring0[tx_cpu_owner_idx0]. ++ txd_info4.VLAN_TAG); ++ /* pdma_dvt_reset_config(); */ ++ } ++ } ++} ++ ++void raeth_pdma_lro_dly_int_dvt(void) ++{ ++ unsigned int reg_int_val; ++ ++ reg_int_val = sysRegRead(RAETH_FE_INT_STATUS); ++ ++ if (pdma_dvt_get_lro_test_config() == PDMA_TEST_LRO_DLY_INT0) { ++ if ((reg_int_val & RX_DLY_INT)) { ++ printk("PASS!!! => reg_int_val=0x%x\n", reg_int_val); ++ pdma_dvt_reset_config(); ++ } ++ } else if (pdma_dvt_get_lro_test_config() == PDMA_TEST_LRO_DLY_INT1) { ++ if ((reg_int_val & RING1_RX_DLY_INT)) { ++ printk("PASS!!! => reg_int_val=0x%x\n", reg_int_val); ++ pdma_dvt_reset_config(); ++ } ++ } else if (pdma_dvt_get_lro_test_config() == PDMA_TEST_LRO_DLY_INT2) { ++ if ((reg_int_val & RING2_RX_DLY_INT)) { ++ printk("PASS!!! => reg_int_val=0x%x\n", reg_int_val); ++ pdma_dvt_reset_config(); ++ } ++ } else if (pdma_dvt_get_lro_test_config() == PDMA_TEST_LRO_DLY_INT3) { ++ if ((reg_int_val & RING3_RX_DLY_INT)) { ++ printk("PASS!!! => reg_int_val=0x%x\n", reg_int_val); ++ pdma_dvt_reset_config(); ++ } ++ } ++} ++ ++void pdma_dvt_set_dma_mode(void) ++{ ++#if defined(CONFIG_RAETH_PDMA_LEGACY_MODE) ++ unsigned int regVal; ++ regVal = sysRegRead(ADMA_LRO_CTRL_DW3); ++ regVal &= ~(BIT(15)); ++ sysRegWrite(ADMA_LRO_CTRL_DW3, regVal); ++#endif /* CONFIG_RAETH_PDMA_DVT */ ++} ++ +diff --git a/drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.h b/drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.h +new file mode 100755 +index 0000000..600aab7 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.h +@@ -0,0 +1,75 @@ ++/* Show controls */ ++#define PDMA_SHOW_RX_DESC (1 << 1) ++#define PDMA_SHOW_TX_DESC (1 << 2) ++#define PDMA_SHOW_DETAIL_RX_DESC (1 << 3) ++#define PDMA_SHOW_DETAIL_TX_DESC (1 << 4) ++ ++/* Rx test controls */ ++#define PDMA_TEST_RX_UDF (1 << 1) ++#define PDMA_TEST_RX_IPV6 (1 << 2) ++#define PDMA_TEST_RX_IPV4 (1 << 3) ++#define PDMA_TEST_RX_IPV4F (1 << 4) ++#define PDMA_TEST_RX_L4VLD (1 << 5) ++#define PDMA_TEST_RX_L4F (1 << 6) ++#define PDMA_TEST_RX_SPORT (1 << 7) ++#define PDMA_TEST_RX_VID_ON (1 << 8) ++#define PDMA_TEST_RX_VID_OFF (1 << 9) ++ ++/* Tx test controls */ ++#define PDMA_TEST_TX_LAN_SPORT (1 << 1) ++#define PDMA_TEST_TX_WAN_SPORT (1 << 2) ++#define PDMA_TEST_TX_VLAN_ON (1 << 3) ++#define PDMA_TEST_TX_VLAN_OFF (1 << 4) ++#define PDMA_TEST_TX_VLAN_ZERO (1 << 5) ++#define PDMA_TEST_TX_VLAN_MAX (1 << 6) ++#define PDMA_TEST_TX_PDMA_LPK (1 << 31) ++ ++/* Debug controls */ ++#define PDMA_TEST_TSO_DEBUG (1 << 1) ++ ++/* LRO test controls */ ++typedef int (*PDMA_LRO_DVT_FUNC) (void); ++ ++#define PDMA_TEST_LRO_DISABLE (0) ++#define PDMA_TEST_LRO_FORCE_PORT (1) ++#define PDMA_TEST_LRO_AUTO_LEARN (2) ++#define PDMA_TEST_LRO_AUTO_IPV6 (3) ++#define PDMA_TEST_LRO_AUTO_MYIP (4) ++#define PDMA_TEST_LRO_FORCE_AGGREGATE (5) ++#define PDMA_TEST_NON_LRO_PORT_ID (6) ++#define PDMA_TEST_NON_LRO_STAG (7) ++#define PDMA_TEST_NON_LRO_VLAN (8) ++#define PDMA_TEST_NON_LRO_TCP_ACK (9) ++#define PDMA_TEST_NON_LRO_PRI1 (10) ++#define PDMA_TEST_NON_LRO_PRI2 (11) ++#define PDMA_TEST_LRO_DLY_INT0 (12) ++#define PDMA_TEST_LRO_DLY_INT1 (13) ++#define PDMA_TEST_LRO_DLY_INT2 (14) ++#define PDMA_TEST_LRO_DLY_INT3 (15) ++ ++void skb_dump(struct sk_buff *sk); ++ ++int pdma_dvt_show_ctrl(int par1, int par2); ++int pdma_dvt_test_rx_ctrl(int par1, int par2); ++int pdma_dvt_test_tx_ctrl(int par1, int par2); ++int pdma_dvt_test_debug_ctrl(int par1, int par2); ++int pdma_dvt_test_lro_ctrl(int par1, int par2); ++ ++unsigned int pdma_dvt_get_show_config(void); ++unsigned int pdma_dvt_get_rx_test_config(void); ++unsigned int pdma_dvt_get_tx_test_config(void); ++unsigned int pdma_dvt_get_debug_test_config(void); ++unsigned int pdma_dvt_get_lro_test_config(void); ++void pdma_dvt_reset_config(void); ++ ++void raeth_pdma_rx_desc_dvt(END_DEVICE *ei_local, int rx_dma_owner_idx0); ++void raeth_pdma_tx_vlan_dvt(END_DEVICE *ei_local, ++ unsigned long tx_cpu_owner_idx0); ++void raeth_pdma_tx_desc_dvt(END_DEVICE *ei_local, ++ unsigned long tx_cpu_owner_idx0); ++ ++void raeth_pdma_lro_dvt(int rx_ring_no, END_DEVICE *ei_local, ++ int rx_dma_owner_idx0); ++void raeth_pdma_lro_dly_int_dvt(void); ++void pdma_dvt_set_dma_mode(void); ++ +diff --git a/drivers/net/ethernet/raeth/ethtool_readme.txt b/drivers/net/ethernet/raeth/ethtool_readme.txt +new file mode 100644 +index 0000000..10e918b +--- /dev/null ++++ b/drivers/net/ethernet/raeth/ethtool_readme.txt +@@ -0,0 +1,44 @@ ++ ++Ethtool readme for selecting different PHY address. ++ ++Before doing any ethtool command you should make sure the current PHY ++address is expected. The default PHY address is 1(port 1). ++ ++You can change current PHY address to X(0~4) by doing follow command: ++# echo X > /proc/rt2880/gmac ++ ++Ethtool command also would show the current PHY address as following. ++ ++# ethtool eth2 ++Settings for eth2: ++ Supported ports: [ TP MII ] ++ Supported link modes: 10baseT/Half 10baseT/Full ++ 100baseT/Half 100baseT/Full ++ Supports auto-negotiation: Yes ++ Advertised link modes: 10baseT/Half 10baseT/Full ++ 100baseT/Half 100baseT/Full ++ Advertised auto-negotiation: No ++ Speed: 10Mb/s ++ Duplex: Full ++ Port: MII ++ PHYAD: 1 ++ Transceiver: internal ++ Auto-negotiation: off ++ Current message level: 0x00000000 (0) ++ Link detected: no ++ ++ ++The "PHYAD" field shows the current PHY address. ++ ++ ++ ++Usage example ++1) show port1 info ++# echo 1 > /proc/rt2880/gmac # change phy address to 1 ++# ethtool eth2 ++ ++2) show port0 info ++# echo 0 > /proc/rt2880/gmac # change phy address to 0 ++# ethtool eth2 ++ ++ +diff --git a/drivers/net/ethernet/raeth/mcast.c b/drivers/net/ethernet/raeth/mcast.c +new file mode 100644 +index 0000000..d796b03 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/mcast.c +@@ -0,0 +1,187 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#define MAX_MCAST_ENTRY 16 ++#define AGEING_TIME 5 //Unit: Sec ++#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2], \ ++ ((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5] ++ ++//#define MCAST_DEBUG ++#ifdef MCAST_DEBUG ++#define MCAST_PRINT(fmt, args...) printk(KERN_INFO fmt, ## args) ++#else ++#define MCAST_PRINT(fmt, args...) { } ++#endif ++ ++typedef struct { ++ uint8_t src_mac[6]; ++ uint8_t dst_mac[6]; ++ uint16_t vlan_id; ++ uint32_t valid; ++ uint32_t use_count; ++ unsigned long ageout; ++} mcast_entry; ++ ++mcast_entry mcast_tbl[MAX_MCAST_ENTRY]; ++atomic_t mcast_entry_num=ATOMIC_INIT(0); ++DECLARE_MUTEX(mtbl_lock); ++ ++uint32_t inline is_multicast_pkt(uint8_t *mac) ++{ ++ if(mac[0]==0x01 && mac[1]==0x00 && mac[2]==0x5E) { ++ return 1; ++ }else{ ++ return 0; ++ } ++} ++ ++int32_t inline mcast_entry_get(uint16_t vlan_id, uint8_t *src_mac, uint8_t *dst_mac) ++{ ++ int i=0; ++ ++ for(i=0;i=0) { ++ mcast_tbl[entry_num].use_count++; ++ mcast_tbl[entry_num].ageout=jiffies + AGEING_TIME * HZ; ++ MCAST_PRINT("%s: Update %0X:%0X:%0X:%0X:%0X:%0X's use_count=%d\n" \ ++ ,__FUNCTION__, MAC_ARG(dst_mac), mcast_tbl[entry_num].use_count); ++ ret = 1; ++ }else { //if entry not found, create new entry. ++ MCAST_PRINT("%s: Create new entry %0X:%0X:%0X:%0X:%0X:%0X\n", \ ++ __FUNCTION__, MAC_ARG(dst_mac)); ++ ret = __add_mcast_entry(vlan_id, src_mac,dst_mac); ++ } ++ ++ up(&mtbl_lock); ++ return ret; ++ ++} ++ ++ ++/* ++ * Return: ++ * 0: entry found ++ * 1: entry not found ++ */ ++int inline mcast_entry_del(uint16_t vlan_id, uint8_t *src_mac, uint8_t *dst_mac) ++{ ++ int entry_num; ++ ++ down(&mtbl_lock); ++ if((entry_num = mcast_entry_get(vlan_id, src_mac, dst_mac)) >=0) { ++ if((--mcast_tbl[entry_num].use_count)==0) { ++ MCAST_PRINT("%s: %0X:%0X:%0X:%0X:%0X:%0X (entry_num=%d)\n", \ ++ __FUNCTION__, MAC_ARG(dst_mac), entry_num); ++ mcast_tbl[entry_num].valid=0; ++ atomic_dec(&mcast_entry_num); ++ } ++ up(&mtbl_lock); ++ return 0; ++ }else { ++ /* this multicast packet was not sent by meself, just ignore it */ ++ up(&mtbl_lock); ++ return 1; ++ } ++} ++ ++/* ++ * Return ++ * 0: drop packet ++ * 1: continue ++ */ ++int32_t mcast_rx(struct sk_buff * skb) ++{ ++ struct vlan_ethhdr *eth = (struct vlan_ethhdr *)(skb->data-ETH_HLEN); ++ ++ /* if we do not send multicast packet before, ++ * we don't need to check re-inject multicast packet. ++ */ ++ if (atomic_read(&mcast_entry_num)==0) { ++ return 1; ++ } ++ ++ ++ if(is_multicast_pkt(eth->h_dest)) { ++ MCAST_PRINT("%s: %0X:%0X:%0X:%0X:%0X:%0X\n", __FUNCTION__, \ ++ MAC_ARG(eth->h_dest)); ++ ++ if(ntohs(eth->h_vlan_proto)==0x8100) { ++ return mcast_entry_del(eth->h_vlan_TCI, eth->h_source, eth->h_dest); ++ } else { ++ return mcast_entry_del(0, eth->h_source, eth->h_dest); ++ } ++ } ++ ++ return 1; ++} ++ ++ ++int32_t mcast_tx(struct sk_buff *skb) ++{ ++ struct vlan_ethhdr *eth = (struct vlan_ethhdr *)(skb->data); ++ ++ ++ if(is_multicast_pkt(eth->h_dest)) { ++ MCAST_PRINT("%s: %0X:%0X:%0X:%0X:%0X:%0X\n", __FUNCTION__,\ ++ MAC_ARG(eth->h_dest)); ++ ++ if(ntohs(eth->h_vlan_proto)==0x8100) { ++ mcast_entry_ins(eth->h_vlan_TCI, eth->h_source, eth->h_dest); ++ } else { ++ mcast_entry_ins(0, eth->h_source, eth->h_dest); ++ } ++ } ++ ++ return 1; ++} ++ +diff --git a/drivers/net/ethernet/raeth/mii_mgr.c b/drivers/net/ethernet/raeth/mii_mgr.c +new file mode 100644 +index 0000000..77a47f1 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/mii_mgr.c +@@ -0,0 +1,603 @@ ++#include ++#include ++#include ++ ++#include ++#include ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) ++#include ++#endif ++ ++#include "ra2882ethreg.h" ++#include "raether.h" ++ ++ ++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++#define PHY_CONTROL_0 0xC0 ++#define PHY_CONTROL_1 0xC4 ++#define MDIO_PHY_CONTROL_0 (RALINK_ETH_SW_BASE + PHY_CONTROL_0) ++#define MDIO_PHY_CONTROL_1 (RALINK_ETH_SW_BASE + PHY_CONTROL_1) ++ ++#define GPIO_MDIO_BIT (1<<7) ++#define GPIO_PURPOSE_SELECT 0x60 ++#define GPIO_PRUPOSE (RALINK_SYSCTL_BASE + GPIO_PURPOSE_SELECT) ++ ++#elif defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) ++ ++#define PHY_CONTROL_0 0x7004 ++#define MDIO_PHY_CONTROL_0 (RALINK_ETH_SW_BASE + PHY_CONTROL_0) ++#define enable_mdio(x) ++ ++#elif defined (CONFIG_RALINK_MT7620) ++ ++#define PHY_CONTROL_0 0x7004 ++#define MDIO_PHY_CONTROL_0 (RALINK_ETH_SW_BASE + PHY_CONTROL_0) ++#define enable_mdio(x) ++ ++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++ ++#define PHY_CONTROL_0 0x0004 ++#define MDIO_PHY_CONTROL_0 (RALINK_ETH_SW_BASE + PHY_CONTROL_0) ++#define enable_mdio(x) ++ ++#else ++#define PHY_CONTROL_0 0x00 ++#define PHY_CONTROL_1 0x04 ++#define MDIO_PHY_CONTROL_0 (RALINK_FRAME_ENGINE_BASE + PHY_CONTROL_0) ++#define MDIO_PHY_CONTROL_1 (RALINK_FRAME_ENGINE_BASE + PHY_CONTROL_1) ++#define enable_mdio(x) ++#endif ++ ++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++void enable_mdio(int enable) ++{ ++#if !defined (CONFIG_P5_MAC_TO_PHY_MODE) && !defined(CONFIG_GE1_RGMII_AN) && !defined(CONFIG_GE2_RGMII_AN) && \ ++ !defined (CONFIG_GE1_MII_AN) && !defined (CONFIG_GE2_MII_AN) && !defined (CONFIG_RALINK_MT7628) ++ u32 data = sysRegRead(GPIO_PRUPOSE); ++ if (enable) ++ data &= ~GPIO_MDIO_BIT; ++ else ++ data |= GPIO_MDIO_BIT; ++ sysRegWrite(GPIO_PRUPOSE, data); ++#endif ++} ++#endif ++ ++#if defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) ++ ++u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data) ++{ ++ u32 volatile status = 0; ++ u32 rc = 0; ++ unsigned long volatile t_start = jiffies; ++ u32 volatile data = 0; ++ ++ /* We enable mdio gpio purpose register, and disable it when exit. */ ++ enable_mdio(1); ++ ++ // make sure previous read operation is complete ++ while (1) { ++ // 0 : Read/write operation complete ++ if(!( sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) ++ { ++ break; ++ } ++ else if (time_after(jiffies, t_start + 5*HZ)) { ++ enable_mdio(0); ++ printk("\n MDIO Read operation is ongoing !!\n"); ++ return rc; ++ } ++ } ++ ++ data = (0x01 << 16) | (0x02 << 18) | (phy_addr << 20) | (phy_register << 25); ++ sysRegWrite(MDIO_PHY_CONTROL_0, data); ++ data |= (1<<31); ++ sysRegWrite(MDIO_PHY_CONTROL_0, data); ++ //printk("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0); ++ ++ ++ // make sure read operation is complete ++ t_start = jiffies; ++ while (1) { ++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) { ++ status = sysRegRead(MDIO_PHY_CONTROL_0); ++ *read_data = (u32)(status & 0x0000FFFF); ++ ++ enable_mdio(0); ++ return 1; ++ } ++ else if (time_after(jiffies, t_start+5*HZ)) { ++ enable_mdio(0); ++ printk("\n MDIO Read operation is ongoing and Time Out!!\n"); ++ return 0; ++ } ++ } ++} ++ ++u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data) ++{ ++ unsigned long volatile t_start=jiffies; ++ u32 volatile data; ++ ++ enable_mdio(1); ++ ++ // make sure previous write operation is complete ++ while(1) { ++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) ++ { ++ break; ++ } ++ else if (time_after(jiffies, t_start + 5 * HZ)) { ++ enable_mdio(0); ++ printk("\n MDIO Write operation ongoing\n"); ++ return 0; ++ } ++ } ++ ++ data = (0x01 << 16)| (1<<18) | (phy_addr << 20) | (phy_register << 25) | write_data; ++ sysRegWrite(MDIO_PHY_CONTROL_0, data); ++ data |= (1<<31); ++ sysRegWrite(MDIO_PHY_CONTROL_0, data); //start operation ++ //printk("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0); ++ ++ t_start = jiffies; ++ ++ // make sure write operation is complete ++ while (1) { ++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) //0 : Read/write operation complete ++ { ++ enable_mdio(0); ++ return 1; ++ } ++ else if (time_after(jiffies, t_start + 5 * HZ)) { ++ enable_mdio(0); ++ printk("\n MDIO Write operation Time Out\n"); ++ return 0; ++ } ++ } ++} ++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_ARCH_MT7623) ++ ++u32 __mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data) ++{ ++ u32 volatile status = 0; ++ u32 rc = 0; ++ unsigned long volatile t_start = jiffies; ++ u32 volatile data = 0; ++ ++ /* We enable mdio gpio purpose register, and disable it when exit. */ ++ enable_mdio(1); ++ ++ // make sure previous read operation is complete ++ while (1) { ++ // 0 : Read/write operation complete ++ if(!( sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) ++ { ++ break; ++ } ++ else if (time_after(jiffies, t_start + 5*HZ)) { ++ enable_mdio(0); ++ printk("\n MDIO Read operation is ongoing !!\n"); ++ return rc; ++ } ++ } ++ ++ data = (0x01 << 16) | (0x02 << 18) | (phy_addr << 20) | (phy_register << 25); ++ sysRegWrite(MDIO_PHY_CONTROL_0, data); ++ data |= (1<<31); ++ sysRegWrite(MDIO_PHY_CONTROL_0, data); ++ //printk("\n Set Command [0x%08X] = [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0, data); ++ ++ ++ // make sure read operation is complete ++ t_start = jiffies; ++ while (1) { ++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) { ++ status = sysRegRead(MDIO_PHY_CONTROL_0); ++ *read_data = (u32)(status & 0x0000FFFF); ++ ++ enable_mdio(0); ++ return 1; ++ } ++ else if (time_after(jiffies, t_start+5*HZ)) { ++ enable_mdio(0); ++ printk("\n MDIO Read operation is ongoing and Time Out!!\n"); ++ return 0; ++ } ++ } ++} ++ ++u32 __mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data) ++{ ++ unsigned long volatile t_start=jiffies; ++ u32 volatile data; ++ ++ enable_mdio(1); ++ ++ // make sure previous write operation is complete ++ while(1) { ++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) ++ { ++ break; ++ } ++ else if (time_after(jiffies, t_start + 5 * HZ)) { ++ enable_mdio(0); ++ printk("\n MDIO Write operation ongoing\n"); ++ return 0; ++ } ++ } ++ ++ data = (0x01 << 16)| (1<<18) | (phy_addr << 20) | (phy_register << 25) | write_data; ++ sysRegWrite(MDIO_PHY_CONTROL_0, data); ++ data |= (1<<31); ++ sysRegWrite(MDIO_PHY_CONTROL_0, data); //start operation ++ //printk("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0); ++ ++ t_start = jiffies; ++ ++ // make sure write operation is complete ++ while (1) { ++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) //0 : Read/write operation complete ++ { ++ enable_mdio(0); ++ return 1; ++ } ++ else if (time_after(jiffies, t_start + 5 * HZ)) { ++ enable_mdio(0); ++ printk("\n MDIO Write operation Time Out\n"); ++ return 0; ++ } ++ } ++} ++ ++u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data) ++{ ++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600) || defined (CONFIG_P5_RGMII_TO_MT7530_MODE) ++ u32 low_word; ++ u32 high_word; ++ u32 an_status = 0; ++ ++ if(phy_addr==31) ++ { ++ an_status = (*(unsigned long *)(ESW_PHY_POLLING) & (1<<31)); ++ if(an_status){ ++ *(unsigned long *)(ESW_PHY_POLLING) &= ~(1<<31);//(AN polling off) ++ } ++ //phase1: write page address phase ++ if(__mii_mgr_write(phy_addr, 0x1f, ((phy_register >> 6) & 0x3FF))) { ++ //phase2: write address & read low word phase ++ if(__mii_mgr_read(phy_addr, (phy_register >> 2) & 0xF, &low_word)) { ++ //phase3: write address & read high word phase ++ if(__mii_mgr_read(phy_addr, (0x1 << 4), &high_word)) { ++ *read_data = (high_word << 16) | (low_word & 0xFFFF); ++ if(an_status){ ++ *(unsigned long *)(ESW_PHY_POLLING) |= (1<<31);//(AN polling on) ++ } ++ return 1; ++ } ++ } ++ } ++ if(an_status){ ++ *(unsigned long *)(ESW_PHY_POLLING) |= (1<<31);//(AN polling on) ++ } ++ } else ++#endif ++ { ++ if(__mii_mgr_read(phy_addr, phy_register, read_data)) { ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ ++u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data) ++{ ++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600) || defined (CONFIG_P5_RGMII_TO_MT7530_MODE) ++ u32 an_status = 0; ++ ++ if(phy_addr == 31) ++ { ++ an_status = (*(unsigned long *)(ESW_PHY_POLLING) & (1<<31)); ++ if(an_status){ ++ *(unsigned long *)(ESW_PHY_POLLING) &= ~(1<<31);//(AN polling off) ++ } ++ //phase1: write page address phase ++ if(__mii_mgr_write(phy_addr, 0x1f, (phy_register >> 6) & 0x3FF)) { ++ //phase2: write address & read low word phase ++ if(__mii_mgr_write(phy_addr, ((phy_register >> 2) & 0xF), write_data & 0xFFFF)) { ++ //phase3: write address & read high word phase ++ if(__mii_mgr_write(phy_addr, (0x1 << 4), write_data >> 16)) { ++ if(an_status){ ++ *(unsigned long *)(ESW_PHY_POLLING) |= (1<<31);//(AN polling on) ++ } ++ return 1; ++ } ++ } ++ } ++ if(an_status){ ++ *(unsigned long *)(ESW_PHY_POLLING) |= (1<<31);//(AN polling on) ++ } ++ } else ++#endif ++ { ++ if(__mii_mgr_write(phy_addr, phy_register, write_data)) { ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ ++u32 mii_mgr_cl45_set_address(u32 port_num, u32 dev_addr, u32 reg_addr) ++{ ++ u32 rc = 0; ++ unsigned long volatile t_start = jiffies; ++ u32 volatile data = 0; ++ ++ enable_mdio(1); ++ ++ while (1) { ++ if(!( sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) ++ { ++ break; ++ } ++ else if (time_after(jiffies, t_start + 5*HZ)) { ++ enable_mdio(0); ++ printk("\n MDIO Read operation is ongoing !!\n"); ++ return rc; ++ } ++ } ++ data = (dev_addr << 25) | (port_num << 20) | (0x00 << 18) | (0x00 << 16) | reg_addr; ++ sysRegWrite(MDIO_PHY_CONTROL_0, data); ++ data |= (1<<31); ++ sysRegWrite(MDIO_PHY_CONTROL_0, data); ++ ++ t_start = jiffies; ++ while (1) { ++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) //0 : Read/write operation complete ++ { ++ enable_mdio(0); ++ return 1; ++ } ++ else if (time_after(jiffies, t_start + 5 * HZ)) { ++ enable_mdio(0); ++ printk("\n MDIO Write operation Time Out\n"); ++ return 0; ++ } ++ } ++ ++} ++ ++ ++u32 mii_mgr_read_cl45(u32 port_num, u32 dev_addr, u32 reg_addr, u32 *read_data) ++{ ++ u32 volatile status = 0; ++ u32 rc = 0; ++ unsigned long volatile t_start = jiffies; ++ u32 volatile data = 0; ++ ++ // set address first ++ mii_mgr_cl45_set_address(port_num, dev_addr, reg_addr); ++ //udelay(10); ++ ++ enable_mdio(1); ++ ++ while (1) { ++ if(!( sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) ++ { ++ break; ++ } ++ else if (time_after(jiffies, t_start + 5*HZ)) { ++ enable_mdio(0); ++ printk("\n MDIO Read operation is ongoing !!\n"); ++ return rc; ++ } ++ } ++ data = (dev_addr << 25) | (port_num << 20) | (0x03 << 18) | (0x00 << 16) | reg_addr; ++ sysRegWrite(MDIO_PHY_CONTROL_0, data); ++ data |= (1<<31); ++ sysRegWrite(MDIO_PHY_CONTROL_0, data); ++ t_start = jiffies; ++ while (1) { ++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) { ++ *read_data = (sysRegRead(MDIO_PHY_CONTROL_0) & 0x0000FFFF); ++ enable_mdio(0); ++ return 1; ++ } ++ else if (time_after(jiffies, t_start+5*HZ)) { ++ enable_mdio(0); ++ printk("\n Set Operation: MDIO Read operation is ongoing and Time Out!!\n"); ++ return 0; ++ } ++ status = sysRegRead(MDIO_PHY_CONTROL_0); ++ } ++ ++} ++ ++u32 mii_mgr_write_cl45 (u32 port_num, u32 dev_addr, u32 reg_addr, u32 write_data) ++{ ++ u32 rc = 0; ++ unsigned long volatile t_start = jiffies; ++ u32 volatile data = 0; ++ ++ // set address first ++ mii_mgr_cl45_set_address(port_num, dev_addr, reg_addr); ++ //udelay(10); ++ ++ enable_mdio(1); ++ while (1) { ++ if(!( sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) ++ { ++ break; ++ } ++ else if (time_after(jiffies, t_start + 5*HZ)) { ++ enable_mdio(0); ++ printk("\n MDIO Read operation is ongoing !!\n"); ++ return rc; ++ } ++ } ++ ++ data = (dev_addr << 25) | (port_num << 20) | (0x01 << 18) | (0x00 << 16) | write_data; ++ sysRegWrite(MDIO_PHY_CONTROL_0, data); ++ data |= (1<<31); ++ sysRegWrite(MDIO_PHY_CONTROL_0, data); ++ ++ t_start = jiffies; ++ ++ while (1) { ++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) ++ { ++ enable_mdio(0); ++ return 1; ++ } ++ else if (time_after(jiffies, t_start + 5 * HZ)) { ++ enable_mdio(0); ++ printk("\n MDIO Write operation Time Out\n"); ++ return 0; ++ } ++ ++ } ++} ++ ++#else // not rt6855 ++ ++u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data) ++{ ++ u32 volatile status = 0; ++ u32 rc = 0; ++ unsigned long volatile t_start = jiffies; ++#if !defined (CONFIG_RALINK_RT3052) && !defined (CONFIG_RALINK_RT3352) && !defined (CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628) ++ u32 volatile data = 0; ++#endif ++ ++ /* We enable mdio gpio purpose register, and disable it when exit. */ ++ enable_mdio(1); ++ ++ // make sure previous read operation is complete ++ while (1) { ++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++ // rd_rdy: read operation is complete ++ if(!( sysRegRead(MDIO_PHY_CONTROL_1) & (0x1 << 1))) ++#else ++ // 0 : Read/write operation complet ++ if(!( sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) ++#endif ++ { ++ break; ++ } ++ else if (time_after(jiffies, t_start + 5*HZ)) { ++ enable_mdio(0); ++ printk("\n MDIO Read operation is ongoing !!\n"); ++ return rc; ++ } ++ } ++ ++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++ sysRegWrite(MDIO_PHY_CONTROL_0 , (1<<14) | (phy_register << 8) | (phy_addr)); ++#else ++ data = (phy_addr << 24) | (phy_register << 16); ++ sysRegWrite(MDIO_PHY_CONTROL_0, data); ++ data |= (1<<31); ++ sysRegWrite(MDIO_PHY_CONTROL_0, data); ++#endif ++ //printk("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0); ++ ++ ++ // make sure read operation is complete ++ t_start = jiffies; ++ while (1) { ++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++ if (sysRegRead(MDIO_PHY_CONTROL_1) & (0x1 << 1)) { ++ status = sysRegRead(MDIO_PHY_CONTROL_1); ++ *read_data = (u32)(status >>16); ++ ++ enable_mdio(0); ++ return 1; ++ } ++#else ++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) { ++ status = sysRegRead(MDIO_PHY_CONTROL_0); ++ *read_data = (u32)(status & 0x0000FFFF); ++ ++ enable_mdio(0); ++ return 1; ++ } ++#endif ++ else if (time_after(jiffies, t_start+5*HZ)) { ++ enable_mdio(0); ++ printk("\n MDIO Read operation is ongoing and Time Out!!\n"); ++ return 0; ++ } ++ } ++} ++ ++ ++u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data) ++{ ++ unsigned long volatile t_start=jiffies; ++ u32 volatile data; ++ ++ enable_mdio(1); ++ ++ // make sure previous write operation is complete ++ while(1) { ++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++ if (!(sysRegRead(MDIO_PHY_CONTROL_1) & (0x1 << 0))) ++#else ++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) ++#endif ++ { ++ break; ++ } ++ else if (time_after(jiffies, t_start + 5 * HZ)) { ++ enable_mdio(0); ++ printk("\n MDIO Write operation ongoing\n"); ++ return 0; ++ } ++ } ++ ++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++ data = ((write_data & 0xFFFF) << 16); ++ data |= (phy_register << 8) | (phy_addr); ++ data |= (1<<13); ++ sysRegWrite(MDIO_PHY_CONTROL_0, data); ++#else ++ data = (1<<30) | (phy_addr << 24) | (phy_register << 16) | write_data; ++ sysRegWrite(MDIO_PHY_CONTROL_0, data); ++ data |= (1<<31); ++ sysRegWrite(MDIO_PHY_CONTROL_0, data); //start operation ++#endif ++ //printk("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0); ++ ++ t_start = jiffies; ++ ++ // make sure write operation is complete ++ while (1) { ++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++ if (sysRegRead(MDIO_PHY_CONTROL_1) & (0x1 << 0)) //wt_done ?= 1 ++#else ++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) //0 : Read/write operation complete ++#endif ++ { ++ enable_mdio(0); ++ return 1; ++ } ++ else if (time_after(jiffies, t_start + 5 * HZ)) { ++ enable_mdio(0); ++ printk("\n MDIO Write operation Time Out\n"); ++ return 0; ++ } ++ } ++} ++ ++ ++ ++ ++#endif ++ ++ ++ ++ ++EXPORT_SYMBOL(mii_mgr_write); ++EXPORT_SYMBOL(mii_mgr_read); +diff --git a/drivers/net/ethernet/raeth/ra2882ethreg.h b/drivers/net/ethernet/raeth/ra2882ethreg.h +new file mode 100644 +index 0000000..c67a042 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/ra2882ethreg.h +@@ -0,0 +1,1985 @@ ++#ifndef RA2882ETHREG_H ++#define RA2882ETHREG_H ++ ++#include // for struct mii_if_info in ra2882ethreg.h ++#include /* check linux version for 2.4 and 2.6 compatibility */ ++#include /* for "struct tasklet_struct" in linux-3.10.14 */ ++#if defined (CONFIG_HW_SFQ) ++#include ++#include ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ++#include ++#endif ++#include "raether.h" ++ ++#ifdef WORKQUEUE_BH ++#include ++#endif // WORKQUEUE_BH // ++#ifdef CONFIG_RAETH_LRO ++#include ++#endif ++ ++#define MAX_PACKET_SIZE 1514 ++#define MIN_PACKET_SIZE 60 ++#define MAX_TXD_LEN 0x3fff ++ ++#if defined (CONFIG_ARCH_MT7623) ++#define phys_to_bus(a) (a) ++#else ++#define phys_to_bus(a) (a & 0x1FFFFFFF) ++#endif ++ ++ ++ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++#define BIT(x) ((1 << x)) ++#endif ++/* bits range: for example BITS(16,23) = 0xFF0000 ++ * ==> (BIT(m)-1) = 0x0000FFFF ~(BIT(m)-1) => 0xFFFF0000 ++ * ==> (BIT(n+1)-1) = 0x00FFFFFF ++ */ ++#define BITS(m,n) (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n))) ++ ++#define ETHER_ADDR_LEN 6 ++ ++/* Phy Vender ID list */ ++ ++#define EV_ICPLUS_PHY_ID0 0x0243 ++#define EV_ICPLUS_PHY_ID1 0x0D90 ++#define EV_MARVELL_PHY_ID0 0x0141 ++#define EV_MARVELL_PHY_ID1 0x0CC2 ++#define EV_VTSS_PHY_ID0 0x0007 ++#define EV_VTSS_PHY_ID1 0x0421 ++ ++/* ++ FE_INT_STATUS ++*/ ++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || \ ++ defined (CONFIG_ARCH_MT7623) ++ ++#define RX_COHERENT BIT(31) ++#define RX_DLY_INT BIT(30) ++#define TX_COHERENT BIT(29) ++#define TX_DLY_INT BIT(28) ++#define RING3_RX_DLY_INT BIT(27) ++#define RING2_RX_DLY_INT BIT(26) ++#define RING1_RX_DLY_INT BIT(25) ++ ++#define ALT_RPLC_INT3 BIT(23) ++#define ALT_RPLC_INT2 BIT(22) ++#define ALT_RPLC_INT1 BIT(21) ++ ++#define RX_DONE_INT3 BIT(19) ++#define RX_DONE_INT2 BIT(18) ++#define RX_DONE_INT1 BIT(17) ++#define RX_DONE_INT0 BIT(16) ++ ++#define TX_DONE_INT3 BIT(3) ++#define TX_DONE_INT2 BIT(2) ++#define TX_DONE_INT1 BIT(1) ++#define TX_DONE_INT0 BIT(0) ++ ++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++#define RLS_COHERENT BIT(29) ++#define RLS_DLY_INT BIT(28) ++#define RLS_DONE_INT BIT(0) ++#endif ++ ++#else ++//#define CNT_PPE_AF BIT(31) ++//#define CNT_GDM_AF BIT(29) ++#define PSE_P2_FC BIT(26) ++#define GDM_CRC_DROP BIT(25) ++#define PSE_BUF_DROP BIT(24) ++#define GDM_OTHER_DROP BIT(23) ++#define PSE_P1_FC BIT(22) ++#define PSE_P0_FC BIT(21) ++#define PSE_FQ_EMPTY BIT(20) ++#define GE1_STA_CHG BIT(18) ++#define TX_COHERENT BIT(17) ++#define RX_COHERENT BIT(16) ++ ++#define TX_DONE_INT3 BIT(11) ++#define TX_DONE_INT2 BIT(10) ++#define TX_DONE_INT1 BIT(9) ++#define TX_DONE_INT0 BIT(8) ++#define RX_DONE_INT1 RX_DONE_INT0 ++#define RX_DONE_INT0 BIT(2) ++#define TX_DLY_INT BIT(1) ++#define RX_DLY_INT BIT(0) ++#endif ++ ++#define FE_INT_ALL (TX_DONE_INT3 | TX_DONE_INT2 | \ ++ TX_DONE_INT1 | TX_DONE_INT0 | \ ++ RX_DONE_INT0 | RX_DONE_INT1 | \ ++ RX_DONE_INT2 | RX_DONE_INT3) ++ ++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++#define QFE_INT_ALL (RLS_DONE_INT | RX_DONE_INT0 | RX_DONE_INT1) ++#define QFE_INT_DLY_INIT (RLS_DLY_INT | RX_DLY_INT) ++ ++#define NUM_QDMA_PAGE 512 ++#define QDMA_PAGE_SIZE 2048 ++#endif ++/* ++ * SW_INT_STATUS ++ */ ++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++#define PORT0_QUEUE_FULL BIT(14) //port0 queue full ++#define PORT1_QUEUE_FULL BIT(15) //port1 queue full ++#define PORT2_QUEUE_FULL BIT(16) //port2 queue full ++#define PORT3_QUEUE_FULL BIT(17) //port3 queue full ++#define PORT4_QUEUE_FULL BIT(18) //port4 queue full ++#define PORT5_QUEUE_FULL BIT(19) //port5 queue full ++#define PORT6_QUEUE_FULL BIT(20) //port6 queue full ++#define SHARED_QUEUE_FULL BIT(23) //shared queue full ++#define QUEUE_EXHAUSTED BIT(24) //global queue is used up and all packets are dropped ++#define BC_STROM BIT(25) //the device is undergoing broadcast storm ++#define PORT_ST_CHG BIT(26) //Port status change ++#define UNSECURED_ALERT BIT(27) //Intruder alert ++#define ABNORMAL_ALERT BIT(28) //Abnormal ++ ++#define ESW_ISR (RALINK_ETH_SW_BASE + 0x00) ++#define ESW_IMR (RALINK_ETH_SW_BASE + 0x04) ++#define ESW_INT_ALL (PORT_ST_CHG) ++ ++#elif defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) ++#define MIB_INT BIT(25) ++#define ACL_INT BIT(24) ++#define P5_LINK_CH BIT(5) ++#define P4_LINK_CH BIT(4) ++#define P3_LINK_CH BIT(3) ++#define P2_LINK_CH BIT(2) ++#define P1_LINK_CH BIT(1) ++#define P0_LINK_CH BIT(0) ++ ++#define RX_GOCT_CNT BIT(4) ++#define RX_GOOD_CNT BIT(6) ++#define TX_GOCT_CNT BIT(17) ++#define TX_GOOD_CNT BIT(19) ++ ++#define MSK_RX_GOCT_CNT BIT(4) ++#define MSK_RX_GOOD_CNT BIT(6) ++#define MSK_TX_GOCT_CNT BIT(17) ++#define MSK_TX_GOOD_CNT BIT(19) ++#define MSK_CNT_INT_ALL (MSK_RX_GOCT_CNT | MSK_RX_GOOD_CNT | MSK_TX_GOCT_CNT | MSK_TX_GOOD_CNT) ++//#define MSK_CNT_INT_ALL (MSK_RX_GOOD_CNT | MSK_TX_GOOD_CNT) ++ ++ ++#define ESW_IMR (RALINK_ETH_SW_BASE + 0x7000 + 0x8) ++#define ESW_ISR (RALINK_ETH_SW_BASE + 0x7000 + 0xC) ++#define ESW_INT_ALL (P0_LINK_CH | P1_LINK_CH | P2_LINK_CH | P3_LINK_CH | P4_LINK_CH | P5_LINK_CH | ACL_INT | MIB_INT) ++#define ESW_AISR (RALINK_ETH_SW_BASE + 0x8) ++#define ESW_P0_IntSn (RALINK_ETH_SW_BASE + 0x4004) ++#define ESW_P1_IntSn (RALINK_ETH_SW_BASE + 0x4104) ++#define ESW_P2_IntSn (RALINK_ETH_SW_BASE + 0x4204) ++#define ESW_P3_IntSn (RALINK_ETH_SW_BASE + 0x4304) ++#define ESW_P4_IntSn (RALINK_ETH_SW_BASE + 0x4404) ++#define ESW_P5_IntSn (RALINK_ETH_SW_BASE + 0x4504) ++#define ESW_P6_IntSn (RALINK_ETH_SW_BASE + 0x4604) ++#define ESW_P0_IntMn (RALINK_ETH_SW_BASE + 0x4008) ++#define ESW_P1_IntMn (RALINK_ETH_SW_BASE + 0x4108) ++#define ESW_P2_IntMn (RALINK_ETH_SW_BASE + 0x4208) ++#define ESW_P3_IntMn (RALINK_ETH_SW_BASE + 0x4308) ++#define ESW_P4_IntMn (RALINK_ETH_SW_BASE + 0x4408) ++#define ESW_P5_IntMn (RALINK_ETH_SW_BASE + 0x4508) ++#define ESW_P6_IntMn (RALINK_ETH_SW_BASE + 0x4608) ++ ++#if defined (CONFIG_RALINK_MT7620) ++#define ESW_P7_IntSn (RALINK_ETH_SW_BASE + 0x4704) ++#define ESW_P7_IntMn (RALINK_ETH_SW_BASE + 0x4708) ++#endif ++ ++ ++#define ESW_PHY_POLLING (RALINK_ETH_SW_BASE + 0x7000) ++ ++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++ ++#define ESW_PHY_POLLING (RALINK_ETH_SW_BASE + 0x0000) ++ ++#define P5_LINK_CH BIT(5) ++#define P4_LINK_CH BIT(4) ++#define P3_LINK_CH BIT(3) ++#define P2_LINK_CH BIT(2) ++#define P1_LINK_CH BIT(1) ++#define P0_LINK_CH BIT(0) ++ ++ ++#endif // CONFIG_RALINK_RT3052 || CONFIG_RALINK_RT3352 || CONFIG_RALINK_RT5350 || defined (CONFIG_RALINK_MT7628)// ++ ++#define RX_BUF_ALLOC_SIZE 2000 ++#define FASTPATH_HEADROOM 64 ++ ++#define ETHER_BUFFER_ALIGN 32 ///// Align on a cache line ++ ++#define ETHER_ALIGNED_RX_SKB_ADDR(addr) \ ++ ((((unsigned long)(addr) + ETHER_BUFFER_ALIGN - 1) & \ ++ ~(ETHER_BUFFER_ALIGN - 1)) - (unsigned long)(addr)) ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++typedef struct _PSEUDO_ADAPTER { ++ struct net_device *RaethDev; ++ struct net_device *PseudoDev; ++ struct net_device_stats stat; ++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/ ++ struct mii_if_info mii_info; ++#endif ++ ++} PSEUDO_ADAPTER, PPSEUDO_ADAPTER; ++ ++#define MAX_PSEUDO_ENTRY 1 ++#endif ++ ++ ++ ++/* Register Categories Definition */ ++#define RAFRAMEENGINE_OFFSET 0x0000 ++#define RAGDMA_OFFSET 0x0020 ++#define RAPSE_OFFSET 0x0040 ++#define RAGDMA2_OFFSET 0x0060 ++#define RACDMA_OFFSET 0x0080 ++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || \ ++ defined (CONFIG_ARCH_MT7623) ++ ++#define RAPDMA_OFFSET 0x0800 ++#define SDM_OFFSET 0x0C00 ++#else ++#define RAPDMA_OFFSET 0x0100 ++#endif ++#define RAPPE_OFFSET 0x0200 ++#define RACMTABLE_OFFSET 0x0400 ++#define RAPOLICYTABLE_OFFSET 0x1000 ++ ++ ++/* Register Map Detail */ ++/* RT3883 */ ++#define SYSCFG1 (RALINK_SYSCTL_BASE + 0x14) ++ ++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++ ++/* 1. PDMA */ ++#define TX_BASE_PTR0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x000) ++#define TX_MAX_CNT0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x004) ++#define TX_CTX_IDX0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x008) ++#define TX_DTX_IDX0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x00C) ++ ++#define TX_BASE_PTR1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x010) ++#define TX_MAX_CNT1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x014) ++#define TX_CTX_IDX1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x018) ++#define TX_DTX_IDX1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x01C) ++ ++#define TX_BASE_PTR2 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x020) ++#define TX_MAX_CNT2 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x024) ++#define TX_CTX_IDX2 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x028) ++#define TX_DTX_IDX2 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x02C) ++ ++#define TX_BASE_PTR3 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x030) ++#define TX_MAX_CNT3 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x034) ++#define TX_CTX_IDX3 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x038) ++#define TX_DTX_IDX3 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x03C) ++ ++#define RX_BASE_PTR0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x100) ++#define RX_MAX_CNT0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x104) ++#define RX_CALC_IDX0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x108) ++#define RX_DRX_IDX0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x10C) ++ ++#define RX_BASE_PTR1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x110) ++#define RX_MAX_CNT1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x114) ++#define RX_CALC_IDX1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x118) ++#define RX_DRX_IDX1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x11C) ++ ++#define PDMA_INFO (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x200) ++#define PDMA_GLO_CFG (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x204) ++#define PDMA_RST_IDX (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x208) ++#define PDMA_RST_CFG (PDMA_RST_IDX) ++#define DLY_INT_CFG (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x20C) ++#define FREEQ_THRES (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x210) ++#define INT_STATUS (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x220) ++#define FE_INT_STATUS (INT_STATUS) ++#define INT_MASK (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x228) ++#define FE_INT_ENABLE (INT_MASK) ++#define PDMA_WRR (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x280) ++#define PDMA_SCH_CFG (PDMA_WRR) ++ ++#define SDM_CON (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x00) //Switch DMA configuration ++#define SDM_RRING (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x04) //Switch DMA Rx Ring ++#define SDM_TRING (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x08) //Switch DMA Tx Ring ++#define SDM_MAC_ADRL (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x0C) //Switch MAC address LSB ++#define SDM_MAC_ADRH (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x10) //Switch MAC Address MSB ++#define SDM_TPCNT (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x100) //Switch DMA Tx packet count ++#define SDM_TBCNT (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x104) //Switch DMA Tx byte count ++#define SDM_RPCNT (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x108) //Switch DMA rx packet count ++#define SDM_RBCNT (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x10C) //Switch DMA rx byte count ++#define SDM_CS_ERR (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x110) //Switch DMA rx checksum error count ++ ++#elif defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || \ ++ defined (CONFIG_ARCH_MT7623) ++ ++/* Old FE with New PDMA */ ++#define PDMA_RELATED 0x0800 ++/* 1. PDMA */ ++#define TX_BASE_PTR0 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x000) ++#define TX_MAX_CNT0 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x004) ++#define TX_CTX_IDX0 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x008) ++#define TX_DTX_IDX0 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x00C) ++ ++#define TX_BASE_PTR1 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x010) ++#define TX_MAX_CNT1 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x014) ++#define TX_CTX_IDX1 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x018) ++#define TX_DTX_IDX1 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x01C) ++ ++#define TX_BASE_PTR2 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x020) ++#define TX_MAX_CNT2 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x024) ++#define TX_CTX_IDX2 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x028) ++#define TX_DTX_IDX2 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x02C) ++ ++#define TX_BASE_PTR3 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x030) ++#define TX_MAX_CNT3 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x034) ++#define TX_CTX_IDX3 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x038) ++#define TX_DTX_IDX3 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x03C) ++ ++#define RX_BASE_PTR0 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x100) ++#define RX_MAX_CNT0 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x104) ++#define RX_CALC_IDX0 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x108) ++#define RX_DRX_IDX0 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x10C) ++ ++#define RX_BASE_PTR1 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x110) ++#define RX_MAX_CNT1 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x114) ++#define RX_CALC_IDX1 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x118) ++#define RX_DRX_IDX1 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x11C) ++ ++#define RX_BASE_PTR2 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x120) ++#define RX_MAX_CNT2 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x124) ++#define RX_CALC_IDX2 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x128) ++#define RX_DRX_IDX12 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x12C) ++ ++#define RX_BASE_PTR3 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x130) ++#define RX_MAX_CNT3 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x134) ++#define RX_CALC_IDX3 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x138) ++#define RX_DRX_IDX3 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x13C) ++ ++#define PDMA_INFO (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x200) ++#define PDMA_GLO_CFG (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x204) ++#define PDMA_RST_IDX (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x208) ++#define PDMA_RST_CFG (PDMA_RST_IDX) ++#define DLY_INT_CFG (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x20C) ++#define FREEQ_THRES (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x210) ++#define INT_STATUS (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x220) ++#define FE_INT_STATUS (INT_STATUS) ++#define INT_MASK (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x228) ++#define FE_INT_ENABLE (INT_MASK) ++#define SCH_Q01_CFG (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x280) ++#define SCH_Q23_CFG (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x284) ++ ++#define FE_GLO_CFG RALINK_FRAME_ENGINE_BASE + 0x00 ++#define FE_RST_GL RALINK_FRAME_ENGINE_BASE + 0x04 ++#define FE_INT_STATUS2 RALINK_FRAME_ENGINE_BASE + 0x08 ++#define FE_INT_ENABLE2 RALINK_FRAME_ENGINE_BASE + 0x0c ++//#define FC_DROP_STA RALINK_FRAME_ENGINE_BASE + 0x18 ++#define FOE_TS_T RALINK_FRAME_ENGINE_BASE + 0x10 ++ ++#if defined (CONFIG_RALINK_MT7620) ++#define GDMA1_RELATED 0x0600 ++#define GDMA1_FWD_CFG (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x00) ++#define GDMA1_SHPR_CFG (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x04) ++#define GDMA1_MAC_ADRL (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x08) ++#define GDMA1_MAC_ADRH (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x0C) ++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++#define GDMA1_RELATED 0x0500 ++#define GDMA1_FWD_CFG (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x00) ++#define GDMA1_SHPR_CFG (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x04) ++#define GDMA1_MAC_ADRL (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x08) ++#define GDMA1_MAC_ADRH (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x0C) ++ ++#define GDMA2_RELATED 0x1500 ++#define GDMA2_FWD_CFG (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x00) ++#define GDMA2_SHPR_CFG (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x04) ++#define GDMA2_MAC_ADRL (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x08) ++#define GDMA2_MAC_ADRH (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x0C) ++#else ++#define GDMA1_RELATED 0x0020 ++#define GDMA1_FWD_CFG (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x00) ++#define GDMA1_SCH_CFG (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x04) ++#define GDMA1_SHPR_CFG (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x08) ++#define GDMA1_MAC_ADRL (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x0C) ++#define GDMA1_MAC_ADRH (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x10) ++ ++#define GDMA2_RELATED 0x0060 ++#define GDMA2_FWD_CFG (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x00) ++#define GDMA2_SCH_CFG (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x04) ++#define GDMA2_SHPR_CFG (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x08) ++#define GDMA2_MAC_ADRL (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x0C) ++#define GDMA2_MAC_ADRH (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x10) ++#endif ++ ++#if defined (CONFIG_RALINK_MT7620) ++#define PSE_RELATED 0x0500 ++#define PSE_FQFC_CFG (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x00) ++#define PSE_IQ_CFG (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x04) ++#define PSE_QUE_STA (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x08) ++#else ++#define PSE_RELATED 0x0040 ++#define PSE_FQ_CFG (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x00) ++#define CDMA_FC_CFG (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x04) ++#define GDMA1_FC_CFG (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x08) ++#define GDMA2_FC_CFG (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x0C) ++#define CDMA_OQ_STA (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x10) ++#define GDMA1_OQ_STA (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x14) ++#define GDMA2_OQ_STA (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x18) ++#define PSE_IQ_STA (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x1C) ++#endif ++ ++ ++#if defined (CONFIG_RALINK_MT7620) ++#define CDMA_RELATED 0x0400 ++#define CDMA_CSG_CFG (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x00) ++#define SMACCR0 (RALINK_ETH_SW_BASE + 0x3FE4) ++#define SMACCR1 (RALINK_ETH_SW_BASE + 0x3FE8) ++#define CKGCR (RALINK_ETH_SW_BASE + 0x3FF0) ++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++#define CDMA_RELATED 0x0400 ++#define CDMA_CSG_CFG (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x00) //fake definition ++#define CDMP_IG_CTRL (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x00) ++#define CDMP_EG_CTRL (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x04) ++#else ++#define CDMA_RELATED 0x0080 ++#define CDMA_CSG_CFG (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x00) ++#define CDMA_SCH_CFG (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x04) ++#define SMACCR0 (RALINK_ETH_SW_BASE + 0x30E4) ++#define SMACCR1 (RALINK_ETH_SW_BASE + 0x30E8) ++#define CKGCR (RALINK_ETH_SW_BASE + 0x30F0) ++#endif ++ ++#define PDMA_FC_CFG (RALINK_FRAME_ENGINE_BASE+0x100) ++ ++ ++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++/*kurtis: add QDMA define*/ ++ ++#define CLK_CFG_0 (RALINK_SYSCTL_BASE + 0x2C) ++#define PAD_RGMII2_MDIO_CFG (RALINK_SYSCTL_BASE + 0x58) ++ ++#define QDMA_RELATED 0x1800 ++#define QTX_CFG_0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x000) ++#define QTX_SCH_0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x004) ++#define QTX_HEAD_0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x008) ++#define QTX_TAIL_0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x00C) ++#define QTX_CFG_1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x010) ++#define QTX_SCH_1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x014) ++#define QTX_HEAD_1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x018) ++#define QTX_TAIL_1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x01C) ++#define QTX_CFG_2 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x020) ++#define QTX_SCH_2 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x024) ++#define QTX_HEAD_2 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x028) ++#define QTX_TAIL_2 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x02C) ++#define QTX_CFG_3 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x030) ++#define QTX_SCH_3 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x034) ++#define QTX_HEAD_3 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x038) ++#define QTX_TAIL_3 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x03C) ++#define QTX_CFG_4 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x040) ++#define QTX_SCH_4 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x044) ++#define QTX_HEAD_4 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x048) ++#define QTX_TAIL_4 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x04C) ++#define QTX_CFG_5 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x050) ++#define QTX_SCH_5 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x054) ++#define QTX_HEAD_5 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x058) ++#define QTX_TAIL_5 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x05C) ++#define QTX_CFG_6 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x060) ++#define QTX_SCH_6 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x064) ++#define QTX_HEAD_6 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x068) ++#define QTX_TAIL_6 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x06C) ++#define QTX_CFG_7 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x070) ++#define QTX_SCH_7 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x074) ++#define QTX_HEAD_7 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x078) ++#define QTX_TAIL_7 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x07C) ++#define QTX_CFG_8 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x080) ++#define QTX_SCH_8 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x084) ++#define QTX_HEAD_8 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x088) ++#define QTX_TAIL_8 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x08C) ++#define QTX_CFG_9 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x090) ++#define QTX_SCH_9 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x094) ++#define QTX_HEAD_9 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x098) ++#define QTX_TAIL_9 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x09C) ++#define QTX_CFG_10 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0A0) ++#define QTX_SCH_10 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0A4) ++#define QTX_HEAD_10 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0A8) ++#define QTX_TAIL_10 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0AC) ++#define QTX_CFG_11 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0B0) ++#define QTX_SCH_11 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0B4) ++#define QTX_HEAD_11 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0B8) ++#define QTX_TAIL_11 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0BC) ++#define QTX_CFG_12 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0C0) ++#define QTX_SCH_12 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0C4) ++#define QTX_HEAD_12 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0C8) ++#define QTX_TAIL_12 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0CC) ++#define QTX_CFG_13 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0D0) ++#define QTX_SCH_13 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0D4) ++#define QTX_HEAD_13 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0D8) ++#define QTX_TAIL_13 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0DC) ++#define QTX_CFG_14 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0E0) ++#define QTX_SCH_14 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0E4) ++#define QTX_HEAD_14 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0E8) ++#define QTX_TAIL_14 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0EC) ++#define QTX_CFG_15 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0F0) ++#define QTX_SCH_15 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0F4) ++#define QTX_HEAD_15 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0F8) ++#define QTX_TAIL_15 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0FC) ++#define QRX_BASE_PTR_0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x100) ++#define QRX_MAX_CNT_0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x104) ++#define QRX_CRX_IDX_0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x108) ++#define QRX_DRX_IDX_0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x10C) ++#define QRX_BASE_PTR_1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x110) ++#define QRX_MAX_CNT_1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x114) ++#define QRX_CRX_IDX_1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x118) ++#define QRX_DRX_IDX_1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x11C) ++#if defined (CONFIG_ARCH_MT7623) ++#define VQTX_TB_BASE_0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x180) ++#define VQTX_TB_BASE_1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x184) ++#define VQTX_TB_BASE_2 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x188) ++#define VQTX_TB_BASE_3 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x18C) ++#endif ++#define QDMA_INFO (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x200) ++#define QDMA_GLO_CFG (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x204) ++#define QDMA_RST_IDX (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x208) ++#define QDMA_RST_CFG (QDMA_RST_IDX) ++#define QDMA_DELAY_INT (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x20C) ++#define QDMA_FC_THRES (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x210) ++#define QDMA_TX_SCH (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x214) ++#define QDMA_INT_STS (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x218) ++#define QFE_INT_STATUS (QDMA_INT_STS) ++#define QDMA_INT_MASK (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x21C) ++#define QFE_INT_ENABLE (QDMA_INT_MASK) ++#define QDMA_TRTCM (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x220) ++#define QDMA_DATA0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x224) ++#define QDMA_DATA1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x228) ++#define QDMA_RED_THRES (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x22C) ++#define QDMA_TEST (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x230) ++#define QDMA_DMA (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x234) ++#define QDMA_BMU (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x238) ++#define QDMA_HRED1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x240) ++#define QDMA_HRED2 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x244) ++#define QDMA_SRED1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x248) ++#define QDMA_SRED2 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x24C) ++#define QTX_CTX_PTR (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x300) ++#define QTX_DTX_PTR (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x304) ++#define QTX_FWD_CNT (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x308) ++#define QTX_CRX_PTR (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x310) ++#define QTX_DRX_PTR (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x314) ++#define QTX_RLS_CNT (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x318) ++#define QDMA_FQ_HEAD (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x320) ++#define QDMA_FQ_TAIL (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x324) ++#define QDMA_FQ_CNT (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x328) ++#define QDMA_FQ_BLEN (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x32C) ++#define QTX_Q0MIN_BK (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x350) ++#define QTX_Q1MIN_BK (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x354) ++#define QTX_Q2MIN_BK (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x358) ++#define QTX_Q3MIN_BK (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x35C) ++#define QTX_Q0MAX_BK (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x360) ++#define QTX_Q1MAX_BK (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x364) ++#define QTX_Q2MAX_BK (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x368) ++#define QTX_Q3MAX_BK (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x36C) ++ ++ ++#endif/*MT7621 QDMA*/ ++ ++#else ++ ++/* 1. Frame Engine Global Registers */ ++#define MDIO_ACCESS (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x00) ++#define MDIO_CFG (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x04) ++#define FE_GLO_CFG (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x08) ++#define FE_RST_GL (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x0C) ++#define FE_INT_STATUS (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x10) ++#define FE_INT_ENABLE (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x14) ++#define MDIO_CFG2 (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x18) //Original:FC_DROP_STA ++#define FOC_TS_T (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x1C) ++ ++ ++/* 2. GDMA Registers */ ++#define GDMA1_FWD_CFG (RALINK_FRAME_ENGINE_BASE+RAGDMA_OFFSET+0x00) ++#define GDMA1_SCH_CFG (RALINK_FRAME_ENGINE_BASE+RAGDMA_OFFSET+0x04) ++#define GDMA1_SHPR_CFG (RALINK_FRAME_ENGINE_BASE+RAGDMA_OFFSET+0x08) ++#define GDMA1_MAC_ADRL (RALINK_FRAME_ENGINE_BASE+RAGDMA_OFFSET+0x0C) ++#define GDMA1_MAC_ADRH (RALINK_FRAME_ENGINE_BASE+RAGDMA_OFFSET+0x10) ++ ++#define GDMA2_FWD_CFG (RALINK_FRAME_ENGINE_BASE+RAGDMA2_OFFSET+0x00) ++#define GDMA2_SCH_CFG (RALINK_FRAME_ENGINE_BASE+RAGDMA2_OFFSET+0x04) ++#define GDMA2_SHPR_CFG (RALINK_FRAME_ENGINE_BASE+RAGDMA2_OFFSET+0x08) ++#define GDMA2_MAC_ADRL (RALINK_FRAME_ENGINE_BASE+RAGDMA2_OFFSET+0x0C) ++#define GDMA2_MAC_ADRH (RALINK_FRAME_ENGINE_BASE+RAGDMA2_OFFSET+0x10) ++ ++/* 3. PSE */ ++#define PSE_FQ_CFG (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x00) ++#define CDMA_FC_CFG (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x04) ++#define GDMA1_FC_CFG (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x08) ++#define GDMA2_FC_CFG (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x0C) ++#define PDMA_FC_CFG (RALINK_FRAME_ENGINE_BASE+0x1f0) ++ ++/* 4. CDMA */ ++#define CDMA_CSG_CFG (RALINK_FRAME_ENGINE_BASE+RACDMA_OFFSET+0x00) ++#define CDMA_SCH_CFG (RALINK_FRAME_ENGINE_BASE+RACDMA_OFFSET+0x04) ++/* skip ppoe sid and vlan id definition */ ++ ++ ++/* 5. PDMA */ ++#define PDMA_GLO_CFG (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x00) ++#define PDMA_RST_CFG (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x04) ++#define PDMA_SCH_CFG (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x08) ++ ++#define DLY_INT_CFG (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x0C) ++ ++#define TX_BASE_PTR0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x10) ++#define TX_MAX_CNT0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x14) ++#define TX_CTX_IDX0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x18) ++#define TX_DTX_IDX0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x1C) ++ ++#define TX_BASE_PTR1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x20) ++#define TX_MAX_CNT1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x24) ++#define TX_CTX_IDX1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x28) ++#define TX_DTX_IDX1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x2C) ++ ++#define TX_BASE_PTR2 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x40) ++#define TX_MAX_CNT2 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x44) ++#define TX_CTX_IDX2 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x48) ++#define TX_DTX_IDX2 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x4C) ++ ++#define TX_BASE_PTR3 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x50) ++#define TX_MAX_CNT3 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x54) ++#define TX_CTX_IDX3 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x58) ++#define TX_DTX_IDX3 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x5C) ++ ++#define RX_BASE_PTR0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x30) ++#define RX_MAX_CNT0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x34) ++#define RX_CALC_IDX0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x38) ++#define RX_DRX_IDX0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x3C) ++ ++#define RX_BASE_PTR1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x40) ++#define RX_MAX_CNT1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x44) ++#define RX_CALC_IDX1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x48) ++#define RX_DRX_IDX1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x4C) ++ ++#endif ++ ++#define DELAY_INT_INIT 0x84048404 ++#define FE_INT_DLY_INIT (TX_DLY_INT | RX_DLY_INT) ++ ++ ++#if !defined (CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628) ++ ++/* 6. Counter and Meter Table */ ++#define PPE_AC_BCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x000) /* PPE Accounting Group 0 Byte Cnt */ ++#define PPE_AC_PCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x004) /* PPE Accounting Group 0 Packet Cnt */ ++/* 0 ~ 63 */ ++ ++#define PPE_MTR_CNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x200) /* 0 ~ 63 */ ++/* skip... */ ++#define PPE_MTR_CNT63 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x2FC) ++ ++#define GDMA_TX_GBCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x300) /* Transmit good byte cnt for GEport */ ++#define GDMA_TX_GPCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x304) /* Transmit good pkt cnt for GEport */ ++#define GDMA_TX_SKIPCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x308) /* Transmit skip cnt for GEport */ ++#define GDMA_TX_COLCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x30C) /* Transmit collision cnt for GEport */ ++ ++/* update these address mapping to fit data sheet v0.26, by bobtseng, 2007.6.14 */ ++#define GDMA_RX_GBCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x320) ++#define GDMA_RX_GPCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x324) ++#define GDMA_RX_OERCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x328) ++#define GDMA_RX_FERCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x32C) ++#define GDMA_RX_SERCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x330) ++#define GDMA_RX_LERCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x334) ++#define GDMA_RX_CERCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x338) ++#define GDMA_RX_FCCNT1 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x33C) ++ ++#endif ++ ++/* LRO global control */ ++/* Bits [15:0]:LRO_ALT_RFSH_TIMER, Bits [20:16]:LRO_ALT_TICK_TIMER */ ++#define LRO_ALT_REFRESH_TIMER (RALINK_FRAME_ENGINE_BASE+0x001C) ++ ++/* LRO auto-learn table info */ ++#define PDMA_FE_ALT_CF8 (RALINK_FRAME_ENGINE_BASE+0x0300) ++#define PDMA_FE_ALT_SGL_CFC (RALINK_FRAME_ENGINE_BASE+0x0304) ++#define PDMA_FE_ALT_SEQ_CFC (RALINK_FRAME_ENGINE_BASE+0x0308) ++ ++/* LRO controls */ ++#define ADMA_LRO_CTRL_OFFSET 0x0980 ++/* ++ * Bit [0]:LRO_EN, Bit [1]:LRO_IPv6_EN, Bit [2]:MULTIPLE_NON_LRO_RX_RING_EN, Bit [3]:MULTIPLE_RXD_PREFETCH_EN, ++ * Bit [4]:RXD_PREFETCH_EN, Bit [5]:LRO_DLY_INT_EN, Bit [6]:LRO_CRSN_BNW, Bit [7]:L3_CKS_UPD_EN, ++ * Bit [20]:first_ineligible_pkt_redirect_en, Bit [21]:cr_lro_alt_score_mode, Bit [22]:cr_lro_alt_rplc_mode, ++ * Bit [23]:cr_lro_l4_ctrl_psh_en, Bits [28:26]:LRO_RING_RELINGUISH_REQ, Bits [31:29]:LRO_RING_RELINGUISH_DONE ++ */ ++#define ADMA_LRO_CTRL_DW0 (RALINK_FRAME_ENGINE_BASE+ADMA_LRO_CTRL_OFFSET+0x00) ++/* Bits [31:0]:LRO_CPU_REASON */ ++#define ADMA_LRO_CTRL_DW1 (RALINK_FRAME_ENGINE_BASE+ADMA_LRO_CTRL_OFFSET+0x04) ++/* Bits [31:0]:AUTO_LEARN_LRO_ELIGIBLE_THRESHOLD */ ++#define ADMA_LRO_CTRL_DW2 (RALINK_FRAME_ENGINE_BASE+ADMA_LRO_CTRL_OFFSET+0x08) ++/* ++ * Bits [7:0]:LRO_MAX_AGGREGATED_CNT, Bits [11:8]:LRO_VLAN_EN, Bits [13:12]:LRO_VLAN_VID_CMP_DEPTH, ++ * Bit [14]:ADMA_FW_RSTN_REQ, Bit [15]:ADMA_MODE, Bits [31:16]:LRO_MIN_RXD_SDL0 ++ */ ++#define ADMA_LRO_CTRL_DW3 (RALINK_FRAME_ENGINE_BASE+ADMA_LRO_CTRL_OFFSET+0x0C) ++ ++/* LRO RX delay interrupt configurations */ ++#define LRO_RX1_DLY_INT (RALINK_FRAME_ENGINE_BASE+0x0a70) ++#define LRO_RX2_DLY_INT (RALINK_FRAME_ENGINE_BASE+0x0a74) ++#define LRO_RX3_DLY_INT (RALINK_FRAME_ENGINE_BASE+0x0a78) ++ ++/* LRO auto-learn configurations */ ++#define PDMA_LRO_ATL_OVERFLOW_ADJ_OFFSET 0x0990 ++#define PDMA_LRO_ATL_OVERFLOW_ADJ (RALINK_FRAME_ENGINE_BASE+PDMA_LRO_ATL_OVERFLOW_ADJ_OFFSET) ++#define LRO_ALT_SCORE_DELTA (RALINK_FRAME_ENGINE_BASE+0x0a4c) ++ ++/* LRO agg timer configurations */ ++#define LRO_MAX_AGG_TIME (RALINK_FRAME_ENGINE_BASE+0x0a5c) ++ ++/* LRO configurations of RX ring #0 */ ++#define LRO_RXRING0_OFFSET 0x0b00 ++#define LRO_RX_RING0_DIP_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x04) ++#define LRO_RX_RING0_DIP_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x08) ++#define LRO_RX_RING0_DIP_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x0C) ++#define LRO_RX_RING0_DIP_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x10) ++#define LRO_RX_RING0_CTRL_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x28) ++/* Bit [8]:RING0_VLD, Bit [9]:RING0_MYIP_VLD */ ++#define LRO_RX_RING0_CTRL_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x2C) ++#define LRO_RX_RING0_CTRL_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x30) ++/* LRO configurations of RX ring #1 */ ++#define LRO_RXRING1_OFFSET 0x0b40 ++#define LRO_RX_RING1_STP_DTP_DW (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x00) ++#define LRO_RX_RING1_DIP_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x04) ++#define LRO_RX_RING1_DIP_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x08) ++#define LRO_RX_RING1_DIP_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x0C) ++#define LRO_RX_RING1_DIP_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x10) ++#define LRO_RX_RING1_SIP_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x14) ++#define LRO_RX_RING1_SIP_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x18) ++#define LRO_RX_RING1_SIP_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x1C) ++#define LRO_RX_RING1_SIP_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x20) ++#define LRO_RX_RING1_CTRL_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x24) ++#define LRO_RX_RING1_CTRL_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x28) ++#define LRO_RX_RING1_CTRL_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x2C) ++#define LRO_RX_RING1_CTRL_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x30) ++#define LRO_RXRING2_OFFSET 0x0b80 ++#define LRO_RX_RING2_STP_DTP_DW (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x00) ++#define LRO_RX_RING2_DIP_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x04) ++#define LRO_RX_RING2_DIP_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x08) ++#define LRO_RX_RING2_DIP_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x0C) ++#define LRO_RX_RING2_DIP_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x10) ++#define LRO_RX_RING2_SIP_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x14) ++#define LRO_RX_RING2_SIP_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x18) ++#define LRO_RX_RING2_SIP_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x1C) ++#define LRO_RX_RING2_SIP_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x20) ++#define LRO_RX_RING2_CTRL_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x24) ++#define LRO_RX_RING2_CTRL_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x28) ++#define LRO_RX_RING2_CTRL_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x2C) ++#define LRO_RX_RING2_CTRL_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x30) ++#define LRO_RXRING3_OFFSET 0x0bc0 ++#define LRO_RX_RING3_STP_DTP_DW (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x00) ++#define LRO_RX_RING3_DIP_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x04) ++#define LRO_RX_RING3_DIP_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x08) ++#define LRO_RX_RING3_DIP_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x0C) ++#define LRO_RX_RING3_DIP_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x10) ++#define LRO_RX_RING3_SIP_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x14) ++#define LRO_RX_RING3_SIP_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x18) ++#define LRO_RX_RING3_SIP_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x1C) ++#define LRO_RX_RING3_SIP_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x20) ++#define LRO_RX_RING3_CTRL_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x24) ++#define LRO_RX_RING3_CTRL_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x28) ++#define LRO_RX_RING3_CTRL_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x2C) ++#define LRO_RX_RING3_CTRL_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x30) ++ ++/* LRO RX ring mode */ ++#define PDMA_RX_NORMAL_MODE (0x0) ++#define PDMA_RX_PSE_MODE (0x1) ++#define PDMA_RX_FORCE_PORT (0x2) ++#define PDMA_RX_AUTO_LEARN (0x3) ++ ++#define ADMA_RX_RING0 (0) ++#define ADMA_RX_RING1 (1) ++#define ADMA_RX_RING2 (2) ++#define ADMA_RX_RING3 (3) ++ ++#define ADMA_RX_LEN0_MASK (0x3fff) ++#define ADMA_RX_LEN1_MASK (0x3) ++ ++#define PDMA_LRO_EN BIT(0) ++#define PDMA_LRO_IPV6_EN BIT(1) ++#define PDMA_LRO_IPV4_CSUM_UPDATE_EN BIT(7) ++#define PDMA_LRO_IPV4_CTRL_PUSH_EN BIT(23) ++#define PDMA_LRO_RXD_PREFETCH_EN BITS(3,4) ++#define PDMA_NON_LRO_MULTI_EN BIT(2) ++#define PDMA_LRO_DLY_INT_EN BIT(5) ++#define PDMA_LRO_FUSH_REQ BITS(26,28) ++#define PDMA_LRO_RELINGUISH BITS(29,31) ++#define PDMA_LRO_FREQ_PRI_ADJ BITS(16,19) ++#define PDMA_LRO_TPUT_PRE_ADJ BITS(8,11) ++#define PDMA_LRO_TPUT_PRI_ADJ BITS(12,15) ++#define PDMA_LRO_ALT_SCORE_MODE BIT(21) ++#define PDMA_LRO_RING_AGE1 BITS(22,31) ++#define PDMA_LRO_RING_AGE2 BITS(0,5) ++#define PDMA_LRO_RING_AGG BITS(10,25) ++#define PDMA_LRO_RING_AGG_CNT1 BITS(26,31) ++#define PDMA_LRO_RING_AGG_CNT2 BITS(0,1) ++#define PDMA_LRO_ALT_TICK_TIMER BITS(16,20) ++#define PDMA_LRO_LRO_MIN_RXD_SDL0 BITS(16,31) ++ ++#define PDMA_LRO_DLY_INT_EN_OFFSET (5) ++#define PDMA_LRO_TPUT_PRE_ADJ_OFFSET (8) ++#define PDMA_LRO_FREQ_PRI_ADJ_OFFSET (16) ++#define PDMA_LRO_LRO_MIN_RXD_SDL0_OFFSET (16) ++#define PDMA_LRO_TPUT_PRI_ADJ_OFFSET (12) ++#define PDMA_LRO_ALT_SCORE_MODE_OFFSET (21) ++#define PDMA_LRO_FUSH_REQ_OFFSET (26) ++#define PDMA_NON_LRO_MULTI_EN_OFFSET (2) ++#define PDMA_LRO_IPV6_EN_OFFSET (1) ++#define PDMA_LRO_RXD_PREFETCH_EN_OFFSET (3) ++#define PDMA_LRO_IPV4_CSUM_UPDATE_EN_OFFSET (7) ++#define PDMA_LRO_IPV4_CTRL_PUSH_EN_OFFSET (23) ++#define PDMA_LRO_ALT_TICK_TIMER_OFFSET (16) ++ ++#define PDMA_LRO_TPUT_OVERFLOW_ADJ BITS(12,31) ++#define PDMA_LRO_CNT_OVERFLOW_ADJ BITS(0,11) ++ ++#define PDMA_LRO_TPUT_OVERFLOW_ADJ_OFFSET (12) ++#define PDMA_LRO_CNT_OVERFLOW_ADJ_OFFSET (0) ++ ++#define PDMA_LRO_ALT_BYTE_CNT_MODE (0) ++#define PDMA_LRO_ALT_PKT_CNT_MODE (1) ++ ++/* LRO_RX_RING1_CTRL_DW1 offsets */ ++#define PDMA_LRO_AGE_H_OFFSET (10) ++#define PDMA_LRO_RING_AGE1_OFFSET (22) ++#define PDMA_LRO_RING_AGG_CNT1_OFFSET (26) ++/* LRO_RX_RING1_CTRL_DW2 offsets */ ++#define PDMA_RX_MODE_OFFSET (6) ++#define PDMA_RX_PORT_VALID_OFFSET (8) ++#define PDMA_RX_MYIP_VALID_OFFSET (9) ++#define PDMA_LRO_RING_AGE2_OFFSET (0) ++#define PDMA_LRO_RING_AGG_OFFSET (10) ++#define PDMA_LRO_RING_AGG_CNT2_OFFSET (0) ++/* LRO_RX_RING1_CTRL_DW3 offsets */ ++#define PDMA_LRO_AGG_CNT_H_OFFSET (6) ++/* LRO_RX_RING1_STP_DTP_DW offsets */ ++#define PDMA_RX_TCP_SRC_PORT_OFFSET (16) ++#define PDMA_RX_TCP_DEST_PORT_OFFSET (0) ++/* LRO_RX_RING1_CTRL_DW0 offsets */ ++#define PDMA_RX_IPV4_FORCE_OFFSET (1) ++#define PDMA_RX_IPV6_FORCE_OFFSET (0) ++ ++#define SET_ADMA_RX_LEN0(x) ((x)&ADMA_RX_LEN0_MASK) ++#define SET_ADMA_RX_LEN1(x) ((x)&ADMA_RX_LEN1_MASK) ++ ++#define SET_PDMA_LRO_MAX_AGG_CNT(x) \ ++ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW3; \ ++ *addr &= ~0xff; \ ++ *addr |= ((x) & 0xff); \ ++ } ++#define SET_PDMA_LRO_FLUSH_REQ(x) \ ++ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \ ++ *addr &= ~PDMA_LRO_FUSH_REQ; \ ++ *addr |= ((x) & 0x7)<>PDMA_LRO_AGE_H_OFFSET) & 0x03f)<>PDMA_LRO_AGG_CNT_H_OFFSET) & 0x03)< KERNEL_VERSION(2,6,35) ++ struct napi_struct napi; ++#endif ++#endif ++#ifdef CONFIG_PSEUDO_SUPPORT ++ struct net_device *PseudoDev; ++ unsigned int isPseudo; ++#endif ++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/ ++ struct mii_if_info mii_info; ++#endif ++#ifdef CONFIG_RAETH_LRO ++ struct lro_counters lro_counters; ++ struct net_lro_mgr lro_mgr; ++ struct net_lro_desc lro_arr[8]; ++#endif ++#ifdef CONFIG_RAETH_HW_VLAN_RX ++ struct vlan_group *vlgrp; ++#endif ++#if defined (CONFIG_RAETH_HW_LRO) ++ struct work_struct hw_lro_wq; ++ unsigned int hw_lro_pkt_interval[3]; ++ unsigned int hw_lro_alpha; /* 0 < packet interval alpha <= 10 */ ++ unsigned int hw_lro_fix_setting; /* 0: dynamical AGG/AGE time, 1: fixed AGG/AGE time */ ++#endif /* CONFIG_RAETH_HW_LRO */ ++} END_DEVICE, *pEND_DEVICE; ++ ++ ++#define RAETH_VERSION "v3.1" ++ ++#endif ++ ++#define DMA_GLO_CFG PDMA_GLO_CFG ++ ++#if defined(CONFIG_RAETH_QDMATX_QDMARX) ++#define GDMA1_FWD_PORT 0x5555 ++#define GDMA2_FWD_PORT 0x5555 ++#elif defined(CONFIG_RAETH_PDMATX_QDMARX) ++#define GDMA1_FWD_PORT 0x5555 ++#define GDMA2_FWD_PORT 0x5555 ++#else ++#define GDMA1_FWD_PORT 0x0000 ++#define GDMA2_FWD_PORT 0x0000 ++#endif ++ ++#if defined(CONFIG_RAETH_QDMATX_QDMARX) ++#define RAETH_RX_CALC_IDX0 QRX_CRX_IDX_0 ++#define RAETH_RX_CALC_IDX1 QRX_CRX_IDX_1 ++#elif defined(CONFIG_RAETH_PDMATX_QDMARX) ++#define RAETH_RX_CALC_IDX0 QRX_CRX_IDX_0 ++#define RAETH_RX_CALC_IDX1 QRX_CRX_IDX_1 ++#else ++#define RAETH_RX_CALC_IDX0 RX_CALC_IDX0 ++#define RAETH_RX_CALC_IDX1 RX_CALC_IDX1 ++#endif ++#define RAETH_RX_CALC_IDX2 RX_CALC_IDX2 ++#define RAETH_RX_CALC_IDX3 RX_CALC_IDX3 ++#define RAETH_FE_INT_STATUS FE_INT_STATUS ++#define RAETH_FE_INT_ALL FE_INT_ALL ++#define RAETH_FE_INT_ENABLE FE_INT_ENABLE ++#define RAETH_FE_INT_DLY_INIT FE_INT_DLY_INIT ++#define RAETH_FE_INT_SETTING RX_DONE_INT0 | RX_DONE_INT1 | TX_DONE_INT0 | TX_DONE_INT1 | TX_DONE_INT2 | TX_DONE_INT3 ++#define QFE_INT_SETTING RX_DONE_INT0 | RX_DONE_INT1 | TX_DONE_INT0 | TX_DONE_INT1 | TX_DONE_INT2 | TX_DONE_INT3 ++#define RAETH_TX_DLY_INT TX_DLY_INT ++#define RAETH_TX_DONE_INT0 TX_DONE_INT0 ++#define RAETH_DLY_INT_CFG DLY_INT_CFG +diff --git a/drivers/net/ethernet/raeth/ra_ethtool.c b/drivers/net/ethernet/raeth/ra_ethtool.c +new file mode 100644 +index 0000000..ff13e59 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/ra_ethtool.c +@@ -0,0 +1,515 @@ ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "ra2882ethreg.h" ++#include "raether.h" ++#include "ra_mac.h" ++#include "ra_ethtool.h" ++ ++#define RAETHER_DRIVER_NAME "raether" ++#define RA_NUM_STATS 4 ++ ++ ++static struct { ++ const char str[ETH_GSTRING_LEN]; ++} ethtool_stats_keys[] = { ++ { "statistic1" }, ++ { "statistic2" }, ++ { "statistic3" }, ++ { "statistic4" }, ++}; ++ ++unsigned char get_current_phy_address(void) ++{ ++ struct net_device *cur_dev_p; ++ END_DEVICE *ei_local; ++#if 0 ++ for(cur_dev_p=dev_base; cur_dev_p!=NULL; cur_dev_p=cur_dev_p->next){ ++ if (strncmp(cur_dev_p->name, DEV_NAME /* "eth2" usually */, 4) == 0) ++ break; ++ } ++#else ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ cur_dev_p = dev_get_by_name(&init_net, DEV_NAME); ++#else ++ cur_dev_p = dev_get_by_name(DEV_NAME); ++#endif ++#endif ++ if(!cur_dev_p) ++ return 0; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ ei_local = netdev_priv(cur_dev_p); ++#else ++ ei_local = cur_dev_p->priv; ++#endif ++ return ei_local->mii_info.phy_id; ++} ++#if 0 ++static u32 et_get_tx_csum(struct net_device *dev) ++{ ++ return (sysRegRead(GDMA1_FWD_CFG) & GDM1_DISCRC) ? 0 : 1; // a pitfall here, "0" means to enable. ++} ++ ++static u32 et_get_rx_csum(struct net_device *dev) ++{ ++ return (sysRegRead(GDMA1_FWD_CFG) & GDM1_STRPCRC) ? 1 : 0; ++} ++ ++static int et_set_tx_csum(struct net_device *dev, u32 data) ++{ ++ int value; ++ //printk("et_set_tx_csum(): data = %d\n", data); ++ ++ value = sysRegRead(GDMA1_FWD_CFG); ++ if(data) ++ value |= GDM1_DISCRC; ++ else ++ value &= ~GDM1_DISCRC; ++ ++ sysRegWrite(GDMA1_FWD_CFG, value); ++ return 0; ++} ++ ++static int et_set_rx_csum(struct net_device *dev, u32 data) ++{ ++ int value; ++ //printk("et_set_rx_csum(): data = %d\n", data); ++ ++ value = sysRegRead(GDMA1_FWD_CFG); ++ if(data) ++ value |= GDM1_STRPCRC; ++ else ++ value &= ~GDM1_STRPCRC; ++ ++ sysRegWrite(GDMA1_FWD_CFG, value); ++ return 0; ++} ++#endif ++ ++#define MII_CR_ADDR 0x00 ++#define MII_CR_MR_AUTONEG_ENABLE (1 << 12) ++#define MII_CR_MR_RESTART_NEGOTIATION (1 << 9) ++ ++#define AUTO_NEGOTIATION_ADVERTISEMENT 0x04 ++#define AN_PAUSE (1 << 10) ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ++static void et_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) ++{ ++ int mii_an_reg; ++ int mdio_cfg_reg; ++ END_DEVICE *ei_local = dev->priv; ++ ++ // get mii auto-negotiation register ++ mii_mgr_read(ei_local->mii_info.phy_id, AUTO_NEGOTIATION_ADVERTISEMENT, &mii_an_reg); ++ epause->autoneg = (mii_an_reg & AN_PAUSE) ? 1 : 0; //get autonet_enable flag bit ++ ++ mdio_cfg_reg = sysRegRead(MDIO_CFG); ++ epause->tx_pause = (mdio_cfg_reg & MDIO_CFG_GP1_FC_TX) ? 1 : 0; ++ epause->rx_pause = (mdio_cfg_reg & MDIO_CFG_GP1_FC_RX) ? 1 : 0; ++ ++ //printk("et_get_pauseparam(): autoneg=%d, tx_pause=%d, rx_pause=%d\n", epause->autoneg, epause->tx_pause, epause->rx_pause); ++} ++ ++static int et_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) ++{ ++ int mdio_cfg_reg; ++ int mii_an_reg; ++ END_DEVICE *ei_local = dev->priv; ++ ++ //printk("et_set_pauseparam(): autoneg=%d, tx_pause=%d, rx_pause=%d\n", epause->autoneg, epause->tx_pause, epause->rx_pause); ++ ++ // auto-neg pause ++ mii_mgr_read(ei_local->mii_info.phy_id, AUTO_NEGOTIATION_ADVERTISEMENT, &mii_an_reg); ++ if(epause->autoneg) ++ mii_an_reg |= AN_PAUSE; ++ else ++ mii_an_reg &= ~AN_PAUSE; ++ mii_mgr_write(ei_local->mii_info.phy_id, AUTO_NEGOTIATION_ADVERTISEMENT, mii_an_reg); ++ ++ // tx/rx pause ++ mdio_cfg_reg = sysRegRead(MDIO_CFG); ++ if(epause->tx_pause) ++ mdio_cfg_reg |= MDIO_CFG_GP1_FC_TX; ++ else ++ mdio_cfg_reg &= ~MDIO_CFG_GP1_FC_TX; ++ if(epause->rx_pause) ++ mdio_cfg_reg |= MDIO_CFG_GP1_FC_RX; ++ else ++ mdio_cfg_reg &= ~MDIO_CFG_GP1_FC_RX; ++ sysRegWrite(MDIO_CFG, mdio_cfg_reg); ++ ++ return 0; ++} ++ ++static int et_nway_reset(struct net_device *dev) ++{ ++ END_DEVICE *ei_local = dev->priv; ++ return mii_nway_restart(&ei_local->mii_info); ++} ++#endif ++ ++static u32 et_get_link(struct net_device *dev) ++{ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ END_DEVICE *ei_local = netdev_priv(dev); ++#else ++ END_DEVICE *ei_local = dev->priv; ++#endif ++ return mii_link_ok(&ei_local->mii_info); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ++static int et_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) ++{ ++ END_DEVICE *ei_local = dev->priv; ++ int rc; ++ rc = mii_ethtool_sset(&ei_local->mii_info, cmd); ++ return rc; ++} ++#endif ++ ++static int et_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) ++{ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ END_DEVICE *ei_local = netdev_priv(dev); ++#else ++ END_DEVICE *ei_local = dev->priv; ++#endif ++ mii_ethtool_gset(&ei_local->mii_info, cmd); ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ++static u32 et_get_msglevel(struct net_device *dev) ++{ ++ return 0; ++} ++ ++static void et_set_msglevel(struct net_device *dev, u32 datum) ++{ ++ return; ++} ++ ++static void et_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) ++{ ++ //END_DEVICE *ei_local = dev->priv; ++ strcpy(info->driver, RAETHER_DRIVER_NAME); ++ strcpy(info->version, RAETH_VERSION); ++ strcpy(info->bus_info, "n/a"); ++ info->n_stats = RA_NUM_STATS; ++ info->eedump_len = 0; ++ info->regdump_len = 0; ++} ++ ++static int et_get_stats_count(struct net_device *dev) ++{ ++ return RA_NUM_STATS; ++} ++ ++static void et_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) ++{ ++// END_DEVICE *ei_local = dev->priv; ++ data[0] = 0;//np->xstats.early_rx; ++ data[1] = 0;//np->xstats.tx_buf_mapped; ++ data[2] = 0;//np->xstats.tx_timeouts; ++ data[3] = 0;//np->xstats.rx_lost_in_ring; ++} ++ ++static void et_get_strings(struct net_device *dev, u32 stringset, u8 *data) ++{ ++ memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); ++} ++#endif ++ ++/* ++ * mii_mgr_read wrapper for mii.o ethtool ++ */ ++int mdio_read(struct net_device *dev, int phy_id, int location) ++{ ++ unsigned int result; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ END_DEVICE *ei_local = netdev_priv(dev); ++#else ++ END_DEVICE *ei_local = dev->priv; ++#endif ++ mii_mgr_read( (unsigned int) ei_local->mii_info.phy_id, (unsigned int)location, &result); ++ //printk("\n%s mii.o query= phy_id:%d, address:%d retval:%x\n", dev->name, phy_id, location, result); ++ return (int)result; ++} ++ ++/* ++ * mii_mgr_write wrapper for mii.o ethtool ++ */ ++void mdio_write(struct net_device *dev, int phy_id, int location, int value) ++{ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ END_DEVICE *ei_local = netdev_priv(dev); ++#else ++ END_DEVICE *ei_local = dev->priv; ++#endif ++ //printk("mii.o write= phy_id:%d, address:%d value:%x\n", phy_id, location, value); ++ mii_mgr_write( (unsigned int) ei_local->mii_info.phy_id, (unsigned int)location, (unsigned int)value); ++ return; ++} ++ ++struct ethtool_ops ra_ethtool_ops = { ++ ++ .get_settings = et_get_settings, ++ .get_link = et_get_link, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ++ .get_drvinfo = et_get_drvinfo, ++ .set_settings = et_set_settings, ++ .get_pauseparam = et_get_pauseparam, ++ .set_pauseparam = et_set_pauseparam, ++// .get_rx_csum = et_get_rx_csum, ++// .set_rx_csum = et_set_rx_csum, ++// .get_tx_csum = et_get_tx_csum, ++// .set_tx_csum = et_set_tx_csum, ++ .nway_reset = et_nway_reset, ++ .get_msglevel = et_get_msglevel, ++ .set_msglevel = et_set_msglevel, ++ .get_strings = et_get_strings, ++ .get_stats_count = et_get_stats_count, ++ .get_ethtool_stats = et_get_ethtool_stats, ++/* .get_regs_len = et_get_regs_len, ++ .get_regs = et_get_regs, ++*/ ++#endif ++}; ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++/* ++ * We unable to re-use the Raether functions because it is hard to tell ++ * where the calling from is. From eth2 or eth3? ++ * ++ * These code size is around 950 bytes. ++ */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ++static void et_virt_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) ++{ ++ // PSEUDO_ADAPTER *pseudo = dev->priv; ++ return et_get_drvinfo(dev, info); ++} ++ ++static void et_virt_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) ++{ ++ int mii_an_reg, mdio_cfg_reg; ++ PSEUDO_ADAPTER *pseudo = dev->priv; ++ ++ // get mii auto-negotiation register ++ mii_mgr_read(pseudo->mii_info.phy_id, AUTO_NEGOTIATION_ADVERTISEMENT, &mii_an_reg); ++ epause->autoneg = (mii_an_reg & AN_PAUSE) ? 1 : 0; //get autonet_enable flag bit ++ ++ mdio_cfg_reg = sysRegRead(MDIO_CFG); ++ epause->tx_pause = (mdio_cfg_reg & MDIO_CFG_GP1_FC_TX) ? 1 : 0; ++ epause->rx_pause = (mdio_cfg_reg & MDIO_CFG_GP1_FC_RX) ? 1 : 0; ++ ++ //printk("et_get_pauseparam(): autoneg=%d, tx_pause=%d, rx_pause=%d\n", epause->autoneg, epause->tx_pause, epause->rx_pause); ++} ++ ++static int et_virt_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) ++{ ++ int mdio_cfg_reg; ++ int mii_an_reg; ++ PSEUDO_ADAPTER *pseudo = dev->priv; ++ ++ //printk("et_set_pauseparam(): autoneg=%d, tx_pause=%d, rx_pause=%d\n", epause->autoneg, epause->tx_pause, epause->rx_pause); ++ // auto-neg pause ++ mii_mgr_read(pseudo->mii_info.phy_id, AUTO_NEGOTIATION_ADVERTISEMENT, &mii_an_reg); ++ if(epause->autoneg) ++ mii_an_reg |= AN_PAUSE; ++ else ++ mii_an_reg &= ~AN_PAUSE; ++ mii_mgr_write(pseudo->mii_info.phy_id, AUTO_NEGOTIATION_ADVERTISEMENT, mii_an_reg); ++ ++ // tx/rx pause ++ mdio_cfg_reg = sysRegRead(MDIO_CFG); ++ if(epause->tx_pause) ++ mdio_cfg_reg |= MDIO_CFG_GP1_FC_TX; ++ else ++ mdio_cfg_reg &= ~MDIO_CFG_GP1_FC_TX; ++ if(epause->rx_pause) ++ mdio_cfg_reg |= MDIO_CFG_GP1_FC_RX; ++ else ++ mdio_cfg_reg &= ~MDIO_CFG_GP1_FC_RX; ++ sysRegWrite(MDIO_CFG, mdio_cfg_reg); ++ ++ return 0; ++} ++ ++static u32 et_virt_get_tx_csum(struct net_device *dev) ++{ ++ return (sysRegRead(GDMA2_FWD_CFG) & GDM1_DISCRC) ? 0 : 1; // a pitfall here, "0" means to enable. ++} ++ ++static u32 et_virt_get_rx_csum(struct net_device *dev) ++{ ++ return (sysRegRead(GDMA2_FWD_CFG) & GDM1_STRPCRC) ? 1 : 0; ++} ++ ++static int et_virt_set_tx_csum(struct net_device *dev, u32 data) ++{ ++ int value; ++ //printk("et_set_tx_csum(): data = %d\n", data); ++ value = sysRegRead(GDMA2_FWD_CFG); ++ if(data) ++ value |= GDM1_DISCRC; ++ else ++ value &= ~GDM1_DISCRC; ++ sysRegWrite(GDMA1_FWD_CFG, value); ++ return 0; ++} ++ ++static int et_virt_set_rx_csum(struct net_device *dev, u32 data) ++{ ++ int value; ++ //printk("et_set_rx_csum(): data = %d\n", data); ++ value = sysRegRead(GDMA2_FWD_CFG); ++ if(data) ++ value |= GDM1_STRPCRC; ++ else ++ value &= ~GDM1_STRPCRC; ++ sysRegWrite(GDMA1_FWD_CFG, value); ++ return 0; ++} ++ ++static int et_virt_nway_reset(struct net_device *dev) ++{ ++ PSEUDO_ADAPTER *pseudo = dev->priv; ++ return mii_nway_restart(&pseudo->mii_info); ++} ++#endif ++ ++static u32 et_virt_get_link(struct net_device *dev) ++{ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ PSEUDO_ADAPTER *pseudo = netdev_priv(dev); ++#else ++ PSEUDO_ADAPTER *pseudo = dev->priv; ++#endif ++ return mii_link_ok(&pseudo->mii_info); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ++static int et_virt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) ++{ ++ PSEUDO_ADAPTER *pseudo = dev->priv; ++ int rc = mii_ethtool_sset(&pseudo->mii_info, cmd); ++ return rc; ++} ++#endif ++ ++static int et_virt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) ++{ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ PSEUDO_ADAPTER *pseudo = netdev_priv(dev); ++#else ++ PSEUDO_ADAPTER *pseudo = dev->priv; ++#endif ++ mii_ethtool_gset(&pseudo->mii_info, cmd); ++ return 0; ++} ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ++static u32 et_virt_get_msglevel(struct net_device *dev) ++{ ++ return 0; ++} ++ ++static void et_virt_set_msglevel(struct net_device *dev, u32 datum) ++{ ++ return; ++} ++ ++static void et_virt_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) ++{ ++// PSEUDO_ADAPTER *pseudo = dev->priv; ++ data[0] = 0;//np->xstats.early_rx; ++ data[1] = 0;//np->xstats.tx_buf_mapped; ++ data[2] = 0;//np->xstats.tx_timeouts; ++ data[3] = 0;//np->xstats.rx_lost_in_ring; ++} ++ ++/* for virtual interface dedicated */ ++#define RA_VIRT_NUM_STATS 4 ++static struct { ++ const char str[ETH_GSTRING_LEN]; ++} ethtool_stats_keys_2[] = { ++ { "statistic1" }, ++ { "statistic2" }, ++ { "statistic3" }, ++ { "statistic4" }, ++}; ++ ++static int et_virt_get_stats_count(struct net_device *dev) ++{ ++ return RA_VIRT_NUM_STATS; ++} ++ ++static void et_virt_get_strings(struct net_device *dev, u32 stringset, u8 *data) ++{ ++ memcpy(data, ethtool_stats_keys_2, sizeof(ethtool_stats_keys_2)); ++} ++#endif ++ ++struct ethtool_ops ra_virt_ethtool_ops = { ++ .get_settings = et_virt_get_settings, ++ .get_link = et_virt_get_link, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ++ .get_drvinfo = et_virt_get_drvinfo, ++ .set_settings = et_virt_set_settings, ++ .get_pauseparam = et_virt_get_pauseparam, ++ .set_pauseparam = et_virt_set_pauseparam, ++ .get_rx_csum = et_virt_get_rx_csum, ++ .set_rx_csum = et_virt_set_rx_csum, ++ .get_tx_csum = et_virt_get_tx_csum, ++ .set_tx_csum = et_virt_set_tx_csum, ++ .nway_reset = et_virt_nway_reset, ++ .get_msglevel = et_virt_get_msglevel, ++ .set_msglevel = et_virt_set_msglevel, ++ .get_strings = et_virt_get_strings, ++ .get_stats_count = et_virt_get_stats_count, ++ .get_ethtool_stats = et_virt_get_ethtool_stats, ++/* .get_regs_len = et_virt_get_regs_len, ++ .get_regs = et_virt_get_regs, ++*/ ++#endif ++}; ++ ++int mdio_virt_read(struct net_device *dev, int phy_id, int location) ++{ ++ unsigned int result; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ PSEUDO_ADAPTER *pseudo = netdev_priv(dev); ++#else ++ PSEUDO_ADAPTER *pseudo = dev->priv; ++#endif ++ mii_mgr_read( (unsigned int) pseudo->mii_info.phy_id, (unsigned int)location, &result); ++// printk("%s mii.o query= phy_id:%d, address:%d retval:%d\n", dev->name, phy_id, location, result); ++ return (int)result; ++} ++ ++void mdio_virt_write(struct net_device *dev, int phy_id, int location, int value) ++{ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ PSEUDO_ADAPTER *pseudo = netdev_priv(dev); ++#else ++ PSEUDO_ADAPTER *pseudo = dev->priv; ++#endif ++// printk("mii.o write= phy_id:%d, address:%d value:%d\n", phy_id, location, value); ++ mii_mgr_write( (unsigned int) pseudo->mii_info.phy_id, (unsigned int)location, (unsigned int)value); ++ return; ++} ++ ++#endif /* CONFIG_PSEUDO_SUPPORT */ ++ ++ +diff --git a/drivers/net/ethernet/raeth/ra_ethtool.h b/drivers/net/ethernet/raeth/ra_ethtool.h +new file mode 100644 +index 0000000..d64a1ab +--- /dev/null ++++ b/drivers/net/ethernet/raeth/ra_ethtool.h +@@ -0,0 +1,13 @@ ++#ifndef RA_ETHTOOL_H ++#define RA_ETHTOOL_H ++ ++/* ethtool related */ ++unsigned char get_current_phy_address(void); ++int mdio_read(struct net_device *dev, int phy_id, int location); ++void mdio_write(struct net_device *dev, int phy_id, int location, int value); ++ ++/* for pseudo interface */ ++int mdio_virt_read(struct net_device *dev, int phy_id, int location); ++void mdio_virt_write(struct net_device *dev, int phy_id, int location, int value); ++ ++#endif +diff --git a/drivers/net/ethernet/raeth/ra_ioctl.h b/drivers/net/ethernet/raeth/ra_ioctl.h +new file mode 100644 +index 0000000..83b806a +--- /dev/null ++++ b/drivers/net/ethernet/raeth/ra_ioctl.h +@@ -0,0 +1,102 @@ ++#ifndef _RAETH_IOCTL_H ++#define _RAETH_IOCTL_H ++ ++/* ioctl commands */ ++#define RAETH_ESW_REG_READ 0x89F1 ++#define RAETH_ESW_REG_WRITE 0x89F2 ++#define RAETH_MII_READ 0x89F3 ++#define RAETH_MII_WRITE 0x89F4 ++#define RAETH_ESW_INGRESS_RATE 0x89F5 ++#define RAETH_ESW_EGRESS_RATE 0x89F6 ++#define RAETH_ESW_PHY_DUMP 0x89F7 ++#define RAETH_QDMA_REG_READ 0x89F8 ++#define RAETH_QDMA_REG_WRITE 0x89F9 ++#define RAETH_QDMA_QUEUE_MAPPING 0x89FA ++#define RAETH_QDMA_READ_CPU_CLK 0x89FB ++#define RAETH_MII_READ_CL45 0x89FC ++#define RAETH_MII_WRITE_CL45 0x89FD ++#if defined(CONFIG_HW_SFQ) ++#define RAETH_QDMA_SFQ_WEB_ENABLE 0x89FE ++#endif ++ ++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || \ ++ defined (CONFIG_ARCH_MT7623) ++ ++#define REG_ESW_WT_MAC_MFC 0x10 ++#define REG_ESW_ISC 0x18 ++#define REG_ESW_WT_MAC_ATA1 0x74 ++#define REG_ESW_WT_MAC_ATA2 0x78 ++#define REG_ESW_WT_MAC_ATWD 0x7C ++#define REG_ESW_WT_MAC_ATC 0x80 ++ ++#define REG_ESW_TABLE_TSRA1 0x84 ++#define REG_ESW_TABLE_TSRA2 0x88 ++#define REG_ESW_TABLE_ATRD 0x8C ++ ++ ++#define REG_ESW_VLAN_VTCR 0x90 ++#define REG_ESW_VLAN_VAWD1 0x94 ++#define REG_ESW_VLAN_VAWD2 0x98 ++ ++ ++#define REG_ESW_VLAN_ID_BASE 0x100 ++ ++//#define REG_ESW_VLAN_ID_BASE 0x50 ++#define REG_ESW_VLAN_MEMB_BASE 0x70 ++#define REG_ESW_TABLE_SEARCH 0x24 ++#define REG_ESW_TABLE_STATUS0 0x28 ++#define REG_ESW_TABLE_STATUS1 0x2C ++#define REG_ESW_TABLE_STATUS2 0x30 ++#define REG_ESW_WT_MAC_AD0 0x34 ++#define REG_ESW_WT_MAC_AD1 0x38 ++#define REG_ESW_WT_MAC_AD2 0x3C ++ ++#else ++/* rt3052 embedded ethernet switch registers */ ++#define REG_ESW_VLAN_ID_BASE 0x50 ++#define REG_ESW_VLAN_MEMB_BASE 0x70 ++#define REG_ESW_TABLE_SEARCH 0x24 ++#define REG_ESW_TABLE_STATUS0 0x28 ++#define REG_ESW_TABLE_STATUS1 0x2C ++#define REG_ESW_TABLE_STATUS2 0x30 ++#define REG_ESW_WT_MAC_AD0 0x34 ++#define REG_ESW_WT_MAC_AD1 0x38 ++#define REG_ESW_WT_MAC_AD2 0x3C ++#endif ++ ++ ++#if defined(CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++#define REG_ESW_MAX 0x16C ++#elif defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) ++#define REG_ESW_MAX 0x7FFFF ++#else //RT305x, RT3350 ++#define REG_ESW_MAX 0xFC ++#endif ++#define REG_HQOS_MAX 0x3FFF ++ ++ ++typedef struct rt3052_esw_reg { ++ unsigned int off; ++ unsigned int val; ++} esw_reg; ++ ++typedef struct ralink_mii_ioctl_data { ++ __u32 phy_id; ++ __u32 reg_num; ++ __u32 val_in; ++ __u32 val_out; ++ __u32 port_num; ++ __u32 dev_addr; ++ __u32 reg_addr; ++} ra_mii_ioctl_data; ++ ++typedef struct rt335x_esw_reg { ++ unsigned int on_off; ++ unsigned int port; ++ unsigned int bw;/*Mbps*/ ++} esw_rate; ++ ++ ++#endif +diff --git a/drivers/net/ethernet/raeth/ra_mac.c b/drivers/net/ethernet/raeth/ra_mac.c +new file mode 100644 +index 0000000..e8e978d +--- /dev/null ++++ b/drivers/net/ethernet/raeth/ra_mac.c +@@ -0,0 +1,2645 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,4) ++#include ++#include ++#endif ++#include ++#include ++#include ++#include ++ ++#include /* for cp0 reg access, added by bobtseng */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++ ++#if defined(CONFIG_RAETH_LRO) ++#include ++#endif ++ ++#include "ra2882ethreg.h" ++#include "raether.h" ++#include "ra_mac.h" ++#include "ra_ethtool.h" ++#if defined(CONFIG_RAETH_PDMA_DVT) ++#include "dvt/raether_pdma_dvt.h" ++#endif //#if defined(CONFIG_RAETH_PDMA_DVT) ++ ++extern struct net_device *dev_raether; ++ ++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) ++extern unsigned short p0_rx_good_cnt; ++extern unsigned short p0_tx_good_cnt; ++extern unsigned short p1_rx_good_cnt; ++extern unsigned short p1_tx_good_cnt; ++extern unsigned short p2_rx_good_cnt; ++extern unsigned short p2_tx_good_cnt; ++extern unsigned short p3_rx_good_cnt; ++extern unsigned short p3_tx_good_cnt; ++extern unsigned short p4_rx_good_cnt; ++extern unsigned short p4_tx_good_cnt; ++extern unsigned short p5_rx_good_cnt; ++extern unsigned short p5_tx_good_cnt; ++extern unsigned short p6_rx_good_cnt; ++extern unsigned short p6_tx_good_cnt; ++ ++extern unsigned short p0_rx_byte_cnt; ++extern unsigned short p1_rx_byte_cnt; ++extern unsigned short p2_rx_byte_cnt; ++extern unsigned short p3_rx_byte_cnt; ++extern unsigned short p4_rx_byte_cnt; ++extern unsigned short p5_rx_byte_cnt; ++extern unsigned short p6_rx_byte_cnt; ++extern unsigned short p0_tx_byte_cnt; ++extern unsigned short p1_tx_byte_cnt; ++extern unsigned short p2_tx_byte_cnt; ++extern unsigned short p3_tx_byte_cnt; ++extern unsigned short p4_tx_byte_cnt; ++extern unsigned short p5_tx_byte_cnt; ++extern unsigned short p6_tx_byte_cnt; ++ ++#if defined(CONFIG_RALINK_MT7620) ++extern unsigned short p7_rx_good_cnt; ++extern unsigned short p7_tx_good_cnt; ++extern unsigned short p7_rx_byte_cnt; ++extern unsigned short p7_tx_byte_cnt; ++#endif ++#endif ++ ++ ++ ++#if defined(CONFIG_RAETH_TSO) ++int txd_cnt[MAX_SKB_FRAGS/2 + 1]; ++int tso_cnt[16]; ++#endif ++ ++#if defined(CONFIG_RAETH_LRO) ++#define MAX_AGGR 64 ++#define MAX_DESC 8 ++int lro_stats_cnt[MAX_AGGR + 1]; ++int lro_flush_cnt[MAX_AGGR + 1]; ++int lro_len_cnt1[16]; ++//int lro_len_cnt2[16]; ++int aggregated[MAX_DESC]; ++int lro_aggregated; ++int lro_flushed; ++int lro_nodesc; ++int force_flush; ++int tot_called1; ++int tot_called2; ++#endif ++ ++#if defined(CONFIG_RAETH_HW_LRO) ++#define HW_LRO_RING_NUM 3 ++#define MAX_HW_LRO_AGGR 64 ++unsigned int hw_lro_agg_num_cnt[HW_LRO_RING_NUM][MAX_HW_LRO_AGGR + 1]; ++unsigned int hw_lro_agg_size_cnt[HW_LRO_RING_NUM][16]; ++unsigned int hw_lro_tot_agg_cnt[HW_LRO_RING_NUM]; ++unsigned int hw_lro_tot_flush_cnt[HW_LRO_RING_NUM]; ++#if defined(CONFIG_RAETH_HW_LRO_REASON_DBG) ++unsigned int hw_lro_agg_flush_cnt[HW_LRO_RING_NUM]; ++unsigned int hw_lro_age_flush_cnt[HW_LRO_RING_NUM]; ++unsigned int hw_lro_seq_flush_cnt[HW_LRO_RING_NUM]; ++unsigned int hw_lro_timestamp_flush_cnt[HW_LRO_RING_NUM]; ++unsigned int hw_lro_norule_flush_cnt[HW_LRO_RING_NUM]; ++#endif /* CONFIG_RAETH_HW_LRO_REASON_DBG */ ++#endif /* CONFIG_RAETH_HW_LRO */ ++ ++#if defined(CONFIG_RAETH_QDMA) ++extern unsigned int M2Q_table[64]; ++extern struct QDMA_txdesc *free_head; ++#endif ++#if defined (CONFIG_ARCH_MT7623) ++extern struct SFQ_table *sfq0; ++extern struct SFQ_table *sfq1; ++extern struct SFQ_table *sfq2; ++extern struct SFQ_table *sfq3; ++#endif ++ ++#if defined(CONFIG_USER_SNMPD) ++ ++static int ra_snmp_seq_show(struct seq_file *seq, void *v) ++{ ++#if !defined(CONFIG_RALINK_RT5350) && !defined(CONFIG_RALINK_MT7620) && !defined (CONFIG_RALINK_MT7628) ++ ++ seq_printf(seq, "rx counters: %x %x %x %x %x %x %x\n", sysRegRead(GDMA_RX_GBCNT0), sysRegRead(GDMA_RX_GPCNT0),sysRegRead(GDMA_RX_OERCNT0), sysRegRead(GDMA_RX_FERCNT0), sysRegRead(GDMA_RX_SERCNT0), sysRegRead(GDMA_RX_LERCNT0), sysRegRead(GDMA_RX_CERCNT0)); ++ ++ seq_printf(seq, "fc config: %x %x %x %x\n", sysRegRead(CDMA_FC_CFG), sysRegRead(GDMA1_FC_CFG), PDMA_FC_CFG, sysRegRead(PDMA_FC_CFG)); ++ ++ seq_printf(seq, "scheduler: %x %x %x\n", sysRegRead(GDMA1_SCH_CFG), sysRegRead(GDMA2_SCH_CFG), sysRegRead(PDMA_SCH_CFG)); ++ ++#endif ++ seq_printf(seq, "ports: %x %x %x %x %x %x\n", sysRegRead(PORT0_PKCOUNT), sysRegRead(PORT1_PKCOUNT), sysRegRead(PORT2_PKCOUNT), sysRegRead(PORT3_PKCOUNT), sysRegRead(PORT4_PKCOUNT), sysRegRead(PORT5_PKCOUNT)); ++ ++ return 0; ++} ++ ++static int ra_snmp_seq_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, ra_snmp_seq_show, NULL); ++} ++ ++static const struct file_operations ra_snmp_seq_fops = { ++ .owner = THIS_MODULE, ++ .open = ra_snmp_seq_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release ++}; ++#endif ++ ++ ++#if defined (CONFIG_GIGAPHY) || defined (CONFIG_100PHY) || \ ++ defined (CONFIG_P5_MAC_TO_PHY_MODE) || defined (CONFIG_RAETH_GMAC2) ++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || \ ++ defined (CONFIG_ARCH_MT7623) ++void enable_auto_negotiate(int unused) ++{ ++ u32 regValue; ++#if !defined (CONFIG_RALINK_MT7621) && !defined (CONFIG_ARCH_MT7623) ++ u32 addr = CONFIG_MAC_TO_GIGAPHY_MODE_ADDR; ++#endif ++ ++#if defined (CONFIG_RALINK_MT7621) ++ //enable MDIO mode all the time ++ regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60)); ++ regValue &= ~(0x3 << 12); ++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue; ++#endif ++ ++ /* FIXME: we don't know how to deal with PHY end addr */ ++ regValue = sysRegRead(ESW_PHY_POLLING); ++ regValue |= (1<<31); ++ regValue &= ~(0x1f); ++ regValue &= ~(0x1f<<8); ++#if defined (CONFIG_RALINK_MT7620) ++ regValue |= ((addr-1) << 0);//setup PHY address for auto polling (Start Addr). ++ regValue |= (addr << 8);// setup PHY address for auto polling (End Addr). ++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN)|| defined (CONFIG_GE_RGMII_INTERNAL_P4_AN) || defined (CONFIG_GE2_RGMII_AN) ++ regValue |= ((CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2-1)&0x1f << 0);//setup PHY address for auto polling (Start Addr). ++ regValue |= (CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2 << 8);// setup PHY address for auto polling (End Addr). ++#else ++ regValue |= (CONFIG_MAC_TO_GIGAPHY_MODE_ADDR << 0);//setup PHY address for auto polling (Start Addr). ++ regValue |= (CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2 << 8);// setup PHY address for auto polling (End Addr). ++#endif ++#else ++ regValue |= (addr << 0);// setup PHY address for auto polling (start Addr). ++ regValue |= (addr << 8);// setup PHY address for auto polling (End Addr). ++#endif ++ ++ /*kurtis: AN is strange*/ ++ sysRegWrite(ESW_PHY_POLLING, regValue); ++ ++#if defined (CONFIG_P4_MAC_TO_PHY_MODE) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x56330; ++#endif ++#if defined (CONFIG_P5_MAC_TO_PHY_MODE) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x56330; ++#endif ++} ++#elif defined (CONFIG_RALINK_RT2880) || defined(CONFIG_RALINK_RT3883) || \ ++ defined (CONFIG_RALINK_RT3052) || defined(CONFIG_RALINK_RT3352) ++ ++void enable_auto_negotiate(int ge) ++{ ++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) ++ u32 regValue = sysRegRead(0xb01100C8); ++#else ++ u32 regValue; ++ regValue = (ge == 2)? sysRegRead(MDIO_CFG2) : sysRegRead(MDIO_CFG); ++#endif ++ ++ regValue &= 0xe0ff7fff; // clear auto polling related field: ++ // (MD_PHY1ADDR & GP1_FRC_EN). ++ regValue |= 0x20000000; // force to enable MDC/MDIO auto polling. ++ ++#if defined (CONFIG_GE2_RGMII_AN) || defined (CONFIG_GE2_MII_AN) ++ if(ge==2) { ++ regValue |= (CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2 << 24); // setup PHY address for auto polling. ++ } ++#endif ++#if defined (CONFIG_GE1_RGMII_AN) || defined (CONFIG_GE1_MII_AN) || defined (CONFIG_P5_MAC_TO_PHY_MODE) ++ if(ge==1) { ++ regValue |= (CONFIG_MAC_TO_GIGAPHY_MODE_ADDR << 24); // setup PHY address for auto polling. ++ } ++#endif ++ ++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) ++ sysRegWrite(0xb01100C8, regValue); ++#else ++ if (ge == 2) ++ sysRegWrite(MDIO_CFG2, regValue); ++ else ++ sysRegWrite(MDIO_CFG, regValue); ++#endif ++} ++#endif ++#endif ++void ra2880stop(END_DEVICE *ei_local) ++{ ++ unsigned int regValue; ++ printk("ra2880stop()..."); ++ ++ regValue = sysRegRead(DMA_GLO_CFG); ++ regValue &= ~(TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN); ++ sysRegWrite(DMA_GLO_CFG, regValue); ++ ++ printk("Done\n"); ++ // printk("Done0x%x...\n", readreg(DMA_GLO_CFG)); ++} ++ ++void ei_irq_clear(void) ++{ ++ sysRegWrite(FE_INT_STATUS, 0xFFFFFFFF); ++} ++ ++void rt2880_gmac_hard_reset(void) ++{ ++#if !defined (CONFIG_RALINK_RT6855A) ++ //FIXME ++ sysRegWrite(RSTCTRL, RALINK_FE_RST); ++ sysRegWrite(RSTCTRL, 0); ++#endif ++} ++ ++void ra2880EnableInterrupt() ++{ ++ unsigned int regValue = sysRegRead(FE_INT_ENABLE); ++ RAETH_PRINT("FE_INT_ENABLE -- : 0x%08x\n", regValue); ++// regValue |= (RX_DONE_INT0 | TX_DONE_INT0); ++ ++ sysRegWrite(FE_INT_ENABLE, regValue); ++} ++ ++void ra2880MacAddressSet(unsigned char p[6]) ++{ ++ unsigned long regValue; ++ ++ regValue = (p[0] << 8) | (p[1]); ++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++ sysRegWrite(SDM_MAC_ADRH, regValue); ++ printk("GMAC1_MAC_ADRH -- : 0x%08x\n", sysRegRead(SDM_MAC_ADRH)); ++#elif defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) ++ sysRegWrite(GDMA1_MAC_ADRH, regValue); ++ printk("GMAC1_MAC_ADRH -- : 0x%08x\n", sysRegRead(GDMA1_MAC_ADRH)); ++ ++ /* To keep the consistence between RT6855 and RT62806, GSW should keep the register. */ ++ sysRegWrite(SMACCR1, regValue); ++ printk("SMACCR1 -- : 0x%08x\n", sysRegRead(SMACCR1)); ++#elif defined (CONFIG_RALINK_MT7620) ++ sysRegWrite(SMACCR1, regValue); ++ printk("SMACCR1 -- : 0x%08x\n", sysRegRead(SMACCR1)); ++#else ++ sysRegWrite(GDMA1_MAC_ADRH, regValue); ++ printk("GMAC1_MAC_ADRH -- : 0x%08x\n", sysRegRead(GDMA1_MAC_ADRH)); ++#endif ++ ++ regValue = (p[2] << 24) | (p[3] <<16) | (p[4] << 8) | p[5]; ++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++ sysRegWrite(SDM_MAC_ADRL, regValue); ++ printk("GMAC1_MAC_ADRL -- : 0x%08x\n", sysRegRead(SDM_MAC_ADRL)); ++#elif defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) ++ sysRegWrite(GDMA1_MAC_ADRL, regValue); ++ printk("GMAC1_MAC_ADRL -- : 0x%08x\n", sysRegRead(GDMA1_MAC_ADRL)); ++ ++ /* To keep the consistence between RT6855 and RT62806, GSW should keep the register. */ ++ sysRegWrite(SMACCR0, regValue); ++ printk("SMACCR0 -- : 0x%08x\n", sysRegRead(SMACCR0)); ++#elif defined (CONFIG_RALINK_MT7620) ++ sysRegWrite(SMACCR0, regValue); ++ printk("SMACCR0 -- : 0x%08x\n", sysRegRead(SMACCR0)); ++#else ++ sysRegWrite(GDMA1_MAC_ADRL, regValue); ++ printk("GMAC1_MAC_ADRL -- : 0x%08x\n", sysRegRead(GDMA1_MAC_ADRL)); ++#endif ++ ++ return; ++} ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++void ra2880Mac2AddressSet(unsigned char p[6]) ++{ ++ unsigned long regValue; ++ ++ regValue = (p[0] << 8) | (p[1]); ++ sysRegWrite(GDMA2_MAC_ADRH, regValue); ++ ++ regValue = (p[2] << 24) | (p[3] <<16) | (p[4] << 8) | p[5]; ++ sysRegWrite(GDMA2_MAC_ADRL, regValue); ++ ++ printk("GDMA2_MAC_ADRH -- : 0x%08x\n", sysRegRead(GDMA2_MAC_ADRH)); ++ printk("GDMA2_MAC_ADRL -- : 0x%08x\n", sysRegRead(GDMA2_MAC_ADRL)); ++ return; ++} ++#endif ++ ++/** ++ * hard_init - Called by raeth_probe to inititialize network device ++ * @dev: device pointer ++ * ++ * ethdev_init initilize dev->priv and set to END_DEVICE structure ++ * ++ */ ++void ethtool_init(struct net_device *dev) ++{ ++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/ ++ END_DEVICE *ei_local = netdev_priv(dev); ++ ++ // init mii structure ++ ei_local->mii_info.dev = dev; ++ ei_local->mii_info.mdio_read = mdio_read; ++ ei_local->mii_info.mdio_write = mdio_write; ++ ei_local->mii_info.phy_id_mask = 0x1f; ++ ei_local->mii_info.reg_num_mask = 0x1f; ++ ei_local->mii_info.supports_gmii = mii_check_gmii_support(&ei_local->mii_info); ++ // TODO: phy_id: 0~4 ++ ei_local->mii_info.phy_id = 1; ++#endif ++ return; ++} ++ ++/* ++ * Routine Name : get_idx(mode, index) ++ * Description: calculate ring usage for tx/rx rings ++ * Mode 1 : Tx Ring ++ * Mode 2 : Rx Ring ++ */ ++int get_ring_usage(int mode, int i) ++{ ++ unsigned long tx_ctx_idx, tx_dtx_idx, tx_usage; ++ unsigned long rx_calc_idx, rx_drx_idx, rx_usage; ++ ++ struct PDMA_rxdesc* rxring; ++ struct PDMA_txdesc* txring; ++ ++ END_DEVICE *ei_local = netdev_priv(dev_raether); ++ ++ ++ if (mode == 2 ) { ++ /* cpu point to the next descriptor of rx dma ring */ ++ rx_calc_idx = *(unsigned long*)RX_CALC_IDX0; ++ rx_drx_idx = *(unsigned long*)RX_DRX_IDX0; ++ rxring = (struct PDMA_rxdesc*)RX_BASE_PTR0; ++ ++ rx_usage = (rx_drx_idx - rx_calc_idx -1 + NUM_RX_DESC) % NUM_RX_DESC; ++ if ( rx_calc_idx == rx_drx_idx ) { ++ if ( rxring[rx_drx_idx].rxd_info2.DDONE_bit == 1) ++ tx_usage = NUM_RX_DESC; ++ else ++ tx_usage = 0; ++ } ++ return rx_usage; ++ } ++ ++ ++ switch (i) { ++ case 0: ++ tx_ctx_idx = *(unsigned long*)TX_CTX_IDX0; ++ tx_dtx_idx = *(unsigned long*)TX_DTX_IDX0; ++ txring = ei_local->tx_ring0; ++ break; ++#if defined(CONFIG_RAETH_QOS) ++ case 1: ++ tx_ctx_idx = *(unsigned long*)TX_CTX_IDX1; ++ tx_dtx_idx = *(unsigned long*)TX_DTX_IDX1; ++ txring = ei_local->tx_ring1; ++ break; ++ case 2: ++ tx_ctx_idx = *(unsigned long*)TX_CTX_IDX2; ++ tx_dtx_idx = *(unsigned long*)TX_DTX_IDX2; ++ txring = ei_local->tx_ring2; ++ break; ++ case 3: ++ tx_ctx_idx = *(unsigned long*)TX_CTX_IDX3; ++ tx_dtx_idx = *(unsigned long*)TX_DTX_IDX3; ++ txring = ei_local->tx_ring3; ++ break; ++#endif ++ default: ++ printk("get_tx_idx failed %d %d\n", mode, i); ++ return 0; ++ }; ++ ++ tx_usage = (tx_ctx_idx - tx_dtx_idx + NUM_TX_DESC) % NUM_TX_DESC; ++ if ( tx_ctx_idx == tx_dtx_idx ) { ++ if ( txring[tx_ctx_idx].txd_info2.DDONE_bit == 1) ++ tx_usage = 0; ++ else ++ tx_usage = NUM_TX_DESC; ++ } ++ return tx_usage; ++ ++} ++ ++#if defined(CONFIG_RAETH_QOS) ++void dump_qos(struct seq_file *s) ++{ ++ int usage; ++ int i; ++ ++ seq_printf(s, "\n-----Raeth QOS -----\n\n"); ++ ++ for ( i = 0; i < 4; i++) { ++ usage = get_ring_usage(1,i); ++ seq_printf(s, "Tx Ring%d Usage : %d/%d\n", i, usage, NUM_TX_DESC); ++ } ++ ++ usage = get_ring_usage(2,0); ++ seq_printf(s, "RX Usage : %d/%d\n\n", usage, NUM_RX_DESC); ++#if defined (CONFIG_RALINK_MT7620) ++ seq_printf(s, "PSE_FQFC_CFG(0x%08x) : 0x%08x\n", PSE_FQFC_CFG, sysRegRead(PSE_FQFC_CFG)); ++ seq_printf(s, "PSE_IQ_CFG(0x%08x) : 0x%08x\n", PSE_IQ_CFG, sysRegRead(PSE_IQ_CFG)); ++ seq_printf(s, "PSE_QUE_STA(0x%08x) : 0x%08x\n", PSE_QUE_STA, sysRegRead(PSE_QUE_STA)); ++#elif defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++ ++#else ++ seq_printf(s, "GDMA1_FC_CFG(0x%08x) : 0x%08x\n", GDMA1_FC_CFG, sysRegRead(GDMA1_FC_CFG)); ++ seq_printf(s, "GDMA2_FC_CFG(0x%08x) : 0x%08x\n", GDMA2_FC_CFG, sysRegRead(GDMA2_FC_CFG)); ++ seq_printf(s, "PDMA_FC_CFG(0x%08x) : 0x%08x\n", PDMA_FC_CFG, sysRegRead(PDMA_FC_CFG)); ++ seq_printf(s, "PSE_FQ_CFG(0x%08x) : 0x%08x\n", PSE_FQ_CFG, sysRegRead(PSE_FQ_CFG)); ++#endif ++ seq_printf(s, "\n\nTX_CTX_IDX0 : 0x%08x\n", sysRegRead(TX_CTX_IDX0)); ++ seq_printf(s, "TX_DTX_IDX0 : 0x%08x\n", sysRegRead(TX_DTX_IDX0)); ++ seq_printf(s, "TX_CTX_IDX1 : 0x%08x\n", sysRegRead(TX_CTX_IDX1)); ++ seq_printf(s, "TX_DTX_IDX1 : 0x%08x\n", sysRegRead(TX_DTX_IDX1)); ++ seq_printf(s, "TX_CTX_IDX2 : 0x%08x\n", sysRegRead(TX_CTX_IDX2)); ++ seq_printf(s, "TX_DTX_IDX2 : 0x%08x\n", sysRegRead(TX_DTX_IDX2)); ++ seq_printf(s, "TX_CTX_IDX3 : 0x%08x\n", sysRegRead(TX_CTX_IDX3)); ++ seq_printf(s, "TX_DTX_IDX3 : 0x%08x\n", sysRegRead(TX_DTX_IDX3)); ++ seq_printf(s, "RX_CALC_IDX0 : 0x%08x\n", sysRegRead(RX_CALC_IDX0)); ++ seq_printf(s, "RX_DRX_IDX0 : 0x%08x\n", sysRegRead(RX_DRX_IDX0)); ++ ++ seq_printf(s, "\n------------------------------\n\n"); ++} ++#endif ++ ++void dump_reg(struct seq_file *s) ++{ ++ int fe_int_enable; ++ int rx_usage; ++ int dly_int_cfg; ++ int rx_base_ptr0; ++ int rx_max_cnt0; ++ int rx_calc_idx0; ++ int rx_drx_idx0; ++#if !defined (CONFIG_RAETH_QDMA) ++ int tx_usage; ++ int tx_base_ptr[4]; ++ int tx_max_cnt[4]; ++ int tx_ctx_idx[4]; ++ int tx_dtx_idx[4]; ++ int i; ++#endif ++ ++ fe_int_enable = sysRegRead(FE_INT_ENABLE); ++ rx_usage = get_ring_usage(2,0); ++ ++ dly_int_cfg = sysRegRead(DLY_INT_CFG); ++ ++#if !defined (CONFIG_RAETH_QDMA) ++ tx_usage = get_ring_usage(1,0); ++ ++ tx_base_ptr[0] = sysRegRead(TX_BASE_PTR0); ++ tx_max_cnt[0] = sysRegRead(TX_MAX_CNT0); ++ tx_ctx_idx[0] = sysRegRead(TX_CTX_IDX0); ++ tx_dtx_idx[0] = sysRegRead(TX_DTX_IDX0); ++ ++ tx_base_ptr[1] = sysRegRead(TX_BASE_PTR1); ++ tx_max_cnt[1] = sysRegRead(TX_MAX_CNT1); ++ tx_ctx_idx[1] = sysRegRead(TX_CTX_IDX1); ++ tx_dtx_idx[1] = sysRegRead(TX_DTX_IDX1); ++ ++ tx_base_ptr[2] = sysRegRead(TX_BASE_PTR2); ++ tx_max_cnt[2] = sysRegRead(TX_MAX_CNT2); ++ tx_ctx_idx[2] = sysRegRead(TX_CTX_IDX2); ++ tx_dtx_idx[2] = sysRegRead(TX_DTX_IDX2); ++ ++ tx_base_ptr[3] = sysRegRead(TX_BASE_PTR3); ++ tx_max_cnt[3] = sysRegRead(TX_MAX_CNT3); ++ tx_ctx_idx[3] = sysRegRead(TX_CTX_IDX3); ++ tx_dtx_idx[3] = sysRegRead(TX_DTX_IDX3); ++#endif ++ ++ rx_base_ptr0 = sysRegRead(RX_BASE_PTR0); ++ rx_max_cnt0 = sysRegRead(RX_MAX_CNT0); ++ rx_calc_idx0 = sysRegRead(RX_CALC_IDX0); ++ rx_drx_idx0 = sysRegRead(RX_DRX_IDX0); ++ ++ seq_printf(s, "\n\nFE_INT_ENABLE : 0x%08x\n", fe_int_enable); ++#if !defined (CONFIG_RAETH_QDMA) ++ seq_printf(s, "TxRing PktCnt: %d/%d\n", tx_usage, NUM_TX_DESC); ++#endif ++ seq_printf(s, "RxRing PktCnt: %d/%d\n\n", rx_usage, NUM_RX_DESC); ++ seq_printf(s, "DLY_INT_CFG : 0x%08x\n", dly_int_cfg); ++ ++#if !defined (CONFIG_RAETH_QDMA) ++ for(i=0;i<4;i++) { ++ seq_printf(s, "TX_BASE_PTR%d : 0x%08x\n", i, tx_base_ptr[i]); ++ seq_printf(s, "TX_MAX_CNT%d : 0x%08x\n", i, tx_max_cnt[i]); ++ seq_printf(s, "TX_CTX_IDX%d : 0x%08x\n", i, tx_ctx_idx[i]); ++ seq_printf(s, "TX_DTX_IDX%d : 0x%08x\n", i, tx_dtx_idx[i]); ++ } ++#endif ++ ++ seq_printf(s, "RX_BASE_PTR0 : 0x%08x\n", rx_base_ptr0); ++ seq_printf(s, "RX_MAX_CNT0 : 0x%08x\n", rx_max_cnt0); ++ seq_printf(s, "RX_CALC_IDX0 : 0x%08x\n", rx_calc_idx0); ++ seq_printf(s, "RX_DRX_IDX0 : 0x%08x\n", rx_drx_idx0); ++ ++#if defined (CONFIG_ETHTOOL) && defined (CONFIG_RAETH_ROUTER) ++ seq_printf(s, "The current PHY address selected by ethtool is %d\n", get_current_phy_address()); ++#endif ++ ++#if defined (CONFIG_RALINK_RT2883) || defined(CONFIG_RALINK_RT3883) ++ seq_printf(s, "GDMA_RX_FCCNT1(0x%08x) : 0x%08x\n\n", GDMA_RX_FCCNT1, sysRegRead(GDMA_RX_FCCNT1)); ++#endif ++} ++ ++#if 0 ++void dump_cp0(void) ++{ ++ printk("CP0 Register dump --\n"); ++ printk("CP0_INDEX\t: 0x%08x\n", read_32bit_cp0_register(CP0_INDEX)); ++ printk("CP0_RANDOM\t: 0x%08x\n", read_32bit_cp0_register(CP0_RANDOM)); ++ printk("CP0_ENTRYLO0\t: 0x%08x\n", read_32bit_cp0_register(CP0_ENTRYLO0)); ++ printk("CP0_ENTRYLO1\t: 0x%08x\n", read_32bit_cp0_register(CP0_ENTRYLO1)); ++ printk("CP0_CONF\t: 0x%08x\n", read_32bit_cp0_register(CP0_CONF)); ++ printk("CP0_CONTEXT\t: 0x%08x\n", read_32bit_cp0_register(CP0_CONTEXT)); ++ printk("CP0_PAGEMASK\t: 0x%08x\n", read_32bit_cp0_register(CP0_PAGEMASK)); ++ printk("CP0_WIRED\t: 0x%08x\n", read_32bit_cp0_register(CP0_WIRED)); ++ printk("CP0_INFO\t: 0x%08x\n", read_32bit_cp0_register(CP0_INFO)); ++ printk("CP0_BADVADDR\t: 0x%08x\n", read_32bit_cp0_register(CP0_BADVADDR)); ++ printk("CP0_COUNT\t: 0x%08x\n", read_32bit_cp0_register(CP0_COUNT)); ++ printk("CP0_ENTRYHI\t: 0x%08x\n", read_32bit_cp0_register(CP0_ENTRYHI)); ++ printk("CP0_COMPARE\t: 0x%08x\n", read_32bit_cp0_register(CP0_COMPARE)); ++ printk("CP0_STATUS\t: 0x%08x\n", read_32bit_cp0_register(CP0_STATUS)); ++ printk("CP0_CAUSE\t: 0x%08x\n", read_32bit_cp0_register(CP0_CAUSE)); ++ printk("CP0_EPC\t: 0x%08x\n", read_32bit_cp0_register(CP0_EPC)); ++ printk("CP0_PRID\t: 0x%08x\n", read_32bit_cp0_register(CP0_PRID)); ++ printk("CP0_CONFIG\t: 0x%08x\n", read_32bit_cp0_register(CP0_CONFIG)); ++ printk("CP0_LLADDR\t: 0x%08x\n", read_32bit_cp0_register(CP0_LLADDR)); ++ printk("CP0_WATCHLO\t: 0x%08x\n", read_32bit_cp0_register(CP0_WATCHLO)); ++ printk("CP0_WATCHHI\t: 0x%08x\n", read_32bit_cp0_register(CP0_WATCHHI)); ++ printk("CP0_XCONTEXT\t: 0x%08x\n", read_32bit_cp0_register(CP0_XCONTEXT)); ++ printk("CP0_FRAMEMASK\t: 0x%08x\n", read_32bit_cp0_register(CP0_FRAMEMASK)); ++ printk("CP0_DIAGNOSTIC\t: 0x%08x\n", read_32bit_cp0_register(CP0_DIAGNOSTIC)); ++ printk("CP0_DEBUG\t: 0x%08x\n", read_32bit_cp0_register(CP0_DEBUG)); ++ printk("CP0_DEPC\t: 0x%08x\n", read_32bit_cp0_register(CP0_DEPC)); ++ printk("CP0_PERFORMANCE\t: 0x%08x\n", read_32bit_cp0_register(CP0_PERFORMANCE)); ++ printk("CP0_ECC\t: 0x%08x\n", read_32bit_cp0_register(CP0_ECC)); ++ printk("CP0_CACHEERR\t: 0x%08x\n", read_32bit_cp0_register(CP0_CACHEERR)); ++ printk("CP0_TAGLO\t: 0x%08x\n", read_32bit_cp0_register(CP0_TAGLO)); ++ printk("CP0_TAGHI\t: 0x%08x\n", read_32bit_cp0_register(CP0_TAGHI)); ++ printk("CP0_ERROREPC\t: 0x%08x\n", read_32bit_cp0_register(CP0_ERROREPC)); ++ printk("CP0_DESAVE\t: 0x%08x\n\n", read_32bit_cp0_register(CP0_DESAVE)); ++} ++#endif ++ ++struct proc_dir_entry *procRegDir; ++static struct proc_dir_entry *procGmac, *procSysCP0, *procTxRing, *procRxRing, *procSkbFree; ++#if defined(CONFIG_PSEUDO_SUPPORT) && defined(CONFIG_ETHTOOL) ++static struct proc_dir_entry *procGmac2; ++#endif ++#if defined(CONFIG_USER_SNMPD) ++static struct proc_dir_entry *procRaSnmp; ++#endif ++#if defined(CONFIG_RAETH_TSO) ++static struct proc_dir_entry *procNumOfTxd, *procTsoLen; ++#endif ++ ++#if defined(CONFIG_RAETH_LRO) ++static struct proc_dir_entry *procLroStats; ++#endif ++#if defined(CONFIG_RAETH_HW_LRO) || defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++static struct proc_dir_entry *procRxRing1, *procRxRing2, *procRxRing3; ++static struct proc_dir_entry *procHwLroStats, *procHwLroAutoTlb; ++const static HWLRO_DBG_FUNC hw_lro_dbg_func[] = ++{ ++ [0] = hwlro_agg_cnt_ctrl, ++ [1] = hwlro_agg_time_ctrl, ++ [2] = hwlro_age_time_ctrl, ++ [3] = hwlro_pkt_int_alpha_ctrl, ++ [4] = hwlro_threshold_ctrl, ++ [5] = hwlro_fix_setting_switch_ctrl, ++}; ++#endif /* CONFIG_RAETH_HW_LRO */ ++#if defined (TASKLET_WORKQUEUE_SW) ++static struct proc_dir_entry *procSCHE; ++#endif ++ ++#if defined(CONFIG_RAETH_PDMA_DVT) ++static struct proc_dir_entry *procPdmaDvt; ++ ++const static PDMA_DBG_FUNC pdma_dvt_dbg_func[] = ++{ ++ [0] = pdma_dvt_show_ctrl, ++ [1] = pdma_dvt_test_rx_ctrl, ++ [2] = pdma_dvt_test_tx_ctrl, ++ [3] = pdma_dvt_test_debug_ctrl, ++ [4] = pdma_dvt_test_lro_ctrl, ++}; ++#endif //#if defined(CONFIG_RAETH_PDMA_DVT) ++ ++int RegReadMain(struct seq_file *seq, void *v) ++{ ++ dump_reg(seq); ++ return 0; ++} ++ ++static void *seq_SkbFree_start(struct seq_file *seq, loff_t *pos) ++{ ++ if (*pos < NUM_TX_DESC) ++ return pos; ++ return NULL; ++} ++ ++static void *seq_SkbFree_next(struct seq_file *seq, void *v, loff_t *pos) ++{ ++ (*pos)++; ++ if (*pos >= NUM_TX_DESC) ++ return NULL; ++ return pos; ++} ++ ++static void seq_SkbFree_stop(struct seq_file *seq, void *v) ++{ ++ /* Nothing to do */ ++} ++ ++static int seq_SkbFree_show(struct seq_file *seq, void *v) ++{ ++ int i = *(loff_t *) v; ++ END_DEVICE *ei_local = netdev_priv(dev_raether); ++ ++ seq_printf(seq, "%d: %08x\n",i, *(int *)&ei_local->skb_free[i]); ++ ++ return 0; ++} ++ ++static const struct seq_operations seq_skb_free_ops = { ++ .start = seq_SkbFree_start, ++ .next = seq_SkbFree_next, ++ .stop = seq_SkbFree_stop, ++ .show = seq_SkbFree_show ++}; ++ ++static int skb_free_open(struct inode *inode, struct file *file) ++{ ++ return seq_open(file, &seq_skb_free_ops); ++} ++ ++static const struct file_operations skb_free_fops = { ++ .owner = THIS_MODULE, ++ .open = skb_free_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = seq_release ++}; ++ ++#if defined (CONFIG_RAETH_QDMA) ++int QDMARead(struct seq_file *seq, void *v) ++{ ++ unsigned int temp,i; ++ unsigned int sw_fq, hw_fq; ++ unsigned int min_en, min_rate, max_en, max_rate, sch, weight; ++ unsigned int queue, tx_des_cnt, hw_resv, sw_resv, queue_head, queue_tail; ++ struct net_device *dev = dev_raether; ++ END_DEVICE *ei_local = netdev_priv(dev); ++ ++ seq_printf(seq, "==== General Information ====\n"); ++ temp = sysRegRead(QDMA_FQ_CNT); ++ sw_fq = (temp&0xFFFF0000)>>16; ++ hw_fq = (temp&0x0000FFFF); ++ seq_printf(seq, "SW TXD: %d/%d; HW TXD: %d/%d\n", sw_fq, NUM_TX_DESC, hw_fq,NUM_QDMA_PAGE); ++ seq_printf(seq, "SW TXD virtual start address: 0x%08x\n", ei_local->txd_pool); ++ seq_printf(seq, "HW TXD virtual start address: 0x%08x\n\n", free_head); ++ ++ seq_printf(seq, "==== Scheduler Information ====\n"); ++ temp = sysRegRead(QDMA_TX_SCH); ++ max_en = (temp&0x00000800)>>11; ++ max_rate = (temp&0x000007F0)>>4; ++ for(i=0;i<(temp&0x0000000F);i++) ++ max_rate *= 10; ++ seq_printf(seq, "SCH1 rate control:%d. Rate is %dKbps.\n", max_en, max_rate); ++ max_en = (temp&0x08000000)>>27; ++ max_rate = (temp&0x07F00000)>>20; ++ for(i=0;i<(temp&0x000F0000);i++) ++ max_rate *= 10; ++ seq_printf(seq, "SCH2 rate control:%d. Rate is %dKbps.\n\n", max_en, max_rate); ++ ++ seq_printf(seq, "==== Physical Queue Information ====\n"); ++ for (queue = 0; queue < 16; queue++){ ++ temp = sysRegRead(QTX_CFG_0 + 0x10 * queue); ++ tx_des_cnt = (temp & 0xffff0000) >> 16; ++ hw_resv = (temp & 0xff00) >> 8; ++ sw_resv = (temp & 0xff); ++ temp = sysRegRead(QTX_CFG_0 +(0x10 * queue) + 0x4); ++ sch = (temp >> 31) + 1 ; ++ min_en = (temp & 0x8000000) >> 27; ++ min_rate = (temp & 0x7f00000) >> 20; ++ for (i = 0; i< (temp & 0xf0000) >> 16; i++) ++ min_rate *= 10; ++ max_en = (temp & 0x800) >> 11; ++ max_rate = (temp & 0x7f0) >> 4; ++ for (i = 0; i< (temp & 0xf); i++) ++ max_rate *= 10; ++ weight = (temp & 0xf000) >> 12; ++ queue_head = sysRegRead(QTX_HEAD_0 + 0x10 * queue); ++ queue_tail = sysRegRead(QTX_TAIL_0 + 0x10 * queue); ++ ++ seq_printf(seq, "Queue#%d Information:\n", queue); ++ seq_printf(seq, "%d packets in the queue; head address is 0x%08x, tail address is 0x%08x.\n", tx_des_cnt, queue_head, queue_tail); ++ seq_printf(seq, "HW_RESV: %d; SW_RESV: %d; SCH: %d; Weighting: %d\n", hw_resv, sw_resv, sch, weight); ++ seq_printf(seq, "Min_Rate_En is %d, Min_Rate is %dKbps; Max_Rate_En is %d, Max_Rate is %dKbps.\n\n", min_en, min_rate, max_en, max_rate); ++ } ++#if defined (CONFIG_ARCH_MT7623) && defined(CONFIG_HW_SFQ) ++ seq_printf(seq, "==== Virtual Queue Information ====\n"); ++ seq_printf(seq, "VQTX_TB_BASE_0:0x%08x;VQTX_TB_BASE_1:0x%08x;VQTX_TB_BASE_2:0x%08x;VQTX_TB_BASE_3:0x%08x\n", \ ++ sfq0, sfq1, sfq2, sfq3); ++ temp = sysRegRead(VQTX_NUM); ++ seq_printf(seq, "VQTX_NUM_0:0x%01x;VQTX_NUM_1:0x%01x;VQTX_NUM_2:0x%01x;VQTX_NUM_3:0x%01x\n\n", \ ++ temp&0xF, (temp&0xF0)>>4, (temp&0xF00)>>8, (temp&0xF000)>>12); ++ ++#endif ++ ++ seq_printf(seq, "==== Flow Control Information ====\n"); ++ temp = sysRegRead(QDMA_FC_THRES); ++ seq_printf(seq, "SW_DROP_EN:%x; SW_DROP_FFA:%d; SW_DROP_MODE:%d\n", \ ++ (temp&0x1000000)>>24, (temp&0x200000)>>25, (temp&0x30000000)>>28); ++ seq_printf(seq, "WH_DROP_EN:%x; HW_DROP_FFA:%d; HW_DROP_MODE:%d\n", \ ++ (temp&0x10000)>>16, (temp&0x2000)>>17, (temp&0x300000)>>20); ++#if defined (CONFIG_ARCH_MT7623) ++ seq_printf(seq, "SW_DROP_FSTVQ_MODE:%d;SW_DROP_FSTVQ:%d\n", \ ++ (temp&0xC0000000)>>30, (temp&0x08000000)>>27); ++ seq_printf(seq, "HW_DROP_FSTVQ_MODE:%d;HW_DROP_FSTVQ:%d\n", \ ++ (temp&0xC00000)>>22, (temp&0x080000)>>19); ++#endif ++ ++ seq_printf(seq, "\n==== FSM Information\n"); ++ temp = sysRegRead(QDMA_DMA); ++#if defined (CONFIG_ARCH_MT7623) ++ seq_printf(seq, "VQTB_FSM:0x%01x\n", (temp&0x0F000000)>>24); ++#endif ++ seq_printf(seq, "FQ_FSM:0x%01x\n", (temp&0x000F0000)>>16); ++ seq_printf(seq, "TX_FSM:0x%01x\n", (temp&0x00000F00)>>12); ++ seq_printf(seq, "RX_FSM:0x%01x\n\n", (temp&0x0000000f)); ++ ++ seq_printf(seq, "==== M2Q Information ====\n"); ++ for (i = 0; i < 64; i+=8){ ++ seq_printf(seq, " (%d,%d)(%d,%d)(%d,%d)(%d,%d)(%d,%d)(%d,%d)(%d,%d)(%d,%d)\n", ++ i, M2Q_table[i], i+1, M2Q_table[i+1], i+2, M2Q_table[i+2], i+3, M2Q_table[i+3], ++ i+4, M2Q_table[i+4], i+5, M2Q_table[i+5], i+6, M2Q_table[i+6], i+7, M2Q_table[i+7]); ++ } ++ ++ return 0; ++ ++} ++ ++static int qdma_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, QDMARead, NULL); ++} ++ ++static const struct file_operations qdma_fops = { ++ .owner = THIS_MODULE, ++ .open = qdma_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release ++}; ++#endif ++ ++int TxRingRead(struct seq_file *seq, void *v) ++{ ++ END_DEVICE *ei_local = netdev_priv(dev_raether); ++ struct PDMA_txdesc *tx_ring; ++ int i = 0; ++ ++ tx_ring = kmalloc(sizeof(struct PDMA_txdesc) * NUM_TX_DESC, GFP_KERNEL); ++ if(tx_ring==NULL){ ++ seq_printf(seq, " allocate temp tx_ring fail.\n"); ++ return 0; ++ } ++ ++ for (i=0; i < NUM_TX_DESC; i++) { ++ tx_ring[i] = ei_local->tx_ring0[i]; ++ } ++ ++ for (i=0; i < NUM_TX_DESC; i++) { ++#ifdef CONFIG_32B_DESC ++ seq_printf(seq, "%d: %08x %08x %08x %08x %08x %08x %08x %08x\n",i, *(int *)&tx_ring[i].txd_info1, ++ *(int *)&tx_ring[i].txd_info2, *(int *)&tx_ring[i].txd_info3, ++ *(int *)&tx_ring[i].txd_info4, *(int *)&tx_ring[i].txd_info5, ++ *(int *)&tx_ring[i].txd_info6, *(int *)&tx_ring[i].txd_info7, ++ *(int *)&tx_ring[i].txd_info8); ++#else ++ seq_printf(seq, "%d: %08x %08x %08x %08x\n",i, *(int *)&tx_ring[i].txd_info1, *(int *)&tx_ring[i].txd_info2, ++ *(int *)&tx_ring[i].txd_info3, *(int *)&tx_ring[i].txd_info4); ++#endif ++ } ++ ++ kfree(tx_ring); ++ return 0; ++} ++ ++static int tx_ring_open(struct inode *inode, struct file *file) ++{ ++#if !defined (CONFIG_RAETH_QDMA) ++ return single_open(file, TxRingRead, NULL); ++#else ++ return single_open(file, QDMARead, NULL); ++#endif ++} ++ ++static const struct file_operations tx_ring_fops = { ++ .owner = THIS_MODULE, ++ .open = tx_ring_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release ++}; ++ ++int RxRingRead(struct seq_file *seq, void *v) ++{ ++ END_DEVICE *ei_local = netdev_priv(dev_raether); ++ struct PDMA_rxdesc *rx_ring; ++ int i = 0; ++ ++ rx_ring = kmalloc(sizeof(struct PDMA_rxdesc) * NUM_RX_DESC, GFP_KERNEL); ++ if(rx_ring==NULL){ ++ seq_printf(seq, " allocate temp rx_ring fail.\n"); ++ return 0; ++ } ++ ++ for (i=0; i < NUM_RX_DESC; i++) { ++ memcpy(&rx_ring[i], &ei_local->rx_ring0[i], sizeof(struct PDMA_rxdesc)); ++ } ++ ++ for (i=0; i < NUM_RX_DESC; i++) { ++#ifdef CONFIG_32B_DESC ++ seq_printf(seq, "%d: %08x %08x %08x %08x %08x %08x %08x %08x\n",i, *(int *)&rx_ring[i].rxd_info1, ++ *(int *)&rx_ring[i].rxd_info2, *(int *)&rx_ring[i].rxd_info3, ++ *(int *)&rx_ring[i].rxd_info4, *(int *)&rx_ring[i].rxd_info5, ++ *(int *)&rx_ring[i].rxd_info6, *(int *)&rx_ring[i].rxd_info7, ++ *(int *)&rx_ring[i].rxd_info8); ++#else ++ seq_printf(seq, "%d: %08x %08x %08x %08x\n",i, *(int *)&rx_ring[i].rxd_info1, *(int *)&rx_ring[i].rxd_info2, ++ *(int *)&rx_ring[i].rxd_info3, *(int *)&rx_ring[i].rxd_info4); ++#endif ++ } ++ ++ kfree(rx_ring); ++ return 0; ++} ++ ++static int rx_ring_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, RxRingRead, NULL); ++} ++ ++static const struct file_operations rx_ring_fops = { ++ .owner = THIS_MODULE, ++ .open = rx_ring_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release ++}; ++ ++#if defined(CONFIG_RAETH_HW_LRO) || defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++int RxLRORingRead(struct seq_file *seq, void *v, struct PDMA_rxdesc *rx_ring_p) ++{ ++ struct PDMA_rxdesc *rx_ring; ++ int i = 0; ++ ++ rx_ring = kmalloc(sizeof(struct PDMA_rxdesc) * NUM_LRO_RX_DESC, GFP_KERNEL); ++ if(rx_ring==NULL){ ++ seq_printf(seq, " allocate temp rx_ring fail.\n"); ++ return 0; ++ } ++ ++ for (i=0; i < NUM_LRO_RX_DESC; i++) { ++ memcpy(&rx_ring[i], &rx_ring_p[i], sizeof(struct PDMA_rxdesc)); ++ } ++ ++ for (i=0; i < NUM_LRO_RX_DESC; i++) { ++#ifdef CONFIG_32B_DESC ++ seq_printf(seq, "%d: %08x %08x %08x %08x %08x %08x %08x %08x\n",i, *(int *)&rx_ring[i].rxd_info1, ++ *(int *)&rx_ring[i].rxd_info2, *(int *)&rx_ring[i].rxd_info3, ++ *(int *)&rx_ring[i].rxd_info4, *(int *)&rx_ring[i].rxd_info5, ++ *(int *)&rx_ring[i].rxd_info6, *(int *)&rx_ring[i].rxd_info7, ++ *(int *)&rx_ring[i].rxd_info8); ++#else ++ seq_printf(seq, "%d: %08x %08x %08x %08x\n",i, *(int *)&rx_ring[i].rxd_info1, *(int *)&rx_ring[i].rxd_info2, ++ *(int *)&rx_ring[i].rxd_info3, *(int *)&rx_ring[i].rxd_info4); ++#endif ++ } ++ ++ kfree(rx_ring); ++ return 0; ++} ++ ++int RxRing1Read(struct seq_file *seq, void *v) ++{ ++ END_DEVICE *ei_local = netdev_priv(dev_raether); ++ RxLRORingRead(seq, v, ei_local->rx_ring1); ++ ++ return 0; ++} ++ ++int RxRing2Read(struct seq_file *seq, void *v) ++{ ++ END_DEVICE *ei_local = netdev_priv(dev_raether); ++ RxLRORingRead(seq, v, ei_local->rx_ring2); ++ ++ return 0; ++} ++ ++int RxRing3Read(struct seq_file *seq, void *v) ++{ ++ END_DEVICE *ei_local = netdev_priv(dev_raether); ++ RxLRORingRead(seq, v, ei_local->rx_ring3); ++ ++ return 0; ++} ++ ++static int rx_ring1_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, RxRing1Read, NULL); ++} ++ ++static int rx_ring2_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, RxRing2Read, NULL); ++} ++ ++static int rx_ring3_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, RxRing3Read, NULL); ++} ++ ++static const struct file_operations rx_ring1_fops = { ++ .owner = THIS_MODULE, ++ .open = rx_ring1_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release ++}; ++ ++static const struct file_operations rx_ring2_fops = { ++ .owner = THIS_MODULE, ++ .open = rx_ring2_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release ++}; ++ ++static const struct file_operations rx_ring3_fops = { ++ .owner = THIS_MODULE, ++ .open = rx_ring3_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release ++}; ++#endif /* CONFIG_RAETH_HW_LRO */ ++ ++#if defined(CONFIG_RAETH_TSO) ++ ++int NumOfTxdUpdate(int num_of_txd) ++{ ++ ++ txd_cnt[num_of_txd]++; ++ ++ return 0; ++} ++ ++static void *seq_TsoTxdNum_start(struct seq_file *seq, loff_t *pos) ++{ ++ seq_printf(seq, "TXD | Count\n"); ++ if (*pos < (MAX_SKB_FRAGS/2 + 1)) ++ return pos; ++ return NULL; ++} ++ ++static void *seq_TsoTxdNum_next(struct seq_file *seq, void *v, loff_t *pos) ++{ ++ (*pos)++; ++ if (*pos >= (MAX_SKB_FRAGS/2 + 1)) ++ return NULL; ++ return pos; ++} ++ ++static void seq_TsoTxdNum_stop(struct seq_file *seq, void *v) ++{ ++ /* Nothing to do */ ++} ++ ++static int seq_TsoTxdNum_show(struct seq_file *seq, void *v) ++{ ++ int i = *(loff_t *) v; ++ seq_printf(seq, "%d: %d\n",i , txd_cnt[i]); ++ ++ return 0; ++} ++ ++ssize_t NumOfTxdWrite(struct file *file, const char __user *buffer, ++ size_t count, loff_t *data) ++{ ++ memset(txd_cnt, 0, sizeof(txd_cnt)); ++ printk("clear txd cnt table\n"); ++ ++ return count; ++} ++ ++int TsoLenUpdate(int tso_len) ++{ ++ ++ if(tso_len > 70000) { ++ tso_cnt[14]++; ++ }else if(tso_len > 65000) { ++ tso_cnt[13]++; ++ }else if(tso_len > 60000) { ++ tso_cnt[12]++; ++ }else if(tso_len > 55000) { ++ tso_cnt[11]++; ++ }else if(tso_len > 50000) { ++ tso_cnt[10]++; ++ }else if(tso_len > 45000) { ++ tso_cnt[9]++; ++ }else if(tso_len > 40000) { ++ tso_cnt[8]++; ++ }else if(tso_len > 35000) { ++ tso_cnt[7]++; ++ }else if(tso_len > 30000) { ++ tso_cnt[6]++; ++ }else if(tso_len > 25000) { ++ tso_cnt[5]++; ++ }else if(tso_len > 20000) { ++ tso_cnt[4]++; ++ }else if(tso_len > 15000) { ++ tso_cnt[3]++; ++ }else if(tso_len > 10000) { ++ tso_cnt[2]++; ++ }else if(tso_len > 5000) { ++ tso_cnt[1]++; ++ }else { ++ tso_cnt[0]++; ++ } ++ ++ return 0; ++} ++ ++ssize_t TsoLenWrite(struct file *file, const char __user *buffer, ++ size_t count, loff_t *data) ++{ ++ memset(tso_cnt, 0, sizeof(tso_cnt)); ++ printk("clear tso cnt table\n"); ++ ++ return count; ++} ++ ++static void *seq_TsoLen_start(struct seq_file *seq, loff_t *pos) ++{ ++ seq_printf(seq, " Length | Count\n"); ++ if (*pos < 15) ++ return pos; ++ return NULL; ++} ++ ++static void *seq_TsoLen_next(struct seq_file *seq, void *v, loff_t *pos) ++{ ++ (*pos)++; ++ if (*pos >= 15) ++ return NULL; ++ return pos; ++} ++ ++static void seq_TsoLen_stop(struct seq_file *seq, void *v) ++{ ++ /* Nothing to do */ ++} ++ ++static int seq_TsoLen_show(struct seq_file *seq, void *v) ++{ ++ int i = *(loff_t *) v; ++ ++ seq_printf(seq, "%d~%d: %d\n", i*5000, (i+1)*5000, tso_cnt[i]); ++ ++ return 0; ++} ++ ++static const struct seq_operations seq_tso_txd_num_ops = { ++ .start = seq_TsoTxdNum_start, ++ .next = seq_TsoTxdNum_next, ++ .stop = seq_TsoTxdNum_stop, ++ .show = seq_TsoTxdNum_show ++}; ++ ++static int tso_txd_num_open(struct inode *inode, struct file *file) ++{ ++ return seq_open(file, &seq_tso_txd_num_ops); ++} ++ ++static struct file_operations tso_txd_num_fops = { ++ .owner = THIS_MODULE, ++ .open = tso_txd_num_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .write = NumOfTxdWrite, ++ .release = seq_release ++}; ++ ++static const struct seq_operations seq_tso_len_ops = { ++ .start = seq_TsoLen_start, ++ .next = seq_TsoLen_next, ++ .stop = seq_TsoLen_stop, ++ .show = seq_TsoLen_show ++}; ++ ++static int tso_len_open(struct inode *inode, struct file *file) ++{ ++ return seq_open(file, &seq_tso_len_ops); ++} ++ ++static struct file_operations tso_len_fops = { ++ .owner = THIS_MODULE, ++ .open = tso_len_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .write = TsoLenWrite, ++ .release = seq_release ++}; ++#endif ++ ++#if defined(CONFIG_RAETH_LRO) ++static int LroLenUpdate(struct net_lro_desc *lro_desc) ++{ ++ int len_idx; ++ ++ if(lro_desc->ip_tot_len > 65000) { ++ len_idx = 13; ++ }else if(lro_desc->ip_tot_len > 60000) { ++ len_idx = 12; ++ }else if(lro_desc->ip_tot_len > 55000) { ++ len_idx = 11; ++ }else if(lro_desc->ip_tot_len > 50000) { ++ len_idx = 10; ++ }else if(lro_desc->ip_tot_len > 45000) { ++ len_idx = 9; ++ }else if(lro_desc->ip_tot_len > 40000) { ++ len_idx = 8; ++ }else if(lro_desc->ip_tot_len > 35000) { ++ len_idx = 7; ++ }else if(lro_desc->ip_tot_len > 30000) { ++ len_idx = 6; ++ }else if(lro_desc->ip_tot_len > 25000) { ++ len_idx = 5; ++ }else if(lro_desc->ip_tot_len > 20000) { ++ len_idx = 4; ++ }else if(lro_desc->ip_tot_len > 15000) { ++ len_idx = 3; ++ }else if(lro_desc->ip_tot_len > 10000) { ++ len_idx = 2; ++ }else if(lro_desc->ip_tot_len > 5000) { ++ len_idx = 1; ++ }else { ++ len_idx = 0; ++ } ++ ++ return len_idx; ++} ++int LroStatsUpdate(struct net_lro_mgr *lro_mgr, bool all_flushed) ++{ ++ struct net_lro_desc *tmp; ++ int len_idx; ++ int i, j; ++ ++ if (all_flushed) { ++ for (i=0; i< MAX_DESC; i++) { ++ tmp = & lro_mgr->lro_arr[i]; ++ if (tmp->pkt_aggr_cnt !=0) { ++ for(j=0; j<=MAX_AGGR; j++) { ++ if(tmp->pkt_aggr_cnt == j) { ++ lro_flush_cnt[j]++; ++ } ++ } ++ len_idx = LroLenUpdate(tmp); ++ lro_len_cnt1[len_idx]++; ++ tot_called1++; ++ } ++ aggregated[i] = 0; ++ } ++ } else { ++ if (lro_flushed != lro_mgr->stats.flushed) { ++ if (lro_aggregated != lro_mgr->stats.aggregated) { ++ for (i=0; ilro_arr[i]; ++ if ((aggregated[i]!= tmp->pkt_aggr_cnt) ++ && (tmp->pkt_aggr_cnt == 0)) { ++ aggregated[i] ++; ++ for (j=0; j<=MAX_AGGR; j++) { ++ if (aggregated[i] == j) { ++ lro_stats_cnt[j] ++; ++ } ++ } ++ aggregated[i] = 0; ++ //len_idx = LroLenUpdate(tmp); ++ //lro_len_cnt2[len_idx]++; ++ tot_called2++; ++ } ++ } ++ } else { ++ for (i=0; ilro_arr[i]; ++ if ((aggregated[i] != 0) && (tmp->pkt_aggr_cnt==0)) { ++ for (j=0; j<=MAX_AGGR; j++) { ++ if (aggregated[i] == j) { ++ lro_stats_cnt[j] ++; ++ } ++ } ++ aggregated[i] = 0; ++ //len_idx = LroLenUpdate(tmp); ++ //lro_len_cnt2[len_idx]++; ++ force_flush ++; ++ tot_called2++; ++ } ++ } ++ } ++ } else { ++ if (lro_aggregated != lro_mgr->stats.aggregated) { ++ for (i=0; ilro_arr[i]; ++ if (tmp->active) { ++ if (aggregated[i] != tmp->pkt_aggr_cnt) ++ aggregated[i] = tmp->pkt_aggr_cnt; ++ } else ++ aggregated[i] = 0; ++ } ++ } ++ } ++ ++ } ++ ++ lro_aggregated = lro_mgr->stats.aggregated; ++ lro_flushed = lro_mgr->stats.flushed; ++ lro_nodesc = lro_mgr->stats.no_desc; ++ ++ return 0; ++ ++} ++ ++ ++ssize_t LroStatsWrite(struct file *file, const char __user *buffer, ++ size_t count, loff_t *data) ++{ ++ memset(lro_stats_cnt, 0, sizeof(lro_stats_cnt)); ++ memset(lro_flush_cnt, 0, sizeof(lro_flush_cnt)); ++ memset(lro_len_cnt1, 0, sizeof(lro_len_cnt1)); ++ //memset(lro_len_cnt2, 0, sizeof(lro_len_cnt2)); ++ memset(aggregated, 0, sizeof(aggregated)); ++ lro_aggregated = 0; ++ lro_flushed = 0; ++ lro_nodesc = 0; ++ force_flush = 0; ++ tot_called1 = 0; ++ tot_called2 = 0; ++ printk("clear lro cnt table\n"); ++ ++ return count; ++} ++ ++int LroStatsRead(struct seq_file *seq, void *v) ++{ ++ int i; ++ int tot_cnt=0; ++ int tot_aggr=0; ++ int ave_aggr=0; ++ ++ seq_printf(seq, "LRO statistic dump:\n"); ++ seq_printf(seq, "Cnt: Kernel | Driver\n"); ++ for(i=0; i<=MAX_AGGR; i++) { ++ tot_cnt = tot_cnt + lro_stats_cnt[i] + lro_flush_cnt[i]; ++ seq_printf(seq, " %d : %d %d\n", i, lro_stats_cnt[i], lro_flush_cnt[i]); ++ tot_aggr = tot_aggr + i * (lro_stats_cnt[i] + lro_flush_cnt[i]); ++ } ++ ave_aggr = lro_aggregated/lro_flushed; ++ seq_printf(seq, "Total aggregated pkt: %d\n", lro_aggregated); ++ seq_printf(seq, "Flushed pkt: %d %d\n", lro_flushed, force_flush); ++ seq_printf(seq, "Average flush cnt: %d\n", ave_aggr); ++ seq_printf(seq, "No descriptor pkt: %d\n\n\n", lro_nodesc); ++ ++ seq_printf(seq, "Driver flush pkt len:\n"); ++ seq_printf(seq, " Length | Count\n"); ++ for(i=0; i<15; i++) { ++ seq_printf(seq, "%d~%d: %d\n", i*5000, (i+1)*5000, lro_len_cnt1[i]); ++ } ++ seq_printf(seq, "Kernel flush: %d; Driver flush: %d\n", tot_called2, tot_called1); ++ return 0; ++} ++ ++static int lro_stats_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, LroStatsRead, NULL); ++} ++ ++static struct file_operations lro_stats_fops = { ++ .owner = THIS_MODULE, ++ .open = lro_stats_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .write = LroStatsWrite, ++ .release = single_release ++}; ++#endif ++ ++int getnext(const char *src, int separator, char *dest) ++{ ++ char *c; ++ int len; ++ ++ if ( (src == NULL) || (dest == NULL) ) { ++ return -1; ++ } ++ ++ c = strchr(src, separator); ++ if (c == NULL) { ++ strcpy(dest, src); ++ return -1; ++ } ++ len = c - src; ++ strncpy(dest, src, len); ++ dest[len] = '\0'; ++ return len + 1; ++} ++ ++int str_to_ip(unsigned int *ip, const char *str) ++{ ++ int len; ++ const char *ptr = str; ++ char buf[128]; ++ unsigned char c[4]; ++ int i; ++ ++ for (i = 0; i < 3; ++i) { ++ if ((len = getnext(ptr, '.', buf)) == -1) { ++ return 1; /* parse error */ ++ } ++ c[i] = simple_strtoul(buf, NULL, 10); ++ ptr += len; ++ } ++ c[3] = simple_strtoul(ptr, NULL, 0); ++ *ip = (c[0]<<24) + (c[1]<<16) + (c[2]<<8) + c[3]; ++ return 0; ++} ++ ++#if defined(CONFIG_RAETH_HW_LRO) ++static int HwLroLenUpdate(unsigned int agg_size) ++{ ++ int len_idx; ++ ++ if(agg_size > 65000) { ++ len_idx = 13; ++ }else if(agg_size > 60000) { ++ len_idx = 12; ++ }else if(agg_size > 55000) { ++ len_idx = 11; ++ }else if(agg_size > 50000) { ++ len_idx = 10; ++ }else if(agg_size > 45000) { ++ len_idx = 9; ++ }else if(agg_size > 40000) { ++ len_idx = 8; ++ }else if(agg_size > 35000) { ++ len_idx = 7; ++ }else if(agg_size > 30000) { ++ len_idx = 6; ++ }else if(agg_size > 25000) { ++ len_idx = 5; ++ }else if(agg_size > 20000) { ++ len_idx = 4; ++ }else if(agg_size > 15000) { ++ len_idx = 3; ++ }else if(agg_size > 10000) { ++ len_idx = 2; ++ }else if(agg_size > 5000) { ++ len_idx = 1; ++ }else { ++ len_idx = 0; ++ } ++ ++ return len_idx; ++} ++ ++int HwLroStatsUpdate(unsigned int ring_num, unsigned int agg_cnt, unsigned int agg_size) ++{ ++ if( (ring_num > 0) && (ring_num < 4) ) ++ { ++ hw_lro_agg_size_cnt[ring_num-1][HwLroLenUpdate(agg_size)]++; ++ hw_lro_agg_num_cnt[ring_num-1][agg_cnt]++; ++ hw_lro_tot_flush_cnt[ring_num-1]++; ++ hw_lro_tot_agg_cnt[ring_num-1] += agg_cnt; ++ } ++ ++ return 0; ++} ++ ++#if defined(CONFIG_RAETH_HW_LRO_REASON_DBG) ++int HwLroFlushStatsUpdate(unsigned int ring_num, unsigned int flush_reason) ++{ ++ if( (ring_num > 0) && (ring_num < 4) ) ++ { ++#if 1 ++ if ( (flush_reason & 0x7) == HW_LRO_AGG_FLUSH ) ++ hw_lro_agg_flush_cnt[ring_num-1]++; ++ else if ( (flush_reason & 0x7) == HW_LRO_AGE_FLUSH ) ++ hw_lro_age_flush_cnt[ring_num-1]++; ++ else if ( (flush_reason & 0x7) == HW_LRO_NOT_IN_SEQ_FLUSH ) ++ hw_lro_seq_flush_cnt[ring_num-1]++; ++ else if ( (flush_reason & 0x7) == HW_LRO_TIMESTAMP_FLUSH ) ++ hw_lro_timestamp_flush_cnt[ring_num-1]++; ++ else if ( (flush_reason & 0x7) == HW_LRO_NON_RULE_FLUSH ) ++ hw_lro_norule_flush_cnt[ring_num-1]++; ++#else ++ if ( flush_reason & BIT(4) ) ++ hw_lro_agg_flush_cnt[ring_num-1]++; ++ else if ( flush_reason & BIT(3) ) ++ hw_lro_age_flush_cnt[ring_num-1]++; ++ else if ( flush_reason & BIT(2) ) ++ hw_lro_seq_flush_cnt[ring_num-1]++; ++ else if ( flush_reason & BIT(1) ) ++ hw_lro_timestamp_flush_cnt[ring_num-1]++; ++ else if ( flush_reason & BIT(0) ) ++ hw_lro_norule_flush_cnt[ring_num-1]++; ++#endif ++ } ++ ++ return 0; ++} ++#endif /* CONFIG_RAETH_HW_LRO_REASON_DBG */ ++ ++ssize_t HwLroStatsWrite(struct file *file, const char __user *buffer, ++ size_t count, loff_t *data) ++{ ++ memset(hw_lro_agg_num_cnt, 0, sizeof(hw_lro_agg_num_cnt)); ++ memset(hw_lro_agg_size_cnt, 0, sizeof(hw_lro_agg_size_cnt)); ++ memset(hw_lro_tot_agg_cnt, 0, sizeof(hw_lro_tot_agg_cnt)); ++ memset(hw_lro_tot_flush_cnt, 0, sizeof(hw_lro_tot_flush_cnt)); ++#if defined(CONFIG_RAETH_HW_LRO_REASON_DBG) ++ memset(hw_lro_agg_flush_cnt, 0, sizeof(hw_lro_agg_flush_cnt)); ++ memset(hw_lro_age_flush_cnt, 0, sizeof(hw_lro_age_flush_cnt)); ++ memset(hw_lro_seq_flush_cnt, 0, sizeof(hw_lro_seq_flush_cnt)); ++ memset(hw_lro_timestamp_flush_cnt, 0, sizeof(hw_lro_timestamp_flush_cnt)); ++ memset(hw_lro_norule_flush_cnt, 0, sizeof(hw_lro_norule_flush_cnt)); ++#endif /* CONFIG_RAETH_HW_LRO_REASON_DBG */ ++ ++ printk("clear hw lro cnt table\n"); ++ ++ return count; ++} ++ ++int HwLroStatsRead(struct seq_file *seq, void *v) ++{ ++ int i; ++ ++ seq_printf(seq, "HW LRO statistic dump:\n"); ++ ++ /* Agg number count */ ++ seq_printf(seq, "Cnt: RING1 | RING2 | RING3 | Total\n"); ++ for(i=0; i<=MAX_HW_LRO_AGGR; i++) { ++ seq_printf(seq, " %d : %d %d %d %d\n", ++ i, hw_lro_agg_num_cnt[0][i], hw_lro_agg_num_cnt[1][i], hw_lro_agg_num_cnt[2][i], ++ hw_lro_agg_num_cnt[0][i]+hw_lro_agg_num_cnt[1][i]+hw_lro_agg_num_cnt[2][i]); ++ } ++ ++ /* Total agg count */ ++ seq_printf(seq, "Total agg: RING1 | RING2 | RING3 | Total\n"); ++ seq_printf(seq, " %d %d %d %d\n", ++ hw_lro_tot_agg_cnt[0], hw_lro_tot_agg_cnt[1], hw_lro_tot_agg_cnt[2], ++ hw_lro_tot_agg_cnt[0]+hw_lro_tot_agg_cnt[1]+hw_lro_tot_agg_cnt[2]); ++ ++ /* Total flush count */ ++ seq_printf(seq, "Total flush: RING1 | RING2 | RING3 | Total\n"); ++ seq_printf(seq, " %d %d %d %d\n", ++ hw_lro_tot_flush_cnt[0], hw_lro_tot_flush_cnt[1], hw_lro_tot_flush_cnt[2], ++ hw_lro_tot_flush_cnt[0]+hw_lro_tot_flush_cnt[1]+hw_lro_tot_flush_cnt[2]); ++ ++ /* Avg agg count */ ++ seq_printf(seq, "Avg agg: RING1 | RING2 | RING3 | Total\n"); ++ seq_printf(seq, " %d %d %d %d\n", ++ (hw_lro_tot_flush_cnt[0]) ? hw_lro_tot_agg_cnt[0]/hw_lro_tot_flush_cnt[0] : 0, ++ (hw_lro_tot_flush_cnt[1]) ? hw_lro_tot_agg_cnt[1]/hw_lro_tot_flush_cnt[1] : 0, ++ (hw_lro_tot_flush_cnt[2]) ? hw_lro_tot_agg_cnt[2]/hw_lro_tot_flush_cnt[2] : 0, ++ (hw_lro_tot_flush_cnt[0]+hw_lro_tot_flush_cnt[1]+hw_lro_tot_flush_cnt[2]) ? \ ++ ((hw_lro_tot_agg_cnt[0]+hw_lro_tot_agg_cnt[1]+hw_lro_tot_agg_cnt[2])/(hw_lro_tot_flush_cnt[0]+hw_lro_tot_flush_cnt[1]+hw_lro_tot_flush_cnt[2])) : 0 ++ ); ++ ++ /* Statistics of aggregation size counts */ ++ seq_printf(seq, "HW LRO flush pkt len:\n"); ++ seq_printf(seq, " Length | RING1 | RING2 | RING3 | Total\n"); ++ for(i=0; i<15; i++) { ++ seq_printf(seq, "%d~%d: %d %d %d %d\n", i*5000, (i+1)*5000, ++ hw_lro_agg_size_cnt[0][i], hw_lro_agg_size_cnt[1][i], hw_lro_agg_size_cnt[2][i], ++ hw_lro_agg_size_cnt[0][i]+hw_lro_agg_size_cnt[1][i]+hw_lro_agg_size_cnt[2][i]); ++ } ++#if defined(CONFIG_RAETH_HW_LRO_REASON_DBG) ++ seq_printf(seq, "Flush reason: RING1 | RING2 | RING3 | Total\n"); ++ seq_printf(seq, "AGG timeout: %d %d %d %d\n", ++ hw_lro_agg_flush_cnt[0], hw_lro_agg_flush_cnt[1], hw_lro_agg_flush_cnt[2], ++ (hw_lro_agg_flush_cnt[0]+hw_lro_agg_flush_cnt[1]+hw_lro_agg_flush_cnt[2]) ++ ); ++ seq_printf(seq, "AGE timeout: %d %d %d %d\n", ++ hw_lro_age_flush_cnt[0], hw_lro_age_flush_cnt[1], hw_lro_age_flush_cnt[2], ++ (hw_lro_age_flush_cnt[0]+hw_lro_age_flush_cnt[1]+hw_lro_age_flush_cnt[2]) ++ ); ++ seq_printf(seq, "Not in-sequence: %d %d %d %d\n", ++ hw_lro_seq_flush_cnt[0], hw_lro_seq_flush_cnt[1], hw_lro_seq_flush_cnt[2], ++ (hw_lro_seq_flush_cnt[0]+hw_lro_seq_flush_cnt[1]+hw_lro_seq_flush_cnt[2]) ++ ); ++ seq_printf(seq, "Timestamp: %d %d %d %d\n", ++ hw_lro_timestamp_flush_cnt[0], hw_lro_timestamp_flush_cnt[1], hw_lro_timestamp_flush_cnt[2], ++ (hw_lro_timestamp_flush_cnt[0]+hw_lro_timestamp_flush_cnt[1]+hw_lro_timestamp_flush_cnt[2]) ++ ); ++ seq_printf(seq, "No LRO rule: %d %d %d %d\n", ++ hw_lro_norule_flush_cnt[0], hw_lro_norule_flush_cnt[1], hw_lro_norule_flush_cnt[2], ++ (hw_lro_norule_flush_cnt[0]+hw_lro_norule_flush_cnt[1]+hw_lro_norule_flush_cnt[2]) ++ ); ++#endif /* CONFIG_RAETH_HW_LRO_REASON_DBG */ ++ ++ return 0; ++} ++ ++static int hw_lro_stats_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, HwLroStatsRead, NULL); ++} ++ ++static struct file_operations hw_lro_stats_fops = { ++ .owner = THIS_MODULE, ++ .open = hw_lro_stats_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .write = HwLroStatsWrite, ++ .release = single_release ++}; ++ ++int hwlro_agg_cnt_ctrl(int par1, int par2) ++{ ++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING1, par2); ++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING2, par2); ++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING3, par2); ++ return 0; ++} ++ ++int hwlro_agg_time_ctrl(int par1, int par2) ++{ ++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING1, par2); ++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING2, par2); ++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING3, par2); ++ return 0; ++} ++ ++int hwlro_age_time_ctrl(int par1, int par2) ++{ ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, par2); ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, par2); ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, par2); ++ return 0; ++} ++ ++int hwlro_pkt_int_alpha_ctrl(int par1, int par2) ++{ ++ END_DEVICE *ei_local = netdev_priv(dev_raether); ++ ++ ei_local->hw_lro_alpha = par2; ++ printk("[hwlro_pkt_int_alpha_ctrl]ei_local->hw_lro_alpha = %d\n", ei_local->hw_lro_alpha); ++ ++ return 0; ++} ++ ++int hwlro_threshold_ctrl(int par1, int par2) ++{ ++ /* bandwidth threshold setting */ ++ SET_PDMA_LRO_BW_THRESHOLD(par2); ++ return 0; ++} ++ ++int hwlro_fix_setting_switch_ctrl(int par1, int par2) ++{ ++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG) ++ END_DEVICE *ei_local = netdev_priv(dev_raether); ++ ++ ei_local->hw_lro_fix_setting = par2; ++ printk("[hwlro_pkt_int_alpha_ctrl]ei_local->hw_lro_fix_setting = %d\n", ei_local->hw_lro_fix_setting); ++#endif /* CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG */ ++ ++ return 0; ++} ++ ++ssize_t HwLroAutoTlbWrite(struct file *file, const char __user *buffer, ++ size_t count, loff_t *data) ++{ ++ char buf[32]; ++ char *pBuf; ++ int len = count; ++ int x = 0,y = 0; ++ char *pToken = NULL; ++ char *pDelimiter = " \t"; ++ ++ printk("[HwLroAutoTlbWrite]write parameter len = %d\n\r", (int)len); ++ if(len >= sizeof(buf)){ ++ printk("input handling fail!\n"); ++ len = sizeof(buf) - 1; ++ return -1; ++ } ++ ++ if(copy_from_user(buf, buffer, len)){ ++ return -EFAULT; ++ } ++ buf[len] = '\0'; ++ printk("[HwLroAutoTlbWrite]write parameter data = %s\n\r", buf); ++ ++ pBuf = buf; ++ pToken = strsep(&pBuf, pDelimiter); ++ x = NULL != pToken ? simple_strtol(pToken, NULL, 16) : 0; ++ ++ pToken = strsep(&pBuf, "\t\n "); ++ if(pToken != NULL){ ++ y = NULL != pToken ? simple_strtol(pToken, NULL, 16) : 0; ++ printk("y = 0x%08x \n\r", y); ++ } ++ ++ if ( (sizeof(hw_lro_dbg_func)/sizeof(hw_lro_dbg_func[0]) > x) && NULL != hw_lro_dbg_func[x]) ++ { ++ (*hw_lro_dbg_func[x])(x, y); ++ } ++ ++ return count; ++} ++ ++void HwLroAutoTlbDump(struct seq_file *seq, unsigned int index) ++{ ++ int i; ++ struct PDMA_LRO_AUTO_TLB_INFO pdma_lro_auto_tlb; ++ unsigned int tlb_info[9]; ++ unsigned int dw_len, cnt, priority; ++ unsigned int entry; ++ ++ if( index > 4 ) ++ index = index - 1; ++ entry = (index * 9) + 1; ++ ++ /* read valid entries of the auto-learn table */ ++ sysRegWrite( PDMA_FE_ALT_CF8, entry ); ++ ++ //seq_printf(seq, "\nEntry = %d\n", entry); ++ for(i=0; i<9; i++){ ++ tlb_info[i] = sysRegRead(PDMA_FE_ALT_SEQ_CFC); ++ //seq_printf(seq, "tlb_info[%d] = 0x%x\n", i, tlb_info[i]); ++ } ++ memcpy(&pdma_lro_auto_tlb, tlb_info, sizeof(struct PDMA_LRO_AUTO_TLB_INFO)); ++ ++ dw_len = pdma_lro_auto_tlb.auto_tlb_info7.DW_LEN; ++ cnt = pdma_lro_auto_tlb.auto_tlb_info6.CNT; ++ ++ if ( sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_ALT_SCORE_MODE ) /* packet count */ ++ priority = cnt; ++ else /* byte count */ ++ priority = dw_len; ++ ++ /* dump valid entries of the auto-learn table */ ++ if( index >= 4 ) ++ seq_printf(seq, "\n===== TABLE Entry: %d (Act) =====\n", index); ++ else ++ seq_printf(seq, "\n===== TABLE Entry: %d (LRU) =====\n", index); ++ if( pdma_lro_auto_tlb.auto_tlb_info8.IPV4 ){ ++ seq_printf(seq, "SIP = 0x%x:0x%x:0x%x:0x%x (IPv4)\n", ++ pdma_lro_auto_tlb.auto_tlb_info4.SIP3, ++ pdma_lro_auto_tlb.auto_tlb_info3.SIP2, ++ pdma_lro_auto_tlb.auto_tlb_info2.SIP1, ++ pdma_lro_auto_tlb.auto_tlb_info1.SIP0); ++ } ++ else{ ++ seq_printf(seq, "SIP = 0x%x:0x%x:0x%x:0x%x (IPv6)\n", ++ pdma_lro_auto_tlb.auto_tlb_info4.SIP3, ++ pdma_lro_auto_tlb.auto_tlb_info3.SIP2, ++ pdma_lro_auto_tlb.auto_tlb_info2.SIP1, ++ pdma_lro_auto_tlb.auto_tlb_info1.SIP0); ++ } ++ seq_printf(seq, "DIP_ID = %d\n", pdma_lro_auto_tlb.auto_tlb_info8.DIP_ID); ++ seq_printf(seq, "TCP SPORT = %d | TCP DPORT = %d\n", ++ pdma_lro_auto_tlb.auto_tlb_info0.STP, ++ pdma_lro_auto_tlb.auto_tlb_info0.DTP); ++ seq_printf(seq, "VLAN1 = %d | VLAN2 = %d | VLAN3 = %d | VLAN4 =%d \n", ++ pdma_lro_auto_tlb.auto_tlb_info5.VLAN_VID0, ++ (pdma_lro_auto_tlb.auto_tlb_info5.VLAN_VID0 << 12), ++ (pdma_lro_auto_tlb.auto_tlb_info5.VLAN_VID0 << 24), ++ pdma_lro_auto_tlb.auto_tlb_info6.VLAN_VID1); ++ seq_printf(seq, "TPUT = %d | FREQ = %d\n", dw_len, cnt); ++ seq_printf(seq, "PRIORITY = %d\n", priority); ++} ++ ++int HwLroAutoTlbRead(struct seq_file *seq, void *v) ++{ ++ int i; ++ unsigned int regVal; ++ unsigned int regOp1, regOp2, regOp3, regOp4; ++ unsigned int agg_cnt, agg_time, age_time; ++ ++ /* Read valid entries of the auto-learn table */ ++ sysRegWrite(PDMA_FE_ALT_CF8, 0); ++ regVal = sysRegRead(PDMA_FE_ALT_SEQ_CFC); ++ ++ seq_printf(seq, "HW LRO Auto-learn Table: (PDMA_LRO_ALT_CFC_RSEQ_DBG=0x%x)\n", regVal); ++ ++ for(i = 7; i >= 0; i--) ++ { ++ if( regVal & (1 << i) ) ++ HwLroAutoTlbDump(seq, i); ++ } ++ ++ /* Read the agg_time/age_time/agg_cnt of LRO rings */ ++ seq_printf(seq, "\nHW LRO Ring Settings\n"); ++ for(i = 1; i <= 3; i++) ++ { ++ regOp1 = sysRegRead( LRO_RX_RING0_CTRL_DW1 + (i * 0x40) ); ++ regOp2 = sysRegRead( LRO_RX_RING0_CTRL_DW2 + (i * 0x40) ); ++ regOp3 = sysRegRead( LRO_RX_RING0_CTRL_DW3 + (i * 0x40) ); ++ regOp4 = sysRegRead( ADMA_LRO_CTRL_DW2 ); ++ agg_cnt = ((regOp3 & 0x03) << PDMA_LRO_AGG_CNT_H_OFFSET) | ((regOp2 >> PDMA_LRO_RING_AGG_CNT1_OFFSET) & 0x3f); ++ agg_time = (regOp2 >> PDMA_LRO_RING_AGG_OFFSET) & 0xffff; ++ age_time = ((regOp2 & 0x03f) << PDMA_LRO_AGE_H_OFFSET) | ((regOp1 >> PDMA_LRO_RING_AGE1_OFFSET) & 0x3ff); ++ seq_printf(seq, "Ring[%d]: MAX_AGG_CNT=%d, AGG_TIME=%d, AGE_TIME=%d, Threshold=%d\n", ++ i, agg_cnt, agg_time, age_time, regOp4); ++ } ++ ++ return 0; ++} ++ ++static int hw_lro_auto_tlb_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, HwLroAutoTlbRead, NULL); ++} ++ ++static struct file_operations hw_lro_auto_tlb_fops = { ++ .owner = THIS_MODULE, ++ .open = hw_lro_auto_tlb_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .write = HwLroAutoTlbWrite, ++ .release = single_release ++}; ++#endif /* CONFIG_RAETH_HW_LRO */ ++ ++#if defined (CONFIG_MIPS) ++int CP0RegRead(struct seq_file *seq, void *v) ++{ ++ seq_printf(seq, "CP0 Register dump --\n"); ++ seq_printf(seq, "CP0_INDEX\t: 0x%08x\n", read_32bit_cp0_register(CP0_INDEX)); ++ seq_printf(seq, "CP0_RANDOM\t: 0x%08x\n", read_32bit_cp0_register(CP0_RANDOM)); ++ seq_printf(seq, "CP0_ENTRYLO0\t: 0x%08x\n", read_32bit_cp0_register(CP0_ENTRYLO0)); ++ seq_printf(seq, "CP0_ENTRYLO1\t: 0x%08x\n", read_32bit_cp0_register(CP0_ENTRYLO1)); ++ seq_printf(seq, "CP0_CONF\t: 0x%08x\n", read_32bit_cp0_register(CP0_CONF)); ++ seq_printf(seq, "CP0_CONTEXT\t: 0x%08x\n", read_32bit_cp0_register(CP0_CONTEXT)); ++ seq_printf(seq, "CP0_PAGEMASK\t: 0x%08x\n", read_32bit_cp0_register(CP0_PAGEMASK)); ++ seq_printf(seq, "CP0_WIRED\t: 0x%08x\n", read_32bit_cp0_register(CP0_WIRED)); ++ seq_printf(seq, "CP0_INFO\t: 0x%08x\n", read_32bit_cp0_register(CP0_INFO)); ++ seq_printf(seq, "CP0_BADVADDR\t: 0x%08x\n", read_32bit_cp0_register(CP0_BADVADDR)); ++ seq_printf(seq, "CP0_COUNT\t: 0x%08x\n", read_32bit_cp0_register(CP0_COUNT)); ++ seq_printf(seq, "CP0_ENTRYHI\t: 0x%08x\n", read_32bit_cp0_register(CP0_ENTRYHI)); ++ seq_printf(seq, "CP0_COMPARE\t: 0x%08x\n", read_32bit_cp0_register(CP0_COMPARE)); ++ seq_printf(seq, "CP0_STATUS\t: 0x%08x\n", read_32bit_cp0_register(CP0_STATUS)); ++ seq_printf(seq, "CP0_CAUSE\t: 0x%08x\n", read_32bit_cp0_register(CP0_CAUSE)); ++ seq_printf(seq, "CP0_EPC\t: 0x%08x\n", read_32bit_cp0_register(CP0_EPC)); ++ seq_printf(seq, "CP0_PRID\t: 0x%08x\n", read_32bit_cp0_register(CP0_PRID)); ++ seq_printf(seq, "CP0_CONFIG\t: 0x%08x\n", read_32bit_cp0_register(CP0_CONFIG)); ++ seq_printf(seq, "CP0_LLADDR\t: 0x%08x\n", read_32bit_cp0_register(CP0_LLADDR)); ++ seq_printf(seq, "CP0_WATCHLO\t: 0x%08x\n", read_32bit_cp0_register(CP0_WATCHLO)); ++ seq_printf(seq, "CP0_WATCHHI\t: 0x%08x\n", read_32bit_cp0_register(CP0_WATCHHI)); ++ seq_printf(seq, "CP0_XCONTEXT\t: 0x%08x\n", read_32bit_cp0_register(CP0_XCONTEXT)); ++ seq_printf(seq, "CP0_FRAMEMASK\t: 0x%08x\n", read_32bit_cp0_register(CP0_FRAMEMASK)); ++ seq_printf(seq, "CP0_DIAGNOSTIC\t: 0x%08x\n", read_32bit_cp0_register(CP0_DIAGNOSTIC)); ++ seq_printf(seq, "CP0_DEBUG\t: 0x%08x\n", read_32bit_cp0_register(CP0_DEBUG)); ++ seq_printf(seq, "CP0_DEPC\t: 0x%08x\n", read_32bit_cp0_register(CP0_DEPC)); ++ seq_printf(seq, "CP0_PERFORMANCE\t: 0x%08x\n", read_32bit_cp0_register(CP0_PERFORMANCE)); ++ seq_printf(seq, "CP0_ECC\t: 0x%08x\n", read_32bit_cp0_register(CP0_ECC)); ++ seq_printf(seq, "CP0_CACHEERR\t: 0x%08x\n", read_32bit_cp0_register(CP0_CACHEERR)); ++ seq_printf(seq, "CP0_TAGLO\t: 0x%08x\n", read_32bit_cp0_register(CP0_TAGLO)); ++ seq_printf(seq, "CP0_TAGHI\t: 0x%08x\n", read_32bit_cp0_register(CP0_TAGHI)); ++ seq_printf(seq, "CP0_ERROREPC\t: 0x%08x\n", read_32bit_cp0_register(CP0_ERROREPC)); ++ seq_printf(seq, "CP0_DESAVE\t: 0x%08x\n\n", read_32bit_cp0_register(CP0_DESAVE)); ++ ++ return 0; ++} ++ ++static int cp0_reg_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, CP0RegRead, NULL); ++} ++ ++static const struct file_operations cp0_reg_fops = { ++ .owner = THIS_MODULE, ++ .open = cp0_reg_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release ++}; ++#endif ++ ++#if defined(CONFIG_RAETH_QOS) ++static struct proc_dir_entry *procRaQOS, *procRaFeIntr, *procRaEswIntr; ++extern uint32_t num_of_rxdone_intr; ++extern uint32_t num_of_esw_intr; ++ ++int RaQOSRegRead(struct seq_file *seq, void *v) ++{ ++ dump_qos(seq); ++ return 0; ++} ++ ++static int raeth_qos_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, RaQOSRegRead, NULL); ++} ++ ++static const struct file_operations raeth_qos_fops = { ++ .owner = THIS_MODULE, ++ .open = raeth_qos_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release ++}; ++#endif ++ ++static struct proc_dir_entry *procEswCnt; ++ ++int EswCntRead(struct seq_file *seq, void *v) ++{ ++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_P5_RGMII_TO_MT7530_MODE) || defined (CONFIG_ARCH_MT7623) ++ unsigned int pkt_cnt = 0; ++ int i = 0; ++#endif ++ seq_printf(seq, "\n <> \n"); ++ seq_printf(seq, " | \n"); ++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++ seq_printf(seq, "+-----------------------------------------------+\n"); ++ seq_printf(seq, "| <> |\n"); ++ seq_printf(seq, "+-----------------------------------------------+\n"); ++#else ++ seq_printf(seq, "+-----------------------------------------------+\n"); ++ seq_printf(seq, "| <> |\n"); ++ seq_printf(seq, "+-----------------------------------------------+\n"); ++ seq_printf(seq, " | \n"); ++ seq_printf(seq, "+-----------------------------------------------+\n"); ++ seq_printf(seq, "| <> |\n"); ++#if defined (CONFIG_RALINK_MT7620) ++ seq_printf(seq, "| GDMA1_TX_GPCNT : %010u (Tx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1304)); ++ seq_printf(seq, "| GDMA1_RX_GPCNT : %010u (Rx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1324)); ++ seq_printf(seq, "| |\n"); ++ seq_printf(seq, "| GDMA1_TX_SKIPCNT: %010u (skip) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1308)); ++ seq_printf(seq, "| GDMA1_TX_COLCNT : %010u (collision) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x130c)); ++ seq_printf(seq, "| GDMA1_RX_OERCNT : %010u (overflow) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1328)); ++ seq_printf(seq, "| GDMA1_RX_FERCNT : %010u (FCS error) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x132c)); ++ seq_printf(seq, "| GDMA1_RX_SERCNT : %010u (too short) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1330)); ++ seq_printf(seq, "| GDMA1_RX_LERCNT : %010u (too long) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1334)); ++ seq_printf(seq, "| GDMA1_RX_CERCNT : %010u (l3/l4 checksum) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1338)); ++ seq_printf(seq, "| GDMA1_RX_FCCNT : %010u (flow control) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x133c)); ++ ++ seq_printf(seq, "| |\n"); ++ seq_printf(seq, "| GDMA2_TX_GPCNT : %010u (Tx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1344)); ++ seq_printf(seq, "| GDMA2_RX_GPCNT : %010u (Rx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1364)); ++ seq_printf(seq, "| |\n"); ++ seq_printf(seq, "| GDMA2_TX_SKIPCNT: %010u (skip) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1348)); ++ seq_printf(seq, "| GDMA2_TX_COLCNT : %010u (collision) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x134c)); ++ seq_printf(seq, "| GDMA2_RX_OERCNT : %010u (overflow) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1368)); ++ seq_printf(seq, "| GDMA2_RX_FERCNT : %010u (FCS error) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x136c)); ++ seq_printf(seq, "| GDMA2_RX_SERCNT : %010u (too short) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1370)); ++ seq_printf(seq, "| GDMA2_RX_LERCNT : %010u (too long) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1374)); ++ seq_printf(seq, "| GDMA2_RX_CERCNT : %010u (l3/l4 checksum) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1378)); ++ seq_printf(seq, "| GDMA2_RX_FCCNT : %010u (flow control) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x137c)); ++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++ seq_printf(seq, "| GDMA1_RX_GBCNT : %010u (Rx Good Bytes) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2400)); ++ seq_printf(seq, "| GDMA1_RX_GPCNT : %010u (Rx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2408)); ++ seq_printf(seq, "| GDMA1_RX_OERCNT : %010u (overflow error) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2410)); ++ seq_printf(seq, "| GDMA1_RX_FERCNT : %010u (FCS error) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2414)); ++ seq_printf(seq, "| GDMA1_RX_SERCNT : %010u (too short) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2418)); ++ seq_printf(seq, "| GDMA1_RX_LERCNT : %010u (too long) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x241C)); ++ seq_printf(seq, "| GDMA1_RX_CERCNT : %010u (checksum error) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2420)); ++ seq_printf(seq, "| GDMA1_RX_FCCNT : %010u (flow control) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2424)); ++ seq_printf(seq, "| GDMA1_TX_SKIPCNT: %010u (about count) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2428)); ++ seq_printf(seq, "| GDMA1_TX_COLCNT : %010u (collision count) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x242C)); ++ seq_printf(seq, "| GDMA1_TX_GBCNT : %010u (Tx Good Bytes) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2430)); ++ seq_printf(seq, "| GDMA1_TX_GPCNT : %010u (Tx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2438)); ++ seq_printf(seq, "| |\n"); ++ seq_printf(seq, "| GDMA2_RX_GBCNT : %010u (Rx Good Bytes) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2440)); ++ seq_printf(seq, "| GDMA2_RX_GPCNT : %010u (Rx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2448)); ++ seq_printf(seq, "| GDMA2_RX_OERCNT : %010u (overflow error) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2450)); ++ seq_printf(seq, "| GDMA2_RX_FERCNT : %010u (FCS error) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2454)); ++ seq_printf(seq, "| GDMA2_RX_SERCNT : %010u (too short) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2458)); ++ seq_printf(seq, "| GDMA2_RX_LERCNT : %010u (too long) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x245C)); ++ seq_printf(seq, "| GDMA2_RX_CERCNT : %010u (checksum error) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2460)); ++ seq_printf(seq, "| GDMA2_RX_FCCNT : %010u (flow control) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2464)); ++ seq_printf(seq, "| GDMA2_TX_SKIPCNT: %010u (skip) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2468)); ++ seq_printf(seq, "| GDMA2_TX_COLCNT : %010u (collision) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x246C)); ++ seq_printf(seq, "| GDMA2_TX_GBCNT : %010u (Tx Good Bytes) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2470)); ++ seq_printf(seq, "| GDMA2_TX_GPCNT : %010u (Tx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2478)); ++#else ++ seq_printf(seq, "| GDMA_TX_GPCNT1 : %010u (Tx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x704)); ++ seq_printf(seq, "| GDMA_RX_GPCNT1 : %010u (Rx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x724)); ++ seq_printf(seq, "| |\n"); ++ seq_printf(seq, "| GDMA_TX_SKIPCNT1: %010u (skip) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x708)); ++ seq_printf(seq, "| GDMA_TX_COLCNT1 : %010u (collision) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x70c)); ++ seq_printf(seq, "| GDMA_RX_OERCNT1 : %010u (overflow) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x728)); ++ seq_printf(seq, "| GDMA_RX_FERCNT1 : %010u (FCS error) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x72c)); ++ seq_printf(seq, "| GDMA_RX_SERCNT1 : %010u (too short) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x730)); ++ seq_printf(seq, "| GDMA_RX_LERCNT1 : %010u (too long) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x734)); ++ seq_printf(seq, "| GDMA_RX_CERCNT1 : %010u (l3/l4 checksum) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x738)); ++ seq_printf(seq, "| GDMA_RX_FCCNT1 : %010u (flow control) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x73c)); ++ ++#endif ++ seq_printf(seq, "+-----------------------------------------------+\n"); ++#endif ++ ++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) ++ ++ seq_printf(seq, " ^ \n"); ++ seq_printf(seq, " | Port6 Rx:%010u Good Pkt \n", ((p6_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4620)&0xFFFF))); ++ seq_printf(seq, " | Port6 Rx:%010u Bad Pkt \n", sysRegRead(RALINK_ETH_SW_BASE+0x4620)>>16); ++ seq_printf(seq, " | Port6 Tx:%010u Good Pkt \n", ((p6_tx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4610)&0xFFFF))); ++ seq_printf(seq, " | Port6 Tx:%010u Bad Pkt \n", sysRegRead(RALINK_ETH_SW_BASE+0x4610)>>16); ++#if defined (CONFIG_RALINK_MT7620) ++ ++ seq_printf(seq, " | Port7 Rx:%010u Good Pkt \n", ((p7_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4720)&0xFFFF))); ++ seq_printf(seq, " | Port7 Rx:%010u Bad Pkt \n", sysRegRead(RALINK_ETH_SW_BASE+0x4720)>>16); ++ seq_printf(seq, " | Port7 Tx:%010u Good Pkt \n", ((p7_tx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4710)&0xFFFF))); ++ seq_printf(seq, " | Port7 Tx:%010u Bad Pkt \n", sysRegRead(RALINK_ETH_SW_BASE+0x4710)>>16); ++#endif ++ seq_printf(seq, "+---------------------v-------------------------+\n"); ++ seq_printf(seq, "| P6 |\n"); ++ seq_printf(seq, "| <<10/100/1000 Embedded Switch>> |\n"); ++ seq_printf(seq, "| P0 P1 P2 P3 P4 P5 |\n"); ++ seq_printf(seq, "+-----------------------------------------------+\n"); ++ seq_printf(seq, " | | | | | | \n"); ++#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++ /* no built-in switch */ ++#else ++ seq_printf(seq, " ^ \n"); ++ seq_printf(seq, " | Port6 Rx:%08u Good Pkt \n", sysRegRead(RALINK_ETH_SW_BASE+0xE0)&0xFFFF); ++ seq_printf(seq, " | Port6 Tx:%08u Good Pkt \n", sysRegRead(RALINK_ETH_SW_BASE+0xE0)>>16); ++ seq_printf(seq, "+---------------------v-------------------------+\n"); ++ seq_printf(seq, "| P6 |\n"); ++ seq_printf(seq, "| <<10/100 Embedded Switch>> |\n"); ++ seq_printf(seq, "| P0 P1 P2 P3 P4 P5 |\n"); ++ seq_printf(seq, "+-----------------------------------------------+\n"); ++ seq_printf(seq, " | | | | | | \n"); ++#endif ++ ++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) ++ ++ seq_printf(seq, "Port0 Good RX=%010u Tx=%010u (Bad Rx=%010u Tx=%010u)\n", ((p0_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4020)&0xFFFF)), ((p0_tx_good_cnt << 16)| (sysRegRead(RALINK_ETH_SW_BASE+0x4010)&0xFFFF)), sysRegRead(RALINK_ETH_SW_BASE+0x4020)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x4010)>>16); ++ ++ seq_printf(seq, "Port1 Good RX=%010u Tx=%010u (Bad Rx=%010u Tx=%010u)\n", ((p1_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4120)&0xFFFF)), ((p1_tx_good_cnt << 16)| (sysRegRead(RALINK_ETH_SW_BASE+0x4110)&0xFFFF)), sysRegRead(RALINK_ETH_SW_BASE+0x4120)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x4110)>>16); ++ ++ seq_printf(seq, "Port2 Good RX=%010u Tx=%010u (Bad Rx=%010u Tx=%010u)\n", ((p2_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4220)&0xFFFF)), ((p2_tx_good_cnt << 16)| (sysRegRead(RALINK_ETH_SW_BASE+0x4210)&0xFFFF)), sysRegRead(RALINK_ETH_SW_BASE+0x4220)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x4210)>>16); ++ ++ seq_printf(seq, "Port3 Good RX=%010u Tx=%010u (Bad Rx=%010u Tx=%010u)\n", ((p3_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4320)&0xFFFF)), ((p3_tx_good_cnt << 16)| (sysRegRead(RALINK_ETH_SW_BASE+0x4310)&0xFFFF)), sysRegRead(RALINK_ETH_SW_BASE+0x4320)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x4310)>>16); ++ ++ seq_printf(seq, "Port4 Good RX=%010u Tx=%010u (Bad Rx=%010u Tx=%010u)\n", ((p4_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4420)&0xFFFF)), ((p4_tx_good_cnt << 16)| (sysRegRead(RALINK_ETH_SW_BASE+0x4410)&0xFFFF)), sysRegRead(RALINK_ETH_SW_BASE+0x4420)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x4410)>>16); ++ ++ seq_printf(seq, "Port5 Good RX=%010u Tx=%010u (Bad Rx=%010u Tx=%010u)\n", ((p5_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4520)&0xFFFF)), ((p5_tx_good_cnt << 16)| (sysRegRead(RALINK_ETH_SW_BASE+0x4510)&0xFFFF)), sysRegRead(RALINK_ETH_SW_BASE+0x4520)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x4510)>>16); ++ ++ seq_printf(seq, "Port0 KBytes RX=%010u Tx=%010u \n", ((p0_rx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4028) >> 10)), ((p0_tx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4018) >> 10))); ++ ++ seq_printf(seq, "Port1 KBytes RX=%010u Tx=%010u \n", ((p1_rx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4128) >> 10)), ((p1_tx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4118) >> 10))); ++ ++ seq_printf(seq, "Port2 KBytes RX=%010u Tx=%010u \n", ((p2_rx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4228) >> 10)), ((p2_tx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4218) >> 10))); ++ ++ seq_printf(seq, "Port3 KBytes RX=%010u Tx=%010u \n", ((p3_rx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4328) >> 10)), ((p3_tx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4318) >> 10))); ++ ++ seq_printf(seq, "Port4 KBytes RX=%010u Tx=%010u \n", ((p4_rx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4428) >> 10)), ((p4_tx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4418) >> 10))); ++ ++ seq_printf(seq, "Port5 KBytes RX=%010u Tx=%010u \n", ((p5_rx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4528) >> 10)), ((p5_tx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4518) >> 10))); ++ ++#if defined (CONFIG_P5_RGMII_TO_MT7530_MODE) ++#define DUMP_EACH_PORT(base) \ ++ for(i=0; i < 7;i++) { \ ++ mii_mgr_read(31, (base) + (i*0x100), &pkt_cnt); \ ++ seq_printf(seq, "%8u ", pkt_cnt); \ ++ } \ ++ seq_printf(seq, "\n"); ++ seq_printf(seq, "========================================[MT7530] READ CLEAR========================\n"); ++ ++ seq_printf(seq, "===================== %8s %8s %8s %8s %8s %8s %8s\n","Port0", "Port1", "Port2", "Port3", "Port4", "Port5", "Port6"); ++ seq_printf(seq, "Tx Drop Packet :"); DUMP_EACH_PORT(0x4000); ++ //seq_printf(seq, "Tx CRC Error :"); DUMP_EACH_PORT(0x4004); ++ seq_printf(seq, "Tx Unicast Packet :"); DUMP_EACH_PORT(0x4008); ++ seq_printf(seq, "Tx Multicast Packet :"); DUMP_EACH_PORT(0x400C); ++ seq_printf(seq, "Tx Broadcast Packet :"); DUMP_EACH_PORT(0x4010); ++ //seq_printf(seq, "Tx Collision Event :"); DUMP_EACH_PORT(0x4014); ++ seq_printf(seq, "Tx Pause Packet :"); DUMP_EACH_PORT(0x402C); ++ seq_printf(seq, "Rx Drop Packet :"); DUMP_EACH_PORT(0x4060); ++ seq_printf(seq, "Rx Filtering Packet :"); DUMP_EACH_PORT(0x4064); ++ seq_printf(seq, "Rx Unicast Packet :"); DUMP_EACH_PORT(0x4068); ++ seq_printf(seq, "Rx Multicast Packet :"); DUMP_EACH_PORT(0x406C); ++ seq_printf(seq, "Rx Broadcast Packet :"); DUMP_EACH_PORT(0x4070); ++ seq_printf(seq, "Rx Alignment Error :"); DUMP_EACH_PORT(0x4074); ++ seq_printf(seq, "Rx CRC Error :"); DUMP_EACH_PORT(0x4078); ++ seq_printf(seq, "Rx Undersize Error :"); DUMP_EACH_PORT(0x407C); ++ //seq_printf(seq, "Rx Fragment Error :"); DUMP_EACH_PORT(0x4080); ++ //seq_printf(seq, "Rx Oversize Error :"); DUMP_EACH_PORT(0x4084); ++ //seq_printf(seq, "Rx Jabber Error :"); DUMP_EACH_PORT(0x4088); ++ seq_printf(seq, "Rx Pause Packet :"); DUMP_EACH_PORT(0x408C); ++ mii_mgr_write(31, 0x4fe0, 0xf0); ++ mii_mgr_write(31, 0x4fe0, 0x800000f0); ++#endif ++ ++ ++#elif defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++ seq_printf(seq, "Port0 Good Pkt Cnt: RX=%08u Tx=%08u (Bad Pkt Cnt: Rx=%08u Tx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xE8)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0x150)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xE8)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x150)>>16); ++ ++ seq_printf(seq, "Port1 Good Pkt Cnt: RX=%08u Tx=%08u (Bad Pkt Cnt: Rx=%08u Tx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xEC)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0x154)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xEC)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x154)>>16); ++ ++ seq_printf(seq, "Port2 Good Pkt Cnt: RX=%08u Tx=%08u (Bad Pkt Cnt: Rx=%08u Tx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xF0)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0x158)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xF0)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x158)>>16); ++ ++ seq_printf(seq, "Port3 Good Pkt Cnt: RX=%08u Tx=%08u (Bad Pkt Cnt: Rx=%08u Tx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xF4)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0x15C)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xF4)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x15c)>>16); ++ ++ seq_printf(seq, "Port4 Good Pkt Cnt: RX=%08u Tx=%08u (Bad Pkt Cnt: Rx=%08u Tx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xF8)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0x160)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xF8)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x160)>>16); ++ ++ seq_printf(seq, "Port5 Good Pkt Cnt: RX=%08u Tx=%08u (Bad Pkt Cnt: Rx=%08u Tx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xFC)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0x164)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xFC)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x164)>>16); ++#elif defined (CONFIG_RALINK_RT3883) ++ /* no built-in switch */ ++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++ ++#define DUMP_EACH_PORT(base) \ ++ for(i=0; i < 7;i++) { \ ++ mii_mgr_read(31, (base) + (i*0x100), &pkt_cnt); \ ++ seq_printf(seq, "%8u ", pkt_cnt); \ ++ } \ ++ seq_printf(seq, "\n"); ++ ++#if defined (CONFIG_RALINK_MT7621) /* TODO: need to update to use MT7530 compiler flag */ ++ if(sysRegRead(0xbe00000c & (1<<16)))//MCM ++#endif ++ { ++ seq_printf(seq, "===================== %8s %8s %8s %8s %8s %8s %8s\n","Port0", "Port1", "Port2", "Port3", "Port4", "Port5", "Port6"); ++ seq_printf(seq, "Tx Drop Packet :"); DUMP_EACH_PORT(0x4000); ++ seq_printf(seq, "Tx CRC Error :"); DUMP_EACH_PORT(0x4004); ++ seq_printf(seq, "Tx Unicast Packet :"); DUMP_EACH_PORT(0x4008); ++ seq_printf(seq, "Tx Multicast Packet :"); DUMP_EACH_PORT(0x400C); ++ seq_printf(seq, "Tx Broadcast Packet :"); DUMP_EACH_PORT(0x4010); ++ seq_printf(seq, "Tx Collision Event :"); DUMP_EACH_PORT(0x4014); ++ seq_printf(seq, "Tx Pause Packet :"); DUMP_EACH_PORT(0x402C); ++ seq_printf(seq, "Rx Drop Packet :"); DUMP_EACH_PORT(0x4060); ++ seq_printf(seq, "Rx Filtering Packet :"); DUMP_EACH_PORT(0x4064); ++ seq_printf(seq, "Rx Unicast Packet :"); DUMP_EACH_PORT(0x4068); ++ seq_printf(seq, "Rx Multicast Packet :"); DUMP_EACH_PORT(0x406C); ++ seq_printf(seq, "Rx Broadcast Packet :"); DUMP_EACH_PORT(0x4070); ++ seq_printf(seq, "Rx Alignment Error :"); DUMP_EACH_PORT(0x4074); ++ seq_printf(seq, "Rx CRC Error :"); DUMP_EACH_PORT(0x4078); ++ seq_printf(seq, "Rx Undersize Error :"); DUMP_EACH_PORT(0x407C); ++ seq_printf(seq, "Rx Fragment Error :"); DUMP_EACH_PORT(0x4080); ++ seq_printf(seq, "Rx Oversize Error :"); DUMP_EACH_PORT(0x4084); ++ seq_printf(seq, "Rx Jabber Error :"); DUMP_EACH_PORT(0x4088); ++ seq_printf(seq, "Rx Pause Packet :"); DUMP_EACH_PORT(0x408C); ++ mii_mgr_write(31, 0x4fe0, 0xf0); ++ mii_mgr_write(31, 0x4fe0, 0x800000f0); ++ } ++#if defined (CONFIG_RALINK_MT7621) /* TODO: need to update to use MT7530 compiler flag */ ++ else { ++ seq_printf(seq, "no built-in switch\n"); ++ } ++#endif ++ ++#else /* RT305x, RT3352 */ ++ seq_printf(seq, "Port0: Good Pkt Cnt: RX=%08u (Bad Pkt Cnt: Rx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xE8)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xE8)>>16); ++ seq_printf(seq, "Port1: Good Pkt Cnt: RX=%08u (Bad Pkt Cnt: Rx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xEC)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xEC)>>16); ++ seq_printf(seq, "Port2: Good Pkt Cnt: RX=%08u (Bad Pkt Cnt: Rx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xF0)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xF0)>>16); ++ seq_printf(seq, "Port3: Good Pkt Cnt: RX=%08u (Bad Pkt Cnt: Rx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xF4)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xF4)>>16); ++ seq_printf(seq, "Port4: Good Pkt Cnt: RX=%08u (Bad Pkt Cnt: Rx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xF8)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xF8)>>16); ++ seq_printf(seq, "Port5: Good Pkt Cnt: RX=%08u (Bad Pkt Cnt: Rx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xFC)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xFC)>>16); ++#endif ++ seq_printf(seq, "\n"); ++ ++ return 0; ++} ++ ++static int switch_count_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, EswCntRead, NULL); ++} ++ ++static const struct file_operations switch_count_fops = { ++ .owner = THIS_MODULE, ++ .open = switch_count_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release ++}; ++ ++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/ ++/* ++ * proc write procedure ++ */ ++static ssize_t change_phyid(struct file *file, const char __user *buffer, ++ size_t count, loff_t *data) ++{ ++ char buf[32]; ++ struct net_device *cur_dev_p; ++ END_DEVICE *ei_local; ++ char if_name[64]; ++ unsigned int phy_id; ++ ++ if (count > 32) ++ count = 32; ++ memset(buf, 0, 32); ++ if (copy_from_user(buf, buffer, count)) ++ return -EFAULT; ++ ++ /* determine interface name */ ++ strcpy(if_name, DEV_NAME); /* "eth2" by default */ ++ if(isalpha(buf[0])) ++ sscanf(buf, "%s %d", if_name, &phy_id); ++ else ++ phy_id = simple_strtol(buf, 0, 10); ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ cur_dev_p = dev_get_by_name(&init_net, DEV_NAME); ++#else ++ cur_dev_p = dev_get_by_name(DEV_NAME); ++#endif ++ if (cur_dev_p == NULL) ++ return -EFAULT; ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ ei_local = netdev_priv(cur_dev_p); ++#else ++ ei_local = cur_dev_p->priv; ++#endif ++ ei_local->mii_info.phy_id = (unsigned char)phy_id; ++ return count; ++} ++ ++#if defined(CONFIG_PSEUDO_SUPPORT) ++static ssize_t change_gmac2_phyid(struct file *file, const char __user *buffer, ++ size_t count, loff_t *data) ++{ ++ char buf[32]; ++ struct net_device *cur_dev_p; ++ PSEUDO_ADAPTER *pPseudoAd; ++ char if_name[64]; ++ unsigned int phy_id; ++ ++ if (count > 32) ++ count = 32; ++ memset(buf, 0, 32); ++ if (copy_from_user(buf, buffer, count)) ++ return -EFAULT; ++ /* determine interface name */ ++ strcpy(if_name, DEV2_NAME); /* "eth3" by default */ ++ if(isalpha(buf[0])) ++ sscanf(buf, "%s %d", if_name, &phy_id); ++ else ++ phy_id = simple_strtol(buf, 0, 10); ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ cur_dev_p = dev_get_by_name(&init_net, DEV2_NAME); ++#else ++ cur_dev_p = dev_get_by_name(DEV2_NAMEj); ++#endif ++ if (cur_dev_p == NULL) ++ return -EFAULT; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ pPseudoAd = netdev_priv(cur_dev_p); ++#else ++ pPseudoAd = cur_dev_p->priv; ++#endif ++ pPseudoAd->mii_info.phy_id = (unsigned char)phy_id; ++ return count; ++} ++ ++static struct file_operations gmac2_fops = { ++ .owner = THIS_MODULE, ++ .write = change_gmac2_phyid ++}; ++#endif ++#endif ++ ++static int gmac_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, RegReadMain, NULL); ++} ++ ++static struct file_operations gmac_fops = { ++ .owner = THIS_MODULE, ++ .open = gmac_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++#if defined (CONFIG_ETHTOOL) ++ .write = change_phyid, ++#endif ++ .release = single_release ++}; ++ ++#if defined (TASKLET_WORKQUEUE_SW) ++extern int init_schedule; ++extern int working_schedule; ++static int ScheduleRead(struct seq_file *seq, void *v) ++{ ++ if (init_schedule == 1) ++ seq_printf(seq, "Initialize Raeth with workqueque<%d>\n", init_schedule); ++ else ++ seq_printf(seq, "Initialize Raeth with tasklet<%d>\n", init_schedule); ++ if (working_schedule == 1) ++ seq_printf(seq, "Raeth is running at workqueque<%d>\n", working_schedule); ++ else ++ seq_printf(seq, "Raeth is running at tasklet<%d>\n", working_schedule); ++ ++ return 0; ++} ++ ++static ssize_t ScheduleWrite(struct file *file, const char __user *buffer, ++ size_t count, loff_t *data) ++{ ++ char buf[2]; ++ int old; ++ ++ if (copy_from_user(buf, buffer, count)) ++ return -EFAULT; ++ old = init_schedule; ++ init_schedule = simple_strtol(buf, 0, 10); ++ printk("Change Raeth initial schedule from <%d> to <%d>\n! Not running schedule at present !\n", ++ old, init_schedule); ++ ++ return count; ++} ++ ++static int schedule_switch_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, ScheduleRead, NULL); ++} ++ ++static const struct file_operations schedule_sw_fops = { ++ .owner = THIS_MODULE, ++ .open = schedule_switch_open, ++ .read = seq_read, ++ .write = ScheduleWrite, ++ .llseek = seq_lseek, ++ .release = single_release ++}; ++#endif ++ ++#if defined(CONFIG_RAETH_PDMA_DVT) ++static int PdmaDvtRead(struct seq_file *seq, void *v) ++{ ++ seq_printf(seq, "g_pdma_dvt_show_config = 0x%x\n", pdma_dvt_get_show_config()); ++ seq_printf(seq, "g_pdma_dvt_rx_test_config = 0x%x\n", pdma_dvt_get_rx_test_config()); ++ seq_printf(seq, "g_pdma_dvt_tx_test_config = 0x%x\n", pdma_dvt_get_tx_test_config()); ++ ++ return 0; ++} ++ ++static int PdmaDvtOpen(struct inode *inode, struct file *file) ++{ ++ return single_open(file, PdmaDvtRead, NULL); ++} ++ ++static ssize_t PdmaDvtWrite(struct file *file, const char __user *buffer, ++ size_t count, loff_t *data) ++{ ++ char buf[32]; ++ char *pBuf; ++ int len = count; ++ int x = 0,y = 0; ++ char *pToken = NULL; ++ char *pDelimiter = " \t"; ++ ++ printk("write parameter len = %d\n\r", (int)len); ++ if(len >= sizeof(buf)){ ++ printk("input handling fail!\n"); ++ len = sizeof(buf) - 1; ++ return -1; ++ } ++ ++ if(copy_from_user(buf, buffer, len)){ ++ return -EFAULT; ++ } ++ buf[len] = '\0'; ++ printk("write parameter data = %s\n\r", buf); ++ ++ pBuf = buf; ++ pToken = strsep(&pBuf, pDelimiter); ++ x = NULL != pToken ? simple_strtol(pToken, NULL, 16) : 0; ++ ++ pToken = strsep(&pBuf, "\t\n "); ++ if(pToken != NULL){ ++ y = NULL != pToken ? simple_strtol(pToken, NULL, 16) : 0; ++ printk("y = 0x%08x \n\r", y); ++ } ++ ++ if ( (sizeof(pdma_dvt_dbg_func)/sizeof(pdma_dvt_dbg_func[0]) > x) && NULL != pdma_dvt_dbg_func[x]) ++ { ++ (*pdma_dvt_dbg_func[x])(x, y); ++ } ++ else ++ { ++ printk("no handler defined for command id(0x%08x)\n\r", x); ++ } ++ ++ printk("x(0x%08x), y(0x%08x)\n", x, y); ++ ++ return len; ++} ++ ++static const struct file_operations pdma_dev_sw_fops = { ++ .owner = THIS_MODULE, ++ .open = PdmaDvtOpen, ++ .read = seq_read, ++ .write = PdmaDvtWrite ++}; ++#endif //#if defined(CONFIG_RAETH_PDMA_DVT) ++ ++int debug_proc_init(void) ++{ ++ if (procRegDir == NULL) ++ procRegDir = proc_mkdir(PROCREG_DIR, NULL); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++ if ((procGmac = create_proc_entry(PROCREG_GMAC, 0, procRegDir))) ++ procGmac->proc_fops = &gmac_fops; ++ else ++#else ++ if (!(procGmac = proc_create(PROCREG_GMAC, 0, procRegDir, &gmac_fops))) ++#endif ++ printk("!! FAIL to create %s PROC !!\n", PROCREG_GMAC); ++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/ ++#if defined(CONFIG_PSEUDO_SUPPORT) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++ if ((procGmac2 = create_proc_entry(PROCREG_GMAC2, 0, procRegDir))) ++ procGmac2->proc_fops = &gmac2_fops; ++ else ++#else ++ if (!(procGmac2 = proc_create(PROCREG_GMAC2, 0, procRegDir, &gmac2_fops))) ++#endif ++ printk("!! FAIL to create %s PROC !!\n", PROCREG_GMAC2); ++#endif ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++ if ((procSkbFree = create_proc_entry(PROCREG_SKBFREE, 0, procRegDir))) ++ procSkbFree->proc_fops = &skb_free_fops; ++ else ++#else ++ if (!(procSkbFree = proc_create(PROCREG_SKBFREE, 0, procRegDir, &skb_free_fops))) ++#endif ++ printk("!! FAIL to create %s PROC !!\n", PROCREG_SKBFREE); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++ if ((procTxRing = create_proc_entry(PROCREG_TXRING, 0, procRegDir))) ++ procTxRing->proc_fops = &tx_ring_fops; ++ else ++#else ++ if (!(procTxRing = proc_create(PROCREG_TXRING, 0, procRegDir, &tx_ring_fops))) ++#endif ++ printk("!! FAIL to create %s PROC !!\n", PROCREG_TXRING); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++ if ((procRxRing = create_proc_entry(PROCREG_RXRING, 0, procRegDir))) ++ procRxRing->proc_fops = &rx_ring_fops; ++ else ++#else ++ if (!(procRxRing = proc_create(PROCREG_RXRING, 0, procRegDir, &rx_ring_fops))) ++#endif ++ printk("!! FAIL to create %s PROC !!\n", PROCREG_RXRING); ++ ++#if defined (CONFIG_RAETH_HW_LRO) || defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++ if ((procRxRing1 = create_proc_entry(PROCREG_RXRING1, 0, procRegDir))) ++ procRxRing1->proc_fops = &rx_ring1_fops; ++ else ++#else ++ if (!(procRxRing1 = proc_create(PROCREG_RXRING1, 0, procRegDir, &rx_ring1_fops))) ++#endif ++ printk("!! FAIL to create %s PROC !!\n", PROCREG_RXRING1); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++ if ((procRxRing2 = create_proc_entry(PROCREG_RXRING2, 0, procRegDir))) ++ procRxRing2->proc_fops = &rx_ring2_fops; ++ else ++#else ++ if (!(procRxRing2 = proc_create(PROCREG_RXRING2, 0, procRegDir, &rx_ring2_fops))) ++#endif ++ printk("!! FAIL to create %s PROC !!\n", PROCREG_RXRING2); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++ if ((procRxRing3 = create_proc_entry(PROCREG_RXRING3, 0, procRegDir))) ++ procRxRing3->proc_fops = &rx_ring3_fops; ++ else ++#else ++ if (!(procRxRing3 = proc_create(PROCREG_RXRING3, 0, procRegDir, &rx_ring3_fops))) ++#endif ++ printk("!! FAIL to create %s PROC !!\n", PROCREG_RXRING3); ++#endif /* CONFIG_RAETH_HW_LRO */ ++ ++#if defined (CONFIG_MIPS) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++ if ((procSysCP0 = create_proc_entry(PROCREG_CP0, 0, procRegDir))) ++ procSysCP0->proc_fops = &cp0_reg_fops; ++ else ++#else ++ if (!(procSysCP0 = proc_create(PROCREG_CP0, 0, procRegDir, &cp0_reg_fops))) ++#endif ++ printk("!! FAIL to create %s PROC !!\n", PROCREG_CP0); ++#endif ++ ++#if defined(CONFIG_RAETH_TSO) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++ if ((procNumOfTxd = create_proc_entry(PROCREG_NUM_OF_TXD, 0, procRegDir))) ++ procNumOfTxd->proc_fops = &tso_txd_num_fops; ++ else ++#else ++ if (!(procNumOfTxd = proc_create(PROCREG_NUM_OF_TXD, 0, procRegDir, &tso_txd_num_fops))) ++#endif ++ printk("!! FAIL to create %s PROC !!\n", PROCREG_NUM_OF_TXD); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++ if ((procTsoLen = create_proc_entry(PROCREG_TSO_LEN, 0, procRegDir))) ++ procTsoLen->proc_fops = &tso_len_fops; ++ else ++#else ++ if (!(procTsoLen = proc_create(PROCREG_TSO_LEN, 0, procRegDir, &tso_len_fops))) ++#endif ++ printk("!! FAIL to create %s PROC !!\n", PROCREG_TSO_LEN); ++#endif ++ ++#if defined(CONFIG_RAETH_LRO) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++ if ((procLroStats = create_proc_entry(PROCREG_LRO_STATS, 0, procRegDir))) ++ procLroStats->proc_fops = &lro_stats_fops; ++ else ++#else ++ if (!(procLroStats = proc_create(PROCREG_LRO_STATS, 0, procRegDir, &lro_stats_fops))) ++#endif ++ printk("!! FAIL to create %s PROC !!\n", PROCREG_LRO_STATS); ++#endif ++ ++#if defined(CONFIG_RAETH_HW_LRO) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++ if ((procHwLroStats = create_proc_entry(PROCREG_HW_LRO_STATS, 0, procRegDir))) ++ procHwLroStats->proc_fops = &hw_lro_stats_fops; ++ else ++#else ++ if (!(procHwLroStats = proc_create(PROCREG_HW_LRO_STATS, 0, procRegDir, &hw_lro_stats_fops))) ++#endif ++ printk("!! FAIL to create %s PROC !!\n", PROCREG_HW_LRO_STATS); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++ if ((procHwLroAutoTlb = create_proc_entry(PROCREG_HW_LRO_AUTO_TLB, 0, procRegDir))) ++ procHwLroAutoTlb->proc_fops = &hw_lro_auto_tlb_fops; ++ else ++#else ++ if (!(procHwLroAutoTlb = proc_create(PROCREG_HW_LRO_AUTO_TLB, 0, procRegDir, &hw_lro_auto_tlb_fops))) ++#endif ++ printk("!! FAIL to create %s PROC !!\n", PROCREG_HW_LRO_AUTO_TLB); ++#endif /* CONFIG_RAETH_HW_LRO */ ++ ++#if defined(CONFIG_RAETH_QOS) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++ if ((procRaQOS = create_proc_entry(PROCREG_RAQOS, 0, procRegDir))) ++ procRaQOS->proc_fops = &raeth_qos_fops; ++ else ++#else ++ if (!(procRaQOS = proc_create(PROCREG_RAQOS, 0, procRegDir, &raeth_qos_fops))) ++#endif ++ printk("!! FAIL to create %s PROC !!\n", PROCREG_RAQOS); ++#endif ++ ++#if defined(CONFIG_USER_SNMPD) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++ if ((procRaSnmp = create_proc_entry(PROCREG_SNMP, S_IRUGO, procRegDir))) ++ procRaSnmp->proc_fops = &ra_snmp_seq_fops; ++ else ++#else ++ if (!(procRaSnmp = proc_create(PROCREG_SNMP, S_IRUGO, procRegDir, &ra_snmp_seq_fops))) ++#endif ++ printk("!! FAIL to create %s PROC !!\n", PROCREG_SNMP); ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++ if ((procEswCnt = create_proc_entry(PROCREG_ESW_CNT, 0, procRegDir))) ++ procEswCnt->proc_fops = &switch_count_fops; ++ else ++#else ++ if (!(procEswCnt = proc_create(PROCREG_ESW_CNT, 0, procRegDir, &switch_count_fops))) ++#endif ++ printk("!! FAIL to create %s PROC !!\n", PROCREG_ESW_CNT); ++ ++#if defined (TASKLET_WORKQUEUE_SW) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++ if ((procSCHE = create_proc_entry(PROCREG_SCHE, 0, procRegDir))) ++ procSCHE->proc_fops = &schedule_sw_fops; ++ else ++#else ++ if (!(procSCHE = proc_create(PROCREG_SCHE, 0, procRegDir, &schedule_sw_fops))) ++#endif ++ printk("!! FAIL to create %s PROC !!\n", PROCREG_SCHE); ++#endif ++ ++#if defined(CONFIG_RAETH_PDMA_DVT) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ++ if ((procPdmaDvt = create_proc_entry(PROCREG_PDMA_DVT, 0, procRegDir))) ++ procPdmaDvt->proc_fops = &pdma_dev_sw_fops; ++ else ++#else ++ if (!(procPdmaDvt = proc_create(PROCREG_PDMA_DVT, 0, procRegDir, &pdma_dev_sw_fops ))) ++#endif ++ printk("!! FAIL to create %s PROC !!\n", PROCREG_PDMA_DVT); ++#endif //#if defined(CONFIG_RAETH_PDMA_DVT) ++ ++ printk(KERN_ALERT "PROC INIT OK!\n"); ++ return 0; ++} ++ ++void debug_proc_exit(void) ++{ ++ ++ if (procSysCP0) ++ remove_proc_entry(PROCREG_CP0, procRegDir); ++ ++ if (procGmac) ++ remove_proc_entry(PROCREG_GMAC, procRegDir); ++#if defined(CONFIG_PSEUDO_SUPPORT) && defined(CONFIG_ETHTOOL) ++ if (procGmac) ++ remove_proc_entry(PROCREG_GMAC, procRegDir); ++#endif ++ if (procSkbFree) ++ remove_proc_entry(PROCREG_SKBFREE, procRegDir); ++ ++ if (procTxRing) ++ remove_proc_entry(PROCREG_TXRING, procRegDir); ++ ++ if (procRxRing) ++ remove_proc_entry(PROCREG_RXRING, procRegDir); ++ ++#if defined(CONFIG_RAETH_TSO) ++ if (procNumOfTxd) ++ remove_proc_entry(PROCREG_NUM_OF_TXD, procRegDir); ++ ++ if (procTsoLen) ++ remove_proc_entry(PROCREG_TSO_LEN, procRegDir); ++#endif ++ ++#if defined(CONFIG_RAETH_LRO) ++ if (procLroStats) ++ remove_proc_entry(PROCREG_LRO_STATS, procRegDir); ++#endif ++ ++#if defined(CONFIG_RAETH_QOS) ++ if (procRaQOS) ++ remove_proc_entry(PROCREG_RAQOS, procRegDir); ++ if (procRaFeIntr) ++ remove_proc_entry(PROCREG_RXDONE_INTR, procRegDir); ++ if (procRaEswIntr) ++ remove_proc_entry(PROCREG_ESW_INTR, procRegDir); ++#endif ++ ++#if defined(CONFIG_USER_SNMPD) ++ if (procRaSnmp) ++ remove_proc_entry(PROCREG_SNMP, procRegDir); ++#endif ++ ++ if (procEswCnt) ++ remove_proc_entry(PROCREG_ESW_CNT, procRegDir); ++ ++ //if (procRegDir) ++ //remove_proc_entry(PROCREG_DIR, 0); ++ ++ printk(KERN_ALERT "proc exit\n"); ++} ++EXPORT_SYMBOL(procRegDir); +diff --git a/drivers/net/ethernet/raeth/ra_mac.h b/drivers/net/ethernet/raeth/ra_mac.h +new file mode 100644 +index 0000000..66b32d3 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/ra_mac.h +@@ -0,0 +1,57 @@ ++#ifndef RA_MAC_H ++#define RA_MAC_H ++ ++void ra2880stop(END_DEVICE *ei_local); ++void ra2880MacAddressSet(unsigned char p[6]); ++void ra2880Mac2AddressSet(unsigned char p[6]); ++void ethtool_init(struct net_device *dev); ++ ++void ra2880EnableInterrupt(void); ++ ++void dump_qos(void); ++void dump_reg(struct seq_file *s); ++void dump_cp0(void); ++ ++int debug_proc_init(void); ++void debug_proc_exit(void); ++ ++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) ++void enable_auto_negotiate(int unused); ++#else ++void enable_auto_negotiate(int ge); ++#endif ++ ++void rt2880_gmac_hard_reset(void); ++ ++int TsoLenUpdate(int tso_len); ++int NumOfTxdUpdate(int num_of_txd); ++ ++#ifdef CONFIG_RAETH_LRO ++int LroStatsUpdate(struct net_lro_mgr *lro_mgr, bool all_flushed); ++#endif ++#ifdef CONFIG_RAETH_HW_LRO ++int HwLroStatsUpdate(unsigned int ring_num, unsigned int agg_cnt, unsigned int agg_size); ++#if defined(CONFIG_RAETH_HW_LRO_REASON_DBG) ++#define HW_LRO_AGG_FLUSH (1) ++#define HW_LRO_AGE_FLUSH (2) ++#define HW_LRO_NOT_IN_SEQ_FLUSH (3) ++#define HW_LRO_TIMESTAMP_FLUSH (4) ++#define HW_LRO_NON_RULE_FLUSH (5) ++int HwLroFlushStatsUpdate(unsigned int ring_num, unsigned int flush_reason); ++#endif /* CONFIG_RAETH_HW_LRO_REASON_DBG */ ++typedef int (*HWLRO_DBG_FUNC)(int par1, int par2); ++int hwlro_agg_cnt_ctrl(int par1, int par2); ++int hwlro_agg_time_ctrl(int par1, int par2); ++int hwlro_age_time_ctrl(int par1, int par2); ++int hwlro_pkt_int_alpha_ctrl(int par1, int par2); ++int hwlro_threshold_ctrl(int par1, int par2); ++int hwlro_fix_setting_switch_ctrl(int par1, int par2); ++#endif /* CONFIG_RAETH_HW_LRO */ ++int getnext(const char *src, int separator, char *dest); ++int str_to_ip(unsigned int *ip, const char *str); ++ ++#if defined(CONFIG_RAETH_PDMA_DVT) ++typedef int (*PDMA_DBG_FUNC)(int par1, int par2); ++#endif //#if defined(CONFIG_RAETH_PDMA_DVT) ++#endif +diff --git a/drivers/net/ethernet/raeth/ra_netlink.c b/drivers/net/ethernet/raeth/ra_netlink.c +new file mode 100644 +index 0000000..f7c3650 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/ra_netlink.c +@@ -0,0 +1,142 @@ ++// for netlink header ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "csr_netlink.h" ++#include "ra2882ethreg.h" ++#include "ra_netlink.h" ++ ++static struct sock *csr_msg_socket = NULL; // synchronize socket for netlink use ++unsigned int flags; ++ ++void rt2880_csr_receiver(struct sock *sk, int len) ++{ ++ struct sk_buff *skb; ++ int err; ++ struct nlmsghdr *nlh; ++ unsigned int reg_value = 0; ++ CSR_MSG *csrmsg; ++ RAETH_PRINT("csr netlink receiver!\n"); ++ skb = skb_recv_datagram(sk, 0, 1, &err); ++ ++ RAETH_PRINT("error no : %d\n", err); ++ ++ if (skb == NULL) { ++ printk("rt2880_csr_receiver(): No data received, error!\n"); ++ return; ++ } ++ ++ nlh = (struct nlmsghdr*)skb->data; ++ ++ csrmsg = NLMSG_DATA(nlh); ++ ++ if (csrmsg->enable == CSR_READ ) { ++ reg_value = sysRegRead(csrmsg->address); ++#if 0 ++ printk("raeth -- 0x%08x: 0x%08x\n", csrmsg->address, reg_value); ++#endif ++ } else if ( csrmsg->enable == CSR_WRITE ) { ++ sysRegWrite(csrmsg->address, csrmsg->default_value); ++ reg_value = sysRegRead(csrmsg->address); ++ } else if ( csrmsg->enable == CSR_TEST ) { ++ reg_value = sysRegRead(csrmsg->address); ++ printk("0x%08x: 0x%08x\n", (unsigned int)csrmsg->address, reg_value); ++ } ++ else ++ printk("drv: Command format error!\n"); ++ ++ csrmsg->default_value = reg_value; ++ ++ RAETH_PRINT("drv: rt2880_csr_msgsend() - msg to send!\n"); ++ ++ err = rt2880_csr_msgsend(csrmsg); ++ ++ if ( err == -2 ) ++ printk("drv: msg send error!\n"); ++ ++ skb_free_datagram(sk, skb); ++} ++ ++int rt2880_csr_msgsend(CSR_MSG* csrmsg) ++{ ++ struct sk_buff *skb; ++ struct nlmsghdr *nlh = NULL; ++ size_t size = 0; ++ struct sock *send_syncnl = csr_msg_socket; ++ ++ CSR_MSG* csr_reg; ++ if (send_syncnl == NULL) { ++ printk("drv: netlink_kernel_create() failed!\n"); ++ return -1; ++ } ++ ++ size = NLMSG_SPACE(sizeof(CSR_MSG)); ++ skb = alloc_skb(size, GFP_ATOMIC); ++ ++ if(!skb) ++ { ++ printk("rt2880_csr_msgsend() : error! msg structure not available\n"); ++ return -1; ++ } ++ ++ nlh = NLMSG_PUT(skb, 0, 0, RALINK_CSR_GROUP, size - sizeof(struct nlmsghdr)); ++ ++ if (!nlh) ++ { ++ printk("rt2880_csr_msgsend() : error! nlh structure not available\n"); ++ return -1; ++ } ++ ++ csr_reg = NLMSG_DATA(nlh); ++ if (!csr_reg) ++ { ++ printk("rt2880_csr_msgsend() : error! nlh structure not available\n"); ++ return -1; ++ } ++ ++ csr_reg->address = csrmsg->address; ++ csr_reg->default_value = csrmsg->default_value; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) ++ NETLINK_CB(skb).dst_group = RALINK_CSR_GROUP; ++#else ++ NETLINK_CB(skb).dst_groups = RALINK_CSR_GROUP; ++#endif ++ netlink_broadcast(send_syncnl, skb, 0, RALINK_CSR_GROUP, GFP_ATOMIC); ++ return 0; ++ ++nlmsg_failure: ++ return -2; ++} ++ ++int csr_netlink_init() ++{ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) ++ csr_msg_socket = netlink_kernel_create(NETLINK_CSR, RALINK_CSR_GROUP, rt2880_csr_receiver, THIS_MODULE); ++#else ++ csr_msg_socket = netlink_kernel_create(NETLINK_CSR, rt2880_csr_receiver); ++#endif ++ ++ if ( csr_msg_socket == NULL ) ++ printk("unable to create netlink socket!\n"); ++ else ++ printk("Netlink init ok!\n"); ++ return 0; ++} ++ ++void csr_netlink_end() ++{ ++ if (csr_msg_socket != NULL){ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) ++ sock_release(csr_msg_socket->sk_socket); ++#else ++ sock_release(csr_msg_socket->socket); ++#endif ++ printk("Netlink end...\n"); ++ } ++} +diff --git a/drivers/net/ethernet/raeth/ra_netlink.h b/drivers/net/ethernet/raeth/ra_netlink.h +new file mode 100644 +index 0000000..19ca71f +--- /dev/null ++++ b/drivers/net/ethernet/raeth/ra_netlink.h +@@ -0,0 +1,10 @@ ++#ifndef RA_NETLINK ++#define RA_NETLINK ++ ++#include "csr_netlink.h" ++int rt2880_csr_msgsend(CSR_MSG* csrmsg); ++void rt2880_csr_receiver(struct sock *sk, int len); ++int csr_netlink_init(void); ++void csr_netlink_end(void); ++ ++#endif +diff --git a/drivers/net/ethernet/raeth/ra_qos.c b/drivers/net/ethernet/raeth/ra_qos.c +new file mode 100644 +index 0000000..0a7d9c5 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/ra_qos.c +@@ -0,0 +1,655 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "ra_qos.h" ++#include "raether.h" ++#include "ra2882ethreg.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) ++#include "../../../net/nat/hw_nat/ra_nat.h" ++#endif ++ ++#define CONTI_TX_SEND_MAX_SIZE 1440 ++ ++/* ++ * set tx queue # to descriptor ++ */ ++void rt3052_tx_queue_init(unsigned long data) ++{ ++ /* define qos p */ ++ ++} ++ ++void rt3052_pse_port0_fc_clear(unsigned long data) ++{ ++ /* clear FE_INT_STATUS.PSE_P0_FC */ ++ ++} ++ ++inline int get_tx_ctx_idx(unsigned int ring_no, unsigned long *idx) ++{ ++ switch (ring_no) { ++ case RING0: ++ *idx = *(unsigned long*)TX_CTX_IDX0; ++ break; ++ case RING1: ++ *idx = *(unsigned long*)TX_CTX_IDX1; ++ break; ++ case RING2: ++ *idx = *(unsigned long*)TX_CTX_IDX2; ++ break; ++ case RING3: ++ *idx = *(unsigned long*)TX_CTX_IDX3; ++ break; ++ default: ++ printk("set_tx_ctx_idex error\n"); ++ return -1; ++ }; ++ return 0; ++} ++ ++inline int set_tx_ctx_idx(unsigned int ring_no, unsigned int idx) ++{ ++ switch (ring_no ) { ++ case RING0: ++ *(unsigned long*)TX_CTX_IDX0 = cpu_to_le32((u32)idx); ++ break; ++ case RING1: ++ *(unsigned long*)TX_CTX_IDX1 = cpu_to_le32((u32)idx); ++ break; ++ case RING2: ++ *(unsigned long*)TX_CTX_IDX2 = cpu_to_le32((u32)idx); ++ break; ++ case RING3: ++ *(unsigned long*)TX_CTX_IDX3 = cpu_to_le32((u32)idx); ++ break; ++ default: ++ printk("set_tx_ctx_idex error\n"); ++ return -1; ++ }; ++ ++ return 1; ++} ++ ++void get_tx_desc_and_dtx_idx(END_DEVICE* ei_local, int ring_no, unsigned long *tx_dtx_idx, struct PDMA_txdesc **tx_desc) ++{ ++ switch (ring_no) { ++ case RING0: ++ *tx_desc = ei_local->tx_ring0; ++ *tx_dtx_idx = *(unsigned long*)TX_DTX_IDX0; ++ break; ++ case RING1: ++ *tx_desc = ei_local->tx_ring1; ++ *tx_dtx_idx = *(unsigned long*)TX_DTX_IDX1; ++ break; ++ case RING2: ++ *tx_desc = ei_local->tx_ring2; ++ *tx_dtx_idx = *(unsigned long*)TX_DTX_IDX2; ++ break; ++ case RING3: ++ *tx_desc = ei_local->tx_ring3; ++ *tx_dtx_idx = *(unsigned long*)TX_DTX_IDX3; ++ break; ++ default: ++ printk("ring_no input error... %d\n", ring_no); ++ }; ++} ++ ++int fe_qos_packet_send(struct net_device *dev, struct sk_buff* skb, unsigned int ring_no, unsigned int qn, unsigned pn) ++{ ++ END_DEVICE* ei_local = netdev_priv(dev); ++ struct PDMA_txdesc* tx_desc; ++ unsigned int tx_cpu_owner_idx, tx_dtx_idx; ++ ++ unsigned int length=skb->len; ++ int ret; ++ unsigned long flags; ++ ++ //printk("fe_qos_packet_send: ring_no=%d qn=%d pn=%d\n", ring_no, qn, pn); ++ ++ switch ( ring_no ) { ++ case 0: ++ tx_desc = ei_local->tx_ring0; ++ tx_cpu_owner_idx = *(unsigned long*)TX_CTX_IDX0; ++ tx_dtx_idx = *(unsigned long*)TX_DTX_IDX0; ++ break; ++ case 1: ++ tx_desc = ei_local->tx_ring1; ++ tx_cpu_owner_idx = *(unsigned long*)TX_CTX_IDX1; ++ tx_dtx_idx = *(unsigned long*)TX_DTX_IDX1; ++ break; ++ case 2: ++ tx_desc = ei_local->tx_ring2; ++ tx_cpu_owner_idx = *(unsigned long*)TX_CTX_IDX2; ++ tx_dtx_idx = *(unsigned long*)TX_DTX_IDX2; ++ break; ++ case 3: ++ tx_desc = ei_local->tx_ring3; ++ tx_cpu_owner_idx = *(unsigned long*)TX_CTX_IDX3; ++ tx_dtx_idx = *(unsigned long*)TX_DTX_IDX3; ++ break; ++ default: ++ printk("ring_no input error... %d\n", ring_no); ++ return -1; ++ }; ++ ++ //printk("tx_cpu_owner_idx=%d tx_dtx_idx=%d\n", tx_cpu_owner_idx, tx_dtx_idx); ++ ++ if(tx_desc == NULL) { ++ printk("%s : txdesc is NULL\n", dev->name); ++ return -1; ++ } ++ ++ tx_desc[tx_cpu_owner_idx].txd_info1.SDP0 = virt_to_phys(skb->data); ++ tx_desc[tx_cpu_owner_idx].txd_info2.SDL0 = length; ++ tx_desc[tx_cpu_owner_idx].txd_info2.DDONE_bit = 0; ++ tx_desc[tx_cpu_owner_idx].txd_info4.PN = pn; ++ tx_desc[tx_cpu_owner_idx].txd_info4.QN = qn; ++ ++#ifdef CONFIG_RAETH_CHECKSUM_OFFLOAD ++ ei_local->tx_ring0[tx_cpu_owner_idx].txd_info4.TCO = 1; ++ ei_local->tx_ring0[tx_cpu_owner_idx].txd_info4.UCO = 1; ++ ei_local->tx_ring0[tx_cpu_owner_idx].txd_info4.ICO = 1; ++#endif ++ ++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) ++ if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) { ++ tx_desc[tx_cpu_owner_idx].txd_info4.PN = 6; /* PPE */ ++ } else { ++ tx_desc[tx_cpu_owner_idx].txd_info4.PN = pn; ++ } ++ ++#endif ++ ++ spin_lock_irqsave(&ei_local->page_lock, flags); ++ ei_local->skb_free[ring_no][tx_cpu_owner_idx] = skb; ++ tx_cpu_owner_idx = (tx_cpu_owner_idx +1) % NUM_TX_DESC; ++ ret = set_tx_ctx_idx(ring_no, tx_cpu_owner_idx); ++ spin_unlock_irqrestore(&ei_local->page_lock, flags); ++ ++ ei_local->stat.tx_packets++; ++ ei_local->stat.tx_bytes += length; ++ ++#ifdef CONFIG_RAETH_NAPI ++ switch ( ring_no ) { ++ case 0: ++ if ( ei_local->tx0_full == 1) { ++ ei_local->tx0_full = 0; ++ netif_wake_queue(dev); ++ } ++ break; ++ case 1: ++ if ( ei_local->tx1_full == 1) { ++ ei_local->tx1_full = 0; ++ netif_wake_queue(dev); ++ } ++ break; ++ case 2: ++ if ( ei_local->tx2_full == 1) { ++ ei_local->tx2_full = 0; ++ netif_wake_queue(dev); ++ } ++ break; ++ case 3: ++ if ( ei_local->tx3_full == 1) { ++ ei_local->tx3_full = 0; ++ netif_wake_queue(dev); ++ } ++ break; ++ default : ++ printk("ring_no input error %d\n", ring_no); ++ }; ++#endif ++ return length; ++} ++ ++int fe_tx_desc_init(struct net_device *dev, unsigned int ring_no, unsigned int qn, unsigned int pn) ++{ ++ END_DEVICE* ei_local = netdev_priv(dev); ++ struct PDMA_txdesc *tx_desc; ++ unsigned int tx_cpu_owner_idx = 0; ++ int i; ++ unsigned int phy_tx_ring; ++ ++ // sanity check ++ if ( ring_no > 3 ){ ++ printk("%s : ring_no - %d, please under 4...\n", dev->name, ring_no); ++ return 0; ++ } ++ ++ if ( pn > 2 ){ ++ printk("%s : pn - %d, please under 2...\n", dev->name, pn); ++ return 0; ++ } ++ ++ tx_desc = pci_alloc_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), &phy_tx_ring); ++ ei_local->tx_cpu_owner_idx0 = tx_cpu_owner_idx; ++ ++ switch (ring_no) { ++ case 0: ++ ei_local->tx_ring0 = tx_desc; ++ ei_local->phy_tx_ring0 = phy_tx_ring; ++ break; ++ case 1: ++ ei_local->phy_tx_ring1 = phy_tx_ring; ++ ei_local->tx_ring1 = tx_desc; ++ break; ++ case 2: ++ ei_local->phy_tx_ring2 = phy_tx_ring; ++ ei_local->tx_ring2 = tx_desc; ++ break; ++ case 3: ++ ei_local->phy_tx_ring3 = phy_tx_ring; ++ ei_local->tx_ring3 = tx_desc; ++ break; ++ default: ++ printk("ring_no input error! %d\n", ring_no); ++ pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), tx_desc, phy_tx_ring); ++ return 0; ++ }; ++ ++ if ( tx_desc == NULL) ++ { ++ printk("tx desc allocation failed!\n"); ++ return 0; ++ } ++ ++ for( i = 0; i < NUM_TX_DESC; i++) { ++ memset( &tx_desc[i], 0, sizeof(struct PDMA_txdesc)); ++ tx_desc[i].txd_info2.LS0_bit = 1; ++ tx_desc[i].txd_info2.DDONE_bit = 1; ++ tx_desc[i].txd_info4.PN = pn; ++ tx_desc[i].txd_info4.QN = qn; ++ } ++ ++ switch ( ring_no ) { ++ case 0 : ++ *(unsigned long*)TX_BASE_PTR0 = phys_to_bus((u32) phy_tx_ring); ++ *(unsigned long*)TX_MAX_CNT0 = cpu_to_le32((u32)NUM_TX_DESC); ++ *(unsigned long*)TX_CTX_IDX0 = cpu_to_le32((u32) tx_cpu_owner_idx); ++ sysRegWrite(PDMA_RST_CFG, PST_DTX_IDX0); ++ break; ++ case 1 : ++ *(unsigned long*)TX_BASE_PTR1 = phys_to_bus((u32) phy_tx_ring); ++ *(unsigned long*)TX_MAX_CNT1 = cpu_to_le32((u32)NUM_TX_DESC); ++ *(unsigned long*)TX_CTX_IDX1 = cpu_to_le32((u32) tx_cpu_owner_idx); ++ sysRegWrite(PDMA_RST_CFG, PST_DTX_IDX1); ++ break; ++ case 2 : ++ *(unsigned long*)TX_BASE_PTR2 = phys_to_bus((u32) phy_tx_ring); ++ *(unsigned long*)TX_MAX_CNT2 = cpu_to_le32((u32)NUM_TX_DESC); ++ *(unsigned long*)TX_CTX_IDX2 = cpu_to_le32((u32) tx_cpu_owner_idx); ++ sysRegWrite(PDMA_RST_CFG, PST_DTX_IDX2); ++ break; ++ case 3 : ++ *(unsigned long*)TX_BASE_PTR3 = phys_to_bus((u32) phy_tx_ring); ++ *(unsigned long*)TX_MAX_CNT3 = cpu_to_le32((u32)NUM_TX_DESC); ++ *(unsigned long*)TX_CTX_IDX3 = cpu_to_le32((u32) tx_cpu_owner_idx); ++ sysRegWrite(PDMA_RST_CFG, PST_DTX_IDX3); ++ break; ++ default : ++ printk("tx descriptor init failed %d\n", ring_no); ++ return 0; ++ }; ++ return 1; ++} ++ ++/* ++ DSCP | AC | WMM_AC (Access Category) ++ ------+----+-------- ++ 00-07| 1 | BE ++ 24-31| 1 | BE ++ 08-15| 0 | BG ++ 16-23| 0 | BG ++ 32-39| 2 | VI ++ 40-47| 2 | VI ++ 48-55| 3 | VO ++ 56-63| 3 | VO ++ ++ | TOS | ++ DSCP |(bit5~bit7)| WMM ++ -------+-----------+------- ++ 0x00 | 000 | BE ++ 0x18 | 011 | BE ++ 0x08 | 001 | BG ++ 0x10 | 010 | BG ++ 0x20 | 100 | VI ++ 0x28 | 101 | VI ++ 0x30 | 110 | VO ++ 0x38 | 111 | VO ++ ++ Notes: BE should be mapped to AC1, but mapped to AC0 in linux kernel. ++ ++ */ ++ ++int pkt_classifier(struct sk_buff *skb,int gmac_no, int *ring_no, int *queue_no, int *port_no) ++{ ++#if defined(CONFIG_RALINK_RT2880) ++ /* RT2880 -- Assume using 1 Ring (Ring0), Queue 0, and Port 0 */ ++ *port_no = 0; ++ *ring_no = 0; ++ *queue_no = 0; ++#else ++ unsigned int ac=0; ++ unsigned int bridge_traffic=0, lan_traffic=0; ++ struct iphdr *iph=NULL; ++ struct vlan_ethhdr *veth=NULL; ++ unsigned int vlan_id=0; ++#if defined (CONFIG_RAETH_QOS_DSCP_BASED) ++ static char DscpToAcMap[8]={1,0,0,1,2,2,3,3}; ++#elif defined (CONFIG_RAETH_QOS_VPRI_BASED) ++ static char VlanPriToAcMap[8]={1,0,0,1,2,2,3,3}; ++#endif ++ ++ /* Bridge:: {BG,BE,VI,VO} */ ++ /* GateWay:: WAN: {BG,BE,VI,VO}, LAN: {BG,BE,VI,VO} */ ++#if defined (CONFIG_RALINK_RT3883) && defined (CONFIG_RAETH_GMAC2) ++ /* ++ * 1) Bridge: ++ * 1.1) GMAC1 ONLY: ++ * VO/VI->Ring3, BG/BE->Ring2 ++ * 1.2) GMAC1+GMAC2: ++ * GMAC1:: VO/VI->Ring3, BG/BE->Ring2 ++ * GMAC2:: VO/VI->Ring1, BG/BE->Ring0 ++ * 2) GateWay: ++ * 2.1) GMAC1 ONLY: ++ * GMAC1:: LAN:VI/VO->Ring2, BE/BK->Ring2 ++ * WAN:VI/VO->Ring3, BE/BK->Ring3 ++ * 2.2)GMAC1+GMAC2: ++ * GMAC1:: LAN:VI/VO/BE/BK->Ring2, WAN:VI/VO/BE/BK->Ring3 ++ * GMAC2:: VI/VO->Ring1, BE/BK->Ring0 ++ */ ++ static unsigned char AcToRing_BridgeMap[4] = {2, 2, 3, 3}; ++ static unsigned char AcToRing_GE1Map[2][4] = {{3, 3, 3, 3},{2, 2, 2, 2}}; ++ static unsigned char AcToRing_GE2Map[4] = {0, 0, 1, 1}; ++#elif defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT2883) || \ ++ defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || \ ++ defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || \ ++ defined (CONFIG_RALINK_MT7628) || \ ++ (defined (CONFIG_RALINK_RT3883) && !defined(CONFIG_RAETH_GMAC2)) ++ /* ++ * 1) Bridge: VO->Ring3, VI->Ring2, BG->Ring1, BE->Ring0 ++ * 2) GateWay: ++ * 2.1) GMAC1:: LAN:VI/VO->Ring1, BE/BK->Ring0 ++ * WAN:VI/VO->Ring3, BE/BK->Ring2 ++ */ ++ static unsigned char AcToRing_BridgeMap[4] = {0, 1, 2, 3}; ++ static unsigned char AcToRing_GE1Map[2][4] = {{2, 2, 3, 3},{0, 0, 1, 1}}; ++#endif // CONFIG_RALINK_RT2883 ++ ++ /* ++ * Set queue no - QN field in TX Descriptor ++ * always use queue 3 for the packet from CPU to GMAC ++ */ ++ *queue_no = 3; ++ ++ /* Get access category */ ++ veth = (struct vlan_ethhdr *)(skb->data); ++ if(veth->h_vlan_proto == htons(ETH_P_8021Q)) { // VLAN traffic ++ iph= (struct iphdr *)(skb->data + VLAN_ETH_HLEN); ++ ++ vlan_id = ntohs(veth->h_vlan_TCI & VLAN_VID_MASK); ++ if(vlan_id==1) { //LAN ++ lan_traffic = 1; ++ } else { //WAN ++ lan_traffic = 0; ++ } ++ ++ if (veth->h_vlan_encapsulated_proto == htons(ETH_P_IP)) { //IPv4 ++#if defined (CONFIG_RAETH_QOS_DSCP_BASED) ++ ac = DscpToAcMap[(iph->tos & 0xe0) >> 5]; ++#elif defined (CONFIG_RAETH_QOS_VPRI_BASED) ++ ac = VlanPriToAcMap[skb->priority]; ++#endif ++ }else { //Ipv6, ARP ...etc ++ ac = 0; ++ } ++ }else { // non-VLAN traffic ++ if (veth->h_vlan_proto == htons(ETH_P_IP)) { //IPv4 ++#if defined (CONFIG_RAETH_QOS_DSCP_BASED) ++ iph= (struct iphdr *)(skb->data + ETH_HLEN); ++ ac = DscpToAcMap[(iph->tos & 0xe0) >> 5]; ++#elif defined (CONFIG_RAETH_QOS_VPRI_BASED) ++ ac= VlanPriToAcMap[skb->priority]; ++#endif ++ }else { // IPv6, ARP ...etc ++ ac = 0; ++ } ++ ++ bridge_traffic=1; ++ } ++ ++ ++ /* Set Tx Ring no */ ++ if(gmac_no==1) { //GMAC1 ++ if(bridge_traffic) { //Bridge Mode ++ *ring_no = AcToRing_BridgeMap[ac]; ++ }else { //GateWay Mode ++ *ring_no = AcToRing_GE1Map[lan_traffic][ac]; ++ } ++ }else { //GMAC2 ++#if defined (CONFIG_RALINK_RT3883) && defined (CONFIG_RAETH_GMAC2) ++ *ring_no = AcToRing_GE2Map[ac]; ++#endif ++ } ++ ++ ++ /* Set Port No - PN field in Tx Descriptor*/ ++#if defined(CONFIG_RAETH_GMAC2) ++ *port_no = gmac_no; ++#else ++ if(bridge_traffic) { ++ *port_no = 1; ++ }else { ++ if(lan_traffic==1) { //LAN use VP1 ++ *port_no = 1; ++ }else { //WAN use VP2 ++ *port_no = 2; ++ } ++ } ++#endif // CONFIG_RAETH_GMAC2 // ++ ++#endif ++ ++ return 1; ++ ++} ++ ++ ++/* ++ * Routine Description : ++ * Hi/Li Rings and Queues definition for QoS Purpose ++ * ++ * Related registers: (Detail information refer to pp106 of RT3052_DS_20080226.doc) ++ * Priority High/Low Definition - PDMA_FC_CFG, GDMA1_FC_CFG, GDMA2_FC_CFG ++ * Bit 28 - Allows high priority Q to share low priority Q's reserved pages ++ * Bit 27:24 - Px high priority definition bitmap ++ * Weight Configuration - GDMA1_SCH_CFG, GDMA2_SCH_CFG, PDMA_SCH_CFG -> default 3210 ++ * ++ * Parameter: ++ * NONE ++ * ++*/ ++#define PSE_P1_LQ_FULL (1<<2) ++#define PSE_P1_HQ_FULL (1<<3) ++#define PSE_P2_LQ_FULL (1<<4) ++#define PSE_P2_HQ_FULL (1<<5) ++ ++#define HIGH_QUEUE(queue) (1<<(queue)) ++#define LOW_QUEUE(queue) (0<<(queue)) ++#define PAGES_SHARING (1<<28) ++#define RSEV_PAGE_COUNT_HQ 0x10 /* Reserved page count for high priority Q */ ++#define RSEV_PAGE_COUNT_LQ 0x10 /* Reserved page count for low priority Q */ ++#define VIQ_FC_ASRT 0x10 /* Virtual input Q FC assertion threshold */ ++ ++#define QUEUE_WEIGHT_1 0 ++#define QUEUE_WEIGHT_2 1 ++#define QUEUE_WEIGHT_4 2 ++#define QUEUE_WEIGHT_8 3 ++#define QUEUE_WEIGHT_16 4 ++ ++#define WRR_SCH 0 /*WRR */ ++#define STRICT_PRI_SCH 1 /* Strict Priority */ ++#define MIX_SCH 2 /* Mixed : Q3>WRR(Q2,Q1,Q0) */ ++ ++/* ++ * Ring3 Ring2 Ring1 Ring0 ++ * | | | | | | | | ++ * | | | | | | | | ++ * -------------------------------- ++ * | WRR Scheduler | ++ * -------------------------------- ++ * | ++ * --------------------------------------- ++ * | PDMA | ++ * --------------------------------------- ++ * |Q3||Q2||Q1||Q0| |Q3||Q2||Q1||Q0| ++ * | || || || | | || || || | ++ * ------------------- ------------------- ++ * | GDMA2 | | GDMA1 | ++ * ------------------- ------------------- ++ * | | ++ * ------------------------------------ ++ * | GMAC | ++ * ------------------------------------ ++ * | ++ * ++ */ ++void set_scheduler_weight(void) ++{ ++#if !defined (CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628) ++ /* ++ * STEP1: Queue scheduling configuration ++ */ ++ *(unsigned long *)GDMA1_SCH_CFG = (WRR_SCH << 24) | ++ (QUEUE_WEIGHT_16 << 12) | /* queue 3 weight */ ++ (QUEUE_WEIGHT_8 << 8) | /* queue 2 weight */ ++ (QUEUE_WEIGHT_4 << 4) | /* queue 1 weight */ ++ (QUEUE_WEIGHT_2 << 0); /* queue 0 weight */ ++ ++ *(unsigned long *)GDMA2_SCH_CFG = (WRR_SCH << 24) | ++ (QUEUE_WEIGHT_16 << 12) | /* queue 3 weight */ ++ (QUEUE_WEIGHT_8 << 8) | /* queue 2 weight */ ++ (QUEUE_WEIGHT_4 << 4) | /* queue 1 weight */ ++ (QUEUE_WEIGHT_2 << 0); /* queue 0 weight */ ++ ++#endif ++ /* ++ * STEP2: Ring scheduling configuration ++ */ ++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) ++ /* MIN_RATE_RATIO0=0, MAX_RATE_ULMT0=1, Weight0=1 */ ++ *(unsigned long *)SCH_Q01_CFG = (0 << 10) | (1<<14) | (0 << 12); ++ /* MIN_RATE_RATIO1=0, MAX_RATE_ULMT1=1, Weight1=4 */ ++ *(unsigned long *)SCH_Q01_CFG |= (0 << 26) | (1<<30) | (2 << 28); ++ ++ /* MIN_RATE_RATIO2=0, MAX_RATE_ULMT2=1, Weight0=1 */ ++ *(unsigned long *)SCH_Q23_CFG = (0 << 10) | (1<<14) | (0 << 12); ++ /* MIN_RATE_RATIO3=0, MAX_RATE_ULMT3=1, Weight1=4 */ ++ *(unsigned long *)SCH_Q23_CFG |= (0 << 26) | (1<<30) | (2 << 28); ++#else ++ *(unsigned long *)PDMA_SCH_CFG = (WRR_SCH << 24) | ++ (QUEUE_WEIGHT_16 << 12) | /* ring 3 weight */ ++ (QUEUE_WEIGHT_4 << 8) | /* ring 2 weight */ ++ (QUEUE_WEIGHT_16 << 4) | /* ring 1 weight */ ++ (QUEUE_WEIGHT_4 << 0); /* ring 0 weight */ ++#endif ++} ++ ++/* ++ * Routine Description : ++ * Bucket size and related information from ASIC Designer, ++ * please check Max Lee to update these values ++ * ++ * Related Registers ++ * FE_GLO_CFG - initialize clock rate for rate limiting ++ * PDMA_FC_CFG - Pause mechanism for Rings (Ref to pp116 in datasheet) ++ * : ++ * Parameter: ++ * NONE ++ */ ++/* ++ * Bit 29:24 - Q3 flow control pause condition ++ * Bit 21:16 - Q2 flow control pause condition ++ * Bit 13:8 - Q1 flow control pause condition ++ * Bit 5:0 - Q0 flow control pause condition ++ * ++ * detail bitmap - ++ * Bit[5] - Pause Qx when PSE p2 HQ full ++ * Bit[4] - Pause Qx when PSE p2 LQ full ++ * Bit[3] - Pause Qx when PSE p1 HQ full ++ * Bit[2] - Pause Qx when PSE p1 LQ full ++ * Bit[1] - Pause Qx when PSE p0 HQ full ++ * Bit[0] - Pause Qx when PSE p0 LQ full ++ */ ++void set_schedule_pause_condition(void) ++{ ++#if defined (CONFIG_RALINK_MT7620) ++ ++#elif defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++ *(unsigned long *)SDM_TRING = (0xC << 28) | (0x3 << 24) | (0xC << 4) | 0x3; ++#else ++ /* ++ * STEP1: Set queue priority is high or low ++ * ++ * Set queue 3 as high queue in GMAC1/GMAC2 ++ */ ++ *(unsigned long *)GDMA1_FC_CFG = ((HIGH_QUEUE(3)|LOW_QUEUE(2) | ++ LOW_QUEUE(1)|LOW_QUEUE(0))<<24) | ++ (RSEV_PAGE_COUNT_HQ << 16) | ++ (RSEV_PAGE_COUNT_LQ <<8) | ++ VIQ_FC_ASRT | PAGES_SHARING; ++ ++ *(unsigned long *)GDMA2_FC_CFG = ((HIGH_QUEUE(3)|LOW_QUEUE(2) | ++ LOW_QUEUE(1)|LOW_QUEUE(0))<<24) | ++ (RSEV_PAGE_COUNT_HQ << 16) | ++ (RSEV_PAGE_COUNT_LQ <<8) | ++ VIQ_FC_ASRT | PAGES_SHARING; ++ ++ /* ++ * STEP2: Set flow control pause condition ++ * ++ * CPU always use queue 3, and queue3 is high queue. ++ * If P2(GMAC2) high queue is full, pause ring3/ring2 ++ * If P1(GMAC1) high queue is full, pause ring1/ring0 ++ */ ++ *(unsigned long *)PDMA_FC_CFG = ( PSE_P2_HQ_FULL << 24 ) | /* queue 3 */ ++ ( PSE_P2_HQ_FULL << 16 ) | /* queue 2 */ ++ ( PSE_P1_HQ_FULL << 8 ) | /* queue 1 */ ++ ( PSE_P1_HQ_FULL << 0 ); /* queue 0 */ ++#endif ++ ++} ++ ++ ++void set_output_shaper(void) ++{ ++#define GDMA1_TOKEN_RATE 16 /* unit=64bits/ms */ ++#define GDMA2_TOKEN_RATE 16 /* unit=64bits/ms */ ++ ++#if 0 ++ *(unsigned long *)GDMA1_SHPR_CFG = (1 << 24) | /* output shaper enable */ ++ (128 << 16) | /* bucket size (unit=1KB) */ ++ (GDMA1_TOKEN_RATE << 0); /* token rate (unit=8B/ms) */ ++#endif ++ ++#if 0 ++ *(unsigned long *)GDMA2_SHPR_CFG = (1 << 24) | /* output shaper enable */ ++ (128 << 16) | /* bucket size (unit=1KB) */ ++ (GDMA2_TOKEN_RATE << 0); /* token rate (unit=8B/ms) */ ++#endif ++} +diff --git a/drivers/net/ethernet/raeth/ra_qos.h b/drivers/net/ethernet/raeth/ra_qos.h +new file mode 100644 +index 0000000..7f2a8a1 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/ra_qos.h +@@ -0,0 +1,18 @@ ++#ifndef RA_QOS_H ++#define RA_QOS_H ++ ++#include "ra2882ethreg.h" ++#define RING0 0 ++#define RING1 1 ++#define RING2 2 ++#define RING3 3 ++void get_tx_desc_and_dtx_idx(END_DEVICE* ei_local, int ring_no, unsigned long *tx_dtx_idx, struct PDMA_txdesc **tx_desc); ++int get_tx_ctx_idx(unsigned int ring_no, unsigned long *idx); ++int fe_tx_desc_init(struct net_device *dev, unsigned int ring_no, unsigned int qn, unsigned int pn); ++int fe_qos_packet_send(struct net_device *dev, struct sk_buff* skb, unsigned int ring_no, unsigned int qn, unsigned int pn); ++ ++int pkt_classifier(struct sk_buff *skb,int gmac_no, int *ring_no, int *queue_no, int *port_no); ++void set_schedule_pause_condition(void); ++void set_scheduler_weight(void); ++void set_output_shaper(void); ++#endif +diff --git a/drivers/net/ethernet/raeth/ra_rfrw.c b/drivers/net/ethernet/raeth/ra_rfrw.c +new file mode 100644 +index 0000000..d73db01 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/ra_rfrw.c +@@ -0,0 +1,66 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ra2882ethreg.h" ++#include "raether.h" ++#include "ra_mac.h" ++ ++#define RF_CSR_CFG 0xb0180500 ++#define RF_CSR_KICK (1<<17) ++int rw_rf_reg(int write, int reg, int *data) ++{ ++ unsigned long rfcsr, i = 0; ++ ++ while (1) { ++ rfcsr = sysRegRead(RF_CSR_CFG); ++ if (! (rfcsr & (u32)RF_CSR_KICK) ) ++ break; ++ if (++i > 10000) { ++ printk("Warning: Abort rw rf register: too busy\n"); ++ return -1; ++ } ++ } ++ ++ rfcsr = (u32)(RF_CSR_KICK | ((reg&0x3f) << 8) | (*data & 0xff)); ++ if (write) ++ rfcsr |= 0x10000; ++ ++ sysRegRead(RF_CSR_CFG) = cpu_to_le32(rfcsr); ++ ++ i = 0; ++ while (1) { ++ rfcsr = sysRegRead(RF_CSR_CFG); ++ if (! (rfcsr & (u32)RF_CSR_KICK) ) ++ break; ++ if (++i > 10000) { ++ printk("Warning: still busy\n"); ++ return -1; ++ } ++ } ++ ++ rfcsr = sysRegRead(RF_CSR_CFG); ++ ++ if (((rfcsr&0x1f00) >> 8) != (reg & 0x1f)) { ++ printk("Error: rw register failed\n"); ++ return -1; ++ } ++ *data = (int)(rfcsr & 0xff); ++ ++ return 0; ++} ++ +diff --git a/drivers/net/ethernet/raeth/ra_rfrw.h b/drivers/net/ethernet/raeth/ra_rfrw.h +new file mode 100644 +index 0000000..da5a371 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/ra_rfrw.h +@@ -0,0 +1,6 @@ ++#ifndef RA_RFRW_H ++#define RA_RFRW_H ++ ++int rw_rf_reg(int write, int reg, int *data); ++ ++#endif +diff --git a/drivers/net/ethernet/raeth/raether.c b/drivers/net/ethernet/raeth/raether.c +new file mode 100644 +index 0000000..328285a +--- /dev/null ++++ b/drivers/net/ethernet/raeth/raether.c +@@ -0,0 +1,6401 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if defined (CONFIG_RAETH_TSO) ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#endif ++#if defined (CONFIG_RAETH_LRO) ++#include ++#endif ++#include ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++#include ++#endif ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) ++#include ++#else ++#include ++#endif ++ ++#include "ra2882ethreg.h" ++#include "raether.h" ++#include "ra_mac.h" ++#include "ra_ioctl.h" ++#include "ra_rfrw.h" ++#ifdef CONFIG_RAETH_NETLINK ++#include "ra_netlink.h" ++#endif ++#if defined (CONFIG_RAETH_QOS) ++#include "ra_qos.h" ++#endif ++ ++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) ++#include "../../../net/nat/hw_nat/ra_nat.h" ++#endif ++#if defined(CONFIG_RAETH_PDMA_DVT) ++#include "dvt/raether_pdma_dvt.h" ++#endif /* CONFIG_RAETH_PDMA_DVT */ ++ ++static int fe_irq = 0; ++ ++#if defined (TASKLET_WORKQUEUE_SW) ++int init_schedule; ++int working_schedule; ++#endif ++ ++#ifdef CONFIG_RAETH_NAPI ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++static int raeth_clean(struct napi_struct *napi, int budget); ++#else ++static int raeth_clean(struct net_device *dev, int *budget); ++#endif ++ ++static int rt2880_eth_recv(struct net_device* dev, int *work_done, int work_to_do); ++#else ++static int rt2880_eth_recv(struct net_device* dev); ++#endif ++ ++#if !defined(CONFIG_RA_NAT_NONE) ++/* bruce+ ++ */ ++extern int (*ra_sw_nat_hook_rx)(struct sk_buff *skb); ++extern int (*ra_sw_nat_hook_tx)(struct sk_buff *skb, int gmac_no); ++#endif ++ ++#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE) ++/* Qwert+ ++ */ ++#include ++extern int (*ra_classifier_hook_tx)(struct sk_buff *skb, unsigned long cur_cycle); ++extern int (*ra_classifier_hook_rx)(struct sk_buff *skb, unsigned long cur_cycle); ++#endif /* CONFIG_RA_CLASSIFIER */ ++ ++#if defined (CONFIG_RALINK_RT3052_MP2) ++int32_t mcast_rx(struct sk_buff * skb); ++int32_t mcast_tx(struct sk_buff * skb); ++#endif ++ ++int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf) ++{ ++ /* TODO */ ++ return 0; ++} ++ ++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_P5_RGMII_TO_MT7530_MODE) || defined (CONFIG_ARCH_MT7623) ++void setup_internal_gsw(void); ++#if defined (CONFIG_GE1_TRGMII_FORCE_1200) ++void apll_xtal_enable(void); ++#define REGBIT(x, n) (x << n) ++#endif ++#endif ++ ++#if defined (CONFIG_MT7623_FPGA) ++void setup_fpga_gsw(void); ++#endif ++ ++/* gmac driver feature set config */ ++#if defined (CONFIG_RAETH_NAPI) || defined (CONFIG_RAETH_QOS) ++#undef DELAY_INT ++#else ++#if defined (CONFIG_ARCH_MT7623) ++#undef DELAY_INT ++#else ++#define DELAY_INT 1 ++#endif ++#endif ++ ++//#define CONFIG_UNH_TEST ++/* end of config */ ++ ++#if defined (CONFIG_RAETH_JUMBOFRAME) ++#define MAX_RX_LENGTH 4096 ++#else ++#define MAX_RX_LENGTH 1536 ++#endif ++ ++struct net_device *dev_raether; ++ ++static int rx_dma_owner_idx; ++static int rx_dma_owner_idx0; ++#if defined (CONFIG_RAETH_HW_LRO) ++static int rx_dma_owner_lro1; ++static int rx_dma_owner_lro2; ++static int rx_dma_owner_lro3; ++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++static int rx_dma_owner_idx1; ++#if defined(CONFIG_ARCH_MT7623) ++static int rx_dma_owner_idx2; ++static int rx_dma_owner_idx3; ++#endif /* CONFIG_ARCH_MT7623 */ ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++int rx_calc_idx1; ++#endif ++#endif ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++int rx_calc_idx0; ++#endif ++static int pending_recv; ++static struct PDMA_rxdesc *rx_ring; ++unsigned long tx_ring_full=0; ++ ++#if defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined(CONFIG_RALINK_MT7620) ++unsigned short p0_rx_good_cnt = 0; ++unsigned short p1_rx_good_cnt = 0; ++unsigned short p2_rx_good_cnt = 0; ++unsigned short p3_rx_good_cnt = 0; ++unsigned short p4_rx_good_cnt = 0; ++unsigned short p5_rx_good_cnt = 0; ++unsigned short p6_rx_good_cnt = 0; ++unsigned short p0_tx_good_cnt = 0; ++unsigned short p1_tx_good_cnt = 0; ++unsigned short p2_tx_good_cnt = 0; ++unsigned short p3_tx_good_cnt = 0; ++unsigned short p4_tx_good_cnt = 0; ++unsigned short p5_tx_good_cnt = 0; ++unsigned short p6_tx_good_cnt = 0; ++ ++unsigned short p0_rx_byte_cnt = 0; ++unsigned short p1_rx_byte_cnt = 0; ++unsigned short p2_rx_byte_cnt = 0; ++unsigned short p3_rx_byte_cnt = 0; ++unsigned short p4_rx_byte_cnt = 0; ++unsigned short p5_rx_byte_cnt = 0; ++unsigned short p6_rx_byte_cnt = 0; ++unsigned short p0_tx_byte_cnt = 0; ++unsigned short p1_tx_byte_cnt = 0; ++unsigned short p2_tx_byte_cnt = 0; ++unsigned short p3_tx_byte_cnt = 0; ++unsigned short p4_tx_byte_cnt = 0; ++unsigned short p5_tx_byte_cnt = 0; ++unsigned short p6_tx_byte_cnt = 0; ++ ++#if defined(CONFIG_RALINK_MT7620) ++unsigned short p7_rx_good_cnt = 0; ++unsigned short p7_tx_good_cnt = 0; ++ ++unsigned short p7_rx_byte_cnt = 0; ++unsigned short p7_tx_byte_cnt = 0; ++#endif ++#endif ++ ++ ++ ++ ++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/ ++#include "ra_ethtool.h" ++extern struct ethtool_ops ra_ethtool_ops; ++#ifdef CONFIG_PSEUDO_SUPPORT ++extern struct ethtool_ops ra_virt_ethtool_ops; ++#endif // CONFIG_PSEUDO_SUPPORT // ++#endif // (CONFIG_ETHTOOL // ++ ++#ifdef CONFIG_RALINK_VISTA_BASIC ++int is_switch_175c = 1; ++#endif ++ ++unsigned int M2Q_table[64] = {0}; ++unsigned int lan_wan_separate = 0; ++ ++#if defined(CONFIG_HW_SFQ) ++unsigned int web_sfq_enable = 0; ++EXPORT_SYMBOL(web_sfq_enable); ++#endif ++ ++EXPORT_SYMBOL(M2Q_table); ++EXPORT_SYMBOL(lan_wan_separate); ++#if defined (CONFIG_RAETH_LRO) ++unsigned int lan_ip; ++struct lro_para_struct lro_para; ++int lro_flush_needed; ++extern char const *nvram_get(int index, char *name); ++#endif ++ ++#define KSEG1 0xa0000000 ++#if defined (CONFIG_MIPS) ++#define PHYS_TO_VIRT(x) ((void *)((x) | KSEG1)) ++#define VIRT_TO_PHYS(x) ((unsigned long)(x) & ~KSEG1) ++#else ++#define PHYS_TO_VIRT(x) phys_to_virt(x) ++#define VIRT_TO_PHYS(x) virt_to_phys(x) ++#endif ++ ++extern int fe_dma_init(struct net_device *dev); ++extern int ei_start_xmit(struct sk_buff* skb, struct net_device *dev, int gmac_no); ++extern void ei_xmit_housekeeping(unsigned long unused); ++extern inline int rt2880_eth_send(struct net_device* dev, struct sk_buff *skb, int gmac_no); ++#if defined (CONFIG_RAETH_HW_LRO) ++extern int fe_hw_lro_init(struct net_device *dev); ++#endif /* CONFIG_RAETH_HW_LRO */ ++ ++#if 0 ++void skb_dump(struct sk_buff* sk) { ++ unsigned int i; ++ ++ printk("skb_dump: from %s with len %d (%d) headroom=%d tailroom=%d\n", ++ sk->dev?sk->dev->name:"ip stack",sk->len,sk->truesize, ++ skb_headroom(sk),skb_tailroom(sk)); ++ ++ //for(i=(unsigned int)sk->head;i<=(unsigned int)sk->tail;i++) { ++ for(i=(unsigned int)sk->head;i<=(unsigned int)sk->data+20;i++) { ++ if((i % 20) == 0) ++ printk("\n"); ++ if(i==(unsigned int)sk->data) printk("{"); ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21) ++ if(i==(unsigned int)sk->transport_header) printk("#"); ++ if(i==(unsigned int)sk->network_header) printk("|"); ++ if(i==(unsigned int)sk->mac_header) printk("*"); ++#else ++ if(i==(unsigned int)sk->h.raw) printk("#"); ++ if(i==(unsigned int)sk->nh.raw) printk("|"); ++ if(i==(unsigned int)sk->mac.raw) printk("*"); ++#endif ++ printk("%02X-",*((unsigned char*)i)); ++ if(i==(unsigned int)sk->tail) printk("}"); ++ } ++ printk("\n"); ++} ++#endif ++ ++ ++ ++#if defined (CONFIG_GIGAPHY) || defined (CONFIG_P5_MAC_TO_PHY_MODE) ++int isICPlusGigaPHY(int ge) ++{ ++ u32 phy_id0 = 0, phy_id1 = 0; ++ ++#ifdef CONFIG_GE2_RGMII_AN ++ if (ge == 2) { ++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 2, &phy_id0)) { ++ printk("\n Read PhyID 1 is Fail!!\n"); ++ phy_id0 =0; ++ } ++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 3, &phy_id1)) { ++ printk("\n Read PhyID 1 is Fail!!\n"); ++ phy_id1 = 0; ++ } ++ } ++ else ++#endif ++#if defined (CONFIG_GE1_RGMII_AN) || defined (CONFIG_P5_MAC_TO_PHY_MODE) ++ { ++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 2, &phy_id0)) { ++ printk("\n Read PhyID 0 is Fail!!\n"); ++ phy_id0 =0; ++ } ++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 3, &phy_id1)) { ++ printk("\n Read PhyID 0 is Fail!!\n"); ++ phy_id1 = 0; ++ } ++ } ++#endif ++ ++ if ((phy_id0 == EV_ICPLUS_PHY_ID0) && ((phy_id1 & 0xfff0) == EV_ICPLUS_PHY_ID1)) ++ return 1; ++ return 0; ++} ++ ++ ++int isMarvellGigaPHY(int ge) ++{ ++ u32 phy_id0 = 0, phy_id1 = 0; ++ ++#if defined (CONFIG_GE2_RGMII_AN) || defined (CONFIG_P4_MAC_TO_PHY_MODE) ++ if (ge == 2) { ++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 2, &phy_id0)) { ++ printk("\n Read PhyID 1 is Fail!!\n"); ++ phy_id0 =0; ++ } ++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 3, &phy_id1)) { ++ printk("\n Read PhyID 1 is Fail!!\n"); ++ phy_id1 = 0; ++ } ++ } ++ else ++#endif ++#if defined (CONFIG_GE1_RGMII_AN) || defined (CONFIG_P5_MAC_TO_PHY_MODE) ++ { ++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 2, &phy_id0)) { ++ printk("\n Read PhyID 0 is Fail!!\n"); ++ phy_id0 =0; ++ } ++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 3, &phy_id1)) { ++ printk("\n Read PhyID 0 is Fail!!\n"); ++ phy_id1 = 0; ++ } ++ } ++#endif ++ ; ++ if ((phy_id0 == EV_MARVELL_PHY_ID0) && (phy_id1 == EV_MARVELL_PHY_ID1)) ++ return 1; ++ return 0; ++} ++ ++int isVtssGigaPHY(int ge) ++{ ++ u32 phy_id0 = 0, phy_id1 = 0; ++ ++#if defined (CONFIG_GE2_RGMII_AN) || defined (CONFIG_P4_MAC_TO_PHY_MODE) ++ if (ge == 2) { ++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 2, &phy_id0)) { ++ printk("\n Read PhyID 1 is Fail!!\n"); ++ phy_id0 =0; ++ } ++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 3, &phy_id1)) { ++ printk("\n Read PhyID 1 is Fail!!\n"); ++ phy_id1 = 0; ++ } ++ } ++ else ++#endif ++#if defined (CONFIG_GE1_RGMII_AN) || defined (CONFIG_P5_MAC_TO_PHY_MODE) ++ { ++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 2, &phy_id0)) { ++ printk("\n Read PhyID 0 is Fail!!\n"); ++ phy_id0 =0; ++ } ++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 3, &phy_id1)) { ++ printk("\n Read PhyID 0 is Fail!!\n"); ++ phy_id1 = 0; ++ } ++ } ++#endif ++ ; ++ if ((phy_id0 == EV_VTSS_PHY_ID0) && (phy_id1 == EV_VTSS_PHY_ID1)) ++ return 1; ++ return 0; ++} ++#endif ++ ++/* ++ * Set the hardware MAC address. ++ */ ++static int ei_set_mac_addr(struct net_device *dev, void *p) ++{ ++ struct sockaddr *addr = p; ++ ++ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); ++ ++ if(netif_running(dev)) ++ return -EBUSY; ++ ++ ra2880MacAddressSet(addr->sa_data); ++ return 0; ++} ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++static int ei_set_mac2_addr(struct net_device *dev, void *p) ++{ ++ struct sockaddr *addr = p; ++ ++ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); ++ ++ if(netif_running(dev)) ++ return -EBUSY; ++ ++ ra2880Mac2AddressSet(addr->sa_data); ++ return 0; ++} ++#endif ++ ++void set_fe_dma_glo_cfg(void) ++{ ++ int dma_glo_cfg=0; ++#if defined (CONFIG_RALINK_RT2880) || defined(CONFIG_RALINK_RT2883) || \ ++ defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3883) ++ int fe_glo_cfg=0; ++#endif ++ ++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) ++ dma_glo_cfg = (TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN | PDMA_BT_SIZE_32DWORDS); ++#elif defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) ++ dma_glo_cfg = (TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN | PDMA_BT_SIZE_16DWORDS); ++#elif defined (CONFIG_ARCH_MT7623) ++ dma_glo_cfg = (TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN | PDMA_BT_SIZE_16DWORDS | ADMA_RX_BT_SIZE_32DWORDS); ++#else ++ dma_glo_cfg = (TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN | PDMA_BT_SIZE_4DWORDS); ++#endif ++ ++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA) ++ dma_glo_cfg |= (RX_2B_OFFSET); ++#endif ++ ++#if defined (CONFIG_32B_DESC) ++ dma_glo_cfg |= (DESC_32B_EN); ++#endif ++ sysRegWrite(DMA_GLO_CFG, dma_glo_cfg); ++#ifdef CONFIG_RAETH_QDMA ++ sysRegWrite(QDMA_GLO_CFG, dma_glo_cfg); ++#endif ++ ++ /* only the following chipset need to set it */ ++#if defined (CONFIG_RALINK_RT2880) || defined(CONFIG_RALINK_RT2883) || \ ++ defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3883) ++ //set 1us timer count in unit of clock cycle ++ fe_glo_cfg = sysRegRead(FE_GLO_CFG); ++ fe_glo_cfg &= ~(0xff << 8); //clear bit8-bit15 ++ fe_glo_cfg |= (((get_surfboard_sysclk()/1000000)) << 8); ++ sysRegWrite(FE_GLO_CFG, fe_glo_cfg); ++#endif ++} ++ ++int forward_config(struct net_device *dev) ++{ ++ ++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++ ++ /* RT5350: No GDMA, PSE, CDMA, PPE */ ++ unsigned int sdmVal; ++ sdmVal = sysRegRead(SDM_CON); ++ ++#ifdef CONFIG_RAETH_CHECKSUM_OFFLOAD ++ sdmVal |= 0x7<<16; // UDPCS, TCPCS, IPCS=1 ++#endif // CONFIG_RAETH_CHECKSUM_OFFLOAD // ++ ++#if defined (CONFIG_RAETH_SPECIAL_TAG) ++ sdmVal |= 0x1<<20; // TCI_81XX ++#endif // CONFIG_RAETH_SPECIAL_TAG // ++ ++ sysRegWrite(SDM_CON, sdmVal); ++ ++#else //Non RT5350 chipset ++ ++ unsigned int regVal, regCsg; ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++ unsigned int regVal2; ++#endif ++ ++#ifdef CONFIG_RAETH_HW_VLAN_TX ++#if defined(CONFIG_RALINK_MT7620) ++ /* frame engine will push VLAN tag regarding to VIDX feild in Tx desc. */ ++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x430) = 0x00010000; ++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x434) = 0x00030002; ++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x438) = 0x00050004; ++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x43C) = 0x00070006; ++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x440) = 0x00090008; ++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x444) = 0x000b000a; ++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x448) = 0x000d000c; ++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x44C) = 0x000f000e; ++#else ++ /* ++ * VLAN_IDX 0 = VLAN_ID 0 ++ * ......... ++ * VLAN_IDX 15 = VLAN ID 15 ++ * ++ */ ++ /* frame engine will push VLAN tag regarding to VIDX feild in Tx desc. */ ++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xa8) = 0x00010000; ++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xac) = 0x00030002; ++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xb0) = 0x00050004; ++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xb4) = 0x00070006; ++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xb8) = 0x00090008; ++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xbc) = 0x000b000a; ++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xc0) = 0x000d000c; ++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xc4) = 0x000f000e; ++#endif ++#endif ++ ++ regVal = sysRegRead(GDMA1_FWD_CFG); ++ regCsg = sysRegRead(CDMA_CSG_CFG); ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++ regVal2 = sysRegRead(GDMA2_FWD_CFG); ++#endif ++ ++ //set unicast/multicast/broadcast frame to cpu ++#if defined (CONFIG_RALINK_MT7620) ++ /* GDMA1 frames destination port is port0 CPU*/ ++ regVal &= ~0x7; ++#else ++ regVal &= ~0xFFFF; ++ regVal |= GDMA1_FWD_PORT; ++#endif ++ regCsg &= ~0x7; ++ ++#if defined (CONFIG_RAETH_SPECIAL_TAG) ++ regVal |= (1 << 24); //GDM1_TCI_81xx ++#endif ++ ++ ++#ifdef CONFIG_RAETH_HW_VLAN_TX ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) ++ dev->features |= NETIF_F_HW_VLAN_TX; ++#else ++ dev->features |= NETIF_F_HW_VLAN_CTAG_TX; ++#endif ++#endif ++#ifdef CONFIG_RAETH_HW_VLAN_RX ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) ++ dev->features |= NETIF_F_HW_VLAN_RX; ++#else ++ dev->features |= NETIF_F_HW_VLAN_CTAG_RX; ++#endif ++#endif ++ ++#ifdef CONFIG_RAETH_CHECKSUM_OFFLOAD ++ //enable ipv4 header checksum check ++ regVal |= GDM1_ICS_EN; ++ regCsg |= ICS_GEN_EN; ++ ++ //enable tcp checksum check ++ regVal |= GDM1_TCS_EN; ++ regCsg |= TCS_GEN_EN; ++ ++ //enable udp checksum check ++ regVal |= GDM1_UCS_EN; ++ regCsg |= UCS_GEN_EN; ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++ regVal2 &= ~0xFFFF; ++ regVal2 |= GDMA2_FWD_PORT; ++ ++ regVal2 |= GDM1_ICS_EN; ++ regVal2 |= GDM1_TCS_EN; ++ regVal2 |= GDM1_UCS_EN; ++#endif ++ ++#if defined (CONFIG_RAETH_HW_LRO) ++ dev->features |= NETIF_F_HW_CSUM; ++#else ++ dev->features |= NETIF_F_IP_CSUM; /* Can checksum TCP/UDP over IPv4 */ ++#endif /* CONFIG_RAETH_HW_LRO */ ++//#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0) ++// dev->vlan_features |= NETIF_F_IP_CSUM; ++//#endif ++ ++#if defined(CONFIG_RALINK_MT7620) ++#if defined (CONFIG_RAETH_TSO) ++ if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) { ++ dev->features |= NETIF_F_SG; ++ dev->features |= NETIF_F_TSO; ++ } ++#endif // CONFIG_RAETH_TSO // ++ ++#if defined (CONFIG_RAETH_TSOV6) ++ if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) { ++ dev->features |= NETIF_F_TSO6; ++ dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */ ++ } ++#endif // CONFIG_RAETH_TSOV6 // ++#else ++#if defined (CONFIG_RAETH_TSO) ++ dev->features |= NETIF_F_SG; ++ dev->features |= NETIF_F_TSO; ++#endif // CONFIG_RAETH_TSO // ++ ++#if defined (CONFIG_RAETH_TSOV6) ++ dev->features |= NETIF_F_TSO6; ++ dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */ ++#endif // CONFIG_RAETH_TSOV6 // ++#endif // CONFIG_RALINK_MT7620 // ++#else // Checksum offload disabled ++ ++ //disable ipv4 header checksum check ++ regVal &= ~GDM1_ICS_EN; ++ regCsg &= ~ICS_GEN_EN; ++ ++ //disable tcp checksum check ++ regVal &= ~GDM1_TCS_EN; ++ regCsg &= ~TCS_GEN_EN; ++ ++ //disable udp checksum check ++ regVal &= ~GDM1_UCS_EN; ++ regCsg &= ~UCS_GEN_EN; ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++ regVal2 &= ~GDM1_ICS_EN; ++ regVal2 &= ~GDM1_TCS_EN; ++ regVal2 &= ~GDM1_UCS_EN; ++#endif ++ ++ dev->features &= ~NETIF_F_IP_CSUM; /* disable checksum TCP/UDP over IPv4 */ ++#endif // CONFIG_RAETH_CHECKSUM_OFFLOAD // ++ ++#ifdef CONFIG_RAETH_JUMBOFRAME ++ regVal |= GDM1_JMB_EN; ++#ifdef CONFIG_PSEUDO_SUPPORT ++ regVal2 |= GDM1_JMB_EN; ++#endif ++#endif ++ ++ sysRegWrite(GDMA1_FWD_CFG, regVal); ++ sysRegWrite(CDMA_CSG_CFG, regCsg); ++#ifdef CONFIG_PSEUDO_SUPPORT ++ sysRegWrite(GDMA2_FWD_CFG, regVal2); ++#endif ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0) ++ dev->vlan_features = dev->features; ++#endif ++ ++/* ++ * PSE_FQ_CFG register definition - ++ * ++ * Define max free queue page count in PSE. (31:24) ++ * RT2883/RT3883 - 0xff908000 (255 pages) ++ * RT3052 - 0x80504000 (128 pages) ++ * RT2880 - 0x80504000 (128 pages) ++ * ++ * In each page, there are 128 bytes in each page. ++ * ++ * 23:16 - free queue flow control release threshold ++ * 15:8 - free queue flow control assertion threshold ++ * 7:0 - free queue empty threshold ++ * ++ * The register affects QOS correctness in frame engine! ++ */ ++ ++#if defined(CONFIG_RALINK_RT2883) || defined(CONFIG_RALINK_RT3883) ++ sysRegWrite(PSE_FQ_CFG, cpu_to_le32(INIT_VALUE_OF_RT2883_PSE_FQ_CFG)); ++#elif defined(CONFIG_RALINK_RT3352) || defined(CONFIG_RALINK_RT5350) || \ ++ defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined(CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || \ ++ defined (CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++ /*use default value*/ ++#else ++ sysRegWrite(PSE_FQ_CFG, cpu_to_le32(INIT_VALUE_OF_PSE_FQFC_CFG)); ++#endif ++ ++ /* ++ *FE_RST_GLO register definition - ++ *Bit 0: PSE Rest ++ *Reset PSE after re-programming PSE_FQ_CFG. ++ */ ++ regVal = 0x1; ++ sysRegWrite(FE_RST_GL, regVal); ++ sysRegWrite(FE_RST_GL, 0); // update for RSTCTL issue ++ ++ regCsg = sysRegRead(CDMA_CSG_CFG); ++ printk("CDMA_CSG_CFG = %0X\n",regCsg); ++ regVal = sysRegRead(GDMA1_FWD_CFG); ++ printk("GDMA1_FWD_CFG = %0X\n",regVal); ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++ regVal = sysRegRead(GDMA2_FWD_CFG); ++ printk("GDMA2_FWD_CFG = %0X\n",regVal); ++#endif ++#endif ++ return 1; ++} ++ ++#ifdef CONFIG_RAETH_LRO ++static int ++rt_get_skb_header(struct sk_buff *skb, void **iphdr, void **tcph, ++ u64 *hdr_flags, void *priv) ++{ ++ struct iphdr *iph = NULL; ++ int vhdr_len = 0; ++ ++ /* ++ * Make sure that this packet is Ethernet II, is not VLAN ++ * tagged, is IPv4, has a valid IP header, and is TCP. ++ */ ++ if (skb->protocol == 0x0081) { ++ vhdr_len = VLAN_HLEN; ++ } ++ ++ iph = (struct iphdr *)(skb->data + vhdr_len); ++ if (iph->daddr != lro_para.lan_ip1) { ++ return -1; ++ } ++ ++ if(iph->protocol != IPPROTO_TCP) { ++ return -1; ++ } else { ++ *iphdr = iph; ++ *tcph = skb->data + (iph->ihl << 2) + vhdr_len; ++ *hdr_flags = LRO_IPV4 | LRO_TCP; ++ ++ lro_flush_needed = 1; ++ return 0; ++ } ++} ++#endif // CONFIG_RAETH_LRO // ++ ++#ifdef CONFIG_RAETH_NAPI ++static int rt2880_eth_recv(struct net_device* dev, int *work_done, int work_to_do) ++#else ++static int rt2880_eth_recv(struct net_device* dev) ++#endif ++{ ++ struct sk_buff *skb, *rx_skb; ++ unsigned int length = 0; ++ unsigned long RxProcessed; ++ ++ int bReschedule = 0; ++ END_DEVICE* ei_local = netdev_priv(dev); ++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING) || defined (CONFIG_RAETH_HW_LRO) ++ int rx_ring_no=0; ++#endif ++ ++#if defined (CONFIG_RAETH_SPECIAL_TAG) ++ struct vlan_ethhdr *veth=NULL; ++#endif ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++ PSEUDO_ADAPTER *pAd; ++#endif ++ ++ RxProcessed = 0; ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ rx_dma_owner_idx0 = (rx_calc_idx0 + 1) % NUM_RX_DESC; ++#else ++ rx_dma_owner_idx0 = (sysRegRead(RAETH_RX_CALC_IDX0) + 1) % NUM_RX_DESC; ++#endif ++ ++#if defined (CONFIG_32B_DESC) ++ dma_cache_sync(NULL, &ei_local->rx_ring0[rx_dma_owner_idx0], sizeof(struct PDMA_rxdesc), DMA_FROM_DEVICE); ++#endif ++#if defined (CONFIG_RAETH_HW_LRO) ++ rx_dma_owner_lro1 = (sysRegRead(RX_CALC_IDX1) + 1) % NUM_LRO_RX_DESC; ++ rx_dma_owner_lro2 = (sysRegRead(RX_CALC_IDX2) + 1) % NUM_LRO_RX_DESC; ++ rx_dma_owner_lro3 = (sysRegRead(RX_CALC_IDX3) + 1) % NUM_LRO_RX_DESC; ++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ rx_dma_owner_idx1 = (rx_calc_idx1 + 1) % NUM_RX_DESC; ++#else ++ rx_dma_owner_idx1 = (sysRegRead(RX_CALC_IDX1) + 1) % NUM_RX_DESC; ++#endif /* CONFIG_RAETH_RW_PDMAPTR_FROM_VAR */ ++#if defined(CONFIG_ARCH_MT7623) ++ rx_dma_owner_idx2 = (sysRegRead(RX_CALC_IDX2) + 1) % NUM_RX_DESC; ++ rx_dma_owner_idx3 = (sysRegRead(RX_CALC_IDX3) + 1) % NUM_RX_DESC; ++#endif ++#if defined (CONFIG_32B_DESC) ++ dma_cache_sync(NULL, &ei_local->rx_ring1[rx_dma_owner_idx1], sizeof(struct PDMA_rxdesc), DMA_FROM_DEVICE); ++#endif ++#endif ++ for ( ; ; ) { ++ ++ ++#ifdef CONFIG_RAETH_NAPI ++ if(*work_done >= work_to_do) ++ break; ++ (*work_done)++; ++#else ++ if (RxProcessed++ > NUM_RX_MAX_PROCESS) ++ { ++ // need to reschedule rx handle ++ bReschedule = 1; ++ break; ++ } ++#endif ++ ++ ++#if defined (CONFIG_RAETH_HW_LRO) ++ if (ei_local->rx_ring3[rx_dma_owner_lro3].rxd_info2.DDONE_bit == 1) { ++ rx_ring = ei_local->rx_ring3; ++ rx_dma_owner_idx = rx_dma_owner_lro3; ++ // printk("rx_dma_owner_lro3=%x\n",rx_dma_owner_lro3); ++ rx_ring_no=3; ++ } ++ else if (ei_local->rx_ring2[rx_dma_owner_lro2].rxd_info2.DDONE_bit == 1) { ++ rx_ring = ei_local->rx_ring2; ++ rx_dma_owner_idx = rx_dma_owner_lro2; ++ // printk("rx_dma_owner_lro2=%x\n",rx_dma_owner_lro2); ++ rx_ring_no=2; ++ } ++ else if (ei_local->rx_ring1[rx_dma_owner_lro1].rxd_info2.DDONE_bit == 1) { ++ rx_ring = ei_local->rx_ring1; ++ rx_dma_owner_idx = rx_dma_owner_lro1; ++ // printk("rx_dma_owner_lro1=%x\n",rx_dma_owner_lro1); ++ rx_ring_no=1; ++ } ++ else if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.DDONE_bit == 1) { ++ rx_ring = ei_local->rx_ring0; ++ rx_dma_owner_idx = rx_dma_owner_idx0; ++ // printk("rx_dma_owner_idx0=%x\n",rx_dma_owner_idx0); ++ rx_ring_no=0; ++ } else { ++ break; ++ } ++ #if defined (CONFIG_RAETH_HW_LRO_DBG) ++ HwLroStatsUpdate(rx_ring_no, rx_ring[rx_dma_owner_idx].rxd_info2.LRO_AGG_CNT, \ ++ (rx_ring[rx_dma_owner_idx].rxd_info2.PLEN1 << 14) | rx_ring[rx_dma_owner_idx].rxd_info2.PLEN0); ++ #endif ++ #if defined(CONFIG_RAETH_HW_LRO_REASON_DBG) ++ HwLroFlushStatsUpdate(rx_ring_no, rx_ring[rx_dma_owner_idx].rxd_info2.REV); ++ #endif ++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++ if (ei_local->rx_ring1[rx_dma_owner_idx1].rxd_info2.DDONE_bit == 1) { ++ rx_ring = ei_local->rx_ring1; ++ rx_dma_owner_idx = rx_dma_owner_idx1; ++ // printk("rx_dma_owner_idx1=%x\n",rx_dma_owner_idx1); ++ rx_ring_no=1; ++ } ++#if defined(CONFIG_ARCH_MT7623) ++ else if (ei_local->rx_ring2[rx_dma_owner_idx2].rxd_info2.DDONE_bit == 1) { ++ rx_ring = ei_local->rx_ring2; ++ rx_dma_owner_idx = rx_dma_owner_idx2; ++ // printk("rx_dma_owner_idx2=%x\n",rx_dma_owner_idx2); ++ rx_ring_no=2; ++ } ++ else if (ei_local->rx_ring3[rx_dma_owner_idx3].rxd_info2.DDONE_bit == 1) { ++ rx_ring = ei_local->rx_ring3; ++ rx_dma_owner_idx = rx_dma_owner_idx3; ++ // printk("rx_dma_owner_idx3=%x\n",rx_dma_owner_idx3); ++ rx_ring_no=3; ++ } ++#endif /* CONFIG_ARCH_MT7623 */ ++ else if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.DDONE_bit == 1) { ++ rx_ring = ei_local->rx_ring0; ++ rx_dma_owner_idx = rx_dma_owner_idx0; ++ // printk("rx_dma_owner_idx0=%x\n",rx_dma_owner_idx0); ++ rx_ring_no=0; ++ } else { ++ break; ++ } ++#else ++ ++ if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.DDONE_bit == 1) { ++ rx_ring = ei_local->rx_ring0; ++ rx_dma_owner_idx = rx_dma_owner_idx0; ++ } else { ++ break; ++ } ++#endif ++ ++#if defined (CONFIG_32B_DESC) ++ prefetch(&rx_ring[(rx_dma_owner_idx + 1) % NUM_RX_DESC]); ++#endif ++ /* skb processing */ ++#if defined (CONFIG_RAETH_HW_LRO) ++ length = (rx_ring[rx_dma_owner_idx].rxd_info2.PLEN1 << 14) | rx_ring[rx_dma_owner_idx].rxd_info2.PLEN0; ++#else ++ length = rx_ring[rx_dma_owner_idx].rxd_info2.PLEN0; ++#endif /* CONFIG_RAETH_HW_LRO */ ++ ++#if defined (CONFIG_ARCH_MT7623) ++ dma_unmap_single(NULL, rx_ring[rx_dma_owner_idx].rxd_info1.PDP0, length, DMA_FROM_DEVICE); ++#endif ++ ++#if defined (CONFIG_RAETH_HW_LRO) ++ if(rx_ring_no==3) { ++ rx_skb = ei_local->netrx3_skbuf[rx_dma_owner_idx]; ++ rx_skb->data = ei_local->netrx3_skbuf[rx_dma_owner_idx]->data; ++ } ++ else if(rx_ring_no==2) { ++ rx_skb = ei_local->netrx2_skbuf[rx_dma_owner_idx]; ++ rx_skb->data = ei_local->netrx2_skbuf[rx_dma_owner_idx]->data; ++ } ++ else if(rx_ring_no==1) { ++ rx_skb = ei_local->netrx1_skbuf[rx_dma_owner_idx]; ++ rx_skb->data = ei_local->netrx1_skbuf[rx_dma_owner_idx]->data; ++ } ++ else { ++ rx_skb = ei_local->netrx0_skbuf[rx_dma_owner_idx]; ++ rx_skb->data = ei_local->netrx0_skbuf[rx_dma_owner_idx]->data; ++ } ++ #if defined(CONFIG_RAETH_PDMA_DVT) ++ raeth_pdma_lro_dvt( rx_ring_no, ei_local, rx_dma_owner_idx ); ++ #endif /* CONFIG_RAETH_PDMA_DVT */ ++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++ if(rx_ring_no==1) { ++ rx_skb = ei_local->netrx1_skbuf[rx_dma_owner_idx]; ++ rx_skb->data = ei_local->netrx1_skbuf[rx_dma_owner_idx]->data; ++ } ++#if defined(CONFIG_ARCH_MT7623) ++ else if(rx_ring_no==2) { ++ rx_skb = ei_local->netrx2_skbuf[rx_dma_owner_idx]; ++ rx_skb->data = ei_local->netrx2_skbuf[rx_dma_owner_idx]->data; ++ } ++ else if(rx_ring_no==3) { ++ rx_skb = ei_local->netrx3_skbuf[rx_dma_owner_idx]; ++ rx_skb->data = ei_local->netrx3_skbuf[rx_dma_owner_idx]->data; ++ } ++#endif /* CONFIG_ARCH_MT7623 */ ++ else { ++ rx_skb = ei_local->netrx0_skbuf[rx_dma_owner_idx]; ++ rx_skb->data = ei_local->netrx0_skbuf[rx_dma_owner_idx]->data; ++ } ++ #if defined(CONFIG_RAETH_PDMA_DVT) ++ raeth_pdma_lro_dvt( rx_ring_no, ei_local, rx_dma_owner_idx ); ++ #endif /* CONFIG_RAETH_PDMA_DVT */ ++#else ++ rx_skb = ei_local->netrx0_skbuf[rx_dma_owner_idx]; ++ rx_skb->data = ei_local->netrx0_skbuf[rx_dma_owner_idx]->data; ++ #if defined(CONFIG_RAETH_PDMA_DVT) ++ raeth_pdma_rx_desc_dvt( ei_local, rx_dma_owner_idx0 ); ++ #endif /* CONFIG_RAETH_PDMA_DVT */ ++#endif ++ rx_skb->len = length; ++/*TODO*/ ++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA) ++ rx_skb->data += NET_IP_ALIGN; ++#endif ++ rx_skb->tail = rx_skb->data + length; ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++ if(rx_ring[rx_dma_owner_idx].rxd_info4.SP == 2) { ++ if(ei_local->PseudoDev!=NULL) { ++ rx_skb->dev = ei_local->PseudoDev; ++ rx_skb->protocol = eth_type_trans(rx_skb,ei_local->PseudoDev); ++ }else { ++ printk("ERROR: PseudoDev is still not initialize but receive packet from GMAC2\n"); ++ } ++ }else{ ++ rx_skb->dev = dev; ++ rx_skb->protocol = eth_type_trans(rx_skb,dev); ++ } ++#else ++ rx_skb->dev = dev; ++ rx_skb->protocol = eth_type_trans(rx_skb,dev); ++#endif ++ ++#ifdef CONFIG_RAETH_CHECKSUM_OFFLOAD ++#if defined (CONFIG_PDMA_NEW) ++ if(rx_ring[rx_dma_owner_idx].rxd_info4.L4VLD) { ++ rx_skb->ip_summed = CHECKSUM_UNNECESSARY; ++ }else { ++ rx_skb->ip_summed = CHECKSUM_NONE; ++ } ++#else ++ if(rx_ring[rx_dma_owner_idx].rxd_info4.IPFVLD_bit) { ++ rx_skb->ip_summed = CHECKSUM_UNNECESSARY; ++ }else { ++ rx_skb->ip_summed = CHECKSUM_NONE; ++ } ++#endif ++#else ++ rx_skb->ip_summed = CHECKSUM_NONE; ++#endif ++ ++#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE) ++ /* Qwert+ ++ */ ++ if(ra_classifier_hook_rx!= NULL) ++ { ++#if defined(CONFIG_RALINK_EXTERNAL_TIMER) ++ ra_classifier_hook_rx(rx_skb, (*((volatile u32 *)(0xB0000D08))&0x0FFFF)); ++#else ++ ra_classifier_hook_rx(rx_skb, read_c0_count()); ++#endif ++ } ++#endif /* CONFIG_RA_CLASSIFIER */ ++ ++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) ++ if(ra_sw_nat_hook_rx != NULL) { ++ FOE_MAGIC_TAG(rx_skb)= FOE_MAGIC_GE; ++ *(uint32_t *)(FOE_INFO_START_ADDR(rx_skb)+2) = *(uint32_t *)&rx_ring[rx_dma_owner_idx].rxd_info4; ++ FOE_ALG(rx_skb) = 0; ++ } ++#endif ++ ++ /* We have to check the free memory size is big enough ++ * before pass the packet to cpu*/ ++#if defined (CONFIG_RAETH_SKB_RECYCLE_2K) ++#if defined (CONFIG_RAETH_HW_LRO) ++ if( rx_ring != ei_local->rx_ring0 ) ++ skb = __dev_alloc_skb(MAX_LRO_RX_LENGTH + NET_IP_ALIGN, GFP_ATOMIC); ++ else ++#endif /* CONFIG_RAETH_HW_LRO */ ++ skb = skbmgr_dev_alloc_skb2k(); ++#else ++#if defined (CONFIG_RAETH_HW_LRO) ++ if( rx_ring != ei_local->rx_ring0 ) ++ skb = __dev_alloc_skb(MAX_LRO_RX_LENGTH + NET_IP_ALIGN, GFP_ATOMIC); ++ else ++#endif /* CONFIG_RAETH_HW_LRO */ ++ skb = __dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN, GFP_ATOMIC); ++#endif ++ ++ if (unlikely(skb == NULL)) ++ { ++ printk(KERN_ERR "skb not available...\n"); ++#ifdef CONFIG_PSEUDO_SUPPORT ++ if (rx_ring[rx_dma_owner_idx].rxd_info4.SP == 2) { ++ if (ei_local->PseudoDev != NULL) { ++ pAd = netdev_priv(ei_local->PseudoDev); ++ pAd->stat.rx_dropped++; ++ } ++ } else ++#endif ++ ei_local->stat.rx_dropped++; ++ bReschedule = 1; ++ break; ++ } ++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA) ++ skb_reserve(skb, NET_IP_ALIGN); ++#endif ++ ++#if defined (CONFIG_RAETH_SPECIAL_TAG) ++ // port0: 0x8100 => 0x8100 0001 ++ // port1: 0x8101 => 0x8100 0002 ++ // port2: 0x8102 => 0x8100 0003 ++ // port3: 0x8103 => 0x8100 0004 ++ // port4: 0x8104 => 0x8100 0005 ++ // port5: 0x8105 => 0x8100 0006 ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21) ++ veth = (struct vlan_ethhdr *)(rx_skb->mac_header); ++#else ++ veth = (struct vlan_ethhdr *)(rx_skb->mac.raw); ++#endif ++ /*donot check 0x81 due to MT7530 SPEC*/ ++ //if((veth->h_vlan_proto & 0xFF) == 0x81) ++ { ++ veth->h_vlan_TCI = htons( (((veth->h_vlan_proto >> 8) & 0xF) + 1) ); ++ rx_skb->protocol = veth->h_vlan_proto = htons(ETH_P_8021Q); ++ } ++#endif ++ ++/* ra_sw_nat_hook_rx return 1 --> continue ++ * ra_sw_nat_hook_rx return 0 --> FWD & without netif_rx ++ */ ++#if !defined(CONFIG_RA_NAT_NONE) ++ if((ra_sw_nat_hook_rx == NULL) || ++ (ra_sw_nat_hook_rx!= NULL && ra_sw_nat_hook_rx(rx_skb))) ++#endif ++ { ++#if defined (CONFIG_RALINK_RT3052_MP2) ++ if(mcast_rx(rx_skb)==0) { ++ kfree_skb(rx_skb); ++ }else ++#endif ++#if defined (CONFIG_RAETH_LRO) ++ if (rx_skb->ip_summed == CHECKSUM_UNNECESSARY) { ++ lro_receive_skb(&ei_local->lro_mgr, rx_skb, NULL); ++ //LroStatsUpdate(&ei_local->lro_mgr,0); ++ } else ++#endif ++#ifdef CONFIG_RAETH_NAPI ++ netif_receive_skb(rx_skb); ++#else ++#ifdef CONFIG_RAETH_HW_VLAN_RX ++ if(ei_local->vlgrp && rx_ring[rx_dma_owner_idx].rxd_info2.TAG) { ++ vlan_hwaccel_rx(rx_skb, ei_local->vlgrp, rx_ring[rx_dma_owner_idx].rxd_info3.VID); ++ } else { ++ netif_rx(rx_skb); ++ } ++#else ++#ifdef CONFIG_RAETH_CPU_LOOPBACK ++ skb_push(rx_skb,ETH_HLEN); ++ ei_start_xmit(rx_skb, dev, 1); ++#else ++ netif_rx(rx_skb); ++#endif ++#endif ++#endif ++ } ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++ if (rx_ring[rx_dma_owner_idx].rxd_info4.SP == 2) { ++ if (ei_local->PseudoDev != NULL) { ++ pAd = netdev_priv(ei_local->PseudoDev); ++ pAd->stat.rx_packets++; ++ pAd->stat.rx_bytes += length; ++ } ++ } else ++#endif ++ { ++ ei_local->stat.rx_packets++; ++ ei_local->stat.rx_bytes += length; ++ } ++ ++ ++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA) ++#if defined (CONFIG_RAETH_HW_LRO) ++ if( rx_ring != ei_local->rx_ring0 ){ ++ rx_ring[rx_dma_owner_idx].rxd_info2.PLEN0 = SET_ADMA_RX_LEN0(MAX_LRO_RX_LENGTH); ++ rx_ring[rx_dma_owner_idx].rxd_info2.PLEN1 = SET_ADMA_RX_LEN1(MAX_LRO_RX_LENGTH >> 14); ++ } ++ else ++#endif /* CONFIG_RAETH_HW_LRO */ ++ rx_ring[rx_dma_owner_idx].rxd_info2.PLEN0 = MAX_RX_LENGTH; ++ rx_ring[rx_dma_owner_idx].rxd_info2.LS0 = 0; ++#endif ++ rx_ring[rx_dma_owner_idx].rxd_info2.DDONE_bit = 0; ++#if defined (CONFIG_RAETH_HW_LRO) ++ if( rx_ring != ei_local->rx_ring0 ) ++ rx_ring[rx_dma_owner_idx].rxd_info1.PDP0 = dma_map_single(NULL, skb->data, MAX_LRO_RX_LENGTH, PCI_DMA_FROMDEVICE); ++ else ++#endif /* CONFIG_RAETH_HW_LRO */ ++ rx_ring[rx_dma_owner_idx].rxd_info1.PDP0 = dma_map_single(NULL, skb->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE); ++#ifdef CONFIG_32B_DESC ++ dma_cache_sync(NULL, &rx_ring[rx_dma_owner_idx], sizeof(struct PDMA_rxdesc), DMA_TO_DEVICE); ++#endif ++ /* Move point to next RXD which wants to alloc*/ ++#if defined (CONFIG_RAETH_HW_LRO) ++ if(rx_ring_no==3) { ++ sysRegWrite(RAETH_RX_CALC_IDX3, rx_dma_owner_idx); ++ ei_local->netrx3_skbuf[rx_dma_owner_idx] = skb; ++ } ++ else if(rx_ring_no==2) { ++ sysRegWrite(RAETH_RX_CALC_IDX2, rx_dma_owner_idx); ++ ei_local->netrx2_skbuf[rx_dma_owner_idx] = skb; ++ } ++ else if(rx_ring_no==1) { ++ sysRegWrite(RAETH_RX_CALC_IDX1, rx_dma_owner_idx); ++ ei_local->netrx1_skbuf[rx_dma_owner_idx] = skb; ++ } ++ else if(rx_ring_no==0) { ++ sysRegWrite(RAETH_RX_CALC_IDX0, rx_dma_owner_idx); ++ ei_local->netrx0_skbuf[rx_dma_owner_idx] = skb; ++ } ++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++ if(rx_ring_no==0) { ++ sysRegWrite(RAETH_RX_CALC_IDX0, rx_dma_owner_idx); ++ ei_local->netrx0_skbuf[rx_dma_owner_idx] = skb; ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ rx_calc_idx0 = rx_dma_owner_idx; ++#endif ++ } ++#if defined(CONFIG_ARCH_MT7623) ++ else if(rx_ring_no==3) { ++ sysRegWrite(RAETH_RX_CALC_IDX3, rx_dma_owner_idx); ++ ei_local->netrx3_skbuf[rx_dma_owner_idx] = skb; ++ } ++ else if(rx_ring_no==2) { ++ sysRegWrite(RAETH_RX_CALC_IDX2, rx_dma_owner_idx); ++ ei_local->netrx2_skbuf[rx_dma_owner_idx] = skb; ++ } ++#endif /* CONFIG_ARCH_MT7623 */ ++ else { ++ sysRegWrite(RAETH_RX_CALC_IDX1, rx_dma_owner_idx); ++ ei_local->netrx1_skbuf[rx_dma_owner_idx] = skb; ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ rx_calc_idx1 = rx_dma_owner_idx; ++#endif ++ } ++#else ++ sysRegWrite(RAETH_RX_CALC_IDX0, rx_dma_owner_idx); ++ ei_local->netrx0_skbuf[rx_dma_owner_idx] = skb; ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ rx_calc_idx0 = rx_dma_owner_idx; ++#endif ++#endif ++ ++ ++ /* Update to Next packet point that was received. ++ */ ++#if defined (CONFIG_RAETH_HW_LRO) ++ if(rx_ring_no==3) ++ rx_dma_owner_lro3 = (sysRegRead(RAETH_RX_CALC_IDX3) + 1) % NUM_LRO_RX_DESC; ++ else if(rx_ring_no==2) ++ rx_dma_owner_lro2 = (sysRegRead(RAETH_RX_CALC_IDX2) + 1) % NUM_LRO_RX_DESC; ++ else if(rx_ring_no==1) ++ rx_dma_owner_lro1 = (sysRegRead(RAETH_RX_CALC_IDX1) + 1) % NUM_LRO_RX_DESC; ++ else if(rx_ring_no==0) ++ rx_dma_owner_idx0 = (sysRegRead(RAETH_RX_CALC_IDX0) + 1) % NUM_RX_DESC; ++ else { ++ } ++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++ if(rx_ring_no==0) { ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ rx_dma_owner_idx0 = (rx_dma_owner_idx + 1) % NUM_RX_DESC; ++#else ++ rx_dma_owner_idx0 = (sysRegRead(RAETH_RX_CALC_IDX0) + 1) % NUM_RX_DESC; ++#endif ++#if defined(CONFIG_ARCH_MT7623) ++ }else if(rx_ring_no==3) { ++ rx_dma_owner_idx3 = (sysRegRead(RAETH_RX_CALC_IDX3) + 1) % NUM_RX_DESC; ++ }else if(rx_ring_no==2) { ++ rx_dma_owner_idx2 = (sysRegRead(RAETH_RX_CALC_IDX2) + 1) % NUM_RX_DESC; ++#endif /* CONFIG_ARCH_MT7623 */ ++ }else { ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ rx_dma_owner_idx1 = (rx_dma_owner_idx + 1) % NUM_RX_DESC; ++#else ++ rx_dma_owner_idx1 = (sysRegRead(RAETH_RX_CALC_IDX1) + 1) % NUM_RX_DESC; ++#endif ++ } ++#else ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ rx_dma_owner_idx0 = (rx_dma_owner_idx + 1) % NUM_RX_DESC; ++#else ++ rx_dma_owner_idx0 = (sysRegRead(RAETH_RX_CALC_IDX0) + 1) % NUM_RX_DESC; ++#endif ++#endif ++ } /* for */ ++ ++#if defined (CONFIG_RAETH_LRO) ++ if (lro_flush_needed) { ++ //LroStatsUpdate(&ei_local->lro_mgr,1); ++ lro_flush_all(&ei_local->lro_mgr); ++ lro_flush_needed = 0; ++ } ++#endif ++ return bReschedule; ++} ++ ++ ++/////////////////////////////////////////////////////////////////// ++///// ++///// ra_get_stats - gather packet information for management plane ++///// ++///// Pass net_device_stats to the upper layer. ++///// ++///// ++///// RETURNS: pointer to net_device_stats ++/////////////////////////////////////////////////////////////////// ++ ++struct net_device_stats *ra_get_stats(struct net_device *dev) ++{ ++ END_DEVICE *ei_local = netdev_priv(dev); ++ return &ei_local->stat; ++} ++ ++#if defined (CONFIG_RT_3052_ESW) ++void kill_sig_workq(struct work_struct *work) ++{ ++ struct file *fp; ++ char pid[8]; ++ struct task_struct *p = NULL; ++ ++ //read udhcpc pid from file, and send signal USR2,USR1 to get a new IP ++ fp = filp_open("/var/run/udhcpc.pid", O_RDONLY, 0); ++ if (IS_ERR(fp)) ++ return; ++ ++ if (fp->f_op && fp->f_op->read) { ++ if (fp->f_op->read(fp, pid, 8, &fp->f_pos) > 0) { ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ p = pid_task(find_get_pid(simple_strtoul(pid, NULL, 10)), PIDTYPE_PID); ++#else ++ p = find_task_by_pid(simple_strtoul(pid, NULL, 10)); ++#endif ++ ++ if (NULL != p) { ++ send_sig(SIGUSR2, p, 0); ++ send_sig(SIGUSR1, p, 0); ++ } ++ } ++ } ++ filp_close(fp, NULL); ++ ++} ++#endif ++ ++ ++/////////////////////////////////////////////////////////////////// ++///// ++///// ra2880Recv - process the next incoming packet ++///// ++///// Handle one incoming packet. The packet is checked for errors and sent ++///// to the upper layer. ++///// ++///// RETURNS: OK on success or ERROR. ++/////////////////////////////////////////////////////////////////// ++ ++#ifndef CONFIG_RAETH_NAPI ++#if defined WORKQUEUE_BH || defined (TASKLET_WORKQUEUE_SW) ++void ei_receive_workq(struct work_struct *work) ++#else ++void ei_receive(unsigned long unused) // device structure ++#endif // WORKQUEUE_BH // ++{ ++ struct net_device *dev = dev_raether; ++ END_DEVICE *ei_local = netdev_priv(dev); ++ unsigned long reg_int_mask=0; ++ int bReschedule=0; ++ ++ ++ if(tx_ring_full==0){ ++ bReschedule = rt2880_eth_recv(dev); ++ if(bReschedule) ++ { ++#ifdef WORKQUEUE_BH ++ schedule_work(&ei_local->rx_wq); ++#else ++#if defined (TASKLET_WORKQUEUE_SW) ++ if (working_schedule == 1) ++ schedule_work(&ei_local->rx_wq); ++ else ++#endif ++ tasklet_hi_schedule(&ei_local->rx_tasklet); ++#endif // WORKQUEUE_BH // ++ }else{ ++ reg_int_mask=sysRegRead(RAETH_FE_INT_ENABLE); ++#if defined(DELAY_INT) ++ sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask| RX_DLY_INT); ++#else ++ sysRegWrite(RAETH_FE_INT_ENABLE, (reg_int_mask | RX_DONE_INT0 | RX_DONE_INT1 | RX_DONE_INT2 | RX_DONE_INT3)); ++#endif ++#ifdef CONFIG_RAETH_QDMA ++ reg_int_mask=sysRegRead(QFE_INT_ENABLE); ++#if defined(DELAY_INT) ++ sysRegWrite(QFE_INT_ENABLE, reg_int_mask| RX_DLY_INT); ++#else ++ sysRegWrite(QFE_INT_ENABLE, (reg_int_mask | RX_DONE_INT0 | RX_DONE_INT1)); ++#endif ++ ++#endif ++ ++ } ++ }else{ ++#ifdef WORKQUEUE_BH ++ schedule_work(&ei_local->rx_wq); ++#else ++#if defined (TASKLET_WORKQUEUE_SW) ++ if (working_schedule == 1) ++ schedule_work(&ei_local->rx_wq); ++ else ++#endif ++ tasklet_schedule(&ei_local->rx_tasklet); ++#endif // WORKQUEUE_BH // ++ } ++} ++#endif ++ ++#if defined (CONFIG_RAETH_HW_LRO) ++void ei_hw_lro_auto_adj(unsigned int index, END_DEVICE* ei_local) ++{ ++ unsigned int entry; ++ unsigned int pkt_cnt; ++ unsigned int tick_cnt; ++ unsigned int duration_us; ++ unsigned int byte_cnt; ++ ++ /* read packet count statitics of the auto-learn table */ ++ entry = index + 68; ++ sysRegWrite( PDMA_FE_ALT_CF8, entry ); ++ pkt_cnt = sysRegRead(PDMA_FE_ALT_SGL_CFC) & 0xfff; ++ tick_cnt = (sysRegRead(PDMA_FE_ALT_SGL_CFC) >> 16) & 0xffff; ++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG) ++ printk("[HW LRO] ei_hw_lro_auto_adj(): pkt_cnt[%d]=%d, tick_cnt[%d]=%d\n", index, pkt_cnt, index, tick_cnt); ++ printk("[HW LRO] ei_hw_lro_auto_adj(): packet_interval[%d]=%d (ticks/pkt)\n", index, tick_cnt/pkt_cnt); ++#endif ++ ++ /* read byte count statitics of the auto-learn table */ ++ entry = index + 64; ++ sysRegWrite( PDMA_FE_ALT_CF8, entry ); ++ byte_cnt = sysRegRead(PDMA_FE_ALT_SGL_CFC); ++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG) ++ printk("[HW LRO] ei_hw_lro_auto_adj(): byte_cnt[%d]=%d\n", index, byte_cnt); ++#endif ++ ++ /* calculate the packet interval of the rx flow */ ++ duration_us = tick_cnt * HW_LRO_TIMER_UNIT; ++ ei_local->hw_lro_pkt_interval[index - 1] = (duration_us/pkt_cnt) * ei_local->hw_lro_alpha / 100; ++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG) ++ printk("[HW LRO] ei_hw_lro_auto_adj(): packet_interval[%d]=%d (20us)\n", index, duration_us/pkt_cnt); ++#endif ++ ++ if ( !ei_local->hw_lro_fix_setting ){ ++ /* adjust age_time, agg_time for the lro ring */ ++ if(ei_local->hw_lro_pkt_interval[index - 1] > 0){ ++ SET_PDMA_RXRING_AGE_TIME(index, (ei_local->hw_lro_pkt_interval[index - 1] * HW_LRO_MAX_AGG_CNT)); ++ SET_PDMA_RXRING_AGG_TIME(index, (ei_local->hw_lro_pkt_interval[index - 1] * HW_LRO_AGG_DELTA)); ++ } ++ else{ ++ SET_PDMA_RXRING_AGE_TIME(index, HW_LRO_MAX_AGG_CNT); ++ SET_PDMA_RXRING_AGG_TIME(index, HW_LRO_AGG_DELTA); ++ } ++ } ++} ++ ++void ei_hw_lro_workq(struct work_struct *work) ++{ ++ END_DEVICE *ei_local; ++ unsigned int reg_int_val; ++ unsigned int reg_int_mask; ++ ++ ei_local = container_of(work, struct end_device, hw_lro_wq); ++ ++ reg_int_val = sysRegRead(RAETH_FE_INT_STATUS); ++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG) ++ printk("[HW LRO] ei_hw_lro_workq(): RAETH_FE_INT_STATUS=0x%x\n", reg_int_val); ++#endif ++ if((reg_int_val & ALT_RPLC_INT3)){ ++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG) ++ printk("[HW LRO] ALT_RPLC_INT3 occurred!\n"); ++#endif ++ sysRegWrite(RAETH_FE_INT_STATUS, ALT_RPLC_INT3); ++ ei_hw_lro_auto_adj(3, ei_local); ++ } ++ if((reg_int_val & ALT_RPLC_INT2)){ ++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG) ++ printk("[HW LRO] ALT_RPLC_INT2 occurred!\n"); ++#endif ++ sysRegWrite(RAETH_FE_INT_STATUS, ALT_RPLC_INT2); ++ ei_hw_lro_auto_adj(2, ei_local); ++ } ++ if((reg_int_val & ALT_RPLC_INT1)){ ++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG) ++ printk("[HW LRO] ALT_RPLC_INT1 occurred!\n"); ++#endif ++ sysRegWrite(RAETH_FE_INT_STATUS, ALT_RPLC_INT1); ++ ei_hw_lro_auto_adj(1, ei_local); ++ } ++ ++ /* unmask interrupts of rx flow to hw lor rings */ ++ reg_int_mask = sysRegRead(RAETH_FE_INT_ENABLE); ++ sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask | ALT_RPLC_INT3 | ALT_RPLC_INT2 | ALT_RPLC_INT1); ++} ++#endif /* CONFIG_RAETH_HW_LRO */ ++ ++#ifdef CONFIG_RAETH_NAPI ++static int ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++raeth_clean(struct napi_struct *napi, int budget) ++#else ++raeth_clean(struct net_device *netdev, int *budget) ++#endif ++{ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ struct net_device *netdev=dev_raether; ++ int work_to_do = budget; ++#else ++ int work_to_do = min(*budget, netdev->quota); ++#endif ++ END_DEVICE *ei_local =netdev_priv(netdev); ++ int work_done = 0; ++ unsigned long reg_int_mask=0; ++ ++ ei_xmit_housekeeping(0); ++ ++ rt2880_eth_recv(netdev, &work_done, work_to_do); ++ ++ /* this could control when to re-enable interrupt, 0-> mean never enable interrupt*/ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ++ *budget -= work_done; ++ netdev->quota -= work_done; ++#endif ++ /* if no Tx and not enough Rx work done, exit the polling mode */ ++ if(( (work_done < work_to_do)) || !netif_running(netdev)) { ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ napi_complete(&ei_local->napi); ++#else ++ netif_rx_complete(netdev); ++#endif ++ atomic_dec_and_test(&ei_local->irq_sem); ++ ++ sysRegWrite(RAETH_FE_INT_STATUS, RAETH_FE_INT_ALL); // ack all fe interrupts ++ reg_int_mask=sysRegRead(RAETH_FE_INT_ENABLE); ++ ++#ifdef DELAY_INT ++ sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask |RAETH_FE_INT_DLY_INIT); // init delay interrupt only ++#else ++ sysRegWrite(RAETH_FE_INT_ENABLE,reg_int_mask | RAETH_FE_INT_SETTING); ++#endif ++ ++#ifdef CONFIG_RAETH_QDMA ++ sysRegWrite(QFE_INT_STATUS, QFE_INT_ALL); ++ reg_int_mask=sysRegRead(QFE_INT_ENABLE); ++#ifdef DELAY_INT ++ sysRegWrite(QFE_INT_ENABLE, reg_int_mask |QFE_INT_DLY_INIT); // init delay interrupt only ++#else ++ sysRegWrite(QFE_INT_ENABLE,reg_int_mask | (RX_DONE_INT0 | RX_DONE_INT1 | RLS_DONE_INT)); ++#endif ++#endif // CONFIG_RAETH_QDMA // ++ ++ return 0; ++ } ++ ++ return 1; ++} ++ ++#endif ++ ++ ++void gsw_delay_setting(void) ++{ ++#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN) || defined (CONFIG_GE_RGMII_INTERNAL_P4_AN) ++ END_DEVICE *ei_local = netdev_priv(dev_raether); ++ int reg_int_val = 0; ++ int link_speed = 0; ++ ++ reg_int_val = sysRegRead(FE_INT_STATUS2); ++#if defined (CONFIG_RALINK_MT7621) ++ if( reg_int_val & BIT(25)) ++ { ++ if(sysRegRead(RALINK_ETH_SW_BASE+0x0208) & 0x1) // link up ++ { ++ link_speed = (sysRegRead(RALINK_ETH_SW_BASE+0x0208)>>2 & 0x3); ++ if(link_speed == 1) ++ { ++ // delay setting for 100M ++ if((sysRegRead(0xbe00000c)&0xFFFF)==0x0101) ++ mii_mgr_write(31, 0x7b00, 8); ++ printk("MT7621 GE2 link rate to 100M\n"); ++ } else ++ { ++ //delay setting for 10/1000M ++ if((sysRegRead(0xbe00000c)&0xFFFF)==0x0101) ++ mii_mgr_write(31, 0x7b00, 0x102); ++ printk("MT7621 GE2 link rate to 10M/1G\n"); ++ } ++ schedule_work(&ei_local->kill_sig_wq); ++ } ++ } ++#endif ++ sysRegWrite(FE_INT_STATUS2, reg_int_val); ++#endif ++} ++ ++/** ++ * ei_interrupt - handle controler interrupt ++ * ++ * This routine is called at interrupt level in response to an interrupt from ++ * the controller. ++ * ++ * RETURNS: N/A. ++ */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) ++static irqreturn_t ei_interrupt(int irq, void *dev_id) ++#else ++static irqreturn_t ei_interrupt(int irq, void *dev_id, struct pt_regs * regs) ++#endif ++{ ++#if !defined(CONFIG_RAETH_NAPI) ++ unsigned long reg_int_val; ++ unsigned long reg_int_mask=0; ++ unsigned int recv = 0; ++ unsigned int transmit __maybe_unused = 0; ++ unsigned long flags; ++#endif ++ ++ struct net_device *dev = (struct net_device *) dev_id; ++ END_DEVICE *ei_local = netdev_priv(dev); ++ ++ //Qwert ++ /* ++ unsigned long old,cur,dcycle; ++ static int cnt = 0; ++ static unsigned long max_dcycle = 0,tcycle = 0; ++ old = read_c0_count(); ++ */ ++ if (dev == NULL) ++ { ++ printk (KERN_ERR "net_interrupt(): irq %x for unknown device.\n", IRQ_ENET0); ++ return IRQ_NONE; ++ } ++ ++#ifdef CONFIG_RAETH_NAPI ++ gsw_delay_setting(); ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ if(napi_schedule_prep(&ei_local->napi)) { ++#else ++ if(netif_rx_schedule_prep(dev)) { ++#endif ++ atomic_inc(&ei_local->irq_sem); ++ sysRegWrite(RAETH_FE_INT_ENABLE, 0); ++#ifdef CONFIG_RAETH_QDMA ++ sysRegWrite(QFE_INT_ENABLE, 0); ++#endif ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ __napi_schedule(&ei_local->napi); ++#else ++ __netif_rx_schedule(dev); ++#endif ++ } ++#else ++ ++ spin_lock_irqsave(&(ei_local->page_lock), flags); ++ reg_int_val = sysRegRead(RAETH_FE_INT_STATUS); ++#ifdef CONFIG_RAETH_QDMA ++ reg_int_val |= sysRegRead(QFE_INT_STATUS); ++#endif ++#if defined (DELAY_INT) ++ if((reg_int_val & RX_DLY_INT)) ++ recv = 1; ++ ++ if (reg_int_val & RAETH_TX_DLY_INT) ++ transmit = 1; ++ ++#if defined(CONFIG_RAETH_PDMA_DVT) ++ raeth_pdma_lro_dly_int_dvt(); ++#endif /* CONFIG_RAETH_PDMA_DVT */ ++ ++#else ++ if((reg_int_val & (RX_DONE_INT0 | RX_DONE_INT3 | RX_DONE_INT2 | RX_DONE_INT1))) ++ recv = 1; ++ ++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++#if defined(CONFIG_ARCH_MT7623) ++ if((reg_int_val & RX_DONE_INT3)) ++ recv = 3; ++ if((reg_int_val & RX_DONE_INT2)) ++ recv = 2; ++#endif /* CONFIG_ARCH_MT7623 */ ++ if((reg_int_val & RX_DONE_INT1)) ++ recv = 1; ++#endif ++ ++ if (reg_int_val & RAETH_TX_DONE_INT0) ++ transmit |= RAETH_TX_DONE_INT0; ++#if defined (CONFIG_RAETH_QOS) ++ if (reg_int_val & TX_DONE_INT1) ++ transmit |= TX_DONE_INT1; ++ if (reg_int_val & TX_DONE_INT2) ++ transmit |= TX_DONE_INT2; ++ if (reg_int_val & TX_DONE_INT3) ++ transmit |= TX_DONE_INT3; ++#endif //CONFIG_RAETH_QOS ++ ++#endif //DELAY_INT ++ ++#if defined (DELAY_INT) ++ sysRegWrite(RAETH_FE_INT_STATUS, RAETH_FE_INT_DLY_INIT); ++#else ++ sysRegWrite(RAETH_FE_INT_STATUS, RAETH_FE_INT_ALL); ++#endif ++#ifdef CONFIG_RAETH_QDMA ++#if defined (DELAY_INT) ++ sysRegWrite(QFE_INT_STATUS, QFE_INT_DLY_INIT); ++#else ++ sysRegWrite(QFE_INT_STATUS, QFE_INT_ALL); ++#endif ++#endif ++ ++#if defined (CONFIG_RAETH_HW_LRO) ++ if( reg_int_val & (ALT_RPLC_INT3 | ALT_RPLC_INT2 | ALT_RPLC_INT1) ){ ++ /* mask interrupts of rx flow to hw lor rings */ ++ reg_int_mask = sysRegRead(RAETH_FE_INT_ENABLE); ++ sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask & ~(ALT_RPLC_INT3 | ALT_RPLC_INT2 | ALT_RPLC_INT1)); ++ schedule_work(&ei_local->hw_lro_wq); ++ } ++#endif /* CONFIG_RAETH_HW_LRO */ ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0) ++ if(transmit) ++ ei_xmit_housekeeping(0); ++#else ++ ei_xmit_housekeeping(0); ++#endif ++ ++ if (((recv == 1) || (pending_recv ==1)) && (tx_ring_full==0)) ++ { ++ reg_int_mask = sysRegRead(RAETH_FE_INT_ENABLE); ++#if defined (DELAY_INT) ++ sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask & ~(RX_DLY_INT)); ++#else ++ sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask & ~(RX_DONE_INT0 | RX_DONE_INT1 | RX_DONE_INT2 | RX_DONE_INT3)); ++#endif //DELAY_INT ++#ifdef CONFIG_RAETH_QDMA ++ reg_int_mask = sysRegRead(QFE_INT_ENABLE); ++#if defined (DELAY_INT) ++ sysRegWrite(QFE_INT_ENABLE, reg_int_mask & ~(RX_DLY_INT)); ++#else ++ sysRegWrite(QFE_INT_ENABLE, reg_int_mask & ~(RX_DONE_INT0 | RX_DONE_INT1 | RX_DONE_INT2 | RX_DONE_INT3)); ++#endif //DELAY_INT ++#endif ++ ++ pending_recv=0; ++#ifdef WORKQUEUE_BH ++ schedule_work(&ei_local->rx_wq); ++#else ++#if defined (TASKLET_WORKQUEUE_SW) ++ if (working_schedule == 1) ++ schedule_work(&ei_local->rx_wq); ++ else ++#endif ++ tasklet_hi_schedule(&ei_local->rx_tasklet); ++#endif // WORKQUEUE_BH // ++ } ++ else if (recv == 1 && tx_ring_full==1) ++ { ++ pending_recv=1; ++ } ++ else if((recv == 0) && (transmit == 0)) ++ { ++ gsw_delay_setting(); ++ } ++ spin_unlock_irqrestore(&(ei_local->page_lock), flags); ++#endif ++ ++ return IRQ_HANDLED; ++} ++ ++#if defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620)|| defined (CONFIG_RALINK_MT7621) ++static void esw_link_status_changed(int port_no, void *dev_id) ++{ ++ unsigned int reg_val; ++ struct net_device *dev = (struct net_device *) dev_id; ++ END_DEVICE *ei_local = netdev_priv(dev); ++ ++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) ++ reg_val = *((volatile u32 *)(RALINK_ETH_SW_BASE+ 0x3008 + (port_no*0x100))); ++#elif defined (CONFIG_RALINK_MT7621) ++ mii_mgr_read(31, (0x3008 + (port_no*0x100)), ®_val); ++#endif ++ if(reg_val & 0x1) { ++ printk("ESW: Link Status Changed - Port%d Link UP\n", port_no); ++#if defined (CONFIG_RALINK_MT7621) && defined (CONFIG_RAETH_8023AZ_EEE) ++ mii_mgr_write(port_no, 31, 0x52b5); ++ mii_mgr_write(port_no, 16, 0xb780); ++ mii_mgr_write(port_no, 17, 0x00e0); ++ mii_mgr_write(port_no, 16, 0x9780); ++#endif ++ ++#if defined (CONFIG_WAN_AT_P0) ++ if(port_no==0) { ++ schedule_work(&ei_local->kill_sig_wq); ++ } ++#elif defined (CONFIG_WAN_AT_P4) ++ if(port_no==4) { ++ schedule_work(&ei_local->kill_sig_wq); ++ } ++#endif ++ } else { ++ printk("ESW: Link Status Changed - Port%d Link Down\n", port_no); ++#if defined (CONFIG_RALINK_MT7621) && defined (CONFIG_RAETH_8023AZ_EEE) ++ mii_mgr_write(port_no, 31, 0x52b5); ++ mii_mgr_write(port_no, 16, 0xb780); ++ mii_mgr_write(port_no, 17, 0x0000); ++ mii_mgr_write(port_no, 16, 0x9780); ++#endif ++ ++ } ++} ++#endif ++ ++#if defined (CONFIG_RT_3052_ESW) && ! defined(CONFIG_RALINK_MT7621) && ! defined(CONFIG_ARCH_MT7623) ++static irqreturn_t esw_interrupt(int irq, void *dev_id) ++{ ++ unsigned long flags; ++ unsigned long reg_int_val; ++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined(CONFIG_RALINK_MT7620) ++ unsigned long acl_int_val; ++ unsigned long mib_int_val; ++#else ++ static unsigned long stat; ++ unsigned long stat_curr; ++#endif ++ ++ struct net_device *dev = (struct net_device *) dev_id; ++ END_DEVICE *ei_local = netdev_priv(dev); ++ ++ ++ spin_lock_irqsave(&(ei_local->page_lock), flags); ++ reg_int_val = (*((volatile u32 *)(ESW_ISR))); //Interrupt Status Register ++ ++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined(CONFIG_RALINK_MT7620) ++ if (reg_int_val & P5_LINK_CH) { ++ esw_link_status_changed(5, dev_id); ++ } ++ if (reg_int_val & P4_LINK_CH) { ++ esw_link_status_changed(4, dev_id); ++ } ++ if (reg_int_val & P3_LINK_CH) { ++ esw_link_status_changed(3, dev_id); ++ } ++ if (reg_int_val & P2_LINK_CH) { ++ esw_link_status_changed(2, dev_id); ++ } ++ if (reg_int_val & P1_LINK_CH) { ++ esw_link_status_changed(1, dev_id); ++ } ++ if (reg_int_val & P0_LINK_CH) { ++ esw_link_status_changed(0, dev_id); ++ } ++ if (reg_int_val & ACL_INT) { ++ acl_int_val = sysRegRead(ESW_AISR); ++ sysRegWrite(ESW_AISR, acl_int_val); ++ } ++ if (reg_int_val & MIB_INT) { ++ ++ mib_int_val = sysRegRead(ESW_P0_IntSn); ++ if(mib_int_val){ ++ sysRegWrite(ESW_P0_IntSn, mib_int_val); ++ if(mib_int_val & RX_GOOD_CNT) ++ p0_rx_good_cnt ++; ++ if(mib_int_val & TX_GOOD_CNT) ++ p0_tx_good_cnt ++; ++ if(mib_int_val & RX_GOCT_CNT) ++ p0_rx_byte_cnt ++; ++ if(mib_int_val & TX_GOCT_CNT) ++ p0_tx_byte_cnt ++; ++ } ++ ++ mib_int_val = sysRegRead(ESW_P1_IntSn); ++ if(mib_int_val){ ++ sysRegWrite(ESW_P1_IntSn, mib_int_val); ++ if(mib_int_val & RX_GOOD_CNT) ++ p1_rx_good_cnt ++; ++ if(mib_int_val & TX_GOOD_CNT) ++ p1_tx_good_cnt ++; ++ if(mib_int_val & RX_GOCT_CNT) ++ p1_rx_byte_cnt ++; ++ if(mib_int_val & TX_GOCT_CNT) ++ p1_tx_byte_cnt ++; ++ } ++ ++ mib_int_val = sysRegRead(ESW_P2_IntSn); ++ if(mib_int_val){ ++ sysRegWrite(ESW_P2_IntSn, mib_int_val); ++ if(mib_int_val & RX_GOOD_CNT) ++ p2_rx_good_cnt ++; ++ if(mib_int_val & TX_GOOD_CNT) ++ p2_tx_good_cnt ++; ++ if(mib_int_val & RX_GOCT_CNT) ++ p2_rx_byte_cnt ++; ++ if(mib_int_val & TX_GOCT_CNT) ++ p2_tx_byte_cnt ++; ++ } ++ ++ ++ mib_int_val = sysRegRead(ESW_P3_IntSn); ++ if(mib_int_val){ ++ sysRegWrite(ESW_P3_IntSn, mib_int_val); ++ if(mib_int_val & RX_GOOD_CNT) ++ p3_rx_good_cnt ++; ++ if(mib_int_val & TX_GOOD_CNT) ++ p3_tx_good_cnt ++; ++ if(mib_int_val & RX_GOCT_CNT) ++ p3_rx_byte_cnt ++; ++ if(mib_int_val & TX_GOCT_CNT) ++ p3_tx_byte_cnt ++; ++ } ++ ++ mib_int_val = sysRegRead(ESW_P4_IntSn); ++ if(mib_int_val){ ++ sysRegWrite(ESW_P4_IntSn, mib_int_val); ++ if(mib_int_val & RX_GOOD_CNT) ++ p4_rx_good_cnt ++; ++ if(mib_int_val & TX_GOOD_CNT) ++ p4_tx_good_cnt ++; ++ if(mib_int_val & RX_GOCT_CNT) ++ p4_rx_byte_cnt ++; ++ if(mib_int_val & TX_GOCT_CNT) ++ p4_tx_byte_cnt ++; ++ } ++ ++ mib_int_val = sysRegRead(ESW_P5_IntSn); ++ if(mib_int_val){ ++ sysRegWrite(ESW_P5_IntSn, mib_int_val); ++ if(mib_int_val & RX_GOOD_CNT) ++ p5_rx_good_cnt ++; ++ if(mib_int_val & TX_GOOD_CNT) ++ p5_tx_good_cnt ++; ++ if(mib_int_val & RX_GOCT_CNT) ++ p5_rx_byte_cnt ++; ++ if(mib_int_val & TX_GOCT_CNT) ++ p5_tx_byte_cnt ++; ++ } ++ ++ mib_int_val = sysRegRead(ESW_P6_IntSn); ++ if(mib_int_val){ ++ sysRegWrite(ESW_P6_IntSn, mib_int_val); ++ if(mib_int_val & RX_GOOD_CNT) ++ p6_rx_good_cnt ++; ++ if(mib_int_val & TX_GOOD_CNT) ++ p6_tx_good_cnt ++; ++ if(mib_int_val & RX_GOCT_CNT) ++ p6_rx_byte_cnt ++; ++ if(mib_int_val & TX_GOCT_CNT) ++ p6_tx_byte_cnt ++; ++ } ++#if defined (CONFIG_RALINK_MT7620) ++ mib_int_val = sysRegRead(ESW_P7_IntSn); ++ if(mib_int_val){ ++ sysRegWrite(ESW_P7_IntSn, mib_int_val); ++ if(mib_int_val & RX_GOOD_CNT) ++ p7_rx_good_cnt ++; ++ if(mib_int_val & TX_GOOD_CNT) ++ p7_tx_good_cnt ++; ++ if(mib_int_val & RX_GOCT_CNT) ++ p7_rx_byte_cnt ++; ++ if(mib_int_val & TX_GOCT_CNT) ++ p7_tx_byte_cnt ++; ++ ++ } ++#endif ++ } ++ ++#else // not RT6855 ++ if (reg_int_val & PORT_ST_CHG) { ++ printk("RT305x_ESW: Link Status Changed\n"); ++ ++ stat_curr = *((volatile u32 *)(RALINK_ETH_SW_BASE+0x80)); ++#ifdef CONFIG_WAN_AT_P0 ++ //link down --> link up : send signal to user application ++ //link up --> link down : ignore ++ if ((stat & (1<<25)) || !(stat_curr & (1<<25))) ++#else ++ if ((stat & (1<<29)) || !(stat_curr & (1<<29))) ++#endif ++ goto out; ++ ++ schedule_work(&ei_local->kill_sig_wq); ++out: ++ stat = stat_curr; ++ } ++ ++#endif // defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A)// ++ ++ sysRegWrite(ESW_ISR, reg_int_val); ++ ++ spin_unlock_irqrestore(&(ei_local->page_lock), flags); ++ return IRQ_HANDLED; ++} ++ ++ ++ ++#elif defined (CONFIG_RT_3052_ESW) && defined(CONFIG_RALINK_MT7621) ++ ++static irqreturn_t esw_interrupt(int irq, void *dev_id) ++{ ++ unsigned long flags; ++ unsigned int reg_int_val; ++ struct net_device *dev = (struct net_device *) dev_id; ++ END_DEVICE *ei_local = netdev_priv(dev); ++ ++ spin_lock_irqsave(&(ei_local->page_lock), flags); ++ mii_mgr_read(31, 0x700c, ®_int_val); ++ ++ if (reg_int_val & P4_LINK_CH) { ++ esw_link_status_changed(4, dev_id); ++ } ++ ++ if (reg_int_val & P3_LINK_CH) { ++ esw_link_status_changed(3, dev_id); ++ } ++ if (reg_int_val & P2_LINK_CH) { ++ esw_link_status_changed(2, dev_id); ++ } ++ if (reg_int_val & P1_LINK_CH) { ++ esw_link_status_changed(1, dev_id); ++ } ++ if (reg_int_val & P0_LINK_CH) { ++ esw_link_status_changed(0, dev_id); ++ } ++ ++ mii_mgr_write(31, 0x700c, 0x1f); //ack switch link change ++ ++ spin_unlock_irqrestore(&(ei_local->page_lock), flags); ++ return IRQ_HANDLED; ++} ++ ++#endif ++ ++ ++static int ei_start_xmit_fake(struct sk_buff* skb, struct net_device *dev) ++{ ++ return ei_start_xmit(skb, dev, 1); ++} ++ ++ ++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) ++void dump_phy_reg(int port_no, int from, int to, int is_local) ++{ ++ u32 i=0; ++ u32 temp=0; ++ ++ if(is_local==0) { ++ printk("Global Register\n"); ++ printk("==============="); ++ mii_mgr_write(0, 31, 0); //select global register ++ for(i=from;i<=to;i++) { ++ if(i%8==0) { ++ printk("\n"); ++ } ++ mii_mgr_read(port_no,i, &temp); ++ printk("%02d: %04X ",i, temp); ++ } ++ } else { ++ mii_mgr_write(0, 31, 0x8000); //select local register ++ printk("\n\nLocal Register Port %d\n",port_no); ++ printk("==============="); ++ for(i=from;i<=to;i++) { ++ if(i%8==0) { ++ printk("\n"); ++ } ++ mii_mgr_read(port_no,i, &temp); ++ printk("%02d: %04X ",i, temp); ++ } ++ } ++ printk("\n"); ++} ++#else ++void dump_phy_reg(int port_no, int from, int to, int is_local, int page_no) ++{ ++ ++ u32 i=0; ++ u32 temp=0; ++ u32 r31=0; ++ ++ ++ if(is_local==0) { ++ ++ printk("\n\nGlobal Register Page %d\n",page_no); ++ printk("==============="); ++ r31 |= 0 << 15; //global ++ r31 |= ((page_no&0x7) << 12); //page no ++ mii_mgr_write(port_no, 31, r31); //select global page x ++ for(i=16;i<32;i++) { ++ if(i%8==0) { ++ printk("\n"); ++ } ++ mii_mgr_read(port_no,i, &temp); ++ printk("%02d: %04X ",i, temp); ++ } ++ }else { ++ printk("\n\nLocal Register Port %d Page %d\n",port_no, page_no); ++ printk("==============="); ++ r31 |= 1 << 15; //local ++ r31 |= ((page_no&0x7) << 12); //page no ++ mii_mgr_write(port_no, 31, r31); //select local page x ++ for(i=16;i<32;i++) { ++ if(i%8==0) { ++ printk("\n"); ++ } ++ mii_mgr_read(port_no,i, &temp); ++ printk("%02d: %04X ",i, temp); ++ } ++ } ++ printk("\n"); ++} ++ ++#endif ++ ++int ei_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ++{ ++#if defined(CONFIG_RT_3052_ESW) || defined(CONFIG_RAETH_QDMA) ++ esw_reg reg; ++#endif ++#if defined(CONFIG_RALINK_RT3352) || defined(CONFIG_RALINK_RT5350) || \ ++ defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined(CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || \ ++ defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++ esw_rate ratelimit; ++#endif ++#if defined(CONFIG_RT_3052_ESW) ++ unsigned int offset = 0; ++ unsigned int value = 0; ++#endif ++ ++ int ret = 0; ++ END_DEVICE *ei_local = netdev_priv(dev); ++ ra_mii_ioctl_data mii; ++ spin_lock_irq(&ei_local->page_lock); ++ ++ switch (cmd) { ++#if defined(CONFIG_RAETH_QDMA) ++#define _HQOS_REG(x) (*((volatile u32 *)(RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + x))) ++ case RAETH_QDMA_REG_READ: ++ copy_from_user(®, ifr->ifr_data, sizeof(reg)); ++ if (reg.off > REG_HQOS_MAX) { ++ ret = -EINVAL; ++ break; ++ } ++ reg.val = _HQOS_REG(reg.off); ++ //printk("read reg off:%x val:%x\n", reg.off, reg.val); ++ copy_to_user(ifr->ifr_data, ®, sizeof(reg)); ++ break; ++ case RAETH_QDMA_REG_WRITE: ++ copy_from_user(®, ifr->ifr_data, sizeof(reg)); ++ if (reg.off > REG_HQOS_MAX) { ++ ret = -EINVAL; ++ break; ++ } ++ _HQOS_REG(reg.off) = reg.val; ++ //printk("write reg off:%x val:%x\n", reg.off, reg.val); ++ break; ++#if 0 ++ case RAETH_QDMA_READ_CPU_CLK: ++ copy_from_user(®, ifr->ifr_data, sizeof(reg)); ++ reg.val = get_surfboard_sysclk(); ++ //printk("read reg off:%x val:%x\n", reg.off, reg.val); ++ copy_to_user(ifr->ifr_data, ®, sizeof(reg)); ++ break; ++#endif ++ case RAETH_QDMA_QUEUE_MAPPING: ++ copy_from_user(®, ifr->ifr_data, sizeof(reg)); ++ if((reg.off&0x100) == 0x100){ ++ lan_wan_separate = 1; ++ reg.off &= 0xff; ++ }else{ ++ lan_wan_separate = 0; ++ } ++ M2Q_table[reg.off] = reg.val; ++ break; ++#if defined(CONFIG_HW_SFQ) ++ case RAETH_QDMA_SFQ_WEB_ENABLE: ++ copy_from_user(®, ifr->ifr_data, sizeof(reg)); ++ if((reg.val) == 0x1){ ++ web_sfq_enable = 1; ++ ++ }else{ ++ web_sfq_enable = 0; ++ } ++ break; ++#endif ++ ++ ++#endif ++ case RAETH_MII_READ: ++ copy_from_user(&mii, ifr->ifr_data, sizeof(mii)); ++ mii_mgr_read(mii.phy_id, mii.reg_num, &mii.val_out); ++ //printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_out); ++ copy_to_user(ifr->ifr_data, &mii, sizeof(mii)); ++ break; ++ ++ case RAETH_MII_WRITE: ++ copy_from_user(&mii, ifr->ifr_data, sizeof(mii)); ++ //printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_in); ++ mii_mgr_write(mii.phy_id, mii.reg_num, mii.val_in); ++ break; ++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_ARCH_MT7623) ++ case RAETH_MII_READ_CL45: ++ copy_from_user(&mii, ifr->ifr_data, sizeof(mii)); ++ //mii_mgr_cl45_set_address(mii.port_num, mii.dev_addr, mii.reg_addr); ++ mii_mgr_read_cl45(mii.port_num, mii.dev_addr, mii.reg_addr, &mii.val_out); ++ copy_to_user(ifr->ifr_data, &mii, sizeof(mii)); ++ break; ++ case RAETH_MII_WRITE_CL45: ++ copy_from_user(&mii, ifr->ifr_data, sizeof(mii)); ++ //mii_mgr_cl45_set_address(mii.port_num, mii.dev_addr, mii.reg_addr); ++ mii_mgr_write_cl45(mii.port_num, mii.dev_addr, mii.reg_addr, mii.val_in); ++ break; ++#endif ++ ++#if defined(CONFIG_RT_3052_ESW) ++#define _ESW_REG(x) (*((volatile u32 *)(RALINK_ETH_SW_BASE + x))) ++ case RAETH_ESW_REG_READ: ++ copy_from_user(®, ifr->ifr_data, sizeof(reg)); ++ if (reg.off > REG_ESW_MAX) { ++ ret = -EINVAL; ++ break; ++ } ++ reg.val = _ESW_REG(reg.off); ++ //printk("read reg off:%x val:%x\n", reg.off, reg.val); ++ copy_to_user(ifr->ifr_data, ®, sizeof(reg)); ++ break; ++ case RAETH_ESW_REG_WRITE: ++ copy_from_user(®, ifr->ifr_data, sizeof(reg)); ++ if (reg.off > REG_ESW_MAX) { ++ ret = -EINVAL; ++ break; ++ } ++ _ESW_REG(reg.off) = reg.val; ++ //printk("write reg off:%x val:%x\n", reg.off, reg.val); ++ break; ++ case RAETH_ESW_PHY_DUMP: ++ copy_from_user(®, ifr->ifr_data, sizeof(reg)); ++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) ++ if (reg.val ==32 ) {//dump all phy register ++ /* Global Register 0~31 ++ * Local Register 0~31 ++ */ ++ dump_phy_reg(0, 0, 31, 0); //dump global register ++ for(offset=0;offset<5;offset++) { ++ dump_phy_reg(offset, 0, 31, 1); //dump local register ++ } ++ } else { ++ dump_phy_reg(reg.val, 0, 31, 0); //dump global register ++ dump_phy_reg(reg.val, 0, 31, 1); //dump local register ++ } ++#else ++ /* SPEC defined Register 0~15 ++ * Global Register 16~31 for each page ++ * Local Register 16~31 for each page ++ */ ++ printk("SPEC defined Register"); ++ if (reg.val ==32 ) {//dump all phy register ++ int i = 0; ++ for(i=0; i<5; i++){ ++ printk("\n[Port %d]===============",i); ++ for(offset=0;offset<16;offset++) { ++ if(offset%8==0) { ++ printk("\n"); ++ } ++ mii_mgr_read(i,offset, &value); ++ printk("%02d: %04X ",offset, value); ++ } ++ } ++ } ++ else{ ++ printk("\n[Port %d]===============",reg.val); ++ for(offset=0;offset<16;offset++) { ++ if(offset%8==0) { ++ printk("\n"); ++ } ++ mii_mgr_read(reg.val,offset, &value); ++ printk("%02d: %04X ",offset, value); ++ } ++ } ++ ++#if defined (CONFIG_RALINK_MT7628) ++ for(offset=0;offset<7;offset++) { //global register page 0~6 ++#else ++ for(offset=0;offset<5;offset++) { //global register page 0~4 ++#endif ++ if(reg.val == 32) //dump all phy register ++ dump_phy_reg(0, 16, 31, 0, offset); ++ else ++ dump_phy_reg(reg.val, 16, 31, 0, offset); ++ } ++ ++ if (reg.val == 32) {//dump all phy register ++#if !defined (CONFIG_RAETH_HAS_PORT4) ++ for(offset=0;offset<5;offset++) { //local register port 0-port4 ++#else ++ for(offset=0;offset<4;offset++) { //local register port 0-port3 ++#endif ++ dump_phy_reg(offset, 16, 31, 1, 0); //dump local page 0 ++ dump_phy_reg(offset, 16, 31, 1, 1); //dump local page 1 ++ dump_phy_reg(offset, 16, 31, 1, 2); //dump local page 2 ++ dump_phy_reg(offset, 16, 31, 1, 3); //dump local page 3 ++ } ++ }else { ++ dump_phy_reg(reg.val, 16, 31, 1, 0); //dump local page 0 ++ dump_phy_reg(reg.val, 16, 31, 1, 1); //dump local page 1 ++ dump_phy_reg(reg.val, 16, 31, 1, 2); //dump local page 2 ++ dump_phy_reg(reg.val, 16, 31, 1, 3); //dump local page 3 ++ } ++#endif ++ break; ++ ++#if defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++#define _ESW_REG(x) (*((volatile u32 *)(RALINK_ETH_SW_BASE + x))) ++ case RAETH_ESW_INGRESS_RATE: ++ copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit)); ++ offset = 0x11c + (4 * (ratelimit.port / 2)); ++ value = _ESW_REG(offset); ++ ++ if((ratelimit.port % 2) == 0) ++ { ++ value &= 0xffff0000; ++ if(ratelimit.on_off == 1) ++ { ++ value |= (ratelimit.on_off << 14); ++ value |= (0x07 << 10); ++ value |= ratelimit.bw; ++ } ++ } ++ else if((ratelimit.port % 2) == 1) ++ { ++ value &= 0x0000ffff; ++ if(ratelimit.on_off == 1) ++ { ++ value |= (ratelimit.on_off << 30); ++ value |= (0x07 << 26); ++ value |= (ratelimit.bw << 16); ++ } ++ } ++ printk("offset = 0x%4x value=0x%x\n\r", offset, value); ++ ++ _ESW_REG(offset) = value; ++ break; ++ ++ case RAETH_ESW_EGRESS_RATE: ++ copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit)); ++ offset = 0x140 + (4 * (ratelimit.port / 2)); ++ value = _ESW_REG(offset); ++ ++ if((ratelimit.port % 2) == 0) ++ { ++ value &= 0xffff0000; ++ if(ratelimit.on_off == 1) ++ { ++ value |= (ratelimit.on_off << 12); ++ value |= (0x03 << 10); ++ value |= ratelimit.bw; ++ } ++ } ++ else if((ratelimit.port % 2) == 1) ++ { ++ value &= 0x0000ffff; ++ if(ratelimit.on_off == 1) ++ { ++ value |= (ratelimit.on_off << 28); ++ value |= (0x03 << 26); ++ value |= (ratelimit.bw << 16); ++ } ++ } ++ printk("offset = 0x%4x value=0x%x\n\r", offset, value); ++ _ESW_REG(offset) = value; ++ break; ++#elif defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \ ++ defined(CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++#define _ESW_REG(x) (*((volatile u32 *)(RALINK_ETH_SW_BASE + x))) ++ case RAETH_ESW_INGRESS_RATE: ++ copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit)); ++#if defined(CONFIG_RALINK_RT6855A) || defined(CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++ offset = 0x1800 + (0x100 * ratelimit.port); ++#else ++ offset = 0x1080 + (0x100 * ratelimit.port); ++#endif ++ value = _ESW_REG(offset); ++ ++ value &= 0xffff0000; ++ if(ratelimit.on_off == 1) ++ { ++ value |= (ratelimit.on_off << 15); ++ if (ratelimit.bw < 100) ++ { ++ value |= (0x0 << 8); ++ value |= ratelimit.bw; ++ }else if(ratelimit.bw < 1000) ++ { ++ value |= (0x1 << 8); ++ value |= ratelimit.bw/10; ++ }else if(ratelimit.bw < 10000) ++ { ++ value |= (0x2 << 8); ++ value |= ratelimit.bw/100; ++ }else if(ratelimit.bw < 100000) ++ { ++ value |= (0x3 << 8); ++ value |= ratelimit.bw/1000; ++ }else ++ { ++ value |= (0x4 << 8); ++ value |= ratelimit.bw/10000; ++ } ++ } ++ printk("offset = 0x%4x value=0x%x\n\r", offset, value); ++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++ mii_mgr_write(0x1f, offset, value); ++#else ++ _ESW_REG(offset) = value; ++#endif ++ break; ++ ++ case RAETH_ESW_EGRESS_RATE: ++ copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit)); ++ offset = 0x1040 + (0x100 * ratelimit.port); ++ value = _ESW_REG(offset); ++ ++ value &= 0xffff0000; ++ if(ratelimit.on_off == 1) ++ { ++ value |= (ratelimit.on_off << 15); ++ if (ratelimit.bw < 100) ++ { ++ value |= (0x0 << 8); ++ value |= ratelimit.bw; ++ }else if(ratelimit.bw < 1000) ++ { ++ value |= (0x1 << 8); ++ value |= ratelimit.bw/10; ++ }else if(ratelimit.bw < 10000) ++ { ++ value |= (0x2 << 8); ++ value |= ratelimit.bw/100; ++ }else if(ratelimit.bw < 100000) ++ { ++ value |= (0x3 << 8); ++ value |= ratelimit.bw/1000; ++ }else ++ { ++ value |= (0x4 << 8); ++ value |= ratelimit.bw/10000; ++ } ++ } ++ printk("offset = 0x%4x value=0x%x\n\r", offset, value); ++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++ mii_mgr_write(0x1f, offset, value); ++#else ++ _ESW_REG(offset) = value; ++#endif ++ break; ++#endif ++#endif // CONFIG_RT_3052_ESW ++ default: ++ ret = -EOPNOTSUPP; ++ break; ++ ++ } ++ ++ spin_unlock_irq(&ei_local->page_lock); ++ return ret; ++} ++ ++/* ++ * Set new MTU size ++ * Change the mtu of Raeth Ethernet Device ++ */ ++static int ei_change_mtu(struct net_device *dev, int new_mtu) ++{ ++ END_DEVICE *ei_local = netdev_priv(dev); // get priv ei_local pointer from net_dev structure ++ ++ if ( ei_local == NULL ) { ++ printk(KERN_EMERG "%s: ei_change_mtu passed a non-existent private pointer from net_dev!\n", dev->name); ++ return -ENXIO; ++ } ++ ++ ++ if ( (new_mtu > 4096) || (new_mtu < 64)) { ++ return -EINVAL; ++ } ++ ++#ifndef CONFIG_RAETH_JUMBOFRAME ++ if ( new_mtu > 1500 ) { ++ return -EINVAL; ++ } ++#endif ++ ++ dev->mtu = new_mtu; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_RAETH_HW_VLAN_RX ++static void ei_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) ++{ ++ END_DEVICE *ei_local = netdev_priv(dev); ++ ++ ei_local->vlgrp = grp; ++ ++ /* enable HW VLAN RX */ ++ sysRegWrite(CDMP_EG_CTRL, 1); ++ ++} ++#endif ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++static const struct net_device_ops ei_netdev_ops = { ++ .ndo_init = rather_probe, ++ .ndo_open = ei_open, ++ .ndo_stop = ei_close, ++ .ndo_start_xmit = ei_start_xmit_fake, ++ .ndo_get_stats = ra_get_stats, ++ .ndo_set_mac_address = eth_mac_addr, ++ .ndo_change_mtu = ei_change_mtu, ++ .ndo_do_ioctl = ei_ioctl, ++ .ndo_validate_addr = eth_validate_addr, ++#ifdef CONFIG_RAETH_HW_VLAN_RX ++ .ndo_vlan_rx_register = ei_vlan_rx_register, ++#endif ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ .ndo_poll_controller = raeth_clean, ++#endif ++// .ndo_tx_timeout = ei_tx_timeout, ++}; ++#endif ++ ++void ra2880_setup_dev_fptable(struct net_device *dev) ++{ ++ RAETH_PRINT(__FUNCTION__ "is called!\n"); ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ dev->netdev_ops = &ei_netdev_ops; ++#else ++ dev->open = ei_open; ++ dev->stop = ei_close; ++ dev->hard_start_xmit = ei_start_xmit_fake; ++ dev->get_stats = ra_get_stats; ++ dev->set_mac_address = ei_set_mac_addr; ++ dev->change_mtu = ei_change_mtu; ++ dev->mtu = 1500; ++ dev->do_ioctl = ei_ioctl; ++// dev->tx_timeout = ei_tx_timeout; ++ ++#ifdef CONFIG_RAETH_NAPI ++ dev->poll = &raeth_clean; ++#if defined (CONFIG_RAETH_ROUTER) ++ dev->weight = 32; ++#elif defined (CONFIG_RT_3052_ESW) ++ dev->weight = 32; ++#else ++ dev->weight = 128; ++#endif ++#endif ++#endif ++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/ ++ dev->ethtool_ops = &ra_ethtool_ops; ++#endif ++#define TX_TIMEOUT (5*HZ) ++ dev->watchdog_timeo = TX_TIMEOUT; ++ ++} ++ ++/* reset frame engine */ ++void fe_reset(void) ++{ ++#if defined (CONFIG_RALINK_RT6855A) ++ /* FIXME */ ++#else ++ u32 val; ++ ++ //val = *(volatile u32 *)(0x1b000000); ++ //printk("0x1b000000 is 0x%x\n", val); ++ //val = sysRegRead(0xFB110100); ++ //val = 0x8000; ++ //sysRegWrite(0xFB110100, val); ++ ++ ++ ++ val = sysRegRead(RSTCTRL); ++ ++// RT5350 need to reset ESW and FE at the same to avoid PDMA panic // ++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++ val = val | RALINK_FE_RST | RALINK_ESW_RST ; ++#else ++ val = val | RALINK_FE_RST; ++#endif ++ sysRegWrite(RSTCTRL, val); ++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7628) ++ val = val & ~(RALINK_FE_RST | RALINK_ESW_RST); ++#else ++ val = val & ~(RALINK_FE_RST); ++#endif ++ ++ sysRegWrite(RSTCTRL, val); ++#endif ++} ++ ++/* set TRGMII */ ++#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC) ++void trgmii_set_7621(void) ++{ ++ u32 val = 0; ++ u32 val_0 = 0; ++ ++ val = sysRegRead(RSTCTRL); ++// MT7621 need to reset GMAC and FE first // ++ val = val | RALINK_FE_RST | RALINK_ETH_RST ; ++ sysRegWrite(RSTCTRL, val); ++ ++//set TRGMII clock// ++ val_0 = sysRegRead(CLK_CFG_0); ++ val_0 &= 0xffffff9f; ++ val_0 |= (0x1 << 5); ++ sysRegWrite(CLK_CFG_0, val_0); ++ mdelay(1); ++ val_0 = sysRegRead(CLK_CFG_0); ++ printk("set CLK_CFG_0 = 0x%x!!!!!!!!!!!!!!!!!!1\n",val_0); ++ val = val & ~(RALINK_FE_RST | RALINK_ETH_RST); ++ sysRegWrite(RSTCTRL, val); ++} ++ ++void trgmii_set_7530(void) ++{ ++// set MT7530 // ++#if 0 ++ ++ mii_mgr_write(31, 103, 0x0020); ++ ++ ++ //disable EEE ++ mii_mgr_write(0, 0x16, 0); ++ mii_mgr_write(1, 0x16, 0); ++ mii_mgr_write(2, 0x16, 0); ++ mii_mgr_write(3, 0x16, 0); ++ mii_mgr_write(4, 0x16, 0); ++ ++ ++ //PLL reset for E2 ++ mii_mgr_write(31, 104, 0x0608); ++ mii_mgr_write(31, 104, 0x2608); ++ ++ mii_mgr_write(31, 0x7808, 0x0); ++ mdelay(1); ++ mii_mgr_write(31, 0x7804, 0x01017e8f); ++ mdelay(1); ++ mii_mgr_write(31, 0x7808, 0x1); ++ mdelay(1); ++ ++#endif ++#if 1 ++ //CL45 command ++ //PLL to 150Mhz ++ mii_mgr_write(0, 13, 0x1f); ++ mii_mgr_write(0, 14, 0x404); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_read(31, 0x7800, ®Value); ++ regValue = (regValue >> 9) & 0x3; ++ if(regValue == 0x3) { //25Mhz Xtal ++ mii_mgr_write(0, 14, 0x0A00);//25Mhz XTAL for 150Mhz CLK ++ } else if(regValue == 0x2) { //40Mhz ++ mii_mgr_write(0, 14, 0x0780);//40Mhz XTAL for 150Mhz CLK ++ } ++ //mii_mgr_write(0, 14, 0x0C00);//ori ++ mdelay(1); ++ ++ mii_mgr_write(0, 13, 0x1f); ++ mii_mgr_write(0, 14, 0x409); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0x57); ++ mdelay(1); ++ ++ mii_mgr_write(0, 13, 0x1f); ++ mii_mgr_write(0, 14, 0x40a); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0x57); ++ ++//PLL BIAS en ++ mii_mgr_write(0, 13, 0x1f); ++ mii_mgr_write(0, 14, 0x403); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0x1800); ++ mdelay(1); ++ ++//BIAS LPF en ++ mii_mgr_write(0, 13, 0x1f); ++ mii_mgr_write(0, 14, 0x403); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0x1c00); ++ ++//sys PLL en ++ mii_mgr_write(0, 13, 0x1f); ++ mii_mgr_write(0, 14, 0x401); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0xc020); ++ ++//LCDDDS PWDS ++ mii_mgr_write(0, 13, 0x1f); ++ mii_mgr_write(0, 14, 0x406); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0xa030); ++ mdelay(1); ++ ++//GSW_2X_CLK ++ mii_mgr_write(0, 13, 0x1f); ++ mii_mgr_write(0, 14, 0x410); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0x0003); ++ ++//enable P6 ++ mii_mgr_write(31, 0x3600, 0x5e33b); ++ ++//enable TRGMII ++ mii_mgr_write(31, 0x7830, 0x1); ++#endif ++ ++} ++#endif ++ ++void ei_reset_task(struct work_struct *work) ++{ ++ struct net_device *dev = dev_raether; ++ ++ ei_close(dev); ++ ei_open(dev); ++ ++ return; ++} ++ ++void ei_tx_timeout(struct net_device *dev) ++{ ++ END_DEVICE *ei_local = netdev_priv(dev); ++ ++ schedule_work(&ei_local->reset_task); ++} ++ ++void setup_statistics(END_DEVICE* ei_local) ++{ ++ ei_local->stat.tx_packets = 0; ++ ei_local->stat.tx_bytes = 0; ++ ei_local->stat.tx_dropped = 0; ++ ei_local->stat.tx_errors = 0; ++ ei_local->stat.tx_aborted_errors= 0; ++ ei_local->stat.tx_carrier_errors= 0; ++ ei_local->stat.tx_fifo_errors = 0; ++ ei_local->stat.tx_heartbeat_errors = 0; ++ ei_local->stat.tx_window_errors = 0; ++ ++ ei_local->stat.rx_packets = 0; ++ ei_local->stat.rx_bytes = 0; ++ ei_local->stat.rx_dropped = 0; ++ ei_local->stat.rx_errors = 0; ++ ei_local->stat.rx_length_errors = 0; ++ ei_local->stat.rx_over_errors = 0; ++ ei_local->stat.rx_crc_errors = 0; ++ ei_local->stat.rx_frame_errors = 0; ++ ei_local->stat.rx_fifo_errors = 0; ++ ei_local->stat.rx_missed_errors = 0; ++ ++ ei_local->stat.collisions = 0; ++#if defined (CONFIG_RAETH_QOS) ++ ei_local->tx3_full = 0; ++ ei_local->tx2_full = 0; ++ ei_local->tx1_full = 0; ++ ei_local->tx0_full = 0; ++#else ++ ei_local->tx_full = 0; ++#endif ++#ifdef CONFIG_RAETH_NAPI ++ atomic_set(&ei_local->irq_sem, 1); ++#endif ++ ++} ++ ++/** ++ * rather_probe - pick up ethernet port at boot time ++ * @dev: network device to probe ++ * ++ * This routine probe the ethernet port at boot time. ++ * ++ * ++ */ ++ ++int __init rather_probe(struct net_device *dev) ++{ ++ int i; ++ END_DEVICE *ei_local = netdev_priv(dev); ++ struct sockaddr addr; ++ unsigned char zero1[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; ++ unsigned char zero2[6]={0x00,0x00,0x00,0x00,0x00,0x00}; ++ ++ fe_reset(); ++ ++ //Get mac0 address from flash ++#ifdef RA_MTD_RW_BY_NUM ++ i = ra_mtd_read(2, GMAC0_OFFSET, 6, addr.sa_data); ++#else ++ i = ra_mtd_read_nm("Factory", GMAC0_OFFSET, 6, addr.sa_data); ++#endif ++ //If reading mtd failed or mac0 is empty, generate a mac address ++ if (i < 0 || ((memcmp(addr.sa_data, zero1, 6) == 0) || (addr.sa_data[0] & 0x1)) || ++ (memcmp(addr.sa_data, zero2, 6) == 0)) { ++ unsigned char mac_addr01234[5] = {0x00, 0x0C, 0x43, 0x28, 0x80}; ++ // net_srandom(jiffies); ++ memcpy(addr.sa_data, mac_addr01234, 5); ++ // addr.sa_data[5] = net_random()&0xFF; ++ } ++ ++#ifdef CONFIG_RAETH_NAPI ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ netif_napi_add(dev, &ei_local->napi, raeth_clean, 128); ++#endif ++#endif ++ ei_set_mac_addr(dev, &addr); ++ spin_lock_init(&ei_local->page_lock); ++ ether_setup(dev); ++ ++#ifdef CONFIG_RAETH_LRO ++ ei_local->lro_mgr.dev = dev; ++ memset(&ei_local->lro_mgr.stats, 0, sizeof(ei_local->lro_mgr.stats)); ++ ei_local->lro_mgr.features = LRO_F_NAPI; ++ ei_local->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY; ++ ei_local->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY; ++ ei_local->lro_mgr.max_desc = ARRAY_SIZE(ei_local->lro_arr); ++ ei_local->lro_mgr.max_aggr = 64; ++ ei_local->lro_mgr.frag_align_pad = 0; ++ ei_local->lro_mgr.lro_arr = ei_local->lro_arr; ++ ei_local->lro_mgr.get_skb_header = rt_get_skb_header; ++#endif ++ ++ setup_statistics(ei_local); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++int VirtualIF_ioctl(struct net_device * net_dev, ++ struct ifreq * ifr, int cmd) ++{ ++ ra_mii_ioctl_data mii; ++ ++ switch (cmd) { ++ case RAETH_MII_READ: ++ copy_from_user(&mii, ifr->ifr_data, sizeof(mii)); ++ mii_mgr_read(mii.phy_id, mii.reg_num, &mii.val_out); ++ //printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_out); ++ copy_to_user(ifr->ifr_data, &mii, sizeof(mii)); ++ break; ++ ++ case RAETH_MII_WRITE: ++ copy_from_user(&mii, ifr->ifr_data, sizeof(mii)); ++ //printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_in); ++ mii_mgr_write(mii.phy_id, mii.reg_num, mii.val_in); ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ return 0; ++} ++ ++struct net_device_stats *VirtualIF_get_stats(struct net_device *dev) ++{ ++ PSEUDO_ADAPTER *pAd = netdev_priv(dev); ++ return &pAd->stat; ++} ++ ++int VirtualIF_open(struct net_device * dev) ++{ ++ PSEUDO_ADAPTER *pPesueoAd = netdev_priv(dev); ++ ++ printk("%s: ===> VirtualIF_open\n", dev->name); ++ ++#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN) || defined (CONFIG_GE_RGMII_INTERNAL_P4_AN) ++ *((volatile u32 *)(FE_INT_ENABLE2)) |= (1<<25); //enable GE2 link change intr for MT7530 delay setting ++#endif ++ ++ netif_start_queue(pPesueoAd->PseudoDev); ++ ++ return 0; ++} ++ ++int VirtualIF_close(struct net_device * dev) ++{ ++ PSEUDO_ADAPTER *pPesueoAd = netdev_priv(dev); ++ ++ printk("%s: ===> VirtualIF_close\n", dev->name); ++ ++ netif_stop_queue(pPesueoAd->PseudoDev); ++ ++ return 0; ++} ++ ++int VirtualIFSendPackets(struct sk_buff * pSkb, ++ struct net_device * dev) ++{ ++ PSEUDO_ADAPTER *pPesueoAd = netdev_priv(dev); ++ END_DEVICE *ei_local __maybe_unused; ++ ++ ++ //printk("VirtualIFSendPackets --->\n"); ++ ++ ei_local = netdev_priv(dev); ++ if (!(pPesueoAd->RaethDev->flags & IFF_UP)) { ++ dev_kfree_skb_any(pSkb); ++ return 0; ++ } ++ //pSkb->cb[40]=0x5a; ++ pSkb->dev = pPesueoAd->RaethDev; ++ ei_start_xmit(pSkb, pPesueoAd->RaethDev, 2); ++ return 0; ++} ++ ++void virtif_setup_statistics(PSEUDO_ADAPTER* pAd) ++{ ++ pAd->stat.tx_packets = 0; ++ pAd->stat.tx_bytes = 0; ++ pAd->stat.tx_dropped = 0; ++ pAd->stat.tx_errors = 0; ++ pAd->stat.tx_aborted_errors= 0; ++ pAd->stat.tx_carrier_errors= 0; ++ pAd->stat.tx_fifo_errors = 0; ++ pAd->stat.tx_heartbeat_errors = 0; ++ pAd->stat.tx_window_errors = 0; ++ ++ pAd->stat.rx_packets = 0; ++ pAd->stat.rx_bytes = 0; ++ pAd->stat.rx_dropped = 0; ++ pAd->stat.rx_errors = 0; ++ pAd->stat.rx_length_errors = 0; ++ pAd->stat.rx_over_errors = 0; ++ pAd->stat.rx_crc_errors = 0; ++ pAd->stat.rx_frame_errors = 0; ++ pAd->stat.rx_fifo_errors = 0; ++ pAd->stat.rx_missed_errors = 0; ++ ++ pAd->stat.collisions = 0; ++} ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++static const struct net_device_ops VirtualIF_netdev_ops = { ++ .ndo_open = VirtualIF_open, ++ .ndo_stop = VirtualIF_close, ++ .ndo_start_xmit = VirtualIFSendPackets, ++ .ndo_get_stats = VirtualIF_get_stats, ++ .ndo_set_mac_address = ei_set_mac2_addr, ++ .ndo_change_mtu = ei_change_mtu, ++ .ndo_do_ioctl = VirtualIF_ioctl, ++ .ndo_validate_addr = eth_validate_addr, ++}; ++#endif ++// Register pseudo interface ++void RAETH_Init_PSEUDO(pEND_DEVICE pAd, struct net_device *net_dev) ++{ ++ int index; ++ struct net_device *dev; ++ PSEUDO_ADAPTER *pPseudoAd; ++ int i = 0; ++ struct sockaddr addr; ++ unsigned char zero1[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; ++ unsigned char zero2[6]={0x00,0x00,0x00,0x00,0x00,0x00}; ++ ++ for (index = 0; index < MAX_PSEUDO_ENTRY; index++) { ++ ++ dev = alloc_etherdev(sizeof(PSEUDO_ADAPTER)); ++ if (NULL == dev) ++ { ++ printk(" alloc_etherdev for PSEUDO_ADAPTER failed.\n"); ++ return; ++ } ++ strcpy(dev->name, DEV2_NAME); ++ ++ //Get mac2 address from flash ++#ifdef RA_MTD_RW_BY_NUM ++ i = ra_mtd_read(2, GMAC2_OFFSET, 6, addr.sa_data); ++#else ++ i = ra_mtd_read_nm("Factory", GMAC2_OFFSET, 6, addr.sa_data); ++#endif ++ ++ //If reading mtd failed or mac0 is empty, generate a mac address ++ if (i < 0 || ((memcmp(addr.sa_data, zero1, 6) == 0) || (addr.sa_data[0] & 0x1)) || ++ (memcmp(addr.sa_data, zero2, 6) == 0)) { ++ unsigned char mac_addr01234[5] = {0x00, 0x0C, 0x43, 0x28, 0x80}; ++ // net_srandom(jiffies); ++ memcpy(addr.sa_data, mac_addr01234, 5); ++ // addr.sa_data[5] = net_random()&0xFF; ++ } ++ ++ ei_set_mac2_addr(dev, &addr); ++ ether_setup(dev); ++ pPseudoAd = netdev_priv(dev); ++ ++ pPseudoAd->PseudoDev = dev; ++ pPseudoAd->RaethDev = net_dev; ++ virtif_setup_statistics(pPseudoAd); ++ pAd->PseudoDev = dev; ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ dev->netdev_ops = &VirtualIF_netdev_ops; ++#else ++ dev->hard_start_xmit = VirtualIFSendPackets; ++ dev->stop = VirtualIF_close; ++ dev->open = VirtualIF_open; ++ dev->do_ioctl = VirtualIF_ioctl; ++ dev->set_mac_address = ei_set_mac2_addr; ++ dev->get_stats = VirtualIF_get_stats; ++ dev->change_mtu = ei_change_mtu; ++ dev->mtu = 1500; ++#endif ++ ++#if defined (CONFIG_RAETH_HW_LRO) ++ dev->features |= NETIF_F_HW_CSUM; ++#else ++ dev->features |= NETIF_F_IP_CSUM; /* Can checksum TCP/UDP over IPv4 */ ++#endif /* CONFIG_RAETH_HW_LRO */ ++ ++#if defined(CONFIG_RALINK_MT7620) ++#if defined (CONFIG_RAETH_TSO) ++ if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) { ++ dev->features |= NETIF_F_SG; ++ dev->features |= NETIF_F_TSO; ++ } ++#endif // CONFIG_RAETH_TSO // ++ ++#if defined (CONFIG_RAETH_TSOV6) ++ if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) { ++ dev->features |= NETIF_F_TSO6; ++ dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */ ++ } ++#endif ++#else ++#if defined (CONFIG_RAETH_TSO) ++ dev->features |= NETIF_F_SG; ++ dev->features |= NETIF_F_TSO; ++#endif // CONFIG_RAETH_TSO // ++ ++#if defined (CONFIG_RAETH_TSOV6) ++ dev->features |= NETIF_F_TSO6; ++ dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */ ++#endif ++#endif // CONFIG_RALINK_MT7620 // ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0) ++ dev->vlan_features = dev->features; ++#endif ++ ++ ++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/ ++ dev->ethtool_ops = &ra_virt_ethtool_ops; ++ // init mii structure ++ pPseudoAd->mii_info.dev = dev; ++ pPseudoAd->mii_info.mdio_read = mdio_virt_read; ++ pPseudoAd->mii_info.mdio_write = mdio_virt_write; ++ pPseudoAd->mii_info.phy_id_mask = 0x1f; ++ pPseudoAd->mii_info.reg_num_mask = 0x1f; ++ pPseudoAd->mii_info.phy_id = 0x1e; ++ pPseudoAd->mii_info.supports_gmii = mii_check_gmii_support(&pPseudoAd->mii_info); ++#endif ++ ++ // Register this device ++ register_netdevice(dev); ++ } ++} ++#endif ++ ++/** ++ * ei_open - Open/Initialize the ethernet port. ++ * @dev: network device to initialize ++ * ++ * This routine goes all-out, setting everything ++ * up a new at each open, even though many of these registers should only need to be set once at boot. ++ */ ++int ei_open(struct net_device *dev) ++{ ++ int i, err; ++#if !defined (CONFIG_MT7623_FPGA) ++ unsigned long flags; ++#endif ++ END_DEVICE *ei_local; ++ ++#ifdef CONFIG_RAETH_LRO ++ const char *lan_ip_tmp; ++#ifdef CONFIG_DUAL_IMAGE ++#define RT2860_NVRAM 1 ++#else ++#define RT2860_NVRAM 0 ++#endif ++#endif // CONFIG_RAETH_LRO // ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ++ if (!try_module_get(THIS_MODULE)) ++ { ++ printk("%s: Cannot reserve module\n", __FUNCTION__); ++ return -1; ++ } ++#else ++ MOD_INC_USE_COUNT; ++#endif ++ ++ printk("Raeth %s (",RAETH_VERSION); ++#if defined (CONFIG_RAETH_NAPI) ++ printk("NAPI\n"); ++#elif defined (CONFIG_RA_NETWORK_TASKLET_BH) ++ printk("Tasklet"); ++#elif defined (CONFIG_RA_NETWORK_WORKQUEUE_BH) ++ printk("Workqueue"); ++#endif ++ ++#if defined (CONFIG_RAETH_SKB_RECYCLE_2K) ++ printk(",SkbRecycle"); ++#endif ++ printk(")\n"); ++ ++ ++ ei_local = netdev_priv(dev); // get device pointer from System ++ // unsigned int flags; ++ ++ if (ei_local == NULL) ++ { ++ printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name); ++ return -ENXIO; ++ } ++ ++ /* receiving packet buffer allocation - NUM_RX_DESC x MAX_RX_LENGTH */ ++ for ( i = 0; i < NUM_RX_DESC; i++) ++ { ++#if defined (CONFIG_RAETH_SKB_RECYCLE_2K) ++ ei_local->netrx0_skbuf[i] = skbmgr_dev_alloc_skb2k(); ++#else ++ ei_local->netrx0_skbuf[i] = dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN); ++#endif ++ if (ei_local->netrx0_skbuf[i] == NULL ) { ++ printk("rx skbuff buffer allocation failed!"); ++ } else { ++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA) ++ skb_reserve(ei_local->netrx0_skbuf[i], NET_IP_ALIGN); ++#endif ++ } ++ ++ ++#if defined (CONFIG_RAETH_HW_LRO) ++ ei_local->netrx3_skbuf[i] = dev_alloc_skb(MAX_LRO_RX_LENGTH + NET_IP_ALIGN); ++ if (ei_local->netrx3_skbuf[i] == NULL ) { ++ printk("rx3 skbuff buffer allocation failed!"); ++ } else { ++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA) ++ skb_reserve(ei_local->netrx3_skbuf[i], NET_IP_ALIGN); ++#endif ++ } ++ ei_local->netrx2_skbuf[i] = dev_alloc_skb(MAX_LRO_RX_LENGTH + NET_IP_ALIGN); ++ if (ei_local->netrx2_skbuf[i] == NULL ) { ++ printk("rx2 skbuff buffer allocation failed!"); ++ } else { ++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA) ++ skb_reserve(ei_local->netrx2_skbuf[i], NET_IP_ALIGN); ++#endif ++ } ++ ei_local->netrx1_skbuf[i] = dev_alloc_skb(MAX_LRO_RX_LENGTH + NET_IP_ALIGN); ++ if (ei_local->netrx1_skbuf[i] == NULL ) { ++ printk("rx1 skbuff buffer allocation failed!"); ++ } else { ++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA) ++ skb_reserve(ei_local->netrx1_skbuf[i], NET_IP_ALIGN); ++#endif ++ } ++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++#if defined(CONFIG_ARCH_MT7623) ++ ei_local->netrx3_skbuf[i] = dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN); ++ if (ei_local->netrx3_skbuf[i] == NULL ) { ++ printk("rx3 skbuff buffer allocation failed!"); ++ } else { ++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA) ++ skb_reserve(ei_local->netrx3_skbuf[i], NET_IP_ALIGN); ++#endif ++ } ++ ei_local->netrx2_skbuf[i] = dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN); ++ if (ei_local->netrx2_skbuf[i] == NULL ) { ++ printk("rx2 skbuff buffer allocation failed!"); ++ } else { ++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA) ++ skb_reserve(ei_local->netrx2_skbuf[i], NET_IP_ALIGN); ++#endif ++ } ++#endif /* CONFIG_ARCH_MT7623 */ ++ ei_local->netrx1_skbuf[i] = dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN); ++ if (ei_local->netrx1_skbuf[i] == NULL ) { ++ printk("rx1 skbuff buffer allocation failed!"); ++ } else { ++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA) ++ skb_reserve(ei_local->netrx1_skbuf[i], NET_IP_ALIGN); ++#endif ++ } ++#endif ++ } ++#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC) ++ trgmii_set_7621(); //reset FE/GMAC in this function ++#endif ++ ++ fe_dma_init(dev); ++ ++#if defined (CONFIG_RAETH_HW_LRO) ++ fe_hw_lro_init(dev); ++#endif /* CONFIG_RAETH_HW_LRO */ ++ ++ fe_sw_init(); //initialize fe and switch register ++#if defined (CONFIG_MIPS) ++ err = request_irq( dev->irq, ei_interrupt, IRQF_DISABLED, dev->name, dev); // try to fix irq in open ++#else ++ err = request_irq(dev->irq, ei_interrupt, /*IRQF_TRIGGER_LOW*/ 0, dev->name, dev); // try to fix irq in open ++#endif ++ if (err) ++ return err; ++ ++ if ( dev->dev_addr != NULL) { ++ ra2880MacAddressSet((void *)(dev->dev_addr)); ++ } else { ++ printk("dev->dev_addr is empty !\n"); ++ } ++/*TODO: MT7623 MCM INT */ ++#if defined (CONFIG_RT_3052_ESW) && !defined(CONFIG_ARCH_MT7623) ++ err = request_irq(SURFBOARDINT_ESW, esw_interrupt, IRQF_DISABLED, "Ralink_ESW", dev); ++ if (err) ++ return err; ++ INIT_WORK(&ei_local->kill_sig_wq, kill_sig_workq); ++#if defined (CONFIG_RALINK_MT7621) ++ mii_mgr_write(31, 0x7008, 0x1f); //enable switch link change intr ++ ++#else ++ *((volatile u32 *)(RALINK_INTCL_BASE + 0x34)) = (1<<17); ++ *((volatile u32 *)(ESW_IMR)) &= ~(ESW_INT_ALL); ++ ++#if defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) ++ *((volatile u32 *)(ESW_P0_IntMn)) &= ~(MSK_CNT_INT_ALL); ++ *((volatile u32 *)(ESW_P1_IntMn)) &= ~(MSK_CNT_INT_ALL); ++ *((volatile u32 *)(ESW_P2_IntMn)) &= ~(MSK_CNT_INT_ALL); ++ *((volatile u32 *)(ESW_P3_IntMn)) &= ~(MSK_CNT_INT_ALL); ++ *((volatile u32 *)(ESW_P4_IntMn)) &= ~(MSK_CNT_INT_ALL); ++ *((volatile u32 *)(ESW_P5_IntMn)) &= ~(MSK_CNT_INT_ALL); ++ *((volatile u32 *)(ESW_P6_IntMn)) &= ~(MSK_CNT_INT_ALL); ++#endif ++#if defined(CONFIG_RALINK_MT7620) ++ *((volatile u32 *)(ESW_P7_IntMn)) &= ~(MSK_CNT_INT_ALL); ++#endif ++ ++#endif ++#endif // CONFIG_RT_3052_ESW // ++ ++/*TODO*/ ++#if !defined (CONFIG_MT7623_FPGA) ++ spin_lock_irqsave(&(ei_local->page_lock), flags); ++#endif ++ ++ ++#ifdef DELAY_INT ++ sysRegWrite(RAETH_DLY_INT_CFG, DELAY_INT_INIT); ++ sysRegWrite(RAETH_FE_INT_ENABLE, RAETH_FE_INT_DLY_INIT); ++ #if defined (CONFIG_RAETH_HW_LRO) ++ sysRegWrite(RAETH_FE_INT_ENABLE, RAETH_FE_INT_DLY_INIT | ALT_RPLC_INT3 | ALT_RPLC_INT2 | ALT_RPLC_INT1); ++ #endif /* CONFIG_RAETH_HW_LRO */ ++#else ++ sysRegWrite(RAETH_FE_INT_ENABLE, RAETH_FE_INT_ALL); ++ #if defined (CONFIG_RAETH_HW_LRO) ++ sysRegWrite(RAETH_FE_INT_ENABLE, RAETH_FE_INT_ALL | ALT_RPLC_INT3 | ALT_RPLC_INT2 | ALT_RPLC_INT1); ++ #endif /* CONFIG_RAETH_HW_LRO */ ++#endif ++ ++#ifdef CONFIG_RAETH_QDMA ++#ifdef DELAY_INT ++ sysRegWrite(QDMA_DELAY_INT, DELAY_INT_INIT); ++ sysRegWrite(QFE_INT_ENABLE, QFE_INT_DLY_INIT); ++#else ++ sysRegWrite(QFE_INT_ENABLE, QFE_INT_ALL); ++ ++#endif ++#endif ++ ++ INIT_WORK(&ei_local->reset_task, ei_reset_task); ++ ++#ifdef WORKQUEUE_BH ++#ifndef CONFIG_RAETH_NAPI ++ INIT_WORK(&ei_local->rx_wq, ei_receive_workq); ++#endif // CONFIG_RAETH_NAPI // ++#else ++#ifndef CONFIG_RAETH_NAPI ++#if defined (TASKLET_WORKQUEUE_SW) ++ working_schedule = init_schedule; ++ INIT_WORK(&ei_local->rx_wq, ei_receive_workq); ++ tasklet_init(&ei_local->rx_tasklet, ei_receive_workq, 0); ++#else ++ tasklet_init(&ei_local->rx_tasklet, ei_receive, 0); ++#endif ++#endif // CONFIG_RAETH_NAPI // ++#endif // WORKQUEUE_BH // ++ ++ netif_start_queue(dev); ++ ++#ifdef CONFIG_RAETH_NAPI ++ atomic_dec(&ei_local->irq_sem); ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ napi_enable(&ei_local->napi); ++#else ++ netif_poll_enable(dev); ++#endif ++#endif ++//*TODO*/ ++#if !defined (CONFIG_MT7623_FPGA) ++ spin_unlock_irqrestore(&(ei_local->page_lock), flags); ++#endif ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++ if(ei_local->PseudoDev == NULL) { ++ RAETH_Init_PSEUDO(ei_local, dev); ++ } ++ ++ if(ei_local->PseudoDev == NULL) ++ printk("Open PseudoDev failed.\n"); ++ else ++ VirtualIF_open(ei_local->PseudoDev); ++ ++#endif ++ ++#ifdef CONFIG_RAETH_LRO ++ lan_ip_tmp = nvram_get(RT2860_NVRAM, "lan_ipaddr"); ++ str_to_ip(&lan_ip, lan_ip_tmp); ++ lro_para.lan_ip1 = lan_ip = htonl(lan_ip); ++#endif // CONFIG_RAETH_LRO // ++ ++#if defined (CONFIG_RAETH_HW_LRO) ++ INIT_WORK(&ei_local->hw_lro_wq, ei_hw_lro_workq); ++#endif /* CONFIG_RAETH_HW_LRO */ ++ ++ forward_config(dev); ++ return 0; ++} ++ ++/** ++ * ei_close - shut down network device ++ * @dev: network device to clear ++ * ++ * This routine shut down network device. ++ * ++ * ++ */ ++int ei_close(struct net_device *dev) ++{ ++ int i; ++ END_DEVICE *ei_local = netdev_priv(dev); // device pointer ++ ++ netif_stop_queue(dev); ++ ra2880stop(ei_local); ++ ++ free_irq(dev->irq, dev); ++ ++/*TODO: MT7623 MCM INT */ ++#if defined (CONFIG_RT_3052_ESW) && !defined(CONFIG_ARCH_MT7623) ++ free_irq(SURFBOARDINT_ESW, dev); ++#endif ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ cancel_work_sync(&ei_local->reset_task); ++#endif ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++ VirtualIF_close(ei_local->PseudoDev); ++#endif ++ ++ ++#ifdef WORKQUEUE_BH ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ cancel_work_sync(&ei_local->rx_wq); ++#endif ++#else ++#if defined (TASKLET_WORKQUEUE_SW) ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ cancel_work_sync(&ei_local->rx_wq); ++#endif ++#endif ++ tasklet_kill(&ei_local->tx_tasklet); ++ tasklet_kill(&ei_local->rx_tasklet); ++#endif // WORKQUEUE_BH // ++ ++#ifdef CONFIG_RAETH_NAPI ++ atomic_inc(&ei_local->irq_sem); ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ napi_disable(&ei_local->napi); ++#else ++ netif_poll_disable(dev); ++#endif ++#endif ++ ++ ++#if defined (CONFIG_RAETH_HW_LRO) ++ cancel_work_sync(&ei_local->hw_lro_wq); ++#endif /* CONFIG_RAETH_HW_LRO */ ++ ++ for ( i = 0; i < NUM_RX_DESC; i++) ++ { ++ if (ei_local->netrx0_skbuf[i] != NULL) { ++ dev_kfree_skb(ei_local->netrx0_skbuf[i]); ++ ei_local->netrx0_skbuf[i] = NULL; ++ } ++#if defined (CONFIG_RAETH_HW_LRO) ++ if (ei_local->netrx3_skbuf[i] != NULL) { ++ dev_kfree_skb(ei_local->netrx3_skbuf[i]); ++ ei_local->netrx3_skbuf[i] = NULL; ++ } ++ if (ei_local->netrx2_skbuf[i] != NULL) { ++ dev_kfree_skb(ei_local->netrx2_skbuf[i]); ++ ei_local->netrx2_skbuf[i] = NULL; ++ } ++ if (ei_local->netrx1_skbuf[i] != NULL) { ++ dev_kfree_skb(ei_local->netrx1_skbuf[i]); ++ ei_local->netrx1_skbuf[i] = NULL; ++ } ++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++#if defined(CONFIG_ARCH_MT7623) ++ if (ei_local->netrx3_skbuf[i] != NULL) { ++ dev_kfree_skb(ei_local->netrx3_skbuf[i]); ++ ei_local->netrx3_skbuf[i] = NULL; ++ } ++ if (ei_local->netrx2_skbuf[i] != NULL) { ++ dev_kfree_skb(ei_local->netrx2_skbuf[i]); ++ ei_local->netrx2_skbuf[i] = NULL; ++ } ++#endif /* CONFIG_ARCH_MT7623 */ ++ if (ei_local->netrx1_skbuf[i] != NULL) { ++ dev_kfree_skb(ei_local->netrx1_skbuf[i]); ++ ei_local->netrx1_skbuf[i] = NULL; ++ } ++#endif ++ } ++ ++ for ( i = 0; i < NUM_TX_DESC; i++) ++ { ++ if((ei_local->skb_free[i]!=(struct sk_buff *)0xFFFFFFFF) && (ei_local->skb_free[i]!= 0)) ++ { ++ dev_kfree_skb_any(ei_local->skb_free[i]); ++ } ++ } ++ ++ /* TX Ring */ ++#ifdef CONFIG_RAETH_QDMA ++ if (ei_local->txd_pool != NULL) { ++ pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct QDMA_txdesc), ei_local->txd_pool, ei_local->phy_txd_pool); ++ } ++ if (ei_local->free_head != NULL){ ++ pci_free_consistent(NULL, NUM_QDMA_PAGE * sizeof(struct QDMA_txdesc), ei_local->free_head, ei_local->phy_free_head); ++ } ++ if (ei_local->free_page_head != NULL){ ++ pci_free_consistent(NULL, NUM_QDMA_PAGE * QDMA_PAGE_SIZE, ei_local->free_page_head, ei_local->phy_free_page_head); ++ } ++#else ++ if (ei_local->tx_ring0 != NULL) { ++ pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring0, ei_local->phy_tx_ring0); ++ } ++#endif ++ ++#if defined (CONFIG_RAETH_QOS) ++ if (ei_local->tx_ring1 != NULL) { ++ pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring1, ei_local->phy_tx_ring1); ++ } ++ ++#if !defined (CONFIG_RALINK_RT2880) ++ if (ei_local->tx_ring2 != NULL) { ++ pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring2, ei_local->phy_tx_ring2); ++ } ++ ++ if (ei_local->tx_ring3 != NULL) { ++ pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring3, ei_local->phy_tx_ring3); ++ } ++#endif ++#endif ++ /* RX Ring */ ++#ifdef CONFIG_32B_DESC ++ kfree(ei_local->rx_ring0); ++#else ++ pci_free_consistent(NULL, NUM_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring0, ei_local->phy_rx_ring0); ++#endif ++#if defined CONFIG_RAETH_QDMA && !defined(CONFIG_RAETH_QDMATX_QDMARX) ++#ifdef CONFIG_32B_DESC ++ kfree(ei_local->qrx_ring); ++#else ++ pci_free_consistent(NULL, NUM_QRX_DESC*sizeof(struct PDMA_rxdesc), ei_local->qrx_ring, ei_local->phy_qrx_ring); ++#endif ++#endif ++#if defined (CONFIG_RAETH_HW_LRO) ++ pci_free_consistent(NULL, NUM_LRO_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring3, ei_local->phy_rx_ring3); ++ pci_free_consistent(NULL, NUM_LRO_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring2, ei_local->phy_rx_ring2); ++ pci_free_consistent(NULL, NUM_LRO_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring1, ei_local->phy_rx_ring1); ++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++#ifdef CONFIG_32B_DESC ++ kfree(ei_local->rx_ring1); ++#else ++#if defined(CONFIG_ARCH_MT7623) ++ pci_free_consistent(NULL, NUM_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring3, ei_local->phy_rx_ring3); ++ pci_free_consistent(NULL, NUM_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring2, ei_local->phy_rx_ring2); ++#endif /* CONFIG_ARCH_MT7623 */ ++ pci_free_consistent(NULL, NUM_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring1, ei_local->phy_rx_ring1); ++#endif ++#endif ++ ++ printk("Free TX/RX Ring Memory!\n"); ++ ++ fe_reset(); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ++ module_put(THIS_MODULE); ++#else ++ MOD_DEC_USE_COUNT; ++#endif ++ return 0; ++} ++ ++#if defined (CONFIG_RT6855A_FPGA) ++void rt6855A_eth_gpio_reset(void) ++{ ++ u8 ether_gpio = 12; ++ ++ /* Load the ethernet gpio value to reset Ethernet PHY */ ++ *(unsigned long *)(RALINK_PIO_BASE + 0x00) |= 1<<(ether_gpio<<1); ++ *(unsigned long *)(RALINK_PIO_BASE + 0x14) |= 1<<(ether_gpio); ++ *(unsigned long *)(RALINK_PIO_BASE + 0x04) &= ~(1< PortPageSel, 1=local, 0=global ++ * Bit 14:12 => PageSel, local:0~3, global:0~4 ++ * ++ *Reg16~30:Local/Global registers ++ * ++ */ ++ /*correct PHY setting J8.0*/ ++ mii_mgr_read(0, 31, &rev); ++ rev &= (0x0f); ++ ++ mii_mgr_write(1, 31, 0x4000); //global, page 4 ++ ++ mii_mgr_write(1, 16, 0xd4cc); ++ mii_mgr_write(1, 17, 0x7444); ++ mii_mgr_write(1, 19, 0x0112); ++ mii_mgr_write(1, 21, 0x7160); ++ mii_mgr_write(1, 22, 0x10cf); ++ mii_mgr_write(1, 26, 0x0777); ++ ++ if(rev == 0){ ++ mii_mgr_write(1, 25, 0x0102); ++ mii_mgr_write(1, 29, 0x8641); ++ } ++ else{ ++ mii_mgr_write(1, 25, 0x0212); ++ mii_mgr_write(1, 29, 0x4640); ++ } ++ ++ mii_mgr_write(1, 31, 0x2000); //global, page 2 ++ mii_mgr_write(1, 21, 0x0655); ++ mii_mgr_write(1, 22, 0x0fd3); ++ mii_mgr_write(1, 23, 0x003d); ++ mii_mgr_write(1, 24, 0x096e); ++ mii_mgr_write(1, 25, 0x0fed); ++ mii_mgr_write(1, 26, 0x0fc4); ++ ++ mii_mgr_write(1, 31, 0x1000); //global, page 1 ++ mii_mgr_write(1, 17, 0xe7f8); ++ ++ ++ mii_mgr_write(1, 31, 0xa000); //local, page 2 ++ ++ mii_mgr_write(0, 16, 0x0e0e); ++ mii_mgr_write(1, 16, 0x0c0c); ++ mii_mgr_write(2, 16, 0x0f0f); ++ mii_mgr_write(3, 16, 0x1010); ++ mii_mgr_write(4, 16, 0x0909); ++ ++ mii_mgr_write(0, 17, 0x0000); ++ mii_mgr_write(1, 17, 0x0000); ++ mii_mgr_write(2, 17, 0x0000); ++ mii_mgr_write(3, 17, 0x0000); ++ mii_mgr_write(4, 17, 0x0000); ++#endif ++ ++#if defined (CONFIG_RT6855A_ASIC) ++ ++#if defined (CONFIG_P5_RGMII_TO_MAC_MODE) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e33b;//(P5, Force mode, Link Up, 1000Mbps, Full-Duplex, FC ON) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x7014) = 0x1f0c000c;//disable port0-port4 internal phy, set phy base address to 12 ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x250c) = 0x000fff10;//disable port5 mac learning ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x260c) = 0x000fff10;//disable port6 mac learning ++ ++#elif defined (CONFIG_P5_MII_TO_MAC_MODE) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON) ++#elif defined (CONFIG_P5_MAC_TO_PHY_MODE) ++ //rt6855/6 need to modify TX/RX phase ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x7014) = 0xc;//TX/RX CLOCK Phase select ++ ++ enable_auto_negotiate(1); ++ ++ if (isICPlusGigaPHY(1)) { ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, &phy_val); ++ phy_val |= 1<<10; //enable pause ability ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, phy_val); ++ ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val); ++ phy_val |= 1<<9; //restart AN ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val); ++ } ++ ++ if (isMarvellGigaPHY(1)) { ++ printk("Reset MARVELL phy1\n"); ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, &phy_val); ++ phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, phy_val); ++ ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val); ++ phy_val |= 1<<15; //PHY Software Reset ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val); ++ } ++ if (isVtssGigaPHY(1)) { ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0001); //extended page ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, &phy_val); ++ printk("Vitesse phy skew: %x --> ", phy_val); ++ phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns ++ phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns ++ printk("%x\n", phy_val); ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, phy_val); ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0000); //main registers ++ } ++#elif defined (CONFIG_P5_RMII_TO_MAC_MODE) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON) ++#else // Port 5 Disabled // ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x8000;//link down ++#endif ++#endif ++} ++#endif ++ ++ ++ ++ ++#if defined (CONFIG_MT7623_FPGA) ++void setup_fpga_gsw(void) ++{ ++ u32 i; ++ u32 regValue; ++ ++ /* reduce RGMII2 PAD driving strength */ ++ *(volatile u_long *)(PAD_RGMII2_MDIO_CFG) &= ~(0x3 << 4); ++ ++ //RGMII1=Normal mode ++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 14); ++ ++ //GMAC1= RGMII mode ++ *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 12); ++ ++ //enable MDIO to control MT7530 ++ regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60)); ++ regValue &= ~(0x3 << 12); ++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue; ++ ++ for(i=0;i<=4;i++) ++ { ++ //turn off PHY ++ mii_mgr_read(i, 0x0 ,®Value); ++ regValue |= (0x1<<11); ++ mii_mgr_write(i, 0x0, regValue); ++ } ++ mii_mgr_write(31, 0x7000, 0x3); //reset switch ++ udelay(10); ++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2105e337);//(GE1, Force 100M/FD, FC ON) ++ mii_mgr_write(31, 0x3600, 0x5e337); ++ ++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x00008000);//(GE2, Link down) ++ mii_mgr_write(31, 0x3500, 0x8000); ++ ++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600) ++ //regValue = 0x117ccf; //Enable Port 6, P5 as GMAC5, P5 disable*/ ++ mii_mgr_read(31, 0x7804 ,®Value); ++ regValue &= ~(1<<8); //Enable Port 6 ++ regValue |= (1<<6); //Disable Port 5 ++ regValue |= (1<<13); //Port 5 as GMAC, no Internal PHY ++ ++#if defined (CONFIG_RAETH_GMAC2) ++ //RGMII2=Normal mode ++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15); ++ ++ //GMAC2= RGMII mode ++ *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14); ++ ++ mii_mgr_write(31, 0x3500, 0x56300); //MT7530 P5 AN, we can ignore this setting?????? ++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x21056300);//(GE2, auto-polling) ++ ++ enable_auto_negotiate(0);//set polling address ++ /* set MT7530 Port 5 to PHY 0/4 mode */ ++#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN) ++ regValue &= ~((1<<13)|(1<<6)); ++ regValue |= ((1<<7)|(1<<16)|(1<<20)); ++#elif defined (CONFIG_GE_RGMII_INTERNAL_P4_AN) ++ regValue &= ~((1<<13)|(1<<6)|((1<<20))); ++ regValue |= ((1<<7)|(1<<16)); ++#endif ++ ++ //sysRegWrite(GDMA2_FWD_CFG, 0x20710000); ++#endif ++ regValue |= (1<<16);//change HW-TRAP ++ printk("change HW-TRAP to 0x%x\n",regValue); ++ mii_mgr_write(31, 0x7804 ,regValue); ++#endif ++ mii_mgr_write(0, 14, 0x1); /*RGMII*/ ++/* set MT7530 central align */ ++ mii_mgr_read(31, 0x7830, ®Value); ++ regValue &= ~1; ++ regValue |= 1<<1; ++ mii_mgr_write(31, 0x7830, regValue); ++ ++ mii_mgr_read(31, 0x7a40, ®Value); ++ regValue &= ~(1<<30); ++ mii_mgr_write(31, 0x7a40, regValue); ++ ++ regValue = 0x855; ++ mii_mgr_write(31, 0x7a78, regValue); ++ ++/*to check!!*/ ++ mii_mgr_write(31, 0x7b00, 0x102); //delay setting for 10/1000M ++ mii_mgr_write(31, 0x7b04, 0x14); //delay setting for 10/1000M ++ ++ for(i=0;i<=4;i++) { ++ mii_mgr_read(i, 4, ®Value); ++ regValue |= (3<<7); //turn on 100Base-T Advertisement ++ //regValue &= ~(3<<7); //turn off 100Base-T Advertisement ++ mii_mgr_write(i, 4, regValue); ++ ++ mii_mgr_read(i, 9, ®Value); ++ //regValue |= (3<<8); //turn on 1000Base-T Advertisement ++ regValue &= ~(3<<8); //turn off 1000Base-T Advertisement ++ mii_mgr_write(i, 9, regValue); ++ ++ //restart AN ++ mii_mgr_read(i, 0, ®Value); ++ regValue |= (1 << 9); ++ mii_mgr_write(i, 0, regValue); ++ } ++ ++ /*Tx Driving*/ ++ mii_mgr_write(31, 0x7a54, 0x44); //lower driving ++ mii_mgr_write(31, 0x7a5c, 0x44); //lower driving ++ mii_mgr_write(31, 0x7a64, 0x44); //lower driving ++ mii_mgr_write(31, 0x7a6c, 0x44); //lower driving ++ mii_mgr_write(31, 0x7a74, 0x44); //lower driving ++ mii_mgr_write(31, 0x7a7c, 0x44); //lower driving ++ ++ for(i=0;i<=4;i++) ++ { ++ //turn on PHY ++ mii_mgr_read(i, 0x0 ,®Value); ++ regValue &= ~(0x1<<11); ++ mii_mgr_write(i, 0x0, regValue); ++ } ++} ++#endif ++ ++ ++#if defined (CONFIG_RALINK_MT7621) ++ ++ ++void setup_external_gsw(void) ++{ ++ u32 regValue; ++ ++ /* reduce RGMII2 PAD driving strength */ ++ *(volatile u_long *)(PAD_RGMII2_MDIO_CFG) &= ~(0x3 << 4); ++ //enable MDIO ++ regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60)); ++ regValue &= ~(0x3 << 12); ++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue; ++ ++ //RGMII1=Normal mode ++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 14); ++ //GMAC1= RGMII mode ++ *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 12); ++ ++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x00008000);//(GE1, Link down) ++ ++ //RGMII2=Normal mode ++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15); ++ //GMAC2= RGMII mode ++ *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14); ++ ++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x2105e33b);//(GE2, Force 1000M/FD, FC ON) ++ ++} ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++void IsSwitchVlanTableBusy(void) ++{ ++ int j = 0; ++ unsigned int value = 0; ++ ++ for (j = 0; j < 20; j++) { ++ mii_mgr_read(31, 0x90, &value); ++ if ((value & 0x80000000) == 0 ){ //table busy ++ break; ++ } ++ udelay(70000); ++ } ++ if (j == 20) ++ printk("set vlan timeout value=0x%x.\n", value); ++} ++ ++void LANWANPartition(void) ++{ ++/*Set MT7530 */ ++#ifdef CONFIG_WAN_AT_P0 ++ printk("set LAN/WAN WLLLL\n"); ++ //WLLLL, wan at P0 ++ //LAN/WAN ports as security mode ++ mii_mgr_write(31, 0x2004, 0xff0003);//port0 ++ mii_mgr_write(31, 0x2104, 0xff0003);//port1 ++ mii_mgr_write(31, 0x2204, 0xff0003);//port2 ++ mii_mgr_write(31, 0x2304, 0xff0003);//port3 ++ mii_mgr_write(31, 0x2404, 0xff0003);//port4 ++ ++ //set PVID ++ mii_mgr_write(31, 0x2014, 0x10002);//port0 ++ mii_mgr_write(31, 0x2114, 0x10001);//port1 ++ mii_mgr_write(31, 0x2214, 0x10001);//port2 ++ mii_mgr_write(31, 0x2314, 0x10001);//port3 ++ mii_mgr_write(31, 0x2414, 0x10001);//port4 ++ /*port6 */ ++ //VLAN member ++ IsSwitchVlanTableBusy(); ++ mii_mgr_write(31, 0x94, 0x407e0001);//VAWD1 ++ mii_mgr_write(31, 0x90, 0x80001001);//VTCR, VID=1 ++ IsSwitchVlanTableBusy(); ++ ++ mii_mgr_write(31, 0x94, 0x40610001);//VAWD1 ++ mii_mgr_write(31, 0x90, 0x80001002);//VTCR, VID=2 ++ IsSwitchVlanTableBusy(); ++#endif ++#ifdef CONFIG_WAN_AT_P4 ++ printk("set LAN/WAN LLLLW\n"); ++ //LLLLW, wan at P4 ++ //LAN/WAN ports as security mode ++ mii_mgr_write(31, 0x2004, 0xff0003);//port0 ++ mii_mgr_write(31, 0x2104, 0xff0003);//port1 ++ mii_mgr_write(31, 0x2204, 0xff0003);//port2 ++ mii_mgr_write(31, 0x2304, 0xff0003);//port3 ++ mii_mgr_write(31, 0x2404, 0xff0003);//port4 ++ ++ //set PVID ++ mii_mgr_write(31, 0x2014, 0x10001);//port0 ++ mii_mgr_write(31, 0x2114, 0x10001);//port1 ++ mii_mgr_write(31, 0x2214, 0x10001);//port2 ++ mii_mgr_write(31, 0x2314, 0x10001);//port3 ++ mii_mgr_write(31, 0x2414, 0x10002);//port4 ++ ++ //VLAN member ++ IsSwitchVlanTableBusy(); ++ mii_mgr_write(31, 0x94, 0x404f0001);//VAWD1 ++ mii_mgr_write(31, 0x90, 0x80001001);//VTCR, VID=1 ++ IsSwitchVlanTableBusy(); ++ mii_mgr_write(31, 0x94, 0x40500001);//VAWD1 ++ mii_mgr_write(31, 0x90, 0x80001002);//VTCR, VID=2 ++ IsSwitchVlanTableBusy(); ++#endif ++} ++ ++#if defined (CONFIG_RAETH_8023AZ_EEE) && defined (CONFIG_RALINK_MT7621) ++void mt7621_eee_patch(void) ++{ ++ u32 i; ++ ++ for(i=0;i<5;i++) ++ { ++ /* Enable EEE */ ++ mii_mgr_write(i, 13, 0x07); ++ mii_mgr_write(i, 14, 0x3c); ++ mii_mgr_write(i, 13, 0x4007); ++ mii_mgr_write(i, 14, 0x6); ++ ++ /* Forced Slave mode */ ++ mii_mgr_write(i, 31, 0x0); ++ mii_mgr_write(i, 9, 0x1600); ++ /* Increase SlvDPSready time */ ++ mii_mgr_write(i, 31, 0x52b5); ++ mii_mgr_write(i, 16, 0xafae); ++ mii_mgr_write(i, 18, 0x2f); ++ mii_mgr_write(i, 16, 0x8fae); ++ /* Incease post_update_timer */ ++ mii_mgr_write(i, 31, 0x3); ++ mii_mgr_write(i, 17, 0x4b); ++ /* Adjust 100_mse_threshold */ ++ mii_mgr_write(i, 13, 0x1e); ++ mii_mgr_write(i, 14, 0x123); ++ mii_mgr_write(i, 13, 0x401e); ++ mii_mgr_write(i, 14, 0xffff); ++ /* Disable mcc ++ mii_mgr_write(i, 13, 0x1e); ++ mii_mgr_write(i, 14, 0xa6); ++ mii_mgr_write(i, 13, 0x401e); ++ mii_mgr_write(i, 14, 0x300); ++ */ ++ } ++ ++} ++#endif ++ ++ ++#if defined (CONFIG_RALINK_MT7621) ++void setup_internal_gsw(void) ++{ ++ u32 i; ++ u32 regValue; ++ ++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600) ++ /*Hardware reset Switch*/ ++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x34) |= (0x1 << 2); ++ udelay(1000); ++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x34) &= ~(0x1 << 2); ++ udelay(10000); ++ ++ /* reduce RGMII2 PAD driving strength */ ++ *(volatile u_long *)(PAD_RGMII2_MDIO_CFG) &= ~(0x3 << 4); ++ ++ //RGMII1=Normal mode ++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 14); ++ ++ //GMAC1= RGMII mode ++ *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 12); ++ ++ //enable MDIO to control MT7530 ++ regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60)); ++ regValue &= ~(0x3 << 12); ++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue; ++ ++ for(i=0;i<=4;i++) ++ { ++ //turn off PHY ++ mii_mgr_read(i, 0x0 ,®Value); ++ regValue |= (0x1<<11); ++ mii_mgr_write(i, 0x0, regValue); ++ } ++ mii_mgr_write(31, 0x7000, 0x3); //reset switch ++ udelay(100); ++ ++ ++#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC) ++ trgmii_set_7530(); //reset FE, config MDIO again ++ ++ //enable MDIO to control MT7530 ++ regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60)); ++ regValue &= ~(0x3 << 12); ++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue; ++ ++ // switch to APLL if TRGMII and DDR2 ++ if ((sysRegRead(0xBE000010)>>4)&0x1) ++ { ++ apll_xtal_enable(); ++ } ++#endif ++ ++#if defined (CONFIG_MT7621_ASIC) ++ if((sysRegRead(0xbe00000c)&0xFFFF)==0x0101) { ++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2105e30b);//(GE1, Force 1000M/FD, FC ON) ++ mii_mgr_write(31, 0x3600, 0x5e30b); ++ } else { ++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2105e33b);//(GE1, Force 1000M/FD, FC ON) ++ mii_mgr_write(31, 0x3600, 0x5e33b); ++ } ++#elif defined (CONFIG_MT7621_FPGA) ++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2105e337);//(GE1, Force 100M/FD, FC ON) ++ mii_mgr_write(31, 0x3600, 0x5e337); ++#endif ++ ++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x00008000);//(GE2, Link down) ++#endif ++ ++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600) ++ //regValue = 0x117ccf; //Enable Port 6, P5 as GMAC5, P5 disable*/ ++ mii_mgr_read(31, 0x7804 ,®Value); ++ regValue &= ~(1<<8); //Enable Port 6 ++ regValue |= (1<<6); //Disable Port 5 ++ regValue |= (1<<13); //Port 5 as GMAC, no Internal PHY ++ ++#if defined (CONFIG_RAETH_GMAC2) ++ //RGMII2=Normal mode ++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15); ++ ++ //GMAC2= RGMII mode ++ *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14); ++#if !defined (CONFIG_RAETH_8023AZ_EEE) ++ mii_mgr_write(31, 0x3500, 0x56300); //MT7530 P5 AN, we can ignore this setting?????? ++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x21056300);//(GE2, auto-polling) ++ ++ enable_auto_negotiate(0);//set polling address ++#endif ++#if defined (CONFIG_RAETH_8023AZ_EEE) ++ mii_mgr_write(31, 0x3500, 0x5e33b); //MT7530 P5 Force 1000, we can ignore this setting?????? ++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x2105e33b);//(GE2, Force 1000) ++#endif ++ ++ ++ ++ /* set MT7530 Port 5 to PHY 0/4 mode */ ++#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN) ++ regValue &= ~((1<<13)|(1<<6)); ++ regValue |= ((1<<7)|(1<<16)|(1<<20)); ++#elif defined (CONFIG_GE_RGMII_INTERNAL_P4_AN) ++ regValue &= ~((1<<13)|(1<<6)|(1<<20)); ++ regValue |= ((1<<7)|(1<<16)); ++#endif ++ ++#if defined (CONFIG_RAETH_8023AZ_EEE) ++ regValue |= (1<<13); //Port 5 as GMAC, no Internal PHY ++#endif ++ //sysRegWrite(GDMA2_FWD_CFG, 0x20710000); ++#endif ++ regValue |= (1<<16);//change HW-TRAP ++ //printk("change HW-TRAP to 0x%x\n",regValue); ++ mii_mgr_write(31, 0x7804 ,regValue); ++#endif ++ mii_mgr_read(31, 0x7800, ®Value); ++ regValue = (regValue >> 9) & 0x3; ++ if(regValue == 0x3) { //25Mhz Xtal ++ /* do nothing */ ++ } else if(regValue == 0x2) { //40Mhz ++ ++ mii_mgr_write(0, 13, 0x1f); // disable MT7530 core clock ++ mii_mgr_write(0, 14, 0x410); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0x0); ++ ++ mii_mgr_write(0, 13, 0x1f); // disable MT7530 PLL ++ mii_mgr_write(0, 14, 0x40d); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0x2020); ++ ++ mii_mgr_write(0, 13, 0x1f); // for MT7530 core clock = 500Mhz ++ mii_mgr_write(0, 14, 0x40e); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0x119); ++ ++ mii_mgr_write(0, 13, 0x1f); // enable MT7530 PLL ++ mii_mgr_write(0, 14, 0x40d); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0x2820); ++ ++ udelay(20); //suggest by CD ++ ++ mii_mgr_write(0, 13, 0x1f); // enable MT7530 core clock ++ mii_mgr_write(0, 14, 0x410); ++ mii_mgr_write(0, 13, 0x401f); ++ }else { //20Mhz Xtal ++ ++ /* TODO */ ++ ++ } ++#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC) ++ mii_mgr_write(0, 14, 0x3); /*TRGMII*/ ++#else ++ mii_mgr_write(0, 14, 0x1); /*RGMII*/ ++/* set MT7530 central align */ ++ mii_mgr_read(31, 0x7830, ®Value); ++ regValue &= ~1; ++ regValue |= 1<<1; ++ mii_mgr_write(31, 0x7830, regValue); ++ ++ mii_mgr_read(31, 0x7a40, ®Value); ++ regValue &= ~(1<<30); ++ mii_mgr_write(31, 0x7a40, regValue); ++ ++ regValue = 0x855; ++ mii_mgr_write(31, 0x7a78, regValue); ++ ++#endif ++#if !defined (CONFIG_RAETH_8023AZ_EEE) ++ mii_mgr_write(31, 0x7b00, 0x102); //delay setting for 10/1000M ++ mii_mgr_write(31, 0x7b04, 0x14); //delay setting for 10/1000M ++#endif ++#if 0 ++ for(i=0;i<=4;i++) { ++ mii_mgr_read(i, 4, ®Value); ++ regValue |= (3<<7); //turn on 100Base-T Advertisement ++ //regValue &= ~(3<<7); //turn off 100Base-T Advertisement ++ mii_mgr_write(i, 4, regValue); ++ ++ mii_mgr_read(i, 9, ®Value); ++ regValue |= (3<<8); //turn on 1000Base-T Advertisement ++ //regValue &= ~(3<<8); //turn off 1000Base-T Advertisement ++ mii_mgr_write(i, 9, regValue); ++ ++ //restart AN ++ mii_mgr_read(i, 0, ®Value); ++ regValue |= (1 << 9); ++ mii_mgr_write(i, 0, regValue); ++ } ++#endif ++ ++ /*Tx Driving*/ ++ mii_mgr_write(31, 0x7a54, 0x44); //lower driving ++ mii_mgr_write(31, 0x7a5c, 0x44); //lower driving ++ mii_mgr_write(31, 0x7a64, 0x44); //lower driving ++ mii_mgr_write(31, 0x7a6c, 0x44); //lower driving ++ mii_mgr_write(31, 0x7a74, 0x44); //lower driving ++ mii_mgr_write(31, 0x7a7c, 0x44); //lower driving ++ ++ ++ LANWANPartition(); ++ ++#if !defined (CONFIG_RAETH_8023AZ_EEE) ++ //disable EEE ++ for(i=0;i<=4;i++) ++ { ++ mii_mgr_write(i, 13, 0x7); ++ mii_mgr_write(i, 14, 0x3C); ++ mii_mgr_write(i, 13, 0x4007); ++ mii_mgr_write(i, 14, 0x0); ++ } ++ ++ //Disable EEE 10Base-Te: ++ for(i=0;i<=4;i++) ++ { ++ mii_mgr_write(i, 13, 0x1f); ++ mii_mgr_write(i, 14, 0x027b); ++ mii_mgr_write(i, 13, 0x401f); ++ mii_mgr_write(i, 14, 0x1177); ++ } ++#endif ++ ++ for(i=0;i<=4;i++) ++ { ++ //turn on PHY ++ mii_mgr_read(i, 0x0 ,®Value); ++ regValue &= ~(0x1<<11); ++ mii_mgr_write(i, 0x0, regValue); ++ } ++ ++ mii_mgr_read(31, 0x7808 ,®Value); ++ regValue |= (3<<16); //Enable INTR ++ mii_mgr_write(31, 0x7808 ,regValue); ++#if defined (CONFIG_RAETH_8023AZ_EEE) && defined (CONFIG_RALINK_MT7621) ++ mt7621_eee_patch(); ++#endif ++} ++#endif ++ ++#if defined (CONFIG_GE1_TRGMII_FORCE_1200) ++void apll_xtal_enable(void) ++{ ++ unsigned long data = 0; ++ unsigned long regValue = 0; ++ ++ /* Firstly, reset all required register to default value */ ++ sysRegWrite(RALINK_ANA_CTRL_BASE, 0x00008000); ++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x0014, 0x01401d61); ++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x0018, 0x38233d0e); ++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, 0x80120004); ++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x0020, 0x1c7dbf48); ++ ++ /* toggle RG_XPTL_CHG */ ++ sysRegWrite(RALINK_ANA_CTRL_BASE, 0x00008800); ++ sysRegWrite(RALINK_ANA_CTRL_BASE, 0x00008c00); ++ ++ data = sysRegRead(RALINK_ANA_CTRL_BASE+0x0014); ++ data &= ~(0x0000ffc0); ++ ++ regValue = *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x10); ++ regValue = (regValue >> 6) & 0x7; ++ if(regValue < 6) { //20/40Mhz Xtal ++ data |= REGBIT(0x1d, 8); ++ }else { ++ data |= REGBIT(0x17, 8); ++ } ++ ++ if(regValue < 6) { //20/40Mhz Xtal ++ data |= REGBIT(0x1, 6); ++ } ++ ++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x0014, data); ++ ++ data = sysRegRead(RALINK_ANA_CTRL_BASE+0x0018); ++ data &= ~(0xf0773f00); ++ data |= REGBIT(0x3, 28); ++ data |= REGBIT(0x2, 20); ++ if(regValue < 6) { //20/40Mhz Xtal ++ data |= REGBIT(0x3, 16); ++ }else { ++ data |= REGBIT(0x2, 16); ++ } ++ data |= REGBIT(0x3, 12); ++ ++ if(regValue < 6) { //20/40Mhz Xtal ++ data |= REGBIT(0xd, 8); ++ }else { ++ data |= REGBIT(0x7, 8); ++ } ++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x0018, data); ++ ++ if(regValue < 6) { //20/40Mhz Xtal ++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x0020, 0x1c7dbf48); ++ }else { ++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x0020, 0x1697cc39); ++ } ++ //*Common setting - Set PLLGP_CTRL_4 *// ++ ///* 1. Bit 31 */ ++ data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c); ++ data &= ~(REGBIT(0x1, 31)); ++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data); ++ ++ /* 2. Bit 0 */ ++ data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c); ++ data |= REGBIT(0x1, 0); ++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data); ++ ++ /* 3. Bit 3 */ ++ data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c); ++ data |= REGBIT(0x1, 3); ++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data); ++ ++ /* 4. Bit 8 */ ++ data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c); ++ data |= REGBIT(0x1, 8); ++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data); ++ ++ /* 5. Bit 6 */ ++ data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c); ++ data |= REGBIT(0x1, 6); ++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data); ++ ++ /* 6. Bit 7 */ ++ data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c); ++ data |= REGBIT(0x1, 5); ++ data |= REGBIT(0x1, 7); ++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data); ++ ++ /* 7. Bit 17 */ ++ data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c); ++ data &= ~REGBIT(0x1, 17); ++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data); ++ ++ /* 8. TRGMII TX CLK SEL APLL */ ++ data = sysRegRead(0xbe00002c); ++ data &= 0xffffff9f; ++ data |= 0x40; ++ sysRegWrite(0xbe00002c, data); ++ ++} ++#endif ++ ++#endif ++#if defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_MT7620) ++void rt_gsw_init(void) ++{ ++#if defined (CONFIG_P4_MAC_TO_PHY_MODE) || defined (CONFIG_P5_MAC_TO_PHY_MODE) ++ u32 phy_val=0; ++#endif ++#if defined (CONFIG_RT6855_FPGA) || defined (CONFIG_MT7620_FPGA) ++ u32 i=0; ++#elif defined (CONFIG_MT7620_ASIC) ++ u32 is_BGA=0; ++#endif ++#if defined (CONFIG_P5_RGMII_TO_MT7530_MODE) ++ unsigned int regValue = 0; ++#endif ++#if defined (CONFIG_RT6855_FPGA) || defined (CONFIG_MT7620_FPGA) ++ /*keep dump switch mode */ ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3000) = 0x5e333;//(P0, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3100) = 0x5e333;//(P1, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3200) = 0x5e333;//(P2, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3300) = 0x5e333;//(P3, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON) ++#if defined (CONFIG_RAETH_HAS_PORT4) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e337;//(P4, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON) ++#else ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e333;//(P4, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON) ++#endif ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON) ++ ++ /* In order to use 10M/Full on FPGA board. We configure phy capable to ++ * 10M Full/Half duplex, so we can use auto-negotiation on PC side */ ++#if defined (CONFIG_RAETH_HAS_PORT4) ++ for(i=0;i<4;i++){ ++#else ++ for(i=0;i<5;i++){ ++#endif ++ mii_mgr_write(i, 4, 0x0461); //Capable of 10M Full/Half Duplex, flow control on/off ++ mii_mgr_write(i, 0, 0xB100); //reset all digital logic, except phy_reg ++ } ++ ++#endif ++ ++#if defined (CONFIG_PDMA_NEW) ++ *(unsigned long *)(SYSCFG1) |= (0x1 << 8); //PCIE_RC_MODE=1 ++#endif ++ ++ ++#if defined (CONFIG_MT7620_ASIC) && !defined (CONFIG_P5_RGMII_TO_MT7530_MODE) ++ is_BGA = (sysRegRead(RALINK_SYSCTL_BASE + 0xc) >> 16) & 0x1; ++ /* ++ * Reg 31: Page Control ++ * Bit 15 => PortPageSel, 1=local, 0=global ++ * Bit 14:12 => PageSel, local:0~3, global:0~4 ++ * ++ * Reg16~30:Local/Global registers ++ * ++ */ ++ /*correct PHY setting L3.0 BGA*/ ++ mii_mgr_write(1, 31, 0x4000); //global, page 4 ++ ++ mii_mgr_write(1, 17, 0x7444); ++ if(is_BGA){ ++ mii_mgr_write(1, 19, 0x0114); ++ }else{ ++ mii_mgr_write(1, 19, 0x0117); ++ } ++ ++ mii_mgr_write(1, 22, 0x10cf); ++ mii_mgr_write(1, 25, 0x6212); ++ mii_mgr_write(1, 26, 0x0777); ++ mii_mgr_write(1, 29, 0x4000); ++ mii_mgr_write(1, 28, 0xc077); ++ mii_mgr_write(1, 24, 0x0000); ++ ++ mii_mgr_write(1, 31, 0x3000); //global, page 3 ++ mii_mgr_write(1, 17, 0x4838); ++ ++ mii_mgr_write(1, 31, 0x2000); //global, page 2 ++ if(is_BGA){ ++ mii_mgr_write(1, 21, 0x0515); ++ mii_mgr_write(1, 22, 0x0053); ++ mii_mgr_write(1, 23, 0x00bf); ++ mii_mgr_write(1, 24, 0x0aaf); ++ mii_mgr_write(1, 25, 0x0fad); ++ mii_mgr_write(1, 26, 0x0fc1); ++ }else{ ++ mii_mgr_write(1, 21, 0x0517); ++ mii_mgr_write(1, 22, 0x0fd2); ++ mii_mgr_write(1, 23, 0x00bf); ++ mii_mgr_write(1, 24, 0x0aab); ++ mii_mgr_write(1, 25, 0x00ae); ++ mii_mgr_write(1, 26, 0x0fff); ++ } ++ mii_mgr_write(1, 31, 0x1000); //global, page 1 ++ mii_mgr_write(1, 17, 0xe7f8); ++ ++ mii_mgr_write(1, 31, 0x8000); //local, page 0 ++ mii_mgr_write(0, 30, 0xa000); ++ mii_mgr_write(1, 30, 0xa000); ++ mii_mgr_write(2, 30, 0xa000); ++ mii_mgr_write(3, 30, 0xa000); ++#if !defined (CONFIG_RAETH_HAS_PORT4) ++ mii_mgr_write(4, 30, 0xa000); ++#endif ++ ++ mii_mgr_write(0, 4, 0x05e1); ++ mii_mgr_write(1, 4, 0x05e1); ++ mii_mgr_write(2, 4, 0x05e1); ++ mii_mgr_write(3, 4, 0x05e1); ++#if !defined (CONFIG_RAETH_HAS_PORT4) ++ mii_mgr_write(4, 4, 0x05e1); ++#endif ++ ++ mii_mgr_write(1, 31, 0xa000); //local, page 2 ++ mii_mgr_write(0, 16, 0x1111); ++ mii_mgr_write(1, 16, 0x1010); ++ mii_mgr_write(2, 16, 0x1515); ++ mii_mgr_write(3, 16, 0x0f0f); ++#if !defined (CONFIG_RAETH_HAS_PORT4) ++ mii_mgr_write(4, 16, 0x1313); ++#endif ++ ++#if !defined (CONFIG_RAETH_8023AZ_EEE) ++ mii_mgr_write(1, 31, 0xb000); //local, page 3 ++ mii_mgr_write(0, 17, 0x0); ++ mii_mgr_write(1, 17, 0x0); ++ mii_mgr_write(2, 17, 0x0); ++ mii_mgr_write(3, 17, 0x0); ++#if !defined (CONFIG_RAETH_HAS_PORT4) ++ mii_mgr_write(4, 17, 0x0); ++#endif ++#endif ++ ++ ++ ++#if 0 ++ // for ethernet extended mode ++ mii_mgr_write(1, 31, 0x3000); ++ mii_mgr_write(1, 19, 0x122); ++ mii_mgr_write(1, 20, 0x0044); ++ mii_mgr_write(1, 23, 0xa80c); ++ mii_mgr_write(1, 24, 0x129d); ++ mii_mgr_write(1, 31, 9000); ++ mii_mgr_write(0, 18, 0x140c); ++ mii_mgr_write(1, 18, 0x140c); ++ mii_mgr_write(2, 18, 0x140c); ++ mii_mgr_write(3, 18, 0x140c); ++ mii_mgr_write(0, 0, 0x3300); ++ mii_mgr_write(1, 0, 0x3300); ++ mii_mgr_write(2, 0, 0x3300); ++ mii_mgr_write(3, 0, 0x3300); ++#if !defined (CONFIG_RAETH_HAS_PORT4) ++ mii_mgr_write(4, 18, 0x140c); ++ mii_mgr_write(4, 0, 0x3300); ++#endif ++#endif ++ ++#endif ++ ++#if defined(CONFIG_RALINK_MT7620) ++ if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) { ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x701c) = 0x800000c; //enlarge FE2SW_IPG ++ } ++#endif // CONFIG_RAETH_7620 // ++ ++ ++ ++#if defined (CONFIG_MT7620_FPGA)|| defined (CONFIG_MT7620_ASIC) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3600) = 0x5e33b;//CPU Port6 Force Link 1G, FC ON ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0010) = 0x7f7f7fe0;//Set Port6 CPU Port ++ ++#if defined (CONFIG_P5_RGMII_TO_MAC_MODE) || defined (CONFIG_P5_RGMII_TO_MT7530_MODE) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e33b;//(P5, Force mode, Link Up, 1000Mbps, Full-Duplex, FC ON) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x7014) = 0x1f0c000c; //disable port 0 ~ 4 internal phy, set phy base address to 12 ++ /*MT7620 need mac learning for PPE*/ ++ //*(unsigned long *)(RALINK_ETH_SW_BASE+0x250c) = 0x000fff10;//disable port5 mac learning ++ //*(unsigned long *)(RALINK_ETH_SW_BASE+0x260c) = 0x000fff10;//disable port6 mac learning ++ *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode ++ //rxclk_skew, txclk_skew = 0 ++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RGMii Mode ++#if defined (CONFIG_P5_RGMII_TO_MT7530_MODE) ++ ++ *(unsigned long *)(0xb0000060) &= ~(3 << 7); //set MDIO to Normal mode ++ ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x56330;//(P4, AN) ++ *(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode ++ //rxclk_skew, txclk_skew = 0 ++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=RGMii Mode ++ ++ ++ /* set MT7530 Port 0 to PHY mode */ ++ mii_mgr_read(31, 0x7804 ,®Value); ++#if defined (CONFIG_GE_RGMII_MT7530_P0_AN) ++ regValue &= ~((1<<13)|(1<<6)|(1<<5)|(1<<15)); ++ regValue |= ((1<<7)|(1<<16)|(1<<20)|(1<<24)); ++ //mii_mgr_write(31, 0x7804 ,0x115c8f); ++#elif defined (CONFIG_GE_RGMII_MT7530_P4_AN) ++ regValue &= ~((1<<13)|(1<<6)|(1<<20)|(1<<5)|(1<<15)); ++ regValue |= ((1<<7)|(1<<16)|(1<<24)); ++#endif ++ regValue &= ~(1<<8); //Enable Port 6 ++ mii_mgr_write(31, 0x7804 ,regValue); //bit 24 standalone switch ++ ++/* set MT7530 central align */ ++ mii_mgr_read(31, 0x7830, ®Value); ++ regValue &= ~1; ++ regValue |= 1<<1; ++ mii_mgr_write(31, 0x7830, regValue); ++ ++ mii_mgr_read(31, 0x7a40, ®Value); ++ regValue &= ~(1<<30); ++ mii_mgr_write(31, 0x7a40, regValue); ++ ++ regValue = 0x855; ++ mii_mgr_write(31, 0x7a78, regValue); ++ ++ /*AN should be set after MT7530 HWSTRAP*/ ++#if defined (CONFIG_GE_RGMII_MT7530_P0_AN) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x7000) = 0xc5000100;//(P0, AN polling) ++#elif defined (CONFIG_GE_RGMII_MT7530_P4_AN) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x7000) = 0xc5000504;//(P4, AN polling) ++#endif ++#endif ++ ++#elif defined (CONFIG_P5_MII_TO_MAC_MODE) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON) ++ *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode ++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=Mii Mode ++ *(unsigned long *)(SYSCFG1) |= (0x1 << 12); ++ ++#elif defined (CONFIG_P5_MAC_TO_PHY_MODE) ++ *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode ++ *(unsigned long *)(0xb0000060) &= ~(3 << 7); //set MDIO to Normal mode ++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RGMii Mode ++ ++ enable_auto_negotiate(1); ++ ++ if (isICPlusGigaPHY(1)) { ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, &phy_val); ++ phy_val |= 1<<10; //enable pause ability ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, phy_val); ++ ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val); ++ phy_val |= 1<<9; //restart AN ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val); ++ }else if (isMarvellGigaPHY(1)) { ++#if defined (CONFIG_MT7620_FPGA) ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, &phy_val); ++ phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half) ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, phy_val); ++#endif ++ printk("Reset MARVELL phy1\n"); ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, &phy_val); ++ phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, phy_val); ++ ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val); ++ phy_val |= 1<<15; //PHY Software Reset ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val); ++ }else if (isVtssGigaPHY(1)) { ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0001); //extended page ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, &phy_val); ++ printk("Vitesse phy skew: %x --> ", phy_val); ++ phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns ++ phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns ++ printk("%x\n", phy_val); ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, phy_val); ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0000); //main registers ++ } ++ ++ ++#elif defined (CONFIG_P5_RMII_TO_MAC_MODE) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON) ++ *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode ++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RvMii Mode ++ *(unsigned long *)(SYSCFG1) |= (0x2 << 12); ++ ++#else // Port 5 Disabled // ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x8000;//link down ++ *(unsigned long *)(0xb0000060) |= (1 << 9); //set RGMII to GPIO mode ++#endif ++#endif ++ ++#if defined (CONFIG_P4_RGMII_TO_MAC_MODE) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e33b;//(P4, Force mode, Link Up, 1000Mbps, Full-Duplex, FC ON) ++ *(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode ++ //rxclk_skew, txclk_skew = 0 ++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=RGMii Mode ++ ++#elif defined (CONFIG_P4_MII_TO_MAC_MODE) ++ *(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode ++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=Mii Mode ++ *(unsigned long *)(SYSCFG1) |= (0x1 << 14); ++ ++#elif defined (CONFIG_P4_MAC_TO_PHY_MODE) ++ *(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode ++ *(unsigned long *)(0xb0000060) &= ~(3 << 7); //set MDIO to Normal mode ++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=RGMii Mode ++ ++ enable_auto_negotiate(1); ++ ++ if (isICPlusGigaPHY(2)) { ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 4, &phy_val); ++ phy_val |= 1<<10; //enable pause ability ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 4, phy_val); ++ ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, &phy_val); ++ phy_val |= 1<<9; //restart AN ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, phy_val); ++ }else if (isMarvellGigaPHY(2)) { ++#if defined (CONFIG_MT7620_FPGA) ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, &phy_val); ++ phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half) ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, phy_val); ++#endif ++ printk("Reset MARVELL phy2\n"); ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, &phy_val); ++ phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, phy_val); ++ ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, &phy_val); ++ phy_val |= 1<<15; //PHY Software Reset ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, phy_val); ++ }else if (isVtssGigaPHY(2)) { ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 0x0001); //extended page ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, &phy_val); ++ printk("Vitesse phy skew: %x --> ", phy_val); ++ phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns ++ phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns ++ printk("%x\n", phy_val); ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, phy_val); ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 0x0000); //main registers ++ } ++ ++#elif defined (CONFIG_P4_RMII_TO_MAC_MODE) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON) ++ *(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode ++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE1_MODE=RvMii Mode ++ *(unsigned long *)(SYSCFG1) |= (0x2 << 14); ++#elif defined (CONFIG_GE_RGMII_MT7530_P0_AN) || defined (CONFIG_GE_RGMII_MT7530_P4_AN) ++#else // Port 4 Disabled // ++ *(unsigned long *)(SYSCFG1) |= (0x3 << 14); //GE2_MODE=RJ45 Mode ++ *(unsigned long *)(0xb0000060) |= (1 << 10); //set RGMII2 to GPIO mode ++#endif ++ ++} ++#endif ++ ++#if defined (CONFIG_RALINK_MT7628) ++ ++void mt7628_ephy_init(void) ++{ ++ int i; ++ u32 phy_val; ++ mii_mgr_write(0, 31, 0x2000); //change G2 page ++ mii_mgr_write(0, 26, 0x0000); ++ ++ for(i=0; i<5; i++){ ++ mii_mgr_write(i, 31, 0x8000); //change L0 page ++ mii_mgr_write(i, 0, 0x3100); ++ ++#if defined (CONFIG_RAETH_8023AZ_EEE) ++ mii_mgr_read(i, 26, &phy_val);// EEE setting ++ phy_val |= (1 << 5); ++ mii_mgr_write(i, 26, phy_val); ++#else ++ //disable EEE ++ mii_mgr_write(i, 13, 0x7); ++ mii_mgr_write(i, 14, 0x3C); ++ mii_mgr_write(i, 13, 0x4007); ++ mii_mgr_write(i, 14, 0x0); ++#endif ++ mii_mgr_write(i, 30, 0xa000); ++ mii_mgr_write(i, 31, 0xa000); // change L2 page ++ mii_mgr_write(i, 16, 0x0606); ++ mii_mgr_write(i, 23, 0x0f0e); ++ mii_mgr_write(i, 24, 0x1610); ++ mii_mgr_write(i, 30, 0x1f15); ++ mii_mgr_write(i, 28, 0x6111); ++ ++ mii_mgr_read(i, 4, &phy_val); ++ phy_val |= (1 << 10); ++ mii_mgr_write(i, 4, phy_val); ++ } ++ ++ //100Base AOI setting ++ mii_mgr_write(0, 31, 0x5000); //change G5 page ++ mii_mgr_write(0, 19, 0x004a); ++ mii_mgr_write(0, 20, 0x015a); ++ mii_mgr_write(0, 21, 0x00ee); ++ mii_mgr_write(0, 22, 0x0033); ++ mii_mgr_write(0, 23, 0x020a); ++ mii_mgr_write(0, 24, 0x0000); ++ mii_mgr_write(0, 25, 0x024a); ++ mii_mgr_write(0, 26, 0x035a); ++ mii_mgr_write(0, 27, 0x02ee); ++ mii_mgr_write(0, 28, 0x0233); ++ mii_mgr_write(0, 29, 0x000a); ++ mii_mgr_write(0, 30, 0x0000); ++ /* Fix EPHY idle state abnormal behavior */ ++ mii_mgr_write(0, 31, 0x4000); //change G4 page ++ mii_mgr_write(0, 29, 0x000d); ++ mii_mgr_write(0, 30, 0x0500); ++ ++} ++ ++#endif ++ ++ ++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++void rt305x_esw_init(void) ++{ ++ int i=0; ++ u32 phy_val=0, val=0; ++#if defined (CONFIG_RT3052_ASIC) ++ u32 phy_val2; ++#endif ++ ++#if defined (CONFIG_RT5350_ASIC) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0168) = 0x17; ++#endif ++ ++ /* ++ * FC_RLS_TH=200, FC_SET_TH=160 ++ * DROP_RLS=120, DROP_SET_TH=80 ++ */ ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0008) = 0xC8A07850; ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00E4) = 0x00000000; ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0014) = 0x00405555; ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0050) = 0x00002001; ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0090) = 0x00007f7f; ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0098) = 0x00007f3f; //disable VLAN ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00CC) = 0x0002500c; ++#ifndef CONFIG_UNH_TEST ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x009C) = 0x0008a301; //hashing algorithm=XOR48, aging interval=300sec ++#else ++ /* ++ * bit[30]:1 Backoff Algorithm Option: The latest one to pass UNH test ++ * bit[29]:1 Length of Received Frame Check Enable ++ * bit[8]:0 Enable collision 16 packet abort and late collision abort ++ * bit[7:6]:01 Maximum Packet Length: 1518 ++ */ ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x009C) = 0x6008a241; ++#endif ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x008C) = 0x02404040; ++#if defined (CONFIG_RT3052_ASIC) || defined (CONFIG_RT3352_ASIC) || defined (CONFIG_RT5350_ASIC) || defined (CONFIG_MT7628_ASIC) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) = 0x3f502b28; //Change polling Ext PHY Addr=0x1F ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0084) = 0x00000000; ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0110) = 0x7d000000; //1us cycle number=125 (FE's clock=125Mhz) ++#elif defined (CONFIG_RT3052_FPGA) || defined (CONFIG_RT3352_FPGA) || defined (CONFIG_RT5350_FPGA) || defined (CONFIG_MT7628_FPGA) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) = 0x00f03ff9; //polling Ext PHY Addr=0x0, force port5 as 100F/D (disable auto-polling) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0084) = 0xffdf1f00; ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0110) = 0x0d000000; //1us cycle number=13 (FE's clock=12.5Mhz) ++ ++ /* In order to use 10M/Full on FPGA board. We configure phy capable to ++ * 10M Full/Half duplex, so we can use auto-negotiation on PC side */ ++ for(i=0;i<5;i++){ ++ mii_mgr_write(i, 4, 0x0461); //Capable of 10M Full/Half Duplex, flow control on/off ++ mii_mgr_write(i, 0, 0xB100); //reset all digital logic, except phy_reg ++ } ++#endif ++ ++ /* ++ * set port 5 force to 1000M/Full when connecting to switch or iNIC ++ */ ++#if defined (CONFIG_P5_RGMII_TO_MAC_MODE) ++ *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1<<29); //disable port 5 auto-polling ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) |= 0x3fff; //force 1000M full duplex ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(0xf<<20); //rxclk_skew, txclk_skew = 0 ++#elif defined (CONFIG_P5_MII_TO_MAC_MODE) ++ *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1<<29); //disable port 5 auto-polling ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(0x3fff); ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) |= 0x3ffd; //force 100M full duplex ++ ++#if defined (CONFIG_RALINK_RT3352) ++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=Mii Mode ++ *(unsigned long *)(SYSCFG1) |= (0x1 << 12); ++#endif ++ ++#elif defined (CONFIG_P5_MAC_TO_PHY_MODE) ++ *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode ++ *(unsigned long *)(0xb0000060) &= ~(1 << 7); //set MDIO to Normal mode ++#if defined (CONFIG_RT3052_ASIC) || defined (CONFIG_RT3352_ASIC) ++ enable_auto_negotiate(1); ++#endif ++ if (isMarvellGigaPHY(1)) { ++#if defined (CONFIG_RT3052_FPGA) || defined (CONFIG_RT3352_FPGA) ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, &phy_val); ++ phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half) ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, phy_val); ++#endif ++ printk("\n Reset MARVELL phy\n"); ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, &phy_val); ++ phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, phy_val); ++ ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val); ++ phy_val |= 1<<15; //PHY Software Reset ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val); ++ } ++ if (isVtssGigaPHY(1)) { ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0001); //extended page ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, &phy_val); ++ printk("Vitesse phy skew: %x --> ", phy_val); ++ phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns ++ phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns ++ printk("%x\n", phy_val); ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, phy_val); ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0000); //main registers ++ } ++ ++#elif defined (CONFIG_P5_RMII_TO_MAC_MODE) ++ *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1<<29); //disable port 5 auto-polling ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(0x3fff); ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) |= 0x3ffd; //force 100M full duplex ++ ++#if defined (CONFIG_RALINK_RT3352) ++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RvMii Mode ++ *(unsigned long *)(SYSCFG1) |= (0x2 << 12); ++#endif ++#else // Port 5 Disabled // ++ ++#if defined (CONFIG_RALINK_RT3052) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1 << 29); //port5 auto polling disable ++ *(unsigned long *)(0xb0000060) |= (1 << 7); //set MDIO to GPIO mode (GPIO22-GPIO23) ++ *(unsigned long *)(0xb0000060) |= (1 << 9); //set RGMII to GPIO mode (GPIO41-GPIO50) ++ *(unsigned long *)(0xb0000674) = 0xFFF; //GPIO41-GPIO50 output mode ++ *(unsigned long *)(0xb000067C) = 0x0; //GPIO41-GPIO50 output low ++#elif defined (CONFIG_RALINK_RT3352) ++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1 << 29); //port5 auto polling disable ++ *(unsigned long *)(0xb0000060) |= (1 << 7); //set MDIO to GPIO mode (GPIO22-GPIO23) ++ *(unsigned long *)(0xb0000624) = 0xC0000000; //GPIO22-GPIO23 output mode ++ *(unsigned long *)(0xb000062C) = 0xC0000000; //GPIO22-GPIO23 output high ++ ++ *(unsigned long *)(0xb0000060) |= (1 << 9); //set RGMII to GPIO mode (GPIO24-GPIO35) ++ *(unsigned long *)(0xb000064C) = 0xFFF; //GPIO24-GPIO35 output mode ++ *(unsigned long *)(0xb0000654) = 0xFFF; //GPIO24-GPIO35 output high ++#elif defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628) ++ /* do nothing */ ++#endif ++#endif // CONFIG_P5_RGMII_TO_MAC_MODE // ++ ++ ++#if defined (CONFIG_RT3052_ASIC) ++ rw_rf_reg(0, 0, &phy_val); ++ phy_val = phy_val >> 4; ++ ++ if(phy_val > 0x5) { ++ ++ rw_rf_reg(0, 26, &phy_val); ++ phy_val2 = (phy_val | (0x3 << 5)); ++ rw_rf_reg(1, 26, &phy_val2); ++ ++ // reset EPHY ++ val = sysRegRead(RSTCTRL); ++ val = val | RALINK_EPHY_RST; ++ sysRegWrite(RSTCTRL, val); ++ val = val & ~(RALINK_EPHY_RST); ++ sysRegWrite(RSTCTRL, val); ++ ++ rw_rf_reg(1, 26, &phy_val); ++ ++ //select local register ++ mii_mgr_write(0, 31, 0x8000); ++ for(i=0;i<5;i++){ ++ mii_mgr_write(i, 26, 0x1600); //TX10 waveform coefficient //LSB=0 disable PHY ++ mii_mgr_write(i, 29, 0x7058); //TX100/TX10 AD/DA current bias ++ mii_mgr_write(i, 30, 0x0018); //TX100 slew rate control ++ } ++ ++ //select global register ++ mii_mgr_write(0, 31, 0x0); ++ mii_mgr_write(0, 1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2 ++ mii_mgr_write(0, 2, 0x6254); //enlarge agcsel threshold 5 and threshold 4 ++ mii_mgr_write(0, 3, 0xa17f); //enlarge agcsel threshold 6 ++//#define ENABLE_LDPS ++#if defined (ENABLE_LDPS) ++ mii_mgr_write(0, 12, 0x7eaa); ++ mii_mgr_write(0, 22, 0x252f); //tune TP_IDL tail and head waveform, enable power down slew rate control ++#else ++ mii_mgr_write(0, 12, 0x0); ++ mii_mgr_write(0, 22, 0x052f); ++#endif ++ mii_mgr_write(0, 14, 0x65); //longer TP_IDL tail length ++ mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold. ++ mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum ++ mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold ++ mii_mgr_write(0, 27, 0x2fce); //set PLL/Receive bias current are calibrated ++ mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350) ++ mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3) ++ mii_mgr_write(0, 31, 0x8000); //select local register ++ ++ for(i=0;i<5;i++){ ++ //LSB=1 enable PHY ++ mii_mgr_read(i, 26, &phy_val); ++ phy_val |= 0x0001; ++ mii_mgr_write(i, 26, phy_val); ++ } ++ } else { ++ //select local register ++ mii_mgr_write(0, 31, 0x8000); ++ for(i=0;i<5;i++){ ++ mii_mgr_write(i, 26, 0x1600); //TX10 waveform coefficient //LSB=0 disable PHY ++ mii_mgr_write(i, 29, 0x7058); //TX100/TX10 AD/DA current bias ++ mii_mgr_write(i, 30, 0x0018); //TX100 slew rate control ++ } ++ ++ //select global register ++ mii_mgr_write(0, 31, 0x0); ++ mii_mgr_write(0, 1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2 ++ mii_mgr_write(0, 2, 0x6254); //enlarge agcsel threshold 5 and threshold 4 ++ mii_mgr_write(0, 3, 0xa17f); //enlarge agcsel threshold 6 ++ mii_mgr_write(0, 14, 0x65); //longer TP_IDL tail length ++ mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold. ++ mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum ++ mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold ++ mii_mgr_write(0, 22, 0x052f); //tune TP_IDL tail and head waveform ++ mii_mgr_write(0, 27, 0x2fce); //set PLL/Receive bias current are calibrated ++ mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350) ++ mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3) ++ mii_mgr_write(0, 31, 0x8000); //select local register ++ ++ for(i=0;i<5;i++){ ++ //LSB=1 enable PHY ++ mii_mgr_read(i, 26, &phy_val); ++ phy_val |= 0x0001; ++ mii_mgr_write(i, 26, phy_val); ++ } ++ } ++#elif defined (CONFIG_RT3352_ASIC) ++ //PHY IOT ++ // reset EPHY ++ val = sysRegRead(RSTCTRL); ++ val = val | RALINK_EPHY_RST; ++ sysRegWrite(RSTCTRL, val); ++ val = val & ~(RALINK_EPHY_RST); ++ sysRegWrite(RSTCTRL, val); ++ ++ //select local register ++ mii_mgr_write(0, 31, 0x8000); ++ for(i=0;i<5;i++){ ++ mii_mgr_write(i, 26, 0x1600); //TX10 waveform coefficient //LSB=0 disable PHY ++ mii_mgr_write(i, 29, 0x7016); //TX100/TX10 AD/DA current bias ++ mii_mgr_write(i, 30, 0x0038); //TX100 slew rate control ++ } ++ ++ //select global register ++ mii_mgr_write(0, 31, 0x0); ++ mii_mgr_write(0, 1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2 ++ mii_mgr_write(0, 2, 0x6254); //enlarge agcsel threshold 5 and threshold 4 ++ mii_mgr_write(0, 3, 0xa17f); //enlarge agcsel threshold 6 ++ mii_mgr_write(0, 12, 0x7eaa); ++ mii_mgr_write(0, 14, 0x65); //longer TP_IDL tail length ++ mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold. ++ mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum ++ mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold ++ mii_mgr_write(0, 22, 0x253f); //tune TP_IDL tail and head waveform, enable power down slew rate control ++ mii_mgr_write(0, 27, 0x2fda); //set PLL/Receive bias current are calibrated ++ mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350) ++ mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3) ++ mii_mgr_write(0, 31, 0x8000); //select local register ++ ++ for(i=0;i<5;i++){ ++ //LSB=1 enable PHY ++ mii_mgr_read(i, 26, &phy_val); ++ phy_val |= 0x0001; ++ mii_mgr_write(i, 26, phy_val); ++ } ++ ++#elif defined (CONFIG_RT5350_ASIC) ++ //PHY IOT ++ // reset EPHY ++ val = sysRegRead(RSTCTRL); ++ val = val | RALINK_EPHY_RST; ++ sysRegWrite(RSTCTRL, val); ++ val = val & ~(RALINK_EPHY_RST); ++ sysRegWrite(RSTCTRL, val); ++ ++ //select local register ++ mii_mgr_write(0, 31, 0x8000); ++ for(i=0;i<5;i++){ ++ mii_mgr_write(i, 26, 0x1600); //TX10 waveform coefficient //LSB=0 disable PHY ++ mii_mgr_write(i, 29, 0x7015); //TX100/TX10 AD/DA current bias ++ mii_mgr_write(i, 30, 0x0038); //TX100 slew rate control ++ } ++ ++ //select global register ++ mii_mgr_write(0, 31, 0x0); ++ mii_mgr_write(0, 1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2 ++ mii_mgr_write(0, 2, 0x6254); //enlarge agcsel threshold 5 and threshold 4 ++ mii_mgr_write(0, 3, 0xa17f); //enlarge agcsel threshold 6 ++ mii_mgr_write(0, 12, 0x7eaa); ++ mii_mgr_write(0, 14, 0x65); //longer TP_IDL tail length ++ mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold. ++ mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum ++ mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold ++ mii_mgr_write(0, 22, 0x253f); //tune TP_IDL tail and head waveform, enable power down slew rate control ++ mii_mgr_write(0, 27, 0x2fda); //set PLL/Receive bias current are calibrated ++ mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350) ++ mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3) ++ mii_mgr_write(0, 31, 0x8000); //select local register ++ ++ for(i=0;i<5;i++){ ++ //LSB=1 enable PHY ++ mii_mgr_read(i, 26, &phy_val); ++ phy_val |= 0x0001; ++ mii_mgr_write(i, 26, phy_val); ++ } ++#elif defined (CONFIG_MT7628_ASIC) ++/*INIT MT7628 PHY HERE*/ ++ val = sysRegRead(RT2880_AGPIOCFG_REG); ++#if defined (CONFIG_ETH_ONE_PORT_ONLY) ++ val |= (MT7628_P0_EPHY_AIO_EN | MT7628_P1_EPHY_AIO_EN | MT7628_P2_EPHY_AIO_EN | MT7628_P3_EPHY_AIO_EN | MT7628_P4_EPHY_AIO_EN); ++ val = val & ~(MT7628_P0_EPHY_AIO_EN); ++#else ++ val = val & ~(MT7628_P0_EPHY_AIO_EN | MT7628_P1_EPHY_AIO_EN | MT7628_P2_EPHY_AIO_EN | MT7628_P3_EPHY_AIO_EN | MT7628_P4_EPHY_AIO_EN); ++#endif ++ if ((*((volatile u32 *)(RALINK_SYSCTL_BASE + 0x8))) & 0x10000) ++ val &= ~0x1f0000; ++ sysRegWrite(RT2880_AGPIOCFG_REG, val); ++ ++ val = sysRegRead(RSTCTRL); ++ val = val | RALINK_EPHY_RST; ++ sysRegWrite(RSTCTRL, val); ++ val = val & ~(RALINK_EPHY_RST); ++ sysRegWrite(RSTCTRL, val); ++ ++ ++ val = sysRegRead(RALINK_SYSCTL_BASE + 0x64); ++#if defined (CONFIG_ETH_ONE_PORT_ONLY) ++ val &= 0xf003f003; ++ val |= 0x05540554; ++ sysRegWrite(RALINK_SYSCTL_BASE + 0x64, val); // set P0 EPHY LED mode ++#else ++ val &= 0xf003f003; ++ sysRegWrite(RALINK_SYSCTL_BASE + 0x64, val); // set P0~P4 EPHY LED mode ++#endif ++ ++ udelay(5000); ++ mt7628_ephy_init(); ++ ++#endif ++} ++#endif ++ ++#if defined (CONFIG_ARCH_MT7623) /* TODO: just for bring up, should be removed!!! */ ++void mt7623_pinmux_set(void) ++{ ++ unsigned long regValue; ++ ++ //printk("[mt7623_pinmux_set]start\n"); ++ /* Pin277: ESW_RST (1) */ ++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ad0)); ++ regValue &= ~(BITS(6,8)); ++ regValue |= BIT(6); ++ *(volatile u_long *)(0xf0005ad0) = regValue; ++ ++ /* Pin262: G2_TXEN (1) */ ++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005aa0)); ++ regValue &= ~(BITS(6,8)); ++ regValue |= BIT(6); ++ *(volatile u_long *)(0xf0005aa0) = regValue; ++ /* Pin263: G2_TXD3 (1) */ ++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005aa0)); ++ regValue &= ~(BITS(9,11)); ++ regValue |= BIT(9); ++ *(volatile u_long *)(0xf0005aa0) = regValue; ++ /* Pin264: G2_TXD2 (1) */ ++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005aa0)); ++ regValue &= ~(BITS(12,14)); ++ regValue |= BIT(12); ++ *(volatile u_long *)(0xf0005aa0) = regValue; ++ /* Pin265: G2_TXD1 (1) */ ++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ab0)); ++ regValue &= ~(BITS(0,2)); ++ regValue |= BIT(0); ++ *(volatile u_long *)(0xf0005ab0) = regValue; ++ /* Pin266: G2_TXD0 (1) */ ++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ab0)); ++ regValue &= ~(BITS(3,5)); ++ regValue |= BIT(3); ++ *(volatile u_long *)(0xf0005ab0) = regValue; ++ /* Pin267: G2_TXC (1) */ ++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ab0)); ++ regValue &= ~(BITS(6,8)); ++ regValue |= BIT(6); ++ *(volatile u_long *)(0xf0005ab0) = regValue; ++ /* Pin268: G2_RXC (1) */ ++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ab0)); ++ regValue &= ~(BITS(9,11)); ++ regValue |= BIT(9); ++ *(volatile u_long *)(0xf0005ab0) = regValue; ++ /* Pin269: G2_RXD0 (1) */ ++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ab0)); ++ regValue &= ~(BITS(12,14)); ++ regValue |= BIT(12); ++ *(volatile u_long *)(0xf0005ab0) = regValue; ++ /* Pin270: G2_RXD1 (1) */ ++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ac0)); ++ regValue &= ~(BITS(0,2)); ++ regValue |= BIT(0); ++ *(volatile u_long *)(0xf0005ac0) = regValue; ++ /* Pin271: G2_RXD2 (1) */ ++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ac0)); ++ regValue &= ~(BITS(3,5)); ++ regValue |= BIT(3); ++ *(volatile u_long *)(0xf0005ac0) = regValue; ++ /* Pin272: G2_RXD3 (1) */ ++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ac0)); ++ regValue &= ~(BITS(6,8)); ++ regValue |= BIT(6); ++ *(volatile u_long *)(0xf0005ac0) = regValue; ++ /* Pin274: G2_RXDV (1) */ ++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ac0)); ++ regValue &= ~(BITS(12,14)); ++ regValue |= BIT(12); ++ *(volatile u_long *)(0xf0005ac0) = regValue; ++ ++ /* Pin275: MDC (1) */ ++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ad0)); ++ regValue &= ~(BITS(0,2)); ++ regValue |= BIT(0); ++ *(volatile u_long *)(0xf0005ad0) = regValue; ++ /* Pin276: MDIO (1) */ ++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ad0)); ++ regValue &= ~(BITS(3,5)); ++ regValue |= BIT(3); ++ *(volatile u_long *)(0xf0005ad0) = regValue; ++ //printk("[mt7623_pinmux_set]end\n"); ++} ++ ++void wait_loop(void) { ++ int i,j; ++ int read_data; ++ j =0; ++ while (j< 10) { ++ for(i = 0; i<32; i = i+1){ ++ read_data = *(volatile u_long *)(0xFB110610); ++ } ++ j++; ++ } ++} ++ ++void trgmii_calibration_7623(void) { ++ ++ unsigned int tap_a[5]; // minumum delay for all correct ++ unsigned int tap_b[5]; // maximum delay for all correct ++ unsigned int final_tap[5]; ++ unsigned int bslip_en; ++ unsigned int rxc_step_size; ++ unsigned int rxd_step_size; ++ unsigned int read_data; ++ unsigned int tmp; ++ unsigned int rd_wd; ++ int i; ++ unsigned int err_cnt[5]; ++ unsigned int init_toggle_data; ++ unsigned int err_flag[5]; ++ unsigned int err_total_flag; ++ unsigned int training_word; ++ unsigned int rd_tap; ++ ++ u32 TRGMII_7623_base; ++ u32 TRGMII_7623_RD_0; ++ u32 TRGMII_RD_1; ++ u32 TRGMII_RD_2; ++ u32 TRGMII_RD_3; ++ u32 TRGMII_RXCTL; ++ u32 TRGMII_RCK_CTRL; ++ u32 TRGMII_7530_base; ++ TRGMII_7623_base = 0xFB110300; ++ TRGMII_7623_RD_0 = TRGMII_7623_base + 0x10; ++ TRGMII_RCK_CTRL = TRGMII_7623_base; ++ rxd_step_size =0x1; ++ rxc_step_size =0x4; ++ init_toggle_data = 0x00000055; ++ training_word = 0x000000AC; ++ ++ //printk("Calibration begin ........"); ++ *(volatile u_long *)(TRGMII_7623_base +0x04) &= 0x3fffffff; // RX clock gating in MT7623 ++ *(volatile u_long *)(TRGMII_7623_base +0x00) |= 0x80000000; // Assert RX reset in MT7623 ++ *(volatile u_long *)(TRGMII_7623_base +0x78) |= 0x00002000; // Set TX OE edge in MT7623 ++ *(volatile u_long *)(TRGMII_7623_base +0x04) |= 0xC0000000; // Disable RX clock gating in MT7623 ++ *(volatile u_long *)(TRGMII_7623_base ) &= 0x7fffffff; // Release RX reset in MT7623 ++ //printk("Check Point 1 .....\n"); ++ for (i = 0 ; i<5 ; i++) { ++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) |= 0x80000000; // Set bslip_en = 1 ++ } ++ ++ //printk("Enable Training Mode in MT7530\n"); ++ mii_mgr_read(0x1F,0x7A40,&read_data); ++ read_data |= 0xc0000000; ++ mii_mgr_write(0x1F,0x7A40,read_data); //Enable Training Mode in MT7530 ++ err_total_flag = 0; ++ //printk("Adjust RXC delay in MT7623\n"); ++ read_data =0x0; ++ while (err_total_flag == 0 && read_data != 0x68) { ++ //printk("2nd Enable EDGE CHK in MT7623\n"); ++ /* Enable EDGE CHK in MT7623*/ ++ for (i = 0 ; i<5 ; i++) { ++ tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8); ++ tmp |= 0x40000000; ++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff; ++ } ++ wait_loop(); ++ err_total_flag = 1; ++ for (i = 0 ; i<5 ; i++) { ++ err_cnt[i] = ((*(volatile u_long *)(TRGMII_7623_RD_0 + i*8)) >> 8) & 0x0000000f; ++ rd_wd = ((*(volatile u_long *)(TRGMII_7623_RD_0 + i*8)) >> 16) & 0x000000ff; ++ //printk("ERR_CNT = %d, RD_WD =%x\n",err_cnt[i],rd_wd); ++ if ( err_cnt[i] !=0 ) { ++ err_flag[i] = 1; ++ } ++ else if (rd_wd != 0x55) { ++ err_flag[i] = 1; ++ } ++ else { ++ err_flag[i] = 0; ++ } ++ err_total_flag = err_flag[i] & err_total_flag; ++ } ++ ++ //printk("2nd Disable EDGE CHK in MT7623\n"); ++ /* Disable EDGE CHK in MT7623*/ ++ for (i = 0 ; i<5 ; i++) { ++ tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8); ++ tmp |= 0x40000000; ++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff; ++ } ++ wait_loop(); ++ //printk("2nd Disable EDGE CHK in MT7623\n"); ++ /* Adjust RXC delay */ ++ *(volatile u_long *)(TRGMII_7623_base +0x00) |= 0x80000000; // Assert RX reset in MT7623 ++ *(volatile u_long *)(TRGMII_7623_base +0x04) &= 0x3fffffff; // RX clock gating in MT7623 ++ read_data = *(volatile u_long *)(TRGMII_7623_base); ++ if (err_total_flag == 0) { ++ tmp = (read_data & 0x0000007f) + rxc_step_size; ++ //printk(" RXC delay = %d\n", tmp); ++ read_data >>= 8; ++ read_data &= 0xffffff80; ++ read_data |= tmp; ++ read_data <<=8; ++ read_data &= 0xffffff80; ++ read_data |=tmp; ++ *(volatile u_long *)(TRGMII_7623_base) = read_data; ++ } ++ read_data &=0x000000ff; ++ *(volatile u_long *)(TRGMII_7623_base ) &= 0x7fffffff; // Release RX reset in MT7623 ++ *(volatile u_long *)(TRGMII_7623_base +0x04) |= 0xC0000000; // Disable RX clock gating in MT7623 ++ for (i = 0 ; i<5 ; i++) { ++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = (*(volatile u_long *)(TRGMII_7623_RD_0 + i*8)) | 0x80000000; // Set bslip_en = ~bit_slip_en ++ } ++ } ++ //printk("Finish RXC Adjustment while loop\n"); ++ //printk("Read RD_WD MT7623\n"); ++ /* Read RD_WD MT7623*/ ++ for (i = 0 ; i<5 ; i++) { ++ rd_tap=0; ++ while (err_flag[i] != 0) { ++ /* Enable EDGE CHK in MT7623*/ ++ tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8); ++ tmp |= 0x40000000; ++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff; ++ wait_loop(); ++ read_data = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8); ++ err_cnt[i] = (read_data >> 8) & 0x0000000f; // Read MT7623 Errcnt ++ rd_wd = (read_data >> 16) & 0x000000ff; ++ if (err_cnt[i] != 0 || rd_wd !=0x55){ ++ err_flag [i] = 1; ++ } ++ else { ++ err_flag[i] =0; ++ } ++ /* Disable EDGE CHK in MT7623*/ ++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) &= 0x4fffffff; ++ tmp |= 0x40000000; ++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff; ++ wait_loop(); ++ //err_cnt[i] = ((read_data) >> 8) & 0x0000000f; // Read MT7623 Errcnt ++ if (err_flag[i] !=0) { ++ rd_tap = (read_data & 0x0000007f) + rxd_step_size; // Add RXD delay in MT7623 ++ read_data = (read_data & 0xffffff80) | rd_tap; ++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = read_data; ++ tap_a[i] = rd_tap; ++ } else { ++ rd_tap = (read_data & 0x0000007f) + 4; ++ read_data = (read_data & 0xffffff80) | rd_tap; ++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = read_data; ++ } ++ //err_cnt[i] = (*(volatile u_long *)(TRGMII_7623_RD_0 + i*8) >> 8) & 0x0000000f; // Read MT7623 Errcnt ++ ++ } ++ //printk("%dth bit Tap_a = %d\n", i, tap_a[i]); ++ } ++ //printk("Last While Loop\n"); ++ for (i = 0 ; i<5 ; i++) { ++ //printk(" Bit%d\n", i); ++ rd_tap =0; ++ while ((err_cnt[i] == 0) && (rd_tap !=128)) { ++ read_data = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8); ++ rd_tap = (read_data & 0x0000007f) + rxd_step_size; // Add RXD delay in MT7623 ++ read_data = (read_data & 0xffffff80) | rd_tap; ++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = read_data; ++ /* Enable EDGE CHK in MT7623*/ ++ tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8); ++ tmp |= 0x40000000; ++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff; ++ wait_loop(); ++ err_cnt[i] = ((*(volatile u_long *)(TRGMII_7623_RD_0 + i*8)) >> 8) & 0x0000000f; // Read MT7623 Errcnt ++ /* Disable EDGE CHK in MT7623*/ ++ tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8); ++ tmp |= 0x40000000; ++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff; ++ wait_loop(); ++ //err_cnt[i] = ((*(volatile u_long *)(TRGMII_7623_RD_0 + i*8)) >> 8) & 0x0000000f; // Read MT7623 Errcnt ++ ++ } ++ tap_b[i] = rd_tap;// -rxd_step_size; // Record the max delay TAP_B ++ //printk("tap_b[%d] is %d \n", i,tap_b[i]); ++ final_tap[i] = (tap_a[i]+tap_b[i])/2; // Calculate RXD delay = (TAP_A + TAP_B)/2 ++ //printk("%dth bit Final Tap = %d\n", i, final_tap[i]); ++ read_data = (read_data & 0xffffff80) | final_tap[i]; ++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = read_data; ++ } ++// /*word alignment*/ ++// mii_mgr_read(0x1F,0x7A50,&read_data); ++// read_data &= ~(0xff); ++// read_data |= 0xac; ++// mii_mgr_write(0x1F,0x7A50,read_data); ++// while (i <10) { ++// i++; ++// wait_loop(); ++// } ++// /* Enable EDGE CHK in MT7623*/ ++// for (i=0; i<5; i++) { ++// tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8); ++// tmp |= 0x40000000; ++// *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff; ++// wait_loop(); ++// /* Disable EDGE CHK in MT7623*/ ++// tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8); ++// tmp |= 0x40000000; ++// *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff; ++// wait_loop(); ++// read_data = *(volatile u_long *)(TRGMII_7623_RD_0+i*8); ++// printk(" MT7623 training word = %x\n", read_data); ++// } ++ ++ ++ mii_mgr_read(0x1F,0x7A40,&read_data); ++ //printk(" MT7530 0x7A40 = %x\n", read_data); ++ read_data &=0x3fffffff; ++ mii_mgr_write(0x1F,0x7A40,read_data); ++} ++ ++ ++void trgmii_calibration_7530(void){ ++ ++ unsigned int tap_a[5]; ++ unsigned int tap_b[5]; ++ unsigned int final_tap[5]; ++ unsigned int bslip_en; ++ unsigned int rxc_step_size; ++ unsigned int rxd_step_size; ++ unsigned int read_data; ++ unsigned int tmp; ++ int i,j; ++ unsigned int err_cnt[5]; ++ unsigned int rd_wd; ++ unsigned int init_toggle_data; ++ unsigned int err_flag[5]; ++ unsigned int err_total_flag; ++ unsigned int training_word; ++ unsigned int rd_tap; ++ ++ u32 TRGMII_7623_base; ++ u32 TRGMII_7530_RD_0; ++ u32 TRGMII_RD_1; ++ u32 TRGMII_RD_2; ++ u32 TRGMII_RD_3; ++ u32 TRGMII_RXCTL; ++ u32 TRGMII_RCK_CTRL; ++ u32 TRGMII_7530_base; ++ u32 TRGMII_7530_TX_base; ++ TRGMII_7623_base = 0xFB110300; ++ TRGMII_7530_base = 0x7A00; ++ TRGMII_7530_RD_0 = TRGMII_7530_base + 0x10; ++ TRGMII_RCK_CTRL = TRGMII_7623_base; ++ rxd_step_size = 0x1; ++ rxc_step_size = 0x8; ++ init_toggle_data = 0x00000055; ++ training_word = 0x000000AC; ++ ++ TRGMII_7530_TX_base = TRGMII_7530_base + 0x50; ++ ++ //printk("Calibration begin ........\n"); ++ *(volatile u_long *)(TRGMII_7623_base + 0x40) |= 0x80000000; ++ mii_mgr_read(0x1F, 0x7a10, &read_data); ++ //printk("TRGMII_7530_RD_0 is %x\n", read_data); ++ ++ mii_mgr_read(0x1F,TRGMII_7530_base+0x04,&read_data); ++ read_data &= 0x3fffffff; ++ mii_mgr_write(0x1F,TRGMII_7530_base+0x04,read_data); // RX clock gating in MT7530 ++ ++ mii_mgr_read(0x1F,TRGMII_7530_base+0x78,&read_data); ++ read_data |= 0x00002000; ++ mii_mgr_write(0x1F,TRGMII_7530_base+0x78,read_data); // Set TX OE edge in MT7530 ++ ++ mii_mgr_read(0x1F,TRGMII_7530_base,&read_data); ++ read_data |= 0x80000000; ++ mii_mgr_write(0x1F,TRGMII_7530_base,read_data); // Assert RX reset in MT7530 ++ ++ ++ mii_mgr_read(0x1F,TRGMII_7530_base,&read_data); ++ read_data &= 0x7fffffff; ++ mii_mgr_write(0x1F,TRGMII_7530_base,read_data); // Release RX reset in MT7530 ++ ++ mii_mgr_read(0x1F,TRGMII_7530_base+0x04,&read_data); ++ read_data |= 0xC0000000; ++ mii_mgr_write(0x1F,TRGMII_7530_base+0x04,read_data); // Disable RX clock gating in MT7530 ++ ++ //printk("Enable Training Mode in MT7623\n"); ++ /*Enable Training Mode in MT7623*/ ++ *(volatile u_long *)(TRGMII_7623_base + 0x40) &= 0xbfffffff; ++ *(volatile u_long *)(TRGMII_7623_base + 0x40) |= 0x80000000; ++ *(volatile u_long *)(TRGMII_7623_base + 0x78) &= 0xfffff0ff; ++ *(volatile u_long *)(TRGMII_7623_base + 0x78) |= 0x00000400; ++ ++ err_total_flag =0; ++ //printk("Adjust RXC delay in MT7530\n"); ++ read_data =0x0; ++ while (err_total_flag == 0 && (read_data != 0x68)) { ++ //printk("2nd Enable EDGE CHK in MT7530\n"); ++ /* Enable EDGE CHK in MT7530*/ ++ for (i = 0 ; i<5 ; i++) { ++ mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&read_data); ++ read_data |= 0x40000000; ++ read_data &= 0x4fffffff; ++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data); ++ wait_loop(); ++ //printk("2nd Disable EDGE CHK in MT7530\n"); ++ mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&err_cnt[i]); ++ //printk("***** MT7530 %dth bit ERR_CNT =%x\n",i, err_cnt[i]); ++ //printk("MT7530 %dth bit ERR_CNT =%x\n",i, err_cnt[i]); ++ err_cnt[i] >>= 8; ++ err_cnt[i] &= 0x0000ff0f; ++ rd_wd = err_cnt[i] >> 8; ++ rd_wd &= 0x000000ff; ++ err_cnt[i] &= 0x0000000f; ++ //mii_mgr_read(0x1F,0x7a10,&read_data); ++ if ( err_cnt[i] !=0 ) { ++ err_flag[i] = 1; ++ } ++ else if (rd_wd != 0x55) { ++ err_flag[i] = 1; ++ } else { ++ err_flag[i] = 0; ++ } ++ if (i==0) { ++ err_total_flag = err_flag[i]; ++ } else { ++ err_total_flag = err_flag[i] & err_total_flag; ++ } ++ /* Disable EDGE CHK in MT7530*/ ++ mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&read_data); ++ read_data |= 0x40000000; ++ read_data &= 0x4fffffff; ++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data); ++ wait_loop(); ++ } ++ /*Adjust RXC delay*/ ++ if (err_total_flag ==0) { ++ mii_mgr_read(0x1F,TRGMII_7530_base,&read_data); ++ read_data |= 0x80000000; ++ mii_mgr_write(0x1F,TRGMII_7530_base,read_data); // Assert RX reset in MT7530 ++ ++ mii_mgr_read(0x1F,TRGMII_7530_base+0x04,&read_data); ++ read_data &= 0x3fffffff; ++ mii_mgr_write(0x1F,TRGMII_7530_base+0x04,read_data); // RX clock gating in MT7530 ++ ++ mii_mgr_read(0x1F,TRGMII_7530_base,&read_data); ++ tmp = read_data; ++ tmp &= 0x0000007f; ++ tmp += rxc_step_size; ++ //printk("Current rxc delay = %d\n", tmp); ++ read_data &= 0xffffff80; ++ read_data |= tmp; ++ mii_mgr_write (0x1F,TRGMII_7530_base,read_data); ++ mii_mgr_read(0x1F,TRGMII_7530_base,&read_data); ++ //printk("Current RXC delay = %x\n", read_data); ++ ++ mii_mgr_read(0x1F,TRGMII_7530_base,&read_data); ++ read_data &= 0x7fffffff; ++ mii_mgr_write(0x1F,TRGMII_7530_base,read_data); // Release RX reset in MT7530 ++ ++ mii_mgr_read(0x1F,TRGMII_7530_base+0x04,&read_data); ++ read_data |= 0xc0000000; ++ mii_mgr_write(0x1F,TRGMII_7530_base+0x04,read_data); // Disable RX clock gating in MT7530 ++ } ++ read_data = tmp; ++ } ++ //printk("RXC delay is %d\n", tmp); ++ //printk("Finish RXC Adjustment while loop\n"); ++ ++ //printk("Read RD_WD MT7530\n"); ++ /* Read RD_WD MT7530*/ ++ for (i = 0 ; i<5 ; i++) { ++ rd_tap = 0; ++ while (err_flag[i] != 0) { ++ /* Enable EDGE CHK in MT7530*/ ++ mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&read_data); ++ read_data |= 0x40000000; ++ read_data &= 0x4fffffff; ++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data); ++ wait_loop(); ++ err_cnt[i] = (read_data >> 8) & 0x0000000f; ++ rd_wd = (read_data >> 16) & 0x000000ff; ++ //printk("##### %dth bit ERR_CNT = %x RD_WD =%x ######\n", i, err_cnt[i],rd_wd); ++ if (err_cnt[i] != 0 || rd_wd !=0x55){ ++ err_flag [i] = 1; ++ } ++ else { ++ err_flag[i] =0; ++ } ++ if (err_flag[i] !=0 ) { ++ rd_tap = (read_data & 0x0000007f) + rxd_step_size; // Add RXD delay in MT7530 ++ read_data = (read_data & 0xffffff80) | rd_tap; ++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data); ++ tap_a[i] = rd_tap; ++ } else { ++ tap_a[i] = (read_data & 0x0000007f); // Record the min delay TAP_A ++ rd_tap = tap_a[i] + 0x4; ++ read_data = (read_data & 0xffffff80) | rd_tap ; ++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data); ++ } ++ ++ /* Disable EDGE CHK in MT7530*/ ++ mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&read_data); ++ read_data |= 0x40000000; ++ read_data &= 0x4fffffff; ++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data); ++ wait_loop(); ++ ++ } ++ //printk("%dth bit Tap_a = %d\n", i, tap_a[i]); ++ } ++ //printk("Last While Loop\n"); ++ for (i = 0 ; i<5 ; i++) { ++ rd_tap =0; ++ while (err_cnt[i] == 0 && (rd_tap!=128)) { ++ /* Enable EDGE CHK in MT7530*/ ++ mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&read_data); ++ read_data |= 0x40000000; ++ read_data &= 0x4fffffff; ++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data); ++ wait_loop(); ++ err_cnt[i] = (read_data >> 8) & 0x0000000f; ++ //rd_tap = (read_data & 0x0000007f) + 0x4; // Add RXD delay in MT7530 ++ if (err_cnt[i] == 0 && (rd_tap!=128)) { ++ rd_tap = (read_data & 0x0000007f) + rxd_step_size; // Add RXD delay in MT7530 ++ read_data = (read_data & 0xffffff80) | rd_tap; ++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data); ++ } ++ /* Disable EDGE CHK in MT7530*/ ++ mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&read_data); ++ read_data |= 0x40000000; ++ read_data &= 0x4fffffff; ++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data); ++ wait_loop(); ++ } ++ tap_b[i] = rd_tap;// - rxd_step_size; // Record the max delay TAP_B ++ //printk("%dth bit Tap_b = %d, ERR_CNT=%d\n", i, tap_b[i],err_cnt[i]); ++ final_tap[i] = (tap_a[i]+tap_b[i])/2; // Calculate RXD delay = (TAP_A + TAP_B)/2 ++ //printk("%dth bit Final Tap = %d\n", i, final_tap[i]); ++ ++ read_data = ( read_data & 0xffffff80) | final_tap[i]; ++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data); ++ } ++ *(volatile u_long *)(TRGMII_7623_base + 0x40) &=0x3fffffff; ++ ++} ++ ++void set_trgmii_325_delay_setting(void) ++{ ++ /*mt7530 side*/ ++ *(volatile u_long *)(0xfb110300) = 0x80020050; ++ *(volatile u_long *)(0xfb110304) = 0x00980000; ++ *(volatile u_long *)(0xfb110300) = 0x40020050; ++ *(volatile u_long *)(0xfb110304) = 0xc0980000; ++ *(volatile u_long *)(0xfb110310) = 0x00000028; ++ *(volatile u_long *)(0xfb110318) = 0x0000002e; ++ *(volatile u_long *)(0xfb110320) = 0x0000002d; ++ *(volatile u_long *)(0xfb110328) = 0x0000002b; ++ *(volatile u_long *)(0xfb110330) = 0x0000002a; ++ *(volatile u_long *)(0xfb110340) = 0x00020000; ++ /*mt7530 side*/ ++ mii_mgr_write(31, 0x7a00, 0x10); ++ mii_mgr_write(31, 0x7a10, 0x23); ++ mii_mgr_write(31, 0x7a18, 0x27); ++ mii_mgr_write(31, 0x7a20, 0x24); ++ mii_mgr_write(31, 0x7a28, 0x29); ++ mii_mgr_write(31, 0x7a30, 0x24); ++ ++} ++ ++ ++void setup_internal_gsw(void) ++{ ++ u32 i; ++ u32 regValue; ++ u32 xtal_mode; ++ ++ mt7623_pinmux_set(); /* TODO: just for bring up, should be removed!!! */ ++ ++#if 0 ++ /* GE1: RGMII mode setting */ ++ *(volatile u_long *)(0xfb110300) = 0x80020000; ++ *(volatile u_long *)(0xfb110304) = 0x00980000; ++ *(volatile u_long *)(0xfb110300) = 0x40020000; ++ *(volatile u_long *)(0xfb110304) = 0xc0980000; ++ *(volatile u_long *)(0xfb110310) = 0x00000041; ++ *(volatile u_long *)(0xfb110318) = 0x00000044; ++ *(volatile u_long *)(0xfb110320) = 0x00000043; ++ *(volatile u_long *)(0xfb110328) = 0x00000042; ++ *(volatile u_long *)(0xfb110330) = 0x00000042; ++ *(volatile u_long *)(0xfb110340) = 0x00020000; ++ *(volatile u_long *)(0xfb110390) &= 0xfffffff8; //RGMII mode ++#else ++ /* GE1: TRGMII mode setting */ ++ *(volatile u_long *)(0xfb110390) |= 0x00000002; //TRGMII mode ++#endif ++ ++ /*Todo: Hardware reset Switch*/ ++ /*Hardware reset Switch*/ ++#if defined(CONFIG_ARCH_MT7623) ++ regValue = *(volatile u_long *)(0xfb00000c); ++ /*MT7530 Reset. Flows for MT7623 and MT7683 are both excuted.*/ ++ /* Should Modify this section if EFUSE is ready*/ ++ /*For MT7683 reset MT7530*/ ++ if(!(regValue & (1<<16))) ++ { ++ *(volatile u_long *)(0xf0005520) &= ~(1<<1); ++ udelay(1000); ++ *(volatile u_long *)(0xf0005520) |= (1<<1); ++ mdelay(100); ++ } ++ //printk("Assert MT7623 RXC reset\n"); ++ *(volatile u_long *)(0xfb110300) |= 0x80000000; // Assert MT7623 RXC reset ++ /*For MT7623 reset MT7530*/ ++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x34) |= (0x1 << 2); ++ udelay(1000); ++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x34) &= ~(0x1 << 2); ++ mdelay(100); ++#endif ++ ++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600) ++ for(i=0;i<=4;i++) ++ { ++ //turn off PHY ++ mii_mgr_read(i, 0x0 ,®Value); ++ regValue |= (0x1<<11); ++ mii_mgr_write(i, 0x0, regValue); ++ } ++ mii_mgr_write(31, 0x7000, 0x3); //reset switch ++ udelay(100); ++ ++#if defined (CONFIG_MT7621_ASIC) || defined (CONFIG_ARCH_MT7623) ++#if 0 ++ if((sysRegRead(0xbe00000c)&0xFFFF)==0x0101) { ++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2105e30b);//(GE1, Force 1000M/FD, FC ON) ++ mii_mgr_write(31, 0x3600, 0x5e30b); ++ } else ++#endif ++ { ++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2105e33b);//(GE1, Force 1000M/FD, FC ON) ++ mii_mgr_write(31, 0x3600, 0x5e33b); ++ mii_mgr_read(31, 0x3600 ,®Value); ++ } ++#endif ++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x00008000);//(GE2, Link down) ++#endif ++ ++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600) ++ //regValue = 0x117ccf; //Enable Port 6, P5 as GMAC5, P5 disable*/ ++ mii_mgr_read(31, 0x7804 ,®Value); ++ regValue &= ~(1<<8); //Enable Port 6 ++ regValue |= (1<<6); //Disable Port 5 ++ regValue |= (1<<13); //Port 5 as GMAC, no Internal PHY ++ ++#if defined (CONFIG_RAETH_GMAC2) ++ //RGMII2=Normal mode ++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15); ++ ++ //GMAC2= RGMII mode ++ *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14); ++ mii_mgr_write(31, 0x3500, 0x56300); //MT7530 P5 AN, we can ignore this setting?????? ++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x21056300);//(GE2, auto-polling) ++ enable_auto_negotiate(0);//set polling address ++ ++ /* set MT7530 Port 5 to PHY 0/4 mode */ ++#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN) ++ regValue &= ~((1<<13)|(1<<6)); ++ regValue |= ((1<<7)|(1<<16)|(1<<20)); ++#elif defined (CONFIG_GE_RGMII_INTERNAL_P4_AN) ++ regValue &= ~((1<<13)|(1<<6)|(1<<20)); ++ regValue |= ((1<<7)|(1<<16)); ++#endif ++ /*Set MT7530 phy direct access mode**/ ++ regValue &= ~(1<<5); ++ ++ //sysRegWrite(GDMA2_FWD_CFG, 0x20710000); ++#endif ++ regValue |= (1<<16);//change HW-TRAP ++ printk("change HW-TRAP to 0x%x\n",regValue); ++ mii_mgr_write(31, 0x7804 ,regValue); ++#endif ++ mii_mgr_read(31, 0x7800, ®Value); ++ regValue = (regValue >> 9) & 0x3; ++ if(regValue == 0x3)//25Mhz Xtal ++ xtal_mode = 1; ++ else if(regValue == 0x2) //40Mhz ++ xtal_mode = 2; ++ else ++ xtal_mode = 3; ++ ++ if(xtal_mode == 1) { //25Mhz Xtal ++ /* do nothing */ ++ } else if(xtal_mode = 2) { //40Mhz ++ mii_mgr_write(0, 13, 0x1f); // disable MT7530 core clock ++ mii_mgr_write(0, 14, 0x410); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0x0); ++ ++ mii_mgr_write(0, 13, 0x1f); // disable MT7530 PLL ++ mii_mgr_write(0, 14, 0x40d); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0x2020); ++ ++ mii_mgr_write(0, 13, 0x1f); // for MT7530 core clock = 500Mhz ++ mii_mgr_write(0, 14, 0x40e); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0x119); ++ ++ mii_mgr_write(0, 13, 0x1f); // enable MT7530 PLL ++ mii_mgr_write(0, 14, 0x40d); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0x2820); ++ ++ udelay(20); //suggest by CD ++ ++ mii_mgr_write(0, 13, 0x1f); // enable MT7530 core clock ++ mii_mgr_write(0, 14, 0x410); ++ mii_mgr_write(0, 13, 0x401f); ++ }else {//20MHz ++ /*TODO*/ ++ } ++ ++#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC) ++ mii_mgr_write(0, 14, 0x3); /*TRGMII*/ ++#else ++ mii_mgr_write(0, 14, 0x1); /*RGMII*/ ++/* set MT7530 central align */ ++ mii_mgr_read(31, 0x7830, ®Value); ++ regValue &= ~1; ++ regValue |= 1<<1; ++ mii_mgr_write(31, 0x7830, regValue); ++ ++ mii_mgr_read(31, 0x7a40, ®Value); ++ regValue &= ~(1<<30); ++ mii_mgr_write(31, 0x7a40, regValue); ++ ++ regValue = 0x855; ++ mii_mgr_write(31, 0x7a78, regValue); ++ ++#endif ++ mii_mgr_write(31, 0x7b00, 0x104); //delay setting for 10/1000M ++ mii_mgr_write(31, 0x7b04, 0x10); //delay setting for 10/1000M ++ ++ /*Tx Driving*/ ++ mii_mgr_write(31, 0x7a54, 0x88); //lower GE1 driving ++ mii_mgr_write(31, 0x7a5c, 0x88); //lower GE1 driving ++ mii_mgr_write(31, 0x7a64, 0x88); //lower GE1 driving ++ mii_mgr_write(31, 0x7a6c, 0x88); //lower GE1 driving ++ mii_mgr_write(31, 0x7a74, 0x88); //lower GE1 driving ++ mii_mgr_write(31, 0x7a7c, 0x88); //lower GE1 driving ++ mii_mgr_write(31, 0x7810, 0x11); //lower GE2 driving ++ /*Set MT7623/MT7683 TX Driving*/ ++ *(volatile u_long *)(0xfb110354) = 0x88; ++ *(volatile u_long *)(0xfb11035c) = 0x88; ++ *(volatile u_long *)(0xfb110364) = 0x88; ++ *(volatile u_long *)(0xfb11036c) = 0x88; ++ *(volatile u_long *)(0xfb110374) = 0x88; ++ *(volatile u_long *)(0xfb11037c) = 0x88; ++#if defined (CONFIG_GE2_RGMII_AN) ++ *(volatile u_long *)(0xf0005f00) = 0xe00; //Set GE2 driving and slew rate ++#else ++ *(volatile u_long *)(0xf0005f00) = 0xa00; //Set GE2 driving and slew rate ++#endif ++ *(volatile u_long *)(0xf00054c0) = 0x5; //set GE2 TDSEL ++ *(volatile u_long *)(0xf0005ed0) = 0; //set GE2 TUNE ++ ++ /* TRGMII Clock */ ++// printk("Set TRGMII mode clock stage 1\n"); ++ mii_mgr_write(0, 13, 0x1f); ++ mii_mgr_write(0, 14, 0x404); ++ mii_mgr_write(0, 13, 0x401f); ++ if (xtal_mode == 1){ //25MHz ++#if defined (CONFIG_GE1_TRGMII_FORCE_2900) ++ mii_mgr_write(0, 14, 0x1d00); // 362.5MHz ++#elif defined (CONFIG_GE1_TRGMII_FORCE_2600) ++ mii_mgr_write(0, 14, 0x1a00); // 325MHz ++#elif defined (CONFIG_GE1_TRGMII_FORCE_2000) ++ mii_mgr_write(0, 14, 0x1400); //250MHz ++#elif defined (CONFIG_GE1_RGMII_FORCE_1000) ++ mii_mgr_write(0, 14, 0x00a0); //125MHz ++#endif ++ }else if(xtal_mode == 2){//40MHz ++#if defined (CONFIG_GE1_TRGMII_FORCE_2900) ++ mii_mgr_write(0, 14, 0x1220); // 362.5MHz ++#elif defined (CONFIG_GE1_TRGMII_FORCE_2600) ++ mii_mgr_write(0, 14, 0x1040); // 325MHz ++#elif defined (CONFIG_GE1_TRGMII_FORCE_2000) ++ mii_mgr_write(0, 14, 0x0c80); //250MHz ++#elif defined (CONFIG_GE1_RGMII_FORCE_1000) ++ mii_mgr_write(0, 14, 0x0640); //125MHz ++#endif ++ } ++// printk("Set TRGMII mode clock stage 2\n"); ++ mii_mgr_write(0, 13, 0x1f); ++ mii_mgr_write(0, 14, 0x405); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0x0); ++ ++// printk("Set TRGMII mode clock stage 3\n"); ++ mii_mgr_write(0, 13, 0x1f); ++ mii_mgr_write(0, 14, 0x409); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0x0087); ++ ++// printk("Set TRGMII mode clock stage 4\n"); ++ mii_mgr_write(0, 13, 0x1f); ++ mii_mgr_write(0, 14, 0x40a); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0x0087); ++ ++// printk("Set TRGMII mode clock stage 5\n"); ++ mii_mgr_write(0, 13, 0x1f); ++ mii_mgr_write(0, 14, 0x403); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0x1800); ++ ++// printk("Set TRGMII mode clock stage 6\n"); ++ mii_mgr_write(0, 13, 0x1f); ++ mii_mgr_write(0, 14, 0x403); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0x1c00); ++ ++// printk("Set TRGMII mode clock stage 7\n"); ++ mii_mgr_write(0, 13, 0x1f); ++ mii_mgr_write(0, 14, 0x401); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0xc020); ++ ++// printk("Set TRGMII mode clock stage 8\n"); ++ mii_mgr_write(0, 13, 0x1f); ++ mii_mgr_write(0, 14, 0x406); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0xa030); ++ ++// printk("Set TRGMII mode clock stage 9\n"); ++ mii_mgr_write(0, 13, 0x1f); ++ mii_mgr_write(0, 14, 0x406); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0xa038); ++ ++ udelay(120); // for MT7623 bring up test ++ ++// printk("Set TRGMII mode clock stage 10\n"); ++ mii_mgr_write(0, 13, 0x1f); ++ mii_mgr_write(0, 14, 0x410); ++ mii_mgr_write(0, 13, 0x401f); ++ mii_mgr_write(0, 14, 0x3); ++ ++// printk("Set TRGMII mode clock stage 11\n"); ++ ++ mii_mgr_read(31, 0x7830 ,®Value); ++ regValue &=0xFFFFFFFC; ++ regValue |=0x00000001; ++ mii_mgr_write(31, 0x7830, regValue); ++ ++// printk("Set TRGMII mode clock stage 12\n"); ++ mii_mgr_read(31, 0x7a40 ,®Value); ++ regValue &= ~(0x1<<30); ++ regValue &= ~(0x1<<28); ++ mii_mgr_write(31, 0x7a40, regValue); ++ ++ //mii_mgr_write(31, 0x7a78, 0x855); ++ mii_mgr_write(31, 0x7a78, 0x55); ++// printk(" Adjust MT7530 TXC delay\n"); ++ udelay(100); // for mt7623 bring up test ++ ++// printk(" Release MT7623 RXC Reset\n"); ++ *(volatile u_long *)(0xfb110300) &= 0x7fffffff; // Release MT7623 RXC reset ++ //disable EEE ++ for(i=0;i<=4;i++) ++ { ++ mii_mgr_write(i, 13, 0x7); ++ mii_mgr_write(i, 14, 0x3C); ++ mii_mgr_write(i, 13, 0x4007); ++ mii_mgr_write(i, 14, 0x0); ++ } ++ ++ //Disable EEE 10Base-Te: ++ for(i=0;i<=4;i++) ++ { ++ mii_mgr_write(i, 13, 0x1f); ++ mii_mgr_write(i, 14, 0x027b); ++ mii_mgr_write(i, 13, 0x401f); ++ mii_mgr_write(i, 14, 0x1177); ++ } ++ ++ for(i=0;i<=4;i++) ++ { ++ //turn on PHY ++ mii_mgr_read(i, 0x0 ,®Value); ++ regValue &= ~(0x1<<11); ++ mii_mgr_write(i, 0x0, regValue); ++ } ++ ++ for(i=0;i<=4;i++) { ++ mii_mgr_read(i, 4, ®Value); ++ regValue |= (3<<7); //turn on 100Base-T Advertisement ++ mii_mgr_write(i, 4, regValue); ++ ++ mii_mgr_read(i, 9, ®Value); ++ regValue |= (3<<8); //turn on 1000Base-T Advertisement ++ mii_mgr_write(i, 9, regValue); ++ ++ //restart AN ++ mii_mgr_read(i, 0, ®Value); ++ regValue |= (1 << 9); ++ mii_mgr_write(i, 0, regValue); ++ } ++ ++ mii_mgr_read(31, 0x7808 ,®Value); ++ regValue |= (3<<16); //Enable INTR ++ mii_mgr_write(31, 0x7808 ,regValue); ++} ++ ++void mt7623_ethifsys_init(void) ++{ ++#define TRGPLL_CON0 (0xF0209280) ++#define TRGPLL_CON1 (0xF0209284) ++#define TRGPLL_CON2 (0xF0209288) ++#define TRGPLL_PWR_CON0 (0xF020928C) ++#define ETHPLL_CON0 (0xF0209290) ++#define ETHPLL_CON1 (0xF0209294) ++#define ETHPLL_CON2 (0xF0209298) ++#define ETHPLL_PWR_CON0 (0xF020929C) ++#define ETH_PWR_CON (0xF00062A0) ++#define HIF_PWR_CON (0xF00062A4) ++ ++ u32 temp, pwr_ack_status; ++ /*=========================================================================*/ ++ /* Enable ETHPLL & TRGPLL*/ ++ /*=========================================================================*/ ++ /* xPLL PWR ON*/ ++ temp = sysRegRead(ETHPLL_PWR_CON0); ++ sysRegWrite(ETHPLL_PWR_CON0, temp | 0x1); ++ ++ temp = sysRegRead(TRGPLL_PWR_CON0); ++ sysRegWrite(TRGPLL_PWR_CON0, temp | 0x1); ++ ++ udelay(5); /* wait for xPLL_PWR_ON ready (min delay is 1us)*/ ++ ++ /* xPLL ISO Disable*/ ++ temp = sysRegRead(ETHPLL_PWR_CON0); ++ sysRegWrite(ETHPLL_PWR_CON0, temp & ~0x2); ++ ++ temp = sysRegRead(TRGPLL_PWR_CON0); ++ sysRegWrite(TRGPLL_PWR_CON0, temp & ~0x2); ++ ++ /* xPLL Frequency Set*/ ++ temp = sysRegRead(ETHPLL_CON0); ++ sysRegWrite(ETHPLL_CON0, temp | 0x1); ++#if defined (CONFIG_GE1_TRGMII_FORCE_2900) ++ temp = sysRegRead(TRGPLL_CON0); ++ sysRegWrite(TRGPLL_CON0, temp | 0x1); ++#elif defined (CONFIG_GE1_TRGMII_FORCE_2600) ++ sysRegWrite(TRGPLL_CON1, 0xB2000000); ++ temp = sysRegRead(TRGPLL_CON0); ++ sysRegWrite(TRGPLL_CON0, temp | 0x1); ++#elif defined (CONFIG_GE1_TRGMII_FORCE_2000) ++ sysRegWrite(TRGPLL_CON1, 0xCCEC4EC5); ++ sysRegWrite(TRGPLL_CON0, 0x121); ++#endif ++ udelay(40); /* wait for PLL stable (min delay is 20us)*/ ++ ++ ++ /*=========================================================================*/ ++ /* Power on ETHDMASYS and HIFSYS*/ ++ /*=========================================================================*/ ++ /* Power on ETHDMASYS*/ ++ sysRegWrite(0xF0006000, 0x0b160001); ++ pwr_ack_status = (sysRegRead(ETH_PWR_CON) & 0x0000f000) >> 12; ++ ++ if(pwr_ack_status == 0x0) { ++ printk("ETH already turn on and power on flow will be skipped...\n"); ++ }else { ++ temp = sysRegRead(ETH_PWR_CON) ; ++ sysRegWrite(ETH_PWR_CON, temp | 0x4); /* PWR_ON*/ ++ temp = sysRegRead(ETH_PWR_CON) ; ++ sysRegWrite(ETH_PWR_CON, temp | 0x8); /* PWR_ON_S*/ ++ ++ udelay(5); /* wait power settle time (min delay is 1us)*/ ++ ++ temp = sysRegRead(ETH_PWR_CON) ; ++ sysRegWrite(ETH_PWR_CON, temp & ~0x10); /* PWR_CLK_DIS*/ ++ temp = sysRegRead(ETH_PWR_CON) ; ++ sysRegWrite(ETH_PWR_CON, temp & ~0x2); /* PWR_ISO*/ ++ temp = sysRegRead(ETH_PWR_CON) ; ++ sysRegWrite(ETH_PWR_CON, temp & ~0x100); /* SRAM_PDN 0*/ ++ temp = sysRegRead(ETH_PWR_CON) ; ++ sysRegWrite(ETH_PWR_CON, temp & ~0x200); /* SRAM_PDN 1*/ ++ temp = sysRegRead(ETH_PWR_CON) ; ++ sysRegWrite(ETH_PWR_CON, temp & ~0x400); /* SRAM_PDN 2*/ ++ temp = sysRegRead(ETH_PWR_CON) ; ++ sysRegWrite(ETH_PWR_CON, temp & ~0x800); /* SRAM_PDN 3*/ ++ ++ udelay(5); /* wait SRAM settle time (min delay is 1Us)*/ ++ ++ temp = sysRegRead(ETH_PWR_CON) ; ++ sysRegWrite(ETH_PWR_CON, temp | 0x1); /* PWR_RST_B*/ ++ } ++ ++ /* Power on HIFSYS*/ ++ pwr_ack_status = (sysRegRead(HIF_PWR_CON) & 0x0000f000) >> 12; ++ if(pwr_ack_status == 0x0) { ++ printk("HIF already turn on and power on flow will be skipped...\n"); ++ } ++ else { ++ temp = sysRegRead(HIF_PWR_CON) ; ++ sysRegWrite(HIF_PWR_CON, temp | 0x4); /* PWR_ON*/ ++ temp = sysRegRead(HIF_PWR_CON) ; ++ sysRegWrite(HIF_PWR_CON, temp | 0x8); /* PWR_ON_S*/ ++ ++ udelay(5); /* wait power settle time (min delay is 1us)*/ ++ ++ temp = sysRegRead(HIF_PWR_CON) ; ++ sysRegWrite(HIF_PWR_CON, temp & ~0x10); /* PWR_CLK_DIS*/ ++ temp = sysRegRead(HIF_PWR_CON) ; ++ sysRegWrite(HIF_PWR_CON, temp & ~0x2); /* PWR_ISO*/ ++ temp = sysRegRead(HIF_PWR_CON) ; ++ sysRegWrite(HIF_PWR_CON, temp & ~0x100); /* SRAM_PDN 0*/ ++ temp = sysRegRead(HIF_PWR_CON) ; ++ sysRegWrite(HIF_PWR_CON, temp & ~0x200); /* SRAM_PDN 1*/ ++ temp = sysRegRead(HIF_PWR_CON) ; ++ sysRegWrite(HIF_PWR_CON, temp & ~0x400); /* SRAM_PDN 2*/ ++ temp = sysRegRead(HIF_PWR_CON) ; ++ sysRegWrite(HIF_PWR_CON, temp & ~0x800); /* SRAM_PDN 3*/ ++ ++ udelay(5); /* wait SRAM settle time (min delay is 1Us)*/ ++ ++ temp = sysRegRead(HIF_PWR_CON) ; ++ sysRegWrite(HIF_PWR_CON, temp | 0x1); /* PWR_RST_B*/ ++ } ++ ++ /* Release mt7530 reset */ ++ temp = le32_to_cpu(*(volatile u_long *)(0xfb000034)); ++ temp &= ~(BIT(2)); ++ *(volatile u_long *)(0xfb000034) = temp; ++} ++#endif ++ ++/** ++ * ra2882eth_init - Module Init code ++ * ++ * Called by kernel to register net_device ++ * ++ */ ++ ++static int fe_probe(struct platform_device *pdev) ++{ ++ int ret; ++ struct net_device *dev = alloc_etherdev(sizeof(END_DEVICE)); ++ ++ fe_irq = platform_get_irq(pdev, 0); ++ ++#ifdef CONFIG_RALINK_VISTA_BASIC ++ int sw_id=0; ++ mii_mgr_read(29, 31, &sw_id); ++ is_switch_175c = (sw_id == 0x175c) ? 1:0; ++#endif ++ ++ if (!dev) ++ return -ENOMEM; ++ ++ strcpy(dev->name, DEV_NAME); ++ printk("%s:%s[%d]%d\n", __FILE__, __func__, __LINE__, fe_irq); ++ dev->irq = fe_irq; ++ dev->addr_len = 6; ++ dev->base_addr = RALINK_FRAME_ENGINE_BASE; ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ rather_probe(dev); ++#else ++ dev->init = rather_probe; ++#endif ++ ra2880_setup_dev_fptable(dev); ++ ++ /* net_device structure Init */ ++ ethtool_init(dev); ++ printk("Ralink APSoC Ethernet Driver Initilization. %s %d rx/tx descriptors allocated, mtu = %d!\n", RAETH_VERSION, NUM_RX_DESC, dev->mtu); ++#ifdef CONFIG_RAETH_NAPI ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ printk("NAPI enable, Tx Ring = %d, Rx Ring = %d\n", NUM_TX_DESC, NUM_RX_DESC); ++#else ++ printk("NAPI enable, weight = %d, Tx Ring = %d, Rx Ring = %d\n", dev->weight, NUM_TX_DESC, NUM_RX_DESC); ++#endif ++#endif ++ ++ /* Register net device for the driver */ ++ if ( register_netdev(dev) != 0) { ++ printk(KERN_WARNING " " __FILE__ ": No ethernet port found.\n"); ++ return -ENXIO; ++ } ++ ++ ++#ifdef CONFIG_RAETH_NETLINK ++ csr_netlink_init(); ++#endif ++ ret = debug_proc_init(); ++ ++ dev_raether = dev; ++#ifdef CONFIG_ARCH_MT7623 ++ mt7623_ethifsys_init(); ++#endif ++ return ret; ++} ++ ++ ++ ++ ++ ++ ++ ++void fe_sw_init(void) ++{ ++#if defined (CONFIG_GIGAPHY) || defined (CONFIG_RAETH_ROUTER) || defined (CONFIG_100PHY) ++ unsigned int regValue = 0; ++#endif ++ ++ // Case1: RT288x/RT3883/MT7621 GE1 + GigaPhy ++#if defined (CONFIG_GE1_RGMII_AN) ++ enable_auto_negotiate(1); ++ if (isMarvellGigaPHY(1)) { ++#if defined (CONFIG_RT3883_FPGA) ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, ®Value); ++ regValue &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half) ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, regValue); ++ ++ printk("\n Reset MARVELL phy\n"); ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, ®Value); ++ regValue |= 1<<7; //Add delay to RX_CLK for RXD Outputs ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, regValue); ++ ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, ®Value); ++ regValue |= 1<<15; //PHY Software Reset ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, regValue); ++#elif defined (CONFIG_MT7621_FPGA) || defined (CONFIG_MT7623_FPGA) ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, ®Value); ++ regValue &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half) ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, regValue); ++ ++ /*10Mbps, debug*/ ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, 0x461); ++ ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, ®Value); ++ regValue |= 1<<9; //restart AN ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, regValue); ++#endif ++ ++ } ++ if (isVtssGigaPHY(1)) { ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 1); ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, ®Value); ++ printk("Vitesse phy skew: %x --> ", regValue); ++ regValue |= (0x3<<12); ++ regValue &= ~(0x3<<14); ++ printk("%x\n", regValue); ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, regValue); ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0); ++ } ++#if defined (CONFIG_RALINK_MT7621) ++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x21056300);//(P0, Auto mode) ++#endif ++#endif // CONFIG_GE1_RGMII_AN // ++ ++ // Case2: RT3883/MT7621 GE2 + GigaPhy ++#if defined (CONFIG_GE2_RGMII_AN) ++ enable_auto_negotiate(2); ++ if (isMarvellGigaPHY(2)) { ++#if defined (CONFIG_RT3883_FPGA) ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, ®Value); ++ regValue &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half) ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, regValue); ++ ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, ®Value); ++ regValue |= 1<<7; //Add delay to RX_CLK for RXD Outputs ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, regValue); ++ ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, ®Value); ++ regValue |= 1<<15; //PHY Software Reset ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, regValue); ++#elif defined (CONFIG_MT7621_FPGA) || defined (CONFIG_MT7623_FPGA) ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, ®Value); ++ regValue &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half) ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, regValue); ++ ++ /*10Mbps, debug*/ ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 4, 0x461); ++ ++ ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, ®Value); ++ regValue |= 1<<9; //restart AN ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, regValue); ++#endif ++ ++ } ++ if (isVtssGigaPHY(2)) { ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 1); ++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, ®Value); ++ printk("Vitesse phy skew: %x --> ", regValue); ++ regValue |= (0x3<<12); ++ regValue &= ~(0x3<<14); ++ printk("%x\n", regValue); ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, regValue); ++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 0); ++ } ++#if defined (CONFIG_RALINK_MT7621) ++ //RGMII2=Normal mode ++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15); ++ //GMAC2= RGMII mode ++ *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14); ++ ++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x21056300);//(P1, Auto mode) ++#endif ++#endif // CONFIG_GE2_RGMII_AN // ++ ++ // Case3: RT305x/RT335x/RT6855/RT6855A/MT7620 + EmbeddedSW ++#if defined (CONFIG_RT_3052_ESW) && !defined(CONFIG_RALINK_MT7621) && !defined(CONFIG_ARCH_MT7623) ++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_MT7620) ++ rt_gsw_init(); ++#elif defined(CONFIG_RALINK_RT6855A) ++ rt6855A_gsw_init(); ++#else ++ rt305x_esw_init(); ++#endif ++#endif ++ // Case4: RT288x/RT388x/MT7621 GE1 + Internal GigaSW ++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600) ++#if defined (CONFIG_RALINK_MT7621) ++ setup_internal_gsw(); ++ /*MT7530 Init*/ ++#elif defined (CONFIG_ARCH_MT7623) ++#if defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600) ++ *(volatile u_long *)(0xfb00002c) |= (1<<11); ++#else ++ *(volatile u_long *)(0xfb00002c) &= ~(1<<11); ++#endif ++ setup_internal_gsw(); ++ trgmii_calibration_7623(); ++ trgmii_calibration_7530(); ++ //*(volatile u_long *)(0xfb110300) |= (0x1f << 24); //Just only for 312.5/325MHz ++ *(volatile u_long *)(0xfb110340) = 0x00020000; ++ *(volatile u_long *)(0xfb110304) &= 0x3fffffff; // RX clock gating in MT7623 ++ *(volatile u_long *)(0xfb110300) |= 0x80000000; // Assert RX reset in MT7623 ++ *(volatile u_long *)(0xfb110300 ) &= 0x7fffffff; // Release RX reset in MT7623 ++ *(volatile u_long *)(0xfb110300 +0x04) |= 0xC0000000; // Disable RX clock gating in MT7623 ++/*GE1@125MHz(RGMII mode) TX delay adjustment*/ ++#if defined (CONFIG_GE1_RGMII_FORCE_1000) ++ *(volatile u_long *)(0xfb110350) = 0x55; ++ *(volatile u_long *)(0xfb110358) = 0x55; ++ *(volatile u_long *)(0xfb110360) = 0x55; ++ *(volatile u_long *)(0xfb110368) = 0x55; ++ *(volatile u_long *)(0xfb110370) = 0x55; ++ *(volatile u_long *)(0xfb110378) = 0x855; ++#endif ++ ++ ++#elif defined (CONFIG_MT7623_FPGA) /* Nelson: remove for bring up, should be added!!! */ ++ setup_fpga_gsw(); ++#else ++ sysRegWrite(MDIO_CFG, INIT_VALUE_OF_FORCE_1000_FD); ++#endif ++#endif ++ ++ // Case5: RT388x/MT7621 GE2 + GigaSW ++#if defined (CONFIG_GE2_RGMII_FORCE_1000) ++#if defined (CONFIG_RALINK_MT7621) ++ setup_external_gsw(); ++#else ++ sysRegWrite(MDIO_CFG2, INIT_VALUE_OF_FORCE_1000_FD); ++#endif ++#endif ++ ++ // Case6: RT288x GE1 /RT388x,MT7621 GE1/GE2 + (10/100 Switch or 100PHY) ++#if defined (CONFIG_RAETH_ROUTER) || defined (CONFIG_100PHY) ++ ++ //set GMAC to MII or RvMII mode ++#if defined (CONFIG_RALINK_RT3883) ++ regValue = sysRegRead(SYSCFG1); ++#if defined (CONFIG_GE1_MII_FORCE_100) || defined (CONFIG_GE1_MII_AN) ++ regValue &= ~(0x3 << 12); ++ regValue |= 0x1 << 12; // GE1 MII Mode ++#elif defined (CONFIG_GE1_RVMII_FORCE_100) ++ regValue &= ~(0x3 << 12); ++ regValue |= 0x2 << 12; // GE1 RvMII Mode ++#endif ++ ++#if defined (CONFIG_GE2_MII_FORCE_100) || defined (CONFIG_GE2_MII_AN) ++ regValue &= ~(0x3 << 14); ++ regValue |= 0x1 << 14; // GE2 MII Mode ++#elif defined (CONFIG_GE2_RVMII_FORCE_100) ++ regValue &= ~(0x3 << 14); ++ regValue |= 0x2 << 14; // GE2 RvMII Mode ++#endif ++ sysRegWrite(SYSCFG1, regValue); ++#endif // CONFIG_RALINK_RT3883 // ++ ++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++ ++#if defined (CONFIG_GE1_MII_FORCE_100) ++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x5e337);//(P0, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON) ++#endif ++#if defined (CONFIG_GE2_MII_FORCE_100) ++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x5e337);//(P1, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON) ++#endif ++#if defined (CONFIG_GE1_MII_AN) || defined (CONFIG_GE1_RGMII_AN) ++ enable_auto_negotiate(1); ++#if defined (CONFIG_RALINK_MT7621) ++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x21056300);//(P0, Auto mode) ++#endif ++#endif ++#if defined (CONFIG_GE2_MII_AN) || defined (CONFIG_GE1_RGMII_AN) ++ enable_auto_negotiate(2); ++#if defined (CONFIG_RALINK_MT7621) ++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x21056300);//(P1, Auto mode) ++#endif ++#endif ++ ++#else ++#if defined (CONFIG_GE1_MII_FORCE_100) ++#if defined (CONFIG_RALINK_MT7621) ++#else ++ sysRegWrite(MDIO_CFG, INIT_VALUE_OF_FORCE_100_FD); ++#endif ++#endif ++#if defined (CONFIG_GE2_MII_FORCE_100) ++#if defined (CONFIG_RALINK_MT7621) ++#else ++ sysRegWrite(MDIO_CFG2, INIT_VALUE_OF_FORCE_100_FD); ++#endif ++#endif ++ //add switch configuration here for other switch chips. ++#if defined (CONFIG_GE1_MII_FORCE_100) || defined (CONFIG_GE2_MII_FORCE_100) ++ // IC+ 175x: force IC+ switch cpu port is 100/FD ++ mii_mgr_write(29, 22, 0x8420); ++#endif ++ ++ ++#endif // defined (CONFIG_RAETH_ROUTER) || defined (CONFIG_100PHY) // ++ ++} ++ ++ ++/** ++ * ra2882eth_cleanup_module - Module Exit code ++ * ++ * Cmd 'rmmod' will invode the routine to exit the module ++ * ++ */ ++#if 0 ++ void ra2882eth_cleanup_module(void) ++{ ++ struct net_device *dev = dev_raether; ++ END_DEVICE *ei_local; ++ ++ ei_local = netdev_priv(dev); ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++ unregister_netdev(ei_local->PseudoDev); ++ free_netdev(ei_local->PseudoDev); ++#endif ++ unregister_netdev(dev); ++ RAETH_PRINT("Free ei_local and unregister netdev...\n"); ++ ++ free_netdev(dev); ++ debug_proc_exit(); ++#ifdef CONFIG_RAETH_NETLINK ++ csr_netlink_end(); ++#endif ++} ++#endif ++EXPORT_SYMBOL(set_fe_dma_glo_cfg); ++//module_init(ra2882eth_init); ++//module_exit(ra2882eth_cleanup_module); ++ ++const struct of_device_id of_fe_match[] = { ++ { .compatible = "mediatek,mt7623-net", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, of_fe_match); ++ ++static struct platform_driver fe_driver = { ++ .probe = fe_probe, ++// .remove = ra2882eth_cleanup_module, ++ .driver = { ++ .name = "ralink_soc_eth", ++ .owner = THIS_MODULE, ++ .of_match_table = of_fe_match, ++ }, ++}; ++ ++static int __init init_rtfe(void) ++{ ++ int ret; ++ ret = platform_driver_register(&fe_driver); ++ return ret; ++} ++ ++static void __exit exit_rtfe(void) ++{ ++ platform_driver_unregister(&fe_driver); ++} ++ ++module_init(init_rtfe); ++module_exit(exit_rtfe); ++ ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/net/ethernet/raeth/raether.h b/drivers/net/ethernet/raeth/raether.h +new file mode 100644 +index 0000000..7a97109 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/raether.h +@@ -0,0 +1,126 @@ ++#ifndef RA2882ETHEND_H ++#define RA2882ETHEND_H ++ ++#ifdef DSP_VIA_NONCACHEABLE ++#define ESRAM_BASE 0xa0800000 /* 0x0080-0000 ~ 0x00807FFF */ ++#else ++#define ESRAM_BASE 0x80800000 /* 0x0080-0000 ~ 0x00807FFF */ ++#endif ++ ++#define RX_RING_BASE ((int)(ESRAM_BASE + 0x7000)) ++#define TX_RING_BASE ((int)(ESRAM_BASE + 0x7800)) ++ ++#if defined(CONFIG_RALINK_RT2880) ++#define NUM_TX_RINGS 1 ++#else ++#define NUM_TX_RINGS 4 ++#endif ++#ifdef MEMORY_OPTIMIZATION ++#ifdef CONFIG_RAETH_ROUTER ++#define NUM_RX_DESC 32 //128 ++#define NUM_TX_DESC 32 //128 ++#elif CONFIG_RT_3052_ESW ++#define NUM_RX_DESC 16 //64 ++#define NUM_TX_DESC 16 //64 ++#else ++#define NUM_RX_DESC 32 //128 ++#define NUM_TX_DESC 32 //128 ++#endif ++//#define NUM_RX_MAX_PROCESS 32 ++#define NUM_RX_MAX_PROCESS 32 ++#else ++#if defined (CONFIG_RAETH_ROUTER) ++#define NUM_RX_DESC 256 ++#define NUM_TX_DESC 256 ++#elif defined (CONFIG_RT_3052_ESW) ++#if defined (CONFIG_RALINK_MT7621) ++#define NUM_RX_DESC 512 ++#define NUM_QRX_DESC 16 ++#define NUM_TX_DESC 512 ++#else ++#define NUM_RX_DESC 256 ++#define NUM_QRX_DESC NUM_RX_DESC ++#define NUM_TX_DESC 256 ++#endif ++#else ++#define NUM_RX_DESC 256 ++#define NUM_QRX_DESC NUM_RX_DESC ++#define NUM_TX_DESC 256 ++#endif ++#if defined(CONFIG_RALINK_RT3883) || defined(CONFIG_RALINK_MT7620) ++#define NUM_RX_MAX_PROCESS 2 ++#else ++#define NUM_RX_MAX_PROCESS 16 ++#endif ++#endif ++#define NUM_LRO_RX_DESC 16 ++ ++#if defined (CONFIG_SUPPORT_OPENWRT) ++#define DEV_NAME "eth0" ++#define DEV2_NAME "eth1" ++#else ++#define DEV_NAME "eth2" ++#define DEV2_NAME "eth3" ++#endif ++ ++#if defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7621) ++#define GMAC0_OFFSET 0xE000 ++#define GMAC2_OFFSET 0xE006 ++#else ++#define GMAC0_OFFSET 0x28 ++#define GMAC2_OFFSET 0x22 ++#endif ++ ++#if defined(CONFIG_RALINK_RT6855A) ++#define IRQ_ENET0 22 ++#elif defined(CONFIG_ARCH_MT7623) ++#define IRQ_ENET0 232 ++#else ++#define IRQ_ENET0 3 /* hardware interrupt #3, defined in RT2880 Soc Design Spec Rev 0.03, pp43 */ ++#endif ++ ++#if defined (CONFIG_RAETH_HW_LRO) ++#define HW_LRO_TIMER_UNIT 1 ++#define HW_LRO_REFRESH_TIME 50000 ++#define HW_LRO_MAX_AGG_CNT 64 ++#define HW_LRO_AGG_DELTA 1 ++#if defined(CONFIG_RAETH_PDMA_DVT) ++#define MAX_LRO_RX_LENGTH 10240 ++#else ++#define MAX_LRO_RX_LENGTH (PAGE_SIZE - SKB_DATA_ALIGN(NET_SKB_PAD + sizeof(struct skb_shared_info))) ++#endif ++#define HW_LRO_AGG_TIME 10 /* 200us */ ++#define HW_LRO_AGE_TIME 50 ++#define HW_LRO_BW_THRE 3000 ++#define HW_LRO_PKT_INT_ALPHA 100 ++#endif /* CONFIG_RAETH_HW_LRO */ ++#define FE_INT_STATUS_REG (*(volatile unsigned long *)(FE_INT_STATUS)) ++#define FE_INT_STATUS_CLEAN(reg) (*(volatile unsigned long *)(FE_INT_STATUS)) = reg ++ ++//#define RAETH_DEBUG ++#ifdef RAETH_DEBUG ++#define RAETH_PRINT(fmt, args...) printk(KERN_INFO fmt, ## args) ++#else ++#define RAETH_PRINT(fmt, args...) { } ++#endif ++ ++struct net_device_stats *ra_get_stats(struct net_device *dev); ++ ++void ei_tx_timeout(struct net_device *dev); ++int rather_probe(struct net_device *dev); ++int ei_open(struct net_device *dev); ++int ei_close(struct net_device *dev); ++ ++int ra2882eth_init(void); ++void ra2882eth_cleanup_module(void); ++ ++void ei_xmit_housekeeping(unsigned long data); ++ ++u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data); ++u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data); ++u32 mii_mgr_cl45_set_address(u32 port_num, u32 dev_addr, u32 reg_addr); ++u32 mii_mgr_read_cl45(u32 port_num, u32 dev_addr, u32 reg_addr, u32 *read_data); ++u32 mii_mgr_write_cl45(u32 port_num, u32 dev_addr, u32 reg_addr, u32 write_data); ++void fe_sw_init(void); ++ ++#endif +diff --git a/drivers/net/ethernet/raeth/raether_hwlro.c b/drivers/net/ethernet/raeth/raether_hwlro.c +new file mode 100755 +index 0000000..5fc4f36 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/raether_hwlro.c +@@ -0,0 +1,347 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "ra2882ethreg.h" ++#include "raether.h" ++#include "ra_mac.h" ++#include "ra_ioctl.h" ++#include "ra_rfrw.h" ++ ++#if defined(CONFIG_RAETH_HW_LRO_FORCE) ++int set_fe_lro_ring1_cfg(struct net_device *dev) ++{ ++ unsigned int ip; ++ ++ netdev_printk(KERN_CRIT, dev, "set_fe_lro_ring1_cfg()\n"); ++ ++ /* 1. Set RX ring mode to force port */ ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_FORCE_PORT); ++ ++ /* 2. Configure lro ring */ ++ /* 2.1 set src/destination TCP ports */ ++ SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING1, 1122); ++ SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING1, 3344); ++ /* 2.2 set src/destination IPs */ ++ str_to_ip(&ip, "10.10.10.3"); ++ sysRegWrite(LRO_RX_RING1_SIP_DW0, ip); ++ str_to_ip(&ip, "10.10.10.254"); ++ sysRegWrite(LRO_RX_RING1_DIP_DW0, ip); ++ /* 2.3 IPv4 force port mode */ ++ SET_PDMA_RXRING_IPV4_FORCE_MODE(ADMA_RX_RING1, 1); ++ /* 2.4 IPv6 force port mode */ ++ SET_PDMA_RXRING_IPV6_FORCE_MODE(ADMA_RX_RING1, 1); ++ ++ /* 3. Set Age timer: 10 msec. */ ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, HW_LRO_AGE_TIME); ++ ++ /* 4. Valid LRO ring */ ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1); ++ ++ return 0; ++} ++ ++int set_fe_lro_ring2_cfg(struct net_device *dev) ++{ ++ unsigned int ip; ++ ++ netdev_printk(KERN_CRIT, dev, "set_fe_lro_ring2_cfg()\n"); ++ ++ /* 1. Set RX ring mode to force port */ ++ SET_PDMA_RXRING2_MODE(PDMA_RX_FORCE_PORT); ++ ++ /* 2. Configure lro ring */ ++ /* 2.1 set src/destination TCP ports */ ++ SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING2, 5566); ++ SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING2, 7788); ++ /* 2.2 set src/destination IPs */ ++ str_to_ip(&ip, "10.10.10.3"); ++ sysRegWrite(LRO_RX_RING2_SIP_DW0, ip); ++ str_to_ip(&ip, "10.10.10.254"); ++ sysRegWrite(LRO_RX_RING2_DIP_DW0, ip); ++ /* 2.3 IPv4 force port mode */ ++ SET_PDMA_RXRING_IPV4_FORCE_MODE(ADMA_RX_RING2, 1); ++ /* 2.4 IPv6 force port mode */ ++ SET_PDMA_RXRING_IPV6_FORCE_MODE(ADMA_RX_RING2, 1); ++ ++ /* 3. Set Age timer: 10 msec. */ ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, HW_LRO_AGE_TIME); ++ ++ /* 4. Valid LRO ring */ ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 1); ++ ++ return 0; ++} ++ ++int set_fe_lro_ring3_cfg(struct net_device *dev) ++{ ++ unsigned int ip; ++ ++ netdev_printk(KERN_CRIT, dev, "set_fe_lro_ring3_cfg()\n"); ++ ++ /* 1. Set RX ring mode to force port */ ++ SET_PDMA_RXRING3_MODE(PDMA_RX_FORCE_PORT); ++ ++ /* 2. Configure lro ring */ ++ /* 2.1 set src/destination TCP ports */ ++ SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING3, 9900); ++ SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING3, 99); ++ /* 2.2 set src/destination IPs */ ++ str_to_ip(&ip, "10.10.10.3"); ++ sysRegWrite(LRO_RX_RING3_SIP_DW0, ip); ++ str_to_ip(&ip, "10.10.10.254"); ++ sysRegWrite(LRO_RX_RING3_DIP_DW0, ip); ++ /* 2.3 IPv4 force port mode */ ++ SET_PDMA_RXRING_IPV4_FORCE_MODE(ADMA_RX_RING3, 1); ++ /* 2.4 IPv6 force port mode */ ++ SET_PDMA_RXRING_IPV6_FORCE_MODE(ADMA_RX_RING3, 1); ++ ++ /* 3. Set Age timer: 10 msec. */ ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, HW_LRO_AGE_TIME); ++ ++ /* 4. Valid LRO ring */ ++ SET_PDMA_RXRING3_VALID(1); ++ ++ return 0; ++} ++ ++int set_fe_lro_glo_cfg(struct net_device *dev) ++{ ++ unsigned int regVal = 0; ++ ++ netdev_printk(KERN_CRIT, dev, "set_fe_lro_glo_cfg()\n"); ++ ++ /* 1 Set max AGG timer: 10 msec. */ ++ SET_PDMA_LRO_MAX_AGG_TIME(HW_LRO_AGG_TIME); ++ ++ /* 2. Set max LRO agg count */ ++ SET_PDMA_LRO_MAX_AGG_CNT(HW_LRO_MAX_AGG_CNT); ++ ++ /* PDMA prefetch enable setting */ ++ SET_PDMA_LRO_RXD_PREFETCH_EN(0x3); ++ ++ /* 2.1 IPv4 checksum update enable */ ++ SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1); ++ ++ /* 3. Polling relinguish */ ++ while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) ++ ; ++ ++ /* 4. Enable LRO */ ++ regVal = sysRegRead(ADMA_LRO_CTRL_DW0); ++ regVal |= PDMA_LRO_EN; ++ sysRegWrite(ADMA_LRO_CTRL_DW0, regVal); ++ ++ return 0; ++} ++#else ++int set_fe_lro_auto_cfg(struct net_device *dev) ++{ ++ unsigned int regVal = 0; ++ unsigned int ip; ++ ++ netdev_printk(KERN_CRIT, dev, "set_fe_lro_auto_cfg()\n"); ++ ++ /* 1.1 Set my IP_1 */ ++ str_to_ip(&ip, "10.10.10.254"); ++ sysRegWrite(LRO_RX_RING0_DIP_DW0, ip); ++ sysRegWrite(LRO_RX_RING0_DIP_DW1, 0); ++ sysRegWrite(LRO_RX_RING0_DIP_DW2, 0); ++ sysRegWrite(LRO_RX_RING0_DIP_DW3, 0); ++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING0, 1); ++ ++ /* 1.2 Set my IP_2 */ ++ str_to_ip(&ip, "10.10.20.254"); ++ sysRegWrite(LRO_RX_RING1_DIP_DW0, ip); ++ sysRegWrite(LRO_RX_RING1_DIP_DW1, 0); ++ sysRegWrite(LRO_RX_RING1_DIP_DW2, 0); ++ sysRegWrite(LRO_RX_RING1_DIP_DW3, 0); ++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING1, 1); ++ ++ /* 1.3 Set my IP_3 */ ++ sysRegWrite(LRO_RX_RING2_DIP_DW3, 0x20010238); ++ sysRegWrite(LRO_RX_RING2_DIP_DW2, 0x08000000); ++ sysRegWrite(LRO_RX_RING2_DIP_DW1, 0x00000000); ++ sysRegWrite(LRO_RX_RING2_DIP_DW0, 0x00000254); ++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING2, 1); ++ ++ /* 1.4 Set my IP_4 */ ++ sysRegWrite(LRO_RX_RING3_DIP_DW3, 0x20010238); ++ sysRegWrite(LRO_RX_RING3_DIP_DW2, 0x08010000); ++ sysRegWrite(LRO_RX_RING3_DIP_DW1, 0x00000000); ++ sysRegWrite(LRO_RX_RING3_DIP_DW0, 0x00000254); ++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING3, 1); ++ ++ /* 2.1 Set RX ring1~3 to auto-learn modes */ ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_AUTO_LEARN); ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_AUTO_LEARN); ++ SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_AUTO_LEARN); ++ ++ /* 2.2 Valid LRO ring */ ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING0, 1); ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1); ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 1); ++ SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 1); ++ ++ /* 2.3 Set AGE timer */ ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, HW_LRO_AGE_TIME); ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, HW_LRO_AGE_TIME); ++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, HW_LRO_AGE_TIME); ++ ++ /* 2.4 Set max AGG timer */ ++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING1, HW_LRO_AGG_TIME); ++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING2, HW_LRO_AGG_TIME); ++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING3, HW_LRO_AGG_TIME); ++ ++ /* 2.5 Set max LRO agg count */ ++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING1, HW_LRO_MAX_AGG_CNT); ++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING2, HW_LRO_MAX_AGG_CNT); ++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING3, HW_LRO_MAX_AGG_CNT); ++ ++ /* 3.0 IPv6 LRO enable */ ++ SET_PDMA_LRO_IPV6_EN(1); ++ ++ /* 3.1 IPv4 checksum update enable */ ++ SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1); ++ ++ /* 3.2 TCP push option check disable */ ++ //SET_PDMA_LRO_IPV4_CTRL_PUSH_EN(0); ++ ++ /* PDMA prefetch enable setting */ ++ SET_PDMA_LRO_RXD_PREFETCH_EN(0x3); ++ ++ /* 3.2 switch priority comparison to byte count mode */ ++/* SET_PDMA_LRO_ALT_SCORE_MODE(PDMA_LRO_ALT_BYTE_CNT_MODE); */ ++ SET_PDMA_LRO_ALT_SCORE_MODE(PDMA_LRO_ALT_PKT_CNT_MODE); ++ ++ /* 3.3 bandwidth threshold setting */ ++ SET_PDMA_LRO_BW_THRESHOLD(HW_LRO_BW_THRE); ++ ++ /* 3.4 auto-learn score delta setting */ ++ sysRegWrite(LRO_ALT_SCORE_DELTA, 0); ++ ++ /* 3.5 Set ALT timer to 20us: (unit: 20us) */ ++ SET_PDMA_LRO_ALT_REFRESH_TIMER_UNIT(HW_LRO_TIMER_UNIT); ++ /* 3.6 Set ALT refresh timer to 1 sec. (unit: 20us) */ ++ SET_PDMA_LRO_ALT_REFRESH_TIMER(HW_LRO_REFRESH_TIME); ++ ++ /* 3.7 the least remaining room of SDL0 in RXD for lro aggregation */ ++ SET_PDMA_LRO_MIN_RXD_SDL(1522); ++ ++ /* 4. Polling relinguish */ ++ while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) ++ ; ++ ++ /* 5. Enable LRO */ ++ regVal = sysRegRead(ADMA_LRO_CTRL_DW0); ++ regVal |= PDMA_LRO_EN; ++ sysRegWrite(ADMA_LRO_CTRL_DW0, regVal); ++ ++ return 0; ++} ++#endif /* CONFIG_RAETH_HW_LRO_FORCE */ ++ ++int fe_hw_lro_init(struct net_device *dev) ++{ ++ int i; ++ END_DEVICE *ei_local = netdev_priv(dev); ++ ++ /* Initial RX Ring 3 */ ++ ei_local->rx_ring3 = ++ pci_alloc_consistent(NULL, NUM_LRO_RX_DESC * sizeof(struct PDMA_rxdesc), ++ &ei_local->phy_rx_ring3); ++ for (i = 0; i < NUM_LRO_RX_DESC; i++) { ++ memset(&ei_local->rx_ring3[i], 0, sizeof(struct PDMA_rxdesc)); ++ ei_local->rx_ring3[i].rxd_info2.DDONE_bit = 0; ++ ei_local->rx_ring3[i].rxd_info2.LS0 = 0; ++ ei_local->rx_ring3[i].rxd_info2.PLEN0 = ++ SET_ADMA_RX_LEN0(MAX_LRO_RX_LENGTH); ++ ei_local->rx_ring3[i].rxd_info2.PLEN1 = ++ SET_ADMA_RX_LEN1(MAX_LRO_RX_LENGTH >> 14); ++ ei_local->rx_ring3[i].rxd_info1.PDP0 = ++ dma_map_single(NULL, ei_local->netrx3_skbuf[i]->data, ++ MAX_LRO_RX_LENGTH, PCI_DMA_FROMDEVICE); ++ } ++ netdev_printk(KERN_CRIT, dev, ++ "\nphy_rx_ring3 = 0x%08x, rx_ring3 = 0x%p\n", ++ ei_local->phy_rx_ring3, ei_local->rx_ring3); ++ /* Initial RX Ring 2 */ ++ ei_local->rx_ring2 = ++ pci_alloc_consistent(NULL, NUM_LRO_RX_DESC * sizeof(struct PDMA_rxdesc), ++ &ei_local->phy_rx_ring2); ++ for (i = 0; i < NUM_LRO_RX_DESC; i++) { ++ memset(&ei_local->rx_ring2[i], 0, sizeof(struct PDMA_rxdesc)); ++ ei_local->rx_ring2[i].rxd_info2.DDONE_bit = 0; ++ ei_local->rx_ring2[i].rxd_info2.LS0 = 0; ++ ei_local->rx_ring2[i].rxd_info2.PLEN0 = ++ SET_ADMA_RX_LEN0(MAX_LRO_RX_LENGTH); ++ ei_local->rx_ring2[i].rxd_info2.PLEN1 = ++ SET_ADMA_RX_LEN1(MAX_LRO_RX_LENGTH >> 14); ++ ei_local->rx_ring2[i].rxd_info1.PDP0 = ++ dma_map_single(NULL, ei_local->netrx2_skbuf[i]->data, ++ MAX_LRO_RX_LENGTH, PCI_DMA_FROMDEVICE); ++ } ++ netdev_printk(KERN_CRIT, dev, ++ "\nphy_rx_ring2 = 0x%08x, rx_ring2 = 0x%p\n", ++ ei_local->phy_rx_ring2, ei_local->rx_ring2); ++ /* Initial RX Ring 1 */ ++ ei_local->rx_ring1 = ++ pci_alloc_consistent(NULL, NUM_LRO_RX_DESC * sizeof(struct PDMA_rxdesc), ++ &ei_local->phy_rx_ring1); ++ for (i = 0; i < NUM_LRO_RX_DESC; i++) { ++ memset(&ei_local->rx_ring1[i], 0, sizeof(struct PDMA_rxdesc)); ++ ei_local->rx_ring1[i].rxd_info2.DDONE_bit = 0; ++ ei_local->rx_ring1[i].rxd_info2.LS0 = 0; ++ ei_local->rx_ring1[i].rxd_info2.PLEN0 = ++ SET_ADMA_RX_LEN0(MAX_LRO_RX_LENGTH); ++ ei_local->rx_ring1[i].rxd_info2.PLEN1 = ++ SET_ADMA_RX_LEN1(MAX_LRO_RX_LENGTH >> 14); ++ ei_local->rx_ring1[i].rxd_info1.PDP0 = ++ dma_map_single(NULL, ei_local->netrx1_skbuf[i]->data, ++ MAX_LRO_RX_LENGTH, PCI_DMA_FROMDEVICE); ++ } ++ netdev_printk(KERN_CRIT, dev, ++ "\nphy_rx_ring1 = 0x%08x, rx_ring1 = 0x%p\n", ++ ei_local->phy_rx_ring1, ei_local->rx_ring1); ++ ++ sysRegWrite(RX_BASE_PTR3, phys_to_bus((u32) ei_local->phy_rx_ring3)); ++ sysRegWrite(RX_MAX_CNT3, cpu_to_le32((u32) NUM_LRO_RX_DESC)); ++ sysRegWrite(RX_CALC_IDX3, cpu_to_le32((u32) (NUM_LRO_RX_DESC - 1))); ++ sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX3); ++ sysRegWrite(RX_BASE_PTR2, phys_to_bus((u32) ei_local->phy_rx_ring2)); ++ sysRegWrite(RX_MAX_CNT2, cpu_to_le32((u32) NUM_LRO_RX_DESC)); ++ sysRegWrite(RX_CALC_IDX2, cpu_to_le32((u32) (NUM_LRO_RX_DESC - 1))); ++ sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX2); ++ sysRegWrite(RX_BASE_PTR1, phys_to_bus((u32) ei_local->phy_rx_ring1)); ++ sysRegWrite(RX_MAX_CNT1, cpu_to_le32((u32) NUM_LRO_RX_DESC)); ++ sysRegWrite(RX_CALC_IDX1, cpu_to_le32((u32) (NUM_LRO_RX_DESC - 1))); ++ sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX1); ++ ++#if defined(CONFIG_RAETH_HW_LRO_FORCE) ++ set_fe_lro_ring1_cfg(dev); ++ set_fe_lro_ring2_cfg(dev); ++ set_fe_lro_ring3_cfg(dev); ++ set_fe_lro_glo_cfg(dev); ++#else ++ set_fe_lro_auto_cfg(dev); ++#endif /* CONFIG_RAETH_HW_LRO_FORCE */ ++ ++ /* HW LRO parameter settings */ ++ ei_local->hw_lro_alpha = HW_LRO_PKT_INT_ALPHA; ++ ei_local->hw_lro_fix_setting = 1; ++ ++ return 1; ++} ++EXPORT_SYMBOL(fe_hw_lro_init); ++ +diff --git a/drivers/net/ethernet/raeth/raether_pdma.c b/drivers/net/ethernet/raeth/raether_pdma.c +new file mode 100755 +index 0000000..4d47ee2 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/raether_pdma.c +@@ -0,0 +1,1121 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if defined (CONFIG_RAETH_TSO) ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#endif ++#if defined (CONFIG_RAETH_LRO) ++#include ++#endif ++#include ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++#include ++#endif ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) ++#include ++#else ++#include ++#endif ++ ++#include "ra2882ethreg.h" ++#include "raether.h" ++#include "ra_mac.h" ++#include "ra_ioctl.h" ++#include "ra_rfrw.h" ++#ifdef CONFIG_RAETH_NETLINK ++#include "ra_netlink.h" ++#endif ++#if defined (CONFIG_RAETH_QOS) ++#include "ra_qos.h" ++#endif ++ ++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) ++#include "../../../net/nat/hw_nat/ra_nat.h" ++#endif ++#if defined(CONFIG_RAETH_PDMA_DVT) ++#include "dvt/raether_pdma_dvt.h" ++#endif /* CONFIG_RAETH_PDMA_DVT */ ++ ++#if !defined(CONFIG_RA_NAT_NONE) ++/* bruce+ ++ */ ++extern int (*ra_sw_nat_hook_rx)(struct sk_buff *skb); ++extern int (*ra_sw_nat_hook_tx)(struct sk_buff *skb, int gmac_no); ++#endif ++ ++#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE) ++/* Qwert+ ++ */ ++#include ++extern int (*ra_classifier_hook_tx)(struct sk_buff *skb, unsigned long cur_cycle); ++extern int (*ra_classifier_hook_rx)(struct sk_buff *skb, unsigned long cur_cycle); ++#endif /* CONFIG_RA_CLASSIFIER */ ++ ++#if defined (CONFIG_RALINK_RT3052_MP2) ++int32_t mcast_rx(struct sk_buff * skb); ++int32_t mcast_tx(struct sk_buff * skb); ++#endif ++ ++#if 0 ++#ifdef RA_MTD_RW_BY_NUM ++int ra_mtd_read(int num, loff_t from, size_t len, u_char *buf); ++#else ++int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf); ++#endif ++#endif ++/* gmac driver feature set config */ ++#if defined (CONFIG_RAETH_NAPI) || defined (CONFIG_RAETH_QOS) ++#undef DELAY_INT ++#else ++#if defined (CONFIG_ARCH_MT7623) ++#undef DELAY_INT ++#else ++#define DELAY_INT 1 ++#endif ++#endif ++ ++//#define CONFIG_UNH_TEST ++/* end of config */ ++ ++#if defined (CONFIG_RAETH_JUMBOFRAME) ++#define MAX_RX_LENGTH 4096 ++#else ++#define MAX_RX_LENGTH 1536 ++#endif ++ ++extern struct net_device *dev_raether; ++ ++ ++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++extern int rx_calc_idx1; ++#endif ++#endif ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++extern int rx_calc_idx0; ++static unsigned long tx_cpu_owner_idx0=0; ++#endif ++extern unsigned long tx_ring_full; ++ ++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/ ++#include "ra_ethtool.h" ++extern struct ethtool_ops ra_ethtool_ops; ++#ifdef CONFIG_PSEUDO_SUPPORT ++extern struct ethtool_ops ra_virt_ethtool_ops; ++#endif // CONFIG_PSEUDO_SUPPORT // ++#endif // (CONFIG_ETHTOOL // ++ ++#ifdef CONFIG_RALINK_VISTA_BASIC ++int is_switch_175c = 1; ++#endif ++ ++#ifdef CONFIG_RAETH_PDMATX_QDMARX /* QDMA RX */ ++struct QDMA_txdesc *free_head = NULL; ++#endif ++ ++//#if defined (CONFIG_RAETH_LRO) ++#if 0 ++unsigned int lan_ip; ++struct lro_para_struct lro_para; ++int lro_flush_needed; ++extern char const *nvram_get(int index, char *name); ++#endif ++ ++#define KSEG1 0xa0000000 ++#define PHYS_TO_VIRT(x) ((void *)((x) | KSEG1)) ++#define VIRT_TO_PHYS(x) ((unsigned long)(x) & ~KSEG1) ++ ++extern void set_fe_dma_glo_cfg(void); ++ ++/* ++ * @brief cal txd number for a page ++ * ++ * @parm size ++ * ++ * @return frag_txd_num ++ */ ++ ++unsigned int cal_frag_txd_num(unsigned int size) ++{ ++ unsigned int frag_txd_num = 0; ++ if(size == 0) ++ return 0; ++ while(size > 0){ ++ if(size > MAX_TXD_LEN){ ++ frag_txd_num++; ++ size -= MAX_TXD_LEN; ++ }else{ ++ frag_txd_num++; ++ size = 0; ++ } ++ } ++ return frag_txd_num; ++ ++} ++ ++#ifdef CONFIG_RAETH_PDMATX_QDMARX /* QDMA RX */ ++bool fq_qdma_init(struct net_device *dev) ++{ ++ END_DEVICE* ei_local = netdev_priv(dev); ++ unsigned int phy_free_head; ++ unsigned int phy_free_tail; ++ unsigned int *free_page_head = NULL; ++ unsigned int phy_free_page_head; ++ int i; ++ ++ free_head = pci_alloc_consistent(NULL, NUM_QDMA_PAGE * sizeof(struct QDMA_txdesc), &phy_free_head); ++ if (unlikely(free_head == NULL)){ ++ printk(KERN_ERR "QDMA FQ decriptor not available...\n"); ++ return 0; ++ } ++ memset(free_head, 0x0, sizeof(struct QDMA_txdesc) * NUM_QDMA_PAGE); ++ ++ free_page_head = pci_alloc_consistent(NULL, NUM_QDMA_PAGE * QDMA_PAGE_SIZE, &phy_free_page_head); ++ if (unlikely(free_page_head == NULL)){ ++ printk(KERN_ERR "QDMA FQ page not available...\n"); ++ return 0; ++ } ++ for (i=0; i < NUM_QDMA_PAGE; i++) { ++ free_head[i].txd_info1.SDP = (phy_free_page_head + (i * QDMA_PAGE_SIZE)); ++ if(i < (NUM_QDMA_PAGE-1)){ ++ free_head[i].txd_info2.NDP = (phy_free_head + ((i+1) * sizeof(struct QDMA_txdesc))); ++ ++ ++#if 0 ++ printk("free_head_phy[%d] is 0x%x!!!\n",i, VIRT_TO_PHYS(&free_head[i]) ); ++ printk("free_head[%d] is 0x%x!!!\n",i, &free_head[i] ); ++ printk("free_head[%d].txd_info1.SDP is 0x%x!!!\n",i, free_head[i].txd_info1.SDP ); ++ printk("free_head[%d].txd_info2.NDP is 0x%x!!!\n",i, free_head[i].txd_info2.NDP ); ++#endif ++ } ++ free_head[i].txd_info3.SDL = QDMA_PAGE_SIZE; ++ ++ } ++ phy_free_tail = (phy_free_head + (u32)((NUM_QDMA_PAGE-1) * sizeof(struct QDMA_txdesc))); ++ ++ printk("phy_free_head is 0x%x!!!\n", phy_free_head); ++ printk("phy_free_tail_phy is 0x%x!!!\n", phy_free_tail); ++ sysRegWrite(QDMA_FQ_HEAD, (u32)phy_free_head); ++ sysRegWrite(QDMA_FQ_TAIL, (u32)phy_free_tail); ++ sysRegWrite(QDMA_FQ_CNT, ((NUM_TX_DESC << 16) | NUM_QDMA_PAGE)); ++ sysRegWrite(QDMA_FQ_BLEN, QDMA_PAGE_SIZE << 16); ++ ++ ei_local->free_head = free_head; ++ ei_local->phy_free_head = phy_free_head; ++ ei_local->free_page_head = free_page_head; ++ ei_local->phy_free_page_head = phy_free_page_head; ++ return 1; ++} ++#endif ++ ++int fe_dma_init(struct net_device *dev) ++{ ++ ++ int i; ++ unsigned int regVal; ++ END_DEVICE* ei_local = netdev_priv(dev); ++#if defined (CONFIG_RAETH_QOS) ++ int j; ++#endif ++ ++ while(1) ++ { ++ regVal = sysRegRead(PDMA_GLO_CFG); ++ if((regVal & RX_DMA_BUSY)) ++ { ++ printk("\n RX_DMA_BUSY !!! "); ++ continue; ++ } ++ if((regVal & TX_DMA_BUSY)) ++ { ++ printk("\n TX_DMA_BUSY !!! "); ++ continue; ++ } ++ break; ++ } ++ ++#if defined(CONFIG_RAETH_PDMA_DVT) ++ pdma_dvt_set_dma_mode(); ++#endif /* CONFIG_RAETH_PDMA_DVT */ ++ ++#if defined (CONFIG_RAETH_QOS) ++ for (i=0;iskb_free[i][j]=0; ++ } ++ ei_local->free_idx[i]=0; ++ } ++ /* ++ * RT2880: 2 x TX_Ring, 1 x Rx_Ring ++ * RT2883: 4 x TX_Ring, 1 x Rx_Ring ++ * RT3883: 4 x TX_Ring, 1 x Rx_Ring ++ * RT3052: 4 x TX_Ring, 1 x Rx_Ring ++ */ ++ fe_tx_desc_init(dev, 0, 3, 1); ++ if (ei_local->tx_ring0 == NULL) { ++ printk("RAETH: tx ring0 allocation failed\n"); ++ return 0; ++ } ++ ++ fe_tx_desc_init(dev, 1, 3, 1); ++ if (ei_local->tx_ring1 == NULL) { ++ printk("RAETH: tx ring1 allocation failed\n"); ++ return 0; ++ } ++ ++ printk("\nphy_tx_ring0 = %08x, tx_ring0 = %p, size: %d bytes\n", ei_local->phy_tx_ring0, ei_local->tx_ring0, sizeof(struct PDMA_txdesc)); ++ ++ printk("\nphy_tx_ring1 = %08x, tx_ring1 = %p, size: %d bytes\n", ei_local->phy_tx_ring1, ei_local->tx_ring1, sizeof(struct PDMA_txdesc)); ++ ++#if ! defined (CONFIG_RALINK_RT2880) ++ fe_tx_desc_init(dev, 2, 3, 1); ++ if (ei_local->tx_ring2 == NULL) { ++ printk("RAETH: tx ring2 allocation failed\n"); ++ return 0; ++ } ++ ++ fe_tx_desc_init(dev, 3, 3, 1); ++ if (ei_local->tx_ring3 == NULL) { ++ printk("RAETH: tx ring3 allocation failed\n"); ++ return 0; ++ } ++ ++ printk("\nphy_tx_ring2 = %08x, tx_ring2 = %p, size: %d bytes\n", ei_local->phy_tx_ring2, ei_local->tx_ring2, sizeof(struct PDMA_txdesc)); ++ ++ printk("\nphy_tx_ring3 = %08x, tx_ring3 = %p, size: %d bytes\n", ei_local->phy_tx_ring3, ei_local->tx_ring3, sizeof(struct PDMA_txdesc)); ++ ++#endif // CONFIG_RALINK_RT2880 // ++#else ++ for (i=0;iskb_free[i]=0; ++ } ++ ei_local->free_idx =0; ++#if defined (CONFIG_MIPS) ++ ei_local->tx_ring0 = pci_alloc_consistent(NULL, NUM_TX_DESC * sizeof(struct PDMA_txdesc), &ei_local->phy_tx_ring0); ++#else ++ ei_local->tx_ring0 = dma_alloc_coherent(NULL, NUM_TX_DESC * sizeof(struct PDMA_txdesc), &ei_local->phy_tx_ring0, GFP_KERNEL); ++#endif ++ printk("\nphy_tx_ring = 0x%08x, tx_ring = 0x%p\n", ei_local->phy_tx_ring0, ei_local->tx_ring0); ++ ++ for (i=0; i < NUM_TX_DESC; i++) { ++ memset(&ei_local->tx_ring0[i],0,sizeof(struct PDMA_txdesc)); ++ ei_local->tx_ring0[i].txd_info2.LS0_bit = 1; ++ ei_local->tx_ring0[i].txd_info2.DDONE_bit = 1; ++ ++ } ++#endif // CONFIG_RAETH_QOS ++ ++#ifdef CONFIG_RAETH_PDMATX_QDMARX /* QDMA RX */ ++ ++ fq_qdma_init(dev); ++ ++ while(1) ++ { ++ regVal = sysRegRead(QDMA_GLO_CFG); ++ if((regVal & RX_DMA_BUSY)) ++ { ++ printk("\n RX_DMA_BUSY !!! "); ++ continue; ++ } ++ if((regVal & TX_DMA_BUSY)) ++ { ++ printk("\n TX_DMA_BUSY !!! "); ++ continue; ++ } ++ break; ++ } ++ ++ /* Initial RX Ring 0*/ ++ ++#ifdef CONFIG_32B_DESC ++ ei_local->qrx_ring = kmalloc(NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL); ++ ei_local->phy_qrx_ring = virt_to_phys(ei_local->qrx_ring); ++#else ++ ei_local->qrx_ring = pci_alloc_consistent(NULL, NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_qrx_ring); ++#endif ++ for (i = 0; i < NUM_QRX_DESC; i++) { ++ memset(&ei_local->qrx_ring[i],0,sizeof(struct PDMA_rxdesc)); ++ ei_local->qrx_ring[i].rxd_info2.DDONE_bit = 0; ++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA) ++ ei_local->qrx_ring[i].rxd_info2.LS0 = 0; ++ ei_local->qrx_ring[i].rxd_info2.PLEN0 = MAX_RX_LENGTH; ++#else ++ ei_local->qrx_ring[i].rxd_info2.LS0 = 1; ++#endif ++ ei_local->qrx_ring[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx0_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE); ++ } ++ printk("\nphy_qrx_ring = 0x%08x, qrx_ring = 0x%p\n",ei_local->phy_qrx_ring,ei_local->qrx_ring); ++ ++ regVal = sysRegRead(QDMA_GLO_CFG); ++ regVal &= 0x000000FF; ++ ++ sysRegWrite(QDMA_GLO_CFG, regVal); ++ regVal=sysRegRead(QDMA_GLO_CFG); ++ ++ /* Tell the adapter where the TX/RX rings are located. */ ++ ++ sysRegWrite(QRX_BASE_PTR_0, phys_to_bus((u32) ei_local->phy_qrx_ring)); ++ sysRegWrite(QRX_MAX_CNT_0, cpu_to_le32((u32) NUM_QRX_DESC)); ++ sysRegWrite(QRX_CRX_IDX_0, cpu_to_le32((u32) (NUM_QRX_DESC - 1))); ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ rx_calc_idx0 = rx_dma_owner_idx0 = sysRegRead(QRX_CRX_IDX_0); ++#endif ++ sysRegWrite(QDMA_RST_CFG, PST_DRX_IDX0); ++ ++ ei_local->rx_ring0 = ei_local->qrx_ring; ++ ++#else /* PDMA RX */ ++ ++ /* Initial RX Ring 0*/ ++#ifdef CONFIG_32B_DESC ++ ei_local->rx_ring0 = kmalloc(NUM_RX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL); ++ ei_local->phy_rx_ring0 = virt_to_phys(ei_local->rx_ring0); ++#else ++#if defined (CONFIG_MIPS) ++ ei_local->rx_ring0 = pci_alloc_consistent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring0); ++#else ++ ei_local->rx_ring0 = dma_alloc_coherent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring0, GFP_KERNEL); ++#endif ++#endif ++ for (i = 0; i < NUM_RX_DESC; i++) { ++ memset(&ei_local->rx_ring0[i],0,sizeof(struct PDMA_rxdesc)); ++ ei_local->rx_ring0[i].rxd_info2.DDONE_bit = 0; ++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA) ++ ei_local->rx_ring0[i].rxd_info2.LS0 = 0; ++ ei_local->rx_ring0[i].rxd_info2.PLEN0 = MAX_RX_LENGTH; ++#else ++ ei_local->rx_ring0[i].rxd_info2.LS0 = 1; ++#endif ++ ei_local->rx_ring0[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx0_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE); ++ } ++ printk("\nphy_rx_ring0 = 0x%08x, rx_ring0 = 0x%p\n",ei_local->phy_rx_ring0,ei_local->rx_ring0); ++ ++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++ /* Initial RX Ring 1*/ ++#ifdef CONFIG_32B_DESC ++ ei_local->rx_ring1 = kmalloc(NUM_RX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL); ++ ei_local->phy_rx_ring1 = virt_to_phys(ei_local->rx_ring1); ++#else ++#if defined (CONFIG_MIPS) ++ ei_local->rx_ring1 = pci_alloc_consistent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring1); ++#else ++ ei_local->rx_ring1 = dma_alloc_coherent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring1, GFP_KERNEL); ++ ++#endif ++#endif ++ for (i = 0; i < NUM_RX_DESC; i++) { ++ memset(&ei_local->rx_ring1[i],0,sizeof(struct PDMA_rxdesc)); ++ ei_local->rx_ring1[i].rxd_info2.DDONE_bit = 0; ++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA) ++ ei_local->rx_ring1[i].rxd_info2.LS0 = 0; ++ ei_local->rx_ring1[i].rxd_info2.PLEN0 = MAX_RX_LENGTH; ++#else ++ ei_local->rx_ring1[i].rxd_info2.LS0 = 1; ++#endif ++ ei_local->rx_ring1[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx1_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE); ++ } ++ printk("\nphy_rx_ring1 = 0x%08x, rx_ring1 = 0x%p\n",ei_local->phy_rx_ring1,ei_local->rx_ring1); ++#if defined(CONFIG_ARCH_MT7623) ++ /* Initial RX Ring 2*/ ++ ei_local->rx_ring2 = pci_alloc_consistent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring2); ++ for (i = 0; i < NUM_RX_DESC; i++) { ++ memset(&ei_local->rx_ring2[i],0,sizeof(struct PDMA_rxdesc)); ++ ei_local->rx_ring2[i].rxd_info2.DDONE_bit = 0; ++ ei_local->rx_ring2[i].rxd_info2.LS0 = 0; ++ ei_local->rx_ring2[i].rxd_info2.PLEN0 = SET_ADMA_RX_LEN0(MAX_RX_LENGTH); ++ ei_local->rx_ring2[i].rxd_info2.PLEN1 = SET_ADMA_RX_LEN1(MAX_RX_LENGTH >> 14); ++ ei_local->rx_ring2[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx2_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE); ++ } ++ printk("\nphy_rx_ring2 = 0x%08x, rx_ring2 = 0x%p\n",ei_local->phy_rx_ring2,ei_local->rx_ring2); ++ /* Initial RX Ring 3*/ ++ ei_local->rx_ring3 = pci_alloc_consistent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring3); ++ for (i = 0; i < NUM_RX_DESC; i++) { ++ memset(&ei_local->rx_ring3[i],0,sizeof(struct PDMA_rxdesc)); ++ ei_local->rx_ring3[i].rxd_info2.DDONE_bit = 0; ++ ei_local->rx_ring3[i].rxd_info2.LS0 = 0; ++ ei_local->rx_ring3[i].rxd_info2.PLEN0 = SET_ADMA_RX_LEN0(MAX_RX_LENGTH); ++ ei_local->rx_ring3[i].rxd_info2.PLEN1 = SET_ADMA_RX_LEN1(MAX_RX_LENGTH >> 14); ++ ei_local->rx_ring3[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx3_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE); ++ } ++ printk("\nphy_rx_ring3 = 0x%08x, rx_ring3 = 0x%p\n",ei_local->phy_rx_ring3,ei_local->rx_ring3); ++#endif /* CONFIG_ARCH_MT7623 */ ++#endif ++ ++#endif ++ ++ regVal = sysRegRead(PDMA_GLO_CFG); ++ regVal &= 0x000000FF; ++ sysRegWrite(PDMA_GLO_CFG, regVal); ++ regVal=sysRegRead(PDMA_GLO_CFG); ++ ++ /* Tell the adapter where the TX/RX rings are located. */ ++#if !defined (CONFIG_RAETH_QOS) ++ sysRegWrite(TX_BASE_PTR0, phys_to_bus((u32) ei_local->phy_tx_ring0)); ++ sysRegWrite(TX_MAX_CNT0, cpu_to_le32((u32) NUM_TX_DESC)); ++ sysRegWrite(TX_CTX_IDX0, 0); ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ tx_cpu_owner_idx0 = 0; ++#endif ++ sysRegWrite(PDMA_RST_CFG, PST_DTX_IDX0); ++#endif ++ ++#ifdef CONFIG_RAETH_PDMATX_QDMARX /* QDMA RX */ ++ sysRegWrite(QRX_BASE_PTR_0, phys_to_bus((u32) ei_local->phy_qrx_ring)); ++ sysRegWrite(QRX_MAX_CNT_0, cpu_to_le32((u32) NUM_QRX_DESC)); ++ sysRegWrite(QRX_CRX_IDX_0, cpu_to_le32((u32) (NUM_QRX_DESC - 1))); ++#else /* PDMA RX */ ++ sysRegWrite(RX_BASE_PTR0, phys_to_bus((u32) ei_local->phy_rx_ring0)); ++ sysRegWrite(RX_MAX_CNT0, cpu_to_le32((u32) NUM_RX_DESC)); ++ sysRegWrite(RX_CALC_IDX0, cpu_to_le32((u32) (NUM_RX_DESC - 1))); ++#endif ++ ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ rx_calc_idx0 = sysRegRead(RX_CALC_IDX0); ++#endif ++ sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX0); ++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++ sysRegWrite(RX_BASE_PTR1, phys_to_bus((u32) ei_local->phy_rx_ring1)); ++ sysRegWrite(RX_MAX_CNT1, cpu_to_le32((u32) NUM_RX_DESC)); ++ sysRegWrite(RX_CALC_IDX1, cpu_to_le32((u32) (NUM_RX_DESC - 1))); ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ rx_calc_idx1 = sysRegRead(RX_CALC_IDX1); ++#endif ++ sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX1); ++#if defined(CONFIG_ARCH_MT7623) ++ sysRegWrite(RX_BASE_PTR2, phys_to_bus((u32) ei_local->phy_rx_ring2)); ++ sysRegWrite(RX_MAX_CNT2, cpu_to_le32((u32) NUM_RX_DESC)); ++ sysRegWrite(RX_CALC_IDX2, cpu_to_le32((u32) (NUM_RX_DESC - 1))); ++ sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX2); ++ sysRegWrite(RX_BASE_PTR3, phys_to_bus((u32) ei_local->phy_rx_ring3)); ++ sysRegWrite(RX_MAX_CNT3, cpu_to_le32((u32) NUM_RX_DESC)); ++ sysRegWrite(RX_CALC_IDX3, cpu_to_le32((u32) (NUM_RX_DESC - 1))); ++ sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX3); ++#endif /* CONFIG_ARCH_MT7623 */ ++#endif ++#if defined (CONFIG_RALINK_RT6855A) ++ regVal = sysRegRead(RX_DRX_IDX0); ++ regVal = (regVal == 0)? (NUM_RX_DESC - 1) : (regVal - 1); ++ sysRegWrite(RX_CALC_IDX0, cpu_to_le32(regVal)); ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ rx_calc_idx0 = sysRegRead(RX_CALC_IDX0); ++#endif ++ regVal = sysRegRead(TX_DTX_IDX0); ++ sysRegWrite(TX_CTX_IDX0, cpu_to_le32(regVal)); ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ tx_cpu_owner_idx0 = regVal; ++#endif ++ ei_local->free_idx = regVal; ++#endif ++ ++#if defined (CONFIG_RAETH_QOS) ++ set_scheduler_weight(); ++ set_schedule_pause_condition(); ++ set_output_shaper(); ++#endif ++ ++ set_fe_dma_glo_cfg(); ++ ++ return 1; ++} ++ ++inline int rt2880_eth_send(struct net_device* dev, struct sk_buff *skb, int gmac_no) ++{ ++ unsigned int length=skb->len; ++ END_DEVICE* ei_local = netdev_priv(dev); ++#ifndef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ unsigned long tx_cpu_owner_idx0 = sysRegRead(TX_CTX_IDX0); ++#endif ++#if defined (CONFIG_RAETH_TSO) ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ unsigned long ctx_idx_start_addr = tx_cpu_owner_idx0; ++#endif ++ struct iphdr *iph = NULL; ++ struct tcphdr *th = NULL; ++ struct skb_frag_struct *frag; ++ unsigned int nr_frags = skb_shinfo(skb)->nr_frags; ++ int i=0; ++ unsigned int len, size, offset, frag_txd_num, skb_txd_num ; ++#endif // CONFIG_RAETH_TSO // ++ ++#if defined (CONFIG_RAETH_TSOV6) ++ struct ipv6hdr *ip6h = NULL; ++#endif ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++ PSEUDO_ADAPTER *pAd; ++#endif ++ ++ while(ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.DDONE_bit == 0) ++ { ++#ifdef CONFIG_PSEUDO_SUPPORT ++ if (gmac_no == 2) { ++ if (ei_local->PseudoDev != NULL) { ++ pAd = netdev_priv(ei_local->PseudoDev); ++ pAd->stat.tx_errors++; ++ } ++ } else ++#endif ++ ei_local->stat.tx_errors++; ++ } ++ ++#if !defined (CONFIG_RAETH_TSO) ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info1.SDP0 = virt_to_phys(skb->data); ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.SDL0 = length; ++#if defined (CONFIG_RALINK_MT7620) ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FP_BMAP = 0; ++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++ if (gmac_no == 1) { ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 1; ++ }else { ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 2; ++ } ++#else ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.PN = gmac_no; ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.QN = 3; ++#endif ++ ++#if defined (CONFIG_RAETH_CHECKSUM_OFFLOAD) && ! defined(CONFIG_RALINK_RT5350) && !defined(CONFIG_RALINK_MT7628) ++ if (skb->ip_summed == CHECKSUM_PARTIAL){ ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TUI_CO = 7; ++ }else { ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TUI_CO = 0; ++ } ++#endif ++ ++#ifdef CONFIG_RAETH_HW_VLAN_TX ++ if(vlan_tx_tag_present(skb)) { ++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0x10000 | vlan_tx_tag_get(skb); ++#else ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VPRI_VIDX = 0x80 | (vlan_tx_tag_get(skb) >> 13) << 4 | (vlan_tx_tag_get(skb) & 0xF); ++#endif ++ }else { ++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0; ++#else ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VPRI_VIDX = 0; ++#endif ++ } ++#endif ++ ++#if defined(CONFIG_RAETH_PDMA_DVT) ++ raeth_pdma_tx_vlan_dvt( ei_local, tx_cpu_owner_idx0 ); ++#endif /* CONFIG_RAETH_PDMA_DVT */ ++ ++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) ++ if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) { ++ if(ra_sw_nat_hook_rx!= NULL){ ++#if defined (CONFIG_RALINK_MT7620) ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FP_BMAP = (1 << 7); /* PPE */ ++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 4; /* PPE */ ++#else ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.PN = 6; /* PPE */ ++#endif ++ FOE_MAGIC_TAG(skb) = 0; ++ } ++ } ++#endif ++ ++#if defined(CONFIG_RAETH_PDMA_DVT) ++ raeth_pdma_tx_desc_dvt( ei_local, tx_cpu_owner_idx0 ); ++#endif /* CONFIG_RAETH_PDMA_DVT */ ++ ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.DDONE_bit = 0; ++ ++#if 0 ++ printk("---------------\n"); ++ printk("tx_info1=%x\n",ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info1); ++ printk("tx_info2=%x\n",ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2); ++ printk("tx_info3=%x\n",ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info3); ++ printk("tx_info4=%x\n",ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4); ++#endif ++ ++#else ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info1.SDP0 = virt_to_phys(skb->data); ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.SDL0 = (length - skb->data_len); ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS0_bit = nr_frags ? 0:1; ++#if defined (CONFIG_RALINK_MT7620) ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FP_BMAP = 0; ++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++ if (gmac_no == 1) { ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 1; ++ }else { ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 2; ++ } ++#else ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.PN = gmac_no; ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.QN = 3; ++#endif ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TSO = 0; ++ ++#if defined (CONFIG_RAETH_CHECKSUM_OFFLOAD) && ! defined(CONFIG_RALINK_RT5350) && !defined(CONFIG_RALINK_MT7628) ++ if (skb->ip_summed == CHECKSUM_PARTIAL){ ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TUI_CO = 7; ++ }else { ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TUI_CO = 0; ++ } ++#endif ++ ++#ifdef CONFIG_RAETH_HW_VLAN_TX ++ if(vlan_tx_tag_present(skb)) { ++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0x10000 | vlan_tx_tag_get(skb); ++#else ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VPRI_VIDX = 0x80 | (vlan_tx_tag_get(skb) >> 13) << 4 | (vlan_tx_tag_get(skb) & 0xF); ++#endif ++ }else { ++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0; ++#else ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VPRI_VIDX = 0; ++#endif ++ } ++#endif ++ ++#if defined(CONFIG_RAETH_PDMA_DVT) ++ raeth_pdma_tx_vlan_dvt( ei_local, tx_cpu_owner_idx0 ); ++#endif /* CONFIG_RAETH_PDMA_DVT */ ++ ++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) ++ if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) { ++ if(ra_sw_nat_hook_rx!= NULL){ ++#if defined (CONFIG_RALINK_MT7620) ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FP_BMAP = (1 << 7); /* PPE */ ++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 4; /* PPE */ ++#else ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.PN = 6; /* PPE */ ++#endif ++ FOE_MAGIC_TAG(skb) = 0; ++ } ++ } ++#endif ++ ++ skb_txd_num = 1; ++ ++ if(nr_frags > 0) { ++ ++ for(i=0;ifrags[i]; ++ offset = frag->page_offset; ++ len = frag->size; ++ frag_txd_num = cal_frag_txd_num(len); ++ ++ while(frag_txd_num > 0){ ++ if(len < MAX_TXD_LEN) ++ size = len; ++ else ++ size = MAX_TXD_LEN; ++ if(skb_txd_num%2 == 0) { ++ tx_cpu_owner_idx0 = (tx_cpu_owner_idx0+1) % NUM_TX_DESC; ++ ++ while(ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.DDONE_bit == 0) ++ { ++#ifdef config_pseudo_support ++ if (gmac_no == 2) { ++ if (ei_local->pseudodev != null) { ++ pad = netdev_priv(ei_local->pseudodev); ++ pad->stat.tx_errors++; ++ } ++ } else ++#endif ++ ei_local->stat.tx_errors++; ++ } ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info1.SDP0 = pci_map_page(NULL, frag->page, offset, size, PCI_DMA_TODEVICE); ++#else ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info1.SDP0 = pci_map_page(NULL, frag->page.p, offset, size, PCI_DMA_TODEVICE); ++#endif ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.SDL0 = size; ++ ++ if( (i==(nr_frags-1)) && (frag_txd_num == 1)) ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS0_bit = 1; ++ else ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS0_bit = 0; ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.DDONE_bit = 0; ++ }else { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info3.SDP1 = pci_map_page(NULL, frag->page, offset, size, PCI_DMA_TODEVICE); ++#else ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info3.SDP1 = pci_map_page(NULL, frag->page.p, offset, size, PCI_DMA_TODEVICE); ++ ++#endif ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.SDL1 = size; ++ if( (i==(nr_frags-1)) && (frag_txd_num == 1)) ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS1_bit = 1; ++ else ++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS1_bit = 0; ++ } ++ offset += size; ++ len -= size; ++ frag_txd_num--; ++ skb_txd_num++; ++ } ++ } ++ } ++ ++#if defined(CONFIG_RAETH_PDMA_DVT) ++ if( (pdma_dvt_get_debug_test_config() & PDMA_TEST_TSO_DEBUG) ){ ++ printk("skb_shinfo(skb)->gso_segs = %d\n", skb_shinfo(skb)->gso_segs); ++ } ++#endif /* CONFIG_RAETH_PDMA_DVT */ ++ /* fill in MSS info in tcp checksum field */ ++ if(skb_shinfo(skb)->gso_segs > 1) { ++ ++// TsoLenUpdate(skb->len); ++ ++ /* TCP over IPv4 */ ++ iph = (struct iphdr *)skb_network_header(skb); ++#if defined (CONFIG_RAETH_TSOV6) ++ /* TCP over IPv6 */ ++ ip6h = (struct ipv6hdr *)skb_network_header(skb); ++#endif ++ if((iph->version == 4) && (iph->protocol == IPPROTO_TCP)) { ++ th = (struct tcphdr *)skb_transport_header(skb); ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ ei_local->tx_ring0[ctx_idx_start_addr].txd_info4.TSO = 1; ++#else ++ ei_local->tx_ring0[sysRegRead(TX_CTX_IDX0)].txd_info4.TSO = 1; ++#endif ++ th->check = htons(skb_shinfo(skb)->gso_size); ++#if defined (CONFIG_MIPS) ++ dma_cache_sync(NULL, th, sizeof(struct tcphdr), DMA_TO_DEVICE); ++#else ++ dma_sync_single_for_device(NULL, virt_to_phys(th), sizeof(struct tcphdr), DMA_TO_DEVICE); ++#endif ++ } ++ ++#if defined (CONFIG_RAETH_TSOV6) ++ /* TCP over IPv6 */ ++ else if ((ip6h->version == 6) && (ip6h->nexthdr == NEXTHDR_TCP)) { ++ th = (struct tcphdr *)skb_transport_header(skb); ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ ei_local->tx_ring0[ctx_idx_start_addr].txd_info4.TSO = 1; ++#else ++ ei_local->tx_ring0[sysRegRead(TX_CTX_IDX0)].txd_info4.TSO = 1; ++#endif ++ th->check = htons(skb_shinfo(skb)->gso_size); ++#if defined (CONFIG_MIPS) ++ dma_cache_sync(NULL, th, sizeof(struct tcphdr), DMA_TO_DEVICE); ++#else ++ dma_sync_single_for_device(NULL, virt_to_phys(th), sizeof(struct tcphdr), DMA_TO_DEVICE); ++#endif ++ } ++#endif // CONFIG_RAETH_TSOV6 // ++ } ++ ++#if defined(CONFIG_RAETH_PDMA_DVT) ++ raeth_pdma_tx_desc_dvt( ei_local, tx_cpu_owner_idx0 ); ++#endif /* CONFIG_RAETH_PDMA_DVT */ ++ ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ ei_local->tx_ring0[ctx_idx_start_addr].txd_info2.DDONE_bit = 0; ++#else ++ ei_local->tx_ring0[sysRegRead(TX_CTX_IDX0)].txd_info2.DDONE_bit = 0; ++#endif ++#endif // CONFIG_RAETH_TSO // ++ ++ tx_cpu_owner_idx0 = (tx_cpu_owner_idx0+1) % NUM_TX_DESC; ++ while(ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.DDONE_bit == 0) ++ { ++// printk(KERN_ERR "%s: TXD=%lu TX DMA is Busy !!\n", dev->name, tx_cpu_owner_idx0); ++#ifdef CONFIG_PSEUDO_SUPPORT ++ if (gmac_no == 2) { ++ if (ei_local->PseudoDev != NULL) { ++ pAd = netdev_priv(ei_local->PseudoDev); ++ pAd->stat.tx_errors++; ++ } ++ } else ++#endif ++ ei_local->stat.tx_errors++; ++ } ++ sysRegWrite(TX_CTX_IDX0, cpu_to_le32((u32)tx_cpu_owner_idx0)); ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++ if (gmac_no == 2) { ++ if (ei_local->PseudoDev != NULL) { ++ pAd = netdev_priv(ei_local->PseudoDev); ++ pAd->stat.tx_packets++; ++ pAd->stat.tx_bytes += length; ++ } ++ } else ++#endif ++ { ++ ei_local->stat.tx_packets++; ++ ei_local->stat.tx_bytes += length; ++ } ++#ifdef CONFIG_RAETH_NAPI ++ if ( ei_local->tx_full == 1) { ++ ei_local->tx_full = 0; ++ netif_wake_queue(dev); ++ } ++#endif ++ ++ return length; ++} ++ ++int ei_start_xmit(struct sk_buff* skb, struct net_device *dev, int gmac_no) ++{ ++ END_DEVICE *ei_local = netdev_priv(dev); ++ unsigned long flags; ++ unsigned long tx_cpu_owner_idx; ++ unsigned int tx_cpu_owner_idx_next; ++ unsigned int num_of_txd = 0; ++#if defined (CONFIG_RAETH_TSO) ++ unsigned int nr_frags = skb_shinfo(skb)->nr_frags, i; ++ struct skb_frag_struct *frag; ++#endif ++#if !defined(CONFIG_RAETH_QOS) ++ unsigned int tx_cpu_owner_idx_next2; ++#else ++ int ring_no, queue_no, port_no; ++#endif ++#ifdef CONFIG_RALINK_VISTA_BASIC ++ struct vlan_ethhdr *veth; ++#endif ++#ifdef CONFIG_PSEUDO_SUPPORT ++ PSEUDO_ADAPTER *pAd; ++#endif ++ ++#if !defined(CONFIG_RA_NAT_NONE) ++ if(ra_sw_nat_hook_tx!= NULL) ++ { ++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) ++ if(FOE_MAGIC_TAG(skb) != FOE_MAGIC_PPE) ++#endif ++ { ++ //spin_lock_irqsave(&ei_local->page_lock, flags); ++ if(ra_sw_nat_hook_tx(skb, gmac_no)==1){ ++ //spin_unlock_irqrestore(&ei_local->page_lock, flags); ++ }else{ ++ kfree_skb(skb); ++ //spin_unlock_irqrestore(&ei_local->page_lock, flags); ++ return 0; ++ } ++ } ++ } ++#endif ++#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE) ++ /* Qwert+ ++ */ ++ if(ra_classifier_hook_tx!= NULL) ++ { ++#if defined(CONFIG_RALINK_EXTERNAL_TIMER) ++ ra_classifier_hook_tx(skb, (*((volatile u32 *)(0xB0000D08))&0x0FFFF)); ++#else ++ ra_classifier_hook_tx(skb, read_c0_count()); ++#endif ++ } ++#endif /* CONFIG_RA_CLASSIFIER */ ++ ++#if defined (CONFIG_RALINK_RT3052_MP2) ++ mcast_tx(skb); ++#endif ++ ++#if !defined (CONFIG_RALINK_RT6855) && !defined (CONFIG_RALINK_RT6855A) && \ ++ !defined(CONFIG_RALINK_MT7621) && !defined (CONFIG_ARCH_MT7623) ++ ++#define MIN_PKT_LEN 60 ++ if (skb->len < MIN_PKT_LEN) { ++ if (skb_padto(skb, MIN_PKT_LEN)) { ++ printk("raeth: skb_padto failed\n"); ++ return 0; ++ } ++ skb_put(skb, MIN_PKT_LEN - skb->len); ++ } ++#endif ++ ++ dev->trans_start = jiffies; /* save the timestamp */ ++ spin_lock_irqsave(&ei_local->page_lock, flags); ++#if defined (CONFIG_MIPS) ++ dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE); ++#else ++ dma_sync_single_for_device(NULL, virt_to_phys(skb->data), skb->len, DMA_TO_DEVICE); ++ ++#endif ++ ++#ifdef CONFIG_RALINK_VISTA_BASIC ++ veth = (struct vlan_ethhdr *)(skb->data); ++ if (is_switch_175c && veth->h_vlan_proto == __constant_htons(ETH_P_8021Q)) { ++ if ((veth->h_vlan_TCI & __constant_htons(VLAN_VID_MASK)) == 0) { ++ veth->h_vlan_TCI |= htons(VLAN_DEV_INFO(dev)->vlan_id); ++ } ++ } ++#endif ++ ++#if defined (CONFIG_RAETH_QOS) ++ if(pkt_classifier(skb, gmac_no, &ring_no, &queue_no, &port_no)) { ++ get_tx_ctx_idx(ring_no, &tx_cpu_owner_idx); ++ tx_cpu_owner_idx_next = (tx_cpu_owner_idx + 1) % NUM_TX_DESC; ++ if(((ei_local->skb_free[ring_no][tx_cpu_owner_idx]) ==0) && (ei_local->skb_free[ring_no][tx_cpu_owner_idx_next]==0)){ ++ fe_qos_packet_send(dev, skb, ring_no, queue_no, port_no); ++ }else{ ++ ei_local->stat.tx_dropped++; ++ kfree_skb(skb); ++ spin_unlock_irqrestore(&ei_local->page_lock, flags); ++ return 0; ++ } ++ } ++#else ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ tx_cpu_owner_idx = tx_cpu_owner_idx0; ++#else ++ tx_cpu_owner_idx = sysRegRead(TX_CTX_IDX0); ++#endif ++#if defined (CONFIG_RAETH_TSO) ++// num_of_txd = (nr_frags==0) ? 1 : ((nr_frags>>1) + 1); ++// NumOfTxdUpdate(num_of_txd); ++ if(nr_frags != 0){ ++ for(i=0;ifrags[i]; ++ num_of_txd += cal_frag_txd_num(frag->size); ++ } ++ num_of_txd = (num_of_txd >> 1) + 1; ++ }else ++ num_of_txd = 1; ++ ++#else ++ num_of_txd = 1; ++#endif ++ tx_cpu_owner_idx_next = (tx_cpu_owner_idx + num_of_txd) % NUM_TX_DESC; ++ ++ if(((ei_local->skb_free[tx_cpu_owner_idx]) ==0) && (ei_local->skb_free[tx_cpu_owner_idx_next]==0)){ ++ rt2880_eth_send(dev, skb, gmac_no); ++ ++ tx_cpu_owner_idx_next2 = (tx_cpu_owner_idx_next + 1) % NUM_TX_DESC; ++ ++ if(ei_local->skb_free[tx_cpu_owner_idx_next2]!=0){ ++#if defined (CONFIG_RAETH_SW_FC) ++ netif_stop_queue(dev); ++#ifdef CONFIG_PSEUDO_SUPPORT ++ netif_stop_queue(ei_local->PseudoDev); ++#endif ++ tx_ring_full=1; ++#endif ++ } ++ }else { ++#ifdef CONFIG_PSEUDO_SUPPORT ++ if (gmac_no == 2) { ++ if (ei_local->PseudoDev != NULL) { ++ pAd = netdev_priv(ei_local->PseudoDev); ++ pAd->stat.tx_dropped++; ++ } ++ } else ++#endif ++ ei_local->stat.tx_dropped++; ++#if defined (CONFIG_RAETH_SW_FC) ++ printk("tx_ring_full, drop packet\n"); ++#endif ++ kfree_skb(skb); ++ spin_unlock_irqrestore(&ei_local->page_lock, flags); ++ return 0; ++ } ++ ++#if defined (CONFIG_RAETH_TSO) ++ /* SG: use multiple TXD to send the packet (only have one skb) */ ++ ei_local->skb_free[(tx_cpu_owner_idx + num_of_txd - 1) % NUM_TX_DESC] = skb; ++ while(--num_of_txd) { ++ ei_local->skb_free[(tx_cpu_owner_idx + num_of_txd -1) % NUM_TX_DESC] = (struct sk_buff *)0xFFFFFFFF; //MAGIC ID ++ } ++#else ++ ei_local->skb_free[tx_cpu_owner_idx] = skb; ++#endif ++#endif ++ spin_unlock_irqrestore(&ei_local->page_lock, flags); ++ return 0; ++} ++ ++void ei_xmit_housekeeping(unsigned long unused) ++{ ++ struct net_device *dev = dev_raether; ++ END_DEVICE *ei_local = netdev_priv(dev); ++ struct PDMA_txdesc *tx_desc; ++ unsigned long skb_free_idx; ++ unsigned long tx_dtx_idx __maybe_unused; ++#ifndef CONFIG_RAETH_NAPI ++ unsigned long reg_int_mask=0; ++#endif ++ ++#ifdef CONFIG_RAETH_QOS ++ int i; ++ for (i=0;ifree_idx[i]; ++ if((ei_local->skb_free[i][skb_free_idx])==0){ ++ continue; ++ } ++ ++ get_tx_desc_and_dtx_idx(ei_local, i, &tx_dtx_idx, &tx_desc); ++ ++ while(tx_desc[skb_free_idx].txd_info2.DDONE_bit==1 && (ei_local->skb_free[i][skb_free_idx])!=0 ){ ++ dev_kfree_skb_any((ei_local->skb_free[i][skb_free_idx])); ++ ++ ei_local->skb_free[i][skb_free_idx]=0; ++ skb_free_idx = (skb_free_idx +1) % NUM_TX_DESC; ++ } ++ ei_local->free_idx[i] = skb_free_idx; ++ } ++#else ++ tx_dtx_idx = sysRegRead(TX_DTX_IDX0); ++ tx_desc = ei_local->tx_ring0; ++ skb_free_idx = ei_local->free_idx; ++ if ((ei_local->skb_free[skb_free_idx]) != 0 && tx_desc[skb_free_idx].txd_info2.DDONE_bit==1) { ++ while(tx_desc[skb_free_idx].txd_info2.DDONE_bit==1 && (ei_local->skb_free[skb_free_idx])!=0 ){ ++#if defined (CONFIG_RAETH_TSO) ++ if(ei_local->skb_free[skb_free_idx]!=(struct sk_buff *)0xFFFFFFFF) { ++ dev_kfree_skb_any(ei_local->skb_free[skb_free_idx]); ++ } ++#else ++ dev_kfree_skb_any(ei_local->skb_free[skb_free_idx]); ++#endif ++ ei_local->skb_free[skb_free_idx]=0; ++ skb_free_idx = (skb_free_idx +1) % NUM_TX_DESC; ++ } ++ ++ netif_wake_queue(dev); ++#ifdef CONFIG_PSEUDO_SUPPORT ++ netif_wake_queue(ei_local->PseudoDev); ++#endif ++ tx_ring_full=0; ++ ei_local->free_idx = skb_free_idx; ++ } /* if skb_free != 0 */ ++#endif ++ ++#ifndef CONFIG_RAETH_NAPI ++ reg_int_mask=sysRegRead(FE_INT_ENABLE); ++#if defined (DELAY_INT) ++ sysRegWrite(FE_INT_ENABLE, reg_int_mask| TX_DLY_INT); ++#else ++ ++ sysRegWrite(FE_INT_ENABLE, reg_int_mask | TX_DONE_INT0 \ ++ | TX_DONE_INT1 \ ++ | TX_DONE_INT2 \ ++ | TX_DONE_INT3); ++#endif ++#endif //CONFIG_RAETH_NAPI// ++} ++ ++ ++ ++EXPORT_SYMBOL(ei_start_xmit); ++EXPORT_SYMBOL(ei_xmit_housekeeping); ++EXPORT_SYMBOL(fe_dma_init); ++EXPORT_SYMBOL(rt2880_eth_send); +diff --git a/drivers/net/ethernet/raeth/raether_qdma.c b/drivers/net/ethernet/raeth/raether_qdma.c +new file mode 100644 +index 0000000..acf8bfe +--- /dev/null ++++ b/drivers/net/ethernet/raeth/raether_qdma.c +@@ -0,0 +1,1407 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if defined (CONFIG_RAETH_TSO) ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#endif ++#include ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++#include ++#endif ++#if defined (CONFIG_HW_SFQ) ++#include ++#include ++#include ++#include ++#include ++#endif ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) ++#include ++#else ++#include ++#endif ++ ++#include "ra2882ethreg.h" ++#include "raether.h" ++#include "ra_mac.h" ++#include "ra_ioctl.h" ++#include "ra_rfrw.h" ++#ifdef CONFIG_RAETH_NETLINK ++#include "ra_netlink.h" ++#endif ++#if defined (CONFIG_RAETH_QOS) ++#include "ra_qos.h" ++#endif ++ ++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) ++#include "../../../net/nat/hw_nat/ra_nat.h" ++#endif ++ ++ ++#if !defined(CONFIG_RA_NAT_NONE) ++/* bruce+ ++ */ ++extern int (*ra_sw_nat_hook_rx)(struct sk_buff *skb); ++extern int (*ra_sw_nat_hook_tx)(struct sk_buff *skb, int gmac_no); ++#endif ++ ++#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE) ++/* Qwert+ ++ */ ++#include ++extern int (*ra_classifier_hook_tx)(struct sk_buff *skb, unsigned long cur_cycle); ++extern int (*ra_classifier_hook_rx)(struct sk_buff *skb, unsigned long cur_cycle); ++#endif /* CONFIG_RA_CLASSIFIER */ ++ ++#if defined (CONFIG_RALINK_RT3052_MP2) ++int32_t mcast_rx(struct sk_buff * skb); ++int32_t mcast_tx(struct sk_buff * skb); ++#endif ++ ++#ifdef RA_MTD_RW_BY_NUM ++int ra_mtd_read(int num, loff_t from, size_t len, u_char *buf); ++#else ++int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf); ++#endif ++ ++/* gmac driver feature set config */ ++#if defined (CONFIG_RAETH_NAPI) || defined (CONFIG_RAETH_QOS) ++#undef DELAY_INT ++#else ++#if defined (CONFIG_ARCH_MT7623) ++#undef DELAY_INT ++#else ++#define DELAY_INT 1 ++#endif ++#endif ++ ++//#define CONFIG_UNH_TEST ++/* end of config */ ++ ++#if defined (CONFIG_RAETH_JUMBOFRAME) ++#define MAX_RX_LENGTH 4096 ++#else ++#define MAX_RX_LENGTH 1536 ++#endif ++ ++extern struct net_device *dev_raether; ++ ++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++static int rx_dma_owner_idx1; ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++static int rx_calc_idx1; ++#endif ++#endif ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++static int rx_calc_idx0; ++static unsigned long tx_cpu_owner_idx0=0; ++#endif ++extern unsigned long tx_ring_full; ++ ++#if defined (CONFIG_ETHTOOL) && defined (CONFIG_RAETH_ROUTER) ++#include "ra_ethtool.h" ++extern struct ethtool_ops ra_ethtool_ops; ++#ifdef CONFIG_PSEUDO_SUPPORT ++extern struct ethtool_ops ra_virt_ethtool_ops; ++#endif // CONFIG_PSEUDO_SUPPORT // ++#endif // (CONFIG_ETHTOOL // ++ ++#ifdef CONFIG_RALINK_VISTA_BASIC ++int is_switch_175c = 1; ++#endif ++ ++//skb->mark to queue mapping table ++extern unsigned int M2Q_table[64]; ++struct QDMA_txdesc *free_head = NULL; ++extern unsigned int lan_wan_separate; ++#if defined (CONFIG_HW_SFQ) ++extern unsigned int web_sfq_enable; ++#define HwSfqQUp 3 ++#define HwSfqQDl 1 ++#endif ++int dbg =0;//debug used ++#if defined (CONFIG_HW_SFQ) ++struct SFQ_table *sfq0; ++struct SFQ_table *sfq1; ++struct SFQ_table *sfq2; ++struct SFQ_table *sfq3; ++#endif ++ ++#define KSEG1 0xa0000000 ++#if defined (CONFIG_MIPS) ++#define PHYS_TO_VIRT(x) ((void *)((x) | KSEG1)) ++#define VIRT_TO_PHYS(x) ((unsigned long)(x) & ~KSEG1) ++#else ++#define PHYS_TO_VIRT(x) phys_to_virt(x) ++#define VIRT_TO_PHYS(x) virt_to_phys(x) ++#endif ++ ++extern void set_fe_dma_glo_cfg(void); ++ ++#if defined (CONFIG_HW_SFQ) ++ParseResult SfqParseResult; ++#endif ++ ++/** ++ * ++ * @brief: get the TXD index from its address ++ * ++ * @param: cpu_ptr ++ * ++ * @return: TXD index ++*/ ++ ++static unsigned int GET_TXD_OFFSET(struct QDMA_txdesc **cpu_ptr) ++{ ++ struct net_device *dev = dev_raether; ++ END_DEVICE *ei_local = netdev_priv(dev); ++ int ctx_offset; ++ //ctx_offset = (((((u32)*cpu_ptr) <<8)>>8) - ((((u32)ei_local->txd_pool)<<8)>>8))/ sizeof(struct QDMA_txdesc); ++ //ctx_offset = (*cpu_ptr - ei_local->txd_pool); ++ ctx_offset = (((((u32)*cpu_ptr) <<8)>>8) - ((((u32)ei_local->phy_txd_pool)<<8)>>8))/ sizeof(struct QDMA_txdesc); ++ ++ return ctx_offset; ++} ++ ++ ++ ++ ++/** ++ * @brief cal txd number for a page ++ * ++ * @parm size ++ * ++ * @return frag_txd_num ++ */ ++ ++unsigned int cal_frag_txd_num(unsigned int size) ++{ ++ unsigned int frag_txd_num = 0; ++ if(size == 0) ++ return 0; ++ while(size > 0){ ++ if(size > MAX_TXD_LEN){ ++ frag_txd_num++; ++ size -= MAX_TXD_LEN; ++ }else{ ++ frag_txd_num++; ++ size = 0; ++ } ++ } ++ return frag_txd_num; ++ ++} ++ ++/** ++ * @brief get free TXD from TXD queue ++ * ++ * @param free_txd ++ * ++ * @return ++ */ ++static int get_free_txd(struct QDMA_txdesc **free_txd) ++{ ++ struct net_device *dev = dev_raether; ++ END_DEVICE *ei_local = netdev_priv(dev); ++ unsigned int tmp_idx; ++ ++ if(ei_local->free_txd_num > 0){ ++ tmp_idx = ei_local->free_txd_head; ++ ei_local->free_txd_head = ei_local->txd_pool_info[tmp_idx]; ++ ei_local->free_txd_num -= 1; ++ //*free_txd = &ei_local->txd_pool[tmp_idx]; ++ *free_txd = ei_local->phy_txd_pool + (sizeof(struct QDMA_txdesc) * tmp_idx); ++ return tmp_idx; ++ }else ++ return NUM_TX_DESC; ++} ++ ++ ++/** ++ * @brief add free TXD into TXD queue ++ * ++ * @param free_txd ++ * ++ * @return ++ */ ++int put_free_txd(int free_txd_idx) ++{ ++ struct net_device *dev = dev_raether; ++ END_DEVICE *ei_local = netdev_priv(dev); ++ ei_local->txd_pool_info[ei_local->free_txd_tail] = free_txd_idx; ++ ei_local->free_txd_tail = free_txd_idx; ++ ei_local->txd_pool_info[free_txd_idx] = NUM_TX_DESC; ++ ei_local->free_txd_num += 1; ++ return 1; ++} ++ ++/*define qdma initial alloc*/ ++/** ++ * @brief ++ * ++ * @param net_dev ++ * ++ * @return 0: fail ++ * 1: success ++ */ ++bool qdma_tx_desc_alloc(void) ++{ ++ struct net_device *dev = dev_raether; ++ END_DEVICE *ei_local = netdev_priv(dev); ++ struct QDMA_txdesc *free_txd = NULL; ++ unsigned int txd_idx; ++ int i = 0; ++ ++ ++ ei_local->txd_pool = pci_alloc_consistent(NULL, sizeof(struct QDMA_txdesc) * NUM_TX_DESC, &ei_local->phy_txd_pool); ++ printk("txd_pool=%p phy_txd_pool=%08X\n", ei_local->txd_pool , ei_local->phy_txd_pool); ++ ++ if (ei_local->txd_pool == NULL) { ++ printk("adapter->txd_pool allocation failed!\n"); ++ return 0; ++ } ++ printk("ei_local->skb_free start address is 0x%p.\n", ei_local->skb_free); ++ //set all txd_pool_info to 0. ++ for ( i = 0; i < NUM_TX_DESC; i++) ++ { ++ ei_local->skb_free[i]= 0; ++ ei_local->txd_pool_info[i] = i + 1; ++ ei_local->txd_pool[i].txd_info3.LS_bit = 1; ++ ei_local->txd_pool[i].txd_info3.OWN_bit = 1; ++ } ++ ++ ei_local->free_txd_head = 0; ++ ei_local->free_txd_tail = NUM_TX_DESC - 1; ++ ei_local->free_txd_num = NUM_TX_DESC; ++ ++ ++ //get free txd from txd pool ++ txd_idx = get_free_txd(&free_txd); ++ if( txd_idx == NUM_TX_DESC) { ++ printk("get_free_txd fail\n"); ++ return 0; ++ } ++ ++ //add null TXD for transmit ++ //ei_local->tx_dma_ptr = VIRT_TO_PHYS(free_txd); ++ //ei_local->tx_cpu_ptr = VIRT_TO_PHYS(free_txd); ++ ei_local->tx_dma_ptr = free_txd; ++ ei_local->tx_cpu_ptr = free_txd; ++ sysRegWrite(QTX_CTX_PTR, ei_local->tx_cpu_ptr); ++ sysRegWrite(QTX_DTX_PTR, ei_local->tx_dma_ptr); ++ ++ //get free txd from txd pool ++ ++ txd_idx = get_free_txd(&free_txd); ++ if( txd_idx == NUM_TX_DESC) { ++ printk("get_free_txd fail\n"); ++ return 0; ++ } ++ // add null TXD for release ++ //sysRegWrite(QTX_CRX_PTR, VIRT_TO_PHYS(free_txd)); ++ //sysRegWrite(QTX_DRX_PTR, VIRT_TO_PHYS(free_txd)); ++ sysRegWrite(QTX_CRX_PTR, free_txd); ++ sysRegWrite(QTX_DRX_PTR, free_txd); ++ printk("free_txd: %p, ei_local->cpu_ptr: %08X\n", free_txd, ei_local->tx_cpu_ptr); ++ ++ printk(" POOL HEAD_PTR | DMA_PTR | CPU_PTR \n"); ++ printk("----------------+---------+--------\n"); ++ printk(" 0x%p 0x%08X 0x%08X\n",ei_local->txd_pool, ei_local->tx_dma_ptr, ei_local->tx_cpu_ptr); ++ return 1; ++} ++#if defined (CONFIG_HW_SFQ) ++bool sfq_init(void) ++{ ++ unsigned int regVal; ++ ++ unsigned int sfq_phy0; ++ unsigned int sfq_phy1; ++ unsigned int sfq_phy2; ++ unsigned int sfq_phy3; ++ struct SFQ_table *sfq0; ++ struct SFQ_table *sfq1; ++ struct SFQ_table *sfq2; ++ struct SFQ_table *sfq3; ++ int i = 0; ++ regVal = sysRegRead(VQTX_GLO); ++ regVal = regVal | VQTX_MIB_EN |(1<<16) ; ++ sysRegWrite(VQTX_GLO, regVal);// Virtual table extends to 32bytes ++ regVal = sysRegRead(VQTX_GLO); ++ sysRegWrite(VQTX_NUM, (VQTX_NUM_0) | (VQTX_NUM_1) | (VQTX_NUM_2) | (VQTX_NUM_3)); ++ sysRegWrite(VQTX_HASH_CFG, 0xF002710); //10 s change hash algorithm ++ sysRegWrite(VQTX_VLD_CFG, 0x00); ++ sysRegWrite(VQTX_HASH_SD, 0x0D); ++ sysRegWrite(QDMA_FC_THRES, 0x9b9b4444); ++ sysRegWrite(QDMA_HRED1, 0); ++ sysRegWrite(QDMA_HRED2, 0); ++ sysRegWrite(QDMA_SRED1, 0); ++ sysRegWrite(QDMA_SRED2, 0); ++ sfq0 = pci_alloc_consistent(NULL, 256*sizeof(struct SFQ_table), &sfq_phy0); ++ memset(sfq0, 0x0, 256*sizeof(struct SFQ_table) ); ++ for (i=0; i < 256; i++) { ++ sfq0[i].sfq_info1.VQHPTR = 0xdeadbeef; ++ sfq0[i].sfq_info2.VQTPTR = 0xdeadbeef; ++ } ++#if(1) ++ sfq1 = pci_alloc_consistent(NULL, 256*sizeof(struct SFQ_table), &sfq_phy1); ++ ++ memset(sfq1, 0x0, 256*sizeof(struct SFQ_table) ); ++ for (i=0; i < 256; i++) { ++ sfq1[i].sfq_info1.VQHPTR = 0xdeadbeef; ++ sfq1[i].sfq_info2.VQTPTR = 0xdeadbeef; ++ } ++ ++ sfq2 = pci_alloc_consistent(NULL, 256*sizeof(struct SFQ_table), &sfq_phy2); ++ memset(sfq2, 0x0, 256*sizeof(struct SFQ_table) ); ++ for (i=0; i < 256; i++) { ++ sfq2[i].sfq_info1.VQHPTR = 0xdeadbeef; ++ sfq2[i].sfq_info2.VQTPTR = 0xdeadbeef; ++ } ++ ++ sfq3 = pci_alloc_consistent(NULL, 256*sizeof(struct SFQ_table), &sfq_phy3); ++ memset(sfq3, 0x0, 256*sizeof(struct SFQ_table) ); ++ for (i=0; i < 256; i++) { ++ sfq3[i].sfq_info1.VQHPTR = 0xdeadbeef; ++ sfq3[i].sfq_info2.VQTPTR = 0xdeadbeef; ++ } ++ ++#endif ++ printk("*****sfq_phy0 is 0x%x!!!*******\n", sfq_phy0); ++ printk("*****sfq_phy1 is 0x%x!!!*******\n", sfq_phy1); ++ printk("*****sfq_phy2 is 0x%x!!!*******\n", sfq_phy2); ++ printk("*****sfq_phy3 is 0x%x!!!*******\n", sfq_phy3); ++ printk("*****sfq_virt0 is 0x%x!!!*******\n", sfq0); ++ printk("*****sfq_virt1 is 0x%x!!!*******\n", sfq1); ++ printk("*****sfq_virt2 is 0x%x!!!*******\n", sfq2); ++ printk("*****sfq_virt3 is 0x%x!!!*******\n", sfq3); ++ printk("*****sfq_virt0 is 0x%x!!!*******\n", sfq0); ++ sysRegWrite(VQTX_TB_BASE0, (u32)sfq_phy0); ++ sysRegWrite(VQTX_TB_BASE1, (u32)sfq_phy1); ++ sysRegWrite(VQTX_TB_BASE2, (u32)sfq_phy2); ++ sysRegWrite(VQTX_TB_BASE3, (u32)sfq_phy3); ++ ++ return 1; ++} ++#endif ++bool fq_qdma_init(struct net_device *dev) ++{ ++ END_DEVICE* ei_local = netdev_priv(dev); ++ //struct QDMA_txdesc *free_head = NULL; ++ unsigned int phy_free_head; ++ unsigned int phy_free_tail; ++ unsigned int *free_page_head = NULL; ++ unsigned int phy_free_page_head; ++ int i; ++ ++ free_head = pci_alloc_consistent(NULL, NUM_QDMA_PAGE * sizeof(struct QDMA_txdesc), &phy_free_head); ++ if (unlikely(free_head == NULL)){ ++ printk(KERN_ERR "QDMA FQ decriptor not available...\n"); ++ return 0; ++ } ++ memset(free_head, 0x0, sizeof(struct QDMA_txdesc) * NUM_QDMA_PAGE); ++ ++ free_page_head = pci_alloc_consistent(NULL, NUM_QDMA_PAGE * QDMA_PAGE_SIZE, &phy_free_page_head); ++ if (unlikely(free_page_head == NULL)){ ++ printk(KERN_ERR "QDMA FQ page not available...\n"); ++ return 0; ++ } ++ for (i=0; i < NUM_QDMA_PAGE; i++) { ++ free_head[i].txd_info1.SDP = (phy_free_page_head + (i * QDMA_PAGE_SIZE)); ++ if(i < (NUM_QDMA_PAGE-1)){ ++ free_head[i].txd_info2.NDP = (phy_free_head + ((i+1) * sizeof(struct QDMA_txdesc))); ++ ++ ++#if 0 ++ printk("free_head_phy[%d] is 0x%x!!!\n",i, VIRT_TO_PHYS(&free_head[i]) ); ++ printk("free_head[%d] is 0x%x!!!\n",i, &free_head[i] ); ++ printk("free_head[%d].txd_info1.SDP is 0x%x!!!\n",i, free_head[i].txd_info1.SDP ); ++ printk("free_head[%d].txd_info2.NDP is 0x%x!!!\n",i, free_head[i].txd_info2.NDP ); ++#endif ++ } ++ free_head[i].txd_info3.SDL = QDMA_PAGE_SIZE; ++ ++ } ++ phy_free_tail = (phy_free_head + (u32)((NUM_QDMA_PAGE-1) * sizeof(struct QDMA_txdesc))); ++ ++ printk("phy_free_head is 0x%x!!!\n", phy_free_head); ++ printk("phy_free_tail_phy is 0x%x!!!\n", phy_free_tail); ++ sysRegWrite(QDMA_FQ_HEAD, (u32)phy_free_head); ++ sysRegWrite(QDMA_FQ_TAIL, (u32)phy_free_tail); ++ sysRegWrite(QDMA_FQ_CNT, ((NUM_TX_DESC << 16) | NUM_QDMA_PAGE)); ++ sysRegWrite(QDMA_FQ_BLEN, QDMA_PAGE_SIZE << 16); ++ ++ ei_local->free_head = free_head; ++ ei_local->phy_free_head = phy_free_head; ++ ei_local->free_page_head = free_page_head; ++ ei_local->phy_free_page_head = phy_free_page_head; ++ return 1; ++} ++ ++int fe_dma_init(struct net_device *dev) ++{ ++ ++ int i; ++ unsigned int regVal; ++ END_DEVICE* ei_local = netdev_priv(dev); ++ ++ ++ #if defined (CONFIG_HW_SFQ) ++ sfq_init(); ++ #endif ++ fq_qdma_init(dev); ++ ++ while(1) ++ { ++ regVal = sysRegRead(QDMA_GLO_CFG); ++ if((regVal & RX_DMA_BUSY)) ++ { ++ printk("\n RX_DMA_BUSY !!! "); ++ continue; ++ } ++ if((regVal & TX_DMA_BUSY)) ++ { ++ printk("\n TX_DMA_BUSY !!! "); ++ continue; ++ } ++ break; ++ } ++ /*tx desc alloc, add a NULL TXD to HW*/ ++ ++ qdma_tx_desc_alloc(); ++ ++ /* Initial RX Ring 0*/ ++ ++#ifdef CONFIG_32B_DESC ++ ei_local->qrx_ring = kmalloc(NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL); ++ ei_local->phy_qrx_ring = virt_to_phys(ei_local->qrx_ring); ++#else ++ ei_local->qrx_ring = pci_alloc_consistent(NULL, NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_qrx_ring); ++#endif ++ for (i = 0; i < NUM_QRX_DESC; i++) { ++ memset(&ei_local->qrx_ring[i],0,sizeof(struct PDMA_rxdesc)); ++ ei_local->qrx_ring[i].rxd_info2.DDONE_bit = 0; ++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA) ++ ei_local->qrx_ring[i].rxd_info2.LS0 = 0; ++ ei_local->qrx_ring[i].rxd_info2.PLEN0 = MAX_RX_LENGTH; ++#else ++ ei_local->qrx_ring[i].rxd_info2.LS0 = 1; ++#endif ++ ei_local->qrx_ring[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx0_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE); ++ } ++ printk("\nphy_qrx_ring = 0x%08x, qrx_ring = 0x%p\n",ei_local->phy_qrx_ring,ei_local->qrx_ring); ++ ++ regVal = sysRegRead(QDMA_GLO_CFG); ++ regVal &= 0x000000FF; ++ ++ sysRegWrite(QDMA_GLO_CFG, regVal); ++ regVal=sysRegRead(QDMA_GLO_CFG); ++ ++ /* Tell the adapter where the TX/RX rings are located. */ ++ ++ sysRegWrite(QRX_BASE_PTR_0, phys_to_bus((u32) ei_local->phy_qrx_ring)); ++ sysRegWrite(QRX_MAX_CNT_0, cpu_to_le32((u32) NUM_QRX_DESC)); ++ sysRegWrite(QRX_CRX_IDX_0, cpu_to_le32((u32) (NUM_QRX_DESC - 1))); ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ rx_calc_idx0 = rx_dma_owner_idx0 = sysRegRead(QRX_CRX_IDX_0); ++#endif ++ sysRegWrite(QDMA_RST_CFG, PST_DRX_IDX0); ++ ++ ei_local->rx_ring0 = ei_local->qrx_ring; ++#if !defined (CONFIG_RAETH_QDMATX_QDMARX) ++ /* Initial PDMA RX Ring 0*/ ++#ifdef CONFIG_32B_DESC ++ ei_local->rx_ring0 = kmalloc(NUM_RX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL); ++ ei_local->phy_rx_ring0 = virt_to_phys(ei_local->rx_ring0); ++#else ++ ei_local->rx_ring0 = pci_alloc_consistent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring0); ++#endif ++ for (i = 0; i < NUM_RX_DESC; i++) { ++ memset(&ei_local->rx_ring0[i],0,sizeof(struct PDMA_rxdesc)); ++ ei_local->rx_ring0[i].rxd_info2.DDONE_bit = 0; ++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA) ++ ei_local->rx_ring0[i].rxd_info2.LS0 = 0; ++ ei_local->rx_ring0[i].rxd_info2.PLEN0 = MAX_RX_LENGTH; ++#else ++ ei_local->rx_ring0[i].rxd_info2.LS0 = 1; ++#endif ++ ei_local->rx_ring0[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx0_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE); ++ } ++ printk("\nphy_rx_ring0 = 0x%08x, rx_ring0 = 0x%p\n",ei_local->phy_rx_ring0,ei_local->rx_ring0); ++ ++ regVal = sysRegRead(PDMA_GLO_CFG); ++ regVal &= 0x000000FF; ++ sysRegWrite(PDMA_GLO_CFG, regVal); ++ regVal=sysRegRead(PDMA_GLO_CFG); ++ ++ sysRegWrite(RX_BASE_PTR0, phys_to_bus((u32) ei_local->phy_rx_ring0)); ++ sysRegWrite(RX_MAX_CNT0, cpu_to_le32((u32) NUM_RX_DESC)); ++ sysRegWrite(RX_CALC_IDX0, cpu_to_le32((u32) (NUM_RX_DESC - 1))); ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ rx_calc_idx0 = sysRegRead(RX_CALC_IDX0); ++#endif ++ sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX0); ++#endif ++#if !defined (CONFIG_HW_SFQ) ++ /* Enable randon early drop and set drop threshold automatically */ ++ sysRegWrite(QDMA_FC_THRES, 0x174444); ++#endif ++ sysRegWrite(QDMA_HRED2, 0x0); ++ set_fe_dma_glo_cfg(); ++#if defined (CONFIG_ARCH_MT7623) ++ printk("Enable QDMA TX NDP coherence check and re-read mechanism\n"); ++ regVal=sysRegRead(QDMA_GLO_CFG); ++ regVal = regVal | 0x400; ++ sysRegWrite(QDMA_GLO_CFG, regVal); ++ printk("***********QDMA_GLO_CFG=%x\n", sysRegRead(QDMA_GLO_CFG)); ++#endif ++ ++ return 1; ++} ++ ++#if defined (CONFIG_HW_SFQ) ++ ++int sfq_prot = 0; ++int proto_id=0; ++int udp_source_port=0; ++int tcp_source_port=0; ++int ack_packt =0; ++int SfqParseLayerInfo(struct sk_buff * skb) ++{ ++ ++ struct vlan_hdr *vh_sfq = NULL; ++ struct ethhdr *eth_sfq = NULL; ++ struct iphdr *iph_sfq = NULL; ++ struct ipv6hdr *ip6h_sfq = NULL; ++ struct tcphdr *th_sfq = NULL; ++ struct udphdr *uh_sfq = NULL; ++#ifdef CONFIG_RAETH_HW_VLAN_TX ++ struct vlan_hdr pseudo_vhdr_sfq; ++#endif ++ ++ memset(&SfqParseResult, 0, sizeof(SfqParseResult)); ++ ++ eth_sfq = (struct ethhdr *)skb->data; ++ memcpy(SfqParseResult.dmac, eth_sfq->h_dest, ETH_ALEN); ++ memcpy(SfqParseResult.smac, eth_sfq->h_source, ETH_ALEN); ++ SfqParseResult.eth_type = eth_sfq->h_proto; ++ ++ ++ if (SfqParseResult.eth_type == htons(ETH_P_8021Q)){ ++ SfqParseResult.vlan1_gap = VLAN_HLEN; ++ vh_sfq = (struct vlan_hdr *)(skb->data + ETH_HLEN); ++ SfqParseResult.eth_type = vh_sfq->h_vlan_encapsulated_proto; ++ }else{ ++ SfqParseResult.vlan1_gap = 0; ++ } ++ ++ ++ ++ LAYER2_HEADER(skb) = skb->data; ++ LAYER3_HEADER(skb) = (skb->data + ETH_HLEN + (SfqParseResult.vlan1_gap)); ++ ++ ++ ++ /* set layer4 start addr */ ++ if ((SfqParseResult.eth_type == htons(ETH_P_IP)) || (SfqParseResult.eth_type == htons(ETH_P_PPP_SES) ++ && SfqParseResult.ppp_tag == htons(PPP_IP))) { ++ iph_sfq = (struct iphdr *)LAYER3_HEADER(skb); ++ ++ //prepare layer3/layer4 info ++ memcpy(&SfqParseResult.iph, iph_sfq, sizeof(struct iphdr)); ++ if (iph_sfq->protocol == IPPROTO_TCP) { ++ ++ LAYER4_HEADER(skb) = ((uint8_t *) iph_sfq + (iph_sfq->ihl * 4)); ++ th_sfq = (struct tcphdr *)LAYER4_HEADER(skb); ++ memcpy(&SfqParseResult.th, th_sfq, sizeof(struct tcphdr)); ++ SfqParseResult.pkt_type = IPV4_HNAPT; ++ //printk("tcp parsing\n"); ++ tcp_source_port = ntohs(SfqParseResult.th.source); ++ udp_source_port = 0; ++ #if(0) //for TCP ack, test use ++ if(ntohl(SfqParseResult.iph.saddr) == 0xa0a0a04){ // tcp ack packet ++ ack_packt = 1; ++ }else { ++ ack_packt = 0; ++ } ++ #endif ++ sfq_prot = 2;//IPV4_HNAPT ++ proto_id = 1;//TCP ++ if(iph_sfq->frag_off & htons(IP_MF|IP_OFFSET)) { ++ //return 1; ++ } ++ } else if (iph_sfq->protocol == IPPROTO_UDP) { ++ LAYER4_HEADER(skb) = ((uint8_t *) iph_sfq + iph_sfq->ihl * 4); ++ uh_sfq = (struct udphdr *)LAYER4_HEADER(skb); ++ memcpy(&SfqParseResult.uh, uh_sfq, sizeof(struct udphdr)); ++ SfqParseResult.pkt_type = IPV4_HNAPT; ++ udp_source_port = ntohs(SfqParseResult.uh.source); ++ tcp_source_port = 0; ++ ack_packt = 0; ++ sfq_prot = 2;//IPV4_HNAPT ++ proto_id =2;//UDP ++ if(iph_sfq->frag_off & htons(IP_MF|IP_OFFSET)) { ++ return 1; ++ } ++ }else{ ++ sfq_prot = 1; ++ } ++ }else if (SfqParseResult.eth_type == htons(ETH_P_IPV6) || ++ (SfqParseResult.eth_type == htons(ETH_P_PPP_SES) && ++ SfqParseResult.ppp_tag == htons(PPP_IPV6))) { ++ ip6h_sfq = (struct ipv6hdr *)LAYER3_HEADER(skb); ++ memcpy(&SfqParseResult.ip6h, ip6h_sfq, sizeof(struct ipv6hdr)); ++ ++ if (ip6h_sfq->nexthdr == NEXTHDR_TCP) { ++ LAYER4_HEADER(skb) = ((uint8_t *) ip6h_sfq + sizeof(struct ipv6hdr)); ++ th_sfq = (struct tcphdr *)LAYER4_HEADER(skb); ++ memcpy(&SfqParseResult.th, th_sfq, sizeof(struct tcphdr)); ++ SfqParseResult.pkt_type = IPV6_5T_ROUTE; ++ sfq_prot = 4;//IPV6_5T ++ #if(0) //for TCP ack, test use ++ if(ntohl(SfqParseResult.ip6h.saddr.s6_addr32[3]) == 8){ ++ ack_packt = 1; ++ }else { ++ ack_packt = 0; ++ } ++ #endif ++ } else if (ip6h_sfq->nexthdr == NEXTHDR_UDP) { ++ LAYER4_HEADER(skb) = ((uint8_t *) ip6h_sfq + sizeof(struct ipv6hdr)); ++ uh_sfq = (struct udphdr *)LAYER4_HEADER(skb); ++ memcpy(&SfqParseResult.uh, uh_sfq, sizeof(struct udphdr)); ++ SfqParseResult.pkt_type = IPV6_5T_ROUTE; ++ ack_packt = 0; ++ sfq_prot = 4;//IPV6_5T ++ ++ }else{ ++ sfq_prot = 3;//IPV6_3T ++ } ++ } ++ ++ return 0; ++} ++#endif ++ ++inline int rt2880_eth_send(struct net_device* dev, struct sk_buff *skb, int gmac_no) ++{ ++ unsigned int length=skb->len; ++ END_DEVICE* ei_local = netdev_priv(dev); ++ ++ struct QDMA_txdesc *cpu_ptr; ++ ++ struct QDMA_txdesc *dma_ptr __maybe_unused; ++ struct QDMA_txdesc *free_txd; ++ int ctx_offset; ++#if defined (CONFIG_RAETH_TSO) ++ struct iphdr *iph = NULL; ++ struct QDMA_txdesc *init_cpu_ptr; ++ struct tcphdr *th = NULL; ++ struct skb_frag_struct *frag; ++ unsigned int nr_frags = skb_shinfo(skb)->nr_frags; ++ unsigned int len, size, offset, frag_txd_num; ++ int init_txd_idx, i; ++#endif // CONFIG_RAETH_TSO // ++ ++#if defined (CONFIG_RAETH_TSOV6) ++ struct ipv6hdr *ip6h = NULL; ++#endif ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++ PSEUDO_ADAPTER *pAd; ++#endif ++ //cpu_ptr = PHYS_TO_VIRT(ei_local->tx_cpu_ptr); ++ //dma_ptr = PHYS_TO_VIRT(ei_local->tx_dma_ptr); ++ //ctx_offset = GET_TXD_OFFSET(&cpu_ptr); ++ cpu_ptr = (ei_local->tx_cpu_ptr); ++ ctx_offset = GET_TXD_OFFSET(&cpu_ptr); ++ cpu_ptr = phys_to_virt(ei_local->tx_cpu_ptr); ++ dma_ptr = phys_to_virt(ei_local->tx_dma_ptr); ++ cpu_ptr = (ei_local->txd_pool + (ctx_offset)); ++ ei_local->skb_free[ctx_offset] = skb; ++#if defined (CONFIG_RAETH_TSO) ++ init_cpu_ptr = cpu_ptr; ++ init_txd_idx = ctx_offset; ++#endif ++ ++#if !defined (CONFIG_RAETH_TSO) ++ ++ //2. prepare data ++ //cpu_ptr->txd_info1.SDP = VIRT_TO_PHYS(skb->data); ++ cpu_ptr->txd_info1.SDP = virt_to_phys(skb->data); ++ cpu_ptr->txd_info3.SDL = skb->len; ++#if defined (CONFIG_HW_SFQ) ++ SfqParseLayerInfo(skb); ++ cpu_ptr->txd_info4.VQID0 = 1;//1:HW hash 0:CPU ++ ++ ++#if(0)// for tcp ack use, test use ++ if (ack_packt==1){ ++ cpu_ptr->txd_info3.QID = 0x0a; ++ //cpu_ptr->txd_info3.VQID = 0; ++ }else{ ++ cpu_ptr->txd_info3.QID = 0; ++ } ++#endif ++ cpu_ptr->txd_info3.PROT = sfq_prot; ++ cpu_ptr->txd_info3.IPOFST = 14 + (SfqParseResult.vlan1_gap); //no vlan ++ ++#endif ++ if (gmac_no == 1) { ++ cpu_ptr->txd_info4.FPORT = 1; ++ }else { ++ cpu_ptr->txd_info4.FPORT = 2; ++ } ++ ++ cpu_ptr->txd_info3.QID = M2Q_table[skb->mark]; ++#ifdef CONFIG_PSEUDO_SUPPORT ++ if((lan_wan_separate==1) && (gmac_no==2)){ ++ cpu_ptr->txd_info3.QID += 8; ++#if defined (CONFIG_HW_SFQ) ++ if(web_sfq_enable==1 &&(skb->mark == 2)){ ++ cpu_ptr->txd_info3.QID = HwSfqQUp; ++ } ++#endif ++ } ++#if defined (CONFIG_HW_SFQ) ++ if((lan_wan_separate==1) && (gmac_no==1)){ ++ if(web_sfq_enable==1 &&(skb->mark == 2)){ ++ cpu_ptr->txd_info3.QID = HwSfqQDl; ++ } ++ } ++#endif ++#endif //end CONFIG_PSEUDO_SUPPORT ++ ++ if(dbg==1){ ++ printk("M2Q_table[%d]=%d\n", skb->mark, M2Q_table[skb->mark]); ++ printk("cpu_ptr->txd_info3.QID = %d\n", cpu_ptr->txd_info3.QID); ++ } ++#if 0 ++ iph = (struct iphdr *)skb_network_header(skb); ++ if (iph->tos == 0xe0) ++ cpu_ptr->txd_info3.QID = 3; ++ else if (iph->tos == 0xa0) ++ cpu_ptr->txd_info3.QID = 2; ++ else if (iph->tos == 0x20) ++ cpu_ptr->txd_info3.QID = 1; ++ else ++ cpu_ptr->txd_info3.QID = 0; ++#endif ++ ++#if defined (CONFIG_RAETH_CHECKSUM_OFFLOAD) && ! defined(CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628) ++ if (skb->ip_summed == CHECKSUM_PARTIAL){ ++ cpu_ptr->txd_info4.TUI_CO = 7; ++ }else { ++ cpu_ptr->txd_info4.TUI_CO = 0; ++ } ++#endif ++ ++#ifdef CONFIG_RAETH_HW_VLAN_TX ++ if(vlan_tx_tag_present(skb)) { ++ cpu_ptr->txd_info4.VLAN_TAG = 0x10000 | vlan_tx_tag_get(skb); ++ }else { ++ cpu_ptr->txd_info4.VLAN_TAG = 0; ++ } ++#endif ++ ++#ifdef CONFIG_RAETH_HW_VLAN_TX // QoS Web UI used ++ ++ if((lan_wan_separate==1) && (vlan_tx_tag_get(skb)==2)){ ++ cpu_ptr->txd_info3.QID += 8; ++#if defined (CONFIG_HW_SFQ) ++ if(web_sfq_enable==1 &&(skb->mark == 2)){ ++ cpu_ptr->txd_info3.QID = HwSfqQUp; ++ } ++#endif ++ } ++#if defined (CONFIG_HW_SFQ) ++ if((lan_wan_separate==1) && (vlan_tx_tag_get(skb)==1)){ ++ if(web_sfq_enable==1 &&(skb->mark == 2)){ ++ cpu_ptr->txd_info3.QID = HwSfqQDl; ++ } ++ } ++#endif ++#endif // CONFIG_RAETH_HW_VLAN_TX ++ ++ ++//no hw van, no GE2, web UI used ++#ifndef CONFIG_PSEUDO_SUPPORT ++#ifndef CONFIG_RAETH_HW_VLAN_TX ++ if(lan_wan_separate==1){ ++ struct vlan_hdr *vh = NULL; ++ unsigned short vlanid = 0; ++ unsigned short vlan_TCI; ++ vh = (struct vlan_hdr *)(skb->data + ETH_HLEN); ++ vlan_TCI = vh->h_vlan_TCI; ++ vlanid = (vlan_TCI & VLAN_VID_MASK)>>8; ++ if(vlanid == 2)//to wan ++ { ++ cpu_ptr->txd_info3.QID += 8; ++#if defined (CONFIG_HW_SFQ) ++ if(web_sfq_enable==1 &&(skb->mark == 2)){ ++ cpu_ptr->txd_info3.QID = HwSfqQUp; ++ } ++#endif ++ }else if(vlanid == 1){ //to lan ++#if defined (CONFIG_HW_SFQ) ++ if(web_sfq_enable==1 &&(skb->mark == 2)){ ++ cpu_ptr->txd_info3.QID = HwSfqQDl; ++ } ++#endif ++ } ++ } ++#endif ++#endif ++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) ++ if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) { ++ if(ra_sw_nat_hook_rx!= NULL){ ++ cpu_ptr->txd_info4.FPORT = 4; /* PPE */ ++ FOE_MAGIC_TAG(skb) = 0; ++ } ++ } ++#endif ++#if 0 ++ cpu_ptr->txd_info4.FPORT = 4; /* PPE */ ++ cpu_ptr->txd_info4.UDF = 0x2F; ++#endif ++ ++#if defined (CONFIG_MIPS) ++ dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE); ++#else ++ dma_sync_single_for_device(NULL, virt_to_phys(skb->data), skb->len, DMA_TO_DEVICE); ++#endif ++ cpu_ptr->txd_info3.SWC_bit = 1; ++ ++ //3. get NULL TXD and decrease free_tx_num by 1. ++ ctx_offset = get_free_txd(&free_txd); ++ if(ctx_offset == NUM_TX_DESC) { ++ printk("get_free_txd fail\n"); // this should not happen. free_txd_num is 2 at least. ++ return 0; ++ } ++ ++ //4. hook new TXD in the end of queue ++ //cpu_ptr->txd_info2.NDP = VIRT_TO_PHYS(free_txd); ++ cpu_ptr->txd_info2.NDP = (free_txd); ++ ++ ++ //5. move CPU_PTR to new TXD ++ //ei_local->tx_cpu_ptr = VIRT_TO_PHYS(free_txd); ++ ei_local->tx_cpu_ptr = (free_txd); ++ cpu_ptr->txd_info3.OWN_bit = 0; ++ sysRegWrite(QTX_CTX_PTR, ei_local->tx_cpu_ptr); ++ ++#if 0 ++ printk("----------------------------------------------\n"); ++ printk("txd_info1:%08X \n",*(int *)&cpu_ptr->txd_info1); ++ printk("txd_info2:%08X \n",*(int *)&cpu_ptr->txd_info2); ++ printk("txd_info3:%08X \n",*(int *)&cpu_ptr->txd_info3); ++ printk("txd_info4:%08X \n",*(int *)&cpu_ptr->txd_info4); ++#endif ++ ++#else //#if !defined (CONFIG_RAETH_TSO) ++ cpu_ptr->txd_info1.SDP = virt_to_phys(skb->data); ++ cpu_ptr->txd_info3.SDL = (length - skb->data_len); ++ cpu_ptr->txd_info3.LS_bit = nr_frags ? 0:1; ++#if defined (CONFIG_HW_SFQ) ++ SfqParseLayerInfo(skb); ++ // printk("tcp_source_port=%d\n", tcp_source_port); ++#if(0) ++ cpu_ptr->txd_info4.VQID0 = 0;//1:HW hash 0:CPU ++ if (tcp_source_port==1000) cpu_ptr->txd_info3.VQID = 0; ++ else if (tcp_source_port==1100) cpu_ptr->txd_info3.VQID = 1; ++ else if (tcp_source_port==1200) cpu_ptr->txd_info3.VQID = 2; ++ else cpu_ptr->txd_info3.VQID = 0; ++ #else ++ cpu_ptr->txd_info4.VQID0 = 1; ++ cpu_ptr->txd_info3.PROT = sfq_prot; ++ cpu_ptr->txd_info3.IPOFST = 14 + (SfqParseResult.vlan1_gap); //no vlan ++#endif ++#endif ++ if (gmac_no == 1) { ++ cpu_ptr->txd_info4.FPORT = 1; ++ }else { ++ cpu_ptr->txd_info4.FPORT = 2; ++ } ++ ++ cpu_ptr->txd_info4.TSO = 0; ++ cpu_ptr->txd_info3.QID = M2Q_table[skb->mark]; ++#ifdef CONFIG_PSEUDO_SUPPORT //web UI used tso ++ if((lan_wan_separate==1) && (gmac_no==2)){ ++ cpu_ptr->txd_info3.QID += 8; ++#if defined (CONFIG_HW_SFQ) ++ if(web_sfq_enable == 1 &&(skb->mark == 2)){ ++ cpu_ptr->txd_info3.QID = HwSfqQUp; ++ } ++#endif ++ } ++#if defined (CONFIG_HW_SFQ) ++ if((lan_wan_separate==1) && (gmac_no==1)){ ++ if(web_sfq_enable==1 &&(skb->mark == 2)){ ++ cpu_ptr->txd_info3.QID = HwSfqQDl; ++ } ++ } ++#endif ++#endif //CONFIG_PSEUDO_SUPPORT ++ if(dbg==1){ ++ printk("M2Q_table[%d]=%d\n", skb->mark, M2Q_table[skb->mark]); ++ printk("cpu_ptr->txd_info3.QID = %d\n", cpu_ptr->txd_info3.QID); ++ } ++#if defined (CONFIG_RAETH_CHECKSUM_OFFLOAD) && ! defined(CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628) ++ if (skb->ip_summed == CHECKSUM_PARTIAL){ ++ cpu_ptr->txd_info4.TUI_CO = 7; ++ }else { ++ cpu_ptr->txd_info4.TUI_CO = 0; ++ } ++#endif ++ ++#ifdef CONFIG_RAETH_HW_VLAN_TX ++ if(vlan_tx_tag_present(skb)) { ++ cpu_ptr->txd_info4.VLAN_TAG = 0x10000 | vlan_tx_tag_get(skb); ++ }else { ++ cpu_ptr->txd_info4.VLAN_TAG = 0; ++ } ++#endif ++#ifdef CONFIG_RAETH_HW_VLAN_TX // QoS Web UI used tso ++ ++ if((lan_wan_separate==1) && (vlan_tx_tag_get(skb)==2)){ ++ //cpu_ptr->txd_info3.QID += 8; ++ cpu_ptr->txd_info3.QID += 8; ++#if defined (CONFIG_HW_SFQ) ++ if(web_sfq_enable==1 &&(skb->mark == 2)){ ++ cpu_ptr->txd_info3.QID = HwSfqQUp; ++ } ++#endif ++ } ++#if defined (CONFIG_HW_SFQ) ++ if((lan_wan_separate==1) && (vlan_tx_tag_get(skb)==1)){ ++ if(web_sfq_enable==1 &&(skb->mark == 2)){ ++ cpu_ptr->txd_info3.QID = HwSfqQDl; ++ } ++ } ++#endif ++#endif // CONFIG_RAETH_HW_VLAN_TX ++ ++ ++//no hw van, no GE2, web UI used ++#ifndef CONFIG_PSEUDO_SUPPORT ++#ifndef CONFIG_RAETH_HW_VLAN_TX ++ if(lan_wan_separate==1){ ++ struct vlan_hdr *vh = NULL; ++ unsigned short vlanid = 0; ++ unsigned short vlan_TCI; ++ vh = (struct vlan_hdr *)(skb->data + ETH_HLEN); ++ vlan_TCI = vh->h_vlan_TCI; ++ vlanid = (vlan_TCI & VLAN_VID_MASK)>>8; ++ if(vlanid == 2)//eth2.2 to wan ++ { ++ cpu_ptr->txd_info3.QID += 8; ++#if defined (CONFIG_HW_SFQ) ++ if(web_sfq_enable==1 &&(skb->mark == 2)){ ++ cpu_ptr->txd_info3.QID = HwSfqQUp; ++ } ++#endif ++ }else if(!strcmp(netdev, "eth2.1")){ // eth2.1 to lan ++#if defined (CONFIG_HW_SFQ) ++ if(web_sfq_enable==1 &&(skb->mark == 2)){ ++ cpu_ptr->txd_info3.QID = HwSfqQDl; ++ } ++#endif ++ } ++} ++#endif ++#endif ++ ++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) ++ if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) { ++ if(ra_sw_nat_hook_rx!= NULL){ ++ cpu_ptr->txd_info4.FPORT = 4; /* PPE */ ++ FOE_MAGIC_TAG(skb) = 0; ++ } ++ } ++#endif ++ ++ cpu_ptr->txd_info3.SWC_bit = 1; ++ ++ ctx_offset = get_free_txd(&free_txd); ++ if(ctx_offset == NUM_TX_DESC) { ++ printk("get_free_txd fail\n"); ++ return 0; ++ } ++ //cpu_ptr->txd_info2.NDP = VIRT_TO_PHYS(free_txd); ++ //ei_local->tx_cpu_ptr = VIRT_TO_PHYS(free_txd); ++ cpu_ptr->txd_info2.NDP = free_txd; ++ ei_local->tx_cpu_ptr = free_txd; ++ ++ ++ if(nr_frags > 0) { ++ for(i=0;ifrags[i]; ++ len = frag->size; ++ frag_txd_num = cal_frag_txd_num(len); // calculate the needed TXD numbers for this fragment ++ for(frag_txd_num = frag_txd_num;frag_txd_num > 0; frag_txd_num --){ ++ // 2. size will be assigned to SDL and can't be larger than MAX_TXD_LEN ++ if(len < MAX_TXD_LEN) ++ size = len; ++ else ++ size = MAX_TXD_LEN; ++ ++ //3. Update TXD info ++ cpu_ptr = (ei_local->txd_pool + (ctx_offset)); ++ cpu_ptr->txd_info3.QID = M2Q_table[skb->mark]; ++#ifdef CONFIG_PSEUDO_SUPPORT //QoS Web UI used , nr_frags ++ if((lan_wan_separate==1) && (gmac_no==2)){ ++ //cpu_ptr->txd_info3.QID += 8; ++ cpu_ptr->txd_info3.QID += 8; ++#if defined (CONFIG_HW_SFQ) ++ if(web_sfq_enable==1 &&(skb->mark == 2)){ ++ cpu_ptr->txd_info3.QID = HwSfqQUp; ++ } ++#endif ++ } ++#if defined (CONFIG_HW_SFQ) ++ if((lan_wan_separate==1) && (gmac_no==1)){ ++ if(web_sfq_enable==1 &&(skb->mark == 2)){ ++ cpu_ptr->txd_info3.QID = HwSfqQDl; ++ } ++ } ++#endif ++#endif //CONFIG_PSEUDO_SUPPORT ++ ++//QoS web used, nr_frags ++#ifdef CONFIG_RAETH_HW_VLAN_TX ++ if((lan_wan_separate==1) && (vlan_tx_tag_get(skb)==2)){ ++ cpu_ptr->txd_info3.QID += 8; ++#if defined (CONFIG_HW_SFQ) ++ if(web_sfq_enable==1 &&(skb->mark == 2)){ ++ cpu_ptr->txd_info3.QID = HwSfqQUp; ++ } ++#endif ++ } ++#if defined (CONFIG_HW_SFQ) ++ if((lan_wan_separate==1) && (vlan_tx_tag_get(skb)==1)){ ++ if(web_sfq_enable==1 &&(skb->mark == 2)){ ++ cpu_ptr->txd_info3.QID = HwSfqQDl; ++ } ++ } ++#endif ++#endif // CONFIG_RAETH_HW_VLAN_TX ++//no hw van, no GE2, web UI used ++#ifndef CONFIG_PSEUDO_SUPPORT ++#ifndef CONFIG_RAETH_HW_VLAN_TX ++ if(lan_wan_separate==1){ ++ struct vlan_hdr *vh = NULL; ++ unsigned short vlanid = 0; ++ unsigned short vlan_TCI; ++ vh = (struct vlan_hdr *)(skb->data + ETH_HLEN); ++ vlan_TCI = vh->h_vlan_TCI; ++ vlanid = (vlan_TCI & VLAN_VID_MASK)>>8; ++ if(vlanid == 2))//eth2.2 to wan ++ { ++ cpu_ptr->txd_info3.QID += 8; ++#if defined (CONFIG_HW_SFQ) ++ if(web_sfq_enable==1 &&(skb->mark == 2)){ ++ cpu_ptr->txd_info3.QID = HwSfqQUp; ++ } ++#endif ++ } ++ }else if(vlanid == 1){ // eth2.1 to lan ++#if defined (CONFIG_HW_SFQ) ++ if(web_sfq_enable==1 &&(skb->mark == 2)){ ++ cpu_ptr->txd_info3.QID = HwSfqQDl; ++ } ++#endif ++ } ++ } ++#endif ++#endif ++ if(dbg==1){ ++ printk("M2Q_table[%d]=%d\n", skb->mark, M2Q_table[skb->mark]); ++ printk("cpu_ptr->txd_info3.QID = %d\n", cpu_ptr->txd_info3.QID); ++ } ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) ++ cpu_ptr->txd_info1.SDP = pci_map_page(NULL, frag->page, frag->page_offset, frag->size, PCI_DMA_TODEVICE); ++#else ++ cpu_ptr->txd_info1.SDP = pci_map_page(NULL, frag->page.p, frag->page_offset + offset, size, PCI_DMA_TODEVICE); ++// printk(" frag->page = %08x. frag->page_offset = %08x. frag->size = % 08x.\n", frag->page, (frag->page_offset+offset), size); ++#endif ++ cpu_ptr->txd_info3.SDL = size; ++ if( (i==(nr_frags-1)) && (frag_txd_num == 1)) ++ cpu_ptr->txd_info3.LS_bit = 1; ++ else ++ cpu_ptr->txd_info3.LS_bit = 0; ++ cpu_ptr->txd_info3.OWN_bit = 0; ++ cpu_ptr->txd_info3.SWC_bit = 1; ++ //4. Update skb_free for housekeeping ++ ei_local->skb_free[ctx_offset] = (cpu_ptr->txd_info3.LS_bit == 1)?skb:(struct sk_buff *)0xFFFFFFFF; //MAGIC ID ++ ++ //5. Get next TXD ++ ctx_offset = get_free_txd(&free_txd); ++ //cpu_ptr->txd_info2.NDP = VIRT_TO_PHYS(free_txd); ++ //ei_local->tx_cpu_ptr = VIRT_TO_PHYS(free_txd); ++ cpu_ptr->txd_info2.NDP = free_txd; ++ ei_local->tx_cpu_ptr = free_txd; ++ //6. Update offset and len. ++ offset += size; ++ len -= size; ++ } ++ } ++ ei_local->skb_free[init_txd_idx]= (struct sk_buff *)0xFFFFFFFF; //MAGIC ID ++ } ++ ++ if(skb_shinfo(skb)->gso_segs > 1) { ++ ++// TsoLenUpdate(skb->len); ++ ++ /* TCP over IPv4 */ ++ iph = (struct iphdr *)skb_network_header(skb); ++#if defined (CONFIG_RAETH_TSOV6) ++ /* TCP over IPv6 */ ++ ip6h = (struct ipv6hdr *)skb_network_header(skb); ++#endif ++ if((iph->version == 4) && (iph->protocol == IPPROTO_TCP)) { ++ th = (struct tcphdr *)skb_transport_header(skb); ++#if defined (CONFIG_HW_SFQ) ++#if(0) ++ init_cpu_ptr->txd_info4.VQID0 = 0;//1:HW hash 0:CPU ++ if (tcp_source_port==1000) init_cpu_ptr->txd_info3.VQID = 0; ++ else if (tcp_source_port==1100) init_cpu_ptr->txd_info3.VQID = 1; ++ else if (tcp_source_port==1200) init_cpu_ptr->txd_info3.VQID = 2; ++ else cpu_ptr->txd_info3.VQID = 0; ++ #else ++ init_cpu_ptr->txd_info4.VQID0 = 1; ++ init_cpu_ptr->txd_info3.PROT = sfq_prot; ++ init_cpu_ptr->txd_info3.IPOFST = 14 + (SfqParseResult.vlan1_gap); //no vlan ++#endif ++#endif ++ init_cpu_ptr->txd_info4.TSO = 1; ++ ++ th->check = htons(skb_shinfo(skb)->gso_size); ++#if defined (CONFIG_MIPS) ++ dma_cache_sync(NULL, th, sizeof(struct tcphdr), DMA_TO_DEVICE); ++#else ++ dma_sync_single_for_device(NULL, virt_to_phys(th), sizeof(struct tcphdr), DMA_TO_DEVICE); ++#endif ++ } ++ ++#if defined (CONFIG_RAETH_TSOV6) ++ /* TCP over IPv6 */ ++ //ip6h = (struct ipv6hdr *)skb_network_header(skb); ++ else if ((ip6h->version == 6) && (ip6h->nexthdr == NEXTHDR_TCP)) { ++ th = (struct tcphdr *)skb_transport_header(skb); ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ init_cpu_ptr->txd_info4.TSO = 1; ++#else ++ init_cpu_ptr->txd_info4.TSO = 1; ++#endif ++ th->check = htons(skb_shinfo(skb)->gso_size); ++#if defined (CONFIG_MIPS) ++ dma_cache_sync(NULL, th, sizeof(struct tcphdr), DMA_TO_DEVICE); ++#else ++ dma_sync_single_for_device(NULL, virt_to_phys(th), sizeof(struct tcphdr), DMA_TO_DEVICE); ++#endif ++ } ++#endif ++ } ++ ++ ++// dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE); ++ ++ init_cpu_ptr->txd_info3.OWN_bit = 0; ++#endif // CONFIG_RAETH_TSO // ++ ++ sysRegWrite(QTX_CTX_PTR, ei_local->tx_cpu_ptr); ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++ if (gmac_no == 2) { ++ if (ei_local->PseudoDev != NULL) { ++ pAd = netdev_priv(ei_local->PseudoDev); ++ pAd->stat.tx_packets++; ++ pAd->stat.tx_bytes += length; ++ } ++ } else ++ ++#endif ++ { ++ ei_local->stat.tx_packets++; ++ ei_local->stat.tx_bytes += skb->len; ++ } ++#ifdef CONFIG_RAETH_NAPI ++ if ( ei_local->tx_full == 1) { ++ ei_local->tx_full = 0; ++ netif_wake_queue(dev); ++ } ++#endif ++ ++ return length; ++} ++ ++int ei_start_xmit(struct sk_buff* skb, struct net_device *dev, int gmac_no) ++{ ++ END_DEVICE *ei_local = netdev_priv(dev); ++ unsigned long flags; ++ unsigned int num_of_txd = 0; ++#if defined (CONFIG_RAETH_TSO) ++ unsigned int nr_frags = skb_shinfo(skb)->nr_frags, i; ++ struct skb_frag_struct *frag; ++#endif ++#ifdef CONFIG_PSEUDO_SUPPORT ++ PSEUDO_ADAPTER *pAd; ++#endif ++ ++#if !defined(CONFIG_RA_NAT_NONE) ++ if(ra_sw_nat_hook_tx!= NULL) ++ { ++// spin_lock_irqsave(&ei_local->page_lock, flags); ++ if(ra_sw_nat_hook_tx(skb, gmac_no)==1){ ++// spin_unlock_irqrestore(&ei_local->page_lock, flags); ++ }else{ ++ kfree_skb(skb); ++// spin_unlock_irqrestore(&ei_local->page_lock, flags); ++ return 0; ++ } ++ } ++#endif ++ ++ ++ ++ dev->trans_start = jiffies; /* save the timestamp */ ++ spin_lock_irqsave(&ei_local->page_lock, flags); ++#if defined (CONFIG_MIPS) ++ dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE); ++#else ++ dma_sync_single_for_device(NULL, virt_to_phys(skb->data), skb->len, DMA_TO_DEVICE); ++#endif ++ ++ ++//check free_txd_num before calling rt288_eth_send() ++ ++#if defined (CONFIG_RAETH_TSO) ++ // num_of_txd = (nr_frags==0) ? 1 : (nr_frags + 1); ++ if(nr_frags != 0){ ++ for(i=0;ifrags[i]; ++ num_of_txd += cal_frag_txd_num(frag->size); ++ } ++ }else ++ num_of_txd = 1; ++#else ++ num_of_txd = 1; ++#endif ++ ++#if defined(CONFIG_RALINK_MT7621) ++ if((sysRegRead(0xbe00000c)&0xFFFF) == 0x0101) { ++ ei_xmit_housekeeping(0); ++ } ++#endif ++ ++ ++ if ((ei_local->free_txd_num > num_of_txd + 1) && (ei_local->free_txd_num != NUM_TX_DESC)) ++ { ++ rt2880_eth_send(dev, skb, gmac_no); // need to modify rt2880_eth_send() for QDMA ++ if (ei_local->free_txd_num < 3) ++ { ++#if defined (CONFIG_RAETH_STOP_RX_WHEN_TX_FULL) ++ netif_stop_queue(dev); ++#ifdef CONFIG_PSEUDO_SUPPORT ++ netif_stop_queue(ei_local->PseudoDev); ++#endif ++ tx_ring_full = 1; ++#endif ++ } ++ } else { ++#ifdef CONFIG_PSEUDO_SUPPORT ++ if (gmac_no == 2) ++ { ++ if (ei_local->PseudoDev != NULL) ++ { ++ pAd = netdev_priv(ei_local->PseudoDev); ++ pAd->stat.tx_dropped++; ++ } ++ } else ++#endif ++ ei_local->stat.tx_dropped++; ++ kfree_skb(skb); ++ spin_unlock_irqrestore(&ei_local->page_lock, flags); ++ return 0; ++ } ++ spin_unlock_irqrestore(&ei_local->page_lock, flags); ++ return 0; ++} ++ ++void ei_xmit_housekeeping(unsigned long unused) ++{ ++ struct net_device *dev = dev_raether; ++ END_DEVICE *ei_local = netdev_priv(dev); ++#ifndef CONFIG_RAETH_NAPI ++ unsigned long reg_int_mask=0; ++#endif ++ struct QDMA_txdesc *dma_ptr = NULL; ++ struct QDMA_txdesc *cpu_ptr = NULL; ++ struct QDMA_txdesc *tmp_ptr = NULL; ++ unsigned int ctx_offset = 0; ++ unsigned int dtx_offset = 0; ++ ++ cpu_ptr = sysRegRead(QTX_CRX_PTR); ++ dma_ptr = sysRegRead(QTX_DRX_PTR); ++ ctx_offset = GET_TXD_OFFSET(&cpu_ptr); ++ dtx_offset = GET_TXD_OFFSET(&dma_ptr); ++ cpu_ptr = (ei_local->txd_pool + (ctx_offset)); ++ dma_ptr = (ei_local->txd_pool + (dtx_offset)); ++ ++ while(cpu_ptr != dma_ptr && (cpu_ptr->txd_info3.OWN_bit == 1)) { ++ //1. keep cpu next TXD ++ tmp_ptr = cpu_ptr->txd_info2.NDP; ++ //2. release TXD ++ put_free_txd(ctx_offset); ++ //3. update ctx_offset and free skb memory ++ ctx_offset = GET_TXD_OFFSET(&tmp_ptr); ++#if defined (CONFIG_RAETH_TSO) ++ if(ei_local->skb_free[ctx_offset]!=(struct sk_buff *)0xFFFFFFFF) { ++ dev_kfree_skb_any(ei_local->skb_free[ctx_offset]); ++ } ++#else ++ dev_kfree_skb_any(ei_local->skb_free[ctx_offset]); ++#endif ++ ei_local->skb_free[ctx_offset] = 0; ++ ++ netif_wake_queue(dev); ++#ifdef CONFIG_PSEUDO_SUPPORT ++ netif_wake_queue(ei_local->PseudoDev); ++#endif ++ tx_ring_full=0; ++ //4. update cpu_ptr ++ cpu_ptr = (ei_local->txd_pool + ctx_offset); ++ } ++ sysRegWrite(QTX_CRX_PTR, (ei_local->phy_txd_pool + (ctx_offset << 4))); ++#ifndef CONFIG_RAETH_NAPI ++ reg_int_mask=sysRegRead(QFE_INT_ENABLE); ++#if defined (DELAY_INT) ++ sysRegWrite(QFE_INT_ENABLE, reg_int_mask| RLS_DLY_INT); ++#else ++ ++ sysRegWrite(QFE_INT_ENABLE, reg_int_mask | RLS_DONE_INT); ++#endif ++#endif //CONFIG_RAETH_NAPI// ++} ++ ++EXPORT_SYMBOL(ei_start_xmit); ++EXPORT_SYMBOL(ei_xmit_housekeeping); ++EXPORT_SYMBOL(fe_dma_init); ++EXPORT_SYMBOL(rt2880_eth_send); +diff --git a/drivers/net/ethernet/raeth/raether_qdma_mt7623.c b/drivers/net/ethernet/raeth/raether_qdma_mt7623.c +new file mode 100644 +index 0000000..b465b75 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/raether_qdma_mt7623.c +@@ -0,0 +1,1020 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if defined (CONFIG_RAETH_TSO) ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#endif ++#include ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++#include ++#endif ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) ++#include ++#else ++#include ++#endif ++ ++#include "ra2882ethreg.h" ++#include "raether.h" ++#include "ra_mac.h" ++#include "ra_ioctl.h" ++#include "ra_rfrw.h" ++#ifdef CONFIG_RAETH_NETLINK ++#include "ra_netlink.h" ++#endif ++#if defined (CONFIG_RAETH_QOS) ++#include "ra_qos.h" ++#endif ++ ++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) ++#include "../../../net/nat/hw_nat/ra_nat.h" ++#endif ++ ++ ++#if !defined(CONFIG_RA_NAT_NONE) ++/* bruce+ ++ */ ++extern int (*ra_sw_nat_hook_rx)(struct sk_buff *skb); ++extern int (*ra_sw_nat_hook_tx)(struct sk_buff *skb, int gmac_no); ++#endif ++ ++#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE) ++/* Qwert+ ++ */ ++#include ++extern int (*ra_classifier_hook_tx)(struct sk_buff *skb, unsigned long cur_cycle); ++extern int (*ra_classifier_hook_rx)(struct sk_buff *skb, unsigned long cur_cycle); ++#endif /* CONFIG_RA_CLASSIFIER */ ++ ++#if defined (CONFIG_RALINK_RT3052_MP2) ++int32_t mcast_rx(struct sk_buff * skb); ++int32_t mcast_tx(struct sk_buff * skb); ++#endif ++ ++#ifdef RA_MTD_RW_BY_NUM ++int ra_mtd_read(int num, loff_t from, size_t len, u_char *buf); ++#else ++int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf); ++#endif ++ ++/* gmac driver feature set config */ ++#if defined (CONFIG_RAETH_NAPI) || defined (CONFIG_RAETH_QOS) ++#undef DELAY_INT ++#else ++#define DELAY_INT 1 ++#endif ++ ++//#define CONFIG_UNH_TEST ++/* end of config */ ++ ++#if defined (CONFIG_RAETH_JUMBOFRAME) ++#define MAX_RX_LENGTH 4096 ++#else ++#define MAX_RX_LENGTH 1536 ++#endif ++ ++extern struct net_device *dev_raether; ++ ++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++static int rx_dma_owner_idx1; ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++static int rx_calc_idx1; ++#endif ++#endif ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++static int rx_calc_idx0; ++static unsigned long tx_cpu_owner_idx0=0; ++#endif ++static unsigned long tx_ring_full=0; ++ ++#if defined (CONFIG_ETHTOOL) && defined (CONFIG_RAETH_ROUTER) ++#include "ra_ethtool.h" ++extern struct ethtool_ops ra_ethtool_ops; ++#ifdef CONFIG_PSEUDO_SUPPORT ++extern struct ethtool_ops ra_virt_ethtool_ops; ++#endif // CONFIG_PSEUDO_SUPPORT // ++#endif // (CONFIG_ETHTOOL // ++ ++#ifdef CONFIG_RALINK_VISTA_BASIC ++int is_switch_175c = 1; ++#endif ++ ++//skb->mark to queue mapping table ++extern unsigned int M2Q_table[64]; ++ ++ ++#define KSEG1 0xa0000000 ++#if defined (CONFIG_MIPS) ++#define PHYS_TO_VIRT(x) ((void *)((x) | KSEG1)) ++#define VIRT_TO_PHYS(x) ((unsigned long)(x) & ~KSEG1) ++#else ++#define PHYS_TO_VIRT(x) phys_to_virt(x) ++#define VIRT_TO_PHYS(x) virt_to_phys(x) ++#endif ++ ++ ++extern void set_fe_dma_glo_cfg(void); ++ ++ ++/** ++ * ++ * @brief: get the TXD index from its address ++ * ++ * @param: cpu_ptr ++ * ++ * @return: TXD index ++*/ ++ ++static unsigned int GET_TXD_OFFSET(struct QDMA_txdesc **cpu_ptr) ++{ ++ struct net_device *dev = dev_raether; ++ END_DEVICE *ei_local = netdev_priv(dev); ++ int ctx_offset; ++ //ctx_offset = (((((u32)*cpu_ptr) <<8)>>8) - ((((u32)ei_local->txd_pool)<<8)>>8))/ sizeof(struct QDMA_txdesc); ++ //ctx_offset = (*cpu_ptr - ei_local->txd_pool); ++ /*kurtis*/ ++ ctx_offset = (((((u32)*cpu_ptr) <<8)>>8) - ((((u32)ei_local->phy_txd_pool)<<8)>>8))/ sizeof(struct QDMA_txdesc); ++ return ctx_offset; ++} ++ ++ ++ ++ ++/** ++ * @brief cal txd number for a page ++ * ++ * @parm size ++ * ++ * @return frag_txd_num ++ */ ++ ++unsigned int cal_frag_txd_num(unsigned int size) ++{ ++ unsigned int frag_txd_num = 0; ++ if(size == 0) ++ return 0; ++ while(size > 0){ ++ if(size > MAX_TXD_LEN){ ++ frag_txd_num++; ++ size -= MAX_TXD_LEN; ++ }else{ ++ frag_txd_num++; ++ size = 0; ++ } ++ } ++ return frag_txd_num; ++ ++} ++ ++/** ++ * @brief get free TXD from TXD queue ++ * ++ * @param free_txd ++ * ++ * @return ++ */ ++static int get_free_txd(struct QDMA_txdesc **free_txd) ++{ ++ struct net_device *dev = dev_raether; ++ END_DEVICE *ei_local = netdev_priv(dev); ++ unsigned int tmp_idx; ++ ++ if(ei_local->free_txd_num > 0){ ++ tmp_idx = ei_local->free_txd_head; ++ ei_local->free_txd_head = ei_local->txd_pool_info[tmp_idx]; ++ ei_local->free_txd_num -= 1; ++ //*free_txd = &ei_local->txd_pool[tmp_idx]; ++ *free_txd = ei_local->phy_txd_pool + (sizeof(struct QDMA_txdesc) * tmp_idx); ++ return tmp_idx; ++ }else ++ return NUM_TX_DESC; ++} ++ ++ ++/** ++ * @brief add free TXD into TXD queue ++ * ++ * @param free_txd ++ * ++ * @return ++ */ ++int put_free_txd(int free_txd_idx) ++{ ++ struct net_device *dev = dev_raether; ++ END_DEVICE *ei_local = netdev_priv(dev); ++ ei_local->txd_pool_info[ei_local->free_txd_tail] = free_txd_idx; ++ ei_local->free_txd_tail = free_txd_idx; ++ ei_local->txd_pool_info[free_txd_idx] = NUM_TX_DESC; ++ ei_local->free_txd_num += 1; ++ return 1; ++} ++ ++/*define qdma initial alloc*/ ++/** ++ * @brief ++ * ++ * @param net_dev ++ * ++ * @return 0: fail ++ * 1: success ++ */ ++bool qdma_tx_desc_alloc(void) ++{ ++ struct net_device *dev = dev_raether; ++ END_DEVICE *ei_local = netdev_priv(dev); ++ struct QDMA_txdesc *free_txd = NULL; ++ unsigned int txd_idx; ++ int i = 0; ++ ++ ++ ei_local->txd_pool = pci_alloc_consistent(NULL, sizeof(struct QDMA_txdesc) * NUM_TX_DESC, &ei_local->phy_txd_pool); ++ printk("txd_pool=%p phy_txd_pool=%08X\n", ei_local->txd_pool , ei_local->phy_txd_pool); ++ ++ if (ei_local->txd_pool == NULL) { ++ printk("adapter->txd_pool allocation failed!\n"); ++ return 0; ++ } ++ printk("ei_local->skb_free start address is 0x%p.\n", ei_local->skb_free); ++ //set all txd_pool_info to 0. ++ for ( i = 0; i < NUM_TX_DESC; i++) ++ { ++ ei_local->skb_free[i]= 0; ++ ei_local->txd_pool_info[i] = i + 1; ++ ei_local->txd_pool[i].txd_info3.LS_bit = 1; ++ ei_local->txd_pool[i].txd_info3.OWN_bit = 1; ++ } ++ ++ ei_local->free_txd_head = 0; ++ ei_local->free_txd_tail = NUM_TX_DESC - 1; ++ ei_local->free_txd_num = NUM_TX_DESC; ++ ++ ++ //get free txd from txd pool ++ txd_idx = get_free_txd(&free_txd); ++ if( txd_idx == NUM_TX_DESC) { ++ printk("get_free_txd fail\n"); ++ return 0; ++ } ++ ++ //add null TXD for transmit ++ ++ /*kurtis test*/ ++ ei_local->tx_dma_ptr = free_txd; ++ ei_local->tx_cpu_ptr = free_txd; ++ //ei_local->tx_dma_ptr = virt_to_phys(free_txd); ++ //ei_local->tx_cpu_ptr = virt_to_phys(free_txd); ++ sysRegWrite(QTX_CTX_PTR, ei_local->tx_cpu_ptr); ++ sysRegWrite(QTX_DTX_PTR, ei_local->tx_dma_ptr); ++ ++ printk("kurtis: free_txd = 0x%x!!!\n", free_txd); ++ printk("kurtis: ei_local->tx_dma_ptr = 0x%x!!!\n", ei_local->tx_dma_ptr); ++ ++ //get free txd from txd pool ++ ++ txd_idx = get_free_txd(&free_txd); ++ if( txd_idx == NUM_TX_DESC) { ++ printk("get_free_txd fail\n"); ++ return 0; ++ } ++ // add null TXD for release ++ //sysRegWrite(QTX_CRX_PTR, virt_to_phys(free_txd)); ++ //sysRegWrite(QTX_DRX_PTR, virt_to_phys(free_txd)); ++ sysRegWrite(QTX_CRX_PTR, free_txd); ++ sysRegWrite(QTX_DRX_PTR, free_txd); ++ ++ printk("free_txd: %p, ei_local->cpu_ptr: %08X\n", free_txd, ei_local->tx_cpu_ptr); ++ ++ printk(" POOL HEAD_PTR | DMA_PTR | CPU_PTR \n"); ++ printk("----------------+---------+--------\n"); ++#if 1 ++ printk(" 0x%p 0x%08X 0x%08X\n",ei_local->txd_pool, ++ ei_local->tx_dma_ptr, ei_local->tx_cpu_ptr); ++#endif ++ return 1; ++} ++ ++bool fq_qdma_init(void) ++{ ++ struct QDMA_txdesc *free_head = NULL; ++ unsigned int free_head_phy; ++ unsigned int free_tail_phy; ++ unsigned int *free_page_head = NULL; ++ unsigned int free_page_head_phy; ++ int i; ++ ++ free_head = pci_alloc_consistent(NULL, NUM_QDMA_PAGE * sizeof(struct QDMA_txdesc), &free_head_phy); ++ if (unlikely(free_head == NULL)){ ++ printk(KERN_ERR "QDMA FQ decriptor not available...\n"); ++ return 0; ++ } ++ memset(free_head, 0x0, sizeof(struct QDMA_txdesc) * NUM_QDMA_PAGE); ++ ++ free_page_head = pci_alloc_consistent(NULL, NUM_QDMA_PAGE * QDMA_PAGE_SIZE, &free_page_head_phy); ++ if (unlikely(free_page_head == NULL)){ ++ printk(KERN_ERR "QDMA FQ pager not available...\n"); ++ return 0; ++ } ++ for (i=0; i < NUM_QDMA_PAGE; i++) { ++ free_head[i].txd_info1.SDP = (free_page_head_phy + (i * QDMA_PAGE_SIZE)); ++ if(i < (NUM_QDMA_PAGE-1)){ ++ free_head[i].txd_info2.NDP = (free_head_phy + ((i+1) * sizeof(struct QDMA_txdesc))); ++ ++ ++#if 0 ++ printk("free_head_phy[%d] is 0x%x!!!\n",i, VIRT_TO_PHYS(&free_head[i]) ); ++ printk("free_head[%d] is 0x%x!!!\n",i, &free_head[i] ); ++ printk("free_head[%d].txd_info1.SDP is 0x%x!!!\n",i, free_head[i].txd_info1.SDP ); ++ printk("free_head[%d].txd_info2.NDP is 0x%x!!!\n",i, free_head[i].txd_info2.NDP ); ++#endif ++ } ++ free_head[i].txd_info3.SDL = QDMA_PAGE_SIZE; ++ ++ } ++ free_tail_phy = (free_head_phy + (u32)((NUM_QDMA_PAGE-1) * sizeof(struct QDMA_txdesc))); ++ ++ printk("free_head_phy is 0x%x!!!\n", free_head_phy); ++ printk("free_tail_phy is 0x%x!!!\n", free_tail_phy); ++ sysRegWrite(QDMA_FQ_HEAD, (u32)free_head_phy); ++ sysRegWrite(QDMA_FQ_TAIL, (u32)free_tail_phy); ++ sysRegWrite(QDMA_FQ_CNT, ((NUM_TX_DESC << 16) | NUM_QDMA_PAGE)); ++ sysRegWrite(QDMA_FQ_BLEN, QDMA_PAGE_SIZE << 16); ++ return 1; ++} ++ ++int fe_dma_init(struct net_device *dev) ++{ ++ ++ int i; ++ unsigned int regVal; ++ END_DEVICE* ei_local = netdev_priv(dev); ++ ++ fq_qdma_init(); ++ ++ while(1) ++ { ++ regVal = sysRegRead(QDMA_GLO_CFG); ++ if((regVal & RX_DMA_BUSY)) ++ { ++ printk("\n RX_DMA_BUSY !!! "); ++ continue; ++ } ++ if((regVal & TX_DMA_BUSY)) ++ { ++ printk("\n TX_DMA_BUSY !!! "); ++ continue; ++ } ++ break; ++ } ++ /*tx desc alloc, add a NULL TXD to HW*/ ++ ++ qdma_tx_desc_alloc(); ++ ++ ++ /* Initial RX Ring 0*/ ++#ifdef CONFIG_32B_DESC ++ ei_local->rx_ring0 = kmalloc(NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL); ++ ei_local->phy_rx_ring0 = virt_to_phys(ei_local->rx_ring0); ++#else ++ ei_local->rx_ring0 = pci_alloc_consistent(NULL, NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring0); ++#endif ++ for (i = 0; i < NUM_QRX_DESC; i++) { ++ memset(&ei_local->rx_ring0[i],0,sizeof(struct PDMA_rxdesc)); ++ ei_local->rx_ring0[i].rxd_info2.DDONE_bit = 0; ++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA) ++ ei_local->rx_ring0[i].rxd_info2.LS0 = 0; ++ ei_local->rx_ring0[i].rxd_info2.PLEN0 = MAX_RX_LENGTH; ++#else ++ ei_local->rx_ring0[i].rxd_info2.LS0 = 1; ++#endif ++ ei_local->rx_ring0[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx0_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE); ++ } ++ printk("QDMA_RX:phy_rx_ring0 = 0x%08x, rx_ring0 = 0x%p\n",ei_local->phy_rx_ring0,ei_local->rx_ring0); ++ ++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++ /* Initial RX Ring 1*/ ++#ifdef CONFIG_32B_DESC ++ ei_local->rx_ring1 = kmalloc(NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL); ++ ei_local->phy_rx_ring1 = virt_to_phys(ei_local->rx_ring1); ++#else ++ ei_local->rx_ring1 = pci_alloc_consistent(NULL, NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring1); ++#endif ++ for (i = 0; i < NUM_QRX_DESC; i++) { ++ memset(&ei_local->rx_ring1[i],0,sizeof(struct PDMA_rxdesc)); ++ ei_local->rx_ring1[i].rxd_info2.DDONE_bit = 0; ++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA) ++ ei_local->rx_ring0[i].rxd_info2.LS0 = 0; ++ ei_local->rx_ring0[i].rxd_info2.PLEN0 = MAX_RX_LENGTH; ++#else ++ ei_local->rx_ring1[i].rxd_info2.LS0 = 1; ++#endif ++ ei_local->rx_ring1[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx1_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE); ++ } ++ printk("\nphy_rx_ring1 = 0x%08x, rx_ring1 = 0x%p\n",ei_local->phy_rx_ring1,ei_local->rx_ring1); ++#endif ++ ++ regVal = sysRegRead(QDMA_GLO_CFG); ++ regVal &= 0x000000FF; ++ sysRegWrite(QDMA_GLO_CFG, regVal); ++ regVal=sysRegRead(QDMA_GLO_CFG); ++ ++ /* Tell the adapter where the TX/RX rings are located. */ ++ ++ sysRegWrite(QRX_BASE_PTR_0, phys_to_bus((u32) ei_local->phy_rx_ring0)); ++ sysRegWrite(QRX_MAX_CNT_0, cpu_to_le32((u32) NUM_QRX_DESC)); ++ sysRegWrite(QRX_CRX_IDX_0, cpu_to_le32((u32) (NUM_QRX_DESC - 1))); ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ rx_calc_idx0 = rx_dma_owner_idx0 = sysRegRead(QRX_CRX_IDX_0); ++#endif ++ sysRegWrite(QDMA_RST_CFG, PST_DRX_IDX0); ++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING) ++ sysRegWrite(QRX_BASE_PTR_1, phys_to_bus((u32) ei_local->phy_rx_ring1)); ++ sysRegWrite(QRX_MAX_CNT_1, cpu_to_le32((u32) NUM_QRX_DESC)); ++ sysRegWrite(QRX_CRX_IDX_1, cpu_to_le32((u32) (NUM_QRX_DESC - 1))); ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ rx_calc_idx1 = rx_dma_owner_idx1 = sysRegRead(QRX_CRX_IDX_1); ++#endif ++ sysRegWrite(QDMA_RST_CFG, PST_DRX_IDX1); ++#endif ++ ++#if !defined (CONFIG_RAETH_QDMATX_QDMARX) ++ /* Initial PDMA RX Ring 0*/ ++#ifdef CONFIG_32B_DESC ++ ei_local->rx_ring0 = kmalloc(NUM_RX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL); ++ ei_local->phy_rx_ring0 = virt_to_phys(ei_local->rx_ring0); ++#else ++ ei_local->rx_ring0 = pci_alloc_consistent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring0); ++#endif ++ for (i = 0; i < NUM_RX_DESC; i++) { ++ memset(&ei_local->rx_ring0[i],0,sizeof(struct PDMA_rxdesc)); ++ ei_local->rx_ring0[i].rxd_info2.DDONE_bit = 0; ++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA) ++ ei_local->rx_ring0[i].rxd_info2.LS0 = 0; ++ ei_local->rx_ring0[i].rxd_info2.PLEN0 = MAX_RX_LENGTH; ++#else ++ ei_local->rx_ring0[i].rxd_info2.LS0 = 1; ++#endif ++ ei_local->rx_ring0[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx0_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE); ++ } ++ printk("PDMA_RX:phy_rx_ring0 = 0x%08x, rx_ring0 = 0x%p\n",ei_local->phy_rx_ring0,ei_local->rx_ring0); ++ ++ regVal = sysRegRead(PDMA_GLO_CFG); ++ regVal &= 0x000000FF; ++ sysRegWrite(PDMA_GLO_CFG, regVal); ++ regVal=sysRegRead(PDMA_GLO_CFG); ++ ++ sysRegWrite(RX_BASE_PTR0, phys_to_bus((u32) ei_local->phy_rx_ring0)); ++ sysRegWrite(RX_MAX_CNT0, cpu_to_le32((u32) NUM_RX_DESC)); ++ sysRegWrite(RX_CALC_IDX0, cpu_to_le32((u32) (NUM_RX_DESC - 1))); ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ rx_calc_idx0 = sysRegRead(RX_CALC_IDX0); ++#endif ++ sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX0); ++ ++#endif/*kurtis*/ ++ /* Enable randon early drop and set drop threshold automatically */ ++ sysRegWrite(QDMA_FC_THRES, 0x174444); ++ sysRegWrite(QDMA_HRED2, 0x0); ++ set_fe_dma_glo_cfg(); ++ ++ return 1; ++} ++ ++inline int rt2880_eth_send(struct net_device* dev, struct sk_buff *skb, int gmac_no) ++{ ++ unsigned int length=skb->len; ++ END_DEVICE* ei_local = netdev_priv(dev); ++ ++ struct QDMA_txdesc *cpu_ptr; ++ ++ struct QDMA_txdesc *dma_ptr __maybe_unused; ++ struct QDMA_txdesc *free_txd; ++ unsigned int ctx_offset = 0; ++ unsigned int dtx_offset = 0; ++#if defined (CONFIG_RAETH_TSO) ++ struct iphdr *iph = NULL; ++ struct QDMA_txdesc *init_cpu_ptr; ++ struct tcphdr *th = NULL; ++ struct skb_frag_struct *frag; ++ unsigned int nr_frags = skb_shinfo(skb)->nr_frags; ++ unsigned int len, size, offset, frag_txd_num; ++ int init_txd_idx, i; ++#endif // CONFIG_RAETH_TSO // ++ ++#if defined (CONFIG_RAETH_TSOV6) ++ struct ipv6hdr *ip6h = NULL; ++#endif ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++ PSEUDO_ADAPTER *pAd; ++#endif ++ cpu_ptr = (ei_local->tx_cpu_ptr); ++ ctx_offset = GET_TXD_OFFSET(&cpu_ptr); ++ cpu_ptr = phys_to_virt(ei_local->tx_cpu_ptr); ++ dma_ptr = phys_to_virt(ei_local->tx_dma_ptr); ++/*kurtis test*/ ++ //dma_ptr = (ei_local->tx_dma_ptr); ++ ++ ++ /*only modify virtual address*/ ++ //cpu_ptr = (ei_local->txd_pool) + (ctx_offset * sizeof(struct QDMA_txdesc)); ++ cpu_ptr = (ei_local->txd_pool + (ctx_offset)); ++ ++ //dtx_offset = GET_TXD_OFFSET(&dma_ptr); ++ //dma_ptr = (ei_local->txd_pool) + (dtx_offset * sizeof(struct QDMA_txdesc)); ++ ++ //printk("eth_send ctx_offset = 0x%x!!!\n", ctx_offset); ++ //printk("eth_send dtx_offset = 0x%x!!!\n", dtx_offset); ++ //printk("eth_send ei_local->txd_pool = 0x%x!!!\n", ei_local->txd_pool); ++ //printk("eth_send cpu_ptr = 0x%x!!!\n", cpu_ptr); ++ //printk("eth_send ctx_offset = 0x%x!!!\n", ctx_offset); ++ //printk("eth_send ei_local->skb_free[ctx_offset] = 0x%x!!!\n", skb); ++ ++ ++ ei_local->skb_free[ctx_offset] = skb; ++#if defined (CONFIG_RAETH_TSO) ++ init_cpu_ptr = cpu_ptr; ++ init_txd_idx = ctx_offset; ++#endif ++ ++#if !defined (CONFIG_RAETH_TSO) ++ ++ //2. prepare data ++ cpu_ptr->txd_info1.SDP = virt_to_phys(skb->data); ++ cpu_ptr->txd_info3.SDL = skb->len; ++ ++ if (gmac_no == 1) { ++ cpu_ptr->txd_info4.FPORT = 1; ++ }else { ++ cpu_ptr->txd_info4.FPORT = 2; ++ } ++ ++ ++ cpu_ptr->txd_info3.QID = M2Q_table[skb->mark]; ++#if 0 ++ iph = (struct iphdr *)skb_network_header(skb); ++ if (iph->tos == 0xe0) ++ cpu_ptr->txd_info3.QID = 3; ++ else if (iph->tos == 0xa0) ++ cpu_ptr->txd_info3.QID = 2; ++ else if (iph->tos == 0x20) ++ cpu_ptr->txd_info3.QID = 1; ++ else ++ cpu_ptr->txd_info3.QID = 0; ++#endif ++ ++#if defined (CONFIG_RAETH_CHECKSUM_OFFLOAD) && ! defined(CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628) ++ if (skb->ip_summed == CHECKSUM_PARTIAL){ ++ cpu_ptr->txd_info4.TUI_CO = 7; ++ }else { ++ cpu_ptr->txd_info4.TUI_CO = 0; ++ } ++#endif ++ ++#ifdef CONFIG_RAETH_HW_VLAN_TX ++ if(vlan_tx_tag_present(skb)) { ++ cpu_ptr->txd_info4.VLAN_TAG = 0x10000 | vlan_tx_tag_get(skb); ++ }else { ++ cpu_ptr->txd_info4.VLAN_TAG = 0; ++ } ++#endif ++ ++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) ++ if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) { ++ if(ra_sw_nat_hook_rx!= NULL){ ++ cpu_ptr->txd_info4.FPORT = 4; /* PPE */ ++ FOE_MAGIC_TAG(skb) = 0; ++ } ++ } ++#endif ++#if 0 ++ cpu_ptr->txd_info4.FPORT = 4; /* PPE */ ++ cpu_ptr->txd_info4.UDF = 0x2F; ++#endif ++ ++#if defined (CONFIG_MIPS) ++ dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE); ++#else ++ dma_sync_single_for_device(NULL, virt_to_phys(skb->data), skb->len, DMA_TO_DEVICE); ++#endif ++ cpu_ptr->txd_info3.SWC_bit = 1; ++ ++ //3. get NULL TXD and decrease free_tx_num by 1. ++ ctx_offset = get_free_txd(&free_txd); ++ if(ctx_offset == NUM_TX_DESC) { ++ printk("get_free_txd fail\n"); // this should not happen. free_txd_num is 2 at least. ++ return 0; ++ } ++ ++ //4. hook new TXD in the end of queue ++ //cpu_ptr->txd_info2.NDP = virt_to_phys(free_txd); ++ cpu_ptr->txd_info2.NDP = (free_txd); ++ ++ ++ //5. move CPU_PTR to new TXD ++ //ei_local->tx_cpu_ptr = virt_to_phys(free_txd); ++ ei_local->tx_cpu_ptr = (free_txd); ++ cpu_ptr->txd_info3.OWN_bit = 0; ++ sysRegWrite(QTX_CTX_PTR, ei_local->tx_cpu_ptr); ++ ++#if 0 ++ printk("----------------------------------------------\n"); ++ printk("txd_info1:%08X \n",*(int *)&cpu_ptr->txd_info1); ++ printk("txd_info2:%08X \n",*(int *)&cpu_ptr->txd_info2); ++ printk("txd_info3:%08X \n",*(int *)&cpu_ptr->txd_info3); ++ printk("txd_info4:%08X \n",*(int *)&cpu_ptr->txd_info4); ++#endif ++ ++#else //#if !defined (CONFIG_RAETH_TSO) ++ cpu_ptr->txd_info1.SDP = virt_to_phys(skb->data); ++ cpu_ptr->txd_info3.SDL = (length - skb->data_len); ++ cpu_ptr->txd_info3.LS_bit = nr_frags ? 0:1; ++ if (gmac_no == 1) { ++ cpu_ptr->txd_info4.FPORT = 1; ++ }else { ++ cpu_ptr->txd_info4.FPORT = 2; ++ } ++ ++ cpu_ptr->txd_info4.TSO = 0; ++ cpu_ptr->txd_info3.QID = M2Q_table[skb->mark]; ++#if defined (CONFIG_RAETH_CHECKSUM_OFFLOAD) && ! defined(CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628) ++ if (skb->ip_summed == CHECKSUM_PARTIAL){ ++ cpu_ptr->txd_info4.TUI_CO = 7; ++ }else { ++ cpu_ptr->txd_info4.TUI_CO = 0; ++ } ++#endif ++ ++#ifdef CONFIG_RAETH_HW_VLAN_TX ++ if(vlan_tx_tag_present(skb)) { ++ cpu_ptr->txd_info4.VLAN_TAG = 0x10000 | vlan_tx_tag_get(skb); ++ }else { ++ cpu_ptr->txd_info4.VLAN_TAG = 0; ++ } ++#endif ++ ++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) ++ if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) { ++ if(ra_sw_nat_hook_rx!= NULL){ ++ cpu_ptr->txd_info4.FPORT = 4; /* PPE */ ++ FOE_MAGIC_TAG(skb) = 0; ++ } ++ } ++#endif ++ ++ cpu_ptr->txd_info3.SWC_bit = 1; ++ ++ ctx_offset = get_free_txd(&free_txd); ++ if(ctx_offset == NUM_TX_DESC) { ++ printk("get_free_txd fail\n"); ++ return 0; ++ } ++ //cpu_ptr->txd_info2.NDP = virt_to_phys(free_txd); ++ //ei_local->tx_cpu_ptr = virt_to_phys(free_txd); ++ cpu_ptr->txd_info2.NDP = free_txd; ++ ei_local->tx_cpu_ptr = free_txd; ++ ++ if(nr_frags > 0) { ++ for(i=0;ifrags[i]; ++ len = frag->size; ++ frag_txd_num = cal_frag_txd_num(len); // calculate the needed TXD numbers for this fragment ++ for(frag_txd_num = frag_txd_num;frag_txd_num > 0; frag_txd_num --){ ++ // 2. size will be assigned to SDL and can't be larger than MAX_TXD_LEN ++ if(len < MAX_TXD_LEN) ++ size = len; ++ else ++ size = MAX_TXD_LEN; ++ ++ //3. Update TXD info ++ cpu_ptr = (ei_local->txd_pool + (ctx_offset)); ++ cpu_ptr->txd_info3.QID = M2Q_table[skb->mark]; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) ++ cpu_ptr->txd_info1.SDP = pci_map_page(NULL, frag->page, frag->page_offset, frag->size, PCI_DMA_TODEVICE); ++#else ++ cpu_ptr->txd_info1.SDP = pci_map_page(NULL, frag->page.p, frag->page_offset + offset, size, PCI_DMA_TODEVICE); ++// printk(" frag->page = %08x. frag->page_offset = %08x. frag->size = % 08x.\n", frag->page, (frag->page_offset+offset), size); ++#endif ++ cpu_ptr->txd_info3.SDL = size; ++ if( (i==(nr_frags-1)) && (frag_txd_num == 1)) ++ cpu_ptr->txd_info3.LS_bit = 1; ++ else ++ cpu_ptr->txd_info3.LS_bit = 0; ++ cpu_ptr->txd_info3.OWN_bit = 0; ++ cpu_ptr->txd_info3.SWC_bit = 1; ++ //4. Update skb_free for housekeeping ++ ei_local->skb_free[ctx_offset] = (cpu_ptr->txd_info3.LS_bit == 1)?skb:(struct sk_buff *)0xFFFFFFFF; //MAGIC ID ++ ++ //5. Get next TXD ++ ctx_offset = get_free_txd(&free_txd); ++ //cpu_ptr->txd_info2.NDP = virt_to_phys(free_txd); ++ //ei_local->tx_cpu_ptr = virt_to_phys(free_txd); ++ cpu_ptr->txd_info2.NDP = free_txd; ++ ei_local->tx_cpu_ptr = free_txd; ++ //6. Update offset and len. ++ offset += size; ++ len -= size; ++ } ++ } ++ ei_local->skb_free[init_txd_idx]= (struct sk_buff *)0xFFFFFFFF; //MAGIC ID ++ } ++ ++ if(skb_shinfo(skb)->gso_segs > 1) { ++ ++// TsoLenUpdate(skb->len); ++ ++ /* TCP over IPv4 */ ++ iph = (struct iphdr *)skb_network_header(skb); ++#if defined (CONFIG_RAETH_TSOV6) ++ /* TCP over IPv6 */ ++ ip6h = (struct ipv6hdr *)skb_network_header(skb); ++#endif ++ if((iph->version == 4) && (iph->protocol == IPPROTO_TCP)) { ++ th = (struct tcphdr *)skb_transport_header(skb); ++ ++ init_cpu_ptr->txd_info4.TSO = 1; ++ ++ th->check = htons(skb_shinfo(skb)->gso_size); ++#if defined (CONFIG_MIPS) ++ dma_cache_sync(NULL, th, sizeof(struct tcphdr), DMA_TO_DEVICE); ++#else ++ dma_sync_single_for_device(NULL, virt_to_phys(th), sizeof(struct tcphdr), DMA_TO_DEVICE); ++#endif ++ } ++ ++#if defined (CONFIG_RAETH_TSOV6) ++ /* TCP over IPv6 */ ++ //ip6h = (struct ipv6hdr *)skb_network_header(skb); ++ else if ((ip6h->version == 6) && (ip6h->nexthdr == NEXTHDR_TCP)) { ++ th = (struct tcphdr *)skb_transport_header(skb); ++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR ++ init_cpu_ptr->txd_info4.TSO = 1; ++#else ++ init_cpu_ptr->txd_info4.TSO = 1; ++#endif ++ th->check = htons(skb_shinfo(skb)->gso_size); ++#if defined (CONFIG_MIPS) ++ dma_cache_sync(NULL, th, sizeof(struct tcphdr), DMA_TO_DEVICE); ++#else ++ dma_sync_single_for_device(NULL, virt_to_phys(th), sizeof(struct tcphdr), DMA_TO_DEVICE); ++#endif ++ } ++#endif ++ } ++ ++ ++// dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE); ++ ++ init_cpu_ptr->txd_info3.OWN_bit = 0; ++#endif // CONFIG_RAETH_TSO // ++ ++ sysRegWrite(QTX_CTX_PTR, ei_local->tx_cpu_ptr); ++ ++#ifdef CONFIG_PSEUDO_SUPPORT ++ if (gmac_no == 2) { ++ if (ei_local->PseudoDev != NULL) { ++ pAd = netdev_priv(ei_local->PseudoDev); ++ pAd->stat.tx_packets++; ++ pAd->stat.tx_bytes += length; ++ } ++ } else ++ ++#endif ++ { ++ ei_local->stat.tx_packets++; ++ ei_local->stat.tx_bytes += skb->len; ++ } ++#ifdef CONFIG_RAETH_NAPI ++ if ( ei_local->tx_full == 1) { ++ ei_local->tx_full = 0; ++ netif_wake_queue(dev); ++ } ++#endif ++ ++ return length; ++} ++ ++int ei_start_xmit(struct sk_buff* skb, struct net_device *dev, int gmac_no) ++{ ++ END_DEVICE *ei_local = netdev_priv(dev); ++ unsigned long flags; ++ unsigned int num_of_txd = 0; ++#if defined (CONFIG_RAETH_TSO) ++ unsigned int nr_frags = skb_shinfo(skb)->nr_frags, i; ++ struct skb_frag_struct *frag; ++#endif ++#ifdef CONFIG_PSEUDO_SUPPORT ++ PSEUDO_ADAPTER *pAd; ++#endif ++ ++#if !defined(CONFIG_RA_NAT_NONE) ++ if(ra_sw_nat_hook_tx!= NULL) ++ { ++// spin_lock_irqsave(&ei_local->page_lock, flags); ++ if(ra_sw_nat_hook_tx(skb, gmac_no)==1){ ++// spin_unlock_irqrestore(&ei_local->page_lock, flags); ++ }else{ ++ kfree_skb(skb); ++// spin_unlock_irqrestore(&ei_local->page_lock, flags); ++ return 0; ++ } ++ } ++#endif ++ ++#if defined(CONFIG_RALINK_MT7621) || defined(CONFIG_ARCH_MT7623) ++#define MIN_PKT_LEN 64 ++ if (skb->len < MIN_PKT_LEN) { ++ if (skb_padto(skb, MIN_PKT_LEN)) { ++ printk("raeth: skb_padto failed\n"); ++ return 0; ++ } ++ skb_put(skb, MIN_PKT_LEN - skb->len); ++ } ++#endif ++ ++ ++ dev->trans_start = jiffies; /* save the timestamp */ ++ spin_lock_irqsave(&ei_local->page_lock, flags); ++#if defined (CONFIG_MIPS) ++ dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE); ++#else ++ dma_sync_single_for_device(NULL, virt_to_phys(skb->data), skb->len, DMA_TO_DEVICE); ++#endif ++ ++ ++//check free_txd_num before calling rt288_eth_send() ++ ++#if defined (CONFIG_RAETH_TSO) ++ // num_of_txd = (nr_frags==0) ? 1 : (nr_frags + 1); ++ if(nr_frags != 0){ ++ for(i=0;ifrags[i]; ++ num_of_txd += cal_frag_txd_num(frag->size); ++ } ++ }else ++ num_of_txd = 1; ++#else ++ num_of_txd = 1; ++#endif ++ ++#if defined(CONFIG_RALINK_MT7621) ++ if((sysRegRead(0xbe00000c)&0xFFFF) == 0x0101) { ++ ei_xmit_housekeeping(0); ++ } ++#endif ++ ++ ei_xmit_housekeeping(0); ++ ++ //if ((ei_local->free_txd_num > num_of_txd + 1) && (ei_local->free_txd_num != NUM_TX_DESC)) ++ if ((ei_local->free_txd_num > num_of_txd + 5) && (ei_local->free_txd_num != NUM_TX_DESC)) ++ { ++ rt2880_eth_send(dev, skb, gmac_no); // need to modify rt2880_eth_send() for QDMA ++ if (ei_local->free_txd_num < 3) ++ { ++#if defined (CONFIG_RAETH_STOP_RX_WHEN_TX_FULL) ++ netif_stop_queue(dev); ++#ifdef CONFIG_PSEUDO_SUPPORT ++ netif_stop_queue(ei_local->PseudoDev); ++#endif ++ tx_ring_full = 1; ++#endif ++ } ++ } else { ++#ifdef CONFIG_PSEUDO_SUPPORT ++ if (gmac_no == 2) ++ { ++ if (ei_local->PseudoDev != NULL) ++ { ++ pAd = netdev_priv(ei_local->PseudoDev); ++ pAd->stat.tx_dropped++; ++ } ++ } else ++#endif ++ ei_local->stat.tx_dropped++; ++ kfree_skb(skb); ++ spin_unlock_irqrestore(&ei_local->page_lock, flags); ++ return 0; ++ } ++ spin_unlock_irqrestore(&ei_local->page_lock, flags); ++ return 0; ++} ++ ++void ei_xmit_housekeeping(unsigned long unused) ++{ ++ struct net_device *dev = dev_raether; ++ END_DEVICE *ei_local = netdev_priv(dev); ++#ifndef CONFIG_RAETH_NAPI ++ unsigned long reg_int_mask=0; ++#endif ++ struct QDMA_txdesc *dma_ptr = NULL; ++ struct QDMA_txdesc *cpu_ptr = NULL; ++ struct QDMA_txdesc *tmp_ptr = NULL; ++ unsigned int htx_offset = 0; ++ unsigned int ctx_offset = 0; ++ unsigned int dtx_offset = 0; ++ ++ //dma_ptr = phys_to_virt(sysRegRead(QTX_DRX_PTR)); ++ //cpu_ptr = phys_to_virt(sysRegRead(QTX_CRX_PTR)); ++ //printk("kurtis:housekeeping QTX_DRX_PTR = 0x%x!!!\n", sysRegRead(QTX_DRX_PTR)); ++ //printk("kurtis:housekeeping DMA_PTR = 0x%x!!!\n", dma_ptr); ++ ++ cpu_ptr = sysRegRead(QTX_CRX_PTR); ++ dma_ptr = sysRegRead(QTX_DRX_PTR); ++ ++ //printk("kurtis:housekeeping QTX_CRX_PTR = 0x%x!!!\n", cpu_ptr); ++ //printk("kurtis:housekeeping QTX_DRX_PTR = 0x%x!!!\n", dma_ptr); ++ ctx_offset = GET_TXD_OFFSET(&cpu_ptr); ++ dtx_offset = GET_TXD_OFFSET(&dma_ptr); ++ htx_offset = ctx_offset; ++ cpu_ptr = (ei_local->txd_pool + (ctx_offset)); ++ dma_ptr = (ei_local->txd_pool + (dtx_offset)); ++ ++ ++ //printk("kurtis:housekeeping CPU_PTR = 0x%x!!!\n", cpu_ptr); ++ //printk("kurtis:housekeeping DMA_PTR = 0x%x!!!\n", dma_ptr); ++ ++/*temp mark*/ ++#if 1 ++ ++ ++ if(cpu_ptr != dma_ptr && (cpu_ptr->txd_info3.OWN_bit == 1)) { ++ while(cpu_ptr != dma_ptr && (cpu_ptr->txd_info3.OWN_bit == 1)) { ++ ++ //1. keep cpu next TXD ++ //tmp_ptr = phys_to_virt(cpu_ptr->txd_info2.NDP); ++ tmp_ptr = cpu_ptr->txd_info2.NDP; ++ htx_offset = GET_TXD_OFFSET(&tmp_ptr); ++ //printk("kurtis:housekeeping cpu_ptr->txd_info2.NDP = 0x%x!!!\n", cpu_ptr->txd_info2.NDP); ++ //printk("kurtis:housekeeping tmp_ptr = 0x%x!!!\n", tmp_ptr); ++ //printk("kurtis:housekeeping htx_offset = 0x%x!!!\n", htx_offset); ++ //2. free skb meomry ++#if defined (CONFIG_RAETH_TSO) ++ if(ei_local->skb_free[htx_offset]!=(struct sk_buff *)0xFFFFFFFF) { ++ dev_kfree_skb_any(ei_local->skb_free[htx_offset]); ++ } ++#else ++ dev_kfree_skb_any(ei_local->skb_free[htx_offset]); ++#endif ++ ++ //3. release TXD ++ //htx_offset = GET_TXD_OFFSET(&cpu_ptr); ++ //put_free_txd(htx_offset); ++ put_free_txd(ctx_offset); ++ ++ ++ ++ netif_wake_queue(dev); ++#ifdef CONFIG_PSEUDO_SUPPORT ++ netif_wake_queue(ei_local->PseudoDev); ++#endif ++ tx_ring_full=0; ++ ++ //4. update cpu_ptr to next ptr ++ //cpu_ptr = tmp_ptr; ++ cpu_ptr = (ei_local->txd_pool + htx_offset); ++ ctx_offset = htx_offset; ++ //cpu_ptr = (cpu_ptr + (htx_offset)); ++ //printk("kurtis:housekeeping 4. update cpu_ptr = 0x%x!!!\n", cpu_ptr); ++ } ++ } ++ //sysRegWrite(QTX_CRX_PTR, virt_to_phys(cpu_ptr)); ++ //sysRegWrite(QTX_CRX_PTR, cpu_ptr); ++ tmp_ptr = (ei_local->phy_txd_pool + (htx_offset << 4)); ++ //printk("kurtis:housekeeping 5. update QTX_CRX_PTR = 0x%x!!!\n", tmp_ptr); ++ sysRegWrite(QTX_CRX_PTR, tmp_ptr); ++ ++#endif ++ ++#ifndef CONFIG_RAETH_NAPI ++ reg_int_mask=sysRegRead(QFE_INT_ENABLE); ++#if defined (DELAY_INT) ++ sysRegWrite(FE_INT_ENABLE, reg_int_mask| RLS_DLY_INT); ++#else ++ ++ sysRegWrite(FE_INT_ENABLE, reg_int_mask | RLS_DONE_INT); ++#endif ++#endif //CONFIG_RAETH_NAPI// ++} ++ ++EXPORT_SYMBOL(ei_start_xmit); ++EXPORT_SYMBOL(ei_xmit_housekeeping); ++EXPORT_SYMBOL(fe_dma_init); ++EXPORT_SYMBOL(rt2880_eth_send); +diff --git a/drivers/net/ethernet/raeth/smb_hook.c b/drivers/net/ethernet/raeth/smb_hook.c +new file mode 100644 +index 0000000..617139c +--- /dev/null ++++ b/drivers/net/ethernet/raeth/smb_hook.c +@@ -0,0 +1,17 @@ ++#include ++#include ++#include ++#include ++#include ++ ++ ++int (*smb_nf_local_in_hook)(struct sk_buff *skb) = NULL; ++int (*smb_nf_pre_routing_hook)(struct sk_buff *skb) = NULL; ++int (*smb_nf_local_out_hook)(struct sk_buff *skb) = NULL; ++int (*smb_nf_post_routing_hook)(struct sk_buff *skb) = NULL; ++EXPORT_SYMBOL(smb_nf_local_in_hook); ++EXPORT_SYMBOL(smb_nf_pre_routing_hook); ++EXPORT_SYMBOL(smb_nf_local_out_hook); ++EXPORT_SYMBOL(smb_nf_post_routing_hook); ++ ++ +diff --git a/drivers/net/ethernet/raeth/smb_nf.c b/drivers/net/ethernet/raeth/smb_nf.c +new file mode 100644 +index 0000000..86250eb +--- /dev/null ++++ b/drivers/net/ethernet/raeth/smb_nf.c +@@ -0,0 +1,177 @@ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++extern int (*smb_nf_local_in_hook)(struct sk_buff *skb); ++extern int (*smb_nf_pre_routing_hook)(struct sk_buff *skb); ++extern int (*smb_nf_local_out_hook)(struct sk_buff *skb); ++extern int (*smb_nf_post_routing_hook)(struct sk_buff *skb); ++ ++struct net_device *lan_int = NULL; ++struct in_ifaddr *lan_ifa = NULL; ++ ++ ++int mtk_smb_nf_local_in_hook(struct sk_buff *skb) ++{ ++ struct iphdr *iph = ip_hdr(skb); ++ ++ if (skb->protocol == htons(ETH_P_IP)) { ++ struct iphdr *iph = ip_hdr(skb); ++ ++ if (iph->protocol == IPPROTO_TCP) { ++ struct tcphdr *th = tcp_hdr(skb); ++ unsigned short sport, dport; ++ ++ th = tcp_hdr(skb); ++ th = (struct tcphdr *)(((unsigned char *)iph) + iph->ihl*4); ++ ++ if ((iph->daddr == lan_ifa->ifa_local) ++ && ((th->dest == 0xbd01) || (th->dest == 0x8900) ++ || (th->dest == 0x8a00) || (th->dest == 0x8b00))) ++ return 1; ++ else ++ return 0; ++ } ++ ++ } ++ ++ return 0; ++} ++ ++int mtk_smb_nf_pre_routing_hook(struct sk_buff *skb) ++{ ++ struct iphdr *iph = ip_hdr(skb); ++ ++ if (skb->protocol == htons(ETH_P_IP)) { ++ struct iphdr *iph = ip_hdr(skb); ++ ++ if (iph->protocol == IPPROTO_TCP) { ++ struct tcphdr *th = tcp_hdr(skb); ++ unsigned short sport, dport; ++ ++ th = tcp_hdr(skb); ++ th = (struct tcphdr *)(((unsigned char *)iph) + iph->ihl*4); ++ if ((iph->daddr == lan_ifa->ifa_local) ++ && ((th->dest == 0xbd01) || (th->dest == 0x8900) ++ || (th->dest == 0x8a00) || (th->dest == 0x8b00))) ++ return 1; ++ else ++ return 0; ++ } ++ ++ } ++ ++ return 0; ++} ++ ++int mtk_smb_nf_local_out_hook(struct sk_buff *skb) ++{ ++ struct iphdr *iph = ip_hdr(skb); ++ ++ if (iph->protocol == IPPROTO_TCP) { ++ struct tcphdr *th = tcp_hdr(skb); ++ ++ th = tcp_hdr(skb); ++ th = (struct tcphdr *)(((unsigned char *)iph) + iph->ihl*4); ++ ++ if ((iph->saddr == lan_ifa->ifa_local) ++ && ((th->source == 0xbd01) || (th->source == 0x8900) ++ || (th->source == 0x8a00) || (th->source == 0x8b00))) ++ return 1; ++ else ++ return 0; ++ } ++ ++ return 0; ++} ++ ++int mtk_smb_nf_post_routing_hook(struct sk_buff *skb) ++{ ++ struct iphdr *iph = ip_hdr(skb); ++ ++ if (skb->protocol == htons(ETH_P_IP)) { ++ struct iphdr *iph = ip_hdr(skb); ++ ++ if (iph->protocol == IPPROTO_TCP) { ++ struct tcphdr *th = tcp_hdr(skb); ++ ++ th = tcp_hdr(skb); ++ th = (struct tcphdr *)(((unsigned char *)iph) + iph->ihl*4); ++ ++ if ((iph->saddr == lan_ifa->ifa_local) ++ && ((th->source == 0xbd01) || (th->source == 0x8900) ++ || (th->source == 0x8a00) || (th->source == 0x8b00))) ++ return 1; ++ else ++ return 0; ++ } ++ ++ } ++ ++ return 0; ++} ++ ++int __init mtk_smb_hook_init(void) ++{ ++ struct in_device *in_dev; ++ struct in_ifaddr **ifap = NULL; ++ struct in_ifaddr *ifa = NULL; ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ lan_int = dev_get_by_name(&init_net, "br0"); ++#else ++ lan_int = dev_get_by_name("br0"); ++#endif ++ if (lan_int) ++ in_dev = __in_dev_get_rtnl(lan_int); ++ else ++ return 0; ++ ++ if (in_dev) { ++ for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ++ ifap = &ifa->ifa_next) { ++ if (!strcmp("br0", ifa->ifa_label)) ++ { ++ lan_ifa = ifa; ++ break; /* found */ ++ } ++ } ++ } ++ else ++ return 0; ++ ++ if (lan_ifa) { ++ smb_nf_local_in_hook = mtk_smb_nf_local_in_hook; ++ smb_nf_pre_routing_hook = mtk_smb_nf_pre_routing_hook; ++ smb_nf_local_out_hook = mtk_smb_nf_local_out_hook; ++ smb_nf_post_routing_hook = mtk_smb_nf_post_routing_hook; ++ } ++ ++ printk("Samba Netfilter Hook Enabled\n"); ++ ++ return 0; ++} ++ ++void mtk_smb_hook_cleanup(void) ++{ ++ lan_int = NULL; ++ lan_ifa = NULL; ++ smb_nf_local_in_hook = NULL; ++ smb_nf_pre_routing_hook = NULL; ++ smb_nf_local_out_hook = NULL; ++ smb_nf_post_routing_hook = NULL; ++ ++ return; ++} ++ ++module_init(mtk_smb_hook_init); ++module_exit(mtk_smb_hook_cleanup); ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/net/ethernet/raeth/sync_write.h b/drivers/net/ethernet/raeth/sync_write.h +new file mode 100644 +index 0000000..8b800e6 +--- /dev/null ++++ b/drivers/net/ethernet/raeth/sync_write.h +@@ -0,0 +1,103 @@ ++#ifndef _MT_SYNC_WRITE_H ++#define _MT_SYNC_WRITE_H ++ ++#if defined(__KERNEL__) ++ ++#include ++#include ++//#include ++ ++/* ++ * Define macros. ++ */ ++ ++#define mt65xx_reg_sync_writel(v, a) \ ++ do { \ ++ __raw_writel((v), IOMEM((a))); \ ++ dsb(); \ ++ } while (0) ++ ++#define mt65xx_reg_sync_writew(v, a) \ ++ do { \ ++ __raw_writew((v), IOMEM((a))); \ ++ dsb(); \ ++ } while (0) ++ ++#define mt65xx_reg_sync_writeb(v, a) \ ++ do { \ ++ __raw_writeb((v), IOMEM((a))); \ ++ dsb(); \ ++ } while (0) ++ ++#define mt_reg_sync_writel(v, a) \ ++ do { \ ++ __raw_writel((v), IOMEM((a))); \ ++ dsb(); \ ++ } while (0) ++ ++#define mt_reg_sync_writew(v, a) \ ++ do { \ ++ __raw_writew((v), IOMEM((a))); \ ++ dsb(); \ ++ } while (0) ++ ++#define mt_reg_sync_writeb(v, a) \ ++ do { \ ++ __raw_writeb((v), IOMEM((a))); \ ++ dsb(); \ ++ } while (0) ++ ++ ++#else /* __KERNEL__ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define dsb() \ ++ do { \ ++ __asm__ __volatile__ ("dsb" : : : "memory"); \ ++ } while (0) ++ ++#define mt65xx_reg_sync_writel(v, a) \ ++ do { \ ++ *(volatile unsigned int *)(a) = (v); \ ++ dsb(); \ ++ } while (0) ++ ++#define mt65xx_reg_sync_writew(v, a) \ ++ do { \ ++ *(volatile unsigned short *)(a) = (v); \ ++ dsb(); \ ++ } while (0) ++ ++#define mt65xx_reg_sync_writeb(v, a) \ ++ do { \ ++ *(volatile unsigned char *)(a) = (v); \ ++ dsb(); \ ++ } while (0) ++ ++#define mt_reg_sync_writel(v, a) \ ++ do { \ ++ *(volatile unsigned int *)(a) = (v); \ ++ dsb(); \ ++ } while (0) ++ ++#define mt_reg_sync_writew(v, a) \ ++ do { \ ++ *(volatile unsigned short *)(a) = (v); \ ++ dsb(); \ ++ } while (0) ++ ++#define mt_reg_sync_writeb(v, a) \ ++ do { \ ++ *(volatile unsigned char *)(a) = (v); \ ++ dsb(); \ ++ } while (0) ++ ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* !_MT_SYNC_WRITE_H */ +-- +1.7.10.4 + -- cgit v1.2.3