History

net/mlx5: Introduce EQ polling budget

Multiple EQs may share the same irq in subsequent patches. To avoid starvation, a budget is set per EQ's interrupt handler. Because of this change, it is no longer required to check that MLX5_NUM_SPARE_EQE eqes were polled (to detect that arm is required). It is guaranteed that MLX5_NUM_SPARE_EQE > budget, therefore the handler will arm and exit the handler before all the entries in the eq are polled. In the scenario where the handler is out of budget and there are more EQEs to poll, arming the EQ guarantees that the HW will send another interrupt and the handler will be called again.

Yuval Avnery committed 7 years ago

Commit 081cc2d1 parent 86eec501 file · +27 −28Browse files

Unified · Split

drivers/net/ethernet/mellanox/mlx5/core/eq.c+27−28
@@ -61,6 +61,16 @@ enum { · 60 unmodified lines
61 MLX5_EQ_DOORBEL_OFFSET = 0x40,61 MLX5_EQ_DOORBEL_OFFSET = 0x40,
62};62};
63 63
64/* budget must be smaller than MLX5_NUM_SPARE_EQE to guarantee that we update
65 * the ci before we polled all the entries in the EQ. MLX5_NUM_SPARE_EQE is
66 * used to set the EQ size, budget must be smaller than the EQ size.
67 */
68enum {
69 MLX5_EQ_POLLING_BUDGET = 128,
70};
71
72static_assert(MLX5_EQ_POLLING_BUDGET <= MLX5_NUM_SPARE_EQE);
73
64struct mlx5_irq_info {74struct mlx5_irq_info {
65 cpumask_var_t mask;75 cpumask_var_t mask;
66 char name[MLX5_MAX_IRQ_NAME];76 char name[MLX5_MAX_IRQ_NAME];
@@ -129,11 +139,16 @@ static irqreturn_t mlx5_eq_comp_int(int irq, void *eq_ptr) · 62 unmodified lines
129 struct mlx5_eq_comp *eq_comp = eq_ptr;139 struct mlx5_eq_comp *eq_comp = eq_ptr;
130 struct mlx5_eq *eq = eq_ptr;140 struct mlx5_eq *eq = eq_ptr;
131 struct mlx5_eqe *eqe;141 struct mlx5_eqe *eqe;
132 int set_ci = 0;142 int num_eqes = 0;
133 u32 cqn = -1;143 u32 cqn = -1;
134 144
135 while ((eqe = next_eqe_sw(eq))) {145 eqe = next_eqe_sw(eq);
146 if (!eqe)
147 goto out;
148
149 do {
136 struct mlx5_core_cq *cq;150 struct mlx5_core_cq *cq;
151
137 /* Make sure we read EQ entry contents after we've152 /* Make sure we read EQ entry contents after we've
138 * checked the ownership bit.153 * checked the ownership bit.
139 */154 */
@@ -151,20 +166,10 @@ static irqreturn_t mlx5_eq_comp_int(int irq, void *eq_ptr) · 11 unmodified lines
151 }166 }
152 167
153 ++eq->cons_index;168 ++eq->cons_index;
154 ++set_ci;
155 169
156 /* The HCA will think the queue has overflowed if we170 } while ((++num_eqes < MLX5_EQ_POLLING_BUDGET) && (eqe = next_eqe_sw(eq)));
157 * don't tell it we've been processing events. We
158 * create our EQs with MLX5_NUM_SPARE_EQE extra
159 * entries, so we must update our consumer index at
160 * least that often.
161 */
162 if (unlikely(set_ci >= MLX5_NUM_SPARE_EQE)) {
163 eq_update_ci(eq, 0);
164 set_ci = 0;
165 }
166 }
167 171
172out:
168 eq_update_ci(eq, 1);173 eq_update_ci(eq, 1);
169 174
170 if (cqn != -1)175 if (cqn != -1)
@@ -197,12 +202,16 @@ static irqreturn_t mlx5_eq_async_int(int irq, void *eq_ptr) · 26 unmodified lines
197 struct mlx5_eq_table *eqt;202 struct mlx5_eq_table *eqt;
198 struct mlx5_core_dev *dev;203 struct mlx5_core_dev *dev;
199 struct mlx5_eqe *eqe;204 struct mlx5_eqe *eqe;
200 int set_ci = 0;205 int num_eqes = 0;
201 206
202 dev = eq->dev;207 dev = eq->dev;
203 eqt = dev->priv.eq_table;208 eqt = dev->priv.eq_table;
204 209
205 while ((eqe = next_eqe_sw(eq))) {210 eqe = next_eqe_sw(eq);
211 if (!eqe)
212 goto out;
213
214 do {
206 /*215 /*
207 * Make sure we read EQ entry contents after we've216 * Make sure we read EQ entry contents after we've
208 * checked the ownership bit.217 * checked the ownership bit.
@@ -217,20 +226,10 @@ static irqreturn_t mlx5_eq_async_int(int irq, void *eq_ptr) · 8 unmodified lines
217 atomic_notifier_call_chain(&eqt->nh[MLX5_EVENT_TYPE_NOTIFY_ANY], eqe->type, eqe);226 atomic_notifier_call_chain(&eqt->nh[MLX5_EVENT_TYPE_NOTIFY_ANY], eqe->type, eqe);
218 227
219 ++eq->cons_index;228 ++eq->cons_index;
220 ++set_ci;
221 229
222 /* The HCA will think the queue has overflowed if we230 } while ((++num_eqes < MLX5_EQ_POLLING_BUDGET) && (eqe = next_eqe_sw(eq)));
223 * don't tell it we've been processing events. We
224 * create our EQs with MLX5_NUM_SPARE_EQE extra
225 * entries, so we must update our consumer index at
226 * least that often.
227 */
228 if (unlikely(set_ci >= MLX5_NUM_SPARE_EQE)) {
229 eq_update_ci(eq, 0);
230 set_ci = 0;
231 }
232 }
233 231
232out:
234 eq_update_ci(eq, 1);233 eq_update_ci(eq, 1);
235 234
236 return IRQ_HANDLED;235 return IRQ_HANDLED;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t