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

Commit 829d464e authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
  IB/ehca: Tweak trace message format
  IB/ehca: Fix device registration
  IB/ipath: Fix RDMA reads
  RDMA/cma: Optimize error handling
  RDMA/cma: Eliminate unnecessary remove_list
  RDMA/cma: Set status correctly on route resolution error
  RDMA/cma: Fix device removal race
  RDMA/cma: Fix leak of cm_ids in case of failures
parents b65d04a7 e5a01069
Loading
Loading
Loading
Loading
+28 −19
Original line number Diff line number Diff line
@@ -874,23 +874,25 @@ static struct rdma_id_private *cma_new_id(struct rdma_cm_id *listen_id,
	__u16 port;
	u8 ip_ver;

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

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

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

	rt = &id->route;
	rt->num_paths = ib_event->param.req_rcvd.alternate_path ? 2 : 1;
	rt->path_rec = kmalloc(sizeof *rt->path_rec * rt->num_paths, GFP_KERNEL);
	rt->path_rec = kmalloc(sizeof *rt->path_rec * rt->num_paths,
			       GFP_KERNEL);
	if (!rt->path_rec)
		goto err;

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

	cma_save_net_info(&id->route.addr, &listen_id->route.addr,
			  ip_ver, port, src, dst);
	rt->path_rec[0] = *ib_event->param.req_rcvd.primary_path;
	if (rt->num_paths == 2)
		rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path;
@@ -903,8 +905,10 @@ static struct rdma_id_private *cma_new_id(struct rdma_cm_id *listen_id,
	id_priv = container_of(id, struct rdma_id_private, id);
	id_priv->state = CMA_CONNECT;
	return id_priv;
err:

destroy_id:
	rdma_destroy_id(id);
err:
	return NULL;
}

@@ -932,6 +936,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
	mutex_unlock(&lock);
	if (ret) {
		ret = -ENODEV;
		cma_exch(conn_id, CMA_DESTROYING);
		cma_release_remove(conn_id);
		rdma_destroy_id(&conn_id->id);
		goto out;
@@ -1307,6 +1312,7 @@ static void cma_query_handler(int status, struct ib_sa_path_rec *path_rec,
		work->old_state = CMA_ROUTE_QUERY;
		work->new_state = CMA_ADDR_RESOLVED;
		work->event.event = RDMA_CM_EVENT_ROUTE_ERROR;
		work->event.status = status;
	}

	queue_work(cma_wq, &work->work);
@@ -1862,6 +1868,11 @@ static int cma_connect_ib(struct rdma_id_private *id_priv,

	ret = ib_send_cm_req(id_priv->cm_id.ib, &req);
out:
	if (ret && !IS_ERR(id_priv->cm_id.ib)) {
		ib_destroy_cm_id(id_priv->cm_id.ib);
		id_priv->cm_id.ib = NULL;
	}

	kfree(private_data);
	return ret;
}
@@ -1889,10 +1900,8 @@ static int cma_connect_iw(struct rdma_id_private *id_priv,
	cm_id->remote_addr = *sin;

	ret = cma_modify_qp_rtr(&id_priv->id);
	if (ret) {
		iw_destroy_cm_id(cm_id);
		return ret;
	}
	if (ret)
		goto out;

	iw_param.ord = conn_param->initiator_depth;
	iw_param.ird = conn_param->responder_resources;
@@ -1904,6 +1913,10 @@ static int cma_connect_iw(struct rdma_id_private *id_priv,
		iw_param.qpn = conn_param->qp_num;
	ret = iw_cm_connect(cm_id, &iw_param);
out:
	if (ret && !IS_ERR(cm_id)) {
		iw_destroy_cm_id(cm_id);
		id_priv->cm_id.iw = NULL;
	}
	return ret;
}

@@ -2142,12 +2155,9 @@ static int cma_remove_id_dev(struct rdma_id_private *id_priv)

static void cma_process_remove(struct cma_device *cma_dev)
{
	struct list_head remove_list;
	struct rdma_id_private *id_priv;
	int ret;

	INIT_LIST_HEAD(&remove_list);

	mutex_lock(&lock);
	while (!list_empty(&cma_dev->id_list)) {
		id_priv = list_entry(cma_dev->id_list.next,
@@ -2158,8 +2168,7 @@ static void cma_process_remove(struct cma_device *cma_dev)
			continue;
		}

		list_del(&id_priv->list);
		list_add_tail(&id_priv->list, &remove_list);
		list_del_init(&id_priv->list);
		atomic_inc(&id_priv->refcount);
		mutex_unlock(&lock);

+19 −17
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
MODULE_VERSION("SVNEHCA_0016");
MODULE_VERSION("SVNEHCA_0017");

int ehca_open_aqp1     = 0;
int ehca_debug_level   = 0;
@@ -239,7 +239,7 @@ static int init_node_guid(struct ehca_shca *shca)
	return ret;
}

int ehca_register_device(struct ehca_shca *shca)
int ehca_init_device(struct ehca_shca *shca)
{
	int ret;

@@ -317,11 +317,6 @@ int ehca_register_device(struct ehca_shca *shca)
	/* shca->ib_device.process_mad	    = ehca_process_mad;	    */
	shca->ib_device.mmap		    = ehca_mmap;

	ret = ib_register_device(&shca->ib_device);
	if (ret)
		ehca_err(&shca->ib_device,
			 "ib_register_device() failed ret=%x", ret);

	return ret;
}

@@ -561,9 +556,9 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
		goto probe1;
	}

	ret = ehca_register_device(shca);
	ret = ehca_init_device(shca);
	if (ret) {
		ehca_gen_err("Cannot register Infiniband device");
		ehca_gen_err("Cannot init ehca  device struct");
		goto probe1;
	}

@@ -571,7 +566,7 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
	ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, 2048);
	if (ret) {
		ehca_err(&shca->ib_device, "Cannot create EQ.");
		goto probe2;
		goto probe1;
	}

	ret = ehca_create_eq(shca, &shca->neq, EHCA_NEQ, 513);
@@ -600,6 +595,13 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
		goto probe5;
	}

	ret = ib_register_device(&shca->ib_device);
	if (ret) {
		ehca_err(&shca->ib_device,
			 "ib_register_device() failed ret=%x", ret);
		goto probe6;
	}

	/* create AQP1 for port 1 */
	if (ehca_open_aqp1 == 1) {
		shca->sport[0].port_state = IB_PORT_DOWN;
@@ -607,7 +609,7 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
		if (ret) {
			ehca_err(&shca->ib_device,
				 "Cannot create AQP1 for port 1.");
			goto probe6;
			goto probe7;
		}
	}

@@ -618,7 +620,7 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
		if (ret) {
			ehca_err(&shca->ib_device,
				 "Cannot create AQP1 for port 2.");
			goto probe7;
			goto probe8;
		}
	}

@@ -630,12 +632,15 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,

	return 0;

probe7:
probe8:
	ret = ehca_destroy_aqp1(&shca->sport[0]);
	if (ret)
		ehca_err(&shca->ib_device,
			 "Cannot destroy AQP1 for port 1. ret=%x", ret);

probe7:
	ib_unregister_device(&shca->ib_device);

probe6:
	ret = ehca_dereg_internal_maxmr(shca);
	if (ret)
@@ -660,9 +665,6 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
		ehca_err(&shca->ib_device,
			 "Cannot destroy EQ. ret=%x", ret);

probe2:
	ib_unregister_device(&shca->ib_device);

probe1:
	ib_dealloc_device(&shca->ib_device);

@@ -750,7 +752,7 @@ int __init ehca_module_init(void)
	int ret;

	printk(KERN_INFO "eHCA Infiniband Device Driver "
	                 "(Rel.: SVNEHCA_0016)\n");
	                 "(Rel.: SVNEHCA_0017)\n");
	idr_init(&ehca_qp_idr);
	idr_init(&ehca_cq_idr);
	spin_lock_init(&ehca_qp_idr_lock);
+32 −27
Original line number Diff line number Diff line
@@ -241,10 +241,7 @@ int ipath_make_rc_req(struct ipath_qp *qp,
		 * original work request since we may need to resend
		 * it.
		 */
		qp->s_sge.sge = wqe->sg_list[0];
		qp->s_sge.sg_list = wqe->sg_list + 1;
		qp->s_sge.num_sge = wqe->wr.num_sge;
		qp->s_len = len = wqe->length;
		len = wqe->length;
		ss = &qp->s_sge;
		bth2 = 0;
		switch (wqe->wr.opcode) {
@@ -368,14 +365,23 @@ int ipath_make_rc_req(struct ipath_qp *qp,
		default:
			goto done;
		}
		qp->s_sge.sge = wqe->sg_list[0];
		qp->s_sge.sg_list = wqe->sg_list + 1;
		qp->s_sge.num_sge = wqe->wr.num_sge;
		qp->s_len = wqe->length;
		if (newreq) {
			qp->s_tail++;
			if (qp->s_tail >= qp->s_size)
				qp->s_tail = 0;
		}
		bth2 |= qp->s_psn++ & IPATH_PSN_MASK;
		bth2 |= qp->s_psn & IPATH_PSN_MASK;
		if (wqe->wr.opcode == IB_WR_RDMA_READ)
			qp->s_psn = wqe->lpsn + 1;
		else {
			qp->s_psn++;
			if ((int)(qp->s_psn - qp->s_next_psn) > 0)
				qp->s_next_psn = qp->s_psn;
		}
		/*
		 * Put the QP on the pending list so lost ACKs will cause
		 * a retry.  More than one request can be pending so the
@@ -690,13 +696,6 @@ void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc)
	struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last);
	struct ipath_ibdev *dev;

	/*
	 * If there are no requests pending, we are done.
	 */
	if (ipath_cmp24(psn, qp->s_next_psn) >= 0 ||
	    qp->s_last == qp->s_tail)
		goto done;

	if (qp->s_retry == 0) {
		wc->wr_id = wqe->wr.wr_id;
		wc->status = IB_WC_RETRY_EXC_ERR;
@@ -731,8 +730,6 @@ void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc)
		dev->n_rc_resends += (int)qp->s_psn - (int)psn;

	reset_psn(qp, psn);

done:
	tasklet_hi_schedule(&qp->s_task);

bail:
@@ -765,6 +762,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
	struct ib_wc wc;
	struct ipath_swqe *wqe;
	int ret = 0;
	u32 ack_psn;

	/*
	 * Remove the QP from the timeout queue (or RNR timeout queue).
@@ -777,26 +775,26 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
		list_del_init(&qp->timerwait);
	spin_unlock(&dev->pending_lock);

	/* Nothing is pending to ACK/NAK. */
	if (unlikely(qp->s_last == qp->s_tail))
		goto bail;

	/*
	 * Note that NAKs implicitly ACK outstanding SEND and RDMA write
	 * requests and implicitly NAK RDMA read and atomic requests issued
	 * before the NAK'ed request.  The MSN won't include the NAK'ed
	 * request but will include an ACK'ed request(s).
	 */
	ack_psn = psn;
	if (aeth >> 29)
		ack_psn--;
	wqe = get_swqe_ptr(qp, qp->s_last);

	/* Nothing is pending to ACK/NAK. */
	if (qp->s_last == qp->s_tail)
		goto bail;

	/*
	 * The MSN might be for a later WQE than the PSN indicates so
	 * only complete WQEs that the PSN finishes.
	 */
	while (ipath_cmp24(psn, wqe->lpsn) >= 0) {
		/* If we are ACKing a WQE, the MSN should be >= the SSN. */
		if (ipath_cmp24(aeth, wqe->ssn) < 0)
			break;
	while (ipath_cmp24(ack_psn, wqe->lpsn) >= 0) {
		/*
		 * If this request is a RDMA read or atomic, and the ACK is
		 * for a later operation, this ACK NAKs the RDMA read or
@@ -807,7 +805,8 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
		 * is sent but before the response is received.
		 */
		if ((wqe->wr.opcode == IB_WR_RDMA_READ &&
		     opcode != OP(RDMA_READ_RESPONSE_LAST)) ||
		     (opcode != OP(RDMA_READ_RESPONSE_LAST) ||
		       ipath_cmp24(ack_psn, wqe->lpsn) != 0)) ||
		    ((wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
		      wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) &&
		     (opcode != OP(ATOMIC_ACKNOWLEDGE) ||
@@ -825,6 +824,10 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
			 */
			goto bail;
		}
		if (wqe->wr.opcode == IB_WR_RDMA_READ ||
		    wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
		    wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD)
			tasklet_hi_schedule(&qp->s_task);
		/* Post a send completion queue entry if requested. */
		if (!test_bit(IPATH_S_SIGNAL_REQ_WR, &qp->s_flags) ||
		    (wqe->wr.send_flags & IB_SEND_SIGNALED)) {
@@ -1055,6 +1058,7 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
		/* no AETH, no ACK */
		if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) {
			dev->n_rdma_seq++;
			if (qp->s_last != qp->s_tail)
				ipath_restart_rc(qp, qp->s_last_psn + 1, &wc);
			goto ack_done;
		}
@@ -1091,6 +1095,7 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
		/* ACKs READ req. */
		if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) {
			dev->n_rdma_seq++;
			if (qp->s_last != qp->s_tail)
				ipath_restart_rc(qp, qp->s_last_psn + 1, &wc);
			goto ack_done;
		}
+1 −1

File changed.

Contains only whitespace changes.