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

Commit 9090fdb9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull rdma fixes from Doug Ledford:
 "Mainly fix-ups for the various 4.2 items"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma: (24 commits)
  IB/core: Destroy ocrdma_dev_id IDR on module exit
  IB/core: Destroy multcast_idr on module exit
  IB/mlx4: Optimize do_slave_init
  IB/mlx4: Fix memory leak in do_slave_init
  IB/mlx4: Optimize freeing of items on error unwind
  IB/mlx4: Fix use of flow-counters for process_mad
  IB/ipath: Convert use of __constant_<foo> to <foo>
  IB/ipoib: Set MTU to max allowed by mode when mode changes
  IB/ipoib: Scatter-Gather support in connected mode
  IB/ucm: Fix bitmap wrap when devnum > IB_UCM_MAX_DEVICES
  IB/ipoib: Prevent lockdep warning in __ipoib_ib_dev_flush
  IB/ucma: Fix lockdep warning in ucma_lock_files
  rds: rds_ib_device.refcount overflow
  RDMA/nes: Fix for incorrect recording of the MAC address
  RDMA/nes: Fix for resolving the neigh
  RDMA/core: Fixes for port mapper client registration
  IB/IPoIB: Fix bad error flow in ipoib_add_port()
  IB/mlx4: Do not attemp to report HCA clock offset on VFs
  IB/cm: Do not queue work to a device that's going away
  IB/srp: Avoid using uninitialized variable
  ...
parents 16ff49a0 d8b2ba7c
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -88,7 +88,7 @@ void agent_send_response(const struct ib_mad_hdr *mad_hdr, const struct ib_grh *
	struct ib_ah *ah;
	struct ib_ah *ah;
	struct ib_mad_send_wr_private *mad_send_wr;
	struct ib_mad_send_wr_private *mad_send_wr;


	if (device->node_type == RDMA_NODE_IB_SWITCH)
	if (rdma_cap_ib_switch(device))
		port_priv = ib_get_agent_port(device, 0);
		port_priv = ib_get_agent_port(device, 0);
	else
	else
		port_priv = ib_get_agent_port(device, port_num);
		port_priv = ib_get_agent_port(device, port_num);
@@ -122,7 +122,7 @@ void agent_send_response(const struct ib_mad_hdr *mad_hdr, const struct ib_grh *
	memcpy(send_buf->mad, mad_hdr, resp_mad_len);
	memcpy(send_buf->mad, mad_hdr, resp_mad_len);
	send_buf->ah = ah;
	send_buf->ah = ah;


	if (device->node_type == RDMA_NODE_IB_SWITCH) {
	if (rdma_cap_ib_switch(device)) {
		mad_send_wr = container_of(send_buf,
		mad_send_wr = container_of(send_buf,
					   struct ib_mad_send_wr_private,
					   struct ib_mad_send_wr_private,
					   send_buf);
					   send_buf);
+55 −6
Original line number Original line Diff line number Diff line
@@ -169,6 +169,7 @@ struct cm_device {
	struct ib_device *ib_device;
	struct ib_device *ib_device;
	struct device *device;
	struct device *device;
	u8 ack_delay;
	u8 ack_delay;
	int going_down;
	struct cm_port *port[0];
	struct cm_port *port[0];
};
};


@@ -805,6 +806,11 @@ static void cm_enter_timewait(struct cm_id_private *cm_id_priv)
{
{
	int wait_time;
	int wait_time;
	unsigned long flags;
	unsigned long flags;
	struct cm_device *cm_dev;

	cm_dev = ib_get_client_data(cm_id_priv->id.device, &cm_client);
	if (!cm_dev)
		return;


	spin_lock_irqsave(&cm.lock, flags);
	spin_lock_irqsave(&cm.lock, flags);
	cm_cleanup_timewait(cm_id_priv->timewait_info);
	cm_cleanup_timewait(cm_id_priv->timewait_info);
@@ -818,8 +824,14 @@ static void cm_enter_timewait(struct cm_id_private *cm_id_priv)
	 */
	 */
	cm_id_priv->id.state = IB_CM_TIMEWAIT;
	cm_id_priv->id.state = IB_CM_TIMEWAIT;
	wait_time = cm_convert_to_ms(cm_id_priv->av.timeout);
	wait_time = cm_convert_to_ms(cm_id_priv->av.timeout);

	/* Check if the device started its remove_one */
	spin_lock_irq(&cm.lock);
	if (!cm_dev->going_down)
		queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work,
		queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work,
				   msecs_to_jiffies(wait_time));
				   msecs_to_jiffies(wait_time));
	spin_unlock_irq(&cm.lock);

	cm_id_priv->timewait_info = NULL;
	cm_id_priv->timewait_info = NULL;
}
}


@@ -3305,6 +3317,11 @@ static int cm_establish(struct ib_cm_id *cm_id)
	struct cm_work *work;
	struct cm_work *work;
	unsigned long flags;
	unsigned long flags;
	int ret = 0;
	int ret = 0;
	struct cm_device *cm_dev;

	cm_dev = ib_get_client_data(cm_id->device, &cm_client);
	if (!cm_dev)
		return -ENODEV;


	work = kmalloc(sizeof *work, GFP_ATOMIC);
	work = kmalloc(sizeof *work, GFP_ATOMIC);
	if (!work)
	if (!work)
@@ -3343,7 +3360,17 @@ static int cm_establish(struct ib_cm_id *cm_id)
	work->remote_id = cm_id->remote_id;
	work->remote_id = cm_id->remote_id;
	work->mad_recv_wc = NULL;
	work->mad_recv_wc = NULL;
	work->cm_event.event = IB_CM_USER_ESTABLISHED;
	work->cm_event.event = IB_CM_USER_ESTABLISHED;

	/* Check if the device started its remove_one */
	spin_lock_irq(&cm.lock);
	if (!cm_dev->going_down) {
		queue_delayed_work(cm.wq, &work->work, 0);
		queue_delayed_work(cm.wq, &work->work, 0);
	} else {
		kfree(work);
		ret = -ENODEV;
	}
	spin_unlock_irq(&cm.lock);

out:
out:
	return ret;
	return ret;
}
}
@@ -3394,6 +3421,7 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent,
	enum ib_cm_event_type event;
	enum ib_cm_event_type event;
	u16 attr_id;
	u16 attr_id;
	int paths = 0;
	int paths = 0;
	int going_down = 0;


	switch (mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) {
	switch (mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) {
	case CM_REQ_ATTR_ID:
	case CM_REQ_ATTR_ID:
@@ -3452,7 +3480,19 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent,
	work->cm_event.event = event;
	work->cm_event.event = event;
	work->mad_recv_wc = mad_recv_wc;
	work->mad_recv_wc = mad_recv_wc;
	work->port = port;
	work->port = port;

	/* Check if the device started its remove_one */
	spin_lock_irq(&cm.lock);
	if (!port->cm_dev->going_down)
		queue_delayed_work(cm.wq, &work->work, 0);
		queue_delayed_work(cm.wq, &work->work, 0);
	else
		going_down = 1;
	spin_unlock_irq(&cm.lock);

	if (going_down) {
		kfree(work);
		ib_free_recv_mad(mad_recv_wc);
	}
}
}


static int cm_init_qp_init_attr(struct cm_id_private *cm_id_priv,
static int cm_init_qp_init_attr(struct cm_id_private *cm_id_priv,
@@ -3771,7 +3811,7 @@ static void cm_add_one(struct ib_device *ib_device)


	cm_dev->ib_device = ib_device;
	cm_dev->ib_device = ib_device;
	cm_get_ack_delay(cm_dev);
	cm_get_ack_delay(cm_dev);

	cm_dev->going_down = 0;
	cm_dev->device = device_create(&cm_class, &ib_device->dev,
	cm_dev->device = device_create(&cm_class, &ib_device->dev,
				       MKDEV(0, 0), NULL,
				       MKDEV(0, 0), NULL,
				       "%s", ib_device->name);
				       "%s", ib_device->name);
@@ -3864,14 +3904,23 @@ static void cm_remove_one(struct ib_device *ib_device)
	list_del(&cm_dev->list);
	list_del(&cm_dev->list);
	write_unlock_irqrestore(&cm.device_lock, flags);
	write_unlock_irqrestore(&cm.device_lock, flags);


	spin_lock_irq(&cm.lock);
	cm_dev->going_down = 1;
	spin_unlock_irq(&cm.lock);

	for (i = 1; i <= ib_device->phys_port_cnt; i++) {
	for (i = 1; i <= ib_device->phys_port_cnt; i++) {
		if (!rdma_cap_ib_cm(ib_device, i))
		if (!rdma_cap_ib_cm(ib_device, i))
			continue;
			continue;


		port = cm_dev->port[i-1];
		port = cm_dev->port[i-1];
		ib_modify_port(ib_device, port->port_num, 0, &port_modify);
		ib_modify_port(ib_device, port->port_num, 0, &port_modify);
		ib_unregister_mad_agent(port->mad_agent);
		/*
		 * We flush the queue here after the going_down set, this
		 * verify that no new works will be queued in the recv handler,
		 * after that we can call the unregister_mad_agent
		 */
		flush_workqueue(cm.wq);
		flush_workqueue(cm.wq);
		ib_unregister_mad_agent(port->mad_agent);
		cm_remove_port_fs(port);
		cm_remove_port_fs(port);
	}
	}
	device_unregister(cm_dev->device);
	device_unregister(cm_dev->device);
+16 −17
Original line number Original line Diff line number Diff line
@@ -67,7 +67,8 @@ int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client)
		err_str = "Invalid port mapper client";
		err_str = "Invalid port mapper client";
		goto pid_query_error;
		goto pid_query_error;
	}
	}
	if (iwpm_registered_client(nl_client))
	if (iwpm_check_registration(nl_client, IWPM_REG_VALID) ||
			iwpm_user_pid == IWPM_PID_UNAVAILABLE)
		return 0;
		return 0;
	skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REG_PID, &nlh, nl_client);
	skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REG_PID, &nlh, nl_client);
	if (!skb) {
	if (!skb) {
@@ -106,7 +107,6 @@ int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client)
	ret = ibnl_multicast(skb, nlh, RDMA_NL_GROUP_IWPM, GFP_KERNEL);
	ret = ibnl_multicast(skb, nlh, RDMA_NL_GROUP_IWPM, GFP_KERNEL);
	if (ret) {
	if (ret) {
		skb = NULL; /* skb is freed in the netlink send-op handling */
		skb = NULL; /* skb is freed in the netlink send-op handling */
		iwpm_set_registered(nl_client, 1);
		iwpm_user_pid = IWPM_PID_UNAVAILABLE;
		iwpm_user_pid = IWPM_PID_UNAVAILABLE;
		err_str = "Unable to send a nlmsg";
		err_str = "Unable to send a nlmsg";
		goto pid_query_error;
		goto pid_query_error;
@@ -144,12 +144,12 @@ int iwpm_add_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
		err_str = "Invalid port mapper client";
		err_str = "Invalid port mapper client";
		goto add_mapping_error;
		goto add_mapping_error;
	}
	}
	if (!iwpm_registered_client(nl_client)) {
	if (!iwpm_valid_pid())
		return 0;
	if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) {
		err_str = "Unregistered port mapper client";
		err_str = "Unregistered port mapper client";
		goto add_mapping_error;
		goto add_mapping_error;
	}
	}
	if (!iwpm_valid_pid())
		return 0;
	skb = iwpm_create_nlmsg(RDMA_NL_IWPM_ADD_MAPPING, &nlh, nl_client);
	skb = iwpm_create_nlmsg(RDMA_NL_IWPM_ADD_MAPPING, &nlh, nl_client);
	if (!skb) {
	if (!skb) {
		err_str = "Unable to create a nlmsg";
		err_str = "Unable to create a nlmsg";
@@ -214,12 +214,12 @@ int iwpm_add_and_query_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
		err_str = "Invalid port mapper client";
		err_str = "Invalid port mapper client";
		goto query_mapping_error;
		goto query_mapping_error;
	}
	}
	if (!iwpm_registered_client(nl_client)) {
	if (!iwpm_valid_pid())
		return 0;
	if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) {
		err_str = "Unregistered port mapper client";
		err_str = "Unregistered port mapper client";
		goto query_mapping_error;
		goto query_mapping_error;
	}
	}
	if (!iwpm_valid_pid())
		return 0;
	ret = -ENOMEM;
	ret = -ENOMEM;
	skb = iwpm_create_nlmsg(RDMA_NL_IWPM_QUERY_MAPPING, &nlh, nl_client);
	skb = iwpm_create_nlmsg(RDMA_NL_IWPM_QUERY_MAPPING, &nlh, nl_client);
	if (!skb) {
	if (!skb) {
@@ -288,12 +288,12 @@ int iwpm_remove_mapping(struct sockaddr_storage *local_addr, u8 nl_client)
		err_str = "Invalid port mapper client";
		err_str = "Invalid port mapper client";
		goto remove_mapping_error;
		goto remove_mapping_error;
	}
	}
	if (!iwpm_registered_client(nl_client)) {
	if (!iwpm_valid_pid())
		return 0;
	if (iwpm_check_registration(nl_client, IWPM_REG_UNDEF)) {
		err_str = "Unregistered port mapper client";
		err_str = "Unregistered port mapper client";
		goto remove_mapping_error;
		goto remove_mapping_error;
	}
	}
	if (!iwpm_valid_pid())
		return 0;
	skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REMOVE_MAPPING, &nlh, nl_client);
	skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REMOVE_MAPPING, &nlh, nl_client);
	if (!skb) {
	if (!skb) {
		ret = -ENOMEM;
		ret = -ENOMEM;
@@ -388,7 +388,7 @@ int iwpm_register_pid_cb(struct sk_buff *skb, struct netlink_callback *cb)
	pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
	pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
			__func__, iwpm_user_pid);
			__func__, iwpm_user_pid);
	if (iwpm_valid_client(nl_client))
	if (iwpm_valid_client(nl_client))
		iwpm_set_registered(nl_client, 1);
		iwpm_set_registration(nl_client, IWPM_REG_VALID);
register_pid_response_exit:
register_pid_response_exit:
	nlmsg_request->request_done = 1;
	nlmsg_request->request_done = 1;
	/* always for found nlmsg_request */
	/* always for found nlmsg_request */
@@ -644,7 +644,6 @@ int iwpm_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
{
{
	struct nlattr *nltb[IWPM_NLA_MAPINFO_REQ_MAX];
	struct nlattr *nltb[IWPM_NLA_MAPINFO_REQ_MAX];
	const char *msg_type = "Mapping Info response";
	const char *msg_type = "Mapping Info response";
	int iwpm_pid;
	u8 nl_client;
	u8 nl_client;
	char *iwpm_name;
	char *iwpm_name;
	u16 iwpm_version;
	u16 iwpm_version;
@@ -669,14 +668,14 @@ int iwpm_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
				__func__, nl_client);
				__func__, nl_client);
		return ret;
		return ret;
	}
	}
	iwpm_set_registered(nl_client, 0);
	iwpm_set_registration(nl_client, IWPM_REG_INCOMPL);
	atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
	atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
	iwpm_user_pid = cb->nlh->nlmsg_pid;
	if (!iwpm_mapinfo_available())
	if (!iwpm_mapinfo_available())
		return 0;
		return 0;
	iwpm_pid = cb->nlh->nlmsg_pid;
	pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
	pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
		 __func__, iwpm_pid);
		 __func__, iwpm_user_pid);
	ret = iwpm_send_mapinfo(nl_client, iwpm_pid);
	ret = iwpm_send_mapinfo(nl_client, iwpm_user_pid);
	return ret;
	return ret;
}
}
EXPORT_SYMBOL(iwpm_mapping_info_cb);
EXPORT_SYMBOL(iwpm_mapping_info_cb);
+10 −2
Original line number Original line Diff line number Diff line
@@ -78,6 +78,7 @@ int iwpm_init(u8 nl_client)
	mutex_unlock(&iwpm_admin_lock);
	mutex_unlock(&iwpm_admin_lock);
	if (!ret) {
	if (!ret) {
		iwpm_set_valid(nl_client, 1);
		iwpm_set_valid(nl_client, 1);
		iwpm_set_registration(nl_client, IWPM_REG_UNDEF);
		pr_debug("%s: Mapinfo and reminfo tables are created\n",
		pr_debug("%s: Mapinfo and reminfo tables are created\n",
				__func__);
				__func__);
	}
	}
@@ -106,6 +107,7 @@ int iwpm_exit(u8 nl_client)
	}
	}
	mutex_unlock(&iwpm_admin_lock);
	mutex_unlock(&iwpm_admin_lock);
	iwpm_set_valid(nl_client, 0);
	iwpm_set_valid(nl_client, 0);
	iwpm_set_registration(nl_client, IWPM_REG_UNDEF);
	return 0;
	return 0;
}
}
EXPORT_SYMBOL(iwpm_exit);
EXPORT_SYMBOL(iwpm_exit);
@@ -397,17 +399,23 @@ void iwpm_set_valid(u8 nl_client, int valid)
}
}


/* valid client */
/* valid client */
int iwpm_registered_client(u8 nl_client)
u32 iwpm_get_registration(u8 nl_client)
{
{
	return iwpm_admin.reg_list[nl_client];
	return iwpm_admin.reg_list[nl_client];
}
}


/* valid client */
/* valid client */
void iwpm_set_registered(u8 nl_client, int reg)
void iwpm_set_registration(u8 nl_client, u32 reg)
{
{
	iwpm_admin.reg_list[nl_client] = reg;
	iwpm_admin.reg_list[nl_client] = reg;
}
}


/* valid client */
u32 iwpm_check_registration(u8 nl_client, u32 reg)
{
	return (iwpm_get_registration(nl_client) & reg);
}

int iwpm_compare_sockaddr(struct sockaddr_storage *a_sockaddr,
int iwpm_compare_sockaddr(struct sockaddr_storage *a_sockaddr,
				struct sockaddr_storage *b_sockaddr)
				struct sockaddr_storage *b_sockaddr)
{
{
+22 −6
Original line number Original line Diff line number Diff line
@@ -58,6 +58,10 @@
#define IWPM_PID_UNDEFINED     -1
#define IWPM_PID_UNDEFINED     -1
#define IWPM_PID_UNAVAILABLE   -2
#define IWPM_PID_UNAVAILABLE   -2


#define IWPM_REG_UNDEF          0x01
#define IWPM_REG_VALID          0x02
#define IWPM_REG_INCOMPL        0x04

struct iwpm_nlmsg_request {
struct iwpm_nlmsg_request {
	struct list_head    inprocess_list;
	struct list_head    inprocess_list;
	__u32               nlmsg_seq;
	__u32               nlmsg_seq;
@@ -88,7 +92,7 @@ struct iwpm_admin_data {
	atomic_t refcount;
	atomic_t refcount;
	atomic_t nlmsg_seq;
	atomic_t nlmsg_seq;
	int      client_list[RDMA_NL_NUM_CLIENTS];
	int      client_list[RDMA_NL_NUM_CLIENTS];
	int      reg_list[RDMA_NL_NUM_CLIENTS];
	u32      reg_list[RDMA_NL_NUM_CLIENTS];
};
};


/**
/**
@@ -159,19 +163,31 @@ int iwpm_valid_client(u8 nl_client);
void iwpm_set_valid(u8 nl_client, int valid);
void iwpm_set_valid(u8 nl_client, int valid);


/**
/**
 * iwpm_registered_client - Check if the port mapper client is registered
 * iwpm_check_registration - Check if the client registration
 *			      matches the given one
 * @nl_client: The index of the netlink client
 * @nl_client: The index of the netlink client
 * @reg: The given registration type to compare with
 *
 *
 * Call iwpm_register_pid() to register a client
 * Call iwpm_register_pid() to register a client
 * Returns true if the client registration matches reg,
 * otherwise returns false
 */
u32 iwpm_check_registration(u8 nl_client, u32 reg);

/**
 * iwpm_set_registration - Set the client registration
 * @nl_client: The index of the netlink client
 * @reg: Registration type to set
 */
 */
int iwpm_registered_client(u8 nl_client);
void iwpm_set_registration(u8 nl_client, u32 reg);


/**
/**
 * iwpm_set_registered - Set the port mapper client to registered or not
 * iwpm_get_registration
 * @nl_client: The index of the netlink client
 * @nl_client: The index of the netlink client
 * @reg: 1 if registered or 0 if not
 *
 * Returns the client registration type
 */
 */
void iwpm_set_registered(u8 nl_client, int reg);
u32 iwpm_get_registration(u8 nl_client);


/**
/**
 * iwpm_send_mapinfo - Send local and mapped IPv4/IPv6 address info of
 * iwpm_send_mapinfo - Send local and mapped IPv4/IPv6 address info of
Loading