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

Commit bfa738cf authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull rdma fixes from Doug Ledford:
 "Third set of -rc fixes for 4.13 cycle

   - small set of miscellanous fixes

   - a reasonably sizable set of IPoIB fixes that deal with multiple
     long standing issues"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma:
  IB/hns: checking for IS_ERR() instead of NULL
  RDMA/mlx5: Fix existence check for extended address vector
  IB/uverbs: Fix device cleanup
  RDMA/uverbs: Prevent leak of reserved field
  IB/core: Fix race condition in resolving IP to MAC
  IB/ipoib: Notify on modify QP failure only when relevant
  Revert "IB/core: Allow QP state transition from reset to error"
  IB/ipoib: Remove double pointer assigning
  IB/ipoib: Clean error paths in add port
  IB/ipoib: Add get statistics support to SRIOV VF
  IB/ipoib: Add multicast packets statistics
  IB/ipoib: Set IPOIB_NEIGH_TBL_FLUSH after flushed completion initialization
  IB/ipoib: Prevent setting negative values to max_nonsrq_conn_qp
  IB/ipoib: Make sure no in-flight joins while leaving that mcast
  IB/ipoib: Use cancel_delayed_work_sync when needed
  IB/ipoib: Fix race between light events and interface restart
parents b95c29a2 48107c4e
Loading
Loading
Loading
Loading
+48 −14
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ struct addr_req {
	void (*callback)(int status, struct sockaddr *src_addr,
			 struct rdma_dev_addr *addr, void *context);
	unsigned long timeout;
	struct delayed_work work;
	int status;
	u32 seq;
};
@@ -295,7 +296,7 @@ int rdma_translate_ip(const struct sockaddr *addr,
}
EXPORT_SYMBOL(rdma_translate_ip);

static void set_timeout(unsigned long time)
static void set_timeout(struct delayed_work *delayed_work, unsigned long time)
{
	unsigned long delay;

@@ -303,7 +304,7 @@ static void set_timeout(unsigned long time)
	if ((long)delay < 0)
		delay = 0;

	mod_delayed_work(addr_wq, &work, delay);
	mod_delayed_work(addr_wq, delayed_work, delay);
}

static void queue_req(struct addr_req *req)
@@ -318,8 +319,7 @@ static void queue_req(struct addr_req *req)

	list_add(&req->list, &temp_req->list);

	if (req_list.next == &req->list)
		set_timeout(req->timeout);
	set_timeout(&req->work, req->timeout);
	mutex_unlock(&lock);
}

@@ -574,6 +574,37 @@ static int addr_resolve(struct sockaddr *src_in,
	return ret;
}

static void process_one_req(struct work_struct *_work)
{
	struct addr_req *req;
	struct sockaddr *src_in, *dst_in;

	mutex_lock(&lock);
	req = container_of(_work, struct addr_req, work.work);

	if (req->status == -ENODATA) {
		src_in = (struct sockaddr *)&req->src_addr;
		dst_in = (struct sockaddr *)&req->dst_addr;
		req->status = addr_resolve(src_in, dst_in, req->addr,
					   true, req->seq);
		if (req->status && time_after_eq(jiffies, req->timeout)) {
			req->status = -ETIMEDOUT;
		} else if (req->status == -ENODATA) {
			/* requeue the work for retrying again */
			set_timeout(&req->work, req->timeout);
			mutex_unlock(&lock);
			return;
		}
	}
	list_del(&req->list);
	mutex_unlock(&lock);

	req->callback(req->status, (struct sockaddr *)&req->src_addr,
		req->addr, req->context);
	put_client(req->client);
	kfree(req);
}

static void process_req(struct work_struct *work)
{
	struct addr_req *req, *temp_req;
@@ -591,20 +622,23 @@ static void process_req(struct work_struct *work)
						   true, req->seq);
			if (req->status && time_after_eq(jiffies, req->timeout))
				req->status = -ETIMEDOUT;
			else if (req->status == -ENODATA)
			else if (req->status == -ENODATA) {
				set_timeout(&req->work, req->timeout);
				continue;
			}
		}
		list_move_tail(&req->list, &done_list);
	}

	if (!list_empty(&req_list)) {
		req = list_entry(req_list.next, struct addr_req, list);
		set_timeout(req->timeout);
	}
	mutex_unlock(&lock);

	list_for_each_entry_safe(req, temp_req, &done_list, list) {
		list_del(&req->list);
		/* It is safe to cancel other work items from this work item
		 * because at a time there can be only one work item running
		 * with this single threaded work queue.
		 */
		cancel_delayed_work(&req->work);
		req->callback(req->status, (struct sockaddr *) &req->src_addr,
			req->addr, req->context);
		put_client(req->client);
@@ -647,6 +681,7 @@ int rdma_resolve_ip(struct rdma_addr_client *client,
	req->context = context;
	req->client = client;
	atomic_inc(&client->refcount);
	INIT_DELAYED_WORK(&req->work, process_one_req);
	req->seq = (u32)atomic_inc_return(&ib_nl_addr_request_seq);

	req->status = addr_resolve(src_in, dst_in, addr, true, req->seq);
@@ -701,7 +736,7 @@ void rdma_addr_cancel(struct rdma_dev_addr *addr)
			req->status = -ECANCELED;
			req->timeout = jiffies;
			list_move(&req->list, &req_list);
			set_timeout(req->timeout);
			set_timeout(&req->work, req->timeout);
			break;
		}
	}
@@ -807,9 +842,8 @@ static int netevent_callback(struct notifier_block *self, unsigned long event,
	if (event == NETEVENT_NEIGH_UPDATE) {
		struct neighbour *neigh = ctx;

		if (neigh->nud_state & NUD_VALID) {
			set_timeout(jiffies);
		}
		if (neigh->nud_state & NUD_VALID)
			set_timeout(&work, jiffies);
	}
	return 0;
}
@@ -820,7 +854,7 @@ static struct notifier_block nb = {

int addr_init(void)
{
	addr_wq = alloc_workqueue("ib_addr", WQ_MEM_RECLAIM, 0);
	addr_wq = alloc_ordered_workqueue("ib_addr", WQ_MEM_RECLAIM);
	if (!addr_wq)
		return -ENOMEM;

+1 −1
Original line number Diff line number Diff line
@@ -1153,7 +1153,7 @@ ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file,
			    int out_len)
{
	struct ib_uverbs_resize_cq	cmd;
	struct ib_uverbs_resize_cq_resp	resp;
	struct ib_uverbs_resize_cq_resp	resp = {};
	struct ib_udata                 udata;
	struct ib_cq			*cq;
	int				ret = -EINVAL;
+1 −2
Original line number Diff line number Diff line
@@ -250,6 +250,7 @@ void ib_uverbs_release_file(struct kref *ref)
	if (atomic_dec_and_test(&file->device->refcount))
		ib_uverbs_comp_dev(file->device);

	kobject_put(&file->device->kobj);
	kfree(file);
}

@@ -917,7 +918,6 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
static int ib_uverbs_close(struct inode *inode, struct file *filp)
{
	struct ib_uverbs_file *file = filp->private_data;
	struct ib_uverbs_device *dev = file->device;

	mutex_lock(&file->cleanup_mutex);
	if (file->ucontext) {
@@ -939,7 +939,6 @@ static int ib_uverbs_close(struct inode *inode, struct file *filp)
			 ib_uverbs_release_async_event_file);

	kref_put(&file->ref, ib_uverbs_release_file);
	kobject_put(&dev->kobj);

	return 0;
}
+0 −1
Original line number Diff line number Diff line
@@ -895,7 +895,6 @@ static const struct {
} qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
	[IB_QPS_RESET] = {
		[IB_QPS_RESET] = { .valid = 1 },
		[IB_QPS_ERR] =   { .valid = 1 },
		[IB_QPS_INIT]  = {
			.valid = 1,
			.req_param = {
+1 −1
Original line number Diff line number Diff line
@@ -733,7 +733,7 @@ static int hns_roce_v1_rsv_lp_qp(struct hns_roce_dev *hr_dev)
			continue;

		free_mr->mr_free_qp[i] = hns_roce_v1_create_lp_qp(hr_dev, pd);
		if (IS_ERR(free_mr->mr_free_qp[i])) {
		if (!free_mr->mr_free_qp[i]) {
			dev_err(dev, "Create loop qp failed!\n");
			goto create_lp_qp_failed;
		}
Loading