Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0bd0f1e6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull rdma fixes from Doug Ledford:
 "Most are minor to important fixes.

  There is one performance enhancement that I took on the grounds that
  failing to check if other processes can run before running what's
  intended to be a background, idle-time task is a bug, even though the
  primary effect of the fix is to improve performance (and it was a very
  simple patch)"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma:
  IB/mlx5: Postpone remove_keys under knowledge of coming preemption
  IB/mlx4: Use vmalloc for WR buffers when needed
  IB/mlx4: Use correct order of variables in log message
  iser-target: Remove explicit mlx4 work-around
  mlx4: Expose correct max_sge_rd limit
  IB/mad: Require CM send method for everything except ClassPortInfo
  IB/cma: Add a missing rcu_read_unlock()
  IB core: Fix ib_sg_to_pages()
  IB/srp: Fix srp_map_sg_fr()
  IB/srp: Fix indirect data buffer rkey endianness
  IB/srp: Initialize dma_length in srp_map_idb
  IB/srp: Fix possible send queue overflow
  IB/srp: Fix a memory leak
  IB/sa: Put netlink request into the request list before sending
  IB/iser: use sector_div instead of do_div
  IB/core: use RCU for uverbs id lookup
  IB/qib: Minor fixes to qib per SFF 8636
  IB/core: Fix user mode post wr corruption
  IB/qib: Fix qib_mr structure
parents a80c47da ab5cdc31
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -1126,10 +1126,7 @@ static bool validate_ipv4_net_dev(struct net_device *net_dev,

	rcu_read_lock();
	err = fib_lookup(dev_net(net_dev), &fl4, &res, 0);
	if (err)
		return false;

	ret = FIB_RES_DEV(res) == net_dev;
	ret = err == 0 && FIB_RES_DEV(res) == net_dev;
	rcu_read_unlock();

	return ret;
+5 −0
Original line number Diff line number Diff line
@@ -1811,6 +1811,11 @@ static int validate_mad(const struct ib_mad_hdr *mad_hdr,
		if (qp_num == 0)
			valid = 1;
	} else {
		/* CM attributes other than ClassPortInfo only use Send method */
		if ((mad_hdr->mgmt_class == IB_MGMT_CLASS_CM) &&
		    (mad_hdr->attr_id != IB_MGMT_CLASSPORTINFO_ATTR_ID) &&
		    (mad_hdr->method != IB_MGMT_METHOD_SEND))
			goto out;
		/* Filter GSI packets sent to QP0 */
		if (qp_num != 0)
			valid = 1;
+17 −15
Original line number Diff line number Diff line
@@ -512,7 +512,7 @@ static int ib_nl_get_path_rec_attrs_len(ib_sa_comp_mask comp_mask)
	return len;
}

static int ib_nl_send_msg(struct ib_sa_query *query)
static int ib_nl_send_msg(struct ib_sa_query *query, gfp_t gfp_mask)
{
	struct sk_buff *skb = NULL;
	struct nlmsghdr *nlh;
@@ -526,7 +526,7 @@ static int ib_nl_send_msg(struct ib_sa_query *query)
	if (len <= 0)
		return -EMSGSIZE;

	skb = nlmsg_new(len, GFP_KERNEL);
	skb = nlmsg_new(len, gfp_mask);
	if (!skb)
		return -ENOMEM;

@@ -544,7 +544,7 @@ static int ib_nl_send_msg(struct ib_sa_query *query)
	/* Repair the nlmsg header length */
	nlmsg_end(skb, nlh);

	ret = ibnl_multicast(skb, nlh, RDMA_NL_GROUP_LS, GFP_KERNEL);
	ret = ibnl_multicast(skb, nlh, RDMA_NL_GROUP_LS, gfp_mask);
	if (!ret)
		ret = len;
	else
@@ -553,7 +553,7 @@ static int ib_nl_send_msg(struct ib_sa_query *query)
	return ret;
}

static int ib_nl_make_request(struct ib_sa_query *query)
static int ib_nl_make_request(struct ib_sa_query *query, gfp_t gfp_mask)
{
	unsigned long flags;
	unsigned long delay;
@@ -562,24 +562,26 @@ static int ib_nl_make_request(struct ib_sa_query *query)
	INIT_LIST_HEAD(&query->list);
	query->seq = (u32)atomic_inc_return(&ib_nl_sa_request_seq);

	/* Put the request on the list first.*/
	spin_lock_irqsave(&ib_nl_request_lock, flags);
	ret = ib_nl_send_msg(query);
	if (ret <= 0) {
		ret = -EIO;
		goto request_out;
	} else {
		ret = 0;
	}

	delay = msecs_to_jiffies(sa_local_svc_timeout_ms);
	query->timeout = delay + jiffies;
	list_add_tail(&query->list, &ib_nl_request_list);
	/* Start the timeout if this is the only request */
	if (ib_nl_request_list.next == &query->list)
		queue_delayed_work(ib_nl_wq, &ib_nl_timed_work, delay);
	spin_unlock_irqrestore(&ib_nl_request_lock, flags);

request_out:
	ret = ib_nl_send_msg(query, gfp_mask);
	if (ret <= 0) {
		ret = -EIO;
		/* Remove the request */
		spin_lock_irqsave(&ib_nl_request_lock, flags);
		list_del(&query->list);
		spin_unlock_irqrestore(&ib_nl_request_lock, flags);
	} else {
		ret = 0;
	}

	return ret;
}
@@ -1108,7 +1110,7 @@ static int send_mad(struct ib_sa_query *query, int timeout_ms, gfp_t gfp_mask)

	if (query->flags & IB_SA_ENABLE_LOCAL_SERVICE) {
		if (!ibnl_chk_listeners(RDMA_NL_GROUP_LS)) {
			if (!ib_nl_make_request(query))
			if (!ib_nl_make_request(query, gfp_mask))
				return id;
		}
		ib_sa_disable_local_svc(query);
+17 −10
Original line number Diff line number Diff line
@@ -62,9 +62,11 @@ static struct uverbs_lock_class rule_lock_class = { .name = "RULE-uobj" };
 * The ib_uobject locking scheme is as follows:
 *
 * - ib_uverbs_idr_lock protects the uverbs idrs themselves, so it
 *   needs to be held during all idr operations.  When an object is
 *   needs to be held during all idr write operations.  When an object is
 *   looked up, a reference must be taken on the object's kref before
 *   dropping this lock.
 *   dropping this lock.  For read operations, the rcu_read_lock()
 *   and rcu_write_lock() but similarly the kref reference is grabbed
 *   before the rcu_read_unlock().
 *
 * - Each object also has an rwsem.  This rwsem must be held for
 *   reading while an operation that uses the object is performed.
@@ -96,7 +98,7 @@ static void init_uobj(struct ib_uobject *uobj, u64 user_handle,

static void release_uobj(struct kref *kref)
{
	kfree(container_of(kref, struct ib_uobject, ref));
	kfree_rcu(container_of(kref, struct ib_uobject, ref), rcu);
}

static void put_uobj(struct ib_uobject *uobj)
@@ -145,7 +147,7 @@ static struct ib_uobject *__idr_get_uobj(struct idr *idr, int id,
{
	struct ib_uobject *uobj;

	spin_lock(&ib_uverbs_idr_lock);
	rcu_read_lock();
	uobj = idr_find(idr, id);
	if (uobj) {
		if (uobj->context == context)
@@ -153,7 +155,7 @@ static struct ib_uobject *__idr_get_uobj(struct idr *idr, int id,
		else
			uobj = NULL;
	}
	spin_unlock(&ib_uverbs_idr_lock);
	rcu_read_unlock();

	return uobj;
}
@@ -2446,6 +2448,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
	int                             i, sg_ind;
	int				is_ud;
	ssize_t                         ret = -EINVAL;
	size_t                          next_size;

	if (copy_from_user(&cmd, buf, sizeof cmd))
		return -EFAULT;
@@ -2490,7 +2493,8 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
				goto out_put;
			}

			ud = alloc_wr(sizeof(*ud), user_wr->num_sge);
			next_size = sizeof(*ud);
			ud = alloc_wr(next_size, user_wr->num_sge);
			if (!ud) {
				ret = -ENOMEM;
				goto out_put;
@@ -2511,7 +2515,8 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
			   user_wr->opcode == IB_WR_RDMA_READ) {
			struct ib_rdma_wr *rdma;

			rdma = alloc_wr(sizeof(*rdma), user_wr->num_sge);
			next_size = sizeof(*rdma);
			rdma = alloc_wr(next_size, user_wr->num_sge);
			if (!rdma) {
				ret = -ENOMEM;
				goto out_put;
@@ -2525,7 +2530,8 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
			   user_wr->opcode == IB_WR_ATOMIC_FETCH_AND_ADD) {
			struct ib_atomic_wr *atomic;

			atomic = alloc_wr(sizeof(*atomic), user_wr->num_sge);
			next_size = sizeof(*atomic);
			atomic = alloc_wr(next_size, user_wr->num_sge);
			if (!atomic) {
				ret = -ENOMEM;
				goto out_put;
@@ -2540,7 +2546,8 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
		} else if (user_wr->opcode == IB_WR_SEND ||
			   user_wr->opcode == IB_WR_SEND_WITH_IMM ||
			   user_wr->opcode == IB_WR_SEND_WITH_INV) {
			next = alloc_wr(sizeof(*next), user_wr->num_sge);
			next_size = sizeof(*next);
			next = alloc_wr(next_size, user_wr->num_sge);
			if (!next) {
				ret = -ENOMEM;
				goto out_put;
@@ -2572,7 +2579,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,

		if (next->num_sge) {
			next->sg_list = (void *) next +
				ALIGN(sizeof *next, sizeof (struct ib_sge));
				ALIGN(next_size, sizeof(struct ib_sge));
			if (copy_from_user(next->sg_list,
					   buf + sizeof cmd +
					   cmd.wr_count * cmd.wqe_size +
+22 −21
Original line number Diff line number Diff line
@@ -1516,7 +1516,7 @@ EXPORT_SYMBOL(ib_map_mr_sg);
 * @sg_nents:      number of entries in sg
 * @set_page:      driver page assignment function pointer
 *
 * Core service helper for drivers to covert the largest
 * Core service helper for drivers to convert the largest
 * prefix of given sg list to a page vector. The sg list
 * prefix converted is the prefix that meet the requirements
 * of ib_map_mr_sg.
@@ -1533,7 +1533,7 @@ int ib_sg_to_pages(struct ib_mr *mr,
	u64 last_end_dma_addr = 0, last_page_addr = 0;
	unsigned int last_page_off = 0;
	u64 page_mask = ~((u64)mr->page_size - 1);
	int i;
	int i, ret;

	mr->iova = sg_dma_address(&sgl[0]);
	mr->length = 0;
@@ -1544,27 +1544,29 @@ int ib_sg_to_pages(struct ib_mr *mr,
		u64 end_dma_addr = dma_addr + dma_len;
		u64 page_addr = dma_addr & page_mask;

		if (i && page_addr != dma_addr) {
			if (last_end_dma_addr != dma_addr) {
				/* gap */
				goto done;
		/*
		 * For the second and later elements, check whether either the
		 * end of element i-1 or the start of element i is not aligned
		 * on a page boundary.
		 */
		if (i && (last_page_off != 0 || page_addr != dma_addr)) {
			/* Stop mapping if there is a gap. */
			if (last_end_dma_addr != dma_addr)
				break;

			} else if (last_page_off + dma_len <= mr->page_size) {
				/* chunk this fragment with the last */
				mr->length += dma_len;
				last_end_dma_addr += dma_len;
				last_page_off += dma_len;
				continue;
			} else {
				/* map starting from the next page */
				page_addr = last_page_addr + mr->page_size;
				dma_len -= mr->page_size - last_page_off;
			}
			/*
			 * Coalesce this element with the last. If it is small
			 * enough just update mr->length. Otherwise start
			 * mapping from the next page.
			 */
			goto next_page;
		}

		do {
			if (unlikely(set_page(mr, page_addr)))
				goto done;
			ret = set_page(mr, page_addr);
			if (unlikely(ret < 0))
				return i ? : ret;
next_page:
			page_addr += mr->page_size;
		} while (page_addr < end_dma_addr);

@@ -1574,7 +1576,6 @@ int ib_sg_to_pages(struct ib_mr *mr,
		last_page_off = end_dma_addr & ~page_mask;
	}

done:
	return i;
}
EXPORT_SYMBOL(ib_sg_to_pages);
Loading