/* SPDX-License-Identifier: GPL-2.0-only */ 
 | 
/* Copyright (c) 2016 Facebook 
 | 
 */ 
 | 
#ifndef __BPF_LRU_LIST_H_ 
 | 
#define __BPF_LRU_LIST_H_ 
 | 
  
 | 
#include <linux/cache.h> 
 | 
#include <linux/list.h> 
 | 
#include <linux/spinlock_types.h> 
 | 
  
 | 
#define NR_BPF_LRU_LIST_T    (3) 
 | 
#define NR_BPF_LRU_LIST_COUNT    (2) 
 | 
#define NR_BPF_LRU_LOCAL_LIST_T (2) 
 | 
#define BPF_LOCAL_LIST_T_OFFSET NR_BPF_LRU_LIST_T 
 | 
  
 | 
enum bpf_lru_list_type { 
 | 
    BPF_LRU_LIST_T_ACTIVE, 
 | 
    BPF_LRU_LIST_T_INACTIVE, 
 | 
    BPF_LRU_LIST_T_FREE, 
 | 
    BPF_LRU_LOCAL_LIST_T_FREE, 
 | 
    BPF_LRU_LOCAL_LIST_T_PENDING, 
 | 
}; 
 | 
  
 | 
struct bpf_lru_node { 
 | 
    struct list_head list; 
 | 
    u16 cpu; 
 | 
    u8 type; 
 | 
    u8 ref; 
 | 
}; 
 | 
  
 | 
struct bpf_lru_list { 
 | 
    struct list_head lists[NR_BPF_LRU_LIST_T]; 
 | 
    unsigned int counts[NR_BPF_LRU_LIST_COUNT]; 
 | 
    /* The next inactive list rotation starts from here */ 
 | 
    struct list_head *next_inactive_rotation; 
 | 
  
 | 
    raw_spinlock_t lock ____cacheline_aligned_in_smp; 
 | 
}; 
 | 
  
 | 
struct bpf_lru_locallist { 
 | 
    struct list_head lists[NR_BPF_LRU_LOCAL_LIST_T]; 
 | 
    u16 next_steal; 
 | 
    raw_spinlock_t lock; 
 | 
}; 
 | 
  
 | 
struct bpf_common_lru { 
 | 
    struct bpf_lru_list lru_list; 
 | 
    struct bpf_lru_locallist __percpu *local_list; 
 | 
}; 
 | 
  
 | 
typedef bool (*del_from_htab_func)(void *arg, struct bpf_lru_node *node); 
 | 
  
 | 
struct bpf_lru { 
 | 
    union { 
 | 
        struct bpf_common_lru common_lru; 
 | 
        struct bpf_lru_list __percpu *percpu_lru; 
 | 
    }; 
 | 
    del_from_htab_func del_from_htab; 
 | 
    void *del_arg; 
 | 
    unsigned int hash_offset; 
 | 
    unsigned int nr_scans; 
 | 
    bool percpu; 
 | 
}; 
 | 
  
 | 
static inline void bpf_lru_node_set_ref(struct bpf_lru_node *node) 
 | 
{ 
 | 
    /* ref is an approximation on access frequency.  It does not 
 | 
     * have to be very accurate.  Hence, no protection is used. 
 | 
     */ 
 | 
    if (!node->ref) 
 | 
        node->ref = 1; 
 | 
} 
 | 
  
 | 
int bpf_lru_init(struct bpf_lru *lru, bool percpu, u32 hash_offset, 
 | 
         del_from_htab_func del_from_htab, void *delete_arg); 
 | 
void bpf_lru_populate(struct bpf_lru *lru, void *buf, u32 node_offset, 
 | 
              u32 elem_size, u32 nr_elems); 
 | 
void bpf_lru_destroy(struct bpf_lru *lru); 
 | 
struct bpf_lru_node *bpf_lru_pop_free(struct bpf_lru *lru, u32 hash); 
 | 
void bpf_lru_push_free(struct bpf_lru *lru, struct bpf_lru_node *node); 
 | 
void bpf_lru_promote(struct bpf_lru *lru, struct bpf_lru_node *node); 
 | 
  
 | 
#endif 
 |