Commit 37356e78 authored by Kaike Wan's avatar Kaike Wan Committed by Doug Ledford
Browse files

IB/hfi1: TID RDMA flow allocation



The hfi1 hardware flow is a hardware flow-control mechanism for a KDETH
data packet that is received on a hfi1 port. It validates the packet by
checking both the generation and sequence. Each QP that uses the TID RDMA
mechanism will allocate a hardware flow from its receiving context for
any incoming KDETH data packets.

This patch implements:
(1) a function to allocate hardware flow
(2) a function to free hardware flow
(3) a function to initialize hardware flow generation for a receiving
    context
(4) a wait mechanism if the hardware flow is not available
(4) a function to remove the qp from the wait queue for hardware flow
    when the qp is reset or destroyed.

Signed-off-by: default avatarMitko Haralanov <mitko.haralanov@intel.com>
Signed-off-by: default avatarAshutosh Dixit <ashutosh.dixit@intel.com>
Signed-off-by: default avatarMike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: default avatarKaike Wan <kaike.wan@intel.com>
Signed-off-by: default avatarDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 385156c5
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -340,6 +340,10 @@ struct diag_pkt {

#define HFI1_PSM_IOC_BASE_SEQ 0x0

/* Number of BTH.PSN bits used for sequence number in expected rcvs */
#define HFI1_KDETH_BTH_SEQ_SHIFT 11
#define HFI1_KDETH_BTH_SEQ_MASK (BIT(HFI1_KDETH_BTH_SEQ_SHIFT) - 1)

static inline __u64 rhf_to_cpu(const __le32 *rbuf)
{
	return __le64_to_cpu(*((__le64 *)rbuf));
+15 −0
Original line number Diff line number Diff line
@@ -198,6 +198,14 @@ struct exp_tid_set {
};

typedef int (*rhf_rcv_function_ptr)(struct hfi1_packet *packet);

struct tid_queue {
	struct list_head queue_head;
			/* queue head for QP TID resource waiters */
	u32 enqueue;	/* count of tid enqueues */
	u32 dequeue;	/* count of tid dequeues */
};

struct hfi1_ctxtdata {
	/* rcvhdrq base, needs mmap before useful */
	void *rcvhdrq;
@@ -291,6 +299,10 @@ struct hfi1_ctxtdata {
	/* PSM Specific fields */
	/* lock protecting all Expected TID data */
	struct mutex exp_mutex;
	/* lock protecting all Expected TID data of kernel contexts */
	spinlock_t exp_lock;
	/* Queue for QP's waiting for HW TID flows */
	struct tid_queue flow_queue;
	/* when waiting for rcv or pioavail */
	wait_queue_head_t wait;
	/* uuid from PSM */
@@ -323,6 +335,9 @@ struct hfi1_ctxtdata {
	 */
	u8 subctxt_cnt;

	/* Bit mask to track free TID RDMA HW flows */
	unsigned long flow_mask;
	struct tid_flow_state flows[RXE_NUM_TID_FLOWS];
};

/**
+7 −0
Original line number Diff line number Diff line
@@ -370,6 +370,8 @@ int hfi1_create_ctxtdata(struct hfi1_pportdata *ppd, int numa,
		rcd->rhf_rcv_function_map = normal_rhf_rcv_functions;

		mutex_init(&rcd->exp_mutex);
		spin_lock_init(&rcd->exp_lock);
		INIT_LIST_HEAD(&rcd->flow_queue.queue_head);

		hfi1_cdbg(PROC, "setting up context %u\n", rcd->ctxt);

@@ -472,6 +474,9 @@ int hfi1_create_ctxtdata(struct hfi1_pportdata *ppd, int numa,
						    GFP_KERNEL, numa);
			if (!rcd->opstats)
				goto bail;

			/* Initialize TID flow generations for the context */
			hfi1_kern_init_ctxt_generations(rcd);
		}

		*context = rcd;
@@ -771,6 +776,8 @@ static void enable_chip(struct hfi1_devdata *dd)
			rcvmask |= HFI1_RCVCTRL_NO_RHQ_DROP_ENB;
		if (HFI1_CAP_KGET_MASK(rcd->flags, NODROP_EGR_FULL))
			rcvmask |= HFI1_RCVCTRL_NO_EGR_DROP_ENB;
		if (HFI1_CAP_IS_KSET(TID_RDMA))
			rcvmask |= HFI1_RCVCTRL_TIDFLOW_ENB;
		hfi1_rcvctrl(dd, rcvmask, rcd);
		sc_enable(rcd->sc);
		hfi1_rcd_put(rcd);
+3 −0
Original line number Diff line number Diff line
@@ -738,6 +738,7 @@ void flush_qp_waiters(struct rvt_qp *qp)
{
	lockdep_assert_held(&qp->s_lock);
	flush_iowait(qp);
	hfi1_tid_rdma_flush_wait(qp);
}

void stop_send_queue(struct rvt_qp *qp)
@@ -745,6 +746,8 @@ void stop_send_queue(struct rvt_qp *qp)
	struct hfi1_qp_priv *priv = qp->priv;

	iowait_cancel_work(&priv->s_iowait);
	if (cancel_work_sync(&priv->tid_rdma.trigger_work))
		rvt_put_qp(qp);
}

void quiesce_qp(struct rvt_qp *qp)
+2 −0
Original line number Diff line number Diff line
@@ -63,11 +63,13 @@ extern const struct rvt_operation_params hfi1_post_parms[];
 * HFI1_S_AHG_VALID - ahg header valid on chip
 * HFI1_S_AHG_CLEAR - have send engine clear ahg state
 * HFI1_S_WAIT_PIO_DRAIN - qp waiting for PIOs to drain
 * HFI1_S_WAIT_TID_SPACE - a QP is waiting for TID resource
 * HFI1_S_MIN_BIT_MASK - the lowest bit that can be used by hfi1
 */
#define HFI1_S_AHG_VALID         0x80000000
#define HFI1_S_AHG_CLEAR         0x40000000
#define HFI1_S_WAIT_PIO_DRAIN    0x20000000
#define HFI1_S_WAIT_TID_SPACE    0x10000000
#define HFI1_S_MIN_BIT_MASK      0x01000000

/*
Loading