hc
2024-01-05 071106ecf68c401173c58808b1cf5f68cc50d390
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2018 Mellanox Technologies */
 
#ifndef __LIB_MLX5_EQ_H__
#define __LIB_MLX5_EQ_H__
#include <linux/mlx5/driver.h>
#include <linux/mlx5/eq.h>
#include <linux/mlx5/cq.h>
 
#define MLX5_EQE_SIZE       (sizeof(struct mlx5_eqe))
 
struct mlx5_eq_tasklet {
   struct list_head      list;
   struct list_head      process_list;
   struct tasklet_struct task;
   spinlock_t            lock; /* lock completion tasklet list */
};
 
struct mlx5_cq_table {
   spinlock_t              lock;    /* protect radix tree */
   struct radix_tree_root  tree;
};
 
struct mlx5_eq {
   struct mlx5_core_dev    *dev;
   struct mlx5_cq_table    cq_table;
   __be32 __iomem            *doorbell;
   u32                     cons_index;
   struct mlx5_frag_buf    buf;
   unsigned int            vecidx;
   unsigned int            irqn;
   u8                      eqn;
   int                     nent;
   struct mlx5_rsc_debug   *dbg;
};
 
struct mlx5_eq_async {
   struct mlx5_eq          core;
   struct notifier_block   irq_nb;
   spinlock_t              lock; /* To avoid irq EQ handle races with resiliency flows */
};
 
struct mlx5_eq_comp {
   struct mlx5_eq          core;
   struct notifier_block   irq_nb;
   struct mlx5_eq_tasklet  tasklet_ctx;
   struct list_head        list;
};
 
static inline struct mlx5_eqe *get_eqe(struct mlx5_eq *eq, u32 entry)
{
   return mlx5_buf_offset(&eq->buf, entry * MLX5_EQE_SIZE);
}
 
static inline struct mlx5_eqe *next_eqe_sw(struct mlx5_eq *eq)
{
   struct mlx5_eqe *eqe = get_eqe(eq, eq->cons_index & (eq->nent - 1));
 
   return ((eqe->owner & 1) ^ !!(eq->cons_index & eq->nent)) ? NULL : eqe;
}
 
static inline void eq_update_ci(struct mlx5_eq *eq, int arm)
{
   __be32 __iomem *addr = eq->doorbell + (arm ? 0 : 2);
   u32 val = (eq->cons_index & 0xffffff) | (eq->eqn << 24);
 
   __raw_writel((__force u32)cpu_to_be32(val), addr);
   /* We still want ordering, just not swabbing, so add a barrier */
   mb();
}
 
int mlx5_eq_table_init(struct mlx5_core_dev *dev);
void mlx5_eq_table_cleanup(struct mlx5_core_dev *dev);
int mlx5_eq_table_create(struct mlx5_core_dev *dev);
void mlx5_eq_table_destroy(struct mlx5_core_dev *dev);
 
int mlx5_eq_add_cq(struct mlx5_eq *eq, struct mlx5_core_cq *cq);
void mlx5_eq_del_cq(struct mlx5_eq *eq, struct mlx5_core_cq *cq);
struct mlx5_eq_comp *mlx5_eqn2comp_eq(struct mlx5_core_dev *dev, int eqn);
struct mlx5_eq *mlx5_get_async_eq(struct mlx5_core_dev *dev);
void mlx5_cq_tasklet_cb(struct tasklet_struct *t);
struct cpumask *mlx5_eq_comp_cpumask(struct mlx5_core_dev *dev, int ix);
 
u32 mlx5_eq_poll_irq_disabled(struct mlx5_eq_comp *eq);
void mlx5_cmd_eq_recover(struct mlx5_core_dev *dev);
void mlx5_eq_synchronize_async_irq(struct mlx5_core_dev *dev);
void mlx5_eq_synchronize_cmd_irq(struct mlx5_core_dev *dev);
 
int mlx5_debug_eq_add(struct mlx5_core_dev *dev, struct mlx5_eq *eq);
void mlx5_debug_eq_remove(struct mlx5_core_dev *dev, struct mlx5_eq *eq);
void mlx5_eq_debugfs_init(struct mlx5_core_dev *dev);
void mlx5_eq_debugfs_cleanup(struct mlx5_core_dev *dev);
 
/* This function should only be called after mlx5_cmd_force_teardown_hca */
void mlx5_core_eq_free_irqs(struct mlx5_core_dev *dev);
 
#ifdef CONFIG_RFS_ACCEL
struct cpu_rmap *mlx5_eq_table_get_rmap(struct mlx5_core_dev *dev);
#endif
 
int mlx5_vector2irqn(struct mlx5_core_dev *dev, int vector, unsigned int *irqn);
 
#endif