xref: /openbmc/linux/drivers/net/ethernet/netronome/nfp/abm/main.h (revision 0898782247ae533d1f4e47a06bc5d4870931b284)
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