Lines Matching +full:ocelot +full:- +full:1

1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /* Microsemi Ocelot Switch driver
21 (1 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP)
35 return -EOPNOTSUPP; in ocelot_chain_to_block()
38 /* Backwards compatibility with older, single-chain tc-flower in ocelot_chain_to_block()
39 * offload support in Ocelot in ocelot_chain_to_block()
56 return -EOPNOTSUPP; in ocelot_chain_to_block()
64 /* Backwards compatibility with older, single-chain tc-flower in ocelot_chain_to_lookup()
65 * offload support in Ocelot in ocelot_chain_to_lookup()
80 /* Backwards compatibility with older, single-chain tc-flower in ocelot_chain_to_pag()
81 * offload support in Ocelot in ocelot_chain_to_pag()
89 return chain - VCAP_IS2_CHAIN(lookup, 0); in ocelot_chain_to_pag()
101 /* Non-optional GOTOs */ in ocelot_is_goto_target_valid()
105 goto_target == VCAP_IS1_CHAIN(1) || in ocelot_is_goto_target_valid()
108 goto_target == VCAP_IS2_CHAIN(1, 0) || in ocelot_is_goto_target_valid()
112 return (goto_target == VCAP_IS1_CHAIN(1)); in ocelot_is_goto_target_valid()
114 if (chain == VCAP_IS1_CHAIN(1)) in ocelot_is_goto_target_valid()
117 /* Lookup 2 of VCAP IS1 can really support non-optional GOTOs, in ocelot_is_goto_target_valid()
118 * using a Policy Association Group (PAG) value, which is an 8-bit in ocelot_is_goto_target_valid()
129 /* Non-optional GOTO from VCAP IS2 lookup 0 to lookup 1. in ocelot_is_goto_target_valid()
134 return (goto_target == VCAP_IS2_CHAIN(1, pag)); in ocelot_is_goto_target_valid()
136 /* VCAP IS2 lookup 1 can goto to PSFP block if hardware support */ in ocelot_is_goto_target_valid()
138 if (chain == VCAP_IS2_CHAIN(1, pag)) in ocelot_is_goto_target_valid()
145 ocelot_find_vcap_filter_that_points_at(struct ocelot *ocelot, int chain) in ocelot_find_vcap_filter_that_points_at() argument
156 block = &ocelot->block[VCAP_IS1]; in ocelot_find_vcap_filter_that_points_at()
158 list_for_each_entry(filter, &block->rules, list) in ocelot_find_vcap_filter_that_points_at()
159 if (filter->type == OCELOT_VCAP_FILTER_PAG && in ocelot_find_vcap_filter_that_points_at()
160 filter->goto_target == chain) in ocelot_find_vcap_filter_that_points_at()
164 list_for_each_entry(filter, &ocelot->dummy_rules, list) in ocelot_find_vcap_filter_that_points_at()
165 if (filter->goto_target == chain) in ocelot_find_vcap_filter_that_points_at()
172 ocelot_flower_parse_ingress_vlan_modify(struct ocelot *ocelot, int port, in ocelot_flower_parse_ingress_vlan_modify() argument
177 struct ocelot_port *ocelot_port = ocelot->ports[port]; in ocelot_flower_parse_ingress_vlan_modify()
179 if (filter->goto_target != -1) { in ocelot_flower_parse_ingress_vlan_modify()
182 return -EOPNOTSUPP; in ocelot_flower_parse_ingress_vlan_modify()
185 if (!ocelot_port->vlan_aware) { in ocelot_flower_parse_ingress_vlan_modify()
188 return -EOPNOTSUPP; in ocelot_flower_parse_ingress_vlan_modify()
191 filter->action.vid_replace_ena = true; in ocelot_flower_parse_ingress_vlan_modify()
192 filter->action.pcp_dei_ena = true; in ocelot_flower_parse_ingress_vlan_modify()
193 filter->action.vid = a->vlan.vid; in ocelot_flower_parse_ingress_vlan_modify()
194 filter->action.pcp = a->vlan.prio; in ocelot_flower_parse_ingress_vlan_modify()
195 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; in ocelot_flower_parse_ingress_vlan_modify()
207 switch (ntohs(a->vlan.proto)) { in ocelot_flower_parse_egress_vlan_modify()
217 return -EOPNOTSUPP; in ocelot_flower_parse_egress_vlan_modify()
220 filter->action.tag_a_tpid_sel = tpid; in ocelot_flower_parse_egress_vlan_modify()
221 filter->action.push_outer_tag = OCELOT_ES0_TAG; in ocelot_flower_parse_egress_vlan_modify()
222 filter->action.tag_a_vid_sel = OCELOT_ES0_VID_PLUS_CLASSIFIED_VID; in ocelot_flower_parse_egress_vlan_modify()
223 filter->action.vid_a_val = a->vlan.vid; in ocelot_flower_parse_egress_vlan_modify()
224 filter->action.pcp_a_val = a->vlan.prio; in ocelot_flower_parse_egress_vlan_modify()
225 filter->action.tag_a_pcp_sel = OCELOT_ES0_PCP; in ocelot_flower_parse_egress_vlan_modify()
226 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; in ocelot_flower_parse_egress_vlan_modify()
231 static int ocelot_flower_parse_action(struct ocelot *ocelot, int port, in ocelot_flower_parse_action() argument
235 const struct flow_action *action = &f->rule->action; in ocelot_flower_parse_action()
236 struct netlink_ext_ack *extack = f->common.extack; in ocelot_flower_parse_action()
245 if (!flow_action_basic_hw_stats_check(&f->rule->action, in ocelot_flower_parse_action()
246 f->common.extack)) in ocelot_flower_parse_action()
247 return -EOPNOTSUPP; in ocelot_flower_parse_action()
249 chain = f->common.chain_index; in ocelot_flower_parse_action()
250 filter->block_id = ocelot_chain_to_block(chain, ingress); in ocelot_flower_parse_action()
251 if (filter->block_id < 0) { in ocelot_flower_parse_action()
253 return -EOPNOTSUPP; in ocelot_flower_parse_action()
255 if (filter->block_id == VCAP_IS1 || filter->block_id == VCAP_IS2) in ocelot_flower_parse_action()
256 filter->lookup = ocelot_chain_to_lookup(chain); in ocelot_flower_parse_action()
257 if (filter->block_id == VCAP_IS2) in ocelot_flower_parse_action()
258 filter->pag = ocelot_chain_to_pag(chain); in ocelot_flower_parse_action()
260 filter->goto_target = -1; in ocelot_flower_parse_action()
261 filter->type = OCELOT_VCAP_FILTER_DUMMY; in ocelot_flower_parse_action()
264 switch (a->id) { in ocelot_flower_parse_action()
266 if (filter->block_id != VCAP_IS2) { in ocelot_flower_parse_action()
269 return -EOPNOTSUPP; in ocelot_flower_parse_action()
271 if (filter->goto_target != -1) { in ocelot_flower_parse_action()
274 return -EOPNOTSUPP; in ocelot_flower_parse_action()
276 filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY; in ocelot_flower_parse_action()
277 filter->action.port_mask = 0; in ocelot_flower_parse_action()
278 filter->action.police_ena = true; in ocelot_flower_parse_action()
279 filter->action.pol_ix = OCELOT_POLICER_DISCARD; in ocelot_flower_parse_action()
280 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; in ocelot_flower_parse_action()
283 if (filter->block_id != VCAP_ES0 && in ocelot_flower_parse_action()
284 filter->block_id != VCAP_IS1 && in ocelot_flower_parse_action()
285 filter->block_id != VCAP_IS2) { in ocelot_flower_parse_action()
288 return -EOPNOTSUPP; in ocelot_flower_parse_action()
290 if (filter->block_id != VCAP_ES0 && in ocelot_flower_parse_action()
291 filter->goto_target != -1) { in ocelot_flower_parse_action()
294 return -EOPNOTSUPP; in ocelot_flower_parse_action()
296 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; in ocelot_flower_parse_action()
299 if (filter->block_id != VCAP_IS2 || in ocelot_flower_parse_action()
300 filter->lookup != 0) { in ocelot_flower_parse_action()
303 return -EOPNOTSUPP; in ocelot_flower_parse_action()
305 if (filter->goto_target != -1) { in ocelot_flower_parse_action()
308 return -EOPNOTSUPP; in ocelot_flower_parse_action()
310 filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY; in ocelot_flower_parse_action()
311 filter->action.port_mask = 0; in ocelot_flower_parse_action()
312 filter->action.cpu_copy_ena = true; in ocelot_flower_parse_action()
313 filter->action.cpu_qu_num = 0; in ocelot_flower_parse_action()
314 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; in ocelot_flower_parse_action()
315 filter->is_trap = true; in ocelot_flower_parse_action()
318 if (filter->block_id == PSFP_BLOCK_ID) { in ocelot_flower_parse_action()
319 filter->type = OCELOT_PSFP_FILTER_OFFLOAD; in ocelot_flower_parse_action()
322 if (filter->block_id != VCAP_IS2 || in ocelot_flower_parse_action()
323 filter->lookup != 0) { in ocelot_flower_parse_action()
326 return -EOPNOTSUPP; in ocelot_flower_parse_action()
328 if (filter->goto_target != -1) { in ocelot_flower_parse_action()
331 return -EOPNOTSUPP; in ocelot_flower_parse_action()
338 filter->action.police_ena = true; in ocelot_flower_parse_action()
340 pol_ix = a->hw_index + ocelot->vcap_pol.base; in ocelot_flower_parse_action()
341 pol_max = ocelot->vcap_pol.max; in ocelot_flower_parse_action()
343 if (ocelot->vcap_pol.max2 && pol_ix > pol_max) { in ocelot_flower_parse_action()
344 pol_ix += ocelot->vcap_pol.base2 - pol_max - 1; in ocelot_flower_parse_action()
345 pol_max = ocelot->vcap_pol.max2; in ocelot_flower_parse_action()
349 return -EINVAL; in ocelot_flower_parse_action()
351 filter->action.pol_ix = pol_ix; in ocelot_flower_parse_action()
353 rate = a->police.rate_bytes_ps; in ocelot_flower_parse_action()
354 filter->action.pol.rate = div_u64(rate, 1000) * 8; in ocelot_flower_parse_action()
355 filter->action.pol.burst = a->police.burst; in ocelot_flower_parse_action()
356 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; in ocelot_flower_parse_action()
359 if (filter->block_id != VCAP_IS2) { in ocelot_flower_parse_action()
362 return -EOPNOTSUPP; in ocelot_flower_parse_action()
364 if (filter->goto_target != -1) { in ocelot_flower_parse_action()
367 return -EOPNOTSUPP; in ocelot_flower_parse_action()
369 egress_port = ocelot->ops->netdev_to_port(a->dev); in ocelot_flower_parse_action()
372 "Destination not an ocelot port"); in ocelot_flower_parse_action()
373 return -EOPNOTSUPP; in ocelot_flower_parse_action()
375 filter->action.mask_mode = OCELOT_MASK_MODE_REDIRECT; in ocelot_flower_parse_action()
376 filter->action.port_mask = BIT(egress_port); in ocelot_flower_parse_action()
377 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; in ocelot_flower_parse_action()
380 if (filter->block_id != VCAP_IS2) { in ocelot_flower_parse_action()
383 return -EOPNOTSUPP; in ocelot_flower_parse_action()
385 if (filter->goto_target != -1) { in ocelot_flower_parse_action()
388 return -EOPNOTSUPP; in ocelot_flower_parse_action()
390 egress_port = ocelot->ops->netdev_to_port(a->dev); in ocelot_flower_parse_action()
393 "Destination not an ocelot port"); in ocelot_flower_parse_action()
394 return -EOPNOTSUPP; in ocelot_flower_parse_action()
396 filter->egress_port.value = egress_port; in ocelot_flower_parse_action()
397 filter->action.mirror_ena = true; in ocelot_flower_parse_action()
398 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; in ocelot_flower_parse_action()
401 if (filter->block_id != VCAP_IS1) { in ocelot_flower_parse_action()
404 return -EOPNOTSUPP; in ocelot_flower_parse_action()
406 if (filter->goto_target != -1) { in ocelot_flower_parse_action()
409 return -EOPNOTSUPP; in ocelot_flower_parse_action()
411 filter->action.vlan_pop_cnt_ena = true; in ocelot_flower_parse_action()
412 filter->action.vlan_pop_cnt++; in ocelot_flower_parse_action()
413 if (filter->action.vlan_pop_cnt > 2) { in ocelot_flower_parse_action()
416 return -EOPNOTSUPP; in ocelot_flower_parse_action()
418 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; in ocelot_flower_parse_action()
421 if (filter->block_id == VCAP_IS1) { in ocelot_flower_parse_action()
422 err = ocelot_flower_parse_ingress_vlan_modify(ocelot, port, in ocelot_flower_parse_action()
425 } else if (filter->block_id == VCAP_ES0) { in ocelot_flower_parse_action()
431 err = -EOPNOTSUPP; in ocelot_flower_parse_action()
437 if (filter->block_id != VCAP_IS1) { in ocelot_flower_parse_action()
440 return -EOPNOTSUPP; in ocelot_flower_parse_action()
442 if (filter->goto_target != -1) { in ocelot_flower_parse_action()
445 return -EOPNOTSUPP; in ocelot_flower_parse_action()
447 filter->action.qos_ena = true; in ocelot_flower_parse_action()
448 filter->action.qos_val = a->priority; in ocelot_flower_parse_action()
449 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; in ocelot_flower_parse_action()
452 filter->goto_target = a->chain_index; in ocelot_flower_parse_action()
454 if (filter->block_id == VCAP_IS1 && filter->lookup == 2) { in ocelot_flower_parse_action()
455 int pag = ocelot_chain_to_pag(filter->goto_target); in ocelot_flower_parse_action()
457 filter->action.pag_override_mask = 0xff; in ocelot_flower_parse_action()
458 filter->action.pag_val = pag; in ocelot_flower_parse_action()
459 filter->type = OCELOT_VCAP_FILTER_PAG; in ocelot_flower_parse_action()
463 if (filter->block_id != VCAP_ES0) { in ocelot_flower_parse_action()
466 return -EOPNOTSUPP; in ocelot_flower_parse_action()
468 switch (ntohs(a->vlan.proto)) { in ocelot_flower_parse_action()
478 return -EOPNOTSUPP; in ocelot_flower_parse_action()
480 filter->action.tag_a_tpid_sel = tpid; in ocelot_flower_parse_action()
481 filter->action.push_outer_tag = OCELOT_ES0_TAG; in ocelot_flower_parse_action()
482 filter->action.tag_a_vid_sel = OCELOT_ES0_VID; in ocelot_flower_parse_action()
483 filter->action.vid_a_val = a->vlan.vid; in ocelot_flower_parse_action()
484 filter->action.pcp_a_val = a->vlan.prio; in ocelot_flower_parse_action()
485 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; in ocelot_flower_parse_action()
488 if (filter->block_id != PSFP_BLOCK_ID) { in ocelot_flower_parse_action()
491 return -EOPNOTSUPP; in ocelot_flower_parse_action()
493 filter->type = OCELOT_PSFP_FILTER_OFFLOAD; in ocelot_flower_parse_action()
497 return -EOPNOTSUPP; in ocelot_flower_parse_action()
501 if (filter->goto_target == -1) { in ocelot_flower_parse_action()
502 if ((filter->block_id == VCAP_IS2 && filter->lookup == 1) || in ocelot_flower_parse_action()
503 chain == 0 || filter->block_id == PSFP_BLOCK_ID) { in ocelot_flower_parse_action()
507 return -EOPNOTSUPP; in ocelot_flower_parse_action()
511 if (!ocelot_is_goto_target_valid(filter->goto_target, chain, ingress) && in ocelot_flower_parse_action()
514 return -EOPNOTSUPP; in ocelot_flower_parse_action()
520 static int ocelot_flower_parse_indev(struct ocelot *ocelot, int port, in ocelot_flower_parse_indev() argument
525 const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0]; in ocelot_flower_parse_indev()
526 int key_length = vcap->keys[VCAP_ES0_IGR_PORT].length; in ocelot_flower_parse_indev()
527 struct netlink_ext_ack *extack = f->common.extack; in ocelot_flower_parse_indev()
534 if (!match.mask->ingress_ifindex) in ocelot_flower_parse_indev()
537 if (match.mask->ingress_ifindex != 0xFFFFFFFF) { in ocelot_flower_parse_indev()
539 return -EOPNOTSUPP; in ocelot_flower_parse_indev()
542 dev = ocelot->ops->port_to_netdev(ocelot, port); in ocelot_flower_parse_indev()
544 return -EINVAL; in ocelot_flower_parse_indev()
546 indev = __dev_get_by_index(dev_net(dev), match.key->ingress_ifindex); in ocelot_flower_parse_indev()
550 return -ENOENT; in ocelot_flower_parse_indev()
553 ingress_port = ocelot->ops->netdev_to_port(indev); in ocelot_flower_parse_indev()
556 "Can only offload an ocelot ingress port"); in ocelot_flower_parse_indev()
557 return -EOPNOTSUPP; in ocelot_flower_parse_indev()
562 return -EINVAL; in ocelot_flower_parse_indev()
565 filter->ingress_port.value = ingress_port; in ocelot_flower_parse_indev()
566 filter->ingress_port.mask = GENMASK(key_length - 1, 0); in ocelot_flower_parse_indev()
572 ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress, in ocelot_flower_parse_key() argument
577 struct flow_dissector *dissector = rule->match.dissector; in ocelot_flower_parse_key()
578 struct netlink_ext_ack *extack = f->common.extack; in ocelot_flower_parse_key()
579 u16 proto = ntohs(f->common.protocol); in ocelot_flower_parse_key()
583 if (dissector->used_keys & in ocelot_flower_parse_key()
592 return -EOPNOTSUPP; in ocelot_flower_parse_key()
599 if (match.mask->l2_miss) { in ocelot_flower_parse_key()
601 return -EOPNOTSUPP; in ocelot_flower_parse_key()
607 ret = ocelot_flower_parse_indev(ocelot, port, f, filter); in ocelot_flower_parse_key()
622 filter->key_type = OCELOT_VCAP_KEY_ANY; in ocelot_flower_parse_key()
623 filter->vlan.vid.value = match.key->vlan_id; in ocelot_flower_parse_key()
624 filter->vlan.vid.mask = match.mask->vlan_id; in ocelot_flower_parse_key()
625 filter->vlan.pcp.value[0] = match.key->vlan_priority; in ocelot_flower_parse_key()
626 filter->vlan.pcp.mask[0] = match.mask->vlan_priority; in ocelot_flower_parse_key()
633 if (filter->block_id == VCAP_ES0) { in ocelot_flower_parse_key()
636 return -EOPNOTSUPP; in ocelot_flower_parse_key()
643 if ((dissector->used_keys & in ocelot_flower_parse_key()
650 return -EOPNOTSUPP; in ocelot_flower_parse_key()
654 if (filter->block_id == VCAP_IS1 && in ocelot_flower_parse_key()
655 !is_zero_ether_addr(match.mask->dst)) { in ocelot_flower_parse_key()
658 return -EOPNOTSUPP; in ocelot_flower_parse_key()
661 filter->key_type = OCELOT_VCAP_KEY_ETYPE; in ocelot_flower_parse_key()
662 ether_addr_copy(filter->key.etype.dmac.value, in ocelot_flower_parse_key()
663 match.key->dst); in ocelot_flower_parse_key()
664 ether_addr_copy(filter->key.etype.smac.value, in ocelot_flower_parse_key()
665 match.key->src); in ocelot_flower_parse_key()
666 ether_addr_copy(filter->key.etype.dmac.mask, in ocelot_flower_parse_key()
667 match.mask->dst); in ocelot_flower_parse_key()
668 ether_addr_copy(filter->key.etype.smac.mask, in ocelot_flower_parse_key()
669 match.mask->src); in ocelot_flower_parse_key()
677 if (ntohs(match.key->n_proto) == ETH_P_IP) { in ocelot_flower_parse_key()
678 if (filter->block_id == VCAP_ES0) { in ocelot_flower_parse_key()
681 return -EOPNOTSUPP; in ocelot_flower_parse_key()
684 filter->key_type = OCELOT_VCAP_KEY_IPV4; in ocelot_flower_parse_key()
685 filter->key.ipv4.proto.value[0] = in ocelot_flower_parse_key()
686 match.key->ip_proto; in ocelot_flower_parse_key()
687 filter->key.ipv4.proto.mask[0] = in ocelot_flower_parse_key()
688 match.mask->ip_proto; in ocelot_flower_parse_key()
691 if (ntohs(match.key->n_proto) == ETH_P_IPV6) { in ocelot_flower_parse_key()
692 if (filter->block_id == VCAP_ES0) { in ocelot_flower_parse_key()
695 return -EOPNOTSUPP; in ocelot_flower_parse_key()
698 filter->key_type = OCELOT_VCAP_KEY_IPV6; in ocelot_flower_parse_key()
699 filter->key.ipv6.proto.value[0] = in ocelot_flower_parse_key()
700 match.key->ip_proto; in ocelot_flower_parse_key()
701 filter->key.ipv6.proto.mask[0] = in ocelot_flower_parse_key()
702 match.mask->ip_proto; in ocelot_flower_parse_key()
712 if (filter->block_id == VCAP_ES0) { in ocelot_flower_parse_key()
715 return -EOPNOTSUPP; in ocelot_flower_parse_key()
720 if (filter->block_id == VCAP_IS1 && *(u32 *)&match.mask->dst) { in ocelot_flower_parse_key()
723 return -EOPNOTSUPP; in ocelot_flower_parse_key()
726 tmp = &filter->key.ipv4.sip.value.addr[0]; in ocelot_flower_parse_key()
727 memcpy(tmp, &match.key->src, 4); in ocelot_flower_parse_key()
729 tmp = &filter->key.ipv4.sip.mask.addr[0]; in ocelot_flower_parse_key()
730 memcpy(tmp, &match.mask->src, 4); in ocelot_flower_parse_key()
732 tmp = &filter->key.ipv4.dip.value.addr[0]; in ocelot_flower_parse_key()
733 memcpy(tmp, &match.key->dst, 4); in ocelot_flower_parse_key()
735 tmp = &filter->key.ipv4.dip.mask.addr[0]; in ocelot_flower_parse_key()
736 memcpy(tmp, &match.mask->dst, 4); in ocelot_flower_parse_key()
742 return -EOPNOTSUPP; in ocelot_flower_parse_key()
748 if (filter->block_id == VCAP_ES0) { in ocelot_flower_parse_key()
751 return -EOPNOTSUPP; in ocelot_flower_parse_key()
755 filter->key.ipv4.sport.value = ntohs(match.key->src); in ocelot_flower_parse_key()
756 filter->key.ipv4.sport.mask = ntohs(match.mask->src); in ocelot_flower_parse_key()
757 filter->key.ipv4.dport.value = ntohs(match.key->dst); in ocelot_flower_parse_key()
758 filter->key.ipv4.dport.mask = ntohs(match.mask->dst); in ocelot_flower_parse_key()
764 if (filter->block_id == VCAP_ES0) { in ocelot_flower_parse_key()
767 return -EOPNOTSUPP; in ocelot_flower_parse_key()
772 return -EOPNOTSUPP; in ocelot_flower_parse_key()
773 filter->key_type = OCELOT_VCAP_KEY_ETYPE; in ocelot_flower_parse_key()
774 *(__be16 *)filter->key.etype.etype.value = htons(proto); in ocelot_flower_parse_key()
775 *(__be16 *)filter->key.etype.etype.mask = htons(0xffff); in ocelot_flower_parse_key()
782 static int ocelot_flower_parse(struct ocelot *ocelot, int port, bool ingress, in ocelot_flower_parse() argument
788 filter->prio = f->common.prio; in ocelot_flower_parse()
789 filter->id.cookie = f->cookie; in ocelot_flower_parse()
790 filter->id.tc_offload = true; in ocelot_flower_parse()
792 ret = ocelot_flower_parse_action(ocelot, port, ingress, f, filter); in ocelot_flower_parse()
797 if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD) in ocelot_flower_parse()
800 return ocelot_flower_parse_key(ocelot, port, ingress, f, filter); in ocelot_flower_parse()
804 *ocelot_vcap_filter_create(struct ocelot *ocelot, int port, bool ingress, in ocelot_vcap_filter_create() argument
814 filter->ingress_port_mask = BIT(port); in ocelot_vcap_filter_create()
816 const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0]; in ocelot_vcap_filter_create()
817 int key_length = vcap->keys[VCAP_ES0_EGR_PORT].length; in ocelot_vcap_filter_create()
819 filter->egress_port.value = port; in ocelot_vcap_filter_create()
820 filter->egress_port.mask = GENMASK(key_length - 1, 0); in ocelot_vcap_filter_create()
826 static int ocelot_vcap_dummy_filter_add(struct ocelot *ocelot, in ocelot_vcap_dummy_filter_add() argument
829 list_add(&filter->list, &ocelot->dummy_rules); in ocelot_vcap_dummy_filter_add()
834 static int ocelot_vcap_dummy_filter_del(struct ocelot *ocelot, in ocelot_vcap_dummy_filter_del() argument
837 list_del(&filter->list); in ocelot_vcap_dummy_filter_del()
852 if (filter->block_id != VCAP_ES0 || in ocelot_flower_patch_es0_vlan_modify()
853 filter->action.tag_a_vid_sel != OCELOT_ES0_VID_PLUS_CLASSIFIED_VID) in ocelot_flower_patch_es0_vlan_modify()
856 if (filter->vlan.vid.mask != VLAN_VID_MASK) { in ocelot_flower_patch_es0_vlan_modify()
859 return -EOPNOTSUPP; in ocelot_flower_patch_es0_vlan_modify()
862 filter->action.vid_a_val -= filter->vlan.vid.value; in ocelot_flower_patch_es0_vlan_modify()
863 filter->action.vid_a_val &= VLAN_VID_MASK; in ocelot_flower_patch_es0_vlan_modify()
868 int ocelot_cls_flower_replace(struct ocelot *ocelot, int port, in ocelot_cls_flower_replace() argument
871 struct netlink_ext_ack *extack = f->common.extack; in ocelot_cls_flower_replace()
873 int chain = f->common.chain_index; in ocelot_cls_flower_replace()
876 if (chain && !ocelot_find_vcap_filter_that_points_at(ocelot, chain)) { in ocelot_cls_flower_replace()
878 return -EOPNOTSUPP; in ocelot_cls_flower_replace()
884 return -EOPNOTSUPP; in ocelot_cls_flower_replace()
887 filter = ocelot_vcap_block_find_filter_by_id(&ocelot->block[block_id], in ocelot_cls_flower_replace()
888 f->cookie, true); in ocelot_cls_flower_replace()
893 return -EOPNOTSUPP; in ocelot_cls_flower_replace()
896 filter->ingress_port_mask |= BIT(port); in ocelot_cls_flower_replace()
898 return ocelot_vcap_filter_replace(ocelot, filter); in ocelot_cls_flower_replace()
902 filter = ocelot_vcap_filter_create(ocelot, port, ingress, f); in ocelot_cls_flower_replace()
904 return -ENOMEM; in ocelot_cls_flower_replace()
906 ret = ocelot_flower_parse(ocelot, port, ingress, f, filter); in ocelot_cls_flower_replace()
918 /* The non-optional GOTOs for the TCAM skeleton don't need in ocelot_cls_flower_replace()
921 if (filter->type == OCELOT_VCAP_FILTER_DUMMY) in ocelot_cls_flower_replace()
922 return ocelot_vcap_dummy_filter_add(ocelot, filter); in ocelot_cls_flower_replace()
924 if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD) { in ocelot_cls_flower_replace()
926 if (ocelot->ops->psfp_filter_add) in ocelot_cls_flower_replace()
927 return ocelot->ops->psfp_filter_add(ocelot, port, f); in ocelot_cls_flower_replace()
930 return -EOPNOTSUPP; in ocelot_cls_flower_replace()
933 return ocelot_vcap_filter_add(ocelot, filter, f->common.extack); in ocelot_cls_flower_replace()
937 int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port, in ocelot_cls_flower_destroy() argument
944 block_id = ocelot_chain_to_block(f->common.chain_index, ingress); in ocelot_cls_flower_destroy()
949 if (ocelot->ops->psfp_filter_del) in ocelot_cls_flower_destroy()
950 return ocelot->ops->psfp_filter_del(ocelot, f); in ocelot_cls_flower_destroy()
952 return -EOPNOTSUPP; in ocelot_cls_flower_destroy()
955 block = &ocelot->block[block_id]; in ocelot_cls_flower_destroy()
957 filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true); in ocelot_cls_flower_destroy()
961 if (filter->type == OCELOT_VCAP_FILTER_DUMMY) in ocelot_cls_flower_destroy()
962 return ocelot_vcap_dummy_filter_del(ocelot, filter); in ocelot_cls_flower_destroy()
965 filter->ingress_port_mask &= ~BIT(port); in ocelot_cls_flower_destroy()
966 if (filter->ingress_port_mask) in ocelot_cls_flower_destroy()
967 return ocelot_vcap_filter_replace(ocelot, filter); in ocelot_cls_flower_destroy()
970 return ocelot_vcap_filter_del(ocelot, filter); in ocelot_cls_flower_destroy()
974 int ocelot_cls_flower_stats(struct ocelot *ocelot, int port, in ocelot_cls_flower_stats() argument
982 block_id = ocelot_chain_to_block(f->common.chain_index, ingress); in ocelot_cls_flower_stats()
987 if (ocelot->ops->psfp_stats_get) { in ocelot_cls_flower_stats()
988 ret = ocelot->ops->psfp_stats_get(ocelot, f, &stats); in ocelot_cls_flower_stats()
995 return -EOPNOTSUPP; in ocelot_cls_flower_stats()
998 block = &ocelot->block[block_id]; in ocelot_cls_flower_stats()
1000 filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true); in ocelot_cls_flower_stats()
1001 if (!filter || filter->type == OCELOT_VCAP_FILTER_DUMMY) in ocelot_cls_flower_stats()
1004 ret = ocelot_vcap_filter_stats_update(ocelot, filter); in ocelot_cls_flower_stats()
1008 stats.pkts = filter->stats.pkts; in ocelot_cls_flower_stats()
1011 flow_stats_update(&f->stats, 0x0, stats.pkts, stats.drops, 0x0, in ocelot_cls_flower_stats()