1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 275957ba3STom Herbert /* 375957ba3STom Herbert * Dynamic queue limits (dql) - Definitions 475957ba3STom Herbert * 575957ba3STom Herbert * Copyright (c) 2011, Tom Herbert <[email protected]> 675957ba3STom Herbert * 775957ba3STom Herbert * This header file contains the definitions for dynamic queue limits (dql). 875957ba3STom Herbert * dql would be used in conjunction with a producer/consumer type queue 975957ba3STom Herbert * (possibly a HW queue). Such a queue would have these general properties: 1075957ba3STom Herbert * 1175957ba3STom Herbert * 1) Objects are queued up to some limit specified as number of objects. 1275957ba3STom Herbert * 2) Periodically a completion process executes which retires consumed 1375957ba3STom Herbert * objects. 1475957ba3STom Herbert * 3) Starvation occurs when limit has been reached, all queued data has 1575957ba3STom Herbert * actually been consumed, but completion processing has not yet run 1675957ba3STom Herbert * so queuing new data is blocked. 1775957ba3STom Herbert * 4) Minimizing the amount of queued data is desirable. 1875957ba3STom Herbert * 1975957ba3STom Herbert * The goal of dql is to calculate the limit as the minimum number of objects 2075957ba3STom Herbert * needed to prevent starvation. 2175957ba3STom Herbert * 2275957ba3STom Herbert * The primary functions of dql are: 2375957ba3STom Herbert * dql_queued - called when objects are enqueued to record number of objects 2475957ba3STom Herbert * dql_avail - returns how many objects are available to be queued based 2575957ba3STom Herbert * on the object limit and how many objects are already enqueued 2675957ba3STom Herbert * dql_completed - called at completion time to indicate how many objects 2775957ba3STom Herbert * were retired from the queue 2875957ba3STom Herbert * 2975957ba3STom Herbert * The dql implementation does not implement any locking for the dql data 3075957ba3STom Herbert * structures, the higher layer should provide this. dql_queued should 3175957ba3STom Herbert * be serialized to prevent concurrent execution of the function; this 3275957ba3STom Herbert * is also true for dql_completed. However, dql_queued and dlq_completed can 3375957ba3STom Herbert * be executed concurrently (i.e. they can be protected by different locks). 3475957ba3STom Herbert */ 3575957ba3STom Herbert 3675957ba3STom Herbert #ifndef _LINUX_DQL_H 3775957ba3STom Herbert #define _LINUX_DQL_H 3875957ba3STom Herbert 3975957ba3STom Herbert #ifdef __KERNEL__ 4075957ba3STom Herbert 416025b913SJakub Kicinski #include <linux/bitops.h> 420cd39f46SPeter Zijlstra #include <asm/bug.h> 430cd39f46SPeter Zijlstra 446025b913SJakub Kicinski #define DQL_HIST_LEN 4 456025b913SJakub Kicinski #define DQL_HIST_ENT(dql, idx) ((dql)->history[(idx) % DQL_HIST_LEN]) 466025b913SJakub Kicinski 4775957ba3STom Herbert struct dql { 4875957ba3STom Herbert /* Fields accessed in enqueue path (dql_queued) */ 4975957ba3STom Herbert unsigned int num_queued; /* Total ever queued */ 5075957ba3STom Herbert unsigned int adj_limit; /* limit + num_completed */ 5175957ba3STom Herbert unsigned int last_obj_cnt; /* Count at last queuing */ 5275957ba3STom Herbert 53*4ba67ef3SBreno Leitao /* Stall threshold (in jiffies), defined by user */ 54*4ba67ef3SBreno Leitao unsigned short stall_thrs; 55*4ba67ef3SBreno Leitao 566025b913SJakub Kicinski unsigned long history_head; /* top 58 bits of jiffies */ 576025b913SJakub Kicinski /* stall entries, a bit per entry */ 586025b913SJakub Kicinski unsigned long history[DQL_HIST_LEN]; 596025b913SJakub Kicinski 6075957ba3STom Herbert /* Fields accessed only by completion path (dql_completed) */ 6175957ba3STom Herbert 6275957ba3STom Herbert unsigned int limit ____cacheline_aligned_in_smp; /* Current limit */ 6375957ba3STom Herbert unsigned int num_completed; /* Total ever completed */ 6475957ba3STom Herbert 6575957ba3STom Herbert unsigned int prev_ovlimit; /* Previous over limit */ 6675957ba3STom Herbert unsigned int prev_num_queued; /* Previous queue total */ 6775957ba3STom Herbert unsigned int prev_last_obj_cnt; /* Previous queuing cnt */ 6875957ba3STom Herbert 6975957ba3STom Herbert unsigned int lowest_slack; /* Lowest slack found */ 7075957ba3STom Herbert unsigned long slack_start_time; /* Time slacks seen */ 7175957ba3STom Herbert 7275957ba3STom Herbert /* Configuration */ 7375957ba3STom Herbert unsigned int max_limit; /* Max limit */ 7475957ba3STom Herbert unsigned int min_limit; /* Minimum limit */ 7575957ba3STom Herbert unsigned int slack_hold_time; /* Time to measure slack */ 766025b913SJakub Kicinski 776025b913SJakub Kicinski /* Longest stall detected, reported to user */ 786025b913SJakub Kicinski unsigned short stall_max; 796025b913SJakub Kicinski unsigned long last_reap; /* Last reap (in jiffies) */ 806025b913SJakub Kicinski unsigned long stall_cnt; /* Number of stalls */ 8175957ba3STom Herbert }; 8275957ba3STom Herbert 8375957ba3STom Herbert /* Set some static maximums */ 8475957ba3STom Herbert #define DQL_MAX_OBJECT (UINT_MAX / 16) 8575957ba3STom Herbert #define DQL_MAX_LIMIT ((UINT_MAX / 2) - DQL_MAX_OBJECT) 8675957ba3STom Herbert 87cbe481a1SBreno Leitao /* Populate the bitmap to be processed later in dql_check_stall() */ 88cbe481a1SBreno Leitao static inline void dql_queue_stall(struct dql *dql) 8975957ba3STom Herbert { 906025b913SJakub Kicinski unsigned long map, now, now_hi, i; 916025b913SJakub Kicinski 926025b913SJakub Kicinski now = jiffies; 936025b913SJakub Kicinski now_hi = now / BITS_PER_LONG; 946025b913SJakub Kicinski 956025b913SJakub Kicinski /* The following code set a bit in the ring buffer, where each 966025b913SJakub Kicinski * bit trackes time the packet was queued. The dql->history buffer 976025b913SJakub Kicinski * tracks DQL_HIST_LEN * BITS_PER_LONG time (jiffies) slot 986025b913SJakub Kicinski */ 996025b913SJakub Kicinski if (unlikely(now_hi != dql->history_head)) { 1006025b913SJakub Kicinski /* About to reuse slots, clear them */ 1016025b913SJakub Kicinski for (i = 0; i < DQL_HIST_LEN; i++) { 1026025b913SJakub Kicinski /* Multiplication masks high bits */ 1036025b913SJakub Kicinski if (now_hi * BITS_PER_LONG == 1046025b913SJakub Kicinski (dql->history_head + i) * BITS_PER_LONG) 1056025b913SJakub Kicinski break; 1066025b913SJakub Kicinski DQL_HIST_ENT(dql, dql->history_head + i + 1) = 0; 1076025b913SJakub Kicinski } 1086025b913SJakub Kicinski /* pairs with smp_rmb() in dql_check_stall() */ 1096025b913SJakub Kicinski smp_wmb(); 1106025b913SJakub Kicinski WRITE_ONCE(dql->history_head, now_hi); 1116025b913SJakub Kicinski } 1126025b913SJakub Kicinski 1136025b913SJakub Kicinski /* __set_bit() does not guarantee WRITE_ONCE() semantics */ 1146025b913SJakub Kicinski map = DQL_HIST_ENT(dql, now_hi); 1156025b913SJakub Kicinski 1166025b913SJakub Kicinski /* Populate the history with an entry (bit) per queued */ 1176025b913SJakub Kicinski if (!(map & BIT_MASK(now))) 1186025b913SJakub Kicinski WRITE_ONCE(DQL_HIST_ENT(dql, now_hi), map | BIT_MASK(now)); 11975957ba3STom Herbert } 12075957ba3STom Herbert 121cbe481a1SBreno Leitao /* 122cbe481a1SBreno Leitao * Record number of objects queued. Assumes that caller has already checked 123cbe481a1SBreno Leitao * availability in the queue with dql_avail. 124cbe481a1SBreno Leitao */ 125cbe481a1SBreno Leitao static inline void dql_queued(struct dql *dql, unsigned int count) 126cbe481a1SBreno Leitao { 127cbe481a1SBreno Leitao if (WARN_ON_ONCE(count > DQL_MAX_OBJECT)) 128cbe481a1SBreno Leitao return; 129cbe481a1SBreno Leitao 130cbe481a1SBreno Leitao dql->last_obj_cnt = count; 131cbe481a1SBreno Leitao 132cbe481a1SBreno Leitao /* We want to force a write first, so that cpu do not attempt 133cbe481a1SBreno Leitao * to get cache line containing last_obj_cnt, num_queued, adj_limit 134cbe481a1SBreno Leitao * in Shared state, but directly does a Request For Ownership 135cbe481a1SBreno Leitao * It is only a hint, we use barrier() only. 136cbe481a1SBreno Leitao */ 137cbe481a1SBreno Leitao barrier(); 138cbe481a1SBreno Leitao 139cbe481a1SBreno Leitao dql->num_queued += count; 140cbe481a1SBreno Leitao 141721f076bSBreno Leitao /* Only populate stall information if the threshold is set */ 142721f076bSBreno Leitao if (READ_ONCE(dql->stall_thrs)) 143cbe481a1SBreno Leitao dql_queue_stall(dql); 144cbe481a1SBreno Leitao } 145cbe481a1SBreno Leitao 14675957ba3STom Herbert /* Returns how many objects can be queued, < 0 indicates over limit. */ 14775957ba3STom Herbert static inline int dql_avail(const struct dql *dql) 14875957ba3STom Herbert { 1496aa7de05SMark Rutland return READ_ONCE(dql->adj_limit) - READ_ONCE(dql->num_queued); 15075957ba3STom Herbert } 15175957ba3STom Herbert 15275957ba3STom Herbert /* Record number of completed objects and recalculate the limit. */ 15375957ba3STom Herbert void dql_completed(struct dql *dql, unsigned int count); 15475957ba3STom Herbert 15575957ba3STom Herbert /* Reset dql state */ 15675957ba3STom Herbert void dql_reset(struct dql *dql); 15775957ba3STom Herbert 15875957ba3STom Herbert /* Initialize dql state */ 1597a0947e7SStephen Hemminger void dql_init(struct dql *dql, unsigned int hold_time); 16075957ba3STom Herbert 16175957ba3STom Herbert #endif /* _KERNEL_ */ 16275957ba3STom Herbert 16375957ba3STom Herbert #endif /* _LINUX_DQL_H */ 164