2 * Copyright (c) 2013-2015, Mellanox Technologies. All rights reserved.
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 #include <linux/interrupt.h>
34 #include <linux/module.h>
35 #include <linux/mlx5/driver.h>
36 #include <linux/mlx5/cmd.h>
37 #include "mlx5_core.h"
38 #ifdef CONFIG_MLX5_CORE_EN
43 MLX5_EQE_SIZE
= sizeof(struct mlx5_eqe
),
44 MLX5_EQE_OWNER_INIT_VAL
= 0x1,
48 MLX5_EQ_STATE_ARMED
= 0x9,
49 MLX5_EQ_STATE_FIRED
= 0xa,
50 MLX5_EQ_STATE_ALWAYS_ARMED
= 0xb,
54 MLX5_NUM_SPARE_EQE
= 0x80,
55 MLX5_NUM_ASYNC_EQE
= 0x100,
56 MLX5_NUM_CMD_EQE
= 32,
60 MLX5_EQ_DOORBEL_OFFSET
= 0x40,
63 #define MLX5_ASYNC_EVENT_MASK ((1ull << MLX5_EVENT_TYPE_PATH_MIG) | \
64 (1ull << MLX5_EVENT_TYPE_COMM_EST) | \
65 (1ull << MLX5_EVENT_TYPE_SQ_DRAINED) | \
66 (1ull << MLX5_EVENT_TYPE_CQ_ERROR) | \
67 (1ull << MLX5_EVENT_TYPE_WQ_CATAS_ERROR) | \
68 (1ull << MLX5_EVENT_TYPE_PATH_MIG_FAILED) | \
69 (1ull << MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR) | \
70 (1ull << MLX5_EVENT_TYPE_WQ_ACCESS_ERROR) | \
71 (1ull << MLX5_EVENT_TYPE_PORT_CHANGE) | \
72 (1ull << MLX5_EVENT_TYPE_SRQ_CATAS_ERROR) | \
73 (1ull << MLX5_EVENT_TYPE_SRQ_LAST_WQE) | \
74 (1ull << MLX5_EVENT_TYPE_SRQ_RQ_LIMIT))
87 static int mlx5_cmd_destroy_eq(struct mlx5_core_dev
*dev
, u8 eqn
)
89 struct mlx5_destroy_eq_mbox_in in
;
90 struct mlx5_destroy_eq_mbox_out out
;
93 memset(&in
, 0, sizeof(in
));
94 memset(&out
, 0, sizeof(out
));
95 in
.hdr
.opcode
= cpu_to_be16(MLX5_CMD_OP_DESTROY_EQ
);
97 err
= mlx5_cmd_exec(dev
, &in
, sizeof(in
), &out
, sizeof(out
));
102 err
= mlx5_cmd_status_to_err(&out
.hdr
);
108 static struct mlx5_eqe
*get_eqe(struct mlx5_eq
*eq
, u32 entry
)
110 return mlx5_buf_offset(&eq
->buf
, entry
* MLX5_EQE_SIZE
);
113 static struct mlx5_eqe
*next_eqe_sw(struct mlx5_eq
*eq
)
115 struct mlx5_eqe
*eqe
= get_eqe(eq
, eq
->cons_index
& (eq
->nent
- 1));
117 return ((eqe
->owner
& 1) ^ !!(eq
->cons_index
& eq
->nent
)) ? NULL
: eqe
;
120 static const char *eqe_type_str(u8 type
)
123 case MLX5_EVENT_TYPE_COMP
:
124 return "MLX5_EVENT_TYPE_COMP";
125 case MLX5_EVENT_TYPE_PATH_MIG
:
126 return "MLX5_EVENT_TYPE_PATH_MIG";
127 case MLX5_EVENT_TYPE_COMM_EST
:
128 return "MLX5_EVENT_TYPE_COMM_EST";
129 case MLX5_EVENT_TYPE_SQ_DRAINED
:
130 return "MLX5_EVENT_TYPE_SQ_DRAINED";
131 case MLX5_EVENT_TYPE_SRQ_LAST_WQE
:
132 return "MLX5_EVENT_TYPE_SRQ_LAST_WQE";
133 case MLX5_EVENT_TYPE_SRQ_RQ_LIMIT
:
134 return "MLX5_EVENT_TYPE_SRQ_RQ_LIMIT";
135 case MLX5_EVENT_TYPE_CQ_ERROR
:
136 return "MLX5_EVENT_TYPE_CQ_ERROR";
137 case MLX5_EVENT_TYPE_WQ_CATAS_ERROR
:
138 return "MLX5_EVENT_TYPE_WQ_CATAS_ERROR";
139 case MLX5_EVENT_TYPE_PATH_MIG_FAILED
:
140 return "MLX5_EVENT_TYPE_PATH_MIG_FAILED";
141 case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR
:
142 return "MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR";
143 case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR
:
144 return "MLX5_EVENT_TYPE_WQ_ACCESS_ERROR";
145 case MLX5_EVENT_TYPE_SRQ_CATAS_ERROR
:
146 return "MLX5_EVENT_TYPE_SRQ_CATAS_ERROR";
147 case MLX5_EVENT_TYPE_INTERNAL_ERROR
:
148 return "MLX5_EVENT_TYPE_INTERNAL_ERROR";
149 case MLX5_EVENT_TYPE_PORT_CHANGE
:
150 return "MLX5_EVENT_TYPE_PORT_CHANGE";
151 case MLX5_EVENT_TYPE_GPIO_EVENT
:
152 return "MLX5_EVENT_TYPE_GPIO_EVENT";
153 case MLX5_EVENT_TYPE_REMOTE_CONFIG
:
154 return "MLX5_EVENT_TYPE_REMOTE_CONFIG";
155 case MLX5_EVENT_TYPE_DB_BF_CONGESTION
:
156 return "MLX5_EVENT_TYPE_DB_BF_CONGESTION";
157 case MLX5_EVENT_TYPE_STALL_EVENT
:
158 return "MLX5_EVENT_TYPE_STALL_EVENT";
159 case MLX5_EVENT_TYPE_CMD
:
160 return "MLX5_EVENT_TYPE_CMD";
161 case MLX5_EVENT_TYPE_PAGE_REQUEST
:
162 return "MLX5_EVENT_TYPE_PAGE_REQUEST";
163 case MLX5_EVENT_TYPE_PAGE_FAULT
:
164 return "MLX5_EVENT_TYPE_PAGE_FAULT";
166 return "Unrecognized event";
170 static enum mlx5_dev_event
port_subtype_event(u8 subtype
)
173 case MLX5_PORT_CHANGE_SUBTYPE_DOWN
:
174 return MLX5_DEV_EVENT_PORT_DOWN
;
175 case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE
:
176 return MLX5_DEV_EVENT_PORT_UP
;
177 case MLX5_PORT_CHANGE_SUBTYPE_INITIALIZED
:
178 return MLX5_DEV_EVENT_PORT_INITIALIZED
;
179 case MLX5_PORT_CHANGE_SUBTYPE_LID
:
180 return MLX5_DEV_EVENT_LID_CHANGE
;
181 case MLX5_PORT_CHANGE_SUBTYPE_PKEY
:
182 return MLX5_DEV_EVENT_PKEY_CHANGE
;
183 case MLX5_PORT_CHANGE_SUBTYPE_GUID
:
184 return MLX5_DEV_EVENT_GUID_CHANGE
;
185 case MLX5_PORT_CHANGE_SUBTYPE_CLIENT_REREG
:
186 return MLX5_DEV_EVENT_CLIENT_REREG
;
191 static void eq_update_ci(struct mlx5_eq
*eq
, int arm
)
193 __be32 __iomem
*addr
= eq
->doorbell
+ (arm
? 0 : 2);
194 u32 val
= (eq
->cons_index
& 0xffffff) | (eq
->eqn
<< 24);
195 __raw_writel((__force u32
) cpu_to_be32(val
), addr
);
196 /* We still want ordering, just not swabbing, so add a barrier */
200 static int mlx5_eq_int(struct mlx5_core_dev
*dev
, struct mlx5_eq
*eq
)
202 struct mlx5_eqe
*eqe
;
209 while ((eqe
= next_eqe_sw(eq
))) {
211 * Make sure we read EQ entry contents after we've
212 * checked the ownership bit.
216 mlx5_core_dbg(eq
->dev
, "eqn %d, eqe type %s\n",
217 eq
->eqn
, eqe_type_str(eqe
->type
));
219 case MLX5_EVENT_TYPE_COMP
:
220 cqn
= be32_to_cpu(eqe
->data
.comp
.cqn
) & 0xffffff;
221 mlx5_cq_completion(dev
, cqn
);
224 case MLX5_EVENT_TYPE_PATH_MIG
:
225 case MLX5_EVENT_TYPE_COMM_EST
:
226 case MLX5_EVENT_TYPE_SQ_DRAINED
:
227 case MLX5_EVENT_TYPE_SRQ_LAST_WQE
:
228 case MLX5_EVENT_TYPE_WQ_CATAS_ERROR
:
229 case MLX5_EVENT_TYPE_PATH_MIG_FAILED
:
230 case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR
:
231 case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR
:
232 rsn
= be32_to_cpu(eqe
->data
.qp_srq
.qp_srq_n
) & 0xffffff;
233 rsn
|= (eqe
->data
.qp_srq
.type
<< MLX5_USER_INDEX_LEN
);
234 mlx5_core_dbg(dev
, "event %s(%d) arrived on resource 0x%x\n",
235 eqe_type_str(eqe
->type
), eqe
->type
, rsn
);
236 mlx5_rsc_event(dev
, rsn
, eqe
->type
);
239 case MLX5_EVENT_TYPE_SRQ_RQ_LIMIT
:
240 case MLX5_EVENT_TYPE_SRQ_CATAS_ERROR
:
241 rsn
= be32_to_cpu(eqe
->data
.qp_srq
.qp_srq_n
) & 0xffffff;
242 mlx5_core_dbg(dev
, "SRQ event %s(%d): srqn 0x%x\n",
243 eqe_type_str(eqe
->type
), eqe
->type
, rsn
);
244 mlx5_srq_event(dev
, rsn
, eqe
->type
);
247 case MLX5_EVENT_TYPE_CMD
:
248 mlx5_cmd_comp_handler(dev
, be32_to_cpu(eqe
->data
.cmd
.vector
));
251 case MLX5_EVENT_TYPE_PORT_CHANGE
:
252 port
= (eqe
->data
.port
.port
>> 4) & 0xf;
253 switch (eqe
->sub_type
) {
254 case MLX5_PORT_CHANGE_SUBTYPE_DOWN
:
255 case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE
:
256 case MLX5_PORT_CHANGE_SUBTYPE_LID
:
257 case MLX5_PORT_CHANGE_SUBTYPE_PKEY
:
258 case MLX5_PORT_CHANGE_SUBTYPE_GUID
:
259 case MLX5_PORT_CHANGE_SUBTYPE_CLIENT_REREG
:
260 case MLX5_PORT_CHANGE_SUBTYPE_INITIALIZED
:
262 dev
->event(dev
, port_subtype_event(eqe
->sub_type
),
263 (unsigned long)port
);
266 mlx5_core_warn(dev
, "Port event with unrecognized subtype: port %d, sub_type %d\n",
267 port
, eqe
->sub_type
);
270 case MLX5_EVENT_TYPE_CQ_ERROR
:
271 cqn
= be32_to_cpu(eqe
->data
.cq_err
.cqn
) & 0xffffff;
272 mlx5_core_warn(dev
, "CQ error on CQN 0x%x, syndrom 0x%x\n",
273 cqn
, eqe
->data
.cq_err
.syndrome
);
274 mlx5_cq_event(dev
, cqn
, eqe
->type
);
277 case MLX5_EVENT_TYPE_PAGE_REQUEST
:
279 u16 func_id
= be16_to_cpu(eqe
->data
.req_pages
.func_id
);
280 s32 npages
= be32_to_cpu(eqe
->data
.req_pages
.num_pages
);
282 mlx5_core_dbg(dev
, "page request for func 0x%x, npages %d\n",
284 mlx5_core_req_pages_handler(dev
, func_id
, npages
);
288 #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
289 case MLX5_EVENT_TYPE_PAGE_FAULT
:
290 mlx5_eq_pagefault(dev
, eqe
);
294 #ifdef CONFIG_MLX5_CORE_EN
295 case MLX5_EVENT_TYPE_NIC_VPORT_CHANGE
:
296 mlx5_eswitch_vport_event(dev
->priv
.eswitch
, eqe
);
300 mlx5_core_warn(dev
, "Unhandled event 0x%x on EQ 0x%x\n",
309 /* The HCA will think the queue has overflowed if we
310 * don't tell it we've been processing events. We
311 * create our EQs with MLX5_NUM_SPARE_EQE extra
312 * entries, so we must update our consumer index at
315 if (unlikely(set_ci
>= MLX5_NUM_SPARE_EQE
)) {
326 static irqreturn_t
mlx5_msix_handler(int irq
, void *eq_ptr
)
328 struct mlx5_eq
*eq
= eq_ptr
;
329 struct mlx5_core_dev
*dev
= eq
->dev
;
331 mlx5_eq_int(dev
, eq
);
333 /* MSI-X vectors always belong to us */
337 static void init_eq_buf(struct mlx5_eq
*eq
)
339 struct mlx5_eqe
*eqe
;
342 for (i
= 0; i
< eq
->nent
; i
++) {
343 eqe
= get_eqe(eq
, i
);
344 eqe
->owner
= MLX5_EQE_OWNER_INIT_VAL
;
348 int mlx5_create_map_eq(struct mlx5_core_dev
*dev
, struct mlx5_eq
*eq
, u8 vecidx
,
349 int nent
, u64 mask
, const char *name
, struct mlx5_uar
*uar
)
351 struct mlx5_priv
*priv
= &dev
->priv
;
352 struct mlx5_create_eq_mbox_in
*in
;
353 struct mlx5_create_eq_mbox_out out
;
357 eq
->nent
= roundup_pow_of_two(nent
+ MLX5_NUM_SPARE_EQE
);
359 err
= mlx5_buf_alloc(dev
, eq
->nent
* MLX5_EQE_SIZE
, &eq
->buf
);
365 inlen
= sizeof(*in
) + sizeof(in
->pas
[0]) * eq
->buf
.npages
;
366 in
= mlx5_vzalloc(inlen
);
371 memset(&out
, 0, sizeof(out
));
373 mlx5_fill_page_array(&eq
->buf
, in
->pas
);
375 in
->hdr
.opcode
= cpu_to_be16(MLX5_CMD_OP_CREATE_EQ
);
376 in
->ctx
.log_sz_usr_page
= cpu_to_be32(ilog2(eq
->nent
) << 24 | uar
->index
);
377 in
->ctx
.intr
= vecidx
;
378 in
->ctx
.log_page_size
= eq
->buf
.page_shift
- MLX5_ADAPTER_PAGE_SHIFT
;
379 in
->events_mask
= cpu_to_be64(mask
);
381 err
= mlx5_cmd_exec(dev
, in
, inlen
, &out
, sizeof(out
));
385 if (out
.hdr
.status
) {
386 err
= mlx5_cmd_status_to_err(&out
.hdr
);
390 snprintf(priv
->irq_info
[vecidx
].name
, MLX5_MAX_IRQ_NAME
, "%s@pci:%s",
391 name
, pci_name(dev
->pdev
));
393 eq
->eqn
= out
.eq_number
;
394 eq
->irqn
= priv
->msix_arr
[vecidx
].vector
;
396 eq
->doorbell
= uar
->map
+ MLX5_EQ_DOORBEL_OFFSET
;
397 err
= request_irq(eq
->irqn
, mlx5_msix_handler
, 0,
398 priv
->irq_info
[vecidx
].name
, eq
);
402 err
= mlx5_debug_eq_add(dev
, eq
);
406 /* EQs are created in ARMED state
414 free_irq(priv
->msix_arr
[vecidx
].vector
, eq
);
417 mlx5_cmd_destroy_eq(dev
, eq
->eqn
);
423 mlx5_buf_free(dev
, &eq
->buf
);
426 EXPORT_SYMBOL_GPL(mlx5_create_map_eq
);
428 int mlx5_destroy_unmap_eq(struct mlx5_core_dev
*dev
, struct mlx5_eq
*eq
)
432 mlx5_debug_eq_remove(dev
, eq
);
433 free_irq(eq
->irqn
, eq
);
434 err
= mlx5_cmd_destroy_eq(dev
, eq
->eqn
);
436 mlx5_core_warn(dev
, "failed to destroy a previously created eq: eqn %d\n",
438 synchronize_irq(eq
->irqn
);
439 mlx5_buf_free(dev
, &eq
->buf
);
443 EXPORT_SYMBOL_GPL(mlx5_destroy_unmap_eq
);
445 int mlx5_eq_init(struct mlx5_core_dev
*dev
)
449 spin_lock_init(&dev
->priv
.eq_table
.lock
);
451 err
= mlx5_eq_debugfs_init(dev
);
457 void mlx5_eq_cleanup(struct mlx5_core_dev
*dev
)
459 mlx5_eq_debugfs_cleanup(dev
);
462 int mlx5_start_eqs(struct mlx5_core_dev
*dev
)
464 struct mlx5_eq_table
*table
= &dev
->priv
.eq_table
;
465 u32 async_event_mask
= MLX5_ASYNC_EVENT_MASK
;
468 if (MLX5_CAP_GEN(dev
, pg
))
469 async_event_mask
|= (1ull << MLX5_EVENT_TYPE_PAGE_FAULT
);
471 if (MLX5_CAP_GEN(dev
, port_type
) == MLX5_CAP_PORT_TYPE_ETH
&&
472 MLX5_CAP_GEN(dev
, vport_group_manager
) &&
473 mlx5_core_is_pf(dev
))
474 async_event_mask
|= (1ull << MLX5_EVENT_TYPE_NIC_VPORT_CHANGE
);
476 err
= mlx5_create_map_eq(dev
, &table
->cmd_eq
, MLX5_EQ_VEC_CMD
,
477 MLX5_NUM_CMD_EQE
, 1ull << MLX5_EVENT_TYPE_CMD
,
478 "mlx5_cmd_eq", &dev
->priv
.uuari
.uars
[0]);
480 mlx5_core_warn(dev
, "failed to create cmd EQ %d\n", err
);
484 mlx5_cmd_use_events(dev
);
486 err
= mlx5_create_map_eq(dev
, &table
->async_eq
, MLX5_EQ_VEC_ASYNC
,
487 MLX5_NUM_ASYNC_EQE
, async_event_mask
,
488 "mlx5_async_eq", &dev
->priv
.uuari
.uars
[0]);
490 mlx5_core_warn(dev
, "failed to create async EQ %d\n", err
);
494 err
= mlx5_create_map_eq(dev
, &table
->pages_eq
,
496 /* TODO: sriov max_vf + */ 1,
497 1 << MLX5_EVENT_TYPE_PAGE_REQUEST
, "mlx5_pages_eq",
498 &dev
->priv
.uuari
.uars
[0]);
500 mlx5_core_warn(dev
, "failed to create pages EQ %d\n", err
);
507 mlx5_destroy_unmap_eq(dev
, &table
->async_eq
);
510 mlx5_cmd_use_polling(dev
);
511 mlx5_destroy_unmap_eq(dev
, &table
->cmd_eq
);
515 int mlx5_stop_eqs(struct mlx5_core_dev
*dev
)
517 struct mlx5_eq_table
*table
= &dev
->priv
.eq_table
;
520 err
= mlx5_destroy_unmap_eq(dev
, &table
->pages_eq
);
524 mlx5_destroy_unmap_eq(dev
, &table
->async_eq
);
525 mlx5_cmd_use_polling(dev
);
527 err
= mlx5_destroy_unmap_eq(dev
, &table
->cmd_eq
);
529 mlx5_cmd_use_events(dev
);
534 int mlx5_core_eq_query(struct mlx5_core_dev
*dev
, struct mlx5_eq
*eq
,
535 struct mlx5_query_eq_mbox_out
*out
, int outlen
)
537 struct mlx5_query_eq_mbox_in in
;
540 memset(&in
, 0, sizeof(in
));
541 memset(out
, 0, outlen
);
542 in
.hdr
.opcode
= cpu_to_be16(MLX5_CMD_OP_QUERY_EQ
);
544 err
= mlx5_cmd_exec(dev
, &in
, sizeof(in
), out
, outlen
);
549 err
= mlx5_cmd_status_to_err(&out
->hdr
);
553 EXPORT_SYMBOL_GPL(mlx5_core_eq_query
);