162306a36Sopenharmony_ci/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ 262306a36Sopenharmony_ci/* Copyright (C) 2018 Netronome Systems, Inc. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#ifndef __NFP_ABM_H__ 562306a36Sopenharmony_ci#define __NFP_ABM_H__ 1 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/bits.h> 862306a36Sopenharmony_ci#include <linux/list.h> 962306a36Sopenharmony_ci#include <linux/radix-tree.h> 1062306a36Sopenharmony_ci#include <net/devlink.h> 1162306a36Sopenharmony_ci#include <net/pkt_cls.h> 1262306a36Sopenharmony_ci#include <net/pkt_sched.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* Dump of 64 PRIOs and 256 REDs seems to take 850us on Xeon v4 @ 2.20GHz; 1562306a36Sopenharmony_ci * 2.5ms / 400Hz seems more than sufficient for stats resolution. 1662306a36Sopenharmony_ci */ 1762306a36Sopenharmony_ci#define NFP_ABM_STATS_REFRESH_IVAL (2500 * 1000) /* ns */ 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define NFP_ABM_LVL_INFINITY S32_MAX 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistruct nfp_app; 2262306a36Sopenharmony_cistruct nfp_net; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define NFP_ABM_PORTID_TYPE GENMASK(23, 16) 2562306a36Sopenharmony_ci#define NFP_ABM_PORTID_ID GENMASK(7, 0) 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci/* The possible actions if thresholds are exceeded */ 2862306a36Sopenharmony_cienum nfp_abm_q_action { 2962306a36Sopenharmony_ci /* mark if ECN capable, otherwise drop */ 3062306a36Sopenharmony_ci NFP_ABM_ACT_MARK_DROP = 0, 3162306a36Sopenharmony_ci /* mark if ECN capable, otherwise goto QM */ 3262306a36Sopenharmony_ci NFP_ABM_ACT_MARK_QUEUE = 1, 3362306a36Sopenharmony_ci NFP_ABM_ACT_DROP = 2, 3462306a36Sopenharmony_ci NFP_ABM_ACT_QUEUE = 3, 3562306a36Sopenharmony_ci NFP_ABM_ACT_NOQUEUE = 4, 3662306a36Sopenharmony_ci}; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/** 3962306a36Sopenharmony_ci * struct nfp_abm - ABM NIC app structure 4062306a36Sopenharmony_ci * @app: back pointer to nfp_app 4162306a36Sopenharmony_ci * @pf_id: ID of our PF link 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * @red_support: is RED offload supported 4462306a36Sopenharmony_ci * @num_prios: number of supported DSCP priorities 4562306a36Sopenharmony_ci * @num_bands: number of supported DSCP priority bands 4662306a36Sopenharmony_ci * @action_mask: bitmask of supported actions 4762306a36Sopenharmony_ci * 4862306a36Sopenharmony_ci * @thresholds: current threshold configuration 4962306a36Sopenharmony_ci * @threshold_undef: bitmap of thresholds which have not been set 5062306a36Sopenharmony_ci * @actions: current FW action configuration 5162306a36Sopenharmony_ci * @num_thresholds: number of @thresholds and bits in @threshold_undef 5262306a36Sopenharmony_ci * 5362306a36Sopenharmony_ci * @prio_map_len: computed length of FW priority map (in bytes) 5462306a36Sopenharmony_ci * @dscp_mask: mask FW will apply on DSCP field 5562306a36Sopenharmony_ci * 5662306a36Sopenharmony_ci * @eswitch_mode: devlink eswitch mode, advanced functions only visible 5762306a36Sopenharmony_ci * in switchdev mode 5862306a36Sopenharmony_ci * 5962306a36Sopenharmony_ci * @q_lvls: queue level control area 6062306a36Sopenharmony_ci * @qm_stats: queue statistics symbol 6162306a36Sopenharmony_ci * @q_stats: basic queue statistics (only in per-band case) 6262306a36Sopenharmony_ci */ 6362306a36Sopenharmony_cistruct nfp_abm { 6462306a36Sopenharmony_ci struct nfp_app *app; 6562306a36Sopenharmony_ci unsigned int pf_id; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci unsigned int red_support; 6862306a36Sopenharmony_ci unsigned int num_prios; 6962306a36Sopenharmony_ci unsigned int num_bands; 7062306a36Sopenharmony_ci unsigned int action_mask; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci u32 *thresholds; 7362306a36Sopenharmony_ci unsigned long *threshold_undef; 7462306a36Sopenharmony_ci u8 *actions; 7562306a36Sopenharmony_ci size_t num_thresholds; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci unsigned int prio_map_len; 7862306a36Sopenharmony_ci u8 dscp_mask; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci enum devlink_eswitch_mode eswitch_mode; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci const struct nfp_rtsym *q_lvls; 8362306a36Sopenharmony_ci const struct nfp_rtsym *qm_stats; 8462306a36Sopenharmony_ci const struct nfp_rtsym *q_stats; 8562306a36Sopenharmony_ci}; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci/** 8862306a36Sopenharmony_ci * struct nfp_alink_stats - ABM NIC statistics 8962306a36Sopenharmony_ci * @tx_pkts: number of TXed packets 9062306a36Sopenharmony_ci * @tx_bytes: number of TXed bytes 9162306a36Sopenharmony_ci * @backlog_pkts: momentary backlog length (packets) 9262306a36Sopenharmony_ci * @backlog_bytes: momentary backlog length (bytes) 9362306a36Sopenharmony_ci * @overlimits: number of ECN marked TXed packets (accumulative) 9462306a36Sopenharmony_ci * @drops: number of tail-dropped packets (accumulative) 9562306a36Sopenharmony_ci */ 9662306a36Sopenharmony_cistruct nfp_alink_stats { 9762306a36Sopenharmony_ci u64 tx_pkts; 9862306a36Sopenharmony_ci u64 tx_bytes; 9962306a36Sopenharmony_ci u64 backlog_pkts; 10062306a36Sopenharmony_ci u64 backlog_bytes; 10162306a36Sopenharmony_ci u64 overlimits; 10262306a36Sopenharmony_ci u64 drops; 10362306a36Sopenharmony_ci}; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci/** 10662306a36Sopenharmony_ci * struct nfp_alink_xstats - extended ABM NIC statistics 10762306a36Sopenharmony_ci * @ecn_marked: number of ECN marked TXed packets 10862306a36Sopenharmony_ci * @pdrop: number of hard drops due to queue limit 10962306a36Sopenharmony_ci */ 11062306a36Sopenharmony_cistruct nfp_alink_xstats { 11162306a36Sopenharmony_ci u64 ecn_marked; 11262306a36Sopenharmony_ci u64 pdrop; 11362306a36Sopenharmony_ci}; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cienum nfp_qdisc_type { 11662306a36Sopenharmony_ci NFP_QDISC_NONE = 0, 11762306a36Sopenharmony_ci NFP_QDISC_MQ, 11862306a36Sopenharmony_ci NFP_QDISC_RED, 11962306a36Sopenharmony_ci NFP_QDISC_GRED, 12062306a36Sopenharmony_ci}; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci#define NFP_QDISC_UNTRACKED ((struct nfp_qdisc *)1UL) 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci/** 12562306a36Sopenharmony_ci * struct nfp_qdisc - tracked TC Qdisc 12662306a36Sopenharmony_ci * @netdev: netdev on which Qdisc was created 12762306a36Sopenharmony_ci * @type: Qdisc type 12862306a36Sopenharmony_ci * @handle: handle of this Qdisc 12962306a36Sopenharmony_ci * @parent_handle: handle of the parent (unreliable if Qdisc was grafted) 13062306a36Sopenharmony_ci * @use_cnt: number of attachment points in the hierarchy 13162306a36Sopenharmony_ci * @num_children: current size of the @children array 13262306a36Sopenharmony_ci * @children: pointers to children 13362306a36Sopenharmony_ci * 13462306a36Sopenharmony_ci * @params_ok: parameters of this Qdisc are OK for offload 13562306a36Sopenharmony_ci * @offload_mark: offload refresh state - selected for offload 13662306a36Sopenharmony_ci * @offloaded: Qdisc is currently offloaded to the HW 13762306a36Sopenharmony_ci * 13862306a36Sopenharmony_ci * @mq: MQ Qdisc specific parameters and state 13962306a36Sopenharmony_ci * @mq.stats: current stats of the MQ Qdisc 14062306a36Sopenharmony_ci * @mq.prev_stats: previously reported @mq.stats 14162306a36Sopenharmony_ci * 14262306a36Sopenharmony_ci * @red: RED Qdisc specific parameters and state 14362306a36Sopenharmony_ci * @red.num_bands: Number of valid entries in the @red.band table 14462306a36Sopenharmony_ci * @red.band: Per-band array of RED instances 14562306a36Sopenharmony_ci * @red.band.ecn: ECN marking is enabled (rather than drop) 14662306a36Sopenharmony_ci * @red.band.threshold: ECN marking threshold 14762306a36Sopenharmony_ci * @red.band.stats: current stats of the RED Qdisc 14862306a36Sopenharmony_ci * @red.band.prev_stats: previously reported @red.stats 14962306a36Sopenharmony_ci * @red.band.xstats: extended stats for RED - current 15062306a36Sopenharmony_ci * @red.band.prev_xstats: extended stats for RED - previously reported 15162306a36Sopenharmony_ci */ 15262306a36Sopenharmony_cistruct nfp_qdisc { 15362306a36Sopenharmony_ci struct net_device *netdev; 15462306a36Sopenharmony_ci enum nfp_qdisc_type type; 15562306a36Sopenharmony_ci u32 handle; 15662306a36Sopenharmony_ci u32 parent_handle; 15762306a36Sopenharmony_ci unsigned int use_cnt; 15862306a36Sopenharmony_ci unsigned int num_children; 15962306a36Sopenharmony_ci struct nfp_qdisc **children; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci bool params_ok; 16262306a36Sopenharmony_ci bool offload_mark; 16362306a36Sopenharmony_ci bool offloaded; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci union { 16662306a36Sopenharmony_ci /* NFP_QDISC_MQ */ 16762306a36Sopenharmony_ci struct { 16862306a36Sopenharmony_ci struct nfp_alink_stats stats; 16962306a36Sopenharmony_ci struct nfp_alink_stats prev_stats; 17062306a36Sopenharmony_ci } mq; 17162306a36Sopenharmony_ci /* TC_SETUP_QDISC_RED, TC_SETUP_QDISC_GRED */ 17262306a36Sopenharmony_ci struct { 17362306a36Sopenharmony_ci unsigned int num_bands; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci struct { 17662306a36Sopenharmony_ci bool ecn; 17762306a36Sopenharmony_ci u32 threshold; 17862306a36Sopenharmony_ci struct nfp_alink_stats stats; 17962306a36Sopenharmony_ci struct nfp_alink_stats prev_stats; 18062306a36Sopenharmony_ci struct nfp_alink_xstats xstats; 18162306a36Sopenharmony_ci struct nfp_alink_xstats prev_xstats; 18262306a36Sopenharmony_ci } band[MAX_DPs]; 18362306a36Sopenharmony_ci } red; 18462306a36Sopenharmony_ci }; 18562306a36Sopenharmony_ci}; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci/** 18862306a36Sopenharmony_ci * struct nfp_abm_link - port tuple of a ABM NIC 18962306a36Sopenharmony_ci * @abm: back pointer to nfp_abm 19062306a36Sopenharmony_ci * @vnic: data vNIC 19162306a36Sopenharmony_ci * @id: id of the data vNIC 19262306a36Sopenharmony_ci * @queue_base: id of base to host queue within PCIe (not QC idx) 19362306a36Sopenharmony_ci * @total_queues: number of PF queues 19462306a36Sopenharmony_ci * 19562306a36Sopenharmony_ci * @last_stats_update: ktime of last stats update 19662306a36Sopenharmony_ci * 19762306a36Sopenharmony_ci * @prio_map: current map of priorities 19862306a36Sopenharmony_ci * @has_prio: @prio_map is valid 19962306a36Sopenharmony_ci * 20062306a36Sopenharmony_ci * @def_band: default band to use 20162306a36Sopenharmony_ci * @dscp_map: list of DSCP to band mappings 20262306a36Sopenharmony_ci * 20362306a36Sopenharmony_ci * @root_qdisc: pointer to the current root of the Qdisc hierarchy 20462306a36Sopenharmony_ci * @qdiscs: all qdiscs recorded by major part of the handle 20562306a36Sopenharmony_ci */ 20662306a36Sopenharmony_cistruct nfp_abm_link { 20762306a36Sopenharmony_ci struct nfp_abm *abm; 20862306a36Sopenharmony_ci struct nfp_net *vnic; 20962306a36Sopenharmony_ci unsigned int id; 21062306a36Sopenharmony_ci unsigned int queue_base; 21162306a36Sopenharmony_ci unsigned int total_queues; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci u64 last_stats_update; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci u32 *prio_map; 21662306a36Sopenharmony_ci bool has_prio; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci u8 def_band; 21962306a36Sopenharmony_ci struct list_head dscp_map; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci struct nfp_qdisc *root_qdisc; 22262306a36Sopenharmony_ci struct radix_tree_root qdiscs; 22362306a36Sopenharmony_ci}; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cistatic inline bool nfp_abm_has_prio(struct nfp_abm *abm) 22662306a36Sopenharmony_ci{ 22762306a36Sopenharmony_ci return abm->num_bands > 1; 22862306a36Sopenharmony_ci} 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_cistatic inline bool nfp_abm_has_drop(struct nfp_abm *abm) 23162306a36Sopenharmony_ci{ 23262306a36Sopenharmony_ci return abm->action_mask & BIT(NFP_ABM_ACT_DROP); 23362306a36Sopenharmony_ci} 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_cistatic inline bool nfp_abm_has_mark(struct nfp_abm *abm) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci return abm->action_mask & BIT(NFP_ABM_ACT_MARK_DROP); 23862306a36Sopenharmony_ci} 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_civoid nfp_abm_qdisc_offload_update(struct nfp_abm_link *alink); 24162306a36Sopenharmony_ciint nfp_abm_setup_root(struct net_device *netdev, struct nfp_abm_link *alink, 24262306a36Sopenharmony_ci struct tc_root_qopt_offload *opt); 24362306a36Sopenharmony_ciint nfp_abm_setup_tc_red(struct net_device *netdev, struct nfp_abm_link *alink, 24462306a36Sopenharmony_ci struct tc_red_qopt_offload *opt); 24562306a36Sopenharmony_ciint nfp_abm_setup_tc_mq(struct net_device *netdev, struct nfp_abm_link *alink, 24662306a36Sopenharmony_ci struct tc_mq_qopt_offload *opt); 24762306a36Sopenharmony_ciint nfp_abm_setup_tc_gred(struct net_device *netdev, struct nfp_abm_link *alink, 24862306a36Sopenharmony_ci struct tc_gred_qopt_offload *opt); 24962306a36Sopenharmony_ciint nfp_abm_setup_cls_block(struct net_device *netdev, struct nfp_repr *repr, 25062306a36Sopenharmony_ci struct flow_block_offload *opt); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ciint nfp_abm_ctrl_read_params(struct nfp_abm_link *alink); 25362306a36Sopenharmony_ciint nfp_abm_ctrl_find_addrs(struct nfp_abm *abm); 25462306a36Sopenharmony_ciint __nfp_abm_ctrl_set_q_lvl(struct nfp_abm *abm, unsigned int id, u32 val); 25562306a36Sopenharmony_ciint nfp_abm_ctrl_set_q_lvl(struct nfp_abm_link *alink, unsigned int band, 25662306a36Sopenharmony_ci unsigned int queue, u32 val); 25762306a36Sopenharmony_ciint __nfp_abm_ctrl_set_q_act(struct nfp_abm *abm, unsigned int id, 25862306a36Sopenharmony_ci enum nfp_abm_q_action act); 25962306a36Sopenharmony_ciint nfp_abm_ctrl_set_q_act(struct nfp_abm_link *alink, unsigned int band, 26062306a36Sopenharmony_ci unsigned int queue, enum nfp_abm_q_action act); 26162306a36Sopenharmony_ciint nfp_abm_ctrl_read_q_stats(struct nfp_abm_link *alink, 26262306a36Sopenharmony_ci unsigned int band, unsigned int queue, 26362306a36Sopenharmony_ci struct nfp_alink_stats *stats); 26462306a36Sopenharmony_ciint nfp_abm_ctrl_read_q_xstats(struct nfp_abm_link *alink, 26562306a36Sopenharmony_ci unsigned int band, unsigned int queue, 26662306a36Sopenharmony_ci struct nfp_alink_xstats *xstats); 26762306a36Sopenharmony_ciu64 nfp_abm_ctrl_stat_non_sto(struct nfp_abm_link *alink, unsigned int i); 26862306a36Sopenharmony_ciu64 nfp_abm_ctrl_stat_sto(struct nfp_abm_link *alink, unsigned int i); 26962306a36Sopenharmony_ciint nfp_abm_ctrl_qm_enable(struct nfp_abm *abm); 27062306a36Sopenharmony_ciint nfp_abm_ctrl_qm_disable(struct nfp_abm *abm); 27162306a36Sopenharmony_civoid nfp_abm_prio_map_update(struct nfp_abm *abm); 27262306a36Sopenharmony_ciint nfp_abm_ctrl_prio_map_update(struct nfp_abm_link *alink, u32 *packed); 27362306a36Sopenharmony_ci#endif 274