196de2506SJakub Kicinski /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
296de2506SJakub Kicinski /* Copyright (C) 2018 Netronome Systems, Inc. */
3c4c8f39aSJakub Kicinski
4c4c8f39aSJakub Kicinski #ifndef __NFP_ABM_H__
5c4c8f39aSJakub Kicinski #define __NFP_ABM_H__ 1
6c4c8f39aSJakub Kicinski
7cae5f48eSJakub Kicinski #include <linux/bits.h>
8174ab544SJakub Kicinski #include <linux/list.h>
94f5681d0SJakub Kicinski #include <linux/radix-tree.h>
10d05d902eSJakub Kicinski #include <net/devlink.h>
1147330f9bSJakub Kicinski #include <net/pkt_cls.h>
12f3d63720SJakub Kicinski #include <net/pkt_sched.h>
13d05d902eSJakub Kicinski
14bd3b5d46SJakub Kicinski /* Dump of 64 PRIOs and 256 REDs seems to take 850us on Xeon v4 @ 2.20GHz;
15bd3b5d46SJakub Kicinski * 2.5ms / 400Hz seems more than sufficient for stats resolution.
16bd3b5d46SJakub Kicinski */
17bd3b5d46SJakub Kicinski #define NFP_ABM_STATS_REFRESH_IVAL (2500 * 1000) /* ns */
18bd3b5d46SJakub Kicinski
19cae5f48eSJakub Kicinski #define NFP_ABM_LVL_INFINITY S32_MAX
20cae5f48eSJakub Kicinski
21c4c8f39aSJakub Kicinski struct nfp_app;
22cc54dc28SJakub Kicinski struct nfp_net;
23c4c8f39aSJakub Kicinski
24d05d902eSJakub Kicinski #define NFP_ABM_PORTID_TYPE GENMASK(23, 16)
25d05d902eSJakub Kicinski #define NFP_ABM_PORTID_ID GENMASK(7, 0)
26d05d902eSJakub Kicinski
27340a4864SJakub Kicinski /* The possible actions if thresholds are exceeded */
28340a4864SJakub Kicinski enum nfp_abm_q_action {
29340a4864SJakub Kicinski /* mark if ECN capable, otherwise drop */
30340a4864SJakub Kicinski NFP_ABM_ACT_MARK_DROP = 0,
31340a4864SJakub Kicinski /* mark if ECN capable, otherwise goto QM */
32340a4864SJakub Kicinski NFP_ABM_ACT_MARK_QUEUE = 1,
33340a4864SJakub Kicinski NFP_ABM_ACT_DROP = 2,
34340a4864SJakub Kicinski NFP_ABM_ACT_QUEUE = 3,
35340a4864SJakub Kicinski NFP_ABM_ACT_NOQUEUE = 4,
36340a4864SJakub Kicinski };
37340a4864SJakub Kicinski
38c4c8f39aSJakub Kicinski /**
39c4c8f39aSJakub Kicinski * struct nfp_abm - ABM NIC app structure
40c4c8f39aSJakub Kicinski * @app: back pointer to nfp_app
41cc54dc28SJakub Kicinski * @pf_id: ID of our PF link
426666f545SJakub Kicinski *
43036b9e7cSJakub Kicinski * @red_support: is RED offload supported
443a448205SJakub Kicinski * @num_prios: number of supported DSCP priorities
453a448205SJakub Kicinski * @num_bands: number of supported DSCP priority bands
46340a4864SJakub Kicinski * @action_mask: bitmask of supported actions
473a448205SJakub Kicinski *
486666f545SJakub Kicinski * @thresholds: current threshold configuration
496666f545SJakub Kicinski * @threshold_undef: bitmap of thresholds which have not been set
50340a4864SJakub Kicinski * @actions: current FW action configuration
516666f545SJakub Kicinski * @num_thresholds: number of @thresholds and bits in @threshold_undef
52174ab544SJakub Kicinski *
5314780c34SJakub Kicinski * @prio_map_len: computed length of FW priority map (in bytes)
54174ab544SJakub Kicinski * @dscp_mask: mask FW will apply on DSCP field
556666f545SJakub Kicinski *
56d05d902eSJakub Kicinski * @eswitch_mode: devlink eswitch mode, advanced functions only visible
57d05d902eSJakub Kicinski * in switchdev mode
5814780c34SJakub Kicinski *
5925e0036fSJakub Kicinski * @q_lvls: queue level control area
60cb89cac8SJakub Kicinski * @qm_stats: queue statistics symbol
6157f31bbaSJakub Kicinski * @q_stats: basic queue statistics (only in per-band case)
62c4c8f39aSJakub Kicinski */
63c4c8f39aSJakub Kicinski struct nfp_abm {
64c4c8f39aSJakub Kicinski struct nfp_app *app;
65cc54dc28SJakub Kicinski unsigned int pf_id;
666666f545SJakub Kicinski
67036b9e7cSJakub Kicinski unsigned int red_support;
683a448205SJakub Kicinski unsigned int num_prios;
693a448205SJakub Kicinski unsigned int num_bands;
70340a4864SJakub Kicinski unsigned int action_mask;
713a448205SJakub Kicinski
726666f545SJakub Kicinski u32 *thresholds;
736666f545SJakub Kicinski unsigned long *threshold_undef;
74340a4864SJakub Kicinski u8 *actions;
756666f545SJakub Kicinski size_t num_thresholds;
76174ab544SJakub Kicinski
7714780c34SJakub Kicinski unsigned int prio_map_len;
78174ab544SJakub Kicinski u8 dscp_mask;
796666f545SJakub Kicinski
80d05d902eSJakub Kicinski enum devlink_eswitch_mode eswitch_mode;
8114780c34SJakub Kicinski
8225e0036fSJakub Kicinski const struct nfp_rtsym *q_lvls;
83cb89cac8SJakub Kicinski const struct nfp_rtsym *qm_stats;
8457f31bbaSJakub Kicinski const struct nfp_rtsym *q_stats;
85cb89cac8SJakub Kicinski };
86cb89cac8SJakub Kicinski
87cb89cac8SJakub Kicinski /**
88cb89cac8SJakub Kicinski * struct nfp_alink_stats - ABM NIC statistics
89cb89cac8SJakub Kicinski * @tx_pkts: number of TXed packets
90cb89cac8SJakub Kicinski * @tx_bytes: number of TXed bytes
91cb89cac8SJakub Kicinski * @backlog_pkts: momentary backlog length (packets)
92cb89cac8SJakub Kicinski * @backlog_bytes: momentary backlog length (bytes)
93cb89cac8SJakub Kicinski * @overlimits: number of ECN marked TXed packets (accumulative)
94cb89cac8SJakub Kicinski * @drops: number of tail-dropped packets (accumulative)
95cb89cac8SJakub Kicinski */
96cb89cac8SJakub Kicinski struct nfp_alink_stats {
97cb89cac8SJakub Kicinski u64 tx_pkts;
98cb89cac8SJakub Kicinski u64 tx_bytes;
99cb89cac8SJakub Kicinski u64 backlog_pkts;
100cb89cac8SJakub Kicinski u64 backlog_bytes;
101cb89cac8SJakub Kicinski u64 overlimits;
102cb89cac8SJakub Kicinski u64 drops;
103cb89cac8SJakub Kicinski };
104cb89cac8SJakub Kicinski
105cb89cac8SJakub Kicinski /**
106cb89cac8SJakub Kicinski * struct nfp_alink_xstats - extended ABM NIC statistics
107cb89cac8SJakub Kicinski * @ecn_marked: number of ECN marked TXed packets
108cb89cac8SJakub Kicinski * @pdrop: number of hard drops due to queue limit
109cb89cac8SJakub Kicinski */
110cb89cac8SJakub Kicinski struct nfp_alink_xstats {
111cb89cac8SJakub Kicinski u64 ecn_marked;
112cb89cac8SJakub Kicinski u64 pdrop;
113c4c8f39aSJakub Kicinski };
114cc54dc28SJakub Kicinski
1154f5681d0SJakub Kicinski enum nfp_qdisc_type {
1164f5681d0SJakub Kicinski NFP_QDISC_NONE = 0,
1174f5681d0SJakub Kicinski NFP_QDISC_MQ,
1184f5681d0SJakub Kicinski NFP_QDISC_RED,
119f3d63720SJakub Kicinski NFP_QDISC_GRED,
1204f5681d0SJakub Kicinski };
1214f5681d0SJakub Kicinski
1226b8417b7SJakub Kicinski #define NFP_QDISC_UNTRACKED ((struct nfp_qdisc *)1UL)
1236b8417b7SJakub Kicinski
1244f5681d0SJakub Kicinski /**
1254f5681d0SJakub Kicinski * struct nfp_qdisc - tracked TC Qdisc
1264f5681d0SJakub Kicinski * @netdev: netdev on which Qdisc was created
1274f5681d0SJakub Kicinski * @type: Qdisc type
1284f5681d0SJakub Kicinski * @handle: handle of this Qdisc
1294f5681d0SJakub Kicinski * @parent_handle: handle of the parent (unreliable if Qdisc was grafted)
130aee7539cSJakub Kicinski * @use_cnt: number of attachment points in the hierarchy
131aee7539cSJakub Kicinski * @num_children: current size of the @children array
132aee7539cSJakub Kicinski * @children: pointers to children
13352db4eacSJakub Kicinski *
13452db4eacSJakub Kicinski * @params_ok: parameters of this Qdisc are OK for offload
135bd3b5d46SJakub Kicinski * @offload_mark: offload refresh state - selected for offload
136bd3b5d46SJakub Kicinski * @offloaded: Qdisc is currently offloaded to the HW
137bd3b5d46SJakub Kicinski *
138bd3b5d46SJakub Kicinski * @mq: MQ Qdisc specific parameters and state
139bd3b5d46SJakub Kicinski * @mq.stats: current stats of the MQ Qdisc
140bd3b5d46SJakub Kicinski * @mq.prev_stats: previously reported @mq.stats
14152db4eacSJakub Kicinski *
14252db4eacSJakub Kicinski * @red: RED Qdisc specific parameters and state
143990b50a5SJakub Kicinski * @red.num_bands: Number of valid entries in the @red.band table
144990b50a5SJakub Kicinski * @red.band: Per-band array of RED instances
145340a4864SJakub Kicinski * @red.band.ecn: ECN marking is enabled (rather than drop)
146990b50a5SJakub Kicinski * @red.band.threshold: ECN marking threshold
147990b50a5SJakub Kicinski * @red.band.stats: current stats of the RED Qdisc
148990b50a5SJakub Kicinski * @red.band.prev_stats: previously reported @red.stats
149990b50a5SJakub Kicinski * @red.band.xstats: extended stats for RED - current
150990b50a5SJakub Kicinski * @red.band.prev_xstats: extended stats for RED - previously reported
1514f5681d0SJakub Kicinski */
1524f5681d0SJakub Kicinski struct nfp_qdisc {
1534f5681d0SJakub Kicinski struct net_device *netdev;
1544f5681d0SJakub Kicinski enum nfp_qdisc_type type;
1554f5681d0SJakub Kicinski u32 handle;
1564f5681d0SJakub Kicinski u32 parent_handle;
157aee7539cSJakub Kicinski unsigned int use_cnt;
158aee7539cSJakub Kicinski unsigned int num_children;
159aee7539cSJakub Kicinski struct nfp_qdisc **children;
16052db4eacSJakub Kicinski
16152db4eacSJakub Kicinski bool params_ok;
162bd3b5d46SJakub Kicinski bool offload_mark;
163bd3b5d46SJakub Kicinski bool offloaded;
16452db4eacSJakub Kicinski
16552db4eacSJakub Kicinski union {
166bd3b5d46SJakub Kicinski /* NFP_QDISC_MQ */
167bd3b5d46SJakub Kicinski struct {
168bd3b5d46SJakub Kicinski struct nfp_alink_stats stats;
169bd3b5d46SJakub Kicinski struct nfp_alink_stats prev_stats;
170bd3b5d46SJakub Kicinski } mq;
171f3d63720SJakub Kicinski /* TC_SETUP_QDISC_RED, TC_SETUP_QDISC_GRED */
17252db4eacSJakub Kicinski struct {
173990b50a5SJakub Kicinski unsigned int num_bands;
174990b50a5SJakub Kicinski
175990b50a5SJakub Kicinski struct {
176340a4864SJakub Kicinski bool ecn;
17752db4eacSJakub Kicinski u32 threshold;
178bd3b5d46SJakub Kicinski struct nfp_alink_stats stats;
179bd3b5d46SJakub Kicinski struct nfp_alink_stats prev_stats;
180bd3b5d46SJakub Kicinski struct nfp_alink_xstats xstats;
181bd3b5d46SJakub Kicinski struct nfp_alink_xstats prev_xstats;
182f3d63720SJakub Kicinski } band[MAX_DPs];
18352db4eacSJakub Kicinski } red;
18452db4eacSJakub Kicinski };
1854f5681d0SJakub Kicinski };
1864f5681d0SJakub Kicinski
187cc54dc28SJakub Kicinski /**
188cc54dc28SJakub Kicinski * struct nfp_abm_link - port tuple of a ABM NIC
189cc54dc28SJakub Kicinski * @abm: back pointer to nfp_abm
190cc54dc28SJakub Kicinski * @vnic: data vNIC
191cc54dc28SJakub Kicinski * @id: id of the data vNIC
192cc54dc28SJakub Kicinski * @queue_base: id of base to host queue within PCIe (not QC idx)
193674cb229SJakub Kicinski * @total_queues: number of PF queues
194bd3b5d46SJakub Kicinski *
195bd3b5d46SJakub Kicinski * @last_stats_update: ktime of last stats update
196bd3b5d46SJakub Kicinski *
197174ab544SJakub Kicinski * @prio_map: current map of priorities
198174ab544SJakub Kicinski * @has_prio: @prio_map is valid
199174ab544SJakub Kicinski *
200f3d63720SJakub Kicinski * @def_band: default band to use
201174ab544SJakub Kicinski * @dscp_map: list of DSCP to band mappings
202f3d63720SJakub Kicinski *
20318531258SJakub Kicinski * @root_qdisc: pointer to the current root of the Qdisc hierarchy
2044f5681d0SJakub Kicinski * @qdiscs: all qdiscs recorded by major part of the handle
205cc54dc28SJakub Kicinski */
206cc54dc28SJakub Kicinski struct nfp_abm_link {
207cc54dc28SJakub Kicinski struct nfp_abm *abm;
208cc54dc28SJakub Kicinski struct nfp_net *vnic;
209cc54dc28SJakub Kicinski unsigned int id;
210cc54dc28SJakub Kicinski unsigned int queue_base;
211674cb229SJakub Kicinski unsigned int total_queues;
212bd3b5d46SJakub Kicinski
213bd3b5d46SJakub Kicinski u64 last_stats_update;
214bd3b5d46SJakub Kicinski
215174ab544SJakub Kicinski u32 *prio_map;
216174ab544SJakub Kicinski bool has_prio;
217174ab544SJakub Kicinski
218f3d63720SJakub Kicinski u8 def_band;
219174ab544SJakub Kicinski struct list_head dscp_map;
220f3d63720SJakub Kicinski
22118531258SJakub Kicinski struct nfp_qdisc *root_qdisc;
2224f5681d0SJakub Kicinski struct radix_tree_root qdiscs;
223cc54dc28SJakub Kicinski };
224cc54dc28SJakub Kicinski
nfp_abm_has_prio(struct nfp_abm * abm)2253a448205SJakub Kicinski static inline bool nfp_abm_has_prio(struct nfp_abm *abm)
2263a448205SJakub Kicinski {
2273a448205SJakub Kicinski return abm->num_bands > 1;
2283a448205SJakub Kicinski }
2293a448205SJakub Kicinski
nfp_abm_has_drop(struct nfp_abm * abm)230340a4864SJakub Kicinski static inline bool nfp_abm_has_drop(struct nfp_abm *abm)
231340a4864SJakub Kicinski {
232340a4864SJakub Kicinski return abm->action_mask & BIT(NFP_ABM_ACT_DROP);
233340a4864SJakub Kicinski }
234340a4864SJakub Kicinski
nfp_abm_has_mark(struct nfp_abm * abm)235340a4864SJakub Kicinski static inline bool nfp_abm_has_mark(struct nfp_abm *abm)
236340a4864SJakub Kicinski {
237340a4864SJakub Kicinski return abm->action_mask & BIT(NFP_ABM_ACT_MARK_DROP);
238340a4864SJakub Kicinski }
239340a4864SJakub Kicinski
240bd3b5d46SJakub Kicinski void nfp_abm_qdisc_offload_update(struct nfp_abm_link *alink);
24118531258SJakub Kicinski int nfp_abm_setup_root(struct net_device *netdev, struct nfp_abm_link *alink,
24218531258SJakub Kicinski struct tc_root_qopt_offload *opt);
24347330f9bSJakub Kicinski int nfp_abm_setup_tc_red(struct net_device *netdev, struct nfp_abm_link *alink,
24447330f9bSJakub Kicinski struct tc_red_qopt_offload *opt);
24547330f9bSJakub Kicinski int nfp_abm_setup_tc_mq(struct net_device *netdev, struct nfp_abm_link *alink,
24647330f9bSJakub Kicinski struct tc_mq_qopt_offload *opt);
247f3d63720SJakub Kicinski int nfp_abm_setup_tc_gred(struct net_device *netdev, struct nfp_abm_link *alink,
248f3d63720SJakub Kicinski struct tc_gred_qopt_offload *opt);
249174ab544SJakub Kicinski int nfp_abm_setup_cls_block(struct net_device *netdev, struct nfp_repr *repr,
250*955bcb6eSPablo Neira Ayuso struct flow_block_offload *opt);
25147330f9bSJakub Kicinski
25214780c34SJakub Kicinski int nfp_abm_ctrl_read_params(struct nfp_abm_link *alink);
253cc54dc28SJakub Kicinski int nfp_abm_ctrl_find_addrs(struct nfp_abm *abm);
2546666f545SJakub Kicinski int __nfp_abm_ctrl_set_q_lvl(struct nfp_abm *abm, unsigned int id, u32 val);
25557207696SJakub Kicinski int nfp_abm_ctrl_set_q_lvl(struct nfp_abm_link *alink, unsigned int band,
25657207696SJakub Kicinski unsigned int queue, u32 val);
257340a4864SJakub Kicinski int __nfp_abm_ctrl_set_q_act(struct nfp_abm *abm, unsigned int id,
258340a4864SJakub Kicinski enum nfp_abm_q_action act);
259340a4864SJakub Kicinski int nfp_abm_ctrl_set_q_act(struct nfp_abm_link *alink, unsigned int band,
260340a4864SJakub Kicinski unsigned int queue, enum nfp_abm_q_action act);
26157207696SJakub Kicinski int nfp_abm_ctrl_read_q_stats(struct nfp_abm_link *alink,
26257207696SJakub Kicinski unsigned int band, unsigned int queue,
263674cb229SJakub Kicinski struct nfp_alink_stats *stats);
26457207696SJakub Kicinski int nfp_abm_ctrl_read_q_xstats(struct nfp_abm_link *alink,
26557207696SJakub Kicinski unsigned int band, unsigned int queue,
266674cb229SJakub Kicinski struct nfp_alink_xstats *xstats);
2670a8b7019SJakub Kicinski u64 nfp_abm_ctrl_stat_non_sto(struct nfp_abm_link *alink, unsigned int i);
2680a8b7019SJakub Kicinski u64 nfp_abm_ctrl_stat_sto(struct nfp_abm_link *alink, unsigned int i);
269055ee0d6SJakub Kicinski int nfp_abm_ctrl_qm_enable(struct nfp_abm *abm);
270055ee0d6SJakub Kicinski int nfp_abm_ctrl_qm_disable(struct nfp_abm *abm);
271174ab544SJakub Kicinski void nfp_abm_prio_map_update(struct nfp_abm *abm);
2726a802405SJakub Kicinski int nfp_abm_ctrl_prio_map_update(struct nfp_abm_link *alink, u32 *packed);
273c4c8f39aSJakub Kicinski #endif
274