|  | /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ | 
|  | /* Copyright (C) 2018 Netronome Systems, Inc. */ | 
|  |  | 
|  | #ifndef __NFP_ABM_H__ | 
|  | #define __NFP_ABM_H__ 1 | 
|  |  | 
|  | #include <linux/bits.h> | 
|  | #include <linux/list.h> | 
|  | #include <linux/radix-tree.h> | 
|  | #include <net/devlink.h> | 
|  | #include <net/pkt_cls.h> | 
|  | #include <net/pkt_sched.h> | 
|  |  | 
|  | /* Dump of 64 PRIOs and 256 REDs seems to take 850us on Xeon v4 @ 2.20GHz; | 
|  | * 2.5ms / 400Hz seems more than sufficient for stats resolution. | 
|  | */ | 
|  | #define NFP_ABM_STATS_REFRESH_IVAL	(2500 * 1000) /* ns */ | 
|  |  | 
|  | #define NFP_ABM_LVL_INFINITY		S32_MAX | 
|  |  | 
|  | struct nfp_app; | 
|  | struct nfp_net; | 
|  |  | 
|  | #define NFP_ABM_PORTID_TYPE	GENMASK(23, 16) | 
|  | #define NFP_ABM_PORTID_ID	GENMASK(7, 0) | 
|  |  | 
|  | /* The possible actions if thresholds are exceeded */ | 
|  | enum nfp_abm_q_action { | 
|  | /* mark if ECN capable, otherwise drop */ | 
|  | NFP_ABM_ACT_MARK_DROP		= 0, | 
|  | /* mark if ECN capable, otherwise goto QM */ | 
|  | NFP_ABM_ACT_MARK_QUEUE		= 1, | 
|  | NFP_ABM_ACT_DROP		= 2, | 
|  | NFP_ABM_ACT_QUEUE		= 3, | 
|  | NFP_ABM_ACT_NOQUEUE		= 4, | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * struct nfp_abm - ABM NIC app structure | 
|  | * @app:	back pointer to nfp_app | 
|  | * @pf_id:	ID of our PF link | 
|  | * | 
|  | * @red_support:	is RED offload supported | 
|  | * @num_prios:	number of supported DSCP priorities | 
|  | * @num_bands:	number of supported DSCP priority bands | 
|  | * @action_mask:	bitmask of supported actions | 
|  | * | 
|  | * @thresholds:		current threshold configuration | 
|  | * @threshold_undef:	bitmap of thresholds which have not been set | 
|  | * @actions:		current FW action configuration | 
|  | * @num_thresholds:	number of @thresholds and bits in @threshold_undef | 
|  | * | 
|  | * @prio_map_len:	computed length of FW priority map (in bytes) | 
|  | * @dscp_mask:		mask FW will apply on DSCP field | 
|  | * | 
|  | * @eswitch_mode:	devlink eswitch mode, advanced functions only visible | 
|  | *			in switchdev mode | 
|  | * | 
|  | * @q_lvls:	queue level control area | 
|  | * @qm_stats:	queue statistics symbol | 
|  | * @q_stats:	basic queue statistics (only in per-band case) | 
|  | */ | 
|  | struct nfp_abm { | 
|  | struct nfp_app *app; | 
|  | unsigned int pf_id; | 
|  |  | 
|  | unsigned int red_support; | 
|  | unsigned int num_prios; | 
|  | unsigned int num_bands; | 
|  | unsigned int action_mask; | 
|  |  | 
|  | u32 *thresholds; | 
|  | unsigned long *threshold_undef; | 
|  | u8 *actions; | 
|  | size_t num_thresholds; | 
|  |  | 
|  | unsigned int prio_map_len; | 
|  | u8 dscp_mask; | 
|  |  | 
|  | enum devlink_eswitch_mode eswitch_mode; | 
|  |  | 
|  | const struct nfp_rtsym *q_lvls; | 
|  | const struct nfp_rtsym *qm_stats; | 
|  | const struct nfp_rtsym *q_stats; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * struct nfp_alink_stats - ABM NIC statistics | 
|  | * @tx_pkts:		number of TXed packets | 
|  | * @tx_bytes:		number of TXed bytes | 
|  | * @backlog_pkts:	momentary backlog length (packets) | 
|  | * @backlog_bytes:	momentary backlog length (bytes) | 
|  | * @overlimits:		number of ECN marked TXed packets (accumulative) | 
|  | * @drops:		number of tail-dropped packets (accumulative) | 
|  | */ | 
|  | struct nfp_alink_stats { | 
|  | u64 tx_pkts; | 
|  | u64 tx_bytes; | 
|  | u64 backlog_pkts; | 
|  | u64 backlog_bytes; | 
|  | u64 overlimits; | 
|  | u64 drops; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * struct nfp_alink_xstats - extended ABM NIC statistics | 
|  | * @ecn_marked:		number of ECN marked TXed packets | 
|  | * @pdrop:		number of hard drops due to queue limit | 
|  | */ | 
|  | struct nfp_alink_xstats { | 
|  | u64 ecn_marked; | 
|  | u64 pdrop; | 
|  | }; | 
|  |  | 
|  | enum nfp_qdisc_type { | 
|  | NFP_QDISC_NONE = 0, | 
|  | NFP_QDISC_MQ, | 
|  | NFP_QDISC_RED, | 
|  | NFP_QDISC_GRED, | 
|  | }; | 
|  |  | 
|  | #define NFP_QDISC_UNTRACKED	((struct nfp_qdisc *)1UL) | 
|  |  | 
|  | /** | 
|  | * struct nfp_qdisc - tracked TC Qdisc | 
|  | * @netdev:		netdev on which Qdisc was created | 
|  | * @type:		Qdisc type | 
|  | * @handle:		handle of this Qdisc | 
|  | * @parent_handle:	handle of the parent (unreliable if Qdisc was grafted) | 
|  | * @use_cnt:		number of attachment points in the hierarchy | 
|  | * @num_children:	current size of the @children array | 
|  | * @children:		pointers to children | 
|  | * | 
|  | * @params_ok:		parameters of this Qdisc are OK for offload | 
|  | * @offload_mark:	offload refresh state - selected for offload | 
|  | * @offloaded:		Qdisc is currently offloaded to the HW | 
|  | * | 
|  | * @mq:			MQ Qdisc specific parameters and state | 
|  | * @mq.stats:		current stats of the MQ Qdisc | 
|  | * @mq.prev_stats:	previously reported @mq.stats | 
|  | * | 
|  | * @red:		RED Qdisc specific parameters and state | 
|  | * @red.num_bands:	Number of valid entries in the @red.band table | 
|  | * @red.band:		Per-band array of RED instances | 
|  | * @red.band.ecn:		ECN marking is enabled (rather than drop) | 
|  | * @red.band.threshold:		ECN marking threshold | 
|  | * @red.band.stats:		current stats of the RED Qdisc | 
|  | * @red.band.prev_stats:	previously reported @red.stats | 
|  | * @red.band.xstats:		extended stats for RED - current | 
|  | * @red.band.prev_xstats:	extended stats for RED - previously reported | 
|  | */ | 
|  | struct nfp_qdisc { | 
|  | struct net_device *netdev; | 
|  | enum nfp_qdisc_type type; | 
|  | u32 handle; | 
|  | u32 parent_handle; | 
|  | unsigned int use_cnt; | 
|  | unsigned int num_children; | 
|  | struct nfp_qdisc **children; | 
|  |  | 
|  | bool params_ok; | 
|  | bool offload_mark; | 
|  | bool offloaded; | 
|  |  | 
|  | union { | 
|  | /* NFP_QDISC_MQ */ | 
|  | struct { | 
|  | struct nfp_alink_stats stats; | 
|  | struct nfp_alink_stats prev_stats; | 
|  | } mq; | 
|  | /* TC_SETUP_QDISC_RED, TC_SETUP_QDISC_GRED */ | 
|  | struct { | 
|  | unsigned int num_bands; | 
|  |  | 
|  | struct { | 
|  | bool ecn; | 
|  | u32 threshold; | 
|  | struct nfp_alink_stats stats; | 
|  | struct nfp_alink_stats prev_stats; | 
|  | struct nfp_alink_xstats xstats; | 
|  | struct nfp_alink_xstats prev_xstats; | 
|  | } band[MAX_DPs]; | 
|  | } red; | 
|  | }; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * struct nfp_abm_link - port tuple of a ABM NIC | 
|  | * @abm:	back pointer to nfp_abm | 
|  | * @vnic:	data vNIC | 
|  | * @id:		id of the data vNIC | 
|  | * @queue_base:	id of base to host queue within PCIe (not QC idx) | 
|  | * @total_queues:	number of PF queues | 
|  | * | 
|  | * @last_stats_update:	ktime of last stats update | 
|  | * | 
|  | * @prio_map:		current map of priorities | 
|  | * @has_prio:		@prio_map is valid | 
|  | * | 
|  | * @def_band:		default band to use | 
|  | * @dscp_map:		list of DSCP to band mappings | 
|  | * | 
|  | * @root_qdisc:	pointer to the current root of the Qdisc hierarchy | 
|  | * @qdiscs:	all qdiscs recorded by major part of the handle | 
|  | */ | 
|  | struct nfp_abm_link { | 
|  | struct nfp_abm *abm; | 
|  | struct nfp_net *vnic; | 
|  | unsigned int id; | 
|  | unsigned int queue_base; | 
|  | unsigned int total_queues; | 
|  |  | 
|  | u64 last_stats_update; | 
|  |  | 
|  | u32 *prio_map; | 
|  | bool has_prio; | 
|  |  | 
|  | u8 def_band; | 
|  | struct list_head dscp_map; | 
|  |  | 
|  | struct nfp_qdisc *root_qdisc; | 
|  | struct radix_tree_root qdiscs; | 
|  | }; | 
|  |  | 
|  | static inline bool nfp_abm_has_prio(struct nfp_abm *abm) | 
|  | { | 
|  | return abm->num_bands > 1; | 
|  | } | 
|  |  | 
|  | static inline bool nfp_abm_has_drop(struct nfp_abm *abm) | 
|  | { | 
|  | return abm->action_mask & BIT(NFP_ABM_ACT_DROP); | 
|  | } | 
|  |  | 
|  | static inline bool nfp_abm_has_mark(struct nfp_abm *abm) | 
|  | { | 
|  | return abm->action_mask & BIT(NFP_ABM_ACT_MARK_DROP); | 
|  | } | 
|  |  | 
|  | void nfp_abm_qdisc_offload_update(struct nfp_abm_link *alink); | 
|  | int nfp_abm_setup_root(struct net_device *netdev, struct nfp_abm_link *alink, | 
|  | struct tc_root_qopt_offload *opt); | 
|  | int nfp_abm_setup_tc_red(struct net_device *netdev, struct nfp_abm_link *alink, | 
|  | struct tc_red_qopt_offload *opt); | 
|  | int nfp_abm_setup_tc_mq(struct net_device *netdev, struct nfp_abm_link *alink, | 
|  | struct tc_mq_qopt_offload *opt); | 
|  | int nfp_abm_setup_tc_gred(struct net_device *netdev, struct nfp_abm_link *alink, | 
|  | struct tc_gred_qopt_offload *opt); | 
|  | int nfp_abm_setup_cls_block(struct net_device *netdev, struct nfp_repr *repr, | 
|  | struct tc_block_offload *opt); | 
|  |  | 
|  | int nfp_abm_ctrl_read_params(struct nfp_abm_link *alink); | 
|  | int nfp_abm_ctrl_find_addrs(struct nfp_abm *abm); | 
|  | int __nfp_abm_ctrl_set_q_lvl(struct nfp_abm *abm, unsigned int id, u32 val); | 
|  | int nfp_abm_ctrl_set_q_lvl(struct nfp_abm_link *alink, unsigned int band, | 
|  | unsigned int queue, u32 val); | 
|  | int __nfp_abm_ctrl_set_q_act(struct nfp_abm *abm, unsigned int id, | 
|  | enum nfp_abm_q_action act); | 
|  | int nfp_abm_ctrl_set_q_act(struct nfp_abm_link *alink, unsigned int band, | 
|  | unsigned int queue, enum nfp_abm_q_action act); | 
|  | int nfp_abm_ctrl_read_q_stats(struct nfp_abm_link *alink, | 
|  | unsigned int band, unsigned int queue, | 
|  | struct nfp_alink_stats *stats); | 
|  | int nfp_abm_ctrl_read_q_xstats(struct nfp_abm_link *alink, | 
|  | unsigned int band, unsigned int queue, | 
|  | struct nfp_alink_xstats *xstats); | 
|  | u64 nfp_abm_ctrl_stat_non_sto(struct nfp_abm_link *alink, unsigned int i); | 
|  | u64 nfp_abm_ctrl_stat_sto(struct nfp_abm_link *alink, unsigned int i); | 
|  | int nfp_abm_ctrl_qm_enable(struct nfp_abm *abm); | 
|  | int nfp_abm_ctrl_qm_disable(struct nfp_abm *abm); | 
|  | void nfp_abm_prio_map_update(struct nfp_abm *abm); | 
|  | int nfp_abm_ctrl_prio_map_update(struct nfp_abm_link *alink, u32 *packed); | 
|  | #endif |