提交 01c8d803 编写于 作者: L Linus Torvalds

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma

Pull rdma fixes from Jason Gunthorpe:
 "Several driver bug fixes post in the last three weeks

   - first part of a race condition fix in mlx4 with CATAS errors

   - bad interaction with FW causing resource leaks in the mlx5 DCT flow

   - bad reporting of link speed/width in new mlx5 devices

   - user triggable OOPS in i40iw"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma:
  i40iw: Avoid panic when handling the inetdev event
  IB/mlx5: Fix mapping of link-mode to IB width and speed
  IB/mlx5: Use mlx5 core to create/destroy a DEVX DCT
  net/mlx5: Fix DCT creation bad flow
  IB/mlx4: Fix race condition between catas error reset and aliasguid flows
...@@ -173,7 +173,12 @@ int i40iw_inetaddr_event(struct notifier_block *notifier, ...@@ -173,7 +173,12 @@ int i40iw_inetaddr_event(struct notifier_block *notifier,
rcu_read_lock(); rcu_read_lock();
in = __in_dev_get_rcu(upper_dev); in = __in_dev_get_rcu(upper_dev);
local_ipaddr = ntohl(in->ifa_list->ifa_address);
if (!in->ifa_list)
local_ipaddr = 0;
else
local_ipaddr = ntohl(in->ifa_list->ifa_address);
rcu_read_unlock(); rcu_read_unlock();
} else { } else {
local_ipaddr = ntohl(ifa->ifa_address); local_ipaddr = ntohl(ifa->ifa_address);
...@@ -185,6 +190,11 @@ int i40iw_inetaddr_event(struct notifier_block *notifier, ...@@ -185,6 +190,11 @@ int i40iw_inetaddr_event(struct notifier_block *notifier,
case NETDEV_UP: case NETDEV_UP:
/* Fall through */ /* Fall through */
case NETDEV_CHANGEADDR: case NETDEV_CHANGEADDR:
/* Just skip if no need to handle ARP cache */
if (!local_ipaddr)
break;
i40iw_manage_arp_cache(iwdev, i40iw_manage_arp_cache(iwdev,
netdev->dev_addr, netdev->dev_addr,
&local_ipaddr, &local_ipaddr,
......
...@@ -804,8 +804,8 @@ void mlx4_ib_destroy_alias_guid_service(struct mlx4_ib_dev *dev) ...@@ -804,8 +804,8 @@ void mlx4_ib_destroy_alias_guid_service(struct mlx4_ib_dev *dev)
unsigned long flags; unsigned long flags;
for (i = 0 ; i < dev->num_ports; i++) { for (i = 0 ; i < dev->num_ports; i++) {
cancel_delayed_work(&dev->sriov.alias_guid.ports_guid[i].alias_guid_work);
det = &sriov->alias_guid.ports_guid[i]; det = &sriov->alias_guid.ports_guid[i];
cancel_delayed_work_sync(&det->alias_guid_work);
spin_lock_irqsave(&sriov->alias_guid.ag_work_lock, flags); spin_lock_irqsave(&sriov->alias_guid.ag_work_lock, flags);
while (!list_empty(&det->cb_list)) { while (!list_empty(&det->cb_list)) {
cb_ctx = list_entry(det->cb_list.next, cb_ctx = list_entry(det->cb_list.next,
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
enum devx_obj_flags { enum devx_obj_flags {
DEVX_OBJ_FLAGS_INDIRECT_MKEY = 1 << 0, DEVX_OBJ_FLAGS_INDIRECT_MKEY = 1 << 0,
DEVX_OBJ_FLAGS_DCT = 1 << 1,
}; };
struct devx_async_data { struct devx_async_data {
...@@ -39,7 +40,10 @@ struct devx_obj { ...@@ -39,7 +40,10 @@ struct devx_obj {
u32 dinlen; /* destroy inbox length */ u32 dinlen; /* destroy inbox length */
u32 dinbox[MLX5_MAX_DESTROY_INBOX_SIZE_DW]; u32 dinbox[MLX5_MAX_DESTROY_INBOX_SIZE_DW];
u32 flags; u32 flags;
struct mlx5_ib_devx_mr devx_mr; union {
struct mlx5_ib_devx_mr devx_mr;
struct mlx5_core_dct core_dct;
};
}; };
struct devx_umem { struct devx_umem {
...@@ -347,7 +351,6 @@ static u64 devx_get_obj_id(const void *in) ...@@ -347,7 +351,6 @@ static u64 devx_get_obj_id(const void *in)
obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ, obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
MLX5_GET(arm_rq_in, in, srq_number)); MLX5_GET(arm_rq_in, in, srq_number));
break; break;
case MLX5_CMD_OP_DRAIN_DCT:
case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION: case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT, obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT,
MLX5_GET(drain_dct_in, in, dctn)); MLX5_GET(drain_dct_in, in, dctn));
...@@ -618,7 +621,6 @@ static bool devx_is_obj_modify_cmd(const void *in) ...@@ -618,7 +621,6 @@ static bool devx_is_obj_modify_cmd(const void *in)
case MLX5_CMD_OP_2RST_QP: case MLX5_CMD_OP_2RST_QP:
case MLX5_CMD_OP_ARM_XRC_SRQ: case MLX5_CMD_OP_ARM_XRC_SRQ:
case MLX5_CMD_OP_ARM_RQ: case MLX5_CMD_OP_ARM_RQ:
case MLX5_CMD_OP_DRAIN_DCT:
case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION: case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
case MLX5_CMD_OP_ARM_XRQ: case MLX5_CMD_OP_ARM_XRQ:
case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY: case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY:
...@@ -1124,7 +1126,11 @@ static int devx_obj_cleanup(struct ib_uobject *uobject, ...@@ -1124,7 +1126,11 @@ static int devx_obj_cleanup(struct ib_uobject *uobject,
if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY) if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY)
devx_cleanup_mkey(obj); devx_cleanup_mkey(obj);
ret = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out)); if (obj->flags & DEVX_OBJ_FLAGS_DCT)
ret = mlx5_core_destroy_dct(obj->mdev, &obj->core_dct);
else
ret = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out,
sizeof(out));
if (ib_is_destroy_retryable(ret, why, uobject)) if (ib_is_destroy_retryable(ret, why, uobject))
return ret; return ret;
...@@ -1185,9 +1191,17 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)( ...@@ -1185,9 +1191,17 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
devx_set_umem_valid(cmd_in); devx_set_umem_valid(cmd_in);
} }
err = mlx5_cmd_exec(dev->mdev, cmd_in, if (opcode == MLX5_CMD_OP_CREATE_DCT) {
cmd_in_len, obj->flags |= DEVX_OBJ_FLAGS_DCT;
cmd_out, cmd_out_len); err = mlx5_core_create_dct(dev->mdev, &obj->core_dct,
cmd_in, cmd_in_len,
cmd_out, cmd_out_len);
} else {
err = mlx5_cmd_exec(dev->mdev, cmd_in,
cmd_in_len,
cmd_out, cmd_out_len);
}
if (err) if (err)
goto obj_free; goto obj_free;
...@@ -1214,7 +1228,11 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)( ...@@ -1214,7 +1228,11 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY) if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY)
devx_cleanup_mkey(obj); devx_cleanup_mkey(obj);
obj_destroy: obj_destroy:
mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out)); if (obj->flags & DEVX_OBJ_FLAGS_DCT)
mlx5_core_destroy_dct(obj->mdev, &obj->core_dct);
else
mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out,
sizeof(out));
obj_free: obj_free:
kfree(obj); kfree(obj);
return err; return err;
......
...@@ -415,10 +415,17 @@ static int translate_eth_ext_proto_oper(u32 eth_proto_oper, u8 *active_speed, ...@@ -415,10 +415,17 @@ static int translate_eth_ext_proto_oper(u32 eth_proto_oper, u8 *active_speed,
*active_speed = IB_SPEED_EDR; *active_speed = IB_SPEED_EDR;
break; break;
case MLX5E_PROT_MASK(MLX5E_50GAUI_2_LAUI_2_50GBASE_CR2_KR2): case MLX5E_PROT_MASK(MLX5E_50GAUI_2_LAUI_2_50GBASE_CR2_KR2):
*active_width = IB_WIDTH_2X;
*active_speed = IB_SPEED_EDR;
break;
case MLX5E_PROT_MASK(MLX5E_50GAUI_1_LAUI_1_50GBASE_CR_KR): case MLX5E_PROT_MASK(MLX5E_50GAUI_1_LAUI_1_50GBASE_CR_KR):
*active_width = IB_WIDTH_1X; *active_width = IB_WIDTH_1X;
*active_speed = IB_SPEED_HDR; *active_speed = IB_SPEED_HDR;
break; break;
case MLX5E_PROT_MASK(MLX5E_CAUI_4_100GBASE_CR4_KR4):
*active_width = IB_WIDTH_4X;
*active_speed = IB_SPEED_EDR;
break;
case MLX5E_PROT_MASK(MLX5E_100GAUI_2_100GBASE_CR2_KR2): case MLX5E_PROT_MASK(MLX5E_100GAUI_2_100GBASE_CR2_KR2):
*active_width = IB_WIDTH_2X; *active_width = IB_WIDTH_2X;
*active_speed = IB_SPEED_HDR; *active_speed = IB_SPEED_HDR;
......
...@@ -3729,6 +3729,7 @@ static int mlx5_ib_modify_dct(struct ib_qp *ibqp, struct ib_qp_attr *attr, ...@@ -3729,6 +3729,7 @@ static int mlx5_ib_modify_dct(struct ib_qp *ibqp, struct ib_qp_attr *attr,
} else if (cur_state == IB_QPS_INIT && new_state == IB_QPS_RTR) { } else if (cur_state == IB_QPS_INIT && new_state == IB_QPS_RTR) {
struct mlx5_ib_modify_qp_resp resp = {}; struct mlx5_ib_modify_qp_resp resp = {};
u32 out[MLX5_ST_SZ_DW(create_dct_out)] = {0};
u32 min_resp_len = offsetof(typeof(resp), dctn) + u32 min_resp_len = offsetof(typeof(resp), dctn) +
sizeof(resp.dctn); sizeof(resp.dctn);
...@@ -3747,7 +3748,8 @@ static int mlx5_ib_modify_dct(struct ib_qp *ibqp, struct ib_qp_attr *attr, ...@@ -3747,7 +3748,8 @@ static int mlx5_ib_modify_dct(struct ib_qp *ibqp, struct ib_qp_attr *attr,
MLX5_SET(dctc, dctc, hop_limit, attr->ah_attr.grh.hop_limit); MLX5_SET(dctc, dctc, hop_limit, attr->ah_attr.grh.hop_limit);
err = mlx5_core_create_dct(dev->mdev, &qp->dct.mdct, qp->dct.in, err = mlx5_core_create_dct(dev->mdev, &qp->dct.mdct, qp->dct.in,
MLX5_ST_SZ_BYTES(create_dct_in)); MLX5_ST_SZ_BYTES(create_dct_in), out,
sizeof(out));
if (err) if (err)
return err; return err;
resp.dctn = qp->dct.mdct.mqp.qpn; resp.dctn = qp->dct.mdct.mqp.qpn;
......
...@@ -40,6 +40,9 @@ ...@@ -40,6 +40,9 @@
#include "mlx5_core.h" #include "mlx5_core.h"
#include "lib/eq.h" #include "lib/eq.h"
static int mlx5_core_drain_dct(struct mlx5_core_dev *dev,
struct mlx5_core_dct *dct);
static struct mlx5_core_rsc_common * static struct mlx5_core_rsc_common *
mlx5_get_rsc(struct mlx5_qp_table *table, u32 rsn) mlx5_get_rsc(struct mlx5_qp_table *table, u32 rsn)
{ {
...@@ -227,20 +230,49 @@ static void destroy_resource_common(struct mlx5_core_dev *dev, ...@@ -227,20 +230,49 @@ static void destroy_resource_common(struct mlx5_core_dev *dev,
wait_for_completion(&qp->common.free); wait_for_completion(&qp->common.free);
} }
static int _mlx5_core_destroy_dct(struct mlx5_core_dev *dev,
struct mlx5_core_dct *dct, bool need_cleanup)
{
u32 out[MLX5_ST_SZ_DW(destroy_dct_out)] = {0};
u32 in[MLX5_ST_SZ_DW(destroy_dct_in)] = {0};
struct mlx5_core_qp *qp = &dct->mqp;
int err;
err = mlx5_core_drain_dct(dev, dct);
if (err) {
if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
goto destroy;
} else {
mlx5_core_warn(
dev, "failed drain DCT 0x%x with error 0x%x\n",
qp->qpn, err);
return err;
}
}
wait_for_completion(&dct->drained);
destroy:
if (need_cleanup)
destroy_resource_common(dev, &dct->mqp);
MLX5_SET(destroy_dct_in, in, opcode, MLX5_CMD_OP_DESTROY_DCT);
MLX5_SET(destroy_dct_in, in, dctn, qp->qpn);
MLX5_SET(destroy_dct_in, in, uid, qp->uid);
err = mlx5_cmd_exec(dev, (void *)&in, sizeof(in),
(void *)&out, sizeof(out));
return err;
}
int mlx5_core_create_dct(struct mlx5_core_dev *dev, int mlx5_core_create_dct(struct mlx5_core_dev *dev,
struct mlx5_core_dct *dct, struct mlx5_core_dct *dct,
u32 *in, int inlen) u32 *in, int inlen,
u32 *out, int outlen)
{ {
u32 out[MLX5_ST_SZ_DW(create_dct_out)] = {0};
u32 din[MLX5_ST_SZ_DW(destroy_dct_in)] = {0};
u32 dout[MLX5_ST_SZ_DW(destroy_dct_out)] = {0};
struct mlx5_core_qp *qp = &dct->mqp; struct mlx5_core_qp *qp = &dct->mqp;
int err; int err;
init_completion(&dct->drained); init_completion(&dct->drained);
MLX5_SET(create_dct_in, in, opcode, MLX5_CMD_OP_CREATE_DCT); MLX5_SET(create_dct_in, in, opcode, MLX5_CMD_OP_CREATE_DCT);
err = mlx5_cmd_exec(dev, in, inlen, &out, sizeof(out)); err = mlx5_cmd_exec(dev, in, inlen, out, outlen);
if (err) { if (err) {
mlx5_core_warn(dev, "create DCT failed, ret %d\n", err); mlx5_core_warn(dev, "create DCT failed, ret %d\n", err);
return err; return err;
...@@ -254,11 +286,7 @@ int mlx5_core_create_dct(struct mlx5_core_dev *dev, ...@@ -254,11 +286,7 @@ int mlx5_core_create_dct(struct mlx5_core_dev *dev,
return 0; return 0;
err_cmd: err_cmd:
MLX5_SET(destroy_dct_in, din, opcode, MLX5_CMD_OP_DESTROY_DCT); _mlx5_core_destroy_dct(dev, dct, false);
MLX5_SET(destroy_dct_in, din, dctn, qp->qpn);
MLX5_SET(destroy_dct_in, din, uid, qp->uid);
mlx5_cmd_exec(dev, (void *)&in, sizeof(din),
(void *)&out, sizeof(dout));
return err; return err;
} }
EXPORT_SYMBOL_GPL(mlx5_core_create_dct); EXPORT_SYMBOL_GPL(mlx5_core_create_dct);
...@@ -323,29 +351,7 @@ static int mlx5_core_drain_dct(struct mlx5_core_dev *dev, ...@@ -323,29 +351,7 @@ static int mlx5_core_drain_dct(struct mlx5_core_dev *dev,
int mlx5_core_destroy_dct(struct mlx5_core_dev *dev, int mlx5_core_destroy_dct(struct mlx5_core_dev *dev,
struct mlx5_core_dct *dct) struct mlx5_core_dct *dct)
{ {
u32 out[MLX5_ST_SZ_DW(destroy_dct_out)] = {0}; return _mlx5_core_destroy_dct(dev, dct, true);
u32 in[MLX5_ST_SZ_DW(destroy_dct_in)] = {0};
struct mlx5_core_qp *qp = &dct->mqp;
int err;
err = mlx5_core_drain_dct(dev, dct);
if (err) {
if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
goto destroy;
} else {
mlx5_core_warn(dev, "failed drain DCT 0x%x with error 0x%x\n", qp->qpn, err);
return err;
}
}
wait_for_completion(&dct->drained);
destroy:
destroy_resource_common(dev, &dct->mqp);
MLX5_SET(destroy_dct_in, in, opcode, MLX5_CMD_OP_DESTROY_DCT);
MLX5_SET(destroy_dct_in, in, dctn, qp->qpn);
MLX5_SET(destroy_dct_in, in, uid, qp->uid);
err = mlx5_cmd_exec(dev, (void *)&in, sizeof(in),
(void *)&out, sizeof(out));
return err;
} }
EXPORT_SYMBOL_GPL(mlx5_core_destroy_dct); EXPORT_SYMBOL_GPL(mlx5_core_destroy_dct);
......
...@@ -557,7 +557,8 @@ static inline struct mlx5_core_mkey *__mlx5_mr_lookup(struct mlx5_core_dev *dev, ...@@ -557,7 +557,8 @@ static inline struct mlx5_core_mkey *__mlx5_mr_lookup(struct mlx5_core_dev *dev,
int mlx5_core_create_dct(struct mlx5_core_dev *dev, int mlx5_core_create_dct(struct mlx5_core_dev *dev,
struct mlx5_core_dct *qp, struct mlx5_core_dct *qp,
u32 *in, int inlen); u32 *in, int inlen,
u32 *out, int outlen);
int mlx5_core_create_qp(struct mlx5_core_dev *dev, int mlx5_core_create_qp(struct mlx5_core_dev *dev,
struct mlx5_core_qp *qp, struct mlx5_core_qp *qp,
u32 *in, u32 *in,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册