Commit 885c5807 authored by Doug Ledford's avatar Doug Ledford
Browse files

Merge branch 'tid-write' into hfi1-tid

Here is the final set of patches for TID RDMA. Again this is code which
was previously submitted but re-organized so as to be easier to review.

Similar to how the READ series was organized the patches to build,
receive, allocate resources etc are broken out. For details on TID RDMA
as a whole again refer to the original cover letter.

https://www.spinics.net/lists/linux-rdma/msg66611.html



* tid-write: (23 commits)
  IB/hfi1: Prioritize the sending of ACK packets
  IB/hfi1: Add static trace for TID RDMA WRITE protocol
  IB/hfi1: Enable TID RDMA WRITE protocol
  IB/hfi1: Add interlock between TID RDMA WRITE and other requests
  IB/hfi1: Add TID RDMA WRITE functionality into RDMA verbs
  IB/hfi1: Add the dual leg code
  IB/hfi1: Add the TID second leg ACK packet builder
  IB/hfi1: Add the TID second leg send packet builder
  IB/hfi1: Resend the TID RDMA WRITE DATA packets
  IB/hfi1: Add a function to receive TID RDMA RESYNC packet
  IB/hfi1: Add a function to build TID RDMA RESYNC packet
  IB/hfi1: Add TID RDMA retry timer
  IB/hfi1: Add a function to receive TID RDMA ACK packet
  IB/hfi1: Add a function to build TID RDMA ACK packet
  IB/hfi1: Add a function to receive TID RDMA WRITE DATA packet
  IB/hfi1: Add a function to build TID RDMA WRITE DATA packet
  IB/hfi1: Add a function to receive TID RDMA WRITE response
  IB/hfi1: Add TID resource timer
  IB/hfi1: Add a function to build TID RDMA WRITE response
  IB/hfi1: Add functions to receive TID RDMA WRITE request
  ...

Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parents a2f3bde8 34025fb0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1512,6 +1512,7 @@ static int __init hfi1_mod_init(void)
		goto bail_dev;
	}

	hfi1_compute_tid_rdma_flow_wt();
	/*
	 * These must be called before the driver is registered with
	 * the PCI subsystem.
+33 −1
Original line number Diff line number Diff line
@@ -6,6 +6,9 @@
#include "iowait.h"
#include "trace_iowait.h"

/* 1 priority == 16 starve_cnt */
#define IOWAIT_PRIORITY_STARVE_SHIFT 4

void iowait_set_flag(struct iowait *wait, u32 flag)
{
	trace_hfi1_iowait_set(wait, flag);
@@ -44,7 +47,8 @@ void iowait_init(struct iowait *wait, u32 tx_limit,
			      uint seq,
			      bool pkts_sent),
		 void (*wakeup)(struct iowait *wait, int reason),
		 void (*sdma_drained)(struct iowait *wait))
		 void (*sdma_drained)(struct iowait *wait),
		 void (*init_priority)(struct iowait *wait))
{
	int i;

@@ -58,6 +62,7 @@ void iowait_init(struct iowait *wait, u32 tx_limit,
	wait->sleep = sleep;
	wait->wakeup = wakeup;
	wait->sdma_drained = sdma_drained;
	wait->init_priority = init_priority;
	wait->flags = 0;
	for (i = 0; i < IOWAIT_SES; i++) {
		wait->wait[i].iow = wait;
@@ -92,3 +97,30 @@ int iowait_set_work_flag(struct iowait_work *w)
	iowait_set_flag(w->iow, IOWAIT_PENDING_TID);
	return IOWAIT_TID_SE;
}

/**
 * iowait_priority_update_top - update the top priority entry
 * @w: the iowait struct
 * @top: a pointer to the top priority entry
 * @idx: the index of the current iowait in an array
 * @top_idx: the array index for the iowait entry that has the top priority
 *
 * This function is called to compare the priority of a given
 * iowait with the given top priority entry. The top index will
 * be returned.
 */
uint iowait_priority_update_top(struct iowait *w,
				struct iowait *top,
				uint idx, uint top_idx)
{
	u8 cnt, tcnt;

	/* Convert priority into starve_cnt and compare the total.*/
	cnt = (w->priority << IOWAIT_PRIORITY_STARVE_SHIFT) + w->starved_cnt;
	tcnt = (top->priority << IOWAIT_PRIORITY_STARVE_SHIFT) +
		top->starved_cnt;
	if (cnt > tcnt)
		return idx;
	else
		return top_idx;
}
+69 −30
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ struct iowait_work {
 * @sleep: no space callback
 * @wakeup: space callback wakeup
 * @sdma_drained: sdma count drained
 * @init_priority: callback to manipulate priority
 * @lock: lock protected head of wait queue
 * @iowork: workqueue overhead
 * @wait_dma: wait for sdma_busy == 0
@@ -109,7 +110,7 @@ struct iowait_work {
 * @tx_limit: limit for overflow queuing
 * @tx_count: number of tx entry's in tx_head'ed list
 * @flags: wait flags (one per QP)
 * @wait: SE array
 * @wait: SE array for multiple legs
 *
 * This is to be embedded in user's state structure
 * (QP or PQ).
@@ -120,10 +121,13 @@ struct iowait_work {
 * are callbacks for the ULP to implement
 * what ever queuing/dequeuing of
 * the embedded iowait and its containing struct
 * when a resource shortage like SDMA ring space is seen.
 * when a resource shortage like SDMA ring space
 * or PIO credit space is seen.
 *
 * Both potentially have locks help
 * so sleeping is not allowed.
 * so sleeping is not allowed and it is not
 * supported to submit txreqs from the wakeup
 * call directly because of lock conflicts.
 *
 * The wait_dma member along with the iow
 *
@@ -143,6 +147,7 @@ struct iowait {
		);
	void (*wakeup)(struct iowait *wait, int reason);
	void (*sdma_drained)(struct iowait *wait);
	void (*init_priority)(struct iowait *wait);
	seqlock_t *lock;
	wait_queue_head_t wait_dma;
	wait_queue_head_t wait_pio;
@@ -152,6 +157,7 @@ struct iowait {
	u32 tx_limit;
	u32 tx_count;
	u8 starved_cnt;
	u8 priority;
	unsigned long flags;
	struct iowait_work wait[IOWAIT_SES];
};
@@ -171,7 +177,8 @@ void iowait_init(struct iowait *wait, u32 tx_limit,
			      uint seq,
			      bool pkts_sent),
		 void (*wakeup)(struct iowait *wait, int reason),
		 void (*sdma_drained)(struct iowait *wait));
		 void (*sdma_drained)(struct iowait *wait),
		 void (*init_priority)(struct iowait *wait));

/**
 * iowait_schedule() - schedule the default send engine work
@@ -185,6 +192,18 @@ static inline bool iowait_schedule(struct iowait *wait,
	return !!queue_work_on(cpu, wq, &wait->wait[IOWAIT_IB_SE].iowork);
}

/**
 * iowait_tid_schedule - schedule the tid SE
 * @wait: the iowait structure
 * @wq: the work queue
 * @cpu: the cpu
 */
static inline bool iowait_tid_schedule(struct iowait *wait,
				       struct workqueue_struct *wq, int cpu)
{
	return !!queue_work_on(cpu, wq, &wait->wait[IOWAIT_TID_SE].iowork);
}

/**
 * iowait_sdma_drain() - wait for DMAs to drain
 *
@@ -327,6 +346,8 @@ static inline u16 iowait_get_desc(struct iowait_work *w)
		tx = list_first_entry(&w->tx_head, struct sdma_txreq,
				      list);
		num_desc = tx->num_desc;
		if (tx->flags & SDMA_TXREQ_F_VIP)
			w->iow->priority++;
	}
	return num_desc;
}
@@ -340,6 +361,37 @@ static inline u32 iowait_get_all_desc(struct iowait *w)
	return num_desc;
}

static inline void iowait_update_priority(struct iowait_work *w)
{
	struct sdma_txreq *tx = NULL;

	if (!list_empty(&w->tx_head)) {
		tx = list_first_entry(&w->tx_head, struct sdma_txreq,
				      list);
		if (tx->flags & SDMA_TXREQ_F_VIP)
			w->iow->priority++;
	}
}

static inline void iowait_update_all_priority(struct iowait *w)
{
	iowait_update_priority(&w->wait[IOWAIT_IB_SE]);
	iowait_update_priority(&w->wait[IOWAIT_TID_SE]);
}

static inline void iowait_init_priority(struct iowait *w)
{
	w->priority = 0;
	if (w->init_priority)
		w->init_priority(w);
}

static inline void iowait_get_priority(struct iowait *w)
{
	iowait_init_priority(w);
	iowait_update_all_priority(w);
}

/**
 * iowait_queue - Put the iowait on a wait queue
 * @pkts_sent: have some packets been sent before queuing?
@@ -356,14 +408,18 @@ static inline void iowait_queue(bool pkts_sent, struct iowait *w,
	/*
	 * To play fair, insert the iowait at the tail of the wait queue if it
	 * has already sent some packets; Otherwise, put it at the head.
	 * However, if it has priority packets to send, also put it at the
	 * head.
	 */
	if (pkts_sent) {
		list_add_tail(&w->list, wait_head);
	if (pkts_sent)
		w->starved_cnt = 0;
	} else {
		list_add(&w->list, wait_head);
	else
		w->starved_cnt++;
	}

	if (w->priority > 0 || !pkts_sent)
		list_add(&w->list, wait_head);
	else
		list_add_tail(&w->list, wait_head);
}

/**
@@ -380,27 +436,10 @@ static inline void iowait_starve_clear(bool pkts_sent, struct iowait *w)
		w->starved_cnt = 0;
}

/**
 * iowait_starve_find_max - Find the maximum of the starve count
 * @w: the iowait struct
 * @max: a variable containing the max starve count
 * @idx: the index of the current iowait in an array
 * @max_idx: a variable containing the array index for the
 *         iowait entry that has the max starve count
 *
 * This function is called to compare the starve count of a
 * given iowait with the given max starve count. The max starve
 * count and the index will be updated if the iowait's start
 * count is larger.
 */
static inline void iowait_starve_find_max(struct iowait *w, u8 *max,
					  uint idx, uint *max_idx)
{
	if (w->starved_cnt > *max) {
		*max = w->starved_cnt;
		*max_idx = idx;
	}
}
/* Update the top priority index */
uint iowait_priority_update_top(struct iowait *w,
				struct iowait *top,
				uint idx, uint top_idx);

/**
 * iowait_packet_queued() - determine if a packet is queued
+5 −0
Original line number Diff line number Diff line
@@ -245,10 +245,15 @@ void opfn_qp_init(struct rvt_qp *qp, struct ib_qp_attr *attr, int attr_mask)
	struct hfi1_qp_priv *priv = qp->priv;
	unsigned long flags;

	if (attr_mask & IB_QP_RETRY_CNT)
		priv->s_retry = attr->retry_cnt;

	spin_lock_irqsave(&priv->opfn.lock, flags);
	if (ibqp->qp_type == IB_QPT_RC && HFI1_CAP_IS_KSET(TID_RDMA)) {
		struct tid_rdma_params *local = &priv->tid_rdma.local;

		if (attr_mask & IB_QP_TIMEOUT)
			priv->tid_retry_timeout_jiffies = qp->timeout_jiffies;
		if (qp->pmtu == enum_to_mtu(OPA_MTU_4096) ||
		    qp->pmtu == enum_to_mtu(OPA_MTU_8192)) {
			tid_rdma_opfn_init(qp, local);
+12 −6
Original line number Diff line number Diff line
@@ -1599,8 +1599,7 @@ static void sc_piobufavail(struct send_context *sc)
	struct rvt_qp *qp;
	struct hfi1_qp_priv *priv;
	unsigned long flags;
	uint i, n = 0, max_idx = 0;
	u8 max_starved_cnt = 0;
	uint i, n = 0, top_idx = 0;

	if (dd->send_contexts[sc->sw_index].type != SC_KERNEL &&
	    dd->send_contexts[sc->sw_index].type != SC_VL15)
@@ -1619,11 +1618,18 @@ static void sc_piobufavail(struct send_context *sc)
		if (n == ARRAY_SIZE(qps))
			break;
		wait = list_first_entry(list, struct iowait, list);
		iowait_get_priority(wait);
		qp = iowait_to_qp(wait);
		priv = qp->priv;
		list_del_init(&priv->s_iowait.list);
		priv->s_iowait.lock = NULL;
		iowait_starve_find_max(wait, &max_starved_cnt, n, &max_idx);
		if (n) {
			priv = qps[top_idx]->priv;
			top_idx = iowait_priority_update_top(wait,
							     &priv->s_iowait,
							     n, top_idx);
		}

		/* refcount held until actual wake up */
		qps[n++] = qp;
	}
@@ -1638,12 +1644,12 @@ static void sc_piobufavail(struct send_context *sc)
	}
	write_sequnlock_irqrestore(&sc->waitlock, flags);

	/* Wake up the most starved one first */
	/* Wake up the top-priority one first */
	if (n)
		hfi1_qp_wakeup(qps[max_idx],
		hfi1_qp_wakeup(qps[top_idx],
			       RVT_S_WAIT_PIO | HFI1_S_WAIT_PIO_DRAIN);
	for (i = 0; i < n; i++)
		if (i != max_idx)
		if (i != top_idx)
			hfi1_qp_wakeup(qps[i],
				       RVT_S_WAIT_PIO | HFI1_S_WAIT_PIO_DRAIN);
}
Loading