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

Commit dae81683 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: Discard double CQE for one WR
  IB/ehca: Check idr_find() return value
  IB/ehca: Repoll CQ on invalid opcode
  IB/ehca: Rename goto label in ehca_poll_cq_one()
  IB/ehca: Update qp_state on cached modify_qp()
  IPoIB/cm: Use vmalloc() to allocate rx_rings
parents ddc752a4 3a3eae0d
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -156,6 +156,14 @@ struct ehca_mod_qp_parm {

#define EHCA_MOD_QP_PARM_MAX 4

#define QMAP_IDX_MASK 0xFFFFULL

/* struct for tracking if cqes have been reported to the application */
struct ehca_qmap_entry {
	u16 app_wr_id;
	u16 reported;
};

struct ehca_qp {
	union {
		struct ib_qp ib_qp;
@@ -165,6 +173,7 @@ struct ehca_qp {
	enum ehca_ext_qp_type ext_type;
	enum ib_qp_state state;
	struct ipz_queue ipz_squeue;
	struct ehca_qmap_entry *sq_map;
	struct ipz_queue ipz_rqueue;
	struct h_galpas galpas;
	u32 qkey;
+1 −0
Original line number Diff line number Diff line
@@ -213,6 +213,7 @@ struct ehca_wqe {
#define WC_STATUS_ERROR_BIT 0x80000000
#define WC_STATUS_REMOTE_ERROR_FLAGS 0x0000F800
#define WC_STATUS_PURGE_BIT 0x10
#define WC_SEND_RECEIVE_BIT 0x80

struct ehca_cqe {
	u64 work_request_id;
+35 −13
Original line number Diff line number Diff line
@@ -412,6 +412,7 @@ static struct ehca_qp *internal_create_qp(
	struct ehca_shca *shca = container_of(pd->device, struct ehca_shca,
					      ib_device);
	struct ib_ucontext *context = NULL;
	u32 nr_qes;
	u64 h_ret;
	int is_llqp = 0, has_srq = 0;
	int qp_type, max_send_sge, max_recv_sge, ret;
@@ -715,6 +716,15 @@ static struct ehca_qp *internal_create_qp(
				 "and pages ret=%i", ret);
			goto create_qp_exit2;
		}
		nr_qes = my_qp->ipz_squeue.queue_length /
			 my_qp->ipz_squeue.qe_size;
		my_qp->sq_map = vmalloc(nr_qes *
					sizeof(struct ehca_qmap_entry));
		if (!my_qp->sq_map) {
			ehca_err(pd->device, "Couldn't allocate squeue "
				 "map ret=%i", ret);
			goto create_qp_exit3;
		}
	}

	if (HAS_RQ(my_qp)) {
@@ -724,7 +734,7 @@ static struct ehca_qp *internal_create_qp(
		if (ret) {
			ehca_err(pd->device, "Couldn't initialize rqueue "
				 "and pages ret=%i", ret);
			goto create_qp_exit3;
			goto create_qp_exit4;
		}
	}

@@ -770,7 +780,7 @@ static struct ehca_qp *internal_create_qp(
			if (!my_qp->mod_qp_parm) {
				ehca_err(pd->device,
					 "Could not alloc mod_qp_parm");
				goto create_qp_exit4;
				goto create_qp_exit5;
			}
		}
	}
@@ -780,7 +790,7 @@ static struct ehca_qp *internal_create_qp(
		h_ret = ehca_define_sqp(shca, my_qp, init_attr);
		if (h_ret != H_SUCCESS) {
			ret = ehca2ib_return_code(h_ret);
			goto create_qp_exit5;
			goto create_qp_exit6;
		}
	}

@@ -789,7 +799,7 @@ static struct ehca_qp *internal_create_qp(
		if (ret) {
			ehca_err(pd->device,
				 "Couldn't assign qp to send_cq ret=%i", ret);
			goto create_qp_exit5;
			goto create_qp_exit6;
		}
	}

@@ -815,22 +825,26 @@ static struct ehca_qp *internal_create_qp(
		if (ib_copy_to_udata(udata, &resp, sizeof resp)) {
			ehca_err(pd->device, "Copy to udata failed");
			ret = -EINVAL;
			goto create_qp_exit6;
			goto create_qp_exit7;
		}
	}

	return my_qp;

create_qp_exit6:
create_qp_exit7:
	ehca_cq_unassign_qp(my_qp->send_cq, my_qp->real_qp_num);

create_qp_exit5:
create_qp_exit6:
	kfree(my_qp->mod_qp_parm);

create_qp_exit4:
create_qp_exit5:
	if (HAS_RQ(my_qp))
		ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);

create_qp_exit4:
	if (HAS_SQ(my_qp))
		vfree(my_qp->sq_map);

create_qp_exit3:
	if (HAS_SQ(my_qp))
		ipz_queue_dtor(my_pd, &my_qp->ipz_squeue);
@@ -1534,8 +1548,6 @@ static int internal_modify_qp(struct ib_qp *ibqp,
	if (attr_mask & IB_QP_QKEY)
		my_qp->qkey = attr->qkey;

	my_qp->state = qp_new_state;

modify_qp_exit2:
	if (squeue_locked) { /* this means: sqe -> rts */
		spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
@@ -1551,6 +1563,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
		   struct ib_udata *udata)
{
	int ret = 0;

	struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca,
					      ib_device);
	struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
@@ -1597,12 +1611,18 @@ int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
				 attr->qp_state, my_qp->init_attr.port_num,
				 ibqp->qp_type);
			spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
			return 0;
			goto out;
		}
		spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
	}

	return internal_modify_qp(ibqp, attr, attr_mask, 0);
	ret = internal_modify_qp(ibqp, attr, attr_mask, 0);

out:
	if ((ret == 0) && (attr_mask & IB_QP_STATE))
		my_qp->state = attr->qp_state;

	return ret;
}

void ehca_recover_sqp(struct ib_qp *sqp)
@@ -1973,8 +1993,10 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,

	if (HAS_RQ(my_qp))
		ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
	if (HAS_SQ(my_qp))
	if (HAS_SQ(my_qp)) {
		ipz_queue_dtor(my_pd, &my_qp->ipz_squeue);
		vfree(my_qp->sq_map);
	}
	kmem_cache_free(qp_cache, my_qp);
	atomic_dec(&shca->num_qps);
	return 0;
+47 −13
Original line number Diff line number Diff line
@@ -139,6 +139,7 @@ static void trace_send_wr_ud(const struct ib_send_wr *send_wr)
static inline int ehca_write_swqe(struct ehca_qp *qp,
				  struct ehca_wqe *wqe_p,
				  const struct ib_send_wr *send_wr,
				  u32 sq_map_idx,
				  int hidden)
{
	u32 idx;
@@ -157,7 +158,11 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
	/* clear wqe header until sglist */
	memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list));

	wqe_p->work_request_id = send_wr->wr_id;
	wqe_p->work_request_id = send_wr->wr_id & ~QMAP_IDX_MASK;
	wqe_p->work_request_id |= sq_map_idx & QMAP_IDX_MASK;

	qp->sq_map[sq_map_idx].app_wr_id = send_wr->wr_id & QMAP_IDX_MASK;
	qp->sq_map[sq_map_idx].reported = 0;

	switch (send_wr->opcode) {
	case IB_WR_SEND:
@@ -381,6 +386,7 @@ static inline int post_one_send(struct ehca_qp *my_qp,
{
	struct ehca_wqe *wqe_p;
	int ret;
	u32 sq_map_idx;
	u64 start_offset = my_qp->ipz_squeue.current_q_offset;

	/* get pointer next to free WQE */
@@ -393,8 +399,15 @@ static inline int post_one_send(struct ehca_qp *my_qp,
			 "qp_num=%x", my_qp->ib_qp.qp_num);
		return -ENOMEM;
	}

	/*
	 * Get the index of the WQE in the send queue. The same index is used
	 * for writing into the sq_map.
	 */
	sq_map_idx = start_offset / my_qp->ipz_squeue.qe_size;

	/* write a SEND WQE into the QUEUE */
	ret = ehca_write_swqe(my_qp, wqe_p, cur_send_wr, hidden);
	ret = ehca_write_swqe(my_qp, wqe_p, cur_send_wr, sq_map_idx, hidden);
	/*
	 * if something failed,
	 * reset the free entry pointer to the start value
@@ -589,7 +602,7 @@ static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc)
	struct ehca_qp *my_qp;
	int cqe_count = 0, is_error;

poll_cq_one_read_cqe:
repoll:
	cqe = (struct ehca_cqe *)
		ipz_qeit_get_inc_valid(&my_cq->ipz_queue);
	if (!cqe) {
@@ -617,7 +630,7 @@ static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc)
			ehca_dmp(cqe, 64, "cq_num=%x qp_num=%x",
				 my_cq->cq_number, cqe->local_qp_number);
			/* ignore this purged cqe */
			goto poll_cq_one_read_cqe;
			goto repoll;
		}
		spin_lock_irqsave(&qp->spinlock_s, flags);
		purgeflag = qp->sqerr_purgeflag;
@@ -636,7 +649,7 @@ static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc)
			 * that caused sqe and turn off purge flag
			 */
			qp->sqerr_purgeflag = 0;
			goto poll_cq_one_read_cqe;
			goto repoll;
		}
	}

@@ -654,7 +667,33 @@ static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc)
			 my_cq, my_cq->cq_number);
	}

	/* we got a completion! */
	read_lock(&ehca_qp_idr_lock);
	my_qp = idr_find(&ehca_qp_idr, cqe->qp_token);
	read_unlock(&ehca_qp_idr_lock);
	if (!my_qp)
		goto repoll;
	wc->qp = &my_qp->ib_qp;

	if (!(cqe->w_completion_flags & WC_SEND_RECEIVE_BIT)) {
		struct ehca_qmap_entry *qmap_entry;
		/*
		 * We got a send completion and need to restore the original
		 * wr_id.
		 */
		qmap_entry = &my_qp->sq_map[cqe->work_request_id &
					    QMAP_IDX_MASK];

		if (qmap_entry->reported) {
			ehca_warn(cq->device, "Double cqe on qp_num=%#x",
				  my_qp->real_qp_num);
			/* found a double cqe, discard it and read next one */
			goto repoll;
		}
		wc->wr_id = cqe->work_request_id & ~QMAP_IDX_MASK;
		wc->wr_id |= qmap_entry->app_wr_id;
		qmap_entry->reported = 1;
	} else
		/* We got a receive completion. */
		wc->wr_id = cqe->work_request_id;

	/* eval ib_wc_opcode */
@@ -667,7 +706,7 @@ static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc)
		ehca_dmp(cqe, 64, "ehca_cq=%p cq_num=%x",
			 my_cq, my_cq->cq_number);
		/* update also queue adder to throw away this entry!!! */
		goto poll_cq_one_exit0;
		goto repoll;
	}

	/* eval ib_wc_status */
@@ -678,11 +717,6 @@ static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc)
	} else
		wc->status = IB_WC_SUCCESS;

	read_lock(&ehca_qp_idr_lock);
	my_qp = idr_find(&ehca_qp_idr, cqe->qp_token);
	wc->qp = &my_qp->ib_qp;
	read_unlock(&ehca_qp_idr_lock);

	wc->byte_len = cqe->nr_bytes_transferred;
	wc->pkey_index = cqe->pkey_index;
	wc->slid = cqe->rlid;
+12 −5
Original line number Diff line number Diff line
@@ -202,7 +202,7 @@ static void ipoib_cm_free_rx_ring(struct net_device *dev,
			dev_kfree_skb_any(rx_ring[i].skb);
		}

	kfree(rx_ring);
	vfree(rx_ring);
}

static void ipoib_cm_start_rx_drain(struct ipoib_dev_priv *priv)
@@ -352,9 +352,14 @@ static int ipoib_cm_nonsrq_init_rx(struct net_device *dev, struct ib_cm_id *cm_i
	int ret;
	int i;

	rx->rx_ring = kcalloc(ipoib_recvq_size, sizeof *rx->rx_ring, GFP_KERNEL);
	if (!rx->rx_ring)
	rx->rx_ring = vmalloc(ipoib_recvq_size * sizeof *rx->rx_ring);
	if (!rx->rx_ring) {
		printk(KERN_WARNING "%s: failed to allocate CM non-SRQ ring (%d entries)\n",
		       priv->ca->name, ipoib_recvq_size);
		return -ENOMEM;
	}

	memset(rx->rx_ring, 0, ipoib_recvq_size * sizeof *rx->rx_ring);

	t = kmalloc(sizeof *t, GFP_KERNEL);
	if (!t) {
@@ -1494,14 +1499,16 @@ static void ipoib_cm_create_srq(struct net_device *dev, int max_sge)
		return;
	}

	priv->cm.srq_ring = kzalloc(ipoib_recvq_size * sizeof *priv->cm.srq_ring,
				    GFP_KERNEL);
	priv->cm.srq_ring = vmalloc(ipoib_recvq_size * sizeof *priv->cm.srq_ring);
	if (!priv->cm.srq_ring) {
		printk(KERN_WARNING "%s: failed to allocate CM SRQ ring (%d entries)\n",
		       priv->ca->name, ipoib_recvq_size);
		ib_destroy_srq(priv->cm.srq);
		priv->cm.srq = NULL;
		return;
	}

	memset(priv->cm.srq_ring, 0, ipoib_recvq_size * sizeof *priv->cm.srq_ring);
}

int ipoib_cm_dev_init(struct net_device *dev)