Provide more error details when a QP moves to error state
Subsystems (7)
cover Provide more error details when a QP moves to error state
From: Leon Romanovsky <[email protected]>
Changelog:
v1:
* Reworked mlx4 to allow non-atomic IB QP event handler.
v0: https://lore.kernel.org/linux-rdma/[email protected]/
------------------------------------------
The following series adds ability to get information about fatal QP events.
This functionality is extremely useful for the following reasons:
* Provides an information about the reason why QP moved to error state, in cases where CQE isn't generated.
* Allows to provide vendor specfic error codes and information that could be very useful to users who know them.
An example of a case without CQE is a remote write with RKEY violation. In this flow, on remote side no CQEs are generated and such error without indication is hard to debug.
Thanks.
Mark Zhang (1):
RDMA/mlx: Calling qp event handler in workqueue context
Patrisious Haddad (2):
net/mlx5: Introduce CQE error syndrome RDMA/mlx5: Print error syndrome in case of fatal QP errors
drivers/infiniband/hw/mlx4/main.c | 8 ++ drivers/infiniband/hw/mlx4/mlx4_ib.h | 3 + drivers/infiniband/hw/mlx4/qp.c | 121 +++++++++++------ drivers/infiniband/hw/mlx5/main.c | 7 + drivers/infiniband/hw/mlx5/qp.c | 164 ++++++++++++++++++------ drivers/infiniband/hw/mlx5/qp.h | 4 +- drivers/infiniband/hw/mlx5/qpc.c | 7 +- drivers/net/ethernet/mellanox/mlx4/qp.c | 14 +- include/linux/mlx4/qp.h | 1 + include/linux/mlx5/mlx5_ifc.h | 47 ++++++- include/rdma/ib_verbs.h | 2 +- 11 files changed, 292 insertions(+), 86 deletions(-)
Signature · 1 line
2.38.1
PATCH 1/3 RDMA/mlx: Calling qp event handler in workqueue context
From: Mark Zhang <[email protected]>
Move the call of qp event handler from atomic to workqueue context, so that the handler is able to block. This is needed by following patches.
--- drivers/infiniband/hw/mlx4/main.c | 8 ++ drivers/infiniband/hw/mlx4/mlx4_ib.h | 3 + drivers/infiniband/hw/mlx4/qp.c | 121 +++++++++++++++++------- drivers/infiniband/hw/mlx5/main.c | 7 ++ drivers/infiniband/hw/mlx5/qp.c | 119 ++++++++++++++++------- drivers/infiniband/hw/mlx5/qp.h | 2 + drivers/infiniband/hw/mlx5/qpc.c | 3 +- drivers/net/ethernet/mellanox/mlx4/qp.c | 14 ++- include/linux/mlx4/qp.h | 1 + include/rdma/ib_verbs.h | 2 +- 10 files changed, 202 insertions(+), 78 deletions(-)
drivers/infiniband/hw/mlx4/main.c +8 -0
@@ -3303,6 +3303,10 @@ static int __init mlx4_ib_init(void)if (!wq)return -ENOMEM ; + err =mlx4_ib_qp_event_init (); +if (err) + goto clean_qp_event; + err =mlx4_ib_cm_init ();if (err) goto clean_wq;
@@ -3324,6 +3328,9 @@ static int __init mlx4_ib_init(void)mlx4_ib_cm_destroy (); clean_wq: +mlx4_ib_qp_event_cleanup (); + +clean_qp_event:destroy_workqueue (wq);return err; }
@@ -3333,6 +3340,7 @@ static void __exit mlx4_ib_cleanup(void)mlx4_unregister_interface (&mlx4_ib_interface);mlx4_ib_mcg_destroy ();mlx4_ib_cm_destroy (); +mlx4_ib_qp_event_cleanup ();destroy_workqueue (wq); }
drivers/infiniband/hw/mlx4/mlx4_ib.h +3 -0
@@ -940,4 +940,7 @@ int mlx4_ib_umem_calc_optimal_mtt_size(struct ib_umem *umem, u64 start_va,int mlx4_ib_cm_init (void );void mlx4_ib_cm_destroy (void ); +int mlx4_ib_qp_event_init (void ); +void mlx4_ib_qp_event_cleanup (void ); +#endif /* MLX4_IB_H */
drivers/infiniband/hw/mlx4/qp.c +85 -36
144 lines not on this page · raw message
drivers/infiniband/hw/mlx5/main.c +7 -0
@@ -4403,6 +4403,10 @@ static int __init mlx5_ib_init(void)return -ENOMEM ; } + ret =mlx5_ib_qp_event_init (); +if (ret) + goto qp_event_err; +mlx5_ib_odp_init (); ret =mlx5r_rep_init ();if (ret)
@@ -4420,6 +4424,8 @@ static int __init mlx5_ib_init(void) mp_err:mlx5r_rep_cleanup (); rep_err: +mlx5_ib_qp_event_cleanup (); +qp_event_err:destroy_workqueue (mlx5_ib_event_wq);free_page ((unsigned long )xlt_emergency_page);return ret;
@@ -4431,6 +4437,7 @@ static void __exit mlx5_ib_cleanup(void)auxiliary_driver_unregister (&mlx5r_mp_driver);mlx5r_rep_cleanup (); +mlx5_ib_qp_event_cleanup ();destroy_workqueue (mlx5_ib_event_wq);free_page ((unsigned long )xlt_emergency_page); }
drivers/infiniband/hw/mlx5/qp.c +84 -35
144 lines not on this page · raw message
drivers/infiniband/hw/mlx5/qp.h +2 -0
@@ -44,4 +44,6 @@ void mlx5_core_res_put(struct mlx5_core_rsc_common *res);int mlx5_core_xrcd_alloc (struct mlx5_ib_dev *dev,u32 *xrcdn);int mlx5_core_xrcd_dealloc (struct mlx5_ib_dev *dev,u32 xrcdn);int mlx5_ib_qp_set_counter (struct ib_qp *qp,struct rdma_counter *counter); +int mlx5_ib_qp_event_init (void ); +void mlx5_ib_qp_event_cleanup (void );#endif /* _MLX5_IB_QP_H */
drivers/infiniband/hw/mlx5/qpc.c +2 -1
@@ -135,7 +135,8 @@ static int rsc_event_notifier(struct notifier_block *nb,case MLX5_RES_SQ : qp = (struct mlx5_core_qp *)common; qp->event (qp, event_type); -break ; +/* Need to put resource in event handler */ +return NOTIFY_OK ;case MLX5_RES_DCT : dct = (struct mlx5_core_dct *)common;if (event_type ==MLX5_EVENT_TYPE_DCT_DRAINED )
drivers/net/ethernet/mellanox/mlx4/qp.c +9 -5
@@ -46,6 +46,13 @@#define MLX4_BF_QP_SKIP_MASK 0xc0#define MLX4_MAX_BF_QP_RANGE 0x40 +void mlx4_put_qp (struct mlx4_qp *qp) +{ +if (refcount_dec_and_test (&qp->refcount)) +complete (&qp->free); +} +EXPORT_SYMBOL_GPL (mlx4_put_qp); +void mlx4_qp_event (struct mlx4_dev *dev,u32 qpn,int event_type) {struct mlx4_qp_table *qp_table = &mlx4_priv (dev)->qp_table;
@@ -64,10 +71,8 @@ void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type)return ; } +/* Need to call mlx4_put_qp() in event handler */ qp->event (qp, event_type); - -if (refcount_dec_and_test (&qp->refcount)) -complete (&qp->free); }/* used for INIT/CLOSE port logic */
@@ -523,8 +528,7 @@ EXPORT_SYMBOL_GPL(mlx4_qp_remove);void mlx4_qp_free (struct mlx4_dev *dev,struct mlx4_qp *qp) { -if (refcount_dec_and_test (&qp->refcount)) -complete (&qp->free); +mlx4_put_qp (qp);wait_for_completion (&qp->free);mlx4_qp_free_icm (dev, qp->qpn);
include/linux/mlx4/qp.h +1 -0
@@ -503,4 +503,5 @@ static inline u16 folded_qp(u32 q)u16 mlx4_qp_roce_entropy (struct mlx4_dev *dev,u32 qpn); +void mlx4_put_qp (struct mlx4_qp *qp);#endif /* MLX4_QP_H */
include/rdma/ib_verbs.h +1 -1
@@ -1168,7 +1168,7 @@ enum ib_qp_create_flags {*/ struct ib_qp_init_attr { -/* Consumer's event_handler callback must not block */ +/* This callback occurs in workqueue context */ void (*event_handler)(struct ib_event *,void *);void *qp_context;
Signature · 1 line
2.38.1
PATCH 2/3 net/mlx5: Introduce CQE error syndrome
In reply to Leon RomanovskyFrom: Patrisious Haddad <[email protected]>
Introduces CQE error syndrome bits which are inside qp_context_extension and are used to report the reason the QP was moved to error state. Useful for cases in which a CQE isn't generated, such as remote write rkey violation.
--- include/linux/mlx5/mlx5_ifc.h | 47 +++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 5 deletions(-)
include/linux/mlx5/mlx5_ifc.h +42 -5
@@ -1497,7 +1497,9 @@ struct mlx5_ifc_cmd_hca_cap_bits {u8 null_mkey[0x1 ];u8 log_max_klm_list_size[0x6 ]; -u8 reserved_at_120[0xa ]; +u8 reserved_at_120[0x2 ]; +u8 qpc_extension[0x1 ]; +u8 reserved_at_123[0x7 ];u8 log_max_ra_req_dc[0x6 ];u8 reserved_at_130[0x2 ];u8 eth_wqe_too_small[0x1 ];
@@ -1663,7 +1665,9 @@ struct mlx5_ifc_cmd_hca_cap_bits {u8 log_bf_reg_size[0x5 ]; -u8 reserved_at_270[0x6 ]; +u8 reserved_at_270[0x3 ]; +u8 qp_error_syndrome[0x1 ]; +u8 reserved_at_274[0x2 ];u8 lag_dct[0x2 ];u8 lag_tx_port_affinity[0x1 ];u8 lag_native_fdb_selection[0x1 ];
@@ -5347,6 +5351,37 @@ struct mlx5_ifc_query_rmp_in_bits {u8 reserved_at_60[0x20 ]; }; +struct mlx5_ifc_cqe_error_syndrome_bits { +u8 hw_error_syndrome[0x8 ]; +u8 hw_syndrome_type[0x4 ]; +u8 reserved_at_c[0x4 ]; +u8 vendor_error_syndrome[0x8 ]; +u8 syndrome[0x8 ]; +}; + +struct mlx5_ifc_qp_context_extension_bits { +u8 reserved_at_0[0x60 ]; + +struct mlx5_ifc_cqe_error_syndrome_bits error_syndrome; + +u8 reserved_at_80[0x580 ]; +}; + +struct mlx5_ifc_qpc_extension_and_pas_list_in_bits { +struct mlx5_ifc_qp_context_extension_bits qpc_data_extension; + +u8 pas[0 ][0x40 ]; +}; + +struct mlx5_ifc_qp_pas_list_in_bits { +struct mlx5_ifc_cmd_pas_bits pas[0 ]; +}; + +union mlx5_ifc_qp_pas_or_qpc_ext_and_pas_bits { +struct mlx5_ifc_qp_pas_list_in_bits qp_pas_list; +struct mlx5_ifc_qpc_extension_and_pas_list_in_bits qpc_ext_and_pas_list; +}; +struct mlx5_ifc_query_qp_out_bits {u8 status[0x8 ];u8 reserved_at_8[0x18 ];
@@ -5363,7 +5398,7 @@ struct mlx5_ifc_query_qp_out_bits {u8 reserved_at_800[0x80 ]; -u8 pas[][0x40 ]; +union mlx5_ifc_qp_pas_or_qpc_ext_and_pas_bits qp_pas_or_qpc_ext_and_pas; };struct mlx5_ifc_query_qp_in_bits {
@@ -5373,7 +5408,8 @@ struct mlx5_ifc_query_qp_in_bits {u8 reserved_at_20[0x10 ];u8 op_mod[0x10 ]; -u8 reserved_at_40[0x8 ]; +u8 qpc_ext[0x1 ]; +u8 reserved_at_41[0x7 ];u8 qpn[0x18 ];u8 reserved_at_60[0x20 ];
@@ -8576,7 +8612,8 @@ struct mlx5_ifc_create_qp_in_bits {u8 reserved_at_20[0x10 ];u8 op_mod[0x10 ]; -u8 reserved_at_40[0x8 ]; +u8 qpc_ext[0x1 ]; +u8 reserved_at_41[0x7 ];u8 input_qpn[0x18 ];u8 reserved_at_60[0x20 ];
Signature · 1 line
2.38.1
Re: [PATCH mlx5-next v1 2/3] net/mlx5: Introduce CQE error syndrome
Quoted 9 lines · Leon Romanovsky
From: Patrisious Haddad <[email protected]>
Introduces CQE error syndrome bits which are inside
qp_context_extensionand are used to report the reason the QP was moved to error state. Useful for cases in which a CQE isn't generated, such as remote write rkey violation.Signed-off-by Patrisious Haddad <[email protected]>Signed-off-by Leon Romanovsky <[email protected]>
PATCH 3/3 RDMA/mlx5: Print error syndrome in case of fatal QP errors
In reply to Leon RomanovskyFrom: Patrisious Haddad <[email protected]>
Print syndromes in case of fatal QP events. This is helpful for upper level debugging, as there maybe no CQEs.
--- drivers/infiniband/hw/mlx5/qp.c | 45 +++++++++++++++++++++++++++++++- drivers/infiniband/hw/mlx5/qp.h | 2 +- drivers/infiniband/hw/mlx5/qpc.c | 4 ++- 3 files changed, 48 insertions(+), 3 deletions(-)
drivers/infiniband/hw/mlx5/qp.c +44 -1
@@ -310,6 +310,44 @@ int mlx5_ib_read_wqe_srq(struct mlx5_ib_srq *srq, int wqe_index, void *buffer,return mlx5_ib_read_user_wqe_srq (srq, wqe_index, buffer, buflen, bc); } +static void mlx5_ib_qp_err_syndrome (struct ib_qp *ibqp) +{ +struct mlx5_ib_dev *dev =to_mdev (ibqp->device); +int outlen =MLX5_ST_SZ_BYTES (query_qp_out); +struct mlx5_ib_qp *qp =to_mqp (ibqp); +void *pas_ext_union, *err_syn; +u32 *outb; +int err; + +if (!MLX5_CAP_GEN (dev->mdev, qpc_extension) || + !MLX5_CAP_GEN (dev->mdev, qp_error_syndrome)) +return ; + + outb =kzalloc (outlen,GFP_KERNEL ); +if (!outb) +return ; + + err =mlx5_core_qp_query (dev, &qp->trans_qp.base.mqp, outb, outlen, + true); +if (err) + goto out; + + pas_ext_union = +MLX5_ADDR_OF (query_qp_out, outb, qp_pas_or_qpc_ext_and_pas); + err_syn =MLX5_ADDR_OF (qpc_extension_and_pas_list_in, pas_ext_union, + qpc_data_extension.error_syndrome); + +pr_err ("%s/%d: QP %d error: %s (0x%x 0x%x 0x%x)\n" , + ibqp->device->name, ibqp->port, ibqp->qp_num, +ib_wc_status_msg ( +MLX5_GET (cqe_error_syndrome, err_syn, syndrome)), +MLX5_GET (cqe_error_syndrome, err_syn, vendor_error_syndrome), +MLX5_GET (cqe_error_syndrome, err_syn, hw_syndrome_type), +MLX5_GET (cqe_error_syndrome, err_syn, hw_error_syndrome)); +out: +kfree (outb); +} +static void mlx5_ib_handle_qp_event (struct work_struct *_work) { struct mlx5_ib_qp_event_work *qpe_work =
@@ -350,6 +388,10 @@ static void mlx5_ib_handle_qp_event(struct work_struct *_work) goto out; } +if ((event.event ==IB_EVENT_QP_FATAL ) || + (event.event ==IB_EVENT_QP_ACCESS_ERR )) +mlx5_ib_qp_err_syndrome (ibqp); + ibqp->event_handler (&event, ibqp->qp_context); out:
@@ -4843,7 +4885,8 @@ static int query_qp_attr(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,if (!outb)return -ENOMEM ; - err =mlx5_core_qp_query (dev, &qp->trans_qp.base.mqp, outb, outlen); + err =mlx5_core_qp_query (dev, &qp->trans_qp.base.mqp, outb, outlen, + false);if (err) goto out;
drivers/infiniband/hw/mlx5/qp.h +1 -1
@@ -20,7 +20,7 @@ int mlx5_core_qp_modify(struct mlx5_ib_dev *dev, u16 opcode, u32 opt_param_mask,int mlx5_core_destroy_qp (struct mlx5_ib_dev *dev,struct mlx5_core_qp *qp);int mlx5_core_destroy_dct (struct mlx5_ib_dev *dev,struct mlx5_core_dct *dct);int mlx5_core_qp_query (struct mlx5_ib_dev *dev,struct mlx5_core_qp *qp, -u32 *out,int outlen); +u32 *out,int outlen,bool qpc_ext);int mlx5_core_dct_query (struct mlx5_ib_dev *dev,struct mlx5_core_dct *dct,u32 *out,int outlen);
drivers/infiniband/hw/mlx5/qpc.c +3 -1
@@ -507,12 +507,14 @@ void mlx5_cleanup_qp_table(struct mlx5_ib_dev *dev) }int mlx5_core_qp_query (struct mlx5_ib_dev *dev,struct mlx5_core_qp *qp, -u32 *out,int outlen) +u32 *out,int outlen,bool qpc_ext) {u32 in[MLX5_ST_SZ_DW (query_qp_in)] = {};MLX5_SET (query_qp_in, in, opcode,MLX5_CMD_OP_QUERY_QP );MLX5_SET (query_qp_in, in, qpn, qp->qpn); +MLX5_SET (query_qp_in, in, qpc_ext, qpc_ext); +return mlx5_cmd_exec (dev->mdev, in,sizeof (in), out, outlen); }
Signature · 1 line
2.38.1
Re: [PATCH rdma-next v1 3/3] RDMA/mlx5: Print error syndrome in case of fatal QP errors
Quoted 8 lines · Leon Romanovsky
From: Patrisious Haddad <[email protected]>
Print syndromes in case of fatal QP events. This is helpful for upper level debugging, as there maybe no CQEs.
Signed-off-by Patrisious Haddad <[email protected]>Signed-off-by Mark Zhang <[email protected]>Signed-off-by Leon Romanovsky <[email protected]>