/****************************************************************************** Copyright (c) 2012, 2014, 2015 Lantiq Deutschland GmbH For licensing information, see the file 'LICENSE' in the root folder of this software module. ******************************************************************************/ #include "gsw_init.h" #define PCE_MC_M3(val, msk, ns, out, len, type, flags, ipv4_len) \ { val, msk, (ns << 8 | out << 0),\ (len | type << 5 | flags << 8 | ipv4_len << 7)} const PCE_MICROCODE pce_mc_max_ifx_tag_m_30 = {/* V30_13 */ PCE_MC_M3(0x88C3 , 0xFFFF , 1 , OUT_ITAG0 , 4 , INSTR , FLAG_ITAG , 0), PCE_MC_M3(0x8100 , 0xFFFF , 4 , OUT_1VTAG0 , 2 , INSTR , FLAG_1VLAN , 0), PCE_MC_M3(0x88A8 , 0xFFFF , 4 , OUT_1VTAG0 , 2 , INSTR , FLAG_1VLAN , 0), PCE_MC_M3(0x0000 , 0x0000 , 15 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x8100 , 0xFFFF , 7 , OUT_2VTAG0 , 2 , INSTR , FLAG_2VLAN , 0), PCE_MC_M3(0x88A8 , 0xFFFF , 7 , OUT_2VTAG0 , 2 , INSTR , FLAG_2VLAN , 0), PCE_MC_M3(0x0000 , 0x0000 , 15 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x8100 , 0xFFFF , 10 , OUT_3VTAG0 , 2 , INSTR , FLAG_3VLAN , 0), PCE_MC_M3(0x88A8 , 0xFFFF , 10 , OUT_3VTAG0 , 2 , INSTR , FLAG_3VLAN , 0), PCE_MC_M3(0x0000 , 0x0000 , 15 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x8100 , 0xFFFF , 13 , OUT_4VTAG0 , 2 , INSTR , FLAG_4VLAN , 0), PCE_MC_M3(0x88A8 , 0xFFFF , 13 , OUT_4VTAG0 , 2 , INSTR , FLAG_4VLAN , 0), PCE_MC_M3(0x0000 , 0x0000 , 15 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x8100 , 0xFFFF , 13 , OUT_NONE , 2 , INSTR , FLAG_ROUTEXP , 0), PCE_MC_M3(0x88A8 , 0xFFFF , 13 , OUT_NONE , 2 , INSTR , FLAG_ROUTEXP , 0), PCE_MC_M3(0x0000 , 0xF800 , 17 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 23 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0600 , 0x0600 , 23 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 19 , OUT_ETYPE , 1 , INSTR , FLAG_LEN , 0), PCE_MC_M3(0xAAAA , 0xFFFF , 21 , OUT_APP0 , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 174 , OUT_APP0 , 2 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0300 , 0xFF00 , 23 , OUT_APP1 , 2 , INSTR , FLAG_SNAP , 0), PCE_MC_M3(0x0000 , 0x0000 , 174 , OUT_APP1 , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x8864 , 0xFFFF , 28 , OUT_ETYPE , 4 , INSTR , FLAG_PPPOES , 0), PCE_MC_M3(0x0800 , 0xFFFF , 31 , OUT_ETYPE , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x86DD , 0xFFFF , 48 , OUT_ETYPE , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x888E , 0xFFFF , 173 , OUT_ETYPE , 1 , INSTR , FLAG_EAPOL , 0), PCE_MC_M3(0x0000 , 0x0000 , 173 , OUT_ETYPE , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0021 , 0xFFFF , 31 , OUT_PPP , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0057 , 0xFFFF , 48 , OUT_PPP , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 173 , OUT_PPP , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x4000 , 0xF000 , 33 , OUT_NONE , 0 , INSTR , FLAG_1IPV4 , 1), PCE_MC_M3(0x0000 , 0x0000 , 173 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0500 , 0x0F00 , 36 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 35 , OUT_NONE , 0 , INSTR , FLAG_IPV4OPT , 0), PCE_MC_M3(0x0000 , 0x0000 , 36 , OUT_NONE , 0 , INSTR , FLAG_LROEXP , 0), PCE_MC_M3(0x0003 , 0x0003 , 38 , OUT_1IP0 , 3 , INSTR , FLAG_LROEXP , 0), PCE_MC_M3(0x0000 , 0x0000 , 38 , OUT_1IP0 , 3 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x3FFF , 40 , OUT_1IP3 , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 40 , OUT_1IP3 , 1 , INSTR , FLAG_IPFRAG , 0), PCE_MC_M3(0x0000 , 0xFE00 , 41 , OUT_NONE , 0 , INSTR , FLAG_ROUTEXP , 0), PCE_MC_M3(0x0011 , 0x00FF , 111 , OUT_1IP4 , 6 , LENACCU , FLAG_NO , 0), PCE_MC_M3(0x0006 , 0x00FF , 99 , OUT_1IP4 , 6 , LENACCU , FLAG_NO , 0), PCE_MC_M3(0x0002 , 0x00FF , 116 , OUT_1IP4 , 6 , LENACCU , FLAG_NO , 0), PCE_MC_M3(0x0029 , 0x00FF , 83 , OUT_1IP4 , 6 , LENACCU , FLAG_NO , 0), PCE_MC_M3(0x0004 , 0x00FF , 73 , OUT_1IP4 , 6 , LENACCU , FLAG_NO , 0), PCE_MC_M3(0x002F , 0x00FF , 133 , OUT_1IP4 , 6 , LENACCU , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 173 , OUT_1IP4 , 6 , LENACCU , FLAG_NO , 0), PCE_MC_M3(0x6000 , 0xF000 , 50 , OUT_NONE , 0 , INSTR , FLAG_1IPV6 , 0), PCE_MC_M3(0x0000 , 0x0000 , 173 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0030 , 0x0030 , 52 , OUT_1IP0 , 3 , INSTR , FLAG_LROEXP , 0), PCE_MC_M3(0x0000 , 0x0000 , 52 , OUT_1IP0 , 3 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x00FE , 53 , OUT_NONE , 0 , INSTR , FLAG_ROUTEXP , 0), PCE_MC_M3(0x1100 , 0xFF00 , 111 , OUT_1IP3 , 17 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0600 , 0xFF00 , 99 , OUT_1IP3 , 17 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 56 , OUT_NONE , 0 , INSTR , FLAG_LROEXP , 0), PCE_MC_M3(0x0400 , 0xFF00 , 73 , OUT_1IP3 , 17 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x2900 , 0xFF00 , 83 , OUT_1IP3 , 17 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x2F00 , 0xFF00 , 133 , OUT_1IP3 , 17 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0xFF00 , 63 , OUT_1IP3 , 17 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x2B00 , 0xFF00 , 63 , OUT_1IP3 , 17 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x3C00 , 0xFF00 , 63 , OUT_1IP3 , 17 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 173 , OUT_1IP3 , 17 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x00F8 , 65 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 173 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0xFF00 , 63 , OUT_1LNH , 1 , IPV6 , FLAG_1IPV6EXT , 0), PCE_MC_M3(0x2B00 , 0xFF00 , 63 , OUT_1LNH , 1 , IPV6 , FLAG_1IPV6EXT , 0), PCE_MC_M3(0x3C00 , 0xFF00 , 63 , OUT_1LNH , 1 , IPV6 , FLAG_1IPV6EXT , 0), PCE_MC_M3(0x1100 , 0xFF00 , 111 , OUT_1LNH , 1 , IPV6 , FLAG_1IPV6EXT , 0), PCE_MC_M3(0x0600 , 0xFF00 , 99 , OUT_1LNH , 1 , IPV6 , FLAG_1IPV6EXT , 0), PCE_MC_M3(0x0400 , 0xFF00 , 73 , OUT_1LNH , 1 , IPV6 , FLAG_1IPV6EXT , 0), PCE_MC_M3(0x2900 , 0xFF00 , 83 , OUT_1LNH , 1 , IPV6 , FLAG_1IPV6EXT , 0), PCE_MC_M3(0x0000 , 0x0000 , 173 , OUT_1LNH , 1 , IPV6 , FLAG_1IPV6EXT , 0), PCE_MC_M3(0x0000 , 0x0000 , 74 , OUT_NONE , 0 , INSTR , FLAG_2IPV4 , 1), PCE_MC_M3(0x0500 , 0x0F00 , 76 , OUT_2IP0 , 3 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 77 , OUT_2IP0 , 3 , INSTR , FLAG_IPV4OPT , 0), PCE_MC_M3(0x0000 , 0x3FFF , 78 , OUT_2IP3 , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 78 , OUT_2IP3 , 1 , INSTR , FLAG_IPFRAG , 0), PCE_MC_M3(0x0000 , 0xFE00 , 79 , OUT_NONE , 0 , INSTR , FLAG_ROUTEXP , 0), PCE_MC_M3(0x0011 , 0x00FF , 115 , OUT_2IP4 , 6 , LENACCU , FLAG_NO , 0), PCE_MC_M3(0x0006 , 0x00FF , 99 , OUT_2IP4 , 6 , LENACCU , FLAG_NO , 0), PCE_MC_M3(0x0002 , 0x00FF , 116 , OUT_2IP4 , 6 , LENACCU , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 173 , OUT_2IP4 , 6 , LENACCU , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 84 , OUT_2IP0 , 3 , INSTR , FLAG_2IPV6 , 0), PCE_MC_M3(0x0000 , 0x00FE , 85 , OUT_NONE , 0 , INSTR , FLAG_ROUTEXP , 0), PCE_MC_M3(0x1100 , 0xFF00 , 115 , OUT_2IP3 , 17 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0600 , 0xFF00 , 99 , OUT_2IP3 , 17 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0xFF00 , 91 , OUT_2IP3 , 17 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x2B00 , 0xFF00 , 91 , OUT_2IP3 , 17 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x3C00 , 0xFF00 , 91 , OUT_2IP3 , 17 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 173 , OUT_2IP3 , 17 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x00F8 , 93 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 173 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0xFF00 , 91 , OUT_2LNH , 1 , IPV6 , FLAG_2IPV6EXT , 0), PCE_MC_M3(0x2B00 , 0xFF00 , 91 , OUT_2LNH , 1 , IPV6 , FLAG_2IPV6EXT , 0), PCE_MC_M3(0x3C00 , 0xFF00 , 91 , OUT_2LNH , 1 , IPV6 , FLAG_2IPV6EXT , 0), PCE_MC_M3(0x1100 , 0xFF00 , 115 , OUT_2LNH , 1 , IPV6 , FLAG_2IPV6EXT , 0), PCE_MC_M3(0x0600 , 0xFF00 , 99 , OUT_2LNH , 1 , IPV6 , FLAG_2IPV6EXT , 0), PCE_MC_M3(0x0000 , 0x0000 , 173 , OUT_2LNH , 1 , IPV6 , FLAG_2IPV6EXT , 0), PCE_MC_M3(0x0000 , 0x0000 , 100 , OUT_APP0 , 6 , INSTR , FLAG_TCP , 0), PCE_MC_M3(0x0040 , 0x0040 , 101 , OUT_NONE , 0 , INSTR , FLAG_LROEXP , 0), PCE_MC_M3(0x0080 , 0x0080 , 102 , OUT_NONE , 0 , INSTR , FLAG_LROEXP , 0), PCE_MC_M3(0x0020 , 0x0020 , 103 , OUT_NONE , 0 , INSTR , FLAG_LROEXP , 0), PCE_MC_M3(0x0008 , 0x0008 , 104 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0001 , 0x0001 , 105 , OUT_NONE , 0 , INSTR , FLAG_ROUTEXP , 0), PCE_MC_M3(0x0001 , 0x0001 , 106 , OUT_NONE , 0 , INSTR , FLAG_LROEXP , 0), PCE_MC_M3(0x0004 , 0x0004 , 107 , OUT_NONE , 0 , INSTR , FLAG_ROUTEXP , 0), PCE_MC_M3(0x0004 , 0x0004 , 108 , OUT_NONE , 0 , INSTR , FLAG_LROEXP , 0), PCE_MC_M3(0x0002 , 0x0002 , 109 , OUT_NONE , 0 , INSTR , FLAG_LROEXP , 0), PCE_MC_M3(0x0010 , 0x0010 , 176 , OUT_APP6 , 4 , INSTR , FLAG_TCPACK , 0), PCE_MC_M3(0x0000 , 0x0010 , 176 , OUT_APP6 , 4 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 112 , OUT_APP0 , 1 , INSTR , FLAG_1UDP , 0), PCE_MC_M3(0x06A5 , 0xFFFF , 117 , OUT_APP1 , 3 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x147F , 0xFFFF , 129 , OUT_APP1 , 3 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 174 , OUT_APP1 , 3 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 174 , OUT_APP0 , 4 , INSTR , FLAG_2UDP , 0), PCE_MC_M3(0x0000 , 0x0000 , 174 , OUT_APP0 , 4 , INSTR , FLAG_IGMP , 0), PCE_MC_M3(0x0000 , 0xCA00 , 124 , OUT_NONE , 3 , INSTR , FLAG_L2TP , 0), PCE_MC_M3(0x4000 , 0xCA00 , 124 , OUT_NONE , 4 , INSTR , FLAG_L2TP , 0), PCE_MC_M3(0x0200 , 0xCA00 , 122 , OUT_NONE , 3 , INSTR , FLAG_L2TP , 0), PCE_MC_M3(0x4200 , 0xCA00 , 122 , OUT_NONE , 4 , INSTR , FLAG_L2TP , 0), PCE_MC_M3(0x0000 , 0x0000 , 174 , OUT_NONE , 0 , INSTR , FLAG_L2TP , 0), PCE_MC_M3(0x0000 , 0xFFFF , 124 , OUT_NONE , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 174 , OUT_NONE , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0xFF03 , 0xFFFF , 126 , OUT_NONE , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 174 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0021 , 0xFFFF , 73 , OUT_NONE , 1 , INSTR , FLAG_L2TPNEXP , 0), PCE_MC_M3(0x0057 , 0xFFFF , 83 , OUT_NONE , 1 , INSTR , FLAG_L2TPNEXP , 0), PCE_MC_M3(0x0000 , 0x0000 , 174 , OUT_NONE , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0010 , 0x00F8 , 131 , OUT_NONE , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 174 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x01F8 , 174 , OUT_NONE , 0 , INSTR , FLAG_CAPWAP , 0), PCE_MC_M3(0x0000 , 0x0000 , 174 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x2000 , 0xFFFF , 136 , OUT_NONE , 1 , INSTR , FLAG_GREK , 0), PCE_MC_M3(0x0000 , 0xFFFF , 154 , OUT_NONE , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 173 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x6558 , 0xFFFF , 140 , OUT_NONE , 1 , INSTR , FLAG_GRE , 0), PCE_MC_M3(0x0800 , 0xFFFF , 152 , OUT_NONE , 1 , INSTR , FLAG_GRE , 0), PCE_MC_M3(0x86DD , 0xFFFF , 153 , OUT_NONE , 1 , INSTR , FLAG_GRE , 0), PCE_MC_M3(0x0000 , 0x0000 , 173 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 141 , OUT_1PL , 2 , INSTR , FLAG_L2TPNEXP , 0), PCE_MC_M3(0x0000 , 0x0000 , 142 , OUT_NONE , 6 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x8100 , 0xFFFF , 144 , OUT_NONE , 2 , INSTR , FLAG_GRE_VLAN1 , 0), PCE_MC_M3(0x0000 , 0x0000 , 145 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x8100 , 0xFFFF , 145 , OUT_NONE , 2 , INSTR , FLAG_GRE_VLAN2 , 0), PCE_MC_M3(0x8864 , 0xFFFF , 149 , OUT_NONE , 4 , INSTR , FLAG_GRE_PPPOE , 0), PCE_MC_M3(0x0800 , 0xFFFF , 158 , OUT_NONE , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x86DD , 0xFFFF , 167 , OUT_NONE , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0021 , 0xFFFF , 158 , OUT_NONE , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0057 , 0xFFFF , 167 , OUT_NONE , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 158 , OUT_1PL , 2 , INSTR , FLAG_L2TPNEXP , 0), PCE_MC_M3(0x0000 , 0x0000 , 167 , OUT_1PL , 2 , INSTR , FLAG_L2TPNEXP , 0), PCE_MC_M3(0x6558 , 0xFFFF , 141 , OUT_NONE , 1 , INSTR , FLAG_GRE , 0), PCE_MC_M3(0x0800 , 0xFFFF , 158 , OUT_NONE , 1 , INSTR , FLAG_GRE , 0), PCE_MC_M3(0x86DD , 0xFFFF , 167 , OUT_NONE , 1 , INSTR , FLAG_GRE , 0), PCE_MC_M3(0x0000 , 0x0000 , 173 , OUT_NONE , 0 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 159 , OUT_NONE , 0 , INSTR , FLAG_2IPV4 , 1), PCE_MC_M3(0x0500 , 0x0F00 , 161 , OUT_2IP0 , 3 , INSTR , FLAG_L2TPNEXP , 0), PCE_MC_M3(0x0000 , 0x0000 , 162 , OUT_2IP0 , 3 , INSTR , FLAG_IPV4OPT , 0), PCE_MC_M3(0x0000 , 0x3FFF , 163 , OUT_2IP3 , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 163 , OUT_2IP3 , 1 , INSTR , FLAG_IPFRAG , 0), PCE_MC_M3(0x0000 , 0xFE00 , 164 , OUT_NONE , 0 , INSTR , FLAG_ROUTEXP , 0), PCE_MC_M3(0x0011 , 0x00FF , 172 , OUT_2IP4 , 6 , LENACCU , FLAG_NO , 0), PCE_MC_M3(0x0006 , 0x00FF , 99 , OUT_2IP4 , 6 , LENACCU , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_2IP4 , 6 , LENACCU , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 168 , OUT_2IP0 , 3 , INSTR , FLAG_2IPV6 , 0), PCE_MC_M3(0x0000 , 0x00FE , 169 , OUT_NONE , 0 , INSTR , FLAG_ROUTEXP , 0), PCE_MC_M3(0x1100 , 0xFF00 , 172 , OUT_2IP3 , 17 , INSTR , FLAG_L2TPNEXP , 0), PCE_MC_M3(0x0600 , 0xFF00 , 99 , OUT_2IP3 , 17 , INSTR , FLAG_L2TPNEXP , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_2IP3 , 17 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_APP0 , 4 , INSTR , FLAG_2UDP , 0), PCE_MC_M3(0x0000 , 0x0000 , 174 , OUT_APP0 , 2 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 175 , OUT_1PL , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_2PL , 1 , INSTR , FLAG_NO , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), PCE_MC_M3(0x0000 , 0x0000 , 176 , OUT_NONE , 0 , INSTR , FLAG_END , 0), }; #define PCE_MC_M(val, msk, ns, out, len, type, flags, ipv4_len) \ { val, msk, (ns<<10 | out<<4 | len>>1),\ (len&1)<<15 | type<<13 | flags<<9 | ipv4_len<<8 } const PCE_MICROCODE pce_mc_max_ifx_tag_m = { /*-----------------------------------------------------------------*/ /** value mask ns out_fields L type flags ipv4_len **/ /*-----------------------------------------------------------------*/ PCE_MC_M(0x88c3, 0xFFFF, 1, GOUT_ITAG0, 4, INSTR, GFLAG_ITAG, 0), PCE_MC_M(0x8100, 0xFFFF, 2, GOUT_VTAG0, 2, INSTR, GFLAG_VLAN, 0), PCE_MC_M(0x88A8, 0xFFFF, 1, GOUT_VTAG0, 2, INSTR, GFLAG_VLAN, 0), PCE_MC_M(0x8100, 0xFFFF, 1, GOUT_VTAG0, 2, INSTR, GFLAG_VLAN, 0), PCE_MC_M(0x8864, 0xFFFF, 17, GOUT_ETHTYP, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0800, 0xFFFF, 21, GOUT_ETHTYP, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x86DD, 0xFFFF, 22, GOUT_ETHTYP, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x8863, 0xFFFF, 16, GOUT_ETHTYP, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0xF800, 10, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 40, GOUT_ETHTYP, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0600, 0x0600, 40, GOUT_ETHTYP, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 12, GOUT_NONE, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0xAAAA, 0xFFFF, 14, GOUT_NONE, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0300, 0xFF00, 41, GOUT_NONE, 0, INSTR, GFLAG_SNAP, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_DIP7, 3, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 18, GOUT_DIP7, 3, INSTR, GFLAG_PPPOE, 0), PCE_MC_M(0x0021, 0xFFFF, 21, GOUT_NONE, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0057, 0xFFFF, 22, GOUT_NONE, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 40, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x4000, 0xF000, 24, GOUT_IP0, 4, INSTR, GFLAG_IPV4, 1), PCE_MC_M(0x6000, 0xF000, 27, GOUT_IP0, 3, INSTR, GFLAG_IPV6, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 25, GOUT_IP3, 2, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 26, GOUT_SIP0, 4, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 40, GOUT_NONE, 0, LENACCU, GFLAG_NO, 0), PCE_MC_M(0x1100, 0xFF00, 39, GOUT_PROT, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0600, 0xFF00, 39, GOUT_PROT, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0xFF00, 33, GOUT_IP3, 17, INSTR, GFLAG_HOP, 0), PCE_MC_M(0x2B00, 0xFF00, 33, GOUT_IP3, 17, INSTR, GFLAG_NN1, 0), PCE_MC_M(0x3C00, 0xFF00, 33, GOUT_IP3, 17, INSTR, GFLAG_NN2, 0), PCE_MC_M(0x0000, 0x0000, 39, GOUT_PROT, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x00E0, 35, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 40, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0xFF00, 33, GOUT_NONE, 0, IPV6, GFLAG_HOP, 0), PCE_MC_M(0x2B00, 0xFF00, 33, GOUT_NONE, 0, IPV6, GFLAG_NN1, 0), PCE_MC_M(0x3C00, 0xFF00, 33, GOUT_NONE, 0, IPV6, GFLAG_NN2, 0), PCE_MC_M(0x0000, 0x0000, 40, GOUT_PROT, 1, IPV6, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 40, GOUT_SIP0, 16, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_APP0, 4, INSTR, GFLAG_IGMP, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 41, GOUT_NONE, 0, INSTR, GFLAG_END, 0), }; /* Static Function Declaration */ static int tbl_write(void *tstart, u16 *rcnt, void *parm, u32 tsize, u32 tnum) { int i; /* search if the entry is already available and can be re-used */ for (i = 0; i < tnum; i++) { if (rcnt[i] > 0) { /* entry is used, check if the entry content fits */ if (memcmp(((char *)tstart) + i * tsize, parm, (u8)tsize) == 0) { rcnt[i]++; return i; } } } /* find an empty entry and add information */ for (i = 0; i < tnum; i++) { if (rcnt[i] == 0) { memcpy(((char *)tstart) + i * tsize, parm, (u8)tsize); rcnt[i]++; return i; } } /* table is full, return an error */ pr_err("ERROR:\n\tFile %s\n\tLine %d\n", __FILE__, __LINE__); return -1; } static int tbl_idx_delete(u16 *rcnt, u32 index, u32 tsize) { PCE_ASSERT(index >= tsize); if (rcnt[index] > 0) rcnt[index]--; return 0; } int gsw_pce_table_write(void *cdev, pctbl_prog_t *ptdata) { u32 value; u16 udata; do { gsw_r32(cdev, PCE_TBL_CTRL_BAS_OFFSET, PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, &value); } while (value); value = ptdata->pcindex; gsw_w32(cdev, PCE_TBL_ADDR_ADDR_OFFSET, PCE_TBL_ADDR_ADDR_SHIFT, PCE_TBL_ADDR_ADDR_SIZE, value); udata = ptdata->table; gsw_w32(cdev, PCE_TBL_CTRL_ADDR_OFFSET, PCE_TBL_CTRL_ADDR_SHIFT, PCE_TBL_CTRL_ADDR_SIZE, udata); value = PCE_OP_MODE_ADWR; gsw_w32(cdev, PCE_TBL_CTRL_OPMOD_OFFSET, PCE_TBL_CTRL_OPMOD_SHIFT, PCE_TBL_CTRL_OPMOD_SIZE, value); gsw_w32(cdev, PCE_TBL_KEY_15_KEY15_OFFSET, PCE_TBL_KEY_15_KEY15_SHIFT, PCE_TBL_KEY_15_KEY15_SIZE, ptdata->key[15]); gsw_w32(cdev, PCE_TBL_KEY_14_KEY14_OFFSET, PCE_TBL_KEY_14_KEY14_SHIFT, PCE_TBL_KEY_14_KEY14_SIZE, ptdata->key[14]); gsw_w32(cdev, PCE_TBL_KEY_13_KEY13_OFFSET, PCE_TBL_KEY_13_KEY13_SHIFT, PCE_TBL_KEY_13_KEY13_SIZE, ptdata->key[13]); gsw_w32(cdev, PCE_TBL_KEY_12_KEY12_OFFSET, PCE_TBL_KEY_12_KEY12_SHIFT, PCE_TBL_KEY_12_KEY12_SIZE, ptdata->key[12]); gsw_w32(cdev, PCE_TBL_KEY_11_KEY11_OFFSET, PCE_TBL_KEY_11_KEY11_SHIFT, PCE_TBL_KEY_11_KEY11_SIZE, ptdata->key[11]); gsw_w32(cdev, PCE_TBL_KEY_10_KEY10_OFFSET, PCE_TBL_KEY_10_KEY10_SHIFT, PCE_TBL_KEY_10_KEY10_SIZE, ptdata->key[10]); gsw_w32(cdev, PCE_TBL_KEY_9_KEY9_OFFSET, PCE_TBL_KEY_9_KEY9_SHIFT, PCE_TBL_KEY_9_KEY9_SIZE, ptdata->key[9]); gsw_w32(cdev, PCE_TBL_KEY_8_KEY8_OFFSET, PCE_TBL_KEY_8_KEY8_SHIFT, PCE_TBL_KEY_8_KEY8_SIZE, ptdata->key[8]); gsw_w32(cdev, PCE_TBL_KEY_7_KEY7_OFFSET, PCE_TBL_KEY_7_KEY7_SHIFT, PCE_TBL_KEY_7_KEY7_SIZE, ptdata->key[7]); gsw_w32(cdev, PCE_TBL_KEY_6_KEY6_OFFSET, PCE_TBL_KEY_6_KEY6_SHIFT, PCE_TBL_KEY_6_KEY6_SIZE, ptdata->key[6]); gsw_w32(cdev, PCE_TBL_KEY_5_KEY5_OFFSET, PCE_TBL_KEY_5_KEY5_SHIFT, PCE_TBL_KEY_5_KEY5_SIZE, ptdata->key[5]); gsw_w32(cdev, PCE_TBL_KEY_4_KEY4_OFFSET, PCE_TBL_KEY_4_KEY4_SHIFT, PCE_TBL_KEY_4_KEY4_SIZE, ptdata->key[4]); gsw_w32(cdev, PCE_TBL_KEY_3_KEY3_OFFSET, PCE_TBL_KEY_3_KEY3_SHIFT, PCE_TBL_KEY_3_KEY3_SIZE, ptdata->key[3]); gsw_w32(cdev, PCE_TBL_KEY_2_KEY2_OFFSET, PCE_TBL_KEY_2_KEY2_SHIFT, PCE_TBL_KEY_2_KEY2_SIZE, ptdata->key[2]); gsw_w32(cdev, PCE_TBL_KEY_1_KEY1_OFFSET, PCE_TBL_KEY_1_KEY1_SHIFT, PCE_TBL_KEY_1_KEY1_SIZE, ptdata->key[1]); gsw_w32(cdev, PCE_TBL_KEY_0_KEY0_OFFSET, PCE_TBL_KEY_0_KEY0_SHIFT, PCE_TBL_KEY_0_KEY0_SIZE, ptdata->key[0]); gsw_w32(cdev, PCE_TBL_MASK_0_MASK0_OFFSET, PCE_TBL_MASK_0_MASK0_SHIFT, PCE_TBL_MASK_0_MASK0_SIZE, ptdata->mask[0]); gsw_w32(cdev, PCE_TBL_MASK_1_MASK1_OFFSET, PCE_TBL_MASK_1_MASK1_SHIFT, PCE_TBL_MASK_1_MASK1_SIZE, ptdata->mask[1]); gsw_w32(cdev, PCE_TBL_MASK_2_MASK2_OFFSET, PCE_TBL_MASK_2_MASK2_SHIFT, PCE_TBL_MASK_2_MASK2_SIZE, ptdata->mask[2]); gsw_w32(cdev, PCE_TBL_MASK_3_MASK3_OFFSET, PCE_TBL_MASK_3_MASK3_SHIFT, PCE_TBL_MASK_3_MASK3_SIZE, ptdata->mask[3]); gsw_w32(cdev, PCE_TBL_VAL_15_VAL15_OFFSET, PCE_TBL_VAL_15_VAL15_SHIFT, PCE_TBL_VAL_15_VAL15_SIZE, ptdata->val[15]); gsw_w32(cdev, PCE_TBL_VAL_14_VAL14_OFFSET, PCE_TBL_VAL_14_VAL14_SHIFT, PCE_TBL_VAL_14_VAL14_SIZE, ptdata->val[14]); gsw_w32(cdev, PCE_TBL_VAL_13_VAL13_OFFSET, PCE_TBL_VAL_13_VAL13_SHIFT, PCE_TBL_VAL_13_VAL13_SIZE, ptdata->val[13]); gsw_w32(cdev, PCE_TBL_VAL_12_VAL12_OFFSET, PCE_TBL_VAL_12_VAL12_SHIFT, PCE_TBL_VAL_12_VAL12_SIZE, ptdata->val[12]); gsw_w32(cdev, PCE_TBL_VAL_11_VAL11_OFFSET, PCE_TBL_VAL_11_VAL11_SHIFT, PCE_TBL_VAL_11_VAL11_SIZE, ptdata->val[11]); gsw_w32(cdev, PCE_TBL_VAL_10_VAL10_OFFSET, PCE_TBL_VAL_10_VAL10_SHIFT, PCE_TBL_VAL_10_VAL10_SIZE, ptdata->val[10]); gsw_w32(cdev, PCE_TBL_VAL_9_VAL9_OFFSET, PCE_TBL_VAL_9_VAL9_SHIFT, PCE_TBL_VAL_9_VAL9_SIZE, ptdata->val[9]); gsw_w32(cdev, PCE_TBL_VAL_8_VAL8_OFFSET, PCE_TBL_VAL_8_VAL8_SHIFT, PCE_TBL_VAL_8_VAL8_SIZE, ptdata->val[8]); gsw_w32(cdev, PCE_TBL_VAL_7_VAL7_OFFSET, PCE_TBL_VAL_7_VAL7_SHIFT, PCE_TBL_VAL_7_VAL7_SIZE, ptdata->val[7]); gsw_w32(cdev, PCE_TBL_VAL_6_VAL6_OFFSET, PCE_TBL_VAL_6_VAL6_SHIFT, PCE_TBL_VAL_6_VAL6_SIZE, ptdata->val[6]); gsw_w32(cdev, PCE_TBL_VAL_5_VAL5_OFFSET, PCE_TBL_VAL_5_VAL5_SHIFT, PCE_TBL_VAL_5_VAL5_SIZE, ptdata->val[5]); gsw_w32(cdev, PCE_TBL_VAL_4_VAL4_OFFSET, PCE_TBL_VAL_4_VAL4_SHIFT, PCE_TBL_VAL_4_VAL4_SIZE, ptdata->val[4]); gsw_w32(cdev, PCE_TBL_VAL_3_VAL3_OFFSET, PCE_TBL_VAL_3_VAL3_SHIFT, PCE_TBL_VAL_3_VAL3_SIZE, ptdata->val[3]); gsw_w32(cdev, PCE_TBL_VAL_2_VAL2_OFFSET, PCE_TBL_VAL_2_VAL2_SHIFT, PCE_TBL_VAL_2_VAL2_SIZE, ptdata->val[2]); gsw_w32(cdev, PCE_TBL_VAL_1_VAL1_OFFSET, PCE_TBL_VAL_1_VAL1_SHIFT, PCE_TBL_VAL_1_VAL1_SIZE, ptdata->val[1]); gsw_w32(cdev, PCE_TBL_VAL_0_VAL0_OFFSET, PCE_TBL_VAL_0_VAL0_SHIFT, PCE_TBL_VAL_0_VAL0_SIZE, ptdata->val[0]); value = ptdata->kformat; gsw_w32(cdev, PCE_TBL_CTRL_KEYFORM_OFFSET, PCE_TBL_CTRL_KEYFORM_SHIFT, PCE_TBL_CTRL_KEYFORM_SIZE, value); value = ptdata->type; gsw_w32(cdev, PCE_TBL_CTRL_TYPE_OFFSET, PCE_TBL_CTRL_TYPE_SHIFT, PCE_TBL_CTRL_TYPE_SIZE, value); value = ptdata->valid; gsw_w32(cdev, PCE_TBL_CTRL_VLD_OFFSET, PCE_TBL_CTRL_VLD_SHIFT, PCE_TBL_CTRL_VLD_SIZE, value); value = ptdata->group; gsw_w32(cdev, PCE_TBL_CTRL_GMAP_OFFSET, PCE_TBL_CTRL_GMAP_SHIFT, PCE_TBL_CTRL_GMAP_SIZE, value); gsw_w32(cdev, PCE_TBL_CTRL_BAS_OFFSET, PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, 1); do { gsw_r32(cdev, PCE_TBL_CTRL_BAS_OFFSET, PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, &value); } while (value != 0); gsw_w32(cdev, PCE_TBL_CTRL_ADDR_OFFSET, 0, 16, 0); /* gsw_r32(cdev, PCE_TBL_CTRL_BAS_OFFSET, 0, 15, &value); */ return 0; } int gsw_pce_table_read(void *cdev, pctbl_prog_t *ptdata) { u32 value; do { gsw_r32(cdev, PCE_TBL_CTRL_BAS_OFFSET, PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, &value); } while (value != 0); gsw_w32(cdev, PCE_TBL_ADDR_ADDR_OFFSET, PCE_TBL_ADDR_ADDR_SHIFT, PCE_TBL_ADDR_ADDR_SIZE, ptdata->pcindex); gsw_w32(cdev, PCE_TBL_CTRL_ADDR_OFFSET, PCE_TBL_CTRL_ADDR_SHIFT, PCE_TBL_CTRL_ADDR_SIZE, ptdata->table); gsw_w32(cdev, PCE_TBL_CTRL_OPMOD_OFFSET, PCE_TBL_CTRL_OPMOD_SHIFT, PCE_TBL_CTRL_OPMOD_SIZE, PCE_OP_MODE_ADRD); gsw_w32(cdev, PCE_TBL_CTRL_BAS_OFFSET, PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, 1); do { gsw_r32(cdev, PCE_TBL_CTRL_BAS_OFFSET, PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, &value); } while (value != 0); gsw_r32(cdev, PCE_TBL_KEY_15_KEY15_OFFSET, PCE_TBL_KEY_15_KEY15_SHIFT, PCE_TBL_KEY_15_KEY15_SIZE, &value); ptdata->key[15] = value; gsw_r32(cdev, PCE_TBL_KEY_14_KEY14_OFFSET, PCE_TBL_KEY_14_KEY14_SHIFT, PCE_TBL_KEY_14_KEY14_SIZE, &value); ptdata->key[14] = value; gsw_r32(cdev, PCE_TBL_KEY_13_KEY13_OFFSET, PCE_TBL_KEY_13_KEY13_SHIFT, PCE_TBL_KEY_13_KEY13_SIZE, &value); ptdata->key[13] = value; gsw_r32(cdev, PCE_TBL_KEY_12_KEY12_OFFSET, PCE_TBL_KEY_12_KEY12_SHIFT, PCE_TBL_KEY_12_KEY12_SIZE, &value); ptdata->key[12] = value; gsw_r32(cdev, PCE_TBL_KEY_11_KEY11_OFFSET, PCE_TBL_KEY_11_KEY11_SHIFT, PCE_TBL_KEY_11_KEY11_SIZE, &value); ptdata->key[11] = value; gsw_r32(cdev, PCE_TBL_KEY_10_KEY10_OFFSET, PCE_TBL_KEY_10_KEY10_SHIFT, PCE_TBL_KEY_10_KEY10_SIZE, &value); ptdata->key[10] = value; gsw_r32(cdev, PCE_TBL_KEY_9_KEY9_OFFSET, PCE_TBL_KEY_9_KEY9_SHIFT, PCE_TBL_KEY_9_KEY9_SIZE, &value); ptdata->key[9] = value; gsw_r32(cdev, PCE_TBL_KEY_8_KEY8_OFFSET, PCE_TBL_KEY_8_KEY8_SHIFT, PCE_TBL_KEY_8_KEY8_SIZE, &value); ptdata->key[8] = value; gsw_r32(cdev, PCE_TBL_KEY_7_KEY7_OFFSET, PCE_TBL_KEY_7_KEY7_SHIFT, PCE_TBL_KEY_7_KEY7_SIZE, &value); ptdata->key[7] = value; gsw_r32(cdev, PCE_TBL_KEY_6_KEY6_OFFSET, PCE_TBL_KEY_6_KEY6_SHIFT, PCE_TBL_KEY_6_KEY6_SIZE, &value); ptdata->key[6] = value; gsw_r32(cdev, PCE_TBL_KEY_5_KEY5_OFFSET, PCE_TBL_KEY_5_KEY5_SHIFT, PCE_TBL_KEY_5_KEY5_SIZE, &value); ptdata->key[5] = value; gsw_r32(cdev, PCE_TBL_KEY_4_KEY4_OFFSET, PCE_TBL_KEY_4_KEY4_SHIFT, PCE_TBL_KEY_4_KEY4_SIZE, &value); ptdata->key[4] = value; gsw_r32(cdev, PCE_TBL_KEY_3_KEY3_OFFSET, PCE_TBL_KEY_3_KEY3_SHIFT, PCE_TBL_KEY_3_KEY3_SIZE, &value); ptdata->key[3] = value; gsw_r32(cdev, PCE_TBL_KEY_2_KEY2_OFFSET, PCE_TBL_KEY_2_KEY2_SHIFT, PCE_TBL_KEY_2_KEY2_SIZE, &value); ptdata->key[2] = value; gsw_r32(cdev, PCE_TBL_KEY_1_KEY1_OFFSET, PCE_TBL_KEY_1_KEY1_SHIFT, PCE_TBL_KEY_1_KEY1_SIZE, &value); ptdata->key[1] = value; gsw_r32(cdev, PCE_TBL_KEY_0_KEY0_OFFSET, PCE_TBL_KEY_0_KEY0_SHIFT, PCE_TBL_KEY_0_KEY0_SIZE, &value); ptdata->key[0] = value; gsw_r32(cdev, PCE_TBL_VAL_15_VAL15_OFFSET, PCE_TBL_VAL_15_VAL15_SHIFT, PCE_TBL_VAL_15_VAL15_SIZE, &value); ptdata->val[15] = value; gsw_r32(cdev, PCE_TBL_VAL_14_VAL14_OFFSET, PCE_TBL_VAL_14_VAL14_SHIFT, PCE_TBL_VAL_14_VAL14_SIZE, &value); ptdata->val[14] = value; gsw_r32(cdev, PCE_TBL_VAL_13_VAL13_OFFSET, PCE_TBL_VAL_13_VAL13_SHIFT, PCE_TBL_VAL_13_VAL13_SIZE, &value); ptdata->val[13] = value; gsw_r32(cdev, PCE_TBL_VAL_12_VAL12_OFFSET, PCE_TBL_VAL_12_VAL12_SHIFT, PCE_TBL_VAL_12_VAL12_SIZE, &value); ptdata->val[12] = value; gsw_r32(cdev, PCE_TBL_VAL_11_VAL11_OFFSET, PCE_TBL_VAL_11_VAL11_SHIFT, PCE_TBL_VAL_11_VAL11_SIZE, &value); ptdata->val[11] = value; gsw_r32(cdev, PCE_TBL_VAL_10_VAL10_OFFSET, PCE_TBL_VAL_10_VAL10_SHIFT, PCE_TBL_VAL_10_VAL10_SIZE, &value); ptdata->val[10] = value; gsw_r32(cdev, PCE_TBL_VAL_9_VAL9_OFFSET, PCE_TBL_VAL_9_VAL9_SHIFT, PCE_TBL_VAL_9_VAL9_SIZE, &value); ptdata->val[9] = value; gsw_r32(cdev, PCE_TBL_VAL_8_VAL8_OFFSET, PCE_TBL_VAL_8_VAL8_SHIFT, PCE_TBL_VAL_8_VAL8_SIZE, &value); ptdata->val[8] = value; gsw_r32(cdev, PCE_TBL_VAL_7_VAL7_OFFSET, PCE_TBL_VAL_7_VAL7_SHIFT, PCE_TBL_VAL_7_VAL7_SIZE, &value); ptdata->val[7] = value; gsw_r32(cdev, PCE_TBL_VAL_6_VAL6_OFFSET, PCE_TBL_VAL_6_VAL6_SHIFT, PCE_TBL_VAL_6_VAL6_SIZE, &value); ptdata->val[6] = value; gsw_r32(cdev, PCE_TBL_VAL_5_VAL5_OFFSET, PCE_TBL_VAL_5_VAL5_SHIFT, PCE_TBL_VAL_5_VAL5_SIZE, &value); ptdata->val[5] = value; gsw_r32(cdev, PCE_TBL_VAL_4_VAL4_OFFSET, PCE_TBL_VAL_4_VAL4_SHIFT, PCE_TBL_VAL_4_VAL4_SIZE, &value); ptdata->val[4] = value; gsw_r32(cdev, PCE_TBL_VAL_3_VAL3_OFFSET, PCE_TBL_VAL_3_VAL3_SHIFT, PCE_TBL_VAL_3_VAL3_SIZE, &value); ptdata->val[3] = value; gsw_r32(cdev, PCE_TBL_VAL_2_VAL2_OFFSET, PCE_TBL_VAL_2_VAL2_SHIFT, PCE_TBL_VAL_2_VAL2_SIZE, &value); ptdata->val[2] = value; gsw_r32(cdev, PCE_TBL_VAL_1_VAL1_OFFSET, PCE_TBL_VAL_1_VAL1_SHIFT, PCE_TBL_VAL_1_VAL1_SIZE, &value); ptdata->val[1] = value; gsw_r32(cdev, PCE_TBL_VAL_0_VAL0_OFFSET, PCE_TBL_VAL_0_VAL0_SHIFT, PCE_TBL_VAL_0_VAL0_SIZE, &value); ptdata->val[0] = value; gsw_r32(cdev, PCE_TBL_MASK_0_MASK0_OFFSET, PCE_TBL_MASK_0_MASK0_SHIFT, PCE_TBL_MASK_0_MASK0_SIZE, &value); ptdata->mask[0] = value; gsw_r32(cdev, PCE_TBL_MASK_1_MASK1_OFFSET, PCE_TBL_MASK_1_MASK1_SHIFT, PCE_TBL_MASK_1_MASK1_SIZE, &value); ptdata->mask[1] = value; gsw_r32(cdev, PCE_TBL_MASK_2_MASK2_OFFSET, PCE_TBL_MASK_2_MASK2_SHIFT, PCE_TBL_MASK_2_MASK2_SIZE, &value); ptdata->mask[2] = value; gsw_r32(cdev, PCE_TBL_MASK_3_MASK3_OFFSET, PCE_TBL_MASK_3_MASK3_SHIFT, PCE_TBL_MASK_3_MASK3_SIZE, &value); ptdata->mask[3] = value; gsw_r32(cdev, PCE_TBL_CTRL_TYPE_OFFSET, PCE_TBL_CTRL_TYPE_SHIFT, PCE_TBL_CTRL_TYPE_SIZE, &value); ptdata->type = value; gsw_r32(cdev, PCE_TBL_CTRL_VLD_OFFSET, PCE_TBL_CTRL_VLD_SHIFT, PCE_TBL_CTRL_VLD_SIZE, &value); ptdata->valid = value; gsw_r32(cdev, PCE_TBL_CTRL_GMAP_OFFSET, PCE_TBL_CTRL_GMAP_SHIFT, PCE_TBL_CTRL_GMAP_SIZE, &value); ptdata->group = value; gsw_w32(cdev, PCE_TBL_CTRL_ADDR_OFFSET, 0, 16, 0); return 0; } int gsw_pce_table_key_read(void *cdev, pctbl_prog_t *ptdata) { u32 value; do { gsw_r32(cdev, PCE_TBL_CTRL_BAS_OFFSET, PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, &value); } while (value != 0); value = ptdata->table; gsw_w32(cdev, PCE_TBL_CTRL_ADDR_OFFSET, PCE_TBL_CTRL_ADDR_SHIFT, PCE_TBL_CTRL_ADDR_SIZE, value); value = ptdata->key[15]; gsw_w32(cdev, PCE_TBL_KEY_15_KEY15_OFFSET, PCE_TBL_KEY_15_KEY15_SHIFT, PCE_TBL_KEY_15_KEY15_SIZE, value); value = ptdata->key[14]; gsw_w32(cdev, PCE_TBL_KEY_14_KEY14_OFFSET, PCE_TBL_KEY_14_KEY14_SHIFT, PCE_TBL_KEY_14_KEY14_SIZE, value); value = ptdata->key[13]; gsw_w32(cdev, PCE_TBL_KEY_13_KEY13_OFFSET, PCE_TBL_KEY_13_KEY13_SHIFT, PCE_TBL_KEY_13_KEY13_SIZE, value); value = ptdata->key[12]; gsw_w32(cdev, PCE_TBL_KEY_12_KEY12_OFFSET, PCE_TBL_KEY_12_KEY12_SHIFT, PCE_TBL_KEY_12_KEY12_SIZE, value); value = ptdata->key[11]; gsw_w32(cdev, PCE_TBL_KEY_11_KEY11_OFFSET, PCE_TBL_KEY_11_KEY11_SHIFT, PCE_TBL_KEY_11_KEY11_SIZE, value); value = ptdata->key[10]; gsw_w32(cdev, PCE_TBL_KEY_10_KEY10_OFFSET, PCE_TBL_KEY_10_KEY10_SHIFT, PCE_TBL_KEY_10_KEY10_SIZE, value); value = ptdata->key[9]; gsw_w32(cdev, PCE_TBL_KEY_9_KEY9_OFFSET, PCE_TBL_KEY_9_KEY9_SHIFT, PCE_TBL_KEY_9_KEY9_SIZE, value); value = ptdata->key[8]; gsw_w32(cdev, PCE_TBL_KEY_8_KEY8_OFFSET, PCE_TBL_KEY_8_KEY8_SHIFT, PCE_TBL_KEY_8_KEY8_SIZE, value); value = ptdata->key[7]; gsw_w32(cdev, PCE_TBL_KEY_7_KEY7_OFFSET, PCE_TBL_KEY_7_KEY7_SHIFT, PCE_TBL_KEY_7_KEY7_SIZE, value); value = ptdata->key[6]; gsw_w32(cdev, PCE_TBL_KEY_6_KEY6_OFFSET, PCE_TBL_KEY_6_KEY6_SHIFT, PCE_TBL_KEY_6_KEY6_SIZE, value); value = ptdata->key[5]; gsw_w32(cdev, PCE_TBL_KEY_5_KEY5_OFFSET, PCE_TBL_KEY_5_KEY5_SHIFT, PCE_TBL_KEY_5_KEY5_SIZE, value); value = ptdata->key[4]; gsw_w32(cdev, PCE_TBL_KEY_4_KEY4_OFFSET, PCE_TBL_KEY_4_KEY4_SHIFT, PCE_TBL_KEY_4_KEY4_SIZE, value); value = ptdata->key[3]; gsw_w32(cdev, PCE_TBL_KEY_3_KEY3_OFFSET, PCE_TBL_KEY_3_KEY3_SHIFT, PCE_TBL_KEY_3_KEY3_SIZE, value); value = ptdata->key[2]; gsw_w32(cdev, PCE_TBL_KEY_2_KEY2_OFFSET, PCE_TBL_KEY_2_KEY2_SHIFT, PCE_TBL_KEY_2_KEY2_SIZE, value); value = ptdata->key[1]; gsw_w32(cdev, PCE_TBL_KEY_1_KEY1_OFFSET, PCE_TBL_KEY_1_KEY1_SHIFT, PCE_TBL_KEY_1_KEY1_SIZE, value); value = ptdata->key[0]; gsw_w32(cdev, PCE_TBL_KEY_0_KEY0_OFFSET, PCE_TBL_KEY_0_KEY0_SHIFT, PCE_TBL_KEY_0_KEY0_SIZE, value); gsw_w32(cdev, PCE_TBL_CTRL_OPMOD_OFFSET, PCE_TBL_CTRL_OPMOD_SHIFT, PCE_TBL_CTRL_OPMOD_SIZE, PCE_OP_MODE_KSRD); gsw_w32(cdev, PCE_TBL_CTRL_BAS_OFFSET, PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, 1); do { gsw_r32(cdev, PCE_TBL_CTRL_BAS_OFFSET, PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, &value); } while (value != 0); gsw_r32(cdev, PCE_TBL_VAL_15_VAL15_OFFSET, PCE_TBL_VAL_15_VAL15_SHIFT, PCE_TBL_VAL_15_VAL15_SIZE, &value); ptdata->val[15] = value; gsw_r32(cdev, PCE_TBL_VAL_14_VAL14_OFFSET, PCE_TBL_VAL_14_VAL14_SHIFT, PCE_TBL_VAL_14_VAL14_SIZE, &value); ptdata->val[14] = value; gsw_r32(cdev, PCE_TBL_VAL_13_VAL13_OFFSET, PCE_TBL_VAL_13_VAL13_SHIFT, PCE_TBL_VAL_13_VAL13_SIZE, &value); ptdata->val[13] = value; gsw_r32(cdev, PCE_TBL_VAL_12_VAL12_OFFSET, PCE_TBL_VAL_12_VAL12_SHIFT, PCE_TBL_VAL_12_VAL12_SIZE, &value); ptdata->val[12] = value; gsw_r32(cdev, PCE_TBL_VAL_11_VAL11_OFFSET, PCE_TBL_VAL_11_VAL11_SHIFT, PCE_TBL_VAL_11_VAL11_SIZE, &value); ptdata->val[11] = value; gsw_r32(cdev, PCE_TBL_VAL_10_VAL10_OFFSET, PCE_TBL_VAL_10_VAL10_SHIFT, PCE_TBL_VAL_10_VAL10_SIZE, &value); ptdata->val[10] = value; gsw_r32(cdev, PCE_TBL_VAL_9_VAL9_OFFSET, PCE_TBL_VAL_9_VAL9_SHIFT, PCE_TBL_VAL_9_VAL9_SIZE, &value); ptdata->val[9] = value; gsw_r32(cdev, PCE_TBL_VAL_8_VAL8_OFFSET, PCE_TBL_VAL_8_VAL8_SHIFT, PCE_TBL_VAL_8_VAL8_SIZE, &value); ptdata->val[8] = value; gsw_r32(cdev, PCE_TBL_VAL_7_VAL7_OFFSET, PCE_TBL_VAL_7_VAL7_SHIFT, PCE_TBL_VAL_7_VAL7_SIZE, &value); ptdata->val[7] = value; gsw_r32(cdev, PCE_TBL_VAL_6_VAL6_OFFSET, PCE_TBL_VAL_6_VAL6_SHIFT, PCE_TBL_VAL_6_VAL6_SIZE, &value); ptdata->val[6] = value; gsw_r32(cdev, PCE_TBL_VAL_5_VAL5_OFFSET, PCE_TBL_VAL_5_VAL5_SHIFT, PCE_TBL_VAL_5_VAL5_SIZE, &value); ptdata->val[5] = value; gsw_r32(cdev, PCE_TBL_VAL_4_VAL4_OFFSET, PCE_TBL_VAL_4_VAL4_SHIFT, PCE_TBL_VAL_4_VAL4_SIZE, &value); ptdata->val[4] = value; gsw_r32(cdev, PCE_TBL_VAL_3_VAL3_OFFSET, PCE_TBL_VAL_3_VAL3_SHIFT, PCE_TBL_VAL_3_VAL3_SIZE, &value); ptdata->val[3] = value; gsw_r32(cdev, PCE_TBL_VAL_2_VAL2_OFFSET, PCE_TBL_VAL_2_VAL2_SHIFT, PCE_TBL_VAL_2_VAL2_SIZE, &value); ptdata->val[2] = value; gsw_r32(cdev, PCE_TBL_VAL_1_VAL1_OFFSET, PCE_TBL_VAL_1_VAL1_SHIFT, PCE_TBL_VAL_1_VAL1_SIZE, &value); ptdata->val[1] = value; gsw_r32(cdev, PCE_TBL_VAL_0_VAL0_OFFSET, PCE_TBL_VAL_0_VAL0_SHIFT, PCE_TBL_VAL_0_VAL0_SIZE, &value); ptdata->val[0] = value; gsw_r32(cdev, PCE_TBL_MASK_0_MASK0_OFFSET, PCE_TBL_MASK_0_MASK0_SHIFT, PCE_TBL_MASK_0_MASK0_SIZE, &value); ptdata->mask[0] = value; gsw_r32(cdev, PCE_TBL_MASK_1_MASK1_OFFSET, PCE_TBL_MASK_1_MASK1_SHIFT, PCE_TBL_MASK_1_MASK1_SIZE, &value); ptdata->mask[1] = value; gsw_r32(cdev, PCE_TBL_MASK_2_MASK2_OFFSET, PCE_TBL_MASK_2_MASK2_SHIFT, PCE_TBL_MASK_2_MASK2_SIZE, &value); ptdata->mask[2] = value; gsw_r32(cdev, PCE_TBL_MASK_3_MASK3_OFFSET, PCE_TBL_MASK_3_MASK3_SHIFT, PCE_TBL_MASK_3_MASK3_SIZE, &value); ptdata->mask[3] = value; gsw_r32(cdev, PCE_TBL_CTRL_TYPE_OFFSET, PCE_TBL_CTRL_TYPE_SHIFT, PCE_TBL_CTRL_TYPE_SIZE, &value); ptdata->type = value; gsw_r32(cdev, PCE_TBL_CTRL_VLD_OFFSET, PCE_TBL_CTRL_VLD_SHIFT, PCE_TBL_CTRL_VLD_SIZE, &value); ptdata->valid = value; gsw_r32(cdev, PCE_TBL_CTRL_GMAP_OFFSET, PCE_TBL_CTRL_GMAP_SHIFT, PCE_TBL_CTRL_GMAP_SIZE, &value); ptdata->group = value; gsw_r32(cdev, PCE_TBL_ADDR_ADDR_OFFSET, PCE_TBL_ADDR_ADDR_SHIFT, PCE_TBL_ADDR_ADDR_SIZE, &value); ptdata->pcindex = value; gsw_w32(cdev, PCE_TBL_CTRL_ADDR_OFFSET, 0, 16, 0); return 0; } int gsw_pce_table_key_write(void *cdev, pctbl_prog_t *ptdata) { u32 value; do { gsw_r32(cdev, PCE_TBL_CTRL_BAS_OFFSET, PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, &value); } while (value != 0); gsw_w32(cdev, PCE_TBL_CTRL_ADDR_OFFSET, PCE_TBL_CTRL_ADDR_SHIFT, PCE_TBL_CTRL_ADDR_SIZE, ptdata->table); gsw_w32(cdev, PCE_TBL_CTRL_OPMOD_OFFSET, PCE_TBL_CTRL_OPMOD_SHIFT, PCE_TBL_CTRL_OPMOD_SIZE, PCE_OP_MODE_KSWR); value = ptdata->key[15]; gsw_w32(cdev, PCE_TBL_KEY_15_KEY15_OFFSET, PCE_TBL_KEY_15_KEY15_SHIFT, PCE_TBL_KEY_15_KEY15_SIZE, value); value = ptdata->key[14]; gsw_w32(cdev, PCE_TBL_KEY_14_KEY14_OFFSET, PCE_TBL_KEY_14_KEY14_SHIFT, PCE_TBL_KEY_14_KEY14_SIZE, value); value = ptdata->key[13]; gsw_w32(cdev, PCE_TBL_KEY_13_KEY13_OFFSET, PCE_TBL_KEY_13_KEY13_SHIFT, PCE_TBL_KEY_13_KEY13_SIZE, value); value = ptdata->key[12]; gsw_w32(cdev, PCE_TBL_KEY_12_KEY12_OFFSET, PCE_TBL_KEY_12_KEY12_SHIFT, PCE_TBL_KEY_12_KEY12_SIZE, value); value = ptdata->key[11]; gsw_w32(cdev, PCE_TBL_KEY_11_KEY11_OFFSET, PCE_TBL_KEY_11_KEY11_SHIFT, PCE_TBL_KEY_11_KEY11_SIZE, value); value = ptdata->key[10]; gsw_w32(cdev, PCE_TBL_KEY_10_KEY10_OFFSET, PCE_TBL_KEY_10_KEY10_SHIFT, PCE_TBL_KEY_10_KEY10_SIZE, value); value = ptdata->key[9]; gsw_w32(cdev, PCE_TBL_KEY_9_KEY9_OFFSET, PCE_TBL_KEY_9_KEY9_SHIFT, PCE_TBL_KEY_9_KEY9_SIZE, value); value = ptdata->key[8]; gsw_w32(cdev, PCE_TBL_KEY_8_KEY8_OFFSET, PCE_TBL_KEY_8_KEY8_SHIFT, PCE_TBL_KEY_8_KEY8_SIZE, value); value = ptdata->key[7]; gsw_w32(cdev, PCE_TBL_KEY_7_KEY7_OFFSET, PCE_TBL_KEY_7_KEY7_SHIFT, PCE_TBL_KEY_7_KEY7_SIZE, value); value = ptdata->key[6]; gsw_w32(cdev, PCE_TBL_KEY_6_KEY6_OFFSET, PCE_TBL_KEY_6_KEY6_SHIFT, PCE_TBL_KEY_6_KEY6_SIZE, value); value = ptdata->key[5]; gsw_w32(cdev, PCE_TBL_KEY_5_KEY5_OFFSET, PCE_TBL_KEY_5_KEY5_SHIFT, PCE_TBL_KEY_5_KEY5_SIZE, value); value = ptdata->key[4]; gsw_w32(cdev, PCE_TBL_KEY_4_KEY4_OFFSET, PCE_TBL_KEY_4_KEY4_SHIFT, PCE_TBL_KEY_4_KEY4_SIZE, value); value = ptdata->key[3]; gsw_w32(cdev, PCE_TBL_KEY_3_KEY3_OFFSET, PCE_TBL_KEY_3_KEY3_SHIFT, PCE_TBL_KEY_3_KEY3_SIZE, value); value = ptdata->key[2]; gsw_w32(cdev, PCE_TBL_KEY_2_KEY2_OFFSET, PCE_TBL_KEY_2_KEY2_SHIFT, PCE_TBL_KEY_2_KEY2_SIZE, value); value = ptdata->key[1]; gsw_w32(cdev, PCE_TBL_KEY_1_KEY1_OFFSET, PCE_TBL_KEY_1_KEY1_SHIFT, PCE_TBL_KEY_1_KEY1_SIZE, value); value = ptdata->key[0]; gsw_w32(cdev, PCE_TBL_KEY_0_KEY0_OFFSET, PCE_TBL_KEY_0_KEY0_SHIFT, PCE_TBL_KEY_0_KEY0_SIZE, value); value = ptdata->mask[0]; gsw_w32(cdev, PCE_TBL_MASK_0_MASK0_OFFSET, PCE_TBL_MASK_0_MASK0_SHIFT, PCE_TBL_MASK_0_MASK0_SIZE, value); value = ptdata->mask[1]; gsw_w32(cdev, PCE_TBL_MASK_1_MASK1_OFFSET, PCE_TBL_MASK_1_MASK1_SHIFT, PCE_TBL_MASK_1_MASK1_SIZE, value); value = ptdata->mask[2]; gsw_w32(cdev, PCE_TBL_MASK_2_MASK2_OFFSET, PCE_TBL_MASK_2_MASK2_SHIFT, PCE_TBL_MASK_2_MASK2_SIZE, value); value = ptdata->mask[3]; gsw_w32(cdev, PCE_TBL_MASK_3_MASK3_OFFSET, PCE_TBL_MASK_3_MASK3_SHIFT, PCE_TBL_MASK_3_MASK3_SIZE, value); value = ptdata->val[15]; gsw_w32(cdev, PCE_TBL_VAL_15_VAL15_OFFSET, PCE_TBL_VAL_15_VAL15_SHIFT, PCE_TBL_VAL_15_VAL15_SIZE, value); value = ptdata->val[14]; gsw_w32(cdev, PCE_TBL_VAL_14_VAL14_OFFSET, PCE_TBL_VAL_14_VAL14_SHIFT, PCE_TBL_VAL_14_VAL14_SIZE, value); value = ptdata->val[13]; gsw_w32(cdev, PCE_TBL_VAL_13_VAL13_OFFSET, PCE_TBL_VAL_13_VAL13_SHIFT, PCE_TBL_VAL_13_VAL13_SIZE, value); value = ptdata->val[12]; gsw_w32(cdev, PCE_TBL_VAL_12_VAL12_OFFSET, PCE_TBL_VAL_12_VAL12_SHIFT, PCE_TBL_VAL_12_VAL12_SIZE, value); value = ptdata->val[11]; gsw_w32(cdev, PCE_TBL_VAL_11_VAL11_OFFSET, PCE_TBL_VAL_11_VAL11_SHIFT, PCE_TBL_VAL_11_VAL11_SIZE, value); value = ptdata->val[10]; gsw_w32(cdev, PCE_TBL_VAL_10_VAL10_OFFSET, PCE_TBL_VAL_10_VAL10_SHIFT, PCE_TBL_VAL_10_VAL10_SIZE, value); value = ptdata->val[9]; gsw_w32(cdev, PCE_TBL_VAL_9_VAL9_OFFSET, PCE_TBL_VAL_9_VAL9_SHIFT, PCE_TBL_VAL_9_VAL9_SIZE, value); value = ptdata->val[8]; gsw_w32(cdev, PCE_TBL_VAL_8_VAL8_OFFSET, PCE_TBL_VAL_8_VAL8_SHIFT, PCE_TBL_VAL_8_VAL8_SIZE, value); value = ptdata->val[7]; gsw_w32(cdev, PCE_TBL_VAL_7_VAL7_OFFSET, PCE_TBL_VAL_7_VAL7_SHIFT, PCE_TBL_VAL_7_VAL7_SIZE, value); value = ptdata->val[6]; gsw_w32(cdev, PCE_TBL_VAL_6_VAL6_OFFSET, PCE_TBL_VAL_6_VAL6_SHIFT, PCE_TBL_VAL_6_VAL6_SIZE, value); value = ptdata->val[5]; gsw_w32(cdev, PCE_TBL_VAL_5_VAL5_OFFSET, PCE_TBL_VAL_5_VAL5_SHIFT, PCE_TBL_VAL_5_VAL5_SIZE, value); value = ptdata->val[4]; gsw_w32(cdev, PCE_TBL_VAL_4_VAL4_OFFSET, PCE_TBL_VAL_4_VAL4_SHIFT, PCE_TBL_VAL_4_VAL4_SIZE, value); value = ptdata->val[3]; gsw_w32(cdev, PCE_TBL_VAL_3_VAL3_OFFSET, PCE_TBL_VAL_3_VAL3_SHIFT, PCE_TBL_VAL_3_VAL3_SIZE, value); value = ptdata->val[2]; gsw_w32(cdev, PCE_TBL_VAL_2_VAL2_OFFSET, PCE_TBL_VAL_2_VAL2_SHIFT, PCE_TBL_VAL_2_VAL2_SIZE, value); value = ptdata->val[1]; gsw_w32(cdev, PCE_TBL_VAL_1_VAL1_OFFSET, PCE_TBL_VAL_1_VAL1_SHIFT, PCE_TBL_VAL_1_VAL1_SIZE, value); value = ptdata->val[0]; gsw_w32(cdev, PCE_TBL_VAL_0_VAL0_OFFSET, PCE_TBL_VAL_0_VAL0_SHIFT, PCE_TBL_VAL_0_VAL0_SIZE, value); value = ptdata->type; gsw_w32(cdev, PCE_TBL_CTRL_TYPE_OFFSET, PCE_TBL_CTRL_TYPE_SHIFT, PCE_TBL_CTRL_TYPE_SIZE, value); value = ptdata->valid; gsw_w32(cdev, PCE_TBL_CTRL_VLD_OFFSET, PCE_TBL_CTRL_VLD_SHIFT, PCE_TBL_CTRL_VLD_SIZE, value); value = ptdata->group; gsw_w32(cdev, PCE_TBL_CTRL_GMAP_OFFSET, PCE_TBL_CTRL_GMAP_SHIFT, PCE_TBL_CTRL_GMAP_SIZE, ptdata->group); gsw_w32(cdev, PCE_TBL_CTRL_BAS_OFFSET, PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, 1); do { gsw_r32(cdev, PCE_TBL_CTRL_BAS_OFFSET, PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, &value); } while (value != 0); gsw_w32(cdev, PCE_TBL_CTRL_ADDR_OFFSET, 0, 16, 0); return 0; } /* Packet Length Table write */ static int pce_tm_pkg_lng_tbl_write(void *cdev, pcetbl_prog_t *pthandle, pce_pkt_length_t *parm) { pctbl_prog_t ptbl; int pcindex; pcindex = tbl_write(pthandle->pkg_lng_tbl, pthandle->pkg_lng_tbl_cnt, parm, sizeof(pce_pkt_length_t), PCE_PKG_LNG_TBL_SIZE); PCE_ASSERT(pcindex < 0); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PACKET_INDEX; ptbl.pcindex = pcindex; ptbl.key[0] = parm->pkg_lng; ptbl.mask[0] = parm->pkg_lng_rng; ptbl.valid = 1; gsw_pce_table_write(cdev, &ptbl); return pcindex; } /* Packet Length Table delete */ static int pce_tm_pkg_lng_tbl_delete(void *cdev, pcetbl_prog_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= PCE_PKG_LNG_TBL_SIZE); if (pthandle->pkg_lng_tbl_cnt[index] > 0) pthandle->pkg_lng_tbl_cnt[index]--; if (pthandle->pkg_lng_tbl_cnt[index] == 0) { memset((((char *)pthandle->pkg_lng_tbl) + (index * sizeof(pce_pkt_length_t))), 0, sizeof(pce_pkt_length_t)); /* initialize the data structure before using it */ memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PACKET_INDEX; ptbl.pcindex = index; gsw_pce_table_write(cdev, &ptbl); } return 0; } /* Packet Length Table read */ static int pce_tm_pkg_lng_tbl_read(pcetbl_prog_t *pthandle, int index, pce_pkt_length_t *parm) { PCE_ASSERT(index >= PCE_PKG_LNG_TBL_SIZE); memcpy(parm, &pthandle->pkg_lng_tbl[index], sizeof(pce_pkt_length_t)); return 0; } /* MAC DA Table index write */ static int pce_da_mac_tbl_write(void *cdev, pcetbl_prog_t *pthandle, pce_da_prog_t *parm) { pctbl_prog_t ptbl; int pcindex; pcindex = tbl_write(pthandle->da_mac_tbl, pthandle->da_mac_tbl_cnt, parm, sizeof(pce_da_prog_t), PCE_DASA_MAC_TBL_SIZE); PCE_ASSERT(pcindex < 0); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_MACDA_INDEX; ptbl.pcindex = pcindex; ptbl.key[0] = (parm->mac[4] << 8 | parm->mac[5]); ptbl.key[1] = (parm->mac[2] << 8 | parm->mac[3]); ptbl.key[2] = (parm->mac[0] << 8 | parm->mac[1]); ptbl.mask[0] = parm->mac_mask; ptbl.valid = 1; gsw_pce_table_write(cdev, &ptbl); return pcindex; } /* MAC SA Table index write */ static int pce_sa_mac_tbl_write(void *cdev, pcetbl_prog_t *pthandle, pce_sa_prog_t *parm) { pctbl_prog_t ptbl; int pcindex; pcindex = tbl_write(pthandle->sa_mac_tbl, pthandle->sa_mac_tbl_cnt, parm, sizeof(pce_sa_prog_t), PCE_DASA_MAC_TBL_SIZE); PCE_ASSERT(pcindex < 0); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_MACSA_INDEX; ptbl.pcindex = pcindex; ptbl.key[0] = (parm->mac[4] << 8 | parm->mac[5]); ptbl.key[1] = (parm->mac[2] << 8 | parm->mac[3]); ptbl.key[2] = (parm->mac[0] << 8 | parm->mac[1]); ptbl.mask[0]= parm->mac_mask; ptbl.valid = 1; gsw_pce_table_write(cdev, &ptbl); return pcindex; } /* MAC SA Table delete */ static int pce_tm_sa_mac_tbl_delete(void *cdev, pcetbl_prog_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= PCE_DASA_MAC_TBL_SIZE); if (pthandle->sa_mac_tbl_cnt[index] > 0) pthandle->sa_mac_tbl_cnt[index]--; if (pthandle->sa_mac_tbl_cnt[index] == 0) { memset((((char *)pthandle->sa_mac_tbl) + (index * sizeof(pce_sa_prog_t))), 0, sizeof(pce_sa_prog_t)); /* initialize the data structure before using it */ memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_MACSA_INDEX; ptbl.pcindex = index; gsw_pce_table_write(cdev, &ptbl); } return 0; } /* MAC DA Table delete */ static int pce_tm_da_mac_tbl_delete(void *cdev, pcetbl_prog_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= PCE_DASA_MAC_TBL_SIZE); if (pthandle->da_mac_tbl_cnt[index] > 0) pthandle->da_mac_tbl_cnt[index]--; if (pthandle->da_mac_tbl_cnt[index] == 0) { memset((((char *)pthandle->da_mac_tbl) + (index * sizeof(pce_da_prog_t))), 0, sizeof(pce_sa_prog_t)); /* initialize the data structure before using it */ memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_MACDA_INDEX; ptbl.pcindex = index; gsw_pce_table_write(cdev, &ptbl); } return 0; } /* MAC DA Table Read */ static int pce_tm_da_mac_tbl_read(pcetbl_prog_t *pthandle, int index, pce_da_prog_t *parm) { PCE_ASSERT(index >= PCE_DASA_MAC_TBL_SIZE); memcpy(parm, &pthandle->da_mac_tbl[index], sizeof(pce_da_prog_t)); return 0; } /* MAC SA Table Read */ static int pce_tm_sa_mac_tbl_read(pcetbl_prog_t *pthandle, int index, pce_sa_prog_t *parm) { PCE_ASSERT(index >= PCE_DASA_MAC_TBL_SIZE); memcpy(parm, &pthandle->sa_mac_tbl[index], sizeof(pce_sa_prog_t)); return 0; } /* Application Table write */ static int pce_appl_tbl_write(void *cdev, pcetbl_prog_t *pthandle, app_tbl_t *parm) { pctbl_prog_t ptbl; int pcindex; pcindex = tbl_write(pthandle->appl_tbl, pthandle->appl_tbl_cnt, parm, sizeof(app_tbl_t), PCE_APPL_TBL_SIZE); PCE_ASSERT(pcindex < 0); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_APPLICATION_INDEX; ptbl.pcindex = pcindex; ptbl.key[0] = parm->appl_data; ptbl.mask[0] = parm->mask_range; ptbl.type = parm->mask_range_type; ptbl.valid = 1; gsw_pce_table_write(cdev, &ptbl); return pcindex; } /* Flags Table write */ static int pce_flags_tbl_write(void *cdev, pcetbl_prog_t *pthandle, flag_tbl_t *parm) { pctbl_prog_t ptbl; int pcindex, i; u8 mask_section, key_section, bit_pos; u16 column[4] = {0}; u16 key_val = parm->parser_flag_data; u16 bit_mask = parm->mask_value; pcindex = tbl_write(pthandle->flags_tbl, pthandle->flags_tbl_cnt, parm, sizeof(flag_tbl_t), PCE_FLAGS_TBL_SIZE); PCE_ASSERT(pcindex < 0); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PARSER_FLAGS_INDEX; ptbl.pcindex = pcindex; for (i = 0; i < 4; i++) { mask_section = ((bit_mask >> (i*4)) & 0xF); key_section = ((key_val >> (i*4)) & 0xF); bit_pos = key_section; column[i] = (1 << bit_pos); if ((mask_section & 0x1) == 1) { bit_pos = key_section & 0xe; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0x1); column[i] |= (1 << bit_pos); } if (((mask_section >> 1) & 0x1) == 1) { bit_pos = key_section & 0xd; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0x2); column[i] |= (1 << bit_pos); } if (((mask_section >> 0) & 0x3) == 0x3) { bit_pos = key_section & 0xc; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0x3); column[i] |= (1 << bit_pos); } if (((mask_section >> 2) & 0x1) == 0x1) { bit_pos = key_section & 0xb; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0x4); column[i] |= (1 << bit_pos); } if (((mask_section >> 0) & 0x5) == 0x5) { bit_pos = key_section & 0xa; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0x5); column[i] |= (1 << bit_pos); } if (((mask_section >> 1) & 0x3) == 0x3) { bit_pos = key_section & 0x9; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0x6); column[i] |= (1 << bit_pos); } if (((mask_section >> 0) & 0x7) == 0x7) { bit_pos = key_section & 0x8; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0x7); column[i] |= (1 << bit_pos); } if (((mask_section >> 3) & 0x1) == 0x1) { bit_pos = key_section & 0x7; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0x8); column[i] |= (1 << bit_pos); } if (((mask_section >> 0) & 0x9) == 0x9) { bit_pos = key_section & 0x6; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0x9); column[i] |= (1 << bit_pos); } if (((mask_section >> 0) & 0xa) == 0xa) { bit_pos = key_section & 0x5; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0xa); column[i] |= (1 << bit_pos); } if (((mask_section >> 2) & 0x3) == 0x3) { bit_pos = key_section & 0x3; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0xc); column[i] |= (1 << bit_pos); } if (((mask_section >> 0) & 0xb) == 0xb) { bit_pos = key_section & 0x4; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0xb); column[i] |= (1 << bit_pos); } if (((mask_section >> 0) & 0xd) == 0xd) { bit_pos = key_section & 0x2; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0xd); column[i] |= (1 << bit_pos); } if (((mask_section >> 1) & 0x7) == 0x7) { bit_pos = key_section & 0x1; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0xe); column[i] |= (1 << bit_pos); } if (((mask_section >> 0) & 0xf) == 0xf) { bit_pos = key_section & 0x0; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0xf); column[i] |= (1 << bit_pos); } } for (i = 0; i < 4; i++) ptbl.key[i] = column[i]; ptbl.valid = 1; ptbl.kformat = 1; gsw_pce_table_write(cdev, &ptbl); gsw_w32(cdev, PCE_TBL_CTRL_KEYFORM_OFFSET, PCE_TBL_CTRL_KEYFORM_SHIFT, PCE_TBL_CTRL_KEYFORM_SIZE, 0); return pcindex; } /* Payload Table write */ static int pce_payload_tbl_write(void *cdev, pcetbl_prog_t *pthandle, payload_tbl_t *parm) { pctbl_prog_t ptbl; int pcindex; pcindex = tbl_write(pthandle->payload_tbl, pthandle->payload_tbl_cnt, parm, sizeof(payload_tbl_t), PCE_PAYLOAD_TBL_SIZE); PCE_ASSERT(pcindex < 0); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PAYLOAD_INDEX; ptbl.pcindex = pcindex; ptbl.key[0] = parm->payload_data; ptbl.mask[0] = parm->mask_range; ptbl.type = parm->mask_range_type; ptbl.valid = 1; gsw_pce_table_write(cdev, &ptbl); return pcindex; } /* Application Table Delete */ static int pce_tm_appl_tbl_delete(void *cdev, pcetbl_prog_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= PCE_APPL_TBL_SIZE); if (pthandle->appl_tbl_cnt[index] > 0) pthandle->appl_tbl_cnt[index]--; if (pthandle->appl_tbl_cnt[index] == 0) { memset((((char *)pthandle->appl_tbl) + (index * sizeof(app_tbl_t))), 0, sizeof(app_tbl_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_APPLICATION_INDEX; ptbl.pcindex = index; gsw_pce_table_write(cdev, &ptbl); } return 0; } /* Flags Table Delete */ static int pce_tm_flags_tbl_delete(void *cdev, pcetbl_prog_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= PCE_FLAGS_TBL_SIZE); if (pthandle->flags_tbl_cnt[index] > 0) pthandle->flags_tbl_cnt[index]--; if (pthandle->flags_tbl_cnt[index] == 0) { memset((((char *)pthandle->flags_tbl) + (index * sizeof(flag_tbl_t))), 0, sizeof(flag_tbl_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PARSER_FLAGS_INDEX; ptbl.pcindex = index; gsw_pce_table_write(cdev, &ptbl); } return 0; } /* Payload Table Delete */ static int pce_tm_payload_tbl_delete(void *cdev, pcetbl_prog_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= PCE_PAYLOAD_TBL_SIZE); if (pthandle->payload_tbl_cnt[index] > 0) pthandle->payload_tbl_cnt[index]--; if (pthandle->payload_tbl_cnt[index] == 0) { memset((((char *)pthandle->payload_tbl) + (index * sizeof(payload_tbl_t))), 0, sizeof(payload_tbl_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PAYLOAD_INDEX; ptbl.pcindex = index; gsw_pce_table_write(cdev, &ptbl); } return 0; } /* Application Table Read */ static int pce_tm_appl_tbl_read(pcetbl_prog_t *pthandle, int index, app_tbl_t *parm) { PCE_ASSERT(index >= PCE_APPL_TBL_SIZE); memcpy(parm, &pthandle->appl_tbl[index], sizeof(app_tbl_t)); return 0; } /* Flags Table Read */ static int pce_tm_flags_tbl_read(pcetbl_prog_t *pthandle, int index, flag_tbl_t *parm) { PCE_ASSERT(index >= PCE_FLAGS_TBL_SIZE); memcpy(parm, &pthandle->flags_tbl[index], sizeof(flag_tbl_t)); return 0; } /* Payload Table Read */ static int pce_tm_payload_tbl_read(pcetbl_prog_t *pthandle, int index, payload_tbl_t *parm) { PCE_ASSERT(index >= PCE_PAYLOAD_TBL_SIZE); memcpy(parm, &pthandle->payload_tbl[index], sizeof(payload_tbl_t)); return 0; } /* IP DA/SA msb Table write */ int pce_dasa_msb_tbl_write(void *cdev, pcetbl_prog_t *pthandle, pce_dasa_msb_t *parm) { pctbl_prog_t ptbl; int pcindex, i; pcindex = tbl_write(pthandle->ip_dasa_msb_tbl, pthandle->ipmsbtcnt, parm, sizeof(pce_dasa_msb_t), IP_DASA_PC_MSIZE); if (pcindex < 0) return pcindex; memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_IP_DASA_MSB_INDEX; ptbl.pcindex = pcindex; for (i = 0; i < 4; i++) ptbl.key[i] = ((parm->imsb[((i*2)+1)] << 8) | parm->imsb[(i*2)]); ptbl.mask[0] = parm->mask[0]; ptbl.mask[1] = parm->mask[1]; ptbl.mask[2] = parm->mask[2]; ptbl.mask[3] = parm->mask[3]; ptbl.valid = 1; gsw_pce_table_write(cdev, &ptbl); return pcindex; } /* IP DA/SA msb Table delete */ int ip_dasa_msb_tbl_del(void *cdev, pcetbl_prog_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= IP_DASA_PC_MSIZE); if (pthandle->ipmsbtcnt[index] > 0) pthandle->ipmsbtcnt[index]--; if (pthandle->ipmsbtcnt[index] == 0) { memset((((char *)pthandle->ip_dasa_msb_tbl) + (index * sizeof(pce_dasa_msb_t))), 0, sizeof(pce_dasa_msb_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_IP_DASA_MSB_INDEX; ptbl.pcindex = index; gsw_pce_table_write(cdev, &ptbl); } return 0; } /* IP DA/SA msb Table read */ static int pce_dasa_msb_tbl_read(pcetbl_prog_t *pthandle, int index, pce_dasa_msb_t *parm) { PCE_ASSERT(index >= IP_DASA_PC_MSIZE); memcpy(parm, &pthandle->ip_dasa_msb_tbl[index], sizeof(pce_dasa_msb_t)); return 0; } static int get_tbl_index(void *tstart, void *parm, u32 tsize, u32 tnum) { int i; /* search if the entry is already available and can be re-used */ for (i = 0; i < tnum; i++) { /* entry is used, check if the entry content fits */ if (memcmp(((char *)tstart) + i * tsize, parm, (u8)tsize) == 0) return i; } return 0xFF; } /* Static Function Declaration */ int find_dasa_tbl_entry(pcetbl_prog_t *pthandle, pce_dasa_lsb_t *parm) { return get_tbl_index(pthandle->ip_dasa_lsb_tbl, parm, sizeof(pce_dasa_lsb_t), IP_DASA_PC_LSIZE); } /* Static Function Declaration */ int find_msb_tbl_entry(pcetbl_prog_t *pthandle, pce_dasa_msb_t *parm) { return get_tbl_index(pthandle->ip_dasa_msb_tbl, parm, sizeof(pce_dasa_msb_t), IP_DASA_PC_MSIZE); } /* IP DA/SA lsb Table Write */ int pce_dasa_lsb_tbl_write(void *cdev, pcetbl_prog_t *pthandle, pce_dasa_lsb_t *parm) { pctbl_prog_t ptbl; int pcindex, i; pcindex = tbl_write(pthandle->ip_dasa_lsb_tbl, pthandle->iplsbtcnt, parm, sizeof(pce_dasa_lsb_t), IP_DASA_PC_LSIZE); PCE_ASSERT(pcindex < 0); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_IP_DASA_LSB_INDEX; ptbl.pcindex = pcindex; for (i = 0; i < 4; i++) ptbl.key[i] = ((parm->ilsb[((i*2)+1)] << 8) | parm->ilsb[(i*2)]); ptbl.mask[0] = parm->mask[0]; ptbl.mask[1] = parm->mask[1]; ptbl.mask[2] = parm->mask[2]; ptbl.mask[3] = parm->mask[3]; ptbl.valid = 1; gsw_pce_table_write(cdev, &ptbl); return pcindex; } /* IP DA/SA lsb Table delete */ int ip_dasa_lsb_tbl_del(void *cdev, pcetbl_prog_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= IP_DASA_PC_LSIZE); if (pthandle->iplsbtcnt[index] > 0) pthandle->iplsbtcnt[index]--; if (pthandle->iplsbtcnt[index] == 0) { memset((((char *)pthandle->ip_dasa_lsb_tbl) + (index * sizeof(pce_dasa_lsb_t))), 0, sizeof(pce_dasa_lsb_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_IP_DASA_LSB_INDEX; ptbl.pcindex = index; gsw_pce_table_write(cdev, &ptbl); } return 0; } /* IP DA/SA lsb Table index delete */ int ipdslsb_tblidx_del(pcetbl_prog_t *pthandle, u32 index) { return tbl_idx_delete(pthandle->iplsbtcnt, index, IP_DASA_PC_LSIZE); } /* IP DA/SA msb Table index delete */ int ipdsmsb_tblidx_del(pcetbl_prog_t *pthandle, u32 index) { return tbl_idx_delete(pthandle->ipmsbtcnt, index, IP_DASA_PC_MSIZE); } /* IP DA/SA lsb Table read */ int pce_dasa_lsb_tbl_read(pcetbl_prog_t *pthandle, int index, pce_dasa_lsb_t *parm) { PCE_ASSERT(index >= IP_DASA_PC_LSIZE); memcpy(parm, &pthandle->ip_dasa_lsb_tbl[index], sizeof(pce_dasa_lsb_t)); return 0; } /* Protocal Table write */ static int pce_ptcl_tbl_write(void *cdev, pcetbl_prog_t *pthandle, prtcol_tbl_t *parm) { pctbl_prog_t ptbl; int pcindex; pcindex = tbl_write(pthandle->ptcl_tbl, pthandle->ptcl_tbl_cnt, parm, sizeof(prtcol_tbl_t), PCE_PTCL_TBL_SIZE); PCE_ASSERT(pcindex < 0); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PROTOCOL_INDEX; ptbl.pcindex = pcindex; ptbl.key[0] = parm->ethertype; ptbl.mask[0] = parm->emask; ptbl.valid = 1; gsw_pce_table_write(cdev, &ptbl); return pcindex; } /* Get the vlan flow table index*/ int gavlan_tbl_index(pcetbl_prog_t *pthandle, u8 index) { PCE_ASSERT(index >= PCE_VLAN_ACT_TBL_SIZE); if (pthandle->vlan_act_tbl_cnt[index] == 0) return 0; else return -1; } /* Protocal Table delete */ static int pce_tm_ptcl_tbl_delete(void *cdev, pcetbl_prog_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= PCE_PTCL_TBL_SIZE); if (pthandle->ptcl_tbl_cnt[index] > 0) pthandle->ptcl_tbl_cnt[index]--; if (pthandle->ptcl_tbl_cnt[index] == 0) { memset((((char *)pthandle->ptcl_tbl) + (index * sizeof(prtcol_tbl_t))), 0, sizeof(prtcol_tbl_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PROTOCOL_INDEX; ptbl.pcindex = index; gsw_pce_table_write(cdev, &ptbl); } return 0; } /* Protocal Table Read */ static int pce_tm_ptcl_tbl_read(pcetbl_prog_t *pthandle, int index, prtcol_tbl_t *parm) { PCE_ASSERT(index >= PCE_PTCL_TBL_SIZE); memcpy(parm, &pthandle->ptcl_tbl[index], sizeof(prtcol_tbl_t)); return 0; } /* PPPoE Table Write */ static int pce_tm_pppoe_tbl_write(void *cdev, pcetbl_prog_t *pthandle, pce_ppoe_tbl_t *parm) { pctbl_prog_t ptbl; int pcindex; pcindex = tbl_write(pthandle->pppoe_tbl, pthandle->pppoe_tbl_cnt, parm, sizeof(pce_ppoe_tbl_t), PCE_PPPOE_TBL_SIZE); if (pcindex < 0) return pcindex; /* initialize the data structure before using it */ memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PPPOE_INDEX; ptbl.pcindex = pcindex; ptbl.key[0] = parm->sess_id; ptbl.valid = 1; gsw_pce_table_write(cdev, &ptbl); return pcindex; } /* PPPoE Table Delete */ static int pce_tm_pppoe_tbl_delete(void *cdev, pcetbl_prog_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= PCE_PPPOE_TBL_SIZE); if (pthandle->pppoe_tbl_cnt[index] > 0) pthandle->pppoe_tbl_cnt[index]--; if (pthandle->pppoe_tbl_cnt[index] == 0) { memset((((char *)pthandle->pppoe_tbl) + (index * sizeof(pce_ppoe_tbl_t))), 0, sizeof(pce_ppoe_tbl_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PPPOE_INDEX; ptbl.pcindex = index; gsw_pce_table_write(cdev, &ptbl); } return 0; } /* PPPoE Table Read */ static int pce_tm_pppoe_tbl_read(pcetbl_prog_t *pthandle, int index, pce_ppoe_tbl_t *parm) { PCE_ASSERT(index >= PCE_PPPOE_TBL_SIZE); memcpy(parm, &pthandle->pppoe_tbl[index], sizeof(pce_ppoe_tbl_t)); return 0; } /* VLAN Table Delete */ static int pce_tm_vlan_act_tbl_delete(void *cdev, pcetbl_prog_t *pthandle, u32 index) { PCE_ASSERT(index >= PCE_VLAN_ACT_TBL_SIZE); if (pthandle->vlan_act_tbl_cnt[index] > 0) pthandle->vlan_act_tbl_cnt[index]--; return 0; } static u32 act_vlan_id_create(void *cdev, u16 vid, int range_flag, u16 range_val) { pctbl_prog_t ptbl; u32 index, vid_index = 0x7F; for (index = 0; index < PCE_VLAN_ACT_TBL_SIZE; index++) { memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_ACTVLAN_INDEX; ptbl.pcindex = index; gsw_pce_table_read(cdev, &ptbl); if (ptbl.valid == 0) { ptbl.pcindex = index; vid_index = index; ptbl.table = PCE_ACTVLAN_INDEX; ptbl.key[0] = vid; if (range_flag) ptbl.mask[0] = range_val; else ptbl.mask[0] = 0; ptbl.valid = 1; ptbl.type = range_flag; gsw_pce_table_write(cdev, &ptbl); break; } } return vid_index; } static int pce_vid_index(void *cdev, pcetbl_prog_t *pthandle, u16 vid) { pctbl_prog_t pcetable_vlan; int index, vid_index = 0x7F; for (index = 0; index < PCE_VLAN_ACT_TBL_SIZE; index++) { memset(&pcetable_vlan, 0, sizeof(pctbl_prog_t)); pcetable_vlan.table = PCE_ACTVLAN_INDEX; pcetable_vlan.pcindex = index; gsw_pce_table_read(cdev, &pcetable_vlan); if (pcetable_vlan.valid == 1) { if (pcetable_vlan.key[0] == vid) { vid_index = index; pthandle->vlan_act_tbl_cnt[index]++; break; } } } return vid_index; } static int pce_vlan_id_fid_index(void *cdev, pcetbl_prog_t *pthandle, avlan_tbl_t *vatable) { pctbl_prog_t pcetable_vlan; int index, vid_index = 0x7F; for (index = 0; index < PCE_VLAN_ACT_TBL_SIZE; index++) { memset(&pcetable_vlan, 0, sizeof(pctbl_prog_t)); pcetable_vlan.table = PCE_ACTVLAN_INDEX; pcetable_vlan.pcindex = index; gsw_pce_table_read(cdev, &pcetable_vlan); if (pcetable_vlan.valid == 1) { if (pcetable_vlan.key[0] == vatable->vid) { vid_index = index; vatable->fid = (pcetable_vlan.val[0] & 0xFF); pthandle->vlan_act_tbl_cnt[index]++; break; } } } return vid_index; } /* PCE Table Init routine */ int pce_table_init(ltq_pce_table_t *ptable) { int i; PCE_ASSERT(ptable == NULL); memset(&ptable->pce_sub_tbl, 0, sizeof(pcetbl_prog_t)); memset(&ptable->pce_tbl, 0, sizeof(pce_table_t)); memset(&ptable->pce_act, 0, sizeof(GSW_PCE_action_t)); for (i = 0; i < PCE_TABLE_SIZE; i++) ptable->ptblused[i] = 0; return 0; } /* PCE Table Micro Code Init routine */ int gsw_pmicro_code_init(void *cdev) { ethsw_api_dev_t *gswdev = (ethsw_api_dev_t *)cdev; pctbl_prog_t tbl_entry; u16 i, j; /* Disable all physical port */ for (j = 0; j < gswdev->pnum; j++) { gsw_w32(cdev, (FDMA_PCTRL_EN_OFFSET + (j * 0x6)), FDMA_PCTRL_EN_SHIFT, FDMA_PCTRL_EN_SIZE, 0); gsw_w32(cdev, (SDMA_PCTRL_PEN_OFFSET + (j * 0x6)), SDMA_PCTRL_PEN_SHIFT, SDMA_PCTRL_PEN_SIZE, 0); } if (gswdev->gipver == LTQ_GSWIP_3_0) { gsw_w32(cdev, (GSWT_GCTRL_SE_OFFSET + 0xF00), GSWT_GCTRL_SE_SHIFT, GSWT_GCTRL_SE_SIZE, 1); gsw_w32(cdev, PCE_GCTRL_0_MC_VALID_OFFSET, PCE_GCTRL_0_MC_VALID_SHIFT, PCE_GCTRL_0_MC_VALID_SIZE, 0x0); /* Download the microcode */ for (i = 0; i < 256 /*PCE_MICRO_TABLE_SIZE*/; i++) { memset(&tbl_entry, 0, sizeof(pctbl_prog_t)); tbl_entry.val[3] = pce_mc_max_ifx_tag_m_30[i].val_3; tbl_entry.val[2] = pce_mc_max_ifx_tag_m_30[i].val_2; tbl_entry.val[1] = pce_mc_max_ifx_tag_m_30[i].val_1; tbl_entry.val[0] = pce_mc_max_ifx_tag_m_30[i].val_0; tbl_entry.pcindex = i; tbl_entry.table = PCE_PARS_INDEX; gsw_pce_table_write(gswdev, &tbl_entry); } } else { gsw_w32(cdev, (GLOB_CTRL_SE_OFFSET + 0xC40), GLOB_CTRL_SE_SHIFT, GLOB_CTRL_SE_SIZE, 1); gsw_w32(cdev, PCE_GCTRL_0_MC_VALID_OFFSET, PCE_GCTRL_0_MC_VALID_SHIFT, PCE_GCTRL_0_MC_VALID_SIZE, 0x0); /* Download the microcode */ for (i = 0; i < 64 /* PCE_MICRO_TABLE_SIZE */; i++) { memset(&tbl_entry, 0, sizeof(tbl_entry)); tbl_entry.val[3] = pce_mc_max_ifx_tag_m[i].val_3; tbl_entry.val[2] = pce_mc_max_ifx_tag_m[i].val_2; tbl_entry.val[1] = pce_mc_max_ifx_tag_m[i].val_1; tbl_entry.val[0] = pce_mc_max_ifx_tag_m[i].val_0; tbl_entry.pcindex = i; tbl_entry.table = PCE_PARS_INDEX; gsw_pce_table_write(gswdev, &tbl_entry); } gsw_w32(cdev, PCE_PMAP_2_DMCPMAP_OFFSET, PCE_PMAP_2_DMCPMAP_SHIFT, PCE_PMAP_2_DMCPMAP_SIZE, 0x7F); gsw_w32(cdev, PCE_PMAP_3_UUCMAP_OFFSET, PCE_PMAP_3_UUCMAP_SHIFT, PCE_PMAP_3_UUCMAP_SIZE, 0x7F); } gsw_w32(cdev, PCE_GCTRL_0_MC_VALID_OFFSET, PCE_GCTRL_0_MC_VALID_SHIFT, PCE_GCTRL_0_MC_VALID_SIZE, 0x1); /* Enable RMON Counter for all ports */ for (j = 0; j < gswdev->pnum; j++) { gsw_w32(cdev, (BM_PCFG_CNTEN_OFFSET + (j * 0x2)), BM_PCFG_CNTEN_SHIFT, BM_PCFG_CNTEN_SIZE, 1); } for (j = 0; j < gswdev->pnum; j++) { gsw_w32(cdev, (BM_RMON_CTRL_BCAST_CNT_OFFSET + (j * 0x2)), BM_RMON_CTRL_BCAST_CNT_SHIFT, BM_RMON_CTRL_BCAST_CNT_SIZE, 1); } gsw_w32(cdev, BM_QUEUE_GCTRL_GL_MOD_OFFSET, BM_QUEUE_GCTRL_GL_MOD_SHIFT, BM_QUEUE_GCTRL_GL_MOD_SIZE, 0); return 0; } int pce_action_delete(void *cdev, ltq_pce_table_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= PCE_TABLE_SIZE); memset(&pthandle->pce_act[index], 0, sizeof(GSW_PCE_action_t)); /* REMOVE RULE ACTION FROM HARDWARE DEVICE */ ptbl.pcindex = index; /*index of the Traffic Flow Table index configuration */ ptbl.table = PCE_TFLOW_INDEX; gsw_pce_table_read(cdev, &ptbl); if (ptbl.valid == 1) { if (((ptbl.val[0] >> 1) & 0x1) == 1) { u32 index = (ptbl.val[2] & 0x3F); if (pthandle->pce_sub_tbl.vlan_act_tbl_cnt[index] > 0) pthandle->pce_sub_tbl.vlan_act_tbl_cnt[index]--; } } ptbl.valid = 0; gsw_pce_table_write(cdev, &ptbl); return 0; } int pce_pattern_delete(void *cdev, ltq_pce_table_t *pthandle, u32 index) { pce_table_t *ptable; PCE_ASSERT(index >= PCE_TABLE_SIZE); /* Check if an entry is currently programmed and remove that one. */ if (pthandle->ptblused[index] == 0) return 0; ptable = &(pthandle->pce_tbl[index]); #define IFX_PCE_TM_IDX_DELETE(x, y, z) { if (x != y) \ if (0 != z(cdev, &pthandle->pce_sub_tbl, y)) GSW_RETURN_PCE; } /* Packet length */ IFX_PCE_TM_IDX_DELETE(0x1F, ptable->pkt_lng_idx, pce_tm_pkg_lng_tbl_delete) /* Destination MAC address */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->dst_mac_addr_idx, pce_tm_da_mac_tbl_delete) /* Source MAC address */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->src_mac_addr_idx, pce_tm_sa_mac_tbl_delete) /* Destination Application field */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->dst_appl_fld_idx, pce_tm_appl_tbl_delete) /* Source Application field */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->src_appl_fld_idx, pce_tm_appl_tbl_delete) /* Destination Application field */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->parse_lsb_idx, pce_tm_flags_tbl_delete) /* Destination Application field */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->parse_msb_idx, pce_tm_flags_tbl_delete) /* Payload1 field */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->payload1_idx, pce_tm_payload_tbl_delete) /* payload2 field */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->payload2_idx, pce_tm_payload_tbl_delete) /* DIP MSB */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->dip_msb_idx, ip_dasa_msb_tbl_del) /* Inner DIP MSB */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->inr_dip_msb_idx, ip_dasa_msb_tbl_del) /* DIP LSB */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->dip_lsb_idx, ip_dasa_lsb_tbl_del) /* Inner DIP LSB */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->inr_dip_lsb_idx, ip_dasa_lsb_tbl_del) /* SIP MSB */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->sip_msb_idx, ip_dasa_msb_tbl_del) /* Inner SIP MSB */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->inr_sip_msb_idx, ip_dasa_msb_tbl_del) /* SIP LSB */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->sip_lsb_idx, ip_dasa_lsb_tbl_del) /* Inner SIP LSB */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->inr_sip_lsb_idx, ip_dasa_lsb_tbl_del) /* IP protocol */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->ip_prot_idx, pce_tm_ptcl_tbl_delete) /* Inner IP protocol */ /* IFX_PCE_TM_IDX_DELETE(0xFF, ptable->inr_ip_prot_idx,*/ /*pce_tm_ptcl_tbl_delete) */ /* Ethertype */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->ethertype_idx, pce_tm_ptcl_tbl_delete) /* PPP Protocol */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->ppp_prot_idx, pce_tm_ptcl_tbl_delete) /* PPPoE */ IFX_PCE_TM_IDX_DELETE(0x1F, ptable->pppoe_idx, pce_tm_pppoe_tbl_delete) /* VLAN */ IFX_PCE_TM_IDX_DELETE(0x7F, ptable->vlan_idx, pce_tm_vlan_act_tbl_delete) /* SVLAN */ IFX_PCE_TM_IDX_DELETE(0x7F, ptable->svlan_idx, pce_tm_vlan_act_tbl_delete) /* reset the flag that this rule line is used */ pthandle->ptblused[index] = 0; /* reset the rule line */ memset(ptable, 0xFF, sizeof(pce_table_t)); /* WRITE DOWN THE NEW LINE TO THE HARDWARE */ /* also remove the action for this rule */ return pce_action_delete(cdev, pthandle, index); } int pce_rule_read(void *cdev, ltq_pce_table_t *pthandle, GSW_PCE_rule_t *parm) { ethsw_api_dev_t *gswdev = (ethsw_api_dev_t *)cdev; u32 i, idx = parm->pattern.nIndex; pce_table_t *ptable; pctbl_prog_t ptbl; PCE_ASSERT(idx >= PCE_TABLE_SIZE); /* initialize to zero the structure before writing the parameters */ memset(parm, 0, sizeof(GSW_PCE_rule_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); parm->pattern.nIndex = idx; if (pthandle->ptblused[idx] == 0) return 0; else parm->pattern.bEnable = 1; ptbl.table = PCE_TFLOW_INDEX; ptbl.pcindex = idx; gsw_pce_table_read(cdev, &ptbl); if (gswdev->gipver == LTQ_GSWIP_3_0) { if ((ptbl.key[15] >> 0) & 0x1) parm->pattern.bDstMAC_Exclude = 1; if ((ptbl.key[15] >> 1) & 0x1) parm->pattern.bCTAG_PCP_DEI_Exclude = 1; if ((ptbl.key[15] >> 2) & 0x1) parm->pattern.bSTAG_PCP_DEI_Exclude = 1; if ((ptbl.key[15] >> 3) & 0x1) parm->pattern.bDSCP_Exclude = 1; if ((ptbl.key[15] >> 4) & 0x1) parm->pattern.bPktLng_Exclude = 1; if ((ptbl.key[15] >> 5) & 0x1) parm->pattern.bSessionId_Exclude = 1; if ((ptbl.key[15] >> 6) & 0x1) parm->pattern.bSLANVid_Exclude = 1; if ((ptbl.key[15] >> 7) & 0x1) parm->pattern.bPPP_Protocol_Exclude = 1; if ((ptbl.key[15] >> 8) & 0x1) parm->pattern.bInnerDSCP_Exclude = 1; if ((ptbl.key[15] >> 9) & 0x1) parm->pattern.bInnerSrcIP_Exclude = 1; if ((ptbl.key[15] >> 10) & 0x1) parm->pattern.bInnerDstIP_Exclude = 1; if ((ptbl.key[15] >> 11) & 0x1) parm->pattern.bParserFlagLSB_Exclude = 1; if ((ptbl.key[15] >> 12) & 0x1) parm->pattern.bParserFlagMSB_Exclude = 1; if ((ptbl.key[15] >> 13) & 0x1) parm->pattern.bPayload1_Exclude = 1; if ((ptbl.key[15] >> 14) & 0x1) parm->pattern.bPayload2_Exclude = 1; if ((ptbl.key[15] >> 15) & 0x1) parm->pattern.bSubIfId_Exclude = 1; if ((ptbl.key[14] >> 7) & 0x1) parm->pattern.bPortId_Exclude = 1; if ((ptbl.key[14] >> 8) & 0x1) parm->pattern.bVid_Exclude = 1; if ((ptbl.key[14] >> 9) & 0x1) parm->pattern.bEtherType_Exclude = 1; if ((ptbl.key[14] >> 10) & 0x1) parm->pattern.bProtocol_Exclude = 1; if ((ptbl.key[14] >> 11) & 0x1) parm->pattern.bSrcIP_Exclude = 1; if ((ptbl.key[14] >> 12) & 0x1) parm->pattern.bDstIP_Exclude = 1; if ((ptbl.key[14] >> 13) & 0x1) parm->pattern.bAppMSB_Exclude = 1; if ((ptbl.key[14] >> 14) & 0x1) parm->pattern.bAppLSB_Exclude = 1; if ((ptbl.key[14] >> 15) & 0x1) parm->pattern.bSrcMAC_Exclude = 1; if ((ptbl.key[14] & 0x1F) == 0x1F) { parm->pattern.nSubIfId = 0; parm->pattern.bSubIfIdEnable = 0; } else { parm->pattern.nSubIfId = (ptbl.key[14] & 0x1F); parm->pattern.bSubIfIdEnable = 1; } } /* Port ID */ if (((ptbl.key[0] & 0x0F) == 0x0F)) { parm->pattern.nPortId = 0; parm->pattern.bPortIdEnable = 0; } else { parm->pattern.nPortId = (ptbl.key[0] & 0xFF); parm->pattern.bPortIdEnable = 1; } if (((ptbl.key[6] >> 8) & 0x7F) == 0x7F) { parm->pattern.nDSCP = 0; parm->pattern.bDSCP_Enable = 0; } else { parm->pattern.nDSCP = (ptbl.key[6] >> 8) & 0x7F; parm->pattern.bDSCP_Enable = 1; } if (gswdev->gipver == LTQ_GSWIP_3_0) { /* Inner DSCP value used */ if (((ptbl.key[9] >> 8) & 0x7F) == 0x7F) { parm->pattern.nInnerDSCP = 0; parm->pattern.bInner_DSCP_Enable = 0; } else { parm->pattern.nInnerDSCP = (ptbl.key[9] >> 8) & 0x7F; parm->pattern.bInner_DSCP_Enable = 1; } parm->action.ePortFilterType_Action = (ptbl.val[7] >> 1) & 0x3F; if (ptbl.val[8] & 0x1) parm->action.eProcessPath_Action = ((ptbl.val[8] >> 1) & 0x3); if (gswdev->sdev == LTQ_FLOW_DEV_INT_R) { parm->action.bRtCtrlEna_Action = (ptbl.val[9] & 0x1); parm->action.bRtAccelEna_Action = ((ptbl.val[9] >> 1) & 0x1); parm->action.bRtInnerIPasKey_Action = ((ptbl.val[9] >> 2) & 0x1); if ((ptbl.val[9] >> 3) & 0x1) parm->action.bRtSrcIpMaskCmp_Action = 0; else parm->action.bRtSrcIpMaskCmp_Action = 1; if ((ptbl.val[9] >> 4) & 0x1) parm->action.bRtDstIpMaskCmp_Action = 0; else parm->action.bRtDstIpMaskCmp_Action = 1; if ((ptbl.val[9] >> 5) & 0x1) parm->action.bRtSrcPortMaskCmp_Action = 0; else parm->action.bRtSrcPortMaskCmp_Action = 1; if ((ptbl.val[9] >> 6) & 0x1) parm->action.bRtDstPortMaskCmp_Action = 0; else parm->action.bRtDstPortMaskCmp_Action = 1; if (((ptbl.val[9] >> 8) & 0xFF) == 0xFF) { parm->action.bRoutExtId_Action = 0; parm->action.nRoutExtId = 0; } else { parm->action.bRoutExtId_Action = 1; parm->action.nRoutExtId = ((ptbl.val[9] >> 8) & 0xFF); } } if ((ptbl.val[4] >> 4) & 0x1) { parm->action.bFlowID_Action = 1; parm->action.nFlowID = ptbl.val[1]; } else { parm->action.bFlowID_Action = 0; parm->action.nFlowID = 0; } parm->action.bPortLinkSelection = ((ptbl.val[5] >> 1) & 0x1); parm->action.bPortTrunkAction = ((ptbl.val[5] >> 0) & 0x1); parm->action.bPortBitMapMuxControl = ((ptbl.val[6] >> 0) & 0x1); if (((ptbl.val[5] >> 2) & 0x1) && ((ptbl.val[0] >> 1) & 0x1)) parm->action.bCVLAN_Ignore_Control = 1; else parm->action.bCVLAN_Ignore_Control = 0; if ((ptbl.val[0] >> 4) & 0x1) parm->action.eVLAN_CrossAction = ((ptbl.val[3] >> 15) & 0x1); else parm->action.eVLAN_CrossAction = 0; if ((ptbl.val[0] >> 1) & 0x1) { parm->action.eSVLAN_Action = 1; parm->action.nSVLAN_Id = (ptbl.val[6] >> 4) & 0xFFF; } else { parm->action.eSVLAN_Action = 0; parm->action.nSVLAN_Id = 0; } if ((ptbl.val[0] >> 1) & 0x1) { parm->action.eVLAN_Action = 1; parm->action.nVLAN_Id = (ptbl.val[5] >> 4) & 0xFFF; parm->action.nFId = ((ptbl.val[2] >> 8) & 0xFF); } else { parm->action.eVLAN_Action = 0; parm->action.nVLAN_Id = 0; parm->action.nFId = 0; } if ((ptbl.val[0] >> 12) & 0x1) { parm->action.bRMON_Action = 1; parm->action.nRMON_Id = (((ptbl.val[4] >> 8) & 0x1F) - 1); } else { parm->action.bRMON_Action = 0; parm->action.nRMON_Id = 0; } if ((ptbl.val[0] >> 11) & 0x1) { parm->action.eMeterAction = ((ptbl.val[3] >> 6) & 0x3); parm->action.nMeterId = (ptbl.val[3] & 0x1F); } else { parm->action.eMeterAction = 0; parm->action.nMeterId = 0; } if ((ptbl.val[3] >> 13) & 0x1) parm->action.bRemarkClass = 0; else parm->action.bRemarkClass = 1; if ((ptbl.val[3] >> 12) & 0x1) parm->action.bRemarkDSCP = 0; else parm->action.bRemarkDSCP = 1; if ((ptbl.val[6] >> 2) & 0x1) parm->action.bRemarkSTAG_DEI = 0; else parm->action.bRemarkSTAG_DEI = 1; if ((ptbl.val[6] >> 1) & 0x1) parm->action.bRemarkSTAG_PCP = 0; else parm->action.bRemarkSTAG_PCP = 1; if ((ptbl.val[3] >> 14) & 0x1) parm->action.bRemarkPCP = 0; else parm->action.bRemarkPCP = 1; if ((ptbl.val[0] >> 3) & 0x1) parm->action.bRemarkAction = 1; else parm->action.bRemarkAction = 0; if ((ptbl.val[0] >> 0) & 0x1) { if ((ptbl.val[1] == 0x0) && (((ptbl.val[4] >> 2) & 0x3) == 0x3)) { parm->action.ePortMapAction = GSW_PCE_ACTION_PORTMAP_DISCARD; parm->action.nForwardPortMap = 0; } else if ((ptbl.val[1] != 0x0) && (((ptbl.val[4] >> 2) & 0x3) == 0x3)) { parm->action.nForwardPortMap = ptbl.val[1]; parm->action.ePortMapAction = GSW_PCE_ACTION_PORTMAP_ALTERNATIVE; } else if ((((ptbl.val[4] >> 2) & 0x3) == 0x0)) { parm->action.nForwardPortMap = 0; parm->action.ePortMapAction = GSW_PCE_ACTION_PORTMAP_REGULAR; } else if ((((ptbl.val[4] >> 2) & 0x3) == 0x1)) { parm->action.nForwardPortMap = ptbl.val[1]; parm->action.ePortMapAction = GSW_PCE_ACTION_PORTMAP_CPU; } } else { parm->action.ePortMapAction = 0; parm->action.nForwardPortMap = 0; } if ((ptbl.val[0] >> 7) & 0x1) parm->action.eTimestampAction = ((ptbl.val[4] >> 15) & 0x1); if ((ptbl.val[0] >> 6) & 0x1) parm->action.eCritFrameAction = ((ptbl.val[4] >> 14) & 0x1); if ((ptbl.val[0] >> 5) & 0x1) parm->action.eCrossStateAction = ((ptbl.val[4] >> 13) & 0x1); if ((ptbl.val[0] >> 8) & 0x1) parm->action.eIrqAction = ((ptbl.val[0] >> 15) & 0x1); if ((ptbl.val[0] >> 9) & 0x1) parm->action.eLearningAction = ((ptbl.val[4]) & 0x3); parm->action.eSnoopingTypeAction = ((ptbl.val[4] >> 5) & 0x7); if ((ptbl.val[0] >> 2) & 1) { if ((ptbl.val[0] >> 14) & 1) parm->action.eTrafficClassAction = GSW_PCE_ACTION_TRAFFIC_CLASS_ALTERNATIVE; else parm->action.eTrafficClassAction = GSW_PCE_ACTION_TRAFFIC_CLASS_REGULAR; if (((ptbl.val[3] >> 8) & 0xF) == 0xF) parm->action.nTrafficClassAlternate = 0; else parm->action.nTrafficClassAlternate = ((ptbl.val[3] >> 8) & 0xF); } } if (((ptbl.key[6]) & 0xF) == 0xF) { parm->pattern.nPCP = 0; parm->pattern.bPCP_Enable = 0; } else { parm->pattern.nPCP = (ptbl.key[6]) & 0xF; parm->pattern.bPCP_Enable = 1; } if (((ptbl.key[8]) & 0x1F) == 0x1F) { parm->pattern.nSTAG_PCP_DEI = 0; parm->pattern.bSTAG_PCP_DEI_Enable = 0; } else { parm->pattern.nSTAG_PCP_DEI = (ptbl.key[8]) & 0x1F; parm->pattern.bSTAG_PCP_DEI_Enable = 1; } ptable = &(pthandle->pce_tbl[idx]); if (ptable->pkt_lng_idx != 0x1F) { pce_pkt_length_t pkg_lng_tbl; memset(&pkg_lng_tbl, 0, sizeof(pce_pkt_length_t)); /* Packet length used */ parm->pattern.bPktLngEnable = 1; if (0 != pce_tm_pkg_lng_tbl_read(&pthandle->pce_sub_tbl, ptable->pkt_lng_idx, &pkg_lng_tbl)) GSW_RETURN_PCE; /* Packet length */ parm->pattern.nPktLng = pkg_lng_tbl.pkg_lng; /* Packet length Range */ parm->pattern.nPktLngRange = pkg_lng_tbl.pkg_lng_rng; } if (ptable->dst_mac_addr_idx != 0xFF) { pce_da_prog_t da_mac_tbl; memset(&da_mac_tbl, 0, sizeof(pce_da_prog_t)); if (0 != pce_tm_da_mac_tbl_read(&pthandle->pce_sub_tbl, ptable->dst_mac_addr_idx, &da_mac_tbl)) GSW_RETURN_PCE; /* Destination MAC address used */ parm->pattern.bMAC_DstEnable = 1; /* Destination MAC address */ for (i = 0; i < 6; i++) parm->pattern.nMAC_Dst[i] = da_mac_tbl.mac[i]; /* Destination MAC address mask */ parm->pattern.nMAC_DstMask = da_mac_tbl.mac_mask; } if (ptable->src_mac_addr_idx != 0xFF) { pce_sa_prog_t sa_mac_tbl; memset(&sa_mac_tbl, 0, sizeof(pce_sa_prog_t)); if (0 != pce_tm_sa_mac_tbl_read(&pthandle->pce_sub_tbl, ptable->src_mac_addr_idx, &sa_mac_tbl)) GSW_RETURN_PCE; /* Destination MAC address used */ parm->pattern.bMAC_SrcEnable = 1; /* Destination MAC address */ for (i = 0; i < 6; i++) parm->pattern.nMAC_Src[i] = sa_mac_tbl.mac[i]; /* Destination MAC address mask */ parm->pattern.nMAC_SrcMask = sa_mac_tbl.mac_mask; } if (ptable->payload1_idx != 0xFF) { payload_tbl_t payload_tbl; memset(&payload_tbl, 0, sizeof(payload_tbl_t)); if (0 != pce_tm_payload_tbl_read(&pthandle->pce_sub_tbl, ptable->payload1_idx, &payload_tbl)) GSW_RETURN_PCE; /* Destination Application used */ parm->pattern.bPayload1_SrcEnable = 1; /* Destination Application field */ parm->pattern.nPayload1 = payload_tbl.payload_data; /* Payload mask/range used */ parm->pattern.bPayload1MaskRange_Select = payload_tbl.mask_range_type; /* Payload mask/range */ parm->pattern.nPayload1_Mask = payload_tbl.mask_range; } if (ptable->payload2_idx != 0xFF) { payload_tbl_t payload_tbl; memset(&payload_tbl, 0, sizeof(payload_tbl_t)); if (0 != pce_tm_payload_tbl_read(&pthandle->pce_sub_tbl, ptable->payload2_idx, &payload_tbl)) GSW_RETURN_PCE; /* Destination Application used */ parm->pattern.bPayload2_SrcEnable = 1; /* Destination Application field */ parm->pattern.nPayload2 = payload_tbl.payload_data; /* Payload mask/range used */ parm->pattern.bPayload2MaskRange_Select = payload_tbl.mask_range_type; /* Payload mask/range */ parm->pattern.nPayload2_Mask = payload_tbl.mask_range; } if (ptable->dst_appl_fld_idx != 0xFF) { app_tbl_t appl_tbl; memset(&appl_tbl, 0, sizeof(app_tbl_t)); if (0 != pce_tm_appl_tbl_read(&pthandle->pce_sub_tbl, ptable->dst_appl_fld_idx, &appl_tbl)) GSW_RETURN_PCE; /* Destination Application used */ parm->pattern.bAppDataMSB_Enable = 1; /* Destination Application field */ parm->pattern.nAppDataMSB = appl_tbl.appl_data; /* Destination Application mask/range used */ parm->pattern.bAppMaskRangeMSB_Select = appl_tbl.mask_range_type; /* Destination Application mask/range */ parm->pattern.nAppMaskRangeMSB = appl_tbl.mask_range; } if (ptable->src_appl_fld_idx != 0xFF) { app_tbl_t appl_tbl; memset(&appl_tbl, 0, sizeof(app_tbl_t)); if (0 != pce_tm_appl_tbl_read(&pthandle->pce_sub_tbl, ptable->src_appl_fld_idx, &appl_tbl)) GSW_RETURN_PCE; /* Source Application used */ parm->pattern.bAppDataLSB_Enable = 1; /* Source Application field */ parm->pattern.nAppDataLSB = appl_tbl.appl_data; /* Destination Application mask/range used */ parm->pattern.bAppMaskRangeLSB_Select = appl_tbl.mask_range_type; /* Source Application mask/range */ parm->pattern.nAppMaskRangeLSB = appl_tbl.mask_range; } if (gswdev->gipver == LTQ_GSWIP_3_0) { if (ptable->parse_lsb_idx != 0xFF) { flag_tbl_t flags_tbl; memset(&flags_tbl, 0, sizeof(flag_tbl_t)); if (0 != pce_tm_flags_tbl_read(&pthandle->pce_sub_tbl, ptable->parse_lsb_idx, &flags_tbl)) GSW_RETURN_PCE; parm->pattern.bParserFlagLSB_Enable = 1; parm->pattern.nParserFlagLSB = flags_tbl.parser_flag_data; parm->pattern.nParserFlagLSB_Mask = flags_tbl.mask_value; } if (ptable->parse_msb_idx != 0xFF) { flag_tbl_t flags_tbl; memset(&flags_tbl, 0, sizeof(flag_tbl_t)); if (0 != pce_tm_flags_tbl_read(&pthandle->pce_sub_tbl, ptable->parse_msb_idx, &flags_tbl)) GSW_RETURN_PCE; parm->pattern.bParserFlagMSB_Enable = 1; parm->pattern.nParserFlagMSB = flags_tbl.parser_flag_data; parm->pattern.nParserFlagMSB_Mask = flags_tbl.mask_value; } if ((ptable->inr_dip_msb_idx != 0xFF) && (ptable->inr_dip_lsb_idx != 0xFF)) { /*for IPv6 */ pce_dasa_msb_t dasa_tbl; pce_dasa_lsb_t dasa_tbl_lsb; int i, j; memset(&dasa_tbl, 0, sizeof(pce_dasa_msb_t)); memset(&dasa_tbl_lsb, 0, sizeof(pce_dasa_lsb_t)); /* Inner DIP MSB used */ parm->pattern.eInnerDstIP_Select = GSW_PCE_IP_V6; if (0 != pce_dasa_msb_tbl_read(&pthandle->pce_sub_tbl, ptable->inr_dip_msb_idx, &dasa_tbl)) GSW_RETURN_PCE; /* First, search for DIP in the DA/SA table (DIP MSB) */ for (i = 0, j = 7; i < 4; i++, j -= 2) parm->pattern.nInnerDstIP.nIPv6[i] = (((dasa_tbl.imsb[j] & 0xFF) << 8) | (dasa_tbl.imsb[j-1] & 0xFF)); /* Inner DIP MSB Nibble Mask */ if (gswdev->gipver == LTQ_GSWIP_3_0) parm->pattern.nInnerDstIP_Mask = (dasa_tbl.nmask & 0xFFFF) << 16; else parm->pattern.nInnerDstIP_Mask = (dasa_tbl.mask[0] & 0xFFFF) << 16; /* Inner DIP LSB used */ parm->pattern.eInnerDstIP_Select = GSW_PCE_IP_V6; if (0 != pce_dasa_lsb_tbl_read(&pthandle->pce_sub_tbl, ptable->inr_dip_lsb_idx, &dasa_tbl_lsb)) GSW_RETURN_PCE; for (i = 0, j = 7; i < 4; i++, j -= 2) parm->pattern.nInnerDstIP.nIPv6[i+4] = (((dasa_tbl_lsb.ilsb[j] & 0xFF) << 8) | (dasa_tbl_lsb.ilsb[j-1] & 0xFF)); if (gswdev->gipver == LTQ_GSWIP_3_0) parm->pattern.nInnerDstIP_Mask |= dasa_tbl_lsb.nmask & 0xFFFF; else parm->pattern.nInnerDstIP_Mask |= dasa_tbl_lsb.mask[0] & 0xFFFF; } else if (ptable->inr_dip_lsb_idx != 0xFF) { /*For IPv4 only */ pce_dasa_lsb_t dasa_tbl; memset(&dasa_tbl, 0, sizeof(pce_dasa_lsb_t)); /*Inner DIP LSB used */ parm->pattern.eInnerDstIP_Select = GSW_PCE_IP_V4; if (0 != pce_dasa_lsb_tbl_read(&pthandle->pce_sub_tbl, ptable->inr_dip_lsb_idx, &dasa_tbl)) GSW_RETURN_PCE; /* Inner DIP LSB */ parm->pattern.nInnerDstIP.nIPv4 = (dasa_tbl.ilsb[0] | (dasa_tbl.ilsb[1] << 8) | (dasa_tbl.ilsb[2] << 16) | (dasa_tbl.ilsb[3] << 24)); if (gswdev->gipver == LTQ_GSWIP_3_0) parm->pattern.nInnerDstIP_Mask = dasa_tbl.nmask; else /* Inner DIP LSB Nibble Mask */ parm->pattern.nInnerDstIP_Mask = dasa_tbl.mask[0]; } if ((ptable->inr_sip_msb_idx != 0xFF) && (ptable->inr_sip_lsb_idx != 0xFF)) { /* for IPv6 */ pce_dasa_msb_t dasa_tbl; pce_dasa_lsb_t dasa_tbl_lsb; int i, j; memset(&dasa_tbl, 0, sizeof(pce_dasa_msb_t)); memset(&dasa_tbl_lsb, 0, sizeof(pce_dasa_lsb_t)); /* Inner SIP MSB used */ parm->pattern.eInnerSrcIP_Select = GSW_PCE_IP_V6; if (0 != pce_dasa_msb_tbl_read(&pthandle->pce_sub_tbl, ptable->inr_sip_msb_idx, &dasa_tbl)) GSW_RETURN_PCE; for (i = 0, j = 7; i < 4; i++, j -= 2) parm->pattern.nInnerSrcIP.nIPv6[i] = (((dasa_tbl.imsb[j] & 0xFF) << 8) | (dasa_tbl.imsb[j-1] & 0xFF)); if (gswdev->gipver == LTQ_GSWIP_3_0) { parm->pattern.nInnerSrcIP_Mask = (dasa_tbl.nmask & 0xFFFF) << 16; } else { /* Inner SIP MSB Nibble Mask */ parm->pattern.nInnerSrcIP_Mask = (dasa_tbl.mask[0] & 0xFFFF) << 16; } /* Inner SIP LSB used */ parm->pattern.eInnerSrcIP_Select = GSW_PCE_IP_V6; if (0 != pce_dasa_lsb_tbl_read(&pthandle->pce_sub_tbl, ptable->inr_sip_lsb_idx, &dasa_tbl_lsb)) GSW_RETURN_PCE; for (i = 0, j = 7; i < 4; i++, j -= 2) parm->pattern.nInnerSrcIP.nIPv6[i+4] = (((dasa_tbl_lsb.ilsb[j] & 0xFF) << 8) | (dasa_tbl_lsb.ilsb[j-1] & 0xFF)); parm->pattern.nInnerSrcIP_Mask |= dasa_tbl_lsb.nmask & 0xFFFF; } else if (ptable->inr_sip_lsb_idx != 0xFF) { /* for IPv4 only */ pce_dasa_lsb_t dasa_tbl; memset(&dasa_tbl, 0, sizeof(pce_dasa_lsb_t)); /* Inner SIP LSB used */ parm->pattern.eInnerSrcIP_Select = GSW_PCE_IP_V4; if (0 != pce_dasa_lsb_tbl_read(&pthandle->pce_sub_tbl, ptable->inr_sip_lsb_idx, &dasa_tbl)) GSW_RETURN_PCE; /* Inner SIP LSB */ parm->pattern.nInnerSrcIP.nIPv4 = (dasa_tbl.ilsb[0] | (dasa_tbl.ilsb[1] << 8) | (dasa_tbl.ilsb[2] << 16) | (dasa_tbl.ilsb[3] << 24)); parm->pattern.nInnerSrcIP_Mask = dasa_tbl.nmask; } } /*LTQ_GSWIP_3_0*/ if ((ptable->dip_msb_idx != 0xFF) && (ptable->dip_lsb_idx != 0xFF)) { /*for IPv6 */ pce_dasa_msb_t dasa_tbl; pce_dasa_lsb_t dasa_tbl_lsb; int i, j; memset(&dasa_tbl, 0, sizeof(pce_dasa_msb_t)); memset(&dasa_tbl_lsb, 0, sizeof(pce_dasa_lsb_t)); /* DIP MSB used */ parm->pattern.eDstIP_Select = GSW_PCE_IP_V6; if (0 != pce_dasa_msb_tbl_read(&pthandle->pce_sub_tbl, ptable->dip_msb_idx, &dasa_tbl)) GSW_RETURN_PCE; /* First, search for DIP in the DA/SA table (DIP MSB) */ for (i = 0, j = 7; i < 4; i++, j -= 2) parm->pattern.nDstIP.nIPv6[i] = (((dasa_tbl.imsb[j] & 0xFF) << 8) | (dasa_tbl.imsb[j-1] & 0xFF)); if (gswdev->gipver == LTQ_GSWIP_3_0) parm->pattern.nDstIP_Mask = (dasa_tbl.nmask & 0xFFFF) << 16; else /* DIP MSB Nibble Mask */ parm->pattern.nDstIP_Mask = (dasa_tbl.mask[0] & 0xFFFF) << 16; /* DIP LSB used */ parm->pattern.eDstIP_Select = GSW_PCE_IP_V6; if (0 != pce_dasa_lsb_tbl_read(&pthandle->pce_sub_tbl, ptable->dip_lsb_idx, &dasa_tbl_lsb)) GSW_RETURN_PCE; for (i = 0, j = 7; i < 4; i++, j -= 2) parm->pattern.nDstIP.nIPv6[i+4] = (((dasa_tbl_lsb.ilsb[j] & 0xFF) << 8) | (dasa_tbl_lsb.ilsb[j-1] & 0xFF)); if (gswdev->gipver == LTQ_GSWIP_3_0) parm->pattern.nDstIP_Mask |= dasa_tbl_lsb.nmask & 0xFFFF; else parm->pattern.nDstIP_Mask |= dasa_tbl_lsb.mask[0] & 0xFFFF; } else if (ptable->dip_lsb_idx != 0xFF) { /*For IPv4 only */ pce_dasa_lsb_t dasa_tbl; memset(&dasa_tbl, 0, sizeof(pce_dasa_lsb_t)); /* DIP LSB used */ parm->pattern.eDstIP_Select = GSW_PCE_IP_V4; if (0 != pce_dasa_lsb_tbl_read(&pthandle->pce_sub_tbl, ptable->dip_lsb_idx, &dasa_tbl)) GSW_RETURN_PCE; /* DIP LSB */ parm->pattern.nDstIP.nIPv4 = (dasa_tbl.ilsb[0] | (dasa_tbl.ilsb[1] << 8) | (dasa_tbl.ilsb[2] << 16) | (dasa_tbl.ilsb[3] << 24)); if (gswdev->gipver == LTQ_GSWIP_3_0) parm->pattern.nDstIP_Mask = dasa_tbl.nmask; else /* DIP LSB Nibble Mask */ parm->pattern.nDstIP_Mask = dasa_tbl.mask[0]; } if ((ptable->sip_msb_idx != 0xFF) && (ptable->sip_lsb_idx != 0xFF)) { /* for IPv6 */ pce_dasa_msb_t dasa_tbl; pce_dasa_lsb_t dasa_tbl_lsb; int i, j; memset(&dasa_tbl, 0, sizeof(pce_dasa_msb_t)); memset(&dasa_tbl_lsb, 0, sizeof(pce_dasa_lsb_t)); /* SIP MSB used */ parm->pattern.eSrcIP_Select = GSW_PCE_IP_V6; if (0 != pce_dasa_msb_tbl_read(&pthandle->pce_sub_tbl, ptable->sip_msb_idx, &dasa_tbl)) GSW_RETURN_PCE; for (i = 0, j = 7; i < 4; i++, j -= 2) parm->pattern.nSrcIP.nIPv6[i] = (((dasa_tbl.imsb[j] & 0xFF) << 8) | (dasa_tbl.imsb[j-1] & 0xFF)); if (gswdev->gipver == LTQ_GSWIP_3_0) { parm->pattern.nSrcIP_Mask = (dasa_tbl.nmask & 0xFFFF) << 16; } else { /* SIP MSB Nibble Mask */ parm->pattern.nSrcIP_Mask = (dasa_tbl.mask[0] & 0xFFFF) << 16; } /* SIP LSB used */ parm->pattern.eSrcIP_Select = GSW_PCE_IP_V6; if (0 != pce_dasa_lsb_tbl_read(&pthandle->pce_sub_tbl, ptable->sip_lsb_idx, &dasa_tbl_lsb)) GSW_RETURN_PCE; for (i = 0, j = 7; i < 4; i++, j -= 2) parm->pattern.nSrcIP.nIPv6[i+4] = (((dasa_tbl_lsb.ilsb[j] & 0xFF) << 8) | (dasa_tbl_lsb.ilsb[j-1] & 0xFF)); if (gswdev->gipver == LTQ_GSWIP_3_0) { parm->pattern.nSrcIP_Mask |= dasa_tbl_lsb.nmask & 0xFFFF; } else { /* SIP LSB Nibble Mask */ parm->pattern.nSrcIP_Mask |= dasa_tbl_lsb.mask[0] & 0xFFFF; } } else if (ptable->sip_lsb_idx != 0xFF) { /* for IPv4 only */ pce_dasa_lsb_t dasa_tbl; memset(&dasa_tbl, 0, sizeof(pce_dasa_lsb_t)); /* SIP LSB used */ parm->pattern.eSrcIP_Select = GSW_PCE_IP_V4; if (0 != pce_dasa_lsb_tbl_read(&pthandle->pce_sub_tbl, ptable->sip_lsb_idx, &dasa_tbl)) GSW_RETURN_PCE; /* SIP LSB */ parm->pattern.nSrcIP.nIPv4 = (dasa_tbl.ilsb[0] | (dasa_tbl.ilsb[1] << 8) | (dasa_tbl.ilsb[2] << 16) | (dasa_tbl.ilsb[3] << 24)); if (gswdev->gipver == LTQ_GSWIP_3_0) parm->pattern.nSrcIP_Mask = dasa_tbl.nmask; else /* SIP LSB Nibble Mask */ parm->pattern.nSrcIP_Mask = dasa_tbl.mask[0]; } if (ptable->ethertype_idx != 0xFF) { prtcol_tbl_t pctl_tbl; memset(&pctl_tbl, 0, sizeof(prtcol_tbl_t)); /* Ethertype used */ parm->pattern.bEtherTypeEnable = 1; if (0 != pce_tm_ptcl_tbl_read(&pthandle->pce_sub_tbl, ptable->ethertype_idx, &pctl_tbl)) GSW_RETURN_PCE; /* Ethertype */ parm->pattern.nEtherType = pctl_tbl.ethertype; /* Ethertype Mask */ parm->pattern.nEtherTypeMask = pctl_tbl.emask; } if (gswdev->gipver == LTQ_GSWIP_3_0) { if (ptable->ppp_prot_idx != 0xFF) { prtcol_tbl_t pctl_tbl; memset(&pctl_tbl, 0, sizeof(prtcol_tbl_t)); /* Ethertype used */ parm->pattern.bPPP_ProtocolEnable = 1; if (0 != pce_tm_ptcl_tbl_read(&pthandle->pce_sub_tbl, ptable->ppp_prot_idx, &pctl_tbl)) GSW_RETURN_PCE; /* Ethertype */ parm->pattern.nPPP_Protocol = pctl_tbl.ethertype; /* Ethertype Mask */ parm->pattern.nPPP_ProtocolMask = pctl_tbl.emask; } } if (ptable->ip_prot_idx != 0xFF) { prtcol_tbl_t pctl_tbl; memset(&pctl_tbl, 0, sizeof(prtcol_tbl_t)); /* IP protocol used */ if (0 != pce_tm_ptcl_tbl_read(&pthandle->pce_sub_tbl, ptable->ip_prot_idx, &pctl_tbl)) GSW_RETURN_PCE; if ((pctl_tbl.ethertype & 0xFF) == 0xFF) parm->pattern.bProtocolEnable = 0; else parm->pattern.bProtocolEnable = 1; if (((pctl_tbl.ethertype >> 8) & 0xFF) == 0xFF) parm->pattern.bInnerProtocolEnable = 0; else parm->pattern.bInnerProtocolEnable = 1; /* IP protocol */ parm->pattern.nProtocol = pctl_tbl.ethertype & 0xFF; /* IP protocol Mask */ parm->pattern.nProtocolMask = pctl_tbl.emask & 0x3; /* IP protocol */ parm->pattern.nInnerProtocol = (pctl_tbl.ethertype >> 8) & 0xFF; /* IP protocol Mask */ parm->pattern.nInnerProtocolMask = (pctl_tbl.emask >> 2) & 0x3; } if (ptable->pppoe_idx != 0x1F) { pce_ppoe_tbl_t pppoe_tbl; memset(&pppoe_tbl, 0, sizeof(pce_ppoe_tbl_t)); /* PPPoE used */ parm->pattern.bSessionIdEnable = 1; if (0 != pce_tm_pppoe_tbl_read(&pthandle->pce_sub_tbl, ptable->pppoe_idx, &pppoe_tbl)) GSW_RETURN_PCE; /* PPPoE */ parm->pattern.nSessionId = pppoe_tbl.sess_id; } if (ptable->vlan_idx != 0x7F) { pctbl_prog_t pcetable_vlan; memset(&pcetable_vlan, 0, sizeof(pctbl_prog_t)); /* VLAN used */ parm->pattern.bVid = 1; pcetable_vlan.table = PCE_ACTVLAN_INDEX; /*index of the VLAN ID configuration */ pcetable_vlan.pcindex = ptable->vlan_idx; /* ptbl.key[0] = parm->nVId; */ gsw_pce_table_read(cdev, &pcetable_vlan); if (pcetable_vlan.valid == 1) parm->pattern.nVid = pcetable_vlan.key[0] & 0xFFF; } if (ptable->svlan_idx != 0x7F) { pctbl_prog_t pcetable_vlan; memset(&pcetable_vlan, 0, sizeof(pctbl_prog_t)); /* VLAN used */ parm->pattern.bSLAN_Vid = 1; pcetable_vlan.table = PCE_ACTVLAN_INDEX; /*index of the VLAN ID configuration */ pcetable_vlan.pcindex = ptable->svlan_idx; /* ptbl.key[0] = parm->nVId; */ gsw_pce_table_read(cdev, &pcetable_vlan); if (pcetable_vlan.valid == 1) parm->pattern.nSLAN_Vid = pcetable_vlan.key[0] & 0xFFF; } /* Copy whole action table into action structure */ /* memcpy(&parm->action, &pthandle->pce_act[idx], */ /* sizeof(GSW_PCE_action_t)); */ return 0; } int pce_rule_write(void *cdev, ltq_pce_table_t *pthandle, GSW_PCE_rule_t *parm) { ethsw_api_dev_t *gswdev = (ethsw_api_dev_t *)cdev; pctbl_prog_t ptbl; u32 idx = parm->pattern.nIndex; pce_table_t *ptable; GSW_PCE_action_t *paction; GSW_PCE_rule_t key_current; int tindex, i, reg_val; PCE_ASSERT(idx >= PCE_TABLE_SIZE); if (parm->pattern.bEnable == 0) { /* Entry to delete. */ return pce_pattern_delete(cdev, pthandle, idx); } /* first read the current value context from the table to compare if */ /* the new configuration is the same. */ key_current.pattern.nIndex = idx; /* This key is already programmed on the hardware, no need to update */ /* the current hardware programming. */ if (pce_rule_read(cdev, pthandle, &key_current) != 0) GSW_RETURN_PCE; if (!memcmp(&key_current, parm, sizeof(GSW_PCE_rule_t))) return 0; memset(&ptbl, 0, sizeof(pctbl_prog_t)); gsw_r32(cdev, PCE_GCTRL_1_VLANMD_OFFSET, PCE_GCTRL_1_VLANMD_SHIFT, PCE_GCTRL_1_VLANMD_SIZE, ®_val); /* Delete the old entry before adding the new one. */ if (pthandle->ptblused[idx] != 0) { if (pce_pattern_delete(cdev, pthandle, idx) != 0) GSW_RETURN_PCE; } /* Mark the entry as taken already and then program it. */ pthandle->ptblused[idx] = 1; /* Now convert the parameter and add to the table. */ ptable = &(pthandle->pce_tbl[idx]); /* Port ID */ if (parm->pattern.bPortIdEnable == 1) ptbl.key[0] = (parm->pattern.nPortId & 0xFF); else ptbl.key[0] = 0xFF; /* DSCP value used */ if (parm->pattern.bDSCP_Enable == 1) ptbl.key[6] |= ((parm->pattern.nDSCP & 0x3F) << 8); else ptbl.key[6] |= (0x7F << 8); if (gswdev->gipver == LTQ_GSWIP_3_0) { /* Inner DSCP value used */ if (parm->pattern.bInner_DSCP_Enable == 1) ptbl.key[9] |= ((parm->pattern.nInnerDSCP & 0x3F) << 8); else ptbl.key[9] |= (0x7F << 8); } /* PCP value used */ if (parm->pattern.bPCP_Enable == 1) ptbl.key[6] |= (parm->pattern.nPCP & 0x7); else ptbl.key[6] |= 0xF; /* PCP DEI value used */ ptbl.key[8] &= ~(0x1F); if (parm->pattern.bSTAG_PCP_DEI_Enable == 1) { /* PCP value */ ptbl.key[8] |= (parm->pattern.nSTAG_PCP_DEI & 0xF); } else { ptbl.key[8] |= 0x1F; } /* Packet length used */ if (parm->pattern.bPktLngEnable == 1) { pce_pkt_length_t pkg_lng; /* Packet length */ pkg_lng.pkg_lng = parm->pattern.nPktLng; /* Packet length range, in number of bytes */ pkg_lng.pkg_lng_rng = parm->pattern.nPktLngRange; tindex = pce_tm_pkg_lng_tbl_write(cdev, &pthandle->pce_sub_tbl, &pkg_lng); if (tindex < 0) return tindex; ptable->pkt_lng_idx = tindex; } else { ptable->pkt_lng_idx = 0x1F; } ptbl.key[7] = ptable->pkt_lng_idx; /* Destination MAC address used */ if (parm->pattern.bMAC_DstEnable == 1) { pce_da_prog_t da_mac_tbl; for (i = 0; i < 6; i++) da_mac_tbl.mac[i] = parm->pattern.nMAC_Dst[i]; da_mac_tbl.mac_mask = parm->pattern.nMAC_DstMask; tindex = pce_da_mac_tbl_write(cdev, &pthandle->pce_sub_tbl, &da_mac_tbl); if (tindex < 0) return tindex; ptable->dst_mac_addr_idx = tindex; } else { ptable->dst_mac_addr_idx = 0xFF; } ptbl.key[5] |= (ptable->dst_mac_addr_idx << 8); /* Source MAC address used */ if (parm->pattern.bMAC_SrcEnable == 1) { pce_sa_prog_t sa_mac_tbl; for (i = 0; i < 6; i++) sa_mac_tbl.mac[i] = parm->pattern.nMAC_Src[i]; /* Source MAC address mask */ sa_mac_tbl.mac_mask = parm->pattern.nMAC_SrcMask; tindex = pce_sa_mac_tbl_write(cdev, &pthandle->pce_sub_tbl, &sa_mac_tbl); if (tindex < 0) return tindex; ptable->src_mac_addr_idx = tindex; } else { ptable->src_mac_addr_idx = 0xFF; } ptbl.key[5] |= ptable->src_mac_addr_idx; if (gswdev->gipver == LTQ_GSWIP_3_0) { /* Parser Flags Table */ if (parm->pattern.bParserFlagLSB_Enable == 1) { flag_tbl_t flags_tbl; memset(&flags_tbl, 0, sizeof(flag_tbl_t)); flags_tbl.parser_flag_data = parm->pattern.nParserFlagLSB; flags_tbl.mask_value = parm->pattern.nParserFlagLSB_Mask; flags_tbl.valid = 1; tindex = pce_flags_tbl_write(cdev, &pthandle->pce_sub_tbl, &flags_tbl); if (tindex < 0) return tindex; ptable->parse_lsb_idx = tindex; } else { ptable->parse_lsb_idx = 0xFF; } ptbl.key[12] |= ptable->parse_lsb_idx; /* Source Application field used */ if (parm->pattern.bParserFlagMSB_Enable == 1) { flag_tbl_t flags_tbl; memset(&flags_tbl, 0, sizeof(flag_tbl_t)); flags_tbl.parser_flag_data = parm->pattern.nParserFlagMSB; flags_tbl.mask_value = parm->pattern.nParserFlagMSB_Mask; flags_tbl.valid = 1; tindex = pce_flags_tbl_write(cdev, &pthandle->pce_sub_tbl, &flags_tbl); if (tindex < 0) return tindex; ptable->parse_msb_idx = tindex; } else { ptable->parse_msb_idx = 0xFF; } ptbl.key[12] |= (ptable->parse_msb_idx << 8); /* Payload1 used */ if (parm->pattern.bPayload1_SrcEnable == 1) { payload_tbl_t payload_tbl; memset(&payload_tbl, 0, sizeof(payload_tbl_t)); payload_tbl.mask_range_type = parm->pattern.bPayload1MaskRange_Select; payload_tbl.payload_data = parm->pattern.nPayload1; payload_tbl.mask_range = parm->pattern.nPayload1_Mask; payload_tbl.valid = 1; tindex = pce_payload_tbl_write(cdev, &pthandle->pce_sub_tbl, &payload_tbl); if (tindex < 0) return tindex; ptable->payload1_idx = tindex; } else { ptable->payload1_idx = 0xFF; } ptbl.key[13] |= ptable->payload1_idx; /* Payload2 used */ if (parm->pattern.bPayload2_SrcEnable == 1) { payload_tbl_t payload_tbl; memset(&payload_tbl, 0, sizeof(payload_tbl_t)); payload_tbl.mask_range_type = parm->pattern.bPayload2MaskRange_Select; payload_tbl.payload_data = parm->pattern.nPayload2; /* Destination Application mask/range */ payload_tbl.mask_range = parm->pattern.nPayload2_Mask; payload_tbl.valid = 1; tindex = pce_payload_tbl_write(cdev, &pthandle->pce_sub_tbl, &payload_tbl); if (tindex < 0) return tindex; ptable->payload2_idx = tindex; } else { ptable->payload2_idx = 0xFF; } ptbl.key[13] |= (ptable->payload2_idx << 8); } /* Destination Application used */ if (parm->pattern.bAppDataMSB_Enable == 1) { app_tbl_t appl_tbl; appl_tbl.mask_range_type = parm->pattern.bAppMaskRangeMSB_Select; /* Destination Application field */ appl_tbl.appl_data = parm->pattern.nAppDataMSB; /* Destination Application mask/range */ appl_tbl.mask_range = parm->pattern.nAppMaskRangeMSB; tindex = pce_appl_tbl_write(cdev, &pthandle->pce_sub_tbl, &appl_tbl); if (tindex < 0) return tindex; ptable->dst_appl_fld_idx = tindex; } else { ptable->dst_appl_fld_idx = 0xFF; } ptbl.key[4] |= ptable->dst_appl_fld_idx; /* Source Application field used */ if (parm->pattern.bAppDataLSB_Enable == 1) { app_tbl_t appl_tbl; appl_tbl.mask_range_type = parm->pattern.bAppMaskRangeLSB_Select; /* Source Application field */ appl_tbl.appl_data = parm->pattern.nAppDataLSB; /* Source Application mask/range */ appl_tbl.mask_range = parm->pattern.nAppMaskRangeLSB; tindex = pce_appl_tbl_write(cdev, &pthandle->pce_sub_tbl, &appl_tbl); if (tindex < 0) return tindex; ptable->src_appl_fld_idx = tindex; } else { ptable->src_appl_fld_idx = 0xFF; } ptbl.key[4] |= (ptable->src_appl_fld_idx << 8); ptable->dip_msb_idx = 0xFF; ptable->dip_lsb_idx = 0xFF; /* DIP MSB used */ if (parm->pattern.eDstIP_Select == /*2*/GSW_PCE_IP_V6) { pce_dasa_msb_t mtbl; pce_dasa_lsb_t ltbl; int j; memset(&mtbl, 0, sizeof(pce_dasa_msb_t)); memset(<bl, 0, sizeof(pce_dasa_lsb_t)); /* First, search for DIP in the DA/SA table (DIP MSB) */ for (i = 0, j = 7; i < 4; i++, j -= 2) { mtbl.imsb[j-1] = (parm->pattern.nDstIP.nIPv6[i] & 0xFF); mtbl.imsb[j] = ((parm->pattern.nDstIP.nIPv6[i] >> 8) & 0xFF); } if (gswdev->gipver == LTQ_GSWIP_3_0) { mtbl.nmask = (u16)((parm->pattern.nDstIP_Mask >> 16) & 0xFFFF); for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if ((((parm->pattern.nDstIP_Mask >> ((i * 4) + 16)) & 0xF) >> j) & 0x1) mtbl.mask[i] |= (0xF << (j*4)); } } } else { mtbl.mask[0] = (u16)((parm->pattern.nDstIP_Mask >> 16) & 0xFFFF); } mtbl.valid = 1; tindex = pce_dasa_msb_tbl_write(cdev, &pthandle->pce_sub_tbl, &mtbl); if (tindex < 0) { pr_err("%s:%s:%d(DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->dip_msb_idx = tindex; /* First, search for DIP in the DA/SA table (DIP LSB) */ for (i = 0, j = 7; i < 4; i++, j -= 2) { ltbl.ilsb[j-1] = (parm->pattern.nDstIP.nIPv6[i+4] & 0xFF); ltbl.ilsb[j] = ((parm->pattern.nDstIP.nIPv6[i+4] >> 8) & 0xFF); } if (gswdev->gipver == LTQ_GSWIP_3_0) { ltbl.nmask = (u16)(parm->pattern.nDstIP_Mask & 0xFFFF); for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if ((((parm->pattern.nDstIP_Mask >> (i * 4)) & 0xF) >> j) & 0x1) ltbl.mask[i] |= (0xF << (j*4)); } } } else { ltbl.mask[0] = (u16)(parm->pattern.nDstIP_Mask & 0xFFFF); } ltbl.valid = 1; tindex = pce_dasa_lsb_tbl_write(cdev, &pthandle->pce_sub_tbl, <bl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->dip_lsb_idx = (u16)tindex; } else if (parm->pattern.eDstIP_Select == GSW_PCE_IP_V4) { /* DIP LSB used */ pce_dasa_lsb_t ltbl; memset(<bl, 0, sizeof(pce_dasa_lsb_t)); /* First, search for DIP in the DA/SA table (DIP LSB) */ for (i = 0; i < 4; i++) ltbl.ilsb[i] = ((parm->pattern.nDstIP.nIPv4 >> (i * 8)) & 0xFF); if (gswdev->gipver == LTQ_GSWIP_3_0) { int j; ltbl.nmask = (u16)(parm->pattern.nDstIP_Mask) & 0xFFFF; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if ((((parm->pattern.nDstIP_Mask >> (i * 4)) & 0xF) >> j) & 0x1) ltbl.mask[i] |= (0xF << (j*4)); } } } else { /* DIP LSB Nibble Mask */ ltbl.mask[0] = (u16)(parm->pattern.nDstIP_Mask | 0xFF00) & 0xFFFF; } ltbl.valid = 1; tindex = pce_dasa_lsb_tbl_write(cdev, &pthandle->pce_sub_tbl, <bl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->dip_lsb_idx = (u16)tindex; } ptbl.key[3] |= (ptable->dip_msb_idx << 8); ptbl.key[3] |= ptable->dip_lsb_idx; /* SIP MSB used */ ptable->sip_msb_idx = 0xFF; ptable->sip_lsb_idx = 0xFF; if (parm->pattern.eSrcIP_Select == GSW_PCE_IP_V6) { pce_dasa_msb_t mtbl; pce_dasa_lsb_t ltbl; int j; memset(&mtbl, 0, sizeof(pce_dasa_msb_t)); memset(<bl, 0, sizeof(pce_dasa_lsb_t)); /* First, search for DIP in the DA/SA table (DIP MSB) */ for (i = 0, j = 7; i < 4; i++, j -= 2) { mtbl.imsb[j-1] = (parm->pattern.nSrcIP.nIPv6[i] & 0xFF); mtbl.imsb[j] = ((parm->pattern.nSrcIP.nIPv6[i] >> 8) & 0xFF); } if (gswdev->gipver == LTQ_GSWIP_3_0) { mtbl.nmask = (u16)((parm->pattern.nSrcIP_Mask >> 16) & 0xFFFF); for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if ((((parm->pattern.nSrcIP_Mask >> ((i * 4) + 16)) & 0xF) >> j) & 0x1) mtbl.mask[i] |= (0xF << (j*4)); } } } else { mtbl.mask[0] = (u16)((parm->pattern.nSrcIP_Mask >> 16) & 0xFFFF); } mtbl.valid = 1; tindex = pce_dasa_msb_tbl_write(cdev, &pthandle->pce_sub_tbl, &mtbl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->sip_msb_idx = (u16)tindex; /* First, search for DIP in the DA/SA table (DIP LSB) */ for (i = 0, j = 7; i < 4; i++, j -= 2) { ltbl.ilsb[j-1] = (parm->pattern.nSrcIP.nIPv6[i+4] & 0xFF); ltbl.ilsb[j] = ((parm->pattern.nSrcIP.nIPv6[i+4] >> 8) & 0xFF); } if (gswdev->gipver == LTQ_GSWIP_3_0) { ltbl.nmask = (u16)(parm->pattern.nSrcIP_Mask & 0xFFFF); for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if ((((parm->pattern.nSrcIP_Mask >> (i * 4)) & 0xF) >> j) & 0x1) ltbl.mask[i] |= (0xF << (j*4)); } } } else { ltbl.mask[0] = (u16)(parm->pattern.nSrcIP_Mask & 0xFFFF); } ltbl.valid = 1; tindex = pce_dasa_lsb_tbl_write(cdev, &pthandle->pce_sub_tbl, <bl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->sip_lsb_idx = (u16)tindex; } else if (parm->pattern.eSrcIP_Select == GSW_PCE_IP_V4) { /* SIP LSB used */ pce_dasa_lsb_t ltbl; memset(<bl, 0, sizeof(pce_dasa_lsb_t)); /* Second, search for SIP in the DA/SA table (SIP LSB) */ for (i = 0; i < 4; i++) ltbl.ilsb[i] = ((parm->pattern.nSrcIP.nIPv4 >> (i * 8)) & 0xFF); if (gswdev->gipver == LTQ_GSWIP_3_0) { int j; ltbl.nmask = (u16)(parm->pattern.nSrcIP_Mask) & 0xFFFF; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if ((((parm->pattern.nSrcIP_Mask >> (i * 4)) & 0xF) >> j) & 0x1) ltbl.mask[i] |= (0xF << (j*4)); } } } else { /* DIP LSB Nibble Mask */ ltbl.mask[0] = (u16)(parm->pattern.nSrcIP_Mask | 0xFF00) & 0xFFFF; } ltbl.valid = 1; tindex = pce_dasa_lsb_tbl_write(cdev, &pthandle->pce_sub_tbl, <bl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->sip_lsb_idx = (u16)tindex; } ptbl.key[2] |= (ptable->sip_msb_idx << 8); ptbl.key[2] |= ptable->sip_lsb_idx; if (gswdev->gipver == LTQ_GSWIP_3_0) { ptable->inr_dip_msb_idx = 0xFF; ptable->inr_dip_lsb_idx = 0xFF; /* Inner DIP MSB used */ if (parm->pattern.eInnerDstIP_Select == /*2*/GSW_PCE_IP_V6) { pce_dasa_msb_t mtbl; pce_dasa_lsb_t ltbl; int j; memset(&mtbl, 0, sizeof(pce_dasa_msb_t)); memset(<bl, 0, sizeof(pce_dasa_lsb_t)); /* First, search for DIP in the DA/SA table (DIP MSB) */ for (i = 0, j = 7; i < 4; i++, j -= 2) { mtbl.imsb[j-1] = (parm->pattern.nInnerDstIP.nIPv6[i] & 0xFF); mtbl.imsb[j] = ((parm->pattern.nInnerDstIP.nIPv6[i] >> 8) & 0xFF); } for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if ((((parm->pattern.nInnerDstIP_Mask >> ((i * 4) + 16)) & 0xF) >> j) & 0x1) mtbl.mask[i] |= (0xF << (j*4)); } } mtbl.nmask = (u16)((parm->pattern.nInnerDstIP_Mask >> 16) & 0xFFFF); mtbl.valid = 1; tindex = pce_dasa_msb_tbl_write(cdev, &pthandle->pce_sub_tbl, &mtbl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->inr_dip_msb_idx = tindex; /* First, search for DIP in the DA/SA table (DIP LSB) */ for (i = 0, j = 7; i < 4; i++, j -= 2) { ltbl.ilsb[j-1] = (parm->pattern.nInnerDstIP.nIPv6[i+4] & 0xFF); ltbl.ilsb[j] = ((parm->pattern.nInnerDstIP.nIPv6[i+4] >> 8) & 0xFF); } for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if ((((parm->pattern.nInnerDstIP_Mask >> (i * 4)) & 0xF) >> j) & 0x1) ltbl.mask[i] |= (0xF << (j*4)); } } ltbl.nmask = (u16)(parm->pattern.nInnerDstIP_Mask & 0xFFFF); ltbl.valid = 1; tindex = pce_dasa_lsb_tbl_write(cdev, &pthandle->pce_sub_tbl, <bl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->inr_dip_lsb_idx = (u16)tindex; } else if (parm->pattern.eInnerDstIP_Select == GSW_PCE_IP_V4) { /* DIP LSB used */ pce_dasa_lsb_t ltbl; int j; memset(<bl, 0, sizeof(pce_dasa_lsb_t)); /* First, search for DIP in the DA/SA table (DIP LSB) */ for (i = 0; i < 4; i++) ltbl.ilsb[i] = ((parm->pattern.nInnerDstIP.nIPv4 >> (i * 8)) & 0xFF); for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if ((((parm->pattern.nInnerDstIP_Mask >> (i * 4)) & 0xF) >> j) & 0x1) ltbl.mask[i] |= (0xF << (j*4)); } } ltbl.nmask = (u16)(parm->pattern.nInnerDstIP_Mask & 0xFFFF); ltbl.valid = 1; tindex = pce_dasa_lsb_tbl_write(cdev, &pthandle->pce_sub_tbl, <bl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->inr_dip_lsb_idx = (u16)tindex; } ptbl.key[11] |= (ptable->inr_dip_msb_idx << 8); ptbl.key[11] |= ptable->inr_dip_lsb_idx; /* Inner SIP MSB used */ ptable->inr_sip_msb_idx = 0xFF; ptable->inr_sip_lsb_idx = 0xFF; if (parm->pattern.eInnerSrcIP_Select == GSW_PCE_IP_V6) { pce_dasa_msb_t mtbl; pce_dasa_lsb_t ltbl; int j; memset(&mtbl, 0, sizeof(pce_dasa_msb_t)); memset(<bl, 0, sizeof(pce_dasa_lsb_t)); /* First, search for DIP in the DA/SA table (DIP MSB) */ for (i = 0, j = 7; i < 4; i++, j -= 2) { mtbl.imsb[j-1] = (parm->pattern.nInnerSrcIP.nIPv6[i] & 0xFF); mtbl.imsb[j] = ((parm->pattern.nInnerSrcIP.nIPv6[i] >> 8) & 0xFF); } for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if ((((parm->pattern.nInnerSrcIP_Mask >> ((i * 4) + 16)) & 0xF) >> j) & 0x1) mtbl.mask[i] |= (0xF << (j*4)); } } mtbl.nmask = (u16)((parm->pattern.nInnerSrcIP_Mask >> 16) & 0xFFFF); mtbl.valid = 1; tindex = pce_dasa_msb_tbl_write(cdev, &pthandle->pce_sub_tbl, &mtbl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->inr_sip_msb_idx = (u16)tindex; /* First, search for DIP in the DA/SA table (DIP LSB) */ for (i = 0, j = 7; i < 4; i++, j -= 2) { ltbl.ilsb[j-1] = (parm->pattern.nInnerSrcIP.nIPv6[i+4] & 0xFF); ltbl.ilsb[j] = ((parm->pattern.nInnerSrcIP.nIPv6[i+4] >> 8) & 0xFF); } for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if ((((parm->pattern.nInnerSrcIP_Mask >> (i * 4)) & 0xF) >> j) & 0x1) ltbl.mask[i] |= (0xF << (j*4)); } } ltbl.nmask = (u16)(parm->pattern.nInnerSrcIP_Mask & 0xFFFF); ltbl.valid = 1; tindex = pce_dasa_lsb_tbl_write(cdev, &pthandle->pce_sub_tbl, <bl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->inr_sip_lsb_idx = (u16)tindex; } else if (parm->pattern.eInnerSrcIP_Select == GSW_PCE_IP_V4) { /* SIP LSB used */ pce_dasa_lsb_t ltbl; int j; memset(<bl, 0, sizeof(pce_dasa_lsb_t)); /* Second, search for SIP in the DA/SA table (SIP LSB) */ for (i = 0; i < 4; i++) ltbl.ilsb[i] = ((parm->pattern.nInnerSrcIP.nIPv4 >> (i * 8)) & 0xFF); for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if ((((parm->pattern.nInnerSrcIP_Mask >> (i * 4)) & 0xF) >> j) & 0x1) ltbl.mask[i] |= (0xF << (j*4)); } } ltbl.nmask = (u16)(parm->pattern.nInnerSrcIP_Mask & 0xFFFF); ltbl.valid = 1; tindex = pce_dasa_lsb_tbl_write(cdev, &pthandle->pce_sub_tbl, <bl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->inr_sip_lsb_idx = (u16)tindex; } ptbl.key[10] |= (ptable->inr_sip_msb_idx << 8); ptbl.key[10] |= ptable->inr_sip_lsb_idx; } /* Ethertype used */ if (parm->pattern.bEtherTypeEnable == 1) { prtcol_tbl_t pctl_tbl; memset(&pctl_tbl, 0, sizeof(prtcol_tbl_t)); pctl_tbl.ethertype = parm->pattern.nEtherType; pctl_tbl.emask = parm->pattern.nEtherTypeMask; tindex = pce_ptcl_tbl_write(cdev, &pthandle->pce_sub_tbl, &pctl_tbl); if (tindex < 0) return tindex; ptable->ethertype_idx = (u16)tindex; } else { ptable->ethertype_idx = 0xFF; } ptbl.key[1] |= ptable->ethertype_idx; if (gswdev->gipver == LTQ_GSWIP_3_0) { /* PPP Protocol used */ if (parm->pattern.bPPP_ProtocolEnable == 1) { prtcol_tbl_t pctl_tbl; memset(&pctl_tbl, 0, sizeof(prtcol_tbl_t)); pctl_tbl.ethertype = parm->pattern.nPPP_Protocol; pctl_tbl.emask = parm->pattern.nPPP_ProtocolMask; tindex = pce_ptcl_tbl_write(cdev, &pthandle->pce_sub_tbl, &pctl_tbl); if (tindex < 0) return tindex; ptable->ppp_prot_idx = (u16)tindex; } else { ptable->ppp_prot_idx = 0xFF; } ptbl.key[9] |= ptable->ppp_prot_idx; } if ((parm->pattern.bProtocolEnable == 1) && (parm->pattern.bInnerProtocolEnable == 1)) { /* Inner and outer IP protocol used */ prtcol_tbl_t pctl_tbl; memset(&pctl_tbl, 0, sizeof(prtcol_tbl_t)); pctl_tbl.ethertype = (parm->pattern.nProtocol & 0xFF); pctl_tbl.ethertype |= ((parm->pattern.nInnerProtocol & 0xFF) << 8); pctl_tbl.emask = (parm->pattern.nProtocolMask & 0x3); pctl_tbl.emask |= ((parm->pattern.nInnerProtocolMask & 0x3) << 2); tindex = pce_ptcl_tbl_write(cdev, &pthandle->pce_sub_tbl, &pctl_tbl); if (tindex < 0) return tindex; ptable->ip_prot_idx = (u16)tindex; } else if (parm->pattern.bInnerProtocolEnable == 1) { /* Inner IP protocol used */ prtcol_tbl_t pctl_tbl; memset(&pctl_tbl, 0, sizeof(prtcol_tbl_t)); pctl_tbl.ethertype = (0xFF); pctl_tbl.ethertype |= ((parm->pattern.nInnerProtocol & 0xFF) << 8); pctl_tbl.emask = 0x3; pctl_tbl.emask |= ((parm->pattern.nInnerProtocolMask & 0x3) << 2); tindex = pce_ptcl_tbl_write(cdev, &pthandle->pce_sub_tbl, &pctl_tbl); if (tindex < 0) return tindex; ptable->ip_prot_idx = (u16)tindex; } else if (parm->pattern.bProtocolEnable == 1) { prtcol_tbl_t pctl_tbl; memset(&pctl_tbl, 0, sizeof(prtcol_tbl_t)); pctl_tbl.ethertype = (parm->pattern.nProtocol & 0xFF); pctl_tbl.ethertype |= (0xFF << 8); pctl_tbl.emask = (parm->pattern.nProtocolMask & 0x3); pctl_tbl.emask |= (0x3 << 2); tindex = pce_ptcl_tbl_write(cdev, &pthandle->pce_sub_tbl, &pctl_tbl); if (tindex < 0) return tindex; ptable->ip_prot_idx = (u16)tindex; } else { ptable->ip_prot_idx = 0xFF; } ptbl.key[1] |= (ptable->ip_prot_idx << 8); /* PPPoE used */ if (parm->pattern.bSessionIdEnable == 1) { pce_ppoe_tbl_t pppoe_tbl; pppoe_tbl.sess_id = parm->pattern.nSessionId; tindex = pce_tm_pppoe_tbl_write(cdev, &pthandle->pce_sub_tbl, (pce_ppoe_tbl_t *)parm); if (tindex < 0) return tindex; ptable->pppoe_idx = (u16)tindex; } else { ptable->pppoe_idx = 0x1F; } ptbl.key[7] |= (ptable->pppoe_idx << 8); /* VLAN used */ tindex = 0x7F; if (parm->pattern.bVid == 1) { tindex = pce_vid_index(cdev, &pthandle->pce_sub_tbl, parm->pattern.nVid); if (reg_val == 1) { /*ETC*/ if (tindex == 0x7F) tindex = act_vlan_id_create(cdev, parm->pattern.nVid, parm->pattern.bVidRange_Select, parm->pattern.nVidRange); } else { if (tindex == 0x7F) { pr_err("%s:%s:%d (Create VID before use it)\n", __FILE__, __func__, __LINE__); return -1; } } } ptable->vlan_idx = (u16)tindex; ptbl.key[0] &= ~(0xFF << 8); ptbl.key[0] |= (ptable->vlan_idx << 8); tindex = 0x7F; /* ETC */ if (reg_val == 1) { if (parm->pattern.bSLAN_Vid == 1) { tindex = pce_vid_index(cdev, &pthandle->pce_sub_tbl, parm->pattern.nSLAN_Vid); if (tindex == 0x7F) tindex = act_vlan_id_create(cdev, parm->pattern.nSLAN_Vid, 0, 0); } ptable->svlan_idx = (u16)tindex; ptbl.key[8] &= ~(0xFF << 8); ptbl.key[8] |= (ptable->svlan_idx << 8); } if (gswdev->gipver == LTQ_GSWIP_3_0) { /* Sub-Interface ID */ if (parm->pattern.bSubIfIdEnable == 1) ptbl.key[14] |= (parm->pattern.nSubIfId & 0xF); else ptbl.key[14] |= 0x1F; if (parm->pattern.bPortId_Exclude == 1) ptbl.key[14] |= (1 << 7); if (parm->pattern.bVid_Exclude == 1) ptbl.key[14] |= (1 << 8); if (parm->pattern.bEtherType_Exclude == 1) ptbl.key[14] |= (1 << 9); if (parm->pattern.bProtocol_Exclude == 1) ptbl.key[14] |= (1 << 10); if (parm->pattern.bSrcIP_Exclude == 1) ptbl.key[14] |= (1 << 11); if (parm->pattern.bDstIP_Exclude == 1) ptbl.key[14] |= (1 << 12); /* source port */ if (parm->pattern.bAppMSB_Exclude == 1) ptbl.key[14] |= (1 << 13); if (parm->pattern.bAppLSB_Exclude == 1) ptbl.key[14] |= (1 << 14); if (parm->pattern.bSrcMAC_Exclude == 1) ptbl.key[14] |= (1 << 15); if (parm->pattern.bDstMAC_Exclude == 1) ptbl.key[15] |= (1 << 0); if (parm->pattern.bCTAG_PCP_DEI_Exclude == 1) ptbl.key[15] |= (1 << 1); if (parm->pattern.bSTAG_PCP_DEI_Exclude == 1) ptbl.key[15] |= (1 << 2); if (parm->pattern.bDSCP_Exclude == 1) ptbl.key[15] |= (1 << 3); if (parm->pattern.bPktLng_Exclude == 1) ptbl.key[15] |= (1 << 4); if (parm->pattern.bSessionId_Exclude == 1) ptbl.key[15] |= (1 << 5); if (parm->pattern.bSLANVid_Exclude == 1) ptbl.key[15] |= (1 << 6); if (parm->pattern.bPPP_Protocol_Exclude == 1) ptbl.key[15] |= (1 << 7); if (parm->pattern.bInnerDSCP_Exclude == 1) ptbl.key[15] |= (1 << 8); if (parm->pattern.bInnerSrcIP_Exclude == 1) ptbl.key[15] |= (1 << 9); if (parm->pattern.bInnerDstIP_Exclude == 1) ptbl.key[15] |= (1 << 10); if (parm->pattern.bParserFlagLSB_Exclude == 1) ptbl.key[15] |= (1 << 11); if (parm->pattern.bParserFlagMSB_Exclude == 1) ptbl.key[15] |= (1 << 12); if (parm->pattern.bPayload1_Exclude == 1) ptbl.key[15] |= (1 << 13); if (parm->pattern.bPayload2_Exclude == 1) ptbl.key[15] |= (1 << 14); if (parm->pattern.bSubIfId_Exclude == 1) ptbl.key[15] |= (1 << 15); } paction = &(pthandle->pce_act[idx]); memcpy(paction, &parm->action, sizeof(GSW_PCE_action_t)); /* Fill the Action parameter into the ptbl.val[x]*/ /**** Action "Forwarding" Group. Port map action enable. This port */ /*forwarding configuration is ignored in case the action "IGMP Snooping"*/ /* is enabled via the parameter 'nSnoopingTypeAction'. *****/ if (paction->ePortMapAction != GSW_PCE_ACTION_PORTMAP_DISABLE) { if (paction->eSnoopingTypeAction == GSW_PCE_ACTION_IGMP_SNOOP_DISABLE) { ptbl.val[0] = 1; ptbl.val[4] |= (0x3 << 2); switch (paction->ePortMapAction) { case GSW_PCE_ACTION_PORTMAP_REGULAR: ptbl.val[4] &= ~(0x3 << 2); break; case GSW_PCE_ACTION_PORTMAP_DISCARD: ptbl.val[1] = 0; break; case GSW_PCE_ACTION_PORTMAP_CPU: /* ptbl.val[1] = 0x40; */ /* Port 6 */ ptbl.val[1] = (paction->nForwardPortMap & 0xFFFF); ptbl.val[4] &= ~(0x3 << 2); ptbl.val[4] |= (0x1 << 2); break; case GSW_PCE_ACTION_PORTMAP_ALTERNATIVE: ptbl.val[1] = (paction->nForwardPortMap & 0xFFFF); break; /* To fix compilation warnings*/ case GSW_PCE_ACTION_PORTMAP_DISABLE: case GSW_PCE_ACTION_PORTMAP_MULTICAST_ROUTER: case GSW_PCE_ACTION_PORTMAP_MULTICAST_HW_TABLE: case GSW_PCE_ACTION_PORTMAP_ALTERNATIVE_VLAN: case GSW_PCE_ACTION_PORTMAP_ALTERNATIVE_STAG_VLAN: break; } } else { switch (paction->eSnoopingTypeAction) { case GSW_PCE_ACTION_IGMP_SNOOP_REPORT: case GSW_PCE_ACTION_IGMP_SNOOP_LEAVE: ptbl.val[0] = 1; ptbl.val[4] &= ~(0x3 << 2); /* Forwarding Action enabled. Select Multicast Router Port-Map */ /* Multicast router portmap */ ptbl.val[4] |= (0x1 << 2); break; default: ptbl.val[0] = 1; ptbl.val[4] &= ~(0x3 << 2); /* default port map */ ptbl.val[4] |= (0x0 << 2); break; } } } else { ptbl.val[0] = 0; ptbl.val[1] = 0xFFFF; ptbl.val[4] &= ~(0x3 << 2); } /* Action "Flow ID". This flow table action and the 'bFlowID_Action' */ /*action can be used exclusively. */ if (paction->bFlowID_Action != 0) { if (paction->ePortMapAction == GSW_PCE_ACTION_PORTMAP_DISABLE) { /* enable Flow ID action */ ptbl.val[4] |= (0x1 << 4); ptbl.val[1] = paction->nFlowID & 0xFFFF; } else { pr_err("%s:%s:%d (pmap & FlowID can be used exclusively)\n", __FILE__, __func__, __LINE__); return -1; } } tindex = 0x7F; /** Action "VLAN" Group. VLAN action enable */ ptbl.val[2] = 0; /* for GSW_PCE_ACTION_VLAN_REGULAR also*/ ptbl.val[0] &= ~(1 << 13); if (paction->eVLAN_Action != GSW_PCE_ACTION_VLAN_DISABLE) { ptbl.val[0] |= (1 << 1); if (paction->eVLAN_Action == GSW_PCE_ACTION_VLAN_ALTERNATIVE) { if (reg_val == 1) { /*ETC */ ptbl.val[5] |= ((paction->nVLAN_Id & 0xFFF) << 4); ptbl.val[2] |= ((paction->nFId & 0xFF) << 8); /* alternative CTAG VLAN ID and FID */ ptbl.val[5] |= (1 << 3); ptbl.val[0] |= (1 << 13); } else { avlan_tbl_t vatable; memset(&vatable, 0, sizeof(avlan_tbl_t)); vatable.vid = paction->nVLAN_Id; tindex = pce_vlan_id_fid_index(cdev, &pthandle->pce_sub_tbl, &vatable); if (tindex != 0x7F) { ptbl.val[2] = (tindex & 0xFF); ptbl.val[2] |= ((vatable.fid & 0xFF) << 8); ptbl.val[0] |= (1 << 13); } } } } /* ETC */ /** Action "SVLAN" Group. SVLAN action enable */ if (reg_val == 1) { ptbl.val[6] = 0; if (paction->eSVLAN_Action != GSW_PCE_ACTION_VLAN_DISABLE) { ptbl.val[0] |= (1 << 1); /* default CTAG VLAN ID and FID */ ptbl.val[6] &= ~(1 << 3); if (paction->eSVLAN_Action == GSW_PCE_ACTION_VLAN_ALTERNATIVE) { ptbl.val[6] |= ((paction->nSVLAN_Id & 0xFFF) << 4); ptbl.val[0] |= (1 << 13); ptbl.val[6] |= (1 << 3); } } } /** Action "Traffic Class" Group. Traffic class action enable */ if (paction->eTrafficClassAction != GSW_PCE_ACTION_TRAFFIC_CLASS_DISABLE) { ptbl.val[0] |= (1 << 2); switch (paction->eTrafficClassAction) { case GSW_PCE_ACTION_TRAFFIC_CLASS_REGULAR: ptbl.val[0] &= ~(1 << 14); break; case GSW_PCE_ACTION_TRAFFIC_CLASS_ALTERNATIVE: ptbl.val[0] |= (1 << 14); ptbl.val[3] &= ~(0xF << 8); ptbl.val[3] |= (paction->nTrafficClassAlternate & 0xF) << 8; break; case GSW_PCE_ACTION_TRAFFIC_CLASS_DISABLE: break; } } else { ptbl.val[0] &= ~((1 << 2) | (1 << 14)); ptbl.val[3] |= (0xF << 8); } /** Action "Remarking" Group. Remarking action enable */ if (paction->bRemarkAction != 0) ptbl.val[0] |= (1 << 3); else ptbl.val[0] &= ~(1 << 3); /** Action "Cross VLAN" Group. Cross VLAN action enable */ if (paction->eVLAN_CrossAction != GSW_PCE_ACTION_CROSS_VLAN_DISABLE) { ptbl.val[0] |= (1 << 4); if (paction->eVLAN_CrossAction == GSW_PCE_ACTION_CROSS_VLAN_REGULAR) ptbl.val[3] &= ~(0 << 15); else ptbl.val[3] |= (1 << 15); } else { ptbl.val[0] &= ~(1 << 4); ptbl.val[3] &= ~(0 << 15); } /** Action "Cross State" Group. Cross state action control and enable */ if (paction->eCrossStateAction != GSW_PCE_ACTION_CROSS_STATE_DISABLE) { ptbl.val[0] |= (1 << 5); if (paction->eCrossStateAction == GSW_PCE_ACTION_CROSS_STATE_CROSS) ptbl.val[4] |= (1 << 13); else ptbl.val[4] &= ~(1 << 13); } else { ptbl.val[4] &= ~(1 << 13); ptbl.val[0] &= ~(1 << 5); } /* Action "Critical Frames" Group. Critical Frame action control and enable*/ if (paction->eCritFrameAction != GSW_PCE_ACTION_CRITICAL_FRAME_DISABLE) { ptbl.val[0] |= (1 << 6); if (paction->eCritFrameAction == GSW_PCE_ACTION_CRITICAL_FRAME_CRITICAL) ptbl.val[4] |= (1 << 14); else ptbl.val[4] &= ~(1 << 14); } else { ptbl.val[0] &= ~(1 << 6); ptbl.val[4] &= ~(1 << 14); } /** Action "Timestamp" Group. Time stamp action control and enable */ if (paction->eTimestampAction != GSW_PCE_ACTION_TIMESTAMP_DISABLE) { ptbl.val[0] |= (1 << 7); if (paction->eTimestampAction == GSW_PCE_ACTION_TIMESTAMP_STORED) ptbl.val[4] |= (1 << 15); else ptbl.val[4] &= ~(1 << 15); } else { ptbl.val[0] &= ~(1 << 7); ptbl.val[4] &= ~(1 << 15); } /** Action "Interrupt" Group. Interrupt action generate and enable */ if (paction->eIrqAction != GSW_PCE_ACTION_IRQ_DISABLE) { ptbl.val[0] |= (1 << 8); if (paction->eIrqAction == GSW_PCE_ACTION_IRQ_EVENT) ptbl.val[0] |= (1 << 15); else ptbl.val[0] &= ~(1 << 15); } else { ptbl.val[0] &= ~((1 << 8) | (1 << 15)); } /** Action "Learning" Group. Learning action control and enable */ if (paction->eLearningAction != GSW_PCE_ACTION_LEARNING_DISABLE) { ptbl.val[0] |= (1 << 9); /* Todo: Learning Rule need to be check */ switch (paction->eLearningAction) { case GSW_PCE_ACTION_LEARNING_REGULAR: ptbl.val[4] &= ~0x3; break; case GSW_PCE_ACTION_LEARNING_FORCE_NOT: ptbl.val[4] = (ptbl.val[4] & ~0x3) | 0x2; break; case GSW_PCE_ACTION_LEARNING_FORCE: ptbl.val[4] |= 0x3; break; case GSW_PCE_ACTION_LEARNING_DISABLE: break; } } else { ptbl.val[0] &= ~(1 << 9); ptbl.val[4] &= ~0x3; } /** Action "IGMP Snooping" Group. */ if (paction->eSnoopingTypeAction != GSW_PCE_ACTION_IGMP_SNOOP_DISABLE) { ptbl.val[0] |= (1 << 10); ptbl.val[4] &= ~(0x7 << 5); switch (paction->eSnoopingTypeAction) { case GSW_PCE_ACTION_IGMP_SNOOP_REGULAR: ptbl.val[4] |= (0 << 5); break; case GSW_PCE_ACTION_IGMP_SNOOP_REPORT: ptbl.val[4] |= (1 << 5); break; case GSW_PCE_ACTION_IGMP_SNOOP_LEAVE: ptbl.val[4] |= (2 << 5); break; case GSW_PCE_ACTION_IGMP_SNOOP_AD: ptbl.val[4] |= (3 << 5); break; case GSW_PCE_ACTION_IGMP_SNOOP_QUERY: ptbl.val[4] |= (4 << 5); break; case GSW_PCE_ACTION_IGMP_SNOOP_QUERY_GROUP: ptbl.val[4] |= (5 << 5); break; case GSW_PCE_ACTION_IGMP_SNOOP_QUERY_NO_ROUTER: ptbl.val[4] |= (6 << 5); break; case GSW_PCE_ACTION_IGMP_SNOOP_DISABLE: break; } } else { ptbl.val[0] &= ~(1 << 10); ptbl.val[4] &= ~(0x7 << 5); } /** Action "Meter" Group. Meter action control and enable. */ if (paction->eMeterAction != GSW_PCE_ACTION_METER_DISABLE) { ptbl.val[0] |= (1 << 11); ptbl.val[3] = (paction->nMeterId & 0x1F); switch (paction->eMeterAction) { case GSW_PCE_ACTION_METER_REGULAR: ptbl.val[3] |= 0 << 6; break; case GSW_PCE_ACTION_METER_1: ptbl.val[3] |= 1 << 6; break; /* case GSW_PCE_ACTION_METER_2: */ /* ptbl.val[3] |= 2 << 6; */ /* break; */ case GSW_PCE_ACTION_METER_1_2: ptbl.val[3] |= 3 << 6; break; case GSW_PCE_ACTION_METER_DISABLE: break; } } else { ptbl.val[0] &= ~(1 << 11); ptbl.val[3] |= 0x1F; } /** Action "RMON" Group. RMON action enable */ if (paction->bRMON_Action != 0) { ptbl.val[0] |= (1 << 12); ptbl.val[4] &= ~(0x1F << 8); if (paction->nRMON_Id < 24) { /*RMON_ID will support from 1 to 24 */ ptbl.val[4] |= ((paction->nRMON_Id + 1) << 8); } else { return -1; } } else { ptbl.val[0] &= ~(1 << 12); ptbl.val[4] &= ~(0x1F << 8); } ptbl.val[3] |= (0x7 << 12); if (paction->bRemarkDSCP == 1) ptbl.val[3] &= ~(1 << 12); if (paction->bRemarkClass == 1) ptbl.val[3] &= ~(1 << 13); if (paction->bRemarkPCP == 1) ptbl.val[3] &= ~(1 << 14); /* ETC */ if (paction->bRemarkSTAG_PCP == 1) ptbl.val[6] &= ~(1 << 1); else ptbl.val[6] |= (1 << 1); if (paction->bRemarkSTAG_DEI == 1) ptbl.val[6] &= ~(1 << 2); else ptbl.val[6] |= (1 << 2); if (paction->bPortBitMapMuxControl == 1) ptbl.val[6] |= (1 << 0); else ptbl.val[6] &= ~(1 << 0); /* Trunking action enable */ if (paction->bPortTrunkAction == 1) ptbl.val[5] |= (1 << 0); else ptbl.val[5] &= ~(1 << 0); /* Port Link Selection control */ if (paction->bPortLinkSelection == 1) ptbl.val[5] |= (1 << 1); else ptbl.val[5] &= ~(1 << 1); /* CVLAN Ignore control */ if (paction->bCVLAN_Ignore_Control == 1) { ptbl.val[5] |= (1 << 2); ptbl.val[0] |= (1 << 1); } else { ptbl.val[5] &= ~(1 << 2); } if (gswdev->gipver == LTQ_GSWIP_3_0) { if (paction->ePortFilterType_Action != GSW_PCE_PORT_FILTER_ACTION_UNUSED) { if (paction->ePortMapAction == GSW_PCE_ACTION_PORTMAP_DISABLE) { ptbl.val[7] &= ~(0x3F << 1); switch (paction->ePortFilterType_Action) { case GSW_PCE_PORT_FILTER_ACTION_1: ptbl.val[7] |= (1 << 1); break; case GSW_PCE_PORT_FILTER_ACTION_2: ptbl.val[7] |= (1 << 2); break; case GSW_PCE_PORT_FILTER_ACTION_3: ptbl.val[7] |= (1 << 3); break; case GSW_PCE_PORT_FILTER_ACTION_4: ptbl.val[7] |= (1 << 4); break; case GSW_PCE_PORT_FILTER_ACTION_5: ptbl.val[7] |= (1 << 5); break; case GSW_PCE_PORT_FILTER_ACTION_6: ptbl.val[7] |= (1 << 6); break; case GSW_PCE_PORT_FILTER_ACTION_UNUSED: break; } ptbl.val[1] = paction->nForwardPortMap & 0xFFFF; } else { ptbl.val[7] &= ~(0x3F << 1); /* return -1;*/ } } if (paction->eProcessPath_Action != GSW_PCE_PROCESSING_PATH_UNUSED) { ptbl.val[8] &= ~(7 << 0); ptbl.val[8] |= (1 << 0); switch (paction->eProcessPath_Action) { case GSW_PCE_PROCESSING_PATH_1: ptbl.val[8] |= (1 << 1); break; case GSW_PCE_PROCESSING_PATH_2: ptbl.val[8] |= (1 << 2); break; case GSW_PCE_PROCESSING_PATH_BOTH: ptbl.val[8] |= (3 << 1); break; case GSW_PCE_PROCESSING_PATH_UNUSED: break; } } else { ptbl.val[8] &= ~(7 << 0); ptbl.val[8] &= ~(1 << 0); } if (gswdev->sdev == LTQ_FLOW_DEV_INT_R) { if (paction->bRoutExtId_Action == 1) ptbl.val[9] |= ((paction->nRoutExtId & 0xFF) << 8); else ptbl.val[9] |= (0xFF << 8); if (paction->bRtDstPortMaskCmp_Action == 1) ptbl.val[9] &= ~(1 << 6); else ptbl.val[9] |= (1 << 6); if (paction->bRtSrcPortMaskCmp_Action == 1) ptbl.val[9] &= ~(1 << 5); else ptbl.val[9] |= (1 << 5); if (paction->bRtDstIpMaskCmp_Action == 1) ptbl.val[9] &= ~(1 << 4); else ptbl.val[9] |= (1 << 4); if (paction->bRtSrcIpMaskCmp_Action == 1) ptbl.val[9] &= ~(1 << 3); else ptbl.val[9] |= (1 << 3); if (paction->bRtInnerIPasKey_Action == 1) ptbl.val[9] |= (1 << 2); else ptbl.val[9] &= ~(1 << 2); if (paction->bRtAccelEna_Action == 1) ptbl.val[9] |= (1 << 1); else ptbl.val[9] &= ~(1 << 1); if (paction->bRtCtrlEna_Action == 1) ptbl.val[9] |= (1 << 0); else ptbl.val[9] &= ~(1 << 0); } } ptbl.pcindex = idx; ptbl.table = PCE_TFLOW_INDEX; ptbl.valid = 1; gsw_pce_table_write(cdev, &ptbl); return 0; }