Commit 9420e8ad authored by Linus Torvalds's avatar Linus Torvalds

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

Pull rdma fixes from Jason Gunthorpe:
 "A small set of late-rc patches, mostly fixes for various crashers,
  some syzkaller fixes and a mlx5 HW limitation:

   - Several MAINTAINERS updates

   - Memory leak regression in ODP

   - Several fixes for syzkaller related crashes. Google recently taught
     syzkaller to create the software RDMA devices

   - Crash fixes for HFI1

   - Several fixes for mlx5 crashes

   - Prevent unprivileged access to an unsafe mlx5 HW resource"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma:
  RDMA/mlx5: Block delay drop to unprivileged users
  RDMA/mlx5: Fix access to wrong pointer while performing flush due to error
  RDMA/core: Ensure security pkey modify is not lost
  MAINTAINERS: Clean RXE section and add Zhu as RXE maintainer
  IB/hfi1: Ensure pq is not left on waitlist
  IB/rdmavt: Free kernel completion queue when done
  RDMA/mad: Do not crash if the rdma device does not have a umad interface
  RDMA/core: Fix missing error check on dev_set_name()
  RDMA/nl: Do not permit empty devices names during RDMA_NLDEV_CMD_NEWLINK/SET
  RDMA/mlx5: Fix the number of hwcounters of a dynamic counter
  MAINTAINERS: Update maintainers for HISILICON ROCE DRIVER
  RDMA/odp: Fix leaking the tgid for implicit ODP
parents 1b649e0b ba80013f
...@@ -7579,7 +7579,8 @@ F: Documentation/admin-guide/perf/hisi-pmu.rst ...@@ -7579,7 +7579,8 @@ F: Documentation/admin-guide/perf/hisi-pmu.rst
HISILICON ROCE DRIVER HISILICON ROCE DRIVER
M: Lijun Ou <oulijun@huawei.com> M: Lijun Ou <oulijun@huawei.com>
M: Wei Hu(Xavier) <xavier.huwei@huawei.com> M: Wei Hu(Xavier) <huwei87@hisilicon.com>
M: Weihang Li <liweihang@huawei.com>
L: linux-rdma@vger.kernel.org L: linux-rdma@vger.kernel.org
S: Maintained S: Maintained
F: drivers/infiniband/hw/hns/ F: drivers/infiniband/hw/hns/
...@@ -15421,11 +15422,9 @@ F: drivers/infiniband/sw/siw/ ...@@ -15421,11 +15422,9 @@ F: drivers/infiniband/sw/siw/
F: include/uapi/rdma/siw-abi.h F: include/uapi/rdma/siw-abi.h
SOFT-ROCE DRIVER (rxe) SOFT-ROCE DRIVER (rxe)
M: Moni Shoua <monis@mellanox.com> M: Zhu Yanjun <yanjunz@mellanox.com>
L: linux-rdma@vger.kernel.org L: linux-rdma@vger.kernel.org
S: Supported S: Supported
W: https://github.com/SoftRoCE/rxe-dev/wiki/rxe-dev:-Home
Q: http://patchwork.kernel.org/project/linux-rdma/list/
F: drivers/infiniband/sw/rxe/ F: drivers/infiniband/sw/rxe/
F: include/uapi/rdma/rdma_user_rxe.h F: include/uapi/rdma/rdma_user_rxe.h
......
...@@ -896,7 +896,9 @@ static int add_one_compat_dev(struct ib_device *device, ...@@ -896,7 +896,9 @@ static int add_one_compat_dev(struct ib_device *device,
cdev->dev.parent = device->dev.parent; cdev->dev.parent = device->dev.parent;
rdma_init_coredev(cdev, device, read_pnet(&rnet->net)); rdma_init_coredev(cdev, device, read_pnet(&rnet->net));
cdev->dev.release = compatdev_release; cdev->dev.release = compatdev_release;
dev_set_name(&cdev->dev, "%s", dev_name(&device->dev)); ret = dev_set_name(&cdev->dev, "%s", dev_name(&device->dev));
if (ret)
goto add_err;
ret = device_add(&cdev->dev); ret = device_add(&cdev->dev);
if (ret) if (ret)
......
...@@ -918,6 +918,10 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -918,6 +918,10 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
nla_strlcpy(name, tb[RDMA_NLDEV_ATTR_DEV_NAME], nla_strlcpy(name, tb[RDMA_NLDEV_ATTR_DEV_NAME],
IB_DEVICE_NAME_MAX); IB_DEVICE_NAME_MAX);
if (strlen(name) == 0) {
err = -EINVAL;
goto done;
}
err = ib_device_rename(device, name); err = ib_device_rename(device, name);
goto done; goto done;
} }
...@@ -1514,7 +1518,7 @@ static int nldev_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1514,7 +1518,7 @@ static int nldev_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
nla_strlcpy(ibdev_name, tb[RDMA_NLDEV_ATTR_DEV_NAME], nla_strlcpy(ibdev_name, tb[RDMA_NLDEV_ATTR_DEV_NAME],
sizeof(ibdev_name)); sizeof(ibdev_name));
if (strchr(ibdev_name, '%')) if (strchr(ibdev_name, '%') || strlen(ibdev_name) == 0)
return -EINVAL; return -EINVAL;
nla_strlcpy(type, tb[RDMA_NLDEV_ATTR_LINK_TYPE], sizeof(type)); nla_strlcpy(type, tb[RDMA_NLDEV_ATTR_LINK_TYPE], sizeof(type));
......
...@@ -349,16 +349,11 @@ static struct ib_ports_pkeys *get_new_pps(const struct ib_qp *qp, ...@@ -349,16 +349,11 @@ static struct ib_ports_pkeys *get_new_pps(const struct ib_qp *qp,
else if (qp_pps) else if (qp_pps)
new_pps->main.pkey_index = qp_pps->main.pkey_index; new_pps->main.pkey_index = qp_pps->main.pkey_index;
if ((qp_attr_mask & IB_QP_PKEY_INDEX) && (qp_attr_mask & IB_QP_PORT)) if (((qp_attr_mask & IB_QP_PKEY_INDEX) &&
(qp_attr_mask & IB_QP_PORT)) ||
(qp_pps && qp_pps->main.state != IB_PORT_PKEY_NOT_VALID))
new_pps->main.state = IB_PORT_PKEY_VALID; new_pps->main.state = IB_PORT_PKEY_VALID;
if (!(qp_attr_mask & (IB_QP_PKEY_INDEX | IB_QP_PORT)) && qp_pps) {
new_pps->main.port_num = qp_pps->main.port_num;
new_pps->main.pkey_index = qp_pps->main.pkey_index;
if (qp_pps->main.state != IB_PORT_PKEY_NOT_VALID)
new_pps->main.state = IB_PORT_PKEY_VALID;
}
if (qp_attr_mask & IB_QP_ALT_PATH) { if (qp_attr_mask & IB_QP_ALT_PATH) {
new_pps->alt.port_num = qp_attr->alt_port_num; new_pps->alt.port_num = qp_attr->alt_port_num;
new_pps->alt.pkey_index = qp_attr->alt_pkey_index; new_pps->alt.pkey_index = qp_attr->alt_pkey_index;
......
...@@ -275,8 +275,8 @@ void ib_umem_odp_release(struct ib_umem_odp *umem_odp) ...@@ -275,8 +275,8 @@ void ib_umem_odp_release(struct ib_umem_odp *umem_odp)
mmu_interval_notifier_remove(&umem_odp->notifier); mmu_interval_notifier_remove(&umem_odp->notifier);
kvfree(umem_odp->dma_list); kvfree(umem_odp->dma_list);
kvfree(umem_odp->page_list); kvfree(umem_odp->page_list);
put_pid(umem_odp->tgid);
} }
put_pid(umem_odp->tgid);
kfree(umem_odp); kfree(umem_odp);
} }
EXPORT_SYMBOL(ib_umem_odp_release); EXPORT_SYMBOL(ib_umem_odp_release);
......
...@@ -1129,17 +1129,30 @@ static const struct file_operations umad_sm_fops = { ...@@ -1129,17 +1129,30 @@ static const struct file_operations umad_sm_fops = {
.llseek = no_llseek, .llseek = no_llseek,
}; };
static struct ib_umad_port *get_port(struct ib_device *ibdev,
struct ib_umad_device *umad_dev,
unsigned int port)
{
if (!umad_dev)
return ERR_PTR(-EOPNOTSUPP);
if (!rdma_is_port_valid(ibdev, port))
return ERR_PTR(-EINVAL);
if (!rdma_cap_ib_mad(ibdev, port))
return ERR_PTR(-EOPNOTSUPP);
return &umad_dev->ports[port - rdma_start_port(ibdev)];
}
static int ib_umad_get_nl_info(struct ib_device *ibdev, void *client_data, static int ib_umad_get_nl_info(struct ib_device *ibdev, void *client_data,
struct ib_client_nl_info *res) struct ib_client_nl_info *res)
{ {
struct ib_umad_device *umad_dev = client_data; struct ib_umad_port *port = get_port(ibdev, client_data, res->port);
if (!rdma_is_port_valid(ibdev, res->port)) if (IS_ERR(port))
return -EINVAL; return PTR_ERR(port);
res->abi = IB_USER_MAD_ABI_VERSION; res->abi = IB_USER_MAD_ABI_VERSION;
res->cdev = &umad_dev->ports[res->port - rdma_start_port(ibdev)].dev; res->cdev = &port->dev;
return 0; return 0;
} }
...@@ -1154,15 +1167,13 @@ MODULE_ALIAS_RDMA_CLIENT("umad"); ...@@ -1154,15 +1167,13 @@ MODULE_ALIAS_RDMA_CLIENT("umad");
static int ib_issm_get_nl_info(struct ib_device *ibdev, void *client_data, static int ib_issm_get_nl_info(struct ib_device *ibdev, void *client_data,
struct ib_client_nl_info *res) struct ib_client_nl_info *res)
{ {
struct ib_umad_device *umad_dev = struct ib_umad_port *port = get_port(ibdev, client_data, res->port);
ib_get_client_data(ibdev, &umad_client);
if (!rdma_is_port_valid(ibdev, res->port)) if (IS_ERR(port))
return -EINVAL; return PTR_ERR(port);
res->abi = IB_USER_MAD_ABI_VERSION; res->abi = IB_USER_MAD_ABI_VERSION;
res->cdev = &umad_dev->ports[res->port - rdma_start_port(ibdev)].sm_dev; res->cdev = &port->sm_dev;
return 0; return 0;
} }
......
...@@ -141,6 +141,7 @@ static int defer_packet_queue( ...@@ -141,6 +141,7 @@ static int defer_packet_queue(
*/ */
xchg(&pq->state, SDMA_PKT_Q_DEFERRED); xchg(&pq->state, SDMA_PKT_Q_DEFERRED);
if (list_empty(&pq->busy.list)) { if (list_empty(&pq->busy.list)) {
pq->busy.lock = &sde->waitlock;
iowait_get_priority(&pq->busy); iowait_get_priority(&pq->busy);
iowait_queue(pkts_sent, &pq->busy, &sde->dmawait); iowait_queue(pkts_sent, &pq->busy, &sde->dmawait);
} }
...@@ -155,6 +156,7 @@ static void activate_packet_queue(struct iowait *wait, int reason) ...@@ -155,6 +156,7 @@ static void activate_packet_queue(struct iowait *wait, int reason)
{ {
struct hfi1_user_sdma_pkt_q *pq = struct hfi1_user_sdma_pkt_q *pq =
container_of(wait, struct hfi1_user_sdma_pkt_q, busy); container_of(wait, struct hfi1_user_sdma_pkt_q, busy);
pq->busy.lock = NULL;
xchg(&pq->state, SDMA_PKT_Q_ACTIVE); xchg(&pq->state, SDMA_PKT_Q_ACTIVE);
wake_up(&wait->wait_dma); wake_up(&wait->wait_dma);
}; };
...@@ -256,6 +258,21 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt, ...@@ -256,6 +258,21 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt,
return ret; return ret;
} }
static void flush_pq_iowait(struct hfi1_user_sdma_pkt_q *pq)
{
unsigned long flags;
seqlock_t *lock = pq->busy.lock;
if (!lock)
return;
write_seqlock_irqsave(lock, flags);
if (!list_empty(&pq->busy.list)) {
list_del_init(&pq->busy.list);
pq->busy.lock = NULL;
}
write_sequnlock_irqrestore(lock, flags);
}
int hfi1_user_sdma_free_queues(struct hfi1_filedata *fd, int hfi1_user_sdma_free_queues(struct hfi1_filedata *fd,
struct hfi1_ctxtdata *uctxt) struct hfi1_ctxtdata *uctxt)
{ {
...@@ -281,6 +298,7 @@ int hfi1_user_sdma_free_queues(struct hfi1_filedata *fd, ...@@ -281,6 +298,7 @@ int hfi1_user_sdma_free_queues(struct hfi1_filedata *fd,
kfree(pq->reqs); kfree(pq->reqs);
kfree(pq->req_in_use); kfree(pq->req_in_use);
kmem_cache_destroy(pq->txreq_cache); kmem_cache_destroy(pq->txreq_cache);
flush_pq_iowait(pq);
kfree(pq); kfree(pq);
} else { } else {
spin_unlock(&fd->pq_rcu_lock); spin_unlock(&fd->pq_rcu_lock);
...@@ -587,11 +605,12 @@ int hfi1_user_sdma_process_request(struct hfi1_filedata *fd, ...@@ -587,11 +605,12 @@ int hfi1_user_sdma_process_request(struct hfi1_filedata *fd,
if (ret < 0) { if (ret < 0) {
if (ret != -EBUSY) if (ret != -EBUSY)
goto free_req; goto free_req;
wait_event_interruptible_timeout( if (wait_event_interruptible_timeout(
pq->busy.wait_dma, pq->busy.wait_dma,
(pq->state == SDMA_PKT_Q_ACTIVE), pq->state == SDMA_PKT_Q_ACTIVE,
msecs_to_jiffies( msecs_to_jiffies(
SDMA_IOWAIT_TIMEOUT)); SDMA_IOWAIT_TIMEOUT)) <= 0)
flush_pq_iowait(pq);
} }
} }
*count += idx; *count += idx;
......
...@@ -330,6 +330,22 @@ static void mlx5_handle_error_cqe(struct mlx5_ib_dev *dev, ...@@ -330,6 +330,22 @@ static void mlx5_handle_error_cqe(struct mlx5_ib_dev *dev,
dump_cqe(dev, cqe); dump_cqe(dev, cqe);
} }
static void handle_atomics(struct mlx5_ib_qp *qp, struct mlx5_cqe64 *cqe64,
u16 tail, u16 head)
{
u16 idx;
do {
idx = tail & (qp->sq.wqe_cnt - 1);
if (idx == head)
break;
tail = qp->sq.w_list[idx].next;
} while (1);
tail = qp->sq.w_list[idx].next;
qp->sq.last_poll = tail;
}
static void free_cq_buf(struct mlx5_ib_dev *dev, struct mlx5_ib_cq_buf *buf) static void free_cq_buf(struct mlx5_ib_dev *dev, struct mlx5_ib_cq_buf *buf)
{ {
mlx5_frag_buf_free(dev->mdev, &buf->frag_buf); mlx5_frag_buf_free(dev->mdev, &buf->frag_buf);
...@@ -368,7 +384,7 @@ static void get_sig_err_item(struct mlx5_sig_err_cqe *cqe, ...@@ -368,7 +384,7 @@ static void get_sig_err_item(struct mlx5_sig_err_cqe *cqe,
} }
static void sw_comp(struct mlx5_ib_qp *qp, int num_entries, struct ib_wc *wc, static void sw_comp(struct mlx5_ib_qp *qp, int num_entries, struct ib_wc *wc,
int *npolled, int is_send) int *npolled, bool is_send)
{ {
struct mlx5_ib_wq *wq; struct mlx5_ib_wq *wq;
unsigned int cur; unsigned int cur;
...@@ -383,10 +399,16 @@ static void sw_comp(struct mlx5_ib_qp *qp, int num_entries, struct ib_wc *wc, ...@@ -383,10 +399,16 @@ static void sw_comp(struct mlx5_ib_qp *qp, int num_entries, struct ib_wc *wc,
return; return;
for (i = 0; i < cur && np < num_entries; i++) { for (i = 0; i < cur && np < num_entries; i++) {
wc->wr_id = wq->wrid[wq->tail & (wq->wqe_cnt - 1)]; unsigned int idx;
idx = (is_send) ? wq->last_poll : wq->tail;
idx &= (wq->wqe_cnt - 1);
wc->wr_id = wq->wrid[idx];
wc->status = IB_WC_WR_FLUSH_ERR; wc->status = IB_WC_WR_FLUSH_ERR;
wc->vendor_err = MLX5_CQE_SYNDROME_WR_FLUSH_ERR; wc->vendor_err = MLX5_CQE_SYNDROME_WR_FLUSH_ERR;
wq->tail++; wq->tail++;
if (is_send)
wq->last_poll = wq->w_list[idx].next;
np++; np++;
wc->qp = &qp->ibqp; wc->qp = &qp->ibqp;
wc++; wc++;
...@@ -473,6 +495,7 @@ static int mlx5_poll_one(struct mlx5_ib_cq *cq, ...@@ -473,6 +495,7 @@ static int mlx5_poll_one(struct mlx5_ib_cq *cq,
wqe_ctr = be16_to_cpu(cqe64->wqe_counter); wqe_ctr = be16_to_cpu(cqe64->wqe_counter);
idx = wqe_ctr & (wq->wqe_cnt - 1); idx = wqe_ctr & (wq->wqe_cnt - 1);
handle_good_req(wc, cqe64, wq, idx); handle_good_req(wc, cqe64, wq, idx);
handle_atomics(*cur_qp, cqe64, wq->last_poll, idx);
wc->wr_id = wq->wrid[idx]; wc->wr_id = wq->wrid[idx];
wq->tail = wq->wqe_head[idx] + 1; wq->tail = wq->wqe_head[idx] + 1;
wc->status = IB_WC_SUCCESS; wc->status = IB_WC_SUCCESS;
......
...@@ -5722,9 +5722,10 @@ mlx5_ib_counter_alloc_stats(struct rdma_counter *counter) ...@@ -5722,9 +5722,10 @@ mlx5_ib_counter_alloc_stats(struct rdma_counter *counter)
const struct mlx5_ib_counters *cnts = const struct mlx5_ib_counters *cnts =
get_counters(dev, counter->port - 1); get_counters(dev, counter->port - 1);
/* Q counters are in the beginning of all counters */
return rdma_alloc_hw_stats_struct(cnts->names, return rdma_alloc_hw_stats_struct(cnts->names,
cnts->num_q_counters, cnts->num_q_counters +
cnts->num_cong_counters +
cnts->num_ext_ppcnt_counters,
RDMA_HW_STATS_DEFAULT_LIFESPAN); RDMA_HW_STATS_DEFAULT_LIFESPAN);
} }
......
...@@ -288,6 +288,7 @@ struct mlx5_ib_wq { ...@@ -288,6 +288,7 @@ struct mlx5_ib_wq {
unsigned head; unsigned head;
unsigned tail; unsigned tail;
u16 cur_post; u16 cur_post;
u16 last_poll;
void *cur_edge; void *cur_edge;
}; };
......
...@@ -3775,6 +3775,7 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp, ...@@ -3775,6 +3775,7 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
qp->sq.cur_post = 0; qp->sq.cur_post = 0;
if (qp->sq.wqe_cnt) if (qp->sq.wqe_cnt)
qp->sq.cur_edge = get_sq_edge(&qp->sq, 0); qp->sq.cur_edge = get_sq_edge(&qp->sq, 0);
qp->sq.last_poll = 0;
qp->db.db[MLX5_RCV_DBR] = 0; qp->db.db[MLX5_RCV_DBR] = 0;
qp->db.db[MLX5_SND_DBR] = 0; qp->db.db[MLX5_SND_DBR] = 0;
} }
...@@ -6204,6 +6205,10 @@ struct ib_wq *mlx5_ib_create_wq(struct ib_pd *pd, ...@@ -6204,6 +6205,10 @@ struct ib_wq *mlx5_ib_create_wq(struct ib_pd *pd,
if (udata->outlen && udata->outlen < min_resp_len) if (udata->outlen && udata->outlen < min_resp_len)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
if (!capable(CAP_SYS_RAWIO) &&
init_attr->create_flags & IB_WQ_FLAGS_DELAY_DROP)
return ERR_PTR(-EPERM);
dev = to_mdev(pd->device); dev = to_mdev(pd->device);
switch (init_attr->wq_type) { switch (init_attr->wq_type) {
case IB_WQT_RQ: case IB_WQT_RQ:
......
...@@ -327,7 +327,7 @@ void rvt_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata) ...@@ -327,7 +327,7 @@ void rvt_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata)
if (cq->ip) if (cq->ip)
kref_put(&cq->ip->ref, rvt_release_mmap_info); kref_put(&cq->ip->ref, rvt_release_mmap_info);
else else
vfree(cq->queue); vfree(cq->kqueue);
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment