Lines Matching +full:sparx5 +full:- +full:switch

1 // SPDX-License-Identifier: GPL-2.0+
2 /* Microchip Sparx5 Switch driver VCAP implementation
6 * The Sparx5 Chip Register Model can be browsed at this location:
7 * https://github.com/microchip-ung/sparx-5_reginfo
66 .vtype = VCAP_TYPE_IS0, /* CLM-0 */
72 .last_cid = SPARX5_VCAP_CID_IS0_L2 - 1,
73 .blockno = 8, /* Maps block 8-9 */
78 .vtype = VCAP_TYPE_IS0, /* CLM-1 */
84 .last_cid = SPARX5_VCAP_CID_IS0_L4 - 1,
85 .blockno = 6, /* Maps block 6-7 */
90 .vtype = VCAP_TYPE_IS0, /* CLM-2 */
97 .blockno = 4, /* Maps block 4-5 */
102 .vtype = VCAP_TYPE_IS2, /* IS2-0 */
108 .last_cid = SPARX5_VCAP_CID_IS2_L2 - 1,
109 .blockno = 0, /* Maps block 0-1 */
114 .vtype = VCAP_TYPE_IS2, /* IS2-1 */
121 .blockno = 2, /* Maps block 2-3 */
168 static void sparx5_vcap_type_err(struct sparx5 *sparx5, in sparx5_vcap_type_err() argument
173 fname, sparx5_vcaps[admin->vtype].name); in sparx5_vcap_type_err()
177 static void sparx5_vcap_wait_super_update(struct sparx5 *sparx5) in sparx5_vcap_wait_super_update() argument
183 false, sparx5, VCAP_SUPER_CTRL); in sparx5_vcap_wait_super_update()
187 static void sparx5_vcap_wait_es0_update(struct sparx5 *sparx5) in sparx5_vcap_wait_es0_update() argument
193 false, sparx5, VCAP_ES0_CTRL); in sparx5_vcap_wait_es0_update()
197 static void sparx5_vcap_wait_es2_update(struct sparx5 *sparx5) in sparx5_vcap_wait_es2_update() argument
203 false, sparx5, VCAP_ES2_CTRL); in sparx5_vcap_wait_es2_update()
207 static void _sparx5_vcap_range_init(struct sparx5 *sparx5, in _sparx5_vcap_range_init() argument
211 u32 size = count - 1; in _sparx5_vcap_range_init()
213 switch (admin->vtype) { in _sparx5_vcap_range_init()
218 sparx5, VCAP_SUPER_CFG); in _sparx5_vcap_range_init()
226 sparx5, VCAP_SUPER_CTRL); in _sparx5_vcap_range_init()
227 sparx5_vcap_wait_super_update(sparx5); in _sparx5_vcap_range_init()
232 sparx5, VCAP_ES0_CFG); in _sparx5_vcap_range_init()
240 sparx5, VCAP_ES0_CTRL); in _sparx5_vcap_range_init()
241 sparx5_vcap_wait_es0_update(sparx5); in _sparx5_vcap_range_init()
246 sparx5, VCAP_ES2_CFG); in _sparx5_vcap_range_init()
254 sparx5, VCAP_ES2_CTRL); in _sparx5_vcap_range_init()
255 sparx5_vcap_wait_es2_update(sparx5); in _sparx5_vcap_range_init()
258 sparx5_vcap_type_err(sparx5, admin, __func__); in _sparx5_vcap_range_init()
264 static void sparx5_vcap_block_init(struct sparx5 *sparx5, in sparx5_vcap_block_init() argument
267 _sparx5_vcap_range_init(sparx5, admin, admin->first_valid_addr, in sparx5_vcap_block_init()
268 admin->last_valid_addr - in sparx5_vcap_block_init()
269 admin->first_valid_addr); in sparx5_vcap_block_init()
272 /* Get the keyset name from the sparx5 VCAP model */
278 return vcap_keyset_name(port->sparx5->vcap_ctrl, keyset); in sparx5_vcap_keyset_name()
284 return (rule->vcap_chain_id >= SPARX5_VCAP_CID_IS0_L0 && in sparx5_vcap_is0_is_first_chain()
285 rule->vcap_chain_id < SPARX5_VCAP_CID_IS0_L1) || in sparx5_vcap_is0_is_first_chain()
286 ((rule->vcap_chain_id >= SPARX5_VCAP_CID_IS0_L2 && in sparx5_vcap_is0_is_first_chain()
287 rule->vcap_chain_id < SPARX5_VCAP_CID_IS0_L3)) || in sparx5_vcap_is0_is_first_chain()
288 ((rule->vcap_chain_id >= SPARX5_VCAP_CID_IS0_L4 && in sparx5_vcap_is0_is_first_chain()
289 rule->vcap_chain_id < SPARX5_VCAP_CID_IS0_L5)); in sparx5_vcap_is0_is_first_chain()
295 return (rule->vcap_chain_id >= SPARX5_VCAP_CID_IS2_L0 && in sparx5_vcap_is2_is_first_chain()
296 rule->vcap_chain_id < SPARX5_VCAP_CID_IS2_L1) || in sparx5_vcap_is2_is_first_chain()
297 ((rule->vcap_chain_id >= SPARX5_VCAP_CID_IS2_L2 && in sparx5_vcap_is2_is_first_chain()
298 rule->vcap_chain_id < SPARX5_VCAP_CID_IS2_L3)); in sparx5_vcap_is2_is_first_chain()
303 return (rule->vcap_chain_id >= SPARX5_VCAP_CID_ES2_L0 && in sparx5_vcap_es2_is_first_chain()
304 rule->vcap_chain_id < SPARX5_VCAP_CID_ES2_L1); in sparx5_vcap_es2_is_first_chain()
315 range = port->portno / BITS_PER_TYPE(u32); in sparx5_vcap_add_ingress_range_port_mask()
316 /* Port bit set to match-any */ in sparx5_vcap_add_ingress_range_port_mask()
317 port_mask = ~BIT(port->portno % BITS_PER_TYPE(u32)); in sparx5_vcap_add_ingress_range_port_mask()
331 /* Port bit set to match-any */ in sparx5_vcap_add_wide_port_mask()
334 range = port->portno / BITS_PER_BYTE; in sparx5_vcap_add_wide_port_mask()
335 port_mask.mask[range] = ~BIT(port->portno % BITS_PER_BYTE); in sparx5_vcap_add_wide_port_mask()
347 * 0-2: Physical/Logical egress port number 0-31, 32–63, 64. in sparx5_vcap_add_egress_range_port_mask()
348 * 3-5: Virtual Interface Number 0-31, 32-63, 64. in sparx5_vcap_add_egress_range_port_mask()
349 * 6: CPU queue Number 0-7. in sparx5_vcap_add_egress_range_port_mask()
351 * Use physical/logical port ranges (0-2) in sparx5_vcap_add_egress_range_port_mask()
353 range = port->portno / BITS_PER_TYPE(u32); in sparx5_vcap_add_egress_range_port_mask()
354 /* Port bit set to match-any */ in sparx5_vcap_add_egress_range_port_mask()
355 port_mask = ~BIT(port->portno % BITS_PER_TYPE(u32)); in sparx5_vcap_add_egress_range_port_mask()
410 switch (ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL_GET(value)) { in sparx5_vcap_is0_get_port_etype_keysets()
427 struct sparx5 *sparx5 = port->sparx5; in sparx5_vcap_is0_get_port_keysets() local
428 int portno = port->portno; in sparx5_vcap_is0_get_port_keysets()
431 value = spx5_rd(sparx5, ANA_CL_ADV_CL_CFG(portno, lookup)); in sparx5_vcap_is0_get_port_keysets()
438 switch (ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL_GET(value)) { in sparx5_vcap_is0_get_port_keysets()
454 switch (ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL_GET(value)) { in sparx5_vcap_is0_get_port_keysets()
481 struct sparx5 *sparx5 = port->sparx5; in sparx5_vcap_is2_get_port_keysets() local
482 int portno = port->portno; in sparx5_vcap_is2_get_port_keysets()
485 value = spx5_rd(sparx5, ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup)); in sparx5_vcap_is2_get_port_keysets()
489 switch (ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_GET(value)) { in sparx5_vcap_is2_get_port_keysets()
500 switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL_GET(value)) { in sparx5_vcap_is2_get_port_keysets()
513 switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL_GET(value)) { in sparx5_vcap_is2_get_port_keysets()
528 switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_GET(value)) { in sparx5_vcap_is2_get_port_keysets()
544 switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL_GET(value)) { in sparx5_vcap_is2_get_port_keysets()
566 switch (ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL_GET(value)) { in sparx5_vcap_is2_get_port_keysets()
568 /* IS2 non-classified frames generate MAC_ETYPE */ in sparx5_vcap_is2_get_port_keysets()
581 switch (EACL_VCAP_ES2_KEY_SEL_IP4_KEY_SEL_GET(value)) { in sparx5_vcap_es2_get_port_ipv4_keysets()
610 struct sparx5 *sparx5 = port->sparx5; in sparx5_vcap_es0_get_port_keysets() local
611 int portno = port->portno; in sparx5_vcap_es0_get_port_keysets()
614 value = spx5_rd(sparx5, REW_RTAG_ETAG_CTRL(portno)); in sparx5_vcap_es0_get_port_keysets()
617 switch (REW_RTAG_ETAG_CTRL_ES0_ISDX_KEY_ENA_GET(value)) { in sparx5_vcap_es0_get_port_keysets()
635 struct sparx5 *sparx5 = port->sparx5; in sparx5_vcap_es2_get_port_keysets() local
636 int portno = port->portno; in sparx5_vcap_es2_get_port_keysets()
639 value = spx5_rd(sparx5, EACL_VCAP_ES2_KEY_SEL(portno, lookup)); in sparx5_vcap_es2_get_port_keysets()
643 switch (EACL_VCAP_ES2_KEY_SEL_ARP_KEY_SEL_GET(value)) { in sparx5_vcap_es2_get_port_keysets()
657 switch (EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL_GET(value)) { in sparx5_vcap_es2_get_port_keysets()
698 int lookup, err = -EINVAL; in sparx5_vcap_get_port_keyset()
701 switch (admin->vtype) { in sparx5_vcap_get_port_keyset()
722 sparx5_vcap_type_err(port->sparx5, admin, __func__); in sparx5_vcap_get_port_keyset()
734 switch (admin->vtype) { in sparx5_vcap_is_known_etype()
771 if (!kslist || kslist->cnt == 0) in sparx5_vcap_validate_keyset()
778 switch (admin->vtype) { in sparx5_vcap_validate_keyset()
780 lookup = sparx5_vcap_is0_cid_to_lookup(rule->vcap_chain_id); in sparx5_vcap_validate_keyset()
785 lookup = sparx5_vcap_is2_cid_to_lookup(rule->vcap_chain_id); in sparx5_vcap_validate_keyset()
793 lookup = sparx5_vcap_es2_cid_to_lookup(rule->vcap_chain_id); in sparx5_vcap_validate_keyset()
799 sparx5_vcap_type_err(port->sparx5, admin, __func__); in sparx5_vcap_validate_keyset()
804 for (idx = 0; idx < kslist->cnt; ++idx) in sparx5_vcap_validate_keyset()
806 if (kslist->keysets[idx] == keysets[jdx]) in sparx5_vcap_validate_keyset()
807 return kslist->keysets[idx]; in sparx5_vcap_validate_keyset()
811 sparx5_vcap_keyset_name(ndev, kslist->keysets[0])); in sparx5_vcap_validate_keyset()
813 return -ENOENT; in sparx5_vcap_validate_keyset()
825 if (field && field->width == SPX5_PORTS) in sparx5_vcap_ingress_add_default_fields()
827 else if (field && field->width == BITS_PER_TYPE(u32)) in sparx5_vcap_ingress_add_default_fields()
832 sparx5_vcap_keyset_name(ndev, rule->keyset)); in sparx5_vcap_ingress_add_default_fields()
834 if (admin->vtype == VCAP_TYPE_IS0) in sparx5_vcap_ingress_add_default_fields()
854 vcap_rule_add_key_u32(rule, VCAP_KF_IF_EGR_PORT_NO, port->portno, ~0); in sparx5_vcap_es0_add_default_fields()
891 switch (admin->vtype) { in sparx5_vcap_add_default_fields()
904 sparx5_vcap_type_err(port->sparx5, admin, __func__); in sparx5_vcap_add_default_fields()
912 memset(admin->cache.keystream, 0, STREAMSIZE); in sparx5_vcap_cache_erase()
913 memset(admin->cache.maskstream, 0, STREAMSIZE); in sparx5_vcap_cache_erase()
914 memset(admin->cache.actionstream, 0, STREAMSIZE); in sparx5_vcap_cache_erase()
915 memset(&admin->cache.counter, 0, sizeof(admin->cache.counter)); in sparx5_vcap_cache_erase()
918 static void sparx5_vcap_is0_cache_write(struct sparx5 *sparx5, in sparx5_vcap_is0_cache_write() argument
927 keystr = &admin->cache.keystream[start]; in sparx5_vcap_is0_cache_write()
928 mskstr = &admin->cache.maskstream[start]; in sparx5_vcap_is0_cache_write()
929 actstr = &admin->cache.actionstream[start]; in sparx5_vcap_is0_cache_write()
931 switch (sel) { in sparx5_vcap_is0_cache_write()
934 /* Avoid 'match-off' by setting value & mask */ in sparx5_vcap_is0_cache_write()
935 spx5_wr(keystr[idx] & mskstr[idx], sparx5, in sparx5_vcap_is0_cache_write()
937 spx5_wr(~mskstr[idx], sparx5, in sparx5_vcap_is0_cache_write()
943 spx5_wr(actstr[idx], sparx5, in sparx5_vcap_is0_cache_write()
955 spx5_wr(admin->cache.counter, sparx5, in sparx5_vcap_is0_cache_write()
959 static void sparx5_vcap_is2_cache_write(struct sparx5 *sparx5, in sparx5_vcap_is2_cache_write() argument
968 keystr = &admin->cache.keystream[start]; in sparx5_vcap_is2_cache_write()
969 mskstr = &admin->cache.maskstream[start]; in sparx5_vcap_is2_cache_write()
970 actstr = &admin->cache.actionstream[start]; in sparx5_vcap_is2_cache_write()
972 switch (sel) { in sparx5_vcap_is2_cache_write()
975 /* Avoid 'match-off' by setting value & mask */ in sparx5_vcap_is2_cache_write()
976 spx5_wr(keystr[idx] & mskstr[idx], sparx5, in sparx5_vcap_is2_cache_write()
978 spx5_wr(~mskstr[idx], sparx5, in sparx5_vcap_is2_cache_write()
984 spx5_wr(actstr[idx], sparx5, in sparx5_vcap_is2_cache_write()
996 if (admin->vinst == 0) in sparx5_vcap_is2_cache_write()
997 spx5_wr(admin->cache.counter, sparx5, in sparx5_vcap_is2_cache_write()
1000 spx5_wr(admin->cache.counter, sparx5, in sparx5_vcap_is2_cache_write()
1002 spx5_wr(admin->cache.sticky, sparx5, in sparx5_vcap_is2_cache_write()
1008 static void sparx5_es0_write_esdx_counter(struct sparx5 *sparx5, in sparx5_es0_write_esdx_counter() argument
1011 mutex_lock(&sparx5->queue_stats_lock); in sparx5_es0_write_esdx_counter()
1012 spx5_wr(XQS_STAT_CFG_STAT_VIEW_SET(id), sparx5, XQS_STAT_CFG); in sparx5_es0_write_esdx_counter()
1013 spx5_wr(admin->cache.counter, sparx5, in sparx5_es0_write_esdx_counter()
1015 spx5_wr(0, sparx5, XQS_CNT(SPARX5_STAT_ESDX_YEL_PKTS)); in sparx5_es0_write_esdx_counter()
1016 mutex_unlock(&sparx5->queue_stats_lock); in sparx5_es0_write_esdx_counter()
1019 static void sparx5_vcap_es0_cache_write(struct sparx5 *sparx5, in sparx5_vcap_es0_cache_write() argument
1028 keystr = &admin->cache.keystream[start]; in sparx5_vcap_es0_cache_write()
1029 mskstr = &admin->cache.maskstream[start]; in sparx5_vcap_es0_cache_write()
1030 actstr = &admin->cache.actionstream[start]; in sparx5_vcap_es0_cache_write()
1032 switch (sel) { in sparx5_vcap_es0_cache_write()
1035 /* Avoid 'match-off' by setting value & mask */ in sparx5_vcap_es0_cache_write()
1036 spx5_wr(keystr[idx] & mskstr[idx], sparx5, in sparx5_vcap_es0_cache_write()
1038 spx5_wr(~mskstr[idx], sparx5, in sparx5_vcap_es0_cache_write()
1044 spx5_wr(actstr[idx], sparx5, in sparx5_vcap_es0_cache_write()
1055 spx5_wr(admin->cache.counter, sparx5, VCAP_ES0_VCAP_CNT_DAT(0)); in sparx5_vcap_es0_cache_write()
1056 sparx5_es0_write_esdx_counter(sparx5, admin, start); in sparx5_vcap_es0_cache_write()
1060 static void sparx5_vcap_es2_cache_write(struct sparx5 *sparx5, in sparx5_vcap_es2_cache_write() argument
1069 keystr = &admin->cache.keystream[start]; in sparx5_vcap_es2_cache_write()
1070 mskstr = &admin->cache.maskstream[start]; in sparx5_vcap_es2_cache_write()
1071 actstr = &admin->cache.actionstream[start]; in sparx5_vcap_es2_cache_write()
1073 switch (sel) { in sparx5_vcap_es2_cache_write()
1076 /* Avoid 'match-off' by setting value & mask */ in sparx5_vcap_es2_cache_write()
1077 spx5_wr(keystr[idx] & mskstr[idx], sparx5, in sparx5_vcap_es2_cache_write()
1079 spx5_wr(~mskstr[idx], sparx5, in sparx5_vcap_es2_cache_write()
1085 spx5_wr(actstr[idx], sparx5, in sparx5_vcap_es2_cache_write()
1097 spx5_wr(admin->cache.counter, sparx5, EACL_ES2_CNT(start)); in sparx5_vcap_es2_cache_write()
1098 spx5_wr(admin->cache.sticky, sparx5, VCAP_ES2_VCAP_CNT_DAT(0)); in sparx5_vcap_es2_cache_write()
1110 struct sparx5 *sparx5 = port->sparx5; in sparx5_vcap_cache_write() local
1112 switch (admin->vtype) { in sparx5_vcap_cache_write()
1114 sparx5_vcap_is0_cache_write(sparx5, admin, sel, start, count); in sparx5_vcap_cache_write()
1117 sparx5_vcap_is2_cache_write(sparx5, admin, sel, start, count); in sparx5_vcap_cache_write()
1120 sparx5_vcap_es0_cache_write(sparx5, admin, sel, start, count); in sparx5_vcap_cache_write()
1123 sparx5_vcap_es2_cache_write(sparx5, admin, sel, start, count); in sparx5_vcap_cache_write()
1126 sparx5_vcap_type_err(sparx5, admin, __func__); in sparx5_vcap_cache_write()
1131 static void sparx5_vcap_is0_cache_read(struct sparx5 *sparx5, in sparx5_vcap_is0_cache_read() argument
1140 keystr = &admin->cache.keystream[start]; in sparx5_vcap_is0_cache_read()
1141 mskstr = &admin->cache.maskstream[start]; in sparx5_vcap_is0_cache_read()
1142 actstr = &admin->cache.actionstream[start]; in sparx5_vcap_is0_cache_read()
1146 keystr[idx] = spx5_rd(sparx5, in sparx5_vcap_is0_cache_read()
1148 mskstr[idx] = ~spx5_rd(sparx5, in sparx5_vcap_is0_cache_read()
1155 actstr[idx] = spx5_rd(sparx5, in sparx5_vcap_is0_cache_read()
1159 admin->cache.counter = in sparx5_vcap_is0_cache_read()
1160 spx5_rd(sparx5, VCAP_SUPER_VCAP_CNT_DAT(0)); in sparx5_vcap_is0_cache_read()
1161 admin->cache.sticky = in sparx5_vcap_is0_cache_read()
1162 spx5_rd(sparx5, VCAP_SUPER_VCAP_CNT_DAT(0)); in sparx5_vcap_is0_cache_read()
1166 static void sparx5_vcap_is2_cache_read(struct sparx5 *sparx5, in sparx5_vcap_is2_cache_read() argument
1175 keystr = &admin->cache.keystream[start]; in sparx5_vcap_is2_cache_read()
1176 mskstr = &admin->cache.maskstream[start]; in sparx5_vcap_is2_cache_read()
1177 actstr = &admin->cache.actionstream[start]; in sparx5_vcap_is2_cache_read()
1181 keystr[idx] = spx5_rd(sparx5, in sparx5_vcap_is2_cache_read()
1183 mskstr[idx] = ~spx5_rd(sparx5, in sparx5_vcap_is2_cache_read()
1190 actstr[idx] = spx5_rd(sparx5, in sparx5_vcap_is2_cache_read()
1195 if (admin->vinst == 0) in sparx5_vcap_is2_cache_read()
1196 admin->cache.counter = in sparx5_vcap_is2_cache_read()
1197 spx5_rd(sparx5, ANA_ACL_CNT_A(start)); in sparx5_vcap_is2_cache_read()
1199 admin->cache.counter = in sparx5_vcap_is2_cache_read()
1200 spx5_rd(sparx5, ANA_ACL_CNT_B(start)); in sparx5_vcap_is2_cache_read()
1201 admin->cache.sticky = in sparx5_vcap_is2_cache_read()
1202 spx5_rd(sparx5, VCAP_SUPER_VCAP_CNT_DAT(0)); in sparx5_vcap_is2_cache_read()
1207 static void sparx5_es0_read_esdx_counter(struct sparx5 *sparx5, in sparx5_es0_read_esdx_counter() argument
1212 mutex_lock(&sparx5->queue_stats_lock); in sparx5_es0_read_esdx_counter()
1213 spx5_wr(XQS_STAT_CFG_STAT_VIEW_SET(id), sparx5, XQS_STAT_CFG); in sparx5_es0_read_esdx_counter()
1214 counter = spx5_rd(sparx5, XQS_CNT(SPARX5_STAT_ESDX_GRN_PKTS)) + in sparx5_es0_read_esdx_counter()
1215 spx5_rd(sparx5, XQS_CNT(SPARX5_STAT_ESDX_YEL_PKTS)); in sparx5_es0_read_esdx_counter()
1216 mutex_unlock(&sparx5->queue_stats_lock); in sparx5_es0_read_esdx_counter()
1218 admin->cache.counter = counter; in sparx5_es0_read_esdx_counter()
1221 static void sparx5_vcap_es0_cache_read(struct sparx5 *sparx5, in sparx5_vcap_es0_cache_read() argument
1230 keystr = &admin->cache.keystream[start]; in sparx5_vcap_es0_cache_read()
1231 mskstr = &admin->cache.maskstream[start]; in sparx5_vcap_es0_cache_read()
1232 actstr = &admin->cache.actionstream[start]; in sparx5_vcap_es0_cache_read()
1237 spx5_rd(sparx5, VCAP_ES0_VCAP_ENTRY_DAT(idx)); in sparx5_vcap_es0_cache_read()
1239 ~spx5_rd(sparx5, VCAP_ES0_VCAP_MASK_DAT(idx)); in sparx5_vcap_es0_cache_read()
1246 spx5_rd(sparx5, VCAP_ES0_VCAP_ACTION_DAT(idx)); in sparx5_vcap_es0_cache_read()
1249 admin->cache.counter = in sparx5_vcap_es0_cache_read()
1250 spx5_rd(sparx5, VCAP_ES0_VCAP_CNT_DAT(0)); in sparx5_vcap_es0_cache_read()
1251 admin->cache.sticky = admin->cache.counter; in sparx5_vcap_es0_cache_read()
1252 sparx5_es0_read_esdx_counter(sparx5, admin, start); in sparx5_vcap_es0_cache_read()
1256 static void sparx5_vcap_es2_cache_read(struct sparx5 *sparx5, in sparx5_vcap_es2_cache_read() argument
1265 keystr = &admin->cache.keystream[start]; in sparx5_vcap_es2_cache_read()
1266 mskstr = &admin->cache.maskstream[start]; in sparx5_vcap_es2_cache_read()
1267 actstr = &admin->cache.actionstream[start]; in sparx5_vcap_es2_cache_read()
1272 spx5_rd(sparx5, VCAP_ES2_VCAP_ENTRY_DAT(idx)); in sparx5_vcap_es2_cache_read()
1274 ~spx5_rd(sparx5, VCAP_ES2_VCAP_MASK_DAT(idx)); in sparx5_vcap_es2_cache_read()
1281 spx5_rd(sparx5, VCAP_ES2_VCAP_ACTION_DAT(idx)); in sparx5_vcap_es2_cache_read()
1285 admin->cache.counter = in sparx5_vcap_es2_cache_read()
1286 spx5_rd(sparx5, EACL_ES2_CNT(start)); in sparx5_vcap_es2_cache_read()
1287 admin->cache.sticky = in sparx5_vcap_es2_cache_read()
1288 spx5_rd(sparx5, VCAP_ES2_VCAP_CNT_DAT(0)); in sparx5_vcap_es2_cache_read()
1300 struct sparx5 *sparx5 = port->sparx5; in sparx5_vcap_cache_read() local
1302 switch (admin->vtype) { in sparx5_vcap_cache_read()
1304 sparx5_vcap_is0_cache_read(sparx5, admin, sel, start, count); in sparx5_vcap_cache_read()
1307 sparx5_vcap_is2_cache_read(sparx5, admin, sel, start, count); in sparx5_vcap_cache_read()
1310 sparx5_vcap_es0_cache_read(sparx5, admin, sel, start, count); in sparx5_vcap_cache_read()
1313 sparx5_vcap_es2_cache_read(sparx5, admin, sel, start, count); in sparx5_vcap_cache_read()
1316 sparx5_vcap_type_err(sparx5, admin, __func__); in sparx5_vcap_cache_read()
1327 struct sparx5 *sparx5 = port->sparx5; in sparx5_vcap_range_init() local
1329 _sparx5_vcap_range_init(sparx5, admin, addr, count); in sparx5_vcap_range_init()
1332 static void sparx5_vcap_super_update(struct sparx5 *sparx5, in sparx5_vcap_super_update() argument
1339 VCAP_SUPER_CFG_MV_SIZE_SET(0), sparx5, VCAP_SUPER_CFG); in sparx5_vcap_super_update()
1347 sparx5, VCAP_SUPER_CTRL); in sparx5_vcap_super_update()
1348 sparx5_vcap_wait_super_update(sparx5); in sparx5_vcap_super_update()
1351 static void sparx5_vcap_es0_update(struct sparx5 *sparx5, in sparx5_vcap_es0_update() argument
1358 VCAP_ES0_CFG_MV_SIZE_SET(0), sparx5, VCAP_ES0_CFG); in sparx5_vcap_es0_update()
1366 sparx5, VCAP_ES0_CTRL); in sparx5_vcap_es0_update()
1367 sparx5_vcap_wait_es0_update(sparx5); in sparx5_vcap_es0_update()
1370 static void sparx5_vcap_es2_update(struct sparx5 *sparx5, in sparx5_vcap_es2_update() argument
1377 VCAP_ES2_CFG_MV_SIZE_SET(0), sparx5, VCAP_ES2_CFG); in sparx5_vcap_es2_update()
1385 sparx5, VCAP_ES2_CTRL); in sparx5_vcap_es2_update()
1386 sparx5_vcap_wait_es2_update(sparx5); in sparx5_vcap_es2_update()
1395 struct sparx5 *sparx5 = port->sparx5; in sparx5_vcap_update() local
1397 switch (admin->vtype) { in sparx5_vcap_update()
1400 sparx5_vcap_super_update(sparx5, cmd, sel, addr); in sparx5_vcap_update()
1403 sparx5_vcap_es0_update(sparx5, cmd, sel, addr); in sparx5_vcap_update()
1406 sparx5_vcap_es2_update(sparx5, cmd, sel, addr); in sparx5_vcap_update()
1409 sparx5_vcap_type_err(sparx5, admin, __func__); in sparx5_vcap_update()
1414 static void sparx5_vcap_super_move(struct sparx5 *sparx5, in sparx5_vcap_super_move() argument
1422 sparx5, VCAP_SUPER_CFG); in sparx5_vcap_super_move()
1430 sparx5, VCAP_SUPER_CTRL); in sparx5_vcap_super_move()
1431 sparx5_vcap_wait_super_update(sparx5); in sparx5_vcap_super_move()
1434 static void sparx5_vcap_es0_move(struct sparx5 *sparx5, in sparx5_vcap_es0_move() argument
1442 sparx5, VCAP_ES0_CFG); in sparx5_vcap_es0_move()
1450 sparx5, VCAP_ES0_CTRL); in sparx5_vcap_es0_move()
1451 sparx5_vcap_wait_es0_update(sparx5); in sparx5_vcap_es0_move()
1454 static void sparx5_vcap_es2_move(struct sparx5 *sparx5, in sparx5_vcap_es2_move() argument
1462 sparx5, VCAP_ES2_CFG); in sparx5_vcap_es2_move()
1470 sparx5, VCAP_ES2_CTRL); in sparx5_vcap_es2_move()
1471 sparx5_vcap_wait_es2_update(sparx5); in sparx5_vcap_es2_move()
1479 struct sparx5 *sparx5 = port->sparx5; in sparx5_vcap_move() local
1484 mv_size = count - 1; in sparx5_vcap_move()
1486 mv_num_pos = offset - 1; in sparx5_vcap_move()
1489 mv_num_pos = -offset - 1; in sparx5_vcap_move()
1493 switch (admin->vtype) { in sparx5_vcap_move()
1496 sparx5_vcap_super_move(sparx5, addr, cmd, mv_num_pos, mv_size); in sparx5_vcap_move()
1499 sparx5_vcap_es0_move(sparx5, addr, cmd, mv_num_pos, mv_size); in sparx5_vcap_move()
1502 sparx5_vcap_es2_move(sparx5, addr, cmd, mv_num_pos, mv_size); in sparx5_vcap_move()
1505 sparx5_vcap_type_err(sparx5, admin, __func__); in sparx5_vcap_move()
1524 switch (keyset) { in sparx5_vcap_is0_keyset_to_etype_ps()
1539 struct sparx5 *sparx5 = port->sparx5; in sparx5_vcap_is0_set_port_keyset() local
1540 int portno = port->portno; in sparx5_vcap_is0_set_port_keyset()
1543 switch (l3_proto) { in sparx5_vcap_is0_set_port_keyset()
1548 sparx5, in sparx5_vcap_is0_set_port_keyset()
1555 sparx5, in sparx5_vcap_is0_set_port_keyset()
1562 sparx5, in sparx5_vcap_is0_set_port_keyset()
1570 switch (keyset) { in sparx5_vcap_is2_keyset_to_arp_ps()
1580 switch (keyset) { in sparx5_vcap_is2_keyset_to_ipv4_ps()
1595 switch (keyset) { in sparx5_vcap_is2_keyset_to_ipv6_uc_ps()
1610 switch (keyset) { in sparx5_vcap_is2_keyset_to_ipv6_mc_ps()
1628 struct sparx5 *sparx5 = port->sparx5; in sparx5_vcap_is2_set_port_keyset() local
1629 int portno = port->portno; in sparx5_vcap_is2_set_port_keyset()
1632 switch (l3_proto) { in sparx5_vcap_is2_set_port_keyset()
1637 sparx5, in sparx5_vcap_is2_set_port_keyset()
1644 sparx5, in sparx5_vcap_is2_set_port_keyset()
1648 sparx5, in sparx5_vcap_is2_set_port_keyset()
1655 sparx5, in sparx5_vcap_is2_set_port_keyset()
1660 sparx5, in sparx5_vcap_is2_set_port_keyset()
1667 sparx5, in sparx5_vcap_is2_set_port_keyset()
1675 switch (keyset) { in sparx5_vcap_es2_keyset_to_arp_ps()
1685 switch (keyset) { in sparx5_vcap_es2_keyset_to_ipv4_ps()
1701 switch (keyset) { in sparx5_vcap_es2_keyset_to_ipv6_ps()
1721 struct sparx5 *sparx5 = port->sparx5; in sparx5_vcap_es2_set_port_keyset() local
1722 int portno = port->portno; in sparx5_vcap_es2_set_port_keyset()
1725 switch (l3_proto) { in sparx5_vcap_es2_set_port_keyset()
1730 sparx5, in sparx5_vcap_es2_set_port_keyset()
1737 sparx5, in sparx5_vcap_es2_set_port_keyset()
1744 sparx5, in sparx5_vcap_es2_set_port_keyset()
1761 switch (admin->vtype) { in sparx5_vcap_set_port_keyset()
1787 sparx5_vcap_type_err(port->sparx5, admin, __func__); in sparx5_vcap_set_port_keyset()
1793 static void sparx5_vcap_is0_port_key_selection(struct sparx5 *sparx5, in sparx5_vcap_is0_port_key_selection() argument
1806 for (lookup = 0; lookup < admin->lookups; ++lookup) { in sparx5_vcap_is0_port_key_selection()
1808 spx5_wr(keysel, sparx5, in sparx5_vcap_is0_port_key_selection()
1812 sparx5, in sparx5_vcap_is0_port_key_selection()
1819 static void sparx5_vcap_is2_port_key_selection(struct sparx5 *sparx5, in sparx5_vcap_is2_port_key_selection() argument
1831 for (lookup = 0; lookup < admin->lookups; ++lookup) { in sparx5_vcap_is2_port_key_selection()
1833 spx5_wr(keysel, sparx5, in sparx5_vcap_is2_port_key_selection()
1841 sparx5, in sparx5_vcap_is2_port_key_selection()
1846 static void sparx5_vcap_es0_port_key_selection(struct sparx5 *sparx5, in sparx5_vcap_es0_port_key_selection() argument
1855 sparx5, REW_RTAG_ETAG_CTRL(portno)); in sparx5_vcap_es0_port_key_selection()
1858 sparx5, REW_ES0_CTRL); in sparx5_vcap_es0_port_key_selection()
1862 static void sparx5_vcap_es2_port_key_selection(struct sparx5 *sparx5, in sparx5_vcap_es2_port_key_selection() argument
1871 for (lookup = 0; lookup < admin->lookups; ++lookup) in sparx5_vcap_es2_port_key_selection()
1873 spx5_wr(keysel, sparx5, in sparx5_vcap_es2_port_key_selection()
1878 static void sparx5_vcap_port_key_selection(struct sparx5 *sparx5, in sparx5_vcap_port_key_selection() argument
1881 switch (admin->vtype) { in sparx5_vcap_port_key_selection()
1883 sparx5_vcap_is0_port_key_selection(sparx5, admin); in sparx5_vcap_port_key_selection()
1886 sparx5_vcap_is2_port_key_selection(sparx5, admin); in sparx5_vcap_port_key_selection()
1889 sparx5_vcap_es0_port_key_selection(sparx5, admin); in sparx5_vcap_port_key_selection()
1892 sparx5_vcap_es2_port_key_selection(sparx5, admin); in sparx5_vcap_port_key_selection()
1895 sparx5_vcap_type_err(sparx5, admin, __func__); in sparx5_vcap_port_key_selection()
1901 static void sparx5_vcap_port_key_deselection(struct sparx5 *sparx5, in sparx5_vcap_port_key_deselection() argument
1906 switch (admin->vtype) { in sparx5_vcap_port_key_deselection()
1908 for (lookup = 0; lookup < admin->lookups; ++lookup) in sparx5_vcap_port_key_deselection()
1912 sparx5, in sparx5_vcap_port_key_deselection()
1919 sparx5, in sparx5_vcap_port_key_deselection()
1924 REW_ES0_CTRL_ES0_LU_ENA, sparx5, REW_ES0_CTRL); in sparx5_vcap_port_key_deselection()
1927 for (lookup = 0; lookup < admin->lookups; ++lookup) in sparx5_vcap_port_key_deselection()
1931 sparx5, in sparx5_vcap_port_key_deselection()
1935 sparx5_vcap_type_err(sparx5, admin, __func__); in sparx5_vcap_port_key_deselection()
1944 mutex_destroy(&admin->lock); in sparx5_vcap_admin_free()
1945 kfree(admin->cache.keystream); in sparx5_vcap_admin_free()
1946 kfree(admin->cache.maskstream); in sparx5_vcap_admin_free()
1947 kfree(admin->cache.actionstream); in sparx5_vcap_admin_free()
1953 sparx5_vcap_admin_alloc(struct sparx5 *sparx5, struct vcap_control *ctrl, in sparx5_vcap_admin_alloc() argument
1960 return ERR_PTR(-ENOMEM); in sparx5_vcap_admin_alloc()
1961 INIT_LIST_HEAD(&admin->list); in sparx5_vcap_admin_alloc()
1962 INIT_LIST_HEAD(&admin->rules); in sparx5_vcap_admin_alloc()
1963 INIT_LIST_HEAD(&admin->enabled); in sparx5_vcap_admin_alloc()
1964 mutex_init(&admin->lock); in sparx5_vcap_admin_alloc()
1965 admin->vtype = cfg->vtype; in sparx5_vcap_admin_alloc()
1966 admin->vinst = cfg->vinst; in sparx5_vcap_admin_alloc()
1967 admin->ingress = cfg->ingress; in sparx5_vcap_admin_alloc()
1968 admin->lookups = cfg->lookups; in sparx5_vcap_admin_alloc()
1969 admin->lookups_per_instance = cfg->lookups_per_instance; in sparx5_vcap_admin_alloc()
1970 admin->first_cid = cfg->first_cid; in sparx5_vcap_admin_alloc()
1971 admin->last_cid = cfg->last_cid; in sparx5_vcap_admin_alloc()
1972 admin->cache.keystream = in sparx5_vcap_admin_alloc()
1974 admin->cache.maskstream = in sparx5_vcap_admin_alloc()
1976 admin->cache.actionstream = in sparx5_vcap_admin_alloc()
1978 if (!admin->cache.keystream || !admin->cache.maskstream || in sparx5_vcap_admin_alloc()
1979 !admin->cache.actionstream) { in sparx5_vcap_admin_alloc()
1981 return ERR_PTR(-ENOMEM); in sparx5_vcap_admin_alloc()
1987 static void sparx5_vcap_block_alloc(struct sparx5 *sparx5, in sparx5_vcap_block_alloc() argument
1993 switch (admin->vtype) { in sparx5_vcap_block_alloc()
2000 for (idx = cfg->blockno; idx < cfg->blockno + cfg->blocks; in sparx5_vcap_block_alloc()
2002 spx5_wr(VCAP_SUPER_IDX_CORE_IDX_SET(idx), sparx5, in sparx5_vcap_block_alloc()
2004 spx5_wr(VCAP_SUPER_MAP_CORE_MAP_SET(cfg->map_id), in sparx5_vcap_block_alloc()
2005 sparx5, VCAP_SUPER_MAP); in sparx5_vcap_block_alloc()
2007 admin->first_valid_addr = cfg->blockno * SUPER_VCAP_BLK_SIZE; in sparx5_vcap_block_alloc()
2008 admin->last_used_addr = admin->first_valid_addr + in sparx5_vcap_block_alloc()
2009 cfg->blocks * SUPER_VCAP_BLK_SIZE; in sparx5_vcap_block_alloc()
2010 admin->last_valid_addr = admin->last_used_addr - 1; in sparx5_vcap_block_alloc()
2013 admin->first_valid_addr = 0; in sparx5_vcap_block_alloc()
2014 admin->last_used_addr = cfg->count; in sparx5_vcap_block_alloc()
2015 admin->last_valid_addr = cfg->count - 1; in sparx5_vcap_block_alloc()
2016 cores = spx5_rd(sparx5, VCAP_ES0_CORE_CNT); in sparx5_vcap_block_alloc()
2018 spx5_wr(VCAP_ES0_IDX_CORE_IDX_SET(idx), sparx5, in sparx5_vcap_block_alloc()
2020 spx5_wr(VCAP_ES0_MAP_CORE_MAP_SET(1), sparx5, in sparx5_vcap_block_alloc()
2025 admin->first_valid_addr = 0; in sparx5_vcap_block_alloc()
2026 admin->last_used_addr = cfg->count; in sparx5_vcap_block_alloc()
2027 admin->last_valid_addr = cfg->count - 1; in sparx5_vcap_block_alloc()
2028 cores = spx5_rd(sparx5, VCAP_ES2_CORE_CNT); in sparx5_vcap_block_alloc()
2030 spx5_wr(VCAP_ES2_IDX_CORE_IDX_SET(idx), sparx5, in sparx5_vcap_block_alloc()
2032 spx5_wr(VCAP_ES2_MAP_CORE_MAP_SET(1), sparx5, in sparx5_vcap_block_alloc()
2037 sparx5_vcap_type_err(sparx5, admin, __func__); in sparx5_vcap_block_alloc()
2043 int sparx5_vcap_init(struct sparx5 *sparx5) in sparx5_vcap_init() argument
2054 * - Create administrative state for each available VCAP in sparx5_vcap_init()
2055 * - Lists of rules in sparx5_vcap_init()
2056 * - Address information in sparx5_vcap_init()
2057 * - Initialize VCAP blocks in sparx5_vcap_init()
2058 * - Configure port keysets in sparx5_vcap_init()
2062 return -ENOMEM; in sparx5_vcap_init()
2064 sparx5->vcap_ctrl = ctrl; in sparx5_vcap_init()
2065 /* select the sparx5 VCAP model */ in sparx5_vcap_init()
2066 ctrl->vcaps = sparx5_vcaps; in sparx5_vcap_init()
2067 ctrl->stats = &sparx5_vcap_stats; in sparx5_vcap_init()
2069 ctrl->ops = &sparx5_vcap_ops; in sparx5_vcap_init()
2071 INIT_LIST_HEAD(&ctrl->list); in sparx5_vcap_init()
2074 admin = sparx5_vcap_admin_alloc(sparx5, ctrl, cfg); in sparx5_vcap_init()
2081 sparx5_vcap_block_alloc(sparx5, admin, cfg); in sparx5_vcap_init()
2082 sparx5_vcap_block_init(sparx5, admin); in sparx5_vcap_init()
2083 if (cfg->vinst == 0) in sparx5_vcap_init()
2084 sparx5_vcap_port_key_selection(sparx5, admin); in sparx5_vcap_init()
2085 list_add_tail(&admin->list, &ctrl->list); in sparx5_vcap_init()
2087 dir = vcap_debugfs(sparx5->dev, sparx5->debugfs_root, ctrl); in sparx5_vcap_init()
2089 if (sparx5->ports[idx]) in sparx5_vcap_init()
2090 vcap_port_debugfs(sparx5->dev, dir, ctrl, in sparx5_vcap_init()
2091 sparx5->ports[idx]->ndev); in sparx5_vcap_init()
2096 void sparx5_vcap_destroy(struct sparx5 *sparx5) in sparx5_vcap_destroy() argument
2098 struct vcap_control *ctrl = sparx5->vcap_ctrl; in sparx5_vcap_destroy()
2104 list_for_each_entry_safe(admin, admin_next, &ctrl->list, list) { in sparx5_vcap_destroy()
2105 sparx5_vcap_port_key_deselection(sparx5, admin); in sparx5_vcap_destroy()
2107 list_del(&admin->list); in sparx5_vcap_destroy()