diff options
author | Saeed Mahameed <saeedm@mellanox.com> | 2018-02-01 06:32:00 -0500 |
---|---|---|
committer | Saeed Mahameed <saeedm@mellanox.com> | 2018-02-15 03:30:01 -0500 |
commit | f105b45bf77ced96e516e1cd771c41bb7e8c830b (patch) | |
tree | bc86d8533f9f0ffc3187d7bf13565610f2e3f15e | |
parent | d5c07157dd4f5ab9123eaab7db572ca360c19a55 (diff) |
net/mlx5: CQ hold/put API
Now as the CQ table is per EQ, add an API to hold/put CQ to be used from
eq.c in downstream patch.
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Reviewed-by: Gal Pressman <galp@mellanox.com>
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/cq.c | 42 | ||||
-rw-r--r-- | include/linux/mlx5/cq.h | 11 |
2 files changed, 30 insertions, 23 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cq.c b/drivers/net/ethernet/mellanox/mlx5/core/cq.c index f6e478d05ecc..06dc7bd302ed 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cq.c | |||
@@ -58,8 +58,7 @@ void mlx5_cq_tasklet_cb(unsigned long data) | |||
58 | tasklet_ctx.list) { | 58 | tasklet_ctx.list) { |
59 | list_del_init(&mcq->tasklet_ctx.list); | 59 | list_del_init(&mcq->tasklet_ctx.list); |
60 | mcq->tasklet_ctx.comp(mcq); | 60 | mcq->tasklet_ctx.comp(mcq); |
61 | if (refcount_dec_and_test(&mcq->refcount)) | 61 | mlx5_cq_put(mcq); |
62 | complete(&mcq->free); | ||
63 | if (time_after(jiffies, end)) | 62 | if (time_after(jiffies, end)) |
64 | break; | 63 | break; |
65 | } | 64 | } |
@@ -80,23 +79,31 @@ static void mlx5_add_cq_to_tasklet(struct mlx5_core_cq *cq) | |||
80 | * still arrive. | 79 | * still arrive. |
81 | */ | 80 | */ |
82 | if (list_empty_careful(&cq->tasklet_ctx.list)) { | 81 | if (list_empty_careful(&cq->tasklet_ctx.list)) { |
83 | refcount_inc(&cq->refcount); | 82 | mlx5_cq_hold(cq); |
84 | list_add_tail(&cq->tasklet_ctx.list, &tasklet_ctx->list); | 83 | list_add_tail(&cq->tasklet_ctx.list, &tasklet_ctx->list); |
85 | } | 84 | } |
86 | spin_unlock_irqrestore(&tasklet_ctx->lock, flags); | 85 | spin_unlock_irqrestore(&tasklet_ctx->lock, flags); |
87 | } | 86 | } |
88 | 87 | ||
89 | void mlx5_cq_completion(struct mlx5_eq *eq, u32 cqn) | 88 | /* caller must eventually call mlx5_cq_put on the returned cq */ |
89 | static struct mlx5_core_cq *mlx5_eq_cq_get(struct mlx5_eq *eq, u32 cqn) | ||
90 | { | 90 | { |
91 | struct mlx5_cq_table *table = &eq->cq_table; | 91 | struct mlx5_cq_table *table = &eq->cq_table; |
92 | struct mlx5_core_cq *cq; | 92 | struct mlx5_core_cq *cq = NULL; |
93 | 93 | ||
94 | spin_lock(&table->lock); | 94 | spin_lock(&table->lock); |
95 | cq = radix_tree_lookup(&table->tree, cqn); | 95 | cq = radix_tree_lookup(&table->tree, cqn); |
96 | if (likely(cq)) | 96 | if (likely(cq)) |
97 | refcount_inc(&cq->refcount); | 97 | mlx5_cq_hold(cq); |
98 | spin_unlock(&table->lock); | 98 | spin_unlock(&table->lock); |
99 | 99 | ||
100 | return cq; | ||
101 | } | ||
102 | |||
103 | void mlx5_cq_completion(struct mlx5_eq *eq, u32 cqn) | ||
104 | { | ||
105 | struct mlx5_core_cq *cq = mlx5_eq_cq_get(eq, cqn); | ||
106 | |||
100 | if (unlikely(!cq)) { | 107 | if (unlikely(!cq)) { |
101 | mlx5_core_warn(eq->dev, "Completion event for bogus CQ 0x%x\n", cqn); | 108 | mlx5_core_warn(eq->dev, "Completion event for bogus CQ 0x%x\n", cqn); |
102 | return; | 109 | return; |
@@ -106,22 +113,12 @@ void mlx5_cq_completion(struct mlx5_eq *eq, u32 cqn) | |||
106 | 113 | ||
107 | cq->comp(cq); | 114 | cq->comp(cq); |
108 | 115 | ||
109 | if (refcount_dec_and_test(&cq->refcount)) | 116 | mlx5_cq_put(cq); |
110 | complete(&cq->free); | ||
111 | } | 117 | } |
112 | 118 | ||
113 | void mlx5_cq_event(struct mlx5_eq *eq, u32 cqn, int event_type) | 119 | void mlx5_cq_event(struct mlx5_eq *eq, u32 cqn, int event_type) |
114 | { | 120 | { |
115 | struct mlx5_cq_table *table = &eq->cq_table; | 121 | struct mlx5_core_cq *cq = mlx5_eq_cq_get(eq, cqn); |
116 | struct mlx5_core_cq *cq; | ||
117 | |||
118 | spin_lock(&table->lock); | ||
119 | |||
120 | cq = radix_tree_lookup(&table->tree, cqn); | ||
121 | if (likely(cq)) | ||
122 | refcount_inc(&cq->refcount); | ||
123 | |||
124 | spin_unlock(&table->lock); | ||
125 | 122 | ||
126 | if (unlikely(!cq)) { | 123 | if (unlikely(!cq)) { |
127 | mlx5_core_warn(eq->dev, "Async event for bogus CQ 0x%x\n", cqn); | 124 | mlx5_core_warn(eq->dev, "Async event for bogus CQ 0x%x\n", cqn); |
@@ -130,8 +127,7 @@ void mlx5_cq_event(struct mlx5_eq *eq, u32 cqn, int event_type) | |||
130 | 127 | ||
131 | cq->event(cq, event_type); | 128 | cq->event(cq, event_type); |
132 | 129 | ||
133 | if (refcount_dec_and_test(&cq->refcount)) | 130 | mlx5_cq_put(cq); |
134 | complete(&cq->free); | ||
135 | } | 131 | } |
136 | 132 | ||
137 | int mlx5_core_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, | 133 | int mlx5_core_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, |
@@ -158,7 +154,8 @@ int mlx5_core_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, | |||
158 | cq->cons_index = 0; | 154 | cq->cons_index = 0; |
159 | cq->arm_sn = 0; | 155 | cq->arm_sn = 0; |
160 | cq->eq = eq; | 156 | cq->eq = eq; |
161 | refcount_set(&cq->refcount, 1); | 157 | refcount_set(&cq->refcount, 0); |
158 | mlx5_cq_hold(cq); | ||
162 | init_completion(&cq->free); | 159 | init_completion(&cq->free); |
163 | if (!cq->comp) | 160 | if (!cq->comp) |
164 | cq->comp = mlx5_add_cq_to_tasklet; | 161 | cq->comp = mlx5_add_cq_to_tasklet; |
@@ -221,8 +218,7 @@ int mlx5_core_destroy_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq) | |||
221 | synchronize_irq(cq->irqn); | 218 | synchronize_irq(cq->irqn); |
222 | 219 | ||
223 | mlx5_debug_cq_remove(dev, cq); | 220 | mlx5_debug_cq_remove(dev, cq); |
224 | if (refcount_dec_and_test(&cq->refcount)) | 221 | mlx5_cq_put(cq); |
225 | complete(&cq->free); | ||
226 | wait_for_completion(&cq->free); | 222 | wait_for_completion(&cq->free); |
227 | 223 | ||
228 | return 0; | 224 | return 0; |
diff --git a/include/linux/mlx5/cq.h b/include/linux/mlx5/cq.h index 06ba425a6ad7..445ad194e0fe 100644 --- a/include/linux/mlx5/cq.h +++ b/include/linux/mlx5/cq.h | |||
@@ -172,6 +172,17 @@ static inline void mlx5_cq_arm(struct mlx5_core_cq *cq, u32 cmd, | |||
172 | mlx5_write64(doorbell, uar_page + MLX5_CQ_DOORBELL, NULL); | 172 | mlx5_write64(doorbell, uar_page + MLX5_CQ_DOORBELL, NULL); |
173 | } | 173 | } |
174 | 174 | ||
175 | static inline void mlx5_cq_hold(struct mlx5_core_cq *cq) | ||
176 | { | ||
177 | refcount_inc(&cq->refcount); | ||
178 | } | ||
179 | |||
180 | static inline void mlx5_cq_put(struct mlx5_core_cq *cq) | ||
181 | { | ||
182 | if (refcount_dec_and_test(&cq->refcount)) | ||
183 | complete(&cq->free); | ||
184 | } | ||
185 | |||
175 | int mlx5_core_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, | 186 | int mlx5_core_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, |
176 | u32 *in, int inlen); | 187 | u32 *in, int inlen); |
177 | int mlx5_core_destroy_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq); | 188 | int mlx5_core_destroy_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq); |