|
@@ -1,7 +1,7 @@
|
|
|
#ifndef _HFI1_IOWAIT_H
|
|
|
#define _HFI1_IOWAIT_H
|
|
|
/*
|
|
|
- * Copyright(c) 2015, 2016 Intel Corporation.
|
|
|
+ * Copyright(c) 2015 - 2018 Intel Corporation.
|
|
|
*
|
|
|
* This file is provided under a dual BSD/GPLv2 license. When using or
|
|
|
* redistributing this file, you may do so under either license.
|
|
@@ -49,6 +49,7 @@
|
|
|
|
|
|
#include <linux/list.h>
|
|
|
#include <linux/workqueue.h>
|
|
|
+#include <linux/wait.h>
|
|
|
#include <linux/sched.h>
|
|
|
|
|
|
#include "sdma_txreq.h"
|
|
@@ -59,16 +60,47 @@
|
|
|
*/
|
|
|
typedef void (*restart_t)(struct work_struct *work);
|
|
|
|
|
|
+#define IOWAIT_PENDING_IB 0x0
|
|
|
+#define IOWAIT_PENDING_TID 0x1
|
|
|
+
|
|
|
+/*
|
|
|
+ * A QP can have multiple Send Engines (SEs).
|
|
|
+ *
|
|
|
+ * The current use case is for supporting a TID RDMA
|
|
|
+ * packet build/xmit mechanism independent from verbs.
|
|
|
+ */
|
|
|
+#define IOWAIT_SES 2
|
|
|
+#define IOWAIT_IB_SE 0
|
|
|
+#define IOWAIT_TID_SE 1
|
|
|
+
|
|
|
struct sdma_txreq;
|
|
|
struct sdma_engine;
|
|
|
/**
|
|
|
- * struct iowait - linkage for delayed progress/waiting
|
|
|
+ * @iowork: the work struct
|
|
|
+ * @tx_head: list of prebuilt packets
|
|
|
+ * @iow: the parent iowait structure
|
|
|
+ *
|
|
|
+ * This structure is the work item (process) specific
|
|
|
+ * details associated with the each of the two SEs of the
|
|
|
+ * QP.
|
|
|
+ *
|
|
|
+ * The workstruct and the queued TXs are unique to each
|
|
|
+ * SE.
|
|
|
+ */
|
|
|
+struct iowait;
|
|
|
+struct iowait_work {
|
|
|
+ struct work_struct iowork;
|
|
|
+ struct list_head tx_head;
|
|
|
+ struct iowait *iow;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
* @list: used to add/insert into QP/PQ wait lists
|
|
|
- * @lock: uses to record the list head lock
|
|
|
* @tx_head: overflow list of sdma_txreq's
|
|
|
* @sleep: no space callback
|
|
|
* @wakeup: space callback wakeup
|
|
|
* @sdma_drained: sdma count drained
|
|
|
+ * @lock: lock protected head of wait queue
|
|
|
* @iowork: workqueue overhead
|
|
|
* @wait_dma: wait for sdma_busy == 0
|
|
|
* @wait_pio: wait for pio_busy == 0
|
|
@@ -76,6 +108,8 @@ struct sdma_engine;
|
|
|
* @count: total number of descriptors in tx_head'ed list
|
|
|
* @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
|
|
|
*
|
|
|
* This is to be embedded in user's state structure
|
|
|
* (QP or PQ).
|
|
@@ -98,13 +132,11 @@ struct sdma_engine;
|
|
|
* Waiters explicity know that, but the destroy
|
|
|
* code that unwaits QPs does not.
|
|
|
*/
|
|
|
-
|
|
|
struct iowait {
|
|
|
struct list_head list;
|
|
|
- struct list_head tx_head;
|
|
|
int (*sleep)(
|
|
|
struct sdma_engine *sde,
|
|
|
- struct iowait *wait,
|
|
|
+ struct iowait_work *wait,
|
|
|
struct sdma_txreq *tx,
|
|
|
uint seq,
|
|
|
bool pkts_sent
|
|
@@ -112,7 +144,6 @@ struct iowait {
|
|
|
void (*wakeup)(struct iowait *wait, int reason);
|
|
|
void (*sdma_drained)(struct iowait *wait);
|
|
|
seqlock_t *lock;
|
|
|
- struct work_struct iowork;
|
|
|
wait_queue_head_t wait_dma;
|
|
|
wait_queue_head_t wait_pio;
|
|
|
atomic_t sdma_busy;
|
|
@@ -121,63 +152,37 @@ struct iowait {
|
|
|
u32 tx_limit;
|
|
|
u32 tx_count;
|
|
|
u8 starved_cnt;
|
|
|
+ unsigned long flags;
|
|
|
+ struct iowait_work wait[IOWAIT_SES];
|
|
|
};
|
|
|
|
|
|
#define SDMA_AVAIL_REASON 0
|
|
|
|
|
|
-/**
|
|
|
- * iowait_init() - initialize wait structure
|
|
|
- * @wait: wait struct to initialize
|
|
|
- * @tx_limit: limit for overflow queuing
|
|
|
- * @func: restart function for workqueue
|
|
|
- * @sleep: sleep function for no space
|
|
|
- * @resume: wakeup function for no space
|
|
|
- *
|
|
|
- * This function initializes the iowait
|
|
|
- * structure embedded in the QP or PQ.
|
|
|
- *
|
|
|
- */
|
|
|
+void iowait_set_flag(struct iowait *wait, u32 flag);
|
|
|
+bool iowait_flag_set(struct iowait *wait, u32 flag);
|
|
|
+void iowait_clear_flag(struct iowait *wait, u32 flag);
|
|
|
|
|
|
-static inline void iowait_init(
|
|
|
- struct iowait *wait,
|
|
|
- u32 tx_limit,
|
|
|
- void (*func)(struct work_struct *work),
|
|
|
- int (*sleep)(
|
|
|
- struct sdma_engine *sde,
|
|
|
- struct iowait *wait,
|
|
|
- struct sdma_txreq *tx,
|
|
|
- uint seq,
|
|
|
- bool pkts_sent),
|
|
|
- void (*wakeup)(struct iowait *wait, int reason),
|
|
|
- void (*sdma_drained)(struct iowait *wait))
|
|
|
-{
|
|
|
- wait->count = 0;
|
|
|
- wait->lock = NULL;
|
|
|
- INIT_LIST_HEAD(&wait->list);
|
|
|
- INIT_LIST_HEAD(&wait->tx_head);
|
|
|
- INIT_WORK(&wait->iowork, func);
|
|
|
- init_waitqueue_head(&wait->wait_dma);
|
|
|
- init_waitqueue_head(&wait->wait_pio);
|
|
|
- atomic_set(&wait->sdma_busy, 0);
|
|
|
- atomic_set(&wait->pio_busy, 0);
|
|
|
- wait->tx_limit = tx_limit;
|
|
|
- wait->sleep = sleep;
|
|
|
- wait->wakeup = wakeup;
|
|
|
- wait->sdma_drained = sdma_drained;
|
|
|
-}
|
|
|
+void iowait_init(struct iowait *wait, u32 tx_limit,
|
|
|
+ void (*func)(struct work_struct *work),
|
|
|
+ void (*tidfunc)(struct work_struct *work),
|
|
|
+ int (*sleep)(struct sdma_engine *sde,
|
|
|
+ struct iowait_work *wait,
|
|
|
+ struct sdma_txreq *tx,
|
|
|
+ uint seq,
|
|
|
+ bool pkts_sent),
|
|
|
+ void (*wakeup)(struct iowait *wait, int reason),
|
|
|
+ void (*sdma_drained)(struct iowait *wait));
|
|
|
|
|
|
/**
|
|
|
- * iowait_schedule() - initialize wait structure
|
|
|
+ * iowait_schedule() - schedule the default send engine work
|
|
|
* @wait: wait struct to schedule
|
|
|
* @wq: workqueue for schedule
|
|
|
* @cpu: cpu
|
|
|
*/
|
|
|
-static inline void iowait_schedule(
|
|
|
- struct iowait *wait,
|
|
|
- struct workqueue_struct *wq,
|
|
|
- int cpu)
|
|
|
+static inline bool iowait_schedule(struct iowait *wait,
|
|
|
+ struct workqueue_struct *wq, int cpu)
|
|
|
{
|
|
|
- queue_work_on(cpu, wq, &wait->iowork);
|
|
|
+ return !!queue_work_on(cpu, wq, &wait->wait[IOWAIT_IB_SE].iowork);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -228,6 +233,8 @@ static inline void iowait_sdma_add(struct iowait *wait, int count)
|
|
|
*/
|
|
|
static inline int iowait_sdma_dec(struct iowait *wait)
|
|
|
{
|
|
|
+ if (!wait)
|
|
|
+ return 0;
|
|
|
return atomic_dec_and_test(&wait->sdma_busy);
|
|
|
}
|
|
|
|
|
@@ -267,11 +274,13 @@ static inline void iowait_pio_inc(struct iowait *wait)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * iowait_sdma_dec - note pio complete
|
|
|
+ * iowait_pio_dec - note pio complete
|
|
|
* @wait: iowait structure
|
|
|
*/
|
|
|
static inline int iowait_pio_dec(struct iowait *wait)
|
|
|
{
|
|
|
+ if (!wait)
|
|
|
+ return 0;
|
|
|
return atomic_dec_and_test(&wait->pio_busy);
|
|
|
}
|
|
|
|
|
@@ -293,9 +302,9 @@ static inline void iowait_drain_wakeup(struct iowait *wait)
|
|
|
/**
|
|
|
* iowait_get_txhead() - get packet off of iowait list
|
|
|
*
|
|
|
- * @wait wait struture
|
|
|
+ * @wait iowait_work struture
|
|
|
*/
|
|
|
-static inline struct sdma_txreq *iowait_get_txhead(struct iowait *wait)
|
|
|
+static inline struct sdma_txreq *iowait_get_txhead(struct iowait_work *wait)
|
|
|
{
|
|
|
struct sdma_txreq *tx = NULL;
|
|
|
|
|
@@ -309,6 +318,28 @@ static inline struct sdma_txreq *iowait_get_txhead(struct iowait *wait)
|
|
|
return tx;
|
|
|
}
|
|
|
|
|
|
+static inline u16 iowait_get_desc(struct iowait_work *w)
|
|
|
+{
|
|
|
+ u16 num_desc = 0;
|
|
|
+ struct sdma_txreq *tx = NULL;
|
|
|
+
|
|
|
+ if (!list_empty(&w->tx_head)) {
|
|
|
+ tx = list_first_entry(&w->tx_head, struct sdma_txreq,
|
|
|
+ list);
|
|
|
+ num_desc = tx->num_desc;
|
|
|
+ }
|
|
|
+ return num_desc;
|
|
|
+}
|
|
|
+
|
|
|
+static inline u32 iowait_get_all_desc(struct iowait *w)
|
|
|
+{
|
|
|
+ u32 num_desc = 0;
|
|
|
+
|
|
|
+ num_desc = iowait_get_desc(&w->wait[IOWAIT_IB_SE]);
|
|
|
+ num_desc += iowait_get_desc(&w->wait[IOWAIT_TID_SE]);
|
|
|
+ return num_desc;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* iowait_queue - Put the iowait on a wait queue
|
|
|
* @pkts_sent: have some packets been sent before queuing?
|
|
@@ -372,12 +403,57 @@ static inline void iowait_starve_find_max(struct iowait *w, u8 *max,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * iowait_packet_queued() - determine if a packet is already built
|
|
|
- * @wait: the wait structure
|
|
|
+ * iowait_packet_queued() - determine if a packet is queued
|
|
|
+ * @wait: the iowait_work structure
|
|
|
*/
|
|
|
-static inline bool iowait_packet_queued(struct iowait *wait)
|
|
|
+static inline bool iowait_packet_queued(struct iowait_work *wait)
|
|
|
{
|
|
|
return !list_empty(&wait->tx_head);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * inc_wait_count - increment wait counts
|
|
|
+ * @w: the log work struct
|
|
|
+ * @n: the count
|
|
|
+ */
|
|
|
+static inline void iowait_inc_wait_count(struct iowait_work *w, u16 n)
|
|
|
+{
|
|
|
+ if (!w)
|
|
|
+ return;
|
|
|
+ w->iow->tx_count++;
|
|
|
+ w->iow->count += n;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * iowait_get_tid_work - return iowait_work for tid SE
|
|
|
+ * @w: the iowait struct
|
|
|
+ */
|
|
|
+static inline struct iowait_work *iowait_get_tid_work(struct iowait *w)
|
|
|
+{
|
|
|
+ return &w->wait[IOWAIT_TID_SE];
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * iowait_get_ib_work - return iowait_work for ib SE
|
|
|
+ * @w: the iowait struct
|
|
|
+ */
|
|
|
+static inline struct iowait_work *iowait_get_ib_work(struct iowait *w)
|
|
|
+{
|
|
|
+ return &w->wait[IOWAIT_IB_SE];
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * iowait_ioww_to_iow - return iowait given iowait_work
|
|
|
+ * @w: the iowait_work struct
|
|
|
+ */
|
|
|
+static inline struct iowait *iowait_ioww_to_iow(struct iowait_work *w)
|
|
|
+{
|
|
|
+ if (likely(w))
|
|
|
+ return w->iow;
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+void iowait_cancel_work(struct iowait *w);
|
|
|
+int iowait_set_work_flag(struct iowait_work *w);
|
|
|
+
|
|
|
#endif
|