openwrt/target/linux/mediatek/patches/0063-arm-mediatek-add-SDK-ethernet.patch
John Crispin 25afe99b31 mediatek: add support for the new MT7623 Arm SoC
the support is still WIP. next steps are to make the pmic and ethernet work.
this is the first commit to make sure nothing gets lost.

Signed-off-by: John Crispin <blogic@openwrt.org>

SVN-Revision: 47354
2015-11-02 10:18:50 +00:00

20655 lines
662 KiB
Diff

From e3aece79d5003b6879298b05551e113117d5cdd8 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sat, 27 Jun 2015 13:13:36 +0200
Subject: [PATCH 63/76] arm: mediatek: add SDK ethernet
Signed-off-by: John Crispin <blogic@openwrt.org>
---
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 <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/netfilter.h>
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <linux/moduleparam.h>
+
+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;i<sizeof(pkt);i++){
+ if(i%16==0) {
+ printk("\n");
+ }
+ printk("%02X-",skb->data[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 <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/netfilter.h>
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <linux/moduleparam.h>
+
+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;i<sizeof(pkt_1);i++){
+ if(i%16==0) {
+ printk("\n");
+ }
+ printk("%02X-",skb_1->data[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;i<sizeof(pkt_2);i++){
+ if(i%16==0) {
+ printk("\n");
+ }
+ printk("%02X-",skb_2->data[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 <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/netfilter.h>
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <linux/moduleparam.h>
+
+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;i<sizeof(pkt_0);i++){
+ if(i%16==0) {
+ printk("\n");
+ }
+ printk("%02X-",skb_0->data[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;i<sizeof(pkt_1);i++){
+ if(i%16==0) {
+ printk("\n");
+ }
+ printk("%02X-",skb_1->data[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;i<sizeof(pkt_2);i++){
+ if(i%16==0) {
+ printk("\n");
+ }
+ printk("%02X-",skb_2->data[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 <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/if_vlan.h>
+#include <linux/if_ether.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <asm/rt2880/surfboardint.h>
+#if defined(CONFIG_RAETH_TSO)
+#include <linux/tcp.h>
+#include <net/ipv6.h>
+#include <linux/ip.h>
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <linux/in.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_pppox.h>
+#endif
+#if defined(CONFIG_RAETH_LRO)
+#include <linux/inet_lro.h>
+#endif
+#include <linux/delay.h>
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
+#include <linux/sched.h>
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 0)
+#include <asm/rt2880/rt_mmap.h>
+#else
+#include <linux/libata-compat.h>
+#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 <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+
+
+#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<MAX_MCAST_ENTRY;i++) {
+ if( (mcast_tbl[i].vlan_id == vlan_id) &&
+ memcmp(mcast_tbl[i].src_mac,src_mac, 6)==0 &&
+ memcmp(mcast_tbl[i].dst_mac, dst_mac, 6)==0 &&
+ mcast_tbl[i].valid == 1) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+int inline __add_mcast_entry(uint16_t vlan_id, uint8_t *src_mac, uint8_t *dst_mac)
+{
+ int i=0;
+
+ // use empty or ageout entry
+ for(i=0;i<MAX_MCAST_ENTRY;i++) {
+ if( mcast_tbl[i].valid==0 ||
+ time_after(jiffies, mcast_tbl[i].ageout)) {
+
+ if(mcast_tbl[i].valid==0) {
+ atomic_inc(&mcast_entry_num);
+ }
+ mcast_tbl[i].vlan_id = vlan_id;
+ memcpy(mcast_tbl[i].src_mac, src_mac, 6);
+ memcpy(mcast_tbl[i].dst_mac, dst_mac, 6);
+ mcast_tbl[i].valid=1;
+ mcast_tbl[i].use_count=1;
+ mcast_tbl[i].ageout=jiffies + AGEING_TIME * HZ;
+
+ return 1;
+ }
+ }
+
+ MCAST_PRINT("RAETH: Multicast Table is FULL!!\n");
+ return 0;
+}
+
+int inline mcast_entry_ins(uint16_t vlan_id, uint8_t *src_mac, uint8_t *dst_mac)
+{
+ int entry_num=0, ret=0;
+
+ down(&mtbl_lock);
+ if((entry_num = mcast_entry_get(vlan_id, src_mac, dst_mac)) >=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 <linux/module.h>
+#include <linux/version.h>
+#include <linux/netdevice.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
+#include <asm/rt2880/rt_mmap.h>
+#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 <linux/mii.h> // for struct mii_if_info in ra2882ethreg.h
+#include <linux/version.h> /* check linux version for 2.4 and 2.6 compatibility */
+#include <linux/interrupt.h> /* for "struct tasklet_struct" in linux-3.10.14 */
+#if defined (CONFIG_HW_SFQ)
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#include <asm/rt2880/rt_mmap.h>
+#endif
+#include "raether.h"
+
+#ifdef WORKQUEUE_BH
+#include <linux/workqueue.h>
+#endif // WORKQUEUE_BH //
+#ifdef CONFIG_RAETH_LRO
+#include <linux/inet_lro.h>
+#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_FUSH_REQ_OFFSET; \
+ }
+#define SET_PDMA_LRO_IPV6_EN(x) \
+ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
+ *addr &= ~PDMA_LRO_IPV6_EN; \
+ *addr |= ((x) & 0x1)<<PDMA_LRO_IPV6_EN_OFFSET; \
+ }
+#if defined(CONFIG_RAETH_HW_LRO_PREFETCH)
+#define SET_PDMA_LRO_RXD_PREFETCH_EN(x) \
+ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
+ *addr &= ~PDMA_LRO_RXD_PREFETCH_EN; \
+ *addr |= ((x) & 0x3)<<PDMA_LRO_RXD_PREFETCH_EN_OFFSET; \
+ }
+#else
+#define SET_PDMA_LRO_RXD_PREFETCH_EN(x)
+#endif
+#define SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(x) \
+ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
+ *addr &= ~PDMA_LRO_IPV4_CSUM_UPDATE_EN; \
+ *addr |= ((x) & 0x1)<<PDMA_LRO_IPV4_CSUM_UPDATE_EN_OFFSET; \
+ }
+#define SET_PDMA_LRO_IPV4_CTRL_PUSH_EN(x) \
+ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
+ *addr &= ~PDMA_LRO_IPV4_CTRL_PUSH_EN; \
+ *addr |= ((x) & 0x1)<<PDMA_LRO_IPV4_CTRL_PUSH_EN_OFFSET; \
+ }
+#define SET_PDMA_NON_LRO_MULTI_EN(x) \
+ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
+ *addr &= ~(PDMA_NON_LRO_MULTI_EN); \
+ *addr |= ((x) & 0x1)<<PDMA_NON_LRO_MULTI_EN_OFFSET; \
+ }
+#define SET_PDMA_LRO_FREQ_PRI_ADJ(x) \
+ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
+ *addr &= ~PDMA_LRO_FREQ_PRI_ADJ; \
+ *addr |= ((x) & 0xf)<<PDMA_LRO_FREQ_PRI_ADJ_OFFSET; \
+ }
+#define SET_PDMA_LRO_TPUT_PRE_ADJ(x) \
+ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
+ *addr &= ~PDMA_LRO_TPUT_PRE_ADJ; \
+ *addr |= ((x) & 0xf)<<PDMA_LRO_TPUT_PRE_ADJ_OFFSET; \
+ }
+#define SET_PDMA_LRO_TPUT_PRI_ADJ(x) \
+ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
+ *addr &= ~PDMA_LRO_TPUT_PRI_ADJ; \
+ *addr |= ((x) & 0xf)<<PDMA_LRO_TPUT_PRI_ADJ_OFFSET; \
+ }
+#define SET_PDMA_LRO_ALT_SCORE_MODE(x) \
+ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
+ *addr &= ~PDMA_LRO_ALT_SCORE_MODE; \
+ *addr |= ((x) & 0x1)<<PDMA_LRO_ALT_SCORE_MODE_OFFSET; \
+ }
+#define SET_PDMA_LRO_DLY_INT_EN(x) \
+ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
+ *addr &= ~PDMA_LRO_DLY_INT_EN; \
+ *addr |= ((x) & 0x1)<<PDMA_LRO_DLY_INT_EN_OFFSET; \
+ }
+#define SET_PDMA_LRO_BW_THRESHOLD(x) \
+ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW2; \
+ *addr = (x); \
+ }
+#define SET_PDMA_LRO_MIN_RXD_SDL(x) \
+ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW3; \
+ *addr &= ~PDMA_LRO_LRO_MIN_RXD_SDL0; \
+ *addr |= ((x) & 0xffff)<<PDMA_LRO_LRO_MIN_RXD_SDL0_OFFSET; \
+ }
+#define SET_PDMA_LRO_TPUT_OVERFLOW_ADJ(x) \
+ { volatile unsigned int *addr = (unsigned int*)PDMA_LRO_ATL_OVERFLOW_ADJ; \
+ *addr &= ~PDMA_LRO_TPUT_OVERFLOW_ADJ; \
+ *addr |= ((x) & 0xfffff)<<PDMA_LRO_TPUT_OVERFLOW_ADJ_OFFSET; \
+ }
+#define SET_PDMA_LRO_CNT_OVERFLOW_ADJ(x) \
+ { volatile unsigned int *addr = (unsigned int*)PDMA_LRO_ATL_OVERFLOW_ADJ; \
+ *addr &= ~PDMA_LRO_CNT_OVERFLOW_ADJ; \
+ *addr |= ((x) & 0xfff)<<PDMA_LRO_CNT_OVERFLOW_ADJ_OFFSET; \
+ }
+#define SET_PDMA_LRO_ALT_REFRESH_TIMER_UNIT(x) \
+ { volatile unsigned int *addr = (unsigned int*)LRO_ALT_REFRESH_TIMER; \
+ *addr &= ~PDMA_LRO_ALT_TICK_TIMER; \
+ *addr |= ((x) & 0x1f)<<PDMA_LRO_ALT_TICK_TIMER_OFFSET; \
+ }
+#define SET_PDMA_LRO_ALT_REFRESH_TIMER(x) \
+ { volatile unsigned int *addr = (unsigned int*)LRO_ALT_REFRESH_TIMER; \
+ *addr &= ~0xffff; \
+ *addr |= ((x) & 0xffff); \
+ }
+#define SET_PDMA_LRO_MAX_AGG_TIME(x) \
+ { volatile unsigned int *addr = (unsigned int*)LRO_MAX_AGG_TIME; \
+ *addr &= ~0xffff; \
+ *addr |= ((x) & 0xffff); \
+ }
+#define SET_PDMA_RXRING_MODE(x,y) \
+ { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING0_CTRL_DW2 + ((x) << 6)); \
+ *addr &= ~(0x3<<PDMA_RX_MODE_OFFSET); \
+ *addr |= (y)<<PDMA_RX_MODE_OFFSET; \
+ }
+#define SET_PDMA_RXRING_MYIP_VALID(x,y) \
+ { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING0_CTRL_DW2 + ((x) << 6)); \
+ *addr &= ~(0x1<<PDMA_RX_MYIP_VALID_OFFSET); \
+ *addr |= ((y)&0x1)<<PDMA_RX_MYIP_VALID_OFFSET; \
+ }
+#define SET_PDMA_RXRING_VALID(x,y) \
+ { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING0_CTRL_DW2 + ((x) << 6)); \
+ *addr &= ~(0x1<<PDMA_RX_PORT_VALID_OFFSET); \
+ *addr |= ((y)&0x1)<<PDMA_RX_PORT_VALID_OFFSET; \
+ }
+#define SET_PDMA_RXRING_TCP_SRC_PORT(x,y) \
+ { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING1_STP_DTP_DW + (((x)-1) << 6)); \
+ *addr &= ~(0xffff<<PDMA_RX_TCP_SRC_PORT_OFFSET); \
+ *addr |= (y)<<PDMA_RX_TCP_SRC_PORT_OFFSET; \
+ }
+#define SET_PDMA_RXRING_TCP_DEST_PORT(x,y) \
+ { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING1_STP_DTP_DW + (((x)-1) << 6)); \
+ *addr &= ~(0xffff<<PDMA_RX_TCP_DEST_PORT_OFFSET); \
+ *addr |= (y)<<PDMA_RX_TCP_DEST_PORT_OFFSET; \
+ }
+#define SET_PDMA_RXRING_IPV4_FORCE_MODE(x,y) \
+ { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING1_CTRL_DW0 + (((x)-1) << 6)); \
+ *addr &= ~(0x1<<PDMA_RX_IPV4_FORCE_OFFSET); \
+ *addr |= (y)<<PDMA_RX_IPV4_FORCE_OFFSET; \
+ }
+#define SET_PDMA_RXRING_IPV6_FORCE_MODE(x,y) \
+ { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING1_CTRL_DW0 + (((x)-1) << 6)); \
+ *addr &= ~(0x1<<PDMA_RX_IPV6_FORCE_OFFSET); \
+ *addr |= (y)<<PDMA_RX_IPV6_FORCE_OFFSET; \
+ }
+#define SET_PDMA_RXRING_AGE_TIME(x,y) \
+ { volatile unsigned int *addr1 = (unsigned int*)(LRO_RX_RING0_CTRL_DW1 + ((x) << 6)); \
+ volatile unsigned int *addr2 = (unsigned int*)(LRO_RX_RING0_CTRL_DW2 + ((x) << 6)); \
+ *addr1 &= ~PDMA_LRO_RING_AGE1; \
+ *addr2 &= ~PDMA_LRO_RING_AGE2; \
+ *addr1 |= ((y) & 0x3ff)<<PDMA_LRO_RING_AGE1_OFFSET; \
+ *addr2 |= (((y)>>PDMA_LRO_AGE_H_OFFSET) & 0x03f)<<PDMA_LRO_RING_AGE2_OFFSET; \
+ }
+#define SET_PDMA_RXRING_AGG_TIME(x,y) \
+ { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING0_CTRL_DW2 + ((x) << 6)); \
+ *addr &= ~PDMA_LRO_RING_AGG; \
+ *addr |= ((y) & 0xffff)<<PDMA_LRO_RING_AGG_OFFSET; \
+ }
+#define SET_PDMA_RXRING_MAX_AGG_CNT(x,y) \
+ { volatile unsigned int *addr1 = (unsigned int*)(LRO_RX_RING1_CTRL_DW2 + (((x)-1) << 6)); \
+ volatile unsigned int *addr2 = (unsigned int*)(LRO_RX_RING1_CTRL_DW3 + (((x)-1) << 6)); \
+ *addr1 &= ~PDMA_LRO_RING_AGG_CNT1; \
+ *addr2 &= ~PDMA_LRO_RING_AGG_CNT2; \
+ *addr1 |= ((y) & 0x3f)<<PDMA_LRO_RING_AGG_CNT1_OFFSET; \
+ *addr2 |= (((y)>>PDMA_LRO_AGG_CNT_H_OFFSET) & 0x03)<<PDMA_LRO_RING_AGG_CNT2_OFFSET; \
+ }
+
+typedef struct _PDMA_LRO_AUTO_TLB_INFO0_ PDMA_LRO_AUTO_TLB_INFO0_T;
+typedef struct _PDMA_LRO_AUTO_TLB_INFO1_ PDMA_LRO_AUTO_TLB_INFO1_T;
+typedef struct _PDMA_LRO_AUTO_TLB_INFO2_ PDMA_LRO_AUTO_TLB_INFO2_T;
+typedef struct _PDMA_LRO_AUTO_TLB_INFO3_ PDMA_LRO_AUTO_TLB_INFO3_T;
+typedef struct _PDMA_LRO_AUTO_TLB_INFO4_ PDMA_LRO_AUTO_TLB_INFO4_T;
+typedef struct _PDMA_LRO_AUTO_TLB_INFO5_ PDMA_LRO_AUTO_TLB_INFO5_T;
+typedef struct _PDMA_LRO_AUTO_TLB_INFO6_ PDMA_LRO_AUTO_TLB_INFO6_T;
+typedef struct _PDMA_LRO_AUTO_TLB_INFO7_ PDMA_LRO_AUTO_TLB_INFO7_T;
+typedef struct _PDMA_LRO_AUTO_TLB_INFO8_ PDMA_LRO_AUTO_TLB_INFO8_T;
+
+struct _PDMA_LRO_AUTO_TLB_INFO0_
+{
+ unsigned int DTP : 16;
+ unsigned int STP : 16;
+};
+struct _PDMA_LRO_AUTO_TLB_INFO1_
+{
+ unsigned int SIP0 : 32;
+};
+struct _PDMA_LRO_AUTO_TLB_INFO2_
+{
+ unsigned int SIP1 : 32;
+};
+struct _PDMA_LRO_AUTO_TLB_INFO3_
+{
+ unsigned int SIP2 : 32;
+};
+struct _PDMA_LRO_AUTO_TLB_INFO4_
+{
+ unsigned int SIP3 : 32;
+};
+struct _PDMA_LRO_AUTO_TLB_INFO5_
+{
+ unsigned int VLAN_VID0 : 32;
+};
+struct _PDMA_LRO_AUTO_TLB_INFO6_
+{
+ unsigned int VLAN_VID1 : 16;
+ unsigned int VLAN_VID_VLD : 4;
+ unsigned int CNT : 12;
+};
+struct _PDMA_LRO_AUTO_TLB_INFO7_
+{
+ unsigned int DW_LEN : 32;
+};
+struct _PDMA_LRO_AUTO_TLB_INFO8_
+{
+ unsigned int DIP_ID : 2;
+ unsigned int IPV6 : 1;
+ unsigned int IPV4 : 1;
+ unsigned int RESV : 27;
+ unsigned int VALID : 1;
+};
+struct PDMA_LRO_AUTO_TLB_INFO {
+ PDMA_LRO_AUTO_TLB_INFO0_T auto_tlb_info0;
+ PDMA_LRO_AUTO_TLB_INFO1_T auto_tlb_info1;
+ PDMA_LRO_AUTO_TLB_INFO2_T auto_tlb_info2;
+ PDMA_LRO_AUTO_TLB_INFO3_T auto_tlb_info3;
+ PDMA_LRO_AUTO_TLB_INFO4_T auto_tlb_info4;
+ PDMA_LRO_AUTO_TLB_INFO5_T auto_tlb_info5;
+ PDMA_LRO_AUTO_TLB_INFO6_T auto_tlb_info6;
+ PDMA_LRO_AUTO_TLB_INFO7_T auto_tlb_info7;
+ PDMA_LRO_AUTO_TLB_INFO8_T auto_tlb_info8;
+};
+
+#if defined (CONFIG_HW_SFQ)
+#define VQTX_TB_BASE0 (ETHDMASYS_FRAME_ENGINE_BASE + 0x1980)
+#define VQTX_TB_BASE1 (ETHDMASYS_FRAME_ENGINE_BASE + 0x1984)
+#define VQTX_TB_BASE2 (ETHDMASYS_FRAME_ENGINE_BASE + 0x1988)
+#define VQTX_TB_BASE3 (ETHDMASYS_FRAME_ENGINE_BASE + 0x198C)
+#define SFQ_OFFSET 0x1A80
+#define VQTX_GLO (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET)
+#define VQTX_INVLD_PTR (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x0C)
+#define VQTX_NUM (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x10)
+#define VQTX_SCH (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x18)
+#define VQTX_HASH_CFG (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x20)
+#define VQTX_HASH_SD (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x24)
+#define VQTX_VLD_CFG (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x30)
+#define VQTX_MIB_IF (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x3C)
+#define VQTX_MIB_PCNT (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x40)
+#define VQTX_MIB_BCNT0 (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x44)
+#define VQTX_MIB_BCNT1 (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x48)
+
+#define VQTX_MIB_EN (1<<17)
+#define VQTX_NUM_0 (4<<0)
+#define VQTX_NUM_1 (4<<4)
+#define VQTX_NUM_2 (4<<8)
+#define VQTX_NUM_3 (4<<12)
+
+/*=========================================
+ SFQ Table Format define
+=========================================*/
+typedef struct _SFQ_INFO1_ SFQ_INFO1_T;
+
+struct _SFQ_INFO1_
+{
+ unsigned int VQHPTR;
+};
+//-------------------------------------------------
+typedef struct _SFQ_INFO2_ SFQ_INFO2_T;
+
+struct _SFQ_INFO2_
+{
+ unsigned int VQTPTR;
+};
+//-------------------------------------------------
+typedef struct _SFQ_INFO3_ SFQ_INFO3_T;
+
+struct _SFQ_INFO3_
+{
+ unsigned int QUE_DEPTH:16;
+ unsigned int DEFICIT_CNT:16;
+};
+//-------------------------------------------------
+typedef struct _SFQ_INFO4_ SFQ_INFO4_T;
+
+struct _SFQ_INFO4_
+{
+ unsigned int RESV;
+};
+//-------------------------------------------------
+
+typedef struct _SFQ_INFO5_ SFQ_INFO5_T;
+
+struct _SFQ_INFO5_
+{
+ unsigned int PKT_CNT;
+};
+//-------------------------------------------------
+
+typedef struct _SFQ_INFO6_ SFQ_INFO6_T;
+
+struct _SFQ_INFO6_
+{
+ unsigned int BYTE_CNT;
+};
+//-------------------------------------------------
+
+typedef struct _SFQ_INFO7_ SFQ_INFO7_T;
+
+struct _SFQ_INFO7_
+{
+ unsigned int BYTE_CNT;
+};
+//-------------------------------------------------
+
+typedef struct _SFQ_INFO8_ SFQ_INFO8_T;
+
+struct _SFQ_INFO8_
+{
+ unsigned int RESV;
+};
+
+
+struct SFQ_table {
+ SFQ_INFO1_T sfq_info1;
+ SFQ_INFO2_T sfq_info2;
+ SFQ_INFO3_T sfq_info3;
+ SFQ_INFO4_T sfq_info4;
+ SFQ_INFO5_T sfq_info5;
+ SFQ_INFO6_T sfq_info6;
+ SFQ_INFO7_T sfq_info7;
+ SFQ_INFO8_T sfq_info8;
+
+};
+#endif
+#if defined (CONFIG_RAETH_HW_LRO) || defined (CONFIG_RAETH_MULTIPLE_RX_RING)
+#define FE_GDM_RXID1_OFFSET (0x0130)
+#define FE_GDM_RXID1 (RALINK_FRAME_ENGINE_BASE+FE_GDM_RXID1_OFFSET)
+#define GDM_VLAN_PRI7_RXID_SEL BITS(30,31)
+#define GDM_VLAN_PRI6_RXID_SEL BITS(28,29)
+#define GDM_VLAN_PRI5_RXID_SEL BITS(26,27)
+#define GDM_VLAN_PRI4_RXID_SEL BITS(24,25)
+#define GDM_VLAN_PRI3_RXID_SEL BITS(22,23)
+#define GDM_VLAN_PRI2_RXID_SEL BITS(20,21)
+#define GDM_VLAN_PRI1_RXID_SEL BITS(18,19)
+#define GDM_VLAN_PRI0_RXID_SEL BITS(16,17)
+#define GDM_TCP_ACK_RXID_SEL BITS(4,5)
+#define GDM_TCP_ACK_WZPC BIT(3)
+#define GDM_RXID_PRI_SEL BITS(0,2)
+
+#define FE_GDM_RXID2_OFFSET (0x0134)
+#define FE_GDM_RXID2 (RALINK_FRAME_ENGINE_BASE+FE_GDM_RXID2_OFFSET)
+#define GDM_STAG7_RXID_SEL BITS(30,31)
+#define GDM_STAG6_RXID_SEL BITS(28,29)
+#define GDM_STAG5_RXID_SEL BITS(26,27)
+#define GDM_STAG4_RXID_SEL BITS(24,25)
+#define GDM_STAG3_RXID_SEL BITS(22,23)
+#define GDM_STAG2_RXID_SEL BITS(20,21)
+#define GDM_STAG1_RXID_SEL BITS(18,19)
+#define GDM_STAG0_RXID_SEL BITS(16,17)
+#define GDM_PID2_RXID_SEL BITS(2,3)
+#define GDM_PID1_RXID_SEL BITS(0,1)
+
+#define GDM_PRI_PID (0)
+#define GDM_PRI_VLAN_PID (1)
+#define GDM_PRI_ACK_PID (2)
+#define GDM_PRI_VLAN_ACK_PID (3)
+#define GDM_PRI_ACK_VLAN_PID (4)
+
+#define SET_GDM_VLAN_PRI_RXID_SEL(x,y) \
+ { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID1; \
+ *addr &= ~(0x03 << (((x) << 1)+16)); \
+ *addr |= ((y) & 0x3) << (((x) << 1)+16); \
+ }
+#define SET_GDM_TCP_ACK_RXID_SEL(x) \
+ { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID1; \
+ *addr &= ~(GDM_TCP_ACK_RXID_SEL); \
+ *addr |= ((x) & 0x3) << 4; \
+ }
+#define SET_GDM_TCP_ACK_WZPC(x) \
+ { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID1; \
+ *addr &= ~(GDM_TCP_ACK_WZPC); \
+ *addr |= ((x) & 0x1) << 3; \
+ }
+#define SET_GDM_RXID_PRI_SEL(x) \
+ { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID1; \
+ *addr &= ~(GDM_RXID_PRI_SEL); \
+ *addr |= (x) & 0x7; \
+ }
+#define GDM_STAG_RXID_SEL(x,y) \
+ { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID2; \
+ *addr &= ~(0x03 << (((x) << 1)+16)); \
+ *addr |= ((y) & 0x3) << (((x) << 1)+16); \
+ }
+#define SET_GDM_PID2_RXID_SEL(x) \
+ { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID2; \
+ *addr &= ~(GDM_PID2_RXID_SEL); \
+ *addr |= ((x) & 0x3) << 2; \
+ }
+#define SET_GDM_PID1_RXID_SEL(x) \
+ { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID2; \
+ *addr &= ~(GDM_PID1_RXID_SEL); \
+ *addr |= ((x) & 0x3); \
+ }
+#endif /* CONFIG_RAETH_MULTIPLE_RX_RING */
+/* Per Port Packet Counts in RT3052, added by bobtseng 2009.4.17. */
+#define PORT0_PKCOUNT (0xb01100e8)
+#define PORT1_PKCOUNT (0xb01100ec)
+#define PORT2_PKCOUNT (0xb01100f0)
+#define PORT3_PKCOUNT (0xb01100f4)
+#define PORT4_PKCOUNT (0xb01100f8)
+#define PORT5_PKCOUNT (0xb01100fc)
+
+#if defined (CONFIG_ARCH_MT7623)
+#include "sync_write.h"
+#define sysRegRead(phys) (*(volatile unsigned int *)((phys)))
+#define sysRegWrite(phys, val) mt65xx_reg_sync_writel((val), (phys))
+#else
+#define PHYS_TO_K1(physaddr) KSEG1ADDR(physaddr)
+#define sysRegRead(phys) (*(volatile unsigned int *)PHYS_TO_K1(phys))
+#define sysRegWrite(phys, val) ((*(volatile unsigned int *)PHYS_TO_K1(phys)) = (val))
+#endif
+
+#define u_long unsigned long
+#define u32 unsigned int
+#define u16 unsigned short
+
+
+/* ====================================== */
+#define GDM1_DISPAD BIT(18)
+#define GDM1_DISCRC BIT(17)
+
+//GDMA1 uni-cast frames destination port
+#define GDM1_ICS_EN (0x1 << 22)
+#define GDM1_TCS_EN (0x1 << 21)
+#define GDM1_UCS_EN (0x1 << 20)
+#define GDM1_JMB_EN (0x1 << 19)
+#define GDM1_STRPCRC (0x1 << 16)
+#define GDM1_UFRC_P_CPU (0 << 12)
+#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
+#define GDM1_UFRC_P_PPE (4 << 12)
+#else
+#define GDM1_UFRC_P_PPE (6 << 12)
+#endif
+
+//GDMA1 broad-cast MAC address frames
+#define GDM1_BFRC_P_CPU (0 << 8)
+#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
+#define GDM1_BFRC_P_PPE (4 << 8)
+#else
+#define GDM1_BFRC_P_PPE (6 << 8)
+#endif
+
+//GDMA1 multi-cast MAC address frames
+#define GDM1_MFRC_P_CPU (0 << 4)
+#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
+#define GDM1_MFRC_P_PPE (4 << 4)
+#else
+#define GDM1_MFRC_P_PPE (6 << 4)
+#endif
+
+//GDMA1 other MAC address frames destination port
+#define GDM1_OFRC_P_CPU (0 << 0)
+#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
+#define GDM1_OFRC_P_PPE (4 << 0)
+#else
+#define GDM1_OFRC_P_PPE (6 << 0)
+#endif
+
+#if defined (CONFIG_RALINK_RT6856) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
+/* checksum generator registers are removed */
+#define ICS_GEN_EN (0 << 2)
+#define UCS_GEN_EN (0 << 1)
+#define TCS_GEN_EN (0 << 0)
+#else
+#define ICS_GEN_EN (1 << 2)
+#define UCS_GEN_EN (1 << 1)
+#define TCS_GEN_EN (1 << 0)
+#endif
+
+// MDIO_CFG bit
+#define MDIO_CFG_GP1_FC_TX (1 << 11)
+#define MDIO_CFG_GP1_FC_RX (1 << 10)
+
+/* ====================================== */
+/* ====================================== */
+#define GP1_LNK_DWN BIT(9)
+#define GP1_AN_FAIL BIT(8)
+/* ====================================== */
+/* ====================================== */
+#define PSE_RESET BIT(0)
+/* ====================================== */
+#define PST_DRX_IDX3 BIT(19)
+#define PST_DRX_IDX2 BIT(18)
+#define PST_DRX_IDX1 BIT(17)
+#define PST_DRX_IDX0 BIT(16)
+#define PST_DTX_IDX3 BIT(3)
+#define PST_DTX_IDX2 BIT(2)
+#define PST_DTX_IDX1 BIT(1)
+#define PST_DTX_IDX0 BIT(0)
+
+#define RX_2B_OFFSET BIT(31)
+#define DESC_32B_EN BIT(8)
+#define TX_WB_DDONE BIT(6)
+#define RX_DMA_BUSY BIT(3)
+#define TX_DMA_BUSY BIT(1)
+#define RX_DMA_EN BIT(2)
+#define TX_DMA_EN BIT(0)
+
+#define PDMA_BT_SIZE_4DWORDS (0<<4)
+#define PDMA_BT_SIZE_8DWORDS (1<<4)
+#define PDMA_BT_SIZE_16DWORDS (2<<4)
+#define PDMA_BT_SIZE_32DWORDS (3<<4)
+
+#define ADMA_RX_BT_SIZE_4DWORDS (0<<11)
+#define ADMA_RX_BT_SIZE_8DWORDS (1<<11)
+#define ADMA_RX_BT_SIZE_16DWORDS (2<<11)
+#define ADMA_RX_BT_SIZE_32DWORDS (3<<11)
+
+/* Register bits.
+ */
+
+#define MACCFG_RXEN (1<<2)
+#define MACCFG_TXEN (1<<3)
+#define MACCFG_PROMISC (1<<18)
+#define MACCFG_RXMCAST (1<<19)
+#define MACCFG_FDUPLEX (1<<20)
+#define MACCFG_PORTSEL (1<<27)
+#define MACCFG_HBEATDIS (1<<28)
+
+
+#define DMACTL_SR (1<<1) /* Start/Stop Receive */
+#define DMACTL_ST (1<<13) /* Start/Stop Transmission Command */
+
+#define DMACFG_SWR (1<<0) /* Software Reset */
+#define DMACFG_BURST32 (32<<8)
+
+#define DMASTAT_TS 0x00700000 /* Transmit Process State */
+#define DMASTAT_RS 0x000e0000 /* Receive Process State */
+
+#define MACCFG_INIT 0 //(MACCFG_FDUPLEX) // | MACCFG_PORTSEL)
+
+
+
+/* Descriptor bits.
+ */
+#define R_OWN 0x80000000 /* Own Bit */
+#define RD_RER 0x02000000 /* Receive End Of Ring */
+#define RD_LS 0x00000100 /* Last Descriptor */
+#define RD_ES 0x00008000 /* Error Summary */
+#define RD_CHAIN 0x01000000 /* Chained */
+
+/* Word 0 */
+#define T_OWN 0x80000000 /* Own Bit */
+#define TD_ES 0x00008000 /* Error Summary */
+
+/* Word 1 */
+#define TD_LS 0x40000000 /* Last Segment */
+#define TD_FS 0x20000000 /* First Segment */
+#define TD_TER 0x08000000 /* Transmit End Of Ring */
+#define TD_CHAIN 0x01000000 /* Chained */
+
+
+#define TD_SET 0x08000000 /* Setup Packet */
+
+
+#define POLL_DEMAND 1
+
+#define RSTCTL (0x34)
+#define RSTCTL_RSTENET1 (1<<19)
+#define RSTCTL_RSTENET2 (1<<20)
+
+#define INIT_VALUE_OF_RT2883_PSE_FQ_CFG 0xff908000
+#define INIT_VALUE_OF_PSE_FQFC_CFG 0x80504000
+#define INIT_VALUE_OF_FORCE_100_FD 0x1001BC01
+#define INIT_VALUE_OF_FORCE_1000_FD 0x1F01DC01
+
+// Define Whole FE Reset Register
+#define RSTCTRL (RALINK_SYSCTL_BASE + 0x34)
+#define RT2880_AGPIOCFG_REG (RALINK_SYSCTL_BASE + 0x3C)
+
+/*=========================================
+ PDMA RX Descriptor Format define
+=========================================*/
+
+//-------------------------------------------------
+typedef struct _PDMA_RXD_INFO1_ PDMA_RXD_INFO1_T;
+
+struct _PDMA_RXD_INFO1_
+{
+ unsigned int PDP0;
+};
+//-------------------------------------------------
+typedef struct _PDMA_RXD_INFO2_ PDMA_RXD_INFO2_T;
+
+struct _PDMA_RXD_INFO2_
+{
+#if defined (CONFIG_ARCH_MT7623)
+ unsigned int PLEN1 : 2;
+ unsigned int LRO_AGG_CNT : 8;
+ unsigned int REV : 5;
+#else
+ unsigned int PLEN1 : 14;
+ unsigned int LS1 : 1;
+#endif /* CONFIG_RAETH_HW_LRO */
+ unsigned int TAG : 1;
+ unsigned int PLEN0 : 14;
+ unsigned int LS0 : 1;
+ unsigned int DDONE_bit : 1;
+};
+//-------------------------------------------------
+typedef struct _PDMA_RXD_INFO3_ PDMA_RXD_INFO3_T;
+
+struct _PDMA_RXD_INFO3_
+{
+ unsigned int VID:16;
+ unsigned int TPID:16;
+};
+//-------------------------------------------------
+typedef struct _PDMA_RXD_INFO4_ PDMA_RXD_INFO4_T;
+
+struct _PDMA_RXD_INFO4_
+{
+#if defined (CONFIG_RALINK_MT7620)
+ unsigned int FOE_Entry : 14;
+ unsigned int CRSN : 5;
+ unsigned int SPORT : 3;
+ unsigned int L4F : 1;
+ unsigned int L4VLD : 1;
+ unsigned int TACK : 1;
+ unsigned int IP4F : 1;
+ unsigned int IP4 : 1;
+ unsigned int IP6 : 1;
+ unsigned int UN_USE1 : 4;
+#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
+ unsigned int FOE_Entry : 14;
+ unsigned int CRSN : 5;
+ unsigned int SP : 4;
+ unsigned int L4F : 1;
+ unsigned int L4VLD : 1;
+ unsigned int TACK : 1;
+ unsigned int IP4F : 1;
+ unsigned int IP4 : 1;
+ unsigned int IP6 : 1;
+ unsigned int UN_USE1 : 3;
+#else
+ unsigned int FOE_Entry : 14;
+ unsigned int FVLD : 1;
+ unsigned int UN_USE1 : 1;
+ unsigned int AI : 8;
+ unsigned int SP : 3;
+ unsigned int AIS : 1;
+ unsigned int L4F : 1;
+ unsigned int IPF : 1;
+ unsigned int L4FVLD_bit : 1;
+ unsigned int IPFVLD_bit : 1;
+#endif
+};
+
+
+struct PDMA_rxdesc {
+ PDMA_RXD_INFO1_T rxd_info1;
+ PDMA_RXD_INFO2_T rxd_info2;
+ PDMA_RXD_INFO3_T rxd_info3;
+ PDMA_RXD_INFO4_T rxd_info4;
+#ifdef CONFIG_32B_DESC
+ unsigned int rxd_info5;
+ unsigned int rxd_info6;
+ unsigned int rxd_info7;
+ unsigned int rxd_info8;
+#endif
+};
+
+/*=========================================
+ PDMA TX Descriptor Format define
+=========================================*/
+//-------------------------------------------------
+typedef struct _PDMA_TXD_INFO1_ PDMA_TXD_INFO1_T;
+
+struct _PDMA_TXD_INFO1_
+{
+ unsigned int SDP0;
+};
+//-------------------------------------------------
+typedef struct _PDMA_TXD_INFO2_ PDMA_TXD_INFO2_T;
+
+struct _PDMA_TXD_INFO2_
+{
+ unsigned int SDL1 : 14;
+ unsigned int LS1_bit : 1;
+ unsigned int BURST_bit : 1;
+ unsigned int SDL0 : 14;
+ unsigned int LS0_bit : 1;
+ unsigned int DDONE_bit : 1;
+};
+//-------------------------------------------------
+typedef struct _PDMA_TXD_INFO3_ PDMA_TXD_INFO3_T;
+
+struct _PDMA_TXD_INFO3_
+{
+ unsigned int SDP1;
+};
+//-------------------------------------------------
+typedef struct _PDMA_TXD_INFO4_ PDMA_TXD_INFO4_T;
+
+struct _PDMA_TXD_INFO4_
+{
+#if defined (CONFIG_RALINK_MT7620)
+ unsigned int VPRI_VIDX : 8;
+ unsigned int SIDX : 4;
+ unsigned int INSP : 1;
+ unsigned int RESV : 2;
+ unsigned int UDF : 5;
+ unsigned int FP_BMAP : 8;
+ unsigned int TSO : 1;
+ unsigned int TUI_CO : 3;
+#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
+ unsigned int VLAN_TAG :17; // INSV(1)+VPRI(3)+CFI(1)+VID(12)
+ unsigned int RESV : 2;
+ unsigned int UDF : 6;
+ unsigned int FPORT : 3;
+ unsigned int TSO : 1;
+ unsigned int TUI_CO : 3;
+#else
+ unsigned int VPRI_VIDX : 8;
+ unsigned int SIDX : 4;
+ unsigned int INSP : 1;
+ unsigned int RESV : 1;
+ unsigned int UN_USE3 : 2;
+ unsigned int QN : 3;
+ unsigned int UN_USE2 : 1;
+ unsigned int UDF : 4;
+ unsigned int PN : 3;
+ unsigned int UN_USE1 : 1;
+ unsigned int TSO : 1;
+ unsigned int TUI_CO : 3;
+#endif
+};
+
+
+struct PDMA_txdesc {
+ PDMA_TXD_INFO1_T txd_info1;
+ PDMA_TXD_INFO2_T txd_info2;
+ PDMA_TXD_INFO3_T txd_info3;
+ PDMA_TXD_INFO4_T txd_info4;
+#ifdef CONFIG_32B_DESC
+ unsigned int txd_info5;
+ unsigned int txd_info6;
+ unsigned int txd_info7;
+ unsigned int txd_info8;
+#endif
+};
+
+
+#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
+/*=========================================
+ QDMA TX Descriptor Format define
+=========================================*/
+//-------------------------------------------------
+typedef struct _QDMA_TXD_INFO1_ QDMA_TXD_INFO1_T;
+
+struct _QDMA_TXD_INFO1_
+{
+ unsigned int SDP;
+};
+//-------------------------------------------------
+typedef struct _QDMA_TXD_INFO2_ QDMA_TXD_INFO2_T;
+
+struct _QDMA_TXD_INFO2_
+{
+ unsigned int NDP;
+};
+//-------------------------------------------------
+typedef struct _QDMA_TXD_INFO3_ QDMA_TXD_INFO3_T;
+
+struct _QDMA_TXD_INFO3_
+{
+ unsigned int QID : 4;
+#if defined (CONFIG_HW_SFQ)
+ //unsigned int VQID : 10;
+ unsigned int PROT : 3;
+ unsigned int IPOFST : 7;
+#else
+ unsigned int RESV : 10;
+#endif
+ unsigned int SWC_bit : 1;
+ unsigned int BURST_bit : 1;
+ unsigned int SDL : 14;
+ unsigned int LS_bit : 1;
+ unsigned int OWN_bit : 1;
+};
+//-------------------------------------------------
+typedef struct _QDMA_TXD_INFO4_ QDMA_TXD_INFO4_T;
+
+struct _QDMA_TXD_INFO4_
+{
+ unsigned int VLAN_TAG :17; // INSV(1)+VPRI(3)+CFI(1)+VID(12)
+#if defined (CONFIG_RALINK_MT7621)
+ unsigned int RESV : 2;
+ unsigned int UDF : 6;
+#elif defined(CONFIG_ARCH_MT7623)
+ unsigned int VQID0 : 1;
+ unsigned int RESV : 7;
+#endif
+ unsigned int FPORT : 3;
+ unsigned int TSO : 1;
+ unsigned int TUI_CO : 3;
+};
+
+
+struct QDMA_txdesc {
+ QDMA_TXD_INFO1_T txd_info1;
+ QDMA_TXD_INFO2_T txd_info2;
+ QDMA_TXD_INFO3_T txd_info3;
+ QDMA_TXD_INFO4_T txd_info4;
+#ifdef CONFIG_32B_DESC
+ unsigned int txd_info5;
+ unsigned int txd_info6;
+ unsigned int txd_info7;
+ unsigned int txd_info8;
+#endif
+};
+#endif
+
+#if defined (CONFIG_ARCH_MT7623)
+#define phys_to_bus(a) (a)
+#else
+#define phys_to_bus(a) (a & 0x1FFFFFFF)
+#endif
+
+#define PHY_Enable_Auto_Nego 0x1000
+#define PHY_Restart_Auto_Nego 0x0200
+
+/* PHY_STAT_REG = 1; */
+#define PHY_Auto_Neco_Comp 0x0020
+#define PHY_Link_Status 0x0004
+
+/* PHY_AUTO_NEGO_REG = 4; */
+#define PHY_Cap_10_Half 0x0020
+#define PHY_Cap_10_Full 0x0040
+#define PHY_Cap_100_Half 0x0080
+#define PHY_Cap_100_Full 0x0100
+
+/* proc definition */
+
+#if !defined (CONFIG_RALINK_RT6855) && !defined(CONFIG_RALINK_RT6855A) && \
+ !defined (CONFIG_RALINK_MT7620) && !defined (CONFIG_RALINK_MT7621) && \
+ !defined (CONFIG_ARCH_MT7623)
+#define CDMA_OQ_STA (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x4c)
+#define GDMA1_OQ_STA (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x50)
+#define PPE_OQ_STA (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x54)
+#define PSE_IQ_STA (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x58)
+#endif
+
+#define PROCREG_CONTROL_FILE "/var/run/procreg_control"
+#if defined (CONFIG_RALINK_RT2880)
+#define PROCREG_DIR "rt2880"
+#elif defined (CONFIG_RALINK_RT3052)
+#define PROCREG_DIR "rt3052"
+#elif defined (CONFIG_RALINK_RT3352)
+#define PROCREG_DIR "rt3352"
+#elif defined (CONFIG_RALINK_RT5350)
+#define PROCREG_DIR "rt5350"
+#elif defined (CONFIG_RALINK_RT2883)
+#define PROCREG_DIR "rt2883"
+#elif defined (CONFIG_RALINK_RT3883)
+#define PROCREG_DIR "rt3883"
+#elif defined (CONFIG_RALINK_RT6855)
+#define PROCREG_DIR "rt6855"
+#elif defined (CONFIG_RALINK_MT7620)
+#define PROCREG_DIR "mt7620"
+#elif defined (CONFIG_RALINK_MT7621)
+#define PROCREG_DIR "mt7621"
+#elif defined (CONFIG_ARCH_MT7623)
+#define PROCREG_DIR "mt7623"
+#elif defined (CONFIG_RALINK_MT7628)
+#define PROCREG_DIR "mt7628"
+#elif defined (CONFIG_RALINK_RT6855A)
+#define PROCREG_DIR "rt6855a"
+#else
+#define PROCREG_DIR "rt2880"
+#endif
+#define PROCREG_SKBFREE "skb_free"
+#define PROCREG_TXRING "tx_ring"
+#define PROCREG_RXRING "rx_ring"
+#define PROCREG_RXRING1 "rx_ring1"
+#define PROCREG_RXRING2 "rx_ring2"
+#define PROCREG_RXRING3 "rx_ring3"
+#define PROCREG_NUM_OF_TXD "num_of_txd"
+#define PROCREG_TSO_LEN "tso_len"
+#define PROCREG_LRO_STATS "lro_stats"
+#define PROCREG_HW_LRO_STATS "hw_lro_stats"
+#define PROCREG_HW_LRO_AUTO_TLB "hw_lro_auto_tlb"
+#define PROCREG_GMAC "gmac"
+#define PROCREG_GMAC2 "gmac2"
+#define PROCREG_CP0 "cp0"
+#define PROCREG_RAQOS "qos"
+#define PROCREG_READ_VAL "regread_value"
+#define PROCREG_WRITE_VAL "regwrite_value"
+#define PROCREG_ADDR "reg_addr"
+#define PROCREG_CTL "procreg_control"
+#define PROCREG_RXDONE_INTR "rxdone_intr_count"
+#define PROCREG_ESW_INTR "esw_intr_count"
+#define PROCREG_ESW_CNT "esw_cnt"
+#define PROCREG_SNMP "snmp"
+#if defined (TASKLET_WORKQUEUE_SW)
+#define PROCREG_SCHE "schedule"
+#endif
+#define PROCREG_QDMA "qdma"
+#if defined(CONFIG_RAETH_PDMA_DVT)
+#define PROCREG_PDMA_DVT "pdma_dvt"
+#endif //#if defined(CONFIG_RAETH_PDMA_DVT)
+struct rt2880_reg_op_data {
+ char name[64];
+ unsigned int reg_addr;
+ unsigned int op;
+ unsigned int reg_value;
+};
+
+#ifdef CONFIG_RAETH_LRO
+struct lro_counters {
+ u32 lro_aggregated;
+ u32 lro_flushed;
+ u32 lro_no_desc;
+};
+
+struct lro_para_struct {
+ unsigned int lan_ip1;
+};
+
+#endif // CONFIG_RAETH_LRO //
+
+
+#if defined (CONFIG_HW_SFQ)
+typedef struct {
+ //layer2 header
+ uint8_t dmac[6];
+ uint8_t smac[6];
+
+ //vlan header
+ uint16_t vlan_tag;
+ uint16_t vlan1_gap;
+ uint16_t vlan1;
+ uint16_t vlan2_gap;
+ uint16_t vlan2;
+ uint16_t vlan_layer;
+
+ //pppoe header
+ uint32_t pppoe_gap;
+ uint16_t ppp_tag;
+ uint16_t pppoe_sid;
+
+ //layer3 header
+ uint16_t eth_type;
+ struct iphdr iph;
+ struct ipv6hdr ip6h;
+
+ //layer4 header
+ struct tcphdr th;
+ struct udphdr uh;
+
+ uint32_t pkt_type;
+ uint8_t is_mcast;
+
+} ParseResult;
+#endif
+typedef struct end_device
+{
+
+ unsigned int tx_cpu_owner_idx0;
+ unsigned int rx_cpu_owner_idx0;
+ unsigned int fe_int_status;
+ unsigned int tx_full;
+
+#if !defined (CONFIG_RAETH_QDMA)
+ unsigned int phy_tx_ring0;
+#else
+ /* QDMA Tx PTR */
+ struct sk_buff *free_skb[NUM_TX_DESC];
+ unsigned int tx_dma_ptr;
+ unsigned int tx_cpu_ptr;
+ unsigned int free_txd_num;
+ unsigned int free_txd_head;
+ unsigned int free_txd_tail;
+ struct QDMA_txdesc *txd_pool;
+ dma_addr_t phy_txd_pool;
+ unsigned int txd_pool_info[NUM_TX_DESC];
+ struct QDMA_txdesc *free_head;
+ unsigned int phy_free_head;
+ unsigned int *free_page_head;
+ unsigned int phy_free_page_head;
+ struct PDMA_rxdesc *qrx_ring;
+ unsigned int phy_qrx_ring;
+#ifdef CONFIG_RAETH_PDMATX_QDMARX /* QDMA RX */
+ unsigned int phy_tx_ring0;
+#endif
+#endif
+
+ unsigned int phy_rx_ring0, phy_rx_ring1, phy_rx_ring2, phy_rx_ring3;
+
+#if defined (CONFIG_RALINK_RT3052) || 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)
+ //send signal to user application to notify link status changed
+ struct work_struct kill_sig_wq;
+#endif
+
+ struct work_struct reset_task;
+#ifdef WORKQUEUE_BH
+ struct work_struct rx_wq;
+#else
+#if defined (TASKLET_WORKQUEUE_SW)
+ struct work_struct rx_wq;
+#endif
+ struct tasklet_struct rx_tasklet;
+ struct tasklet_struct tx_tasklet;
+#endif // WORKQUEUE_BH //
+
+#if defined(CONFIG_RAETH_QOS)
+ struct sk_buff * skb_free[NUM_TX_RINGS][NUM_TX_DESC];
+ unsigned int free_idx[NUM_TX_RINGS];
+#else
+ struct sk_buff* skb_free[NUM_TX_DESC];
+ unsigned int free_idx;
+#endif
+
+ struct net_device_stats stat; /* The new statistics table. */
+ spinlock_t page_lock; /* Page register locks */
+ struct PDMA_txdesc *tx_ring0;
+#if defined(CONFIG_RAETH_QOS)
+ struct PDMA_txdesc *tx_ring1;
+ struct PDMA_txdesc *tx_ring2;
+ struct PDMA_txdesc *tx_ring3;
+#endif
+ struct PDMA_rxdesc *rx_ring0;
+ struct sk_buff *netrx0_skbuf[NUM_RX_DESC];
+#if defined (CONFIG_RAETH_HW_LRO)
+ struct PDMA_rxdesc *rx_ring3;
+ struct sk_buff *netrx3_skbuf[NUM_RX_DESC];
+ struct PDMA_rxdesc *rx_ring2;
+ struct sk_buff *netrx2_skbuf[NUM_RX_DESC];
+ struct PDMA_rxdesc *rx_ring1;
+ struct sk_buff *netrx1_skbuf[NUM_RX_DESC];
+#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
+ struct PDMA_rxdesc *rx_ring1;
+ struct sk_buff *netrx1_skbuf[NUM_RX_DESC];
+#if defined(CONFIG_ARCH_MT7623)
+ struct PDMA_rxdesc *rx_ring2;
+ struct sk_buff *netrx2_skbuf[NUM_RX_DESC];
+ struct PDMA_rxdesc *rx_ring3;
+ struct sk_buff *netrx3_skbuf[NUM_RX_DESC];
+#endif /* CONFIG_ARCH_MT7623 */
+#endif
+#ifdef CONFIG_RAETH_NAPI
+ atomic_t irq_sem;
+#if LINUX_VERSION_CODE > 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 <linux/module.h>
+#include <linux/version.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_ether.h>
+#include <linux/ethtool.h>
+
+#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 <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/signal.h>
+#include <linux/irq.h>
+#include <linux/ctype.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,4)
+#include <asm/system.h>
+#include <linux/mca.h>
+#endif
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include <asm/rt2880/surfboardint.h> /* for cp0 reg access, added by bobtseng */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+
+#include <linux/seq_file.h>
+
+
+#if defined(CONFIG_RAETH_LRO)
+#include <linux/inet_lro.h>
+#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; i<MAX_DESC; i++) {
+ tmp = &lro_mgr->lro_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; i<MAX_DESC; i++) {
+ tmp = &lro_mgr->lro_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; i<MAX_DESC; i++) {
+ tmp = &lro_mgr->lro_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 <<CPU>> \n");
+ seq_printf(seq, " | \n");
+#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
+ seq_printf(seq, "+-----------------------------------------------+\n");
+ seq_printf(seq, "| <<PDMA>> |\n");
+ seq_printf(seq, "+-----------------------------------------------+\n");
+#else
+ seq_printf(seq, "+-----------------------------------------------+\n");
+ seq_printf(seq, "| <<PSE>> |\n");
+ seq_printf(seq, "+-----------------------------------------------+\n");
+ seq_printf(seq, " | \n");
+ seq_printf(seq, "+-----------------------------------------------+\n");
+ seq_printf(seq, "| <<GDMA>> |\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 <asm/types.h>
+#include <net/sock.h>
+#include <linux/socket.h>
+#include <linux/netlink.h>
+#include <linux/skbuff.h>
+#include <linux/net.h>
+#include <linux/version.h>
+
+#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 <asm/io.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/net.h>
+#include <linux/in.h>
+#include "ra_qos.h"
+#include "raether.h"
+#include "ra2882ethreg.h"
+
+#include <asm/types.h>
+#include <net/sock.h>
+#include <linux/socket.h>
+#include <linux/skbuff.h>
+#include <linux/net.h>
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+
+
+#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 <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/signal.h>
+#include <linux/irq.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#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 <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/if_vlan.h>
+#include <linux/if_ether.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <asm/rt2880/surfboardint.h>
+#include <linux/platform_device.h>
+#if defined (CONFIG_RAETH_TSO)
+#include <linux/tcp.h>
+#include <net/ipv6.h>
+#include <linux/ip.h>
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <linux/in.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_pppox.h>
+#endif
+#if defined (CONFIG_RAETH_LRO)
+#include <linux/inet_lro.h>
+#endif
+#include <linux/delay.h>
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
+#include <linux/sched.h>
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
+#include <asm/rt2880/rt_mmap.h>
+#else
+#include <linux/libata-compat.h>
+#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 <asm/mipsregs.h>
+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)), &reg_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, &reg_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(&reg, 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, &reg, sizeof(reg));
+ break;
+ case RAETH_QDMA_REG_WRITE:
+ copy_from_user(&reg, 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(&reg, 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, &reg, sizeof(reg));
+ break;
+#endif
+ case RAETH_QDMA_QUEUE_MAPPING:
+ copy_from_user(&reg, 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(&reg, 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(&reg, 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, &reg, sizeof(reg));
+ break;
+ case RAETH_ESW_REG_WRITE:
+ copy_from_user(&reg, 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(&reg, 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, &regValue);
+ 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<<ether_gpio);
+
+ udelay(100000);
+
+ *(unsigned long *)(RALINK_PIO_BASE + 0x04) |= (1<<ether_gpio);
+
+ /* must wait for 0.6 seconds after reset*/
+ udelay(600000);
+}
+#endif
+
+#if defined(CONFIG_RALINK_RT6855A)
+void rt6855A_gsw_init(void)
+{
+ u32 phy_val=0;
+ u32 rev=0;
+
+#if defined (CONFIG_RT6855A_FPGA)
+ /*keep dump switch mode */
+ rt6855A_eth_gpio_reset();
+
+ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3000) = 0x5e353;//(P0,Force mode,Link Up,100Mbps,Full-Duplex,FC ON)
+ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3100) = 0x5e353;//(P1,Force mode,Link Up,100Mbps,Full-Duplex,FC ON)
+ //*(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) = 0x8000;//link down
+ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3300) = 0x8000;//link down
+ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x8000;//link down
+ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x8000;//link down
+ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3600) = 0x5e33b;//CPU Port6 Force Link 1G, FC ON
+
+ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0010) = 0xffffffe0;//Set Port6 CPU Port
+
+ /* 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=6;i<8;i++){
+ mii_mgr_write(i, 4, 0x07e1); //Capable of 10M&100M Full/Half Duplex, flow control on/off
+ //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
+ mii_mgr_read(i, 9, &phy_val);
+ phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
+ mii_mgr_write(i, 9, phy_val);
+ }
+#elif defined (CONFIG_RT6855A_ASIC)
+ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3600) = 0x5e33b;//CPU Port6 Force Link 1G, FC ON
+ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0010) = 0xffffffe0;//Set Port6 CPU Port
+
+ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE+0x1ec) = 0x0fffffff;//Set PSE should pause 4 tx ring as default
+ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE+0x1f0) = 0x0fffffff;//switch IOT more stable
+
+ *(unsigned long *)(CKGCR) &= ~(0x3 << 4); //keep rx/tx port clock ticking, disable internal clock-gating to avoid switch stuck
+
+ /*
+ *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 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 ,&regValue);
+ 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 ,&regValue);
+ 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, &regValue);
+ regValue &= ~1;
+ regValue |= 1<<1;
+ mii_mgr_write(31, 0x7830, regValue);
+
+ mii_mgr_read(31, 0x7a40, &regValue);
+ 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, &regValue);
+ 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, &regValue);
+ //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, &regValue);
+ 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 ,&regValue);
+ 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 ,&regValue);
+ 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 ,&regValue);
+ 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, &regValue);
+ 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, &regValue);
+ regValue &= ~1;
+ regValue |= 1<<1;
+ mii_mgr_write(31, 0x7830, regValue);
+
+ mii_mgr_read(31, 0x7a40, &regValue);
+ 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, &regValue);
+ 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, &regValue);
+ 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, &regValue);
+ 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 ,&regValue);
+ regValue &= ~(0x1<<11);
+ mii_mgr_write(i, 0x0, regValue);
+ }
+
+ mii_mgr_read(31, 0x7808 ,&regValue);
+ 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 ,&regValue);
+#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, &regValue);
+ regValue &= ~1;
+ regValue |= 1<<1;
+ mii_mgr_write(31, 0x7830, regValue);
+
+ mii_mgr_read(31, 0x7a40, &regValue);
+ 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 ,&regValue);
+ 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 ,&regValue);
+ }
+#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 ,&regValue);
+ 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, &regValue);
+ 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, &regValue);
+ regValue &= ~1;
+ regValue |= 1<<1;
+ mii_mgr_write(31, 0x7830, regValue);
+
+ mii_mgr_read(31, 0x7a40, &regValue);
+ 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 ,&regValue);
+ regValue &=0xFFFFFFFC;
+ regValue |=0x00000001;
+ mii_mgr_write(31, 0x7830, regValue);
+
+// printk("Set TRGMII mode clock stage 12\n");
+ mii_mgr_read(31, 0x7a40 ,&regValue);
+ 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 ,&regValue);
+ regValue &= ~(0x1<<11);
+ mii_mgr_write(i, 0x0, regValue);
+ }
+
+ for(i=0;i<=4;i++) {
+ mii_mgr_read(i, 4, &regValue);
+ regValue |= (3<<7); //turn on 100Base-T Advertisement
+ mii_mgr_write(i, 4, regValue);
+
+ mii_mgr_read(i, 9, &regValue);
+ regValue |= (3<<8); //turn on 1000Base-T Advertisement
+ mii_mgr_write(i, 9, regValue);
+
+ //restart AN
+ mii_mgr_read(i, 0, &regValue);
+ regValue |= (1 << 9);
+ mii_mgr_write(i, 0, regValue);
+ }
+
+ mii_mgr_read(31, 0x7808 ,&regValue);
+ 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, &regValue);
+ 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, &regValue);
+ 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, &regValue);
+ 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, &regValue);
+ 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, &regValue);
+ 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, &regValue);
+ 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, &regValue);
+ 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, &regValue);
+ 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, &regValue);
+ 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, &regValue);
+ 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, &regValue);
+ 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, &regValue);
+ 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 <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/if_vlan.h>
+#include <linux/if_ether.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <asm/rt2880/surfboardint.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <asm/rt2880/rt_mmap.h>
+#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 <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/if_vlan.h>
+#include <linux/if_ether.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <asm/rt2880/surfboardint.h>
+#if defined (CONFIG_RAETH_TSO)
+#include <linux/tcp.h>
+#include <net/ipv6.h>
+#include <linux/ip.h>
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <linux/in.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_pppox.h>
+#endif
+#if defined (CONFIG_RAETH_LRO)
+#include <linux/inet_lro.h>
+#endif
+#include <linux/delay.h>
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
+#include <linux/sched.h>
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
+#include <asm/rt2880/rt_mmap.h>
+#else
+#include <linux/libata-compat.h>
+#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 <asm/mipsregs.h>
+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;i<NUM_TX_RINGS;i++){
+ for (j=0;j<NUM_TX_DESC;j++){
+ ei_local->skb_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;i<NUM_TX_DESC;i++){
+ ei_local->skb_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;i<nr_frags;i++) {
+ frag = &skb_shinfo(skb)->frags[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;i<nr_frags;i++) {
+ frag = &skb_shinfo(skb)->frags[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;i<NUM_TX_RINGS;i++){
+ skb_free_idx = ei_local->free_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 <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/if_vlan.h>
+#include <linux/if_ether.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <asm/rt2880/surfboardint.h>
+#if defined (CONFIG_RAETH_TSO)
+#include <linux/tcp.h>
+#include <net/ipv6.h>
+#include <linux/ip.h>
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <linux/in.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_pppox.h>
+#endif
+#include <linux/delay.h>
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
+#include <linux/sched.h>
+#endif
+#if defined (CONFIG_HW_SFQ)
+#include <linux/if_vlan.h>
+#include <net/ipv6.h>
+#include <net/ip.h>
+#include <linux/if_pppox.h>
+#include <linux/ppp_defs.h>
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
+#include <asm/rt2880/rt_mmap.h>
+#else
+#include <linux/libata-compat.h>
+#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 <asm/mipsregs.h>
+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;i<nr_frags;i++) {
+ // 1. set or get init value for current fragment
+ offset = 0;
+ frag = &skb_shinfo(skb)->frags[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;i<nr_frags;i++) {
+ frag = &skb_shinfo(skb)->frags[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 <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/if_vlan.h>
+#include <linux/if_ether.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <asm/rt2880/surfboardint.h>
+#if defined (CONFIG_RAETH_TSO)
+#include <linux/tcp.h>
+#include <net/ipv6.h>
+#include <linux/ip.h>
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <linux/in.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_pppox.h>
+#endif
+#include <linux/delay.h>
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
+#include <linux/sched.h>
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
+#include <asm/rt2880/rt_mmap.h>
+#else
+#include <linux/libata-compat.h>
+#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 <asm/mipsregs.h>
+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;i<nr_frags;i++) {
+ // 1. set or get init value for current fragment
+ offset = 0;
+ frag = &skb_shinfo(skb)->frags[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;i<nr_frags;i++) {
+ frag = &skb_shinfo(skb)->frags[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 <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+
+
+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 <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <linux/inetdevice.h>
+#include <linux/tcp.h>
+#include <linux/ip.h>
+#include <net/tcp.h>
+#include <net/ip.h>
+
+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 <linux/io.h>
+#include <asm/cacheflush.h>
+//#include <asm/system.h>
+
+/*
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#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