Lines Matching +full:int +full:- +full:fwd +full:- +full:mask
1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
17 void enetc_sched_speed_set(struct enetc_ndev_priv *priv, int speed) in enetc_sched_speed_set()
19 struct enetc_hw *hw = &priv->si->hw; in enetc_sched_speed_set()
20 u32 old_speed = priv->speed; in enetc_sched_speed_set()
41 priv->speed = speed; in enetc_sched_speed_set()
46 static int enetc_setup_taprio(struct enetc_ndev_priv *priv, in enetc_setup_taprio()
49 struct enetc_hw *hw = &priv->si->hw; in enetc_setup_taprio()
59 int err; in enetc_setup_taprio()
60 int i; in enetc_setup_taprio()
63 for (i = 0; i < priv->num_tx_rings; i++) in enetc_setup_taprio()
64 if (priv->tx_ring[i]->tsd_enable) in enetc_setup_taprio()
65 return -EBUSY; in enetc_setup_taprio()
67 if (admin_conf->num_entries > enetc_get_max_gcl_len(hw)) in enetc_setup_taprio()
68 return -EINVAL; in enetc_setup_taprio()
70 if (admin_conf->cycle_time > U32_MAX || in enetc_setup_taprio()
71 admin_conf->cycle_time_extension > U32_MAX) in enetc_setup_taprio()
72 return -EINVAL; in enetc_setup_taprio()
78 gcl_len = admin_conf->num_entries; in enetc_setup_taprio()
81 tmp = enetc_cbd_alloc_data_mem(priv->si, &cbd, data_size, in enetc_setup_taprio()
84 return -ENOMEM; in enetc_setup_taprio()
89 gcl_config->atc = 0xff; in enetc_setup_taprio()
90 gcl_config->acl_len = cpu_to_le16(gcl_len); in enetc_setup_taprio()
92 gcl_data->btl = cpu_to_le32(lower_32_bits(admin_conf->base_time)); in enetc_setup_taprio()
93 gcl_data->bth = cpu_to_le32(upper_32_bits(admin_conf->base_time)); in enetc_setup_taprio()
94 gcl_data->ct = cpu_to_le32(admin_conf->cycle_time); in enetc_setup_taprio()
95 gcl_data->cte = cpu_to_le32(admin_conf->cycle_time_extension); in enetc_setup_taprio()
101 temp_entry = &admin_conf->entries[i]; in enetc_setup_taprio()
103 temp_gce->gate = (u8)temp_entry->gate_mask; in enetc_setup_taprio()
104 temp_gce->period = cpu_to_le32(temp_entry->interval); in enetc_setup_taprio()
115 err = enetc_send_cmd(priv->si, &cbd); in enetc_setup_taprio()
119 enetc_cbd_free_data_mem(priv->si, data_size, tmp, &dma); in enetc_setup_taprio()
124 enetc_set_ptcmsdur(hw, admin_conf->max_sdu); in enetc_setup_taprio()
125 priv->active_offloads |= ENETC_F_QBV; in enetc_setup_taprio()
132 int i; in enetc_reset_taprio_stats()
134 for (i = 0; i < priv->num_tx_rings; i++) in enetc_reset_taprio_stats()
135 priv->tx_ring[i]->stats.win_drop = 0; in enetc_reset_taprio_stats()
140 struct enetc_hw *hw = &priv->si->hw; in enetc_reset_taprio()
147 priv->active_offloads &= ~ENETC_F_QBV; in enetc_reset_taprio()
164 int i; in enetc_taprio_stats()
166 for (i = 0; i < priv->num_tx_rings; i++) in enetc_taprio_stats()
167 window_drops += priv->tx_ring[i]->stats.win_drop; in enetc_taprio_stats()
169 stats->window_drops = window_drops; in enetc_taprio_stats()
175 struct tc_taprio_qopt_stats *stats = &queue_stats->stats; in enetc_taprio_queue_stats()
177 int queue = queue_stats->queue; in enetc_taprio_queue_stats()
179 stats->window_drops = priv->tx_ring[queue]->stats.win_drop; in enetc_taprio_queue_stats()
182 static int enetc_taprio_replace(struct net_device *ndev, in enetc_taprio_replace()
186 int err; in enetc_taprio_replace()
188 err = enetc_setup_tc_mqprio(ndev, &offload->mqprio); in enetc_taprio_replace()
199 int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data) in enetc_setup_tc_taprio()
202 int err = 0; in enetc_setup_tc_taprio()
204 switch (offload->cmd) { in enetc_setup_tc_taprio()
212 enetc_taprio_stats(ndev, &offload->stats); in enetc_setup_tc_taprio()
215 enetc_taprio_queue_stats(ndev, &offload->queue_stats); in enetc_setup_tc_taprio()
218 err = -EOPNOTSUPP; in enetc_setup_tc_taprio()
234 int enetc_setup_tc_cbs(struct net_device *ndev, void *type_data) in enetc_setup_tc_cbs()
238 u32 port_transmit_rate = priv->speed; in enetc_setup_tc_cbs()
240 struct enetc_hw *hw = &priv->si->hw; in enetc_setup_tc_cbs()
244 u8 tc = cbs->queue; in enetc_setup_tc_cbs()
246 int bw_sum = 0; in enetc_setup_tc_cbs()
249 prio_top = tc_nums - 1; in enetc_setup_tc_cbs()
250 prio_next = tc_nums - 2; in enetc_setup_tc_cbs()
254 return -EOPNOTSUPP; in enetc_setup_tc_cbs()
256 if (!cbs->enable) { in enetc_setup_tc_cbs()
262 dev_err(&ndev->dev, in enetc_setup_tc_cbs()
265 return -EINVAL; in enetc_setup_tc_cbs()
274 if (cbs->idleslope - cbs->sendslope != port_transmit_rate * 1000L || in enetc_setup_tc_cbs()
275 cbs->idleslope < 0 || cbs->sendslope > 0) in enetc_setup_tc_cbs()
276 return -EOPNOTSUPP; in enetc_setup_tc_cbs()
278 port_frame_max_size = ndev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; in enetc_setup_tc_cbs()
280 bw = cbs->idleslope / (port_transmit_rate * 10UL); in enetc_setup_tc_cbs()
287 dev_err(&ndev->dev, in enetc_setup_tc_cbs()
290 return -EINVAL; in enetc_setup_tc_cbs()
296 dev_err(&ndev->dev, in enetc_setup_tc_cbs()
298 return -EINVAL; in enetc_setup_tc_cbs()
307 * max_interference_size = M0 + Ma + Ra * M0 / (R0 - Ra) in enetc_setup_tc_cbs()
309 * - RA: idleSlope for AVB Class A in enetc_setup_tc_cbs()
310 * - R0: port transmit rate in enetc_setup_tc_cbs()
311 * - M0: maximum sized frame for the port in enetc_setup_tc_cbs()
312 * - MA: maximum sized frame for AVB Class A in enetc_setup_tc_cbs()
326 (u32)div_u64((u64)ra * m0, r0 - ra); in enetc_setup_tc_cbs()
350 int enetc_setup_tc_txtime(struct net_device *ndev, void *type_data) in enetc_setup_tc_txtime()
355 struct enetc_hw *hw = &priv->si->hw; in enetc_setup_tc_txtime()
356 int tc; in enetc_setup_tc_txtime()
359 return -EOPNOTSUPP; in enetc_setup_tc_txtime()
361 tc = qopt->queue; in enetc_setup_tc_txtime()
363 if (tc < 0 || tc >= priv->num_tx_rings) in enetc_setup_tc_txtime()
364 return -EINVAL; in enetc_setup_tc_txtime()
368 return -EBUSY; in enetc_setup_tc_txtime()
370 priv->tx_ring[tc]->tsd_enable = qopt->enable; in enetc_setup_tc_txtime()
371 enetc_port_wr(hw, ENETC_PTCTSDR(tc), qopt->enable ? ENETC_TSDE : 0); in enetc_setup_tc_txtime()
389 #define ENETC_PSFP_WILDCARD -1
511 static int enetc_streamid_hw_set(struct enetc_ndev_priv *priv, in enetc_streamid_hw_set()
521 int port; in enetc_streamid_hw_set()
522 int err; in enetc_streamid_hw_set()
524 port = enetc_pf_to_port(priv->si->pdev); in enetc_streamid_hw_set()
526 return -EINVAL; in enetc_streamid_hw_set()
528 if (sid->index >= priv->psfp_cap.max_streamid) in enetc_streamid_hw_set()
529 return -EINVAL; in enetc_streamid_hw_set()
531 if (sid->filtertype != STREAMID_TYPE_NULL && in enetc_streamid_hw_set()
532 sid->filtertype != STREAMID_TYPE_SMAC) in enetc_streamid_hw_set()
533 return -EOPNOTSUPP; in enetc_streamid_hw_set()
536 cbd.index = cpu_to_le16((u16)sid->index); in enetc_streamid_hw_set()
541 tmp = enetc_cbd_alloc_data_mem(priv->si, &cbd, data_size, in enetc_streamid_hw_set()
544 return -ENOMEM; in enetc_streamid_hw_set()
546 eth_broadcast_addr(si_data->dmac); in enetc_streamid_hw_set()
547 si_data->vid_vidm_tg = (ENETC_CBDR_SID_VID_MASK in enetc_streamid_hw_set()
552 si_conf->iports = cpu_to_le32(1 << port); in enetc_streamid_hw_set()
553 si_conf->id_type = 1; in enetc_streamid_hw_set()
554 si_conf->oui[2] = 0x0; in enetc_streamid_hw_set()
555 si_conf->oui[1] = 0x80; in enetc_streamid_hw_set()
556 si_conf->oui[0] = 0xC2; in enetc_streamid_hw_set()
558 err = enetc_send_cmd(priv->si, &cbd); in enetc_streamid_hw_set()
568 si_conf->en = 0x80; in enetc_streamid_hw_set()
569 si_conf->stream_handle = cpu_to_le32(sid->handle); in enetc_streamid_hw_set()
570 si_conf->iports = cpu_to_le32(1 << port); in enetc_streamid_hw_set()
571 si_conf->id_type = sid->filtertype; in enetc_streamid_hw_set()
572 si_conf->oui[2] = 0x0; in enetc_streamid_hw_set()
573 si_conf->oui[1] = 0x80; in enetc_streamid_hw_set()
574 si_conf->oui[0] = 0xC2; in enetc_streamid_hw_set()
583 if (si_conf->id_type == STREAMID_TYPE_NULL) { in enetc_streamid_hw_set()
584 ether_addr_copy(si_data->dmac, sid->dst_mac); in enetc_streamid_hw_set()
585 si_data->vid_vidm_tg = (sid->vid & ENETC_CBDR_SID_VID_MASK) + in enetc_streamid_hw_set()
586 ((((u16)(sid->tagged) & 0x3) << 14) in enetc_streamid_hw_set()
588 } else if (si_conf->id_type == STREAMID_TYPE_SMAC) { in enetc_streamid_hw_set()
589 ether_addr_copy(si_data->smac, sid->src_mac); in enetc_streamid_hw_set()
590 si_data->vid_vidm_tg = (sid->vid & ENETC_CBDR_SID_VID_MASK) + in enetc_streamid_hw_set()
591 ((((u16)(sid->tagged) & 0x3) << 14) in enetc_streamid_hw_set()
595 err = enetc_send_cmd(priv->si, &cbd); in enetc_streamid_hw_set()
597 enetc_cbd_free_data_mem(priv->si, data_size, tmp, &dma); in enetc_streamid_hw_set()
603 static int enetc_streamfilter_hw_set(struct enetc_ndev_priv *priv, in enetc_streamfilter_hw_set()
609 int port; in enetc_streamfilter_hw_set()
611 port = enetc_pf_to_port(priv->si->pdev); in enetc_streamfilter_hw_set()
613 return -EINVAL; in enetc_streamfilter_hw_set()
615 cbd.index = cpu_to_le16(sfi->index); in enetc_streamfilter_hw_set()
624 sfi_config->en = 0x80; in enetc_streamfilter_hw_set()
626 if (sfi->handle >= 0) { in enetc_streamfilter_hw_set()
627 sfi_config->stream_handle = in enetc_streamfilter_hw_set()
628 cpu_to_le32(sfi->handle); in enetc_streamfilter_hw_set()
629 sfi_config->sthm |= 0x80; in enetc_streamfilter_hw_set()
632 sfi_config->sg_inst_table_index = cpu_to_le16(sfi->gate_id); in enetc_streamfilter_hw_set()
633 sfi_config->input_ports = cpu_to_le32(1 << port); in enetc_streamfilter_hw_set()
638 if (sfi->prio >= 0) in enetc_streamfilter_hw_set()
639 sfi_config->multi |= (sfi->prio & 0x7) | 0x8; in enetc_streamfilter_hw_set()
645 if (sfi->maxsdu) { in enetc_streamfilter_hw_set()
646 sfi_config->msdu = in enetc_streamfilter_hw_set()
647 cpu_to_le16(sfi->maxsdu); in enetc_streamfilter_hw_set()
648 sfi_config->multi |= 0x40; in enetc_streamfilter_hw_set()
651 if (sfi->meter_id >= 0) { in enetc_streamfilter_hw_set()
652 sfi_config->fm_inst_table_index = cpu_to_le16(sfi->meter_id); in enetc_streamfilter_hw_set()
653 sfi_config->multi |= 0x80; in enetc_streamfilter_hw_set()
657 return enetc_send_cmd(priv->si, &cbd); in enetc_streamfilter_hw_set()
660 static int enetc_streamcounter_hw_get(struct enetc_ndev_priv *priv, in enetc_streamcounter_hw_get()
669 int err; in enetc_streamcounter_hw_get()
678 tmp = enetc_cbd_alloc_data_mem(priv->si, &cbd, data_size, in enetc_streamcounter_hw_get()
681 return -ENOMEM; in enetc_streamcounter_hw_get()
683 err = enetc_send_cmd(priv->si, &cbd); in enetc_streamcounter_hw_get()
687 cnt->matching_frames_count = ((u64)data_buf->matchh << 32) + in enetc_streamcounter_hw_get()
688 data_buf->matchl; in enetc_streamcounter_hw_get()
690 cnt->not_passing_sdu_count = ((u64)data_buf->msdu_droph << 32) + in enetc_streamcounter_hw_get()
691 data_buf->msdu_dropl; in enetc_streamcounter_hw_get()
693 cnt->passing_sdu_count = cnt->matching_frames_count in enetc_streamcounter_hw_get()
694 - cnt->not_passing_sdu_count; in enetc_streamcounter_hw_get()
696 cnt->not_passing_frames_count = in enetc_streamcounter_hw_get()
697 ((u64)data_buf->stream_gate_droph << 32) + in enetc_streamcounter_hw_get()
698 data_buf->stream_gate_dropl; in enetc_streamcounter_hw_get()
700 cnt->passing_frames_count = cnt->matching_frames_count - in enetc_streamcounter_hw_get()
701 cnt->not_passing_sdu_count - in enetc_streamcounter_hw_get()
702 cnt->not_passing_frames_count; in enetc_streamcounter_hw_get()
704 cnt->red_frames_count = ((u64)data_buf->flow_meter_droph << 32) + in enetc_streamcounter_hw_get()
705 data_buf->flow_meter_dropl; in enetc_streamcounter_hw_get()
708 enetc_cbd_free_data_mem(priv->si, data_size, tmp, &dma); in enetc_streamcounter_hw_get()
724 static int get_start_ns(u64 now, u64 cycle, u64 *start) in get_start_ns()
729 return -EFAULT; in get_start_ns()
739 static int enetc_streamgate_hw_set(struct enetc_ndev_priv *priv, in enetc_streamgate_hw_set()
750 int err, i; in enetc_streamgate_hw_set()
754 cbd.index = cpu_to_le16(sgi->index); in enetc_streamgate_hw_set()
761 return enetc_send_cmd(priv->si, &cbd); in enetc_streamgate_hw_set()
763 if (!sgi->num_entries) in enetc_streamgate_hw_set()
766 if (sgi->num_entries > priv->psfp_cap.max_psfp_gatelist || in enetc_streamgate_hw_set()
767 !sgi->cycletime) in enetc_streamgate_hw_set()
768 return -EINVAL; in enetc_streamgate_hw_set()
774 sgi_config->ocgtst = 0x80; in enetc_streamgate_hw_set()
776 sgi_config->oipv = (sgi->init_ipv < 0) ? in enetc_streamgate_hw_set()
777 0x0 : ((sgi->init_ipv & 0x7) | 0x8); in enetc_streamgate_hw_set()
779 sgi_config->en = 0x80; in enetc_streamgate_hw_set()
782 err = enetc_send_cmd(priv->si, &cbd); in enetc_streamgate_hw_set()
784 return -EINVAL; in enetc_streamgate_hw_set()
788 cbd.index = cpu_to_le16(sgi->index); in enetc_streamgate_hw_set()
795 sgcl_config->acl_len = (sgi->num_entries - 1) & 0x3; in enetc_streamgate_hw_set()
797 data_size = struct_size(sgcl_data, sgcl, sgi->num_entries); in enetc_streamgate_hw_set()
798 tmp = enetc_cbd_alloc_data_mem(priv->si, &cbd, data_size, in enetc_streamgate_hw_set()
801 return -ENOMEM; in enetc_streamgate_hw_set()
803 sgce = &sgcl_data->sgcl[0]; in enetc_streamgate_hw_set()
805 sgcl_config->agtst = 0x80; in enetc_streamgate_hw_set()
807 sgcl_data->ct = sgi->cycletime; in enetc_streamgate_hw_set()
808 sgcl_data->cte = sgi->cycletimext; in enetc_streamgate_hw_set()
810 if (sgi->init_ipv >= 0) in enetc_streamgate_hw_set()
811 sgcl_config->aipv = (sgi->init_ipv & 0x7) | 0x8; in enetc_streamgate_hw_set()
813 for (i = 0; i < sgi->num_entries; i++) { in enetc_streamgate_hw_set()
814 struct action_gate_entry *from = &sgi->entries[i]; in enetc_streamgate_hw_set()
817 if (from->gate_state) in enetc_streamgate_hw_set()
818 to->multi |= 0x10; in enetc_streamgate_hw_set()
820 if (from->ipv >= 0) in enetc_streamgate_hw_set()
821 to->multi |= ((from->ipv & 0x7) << 5) | 0x08; in enetc_streamgate_hw_set()
823 if (from->maxoctets >= 0) { in enetc_streamgate_hw_set()
824 to->multi |= 0x01; in enetc_streamgate_hw_set()
825 to->msdu[0] = from->maxoctets & 0xFF; in enetc_streamgate_hw_set()
826 to->msdu[1] = (from->maxoctets >> 8) & 0xFF; in enetc_streamgate_hw_set()
827 to->msdu[2] = (from->maxoctets >> 16) & 0xFF; in enetc_streamgate_hw_set()
830 to->interval = from->interval; in enetc_streamgate_hw_set()
834 now = get_ptp_now(&priv->si->hw); in enetc_streamgate_hw_set()
836 if (sgi->basetime < now) { in enetc_streamgate_hw_set()
839 err = get_start_ns(now, sgi->cycletime, &start); in enetc_streamgate_hw_set()
842 sgcl_data->btl = lower_32_bits(start); in enetc_streamgate_hw_set()
843 sgcl_data->bth = upper_32_bits(start); in enetc_streamgate_hw_set()
847 hi = upper_32_bits(sgi->basetime); in enetc_streamgate_hw_set()
848 lo = lower_32_bits(sgi->basetime); in enetc_streamgate_hw_set()
849 sgcl_data->bth = hi; in enetc_streamgate_hw_set()
850 sgcl_data->btl = lo; in enetc_streamgate_hw_set()
853 err = enetc_send_cmd(priv->si, &cbd); in enetc_streamgate_hw_set()
856 enetc_cbd_free_data_mem(priv->si, data_size, tmp, &dma); in enetc_streamgate_hw_set()
860 static int enetc_flowmeter_hw_set(struct enetc_ndev_priv *priv, in enetc_flowmeter_hw_set()
868 cbd.index = cpu_to_le16((u16)fmi->index); in enetc_flowmeter_hw_set()
873 return enetc_send_cmd(priv->si, &cbd); in enetc_flowmeter_hw_set()
876 fmi_config->en = 0x80; in enetc_flowmeter_hw_set()
878 if (fmi->cir) { in enetc_flowmeter_hw_set()
879 temp = (u64)8000 * fmi->cir; in enetc_flowmeter_hw_set()
883 fmi_config->cir = cpu_to_le32((u32)temp); in enetc_flowmeter_hw_set()
884 fmi_config->cbs = cpu_to_le32(fmi->cbs); in enetc_flowmeter_hw_set()
887 fmi_config->eir = 0; in enetc_flowmeter_hw_set()
888 fmi_config->ebs = 0; in enetc_flowmeter_hw_set()
896 fmi_config->conf = 0; in enetc_flowmeter_hw_set()
898 return enetc_send_cmd(priv->si, &cbd); in enetc_flowmeter_hw_set()
906 if (f->sid.index == index) in enetc_get_stream_by_index()
917 if (g->index == index) in enetc_get_gate_by_index()
928 if (s->index == index) in enetc_get_filter_by_index()
939 if (m->index == index) in enetc_get_meter_by_index()
951 if (s->gate_id == sfi->gate_id && in enetc_psfp_check_sfi()
952 s->prio == sfi->prio && in enetc_psfp_check_sfi()
953 s->maxsdu == sfi->maxsdu && in enetc_psfp_check_sfi()
954 s->meter_id == sfi->meter_id) in enetc_psfp_check_sfi()
960 static int enetc_get_free_index(struct enetc_ndev_priv *priv) in enetc_get_free_index()
962 u32 max_size = priv->psfp_cap.max_psfp_filter; in enetc_get_free_index()
967 return -1; in enetc_get_free_index()
979 z = refcount_dec_and_test(&sfi->refcount); in stream_filter_unref()
983 hlist_del(&sfi->node); in stream_filter_unref()
996 z = refcount_dec_and_test(&sgi->refcount); in stream_gate_unref()
999 hlist_del(&sgi->node); in stream_gate_unref()
1011 z = refcount_dec_and_test(&fmi->refcount); in flow_meter_unref()
1014 hlist_del(&fmi->node); in flow_meter_unref()
1022 if (filter->flags & ENETC_PSFP_FLAGS_FMI) in remove_one_chain()
1023 flow_meter_unref(priv, filter->fmi_index); in remove_one_chain()
1025 stream_gate_unref(priv, filter->sgi_index); in remove_one_chain()
1026 stream_filter_unref(priv, filter->sfi_index); in remove_one_chain()
1028 hlist_del(&filter->node); in remove_one_chain()
1032 static int enetc_psfp_hw_set(struct enetc_ndev_priv *priv, in enetc_psfp_hw_set()
1038 int err; in enetc_psfp_hw_set()
1075 int i; in enetc_check_flow_actions()
1085 static int enetc_psfp_policer_validate(const struct flow_action *action, in enetc_psfp_policer_validate()
1089 if (act->police.exceed.act_id != FLOW_ACTION_DROP) { in enetc_psfp_policer_validate()
1092 return -EOPNOTSUPP; in enetc_psfp_policer_validate()
1095 if (act->police.notexceed.act_id != FLOW_ACTION_PIPE && in enetc_psfp_policer_validate()
1096 act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) { in enetc_psfp_policer_validate()
1099 return -EOPNOTSUPP; in enetc_psfp_policer_validate()
1102 if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT && in enetc_psfp_policer_validate()
1106 return -EOPNOTSUPP; in enetc_psfp_policer_validate()
1109 if (act->police.peakrate_bytes_ps || in enetc_psfp_policer_validate()
1110 act->police.avrate || act->police.overhead) { in enetc_psfp_policer_validate()
1113 return -EOPNOTSUPP; in enetc_psfp_policer_validate()
1116 if (act->police.rate_pkt_ps) { in enetc_psfp_policer_validate()
1119 return -EOPNOTSUPP; in enetc_psfp_policer_validate()
1125 static int enetc_psfp_parse_clsflower(struct enetc_ndev_priv *priv, in enetc_psfp_parse_clsflower()
1130 struct netlink_ext_ack *extack = f->common.extack; in enetc_psfp_parse_clsflower()
1138 int entries_size; in enetc_psfp_parse_clsflower()
1139 int i, err; in enetc_psfp_parse_clsflower()
1141 if (f->common.chain_index >= priv->psfp_cap.max_streamid) { in enetc_psfp_parse_clsflower()
1143 return -ENOSPC; in enetc_psfp_parse_clsflower()
1146 flow_action_for_each(i, entry, &rule->action) in enetc_psfp_parse_clsflower()
1147 if (entry->id == FLOW_ACTION_GATE) in enetc_psfp_parse_clsflower()
1149 else if (entry->id == FLOW_ACTION_POLICE) in enetc_psfp_parse_clsflower()
1154 return -EINVAL; in enetc_psfp_parse_clsflower()
1158 return -ENOMEM; in enetc_psfp_parse_clsflower()
1160 filter->sid.index = f->common.chain_index; in enetc_psfp_parse_clsflower()
1167 if (!is_zero_ether_addr(match.mask->dst) && in enetc_psfp_parse_clsflower()
1168 !is_zero_ether_addr(match.mask->src)) { in enetc_psfp_parse_clsflower()
1171 err = -EINVAL; in enetc_psfp_parse_clsflower()
1175 if (!is_zero_ether_addr(match.mask->dst)) { in enetc_psfp_parse_clsflower()
1176 if (!is_broadcast_ether_addr(match.mask->dst)) { in enetc_psfp_parse_clsflower()
1179 err = -EINVAL; in enetc_psfp_parse_clsflower()
1182 ether_addr_copy(filter->sid.dst_mac, match.key->dst); in enetc_psfp_parse_clsflower()
1183 filter->sid.filtertype = STREAMID_TYPE_NULL; in enetc_psfp_parse_clsflower()
1186 if (!is_zero_ether_addr(match.mask->src)) { in enetc_psfp_parse_clsflower()
1187 if (!is_broadcast_ether_addr(match.mask->src)) { in enetc_psfp_parse_clsflower()
1190 err = -EINVAL; in enetc_psfp_parse_clsflower()
1193 ether_addr_copy(filter->sid.src_mac, match.key->src); in enetc_psfp_parse_clsflower()
1194 filter->sid.filtertype = STREAMID_TYPE_SMAC; in enetc_psfp_parse_clsflower()
1198 err = -EINVAL; in enetc_psfp_parse_clsflower()
1206 if (match.mask->vlan_priority) { in enetc_psfp_parse_clsflower()
1207 if (match.mask->vlan_priority != in enetc_psfp_parse_clsflower()
1209 NL_SET_ERR_MSG_MOD(extack, "Only full mask is supported for VLAN priority"); in enetc_psfp_parse_clsflower()
1210 err = -EINVAL; in enetc_psfp_parse_clsflower()
1215 if (match.mask->vlan_id) { in enetc_psfp_parse_clsflower()
1216 if (match.mask->vlan_id != VLAN_VID_MASK) { in enetc_psfp_parse_clsflower()
1217 NL_SET_ERR_MSG_MOD(extack, "Only full mask is supported for VLAN id"); in enetc_psfp_parse_clsflower()
1218 err = -EINVAL; in enetc_psfp_parse_clsflower()
1222 filter->sid.vid = match.key->vlan_id; in enetc_psfp_parse_clsflower()
1223 if (!filter->sid.vid) in enetc_psfp_parse_clsflower()
1224 filter->sid.tagged = STREAMID_VLAN_UNTAGGED; in enetc_psfp_parse_clsflower()
1226 filter->sid.tagged = STREAMID_VLAN_TAGGED; in enetc_psfp_parse_clsflower()
1229 filter->sid.tagged = STREAMID_VLAN_ALL; in enetc_psfp_parse_clsflower()
1233 if (entryg->hw_index >= priv->psfp_cap.max_psfp_gate) { in enetc_psfp_parse_clsflower()
1235 err = -ENOSPC; in enetc_psfp_parse_clsflower()
1239 if (entryg->gate.num_entries >= priv->psfp_cap.max_psfp_gatelist) { in enetc_psfp_parse_clsflower()
1241 err = -ENOSPC; in enetc_psfp_parse_clsflower()
1245 entries_size = struct_size(sgi, entries, entryg->gate.num_entries); in enetc_psfp_parse_clsflower()
1248 err = -ENOMEM; in enetc_psfp_parse_clsflower()
1252 refcount_set(&sgi->refcount, 1); in enetc_psfp_parse_clsflower()
1253 sgi->index = entryg->hw_index; in enetc_psfp_parse_clsflower()
1254 sgi->init_ipv = entryg->gate.prio; in enetc_psfp_parse_clsflower()
1255 sgi->basetime = entryg->gate.basetime; in enetc_psfp_parse_clsflower()
1256 sgi->cycletime = entryg->gate.cycletime; in enetc_psfp_parse_clsflower()
1257 sgi->num_entries = entryg->gate.num_entries; in enetc_psfp_parse_clsflower()
1259 e = sgi->entries; in enetc_psfp_parse_clsflower()
1260 for (i = 0; i < entryg->gate.num_entries; i++) { in enetc_psfp_parse_clsflower()
1261 e[i].gate_state = entryg->gate.entries[i].gate_state; in enetc_psfp_parse_clsflower()
1262 e[i].interval = entryg->gate.entries[i].interval; in enetc_psfp_parse_clsflower()
1263 e[i].ipv = entryg->gate.entries[i].ipv; in enetc_psfp_parse_clsflower()
1264 e[i].maxoctets = entryg->gate.entries[i].maxoctets; in enetc_psfp_parse_clsflower()
1267 filter->sgi_index = sgi->index; in enetc_psfp_parse_clsflower()
1271 err = -ENOMEM; in enetc_psfp_parse_clsflower()
1275 refcount_set(&sfi->refcount, 1); in enetc_psfp_parse_clsflower()
1276 sfi->gate_id = sgi->index; in enetc_psfp_parse_clsflower()
1277 sfi->meter_id = ENETC_PSFP_WILDCARD; in enetc_psfp_parse_clsflower()
1281 err = enetc_psfp_policer_validate(&rule->action, entryp, extack); in enetc_psfp_parse_clsflower()
1285 if (entryp->police.burst) { in enetc_psfp_parse_clsflower()
1288 err = -ENOMEM; in enetc_psfp_parse_clsflower()
1291 refcount_set(&fmi->refcount, 1); in enetc_psfp_parse_clsflower()
1292 fmi->cir = entryp->police.rate_bytes_ps; in enetc_psfp_parse_clsflower()
1293 fmi->cbs = entryp->police.burst; in enetc_psfp_parse_clsflower()
1294 fmi->index = entryp->hw_index; in enetc_psfp_parse_clsflower()
1295 filter->flags |= ENETC_PSFP_FLAGS_FMI; in enetc_psfp_parse_clsflower()
1296 filter->fmi_index = fmi->index; in enetc_psfp_parse_clsflower()
1297 sfi->meter_id = fmi->index; in enetc_psfp_parse_clsflower()
1300 if (entryp->police.mtu) in enetc_psfp_parse_clsflower()
1301 sfi->maxsdu = entryp->police.mtu; in enetc_psfp_parse_clsflower()
1305 if (f->common.prio && f->common.prio <= BIT(3)) in enetc_psfp_parse_clsflower()
1306 sfi->prio = f->common.prio - 1; in enetc_psfp_parse_clsflower()
1308 sfi->prio = ENETC_PSFP_WILDCARD; in enetc_psfp_parse_clsflower()
1312 int index; in enetc_psfp_parse_clsflower()
1317 err = -ENOSPC; in enetc_psfp_parse_clsflower()
1321 sfi->index = index; in enetc_psfp_parse_clsflower()
1322 sfi->handle = index + HANDLE_OFFSET; in enetc_psfp_parse_clsflower()
1324 filter->sid.handle = sfi->handle; in enetc_psfp_parse_clsflower()
1325 filter->sfi_index = sfi->index; in enetc_psfp_parse_clsflower()
1328 filter->sfi_index = old_sfi->index; in enetc_psfp_parse_clsflower()
1329 filter->sid.handle = old_sfi->handle; in enetc_psfp_parse_clsflower()
1333 err = enetc_psfp_hw_set(priv, &filter->sid, in enetc_psfp_parse_clsflower()
1339 if (filter->flags & ENETC_PSFP_FLAGS_FMI) { in enetc_psfp_parse_clsflower()
1340 old_fmi = enetc_get_meter_by_index(filter->fmi_index); in enetc_psfp_parse_clsflower()
1342 fmi->refcount = old_fmi->refcount; in enetc_psfp_parse_clsflower()
1343 refcount_set(&fmi->refcount, in enetc_psfp_parse_clsflower()
1344 refcount_read(&old_fmi->refcount) + 1); in enetc_psfp_parse_clsflower()
1345 hlist_del(&old_fmi->node); in enetc_psfp_parse_clsflower()
1348 hlist_add_head(&fmi->node, &epsfp.psfp_meter_list); in enetc_psfp_parse_clsflower()
1352 old_sgi = enetc_get_gate_by_index(filter->sgi_index); in enetc_psfp_parse_clsflower()
1354 refcount_set(&sgi->refcount, in enetc_psfp_parse_clsflower()
1355 refcount_read(&old_sgi->refcount) + 1); in enetc_psfp_parse_clsflower()
1356 hlist_del(&old_sgi->node); in enetc_psfp_parse_clsflower()
1360 hlist_add_head(&sgi->node, &epsfp.psfp_gate_list); in enetc_psfp_parse_clsflower()
1363 hlist_add_head(&sfi->node, &epsfp.psfp_filter_list); in enetc_psfp_parse_clsflower()
1364 set_bit(sfi->index, epsfp.psfp_sfi_bitmap); in enetc_psfp_parse_clsflower()
1367 refcount_inc(&old_sfi->refcount); in enetc_psfp_parse_clsflower()
1370 old_filter = enetc_get_stream_by_index(filter->sid.index); in enetc_psfp_parse_clsflower()
1374 filter->stats.lastused = jiffies; in enetc_psfp_parse_clsflower()
1375 hlist_add_head(&filter->node, &epsfp.stream_list); in enetc_psfp_parse_clsflower()
1393 static int enetc_config_clsflower(struct enetc_ndev_priv *priv, in enetc_config_clsflower()
1397 struct netlink_ext_ack *extack = cls_flower->common.extack; in enetc_config_clsflower()
1398 struct flow_dissector *dissector = rule->match.dissector; in enetc_config_clsflower()
1399 struct flow_action *action = &rule->action; in enetc_config_clsflower()
1401 struct actions_fwd *fwd; in enetc_config_clsflower() local
1403 int i, err; in enetc_config_clsflower()
1407 return -EINVAL; in enetc_config_clsflower()
1411 actions |= BIT(entry->id); in enetc_config_clsflower()
1413 fwd = enetc_check_flow_actions(actions, dissector->used_keys); in enetc_config_clsflower()
1414 if (!fwd) { in enetc_config_clsflower()
1416 return -EOPNOTSUPP; in enetc_config_clsflower()
1419 if (fwd->output & FILTER_ACTION_TYPE_PSFP) { in enetc_config_clsflower()
1427 return -EOPNOTSUPP; in enetc_config_clsflower()
1433 static int enetc_psfp_destroy_clsflower(struct enetc_ndev_priv *priv, in enetc_psfp_destroy_clsflower()
1437 struct netlink_ext_ack *extack = f->common.extack; in enetc_psfp_destroy_clsflower()
1438 int err; in enetc_psfp_destroy_clsflower()
1440 if (f->common.chain_index >= priv->psfp_cap.max_streamid) { in enetc_psfp_destroy_clsflower()
1442 return -ENOSPC; in enetc_psfp_destroy_clsflower()
1445 filter = enetc_get_stream_by_index(f->common.chain_index); in enetc_psfp_destroy_clsflower()
1447 return -EINVAL; in enetc_psfp_destroy_clsflower()
1449 err = enetc_streamid_hw_set(priv, &filter->sid, false); in enetc_psfp_destroy_clsflower()
1458 static int enetc_destroy_clsflower(struct enetc_ndev_priv *priv, in enetc_destroy_clsflower()
1464 static int enetc_psfp_get_stats(struct enetc_ndev_priv *priv, in enetc_psfp_get_stats()
1470 int err; in enetc_psfp_get_stats()
1472 filter = enetc_get_stream_by_index(f->common.chain_index); in enetc_psfp_get_stats()
1474 return -EINVAL; in enetc_psfp_get_stats()
1476 err = enetc_streamcounter_hw_get(priv, filter->sfi_index, &counters); in enetc_psfp_get_stats()
1478 return -EINVAL; in enetc_psfp_get_stats()
1482 counters.not_passing_sdu_count - in enetc_psfp_get_stats()
1483 filter->stats.pkts; in enetc_psfp_get_stats()
1486 counters.red_frames_count - in enetc_psfp_get_stats()
1487 filter->stats.drops; in enetc_psfp_get_stats()
1488 stats.lastused = filter->stats.lastused; in enetc_psfp_get_stats()
1489 filter->stats.pkts += stats.pkts; in enetc_psfp_get_stats()
1490 filter->stats.drops += stats.drops; in enetc_psfp_get_stats()
1493 flow_stats_update(&f->stats, 0x0, stats.pkts, stats.drops, in enetc_psfp_get_stats()
1499 static int enetc_setup_tc_cls_flower(struct enetc_ndev_priv *priv, in enetc_setup_tc_cls_flower()
1502 switch (cls_flower->command) { in enetc_setup_tc_cls_flower()
1510 return -EOPNOTSUPP; in enetc_setup_tc_cls_flower()
1526 hlist_del(&s->node); in clean_stream_list()
1537 hlist_del(&sfi->node); in clean_sfi_list()
1548 hlist_del(&sgi->node); in clean_sgi_list()
1563 int enetc_setup_tc_block_cb(enum tc_setup_type type, void *type_data, in enetc_setup_tc_block_cb()
1569 return -EOPNOTSUPP; in enetc_setup_tc_block_cb()
1575 return -EOPNOTSUPP; in enetc_setup_tc_block_cb()
1579 int enetc_set_psfp(struct net_device *ndev, bool en) in enetc_set_psfp()
1582 int err; in enetc_set_psfp()
1589 priv->active_offloads |= ENETC_F_QCI; in enetc_set_psfp()
1597 priv->active_offloads &= ~ENETC_F_QCI; in enetc_set_psfp()
1602 int enetc_psfp_init(struct enetc_ndev_priv *priv) in enetc_psfp_init()
1607 epsfp.psfp_sfi_bitmap = bitmap_zalloc(priv->psfp_cap.max_psfp_filter, in enetc_psfp_init()
1610 return -ENOMEM; in enetc_psfp_init()
1620 int enetc_psfp_clean(struct enetc_ndev_priv *priv) in enetc_psfp_clean()
1623 return -EBUSY; in enetc_psfp_clean()
1630 int enetc_setup_tc_psfp(struct net_device *ndev, void *type_data) in enetc_setup_tc_psfp()
1634 int port, err; in enetc_setup_tc_psfp()
1642 switch (f->command) { in enetc_setup_tc_psfp()
1644 port = enetc_pf_to_port(priv->si->pdev); in enetc_setup_tc_psfp()
1646 return -EINVAL; in enetc_setup_tc_psfp()
1651 port = enetc_pf_to_port(priv->si->pdev); in enetc_setup_tc_psfp()
1653 return -EINVAL; in enetc_setup_tc_psfp()
1664 int enetc_qos_query_caps(struct net_device *ndev, void *type_data) in enetc_qos_query_caps()
1668 struct enetc_si *si = priv->si; in enetc_qos_query_caps()
1670 switch (base->type) { in enetc_qos_query_caps()
1672 struct tc_mqprio_caps *caps = base->caps; in enetc_qos_query_caps()
1674 caps->validate_queue_counts = true; in enetc_qos_query_caps()
1679 struct tc_taprio_caps *caps = base->caps; in enetc_qos_query_caps()
1681 if (si->hw_features & ENETC_SI_F_QBV) in enetc_qos_query_caps()
1682 caps->supports_queue_max_sdu = true; in enetc_qos_query_caps()
1687 return -EOPNOTSUPP; in enetc_qos_query_caps()