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

Commit b1ef951e authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband

* 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband:
  IPoIB: Make sure struct ipoib_neigh.queue is always initialized
  IB/iser: Use the new verbs DMA mapping functions
  IB/srp: Use new verbs IB DMA mapping functions
  IPoIB: Use the new verbs DMA mapping functions
  IB/core: Use the new verbs DMA mapping functions
  IB/ipath: Implement new verbs DMA mapping functions
  IB: Add DMA mapping functions to allow device drivers to interpose
  RDMA/cma: Export rdma cm interface to userspace
  RDMA/cma: Add support for RDMA_PS_UDP
  RDMA/cma: Allow early transition to RTS to handle lost CM messages
  RDMA/cma: Report connect info with connect events
  RDMA/cma: Remove unneeded qp_type parameter from rdma_cm
  IB/ipath: Fix IRQ for PCI Express HCAs
  RDMA/amso1100: Fix memory leak in c2_qp_modify()
  IB/iser: Remove unused "write-only" variables
  IB/ipath: Remove unused "write-only" variables
  IB/fmr: ib_flush_fmr_pool() may wait too long
parents 775ba7ad 82b39913
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
infiniband-$(CONFIG_INFINIBAND_ADDR_TRANS)	:= ib_addr.o rdma_cm.o
user_access-$(CONFIG_INFINIBAND_ADDR_TRANS)	:= rdma_ucm.o

obj-$(CONFIG_INFINIBAND) +=		ib_core.o ib_mad.o ib_sa.o \
					ib_cm.o iw_cm.o $(infiniband-y)
obj-$(CONFIG_INFINIBAND_USER_MAD) +=	ib_umad.o
obj-$(CONFIG_INFINIBAND_USER_ACCESS) +=	ib_uverbs.o ib_ucm.o
obj-$(CONFIG_INFINIBAND_USER_ACCESS) +=	ib_uverbs.o ib_ucm.o \
					$(user_access-y)

ib_core-y :=			packer.o ud_header.o verbs.o sysfs.o \
				device.o fmr_pool.o cache.o
@@ -18,6 +20,8 @@ iw_cm-y := iwcm.o

rdma_cm-y :=			cma.o

rdma_ucm-y :=			ucma.o

ib_addr-y :=			addr.o

ib_umad-y :=			user_mad.o
+4 −0
Original line number Diff line number Diff line
@@ -3289,6 +3289,10 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv,

	spin_lock_irqsave(&cm_id_priv->lock, flags);
	switch (cm_id_priv->id.state) {
	/* Allow transition to RTS before sending REP */
	case IB_CM_REQ_RCVD:
	case IB_CM_MRA_REQ_SENT:

	case IB_CM_REP_RCVD:
	case IB_CM_MRA_REP_SENT:
	case IB_CM_REP_SENT:
+324 −92
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ static DEFINE_MUTEX(lock);
static struct workqueue_struct *cma_wq;
static DEFINE_IDR(sdp_ps);
static DEFINE_IDR(tcp_ps);
static DEFINE_IDR(udp_ps);

struct cma_device {
	struct list_head	list;
@@ -133,7 +134,6 @@ struct rdma_id_private {

	u32			seq_num;
	u32			qp_num;
	enum ib_qp_type		qp_type;
	u8			srq;
};

@@ -392,7 +392,6 @@ int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd,

	id->qp = qp;
	id_priv->qp_num = qp->qp_num;
	id_priv->qp_type = qp->qp_type;
	id_priv->srq = (qp->srq != NULL);
	return 0;
err:
@@ -510,9 +509,17 @@ static inline int cma_any_addr(struct sockaddr *addr)
	return cma_zero_addr(addr) || cma_loopback_addr(addr);
}

static inline __be16 cma_port(struct sockaddr *addr)
{
	if (addr->sa_family == AF_INET)
		return ((struct sockaddr_in *) addr)->sin_port;
	else
		return ((struct sockaddr_in6 *) addr)->sin6_port;
}

static inline int cma_any_port(struct sockaddr *addr)
{
	return !((struct sockaddr_in *) addr)->sin_port;
	return !cma_port(addr);
}

static int cma_get_net_info(void *hdr, enum rdma_port_space ps,
@@ -594,20 +601,6 @@ static inline int cma_user_data_offset(enum rdma_port_space ps)
	}
}

static int cma_notify_user(struct rdma_id_private *id_priv,
			   enum rdma_cm_event_type type, int status,
			   void *data, u8 data_len)
{
	struct rdma_cm_event event;

	event.event = type;
	event.status = status;
	event.private_data = data;
	event.private_data_len = data_len;

	return id_priv->id.event_handler(&id_priv->id, &event);
}

static void cma_cancel_route(struct rdma_id_private *id_priv)
{
	switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
@@ -776,63 +769,61 @@ static int cma_verify_rep(struct rdma_id_private *id_priv, void *data)
	return 0;
}

static int cma_rtu_recv(struct rdma_id_private *id_priv)
static void cma_set_rep_event_data(struct rdma_cm_event *event,
				   struct ib_cm_rep_event_param *rep_data,
				   void *private_data)
{
	int ret;

	ret = cma_modify_qp_rts(&id_priv->id);
	if (ret)
		goto reject;

	return 0;
reject:
	cma_modify_qp_err(&id_priv->id);
	ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED,
		       NULL, 0, NULL, 0);
	return ret;
	event->param.conn.private_data = private_data;
	event->param.conn.private_data_len = IB_CM_REP_PRIVATE_DATA_SIZE;
	event->param.conn.responder_resources = rep_data->responder_resources;
	event->param.conn.initiator_depth = rep_data->initiator_depth;
	event->param.conn.flow_control = rep_data->flow_control;
	event->param.conn.rnr_retry_count = rep_data->rnr_retry_count;
	event->param.conn.srq = rep_data->srq;
	event->param.conn.qp_num = rep_data->remote_qpn;
}

static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
{
	struct rdma_id_private *id_priv = cm_id->context;
	enum rdma_cm_event_type event;
	u8 private_data_len = 0;
	int ret = 0, status = 0;
	struct rdma_cm_event event;
	int ret = 0;

	atomic_inc(&id_priv->dev_remove);
	if (!cma_comp(id_priv, CMA_CONNECT))
		goto out;

	memset(&event, 0, sizeof event);
	switch (ib_event->event) {
	case IB_CM_REQ_ERROR:
	case IB_CM_REP_ERROR:
		event = RDMA_CM_EVENT_UNREACHABLE;
		status = -ETIMEDOUT;
		event.event = RDMA_CM_EVENT_UNREACHABLE;
		event.status = -ETIMEDOUT;
		break;
	case IB_CM_REP_RECEIVED:
		status = cma_verify_rep(id_priv, ib_event->private_data);
		if (status)
			event = RDMA_CM_EVENT_CONNECT_ERROR;
		event.status = cma_verify_rep(id_priv, ib_event->private_data);
		if (event.status)
			event.event = RDMA_CM_EVENT_CONNECT_ERROR;
		else if (id_priv->id.qp && id_priv->id.ps != RDMA_PS_SDP) {
			status = cma_rep_recv(id_priv);
			event = status ? RDMA_CM_EVENT_CONNECT_ERROR :
			event.status = cma_rep_recv(id_priv);
			event.event = event.status ? RDMA_CM_EVENT_CONNECT_ERROR :
						     RDMA_CM_EVENT_ESTABLISHED;
		} else
			event = RDMA_CM_EVENT_CONNECT_RESPONSE;
		private_data_len = IB_CM_REP_PRIVATE_DATA_SIZE;
			event.event = RDMA_CM_EVENT_CONNECT_RESPONSE;
		cma_set_rep_event_data(&event, &ib_event->param.rep_rcvd,
				       ib_event->private_data);
		break;
	case IB_CM_RTU_RECEIVED:
		status = cma_rtu_recv(id_priv);
		event = status ? RDMA_CM_EVENT_CONNECT_ERROR :
				 RDMA_CM_EVENT_ESTABLISHED;
	case IB_CM_USER_ESTABLISHED:
		event.event = RDMA_CM_EVENT_ESTABLISHED;
		break;
	case IB_CM_DREQ_ERROR:
		status = -ETIMEDOUT; /* fall through */
		event.status = -ETIMEDOUT; /* fall through */
	case IB_CM_DREQ_RECEIVED:
	case IB_CM_DREP_RECEIVED:
		if (!cma_comp_exch(id_priv, CMA_CONNECT, CMA_DISCONNECT))
			goto out;
		event = RDMA_CM_EVENT_DISCONNECTED;
		event.event = RDMA_CM_EVENT_DISCONNECTED;
		break;
	case IB_CM_TIMEWAIT_EXIT:
	case IB_CM_MRA_RECEIVED:
@@ -840,9 +831,10 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
		goto out;
	case IB_CM_REJ_RECEIVED:
		cma_modify_qp_err(&id_priv->id);
		status = ib_event->param.rej_rcvd.reason;
		event = RDMA_CM_EVENT_REJECTED;
		private_data_len = IB_CM_REJ_PRIVATE_DATA_SIZE;
		event.status = ib_event->param.rej_rcvd.reason;
		event.event = RDMA_CM_EVENT_REJECTED;
		event.param.conn.private_data = ib_event->private_data;
		event.param.conn.private_data_len = IB_CM_REJ_PRIVATE_DATA_SIZE;
		break;
	default:
		printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d",
@@ -850,8 +842,7 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
		goto out;
	}

	ret = cma_notify_user(id_priv, event, status, ib_event->private_data,
			      private_data_len);
	ret = id_priv->id.event_handler(&id_priv->id, &event);
	if (ret) {
		/* Destroy the CM ID by returning a non-zero value. */
		id_priv->cm_id.ib = NULL;
@@ -865,7 +856,7 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
	return ret;
}

static struct rdma_id_private *cma_new_id(struct rdma_cm_id *listen_id,
static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
					       struct ib_cm_event *ib_event)
{
	struct rdma_id_private *id_priv;
@@ -913,9 +904,61 @@ static struct rdma_id_private *cma_new_id(struct rdma_cm_id *listen_id,
	return NULL;
}

static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id,
					      struct ib_cm_event *ib_event)
{
	struct rdma_id_private *id_priv;
	struct rdma_cm_id *id;
	union cma_ip_addr *src, *dst;
	__u16 port;
	u8 ip_ver;
	int ret;

	id = rdma_create_id(listen_id->event_handler, listen_id->context,
			    listen_id->ps);
	if (IS_ERR(id))
		return NULL;


	if (cma_get_net_info(ib_event->private_data, listen_id->ps,
			     &ip_ver, &port, &src, &dst))
		goto err;

	cma_save_net_info(&id->route.addr, &listen_id->route.addr,
			  ip_ver, port, src, dst);

	ret = rdma_translate_ip(&id->route.addr.src_addr,
				&id->route.addr.dev_addr);
	if (ret)
		goto err;

	id_priv = container_of(id, struct rdma_id_private, id);
	id_priv->state = CMA_CONNECT;
	return id_priv;
err:
	rdma_destroy_id(id);
	return NULL;
}

static void cma_set_req_event_data(struct rdma_cm_event *event,
				   struct ib_cm_req_event_param *req_data,
				   void *private_data, int offset)
{
	event->param.conn.private_data = private_data + offset;
	event->param.conn.private_data_len = IB_CM_REQ_PRIVATE_DATA_SIZE - offset;
	event->param.conn.responder_resources = req_data->responder_resources;
	event->param.conn.initiator_depth = req_data->initiator_depth;
	event->param.conn.flow_control = req_data->flow_control;
	event->param.conn.retry_count = req_data->retry_count;
	event->param.conn.rnr_retry_count = req_data->rnr_retry_count;
	event->param.conn.srq = req_data->srq;
	event->param.conn.qp_num = req_data->remote_qpn;
}

static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
{
	struct rdma_id_private *listen_id, *conn_id;
	struct rdma_cm_event event;
	int offset, ret;

	listen_id = cm_id->context;
@@ -925,7 +968,19 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
		goto out;
	}

	conn_id = cma_new_id(&listen_id->id, ib_event);
	memset(&event, 0, sizeof event);
	offset = cma_user_data_offset(listen_id->id.ps);
	event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
	if (listen_id->id.ps == RDMA_PS_UDP) {
		conn_id = cma_new_udp_id(&listen_id->id, ib_event);
		event.param.ud.private_data = ib_event->private_data + offset;
		event.param.ud.private_data_len =
				IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE - offset;
	} else {
		conn_id = cma_new_conn_id(&listen_id->id, ib_event);
		cma_set_req_event_data(&event, &ib_event->param.req_rcvd,
				       ib_event->private_data, offset);
	}
	if (!conn_id) {
		ret = -ENOMEM;
		goto out;
@@ -942,10 +997,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
	cm_id->context = conn_id;
	cm_id->cm_handler = cma_ib_handler;

	offset = cma_user_data_offset(listen_id->id.ps);
	ret = cma_notify_user(conn_id, RDMA_CM_EVENT_CONNECT_REQUEST, 0,
			      ib_event->private_data + offset,
			      IB_CM_REQ_PRIVATE_DATA_SIZE - offset);
	ret = conn_id->id.event_handler(&conn_id->id, &event);
	if (!ret)
		goto out;

@@ -964,8 +1016,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)

static __be64 cma_get_service_id(enum rdma_port_space ps, struct sockaddr *addr)
{
	return cpu_to_be64(((u64)ps << 16) +
	       be16_to_cpu(((struct sockaddr_in *) addr)->sin_port));
	return cpu_to_be64(((u64)ps << 16) + be16_to_cpu(cma_port(addr)));
}

static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr,
@@ -1021,15 +1072,16 @@ static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr,
static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
{
	struct rdma_id_private *id_priv = iw_id->context;
	enum rdma_cm_event_type event = 0;
	struct rdma_cm_event event;
	struct sockaddr_in *sin;
	int ret = 0;

	memset(&event, 0, sizeof event);
	atomic_inc(&id_priv->dev_remove);

	switch (iw_event->event) {
	case IW_CM_EVENT_CLOSE:
		event = RDMA_CM_EVENT_DISCONNECTED;
		event.event = RDMA_CM_EVENT_DISCONNECTED;
		break;
	case IW_CM_EVENT_CONNECT_REPLY:
		sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr;
@@ -1037,20 +1089,21 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
		sin = (struct sockaddr_in *) &id_priv->id.route.addr.dst_addr;
		*sin = iw_event->remote_addr;
		if (iw_event->status)
			event = RDMA_CM_EVENT_REJECTED;
			event.event = RDMA_CM_EVENT_REJECTED;
		else
			event = RDMA_CM_EVENT_ESTABLISHED;
			event.event = RDMA_CM_EVENT_ESTABLISHED;
		break;
	case IW_CM_EVENT_ESTABLISHED:
		event = RDMA_CM_EVENT_ESTABLISHED;
		event.event = RDMA_CM_EVENT_ESTABLISHED;
		break;
	default:
		BUG_ON(1);
	}

	ret = cma_notify_user(id_priv, event, iw_event->status,
			      iw_event->private_data,
			      iw_event->private_data_len);
	event.status = iw_event->status;
	event.param.conn.private_data = iw_event->private_data;
	event.param.conn.private_data_len = iw_event->private_data_len;
	ret = id_priv->id.event_handler(&id_priv->id, &event);
	if (ret) {
		/* Destroy the CM ID by returning a non-zero value. */
		id_priv->cm_id.iw = NULL;
@@ -1071,6 +1124,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
	struct rdma_id_private *listen_id, *conn_id;
	struct sockaddr_in *sin;
	struct net_device *dev = NULL;
	struct rdma_cm_event event;
	int ret;

	listen_id = cm_id->context;
@@ -1124,9 +1178,11 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
	sin = (struct sockaddr_in *) &new_cm_id->route.addr.dst_addr;
	*sin = iw_event->remote_addr;

	ret = cma_notify_user(conn_id, RDMA_CM_EVENT_CONNECT_REQUEST, 0,
			      iw_event->private_data,
			      iw_event->private_data_len);
	memset(&event, 0, sizeof event);
	event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
	event.param.conn.private_data = iw_event->private_data;
	event.param.conn.private_data_len = iw_event->private_data_len;
	ret = conn_id->id.event_handler(&conn_id->id, &event);
	if (ret) {
		/* User wants to destroy the CM ID */
		conn_id->cm_id.iw = NULL;
@@ -1515,8 +1571,9 @@ static void addr_handler(int status, struct sockaddr *src_addr,
			 struct rdma_dev_addr *dev_addr, void *context)
{
	struct rdma_id_private *id_priv = context;
	enum rdma_cm_event_type event;
	struct rdma_cm_event event;

	memset(&event, 0, sizeof event);
	atomic_inc(&id_priv->dev_remove);

	/*
@@ -1536,14 +1593,15 @@ static void addr_handler(int status, struct sockaddr *src_addr,
	if (status) {
		if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ADDR_BOUND))
			goto out;
		event = RDMA_CM_EVENT_ADDR_ERROR;
		event.event = RDMA_CM_EVENT_ADDR_ERROR;
		event.status = status;
	} else {
		memcpy(&id_priv->id.route.addr.src_addr, src_addr,
		       ip_addr_size(src_addr));
		event = RDMA_CM_EVENT_ADDR_RESOLVED;
		event.event = RDMA_CM_EVENT_ADDR_RESOLVED;
	}

	if (cma_notify_user(id_priv, event, status, NULL, 0)) {
	if (id_priv->id.event_handler(&id_priv->id, &event)) {
		cma_exch(id_priv, CMA_DESTROYING);
		cma_release_remove(id_priv);
		cma_deref_id(id_priv);
@@ -1733,6 +1791,9 @@ static int cma_get_port(struct rdma_id_private *id_priv)
	case RDMA_PS_TCP:
		ps = &tcp_ps;
		break;
	case RDMA_PS_UDP:
		ps = &udp_ps;
		break;
	default:
		return -EPROTONOSUPPORT;
	}
@@ -1821,6 +1882,110 @@ static int cma_format_hdr(void *hdr, enum rdma_port_space ps,
	return 0;
}

static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
				struct ib_cm_event *ib_event)
{
	struct rdma_id_private *id_priv = cm_id->context;
	struct rdma_cm_event event;
	struct ib_cm_sidr_rep_event_param *rep = &ib_event->param.sidr_rep_rcvd;
	int ret = 0;

	memset(&event, 0, sizeof event);
	atomic_inc(&id_priv->dev_remove);
	if (!cma_comp(id_priv, CMA_CONNECT))
		goto out;

	switch (ib_event->event) {
	case IB_CM_SIDR_REQ_ERROR:
		event.event = RDMA_CM_EVENT_UNREACHABLE;
		event.status = -ETIMEDOUT;
		break;
	case IB_CM_SIDR_REP_RECEIVED:
		event.param.ud.private_data = ib_event->private_data;
		event.param.ud.private_data_len = IB_CM_SIDR_REP_PRIVATE_DATA_SIZE;
		if (rep->status != IB_SIDR_SUCCESS) {
			event.event = RDMA_CM_EVENT_UNREACHABLE;
			event.status = ib_event->param.sidr_rep_rcvd.status;
			break;
		}
		if (rep->qkey != RDMA_UD_QKEY) {
			event.event = RDMA_CM_EVENT_UNREACHABLE;
			event.status = -EINVAL;
			break;
		}
		ib_init_ah_from_path(id_priv->id.device, id_priv->id.port_num,
				     id_priv->id.route.path_rec,
				     &event.param.ud.ah_attr);
		event.param.ud.qp_num = rep->qpn;
		event.param.ud.qkey = rep->qkey;
		event.event = RDMA_CM_EVENT_ESTABLISHED;
		event.status = 0;
		break;
	default:
		printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d",
		       ib_event->event);
		goto out;
	}

	ret = id_priv->id.event_handler(&id_priv->id, &event);
	if (ret) {
		/* Destroy the CM ID by returning a non-zero value. */
		id_priv->cm_id.ib = NULL;
		cma_exch(id_priv, CMA_DESTROYING);
		cma_release_remove(id_priv);
		rdma_destroy_id(&id_priv->id);
		return ret;
	}
out:
	cma_release_remove(id_priv);
	return ret;
}

static int cma_resolve_ib_udp(struct rdma_id_private *id_priv,
			      struct rdma_conn_param *conn_param)
{
	struct ib_cm_sidr_req_param req;
	struct rdma_route *route;
	int ret;

	req.private_data_len = sizeof(struct cma_hdr) +
			       conn_param->private_data_len;
	req.private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
	if (!req.private_data)
		return -ENOMEM;

	if (conn_param->private_data && conn_param->private_data_len)
		memcpy((void *) req.private_data + sizeof(struct cma_hdr),
		       conn_param->private_data, conn_param->private_data_len);

	route = &id_priv->id.route;
	ret = cma_format_hdr((void *) req.private_data, id_priv->id.ps, route);
	if (ret)
		goto out;

	id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device,
					    cma_sidr_rep_handler, id_priv);
	if (IS_ERR(id_priv->cm_id.ib)) {
		ret = PTR_ERR(id_priv->cm_id.ib);
		goto out;
	}

	req.path = route->path_rec;
	req.service_id = cma_get_service_id(id_priv->id.ps,
					    &route->addr.dst_addr);
	req.timeout_ms = 1 << (CMA_CM_RESPONSE_TIMEOUT - 8);
	req.max_cm_retries = CMA_MAX_CM_RETRIES;

	ret = ib_send_cm_sidr_req(id_priv->cm_id.ib, &req);
	if (ret) {
		ib_destroy_cm_id(id_priv->cm_id.ib);
		id_priv->cm_id.ib = NULL;
	}
out:
	kfree(req.private_data);
	return ret;
}

static int cma_connect_ib(struct rdma_id_private *id_priv,
			  struct rdma_conn_param *conn_param)
{
@@ -1860,7 +2025,7 @@ static int cma_connect_ib(struct rdma_id_private *id_priv,
	req.service_id = cma_get_service_id(id_priv->id.ps,
					    &route->addr.dst_addr);
	req.qp_num = id_priv->qp_num;
	req.qp_type = id_priv->qp_type;
	req.qp_type = IB_QPT_RC;
	req.starting_psn = id_priv->seq_num;
	req.responder_resources = conn_param->responder_resources;
	req.initiator_depth = conn_param->initiator_depth;
@@ -1937,12 +2102,14 @@ int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)

	if (!id->qp) {
		id_priv->qp_num = conn_param->qp_num;
		id_priv->qp_type = conn_param->qp_type;
		id_priv->srq = conn_param->srq;
	}

	switch (rdma_node_get_transport(id->device->node_type)) {
	case RDMA_TRANSPORT_IB:
		if (id->ps == RDMA_PS_UDP)
			ret = cma_resolve_ib_udp(id_priv, conn_param);
		else
			ret = cma_connect_ib(id_priv, conn_param);
		break;
	case RDMA_TRANSPORT_IWARP:
@@ -1966,11 +2133,25 @@ static int cma_accept_ib(struct rdma_id_private *id_priv,
			 struct rdma_conn_param *conn_param)
{
	struct ib_cm_rep_param rep;
	int ret;
	struct ib_qp_attr qp_attr;
	int qp_attr_mask, ret;

	if (id_priv->id.qp) {
		ret = cma_modify_qp_rtr(&id_priv->id);
		if (ret)
		return ret;
			goto out;

		qp_attr.qp_state = IB_QPS_RTS;
		ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, &qp_attr,
					 &qp_attr_mask);
		if (ret)
			goto out;

		qp_attr.max_rd_atomic = conn_param->initiator_depth;
		ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
		if (ret)
			goto out;
	}

	memset(&rep, 0, sizeof rep);
	rep.qp_num = id_priv->qp_num;
@@ -1985,7 +2166,9 @@ static int cma_accept_ib(struct rdma_id_private *id_priv,
	rep.rnr_retry_count = conn_param->rnr_retry_count;
	rep.srq = id_priv->srq ? 1 : 0;

	return ib_send_cm_rep(id_priv->cm_id.ib, &rep);
	ret = ib_send_cm_rep(id_priv->cm_id.ib, &rep);
out:
	return ret;
}

static int cma_accept_iw(struct rdma_id_private *id_priv,
@@ -2010,6 +2193,24 @@ static int cma_accept_iw(struct rdma_id_private *id_priv,
	return iw_cm_accept(id_priv->cm_id.iw, &iw_param);
}

static int cma_send_sidr_rep(struct rdma_id_private *id_priv,
			     enum ib_cm_sidr_status status,
			     const void *private_data, int private_data_len)
{
	struct ib_cm_sidr_rep_param rep;

	memset(&rep, 0, sizeof rep);
	rep.status = status;
	if (status == IB_SIDR_SUCCESS) {
		rep.qp_num = id_priv->qp_num;
		rep.qkey = RDMA_UD_QKEY;
	}
	rep.private_data = private_data;
	rep.private_data_len = private_data_len;

	return ib_send_cm_sidr_rep(id_priv->cm_id.ib, &rep);
}

int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
{
	struct rdma_id_private *id_priv;
@@ -2021,13 +2222,16 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)

	if (!id->qp && conn_param) {
		id_priv->qp_num = conn_param->qp_num;
		id_priv->qp_type = conn_param->qp_type;
		id_priv->srq = conn_param->srq;
	}

	switch (rdma_node_get_transport(id->device->node_type)) {
	case RDMA_TRANSPORT_IB:
		if (conn_param)
		if (id->ps == RDMA_PS_UDP)
			ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
						conn_param->private_data,
						conn_param->private_data_len);
		else if (conn_param)
			ret = cma_accept_ib(id_priv, conn_param);
		else
			ret = cma_rep_recv(id_priv);
@@ -2051,6 +2255,27 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
}
EXPORT_SYMBOL(rdma_accept);

int rdma_notify(struct rdma_cm_id *id, enum ib_event_type event)
{
	struct rdma_id_private *id_priv;
	int ret;

	id_priv = container_of(id, struct rdma_id_private, id);
	if (!cma_comp(id_priv, CMA_CONNECT))
		return -EINVAL;

	switch (id->device->node_type) {
	case RDMA_NODE_IB_CA:
		ret = ib_cm_notify(id_priv->cm_id.ib, event);
		break;
	default:
		ret = 0;
		break;
	}
	return ret;
}
EXPORT_SYMBOL(rdma_notify);

int rdma_reject(struct rdma_cm_id *id, const void *private_data,
		u8 private_data_len)
{
@@ -2063,9 +2288,13 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data,

	switch (rdma_node_get_transport(id->device->node_type)) {
	case RDMA_TRANSPORT_IB:
		ret = ib_send_cm_rej(id_priv->cm_id.ib,
				     IB_CM_REJ_CONSUMER_DEFINED, NULL, 0,
		if (id->ps == RDMA_PS_UDP)
			ret = cma_send_sidr_rep(id_priv, IB_SIDR_REJECT,
						private_data, private_data_len);
		else
			ret = ib_send_cm_rej(id_priv->cm_id.ib,
					     IB_CM_REJ_CONSUMER_DEFINED, NULL,
					     0, private_data, private_data_len);
		break;
	case RDMA_TRANSPORT_IWARP:
		ret = iw_cm_reject(id_priv->cm_id.iw,
@@ -2136,6 +2365,7 @@ static void cma_add_one(struct ib_device *device)

static int cma_remove_id_dev(struct rdma_id_private *id_priv)
{
	struct rdma_cm_event event;
	enum cma_state state;

	/* Record that we want to remove the device */
@@ -2150,8 +2380,9 @@ static int cma_remove_id_dev(struct rdma_id_private *id_priv)
	if (!cma_comp(id_priv, CMA_DEVICE_REMOVAL))
		return 0;

	return cma_notify_user(id_priv, RDMA_CM_EVENT_DEVICE_REMOVAL,
			       0, NULL, 0);
	memset(&event, 0, sizeof event);
	event.event = RDMA_CM_EVENT_DEVICE_REMOVAL;
	return id_priv->id.event_handler(&id_priv->id, &event);
}

static void cma_process_remove(struct cma_device *cma_dev)
@@ -2233,6 +2464,7 @@ static void cma_cleanup(void)
	destroy_workqueue(cma_wq);
	idr_destroy(&sdp_ps);
	idr_destroy(&tcp_ps);
	idr_destroy(&udp_ps);
}

module_init(cma_init);
+2 −10
Original line number Diff line number Diff line
@@ -394,20 +394,12 @@ EXPORT_SYMBOL(ib_destroy_fmr_pool);
 */
int ib_flush_fmr_pool(struct ib_fmr_pool *pool)
{
	int serial;

	atomic_inc(&pool->req_ser);
	/*
	 * It's OK if someone else bumps req_ser again here -- we'll
	 * just wait a little longer.
	 */
	serial = atomic_read(&pool->req_ser);
	int serial = atomic_inc_return(&pool->req_ser);

	wake_up_process(pool->thread);

	if (wait_event_interruptible(pool->force_wait,
				     atomic_read(&pool->flush_ser) -
				     atomic_read(&pool->req_ser) >= 0))
				     atomic_read(&pool->flush_ser) - serial >= 0))
		return -EINTR;

	return 0;
+44 −46
Original line number Diff line number Diff line
@@ -998,17 +998,17 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)

	mad_agent = mad_send_wr->send_buf.mad_agent;
	sge = mad_send_wr->sg_list;
	sge[0].addr = dma_map_single(mad_agent->device->dma_device,
	sge[0].addr = ib_dma_map_single(mad_agent->device,
					mad_send_wr->send_buf.mad,
					sge[0].length,
					DMA_TO_DEVICE);
	pci_unmap_addr_set(mad_send_wr, header_mapping, sge[0].addr);
	mad_send_wr->header_mapping = sge[0].addr;

	sge[1].addr = dma_map_single(mad_agent->device->dma_device,
	sge[1].addr = ib_dma_map_single(mad_agent->device,
					ib_get_payload(mad_send_wr),
					sge[1].length,
					DMA_TO_DEVICE);
	pci_unmap_addr_set(mad_send_wr, payload_mapping, sge[1].addr);
	mad_send_wr->payload_mapping = sge[1].addr;

	spin_lock_irqsave(&qp_info->send_queue.lock, flags);
	if (qp_info->send_queue.count < qp_info->send_queue.max_active) {
@@ -1026,11 +1026,11 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
	}
	spin_unlock_irqrestore(&qp_info->send_queue.lock, flags);
	if (ret) {
		dma_unmap_single(mad_agent->device->dma_device,
				 pci_unmap_addr(mad_send_wr, header_mapping),
		ib_dma_unmap_single(mad_agent->device,
				    mad_send_wr->header_mapping,
				    sge[0].length, DMA_TO_DEVICE);
		dma_unmap_single(mad_agent->device->dma_device,
				 pci_unmap_addr(mad_send_wr, payload_mapping),
		ib_dma_unmap_single(mad_agent->device,
				    mad_send_wr->payload_mapping,
				    sge[1].length, DMA_TO_DEVICE);
	}
	return ret;
@@ -1850,8 +1850,8 @@ static void ib_mad_recv_done_handler(struct ib_mad_port_private *port_priv,
	mad_priv_hdr = container_of(mad_list, struct ib_mad_private_header,
				    mad_list);
	recv = container_of(mad_priv_hdr, struct ib_mad_private, header);
	dma_unmap_single(port_priv->device->dma_device,
			 pci_unmap_addr(&recv->header, mapping),
	ib_dma_unmap_single(port_priv->device,
			    recv->header.mapping,
			    sizeof(struct ib_mad_private) -
			      sizeof(struct ib_mad_private_header),
			    DMA_FROM_DEVICE);
@@ -2080,11 +2080,11 @@ static void ib_mad_send_done_handler(struct ib_mad_port_private *port_priv,
	qp_info = send_queue->qp_info;

retry:
	dma_unmap_single(mad_send_wr->send_buf.mad_agent->device->dma_device,
			 pci_unmap_addr(mad_send_wr, header_mapping),
	ib_dma_unmap_single(mad_send_wr->send_buf.mad_agent->device,
			    mad_send_wr->header_mapping,
			    mad_send_wr->sg_list[0].length, DMA_TO_DEVICE);
	dma_unmap_single(mad_send_wr->send_buf.mad_agent->device->dma_device,
			 pci_unmap_addr(mad_send_wr, payload_mapping),
	ib_dma_unmap_single(mad_send_wr->send_buf.mad_agent->device,
			    mad_send_wr->payload_mapping,
			    mad_send_wr->sg_list[1].length, DMA_TO_DEVICE);
	queued_send_wr = NULL;
	spin_lock_irqsave(&send_queue->lock, flags);
@@ -2528,13 +2528,12 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info,
				break;
			}
		}
		sg_list.addr = dma_map_single(qp_info->port_priv->
					        device->dma_device,
		sg_list.addr = ib_dma_map_single(qp_info->port_priv->device,
						 &mad_priv->grh,
						 sizeof *mad_priv -
						   sizeof mad_priv->header,
						 DMA_FROM_DEVICE);
		pci_unmap_addr_set(&mad_priv->header, mapping, sg_list.addr);
		mad_priv->header.mapping = sg_list.addr;
		recv_wr.wr_id = (unsigned long)&mad_priv->header.mad_list;
		mad_priv->header.mad_list.mad_queue = recv_queue;

@@ -2549,9 +2548,8 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info,
			list_del(&mad_priv->header.mad_list.list);
			recv_queue->count--;
			spin_unlock_irqrestore(&recv_queue->lock, flags);
			dma_unmap_single(qp_info->port_priv->device->dma_device,
					 pci_unmap_addr(&mad_priv->header,
							mapping),
			ib_dma_unmap_single(qp_info->port_priv->device,
					    mad_priv->header.mapping,
					    sizeof *mad_priv -
					      sizeof mad_priv->header,
					    DMA_FROM_DEVICE);
@@ -2586,8 +2584,8 @@ static void cleanup_recv_queue(struct ib_mad_qp_info *qp_info)
		/* Remove from posted receive MAD list */
		list_del(&mad_list->list);

		dma_unmap_single(qp_info->port_priv->device->dma_device,
				 pci_unmap_addr(&recv->header, mapping),
		ib_dma_unmap_single(qp_info->port_priv->device,
				    recv->header.mapping,
				    sizeof(struct ib_mad_private) -
				      sizeof(struct ib_mad_private_header),
				    DMA_FROM_DEVICE);
Loading