Skip to content

Commit

Permalink
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/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
  • Loading branch information
Linus Torvalds committed Mar 26, 2020
2 parents 1b649e0 + ba80013 commit 9420e8a
Show file tree
Hide file tree
Showing 12 changed files with 94 additions and 34 deletions.
7 changes: 3 additions & 4 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -7579,7 +7579,8 @@ F: Documentation/admin-guide/perf/hisi-pmu.rst

HISILICON ROCE DRIVER
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
S: Maintained
F: drivers/infiniband/hw/hns/
Expand Down Expand Up @@ -15421,11 +15422,9 @@ F: drivers/infiniband/sw/siw/
F: include/uapi/rdma/siw-abi.h

SOFT-ROCE DRIVER (rxe)
M: Moni Shoua <monis@mellanox.com>
M: Zhu Yanjun <yanjunz@mellanox.com>
L: linux-rdma@vger.kernel.org
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: include/uapi/rdma/rdma_user_rxe.h

Expand Down
4 changes: 3 additions & 1 deletion drivers/infiniband/core/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,9 @@ static int add_one_compat_dev(struct ib_device *device,
cdev->dev.parent = device->dev.parent;
rdma_init_coredev(cdev, device, read_pnet(&rnet->net));
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);
if (ret)
Expand Down
6 changes: 5 additions & 1 deletion drivers/infiniband/core/nldev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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],
IB_DEVICE_NAME_MAX);
if (strlen(name) == 0) {
err = -EINVAL;
goto done;
}
err = ib_device_rename(device, name);
goto done;
}
Expand Down Expand Up @@ -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],
sizeof(ibdev_name));
if (strchr(ibdev_name, '%'))
if (strchr(ibdev_name, '%') || strlen(ibdev_name) == 0)
return -EINVAL;

nla_strlcpy(type, tb[RDMA_NLDEV_ATTR_LINK_TYPE], sizeof(type));
Expand Down
11 changes: 3 additions & 8 deletions drivers/infiniband/core/security.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,16 +349,11 @@ static struct ib_ports_pkeys *get_new_pps(const struct ib_qp *qp,
else if (qp_pps)
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;

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) {
new_pps->alt.port_num = qp_attr->alt_port_num;
new_pps->alt.pkey_index = qp_attr->alt_pkey_index;
Expand Down
2 changes: 1 addition & 1 deletion drivers/infiniband/core/umem_odp.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,8 @@ void ib_umem_odp_release(struct ib_umem_odp *umem_odp)
mmu_interval_notifier_remove(&umem_odp->notifier);
kvfree(umem_odp->dma_list);
kvfree(umem_odp->page_list);
put_pid(umem_odp->tgid);
}
put_pid(umem_odp->tgid);
kfree(umem_odp);
}
EXPORT_SYMBOL(ib_umem_odp_release);
Expand Down
33 changes: 22 additions & 11 deletions drivers/infiniband/core/user_mad.c
Original file line number Diff line number Diff line change
Expand Up @@ -1129,17 +1129,30 @@ static const struct file_operations umad_sm_fops = {
.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,
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))
return -EINVAL;
if (IS_ERR(port))
return PTR_ERR(port);

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;
}

Expand All @@ -1154,15 +1167,13 @@ MODULE_ALIAS_RDMA_CLIENT("umad");
static int ib_issm_get_nl_info(struct ib_device *ibdev, void *client_data,
struct ib_client_nl_info *res)
{
struct ib_umad_device *umad_dev =
ib_get_client_data(ibdev, &umad_client);
struct ib_umad_port *port = get_port(ibdev, client_data, res->port);

if (!rdma_is_port_valid(ibdev, res->port))
return -EINVAL;
if (IS_ERR(port))
return PTR_ERR(port);

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;
}

Expand Down
25 changes: 22 additions & 3 deletions drivers/infiniband/hw/hfi1/user_sdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ static int defer_packet_queue(
*/
xchg(&pq->state, SDMA_PKT_Q_DEFERRED);
if (list_empty(&pq->busy.list)) {
pq->busy.lock = &sde->waitlock;
iowait_get_priority(&pq->busy);
iowait_queue(pkts_sent, &pq->busy, &sde->dmawait);
}
Expand All @@ -155,6 +156,7 @@ static void activate_packet_queue(struct iowait *wait, int reason)
{
struct hfi1_user_sdma_pkt_q *pq =
container_of(wait, struct hfi1_user_sdma_pkt_q, busy);
pq->busy.lock = NULL;
xchg(&pq->state, SDMA_PKT_Q_ACTIVE);
wake_up(&wait->wait_dma);
};
Expand Down Expand Up @@ -256,6 +258,21 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt,
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,
struct hfi1_ctxtdata *uctxt)
{
Expand All @@ -281,6 +298,7 @@ int hfi1_user_sdma_free_queues(struct hfi1_filedata *fd,
kfree(pq->reqs);
kfree(pq->req_in_use);
kmem_cache_destroy(pq->txreq_cache);
flush_pq_iowait(pq);
kfree(pq);
} else {
spin_unlock(&fd->pq_rcu_lock);
Expand Down Expand Up @@ -587,11 +605,12 @@ int hfi1_user_sdma_process_request(struct hfi1_filedata *fd,
if (ret < 0) {
if (ret != -EBUSY)
goto free_req;
wait_event_interruptible_timeout(
if (wait_event_interruptible_timeout(
pq->busy.wait_dma,
(pq->state == SDMA_PKT_Q_ACTIVE),
pq->state == SDMA_PKT_Q_ACTIVE,
msecs_to_jiffies(
SDMA_IOWAIT_TIMEOUT));
SDMA_IOWAIT_TIMEOUT)) <= 0)
flush_pq_iowait(pq);
}
}
*count += idx;
Expand Down
27 changes: 25 additions & 2 deletions drivers/infiniband/hw/mlx5/cq.c
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,22 @@ static void mlx5_handle_error_cqe(struct mlx5_ib_dev *dev,
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)
{
mlx5_frag_buf_free(dev->mdev, &buf->frag_buf);
Expand Down Expand Up @@ -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,
int *npolled, int is_send)
int *npolled, bool is_send)
{
struct mlx5_ib_wq *wq;
unsigned int cur;
Expand All @@ -383,10 +399,16 @@ static void sw_comp(struct mlx5_ib_qp *qp, int num_entries, struct ib_wc *wc,
return;

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->vendor_err = MLX5_CQE_SYNDROME_WR_FLUSH_ERR;
wq->tail++;
if (is_send)
wq->last_poll = wq->w_list[idx].next;
np++;
wc->qp = &qp->ibqp;
wc++;
Expand Down Expand Up @@ -473,6 +495,7 @@ static int mlx5_poll_one(struct mlx5_ib_cq *cq,
wqe_ctr = be16_to_cpu(cqe64->wqe_counter);
idx = wqe_ctr & (wq->wqe_cnt - 1);
handle_good_req(wc, cqe64, wq, idx);
handle_atomics(*cur_qp, cqe64, wq->last_poll, idx);
wc->wr_id = wq->wrid[idx];
wq->tail = wq->wqe_head[idx] + 1;
wc->status = IB_WC_SUCCESS;
Expand Down
5 changes: 3 additions & 2 deletions drivers/infiniband/hw/mlx5/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5722,9 +5722,10 @@ mlx5_ib_counter_alloc_stats(struct rdma_counter *counter)
const struct mlx5_ib_counters *cnts =
get_counters(dev, counter->port - 1);

/* Q counters are in the beginning of all counters */
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);
}

Expand Down
1 change: 1 addition & 0 deletions drivers/infiniband/hw/mlx5/mlx5_ib.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ struct mlx5_ib_wq {
unsigned head;
unsigned tail;
u16 cur_post;
u16 last_poll;
void *cur_edge;
};

Expand Down
5 changes: 5 additions & 0 deletions drivers/infiniband/hw/mlx5/qp.c
Original file line number Diff line number Diff line change
Expand Up @@ -3775,6 +3775,7 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
qp->sq.cur_post = 0;
if (qp->sq.wqe_cnt)
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_SND_DBR] = 0;
}
Expand Down Expand Up @@ -6204,6 +6205,10 @@ struct ib_wq *mlx5_ib_create_wq(struct ib_pd *pd,
if (udata->outlen && udata->outlen < min_resp_len)
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);
switch (init_attr->wq_type) {
case IB_WQT_RQ:
Expand Down
2 changes: 1 addition & 1 deletion drivers/infiniband/sw/rdmavt/cq.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ void rvt_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata)
if (cq->ip)
kref_put(&cq->ip->ref, rvt_release_mmap_info);
else
vfree(cq->queue);
vfree(cq->kqueue);
}

/**
Expand Down

0 comments on commit 9420e8a

Please sign in to comment.