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

Commit 92898522 authored by Michael S. Tsirkin's avatar Michael S. Tsirkin Committed by Roland Dreier
Browse files

IB/mthca: prevent event queue overrun



I am seeing EQ overruns in SDP stress tests: if the CQ completion
handler arms a CQ, this could generate more EQEs, so that EQ will
never get empty and consumer index will never get updated.

This is similiar to what we have with command interface:
		/*
		 * cmd_event() may add more commands.
		 * The card will think the queue has overflowed if
		 * we don't tell it we've been processing events.
		 */
However, for completion events, we *don't* want to update the consumer
index on each event. So, perform EQ doorbell coalescing: allocate EQs
with some spare EQEs, and update once we run out of them.

The value 0x80 was selected to avoid any performance impact.

Signed-off-by: default avatarMichael S. Tsirkin <mst@mellanox.co.il>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 6627fa66
Loading
Loading
Loading
Loading
+15 −13
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@
enum {
	MTHCA_NUM_ASYNC_EQE = 0x80,
	MTHCA_NUM_CMD_EQE   = 0x80,
	MTHCA_NUM_SPARE_EQE = 0x80,
	MTHCA_EQ_ENTRY_SIZE = 0x20
};

@@ -278,10 +279,9 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
	struct mthca_eqe *eqe;
	int disarm_cqn;
	int eqes_found = 0;

	while ((eqe = next_eqe_sw(eq))) {
	int set_ci = 0;

	while ((eqe = next_eqe_sw(eq))) {
		/*
		 * Make sure we read EQ entry contents after we've
		 * checked the ownership bit.
@@ -345,12 +345,6 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
					be16_to_cpu(eqe->event.cmd.token),
					eqe->event.cmd.status,
					be64_to_cpu(eqe->event.cmd.out_param));
			/*
			 * cmd_event() may add more commands.
			 * The card will think the queue has overflowed if
			 * we don't tell it we've been processing events.
			 */
			set_ci = 1;
			break;

		case MTHCA_EVENT_TYPE_PORT_CHANGE:
@@ -385,8 +379,16 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
		set_eqe_hw(eqe);
		++eq->cons_index;
		eqes_found = 1;
		++set_ci;

		if (unlikely(set_ci)) {
		/*
		 * The HCA will think the queue has overflowed if we
		 * don't tell it we've been processing events.  We
		 * create our EQs with MTHCA_NUM_SPARE_EQE extra
		 * entries, so we must update our consumer index at
		 * least that often.
		 */
		if (unlikely(set_ci >= MTHCA_NUM_SPARE_EQE)) {
			/*
			 * Conditional on hca_type is OK here because
			 * this is a rare case, not the fast path.
@@ -862,19 +864,19 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev)
	intr = (dev->mthca_flags & MTHCA_FLAG_MSI) ?
		128 : dev->eq_table.inta_pin;

	err = mthca_create_eq(dev, dev->limits.num_cqs,
	err = mthca_create_eq(dev, dev->limits.num_cqs + MTHCA_NUM_SPARE_EQE,
			      (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr,
			      &dev->eq_table.eq[MTHCA_EQ_COMP]);
	if (err)
		goto err_out_unmap;

	err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE,
	err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE + MTHCA_NUM_SPARE_EQE,
			      (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 129 : intr,
			      &dev->eq_table.eq[MTHCA_EQ_ASYNC]);
	if (err)
		goto err_out_comp;

	err = mthca_create_eq(dev, MTHCA_NUM_CMD_EQE,
	err = mthca_create_eq(dev, MTHCA_NUM_CMD_EQE + MTHCA_NUM_SPARE_EQE,
			      (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 130 : intr,
			      &dev->eq_table.eq[MTHCA_EQ_CMD]);
	if (err)